| Name | typst-pagemaker JSON |
| Version |
0.1.18
JSON |
| download |
| home_page | None |
| Summary | Structured document-to-page layout system for Typst with explicit positioning and professional typography |
| upload_time | 2025-10-09 10:34:53 |
| maintainer | None |
| docs_url | None |
| author | Project |
| requires_python | >=3.9 |
| license | None |
| keywords |
typst
orgmode
layout
grid
slides
pdf
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# 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.
<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
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
### Migration Notice (Breaking Change)
PDF embedding now always uses automatic contain scaling (legacy `:FIT:` modes and the `:FULL_PAGE:` flag for `pdf` elements were removed). A previously documented optional `:SCALE:` multiplier is currently ignored and will emit a warning when specified.
New behavior (pdf elements only):
- The system computes a base auto-contain scale so the intrinsic PDF page fits entirely within the element's padded frame (respecting margins + element `:PADDING:`).
- User `:SCALE:` values (if present in older documents) are ignored for now (warning emitted). Future releases may reintroduce controlled fit modes.
- Result: PDFs never overflow their frame via scale; enlarge the `:AREA:` to show more context.
Migration:
- Remove any `:FIT:` / `:FULL_PAGE:` properties on `pdf` elements (ignored if still present).
- If you previously relied on `:FIT: contain` just delete it (behavior now default). If you relied on oversizing via `:FIT: fill` or manual big areas, you may enlarge the `:AREA:` instead; scale no longer exceeds containment.
- Image `figure` elements still support `:FIT:` (contain|cover|fill) unchanged.
- Legacy per-PDF alignment property (`pdf_align` / `:PDF_ALIGN:`) has been removed; use the standard `:ALIGN:` / `:VALIGN:` properties on `pdf` elements.
See the Vector PDF Embedding section below for details and examples.
### 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
- **PDF embedding**: MuchPDF integration with sanitize/SVG/PNG fallback
- **Rectangles**: Colored overlays with alpha transparency; optional stroke, stroke_color fallback, and corner radius
- **Images**: Fit modes (contain, cover, fill) and captions
- **Debug grid**: Optional grid lines and labels (columns 1..N, rows a..z)
- **Custom fonts**: Integrated font management system with Google Fonts integration
- **Text justification**: `:JUSTIFY:` for header/subheader/body (wraps Typst `par(justify: true)`)
- **Padding**: `:PADDING:` on text, images, SVG, and PDF (CSS-like TRBL shorthand in mm; per-side padding inherits and accumulates; if totals cancel to 0mm on all sides, generator still emits padded placement).
- **Alignment & flow**: `:ALIGN:` (left|center|right) for text/figure/svg/pdf/toc; `:VALIGN:` (top|middle|bottom) for text and pdf elements (note: `middle` maps to Typst `horizon`); `:FLOW:` (normal|bottom-up|center-out) — when `:VALIGN:` is not set for text, `:FLOW:` can imply vertical alignment (bottom-up -> bottom, center-out -> horizon).
- **Custom styles**: Per-document text styles via Org meta `#+STYLE_*` and per-element `:STYLE:` name. See Custom Styles section.
### 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 with optional captions | Supports fit modes, captions |
| `pdf` | Vector PDF embedding | Page selection, scaling |
| `svg` | SVG image embedding | Fit: contain; path via `:SVG:` |
| `rectangle` | Colored overlays | Color, alpha, optional stroke/stroke_color/radius |
| `toc` | Table of contents | Auto-lists slide titles (• 1. Title); supports :AREA:, :PADDING:, :ALIGN: |
## 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 and PNG rendering
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 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
```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
# Emit IR JSON to stdout
pagemaker ir examples/sample.org > ir.json
# Validate IR (non-zero exit on error)
pagemaker validate examples/sample.org
```
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.
### 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
| 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
```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
: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:
```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
```
### Colored Rectangles
Create transparent overlays and design elements:
```org
** 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`
### Vector PDF Embedding
Include high-quality PDF pages with fallback support:
```org
** Technical Diagram
:PROPERTIES:
:TYPE: pdf
:PDF: assets/technical-drawing.pdf
:PAGE: 2
# (Deprecated) :SCALE: 1.2 -> ignored; auto-contain applied
:AREA: D2,I5
:Z: 50
:END:
```
Notes:
- For problematic PDFs with MuchPDF, run the CLI with `--sanitize-pdfs`.
- If sanitization still fails, the first requested page is auto-converted to SVG (preferred) or PNG and embedded as an image.
- Fallback assets are written under `export_dir/assets/pdf-fallbacks/` and linked in the generated Typst.
PDF scaling semantics (automatic contain + multiplier):
- Intrinsic PDF size is parsed (MediaBox) to obtain its natural width/height in mm.
- The usable element frame is the declared `:AREA:` cell span minus element `:PADDING:` (and respects page `#+MARGINS:` when present).
- Applied scale: `base_scale = min(frame_w_mm / pdf_w_mm, frame_h_mm / pdf_h_mm)` (falls back to 1.0 when intrinsic probing fails).
- Any legacy `:SCALE:` property (from earlier docs) is currently ignored with a warning; only containment is applied.
- Element `:PADDING:` reduces the frame before base scale calculation (shrinking resulting size).
Legacy validation errors related to `:SCALE:` are currently dormant because `:SCALE:` is ignored; future fit/scale options may restore stricter validation.
Migration from older versions:
- Remove any `:FIT:` or `:FULL_PAGE:` on pdf elements (ignored if present).
- If you depended on `:FIT: contain`, just delete it (now default implicit behavior).
- If you previously used `:FIT: fill` to overshoot, enlarge the `:AREA:` instead; scale is capped at containment.
- To simulate a full-page background, span the entire (including margin tracks) grid with `:AREA:` and keep default scale.
Planned (optional) debug: A future `:PDF_DEBUG_SCALE:` flag may emit computed `pdf_w_mm`, `pdf_h_mm`, `frame_w_mm`, `frame_h_mm`, `base_scale` as Typst comments for troubleshooting (user scale currently unused).
### SVG Embedding
Embed SVG graphics directly:
```org
** Vector Graphic
:PROPERTIES:
:TYPE: svg
:SVG: assets/test-svgs/test-plan-p11.svg
:AREA: C2,J6
:END:
```
- Paths are treated like other assets and adjusted relative to the export directory.
- Fit defaults to contain within the target area.
### 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).
```org
#+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:`.
```org
#+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
```elisp
;; 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
```bash
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` or the `@preview/muchpdf` package are unavailable on your system.
### Code Style & Pre-commit
This project uses pre-commit with Ruff for formatting and linting.
Setup:
```bash
pip install pre-commit
pre-commit install
```
Run hooks on the entire repo:
```bash
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:
```bash
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](https://github.com/sanderboer/typst-pagemaker/blob/main/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.*
Raw data
{
"_id": null,
"home_page": null,
"name": "typst-pagemaker",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "typst, orgmode, layout, grid, slides, pdf",
"author": "Project",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/fc/2d/9e82a9c20627b4ddcb7ec1c768671d8074633c8c3e34d706c647a9a59905/typst_pagemaker-0.1.18.tar.gz",
"platform": null,
"description": "# pagemaker\n\nPlease note: This project is in no way affiliated with or related to the old Aldus PageMaker program from the 90s.\n\nA 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.\n\n<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>\nThe 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. \n\n\n## Design Philosophy\n\nUnlike traditional document systems that rely on automatic text flow and built-in spacing, pagemaker takes a fundamentally different approach:\n\n- **Every page is explicitly described** - no automatic page breaks or content flow\n- **Every element is explicitly positioned** - precise grid-based placement using A1-style coordinates\n- **Gutter-free grid system** - clean grid divisions with no built-in spacing between cells\n- **Element-level padding** - fine-grained spacing control through per-element padding properties\n- **Professional typography** - leverages Typst's advanced typesetting with three bundled professional fonts (Inter, Crimson Pro, JetBrains Mono)\n\nThis approach is ideal for creating presentations, posters, reports, and any document where you need pixel-perfect control over layout and positioning.\n\n## Features\n\n### Migration Notice (Breaking Change)\nPDF embedding now always uses automatic contain scaling (legacy `:FIT:` modes and the `:FULL_PAGE:` flag for `pdf` elements were removed). A previously documented optional `:SCALE:` multiplier is currently ignored and will emit a warning when specified.\n\nNew behavior (pdf elements only):\n- The system computes a base auto-contain scale so the intrinsic PDF page fits entirely within the element's padded frame (respecting margins + element `:PADDING:`).\n- User `:SCALE:` values (if present in older documents) are ignored for now (warning emitted). Future releases may reintroduce controlled fit modes.\n- Result: PDFs never overflow their frame via scale; enlarge the `:AREA:` to show more context.\n\nMigration:\n- Remove any `:FIT:` / `:FULL_PAGE:` properties on `pdf` elements (ignored if still present).\n- If you previously relied on `:FIT: contain` just delete it (behavior now default). If you relied on oversizing via `:FIT: fill` or manual big areas, you may enlarge the `:AREA:` instead; scale no longer exceeds containment.\n- Image `figure` elements still support `:FIT:` (contain|cover|fill) unchanged.\n- Legacy per-PDF alignment property (`pdf_align` / `:PDF_ALIGN:`) has been removed; use the standard `:ALIGN:` / `:VALIGN:` properties on `pdf` elements.\n\nSee the Vector PDF Embedding section below for details and examples.\n\n### Core Functionality\n- **Org-mode to Typst conversion (optional)**: Converts Org documents to Typst\n- **Grid-based positioning**: Grid layout (e.g., 12x8) with A1-style areas\n- **Element types**: Header, subheader, body text, image, PDF, rectangle, TOC\n- **Z-order**: Element stacking control\n- **Typography**: Fonts and basic theming\n\n### Features\n- **PDF embedding**: MuchPDF integration with sanitize/SVG/PNG fallback\n- **Rectangles**: Colored overlays with alpha transparency; optional stroke, stroke_color fallback, and corner radius\n- **Images**: Fit modes (contain, cover, fill) and captions\n- **Debug grid**: Optional grid lines and labels (columns 1..N, rows a..z)\n- **Custom fonts**: Integrated font management system with Google Fonts integration\n- **Text justification**: `:JUSTIFY:` for header/subheader/body (wraps Typst `par(justify: true)`)\n- **Padding**: `:PADDING:` on text, images, SVG, and PDF (CSS-like TRBL shorthand in mm; per-side padding inherits and accumulates; if totals cancel to 0mm on all sides, generator still emits padded placement).\n- **Alignment & flow**: `:ALIGN:` (left|center|right) for text/figure/svg/pdf/toc; `:VALIGN:` (top|middle|bottom) for text and pdf elements (note: `middle` maps to Typst `horizon`); `:FLOW:` (normal|bottom-up|center-out) \u2014 when `:VALIGN:` is not set for text, `:FLOW:` can imply vertical alignment (bottom-up -> bottom, center-out -> horizon).\n- **Custom styles**: Per-document text styles via Org meta `#+STYLE_*` and per-element `:STYLE:` name. See Custom Styles section.\n\n### Supported Elements\n\n| Element Type | Description | Properties |\n|-------------|-------------|------------|\n| `header` | Main headings | Font: Inter Bold, 24pt |\n| `subheader` | Section headings | Font: Inter SemiBold, 18pt | \n| `body` | Regular text | Font: Inter Regular |\n| `figure` | Images with optional captions | Supports fit modes, captions |\n| `pdf` | Vector PDF embedding | Page selection, scaling |\n| `svg` | SVG image embedding | Fit: contain; path via `:SVG:` |\n| `rectangle` | Colored overlays | Color, alpha, optional stroke/stroke_color/radius |\n| `toc` | Table of contents | Auto-lists slide titles (\u2022 1. Title); supports :AREA:, :PADDING:, :ALIGN: |\n\n## Quick Start\n\n### Installation\n```bash\n# Install from PyPI\npip install typst-pagemaker\n\n# Verify installation\npagemaker --help\ntypst --version # Ensure Typst is also installed\n```\n\n### Requirements\n\n**Essential Dependencies:**\n- **Typst** - The core typesetting engine. Install from [typst.app](https://typst.app/docs/tutorial/installation/)\n- **MuPDF tools (mutool)** - Essential for PDF processing, SVG/PNG fallback generation, and `--sanitize-pdfs` functionality\n\n**Optional Dependencies:**\n- **qpdf** - Enhanced PDF repair and normalization \n- **Ghostscript (gs)** - Alternative PDF processing and PNG rendering\n\nInstall platform-specific dependencies:\n```bash\n# macOS (via Homebrew)\nbrew install typst mupdf qpdf ghostscript\n\n# Ubuntu/Debian\nsudo apt update && sudo apt install typst-cli mupdf-tools qpdf ghostscript\n\n# Arch Linux\nsudo pacman -S typst mupdf-tools qpdf ghostscript\n\n# Windows (via winget or chocolatey)\nwinget install --id Typst.Typst\n# For MuPDF, download from: https://mupdf.com/releases/index.html\n```\n\n### Development Installation\n```bash\n# Clone the repository for development\ngit clone https://github.com/sanderboer/typst-pagemaker.git\ncd typst-pagemaker\n\n# Install in editable mode\npip install -e .\npagemaker --help\n```\n\n### Basic Usage (New Multi-Command CLI)\n\n#### Watch Mode\nContinuously rebuild Typst (and optionally PDF) when the source Org file changes.\n```\n# Rebuild typst on change\npagemaker watch examples/sample.org --export-dir export\n\n# Build PDF on each change, keep intermediate .typ\npagemaker watch examples/sample.org --pdf --no-clean --export-dir export\n\n# Single build (no loop) - useful for tests\npagemaker watch examples/sample.org --once --export-dir export\n```\nOptions:\n- `--interval <seconds>`: Polling interval (default 1.0)\n- `--pdf`: Also compile PDF each rebuild\n- `--pdf-output <file>`: Custom PDF filename\n- `--typst-bin <path>`: Path to `typst` binary\n- `--no-clean`: Keep the intermediate `.typ` after PDF build\n- `--update-html <path>`: Update existing HTML file's page count placeholder\n- `--once`: Perform exactly one build then exit\n- `--sanitize-pdfs`: Attempt to sanitize PDFs; if Typst compile still fails, auto-fallback to SVG or PNG for the requested page\n\n```bash\n# Build Typst from Org (org -> typst)\npagemaker build examples/sample.org -o deck.typ\n\n# Build and produce PDF (cleans .typ by default)\npagemaker pdf examples/sample.org --pdf-output deck.pdf\n\n# Build with PDF sanitize + fallback (qpdf/mutool/gs optional)\npagemaker pdf examples/sample.org --sanitize-pdfs --pdf-output deck.pdf\n\n# Emit IR JSON to stdout\npagemaker ir examples/sample.org > ir.json\n\n# Validate IR (non-zero exit on error)\npagemaker validate examples/sample.org\n```\n\n\nManual Typst compile (if you only produced .typ):\n```bash\ntypst compile --root . --font-path assets/fonts --font-path assets/fonts/static export/deck.typ export/deck.pdf\n```\n\nOr use the Makefile targets:\n```bash\nmake debug-overlay # Build debug example\n```\n\n#### Asset Path Semantics\nWhen exporting into an `export/` directory, any relative asset references in the Org file like:\n```\n[[file:assets/diagram.png]]\n:PDF: assets/spec.pdf\n:SVG: assets/graphics/logo.svg\n```\nare 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.\n\n### Example Org File\n\nDynamic helpers available in text:\n- `#page_no` / `#page_total` for page counters (no parentheses; Typst context-based).\n- Dates: `#date_iso` (YYYY-MM-DD), `#date_yy_mm_dd` (YY.MM.DD), `#date_dd_mm_yy` (DD.MM.YY)\n- To lock dates for reproducible builds, set `#+DATE_OVERRIDE: YYYY-MM-DD` (or `#+DATE:`) in the Org meta header.\n\nTOC element:\n- Add a `toc` element to list slide titles automatically.\n```org\n** Table of Contents\n:PROPERTIES:\n:TYPE: toc\n:AREA: A1,L8\n:PADDING: 4,6\n:END:\n```\n\n\nText: use `:JUSTIFY:` to enable full justification and `:PADDING:` to inset content in millimeters.\n(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)\n\n<div style=\"display: flex; justify-content: space-between; align-items: center;\"><img src=\"img/example.jpg\" alt=\"Alt Text\" style=\"width: 48%;\"></div>\n\n```org\n#+TITLE: My Presentation\n#+PAGESIZE: A4\n#+ORIENTATION: landscape\n#+GRID: 12x8\n#+GRID_DEBUG: false\n#+STYLE_WHITE_BODY: font: Playfair Display, color: #ffffff, size: 16pt, spacing: 20pt\n\n\n* Introduction Slide\n:PROPERTIES:\n:ID: intro_slide\n:END:\n\n** Main Title\n:PROPERTIES:\n:TYPE: header\n:AREA: b1,c4\n:PADDING: 8,8\n:JUSTIFY: \n:Z: 10\n:END:\nWelcome to pagemaker\n\n** Background Rectangle\n:PROPERTIES:\n:TYPE: rectangle\n:AREA: A1,L4\n:COLOR: #3498db\n:ALPHA: 0.2\n:Z: -1\n:END:\n\n** Demo Image\n:PROPERTIES:\n:TYPE: figure\n:AREA: A5, H12\n:PADDING: 0,0,0,0\n:FIT: cover\n:Z: -1\n:END:\n[[file:assets/test-images/landscapes/landscape-1.jpg]]\n\n** poem\n:PROPERTIES:\n:TYPE: body\n:STYLE: white_body\n:AREA: C7,D10\n:valign: top\n:END:\n\nI am but a leaf\n\nClinging to the tree of life\n\nIn the world\u2019s garden.\n\n** poem\n:PROPERTIES:\n:TYPE: subheader\n:STYLE: white_body\n:AREA: E7,F10\n:align: right\n:valign: middle\n:END:\nLast night I saw you,\n\nA dream rose and I your stem\n\nShowing you the sun.\n\n```\n\n## Directory Structure\n\n```\ntypst-pagemaker/\n\u251c\u2500\u2500 src/ # Source code\n\u2502 \u251c\u2500\u2500 pagemaker/ # Package (parser, generator, CLI)\n\u251c\u2500\u2500 bin/ # Build tools and scripts\n\u2502 \u251c\u2500\u2500 Makefile # Build automation\n\u2502 \u2514\u2500\u2500 debug_test_fonts.sh\n\u251c\u2500\u2500 examples/ # Example Org files and outputs\n\u2502 \u251c\u2500\u2500 assets/ # Fonts and test resources\n\u2502 \u2502 \u251c\u2500\u2500 fonts/ # Downloaded fonts\n\u2502 \u2502 \u251c\u2500\u2500 test-images/ # Sample images for testing\n\u2502 \u2502 \u2514\u2500\u2500 test-pdfs/ # Sample PDFs for testing\n\u251c\u2500\u2500 tests/ # Test suite\n\u2502 \u251c\u2500\u2500 unit/ # Unit tests\n\u2502 \u251c\u2500\u2500 integration/ # Integration tests\n\u2502 \u2514\u2500\u2500 fixtures/ # Test data\n\u2514\u2500\u2500 docs/ # Documentation\n```\n\n## Quick Reference\n\n### Common Element Properties\n| Property | Values | Description |\n|----------|--------|-------------|\n| `:TYPE:` | `header`, `subheader`, `body`, `figure`, `pdf`, `svg`, `rectangle`, `toc` | Element type |\n| `:AREA:` | `A1`, `B3,F5` | Grid position (A1 notation) |\n| `:Z:` | `10`, `100` | Stacking order (higher on top) |\n| `:PADDING:` | `4`, `2,4`, `2,4,6,8` | Margin in mm (CSS TRBL) |\n| `:ALIGN:` | `left`, `center`, `right` | Horizontal alignment |\n| `:VALIGN:` | `top`, `middle`, `bottom` | Vertical alignment (text + pdf elements) |\n| `:JUSTIFY:` | (bare) or `true`/`false` | Full text justification |\n| `:IGNORE:` | `true`, `false` | When `true`: drop this page (level 1) or this section and its subtree (level \u22652). If `:TYPE:` is missing or `none`, only the element is omitted; children still parse. |\n\n### Page Setup Headers\n| Header | Example | Description |\n|--------|---------|-------------|\n| `#+PAGESIZE:` | `A4`, `A3`, `A1` | Page size |\n| `#+ORIENTATION:` | `landscape`, `portrait` | Page orientation |\n| `#+GRID:` | `12x8`, `16x9` | Grid dimensions |\n| `#+MARGINS:` | `10,15,10,15` | Margins in mm (TRBL) |\n| `#+GRID_DEBUG:` | `true`, `false` | Show debug grid |\n\n### Element Types Quick Syntax\n```org\n** Header Text\n:PROPERTIES:\n:TYPE: header\n:AREA: A1,F2\n:END:\n\n** Image\n:PROPERTIES:\n:TYPE: figure\n:AREA: G1,L4\n:FIT: contain\n:END:\n[[file:path/to/image.jpg]]\n\n** PDF Page\n:PROPERTIES:\n:TYPE: pdf\n:PDF: path/to/doc.pdf\n:PAGE: 2\n:AREA: A5,F8\n:END:\n\n** Colored Rectangle\n:PROPERTIES:\n:TYPE: rectangle\n:AREA: B2,K7\n:COLOR: #3498db\n:ALPHA: 0.3\n:END:\n```\n\n## Configuration\n\n### Page Setup\n- **PAGESIZE**: A4, A3, A2, A1, A5\n- **ORIENTATION**: landscape, portrait\n- **GRID**: Custom grid dimensions (e.g., 12x8, 16x9)\n- **MARGINS**: Absolute mm in CSS TRBL order (top,right,bottom,left)\n- **GRID_DEBUG**: Show/hide debug grid lines\nNotes:\n- Typst page size is set once at the document level from the first rendered page\u2019s `PAGESIZE` and `ORIENTATION`. Per-page overrides are ignored during Typst generation; the validator warns if pages disagree.\n- `:AREA:` always addresses the total grid (including margin tracks); there is no `:COORDS:` directive.\n\n### Element Properties\n\n#### Ignore Semantics\n- `: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.\n- `:IGNORE: true` on a section (level \u22652) removes that section and its entire subtree.\n- 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:`.\n\n#### Validation Rules\nThe `validate` subcommand parses Org -> IR, then enforces structural rules.\nErrors (fail the build):\n- Duplicate page IDs\n- Duplicate element IDs\n- Rectangle alpha outside 0.0\u20131.0\n- Area issues: non-positive dimensions or exceeding page grid bounds (when grid + area fully specified)\n\nWarnings (reported but do not fail):\n- Unknown element types (fallback treatment may change later)\n- Missing figure or PDF asset file (relative path that does not exist when validating)\n\nTo escalate missing asset warnings into errors (e.g., for CI pipelines), use:\n```\npagemaker validate --strict-assets examples/sample.org\n```\nThis makes missing figure/pdf assets fail validation (non-zero exit code).\n\nExample:\n```\npagemaker validate examples/sample.org\n```\nExit code 0 means no errors (warnings may still appear).\n- **TYPE**: Element type (header, subheader, body, figure, pdf, rectangle)\n- **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.\n- **Z**: Stacking order (higher numbers appear on top)\n- **COLOR**: Hex color for rectangles (#RRGGBB)\n- **ALPHA**: Transparency (0.0 = transparent, 1.0 = opaque)\n- **FIT**: Image fitting (contain, cover, fill)\n- **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.\n- **JUSTIFY**: Optional boolean for text elements. `:JUSTIFY:` (bare) or `:JUSTIFY: true` enables full justification; `false` disables. Maps to Typst `par(justify: true)` wrapping.\n- **ALIGN**: Horizontal alignment within the element frame. Values: `left`, `center`, `right`. Applies to text (`header`, `subheader`, `body`) and media (`figure`, `svg`, `pdf`, `toc`).\n- **VALIGN**: Vertical alignment within the element frame. Values: `top`, `middle`, `bottom`. Applies to text elements. Note: `middle` maps to Typst `horizon` (Typst\u2019s vertical-center token).\n- **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.\n\n## Tooling\n\n**Essential external tools:**\n- `typst`: Required for all document compilation\n- `mutool` (MuPDF): Essential for PDF processing, SVG/PNG fallback generation, and full `--sanitize-pdfs` functionality\n\n**Optional external tools** that enhance PDF handling with `--sanitize-pdfs`:\n- `qpdf`: Repairs and normalizes PDF structure (stream recompress, object streams)\n- `gs` (Ghostscript): Alternate PDF distillation and PNG fallback rendering\n\nThe CLI automatically detects these tools. If unavailable, related stages are skipped, but missing essential tools will limit core functionality.\n\n## Advanced Usage\n\nSee the in-depth guide: docs/master_styles.md (styles, paragraph options, master pages, margins/grid, and padding semantics including zero-sum).\n\n### Custom Styles\n- Declare styles in document meta using `#+STYLE_<NAME>:` where `<NAME>` is case-insensitive. Built-ins: `HEADER`, `SUBHEADER`, `BODY`.\n- Supported keys (case-insensitive) with aliases:\n - font | font-family\n - weight | font-weight (numeric or names like bold, semibold)\n - size | font-size (Typst units like `pt`, `em`)\n - color | colour | fill (supports `#hex`, `rgb(...)`, `hsl(...)`, or named)\n- Use a style on an element by setting `:STYLE:` to the style name (e.g., `hero`). If omitted, the element\u2019s type is used as the style key (`header`, `subheader`, `body`).\n- Commas inside parentheses are handled correctly (e.g., `rgb(50%,50%,50%)`).\n\nExample:\n```org\n#+STYLE_HEADER: font: Inter, weight: 900, size: 30pt, color: #ff00aa\n#+STYLE_BODY: font: Inter, color: rgb(50%,50%,50%)\n#+STYLE_HERO: font: Inter, weight: bold, size: 36pt, color: #123456\n\n* Title\n:PROPERTIES:\n:TYPE: header\n:AREA: 1,1,6,1\n:END:\nMy Header\n\n** Big Title\n:PROPERTIES:\n:TYPE: body\n:STYLE: hero\n:AREA: 1,2,12,2\n:END:\nBig Title\n```\nSee `examples/custom_styles_demo.org` for a complete, runnable example.\n\n#### Paragraph Options\n- Style declarations may also include paragraph settings applied via Typst `par(...)`:\n - `leading`: Line leading (Typst length, e.g., `1.4em`, `14pt`).\n - `spacing`: Space between paragraphs (length).\n - `first-line-indent` (or `first_line_indent`): Indent the first line (length).\n - `hanging-indent` (or `hanging_indent`): Hanging indent for subsequent lines (length).\n - `linebreaks`: Typst line-breaking mode token (e.g., `auto`, `loose`, `strict`).\n - `justify`: Boolean or token; when set, maps to `justify: true|false`.\n- Element-level `:JUSTIFY:` always overrides the style\u2019s `justify` value.\n\nParagraphs are split by:\n- Blank lines\n- Lines that are exactly `---` or `:::`\n\nIf 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\u2019s `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.\n\nExample (Org):\n```org\n#+STYLE_BODY: font: Inter, leading: 1.4em, spacing: 1em, first-line-indent: 2em, hanging-indent: 1em, linebreaks: loose, justify: false\n\n** Styled Body\n:PROPERTIES:\n:TYPE: body\n:AREA: A1,L8\n:JUSTIFY: true # element-level override\n:END:\nFirst paragraph line one.\n\n---\nSecond paragraph, now with the style\u2019s paragraph options and justify enabled.\n```\n\n### Custom Fonts\nThe package includes professional bundled fonts as a reliable default, with support for rich project-specific font libraries.\n\n**Font Resolution Order:**\n1. **Project fonts**: `assets/fonts/` (custom library checked first) \n2. **Bundled fonts**: Package-included minimal defaults (Inter, Crimson Pro, JetBrains Mono)\n3. **System fonts**: Typst automatically discovers installed system fonts (final fallback)\n\n**Bundled Fonts (Always Available):**\n- **Inter**: Modern sans-serif optimized for screens and interfaces\n- **Crimson Pro**: Professional serif for body text and academic documents \n- **JetBrains Mono**: Code-friendly monospace with excellent readability\n\n**Project Font Library:**\n```bash\n# Add custom fonts to your project\nmkdir -p assets/fonts/FontFamily\ncp path/to/FontFamily-*.ttf assets/fonts/FontFamily/\n\n# Fonts are automatically discovered and available in your documents\n```\n\n**Font Management CLI:**\n```bash\n# List all available fonts\npagemaker fonts list-all\n\n# Show bundled fonts only\npagemaker fonts list-bundled --details\n\n# Show project fonts only \npagemaker fonts list-project --details\n\n# Validate specific font availability\npagemaker fonts validate \"Inter\"\npagemaker fonts validate \"Your Custom Font\"\n```\n\n**Using Custom Fonts:**\n```org\n# Reference any available font in your documents\n#+CUSTOM_STYLE: #set text(font: \"Your Custom Font\", size: 12pt)\n\n* Heading with Custom Typography\n#set text(font: \"Playfair Display\", weight: \"bold\", size: 18pt)\n\nThis heading uses a custom display font for elegant typography.\n\n#set text(font: \"Inter\")\nThis paragraph switches back to the reliable bundled Inter font.\n```\n\n**Font Discovery:**\nThe 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.\n\n## Font Management System\n\nThe pagemaker CLI includes a comprehensive font management system to help discover, install, analyze, and preview fonts in your projects.\n\n### Font Discovery and Listing\n\nList all fonts available to your project:\n```bash\n# Show all available fonts (project + bundled + system)\npagemaker fonts list-all\n\n# Show only bundled fonts with details\npagemaker fonts list-bundled --details\n\n# Show only project fonts with details \npagemaker fonts list-project --details\n\n# Validate specific font availability\npagemaker fonts validate \"Inter\"\npagemaker fonts validate \"Playfair Display\"\n```\n\n### Google Fonts Integration\n\nSearch and install fonts directly from Google Fonts:\n```bash\n# Search for fonts by name\npagemaker fonts search \"Playfair\"\npagemaker fonts search \"mono\" --limit 10\n\n# Install fonts to your project\npagemaker fonts install \"Playfair Display\"\npagemaker fonts install \"JetBrains Mono\" --variants regular,700,italic\n\n# Clear font installation cache\npagemaker fonts cache-clear\n```\n\n**Installation Details:**\n- Fonts are downloaded from Google Fonts API with offline fallback for popular fonts\n- Installed to `assets/fonts/FontFamily/` directory structure\n- Supports variant selection (regular, 700, italic, etc.)\n- Automatically creates proper directory structure\n\n### Font Usage Analysis\n\nAnalyze your documents to find font references and check availability:\n```bash\n# Analyze font usage in a document\npagemaker fonts analyze examples/sample.org\n\n# Analyze with installation suggestions for missing fonts\npagemaker fonts analyze examples/font_management_demo.org\n```\n\n**Analysis Features:**\n- Detects fonts referenced in `#+CUSTOM_STYLE` and `#set text(font: \"Name\")` patterns\n- Cross-references with available font inventory from all sources\n- Provides installation suggestions for missing fonts\n- Shows font availability status (\u2713 Available, \u2717 Missing)\n\n### Font Specimen Generation\n\nGenerate font showcase documents to preview and compare fonts:\n```bash\n# Generate comprehensive font specimen\npagemaker fonts specimen my-fonts.org\n\n# Generate simple comparison format\npagemaker fonts specimen fonts-comparison.org --format comparison\n\n# Generate simple list format \npagemaker fonts specimen fonts-list.org --format simple\n\n# Auto-build PDF after generating specimen\npagemaker fonts specimen my-fonts.org --build-pdf\n```\n\n**Specimen Formats:**\n- **showcase** (default): Detailed specimens with multiple text samples and sizes\n- **comparison**: Side-by-side comparison with consistent sample text\n- **simple**: Minimal list format with basic font information\n\n### Build-Time Font Validation\n\nIntegrate font validation into your build process:\n```bash\n# Build with font validation (warnings only)\npagemaker build examples/sample.org --validate-fonts\n\n# Build with strict font validation (fails on missing fonts) \npagemaker pdf examples/sample.org --strict-fonts --pdf-output output.pdf\n\n# Watch mode with font validation\npagemaker watch examples/sample.org --validate-fonts --pdf\n```\n\n**Validation Features:**\n- Scans document for font references during build\n- Reports missing fonts with helpful error messages\n- Suggests installation commands for missing Google Fonts\n- `--validate-fonts`: Shows warnings but continues build\n- `--strict-fonts`: Fails build on missing fonts (useful for CI/CD)\n\n### Performance Optimization\n\nThe font system includes caching for improved performance:\n- **Font discovery caching**: Results cached for 5 minutes to speed up repeated operations\n- **Google Fonts API caching**: Downloaded font lists cached locally\n- **Cache invalidation**: Automatically detects font directory changes\n- **Graceful fallback**: Continues operation if caching fails\n\n### Font Management Examples\n\n**Complete workflow for adding a new font:**\n```bash\n# 1. Search for desired font\npagemaker fonts search \"Crimson\"\n\n# 2. Install the font\npagemaker fonts install \"Crimson Pro\"\n\n# 3. Verify installation\npagemaker fonts validate \"Crimson Pro\"\n\n# 4. Generate specimen to preview\npagemaker fonts specimen fonts-preview.org --format showcase\n\n# 5. Use in your document\necho '#+CUSTOM_STYLE: #set text(font: \"Crimson Pro\", size: 12pt)' >> my-doc.org\n\n# 6. Build with font validation\npagemaker pdf my-doc.org --validate-fonts --pdf-output my-doc.pdf\n```\n\n**Analyzing and fixing font issues:**\n```bash\n# Analyze document for font problems\npagemaker fonts analyze problematic-doc.org\n\n# Output might show:\n# \u2717 Missing: \"Custom Font\" - try: pagemaker fonts install \"Custom Font\"\n# \u2713 Available: \"Inter\"\n\n# Install missing fonts as suggested\npagemaker fonts install \"Custom Font\"\n\n# Rebuild with validation\npagemaker pdf problematic-doc.org --strict-fonts --pdf-output fixed-doc.pdf\n```\n\n### Colored Rectangles\nCreate transparent overlays and design elements:\n```org\n** Background Accent\n:PROPERTIES:\n:TYPE: rectangle\n:AREA: B2,I6\n:COLOR: #FF6B6B\n:ALPHA: 0.3\n:Z: 10\n:END:\n```\n\nRectangle style keys and behavior:\n- color: fill color (`#hex`, `rgb(...)`, `hsl(...)`, named)\n- alpha: 0.0\u20131.0 (values outside are clamped during generation)\n- stroke: length with unit (`pt|mm|cm|in`)\n- stroke_color: stroke color; when omitted but stroke is set, falls back to fill color\n- radius: corner radius (length with unit)\n\nEmission rules:\n- Minimal: `ColorRect(\"<color>\", <alpha>)` when no stroke/radius provided\n- Any optional set: `ColorRect(..., stroke: ..., stroke_color: ..., radius: ...)`\n- Radius-only: emits `stroke: none, stroke_color: none` with provided `radius`\n\n\n### Vector PDF Embedding\nInclude high-quality PDF pages with fallback support:\n```org\n** Technical Diagram\n:PROPERTIES:\n:TYPE: pdf\n:PDF: assets/technical-drawing.pdf\n:PAGE: 2\n# (Deprecated) :SCALE: 1.2 -> ignored; auto-contain applied\n:AREA: D2,I5\n:Z: 50\n:END:\n```\nNotes:\n- For problematic PDFs with MuchPDF, run the CLI with `--sanitize-pdfs`.\n- If sanitization still fails, the first requested page is auto-converted to SVG (preferred) or PNG and embedded as an image.\n- Fallback assets are written under `export_dir/assets/pdf-fallbacks/` and linked in the generated Typst.\n\nPDF scaling semantics (automatic contain + multiplier):\n- Intrinsic PDF size is parsed (MediaBox) to obtain its natural width/height in mm.\n- The usable element frame is the declared `:AREA:` cell span minus element `:PADDING:` (and respects page `#+MARGINS:` when present).\n- Applied scale: `base_scale = min(frame_w_mm / pdf_w_mm, frame_h_mm / pdf_h_mm)` (falls back to 1.0 when intrinsic probing fails).\n- Any legacy `:SCALE:` property (from earlier docs) is currently ignored with a warning; only containment is applied.\n- Element `:PADDING:` reduces the frame before base scale calculation (shrinking resulting size).\n\nLegacy validation errors related to `:SCALE:` are currently dormant because `:SCALE:` is ignored; future fit/scale options may restore stricter validation.\n\nMigration from older versions:\n- Remove any `:FIT:` or `:FULL_PAGE:` on pdf elements (ignored if present).\n- If you depended on `:FIT: contain`, just delete it (now default implicit behavior).\n- If you previously used `:FIT: fill` to overshoot, enlarge the `:AREA:` instead; scale is capped at containment.\n- To simulate a full-page background, span the entire (including margin tracks) grid with `:AREA:` and keep default scale.\n\nPlanned (optional) debug: A future `:PDF_DEBUG_SCALE:` flag may emit computed `pdf_w_mm`, `pdf_h_mm`, `frame_w_mm`, `frame_h_mm`, `base_scale` as Typst comments for troubleshooting (user scale currently unused).\n\n### SVG Embedding\nEmbed SVG graphics directly:\n```org\n** Vector Graphic\n:PROPERTIES:\n:TYPE: svg\n:SVG: assets/test-svgs/test-plan-p11.svg\n:AREA: C2,J6\n:END:\n```\n- Paths are treated like other assets and adjusted relative to the export directory.\n- Fit defaults to contain within the target area.\n\n### Margins\nDefine outer margins in millimeters that expand the total grid while keeping your content coordinates stable. Format: `top,right,bottom,left` (CSS TRBL order).\n```org\n#+GRID: 12x8\n#+MARGINS: 10,15,10,15\n\n* Slide\n:PROPERTIES:\n:ID: s1\n:END:\n\n** Full-bleed background (uses margin tracks)\n:PROPERTIES:\n:TYPE: rectangle\n:AREA: 1,1,14,10\n:COLOR: #3498db\n:ALPHA: 0.1\n:END:\n\n** Content inside margins\n:PROPERTIES:\n:TYPE: body\n:AREA: A1,L8\n:END:\nThe 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.\n```\nNotes:\n- `MARGINS` values are absolute sizes in mm.\n- `: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.\n- 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`.\n\n### Master Pages\nSee examples/master_pages_demo.org for a runnable master page setup.\n\n\nDefine reusable element sets as master pages that are not directly rendered. Apply them per slide with `:MASTER:` or globally with `#+DEFAULT_MASTER:`.\n```org\n#+DEFAULT_MASTER: Base\n\n* Base Master (not rendered)\n:PROPERTIES:\n:MASTER_DEF: Base\n:END:\n\n** Header Bar\n:PROPERTIES:\n:TYPE: rectangle\n:AREA: A1,A12\n:COLOR: #000000\n:ALPHA: 0.08\n:END:\n\n** Footer Text\n:PROPERTIES:\n:TYPE: body\n:AREA: H11,H12\n:END:\nPage #page_no / #page_total \u2014 #date_dd_mm_yy\n\n* Slide One (inherits Base)\n:PROPERTIES:\n:ID: s1\n:END:\n\n** Title\n:PROPERTIES:\n:TYPE: header\n:AREA: B2,C11\n:END:\nWelcome with Master\n```\nNotes:\n- Pages that define `:MASTER_DEF:` are used as master definitions and are skipped at render time.\n- Slides can reference a master via per-page `:MASTER:` or inherit from `#+DEFAULT_MASTER:`.\n- Master elements are combined with slide elements and z-ordered together.\n\n## A1 AREA Notation\n\n- Rows are letters A..Z, then AA, AB, etc. (case-insensitive). A maps to row 1.\n- Columns are numbers starting at 1.\n- Single cell: \"B3\" -> [x=3, y=2, w=1, h=1].\n- Range: \"A1,C2\" -> inclusive rectangle normalized to top-left/bottom-right yielding [x=1, y=1, w=2, h=3].\n- Reverse ranges like \"C2,A1\" are normalized the same as \"A1,C2\".\n- Legacy format \"x,y,w,h\" remains supported for backward compatibility.\n- Debug grid labels: columns show 1..N at top; rows show a..z at left (rows > 26 currently fall back to numeric display).\n\n## Editor Integration (Emacs)\n\npagemaker 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.\n\n### Requirements\n- Emacs 27 or newer recommended\n- Optional: hydra package (for the in-buffer command menu)\n- pagemaker CLI available on PATH (pip install typst-pagemaker)\n\n### Install via straight.el\n```elisp\n;; Stable: pin to a released tag (recommended)\n(use-package org-pagemaker\n :straight (org-pagemaker\n :type git\n :host github\n :repo \"sanderboer/org-pagemaker\"\n :tag \"v0.1.2\" ;; pin to a release tag (if available)\n :files (\"lisp/*.el\"))\n :hook (org-mode . org-pagemaker-mode))\n\n\n;; (use-package org-pagemaker\n;; :straight (org-pagemaker :type git :host github :repo \"sanderboer/org-pagemaker\" :files (\"lisp/*.el\"))\n;; :hook (org-mode . org-pagemaker-mode))\n```\n\nNotes:\n- The Emacs package is developed in a separate repo; this project\u2019s .gitignore ignores any nested pagemaker-el/ checkout under the root.\n- Ensure the pagemaker executable resolves in Emacs (M-: (executable-find \"pagemaker\")). If needed, adjust exec-path or your shell init for GUI Emacs.\n\n### Keybindings (org-pagemaker-mode)\n- C-c p h: Show the org-pagemaker Hydra (if hydra is installed)\n- C-c p b: Build Typst (.typ)\n- C-c p p: Build PDF\n- C-c p w: Watch and rebuild on save\n- C-c p v: Validate IR\n- C-c p s: Build with PDF sanitize/fallback\n- C-c p o: Open last output (PDF/Typst)\n- C-c p i: Insert example/template\n\nThe Hydra is an optional convenience. If hydra is not present, C-c p h displays a helpful message; all other keybindings continue to work.\n\n### Quick check\n1) Open any of the example .org files in this repo\n2) Enable the mode: M-x org-pagemaker-mode\n3) Run C-c p b to generate a .typ into export/ (or use C-c p p for a PDF if Typst is installed)\n\n### Pinning and upgrades\n- Prefer pinning to a stable tag (e.g., :tag \"v0.1.2\" when available).\n- To update: bump the :tag or track main and run straight-pull followed by straight-rebuild.\n\n## Development\n\n### Running Tests\n```bash\nmake test\n# or\npython -m unittest discover tests -v\n```\n\n- The suite includes an optional PDF compile test that runs `pagemaker pdf` end-to-end and compiles via Typst. It automatically skips if `typst` or the `@preview/muchpdf` package are unavailable on your system.\n\n### Code Style & Pre-commit\n\nThis project uses pre-commit with Ruff for formatting and linting.\n\nSetup:\n```bash\npip install pre-commit\npre-commit install\n```\n\nRun hooks on the entire repo:\n```bash\npre-commit run --all-files\n```\n\nTools:\n- Formatter: Ruff formatter (`ruff-format`)\n- Linter: Ruff check with autofix\n\nCurrent temporary linter ignores (to keep commits unblocked):\n- E501 (line length) \u2014 many long Typst/doc lines\n- B028, B007 \u2014 non-critical warnings\n- UP006, UP035 \u2014 typing modernization postponed\n- F841 \u2014 temporary allowance for unused variables\n\nRun Ruff manually:\n```bash\nruff format .\nruff check . --fix\n```\n\nWe plan to remove the temporary ignores as the codebase is modernized.\n\n### Contributing\n1. Fork the repository at https://github.com/sanderboer/typst-pagemaker\n2. Create a feature branch\n3. Make your changes\n4. Add tests for new functionality\n5. Submit a pull request\n\n## License\n\nMIT License - see [LICENSE](https://github.com/sanderboer/typst-pagemaker/blob/main/LICENSE) file for details.\n\n## Author\n\nCreated for building Typst-based slide decks from Org-mode.\n\n---\n\n*For more detailed documentation, examples, and advanced usage patterns, see the `docs/` directory and `examples/` folder.*\n",
"bugtrack_url": null,
"license": null,
"summary": "Structured document-to-page layout system for Typst with explicit positioning and professional typography",
"version": "0.1.18",
"project_urls": {
"Homepage": "https://github.com/sanderboer/typst-pagemaker",
"Issues": "https://github.com/sanderboer/typst-pagemaker/issues",
"Repository": "https://github.com/sanderboer/typst-pagemaker"
},
"split_keywords": [
"typst",
" orgmode",
" layout",
" grid",
" slides",
" pdf"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "03f2dfc046c9089e932e6b10052c88bece08d20a0f32c564a8fc00b2938d4f2e",
"md5": "a887262ee859ec36771b1d37f01f9395",
"sha256": "ed946a771b91088cc90cc7bae5177101a0b16ee783ae12271cbbe5bcce643b94"
},
"downloads": -1,
"filename": "typst_pagemaker-0.1.18-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a887262ee859ec36771b1d37f01f9395",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 1415120,
"upload_time": "2025-10-09T10:34:51",
"upload_time_iso_8601": "2025-10-09T10:34:51.927479Z",
"url": "https://files.pythonhosted.org/packages/03/f2/dfc046c9089e932e6b10052c88bece08d20a0f32c564a8fc00b2938d4f2e/typst_pagemaker-0.1.18-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "fc2d9e82a9c20627b4ddcb7ec1c768671d8074633c8c3e34d706c647a9a59905",
"md5": "d0a93b9b038558b50429b2ca187e5839",
"sha256": "c50cca57298dbdbe2a1caeb0e3492d6c587eadcc336e3544e04625cda90bb93d"
},
"downloads": -1,
"filename": "typst_pagemaker-0.1.18.tar.gz",
"has_sig": false,
"md5_digest": "d0a93b9b038558b50429b2ca187e5839",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 1433168,
"upload_time": "2025-10-09T10:34:53",
"upload_time_iso_8601": "2025-10-09T10:34:53.845044Z",
"url": "https://files.pythonhosted.org/packages/fc/2d/9e82a9c20627b4ddcb7ec1c768671d8074633c8c3e34d706c647a9a59905/typst_pagemaker-0.1.18.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-09 10:34:53",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "sanderboer",
"github_project": "typst-pagemaker",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "typst-pagemaker"
}