Typst Render

Quarto Extension

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)

The output-location option controls where rendered output appears in Reveal.js presentations.

Fragment

#set text(size: 14pt)
#align(center)[Output appears as a *fragment* after the source.]

#set text(size: 14pt)
#align(center)[Output appears as a *fragment* after the source.]

Slide

#set text(size: 14pt)
#align(center)[Output appears on the *next slide*.]

Slide

#set text(size: 14pt)
#align(center)[Output appears on the *next slide*.]

Column

#set text(size: 14pt)
#align(center)[Output appears in a *side-by-side column*.]

#set text(size: 14pt)
#align(center)[Output appears in a *side-by-side column*.]

Column Fragment

#set text(size: 14pt)
#align(center)[Output appears in a *column*, revealed as a fragment.]

#set text(size: 14pt)
#align(center)[Output appears in a *column*, revealed as a fragment.]

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.

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
        ]
      ],
    )
  ]
]
```

Social Card

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]`.