最近学数学比较多,可能会贴一些公式,所以给博客增加了数学公式显示的功能,写篇文章记录一下过程。
2024-04-20 更新:因为简化数学公式的处理,本文的一些观点可能已经过时/页面不能正常显示。
公式的显示借助 MathJax.js 插件(好像没有其它选择,不过它已经非常完善了),它能在几乎所有浏览器上排版出非常漂亮的数学公式。
MathJax 简介
#MathJax 用于在网页中显示公式,支持的公式输入包括:LaTeX、MathML、AsciiMath,公式输出包括:HTML-CSS、SVG、CommonHTML等。
注意:如果采用默认的语法,则只需要引入一个 JavaScript 文件即可。本文后面的内容就不用关心了。
使用方式评估
MathJax 默认是自动排版整个页面的公式,公式也不要求放在 HTML 标签内,这与 LaTex 的方式很像。公式直接混合在文字中,并用 $...$ 或 $$...$$ 或 (...)
括起来。
比如:这是一个 $y=x^2$ 公式(我不支持这种方式,不予显示)。
因为公式没有被放在单独的HTML标签(比如 code)中,这样可能有几个小问题:
- 如果公式包含
<
小于符号,可能会被错误解析。否则可能要写成<
这种形式,比较麻烦 - 由于是直接嵌入在文字中的,解析器可能会遍历整个DOM树的节点来查找公式,找到后进行文本替换,可能稍有性能问题(具体不知道它是怎么处理的)
同时,由于我的博客文章是用 Markdown 写的,公式的插入应该像插入代码片段一样简单,所以我决定把它们放在 ``
中。
比如:
-
行内公式
这是一个
`$y=x^2$`
公式。 -
块公式
这是一个
```$$y=x^2$$```
公式。
这样还有一个好处:避免与代码的插入方式冲突。
注:MathJax 默认不处理 <code></code>
中的数学公式。
这样一来,恰好避免了上面两个小问题。并且,由于 <code></code>
默认是有背景色的(你看到了没?),所以就算没有显示公式,公式也很好和文字区分开来。
具体实施方案
GitHub提交记录:新插件:MathJax,用于显示公式 · movsb/taoblog@25aa3d7
-
像插入代码一样在 Markdown 中插入公式
-
Markdown 编译器把公式编译进
<code></code>
标签中 -
初始化 MathJax 的配置
这里值得一提的是,MathJax 要求我们先在一个
<script type="text/x-mathjax-config"></script>
的标签中写入相关的配置,然后才引入插件,目的是为了减少不必要的资源加载。 我的初始化代码如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<script type="text/x-mathjax-config"> MathJax.Hub.Config({ jax: ["input/TeX", "output/CommonHTML"], extensions: ["tex2jax.js"], tex2jax: { skipTags: [], inlineMath: [['$', '$']], displayMath: [['$$', '$$']], }, skipStartupTypeset: true, //showMathMenu: false, menuSettings: { zoom: 'Click', } }); </script>
从配置可以看出,我只启用了对 LaTeX 的支持,并禁止了自动排版,并设置了单击为公式放大预览。
-
加载脚本文件
我使用了 cloudflare 的 cdn: /mathjax/2.7.4/MathJax.js,目前好像没有被墙。
如果访问速度过慢,还请在评论里面告知一声,非常感谢! -
遍历
<code></code>
并调用MathJax.Hub.Typeset()
手动排版这里有一个问题是:我文章中的代码也是显示在
<code></code>
中的,需要避免。不细说了,具体代码如下:1 2 3 4 5 6 7 8 9 10 11 12 13
MathJax.Hub.Typeset($('<p>$a$</p>').get(0), function(){ console.log('typeset warming-up'); $('code:not([class*="lang"])').each(function(_, e) { var html = $(e).html(); if(html.startsWith('$') && html.endsWith('$')) { var wrap = $(html.startsWith('$$') ? '<div/>' : '<span/>') .css('margin', '3px') .html(html)[0]; MathJax.Hub.Typeset(wrap); console.log('Typeset: ', e); $(e).replaceWith(wrap); } });
公式效果展示
结束语
由于我没有使用默认的自动排版,所以我的使用方式看起来非常复杂。但是,最终效果还是很不错的。
文章并没有提到其它的很多细节问题,如果有什么自定义相关的问题,欢迎一起讨论。
另外,评论中暂时不支持显示公式,但是可以插入。
更新
已经改成服务器渲染,并且替换成了:KaTex + QuickJS。