Files
khosra/cmd/khosra/wire.go
T
bdeshiandClaude Opus 5 69f43e5791 enable task lists, superseding the decision that excluded them
ADR-0058 kept task lists out as "a note-taking affordance, not a publishing
one". That reasoning measured the wrong axis: a checklist inside a published
technical piece — setup steps, a runbook, a what-I-tried list — is publishing,
and nothing else in the dialect expresses "this item is done" without the author
hand-writing an entity. ADR-0078 supersedes that half and records why.

The half of ADR-0058 that mattered is untouched: extension.GFM stays refused,
because the bundle drags linkify in with the tables it is wanted for, and
linkify rewrites an author's plain text into markup — the line ADR-0034 draws.
One named extension is not a bundle, and wire.go now says so where the
temptation to reach for GFM will next appear.

ADR-0058's Status line names its successor, so a reader arriving there learns
the task-list sentence no longer holds. Same in-place Status annotation the
mutability rule allows, Decision text untouched.

Checkboxes render disabled: static markup, nothing clickable, nothing stored. A
reader with scripting off sees the same page, which is the property the whole
theme is built on. goldmark adds no class to the list, so theme.css finds it
with :has rather than the engine inventing markup to be styled by.

Demo carries the case ADR-0051 requires — a colophon checklist of what this
build does and does not do, including the unticked "ship a single byte of
JavaScript", which is true of that page and asserted by the test's absent list.

No counter moves: state.md's counters are explicit that an upstream extension
enabled in the list is dialect, not a feature of this engine — only a package
under internal/ext/ counts.

8 files, +55/-10. 1 line of engine code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 19:00:51 +06:00

45 lines
1.7 KiB
Go

package main
import (
"io/fs"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
"khosra/internal/content"
"khosra/internal/ext/notation"
"khosra/internal/ext/shortcodes"
"khosra/internal/render"
)
// theme builds the renderer this build ships: the list below, plus what `include: merge` needs (ADR-0066).
// One function, because the only other caller is the demo's coverage test, and a copy of this wiring drifted
// three times before it stopped being a copy (ADR-0072).
func theme(siteFS fs.FS, settings content.Settings) (*render.Renderer, error) {
r, err := render.New(siteFS, settings, extenders)
if err == nil {
r.Compose(shortcodes.Merge)
}
return r, err
}
// extenders is the only list of features this build includes (extensions.md). Source order is the
// semantics; enabling or disabling one is a one-line diff and a rebuild.
//
// It lives in cmd because nothing below it may know which features exist: internal/render, internal/web
// and internal/content must all build and serve with this list empty (conventions.md layering).
func extenders(partial render.Partial) []goldmark.Extender {
// Dialect before features: these say what Markdown *means* here (ADR-0058, ADR-0061), and shortcodes is
// khosra's own. Every one is parse-phase, so none of them moves the render-transform counter.
return []goldmark.Extender{
extension.Table,
extension.NewFootnote(extension.WithFootnoteIDPrefixFunction(shortcodes.FootnotePrefix)),
extension.DefinitionList,
// TaskList alone, never extension.GFM: the bundle would drag linkify in with it, and linkify
// rewrites an author's plain text into markup, which is the line ADR-0034 draws (ADR-0078).
extension.TaskList,
notation.New(),
shortcodes.New(partial),
}
}