summaryrefslogtreecommitdiffstats
path: root/docs/content/en/functions/transform/ToMath.md
blob: 10cd256c5e20a18d4fac0647a7e6beae87b0c099 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
---
title: transform.ToMath
description: Renders mathematical equations and expressions written in the LaTeX markup language.
categories: []
keywords: [katex,latex,math,typesetting]
action:
  aliases: []
  related:
    - content-management/mathematics
  returnType: types.Result[template.HTML]
  signatures: ['transform.ToMath INPUT [OPTIONS]']
aliases: [/functions/tomath]
toc: true
---

{{< new-in 0.132.0 />}}

Hugo uses an embedded instance of the [KaTeX] display engine to render mathematical markup to HTML. You do not need to install the KaTeX display engine.

[KaTeX]: https://katex.org/

```go-html-template
{{ transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" }}
```

{{% note %}}
By default, Hugo renders mathematical markup to [MathML], and does not require any CSS to display the result.

[MathML]: https://developer.mozilla.org/en-US/docs/Web/MathML

To optimize rendering quality and accessibility, use the `htmlAndMathml` output option as described below. This approach requires an external stylesheet.

{{% /note %}}

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

## Options

Pass a map of options as the second argument to the `transform.ToMath` function. The options below are a subset of the KaTeX [rendering options].

[rendering options]: https://katex.org/docs/options.html

displayMode
: (`bool`) If `true` render in display mode, else render in inline mode. Default is `false`.

errorColor
: (`string`) The color of the error messages expressed as an RGB [hexadecimal color]. Default is `#cc0000`.

[hexadecimal color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color

fleqn
: (`bool`) If `true` 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 `{}`.

    ```go-html-template
    {{ $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 style sheet within the `head` element of your base template.

    ```html
    <link href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css" rel="stylesheet">

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

## Error handling

There are three ways to handle errors:

1. Let KaTeX throw an error and fail the build. This is the default behavior.
1. Set the `throwOnError` option to `false` to make KaTeX render the expression as an error instead of throwing an error. See [options](#options).
1. Handle the error in your template.

The example below demonstrates error handing within a template.

## Example

Instead of client-side JavaScript rendering of mathematical markup using MathJax or KaTeX, create a passthrough render hook which calls the `transform.ToMath` function.

###### Step 1

Enable and configure the Goldmark [passthrough extension] in your site configuration. The passthrough extension preserves raw Markdown within delimited snippets of text, including the delimiters themselves.

[passthrough extension]: /getting-started/configuration-markup/#passthrough

{{< code-toggle file=hugo copy=true >}}
[markup.goldmark.extensions.passthrough]
enable = true

[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
inline = [['\(', '\)']]
{{< /code-toggle >}}

{{% note %}}
The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration, you will need to double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting.
{{% /note %}}

###### Step 2

Create a [passthrough render hook] to capture and render the LaTeX markup.

[passthrough render hook]: /render-hooks/passthrough/

{{< code file=layouts/_default/_markup/render-passthrough.html copy=true >}}
{{- $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 -}}
{{< /code >}}

###### Step 3

In your base template, conditionally include the KaTeX CSS within the head element.

{{< code file=layouts/_default/baseof.html copy=true >}}
<head>
  {{ $noop := .WordCount }}
  {{ if .Page.Store.Get "hasMath" }}
    <link href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css" rel="stylesheet">
  {{ end }}
</head>
{{< /code >}}

In the above, note the use of a [noop](g) statement to force content rendering before we check the value of `hasMath` with the `Store.Get` method.

#### Step 4

Add some mathematical markup to your content, then test.

{{< code file=content/example.md >}}
This is an inline \(a^*=x-b^*\) equation.

These are block equations:

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

$$a^*=x-b^*$$
{{< /code >}}