Body font size is now specified in millimetres and defaults to 3mm. Page numbers move from the centre footer to the outer bottom corners, alternating left and right per A5 page.
9.5 KiB
tttk syntax reference
Generated from src/cli/validate/known.ts by npm run gen:reference.
Do not edit by hand.
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
:name[content]{key="value" .class #id}
| 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:
::: container
Content here, including nested directives.
:dice[1d20]
:::
Nest with more colons (::::, :::::).
Custom elements
| Directive | Body | Key attributes |
|---|---|---|
:md-dice |
dice formula | key |
:md-table |
CSV path or inline id | roll, remix |
:md-deck |
CSV path | size, grid, layers |
:md-print |
markdown path, optional #section | columns, margin, gap, font, title, pageNumbers, cutMarks |
:md-link |
path, optional #section | — |
:md-embed |
path, optional #section | headingBase |
:md-bg |
image path or CSS color | fit |
:md-border |
color or border image | width, slice |
:md-font |
font family | source, weight, color |
:md-pins |
image path | pins, fixed, labelStart |
:md-yarn-spinner |
Yarn Spinner file | start |
:md-dice
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
:md-dice[1d20+5]{key="attack"}
:md-dice[2d6+3]
:md-dice[3d6kh1]
:md-table
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
:md-table[./npcs.csv]
:md-table[./encounters.csv]{roll=true}
:md-table[./quests.csv]{roll=true remix=true}
:md-deck
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
:md-deck[./cards.csv]{size="63x88" grid="5x5" layers="title:1,1-5,1f8 body:1,5-5,8f3"}
:md-print
Paginates a markdown document into A4 landscape sheets for printing.
Each sheet holds two A5 pages side by side, and each A5 page flows the markdown into columns columns. margin, gap, and font are in millimetres (the body font defaults to 3mm). pageNumbers adds an n / total footer in the outer corner and cutMarks draws the centre cut line. The preview modal exports through the browser's print dialog (choose A4 landscape, no margins, 100% scale).
- Body: markdown path, optional #section
- Attributes:
columns,margin,gap,font,title,pageNumbers,cutMarks
:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}
```yaml role=tag
tag: md-print
body: ./rules.md
columns: 2
margin: 10
gap: 5
font: 3
title: 规则书
```
:md-link
Clickable link that expands the target article inline.
- Body: path, optional #section
:md-link[./rules.md]
:md-link[./rules.md#combat]
:md-embed
Renders the target article or section inline.
headingBase shifts the heading levels of the embedded content.
- Body: path, optional #section
- Attributes:
headingBase
:md-embed[./rules.md#combat]{headingBase=1}
:md-bg
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).
:md-bg[./images/dungeon-bg.jpg]{fit="cover"}
:md-bg[#2a1a3a]
:md-border
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).
:md-border[crimson]{.b}
:md-border[./frame.png]{width="2mm" slice="10" .all.round}
:md-font
Sets the article font.
source is google, emfont, or local (default).
- Body: font family
- Attributes:
source,weight,color
:md-font[Noto Sans SC]{source="google" weight="700" color="#1a1a2e"}
:md-pins
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
:md-pins[./images/battle-map.png]{pins="A:25,50 B:75,30 C:50,80" fixed}
:md-pins[./images/dungeon.png]{labelStart="1"}
:md-yarn-spinner
Runs a Yarn Spinner dialogue file.
start names the entry node (default start).
- Body: Yarn Spinner file
- Attributes:
start
:md-yarn-spinner[./story.yarn]{start="start"}
Inline directives
:[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. label overlays text, repeat duplicates N times, and join places a tag name between repeats.
- Body: icon name
- Attributes:
label,repeat,join,class
:[attack] :[shield.svg] :[potion]
:[attack]{label=ATK repeat=3 join=br}
:cmd[command]
Renders a clickable span that dispatches a journal command.
- Body: journal command
- Attributes:
label
:cmd[roll 1d20+5]{label=Roll initiative}
:cmd[spark dungeon room-type]{label=Random room}
Code block roles
The role= attribute on the info string determines how a fenced block is
handled.
Fences may use backticks or tildes (~~~); the closing fence must reuse
the opening marker. Fence attribute keys may contain hyphens (e.g.
data-foo=bar).
role=spark-table
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.
```csv role=spark-table
d6,结果
1,遭遇强盗
2,平安无事
```
```markdown role=spark-table
| d6 | 结果 |
|----|------|
| 1 | 遭遇强盗 |
| 2 | 平安无事 |
```
role=declare
Reactive variable / tag-modifier definitions.
YAML with two optional maps. vars: maps a $name to its expression. tags: maps a tag name to a map of thresholds to $target modifiers: at that tag count the target gains the value, so sibling thresholds stack. Tag names may be written with or without the leading #. YAML resolves bare numbers to numbers and everything else to strings; both become expression text.
```yaml role=declare
vars:
$hp: $con*5 + $mod_hp
$ac: 10 + $dex
tags:
warrior:
1:
$mod_hp: 20
2:
$mod_str: 1
```
role=file
Stored as inline text content and stripped.
Referenced by the derived inline id, e.g. :md-embed[./text_<hash>].
```text role=file
Stored as inline content.
```
role=tag
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.
```yaml role=tag
tag: md-deck
body: ./cards.csv
size: 63x88
grid: 5x5
```
No role / unknown role
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 |
d20 |
one twenty-sided die (count optional) |
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
and templates in a yaml role=tag block's data-config.
label— unique row id (number or text).body— main content, supports markdown.- Any other columns are custom fields.
{{prop}}inbodyinterpolates another column (or front-matter key) from the same row; with{remix}it pulls from a random row.- Wrap values containing
,,", or newlines in double quotes; escape"as"". Lines beginning with#are comments.