Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easy resolution to underscore issue in MathJax and Markdown?

I know there are already many questions regarding this issue, but I have not found any that specifically answer my question.

I am building a site using Jekyll (AcademicPages). I have several pages full of mathematical expressions, and the underscores are behaving badly due to the interaction between Markdown and Jekyll.

I am aware that this can be (partially) resolved by escaping the underscores, but I cannot do this for the entire page.

An example can be seen on my testing site here. Here is the markdown file for that page:

---
title: "Testing"
collection: archive
type: "Type"
permalink: /testing
excerpt: ""
---

Main paragraph underscore $\operatorname{ext}_\in(X) = \operatorname{ext}_\in(\emptyset)$.
<ol>
<li>Item underscores $\operatorname{ext}_\in(X) = \operatorname{ext}_\in(\emptyset)$.</li>
</ol>
    
$$
\operatorname{ext}_\in(X) = \operatorname{ext}_\in(\emptyset)
$$


Main paragraph underscore $\operatorname{ext}\_\in(X) = \operatorname{ext}\_\in(\emptyset)$.
<ol>
<li>Item underscores $\operatorname{ext}\_\in(X) = \operatorname{ext}\_\in(\emptyset)$.</li>
</ol>
    
$$
\operatorname{ext}\_\in(X) = \operatorname{ext}\_\in(\emptyset)
$$

The first half of the page uses _ while the second half of the page uses \_.

  • In the first half of the page, the underscores in the main paragraph are badly rendered.
  • In the second half the underscores in the list element and math environment are badly rendered.

As my pages are much longer than my testing page, I wish to know if there is an easy way to resolve this problem without having to manually escape the underscores at parts of the page where it is badly rendered.

A few things I have tried but did not work:

  1. Putting {% raw %} and {% endraw %} at the start and end of the body respectively. There were no changes to the page.

  2. Putting <span> and </span> around all expressions of the form $...$. It fixes the formatting around the text, but the underscore still disappears from the math expression.

  3. Putting <div> and </div> around all expressions of the form $...$. It does nothing.

like image 873
Clement Yung Avatar asked Oct 21 '25 07:10

Clement Yung


2 Answers

I'm also trying to find a way to solve this problem, but unfortunately with no perfect solution until now. A not-so-perfect way is putting {::nomarkdown} and {:/} around all mathematics expressions. But I don't think this is a real solution for people dealing with math all day like me, and I'm looking forward to a perfect solution.

like image 136
Bao Avatar answered Oct 23 '25 22:10

Bao


I see that you are using MathJax v2.7.4, so you may want to update to version 2.7.9, which is the highest v2 release (the latest.js from that version no longer works properly, I'm afraid, so you get the 2.7.4 version). it would be even better to update to version 3, if you can.

Here is a configuration that would allow you to use `$...$` and `$$...$$` to delimit in-line and displayed math (note the back-ticks around the dollar signs).

<script type="text/x-mathjax-config">
MathJax.Hub.Config({
  tex2jax: {
    skipTags: ["script","noscript","style","textarea"],
    inlineMath: [['$', '$'], ['`$', '$`'], ['\\(', '\\)']],
    displayMath: [['$$', '$$'], ['`$$', '$$`'], ['\\[', '\\]']]
  }
});
MathJax.Hub.Register.LoadHook("[MathJax]/extensions/tex2jax.js", function () {
  var TEX2JAX = MathJax.Extension.tex2jax;
  TEX2JAX._createMathTag = TEX2JAX.createMathTag;
  TEX2JAX.createMathTag = function (mode, tex) {
    const math = this._createMathTag(mode, tex);
    const code = math.parentNode;
    if (code.nodeName === 'CODE' && code.childNodes.length <= 3) {
      const span = document.createElement('mjx-span');
      code.parentNode.replaceChild(span, code);
      span.appendChild(math);
    }
    return math;
  };
});
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS_CHTML" defer></script>

It handles removing the <code> tags that I mentioned, and also gets MathJax from a different CDN where you can request the highest version 2 release more easily.

I'm not sure how you need to configure Jekyll for this, but you should be able to provide a custom configuration, and may be able to replace the actual URL to use for MathJax, so should be able to integrate this into your site.

If you want to use version 3, here is the corresponding configuration:

<script>
MathJax = {
  removeCode(math, doc) {
    const code = math.start.node.parentNode;
    if (code.nodeName === 'CODE' && code.childNodes.length === 1) {
      const span = document.createElement('mjx-span');
      code.parentNode.replaceChild(span, code);
      span.appendChild(code.firstChild);
    }
  },
  options: {
    skipHtmlTags: {'[-]': ['code', 'pre']},
    renderActions: {
      removeCode: [
        11,
        (doc) => {for (const math of MathJax.startup.document.math) MathJax.config.removeCode(math, doc)},
        (math, doc) => MathJax.config.removeCode(math, doc),
        false
      ]
    }
  },
  tex: {
    inlineMath: [['$', '$'], ['`$', '$`'], ['\\(', '\\)']],
    displayMath: [['$$', '$$'], ['`$$', '$$`'], ['\\[', '\\]']]
  }
};
</script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js" defer id="MathJax-script"></script>

So your test page (with either of these configurations) would look like

Main paragraph underscore `$\operatorname{ext}_\in(X) = \operatorname{ext}_\in(\emptyset)$`.
<ol>
<li>Item underscores `$\operatorname{ext}_\in(X) = \operatorname{ext}_\in(\emptyset)$`.</li>
</ol>
like image 22
Davide Cervone Avatar answered Oct 23 '25 20:10

Davide Cervone



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!