Skip to content

feat: format alignment engine — 從既有 docx 逆向 template schema 並單指令重建(word reverse 深化) #130

Description

@kiki830621

Problem

Original text(使用者口述構想,逐字保留):
「我正在設計word的test,可以參考這個:對,這樣就不是「從零生成 Word」,而是更精確地說:

從既有 Word 文件中逆向工程出可重用的格式範本,然後讓新內容自動對齊那個格式。

這比較像:reference document → template extraction → content mapping → regenerated document

也就是「格式模仿器」或「文件格式對齊引擎」。核心任務不是生成內容,而是抽取格式規則。

你要的系統大概會做這幾件事:

  1. 讀入一份範本文檔 docx
  2. 分析它的標題、段落、表格、頁面設定、字體、縮排、間距
  3. 把這些格式抽成一個 template schema
  4. 將新的內容塞進對應位置
  5. 輸出一份格式高度相似的新 docx

這跟一般 AI 寫作不一樣。它的重點是 style/layout fidelity,不是內容創造。

你真正需要抽取的東西 — 一份 Word 文件其實可以分成幾層格式:

  1. Page-level format:紙張大小、直式/橫式、上下左右邊界、頁首頁尾、頁碼、行距基準、分節設定
  2. Paragraph-level format:標題層級、段前段後距離、縮排、首行縮排、對齊方式、行距、項目符號/編號
  3. Run-level format:字型、字體大小、粗體、斜體、底線、顏色、上標/下標、中英文字型差異
  4. Table-level format:欄寬、列高、框線、儲存格底色、文字垂直置中、表格對齊、合併儲存格
  5. Structural role(最重要但最難):不是只知道「這段是 16pt 粗體」,而是要知道它的角色 — 文件標題/章標題/節標題/正文/引用/表格標題/註腳/簽名檔/附件清單/日期/收件者。也就是 format → semantic role。這一步才是真正的「逆向工程範本」。

比較合理的架構:
Reference DOCX → DOCX Parser → Style Extractor → Template Schema → Content Aligner → DOCX Renderer → New DOCX

Template schema 範例:

{
  "page": { "size": "A4", "margins": { "top": "2.54cm", "bottom": "2.54cm", "left": "3.18cm", "right": "3.18cm" } },
  "styles": {
    "title": { "font": "標楷體", "size": 18, "bold": true, "alignment": "center", "space_after": 12 },
    "body": { "font": "標楷體", "size": 12, "line_spacing": 1.5, "first_line_indent": "2em" }
  },
  "structure": [
    { "role": "title", "source_pattern": "first_centered_bold_paragraph" },
    { "role": "body", "source_pattern": "normal_paragraphs" }
  ]
}

最難的是「內容對齊」:新內容的語意角色 → 範本文檔中的格式位置。需要 content slot system:

{ "slots": [
  { "name": "title", "role": "document_title", "style": "title", "position": 0 },
  { "name": "body", "role": "main_body", "style": "body", "position": 3 } ] }

未來只要輸入 { "title": "...", "body": "..." } 就可以套進去。

兩種模式:

  • A. Strict template mode:精準保留原文件結構,只替換內容(placeholder {{title}} {{date}} {{body}} {{signature}})。適合公文/會議紀錄/邀請函/報帳文件/表格文件/固定格式報告。優點穩定,缺點要先人工標記 slot。
  • B. Inferred template mode:程式自己推斷(第一個置中粗體大字 = title、日期附近段落 = date、最後幾段 = signature、表格 = structured data section)。優點神奇,缺點容易錯。
  • 建議 MVP 先做 Strict template mode,再慢慢做 inferred mode。

測試策略:

  • Smoke test:能不能讀入 docx 並輸出新的 docx
  • Unit test:每個 style extractor 是否能正確讀出字型、行距、縮排
  • Round-trip test:docx → template schema → docx,格式是否盡量保持
  • Snapshot test:同一份範本產生的輸出是否穩定
  • Regression test:修某個表格 bug 後,不要弄壞標題或段落
  • Visual diff test:把兩份 docx 轉成 PDF 或圖片,比較版面差異(最關鍵 — Word 格式最終不是只看 XML,而是看「視覺上像不像」)
  • Fuzz test:丟格式混亂的 docx,看程式會不會崩潰

精準定義:給定一份 Word 範本文檔,系統自動抽取其版面、段落、字型、表格與結構規則,形成一個可重用的 template schema。之後使用者只要提供新內容,系統就能自動將內容對齊到原本的格式,並輸出新的 .docx。這不是普通 Word clone,而是 Word template induction + document rendering。

我現在想做的是,如果我給一個docx,你有沒有辦法用一條入境(指令)從頭開始做成這個檔案,只用合法的word處理」
— Source: 使用者貼上文字(2026-07-07 口述構想,「一條入境」依上下文解讀為「一條指令」)

解讀:這是 format alignment engine(Word template induction)的完整構想。核心 ask 是最後一句 —— 給一個 docx,用一條指令從頭重建出這個檔案(只用合法的 OOXML 處理),即「docx → 可執行的重建腳本 → 內容等價的新 docx」單指令閉環。這正是 word-aligned-state-sync 的 reverse 方向延伸到完整格式保真。

與 macdoc 現況的關聯(起點不是零)

剛出貨的 word-aligned-state-sync(archived 2026-07-06,ooxml-swift v1.0.3)已交付這個願景的骨架:

構想元素 現況 缺口
「一條指令逆向」 ✅ macdoc word reverse <docx> --to-mdocx out.mdocx.swift 已存在(Phase 4 task 5.7) 只覆蓋段落文字 + styleId;page/table/run 級格式未抽取
Template schema .mdocx DSL(WordDSLSwift)即 schema 的 Swift 形;WordStyle/defineStyle 是 styles 段 run-level 屬性只有 bold/italic/color;page-level(sectPr:紙張/邊界/頁首頁尾)完全沒有 reverse 通道
DOCX Renderer ✅ WordDocument{}.save(to:) 三檔原子寫;reducer/tree 路徑保真 Table/Hyperlink/Bookmark 的 DSL authoring 是 loud-throw(5.5 已知範圍)
Structural role 推斷 無 Inferred mode 的核心;heuristic-output rule 的既有原則適用
Content slots 無 Strict mode 的 placeholder 系統
Visual diff test 無(現有為 XML/byte 級 round-trip + live-Word gated) convert --to pdf + 圖像比對可組裝

Type

feature

Expected

  1. 單指令重建閉環(MVP 驗收):macdoc word reverse ref.docx --to-mdocx t.mdocx.swift 抽出的腳本執行後產出的 docx,與原檔在「五層格式」上高度相似(先段落層完整 → 再 page/run/table 層逐步補齊)
  2. Template schema 層(.mdocx 或衍生 JSON)覆蓋 page/paragraph/run/table 四層格式屬性
  3. Strict template mode:content slots(placeholder 替換)先行;inferred mode 後續
  4. 測試矩陣落地:round-trip / snapshot / visual diff(docx→PDF→圖像比對)/ fuzz

Actual

word reverse 只逆向段落文字 + styleId + paraId;格式四層中 page/run 細節/table 全部走 // @op raw escape 或直接略過(stderr 警告)。無 template schema 抽象、無 content slots、無 visual diff 測試設施。

Impact

  • 這是 word-aligned-state-sync follow-up register 的自然延伸(Table/Hyperlink/Bookmark canonical authoring、WordStyle properties 深化都在 register 內)
  • 使用者當前的 Word 測試設計(round-trip 驗證)直接受益:visual diff test 是現有 byte-level 測試的正交補充
  • 潛在拆分:此 issue 可作為 umbrella,後續拆 Spectra change(template-schema 抽取 / content slots / visual diff infra 三塊)

Clarity Surface(idd-clarify run 2026-07-07T00:37:03Z)

Type Source Suggested canonical Status
ambiguity 「用一條入境從頭開始做成這個檔案」 「入境」依上下文解讀為「指令」(speech-to-text 誤植)——但也可能是「引擎」(one engine);影響驗收形態(CLI 單指令 vs 單一 engine API) resolved @ 2026-07-07T00:43:34Z(使用者確認 =「路徑」— 一條完整 pipeline 路徑)
ambiguity 「只用合法的word處理" 三種解讀:(a) 只產生合法 ECMA-376 OOXML(macdoc 現行路線)(b) 只透過 Word 應用程式本身處理 (c) 不做 binary hack。建議 canonical:(a) resolved @ 2026-07-07T00:43:34Z(使用者確認 (a))
ambiguity 「輸出一份格式高度相似的新 docx」 「高度相似」驗收標準未定:byte-equal / XML 結構等價 / visual diff 閾值?五層格式各自的相似度定義需要 per-layer 驗收條款 resolved @ 2026-07-07T00:43:34Z(使用者定調:要完全一樣,byte-equal——「我要看的是你仿作的能力」。最強驗收層級)
missing-context 「把兩份 docx 轉成 PDF 或圖片,比較版面差異」 docx→PDF 轉換通道未指定:macdoc 現有 pdf 輸出僅 html→pdf(playwright);docx→PDF 需 Word/LibreOffice export 或新增通道 resolved @ 2026-07-07T00:43:34Z(使用者委託:「你要看看怎麼用」— 通道調查轉為 diagnose 階段工作項)
missing-context 「讀入一份範本文檔 docx」 MVP 驗收用的 reference docx 樣本集未指定(公文/會議紀錄/報告——哪一類先行?現有 test-files 與 document fixture 是否適用) resolved @ 2026-07-07T00:43:34Z(使用者:建範本資料夾;候選 = 日本心理學範本,即先前記錄的 90_template_ja.docx)


Current Status

Phase: closed
Last updated: 2026-09-24 by idd-close
Closing Summary: #130 (comment)

Key Decisions

  • 驗收採 byte-equal(使用者 2026-07-07 定調);Spectra change 已於 2026-07-08 archive
  • 2026-09-24 以 CLI v0.8.0 重跑:90_template_ja 13/13、REC 表單 16/16 part 逐位元組相同

Scope Changes

  • (none)

Blocking

  • (none)

Commits

  • 見 archive 的 format-alignment-engine change

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions