Show the code
#set text(size: 14pt)
$ e^(i pi) + 1 = 0 $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.
quarto add mcanouil/quarto-typst-render@0.17.0This will install the extension under the _extensions subdirectory.
If you are using version control, you will want to check in this directory.
To use the extension, add the following to your document’s front matter:
filters:
- typst-renderFor cross-referencing support, use timing control:
filters:
- path: typst-render
at: pre-quartoThen write Typst code blocks in your document:
```{typst}
#set text(size: 16pt)
Hello from *Typst*!
```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.
```Use comment+pipe syntax (//| key: value) at the top of the code block to set per-block options.
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 the output image format and resolution:
```{typst}
//| format: png
//| dpi: 288
#set text(size: 14pt)
#align(center)[High-resolution PNG output.]
```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.
]
```Control horizontal alignment of the rendered image block.
```{typst}
//| align: center
//| width: 8cm
#set text(size: 14pt)
A centred block.
```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%))
]
]
```The echo and eval options control whether source code is displayed and whether the block is compiled.
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 $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 $
```For HTML-based output, code-fold: true collapses the echoed source in a <details> block, and code-summary sets the disclosure text. The rendered output stays outside the fold, and the options are ignored for non-HTML formats.
#set text(size: 14pt)
$ e^(i pi) + 1 = 0 $With echo: true, Quarto code annotations work on the Typst source. Add // <N> markers to the lines you want to annotate, then a numbered list immediately after the block. Other echo values (false, fenced) strip the markers and ignore annotations.
n integers.
Code annotations compose with code-fold for HTML-based output.
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))
})
```Setting include: false suppresses all output (both source and rendered image). The block is completely hidden from the document, regardless of other options.
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.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.
```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")!
```Use typst_define() to push named values from a knitr or jupyter session into every {typst} cell. Defined values are exposed as #typst_define.<name>. Supports scalars, strings, booleans, arrays, nested objects, R data frames (column-wise), pandas/polars DataFrames, and numpy arrays.
This document uses the markdown engine; the snippets below are illustrative. For an executable demo, switch the document engine to knitr (R) or jupyter (Python) and copy the helper from _extensions/mcanouil/typst-render/_resources/ (once installed): typst_define.R or typst_define.py.
R (knitr engine):
```{r}
#| include: false
source("_extensions/mcanouil/typst-render/_resources/typst_define.R")
```
```{r}
#| output: asis
typst_define(mtcars = head(mtcars)[, c("mpg", "cyl", "hp")], n = 42L)
```
```{typst}
n = #typst_define.n
#let df = typst_define.mtcars
#let cols = df.keys()
#table(
columns: cols.len(),
table.header(..cols.map(c => [*#c*])),
..for i in range(df.at(cols.at(0)).len()) {
cols.map(c => [#df.at(c).at(i)])
}
)
```Python (jupyter engine):
```{python}
#| include: false
import sys
sys.path.insert(0, "_extensions/mcanouil/typst-render/_resources")
from typst_define import typst_define
```
```{python}
#| output: asis
import pandas as pd
typst_define(df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]}), label = "hello")
```
```{typst}
#typst_define.label
#let df = typst_define.df
#let cols = df.keys()
#table(
columns: cols.len(),
table.header(..cols.map(c => [*#c*])),
..for i in range(df.at(cols.at(0)).len()) {
cols.map(c => [#df.at(c).at(i)])
}
)
```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.
```{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.
]
``````{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.
]
```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.
]
```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).
```{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`.]
```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%))
]
```Set output-source: true to also write the compiled Typst source (preamble plus colour bindings plus user code) next to the saved image, using the same stem with a .typ extension. This is useful for reproducibility: every persisted image has a recompilable source next to it.
```{typst}
//| label: fig-with-source
//| cap: "Image saved with `.typ` source alongside."
//| output-directory: _output
//| output-source: true
//| format: png
#set text(size: 14pt)
#align(center)[
Image and source are persisted together.
]
```.typ source alongside.
Typst code can be prepended before each block using the preamble option. This is useful for setting global styles or importing packages.
extensions:
typst-render:
preamble: '#set text(font: "Libertinus Serif")'Any value ending in .typ is treated as a file path:
extensions:
typst-render:
preamble: "preamble.typ"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 in the middle of a sentence.
Inline maths: renders as a formula image.
Inline with explicit alt text: for the area of a circle.
Escaped inline code is not evaluated: `{typst} #text(red)[hello]`.
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| 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. |
output-source |
boolean | false |
Also write compiled Typst source next to each saved image (same stem, .typ extension). |
echo |
boolean|string | false |
Show Typst source code alongside output (true, false, fenced). |
code-fold |
boolean|string | false |
Collapse echoed source in a <details> block (HTML only). Use show to expand. |
code-summary |
string | "Code" |
Summary text for the code-fold <details> block (HTML only). |
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").
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). |
| 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. |
| Output Format | Default Image Format |
|---|---|
| HTML / RevealJS | svg |
| LaTeX / Beamer | pdf |
| Typst | png |
| DOCX / PPTX | png |
| Other | png |
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.
Social Card
A repository social card built entirely in Typst, rendered as a high-resolution PNG.