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. 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 so it could be rendered ahead of time.
- MathJax, another JavaScript based client-side renderer of LaTeX formulas.
Unresolved Questions
- 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$
, 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.) - 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…
- 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.