Rendering
The engine separates what gets compiled (setTarget) from how you turn
the result into pixels or files (render and export).
Targets
core.setTarget(target) keeps one artifact pipeline warm. It accepts
'pdf' | 'svg' | 'png' | 'html' | 'none' ('none' = diagnostics only, no
artifact). It's independent of export() - preview as SVG, still export PDF.
The render loop
onPages fires after every compile that changes layout, with each page's size
in points. Render from there:
Canvas (raster)
renderToCanvas draws one <canvas> per page into the container, replacing its
children. It oversamples by devicePixelRatio for hi-DPI sharpness (override
with dpr).
Sizing is either { fit: 'width' } (re-run on resize) or { zoom } (CSS pixels
per Typst point) - there is no fit: 'height' or fit: 'page'. To paint a
single page yourself:
SVG
Export each page and inline the markup:
HTML
HTML export returns a full document; render it in an iframe:
Outline
onOutline emits the document's heading outline after every compile - the same
set #outline() renders. Use it for a navigation sidebar.
Each entry is { level, title, position, children? }. position is
{ page, x, y } - page is 0-based (it indexes straight into the pages
array), x/y are in points.
Export
core.export(args) returns { data: Uint8Array, mime: string }.
| format | scope | call |
|---|---|---|
pdf | whole document | core.export({ format: 'pdf', standards? }) |
html | whole document | core.export({ format: 'html' }) |
svg | one page (zero-based) | core.export({ format: 'svg', index }) |
png | one page (zero-based) | core.export({ format: 'png', index, ppi? }) |
png takes an optional ppi (default 144). pdf takes an optional standards
array to produce archival/accessible output, e.g. ['a-2b'] for PDF/A-2b.
PDF/A has hard requirements - notably every font must be embeddable. When export can't meet a standard it rejects with the compiler's actual reason and hints; surface that message to the user.