Skip to main content

Structured document-to-page layout system for Typst with explicit positioning and professional typography

Project description

pagemaker

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

A structured document-to-page layout system for Typst that gives you complete control over element positioning while leveraging Typst's powerful typesetting engine and variable weight font support.

Alt Text Alt Text

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

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.

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 :SRC: instead
  • Figure elements still accept [[file:...]] links but :SRC: is preferred
  • Legacy :PDF_ALIGN: property was removed—use standard :ALIGN: / :VALIGN:

See the Media Embedding section for comprehensive documentation.

Core Functionality

  • Org-mode to Typst conversion (optional): Converts Org documents to Typst
  • Grid-based positioning: Grid layout (e.g., 12x8) with A1-style areas
  • Element types: Header, subheader, body text, image, PDF, rectangle, TOC
  • Z-order: Element stacking control
  • Typography: Fonts and basic theming

Features

  • 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 section below for comprehensive documentation on fit modes, alignment, captions, and sizing behavior.

Quick Start

Installation

# 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
  • 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:

# 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

# 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 Typst (and optionally PDF) when the source Org file changes.

# 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

Options:

  • --interval <seconds>: Polling interval (default 1.0)
  • --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
  • --once: Perform exactly one build then exit
  • --sanitize-pdfs: Attempt to sanitize PDFs; if Typst compile still fails, auto-fallback to SVG or PNG for the requested page
# 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

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

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

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:

# 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):

typst compile --root . --font-path assets/fonts --font-path assets/fonts/static export/deck.typ export/deck.pdf

Or use the Makefile targets:

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 (:SRC:)

Media elements (figure, pdf, svg) now accept a unified :SRC: property for their primary asset path. Precedence rules:

  1. If :SRC: is present and non-empty it is used.
  2. Else legacy keys are used (:PDF: for pdf, :SVG: for svg), or for figures a single [[file:...]] link.
  3. When both :SRC: and a legacy key are present, the legacy key is ignored (deprecation warning emitted).
  4. Using only :PDF: or :SVG: emits a deprecation warning advising migration to :SRC:.

Examples:

** Vector Logo
:PROPERTIES:
:TYPE: svg
:SRC: assets/graphics/logo.svg
:END:

** Plan Page 2
:PROPERTIES:
:TYPE: pdf
:SRC: assets/spec.pdf
:PAGE: 2
:END:

** Cover Image
:PROPERTIES:
:TYPE: figure
:SRC: assets/test-images/forest.jpg
:FIT: cover
:END:

Figure elements still accept a lone [[file:...]] link when :SRC: is omitted, but new documents should prefer explicit :SRC: for consistency.

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.
** 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)

Alt Text
#+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

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.

Page Setup Headers

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

Element Types Quick Syntax

** 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
:PDF: path/to/doc.pdf
:PAGE: 2
:AREA: A5,F8
:END:

** 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:

#+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):

#+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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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
:SRC: Path or URL Primary asset path (replaces legacy :PDF: / :SVG:)
:FIT: contain, cover, stretch How media scales within its frame
:ALIGN: left, center, right Horizontal alignment within frame
:VALIGN: top, middle, bottom Vertical alignment within frame
:PADDING: 4, 2,4, 2,4,6,8 Internal padding in mm (CSS TRBL)
:CAPTION: Text Caption text (figure and pdf)
:PAGE: Number Select page from multi-page PDF (figure and pdf)
:Z: Number Stacking order

Migration Note: Legacy :PDF: and :SVG: properties are deprecated. Use :SRC: instead. Figure elements can still use [[file:...]] links but :SRC: is recommended for consistency.

Fit Modes Explained

The :FIT: property controls how media scales to fill its frame (defined by :AREA: minus :PADDING:):

contain (default): Scales media to fit completely within the frame while preserving aspect ratio. Media is centered with empty space (letterboxing) if aspect ratios don't match. Use :ALIGN: and :VALIGN: to reposition within the frame.

** Logo (centered, no cropping)
:PROPERTIES:
:TYPE: figure
:SRC: assets/logo.png
:FIT: contain
:AREA: B2,D4
:END:

cover: Scales media to completely fill the frame while preserving aspect ratio. Media is cropped if aspect ratios don't match. Use :ALIGN: and :VALIGN: to control which part is visible.

** Hero Image (fills area, crops edges)
:PROPERTIES:
:TYPE: figure
:SRC: assets/hero.jpg
:FIT: cover
:ALIGN: center
:VALIGN: middle
:AREA: A1,L4
:END:

stretch: Distorts media to exactly match frame dimensions, ignoring aspect ratio. Rarely needed but useful for precise graphic alignment.

** Exact Fit (may distort)
:PROPERTIES:
:TYPE: figure
:SRC: assets/bg-pattern.png
:FIT: stretch
:AREA: A1,L8
:END:

Alignment Behavior

Alignment properties control positioning within the element frame:

  • Without alignment (default): Media is centered in the frame
  • With :ALIGN: / :VALIGN:: Media is positioned accordingly
    • contain mode: Controls placement of letterboxed media
    • cover mode: Controls which part of the cropped media is visible

Cover Mode Cropping Details:

In cover mode, media is scaled to completely fill the frame, and overflow is cropped. Alignment determines which part remains visible:

  • Horizontal alignment (:ALIGN:):

    • left: Left edge visible, right edge cropped
    • center: Center visible, both edges cropped equally (default)
    • right: Right edge visible, left edge cropped
  • Vertical alignment (:VALIGN:):

    • top: Top visible, bottom cropped
    • middle: Middle visible, top and bottom cropped equally (default)
    • bottom: Bottom visible, top cropped

Example: Cover mode with alignment to focus on specific area:

** Portrait Photo (focus on face)
:PROPERTIES:
:TYPE: figure
:SRC: assets/portrait.jpg
:FIT: cover
:ALIGN: center
:VALIGN: top    # Keep top portion visible (face)
:AREA: C2,E6
:END:

Example: Landscape photo with left-aligned crop:

** Landscape (focus on left side)
:PROPERTIES:
:TYPE: figure
:SRC: assets/landscape.jpg
:FIT: cover
:ALIGN: left    # Keep left edge visible
:VALIGN: middle
:AREA: B3,F5
:END:

Media Type Reference

Figure Elements (figure): For raster images and general media embedding

  • Supports: JPG, PNG, WebP, SVG, PDF
  • Supports all fit modes
  • Can include captions and page selection
  • Use for: Photos, illustrations, diagrams
** Product Photo
:PROPERTIES:
:TYPE: figure
:SRC: assets/product.jpg
:FIT: cover
:CAPTION: Premium Widget - Model XL
:AREA: B2,F6
:END:

PDF Elements (pdf): For embedded PDF pages with precise sizing

  • Supports all fit modes (contain, cover, stretch)
  • Intrinsic PDF page size is detected (MediaBox dimensions)
  • Supports captions, page selection, and alignment-based cropping
  • Use for: Technical drawings, multi-page documents, vector artwork
** Technical Specification
:PROPERTIES:
:TYPE: pdf
:SRC: assets/spec.pdf
:PAGE: 2
:FIT: contain
:CAPTION: System Architecture Diagram
:AREA: D2,I6
:END:

Cover Mode Example: PDF cropped to fill area with alignment control:

** Blueprint Detail
:PROPERTIES:
:TYPE: pdf
:SRC: assets/plans.pdf
:FIT: cover
:ALIGN: left
:VALIGN: top
:AREA: C3,H7
:END:

SVG Elements (svg): For vector graphics with intrinsic sizing

  • Automatically detects viewBox and intrinsic dimensions
  • Supports all fit modes (contain, cover, stretch)
  • Preserves vector sharpness at any scale
  • Use for: Logos, icons, diagrams, technical illustrations
** Vector Logo
:PROPERTIES:
:TYPE: svg
:SRC: assets/logo.svg
:FIT: contain
:ALIGN: center
:VALIGN: middle
:AREA: A1,C2
:END:

SVG Sizing: The system intelligently detects SVG intrinsic size from viewBox, width, height attributes, and falls back to content bounding box analysis for proper scaling.

Cover Mode Example: SVG cropped to fill area with alignment:

** Icon Background
:PROPERTIES:
:TYPE: svg
:SRC: assets/pattern.svg
:FIT: cover
:ALIGN: center
:AREA: B2,D4
:END:

Caption Handling

Both figure and pdf elements support captions:

** Captioned Image
:PROPERTIES:
:TYPE: figure
:SRC: assets/chart.png
:FIT: contain
:CAPTION: Q4 Sales Performance - Up 23% YoY
:AREA: A5,F8
:END:

Caption Behavior:

  • Captions appear below the media
  • Caption space (5mm) is automatically reserved from the frame height
  • Alignment properties apply to both media and caption
  • Works with all fit modes

Media Consolidation Features

The unified architecture allows flexible cross-type capabilities:

  • PDFs in figures: Use figure with :PAGE: to embed PDF pages
  • Captions on PDFs: Use pdf with :CAPTION: for captioned document pages
  • Consistent properties: All types use :SRC:, :ALIGN:, :VALIGN:, :PADDING:
  • Semantic choice: Choose type based on intent (image vs. document) rather than capabilities

Common Patterns

Full-bleed background image:

** Background
:PROPERTIES:
:TYPE: figure
:SRC: assets/texture.jpg
:FIT: cover
:AREA: A1,L8
:Z: -10
:END:

Contained logo with padding:

** Company Logo
:PROPERTIES:
:TYPE: svg
:SRC: assets/logo.svg
:FIT: contain
:PADDING: 10
:ALIGN: center
:VALIGN: middle
:AREA: A1,B2
:END:

PDF page with specific focus:

** Blueprint Detail
:PROPERTIES:
:TYPE: pdf
:SRC: assets/plans.pdf
:PAGE: 3
:ALIGN: left
:VALIGN: top
:AREA: C3,H7
:CAPTION: Ground Floor Detail
:END:

Troubleshooting Media Issues

For problematic PDFs, use the --sanitize-pdfs flag:

pagemaker pdf document.org --sanitize-pdfs --pdf-output output.pdf

If sanitization fails, pagemaker automatically falls back to SVG (preferred) or PNG conversion for the requested page. Fallback assets are written to export_dir/assets/pdf-fallbacks/.

For missing media, use strict validation:

pagemaker validate document.org --strict-assets

See examples/test_image_fit.org for a comprehensive comparison of fit modes across different media types.

Colored Rectangles

Create transparent overlays and design elements:

** Background Accent
:PROPERTIES:
:TYPE: rectangle
:AREA: B2,I6
:COLOR: #FF6B6B
:ALPHA: 0.3
:Z: 10
:END:

Rectangle style keys and behavior:

  • color: fill color (#hex, rgb(...), hsl(...), named)
  • alpha: 0.0–1.0 (values outside are clamped during generation)
  • stroke: length with unit (pt|mm|cm|in)
  • stroke_color: stroke color; when omitted but stroke is set, falls back to fill color
  • radius: corner radius (length with unit)

Emission rules:

  • Minimal: ColorRect("<color>", <alpha>) when no stroke/radius provided
  • Any optional set: ColorRect(..., stroke: ..., stroke_color: ..., radius: ...)
  • Radius-only: emits stroke: none, stroke_color: none with provided radius

Margins

Define outer margins in millimeters that expand the total grid while keeping your content coordinates stable. Format: top,right,bottom,left (CSS TRBL order).

#+GRID: 12x8
#+MARGINS: 10,15,10,15

* Slide
:PROPERTIES:
:ID: s1
:END:

** Full-bleed background (uses margin tracks)
:PROPERTIES:
:TYPE: rectangle
:AREA: 1,1,14,10
:COLOR: #3498db
:ALPHA: 0.1
:END:

** Content inside margins
:PROPERTIES:
:TYPE: body
:AREA: A1,L8
:END:
The content grid remains 12x8, but the total grid has one margin track on each side. Content coordinates map to total with a +1,+1 offset when margins are present.

Notes:

  • MARGINS values are absolute sizes in mm.
  • :AREA: always addresses the total grid (including margin tracks). The content grid remains your declared GRID inside the margins; when margins are present, content coordinates map to total with a +1,+1 offset.
  • With #+GRID_DEBUG: true, the overlay shows the total grid (including margin tracks). Labels cover all tracks: first column is 1, first row is A.

Master Pages

See examples/master_pages_demo.org for a runnable master page setup.

Define reusable element sets as master pages that are not directly rendered. Apply them per slide with :MASTER: or globally with #+DEFAULT_MASTER:.

#+DEFAULT_MASTER: Base

* Base Master (not rendered)
:PROPERTIES:
:MASTER_DEF: Base
:END:

** Header Bar
:PROPERTIES:
:TYPE: rectangle
:AREA: A1,A12
:COLOR: #000000
:ALPHA: 0.08
:END:

** Footer Text
:PROPERTIES:
:TYPE: body
:AREA: H11,H12
:END:
Page #page_no / #page_total — #date_dd_mm_yy

* Slide One (inherits Base)
:PROPERTIES:
:ID: s1
:END:

** Title
:PROPERTIES:
:TYPE: header
:AREA: B2,C11
:END:
Welcome with Master

Notes:

  • Pages that define :MASTER_DEF: are used as master definitions and are skipped at render time.
  • Slides can reference a master via per-page :MASTER: or inherit from #+DEFAULT_MASTER:.
  • Master elements are combined with slide elements and z-ordered together.

A1 AREA Notation

  • Rows are letters A..Z, then AA, AB, etc. (case-insensitive). A maps to row 1.
  • Columns are numbers starting at 1.
  • Single cell: "B3" -> [x=3, y=2, w=1, h=1].
  • Range: "A1,C2" -> inclusive rectangle normalized to top-left/bottom-right yielding [x=1, y=1, w=2, h=3].
  • Reverse ranges like "C2,A1" are normalized the same as "A1,C2".
  • Legacy format "x,y,w,h" remains supported for backward compatibility.
  • Debug grid labels: columns show 1..N at top; rows show a..z at left (rows > 26 currently fall back to numeric display).

Editor Integration (Emacs)

pagemaker ships a CLI, and an optional Emacs minor mode (org-pagemaker) to drive the CLI from Org buffers. This section shows how to install and use it.

Requirements

  • Emacs 27 or newer recommended
  • Optional: hydra package (for the in-buffer command menu)
  • pagemaker CLI available on PATH (pip install typst-pagemaker)

Install via straight.el

;; Stable: pin to a released tag (recommended)
(use-package org-pagemaker
  :straight (org-pagemaker
             :type git
             :host github
             :repo "sanderboer/org-pagemaker"
             :tag "v0.1.2"         ;; pin to a release tag (if available)
             :files ("lisp/*.el"))
  :hook (org-mode . org-pagemaker-mode))


;; (use-package org-pagemaker
;;   :straight (org-pagemaker :type git :host github :repo "sanderboer/org-pagemaker" :files ("lisp/*.el"))
;;   :hook (org-mode . org-pagemaker-mode))

Notes:

  • The Emacs package is developed in a separate repo; this project’s .gitignore ignores any nested pagemaker-el/ checkout under the root.
  • Ensure the pagemaker executable resolves in Emacs (M-: (executable-find "pagemaker")). If needed, adjust exec-path or your shell init for GUI Emacs.

Keybindings (org-pagemaker-mode)

  • C-c p h: Show the org-pagemaker Hydra (if hydra is installed)
  • C-c p b: Build Typst (.typ)
  • C-c p p: Build PDF
  • C-c p w: Watch and rebuild on save
  • C-c p v: Validate IR
  • C-c p s: Build with PDF sanitize/fallback
  • C-c p o: Open last output (PDF/Typst)
  • C-c p i: Insert example/template

The Hydra is an optional convenience. If hydra is not present, C-c p h displays a helpful message; all other keybindings continue to work.

Quick check

  1. Open any of the example .org files in this repo
  2. Enable the mode: M-x org-pagemaker-mode
  3. Run C-c p b to generate a .typ into export/ (or use C-c p p for a PDF if Typst is installed)

Pinning and upgrades

  • Prefer pinning to a stable tag (e.g., :tag "v0.1.2" when available).
  • To update: bump the :tag or track main and run straight-pull followed by straight-rebuild.

Development

Running Tests

make test
# or
python -m unittest discover tests -v
  • The suite includes an optional PDF compile test that runs pagemaker pdf end-to-end and compiles via Typst. It automatically skips if typst is unavailable.

Code Style & Pre-commit

This project uses pre-commit with Ruff for formatting and linting.

Setup:

pip install pre-commit
pre-commit install

Run hooks on the entire repo:

pre-commit run --all-files

Tools:

  • Formatter: Ruff formatter (ruff-format)
  • Linter: Ruff check with autofix

Current temporary linter ignores (to keep commits unblocked):

  • E501 (line length) — many long Typst/doc lines
  • B028, B007 — non-critical warnings
  • UP006, UP035 — typing modernization postponed
  • F841 — temporary allowance for unused variables

Run Ruff manually:

ruff format .
ruff check . --fix

We plan to remove the temporary ignores as the codebase is modernized.

Contributing

  1. Fork the repository at https://github.com/sanderboer/typst-pagemaker
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

Author

Created for building Typst-based slide decks from Org-mode.


For more detailed documentation, examples, and advanced usage patterns, see the docs/ directory and examples/ folder.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typst_pagemaker-0.1.19.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typst_pagemaker-0.1.19-py3-none-any.whl (1.4 MB view details)

Uploaded Python 3

File details

Details for the file typst_pagemaker-0.1.19.tar.gz.

File metadata

  • Download URL: typst_pagemaker-0.1.19.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for typst_pagemaker-0.1.19.tar.gz
Algorithm Hash digest
SHA256 68f08f44bf6cac4b9e0481293c88ea18679d73566e40c149111a92bc06c08e45
MD5 5e7bb7d5b87b1f19db2ec69b821cd28b
BLAKE2b-256 015e4e542056d464dbd2cd28f9b96159292605e2f05ba70ae97c20907c14f0eb

See more details on using hashes here.

File details

Details for the file typst_pagemaker-0.1.19-py3-none-any.whl.

File metadata

File hashes

Hashes for typst_pagemaker-0.1.19-py3-none-any.whl
Algorithm Hash digest
SHA256 3fc3de7017efff774e5bb9353fd1018ed6c17c755b71aa0666f202245e830697
MD5 e4c275f9e52b3ce8805e0c866118079f
BLAKE2b-256 1ee17d88d0ee87b8e0cbffb1f436f9a80af22617895d7104a97cfd2cc352e94b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page