Diagrams
Diagram blocks are wdoc's way of drawing diagrams and charts on pages. A diagram is made of shapes that break down into primitive shapes and render as SVG, which lets the same source target different backends.
§ 1The diagram block
Diagrams have the following properties that can be set.
| Property | Type | Required | Description |
|---|---|---|---|
| width | i64 | yes | Diagram canvas width in pixels. |
| height | i64 | yes | Diagram canvas height in pixels. |
| id | identifier | no | Optional explicit HTML id. |
| class | list<utf8> | no | Optional style classes. |
| layout | symbol | no | Layout mode: :free (default, manual x/y) / :grid / :layered / :force / :radial. |
| direction | symbol | no | Flow direction for :layered: :top_to_bottom (default) / :left_to_right. |
| layer_gap | f64 | no | Spacing between ranks (layers) in :layered layout. |
| node_gap | f64 | no | Spacing between nodes within a rank in :layered layout. |
| cell_width | f64 | no | Grid cell width for :grid layout. |
| cell_height | f64 | no | Grid cell height for :grid layout. |
| columns | i64 | no | Number of columns for :grid layout. |
| gap | f64 | no | Gap between cells in :grid layout. |
| iterations | i64 | no | :force relaxation steps (default 300). |
| repulsion | f64 | no | :force node repulsion strength (default 9000). |
| link_distance | f64 | no | :force ideal edge-to-edge length (default 60). |
| gravity | f64 | no | :force centering pull (default 0.05). |
| seed | i64 | no | :force random seed for reproducible layouts (default 1). |
| hub | identifier | no | :radial hub shape id (defaults to the highest-degree shape). |
| radius | f64 | no | :radial radius of the first ring (default: auto-fit to shape sizes). |
| ring_gap | f64 | no | :radial added radius per successive ring (default 120). |
| start_angle | f64 | no | :radial angle (radians) of the first shape on each ring (default -PI/2, i.e. top). |
| routing | symbol | no | Edge routing: :elbow (default) / :straight. |
| edge_separation | f64 | no | Nudge step that separates parallel edges (default 4). |
| pan_zoom | bool | no | When true, wrap in an interactive viewport with wheel-zoom, drag-pan, and +/−/⟲ controls. |
| zoom_min | f64 | no | Minimum zoom scale; 1.0 = fitted view (default 1.0). |
| zoom_max | f64 | no | Maximum zoom scale (default 4.0). |
| pan_margin | f64 | no | Extra overscroll past the content bounds, in px (default 0). |
| desc | utf8 | no | Accessible description: becomes the SVG's <title> and aria-label, so screen readers can announce the diagram. |
| edges | list<Edge> | yes | Edges connecting shapes (a -> b). |
Child blocks
| Slot | Accepts | Multiple | Description |
|---|---|---|---|
| children | SvgBlock | yes | The shapes drawn in the diagram. |
For accessibility, give a diagram a desc — it becomes the SVG's <title> and aria-label, so screen readers announce the diagram instead of skipping it.
§ 2Pan & zoom
Set pan_zoom = true to wrap the diagram in an interactive viewport. Wheel zooms toward the cursor, drag pans, the corner buttons zoom about centre / reset. Zoom is clamped to [zoom_min, zoom_max]; pan allows half-a-viewport of overscroll past each content edge plus the author's pan_margin. Try it on the diagram below:
diagram {
width = 320 height = 160 pan_zoom = true
zoom_min = 0.5 zoom_max = 4.0
rect { id = a x = 20.0 y = 30.0 width = 80.0 height = 50.0 fill = "#88c0d0" }
rect { id = b x = 210.0 y = 90.0 width = 80.0 height = 50.0 fill = "#a3be8c" }
a -> b
}
§ 3Linking shapes to pages
Give any shape a link to turn it into a hyperlink: clicking the box/pill navigates to that page — handy when each shape stands for a node that has its own page. The target resolves exactly like a prose link: a bare page name → page.html, a cross-site site:page, and an unknown page fails the build the same way a bad markdown link does. Try clicking the shape below:
diagram { width = 320 height = 100
process "Primitive shapes" { link = "wdoc_primitives" }
}
Because SVG/HTML anchors can't nest, don't put link on a container whose children are also linked — link the container's title label instead. On a pan_zoom diagram a plain click still navigates, while a drag-to-pan that happens to end on a linked shape does not.
§ 4Styling shapes with classes
Every shape takes a class list, just like text. A class emits SVG paint properties — fill, stroke, stroke_width, stroke_linecap, stroke_linejoin, opacity — with dark { } / light { } overrides, so you style shapes the same way you style prose. Prefer a class over an inline fill = … so a shape follows the site theme and the reader's light/dark mode.
// Declared at the top level (apply site-wide). Hyphenated names may be
// written bare (`class dgm-box`) or quoted.
class "dgm-box" {
fill = "#5e81ac"
stroke = "#2e3440"
stroke_width = "2"
dark { fill = "#88c0d0" stroke = "#eceff4" }
light { fill = "#5e81ac" stroke = "#2e3440" }
}
class "dgm-ghost" {
fill = "#a3be8c"
opacity = "0.5"
}
diagram { width = 320 height = 120
rect { x = 20.0 y = 25.0 width = 110.0 height = 70.0 class = ["dgm-box"] }
rect { x = 160.0 y = 25.0 width = 110.0 height = 70.0 class = ["dgm-ghost"] }
}
The SVG paint fields a class understands on a shape:
| Field | Effect |
|---|---|
| fill | Interior colour. |
| stroke | Outline colour. |
| stroke_width | Outline thickness. |
| stroke_linecap / stroke_linejoin | Line end / corner style. |
| opacity | Overall transparency (0–1). |
| dark { } / light { } | Per-colour-scheme overrides. |
Built-in shape classes work the same way — redeclare a quoted name to recolour it everywhere. For example, the chart palette (wdoc-series-1..wdoc-series-8) or the timeline parts:
class "wdoc-series-1" {
fill = "#bf616a"
stroke = "#bf616a"
dark { fill = "#d08770" }
}