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