feat(templates,schemas): render audience, derive the journal word count from Zola - #178
Merged
Merged
Conversation
…nt from Zola Two fixes that unblock a consumer, plus a design correction that removed a third. DERIVED WORD COUNT. schemas/journal-entry.schema.json no longer REQUIRES extra.words / extra.words_source; journal-entry.html and journal-section.html render Zola's own page.word_count instead. An explicit extra.words still wins as an override, and words_source is required only alongside it. The count was a hand-written claim that drifted: measured against a consumer's 8 essays, three were off by 13-20 percent -- one claiming ~1050 words for 1263, one ~1150 for 944, one ~1120 for 1264. Written once, never updated as the essays were edited. A derived count cannot drift. What page.word_count actually counts, verified against real builds with isolated per-variable fixtures rather than assumed: headings, emphasis inner text, inline code span content, link visible text AND the link URL, image alt text AND the image src path. Fenced code block content is excluded entirely. Worth stating, because a reader of the number deserves to know what it measures. RENDERED AUDIENCE. extra.audience is now rendered in the entry header beside components, and stays required. Its schema rationale said it was 'required so rendered deliverables carry audience assumptions explicitly' -- and nothing rendered it. No template in this repo, no consumer template, no script; outside the schemas it appeared only in fixtures that existed to satisfy the requirement. A requirement justified by an effect that does not happen is the defect; the operator chose to make the claim true rather than drop the field. WHAT WAS DROPPED, and why it is worth recording. This branch first added an extra-cascade so a section could set audience once for its pages. Zola has no such mechanism -- a bare [cascade] table is a hard 'unknown field' error at 0.22.1, and never existed through 0.23.3. The cascade was therefore validator-only: it satisfied typikon-validate and told the renderer nothing, so a page relying on it passed validation and then failed zola build against the render-time assert. Rendering audience moots it entirely, since a rendered value must reach Zola and so must live in the page's own frontmatter. The two asserts removed while chasing that are restored, and are correct again.
forkwright
force-pushed
the
fix/derived-word-count-and-cascaded-extra
branch
from
August 17, 2026 20:48
cfb97ef to
f194f0f
Compare
forkwright
pushed a commit
that referenced
this pull request
Aug 18, 2026
🤖 I have created a release *beep* *boop* --- ## [0.5.0](v0.4.2...v0.5.0) (2026-08-17) ### Features * **templates,css,ci:** expose a real consumer design API, split Leather's skin out of core ([#175](#175)) ([b61228c](b61228c)) * **templates,schemas:** render audience, derive the journal word count from Zola ([#178](#178)) ([af66fa0](af66fa0)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: forkwright <cody@forkwright.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two fixes that unblock a consumer, plus a design correction that removed a third. The PR pivoted mid-flight; this body describes what it is, not what it was.
1. The journal word count is derived, not declared
schemas/journal-entry.schema.jsonno longer requiresextra.words/extra.words_source.journal-entry.htmlandjournal-section.htmlrender Zola's ownpage.word_count. An explicitextra.wordsstill wins as an override, andwords_sourceis required only alongside it (thedependentRequiredpatternproduct.schema.jsonalready uses foravailability).Why: the count was a hand-written claim that drifts. Measured against a consumer's 8 essays, three were materially wrong —
~1050for 1263 words,~1150for 944,~1120for 1264. Written once, never updated as the essays were edited. A derived count cannot drift.What
page.word_countactually counts — verified against real builds with isolated per-variable fixtures, not assumed:srcpathWorth stating in the docs, because a reader of the rendered number deserves to know what it measures — particularly on essays containing code fences.
Demonstrated:
second-entry(noextra.words) renders93 words; appending a 23-word sentence renders133— hand-checked exact delta.first-entrykeeps its~120 wordsoverride.2.
audienceis rendered, so requiring it is honestextra.audiencenow renders in the entry header besidecomponents, and stays required.Its schema rationale claimed it was "required so rendered deliverables carry audience assumptions explicitly." Nothing rendered it — no template in this repo, no consumer template, no script. Outside the schema definitions it appeared only in test fixtures that existed to satisfy the requirement. A requirement justified by an effect that does not occur is the defect; the choice was to make the claim true rather than drop the field.
3. What was dropped, and why that is the interesting part
This branch first added an
extracascade, so a section could setaudienceonce for all its pages.Zola has no such mechanism. A bare
[cascade]table is a hardunknown fielderror at 0.22.1 — verified directly, and confirmed absent through 0.23.3 release notes:So the cascade was validator-only: it satisfied
typikon-validateand told the renderer nothing. A page relying on it passed validation and then failedzola buildagainst the render-time assert — reproduced before it was removed. That is a validate-passes/build-fails trap, and shipping one to fix a metadata gap would have been a bad trade.Rendering
audiencemoots it entirely: a rendered value must reach Zola, so it must live in the page's own frontmatter.ci/check-extra-cascade.py, thesection.core.schema.jsonchange, and the validator's cascade functions are all gone, and the two asserts removed while chasing it are restored — correct again, since they now guard a value that is genuinely rendered.Verification
bash ci/run-fixtures.sh(with~/.npm-global/binon PATH sopa11y-ciresolves) → exit 0, every stage pass.bin/typikon-check examples/sample-blogandexamples/sample-shop→ exit 0 each.<p class="entry-audience">…</p>and<p class="specs">93 words</p>on the fixture with no override.