Skip to content

Arithmatex

Overview

Arithmatex is an extension that preserves LaTeX math equations during the Markdown conversion process so that they can be used with libraries like MathJax. If you prefer to use something other than MathJax, Arithmatex can output a more generic format suitable for other libraries like KaTeX.

Arithmatex searches for the patterns $...$ and \(...\) for inline math, and $$...$$, \[...\], and \begin{}...\end{} for block math. By default, all formats are enabled, but each format can individually be disabled if desired.

The Arithmatex extension can be included in Python Markdown by using the following:

import markdown
md = markdown.Markdown(extensions=['pymdownx.arithmatex'])

Input Format

By default, smart_dollar mode is enabled for the $...$ inline variant. With smart_dollar it is expected that the opening token ($) is to be followed by a non-whitespace character, and the closing to be preceded by a non-white-space character. This is to help avoid false positives when using the dollar sign in traditional ways such as: I have $2.00 and Bob has $10.00. The previous statement requires no escaping of the $ character. But when needed, the $ character can be escaped using \$. smart_dollar can be disabled and will capture any $...$ whose dollar symbols are not escaped (\$).

Inline
$p(x|y) = \frac{p(y|x)p(x)}{p(y)}$, \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\).

\(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\), \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\).

Inline Configuration

When using MathJax, for best results, it is advised to not use generic mode, and configure MathJax without the text2jax extension since MathJax automatically detects Arithmatex's default output.

If using generic mode (for libraries like KaTeX), Arithmatex will convert dollars to the form \(...\) in the HTML output. This is because $...$ is extremely problematic to scan for, which is why MathJax and KaTeX disable $...$ by default in their plain text scanners, and why Arithmatex enables smart_dollar by default when scanning for $...$.

It is advised that if you are outputting in generic mode that you do not configure your JavaScript library to look for $...$ and instead look for \(...\), and let Arithmatex's handle $...$.

For block forms, the block must start with the appropriate opening for the block type: $$, \[, and \begin{} for the respective search pattern. The block must also end with the proper respective end: $$, \], and \end{}. A block also must contain no empty lines and should be both preceded and followed by an empty line.

Block
$$
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
$$

\[3 < 4\]

\begin{align}
    p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
    p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
\end{align}
\[
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
\]
\[3 < 4\]
\[\begin{align}
    p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
    p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
\end{align}\]

MathJax Output Format

Format Dropped in MathJax 3

The title is a bit misleading. Yes, MathJax 3 dropped supporting the format as a default recognized form, but you can still use the form with MathJax 3, you just have to add a little more configuration.

This used to be a supported format for MathJax 2. It appears this form was dropped in MathJax 3. While it is the current default for Arithmatex, it may be relegated to a secondary option in the future. If this output is preferred method, setting generic to False will prevent any surprises in the future if/when the default changes.

The math equations will be wrapped in a special MathJax script tag and embedded into the HTML. This format does not require the tex2jax.js extension when setting up MathJax. The tag will be in the form of <script type="math/tex"></script> for inline and <script type="math/tex; mode=display"></script> for block.

By default, Arithmatex will also generate a preview span with the class MathJax_Preview that can/should be hidden when the math content is actually loaded. If you do not want to generate the preview, simply set preview to False.

All elements are additionally wrapped in a <div class="arithmatex"></div> container by default (span if outputting inline math).

Generic Output Format

If generic is enabled, the extension will escape necessary symbols and normalize all output to be wrapped in the more reliable \(...\) for inline math and \[...\] for display math (unless changed via tex_inline_wrap and tex_block_wrap in the options). Lastly, everything is inserted into a <span> or <div> for inline and display math respectively.

With the default settings, if in your Markdown you used $...$ for inline math, it would be converted to <span class="arithmatex">\(...\)</span> in the HTML. Blocks would be normalized from $$...$$ to <div class="arithmatex">\[...\]</div>. In the case of \begin{}...\end{}, begins and ends will not be replaced, only wrapped: <div class="arithmatex">\[\begin{}...\end{}\]</div>.

Loading MathJax

Arithmatex requires you to provide the MathJax library and provide and configure it to your liking. The recommended way of including MathJax is to use the CDN. Latest version at time of writing this is found below.

<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>

Generally, it is best to add your own configuration to get exactly what you want. Here we show some simple examples of configurations done in JavaScript. We've provided two basic configurations below: one that is configured for Arithmatex's MathJax Output Format, and one that works with the Generic Output Format by using tex2jax. These are a good starting point, so feel free to take them and configure them further. Please see the MathJax site for more info on using MathJax extensions/plugins and configuring those extensions/plugins.

As noted below, the non-generic methodology is more complicated in MathJax 3 as they abandoned the approach via wrapping math in script tags, but the solution is easily configurable as a simple copy/paste configuration.

window.MathJax = {
  tex: {
    inlineMath: [ ["\\(","\\)"] ],
    displayMath: [ ["\\[","\\]"] ],
    processEscapes: true,
    processEnvironments: true
  },
  options: {
    ignoreHtmlClass: ".*",
    processHtmlClass: "arithmatex"
  }
};
window.MathJax = {
  options: {
    ignoreHtmlClass: 'tex2jax_ignore',
    processHtmlClass: 'tex2jax_process',
    renderActions: {
      find: [10, function (doc) {
        for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
          const display = !!node.type.match(/; *mode=display/);
          const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
          const text = document.createTextNode('');
          const sibling = node.previousElementSibling;
          node.parentNode.replaceChild(text, node);
          math.start = {node: text, delim: '', n: 0};
          math.end = {node: text, delim: '', n: 0};
          doc.math.push(math);
          if (sibling && sibling.matches('.MathJax_Preview')) {
            sibling.parentNode.removeChild(sibling);
          }
        }
      }, '']
    }
  }
};
MathJax.Hub.Config({
  config: ["MMLorHTML.js"],
  extensions: ["tex2jax.js"],
  jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"],
  tex2jax: {
    inlineMath: [ ["\\(","\\)"] ],
    displayMath: [ ["\\[","\\]"] ],
    processEscapes: true,
    processEnvironments: true,
    ignoreClass: ".*|",
    processClass: "arithmatex"
  },
});
MathJax.Hub.Config({
  config: ["MMLorHTML.js"],
  jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"],
  extensions: ["MathMenu.js", "MathZoom.js"]
});

Notice that in our generic configuration, we set up tex2jax to only load arithmatex classes by excluding all elements and adding an exception for the arithmatex class. We also don't bother adding $...$ and $$...$$ to the inlineMath and displayMath options as Arithmatex converts them respectively to \(...\) and \[...\] in the HTML output (unless altered in Options). But we do have to enable processEnvironments to properly process \begin{}...\end{} blocks.

Loading KaTeX

In order to use KaTeX, the generic output format is required. You will need to include the KaTeX library:

<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.js"></script>

And the KaTeX CSS:

<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.css">

Though KaTeX does have its own auto load script, we want to ensure it only loads math content from elements with the arithmatex class. Below is a script that would do just that. Notice we check for and strip wrappers \(...\) and \[...\] off the content of the elements and send it through the renderer. We also don't bother adding $...$ and $$...$$ to the inlineMath and displayMath options as Arithmatex converts them respectively to \(...\) and \[...\] in the HTML output (unless altered in Options).

(function () {
'use strict';

var katexMath = (function () {
    var maths = document.querySelectorAll('.arithmatex'),
        tex;

    for (var i = 0; i < maths.length; i++) {
      tex = maths[i].textContent || maths[i].innerText;
      if (tex.startsWith('\\(') && tex.endsWith('\\)')) {
        katex.render(tex.slice(2, -2), maths[i], {'displayMode': false});
      } else if (tex.startsWith('\\[') && tex.endsWith('\\]')) {
        katex.render(tex.slice(2, -2), maths[i], {'displayMode': true});
      }
    }
});

(function () {
  var onReady = function onReady(fn) {
    if (document.addEventListener) {
      document.addEventListener("DOMContentLoaded", fn);
    } else {
      document.attachEvent("onreadystatechange", function () {
        if (document.readyState === "interactive") {
          fn();
        }
      });
    }
  };

  onReady(function () {
    if (typeof katex !== "undefined") {
      katexMath();
    }
  });
})();

}());

Alternative Math Blocks

New 9.0

Added new formats arithmatex_inline_format and arithmatex_fenced_format. Both are configurable and effectively replace all other previously available formats.

Deprecated 9.0

The old formatters inline_mathjax_format, inline_mathjax_preview_format, and inline_generic_format have all been deprecated and will be removed at some future time.

It is advised to use the new arithmatex_inline_format which is configurable and will give the same results as the above three.

InlineHilite and SuperFences both have a feature where you can specify your own custom inline and fence blocks respectively. Arithmatex provides a number of compatible formats that can be used in conjunction with InlineHilite and SuperFences to create an alternative (and possibly more preferable) syntax for math.

In InlineHilite, by simply providing the following configuration (no need to include pymdownx.arithmatex as an extension), you can create a familiar inline math format:

import pymdownx.arithmatex as arithmatex

extensions = [
    "pymdownx.inlinehilite"
]

extension_config = {
    "pymdownx.inlinehilite": {
        "custom_inline": [
            {"name": "math", "class": "arithmatex", "format": arithmatex.arithmatex_inline_format(which="generic")}
        ]
    }
}

YAML Configuration Format

If you are attempting to configure these options in a YAML based configuration (like in MkDocs), please see the FAQ to see how to specify function references in YAML.

Inline Math
`#!math p(x|y) = \frac{p(y|x)p(x)}{p(y)}`

\(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\)

In SuperFences, by providing the following configuration (no need to include pymdownx.arithmatex as an extension), you can create math fences:

import pymdownx.arithmatex as arithmatex

extensions = [
    "pymdownx.superfences"
]

extension_config = {
    "pymdownx.superfences": {
        "custom_fences": [
            {"name": "math", "class": "arithmatex", arithmatex.arithmatex_fenced_format(which="generic")}
        ]
    }
}
Math Fences
```math
\begin{align}
    p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
    p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
\end{align}
```
\[
\begin{align}
    p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
    p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
\end{align}
\]

Provided formats are found below:

Name Description
arithmatex_inline_format Returns a formatter for creating inline math. Generic mode will wrap math in \(...\).
arithmatex_fenced_format Returns a formatter for creating block math. Generic mode will wrap math in \[...\]

Options apply to both formatters:

Name Description
mode Sets to output mode to either generic or mathjax (script output). generic is the default.
tag Sets the tag type of the parent container. By default, it is div of fenced blocks and span on inline.
preview Sets whether a preview is generated for mathjax mode only.

Options

Option Type Default Description
inline_syntax [string] ['dollar', 'round'] Syntax to search for: dollar=$...$ and round=\(...\).
block_syntax [string] ['dollar', 'square', 'begin'] Syntax to search for: dollar=$...$, square=\[...\], and \begin{}...\end{}.
generic bool False Output in a generic format suitable for non MathJax libraries.
tex_inline_wrap [string] ['\\(', '\\)'] An array containing the opening and closing portion of the generic wrap.
tex_block_wrap [string] ['\\[', '\\]'] An array containing the opening and closing portion of the generic wrap.
smart_dollar bool True Enable Arithmatex's smart dollar logic to minimize math detection issues with $.
preview bool True Insert a preview to show until MathJax finishes loading the equations.
block_tag string 'div' Change the default block tag element wrapper.
inline_tag string 'span' Change the default inline tag element wrapper.