前言
今日发公众号转载别人的某篇文章。本来是个很简单的活,但文章里有几个公式排版炸了。虽然可以无视,但抱着挑战的心态,我还是试着去修了下。百度,不出所料,基本都是推广,不过还是有一些有用的信息。本着和微信较劲以及绝不注册新账号的精神,我决定尝试手动将LATEX公式转svg。
由于这次修的几个公式比较简单,肯定有不少边界情况没有覆盖到,而且这一套工作流程也暂时没办法流水线化(懒得写脚本),因此本文章称不上是教程。
没有去Github上搜索有没有好心人写的转换脚本,可以去搜搜试试。
过程
- 随便找个网站或者包将LATEX公式转换为SVG。我这里用的是Thomas Lochmatter提供的在线转换器,其声称使用的是MathJAX这个包。不过这一步对后续的影响应该不大。
- 打开转换好的SVG。一般来说这种转换好的SVG里面会包括defs和use两部分。例如下面是$\theta$的转换结果:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<svg xmlns="http://www.w3.org/2000/svg" width="8.488px" height="12.944px" viewBox="0 -705 469 715" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true">
<defs>
<path id="MJX-27-TEX-I-1D703" d="M35 200Q35 302 74 415..."></path>
</defs>
<g stroke="#000000" fill="#000000" stroke-width="0" transform="scale(1,-1)">
<g data-mml-node="math">
<g data-mml-node="mi">
<use data-c="1D703" xlink:href="#MJX-27-TEX-I-1D703"></use>
</g>
</g>
</g>
</svg>
SVG元素里面的各个子元素的具体意思可以去MDN docs上阅读。粗略来说,defs
里面会定义各个符号对应的矢量图,而下面则会通过use
元素来引用这些符号;
但不幸的是,微信的编辑器似乎不允许定义id这个属性(至少在path标签上不允许)。因此,这里我们必须将use节点手动展开。
- 观察
use
元素通过xlink:href
所引用的元素,并将其手动展开。展开过程需要我们对use
元素上的属性进行处理。理论上来说,use
上的data-*
属性应被复制到展开后的元素上,而x
与y
属性(给这个元素一个额外的shift)则可以通过在外层的g
标签上加transform=translation(x,y)
,以变换的形式来实现。这里展开之后应该如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<svg xmlns="http://www.w3.org/2000/svg" width="8.488px" height="12.944px" viewBox="0 -705 469 715" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true">
<g stroke="#000000" fill="#000000" stroke-width="0" transform="scale(1,-1)">
<g data-mml-node="math">
<g data-mml-node="mi">
<path data-c="1D703" d="M35 200Q35 302 74 415..."></path>
</g>
</g>
</g>
</svg>
- 收尾工作。删去部分不需要的属性与元素,如第一行的
<?xml ?>
和xmlns:xlink
属性(不删应该问题也不大);值得注意的是,有的公式转换为SVG时会生成一个<g data-mml-node="TeXAtom" data-mjx-texclass="ORD">
元素,而微信公众号平台很神奇的不知为何会把这个组元素以及之外的所有组全部删掉,导致公式直接变白纸,因此我们需要提前删掉这个元素。由于我不确认这个元素的具体作用(虽然我的场景下删了没事),因此请多加小心。 - 将svg塞进微信图文编辑器。虽然上网一搜应该有不少插件,但我个人这里使用的方法是F12直接编辑前端。一般来说新建一个并塞到里面就足够了。
- 微调工作。塞进去的公式很可能在垂直方向上没有对齐,可以通过在
svg
元素上加内嵌css(具体来说是vertical-align
属性)来控制svg不要飞出去。(这一偏移值应该可以自动生成,但我没有具体研究)。 - 看着舒服了之后点击保存为草稿按钮,看看微信处理过之后公式显示是否仍然正常。如果公式消失,请手动diff微信处理前后的svg源代码。
附言
- 实际上上述大部分过程均可以写个脚本自动化,大概调个beautifulsoup就行,但是明显很耗时间。
- 上述过程很可能没有覆盖到一些边界情况,需要手动修正查错;如果你决定使用这一方案,请确保你对前端有一定了解;
- 不确定
svg
元素放在其他的行间元素(如strong
)里面会不会出问题。 - 一定要确保你粘贴的源代码里面的所有标签都正确关闭了,不然很可能会导致文章其他部分的排版莫名爆炸,只能回滚。