Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latex Array is not rendering on website, but works locally. #2377

Closed
mateuszdorobek opened this issue Mar 22, 2020 · 24 comments
Closed

Latex Array is not rendering on website, but works locally. #2377

mateuszdorobek opened this issue Mar 22, 2020 · 24 comments
Labels
Expected Behavior This is how MathJax works

Comments

@mateuszdorobek
Copy link

Issue Summary

I'm trying to write Latex array using MathJax, it works fine locally when I render it with bundle exec jekyll liveserve but when I push it to my GitHub pages repo it doesn't render. Simple equations work on the website, but I have a problem with arrays.

Steps to Reproduce:

$$
  \left(\begin{array}{lll}
  {a} & {b} & {c} \\
  {0} & {d} & {e} \\
  {0} & {0} & {f}
  \end{array}\right)
$$

Technical details:

  • MathJax Version: >3
  • Client OS: Win 10 64
  • Browser: Chrome

Supporting information:

My config files:
\includes\_lib\mathjax.html

<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script type="text/javascript" id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>

\asserts\js\MathJaxLocal.js

MathJax.Hub.Config({
  jax: ["input/TeX", "output/HTML-CSS"],
  tex2jax: {
    inlineMath: [['$', '$'], ["\\(","\\)"]],
    displayMath: [['$$', '$$'],['\\[','\\]']],
    processEscapes: true,
    skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
  },
  messageStyle: "none",
  "HTML-CSS": { preferredFont: "TeX", availableFonts: ["STIX","TeX"] },
  TeX: {
    equationNumbers: { autoNumber: "all" },
    extensions: ["AMSmath.js", "AMSsymbols.js","AMScd.js"],
    TagSide: "left",
    Macros: {
      field: ['\\mathbb{#1}', 1],
      C: ['\\field{C}'],
      F: ['\\field{F}'],
      N: ['\\field{N}'],
      Q: ['\\field{Q}'],
      R: ['\\field{R}'],
      Z: ['\\field{Z}'],

      zeros: ['\\mathbf{0}'],
      ud: ['\\,\\mathrm{d}'],

      vect:['\\boldsymbol{\\mathbf{#1}}',1],
      abs: ['\\lvert#1\\rvert', 1],
      abslr:['\\left\\lvert#1\\right\\rvert', 1],
      norm: ['\\lVert#1\\rVert', 1],
      normlr: ['\\left\\lVert#1\\right\\rVert', 1],

      lcm: ['\\mathop{\\mathrm{lcm}}'],
      interior: ['\\mathop{\\mathrm{int}}'],
      exterior: ['\\mathop{\\mathrm{ext}}'],
      volume: ['\\mathop{\\mathrm{vol}}'],

      E: ['{\\rm I\\kern-.3em E}'],
      Var: ['\\mathop{\\mathrm{Var}}'],
      Cov: ['\\mathop{\\mathrm{Cov}}'],
      Binom: ['\\mathop{\\mathrm{Binom}}'],
      Exp: ['\\mathop{\\mathrm{Exp}}'],
      Poi: ['\\mathop{\\mathrm{Poi}}'],

      GL: ['\\mathrm{GL}'],
      SL: ['\\mathrm{SL}'],
      Aut: ['\\mathrm{Aut}'],
      ker: ['\\mathrm{ker}'],
      id: ['\\mathop{\\mathrm{id}}'],

      Re: ['\\mathop{\\mathrm{Re}}'],
      Im: ['\\mathop{\\mathrm{Im}}'],
      Res: ['\\mathop{\\mathrm{Res}}'],
    }
  }
});

MathJax.Ajax.loadComplete("https://idcrook.github.io/assets/js/MathJaxLocal.js");

mahjax

image

My web Page: https://www.mateuszdorobek.pl/posts/2020/03/Numerical-linear-algebra-notes

@dpvc
Copy link
Member

dpvc commented Mar 23, 2020

That main problem is that the newlines have been stripped out of the page when it is being served at the https://www.mateuszdorobek.pl site. If you look at the two source windows in your images, the live site has no line breaks, while the local one does.

The reason this matters is because jekyll (I think) is preprocessing the math on the page to insert MathJax v2-style <script type="math/tex"> tags that contain the math to be processed by MathJax. While doing so, it inserts % <![CDATA[ before the math and %]]> after it. (These are unnecessary today, but where needed in some situations in the past.) Because these start with %, MathJax will consider the rest of the line to be a comment, and ignore the <![CDATA[ and ]]>, leaving only your original math to be processed. But when the server removes the line breaks, that means the initial % makes the entire expression into a comment, and so you get no math content, and only the automatic equation number.

So you either need to tell your server not to remove newlines, or tell Jekyll not to insert the CDATA comments in order to resolve the problem. I don't know how to do either of those, but perhaps you can figure that out.

Alternatively, you could install a TeX input filter to remove the CDATA comments before MathJax processes them. Something like

<script type="text/x-mathjax-config">
MathJax.Hub.Register.StartupHook('TeX Jax Ready', function () {
  MathJax.InputJax.TeX.prefilterHooks.Add(function (data) {
    data.math = data.math.replace(/^% <!\[CDATA\[/, '').replace(/%\]\]>$/, '');
  });
});
</script>

used before the script that loads MathJax's latest.js file would do it. But I suspect that the configuration script and the loading of latest.js is not something you have access to, so that might not work.

Note, that you are not using MathJax v3 but rather MathJax v2.7.4 (see the press release for v2.7.6 for why you are not getting the latest version of mathJax any longer). You actually are loading both v2 and v3 (not very efficient), but because the page has v2-style <script> tags that MathJax v3 doesn't recognize by default (see issue #2220 for how to handle that in v3), mathJax v3 runs but finds no math. Version 3 seems to be loading first, then v2 loads and replaces the v3 MathJax variable with the v2 version (check the About MathJax item in the MathJax contextual menu to see). It may be that sometimes v3 will load slower and v2 will be replaced, but I haven't seen that happen.

In any case, you don't want to load both. Also, your v2 configuration will not work with v3, as it has a different means of configuration. There is a configuration converter that can help you convert your old configuration to v3 form. But again, you might not have access to that, as Jekyll is probably putting that in place for you. So you might need to get an updated version of whatever plugin you are using to include MathJax in Jekyll output. I don't know if there is a v3 one or not; you'll have to look.

@dpvc dpvc added the Expected Behavior This is how MathJax works label Mar 23, 2020
@mateuszdorobek
Copy link
Author

Thank you for such a detailed answer.

... tell your server not to remove newlines, or tell Jekyll not to insert the CDATA comments ...

I'm hosting it on github pages, so I have no control over the server.

... the initial % makes the entire expression into a comment ...

Wow

... install a TeX input filter to remove the CDATA comments before MathJax processes them

I've done so and this FIXED THE PROBLEM for me.

... Version 3 seems to be loading first, then v2 loads and replaces the v3 MathJax variable with the v2 version

Yeah you're right, I thought that is another .js file.

This Is my _includes\lib\mathjax.html:

<script type="text/x-mathjax-config">
MathJax.Hub.Register.StartupHook('TeX Jax Ready', function () {
  MathJax.InputJax.TeX.prefilterHooks.Add(function (data) {
    data.math = data.math.replace(/^% <!\[CDATA\[/, '').replace(/%\]\]>$/, '');
  });
});
</script>
<script type="text/javascript" id="MathJax-script" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/latest.js"></script>

My page looks OK now. Thank you very much. That was really sick error, but your preprocessing code did the job, thank you again ;)

image

@dpvc
Copy link
Member

dpvc commented Mar 23, 2020

Glad you were able to get it to work. Thanks for letting us know.

@aseemrb
Copy link

aseemrb commented May 22, 2020

<script type="text/x-mathjax-config">
MathJax.Hub.Register.StartupHook('TeX Jax Ready', function () {
  MathJax.InputJax.TeX.prefilterHooks.Add(function (data) {
    data.math = data.math.replace(/^% <!\[CDATA\[/, '').replace(/%\]\]>$/, '');
  });
});
</script>

Great answer, thanks, this tells me exactly what the problem is!
I'm stuck with the same problem, however, this code does not work for v3 as StartupHook has been replaced by ready() if I understood correctly from the docs.

I can't seem to figure out how to access "data.math" inside ready(). There doesn't seem to be any InputJax.TeX.prefilterHooks arrangement either. Any help would be great.

@dpvc
Copy link
Member

dpvc commented May 22, 2020

For v3 it is a little more complicated, since the comment strings are removed before the TeX input jax runs, so a pre-filter doesn't work in that case. So you have to modify the code that collects the DOM strings to make sure the CDATA comments are included. Here is one possible solution:

<script>
MathJax = {
  startup: {
    ready: function() {
      var HTMLDomStrings = MathJax._.handlers.html.HTMLDomStrings.HTMLDomStrings;
      var handleTag = HTMLDomStrings.prototype.handleTag;
      HTMLDomStrings.prototype.handleTag = function (node, ignore) {
        if (this.adaptor.kind(node) === '#comment') {
          var text = this.adaptor.textContent(node);
          if (text.match(/^\[CDATA\[(?:\n|.)*\]\]$/)) {
            this.string += '<!'
            this.extendString(node, text);
            this.string += '>';
            return this.adaptor.next(node);
          }
        }
        return handleTag.call(this, node, ignore);
      }
      MathJax.startup.defaultReady();
      MathJax.startup.document.inputJax[0].preFilters.add(function (data) {
        data.math.math = data.math.math.replace(/^% <!\[CDATA\[/, '').replace(/%\]\]>$/, '');
      });
    }
  }
};
</script>

This should come before the script that loads the MathJax component you are using, and if you already have other configuration, it needs to me merged into that.

@dpvc
Copy link
Member

dpvc commented May 26, 2020

@aseemrb, did you get this to work? I got a notification of a post from you, but it seems to have been deleted.

@aseemrb
Copy link

aseemrb commented May 29, 2020

@dpvc sorry for the late response, the snippet you provided didn't work; but I ended up with the following, which works:

<script>
document.addEventListener('DOMContentLoaded', function(){
  function stripcdata(x) {
    if (x.startsWith('% <![CDATA[') && x.endsWith('%]]>'))
      return x.substring(11,x.length-4);
    return x;
  }
  document.querySelectorAll("script[type='math/tex']").forEach(function(el){
    el.outerHTML = "\\(" + stripcdata(el.textContent) + "\\)";
  });
  document.querySelectorAll("script[type='math/tex; mode=display']").forEach(function(el){
    el.outerHTML = "\\[" + stripcdata(el.textContent) + "\\]";
  });
}, false);
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();
      }, '']
    }
  }
};
</script>

Here the latter half comes from the official documentation, while in the first half I'm simply stripping the dom content of all % <![CDATA[ ... %]] strings.

I see that github needs to allow math_engine: nil in Jekyll’s _config.yml for Kramdown settings. This is currently an open issue. Once that is solved, we won't need this fix I believe :)

@dpvc
Copy link
Member

dpvc commented May 29, 2020

OK, thanks for sharing your solution. I suspect you don't need to the findScript render action any longer, since your event listener will replace all the old MathJax scripts with regular delimiters, so there won't be any left for that render action to find.

@moribots
Copy link

moribots commented Sep 12, 2020

Hi, I've tried both of the presented solutions but neither has worked. I am using V2 and I noticed that OP's website is not rendering the maths, so I'm assuming that solution may be outdated.

Website: https://moribots.github.io/project/ekfslam

Here is my mathjax.html

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    TeX: {
      equationNumbers: {
        autoNumber: "AMS"
      }
    },
    tex2jax: {
      inlineMath: [ ['$','$'] ],
      displayMath: [ ['$$','$$'] ],
      processEscapes: true,
    }
  });
</script>

<script type="text/javascript" async
  src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML">
</script>

<script type="text/javascript">
  MathJax.Hub.Queue(
    ["resetEquationNumbers",MathJax.InputJax.TeX],
    ["Typeset",MathJax.Hub]
  );
</script>

The last script is for mathjax to render any math that was missed in the first pass since I'm using a dynamic jekyll site.

@dpvc
Copy link
Member

dpvc commented Sep 12, 2020

@moribots, you are using \[...\] delimiters around the displayed math containing the arrays, bit have removed those delimiters from the displayMath list of delimiters. So they are ignored by MathJax, and you end up getting the \begin{array}...\end{array} ending up as math delimiters because \begin{...}...\end{...} are taken as math delimiters when preocessEnvironments is true (which it is by default).

Try using

displayMath: [ ['$$','$$'], '[\\[','\\]'] ],

od use '$$...$$' around your displayed equations instead of '[...]'.

@moribots
Copy link

Thanks for the quick response!

Here is an example of an array I use, delimited by $$ ... $$

$$ A_{1b} = \left[\begin{array}{ccc} 1 & 0 & 0 \\ -D & 1 & 0 \\ 0 & 0 & 1 \end{array} \right] $$

If I understood correctly I think this fits your description of what should be working.

@dpvc
Copy link
Member

dpvc commented Sep 12, 2020

@moribots, the arrays on the link you provided above are not delimited by $$ but by \[...\]. That is why they are not working. I do not see any on that page that use $$ delimiters. Is that on a different page? If so, can you provide a link to it?

The issue on the page for which you provided a link is the inconsistency between the configured delimiters ($$...$$) and the ones used in the page (\[...\]).

@moribots
Copy link

moribots commented Sep 12, 2020

I just noticed something odd based on your comment:

image

This array delimited as you described by \[...\] on the live site is actually written as $$ A_{1b} = \left[\begin{array}{ccc} 1 & 0 & 0 \\ -D & 1 & 0 \\ 0 & 0 & 1 \end{array} \right] $$ in my code. Do you have any idea how this could have happened?

For reference, it looks like this offline:

image

Edit: I also tried adding changing the display config as you suggested but this did not change the live site. However, now the offline build is also unrendered.

Thanks again, I hope I've given you enough information.

@dpvc
Copy link
Member

dpvc commented Sep 12, 2020

@moribots, whatever content management system you are using to create your pages (Jekyll?) is probably identifying the math (so that it doesn't further process the math itself) and inserting it into the page after creating the HTML needed for it. It may change the delimiters to the standard LaTeX ones in that process.

So your solution is to change the configuration as I suggested above so that it will work both with your original delimiters and the ones that Jekyll uses.

@moribots
Copy link

Thanks! When I tried to add the backslash delimiter option it actually stopped rendering all of the maths instead of just the arrays like before. Does that give you any clues?

Yes I am using Jekyll

@dpvc
Copy link
Member

dpvc commented Sep 12, 2020

That suggests that you made a syntax error in your configuration and MathJax couldn't process it. Were there any errors in your browser console window?

@moribots
Copy link

When I run bundle exec jekyll serve I get no errors.
This is my whole config:

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      displayMath: [ ['$$','$$'] ],
      processEscapes: true,
      skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
    }
  });
</script>

<script type="text/javascript" async
  src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML">
</script>

<script type="text/javascript">
  MathJax.Hub.Queue(
    ["resetEquationNumbers",MathJax.InputJax.TeX],
    ["Typeset",MathJax.Hub]
  );
</script>

I hope that helps.

@dpvc
Copy link
Member

dpvc commented Sep 15, 2020 via email

@moribots
Copy link

moribots commented Sep 16, 2020

Thanks for the detailed response! I've gotten rid of the last script.

If I include displayMath: [ ['$$','$$'], '[\\[','\\]'] ], , none of my maths renders locally anymore.

On the live site, nothing has changed.

@dpvc
Copy link
Member

dpvc commented Sep 16, 2020

If I include displayMath: [ ['$$','$$'], '[\\[','\\]'] ], , none of my maths renders locally anymore.

you have the quotation marks in the wrong place. Try

displayMath: [ ['$$','$$'], ['\\[','\\]'] ],

instead. Your way, the configuration failed to be processed, and so MathJax couldn't run. You should probably see an error message in the browser console.

@moribots
Copy link

Thank you so much, that was it!

@lhoangan
Copy link

lhoangan commented Sep 19, 2020

I come across this thread while struggling finding a solution to why all of the line break delimiter // get converted to <br/>. The same code works locally. So I guess it's from the server side. I've tried with the following code, but it doesn't seem to work.

The website is at https://lhoangan.github.io/camera-params/, Equation (3)

<script type="text/x-mathjax-config">
MathJax.Hub.Register.StartupHook('TeX Jax Ready', function () {
      MathJax.InputJax.TeX.prefilterHooks.Add(function (data) {
        data.math = data.math.replace('<br/>', '\\');
      });
    });
</script>
</script>                                                                   
<script type="text/javascript" async                                        
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML">
</script>

@dpvc
Copy link
Member

dpvc commented Sep 19, 2020

@lhoangan, Equation 3 renders properly for me in the page you link to. Does that link not work for you?

Also note that v2.7.1 of MathJax is three and a half years old, so you may want to update to a more recent version. The highest version of 2.x is 2.7.9.

@lhoangan
Copy link

lhoangan commented Sep 20, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Expected Behavior This is how MathJax works
Projects
None yet
Development

No branches or pull requests

5 participants