๐Ÿ“ข Actions Speak Louder Than Words!

Hugo with Math (KaTeX + mmark)

Posted: Jul 14, 2021 | Reading time: 4 min


I not good with math but sometimes I need to use math notation to explain something. So I try to find if Hugo have built-in math syntax, but seem it not there. On Jekyll, I can use MathJax but it terribly slow and broke it it take times too long to render the formulas, then I found the alternative for MathJax and it called as KaTeX.

As usual, stuff like this are depend on CSS and JavaScript programming, so here we are. There is no need to re-invent too much because KaTeX already prepare the CDN for us to use.

Partial layout:

Like I told you, KaTeX have CDN ready to use but I still want to host it on Gitlab pages and just use the CDN on local built.

You will get CORS policy: No 'Access-Control-Allow-Origin' header issue appears on your dev-tools console if you don't use CDN when doing local built on your computer, so I suggest to use CDN for local build and use stored asset when upload / build it on server

First add this /themes/XYZ/layouts/partials/katex.html file, please alter it if you just one to use CDN on both local and remote hosted Hugo.

{{/*  KaTeX  */}}
{{ if eq (printf "%v" $.Site.BaseURL) "http://localhost:1313/" }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" media="all" onload="this.media='all',this.onload=null" crossorigin="">
<script defer="" src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js" integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4" crossorigin=""></script>
<script defer="" src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js" integrity="sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa" crossorigin=""></script>
{{ else }}
{{ $katex := resources.Get "css/katex.min.css" | minify | fingerprint }}
<link rel=stylesheet href="{{ $katex.Permalink }}" media=print onload="this.media='all',this.onload=null" crossorigin>
<script defer src="{{ .Site.BaseURL }}js/katex.min.js" crossorigin></script>
<script defer src="{{ .Site.BaseURL }}js/auto-render.min.js" crossorigin></script>
  document.addEventListener("DOMContentLoaded", function () {
    renderMathInElement(document.body, {
      delimiters: [
        { left: "$$", right: "$$", display: true },
        { left: "$", right: "$", display: false },
        { left: "\\(", right: "\\)", display: false },
        { left: "\\[", right: "\\]", display: true }
{{ end }}

Let's inject our partial code to headers file, just put it between <head>...</head>

{{ if ( .Params.math | default false )}}
  {{ partial "katex.html" . }}
{{ end }}

Matterfront setting

To supports the rendering of mathematical formulas by using KaTeX, we need to define two extra parameter on each post or page that use KaTeX, we need to put markup: "mmark" and math: true parameters

title: "Hugo with Math (KaTeX + mmark)"
date: 2021-07-14T15:24:14+08:00
markup: "mmark"
math: true

Writing $\LaTeX$

To displayed equation like this:

\[ \int u \frac{dv}{dx}\, dx=uv-\int \frac{du}{dx}v\,dx \]

You need to using <div> tags as example below:

\[ \int u \frac{dv}{dx}\, dx=uv-\int \frac{du}{dx}v\,dx \]

Here another example, the famous Matrix reloaded (just kidding) :

\[ \begin{pmatrix} a&b\\c&d \end{pmatrix} \quad \begin{bmatrix} a&b\\c&d \end{bmatrix} \quad \begin{Bmatrix} a&b\\c&d \end{Bmatrix} \quad \begin{vmatrix} a&b\\c&d \end{vmatrix} \]

As mentioned before, you need to use <div>

\[ \begin{pmatrix} a&b\\c&d \end{pmatrix} \quad
\begin{bmatrix} a&b\\c&d \end{bmatrix} \quad
\begin{Bmatrix} a&b\\c&d \end{Bmatrix} \quad
\begin{vmatrix} a&b\\c&d \end{vmatrix} \]

Same goes for aligned equation:

\[\begin{aligned} x ={}& a+b+c+{} \\ &d+e+f+g \end{aligned}\]
x ={}& a+b+c+{} \\

Another thing is you can type inline equation like example below:

  • $E=mc^2$ which rendered as $E=mc^2$
  • $\int_{a}^{b} x^2 dx$ which rendered as $\int_{a}^{b} x^2 dx$
  • $\int u \frac{dv}{dx}\, dx=uv-\int \frac{du}{dx}v\,dx$ as $\int u \frac{dv}{dx}\, dx=uv-\int \frac{du}{dx}v\,dx$
  • $\mathbf{y} = \mathbf{X}\boldsymbol\beta + \boldsymbol\varepsilon$ as $\mathbf{y} = \mathbf{X}\boldsymbol\beta + \boldsymbol\varepsilon$

It also capable to generated multi line math formula \(f(k;p_0^*) = \begin{cases} p_0^* & \text{if }k=1, \\ 1-p_0^* & \text {if }k=0.\end{cases}\) by using standard $\LaTeX$ line break consisting of 2 backslashes and you must put double dolar sign to make it work correctly.

multi line math formula $$f(k;p_0^*) = \begin{cases} p_0^* & \text{if }k=1, \\
1-p_0^* & \text {if }k=0.\end{cases}$$ just like this.


Well, the drawback is by using mmark, it may broken later in future because when you build it, you may notice a warning message which it say:

mmark is deprecated and will be removed in a future release. See https://gohugo.io/content-management/formats/#list-of-content-formats"

Plus, some hugo tag maybe not working such as .Page.TableOfContents (for table of contents) when you use nmark markup but for me, I don't mind so much about it, let fix it later :)

\[\left [ โ€“ \frac{\hbar^2}{2 m} \frac{\partial^2}{\partial x^2} + V \right ] \Psi = i \hbar \frac{\partial}{\partial t} \Psi\]

P/s : Maybe we should use MathJax instead of KaTeX?


Discussion and feedback

You can use utterances provided below to post comment on behalf using Github account. Alternatively, you can just send a public comment to my mailing list or send a private message to my e-mail. In a few cases and on certain time, I just donโ€™t have time to moderate them. Please read terms-of-service (ToS) for details.