微信公众号文章中可插入的富文本格式不如一般的博客自由,但目前来说也是中文互联网勉强都能接受的一个平台和事实标准了。然而,在撰写理工相关的文章时不免要用到数学公式,微信公众号不支持数学公式的插入和编辑,用图片(位图)代替又比较麻烦,截图、上传,尤其是行间公式排版相当麻烦。
目前来说,最佳的方案是将公式转换为 SVG 图片格式插入。SVG 是矢量图格式,在不同设备上都能清晰显示,而且可以以 DOM 的形式嵌入到富文本中,还有简单而严格安全的交互功能。
但是就目前可查阅到的资料来看,实现这一功能的仅有 ciaochaos 实现的微信公众号公式编辑插件和部分功能收费的 MdNice。笔者在这近一个月的时间里,结合这两年对数学公式排版的研究经验,对功能实现的一些技术难点一一突破,下面简记之,供自己参考。
分析 tex-svg-full.js
MpMath 插件的核心模块是引用的 MathJax 的tex-svg-full.js
文件,这个文件提供了所有数学符号对应的 SVG 数据,均是以 path 绘制的,如
8715:"96 251Q96 268 119 281H363Q607 281 607 283Q607 295 600 319T576 379T519 451T425 507Q386 521 361 523T233 526L119 527Q96 535 96 557Q96 578 116 585Q121 587 229 587Q238 587 257 587T288 588Q366 588 435 568T568 488Q670 388 670 251Q670 155 621 78T499 -39T345 -85Q336 -86 225 -86L119 -85Q96 -77 96 -55Q96 -38 119 -25H233Q356 -24 371 -21Q373 -21 393 -16Q468 3 523 55T599 177Q607 206 607 218Q607 220 363 220L119 221Q96 229 96 251"
MathJax 的大版本互相不兼容,主要的版本是 MathJax 2.x、3.x 以及最新的 4.x,4.x 不再在原有的 Repository 基础上修改,而是另起炉灶为 MathJax-src
Repository。
所以在分析时要分清版本。MathJax 3.x 版本路径如下
https://github.com/mathjax/MathJax/blob/develop/es5/tex-svg-full.js
该文件应该是由 output/svg/fonts/
文件打包而成的。如下 tex.js
文件中就包含了大部分数学符号的 SVG 数据。
https://github.com/mathjax/MathJax/blob/master/es5/output/svg/fonts/tex.js
ciaochaos 的插件中用的 tex-svg-full.js
如下
https://raw.githubusercontent.com/ciaochaos/mpMath/master/mpMath/assets/js/tex-svg-full.js
文件体积还略大于官方的版本,暂不清楚原因。
更多版本的 tex-svg-full.js
如下
https://www.cdnpkg.com/mathjax/file/tex-svg-full.js/?id=53958#
MathJax 2.x 是没有 tex-svg-full.js
的,而是分成各个字体,各字体又分 AMS
、Variant
这些目录,目录中的 javascript
文件中定义一部分符号的 SVG 数据。
但不知道为什么,MathJax 3.0 版本开始后,就不再提供其它数学字体了(包括 STIX 字体),至少在 Repository 中看不到了。因此下面的链接是不存在的。
https://github.com/mathjax/MathJax/tree/master/fonts/HTML-CSS
需要切换 branch 到 MathJax 2.x 的版本,如下
https://github.com/mathjax/MathJax/tree/woff2/jax/output/SVG/fonts/STIX-Web
https://github.com/mathjax/MathJax/tree/v2.6-latest/fonts/HTML-CSS/STIX-Web
需要注意的是,MathJax 2/3 在对数学符号编码时可能有不同之处,可能有的 dict key 用的是十进制数字,有的是十六进制数字,无法直接对应。
GitHub 还有对 MathJax 2.x 的散碎文件整体合并的版本:
https://github.com/hemashushu/mathjax-compact/tree/master/jax/output/SVG/fonts/STIX-Web
https://github.com/pkra/MathJax-single-file/blob/master/dist/TeXSVGSTIX-Web/MathJax.js
MdNice 的实现
MdNice 将 Markdown 转换为适合微信公众号排版的样式,数学公式用的是 MathJax。最后将渲染的 DOM 复制粘贴到微信公众号。
粘贴到公众号
复制时格式必须为 text/html
,所以要借助 JavaScript 实现。
function copyToClip(str) {
function listener(e) {
e.clipboardData.setData("text/html", str);
e.clipboardData.setData("text/plain", str);