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 提供三種不同的轉換路徑:

  1. 行內樣式解析 (styleSource: "inline"):預設的純 JavaScript 路徑。它直接解析 style="" 屬性,且不需要瀏覽器環境。
  2. 計算樣式解析 (styleSource: "computed"):使用 getComputedStyle 解析 <style> 區塊、類別 (classes) 和 ID 選擇器。
    • 在 Node.js 中:需要 Playwright 和 Chromium 來進行無頭 (headless) 渲染片段。
    • 在瀏覽器中:使用使用者分頁的即時 DOM,不需要額外的安裝。
  3. 光柵化 (rasterizeInPlace):在轉換前將 <canvas> 和複雜的 <svg> (例如 Highcharts) 轉換為 PNG 圖片。這對於複雜圖表是建議的做法,並建議使用 scale: 2 以獲得高密度輸出。

技術架構

轉換流程

該函式庫透過三個階段的過程將 HTML 映射到 OOXML:

  1. 樣式解析:透過行內屬性或瀏覽器計算樣式來確定最終樣式。
  2. 訪問者模式 (Visitor Pattern):透過 Cheerio 遍歷將 HTML 元素轉換為 docx 段落、表格、編號和超連結。
  3. 打包與修補 (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)。
  • 無法保證多頁佈局保真度,或針對第一頁/偶數頁的特定頁首/頁尾變體。

Sources