docs(skill): Generate the tttk reference catalog

Enrich known.ts with element/role details, inline specs, and dice notation, and render them from reference.ts. Add gen:skill-reference and ~ expansion in --out so the skill copy can be regenerated.

The skill's reference.md is now generated; its extra authoring content moved to layout.md, yaml-tag.md, csv.md, and markdown.md.
This commit is contained in:
2026-09-12 17:13:42 +08:00
parent 71542e7453
commit 6d94a99b42
7 changed files with 433 additions and 45 deletions
+3 -1
View File
@@ -368,7 +368,9 @@ Exit code is the contract that makes `check` usable in an agent loop.
write → check → fix. Remove the "compile is a no-op stub" note. Cross-link
the code catalog (`reference.md`) with the diagnostic codes.
- `reference.md` is generated from `known.ts` (§7.11) — do not hand-edit. The
skill's copy is refreshed by `npm run gen:reference`.
skill's copy is refreshed by `npm run gen:skill-reference`; deeper authoring
topics live in the skill's `yaml-tag.md`, `csv.md`, `layout.md`, and
`markdown.md` (see `docs/skill-reference-plan.md`).
## 10. Resolved decisions
+88 -9
View File
@@ -3,8 +3,18 @@
Generated from `src/cli/validate/known.ts` by `npm run gen:reference`.
Do not edit by hand.
Everything not listed here is standard GFM markdown. Element names are
prefixed `md-` and must match exactly.
Complete catalog of the custom elements, inline directives, and code block
roles that `tttk` understands. Everything not listed here is standard GFM
markdown. Element names are prefixed `md-` and must match exactly.
## Contents
- [Directive syntax](#directive-syntax)
- [Custom elements](#custom-elements)
- [Inline directives](#inline-directives)
- [Code block roles](#code-block-roles)
- [Dice notation](#dice-notation)
- [CSV data files](#csv-data-files)
## Directive syntax
@@ -12,9 +22,24 @@ prefixed `md-` and must match exactly.
:name[content]{key="value" .class #id}
```
- `[content]` is the directive body — a path, dice formula, color, etc.
- `{key="value"}` sets attributes; `{.class}` and `{#id}` are shorthands.
- Container directives use `::: name` … `:::`; nest with `::::`, `:::::`.
| Part | Meaning | Example |
|---|---|---|
| `:name` | Registered element name | `:md-dice` |
| `[content]` | Directive body | `[2d6+d8]` |
| `{attrs}` | Attributes | `{key="attack"}` |
| `{.class}` | Shorthand for `class` | `{.text-red-500}` |
| `{#id}` | Shorthand for `id` | `{#my-dice}` |
Container directives:
```markdown
::: container
Content here, including nested directives.
:dice[1d20]
:::
```
Nest with more colons (`::::`, `:::::`).
## Custom elements
@@ -36,6 +61,8 @@ prefixed `md-` and must match exactly.
Clickable dice roller; `key` stores the result in the URL.
Clicking the text rolls; clicking the 🎲 resets to the formula. With `key`, the result is stored in the URL as `?dice-<key>=<value>`.
- Body: dice formula
- Attributes: `key`
@@ -55,6 +82,8 @@ Clickable dice roller; `key` stores the result in the URL.
Tab-separated view of a CSV with optional group tabs.
`roll` adds a 🎲 random-tab button; `remix` makes `{{prop}}` references pull from a random row. A `group` column in the CSV produces group tabs automatically.
- Body: CSV path or inline id
- Attributes: `roll`, `remix`
@@ -74,6 +103,8 @@ Tab-separated view of a CSV with optional group tabs.
Card layout from a CSV (legacy; prefer `yaml role=tag`).
Prefer the `yaml role=tag` form — it is the only form that supports template layers, per-layer alignment, and card backs. The directive form is legacy and only supports the compact `layers` string.
- Body: CSV path
- Attributes: `size`, `grid`, `layers`
@@ -99,6 +130,8 @@ Clickable link that expands the target article inline.
Renders the target article or section inline.
`headingBase` shifts the heading levels of the embedded content.
- Body: path, optional #section
- Attributes: `headingBase`
@@ -110,6 +143,8 @@ Renders the target article or section inline.
Sets the surrounding article card background.
`fit` is one of `cover` (default), `contain`, `fill`, `none`, `scale-down`.
- Body: image path or CSS color
- Attributes: `fit`
- Body may also be a CSS color (e.g. `#2a1a3a`, `crimson`).
@@ -126,6 +161,8 @@ Sets the surrounding article card background.
Applies a border to the article card.
Body is a CSS color or a border-image path. Class flags select sides (`t b l r all`), style (`solid dashed dotted double groove ridge inset outset none`), and image repeat (`stretch repeat round space`).
- Body: color or border image
- Attributes: `width`, `slice`
- Body may also be a CSS color (e.g. `#2a1a3a`, `crimson`).
@@ -142,6 +179,8 @@ Applies a border to the article card.
Sets the article font.
`source` is `google`, `emfont`, or `local` (default).
- Body: font family
- Attributes: `source`, `weight`, `color`
@@ -153,6 +192,8 @@ Sets the article font.
Numbered markers on an image.
`pins` is a space-separated list of `label:x,y` (percent coordinates). `fixed` makes it read-only; otherwise click to add and click a pin to remove. `labelStart` sets the first label (letter or number).
- Body: image path
- Attributes: `pins`, `fixed`, `labelStart`
@@ -168,6 +209,8 @@ Numbered markers on an image.
Interactive command history / tracker panel.
The body is a CSV of command templates (`command,parameter,label,description,insertedText`).
- Body: command template CSV
- Attributes: `placeholder`, `class`, `height`
@@ -179,6 +222,8 @@ Interactive command history / tracker panel.
Runs a Yarn Spinner dialogue file.
`start` names the entry node (default `start`).
- Body: Yarn Spinner file
- Attributes: `start`
@@ -188,24 +233,38 @@ Runs a Yarn Spinner dialogue file.
## Inline directives
### Icons — `:[name]`
### `:[name]`
Inserts an icon looked up under `assets/` (searching upward from the file).
Default extension is `.png`; `.svg`, `.gif`, `.jpg`, `.jpeg`, and `.webp`
are also supported.
Default extension is `.png`; `.svg`, `.gif`, `.jpg`, `.jpeg`, and `.webp` are also supported. `label` overlays text, `repeat` duplicates N times, and `join` places a tag name between repeats.
- Body: icon name
- Attributes: `label`, `repeat`, `join`, `class`
```markdown
:[attack] :[shield.svg] :[potion]
```
### Command links — `:cmd[command]{label=...}`
```markdown
:[attack]{label=ATK repeat=3 join=br}
```
### `:cmd[command]`
Renders a clickable span that dispatches a journal command.
- Body: journal command
- Attributes: `label`
```markdown
:cmd[roll 1d20+5]{label=Roll initiative}
```
```markdown
:cmd[spark dungeon room-type]{label=Random room}
```
## Code block roles
The `role=` attribute on the info string determines how a fenced block is
@@ -215,6 +274,8 @@ handled.
CSV (or markdown pipe table) rendered as `:md-table`.
The first column header must be a dice formula; each row's first cell is the roll value (a number, or a range like `1-3`). Extra fence attributes are forwarded to the generated `:md-table`, e.g. ` ```csv role=spark-table roll=true `.
````markdown
```csv role=spark-table
d6,结果
@@ -236,6 +297,8 @@ d6,结果
Reactive variable / tag-modifier definitions.
Columns (any order): `tag`, `threshold`, `key`, `expr`. A row with an empty `tag` declares a variable; a row with a `#tag` applies a modifier when that tag is active.
````markdown
```csv role=declare
tag,threshold,key,expr
@@ -248,6 +311,8 @@ tag,threshold,key,expr
Stored as inline text content and stripped.
Referenced by the derived inline id, e.g. `:md-embed[./text_<hash>]`.
````markdown
```text role=file
Stored as inline content.
@@ -258,6 +323,8 @@ Stored as inline content.
YAML rendered as a custom element.
`tag:` names the element, `body:` becomes its content, and any other key becomes an attribute. Fence-line attributes override the YAML body. See `yaml-tag.md`.
````markdown
```yaml role=tag
tag: md-deck
@@ -272,6 +339,18 @@ grid: 5x5
No role → a normal visible code block. Unknown role → warned about and
stripped.
## Dice notation
Used by `:md-dice`, spark-table headers, and the journal `/roll`:
| Notation | Meaning |
|---|---|
| `2d6` | two six-sided dice |
| `1d20+5` | d20 plus modifier |
| `3d6kh1` | keep highest 1 |
| `3d6dl2-1` | drop lowest 2, minus 1 |
| `{d4, d8}` | choose one of the listed dice |
## CSV data files
Keep CSV files clean — a header row and data rows. Put deck configuration
+164
View File
@@ -0,0 +1,164 @@
# tttk skill reference — reorganization plan
Status: **implemented.** Follows the `tttk check` work that made
`docs/reference.md` a generated artifact (see `docs/check-plan.md` §7.11).
Landed: `known.ts` carries element/role `details`, inline specs, and dice
notation; `reference.ts` renders them; `scripts/generate-reference.ts` expands
`~` in `--out`; `npm run gen:skill-reference` refreshes the skill copy. The
skill's `reference.md` is now generated and byte-identical to
`docs/reference.md`, with the extra content moved to `layout.md`, `yaml-tag.md`,
`csv.md`, and `markdown.md`.
## 1. Goal
Make the `tttk-authoring` skill's `reference.md` a **generated** file — the same
catalog the validator uses — and relocate the authoring content it does not
cover into focused companion files. One source of truth (`known.ts`), no
hand-maintained element list, and no content lost in the swap.
## 2. Current state
The skill (`~/.agents/skills/tttk-authoring/`) has a hand-written
`reference.md` (~465 lines) and `SKILL.md`. The repo now generates
`docs/reference.md` from `src/cli/validate/known.ts` via `npm run
gen:reference`.
What the generated doc already covers:
- Directive syntax (brief)
- Custom elements: table + per-element summary, body, attrs, examples
- Inline directives: icons, `:cmd` (brief)
- Code block roles: `spark-table`, `declare`, `file`, `tag` (brief)
- CSV data files (brief)
What only the hand-written skill copy has (the "extra content"):
| # | Section | Notes |
|---|---|---|
| A | Directive syntax table + container example | richer than generated |
| B | Per-element prose | md-dice behavior, md-table `roll`/`remix`/`group`, md-deck legacy layer syntax, md-bg `fit` values, md-border class flags, md-font `source` values, md-pins behavior, md-commander CSV columns |
| C | Icon attributes | `label`, `repeat`, `join`, `class` |
| D | Column layout | `\|---` / `-\|-` / `--\|` markers |
| E | `role=declare` column semantics | `tag`/`threshold`/`key`/`expr` |
| F | YAML tag blocks | `data-config`, layers, `back_layers`, fence-line overrides |
| G | CSV authoring | clean-CSV guidance, `label`/`body`, front matter (avoid) |
| H | Alerts and mermaid | GitHub alerts, mermaid diagrams |
| I | Dice notation | notation table |
| J | Validation codes | already duplicated in `SKILL.md` |
## 3. Target skill layout
```
tttk-authoring/
├── SKILL.md # workflow, rules, validation codes, links
├── reference.md # GENERATED from known.ts — elements, roles, inline, dice, CSV basics
├── layout.md # column layout
├── yaml-tag.md # role=tag, data-config, deck layers and backs
├── csv.md # CSV authoring and front matter
├── markdown.md # alerts and mermaid
└── examples/ # unchanged
```
`reference.md` is the only generated file; the rest are hand-written and linked
from `SKILL.md`.
## 4. Content mapping
| Source | Destination |
|---|---|
| A directive syntax | generator (`reference.ts`) — add the part/meaning table + container example |
| B per-element prose | `known.ts` `details` field → rendered into `reference.md` |
| C icon attributes | `known.ts` inline specs → rendered into `reference.md` |
| E declare semantics | `known.ts` `RoleSpec.details` → rendered into `reference.md` |
| I dice notation | `known.ts` `DICE_NOTATION` → rendered into `reference.md` |
| D column layout | `layout.md` |
| F YAML tag blocks | `yaml-tag.md` |
| G CSV authoring | `csv.md` |
| H alerts and mermaid | `markdown.md` |
| J validation codes | dropped — `SKILL.md` owns the code tables |
**Decision (recommended):** fold B/C/E/I into `known.ts` rather than a separate
`components.md`. It keeps the generated reference self-sufficient and avoids a
second, drifting description of the same elements. The alternative — a
hand-written `components.md` — is rejected because it reintroduces the drift the
generator exists to prevent.
## 5. Generator changes
`src/cli/validate/known.ts`:
- `ElementSpec.details?: string` — one paragraph of authoring prose.
- `ElementSpec.attrs` → optional richer `{ name, description }[]` so the
reference can render an attribute table (keep the plain list if not worth it).
- `InlineSpec` for `:[icon]` and `:cmd` with body/attrs/summary/examples.
- `RoleSpec.details?: string` for `declare` column semantics.
- `DICE_NOTATION: { notation, meaning }[]`.
`src/cli/validate/reference.ts`:
- Render `details`, the attribute table, inline specs, and dice notation.
- Add a `Contents` TOC.
- Upgrade the directive-syntax section (table + container example).
`scripts/generate-reference.ts`:
- Expand a leading `~` in `--out` to `os.homedir()` so the skill copy can be
regenerated cross-platform.
`package.json`:
- `gen:reference` — unchanged (writes `docs/reference.md`).
- `gen:skill-reference` — `gen:reference -- --out ~/.agents/skills/tttk-authoring/reference.md`.
## 6. New skill file outlines
- **`layout.md`** — column markers, the `-N` width suffix, a worked example.
- **`yaml-tag.md`** — `role=tag` shape (`tag:`, `body:`, other keys as attrs),
fence-line overrides, `data-config` layer fields (`prop`/`template`, `pos`,
`font`/`fontSize`, `orientation`, `align`, `visible`), `back_layers`, and the
legacy `:md-deck` compact layer syntax.
- **`csv.md`** — clean-CSV guidance, `label`/`body` conventions, `group` tabs,
`{{prop}}` interpolation, quoting rules, and the discouraged front-matter form.
- **`markdown.md`** — GitHub alerts and mermaid (standard markdown, not tttk
syntax).
## 7. SKILL.md changes
- Update the "Reference" section to link `reference.md` plus the four new files.
- Keep the validation code tables in `SKILL.md` (they are the agent's quick
reference); `reference.md` no longer carries them.
- Reword "check `reference.md` when unsure" to point at the right file per topic.
## 8. Steps
1. Enrich `known.ts` (details, inline specs, role details, dice notation).
2. Update `reference.ts` and `generate-reference.ts`; regenerate
`docs/reference.md`; keep the `known.test.ts` drift guard green.
3. Extract D/F/G/H from the old skill `reference.md` into `layout.md`,
`yaml-tag.md`, `csv.md`, `markdown.md`.
4. Regenerate the skill's `reference.md` with `npm run gen:skill-reference`.
5. Update `SKILL.md` links.
6. Verify (§9).
## 9. Verification
- `npm run gen:reference` leaves `docs/reference.md` unchanged (idempotent).
- `npx jest` passes, including the reference drift guard.
- Diff the old skill `reference.md` against the new file set and confirm every
section in §2's table has a destination — no content silently dropped.
- `npx tttk check ./content` still runs clean (the catalog changes are
documentation-only, but the drift guard protects `known.ts`).
## 10. Risks
- **Content loss during extraction.** Mitigate with the §4 mapping as a
checklist and a manual diff before deleting the old file.
- **`known.ts` bloat.** Keep `details` to one paragraph per element; long-form
material belongs in the companion files.
- **Skill path portability.** `~` expansion in the generator; the skill lives
outside the repo, so the drift guard cannot cover it — document that
`gen:skill-reference` is the refresh command.
- **Two references.** `docs/reference.md` and the skill copy are both generated
from `known.ts`; they must be regenerated together. Note this in
`docs/check-plan.md` §9.