parse :name: as an icon, and let the theme decide what one is

The engine's half is one call: parse the name, hand it to a single `icon`
fragment, decide nothing else. No icon table in Go, ever. The surveyed engines
split three ways — Unicode (Hugo, Pandoc), a remote image per icon (Jekyll's
jemoji, which fails the sovereignty test outright), and inlined SVG from a
bundled set (MkDocs Material) — and all three are decisions about markup, which
ADR-0036 puts in the theme. A theme wanting Font Awesome ships a sprite in its
own base.html and redefines one fragment: no webfont, no request, no script.

The boundary rules are the whole difficulty, because the colon is the commonest
punctuation in technical prose. A name must start with a letter, hold only
letters, digits, hyphens and underscores, and neither colon may touch an
alphanumeric. Verified on the real binary that 10:30:15, key:value:pair,
"Note: this", a URL and a code span all come through untouched — each of them
would otherwise be a silent edit to someone's sentence.

The literal fallback closes the same hole from the other side: when the theme
renders nothing, the engine writes the author's `:name:` back, so an
unrecognised icon is never deleted from the middle of a paragraph.

An icon needed its own inline node rather than the block one — goldmark
distinguishes the two by type — which also avoids the type switch CLAUDE.md §6
forbids: two kinds, two renderer functions.

The reference theme maps six names to Unicode and ships no sprite, font or
asset. core 2794/2800, ext 1615/2000, 34 gates green.
This commit is contained in:
Claude Opus 5
2026-08-01 21:54:28 +06:00
committed by bdeshi
parent 661fb469e8
commit df9335df33
11 changed files with 265 additions and 30 deletions
+2
View File
@@ -127,6 +127,8 @@ var exampleFeatures = []featureCase{
{what: "an abbreviation expands and its definition line renders nothing", path: "/writing/notes-on-water/", code: 200,
expect: []string{`<abbr title="National Institute of Water and Atmospheric Research">NIWA</abbr>`},
absent: []string{"*[NIWA]"}},
{what: "an icon renders through the theme, and prose colons are untouched", path: "/writing/notes-on-water/", code: 200,
expect: []string{"⚠️", ":nosuchicon:", "10:30:15", "key:value:pair"}},
{what: "the dialect renders tables, definition lists and strikethrough", path: "/writing/notes-on-water/", code: 200,
expect: []string{"<table>", "<th>Gauge</th>", "<dl>", "<dt>Monsoon</dt>", "<del>a struck phrase</del>"}},
{what: "a fragment's footnote ids are namespaced, so the page's own keep working", path: "/writing/notes-on-water/", code: 200,