HUGO
Menu
GitHub 90206 stars Mastodon

transform.ToMath

Returns the given mathematical markup, written in the LaTeX language, rendered to HTML.
Syntax
transform.ToMath INPUT [OPTIONS]
Returns
template.HTML

Usage

The transform.ToMath function returns the given mathematical markup, written in the LaTeX language, rendered to HTML. Hugo uses an embedded instance of the KaTeX display engine to render the markup. You do not need to install the KaTeX display engine.

Call this function from a passthrough render hook to render mathematical markup when you build the site, instead of on the client side with MathJax or KaTeX.

Hugo caches the result to disk in the misc file cache, so calling the function multiple times with the same arguments incurs no additional overhead.

By default, Hugo renders mathematical markup to MathML, and does not require any CSS to display the result.

To optimize rendering quality and accessibility, set the output option to htmlAndMathml. This approach requires the KaTeX stylesheet, as described in the output option.

Error handling

There are three ways to handle errors:

  1. Let KaTeX throw an error and fail the build. This is the default behavior.
  2. Set the throwOnError option to false to make KaTeX render the expression as an error instead of throwing an error.
  3. Handle the error in your template, as shown in the render hook example under examples.

Chemistry

New in v0.144.0

You can also use the transform.ToMath function to render chemical equations, using the \ce and \pu functions from the mhchem package.

$$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$
Cp[HX2O(l)]=75.3 Jmol KC_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}

Options

The transform.ToMath function accepts an options map. These options are a subset of the KaTeX rendering options.

displayMode
(bool) Whether to render in display mode instead of inline mode. Default is false.
errorColor
(string) The color of the error messages expressed as an RGB hexadecimal color. Default is #cc0000.
fleqn
(bool) Whether to render flush left with a 2em left margin. Default is false.
macros
(map) A map of macros to be used in the math expression. Default is {}.
{{ $macros := dict
  "\\addBar" "\\bar{#1}"
  "\\bold" "\\mathbf{#1}"
}}
{{ $opts := dict "macros" $macros }}
{{ transform.ToMath "\\addBar{y} + \\bold{H}" $opts }}
minRuleThickness
(float) The minimum thickness of the fraction lines in em. Default is 0.04.
output
(string) Determines the markup language of the output, one of html, mathml, or htmlAndMathml. Default is mathml.

With html and htmlAndMathml you must include the KaTeX stylesheet within the head element of your base template.

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.18.4/dist/katex.min.css" integrity="sha384-u1zONI5gPXUx0UKI62c75/zww972y0v2rSK5ZYlVdS6xEuWDeZWUI66v6t1gvlXJ" crossorigin="anonymous">
strict
New in v0.147.6
(string) Controls how KaTeX handles LaTeX features that offer convenience but aren’t officially supported, one of error, ignore, or warn. Default is error.
  • error: Throws an error when convenient, unsupported LaTeX features are encountered.
  • ignore: Allows convenient, unsupported LaTeX features without any feedback.
  • warn: New in v0.147.7 Emits a warning when convenient, unsupported LaTeX features are encountered.

The newLineInDisplayMode error code, which flags the use of \\ or \newline in display mode outside an array or tabular environment, is intentionally designed not to throw an error, despite this behavior being questionable.

throwOnError
(bool) Whether to throw a ParseError when KaTeX encounters an unsupported command or invalid LaTeX. Default is true.

Examples

{{ transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" }}

Rendering to HTML and MathML:

{{ $opts := dict "output" "htmlAndMathml" }}
{{ transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" $opts }}

In a passthrough render hook, handling errors within the template:

Step 1
Enable and configure the Goldmark passthrough extension in your project configuration. The passthrough extension preserves raw Markdown within delimited snippets of text, including the delimiters themselves.
markup:
  goldmark:
    extensions:
      passthrough:
        delimiters:
          block:
          - - '\['
            - '\]'
          - - $$
            - $$
          inline:
          - - '\('
            - '\)'
        enable: true
[markup]
  [markup.goldmark]
    [markup.goldmark.extensions]
      [markup.goldmark.extensions.passthrough]
        enable = true
        [markup.goldmark.extensions.passthrough.delimiters]
          block = [['\[', '\]'], ['$$', '$$']]
          inline = [['\(', '\)']]
{
   "markup": {
      "goldmark": {
         "extensions": {
            "passthrough": {
               "delimiters": {
                  "block": [
                     [
                        "\\[",
                        "\\]"
                     ],
                     [
                        "$$",
                        "$$"
                     ]
                  ],
                  "inline": [
                     [
                        "\\(",
                        "\\)"
                     ]
                  ]
               },
               "enable": true
            }
         }
      }
   }
}

The configuration above precludes the use of the $...$ delimiter pair for inline equations. Although you can add this delimiter pair to the configuration, you must double-escape the $ symbol when used outside of math contexts to avoid unintended formatting.

Step 2
Create a passthrough render hook to capture and render the LaTeX markup.
layouts/_markup/render-passthrough.html
{{- $opts := dict "output" "htmlAndMathml" "displayMode" (eq .Type "block") }}
{{- with try (transform.ToMath .Inner $opts) }}
  {{- with .Err }}
    {{- errorf "Unable to render mathematical markup to HTML using the transform.ToMath function. The KaTeX display engine threw the following error: %s: see %s." . $.Position }}
  {{- else }}
    {{- .Value }}
    {{- $.Page.Store.Set "hasMath" true }}
  {{- end }}
{{- end -}}
Step 3
In your base template, conditionally include the KaTeX CSS within the head element.
layouts/baseof.html
<head>
  {{ $noop := .WordCount }}
  {{ if .Page.Store.Get "hasMath" }}
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.18.4/dist/katex.min.css" integrity="sha384-u1zONI5gPXUx0UKI62c75/zww972y0v2rSK5ZYlVdS6xEuWDeZWUI66v6t1gvlXJ" crossorigin="anonymous">
  {{ end }}
</head>

The noop statement forces content rendering before the template checks the value of hasMath with the Store.Get method.

This conditional approach only identifies math on the current page. Mathematical expressions do not display correctly when one page’s content is embedded within another. For example, if a list page calls the Content or Summary methods while ranging through its page collection, the list page does not load the KaTeX CSS.

If this affects your site, use this conditional logic instead:

layouts/baseof.html
{{ $noop := .WordCount }}
{{ if or (.Page.Store.Get "hasMath") .IsNode }}
  <link rel="stylesheet" href="...">
{{ end }}
Step 4
Add some mathematical markup to your content, then test.
content/example.md
This is an inline \(a^*=x-b^*\) equation.

These are block equations:

\[a^*=x-b^*\]

$$a^*=x-b^*$$