最近又要在博客里写很多数学公式,结果又出现了我都忘了的问题:在数学块(两个 $$
之前)里写换行需要写 \\\\
而非 \
,这个问题让我很不爽。于是我决定彻底弄懂并解决这个问题。
Hexo 默认使用 Marked 渲染 Markdown,而 Marked 本身并不支持数学公式,所以我们写的诸如 $a^2 + b^2 = c^2$
只会被当成普通文本,实际的渲染是在浏览器上通过 MathJax 完成的。由于 Markdown 本身的特性,像 \frac
这样的命令中的 \f
会被翻译成 \
和 f
两个字符,而且只有单词边缘的下划线会被翻译成 <em>
标签1,比如 a _em_ b
这样,而这种写法一般也不会出现,$\mathrm{\LaTeX}$ 写法里下划线一般在单词中间,如 x_i
,所以一切基本可以工作。
但 CommonMark 里规定反斜线转义标点符号得到的是符号本身,比如 \,
相当于 ,
,而 $\mathrm{\LaTeX}$ 里有的反斜线加标点符号组合也是命令,比如 \,
表示一种较窄的间距,其中最常用的是 \\
表示换行,而直接写 \\
会被翻译成单个 \
,所以在公式中需要用 \\\\
来代表 \\
。
这个问题该怎么解决已经有一些方案了2 3。实际上我们可以直接写扩展代码来解决:在 Hexo 的 scripts
目录下增加一个脚本文件,可以命名为 math.js
,然后在其中写入以下代码修改 Marked 的行为:
1 | ; |
这样就把 $$
之间的文本原样输出没有转义了,我们直接写 \\
就可以让 MathJax 正常工作。
还可以使用类似 GitHub 的语法,将 `$a^2 + b^2 = c^2$`
这样的行内代码块渲染为数学公式,避免行内公式中的 Markdown 转义(注意 GitHub 用的语法是 $`a^2 + b^2 = c^2`$
反引号和 $
的顺序是反的):
1 | const default_codespan = renderer.codespan; |
如果需要以 $
开头结尾的行内代码块,可以使用两个反引号,如 ``$demo$``
。
也可以将 math
代码块渲染为数学公式:
1 | const default_code = renderer.code; |
但这样需要关掉 Hexo 内置的代码高亮功能。
未来还需要支持 mermaid 图表,也许需要完全在浏览器端渲染代码高亮?日后再议吧。
脚注功能通过 marked-footnote 实现:
1 | const markedFootnote = require('marked-footnote'); |
2025.02.20 更新:我发现 hexo-util
中提供了 highlight
函数来实现代码高亮,这样就可以在配置中关掉高亮,改为完全在自定义脚本中实现,另外其中也提供了 escapeHTML
转换 HTML 实体,不用自己定义了:
1 | const { escapeHTML, highlight } = require("hexo-util"); |
目前我只需要 gutter
来显示行号,其他配置也可按需开启。
示例代码:
1 | ```math |
效果:
$$\begin{aligned} \frac{1}{2} + \frac{1}{3} &= \frac{5}{6} \\ \frac{1}{2} - \frac{1}{3} &= \frac{1}{6} \end{aligned} $$
稍作修改,也可以使用 mermaid
代码块表示 Mermaid 图表了:
1 | ```mermaid |
效果: