# A simpler KaTeX alternative that works today

**URL:** <https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156>\
**Category:** Feature requests\
**Created:** [June 2, 2024, 9:53am UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156 "2024-06-02T09:53:17Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Apanatshka](https://avatars.discourse-cdn.com/v4/letter/a/ecd19e/32.png) [@Apanatshka](https://zola.discourse.group/u/Apanatshka)\
**Post date:** [June 2, 2024, 9:53am UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/1 "2024-06-02T09:53:17Z")

</div>

# Summary

By updating `pulldown-cmark` to `0.11`, we can instruct it to parse parts between single or double dollar signs as math. Then we can use `latex2mathml` to turn the math text into mathml. I have a prototype of this ready in a fork of zola.

# Motivation

Supporting the rendering of mathematical formulas at generation time has been a wish of many for a few years now, given the posts here and the github issues about this. There was a PR to add KaTeX support to do this, which from my brief scanning of the comments got stuck on windows support? I believe my proposal is worthwhile because it’s a small, simple change that can immediately support the most common use cases, even if it may not be as complete as KaTeX.

# Guide-level explanation

You can opt into support for rendering math formulas to mathml by specifying this in your config file under the `markdown` settings with `math = true`. Then LaTeX formulas between single dollars will be rendered as inline mathml formulas, while formulas between double dollars will be rendered as display style formulas. Zola uses the `latex2mathml` crate for this conversion. If you find yourself missing support for a particular LaTeX feature, check their documentation for more information or feature requests.

# Reference-level explanation

As mentioned in the summary, we need `pulldown-cmark` version `0.11` to parse math as events. Then we can add `latex2mathml` to the `libs` component to use it in the `markdown` component. In particular, `markdown_to_html` we can add an if based on the new Zola config option `markdown.math` to add `Options::ENABLE_MATH` to the markdown parser. Then within the big event loop in the same function we match against the new `DisplayMath` and `InlineMath` events, call the `latex_to_mathml` function with the text from the event and the appropriate `DisplayStyle` option, and return the result as an `Html` event.  
A wrong formula makes latex2mathml return an `Err`. In my branch I’m currently then returning the math event unchanged and putting the error in the mutable local variable for an error from the event processing loop.

# Drawbacks

I don’t know that much about KaTeX except that it seems pretty complete, and outputs HTML for displaying formulas while also outputting (styled invisible) MathML to be semantically descriptive. By comparison, latex2mathml only outputs MathML and is limited by it. For example, [MathML lacks the calligraphic mathvariant](https://github.com/mathml-refresh/mathml/issues/61). I imagine this has some influence on browser support for displaying formulas as well.

# Rationale and Alternatives

Given the technical difficulty with getting KaTeX support into Zola, I think this solution is simpler and still achieves support for most people’s needs. It’s also just a single, pure-rust dependency (which has no further dependencies), and seems to take very little time to do its thing. I don’t know how integration of KaTeX was envisioned, but I’ve had bad experiences in the past with a KaTeX plugin in Jekyll that made site generation significantly slower.

# Prior Art

- KaTeX, which can be used client-side with JavaScript and was attempted to be [added into Zola](https://github.com/getzola/zola/pull/1073) so it could be rendered ahead of time.
- MathJax, another JavaScript based client-side renderer of LaTeX formulas.

# Unresolved Questions

1. It’s unclear to me how the parsing of dollar signs changes in `pulldown-cmark` when you enable math mode. I think it would be nice be able to document this or point to more complete documentation. I think this can be easily resolved by asking nicely in their community. (So far I’ve changed single dollar signs in markdown to `&dollar;`, but haven’t checked yet with escaping with backslash works too, and whether that works inside a formula. I’ll do that soon, but I want to finish writing this post first.)
2. Should we support multiple errors from the event processing loop? The single mutable variable seems a bit off to me, there can be multiple latex formulas with errors after all…
3. Should the latex2mathml functionality be exposed as a filter too?

# Future possibilities

I purposely named the config option in markdown `math` to be pretty generic. We could also call it `latex`. This way if it turns out KaTeX can be fully supported in Zola in the future and has a clear benefit worth the change, the `latex2mathml` crate can be removed in favour of KaTeX as the implementation for this feature.

---

<div class="post-metadata">

**Author:** ![Apanatshka](https://avatars.discourse-cdn.com/v4/letter/a/ecd19e/32.png) [@Apanatshka](https://zola.discourse.group/u/Apanatshka)\
**Post date:** [June 8, 2024, 3:51pm UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/2 "2024-06-08T15:51:34Z")

</div>

To answer question number 1: just a backslash in front of a dollar will work just fine.

A bit of experience with this `latex2mathml` crate has taught me that this thing is pretty limited. But hey, better than nothing. It also looks like things it doesn’t like will end up as MathML output rather than an error… So far that’s not been a problem for me, but that’s because I was paying attention.  
Looks like it would be nice to eventually switch to KaTeX, but I still think it can be nice to start with this.

It’s also a very small change, have a look: [Comparing getzola:next...Apanatshka:latex2mathml · getzola/zola · GitHub](https://github.com/getzola/zola/compare/next...Apanatshka:zola:latex2mathml)

---

<div class="post-metadata">

**Author:** ![keats](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@keats](https://zola.discourse.group/u/keats)\
**Post date:** [November 18, 2024, 10:17pm UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/3 "2024-11-18T22:17:27Z")

</div>

Related PR: [Add optional math support for markdown by recmo · Pull Request #2708 · getzola/zola · GitHub](https://github.com/getzola/zola/pull/2708)

---

<div class="post-metadata">

**Author:** ![cestef](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/cestef/32/1407_2.png) [@cestef](https://zola.discourse.group/u/cestef)\
**Post date:** [February 7, 2025, 9:03am UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/4 "2025-02-07T09:03:46Z")

</div>

I have made an opinionated fork supporting [typst](https://typst.app) server rendering and other stuff. I could refactor all of this to make a PR if anyone is interested 😄

> **[GitHub - cestef/zola: A fast static site generator in a single binary...](https://github.com/cestef/zola)**
>
> A fast static site generator in a single binary with everything built-in. https://www.getzola.org

---

<div class="post-metadata">

**Author:** ![keats](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@keats](https://zola.discourse.group/u/keats)\
**Post date:** [February 7, 2025, 12:13pm UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/5 "2025-02-07T12:13:00Z")

</div>

I don’t use math at all, what’s the difference with what’s currently in Zola?

---

<div class="post-metadata">

**Author:** ![cestef](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/cestef/32/1407_2.png) [@cestef](https://zola.discourse.group/u/cestef)\
**Post date:** [February 7, 2025, 12:28pm UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/6 "2025-02-07T12:28:16Z")

</div>

Currently, the “only” way of rendering math in Zola is on the client-side via [katex](https://katex.org/docs/browser.html), which can become heavy on the browser if there is a lot of stuff to render. Not to mention this isn’t a really good idea for non-javascript readers.  
My implementation does the rendering part of the math stuff at the runtime of Zola and outputs SVGs that are then inserted.

---

<div class="post-metadata">

**Author:** ![keats](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@keats](https://zola.discourse.group/u/keats)\
**Post date:** [February 7, 2025, 12:31pm UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/7 "2025-02-07T12:31:38Z")

</div>

I thought it was merged but no: [Add optional math support for markdown by recmo · Pull Request #2708 · getzola/zola · GitHub](https://github.com/getzola/zola/pull/2708)

---

<div class="post-metadata">

**Author:** ![cestef](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/cestef/32/1407_2.png) [@cestef](https://zola.discourse.group/u/cestef)\
**Post date:** [February 7, 2025, 12:33pm UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/8 "2025-02-07T12:33:58Z")

</div>

I am trying to tidy up my branch for the math rendering, I’ll post a PR when it’s done 👍

---

<div class="post-metadata">

**Author:** ![cestef](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/cestef/32/1407_2.png) [@cestef](https://zola.discourse.group/u/cestef)\
**Post date:** [February 7, 2025, 1:37pm UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/9 "2025-02-07T13:37:51Z")

</div>

I posted a draft here:

> <https://github.com/getzola/zola/pull/2791>
>
> \*\*IMPORTANT: Please do not create a Pull Request adding a new feature without di…scussing it first.\*\*
> 
> The place to discuss new features is the forum: \<https://zola.discourse.group/\>
> If you want to add a new feature, please open a thread there first in the feature requests section.
> 
> Sanity check:
> 
> \* \[x\] Have you checked to ensure there aren't other open \[Pull Requests\](https://github.com/getzola/zola/pulls) for the same update/change?
> - https://github.com/getzola/zola/pull/2708 stalled
> 
> \## Code changes
> (Delete or ignore this section for documentation changes)
> 
> \* \[x\] Are you doing the PR on the \`next\` branch?
> 
> If the change is a new feature or adding to/changing an existing one:
> 
> \* \[\] Have you created/updated the relevant documentation page(s)?

---

<div class="post-metadata">

**Author:** ![helibom](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/helibom/32/1301_2.png) [@helibom](https://zola.discourse.group/u/helibom)\
**Post date:** [July 8, 2025, 9:09am UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/10 "2025-07-08T09:09:33Z")

</div>

I’d be really excited to be able to embed Typst in my Zola site.  
Glad to see Keats is taking a look at your PR!!!

---

<div class="post-metadata">

**Author:** ![evnoj](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/evnoj/32/1550_2.png) [@evnoj](https://zola.discourse.group/u/evnoj)\
**Post date:** [October 29, 2025, 8:03pm UTC](https://zola.discourse.group/t/a-simpler-katex-alternative-that-works-today/2156/11 "2025-10-29T20:03:06Z")

</div>

Thank you @Apanatshka for this - I love how simple the implementation is. I just wanted some simple math expressions on my site, and your implementation was very easy to apply to the current Zola `master` branch to get it working for me, especially since Zola upgraded the `pulldown-cmark` version independently. I’ve done this and put some simple documentation on how to use it in the README on a branch [here](https://github.com/evnoj/zola-ev/tree/mathml-readme).

It seems like this idea didn’t really catch on, and other solutions like the typst server rendering are getting more attention, but this solution was perfect for me. I already know LaTeX, and browsers handle the rendering of the MathML without JavaScript. The best thing is that it’s so simple that it’s easy maintain in a fork that stays up to date with mainline Zola - it’s basically one commit that adds 30 lines and one new dependency.

Thank you so much!
