ODF 格式支援矩陣
本文件記錄 OdfKit 對主要 ODF 格式的實作狀態。狀態以目前程式碼與 測試證據為準,不把路線圖中的目標預先標為完成。
ODF Toolkit / ODF Validator 對標線另見 odf-toolkit-parity.md。
三種獨立能力承諾
本矩陣的歷史狀態不得單獨解讀為「完整支援」。新的可稽核宣稱拆成三個互不推導的維度:
PackageFidelity:封裝偵測、載入、儲存、驗證與未知內容儲存。SemanticApiDepth:高階 API 能理解及修改的文件語意深度。InteropEvidence:schema、corpus 與外部辦公軟體的實測證據。
機器可讀 claim、限制與證據路徑見 claims.json 及
能力宣稱與證據索引。Package round-trip 成功不能推導為完整語意支援;
特定版本互通成功也不能推導為所有辦公套件或像素級一致。
狀態標記
封裝與驗證層
verified:已有直接 API 與測試覆蓋,可作為目前支援能力使用。validated:已有驗證或偵測測試證據,但高階 API 仍可能有限。package-level:可建立、載入、儲存與驗證最小封裝,但高階語意 API 尚未完整。partial:已有部分高階模型或來回讀寫能力,但仍有明確缺口。planned:尚未有足夠程式與測試證據支撐。
高階 API 層
workflow-verified:滿足本文件採用的 5 項完成標準——(1) 公開高階 API 可完成該格式常見 工作流程、(2) 有專屬測試、(3) 有來回讀寫/邊界/互通證據(含誠實記錄的上游限制)、 (4)Validate()/ValidateAsync()可用且測試覆蓋正向與負向案例、(5) 文件已同步。 截至 2026-06-24,全部 24 個 extension 均已達成此分級(詳見下方「全格式 workflow-verified 最低能力 矩陣」)。日常辦公自動化不需下沉 DOM。usable/usable-variant:歷史分級,目前矩陣中已無格式使用;保留定義供未來新格式或 迴歸情況參考——usable指常用建立/編輯 API 可用但有明確語意缺口;usable-variant指具 專屬 typed 文件類別但語意 API 仍完全繼承基底格式。package-only:僅封裝層來回讀寫;高階語意模型尚未專屬化或仍共用基底 wrapper。
重要說明(避免過度宣稱):對 ODT、ODS、ODP、ODG、ODC、ODB、ODF、ODI,
workflow-verified 另受 semantic-coverage.json schema v4
約束;16 個 family 的每個 topic
都必須連結 Create、Get、Find、Set、Update、Remove、Clear、RoundTrip、
Interop、規格、實作、測試、限制與 clean-room provenance。範本、Flat XML、主控文件及
Web 文件等變體的 workflow-verified 仍表示沿用其基底格式語意模型並滿足本文件 5 項通用
完成標準,不推導為另一套重複的深度 facade。物理分頁、像素級渲染、完整 Calc/Excel
公式與 Pivot 執行階段、SmartArt 佈局、Office 專屬效果模擬及完整協同演算法,均為明列
非目標;核心另提供具資源上限的 Pivot 彙總、計算欄位、分組、總計與常用衍生顯示計算。
Formula 已具備 FindFirst/GetAll/WithChild/ReplaceFirst/RemoveFirst/
ClearMathTokens 等「尋找→取得→更新→移除/清除」語意編輯 helper;這項完成聲明
不等同於完整公式重算引擎。
凡標示為「真機」的互通證據,均指已有 LibreOfficeInteropTests 與
eng/Test-LibreOfficeInterop.ps1 驗收路徑;一般 dotnet test 不會自動啟動真實
LibreOffice,且專用腳本在找不到 LibreOffice 時預設略過。若要作為發佈門檻,請使用
pwsh eng/Test-LibreOfficeInterop.ps1 -RequireLibreOffice。
CNS 11643/全字庫字型支援邊界
OdfKit 的文字內容仍以 Unicode 儲存;一般 ODT 文字層不寫入 CNS 11643 交換碼。針對臺灣全字庫 與罕見中文字情境,核心能力聚焦在 Unicode 平面分段、ODF font-face 宣告與外部字型註冊/子集化 擴充點:
OdfFontContext.SegmentText可依 BMP、Plane 2、Plane 3、Plane 15/16 將文字拆成多個片段,並對應TW-Kai-*、TW-Song-*、HanaMin、Jigmo 或 Windows ExtB/ExtG 字型名稱。TextDocument.ApplyCjkFontFallback()會宣告常見 CJK fallback 與TW-Kai-98_1、TW-Kai-Ext-B-98_1、TW-Kai-Plus-98_1、TW-Song-98_1、TW-Song-Ext-B-98_1、TW-Song-Plus-98_1等全字庫字型名稱。OdfParagraph.AddText(..., OdfTextFontFallbackOptions.Cns11643())可自動呼叫分段邏輯,將同一段 文字拆成多個 run 並套用對應 font-face。OdfTextFontFallbackOptions.HanaMin()會宣告HanaMinA/HanaMinB,並將 Plane 2 與 Plane 15/16 文字切換至HanaMinB;OdfTextFontFallbackOptions.Jigmo()會宣告Jigmo、Jigmo2、Jigmo3,並將 Plane 2 與 Plane 3 文字分別切換至Jigmo2與Jigmo3。- ODS/ODP/ODG 文字入口已共用同一套分段與 font-face 宣告基礎:
OdfCell.SetText(..., OdfTextFontFallbackOptions.Cns11643())、HanaMin()或Jigmo()會將儲存格文字寫成富文字 run;OdfSlide.AddTextBox(...)與OdfDrawPage.AddTextBox(...)的 fallback options overload 會在文字方塊內寫入帶文字樣式的text:span。 - 圖表(ODC 及嵌入圖表)與簡報嵌入表格亦有對應入口:
OdfChartDocument.SetChartTitle(..., options)/SetAxisTitle(dimension, ..., options)(builder 對應WithTitle(..., options))與OdfEmbeddedTable.SetCellText(row, column, ..., options)使用同一套分段與 font-face 宣告基礎; 頁首頁尾經由OdfPageHeaderFooter.GetOrCreateParagraph()取得OdfParagraph後即可使用段落 的 fallback options 多載。涵蓋範圍至此為所有承載 ODF 文字 run 的高階入口;MathML 公式內容 本質上不適用字型分段。 OdfFontContext的RegisterFontDirectory、RegisterFont與RegisterFontSubsetter提供外部字型 註冊與子集化擴充點;OdfKit 不內建政府字型,也不替第三方字型授權背書。
上述四個層次不得混為同一項保證:
- font-face 宣告只是在
content.xml/styles.xml中建立字型名稱與家族的 ODF 中繼資料, 不代表讀取端已安裝該字型,也不代表字型檔已嵌入封裝。 - run 分段只在呼叫帶有
OdfTextFontFallbackOptions的高階文字寫入入口時執行;載入或解析 既有 ODF 不會自動掃描整份文件並重寫 run。分段依 Unicode 平面選擇字型名稱,不能讓 OpenType GSUB/GPOS 跨越不同字型檔運作。 - 完整字型內嵌由
OdfFontContext.EmbedFonts將已解析的實體字型檔寫入封裝,並以 ODF 1.1~1.4 規定的style:font-face > svg:font-face-src > svg:font-face-uri結構連結;封裝中的字型檔會有 對應的 manifest media type。 - 字型子集內嵌只在文件含 PUA 碼位且已註冊外部
IFontSubsetter時於存檔管線執行。 OdfKit 核心沒有 TTF/OTF 子集編譯器,倉庫亦不存在OdfKit.Extensions.WebFont套件。 目前請求會把文件中蒐集到的 PUA 碼位集合交給每個已宣告的 font-face,尚未建立文字 run 至 實際字型的逐一碼位歸屬;外部實作應容忍來源字型沒有部分請求字形。
IFontSubsetter 契約只傳遞字型名稱、可解析的檔案路徑與 PUA 碼位集合,並不保證保留 GSUB、
GPOS、GDEF、垂直 metrics 或 Unicode variation sequence。OpenType 的 vert/vrt2 是 GSUB
feature tags,不是獨立資料表;IVS 非預設變體通常由 cmap format 14 表示。因此,外部子集化器
必須自行完成 glyph closure、所需 layout tables/feature records 與 variation selector 對應的保留,
並以實際排版引擎驗證;僅「保留 GSUB 表」不足以宣稱直排或 IVS 完整相容。規格依據見
OpenType GSUB、
vert/vrt2 feature 定義
與 cmap format 14。
因此,現階段可說 OdfKit 具備全字庫與補充平面文字的 ODF 文件骨架支援;在缺少真實全字庫字型、 CNS 11643 私用區碼位版本對照與 LibreOffice 開啟/匯出 PDF 的端到端 corpus 前,不應宣稱完整 CNS 11643 官方語意相容或認證。
Unicode 版本相容性與自訂罕字字型擴充點
OdfKit 核心處理與 Unicode 版本無關:文字內容以 Unicode 原樣通過 XML 層,字型分段以 Unicode 平面(plane)為單位路由而非以區塊(block)為單位,因此新版 Unicode 於既有平面新增的 區塊(例如 Unicode 17.0 於 Plane 3 新增的 CJK Ext J,U+323B0–U+33479)會自動歸入既有平面 路由,不需要修改程式碼。
內建對應表的 Plane 3(Ext G/H/J)覆蓋現況:
- 字雲(
Jigmo3)與 WindowsSimSun-ExtG有對應字型可接。 - 全字庫(
TW-Kai-*/TW-Song-*)與花園明朝(HanaMin)無 Plane 3 字面,維持基礎字型 (對應字元將依讀取端字型後援機制呈現)。
若需接上內建規則未涵蓋的罕字字型(例如自備的黑體系 Ext B–J 補字字型),可組合下列公開 擴充點,全程不需修改 OdfKit:
OdfFontContext.RegisterSupplementaryPlaneFontMapping(pattern, planeFontNames):註冊自訂 「基礎字型 → 平面 → 字型名稱」對應,優先於內建規則,可涵蓋 Plane 1 至 16;傳回IDisposable供還原。OdfTextFontFallbackOptions.Custom(baseFont, fontFaces):以自訂OdfFontFaceInfo清單宣告 font-face,配合上述分段規則讓AddText/SetText高階入口自動套用。OdfFontContext.RegisterFont/RegisterFontDirectory:註冊實體字型檔以供解析與內嵌。OdfFontContext是字型子系統的唯一入口:單租戶場景直接使用OdfFontContext.Default; 多租戶或測試隔離場景可建立獨立執行個體,經由OdfDocument.FontContext(文件層級,含存檔 時的字型內嵌)或OdfTextFontFallbackOptions.FontContext(單次呼叫層級)注入,優先序為 「選項 → 文件 → Default」。已知限制:PDF 匯出因 PDFsharp 全域字型解析器 (GlobalFontSettings.FontResolver)為處理程序層級,一律使用Default情境;嵌入子文件與 最外層文件共用封裝時,存檔內嵌以最外層文件的情境為準。
OdfKit 內建部分已知字型家族的平面路由名稱,但不內建任何第三方罕字字型檔;字型選擇、實體檔案 註冊、內嵌與授權政策仍由使用者自行決定。
中文碼對照、Big5/Big5E 與碼位遷移
延續「機制內建、資料外部」原則,OdfKit 對全字庫(CNS 11643 open data)提供下列支援; 對照表資料由使用者自政府資料開放平臺下載 (政府資料開放授權條款-第 1 版),倉庫不內建任何對照資料:
資料來源標示:數位發展部,2026,CNS11643 中文標準交換碼全字庫中文碼對照表 (釘選快照 2026-08-05)。該資料依政府資料開放授權條款-第 1 版 釋出。CI 只在驗證期間下載並快取原始封存檔,不會把對照表納入原始碼、NuGet 套件或發行成品; 因此 OdfKit 原創程式碼維持 CC0,而政府資料本身不宣告為 CC0。若使用者另行散布對照表或其 衍生資料,仍須履行原授權的顯名義務。全字庫資料集另提供 OFL 1.1 選項供字型用途選擇, 本專案的中文碼對照表 baseline 明確採用 OGDL-Taiwan-1.0。
OdfCns11643MappingTable.Parse/JoinOnCns:解析官方「字面-編碼十六進位」對照表 格式並以 CNS 字碼聯結兩表(例如 CNS↔Unicode 聯 CNS↔Big5E 得 Unicode↔Big5E)。 OdfBig5EEncoding.Create(unicodeToBig5E):由對照表驅動的 Big5E 編碼,可直接餵入OdfCsvOptions.Encoding。官方資料若有多個 Unicode 純量值共用同一 Big5E 碼,解碼會以數值 最小的純量值作為確定性的 canonical 結果;因此 alias 不保證逐字往返,但解碼後重新編碼會 回到同一 Big5E 碼。CLI 的--encoding不內建big5e(需外部資料);Big5 則由 .NET CP950 提供(--encoding big5),與官方 CNS↔Big5 表的差異經 baseline 測試量化為 2 字(U+5F5E、U+7B9A 重複對應歧義字,CP950 不提供編碼)。OdfDocument.MigrateTextCodePoints(mapping):資料驅動的文件碼位遷移(含 ContentDom 與 StylesDom),供舊版全字庫 PUA 自造字遷移至新版 Unicode 正式碼位的封存情境,回傳OdfCodePointMigrationReport統計。此方法只替換兩個 DOM 的文字節點,不會重新執行SegmentText或重套文字 run 的字型;若遷移前後跨越 Unicode 平面,呼叫端應在套用 fallback 樣式前先完成遷移,或於遷移後自行重建受影響的文字 runs。- CI baseline:
.github/workflows/cns11643-baseline.yml以釘選版本(2026-08-05、SHA-256 驗證)的官方對照表執行全集驗收——10.4 萬 CNS↔Unicode 碼位的平面路由與分段無損、 CP950 差異白名單、Big5E 全碼位編解碼往返。本機無資料時對應測試自動略過。
碼位遷移引擎本身是語系中立的(吃 IReadOnlyDictionary<int, int>),對照表來源不限全字庫。
OdfCodePointMappingTable 提供與格式無關的階梯:
ParseDelimitedHex(reader, separator):行式十六進位對照表——可直接餵入 unicode.org 官方對照檔(Public/MAPPINGS下的 BIG5.TXT、CP950.TXT 等,TAB 分隔、0x前綴、#註解) 與 UCD 式分號清單(U+前綴亦可);不支援XXXX..YYYY範圍語法。Parse(reader, lineParser):委派擴充點,自訂行格式只需一行解析邏輯。Join(keyToSource, keyToTarget):通用字串鍵聯結(JoinOnCns為其 CNS 語境別名)。- 資源預算(比照 security-limits 的入口原則):兩個解析方法(含 CNS 特化版)施行每行
4,096 字元與每表 2,000,000 筆上限,超出擲出
FormatException;8 位十六進位溢為負值 一律視為無效,例外訊息中的原始行會截斷並清洗控制字元。對照表屬營運端提供的設定資料, 行長檢查在該行讀入後執行——餵入不可信串流前應另行預先限制輸入大小。 - JSON/試算表來源(例如日本文字情報基盤的 MJ 縮退對照,JSON 格式)由呼叫端以對應的
反序列化器轉成字典即可餵入
MigrateTextCodePoints——同一引擎同樣適用日本外字(MJ)、 GB 18030-2022 的 PUA 重指派與歐洲 MUFI 等 PUA 遷移場景。
矩陣
| 副檔名 | MIME 類型 | OdfDocumentKind |
偵測 | 建立 | 載入 | 儲存 | 驗證 | 來回讀寫 | 高階 API | 測試證據 |
|---|---|---|---|---|---|---|---|---|---|---|
.odt |
application/vnd.oasis.opendocument.text |
Text |
verified | verified | verified | verified | validated | verified | workflow-verified | TextApiUsabilityTests, TextHighLevelApiTests, FourFormatApiScenarioTests, TextAdvancedFidelityTests, ComplianceTests, InteropCorpusTests |
.ott |
application/vnd.oasis.opendocument.text-template |
TextTemplate |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, E2ETests, InteropCorpusTests, TemplateRoundTripTests, LibreOfficeInteropTests |
.odm |
application/vnd.oasis.opendocument.text-master |
TextMaster |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, InteropCorpusTests, MasterDocumentTests, LibreOfficeInteropTests |
.oth |
application/vnd.oasis.opendocument.text-web |
TextWeb |
verified | verified | verified | verified | validated | verified | workflow-verified | ComplianceTests, PackageRoundTripTests, TextWebDocumentTests, HtmlExportTests, LibreOfficeInteropTests |
.fodt |
application/vnd.oasis.opendocument.text |
FlatText |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, E2ETests, PackageRoundTripTests, FlatVariantRoundTripTests, LibreOfficeInteropTests |
.ods |
application/vnd.oasis.opendocument.spreadsheet |
Spreadsheet |
verified | verified | verified | verified | validated | verified | workflow-verified | SpreadsheetApiUsabilityTests, SpreadsheetHighLevelApiTests, ChartHighLevelApiTests, FourFormatApiScenarioTests, SpreadsheetCommonApiTests, OpenFormulaSupportTests, InteropCorpusTests |
.ots |
application/vnd.oasis.opendocument.spreadsheet-template |
SpreadsheetTemplate |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, E2ETests, InteropCorpusTests, TemplateRoundTripTests, LibreOfficeInteropTests |
.fods |
application/vnd.oasis.opendocument.spreadsheet |
FlatSpreadsheet |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, E2ETests, PackageRoundTripTests, FlatVariantRoundTripTests, LibreOfficeInteropTests |
.odp |
application/vnd.oasis.opendocument.presentation |
Presentation |
verified | verified | verified | verified | validated | verified | workflow-verified | PresentationApiUsabilityTests, PresentationHighLevelApiTests, FourFormatApiScenarioTests, PresentationAndRenderingTests, PresentationBoundaryTests, InteropCorpusTests |
.otp |
application/vnd.oasis.opendocument.presentation-template |
PresentationTemplate |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, E2ETests, InteropCorpusTests, TemplateRoundTripTests, LibreOfficeInteropTests |
.fodp |
application/vnd.oasis.opendocument.presentation |
FlatPresentation |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, PackageRoundTripTests, FlatVariantRoundTripTests, LibreOfficeInteropTests |
.odg |
application/vnd.oasis.opendocument.graphics |
Graphics |
verified | verified | verified | verified | validated | verified | workflow-verified | DrawingApiUsabilityTests, DrawingHighLevelApiTests, FourFormatApiScenarioTests, ComplianceTests, InteropCorpusTests |
.otg |
application/vnd.oasis.opendocument.graphics-template |
GraphicsTemplate |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, E2ETests, InteropCorpusTests, TemplateRoundTripTests, LibreOfficeInteropTests |
.fodg |
application/vnd.oasis.opendocument.graphics |
FlatGraphics |
verified | verified | verified | verified | validated | verified | workflow-verified | DocumentKindApiUsabilityTests, ComplianceTests, PackageRoundTripTests, FlatVariantRoundTripTests, LibreOfficeInteropTests |
.odc |
application/vnd.oasis.opendocument.chart |
Chart |
verified | verified | verified | verified | validated | verified | workflow-verified | ChartHighLevelApiTests, SecondaryFormatApiScenarioTests, DocumentKindApiUsabilityTests, ComplianceTests, InteropCorpusTests, ChartVariantRoundTripTests, LibreOfficeInteropTests |
.otc |
application/vnd.oasis.opendocument.chart-template |
ChartTemplate |
verified | verified | verified | verified | validated | verified | workflow-verified | ComplianceTests, PackageRoundTripTests, ChartVariantRoundTripTests, LibreOfficeInteropTests |
.odf |
application/vnd.oasis.opendocument.formula |
Formula |
verified | verified | verified | verified | validated | verified | workflow-verified | FormulaHighLevelApiTests, SecondaryFormatApiScenarioTests, DocumentKindApiUsabilityTests, PackageRoundTripTests, InteropCorpusTests, FormulaVariantRoundTripTests, LibreOfficeInteropTests |
.otf |
application/vnd.oasis.opendocument.formula-template |
FormulaTemplate |
verified | verified | verified | verified | validated | verified | workflow-verified | ComplianceTests, PackageRoundTripTests, FormulaVariantRoundTripTests, LibreOfficeInteropTests |
.odi |
application/vnd.oasis.opendocument.image |
Image |
verified | verified | verified | verified | validated | verified | workflow-verified | ImageHighLevelApiTests, SecondaryFormatApiScenarioTests, DocumentKindApiUsabilityTests, ComplianceTests, InteropCorpusTests, ImageVariantRoundTripTests, LibreOfficeInteropTests |
.oti |
application/vnd.oasis.opendocument.image-template |
ImageTemplate |
verified | verified | verified | verified | validated | verified | workflow-verified | ComplianceTests, PackageRoundTripTests, ImageVariantRoundTripTests, LibreOfficeInteropTests |
.odb |
application/vnd.oasis.opendocument.base |
Database |
verified | verified | verified | verified | validated | verified | workflow-verified | DatabaseHighLevelApiTests, DatabaseSchemaAndFormTests, DatabaseBoundaryTests, SecondaryFormatApiScenarioTests, DocumentKindApiUsabilityTests, ComplianceTests, InteropCorpusTests, LibreOfficeInteropTests |
.fodc |
application/vnd.oasis.opendocument.chart |
FlatChart |
verified | verified | verified | verified | validated | verified | workflow-verified | PackageRoundTripTests, CorpusComplianceTests, ChartVariantRoundTripTests, LibreOfficeInteropTests |
.fdf |
application/vnd.oasis.opendocument.formula |
FlatFormula |
verified | verified | verified | verified | validated | verified | workflow-verified | PackageRoundTripTests, corpus manifest, FormulaVariantRoundTripTests, LibreOfficeInteropTests |
.fodi |
application/vnd.oasis.opendocument.image |
FlatImage |
verified | verified | verified | verified | validated | verified | workflow-verified | PackageRoundTripTests, CorpusComplianceTests, ImageVariantRoundTripTests, LibreOfficeInteropTests |
全格式 workflow-verified 最低能力矩陣(Workstream A)
依本文件定義的 5 項完成標準逐格式列出條件是否滿足,作為上方矩陣
workflow-verified 分級的可稽核依據。圖例:✅ 滿足;✅* 滿足,但互通證據為「已實機驗證並誠實
記錄上游應用程式限制」而非綠燈通過(依使用者決策,至少一個驗收案例即符合本矩陣互通欄位要求,
不要求每案必須通過)。
| 副檔名 | (1) 高階 API 完成常見工作流程 | (2) 專屬測試 | (3) 來回讀寫/邊界/互通證據 | (4) Validate() 正負向 | (5) 文件同步 |
|---|---|---|---|---|---|
.odt |
✅ | ✅ TextHighLevelApiTests |
✅ 真機(LibreOfficeHeadlessLoadsGeneratedDocuments) |
✅ 通用骨架 | ✅ |
.ott |
✅ CreateFromTemplate/CreateFromDocument |
✅ TemplateRoundTripTests |
✅ 真機(LibreOfficeHeadlessLoadsTemplateVariantDocuments) |
✅ 通用骨架 | ✅ |
.odm |
✅ 子文件 CRUD/合併/大綱位移 | ✅ MasterDocumentTests |
✅ 真機(LibreOfficeHeadlessLoadsMasterDocument,writerglobal8) |
✅ 通用骨架 | ✅ |
.oth |
✅ CreateFromDocument/CreateFromWebDocument+HTML 匯出整合 |
✅ TextWebDocumentTests |
✅ 真機(LibreOfficeHeadlessLoadsWebTemplateDocument,writerweb8_writer) |
✅ 通用骨架 | ✅ |
.fodt |
✅ CreateFromFlatDocument/CreateFromDocument |
✅ FlatVariantRoundTripTests |
✅ 真機(LibreOfficeHeadlessLoadsNativeFlatXmlDocuments) |
✅ 通用骨架 | ✅ |
.ods |
✅ | ✅ SpreadsheetHighLevelApiTests |
✅ 真機(LibreOfficeHeadlessLoadsGeneratedDocuments) |
✅ 通用骨架 | ✅ |
.ots |
✅ | ✅ TemplateRoundTripTests |
✅ 真機 | ✅ 通用骨架 | ✅ |
.fods |
✅ | ✅ FlatVariantRoundTripTests |
✅ 真機 | ✅ 通用骨架 | ✅ |
.odp |
✅ | ✅ PresentationHighLevelApiTests |
✅ 真機 | ✅ 通用骨架 | ✅ |
.otp |
✅ | ✅ TemplateRoundTripTests |
✅ 真機 | ✅ 通用骨架 | ✅ |
.fodp |
✅ | ✅ FlatVariantRoundTripTests |
✅ 真機 | ✅ 通用骨架 | ✅ |
.odg |
✅ | ✅ DrawingHighLevelApiTests |
✅ 真機 | ✅ 通用骨架 | ✅ |
.otg |
✅ | ✅ TemplateRoundTripTests |
✅ 真機 | ✅ 通用骨架 | ✅ |
.fodg |
✅ | ✅ FlatVariantRoundTripTests |
✅ 真機 | ✅ 通用骨架 | ✅ |
.odc |
✅ 軸線/序列/樣式/error-indicator/regression-curve/mean-value | ✅ ChartHighLevelApiTests |
✅* 嵌入 ODS 真機成功;獨立檔案經實機確認上游不支援(已記錄) | ✅ 通用骨架 | ✅ |
.otc |
✅ CreateFromDocument/CreateFromTemplate |
✅ ChartVariantRoundTripTests |
✅* 封裝結構驗證+上游限制已記錄 | ✅ 通用骨架 | ✅ |
.fodc |
✅ CreateFromDocument/CreateFromFlatDocument |
✅ ChartVariantRoundTripTests |
✅* 封裝結構驗證+上游限制已記錄(誤判為 Writer document) | ✅ 通用骨架 | ✅ |
.odf |
✅ MathML token/builder/LaTeX/annotation | ✅ FormulaHighLevelApiTests |
✅ 真機(LibreOfficeHeadlessLoadsFormulaDocument,math8) |
✅ 通用骨架 | ✅ |
.otf |
✅ CreateFromDocument/CreateFromTemplate |
✅ FormulaVariantRoundTripTests |
✅* 封裝結構驗證+上游限制已記錄 | ✅ 通用骨架 | ✅ |
.fdf |
✅ CreateFromDocument/CreateFromFlatDocument |
✅ FormulaVariantRoundTripTests |
✅* 封裝結構驗證+上游限制已記錄(誤判為 Calc document) | ✅ 通用骨架 | ✅ |
.odi |
✅ 多框架/版面/旋轉/裁切/濾鏡/批次操作 | ✅ ImageHighLevelApiTests |
✅* 封裝結構驗證+上游限制已記錄 | ✅ 通用骨架 | ✅ |
.oti |
✅ CreateFromDocument/CreateFromTemplate |
✅ ImageVariantRoundTripTests |
✅* 封裝結構驗證+上游限制已記錄 | ✅ 通用骨架 | ✅ |
.fodi |
✅ CreateFromDocument/CreateFromFlatDocument |
✅ ImageVariantRoundTripTests |
✅* 封裝結構驗證+上游限制已記錄(誤判為 Writer document) | ✅ 通用骨架 | ✅ |
.odb |
✅ 連線/查詢/表單設計器/報表 href/Schema CRUD | ✅ DatabaseHighLevelApiTests、DatabaseBoundaryTests |
✅* mimetype/manifest 驗證+ LibreOffice UNO API 人工驗證+ --convert-to 行為已誠實記錄 |
✅ 通用骨架 | ✅ |
第 (4) 項「Validate() 正負向」對所有列皆標示「✅ 通用骨架」:因 OdfDocument.Validate()/
ValidateAsync() 定義於基底類別,對全部文件種類自動生效,無需逐格式重複實作或測試;正向
與負向覆蓋見 OdfValidatorApiTests.DocumentInstanceValidateAcrossSecondaryFormatKindsAllSucceed
與 DocumentInstanceValidateDetectsUnregisteredElementUnderStrictProfile。
深度狀態與限制
- 統一的
OdfDocument.Load/OdfDocument.Create與OdfDocumentFactory.LoadDocument/CreateDocument高階入口已建立。 - ODT、ODS、ODP、ODG 高階 API 已達
semantic-contract-verified:schema v4 manifest 對每個 topic 驗證完整生命週期,並逐 family 驗證既有文件、重複儲存載入、未知內容保留、 ODF 1.1~1.3 映射、結構化降版診斷、非法輸入、隨機 mutation、 corpus differential 與外部辦公軟體互通證據;使用者工作流不需下沉裸 DOM。明列非目標不屬於 此分級的未完成項目。 .ott、.ots、.otp、.otg、.odm與 Flat 變體(VAR-1 ✅):具專屬 typed 文件類別與Create/Load入口;內容編輯語意 API 繼承四主格式基底類別。2026-06-24 依 5 項完成標準 標準重新檢視後已升級為workflow-verified,詳見下方各 Batch 說明。.ott/.ots/.otp/.otg(Batch 1 第一波,2026-06-23):新增雙向範本生命週期工作流——TextDocument.CreateFromTemplate/SpreadsheetDocument.CreateFromTemplate/PresentationDocument.CreateFromTemplate/DrawingDocument.CreateFromTemplate(範本→文件, 既有)與新增的TextTemplateDocument.CreateFromDocument/SpreadsheetTemplateDocument.CreateFromDocument/PresentationTemplateDocument.CreateFromDocument/GraphicsTemplateDocument.CreateFromDocument(文件→範本,本次新增),並各補上TemplateRoundTripTests雙向往返測試與LibreOfficeInteropTests.LibreOfficeHeadlessLoadsTemplateVariantDocuments實機互通驗收。 2026-06-23 完成時依「範本內容編輯仍沿用基底格式語意 API,尚未有範本專屬深度內容模型」為 理由維持usable-variant;2026-06-24 依 5 項完成標準(高階 API、 專屬測試、round-trip/boundary/interop 證據、Validate()正負向、文件同步)重新檢視, 確認上述條件已全部滿足,升級為workflow-verified。- 文件級
OdfDocument.Validate(OdfComplianceProfile?)/ValidateAsync(...)已新增(Workstream E ✅,2026-06-23/24):所有文件種類現皆可直接呼叫實例方法驗證目前(含尚未儲存的編輯)記憶體 狀態,內部委派既有OdfValidator靜態進入點與OdfValidationReport結構化結果。因定義於OdfDocument基底類別,對全部文件種類(包含 Chart/Formula/Image/Database 等次要格式與其 Template/Flat 變體)皆通用,無需逐格式重複實作。測試見OdfValidatorApiTests.DocumentInstanceValidateReflectsUnsavedEdits、DocumentInstanceValidateAsyncReturnsStructuredReport(正向,Text)、DocumentInstanceValidateAcrossSecondaryFormatKindsAllSucceed(正向,跨 Chart/Formula/ Image/Database 驗證 API 通用性)、DocumentInstanceValidateDetectsUnregisteredElementUnderStrictProfile(負向,插入未註冊 schema 元素於嚴格設定檔下應回報失敗)。 .fodt/.fods/.fodp/.fodg(Batch 1 第二波,2026-06-23):新增型別化 Flat XML↔ZIP 雙向轉換工作流——FlatTextDocument.CreateFromDocument(TextDocument)/FlatSpreadsheetDocument.CreateFromDocument(SpreadsheetDocument)/FlatPresentationDocument.CreateFromDocument(PresentationDocument)/FlatGraphicsDocument.CreateFromDocument(DrawingDocument)(ZIP→Flat)與對應的TextDocument.CreateFromFlatDocument/SpreadsheetDocument.CreateFromFlatDocument/PresentationDocument.CreateFromFlatDocument/DrawingDocument.CreateFromFlatDocument(Flat→ZIP),共用OdfDocument.ConvertFlatVariantInternal基礎實作,呼應範本批次的CreateFromTemplate/CreateFromDocument模式。新增FlatVariantRoundTripTests雙向往返與 邊界測試,並新增LibreOfficeInteropTests.LibreOfficeHeadlessLoadsNativeFlatXmlDocuments—— 以 OdfKit 直接產生(非由 ZIP 轉換而來)的原生 FODT/FODS/FODP/FODG 檔案實機驗證 LibreOffice 26.x 可直接開啟,證明 Flat XML 與 ZIP 封裝的高階工作流對 LibreOffice 而言互通等價。 2026-06-24 依 5 項完成標準重新檢視,升級為workflow-verified(理由與範本變體相同: 上述 5 項條件已全部滿足;內容編輯仍沿用基底格式語意 API、未有 Flat 專屬深度 內容模型,但這不在最低完成標準之內)。.odm(Batch 2 第一項,2026-06-23):子文件 CRUD、條件式載入、合併為單一文件、大綱階層 位移等變體專屬 workflow 在此之前即已完備(TextMasterDocument.AddSubDocumentReference/GetSubDocumentReferences/RemoveSubDocumentReference/ReorderSubDocumentReferences/SetSubDocumentLoadOnRequest/MergeSubDocuments),本次補上:(1) 實機 LibreOffice 26.x 互通驗收——已確認 LibreOffice 將 .odm 識別為「Writer master document」並使用writerglobal8篩選器,非僅理論相容(LibreOfficeInteropTests.LibreOfficeHeadlessLoadsMasterDocument); (2) 邊界測試——子文件參照目標檔案不存在時擲出FileNotFoundException,baseDirectory為空白時擲出ArgumentException(MasterDocumentTests)。.oth(Batch 2 第二項,2026-06-23):新增型別化雙向轉換工作流TextWebDocument.CreateFromDocument(TextDocument)↔TextDocument.CreateFromWebDocument(TextWebDocument), 重用範本批次的種類/MIME 置換基礎實作。新增TextWebDocumentTests(雙向往返、高階 API 編輯、null 引數邊界);新增OdfHtmlExporterAcceptsTextWebDocumentDirectly證明OdfKit.Extensions.Html的OdfHtmlExporter.Export(TextDocument)因繼承關係可直接接受 OTH 文件,不需任何轉接層,滿足「與 HTML/export 行為一致性」要求。新增實機 LibreOffice 互通驗收——已確認 LibreOffice 將 .oth 識別為「Writer/Web document」並使用writerweb8_writer篩選器轉換為 ODT(LibreOfficeHeadlessLoadsWebTemplateDocument)。 2026-06-24 依 5 項完成標準重新檢視,升級為workflow-verified(內容模型本身與 ODT 相同、 未有專屬深度內容模型,但這不在最低完成標準之內)。.odc/.otc/.fodc(Batch 3,2026-06-23):現況調查發現既有圖表實作已遠比文件先前 描述的「摘要層」深入——OdfChartDocument早已具備軸線(對數刻度、範圍、反向、網格)、 序列、樣式(含 3D 投影、光源)、牆面/地板、股票圖標記等大量可變更高階 API。本次補上先前 明確列出但確認缺失的部分:- 新增
OdfChartSeries.FindErrorIndicator/SetErrorIndicator、FindRegressionCurve/SetRegressionCurve、FindMeanValue/SetMeanValue(對應chart:error-indicator/chart:regression-curve/chart:mean-value),新增時依 OASIS ODF 1.4 schema 規定的 子元素順序(domain、mean-value、regression-curve、error-indicator、data-point、 data-label)正確插入,避免產生不合規文件。 - 新增雙向轉換工作流
ChartTemplateDocument.CreateFromDocument(ChartDocument)↔ChartDocument.CreateFromTemplate(ChartTemplateDocument);FlatChartDocument.CreateFromDocument(ChartDocument)↔ChartDocument.CreateFromFlatDocument(FlatChartDocument),重用既有種類/MIME 置換 基礎實作。新增ChartVariantRoundTripTests(雙向往返、null 引數邊界)。 - 新增
ChartHighLevelApiTests.SeriesErrorIndicatorRegressionCurveAndMeanValueRoundTripAfterSaveAndLoad驗證上述三項 API 與其 schema 順序。 - 互通驗收的誠實負向結果:實測確認 LibreOffice 26.2.1 不支援將獨立(非嵌入
ODS/ODT/ODP)的 ODC/OTC 開啟為主文件(回報
source file could not be loaded), FODC 則被誤判為「Writer document」僅原樣回顯來源 XML,並非真正剖析。 這與既有ImageDocumentPackageStructureMatchesOdf14Schema註解中 「LibreOffice 已在 draw.xcd 註冊 ODC」的舊有假設不符——已在LibreOfficeInteropTests.OdfChartDocumentPackageStructureMatchesOdf14Schema的文件 註解中修正此假設。改以封裝結構驗證取代真機驗證,並以既有LibreOfficeHeadlessLoadsGeneratedDocuments中「圖表嵌入 ODS 後由 LibreOffice 開啟」 的驗收佐證嵌入式圖表(ODF Chart 設計上唯一的真實使用情境)的互通性。 - 2026-06-23 完成時依「仍缺 Legend 統一可編輯模型與 fluent builder API」為理由維持
usable/usable-variant;2026-06-24 依 5 項完成標準重新檢視, 確認已全部滿足,升級為workflow-verified。後續深度工作已補齊 Legend 物件模型、ChartDocument.Builder()、序列樣式 builder 與資料標籤 preset(OdfChartDataLabelPreset/WithDataLabels),目前剩餘 Chart 追蹤重點轉為更完整的跨格式 fidelity 與高階樣式 preset,而不是基礎 builder 缺口。
- 新增
.odf/.otf/.fdf(Batch 4,2026-06-23):現況調查同樣發現既有 MathML token 模型 (OdfMathToken/OdfMathBuilder,17 種 token 類型)與 LaTeX↔MathML 雙向轉換早已完整支援 row/fraction/script/table 等必要結構;本次補上確認缺失的部分:- 新增
OdfFormulaDocument.FindAnnotation/SetAnnotation,支援math:semantics/math:annotation(先前確認缺失的 annotation 結構);LoadFromLatex現會自動將 原始 LaTeX 來源附加為application/x-tex標註,ToLatex優先回傳該標註以達成精確 往返,而非僅 best-effort 由 MathML 重建。 - 修正一個既有的潛在缺陷:實作過程中發現
MathText(公式純文字摘要)直接對整個MathNode取TextContent,會將math:annotation標註文字與呈現內容文字混雜串接; 真實 LibreOffice 的math8匯出篩選器恰好就會附加 StarMath 來源標註,導致MathText回傳髒資料。已修正為僅遍歷呈現內容(略過 annotation/annotation-xml)。 - 新增雙向轉換工作流
FormulaTemplateDocument.CreateFromDocument(FormulaDocument)↔FormulaDocument.CreateFromTemplate(FormulaTemplateDocument);FlatFormulaDocument.CreateFromDocument(FormulaDocument)↔FormulaDocument.CreateFromFlatDocument(FlatFormulaDocument)。 - 修正一個會導致 Flat 公式文件遺失內容的既有缺陷:
OdfFormulaDocument為相容真實 LibreOffice ZIP 封裝慣例,GetContentXmlForPersistence一律回傳裸math:math根節點 (略過office:document-content/office:body包裹);但 Flat XML 寫入器 (OdfPackageArchiveWriter.WriteFlatXmlToStream)需要從content.xml根節點的office:body子元素取出內容才能組成單一 Flat XML 文件,因此先前任何FlatFormulaDocument存檔都會遺失公式內容(在開發本批次新增的 round-trip 測試時發現並修正:現在僅在Package.IsFlatXml為false(ZIP 封裝)時才轉換為裸根節點,Flat XML 情境維持包裹結構)。 - 新增
FormulaVariantRoundTripTests(雙向往返、邊界測試)。 - 互通驗收:實測確認獨立
.odf文件確實有真機支援——LibreOffice 26.2.1 將其識別為 「Math document」並使用math8篩選器(LibreOfficeHeadlessLoadsFormulaDocument),是 目前唯一一個獨立 ZIP 主格式有真機支援的次要格式(不同於 Chart/Image)。但.otf/.fdf變體仍與 Chart/Image 的變體一樣不受 LibreOffice 支援為獨立主文件(.otf回報 「source file could not be loaded」;.fdf被誤判為「Calc document」),改以封裝結構驗證 取代(OdfFormulaVariantDocumentPackageStructureMatchesOdf14Schema)。 - 2026-06-23 完成時依「仍缺公式語意編輯 helper(例如『尋找分數→取得分子→
更新分子』這類查詢-修改-更新 API)」為理由維持
usable/usable-variant; 2026-06-24 依 5 項完成標準重新檢視,確認已全部滿足,升級為workflow-verified。2026-06-28 已補齊OdfMathToken.FindFirst/GetAll/WithChild/ReplaceFirst與OdfFormulaDocument.ReplaceFirst,最小「尋找→取得→更新」語意編輯 helper 有程式與FormulaHighLevelApiTests證據;2026-06-29 已補齊分數/根號/上下標/矩陣的具名 符號級存取與替換 API(Numerator/Denominator/Radicand/RootIndex/Exponent/SubscriptIndex/RowCount/GetRow/GetCell/WithRow/WithCell/AddRow/RemoveRow),符號級編輯模型延伸工作已完成。
- 新增
.odi/.oti/.fodi(Batch 5,2026-06-23):現況調查發現多影像框架、版面配置、旋轉、 裁切、濾鏡與描述性 metadata(svg:title/svg:desc)等必要能力早已完整實作 (GetImageFrames/AddImageFrame/UpdateImageFrame/RemoveImageFrame/SetImageRotation/SetImageCrop/SetImageFilter);圖層與群組支援經查證為 ODF 規格層級 不支援(office:image不同於office:drawing,規格未定義 layer/group 容器),維持先前 「已查證不可行」的結論不變。主文件建議使用短名 facadeImageDocument; 既有OdfImageDocument入口仍保留相容性。本次補上確認缺失的部分:- 新增批次操作 API
ImageDocument.AddImageFrames(IEnumerable<OdfImageFrameRequest>)/RemoveImageFrames(IEnumerable<string>),對應「Frame/picture/layout 的批次操作」要求。 - 新增雙向轉換工作流
ImageTemplateDocument.CreateFromDocument(...)↔ImageDocument.CreateFromTemplate(...);FlatImageDocument.CreateFromDocument(...)↔ImageDocument.CreateFromFlatDocument(...)。新增ImageVariantRoundTripTests(雙向往返、邊界測試)。 - 修正一個既有文件註解的不準確描述:
ImageDocumentPackageStructureMatchesOdf14Schema原先聲稱 LibreOffice 對 ODI/OTI/FODI 一律回報「source file could not be loaded」; 實測確認此描述對 ODI/OTI 成立,但 FODI 實際上被誤判為「Writer document」,以writer_png_Export篩選器產生與影像內容完全無關的輸出,與.fodc(誤判為 Writer document)、.fdf(誤判為 Calc document)的誤判模式一致。已修正文件註解用語,並擴充該 測試涵蓋 ODI/OTI/FODI 三者的封裝結構驗證(先前僅涵蓋 ODI)。 - 2026-06-23 完成時依「Template/Flat 變體內容編輯仍沿用基底格式語意 API,未有專屬深度
內容模型」為理由維持
usable/usable-variant;2026-06-24 依 5 項完成標準 重新檢視,確認已全部滿足,升級為workflow-verified(理由與 Chart/Formula 相同:深度內容模型差異不在最低完成標準之內)。
- 新增批次操作 API
.odb(Batch 6,2026-06-23):現況調查確認 Database 已具備資料來源、查詢、表單與報表等 常見工作流能力, 並無比照 Chart(Legend 物件模型與資料標籤 preset)那樣明確追蹤的延伸項目; Formula 的最小語意編輯 helper 已另有程式與測試證據, 經評估後依使用者先前確認的「ODB workflow-verified 標準採真實可用工作流為準」決策,升級為workflow-verified。主文件建議使用短名 facadeDatabaseDocument;既有OdfDatabaseDocument入口仍保留相容性:- 資料來源:連線 href、登入(
DatabaseDocument.GetLogin/SetLogin)、驅動程式設定 (GetDriverSettings/SetDriverSettings)。 - 查詢:SQL 命令、
ORDER BY/WHERE陳述式、可見欄位、更新目標表、escape processing (DatabaseDocument繼承的查詢 API,實作位於OdfDatabaseDocument.Queries.cs)。 - 表單:完整表單設計器
OdfDatabaseFormDesigner,涵蓋文字框、核取方塊、選項按鈕、下拉 選單、列表框、按鈕、標籤、群組框、數值/日期/時間欄位,並支援事件繫結與必填/長度驗證。 - 報表:因官方 OASIS ODF schema 並未定義報表內容結構(先前以虛構命名空間
urn:oasis:names:tc:opendocument:xmlns:report:1.0推測的設計已查證不可行並移除),改以AddReport的href參照機制連結至獨立TextDocument(搭配text:database-display/text:database-next欄位),這是真實可用且符合規格的作法。 - Schema 導覽與 mutation:
OdfDatabaseSchema提供資料表、欄位、主鍵、外鍵、索引的完整 CRUD(先前基於推測的「ODB 檢視表定義」已查證不可行並移除)。 - 互通驗收:實機重新驗證(2026-06-23)發現 LibreOffice 26.2.1 headless 的
--convert-to對 ODB 的失效模式比先前記錄更隱晦——轉換目標為odb時明確回報 「no export filter」,但轉換目標為txt/ods/xlsx/csv時卻以結束碼 0 成功, 實際上只是逐位元組原樣複製來源檔案、並未真正轉換(已修正LibreOfficeInteropTests.DatabaseSchemaPackageUsesLibreOfficeCompatibleMimeType的文件 註解用語)。改以封裝層級 mimetype/manifest 驗證搭配先前已完成的 LibreOffice UNO API (desktop.loadComponentFromURL)人工驗證佐證真實載入能力。 - 邊界測試:新增
DatabaseBoundaryTests,涵蓋AddTable/AddQuery空白名稱或命令時 擲出ArgumentException、RemoveTable/RemoveQuery/RemoveDataSourceSetting對不存在 名稱回傳false、FindTable/FindQuery/FindDataSourceSetting對不存在名稱回傳null。 - Template/Flat 變體:ODF 規格設計上即未定義 ODB 的 template 或 flat XML 變體(不同於 其他七個格式族),故「變體專屬 workflow」此項不適用(N/A),非缺口。
- 資料來源:連線 href、登入(
- ODT
text:tracked-changes已支援段落與表格儲存格插入/格式變更記錄;LO 互通測試已備(TrackedChangesInteropTests)。 - ODS
table:tracked-changes已支援儲存格內容/公式變更、列/欄插入刪除與儲存格移動;LO 互通測試已新增(需本機 LibreOffice 26.x)。 - ODG 已補強路徑、多邊形、連接線(含
draw:points路由)、自定義幾何、群組、圖層、文字方塊、圖片與圖層指派讀取 API(GetPaths/GetConnectors/GetPolygons/GetCustomShapes/GetGroups/GetLayers/GetTextBoxes/GetPictures/GetShapeLayerAssignments);測試見DrawingHighLevelApiTests。 - ODC/嵌入圖表已補強
OdfChartDocument.GetChartDefinition;ODB 已補強AddForm/GetForms表單元件 API(DatabaseHighLevelApiTests)。 - ODF 已補強
GetMathTokens讀取 API;ODI 已補強GetImageFrames/AddImageFrame(FormulaHighLevelApiTests、ImageHighLevelApiTests)。 calcext條件格式/sparkline 寫入已實作;CALCEXT-1 基礎 ✅:工作表層與SpreadsheetDocument.GetConditionalFormats/GetSparklineGroups文件層聚合讀取。- 密碼保護文件的 manifest 契約符合 ODF 1.0~1.4 Part 2 §4.16:
manifest:checksum-type為urn:oasis:names:tc:opendocument:xmlns:manifest:1.0#sha256-1k,內容是壓縮後未加密資料 前 1024 位元組的摘要;解密端另接受SHA1/1K、#sha1-1k與早期 OdfKit 版本的完整摘要形狀。encryption-data只輸出checksum-type與checksum,子元素依 algorithm →〔start-key-generation〕→ key-derivation 排列。AES-256-CBC 與 Blowfish 產出的META-INF/manifest.xml已以 Jing 對官方OpenDocument-v1.4-manifest-schema.rng實測通過。 Blowfish CFB依實作而非規範字面:規範 §4.16.1 的文字是「8-bit CFB」,但被它標準化的 OpenOffice.org 實作用的是整個 64 位元區塊回饋 —— LibreOffice 的sal/rtl/cipher.cxx對rtl_Cipher_ModeStream呼叫 OpenSSLEVP_bf_cfb()(即EVP_bf_cfb64()),其自有 fallbackBF_updateCFB同樣是每 8 個位元組重新加密一次 IV、再逐位元組 XOR。既有檔案都是這個形狀, OdfKit 因此採 CFB-64;此結論另由 LibreOffice 26.2 實機產生的加密文件逐項目解密確認。 這是規範文字與參考實作的落差,不是實作偏離規範。- 可選屬性的規範預設:
manifest:start-key-generation缺席時採 SHA-1(LibreOffice 的傳統加密 文件不輸出該元素);manifest:key-size缺席時依演算法推導(Blowfish 16、AES-256 32)。 PBKDF2 反覆運算次數上限放寬至OdfEncryption.MaxPbkdf2IterationCount(10,000,000)以容納 LibreOffice 寫入的 100,000 次與 OWASP 的現行建議;OdfKit 自身寫入採DefaultPbkdf2IterationCount(100,000)。 - Argon2id 金鑰衍生(AES-256-GCM 路徑)屬 extended package 功能,形狀對標 LibreOffice 的
OpenDocument-v1.4+libreoffice-manifest-schema.rng:manifest:key-derivation-name為urn:org:documentfoundation:names:experimental:office:manifest:argon2id,參數為loext:argon2-iterations/loext:argon2-memory/loext:argon2-lanes,且不輸出manifest:iteration-count。該 manifest 已以 Jing 對 LibreOffice schema 實測通過;官方 ODF 1.4 manifest schema 未定義 Argon2,因此不會(也不應)通過官方 schema。解密端另接受早期 OdfKit 版本的argon2-t/-m/-p與非標準 URI。
與 LibreOffice 加密文件的互通現況
以 LibreOffice 26.2.4.2 實機產生與開啟的檔案驗證:
OdfKit 讀取 LibreOffice 的加密文件
| LibreOffice 儲存設定 | 封裝形狀 | OdfKit 讀取 |
|---|---|---|
| ODF 1.4(預設,wholesome encryption) | 單一 encrypted-package entry、AES-256-GCM、Argon2id、無 checksum |
✅ 載入時自動展開內層封裝 |
| ODF 1.2/1.3(傳統逐項目加密) | 每個 entry 各自加密、AES-256-CBC、#sha256-1k、PBKDF2 100,000 次 |
✅ 全部 entry 可正確解密並取得原始內容 |
| ODF 1.0/1.1(傳統逐項目加密) | 每個 entry 各自加密、Blowfish CFB、SHA1/1K、PBKDF2 100,000 次、無 key-size/start-key-generation |
✅ 全部 entry 可正確解密並取得原始內容 |
整包加密(wholesome)的形狀(以 LibreOffice 26.2 實機產出驗證,實作見
OdfWholesomeEncryption):ZIP 只含 mimetype、encrypted-package 與 META-INF/manifest.xml;
encrypted-package 的位元組是 IV(12) ‖ AES-256-GCM 密文 ‖ tag(16)(IV 內嵌於開頭,
manifest:initialisation-vector 為重複資訊),解密後為 deflate 過的內層完整 ODF 封裝,
inflate 後大小等於 manifest:size。金鑰為 Argon2id(SHA-256(密碼), salt),不使用逐項目 checksum——
完整性由 AEAD tag 提供。OdfKit 在載入時偵測此形狀並展開內層封裝,之後的操作與一般封裝相同;
寫入時選用 OdfEncryptionAlgorithm.Aes256Gcm 會建立相同的 wholesome 外層封裝。
LibreOffice 讀取 OdfKit 的加密文件
| OdfKit 加密演算法 | LibreOffice 26.2 開啟 |
|---|---|
Blowfish CFB(--encryption blowfish) |
✅ 可開啟並取得完整內容 |
AES-256-CBC(--encryption aes256,預設) |
✅ 可開啟並取得完整內容 |
| AES-256-GCM + Argon2id(wholesome) | ✅ 產出單一 encrypted-package,可由 LibreOffice 開啟 |
達成雙向互通的關鍵有兩項,兩者都是規範明確、OdfKit 先前實作錯誤:
- 加密項目必須以 ZIP
STORED寫出。內容在加密前已 deflate,密文不可再壓縮;先前多包一層 ZIP DEFLATE,LibreOffice 的加密讀取路徑會拿到非預期的位元組。 PBKDF2的虛擬亂數函式固定為 HMAC-SHA-1(Part 2 §4.16.7),與start-key-generation-name無關 —— 後者只決定密碼如何雜湊成 start key。先前把兩者綁在一起, AES 路徑誤用 HMAC-SHA-256。Blowfish 因 start key 恰好也是 SHA-1 而未暴露此問題。 解密端保留 HMAC-SHA-256 後備路徑,既有的 OdfKit 加密檔仍可讀取。
讀取方向已納入 CI:tests/fixtures/encryption-interop/ 收錄 LibreOffice 26.2 實機產生的三份
加密素材(Blowfish CFB、AES-256-CBC 與 wholesome AES-256-GCM)及其加密參數 manifest,由
EncryptionInteropCorpusTests 驗證解密結果、參數契約與載入後重新儲存;素材已提交,因此
不需要本機 LibreOffice 即可在 CI 執行,並掛在主 CI 的 core-security 煙霧分片。
還原任一項修正都會讓對應素材失敗(已實測)。
寫入方向已納入專用排程驗證:libreoffice-interop.yml 在同一個 Windows runner 安裝一次
LibreOffice 26.2,依序以 net8.0 與 net10.0 執行 UNO 測試,開啟 OdfKit 產生的 wholesome ODT
並核對本文;缺少 Python UNO runtime 時該排程會失敗,不會以略過偽裝成功。
odf-external-baseline.yml 另由目前 CLI 產生 wholesome 封裝,抽出 manifest 後以固定版本、
固定 SHA-256 的 LibreOffice extended schema 與 Jing 作阻擋驗證。
已知缺口:
- OpenPGP 寫入已改為 ODF 1.4 Part 2 的封裝形狀:整個 package 共用 256-bit session key,
entry 先 deflate、以壓縮後未加密資料前 1024 bytes 計算
#sha256-1k,再以 AES-256-CBC 加密並以 ZIPSTORED儲存。收件人的完整 OpenPGP encrypted message 位於根層manifest:encrypted-key/CipherData/CipherValue,entry 的 key derivation 只宣告PGP。OpenPgpExternalInteropTests以臨時真實 RSA 金鑰確認 GnuPG 能解出 OdfKit session key,odf-external-baseline.yml再以 Jing 驗證執行期產生的 manifest。 - 反向讀取完整 RFC 4880 OpenPGP message、LibrePGP tag 20 v1 AES-OCB message 與早期 OdfKit 單一 PKESK payload 均保留。tag 20 由 OdfKit 驗證分塊與 final authentication tag, 因為 BouncyCastle.Cryptography 2.7.0 的高階 OpenPGP parser 尚未支援此封包;實機測試 強制 GnuPG 2.5.21 產生 tag 20,並確認末端竄改會遭拒絕。
LibreOfficeUnoOpenPgpRealKeyBidirectionalRoundTrip以臨時 RSA 金鑰驗證 OdfKit 寫入後 LibreOffice 26.2.4.2 可解密並重新儲存;LibreOffice 轉出的 wholesome AES-256-GCM + OpenPGP key transport 封裝再由 OdfKit 解密,且核對 LibreOffice 新增內容與根層manifest:encrypted-key。此測試由每週雙 TFM workflow 強制執行。.odc、.odb、.odf、.odi已納入 schema v4 深度語意證據契約: ODC 補齊單一序列移除,ODB 補齊 table/query 更新與集合清除,ODF 補齊 token 移除與清除, ODI 補齊保留框架版面/替代文字時的影像內容替換;既有圖表樣式、資料庫 schema、 MathML 符號樹與影像效果 API 均納入逐操作證據。ODI 的多框架操作屬 extended-document 工作流;ODF 1.4 嚴格 ODI 仍是單一draw:frame包含單一draw:image,不宣稱圖層或群組。- 次要格式與變體高階物件模型補完工作(原 Batch 1-6 + 測試補強,已於 2026-06-23 全數完成並移除
追蹤文件):ODC/ODB/ODI/ODF 公式四項次要格式高階物件模型,以及範本變數系統
(
text:user-field-decls)、範本清除使用者資料、範本區段唯讀標記、ODM 主控文件子文件 CRUD 完整化/條件式載入/合併為單一文件/大綱階層位移、Flat XML ↔ ZIP 就地轉換 API 與 大型文件記憶體優化。原規劃中基於推測而非實際 schema 查證的項目(ODB 檢視表定義、 報表詳細設計、ODI 中繼資料擴充與分組圖層)已查證為不可行並從規劃中移除。 - RDF-1 基礎 ✅:
manifest.rdf文件層往返、pkg:ontology 同步;corpus 含repo-generated-manifest-rdf-text(RdfMetadataTests)。 - LOEXT-1 基礎 ✅:
loext:decorative載入映射至draw:decorative(OdfLoExtInteropEngine、LoExtInteropTests)。 - repo 內 corpus 已擴充至 266 筆 fixtures(
tools/OdfCorpusGenerator+ 手工負向/版本特例,詳見 Corpus Manifest 規則); 外部 ODF Validator baseline corpus 仍可依ODFKIT_PARITY_CORPUS_ROOT選用擴充。 - Typed DOM 已新增
office:text、table:table、draw:page、office:presentation/office:drawing與次格式office:chart/office:image/office:database/office:spreadsheetcontent model facade(Wave 1 M-3);tools/OdfSchemaGenerator/oasis-odf14-dom-wrappers.json供手動重產 DOM wrappers。