Skip to content

Latest commit

 

History

History
483 lines (381 loc) · 29 KB

File metadata and controls

483 lines (381 loc) · 29 KB

Spectra Instructions

This project uses Spectra for Spec-Driven Development(SDD). Specs live in openspec/specs/, change proposals in openspec/changes/.

Use /spectra-* skills when:

  • A discussion needs structure before coding → /spectra-discuss
  • User wants to plan, propose, or design a change → /spectra-propose
  • Tasks are ready to implement → /spectra-apply
  • There's an in-progress change to continue → /spectra-ingest
  • User asks about specs or how something works → /spectra-ask
  • Implementation is done → /spectra-archive
  • Commit only files related to a specific change → /spectra-commit

Workflow

discuss? → propose → apply ⇄ ingest → archive

  • discuss is optional — skip if requirements are clear
  • Requirements change mid-work? Plan mode → ingest → resume apply

Parked Changes

Changes can be parked(暫存)— temporarily moved out of openspec/changes/. Parked changes won't appear in spectra list but can be found with spectra list --parked. To restore: spectra unpark <name>. The /spectra-apply and /spectra-ingest skills handle parked changes automatically.

CLAUDE.md

This file provides guidance to Claude Code when working with code in this repository.

Repository Overview

macdoc 是一個原生 macOS 文件處理工具集,專注於文件格式解析、轉換和 OCR 功能。整個專案使用 Swift 開發,充分利用 Apple 平台的原生能力。

本 repo 同時是 Claude Code plugin marketplace.claude-plugin/marketplace.json + plugins/,2026-07 起,#112):發布 che-word-mcpche-pdf-mcpche-pptx-mcpmacdoc 四個 plugins,使用者以 claude plugin marketplace add PsychQuant/macdoc 安裝。注意 plugins/(plugin shells,正常入版控)與 packages/(gitignored 本地套件)的差異;MCP shells 的 wrapper 從各 binary repo 的 GitHub Releases 自動下載 binary,安裝前強制驗證 sha256 + Developer ID 簽章鏈(requirement-based codesign,Team 6W377FS7BS)。發布新版時同步 bump plugins/<name>/.claude-plugin/plugin.json.claude-plugin/marketplace.json 兩處版本;binary-backed plugin 的 binary_version 只在 binary repo 發新 release 後才改(shell-only 變更 bump version 即可,#116 解耦契約)。

Project Structure

macdoc/                        # Monorepo 根目錄(同時也是 CLI 專案)
├── Package.swift              # CLI 的 Swift Package 定義
├── Sources/
│   └── MacDocCLI/             # CLI 入口點
│       ├── MacDoc.swift       # 主命令(Convert + PDF + Bib + Config + OCR + Docx + Word 子命令群)
│       ├── MacDoc+Convert.swift # Convert 統一轉換入口(16 路由,textutil-compatible)
│       ├── MacDoc+PDF.swift   # PDF 子命令群(Phase 1 pipeline)
│       ├── MacDoc+PDF+Phase2.swift # PDF Phase 2 consolidation 子命令
│       ├── MacDoc+Bib.swift   # Bib 子命令群(.bib → APA 7 HTML/Markdown/JSON)
│       ├── MacDoc+Config.swift# Config 子命令群(AI 設定管理)
│       └── CLIHelpers.swift   # 共用 helpers(validatedInputURL, writeStringOutput 等)
├── Tests/
├── docs/                      # 開發文檔和對話記錄
│   └── plans/                 # 實作計畫
├── packages/                  # 本地套件(.gitignore 忽略)
│   ├── common-converter-swift/   # Layer 2: 轉換器協議(DocumentConverter, StreamingOutput)
│   ├── word-to-md-swift/      # Layer 3: Word → Markdown
│   ├── html-to-md-swift/      # Layer 3: HTML → Markdown
│   ├── md-to-html-swift/      # Layer 3: Markdown → HTML
│   ├── word-to-html-swift/    # Layer 3: Word → HTML
│   ├── html-to-word-swift/    # Layer 3: HTML → Word
│   ├── md-to-word-swift/      # Layer 3: Markdown → Word
│   ├── pdf-to-md-swift/       # Layer 3: PDF → Markdown
│   ├── pdf-to-docx-swift/     # Layer 3: PDF → DOCX
│   ├── srt-to-html-swift/     # Layer 3: SRT → HTML
│   ├── marker-word-converter-swift/ # Layer 3: Word → Marker 模式
│   ├── bib-apa-to-html-swift/ # Layer 3: BibLaTeX → APA 7 HTML
│   ├── bib-apa-to-md-swift/   # Layer 3: BibLaTeX → APA 7 Markdown
│   ├── bib-apa-to-json-swift/ # Layer 3: BibLaTeX → APA 7 JSON
│   ├── bib-apa-swift/         # APA 7 styling engine
│   ├── ooxml-swift/           # Layer 1: OOXML (Word/Excel) 解析
│   ├── markdown-swift/        # Layer 1: Markdown 生成
│   ├── marker-swift/          # Layer 1: 圖片分類 + Marker 輸出
│   ├── surya-swift/           # Layer 1: OCR 文字辨識
│   └── pdf-to-latex-swift/    # PDF → LaTeX pipeline(簡化: GLM-OCR + Phase 2)
├── mcp/                       # MCP 工具(各自獨立 git repo,.gitignore 忽略)
│   ├── che-word-mcp/          # Layer 4: Word 文件處理 MCP(245 工具)
│   └── che-pdf-mcp/           # Layer 4: PDF 文件處理 MCP(25 工具)
├── cli/                       # CLI 實驗專案(預設 .gitignore;FastOCR 為 submodule)
│   └── FastOCR/               # GLM-OCR PDF→Markdown CLI + 實驗 harness(submodule)
└── reference/                 # 參考專案(.gitignore 忽略)

Package Dependencies

Layer 4 (Consumers)         Layer 3 (Converters)       Layer 2 (Protocols)     Layer 1 (Formats)

macdoc CLI ──────────┐
                     ├──→ word-to-md-swift ──┬──→ common-converter-swift    ooxml-swift
che-word-mcp ────────┘                       ├──→ ooxml-swift            markdown-swift
  └──→ ooxml-swift (直接讀寫)                 └──→ markdown-swift         marker-swift
                                                                        surya-swift
macdoc CLI ──→ pdf-to-latex-swift (PDFToLaTeXCore)                      pdf-to-latex-swift
macdoc CLI ──→ bib-apa-to-html-swift ──→ bib-apa-swift ──→ biblatex-apa-swift
macdoc CLI ──→ bib-apa-to-md-swift  ──→ bib-apa-swift ──→ biblatex-apa-swift
macdoc CLI ──→ word-builder-swift ──→ ooxml-swift (fluent Swift API for .docx, 1:1 mirror of docx.js)

che-pdf-mcp
└──→ Vision.framework / surya-swift

詳見 docs/modular-architecture.md

Development Commands

Build, Install & Run

# 建構主專案(debug,快速迭代)
swift build

# 建構 release(推薦,效能差 10-50x)
swift build -c release

# 安裝到 PATH(~/bin 需在 $PATH 中)
cp .build/release/macdoc ~/bin/macdoc

# 驗證
macdoc --version
# 執行 CLI — 統一轉換入口(textutil-compatible,16 路由)
swift run macdoc convert --to md file.docx          # Word → Markdown
swift run macdoc convert --to md file.docx --frontmatter  # Word → Markdown(含 YAML frontmatter)
swift run macdoc convert --to html file.docx         # Word → HTML
swift run macdoc convert --to marker file.docx       # Word → Marker 目錄(.md + _meta.json + images/)
swift run macdoc convert --to html file.md [--full]  # Markdown → HTML
swift run macdoc convert --to html file.md --html-extensions  # Markdown → HTML(啟用擴充語法)
swift run macdoc convert --to docx file.md           # Markdown → Word
swift run macdoc convert --to md file.html           # HTML → Markdown
swift run macdoc convert --to docx file.html         # HTML → Word
swift run macdoc convert --to pdf file.html          # HTML → PDF(需要 playwright CLI)
swift run macdoc convert --to html file.srt [--full] [--css dark|light]  # SRT → HTML(支援 speaker 偵測)
swift run macdoc convert --to md file.pdf            # PDF → Markdown
swift run macdoc convert --to docx file.pdf          # PDF → Word
swift run macdoc convert --to docx file.tex          # TeX → Word
swift run macdoc convert --to html file.bib [--full] [--css minimal|web]  # Bib → HTML
swift run macdoc convert --to md file.bib            # Bib → Markdown
swift run macdoc convert --to json file.bib          # Bib → JSON

# 執行 CLI — PDF pipeline(OCR + Phase 2 consolidation)
swift run macdoc pdf ocr --project /path/to/project              # 整頁 GLM-OCR(預設 local MLX)
swift run macdoc pdf ocr --project /path/to/project --mode ollama # 透過 Ollama HTTP API
swift run macdoc pdf normalize --project /path/to/project
swift run macdoc pdf fix-envs --project /path/to/project [--fix]
swift run macdoc pdf compile-check --project /path/to/project
swift run macdoc pdf consolidate --project /path/to/project [--dry-run] [--agent codex|claude|gemini]
# (deprecated)舊的 block-level 轉寫命令,已被 pdf ocr 取代:
# swift run macdoc pdf transcribe --project /path/to/project --backend codex|claude|gemini
# swift run macdoc pdf transcribe-pages --project /path/to/project

# 執行 CLI — Bib(APA 7 格式轉換)
swift run macdoc bib list paper.bib [--show-type]
swift run macdoc bib to-html paper.bib -o refs.html [--full] [--css minimal|web]
swift run macdoc bib to-md paper.bib -o refs.md [--heading]
swift run macdoc bib to-html paper.bib --key cheng2025 --key yang2024

# AI 設定管理
swift run macdoc config ai detect
swift run macdoc config ai list
swift run macdoc config ai set agent claude

# OCR 設定管理(v1.1+:具名 host profile;供 pdf-to-latex 內部頁級 OCR 使用)
swift run macdoc config ocr list
swift run macdoc config ocr add-host kyle localhost:11435  # 例:SSH tunnel 到遠端 Ollama
swift run macdoc config ocr set-default kyle
# 注意:通用文字辨識入口 `macdoc ocr` 已移除(#145),改用 bestocr——
# 此處設定只影響 pdf-to-latex 管線內部的頁級 OCR

# 建構個別套件
cd packages/ooxml-swift && swift build
cd packages/markdown-swift && swift build
cd packages/marker-swift && swift build
cd packages/surya-swift && swift build

# 建構 MCP 工具(release 模式)
cd mcp/che-word-mcp && swift build -c release
cd mcp/che-pdf-mcp && swift build -c release

Testing

# 測試主專案(在 repo 根目錄)
swift test

# 測試個別套件
cd packages/ooxml-swift && swift test
cd packages/marker-swift && swift test

Clean Build

# 清除快取(更新本地套件後建議執行)
swift package clean && swift build

Package Details

Layer 1: Format Packages

ooxml-swift

  • 用途:解析 Office Open XML 格式(.docx)
  • 功能:段落、表格、清單解析、圖片提取、語義標註、樣式解析
  • 依賴:ZIPFoundation

markdown-swift

  • 用途:生成 Markdown 文本
  • 功能:Streaming 輸出、行內格式、特殊字元跳脫
  • 依賴:無

marker-swift

  • 用途:圖片分類和 Marker 格式輸出
  • 依賴:markdown-swift

surya-swift

  • 用途:OCR 文字辨識(Detection、Recognition、Table、ReadingOrder、LaTeX)
  • 依賴:swift-async-algorithms
  • 平台:macOS 14+, iOS 17+

Layer 2: Protocol Package

common-converter-swift

  • 用途:轉換器共用協議和模型
  • 內容DocumentConverter protocol, StreamingOutput protocol, ConversionOptions, ConversionError
  • 依賴:無

Layer 3: Converter Packages

word-to-md-swift

  • 用途:Word → Markdown 轉換
  • 功能:streaming 轉換、標題/清單/表格偵測、行內格式、YAML frontmatter
  • 依賴:common-converter-swift + ooxml-swift + markdown-swift
  • APIWordConverter.convert(input:) / WordConverter.convert(document:) / convertToString()

Layer 4: Consumers

pdf-to-latex-swift

  • 用途:PDF → LaTeX 轉換 pipeline
  • Phase 1:PDF 掃描、頁面渲染、GLM-OCR 整頁轉錄、章節偵測、TeX 組裝(舊的 block-level AI 轉寫已 deprecated)
  • Phase 2(consolidation)
    • AIConfig — AI CLI 工具設定(codex/claude/gemini 自動偵測,~/.config/macdoc/config.json
    • LaTeXNormalizer — document class 修正、符號正規化、跨頁去重
    • LaTeXEnvChecker\begin/\end 配對檢查與修復
    • TexCompileChecker — pdflatex log 解析(支援 ! 和 file-line-error 格式)
    • Consolidator — 機械步驟 + agent 迭代修復 orchestrator
  • 依賴:swift-argument-parser
  • 平台:macOS 14+

macdoc (CLI)

  • 用途:CLI 工具,整合各套件功能
  • Convert:統一轉換入口(macdoc convert --to <format> <file>),textutil-compatible 語法,16 路由
  • PDF:簡化 pipeline(init → render → ocr → chapters → assemble)+ Phase 2(normalize → fix-envs → compile-check → consolidate)。舊的 block-level transcribe 已 deprecated,改用整頁 GLM-OCR。
  • Bib:BibLaTeX → APA 7 HTML/Markdown(to-html, to-md, list,支援 --key 過濾)
  • Config:AI 後端設定管理
  • 依賴:word-to-md-swift + marker-word-converter-swift + word-to-html-swift + html-to-word-swift + md-to-word-swift + pdf-to-md-swift + pdf-to-docx-swift + marker-swift + pdf-to-latex-swift + html-to-md-swift + md-to-html-swift + srt-to-html-swift + bib-apa-to-html-swift + bib-apa-to-json-swift + bib-apa-to-md-swift + ArgumentParser

che-word-mcp(245 工具)

  • 用途:Word 文件處理 MCP,讓 Claude 能讀取和分析 Word 文件
  • 功能:OOXML 讀寫(段落、表格、清單、圖片、樣式)+ Markdown 匯出 + 腳本管線(export_script / get_script_coverage / execute_script——與 macdoc word reverse 同一條 ooxml-swift transcoder code path,byte-equal parity 由共享 library 結構保證,見 Spectra change che-word-mcp-script-pipeline-parity
  • 依賴:ooxml-swift + word-to-md-swift
  • 架構:Server.swift(~16,000 行)+ satellite tool 檔(MarkdownExportTools / ReadbackTools / ScriptPipelineTools)
  • Binary.build/release/CheWordMCP

che-pdf-mcp(25 工具)

  • 用途:PDF 文件處理 MCP,讓 Claude 能讀取和分析 PDF 文件
  • 功能
    • PDF 解析和文字提取
    • Vision OCR(原生 macOS)
    • 圖片提取
    • 頁面資訊
  • 依賴:Vision.framework, PDFKit
  • 架構:模組化(分離 OCR、解析邏輯)
  • Binary.build/release/ChePDFMCP

MCP 配置範例

{
  "mcpServers": {
    "che-word-mcp": {
      "command": "/path/to/macdoc/mcp/che-word-mcp/.build/release/CheWordMCP"
    },
    "che-pdf-mcp": {
      "command": "/path/to/macdoc/mcp/che-pdf-mcp/.build/release/ChePDFMCP"
    }
  }
}

Architecture Principles

Streaming Architecture

所有轉換器採用 streaming 設計,避免將整份文件載入記憶體:

protocol StreamingOutput {
    func write(_ text: String) throws
    func writeLine(_ text: String) throws
}

Semantic Annotation

ooxml-swift 在解析階段產生語義標註,讓轉換器直接使用:

// 解析時標註
paragraph.semantic = .heading(level: 1)
paragraph.semantic = .bulletListItem(level: 0)
run.semantic = .formula(.omml)

// 轉換時直接使用
switch paragraph.semantic?.type {
case .heading(let level): // ...
case .paragraph: // ...
}

Module Naming — repo 帶 -swift,module 不帶

新套件的 target / product / Sources/ 目錄名一律不加 Swift 後綴。 repo 叫 foo-to-bar-swift,module 就叫 FooToBar

這是 Swift 生態系的慣例,不是本 repo 的偏好 —— Apple 自己的套件就是這個形狀:

Repo Module
swift-markdown Markdown
swift-argument-parser ArgumentParser
swift-async-algorithms AsyncAlgorithms

repo 名負責標示語言,module 名不必再說一次;在 Swift 檔案裡寫 import OOXMLSwift 是把「Swift」講兩遍。本 repo 的 29 個 target 已有 20 個是這個形狀(HTMLToMDPDFToDOCXNoteToPDFBibAPAToHTML…),所以這是把既有多數寫下來,不是新規定。

既有的 9 個帶後綴者不做大掃除。 改 module 名是對每個 consumer 的 breaking change (所有 import 都要跟著改),成本與消費者數量成正比:

類別 消費者 何時改
Converter,只有 macdoc 用 WordToMDSwiftWordToMD已完成,word-to-md-swift 1.0.0) 少數 該套件本來就要發 breaking release 時順手
廣用函式庫 OOXMLSwift 25+ 套件跨 3 repo 不改 —— 為了美觀發一輪全圖 major bump 不划算

判準是「這次改名有沒有搭上一班本來就要開的車」。沒有就別發車。

Protocol-Based Extensibility

  • DocumentConverter - 文件轉換協議
  • ImageClassifier - 圖片分類協議
  • StreamingOutput - 輸出協議

第一方依賴一律用版本範圍,不用 branch:(#184)

任何第一方 Package.swift 都不得宣告 branch: 這不是風格偏好,是踩過的坑:

branch: 記的是一個 revision,swift build 永不推進它;而且它是 unversioned requirement,會壓過整張圖的版本範圍。所以它不是「追最新」,是「凍結,並且讓別人的版本需求失效」。

2026-09-08 實測到的後果(macdoc#184):

  • word-builder-swift 的一條 branch: "main" 宣告,同時解出兩個不同的舊 revision —— macdoc 拿到 ooxml-swift v3.2.0、word-builder 自己的 resolve 停在 v3.0.0,而宣告旁的註解寫著「always picks up the latest」。
  • 它還被烤進已發布的 v1.0.0 tag,於是每個外部消費者都繼承一個不可重現的建置。
  • 拿掉它之後才發現版本圖本來就無解:六個套件宣告 from: "0.5.x" / "0.7.0",SwiftPM 的 from: 封頂在下一個 major,等於 < 1.0.0,與另外四個的 2.0.0..<4.0.0 互斥。pin 遮的不只是落後,是不可滿足性。
  • 它同時遮住了 macdoc CLI 自己的編譯破口(TranscodeError.rawSlotExecutionFailure,ooxml-swift v3.5.0 新增卻從未處理)。

反模式會靠引用繁殖:docx-workflow-swift 當初就是照抄 word-builder 的做法,理由寫「per the word-builder-swift v1.0.0 policy」。所以這條要寫成規則而不是留在 issue 裡。

現況(2026-09-08):from: "3.7.0"(ooxml-swift)與 from: "1.0.2"(word-builder-swift),第一方 manifest 零 branch:packages/token-counter-swiftrevision: 是第三方 fork 的刻意釘選,不在此規則內。

Package Update Workflow

所有套件皆使用 url: 遠端依賴。

# 1. 在套件目錄提交、推送、打 tag
cd packages/ooxml-swift
git add . && git commit -m "feat: 描述"
git push origin main
git tag v0.3.0 && git push --tags

# 2. 回到主專案更新依賴
cd ../..
swift package update
swift build

若需要本地開發迭代,可暫時將 Package.swift 中的 url: 改為 path: 指向本地路徑,完成後再改回。

Sub-Repositories

主 repo 以兩種方式追蹤外部 repo:

  • Submodule.gitmodules):mcp/ 下三個 MCP server。Clone 主 repo 時加 --recurse-submodules 會自動拉齊,或事後 git submodule update --init --recursive
  • Gitignore 忽略(各自獨立管理):packages/ 下的 Swift 套件、reference/。重建環境時在對應目錄 git clone 即可
目錄 Git Remote 說明
. (root) https://github.com/PsychQuant/macdoc.git 主專案 CLI
packages/common-converter-swift https://github.com/PsychQuant/doc-converter-swift.git 轉換器協議(remote 名 doc-converter-swift)
packages/word-to-md-swift https://github.com/PsychQuant/word-to-md-swift.git Word → MD 轉換
packages/word-builder-swift https://github.com/PsychQuant/word-builder-swift.git Lens-model authoring surface for .docx (v1.0.2+) — wraps OOXMLSwift.WordDocument
packages/docx-workflow-swift (local only — not yet published) Layer 3 manifest-driven docx-edit library on top of word-builder-swift v1.0.2
packages/ooxml-swift https://github.com/PsychQuant/ooxml-swift.git OOXML 解析
packages/markdown-swift https://github.com/PsychQuant/markdown-swift.git Markdown 生成
packages/marker-swift https://github.com/PsychQuant/marker-swift.git 圖片分類
packages/surya-swift (local only) OCR 文字辨識
packages/pptx-swift https://github.com/PsychQuant/pptx-swift.git PresentationML (.pptx) 解析與生成(v0.1.0+)
packages/pdf-to-latex-swift https://github.com/PsychQuant/pdf-to-latex-swift.git PDF → LaTeX pipeline (consumed via remote url dep since #79)
packages/ocr-swift https://github.com/PsychQuant/ocr-swift.git OCR pipeline (MLX + Ollama backends, PDFKit extractor; consumed via remote url dep since #79)
mcp/che-word-mcp https://github.com/PsychQuant/che-word-mcp.git Word MCP(submodule)
mcp/che-pdf-mcp https://github.com/PsychQuant/che-pdf-mcp.git PDF MCP(submodule)
mcp/che-pptx-mcp https://github.com/PsychQuant/che-pptx-mcp.git PPTX MCP(submodule)
reference/* reference/README.md 外部參考 repo(docx-js、pandoc、mlx-swift-lm、swift-argument-parser)— clone-on-demand,只有 README 進版控

MeasureOCR 已遷出(2026-07-18):原 cli/FastOCR(後改名 MeasureOCR)是研究儀器而非文件工具,已遷至 ~/Developer/bestOCR/repos/measureOCR(GitHub repo 同步改名 PsychQuant/measureOCR,舊 URL 自動轉址)。OCR 能力不受影響——macdoc 的 PDF 工具照常透過 published package packages/ocr-swiftPsychQuant/ocr-swift)取用 OCR;搬走的只是 benchmark 儀器。遷移全紀錄見 bestOCR repo 的 docs/migration-2026-07-18.md

Key Files

macdoc

  • Sources/MacDocCLI/MacDoc.swift - CLI 入口點(Convert + PDF + Bib + Config + OCR + Docx + Word 子命令群)
  • Sources/MacDocCLI/MacDoc+Docx.swift - macdoc docx ... 子命令(apply / plan / verify / diff —— manifest-driven .docx edit workflows,per openspec change macdoc-docx-workflow-cli,library 在 packages/docx-workflow-swift
  • Sources/MacDocCLI/MacDoc+Word+Render.swift - macdoc word render <script.mdocx.swift|.mdocx> --to-docx <out> [--verify-against <ref.docx>] [--force](腳本 → docx;word reverse 的反向半邊,補實 mdocx-grammar 早已具名卻從未實作的命令)。與 che-word-mcp 的 execute_script 呼叫同一個 shared entry point(ooxml-swift Transcode/ScriptPipelineExecute.swiftscriptPipelineExecute,v2.1.0 起),兩面因此由結構保證一致而非靠慣例。--verify-against 是 opt-in:不給就不驗、也不印任何驗證結論——沉默永遠不等於通過;給了則不符時 exit 非零並列出不符的 part。ordering contract:參考檔在任何寫入之前先讀進記憶體,因此 --to-docx--verify-against 指向同一路徑時比對的是寫入前的位元組,不會自我比對出假通過。
  • Sources/MacDocCLI/MacDoc+Word.swift - macdoc word reverse <docx> --to-mdocx <out> [--from-oplog] [--force] [--coverage] [--paragraphs-only] [--slot name=paraId]…(docx → .mdocx.swift 腳本反向轉換;transcoder 本體在 ooxml-swift 的 ScriptExporter/ScriptImporter)。預設 full-fidelity(format-alignment-engine Phase C #130):全 parts 騎在腳本上(raw channel byte-equal floor)+ typed DSL 升級(ReverseExtractor 的 trial-rebuild byte-equal gate 通過才升級,涵蓋 run rPr / paragraph pPr / sections / canonical tables 五層);執行腳本重建出 Stage B byte-equal 的 docx。真實 Word 文件的 document.xml 現在會升級(word-canonical-forms #131,ooxml-swift v1.4.0):新增 Word-canonical 詞彙(root namespace 雲、rsid 家族、xml:space、inline passthrough markers(bookmark/proofErr)、pPr/rPr 長尾、docGrid/section-type/pgSz、CRLF prolog)後,90_template_ja.docx(JPA 日文學術 template)的 document.xml 由 0% 升到 per-part 100%(aggregate 53.5%,餘量為尚無 typed 表示的 sibling parts)。--paragraphs-only 退回舊的段落 text+styleId 反向(無 byte-equal 保證);有 oplog sidecar 時仍優先匯出現況 log。--coverage 印出 dual-track 覆蓋率報告:每個 part 的 DSL/raw split + aggregate %(DSL 份額 = byte-equal 證明過的 typed 重建;raw = 逐字搬運;基線數字見 docs/format-alignment-baselines.md)。--slot name=paraId(可重複,Phase D + #131):指定段落的文字成為腳本的 Swift 函式參數;DSL-spellable 段落走 script-text 參數,raw-form 格式化段落(真實 template 常見)走 op-level 替換(// @slot directive + 替換 setRuns run text),raw-channel 文件(整個 document.xml 落 raw,如含表格的官方表單)走 carried XML 內 paraId 定位的 run 級手術(// @slot-raw directive;#171,ooxml-swift v3.5.0——結構感知定位、identity-shortcut default、fail-loud import+術後 well-formedness 驗證),三者都 strict mode 明確指定、不推斷;無 slot 時腳本逐字重建 byte-equal。能拼寫 ≠ 理解渲染效果(render-effect-semantics 第三層):typed 欄位對排版的實際效果由 docs/render-effect-registry.md 台帳記錄——每條 entry 須經 gated perturbation probe(RUN_WORD_INTEGRATION=1 swift test --filter RenderEffectProbeTests,真實 Word 渲染 + PDFKit 幾何量測)驗證方標 verified(no probe, no claim);slot 換內容另有渲染驗收(RealTemplateUpgradeTests scenario (d):頁數/頁框/被替換頁行距結構不變、未動頁 pixel-equal)
  • Sources/MacDocCLI/MacDoc+Convert.swift - Convert 統一轉換入口(16 路由,textutil-compatible)
  • Sources/MacDocCLI/MacDoc+PDF.swift - PDF 子命令(簡化 pipeline: ocr + Phase 2 consolidation)
  • Sources/MacDocCLI/MacDoc+OCR.swift - deprecation shim(#145):macdoc ocr 已移除,印遷移訊息指向 bestocr 並以 exit 2 結束。通用文字辨識歸 PsychQuant/bestOCR 單點;pdf-to-latex 內部頁級 OCR(PageOCRRunner)不受影響,其委派屬第二期(bestOCR#55 介面定案後)
  • Sources/MacDocCLI/MacDoc+Bib.swift - Bib 子命令(.bib → APA 7 HTML/Markdown,支援 --key 過濾)
  • Sources/MacDocCLI/MacDoc+Config.swift - Config 子命令(AI 設定管理)

pdf-to-latex-swift

  • Sources/PDFToLaTeXCore/AIConfig.swift - AI CLI 工具設定
  • Sources/PDFToLaTeXCore/LaTeXNormalizer.swift - 機械式 LaTeX 清理
  • Sources/PDFToLaTeXCore/LaTeXEnvChecker.swift - 環境配對檢查
  • Sources/PDFToLaTeXCore/TexCompileChecker.swift - 編譯錯誤解析
  • Sources/PDFToLaTeXCore/Consolidator.swift - consolidation orchestrator

srt-to-html-swift

  • Sources/SRTToHTML/SRTConverter.swift - SRT → HTML 轉換器
  • Speaker 偵測:自動辨識兩種格式,產出 <span class="speaker"> badge + data-speaker="N" 屬性
    • 冒號格式:Speaker 1: text(Otter.ai、Google Meet、部分 Plaud)
    • 方括號格式:[Speaker 1] text(Whisper、Assembly AI、部分 Plaud)
  • CSS 主題--css dark(深色卡片)或 --css light(淺色列表,適合列印)
  • 輸出模式--full 輸出完整 HTML 文件,否則只輸出 <main> fragment

common-converter-swift

  • Sources/CommonConverterSwift/Protocols/DocumentConverter.swift - 轉換器 protocol
  • Sources/CommonConverterSwift/Protocols/StreamingOutput.swift - 串流輸出 protocol

word-to-md-swift

  • Sources/WordToMD/WordConverter.swift - Word → Markdown 轉換器(module 於 1.0.0 由 WordToMDSwift 更名)

ooxml-swift

  • Sources/OOXMLSwift/IO/DocxReader.swift - Word 文件讀取
  • Sources/OOXMLSwift/Models/SemanticAnnotation.swift - 語義標註定義

che-word-mcp

  • Sources/CheWordMCP/Server.swift - MCP 伺服器主體(245 工具;script-pipeline handlers 在 ScriptPipelineTools.swift)
  • Package.swift - 依賴 ooxml-swift + word-to-md-swift

che-pdf-mcp

  • Sources/ChePDFMCP/Server.swift - MCP 伺服器主體(25 工具)
  • Sources/ChePDFMCP/VisionOCR.swift - Vision OCR 實作

Testing Files

測試時可使用任意 .docx 文件:

swift run macdoc convert --to md /path/to/test.docx
swift run macdoc convert --to marker /path/to/test.docx -o /tmp/test_output/

.note smoke tests (MacDocCLITests)

Tests/MacDocCLITests/NotePDFConvertTests.swiftNoteHTMLConvertTests.swift.note → pdf/html 的端到端 smoke coverage(#81)。兩個 test 透過 CLITestHelper.noteFixture()test-files/*.note 樣本,找不到就 XCTSkip — CI / clean-clone 不會 fail,只會跳過。

若要在本機實際跑 coverage,把任一 .note 檔放到 test-files/(該目錄被 .gitignore 忽略,檔案不會入版控)。committable 小 fixture 是 follow-up(見 #79 討論 serial)。

Platform Requirements

  • macOS 14+ (macdoc, pdf-to-latex-swift)
  • macOS 13+ (ooxml-swift, markdown-swift, marker-swift)
  • macOS 14+ / iOS 17+ (surya-swift)
  • Swift 5.9+