1[:octicons-file-code-24:][_arithmatex]{: .source-link }
2
3# Arithmatex
4
5## Overview
6
7Arithmatex is an extension that preserves LaTeX math equations during the Markdown conversion process so that they can
8be used with libraries like [MathJax][mathjax]. If you prefer to use something other than MathJax, Arithmatex can output
9a more generic format suitable for other libraries like [KaTeX][katex].
10
11Arithmatex searches for the patterns `#!tex $...$` and `#!tex \(...\)` for inline math, and `#!tex $$...$$`,
12`#!tex \[...\]`, and `#!tex \begin{}...\end{}` for block math. By default, all formats are enabled, but each format can
13individually be disabled if desired.
14
15The Arithmatex extension can be included in Python Markdown by using the following:
16
17```py3
18import markdown
19md = markdown.Markdown(extensions=['pymdownx.arithmatex'])
20```
21
22## Input Format
23
24By default, [`smart_dollar`](#options) mode is enabled for the `#!tex $...$` inline variant. With `smart_dollar` it is
25expected that the opening token (`#!tex $`) is to be followed by a non-whitespace character, and the closing to be
26preceded by a non-white-space character.  This is to help avoid false positives when using the dollar sign in
27traditional ways such as: *I have $2.00 and Bob has $10.00*.  The previous statement requires no escaping of the
28`#!tex $` character.  But when needed, the `#!tex $` character can be escaped using `#!tex \$`. `smart_dollar` can be
29disabled and will capture any `#!tex $...$` whose dollar symbols are not escaped (`#!tex \$`).
30
31!!! example "Inline Examples"
32
33    === "Output"
34        $p(x|y) = \frac{p(y|x)p(x)}{p(y)}$, \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\).
35
36    === "Markdown"
37        ```tex
38        $p(x|y) = \frac{p(y|x)p(x)}{p(y)}$, \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\).
39        ```
40
41!!! tip "Inline Configuration"
42    When using MathJax, for best results, it is advised to not use [`generic`](#options) mode, and configure MathJax
43    without the `text2jax` extension since MathJax automatically detects Arithmatex's default output.
44
45    If using generic mode (for libraries like KaTeX), Arithmatex will convert dollars to the form `#!tex \(...\)` in the
46    HTML output. This is because `#!tex $...$` is extremely problematic to scan for, which is why MathJax and KaTeX
47    disable `#!tex $...$` by default in their plain text scanners, and why Arithmatex enables `smart_dollar` by default
48    when scanning for `#!tex $...$`.
49
50    It is advised that if you are outputting in in `generic` mode that you do not configure your JavaScript library to
51    look for `#!tex $...$` and instead look for `#!tex \(...\)`, and let Arithmatex's handle `#!tex $...$`.
52
53For block forms, the block must start with the appropriate opening for the block type: `#!tex $$`, `#!tex \[`, and
54`#!tex \begin{}` for the respective search pattern. The block must also end with the proper respective end: `#!tex $$`,
55`#!tex \]`, and `#!tex \end{}`. A block also must contain no empty lines and should be both preceded and followed by an
56empty line.
57
58!!! example "Block Examples"
59
60    === "Output"
61        $$
62        E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j
63        $$
64
65        \[3 < 4\]
66
67        \begin{align}
68            p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
69            p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
70        \end{align}
71
72    === "Markdown"
73        ```tex
74        $$
75        E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j
76        $$
77
78        \[3 < 4\]
79
80        \begin{align}
81            p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
82            p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
83        \end{align}
84        ```
85
86## MathJax Output Format
87
88!!! note "Form Dropped in MathJax 3"
89    The title is a bit misleading. Yes, MathJax 3 dropped supporting the format as a default recognized form, but you
90    can still use the form with MathJax 3, you just have to add a little more configuration.
91
92    This used to be a supported format for MathJax 2. It appears this form was dropped in MathJax 3. While it is the
93    current default for Arithmatex, it may be relegated to a secondary option in the future. If this output is preferred
94    method, setting `generic` to `#!py False` will prevent any surprises in the future if/when the default changes.
95
96The math equations will be wrapped in a special MathJax script tag and embedded into the HTML. This format does not
97require the `tex2jax.js` extension when setting up MathJax. The tag will be in the form of
98`#!html <script type="math/tex"></script>` for inline and `#!html <script type="math/tex; mode=display"></script>` for
99block.
100
101By default, Arithmatex will also generate a preview span with the class `MathJax_Preview` that can/should be hidden when
102the math content is actually loaded. If you do not want to generate the preview, simply set `preview` to
103`#!py3 False`.
104
105All elements are additionally wrapped in a `#!html <div class="arithmatex"></div>` container by default (`span` if outputting
106inline math).
107
108## Generic Output Format
109
110If [`generic`](#options) is enabled, the extension will escape necessary symbols and normalize all output to be wrapped
111in the more reliable `#!tex \(...\)` for inline math and `#!tex \[...\]` for display math (unless changed via
112`tex_inline_wrap` and `tex_block_wrap` in the [options](#options)). Lastly, everything is inserted into a
113`#!html <span>` or `#!html <div>` for inline and display math respectively.
114
115With the default settings, if in your Markdown you used `#!tex $...$` for inline math, it would be converted to
116`#!html <span class="arithmatex">\(...\)</span>` in the HTML. Blocks would be normalized from `#!tex $$...$$` to
117`#!html <div class="arithmatex">\[...\]</div>`.  In the case of `#!tex \begin{}...\end{}`, begins and ends will not be
118replaced, only wrapped: `#!html <div class="arithmatex">\[\begin{}...\end{}\]</div>`.
119
120## Loading MathJax
121
122Arithmatex requires you to provide the MathJax library and provide and configure it to your liking.  The recommended way
123of including MathJax is to use the CDN. Latest version at time of writing this is found below.
124
125=== "MathJax 3"
126    ```html
127    <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
128    <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
129    ```
130
131=== "Legacy: MathJax 2"
132    ```html
133    <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
134    ```
135
136Generally, it is best to add your own configuration to get exactly what you want. Here we show some simple examples of
137configurations done in JavaScript. We've provided two basic configurations below: one that is configured for
138Arithmatex's [MathJax Output Format](#mathjax-output-format), and one that works with the
139[Generic Output Format](#generic-output-format) by using `tex2jax`. These are a good starting point, so feel free to
140take them and configure them further. Please see the [MathJax][mathjax] site for more info on using MathJax
141extensions/plugins and configuring those extensions/plugins.
142
143As noted below, the non-generic methodology is more complicated in MathJax 3 as they abandoned the approach via wrapping
144math in script tags, but the solution is easily configurable as a simple copy/paste configuration.
145
146=== "Generic - MathJax 3"
147    ```js
148    window.MathJax = {
149      tex: {
150        inlineMath: [ ["\\(","\\)"] ],
151        displayMath: [ ["\\[","\\]"] ],
152        processEscapes: true,
153        processEnvironments: true
154      },
155      options: {
156        ignoreHtmlClass: ".*",
157        processHtmlClass: "arithmatex"
158      }
159    };
160    ```
161
162=== "Script - MathJax 3"
163    ```js
164    window.MathJax = {
165      options: {
166        ignoreHtmlClass: 'tex2jax_ignore',
167        processHtmlClass: 'tex2jax_process',
168        renderActions: {
169          find: [10, function (doc) {
170            for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
171              const display = !!node.type.match(/; *mode=display/);
172              const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
173              const text = document.createTextNode('');
174              const sibling = node.previousElementSibling;
175              node.parentNode.replaceChild(text, node);
176              math.start = {node: text, delim: '', n: 0};
177              math.end = {node: text, delim: '', n: 0};
178              doc.math.push(math);
179              if (sibling && sibling.matches('.MathJax_Preview')) {
180                sibling.parentNode.removeChild(sibling);
181              }
182            }
183          }, '']
184        }
185      }
186    };
187    ```
188
189=== "Legacy: Generic - MathJax 2"
190    ```js
191    MathJax.Hub.Config({
192      config: ["MMLorHTML.js"],
193      extensions: ["tex2jax.js"],
194      jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"],
195      tex2jax: {
196        inlineMath: [ ["\\(","\\)"] ],
197        displayMath: [ ["\\[","\\]"] ],
198        processEscapes: true,
199        processEnvironments: true,
200        ignoreClass: ".*|",
201        processClass: "arithmatex"
202      },
203    });
204    ```
205
206=== "Legacy: Script - MathJax 2"
207    ```js
208    MathJax.Hub.Config({
209      config: ["MMLorHTML.js"],
210      jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"],
211      extensions: ["MathMenu.js", "MathZoom.js"]
212    });
213    ```
214
215Notice that in our generic configuration, we set up `tex2jax` to only load `arithmatex` classes by excluding all
216elements and adding an exception for the `arithmatex` class. We also don't bother adding `#!tex $...$` and
217`#!tex $$...$$` to the `inlineMath` and `displayMath` options as Arithmatex converts them respectively to
218`#!tex \(...\)` and `#!tex \[...\]` in the HTML output (unless altered in [Options](#options)). But we do have to enable
219`processEnvironments` to properly process `#!tex \begin{}...\end{}` blocks.
220
221## Loading KaTeX
222
223In order to use KaTeX, the generic output format is required. You will need to include the KaTeX library:
224
225```html
226<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.js"></script>
227```
228
229And the KaTeX CSS:
230
231```html
232<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.css">
233```
234
235Though KaTeX does have its own auto load script, we want to ensure it *only* loads math content from elements with the
236`arithmatex` class. Below is a script that would do just that. Notice we check for and strip wrappers `#!tex \(...\)`
237and `#!tex \[...\]` off the content of the elements and send it through the renderer. We also don't bother adding
238`#!tex $...$` and `#!tex $$...$$` to the `inlineMath` and `displayMath` options as Arithmatex converts them respectively
239to `#!tex \(...\)` and `#!tex \[...\]` in the HTML output (unless altered in [Options](#options)).
240
241```js
242(function () {
243'use strict';
244
245var katexMath = (function () {
246    var maths = document.querySelectorAll('.arithmatex'),
247        tex;
248
249    for (var i = 0; i < maths.length; i++) {
250      tex = maths[i].textContent || maths[i].innerText;
251      if (tex.startsWith('\\(') && tex.endsWith('\\)')) {
252        katex.render(tex.slice(2, -2), maths[i], {'displayMode': false});
253      } else if (tex.startsWith('\\[') && tex.endsWith('\\]')) {
254        katex.render(tex.slice(2, -2), maths[i], {'displayMode': true});
255      }
256    }
257});
258
259(function () {
260  var onReady = function onReady(fn) {
261    if (document.addEventListener) {
262      document.addEventListener("DOMContentLoaded", fn);
263    } else {
264      document.attachEvent("onreadystatechange", function () {
265        if (document.readyState === "interactive") {
266          fn();
267        }
268      });
269    }
270  };
271
272  onReady(function () {
273    if (typeof katex !== "undefined") {
274      katexMath();
275    }
276  });
277})();
278
279}());
280```
281
282## Alternative Math Blocks
283
284!!! new "New 9.0"
285    Added new formats `arithmatex_inline_format` and `arithmatex_fenced_format`. Both are configurable and effectively
286    replace all other previously available formats.
287
288!!! warning "Deprecated 9.0"
289    The old formatters `inline_mathjax_format`, `inline_mathjax_preview_format`, and `inline_generic_format` have all
290    been deprecated and will be removed at some future time.
291
292    It is advised to use the new `arithmatex_inline_format` which is configurable and will give the same results as the
293    above three.
294
295[InlineHilite](./inlinehilite.md) and [SuperFences](./superfences.md) both have a feature where you can specify your own
296custom inline and fence blocks respectively. Arithmatex provides a number of compatible formats that can be used in
297conjunction with InlineHilite and SuperFences to create an alternative (and possibly more preferable) syntax for math.
298
299In InlineHilite, by simply providing the following configuration (no need to include `pymdownx.arithmatex` as an
300extension), you can create a familiar inline math format:
301
302```py3
303import pymdownx.arithmatex as arithmatex
304
305extensions = [
306    "pymdownx.inlinehilite"
307]
308
309extension_config = {
310    "pymdownx.inlinehilite": {
311        "custom_inline": [
312            {"name": "math", "class": "arithmatex", "format": arithmatex.arithmatex_inline_format(which="generic")}
313        ]
314    }
315}
316```
317
318!!! tip "YAML Configuration Format"
319    If you are attempting to configure these options in a YAML based configuration (like in [MkDocs][mkdocs]), please
320    see the [FAQ](../faq.md#function-references-in-yaml) to see how to specify function references in YAML.
321
322!!! example "Inline Math"
323
324    === "Output"
325        `#!math p(x|y) = \frac{p(y|x)p(x)}{p(y)}`
326
327    === "Markdown"
328        ```
329        `#!math p(x|y) = \frac{p(y|x)p(x)}{p(y)}`
330        ```
331
332
333In SuperFences, by providing the following configuration (no need to include `pymdownx.arithmatex` as an extension), you
334can create math fences:
335
336```py3
337import pymdownx.arithmatex as arithmatex
338
339extensions = [
340    "pymdownx.superfences"
341]
342
343extension_config = {
344    "pymdownx.superfences": {
345        "custom_fences": [
346            {"name": "math", "class": "arithmatex", arithmatex.arithmatex_fenced_format(which="generic")}
347        ]
348    }
349}
350```
351
352!!! example "Math Fences"
353
354    === "Output"
355        ```math
356        \begin{align}
357            p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
358            p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
359        \end{align}
360        ```
361
362    === "Markdown"
363        ````
364        ```math
365        \begin{align}
366            p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
367            p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
368        \end{align}
369        ```
370        ````
371
372Provided formats are found below:
373
374Name                            | Description
375------------------------------- | -----------
376`arithmatex_inline_format`      | Returns a formatter for creating inline math. Generic mode will wrap math in `#!tex \(...\)`.
377`arithmatex_fenced_format`      | Returns a formatter for creating block math. Generic mode will wrap math in `#!tex \[...\]`
378
379Options apply to both formatters:
380
381Name      | Description
382--------- | -----------
383`mode`    | Sets to output mode to either `generic` or `mathjax` (script output). `generic` is the default.
384`tag`     | Sets the tag type of the parent container. By default, it is `div` of fenced blocks and `span` on inline.
385`preview` | Sets whether a preview is generated for `mathjax` mode only.
386
387## Options
388
389Option            | Type     | Default                               | Description
390----------------- | -------- | ------------------------------------- |------------
391`inline_syntax`   | [string] | `#!py3 ['dollar', 'round']`           | Syntax to search for: dollar=`#!tex $...$` and round=`#!tex \(...\)`.
392`block_syntax`    | [string] | `#!py3 ['dollar', 'square', 'begin']` | Syntax to search for: dollar=`#!tex $...$`, square=`#!tex \[...\]`, and `#!tex \begin{}...\end{}`.
393`generic`         | bool     | `#!py3 False`                         | Output in a generic format suitable for non MathJax libraries.
394`tex_inline_wrap` | [string] | `#!py3 ['\\(', '\\)']`                | An array containing the opening and closing portion of the `generic` wrap.
395`tex_block_wrap`  | [string] | `#!py3 ['\\[', '\\]']`                | An array containing the opening and closing portion of the `generic` wrap.
396`smart_dollar`    | bool     | `#!py3 True`                          | Enable Arithmatex's smart dollar logic to minimize math detection issues with `#!tex $`.
397`preview`         | bool     | `#!py3 True`                          | Insert a preview to show until MathJax finishes loading the equations.
398`block_tag`       | string   | `#!py3 'div'`                         | Change the default block tag element wrapper.
399`inline_tag`      | string   | `#!py3 'span'`                        | Change the default inline tag element wrapper.
400