dom-docx: HTML 轉原生可編輯 Word 文件
dom-docx: HTML 轉原生可編輯 Word 文件
概覽
dom-docx 是一個 TypeScript 函式庫,旨在將語義化的 HTML 片段轉換為原生、可編輯的 Word 文件 (OOXML)。與產生截圖或佈局技巧的工具不同,dom-docx 會產生真實的 Word 結構——段落、run、列表和表格——確保生成的文檔在 Microsoft Word 和 LibreOffice 中皆可完全編輯。
核心能力
支援的 HTML 元素
在其預設的 inline 模式下,該函式庫支援廣泛的語義化 HTML:
- 文字與結構:標題、段落、列表 (
<ul>,<ol>) 以及引用塊 (blockquote)。 - 格式化:行內格式 (
<strong>,<em>)、連結以及水平分割線 (<hr>)。 - 引用與佈局:數據表格、陰影提示框 (callouts) 以及簡單的 flex 行 (最多 4 個項目)。
- 視覺效果:
data:圖片以及低複雜度的行內 SVG (特別是條形圖和文字)。
進階渲染選項
根據對樣式和複雜度的不同需求,dom-docx 提供三種不同的轉換路徑:
- 行內樣式解析 (
styleSource: "inline"):預設的純 JavaScript 路徑。它直接解析style=""屬性,且不需要瀏覽器環境。 - 計算樣式解析 (
styleSource: "computed"):使用getComputedStyle解析<style>區塊、類別 (classes) 和 ID 選擇器。- 在 Node.js 中:需要 Playwright 和 Chromium 來進行無頭 (headless) 渲染片段。
- 在瀏覽器中:使用使用者分頁的即時 DOM,不需要額外的安裝。
- 光柵化 (
rasterizeInPlace):在轉換前將<canvas>和複雜的<svg>(例如 Highcharts) 轉換為 PNG 圖片。這對於複雜圖表是建議的做法,並建議使用scale: 2以獲得高密度輸出。
技術架構
轉換流程
該函式庫透過三個階段的過程將 HTML 映射到 OOXML:
- 樣式解析:透過行內屬性或瀏覽器計算樣式來確定最終樣式。
- 訪問者模式 (Visitor Pattern):透過 Cheerio 遍歷將 HTML 元素轉換為
docx段落、表格、編號和超連結。 - 打包與修補 (Pack & Patch):產生 OOXML 並套用修補程式,以確保列表編號和陰影區塊的對齊在 Word 和 LibreOffice PDF 匯出時保持一致。
透過視覺回歸進行品質保證
作者使用「Autoresearch」模式開發 dom-docx——這是一種透過迭代來持續提升保真度的自主迴圈。該過程包括:
- 在 Chromium 中渲染 HTML。
- 透過 dom-docx 將 HTML 轉換為
.docx。 - 使用 LibreOffice 將
.docx檔案轉換為光柵化影像。 - 將瀏覽器截圖與 LibreOffice 截圖進行比較,以評分佈局保真度、可編輯性以及速度。
此迴圈針對 37 種真實世界的 HTML 模式進行測試,以確保與人類品質評分具有高度一致性。
整合與使用
安裝
npm install dom-docx
注意:需要 Node.js ≥ 20。Playwright 是可選的同儕依賴 (peer dependency),僅在 Node.js 中用於計算樣式或光柵化時使用。
快速入門範例
瀏覽器使用 (純 JS,無需 Playwright):
import { convertHtmlToDocx } from "dom-docx/browser";
const html = `<h1 style="color:#1a1a2e">Quarterly Report</h1><p>Revenue grew <strong>12%</strong> year over year.</p>`;
const blob = await convertHtmlToDocx(html);
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "output.docx";
a.click();
Node.js 使用:
import { convertHtmlToDocx } from "dom-docx";
const html = `<h1 style="color:#1a1a2e">Quarterly Report</h1><p>Revenue grew <strong>12%</strong> year over year`;
const docx = await convertHtmlToDocx(html);
await writeFile("output.docx", docx);
CLI 工具
若要進行無需程式碼的快速轉換,該函式庫提供了一個 CLI:
npx dom-docx input.html -o output.docx
限制
在 0.1.x 版本中,以下功能不受支援:
- 在
inline路徑上使用外部樣式表。 - Web 字體、CSS grid、浮動佈局 (float layouts) 以及絕對定位。
- 表單、
<dl>以及表格的rowspan。 - 複雜的 SVG 路徑與漸層 (除非使用
rasterizeInPlace)。 - 無法保證多頁佈局保真度,或針對第一頁/偶數頁的特定頁首/頁尾變體。