@blade-demon/docx-to-html
v1.0.0
Published
Convert Word .docx to mobile H5 HTML — mammoth + style map + anchor fix + MCP server
Readme
docx-to-h5
把 Word .docx 文档转成移动端可直接渲染的 H5 页面。
基于 mammoth + 自定义 style map + 锚点修复 + DOM 后处理 + 移动端 CSS 的完整管线。
适用场景:内容运营、隐私政策、用户协议、长说明文档等"语义化为主、不要求像素级保真"的转换。
工程结构
docx-to-h5/
├─ package.json
├─ src/
│ ├─ cli.js # CLI 入口
│ ├─ convert.js # 主转换管线:mammoth -> 锚点修复 -> 后处理 -> 套模板
│ ├─ style-map.js # Word 样式 -> 带 class 的 HTML 标签映射表
│ ├─ fix-anchors.js # 锚点修复:补齐缺失的 heading id
│ ├─ post-process.js # DOM 后处理:外链 target/rel、表格滚动、空段去除
│ ├─ build-sample-docx.py# 生成测试样张 docx(Python,避开容器 npm 限制)
│ └─ _shims.js # ⚠️ 仅 demo 用,生产环境删掉,改用真实 mammoth/cheerio
├─ styles/
│ └─ mobile.css # 移动端 CSS(mobile-first,含强调块/表格滚动/锚点偏移)
├─ samples/
│ └─ input.docx # 样张
└─ dist/
└─ output.html # 转换产物快速开始(生产)
npm install mammoth cheerio
node src/cli.js path/to/doc.docx dist/output.html --title "你的标题"CLI 选项:
--css <path>:使用自定义 CSS 文件(默认styles/mobile.css)--title <title>:HTML 页面<title>标签内容
容器内 demo(无 npm 环境)
src/_shims.js 是 mammoth 和 cheerio 的最小子集实现,用 Node 内置能力实现,
仅用于在没有 npm 的环境里证明管线跑得通。它不完整,生产环境必须替换。
python3 src/build-sample-docx.py # 用 python-docx 造样张
node src/cli.js samples/input.docx dist/output.html迁回生产时:
npm install mammoth cheerio- 删除
src/_shims.js - 把
convert.js、fix-anchors.js、post-process.js里的 import 改回'mammoth'/'cheerio'(文件里都用🚀 生产环境:注释标记了原版语句) convert.js里被注释掉的convertImage块需要恢复,用于处理图片
四个核心模块
1. style-map.js — 样式映射的契约
mammoth 的核心能力是把 Word 样式名(如 "Heading 1"、"Emphasis Block")映射到带 class 的 HTML 标签。 关键约束:Word 文档里必须真的用了这些命名样式,不是手工调字号字色拼出来的"视觉假标题"。
"p[style-name='Heading 1'] => h1.doc-h1:fresh"
"p[style-name='Emphasis Block'] => p.emphasis-block:fresh"
"table => table.doc-table":fresh 表示"不要把连续同样式段落合并成一个标签",列表/标题尤其需要。
2. fix-anchors.js — 锚点修复
文档内跳转(如目录里的"#一"跳到"一、定义"章节)有两种实现:
- 正规做法:Word 里插 bookmark,mammoth 自动输出
<a id="..."> - 偷懒做法:直接打字写"#一",对应正文里没有 bookmark,跳转就死链
我们的兜底策略:扫描所有 <a href="#xxx">,对缺失的 id,用文字匹配从 heading 里反向查找并补上。
匹配规则:归一化标点和空格后,比较 heading 文本是否以 anchor id 开头。
3. post-process.js — DOM 后处理
style map 解决不了的 DOM 层调整:
- 外链统一加
target="_blank" rel="noopener noreferrer"(H5 webview 必备) - 表格外层包
<div class="table-scroll">(移动端横向滚动) - 去除 mammoth 偶尔产出的空段落
- 图片加
loading="lazy"和默认alt
4. mobile.css — 视觉规范
mobile-first,rem 排版,对齐主流金融类 H5 隐私政策页的视觉风格。
通过 CSS 变量定义颜色 token,便于主题化。
scroll-margin-top 解决锚点跳转在固定 header 下的偏移问题。
工程化建议
构建期转换,不要运行时:隐私政策更新频率低,CI 跑一次输出静态 HTML, 前端只负责套壳渲染。性能最优,且转换问题在 CI 阶段就发现。
图片单独处理:生产里把
convertImage改成上传 OSS,返回 URL 而不是 base64。 长文档全 base64 会让 HTML 暴涨到几 MB。样式审计契约:和内容方约定 Word 样式白名单(H1-H4、List、Quote、Emphasis Block、 Warning Block),加到 style-map.js 里。文档作者必须用样式而非手工字号。
mammoth messages 接到 CI:mammoth 转换会输出
messages数组, 含 unrecognized style 警告。CI 里把这些 message 输出当 lint 看, 出现新样式名就要么加映射要么修文档。回归测试:固定一批典型样张作 snapshot,每次升级 mammoth 或改 style-map 都跑一遍 diff。
已知限制(mammoth 通用)
mammoth 是语义化方案,下列内容不能很好支持:
- 文本框、文字方向、艺术字
- 公式(可用 MathJax 后处理)
- 页眉页脚、分栏布局
- 表格合并单元格的边框样式
如果这些是核心需求,考虑 LibreOffice headless 或 Aspose.Words(见前置方案对比)。
