Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

mdbook-typst-math

Crates.io Version docs.rs

mdbook-typst-math is an mdBook preprocessor that uses Typst to render mathematical expressions.

Requirements

  • mdBook 0.5.x or later - This preprocessor uses the mdbook-preprocessor crate which requires mdBook 0.5.x
  • Rust (for building from source)

Installation

Cargo

You can install the latest released version from crates.io:

cargo install mdbook-typst-math

Or install the latest version from GitHub:

cargo install --git https://github.com/duskmoon314/mdbook-typst-math

Or build from source:

git clone https://github.com/duskmoon314/mdbook-typst-math.git
cd mdbook-typst-math
cargo build --release

Pre-built binaries

You can download pre-built binaries from the releases.

Usage

Setup preprocessor

Add the following to your book.toml:

[preprocessor.typst-math]

If mdbook-typst-math is not in your PATH, you need to specify its location:

[preprocessor.typst-math]
command = "path/to/mdbook-typst-math"

The path is usually ~/.cargo/bin/mdbook-typst-math if you installed it using cargo.

Control the style

Add css to control the style of the typst block:

/* css/typst.css as an example */
.typst-inline {
  display: inline flex;
  vertical-align: bottom;
}

.typst-display {
  display: block flex;
  justify-content: center;
}

.typst-display > .typst-doc {
  transform: scale(1.5);
}

Add the following to your book.toml:

[output.html]
additional-css = ["css/typst.css"]

Theme support (Dark mode)

By default, this preprocessor generates SVGs with transparent backgrounds and replaces black text color with currentColor. This allows the math to adapt to different color themes.

To make the math text color adapt to the current theme automatically, add the following CSS:

/* Use the theme's foreground color for math */
.typst-doc {
  color: var(--fg);
}

If you prefer to set specific colors for dark themes (coal, navy, ayu), you can use:

/* Set specific text color for dark themes */
html.coal .typst-doc,
html.navy .typst-doc,
html.ayu .typst-doc {
  color: #b3b3b3;
}

What this preprocessor does

This preprocessor will convert all math blocks to a <div> with the class typst-inline/typst-display (depends on the type of math blocks) and a <svg> with the class typst-doc inside.

Say you have the following code block in your markdown:

  hello
  $$
  y = f(x)
  $$
  world

This preprocessor will first change it to:

  hello
- $$
- y = f(x)
- $$
+ #set page(width:auto, height:auto, margin:0.5em, fill:none)
+ $ y = f(x) $
  world

The math content is wrapped in typst’s $ ... $ to indicate it is a math block, and a preamble is added before it to set the page size and margin.

Then preprocessor will leverage typst to render the math block and change it to:

hello
<div class="typst-display">
  <svg class="typst-doc" ...></svg>
</div>
world

Configuration

Currently, only following configurations are supported. Here we use an example to show how to set them:

[preprocessor.typst]

# Additional fonts to load
#
# Two types are supported: a string or an array of strings
#
# Usually, you don't need to set this since the default build of preprocessor
# will load system fonts and typst embedded fonts.
fonts = ["/path/to/FiraMath-Regular.otf"] # or "/path/to/FiraMath-Regular.otf"

# Preamble to be added before the typst code
#
# The default preamble is:
# ```
# #set page(width:auto, height:auto, margin:0.5em, fill:none)
# ```
#
# The `fill: none` makes the background transparent, which allows the
# rendered math to adapt to different color themes (light/dark mode).
# If you want a specific background color, you can set it like:
# `fill: white` or `fill: rgb("#ffffff")` for white background.
#
# NOTE: When you customize `preamble`, the default value is completely
# overwritten. If you don't specify `fill`, Typst's default (white
# background) will be used. To keep transparent background, explicitly
# set `fill: none` in your custom preamble.
preamble = """
#set page(width:auto, height:auto, margin:0.5em, fill:white)
#set text(size: 12pt)
#show math.equation: set text(font: "Fira Math")
"""

# Preamble to be added before the typst code for inline math
#
# If not set, then `preamble` will be used.
#
# Usually, this is not needed. But if you want to use different settings for
# inline math and display math, you can set this.
inline_preamble = """
#set page(width:auto, height:auto, margin:0.5em, fill:white)
#set text(size: 12pt)
#show math.equation: set text(font: "Fira Math")
"""

# Preamble to be added before the typst code for display math
#
# If not set, then `preamble` will be used.
#
# Usually, this is not needed. But if you want to use different settings for
# inline math and display math, you can set this.
display_preamble = """
#set page(width:auto, height:auto, margin:0.5em, fill:white)
#set text(size: 14pt)
#show math.equation: set text(font: "Fira Math")
"""

# Cache directory for downloaded packages
#
# If you want to use Typst packages (e.g., physica), you should set this.
# The packages will be downloaded from packages.typst.org and cached here.
cache = ".typst-cache"

# Color mode for SVG output
#
# - "auto" (default): Replace black (#000000) with `currentColor` in SVG,
#   allowing CSS to control text color for theme support (light/dark mode).
# - "static": Keep colors as-is from Typst output. Use this if you want to
#   preserve exact colors or use a fixed background color.
color_mode = "auto"

Using Typst Packages

This preprocessor supports Typst packages from Typst Universe. Packages are automatically downloaded and cached when first used.

To use a package like physica, add the import to your preamble:

[preprocessor.typst-math]
cache = ".typst-cache"
preamble = """
#set page(width:auto, height:auto, margin:0.5em)
#import "@preview/physica:0.9.7": *
"""

Then you can use the package features in your math blocks:

The derivative is $dv(f,x)$ and the partial derivative is $pdv(f,x,y)$.

$$
grad f = vu(x) pdv(f,x) + vu(y) pdv(f,y)
$$

Note: Make sure to set the cache option to specify where downloaded packages should be stored. You may want to add this directory to your .gitignore.

You may also want to re-use the same cache directory as your Typst installation by setting cache to:

  • $XDG_CACHE_HOME/typst/packages or ~/.cache/typst/packages on Linux
  • ~/Library/Caches/typst/packages on macOS
  • %LOCALAPPDATA%\typst\packages on Windows

Examples

Here are some examples demonstrating how to use mdbook-typst-math.

Basic Usage with Inline and Display Math

Pythagorean theorem states that $a^2 + b^2 = c^2$ for a right triangle.

Pythagorean theorem states that for a right triangle.

Fourier transform is given by:
$$
accent(f, "^")(omega) = integral_(-infinity)^infinity f(t) e^(-i omega t) d t
$$

Fourier transform is given by:

Using Typst Packages

You can use Typst packages by importing them in the preamble configuration. For example, to use the physica package:

[preprocessor.typst-math]
cache = ".typst-cache"
preamble = """
#set page(width: auto, height: auto, margin: 0.5em)
#import "@preview/physica:0.9.7": *
"""

Then you can use physica functions in your math blocks:

Derivative: $dv(f, x)$, Partial derivative: $pdv(f, x, y)$

Derivative: , Partial derivative:

$$
grad f = vu(x) pdv(f, x) + vu(y) pdv(f, y) + vu(z) pdv(f, z)
$$
Maxwell's equations are given by:
$$
div vb(E) = rho / epsilon_0 \
div vb(B) = 0 \
curl vb(E) = - pdv(vb(B), t) \
curl vb(B) = mu_0 vb(J) + mu_0 epsilon_0 pdv(vb(E), t)
$$

Maxwell’s equations are given by:

Escaping the Math Mode

Actually, you can escape the math mode using #[] syntax.

$$
#[
    #cetz.canvas({
        import cetz.draw: *
        circle((0, 0))
        line((-1, -1), (1, 1))
        line((-1, 1), (1, -1))
    })
]
$$

Since the code is still wrapped in a math block, the output might not be as expected. In addition, empty lines inside #[] may cause issues in markdown parsing. Use this feature with caution!

Typst’s warnings and errors

Typst’s warnings and errors will be shown in the console output when building the book.

For example, the following block will generate a warning:

$$
#[
    #set text(font: "nonexistent-font")
]
$$

You will see a warning like this in the console:

$ mdbook build
 INFO Book building has started
 WARN Typst: warning: unknown font family: nonexistent-font
    ┌─ Examples examples.md:121:20
    │
121 │     #set text(font: "nonexistent-font")
    │                     ^^^^^^^^^^^^^^^^^^


 INFO Running the html backend
 INFO HTML book written to `/path/to/mdbook-typst-math/example/book`