Mathe in Hugo schreiben

Jul 27, 2026

Warum sollte man das wollen? Gute Frage.. In meinem Fall wollte ich eine Themenübersicht über den Vorkurs für Mathe an meiner Uni schreiben. Und da braucht man irgendwann halt schon mathematische Notationen. Hugo unterstützt das ganze von Haus aus aber nur so semi.

Wenn wir zum Thema Mathematik einmal die Docs konsultieren sehen wir, Hugo gibt uns tatsächlich ein kleines Tutorial mit an die Hand. Dieses Tutorial gucken wir uns hier nochmal ein bisschen mehr im Detail an.

Roadmap

Die Option Mathe rendern zu können, ist tatsächlich gar nicht so einfach hinzuzufügen wie man jetzt denken könnte. In Markdown ist alles was du machen musst $$ oder \(\) zu schreiben, je nach dem welchen Editor du nutzt und dir wird das Ergebnis sofort angezeigt. – Also, falls dein Editor Mathe unterstützt.

Hugo an sich ist aber nur ein CLI, das einen schon bestehenden und externen Markdown Parser, names Goldmark, benutzt um die Markdown Dateien in HTML zu übersetzen. Hugos eigentliche Aufgabe besteht darin Themes (also das Aussehen) und Layouts (die Vorlagen für die Struktur der Website) zu verwalten und die generierten HTML Dateien richtig zusammenzusetzen.

Wir müssen also die folgenden Items abarbeiten:

Schritt 1: Hugo vorbereiten

Wir haben schon geklärt das Hugo die md-Files eigentlich gar nicht selber parst, sondern dafür Goldmark benutzt. Das heißt, im Umkehrschluss, dass wir die Art verändern müssen, in der Hugo Goldmark benutzt. Dafür gibt uns Hugo die hugo.yaml (oder auch hugo.toml oder auch hugo.json, je nach dem wie abenteuerlustig du dich gerade fühlst.. no judgement here 🤷‍♂️), in der wir das gesamte Verhalten anpassen können.

In der hugo.yaml fügen wir als erstes den Parameter math: true an, falls wir Mathe-Rendering auf der gesamten Website wollen,

params:
  ...
  math: true

In meinem Fall wäre das ein bisschen Overkill – mir reicht es, Mathe auf den Unterseiten einzubinden wo ich es wirklich brauche. Wie das geht, zeige ich in Schritt 3.

Jetzt müssen wir aber immer noch Hugo sagen, wie es Goldmark benutzen soll um unsere Matheblöcke nicht zu zerparsen.

I.e. ist unser Problem folgenden: trifft Goldmark auf den Befehl \begin{pmatrix} a & b \\ c & d \end{pmatrix}, wird jedes \ ungewollt “escaped”. Im Prinzip sieht Goldmark das \ und weiß aber, dass es normalerweise nicht vom Browser angezeigt wird weil es ein Steuerzeichen ist – nämlich das Steuerzeichen, das wiederum andere Steuerzeichen sichtbar macht. Zum Beispiel müsste man eigentlich \ oder \\ schreiben, um ein \ zu erzeugen. Goldmark setzt aber dieses \ automatisch für uns, was eingentlich hilft, aber in diesem Kotext halt leider über das Ziel hinaus schießt.

Dafür zapfen wir Hugos markup Section an und fügen sogenannte passthrough delimiters an. Passthrough bedeutet Goldmark einfach bestimmte Bereiche beim Parsen einfach zu ignorieren, und die delimiters geben Goldmark an, wie diese Bereiche begrenzt/gekennzeichnet sind.

In meinem Fall möchte ich Mathe sowohl in Zeilen, als auch als Blöcke rendern können. Goldmark kennt diese zwei Typen als inline und display. Diese beiden Typen möchte ich jeweils begrenzen durch \( ... \)/$ ... $ und \[ ... \]/$$ ... $$.

markup:
  goldmark:
    extensions:
      passthrough:
        delimiters:
          block:
            - - '\['
              - '\]'
            - - $$
              - $$
          inline:
            - - '\('
              - '\)'
            - - $
              - $
        enable: true

Schritt 2: Einen Matherenderer aussuchen

Dieses Schritt ist apparanetly auch eine eigene Wissenschaft für sich. Neben den großen Namen wie KaTeX und MathJax gibt es auch noch TikZJax, Temml, SnuggleTeX und viele mehr. Ein Deepdive in dieses Thema wäre hier aber nicht wirklich zielführend, deswegen reduziere ich den Post an dieser Stelle einmal didaktisch und verweise nur auf den Artikel von PiStack zu dem Thema.

Bei allen externen Links zu Deepdives sind immer Snapshots im Archive verfügbar :)

In meinem Fall ist die Entscheidung am Ende auf MathJax gefallen.

Schritt 3: Partialer Spaß

Ich hab ja schon erwähnt, dass Hugo “nur” den Output von Goldmark richtig zusammensetzt und die Website daraus baut. Dafür sind in jedem Theme Layouts hinterlegt. Diese Layout Files können wir jetzt lokal so anpassen, dass wir neue “Teile” bedingt auf der Website hinzufügen. Diese “Teile” bezeichnen wir als Partials.

Im Grunde genommen ist jedes Layout File einfach nur eine HTML Datei mit Optionen auf ein bisschen in-House Code von Hugo. Als erstes erstellen wir uns die Datei ./layouts/_partials/math.html, in der wir unseren Renderer importieren.

<script
  id="MathJax-script"
  async
  src="https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js"
></script>

<script>
  MathJax = {
    tex: {
      displayMath: [
        ["\\[", "\\]"],
        ["$$", "$$"],
      ],
      inlineMath: [
        ["\\(", "\\)"],
        ["$", "$"],
      ],
    },
    loader: {
      load: ["ui/safe"],
    },
  };
</script>

Wobei wir auch hier nochmal unsere passthrough delimiters aus dem ersten Schritt angeben müssen.

Schritt 4: Das Partial einbinden

Im letzten Schritt müssen wir Hugo noch beibringen das Partial math.html immer dann zu laden, wenn in den Parametern im Frontmatter der Seite

---
...
math: true
---

gesetzt ist. Dazu kopieren wir uns als erstes das “Hauptlayout” vom aktuellen Theme ./themes/<dein Theme hier einfügen>/layouts/_default/baseof.html in unseren lokalen Layouts Ordner ./layouts/_default/baseof.html. Im lokalen baseof.html fügen wir jetzt an der vorgegebenen Stelle dieses Snippet

<head>
  {{ if .Param "math" }}
    {{ partialCached "math.html" . }}
  {{ end }}
</head>

ein. In meinem Fall muss ich diesen Block, laut Docs von MathJax im head der Seite einfügen.

An der Stelle sollte ich vielleicht noch erwähnen, dass Hugo grundsätzlich immer lokale Dateien bevorzugt. In unserem Fall werden also die Dateien in ./layouts immer den Dateien in ./themes/<dein Theme hier einfügen>/layouts vorgezogen. Hugo greift nur auf Layouts aus dem Theme zurück, falls lokal keine passende Datei hinterlegt ist.

Woher weiß ich was die vorgegebene Stelle ist?

Guck in die Docs vom Renderer, den du dir ausgesucht hast. Da steht sowas eigentlich immer drin. Falls nicht, head ist immer eine gute Idee.


Congrats! wenn du im Frontmatter math: true setzt, kannst du jetzt Mathe schreiben.