typst-pagemaker 0.1.22
Structured document-to-page layout system for Typst with explicit positioning and professional typography
Requires Python: >=3.9
Keywords: typst, orgmode, layout, grid, slides, pdf

# pagemaker

Please note: This project is in no way affiliated with or related to the old Aldus PageMaker program from the 90s.

A dual-export document layout system that transforms org-mode files into professional PDFs and web-optimized HTML.

**PDF Export:** Precise grid-based positioning with Typst's powerful typesetting engine for print-ready documents.

**HTML Export:** Grid-faithful web rendering with CSS Grid layouts that mirror PDF positioning, optimized for web viewing.

<p><img src="img/aesop.jpg" alt="Alt Text" width="45%"> <img src="img/aesop_with_debug_grid.jpg" alt="Alt Text" width="45%"></p>
The file examples/custom_styles_demo.org rendered without and with debug grid turned on. Note the custom font, the custom line spacing, the custom paragraph speration, thy hyphenation and the optional justification of the text. 


## Design Philosophy

**PDF Mode (Precision Layout):**

Unlike traditional document systems that rely on automatic text flow and built-in spacing, pagemaker takes a fundamentally different approach:

- **Every page is explicitly described** - no automatic page breaks or content flow
- **Every element is explicitly positioned** - precise grid-based placement using A1-style coordinates
- **Gutter-free grid system** - clean grid divisions with no built-in spacing between cells
- **Element-level padding** - fine-grained spacing control through per-element padding properties
- **Professional typography** - leverages Typst's advanced typesetting with three bundled professional fonts (Inter, Crimson Pro, JetBrains Mono)

This approach is ideal for creating presentations, posters, reports, and any document where you need pixel-perfect control over layout and positioning.

**HTML Export (Web Viewing):**

For web-focused output, HTML export provides maximum PDF fidelity in the browser:

- **Grid-faithful positioning** - CSS Grid layouts mirror PDF grid coordinates exactly
- **Per-page sections** - full-viewport pages with individual grid configurations
- **Web font support** - same fonts as PDF using WOFF2 web fonts
- **Customizable styling** - separate CSS/JS files for easy theming
- **Rich media support** - images, SVGs, PDFs, tables, lists

HTML export is ideal for creating web presentations, documentation, and any content that needs to match PDF layout while being viewable in browsers.

## Features

### Breaking Changes & Migration

**Media Embedding Updates:**
All media types (images, PDFs, SVGs) now support unified fit modes with consistent behavior.

**Current behavior (all media types):**
- All fit modes supported: `contain`, `cover`, `stretch`
- Cover mode works with alignment-based cropping for all media types
- Alignment properties (`:ALIGN:`, `:VALIGN:`) control positioning and visible region
- Intrinsic sizing automatically detected for all media types

**Migration steps:**
- Legacy `:PDF:` and `:SVG:` properties are deprecated—use `[[file:...]]` links (recommended) or `:SRC:` property
- All media types support native org-mode `[[file:...]]` link syntax
- Legacy `:PDF_ALIGN:` property was removed—use standard `:ALIGN:` / `:VALIGN:`

See the [Media Embedding](#media-embedding-images-pdfs-svgs) section for comprehensive documentation.

### Core Functionality

**Two Export Formats:**
- **PDF Export**: Org-mode to Typst to PDF conversion with precise grid-based positioning
- **HTML Export**: Org-mode to HTML conversion with CSS Grid layouts mirroring PDF positioning

**Common Features:**
- **Grid-based positioning**: Grid layout (e.g., 12x8) with A1-style areas, consistent across PDF and HTML
- **Element types**: Header, subheader, body text, image, PDF, SVG, rectangle, TOC
- **Z-order**: Element stacking control
- **Typography**: Professional fonts and theming
- **Watch mode**: Auto-rebuild on file/asset changes for both PDF and HTML

**When to Use Each Format:**

| Use Case | PDF Export | HTML Export |
|----------|----------|------------|
| Print documents | ✅ Best choice | ❌ Not suitable |
| Presentations (offline) | ✅ Precise control | ⚠️ Web only |
| Web presentations | ⚠️ Static PDF | ✅ Interactive, responsive |
| Documentation | ✅ Professional | ✅ Modern, searchable |
| Marketing materials | ✅ Print-ready | ✅ Web-optimized |
| Precise positioning required | ✅ Pixel-perfect | ✅ Grid-faithful CSS |
| Quick prototyping | ⚠️ Requires positioning | ✅ Same layout as PDF |
| Custom styling needed | ⚠️ Typst syntax | ✅ Standard CSS |

### Features
- **HTML Export**: Grid-faithful web rendering with CSS Grid layouts, web fonts, keyboard navigation, and customizable CSS/JS
- **Watch Mode**: Auto-rebuild on file/asset changes for both PDF and HTML export workflows
- **Snapshot Packaging**: Create self-contained packages with org file, assets, fonts, and PDF (like InDesign Package)
- **Unified media embedding**: Consistent interface for images, PDFs, and SVGs with full support for all fit modes (contain, cover, stretch), alignment-based cropping, captions, and intrinsic sizing
- **Cover mode support**: All media types support cover mode with alignment-based cropping—control which part is visible when media fills the frame
- **PDF embedding**: Native Typst PDF embedding with all fit modes, alignment, sanitize/fallback support, and precise intrinsic size detection
- **SVG support**: Vector graphics with viewBox-aware sizing, all fit modes, and perfect scaling at any resolution
- **Rectangles**: Colored overlays with alpha transparency, stroke, and corner radius
- **Debug grid**: Optional grid lines and labels for layout precision
- **Custom fonts**: Integrated font management with Google Fonts integration and project/bundled/system font discovery
- **Text justification**: `:JUSTIFY:` for header/subheader/body elements
- **Padding**: `:PADDING:` on all element types with CSS-like TRBL shorthand
- **Alignment & flow**: `:ALIGN:` / `:VALIGN:` for precise positioning within frames; `:FLOW:` for layout hints
- **Custom styles**: Per-document text styles with paragraph options (leading, spacing, indents)

### Supported Elements

| Element Type | Description | Properties |
|-------------|-------------|------------|
| `header` | Main headings | Font: Inter Bold, 24pt |
| `subheader` | Section headings | Font: Inter SemiBold, 18pt |  
| `body` | Regular text | Font: Inter Regular |
| `figure` | Images/media with captions | Supports all fit modes, captions, page selection |
| `pdf` | Vector PDF embedding | Contain-only scaling, captions, page selection |
| `svg` | SVG vector graphics | Contain-only scaling, intrinsic size detection |
| `rectangle` | Colored overlays | Color, alpha, stroke, radius |
| `toc` | Table of contents | Auto-lists slide titles |

**Media Elements:** See the [Media Embedding](#media-embedding-images-pdfs-svgs) section below for comprehensive documentation on fit modes, alignment, captions, and sizing behavior.

## Quick Start

### Installation
```bash
# Install from PyPI
pip install typst-pagemaker

# Verify installation
pagemaker --help
typst --version  # Ensure Typst is also installed
```

### Requirements

**Essential Dependencies:**
- **Typst** - The core typesetting engine. Install from [typst.app](https://typst.app/docs/tutorial/installation/)
- **MuPDF tools (mutool)** - Essential for PDF processing, SVG/PNG fallback generation, and `--sanitize-pdfs` functionality

**Optional Dependencies:**
- **qpdf** - Enhanced PDF repair and normalization  
- **Ghostscript (gs)** - Alternative PDF processing, PNG rendering, and **OutputIntent injection for PDF/A compliance**

Install platform-specific dependencies:
```bash
# macOS (via Homebrew)
brew install typst mupdf qpdf ghostscript

# Ubuntu/Debian
sudo apt update && sudo apt install typst-cli mupdf-tools qpdf ghostscript

# Arch Linux
sudo pacman -S typst mupdf-tools qpdf ghostscript

# Windows (via winget or chocolatey)
winget install --id Typst.Typst
# For MuPDF, download from: https://mupdf.com/releases/index.html
```

### Development Installation
```bash
# Clone the repository for development
git clone https://github.com/sanderboer/typst-pagemaker.git
cd typst-pagemaker

# Install in editable mode
pip install -e .
pagemaker --help
```

### Basic Usage (New Multi-Command CLI)

#### Watch Mode
Continuously rebuild output when the source Org file or referenced assets change.

**PDF/Typst Mode:**
```bash
# Rebuild typst on change
pagemaker watch examples/sample.org --export-dir export

# Build PDF on each change, keep intermediate .typ
pagemaker watch examples/sample.org --pdf --no-clean --export-dir export

# Single build (no loop) - useful for tests
pagemaker watch examples/sample.org --once --export-dir export
```

**HTML Export:**
```bash
# Auto-rebuild HTML on changes (inline CSS/JS)
pagemaker watch examples/sample.org --html-mode

# Auto-rebuild with separate CSS/JS files (recommended for development)
pagemaker watch examples/sample.org --html-mode --separate-assets

# Custom export directory
pagemaker watch document.org --html-mode --export-dir web/
```

Watch mode monitors your org file and all referenced assets (images, SVGs, PDFs via `[[file:...]]` links). When any file changes, output is automatically regenerated.

**Options:**
- `--interval <seconds>`: Polling interval (default 1.0)
- `--once`: Perform exactly one build then exit
- `--export-dir <path>`: Custom export directory (default: `export/`)

**PDF/Typst Mode Options:**
- `--pdf`: Also compile PDF each rebuild
- `--pdf-output <file>`: Custom PDF filename
- `--typst-bin <path>`: Path to `typst` binary
- `--no-clean`: Keep the intermediate `.typ` after PDF build
- `--update-html <path>`: Update existing HTML file's page count placeholder
- `--sanitize-pdfs`: Attempt to sanitize PDFs; if Typst compile still fails, auto-fallback to SVG or PNG for the requested page

**HTML Export Options:**
- `--html-mode`: Generate HTML export instead of PDF/Typst (watch mode)
- `--separate-assets`: Generate separate CSS/JS files (easier to customize)

```bash
# Build Typst from Org (org -> typst)
pagemaker build examples/sample.org -o deck.typ

# Build and produce PDF (cleans .typ by default)
pagemaker pdf examples/sample.org --pdf-output deck.pdf

# Build with PDF sanitize + fallback (qpdf/mutool/gs optional)
pagemaker pdf examples/sample.org --sanitize-pdfs --pdf-output deck.pdf

# Generate HTML Export (grid-faithful web rendering)
pagemaker html examples/sample.org
pagemaker html examples/sample.org --separate-assets  # Easier to customize

# Emit IR JSON to stdout
pagemaker ir examples/sample.org > ir.json

# Validate IR (non-zero exit on error)
pagemaker validate examples/sample.org
```

#### Commands Overview

| Command | Purpose | Output |
|---------|---------|--------|
| `watch` | Auto-rebuild on changes | PDF or HTML export |
| `html` | Generate web export | HTML with CSS/JS |
| `pdf` | Build PDF document | PDF file |
| `build` | Generate Typst code | .typ file |
| `snapshot` | Package document with assets | Self-contained directory |
| `ir` | Export intermediate representation | JSON to stdout |
| `validate` | Check document validity | Exit code (0=valid) |
| `fonts list` | Show available fonts | Font list |
| `fonts download` | Download Google Fonts | Font files |
| `fonts analyze` | Show document font usage | Usage report |

**Most Common Workflows:**
```bash
# Development: Live preview while editing
pagemaker watch document.org --html-mode --separate-assets    # Web (HTML)
pagemaker watch document.org --pdf                             # Print (PDF)

# Production: Final output
pagemaker html document.org --separate-assets            # Web
pagemaker pdf document.org --pdf-output final.pdf        # Print

# Package: Create self-contained snapshot
pagemaker snapshot document.org --output-dir ./snapshots # Complete package
```

### Snapshot: Package Documents with Assets

Create self-contained packages of your documents, similar to InDesign's "Package" feature. Perfect for archiving, sharing, or moving projects between systems.

**What's Included:**
- Original .org file with updated asset paths
- All referenced media assets (images, PDFs, SVGs)
- All fonts used in the document
- Compiled PDF output (optional)
- README with package metadata

**Basic Usage:**
```bash
# Create snapshot with PDF (default behavior)
pagemaker snapshot document.org --output-dir ./snapshots

# Create snapshot without PDF (faster)
pagemaker snapshot document.org --output-dir ./snapshots --no-build-pdf

# With custom Typst binary
pagemaker snapshot document.org --typst-bin /usr/local/bin/typst
```

**Output Structure:**
```
251128-document_snapshot/
├── document.org          # Updated with ./assets/ paths
├── document.pdf          # Compiled PDF (if built)
├── assets/               # All media files
│   ├── photo1.jpg
│   ├── diagram.svg
│   └── ...
├── fonts/                # All referenced fonts
│   ├── Inter-Regular.woff2
│   ├── Inter-Bold.woff2
│   └── ...
└── README.txt            # Package metadata
```

**Key Features:**
- **Self-contained**: Snapshot directory has everything needed to rebuild
- **Path updates**: Asset paths automatically updated to `./assets/...`
- **Font collection**: Captures all font variants (weights, styles)
- **PDF verification**: Tests that snapshot is self-contained by building PDF from it
- **Duplicate handling**: Files with same name from different dirs are preserved

**Use Cases:**
- Archive projects with all dependencies
- Share documents with collaborators
- Move projects between machines
- Create backup before major changes
- Package for external printing services

### PDF OutputIntent Injection (PDF/A Compliance)

Enhance PDF output with OutputIntent injection for professional print workflows and PDF/A compliance. This feature adds ICC color profiles to PDFs, improving color accuracy and meeting archival standards.

**Requirements:**
- **Ghostscript (gs)** - Required for OutputIntent injection (automatically detected)

**Basic Usage:**
```bash
# Inject sRGB OutputIntent (auto-discovers system sRGB profile)
pagemaker pdf examples/sample.org --inject-output-intent-srgb --pdf-output document.pdf

# Use custom ICC profile
pagemaker pdf examples/sample.org --icc-profile /path/to/profile.icc --pdf-output document.pdf

# Combine with PDF presets for print production
pagemaker pdf examples/sample.org --inject-output-intent-srgb --pdf-preset prepress --pdf-output document.pdf

# Works in watch mode too
pagemaker watch examples/sample.org --pdf --inject-output-intent-srgb --export-dir export
```

**Available Options:**
- `--inject-output-intent-srgb`: Automatically discovers and injects system sRGB ICC profile
- `--icc-profile <path>`: Inject custom ICC profile from specified file path
- `--pdf-preset <preset>`: Apply PDF optimization preset (`screen`, `printer`, `prepress`)

**PDF Presets:**
- `screen`: Optimized for digital display and web viewing
- `printer`: Balanced settings for general printing
- `prepress`: High-quality prepress settings for professional printing

**Graceful Fallback:**
- If Ghostscript is not available, the feature fails gracefully with a warning
- PDF generation continues normally, producing the original Typst PDF without OutputIntent
- This ensures builds don't break in environments without Ghostscript

**Use Cases:**
- **PDF/A compliance**: Required for long-term document archival
- **Print production**: Ensures consistent color reproduction across devices
- **Professional publishing**: Meeting industry standards for color management
- **Color-critical workflows**: Scientific documents, design work, photography

**Technical Details:**
- Supports automatic sRGB profile discovery on macOS, Linux, and Windows
- Uses Ghostscript for reliable OutputIntent injection
- Preserves all original PDF content and metadata
- Compatible with all pagemaker features (fonts, images, layouts, etc.)


Manual Typst compile (if you only produced .typ):
```bash
typst compile --root . --font-path assets/fonts --font-path assets/fonts/static export/deck.typ export/deck.pdf
```

Or use the Makefile targets:
```bash
make debug-overlay  # Build debug example
```

#### Asset Path Semantics
When exporting into an `export/` directory, any relative asset references in the Org file like:
```
[[file:assets/diagram.png]]
:PDF: assets/spec.pdf
:SVG: assets/graphics/logo.svg
```
are automatically rewritten so the generated `deck.typ` can reside in `export/` while still finding the assets in the project root. You can also use absolute paths if preferred.

#### Unified Media Source
Media elements (`figure`, `pdf`, `svg`) accept source paths via `[[file:...]]` links (preferred, native org-mode) or the `:SRC:` property. Precedence rules:
1. If `[[file:...]]` link exists in content, it is used (native org-mode syntax - **recommended**)
2. Else if `:SRC:` property is present and non-empty, it is used
3. Else legacy keys are used (`:PDF:` for pdf, `:SVG:` for svg - **deprecated**)
4. When both `:SRC:` and a legacy key are present, the legacy key is ignored (deprecation warning emitted)

**Recommended syntax (native org-mode):**
```org
** Vector Logo
:PROPERTIES:
:TYPE: svg
:END:
[[file:assets/graphics/logo.svg]]

** Plan Page 2
:PROPERTIES:
:TYPE: pdf
:PAGE: 2
:END:
[[file:assets/spec.pdf]]

** Cover Image
:PROPERTIES:
:TYPE: figure
:FIT: cover
:END:
[[file:assets/test-images/forest.jpg]]
```

**Alternative syntax (property-based):**
```org
** Vector Logo
:PROPERTIES:
:TYPE: svg
:SRC: assets/graphics/logo.svg
:END:
```

Both syntaxes work for all media types. Use `[[file:...]]` for consistency with org-mode conventions.

### Asset Path Resolver (Detailed Behavior)
All path rewriting is centralized in `AssetPathResolver` (`src/pagemaker/utils/assets_paths.py`). It converts element `figure`/`pdf`/`svg` `src` values into paths relative to the chosen export (`--export-dir`) so the `.typ` file can move independently of your assets.

Precedence (non-strict mode):
1. Absolute paths or protocol URLs (`/abs/path`, `https://...`) are passed through unchanged.
2. Invocation current working directory (the directory you run `pagemaker` from).
3. Source document directory (only used when caller supplies it; current CLI path does not pass this yet).
4. Project root (auto-detected by searching upward for `pyproject.toml` or `.git`).
5. Typst export directory (the directory that will contain `deck.typ`).
6. Examples fallback: if the unresolved relative path starts with `assets/`, the resolver also tries `<project_root>/examples/<src>`.
7. Best-effort rewrite: if still unresolved and non-strict, the relative path is mapped through the project root so that a stable relative reference is emitted instead of leaving it unchanged.

Strict mode difference: In strict mode (unused by CLI today) missing relative paths are left unchanged (they will likely cause a later failure) instead of being rewritten via best-effort mapping.

Caching: Resolutions are memoized per original `src` string for the lifetime of the resolver instance (improves large document builds).

Examples Fallback Use Case:
If you reference an asset that only exists under `examples/assets/...` (e.g. `[[file:assets/test-images/forest.jpg]]`) and you run the CLI from the project root, the resolver will rewrite the path to a relative traversal pointing into `examples/assets/...`. This lets example Org files stay portable without copying assets into the top-level `assets/` folder.

Debugging Path Decisions:
Set environment variable `PAGEMAKER_DEBUG_ASSET_PATHS=1` when running any CLI command to log each asset rewrite:
```
PAGEMAKER_DEBUG_ASSET_PATHS=1 pagemaker build examples/sample.org --export-dir export
```
Log lines look like:
```
[asset-path-debug] src='assets/test-images/forest.jpg' -> '../examples/assets/test-images/forest.jpg' (resolved:/absolute/path/to/examples/assets/test-images/forest.jpg)
```
Reason codes:
- `resolved:<absolute>`: Chosen candidate path existed.
- `unchanged-strict-or-absent`: Strict mode left path unchanged or no mapping was possible.

Absolute / Protocol Short-Circuit:
Values beginning with `/` or containing a protocol scheme (e.g. `https://`, `s3://`) bypass all rewriting and remain exactly as specified.

Best Practices:
- Prefer relative `assets/...` paths for portability (works with examples fallback).
- Use absolute paths only for external or system-managed locations.
- To troubleshoot a missing image/PDF/SVG, rerun with the debug flag and inspect which candidate actually resolved.

Future Enhancements:
- CLI may pass the source document directory to further prioritize colocated assets.
- Strict asset validation (`--strict-assets`) already exists on the `validate` subcommand for treating missing figure/pdf assets as errors (operates after rewriting).

### Example Org File

Dynamic helpers available in text:
- `#page_no` / `#page_total` for page counters (no parentheses; Typst context-based).
- Dates: `#date_iso` (YYYY-MM-DD), `#date_yy_mm_dd` (YY.MM.DD), `#date_dd_mm_yy` (DD.MM.YY)
- To lock dates for reproducible builds, set `#+DATE_OVERRIDE: YYYY-MM-DD` (or `#+DATE:`) in the Org meta header.

TOC element:
- Add a `toc` element to list slide titles automatically.
```org
** Table of Contents
:PROPERTIES:
:TYPE: toc
:AREA: A1,L8
:PADDING: 4,6
:END:
```


Text: use `:JUSTIFY:` to enable full justification and `:PADDING:` to inset content in millimeters.
(place this snippet in the examples folder in order for pagemaker to find the fonts and images that are already bundled in the examples/asset folder)

<div style="display: flex; justify-content: space-between; align-items: center;"><img src="img/example.jpg" alt="Alt Text" style="width: 48%;"></div>

```org
#+TITLE: My Presentation
#+PAGESIZE: A4
#+ORIENTATION: landscape
#+GRID: 12x8
#+GRID_DEBUG: false
#+STYLE_WHITE_BODY: font: Playfair Display,  color: #ffffff, size: 16pt, spacing: 20pt


* Introduction Slide
:PROPERTIES:
:ID: intro_slide
:END:

** Main Title
:PROPERTIES:
:TYPE: header
:AREA: b1,c4
:PADDING: 8,8
:JUSTIFY: 
:Z: 10
:END:
Welcome to pagemaker

** Background Rectangle
:PROPERTIES:
:TYPE: rectangle
:AREA: A1,L4
:COLOR: #3498db
:ALPHA: 0.2
:Z: -1
:END:

** Demo Image
:PROPERTIES:
:TYPE: figure
:AREA: A5, H12
:PADDING: 0,0,0,0
:FIT: cover
:Z: -1
:END:
[[file:assets/test-images/landscapes/landscape-1.jpg]]

** poem
:PROPERTIES:
:TYPE: body
:STYLE: white_body
:AREA: C7,D10
:valign: top
:END:

I am but a leaf

Clinging to the tree of life

In the world’s garden.

** poem
:PROPERTIES:
:TYPE: subheader
:STYLE: white_body
:AREA: E7,F10
:align: right
:valign: middle
:END:
Last night I saw you,

A dream rose and I your stem

Showing you the sun.

```

## Directory Structure

```
typst-pagemaker/
├── src/                    # Source code
│   ├── pagemaker/          # Package (parser, generator, CLI)
├── bin/                    # Build tools and scripts
│   ├── Makefile            # Build automation
│   └── debug_test_fonts.sh
├── examples/               # Example Org files and outputs
│   ├── assets/             # Fonts and test resources
│   │   ├── fonts/            # Downloaded fonts
│   │   ├── test-images/      # Sample images for testing
│   │   └── test-pdfs/        # Sample PDFs for testing
├── tests/          # Test suite
│   ├── unit/          # Unit tests
│   ├── integration/   # Integration tests
│   └── fixtures/      # Test data
└── docs/              # Documentation
```

## Quick Reference

### Common Element Properties

**PDF Mode:**
| Property | Values | Description |
|----------|--------|-------------|
| `:TYPE:` | `header`, `subheader`, `body`, `figure`, `pdf`, `svg`, `rectangle`, `toc` | Element type |
| `:AREA:` | `A1`, `B3,F5` | Grid position (A1 notation) |
| `:Z:` | `10`, `100` | Stacking order (higher on top) |
| `:PADDING:` | `4`, `2,4`, `2,4,6,8` | Margin in mm (CSS TRBL) |
| `:ALIGN:` | `left`, `center`, `right` | Horizontal alignment |
| `:VALIGN:` | `top`, `middle`, `bottom` | Vertical alignment (text + pdf elements) |
| `:JUSTIFY:` | (bare) or `true`/`false` | Full text justification |
| `:IGNORE:` | `true`, `false` | When `true`: drop this page (level 1) or this section and its subtree (level ≥2). If `:TYPE:` is missing or `none`, only the element is omitted; children still parse. |

**Story Mode:**
| Property | Values | Description |
|----------|--------|-------------|
| `:BACKGROUND:` | `path/to/image.jpg` | Full-section background image |
| `:STYLE:` | `background: #f0f0f0; color: #333;` | Custom CSS for section |
| `:IGNORE:` | `true`, `false` | Skip section in output |

**Both Modes:**
- Media links: `[[file:path/to/file.jpg]]` (recommended) or `:SRC:` property
- Captions: Text content in figure/media blocks
- Rich text: Bold `*bold*`, italic `/italic/`, code `~code~`, links `[[url][text]]`

### Page Setup Headers

**PDF Mode:**
| Header | Example | Description |
|--------|---------|-------------|
| `#+PAGESIZE:` | `A4`, `A3`, `A1` | Page size |
| `#+ORIENTATION:` | `landscape`, `portrait` | Page orientation |
| `#+GRID:` | `12x8`, `16x9` | Grid dimensions |
| `#+MARGINS:` | `10,15,10,15` | Margins in mm (TRBL) |
| `#+GRID_DEBUG:` | `true`, `false` | Show debug grid |

**Story Mode:**
| Header | Example | Description |
|--------|---------|-------------|
| `#+TITLE:` | `My Story` | Document title (optional) |

Story Mode ignores page size, orientation, grid, and margins settings. Layout is handled automatically.

### Element Types Quick Syntax
```org
** Header Text
:PROPERTIES:
:TYPE: header
:AREA: A1,F2
:END:

** Image
:PROPERTIES:
:TYPE: figure
:AREA: G1,L4
:FIT: contain
:END:
[[file:path/to/image.jpg]]

** PDF Page
:PROPERTIES:
:TYPE: pdf
:PAGE: 2
:AREA: A5,F8
:END:
[[file:path/to/doc.pdf]]

** Colored Rectangle
:PROPERTIES:
:TYPE: rectangle
:AREA: B2,K7
:COLOR: #3498db
:ALPHA: 0.3
:END:
```

## Configuration

### Page Setup
- **PAGESIZE**: A4, A3, A2, A1, A5
- **ORIENTATION**: landscape, portrait
- **GRID**: Custom grid dimensions (e.g., 12x8, 16x9)
- **MARGINS**: Absolute mm in CSS TRBL order (top,right,bottom,left)
- **GRID_DEBUG**: Show/hide debug grid lines
Notes:
- Typst page size is set once at the document level from the first rendered page’s `PAGESIZE` and `ORIENTATION`. Per-page overrides are ignored during Typst generation; the validator warns if pages disagree.
- `:AREA:` always addresses the total grid (including margin tracks); there is no `:COORDS:` directive.

### Element Properties

#### Ignore Semantics
- `:IGNORE: true` on a page (level 1) removes the entire page from the IR; following sections under that page are also ignored until the next page.
- `:IGNORE: true` on a section (level ≥2) removes that section and its entire subtree.
- If `:TYPE:` is omitted or explicitly set to `none`, the element itself is omitted from the IR but its children are still parsed/emitted if they declare a valid `:TYPE:`.

#### Validation Rules
The `validate` subcommand parses Org -> IR, then enforces structural rules.
Errors (fail the build):
- Duplicate page IDs
- Duplicate element IDs
- Rectangle alpha outside 0.0–1.0
- Area issues: non-positive dimensions or exceeding page grid bounds (when grid + area fully specified)

Warnings (reported but do not fail):
- Unknown element types (fallback treatment may change later)
- Missing figure or PDF asset file (relative path that does not exist when validating)

To escalate missing asset warnings into errors (e.g., for CI pipelines), use:
```
pagemaker validate --strict-assets examples/sample.org
```
This makes missing figure/pdf assets fail validation (non-zero exit code).

Example:
```
pagemaker validate examples/sample.org
```
Exit code 0 means no errors (warnings may still appear).
- **TYPE**: Element type (header, subheader, body, figure, pdf, rectangle)
- **AREA**: A1-style coordinates are preferred (e.g., single cell "B3" or range "A1,C2"). Rows are letters (A=1), columns are numbers. Legacy numeric "x,y,w,h" is still supported.
- **Z**: Stacking order (higher numbers appear on top)
- **COLOR**: Hex color for rectangles (#RRGGBB)
- **ALPHA**: Transparency (0.0 = transparent, 1.0 = opaque)
- **FIT**: Image fitting (contain, cover, fill)
- **PADDING**: Optional mm padding around content. CSS-like shorthand: `PADDING: t` | `t,r` | `t,r,b` | `t,r,b,l`. Applies to text (header/subheader/body), figures, SVG, and PDF.
- **JUSTIFY**: Optional boolean for text elements. `:JUSTIFY:` (bare) or `:JUSTIFY: true` enables full justification; `false` disables. Maps to Typst `par(justify: true)` wrapping.
- **ALIGN**: Horizontal alignment within the element frame. Values: `left`, `center`, `right`. Applies to text (`header`, `subheader`, `body`) and media (`figure`, `svg`, `pdf`, `toc`).
- **VALIGN**: Vertical alignment within the element frame. Values: `top`, `middle`, `bottom`. Applies to text elements. Note: `middle` maps to Typst `horizon` (Typst’s vertical-center token).
- **FLOW**: Layout hint for text elements. Values: `normal`, `bottom-up`, `center-out`. Emitted as a comment for visibility, and when `:VALIGN:` is not set it can imply vertical alignment: `bottom-up` -> `bottom`, `center-out` -> `horizon`. Otherwise, explicit `:VALIGN:` wins.

## Tooling

**Essential external tools:**
- `typst`: Required for all document compilation
- `mutool` (MuPDF): Essential for PDF processing, SVG/PNG fallback generation, and full `--sanitize-pdfs` functionality

**Optional external tools** that enhance PDF handling with `--sanitize-pdfs`:
- `qpdf`: Repairs and normalizes PDF structure (stream recompress, object streams)
- `gs` (Ghostscript): Alternate PDF distillation and PNG fallback rendering

The CLI automatically detects these tools. If unavailable, related stages are skipped, but missing essential tools will limit core functionality.

## Advanced Usage

See the in-depth guide: docs/master_styles.md (styles, paragraph options, master pages, margins/grid, and padding semantics including zero-sum).

### Custom Styles
- Declare styles in document meta using `#+STYLE_<NAME>:` where `<NAME>` is case-insensitive. Built-ins: `HEADER`, `SUBHEADER`, `BODY`.
- Supported keys (case-insensitive) with aliases:
  - font | font-family
  - weight | font-weight (numeric or names like bold, semibold)
  - size | font-size (Typst units like `pt`, `em`)
  - color | colour | fill (supports `#hex`, `rgb(...)`, `hsl(...)`, or named)
- Use a style on an element by setting `:STYLE:` to the style name (e.g., `hero`). If omitted, the element’s type is used as the style key (`header`, `subheader`, `body`).
- Commas inside parentheses are handled correctly (e.g., `rgb(50%,50%,50%)`).

Example:
```org
#+STYLE_HEADER: font: Inter, weight: 900, size: 30pt, color: #ff00aa
#+STYLE_BODY: font: Inter, color: rgb(50%,50%,50%)
#+STYLE_HERO: font: Inter, weight: bold, size: 36pt, color: #123456

* Title
:PROPERTIES:
:TYPE: header
:AREA: 1,1,6,1
:END:
My Header

** Big Title
:PROPERTIES:
:TYPE: body
:STYLE: hero
:AREA: 1,2,12,2
:END:
Big Title
```
See `examples/custom_styles_demo.org` for a complete, runnable example.

#### Paragraph Options
- Style declarations may also include paragraph settings applied via Typst `par(...)`:
  - `leading`: Line leading (Typst length, e.g., `1.4em`, `14pt`).
  - `spacing`: Space between paragraphs (length).
  - `first-line-indent` (or `first_line_indent`): Indent the first line (length).
  - `hanging-indent` (or `hanging_indent`): Hanging indent for subsequent lines (length).
  - `linebreaks`: Typst line-breaking mode token (e.g., `auto`, `loose`, `strict`).
  - `justify`: Boolean or token; when set, maps to `justify: true|false`.
- Element-level `:JUSTIFY:` always overrides the style’s `justify` value.

Paragraphs are split by:
- Blank lines
- Lines that are exactly `---` or `:::`

If a text block splits into multiple paragraphs, each paragraph is wrapped with `par(...)`. Paragraphs are concatenated without extra blank lines; the visible gap is controlled by the style’s `spacing` value. If `spacing` is omitted, the next paragraph appears as a line break with minimal separation. When there is a single paragraph and no paragraph options or justification are set, the text is emitted without a `par(...)` wrapper for backward compatibility.

Example (Org):
```org
#+STYLE_BODY: font: Inter, leading: 1.4em, spacing: 1em, first-line-indent: 2em, hanging-indent: 1em, linebreaks: loose, justify: false

** Styled Body
:PROPERTIES:
:TYPE: body
:AREA: A1,L8
:JUSTIFY: true   # element-level override
:END:
First paragraph line one.

---
Second paragraph, now with the style’s paragraph options and justify enabled.
```

### Custom Fonts
The package includes professional bundled fonts as a reliable default, with support for rich project-specific font libraries.

**Font Resolution Order:**
1. **Project fonts**: `assets/fonts/` (custom library checked first)  
2. **Bundled fonts**: Package-included minimal defaults (Inter, Crimson Pro, JetBrains Mono)
3. **System fonts**: Typst automatically discovers installed system fonts (final fallback)

**Bundled Fonts (Always Available):**
- **Inter**: Modern sans-serif optimized for screens and interfaces
- **Crimson Pro**: Professional serif for body text and academic documents  
- **JetBrains Mono**: Code-friendly monospace with excellent readability

**Project Font Library:**
```bash
# Add custom fonts to your project
mkdir -p assets/fonts/FontFamily
cp path/to/FontFamily-*.ttf assets/fonts/FontFamily/

# Fonts are automatically discovered and available in your documents
```

**Font Management CLI:**
```bash
# List all available fonts
pagemaker fonts list-all

# Show bundled fonts only
pagemaker fonts list-bundled --details

# Show project fonts only  
pagemaker fonts list-project --details

# Validate specific font availability
pagemaker fonts validate "Inter"
pagemaker fonts validate "Your Custom Font"
```

**Using Custom Fonts:**
```org
# Reference any available font in your documents
#+CUSTOM_STYLE: #set text(font: "Your Custom Font", size: 12pt)

* Heading with Custom Typography
#set text(font: "Playfair Display", weight: "bold", size: 18pt)

This heading uses a custom display font for elegant typography.

#set text(font: "Inter")
This paragraph switches back to the reliable bundled Inter font.
```

**Font Discovery:**
The system automatically includes all font paths in the correct precedence order. Project fonts in `assets/fonts/` take priority over bundled fonts, ensuring reliable defaults with easy customization.

## Font Management System

The pagemaker CLI includes a comprehensive font management system to help discover, install, analyze, and preview fonts in your projects.

### Font Discovery and Listing

List all fonts available to your project:
```bash
# Show all available fonts (project + bundled + system)
pagemaker fonts list-all

# Show only bundled fonts with details
pagemaker fonts list-bundled --details

# Show only project fonts with details  
pagemaker fonts list-project --details

# Validate specific font availability
pagemaker fonts validate "Inter"
pagemaker fonts validate "Playfair Display"
```

### Google Fonts Integration

Search and install fonts directly from Google Fonts:
```bash
# Search for fonts by name
pagemaker fonts search "Playfair"
pagemaker fonts search "mono" --limit 10

# Install fonts to your project
pagemaker fonts install "Playfair Display"
pagemaker fonts install "JetBrains Mono" --variants regular,700,italic

# Clear font installation cache
pagemaker fonts cache-clear
```

**Installation Details:**
- Fonts are downloaded from Google Fonts API with offline fallback for popular fonts
- Installed to `assets/fonts/FontFamily/` directory structure
- Supports variant selection (regular, 700, italic, etc.)
- Automatically creates proper directory structure

### Font Usage Analysis

Analyze your documents to find font references and check availability:
```bash
# Analyze font usage in a document
pagemaker fonts analyze examples/sample.org

# Analyze with installation suggestions for missing fonts
pagemaker fonts analyze examples/font_management_demo.org
```

**Analysis Features:**
- Detects fonts referenced in `#+CUSTOM_STYLE` and `#set text(font: "Name")` patterns
- Cross-references with available font inventory from all sources
- Provides installation suggestions for missing fonts
- Shows font availability status (✓ Available, ✗ Missing)

### Font Specimen Generation

Generate font showcase documents to preview and compare fonts:
```bash
# Generate comprehensive font specimen
pagemaker fonts specimen my-fonts.org

# Generate simple comparison format
pagemaker fonts specimen fonts-comparison.org --format comparison

# Generate simple list format  
pagemaker fonts specimen fonts-list.org --format simple

# Auto-build PDF after generating specimen
pagemaker fonts specimen my-fonts.org --build-pdf
```

**Specimen Formats:**
- **showcase** (default): Detailed specimens with multiple text samples and sizes
- **comparison**: Side-by-side comparison with consistent sample text
- **simple**: Minimal list format with basic font information

### Build-Time Font Validation

Integrate font validation into your build process:
```bash
# Build with font validation (warnings only)
pagemaker build examples/sample.org --validate-fonts

# Build with strict font validation (fails on missing fonts)  
pagemaker pdf examples/sample.org --strict-fonts --pdf-output output.pdf

# Watch mode with font validation
pagemaker watch examples/sample.org --validate-fonts --pdf
```

**Validation Features:**
- Scans document for font references during build
- Reports missing fonts with helpful error messages
- Suggests installation commands for missing Google Fonts
- `--validate-fonts`: Shows warnings but continues build
- `--strict-fonts`: Fails build on missing fonts (useful for CI/CD)

### Performance Optimization

The font system includes caching for improved performance:
- **Font discovery caching**: Results cached for 5 minutes to speed up repeated operations
- **Google Fonts API caching**: Downloaded font lists cached locally
- **Cache invalidation**: Automatically detects font directory changes
- **Graceful fallback**: Continues operation if caching fails

### Font Management Examples

**Complete workflow for adding a new font:**
```bash
# 1. Search for desired font
pagemaker fonts search "Crimson"

# 2. Install the font
pagemaker fonts install "Crimson Pro"

# 3. Verify installation
pagemaker fonts validate "Crimson Pro"

# 4. Generate specimen to preview
pagemaker fonts specimen fonts-preview.org --format showcase

# 5. Use in your document
echo '#+CUSTOM_STYLE: #set text(font: "Crimson Pro", size: 12pt)' >> my-doc.org

# 6. Build with font validation
pagemaker pdf my-doc.org --validate-fonts --pdf-output my-doc.pdf
```

**Analyzing and fixing font issues:**
```bash
# Analyze document for font problems
pagemaker fonts analyze problematic-doc.org

# Output might show:
# ✗ Missing: "Custom Font" - try: pagemaker fonts install "Custom Font"
# ✓ Available: "Inter"

# Install missing fonts as suggested
pagemaker fonts install "Custom Font"

# Rebuild with validation
pagemaker pdf problematic-doc.org --strict-fonts --pdf-output fixed-doc.pdf
```

### Media Embedding (Images, PDFs, SVGs)

pagemaker provides a unified media embedding system with powerful sizing and alignment controls. All media types share a consistent property interface and support advanced features like fit modes, alignment, and captions.

#### Unified Media Properties

All media elements (`figure`, `pdf`, `svg`) support these common properties:

| Property | Values | Description |
|----------|--------|-------------|
| `[[file:...]]` | Path or URL | Native org-mode link syntax (**recommended**) |
| `:SRC:` | Path or URL | Alternative property-base