@cj-tech-master/excelts 9.5.4 → 9.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (767) hide show
  1. package/dist/browser/modules/archive/compression/streaming-compress.browser.js +29 -0
  2. package/dist/browser/modules/archive/compression/streaming-compress.js +9 -0
  3. package/dist/browser/modules/archive/compression/worker-pool/pool.browser.js +26 -1
  4. package/dist/browser/modules/archive/fs/archive-file.d.ts +8 -5
  5. package/dist/browser/modules/archive/fs/archive-file.js +78 -16
  6. package/dist/browser/modules/archive/unzip/stream.browser.js +43 -2
  7. package/dist/browser/modules/excel/chart/chart-ex-builder.js +7 -2
  8. package/dist/browser/modules/excel/chart/chart-ex-renderer.js +4 -9
  9. package/dist/browser/modules/excel/chart/chart-ex-types.d.ts +0 -12
  10. package/dist/browser/modules/excel/chart/chart.d.ts +1 -5
  11. package/dist/browser/modules/excel/chart/chart.js +1 -7
  12. package/dist/browser/modules/excel/chart/types.d.ts +0 -6
  13. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +25 -1
  14. package/dist/browser/modules/excel/stream/workbook-reader.js +9 -0
  15. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +40 -0
  16. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +228 -13
  17. package/dist/browser/modules/excel/utils/string-buf.d.ts +5 -26
  18. package/dist/browser/modules/excel/utils/string-buf.js +4 -81
  19. package/dist/browser/modules/excel/workbook.browser.js +135 -25
  20. package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.js +6 -20
  21. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +19 -9
  22. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +32 -8
  23. package/dist/browser/modules/excel/xlsx/xlsx.d.ts +10 -2
  24. package/dist/browser/modules/excel/xlsx/xlsx.js +9 -1
  25. package/dist/browser/modules/pdf/excel-bridge.d.ts +30 -1
  26. package/dist/browser/modules/pdf/excel-bridge.js +32 -0
  27. package/dist/browser/modules/pdf/font/metrics.d.ts +3 -52
  28. package/dist/browser/modules/pdf/font/metrics.js +3 -237
  29. package/dist/browser/modules/pdf/index.d.ts +1 -1
  30. package/dist/browser/modules/pdf/index.js +1 -1
  31. package/dist/browser/modules/pdf/render-layout-to-pdf.d.ts +66 -0
  32. package/dist/browser/modules/pdf/render-layout-to-pdf.js +647 -0
  33. package/dist/browser/modules/pdf/word-bridge.d.ts +80 -12
  34. package/dist/browser/modules/pdf/word-bridge.js +122 -274
  35. package/dist/browser/modules/stream/index.base.d.ts +2 -0
  36. package/dist/browser/modules/stream/index.base.js +2 -1
  37. package/dist/browser/modules/stream/internal/sink-adapter.d.ts +65 -0
  38. package/dist/browser/modules/stream/internal/sink-adapter.js +198 -0
  39. package/dist/browser/modules/stream/pull-stream.d.ts +19 -2
  40. package/dist/browser/modules/stream/pull-stream.js +51 -5
  41. package/dist/browser/modules/stream/types.d.ts +13 -1
  42. package/dist/browser/modules/word/advanced/diff.d.ts +61 -0
  43. package/dist/browser/modules/word/advanced/diff.js +167 -0
  44. package/dist/browser/modules/word/advanced/drawing-shapes.d.ts +269 -0
  45. package/dist/browser/modules/word/advanced/drawing-shapes.js +268 -0
  46. package/dist/browser/modules/word/advanced/field-engine.d.ts +43 -0
  47. package/dist/browser/modules/word/advanced/field-engine.js +1225 -0
  48. package/dist/browser/modules/word/advanced/glossary.d.ts +86 -0
  49. package/dist/browser/modules/word/advanced/glossary.js +79 -0
  50. package/dist/browser/modules/word/advanced/math-convert.d.ts +30 -0
  51. package/dist/browser/modules/word/advanced/math-convert.js +595 -0
  52. package/dist/browser/modules/word/advanced/ole-objects.d.ts +115 -0
  53. package/dist/browser/modules/word/advanced/ole-objects.js +271 -0
  54. package/dist/browser/modules/word/advanced/style-map.d.ts +105 -0
  55. package/dist/browser/modules/word/advanced/style-map.js +322 -0
  56. package/dist/browser/modules/word/advanced/validation.d.ts +56 -0
  57. package/dist/browser/modules/word/advanced/validation.js +1065 -0
  58. package/dist/browser/modules/word/advanced/vba-project.d.ts +91 -0
  59. package/dist/browser/modules/word/advanced/vba-project.js +265 -0
  60. package/dist/browser/modules/word/bridge/excel-bridge.d.ts +127 -0
  61. package/dist/browser/modules/word/bridge/excel-bridge.js +980 -0
  62. package/dist/browser/modules/word/builder/document-handle.d.ts +151 -0
  63. package/dist/browser/modules/word/builder/document-handle.js +664 -0
  64. package/dist/browser/modules/word/builder/paragraph-builders.d.ts +61 -0
  65. package/dist/browser/modules/word/builder/paragraph-builders.js +90 -0
  66. package/dist/browser/modules/word/builder/run-builders.d.ts +374 -0
  67. package/dist/browser/modules/word/builder/run-builders.js +600 -0
  68. package/dist/browser/modules/word/builder/table-builders.d.ts +23 -0
  69. package/dist/browser/modules/word/builder/table-builders.js +45 -0
  70. package/dist/browser/modules/word/constants.d.ts +39 -1
  71. package/dist/browser/modules/word/constants.js +109 -1
  72. package/dist/browser/modules/word/convert/conversion-ir.d.ts +210 -0
  73. package/dist/browser/modules/word/convert/conversion-ir.js +31 -0
  74. package/dist/browser/modules/word/convert/docx-to-semantic.d.ts +39 -0
  75. package/dist/browser/modules/word/convert/docx-to-semantic.js +499 -0
  76. package/dist/browser/modules/word/convert/flat-opc.d.ts +44 -0
  77. package/dist/browser/modules/word/convert/flat-opc.js +385 -0
  78. package/dist/browser/modules/word/convert/html/html-import.d.ts +50 -0
  79. package/dist/browser/modules/word/convert/html/html-import.js +1907 -0
  80. package/dist/{types/modules/word → browser/modules/word/convert/html}/html-renderer.d.ts +14 -1
  81. package/dist/{esm/modules/word → browser/modules/word/convert/html}/html-renderer.js +420 -69
  82. package/dist/browser/modules/word/convert/html/html.d.ts +15 -0
  83. package/dist/browser/modules/word/convert/html/html.js +15 -0
  84. package/dist/browser/modules/word/convert/markdown/markdown-import.d.ts +68 -0
  85. package/dist/browser/modules/word/convert/markdown/markdown-import.js +1325 -0
  86. package/dist/browser/modules/word/convert/markdown/markdown-renderer.d.ts +25 -0
  87. package/dist/browser/modules/word/convert/markdown/markdown-renderer.js +634 -0
  88. package/dist/browser/modules/word/convert/markdown/markdown.d.ts +15 -0
  89. package/dist/browser/modules/word/convert/markdown/markdown.js +15 -0
  90. package/dist/browser/modules/word/convert/odt/odt.d.ts +41 -0
  91. package/dist/browser/modules/word/convert/odt/odt.js +1932 -0
  92. package/dist/browser/modules/word/{color-utils.d.ts → core/color-utils.d.ts} +8 -1
  93. package/dist/browser/modules/word/core/color-utils.js +43 -0
  94. package/dist/browser/modules/word/core/internal-utils.d.ts +90 -0
  95. package/dist/browser/modules/word/core/internal-utils.js +209 -0
  96. package/dist/browser/modules/word/core/mapper.d.ts +44 -0
  97. package/dist/browser/modules/word/core/mapper.js +427 -0
  98. package/dist/browser/modules/word/core/opc-paths.d.ts +33 -0
  99. package/dist/browser/modules/word/core/opc-paths.js +48 -0
  100. package/dist/browser/modules/word/core/text-utils.d.ts +38 -0
  101. package/dist/browser/modules/word/core/text-utils.js +202 -0
  102. package/dist/browser/modules/word/core/walker.d.ts +119 -0
  103. package/dist/browser/modules/word/core/walker.js +570 -0
  104. package/dist/browser/modules/word/crypto.d.ts +14 -9
  105. package/dist/browser/modules/word/crypto.js +13 -7
  106. package/dist/browser/modules/word/document-io.d.ts +59 -27
  107. package/dist/browser/modules/word/document-io.js +80 -197
  108. package/dist/browser/modules/word/errors.d.ts +44 -1
  109. package/dist/browser/modules/word/errors.js +54 -2
  110. package/dist/browser/modules/word/excel.d.ts +14 -0
  111. package/dist/browser/modules/word/excel.js +13 -0
  112. package/dist/browser/modules/word/font/font-embed.d.ts +112 -0
  113. package/dist/browser/modules/word/font/font-embed.js +646 -0
  114. package/dist/{esm/modules/word → browser/modules/word/font}/font-obfuscation.js +4 -9
  115. package/dist/browser/modules/word/font/hyphenation.d.ts +65 -0
  116. package/dist/browser/modules/word/font/hyphenation.js +4210 -0
  117. package/dist/browser/modules/word/font/text-shaping.d.ts +58 -0
  118. package/dist/browser/modules/word/font/text-shaping.js +635 -0
  119. package/dist/browser/modules/word/html.d.ts +7 -6
  120. package/dist/browser/modules/word/html.js +6 -5
  121. package/dist/browser/modules/word/incremental-edit.d.ts +123 -0
  122. package/dist/browser/modules/word/incremental-edit.js +361 -0
  123. package/dist/browser/modules/word/index.base.d.ts +194 -10
  124. package/dist/browser/modules/word/index.base.js +138 -29
  125. package/dist/browser/modules/word/layout/layout-constants.d.ts +17 -0
  126. package/dist/browser/modules/word/layout/layout-constants.js +17 -0
  127. package/dist/browser/modules/word/layout/layout-full.d.ts +53 -0
  128. package/dist/browser/modules/word/layout/layout-full.js +1696 -0
  129. package/dist/browser/modules/word/layout/layout-model.d.ts +344 -0
  130. package/dist/browser/modules/word/layout/layout-model.js +16 -0
  131. package/dist/browser/modules/word/layout/layout.d.ts +63 -0
  132. package/dist/browser/modules/word/layout/layout.js +1167 -0
  133. package/dist/browser/modules/word/layout/render-page.d.ts +57 -0
  134. package/dist/browser/modules/word/layout/render-page.js +1238 -0
  135. package/dist/browser/modules/word/markdown.d.ts +14 -0
  136. package/dist/browser/modules/word/markdown.js +13 -0
  137. package/dist/browser/modules/word/patcher.d.ts +62 -0
  138. package/dist/browser/modules/word/patcher.js +537 -0
  139. package/dist/browser/modules/word/query/compat.d.ts +25 -0
  140. package/dist/browser/modules/word/query/compat.js +58 -0
  141. package/dist/browser/modules/word/query/data-binding.d.ts +22 -0
  142. package/dist/browser/modules/word/query/data-binding.js +392 -0
  143. package/dist/browser/modules/word/query/form-fields.d.ts +41 -0
  144. package/dist/browser/modules/word/query/form-fields.js +268 -0
  145. package/dist/browser/modules/word/query/format-search.d.ts +99 -0
  146. package/dist/browser/modules/word/query/format-search.js +329 -0
  147. package/dist/browser/modules/word/query/mail-merge.d.ts +25 -0
  148. package/dist/browser/modules/word/query/mail-merge.js +111 -0
  149. package/dist/browser/modules/word/query/merge.d.ts +50 -0
  150. package/dist/browser/modules/word/query/merge.js +617 -0
  151. package/dist/browser/modules/word/query/replace.d.ts +47 -0
  152. package/dist/browser/modules/word/query/replace.js +301 -0
  153. package/dist/browser/modules/word/query/revisions.d.ts +67 -0
  154. package/dist/browser/modules/word/query/revisions.js +879 -0
  155. package/dist/browser/modules/word/query/search.d.ts +129 -0
  156. package/dist/browser/modules/word/query/search.js +346 -0
  157. package/dist/browser/modules/word/query/split.d.ts +44 -0
  158. package/dist/browser/modules/word/query/split.js +135 -0
  159. package/dist/browser/modules/word/query/style-resolve.d.ts +104 -0
  160. package/dist/browser/modules/word/query/style-resolve.js +368 -0
  161. package/dist/browser/modules/word/reader/chart-parser.d.ts +20 -0
  162. package/dist/browser/modules/word/reader/chart-parser.js +810 -0
  163. package/dist/browser/modules/word/reader/comments-parser.d.ts +26 -0
  164. package/dist/browser/modules/word/reader/comments-parser.js +92 -0
  165. package/dist/browser/modules/word/reader/doc-props-parsers.d.ts +15 -0
  166. package/dist/browser/modules/word/reader/doc-props-parsers.js +190 -0
  167. package/dist/browser/modules/word/reader/docx-reader.d.ts +27 -0
  168. package/dist/browser/modules/word/reader/docx-reader.js +2557 -0
  169. package/dist/browser/modules/word/reader/drawing-helpers.d.ts +27 -0
  170. package/dist/browser/modules/word/reader/drawing-helpers.js +84 -0
  171. package/dist/browser/modules/word/reader/form-field-parser.d.ts +21 -0
  172. package/dist/browser/modules/word/reader/form-field-parser.js +82 -0
  173. package/dist/browser/modules/word/reader/image-parsers.d.ts +11 -0
  174. package/dist/browser/modules/word/reader/image-parsers.js +291 -0
  175. package/dist/browser/modules/word/reader/math-parser.d.ts +12 -0
  176. package/dist/browser/modules/word/reader/math-parser.js +422 -0
  177. package/dist/browser/modules/word/reader/metadata-parsers.d.ts +17 -0
  178. package/dist/browser/modules/word/reader/metadata-parsers.js +87 -0
  179. package/dist/browser/modules/word/reader/numbering-parser.d.ts +13 -0
  180. package/dist/browser/modules/word/reader/numbering-parser.js +166 -0
  181. package/dist/browser/modules/word/reader/paragraph-section-parsers.d.ts +12 -0
  182. package/dist/browser/modules/word/reader/paragraph-section-parsers.js +503 -0
  183. package/dist/browser/modules/word/reader/parse-utils.d.ts +91 -0
  184. package/dist/browser/modules/word/reader/parse-utils.js +249 -0
  185. package/dist/browser/modules/word/reader/properties-parsers.d.ts +21 -0
  186. package/dist/browser/modules/word/reader/properties-parsers.js +332 -0
  187. package/dist/browser/modules/word/reader/reader-context.d.ts +69 -0
  188. package/dist/browser/modules/word/reader/reader-context.js +61 -0
  189. package/dist/browser/modules/word/reader/sdt-helpers.d.ts +29 -0
  190. package/dist/browser/modules/word/reader/sdt-helpers.js +111 -0
  191. package/dist/browser/modules/word/reader/settings-parser.d.ts +8 -0
  192. package/dist/browser/modules/word/reader/settings-parser.js +263 -0
  193. package/dist/browser/modules/word/reader/styles-parser.d.ts +12 -0
  194. package/dist/browser/modules/word/reader/styles-parser.js +147 -0
  195. package/dist/browser/modules/word/reader/table-properties-parsers.d.ts +12 -0
  196. package/dist/browser/modules/word/reader/table-properties-parsers.js +234 -0
  197. package/dist/browser/modules/word/reader/theme-parser.d.ts +8 -0
  198. package/dist/browser/modules/word/reader/theme-parser.js +167 -0
  199. package/dist/browser/modules/word/reader/watermark-parser.d.ts +15 -0
  200. package/dist/browser/modules/word/reader/watermark-parser.js +110 -0
  201. package/dist/browser/modules/word/security/cfb-reader.d.ts +37 -0
  202. package/dist/browser/modules/word/security/cfb-reader.js +410 -0
  203. package/dist/browser/modules/word/{digital-signatures.d.ts → security/digital-signatures.d.ts} +19 -11
  204. package/dist/browser/modules/word/{digital-signatures.js → security/digital-signatures.js} +34 -34
  205. package/dist/browser/modules/word/security/document-protection.d.ts +93 -0
  206. package/dist/browser/modules/word/security/document-protection.js +201 -0
  207. package/dist/{types/modules/word → browser/modules/word/security}/encryption.d.ts +51 -4
  208. package/dist/browser/modules/word/security/encryption.js +602 -0
  209. package/dist/browser/modules/word/security/policy.d.ts +80 -0
  210. package/dist/browser/modules/word/security/policy.js +102 -0
  211. package/dist/browser/modules/word/template/template-chart.d.ts +56 -0
  212. package/dist/browser/modules/word/template/template-chart.js +167 -0
  213. package/dist/browser/modules/word/template/template-datasource.d.ts +154 -0
  214. package/dist/browser/modules/word/template/template-datasource.js +541 -0
  215. package/dist/browser/modules/word/template/template-engine.d.ts +121 -0
  216. package/dist/browser/modules/word/template/template-engine.js +1435 -0
  217. package/dist/browser/modules/word/types.d.ts +224 -25
  218. package/dist/browser/modules/word/units.d.ts +26 -0
  219. package/dist/browser/modules/word/units.js +43 -14
  220. package/dist/browser/modules/word/{writers → writer}/chart-writer.js +164 -23
  221. package/dist/browser/modules/word/writer/checkbox-writer.d.ts +17 -0
  222. package/dist/browser/modules/word/writer/checkbox-writer.js +79 -0
  223. package/dist/{types/modules/word/writers → browser/modules/word/writer}/comment-writer.d.ts +2 -1
  224. package/dist/browser/modules/word/{writers → writer}/comment-writer.js +8 -6
  225. package/dist/browser/modules/word/writer/common-parts.d.ts +57 -0
  226. package/dist/browser/modules/word/writer/common-parts.js +101 -0
  227. package/dist/{types/modules/word → browser/modules/word/writer}/content-types.d.ts +2 -2
  228. package/dist/{esm/modules/word → browser/modules/word/writer}/content-types.js +14 -6
  229. package/dist/browser/modules/word/writer/document-writer.d.ts +24 -0
  230. package/dist/browser/modules/word/writer/document-writer.js +473 -0
  231. package/dist/browser/modules/word/writer/docx-packager.d.ts +35 -0
  232. package/dist/browser/modules/word/writer/docx-packager.js +1515 -0
  233. package/dist/{types/modules/word/writers → browser/modules/word/writer}/footnote-writer.d.ts +3 -2
  234. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/footnote-writer.js +13 -10
  235. package/dist/{types/modules/word/writers → browser/modules/word/writer}/header-footer-writer.d.ts +3 -2
  236. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/header-footer-writer.js +39 -21
  237. package/dist/{types/modules/word/writers → browser/modules/word/writer}/image-writer.d.ts +1 -1
  238. package/dist/browser/modules/word/{writers → writer}/image-writer.js +11 -7
  239. package/dist/browser/modules/word/writer/math-writer.d.ts +20 -0
  240. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/math-writer.js +21 -1
  241. package/dist/browser/modules/word/{writers → writer}/numbering-writer.d.ts +1 -1
  242. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/numbering-writer.js +11 -4
  243. package/dist/browser/modules/word/{writers → writer}/paragraph-writer.d.ts +2 -1
  244. package/dist/browser/modules/word/{writers → writer}/paragraph-writer.js +73 -38
  245. package/dist/browser/modules/word/{writers → writer}/parts-writer.d.ts +3 -3
  246. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/parts-writer.js +91 -12
  247. package/dist/browser/modules/word/writer/reference-scanners.d.ts +42 -0
  248. package/dist/browser/modules/word/writer/reference-scanners.js +111 -0
  249. package/dist/browser/modules/word/writer/relationships.d.ts +52 -0
  250. package/dist/browser/modules/word/writer/relationships.js +117 -0
  251. package/dist/browser/modules/word/writer/render-context.d.ts +124 -0
  252. package/dist/browser/modules/word/writer/render-context.js +46 -0
  253. package/dist/browser/modules/word/{writers → writer}/run-writer.d.ts +10 -1
  254. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/run-writer.js +126 -24
  255. package/dist/browser/modules/word/writer/sdt-writer.d.ts +25 -0
  256. package/dist/browser/modules/word/writer/sdt-writer.js +189 -0
  257. package/dist/browser/modules/word/writer/stream-buf.d.ts +37 -0
  258. package/dist/browser/modules/word/writer/stream-buf.js +73 -0
  259. package/dist/browser/modules/word/writer/streaming-writer.d.ts +344 -0
  260. package/dist/browser/modules/word/writer/streaming-writer.js +1382 -0
  261. package/dist/browser/modules/word/writer/string-buf.d.ts +8 -0
  262. package/dist/browser/modules/word/writer/string-buf.js +7 -0
  263. package/dist/browser/modules/word/{writers → writer}/styles-writer.js +32 -1
  264. package/dist/browser/modules/word/{writers → writer}/table-writer.d.ts +2 -1
  265. package/dist/browser/modules/word/{writers → writer}/table-writer.js +94 -11
  266. package/dist/browser/modules/xml/types.d.ts +22 -0
  267. package/dist/browser/utils/crypto.browser.d.ts +3 -1
  268. package/dist/browser/utils/crypto.browser.js +3 -1
  269. package/dist/browser/utils/crypto.d.ts +4 -1
  270. package/dist/browser/utils/crypto.js +4 -1
  271. package/dist/browser/utils/font-metrics.d.ts +63 -0
  272. package/dist/browser/utils/font-metrics.js +293 -0
  273. package/dist/browser/utils/string-buf.d.ts +42 -0
  274. package/dist/browser/utils/string-buf.js +89 -0
  275. package/dist/browser/utils/theme-colors.d.ts +55 -0
  276. package/dist/browser/utils/theme-colors.js +120 -0
  277. package/dist/cjs/modules/archive/compression/streaming-compress.browser.js +29 -0
  278. package/dist/cjs/modules/archive/compression/streaming-compress.js +9 -0
  279. package/dist/cjs/modules/archive/compression/worker-pool/pool.browser.js +26 -1
  280. package/dist/cjs/modules/archive/fs/archive-file.js +78 -16
  281. package/dist/cjs/modules/archive/unzip/stream.browser.js +43 -2
  282. package/dist/cjs/modules/excel/chart/chart-ex-builder.js +7 -2
  283. package/dist/cjs/modules/excel/chart/chart-ex-renderer.js +4 -9
  284. package/dist/cjs/modules/excel/chart/chart.js +1 -7
  285. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +25 -1
  286. package/dist/cjs/modules/excel/stream/workbook-reader.js +9 -0
  287. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +228 -13
  288. package/dist/cjs/modules/excel/utils/string-buf.js +5 -81
  289. package/dist/cjs/modules/excel/workbook.browser.js +135 -25
  290. package/dist/cjs/modules/excel/xlsx/xform/chart/chart-space-xform.js +6 -20
  291. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +32 -8
  292. package/dist/cjs/modules/excel/xlsx/xlsx.js +9 -1
  293. package/dist/cjs/modules/pdf/excel-bridge.js +33 -0
  294. package/dist/cjs/modules/pdf/font/metrics.js +11 -244
  295. package/dist/cjs/modules/pdf/index.js +2 -1
  296. package/dist/cjs/modules/pdf/render-layout-to-pdf.js +651 -0
  297. package/dist/cjs/modules/pdf/word-bridge.js +155 -274
  298. package/dist/cjs/modules/stream/index.base.js +4 -2
  299. package/dist/cjs/modules/stream/internal/sink-adapter.js +202 -0
  300. package/dist/cjs/modules/stream/pull-stream.js +51 -5
  301. package/dist/cjs/modules/word/advanced/diff.js +170 -0
  302. package/dist/cjs/modules/word/advanced/drawing-shapes.js +279 -0
  303. package/dist/cjs/modules/word/advanced/field-engine.js +1229 -0
  304. package/dist/cjs/modules/word/advanced/glossary.js +87 -0
  305. package/dist/cjs/modules/word/advanced/math-convert.js +599 -0
  306. package/dist/cjs/modules/word/advanced/ole-objects.js +277 -0
  307. package/dist/cjs/modules/word/advanced/style-map.js +329 -0
  308. package/dist/cjs/modules/word/advanced/validation.js +1068 -0
  309. package/dist/cjs/modules/word/advanced/vba-project.js +274 -0
  310. package/dist/cjs/modules/word/bridge/excel-bridge.js +1020 -0
  311. package/dist/cjs/modules/word/builder/document-handle.js +667 -0
  312. package/dist/cjs/modules/word/builder/paragraph-builders.js +109 -0
  313. package/dist/cjs/modules/word/builder/run-builders.js +676 -0
  314. package/dist/cjs/modules/word/builder/table-builders.js +53 -0
  315. package/dist/cjs/modules/word/constants.js +111 -2
  316. package/dist/cjs/modules/word/convert/conversion-ir.js +34 -0
  317. package/dist/cjs/modules/word/convert/docx-to-semantic.js +502 -0
  318. package/dist/cjs/modules/word/convert/flat-opc.js +390 -0
  319. package/dist/cjs/modules/word/convert/html/html-import.js +1910 -0
  320. package/dist/cjs/modules/word/{html-renderer.js → convert/html/html-renderer.js} +420 -69
  321. package/dist/cjs/modules/word/convert/html/html.js +20 -0
  322. package/dist/cjs/modules/word/convert/markdown/markdown-import.js +1329 -0
  323. package/dist/cjs/modules/word/convert/markdown/markdown-renderer.js +637 -0
  324. package/dist/cjs/modules/word/convert/markdown/markdown.js +21 -0
  325. package/dist/cjs/modules/word/convert/odt/odt.js +1936 -0
  326. package/dist/cjs/modules/word/core/color-utils.js +47 -0
  327. package/dist/cjs/modules/word/core/internal-utils.js +219 -0
  328. package/dist/cjs/modules/word/core/mapper.js +430 -0
  329. package/dist/cjs/modules/word/core/opc-paths.js +53 -0
  330. package/dist/cjs/modules/word/core/text-utils.js +210 -0
  331. package/dist/cjs/modules/word/core/walker.js +577 -0
  332. package/dist/cjs/modules/word/crypto.js +19 -8
  333. package/dist/cjs/modules/word/document-io.js +117 -197
  334. package/dist/cjs/modules/word/errors.js +59 -13
  335. package/dist/cjs/modules/word/excel.js +22 -0
  336. package/dist/cjs/modules/word/font/font-embed.js +652 -0
  337. package/dist/cjs/modules/word/{font-obfuscation.js → font/font-obfuscation.js} +4 -9
  338. package/dist/cjs/modules/word/font/hyphenation.js +4216 -0
  339. package/dist/cjs/modules/word/font/text-shaping.js +640 -0
  340. package/dist/cjs/modules/word/html.js +9 -7
  341. package/dist/cjs/modules/word/incremental-edit.js +366 -0
  342. package/dist/cjs/modules/word/index.base.js +370 -137
  343. package/dist/cjs/modules/word/layout/layout-constants.js +20 -0
  344. package/dist/cjs/modules/word/layout/layout-full.js +1699 -0
  345. package/dist/cjs/modules/word/layout/layout-model.js +17 -0
  346. package/dist/cjs/modules/word/layout/layout.js +1170 -0
  347. package/dist/cjs/modules/word/layout/render-page.js +1243 -0
  348. package/dist/cjs/modules/word/markdown.js +19 -0
  349. package/dist/cjs/modules/word/patcher.js +539 -0
  350. package/dist/cjs/modules/word/query/compat.js +61 -0
  351. package/dist/cjs/modules/word/query/data-binding.js +395 -0
  352. package/dist/cjs/modules/word/query/form-fields.js +272 -0
  353. package/dist/cjs/modules/word/query/format-search.js +334 -0
  354. package/dist/cjs/modules/word/query/mail-merge.js +114 -0
  355. package/dist/cjs/modules/word/query/merge.js +620 -0
  356. package/dist/cjs/modules/word/query/replace.js +304 -0
  357. package/dist/cjs/modules/word/query/revisions.js +885 -0
  358. package/dist/cjs/modules/word/query/search.js +361 -0
  359. package/dist/cjs/modules/word/query/split.js +138 -0
  360. package/dist/cjs/modules/word/query/style-resolve.js +374 -0
  361. package/dist/cjs/modules/word/reader/chart-parser.js +814 -0
  362. package/dist/cjs/modules/word/reader/comments-parser.js +96 -0
  363. package/dist/cjs/modules/word/reader/doc-props-parsers.js +194 -0
  364. package/dist/cjs/modules/word/reader/docx-reader.js +2560 -0
  365. package/dist/cjs/modules/word/reader/drawing-helpers.js +90 -0
  366. package/dist/cjs/modules/word/reader/form-field-parser.js +85 -0
  367. package/dist/cjs/modules/word/reader/image-parsers.js +293 -0
  368. package/dist/cjs/modules/word/reader/math-parser.js +424 -0
  369. package/dist/cjs/modules/word/reader/metadata-parsers.js +93 -0
  370. package/dist/cjs/modules/word/reader/numbering-parser.js +168 -0
  371. package/dist/cjs/modules/word/reader/paragraph-section-parsers.js +505 -0
  372. package/dist/cjs/modules/word/reader/parse-utils.js +271 -0
  373. package/dist/cjs/modules/word/reader/properties-parsers.js +338 -0
  374. package/dist/cjs/modules/word/reader/reader-context.js +66 -0
  375. package/dist/cjs/modules/word/reader/sdt-helpers.js +114 -0
  376. package/dist/cjs/modules/word/reader/settings-parser.js +265 -0
  377. package/dist/cjs/modules/word/reader/styles-parser.js +149 -0
  378. package/dist/cjs/modules/word/reader/table-properties-parsers.js +237 -0
  379. package/dist/cjs/modules/word/reader/theme-parser.js +169 -0
  380. package/dist/cjs/modules/word/reader/watermark-parser.js +113 -0
  381. package/dist/cjs/modules/word/security/cfb-reader.js +414 -0
  382. package/dist/cjs/modules/word/{digital-signatures.js → security/digital-signatures.js} +34 -34
  383. package/dist/cjs/modules/word/security/document-protection.js +208 -0
  384. package/dist/cjs/modules/word/security/encryption.js +612 -0
  385. package/dist/cjs/modules/word/security/policy.js +106 -0
  386. package/dist/cjs/modules/word/template/template-chart.js +170 -0
  387. package/dist/cjs/modules/word/template/template-datasource.js +549 -0
  388. package/dist/cjs/modules/word/template/template-engine.js +1430 -0
  389. package/dist/cjs/modules/word/units.js +44 -14
  390. package/dist/cjs/modules/word/{writers → writer}/chart-writer.js +163 -22
  391. package/dist/cjs/modules/word/writer/checkbox-writer.js +82 -0
  392. package/dist/cjs/modules/word/{writers → writer}/comment-writer.js +8 -6
  393. package/dist/cjs/modules/word/writer/common-parts.js +104 -0
  394. package/dist/cjs/modules/word/{content-types.js → writer/content-types.js} +14 -6
  395. package/dist/cjs/modules/word/writer/document-writer.js +478 -0
  396. package/dist/cjs/modules/word/writer/docx-packager.js +1551 -0
  397. package/dist/cjs/modules/word/{writers → writer}/footnote-writer.js +13 -10
  398. package/dist/cjs/modules/word/{writers → writer}/header-footer-writer.js +38 -20
  399. package/dist/cjs/modules/word/{writers → writer}/image-writer.js +11 -7
  400. package/dist/cjs/modules/word/{writers → writer}/math-writer.js +21 -1
  401. package/dist/cjs/modules/word/{writers → writer}/numbering-writer.js +11 -4
  402. package/dist/cjs/modules/word/{writers → writer}/paragraph-writer.js +72 -37
  403. package/dist/cjs/modules/word/{writers → writer}/parts-writer.js +91 -12
  404. package/dist/cjs/modules/word/writer/reference-scanners.js +120 -0
  405. package/dist/cjs/modules/word/writer/relationships.js +124 -0
  406. package/dist/cjs/modules/word/writer/render-context.js +51 -0
  407. package/dist/cjs/modules/word/{writers → writer}/run-writer.js +127 -24
  408. package/dist/cjs/modules/word/writer/sdt-writer.js +192 -0
  409. package/dist/cjs/modules/word/writer/stream-buf.js +76 -0
  410. package/dist/cjs/modules/word/writer/streaming-writer.js +1387 -0
  411. package/dist/cjs/modules/word/writer/string-buf.js +11 -0
  412. package/dist/cjs/modules/word/{writers → writer}/styles-writer.js +32 -1
  413. package/dist/cjs/modules/word/{writers → writer}/table-writer.js +94 -11
  414. package/dist/cjs/utils/crypto.browser.js +3 -1
  415. package/dist/cjs/utils/crypto.js +4 -1
  416. package/dist/cjs/utils/font-metrics.js +303 -0
  417. package/dist/cjs/utils/string-buf.js +92 -0
  418. package/dist/cjs/utils/theme-colors.js +126 -0
  419. package/dist/esm/modules/archive/compression/streaming-compress.browser.js +29 -0
  420. package/dist/esm/modules/archive/compression/streaming-compress.js +9 -0
  421. package/dist/esm/modules/archive/compression/worker-pool/pool.browser.js +26 -1
  422. package/dist/esm/modules/archive/fs/archive-file.js +78 -16
  423. package/dist/esm/modules/archive/unzip/stream.browser.js +43 -2
  424. package/dist/esm/modules/excel/chart/chart-ex-builder.js +7 -2
  425. package/dist/esm/modules/excel/chart/chart-ex-renderer.js +4 -9
  426. package/dist/esm/modules/excel/chart/chart.js +1 -7
  427. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +25 -1
  428. package/dist/esm/modules/excel/stream/workbook-reader.js +9 -0
  429. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +228 -13
  430. package/dist/esm/modules/excel/utils/string-buf.js +4 -81
  431. package/dist/esm/modules/excel/workbook.browser.js +135 -25
  432. package/dist/esm/modules/excel/xlsx/xform/chart/chart-space-xform.js +6 -20
  433. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +32 -8
  434. package/dist/esm/modules/excel/xlsx/xlsx.js +9 -1
  435. package/dist/esm/modules/pdf/excel-bridge.js +32 -0
  436. package/dist/esm/modules/pdf/font/metrics.js +3 -237
  437. package/dist/esm/modules/pdf/index.js +1 -1
  438. package/dist/esm/modules/pdf/render-layout-to-pdf.js +647 -0
  439. package/dist/esm/modules/pdf/word-bridge.js +122 -274
  440. package/dist/esm/modules/stream/index.base.js +2 -1
  441. package/dist/esm/modules/stream/internal/sink-adapter.js +198 -0
  442. package/dist/esm/modules/stream/pull-stream.js +51 -5
  443. package/dist/esm/modules/word/advanced/diff.js +167 -0
  444. package/dist/esm/modules/word/advanced/drawing-shapes.js +268 -0
  445. package/dist/esm/modules/word/advanced/field-engine.js +1225 -0
  446. package/dist/esm/modules/word/advanced/glossary.js +79 -0
  447. package/dist/esm/modules/word/advanced/math-convert.js +595 -0
  448. package/dist/esm/modules/word/advanced/ole-objects.js +271 -0
  449. package/dist/esm/modules/word/advanced/style-map.js +322 -0
  450. package/dist/esm/modules/word/advanced/validation.js +1065 -0
  451. package/dist/esm/modules/word/advanced/vba-project.js +265 -0
  452. package/dist/esm/modules/word/bridge/excel-bridge.js +980 -0
  453. package/dist/esm/modules/word/builder/document-handle.js +664 -0
  454. package/dist/esm/modules/word/builder/paragraph-builders.js +90 -0
  455. package/dist/esm/modules/word/builder/run-builders.js +600 -0
  456. package/dist/esm/modules/word/builder/table-builders.js +45 -0
  457. package/dist/esm/modules/word/constants.js +109 -1
  458. package/dist/esm/modules/word/convert/conversion-ir.js +31 -0
  459. package/dist/esm/modules/word/convert/docx-to-semantic.js +499 -0
  460. package/dist/esm/modules/word/convert/flat-opc.js +385 -0
  461. package/dist/esm/modules/word/convert/html/html-import.js +1907 -0
  462. package/dist/{browser/modules/word → esm/modules/word/convert/html}/html-renderer.js +420 -69
  463. package/dist/esm/modules/word/convert/html/html.js +15 -0
  464. package/dist/esm/modules/word/convert/markdown/markdown-import.js +1325 -0
  465. package/dist/esm/modules/word/convert/markdown/markdown-renderer.js +634 -0
  466. package/dist/esm/modules/word/convert/markdown/markdown.js +15 -0
  467. package/dist/esm/modules/word/convert/odt/odt.js +1932 -0
  468. package/dist/esm/modules/word/core/color-utils.js +43 -0
  469. package/dist/esm/modules/word/core/internal-utils.js +209 -0
  470. package/dist/esm/modules/word/core/mapper.js +427 -0
  471. package/dist/esm/modules/word/core/opc-paths.js +48 -0
  472. package/dist/esm/modules/word/core/text-utils.js +202 -0
  473. package/dist/esm/modules/word/core/walker.js +570 -0
  474. package/dist/esm/modules/word/crypto.js +13 -7
  475. package/dist/esm/modules/word/document-io.js +80 -197
  476. package/dist/esm/modules/word/errors.js +54 -2
  477. package/dist/esm/modules/word/excel.js +13 -0
  478. package/dist/esm/modules/word/font/font-embed.js +646 -0
  479. package/dist/{browser/modules/word → esm/modules/word/font}/font-obfuscation.js +4 -9
  480. package/dist/esm/modules/word/font/hyphenation.js +4210 -0
  481. package/dist/esm/modules/word/font/text-shaping.js +635 -0
  482. package/dist/esm/modules/word/html.js +6 -5
  483. package/dist/esm/modules/word/incremental-edit.js +361 -0
  484. package/dist/esm/modules/word/index.base.js +138 -29
  485. package/dist/esm/modules/word/layout/layout-constants.js +17 -0
  486. package/dist/esm/modules/word/layout/layout-full.js +1696 -0
  487. package/dist/esm/modules/word/layout/layout-model.js +16 -0
  488. package/dist/esm/modules/word/layout/layout.js +1167 -0
  489. package/dist/esm/modules/word/layout/render-page.js +1238 -0
  490. package/dist/esm/modules/word/markdown.js +13 -0
  491. package/dist/esm/modules/word/patcher.js +537 -0
  492. package/dist/esm/modules/word/query/compat.js +58 -0
  493. package/dist/esm/modules/word/query/data-binding.js +392 -0
  494. package/dist/esm/modules/word/query/form-fields.js +268 -0
  495. package/dist/esm/modules/word/query/format-search.js +329 -0
  496. package/dist/esm/modules/word/query/mail-merge.js +111 -0
  497. package/dist/esm/modules/word/query/merge.js +617 -0
  498. package/dist/esm/modules/word/query/replace.js +301 -0
  499. package/dist/esm/modules/word/query/revisions.js +879 -0
  500. package/dist/esm/modules/word/query/search.js +346 -0
  501. package/dist/esm/modules/word/query/split.js +135 -0
  502. package/dist/esm/modules/word/query/style-resolve.js +368 -0
  503. package/dist/esm/modules/word/reader/chart-parser.js +810 -0
  504. package/dist/esm/modules/word/reader/comments-parser.js +92 -0
  505. package/dist/esm/modules/word/reader/doc-props-parsers.js +190 -0
  506. package/dist/esm/modules/word/reader/docx-reader.js +2557 -0
  507. package/dist/esm/modules/word/reader/drawing-helpers.js +84 -0
  508. package/dist/esm/modules/word/reader/form-field-parser.js +82 -0
  509. package/dist/esm/modules/word/reader/image-parsers.js +291 -0
  510. package/dist/esm/modules/word/reader/math-parser.js +422 -0
  511. package/dist/esm/modules/word/reader/metadata-parsers.js +87 -0
  512. package/dist/esm/modules/word/reader/numbering-parser.js +166 -0
  513. package/dist/esm/modules/word/reader/paragraph-section-parsers.js +503 -0
  514. package/dist/esm/modules/word/reader/parse-utils.js +249 -0
  515. package/dist/esm/modules/word/reader/properties-parsers.js +332 -0
  516. package/dist/esm/modules/word/reader/reader-context.js +61 -0
  517. package/dist/esm/modules/word/reader/sdt-helpers.js +111 -0
  518. package/dist/esm/modules/word/reader/settings-parser.js +263 -0
  519. package/dist/esm/modules/word/reader/styles-parser.js +147 -0
  520. package/dist/esm/modules/word/reader/table-properties-parsers.js +234 -0
  521. package/dist/esm/modules/word/reader/theme-parser.js +167 -0
  522. package/dist/esm/modules/word/reader/watermark-parser.js +110 -0
  523. package/dist/esm/modules/word/security/cfb-reader.js +410 -0
  524. package/dist/esm/modules/word/{digital-signatures.js → security/digital-signatures.js} +34 -34
  525. package/dist/esm/modules/word/security/document-protection.js +201 -0
  526. package/dist/esm/modules/word/security/encryption.js +602 -0
  527. package/dist/esm/modules/word/security/policy.js +102 -0
  528. package/dist/esm/modules/word/template/template-chart.js +167 -0
  529. package/dist/esm/modules/word/template/template-datasource.js +541 -0
  530. package/dist/esm/modules/word/template/template-engine.js +1435 -0
  531. package/dist/esm/modules/word/units.js +43 -14
  532. package/dist/esm/modules/word/{writers → writer}/chart-writer.js +164 -23
  533. package/dist/esm/modules/word/writer/checkbox-writer.js +79 -0
  534. package/dist/esm/modules/word/{writers → writer}/comment-writer.js +8 -6
  535. package/dist/esm/modules/word/writer/common-parts.js +101 -0
  536. package/dist/{browser/modules/word → esm/modules/word/writer}/content-types.js +14 -6
  537. package/dist/esm/modules/word/writer/document-writer.js +473 -0
  538. package/dist/esm/modules/word/writer/docx-packager.js +1515 -0
  539. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/footnote-writer.js +13 -10
  540. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/header-footer-writer.js +39 -21
  541. package/dist/esm/modules/word/{writers → writer}/image-writer.js +11 -7
  542. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/math-writer.js +21 -1
  543. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/numbering-writer.js +11 -4
  544. package/dist/esm/modules/word/{writers → writer}/paragraph-writer.js +73 -38
  545. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/parts-writer.js +91 -12
  546. package/dist/esm/modules/word/writer/reference-scanners.js +111 -0
  547. package/dist/esm/modules/word/writer/relationships.js +117 -0
  548. package/dist/esm/modules/word/writer/render-context.js +46 -0
  549. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/run-writer.js +126 -24
  550. package/dist/esm/modules/word/writer/sdt-writer.js +189 -0
  551. package/dist/esm/modules/word/writer/stream-buf.js +73 -0
  552. package/dist/esm/modules/word/writer/streaming-writer.js +1382 -0
  553. package/dist/esm/modules/word/writer/string-buf.js +7 -0
  554. package/dist/esm/modules/word/{writers → writer}/styles-writer.js +32 -1
  555. package/dist/esm/modules/word/{writers → writer}/table-writer.js +94 -11
  556. package/dist/esm/utils/crypto.browser.js +3 -1
  557. package/dist/esm/utils/crypto.js +4 -1
  558. package/dist/esm/utils/font-metrics.js +293 -0
  559. package/dist/esm/utils/string-buf.js +89 -0
  560. package/dist/esm/utils/theme-colors.js +120 -0
  561. package/dist/iife/excelts.iife.js +70692 -70337
  562. package/dist/iife/excelts.iife.js.map +1 -1
  563. package/dist/iife/excelts.iife.min.js +57 -57
  564. package/dist/types/modules/archive/fs/archive-file.d.ts +8 -5
  565. package/dist/types/modules/excel/chart/chart-ex-types.d.ts +0 -12
  566. package/dist/types/modules/excel/chart/chart.d.ts +1 -5
  567. package/dist/types/modules/excel/chart/types.d.ts +0 -6
  568. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +40 -0
  569. package/dist/types/modules/excel/utils/string-buf.d.ts +5 -26
  570. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +19 -9
  571. package/dist/types/modules/excel/xlsx/xlsx.d.ts +10 -2
  572. package/dist/types/modules/pdf/excel-bridge.d.ts +30 -1
  573. package/dist/types/modules/pdf/font/metrics.d.ts +3 -52
  574. package/dist/types/modules/pdf/index.d.ts +1 -1
  575. package/dist/types/modules/pdf/render-layout-to-pdf.d.ts +66 -0
  576. package/dist/types/modules/pdf/word-bridge.d.ts +80 -12
  577. package/dist/types/modules/stream/index.base.d.ts +2 -0
  578. package/dist/types/modules/stream/internal/sink-adapter.d.ts +65 -0
  579. package/dist/types/modules/stream/pull-stream.d.ts +19 -2
  580. package/dist/types/modules/stream/types.d.ts +13 -1
  581. package/dist/types/modules/word/advanced/diff.d.ts +61 -0
  582. package/dist/types/modules/word/advanced/drawing-shapes.d.ts +269 -0
  583. package/dist/types/modules/word/advanced/field-engine.d.ts +43 -0
  584. package/dist/types/modules/word/advanced/glossary.d.ts +86 -0
  585. package/dist/types/modules/word/advanced/math-convert.d.ts +30 -0
  586. package/dist/types/modules/word/advanced/ole-objects.d.ts +115 -0
  587. package/dist/types/modules/word/advanced/style-map.d.ts +105 -0
  588. package/dist/types/modules/word/advanced/validation.d.ts +56 -0
  589. package/dist/types/modules/word/advanced/vba-project.d.ts +91 -0
  590. package/dist/types/modules/word/bridge/excel-bridge.d.ts +127 -0
  591. package/dist/types/modules/word/builder/document-handle.d.ts +151 -0
  592. package/dist/types/modules/word/builder/paragraph-builders.d.ts +61 -0
  593. package/dist/types/modules/word/builder/run-builders.d.ts +374 -0
  594. package/dist/types/modules/word/builder/table-builders.d.ts +23 -0
  595. package/dist/types/modules/word/constants.d.ts +39 -1
  596. package/dist/types/modules/word/convert/conversion-ir.d.ts +210 -0
  597. package/dist/types/modules/word/convert/docx-to-semantic.d.ts +39 -0
  598. package/dist/types/modules/word/convert/flat-opc.d.ts +44 -0
  599. package/dist/types/modules/word/convert/html/html-import.d.ts +50 -0
  600. package/dist/{browser/modules/word → types/modules/word/convert/html}/html-renderer.d.ts +14 -1
  601. package/dist/types/modules/word/convert/html/html.d.ts +15 -0
  602. package/dist/types/modules/word/convert/markdown/markdown-import.d.ts +68 -0
  603. package/dist/types/modules/word/convert/markdown/markdown-renderer.d.ts +25 -0
  604. package/dist/types/modules/word/convert/markdown/markdown.d.ts +15 -0
  605. package/dist/types/modules/word/convert/odt/odt.d.ts +41 -0
  606. package/dist/types/modules/word/{color-utils.d.ts → core/color-utils.d.ts} +8 -1
  607. package/dist/types/modules/word/core/internal-utils.d.ts +90 -0
  608. package/dist/types/modules/word/core/mapper.d.ts +44 -0
  609. package/dist/types/modules/word/core/opc-paths.d.ts +33 -0
  610. package/dist/types/modules/word/core/text-utils.d.ts +38 -0
  611. package/dist/types/modules/word/core/walker.d.ts +119 -0
  612. package/dist/types/modules/word/crypto.d.ts +14 -9
  613. package/dist/types/modules/word/document-io.d.ts +59 -27
  614. package/dist/types/modules/word/errors.d.ts +44 -1
  615. package/dist/types/modules/word/excel.d.ts +14 -0
  616. package/dist/types/modules/word/font/font-embed.d.ts +112 -0
  617. package/dist/types/modules/word/font/hyphenation.d.ts +65 -0
  618. package/dist/types/modules/word/font/text-shaping.d.ts +58 -0
  619. package/dist/types/modules/word/html.d.ts +7 -6
  620. package/dist/types/modules/word/incremental-edit.d.ts +123 -0
  621. package/dist/types/modules/word/index.base.d.ts +194 -10
  622. package/dist/types/modules/word/layout/layout-constants.d.ts +17 -0
  623. package/dist/types/modules/word/layout/layout-full.d.ts +53 -0
  624. package/dist/types/modules/word/layout/layout-model.d.ts +344 -0
  625. package/dist/types/modules/word/layout/layout.d.ts +63 -0
  626. package/dist/types/modules/word/layout/render-page.d.ts +57 -0
  627. package/dist/types/modules/word/markdown.d.ts +14 -0
  628. package/dist/types/modules/word/patcher.d.ts +62 -0
  629. package/dist/types/modules/word/query/compat.d.ts +25 -0
  630. package/dist/types/modules/word/query/data-binding.d.ts +22 -0
  631. package/dist/types/modules/word/query/form-fields.d.ts +41 -0
  632. package/dist/types/modules/word/query/format-search.d.ts +99 -0
  633. package/dist/types/modules/word/query/mail-merge.d.ts +25 -0
  634. package/dist/types/modules/word/query/merge.d.ts +50 -0
  635. package/dist/types/modules/word/query/replace.d.ts +47 -0
  636. package/dist/types/modules/word/query/revisions.d.ts +67 -0
  637. package/dist/types/modules/word/query/search.d.ts +129 -0
  638. package/dist/types/modules/word/query/split.d.ts +44 -0
  639. package/dist/types/modules/word/query/style-resolve.d.ts +104 -0
  640. package/dist/types/modules/word/reader/chart-parser.d.ts +20 -0
  641. package/dist/types/modules/word/reader/comments-parser.d.ts +26 -0
  642. package/dist/types/modules/word/reader/doc-props-parsers.d.ts +15 -0
  643. package/dist/types/modules/word/reader/docx-reader.d.ts +27 -0
  644. package/dist/types/modules/word/reader/drawing-helpers.d.ts +27 -0
  645. package/dist/types/modules/word/reader/form-field-parser.d.ts +21 -0
  646. package/dist/types/modules/word/reader/image-parsers.d.ts +11 -0
  647. package/dist/types/modules/word/reader/math-parser.d.ts +12 -0
  648. package/dist/types/modules/word/reader/metadata-parsers.d.ts +17 -0
  649. package/dist/types/modules/word/reader/numbering-parser.d.ts +13 -0
  650. package/dist/types/modules/word/reader/paragraph-section-parsers.d.ts +12 -0
  651. package/dist/types/modules/word/reader/parse-utils.d.ts +91 -0
  652. package/dist/types/modules/word/reader/properties-parsers.d.ts +21 -0
  653. package/dist/types/modules/word/reader/reader-context.d.ts +69 -0
  654. package/dist/types/modules/word/reader/sdt-helpers.d.ts +29 -0
  655. package/dist/types/modules/word/reader/settings-parser.d.ts +8 -0
  656. package/dist/types/modules/word/reader/styles-parser.d.ts +12 -0
  657. package/dist/types/modules/word/reader/table-properties-parsers.d.ts +12 -0
  658. package/dist/types/modules/word/reader/theme-parser.d.ts +8 -0
  659. package/dist/types/modules/word/reader/watermark-parser.d.ts +15 -0
  660. package/dist/types/modules/word/security/cfb-reader.d.ts +37 -0
  661. package/dist/types/modules/word/{digital-signatures.d.ts → security/digital-signatures.d.ts} +19 -11
  662. package/dist/types/modules/word/security/document-protection.d.ts +93 -0
  663. package/dist/{browser/modules/word → types/modules/word/security}/encryption.d.ts +51 -4
  664. package/dist/types/modules/word/security/policy.d.ts +80 -0
  665. package/dist/types/modules/word/template/template-chart.d.ts +56 -0
  666. package/dist/types/modules/word/template/template-datasource.d.ts +154 -0
  667. package/dist/types/modules/word/template/template-engine.d.ts +121 -0
  668. package/dist/types/modules/word/types.d.ts +224 -25
  669. package/dist/types/modules/word/units.d.ts +26 -0
  670. package/dist/types/modules/word/writer/checkbox-writer.d.ts +17 -0
  671. package/dist/{browser/modules/word/writers → types/modules/word/writer}/comment-writer.d.ts +2 -1
  672. package/dist/types/modules/word/writer/common-parts.d.ts +57 -0
  673. package/dist/{browser/modules/word → types/modules/word/writer}/content-types.d.ts +2 -2
  674. package/dist/types/modules/word/writer/document-writer.d.ts +24 -0
  675. package/dist/types/modules/word/writer/docx-packager.d.ts +35 -0
  676. package/dist/{browser/modules/word/writers → types/modules/word/writer}/footnote-writer.d.ts +3 -2
  677. package/dist/{browser/modules/word/writers → types/modules/word/writer}/header-footer-writer.d.ts +3 -2
  678. package/dist/{browser/modules/word/writers → types/modules/word/writer}/image-writer.d.ts +1 -1
  679. package/dist/types/modules/word/writer/math-writer.d.ts +20 -0
  680. package/dist/types/modules/word/{writers → writer}/numbering-writer.d.ts +1 -1
  681. package/dist/types/modules/word/{writers → writer}/paragraph-writer.d.ts +2 -1
  682. package/dist/types/modules/word/{writers → writer}/parts-writer.d.ts +3 -3
  683. package/dist/types/modules/word/writer/reference-scanners.d.ts +42 -0
  684. package/dist/types/modules/word/writer/relationships.d.ts +52 -0
  685. package/dist/types/modules/word/writer/render-context.d.ts +124 -0
  686. package/dist/types/modules/word/{writers → writer}/run-writer.d.ts +10 -1
  687. package/dist/types/modules/word/writer/sdt-writer.d.ts +25 -0
  688. package/dist/types/modules/word/writer/stream-buf.d.ts +37 -0
  689. package/dist/types/modules/word/writer/streaming-writer.d.ts +344 -0
  690. package/dist/types/modules/word/writer/string-buf.d.ts +8 -0
  691. package/dist/types/modules/word/{writers → writer}/table-writer.d.ts +2 -1
  692. package/dist/types/modules/xml/types.d.ts +22 -0
  693. package/dist/types/utils/crypto.browser.d.ts +3 -1
  694. package/dist/types/utils/crypto.d.ts +4 -1
  695. package/dist/types/utils/font-metrics.d.ts +63 -0
  696. package/dist/types/utils/string-buf.d.ts +42 -0
  697. package/dist/types/utils/theme-colors.d.ts +55 -0
  698. package/package.json +121 -39
  699. package/dist/browser/modules/word/color-utils.js +0 -94
  700. package/dist/browser/modules/word/document.d.ts +0 -657
  701. package/dist/browser/modules/word/document.js +0 -1533
  702. package/dist/browser/modules/word/docx-packager.d.ts +0 -14
  703. package/dist/browser/modules/word/docx-packager.js +0 -822
  704. package/dist/browser/modules/word/docx-reader.d.ts +0 -11
  705. package/dist/browser/modules/word/docx-reader.js +0 -4929
  706. package/dist/browser/modules/word/encryption.js +0 -274
  707. package/dist/browser/modules/word/internal-utils.d.ts +0 -23
  708. package/dist/browser/modules/word/internal-utils.js +0 -54
  709. package/dist/browser/modules/word/namespaces.d.ts +0 -159
  710. package/dist/browser/modules/word/namespaces.js +0 -189
  711. package/dist/browser/modules/word/relationships.d.ts +0 -30
  712. package/dist/browser/modules/word/relationships.js +0 -48
  713. package/dist/browser/modules/word/writers/checkbox-writer.d.ts +0 -9
  714. package/dist/browser/modules/word/writers/checkbox-writer.js +0 -42
  715. package/dist/browser/modules/word/writers/document-writer.d.ts +0 -16
  716. package/dist/browser/modules/word/writers/document-writer.js +0 -461
  717. package/dist/browser/modules/word/writers/math-writer.d.ts +0 -9
  718. package/dist/cjs/modules/word/color-utils.js +0 -97
  719. package/dist/cjs/modules/word/document.js +0 -1645
  720. package/dist/cjs/modules/word/docx-packager.js +0 -825
  721. package/dist/cjs/modules/word/docx-reader.js +0 -4932
  722. package/dist/cjs/modules/word/encryption.js +0 -282
  723. package/dist/cjs/modules/word/internal-utils.js +0 -59
  724. package/dist/cjs/modules/word/namespaces.js +0 -192
  725. package/dist/cjs/modules/word/relationships.js +0 -55
  726. package/dist/cjs/modules/word/writers/checkbox-writer.js +0 -45
  727. package/dist/cjs/modules/word/writers/document-writer.js +0 -465
  728. package/dist/esm/modules/word/color-utils.js +0 -94
  729. package/dist/esm/modules/word/document.js +0 -1533
  730. package/dist/esm/modules/word/docx-packager.js +0 -822
  731. package/dist/esm/modules/word/docx-reader.js +0 -4929
  732. package/dist/esm/modules/word/encryption.js +0 -274
  733. package/dist/esm/modules/word/internal-utils.js +0 -54
  734. package/dist/esm/modules/word/namespaces.js +0 -189
  735. package/dist/esm/modules/word/relationships.js +0 -48
  736. package/dist/esm/modules/word/writers/checkbox-writer.js +0 -42
  737. package/dist/esm/modules/word/writers/document-writer.js +0 -461
  738. package/dist/types/modules/word/document.d.ts +0 -657
  739. package/dist/types/modules/word/docx-packager.d.ts +0 -14
  740. package/dist/types/modules/word/docx-reader.d.ts +0 -11
  741. package/dist/types/modules/word/internal-utils.d.ts +0 -23
  742. package/dist/types/modules/word/namespaces.d.ts +0 -159
  743. package/dist/types/modules/word/relationships.d.ts +0 -30
  744. package/dist/types/modules/word/writers/checkbox-writer.d.ts +0 -9
  745. package/dist/types/modules/word/writers/document-writer.d.ts +0 -16
  746. package/dist/types/modules/word/writers/math-writer.d.ts +0 -9
  747. /package/dist/browser/modules/word/{font-obfuscation.d.ts → font/font-obfuscation.d.ts} +0 -0
  748. /package/dist/browser/modules/word/{writers → writer}/chart-writer.d.ts +0 -0
  749. /package/dist/browser/modules/word/{writers → writer}/section-writer.d.ts +0 -0
  750. /package/dist/browser/modules/word/{writers → writer}/section-writer.js +0 -0
  751. /package/dist/browser/modules/word/{writers → writer}/styles-writer.d.ts +0 -0
  752. /package/dist/browser/modules/word/{writers → writer}/textbox-writer.d.ts +0 -0
  753. /package/dist/browser/modules/word/{writers → writer}/textbox-writer.js +0 -0
  754. /package/dist/browser/modules/word/{writers → writer}/toc-writer.d.ts +0 -0
  755. /package/dist/browser/modules/word/{writers → writer}/toc-writer.js +0 -0
  756. /package/dist/cjs/modules/word/{writers → writer}/section-writer.js +0 -0
  757. /package/dist/cjs/modules/word/{writers → writer}/textbox-writer.js +0 -0
  758. /package/dist/cjs/modules/word/{writers → writer}/toc-writer.js +0 -0
  759. /package/dist/esm/modules/word/{writers → writer}/section-writer.js +0 -0
  760. /package/dist/esm/modules/word/{writers → writer}/textbox-writer.js +0 -0
  761. /package/dist/esm/modules/word/{writers → writer}/toc-writer.js +0 -0
  762. /package/dist/types/modules/word/{font-obfuscation.d.ts → font/font-obfuscation.d.ts} +0 -0
  763. /package/dist/types/modules/word/{writers → writer}/chart-writer.d.ts +0 -0
  764. /package/dist/types/modules/word/{writers → writer}/section-writer.d.ts +0 -0
  765. /package/dist/types/modules/word/{writers → writer}/styles-writer.d.ts +0 -0
  766. /package/dist/types/modules/word/{writers → writer}/textbox-writer.d.ts +0 -0
  767. /package/dist/types/modules/word/{writers → writer}/toc-writer.d.ts +0 -0
@@ -0,0 +1,1936 @@
1
+ "use strict";
2
+ /**
3
+ * DOCX Module - OpenDocument Text (ODT) Format Support
4
+ *
5
+ * Implements reading and writing of ODT (OpenDocument Text) files.
6
+ * ODT files are ZIP archives containing XML content in ODF namespaces.
7
+ *
8
+ * Main archive structure:
9
+ * - content.xml — document body and automatic styles
10
+ * - styles.xml — named styles, page layout, master pages
11
+ * - meta.xml — document metadata
12
+ * - META-INF/manifest.xml — manifest of all archive entries
13
+ * - Pictures/ — embedded images
14
+ *
15
+ * @stability experimental
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.readOdt = readOdt;
19
+ exports.writeOdt = writeOdt;
20
+ const create_archive_1 = require("../../../archive/create-archive.js");
21
+ const read_archive_1 = require("../../../archive/read-archive.js");
22
+ const dom_1 = require("../../../xml/dom.js");
23
+ const writer_1 = require("../../../xml/writer.js");
24
+ const internal_utils_1 = require("../../core/internal-utils");
25
+ const text_utils_1 = require("../../core/text-utils");
26
+ const errors_1 = require("../../errors");
27
+ const units_1 = require("../../units");
28
+ // =============================================================================
29
+ // ODF Namespace Constants
30
+ // =============================================================================
31
+ /** ODF namespace URIs. */
32
+ const NS = {
33
+ office: "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
34
+ style: "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
35
+ text: "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
36
+ table: "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
37
+ draw: "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
38
+ fo: "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
39
+ xlink: "http://www.w3.org/1999/xlink",
40
+ dc: "http://purl.org/dc/elements/1.1/",
41
+ meta: "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
42
+ svg: "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
43
+ manifest: "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"
44
+ };
45
+ // =============================================================================
46
+ // Unit Conversion Helpers
47
+ // =============================================================================
48
+ /** Parse an ODF length value (e.g. "1.27cm", "0.5in", "12pt") to twips. */
49
+ function odfLengthToTwips(value) {
50
+ if (!value) {
51
+ return undefined;
52
+ }
53
+ const match = value.match(/^(-?\d+(?:\.\d+)?)\s*(cm|mm|in|pt|pc|px|em)$/);
54
+ if (!match) {
55
+ return undefined;
56
+ }
57
+ const num = parseFloat(match[1]);
58
+ const unit = match[2];
59
+ switch (unit) {
60
+ case "cm":
61
+ return Math.round(num * 567);
62
+ case "mm":
63
+ return Math.round(num * 56.7);
64
+ case "in":
65
+ return Math.round(num * 1440);
66
+ case "pt":
67
+ return Math.round(num * 20);
68
+ case "pc":
69
+ return Math.round(num * 240);
70
+ case "px":
71
+ // Approximate: 1px ≈ 0.75pt at 96dpi
72
+ return Math.round(num * 15);
73
+ case "em":
74
+ // Approximate: 1em ≈ 12pt
75
+ return Math.round(num * 240);
76
+ default:
77
+ return undefined;
78
+ }
79
+ }
80
+ /** Parse an ODF length value to EMU (English Metric Units). */
81
+ function odfLengthToEmu(value) {
82
+ if (!value) {
83
+ return undefined;
84
+ }
85
+ const match = value.match(/^(-?\d+(?:\.\d+)?)\s*(cm|mm|in|pt|pc|px)$/);
86
+ if (!match) {
87
+ return undefined;
88
+ }
89
+ const num = parseFloat(match[1]);
90
+ const unit = match[2];
91
+ switch (unit) {
92
+ case "cm":
93
+ return Math.round(num * units_1.EMU_PER_CM);
94
+ case "mm":
95
+ return Math.round((num * units_1.EMU_PER_CM) / 10);
96
+ case "in":
97
+ return Math.round(num * units_1.EMU_PER_INCH);
98
+ case "pt":
99
+ return Math.round(num * units_1.EMU_PER_POINT);
100
+ case "pc":
101
+ return Math.round(num * units_1.EMU_PER_POINT * 12); // 1 pica = 12 points
102
+ case "px":
103
+ return Math.round(num * units_1.EMU_PER_PX);
104
+ default:
105
+ return undefined;
106
+ }
107
+ }
108
+ /** Convert twips to ODF length string (cm). */
109
+ function twipsToCm(twips) {
110
+ return (twips / 567).toFixed(3) + "cm";
111
+ }
112
+ /** Convert EMU to ODF length string (cm). */
113
+ function emuToCm(emu) {
114
+ return (emu / units_1.EMU_PER_CM).toFixed(3) + "cm";
115
+ }
116
+ /** Convert half-points to pt string. */
117
+ function halfPointsToPt(hp) {
118
+ return (hp / 2).toString() + "pt";
119
+ }
120
+ /** Parse a font size string (e.g. "12pt") to half-points. */
121
+ function parseFontSizeToHalfPoints(value) {
122
+ if (!value) {
123
+ return undefined;
124
+ }
125
+ const match = value.match(/^(\d+(?:\.\d+)?)\s*pt$/);
126
+ if (!match) {
127
+ return undefined;
128
+ }
129
+ return Math.round(parseFloat(match[1]) * 2);
130
+ }
131
+ /** Parse a 6-digit hex color from ODF format (#RRGGBB). */
132
+ function parseOdfColor(value) {
133
+ if (!value) {
134
+ return undefined;
135
+ }
136
+ const match = value.match(/^#([0-9a-fA-F]{6})$/);
137
+ if (!match) {
138
+ return undefined;
139
+ }
140
+ return match[1].toUpperCase();
141
+ }
142
+ /** Convert a hex color to ODF format (#RRGGBB). */
143
+ function colorToOdf(hex) {
144
+ return `#${hex}`;
145
+ }
146
+ // =============================================================================
147
+ // XML Element Query Helpers (Namespace-Aware)
148
+ // =============================================================================
149
+ /**
150
+ * Find a child element by namespace-prefixed name.
151
+ * Tries both "prefix:local" and just "local" for flexibility.
152
+ */
153
+ function findNsChild(el, prefix, local) {
154
+ return (0, dom_1.findChild)(el, `${prefix}:${local}`) ?? (0, dom_1.findChild)(el, local);
155
+ }
156
+ /** Find all children by namespace-prefixed name. */
157
+ function findNsChildren(el, prefix, local) {
158
+ const result = (0, dom_1.findChildren)(el, `${prefix}:${local}`);
159
+ if (result.length > 0) {
160
+ return result;
161
+ }
162
+ return (0, dom_1.findChildren)(el, local);
163
+ }
164
+ /** Get an attribute value with a namespace prefix. */
165
+ function nsAttr(el, prefix, local) {
166
+ return el.attributes[`${prefix}:${local}`] ?? el.attributes[local];
167
+ }
168
+ // =============================================================================
169
+ // ODF Style Parsing
170
+ // =============================================================================
171
+ /** Parse style properties from a style:style element. */
172
+ function parseOdfStyle(el) {
173
+ const name = nsAttr(el, "style", "name") ?? "";
174
+ const family = nsAttr(el, "style", "family") ?? "";
175
+ const parentStyle = nsAttr(el, "style", "parent-style-name");
176
+ let paragraphProperties;
177
+ let textProperties;
178
+ let tableProperties;
179
+ let tableColumnProperties;
180
+ let tableCellProperties;
181
+ const pPropsEl = findNsChild(el, "style", "paragraph-properties");
182
+ if (pPropsEl) {
183
+ paragraphProperties = {
184
+ textAlign: nsAttr(pPropsEl, "fo", "text-align"),
185
+ marginTop: nsAttr(pPropsEl, "fo", "margin-top"),
186
+ marginBottom: nsAttr(pPropsEl, "fo", "margin-bottom"),
187
+ marginLeft: nsAttr(pPropsEl, "fo", "margin-left"),
188
+ marginRight: nsAttr(pPropsEl, "fo", "margin-right"),
189
+ textIndent: nsAttr(pPropsEl, "fo", "text-indent"),
190
+ lineHeight: nsAttr(pPropsEl, "fo", "line-height"),
191
+ breakBefore: nsAttr(pPropsEl, "fo", "break-before"),
192
+ keepWithNext: nsAttr(pPropsEl, "fo", "keep-with-next")
193
+ };
194
+ }
195
+ const tPropsEl = findNsChild(el, "style", "text-properties");
196
+ if (tPropsEl) {
197
+ textProperties = {
198
+ fontName: nsAttr(tPropsEl, "style", "font-name") ?? nsAttr(tPropsEl, "fo", "font-family"),
199
+ fontSize: nsAttr(tPropsEl, "fo", "font-size"),
200
+ fontWeight: nsAttr(tPropsEl, "fo", "font-weight"),
201
+ fontStyle: nsAttr(tPropsEl, "fo", "font-style"),
202
+ textDecoration: nsAttr(tPropsEl, "style", "text-underline-style") ??
203
+ nsAttr(tPropsEl, "style", "text-line-through-style"),
204
+ color: nsAttr(tPropsEl, "fo", "color"),
205
+ backgroundColor: nsAttr(tPropsEl, "fo", "background-color"),
206
+ textPosition: nsAttr(tPropsEl, "style", "text-position"),
207
+ fontVariant: nsAttr(tPropsEl, "fo", "font-variant"),
208
+ letterSpacing: nsAttr(tPropsEl, "fo", "letter-spacing")
209
+ };
210
+ }
211
+ const tablePropsEl = findNsChild(el, "style", "table-properties");
212
+ if (tablePropsEl) {
213
+ tableProperties = {
214
+ width: nsAttr(tablePropsEl, "style", "width"),
215
+ align: nsAttr(tablePropsEl, "table", "align") ?? nsAttr(tablePropsEl, "fo", "margin-left")
216
+ };
217
+ }
218
+ const tableColPropsEl = findNsChild(el, "style", "table-column-properties");
219
+ if (tableColPropsEl) {
220
+ tableColumnProperties = {
221
+ columnWidth: nsAttr(tableColPropsEl, "style", "column-width")
222
+ };
223
+ }
224
+ const tableCellPropsEl = findNsChild(el, "style", "table-cell-properties");
225
+ if (tableCellPropsEl) {
226
+ tableCellProperties = {
227
+ padding: nsAttr(tableCellPropsEl, "fo", "padding"),
228
+ borderTop: nsAttr(tableCellPropsEl, "fo", "border-top"),
229
+ borderBottom: nsAttr(tableCellPropsEl, "fo", "border-bottom"),
230
+ borderLeft: nsAttr(tableCellPropsEl, "fo", "border-left"),
231
+ borderRight: nsAttr(tableCellPropsEl, "fo", "border-right"),
232
+ backgroundColor: nsAttr(tableCellPropsEl, "fo", "background-color"),
233
+ verticalAlign: nsAttr(tableCellPropsEl, "style", "vertical-align")
234
+ };
235
+ }
236
+ return {
237
+ name,
238
+ family,
239
+ parentStyle,
240
+ paragraphProperties,
241
+ textProperties,
242
+ tableProperties,
243
+ tableColumnProperties,
244
+ tableCellProperties
245
+ };
246
+ }
247
+ /** Parse page layout properties from a style:page-layout element. */
248
+ function parsePageLayout(el) {
249
+ const propsEl = findNsChild(el, "style", "page-layout-properties");
250
+ if (!propsEl) {
251
+ return undefined;
252
+ }
253
+ return {
254
+ pageWidth: nsAttr(propsEl, "fo", "page-width"),
255
+ pageHeight: nsAttr(propsEl, "fo", "page-height"),
256
+ marginTop: nsAttr(propsEl, "fo", "margin-top"),
257
+ marginBottom: nsAttr(propsEl, "fo", "margin-bottom"),
258
+ marginLeft: nsAttr(propsEl, "fo", "margin-left"),
259
+ marginRight: nsAttr(propsEl, "fo", "margin-right")
260
+ };
261
+ }
262
+ // =============================================================================
263
+ // ODF Content Parsing → DocxDocument Model
264
+ // =============================================================================
265
+ /** Convert ODF text alignment to OOXML alignment. */
266
+ function odfAlignToAlignment(align) {
267
+ if (!align) {
268
+ return undefined;
269
+ }
270
+ switch (align) {
271
+ case "start":
272
+ case "left":
273
+ return "left";
274
+ case "center":
275
+ return "center";
276
+ case "end":
277
+ case "right":
278
+ return "right";
279
+ case "justify":
280
+ return "both";
281
+ default:
282
+ return undefined;
283
+ }
284
+ }
285
+ /** Convert ODF paragraph properties to OOXML ParagraphProperties. */
286
+ function odfParagraphPropsToDocx(props, styleName) {
287
+ if (!props && !styleName) {
288
+ return undefined;
289
+ }
290
+ const alignment = odfAlignToAlignment(props?.textAlign);
291
+ let indent;
292
+ const leftTwips = odfLengthToTwips(props?.marginLeft);
293
+ const rightTwips = odfLengthToTwips(props?.marginRight);
294
+ const firstLineTwips = odfLengthToTwips(props?.textIndent);
295
+ if (leftTwips !== undefined || rightTwips !== undefined || firstLineTwips !== undefined) {
296
+ indent = {
297
+ ...(leftTwips !== undefined ? { left: leftTwips } : {}),
298
+ ...(rightTwips !== undefined ? { right: rightTwips } : {}),
299
+ ...(firstLineTwips !== undefined
300
+ ? firstLineTwips >= 0
301
+ ? { firstLine: firstLineTwips }
302
+ : { hanging: -firstLineTwips }
303
+ : {})
304
+ };
305
+ }
306
+ let spacing;
307
+ const beforeTwips = odfLengthToTwips(props?.marginTop);
308
+ const afterTwips = odfLengthToTwips(props?.marginBottom);
309
+ if (beforeTwips !== undefined || afterTwips !== undefined) {
310
+ spacing = {
311
+ ...(beforeTwips !== undefined ? { before: beforeTwips } : {}),
312
+ ...(afterTwips !== undefined ? { after: afterTwips } : {})
313
+ };
314
+ }
315
+ const keepNext = props?.keepWithNext === "always" || props?.keepWithNext === "true" ? true : undefined;
316
+ const pageBreakBefore = props?.breakBefore === "page" ? true : undefined;
317
+ const result = {
318
+ ...(styleName ? { style: styleName } : {}),
319
+ ...(alignment ? { alignment } : {}),
320
+ ...(indent ? { indent } : {}),
321
+ ...(spacing ? { spacing } : {}),
322
+ ...(keepNext !== undefined ? { keepNext } : {}),
323
+ ...(pageBreakBefore !== undefined ? { pageBreakBefore } : {})
324
+ };
325
+ return Object.keys(result).length > 0 ? result : undefined;
326
+ }
327
+ /** Convert ODF text properties to OOXML RunProperties. */
328
+ function odfTextPropsToDocx(props) {
329
+ if (!props) {
330
+ return undefined;
331
+ }
332
+ const font = props.fontName || undefined;
333
+ const size = parseFontSizeToHalfPoints(props.fontSize);
334
+ const bold = props.fontWeight === "bold" ? true : undefined;
335
+ const italic = props.fontStyle === "italic" ? true : undefined;
336
+ let underline;
337
+ if (props.textDecoration && props.textDecoration !== "none") {
338
+ underline = "single";
339
+ }
340
+ let strike;
341
+ if (props.textDecoration === "line-through") {
342
+ strike = true;
343
+ underline = undefined;
344
+ }
345
+ const color = parseOdfColor(props.color);
346
+ const smallCaps = props.fontVariant === "small-caps" ? true : undefined;
347
+ const spacingTwips = odfLengthToTwips(props.letterSpacing);
348
+ let vertAlign;
349
+ if (props.textPosition) {
350
+ if (props.textPosition.startsWith("super") || props.textPosition.startsWith("33%")) {
351
+ vertAlign = "superscript";
352
+ }
353
+ else if (props.textPosition.startsWith("sub") || props.textPosition.startsWith("-33%")) {
354
+ vertAlign = "subscript";
355
+ }
356
+ }
357
+ const result = {
358
+ ...(font ? { font } : {}),
359
+ ...(size !== undefined ? { size } : {}),
360
+ ...(bold !== undefined ? { bold } : {}),
361
+ ...(italic !== undefined ? { italic } : {}),
362
+ ...(underline !== undefined ? { underline } : {}),
363
+ ...(strike !== undefined ? { strike } : {}),
364
+ ...(color !== undefined ? { color } : {}),
365
+ ...(smallCaps !== undefined ? { smallCaps } : {}),
366
+ ...(spacingTwips !== undefined ? { spacing: spacingTwips } : {}),
367
+ ...(vertAlign !== undefined ? { vertAlign } : {})
368
+ };
369
+ return Object.keys(result).length > 0 ? result : undefined;
370
+ }
371
+ /** Parse inline text spans (text:span) within a paragraph. */
372
+ function parseTextSpan(el, styles) {
373
+ const styleName = nsAttr(el, "text", "style-name");
374
+ const style = styleName ? styles.get(styleName) : undefined;
375
+ const runProps = odfTextPropsToDocx(style?.textProperties);
376
+ const content = [];
377
+ for (const child of el.children) {
378
+ if (child.type === "text") {
379
+ if (child.value) {
380
+ content.push({ type: "text", text: child.value });
381
+ }
382
+ }
383
+ else if (child.type === "element") {
384
+ const local = getLocalName(child.name);
385
+ if (local === "s") {
386
+ // text:s — multiple spaces
387
+ const count = parseInt(nsAttr(child, "text", "c") ?? "1", 10);
388
+ content.push({ type: "text", text: " ".repeat(count) });
389
+ }
390
+ else if (local === "tab") {
391
+ content.push({ type: "tab" });
392
+ }
393
+ else if (local === "line-break") {
394
+ content.push({ type: "break" });
395
+ }
396
+ else if (local === "span") {
397
+ // Nested span — flatten into current run content
398
+ const nestedRun = parseTextSpan(child, styles);
399
+ content.push(...nestedRun.content);
400
+ }
401
+ }
402
+ }
403
+ return {
404
+ ...(runProps ? { properties: runProps } : {}),
405
+ content
406
+ };
407
+ }
408
+ /** Parse a text:p or text:h element into a Paragraph. */
409
+ function parseParagraph(el, styles, listContext) {
410
+ const styleName = nsAttr(el, "text", "style-name");
411
+ const style = styleName ? styles.get(styleName) : undefined;
412
+ const isHeading = getLocalName(el.name) === "h";
413
+ const outlineLevel = isHeading
414
+ ? parseInt(nsAttr(el, "text", "outline-level") ?? "1", 10)
415
+ : undefined;
416
+ let paraProps = odfParagraphPropsToDocx(style?.paragraphProperties, styleName);
417
+ // If this is a heading, add outline level
418
+ if (outlineLevel !== undefined && outlineLevel >= 1 && outlineLevel <= 9) {
419
+ paraProps = {
420
+ ...paraProps,
421
+ outlineLevel: outlineLevel - 1,
422
+ style: styleName ?? `Heading${outlineLevel}`
423
+ };
424
+ }
425
+ // If inside a list, add numbering reference
426
+ if (listContext) {
427
+ paraProps = {
428
+ ...paraProps,
429
+ numbering: { numId: 1, level: listContext.level }
430
+ };
431
+ }
432
+ const children = [];
433
+ for (const child of el.children) {
434
+ if (child.type === "text") {
435
+ if (child.value) {
436
+ children.push({
437
+ content: [{ type: "text", text: child.value }]
438
+ });
439
+ }
440
+ }
441
+ else if (child.type === "element") {
442
+ const local = getLocalName(child.name);
443
+ if (local === "span") {
444
+ children.push(parseTextSpan(child, styles));
445
+ }
446
+ else if (local === "a") {
447
+ // Hyperlink. Pass the href through sanitizeUrl so dangerous
448
+ // schemes (javascript:, vbscript:, data: with executable payloads,
449
+ // etc.) coming from an untrusted ODT do not survive into the DOCX
450
+ // model. Unsafe links degrade to plain text — the caller still sees
451
+ // the link's children but no clickable hyperlink is created.
452
+ const rawHref = nsAttr(child, "xlink", "href");
453
+ const safeHref = (0, internal_utils_1.sanitizeUrl)(rawHref);
454
+ const runs = [];
455
+ for (const linkChild of child.children) {
456
+ if (linkChild.type === "text") {
457
+ if (linkChild.value) {
458
+ runs.push({ content: [{ type: "text", text: linkChild.value }] });
459
+ }
460
+ }
461
+ else if (linkChild.type === "element" && getLocalName(linkChild.name) === "span") {
462
+ runs.push(parseTextSpan(linkChild, styles));
463
+ }
464
+ }
465
+ if (safeHref) {
466
+ children.push({
467
+ type: "hyperlink",
468
+ url: safeHref,
469
+ children: runs
470
+ });
471
+ }
472
+ else if (rawHref && rawHref.startsWith("#")) {
473
+ // Internal anchor — sanitizeUrl rejects fragment-only URLs but
474
+ // they're safe and meaningful. Preserve as a Hyperlink with
475
+ // `anchor` set, mirroring how DOCX represents in-document
476
+ // links.
477
+ children.push({
478
+ type: "hyperlink",
479
+ anchor: rawHref.slice(1),
480
+ children: runs
481
+ });
482
+ }
483
+ else {
484
+ // Drop the wrapper — preserve text content as plain runs so no
485
+ // user-visible content disappears.
486
+ for (const r of runs) {
487
+ children.push(r);
488
+ }
489
+ }
490
+ }
491
+ else if (local === "s") {
492
+ const count = parseInt(nsAttr(child, "text", "c") ?? "1", 10);
493
+ children.push({ content: [{ type: "text", text: " ".repeat(count) }] });
494
+ }
495
+ else if (local === "tab") {
496
+ children.push({ content: [{ type: "tab" }] });
497
+ }
498
+ else if (local === "line-break") {
499
+ children.push({ content: [{ type: "break" }] });
500
+ }
501
+ else if (local === "frame") {
502
+ // Inline image frame
503
+ const imageRun = parseDrawFrame(child);
504
+ if (imageRun) {
505
+ children.push(imageRun);
506
+ }
507
+ }
508
+ else if (local === "bookmark-start") {
509
+ const bkName = nsAttr(child, "text", "name") ?? "";
510
+ children.push({ type: "bookmarkStart", id: 0, name: bkName });
511
+ }
512
+ else if (local === "bookmark-end") {
513
+ children.push({ type: "bookmarkEnd", id: 0 });
514
+ }
515
+ else if (local === "note") {
516
+ // Footnote/endnote — extract text content
517
+ const noteBodyEl = findNsChild(child, "text", "note-body");
518
+ if (noteBodyEl) {
519
+ const noteText = (0, dom_1.textContent)(noteBodyEl);
520
+ if (noteText) {
521
+ children.push({ content: [{ type: "text", text: `[${noteText}]` }] });
522
+ }
523
+ }
524
+ }
525
+ }
526
+ }
527
+ return {
528
+ type: "paragraph",
529
+ ...(paraProps ? { properties: paraProps } : {}),
530
+ children
531
+ };
532
+ }
533
+ /** Parse a draw:frame element for inline images. */
534
+ function parseDrawFrame(el) {
535
+ const width = odfLengthToEmu(nsAttr(el, "svg", "width"));
536
+ const height = odfLengthToEmu(nsAttr(el, "svg", "height"));
537
+ const name = nsAttr(el, "draw", "name");
538
+ const imageEl = findNsChild(el, "draw", "image") ?? (0, dom_1.findChild)(el, "draw:image") ?? (0, dom_1.findChild)(el, "image");
539
+ if (!imageEl) {
540
+ return undefined;
541
+ }
542
+ const href = nsAttr(imageEl, "xlink", "href");
543
+ if (!href) {
544
+ return undefined;
545
+ }
546
+ const imageContent = {
547
+ type: "image",
548
+ rId: href, // Use the path as rId placeholder; resolved during image collection
549
+ width: width ?? units_1.EMU_PER_INCH, // Default 1 inch
550
+ height: height ?? units_1.EMU_PER_INCH,
551
+ ...(name ? { name } : {})
552
+ };
553
+ return {
554
+ content: [imageContent]
555
+ };
556
+ }
557
+ /** Parse a text:list element. */
558
+ function parseList(el, styles, parentLevel) {
559
+ const listStyleName = nsAttr(el, "text", "style-name");
560
+ const paragraphs = [];
561
+ const level = parentLevel;
562
+ const items = findNsChildren(el, "text", "list-item");
563
+ for (const item of items) {
564
+ for (const child of item.children) {
565
+ if (child.type !== "element") {
566
+ continue;
567
+ }
568
+ const local = getLocalName(child.name);
569
+ if (local === "p" || local === "h") {
570
+ paragraphs.push(parseParagraph(child, styles, { listStyleName, level }));
571
+ }
572
+ else if (local === "list") {
573
+ // Nested list
574
+ paragraphs.push(...parseList(child, styles, level + 1));
575
+ }
576
+ }
577
+ }
578
+ return paragraphs;
579
+ }
580
+ /** Parse a table:table element into a Table. */
581
+ function parseTable(el, styles) {
582
+ const tableStyleName = nsAttr(el, "table", "style-name");
583
+ const tableStyle = tableStyleName ? styles.get(tableStyleName) : undefined;
584
+ // Parse column definitions for widths
585
+ const columnWidths = [];
586
+ const colElements = findNsChildren(el, "table", "table-column");
587
+ for (const colEl of colElements) {
588
+ const colStyleName = nsAttr(colEl, "table", "style-name");
589
+ const colStyle = colStyleName ? styles.get(colStyleName) : undefined;
590
+ const width = odfLengthToTwips(colStyle?.tableColumnProperties?.columnWidth);
591
+ const repeatCount = parseInt(nsAttr(colEl, "table", "number-columns-repeated") ?? "1", 10);
592
+ for (let i = 0; i < repeatCount; i++) {
593
+ columnWidths.push(width ?? 2000);
594
+ }
595
+ }
596
+ // Parse rows
597
+ const rows = [];
598
+ const rowElements = findNsChildren(el, "table", "table-row");
599
+ for (const rowEl of rowElements) {
600
+ const cells = [];
601
+ // Iterate in document order (preserve natural order)
602
+ const orderedCells = [];
603
+ for (const child of rowEl.children) {
604
+ if (child.type === "element") {
605
+ const childLocal = getLocalName(child.name);
606
+ if (childLocal === "table-cell" || childLocal === "covered-table-cell") {
607
+ orderedCells.push(child);
608
+ }
609
+ }
610
+ }
611
+ for (const cellEl of orderedCells) {
612
+ const cellLocal = getLocalName(cellEl.name);
613
+ const isCovered = cellLocal === "covered-table-cell";
614
+ const gridSpan = parseInt(nsAttr(cellEl, "table", "number-columns-spanned") ?? "1", 10);
615
+ const rowSpan = parseInt(nsAttr(cellEl, "table", "number-rows-spanned") ?? "1", 10);
616
+ const cellProps = {
617
+ ...(gridSpan > 1 ? { gridSpan } : {}),
618
+ ...(rowSpan > 1 ? { rowSpan } : {}),
619
+ ...(isCovered ? { verticalMerge: "continue" } : {})
620
+ };
621
+ // Parse cell content
622
+ const cellContent = [];
623
+ for (const cellChild of cellEl.children) {
624
+ if (cellChild.type !== "element") {
625
+ continue;
626
+ }
627
+ const cellChildLocal = getLocalName(cellChild.name);
628
+ if (cellChildLocal === "p" || cellChildLocal === "h") {
629
+ cellContent.push(parseParagraph(cellChild, styles));
630
+ }
631
+ else if (cellChildLocal === "table") {
632
+ cellContent.push(parseTable(cellChild, styles));
633
+ }
634
+ else if (cellChildLocal === "list") {
635
+ cellContent.push(...parseList(cellChild, styles, 0));
636
+ }
637
+ }
638
+ // Ensure at least one paragraph per cell
639
+ if (cellContent.length === 0) {
640
+ cellContent.push({ type: "paragraph", children: [] });
641
+ }
642
+ cells.push({
643
+ ...(Object.keys(cellProps).length > 0 ? { properties: cellProps } : {}),
644
+ content: cellContent
645
+ });
646
+ }
647
+ rows.push({ cells });
648
+ }
649
+ // Build table properties
650
+ let tableProps;
651
+ const widthTwips = odfLengthToTwips(tableStyle?.tableProperties?.width);
652
+ if (widthTwips !== undefined || tableStyleName) {
653
+ tableProps = {
654
+ ...(tableStyleName ? { style: tableStyleName } : {}),
655
+ ...(widthTwips !== undefined ? { width: { value: widthTwips, type: "dxa" } } : {})
656
+ };
657
+ }
658
+ return {
659
+ type: "table",
660
+ ...(tableProps ? { properties: tableProps } : {}),
661
+ ...(columnWidths.length > 0 ? { columnWidths } : {}),
662
+ rows
663
+ };
664
+ }
665
+ /** Parse document body content from the office:body/office:text element. */
666
+ function parseDocumentBody(bodyEl, styles) {
667
+ const content = [];
668
+ for (const child of bodyEl.children) {
669
+ if (child.type !== "element") {
670
+ continue;
671
+ }
672
+ const local = getLocalName(child.name);
673
+ if (local === "p" || local === "h") {
674
+ content.push(parseParagraph(child, styles));
675
+ }
676
+ else if (local === "table") {
677
+ content.push(parseTable(child, styles));
678
+ }
679
+ else if (local === "list") {
680
+ content.push(...parseList(child, styles, 0));
681
+ }
682
+ else if (local === "section") {
683
+ // Sections in ODF are logical containers; flatten their content
684
+ content.push(...parseDocumentBody(child, styles));
685
+ }
686
+ }
687
+ return content;
688
+ }
689
+ /** Get the local name from a possibly prefixed XML name. */
690
+ function getLocalName(name) {
691
+ const colonIdx = name.indexOf(":");
692
+ if (colonIdx >= 0) {
693
+ return name.substring(colonIdx + 1);
694
+ }
695
+ return name;
696
+ }
697
+ // =============================================================================
698
+ // Meta Parsing
699
+ // =============================================================================
700
+ /** Parse meta.xml into CoreProperties. */
701
+ function parseMetaXml(xml) {
702
+ let doc;
703
+ try {
704
+ doc = (0, dom_1.parseXml)(xml);
705
+ }
706
+ catch {
707
+ return undefined;
708
+ }
709
+ const root = doc.root;
710
+ const metaEl = findNsChild(root, "office", "meta") ?? (0, dom_1.findChild)(root, "office:meta") ?? root;
711
+ const title = getMetaText(metaEl, "dc", "title");
712
+ const subject = getMetaText(metaEl, "dc", "subject");
713
+ const creator = getMetaText(metaEl, "dc", "creator") ?? getMetaText(metaEl, "meta", "initial-creator");
714
+ const description = getMetaText(metaEl, "dc", "description");
715
+ const keywords = getMetaText(metaEl, "meta", "keyword");
716
+ const createdStr = getMetaText(metaEl, "meta", "creation-date");
717
+ const modifiedStr = getMetaText(metaEl, "dc", "date");
718
+ const created = createdStr ? new Date(createdStr) : undefined;
719
+ const modified = modifiedStr ? new Date(modifiedStr) : undefined;
720
+ const result = {
721
+ ...(title ? { title } : {}),
722
+ ...(subject ? { subject } : {}),
723
+ ...(creator ? { creator } : {}),
724
+ ...(description ? { description } : {}),
725
+ ...(keywords ? { keywords } : {}),
726
+ ...(created && !isNaN(created.getTime()) ? { created } : {}),
727
+ ...(modified && !isNaN(modified.getTime()) ? { modified } : {})
728
+ };
729
+ return Object.keys(result).length > 0 ? result : undefined;
730
+ }
731
+ /** Get text content of a metadata element. */
732
+ function getMetaText(parent, prefix, local) {
733
+ const el = findNsChild(parent, prefix, local);
734
+ if (!el) {
735
+ return undefined;
736
+ }
737
+ const text = (0, dom_1.textContent)(el).trim();
738
+ return text || undefined;
739
+ }
740
+ // =============================================================================
741
+ // Page Layout Parsing
742
+ // =============================================================================
743
+ /** Parse page layout from styles.xml into SectionProperties. */
744
+ function parsePageLayoutToSection(pageLayout) {
745
+ if (!pageLayout) {
746
+ return undefined;
747
+ }
748
+ let pageSize;
749
+ const widthTwips = odfLengthToTwips(pageLayout.pageWidth);
750
+ const heightTwips = odfLengthToTwips(pageLayout.pageHeight);
751
+ if (widthTwips !== undefined && heightTwips !== undefined) {
752
+ pageSize = {
753
+ width: widthTwips,
754
+ height: heightTwips,
755
+ ...(widthTwips > heightTwips ? { orientation: "landscape" } : {})
756
+ };
757
+ }
758
+ let margins;
759
+ const marginTop = odfLengthToTwips(pageLayout.marginTop);
760
+ const marginBottom = odfLengthToTwips(pageLayout.marginBottom);
761
+ const marginLeft = odfLengthToTwips(pageLayout.marginLeft);
762
+ const marginRight = odfLengthToTwips(pageLayout.marginRight);
763
+ if (marginTop !== undefined ||
764
+ marginBottom !== undefined ||
765
+ marginLeft !== undefined ||
766
+ marginRight !== undefined) {
767
+ margins = {
768
+ top: marginTop ?? 1440,
769
+ right: marginRight ?? 1440,
770
+ bottom: marginBottom ?? 1440,
771
+ left: marginLeft ?? 1440
772
+ };
773
+ }
774
+ if (!pageSize && !margins) {
775
+ return undefined;
776
+ }
777
+ return {
778
+ ...(pageSize ? { pageSize } : {}),
779
+ ...(margins ? { margins } : {})
780
+ };
781
+ }
782
+ // =============================================================================
783
+ // Styles Conversion → StyleDef[]
784
+ // =============================================================================
785
+ /** Convert parsed ODF styles to DocxDocument style definitions. */
786
+ function convertStylesToStyleDefs(styles) {
787
+ const defs = [];
788
+ for (const [, style] of styles) {
789
+ // Only convert named/non-automatic styles
790
+ if (!style.name) {
791
+ continue;
792
+ }
793
+ let type;
794
+ switch (style.family) {
795
+ case "paragraph":
796
+ type = "paragraph";
797
+ break;
798
+ case "text":
799
+ type = "character";
800
+ break;
801
+ case "table":
802
+ type = "table";
803
+ break;
804
+ default:
805
+ continue; // Skip unsupported style families
806
+ }
807
+ const def = {
808
+ type,
809
+ styleId: style.name,
810
+ name: style.name,
811
+ ...(style.parentStyle ? { basedOn: style.parentStyle } : {}),
812
+ ...(style.paragraphProperties
813
+ ? { paragraphProperties: odfParagraphPropsToDocx(style.paragraphProperties) }
814
+ : {}),
815
+ ...(style.textProperties ? { runProperties: odfTextPropsToDocx(style.textProperties) } : {})
816
+ };
817
+ defs.push(def);
818
+ }
819
+ return defs;
820
+ }
821
+ // =============================================================================
822
+ // ODT list numbering definition (numId=1)
823
+ // =============================================================================
824
+ /**
825
+ * Walk the converted body and, if any paragraph references `numbering.numId`,
826
+ * synthesize the corresponding `abstractNumberings` and `numberingInstances`
827
+ * so Word renders bullet/number markers. Without this the list paragraphs
828
+ * carry a `numId` that resolves to nothing in the produced document and the
829
+ * markers are invisible.
830
+ *
831
+ * The reader currently only emits a single bulleted abstract definition for
832
+ * `numId === 1` (matching parseParagraph above). Numbered/multi-level ODT
833
+ * lists fall back to bullets for now — preserving the visible structure is
834
+ * the primary goal.
835
+ */
836
+ function buildOdtNumberingDefs(body) {
837
+ if (!hasListParagraph(body)) {
838
+ return {};
839
+ }
840
+ const tabSuffix = "tab";
841
+ const bulletChars = ["•", "◦", "▪", "•", "◦", "▪", "•", "◦", "▪"];
842
+ const levels = bulletChars.map((ch, level) => ({
843
+ level,
844
+ format: "bullet",
845
+ text: ch,
846
+ start: 1,
847
+ paragraphProperties: {
848
+ indent: { left: 720 * (level + 1), hanging: 360 }
849
+ },
850
+ suffix: tabSuffix
851
+ }));
852
+ return {
853
+ abstractNumberings: [{ abstractNumId: 1, levels }],
854
+ numberingInstances: [{ numId: 1, abstractNumId: 1 }]
855
+ };
856
+ }
857
+ function hasListParagraph(blocks) {
858
+ for (const block of blocks) {
859
+ if (block.type === "paragraph") {
860
+ if (block.properties?.numbering) {
861
+ return true;
862
+ }
863
+ }
864
+ else if (block.type === "table") {
865
+ for (const row of block.rows) {
866
+ for (const cell of row.cells) {
867
+ if (hasListParagraph(cell.content)) {
868
+ return true;
869
+ }
870
+ }
871
+ }
872
+ }
873
+ }
874
+ return false;
875
+ }
876
+ // =============================================================================
877
+ // readOdt — Main Entry Point
878
+ // =============================================================================
879
+ /**
880
+ * Read an ODT file and convert to DocxDocument model.
881
+ *
882
+ * Extracts the ZIP archive, parses content.xml, styles.xml, and meta.xml,
883
+ * and produces a unified DocxDocument representation.
884
+ *
885
+ * @param buffer - The ODT file as a Uint8Array.
886
+ * @returns A DocxDocument representing the ODT content.
887
+ * @throws {DocxParseError} If the ODT file is malformed or missing required parts.
888
+ *
889
+ * @stability experimental
890
+ */
891
+ async function readOdt(buffer) {
892
+ // Extract ZIP contents
893
+ const reader = (0, read_archive_1.unzip)(buffer);
894
+ const entries = new Map();
895
+ for await (const entry of reader.entries()) {
896
+ const data = await entry.bytes();
897
+ const path = entry.path.replace(/^\//, "").replace(/\\/g, "/");
898
+ entries.set(path, data);
899
+ }
900
+ const decoder = internal_utils_1.utf8Decoder;
901
+ // Parse content.xml (required)
902
+ const contentData = entries.get("content.xml");
903
+ if (!contentData) {
904
+ throw new errors_1.DocxParseError("Required ODT part not found: content.xml");
905
+ }
906
+ const contentXml = decoder.decode(contentData);
907
+ const contentDoc = (0, dom_1.parseXml)(contentXml);
908
+ // Parse styles.xml (optional)
909
+ const stylesData = entries.get("styles.xml");
910
+ let stylesXml;
911
+ if (stylesData) {
912
+ stylesXml = decoder.decode(stylesData);
913
+ }
914
+ // Parse meta.xml (optional)
915
+ const metaData = entries.get("meta.xml");
916
+ let coreProperties;
917
+ if (metaData) {
918
+ coreProperties = parseMetaXml(decoder.decode(metaData));
919
+ }
920
+ // Collect all styles (from both content.xml and styles.xml)
921
+ const allStyles = new Map();
922
+ let pageLayoutProps;
923
+ // Parse styles from styles.xml
924
+ if (stylesXml) {
925
+ const stylesDoc = (0, dom_1.parseXml)(stylesXml);
926
+ const stylesRoot = stylesDoc.root;
927
+ // Named styles (office:styles)
928
+ const officeStylesEl = findNsChild(stylesRoot, "office", "styles");
929
+ if (officeStylesEl) {
930
+ for (const child of officeStylesEl.children) {
931
+ if (child.type === "element" && getLocalName(child.name) === "style") {
932
+ const s = parseOdfStyle(child);
933
+ if (s.name) {
934
+ allStyles.set(s.name, s);
935
+ }
936
+ }
937
+ }
938
+ }
939
+ // Automatic styles in styles.xml (office:automatic-styles)
940
+ const autoStylesEl = findNsChild(stylesRoot, "office", "automatic-styles");
941
+ if (autoStylesEl) {
942
+ for (const child of autoStylesEl.children) {
943
+ if (child.type === "element") {
944
+ const childLocal = getLocalName(child.name);
945
+ if (childLocal === "style") {
946
+ const s = parseOdfStyle(child);
947
+ if (s.name) {
948
+ allStyles.set(s.name, s);
949
+ }
950
+ }
951
+ else if (childLocal === "page-layout") {
952
+ pageLayoutProps = parsePageLayout(child);
953
+ }
954
+ }
955
+ }
956
+ }
957
+ // Master page styles for page layout reference
958
+ const masterStylesEl = findNsChild(stylesRoot, "office", "master-styles");
959
+ if (masterStylesEl && !pageLayoutProps) {
960
+ // Look for the page layout reference in master pages
961
+ for (const child of masterStylesEl.children) {
962
+ if (child.type === "element" && getLocalName(child.name) === "master-page") {
963
+ const pageLayoutName = nsAttr(child, "style", "page-layout-name");
964
+ if (pageLayoutName && autoStylesEl) {
965
+ for (const autoChild of autoStylesEl.children) {
966
+ if (autoChild.type === "element" &&
967
+ getLocalName(autoChild.name) === "page-layout" &&
968
+ nsAttr(autoChild, "style", "name") === pageLayoutName) {
969
+ pageLayoutProps = parsePageLayout(autoChild);
970
+ break;
971
+ }
972
+ }
973
+ }
974
+ break;
975
+ }
976
+ }
977
+ }
978
+ }
979
+ // Parse automatic styles from content.xml
980
+ const contentAutoStylesEl = findNsChild(contentDoc.root, "office", "automatic-styles");
981
+ if (contentAutoStylesEl) {
982
+ for (const child of contentAutoStylesEl.children) {
983
+ if (child.type === "element") {
984
+ const childLocal = getLocalName(child.name);
985
+ if (childLocal === "style") {
986
+ const s = parseOdfStyle(child);
987
+ if (s.name) {
988
+ allStyles.set(s.name, s);
989
+ }
990
+ }
991
+ else if (childLocal === "page-layout" && !pageLayoutProps) {
992
+ pageLayoutProps = parsePageLayout(child);
993
+ }
994
+ }
995
+ }
996
+ }
997
+ // Parse document body
998
+ const bodyEl = findNsChild(contentDoc.root, "office", "body");
999
+ if (!bodyEl) {
1000
+ throw new errors_1.DocxParseError("Invalid ODT: missing office:body element");
1001
+ }
1002
+ const textEl = findNsChild(bodyEl, "office", "text");
1003
+ if (!textEl) {
1004
+ throw new errors_1.DocxParseError("Invalid ODT: missing office:text element");
1005
+ }
1006
+ const body = parseDocumentBody(textEl, allStyles);
1007
+ // Convert styles to StyleDef[]
1008
+ const styleDefs = convertStylesToStyleDefs(allStyles);
1009
+ // Parse section properties from page layout
1010
+ const sectionProperties = parsePageLayoutToSection(pageLayoutProps);
1011
+ // Collect images
1012
+ const images = [];
1013
+ for (const [path, data] of entries) {
1014
+ if (path.startsWith("Pictures/") && data.length > 0) {
1015
+ const ext = path.substring(path.lastIndexOf(".") + 1).toLowerCase();
1016
+ let mediaType;
1017
+ switch (ext) {
1018
+ case "png":
1019
+ mediaType = "image/png";
1020
+ break;
1021
+ case "jpg":
1022
+ case "jpeg":
1023
+ mediaType = "image/jpeg";
1024
+ break;
1025
+ case "gif":
1026
+ mediaType = "image/gif";
1027
+ break;
1028
+ case "svg":
1029
+ mediaType = "image/svg+xml";
1030
+ break;
1031
+ case "emf":
1032
+ mediaType = "image/x-emf";
1033
+ break;
1034
+ case "wmf":
1035
+ mediaType = "image/x-wmf";
1036
+ break;
1037
+ case "tiff":
1038
+ case "tif":
1039
+ mediaType = "image/tiff";
1040
+ break;
1041
+ case "bmp":
1042
+ mediaType = "image/bmp";
1043
+ break;
1044
+ default:
1045
+ mediaType = "application/octet-stream";
1046
+ break;
1047
+ }
1048
+ images.push({
1049
+ rId: path,
1050
+ data,
1051
+ mediaType: mediaType,
1052
+ fileName: path.substring(path.lastIndexOf("/") + 1)
1053
+ });
1054
+ }
1055
+ }
1056
+ const doc = {
1057
+ body,
1058
+ ...(sectionProperties ? { sectionProperties } : {}),
1059
+ ...(styleDefs.length > 0 ? { styles: styleDefs } : {}),
1060
+ ...(coreProperties ? { coreProperties } : {}),
1061
+ ...(images.length > 0 ? { images } : {}),
1062
+ ...buildOdtNumberingDefs(body)
1063
+ };
1064
+ return doc;
1065
+ }
1066
+ /**
1067
+ * Build a deterministic, ZIP-safe `Pictures/` path for each image in the
1068
+ * document. The same rId → path map is consumed by both the content
1069
+ * writer (`xlink:href`) and the archive writer so that what we point at
1070
+ * in content.xml actually exists in the package.
1071
+ *
1072
+ * Image identifiers (`rId`, `fileName`) come from arbitrary upstream
1073
+ * input — including untrusted DOCX files round-tripped through readDocx.
1074
+ * Without sanitisation a hostile rId like `../../etc/passwd` would
1075
+ * produce both an out-of-tree ZIP entry name and an out-of-package
1076
+ * `xlink:href`, which is a real vector for confusing downstream ODT
1077
+ * readers and tooling that resolves relative paths.
1078
+ */
1079
+ function buildOdtImagePathMap(images) {
1080
+ const byRId = new Map();
1081
+ const byFileName = new Map();
1082
+ if (!images) {
1083
+ return { byRId, byFileName };
1084
+ }
1085
+ const used = new Set();
1086
+ // Allocate a unique `Pictures/<safe>` path for each image. We generate
1087
+ // a single counter-based fallback when the preferred name is empty or
1088
+ // collides with an entry that's already taken; the previous version
1089
+ // double-incremented `counter` (once inside the collision loop, once
1090
+ // after) producing sparse names like `image1.bin`, `image3.bin`, ….
1091
+ let counter = 1;
1092
+ const allocate = (preferred) => {
1093
+ const safeBase = sanitizeOdtPictureName(preferred);
1094
+ let candidate = safeBase || `image${counter++}.bin`;
1095
+ while (used.has(candidate)) {
1096
+ // Suffix a fresh counter to disambiguate; preserve the extension
1097
+ // when we have one so downstream readers still classify the file
1098
+ // correctly. `_bin` was the previous fallback when no extension
1099
+ // was available — keep that behaviour for the no-base case.
1100
+ const c = counter++;
1101
+ if (safeBase) {
1102
+ const dot = safeBase.lastIndexOf(".");
1103
+ const stem = dot >= 0 ? safeBase.slice(0, dot) : safeBase;
1104
+ const ext = dot >= 0 ? safeBase.slice(dot) : "";
1105
+ candidate = `${stem}_${c}${ext}`;
1106
+ }
1107
+ else {
1108
+ candidate = `image${c}.bin`;
1109
+ }
1110
+ }
1111
+ used.add(candidate);
1112
+ return `Pictures/${candidate}`;
1113
+ };
1114
+ for (const image of images) {
1115
+ const path = allocate(image.fileName ?? image.rId);
1116
+ if (image.rId) {
1117
+ byRId.set(image.rId, path);
1118
+ }
1119
+ if (image.fileName) {
1120
+ // Two distinct images might share a fileName (the inputs are
1121
+ // attacker-controlled in the round-trip path). The first one to
1122
+ // claim a fileName wins the byFileName lookup; later collisions
1123
+ // are still reachable via their own rId in byRId. Without this
1124
+ // guard the second insertion would silently overwrite the first
1125
+ // and inline-image lookups via fileName would resolve to the
1126
+ // wrong binary.
1127
+ if (!byFileName.has(image.fileName)) {
1128
+ byFileName.set(image.fileName, path);
1129
+ }
1130
+ }
1131
+ }
1132
+ return { byRId, byFileName };
1133
+ }
1134
+ /**
1135
+ * Sanitise a single ODT picture file-name component. Strips path
1136
+ * separators, parent-directory traversal, leading dots, and anything
1137
+ * outside a conservative whitelist. Returns an empty string if no usable
1138
+ * characters remain (caller falls back to a generated name).
1139
+ */
1140
+ function sanitizeOdtPictureName(raw) {
1141
+ if (!raw) {
1142
+ return "";
1143
+ }
1144
+ // Drop directory components — we only ever want a leaf file name.
1145
+ const lastSep = Math.max(raw.lastIndexOf("/"), raw.lastIndexOf("\\"));
1146
+ let leaf = lastSep >= 0 ? raw.substring(lastSep + 1) : raw;
1147
+ // Strip leading dots so names like "..png" or ".htaccess" don't sneak
1148
+ // through with attribute meaning to filesystems.
1149
+ while (leaf.startsWith(".")) {
1150
+ leaf = leaf.substring(1);
1151
+ }
1152
+ // Whitelist alnum, dash, underscore, dot. Replace everything else with
1153
+ // underscore. Empty result triggers fallback in the caller.
1154
+ leaf = leaf.replace(/[^A-Za-z0-9._-]/g, "_");
1155
+ // Avoid pathological double-dot anywhere mid-name (e.g. "foo..bin").
1156
+ leaf = leaf.replace(/\.{2,}/g, ".");
1157
+ return leaf;
1158
+ }
1159
+ // =============================================================================
1160
+ // writeOdt — Main Entry Point
1161
+ // =============================================================================
1162
+ /**
1163
+ * Convert a DocxDocument to ODT (OpenDocument Text) format.
1164
+ *
1165
+ * Generates the ZIP archive structure with content.xml, styles.xml,
1166
+ * meta.xml, and META-INF/manifest.xml.
1167
+ *
1168
+ * @param doc - The DocxDocument to convert.
1169
+ * @returns A Uint8Array containing the ODT ZIP archive.
1170
+ *
1171
+ * @stability experimental
1172
+ */
1173
+ async function writeOdt(doc) {
1174
+ const encoder = internal_utils_1.utf8Encoder;
1175
+ const archive = (0, create_archive_1.zip)();
1176
+ // Mimetype MUST be the first entry in the ZIP, uncompressed (ODF spec requirement)
1177
+ archive.add("mimetype", encoder.encode("application/vnd.oasis.opendocument.text"), { level: 0 });
1178
+ // Compute a sanitised rId → Pictures/<safe>.<ext> map up front so the
1179
+ // content writer and archive writer agree on every image path.
1180
+ const imageMap = buildOdtImagePathMap(doc.images);
1181
+ // Collect image paths for manifest
1182
+ const imagePaths = [];
1183
+ // Generate content.xml — the writer reads from imageMap so href values
1184
+ // are guaranteed in-package and free of traversal sequences.
1185
+ const contentXml = generateContentXml(doc, imagePaths, imageMap);
1186
+ archive.add("content.xml", encoder.encode(contentXml));
1187
+ // Generate styles.xml
1188
+ const stylesXml = generateStylesXml(doc);
1189
+ archive.add("styles.xml", encoder.encode(stylesXml));
1190
+ // Generate meta.xml
1191
+ const metaXml = generateMetaXml(doc);
1192
+ archive.add("meta.xml", encoder.encode(metaXml));
1193
+ // Add images at the sanitised paths.
1194
+ if (doc.images) {
1195
+ for (const image of doc.images) {
1196
+ if (!image.data) {
1197
+ continue;
1198
+ }
1199
+ const imgPath = (image.rId ? imageMap.byRId.get(image.rId) : undefined) ??
1200
+ (image.fileName ? imageMap.byFileName.get(image.fileName) : undefined);
1201
+ if (!imgPath) {
1202
+ continue;
1203
+ }
1204
+ archive.add(imgPath, image.data);
1205
+ imagePaths.push(imgPath);
1206
+ }
1207
+ }
1208
+ // Generate META-INF/manifest.xml
1209
+ const manifestXml = generateManifestXml(imagePaths);
1210
+ archive.add("META-INF/manifest.xml", encoder.encode(manifestXml));
1211
+ return archive.bytes();
1212
+ }
1213
+ /** Create a new write context. */
1214
+ function createWriteContext(imageMap) {
1215
+ return {
1216
+ runStyleMap: new Map(),
1217
+ runStyleProps: new Map(),
1218
+ nextRunStyleId: 1,
1219
+ bookmarkNames: new Map(),
1220
+ imagePathByRId: imageMap?.byRId ?? new Map(),
1221
+ imagePathByFileName: imageMap?.byFileName ?? new Map()
1222
+ };
1223
+ }
1224
+ /**
1225
+ * Generate a deterministic cache key for RunProperties.
1226
+ * Only includes formatting-relevant properties.
1227
+ */
1228
+ function runPropsKey(props) {
1229
+ const parts = [];
1230
+ if (props.font) {
1231
+ const fontName = typeof props.font === "string" ? props.font : props.font.ascii;
1232
+ if (fontName) {
1233
+ parts.push(`f:${fontName}`);
1234
+ }
1235
+ }
1236
+ if (props.size !== undefined) {
1237
+ parts.push(`s:${props.size}`);
1238
+ }
1239
+ if (props.bold) {
1240
+ parts.push("b");
1241
+ }
1242
+ if (props.italic) {
1243
+ parts.push("i");
1244
+ }
1245
+ if (props.underline) {
1246
+ parts.push("u");
1247
+ }
1248
+ if (props.strike) {
1249
+ parts.push("st");
1250
+ }
1251
+ if (props.color) {
1252
+ const colorVal = typeof props.color === "string" ? props.color : props.color.val;
1253
+ if (colorVal) {
1254
+ parts.push(`c:${colorVal}`);
1255
+ }
1256
+ }
1257
+ if (props.smallCaps) {
1258
+ parts.push("sc");
1259
+ }
1260
+ if (props.vertAlign) {
1261
+ parts.push(`va:${props.vertAlign}`);
1262
+ }
1263
+ if (props.spacing !== undefined) {
1264
+ parts.push(`sp:${props.spacing}`);
1265
+ }
1266
+ return parts.join("|");
1267
+ }
1268
+ /** Get or create an automatic style name for the given RunProperties. */
1269
+ function getRunAutoStyleName(ctx, props) {
1270
+ const key = runPropsKey(props);
1271
+ let name = ctx.runStyleMap.get(key);
1272
+ if (!name) {
1273
+ name = `T${ctx.nextRunStyleId++}`;
1274
+ ctx.runStyleMap.set(key, name);
1275
+ ctx.runStyleProps.set(name, props);
1276
+ }
1277
+ return name;
1278
+ }
1279
+ /** Generate the content.xml for the ODT package. */
1280
+ function generateContentXml(doc, imagePaths, imageMap) {
1281
+ // First pass: write body to collect automatic run styles
1282
+ const ctx = createWriteContext(imageMap);
1283
+ const bodyWriter = new writer_1.XmlWriter();
1284
+ bodyWriter.openNode("office:body");
1285
+ bodyWriter.openNode("office:text");
1286
+ for (const block of doc.body) {
1287
+ writeBodyContent(bodyWriter, block, doc, imagePaths, ctx);
1288
+ }
1289
+ bodyWriter.closeNode(); // office:text
1290
+ bodyWriter.closeNode(); // office:body
1291
+ const bodyXml = bodyWriter.xml;
1292
+ // Second pass: assemble the full content.xml with collected automatic styles
1293
+ const w = new writer_1.XmlWriter();
1294
+ w.openXml();
1295
+ w.openNode("office:document-content", {
1296
+ "xmlns:office": NS.office,
1297
+ "xmlns:style": NS.style,
1298
+ "xmlns:text": NS.text,
1299
+ "xmlns:table": NS.table,
1300
+ "xmlns:draw": NS.draw,
1301
+ "xmlns:fo": NS.fo,
1302
+ "xmlns:xlink": NS.xlink,
1303
+ "xmlns:svg": NS.svg,
1304
+ "office:version": "1.3"
1305
+ });
1306
+ // Automatic styles section
1307
+ w.openNode("office:automatic-styles");
1308
+ writeAutoStyles(w, doc);
1309
+ writeCollectedRunStyles(w, ctx);
1310
+ w.closeNode();
1311
+ // Body (inject pre-built body XML)
1312
+ w.writeRaw(bodyXml);
1313
+ w.closeNode(); // office:document-content
1314
+ return w.xml;
1315
+ }
1316
+ /** Write collected automatic run styles into the automatic-styles section. */
1317
+ function writeCollectedRunStyles(w, ctx) {
1318
+ for (const [styleName, props] of ctx.runStyleProps) {
1319
+ w.openNode("style:style", {
1320
+ "style:name": styleName,
1321
+ "style:family": "text"
1322
+ });
1323
+ writeTextPropertiesOdf(w, props);
1324
+ w.closeNode();
1325
+ }
1326
+ }
1327
+ /** Write automatic styles based on document content. */
1328
+ function writeAutoStyles(w, doc) {
1329
+ // Output styles from the StyleDef array that exist in the document.
1330
+ if (doc.styles) {
1331
+ for (const styleDef of doc.styles) {
1332
+ writeStyleDef(w, styleDef);
1333
+ }
1334
+ }
1335
+ }
1336
+ /** Write a single StyleDef as an ODF style. */
1337
+ function writeStyleDef(w, def) {
1338
+ const family = styleTypeToOdfFamily(def.type);
1339
+ if (!family) {
1340
+ return;
1341
+ }
1342
+ w.openNode("style:style", {
1343
+ "style:name": def.styleId,
1344
+ "style:family": family,
1345
+ ...(def.basedOn ? { "style:parent-style-name": def.basedOn } : {}),
1346
+ ...(def.name !== def.styleId ? { "style:display-name": def.name } : {})
1347
+ });
1348
+ // Paragraph properties
1349
+ if (def.paragraphProperties) {
1350
+ writeParagraphPropertiesOdf(w, def.paragraphProperties);
1351
+ }
1352
+ // Run/text properties
1353
+ if (def.runProperties) {
1354
+ writeTextPropertiesOdf(w, def.runProperties);
1355
+ }
1356
+ w.closeNode();
1357
+ }
1358
+ /** Convert DocxDocument style type to ODF style family. */
1359
+ function styleTypeToOdfFamily(type) {
1360
+ switch (type) {
1361
+ case "paragraph":
1362
+ return "paragraph";
1363
+ case "character":
1364
+ return "text";
1365
+ case "table":
1366
+ return "table";
1367
+ default:
1368
+ return undefined;
1369
+ }
1370
+ }
1371
+ /** Write paragraph properties as ODF elements. */
1372
+ function writeParagraphPropertiesOdf(w, props) {
1373
+ const attrs = {};
1374
+ if (props.alignment) {
1375
+ attrs["fo:text-align"] = alignmentToOdf(props.alignment);
1376
+ }
1377
+ if (props.indent) {
1378
+ if (props.indent.left !== undefined) {
1379
+ attrs["fo:margin-left"] = twipsToCm(props.indent.left);
1380
+ }
1381
+ if (props.indent.right !== undefined) {
1382
+ attrs["fo:margin-right"] = twipsToCm(props.indent.right);
1383
+ }
1384
+ if (props.indent.firstLine !== undefined) {
1385
+ attrs["fo:text-indent"] = twipsToCm(props.indent.firstLine);
1386
+ }
1387
+ else if (props.indent.hanging !== undefined) {
1388
+ attrs["fo:text-indent"] = twipsToCm(-props.indent.hanging);
1389
+ }
1390
+ }
1391
+ if (props.spacing) {
1392
+ if (props.spacing.before !== undefined) {
1393
+ attrs["fo:margin-top"] = twipsToCm(props.spacing.before);
1394
+ }
1395
+ if (props.spacing.after !== undefined) {
1396
+ attrs["fo:margin-bottom"] = twipsToCm(props.spacing.after);
1397
+ }
1398
+ }
1399
+ if (props.keepNext) {
1400
+ attrs["fo:keep-with-next"] = "always";
1401
+ }
1402
+ if (props.pageBreakBefore) {
1403
+ attrs["fo:break-before"] = "page";
1404
+ }
1405
+ if (Object.keys(attrs).length > 0) {
1406
+ w.leafNode("style:paragraph-properties", attrs);
1407
+ }
1408
+ }
1409
+ /** Write run/text properties as ODF elements. */
1410
+ function writeTextPropertiesOdf(w, props) {
1411
+ const attrs = {};
1412
+ if (props.font) {
1413
+ const fontName = typeof props.font === "string" ? props.font : props.font.ascii;
1414
+ if (fontName) {
1415
+ attrs["style:font-name"] = fontName;
1416
+ }
1417
+ }
1418
+ if (props.size !== undefined) {
1419
+ attrs["fo:font-size"] = halfPointsToPt(props.size);
1420
+ }
1421
+ if (props.bold) {
1422
+ attrs["fo:font-weight"] = "bold";
1423
+ }
1424
+ if (props.italic) {
1425
+ attrs["fo:font-style"] = "italic";
1426
+ }
1427
+ if (props.underline) {
1428
+ attrs["style:text-underline-style"] = "solid";
1429
+ attrs["style:text-underline-width"] = "auto";
1430
+ attrs["style:text-underline-color"] = "font-color";
1431
+ }
1432
+ if (props.strike) {
1433
+ attrs["style:text-line-through-style"] = "solid";
1434
+ }
1435
+ if (props.color) {
1436
+ const colorVal = typeof props.color === "string" ? props.color : props.color.val;
1437
+ if (colorVal && colorVal !== "auto") {
1438
+ attrs["fo:color"] = colorToOdf(colorVal);
1439
+ }
1440
+ }
1441
+ if (props.smallCaps) {
1442
+ attrs["fo:font-variant"] = "small-caps";
1443
+ }
1444
+ if (props.vertAlign === "superscript") {
1445
+ attrs["style:text-position"] = "super 58%";
1446
+ }
1447
+ else if (props.vertAlign === "subscript") {
1448
+ attrs["style:text-position"] = "sub 58%";
1449
+ }
1450
+ if (props.spacing !== undefined) {
1451
+ attrs["fo:letter-spacing"] = twipsToCm(props.spacing);
1452
+ }
1453
+ if (Object.keys(attrs).length > 0) {
1454
+ w.leafNode("style:text-properties", attrs);
1455
+ }
1456
+ }
1457
+ /** Convert OOXML alignment to ODF text-align value. */
1458
+ function alignmentToOdf(alignment) {
1459
+ switch (alignment) {
1460
+ case "left":
1461
+ case "start":
1462
+ return "start";
1463
+ case "center":
1464
+ return "center";
1465
+ case "right":
1466
+ case "end":
1467
+ return "end";
1468
+ case "both":
1469
+ return "justify";
1470
+ default:
1471
+ return "start";
1472
+ }
1473
+ }
1474
+ /** Write a block-level content element to the XML writer. */
1475
+ function writeBodyContent(w, block, doc, imagePaths, ctx) {
1476
+ switch (block.type) {
1477
+ case "paragraph":
1478
+ writeParagraph(w, block, doc, imagePaths, ctx);
1479
+ break;
1480
+ case "table":
1481
+ writeTable(w, block, doc, imagePaths, ctx);
1482
+ break;
1483
+ case "tableOfContents":
1484
+ // Write TOC cached paragraphs if available
1485
+ if (block.cachedParagraphs) {
1486
+ for (const p of block.cachedParagraphs) {
1487
+ writeParagraph(w, p, doc, imagePaths, ctx);
1488
+ }
1489
+ }
1490
+ break;
1491
+ case "math":
1492
+ // Math blocks are rendered as paragraphs with math text
1493
+ w.openNode("text:p");
1494
+ for (const mc of block.content) {
1495
+ if (mc.type === "mathRun") {
1496
+ w.writeText(mc.text);
1497
+ }
1498
+ }
1499
+ w.closeNode();
1500
+ break;
1501
+ default:
1502
+ // Other block types (floatingImage, textBox, etc.) — emit as empty paragraph placeholder
1503
+ w.leafNode("text:p");
1504
+ break;
1505
+ }
1506
+ }
1507
+ /** Write a paragraph element. */
1508
+ function writeParagraph(w, para, doc, imagePaths, ctx) {
1509
+ const isHeading = para.properties?.outlineLevel !== undefined && para.properties.outlineLevel >= 0;
1510
+ const styleName = para.properties?.style;
1511
+ if (isHeading) {
1512
+ const level = (para.properties.outlineLevel ?? 0) + 1;
1513
+ w.openNode("text:h", {
1514
+ ...(styleName ? { "text:style-name": styleName } : {}),
1515
+ "text:outline-level": String(level)
1516
+ });
1517
+ }
1518
+ else {
1519
+ w.openNode("text:p", {
1520
+ ...(styleName ? { "text:style-name": styleName } : {})
1521
+ });
1522
+ }
1523
+ for (const child of para.children) {
1524
+ writeParagraphChild(w, child, doc, imagePaths, ctx);
1525
+ }
1526
+ w.closeNode();
1527
+ }
1528
+ /** Write a paragraph child (Run, Hyperlink, etc.). */
1529
+ function writeParagraphChild(w, child, doc, imagePaths, ctx) {
1530
+ if ((0, text_utils_1.isRun)(child)) {
1531
+ writeRun(w, child, doc, imagePaths, ctx);
1532
+ return;
1533
+ }
1534
+ switch (child.type) {
1535
+ case "hyperlink": {
1536
+ // Defense in depth: even though hyperlinks coming through readDocx /
1537
+ // htmlImport / odtRead are already sanitized, models can be built
1538
+ // by hand. Run the URL through sanitizeUrl one more time before
1539
+ // writing it into the ODT, so a malicious model can't smuggle
1540
+ // javascript:/vbscript: URLs through this writer.
1541
+ const rawHref = child.url ?? (child.anchor ? `#${child.anchor}` : "");
1542
+ const href = rawHref.startsWith("#") ? rawHref : ((0, internal_utils_1.sanitizeUrl)(rawHref) ?? "");
1543
+ if (!href) {
1544
+ // Drop the link wrapper — write children as plain runs.
1545
+ for (const run of child.children) {
1546
+ writeRun(w, run, doc, imagePaths, ctx);
1547
+ }
1548
+ break;
1549
+ }
1550
+ w.openNode("text:a", {
1551
+ "xlink:type": "simple",
1552
+ "xlink:href": href
1553
+ });
1554
+ for (const run of child.children) {
1555
+ writeRun(w, run, doc, imagePaths, ctx);
1556
+ }
1557
+ w.closeNode();
1558
+ break;
1559
+ }
1560
+ case "bookmarkStart":
1561
+ ctx.bookmarkNames.set(child.id, child.name);
1562
+ w.leafNode("text:bookmark-start", { "text:name": child.name });
1563
+ break;
1564
+ case "bookmarkEnd": {
1565
+ const name = ctx.bookmarkNames.get(child.id);
1566
+ if (name !== undefined) {
1567
+ // Emit the matching name so range-aware ODT readers can pair the
1568
+ // start/end markers correctly.
1569
+ w.leafNode("text:bookmark-end", { "text:name": name });
1570
+ }
1571
+ else {
1572
+ // Stray end without a known start (shouldn't happen for documents
1573
+ // produced by this library) — emit with an empty name to keep the
1574
+ // XML well-formed.
1575
+ w.leafNode("text:bookmark-end", { "text:name": "" });
1576
+ }
1577
+ break;
1578
+ }
1579
+ case "insertedRun":
1580
+ writeRun(w, child.run, doc, imagePaths, ctx);
1581
+ break;
1582
+ case "deletedRun":
1583
+ // Deleted runs are typically not shown in the output
1584
+ break;
1585
+ default:
1586
+ // Other paragraph children (comments, etc.) — skip
1587
+ break;
1588
+ }
1589
+ }
1590
+ /** Write a Run (text:span or direct text). */
1591
+ function writeRun(w, run, doc, imagePaths, ctx) {
1592
+ const hasProps = run.properties && Object.keys(run.properties).length > 0;
1593
+ if (hasProps) {
1594
+ const styleName = getRunAutoStyleName(ctx, run.properties);
1595
+ w.openNode("text:span", { "text:style-name": styleName });
1596
+ }
1597
+ for (const content of run.content) {
1598
+ writeRunContent(w, content, doc, imagePaths, ctx);
1599
+ }
1600
+ if (hasProps) {
1601
+ w.closeNode();
1602
+ }
1603
+ }
1604
+ /** Write run content elements. */
1605
+ function writeRunContent(w, content, doc, imagePaths, ctx) {
1606
+ switch (content.type) {
1607
+ case "text":
1608
+ writeOdfText(w, content.text);
1609
+ break;
1610
+ case "break":
1611
+ if (content.breakType === "page") {
1612
+ // ODF 1.2 §5.1.4 — `text:soft-page-break` is a hint that a layout
1613
+ // page break occurs at this position. Strict semantic page breaks
1614
+ // require `fo:break-before="page"` on the surrounding paragraph
1615
+ // automatic style; we emit the soft hint here so the break is at
1616
+ // least preserved (rather than silently dropped, which corrupted
1617
+ // documents on round-trip).
1618
+ w.leafNode("text:soft-page-break");
1619
+ }
1620
+ else if (content.breakType === "column") {
1621
+ // Column breaks degrade to a soft page break in ODF — better than
1622
+ // dropping silently.
1623
+ w.leafNode("text:soft-page-break");
1624
+ }
1625
+ else {
1626
+ w.leafNode("text:line-break");
1627
+ }
1628
+ break;
1629
+ case "tab":
1630
+ w.leafNode("text:tab");
1631
+ break;
1632
+ case "image": {
1633
+ // Write inline image as draw:frame
1634
+ const widthCm = emuToCm(content.width);
1635
+ const heightCm = emuToCm(content.height);
1636
+ // Resolve the safe Pictures/ path that writeOdt registered when it
1637
+ // built the image map. This keeps content.xml's xlink:href in
1638
+ // lockstep with the actual ZIP entry name, and prevents a hostile
1639
+ // rId from emitting a traversing `xlink:href`.
1640
+ const mapped = ctx.imagePathByRId.get(content.rId) ??
1641
+ (content.name ? ctx.imagePathByFileName.get(content.name) : undefined);
1642
+ const imgPath = mapped ?? `Pictures/${sanitizeOdtPictureName(content.rId) || "image.bin"}`;
1643
+ w.openNode("draw:frame", {
1644
+ "draw:name": content.name ?? "",
1645
+ "svg:width": widthCm,
1646
+ "svg:height": heightCm,
1647
+ "text:anchor-type": "as-char"
1648
+ });
1649
+ w.leafNode("draw:image", {
1650
+ "xlink:href": imgPath,
1651
+ "xlink:type": "simple",
1652
+ "xlink:show": "embed",
1653
+ "xlink:actuate": "onLoad"
1654
+ });
1655
+ w.closeNode();
1656
+ break;
1657
+ }
1658
+ case "carriageReturn":
1659
+ w.leafNode("text:line-break");
1660
+ break;
1661
+ case "noBreakHyphen":
1662
+ w.writeText("\u2011");
1663
+ break;
1664
+ case "softHyphen":
1665
+ w.writeText("\u00AD");
1666
+ break;
1667
+ default:
1668
+ // Other content types (field, footnoteRef, etc.) — skip for now
1669
+ break;
1670
+ }
1671
+ }
1672
+ /** Write text content, handling multiple spaces via text:s. */
1673
+ function writeOdfText(w, text) {
1674
+ // ODF collapses whitespace like HTML. Use text:s for multiple spaces.
1675
+ let i = 0;
1676
+ while (i < text.length) {
1677
+ const spaceStart = text.indexOf(" ", i);
1678
+ if (spaceStart < 0) {
1679
+ w.writeText(text.substring(i));
1680
+ break;
1681
+ }
1682
+ // Write text before the spaces
1683
+ if (spaceStart > i) {
1684
+ w.writeText(text.substring(i, spaceStart));
1685
+ }
1686
+ // Count consecutive spaces
1687
+ let spaceCount = 0;
1688
+ let j = spaceStart;
1689
+ while (j < text.length && text[j] === " ") {
1690
+ spaceCount++;
1691
+ j++;
1692
+ }
1693
+ // First space is implicit, rest use text:s
1694
+ w.writeText(" ");
1695
+ if (spaceCount > 1) {
1696
+ w.leafNode("text:s", { "text:c": String(spaceCount - 1) });
1697
+ }
1698
+ i = j;
1699
+ }
1700
+ }
1701
+ /** Write a table element. */
1702
+ function writeTable(w, table, doc, imagePaths, ctx) {
1703
+ w.openNode("table:table", {
1704
+ ...(table.properties?.style ? { "table:style-name": table.properties.style } : {})
1705
+ });
1706
+ // Write column definitions
1707
+ if (table.columnWidths && table.columnWidths.length > 0) {
1708
+ for (const _width of table.columnWidths) {
1709
+ w.leafNode("table:table-column");
1710
+ }
1711
+ }
1712
+ // Write rows
1713
+ for (const row of table.rows) {
1714
+ writeTableRow(w, row, doc, imagePaths, ctx);
1715
+ }
1716
+ w.closeNode();
1717
+ }
1718
+ /** Write a table row. */
1719
+ function writeTableRow(w, row, doc, imagePaths, ctx) {
1720
+ w.openNode("table:table-row");
1721
+ for (const cell of row.cells) {
1722
+ writeTableCell(w, cell, doc, imagePaths, ctx);
1723
+ }
1724
+ w.closeNode();
1725
+ }
1726
+ /** Write a table cell. */
1727
+ function writeTableCell(w, cell, doc, imagePaths, ctx) {
1728
+ const attrs = {};
1729
+ if (cell.properties?.gridSpan && cell.properties.gridSpan > 1) {
1730
+ attrs["table:number-columns-spanned"] = String(cell.properties.gridSpan);
1731
+ }
1732
+ if (cell.properties?.rowSpan && cell.properties.rowSpan > 1) {
1733
+ attrs["table:number-rows-spanned"] = String(cell.properties.rowSpan);
1734
+ }
1735
+ if (cell.properties?.verticalMerge === "continue") {
1736
+ w.leafNode("table:covered-table-cell");
1737
+ return;
1738
+ }
1739
+ w.openNode("table:table-cell", attrs);
1740
+ for (const content of cell.content) {
1741
+ if (content.type === "paragraph") {
1742
+ writeParagraph(w, content, doc, imagePaths, ctx);
1743
+ }
1744
+ else if (content.type === "table") {
1745
+ writeTable(w, content, doc, imagePaths, ctx);
1746
+ }
1747
+ }
1748
+ w.closeNode();
1749
+ }
1750
+ // =============================================================================
1751
+ // Styles XML Generation
1752
+ // =============================================================================
1753
+ /** Generate styles.xml for the ODT package. */
1754
+ function generateStylesXml(doc) {
1755
+ const w = new writer_1.XmlWriter();
1756
+ w.openXml();
1757
+ w.openNode("office:document-styles", {
1758
+ "xmlns:office": NS.office,
1759
+ "xmlns:style": NS.style,
1760
+ "xmlns:text": NS.text,
1761
+ "xmlns:table": NS.table,
1762
+ "xmlns:fo": NS.fo,
1763
+ "xmlns:draw": NS.draw,
1764
+ "xmlns:svg": NS.svg,
1765
+ "office:version": "1.3"
1766
+ });
1767
+ // Office styles (named styles)
1768
+ w.openNode("office:styles");
1769
+ // Default paragraph style
1770
+ w.openNode("style:default-style", { "style:family": "paragraph" });
1771
+ if (doc.docDefaults?.paragraphProperties) {
1772
+ writeParagraphPropertiesOdf(w, doc.docDefaults.paragraphProperties);
1773
+ }
1774
+ if (doc.docDefaults?.runProperties) {
1775
+ writeTextPropertiesOdf(w, doc.docDefaults.runProperties);
1776
+ }
1777
+ else {
1778
+ w.leafNode("style:text-properties", {
1779
+ "fo:font-size": "12pt",
1780
+ "style:font-name": "Times New Roman"
1781
+ });
1782
+ }
1783
+ w.closeNode();
1784
+ // Default table style
1785
+ w.openNode("style:default-style", { "style:family": "table" });
1786
+ w.closeNode();
1787
+ w.closeNode(); // office:styles
1788
+ // Automatic styles (page layout)
1789
+ w.openNode("office:automatic-styles");
1790
+ // Page layout
1791
+ w.openNode("style:page-layout", { "style:name": "pm1" });
1792
+ const pageProps = {};
1793
+ if (doc.sectionProperties?.pageSize) {
1794
+ pageProps["fo:page-width"] = twipsToCm(doc.sectionProperties.pageSize.width);
1795
+ pageProps["fo:page-height"] = twipsToCm(doc.sectionProperties.pageSize.height);
1796
+ if (doc.sectionProperties.pageSize.orientation === "landscape") {
1797
+ pageProps["style:print-orientation"] = "landscape";
1798
+ }
1799
+ }
1800
+ else {
1801
+ // Default A4
1802
+ pageProps["fo:page-width"] = "21.001cm";
1803
+ pageProps["fo:page-height"] = "29.700cm";
1804
+ }
1805
+ if (doc.sectionProperties?.margins) {
1806
+ const m = doc.sectionProperties.margins;
1807
+ pageProps["fo:margin-top"] = twipsToCm(m.top);
1808
+ pageProps["fo:margin-bottom"] = twipsToCm(m.bottom);
1809
+ pageProps["fo:margin-left"] = twipsToCm(m.left);
1810
+ pageProps["fo:margin-right"] = twipsToCm(m.right);
1811
+ }
1812
+ else {
1813
+ // Default 1 inch margins
1814
+ pageProps["fo:margin-top"] = "2.540cm";
1815
+ pageProps["fo:margin-bottom"] = "2.540cm";
1816
+ pageProps["fo:margin-left"] = "2.540cm";
1817
+ pageProps["fo:margin-right"] = "2.540cm";
1818
+ }
1819
+ w.leafNode("style:page-layout-properties", pageProps);
1820
+ w.closeNode(); // style:page-layout
1821
+ w.closeNode(); // office:automatic-styles
1822
+ // Master styles
1823
+ w.openNode("office:master-styles");
1824
+ w.leafNode("style:master-page", {
1825
+ "style:name": "Default",
1826
+ "style:page-layout-name": "pm1"
1827
+ });
1828
+ w.closeNode();
1829
+ w.closeNode(); // office:document-styles
1830
+ return w.xml;
1831
+ }
1832
+ // =============================================================================
1833
+ // Meta XML Generation
1834
+ // =============================================================================
1835
+ /** Generate meta.xml for the ODT package. */
1836
+ function generateMetaXml(doc) {
1837
+ const w = new writer_1.XmlWriter();
1838
+ w.openXml();
1839
+ w.openNode("office:document-meta", {
1840
+ "xmlns:office": NS.office,
1841
+ "xmlns:meta": NS.meta,
1842
+ "xmlns:dc": NS.dc,
1843
+ "office:version": "1.3"
1844
+ });
1845
+ w.openNode("office:meta");
1846
+ if (doc.coreProperties) {
1847
+ const cp = doc.coreProperties;
1848
+ if (cp.title) {
1849
+ w.leafNode("dc:title", undefined, cp.title);
1850
+ }
1851
+ if (cp.subject) {
1852
+ w.leafNode("dc:subject", undefined, cp.subject);
1853
+ }
1854
+ if (cp.creator) {
1855
+ w.leafNode("meta:initial-creator", undefined, cp.creator);
1856
+ w.leafNode("dc:creator", undefined, cp.creator);
1857
+ }
1858
+ if (cp.description) {
1859
+ w.leafNode("dc:description", undefined, cp.description);
1860
+ }
1861
+ if (cp.keywords) {
1862
+ w.leafNode("meta:keyword", undefined, cp.keywords);
1863
+ }
1864
+ if (cp.created) {
1865
+ w.leafNode("meta:creation-date", undefined, cp.created.toISOString());
1866
+ }
1867
+ if (cp.modified) {
1868
+ w.leafNode("dc:date", undefined, cp.modified.toISOString());
1869
+ }
1870
+ }
1871
+ // Generator
1872
+ w.leafNode("meta:generator", undefined, "excelts/odt");
1873
+ w.closeNode(); // office:meta
1874
+ w.closeNode(); // office:document-meta
1875
+ return w.xml;
1876
+ }
1877
+ // =============================================================================
1878
+ // Manifest XML Generation
1879
+ // =============================================================================
1880
+ /** Generate META-INF/manifest.xml for the ODT package. */
1881
+ function generateManifestXml(imagePaths) {
1882
+ const w = new writer_1.XmlWriter();
1883
+ w.openXml();
1884
+ w.openNode("manifest:manifest", {
1885
+ "xmlns:manifest": NS.manifest,
1886
+ "manifest:version": "1.3"
1887
+ });
1888
+ // Root entry
1889
+ w.leafNode("manifest:file-entry", {
1890
+ "manifest:full-path": "/",
1891
+ "manifest:version": "1.3",
1892
+ "manifest:media-type": "application/vnd.oasis.opendocument.text"
1893
+ });
1894
+ // Content parts
1895
+ w.leafNode("manifest:file-entry", {
1896
+ "manifest:full-path": "content.xml",
1897
+ "manifest:media-type": "text/xml"
1898
+ });
1899
+ w.leafNode("manifest:file-entry", {
1900
+ "manifest:full-path": "styles.xml",
1901
+ "manifest:media-type": "text/xml"
1902
+ });
1903
+ w.leafNode("manifest:file-entry", {
1904
+ "manifest:full-path": "meta.xml",
1905
+ "manifest:media-type": "text/xml"
1906
+ });
1907
+ // Images
1908
+ for (const imgPath of imagePaths) {
1909
+ const ext = imgPath.substring(imgPath.lastIndexOf(".") + 1).toLowerCase();
1910
+ let mediaType;
1911
+ switch (ext) {
1912
+ case "png":
1913
+ mediaType = "image/png";
1914
+ break;
1915
+ case "jpg":
1916
+ case "jpeg":
1917
+ mediaType = "image/jpeg";
1918
+ break;
1919
+ case "gif":
1920
+ mediaType = "image/gif";
1921
+ break;
1922
+ case "svg":
1923
+ mediaType = "image/svg+xml";
1924
+ break;
1925
+ default:
1926
+ mediaType = "application/octet-stream";
1927
+ break;
1928
+ }
1929
+ w.leafNode("manifest:file-entry", {
1930
+ "manifest:full-path": imgPath,
1931
+ "manifest:media-type": mediaType
1932
+ });
1933
+ }
1934
+ w.closeNode(); // manifest:manifest
1935
+ return w.xml;
1936
+ }