MathJax常见问题


MathJax常见问题

本文记录了在配置hexo博客和MathJax一起使用的多个问题及解决方法. hexo本身和数学公式的兼容性就不是很好, 所以发生了很多兼容性问题.

MathJax和英文小括号的冲突

如果你即使用了hexo也使用了MathJax, 那么有很大几率你会使用小括号来正常书写文章内容.

譬如:

This text is (in parenthesis) but it doesn’t work.

它会显示成:

This text is $in parenthesis$ but it doesn’t work.

起初, 我一度认为是MathJax的大括号冲突导致了某个地方的小括号也出了同样的渲染问题, 但后来发现问题完全跑偏了. 这个真的卡了我挺长时间的… 很多地方都没有记载过这个问题. 直到我看到了关于MathJax3.0版本的配置问题, 才找到一段额外管理内联公式的script, 那么2.7是不是也应该有相应的一段呢?

blog\themes\hexo-theme-matery\layout\post.ejs中, 有这样一段代码, 是用来调整内联公式的识别方式的. 如果不添加这段js, Mathjax只能识别大的公式, 而不能识别内联公式. 很明显, 这里直接就将转义后的()小括号对也当做公式匹配范围了, 也就不难解释之前错误识别的情况.

<% if (theme.mathjax.enable && page.mathjax) { %>
<script src="<%- theme.mathjax.cdn %>"></script>
<script>
    MathJax.Hub.Config({
        tex2jax: {inlineMath: [['$', '$'],['\(', '\)']]}
    });
</script>
<% } %>

我们只要把['\(', '\)']删去, 或者替换成更严格匹配的括号对['\\(', '\\)'], 就能解决在博客markdown不能正确显示小括号内容的问题.

MathJax和Markdown冲突

Mathjax和Markdown的下划线语法冲了. 比如:
$$
w^{(l)}_{ij} = w^{(l)}_{ij} - \eta\frac{\partial E(W, b)}{\partial w^{(l)}_{ij}}
$$
它大概率会渲染不出来, 变成:

$$

w^{(l)}{ij} = w^{(l)}{ij} - \eta\frac{\partial E(W, b)}{\partial w^{(l)}_{ij}}

$$

这是因为Markdown和Mathjax的语法冲了, 这时候必须要修改blogtest\node_modules\marked\lib\marked.js, 找到var inline, 修改escapeem的正则匹配式:

var inline = {
 escape: /^\\([`*\[\]()#$+\-.!_>])/,
 // ...
 em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, 
 // 去除了下划线_的斜体匹配
 // ...
}

千万不要去装hexo-renderer-kramed! 否则如果你安装了hexo-prism-plugin, 也就是代码显示插件, 那这个代码高亮插件就崩了.

在更换escape的正则后, 一定要避免的出现, 最起码要在其中加上一个空格变成{ {} }, 否则会编译报错.

我尝试过保留 escape中对\\的转义, 这样4个反斜杠才能换行, Typora里写的时候会额外多空出来一行. 我这里在去掉这个\\后, 在公式换行时仍然会莫名其妙有1个反斜杠被转义, 这样需要3个反斜杠才能换行, 在Typora里会导致公式第二行多一个空格(实际渲染以后没有问题), 但比上面多换一行要强.

2020.08.11: 发现3个反斜杠在Typora写表格时使表格无法正确显示.

还有一个很蛋疼的地方, 有些地方不能在公式中使用带有*的字符, 会导致之后的内容变成斜体. 因为去掉了_在公式中的正则, 那就只能通过*来表示斜体. 虽然斜体我几乎不用, 但是星号是表示斜体唯一的方法了, 考虑到这个就没有把斜体的正则匹配也去掉.

2020.08.11: 今天在整理Markdown公式写法的时候, 意外发现了星号可以用\ast代替! 于是这个问题也被解决了.

MiniValine冲突

2020.8.18: 当博客的mathjaxminivaline同时使用时, 会变得很卡. 这是因为minivaline里的math和博客公式显示的mathjax有冲突. 把它关掉就行了.

minivaline:
  enable: true
  # ...
  math: false # Support MathJax.
  # ...

MathJax2迁移到MathJax3

其实MathJax除了上面那些不太兼容的问题(确实有点恶心)来说, 没什么太大的毛病. 但是一旦公式多了就体现出来一个问题, 慢! 现在MathJax已经更新到3.0及以上版本, 官方团队直接把2的代码重写了, 效率提高了60% ~ 80%, 这个速度还是非常诱人的.

There were a number of design goals to the version 3 rewrite. A primary one was to improve the rendering speed of MathJax, and we feel we have accomplished that. Because the two versions operate so differently, it is difficult to make precise comparisons, but in tests that render a complete page with several hundred expressions, we see a reduction in rendering time of between 60 and 80 percent, depending on the browser and type of computer.

更新版本

因为我用的是Matery, 所以自己稍微改了改. 其他主题的更改方法大致相同.

先在主题下的_config.yml文件中, 将之前的mathjax连接的网址更换为最新的. 当然我这里直接采用了保留原来2.7的版本. 除了因为需要旧版本可以随时更换回来, 还有一个原因就是3.0的配置方法与2.7版本的配置方式是不同的, 这就意味着在渲染过程中的代码需要重新写一份, 没有必要把旧版本的内容完全删除.

mathjax:
  enable2: false
  enable3: true
  cdn2: https://cdn.bootcss.com/mathjax/2.7.7/MathJax.js?config=TeX-AMS-MML_HTMLorMML
  cdn3: https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js

然后再去改渲染的脚本blogtest\themes\hexo-theme-matery\layout\post.ejs, 并参考官方文档配置教程, 在末尾更改:

<% if (theme.mathjax.enable2 && page.mathjax) { %>
<script src="<%- theme.mathjax.cdn2 %>"></script>
<script>
    MathJax.Hub.Config({
        tex2jax: { inlineMath: [['$', '$'], ['\\(', '\\)']] } // 行内公式标识
    });
</script>
<% } %>

<% if (theme.mathjax.enable3 && page.mathjax) { %>
<script id="MathJax-script" async src="<%- theme.mathjax.cdn3 %>"></script>
<script>
    MathJax = {
        tex: {
            inlineMath: [['$', '$'], ['\\(', '\\)']]
        }
    };
</script>
<% } %>

这样在需要旧版本时候直接调整enable就行了. 当然你还可以更改其他的配置, 参考教程即可.

无法换行

我换了以后发现一个问题, 多行公式开始变得没法换行了. 我已经排除掉了转义的问题, 确确实实已经有两个反斜杠, 可是公式没法换行.

测试了一会后, 发现无论多少反斜杠都没有办法换行, 我在官方issue找到了答案(有超多人有这个问题). 官方从旧版本迁移过来还没有实现换行符, 官方提到了两种办法来解决这个问题.

  1. 使用\displaylines.

$$
\displaylines{\lim_{N\to\infty}E(p_{max})=N\frac{1}{N}(1-\frac{1}{N})^{N-1} = \frac{(1-\frac{1}{N})^N}{1-\frac{1}{N}} \\
\lim_{N\to \infty}{1-\frac{1}{N}}=1 \qquad\lim_{N\to \infty}({1-\frac{1}{N}})^N=\frac{1}{e} \\
\lim_{N\to \infty}{E(p_{max})}=\frac{1}{e}=37\%}
$$

​ 我当然比较倾向于用这种, 因为我不习惯下面那种编写方式, 在Typora里实在是太麻烦了.

  1. 使用{align}或者{aligned}.

$$
\begin{align}
x’ = \frac{x - x_{median}}{IQR} \\
IQR = x_{q3} - x_{q1}
\end{align}
$$
​ 这种方式当然也有优点, 就是方便公式的对齐, 因为对齐时候必须要在多行公式的环境里面.
$$
\begin{aligned}
E(p)&=Np(1-p)^{N-1} \\
E’(p)&=N(1-p)^{N-1} -Np(1-p)^{N-2} \\
&=N(1-p)^{N-2}((1-p)-p(N-1))\\
E’(p)&=0 \Rightarrow p_{max}=\frac{1}{N}
\end{aligned}
$$
还发现了一些意外小惊喜:

WordPress uses \ as a special character, and it is often stripped out of WordPress posts (depending on what editor you are using). As an escape character, it can prevent the normal action of the character that follows it, so to get an explicit backslash into your post, you need to double it. That is why you need an extra backslash (because the first two equal a single backslash in the output). You probably should double the second one as well, but apparently that is not required.

官方人员提到了WordPress中的类似问题, 我猜hexo第一个反斜杠被转义也是类似的原因.


文章作者: DaNing
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 DaNing !
评论
 上一篇
Hexo+Github Page的博客搭建 Hexo+Github Page的博客搭建
Hexo+Github Page 博客的搭建顺手搭了个博客, 之前一直想整, 但是没整, 感觉还是有个博客好一些, 可以方便自己记载一些东西, 我之前写过一些笔记都可以传上去了, 尤其是存一份云端备份. 平台和框架选择博客框架的选择其实搭建
2020-07-23
下一篇 
计算机网络-学校 计算机网络-学校
本篇后半部分内容产生格式错乱和渲染错误, 是Ipad导出时所产生的格式混乱所致, 现已无法全部修改, 请转看另一篇计网内容. Chapter 1 Computer Networks and the Internet (about 10%
2020-07-22
  目录