ADR-0108:原生 DOCX 数学模型与示例矢量排版分离
- 状态:接受。
- 日期:2026-11-02。
背景
学术模板示例需要可阅读的 PDF/SVG 数学公式,也需要能在 Word 中继续编辑的原生公式。把 TeX 字符串、图片或原始 OMML 片段保存在模型中,无法同时证明公式结构可查询、实际修改可保留和未知语法不会被丢弃。让所有核心层反向依赖 TeX 或 Word 适配器,也会破坏既有模块方向。
决策
export4j-adapter-docx 提供独立、不可变的 DocxMath 类型树,表达运行、序列、带横线分式、上下标、根式、大型运算符、矩阵、定界符、函数及上下限。DocxMathDocument 包裹既有 DocxSemanticDocument,通过真实段落 ID 和原文 UTF-16 的一个 U+FFFC 槽绑定每个公式;显示公式独占段落,行内公式可与正文相邻。
readMath 先执行完整包安全检查,从标准 OMML 重建数学类型树与 mathPr 设置,再复用既有语义导入。字段缓存归一后按实际对象槽重新定位公式,避免缓存长度改变锚点。writeMath 从类型树重建新包,不保留原 ZIP、DOM、XML 片段或恢复副本。标准包不依赖自有元数据才能重读。
数学结构、属性和格式使用严格白名单。未知或畸形 OMML、隐藏但非空的限位/根指数,在两种损失策略下都失败。Word 写入的结构控制字体只有与明确数学字体完全一致时才归一为默认值;没有模型映射的控制格式不能被忽略。普通 read/readSemantic 在任何样式物化或侧边转换之前拒绝全包公式,仅允许标准数学设置叶子,避免 ALLOW_LOSS 把公式悄悄丢掉。原包编辑继续保留其独立的局部包保留契约。
数学公式数、节点、深度、文字及矩阵格累计有界,并同时计入共享 DOCX 来源预算。锚点不得冒用图片/字段标记或覆盖修订、内容控件、目录缓存。输入/输出流由调用方持有;完整编码验证成功后才触碰输出,最终流 I/O 失败与文件原子发布分别处理。
PDF/SVG 数学排版留在 examples,通过 JLaTeXMath 1.0.7、明确字体资源及 Export4j 矢量指令生成轮廓,同时保留原 TeX 逻辑文本。依赖及许可证只属于示例。原生 Word 数学树由 Java 独立构造,不把示例的 TeX 解析器扩散成公共核心能力,也不声明通用 TeX↔OMML 或 MathML 转换。
结果与边界
Word 数学成为真正可构造、修改并重新编码的公共适配器模型。公共核心及布局后端保持单向依赖,DOCX 仍由 Word 自行分页,不承诺与 PDF 示例逐页一致。通用语义投影、已有 semanticConversion 以及统一跨格式转换没有获得原生数学排版能力;需要这些入口时继续明确拒绝。
验收分别检查模型与预算、标准 OOXML、完全移除自有元数据的三轮往返、实际数学修改、独立 PDF/SVG 结构、双渲染,以及安装 Word 的应用自动化。当前 Word 样例完成 8 式打开、首分母 2a→5a 修改、保存重开和 PDF 导出;普通 Word 附加样式、部件及元数据仍产生 75 条明确诊断。数学严格保留与整份文件无损是不同契约,不将这些结果扩展为任意 Word 文档或人工 UI 验收。
API、单位和可复现命令见原生数学指南,样例范围和证据见ManuWeave 验收。