8. Components and repeaters
Declare data once, then stamp markup from it with `wdoccomponent, slots, and wdocrepeater`.
After this lesson you can
- Declare a wdoc_component with defaulted wdoc_slots - Fill slots via interpolated strings and bare field references - Stamp one instance per data row with wdoc_repeater
Before you start: A book site and its table of contents
A component is a reusable fragment of ordinary wdoc markup with named slots: declare wdoc_slots and a wdoc_body, then instantiate the component by its own name anywhere a block is allowed. Slot values land in text through $"…${slot}…" interpolated strings; bare references (like class = [status]) need no prefix. A slot with a default is optional at the call site.
A wdoc_repeater renders its body once per element of each, binding the element to the symbol named by as — combined with a component it stamps one card per data row. The same repeater emits pages at the document root and chapters inside a toc, so navigation can be data-driven too.
§ 1Exercise: One card per metric
Declare a metric-card component and a data list, then render one card per row with a repeater.
let metrics = [
{ name: "CPU", pct: 42, sev: "warning" },
{ name: "Memory", pct: 88, sev: "error" },
]
wdoc_component metric_card {
wdoc_slot label
wdoc_slot value
wdoc_slot status { default = "note" }
wdoc_body {
callout $"" { class = [status] body = $"Currently at **%**" }
}
}
page health { sites = [:docs]
h1 "Health"
wdoc_repeater { each = metrics as = :m
metric_card { label = m.name value = m.pct status = m.sev }
}
}
Expected result
The page shows one callout per data row — a warning-coloured CPU card and an error-coloured Memory card — with the values interpolated into the bodies.
Hint
Interpolated strings need the $ prefix; a plain "…" renders ${…} literally.