Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Compatibility, Limits And Migration

This guide describes the supported contract of Deixis 0.2.0. The previous release, @preview/deixis:0.1.1, has a different API. Deixis requires Typst 0.15.0 or newer and supports Touying 0.6.3 and 0.8.0. The supported behavior and remaining boundaries are described below.

Supported Behavior

AreaContract
Identityid: creates/names; of: attaches/reuses. An original, its body and reused marks may appear in any order. One original and at most one body per annotation. A standalone body’s ID is not an original-mark placeholder.
Marks and referencesdeixis-mark covers inline, region and phantom forms; specialized names remain available. Reuse shares numbering/body and adds a return origin. @id / deixis-ref formats a reference rather than a measured mark occurrence.
Body placementThe body adapter owns placement. Margin bodies follow the mark/anchor; footnotes allocate at their native declaration/collection; inline bodies stay in flow; inset bodies use their declaration/placement; endnotes use a printer. Identity lookup does not move native allocations.
Invisible declarationsOverlay margin/inset and collected endnote body declarations add no flow whitespace. Page footnotes intentionally reserve space. Native place for flow margin/inset bodies can interrupt paragraphs.
ConnectionsBody connector: supplies the original-to-body shorthand. Independent deixis-connect calls add edges, including deliberate duplicates. Reused marks never inherit an edge. Forward endpoints and named occurrences work.
Continuation visualsDefault dots, optional hollow portals and suppression use the existing continuation field. Native presets support size/style and optional peer/counterpart links. Endpoint heads, including the filled open-notch stealth, remain independent.
FramesAccepted single painted margin/inset frames and explicitly framed inline bodies provide rectangle ports. Native live body start/end points can select collected or paginated bodies. Partial, missing or duplicate geometry is diagnosed.
Pins and attachmentsPins, attachment IDs and annotation IDs have separate namespaces. String/label spellings agree. Pin targets share scope/select/physical-page rules. Attachments capture one live frame; equal names or containing rectangles do not merge owners.
Drawing orderHigher z-index paints later within an overlay layer. Equal priorities keep documented command/group order. Flow, foreground, background and host composition retain their separate order; grouped layouts can be atomic.
Routingdeixis-route supplies native line/cubic geometry. Scenes register fixed accepted rectangles and opt-in avoid/ignore/cut/cross behavior. Numeric groups return plans; deixis-routing scopes collect individual document edges. Use the public facade for these APIs.
Host integrationNative hiding suppresses deferred visuals while retaining semantic identities/counters. Reapply setup after replacing native page layers, or let the host own both hooks. Touying frame-local IDs require the documented pre-layout callback recipe.

Use identities, body ownership, rendering, setup, and independent connections for adapter-specific details.

Unified Note Queries

deixis-page-notes is removed in 0.2. Use deixis-query-notes(page: here().page()), replacing note-type: with include-types:, marker-str with marker, and body-type with type. Page selections default to native body order and include standalone bodies; plain catalogue queries retain paired annotations in source order. Override order: and include-unpaired: explicitly when needed. All modes return safe semantic records, never executable renderer data. Incomplete/duplicate custom spans do not provide page membership. See query migration.

Routing Boundaries

Automatic avoidance is opt-in and uses registered fixed geometry. It does not discover arbitrary text, figures or other document ink. Add attachments or select accepted note/pin geometry with deixis-routing(nodes: ...). It routes edges; it never packs or moves those objects. Native overlay-margin packing remains a separate body-placement mechanism. Flow-margin collision avoidance and collision checks between body layers are not implemented.

The automatic avoid/separate policies use sharp orthogonal paths with zero radius. Curves, rounded routes and mixed sections retain manual/native routing and scene cut/cross interactions. avoid searches each edge independently; separate also attempts bounded group repair. Successful plans need not eliminate all crossings, contacts or shared lanes and are not globally optimal.

Avoidance promises centerline clearance against registered inflated rectangles. Stroke width, arrowhead extents, gap indicators and custom painter ink can extend outside that centerline contract. Increase clearance/padding or choose explicit geometry when that ink matters. Automatic bridges, line jumps, smoothing and general ink-aware routing remain future visual/features work. Crossing gaps and manual cuts/indicators are optional and retain their existing settings.

Automatic continuation points stay in a page-local interval: the accepted margin body’s selected channel, or content width for other destinations. connector.spill can select content/page/custom bounds. Opposite spill points do not share a required x coordinate; use an exact split when that coordinate is deliberate. Marker ink/badge packing remain separate from these point bounds.

The current checked bounds are 128 scene nodes, sixteen enabled visible fragments per routing scope/physical page/layer, and eight exact visits per searched fragment. Search/cell/group budgets bound work and can produce an explicit failure. No unchecked route is painted on failure. Numeric group callers inspect each result’s status before preparing/painting it; document adapters diagnose it. Read-only planning callbacks may run more than once during native layout.

Groups are independent across physical pages, overlay layers and nested routing scopes. Attachments remain page-wide; scoped nodes: lists replace the outer list and restore it on exit. Endpoint lookup and repeated IDs on Touying subslides retain their physical-page rules. Cross-page connectors draw source/destination fragments only; intermediate pages have no shaft. Automatic spill points may move within permitted boundary choices, while exact split positions, sockets and waypoints stay fixed. Counterpart links target actual accepted peer geometry; they do not require equal coordinates across differently sized pages.

See document policies, scenes, numeric groups, and connector continuations.

Native Layout Boundaries

Overlay placement uses existing pages; it cannot create pages for spillover. Page footnotes use native flow by default and paginate; an opt-in overlay footnote must fit its assigned reserved frame. Empty paragraph boundaries and parent-scope floats can prevent native footer allocation; the package diagnoses these cases instead of inserting whitespace. Ordinary column-scope floats have maintained support.

Local table/figure notes use deixis-block; float the complete block to keep the collection with the figure. Repeated table headers reuse marks or references, without creating originals/bodies or named occurrences again. See local notes.

Arbitrary native fragments do not automatically become complete body rectangles. Use breakable: false for a single-frame inline body, or a live start/end point for a paginated body. Region marks retain their explicit page-fragment rules. Wrapping a deferred overlay declaration names its empty declaration frame, not its painted body; use a body selector for the latter.

Typst has a finite contextual layout-pass budget. Deep deferred note/scope/ collection chains, dense flow layouts and custom callbacks that need later geometry can still fail to converge. Arbitrary recursive layouts are not guaranteed to converge. Scoped native page styles should use the host-owned hook pattern because captured decorations do not restore automatically through nested lexical page scopes.

See footnote/rendering limits, paginated blocks, scopes inside notes, custom renderers, and scoped page styles.

Output Formats

Deixis targets paged output: PDF, PNG and SVG. Typst 0.15’s HTML export is experimental and has no pages or page layers. With --features html --format html, Deixis keeps every annotation body and its navigation, and drops geometry:

  • Page footnotes, including overlay layers, print in Typst’s footnote section.
  • Margin, inset and comment bodies follow the document as one list, <aside class="deixis-notes">, in declaration order.
  • Endnote printers and block-local footnotes print <ol class="deixis-notes"> lists where they run, without separators or spacing.
  • Markers link to their bodies, and body markers and backlinks return to the marks through deixis-mark-*/deixis-body-* ids. References and note outlines link the same way; outlines omit page numbers.
  • Inline decorations keep native underline and highlight. Box and parenthesis edges, region shapes, pins, connectors and other page paint are omitted without diagnostics.

See the HTML endnote example. With Typst 0.15.0+, compile it with:

typst compile --features html --format html examples/html-endnotes.typ target/html-endnotes.html

The body marker itself is a return link even with the default backlink setting; backlink: true adds a separate return button. Each selected series has its own list, and separate printers retain print-once ownership.

Built-in renderers and containers emit plain inline text. Custom renderers, containers and margin layouts, and direct drawing calls such as deixis-render-connector or deixis-absolute-place, run as written; Typst warns about layout elements in them that HTML ignores, as it does for the document’s own set page rules. Typst also drops placed content (place, floating figures) from HTML, including annotations declared inside it. Page references (form: "page") and Touying slides have no HTML equivalent. Page-local numbering has no page boundaries in HTML and displays one continuous sequence per counter owner and series. Margin, inset and inline notes, Deixis footnotes and native footnotes declared inside an endnote body converge in PDF and HTML, as do margin notes inside margin bodies. HTML footnotes cost Typst another layout pass, so documents near the convergence budget can fail in HTML even when paged output converges: Deixis notes declared inside a Deixis footnote body work in PDF but exceed the budget in HTML, where a nested footnote can also report a missing native footer allocation. Long forward-attachment chains retain the same convergence limit.

Tagged PDF output, including --pdf-standard ua-1, compiles without diagnostics. Native footnotes are tagged as notes beside their marks, and markers are tagged links. Overlay bodies (margin, inset and comment notes) are painted in a page layer, so assistive technology reaches them after the page’s flow content, without a note role. When explanations must be read beside their marks, prefer native footnotes or inline notes; endnotes read as a list where they are printed.

Known Limits

  • HTML export: upstream export remains experimental. Deixis preserves note bodies and navigation through a semantic fallback, while page geometry and connectors are omitted. Custom layouts and placed content retain the limits described above.
  • Accessibility: overlay bodies follow page-flow content in tagged PDFs and lack a note role. Use native footnotes or inline notes when reading beside the mark is essential.
  • Margin collisions: flow margins have no collision packing, and body layers have no shared collision checks. Overlay-margin packing operates within existing frames.
  • Convergence: Typst’s finite layout-pass budget bounds deep deferred scopes, forward attachments and geometry-dependent callbacks. Page-local numbering and HTML footnotes also depend on layout passes. Arbitrary recursive layouts are not guaranteed to converge.

Migrate From 0.1.1

Update imports to #import "@preview/deixis:0.2.0": * first. Typst downloads the package from Typst Universe automatically. See the installation guide.

Previous usage0.2 contract
label: <n> on a noteUse id: <n> for creation. There is no secondary body alias; update references to the original ID.
A body/wrapper id: <n> intended to attach to an originalUse of: <n>. Body-only id: creates a standalone body; wrapper id: creates an original and body.
Attached body/wrapper relies on the caller’s scopeIt now inherits the original rendering instance. Set target: 0 deliberately to select the caller’s scope.
series: or original-mark options on an attached body/wrapperPut creation options on the original; local repeated-mark decoration belongs on the reused mark.
Attached inline body inherits the original’s marker callbackIts marker now follows local body options and body-declaration defaults, consistently with the other adapters. Pass marker-style: on the body to deliberately reuse a custom callback.
The style component key link, as in stroke: (body: ..., link: ...) or z-index: (link: 2)Use connector, as in stroke: (body: ..., connector: gray). The old key is diagnosed.
link, link-ports, link-waypoints, link-marks, link-heads on margin/inset notes or deixis-setUse connector. A route name is shorthand: connector: "curve". Otherwise connector: (route: ..., ports: ..., via: ..., heads: ...); link-marks: "body" becomes heads: "stealth", "both" becomes heads: (mark: "stealth", body: "stealth"). Note records merge with deixis-set(connector: ...) defaults. The removed names are diagnosed.
Page footnotes painted in the foreground by defaultThey now use native flow and paginate. deixis-setup-notes.with(override-page-footnotes: true) restores the overlay default; layer: still selects one note’s layer.
deixis-set(separator:, clearance:, gap:) for page footnotesPage footnotes share the native footer; use a document-level set footnote.entry(...). The Deixis options still style block collections and endnotes.
Page footnote bodies copy the declaration’s text styleThey use the native footer typography, so notes in headings or emphasized text print as ordinary footnotes. Margin, inset and endnote bodies still capture declaration typography.
Margin connector implicitly follows its body’s layerConnections default to foreground independently of the body. Set connector: (layer: "background") when needed.
Flat arbitrary container arguments on note callsPut them in container-args: (...); unknown note keywords are diagnosed. Keep style options on the note.
Per-name scanned padding mapUse pin-padding: (...), with padding: as the uniform fallback. Geometric pin padding remains separate from endpoint gaps.
Outline include-celibates and old callback recordsUse include-unpaired; callbacks receive semantic query records and structured body descriptions. Runtime identity is note.id; custom fields live in note.data.
deixis-default-render-single / deixis-default-render-groupUse deixis-aligned-render-single / deixis-aligned-render-group; short aliases are aligned-render-single / aligned-render-group. No compatibility aliases.
deixis-set-pin-pattern(prefix:, postfix:)Set delimiters on deixis-attach, or bind deixis-attach.with(prefix: "[", postfix: "]"). Default scanning still uses deixispin and an empty postfix.
deixis-highlight-rect-region / deixis-highlight-ellipse-regionUse deixis-region-mark(stroke: none); add region-shape: deixis-ellipse-region for an ellipse.
deixis-group-layoutChoose a public group renderer through render-group: on settings or a collection printer.
deixis-default-footnote-styleSupply a body-style callback, such as it => text(size: 0.85em, it). Page footnotes use native footer typography.
deixis-show-refsUse #show: deixis-setup-notes, which installs the reference bridge automatically.
deixis-place-anchored(internal-id: ...)Use public pin targets via pin:. Inset note adapters resolve original marks internally.
deixis-minipage(margin: ...)Preserved: margin supplies internal padding (inset: margin, outset: 0pt), as in 0.1.1. It does not add external margins.
Internal module paths or underscore helpersImport the public facade src/lib.typ (or the package). Internal source paths, mutable state and private record shapes may change.

There are no compatibility aliases for removed label: or repeat-only calls. Unknown IDs, duplicate originals/bodies and unresolved of: targets diagnose rather than silently selecting a different object. Details and examples live in identity migration, containers, pins, and outlines.

The 0.2.0 API is supported within these limits. The illustrated manual, guides, and agent skill describe this release. When updating from another version, check the migration table above and keep the imported package version consistent with the examples.

Factory Appearance Changes

Unconfigured decorations now use muted blue-gray #496579 instead of bright red. Mark fills use 6% accent opacity. The margin/inset/inline marker-to-body gap is 0.25em instead of 0.05em; native-style footnotes retain 0.05em and endnotes keep 0.75em. The larger gap can affect wrapping, margin packing and footnote reservation. Explicit colors/gaps, body text styling and renderer precedence remain authoritative. See appearance for the earlier-default recipe. Named palettes and color arrays are opt-in through deixis-set(palette: "deixis") or deixis-set(palette: colors); explicit styles retain precedence and ordinary no-palette appearance stays unchanged.