Port the docgen site generator (gen.py/check.py/palette.py) to Ludic #41
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#41
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #31 (the doc/lint/grammar checks were ported to Ludic there; this is the remaining docgen piece).
Scope
Port the documentation site generator and its guards off Python:
tools/docgen/gen.py(462 lines) — the per-symbol → static-site generator (index/api/<id>/ns-*/color pages,ludic-highlight.js,symbols.json).tools/docgen/check.py(148 lines) — the generated-site coverage/integrity guard.tools/docgen/palette.py(298 lines) — the named-colour source of truth (emitsselfhost/backend/stdlib/emit_color.ludic+palette.json). Also has a latentptr/pointerdrift to fix while here.Building blocks already in place
tools/x/json.ludic— a JSON reader (objects/arrays/strings with\uXXXX+surrogates/numbers/literals) added in #31; reuse it forpalette.json/site.json.tools/x/checks.ludic— string helpers (s_index/sslice/s_trim/front-matter walking) and the fence/param parsing patterns.tools/docgen/assets/*and fills placeholders, so the templates themselves don't need reimplementing — only the parse → symbol-model → fill/emit logic and a small JSON serializer (forsymbols.json+ the highlighter embed).Plan
x docs-gen [--out DIR]in Ludic: parsedocs/language/**front-matter + bodies (fences,Parameters:), build the section/symbol model, read the asset templates, emit every page +symbols.json+.nojekyll.x docs-check DIR: portcheck.py(required files, a page perinventory.jsonsymbol, duplicate-token / one-dir-per-namespace guards, highlighter targets exist).palette.py(move the palette table into Ludic; emitemit_color.ludicwithpointernotptr).gen.pyandx docs-gen, diff the output trees; iterate to byte-identity (or, if a cosmetic diff is accepted, at leastcheck.py-clean)..forgejo/workflows/ci.ymland.forgejo/workflows/docs.ymlcall the Ludic generator; drop thepython:3.12container fromdocs.yml(this is what completes issue #31's criterion 3).Why staged
The generator emits 465 files (~14 KB each) with Python-
json.dumpsformatting and many HTML-escaping/whitespace edge cases; a reimplementation shipped straight to the live pages branch risks a regression, so it wants its own change with an oracle-diff gate — which is why #31's acceptance explicitly allowed staging docgen ("docgen ported or a tracked plan for the remaining piece").Done in
9ed0070.The whole docgen pipeline is Ludic now — no Python anywhere. Three new
xsubcommands, in Ludic and compiled by Ludic:x docs-gen [--out DIR]— the static-site generator. Parsesdocs/language/**front-matter + bodies (```ludic fences,Parameters:), builds the section/symbol model, reads theassets/*templates, and emits every per-symbol page, thens-*/ns-color/apipages, the landing page,ludic-highlight.js,symbols.jsonand.nojekyll.x docs-check [DIR]— the coverage/integrity guard: required files, a page perinventory.jsonsymbol, duplicate-token and one-dir-per-namespace guards, and highlighter link targets.x docs-palette— the named-colour source of truth. ThePALETTEtable moved intotools/x/docgen.ludic(thepal_add(...)rows), emittingselfhost/backend/stdlib/emit_color.ludic(aspointer, notptr) +palette.json.Oracle-diff gate:
x docs-genreproduces the Python generator's output byte-for-byte across all 466 files, andx docs-checkmatchescheck.py's pass/fail output (verified on both a clean and a deliberately-broken tree). This needed a faithful Ludic port ofjson.dumps(ordered dicts,indent=2vs compact separators,ensure_ascii\uXXXXwith surrogate pairs),html.escape(quoteon/off), the front-matter/fence/Parameters:/paragraph parsing, and codepoint-aware first-sentence truncation. Two subtleties that bit: cross-kind token collisions insym["tips"](e.g.exit/string/fixed) need dict-overwrite semantics, andplain_text's 160-char cap is codepoints, not bytes.Wired into
x testas a regression gate (docs-gen→docs-checkon a fresh site;docs-palettestays byte-identical) — the suite is now 59 passed, 0 failed.CI swap:
ci.ymlanddocs.ymlcall the Ludic generator;docs.ymldrops thepython:3.12container and bootstraps the toolchain from the IR seed with clang instead.tools/docgen/{gen,check,palette}.pydeleted — onlyassets/+inventory.jsonremain. Completes #31's criterion 3.