PDF document

Added in version 0.35.0.

The [build.pdf] section configures the single PDF produced by ubc build pdf: the page size and margins, the base type size, the two pieces of page furniture, the external PlantUML renderer, and the quality bar the build is held to.

Warning

ubc build pdf is in alpha. The command works and is under active development, but the typeset output, the theming surface and the command’s options may still change before it is announced as stable, so it is not yet recommended for production deliverables.

For a guide to running it, see Building a PDF.

Minimal example

Everything has a default, so the section is optional: ubc build pdf builds an A4 document at 10 pt with 20 mm margins, a title page and a running header, with no [build.pdf] table at all. What a project usually writes is the deviation from that:

[build.pdf]
page_size = "letter"
base_font_size = 11.0

[build.pdf.margins]
top = 25.0
bottom = 25.0

Options

deny

Type: string (optional, default: "warning")

The build’s quality bar: exit 1 when any finding at or above this level survives [lint] narrowing — "none", "info", "warning" or "error". One bar covers both counts the command reports (index diagnostics and render-phase build warnings), and the PDF is still written before the exit code is decided. The --deny command-line flag overrides the key for one run; "none" never fails the threshold (an explicit --max-warnings budget still applies).

Because constructs that are not typeset yet are reported as warnings, the default bar fails a build that contains one. That is deliberate — the finding is real, and the document has a grey box in it — and Warnings and the quality gate covers the three ways to live with it, narrowest first.

page_size

Type: string (optional, default: "a4")

The page size of the document: a4 (210 × 297 mm) or letter (8.5 × 11 in).

An enum rather than a dimension string, so there are no units to spell and no invalid geometry to express.

margins

Type: table of float (optional, defaults below)

The page margins, in millimetres. Each of top, right, bottom and left defaults to 20.0 and may be set on its own:

[build.pdf.margins]
top = 25.0

A negative value is refused, as is any combination leaving a content box narrower or shorter than 50 mm — the configuration is rejected when it is read, naming the key, rather than producing an unreadable document.

The margins are also where the page furniture is drawn: the page number is centred in the bottom margin, and the running header — when running_header is on — sits in the top one. Each stays just inside the page edge when its own margin is too small to hold it, so a tight margin costs the header’s hairline rule rather than the title.

base_font_size

Type: float (optional, default: 10.0)

The base text size, in points. Must be between 6.0 and 24.0.

Every other size in the document derives from it: headings scale up from it, code and the page number scale down from it, and the line spacing and the gaps between blocks are multiples of it. So this one key is the whole type scale — raising it to 11.0 sets the entire document a step larger, not just its body text.

title_page

Type: bool (optional, default: true)

Open the document with a title page.

On unless title_page = false. When on, the document starts with a cover carrying the project name — or, when no name is set, the root document’s title, or its file name when that document has no title — the version from [project] version when there is one, and how many of the project’s needs and documents the file contains when the build was given a need selection. A date is added only when the SOURCE_DATE_EPOCH environment variable is set, so that two builds of the same sources stay byte-identical.

The cover carries no page number — the pages after it are numbered from 1, and a PDF reader’s own page box shows the same numbers — and it takes the first entry in the document outline, so a reader can navigate back to it.

[build.pdf]
title_page = false

Turning it off removes the cover: the body is the same document in the same order, and the page numbers do not move, because the cover was never counted in them.

running_header

Type: bool (optional, default: true)

Print each page’s document title in the top margin.

On unless running_header = false. When on, every page carries the title of the document its content belongs to — or that document’s file name when it has no title — above the text, set in muted ink with a hairline rule under it, as the counterpart of the page number in the bottom margin.

It is not printed on the page where a document begins, where its own heading is already the title, and not on a title page, which belongs to no document. A document that fits on one page is therefore never headed at all — there is no continuation to head, and its heading is the page’s title. A title too wide for the page is cut short with an ellipsis, and the rule is left out where a small top margin would put it inside the text.

It names the document and not the current section: that is the question a reader of a long concatenation actually has, and the section is already in the bookmark pane and in the heading above.

plantuml.*

The external PlantUML renderer — off by default.

The same four keys as [build.plantuml] (enabled, command, timeout, min_version). This table inherits every key it does not set from [build.plantuml] and wins on every key it does, enabled = false included — see Sharing the renderer between builders for naming the executable once for the whole project, and External PlantUML renderer for the whole surface, the requirements and the trade-offs.

[build.plantuml]
command = ["java", "-jar", "{config_dir}/libs/plantuml.jar"]

[build.pdf.plantuml]
enabled = true

With it configured, a needuml, needarch, uml or plantuml diagram is drawn into the PDF as a real picture, from the same content-addressed store ubc build html renders into — so a diagram both builders draw is rendered once between them. Without it, each of those diagrams is a placeholder box showing its source.

Unrendered constructs

Some constructs are not typeset yet. Each is drawn as a labelled placeholder box — or, inline, as a mono chip — and counted on a build.pdf_* warning naming it, so the document stays honest and the counts are a backlog rather than a mystery.

No key here turns that off or changes it: it is a property of the builder’s coverage at this release, not a setting. The list, the codes and what to do about them are on the guide page: What is not rendered yet.

That is one list in one place, deliberately. It is the same shape ubc build html uses in reverse — there, the coverage warnings are documented on this configuration page and the guide links to them — and it is the placement the list itself argues for: not one of these findings is a [build.pdf] key’s, and duplicating the list across two pages would guarantee that the two drift.

The list is checked against the code, not maintained by hand alone: a test in ubc_build_pdf asserts that every construct class it draws as a placeholder is named on that page, and the per-node matrix behind it lives with the code in rust/ubc_build_pdf/design/coverage.md.