pdg XML → PDF

Reference

Block elements

Structural elements. Use these anywhere a document, page, container, or table cell expects content — they stack, nest, and paginate.

<text>

block

A paragraph of styled text that wraps to the available width and paginates by line.

AttributeValuesDefaultDescription
font sans | serif | <face> | <standard> sans Font family: the embedded built-ins sans/serif, a <font-face>/<google-font> name, or a non-embedded standard PDF font (helvetica, times, courier, symbol, zapfdingbats).
size length 12 Font size.
bold true | false false Bold weight.
italic true | false false Italic.
align left | center | right | justify left Aligns lines within the block's own width; justify stretches every line but the last. The block fills wider than its text only when given a width or a stretching parent.
color color black Text color.
paragraph-spacing length 0 Extra vertical gap opened below each <p> paragraph break.

Inline markup nests freely mid-paragraph: <b>, <i>, <u>, <s>, <font color size>, <a href>, <br/>, <p/> (paragraph break — see paragraph-spacing), <field name> (a page-counter placeholder), and <inline> (an inline-block — set any element in the flow).

align positions lines within the block's own box, which is as wide as its widest line. So align="right" in a shrink-to-fit row aligns the lines relative to each other, not to the row's right edge — to push the whole block to an edge, give it a width (style:width) or a stretching parent (an <expander/> beside it, a cross="stretch" column). A table cell or the full-width page column already provides that box, so alignment fills there.

Try it — edit the source or tweak the controls Open in Playground
<text font="serif" size="14" bold="true" align="center">
  The <i>quick</i> brown fox<br/>
  jumps over the <font color="#b31d28">lazy</font> dog.
</text>

<rect>

block

A solid filled rectangle. Useful as a background, swatch, or block.

AttributeValuesDefaultDescription
width length 0 Box width.
height length 0 Box height.
fill color black Fill color.
Try it — edit the source or tweak the controls Open in Playground
<rect width="120px" height="40px" fill="#3366cc" />

<line>

block

An axis-aligned rule for dividers and separators, solid or dashed.

AttributeValuesDefaultDescription
direction horizontal | vertical horizontal Axis the line runs along.
length length fill Fixed extent; omitted, it fills the offered space.
stroke-width length 1 Stroke width (same name as on circle).
stroke color black Stroke color (same name as on circle).
dash length 0 On/off run length for a dashed line; 0 is solid.

A bare <line/> in a stretched column is a full-width divider. Drawn as a stroke (not a filled rect), so it can dash. stroke / stroke-width match <circle>, so the outline vocabulary is the same across both shapes.

Try it — edit the source or tweak the controls Open in Playground
<vertical gap="8px" cross="stretch">
  <text bold="true">Section</text>
  <line stroke-width="2px" stroke="#c4341f" />
  <text>Body below the rule.</text>
  <line stroke-width="1px" stroke="#999999" dash="3px" />
</vertical>

<circle>

block

A filled and/or stroked ellipse. radius gives a circle; width/height an ellipse.

AttributeValuesDefaultDescription
radius length 0 Circle radius (sets both width and height).
width length Ellipse width (overrides radius).
height length Ellipse height (overrides radius).
fill color black* Fill color. *Defaults to black only if no stroke is set.
stroke color Outline color (drawn inside the box).
stroke-width length 1 Outline width.

With neither fill nor stroke, a circle defaults to a solid black disc.

Try it — edit the source or tweak the controls Open in Playground
<horizontal gap="14px" cross="center">
  <circle radius="20px" fill="#2255cc" />
  <circle radius="20px" stroke="#cc7a00" stroke-width="2px" />
  <circle width="56px" height="28px" fill="#22aa55" />
</horizontal>

<image>

block

A bitmap (PNG/JPEG) from a local path or http(s) URL. Aspect ratio is preserved.

AttributeValuesDefaultDescription
src path | URL Required. File path or http(s) URL.
width length auto Target width; height scales to match.
height length auto Target height; width scales to match.

One of width / height is enough — the other is derived from the image's natural aspect ratio. The CLI reads that from the file; the browser has no filesystem, so it resolves src as a URL (relative paths from the site root, e.g. assets/press.jpg/assets/press.jpg), pre-measures the image, and hands the size to the layout. Give both only to deliberately distort.

Try it — edit the source Open in Playground
<image src="assets/press.jpg" width="240px" />

<spacer>

block

Empty vertical whitespace.

AttributeValuesDefaultDescription
height length 0 Amount of vertical space.
Try it — edit the source Open in Playground
<vertical>
  <rect width="160px" height="16px" fill="#1b1a17" />
  <spacer height="24px" />
  <rect width="160px" height="16px" fill="#c4341f" />
</vertical>

<vertical>

block

Stacks its children top to bottom, paginating by child. The page body is a vertical internally.

AttributeValuesDefaultDescription
gap length [length] 0 Space between children. One value sets both axes; two are (horizontal, vertical).
main start … space-evenly start Main-axis (vertical) distribution: start, center, end, space-between, space-around, space-evenly.
cross start | center | end | stretch start Cross-axis alignment; stretch fills the width.

Any child may carry flex="n" to grow into leftover space.

Try it — edit the source or tweak the controls Open in Playground
<vertical gap="6px" cross="stretch" main="start"
          style:min-height="170px" style:background="#faf6ed" style:padding="8px">
  <text style:background="#efe9db" style:padding="6px">First line</text>
  <text style:background="#e7e0d0" style:padding="6px">Second line</text>
</vertical>

<horizontal>

block

Lays children left to right; a row of rigid children wraps to new lines when it overflows the width.

AttributeValuesDefaultDescription
gap length [length] 0 Between children, and between wrapped lines (2nd value).
main start … space-evenly start Main-axis (horizontal) distribution: start, center, end, space-between, space-around, space-evenly.
cross start | center | end | stretch start Cross-axis alignment; stretch makes cells equal height.

Equal columns: give children flex="1". <expander/> is a contentless spring.

Try it — edit the source Open in Playground
<horizontal gap="12px" cross="stretch">
  <vertical flex="1" style:background="#f0ece1" style:padding="10px">
    <text>Column one</text>
  </vertical>
  <vertical flex="1" style:background="#e7e0d0" style:padding="10px">
    <text>Column two</text>
  </vertical>
</horizontal>

<stack>

block

Layers its children over each other in the same box; the last child is on top.

No attributes.

Children are anchored at the top-left and each is offered the full space; the stack shrink-wraps to the largest layer. When the content overruns the page, each layer paginates independently — its remainder continues on the next page in the same z-position — so a short background layer paints only on the first page. A background that must repeat on every page belongs in <layout>, not here.

Try it — edit the source Open in Playground
<stack>
  <rect width="220px" height="56px" fill="#1b1a17" />
  <padding all="16px"><text color="white" size="16">Overlaid label</text></padding>
</stack>

<box>

block

A background + border + padding container around block-flow content.

AttributeValuesDefaultDescription
background color Fill behind the content.
border 1–4 lengths 0 Border widths (CSS shorthand).
border-color color black Border color.
radius length 0 Rounded corner radius.
padding 1–4 lengths 0 Inner padding (CSS shorthand).
width length Fixed box width.
height length Fixed box height.

Sugar over the same machinery the style: box model builds — richer effects (shadows, per-side borders, clipping) are still available via style: on the same <box>.

A <box> collapses its content like any container: several children stack as a column, a single child is used as-is, and bare text is wrapped as a paragraph — so <box padding="10px">Just text</box> needs no inner <text>.

Try it — edit the source or tweak the controls Open in Playground
<box background="#f3f1ea" border="1px" border-color="#c9c4b4" radius="8px" padding="10px">
  <text>A box gives the box model a home element.</text>
</box>

<padding>

block

Insets a single child. For most spacing, prefer style:padding / style:margin.

AttributeValuesDefaultDescription
all length 0 CSS 1–4 length shorthand for every side (e.g. 8px or 8px 16px). Same grammar as box/style:padding.
top / right / bottom / left length all Override an individual side.
Try it — edit the source Open in Playground
<padding all="8px" left="32px">
  <text>Indented more on the left.</text>
</padding>

<table>

block

A grid with repeating headers, fixed or fractional columns, borders, and zebra striping. Cells hold any elements.

AttributeValuesDefaultDescription
columns spec list equal `*` Per-column widths: a length (100px) is fixed; */2* is a weighted fraction of the leftover; auto sizes to the column's content. Omitted (or any column left unspecified) means an equal * fraction. auto columns are served before fractions, so auto 1* hugs the first column and fills the second.
border spec hairline grid Space-separated: a length (thickness), a color, and which lines — grid (all, default), rows, cols, outer, or none. e.g. 0.5pt #ccc rows outer.
border-color color grey Grid line color, when the border spec names none.
cell-padding length 4 Inset inside every cell.
edge-padding length 0 Extra inset between the table's left/right edge and the outer columns' content. Backgrounds and borders still reach the edge — only the text moves in.
stripe color none Zebra fill for alternating body rows.
header-border true | false true Draw the line between the header and the body. Off lets a full-bleed header run into the first body row.
font / size / bold / italic / color / background Per-<header>/<row>/<cell>: text style (font, size, weight, slant, color) that cascades to the cells' content, and a background fill. align stays per-cell.

Sub-tags: <header> (rows repeated on every page), <row>, and <cell> — cells take colspan, rowspan, valign (top | middle/center | bottom), and background. A <header> or <row> carries the text style for its cells — font, size, bold, italic, color, and a background band — and those cascade to every cell's content (cell beats row beats the document default), reaching nested <text> and inline runs that don't set their own; align stays per-cell, since columns differ. A <header> accepts its cells two ways: wrap them in a <row> (use this for a multi-row header), or — the common case — list <cell>s directly inside <header>, and it reads as a single styled row (the example below uses this shorthand).

A single row taller than the page splits across pages; rowspan cells group their rows into a section that moves together.

Column widths come from the columns spec. A fixed length (100px) claims its size. An auto column is measured and sized to its content — the widest cell, shrinking toward its longest word only if the row would otherwise overflow. A fraction (*, 2*) splits whatever width is left after the fixed and auto columns, by weight. auto is served before fractions, so columns="auto 1*" is the common "label hugs, body fills" pair; a table of only auto columns shrinks to fit its content. With no columns attribute — or for any column the spec doesn't reach — every such column is an equal * fraction, so the grid divides the full width evenly. (Content sizing reads non-spanning cells; a colspan cell lays out into whatever its columns resolve to.)

edge-padding gives the content breathing room at the table's left and right edges without pulling the backgrounds in: it insets only the leftmost cell's left and the rightmost cell's right content, so a full-width header fill or row stripe still reaches the page edge while the text sits in from it. (cell-padding insets every cell on all sides; edge-padding is the extra outer gutter.)

The border spec controls which lines draw. List a thickness, a color, and any of grid (all lines, the default), rows (horizontal lines between rows), cols (vertical lines between columns), outer (just the frame), or none — naming one turns the rest off. So border="0.5pt #ccc rows" draws only row separators, and border="0.5pt #ccc rows outer" adds the frame. (border="0.5pt" with a separate border-color still works.) Row backgrounds and stripes fill edge-to-edge and run continuously between rows — the lines and frame paint over them — so turning a line off never leaves a seam. header-border="false" drops just the header/body line, letting a colored header run straight into the body.

style: works at three levels. The table and each cell are real boxes, so they take the full box model (style:background, padding, border, radius, box-shadow, …) — the table around the whole grid, a cell around its content. A row is painted as a band: it takes the box decorations (background, border, radius, box-shadow), vertical padding (which grows the band and insets its content), and margin — vertical margin opens transparent gaps above/below the band; horizontal margin indents the row into a detached card, stealing the width from the fractional columns first, then the trailing ones. (A margined row leaves the table's grid lines and shows its own style:border instead.) Horizontal padding is still ignored on a row — its cells sit in the shared columns; use cell-padding or a horizontal margin instead. Row margin applies to ordinary, non-rowspan rows.

Bare cell text resolves <text> defaults: a <defaults><text font="…"/></defaults> applies to <cell>foo</cell> just as it would to a standalone <text>.

Try it — edit the source or tweak the controls Open in Playground
<table columns="2* 1* 80px" border="0.5px" cell-padding="6px" stripe="#f3eee2">
  <header background="#1b1a17" color="#fff" bold="true">
    <cell>Name</cell><cell>Role</cell><cell align="right">Age</cell>
  </header>
  <row><cell>Ada</cell><cell>Engineer</cell><cell align="right">36</cell></row>
  <row><cell>Linus</cell><cell>Maintainer</cell><cell align="right">54</cell></row>
  <row><cell colspan="3" valign="middle">Spanning footer</cell></row>
</table>

<list>

block

A bulleted or numbered list; each holds any flow content.

AttributeValuesDefaultDescription
marker bullet/disc | circle | square | dash | decimal | lower-alpha | upper-alpha | none | <literal> bullet Marker glyph or numbering. bullet/disc is a filled dot, circle a hollow one, square a filled square; any other string is used verbatim as the marker.
start number 1 First number for ordered markers.
gap length 4 Vertical space between items.
indent length 18 Width of the marker gutter.
marker-color color text color Color of the markers.
font sans | serif | <family> inherited Font family for item text and markers.
size length inherited Font size for item text and markers.
bold true | false inherited Bolds item text and markers.
italic true | false inherited Italicizes item text and markers.
color color black Text color for items (and the marker fallback when marker-color is unset).

Pagination is by whole item; an <item> taller than the page is dropped (like an over-tall table row). Numbering stays continuous across a page break.

Try it — edit the source or tweak the controls Open in Playground
<list marker="decimal" gap="3px">
  <item>First ordered item</item>
  <item>A longer item that wraps onto a second line</item>
  <item>Third</item>
</list>

<expander>

block

A contentless spring that absorbs leftover main-axis space, pushing what follows to the far edge.

AttributeValuesDefaultDescription
weight number 1 Share of free space relative to sibling springs.

Same idea as flex on an empty element; any child can carry flex="n" directly.

Try it — edit the source Open in Playground
<horizontal cross="center">
  <text bold="true" size="16">Title</text>
  <expander/>
  <text color="#8a8678">page 1</text>
</horizontal>