前段时间帮某单位做信创站点的知识库迁移,技术文档里那一堆数学公式,差点把整个上线计划拖垮。编辑日常用Word排版的公式,传到WordPress后台之后,有的变成一串XML标签,有的变成一行乱码,还有的直接消失或者显示成红叉。处理Word公式的格式兼容问题,在信创环境下比普通服务器环境要难得多,因为从作者电脑到服务器、从浏览器到编辑器,每一环都可能出幺蛾子。
这篇文章不打算写教科书式的原理,就按我实际排查和落地的顺序,把这套“Word公式迁到WordPress”的流程完整讲一遍,包括中间试过的方案、死活避不开的坑,以及最后跑通的一套组合做法。内容比较多,建议先收藏再慢慢看。
1. 问题复盘:公式在信创环境里到底“死”在哪一步
1.1 Word公式在文档内部的三副面孔
很多人以为Word公式就是一个“东西”,复制粘贴就能带走。实际上Word文档里的公式有完全不同的三种载体,它们在脱离Word环境后的命运截然不同。
第一种是OMML。这是Word 2007之后原生公式的存储格式,在docx文件里表现为<m:oMath>这样的XML节点。你直接在Word里用“插入→公式”写出来的公式,默认就是这种格式。它有一个特点:虽然能被Word完美编辑,但除了Word和少数几个Office生态内的软件,几乎没有任何网页编辑器能直接解析它。WordPress的经典编辑器遇到OMML内容,通常直接当作未知标签丢掉或露出一堆代码。
第二种是OLE对象。早年很多技术文档里的公式是用第三方公式编辑器插入的,本质是一个嵌入Word文档的二进制对象,docx里对应<m:oMath之外还有一个OLE关系。这类公式在Windows版Word里双击能调起编辑器修改,但是一旦文档被放到Linux服务器上,或者用信创终端里的国产办公软件打开,这个OLE对象基本就等于废了。网页端更不可能渲染它。
第三种是图片或渲染结果。把Word文档另存为网页(HTML)时,Word会默认把公式转成图片;某些版本会输出VML格式的矢量图,某些版本输出PNG位图。在旧系统、旧文档里,“公式”其实已经变成了“图片”。这种形式在网页端能显示,但无法编辑,放大就糊,而且公式的语义信息彻底丢了,后续想改一个符号都得回到原文档重新导出。
换句话说,你在Word界面里看到的所有公式,一旦离开Word环境,就会因为底层的这三种载体而表现完全不同的命运。这也是为什么同样一份文档,有人粘贴到WordPress后公式还在,有人粘贴后直接变成乱码——大概率是文档里公式的底层载体不一样。
1.2 信创环境下多出来的四个不稳定变量
如果只是在普通Windows服务器上跑WordPress,公式问题相对好办一些。但信创环境把问题放大了,我从四个维度说。
终端侧。做信创迁移后,内容编辑的办公电脑不再是传统的Windows+Word组合,而是国产操作系统加上国产办公套件。这些办公套件对OMML和OLE对象的解析兼容性参差不齐。同一份docx,用原版Word打开能正常显示公式,用信创办公软件打开可能变成图片、可能显示为“域代码”、甚至直接空白。这就导致“编辑在本地看到的公式效果”和“上传到WordPress之后的效果”之间多了一层不确定性。
浏览器侧。信创终端上默认浏览器多为国产双核浏览器,极速模式走Chromium内核、兼容模式走IE式内核。不同内核、不同模式对MathML原生支持的差异非常大。以前很多站点靠浏览器插件或者ActiveX控件渲染公式的方案,在信创浏览器里直接失效。对公式渲染来说,唯一的出路是走纯JavaScript方案,让所有浏览器用同一套渲染引擎。
服务器侧。如果服务器也换成了国产CPU平台的操作系统,PHP扩展、字体库、图像处理库的安装路径都和x86环境有差异。比如Pandoc这类文档转换工具依赖字体和系统库,信创服务器上不预装,需要手动部署。又比如GD库缺了某些字体,Word文档转出来的图片公式会缺字符。这些底层差异平时没人注意,真处理公式迁移时就暴露了。
数据库侧。不少信创项目把数据库也从传统商业数据库换成了兼容MySQL协议的国产数据库。大部分SQL语句没问题,但在特殊字符处理上偶尔有差异。Word文档里的数学字符(比如Unicode数学字母、上下标字符)经过数据库存储再被读取,如果字符集不是utf8mb4,很容易入库后变成问号。公式里的特殊符号一旦在数据层被篡改,前端怎么渲染都白搭。
把这一层盘清楚,后面选方案和排错就会有的放矢。公式兼容问题不是单一的“前端渲染问题”,而是从文档到数据库、从编辑器到浏览器的全链路问题。
2. 方案对比:三条路线怎么选
2.1 离线转换为主:把公式还原成LaTeX源码
我最终落地的主方案是“离线转换为主”,核心思路非常朴素:不要在Word环境和网页环境之间做一对一映射,而是把公式统一转换成网页生态通用的中间格式,最通用、也最没争议的就是LaTeX源码。
什么叫LaTeX源码?一个公式在Word里显示成复杂的分数、根号、上下标,在LaTeX里就是一行文本,比如x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}。这一行文本是纯文本,任何数据库、任何编辑器都不会弄丢它。显示的时候,前端用一个叫MathJax的JavaScript库读这行文本,实时把它渲染成看得懂的数学公式。
这条路线的优势很明显:格式稳定、不依赖作者用什么办公软件、不依赖浏览器是否支持MathML、不依赖服务器装了哪些控件。它对信创环境最友好,因为整个链路里没有任何一处绑死某个厂商的私有格式。
缺点也有:存量Word文档不能丢进去就自动完成,需要走一遍“转换→校对→发布”的流程。但只要做一次流程设计,后面就是批量执行的问题了。我自己的经验是,一份几十页的文档,转换加校对大概几十分钟,比人工一个个截图重传要快得多。
2.2 在线公式编辑器:适合新内容,管不了存量
另一条路线是在WordPress后台直接装一个支持公式的编辑器,让编辑在网页里可视化输入公式。现在的方案一般有两种:一种是所见即所得的可视化公式编辑器,按一下按钮选模板;另一种是输入LaTeX源码,配合实时预览。
这条路线对“新写的内容”非常友好,编辑不需要再打开Word,直接在后台写完文字顺便输公式,格式天然就是网页能渲染的。但问题在于它管不了存量文档——你不可能让编辑把过去几千篇技术文档里的公式全部重新录入一遍。另外,在线公式编辑器本身也有信创兼容问题,某些可视化编辑器依赖Flash或者旧式浏览器插件,在信创终端上打开就白屏。所以它只能作为补充,不能作为主方案。
2.3 插件自动转换:看着省事,坑也不少
第三种路线是装一个支持“Word文档直接导入WordPress”的插件,编辑把docx整个传到后台,插件解析文档并自动把公式转成图片或LaTeX。听起来很美好,实际试下来问题不少。
首先是转换质量不稳定。插件解析docx时,对OMML的转换程度深浅不一。结构简单的公式(比如单个上下标)没问题,复杂一点的矩阵、多行公式、带花括号的分段函数,经常转出缺胳膊少腿的结果。其次是服务器依赖。这类插件通常需要服务器端安装文档解析工具,信创服务器上环境不标准,经常遇到“插件明明装了,上传文档却报错”的情况。最后是上传限制,WordPress默认的上传大小上限一般只有2MB,而技术文档带一堆公式图片,动辄几十MB,还得额外调nginx、php配置。
所以我的判断是:插件自动转换适合“少量文档快速上线”的场景,不适合作为批量迁移的基座。真正靠谱的做法还是要走离线转换,把格式控制在自己手里。
2.4 一张表把三条路线摊开讲
| 方案 | 适用场景 | 转换质量 | 人工干预量 | 信创兼容性 |
|---|---|---|---|---|
| 离线LaTeX转换 | 存量Word文档批量迁移 | 高,公式保留语义 | 中,需要校对 | 最好,不依赖客户端控件 |
| 在线公式编辑器 | 新内容持续创作 | 高,但受编辑器限制 | 低 | 一般,依赖浏览器JS |
| 插件自动导入 | 少量快速导入 | 中,复杂公式易丢 | 低 | 一般,依赖服务器扩展环境 |
实际项目里我用的组合是:存量文档全部走离线LaTeX转换,新内容让编辑在后台用LaTeX输入为主,可视化编辑器作为辅助。这套组合对信创环境的兼容性最稳,也最不依赖某个特定厂商的私有控件。
3. 动手实现:从Word到WordPress的完整链路
3.1 动手前先确认的软硬件清单
开始之前,我强烈建议先检查一遍环境。信创环境下踩坑最多的地方,往往不是方案本身,而是环境里缺了某个不起眼的组件。
第一确认PHP版本和扩展。至少PHP 7.4以上,WordPress官方建议更低的版本早就不维护了。PHP的mbstring、xml、json扩展必须开启,因为后续Pandoc转换生成的HTML、MathJax配置文件都要依赖这些扩展。用php -m命令看一眼,缺了就装。
第二确认服务器字体。公式渲染出来之后,里面的数学符号和中文提示文本需要字体支撑。服务器上如果缺中文字体,页面里的中文标题会变成方块;缺数学字体,渲染出来的公式符号会发虚。在信创服务器上,我用的是安装常用字体包的方式一次性解决,字体目录在 /usr/share/fonts 下面。
第三确认MathJax库的位置。信创内网环境经常访问不了外网CDN,MathJax如果从公共CDN加载,生产环境里很可能直接加载失败。稳妥做法是提前把整个MathJax库下载到服务器本地,放到WordPress主题目录或者独立静态资源目录里,然后配置成从本地加载。这一步能省掉后面90%的渲染问题。
第四确认上传限制。WordPress默认post_max_size只有8MB,upload_max_filesize只有2MB。转换过程中经常要上传原docx做备份,或者上传中间产物,建议改大。改完php.ini后重启PHP进程才生效。
3.2 Word端处理:一条Pandoc命令把公式改成LaTeX
环境准备好之后,核心步骤就是文档转换。我最推荐的工具是Pandoc,它是一个开源文档转换工具,对docx的解析能力远超Word自带的另存为HTML功能。关键一点:Pandoc能把Word文档里的OMML公式自动识别并转成LaTeX源码,也能把部分OLE公式转成图片或提取出来。
普通文档的转换命令非常简单:
pandoc input.docx --mathjax -s -o output.html加--mathjax参数后,Pandoc生成的HTML里会自动把公式标成\(...\)和\[...\]形式,并且自动引用MathJax脚本。这个HTML直接拿到WordPress的自定义HTML区块里就能用。
我更习惯的做法是先用Markdown做中间格式,方便人工校对:
pandoc input.docx -t markdown -o output.md转换完成后打开output.md,你会看到文档里的公式被还原成了$...$或$$...$$包裹的LaTeX源码。我的经验是先抽查几处公式特别复杂的部分,确认Pandoc的转换是否完整。如果文档里有老式OLE公式,Pandoc会提示“无法解析”并把这些公式转成占位图。遇到这种情况,我会在原Word文档里手动把老公式重新输入一遍(或者用兼容Office组件另存为docx后再转),然后再跑Pandoc。
如果信创终端上没装Word,只有国产办公套件,怎么办?我试过几种情况。国产办公套件另存为Word格式后,用Pandoc转换的成功率比直接另存为HTML高很多。如果套件另存为docx后依然有公式丢失,就把文档发到有原版Word的机器上做一次“重新保存”,再做转换。这一步看起来笨,但确实是老文档兼容性最好的兜底办法。
3.3 WordPress端配置:MathJax渲染与编辑器配合
转换完成之后,WordPress端要把LaTeX源码“渲染成公式”。我用的是MathJax方案,它是纯JavaScript渲染引擎,不依赖系统字体和控件,在信创浏览器里实测最稳定。
推荐的做法是安装一个MathJax集成插件。WordPress后台插件市场搜“MathJax”或者“LaTeX”,能找到好几个。我不具体推荐某一个,因为插件更新频繁,关键是看插件是否支持以下能力:自定义加载地址、设置公式定界符、按需加载脚本。如果插件能做到本地加载MathJax,那就优先选它。
如果是纯代码党,也可以自己在主题里引入MathJax。在主题目录的header.php里加一行:
<script src="https://你的站点路径/mathjax/tex-svg.js" id="MathJax-script" async></script>用本地路径替换掉你的站点路径。接着加一段初始化配置:
<script> MathJax = { tex: { inlineMath: [['\\(', '\\)']], displayMath: [['\\[', '\\]']] }, svg: { fontCache: 'global' } }; </script>这里解释一下配置的意义。tex参数告诉MathJax,遇到哪些符号包裹的内容要当成公式来处理。我同时保留了\(...\)和$...$两种形式,因为Pandoc默认输出\(...\),而编辑器手写LaTeX时更习惯用$。svg参数设置输出为SVG矢量图,这是兼容性最稳的模式;MathJax还有HTML-CSS和CommonHTML输出模式,但SVG在信创浏览器和移动端上表现最不容易出问题。
配置完成后,发布文章时记得用“自定义HTML”区块来粘贴公式代码,不要用“经典段落”直接粘贴。原因很简单:WordPress的所见即所得编辑器会自作主张把反斜杠、空格和尖括号做转义,LaTeX源码一旦被转义就直接废了。用“自定义HTML”区块,内容会原样保存,反斜杠不会丢。这是实操里最容易踩、也最容易排查的坑。
3.4 发布后三分钟验证标准
渲染配置完成,不代表万事大吉。我给自己定了一个“发布后三分钟验证流程”,每次执行一遍,基本能把问题挡在发布之前。
第一步看公式有没有渲染成真正的数学样式。打开页面,肉眼观察公式区域。如果公式显示为高清的、可交互的数学表达式,说明MathJax已经接管成功。如果显示的是LaTeX原文(以\(开头的那串字),说明脚本没加载,或者定界符没配对。
第二步用开发者工具检查。F12打开控制台,看有没有报错信息。正常渲染后,页面里公式区域会出现类似mjx-container的元素。如果没有这个元素,说明脚本压根没执行。再看Network面板里MathJax的脚本请求是200还是404,能快速定位是加载路径错误还是网络问题。
第三步切换浏览器模式。在信创终端上分别用极速模式和兼容模式打开同一篇文章,对比公式显示效果。极速模式正常情况下没问题;兼容模式如果出现公式不渲染,不要慌,这是浏览器内核限制,我后面的方案是引导用户默认用极速模式访问站点,保证绝大多数用户看到的是正确的效果。
第四步看特殊字符是否正常。随机找几个含希腊字母、上下标、根号、矩阵的公式,逐一对比原文。中文文字是否乱码、符号是否变成问号,都在这步确认。发现乱码就去查数据库字符集,发现缺符号就去查字体安装情况。
4. 踩坑记录:兼容性问题与排查思路
4.1 公式变成 { EQ \o(...) } 域代码
这是我遇到频率最高的问题,不光信创环境,普通环境也有。现象是文章发布后,公式位置显示成{ EQ \o(\s\up 2(...),\s\do 3(...)) }这样的字符串,又长又乱。
原因分析:Word文档里有一种“域代码”机制,公式在底层可以是域代码形式。你在Word里看到的是渲染后的效果,但粘贴到网页编辑器时,编辑器有可能拿到的是域代码的原始文本。另一个常见诱因是Word里“文件→选项→显示”勾选了“显示域代码”,导致另存为或复制时直接带出了{ }包裹的域文本。
解决方案:第一步在Word里取消“显示域代码”选项,重新保存。第二步如果文档已经传到WordPress,用文本编辑器扫描全文,查找{EQ或{eq开头的片段,批量删掉。第三步如果是存量文档批量处理,最好的办法是回到源头,重新用Pandoc转换原docx,确保公式被正确识别为OMML而不是域代码。
这里补充一个排查技巧:用压缩软件打开docx文件,进入word/document.xml,搜索instrText标签。如果搜到了很多<w:instrText>EQ</w:instrText>这样的内容,说明这个文档的公式就是域代码形态,转换前必须先做“重新保存为docx”的处理,让Word把公式正式转为OMML。
4.2 OLE公式在信创终端显示为红叉
有些历史技术文档里的公式是OLE对象形式(早年用第三方公式编辑器创建的),这类公式在Windows版Word里双击能编辑,但在信创终端的浏览器和国产办公软件里,连显示的资格都没有,直接一个红叉或一个空白框。
原因分析:OLE对象本质上是一个“外部程序的嵌入对象”,网页端没有对应的程序,自然无法渲染。依赖ActiveX插件的旧方案在信创浏览器里基本被禁用了,所以红叉是必然结果。
解决方案:唯一彻底的方案是转换。我试过直接把含OLE公式的docx丢给Pandoc,Pandoc能识别出嵌入对象,但只能提取为图片,公式语义全丢。所以对这类文档,我的建议是优先在本地用原版Word打开,双击每个OLE公式,确认能编辑后“另存为新的docx”,把公式从OLE对象变成OMML原生公式,再交给Pandoc转换。如果原版Word实在打不开,退而求其次:保留图片显示,另外在图片的alt文本里抄录公式的LaTeX描述,至少保证信息可检索。
4.3 渲染延迟、乱码与特殊符号丢失
渲染延迟的问题多数出在MathJax脚本加载上。如果站点用的是外网CDN,在内网环境下加载可能要几十秒甚至超时。我的经验是开局就把MathJax库本地化,并且开启字体缓存。MathJax的SVG输出模式支持fontCache: 'global',开启后重复公式只生成一次SVG,后续公式复用缓存,渲染速度能快不少。
乱码问题要分三种情况。一种是在编辑器里看到反斜杠丢了一半,这是编辑器转义导致,换“自定义HTML”区块解决。一种是发布后发现中文注释乱码,去查数据库字符集,确保数据库表是utf8mb4。还有一种是公式里的特定字符显示成空位,比如空心字母、花体字母、特殊运算符,这多半是服务器字体缺字。检查服务器是否安装了完整字体包,并把MathJax的字体路径也放到本地。
特殊符号丢失还容易发生在数据库读写环节。Word里有些字符是“私有区字符”,不在标准Unicode范围内,一旦经过数据库的字符集转换就没了。遇到这种情况,我一般会建议编辑在文档里用Unicode标准字符替代,或者干脆用LaTeX命令表示(比如花体用\mathcal{}),让MathJax渲染出对应字形。
4.4 老文章里公式图片的兜底处理
不是所有存量文档都能在短时间内完成转换,尤其是一些年代久远、原始docx已经丢失、只留有网页版文章的内容。这种老文章里的“公式”大概率已经是图片了,没法用Pandoc自动转回LaTeX。
兜底方案一:给公式图片补alt文本。WordPress媒体库里可以批量编辑图片的替代文本,把公式的LaTeX描述写进去。这样即使图片本身放大模糊,但文字的语义还在,站内搜索也能搜到公式内容。
兜底方案二:设置图片懒加载。技术文档页面图片多,一个页面上百个公式图片是常事。开启懒加载能显著提升首屏速度,信创终端的浏览器对原生懒加载属性loading="lazy"的支持情况我实测过,主流Chromium内核没问题。
兜底方案三(重点):把图片格式统一转成WebP或SVG。老文档里的公式图片大量是PNG位图,放大就糊。有条件的话,统一转成高分辨率WebP,体积小、清晰度高。这个方法不用动公式内容,只是优化显示效果,作为过渡阶段够用了。
这类图片兜底方案只适合“临时上线”,长期维护还是要逐步替换成LaTeX源码。我每次给客户交付都会说明这一点,避免后续维护的人被一堆图片公式坑到。
5. 我的实操体会与小技巧
最后分享几个我自己总结的操作习惯,不一定写在文档里,但对减少工单真的有用。
小技巧一:把公式转换前置到内容生产流程里,而不是等发布之后再去修复。我参与的那个项目,后来定了一个规矩:所有技术文档在Word里完稿后,先走一遍Pandoc转换成Markdown,编辑在校对Markdown时看到公式是LaTeX源码,有问题的当场改。这样做看起来多了一步,实际把公式问题的成本压到了最低。
小技巧二:用脚本批量扫描站点已有文章。迁移过程中,我用了一个简单的搜索脚本,在数据库里查找疑似公式的残留文本,正则匹配\{EQ、\\\[、\\\(、$这些特征,把所有疑似文章列表导出来,再逐个确认处理。这个方法比“人肉一页页翻”高效得多,也避免漏网之鱼。
小技巧三:对信创环境的项目,先跑通“Word→Pandoc→WordPress”整条链路再批量铺开。我们第一次做迁移时,直接在开发站上拿一篇含公式最多的文档做全流程测试,确认公式渲染正常、浏览器兼容通过之后,才安排内容团队批量导入。结果就是上线后几乎没收到公式相关的返工需求。公式兼容问题最怕的就是“批量跑完才发现方向错了”。
根据我个人经验,处理这类问题的核心其实不是某个插件或者某个工具,而是把公式从“私有格式”拽到“标准格式”这个思路。一旦你让公式在迁移过程中变成了LaTeX这类标准化的纯文本格式,后面无论是信创还是非信创环境,渲染都只是加一个JS库的事。反过来说,只要公式还停留在OMML、OLE对象或者图片这些私有载体里,换什么环境都有风险。希望这套流程能帮到正在折腾Word公式迁移的朋友,少走点我用两周时间才绕出来的弯路。