尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Word公式安全导入XHEDITOR:涉密内网离线转换与过滤实战

Word公式安全导入XHEDITOR:涉密内网离线转换与过滤实战 1. 项目背景与需求拆解XHEDITOR在涉密办公场景的定位做军工配套办公系统的人应该都有同感涉密内网环境下的 Web 办公系统能选的富文本编辑器其实非常有限。国外那几家主流编辑器哪怕功能再强也天然存在合规疑虑——代码闭源、更新依赖国外社区、还时不时要请求外部资源。所以当项目里需要一个既能在完全离线环境跑、又能按涉密要求做代码审计和裁剪的编辑器时选来选去XHEDITOR小红帽编辑器成了最顺手的底座。它是国内作者开源的轻量级 HTML 编辑器文件体积小、依赖少、源码结构清晰更重要的是所有功能都在浏览器本地完成不需要往任何外部服务器发请求这在内网隔离环境下是硬指标。项目的标题里有个关键词——“Word 公式安全导入”。这句话拆开看包含三层需求第一用户已经用 Word 排好含有公式的材料希望直接搬到网页端继续编辑而不是重新敲一遍第二公式不是普通文字Word 里的公式在浏览器中默认是无法解析的必须走一条转换链路第三“安全”二字在内网语境下格外沉重——公式数据不能外传、不经过任何外部在线识别服务、品牌不能有授权风险、HTML 内容不能被注入恶意代码。也就是说这不仅是一个格式转换问题更是一个“链路自给自足 内容清洗过滤”的工程问题。我这边落地的场景是这样的单位内部的信息发布和文档协同系统使用 XHEDITOR 作为正文编辑器用户提交的原始文档大量来自 Word尤其是技术文档、试验报告、方案评审材料公式几乎是标配。过去这些文档进系统最粗暴的办法是整篇转 PDF 或者截图公式是保住了但文字不可编辑、不可检索、不可复用后续维护成本极高。这个项目本质上要解决的就是把 Word 公式这条“单向死胡同”变成一条“可编辑、可渲染、可复用的双车道”。下文我尽量把思路、选型、踩坑过程都摊开讲。这中间没有银弹每一步都是基于内网约束妥协出来的方案但对同样受困于“Word 公式 网页编辑器”组合的人应该有直接的参考价值。1.1 涉密内网环境下编辑器选型的真实约束很多人在互联网项目里做惯了习惯于“先选编辑器再说”——TinyMCE 功能全、Quill 好看、wangEditor 中文友好。但在军工涉密场景下选型逻辑完全倒过来了。第一优先级不是功能丰富度而是可控性和合规性。所谓可控是指源码必须拿得到、读得懂、改得动一旦出了安全问题不能等着开源社区发补丁必须在本地研发团队手里消化第二是内网环境中软件获取困难商业编辑器的授权文件、第三方插件的联网验证机制很可能在隔离网络里直接失效第三编辑器必须彻底剥离“外联”能力不能自带 CDN 引用、字体加载、远程图片上传回调这类功能哪怕只有一个地方会发出外网请求都会被安全审查一票否决。XHEDITOR 在这几个维度上得分都不错。它采用 MIT 许可源码是国内开发者维护对 HTML 解析和过滤逻辑是内嵌的没有依赖 Node 服务端或者云端 API。编辑器核心就两个文件xheditor.js和xheditor_lang.js再加上几个皮肤文件部署起来极其干净。它的 HTML 清洗是“白名单策略”——只保留预先定义的标签和属性其余一律过滤这比很多编辑器“黑名单策略”的安全底子要好。更关键的是它支持源码模式和可视化模式互切这为后面的公式导入提供了入口我们可以在源码模式下直接注入 LaTeX 代码块再让 MathJax 在可视化模式下完成渲染。1.2 真正要解决的三个核心问题围绕“Word 公式安全导入”这个项目其实是在同时解决三个问题任何一个环节没闭环整套流程就断掉。第一个是“格式翻译”。Word 公式是以对象形式嵌入文档的最常见的是 MathType/OLE 对象也可能是 Word 自2010 版以后的 OMMLOffice Math Markup Language原生公式。浏览器不认识这些格式。必须有一套离线方案把它们翻译成网页能理解的语言。业内公认的中间语言是 LaTeX——它既不是 Word 私有格式也不是浏览器原生格式但 MathJax/KaTeX 这类渲染库只需寥寥几行配置就能在网页里把它变成跟 Word 里几乎一致的排版效果。第二个是“通道清洗”。从 Word 复制粘贴到浏览器编辑器的内容天然携带大量垃圾元素span标签套!-- --注释、VML 矢量标记、OLE 加载控件、xml命名空间定义。更危险的是一些 Word 宏或者嵌入对象可能带有客户端执行能力。如果只做格式不转换而直接放行轻则编辑页面乱掉重则给内部系统开一个 XSS 的洞。所以安全导入必须做成一个“过滤管道”HTML 进来先过白名单、洗掉一切可执行属性再落进编辑器。第三个是“使用体验”。公式导入之后不允许变成一张死图片它得能跟随文字排版、能参与二次编辑、能保持编号和交叉引用。这意味着在链路设计之初就要想好公式的“持久化形态”——存成什么格式、以什么标记包围、渲染脚本怎么挂载。我们最终确定的是源数据存 LaTeX 源码 渲染层用 MathJax 按需加载这个方案既保存了编辑活性也保证了预览效果。这三个问题后面每一节都会对着实操展开。2. 方案设计Word 公式为什么不能直接进浏览器别看“把 Word 公式导入网页编辑器”这句话说起来轻松真正写代码的人第一次遇到这需求大概率会在浏览器控制台里反复看空白页。想明白“为什么”之前先别急着“怎么做”。2.1 Word 公式的三种形态与技术本质在拆解方案前我先把 Word 公式的“底盘”讲清楚。不同时代的 Word、不同插件装配习惯会让同一篇文章里的公式呈现完全不一样的底层结构第一种形态是老牌插件 MathType 创建的 OLE 对象。MathType 是安装在 Word 里的 ActiveX/OLE 组件公式作为内嵌对象存在。你在 Word 里双击公式会弹出 MathType 的独立编辑窗口而公式本身在 docx 文件里是一段以\x01开头、\x0B结尾的 OLE 二进制包装。这种对象浏览器端无法解析、无法直接读取文字内容常见的做法是在 Word 端借助 MathType 自身的“转换为 LaTeX”功能导出公式文本。第二种形态是 AxMath、Mathtype 高版本等国产插件创建的域对象。AxMath 的公式本质上是域代码Word 按 F9 切换视图时能看见类似{ EQ \f(...) }或者自定义域的原始结构。它比 OLE 略“透”一点但同样无法被网页直接渲染。第三种形态是 Word 原生公式OMML。从 Word 2007 起微软引入了 Office Math Markup Language公式以m:oMath标签存放在 docx 包内Word 2019/365 里用AltShift输入的就是这类公式。OMML 是 XML 格式理论上浏览器其实能解析——如果用 Office Online 的渲染服务。但内网环境没有 Office 在线服务所以还是得转。这还没算第四种“伪公式”——直接从 PDF 截图或者拍照贴进 Word 的公式图片。严格说它不算公式只是图形不在本项目的转换范围内。理解了这几种形态你就能明白整个问题的本质浏览器只认 HTML/CSS/JS而 Word 公式是私有二进制或专有 XML两者之间必须有一个“翻译官”。这个翻译官就是 LaTeX 吗不一定但它目前是最划算的。2.2 为什么“LaTeX MathJax”是最优中间态技术圈聊公式交换格式绕不开两个LaTeX 和 MathML。前者是 TeX 系统里人类可直接编写的标记语言以\frac{1}{2}、\sum_{i1}^{n}这种反斜杠命令为代表后者是 W3C 制定的数学 XML 标准结构严谨但冗长到令人窒息——一个分式就要写近十层标签。选 LaTeX 不选 MathML我基于三条理由一是人可读性。内网环境里公式从 Word 转过来之后总要有人检查、校对、修正。LaTeX 的源码干不干净一眼就能看出来MathML 那种mrowmfracmrowmsub的嵌套地狱人工审阅几乎不可能。二是工具链的成熟度。MathType 和 AxMath 的“复制为 LaTeX”功能已经做得非常完善Pandoc 可以将 docx 里的 OMML 公式自动转成 LaTeX 片段甚至可以自己写解析器处理 OMML 到 LaTeX 的映射。反过来把 MathML 作为目标的转换工具少得多中文资料更是匮乏。三是前端渲染的生态。MathJax 是老牌渲染引擎KaTeX 主打高性能两者都以 LaTeX 为主体语法。MathJax 对 LaTeX 的兼容性尤其好在文档流中支持\(...\)和$$...$$两种定界方式而且可以手动控制渲染时机这正好契合 XHEDITOR 这种“动态内容注入”的场景。MathML 在 MathJax 里也能渲染但那是“备选项”不是主路径。所以项目定的中间格式就是 LaTeX 文本渲染层用 MathJax 2.7.8后面细说为什么没用 3.x编辑器内用一对定界符把 LaTeX 源码包起来存储和传输都以源码形式走。提示这里说的 LaTeX 不是指“用 LaTeX 写整篇论文”而是特指数学公式片段即 document body 里的公式命令。脱离论文框架的单条公式片段转换成本低、复用效率高。2.3 “安全导入”的双重含义提到安全很多人第一反应是防止 XSS 攻击。但在这个军工项目里“安全”二字是双层的。第一层是数据链路安全。涉密环境下公式内容本身就是敏感信息哪怕只是一个简单的参数关系式也不能通过任何在线公式识别 API、OCR 云服务、公共转换网页进行处理。整个转换过程必须发生在内网内的三台设备之间用户的办公电脑Word 端、应用服务器转换清洗端、用户的浏览器渲染端。所有工具要么是内网已部署的要么是开源可离线运行的。任何形式的“调一下公网接口”都直接违反保密纪律。第二层是内容注入安全。Word 文档转成 HTML 时其中可能夹杂可执行脚本、事件属性、iframe 引用、对象嵌套。即便来源是内部员工也不能排除终端中毒后文档被污染的可能性。所以在 XHEDITOR 接收 HTML 的前面必须设一道强校验的清洗层只放行我们定义好的标签和属性把一切可执行度高、与公式渲染无关的元素全部剥离。我在项目初期踩过一个相关的坑从 Word“另存为网页”得到的 HTML如果直接倒进编辑器页面里会出现大量v:group、v:shape、!--[if gte mso 9]...![endif]--这类 VML/条件注释。看起来无害但里面埋着 OLE 对象加载逻辑在某些浏览器版本中就是任意命令执行的突破口。所以清洗层不能只过滤script这种一眼可见的标签而是要把 Word 生成命名空间、IE 条件注释、ActiveX 引用的所有元素都纳入黑名单只保留纯文本和图片。内网项目的安全很多时候是“自己不给自己挖坑”。公式转换链里任何一环引用了不可控的外部资源就是给整个系统留了口子。3. 实操落地XHEDITOR 中公式安全导入的完整流程思路定下来之后剩下的就是工程实现。这部分比较长我按“单条公式导入”“批量文档导入”“MathJax 集成”“安全过滤配置”四个小节逐一展开每一步都给可直接抄的配置和代码。3.1 单条公式导入MathType/AxMath 转换路径日常最常见的场景是用户手里已经写好了 Word 文档里面的公式数量不算多需要时不时补几个。针对这种“点状操作”最合理的流程是走 Word 插件端把公式转成 LaTeX再人工粘贴进 XHEDITOR。这个路径不需要开发专门的导入工具部署上最轻。具体操作步骤在 Word 中双击公式进入 MathType 编辑窗口。点击 MathType 菜单栏的“预置(Preferences)” → “剪切和复制预置( Cut and Copy Preferences)”将“转换格式”设为“LaTeX 2.09 或之后的版本”确定保存。这一步很关键默认的复制格式是 MathML粘贴到网页里就是一堆math标签MathJax 虽能识别但比较别扭而且带命名空间的 MathML 在清洗环节容易被拦掉。在 MathType 编辑窗口里选中公式全部内容CtrlA再CtrlC复制。此时剪贴板里同时有 LaTeX 文本和其他格式。切到 XHEDITOR不要直接粘贴到可视化模式而是先点工具栏的“源码”按钮进入源码编辑模式。在源码模式里选择你要插入公式的位置粘贴内容。粘贴进去的 LaTeX 可能是\frac{a}{b}这种不带定界符的裸代码也可能带\[...\]或$$...$$。为了保证 MathJax 一定能识别我们统一约定行内公式套\(...\)独立公式套$$...$$。所以在源码模式里贴完手动在首尾补上定界符。保存或预览MathJax 会自动把$$...$$块渲染成排版后的公式。如果编辑器内没看到效果刷新预览页或者触发一次手动渲染渲染接口见 3.3 节。AxMath 的逻辑类似在 Word 里选中公式用它的“复制 LaTeX”功能AxMath 面板上有对应按钮然后走同样的粘贴路径。值得一提的是AxMath 生成的 LaTeX 在个别命令上和 MathType 有差异比如绝对值符号的写法、矩阵环境的分隔符这类细节建议在 XHEDITOR 源码模式下肉眼核对一遍再保存。这条路最大的优点是零开发量、零工具安装。缺点是效率低十几二十条公式还能忍上百条公式靠人工粘贴手会断而且出错率高。所以批量场景必须走自动化。3.2 批量文档导入Word 转 HTML 加本地 LaTeX 化批量场景是这种系统的重头戏——积压的历史 Word 文档要一次性倒进知识库里面的公式几十上百个不可能让人坐在那儿一条条复制。批量的链路我设计成三段式“Word 单机转码 → 本地清洗脚本 → XHEDITOR 批量入库”。第一段用 Word 自身的“另存为网页过滤格式”功能将 docx 转成 HTML 文件。这一步会在本机完成需要一台安装了 Word 2019/365 的办公电脑配合一个带宏的 Word 模板来批量导出VBA 循环遍历词本目录用SaveAs2指定wdFormatFilteredHTML。导出的 HTML 里Word 原生公式会以m:oMathOMML 元素存在MathType 公式则变成图片加上 VML 包装这两种都需要后续处理。第二段跑本地清洗和转换脚本。脚本要做两件事而且必须分开做一是把 OMML 元素转成 LaTeX。我试过几种方式最稳的是用 Pandocpandoc input.docx -t html --mathjax可以直接把 docx 里的公式以 (...) 形式输出到 HTML。如果不想引入 Pandoc也可以写 XSLT 脚本把 OMML 映射成 LaTeX但工程量不小要处理的节点很多光是分数、根号、上下标、求和、积分、矩阵这几个大类就够写几百条模板。实际项目里我最终选用了 Pandoc离线安装后作为内网标准工具之一性能和准确性都经得起几十页文档的考验。二是把转后 HTML 里的“危险内容”全部剥掉。这一步不仅仅是等编辑器端的清洗而是要提前做第一遍过滤缩短脏数据进入数据库的时间线。过滤规则白名单只保留p, br, div, span, table, thead, tbody, tr, td, th, h1~h6, ul, ol, li, a, img, strong, em, sub, sup, blockquote这几个结构性标签其余全部丢弃。属性只保留href, src, alt, title, width, height, colspan, rowspan事件类属性onclick/onload/onerror等一律不放进清单里。第三段把清洗后的 HTML 分段导入系统。导入时的关键操作是用 XHEDITOR 的setContent(html)方法写入内容而不是走前端粘贴。这样可以绕过浏览器剪贴板的格式噪音也便于在服务端对内容做二次落库审查。如果量特别大可以分批导入每批 20~30 篇避免一次事务过大导致系统卡顿。注意Pandoc 转出来的 HTML 里公式是用 MathJax 定界符包的比如\(x^2 y^2 z^2\)。这些定界符在清洗脚本里必须保留不能因为“非标准 HTML 标签”被过滤掉。所以在写白名单时文本节点内容不参与标签过滤只针对标签本身做白名单校验。3.3 XHEDITOR 与 MathJax 的集成细节公式转换成 LaTeX 且放进编辑器内容区之后还差一步“渲染”。这一步由 MathJax 完成。很多人卡在这里因为 XHEDITOR 是动态渲染富文本MathJax 默认只在页面加载时扫描一次 DOM后由 XHEDITOR 写入的内容它根本不会碰。不处理这个问题公式永远显示为源码文本。我在页面里加载 MathJax 2.7.8配置如下script typetext/x-mathjax-config MathJax.Hub.Config({ tex2jax: { inlineMath: [ [\\(,\\)] ], displayMath: [ [$$,$$] ] }, skipStartupTypeset: true }); /script script src/lib/mathjax/MathJax.js?configTeX-AMS-MML_HTMLorMML/script这里的关键是skipStartupTypeset: true——让 MathJax 启动时不自动渲染全文避免与页面初始化时序冲突把渲染时机交给我们手动控制。渲染触发点在 XHEDITOR 的两个事件上挂var editor $(#content).xheditor({ ... onRender: function() { typesetMath(); }, afterSetContent: function() { typesetMath(); }, afterUp: function() { typesetMath(); } }); function typesetMath() { if (window.MathJax MathJax.Hub) { MathJax.Hub.Queue([Typeset, MathJax.Hub]); } }afterSetContent对应我们通过脚本向编辑器注入内容的场景afterUp对应源码模式切换回可视化模式onRender则是页面初始化。三处都挂上公式才能保证“该亮的时候一定亮”。为什么用 2.7.8 而不是 3.xMathJax 3.x 走的是模块化 ES6 架构配置方式完全不同倒是性能更好。但 2.x 的MathJax.Hub.Queue([Typeset, MathJax.Hub])这种手动队列模式与动态富文本编辑器配合最顺而且 2.x 的中文社区资料多、踩坑记录全。内网项目的原则是“稳定优先、文档可查”所以最终锁定 2.7.8。如果你上来就装 3.x记得把渲染接口换成MathJax.typesetPromise()实质思路一样代码不通用。3.4 安全过滤规则配置实战XHEDITOR 自带一套 HTML 过滤机制但默认配置是针对公开网站设计的对涉密内网来说还是过于宽松。需要自己定制一份“内网白名单”加在xheditor.js的配置里。基础过滤配置这样写$(#content).xheditor({ tools: ..., onPrePaste: function(html) { return safeClean(html); } }); function safeClean(html) { // 移除所有不在白名单的标签 var allowedTags [p,br,div,span,table,tr,td,th, tbody,thead,ul,ol,li,a,img, strong,em,sub,sup,blockquote,h1,h2,h3]; // 用 DOMParser 解析 var doc new DOMParser().parseFromString(div idwrap html /div, text/html); var root doc.getElementById(wrap); function clean(node) { if (node.nodeType Node.ELEMENT_NODE) { var tag node.tagName.toLowerCase(); if (allowedTags.indexOf(tag) -1) { // 保留子节点拆掉元素本身 while (node.firstChild) { node.parentNode.insertBefore(node.firstChild, node); } node.remove(); return; } // 属性白名单 var allowedAttrs [href,src,alt,title,width,height,colspan,rowspan]; Array.from(node.attributes).forEach(function(attr) { var name attr.name.toLowerCase(); if (allowedAttrs.indexOf(name) -1 || /^on/i.test(name)) { node.removeAttribute(attr.name); } }); } Array.from(node.childNodes).forEach(clean); } Array.from(root.childNodes).forEach(clean); return root.innerHTML; }这个safeClean函数用在onPrePaste回调里所有粘贴进入编辑器的内容都会先过一遍这道闸门。它的设计理念是“宁可丢格式不可留风险”。再补一条服务端防线入库时用 Java/Python 后端再调用一次同样的清洗逻辑复用同一份白名单规则前端后端各持一份保持同步。前端过滤防的是普通用户有意无意粘贴的坏内容后端过滤防的是有人绕过前端直接 POST 数据。两道防线缺谁都不踏实。还有一个小细节容易被忽略公式里的 LaTeX 源码中常见\{、\}、_、^这些合法但敏感的字符在 XHEDITOR 的源代码模式里会正常显示但如果切到可视化模式XHEDITOR 的轻量级 HTML tidy 器可能会对、做实体转义导致 LaTeX 源码变形比如把\frac{a}{b}的{}转成了#123;#125;。处理办法是在afterUp回调里先对内容里的公式定界符做保护临时替换为占位符再切换编辑器模式。这个细节如果不在测试阶段重点盯上线后一定会遇到“公式莫名其妙变成乱码”的工单。4. 常见问题与排查实录做这类系统的经验往往集中在“踩坑”上。我把项目上线前后遇到的高频问题整理成一份实录每个问题都附上当时的排查路径和最终解法。4.1 公式粘贴后乱码或 LaTeX 源码被 HTML 实体化现象从 MathType 复制公式切到源码模式粘贴显示是一堆\frac{1}{2}但是切回可视化模式再切回来源码里多了、#123;之类的实体编码。原因XHEDITOR 在模式切换时会对内容做 HTML 规范化它默认把、、、引号转为实体。LaTeX 代码里恰好充满这些字符于是“失真”。解法不要直接通过可视化模式切换而是把 LaTeX 代码在源码模式里插入后先保存到后台再重新加载渲染。如果一定要在编辑器内即时渲染可以先把 LaTeX 放进一个textarea或pre标签里包裹让 XHEDITOR 不对包裹内的字符做转义再配合 MathJax 渲染。另外我写过一个临时替换函数在切模式前把\(、\)、$$替换成【M】、【/M】这类占位符切完再替换回来实测能规避绝大多数实体化问题。这个土办法看起来笨但在内网项目里异常好用。4.2 MathJax 渲染不出来公式显示为源码现象内容已经写入库里也能看到$$...$$但页面只显示文本没有公式图形。排查路径打开浏览器控制台看有没有 JS 报错确认 MathJax 脚本有没有加载确认skipStartupTypeset配置后是否有代码主动触发渲染最后确认定界符与配置是否一致——最常见的是库里存的是$...$单美元而配置只认\\(...\\)两边对不上自然静默不渲染。解法统一定界符。项目里所有导入链路都约定\(...\)和$$...$$不再允许单美元定界因为单美元在正文里误伤率极高一个美元符号就可能导致整段异常。同时在typesetMath函数里加一行日志渲染队列触发时打印“Typeset called”方便线上排查是不是回调没挂上。4.3 公式编号与交叉引用丢失现象Word 文档里的公式是有编号的比如(1-1)、(2-3)正文里写着“见式(1-1)”。导入后编号没了交叉引用变成了死文本。原因Word 公式的编号本质是 SEQ 域不是公式内容的一部分。把公式转成 LaTeX 时编号域并不会被 Pandoc/MathType 自动带出来它停留在原文档的上下文里。解法分两步走。第一步在 Word 端用宏把 SEQ 域“煮熟”——选中所有公式编号域CtrlF9展开然后CtrlShiftF9取消域链接把编号变成静态文本。第二步批量导入后写一个后处理脚本检测独立公式行$$...$$如果它前面一行或后面一行有(数字-数字)样式的文本就把这个编号嵌入公式环境形如$$ E_k \frac{1}{2}mv^2 \qquad (2-1) $$这样编号进入公式源文本后续维护时人工调整也会容易很多。4.4 Word 另存网页带来的“毒标签”与样式污染现象导入 XHEDITOR 后整个编辑区域字体大小、行距变得混乱甚至有的段落在可视化模式不显示但源码模式里明明有内容。原因Word 另存为网页时会产生大量mso-*内联样式比如mso-bidi-font-size:11.0pt、mso-fareast-language:ZH-CN之类的命名空间属性。XHEDITOR 的默认过滤并不会逐条清理这些属性它们残留在span上就会污染整个页面的展示。解法在清洗脚本的白名单属性里明确禁止mso-前缀过线。上面那段safeClean的allowedAttrs里加入一个前缀过滤条件if (name.indexOf(mso-) 0) { node.removeAttribute(attr.name); return; }同时把style属性从白名单中移除——公式渲染靠 MathJax 自己算样式不需要 Word 注入的内联样式移掉之后排版反而更干净。4.5 表格内公式显示差一行、对齐异常现象公式在普通段落里显示正常但放进 XHEDITOR 的表格单元格后公式的基线与文字不对齐出现明显的上下偏移。原因Word 转出的表格td高度不一致且 MathJax 在表格内渲染时默认的行高与中文文字行高有冲突。这个问题的根子在 CSS 而没有。解法给 XHEDITOR 的内容区补充一段统一样式.xheditor-content mjx-container { vertical-align: middle; margin: 0 4px; } .xheditor-content td mjx-container { display: inline-block; line-height: 1.2; }必要时也可以给td设置固定行高并将垂直对齐方式设为middle。这类问题在测试环境基本不会暴露数据集一多就会冒头建议上线前就内置该样式。5. 项目收尾后的几点体会流程跑通之后回头再看这个项目有几个认知层面的收获值得留个记录。第一内网环境逼出来的方案未必绕远路。为了不调用在线服务我把公式转换链路全部压到本地Word 端转换、Pandoc 批量处理、后端清洗、前端 MathJax 渲染。最初觉得没有“云公式识别”这种大杀器转换精度可能不行实际跑下来Pandoc 对 OMML 的转换准确率超过预期MathType 手动路径更是完全保真。而这条路换来的最大好处是整个过程没有任何外部依赖系统运行近一年“外联风险”在审计记录里始终保持为零。第二过滤规则的“白名单”理念比“黑名单”省心太多。早期我也试着放过 Word 生成的绝大多数标签只把script和iframe拉黑结果发现 Word 的格式垃圾根本归不完。后来下定决心凡是不在业务需要的清单里的一律拆标签保文本这之后恶意注入和样式污染的问题几乎归零。过滤策略这种设计上的取舍会实际决定你后续要维护多少补充规则。第三单条公式和批量公式的场景要分离。强行用批量方案处理零星公式会引入过度工程强行用人工方式处理大批量文档则会消耗大量工时。项目上线后我给运维人员写了一份流程指南关键词只含两三条的文档直接走 MathType 复制 LaTeX 通道十页以上的报告挂到批量转换服务器上跑一跑。这套“场景分流”策略让不同岗位的人都能找到效率最大化的路径。最后分享一个实用小技巧XHEDITOR 的源码模式里可以把 LaTeX 定界符包进span contenteditablefalse防止误删同时在可视化模式里用 MathJax 渲染。这样既保留了公式整体的原子性又能让非技术用户像编辑图片一样选中、拖拽公式位置不会因为鼠标误点到源码标签而产生难以理解的编辑事故。我们在一个测试版本里对比过有原子保护和无原子保护的编辑体验前者让行政、质量、技术各岗位的用户都能无培训上手后者则经常有人反馈“我不知道为什么公式就变色了”。公式原子化之后才算真正做到了让 Word 公式在网页端“进得来、留得住、改得动”。
返回列表