The Paged Annual is a 134-page document built by driving the real editor. Every page is rendered twice — once by paged, once by InDesign from the same IDML — and the two rasters are compared for colour distance (ΔE2000) and structure (SSIM). The numbers below are that comparison, including the pages that fail it.
IDML in, the page InDesign would set, out
A Rust engine that reads InDesign documents and lays them out the way InDesign does — then paints them on the CPU, on WebGPU, or into print-grade PDF from one display list.
InDesign is the oracle












The engine repository carries its own gate as well: a licence-clear set of generated fixtures, each with a reference PDF exported by InDesign and thresholds for mean ΔE2000, p99 ΔE2000 and SSIM. Rendering changes are gated on them, and a threshold is tightened after a fix — never loosened to make a failure pass.
The screen, the test gate and the press read the same page
Composition ends in a display list — one per page, made of paths, images, gradients and interned glyph outlines. Three backends consume it unchanged: tiny-skia on the CPU, the reference for the fidelity gate; Vello on WebGPU, for every interactive frame in the editor and the viewer; and a PDF writer for print. Nothing is laid out twice, so nothing can disagree.
Edit one character, reuse the rest
The pipeline runs in four tiers. Laid-out paragraphs are cached under a hash of their content, unchanged stories are cheap to rebuild, and a text edit in one story reuses the pages it did not touch. That is what keeps an InDesign-class editor responsive inside a browser tab.
What is inside an .idml
IDML is InDesign's open interchange format: a ZIP of XML parts. The designmap names every spread, master and story; the resources carry the swatches, the styles and the preferences. paged reads the parts that decide the page and says plainly which ones it leaves to the host — fonts are supplied, never guessed.
A paragraph composer, not a line breaker
Text is shaped with harfrust, a Rust port of HarfBuzz, and set by a Knuth–Plass total-fit composer that weighs the whole paragraph before it breaks a line, with its penalties calibrated against InDesign. Dictionary hyphenation, tabs, nested styles, conditional text, super- and subscript and multi-font runs are part of the same pass.
Right-to-left scripts run in the same composer as Latin. Where a writing system is only partly supported — vertical Japanese is read but not yet set vertically — the Annual's margin says exactly how, and so does the conformance reference.

Every object has an address; one set writes any property
The engine names everything it holds — the document, a page, a frame, a swatch, a style, a table cell, a text range — in one address grammar with 30 forms, and selectors find them the way CSS finds elements. Every property has a typed schema; 403 of them are published in the capability catalog. A single set writes any of them, through the operation that already owns it, as one undo step.
// every frame on page 3 whose name starts with "price"
const frames = JSON.parse(paged.query('page:#3 > frame[name^=price]'));
// one batch: all or nothing, one rebuild, one undo step
paged.batch(frames.flatMap((address) => [
{ op: 'set', address, path: 'frameFillColor', value: 'Color/Black' },
{ op: 'set', address, path: 'frameFillTint', value: 10 },
]));
console.log(paged.get(frames[0], 'frameFillTint'));Undo, scripts and gestures share one path
Every change to a document is an operation: typed, serialisable and invertible. A drag in the editor, a line of a script and a command on the terminal all become the same operations, so they all undo the same way. Operations batch: a batch is atomic, costs one rebuild and lands as one undo step, however many objects it touches.
The command line cannot apply a change the editor cannot.
Snapping lives in the engine too: moves, resizes and path edits snap to every visible point and outline, the page, guides and the grid through one resolver in the engine, not in the user interface.
A PDF a printer will take
PDF export is the third backend over the same display list, written directly with pdf-writer. It is not a screenshot in a PDF wrapper: what was text is text, what was vector is vector, and the colour stays in the space the designer chose.
- Text stays text
- Subset CID fonts with ToUnicode maps — selectable, searchable, copyable.
- Native colour
- DeviceCMYK, ICC-based, Separation and Lab colour are kept, not flattened to RGB.
- Live transparency
- Blend modes and opacity stay live, PDF/X-4 style — no flattener.
- Images pass through
- JPEG data is written as it came, with no re-encode.
- Deterministic
- No clock, ids in walk order: the same input yields the same bytes.
- Gated
- CI rasterises the exported PDF and compares it with the engine's own render.
The whole engine, one binary
pageddrives the same typed door as the editor's worker, so it opens .paged containers as well as IDML and inherits fonts, colour management, PDF export, scripting and undo from the editor's own code path. Every operation in the catalog is a verb through paged invoke; a headless JSON session speaks the protocol line by line.
paged render annual.idml --page 3 --dpi 144 -o p3.png
paged inspect annual.idml --json
paged query annual.idml 'page:#3 > frame[name^=price]'
paged set annual.idml frame:u1f2 frameFillTint 10 -o annual.paged
paged script annual.paged build.js -o annual.pdf --render p1.png
paged export annual.paged --format pdf -o annual.pdf
paged diff indesign.png paged.png --heatmap heat.png
paged describe # the capability catalog, no document neededCore format features
| Character fill color color-swatches.character-fill | stable· 3 tests |
| Color groups (CRUD + membership) color-swatches.color-groups | stable· 35 tests |
| ColorOverride specials (paper/black/registration) color-swatches.color-overrides | stable· untested |
| Document defaults for new objects (fill/stroke/weight) color-swatches.document-defaults | stable· 19 tests |
| Apply fill/stroke color + tint to frames color-swatches.fill-stroke-apply | stable· 21 tests |
| Gradients (linear/radial, stops + midpoints) color-swatches.gradients | stable· 39 tests |
| ICC color management (lcms2 native / qcms wasm) color-swatches.icc-cmm | stable· 19 tests |
| Ink management (convert-to-process, aliases, standard Lab) color-swatches.ink-manager | stable· 6 tests |
| Lab / mixed-ink / spot-without-CMYK color-swatches.lab-mixed-ink | stable· 2 tests |
| CMYK overprint color-swatches.overprint | stable· 1 test |
| Process CMYK/RGB + spot inks + tints color-swatches.process-spot-tint | stable· 8 tests |
| Swatch CRUD (create/edit/delete + .ase import/export) color-swatches.swatch.crud | stable· 37 tests |
| Bevel & emboss effects-transparency.bevel-emboss | stable· 1 test |
| Blend modes (26 modes incl. multiply/screen/overlay) effects-transparency.blend-modes | stable· 1 test |
| Drop shadow (soft blur, offset, color, opacity) effects-transparency.drop-shadow | stable· 7 tests |
| Feather (basic + directional) effects-transparency.feather | stable· 1 test |
| Outer / inner glow effects-transparency.glows | stable· 2 tests |
| Gradient feather effects-transparency.gradient-feather | stable· 3 tests |
| Inner shadow effects-transparency.inner-shadow | stable· 2 tests |
| Object opacity effects-transparency.opacity | stable· 11 tests |
| Opacity masks — a real per-pixel soft mask (luminosity or alpha, invertible) effects-transparency.opacity-mask | stable· 6 tests |
| Satin effects-transparency.satin | stable· 1 test |
| Transparency groups (nested blend group buffering) effects-transparency.transparency-groups | stable· untested |
| IDML container open (ZIP + mimetype validation) foundations.container.open | stable· 3 tests |
| designmap parse (spreads, stories, resources wiring) foundations.designmap.structure | stable· untested |
| DOMVersion capture (version-agnostic parser) foundations.domversion-capture | stable· untested |
| Appearance stack bakes to a group of stacked page items (B-24) frames-paths.appearance-bake | stable· untested |
| GraphicLine arrowheads (triangle/circle/bar) frames-paths.arrowheads | stable· untested |
| Decorative corner options (Rounded/Inverse/Bevel/Inset/Fancy) frames-paths.corner-options | stable· 2 tests |
| Corner options on polygons (B-23) — apply arms, renderer, IDML write path frames-paths.corner-options-polygon | stable· untested |
| Delete frame frames-paths.frame.delete | stable· 9 tests |
| Insert frame (rectangle) by bounds frames-paths.frame.insert | stable· 49 tests |
| moveFrame wire op frames-paths.frame.move-op | stable· 1 test |
| Groups (nesting + group transparency/blending + create/dissolve ops) frames-paths.groups | stable· 33 tests |
| Insert line (two-anchor open GraphicLine) frames-paths.line.insert | stable· 29 tests |
| Nested page items (paste-into) — parse, render clip, pasteInto/releaseFrom frames-paths.nested-content | stable· untested |
| Page-item kinds (TextFrame, Rectangle, Oval, Polygon, GraphicLine, Group) frames-paths.page-item-kinds | stable· untested |
| Path clipping/masking (non-zero winding) frames-paths.path-clipping | stable· 1 test |
| closePath — close an open subpath (the faithful inverse of pathOpenAt) frames-paths.path.close | stable· untested |
| Insert freehand path (optional smoothing) frames-paths.path.insert | stable· 29 tests |
| joinPaths — weld two open paths into one element frames-paths.path.join | stable· untested |
| Pathfinder boolean (union/intersect/subtract/exclude) frames-paths.pathfinder-boolean | stable· 21 tests |
| Divide / Trim / Merge / Crop / Outline / Minus Back frames-paths.pathfinder-verbs | stable· untested |
| Planar arrangement — faces of overlapping paths (B-22) frames-paths.planar-arrangement | stable· untested |
| Ellipse / polygon shape tools frames-paths.shape-tools | stable· 25 tests |
| Stroke alignment (center/inside/outside) frames-paths.stroke-alignment | stable· 9 tests |
| Dashed + dotted strokes (dash arrays, 12 dotted variants) frames-paths.stroke-dashed | stable· 2 tests |
| Stroke gap color/tint frames-paths.stroke-gap-color | stable· 4 tests |
| Stroke overprint frames-paths.stroke-overprint | stable· 1 test |
| Striped / wavy strokes frames-paths.stroke-striped-wavy | stable· 6 tests |
| Variable-width (tapered / pressure) strokes — per-anchor width outline frames-paths.stroke-variable-width | stable· 6 tests |
| Stroke weight + line caps + joins frames-paths.stroke-weight-caps-joins | stable· 12 tests |
| Text on a path frames-paths.text-on-path | stable· 2 tests |
| Bezier path geometry (PathPointType anchors + handles) geometry-coordinates.bezier-path-geometry | stable· 8 tests |
| Compound paths (multi-contour subpath boundaries) geometry-coordinates.compound-subpaths | stable· 1 test |
| GeometricBounds (y1 x1 y2 x2, pt) geometry-coordinates.geometric-bounds | stable· 3 tests |
| Image content transform (inner image within frame) geometry-coordinates.image-content-transform | stable· 12 tests |
| ItemTransform (2×3 affine per frame/page) geometry-coordinates.item-transform | stable· 2 tests |
| Path topology ops (insert/remove anchor, open-at, curve type) geometry-coordinates.path-topology-ops | stable· 23 tests |
| Composition part (paged/core/composition/document.pgd — arrangement) package-anatomy.composition-part | stable· 1 test |
| Full package IMPORT — IDML adapter (designmap, spreads, stories, resources) package-anatomy.core-import | stable· 7 tests |
| Graphic part (colors, swatches, gradients, inks, stroke styles) package-anatomy.graphic-part | stable· untested |
| Inline base64 image bytes (<Image><Properties><Contents>) package-anatomy.inline-image-contents | stable· untested |
| Native model part (paged/core/model/document.pgm — the self-owning document) package-anatomy.native-model-part | stable· 1 test |
| The .paged container (ZIP-as-valid-IDML + plugin namespaces + manifest.json) package-anatomy.paged-container | stable· 5 tests |
| host.parts plugin persistence door (namespaced container parts that travel with the file) package-anatomy.paged-parts-door | stable· 6 tests |
| Story parts (ParagraphStyleRange / CharacterStyleRange trees) package-anatomy.story-parts | stable· untested |
| Tagged XML backing store (XMLElement/XMLStory/Mapping) package-anatomy.tagged-xml-backing-store | planned· untested |
| Text caret + range selection (geometry, content selection) stories-text.caret-selection | stable· 24 tests |
| Drag-and-drop text stories-text.drag-drop-text | planned· untested |
| Endnotes stories-text.endnotes | planned· untested |
| Insert field (page-number marker etc.) at offset stories-text.fields.insert | stable· 1 test |
| Footnote bodies stories-text.footnotes | stable· 1 test |
| Nested character styles (per-delimiter run restyling) stories-text.nested-styles | stable· untested |
| Editorial notes (Note element) stories-text.notes | experimental· 1 test |
| Overset handling (last-frame overflow clipped + reported) stories-text.overset | stable· 4 tests |
| Auto page-number markers (current/next page) stories-text.page-number-markers | stable· untested |
| Story model (paragraph/character run trees) stories-text.story-model | stable· 6 tests |
| Apply style attributes to a text range (applyStyle op) stories-text.style-apply-range | stable· 4 tests |
| Text wrap (bounding box / contour / jump modes + offsets) stories-text.text-wrap | stable· 3 tests |
| Delete story range (Backspace/Delete + range) stories-text.text.delete | stable· 13 tests |
| Insert text at story offset stories-text.text.insert | stable· 17 tests |
| Tracked changes (insertions/deletions, author/date) stories-text.tracked-changes | planned· untested |
| Alternating row/column fills tables.alternating-fills | stable· 2 tests |
| Table borders + row/column dividers tables.borders-strokes | stable· untested |
| Per-cell text composition (cell as mini-frame) tables.cell-composition | stable· untested |
| Cell diagonal lines tables.cell-diagonals | stable· 2 tests |
| Cell rotation tables.cell-rotation | stable· untested |
| Cell vertical justification tables.cell-vertical-justification | stable· untested |
| Repeating header/footer rows across chain breaks tables.header-footer-repeat | stable· untested |
| Table model (rows, columns, cells) tables.model | stable· 22 tests |
| Tables inside cells tables.nested-tables | stable· untested |
| Row height constraints + column widths tables.row-col-sizing | stable· untested |
| Row/column spans (cell merges) tables.spans | stable· untested |
| Table/cell style cascade (region defaults) tables.style-cascade | stable· untested |
| Typed collections read surface (21 collections) the-renderer.collections-read | stable· 22 tests |
| CPU backend (tiny-skia, full feature coverage) the-renderer.cpu-backend | stable· 50 tests |
| Scene-graph introspection (tree + property descriptors) the-renderer.devtools-introspection | stable· 9 tests |
| Versioned display list IR (41 command kinds, path interning) the-renderer.display-list | stable· 9 tests |
| Export diagnostics (preflight findings) the-renderer.export-diagnostics | stable· 23 tests |
| Font registration (family/style → bytes, persists across loads) the-renderer.font-registry | stable· 4 tests |
| WebGPU backend (Vello) the-renderer.gpu-backend | stable· untested |
| Hit testing (oriented containment, layer-aware) + marquee the-renderer.hit-testing | stable· 10 tests |
| Missing-asset degraded render (fallback font + placed-link placeholder) the-renderer.missing-asset-fallback | experimental· 6 tests |
| OffscreenCanvas worker rendering (COOP/COEP + SAB) the-renderer.offscreen-worker | stable· 10 tests |
| Package / collect for output (links + fonts + report) — IN SCOPE, not built the-renderer.package-collect | planned· untested |
| PDF export (PDF 1.7 + PDF/X-4, deterministic) the-renderer.pdf-export | stable· 24 tests |
| Export marks + bleed (crop/registration/color bars/page info) the-renderer.pdf-export-marks | stable· 23 tests |
| Export font subsetting + embedding (fsType policy) the-renderer.pdf-font-embedding | stable· 2 tests |
| Export image downsampling + JPEG re-encode the-renderer.pdf-image-downsampling | stable· 1 test |
| Render pipeline (parse → scene → text → compose → raster) the-renderer.pipeline | stable· 4 tests |
| Element properties read (authored/computed/source) the-renderer.properties-read | stable· 24 tests |
| GPU scene cache (LRU, invalidation hints) the-renderer.scene-cache | stable· 6 tests |
| Display-list structural digest (same-code-same-scene keystone) the-renderer.scene-digest | stable· 1 test |
| Snap engine (page edges + sibling targets, 4 px tolerance) the-renderer.snapping | stable· 16 tests |
| Page PNG snapshots (dpi-configurable) the-renderer.snapshots | stable· 8 tests |
| Viewer session — camera present, page layout, events (the public SDK) the-renderer.viewer-session | stable· 2 tests |
| @paged-media/idml-viewer — TS viewer (camera, pages, input lanes, events) the-renderer.viewer-wrapper | stable· untested |
| Baseline shift typography.baseline-shift | stable· 3 tests |
| Bidirectional text reordering typography.bidi | stable· untested |
| Capitalization (AllCaps/SmallCaps/CapToSmallCap) typography.capitalization | stable· 3 tests |
| CJK vertical writing typography.cjk-vertical-writing | stable· untested |
| Drop caps (characters/lines + detail scaling) typography.drop-caps | stable· 1 test |
| Font selection + fallback (AppliedFont/FontStyle/PointSize) typography.font-selection | stable· 14 tests |
| Hyphenation (TeX patterns; Proximity licensed) typography.hyphenation | stable· 1 test |
| Hyphenation zone typography.hyphenation-zone | stable· 2 tests |
| Word/letter spacing + glyph scaling (min/desired/max) typography.justification-spacing | stable· untested |
| Kenten emphasis marks typography.kenten | stable· untested |
| Kinsoku CJK line-break rules typography.kinsoku | stable· untested |
| Knuth–Plass line breaking + justification modes typography.knuth-plass | stable· untested |
| Leading (explicit pt / auto) typography.leading | stable· 3 tests |
| Ligatures + OpenType feature toggles typography.ligatures-opentype | stable· 5 tests |
| Mojikumi CJK spacing typography.mojikumi | stable· untested |
| Position (superscript/subscript) typography.position-super-subscript | stable· 3 tests |
| Ruby annotations typography.ruby | stable· untested |
| HorizontalScale + Skew (false italic) typography.scale-skew | stable· 4 tests |
| Tab stops (L/C/R/decimal + leaders) typography.tab-stops | stable· 1 test |
| Tracking + kerning (metrics; optical falls back to metrics) typography.tracking-kerning | stable· 4 tests |
| Underline / strikethrough decorations typography.underline-strikethru | stable· 3 tests |
| VerticalScale typography.vertical-scale | stable· 3 tests |
Core format, verified
| Character fill color | stable· 3 tests |
| Color groups (CRUD + membership) | stable· 35 tests |
| ColorOverride specials (paper/black/registration) | stable· untested |
| Document defaults for new objects (fill/stroke/weight) | stable· 19 tests |
| Apply fill/stroke color + tint to frames | stable· 21 tests |
| Gradients (linear/radial, stops + midpoints) | stable· 39 tests |
| ICC color management (lcms2 native / qcms wasm) | stable· 19 tests |
| Ink management (convert-to-process, aliases, standard Lab) | stable· 6 tests |
| Lab / mixed-ink / spot-without-CMYK | stable· 2 tests |
| CMYK overprint | stable· 1 test |
| Process CMYK/RGB + spot inks + tints | stable· 8 tests |
| Swatch CRUD (create/edit/delete + .ase import/export) | stable· 37 tests |
| Bevel & emboss | stable· 1 test |
| Blend modes (26 modes incl. multiply/screen/overlay) | stable· 1 test |
| Drop shadow (soft blur, offset, color, opacity) | stable· 7 tests |
| Feather (basic + directional) | stable· 1 test |
| Outer / inner glow | stable· 2 tests |
| Gradient feather | stable· 3 tests |
| Inner shadow | stable· 2 tests |
| Object opacity | stable· 11 tests |
| Opacity masks — a real per-pixel soft mask (luminosity or alpha, invertible) | stable· 6 tests |
| Satin | stable· 1 test |
| Transparency groups (nested blend group buffering) | stable· untested |
| IDML container open (ZIP + mimetype validation) | stable· 3 tests |
| designmap parse (spreads, stories, resources wiring) | stable· untested |
| DOMVersion capture (version-agnostic parser) | stable· untested |
| Appearance stack bakes to a group of stacked page items (B-24) | stable· untested |
| GraphicLine arrowheads (triangle/circle/bar) | stable· untested |
| Decorative corner options (Rounded/Inverse/Bevel/Inset/Fancy) | stable· 2 tests |
| Corner options on polygons (B-23) — apply arms, renderer, IDML write path | stable· untested |
| Delete frame | stable· 9 tests |
| Insert frame (rectangle) by bounds | stable· 49 tests |
| moveFrame wire op | stable· 1 test |
| Groups (nesting + group transparency/blending + create/dissolve ops) | stable· 33 tests |
| Insert line (two-anchor open GraphicLine) | stable· 29 tests |
| Nested page items (paste-into) — parse, render clip, pasteInto/releaseFrom | stable· untested |
| Page-item kinds (TextFrame, Rectangle, Oval, Polygon, GraphicLine, Group) | stable· untested |
| Path clipping/masking (non-zero winding) | stable· 1 test |
| closePath — close an open subpath (the faithful inverse of pathOpenAt) | stable· untested |
| Insert freehand path (optional smoothing) | stable· 29 tests |
| joinPaths — weld two open paths into one element | stable· untested |
| Pathfinder boolean (union/intersect/subtract/exclude) | stable· 21 tests |
| Divide / Trim / Merge / Crop / Outline / Minus Back | stable· untested |
| Planar arrangement — faces of overlapping paths (B-22) | stable· untested |
| Ellipse / polygon shape tools | stable· 25 tests |
| Stroke alignment (center/inside/outside) | stable· 9 tests |
| Dashed + dotted strokes (dash arrays, 12 dotted variants) | stable· 2 tests |
| Stroke gap color/tint | stable· 4 tests |
| Stroke overprint | stable· 1 test |
| Striped / wavy strokes | stable· 6 tests |
| Variable-width (tapered / pressure) strokes — per-anchor width outline | stable· 6 tests |
| Stroke weight + line caps + joins | stable· 12 tests |
| Text on a path | stable· 2 tests |
| Bezier path geometry (PathPointType anchors + handles) | stable· 8 tests |
| Compound paths (multi-contour subpath boundaries) | stable· 1 test |
| GeometricBounds (y1 x1 y2 x2, pt) | stable· 3 tests |
| Image content transform (inner image within frame) | stable· 12 tests |
| ItemTransform (2×3 affine per frame/page) | stable· 2 tests |
| Path topology ops (insert/remove anchor, open-at, curve type) | stable· 23 tests |
| Composition part (paged/core/composition/document.pgd — arrangement) | stable· 1 test |
| Full package IMPORT — IDML adapter (designmap, spreads, stories, resources) | stable· 7 tests |
| Graphic part (colors, swatches, gradients, inks, stroke styles) | stable· untested |
| Inline base64 image bytes (<Image><Properties><Contents>) | stable· untested |
| Native model part (paged/core/model/document.pgm — the self-owning document) | stable· 1 test |
| The .paged container (ZIP-as-valid-IDML + plugin namespaces + manifest.json) | stable· 5 tests |
| host.parts plugin persistence door (namespaced container parts that travel with the file) | stable· 6 tests |
| Story parts (ParagraphStyleRange / CharacterStyleRange trees) | stable· untested |
| Tagged XML backing store (XMLElement/XMLStory/Mapping) | planned· untested |
| Text caret + range selection (geometry, content selection) | stable· 24 tests |
| Drag-and-drop text | planned· untested |
| Endnotes | planned· untested |
| Insert field (page-number marker etc.) at offset | stable· 1 test |
| Footnote bodies | stable· 1 test |
| Hidden text handling | experimental· 1 test |
| Nested character styles (per-delimiter run restyling) | stable· untested |
| Editorial notes (Note element) | experimental· 1 test |
| Overset handling (last-frame overflow clipped + reported) | stable· 4 tests |
| Auto page-number markers (current/next page) | stable· untested |
| Story model (paragraph/character run trees) | stable· 6 tests |
| Apply style attributes to a text range (applyStyle op) | stable· 4 tests |
| Text wrap (bounding box / contour / jump modes + offsets) | stable· 3 tests |
| Delete story range (Backspace/Delete + range) | stable· 13 tests |
| Insert text at story offset | stable· 17 tests |
| Tracked changes (insertions/deletions, author/date) | planned· untested |
| Alternating row/column fills | stable· 2 tests |
| Table borders + row/column dividers | stable· untested |
| Per-cell text composition (cell as mini-frame) | stable· untested |
| Cell diagonal lines | stable· 2 tests |
| Cell rotation | stable· untested |
| Cell vertical justification | stable· untested |
| Repeating header/footer rows across chain breaks | stable· untested |
| Table model (rows, columns, cells) | stable· 22 tests |
| Tables inside cells | stable· untested |
| Row height constraints + column widths | stable· untested |
| Row/column spans (cell merges) | stable· untested |
| Table/cell style cascade (region defaults) | stable· untested |
| Typed collections read surface (21 collections) | stable· 22 tests |
| CPU backend (tiny-skia, full feature coverage) | stable· 50 tests |
| Scene-graph introspection (tree + property descriptors) | stable· 9 tests |
| Versioned display list IR (41 command kinds, path interning) | stable· 9 tests |
| Export diagnostics (preflight findings) | stable· 23 tests |
| Font registration (family/style → bytes, persists across loads) | stable· 4 tests |
| WebGPU backend (Vello) | stable· untested |
| Hit testing (oriented containment, layer-aware) + marquee | stable· 10 tests |
| Missing-asset degraded render (fallback font + placed-link placeholder) | experimental· 6 tests |
| OffscreenCanvas worker rendering (COOP/COEP + SAB) | stable· 10 tests |
| Package / collect for output (links + fonts + report) — IN SCOPE, not built | planned· untested |
| PDF export (PDF 1.7 + PDF/X-4, deterministic) | stable· 24 tests |
| Export marks + bleed (crop/registration/color bars/page info) | stable· 23 tests |
| Export font subsetting + embedding (fsType policy) | stable· 2 tests |
| Export image downsampling + JPEG re-encode | stable· 1 test |
| Render pipeline (parse → scene → text → compose → raster) | stable· 4 tests |
| Element properties read (authored/computed/source) | stable· 24 tests |
| GPU scene cache (LRU, invalidation hints) | stable· 6 tests |
| Display-list structural digest (same-code-same-scene keystone) | stable· 1 test |
| Snap engine (page edges + sibling targets, 4 px tolerance) | stable· 16 tests |
| Page PNG snapshots (dpi-configurable) | stable· 8 tests |
| Viewer session — camera present, page layout, events (the public SDK) | stable· 2 tests |
| @paged-media/idml-viewer — TS viewer (camera, pages, input lanes, events) | stable· untested |
| Baseline shift | stable· 3 tests |
| Bidirectional text reordering | stable· untested |
| Capitalization (AllCaps/SmallCaps/CapToSmallCap) | stable· 3 tests |
| CJK vertical writing | stable· untested |
| Drop caps (characters/lines + detail scaling) | stable· 1 test |
| Font selection + fallback (AppliedFont/FontStyle/PointSize) | stable· 14 tests |
| Hyphenation (TeX patterns; Proximity licensed) | stable· 1 test |
| Hyphenation zone | stable· 2 tests |
| Word/letter spacing + glyph scaling (min/desired/max) | stable· untested |
| Kenten emphasis marks | stable· untested |
| Kinsoku CJK line-break rules | stable· untested |
| Knuth–Plass line breaking + justification modes | stable· untested |
| Leading (explicit pt / auto) | stable· 3 tests |
| Ligatures + OpenType feature toggles | stable· 5 tests |
| Mojikumi CJK spacing | stable· untested |
| Position (superscript/subscript) | stable· 3 tests |
| Ruby annotations | stable· untested |
| HorizontalScale + Skew (false italic) | stable· 4 tests |
| Tab stops (L/C/R/decimal + leaders) | stable· 1 test |
| Tracking + kerning (metrics; optical falls back to metrics) | stable· 4 tests |
| Underline / strikethrough decorations | stable· 3 tests |
| VerticalScale | stable· 3 tests |