# Add KaTeX SSR support

**URL:** <https://zola.discourse.group/t/add-katex-ssr-support/1147>\
**Category:** Feature requests\
**Created:** [January 23, 2022, 6:42am UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147 "2022-01-23T06:42:47Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![narisuzu](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/narisuzu/32/659_2.png) [@narisuzu](https://zola.discourse.group/u/narisuzu)\
**Post date:** [January 23, 2022, 6:42am UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/1 "2022-01-23T06:42:47Z")

</div>

Hi.  
I try to add the KaTeX server side rendering feature to Zola. if Zola has this, it will not be necessary to render KaTeX formulas on browser. KaTeX formulas will be extracted into HTML on server side. Such that web pages will be rendered much faster !

**options:**

- in site config

- in frontmatter

What do you guys think about?

---

<div class="post-metadata">

**Author:** ![spence](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/spence/32/1022_2.png) [@spence](https://zola.discourse.group/u/spence)\
**Post date:** [January 23, 2022, 3:18pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/2 "2022-01-23T15:18:33Z")

</div>

I would like support for katex, but I would probably prefer it to be at the templating layer. Like instead of piping markdown text to be rendered as html, piping latex to be rendered as html.

---

<div class="post-metadata">

**Author:** ![narisuzu](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/narisuzu/32/659_2.png) [@narisuzu](https://zola.discourse.group/u/narisuzu)\
**Post date:** [January 23, 2022, 7:38pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/4 "2022-01-23T19:38:10Z")

</div>

It’s not difficult to integrate katex into templating layer. but it’s difficult to avoid the ugly Tera syntax.

**Default:**

```auto
$$F=ma$$

```

**Tera Function**

```auto
{{ tex(code = "F = ma", display = true) }}

```

if you have a good way to optimize this, Please tell me. I will be glad to use this plan.

---

<div class="post-metadata">

**Author:** ![spence](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/spence/32/1022_2.png) [@spence](https://zola.discourse.group/u/spence)\
**Post date:** [January 24, 2022, 11:10am UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/5 "2022-01-24T11:10:56Z")

</div>

Hi Narisuzu, I think I may have made the mistake of not thinking hard enough before answering your question, so apologies for that. I’ll do more to brainstorm here with you.

First, how would KaTeX normally be utilized? In the browser, it would look something like this:

```auto
katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, {
    throwOnError: false
});

```

There are two things we need to know: 1. ) _what_ is the KaTeX expression we are looking to render and 2.) _where_ do we want it to be rendered, in the context of the rest of the page?

However, the whole problem we’re looking to solve is provide some SSR solution to utilizing KaTeX, within the framework and design of Zola. Bearing this in mind, I see maybe a few places we could do this.

One, is within the context of a markdown file. In this context, point #2 (I.e. where the element should be rendered) is determined by the location in the markdown file. I could imagine there being two places this could done: a.) within a code block, like:

```KaTeX  
c = \pm\sqrt{a^2 + b^2}  
```

and b.) the other way I imagine it could be used within markdown would be via a shortcode.

I don’t think there’s any other way to use Tera within markdown other than through shortcode, so it seems like code blocks and shortcodes is all that would be available to use within a markdown context. Although correct me if I’m wrong there.

Besides markdown, I also think we’d probably also want the ability to inject rendered KaTeX within the context of the actual HTML code, although I think that would be less common. So in Zola that’s basically sections, pages, and macros I believe.

After thinking about it a bit, I feel like all the templating stuff (which so far is within a shortcode, sections/pages, and macros) could probably be best done at the templating layer. I don’t think this

```auto
{{ tex(code = "F = ma", display = true) }}

```

is honestly so bad. Maybe the one thing I’d add is can I also read KaTeX from a file and pipe it to the `tex` function?

That leaves supporting it in markdown via the codeblocks. To be honest, this is where I would use KaTeX 95% of the time anyway… Maybe there could be a branch in the syntax highlighting logic (within Zola) that looks for if the codeblock is marked as `katex`. If it is, then it passes it to the KaTeX rendered. Otherwise, then it goes through the normal code highlighting flow. Also, you’d probably want the ability to show KaTeX unrendered within code blocks as well, so maybe for that you could saw `katex-raw` or something.

I’m not sure if that’s helpful at all. This is just me thinking aloud and where I’m coming from as a user and how I would probably use KaTeX in Zola. Another thing as a user that I would care a lot about is KaTeX support not slowing down how long it takes to compile my site. If using KaTeX in one place on my website slowed down the build by 250ms or something, I’d be pretty annoyed. So, I don’t know if it would work to call out to a nodejs process for each individual case that you have to generate HTML. Maybe there’s a library in rust that can be embedded within the Zola code to do this fast, but you probably know a lot more about that than I do.

Any way, apologies for the wall of text. I’m happy to discuss more offline too. You can find me on GH as `asimpletune`, or on my website [Contact - Spenc.es](https://spenc.es/contact) and I’m happy to collaborate where I can. Best of luck!

---

<div class="post-metadata">

**Author:** ![narisuzu](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/narisuzu/32/659_2.png) [@narisuzu](https://zola.discourse.group/u/narisuzu)\
**Post date:** [January 24, 2022, 3:09pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/6 "2022-01-24T15:09:14Z")

</div>

Thanks for your ideas!

1. We can use [this](https://tera.netlify.app/docs/#filters) to get a simpler syntax. it will be like:

2. I think it is possible to read KaTeX code from a file. it probably will be like

3. code block  
To implement this, I think it’s necessary to modify [Here](https://github.com/getzola/zola/blob/a7abc840678e0331ef77c3a60ce145a6f995bc71/components/rendering/src/markdown.rs#L287-L300) and line 243, which will allow zola checking whether the code block is a KaTeX formula. and render it accordingly.

4. performance  
the KaTeX lib I used is called `katex-rs`(Sorry for that I cannot put more URLs, but you can search this on Github). This lib chose some Rust JS engines as its backend, instead of a Node.js instance. Indeed, it will be better if we have an implementation with pure rust. but I cannot find a lib to do this.

I will go on attempting to implement these (‘tera filter’ and ‘code block’). I will share with you once I have any improvement. I really appreciate your help so much.

---

<div class="post-metadata">

**Author:** ![spence](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/spence/32/1022_2.png) [@spence](https://zola.discourse.group/u/spence)\
**Post date:** [January 24, 2022, 3:20pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/7 "2022-01-24T15:20:49Z")

</div>

Cool! Yeah sounds interesting, I’d be happy to help whenever you have something to share. I’m `asimpletune` on GitHub.

---

<div class="post-metadata">

**Author:** ![narisuzu](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/narisuzu/32/659_2.png) [@narisuzu](https://zola.discourse.group/u/narisuzu)\
**Post date:** [January 25, 2022, 12:10pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/8 "2022-01-25T12:10:24Z")

</div>

for display mode There are two way to implement.

1. `{{"F=ma"| tex_display }}`: make a new function.
2. `{{"F=ma" | tex(display = true) }}`: use same function, but pass a parameter.

I don’t know which is better. the first one is obviously simpler. but the second one is more configurable.

---

<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:** [January 25, 2022, 8:18pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/9 "2022-01-25T20:18:23Z")

</div>

There was a PR for that: [Katex by technicalguy · Pull Request #1073 · getzola/zola · GitHub](https://github.com/getzola/zola/pull/1073) but it didn’t work on Windows at the time. I would take a PR to add support to Zola

---

<div class="post-metadata">

**Author:** ![spence](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/spence/32/1022_2.png) [@spence](https://zola.discourse.group/u/spence)\
**Post date:** [January 27, 2022, 8:32am UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/10 "2022-01-27T08:32:19Z")

</div>

I like `{{"F=ma" | tex(display = true) }}` best of all. Maybe there’s also a way to have the `display` parameter take `true` as a default as well?

---

<div class="post-metadata">

**Author:** ![sshine](https://avatars.discourse-cdn.com/v4/letter/s/71c47a/32.png) [@sshine](https://zola.discourse.group/u/sshine)\
**Post date:** [February 2, 2022, 2:52pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/11 "2022-02-02T14:52:28Z")

</div>

I would also be very interested in this. Having MathJax 3 as a JS dependency adds \>160KB to my website footprint, which is almost double. But not having `$$ equation goes here $$` would be a hard sell for my scientific colleagues, and this is the level of convenience that MathJax currently supports.

The alternative I considered was to produce SVGs like so: [https://latextosvg.com/](https://latextosvg.com/)

Having them compile to anything that can be rendered with JS disabled is preferrable for the purpose of having the website always work (offline, archived, transfered, independent of CDN and JS engines).

I won’t suggest any concrete ways to make `$$ equation $$`s work, since I don’t know enough about Zola’s principles. But I’ll probably stick with MathJax until I find an easy way to make `$$ equations $$` compile to either SVG or KaTeX. 🙂

---

<div class="post-metadata">

**Author:** ![narisuzu](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/narisuzu/32/659_2.png) [@narisuzu](https://zola.discourse.group/u/narisuzu)\
**Post date:** [February 8, 2022, 6:02pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/13 "2022-02-08T18:02:45Z")

</div>

It’s basically done but the macros rendering within a page. It is impossible for Tera funtions/filters to get the macros definition during rendering a page(except some hacky tricks, like, clone and expand the current tera with registering a specific katex filter which the macros defined in the frontmatter are passed to for each page. or set a global hashmap to store the macro definitions in each page)

However, I noticed that @keats has a plan to let filters be able to access context in next version of tera. [https://github.com/Keats/tera/issues/543](https://github.com/Keats/tera/issues/543). So I decide to wait for this update of tera. So that, We are able to define katex macros in the frontmatters and put them in tera context. and register a katex filter just like other filters inside the `components/templates` sub-crate, which is a better way to handle the macros in page.

---

<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 9, 2022, 5:23pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/14 "2022-02-09T17:23:55Z")

</div>

> [@narisuzu](#):
>
> So I decide to wait for this update of tera

That’s potentially a long time! I have a new lexer/parser written but I’m rewriting them to remove a dependency. Going very very slowly though as it’s not a priority currently, i spend maybe 1h a week on it _if_ i’m spending time on it.

---

<div class="post-metadata">

**Author:** ![spence](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/spence/32/1022_2.png) [@spence](https://zola.discourse.group/u/spence)\
**Post date:** [February 10, 2022, 5:12pm UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/15 "2022-02-10T17:12:28Z")

</div>

Hi! Let me take a closer look at this within the next few days. I’m busy traveling right now, but I can probably spend a little time on this next week.

Maybe in the meanwhile you can clarify a few things? I’m sure it’ll be crystal clear when I actually look at the code, but it doesn’t hurt to ask before then.

> It’s basically done but the macros rendering within a page

I’m not sure I understand this macro part. Is the context I’m missing that: you’ve implemented this new katex feature as a tera function, for example `{{"F=ma" | tex(display = true) }}` (to use the example from before), but when you want to use this function from within a macro it doesn’t have _some context_ that it needs? (and this context is usually available within a Zola page/section?)

Did I understand that correctly?

> It is impossible for Tera funtions/filters to get the macros definition during rendering a page  
> […]  
> However, I noticed that @keats has a plan to let filters be able to access context in next version of tera.

I’m not sure I really follow what context is needed where. Like, there’s a page being rendered, and a tera filter being used, but it needs the “macro” definition? That’s the last part I’m not sure I quite follow.

Ok but with this said, I’m also assuming that _whatever dependency_ that is needed (I.e. macro definition above), _can_ be gotten somewhere (I.e. in a page maybe? Not just a filter). So, technically, could the result of doing that just be passed along to the filter as an argument for now?

Maybe I’m way off base here, I’m sort of piecing this together from reading your comment and haven’t looked at the code haha. So I’m sure it’ll be crystal clear when I take a closer look, but if you have a moment to respond to this comment before then, then great and thanks!

O and also I didn’t see a PR on the [Zola repo](https://github.com/getzola/zola/pulls) so maybe you could also tell me where the code lives too.

Also, here’s an idea that just came to me… but if there are parts of this working, it wouldn’t be the end of the world to break this up into separate PRs and at least get something that’s working merged upstream. Like, for example, if the syntax highlighting part is done, that covers a pretty big use case already.

---

<div class="post-metadata">

**Author:** ![narisuzu](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/narisuzu/32/659_2.png) [@narisuzu](https://zola.discourse.group/u/narisuzu)\
**Post date:** [February 15, 2022, 9:57am UTC](https://zola.discourse.group/t/add-katex-ssr-support/1147/16 "2022-02-15T09:57:55Z")

</div>

the macros I mentioned above means the KaTeX Macros. [Info](https://katex.org/docs/options.html). I think users should be able to set different macros in different page. So the macros can be defined in 2 ways: Global macros which is defined in site config and page macros in frontmatters.

and here it is

> **[GitHub - narisuzu/zola at katex](https://github.com/narisuzu/zola/tree/katex)**
>
> katex
