ludic/tools/docgen
Orkuncakilkaya e2528c1b10 docs/language: a page for every keyword and attribute the vocabulary has
Keywords: module uses friend export internal numbers unsafe mut port bind action
reducer registry of as from def open alias component prop view (structure),
shows lasts then loads (scenes), system (ecs), dispatch (control), true false
null (operators). Attributes: @Ref @OneOf @Range @Unit @Asset @Color, @Node /
@Clip / @Material, @Tint @Derived, @Text / @Multiline, @Key, @AppendOnly /
@ByKey, @PerMap / @Chunked, @frame @max, @owns / @creates / @releases,
@deterministic @alloc_ok. Each is in tools/docgen/inventory.json; every fence
that is not marked skip parses (ludicc --fmt). annot-clearcolor's token loses its
quotes, which no reader strips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:59:47 +03:00
..
assets fix(docs): restore the token cards on the generated site 2026-09-05 14:41:10 +03:00
inventory.json docs/language: a page for every keyword and attribute the vocabulary has 2026-09-29 23:59:47 +03:00
README.md refactor(cli)!: split the contributor tool out of the ludic CLI 2026-09-05 23:15:12 +03:00

Ludic documentation generator

Generates the public documentation site (the pages branch) from a single source of truth, so the site can never drift from the language.

Source of truth

docs/
  language/<category>/<id>.md    one file per symbol — keyword, type, phase,
                                 builtin, namespace method, operator, annotation
  language/<category>/_section.md   section title + blurb + order
  language/colors/palette.json   the 221 named colors (generated by `ludic-dev docs-palette`)
  site/site.json                 landing-page messaging (hero, features, …)
  site/snippets/*.ludic          the code shown on the landing page (real programs)
tools/docgen/inventory.json      the authoritative symbol set the coverage guard checks

A symbol file

---
id: screen-fill_rectangle     # anchor + page name (screen-fill_rectangle.html)
name: Screen.fill_rectangle
category: screen
kind: namespace-method        # keyword|type|phase|namespace-method|builtin|annotation|operator
tokens: Screen.fill_rectangle # literal token(s) the highlighter matches & links
sig: Screen.fill_rectangle(x, y, width, height, color)
tip: Draw a solid, filled rectangle.     # one sentence — the hover-card summary
order: 1
ns: Screen                    # namespace-method only
member: fill_rectangle        # namespace-method only
related: screen-clear screen-draw_rectangle
---

Rich description — inline `<code>`/`backticks`, "model instance" language.

Parameters:                   # for anything that takes arguments
- `x` — the left edge, in pixels
- `color` — the fill color, e.g. a `Color.*` name

​```ludic
program Example { … descriptive-named, compilable … }
​```

What it produces

One page per symbol (<id>.html), a namespace overview page per namespace (ns-screen.html … ns-color.html), a searchable index (api.html, fuzzy search over every symbol), the landing page (index.html), the ludic-highlight.js highlighter (all its symbol tables, tips, per-item link targets, per-parameter anchors and hover-card data generated from the sources above), symbols.json, and .nojekyll.

In any code sample: keywords/types/builtins/annotations link to their page; Screen.fill_rectangle links Screen → the namespace page and fill_rectangle → the method page separately; a named argument like width: links to that parameter's anchor; Color.Charcoal links Color and Charcoal separately; hovering any token shows a summary card from the real API data.

Build & check

The generator and its guards are written in Ludic and run through x — there is no Python in the pipeline. assets/ (the CSS/HTML/JS templates) and inventory.json are the only inputs the tools here still read directly.

bin/ludic-dev docs-gen --out build/pages    # generate the whole site
bin/ludic-dev docs-check build/pages        # coverage + duplicate-token + link guard
bin/ludic-dev check-docs                    # parse every ```ludic doc fence

docs-check fails CI if any symbol in inventory.json lacks a page, if a token is documented on two pages, or if a highlighter link points at a missing page — so "every symbol is documented, autogenerated each time" is enforced. It needs a built bin/ludic (bootstrapped from the IR seed with clang alone).

Publish

.forgejo/workflows/docs.yml bootstraps the toolchain from the IR seed and runs ludic-dev docs-gen + ludic-dev docs-check on every push to main that touches docs/**, tools/docgen/** or tools/ludic-cli/**, and publishes the result to the pages branch root. index.html + .nojekyll always stay at the root.

Colors

palette.json and selfhost/backend/stdlib/emit_color.ludic are both generated by bin/ludic-dev docs-palette from a single palette table — the pal_add(...) rows in tools/ludic-cli/docgen.ludic. Edit the table there and regenerate; do not hand-edit the generated files.