Skip to main content

Quarto Wizard 3.3: Typst Preview and Schema Validation

Quarto Wizard 3.3 compiles the Typst block under your cursor and shows the image beside the editor. It also publishes the Lua validator of the extension schema vocabulary, so an extension can check its own options during a render.

quarto
vscode
positron
extensions
typst
quarto-wizard
Author
Published

Monday, the 7th of September, 2026

A card titled Quarto Wizard 3.3, with the line "Typst preview, beside
the editor" and the Typst wordmark under it. Beside the title, an editor
window holds a Typst cell on the left and the preview panel on the
right, where the cell compiles to a scatter plot of penguin flipper
length against body mass.

Quarto Wizard 3.3 adds a preview for Typst blocks, and publishes the Lua validator that an extension can use to check its own options. This post shows both.

Quarto Wizard 3.3 is available from the VS Code Marketplace and the Open VSX Registry.

Preview a Typst Block

Writing Typst inside a Quarto document used to mean rendering the whole document to see one small block. Quarto Wizard 3.3 compiles the block under the cursor and shows the image beside the editor. It uses the Typst binary that ships inside Quarto, so there is nothing else to install.

Put the cursor inside a Typst block, then run Quarto Wizard: Preview Typst Block, or select the code lens above the block. The cell below draws the penguins with Gribouille, and the image beside it is what the render produces.

A Quarto document with a Typst cell on the left and the Quarto Wizard
preview panel on the right, showing the scatter plot of penguin flipper
length against body mass that the cell compiles to.

A Quarto document with a Typst cell on the left and the Quarto Wizard
preview panel on the right, showing the scatter plot of penguin flipper
length against body mass that the cell compiles to.

The panel then follows the cursor, and it compiles again after each edit. Move the cursor to another block, of any of the three kinds, and the panel shows that one instead.

The same document and preview panel, where the cursor visits a Typst
cell, a raw block and a plain block in turn, and the compiled image
follows every edit and every move.

The same document and preview panel, where the cursor visits a Typst
cell, a raw block and a plain block in turn, and the compiled image
follows every edit and every move.

The panel writes a failure over the last good image of the same block. The preview therefore does not go empty while you type.

The preview panel showing a compiler message about an invalid number
suffix, with the last good image of the block still under it.

The preview panel showing a compiler message about an invalid number
suffix, with the last good image of the block still under it.

The full compiler output goes to the Quarto Wizard log.

Tip

quartoWizard.typstPreview.debounceMs sets how long an edit waits before the preview follows it. Its default is 300 milliseconds. Set it to 0 to compile on every keystroke, and raise it when a block is slow to compile.

Where the Image Appears

quartoWizard.typstPreview.surface selects where the image is shown.

  • panel, the default, shows the image beside the editor. The panel scrolls, so a tall image is never cut.
  • hover shows the image when the pointer rests on a block.
  • off shows no image, and offers no code lens.

A hover card over a Typst block, showing the compiled image of that
block above the block itself.

A hover card over a Typst block, showing the compiled image of that
block above the block itself.

A hover cannot scroll, so the image is scaled down to quartoWizard.typstPreview.maxHeight.

Three Kinds of Block

Three fences are spelled almost the same way, and Quarto treats each one differently. The preview treats them differently too, and the code lens above each block says which kind it is.

Fence What Quarto does with it What the preview compiles
```typst Highlights it, and never executes it. The body, under the preview’s own page setup and colours.
```{=typst} Passes it to the Typst output untouched. The body, under every raw block above it in the document.
```{typst} Executes it through the typst-render extension. The body, under the options and the colours of that extension.

A {typst} cell needs typst-render installed in the project. Without it the preview says so and shows nothing. An image compiled with guessed options is not the image the render produces, which is worse than no image at all.

Quarto Wizard installs it for you, in the folder you pick:

Install in VS Code Install in Positron

The other two kinds need no extension.

Colours

A plain block and a raw block take their colours from quartoWizard.typstPreview.foreground and quartoWizard.typstPreview.background. Both accept three forms. auto, the default, follows the editor theme. none writes no colour, so Typst uses its own black on white. Any other value is a Typst colour expression written as it stands, for example rgb("#ff9800").

A {typst} cell keeps the colour contract of typst-render instead, so the image matches the render and not the editor. A cell that resolves a colour from a brand needs a side of that brand. Quarto Wizard: Switch Typst Preview Brand Mode shows the other side, and the panel header always says which side it used.

Paths and the Compile Root

The preview sends the block to Typst through standard input. A path inside the block therefore resolves against the compile root, and not against the file that holds the block.

The preview uses the root that a render uses. For a {typst} cell, that is the root value under extensions.typst-render, whose default is the directory of the document. A cell also compiles with the font-path, the package-path and the input values of the extension. A plain block and a raw block always use the directory of the document.

Open the File a Path Points To

A file: option and a preamble: option name a file. Hold Ctrl, or Cmd on macOS, and select the value to open that file in the editor.

A Typst cell whose preamble option value is underlined as a link, with
the tooltip that names the file and says Cmd and click.

A Typst cell whose preamble option value is underlined as a link, with
the tooltip that names the file and says Cmd and click.

The link appears only when the file is there. A path that leads to no file gets a warning instead. file: works in a cell only, while preamble: also works in the front matter of a document, and under extensions.typst-render in _quarto.yml or _metadata.yml.

The Limits of the Preview

The preview is an authoring aid, and it is not a render. The limits below are the limits of this first version, and most of them can be lifted later.

Important

The preview differs from a render in two ways, and it says so beside the image when the difference applies. A raw block reaches Typst through the document template during a render, and the template contributes imports and rules that the preview does not apply yet. The preview also compiles one block on its own, so a plain block that uses a value from another block fails.

The preview shows the first page of a block of several pages, it always compiles to SVG, and it does not yet see the payload that the R and Python helpers of typst-render produce during a render.

One limit is deliberate and stays. The preview is off in an untrusted workspace, because it runs a compiler over the content of that workspace.

One Schema, Two Validators

The other half of 3.3 is for people who write extensions. It is about _schema.yml, the file where an extension declares every option, shortcode argument, format key, attribute and class that it accepts. If you only use extensions, this part changes nothing for you, beyond better messages from the extensions that adopt it.

Quarto Wizard has read that file for a while, to offer completion, hover documentation and diagnostics. A value of the wrong type, or a key the extension does not declare, is reported while you write.

A \_quarto.yml file where two extension options carry a squiggle, and
the Problems panel below reports a wrong type and an unknown option.

A \_quarto.yml file where two extension options carry a squiggle, and
the Problems panel below reports a wrong type and an unknown option.

That covers the editor only. Someone who writes an option by hand in _quarto.yml, with no editor to help, still reaches the render with a wrong value. So 3.3 publishes the Lua validator that reads the same file during the render.

Two artefacts, two jobs: the meta-schema JSON validates your _schema.yml while you write it, and the Lua module validates the metadata of your user while Quarto renders.

The meta-schema is the file you point $schema at.

_extensions/my-extension/_schema.yml
$schema: https://m.canouil.dev/quarto-wizard/assets/schema/v2/extension-schema.json
options:
  theme:
    type: string
    description: "Colour theme for the extension output."
    default: light
    enum: [light, dark, auto]
  count:
    type: integer
    default: 3
    minimum: 1
    maximum: 100

The module is published as schema.lua. Its version is the version of the vocabulary, so the v2 module implements the v2 meta-schema. Vendor it into your extension, because a render must not need network access.

_extensions/my-extension/my-extension.lua
1local schema = require(quarto.utils.resolve_path('_modules/schema.lua'):gsub('%.lua$', ''))

2local options = schema.validate_options(
  meta,
  'my-extension',
  quarto.utils.resolve_path('_schema.yml')
)
1
Load the vendored copy by its absolute path. Lua keys its module cache by the name you pass, so require('_modules.schema') would hand the second extension of a render the copy of the first one.
2
Read meta.extensions.my-extension, test every value against the schema, and return the options with the defaults applied.

Errors and warnings go through the Quarto logger, and a schema that cannot be read never stops the render. Narrower entry points exist for a shortcode call, for the attributes of an element, and for a format block. The Using the Lua Validator page, added to the Quarto Wizard documentation in this release, describes each one.

The v2 meta-schema also accepts uniqueItems now. The validator already enforced that keyword, so a schema that used it was rejected by the meta-schema and accepted by the module. Both agree again.

Other Fixes

3.4 follows straight after 3.3, and it is about the two features above, so the list below holds both releases.

  • An extension in a repository whose default branch is master installs without writing @master. The branch is read from GitHub when the repository has no release, no tag and no registry entry.
  • A Typst block written between two --- lines that open no front matter is found. The rule the preview follows is the rule Pandoc applies.
  • The search for Quarto projects no longer collects search processes. It applies your files.exclude and search.exclude settings, and it stops when a newer search replaces it.
  • The preview reads a document again when that document takes the name of an untitled document you closed. It used to show you the blocks of the one before.
  • A fenced block that a tab indents inside a blockquote is found, and a body line keeps the indent you wrote.
  • A YAML diagnostic points at the key or the value it is about, rather than at the whole line, and an option written in flow style is checked as well.
  • The Lua validator corrects two checks, accepts a name written with a hyphen where the schema declares it with an underscore, and reports a spelling that two attributes both declare. That last one used to leave the choice to the validator.

The changelog holds the full list, for 3.3 and for 3.4.

Happy writing!

Back to top

Reuse

Citation

BibTeX citation:
@misc{canouil2026,
  author = {CANOUIL, Mickaël},
  title = {Quarto {Wizard} 3.3: {Typst} {Preview} and {Schema}
    {Validation}},
  date = {2026-09-07},
  url = {https://mickael.canouil.fr/posts/2026-09-07-quarto-wizard-3-3/},
  langid = {en-GB}
}
For attribution, please cite this work as:
CANOUIL, M. (2026-09-07). Quarto Wizard 3.3: Typst Preview and Schema Validation. Mickael.canouil.fr. https://mickael.canouil.fr/posts/2026-09-07-quarto-wizard-3-3/