Add opt-in TeX math parsing for Markdown

I am posting this proposal here before opening a pull request, as requested by Zola’s contribution guidelines for new features. I have used a format to make the problem (narrow scope), alternatives, and open design questions easy to review. The goal is to discuss whether this parser-level feature is desirable before submitting an implementation.

Draft: Markdown math parsing

Summary

Add an opt-in markdown.math Boolean that enables pulldown-cmark’s native TeX-math parsing. When enabled, Zola recognizes inline $...$ and display $$...$$ regions before normal Markdown parsing can alter their contents, then outputs the TeX payload with its corresponding delimiters. Themes remain solely responsible for rendering that TeX with KaTeX,
MathJax, or another tool.

Motivation

Themes that use KaTeX or MathJax commonly let authors write TeX directly in Markdown. As of now, Zola’s Markdown parser processes the contents inside dollar delimiters before the browser-side renderer sees them.

pulldown-cmark provides Options::ENABLE_MATH specifically for this purpose: it emits InlineMath and DisplayMath events whose contents conventionally contain TeX formulas. Zola does not currently expose that option. A theme cannot reliably repair arbitrary math after Markdown has transformed its contents. A shortcode or component can bypass the
problem only when an author explicitly uses it, so it does not make ordinary $...$ and $$...$$ syntax safe.

This breaks valid TeX. For example, \{, \}, \,, and \\ may be interpreted as Markdown escapes; _ and * can be interpreted as emphasis; and backticks can start code spans. Authors must double-escape characters, add artificial whitespace, or use a theme-specific component instead of writing normal TeX.

The problem belongs at the Markdown-parser layer: it must know that the delimited region is math before it applies ordinary Markdown rules.

Guide-level explanation

A site opts in under [markdown]:

[markdown]
math = true

With math enabled, authors can write TeX normally:

Inline: $a_1 * b_2 + \{ \alpha \} \,$.

$$
\begin{matrix}
1 & 0 \\
0 & 1
\end{matrix}
$$

Zola preserves the recognized math region for the site’s renderer instead of interpreting its TeX as Markdown. The site or theme remains responsible for loading and configuring KaTeX, MathJax, or another renderer.

With the default setting, existing Markdown behavior is unchanged.

Reference-level explanation

When config.markdown.math is true, Zola enables pulldown_cmark::Options::ENABLE_MATH.

pulldown-cmark then produces Event::InlineMath and Event::DisplayMath instead of ordinary text and Markdown-formatting events. Zola renders those events as $...$ or $$...$$.

The default is false for backward compatibility. No renderer dependency, renderer configuration, CSS, JavaScript, server-side rendering, or theme API is added by this feature.

Drawbacks

  • This adds a configuration option for a feature whose visual rendering is provided by themes or sites.
  • Dollar delimiters can be ambiguous in prose and prices, so math parsing must remain opt-in.
  • Themes with a different existing math solution may choose not to use the option.

Rationale and alternatives

A configuration Boolean matches the deliberately narrow scope: the parser either recognizes TeX math delimiters or it retains existing Markdown behavior. The configuration does not select a renderer or provide a renderer API.

Theme-level components remain useful for specialised rendering. They do not solve the general case for authors who want normal $...$ and $$...$$ syntax, because Markdown has already processed the TeX before component-free theme integration can see it.

Server-side rendering and renderer-specific output are out of scope. They introduce renderer dependencies, distribution concerns, and a larger API surface.

In PR #2708 an enum was suggested to accommodate possible future Zola-side rendering. This proposal does not include rendering; whether future work should replace or extend markdown.math can be decided independently.

pulldown-cmark’s built-in HTML renderer emits <span class="math math-inline"> and <span class="math math-display"> for these events. This proposal intentionally does not adopt that convention: it re-emits $...$ and $$...$$ as text to preserve delimiter-based theme integrations. Whether Zola should additionally expose a class-based mode is a separate design question.

Prior art

  • PR #2708 adds optional pulldown-cmark math parsing and includes renderer-oriented output.
  • PR #2791 proposes Typst and KaTeX rendering, combining parser support with renderer selection and dependencies.
  • The related Support thread documents the concrete escaping failures with KaTeX auto-render.

Unresolved questions

  • Is preserving $...$ and $$...$$ the desired generic output contract for Zola themes?
  • Should future renderer-specific or server-side rendering be a separate feature, and if so, how should it relate to markdown.math?

Future possibilities

  • Renderer-specific or semantic-class output modes.
  • Server-side KaTeX or Typst rendering.
  • Per-page or per-section math configuration.
1 Like

As soon as I can I will create a RFC template and move discussions to a PR so we can do line by line review and sunset the proposal for the forum. Hopefully this week! You’re using the Rust RFC template I was planning on using so maybe we can just submit that as a PR to the zola repo in a rfcs folder and comment there?

I don’t use maths in Zola but I think typst would be better because it can be server side rendered?

Thanx for the quick reply, and happy to move this into rfcs/ and make a PR.

One clarification on scope, since I think the Typst comment is answering a question this proposal doesn’t ask yet: this PR is only about getting $...$ / $$...$$ regions to survive pulldown-cmark’s Markdown pass intact, by turning on Options::ENABLE_MATH. It doesn’t pick a renderer, and it doesn’t decide whether rendering happens client-side, server-side, or at all. A theme can still do nothing with the math events, wire up KaTeX/MathJax in JS, or (later) have Zola render with Typst server-side. All of those stay equally possible after this lands.

Right now, without this change, none of those paths work reliably, because Markdown itself is mangling the TeX before it ever reaches a renderer of any kind; that’s the bug this fixes.

So Typst-vs-KaTeX and SSR-vs-client are real and worth discussing, but they’re downstream questions this PR deliberately leaves open (I called them out under “Future possibilities” / “Unresolved questions”). I’d rather not couple “can Zola pass through valid TeX” to “which renderer should Zola eventually support,” since the second is a much bigger design surface and could stall the first.

Want me to open the RFC PR using your template once it’s up, or should I adapt the draft above into the rfcs/ folder format now?

You can do that, I was going to use the same template anyway.

Yep but I think we should have the rendering bit be part of the RFC as it’s something many people want.

I understand wanting to figure out Zola’s overall math story, given the previous attempts in this area. But I don’t want to get involved in that broader effort here.

I want to address the parsing fix I originally proposed. If that isn’t something you want to consider independently of the broader math work, I’ll leave it here for now.