pdg XML → PDF

The pdg book · Chapter 02 of 10 · Pages & setup

The document skeleton

The four parts every document has — document, config, pages, page — plus paper sizes, margins, units, and metadata. The scaffolding you'll reuse forever.

Before content comes the frame that holds it. This chapter is the boilerplate you will copy into the top of every document — and once you understand it, you can stop thinking about it.

The four nested pieces

Try it — edit the source Open in Playground
<document version="2.0">
  <config>
    <page size="A5" margin="24px" />
    <meta name="title" value="A demo document" />
  </config>
  <pages>
    <page>
      <text size="18" bold="true">A page with room to breathe</text>
      <text size="12">The margin around me was set once, in config.</text>
    </page>
  </pages>
</document>
  • <document version="2.0"> is the root. version is the PDF version to emit, written into the file header; 2.0 is a safe, modern choice. (Leave it off and the engine writes 1.7.)
  • <config> configures the document before content. Everything in it is optional. We will fill it out below.
  • <pages> is the run of content. It holds one or more <page>.
  • <page> is one physical page. Put your content inside it.

The full rundown lives in the Document structure and Configuration guides; here is what you reach for daily.

Paper size and margins

size accepts the usual paper names — A3, A4, A5, A6, Letter, Legal (case-insensitive). Set it once in <config><page> and every page inherits it; a size or margin on an individual <page> overrides the default just for that page. Omit <config><page> entirely and you get A4 with a 36pt (half-inch) margin on every side.

margin is the inner page margin and takes the CSS 1–4 value shorthand you already know:

  • margin="24px" — all four sides.
  • margin="20px 40px" — vertical, then horizontal.
  • margin="10px 20px 30px 40px" — top, right, bottom, left.
Try it — edit the source Open in Playground
<document version="2.0">
  <config><page size="A6" margin="0" /></config>
  <pages>
    <page margin="10px 30px">
      <rect height="40px" fill="#c4341f" />
      <text size="12">This page overrode the document's zero margin with
        10px top/bottom and 30px left/right.</text>
    </page>
  </pages>
</document>

Units: px, pt, mm

Every length in pdg is a number with an optional unit:

  • px — a CSS-style pixel. 1px = 1pt, so your web muscle memory works.
  • pt — a typographic point, the PDF's native unit.
  • mm — millimetres, handy for print specs.
  • A bare number (e.g. size="12") means points.

So margin="24px", margin="24pt", and margin="24" are all the same, and margin="8mm" is about 23px. Mix freely.

Document metadata

<meta> writes into the PDF's Info dictionary — the title, author, and description a PDF reader shows in its properties panel. Add as many pairs as you like:

Try it — edit the source Open in Playground
<document version="2.0">
  <config>
    <page size="A6" margin="20px" />
    <meta name="title" value="Quarterly report" />
    <meta name="author" value="Your name here" />
    <meta name="description" value="Numbers, and what they mean." />
  </config>
  <pages>
    <page><text size="14">Check this PDF's properties — the title is set.</text></page>
  </pages>
</document>

Diagnostics: warnings and strict mode

pdg is tolerant by design. A typo'd attribute, an unknown tag, a malformed colour — none of these stop the render; the engine recovers, falls back to something sensible, and reports the problem as a warning with the line, column, and the enclosing-tag trace. In the playground these surface beside the preview; on the command line pdg validate input.xml reports them without writing a file.

When you want bad input to fail rather than slip through — in a build script or CI — switch the document to strict mode:

Try it — edit the source Open in Playground
<document version="2.0">
  <config>
    <page size="A6" margin="20px" />
    <diagnostics mode="strict" />
  </config>
  <pages>
    <page><text size="14">Strict mode refuses to emit a PDF if any error
      was recorded — warnings still only warn.</text></page>
  </pages>
</document>

The default mode is warn (report everything, render anyway); strict refuses output the moment any error is recorded. Warnings never block in either mode.

Setting defaults once

If every paragraph should be the same font and size, do not repeat yourself on each <text>. A <defaults> block in <config> declares the attribute values a tag assumes when it leaves them out — like a tiny, scoped stylesheet.

Try it — edit the source Open in Playground
<document version="2.0">
  <config>
    <page size="A6" margin="20px" />
    <defaults>
      <text font="serif" size="13" color="#3c392f" />
    </defaults>
  </config>
  <pages>
    <page>
      <text bold="true" size="18">Inheriting the defaults</text>
      <text>This paragraph never set a font, size, or colour — it took them
        from the defaults block above.</text>
    </page>
  </pages>
</document>

An attribute resolves element → nearest enclosing <defaults> → config defaults → built-in default, so an explicit attribute on the element always wins.

A block isn't limited to <config>, and this is where it gets powerful. A <defaults> is a directive, not content — it renders nothing, and it isn't a block, so you can drop one anywhere: at the top of a single <page>, inside a <box>, or right in the middle of a sentence. Wherever it lands it restyles the content that follows it, scoped to its parent, and a mid-paragraph block keeps the text flowing — the words after it just pick up the new style, on the same line.

Try it — edit the source Open in Playground
<document version="2.0">
  <config><page size="A6" margin="20px" /></config>
  <pages>
    <page>
      A plain opening sentence at the default size, and then
      <defaults><text size="17" color="#c4341f" /></defaults>
      everything from here is big and red — no line break, just a new default.

      <box background="#f3f1ea" radius="6px" padding="10px">
        <defaults><text size="10" color="#3c392f" /></defaults>
        Inside this box the default drops to 10pt grey, scoped to the box.
      </box>

      Past the box, the big red default is still in force.
    </page>
  </pages>
</document>

The Defaults guide covers the positional and scoping rules in full, and the Configuration guide covers font registration (local .ttf files and Google Fonts) — we use both in Chapter 3.

With the frame in place, let's fill it with words.