# pdf@0.1

**Status:** normative. **Inherits:** [`../conventions.md`](../conventions.md) — envelope,
preservation, inert raw HTML, safe links, and shared diagnostics. It has no items and does not inherit
the shared item model. **Schema:** [`schema.json`](schema.json).
**Fixtures:** [`fixtures/`](fixtures/). **Owns diagnostic codes:** `MDTO800`–`MDTO899`.

**Companion skill:** [Authoring and editorial guidance](https://markdownto.ai/specs/pdf.skill.md) (non-normative).

---

## 1. Purpose

`pdf@0.1` describes a **print publication**: ordinary GFM prose plus explicit page direction that
renders as refined, self-contained HTML and builds into a paginated PDF from the same view. The
Markdown remains the canonical publication; PDF is a reproducible artifact beside it.

---

## 2. Grammar

### 2.1 Envelope

```yaml
---
markdownto: pdf@0.1
title: Field guide to small observatories
page-size: A4
orientation: portrait
margins: generous
style: editorial
toc: true
---
```

| Key | Type | Default | Meaning |
|---|---|---|---|
| `page-size` | `A4` \| `Letter` \| `Legal` | `A4` | Physical page box. Case-insensitive; canonical IR preserves the displayed spelling. |
| `orientation` | `portrait` \| `landscape` | `portrait` | Page orientation. |
| `margins` | `compact` \| `standard` \| `generous` | `standard` | Named margin system, deliberately not free-form CSS. |
| `style` | `editorial` \| `report` \| `minimal` | `editorial` | Print art direction. Content and hierarchy never change with style. |
| `toc` | boolean | `false` | Include a generated table of contents from named `##` sections. |

Wrong YAML types are shared `MDTO007`. Unknown scalar values are `MDTO800`–`MDTO803` in table order.
Output flags such as `--out` and browser selection describe one build and therefore never enter the
file.

### 2.2 Publication structure

One optional leading `#` is the publication title heading. `##` means a **print section** and forms
the outline used by `toc: true`. A later `#` or a heading deeper than `##` is `MDTO804`; an empty
section name is `MDTO805`. Content before the first section forms an implicit front section.

Paragraphs, emphasis, links, images, blockquotes, bullet and ordered lists, task lists, code blocks,
tables, thematic breaks, and inline code are printable content. Raw HTML is escaped and printed as
source; it never executes. Frontmatter and inline metadata are not printed. A file with no printable
content is `MDTO806`.

### 2.3 Pagination and deterministic output

The HTML view is print-first: `@page` carries size and margins; widows/orphans are controlled;
headings avoid stranded bottoms; code and tables may split only when they exceed a page; URLs remain
clickable; colors meet 4.5:1 in both screen schemes and print. Screen view shows paper sheets on a
quiet studio ground; print removes shadows, controls, and source disclosure.

`mdto pdf build` renders the exact same HTML with a local Chromium-family browser. It performs no
network request, waits for fonts/layout, prints backgrounds, refuses a missing browser with an
actionable message, and verifies that a non-empty PDF was written before reporting success. A build
receipt is not written: browser version and timestamp are run facts, not publication state.

### 2.4 Canonical IR

The IR sits at `result.pdf`, beside `result.document`. It carries effective settings, an ordered
outline of explicit and implicit sections, structured safe content blocks, `printableBlocks`, the
complete frontmatter map, and source positions. The renderer consumes that IR; it never guesses
heading meaning or reads frontmatter again.

### 2.5 Diagnostics

| Code | Severity | Meaning |
|---|---|---|
| `MDTO800` | error | `page-size` is not A4, Letter, or Legal. |
| `MDTO801` | error | `orientation` is not portrait or landscape. |
| `MDTO802` | error | `margins` is not compact, standard, or generous. |
| `MDTO803` | error | `style` is not editorial, report, or minimal. |
| `MDTO804` | error | Heading level is invalid. |
| `MDTO805` | error | A `##` print section has no name. |
| `MDTO806` | error | Document has no printable content. |

---

## 3. Rationale

**Why named page systems.** Free-form CSS is not portable application state; it is an unbounded
program with renderer-specific behavior. Three page boxes, three margin systems, and three art
directions cover the useful decisions while keeping conformance testable.

**Why HTML is the intermediate artifact.** It is inspectable, accessible, printable, and easy to
compare in a real browser. Generating PDF through the same page prevents a preview/print split where
the attractive screen version is not what the artifact contains.

**Why the browser is an adapter, not a hidden dependency of validation.** Parsing, validation,
inspection, and HTML rendering remain deterministic and offline on every machine. Only `build` needs
a browser, and it refuses before writing when one cannot be found.

**Relationship to the shared item model.** None. Lists, including task lists, are publication
content rather than addressable application items. A PDF verb never pins or mutates a list line.

---

## 4. Examples

```markdown
---
markdownto: pdf@0.1
title: Night garden field notes
page-size: A4
style: editorial
toc: true
---

# Night garden field notes

## First light

The moths leave before the color returns to the leaves.
```

`page-size: Tabloid` is `MDTO800` on its own frontmatter line.

---

## 5. Verb reference

`pdf@0.1` owns the vocabulary **build**.

| Verb | Signature | Source edit |
|---|---|---|
| `build` | `mdto pdf build [--out <file.pdf>] [--browser <path>]` | None. Renders and prints `<name>.pdf` through a local Chromium-family browser. |

`build` accepts `--out <file.pdf>` and `--browser <path>`, plus `--json`. The environment variable
`MDTO_CHROME` is the non-CLI equivalent of `--browser`. Default output is the Markdown basename with
`.pdf`; an existing target is replaced atomically only after a complete temporary PDF exists.

### Common flags

`--file <path>` · `--out <file.pdf>` · `--browser <path>` · `--json` · `--help`
