## Contents

*Update (2020-11-29)*: Added information for kramdown v2.2 and GitHub Pages v207.

## Writing Math in Markdown

### Jekyll kramdown

Jekyll uses the kramdown converter to compile Markdown into HTML. As part of the conversion process, kramdown looks for “math blocks” that start and end with `$$`

. The double-dollar-sign is the only math block delimiter that kramdown supports. A math block that is both preceded and follwed by a newline is considered “display math.” Any non-display math block is called “inline math.”

There is one caveat: `$$`

-enclosed text that appears between an explicit pair of opening and closing HTML tags in the Markdown file might need special treatment. See the kramdown documentation on `markdown="span"`

and `markdown="block"`

attributes.

The `math_engine`

option in Jekyll’s `_config.yml`

determines what kramdown does with each math block. The following table shows how kramdown converts math blocks in Markdown into HTML with the default `math_engine: mathjax`

option.

Type | Markdown syntax | HTML output (v2.2+) | HTML output (v1 - v2.1) |
---|---|---|---|

display math | `[newline] $$...$$ [newline]` |
`\[...\]` |
`<script type="math/tex; mode=display">...</script>` |

inline math | `[text] $$...$$ [text]` |
`\(...\)` |
`<script type="math/tex">...</script>` |

The HTML output `<script>`

tags used by kramdown v1 through v2.1 are appropriate for MathJax 2.7, which renders them into math notation. However, MathJax 3 no longer uses the `<script>`

tags. This is explained in more detail below.

Another important note is that kramdown treats the `\`

character as an escape character. In order to have `\(`

or `\[`

appear in the generated HTML output, the Markdown file must have `\\(`

or `\\[`

.

### MathJax

MathJax is a JavaScript library that parses HTML documents, identifies math expressions, and renders them in proper math notation. In both versions 2.7 and 3, MathJax looks for certain math delimiters:

The default math delimiters are

`$$...$$`

and`\[...\]`

for displayed mathematics, and`\(...\)`

for in-line mathematics. Note in particular that the`$...$`

in-line delimiters arenotused by default.

*See MathJax 2.7 and 3 documentation*

Note that these delimiters are customizable. See MathJax 2.7 and 3.

In version 2.7, MathJax ran a preprocessor on HTML files that converted math delimiters into `<script>`

tags, similar to the process described for kramdown above. Then, a MathJax “input jax” would translate each `<script>`

tag into the internal MathJax format which is then rendered by an “output jax” based on the output format chosen by the user (e.g., HTML-CSS, SVG, or NativeMML).

However, MathJax 3 changes the paradigm by skipping `<script>`

tags altogether. Instead, it directly parses math delimiters in HTML documents and renders math expressions. As a result, MathJax 3 by default no longer accepts the `<script>`

tags that kramdown (before v2.2) outputs using `math_engine: mathjax`

option. As a workaround, MathJax 3 can also be extended to work with HTML documents that already have `<script>`

tags by adding an action to its `renderActions`

option. The first element in the list corresponding to the `findScript`

key is a number indicating the priority that the action runs. For reference, MathJax 3’s standard parsing is done using the `find`

action with a priority of 10.

```
window.MathJax = {
options: {
renderActions: {
findScript: [9, 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('');
node.parentNode.replaceChild(text, node);
math.start = {node: text, delim: '', n: 0};
math.end = {node: text, delim: '', n: 0};
doc.math.push(math);
}
doc.findMath();
}, '']
}
}
};
```

Other sources

- MathJax 3 in Jekyll and Kramdown: describes the kramdown-MathJax 3 integration problem and proposes a different JavaScript solution to deal with the
`<script>`

tags that kramdown generates.

### GitHub Pages

GitHub Pages currently always sets `math_engine: mathjax`

in `_config.yml`

, overriding any user-specified value (GitHub Help). This is a GitHub Pages limitation, and not a Jekyll limitation. However, there is a possibility that GitHub removes its `math_engine: mathjax`

requirement.

GitHub Pages also sporadically updates the version of kramdown that it uses. As of August 2020, GitHub Pages v207 now uses kramdown version 2.3+.

## Setup

I have described how kramdown, MathJax, and GitHub Pages work individually. Now I describe what it means when these moving pieces all come together.

### November 2020 onwards

Because I am using GitHub Pages to automatically generate my static site, I am stuck with Jekyll’s `math_engine: mathjax`

option in `_config.yml`

. Since GitHub Pages now uses kramdown v2.3, math blocks `$$`

in Markdown are converted to either inline `\(...\)`

or display `\[...\]`

markers. This means that I can directly use Mathjax 3 without resulting to the `findScript`

workaround.

I could have tried to avoid kramdown’s math blocks altogether by switching to single-dollar-sign `$`

delimiters for inline math and using `\[...\]`

delimiters for display math. However, this strategy does not always work because kramdown does not know to treat the math expression as a math block and may instead interpret LaTeX underscores as italics. (This is also why setting `markdown: GFM`

in `_config.yml`

is a bad idea, because GFM does not know to parse math separately from normal Markdown.)

Thus, my current setup is as follows:

**Setup**

- Set
`use_math: true`

in the preamble of the page. Write`$`

for an actual dollar-sign in the page; no need for any escaping.

**Inline Math**: `[text] $$...$$ [text]`

(note the double dollar signs)

- converted by kramdown into
`[text] \(...\) [text]`

in the HTML - MathJax 3 directly parses and renders the HTML as inline math

**Display Math**: `[newline] $$...$$ [newline]`

- converted by kramdown into
`[newline] \[...\] [newline]`

in the HTML - MathJax 3 directly parses and renders the HTML as display math

**Wishful / possible future directions**

- If kramdown supports custom math delimiters for either the
`math_engine: mathjax`

or`math_engine: null`

options, then I could directly use`\[...\]`

and`\(...\)`

delimiters. - If GFM adds support for math blocks, then I could bypass kramdown altogether and specify
`markdown: GFM`

in`_config.yml`

. - Now that kramdown v2.2+ directly outputs LaTeX into the HTML, I may consider using KaTeX instead of MathJax.

### pre-November 2020

Because I am choosing to upgrade to MathJax 3 and I am using GitHub Pages to automatically generate my static site, I am stuck with Jekyll’s `math_engine: mathjax`

option in `_config.yml`

. Therefore, math blocks `$$`

in Markdown are converted to `<script>`

tags, which I parse with MathJax by adding in the `findScript`

action to its set of `renderActions`

.

I could have tried to avoid kramdown’s math blocks altogether by switching to single-dollar-sign `$`

delimiters for inline math and using `\[...\]`

delimiters for display math. However, this strategy does not always work because kramdown does not know to treat the math expression as a math block and may instead interpret LaTeX underscores as italics. Furthermore, I am also holding out for the possibility that GitHub removes its `math_engine: mathjax`

requirement.

Thus, my current setup is as follows:

**Setup**

- Set
`use_math: true`

in the preamble of the page. To write an actual dollar-sign in the page, escape it as`\$`

. Such escaping is only necessary when`use_math: true`

is set in the preamble.

**Inline Math**

*legacy (but current) option*:`[text] $$...$$ [text]`

(note the double dollar signs)- converted by
`kramdown`

into`[text] <script type="math/tex">...</script> [text]`

- MathJax 3 uses the
`findScript`

action in`renderActions`

of the MathJax configuration to identify these script tags

- converted by
*future (hopefully)*:`[text] $...$ [text]`

or`[text] \\(...\\) [text]`

(double-backslash is necessary because`kramdown`

treats`\`

as an escape character)- not converted by
`kramdown`

during`jekyll`

Markdown-to-HTML compilation - rendered directly from LaTeX by MathJax 3 (after enabling
`$`

inline delimiter)

- not converted by

**Display Math**: `[newline] $$...$$ [newline]`

*legacy (but current) option*- converted by
`kramdown`

into`<script type="math/tex; mode=display">...</script>`

- MathJax 3 uses the
`findScript`

action in`renderActions`

of the MathJax configuration to identify these script tags

- converted by
*future (hopefully)*- not converted by
`kramdown`

during`jekyll`

Markdown-to-HTML compilation - rendered directly from LaTeX by MathJax 3

- not converted by

**Known issue**: Because the `findScript`

action is called separately from `find`

, different math expressions are parsed at different times. Suppose the `findScript`

action is called before `find`

, as illustrated in the example above. As a result, if there are new commands or operators (*e.g.*, `\newcommand{\bx}{\mathbf{x}}`

) that are used by a math expression parsed by `findScript`

but defined within an expression parsed by `find`

, then the expression will fail to display properly.