Typst Render

Quarto Extension

A Quarto filter extension that compiles ```{typst} code blocks to images (PNG, SVG, or PDF) using the Typst binary bundled with Quarto. This makes Typst diagrams, figures, tables, and equations usable across all output formats (HTML, PDF via LaTeX, DOCX, RevealJS, and more).

By default, blocks are compiled to images for all output formats, including Typst. Use output: asis for native passthrough when the output format is Typst.

Installation

quarto add mcanouil/quarto-typst-render@0.12.0

This will install the extension under the _extensions subdirectory.

If you are using version control, you will want to check in this directory.

Usage

To use the extension, add the following to your document’s front matter:

filters:
  - typst-render

For cross-referencing support, use timing control:

filters:
  - path: typst-render
    at: pre-quarto

Then write Typst code blocks in your document:

```{typst}
#set text(size: 16pt)
Hello from *Typst*!
```

Basic Usage

A simple Typst block rendered as an image:

```{typst}
#set text(size: 16pt)
Hello from *Typst*!
This is rendered as an image in all output formats.
```

#set text(size: 16pt)
Hello from *Typst*!
This is rendered as an image in all output formats.

Per-Block Options

Use comment+pipe syntax (//| key: value) at the top of the code block to set per-block options.

Page Dimensions

Control the width, height, and margin of the rendered image page. These options set the Typst page dimensions for image compilation. With output: asis, width and height are ignored; margin is applied as block inset.

```{typst}
//| width: 12cm
//| height: auto
//| margin: 1em
#set text(size: 14pt, fill: eastern)
#align(center)[
  #box(
    fill: luma(240),
    inset: 1em,
    radius: 4pt,
  )[A styled box with custom dimensions.]
]
```

#set text(size: 14pt, fill: eastern)
#align(center)[
  #box(
    fill: luma(240),
    inset: 1em,
    radius: 4pt,
  )[A styled box with custom dimensions.]
]

Image Format and DPI

Set the output image format and resolution:

```{typst}
//| format: png
//| dpi: 288
#set text(size: 14pt)
#align(center)[High-resolution PNG output.]
```

#set text(size: 14pt)
#align(center)[High-resolution PNG output.]

Foreground and Background Colours

Set text and page fill colours for rendered images. Values can be Typst colour literals, CSS hex strings (converted automatically), or auto (reads from _brand.yml).

```{typst}
//| foreground: eastern
//| background: luma(245)
//| width: 8cm
//| margin: 1em
#set text(size: 14pt)
#align(center)[
  Styled text with custom colours.
]
```

#set text(size: 14pt)
#align(center)[
  Styled text with custom colours.
]

Alignment

Control horizontal alignment of the rendered image block.

```{typst}
//| align: center
//| width: 8cm
#set text(size: 14pt)
A centred block.
```

#set text(size: 14pt)
A centred block.

Cross-Referencing

Use //| label: and //| cap: for Quarto cross-references. Generic cap and alt options work with any label prefix. Prefix-specific variants (e.g., fig-cap, tbl-alt) override the generic options when the label matches. Any Quarto cross-reference type is supported (fig-, tbl-, lst-, etc.), including custom types.

See Figure 1 for a captioned figure.

```{typst}
//| label: fig-typst-shapes
//| cap: "A simple Typst diagram with shapes."
//| alt: "A blue circle and orange rectangle arranged horizontally."
#set text(size: 12pt)
#align(center)[
  #stack(dir: ltr, spacing: 1em)[
    #circle(radius: 1cm, fill: blue.lighten(60%))
  ][
    #rect(width: 2cm, height: 2cm, fill: orange.lighten(60%))
  ]
]
```

Figure 1: A simple Typst diagram with shapes.

Echo and Eval Control

The echo and eval options control whether source code is displayed and whether the block is compiled.

Echo: Source Code Alongside Output

Show the source code followed by the rendered output with echo: true:

#set text(size: 14pt)
$ sum_(k=0)^n k = (n(n+1))/2 $

#set text(size: 14pt)
$ sum_(k=0)^n k = (n(n+1))/2 $

Echo: Fenced Source Code

Use echo: fenced to display source code wrapped in fenced code block markers (```{typst}), including any comment+pipe options (except echo itself). This mirrors Quarto’s native echo: fenced behaviour for computational cells.

```{typst}
#set text(size: 14pt)
$ integral_0^infinity e^(-x) d x = 1 $
```

#set text(size: 14pt)
$ integral_0^infinity e^(-x) d x = 1 $

Eval: Source Only (No Compilation)

Display the source code without compiling with eval: false:

```{typst}
//| eval: false
#import "@preview/cetz:0.4.2": canvas, draw
#canvas({
  draw.circle((0, 0), radius: 1)
  draw.line((-1, 0), (1, 0))
})
```

With eval: true (the default), the block is compiled:

```{typst}
//| eval: true
#import "@preview/cetz:0.4.2": canvas, draw
#canvas({
  draw.circle((0, 0), radius: 1)
  draw.line((-1, 0), (1, 0))
})
```

#import "@preview/cetz:0.4.2": canvas, draw
#canvas({
  draw.circle((0, 0), radius: 1)
  draw.line((-1, 0), (1, 0))
})

Hidden Block

Setting eval: false and echo: false hides the block entirely. Nothing is rendered.

Include: Suppress All Output

Setting include: false suppresses all output (both source and rendered image). The block is completely hidden from the document, regardless of other options.

Output: Suppress Rendered Output

Setting output: false skips compilation and suppresses the rendered image. When combined with echo: true, only the source code is shown.

#set text(size: 14pt)
This source is visible, but the rendered image is suppressed.

Output: Native Passthrough (Typst Only)

Setting output: asis passes the Typst code through natively when the output format is Typst. For all other formats, output: asis behaves the same as output: true (compiles to an image).

```{typst}
#set text(size: 14pt)
This block uses native passthrough in Typst output.
```

#set text(size: 14pt)
This block uses native passthrough in Typst output.

Output Location (Reveal.js)

Input Variables

Pass key-value pairs to Typst code via sys.inputs. Global inputs are set in YAML; per-block inputs override them using comma-separated syntax.

```{typst}
//| input: greeting=Hello,subject=World
#set text(size: 16pt)
#sys.inputs.at("greeting"), #sys.inputs.at("subject")!
```

#set text(size: 16pt)
#sys.inputs.at("greeting"), #sys.inputs.at("subject")!

Multi-Page Output

When Typst produces multiple pages, all pages are included by default. Use pages to select specific pages and layout-ncol to arrange them in columns.

All Pages Side by Side

```{typst}
//| layout-ncol: 2
//| width: 8cm
//| height: 6cm
#set text(size: 14pt)
#align(center + horizon)[
  *Page 1*: First page content.
]
#pagebreak()
#align(center + horizon)[
  *Page 2*: Second page content.
]
```

#set text(size: 14pt)
#align(center + horizon)[
  *Page 1*: First page content.
]
#pagebreak()
#align(center + horizon)[
  *Page 2*: Second page content.
]

#set text(size: 14pt)
#align(center + horizon)[
  *Page 1*: First page content.
]
#pagebreak()
#align(center + horizon)[
  *Page 2*: Second page content.
]

First Page Only

```{typst}
//| pages: 1
//| width: 8cm
//| height: 6cm
#set text(size: 14pt)
#align(center + horizon)[
  *Page 1*: This page is shown.
]
#pagebreak()
#align(center + horizon)[
  *Page 2*: This page is hidden.
]
```

#set text(size: 14pt)
#align(center + horizon)[
  *Page 1*: This page is shown.
]
#pagebreak()
#align(center + horizon)[
  *Page 2*: This page is hidden.
]

External File Rendering

Render an external .typ file instead of inline code:

```{typst}
//| file: _example.typ
#set text(size: 14pt)
#align(center)[
  This content was loaded from an external `.typ` file.
]

```

#set text(size: 14pt)
#align(center)[
  This content was loaded from an external `.typ` file.
]

Output Directory

By default, compiled images are only stored in the internal cache directory (.quarto/typst-render/) with auto-generated filenames. Set output-directory to also save copies to a predictable location. Use output-filename to override the auto-generated filename.

Paths follow Quarto conventions: a leading / is relative to the project root, otherwise relative to the document directory.

When output-directory is set and no output-filename is given, the filename is auto-generated from the block label (e.g., fig-diagram.png) or block counter (e.g., typst-block-1.png).

Save with Explicit Filename

```{typst}
//| output-directory: _output
//| output-filename: hello-typst.png
//| format: png
#set text(size: 14pt)
#align(center)[Hello from *Typst*, saved to `_output/hello-typst.png`.]
```

#set text(size: 14pt)
#align(center)[Hello from *Typst*, saved to `_output/hello-typst.png`.]

Auto-Generated Filename from Label

When a label is present, the filename is derived from the label:

```{typst}
//| label: fig-auto-saved
//| cap: "A block saved with an auto-generated filename."
//| output-directory: _output
//| format: png
#set text(size: 14pt)
#align(center)[
  #circle(radius: 0.8cm, fill: eastern.lighten(60%))
]
```

Figure 2: A block saved with an auto-generated filename.

Preamble

Typst code can be prepended before each block using the preamble option. This is useful for setting global styles or importing packages.

Inline Preamble

extensions:
  typst-render:
    preamble: '#set text(font: "Libertinus Serif")'

File-Based Preamble

Any value ending in .typ is treated as a file path:

extensions:
  typst-render:
    preamble: "preamble.typ"

Social Card

A repository social card built entirely in Typst, rendered as a high-resolution PNG.

```{typst}
//| label: fig-social-card
//| cap: "Social card for quarto-typst-render."
//| format: png
//| dpi: 288
//| width: 1280pt
//| height: 640pt
//| margin: 0pt
//| output-location: slide

#let gradient-bg = gradient.linear(
  rgb("#1a1a2e"),
  rgb("#16213e"),
  rgb("#0f3460"),
  angle: 135deg,
)

#let accent = rgb("#e94560")
#let text-primary = rgb("#eaeaea")
#let text-secondary = rgb("#a0a0b0")
#let surface = rgb("#1a1a2e").lighten(10%)

#set page(fill: gradient-bg)
#set text(font: "Inter", fill: text-primary)

#place(
  top + left,
  dx: -40pt,
  dy: -40pt,
  circle(radius: 200pt, fill: accent.transparentize(92%)),
)
#place(
  bottom + right,
  dx: 80pt,
  dy: 80pt,
  circle(radius: 300pt, fill: rgb("#0f3460").transparentize(60%)),
)

#align(horizon)[
  #pad(x: 72pt)[
    #grid(
      columns: (1fr, auto),
      column-gutter: 48pt,
      align: (left + horizon, right + horizon),
      [
        #block(
          fill: accent,
          radius: 6pt,
          inset: (x: 14pt, y: 8pt),
        )[
          #text(
            size: 14pt,
            weight: "bold",
            tracking: 1.5pt,
            fill: white,
          )[QUARTO EXTENSION]
        ]

        #v(20pt)

        #text(size: 48pt, weight: "bold", tracking: -0.5pt)[
          typst-render
        ]

        #v(12pt)

        #text(size: 20pt, fill: text-secondary, weight: "regular")[
          Compile Typst code blocks to images#linebreak()
          for any Quarto output format.
        ]

        #v(28pt)

        #text(size: 16pt, fill: text-secondary)[
          #text(fill: accent, weight: "bold")[mcanouil]
          #h(4pt)
          #text(fill: text-secondary.transparentize(50%))[/]
          #h(4pt)
          quarto-typst-render
        ]
      ],
    )
  ]
]
```

Figure 3: Social card for quarto-typst-render.

Inline Typst

Render Typst expressions inline using backtick code with the typst class. The rendered image scales to match the surrounding text size.

Here is a red word {typst} #text(red)[hello] in the middle of a sentence.

Inline maths: {typst} $ x^2 + y^2 = z^2 $ renders as a formula image.

Inline with explicit alt text: {typst} $pi r^2$ for the area of a circle.

Escaped inline code is not evaluated: `{typst} #text(red)[hello]`.

Global Configuration

Configure the filter globally in your document YAML. Most options can be set globally and overridden per block using comment+pipe syntax (//| key: value). See Global-Only Options for options that cannot be overridden per block.

extensions:
  typst-render:
    dpi: 288
    margin: "1em"
    format: png
    cache: true

Options

Option Type Default Description
format string (auto) Image format: png, svg, pdf.
dpi number 144 Pixels per inch (PNG only).
width string "auto" Page width for image compilation (ignored with output: asis).
height string "auto" Page height for image compilation (ignored with output: asis).
margin string "0.5em" Page margin for image compilation; block inset with output: asis.
background string|object "none" Page fill colour. Accepts a Typst colour, auto (from _brand.yml), or {light, dark} map.
foreground string|object (none) Text fill colour. Accepts a Typst colour, auto (from _brand.yml), or {light, dark} map.
preamble string "" Typst code or path to a .typ file prepended before user code.
cache boolean|string true Cache compiled images. Use "clean" to also remove stale cache files.
input object (none) Key-value pairs passed as --input flags to Typst CLI.
file string (none) Path to external .typ file to render.
output-directory string (none) Directory for saving compiled images.
output-filename string (none) Filename for the saved image. Leading / overrides output-directory.
echo boolean|string false Show Typst source code alongside output (true, false, fenced).
eval boolean true Compile Typst code to image.
include boolean true Include block in output. Set false to suppress entirely.
output boolean|string true Show rendered output. Use asis for native Typst passthrough.
output-location string (none) Output placement in Reveal.js (fragment, slide, column, column-fragment).
classes string (none) Space-separated CSS classes on the output image (e.g., r-stretch).
pages string "all" Pages to include from multi-page output: all, 1, 1-3, 2,5, 3-.
layout-ncol string (none) Number of columns for arranging multi-page output. Omit for vertical stack.
align string (none) Horizontal alignment: left, center, right, default.

Any unknown option with a string value is forwarded as an HTML attribute on the output image element (e.g., //| style: "max-height: 300px;"). Values that look like booleans (true/false) must be quoted to be forwarded (e.g., //| data-lazy: "true").

Global-Only Options

These options can only be set in the document YAML and cannot be overridden per block.

Option Type Default Description
root string (project directory) Root directory for Typst compilation.
font-path string|array (none) Path or list of paths to directories containing additional fonts.
package-path string (none) Path to a directory containing Typst packages (offline/reproducible).

Per-Block Cross-Referencing Options

Option Type Description
label string Quarto cross-ref label (e.g., fig-x, tbl-y, lst-z).
cap string Caption text for the labelled block.
alt string Alternative text for accessibility. Falls back to caption, then source code.
<prefix>-cap string Prefix-specific caption (e.g., fig-cap). Overrides cap for matching labels.
<prefix>-alt string Prefix-specific alt text (e.g., fig-alt). Overrides alt for matching labels.

Auto-Selected Image Format

Output Format Default Image Format
HTML / RevealJS svg
LaTeX / Beamer pdf
Typst png
DOCX / PPTX png
Other png

Echo/Eval Behaviour

eval echo Result
true false Image only (default).
true true Source code block + image below.
true fenced Fenced source code block (with markers) + image.
false true Source code listing only.
false fenced Fenced source code listing only (with markers).
false false Nothing rendered (hidden block).

The include and output options take precedence over the eval/echo matrix:

  • include: false hides the entire block regardless of eval/echo settings.
  • output: false skips compilation and shows only the source code (if echo is enabled).
  • output: asis uses native passthrough for Typst output; behaves as true for other formats.