ludic/tools/docgen/README.md
Orkuncakilkaya e175619543 refactor(cli)!: split the contributor tool out of the ludic CLI
`ludic help` ended with a section titled "contributing to the toolchain itself",
listing bootstrap, reseed, docs-gen and release tasks. None of that is available
to someone who installed the language — those tasks need the repository — so the
shipped tool was advertising work its user cannot do, in a namespace they have to
read past to find `new` and `run`.

The tasks move to a second program, dev.ludic -> bin/ludic-dev, built from a
checkout and excluded from every release artifact. `ludic` keeps the project and
package commands and nothing else; `ludic dev …` now explains where the tasks
went instead of failing as an unknown command.

What this shook out: the two programs share prelude/build/project/pkg, so the
helpers each had accreted in whichever file first needed them — cc(),
ensure_ludicc, the string functions, title_case, cmd_version — moved to where
both can see them. The argument-shift indirection added for the `dev` namespace
is gone with the namespace, so commands read argv directly again.

`ludic-dev test` asserts the split rather than trusting it: the staged install
must build a project, and `ludic dev build` there must fail while naming
ludic-dev. install.sh keeps building older tags, whose bootstrap goes through
main.ludic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 23:15:12 +03:00

91 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
```markdown
---
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.
```bash
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.