diff --git a/docs/content-model.md b/docs/content-model.md index 8100588..4d4e983 100644 --- a/docs/content-model.md +++ b/docs/content-model.md @@ -372,8 +372,9 @@ half-working. Three colons open a **container** directive — `:::name{…}`, body, `:::` on its own line — for calls that wrap content (ADR-0064). The body is Markdown and renders as such. One level: a `:::` inside a container closes it -rather than opening another, the same limit an include carries. `note`, `warn` and `tip` exist; a kind the -theme does not define renders its body unwrapped rather than losing it. +rather than opening another, the same limit an include carries. `note`, `warn` and `tip` exist, plus `details` — an +expandable panel, and tabs when siblings share a `group` — and `aside`, a margin note. A kind the theme does +not define renders its body unwrapped rather than losing it. **Migrating from the retired form.** `{{< name key="value" >}}` is no longer a call and renders as literal text. `khosra check` reports every one as fatal and names the replacement, so a site root is migrated by diff --git a/docs/state.md b/docs/state.md index 36a0d36..f80605d 100644 --- a/docs/state.md +++ b/docs/state.md @@ -24,7 +24,7 @@ table owns. | `internal/render/render.go` | goldmark with the typographer, per-kind template sets with site override, the render methods. The parsed sets plus the stylesheet are one snapshot behind an `atomic.Pointer`; `Refresh` is the only thing that replaces it, so every page serves one theme (ADR-0055, ADR-0056). Heading ids are a parser option set here (ADR-0058), and this is the one renderer that enables raw HTML (ADR-0060) | | `internal/render/view.go` | the theme contract in Go: `Page`, `List`, `Sequence`, `Extras`, `Item`, `Fragment` (with `Body` and `Headings`, ADR-0064, ADR-0065), `Heading`, `Picture`, `Origin` | | `internal/render/chrome.go` | the engine's own words: phrase table, month names, digits, and the `t`/`num`/`day` template funcs (ADR-0034) | -| `internal/render/templates/` | reference theme, complete (six icon names map to Unicode, no assets — ADR-0063): `base.html` (shell, navigation, language links, feed and OpenGraph), `page.html` (bundle, sequence, tags, extras), `list.html`, `extras.html`, `shortcodes.html`, `theme.css` (ADR-0026, ADR-0049) | +| `internal/render/templates/` | reference theme, complete (six icon names map to Unicode, no assets — ADR-0063): `base.html` (shell, navigation, language links, feed and OpenGraph), `page.html` (bundle, sequence, tags, extras), `list.html`, `extras.html`, `shortcodes.html` (figure, gallery, icon, note/warn/tip, details, aside, toc), `theme.css` (ADR-0026, ADR-0049) | | `internal/ext/shortcodes/` | first feature: `::name{key=value}` block parser and node renderer, rendering through a theme fragment (ADR-0036). `figure`, `gallery`, `include`, plus the derivative pass and remembered picture inspection (ADR-0042, ADR-0044). `FootnotePrefix` namespaces an included file's footnote ids (ADR-0058). Directive syntax since ADR-0059, plus `icons.go`: `:name:` inline, rendered by the theme's one `icon` fragment (ADR-0063), `containers.go`: `:::name{…}` … `:::` wrapping a rendered body (ADR-0064), and `toc.go`: the document's headings for a `::toc` call (ADR-0065) | | `internal/ext/notation/` | the inline marks CommonMark lacks: `~sub~`, `^sup^`, `==mark==`, and `~~strike~~`, which it owns so a single tilde can mean subscript (ADR-0061). `abbr.go` adds `*[TERM]:` definitions and the pass that expands them (ADR-0062) | | `internal/ext/scaffold/` | writes one draft directory bundle into a site root through `os.Root`: never an overwrite | diff --git a/docs/surface.md b/docs/surface.md index ad1cc7a..a6c1b71 100644 --- a/docs/surface.md +++ b/docs/surface.md @@ -314,7 +314,7 @@ chrome.go 110 · render.go 483 · view.go 130 - view.go:111 type Item struct - view.go:122 type Alternate struct -## internal/web — 734 lines + 1615 test +## internal/web — 734 lines + 1619 test asset.go 58 · discover.go 71 · extras.go 93 · feed.go 125 · resolve.go 170 · web.go 217 diff --git a/docs/theme-contract.md b/docs/theme-contract.md index 34d83ca..71c06bc 100644 --- a/docs/theme-contract.md +++ b/docs/theme-contract.md @@ -108,6 +108,8 @@ Each picture carries: | `:name:` | `icon` | `.Args.name` — the name as written, nothing else | | `:::note{title=…}` … `:::` | `note` | `.Args.title`, `.Body` — the rendered content | | `::toc` | `toc` | `.Headings` — every heading in the document, in order | +| `:::details{summary=… group=… open=…}` … `:::` | `details` | `.Args`, `.Body`. Siblings sharing a `group` open one at a time, through `
` and no script | +| `:::aside{title=…}` … `:::` | `aside` | `.Args.title`, `.Body`. Beside the text where there is room, in the flow where there is not | A **container** call wraps content: `:::name{…}`, a body, then `:::`. It renders through the fragment of that name with `.Body` already HTML, and one level only — a `:::` inside closes the one it is in. A theme with no diff --git a/examples/demo-site/content/writing/notes-on-water/index.en.md b/examples/demo-site/content/writing/notes-on-water/index.en.md index fe89d18..ee91902 100644 --- a/examples/demo-site/content/writing/notes-on-water/index.en.md +++ b/examples/demo-site/content/writing/notes-on-water/index.en.md @@ -38,6 +38,22 @@ is Markdown: *emphasis*, links and H~2~O all work inside it. | North | 41 mm | steady | | South | 12 mm | falling | +:::aside{title="On the gauges"} +Both were replaced in 2024, which is why the older readings are noisier. +::: + +:::details{summary="Show the raw transcription"} +Twelve pages of it, kept out of the way until asked for. +::: + +:::details{group=readings summary="North gauge" open=yes} +41 mm, steady through the week. +::: + +:::details{group=readings summary="South gauge"} +12 mm, falling. Grouped panels open one at a time, with no script. +::: + Monsoon : The season these readings belong to. diff --git a/internal/render/templates/shortcodes.html b/internal/render/templates/shortcodes.html index 814f7bb..294ffec 100644 --- a/internal/render/templates/shortcodes.html +++ b/internal/render/templates/shortcodes.html @@ -55,3 +55,13 @@ {{- end}} {{- end}} + +{{/* An expandable section, and tabs, from one template. `
` needs no script; siblings sharing a + `group` become mutually exclusive through the native `name` attribute, which is what tabs are. A + browser too old for grouping simply opens them independently — the content is never hidden. */}} +{{define "details"}} +{{with .Args.summary}}{{.}}{{else}}{{.Args.title}}{{end}} +{{.Body}}
{{end}} + +{{/* A margin note: beside the text where there is room, in the flow where there is not. CSS only. */}} +{{define "aside"}}{{end}} diff --git a/internal/render/templates/theme.css b/internal/render/templates/theme.css index a373da4..a5fe76f 100644 --- a/internal/render/templates/theme.css +++ b/internal/render/templates/theme.css @@ -24,6 +24,11 @@ dd { margin-left: 1.25rem; } .footnotes { font-size: 0.9em; } .admonition { border-left: 3px solid #d8d5cd; border-radius: 0; padding: 0.25rem 0 0.25rem 1rem; margin: 1.5rem 0; } .admonition-title { font-weight: 600; margin: 0 0 0.5rem; } +details { margin: 1rem 0; } +summary { cursor: pointer; font-weight: 600; } +aside.side { border-left: 3px solid #d8d5cd; border-radius: 0; padding: 0 0 0 1rem; margin: 1.5rem 0; font-size: 0.95em; } +.side-title { font-weight: 600; margin: 0 0 0.5rem; } +@media (min-width: 55rem) { aside.side { float: right; width: 12rem; margin: 0.25rem 0 1rem 1.5rem; } } nav.toc ol { list-style: none; padding-left: 0; } nav.toc .toc-3 { padding-left: 1rem; } nav.toc .toc-4 { padding-left: 2rem; } @@ -33,5 +38,5 @@ nav.toc .toc-4 { padding-left: 2rem; } pre { background: #22222a; } .kind { color: #9a9a9a; } th, td { border-bottom-color: #33333c; } - .admonition { border-left-color: #33333c; } + .admonition, aside.side { border-left-color: #33333c; } } diff --git a/internal/web/example_test.go b/internal/web/example_test.go index 6db459b..be44eb5 100644 --- a/internal/web/example_test.go +++ b/internal/web/example_test.go @@ -127,6 +127,10 @@ var exampleFeatures = []featureCase{ {what: "an abbreviation expands and its definition line renders nothing", path: "/writing/notes-on-water/", code: 200, expect: []string{`NIWA`}, absent: []string{"*[NIWA]"}}, + {what: "panels and margin notes need no script", path: "/writing/notes-on-water/", code: 200, + expect: []string{"Show the raw transcription", `
`, `

On the gauges

`}, + absent: []string{"`, `The dialect`, `class="toc-2"`}}, {what: "a container renders its body through the theme fragment", path: "/writing/notes-on-water/", code: 200,