MathJax 是一个 JavaScript 引擎,能够将 LaTeX 语法书写的公式在网页上显示出来,而且效果杠杠的。Markdown 是一种轻量级的标记语言。用 Markdown 书写的文章,可以用 Markdown 解释器处理成标准的 HTML 文档。因此 Markdown 很适合用来写网络日志。
作为数学系毕业的学生,写博客时不可避免地会涉及到一些数学公式。可惜不巧,用 Markdown 写博客的我,在使用 MathJax 的时候遇到了一点麻烦。
在 Markdown 中,下划线 _
被保留,用作标记符号。比如 _Slant_
会生成倾斜的 _Slant_。在 LaTeX 中,下划线 _
被用作下标记号。比如 x_i
会生成 $x_i$
。
由于 Markdown 在 MathJax 之前起作用,有时下标记号会被 Markdown 吃掉,变成 HTML 标记 <i>
而失去 LaTeX 的下标效果,造成数学公式显示不正常。比如 This is an example: $f_i = f_{i + 1}$
里的两个下划线会被 Markdown 理解成倾斜的标记,这就不对了。
分析与思路
问题的本质在于,下划线 _
首先被 Markdown 处理,变成 HTML 标记 <i>
。之后,MathJax 会认为相关代码是不合法的公式代码,不予处理。比如上述例子,在 MathJax 看来会变成这样:This is an example: $f<i>i = f<i>{i + 1}$
——这是什么鬼(MathJax 内心独白)。因此,我们要做的,就是在 Markdown 处理文本的时候,将公式中的下划线保留起来;然后,再让 MathJax 去处理保留下来的下划线。
在 Markdown 中,我们可以用 backtip (`) 来做原样抄写(Verbatim)。也就是说,包含在两个 ` 中间的内容,会被 Markdown 原样保留下来。这正符合我们「保护下划线」的需求。于是,上述例子应该写成 This is an example: `$f_i = f_{i + 1}$`
。
问题看似解决了,不过却又引发了下一个问题。被反引号包括的部分,被 Markdown 当做代码来处理,会加上 HTML 标签 <code>
。这样一来,MathJax 在处理文档时,就会跳过这一部分——虽然下划线被保留了,但是整个公式都被忽略了。
一个妥协的办法,是用 JavaScript 处理所有的 <code>
标签:如果发现 <code>
标签内包含数学公式(以美元符号 $ 开头结尾),那么就剥离标签,并调用 MathJax 处理。
下面我们来实现这一思路。
JavaScript 代码
1 | <script type="text/javascript"> |
或者更简洁的
1 | <script type="text/javascript"> |
这里,我们用正则表达式匹配了 <code>
标签内的美元符号,然后将 <code>
标签替换成 <span class=hpl_mathjax_inline>
标签。
经过这样一番处理,This is an example: `$f_i = f_{i + 1}$`
就可以被正确处理为「This is an example: $f_i = f_{i + 1}$
」了。