@cj-tech-master/excelts 9.4.2 → 9.5.0

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 (618) hide show
  1. package/dist/browser/index.browser.d.ts +8 -5
  2. package/dist/browser/index.browser.js +19 -1
  3. package/dist/browser/index.d.ts +4 -2
  4. package/dist/browser/index.js +9 -1
  5. package/dist/browser/modules/excel/chart/cache-populator.d.ts +49 -0
  6. package/dist/browser/modules/excel/chart/cache-populator.js +1171 -0
  7. package/dist/browser/modules/excel/chart/chart-api.d.ts +92 -0
  8. package/dist/browser/modules/excel/chart/chart-api.js +364 -0
  9. package/dist/browser/modules/excel/chart/chart-builder.d.ts +48 -0
  10. package/dist/browser/modules/excel/chart/chart-builder.js +2432 -0
  11. package/dist/browser/modules/excel/chart/chart-ex-builder.d.ts +36 -0
  12. package/dist/browser/modules/excel/chart/chart-ex-builder.js +903 -0
  13. package/dist/browser/modules/excel/chart/chart-ex-parser.d.ts +8 -0
  14. package/dist/browser/modules/excel/chart/chart-ex-parser.js +1205 -0
  15. package/dist/browser/modules/excel/chart/chart-ex-renderer.d.ts +187 -0
  16. package/dist/browser/modules/excel/chart/chart-ex-renderer.js +5352 -0
  17. package/dist/browser/modules/excel/chart/chart-ex-types.d.ts +531 -0
  18. package/dist/browser/modules/excel/chart/chart-ex-types.js +11 -0
  19. package/dist/browser/modules/excel/chart/chart-images.d.ts +78 -0
  20. package/dist/browser/modules/excel/chart/chart-images.js +363 -0
  21. package/dist/browser/modules/excel/chart/chart-presets.d.ts +392 -0
  22. package/dist/browser/modules/excel/chart/chart-presets.js +179 -0
  23. package/dist/browser/modules/excel/chart/chart-renderer.d.ts +550 -0
  24. package/dist/browser/modules/excel/chart/chart-renderer.js +6440 -0
  25. package/dist/browser/modules/excel/chart/chart-sidecar.d.ts +21 -0
  26. package/dist/browser/modules/excel/chart/chart-sidecar.js +427 -0
  27. package/dist/browser/modules/excel/chart/chart-utils.d.ts +306 -0
  28. package/dist/browser/modules/excel/chart/chart-utils.js +821 -0
  29. package/dist/browser/modules/excel/chart/chart.d.ts +504 -0
  30. package/dist/browser/modules/excel/chart/chart.js +1320 -0
  31. package/dist/browser/modules/excel/chart/glyph-rasterizer.d.ts +62 -0
  32. package/dist/browser/modules/excel/chart/glyph-rasterizer.js +658 -0
  33. package/dist/browser/modules/excel/chart/index.d.ts +54 -0
  34. package/dist/browser/modules/excel/chart/index.js +46 -0
  35. package/dist/browser/modules/excel/chart/install.d.ts +44 -0
  36. package/dist/browser/modules/excel/chart/install.js +91 -0
  37. package/dist/browser/modules/excel/chart/shape-properties.d.ts +156 -0
  38. package/dist/browser/modules/excel/chart/shape-properties.js +1557 -0
  39. package/dist/browser/modules/excel/chart/stroke-font.d.ts +36 -0
  40. package/dist/browser/modules/excel/chart/stroke-font.js +1556 -0
  41. package/dist/browser/modules/excel/chart/topojson.d.ts +98 -0
  42. package/dist/browser/modules/excel/chart/topojson.js +236 -0
  43. package/dist/browser/modules/excel/chart/types.d.ts +2559 -0
  44. package/dist/browser/modules/excel/chart/types.js +8 -0
  45. package/dist/browser/modules/excel/chart-host-registry.d.ts +157 -0
  46. package/dist/browser/modules/excel/chart-host-registry.js +90 -0
  47. package/dist/browser/modules/excel/chartsheet.d.ts +102 -0
  48. package/dist/browser/modules/excel/chartsheet.js +196 -0
  49. package/dist/browser/modules/excel/defined-names.d.ts +35 -0
  50. package/dist/browser/modules/excel/defined-names.js +44 -4
  51. package/dist/browser/modules/excel/errors.d.ts +6 -0
  52. package/dist/browser/modules/excel/errors.js +9 -0
  53. package/dist/browser/modules/excel/form-control.d.ts +6 -0
  54. package/dist/browser/modules/excel/form-control.js +17 -0
  55. package/dist/browser/modules/excel/image.js +12 -2
  56. package/dist/browser/modules/excel/pivot-chart.d.ts +7 -0
  57. package/dist/browser/modules/excel/pivot-chart.js +53 -0
  58. package/dist/browser/modules/excel/pivot-table.d.ts +55 -0
  59. package/dist/browser/modules/excel/pivot-table.js +35 -0
  60. package/dist/browser/modules/excel/range.js +5 -1
  61. package/dist/browser/modules/excel/sparkline/index.d.ts +7 -0
  62. package/dist/browser/modules/excel/sparkline/index.js +7 -0
  63. package/dist/browser/modules/excel/sparkline/sparkline.d.ts +206 -0
  64. package/dist/browser/modules/excel/sparkline/sparkline.js +750 -0
  65. package/dist/browser/modules/excel/stream/worksheet-writer.js +3 -2
  66. package/dist/browser/modules/excel/table.js +42 -6
  67. package/dist/browser/modules/excel/types.d.ts +72 -0
  68. package/dist/browser/modules/excel/utils/address.d.ts +18 -0
  69. package/dist/browser/modules/excel/utils/address.js +28 -0
  70. package/dist/browser/modules/excel/utils/drawing-utils.js +11 -6
  71. package/dist/browser/modules/excel/utils/guid.d.ts +15 -0
  72. package/dist/browser/modules/excel/utils/guid.js +35 -0
  73. package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +74 -0
  74. package/dist/browser/modules/excel/utils/ooxml-paths.js +206 -9
  75. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart-sidecar.d.ts +35 -0
  76. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +101 -0
  77. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart.d.ts +32 -0
  78. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart.js +2125 -0
  79. package/dist/browser/modules/excel/utils/ooxml-validator/check-chartsheet.d.ts +9 -0
  80. package/dist/browser/modules/excel/utils/ooxml-validator/check-chartsheet.js +26 -0
  81. package/dist/browser/modules/excel/utils/ooxml-validator/check-content-types.d.ts +16 -0
  82. package/dist/browser/modules/excel/utils/ooxml-validator/check-content-types.js +181 -0
  83. package/dist/browser/modules/excel/utils/ooxml-validator/check-drawing.d.ts +34 -0
  84. package/dist/browser/modules/excel/utils/ooxml-validator/check-drawing.js +267 -0
  85. package/dist/browser/modules/excel/utils/ooxml-validator/check-pivot.d.ts +14 -0
  86. package/dist/browser/modules/excel/utils/ooxml-validator/check-pivot.js +104 -0
  87. package/dist/browser/modules/excel/utils/ooxml-validator/check-relationships.d.ts +18 -0
  88. package/dist/browser/modules/excel/utils/ooxml-validator/check-relationships.js +184 -0
  89. package/dist/browser/modules/excel/utils/ooxml-validator/check-structure.d.ts +21 -0
  90. package/dist/browser/modules/excel/utils/ooxml-validator/check-structure.js +56 -0
  91. package/dist/browser/modules/excel/utils/ooxml-validator/check-styles.d.ts +15 -0
  92. package/dist/browser/modules/excel/utils/ooxml-validator/check-styles.js +89 -0
  93. package/dist/browser/modules/excel/utils/ooxml-validator/check-table.d.ts +31 -0
  94. package/dist/browser/modules/excel/utils/ooxml-validator/check-table.js +177 -0
  95. package/dist/browser/modules/excel/utils/ooxml-validator/check-workbook.d.ts +19 -0
  96. package/dist/browser/modules/excel/utils/ooxml-validator/check-workbook.js +163 -0
  97. package/dist/browser/modules/excel/utils/ooxml-validator/check-worksheet.d.ts +25 -0
  98. package/dist/browser/modules/excel/utils/ooxml-validator/check-worksheet.js +569 -0
  99. package/dist/browser/modules/excel/utils/ooxml-validator/context.d.ts +85 -0
  100. package/dist/browser/modules/excel/utils/ooxml-validator/context.js +191 -0
  101. package/dist/browser/modules/excel/utils/ooxml-validator/index.d.ts +31 -0
  102. package/dist/browser/modules/excel/utils/ooxml-validator/index.js +102 -0
  103. package/dist/browser/modules/excel/utils/ooxml-validator/path-utils.d.ts +67 -0
  104. package/dist/browser/modules/excel/utils/ooxml-validator/path-utils.js +156 -0
  105. package/dist/browser/modules/excel/utils/ooxml-validator/reporter.d.ts +41 -0
  106. package/dist/browser/modules/excel/utils/ooxml-validator/reporter.js +61 -0
  107. package/dist/browser/modules/excel/utils/ooxml-validator/types.d.ts +109 -0
  108. package/dist/browser/modules/excel/utils/ooxml-validator/types.js +12 -0
  109. package/dist/browser/modules/excel/utils/ooxml-validator/xml-utils.d.ts +38 -0
  110. package/dist/browser/modules/excel/utils/ooxml-validator/xml-utils.js +100 -0
  111. package/dist/browser/modules/excel/workbook.browser.d.ts +248 -30
  112. package/dist/browser/modules/excel/workbook.browser.js +966 -31
  113. package/dist/browser/modules/excel/workbook.d.ts +43 -0
  114. package/dist/browser/modules/excel/workbook.js +48 -0
  115. package/dist/browser/modules/excel/worksheet.d.ts +157 -3
  116. package/dist/browser/modules/excel/worksheet.js +394 -35
  117. package/dist/browser/modules/excel/xlsx/rel-type.d.ts +40 -0
  118. package/dist/browser/modules/excel/xlsx/rel-type.js +41 -1
  119. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +1 -0
  120. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  121. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  122. package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  123. package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.d.ts +353 -0
  124. package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.js +6000 -0
  125. package/dist/browser/modules/excel/xlsx/xform/comment/threaded-comments-xform.d.ts +60 -0
  126. package/dist/browser/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +213 -0
  127. package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +150 -11
  128. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  129. package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  130. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +30 -0
  131. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  132. package/dist/browser/modules/excel/xlsx/xform/drawing/graphic-frame-xform.d.ts +54 -0
  133. package/dist/browser/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +225 -0
  134. package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +3 -1
  135. package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  136. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +46 -0
  137. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  138. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +13 -2
  139. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  140. package/dist/browser/modules/excel/xlsx/xform/sheet/chartsheet-xform.d.ts +185 -0
  141. package/dist/browser/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +441 -0
  142. package/dist/browser/modules/excel/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -0
  143. package/dist/browser/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  144. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +196 -20
  145. package/dist/browser/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  146. package/dist/browser/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  147. package/dist/browser/modules/excel/xlsx/xform/xsd-values.d.ts +63 -0
  148. package/dist/browser/modules/excel/xlsx/xform/xsd-values.js +101 -0
  149. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +115 -21
  150. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +4422 -78
  151. package/dist/browser/modules/pdf/builder/document-builder.d.ts +74 -0
  152. package/dist/browser/modules/pdf/builder/document-builder.js +507 -2
  153. package/dist/browser/modules/pdf/builder/pdf-editor.js +48 -3
  154. package/dist/browser/modules/pdf/excel-bridge.d.ts +69 -0
  155. package/dist/browser/modules/pdf/excel-bridge.js +683 -12
  156. package/dist/browser/modules/pdf/font/font-manager.d.ts +25 -0
  157. package/dist/browser/modules/pdf/font/font-manager.js +39 -0
  158. package/dist/browser/modules/pdf/index.d.ts +5 -2
  159. package/dist/browser/modules/pdf/index.js +3 -1
  160. package/dist/browser/modules/pdf/render/chart-surface.d.ts +33 -0
  161. package/dist/browser/modules/pdf/render/chart-surface.js +200 -0
  162. package/dist/browser/modules/pdf/render/layout-engine.d.ts +22 -1
  163. package/dist/browser/modules/pdf/render/layout-engine.js +436 -56
  164. package/dist/browser/modules/pdf/render/page-renderer.js +169 -28
  165. package/dist/browser/modules/pdf/render/pdf-exporter.js +117 -7
  166. package/dist/browser/modules/pdf/types.d.ts +227 -23
  167. package/dist/browser/modules/pdf/types.js +4 -0
  168. package/dist/browser/modules/pdf/word-bridge.d.ts +47 -0
  169. package/dist/browser/modules/pdf/word-bridge.js +304 -0
  170. package/dist/browser/modules/word/constants.d.ts +179 -0
  171. package/dist/browser/modules/word/constants.js +231 -0
  172. package/dist/browser/modules/word/content-types.d.ts +27 -0
  173. package/dist/browser/modules/word/content-types.js +53 -0
  174. package/dist/browser/modules/word/digital-signatures.d.ts +87 -0
  175. package/dist/browser/modules/word/digital-signatures.js +134 -0
  176. package/dist/browser/modules/word/document.d.ts +728 -0
  177. package/dist/browser/modules/word/document.js +1795 -0
  178. package/dist/browser/modules/word/docx-packager.d.ts +14 -0
  179. package/dist/browser/modules/word/docx-packager.js +822 -0
  180. package/dist/browser/modules/word/docx-reader.d.ts +11 -0
  181. package/dist/browser/modules/word/docx-reader.js +4929 -0
  182. package/dist/browser/modules/word/encryption.d.ts +102 -0
  183. package/dist/browser/modules/word/encryption.js +274 -0
  184. package/dist/browser/modules/word/errors.d.ts +49 -0
  185. package/dist/browser/modules/word/errors.js +68 -0
  186. package/dist/browser/modules/word/font-obfuscation.d.ts +31 -0
  187. package/dist/browser/modules/word/font-obfuscation.js +83 -0
  188. package/dist/browser/modules/word/html-renderer.d.ts +38 -0
  189. package/dist/browser/modules/word/html-renderer.js +782 -0
  190. package/dist/browser/modules/word/index.base.d.ts +19 -0
  191. package/dist/browser/modules/word/index.base.js +51 -0
  192. package/dist/browser/modules/word/index.browser.d.ts +4 -0
  193. package/dist/browser/modules/word/index.browser.js +4 -0
  194. package/dist/browser/modules/word/index.d.ts +4 -0
  195. package/dist/browser/modules/word/index.js +4 -0
  196. package/dist/browser/modules/word/internal-utils.d.ts +23 -0
  197. package/dist/browser/modules/word/internal-utils.js +54 -0
  198. package/dist/browser/modules/word/relationships.d.ts +31 -0
  199. package/dist/browser/modules/word/relationships.js +56 -0
  200. package/dist/browser/modules/word/types.d.ts +2325 -0
  201. package/dist/browser/modules/word/types.js +10 -0
  202. package/dist/browser/modules/word/units.d.ts +49 -0
  203. package/dist/browser/modules/word/units.js +111 -0
  204. package/dist/browser/modules/word/writers/chart-writer.d.ts +10 -0
  205. package/dist/browser/modules/word/writers/chart-writer.js +385 -0
  206. package/dist/browser/modules/word/writers/checkbox-writer.d.ts +9 -0
  207. package/dist/browser/modules/word/writers/checkbox-writer.js +42 -0
  208. package/dist/browser/modules/word/writers/comment-writer.d.ts +15 -0
  209. package/dist/browser/modules/word/writers/comment-writer.js +70 -0
  210. package/dist/browser/modules/word/writers/document-writer.d.ts +16 -0
  211. package/dist/browser/modules/word/writers/document-writer.js +461 -0
  212. package/dist/browser/modules/word/writers/footnote-writer.d.ts +11 -0
  213. package/dist/browser/modules/word/writers/footnote-writer.js +72 -0
  214. package/dist/browser/modules/word/writers/header-footer-writer.d.ts +13 -0
  215. package/dist/browser/modules/word/writers/header-footer-writer.js +129 -0
  216. package/dist/browser/modules/word/writers/image-writer.d.ts +10 -0
  217. package/dist/browser/modules/word/writers/image-writer.js +185 -0
  218. package/dist/browser/modules/word/writers/math-writer.d.ts +9 -0
  219. package/dist/browser/modules/word/writers/math-writer.js +428 -0
  220. package/dist/browser/modules/word/writers/numbering-writer.d.ts +10 -0
  221. package/dist/browser/modules/word/writers/numbering-writer.js +125 -0
  222. package/dist/browser/modules/word/writers/paragraph-writer.d.ts +13 -0
  223. package/dist/browser/modules/word/writers/paragraph-writer.js +516 -0
  224. package/dist/browser/modules/word/writers/parts-writer.d.ts +26 -0
  225. package/dist/browser/modules/word/writers/parts-writer.js +660 -0
  226. package/dist/browser/modules/word/writers/run-writer.d.ts +15 -0
  227. package/dist/browser/modules/word/writers/run-writer.js +649 -0
  228. package/dist/browser/modules/word/writers/section-writer.d.ts +10 -0
  229. package/dist/browser/modules/word/writers/section-writer.js +238 -0
  230. package/dist/browser/modules/word/writers/styles-writer.d.ts +10 -0
  231. package/dist/browser/modules/word/writers/styles-writer.js +242 -0
  232. package/dist/browser/modules/word/writers/table-writer.d.ts +10 -0
  233. package/dist/browser/modules/word/writers/table-writer.js +503 -0
  234. package/dist/browser/modules/word/writers/textbox-writer.d.ts +9 -0
  235. package/dist/browser/modules/word/writers/textbox-writer.js +53 -0
  236. package/dist/browser/modules/word/writers/toc-writer.d.ts +9 -0
  237. package/dist/browser/modules/word/writers/toc-writer.js +79 -0
  238. package/dist/browser/modules/xml/encode.d.ts +56 -7
  239. package/dist/browser/modules/xml/encode.js +157 -11
  240. package/dist/cjs/index.js +13 -2
  241. package/dist/cjs/modules/excel/chart/cache-populator.js +1178 -0
  242. package/dist/cjs/modules/excel/chart/chart-api.js +371 -0
  243. package/dist/cjs/modules/excel/chart/chart-builder.js +2440 -0
  244. package/dist/cjs/modules/excel/chart/chart-ex-builder.js +907 -0
  245. package/dist/cjs/modules/excel/chart/chart-ex-parser.js +1208 -0
  246. package/dist/cjs/modules/excel/chart/chart-ex-renderer.js +5364 -0
  247. package/dist/cjs/modules/excel/chart/chart-ex-types.js +12 -0
  248. package/dist/cjs/modules/excel/chart/chart-images.js +366 -0
  249. package/dist/cjs/modules/excel/chart/chart-presets.js +184 -0
  250. package/dist/cjs/modules/excel/chart/chart-renderer.js +6450 -0
  251. package/dist/cjs/modules/excel/chart/chart-sidecar.js +433 -0
  252. package/dist/cjs/modules/excel/chart/chart-utils.js +845 -0
  253. package/dist/cjs/modules/excel/chart/chart.js +1324 -0
  254. package/dist/cjs/modules/excel/chart/glyph-rasterizer.js +664 -0
  255. package/dist/cjs/modules/excel/chart/index.js +101 -0
  256. package/dist/cjs/modules/excel/chart/install.js +95 -0
  257. package/dist/cjs/modules/excel/chart/shape-properties.js +1577 -0
  258. package/dist/cjs/modules/excel/chart/stroke-font.js +1559 -0
  259. package/dist/cjs/modules/excel/chart/topojson.js +239 -0
  260. package/dist/cjs/modules/excel/chart/types.js +9 -0
  261. package/dist/cjs/modules/excel/chart-host-registry.js +96 -0
  262. package/dist/cjs/modules/excel/chartsheet.js +199 -0
  263. package/dist/cjs/modules/excel/defined-names.js +44 -4
  264. package/dist/cjs/modules/excel/errors.js +11 -1
  265. package/dist/cjs/modules/excel/form-control.js +17 -0
  266. package/dist/cjs/modules/excel/image.js +12 -2
  267. package/dist/cjs/modules/excel/pivot-chart.js +56 -0
  268. package/dist/cjs/modules/excel/pivot-table.js +35 -0
  269. package/dist/cjs/modules/excel/range.js +5 -1
  270. package/dist/cjs/modules/excel/sparkline/index.js +23 -0
  271. package/dist/cjs/modules/excel/sparkline/sparkline.js +756 -0
  272. package/dist/cjs/modules/excel/stream/worksheet-writer.js +3 -2
  273. package/dist/cjs/modules/excel/table.js +42 -6
  274. package/dist/cjs/modules/excel/utils/address.js +29 -0
  275. package/dist/cjs/modules/excel/utils/drawing-utils.js +11 -6
  276. package/dist/cjs/modules/excel/utils/guid.js +38 -0
  277. package/dist/cjs/modules/excel/utils/ooxml-paths.js +246 -9
  278. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +103 -0
  279. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chart.js +2128 -0
  280. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chartsheet.js +29 -0
  281. package/dist/cjs/modules/excel/utils/ooxml-validator/check-content-types.js +184 -0
  282. package/dist/cjs/modules/excel/utils/ooxml-validator/check-drawing.js +270 -0
  283. package/dist/cjs/modules/excel/utils/ooxml-validator/check-pivot.js +107 -0
  284. package/dist/cjs/modules/excel/utils/ooxml-validator/check-relationships.js +188 -0
  285. package/dist/cjs/modules/excel/utils/ooxml-validator/check-structure.js +60 -0
  286. package/dist/cjs/modules/excel/utils/ooxml-validator/check-styles.js +92 -0
  287. package/dist/cjs/modules/excel/utils/ooxml-validator/check-table.js +180 -0
  288. package/dist/cjs/modules/excel/utils/ooxml-validator/check-workbook.js +166 -0
  289. package/dist/cjs/modules/excel/utils/ooxml-validator/check-worksheet.js +572 -0
  290. package/dist/cjs/modules/excel/utils/ooxml-validator/context.js +196 -0
  291. package/dist/cjs/modules/excel/utils/ooxml-validator/index.js +105 -0
  292. package/dist/cjs/modules/excel/utils/ooxml-validator/path-utils.js +168 -0
  293. package/dist/cjs/modules/excel/utils/ooxml-validator/reporter.js +66 -0
  294. package/dist/cjs/modules/excel/utils/ooxml-validator/types.js +13 -0
  295. package/dist/cjs/modules/excel/utils/ooxml-validator/xml-utils.js +110 -0
  296. package/dist/cjs/modules/excel/workbook.browser.js +973 -38
  297. package/dist/cjs/modules/excel/workbook.js +48 -0
  298. package/dist/cjs/modules/excel/worksheet.js +393 -34
  299. package/dist/cjs/modules/excel/xlsx/rel-type.js +41 -1
  300. package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  301. package/dist/cjs/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  302. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  303. package/dist/cjs/modules/excel/xlsx/xform/chart/chart-space-xform.js +6003 -0
  304. package/dist/cjs/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +219 -0
  305. package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +149 -10
  306. package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  307. package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  308. package/dist/cjs/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  309. package/dist/cjs/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +228 -0
  310. package/dist/cjs/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  311. package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  312. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  313. package/dist/cjs/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +444 -0
  314. package/dist/cjs/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  315. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +195 -19
  316. package/dist/cjs/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  317. package/dist/cjs/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  318. package/dist/cjs/modules/excel/xlsx/xform/xsd-values.js +106 -0
  319. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +4420 -76
  320. package/dist/cjs/modules/pdf/builder/document-builder.js +506 -1
  321. package/dist/cjs/modules/pdf/builder/pdf-editor.js +48 -3
  322. package/dist/cjs/modules/pdf/excel-bridge.js +684 -12
  323. package/dist/cjs/modules/pdf/font/font-manager.js +39 -0
  324. package/dist/cjs/modules/pdf/index.js +5 -1
  325. package/dist/cjs/modules/pdf/render/chart-surface.js +203 -0
  326. package/dist/cjs/modules/pdf/render/layout-engine.js +437 -56
  327. package/dist/cjs/modules/pdf/render/page-renderer.js +169 -28
  328. package/dist/cjs/modules/pdf/render/pdf-exporter.js +115 -5
  329. package/dist/cjs/modules/pdf/types.js +5 -0
  330. package/dist/cjs/modules/pdf/word-bridge.js +307 -0
  331. package/dist/cjs/modules/word/constants.js +234 -0
  332. package/dist/cjs/modules/word/content-types.js +57 -0
  333. package/dist/cjs/modules/word/digital-signatures.js +140 -0
  334. package/dist/cjs/modules/word/document.js +1909 -0
  335. package/dist/cjs/modules/word/docx-packager.js +825 -0
  336. package/dist/cjs/modules/word/docx-reader.js +4932 -0
  337. package/dist/cjs/modules/word/encryption.js +282 -0
  338. package/dist/cjs/modules/word/errors.js +88 -0
  339. package/dist/cjs/modules/word/font-obfuscation.js +88 -0
  340. package/dist/cjs/modules/word/html-renderer.js +785 -0
  341. package/dist/cjs/modules/word/index.base.js +199 -0
  342. package/dist/cjs/modules/word/index.browser.js +20 -0
  343. package/dist/cjs/modules/word/index.js +20 -0
  344. package/dist/cjs/modules/word/internal-utils.js +59 -0
  345. package/dist/cjs/modules/word/relationships.js +60 -0
  346. package/dist/cjs/modules/word/types.js +11 -0
  347. package/dist/cjs/modules/word/units.js +135 -0
  348. package/dist/cjs/modules/word/writers/chart-writer.js +388 -0
  349. package/dist/cjs/modules/word/writers/checkbox-writer.js +45 -0
  350. package/dist/cjs/modules/word/writers/comment-writer.js +74 -0
  351. package/dist/cjs/modules/word/writers/document-writer.js +465 -0
  352. package/dist/cjs/modules/word/writers/footnote-writer.js +76 -0
  353. package/dist/cjs/modules/word/writers/header-footer-writer.js +134 -0
  354. package/dist/cjs/modules/word/writers/image-writer.js +188 -0
  355. package/dist/cjs/modules/word/writers/math-writer.js +431 -0
  356. package/dist/cjs/modules/word/writers/numbering-writer.js +128 -0
  357. package/dist/cjs/modules/word/writers/paragraph-writer.js +521 -0
  358. package/dist/cjs/modules/word/writers/parts-writer.js +671 -0
  359. package/dist/cjs/modules/word/writers/run-writer.js +655 -0
  360. package/dist/cjs/modules/word/writers/section-writer.js +241 -0
  361. package/dist/cjs/modules/word/writers/styles-writer.js +245 -0
  362. package/dist/cjs/modules/word/writers/table-writer.js +506 -0
  363. package/dist/cjs/modules/word/writers/textbox-writer.js +56 -0
  364. package/dist/cjs/modules/word/writers/toc-writer.js +82 -0
  365. package/dist/cjs/modules/xml/encode.js +158 -11
  366. package/dist/esm/index.browser.js +20 -2
  367. package/dist/esm/index.js +9 -1
  368. package/dist/esm/modules/excel/chart/cache-populator.js +1171 -0
  369. package/dist/esm/modules/excel/chart/chart-api.js +364 -0
  370. package/dist/esm/modules/excel/chart/chart-builder.js +2432 -0
  371. package/dist/esm/modules/excel/chart/chart-ex-builder.js +903 -0
  372. package/dist/esm/modules/excel/chart/chart-ex-parser.js +1205 -0
  373. package/dist/esm/modules/excel/chart/chart-ex-renderer.js +5352 -0
  374. package/dist/esm/modules/excel/chart/chart-ex-types.js +11 -0
  375. package/dist/esm/modules/excel/chart/chart-images.js +363 -0
  376. package/dist/esm/modules/excel/chart/chart-presets.js +179 -0
  377. package/dist/esm/modules/excel/chart/chart-renderer.js +6440 -0
  378. package/dist/esm/modules/excel/chart/chart-sidecar.js +427 -0
  379. package/dist/esm/modules/excel/chart/chart-utils.js +821 -0
  380. package/dist/esm/modules/excel/chart/chart.js +1320 -0
  381. package/dist/esm/modules/excel/chart/glyph-rasterizer.js +658 -0
  382. package/dist/esm/modules/excel/chart/index.js +46 -0
  383. package/dist/esm/modules/excel/chart/install.js +91 -0
  384. package/dist/esm/modules/excel/chart/shape-properties.js +1557 -0
  385. package/dist/esm/modules/excel/chart/stroke-font.js +1556 -0
  386. package/dist/esm/modules/excel/chart/topojson.js +236 -0
  387. package/dist/esm/modules/excel/chart/types.js +8 -0
  388. package/dist/esm/modules/excel/chart-host-registry.js +90 -0
  389. package/dist/esm/modules/excel/chartsheet.js +196 -0
  390. package/dist/esm/modules/excel/defined-names.js +44 -4
  391. package/dist/esm/modules/excel/errors.js +9 -0
  392. package/dist/esm/modules/excel/form-control.js +17 -0
  393. package/dist/esm/modules/excel/image.js +12 -2
  394. package/dist/esm/modules/excel/pivot-chart.js +53 -0
  395. package/dist/esm/modules/excel/pivot-table.js +35 -0
  396. package/dist/esm/modules/excel/range.js +5 -1
  397. package/dist/esm/modules/excel/sparkline/index.js +7 -0
  398. package/dist/esm/modules/excel/sparkline/sparkline.js +750 -0
  399. package/dist/esm/modules/excel/stream/worksheet-writer.js +3 -2
  400. package/dist/esm/modules/excel/table.js +42 -6
  401. package/dist/esm/modules/excel/utils/address.js +28 -0
  402. package/dist/esm/modules/excel/utils/drawing-utils.js +11 -6
  403. package/dist/esm/modules/excel/utils/guid.js +35 -0
  404. package/dist/esm/modules/excel/utils/ooxml-paths.js +206 -9
  405. package/dist/esm/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +101 -0
  406. package/dist/esm/modules/excel/utils/ooxml-validator/check-chart.js +2125 -0
  407. package/dist/esm/modules/excel/utils/ooxml-validator/check-chartsheet.js +26 -0
  408. package/dist/esm/modules/excel/utils/ooxml-validator/check-content-types.js +181 -0
  409. package/dist/esm/modules/excel/utils/ooxml-validator/check-drawing.js +267 -0
  410. package/dist/esm/modules/excel/utils/ooxml-validator/check-pivot.js +104 -0
  411. package/dist/esm/modules/excel/utils/ooxml-validator/check-relationships.js +184 -0
  412. package/dist/esm/modules/excel/utils/ooxml-validator/check-structure.js +56 -0
  413. package/dist/esm/modules/excel/utils/ooxml-validator/check-styles.js +89 -0
  414. package/dist/esm/modules/excel/utils/ooxml-validator/check-table.js +177 -0
  415. package/dist/esm/modules/excel/utils/ooxml-validator/check-workbook.js +163 -0
  416. package/dist/esm/modules/excel/utils/ooxml-validator/check-worksheet.js +569 -0
  417. package/dist/esm/modules/excel/utils/ooxml-validator/context.js +191 -0
  418. package/dist/esm/modules/excel/utils/ooxml-validator/index.js +102 -0
  419. package/dist/esm/modules/excel/utils/ooxml-validator/path-utils.js +156 -0
  420. package/dist/esm/modules/excel/utils/ooxml-validator/reporter.js +61 -0
  421. package/dist/esm/modules/excel/utils/ooxml-validator/types.js +12 -0
  422. package/dist/esm/modules/excel/utils/ooxml-validator/xml-utils.js +100 -0
  423. package/dist/esm/modules/excel/workbook.browser.js +969 -34
  424. package/dist/esm/modules/excel/workbook.js +48 -0
  425. package/dist/esm/modules/excel/worksheet.js +394 -35
  426. package/dist/esm/modules/excel/xlsx/rel-type.js +41 -1
  427. package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  428. package/dist/esm/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  429. package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  430. package/dist/esm/modules/excel/xlsx/xform/chart/chart-space-xform.js +6000 -0
  431. package/dist/esm/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +213 -0
  432. package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +150 -11
  433. package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  434. package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  435. package/dist/esm/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  436. package/dist/esm/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +225 -0
  437. package/dist/esm/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  438. package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  439. package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  440. package/dist/esm/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +441 -0
  441. package/dist/esm/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  442. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +196 -20
  443. package/dist/esm/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  444. package/dist/esm/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  445. package/dist/esm/modules/excel/xlsx/xform/xsd-values.js +101 -0
  446. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +4422 -78
  447. package/dist/esm/modules/pdf/builder/document-builder.js +507 -2
  448. package/dist/esm/modules/pdf/builder/pdf-editor.js +48 -3
  449. package/dist/esm/modules/pdf/excel-bridge.js +683 -12
  450. package/dist/esm/modules/pdf/font/font-manager.js +39 -0
  451. package/dist/esm/modules/pdf/index.js +3 -1
  452. package/dist/esm/modules/pdf/render/chart-surface.js +200 -0
  453. package/dist/esm/modules/pdf/render/layout-engine.js +436 -56
  454. package/dist/esm/modules/pdf/render/page-renderer.js +169 -28
  455. package/dist/esm/modules/pdf/render/pdf-exporter.js +117 -7
  456. package/dist/esm/modules/pdf/types.js +4 -0
  457. package/dist/esm/modules/pdf/word-bridge.js +304 -0
  458. package/dist/esm/modules/word/constants.js +231 -0
  459. package/dist/esm/modules/word/content-types.js +53 -0
  460. package/dist/esm/modules/word/digital-signatures.js +134 -0
  461. package/dist/esm/modules/word/document.js +1795 -0
  462. package/dist/esm/modules/word/docx-packager.js +822 -0
  463. package/dist/esm/modules/word/docx-reader.js +4929 -0
  464. package/dist/esm/modules/word/encryption.js +274 -0
  465. package/dist/esm/modules/word/errors.js +68 -0
  466. package/dist/esm/modules/word/font-obfuscation.js +83 -0
  467. package/dist/esm/modules/word/html-renderer.js +782 -0
  468. package/dist/esm/modules/word/index.base.js +51 -0
  469. package/dist/esm/modules/word/index.browser.js +4 -0
  470. package/dist/esm/modules/word/index.js +4 -0
  471. package/dist/esm/modules/word/internal-utils.js +54 -0
  472. package/dist/esm/modules/word/relationships.js +56 -0
  473. package/dist/esm/modules/word/types.js +10 -0
  474. package/dist/esm/modules/word/units.js +111 -0
  475. package/dist/esm/modules/word/writers/chart-writer.js +385 -0
  476. package/dist/esm/modules/word/writers/checkbox-writer.js +42 -0
  477. package/dist/esm/modules/word/writers/comment-writer.js +70 -0
  478. package/dist/esm/modules/word/writers/document-writer.js +461 -0
  479. package/dist/esm/modules/word/writers/footnote-writer.js +72 -0
  480. package/dist/esm/modules/word/writers/header-footer-writer.js +129 -0
  481. package/dist/esm/modules/word/writers/image-writer.js +185 -0
  482. package/dist/esm/modules/word/writers/math-writer.js +428 -0
  483. package/dist/esm/modules/word/writers/numbering-writer.js +125 -0
  484. package/dist/esm/modules/word/writers/paragraph-writer.js +516 -0
  485. package/dist/esm/modules/word/writers/parts-writer.js +660 -0
  486. package/dist/esm/modules/word/writers/run-writer.js +649 -0
  487. package/dist/esm/modules/word/writers/section-writer.js +238 -0
  488. package/dist/esm/modules/word/writers/styles-writer.js +242 -0
  489. package/dist/esm/modules/word/writers/table-writer.js +503 -0
  490. package/dist/esm/modules/word/writers/textbox-writer.js +53 -0
  491. package/dist/esm/modules/word/writers/toc-writer.js +79 -0
  492. package/dist/esm/modules/xml/encode.js +157 -11
  493. package/dist/iife/excelts.iife.js +11789 -687
  494. package/dist/iife/excelts.iife.js.map +1 -1
  495. package/dist/iife/excelts.iife.min.js +52 -44
  496. package/dist/types/index.browser.d.ts +8 -5
  497. package/dist/types/index.d.ts +4 -2
  498. package/dist/types/modules/excel/chart/cache-populator.d.ts +49 -0
  499. package/dist/types/modules/excel/chart/chart-api.d.ts +92 -0
  500. package/dist/types/modules/excel/chart/chart-builder.d.ts +48 -0
  501. package/dist/types/modules/excel/chart/chart-ex-builder.d.ts +36 -0
  502. package/dist/types/modules/excel/chart/chart-ex-parser.d.ts +8 -0
  503. package/dist/types/modules/excel/chart/chart-ex-renderer.d.ts +187 -0
  504. package/dist/types/modules/excel/chart/chart-ex-types.d.ts +531 -0
  505. package/dist/types/modules/excel/chart/chart-images.d.ts +78 -0
  506. package/dist/types/modules/excel/chart/chart-presets.d.ts +392 -0
  507. package/dist/types/modules/excel/chart/chart-renderer.d.ts +550 -0
  508. package/dist/types/modules/excel/chart/chart-sidecar.d.ts +21 -0
  509. package/dist/types/modules/excel/chart/chart-utils.d.ts +306 -0
  510. package/dist/types/modules/excel/chart/chart.d.ts +504 -0
  511. package/dist/types/modules/excel/chart/glyph-rasterizer.d.ts +62 -0
  512. package/dist/types/modules/excel/chart/index.d.ts +54 -0
  513. package/dist/types/modules/excel/chart/install.d.ts +44 -0
  514. package/dist/types/modules/excel/chart/shape-properties.d.ts +156 -0
  515. package/dist/types/modules/excel/chart/stroke-font.d.ts +36 -0
  516. package/dist/types/modules/excel/chart/topojson.d.ts +98 -0
  517. package/dist/types/modules/excel/chart/types.d.ts +2559 -0
  518. package/dist/types/modules/excel/chart-host-registry.d.ts +157 -0
  519. package/dist/types/modules/excel/chartsheet.d.ts +102 -0
  520. package/dist/types/modules/excel/defined-names.d.ts +35 -0
  521. package/dist/types/modules/excel/errors.d.ts +6 -0
  522. package/dist/types/modules/excel/form-control.d.ts +6 -0
  523. package/dist/types/modules/excel/pivot-chart.d.ts +7 -0
  524. package/dist/types/modules/excel/pivot-table.d.ts +55 -0
  525. package/dist/types/modules/excel/sparkline/index.d.ts +7 -0
  526. package/dist/types/modules/excel/sparkline/sparkline.d.ts +206 -0
  527. package/dist/types/modules/excel/types.d.ts +72 -0
  528. package/dist/types/modules/excel/utils/address.d.ts +18 -0
  529. package/dist/types/modules/excel/utils/guid.d.ts +15 -0
  530. package/dist/types/modules/excel/utils/ooxml-paths.d.ts +74 -0
  531. package/dist/types/modules/excel/utils/ooxml-validator/check-chart-sidecar.d.ts +35 -0
  532. package/dist/types/modules/excel/utils/ooxml-validator/check-chart.d.ts +32 -0
  533. package/dist/types/modules/excel/utils/ooxml-validator/check-chartsheet.d.ts +9 -0
  534. package/dist/types/modules/excel/utils/ooxml-validator/check-content-types.d.ts +16 -0
  535. package/dist/types/modules/excel/utils/ooxml-validator/check-drawing.d.ts +34 -0
  536. package/dist/types/modules/excel/utils/ooxml-validator/check-pivot.d.ts +14 -0
  537. package/dist/types/modules/excel/utils/ooxml-validator/check-relationships.d.ts +18 -0
  538. package/dist/types/modules/excel/utils/ooxml-validator/check-structure.d.ts +21 -0
  539. package/dist/types/modules/excel/utils/ooxml-validator/check-styles.d.ts +15 -0
  540. package/dist/types/modules/excel/utils/ooxml-validator/check-table.d.ts +31 -0
  541. package/dist/types/modules/excel/utils/ooxml-validator/check-workbook.d.ts +19 -0
  542. package/dist/types/modules/excel/utils/ooxml-validator/check-worksheet.d.ts +25 -0
  543. package/dist/types/modules/excel/utils/ooxml-validator/context.d.ts +85 -0
  544. package/dist/types/modules/excel/utils/ooxml-validator/index.d.ts +31 -0
  545. package/dist/types/modules/excel/utils/ooxml-validator/path-utils.d.ts +67 -0
  546. package/dist/types/modules/excel/utils/ooxml-validator/reporter.d.ts +41 -0
  547. package/dist/types/modules/excel/utils/ooxml-validator/types.d.ts +109 -0
  548. package/dist/types/modules/excel/utils/ooxml-validator/xml-utils.d.ts +38 -0
  549. package/dist/types/modules/excel/workbook.browser.d.ts +248 -30
  550. package/dist/types/modules/excel/workbook.d.ts +43 -0
  551. package/dist/types/modules/excel/worksheet.d.ts +157 -3
  552. package/dist/types/modules/excel/xlsx/rel-type.d.ts +40 -0
  553. package/dist/types/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +1 -0
  554. package/dist/types/modules/excel/xlsx/xform/chart/chart-space-xform.d.ts +353 -0
  555. package/dist/types/modules/excel/xlsx/xform/comment/threaded-comments-xform.d.ts +60 -0
  556. package/dist/types/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +30 -0
  557. package/dist/types/modules/excel/xlsx/xform/drawing/graphic-frame-xform.d.ts +54 -0
  558. package/dist/types/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +3 -1
  559. package/dist/types/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +46 -0
  560. package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +13 -2
  561. package/dist/types/modules/excel/xlsx/xform/sheet/chartsheet-xform.d.ts +185 -0
  562. package/dist/types/modules/excel/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -0
  563. package/dist/types/modules/excel/xlsx/xform/xsd-values.d.ts +63 -0
  564. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +115 -21
  565. package/dist/types/modules/pdf/builder/document-builder.d.ts +74 -0
  566. package/dist/types/modules/pdf/excel-bridge.d.ts +69 -0
  567. package/dist/types/modules/pdf/font/font-manager.d.ts +25 -0
  568. package/dist/types/modules/pdf/index.d.ts +5 -2
  569. package/dist/types/modules/pdf/render/chart-surface.d.ts +33 -0
  570. package/dist/types/modules/pdf/render/layout-engine.d.ts +22 -1
  571. package/dist/types/modules/pdf/types.d.ts +227 -23
  572. package/dist/types/modules/pdf/word-bridge.d.ts +47 -0
  573. package/dist/types/modules/word/constants.d.ts +179 -0
  574. package/dist/types/modules/word/content-types.d.ts +27 -0
  575. package/dist/types/modules/word/digital-signatures.d.ts +87 -0
  576. package/dist/types/modules/word/document.d.ts +728 -0
  577. package/dist/types/modules/word/docx-packager.d.ts +14 -0
  578. package/dist/types/modules/word/docx-reader.d.ts +11 -0
  579. package/dist/types/modules/word/encryption.d.ts +102 -0
  580. package/dist/types/modules/word/errors.d.ts +49 -0
  581. package/dist/types/modules/word/font-obfuscation.d.ts +31 -0
  582. package/dist/types/modules/word/html-renderer.d.ts +38 -0
  583. package/dist/types/modules/word/index.base.d.ts +19 -0
  584. package/dist/types/modules/word/index.browser.d.ts +4 -0
  585. package/dist/types/modules/word/index.d.ts +4 -0
  586. package/dist/types/modules/word/internal-utils.d.ts +23 -0
  587. package/dist/types/modules/word/relationships.d.ts +31 -0
  588. package/dist/types/modules/word/types.d.ts +2325 -0
  589. package/dist/types/modules/word/units.d.ts +49 -0
  590. package/dist/types/modules/word/writers/chart-writer.d.ts +10 -0
  591. package/dist/types/modules/word/writers/checkbox-writer.d.ts +9 -0
  592. package/dist/types/modules/word/writers/comment-writer.d.ts +15 -0
  593. package/dist/types/modules/word/writers/document-writer.d.ts +16 -0
  594. package/dist/types/modules/word/writers/footnote-writer.d.ts +11 -0
  595. package/dist/types/modules/word/writers/header-footer-writer.d.ts +13 -0
  596. package/dist/types/modules/word/writers/image-writer.d.ts +10 -0
  597. package/dist/types/modules/word/writers/math-writer.d.ts +9 -0
  598. package/dist/types/modules/word/writers/numbering-writer.d.ts +10 -0
  599. package/dist/types/modules/word/writers/paragraph-writer.d.ts +13 -0
  600. package/dist/types/modules/word/writers/parts-writer.d.ts +26 -0
  601. package/dist/types/modules/word/writers/run-writer.d.ts +15 -0
  602. package/dist/types/modules/word/writers/section-writer.d.ts +10 -0
  603. package/dist/types/modules/word/writers/styles-writer.d.ts +10 -0
  604. package/dist/types/modules/word/writers/table-writer.d.ts +10 -0
  605. package/dist/types/modules/word/writers/textbox-writer.d.ts +9 -0
  606. package/dist/types/modules/word/writers/toc-writer.d.ts +9 -0
  607. package/dist/types/modules/xml/encode.d.ts +56 -7
  608. package/package.json +29 -11
  609. package/dist/browser/modules/excel/utils/ooxml-validator.d.ts +0 -48
  610. package/dist/browser/modules/excel/utils/ooxml-validator.js +0 -493
  611. package/dist/browser/modules/excel/utils/passthrough-manager.d.ts +0 -77
  612. package/dist/browser/modules/excel/utils/passthrough-manager.js +0 -129
  613. package/dist/cjs/modules/excel/utils/ooxml-validator.js +0 -499
  614. package/dist/cjs/modules/excel/utils/passthrough-manager.js +0 -133
  615. package/dist/esm/modules/excel/utils/ooxml-validator.js +0 -493
  616. package/dist/esm/modules/excel/utils/passthrough-manager.js +0 -129
  617. package/dist/types/modules/excel/utils/ooxml-validator.d.ts +0 -48
  618. package/dist/types/modules/excel/utils/passthrough-manager.d.ts +0 -77
@@ -0,0 +1,4932 @@
1
+ "use strict";
2
+ /**
3
+ * DOCX Module - Reader / Parser
4
+ *
5
+ * Reads a DOCX ZIP file and parses it into a DocxDocument model.
6
+ * Uses the archive module for ZIP reading and XML module for parsing.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.readDocx = readDocx;
10
+ const read_archive_1 = require("../archive/read-archive.js");
11
+ const dom_1 = require("../xml/dom.js");
12
+ const constants_1 = require("./constants");
13
+ const errors_1 = require("./errors");
14
+ // Module-level parsing context: set at the start of readDocx, used by parseParagraph etc.
15
+ let _parseRelMap = new Map();
16
+ // =============================================================================
17
+ // Helper Functions
18
+ // =============================================================================
19
+ function attrVal(el, name) {
20
+ // Try with w: prefix and without
21
+ return el.attributes[`w:${name}`] ?? el.attributes[name];
22
+ }
23
+ function attrInt(el, name) {
24
+ const v = attrVal(el, name);
25
+ if (v === undefined) {
26
+ return undefined;
27
+ }
28
+ const n = parseInt(v, 10);
29
+ return Number.isFinite(n) ? n : undefined;
30
+ }
31
+ /**
32
+ * Read an attribute as a strict boolean:
33
+ * "1"|"true" → true
34
+ * "0"|"false" → false
35
+ * otherwise → undefined
36
+ * Useful for attributes where default-false vs explicit-false matters.
37
+ */
38
+ function _attrBool(el, name) {
39
+ const v = attrVal(el, name);
40
+ if (v === undefined) {
41
+ return undefined;
42
+ }
43
+ if (v === "1" || v === "true") {
44
+ return true;
45
+ }
46
+ if (v === "0" || v === "false") {
47
+ return false;
48
+ }
49
+ return undefined;
50
+ }
51
+ function findChildNs(el, localName) {
52
+ // Match either w:localName or just localName
53
+ return (0, dom_1.findChild)(el, `w:${localName}`) ?? (0, dom_1.findChild)(el, localName);
54
+ }
55
+ function findChildrenNs(el, localName) {
56
+ const a = (0, dom_1.findChildren)(el, `w:${localName}`);
57
+ return a.length > 0 ? a : (0, dom_1.findChildren)(el, localName);
58
+ }
59
+ /** Check for a boolean toggle element (present = true, w:val="0" or "false" = false). */
60
+ function boolToggle(parent, name) {
61
+ const el = findChildNs(parent, name);
62
+ if (!el) {
63
+ return undefined;
64
+ }
65
+ const v = attrVal(el, "val");
66
+ if (v === "0" || v === "false") {
67
+ return false;
68
+ }
69
+ return true;
70
+ }
71
+ /** Escape special XML characters in text content. */
72
+ function escapeXml(s) {
73
+ return s
74
+ .replace(/&/g, "&")
75
+ .replace(/</g, "&lt;")
76
+ .replace(/>/g, "&gt;")
77
+ .replace(/"/g, "&quot;");
78
+ }
79
+ /** Serialize an XmlElement back to an XML string (for opaque preservation). */
80
+ function serializeElement(el) {
81
+ let s = `<${el.name}`;
82
+ for (const [k, v] of Object.entries(el.attributes)) {
83
+ s += ` ${k}="${escapeXml(v)}"`;
84
+ }
85
+ if (el.children.length === 0) {
86
+ return s + "/>";
87
+ }
88
+ s += ">";
89
+ for (const child of el.children) {
90
+ if (child.type === "element") {
91
+ s += serializeElement(child);
92
+ }
93
+ else if (child.type === "text") {
94
+ s += escapeXml(child.value);
95
+ }
96
+ }
97
+ s += `</${el.name}>`;
98
+ return s;
99
+ }
100
+ /** Extract all r:xxx attribute values (relationship IDs) from an element tree. */
101
+ function collectRIds(el, out) {
102
+ for (const [k, v] of Object.entries(el.attributes)) {
103
+ if (k.startsWith("r:") || k === "r:id" || k === "r:embed" || k === "r:link") {
104
+ out.add(v);
105
+ }
106
+ }
107
+ for (const child of el.children) {
108
+ if (child.type === "element") {
109
+ collectRIds(child, out);
110
+ }
111
+ }
112
+ }
113
+ /** Get the .rels path for a given part path. */
114
+ function getPartRelsPath(partPath) {
115
+ const lastSlash = partPath.lastIndexOf("/");
116
+ const dir = lastSlash >= 0 ? partPath.substring(0, lastSlash) : "";
117
+ const name = lastSlash >= 0 ? partPath.substring(lastSlash + 1) : partPath;
118
+ return dir ? `${dir}/_rels/${name}.rels` : `_rels/${name}.rels`;
119
+ }
120
+ /**
121
+ * Resolve a relationship target path to an absolute package-root path.
122
+ *
123
+ * - Leading "/" → package root absolute
124
+ * - "../" / "./" → resolved relative to the source part's directory
125
+ * - Plain paths → resolved relative to the source part's directory
126
+ */
127
+ function resolvePartPath(sourcePart, target) {
128
+ if (!target) {
129
+ return "";
130
+ }
131
+ if (target.startsWith("/")) {
132
+ return target.slice(1);
133
+ }
134
+ const lastSlash = sourcePart.lastIndexOf("/");
135
+ const baseDir = lastSlash >= 0 ? sourcePart.substring(0, lastSlash).split("/") : [];
136
+ const segs = target.split("/");
137
+ for (const seg of segs) {
138
+ if (seg === "..") {
139
+ baseDir.pop();
140
+ }
141
+ else if (seg !== "." && seg !== "") {
142
+ baseDir.push(seg);
143
+ }
144
+ }
145
+ return baseDir.join("/");
146
+ }
147
+ /** Parse footnote/endnote properties element. */
148
+ function parseNoteProperties(el) {
149
+ const props = {};
150
+ const numFmtEl = findChildNs(el, "numFmt");
151
+ if (numFmtEl) {
152
+ props.numFmt = attrVal(numFmtEl, "val");
153
+ }
154
+ const numStartEl = findChildNs(el, "numStart");
155
+ if (numStartEl) {
156
+ props.numStart = attrInt(numStartEl, "val");
157
+ }
158
+ const numRestartEl = findChildNs(el, "numRestart");
159
+ if (numRestartEl) {
160
+ props.numRestart = attrVal(numRestartEl, "val");
161
+ }
162
+ const posEl = findChildNs(el, "pos");
163
+ if (posEl) {
164
+ props.position = attrVal(posEl, "val");
165
+ }
166
+ return Object.keys(props).length > 0 ? props : undefined;
167
+ }
168
+ /** Parse w:ffData element into a FormField. */
169
+ function parseFfData(el) {
170
+ const nameEl = findChildNs(el, "name");
171
+ const name = nameEl ? attrVal(nameEl, "val") : undefined;
172
+ const enabledEl = findChildNs(el, "enabled");
173
+ const enabled = enabledEl ? attrVal(enabledEl, "val") !== "0" : undefined;
174
+ const helpTextEl = findChildNs(el, "helpText");
175
+ const helpText = helpTextEl ? attrVal(helpTextEl, "val") : undefined;
176
+ const statusTextEl = findChildNs(el, "statusText");
177
+ const statusText = statusTextEl ? attrVal(statusTextEl, "val") : undefined;
178
+ // Text input
179
+ const textInputEl = findChildNs(el, "textInput");
180
+ if (textInputEl) {
181
+ const defEl = findChildNs(textInputEl, "default");
182
+ const maxLenEl = findChildNs(textInputEl, "maxLength");
183
+ const fmtEl = findChildNs(textInputEl, "format");
184
+ return {
185
+ type: "text",
186
+ name,
187
+ default: defEl ? attrVal(defEl, "val") : undefined,
188
+ maxLength: maxLenEl ? attrInt(maxLenEl, "val") : undefined,
189
+ format: fmtEl ? attrVal(fmtEl, "val") : undefined,
190
+ helpText,
191
+ statusText,
192
+ enabled
193
+ };
194
+ }
195
+ // CheckBox
196
+ const cbEl = findChildNs(el, "checkBox");
197
+ if (cbEl) {
198
+ const checkedEl = findChildNs(cbEl, "checked");
199
+ const defEl = findChildNs(cbEl, "default");
200
+ const sizeEl = findChildNs(cbEl, "size");
201
+ return {
202
+ type: "checkBox",
203
+ name,
204
+ checked: checkedEl ? attrVal(checkedEl, "val") !== "0" : undefined,
205
+ default: defEl ? attrVal(defEl, "val") !== "0" : undefined,
206
+ size: sizeEl ? attrInt(sizeEl, "val") : undefined
207
+ };
208
+ }
209
+ // Drop-down list
210
+ const ddlEl = findChildNs(el, "ddList");
211
+ if (ddlEl) {
212
+ const defEl = findChildNs(ddlEl, "default");
213
+ const entries = [];
214
+ for (const le of findChildrenNs(ddlEl, "listEntry")) {
215
+ const v = attrVal(le, "val");
216
+ if (v !== undefined) {
217
+ entries.push(v);
218
+ }
219
+ }
220
+ return {
221
+ type: "dropDown",
222
+ name,
223
+ entries: entries.length > 0 ? entries : undefined,
224
+ default: defEl ? attrInt(defEl, "val") : undefined,
225
+ helpText,
226
+ statusText,
227
+ enabled
228
+ };
229
+ }
230
+ return undefined;
231
+ }
232
+ // =============================================================================
233
+ // Run Properties Parser
234
+ // =============================================================================
235
+ function parseRunProperties(rPrEl) {
236
+ const rPr = {};
237
+ const rStyleEl = findChildNs(rPrEl, "rStyle");
238
+ if (rStyleEl) {
239
+ rPr.style = attrVal(rStyleEl, "val");
240
+ }
241
+ const fontsEl = findChildNs(rPrEl, "rFonts");
242
+ if (fontsEl) {
243
+ const f = {};
244
+ const ascii = attrVal(fontsEl, "ascii");
245
+ const hAnsi = attrVal(fontsEl, "hAnsi");
246
+ const eastAsia = attrVal(fontsEl, "eastAsia");
247
+ const cs = attrVal(fontsEl, "cs");
248
+ const hint = attrVal(fontsEl, "hint");
249
+ if (ascii) {
250
+ f.ascii = ascii;
251
+ }
252
+ if (hAnsi) {
253
+ f.hAnsi = hAnsi;
254
+ }
255
+ if (eastAsia) {
256
+ f.eastAsia = eastAsia;
257
+ }
258
+ if (cs) {
259
+ f.cs = cs;
260
+ }
261
+ if (hint) {
262
+ f.hint = hint;
263
+ }
264
+ const asciiTheme = attrVal(fontsEl, "asciiTheme");
265
+ if (asciiTheme) {
266
+ f.asciiTheme = asciiTheme;
267
+ }
268
+ const hAnsiTheme = attrVal(fontsEl, "hAnsiTheme");
269
+ if (hAnsiTheme) {
270
+ f.hAnsiTheme = hAnsiTheme;
271
+ }
272
+ const eastAsiaTheme = attrVal(fontsEl, "eastAsiaTheme");
273
+ if (eastAsiaTheme) {
274
+ f.eastAsiaTheme = eastAsiaTheme;
275
+ }
276
+ const cstheme = attrVal(fontsEl, "cstheme");
277
+ if (cstheme) {
278
+ f.cstheme = cstheme;
279
+ }
280
+ rPr.font = f;
281
+ }
282
+ // Boolean toggles: true-only (element presence = true; absence = undefined)
283
+ // Format: [elementName, propertyKey]
284
+ const RUN_ONCE_TOGGLES = [
285
+ ["strike", "strike"],
286
+ ["dstrike", "doubleStrike"],
287
+ ["caps", "caps"],
288
+ ["smallCaps", "smallCaps"],
289
+ ["vanish", "vanish"],
290
+ ["emboss", "emboss"],
291
+ ["imprint", "imprint"],
292
+ ["noProof", "noProof"],
293
+ ["specVanish", "specVanish"],
294
+ ["outline", "outline"],
295
+ ["shadow", "shadow"],
296
+ ["cs", "complexScript"],
297
+ ["oMath", "math"],
298
+ ["webHidden", "webHidden"]
299
+ ];
300
+ for (const [tag, key] of RUN_ONCE_TOGGLES) {
301
+ if (findChildNs(rPrEl, tag) && boolToggle(rPrEl, tag) !== false) {
302
+ rPr[key] = true;
303
+ }
304
+ }
305
+ // Boolean toggles: tri-state (can be explicitly true or false)
306
+ const RUN_TRISTATE_TOGGLES = [
307
+ ["b", "bold"],
308
+ ["bCs", "boldCs"],
309
+ ["i", "italic"],
310
+ ["iCs", "italicCs"],
311
+ ["snapToGrid", "snapToGrid"],
312
+ ["rtl", "rightToLeft"]
313
+ ];
314
+ for (const [tag, key] of RUN_TRISTATE_TOGGLES) {
315
+ const v = boolToggle(rPrEl, tag);
316
+ if (v !== undefined) {
317
+ rPr[key] = v;
318
+ }
319
+ }
320
+ // fitText
321
+ const fitTextEl = findChildNs(rPrEl, "fitText");
322
+ if (fitTextEl) {
323
+ const val = attrInt(fitTextEl, "val");
324
+ if (val !== undefined) {
325
+ const fitText = { val };
326
+ const id = attrInt(fitTextEl, "id");
327
+ if (id !== undefined) {
328
+ fitText.id = id;
329
+ }
330
+ rPr.fitText = fitText;
331
+ }
332
+ }
333
+ const colorEl = findChildNs(rPrEl, "color");
334
+ if (colorEl) {
335
+ const val = attrVal(colorEl, "val");
336
+ const themeColor = attrVal(colorEl, "themeColor");
337
+ if (themeColor) {
338
+ const spec = { val, themeColor };
339
+ const themeTint = attrVal(colorEl, "themeTint");
340
+ const themeShade = attrVal(colorEl, "themeShade");
341
+ if (themeTint) {
342
+ spec.themeTint = themeTint;
343
+ }
344
+ if (themeShade) {
345
+ spec.themeShade = themeShade;
346
+ }
347
+ rPr.color = spec;
348
+ }
349
+ else {
350
+ rPr.color = val;
351
+ }
352
+ }
353
+ const szEl = findChildNs(rPrEl, "sz");
354
+ if (szEl) {
355
+ rPr.size = attrInt(szEl, "val");
356
+ }
357
+ const szCsEl = findChildNs(rPrEl, "szCs");
358
+ if (szCsEl) {
359
+ rPr.sizeCs = attrInt(szCsEl, "val");
360
+ }
361
+ const uEl = findChildNs(rPrEl, "u");
362
+ if (uEl) {
363
+ const uStyle = attrVal(uEl, "val") ?? "single";
364
+ const uColor = attrVal(uEl, "color");
365
+ if (uColor) {
366
+ rPr.underline = { style: uStyle, color: uColor };
367
+ }
368
+ else {
369
+ rPr.underline = uStyle;
370
+ }
371
+ }
372
+ const highlightEl = findChildNs(rPrEl, "highlight");
373
+ if (highlightEl) {
374
+ rPr.highlight = attrVal(highlightEl, "val");
375
+ }
376
+ const vertAlignEl = findChildNs(rPrEl, "vertAlign");
377
+ if (vertAlignEl) {
378
+ rPr.vertAlign = attrVal(vertAlignEl, "val");
379
+ }
380
+ const spacingEl = findChildNs(rPrEl, "spacing");
381
+ if (spacingEl) {
382
+ rPr.spacing = attrInt(spacingEl, "val");
383
+ }
384
+ const shdEl = findChildNs(rPrEl, "shd");
385
+ if (shdEl) {
386
+ rPr.shading = parseShading(shdEl);
387
+ }
388
+ const langEl = findChildNs(rPrEl, "lang");
389
+ if (langEl) {
390
+ rPr.language = {
391
+ val: attrVal(langEl, "val"),
392
+ eastAsia: attrVal(langEl, "eastAsia"),
393
+ bidi: attrVal(langEl, "bidi")
394
+ };
395
+ }
396
+ // New valued properties
397
+ const kernEl = findChildNs(rPrEl, "kern");
398
+ if (kernEl) {
399
+ rPr.kern = attrInt(kernEl, "val");
400
+ }
401
+ const positionEl = findChildNs(rPrEl, "position");
402
+ if (positionEl) {
403
+ rPr.position = attrInt(positionEl, "val");
404
+ }
405
+ const wEl = findChildNs(rPrEl, "w");
406
+ if (wEl) {
407
+ rPr.scale = attrInt(wEl, "val");
408
+ }
409
+ const effectEl = findChildNs(rPrEl, "effect");
410
+ if (effectEl) {
411
+ rPr.effect = attrVal(effectEl, "val");
412
+ }
413
+ const emEl = findChildNs(rPrEl, "em");
414
+ if (emEl) {
415
+ rPr.emphasisMark = attrVal(emEl, "val");
416
+ }
417
+ const bdrEl = findChildNs(rPrEl, "bdr");
418
+ if (bdrEl) {
419
+ rPr.border = parseBorder(bdrEl);
420
+ }
421
+ // rPrChange (track changes for run properties)
422
+ const rPrChangeEl = findChildNs(rPrEl, "rPrChange");
423
+ if (rPrChangeEl) {
424
+ const rev = parseRevisionInfo(rPrChangeEl);
425
+ if (rev) {
426
+ const prevRPrEl = findChildNs(rPrChangeEl, "rPr");
427
+ const change = {
428
+ revision: rev,
429
+ previousProperties: prevRPrEl ? parseRunProperties(prevRPrEl) : undefined
430
+ };
431
+ rPr.propertyChange = change;
432
+ }
433
+ }
434
+ return rPr;
435
+ }
436
+ function parseShading(el) {
437
+ return {
438
+ pattern: attrVal(el, "val"),
439
+ color: attrVal(el, "color"),
440
+ fill: attrVal(el, "fill") ?? "auto"
441
+ };
442
+ }
443
+ function parseBorder(el) {
444
+ const b = {
445
+ style: (attrVal(el, "val") ?? "single"),
446
+ size: attrInt(el, "sz"),
447
+ space: attrInt(el, "space"),
448
+ color: attrVal(el, "color")
449
+ };
450
+ const tc = attrVal(el, "themeColor");
451
+ if (tc) {
452
+ b.themeColor = tc;
453
+ }
454
+ const shadow = attrVal(el, "shadow");
455
+ if (shadow === "1" || shadow === "true") {
456
+ b.shadow = true;
457
+ }
458
+ const frame = attrVal(el, "frame");
459
+ if (frame === "1" || frame === "true") {
460
+ b.frame = true;
461
+ }
462
+ const art = attrVal(el, "art");
463
+ if (art) {
464
+ b.art = art;
465
+ }
466
+ return b;
467
+ }
468
+ function parseTableWidth(el) {
469
+ return {
470
+ value: parseInt(el.attributes["w:w"] ?? el.attributes["w"] ?? "0", 10),
471
+ type: (el.attributes["w:type"] ?? el.attributes["type"] ?? "dxa")
472
+ };
473
+ }
474
+ // =============================================================================
475
+ // Paragraph Properties Parser
476
+ // =============================================================================
477
+ function parseParagraphProperties(pPrEl) {
478
+ const pPr = {};
479
+ const pStyleEl = findChildNs(pPrEl, "pStyle");
480
+ if (pStyleEl) {
481
+ pPr.style = attrVal(pStyleEl, "val");
482
+ }
483
+ const jcEl = findChildNs(pPrEl, "jc");
484
+ if (jcEl) {
485
+ pPr.alignment = attrVal(jcEl, "val");
486
+ }
487
+ if (findChildNs(pPrEl, "keepNext")) {
488
+ pPr.keepNext = true;
489
+ }
490
+ if (findChildNs(pPrEl, "keepLines")) {
491
+ pPr.keepLines = true;
492
+ }
493
+ if (findChildNs(pPrEl, "pageBreakBefore")) {
494
+ pPr.pageBreakBefore = true;
495
+ }
496
+ if (findChildNs(pPrEl, "bidi")) {
497
+ pPr.bidi = true;
498
+ }
499
+ // New boolean toggles
500
+ const ctxSp = boolToggle(pPrEl, "contextualSpacing");
501
+ if (ctxSp !== undefined) {
502
+ pPr.contextualSpacing = ctxSp;
503
+ }
504
+ const suppLn = boolToggle(pPrEl, "suppressLineNumbers");
505
+ if (suppLn !== undefined) {
506
+ pPr.suppressLineNumbers = suppLn;
507
+ }
508
+ const suppHyph = boolToggle(pPrEl, "suppressAutoHyphens");
509
+ if (suppHyph !== undefined) {
510
+ pPr.suppressAutoHyphens = suppHyph;
511
+ }
512
+ const mirr = boolToggle(pPrEl, "mirrorIndents");
513
+ if (mirr !== undefined) {
514
+ pPr.mirrorIndents = mirr;
515
+ }
516
+ const wc = boolToggle(pPrEl, "widowControl");
517
+ if (wc !== undefined) {
518
+ pPr.widowControl = wc;
519
+ }
520
+ const ww = boolToggle(pPrEl, "wordWrap");
521
+ if (ww !== undefined) {
522
+ pPr.wordWrap = ww;
523
+ }
524
+ const stg = boolToggle(pPrEl, "snapToGrid");
525
+ if (stg !== undefined) {
526
+ pPr.snapToGrid = stg;
527
+ }
528
+ const ofp = boolToggle(pPrEl, "overflowPunct");
529
+ if (ofp !== undefined) {
530
+ pPr.overflowPunctuation = ofp;
531
+ }
532
+ const topLinePunct = boolToggle(pPrEl, "topLinePunct");
533
+ if (topLinePunct !== undefined) {
534
+ pPr.topLinePunctuation = topLinePunct;
535
+ }
536
+ const kinsoku = boolToggle(pPrEl, "kinsoku");
537
+ if (kinsoku !== undefined) {
538
+ pPr.kinsoku = kinsoku;
539
+ }
540
+ const asd = boolToggle(pPrEl, "autoSpaceDE");
541
+ if (asd !== undefined) {
542
+ pPr.autoSpaceEastAsianText = asd;
543
+ }
544
+ const asdn = boolToggle(pPrEl, "autoSpaceDN");
545
+ if (asdn !== undefined) {
546
+ pPr.autoSpaceEastAsianDigit = asdn;
547
+ }
548
+ const textAlignEl = findChildNs(pPrEl, "textAlignment");
549
+ if (textAlignEl) {
550
+ pPr.textAlignment = attrVal(textAlignEl, "val");
551
+ }
552
+ const outlineLvlEl = findChildNs(pPrEl, "outlineLvl");
553
+ if (outlineLvlEl) {
554
+ pPr.outlineLevel = attrInt(outlineLvlEl, "val");
555
+ }
556
+ const textDirEl = findChildNs(pPrEl, "textDirection");
557
+ if (textDirEl) {
558
+ pPr.textDirection = attrVal(textDirEl, "val");
559
+ }
560
+ // Paragraph frame
561
+ const framePrEl = findChildNs(pPrEl, "framePr");
562
+ if (framePrEl) {
563
+ const frame = {};
564
+ const f = frame;
565
+ const dropCap = attrVal(framePrEl, "dropCap");
566
+ if (dropCap) {
567
+ f.dropCap = dropCap;
568
+ }
569
+ const lines = attrInt(framePrEl, "lines");
570
+ if (lines !== undefined) {
571
+ f.lines = lines;
572
+ }
573
+ const fw = attrInt(framePrEl, "w");
574
+ if (fw !== undefined) {
575
+ f.width = fw;
576
+ }
577
+ const fh = attrInt(framePrEl, "h");
578
+ if (fh !== undefined) {
579
+ f.height = fh;
580
+ }
581
+ const hSpace = attrInt(framePrEl, "hSpace");
582
+ if (hSpace !== undefined) {
583
+ f.hSpace = hSpace;
584
+ }
585
+ const vSpace = attrInt(framePrEl, "vSpace");
586
+ if (vSpace !== undefined) {
587
+ f.vSpace = vSpace;
588
+ }
589
+ const wrap = attrVal(framePrEl, "wrap");
590
+ if (wrap) {
591
+ f.wrap = wrap;
592
+ }
593
+ const hAnchor = attrVal(framePrEl, "hAnchor");
594
+ if (hAnchor) {
595
+ f.hAnchor = hAnchor;
596
+ }
597
+ const vAnchor = attrVal(framePrEl, "vAnchor");
598
+ if (vAnchor) {
599
+ f.vAnchor = vAnchor;
600
+ }
601
+ const x = attrInt(framePrEl, "x");
602
+ if (x !== undefined) {
603
+ f.x = x;
604
+ }
605
+ const xAlign = attrVal(framePrEl, "xAlign");
606
+ if (xAlign) {
607
+ f.xAlign = xAlign;
608
+ }
609
+ const y = attrInt(framePrEl, "y");
610
+ if (y !== undefined) {
611
+ f.y = y;
612
+ }
613
+ const yAlign = attrVal(framePrEl, "yAlign");
614
+ if (yAlign) {
615
+ f.yAlign = yAlign;
616
+ }
617
+ pPr.frame = frame;
618
+ }
619
+ // Thematic break: check for bottom border with special pattern
620
+ const pBdrEl = findChildNs(pPrEl, "pBdr");
621
+ if (pBdrEl) {
622
+ const borders = {};
623
+ for (const side of ["top", "bottom", "left", "right", "between", "bar"]) {
624
+ const sideEl = findChildNs(pBdrEl, side);
625
+ if (sideEl) {
626
+ borders[side] = parseBorder(sideEl);
627
+ }
628
+ }
629
+ pPr.borders = borders;
630
+ }
631
+ const spacingEl = findChildNs(pPrEl, "spacing");
632
+ if (spacingEl) {
633
+ const spacing = {};
634
+ const before = attrInt(spacingEl, "before");
635
+ const after = attrInt(spacingEl, "after");
636
+ const line = attrInt(spacingEl, "line");
637
+ const lineRule = attrVal(spacingEl, "lineRule");
638
+ if (before !== undefined) {
639
+ spacing.before = before;
640
+ }
641
+ if (after !== undefined) {
642
+ spacing.after = after;
643
+ }
644
+ if (line !== undefined) {
645
+ spacing.line = line;
646
+ // Per ECMA-376, w:lineRule defaults to "auto" when line is set
647
+ spacing.lineRule = (lineRule ?? "auto");
648
+ }
649
+ else if (lineRule) {
650
+ spacing.lineRule = lineRule;
651
+ }
652
+ const beforeAuto = attrVal(spacingEl, "beforeAutospacing");
653
+ if (beforeAuto === "1" || beforeAuto === "true") {
654
+ spacing.beforeAutoSpacing = true;
655
+ }
656
+ const afterAuto = attrVal(spacingEl, "afterAutospacing");
657
+ if (afterAuto === "1" || afterAuto === "true") {
658
+ spacing.afterAutoSpacing = true;
659
+ }
660
+ pPr.spacing = spacing;
661
+ }
662
+ const indEl = findChildNs(pPrEl, "ind");
663
+ if (indEl) {
664
+ const indent = {};
665
+ const left = attrInt(indEl, "left");
666
+ const right = attrInt(indEl, "right");
667
+ const hanging = attrInt(indEl, "hanging");
668
+ const firstLine = attrInt(indEl, "firstLine");
669
+ const start = attrInt(indEl, "start");
670
+ const end = attrInt(indEl, "end");
671
+ if (left !== undefined) {
672
+ indent.left = left;
673
+ }
674
+ if (right !== undefined) {
675
+ indent.right = right;
676
+ }
677
+ if (hanging !== undefined) {
678
+ indent.hanging = hanging;
679
+ }
680
+ if (firstLine !== undefined) {
681
+ indent.firstLine = firstLine;
682
+ }
683
+ if (start !== undefined) {
684
+ indent.start = start;
685
+ }
686
+ if (end !== undefined) {
687
+ indent.end = end;
688
+ }
689
+ pPr.indent = indent;
690
+ }
691
+ const numPrEl = findChildNs(pPrEl, "numPr");
692
+ if (numPrEl) {
693
+ const ilvlEl = findChildNs(numPrEl, "ilvl");
694
+ const numIdEl = findChildNs(numPrEl, "numId");
695
+ // Per OOXML schema, numId is required but ilvl is optional (defaults to 0).
696
+ if (numIdEl) {
697
+ pPr.numbering = {
698
+ level: ilvlEl ? (attrInt(ilvlEl, "val") ?? 0) : 0,
699
+ numId: attrInt(numIdEl, "val") ?? 0
700
+ };
701
+ }
702
+ }
703
+ const tabsEl = findChildNs(pPrEl, "tabs");
704
+ if (tabsEl) {
705
+ const tabs = [];
706
+ for (const tabEl of findChildrenNs(tabsEl, "tab")) {
707
+ tabs.push({
708
+ type: (attrVal(tabEl, "val") ?? "left"),
709
+ position: attrInt(tabEl, "pos") ?? 0,
710
+ leader: attrVal(tabEl, "leader")
711
+ });
712
+ }
713
+ if (tabs.length > 0) {
714
+ pPr.tabs = tabs;
715
+ }
716
+ }
717
+ const shdEl = findChildNs(pPrEl, "shd");
718
+ if (shdEl) {
719
+ pPr.shading = parseShading(shdEl);
720
+ }
721
+ const rPrEl = findChildNs(pPrEl, "rPr");
722
+ if (rPrEl) {
723
+ pPr.markRunProperties = parseRunProperties(rPrEl);
724
+ }
725
+ const sectPrEl = findChildNs(pPrEl, "sectPr");
726
+ if (sectPrEl) {
727
+ pPr.sectionProperties = parseSectionProperties(sectPrEl);
728
+ }
729
+ // Conditional formatting style mask
730
+ const cnfStyleEl = findChildNs(pPrEl, "cnfStyle");
731
+ if (cnfStyleEl) {
732
+ pPr.cnfStyle = attrVal(cnfStyleEl, "val");
733
+ }
734
+ // Paragraph property change
735
+ const pPrChangeEl = findChildNs(pPrEl, "pPrChange");
736
+ if (pPrChangeEl) {
737
+ const rev = parseRevisionInfo(pPrChangeEl);
738
+ if (rev) {
739
+ const prevPPrEl = findChildNs(pPrChangeEl, "pPr");
740
+ pPr.propertyChange = {
741
+ revision: rev,
742
+ previousProperties: prevPPrEl ? parseParagraphProperties(prevPPrEl) : undefined
743
+ };
744
+ }
745
+ }
746
+ // Paragraph mark insertion/deletion (w:pPr > w:rPr > w:ins/w:del)
747
+ const rPrInPPr = findChildNs(pPrEl, "rPr");
748
+ if (rPrInPPr) {
749
+ const insEl = findChildNs(rPrInPPr, "ins");
750
+ if (insEl) {
751
+ const rev = parseRevisionInfo(insEl);
752
+ if (rev) {
753
+ pPr.paragraphInsertion = rev;
754
+ }
755
+ }
756
+ const delEl = findChildNs(rPrInPPr, "del");
757
+ if (delEl) {
758
+ const rev = parseRevisionInfo(delEl);
759
+ if (rev) {
760
+ pPr.paragraphDeletion = rev;
761
+ }
762
+ }
763
+ }
764
+ return pPr;
765
+ }
766
+ // =============================================================================
767
+ // Revision Info Parser
768
+ // =============================================================================
769
+ function parseRevisionInfo(el) {
770
+ const author = attrVal(el, "author");
771
+ const id = attrInt(el, "id");
772
+ if (author === undefined || id === undefined) {
773
+ return undefined;
774
+ }
775
+ return {
776
+ author,
777
+ id,
778
+ date: attrVal(el, "date")
779
+ };
780
+ }
781
+ // =============================================================================
782
+ // Run Content Parser
783
+ // =============================================================================
784
+ function parseRunContent(el) {
785
+ const content = [];
786
+ for (const child of el.children) {
787
+ if (child.type !== "element") {
788
+ continue;
789
+ }
790
+ const name = child.name.replace(/^w:/, "");
791
+ switch (name) {
792
+ case "t":
793
+ content.push({ type: "text", text: (0, dom_1.textContent)(child) });
794
+ break;
795
+ case "br": {
796
+ const brType = attrVal(child, "type");
797
+ content.push({ type: "break", breakType: brType });
798
+ break;
799
+ }
800
+ case "tab":
801
+ content.push({ type: "tab" });
802
+ break;
803
+ case "ptab": {
804
+ const alignment = attrVal(child, "alignment") ?? "left";
805
+ const relativeTo = attrVal(child, "relativeTo") ?? "margin";
806
+ const leader = attrVal(child, "leader");
807
+ const ptab = {
808
+ type: "ptab",
809
+ alignment,
810
+ relativeTo
811
+ };
812
+ if (leader) {
813
+ ptab.leader = leader;
814
+ }
815
+ content.push(ptab);
816
+ break;
817
+ }
818
+ case "ruby": {
819
+ const ruby = { type: "ruby" };
820
+ const rubyPrEl = findChildNs(child, "rubyPr");
821
+ if (rubyPrEl) {
822
+ const props = {};
823
+ const alignEl = findChildNs(rubyPrEl, "rubyAlign");
824
+ if (alignEl) {
825
+ props.align = attrVal(alignEl, "val");
826
+ }
827
+ const hpsEl = findChildNs(rubyPrEl, "hps");
828
+ if (hpsEl) {
829
+ props.fontSize = attrInt(hpsEl, "val");
830
+ }
831
+ const hpsRaiseEl = findChildNs(rubyPrEl, "hpsRaise");
832
+ if (hpsRaiseEl) {
833
+ props.raise = attrInt(hpsRaiseEl, "val");
834
+ }
835
+ const hpsBaseTextEl = findChildNs(rubyPrEl, "hpsBaseText");
836
+ if (hpsBaseTextEl) {
837
+ props.baseFontSize = attrInt(hpsBaseTextEl, "val");
838
+ }
839
+ const lidEl = findChildNs(rubyPrEl, "lid");
840
+ if (lidEl) {
841
+ props.language = attrVal(lidEl, "val");
842
+ }
843
+ if (Object.keys(props).length > 0) {
844
+ ruby.properties = props;
845
+ }
846
+ }
847
+ // Parse w:rt (ruby text)
848
+ const rtEl = findChildNs(child, "rt");
849
+ const rubyText = [];
850
+ if (rtEl) {
851
+ for (const rtChild of rtEl.children) {
852
+ if (rtChild.type === "element" && rtChild.name.replace(/^w:/, "") === "r") {
853
+ rubyText.push(parseRun(rtChild));
854
+ }
855
+ }
856
+ }
857
+ ruby.rubyText = rubyText;
858
+ // Parse w:rubyBase
859
+ const baseEl = findChildNs(child, "rubyBase");
860
+ const baseText = [];
861
+ if (baseEl) {
862
+ for (const bChild of baseEl.children) {
863
+ if (bChild.type === "element" && bChild.name.replace(/^w:/, "") === "r") {
864
+ baseText.push(parseRun(bChild));
865
+ }
866
+ }
867
+ }
868
+ ruby.baseText = baseText;
869
+ content.push(ruby);
870
+ break;
871
+ }
872
+ case "sym":
873
+ content.push({
874
+ type: "symbol",
875
+ font: attrVal(child, "font") ?? "",
876
+ char: attrVal(child, "char") ?? ""
877
+ });
878
+ break;
879
+ case "footnoteReference": {
880
+ const fr = { type: "footnoteRef", id: attrInt(child, "id") ?? 0 };
881
+ const cmf = attrVal(child, "customMarkFollows");
882
+ if (cmf === "1" || cmf === "true") {
883
+ fr.customMarkFollows = true;
884
+ }
885
+ content.push(fr);
886
+ break;
887
+ }
888
+ case "endnoteReference": {
889
+ const er = { type: "endnoteRef", id: attrInt(child, "id") ?? 0 };
890
+ const cmf = attrVal(child, "customMarkFollows");
891
+ if (cmf === "1" || cmf === "true") {
892
+ er.customMarkFollows = true;
893
+ }
894
+ content.push(er);
895
+ break;
896
+ }
897
+ case "drawing":
898
+ parseDrawingContent(child, content);
899
+ break;
900
+ case "cr":
901
+ content.push({ type: "carriageReturn" });
902
+ break;
903
+ case "noBreakHyphen":
904
+ content.push({ type: "noBreakHyphen" });
905
+ break;
906
+ case "softHyphen":
907
+ content.push({ type: "softHyphen" });
908
+ break;
909
+ case "lastRenderedPageBreak":
910
+ content.push({ type: "lastRenderedPageBreak" });
911
+ break;
912
+ case "annotationRef":
913
+ content.push({ type: "annotationReference", id: attrInt(child, "id") ?? 0 });
914
+ break;
915
+ case "commentReference":
916
+ // This is annotationReference for comments inside runs
917
+ content.push({ type: "annotationReference", id: attrInt(child, "id") ?? 0 });
918
+ break;
919
+ }
920
+ }
921
+ return content;
922
+ }
923
+ function parseDrawingContent(drawingEl, content) {
924
+ // Look for wp:inline
925
+ const inlineEl = (0, dom_1.findChild)(drawingEl, "wp:inline");
926
+ if (inlineEl) {
927
+ const extentEl = (0, dom_1.findChild)(inlineEl, "wp:extent");
928
+ const docPrEl = (0, dom_1.findChild)(inlineEl, "wp:docPr");
929
+ const graphicEl = (0, dom_1.findChild)(inlineEl, "a:graphic");
930
+ const graphicDataEl = graphicEl ? (0, dom_1.findChild)(graphicEl, "a:graphicData") : undefined;
931
+ const picEl = graphicDataEl ? (0, dom_1.findChild)(graphicDataEl, "pic:pic") : undefined;
932
+ const blipFillEl = picEl ? (0, dom_1.findChild)(picEl, "pic:blipFill") : undefined;
933
+ const blipEl = blipFillEl ? (0, dom_1.findChild)(blipFillEl, "a:blip") : undefined;
934
+ const rId = blipEl?.attributes["r:embed"] ?? "";
935
+ const cx = parseInt(extentEl?.attributes["cx"] ?? "0", 10);
936
+ const cy = parseInt(extentEl?.attributes["cy"] ?? "0", 10);
937
+ const img = {
938
+ type: "image",
939
+ rId,
940
+ width: cx,
941
+ height: cy,
942
+ altText: docPrEl?.attributes["descr"],
943
+ name: docPrEl?.attributes["name"],
944
+ drawingId: docPrEl ? parseInt(docPrEl.attributes["id"] ?? "1", 10) : undefined
945
+ };
946
+ // Parse xfrm for rotation/flip
947
+ const spPrEl = picEl ? (0, dom_1.findChild)(picEl, "pic:spPr") : undefined;
948
+ if (spPrEl) {
949
+ const xfrmEl = (0, dom_1.findChild)(spPrEl, "a:xfrm");
950
+ if (xfrmEl) {
951
+ const rot = xfrmEl.attributes["rot"];
952
+ if (rot !== undefined && rot !== "") {
953
+ img.rotation = parseInt(rot, 10);
954
+ }
955
+ if (xfrmEl.attributes["flipH"] === "1") {
956
+ img.flipHorizontal = true;
957
+ }
958
+ if (xfrmEl.attributes["flipV"] === "1") {
959
+ img.flipVertical = true;
960
+ }
961
+ }
962
+ // Outline
963
+ const lnEl = (0, dom_1.findChild)(spPrEl, "a:ln");
964
+ if (lnEl) {
965
+ const outline = {};
966
+ const w = lnEl.attributes["w"];
967
+ if (w) {
968
+ outline.width = parseInt(w, 10);
969
+ }
970
+ const sfEl = (0, dom_1.findChild)(lnEl, "a:solidFill");
971
+ const srgbEl = sfEl ? (0, dom_1.findChild)(sfEl, "a:srgbClr") : undefined;
972
+ if (srgbEl) {
973
+ outline.color = srgbEl.attributes["val"];
974
+ }
975
+ img.outline = outline;
976
+ }
977
+ }
978
+ // SVG blip in a:extLst
979
+ if (blipEl) {
980
+ const extLst = (0, dom_1.findChild)(blipEl, "a:extLst");
981
+ if (extLst) {
982
+ for (const ext of (0, dom_1.findChildren)(extLst, "a:ext")) {
983
+ const svgBlip = (0, dom_1.findChild)(ext, "asvg:svgBlip") ?? findChildNs(ext, "svgBlip");
984
+ if (svgBlip) {
985
+ const svgEmbed = svgBlip.attributes["r:embed"];
986
+ if (svgEmbed) {
987
+ img.svgRId = svgEmbed;
988
+ }
989
+ }
990
+ }
991
+ }
992
+ }
993
+ content.push(img);
994
+ }
995
+ }
996
+ // =============================================================================
997
+ // Floating Image Parser
998
+ // =============================================================================
999
+ function parseFloatingImage(anchorEl) {
1000
+ const docPrEl = (0, dom_1.findChild)(anchorEl, "wp:docPr");
1001
+ const extentEl = (0, dom_1.findChild)(anchorEl, "wp:extent");
1002
+ const graphicEl = (0, dom_1.findChild)(anchorEl, "a:graphic");
1003
+ const graphicDataEl = graphicEl ? (0, dom_1.findChild)(graphicEl, "a:graphicData") : undefined;
1004
+ const picEl = graphicDataEl ? (0, dom_1.findChild)(graphicDataEl, "pic:pic") : undefined;
1005
+ const blipFillEl = picEl ? (0, dom_1.findChild)(picEl, "pic:blipFill") : undefined;
1006
+ const blipEl = blipFillEl ? (0, dom_1.findChild)(blipFillEl, "a:blip") : undefined;
1007
+ const rId = blipEl?.attributes["r:embed"];
1008
+ if (!rId) {
1009
+ return undefined;
1010
+ }
1011
+ const cx = parseInt(extentEl?.attributes["cx"] ?? "0", 10);
1012
+ const cy = parseInt(extentEl?.attributes["cy"] ?? "0", 10);
1013
+ const img = {
1014
+ type: "floatingImage",
1015
+ rId,
1016
+ width: cx,
1017
+ height: cy,
1018
+ altText: docPrEl?.attributes["descr"],
1019
+ name: docPrEl?.attributes["name"],
1020
+ drawingId: docPrEl ? parseInt(docPrEl.attributes["id"] ?? "1", 10) : undefined
1021
+ };
1022
+ // Attributes
1023
+ if (anchorEl.attributes["behindDoc"] === "1") {
1024
+ img.behindDoc = true;
1025
+ }
1026
+ if (anchorEl.attributes["locked"] === "1") {
1027
+ img.lockAnchor = true;
1028
+ }
1029
+ if (anchorEl.attributes["layoutInCell"] === "0") {
1030
+ img.layoutInCell = false;
1031
+ }
1032
+ if (anchorEl.attributes["allowOverlap"] === "0") {
1033
+ img.allowOverlap = false;
1034
+ }
1035
+ const rh = anchorEl.attributes["relativeHeight"];
1036
+ if (rh) {
1037
+ img.relativeHeight = parseInt(rh, 10);
1038
+ }
1039
+ // Dist*
1040
+ const distT = anchorEl.attributes["distT"];
1041
+ if (distT) {
1042
+ img.distT = parseInt(distT, 10);
1043
+ }
1044
+ const distB = anchorEl.attributes["distB"];
1045
+ if (distB) {
1046
+ img.distB = parseInt(distB, 10);
1047
+ }
1048
+ const distL = anchorEl.attributes["distL"];
1049
+ if (distL) {
1050
+ img.distL = parseInt(distL, 10);
1051
+ }
1052
+ const distR = anchorEl.attributes["distR"];
1053
+ if (distR) {
1054
+ img.distR = parseInt(distR, 10);
1055
+ }
1056
+ // Simple positioning
1057
+ if (anchorEl.attributes["simplePos"] === "1") {
1058
+ const sposEl = (0, dom_1.findChild)(anchorEl, "wp:simplePos");
1059
+ if (sposEl) {
1060
+ const x = parseInt(sposEl.attributes["x"] ?? "0", 10);
1061
+ const y = parseInt(sposEl.attributes["y"] ?? "0", 10);
1062
+ img.simplePos = { x, y };
1063
+ }
1064
+ }
1065
+ // Horizontal position
1066
+ const hPosEl = (0, dom_1.findChild)(anchorEl, "wp:positionH");
1067
+ if (hPosEl) {
1068
+ const h = { relativeTo: hPosEl.attributes["relativeFrom"] };
1069
+ const offsetEl = (0, dom_1.findChild)(hPosEl, "wp:posOffset");
1070
+ if (offsetEl) {
1071
+ h.offset = parseInt((0, dom_1.textContent)(offsetEl), 10);
1072
+ }
1073
+ const alignEl = (0, dom_1.findChild)(hPosEl, "wp:align");
1074
+ if (alignEl) {
1075
+ h.align = (0, dom_1.textContent)(alignEl);
1076
+ }
1077
+ img.horizontalPosition = h;
1078
+ }
1079
+ // Vertical position
1080
+ const vPosEl = (0, dom_1.findChild)(anchorEl, "wp:positionV");
1081
+ if (vPosEl) {
1082
+ const v = { relativeTo: vPosEl.attributes["relativeFrom"] };
1083
+ const offsetEl = (0, dom_1.findChild)(vPosEl, "wp:posOffset");
1084
+ if (offsetEl) {
1085
+ v.offset = parseInt((0, dom_1.textContent)(offsetEl), 10);
1086
+ }
1087
+ const alignEl = (0, dom_1.findChild)(vPosEl, "wp:align");
1088
+ if (alignEl) {
1089
+ v.align = (0, dom_1.textContent)(alignEl);
1090
+ }
1091
+ img.verticalPosition = v;
1092
+ }
1093
+ // Wrap
1094
+ for (const wrapChild of anchorEl.children) {
1095
+ if (wrapChild.type !== "element") {
1096
+ continue;
1097
+ }
1098
+ const wn = wrapChild.name;
1099
+ if (wn === "wp:wrapSquare") {
1100
+ img.wrap = { style: "square", side: wrapChild.attributes["wrapText"] };
1101
+ }
1102
+ else if (wn === "wp:wrapTight") {
1103
+ img.wrap = { style: "tight", side: wrapChild.attributes["wrapText"] };
1104
+ }
1105
+ else if (wn === "wp:wrapThrough") {
1106
+ img.wrap = { style: "through", side: wrapChild.attributes["wrapText"] };
1107
+ }
1108
+ else if (wn === "wp:wrapTopAndBottom") {
1109
+ img.wrap = { style: "topAndBottom" };
1110
+ }
1111
+ else if (wn === "wp:wrapNone") {
1112
+ img.wrap = { style: "none" };
1113
+ }
1114
+ if (img.wrap) {
1115
+ // Parse wrap margins
1116
+ const distT = anchorEl.attributes["distT"];
1117
+ const distB = anchorEl.attributes["distB"];
1118
+ const distL = anchorEl.attributes["distL"];
1119
+ const distR = anchorEl.attributes["distR"];
1120
+ if (distT || distB || distL || distR) {
1121
+ const margins = {};
1122
+ if (distT) {
1123
+ margins.top = parseInt(distT, 10);
1124
+ }
1125
+ if (distB) {
1126
+ margins.bottom = parseInt(distB, 10);
1127
+ }
1128
+ if (distL) {
1129
+ margins.left = parseInt(distL, 10);
1130
+ }
1131
+ if (distR) {
1132
+ margins.right = parseInt(distR, 10);
1133
+ }
1134
+ img.wrap.margins = margins;
1135
+ }
1136
+ break;
1137
+ }
1138
+ }
1139
+ // Rotation/flip from spPr
1140
+ const spPrEl = picEl ? (0, dom_1.findChild)(picEl, "pic:spPr") : undefined;
1141
+ if (spPrEl) {
1142
+ const xfrmEl = (0, dom_1.findChild)(spPrEl, "a:xfrm");
1143
+ if (xfrmEl) {
1144
+ const rot = xfrmEl.attributes["rot"];
1145
+ if (rot !== undefined && rot !== "") {
1146
+ img.rotation = parseInt(rot, 10);
1147
+ }
1148
+ if (xfrmEl.attributes["flipH"] === "1") {
1149
+ img.flipHorizontal = true;
1150
+ }
1151
+ if (xfrmEl.attributes["flipV"] === "1") {
1152
+ img.flipVertical = true;
1153
+ }
1154
+ }
1155
+ const lnEl = (0, dom_1.findChild)(spPrEl, "a:ln");
1156
+ if (lnEl) {
1157
+ const outline = {};
1158
+ const w = lnEl.attributes["w"];
1159
+ if (w) {
1160
+ outline.width = parseInt(w, 10);
1161
+ }
1162
+ const sfEl = (0, dom_1.findChild)(lnEl, "a:solidFill");
1163
+ const srgbEl = sfEl ? (0, dom_1.findChild)(sfEl, "a:srgbClr") : undefined;
1164
+ if (srgbEl) {
1165
+ outline.color = srgbEl.attributes["val"];
1166
+ }
1167
+ img.outline = outline;
1168
+ }
1169
+ }
1170
+ // SVG blip in a:extLst
1171
+ if (blipEl) {
1172
+ const extLst = (0, dom_1.findChild)(blipEl, "a:extLst");
1173
+ if (extLst) {
1174
+ for (const ext of (0, dom_1.findChildren)(extLst, "a:ext")) {
1175
+ const svgBlip = (0, dom_1.findChild)(ext, "asvg:svgBlip") ?? findChildNs(ext, "svgBlip");
1176
+ if (svgBlip) {
1177
+ const svgEmbed = svgBlip.attributes["r:embed"];
1178
+ if (svgEmbed) {
1179
+ img.svgRId = svgEmbed;
1180
+ }
1181
+ }
1182
+ }
1183
+ }
1184
+ }
1185
+ // Source rectangle (crop)
1186
+ if (blipFillEl) {
1187
+ const srcRectEl = (0, dom_1.findChild)(blipFillEl, "a:srcRect");
1188
+ if (srcRectEl) {
1189
+ const sr = {};
1190
+ const lAttr = srcRectEl.attributes["l"];
1191
+ const tAttr = srcRectEl.attributes["t"];
1192
+ const rAttr = srcRectEl.attributes["r"];
1193
+ const bAttr = srcRectEl.attributes["b"];
1194
+ if (lAttr !== undefined) {
1195
+ sr.l = parseInt(lAttr, 10);
1196
+ }
1197
+ if (tAttr !== undefined) {
1198
+ sr.t = parseInt(tAttr, 10);
1199
+ }
1200
+ if (rAttr !== undefined) {
1201
+ sr.r = parseInt(rAttr, 10);
1202
+ }
1203
+ if (bAttr !== undefined) {
1204
+ sr.b = parseInt(bAttr, 10);
1205
+ }
1206
+ if (Object.keys(sr).length > 0) {
1207
+ img.srcRect = sr;
1208
+ }
1209
+ }
1210
+ }
1211
+ return img;
1212
+ }
1213
+ // =============================================================================
1214
+ // DrawingML Shape Parser
1215
+ // =============================================================================
1216
+ function parseDrawingShape(anchorEl, wspEl) {
1217
+ const docPrEl = (0, dom_1.findChild)(anchorEl, "wp:docPr");
1218
+ const extentEl = (0, dom_1.findChild)(anchorEl, "wp:extent");
1219
+ const cx = parseInt(extentEl?.attributes["cx"] ?? "0", 10);
1220
+ const cy = parseInt(extentEl?.attributes["cy"] ?? "0", 10);
1221
+ // Parse preset shape type from wps:spPr > a:prstGeom
1222
+ const spPrEl = (0, dom_1.findChild)(wspEl, "wps:spPr") ?? findChildNs(wspEl, "spPr");
1223
+ const prstGeomEl = spPrEl
1224
+ ? ((0, dom_1.findChild)(spPrEl, "a:prstGeom") ?? findChildNs(spPrEl, "prstGeom"))
1225
+ : undefined;
1226
+ const shapeType = prstGeomEl?.attributes["prst"] ?? "rect";
1227
+ const shape = {
1228
+ type: "drawingShape",
1229
+ shapeType,
1230
+ width: cx,
1231
+ height: cy,
1232
+ altText: docPrEl?.attributes["descr"],
1233
+ name: docPrEl?.attributes["name"]
1234
+ };
1235
+ // Parse fill
1236
+ if (spPrEl) {
1237
+ const solidFill = (0, dom_1.findChild)(spPrEl, "a:solidFill") ?? findChildNs(spPrEl, "solidFill");
1238
+ if (solidFill) {
1239
+ const srgb = (0, dom_1.findChild)(solidFill, "a:srgbClr") ?? findChildNs(solidFill, "srgbClr");
1240
+ if (srgb) {
1241
+ shape.fillColor = srgb.attributes["val"];
1242
+ }
1243
+ }
1244
+ const noFill = (0, dom_1.findChild)(spPrEl, "a:noFill") ?? findChildNs(spPrEl, "noFill");
1245
+ if (noFill) {
1246
+ shape.noFill = true;
1247
+ }
1248
+ // Parse outline
1249
+ const lnEl = (0, dom_1.findChild)(spPrEl, "a:ln") ?? findChildNs(spPrEl, "ln");
1250
+ if (lnEl) {
1251
+ const w = lnEl.attributes["w"];
1252
+ if (w) {
1253
+ shape.outlineWidth = parseInt(w, 10);
1254
+ }
1255
+ const lnFill = (0, dom_1.findChild)(lnEl, "a:solidFill") ?? findChildNs(lnEl, "solidFill");
1256
+ if (lnFill) {
1257
+ const srgb = (0, dom_1.findChild)(lnFill, "a:srgbClr") ?? findChildNs(lnFill, "srgbClr");
1258
+ if (srgb) {
1259
+ shape.outlineColor = srgb.attributes["val"];
1260
+ }
1261
+ }
1262
+ const noLn = (0, dom_1.findChild)(lnEl, "a:noFill") ?? findChildNs(lnEl, "noFill");
1263
+ if (noLn) {
1264
+ shape.noOutline = true;
1265
+ }
1266
+ }
1267
+ }
1268
+ // Parse text content (wps:txbx > w:txbxContent)
1269
+ const txbxEl = (0, dom_1.findChild)(wspEl, "wps:txbx") ?? findChildNs(wspEl, "txbx");
1270
+ const txbxContentEl = txbxEl
1271
+ ? ((0, dom_1.findChild)(txbxEl, "w:txbxContent") ?? findChildNs(txbxEl, "txbxContent"))
1272
+ : undefined;
1273
+ if (txbxContentEl) {
1274
+ const paras = [];
1275
+ for (const child of txbxContentEl.children) {
1276
+ if (child.type === "element" && child.name.replace(/^w:/, "") === "p") {
1277
+ paras.push(parseParagraph(child));
1278
+ }
1279
+ }
1280
+ if (paras.length > 0) {
1281
+ shape.textContent = paras;
1282
+ }
1283
+ }
1284
+ // Parse positioning
1285
+ const posH = (0, dom_1.findChild)(anchorEl, "wp:positionH");
1286
+ if (posH) {
1287
+ const hp = { relativeTo: posH.attributes["relativeFrom"] };
1288
+ const offsetEl = (0, dom_1.findChild)(posH, "wp:posOffset");
1289
+ if (offsetEl) {
1290
+ hp.offset = parseInt((0, dom_1.textContent)(offsetEl), 10);
1291
+ }
1292
+ const alignEl = (0, dom_1.findChild)(posH, "wp:align");
1293
+ if (alignEl) {
1294
+ hp.align = (0, dom_1.textContent)(alignEl);
1295
+ }
1296
+ shape.horizontalPosition = hp;
1297
+ }
1298
+ const posV = (0, dom_1.findChild)(anchorEl, "wp:positionV");
1299
+ if (posV) {
1300
+ const vp = { relativeTo: posV.attributes["relativeFrom"] };
1301
+ const offsetEl = (0, dom_1.findChild)(posV, "wp:posOffset");
1302
+ if (offsetEl) {
1303
+ vp.offset = parseInt((0, dom_1.textContent)(offsetEl), 10);
1304
+ }
1305
+ const alignEl = (0, dom_1.findChild)(posV, "wp:align");
1306
+ if (alignEl) {
1307
+ vp.align = (0, dom_1.textContent)(alignEl);
1308
+ }
1309
+ shape.verticalPosition = vp;
1310
+ }
1311
+ // Wrap
1312
+ for (const wrapChild of anchorEl.children) {
1313
+ if (wrapChild.type !== "element") {
1314
+ continue;
1315
+ }
1316
+ const wn = wrapChild.name;
1317
+ if (wn === "wp:wrapSquare") {
1318
+ shape.wrap = { style: "square", side: wrapChild.attributes["wrapText"] };
1319
+ }
1320
+ else if (wn === "wp:wrapTight") {
1321
+ shape.wrap = { style: "tight", side: wrapChild.attributes["wrapText"] };
1322
+ }
1323
+ else if (wn === "wp:wrapTopAndBottom") {
1324
+ shape.wrap = { style: "topAndBottom" };
1325
+ }
1326
+ else if (wn === "wp:wrapNone") {
1327
+ shape.wrap = { style: "none" };
1328
+ }
1329
+ }
1330
+ // Behind doc
1331
+ if (anchorEl.attributes["behindDoc"] === "1") {
1332
+ shape.behindDoc = true;
1333
+ }
1334
+ // Rotation
1335
+ if (spPrEl) {
1336
+ const xfrmEl = (0, dom_1.findChild)(spPrEl, "a:xfrm") ?? findChildNs(spPrEl, "xfrm");
1337
+ if (xfrmEl?.attributes["rot"]) {
1338
+ shape.rotation = parseInt(xfrmEl.attributes["rot"], 10);
1339
+ }
1340
+ }
1341
+ return shape;
1342
+ }
1343
+ // =============================================================================
1344
+ // Math Parser
1345
+ // =============================================================================
1346
+ function findMathChild(el, localName) {
1347
+ return (0, dom_1.findChild)(el, `m:${localName}`) ?? (0, dom_1.findChild)(el, localName);
1348
+ }
1349
+ function mathAttrVal(el, name) {
1350
+ return el.attributes[`m:${name}`] ?? el.attributes[name];
1351
+ }
1352
+ function findMathChildren(el, localName) {
1353
+ const a = (0, dom_1.findChildren)(el, `m:${localName}`);
1354
+ return a.length > 0 ? a : (0, dom_1.findChildren)(el, localName);
1355
+ }
1356
+ function parseMathContent(el) {
1357
+ const result = [];
1358
+ for (const child of el.children) {
1359
+ if (child.type !== "element") {
1360
+ continue;
1361
+ }
1362
+ const name = child.name.replace(/^m:/, "");
1363
+ switch (name) {
1364
+ case "r": {
1365
+ // Math run
1366
+ const tEl = findMathChild(child, "t");
1367
+ const mrPrEl = findMathChild(child, "rPr");
1368
+ const mr = { type: "mathRun", text: tEl ? (0, dom_1.textContent)(tEl) : "" };
1369
+ if (mrPrEl) {
1370
+ const props = {};
1371
+ const sty = findMathChild(mrPrEl, "sty");
1372
+ if (sty) {
1373
+ const v = sty.attributes["m:val"] ?? sty.attributes["val"];
1374
+ if (v === "p" || v === "b") {
1375
+ props.italic = false;
1376
+ }
1377
+ if (v === "b" || v === "bi") {
1378
+ props.bold = true;
1379
+ }
1380
+ }
1381
+ if (Object.keys(props).length > 0) {
1382
+ mr.properties = props;
1383
+ }
1384
+ }
1385
+ result.push(mr);
1386
+ break;
1387
+ }
1388
+ case "f": {
1389
+ const fPrEl = findMathChild(child, "fPr");
1390
+ const num = findMathChild(child, "num");
1391
+ const den = findMathChild(child, "den");
1392
+ const frac = {
1393
+ type: "mathFraction",
1394
+ numerator: num ? parseMathContent(num) : [],
1395
+ denominator: den ? parseMathContent(den) : []
1396
+ };
1397
+ if (fPrEl) {
1398
+ const typeEl = findMathChild(fPrEl, "type");
1399
+ if (typeEl) {
1400
+ frac.fractionType = typeEl.attributes["m:val"] ?? typeEl.attributes["val"];
1401
+ }
1402
+ }
1403
+ result.push(frac);
1404
+ break;
1405
+ }
1406
+ case "sSup": {
1407
+ const base = findMathChild(child, "e");
1408
+ const sup = findMathChild(child, "sup");
1409
+ result.push({
1410
+ type: "mathSuperScript",
1411
+ base: base ? parseMathContent(base) : [],
1412
+ superScript: sup ? parseMathContent(sup) : []
1413
+ });
1414
+ break;
1415
+ }
1416
+ case "sSub": {
1417
+ const base = findMathChild(child, "e");
1418
+ const sub = findMathChild(child, "sub");
1419
+ result.push({
1420
+ type: "mathSubScript",
1421
+ base: base ? parseMathContent(base) : [],
1422
+ subScript: sub ? parseMathContent(sub) : []
1423
+ });
1424
+ break;
1425
+ }
1426
+ case "sSubSup": {
1427
+ const base = findMathChild(child, "e");
1428
+ const sub = findMathChild(child, "sub");
1429
+ const sup = findMathChild(child, "sup");
1430
+ result.push({
1431
+ type: "mathSubSuperScript",
1432
+ base: base ? parseMathContent(base) : [],
1433
+ subScript: sub ? parseMathContent(sub) : [],
1434
+ superScript: sup ? parseMathContent(sup) : []
1435
+ });
1436
+ break;
1437
+ }
1438
+ case "sPre": {
1439
+ const base = findMathChild(child, "e");
1440
+ const sub = findMathChild(child, "sub");
1441
+ const sup = findMathChild(child, "sup");
1442
+ result.push({
1443
+ type: "mathPreSubSuperScript",
1444
+ base: base ? parseMathContent(base) : [],
1445
+ preSubScript: sub ? parseMathContent(sub) : [],
1446
+ preSuperScript: sup ? parseMathContent(sup) : []
1447
+ });
1448
+ break;
1449
+ }
1450
+ case "phant": {
1451
+ const eEl = findMathChild(child, "e");
1452
+ const phantPrEl = findMathChild(child, "phantPr");
1453
+ const ph = {
1454
+ type: "mathPhantom",
1455
+ content: eEl ? parseMathContent(eEl) : []
1456
+ };
1457
+ if (phantPrEl) {
1458
+ const boolAttr = (name) => {
1459
+ const el = findMathChild(phantPrEl, name);
1460
+ if (!el) {
1461
+ return false;
1462
+ }
1463
+ const v = mathAttrVal(el, "val");
1464
+ return v !== "0" && v !== "false";
1465
+ };
1466
+ if (boolAttr("show")) {
1467
+ ph.show = true;
1468
+ }
1469
+ if (boolAttr("zeroWid")) {
1470
+ ph.zeroWidth = true;
1471
+ }
1472
+ if (boolAttr("zeroAsc")) {
1473
+ ph.zeroAscent = true;
1474
+ }
1475
+ if (boolAttr("zeroDesc")) {
1476
+ ph.zeroDescent = true;
1477
+ }
1478
+ if (boolAttr("transp")) {
1479
+ ph.transparent = true;
1480
+ }
1481
+ }
1482
+ result.push(ph);
1483
+ break;
1484
+ }
1485
+ case "groupChr": {
1486
+ const eEl = findMathChild(child, "e");
1487
+ const prEl = findMathChild(child, "groupChrPr");
1488
+ const g = {
1489
+ type: "mathGroupChar",
1490
+ base: eEl ? parseMathContent(eEl) : []
1491
+ };
1492
+ if (prEl) {
1493
+ const chrEl = findMathChild(prEl, "chr");
1494
+ if (chrEl) {
1495
+ g.char = mathAttrVal(chrEl, "val");
1496
+ }
1497
+ const posEl = findMathChild(prEl, "pos");
1498
+ if (posEl) {
1499
+ const v = mathAttrVal(posEl, "val");
1500
+ if (v === "top" || v === "bottom") {
1501
+ g.position = v;
1502
+ }
1503
+ }
1504
+ const vjcEl = findMathChild(prEl, "vertJc");
1505
+ if (vjcEl) {
1506
+ const v = mathAttrVal(vjcEl, "val");
1507
+ if (v === "top" || v === "center" || v === "bottom") {
1508
+ g.verticalAlign = v;
1509
+ }
1510
+ }
1511
+ }
1512
+ result.push(g);
1513
+ break;
1514
+ }
1515
+ case "borderBox": {
1516
+ const eEl = findMathChild(child, "e");
1517
+ const prEl = findMathChild(child, "borderBoxPr");
1518
+ const b = {
1519
+ type: "mathBorderBox",
1520
+ content: eEl ? parseMathContent(eEl) : []
1521
+ };
1522
+ if (prEl) {
1523
+ const boolAttr = (name) => {
1524
+ const el = findMathChild(prEl, name);
1525
+ if (!el) {
1526
+ return false;
1527
+ }
1528
+ const v = mathAttrVal(el, "val");
1529
+ return v !== "0" && v !== "false";
1530
+ };
1531
+ if (boolAttr("hideTop")) {
1532
+ b.hideTop = true;
1533
+ }
1534
+ if (boolAttr("hideBot")) {
1535
+ b.hideBottom = true;
1536
+ }
1537
+ if (boolAttr("hideLeft")) {
1538
+ b.hideLeft = true;
1539
+ }
1540
+ if (boolAttr("hideRight")) {
1541
+ b.hideRight = true;
1542
+ }
1543
+ if (boolAttr("strikeBLTR")) {
1544
+ b.strikeBlTr = true;
1545
+ }
1546
+ if (boolAttr("strikeTLBR")) {
1547
+ b.strikeTlBr = true;
1548
+ }
1549
+ if (boolAttr("strikeH")) {
1550
+ b.strikeH = true;
1551
+ }
1552
+ if (boolAttr("strikeV")) {
1553
+ b.strikeV = true;
1554
+ }
1555
+ }
1556
+ result.push(b);
1557
+ break;
1558
+ }
1559
+ case "rad": {
1560
+ const radPrEl = findMathChild(child, "radPr");
1561
+ const deg = findMathChild(child, "deg");
1562
+ const e = findMathChild(child, "e");
1563
+ const rad = {
1564
+ type: "mathRadical",
1565
+ content: e ? parseMathContent(e) : []
1566
+ };
1567
+ if (deg) {
1568
+ rad.degree = parseMathContent(deg);
1569
+ }
1570
+ if (radPrEl) {
1571
+ const hd = findMathChild(radPrEl, "degHide");
1572
+ if (hd) {
1573
+ const v = hd.attributes["m:val"] ?? hd.attributes["val"];
1574
+ if (v === "1" || v === "on" || v === "true") {
1575
+ rad.hideDegree = true;
1576
+ }
1577
+ }
1578
+ }
1579
+ result.push(rad);
1580
+ break;
1581
+ }
1582
+ case "d": {
1583
+ const dPrEl = findMathChild(child, "dPr");
1584
+ const delim = { type: "mathDelimiter", content: [] };
1585
+ if (dPrEl) {
1586
+ const bc = findMathChild(dPrEl, "begChr");
1587
+ if (bc) {
1588
+ delim.beginChar = bc.attributes["m:val"] ?? bc.attributes["val"];
1589
+ }
1590
+ const ec = findMathChild(dPrEl, "endChr");
1591
+ if (ec) {
1592
+ delim.endChar = ec.attributes["m:val"] ?? ec.attributes["val"];
1593
+ }
1594
+ const sc = findMathChild(dPrEl, "sepChr");
1595
+ if (sc) {
1596
+ delim.separatorChar = sc.attributes["m:val"] ?? sc.attributes["val"];
1597
+ }
1598
+ }
1599
+ for (const eEl of findMathChildren(child, "e")) {
1600
+ delim.content.push(parseMathContent(eEl));
1601
+ }
1602
+ result.push(delim);
1603
+ break;
1604
+ }
1605
+ case "nary": {
1606
+ const nPrEl = findMathChild(child, "naryPr");
1607
+ const sub = findMathChild(child, "sub");
1608
+ const sup = findMathChild(child, "sup");
1609
+ const e = findMathChild(child, "e");
1610
+ const nary = {
1611
+ type: "mathNary",
1612
+ content: e ? parseMathContent(e) : []
1613
+ };
1614
+ if (sub) {
1615
+ nary.sub = parseMathContent(sub);
1616
+ }
1617
+ if (sup) {
1618
+ nary.sup = parseMathContent(sup);
1619
+ }
1620
+ if (nPrEl) {
1621
+ const chrEl = findMathChild(nPrEl, "chr");
1622
+ if (chrEl) {
1623
+ nary.char = chrEl.attributes["m:val"] ?? chrEl.attributes["val"];
1624
+ }
1625
+ const limLoc = findMathChild(nPrEl, "limLoc");
1626
+ if (limLoc) {
1627
+ nary.limitsLocation = limLoc.attributes["m:val"] ?? limLoc.attributes["val"];
1628
+ }
1629
+ const sh = findMathChild(nPrEl, "supHide");
1630
+ if (sh && (sh.attributes["m:val"] ?? sh.attributes["val"]) === "1") {
1631
+ nary.supHide = true;
1632
+ }
1633
+ const sbh = findMathChild(nPrEl, "subHide");
1634
+ if (sbh && (sbh.attributes["m:val"] ?? sbh.attributes["val"]) === "1") {
1635
+ nary.subHide = true;
1636
+ }
1637
+ }
1638
+ result.push(nary);
1639
+ break;
1640
+ }
1641
+ case "func": {
1642
+ const fName = findMathChild(child, "fName");
1643
+ const e = findMathChild(child, "e");
1644
+ result.push({
1645
+ type: "mathFunction",
1646
+ name: fName ? parseMathContent(fName) : [],
1647
+ content: e ? parseMathContent(e) : []
1648
+ });
1649
+ break;
1650
+ }
1651
+ case "limLow": {
1652
+ const base = findMathChild(child, "e");
1653
+ const lim = findMathChild(child, "lim");
1654
+ result.push({
1655
+ type: "mathLimit",
1656
+ limitType: "lower",
1657
+ base: base ? parseMathContent(base) : [],
1658
+ limit: lim ? parseMathContent(lim) : []
1659
+ });
1660
+ break;
1661
+ }
1662
+ case "limUpp": {
1663
+ const base = findMathChild(child, "e");
1664
+ const lim = findMathChild(child, "lim");
1665
+ result.push({
1666
+ type: "mathLimit",
1667
+ limitType: "upper",
1668
+ base: base ? parseMathContent(base) : [],
1669
+ limit: lim ? parseMathContent(lim) : []
1670
+ });
1671
+ break;
1672
+ }
1673
+ case "m": {
1674
+ // Matrix
1675
+ const rows = [];
1676
+ for (const mrEl of findMathChildren(child, "mr")) {
1677
+ const row = [];
1678
+ for (const eEl of findMathChildren(mrEl, "e")) {
1679
+ row.push(parseMathContent(eEl));
1680
+ }
1681
+ rows.push(row);
1682
+ }
1683
+ result.push({ type: "mathMatrix", rows });
1684
+ break;
1685
+ }
1686
+ case "acc": {
1687
+ const accPrEl = findMathChild(child, "accPr");
1688
+ const e = findMathChild(child, "e");
1689
+ const acc = {
1690
+ type: "mathAccent",
1691
+ content: e ? parseMathContent(e) : []
1692
+ };
1693
+ if (accPrEl) {
1694
+ const chr = findMathChild(accPrEl, "chr");
1695
+ if (chr) {
1696
+ acc.char = chr.attributes["m:val"] ?? chr.attributes["val"];
1697
+ }
1698
+ }
1699
+ result.push(acc);
1700
+ break;
1701
+ }
1702
+ case "bar": {
1703
+ const barPrEl = findMathChild(child, "barPr");
1704
+ const e = findMathChild(child, "e");
1705
+ let position = "top";
1706
+ if (barPrEl) {
1707
+ const pos = findMathChild(barPrEl, "pos");
1708
+ if (pos) {
1709
+ const v = pos.attributes["m:val"] ?? pos.attributes["val"];
1710
+ if (v === "bot") {
1711
+ position = "bottom";
1712
+ }
1713
+ }
1714
+ }
1715
+ result.push({
1716
+ type: "mathBar",
1717
+ position,
1718
+ content: e ? parseMathContent(e) : []
1719
+ });
1720
+ break;
1721
+ }
1722
+ case "box": {
1723
+ const e = findMathChild(child, "e");
1724
+ result.push({
1725
+ type: "mathBox",
1726
+ content: e ? parseMathContent(e) : []
1727
+ });
1728
+ break;
1729
+ }
1730
+ case "eqArr": {
1731
+ const rows = [];
1732
+ for (const eEl of findMathChildren(child, "e")) {
1733
+ rows.push(parseMathContent(eEl));
1734
+ }
1735
+ result.push({ type: "mathEquationArray", rows });
1736
+ break;
1737
+ }
1738
+ // Recurse into oMath elements
1739
+ case "oMath": {
1740
+ result.push(...parseMathContent(child));
1741
+ break;
1742
+ }
1743
+ }
1744
+ }
1745
+ return result;
1746
+ }
1747
+ function parseMathBlock(oMathParaEl) {
1748
+ const content = [];
1749
+ for (const child of oMathParaEl.children) {
1750
+ if (child.type === "element") {
1751
+ const n = child.name.replace(/^m:/, "");
1752
+ if (n === "oMath") {
1753
+ content.push(...parseMathContent(child));
1754
+ }
1755
+ }
1756
+ }
1757
+ return { type: "math", content };
1758
+ }
1759
+ // =============================================================================
1760
+ // TextBox Parser
1761
+ // =============================================================================
1762
+ function parseTextBox(pictEl) {
1763
+ // Look for v:shape > v:textbox > w:txbxContent
1764
+ let txbxContentEl;
1765
+ let shapeEl;
1766
+ for (const child of pictEl.children) {
1767
+ if (child.type === "element" && (child.name === "v:shape" || child.name === "v:rect")) {
1768
+ shapeEl = child;
1769
+ for (const sc of child.children) {
1770
+ if (sc.type === "element" && sc.name === "v:textbox") {
1771
+ for (const tc of sc.children) {
1772
+ if (tc.type === "element" &&
1773
+ (tc.name === "w:txbxContent" || tc.name === "txbxContent")) {
1774
+ txbxContentEl = tc;
1775
+ }
1776
+ }
1777
+ }
1778
+ }
1779
+ }
1780
+ }
1781
+ if (!txbxContentEl) {
1782
+ return undefined;
1783
+ }
1784
+ const paragraphs = [];
1785
+ for (const c of txbxContentEl.children) {
1786
+ if (c.type === "element" && c.name.replace(/^w:/, "") === "p") {
1787
+ paragraphs.push(parseParagraph(c));
1788
+ }
1789
+ }
1790
+ const tb = { type: "textBox", content: paragraphs };
1791
+ if (shapeEl) {
1792
+ const style = shapeEl.attributes["style"];
1793
+ if (style) {
1794
+ tb.style = style;
1795
+ }
1796
+ const sc = shapeEl.attributes["strokecolor"];
1797
+ if (sc) {
1798
+ tb.strokeColor = sc;
1799
+ }
1800
+ const fc = shapeEl.attributes["fillcolor"];
1801
+ if (fc) {
1802
+ tb.fillColor = fc;
1803
+ }
1804
+ if (shapeEl.attributes["stroked"] === "f") {
1805
+ tb.stroke = false;
1806
+ }
1807
+ if (shapeEl.attributes["filled"] === "f") {
1808
+ tb.fill = false;
1809
+ }
1810
+ }
1811
+ return tb;
1812
+ }
1813
+ // =============================================================================
1814
+ // SDT / CheckBox / TOC Parser
1815
+ // =============================================================================
1816
+ function parseSdt(sdtEl) {
1817
+ const sdtPrEl = findChildNs(sdtEl, "sdtPr");
1818
+ const sdtContentEl = findChildNs(sdtEl, "sdtContent");
1819
+ // Check for checkbox (w14:checkbox)
1820
+ if (sdtPrEl) {
1821
+ const checkBoxEl = (0, dom_1.findChild)(sdtPrEl, "w14:checkbox");
1822
+ if (checkBoxEl) {
1823
+ return parseCheckBox(checkBoxEl);
1824
+ }
1825
+ }
1826
+ // Check for TOC (contains docPartObj with docPartGallery "Table of Contents")
1827
+ if (sdtPrEl) {
1828
+ const docPartObjEl = findChildNs(sdtPrEl, "docPartObj");
1829
+ if (docPartObjEl) {
1830
+ const galleryEl = findChildNs(docPartObjEl, "docPartGallery");
1831
+ const galleryVal = galleryEl ? attrVal(galleryEl, "val") : undefined;
1832
+ if (galleryVal === "Table of Contents") {
1833
+ return parseTocFromSdt(sdtContentEl);
1834
+ }
1835
+ }
1836
+ }
1837
+ // Generic SDT
1838
+ const props = {};
1839
+ if (sdtPrEl) {
1840
+ const tagEl = findChildNs(sdtPrEl, "tag");
1841
+ if (tagEl) {
1842
+ props.tag = attrVal(tagEl, "val");
1843
+ }
1844
+ const aliasEl = findChildNs(sdtPrEl, "alias");
1845
+ if (aliasEl) {
1846
+ props.alias = attrVal(aliasEl, "val");
1847
+ }
1848
+ const lockEl = findChildNs(sdtPrEl, "lock");
1849
+ if (lockEl) {
1850
+ const v = attrVal(lockEl, "val");
1851
+ if (v === "contentLocked" || v === "sdtContentLocked") {
1852
+ props.lockContent = true;
1853
+ }
1854
+ if (v === "sdtLocked" || v === "sdtContentLocked") {
1855
+ props.lockSdt = true;
1856
+ }
1857
+ }
1858
+ // Plain text
1859
+ if (findChildNs(sdtPrEl, "text")) {
1860
+ props.plainText = true;
1861
+ }
1862
+ // showingPlcHdr is a toggle, not a property with a val
1863
+ if (findChildNs(sdtPrEl, "showingPlcHdr")) {
1864
+ const v = boolToggle(sdtPrEl, "showingPlcHdr");
1865
+ if (v !== false) {
1866
+ props.showingPlaceholder = true;
1867
+ }
1868
+ }
1869
+ // w15:appearance (replaces the old misused showingPlcHdr)
1870
+ const appearanceEl = (0, dom_1.findChild)(sdtPrEl, "w15:appearance");
1871
+ if (appearanceEl) {
1872
+ const v = appearanceEl.attributes["w15:val"] ?? appearanceEl.attributes["val"];
1873
+ if (v === "boundingBox" || v === "tags" || v === "hidden") {
1874
+ props.appearance = v;
1875
+ }
1876
+ }
1877
+ // Dropdown list
1878
+ const ddlEl = findChildNs(sdtPrEl, "dropDownList");
1879
+ if (ddlEl) {
1880
+ const items = [];
1881
+ for (const li of findChildrenNs(ddlEl, "listItem")) {
1882
+ const item = { value: attrVal(li, "value") ?? "" };
1883
+ const dt = attrVal(li, "displayText");
1884
+ if (dt) {
1885
+ item.displayText = dt;
1886
+ }
1887
+ items.push(item);
1888
+ }
1889
+ props.dropdownList = items;
1890
+ }
1891
+ // ComboBox
1892
+ const cbEl = findChildNs(sdtPrEl, "comboBox");
1893
+ if (cbEl) {
1894
+ const items = [];
1895
+ for (const li of findChildrenNs(cbEl, "listItem")) {
1896
+ const item = { value: attrVal(li, "value") ?? "" };
1897
+ const dt = attrVal(li, "displayText");
1898
+ if (dt) {
1899
+ item.displayText = dt;
1900
+ }
1901
+ items.push(item);
1902
+ }
1903
+ props.comboBox = items;
1904
+ }
1905
+ // Date picker
1906
+ const dateEl = findChildNs(sdtPrEl, "date");
1907
+ if (dateEl) {
1908
+ const dateProp = {};
1909
+ const fullDate = attrVal(dateEl, "fullDate");
1910
+ if (fullDate) {
1911
+ dateProp.fullDate = fullDate;
1912
+ }
1913
+ const dfEl = findChildNs(dateEl, "dateFormat");
1914
+ if (dfEl) {
1915
+ dateProp.dateFormat = attrVal(dfEl, "val");
1916
+ }
1917
+ const lidEl = findChildNs(dateEl, "lid");
1918
+ if (lidEl) {
1919
+ dateProp.lid = attrVal(lidEl, "val");
1920
+ }
1921
+ const storeEl = findChildNs(dateEl, "storeMappedDataAs");
1922
+ if (storeEl) {
1923
+ dateProp.storeMappedDataAs = attrVal(storeEl, "val");
1924
+ }
1925
+ props.date = dateProp;
1926
+ }
1927
+ // ID
1928
+ const idEl = findChildNs(sdtPrEl, "id");
1929
+ if (idEl) {
1930
+ const v = attrInt(idEl, "val");
1931
+ if (v !== undefined) {
1932
+ props.id = v;
1933
+ }
1934
+ }
1935
+ // Data binding
1936
+ const dbEl = findChildNs(sdtPrEl, "dataBinding");
1937
+ if (dbEl) {
1938
+ const xpath = attrVal(dbEl, "xpath");
1939
+ const storeItemId = attrVal(dbEl, "storeItemID");
1940
+ if (xpath && storeItemId) {
1941
+ const binding = { xpath, storeItemId };
1942
+ const prefixMappings = attrVal(dbEl, "prefixMappings");
1943
+ if (prefixMappings) {
1944
+ binding.prefixMappings = prefixMappings;
1945
+ }
1946
+ props.dataBinding = binding;
1947
+ }
1948
+ }
1949
+ // Placeholder
1950
+ const phEl = findChildNs(sdtPrEl, "placeholder");
1951
+ if (phEl) {
1952
+ const docPartEl = findChildNs(phEl, "docPart");
1953
+ if (docPartEl) {
1954
+ props.placeholder = attrVal(docPartEl, "val");
1955
+ }
1956
+ }
1957
+ // Boolean marker elements
1958
+ if (findChildNs(sdtPrEl, "richText")) {
1959
+ props.richText = true;
1960
+ }
1961
+ if (findChildNs(sdtPrEl, "picture")) {
1962
+ props.picture = true;
1963
+ }
1964
+ if (findChildNs(sdtPrEl, "group")) {
1965
+ props.group = true;
1966
+ }
1967
+ if (findChildNs(sdtPrEl, "equation")) {
1968
+ props.equation = true;
1969
+ }
1970
+ if (findChildNs(sdtPrEl, "citation")) {
1971
+ props.citation = true;
1972
+ }
1973
+ if (findChildNs(sdtPrEl, "bibliography")) {
1974
+ props.bibliography = true;
1975
+ }
1976
+ if (findChildNs(sdtPrEl, "temporary")) {
1977
+ props.temporary = true;
1978
+ }
1979
+ // w15: repeating section
1980
+ const rsEl = (0, dom_1.findChild)(sdtPrEl, "w15:repeatingSection");
1981
+ if (rsEl) {
1982
+ const rs = {};
1983
+ // Read from child elements (correct per schema)
1984
+ const titleEl = (0, dom_1.findChild)(rsEl, "w15:sectionTitle");
1985
+ if (titleEl) {
1986
+ const v = titleEl.attributes["w15:val"] ?? titleEl.attributes["val"];
1987
+ if (v !== undefined) {
1988
+ rs.sectionTitle = v;
1989
+ }
1990
+ }
1991
+ if ((0, dom_1.findChild)(rsEl, "w15:doNotAllowInsertDeleteSection")) {
1992
+ rs.allowInsertDelete = false;
1993
+ }
1994
+ // Also accept attribute form for backwards compatibility
1995
+ const stAttr = rsEl.attributes["w15:sectionTitle"];
1996
+ if (stAttr !== undefined && rs.sectionTitle === undefined) {
1997
+ rs.sectionTitle = stAttr;
1998
+ }
1999
+ const noInsDelAttr = rsEl.attributes["w15:doNotAllowInsertDeleteSection"];
2000
+ if (noInsDelAttr !== undefined && rs.allowInsertDelete === undefined) {
2001
+ rs.allowInsertDelete = noInsDelAttr === "0";
2002
+ }
2003
+ props.repeatingSection = rs;
2004
+ }
2005
+ if ((0, dom_1.findChild)(sdtPrEl, "w15:repeatingSectionItem")) {
2006
+ props.repeatingSectionItem = true;
2007
+ }
2008
+ }
2009
+ const content = [];
2010
+ if (sdtContentEl) {
2011
+ for (const child of sdtContentEl.children) {
2012
+ if (child.type !== "element") {
2013
+ continue;
2014
+ }
2015
+ const n = child.name.replace(/^w:/, "");
2016
+ if (n === "p") {
2017
+ content.push(parseParagraph(child));
2018
+ }
2019
+ else if (n === "tbl") {
2020
+ content.push(parseTable(child));
2021
+ }
2022
+ else if (n === "r") {
2023
+ content.push(parseRun(child));
2024
+ }
2025
+ }
2026
+ }
2027
+ return { type: "sdt", properties: props, content };
2028
+ }
2029
+ function parseCheckBox(checkBoxEl) {
2030
+ const cb = { type: "checkBox" };
2031
+ const checkedEl = (0, dom_1.findChild)(checkBoxEl, "w14:checked");
2032
+ if (checkedEl) {
2033
+ const v = checkedEl.attributes["w14:val"] ?? checkedEl.attributes["val"];
2034
+ cb.checked = v === "1" || v === "true";
2035
+ }
2036
+ const checkedStateEl = (0, dom_1.findChild)(checkBoxEl, "w14:checkedState");
2037
+ if (checkedStateEl) {
2038
+ cb.checkedState = {
2039
+ value: checkedStateEl.attributes["w14:val"] ?? checkedStateEl.attributes["val"] ?? "",
2040
+ font: checkedStateEl.attributes["w14:font"] ?? checkedStateEl.attributes["font"]
2041
+ };
2042
+ }
2043
+ const uncheckedStateEl = (0, dom_1.findChild)(checkBoxEl, "w14:uncheckedState");
2044
+ if (uncheckedStateEl) {
2045
+ cb.uncheckedState = {
2046
+ value: uncheckedStateEl.attributes["w14:val"] ?? uncheckedStateEl.attributes["val"] ?? "",
2047
+ font: uncheckedStateEl.attributes["w14:font"] ?? uncheckedStateEl.attributes["font"]
2048
+ };
2049
+ }
2050
+ return cb;
2051
+ }
2052
+ function parseTocFromSdt(sdtContentEl) {
2053
+ const toc = { type: "tableOfContents" };
2054
+ const cachedParagraphs = [];
2055
+ if (sdtContentEl) {
2056
+ // Collect all instrText to assemble the complete TOC field instruction
2057
+ let instrText = "";
2058
+ const collectInstr = (el) => {
2059
+ for (const child of el.children) {
2060
+ if (child.type !== "element") {
2061
+ continue;
2062
+ }
2063
+ const name = child.name.replace(/^w:/, "");
2064
+ if (name === "instrText") {
2065
+ instrText += (0, dom_1.textContent)(child);
2066
+ }
2067
+ else {
2068
+ collectInstr(child);
2069
+ }
2070
+ }
2071
+ };
2072
+ collectInstr(sdtContentEl);
2073
+ if (instrText.trim()) {
2074
+ parseTocInstruction(instrText, toc);
2075
+ }
2076
+ for (const child of sdtContentEl.children) {
2077
+ if (child.type !== "element") {
2078
+ continue;
2079
+ }
2080
+ const n = child.name.replace(/^w:/, "");
2081
+ if (n === "p") {
2082
+ cachedParagraphs.push(parseParagraph(child));
2083
+ }
2084
+ }
2085
+ }
2086
+ if (cachedParagraphs.length > 0) {
2087
+ toc.cachedParagraphs = cachedParagraphs;
2088
+ }
2089
+ return toc;
2090
+ }
2091
+ /** Parse a TOC field instruction string (e.g. `TOC \o "1-3" \h \t "Style,1" \c "Figure"`). */
2092
+ function parseTocInstruction(instr, toc) {
2093
+ const trimmed = instr.trim();
2094
+ if (!/^TOC\b/i.test(trimmed)) {
2095
+ return;
2096
+ }
2097
+ // Match switches: \<letter> followed by either "quoted" or non-quoted non-switch token.
2098
+ // The next-switch boundary must be respected: an unquoted value cannot start with \.
2099
+ const switchRe = /\\(\w)(?:\s+"([^"]*)"|\s+([^\\\s][^\s]*))?/g;
2100
+ let match;
2101
+ while ((match = switchRe.exec(trimmed)) !== null) {
2102
+ const switchName = match[1].toLowerCase();
2103
+ const value = match[2] ?? match[3];
2104
+ switch (switchName) {
2105
+ case "o": // Heading level range e.g. "1-3"
2106
+ if (value) {
2107
+ toc.headingStyleRange = value;
2108
+ }
2109
+ break;
2110
+ case "h": // Hyperlinks
2111
+ toc.hyperlink = true;
2112
+ break;
2113
+ case "c": // Caption label (table of figures)
2114
+ if (value) {
2115
+ toc.captionLabel = value;
2116
+ }
2117
+ break;
2118
+ case "s": // Sequence field identifier
2119
+ if (value) {
2120
+ toc.sequenceFieldIdentifier = value;
2121
+ }
2122
+ break;
2123
+ case "p": // Page-number leader or style separator
2124
+ // In real TOC fields, \p is sometimes used for tab leader.
2125
+ // Common values: "." "-" "_"
2126
+ if (value === "." || value === "-" || value === "_") {
2127
+ toc.leader = "dot";
2128
+ if (value === "-") {
2129
+ toc.leader = "hyphen";
2130
+ }
2131
+ else if (value === "_") {
2132
+ toc.leader = "underscore";
2133
+ }
2134
+ }
2135
+ break;
2136
+ case "t": {
2137
+ // Styles with levels: "StyleName1,Level1;StyleName2,Level2;..."
2138
+ if (!value) {
2139
+ break;
2140
+ }
2141
+ const items = [];
2142
+ for (const part of value.split(";")) {
2143
+ const [styleName, levelStr] = part.split(",");
2144
+ if (styleName && levelStr) {
2145
+ items.push({ styleName: styleName.trim(), level: parseInt(levelStr, 10) });
2146
+ }
2147
+ }
2148
+ if (items.length > 0) {
2149
+ toc.stylesWithLevels = items;
2150
+ }
2151
+ break;
2152
+ }
2153
+ }
2154
+ }
2155
+ }
2156
+ // =============================================================================
2157
+ // Paragraph Parser
2158
+ // =============================================================================
2159
+ function parseRun(el) {
2160
+ const rPrEl = findChildNs(el, "rPr");
2161
+ return {
2162
+ properties: rPrEl ? parseRunProperties(rPrEl) : undefined,
2163
+ content: parseRunContent(el)
2164
+ };
2165
+ }
2166
+ function parseParagraph(pEl) {
2167
+ const pPrEl = findChildNs(pEl, "pPr");
2168
+ const children = [];
2169
+ // fldChar state machine: tracks field code assembly across runs
2170
+ let fieldState = "none";
2171
+ let fieldInstr = "";
2172
+ let fieldCached = "";
2173
+ let fieldRunProps;
2174
+ let fieldFormField;
2175
+ for (const child of pEl.children) {
2176
+ if (child.type !== "element") {
2177
+ continue;
2178
+ }
2179
+ // Handle mc:AlternateContent — pick mc:Choice, fall back to mc:Fallback
2180
+ let resolved = child;
2181
+ if (child.name === "mc:AlternateContent") {
2182
+ const choice = (0, dom_1.findChild)(child, "mc:Choice");
2183
+ const fallback = (0, dom_1.findChild)(child, "mc:Fallback");
2184
+ const chosen = choice ?? fallback;
2185
+ if (chosen && chosen.children.length > 0) {
2186
+ // The first element child inside Choice/Fallback is the real element
2187
+ const inner = chosen.children.find(c => c.type === "element");
2188
+ if (inner) {
2189
+ resolved = inner;
2190
+ }
2191
+ else {
2192
+ continue;
2193
+ }
2194
+ }
2195
+ else {
2196
+ continue;
2197
+ }
2198
+ }
2199
+ const name = resolved.name.replace(/^w:/, "");
2200
+ switch (name) {
2201
+ case "r": {
2202
+ // Check for fldChar and instrText inside the run
2203
+ let hasFldChar = false;
2204
+ for (const rc of resolved.children) {
2205
+ if (rc.type !== "element") {
2206
+ continue;
2207
+ }
2208
+ const rcName = rc.name.replace(/^w:/, "");
2209
+ if (rcName === "fldChar") {
2210
+ hasFldChar = true;
2211
+ const fldCharType = attrVal(rc, "fldCharType");
2212
+ if (fldCharType === "begin") {
2213
+ fieldState = "instrText";
2214
+ fieldInstr = "";
2215
+ fieldCached = "";
2216
+ // Capture run properties from this run for the field
2217
+ const rPrEl = findChildNs(resolved, "rPr");
2218
+ fieldRunProps = rPrEl ? parseRunProperties(rPrEl) : undefined;
2219
+ // Parse ffData for legacy form fields
2220
+ const ffDataEl = findChildNs(rc, "ffData");
2221
+ if (ffDataEl) {
2222
+ fieldFormField = parseFfData(ffDataEl);
2223
+ }
2224
+ else {
2225
+ fieldFormField = undefined;
2226
+ }
2227
+ }
2228
+ else if (fldCharType === "separate") {
2229
+ fieldState = "cached";
2230
+ }
2231
+ else if (fldCharType === "end") {
2232
+ // Emit the assembled field as a Run with FieldContent
2233
+ const fc = {
2234
+ type: "field",
2235
+ instruction: fieldInstr.trim(),
2236
+ cachedValue: fieldCached || undefined,
2237
+ formField: fieldFormField
2238
+ };
2239
+ children.push({
2240
+ properties: fieldRunProps,
2241
+ content: [fc]
2242
+ });
2243
+ fieldState = "none";
2244
+ fieldInstr = "";
2245
+ fieldCached = "";
2246
+ fieldRunProps = undefined;
2247
+ }
2248
+ }
2249
+ else if (rcName === "instrText" && fieldState === "instrText") {
2250
+ hasFldChar = true;
2251
+ fieldInstr += (0, dom_1.textContent)(rc);
2252
+ }
2253
+ }
2254
+ if (fieldState === "cached") {
2255
+ // Collect cached text from this run
2256
+ for (const rc of resolved.children) {
2257
+ if (rc.type !== "element") {
2258
+ continue;
2259
+ }
2260
+ const rcName = rc.name.replace(/^w:/, "");
2261
+ if (rcName === "t") {
2262
+ fieldCached += (0, dom_1.textContent)(rc);
2263
+ }
2264
+ else if (rcName === "fldChar") {
2265
+ // Already handled above
2266
+ }
2267
+ }
2268
+ if (!hasFldChar) {
2269
+ continue; // Skip adding this run normally
2270
+ }
2271
+ }
2272
+ if (fieldState === "instrText" && hasFldChar) {
2273
+ continue; // Don't add begin/instrText runs as normal content
2274
+ }
2275
+ if (fieldState === "none" && !hasFldChar) {
2276
+ children.push(parseRun(resolved));
2277
+ }
2278
+ break;
2279
+ }
2280
+ case "fldSimple": {
2281
+ // Simple field: <w:fldSimple w:instr=" PAGE "><w:r>...</w:r></w:fldSimple>
2282
+ const instr = attrVal(resolved, "instr") ?? "";
2283
+ let cached = "";
2284
+ for (const fc of resolved.children) {
2285
+ if (fc.type === "element" && fc.name.replace(/^w:/, "") === "r") {
2286
+ for (const rc of fc.children) {
2287
+ if (rc.type === "element" && rc.name.replace(/^w:/, "") === "t") {
2288
+ cached += (0, dom_1.textContent)(rc);
2289
+ }
2290
+ }
2291
+ }
2292
+ }
2293
+ const fc = {
2294
+ type: "field",
2295
+ instruction: instr.trim(),
2296
+ cachedValue: cached || undefined
2297
+ };
2298
+ children.push({
2299
+ properties: undefined,
2300
+ content: [fc]
2301
+ });
2302
+ break;
2303
+ }
2304
+ case "hyperlink": {
2305
+ const rId = resolved.attributes["r:id"];
2306
+ const anchor = resolved.attributes["w:anchor"] ?? resolved.attributes["anchor"];
2307
+ const tooltip = resolved.attributes["w:tooltip"] ?? resolved.attributes["tooltip"];
2308
+ const historyAttr = resolved.attributes["w:history"] ?? resolved.attributes["history"];
2309
+ const tgtFrame = resolved.attributes["w:tgtFrame"] ?? resolved.attributes["tgtFrame"];
2310
+ const docLocation = resolved.attributes["w:docLocation"] ?? resolved.attributes["docLocation"];
2311
+ const hRuns = [];
2312
+ for (const hChild of resolved.children) {
2313
+ if (hChild.type === "element" && hChild.name.replace(/^w:/, "") === "r") {
2314
+ hRuns.push(parseRun(hChild));
2315
+ }
2316
+ }
2317
+ // Resolve URL from relMap
2318
+ let url;
2319
+ if (rId) {
2320
+ const rel = _parseRelMap.get(rId);
2321
+ if (rel && rel.targetMode === "External") {
2322
+ url = rel.target;
2323
+ }
2324
+ }
2325
+ const hyperlink = {
2326
+ type: "hyperlink",
2327
+ rId,
2328
+ anchor,
2329
+ url,
2330
+ tooltip,
2331
+ children: hRuns
2332
+ };
2333
+ if (historyAttr === "1" || historyAttr === "true") {
2334
+ hyperlink.history = true;
2335
+ }
2336
+ if (tgtFrame) {
2337
+ hyperlink.tgtFrame = tgtFrame;
2338
+ }
2339
+ if (docLocation) {
2340
+ hyperlink.docLocation = docLocation;
2341
+ }
2342
+ children.push(hyperlink);
2343
+ break;
2344
+ }
2345
+ case "bookmarkStart": {
2346
+ const bm = {
2347
+ type: "bookmarkStart",
2348
+ id: parseInt(resolved.attributes["w:id"] ?? resolved.attributes["id"] ?? "0", 10),
2349
+ name: resolved.attributes["w:name"] ?? resolved.attributes["name"] ?? ""
2350
+ };
2351
+ const colFirst = resolved.attributes["w:colFirst"] ?? resolved.attributes["colFirst"];
2352
+ if (colFirst !== undefined) {
2353
+ bm.colFirst = parseInt(colFirst, 10);
2354
+ }
2355
+ const colLast = resolved.attributes["w:colLast"] ?? resolved.attributes["colLast"];
2356
+ if (colLast !== undefined) {
2357
+ bm.colLast = parseInt(colLast, 10);
2358
+ }
2359
+ const dcx = resolved.attributes["w:displacedByCustomXml"] ??
2360
+ resolved.attributes["displacedByCustomXml"];
2361
+ if (dcx === "next" || dcx === "prev") {
2362
+ bm.displacedByCustomXml = dcx;
2363
+ }
2364
+ children.push(bm);
2365
+ break;
2366
+ }
2367
+ case "bookmarkEnd":
2368
+ children.push({
2369
+ type: "bookmarkEnd",
2370
+ id: parseInt(resolved.attributes["w:id"] ?? resolved.attributes["id"] ?? "0", 10)
2371
+ });
2372
+ break;
2373
+ case "commentRangeStart":
2374
+ children.push({
2375
+ type: "commentRangeStart",
2376
+ id: parseInt(resolved.attributes["w:id"] ?? resolved.attributes["id"] ?? "0", 10)
2377
+ });
2378
+ break;
2379
+ case "commentRangeEnd":
2380
+ children.push({
2381
+ type: "commentRangeEnd",
2382
+ id: parseInt(resolved.attributes["w:id"] ?? resolved.attributes["id"] ?? "0", 10)
2383
+ });
2384
+ break;
2385
+ case "commentReference":
2386
+ children.push({
2387
+ type: "commentReference",
2388
+ id: parseInt(resolved.attributes["w:id"] ?? resolved.attributes["id"] ?? "0", 10)
2389
+ });
2390
+ break;
2391
+ case "ins": {
2392
+ // Inserted run (track changes)
2393
+ const rev = parseRevisionInfo(resolved);
2394
+ if (rev) {
2395
+ for (const insChild of resolved.children) {
2396
+ if (insChild.type === "element" && insChild.name.replace(/^w:/, "") === "r") {
2397
+ children.push({
2398
+ type: "insertedRun",
2399
+ revision: rev,
2400
+ run: parseRun(insChild)
2401
+ });
2402
+ }
2403
+ }
2404
+ }
2405
+ break;
2406
+ }
2407
+ case "del": {
2408
+ // Deleted run (track changes)
2409
+ const rev = parseRevisionInfo(resolved);
2410
+ if (rev) {
2411
+ for (const delChild of resolved.children) {
2412
+ if (delChild.type === "element" && delChild.name.replace(/^w:/, "") === "r") {
2413
+ children.push({
2414
+ type: "deletedRun",
2415
+ revision: rev,
2416
+ run: parseDeletedRun(delChild)
2417
+ });
2418
+ }
2419
+ }
2420
+ }
2421
+ break;
2422
+ }
2423
+ case "moveFrom": {
2424
+ const rev = parseRevisionInfo(resolved);
2425
+ if (rev) {
2426
+ for (const mfChild of resolved.children) {
2427
+ if (mfChild.type === "element" && mfChild.name.replace(/^w:/, "") === "r") {
2428
+ children.push({
2429
+ type: "movedFromRun",
2430
+ revision: rev,
2431
+ run: parseRun(mfChild)
2432
+ });
2433
+ }
2434
+ }
2435
+ }
2436
+ break;
2437
+ }
2438
+ case "moveTo": {
2439
+ const rev = parseRevisionInfo(resolved);
2440
+ if (rev) {
2441
+ for (const mtChild of resolved.children) {
2442
+ if (mtChild.type === "element" && mtChild.name.replace(/^w:/, "") === "r") {
2443
+ children.push({
2444
+ type: "movedToRun",
2445
+ revision: rev,
2446
+ run: parseRun(mtChild)
2447
+ });
2448
+ }
2449
+ }
2450
+ }
2451
+ break;
2452
+ }
2453
+ case "moveFromRangeStart":
2454
+ case "moveFromRangeEnd":
2455
+ case "moveToRangeStart":
2456
+ case "moveToRangeEnd": {
2457
+ const id = attrInt(resolved, "id");
2458
+ if (id !== undefined) {
2459
+ const marker = {
2460
+ type: name,
2461
+ id
2462
+ };
2463
+ const author = attrVal(resolved, "author");
2464
+ if (author) {
2465
+ marker.author = author;
2466
+ }
2467
+ const date = attrVal(resolved, "date");
2468
+ if (date) {
2469
+ marker.date = date;
2470
+ }
2471
+ const mName = attrVal(resolved, "name");
2472
+ if (mName) {
2473
+ marker.name = mName;
2474
+ }
2475
+ children.push(marker);
2476
+ }
2477
+ break;
2478
+ }
2479
+ case "customXmlInsRangeStart":
2480
+ case "customXmlInsRangeEnd":
2481
+ case "customXmlDelRangeStart":
2482
+ case "customXmlDelRangeEnd":
2483
+ case "customXmlMoveFromRangeStart":
2484
+ case "customXmlMoveFromRangeEnd":
2485
+ case "customXmlMoveToRangeStart":
2486
+ case "customXmlMoveToRangeEnd": {
2487
+ const id = attrInt(resolved, "id");
2488
+ if (id !== undefined) {
2489
+ const marker = { type: name, id };
2490
+ const author = attrVal(resolved, "author");
2491
+ if (author) {
2492
+ marker.author = author;
2493
+ }
2494
+ const date = attrVal(resolved, "date");
2495
+ if (date) {
2496
+ marker.date = date;
2497
+ }
2498
+ children.push(marker);
2499
+ }
2500
+ break;
2501
+ }
2502
+ case "smartTag":
2503
+ case "customXml":
2504
+ case "dir": {
2505
+ // Semantic wrappers: flatten their children into the current paragraph.
2506
+ // A smartTag/customXml/dir can contain runs, hyperlinks, nested wrappers, etc.
2507
+ // Re-use parseParagraph to recursively parse the contained children.
2508
+ const subPara = parseParagraph(resolved);
2509
+ for (const sub of subPara.children) {
2510
+ children.push(sub);
2511
+ }
2512
+ break;
2513
+ }
2514
+ case "proofErr":
2515
+ case "permStart":
2516
+ case "permEnd":
2517
+ case "lastRenderedPageBreak":
2518
+ // Non-semantic markers; safely ignored
2519
+ break;
2520
+ }
2521
+ }
2522
+ const paraId = pEl.attributes["w14:paraId"];
2523
+ const textId = pEl.attributes["w14:textId"];
2524
+ const result = {
2525
+ type: "paragraph",
2526
+ properties: pPrEl ? parseParagraphProperties(pPrEl) : undefined,
2527
+ children
2528
+ };
2529
+ if (paraId) {
2530
+ result.paraId = paraId;
2531
+ }
2532
+ if (textId) {
2533
+ result.textId = textId;
2534
+ }
2535
+ return result;
2536
+ }
2537
+ /** Parse a deleted run (w:delText instead of w:t). */
2538
+ function parseDeletedRun(el) {
2539
+ const rPrEl = findChildNs(el, "rPr");
2540
+ const content = [];
2541
+ for (const child of el.children) {
2542
+ if (child.type !== "element") {
2543
+ continue;
2544
+ }
2545
+ const name = child.name.replace(/^w:/, "");
2546
+ if (name === "delText") {
2547
+ content.push({ type: "text", text: (0, dom_1.textContent)(child) });
2548
+ }
2549
+ else if (name === "t") {
2550
+ content.push({ type: "text", text: (0, dom_1.textContent)(child) });
2551
+ }
2552
+ else if (name === "br") {
2553
+ content.push({ type: "break", breakType: attrVal(child, "type") });
2554
+ }
2555
+ else if (name === "tab") {
2556
+ content.push({ type: "tab" });
2557
+ }
2558
+ }
2559
+ return {
2560
+ properties: rPrEl ? parseRunProperties(rPrEl) : undefined,
2561
+ content
2562
+ };
2563
+ }
2564
+ // =============================================================================
2565
+ // Table Parser
2566
+ // =============================================================================
2567
+ function parseTableBorders(el) {
2568
+ const borders = {};
2569
+ for (const side of [
2570
+ "top",
2571
+ "left",
2572
+ "bottom",
2573
+ "right",
2574
+ "insideH",
2575
+ "insideV",
2576
+ "start",
2577
+ "end",
2578
+ "tl2br",
2579
+ "tr2bl"
2580
+ ]) {
2581
+ const sideEl = findChildNs(el, side);
2582
+ if (sideEl) {
2583
+ borders[side] = parseBorder(sideEl);
2584
+ }
2585
+ }
2586
+ return borders;
2587
+ }
2588
+ function parseTableCellMargins(el) {
2589
+ const margins = {};
2590
+ for (const side of ["top", "left", "bottom", "right", "start", "end"]) {
2591
+ const sideEl = findChildNs(el, side);
2592
+ if (sideEl) {
2593
+ margins[side] = parseTableWidth(sideEl);
2594
+ }
2595
+ }
2596
+ return margins;
2597
+ }
2598
+ function parseTableProperties(el) {
2599
+ const props = {};
2600
+ const styleEl = findChildNs(el, "tblStyle");
2601
+ if (styleEl) {
2602
+ props.style = attrVal(styleEl, "val");
2603
+ }
2604
+ const wEl = findChildNs(el, "tblW");
2605
+ if (wEl) {
2606
+ props.width = parseTableWidth(wEl);
2607
+ }
2608
+ const jcEl = findChildNs(el, "jc");
2609
+ if (jcEl) {
2610
+ props.alignment = attrVal(jcEl, "val");
2611
+ }
2612
+ const indEl = findChildNs(el, "tblInd");
2613
+ if (indEl) {
2614
+ props.indent = parseInt(indEl.attributes["w:w"] ?? indEl.attributes["w"] ?? "0", 10);
2615
+ }
2616
+ const bordersEl = findChildNs(el, "tblBorders");
2617
+ if (bordersEl) {
2618
+ props.borders = parseTableBorders(bordersEl);
2619
+ }
2620
+ const layoutEl = findChildNs(el, "tblLayout");
2621
+ if (layoutEl) {
2622
+ props.layout = attrVal(layoutEl, "type");
2623
+ }
2624
+ const cellMarEl = findChildNs(el, "tblCellMar");
2625
+ if (cellMarEl) {
2626
+ props.cellMargins = parseTableCellMargins(cellMarEl);
2627
+ }
2628
+ // TableLook
2629
+ const lookEl = findChildNs(el, "tblLook");
2630
+ if (lookEl) {
2631
+ const look = {};
2632
+ // Read individual attributes first (authoritative when explicit "0"/"1")
2633
+ const readFlag = (name) => {
2634
+ const v = attrVal(lookEl, name);
2635
+ if (v === "1" || v === "true") {
2636
+ return true;
2637
+ }
2638
+ if (v === "0" || v === "false") {
2639
+ return false;
2640
+ }
2641
+ return undefined;
2642
+ };
2643
+ const firstRow = readFlag("firstRow");
2644
+ const lastRow = readFlag("lastRow");
2645
+ const firstColumn = readFlag("firstColumn");
2646
+ const lastColumn = readFlag("lastColumn");
2647
+ const noHBand = readFlag("noHBand");
2648
+ const noVBand = readFlag("noVBand");
2649
+ if (firstRow !== undefined) {
2650
+ look.firstRow = firstRow;
2651
+ }
2652
+ if (lastRow !== undefined) {
2653
+ look.lastRow = lastRow;
2654
+ }
2655
+ if (firstColumn !== undefined) {
2656
+ look.firstColumn = firstColumn;
2657
+ }
2658
+ if (lastColumn !== undefined) {
2659
+ look.lastColumn = lastColumn;
2660
+ }
2661
+ if (noHBand !== undefined) {
2662
+ look.noHBand = noHBand;
2663
+ }
2664
+ if (noVBand !== undefined) {
2665
+ look.noVBand = noVBand;
2666
+ }
2667
+ // Fall back to w:val bitmask ONLY if no individual attrs were specified
2668
+ if (Object.keys(look).length === 0) {
2669
+ const val = attrVal(lookEl, "val");
2670
+ if (val) {
2671
+ const v = parseInt(val, 16);
2672
+ if (v & 0x0020) {
2673
+ look.firstRow = true;
2674
+ }
2675
+ if (v & 0x0040) {
2676
+ look.lastRow = true;
2677
+ }
2678
+ if (v & 0x0080) {
2679
+ look.firstColumn = true;
2680
+ }
2681
+ if (v & 0x0100) {
2682
+ look.lastColumn = true;
2683
+ }
2684
+ if (v & 0x0200) {
2685
+ look.noHBand = true;
2686
+ }
2687
+ if (v & 0x0400) {
2688
+ look.noVBand = true;
2689
+ }
2690
+ }
2691
+ }
2692
+ if (Object.keys(look).length > 0) {
2693
+ props.look = look;
2694
+ }
2695
+ }
2696
+ // TableFloat
2697
+ const tblpPrEl = findChildNs(el, "tblpPr");
2698
+ if (tblpPrEl) {
2699
+ const tf = {};
2700
+ const f = tf;
2701
+ const hAnchor = attrVal(tblpPrEl, "horzAnchor");
2702
+ if (hAnchor) {
2703
+ f.horizontalAnchor = hAnchor;
2704
+ }
2705
+ const vAnchor = attrVal(tblpPrEl, "vertAnchor");
2706
+ if (vAnchor) {
2707
+ f.verticalAnchor = vAnchor;
2708
+ }
2709
+ const tblpX = attrInt(tblpPrEl, "tblpX");
2710
+ if (tblpX !== undefined) {
2711
+ f.absoluteHorizontalPosition = tblpX;
2712
+ }
2713
+ const tblpY = attrInt(tblpPrEl, "tblpY");
2714
+ if (tblpY !== undefined) {
2715
+ f.absoluteVerticalPosition = tblpY;
2716
+ }
2717
+ const tblpXSpec = attrVal(tblpPrEl, "tblpXSpec");
2718
+ if (tblpXSpec) {
2719
+ f.relativeHorizontalPosition = tblpXSpec;
2720
+ }
2721
+ const tblpYSpec = attrVal(tblpPrEl, "tblpYSpec");
2722
+ if (tblpYSpec) {
2723
+ f.relativeVerticalPosition = tblpYSpec;
2724
+ }
2725
+ const topFromText = attrInt(tblpPrEl, "topFromText");
2726
+ if (topFromText !== undefined) {
2727
+ f.topFromText = topFromText;
2728
+ }
2729
+ const bottomFromText = attrInt(tblpPrEl, "bottomFromText");
2730
+ if (bottomFromText !== undefined) {
2731
+ f.bottomFromText = bottomFromText;
2732
+ }
2733
+ const leftFromText = attrInt(tblpPrEl, "leftFromText");
2734
+ if (leftFromText !== undefined) {
2735
+ f.leftFromText = leftFromText;
2736
+ }
2737
+ const rightFromText = attrInt(tblpPrEl, "rightFromText");
2738
+ if (rightFromText !== undefined) {
2739
+ f.rightFromText = rightFromText;
2740
+ }
2741
+ const overlap = attrVal(tblpPrEl, "overlap");
2742
+ if (overlap) {
2743
+ f.overlap = overlap;
2744
+ }
2745
+ props.float = tf;
2746
+ }
2747
+ // w:tblOverlap is a separate sibling element of w:tblpPr (value "never"|"overlap")
2748
+ const tblOverlapEl = findChildNs(el, "tblOverlap");
2749
+ if (tblOverlapEl && props.float) {
2750
+ const v = attrVal(tblOverlapEl, "val");
2751
+ if (v === "never" || v === "overlap") {
2752
+ props.float.overlap = v;
2753
+ }
2754
+ }
2755
+ // Cell spacing
2756
+ const csEl = findChildNs(el, "tblCellSpacing");
2757
+ if (csEl) {
2758
+ props.cellSpacing = parseTableWidth(csEl);
2759
+ }
2760
+ // Bidi visual
2761
+ if (findChildNs(el, "bidiVisual")) {
2762
+ props.visuallyRightToLeft = true;
2763
+ }
2764
+ // Shading
2765
+ const shdEl = findChildNs(el, "shd");
2766
+ if (shdEl) {
2767
+ props.shading = parseShading(shdEl);
2768
+ }
2769
+ // Accessibility: caption and description
2770
+ const captionEl = findChildNs(el, "tblCaption");
2771
+ if (captionEl) {
2772
+ props.caption = attrVal(captionEl, "val");
2773
+ }
2774
+ const descEl = findChildNs(el, "tblDescription");
2775
+ if (descEl) {
2776
+ props.description = attrVal(descEl, "val");
2777
+ }
2778
+ // Table property change
2779
+ const tblPrChangeEl = findChildNs(el, "tblPrChange");
2780
+ if (tblPrChangeEl) {
2781
+ const rev = parseRevisionInfo(tblPrChangeEl);
2782
+ if (rev) {
2783
+ const prev = findChildNs(tblPrChangeEl, "tblPr");
2784
+ props.propertyChange = {
2785
+ revision: rev,
2786
+ previousProperties: prev ? parseTableProperties(prev) : undefined
2787
+ };
2788
+ }
2789
+ }
2790
+ return props;
2791
+ }
2792
+ function parseTableCell(el) {
2793
+ const tcPrEl = findChildNs(el, "tcPr");
2794
+ const content = [];
2795
+ for (const child of el.children) {
2796
+ if (child.type !== "element") {
2797
+ continue;
2798
+ }
2799
+ const name = child.name.replace(/^w:/, "");
2800
+ if (name === "p") {
2801
+ content.push(parseParagraph(child));
2802
+ }
2803
+ else if (name === "tbl") {
2804
+ content.push(parseTable(child));
2805
+ }
2806
+ }
2807
+ let props;
2808
+ if (tcPrEl) {
2809
+ const p = {};
2810
+ const wEl = findChildNs(tcPrEl, "tcW");
2811
+ if (wEl) {
2812
+ p.width = parseTableWidth(wEl);
2813
+ }
2814
+ const gsEl = findChildNs(tcPrEl, "gridSpan");
2815
+ if (gsEl) {
2816
+ p.gridSpan = attrInt(gsEl, "val");
2817
+ }
2818
+ const vmEl = findChildNs(tcPrEl, "vMerge");
2819
+ if (vmEl) {
2820
+ p.verticalMerge = attrVal(vmEl, "val") ?? "continue";
2821
+ }
2822
+ const bordersEl = findChildNs(tcPrEl, "tcBorders");
2823
+ if (bordersEl) {
2824
+ p.borders = parseTableBorders(bordersEl);
2825
+ }
2826
+ const shdEl = findChildNs(tcPrEl, "shd");
2827
+ if (shdEl) {
2828
+ p.shading = parseShading(shdEl);
2829
+ }
2830
+ const vAlignEl = findChildNs(tcPrEl, "vAlign");
2831
+ if (vAlignEl) {
2832
+ p.verticalAlign = attrVal(vAlignEl, "val");
2833
+ }
2834
+ if (findChildNs(tcPrEl, "noWrap")) {
2835
+ p.noWrap = true;
2836
+ }
2837
+ const textDirEl = findChildNs(tcPrEl, "textDirection");
2838
+ if (textDirEl) {
2839
+ p.textDirection = attrVal(textDirEl, "val");
2840
+ }
2841
+ const marginsEl = findChildNs(tcPrEl, "tcMar");
2842
+ if (marginsEl) {
2843
+ p.margins = parseTableCellMargins(marginsEl);
2844
+ }
2845
+ // Conditional formatting
2846
+ const cnfEl = findChildNs(tcPrEl, "cnfStyle");
2847
+ if (cnfEl) {
2848
+ p.cnfStyle = attrVal(cnfEl, "val");
2849
+ }
2850
+ // Hide cell end-of-cell marker
2851
+ if (findChildNs(tcPrEl, "hideMark")) {
2852
+ p.hideMark = true;
2853
+ }
2854
+ // Fit text
2855
+ if (findChildNs(tcPrEl, "tcFitText")) {
2856
+ p.fitText = true;
2857
+ }
2858
+ // Cell-level revisions
2859
+ const cellInsEl = findChildNs(tcPrEl, "cellIns");
2860
+ if (cellInsEl) {
2861
+ const rev = parseRevisionInfo(cellInsEl);
2862
+ if (rev) {
2863
+ p.inserted = { revision: rev };
2864
+ }
2865
+ }
2866
+ const cellDelEl = findChildNs(tcPrEl, "cellDel");
2867
+ if (cellDelEl) {
2868
+ const rev = parseRevisionInfo(cellDelEl);
2869
+ if (rev) {
2870
+ p.deleted = { revision: rev };
2871
+ }
2872
+ }
2873
+ const cellMergeEl = findChildNs(tcPrEl, "cellMerge");
2874
+ if (cellMergeEl) {
2875
+ const vMerge = attrVal(cellMergeEl, "vMerge");
2876
+ const rev = parseRevisionInfo(cellMergeEl);
2877
+ if (rev && (vMerge === "cont" || vMerge === "rest")) {
2878
+ p.cellMerge = { vMerge, revision: rev };
2879
+ }
2880
+ }
2881
+ // tcPrChange
2882
+ const tcPrChangeEl = findChildNs(tcPrEl, "tcPrChange");
2883
+ if (tcPrChangeEl) {
2884
+ const rev = parseRevisionInfo(tcPrChangeEl);
2885
+ if (rev) {
2886
+ const prev = findChildNs(tcPrChangeEl, "tcPr");
2887
+ p.propertyChange = { revision: rev };
2888
+ if (prev) {
2889
+ // Minimal: previousProperties won't recurse (avoid infinite recursion).
2890
+ // Just capture the presence of the change marker here.
2891
+ }
2892
+ }
2893
+ }
2894
+ props = p;
2895
+ }
2896
+ return { properties: props, content };
2897
+ }
2898
+ function parseTableRow(el) {
2899
+ const trPrEl = findChildNs(el, "trPr");
2900
+ const tblPrExEl = findChildNs(el, "tblPrEx");
2901
+ const cells = [];
2902
+ for (const child of el.children) {
2903
+ if (child.type === "element" && child.name.replace(/^w:/, "") === "tc") {
2904
+ cells.push(parseTableCell(child));
2905
+ }
2906
+ }
2907
+ let props;
2908
+ if (trPrEl || tblPrExEl) {
2909
+ const p = {};
2910
+ if (tblPrExEl) {
2911
+ p.tblPrEx = parseTableProperties(tblPrExEl);
2912
+ }
2913
+ if (trPrEl) {
2914
+ const heightEl = findChildNs(trPrEl, "trHeight");
2915
+ if (heightEl) {
2916
+ p.height = {
2917
+ value: attrInt(heightEl, "val") ?? 0,
2918
+ rule: attrVal(heightEl, "hRule")
2919
+ };
2920
+ }
2921
+ if (findChildNs(trPrEl, "tblHeader")) {
2922
+ p.tableHeader = true;
2923
+ }
2924
+ if (findChildNs(trPrEl, "cantSplit")) {
2925
+ p.cantSplit = true;
2926
+ }
2927
+ if (findChildNs(trPrEl, "hidden")) {
2928
+ p.hidden = true;
2929
+ }
2930
+ const csEl = findChildNs(trPrEl, "tblCellSpacing");
2931
+ if (csEl) {
2932
+ p.cellSpacing = parseTableWidth(csEl);
2933
+ }
2934
+ const insEl = findChildNs(trPrEl, "ins");
2935
+ if (insEl) {
2936
+ const rev = parseRevisionInfo(insEl);
2937
+ if (rev) {
2938
+ p.inserted = { revision: rev };
2939
+ }
2940
+ }
2941
+ const delEl = findChildNs(trPrEl, "del");
2942
+ if (delEl) {
2943
+ const rev = parseRevisionInfo(delEl);
2944
+ if (rev) {
2945
+ p.deleted = { revision: rev };
2946
+ }
2947
+ }
2948
+ const gbEl = findChildNs(trPrEl, "gridBefore");
2949
+ if (gbEl) {
2950
+ p.gridBefore = attrInt(gbEl, "val");
2951
+ }
2952
+ const gaEl = findChildNs(trPrEl, "gridAfter");
2953
+ if (gaEl) {
2954
+ p.gridAfter = attrInt(gaEl, "val");
2955
+ }
2956
+ const wbEl = findChildNs(trPrEl, "wBefore");
2957
+ if (wbEl) {
2958
+ p.widthBefore = parseTableWidth(wbEl);
2959
+ }
2960
+ const waEl = findChildNs(trPrEl, "wAfter");
2961
+ if (waEl) {
2962
+ p.widthAfter = parseTableWidth(waEl);
2963
+ }
2964
+ const cnfEl = findChildNs(trPrEl, "cnfStyle");
2965
+ if (cnfEl) {
2966
+ p.cnfStyle = attrVal(cnfEl, "val");
2967
+ }
2968
+ const trPrChangeEl = findChildNs(trPrEl, "trPrChange");
2969
+ if (trPrChangeEl) {
2970
+ const rev = parseRevisionInfo(trPrChangeEl);
2971
+ if (rev) {
2972
+ const prevTrPr = findChildNs(trPrChangeEl, "trPr");
2973
+ p.propertyChange = {
2974
+ revision: rev,
2975
+ previousProperties: prevTrPr ? parseRowPrInner(prevTrPr) : undefined
2976
+ };
2977
+ }
2978
+ }
2979
+ }
2980
+ props = p;
2981
+ }
2982
+ return { properties: props, cells };
2983
+ }
2984
+ /** Inner parse for row properties content (used by propertyChange recursion). */
2985
+ function parseRowPrInner(trPrEl) {
2986
+ const p = {};
2987
+ const heightEl = findChildNs(trPrEl, "trHeight");
2988
+ if (heightEl) {
2989
+ p.height = { value: attrInt(heightEl, "val") ?? 0, rule: attrVal(heightEl, "hRule") };
2990
+ }
2991
+ if (findChildNs(trPrEl, "tblHeader")) {
2992
+ p.tableHeader = true;
2993
+ }
2994
+ if (findChildNs(trPrEl, "cantSplit")) {
2995
+ p.cantSplit = true;
2996
+ }
2997
+ return p;
2998
+ }
2999
+ function parseTable(tblEl) {
3000
+ const tblPrEl = findChildNs(tblEl, "tblPr");
3001
+ const gridEl = findChildNs(tblEl, "tblGrid");
3002
+ const rows = [];
3003
+ for (const child of tblEl.children) {
3004
+ if (child.type === "element" && child.name.replace(/^w:/, "") === "tr") {
3005
+ rows.push(parseTableRow(child));
3006
+ }
3007
+ }
3008
+ let columnWidths;
3009
+ if (gridEl) {
3010
+ columnWidths = [];
3011
+ for (const col of findChildrenNs(gridEl, "gridCol")) {
3012
+ columnWidths.push(parseInt(col.attributes["w:w"] ?? col.attributes["w"] ?? "0", 10));
3013
+ }
3014
+ }
3015
+ return {
3016
+ type: "table",
3017
+ properties: tblPrEl ? parseTableProperties(tblPrEl) : undefined,
3018
+ columnWidths,
3019
+ rows
3020
+ };
3021
+ }
3022
+ // =============================================================================
3023
+ // Section Properties Parser
3024
+ // =============================================================================
3025
+ function parseSectionProperties(sectPrEl) {
3026
+ const sect = {};
3027
+ const pgSzEl = findChildNs(sectPrEl, "pgSz");
3028
+ if (pgSzEl) {
3029
+ // Per ECMA-376, w:orient defaults to "portrait" when absent
3030
+ const orient = attrVal(pgSzEl, "orient");
3031
+ sect.pageSize = {
3032
+ width: attrInt(pgSzEl, "w"),
3033
+ height: attrInt(pgSzEl, "h"),
3034
+ orientation: (orient === "landscape" ? "landscape" : "portrait")
3035
+ };
3036
+ }
3037
+ const pgMarEl = findChildNs(sectPrEl, "pgMar");
3038
+ if (pgMarEl) {
3039
+ sect.margins = {
3040
+ top: attrInt(pgMarEl, "top"),
3041
+ right: attrInt(pgMarEl, "right"),
3042
+ bottom: attrInt(pgMarEl, "bottom"),
3043
+ left: attrInt(pgMarEl, "left"),
3044
+ header: attrInt(pgMarEl, "header"),
3045
+ footer: attrInt(pgMarEl, "footer"),
3046
+ gutter: attrInt(pgMarEl, "gutter")
3047
+ };
3048
+ }
3049
+ const typeEl = findChildNs(sectPrEl, "type");
3050
+ if (typeEl) {
3051
+ sect.breakType = attrVal(typeEl, "val");
3052
+ }
3053
+ const colsEl = findChildNs(sectPrEl, "cols");
3054
+ if (colsEl) {
3055
+ const cols = {};
3056
+ cols.space = attrInt(colsEl, "space");
3057
+ cols.count = attrInt(colsEl, "num");
3058
+ const eqw = attrVal(colsEl, "equalWidth");
3059
+ if (eqw !== undefined) {
3060
+ cols.equalWidth = eqw === "1";
3061
+ }
3062
+ const sep = attrVal(colsEl, "sep");
3063
+ if (sep === "1" || sep === "true") {
3064
+ cols.separator = true;
3065
+ }
3066
+ const colDefs = findChildrenNs(colsEl, "col");
3067
+ if (colDefs.length > 0) {
3068
+ cols.columns = colDefs.map(c => ({
3069
+ width: attrInt(c, "w") ?? 0,
3070
+ space: attrInt(c, "space")
3071
+ }));
3072
+ }
3073
+ sect.columns = cols;
3074
+ }
3075
+ if (findChildNs(sectPrEl, "titlePg")) {
3076
+ sect.titlePage = true;
3077
+ }
3078
+ const pgNumEl = findChildNs(sectPrEl, "pgNumType");
3079
+ if (pgNumEl) {
3080
+ sect.pageNumbering = {
3081
+ start: attrInt(pgNumEl, "start"),
3082
+ format: attrVal(pgNumEl, "fmt")
3083
+ };
3084
+ }
3085
+ // Page borders
3086
+ const pgBordersEl = findChildNs(sectPrEl, "pgBorders");
3087
+ if (pgBordersEl) {
3088
+ const pb = {};
3089
+ const p = pb;
3090
+ for (const side of ["top", "left", "bottom", "right"]) {
3091
+ const sideEl = findChildNs(pgBordersEl, side);
3092
+ if (sideEl) {
3093
+ p[side] = parseBorder(sideEl);
3094
+ }
3095
+ }
3096
+ const display = attrVal(pgBordersEl, "display");
3097
+ if (display) {
3098
+ p.display = display;
3099
+ }
3100
+ const offsetFrom = attrVal(pgBordersEl, "offsetFrom");
3101
+ if (offsetFrom) {
3102
+ p.offsetFrom = offsetFrom;
3103
+ }
3104
+ const zOrder = attrVal(pgBordersEl, "zOrder");
3105
+ if (zOrder) {
3106
+ p.zOrder = zOrder;
3107
+ }
3108
+ sect.pageBorders = pb;
3109
+ }
3110
+ // Vertical alignment
3111
+ const vAlignEl = findChildNs(sectPrEl, "vAlign");
3112
+ if (vAlignEl) {
3113
+ sect.verticalAlign = attrVal(vAlignEl, "val");
3114
+ }
3115
+ // Text direction
3116
+ const textDirEl = findChildNs(sectPrEl, "textDirection");
3117
+ if (textDirEl) {
3118
+ sect.textDirection = attrVal(textDirEl, "val");
3119
+ }
3120
+ // Bidi
3121
+ const bidiToggle = boolToggle(sectPrEl, "bidi");
3122
+ if (bidiToggle !== undefined) {
3123
+ sect.bidi = bidiToggle;
3124
+ }
3125
+ // RTL gutter
3126
+ const rtlGutterEl = findChildNs(sectPrEl, "rtlGutter");
3127
+ if (rtlGutterEl) {
3128
+ sect.rtlGutter = true;
3129
+ }
3130
+ // Form protection
3131
+ const formProtEl = findChildNs(sectPrEl, "formProt");
3132
+ if (formProtEl) {
3133
+ const v = attrVal(formProtEl, "val");
3134
+ sect.formProtection = v === "1" || v === "true";
3135
+ }
3136
+ // Document grid
3137
+ const docGridEl = findChildNs(sectPrEl, "docGrid");
3138
+ if (docGridEl) {
3139
+ const dg = {};
3140
+ const linePitch = attrInt(docGridEl, "linePitch");
3141
+ if (linePitch !== undefined) {
3142
+ dg.linePitch = linePitch;
3143
+ }
3144
+ const charSpace = attrInt(docGridEl, "charSpace");
3145
+ if (charSpace !== undefined) {
3146
+ dg.charSpace = charSpace;
3147
+ }
3148
+ const gridType = attrVal(docGridEl, "type");
3149
+ if (gridType) {
3150
+ dg.type = gridType;
3151
+ }
3152
+ sect.docGrid = dg;
3153
+ }
3154
+ // Line numbers
3155
+ const lnNumEl = findChildNs(sectPrEl, "lnNumType");
3156
+ if (lnNumEl) {
3157
+ const ln = {};
3158
+ const countBy = attrInt(lnNumEl, "countBy");
3159
+ if (countBy !== undefined) {
3160
+ ln.countBy = countBy;
3161
+ }
3162
+ const start = attrInt(lnNumEl, "start");
3163
+ if (start !== undefined) {
3164
+ ln.start = start;
3165
+ }
3166
+ const restart = attrVal(lnNumEl, "restart");
3167
+ if (restart) {
3168
+ ln.restart = restart;
3169
+ }
3170
+ const distance = attrInt(lnNumEl, "distance");
3171
+ if (distance !== undefined) {
3172
+ ln.distance = distance;
3173
+ }
3174
+ sect.lineNumbers = ln;
3175
+ }
3176
+ // Footnote properties
3177
+ const fnPrEl = findChildNs(sectPrEl, "footnotePr");
3178
+ if (fnPrEl) {
3179
+ sect.footnoteProperties = parseNoteProperties(fnPrEl);
3180
+ }
3181
+ // Endnote properties
3182
+ const enPrEl = findChildNs(sectPrEl, "endnotePr");
3183
+ if (enPrEl) {
3184
+ sect.endnoteProperties = parseNoteProperties(enPrEl);
3185
+ }
3186
+ // Headers/Footers refs
3187
+ const headerRefs = [];
3188
+ for (const hRef of findChildrenNs(sectPrEl, "headerReference")) {
3189
+ headerRefs.push({
3190
+ type: (attrVal(hRef, "type") ?? "default"),
3191
+ rId: hRef.attributes["r:id"] ?? ""
3192
+ });
3193
+ }
3194
+ if (headerRefs.length > 0) {
3195
+ sect.headers = headerRefs;
3196
+ }
3197
+ const footerRefs = [];
3198
+ for (const fRef of findChildrenNs(sectPrEl, "footerReference")) {
3199
+ footerRefs.push({
3200
+ type: (attrVal(fRef, "type") ?? "default"),
3201
+ rId: fRef.attributes["r:id"] ?? ""
3202
+ });
3203
+ }
3204
+ if (footerRefs.length > 0) {
3205
+ sect.footers = footerRefs;
3206
+ }
3207
+ // sectPrChange (track changes for section properties)
3208
+ const sectPrChangeEl = findChildNs(sectPrEl, "sectPrChange");
3209
+ if (sectPrChangeEl) {
3210
+ const rev = parseRevisionInfo(sectPrChangeEl);
3211
+ if (rev) {
3212
+ const prevSectPrEl = findChildNs(sectPrChangeEl, "sectPr");
3213
+ const change = {
3214
+ revision: rev,
3215
+ previousProperties: prevSectPrEl ? parseSectionProperties(prevSectPrEl) : undefined
3216
+ };
3217
+ sect.propertyChange = change;
3218
+ }
3219
+ }
3220
+ return sect;
3221
+ }
3222
+ // =============================================================================
3223
+ // Styles Parser
3224
+ // =============================================================================
3225
+ function parseStyles(xmlStr) {
3226
+ const doc = (0, dom_1.parseXml)(xmlStr);
3227
+ const root = doc.root;
3228
+ let docDefaults;
3229
+ const styles = [];
3230
+ const ddEl = findChildNs(root, "docDefaults");
3231
+ if (ddEl) {
3232
+ const dd = {};
3233
+ const rPrDefaultEl = findChildNs(ddEl, "rPrDefault");
3234
+ if (rPrDefaultEl) {
3235
+ const rPrEl = findChildNs(rPrDefaultEl, "rPr");
3236
+ if (rPrEl) {
3237
+ dd.runProperties = parseRunProperties(rPrEl);
3238
+ }
3239
+ }
3240
+ const pPrDefaultEl = findChildNs(ddEl, "pPrDefault");
3241
+ if (pPrDefaultEl) {
3242
+ const pPrEl = findChildNs(pPrDefaultEl, "pPr");
3243
+ if (pPrEl) {
3244
+ dd.paragraphProperties = parseParagraphProperties(pPrEl);
3245
+ }
3246
+ }
3247
+ docDefaults = dd;
3248
+ }
3249
+ for (const styleEl of findChildrenNs(root, "style")) {
3250
+ const s = {};
3251
+ s.type = attrVal(styleEl, "type");
3252
+ s.styleId = attrVal(styleEl, "styleId");
3253
+ s.isDefault = attrVal(styleEl, "default") === "1";
3254
+ if (attrVal(styleEl, "customStyle") === "1") {
3255
+ s.customStyle = true;
3256
+ }
3257
+ const nameEl = findChildNs(styleEl, "name");
3258
+ s.name = nameEl ? (attrVal(nameEl, "val") ?? "") : "";
3259
+ const basedOnEl = findChildNs(styleEl, "basedOn");
3260
+ if (basedOnEl) {
3261
+ s.basedOn = attrVal(basedOnEl, "val");
3262
+ }
3263
+ const nextEl = findChildNs(styleEl, "next");
3264
+ if (nextEl) {
3265
+ s.next = attrVal(nextEl, "val");
3266
+ }
3267
+ const linkEl = findChildNs(styleEl, "link");
3268
+ if (linkEl) {
3269
+ s.link = attrVal(linkEl, "val");
3270
+ }
3271
+ const uiPrEl = findChildNs(styleEl, "uiPriority");
3272
+ if (uiPrEl) {
3273
+ s.uiPriority = attrInt(uiPrEl, "val");
3274
+ }
3275
+ if (findChildNs(styleEl, "qFormat")) {
3276
+ s.qFormat = true;
3277
+ }
3278
+ if (findChildNs(styleEl, "semiHidden")) {
3279
+ s.semiHidden = true;
3280
+ }
3281
+ if (findChildNs(styleEl, "unhideWhenUsed")) {
3282
+ s.unhideWhenUsed = true;
3283
+ }
3284
+ if (findChildNs(styleEl, "hidden")) {
3285
+ s.hidden = true;
3286
+ }
3287
+ if (findChildNs(styleEl, "locked")) {
3288
+ s.locked = true;
3289
+ }
3290
+ if (findChildNs(styleEl, "autoRedefine")) {
3291
+ s.autoRedefine = true;
3292
+ }
3293
+ const pPrEl = findChildNs(styleEl, "pPr");
3294
+ if (pPrEl) {
3295
+ s.paragraphProperties = parseParagraphProperties(pPrEl);
3296
+ }
3297
+ const rPrEl = findChildNs(styleEl, "rPr");
3298
+ if (rPrEl) {
3299
+ s.runProperties = parseRunProperties(rPrEl);
3300
+ }
3301
+ // Table properties for table styles
3302
+ const tblPrEl = findChildNs(styleEl, "tblPr");
3303
+ if (tblPrEl) {
3304
+ s.tableProperties = parseTableProperties(tblPrEl);
3305
+ }
3306
+ // Table style conditional formats
3307
+ const tblStylePrs = findChildrenNs(styleEl, "tblStylePr");
3308
+ if (tblStylePrs.length > 0) {
3309
+ const conditions = [];
3310
+ for (const tsp of tblStylePrs) {
3311
+ const cond = { type: attrVal(tsp, "type") };
3312
+ const cpPr = findChildNs(tsp, "pPr");
3313
+ if (cpPr) {
3314
+ cond.paragraphProperties = parseParagraphProperties(cpPr);
3315
+ }
3316
+ const crPr = findChildNs(tsp, "rPr");
3317
+ if (crPr) {
3318
+ cond.runProperties = parseRunProperties(crPr);
3319
+ }
3320
+ const ctblPr = findChildNs(tsp, "tblPr");
3321
+ if (ctblPr) {
3322
+ cond.tableProperties = parseTableProperties(ctblPr);
3323
+ }
3324
+ const ctrPr = findChildNs(tsp, "trPr");
3325
+ if (ctrPr) {
3326
+ const rp = {};
3327
+ const hEl = findChildNs(ctrPr, "trHeight");
3328
+ if (hEl) {
3329
+ rp.height = { value: attrInt(hEl, "val") ?? 0, rule: attrVal(hEl, "hRule") };
3330
+ }
3331
+ cond.rowProperties = rp;
3332
+ }
3333
+ const ctcPr = findChildNs(tsp, "tcPr");
3334
+ if (ctcPr) {
3335
+ const cp = {};
3336
+ const bEl = findChildNs(ctcPr, "tcBorders");
3337
+ if (bEl) {
3338
+ cp.borders = parseTableBorders(bEl);
3339
+ }
3340
+ const shd = findChildNs(ctcPr, "shd");
3341
+ if (shd) {
3342
+ cp.shading = parseShading(shd);
3343
+ }
3344
+ cond.cellProperties = cp;
3345
+ }
3346
+ conditions.push(cond);
3347
+ }
3348
+ s.tableStyleConditions = conditions;
3349
+ }
3350
+ styles.push(s);
3351
+ }
3352
+ return { docDefaults, styles };
3353
+ }
3354
+ // =============================================================================
3355
+ // Numbering Parser
3356
+ // =============================================================================
3357
+ function parseNumberingXml(xmlStr) {
3358
+ const doc = (0, dom_1.parseXml)(xmlStr);
3359
+ const root = doc.root;
3360
+ const abstractNums = [];
3361
+ const instances = [];
3362
+ const numPicBullets = [];
3363
+ // Parse picture bullets
3364
+ for (const pbEl of findChildrenNs(root, "numPicBullet")) {
3365
+ const id = attrInt(pbEl, "numPicBulletId");
3366
+ if (id === undefined) {
3367
+ continue;
3368
+ }
3369
+ const pb = { id };
3370
+ // Try to extract VML shape info
3371
+ const pictEl = findChildNs(pbEl, "pict");
3372
+ if (pictEl) {
3373
+ // Preserve raw VML for complete fidelity
3374
+ let rawVml = "";
3375
+ for (const child of pictEl.children) {
3376
+ if (child.type === "element") {
3377
+ rawVml += serializeElement(child);
3378
+ }
3379
+ }
3380
+ if (rawVml) {
3381
+ pb.rawVmlXml = rawVml;
3382
+ }
3383
+ // Extract rId from v:imagedata
3384
+ const shapeEl = (0, dom_1.findChild)(pictEl, "v:shape");
3385
+ if (shapeEl) {
3386
+ const imgDataEl = (0, dom_1.findChild)(shapeEl, "v:imagedata");
3387
+ if (imgDataEl) {
3388
+ const rId = imgDataEl.attributes["r:id"] ?? imgDataEl.attributes["r:pict"];
3389
+ if (rId) {
3390
+ pb.rId = rId;
3391
+ }
3392
+ }
3393
+ // Extract width/height from style
3394
+ const style = shapeEl.attributes["style"];
3395
+ if (style) {
3396
+ const wMatch = /width:([\d.]+)pt/i.exec(style);
3397
+ const hMatch = /height:([\d.]+)pt/i.exec(style);
3398
+ if (wMatch) {
3399
+ pb.width = Math.round(parseFloat(wMatch[1]) * 12700);
3400
+ }
3401
+ if (hMatch) {
3402
+ pb.height = Math.round(parseFloat(hMatch[1]) * 12700);
3403
+ }
3404
+ }
3405
+ }
3406
+ }
3407
+ numPicBullets.push(pb);
3408
+ }
3409
+ for (const absEl of findChildrenNs(root, "abstractNum")) {
3410
+ const levels = [];
3411
+ for (const lvlEl of findChildrenNs(absEl, "lvl")) {
3412
+ levels.push(parseLevel(lvlEl));
3413
+ }
3414
+ const abs = {
3415
+ abstractNumId: attrInt(absEl, "abstractNumId") ?? 0,
3416
+ levels
3417
+ };
3418
+ const mltEl = findChildNs(absEl, "multiLevelType");
3419
+ if (mltEl) {
3420
+ abs.multiLevelType = attrVal(mltEl, "val");
3421
+ }
3422
+ const numStyleLinkEl = findChildNs(absEl, "numStyleLink");
3423
+ if (numStyleLinkEl) {
3424
+ abs.numStyleLink = attrVal(numStyleLinkEl, "val");
3425
+ }
3426
+ const styleLinkEl = findChildNs(absEl, "styleLink");
3427
+ if (styleLinkEl) {
3428
+ abs.styleLink = attrVal(styleLinkEl, "val");
3429
+ }
3430
+ abstractNums.push(abs);
3431
+ }
3432
+ for (const numEl of findChildrenNs(root, "num")) {
3433
+ const absIdEl = findChildNs(numEl, "abstractNumId");
3434
+ const overrides = [];
3435
+ for (const ovEl of findChildrenNs(numEl, "lvlOverride")) {
3436
+ const ov = { level: attrInt(ovEl, "ilvl") ?? 0 };
3437
+ const startOvEl = findChildNs(ovEl, "startOverride");
3438
+ if (startOvEl) {
3439
+ ov.startOverride = attrInt(startOvEl, "val");
3440
+ }
3441
+ // Level def override: parse full level definition
3442
+ const lvlEl = findChildNs(ovEl, "lvl");
3443
+ if (lvlEl) {
3444
+ ov.levelDef = parseLevel(lvlEl);
3445
+ // Inherit level index from parent if not specified
3446
+ if (ov.levelDef.level === undefined) {
3447
+ ov.levelDef.level = ov.level;
3448
+ }
3449
+ }
3450
+ overrides.push(ov);
3451
+ }
3452
+ instances.push({
3453
+ numId: attrInt(numEl, "numId") ?? 0,
3454
+ abstractNumId: absIdEl ? (attrInt(absIdEl, "val") ?? 0) : 0,
3455
+ overrides: overrides.length > 0 ? overrides : undefined
3456
+ });
3457
+ }
3458
+ return { abstractNums, instances, numPicBullets };
3459
+ }
3460
+ /** Parse a w:lvl element into a NumberingLevel (shared by abstractNum and lvlOverride). */
3461
+ function parseLevel(lvlEl) {
3462
+ const level = { level: attrInt(lvlEl, "ilvl") ?? 0 };
3463
+ const startEl = findChildNs(lvlEl, "start");
3464
+ if (startEl) {
3465
+ level.start = attrInt(startEl, "val");
3466
+ }
3467
+ const fmtEl = findChildNs(lvlEl, "numFmt");
3468
+ if (fmtEl) {
3469
+ level.format = attrVal(fmtEl, "val");
3470
+ }
3471
+ const textEl = findChildNs(lvlEl, "lvlText");
3472
+ if (textEl) {
3473
+ level.text = attrVal(textEl, "val") ?? "";
3474
+ }
3475
+ const pStyleEl = findChildNs(lvlEl, "pStyle");
3476
+ if (pStyleEl) {
3477
+ level.paragraphStyle = attrVal(pStyleEl, "val");
3478
+ }
3479
+ const jcEl = findChildNs(lvlEl, "lvlJc");
3480
+ if (jcEl) {
3481
+ level.justification = attrVal(jcEl, "val");
3482
+ }
3483
+ const pPrEl = findChildNs(lvlEl, "pPr");
3484
+ if (pPrEl) {
3485
+ level.paragraphProperties = parseParagraphProperties(pPrEl);
3486
+ }
3487
+ const rPrEl = findChildNs(lvlEl, "rPr");
3488
+ if (rPrEl) {
3489
+ level.runProperties = parseRunProperties(rPrEl);
3490
+ }
3491
+ const suffEl = findChildNs(lvlEl, "suff");
3492
+ if (suffEl) {
3493
+ level.suffix = attrVal(suffEl, "val");
3494
+ }
3495
+ if (findChildNs(lvlEl, "isLgl")) {
3496
+ level.isLegalNumberingStyle = true;
3497
+ }
3498
+ const lvlRestartEl = findChildNs(lvlEl, "lvlRestart");
3499
+ if (lvlRestartEl) {
3500
+ level.restartAfterLevel = attrInt(lvlRestartEl, "val");
3501
+ }
3502
+ const picBulletEl = findChildNs(lvlEl, "lvlPicBulletId");
3503
+ if (picBulletEl) {
3504
+ level.picBulletId = attrInt(picBulletEl, "val");
3505
+ }
3506
+ return level;
3507
+ }
3508
+ // =============================================================================
3509
+ // Footnotes/Endnotes Parser
3510
+ // =============================================================================
3511
+ function parseNotesXml(xmlStr, elementName) {
3512
+ const doc = (0, dom_1.parseXml)(xmlStr);
3513
+ const root = doc.root;
3514
+ const notes = [];
3515
+ for (const noteEl of findChildrenNs(root, elementName)) {
3516
+ const id = attrInt(noteEl, "id");
3517
+ const type = attrVal(noteEl, "type");
3518
+ // Skip auto-generated separator entries (default IDs -1 and 0)
3519
+ // Real separators/continuationSeparators are regenerated by the writer.
3520
+ if (type === "separator" || type === "continuationSeparator") {
3521
+ continue;
3522
+ }
3523
+ if (id === undefined) {
3524
+ continue;
3525
+ }
3526
+ const content = [];
3527
+ for (const child of noteEl.children) {
3528
+ if (child.type === "element" && child.name.replace(/^w:/, "") === "p") {
3529
+ content.push(parseParagraph(child));
3530
+ }
3531
+ }
3532
+ const note = { id, content };
3533
+ if (type === "continuationNotice" || type === "normal") {
3534
+ note.type = type;
3535
+ }
3536
+ notes.push(note);
3537
+ }
3538
+ return notes;
3539
+ }
3540
+ // =============================================================================
3541
+ // Header/Footer Parser
3542
+ // =============================================================================
3543
+ function parseHeaderFooterXml(xmlStr) {
3544
+ return parseHeaderFooterRoot((0, dom_1.parseXml)(xmlStr).root);
3545
+ }
3546
+ function parseHeaderFooterRoot(root) {
3547
+ const children = [];
3548
+ for (const child of root.children) {
3549
+ if (child.type !== "element") {
3550
+ continue;
3551
+ }
3552
+ const name = child.name.replace(/^w:/, "");
3553
+ if (name === "p") {
3554
+ children.push(parseParagraph(child));
3555
+ }
3556
+ else if (name === "tbl") {
3557
+ children.push(parseTable(child));
3558
+ }
3559
+ }
3560
+ return { children };
3561
+ }
3562
+ /** Detect watermark from a header's parsed XML root element. */
3563
+ function detectWatermarkFromRoot(root) {
3564
+ // Look for VML shape with id containing "WaterMark"
3565
+ for (const pEl of root.children) {
3566
+ if (pEl.type !== "element") {
3567
+ continue;
3568
+ }
3569
+ for (const rEl of pEl.children) {
3570
+ if (rEl.type !== "element") {
3571
+ continue;
3572
+ }
3573
+ // Look for w:pict or w:r > w:pict
3574
+ const pictEls = [];
3575
+ const rName = rEl.name.replace(/^w:/, "");
3576
+ if (rName === "pict") {
3577
+ pictEls.push(rEl);
3578
+ }
3579
+ else if (rName === "r") {
3580
+ for (const rc of rEl.children) {
3581
+ if (rc.type === "element" && rc.name.replace(/^w:/, "") === "pict") {
3582
+ pictEls.push(rc);
3583
+ }
3584
+ }
3585
+ }
3586
+ for (const pictEl of pictEls) {
3587
+ for (const shapeEl of pictEl.children) {
3588
+ if (shapeEl.type !== "element") {
3589
+ continue;
3590
+ }
3591
+ const shapeId = shapeEl.attributes["id"] ?? "";
3592
+ if (!shapeId.toLowerCase().includes("watermark")) {
3593
+ continue;
3594
+ }
3595
+ // Found watermark shape
3596
+ const shapeType = shapeEl.attributes["type"] ?? "";
3597
+ if (shapeType.includes("136")) {
3598
+ // WordArt text watermark (shapetype 136)
3599
+ return parseTextWatermark(shapeEl);
3600
+ }
3601
+ // Check for image watermark (has v:imagedata)
3602
+ const imgData = (0, dom_1.findChild)(shapeEl, "v:imagedata");
3603
+ if (imgData) {
3604
+ return parseImageWatermark(shapeEl, imgData);
3605
+ }
3606
+ }
3607
+ }
3608
+ }
3609
+ }
3610
+ return undefined;
3611
+ }
3612
+ function parseTextWatermark(shapeEl) {
3613
+ const fillColor = shapeEl.attributes["fillcolor"] ?? "#C0C0C0";
3614
+ const color = fillColor.replace(/^#/, "");
3615
+ // Parse rotation from style
3616
+ const style = shapeEl.attributes["style"] ?? "";
3617
+ let rotation = -45;
3618
+ const rotMatch = style.match(/rotation:\s*(-?\d+)/);
3619
+ if (rotMatch) {
3620
+ rotation = parseInt(rotMatch[1], 10);
3621
+ }
3622
+ // Get opacity from v:fill
3623
+ const fillEl = (0, dom_1.findChild)(shapeEl, "v:fill");
3624
+ const opacity = fillEl?.attributes["opacity"] ?? ".5";
3625
+ const semiTransparent = opacity !== "1";
3626
+ // Get text and font from v:textpath
3627
+ const textpathEl = (0, dom_1.findChild)(shapeEl, "v:textpath");
3628
+ const text = textpathEl?.attributes["string"] ?? "";
3629
+ const tpStyle = textpathEl?.attributes["style"] ?? "";
3630
+ let font;
3631
+ let fontSize;
3632
+ const fontMatch = tpStyle.match(/font-family:\s*"?([^";]+)"?/);
3633
+ if (fontMatch) {
3634
+ font = fontMatch[1].replace(/&quot;/g, "");
3635
+ }
3636
+ const sizeMatch = tpStyle.match(/font-size:\s*(\d+(?:\.\d+)?)\s*pt/);
3637
+ if (sizeMatch) {
3638
+ fontSize = Math.round(parseFloat(sizeMatch[1]) * 2); // convert pt to half-points
3639
+ }
3640
+ return {
3641
+ type: "text",
3642
+ text,
3643
+ font,
3644
+ fontSize,
3645
+ color,
3646
+ semiTransparent,
3647
+ rotation
3648
+ };
3649
+ }
3650
+ function parseImageWatermark(shapeEl, imgDataEl) {
3651
+ const rId = imgDataEl.attributes["r:id"] ?? "";
3652
+ const gain = imgDataEl.attributes["gain"] ?? "";
3653
+ const washout = gain.startsWith("19661") || gain === "";
3654
+ return {
3655
+ type: "image",
3656
+ rId,
3657
+ washout
3658
+ };
3659
+ }
3660
+ // =============================================================================
3661
+ // Comments Parser
3662
+ // =============================================================================
3663
+ function parseCommentsXml(xmlStr) {
3664
+ const doc = (0, dom_1.parseXml)(xmlStr);
3665
+ const root = doc.root;
3666
+ const comments = [];
3667
+ for (const commentEl of findChildrenNs(root, "comment")) {
3668
+ const id = attrInt(commentEl, "id");
3669
+ const author = attrVal(commentEl, "author");
3670
+ if (id === undefined || !author) {
3671
+ continue;
3672
+ }
3673
+ const content = [];
3674
+ for (const child of commentEl.children) {
3675
+ if (child.type === "element" && child.name.replace(/^w:/, "") === "p") {
3676
+ content.push(parseParagraph(child));
3677
+ }
3678
+ }
3679
+ const comment = { id, author, content };
3680
+ const date = attrVal(commentEl, "date");
3681
+ if (date) {
3682
+ comment.date = date;
3683
+ }
3684
+ const initials = attrVal(commentEl, "initials");
3685
+ if (initials) {
3686
+ comment.initials = initials;
3687
+ }
3688
+ comments.push(comment);
3689
+ }
3690
+ return comments;
3691
+ }
3692
+ /** Parse word/commentsExtended.xml — map paraId → { done, parentId }. */
3693
+ function parseCommentsExtendedXml(xmlStr) {
3694
+ const map = new Map();
3695
+ const doc = (0, dom_1.parseXml)(xmlStr);
3696
+ const root = doc.root;
3697
+ for (const child of root.children) {
3698
+ if (child.type !== "element") {
3699
+ continue;
3700
+ }
3701
+ // w15:commentEx
3702
+ const name = child.name;
3703
+ if (!name.endsWith("commentEx")) {
3704
+ continue;
3705
+ }
3706
+ const paraId = child.attributes["w15:paraId"] ?? child.attributes["paraId"];
3707
+ if (!paraId) {
3708
+ continue;
3709
+ }
3710
+ const entry = {};
3711
+ const done = child.attributes["w15:done"] ?? child.attributes["done"];
3712
+ if (done === "1" || done === "true") {
3713
+ entry.done = true;
3714
+ }
3715
+ else if (done === "0" || done === "false") {
3716
+ entry.done = false;
3717
+ }
3718
+ const pid = child.attributes["w15:paraIdParent"] ?? child.attributes["paraIdParent"];
3719
+ if (pid) {
3720
+ entry.parentId = pid;
3721
+ }
3722
+ map.set(paraId, entry);
3723
+ }
3724
+ return map;
3725
+ }
3726
+ // =============================================================================
3727
+ // Core Properties Parser
3728
+ // =============================================================================
3729
+ function parseCoreProps(xmlStr) {
3730
+ const doc = (0, dom_1.parseXml)(xmlStr);
3731
+ const root = doc.root;
3732
+ const props = {};
3733
+ const fields = [
3734
+ ["dc:title", "title"],
3735
+ ["dc:subject", "subject"],
3736
+ ["dc:creator", "creator"],
3737
+ ["dc:description", "description"],
3738
+ ["cp:keywords", "keywords"],
3739
+ ["cp:lastModifiedBy", "lastModifiedBy"],
3740
+ ["cp:revision", "revision"],
3741
+ ["cp:category", "category"]
3742
+ ];
3743
+ for (const [tag, prop] of fields) {
3744
+ const el = (0, dom_1.findChild)(root, tag);
3745
+ if (el) {
3746
+ const val = (0, dom_1.textContent)(el);
3747
+ if (val) {
3748
+ props[prop] = val;
3749
+ }
3750
+ }
3751
+ }
3752
+ const createdEl = (0, dom_1.findChild)(root, "dcterms:created");
3753
+ if (createdEl) {
3754
+ const val = (0, dom_1.textContent)(createdEl);
3755
+ if (val) {
3756
+ props.created = new Date(val);
3757
+ }
3758
+ }
3759
+ const modifiedEl = (0, dom_1.findChild)(root, "dcterms:modified");
3760
+ if (modifiedEl) {
3761
+ const val = (0, dom_1.textContent)(modifiedEl);
3762
+ if (val) {
3763
+ props.modified = new Date(val);
3764
+ }
3765
+ }
3766
+ return props;
3767
+ }
3768
+ // =============================================================================
3769
+ // App Properties Parser
3770
+ // =============================================================================
3771
+ function parseAppProps(xmlStr) {
3772
+ const doc = (0, dom_1.parseXml)(xmlStr);
3773
+ const root = doc.root;
3774
+ const props = {};
3775
+ const strFields = ["Application", "AppVersion", "Company", "Manager"];
3776
+ const intFields = ["Pages", "Words", "Characters", "Lines", "Paragraphs"];
3777
+ for (const field of strFields) {
3778
+ const el = (0, dom_1.findChild)(root, field);
3779
+ if (el) {
3780
+ const val = (0, dom_1.textContent)(el);
3781
+ if (val) {
3782
+ props[field.charAt(0).toLowerCase() + field.slice(1)] = val;
3783
+ }
3784
+ }
3785
+ }
3786
+ for (const field of intFields) {
3787
+ const el = (0, dom_1.findChild)(root, field);
3788
+ if (el) {
3789
+ const val = (0, dom_1.textContent)(el);
3790
+ if (val) {
3791
+ props[field.charAt(0).toLowerCase() + field.slice(1)] = parseInt(val, 10);
3792
+ }
3793
+ }
3794
+ }
3795
+ return props;
3796
+ }
3797
+ // =============================================================================
3798
+ // Theme Parser
3799
+ // =============================================================================
3800
+ const THEME_COLOR_NAMES = [
3801
+ "dk1",
3802
+ "lt1",
3803
+ "dk2",
3804
+ "lt2",
3805
+ "accent1",
3806
+ "accent2",
3807
+ "accent3",
3808
+ "accent4",
3809
+ "accent5",
3810
+ "accent6",
3811
+ "hlink",
3812
+ "folHlink"
3813
+ ];
3814
+ function parseThemeXml(xmlStr) {
3815
+ const doc = (0, dom_1.parseXml)(xmlStr);
3816
+ const root = doc.root;
3817
+ // Find a:themeElements
3818
+ const themeElements = (0, dom_1.findChild)(root, "a:themeElements") ?? findChildNs(root, "themeElements");
3819
+ const defaultScheme = {
3820
+ name: "Office",
3821
+ colors: {
3822
+ dk1: "000000",
3823
+ lt1: "FFFFFF",
3824
+ dk2: "44546A",
3825
+ lt2: "E7E6E6",
3826
+ accent1: "4472C4",
3827
+ accent2: "ED7D31",
3828
+ accent3: "A5A5A5",
3829
+ accent4: "FFC000",
3830
+ accent5: "5B9BD5",
3831
+ accent6: "70AD47",
3832
+ hlink: "0563C1",
3833
+ folHlink: "954F72"
3834
+ }
3835
+ };
3836
+ const defaultFontScheme = { name: "Office", majorFont: "Calibri Light", minorFont: "Calibri" };
3837
+ if (!themeElements) {
3838
+ return {
3839
+ name: root.attributes["name"],
3840
+ colorScheme: defaultScheme,
3841
+ fontScheme: defaultFontScheme
3842
+ };
3843
+ }
3844
+ // Parse color scheme
3845
+ const clrSchemeEl = (0, dom_1.findChild)(themeElements, "a:clrScheme") ?? findChildNs(themeElements, "clrScheme");
3846
+ const colorScheme = { ...defaultScheme };
3847
+ if (clrSchemeEl) {
3848
+ colorScheme.name = clrSchemeEl.attributes["name"] ?? "Office";
3849
+ for (const colorName of THEME_COLOR_NAMES) {
3850
+ const colorEl = (0, dom_1.findChild)(clrSchemeEl, `a:${colorName}`) ?? findChildNs(clrSchemeEl, colorName);
3851
+ if (colorEl) {
3852
+ // Color can be sysClr (with lastClr) or srgbClr (with val)
3853
+ const srgb = (0, dom_1.findChild)(colorEl, "a:srgbClr") ?? findChildNs(colorEl, "srgbClr");
3854
+ if (srgb) {
3855
+ const val = srgb.attributes["val"];
3856
+ if (val) {
3857
+ colorScheme.colors[colorName] = val;
3858
+ }
3859
+ }
3860
+ else {
3861
+ const sys = (0, dom_1.findChild)(colorEl, "a:sysClr") ?? findChildNs(colorEl, "sysClr");
3862
+ if (sys) {
3863
+ const lastClr = sys.attributes["lastClr"];
3864
+ if (lastClr) {
3865
+ colorScheme.colors[colorName] = lastClr;
3866
+ }
3867
+ }
3868
+ }
3869
+ }
3870
+ }
3871
+ }
3872
+ // Parse font scheme
3873
+ const fontSchemeEl = (0, dom_1.findChild)(themeElements, "a:fontScheme") ?? findChildNs(themeElements, "fontScheme");
3874
+ const fontScheme = { ...defaultFontScheme };
3875
+ if (fontSchemeEl) {
3876
+ fontScheme.name = fontSchemeEl.attributes["name"] ?? "Office";
3877
+ const majorEl = (0, dom_1.findChild)(fontSchemeEl, "a:majorFont") ?? findChildNs(fontSchemeEl, "majorFont");
3878
+ if (majorEl) {
3879
+ const major = parseThemeFont(majorEl);
3880
+ fontScheme.major = major;
3881
+ if (major.latin) {
3882
+ fontScheme.majorFont = major.latin;
3883
+ }
3884
+ }
3885
+ const minorEl = (0, dom_1.findChild)(fontSchemeEl, "a:minorFont") ?? findChildNs(fontSchemeEl, "minorFont");
3886
+ if (minorEl) {
3887
+ const minor = parseThemeFont(minorEl);
3888
+ fontScheme.minor = minor;
3889
+ if (minor.latin) {
3890
+ fontScheme.minorFont = minor.latin;
3891
+ }
3892
+ }
3893
+ }
3894
+ // Parse format scheme (preserve raw XML of its children for round-trip)
3895
+ const fmtSchemeEl = (0, dom_1.findChild)(themeElements, "a:fmtScheme") ?? findChildNs(themeElements, "fmtScheme");
3896
+ let formatScheme;
3897
+ if (fmtSchemeEl) {
3898
+ let rawXml = "";
3899
+ for (const child of fmtSchemeEl.children) {
3900
+ if (child.type === "element") {
3901
+ rawXml += serializeElement(child);
3902
+ }
3903
+ }
3904
+ formatScheme = {
3905
+ name: fmtSchemeEl.attributes["name"] ?? "Office",
3906
+ rawXml: rawXml || undefined
3907
+ };
3908
+ }
3909
+ // Preserve extLst (theme extensions) as raw XML
3910
+ let extLstXml;
3911
+ const extLstEl = (0, dom_1.findChild)(root, "a:extLst") ?? findChildNs(root, "extLst");
3912
+ if (extLstEl) {
3913
+ extLstXml = serializeElement(extLstEl);
3914
+ }
3915
+ return {
3916
+ name: root.attributes["name"],
3917
+ colorScheme,
3918
+ fontScheme,
3919
+ formatScheme,
3920
+ extLstXml
3921
+ };
3922
+ }
3923
+ /** Parse a theme font (a:majorFont or a:minorFont). */
3924
+ function parseThemeFont(el) {
3925
+ const font = {};
3926
+ const latin = (0, dom_1.findChild)(el, "a:latin") ?? findChildNs(el, "latin");
3927
+ if (latin?.attributes["typeface"]) {
3928
+ font.latin = latin.attributes["typeface"];
3929
+ }
3930
+ const ea = (0, dom_1.findChild)(el, "a:ea") ?? findChildNs(el, "ea");
3931
+ if (ea?.attributes["typeface"]) {
3932
+ font.eastAsia = ea.attributes["typeface"];
3933
+ }
3934
+ const cs = (0, dom_1.findChild)(el, "a:cs") ?? findChildNs(el, "cs");
3935
+ if (cs?.attributes["typeface"]) {
3936
+ font.complexScript = cs.attributes["typeface"];
3937
+ }
3938
+ // Supplemental fonts (a:font script="..." typeface="...")
3939
+ const supplementalFonts = {};
3940
+ for (const child of el.children) {
3941
+ if (child.type === "element" && (child.name === "a:font" || child.name === "font")) {
3942
+ const script = child.attributes["script"];
3943
+ const typeface = child.attributes["typeface"];
3944
+ if (script && typeface) {
3945
+ supplementalFonts[script] = typeface;
3946
+ }
3947
+ }
3948
+ }
3949
+ if (Object.keys(supplementalFonts).length > 0) {
3950
+ font.supplementalFonts = supplementalFonts;
3951
+ }
3952
+ return font;
3953
+ }
3954
+ // =============================================================================
3955
+ // Settings Parser
3956
+ // =============================================================================
3957
+ /** Parse word/webSettings.xml. */
3958
+ function parseWebSettings(xmlStr) {
3959
+ const doc = (0, dom_1.parseXml)(xmlStr);
3960
+ const root = doc.root;
3961
+ const ws = {};
3962
+ const ofbEl = findChildNs(root, "optimizeForBrowser");
3963
+ if (ofbEl) {
3964
+ const ofb = {};
3965
+ const target = attrVal(ofbEl, "target");
3966
+ if (target) {
3967
+ ofb.target = target;
3968
+ }
3969
+ const mv = attrInt(ofbEl, "majorVersion");
3970
+ if (mv !== undefined) {
3971
+ ofb.majorVersion = mv;
3972
+ }
3973
+ ws.optimizeForBrowser = ofb;
3974
+ }
3975
+ if (findChildNs(root, "allowPNG")) {
3976
+ ws.allowPng = true;
3977
+ }
3978
+ if (findChildNs(root, "relyOnVML")) {
3979
+ ws.relyOnVml = true;
3980
+ }
3981
+ if (findChildNs(root, "doNotSaveAsSingleFile")) {
3982
+ ws.doNotSaveAsSingleFile = true;
3983
+ }
3984
+ if (findChildNs(root, "doNotOrganizeInFolder")) {
3985
+ ws.doNotOrganizeInFolder = true;
3986
+ }
3987
+ if (findChildNs(root, "useTargetMachineType")) {
3988
+ ws.useTargetMachineType = true;
3989
+ }
3990
+ return ws;
3991
+ }
3992
+ /** Parse word/people.xml. */
3993
+ function parsePeople(xmlStr) {
3994
+ const doc = (0, dom_1.parseXml)(xmlStr);
3995
+ const root = doc.root;
3996
+ const people = [];
3997
+ for (const personEl of root.children) {
3998
+ if (personEl.type !== "element") {
3999
+ continue;
4000
+ }
4001
+ const author = personEl.attributes["w15:author"] ?? personEl.attributes["author"];
4002
+ if (!author) {
4003
+ continue;
4004
+ }
4005
+ const info = { author };
4006
+ // presenceInfo
4007
+ for (const child of personEl.children) {
4008
+ if (child.type === "element" && child.name.endsWith("presenceInfo")) {
4009
+ const pi = {};
4010
+ const providerId = child.attributes["w15:providerId"] ?? child.attributes["providerId"];
4011
+ if (providerId) {
4012
+ pi.providerId = providerId;
4013
+ }
4014
+ const userId = child.attributes["w15:userId"] ?? child.attributes["userId"];
4015
+ if (userId) {
4016
+ pi.userId = userId;
4017
+ }
4018
+ if (Object.keys(pi).length > 0) {
4019
+ info.presenceInfo = pi;
4020
+ }
4021
+ break;
4022
+ }
4023
+ }
4024
+ people.push(info);
4025
+ }
4026
+ return people;
4027
+ }
4028
+ function parseSettingsXml(xmlStr) {
4029
+ const doc = (0, dom_1.parseXml)(xmlStr);
4030
+ const root = doc.root;
4031
+ const settings = {};
4032
+ const zoomEl = findChildNs(root, "zoom");
4033
+ if (zoomEl) {
4034
+ settings.zoom = attrInt(zoomEl, "percent");
4035
+ }
4036
+ const tabEl = findChildNs(root, "defaultTabStop");
4037
+ if (tabEl) {
4038
+ settings.defaultTabStop = attrInt(tabEl, "val");
4039
+ }
4040
+ const csControlEl = findChildNs(root, "characterSpacingControl");
4041
+ if (csControlEl) {
4042
+ const v = attrVal(csControlEl, "val");
4043
+ if (v === "doNotCompress" ||
4044
+ v === "compressPunctuation" ||
4045
+ v === "compressPunctuationAndJapaneseKana") {
4046
+ settings.characterSpacingControl = v;
4047
+ }
4048
+ }
4049
+ // Extended settings
4050
+ if (findChildNs(root, "doNotTrackMoves")) {
4051
+ settings.doNotTrackMoves = true;
4052
+ }
4053
+ if (findChildNs(root, "doNotTrackFormatting")) {
4054
+ settings.doNotTrackFormatting = true;
4055
+ }
4056
+ if (findChildNs(root, "doNotDemoteNonCombiningChars")) {
4057
+ settings.doNotDemoteAsianTextFirstLine = true;
4058
+ }
4059
+ const ssFontsEl = findChildNs(root, "saveSubsetFonts");
4060
+ if (ssFontsEl) {
4061
+ const v = attrVal(ssFontsEl, "val");
4062
+ settings.saveSubsetFonts = v !== "0" && v !== "false";
4063
+ }
4064
+ if (findChildNs(root, "noPunctuationKerning")) {
4065
+ settings.noPunctuationKerning = true;
4066
+ }
4067
+ if (findChildNs(root, "bordersDoNotSurroundHeader")) {
4068
+ settings.bordersDoNotSurroundHeader = true;
4069
+ }
4070
+ if (findChildNs(root, "bordersDoNotSurroundFooter")) {
4071
+ settings.bordersDoNotSurroundFooter = true;
4072
+ }
4073
+ const clickStyleEl = findChildNs(root, "clickAndTypeStyle");
4074
+ if (clickStyleEl) {
4075
+ settings.clickAndTypeStyle = attrVal(clickStyleEl, "val");
4076
+ }
4077
+ const spfEl = findChildNs(root, "stylePaneFormatFilter");
4078
+ if (spfEl) {
4079
+ settings.stylePaneFormatFilter = attrVal(spfEl, "val");
4080
+ }
4081
+ const spsEl = findChildNs(root, "stylePaneSortMethod");
4082
+ if (spsEl) {
4083
+ settings.stylePaneSortMethod = attrVal(spsEl, "val");
4084
+ }
4085
+ const tflEl = findChildNs(root, "themeFontLang");
4086
+ if (tflEl) {
4087
+ const tfl = {};
4088
+ const v = attrVal(tflEl, "val");
4089
+ if (v) {
4090
+ tfl.val = v;
4091
+ }
4092
+ const ea = attrVal(tflEl, "eastAsia");
4093
+ if (ea) {
4094
+ tfl.eastAsia = ea;
4095
+ }
4096
+ const bd = attrVal(tflEl, "bidi");
4097
+ if (bd) {
4098
+ tfl.bidi = bd;
4099
+ }
4100
+ if (Object.keys(tfl).length > 0) {
4101
+ settings.themeFontLang = tfl;
4102
+ }
4103
+ }
4104
+ const dsEl = findChildNs(root, "decimalSymbol");
4105
+ if (dsEl) {
4106
+ settings.decimalSymbol = attrVal(dsEl, "val");
4107
+ }
4108
+ const lsEl = findChildNs(root, "listSeparator");
4109
+ if (lsEl) {
4110
+ settings.listSeparator = attrVal(lsEl, "val");
4111
+ }
4112
+ // RSID list
4113
+ const rsidsEl = findChildNs(root, "rsids");
4114
+ if (rsidsEl) {
4115
+ const rsids = {};
4116
+ const rootEl = findChildNs(rsidsEl, "rsidRoot");
4117
+ if (rootEl) {
4118
+ rsids.rsidRoot = attrVal(rootEl, "val");
4119
+ }
4120
+ const rsidList = [];
4121
+ for (const rsidEl of findChildrenNs(rsidsEl, "rsid")) {
4122
+ const v = attrVal(rsidEl, "val");
4123
+ if (v) {
4124
+ rsidList.push(v);
4125
+ }
4126
+ }
4127
+ if (rsidList.length > 0) {
4128
+ rsids.rsid = rsidList;
4129
+ }
4130
+ if (Object.keys(rsids).length > 0) {
4131
+ settings.rsids = rsids;
4132
+ }
4133
+ }
4134
+ if (findChildNs(root, "evenAndOddHeaders")) {
4135
+ settings.evenAndOddHeaders = true;
4136
+ }
4137
+ if (findChildNs(root, "trackRevisions")) {
4138
+ settings.trackRevisions = true;
4139
+ }
4140
+ if (findChildNs(root, "mirrorMargins")) {
4141
+ settings.mirrorMargins = true;
4142
+ }
4143
+ if (findChildNs(root, "gutterAtTop")) {
4144
+ settings.gutterAtTop = true;
4145
+ }
4146
+ if (findChildNs(root, "displayBackgroundShape")) {
4147
+ settings.displayBackgroundShape = true;
4148
+ }
4149
+ if (findChildNs(root, "updateFields")) {
4150
+ settings.updateFieldsOnOpen = true;
4151
+ }
4152
+ // Hyphenation
4153
+ const autoHyphEl = findChildNs(root, "autoHyphenation");
4154
+ if (autoHyphEl) {
4155
+ settings.autoHyphenation = true;
4156
+ const hyph = { autoHyphenation: true };
4157
+ const hzEl = findChildNs(root, "hyphenationZone");
4158
+ if (hzEl) {
4159
+ hyph.hyphenationZone = attrInt(hzEl, "val");
4160
+ }
4161
+ const chlEl = findChildNs(root, "consecutiveHyphenLimit");
4162
+ if (chlEl) {
4163
+ hyph.consecutiveHyphenLimit = attrInt(chlEl, "val");
4164
+ }
4165
+ if (findChildNs(root, "doNotHyphenateCaps")) {
4166
+ hyph.doNotHyphenateCaps = true;
4167
+ }
4168
+ settings.hyphenation = hyph;
4169
+ }
4170
+ // Document protection
4171
+ const protEl = findChildNs(root, "documentProtection");
4172
+ if (protEl) {
4173
+ settings.documentProtection = {
4174
+ type: attrVal(protEl, "edit") ?? "none",
4175
+ enforcement: attrVal(protEl, "enforcement") === "1"
4176
+ };
4177
+ }
4178
+ const compatEl = findChildNs(root, "compat");
4179
+ if (compatEl) {
4180
+ const compatSettings = [];
4181
+ const compatFlags = [];
4182
+ for (const csEl of compatEl.children) {
4183
+ if (csEl.type !== "element") {
4184
+ continue;
4185
+ }
4186
+ const localName = csEl.name.replace(/^w:/, "");
4187
+ if (localName === "compatSetting") {
4188
+ const name = attrVal(csEl, "name");
4189
+ const uri = attrVal(csEl, "uri");
4190
+ const val = attrVal(csEl, "val");
4191
+ if (name === "compatibilityMode" && val !== undefined) {
4192
+ settings.compatibilityMode = parseInt(val, 10);
4193
+ }
4194
+ else if (name !== undefined && uri !== undefined && val !== undefined) {
4195
+ compatSettings.push({ name, uri, val });
4196
+ }
4197
+ }
4198
+ else {
4199
+ // Legacy compat flags (w:useFELayout, w:balanceSingleByteDoubleByteWidth, etc.)
4200
+ compatFlags.push({ name: localName, val: attrVal(csEl, "val") });
4201
+ }
4202
+ }
4203
+ if (compatSettings.length > 0) {
4204
+ settings.compatSettings = compatSettings;
4205
+ }
4206
+ if (compatFlags.length > 0) {
4207
+ settings.compatFlags = compatFlags;
4208
+ }
4209
+ }
4210
+ // Mail merge settings (preserve as raw XML)
4211
+ const mailMergeEl = findChildNs(root, "mailMerge");
4212
+ if (mailMergeEl) {
4213
+ settings.mailMergeRawXml = serializeElement(mailMergeEl);
4214
+ }
4215
+ // Write protection
4216
+ const writeProtectionEl = findChildNs(root, "writeProtection");
4217
+ if (writeProtectionEl) {
4218
+ const wp = {};
4219
+ const recommended = attrVal(writeProtectionEl, "recommended");
4220
+ if (recommended === "1" || recommended === "true") {
4221
+ wp.recommended = true;
4222
+ }
4223
+ const algName = attrVal(writeProtectionEl, "algorithmName");
4224
+ if (algName) {
4225
+ wp.algorithmName = algName;
4226
+ }
4227
+ const hashValue = attrVal(writeProtectionEl, "hashValue");
4228
+ if (hashValue) {
4229
+ wp.hashValue = hashValue;
4230
+ }
4231
+ const saltValue = attrVal(writeProtectionEl, "saltValue");
4232
+ if (saltValue) {
4233
+ wp.saltValue = saltValue;
4234
+ }
4235
+ const spinCount = attrInt(writeProtectionEl, "spinCount");
4236
+ if (spinCount !== undefined) {
4237
+ wp.spinCount = spinCount;
4238
+ }
4239
+ settings.writeProtection = wp;
4240
+ }
4241
+ // Document variables
4242
+ const docVarsEl = findChildNs(root, "docVars");
4243
+ if (docVarsEl) {
4244
+ const vars = new Map();
4245
+ for (const dvEl of findChildrenNs(docVarsEl, "docVar")) {
4246
+ const name = attrVal(dvEl, "name");
4247
+ const val = attrVal(dvEl, "val");
4248
+ if (name !== undefined && val !== undefined) {
4249
+ vars.set(name, val);
4250
+ }
4251
+ }
4252
+ if (vars.size > 0) {
4253
+ settings.docVars = vars;
4254
+ }
4255
+ }
4256
+ // Footnote/endnote properties at document level
4257
+ const fnPrEl = findChildNs(root, "footnotePr");
4258
+ if (fnPrEl) {
4259
+ const fnProps = parseNoteProperties(fnPrEl);
4260
+ if (fnProps) {
4261
+ settings.footnoteProperties = fnProps;
4262
+ }
4263
+ }
4264
+ const enPrEl = findChildNs(root, "endnotePr");
4265
+ if (enPrEl) {
4266
+ const enProps = parseNoteProperties(enPrEl);
4267
+ if (enProps) {
4268
+ settings.endnoteProperties = enProps;
4269
+ }
4270
+ }
4271
+ return settings;
4272
+ }
4273
+ // =============================================================================
4274
+ // Custom Properties Parser
4275
+ // =============================================================================
4276
+ function parseCustomPropsXml(xmlStr) {
4277
+ const doc = (0, dom_1.parseXml)(xmlStr);
4278
+ const root = doc.root;
4279
+ const props = [];
4280
+ for (const propEl of root.children) {
4281
+ if (propEl.type !== "element" || propEl.name !== "property") {
4282
+ continue;
4283
+ }
4284
+ const name = propEl.attributes["name"];
4285
+ if (!name) {
4286
+ continue;
4287
+ }
4288
+ let value;
4289
+ for (const child of propEl.children) {
4290
+ if (child.type !== "element") {
4291
+ continue;
4292
+ }
4293
+ const tn = child.name;
4294
+ const tv = (0, dom_1.textContent)(child);
4295
+ if (tn === "vt:lpwstr") {
4296
+ value = { type: "string", value: tv };
4297
+ }
4298
+ else if (tn === "vt:i4") {
4299
+ value = { type: "number", value: parseInt(tv, 10) };
4300
+ }
4301
+ else if (tn === "vt:r8") {
4302
+ value = { type: "number", value: parseFloat(tv) };
4303
+ }
4304
+ else if (tn === "vt:bool") {
4305
+ value = { type: "boolean", value: tv === "true" };
4306
+ }
4307
+ else if (tn === "vt:filetime") {
4308
+ value = { type: "date", value: new Date(tv) };
4309
+ }
4310
+ }
4311
+ if (value) {
4312
+ props.push({ name, value });
4313
+ }
4314
+ }
4315
+ return props;
4316
+ }
4317
+ // =============================================================================
4318
+ // Font Table Parser
4319
+ // =============================================================================
4320
+ function parseFontTableXml(xmlStr) {
4321
+ const doc = (0, dom_1.parseXml)(xmlStr);
4322
+ const root = doc.root;
4323
+ const fonts = [];
4324
+ for (const fontEl of findChildrenNs(root, "font")) {
4325
+ const f = { name: attrVal(fontEl, "name") ?? "" };
4326
+ const p1 = findChildNs(fontEl, "panose1");
4327
+ if (p1) {
4328
+ f.panose1 = attrVal(p1, "val");
4329
+ }
4330
+ const cs = findChildNs(fontEl, "charset");
4331
+ if (cs) {
4332
+ f.charset = attrVal(cs, "val");
4333
+ }
4334
+ const fam = findChildNs(fontEl, "family");
4335
+ if (fam) {
4336
+ f.family = attrVal(fam, "val");
4337
+ }
4338
+ const pitch = findChildNs(fontEl, "pitch");
4339
+ if (pitch) {
4340
+ f.pitch = attrVal(pitch, "val");
4341
+ }
4342
+ // Signature
4343
+ const sigEl = findChildNs(fontEl, "sig");
4344
+ if (sigEl) {
4345
+ const sig = {};
4346
+ for (const key of ["usb0", "usb1", "usb2", "usb3", "csb0", "csb1"]) {
4347
+ const v = attrVal(sigEl, key);
4348
+ if (v !== undefined) {
4349
+ sig[key] = v;
4350
+ }
4351
+ }
4352
+ if (Object.keys(sig).length > 0) {
4353
+ f.sig = sig;
4354
+ }
4355
+ }
4356
+ // Embedded fonts
4357
+ for (const [tag, rIdKey, keyKey] of [
4358
+ ["embedRegular", "embedRegular", "embedRegularKey"],
4359
+ ["embedBold", "embedBold", "embedBoldKey"],
4360
+ ["embedItalic", "embedItalic", "embedItalicKey"],
4361
+ ["embedBoldItalic", "embedBoldItalic", "embedBoldItalicKey"]
4362
+ ]) {
4363
+ const el = findChildNs(fontEl, tag);
4364
+ if (el) {
4365
+ const rId = el.attributes["r:id"] ?? el.attributes["id"];
4366
+ if (rId) {
4367
+ f[rIdKey] = rId;
4368
+ const fontKey = attrVal(el, "fontKey");
4369
+ if (fontKey) {
4370
+ f[keyKey] = fontKey;
4371
+ }
4372
+ }
4373
+ }
4374
+ }
4375
+ fonts.push(f);
4376
+ }
4377
+ return fonts;
4378
+ }
4379
+ function parseRelationships(xmlStr) {
4380
+ const doc = (0, dom_1.parseXml)(xmlStr);
4381
+ const rels = [];
4382
+ for (const child of doc.root.children) {
4383
+ if (child.type === "element" && child.name === "Relationship") {
4384
+ rels.push({
4385
+ id: child.attributes["Id"] ?? "",
4386
+ type: child.attributes["Type"] ?? "",
4387
+ target: child.attributes["Target"] ?? "",
4388
+ targetMode: child.attributes["TargetMode"]
4389
+ });
4390
+ }
4391
+ }
4392
+ return rels;
4393
+ }
4394
+ // =============================================================================
4395
+ // Main Document Parser
4396
+ // =============================================================================
4397
+ /** Recursively extract floating images, drawing shapes, and opaque drawings from an element tree. */
4398
+ function extractFloatingContent(el, images, shapes, opaqueDrawings) {
4399
+ for (const child of el.children) {
4400
+ if (child.type !== "element") {
4401
+ continue;
4402
+ }
4403
+ if (child.name === "wp:anchor") {
4404
+ // Check if this is a pic (image) or wsp (shape)
4405
+ const graphicEl = (0, dom_1.findChild)(child, "a:graphic");
4406
+ const graphicDataEl = graphicEl ? (0, dom_1.findChild)(graphicEl, "a:graphicData") : undefined;
4407
+ const wspEl = graphicDataEl
4408
+ ? ((0, dom_1.findChild)(graphicDataEl, "wps:wsp") ?? findChildNs(graphicDataEl, "wsp"))
4409
+ : undefined;
4410
+ if (wspEl) {
4411
+ const shape = parseDrawingShape(child, wspEl);
4412
+ if (shape) {
4413
+ shapes.push(shape);
4414
+ }
4415
+ }
4416
+ else {
4417
+ const fi = parseFloatingImage(child);
4418
+ if (fi) {
4419
+ images.push(fi);
4420
+ }
4421
+ else {
4422
+ // Unknown anchor content (chart, diagram, etc.) — preserve as opaque
4423
+ const drawingEl = findDrawingParent(child);
4424
+ if (drawingEl) {
4425
+ const rids = new Set();
4426
+ collectRIds(drawingEl, rids);
4427
+ opaqueDrawings.push({
4428
+ type: "opaqueDrawing",
4429
+ rawXml: serializeElement(drawingEl),
4430
+ referencedRIds: [...rids]
4431
+ });
4432
+ }
4433
+ }
4434
+ }
4435
+ }
4436
+ else if (child.name === "wp:inline") {
4437
+ // Inline drawings that aren't images — check for chart etc.
4438
+ const graphicEl = (0, dom_1.findChild)(child, "a:graphic");
4439
+ const graphicDataEl = graphicEl ? (0, dom_1.findChild)(graphicEl, "a:graphicData") : undefined;
4440
+ if (graphicDataEl) {
4441
+ const picEl = (0, dom_1.findChild)(graphicDataEl, "pic:pic") ?? findChildNs(graphicDataEl, "pic");
4442
+ if (!picEl) {
4443
+ // Not an image — opaque inline drawing
4444
+ // Find the w:drawing parent
4445
+ const rids = new Set();
4446
+ collectRIds(child, rids);
4447
+ // Serialize the wp:inline element wrapped in w:drawing
4448
+ const rawXml = `<w:drawing>${serializeElement(child)}</w:drawing>`;
4449
+ opaqueDrawings.push({
4450
+ type: "opaqueDrawing",
4451
+ rawXml,
4452
+ referencedRIds: [...rids]
4453
+ });
4454
+ }
4455
+ }
4456
+ }
4457
+ else {
4458
+ extractFloatingContent(child, images, shapes, opaqueDrawings);
4459
+ }
4460
+ }
4461
+ }
4462
+ /** Find the w:drawing ancestor element for serialization. */
4463
+ function findDrawingParent(anchorEl) {
4464
+ // We don't have parent refs, so we construct a synthetic w:drawing wrapper
4465
+ return {
4466
+ type: "element",
4467
+ name: "w:drawing",
4468
+ attributes: {},
4469
+ children: [anchorEl]
4470
+ };
4471
+ }
4472
+ function parseDocumentXml(xmlStr) {
4473
+ const doc = (0, dom_1.parseXml)(xmlStr);
4474
+ const root = doc.root;
4475
+ // Parse background
4476
+ let background;
4477
+ const bgEl = findChildNs(root, "background");
4478
+ if (bgEl) {
4479
+ const bg = {};
4480
+ const color = attrVal(bgEl, "color");
4481
+ if (color) {
4482
+ bg.color = color;
4483
+ }
4484
+ const themeColor = attrVal(bgEl, "themeColor");
4485
+ if (themeColor) {
4486
+ bg.themeColor = themeColor;
4487
+ }
4488
+ const themeShade = attrVal(bgEl, "themeShade");
4489
+ if (themeShade) {
4490
+ bg.themeShade = themeShade;
4491
+ }
4492
+ const themeTint = attrVal(bgEl, "themeTint");
4493
+ if (themeTint) {
4494
+ bg.themeTint = themeTint;
4495
+ }
4496
+ background = bg;
4497
+ }
4498
+ const bodyEl = findChildNs(root, "body") ?? (0, dom_1.findChild)(root, "w:body");
4499
+ if (!bodyEl) {
4500
+ throw new errors_1.DocxParseError("Missing w:body element in document.xml");
4501
+ }
4502
+ const body = [];
4503
+ let sectionProperties;
4504
+ // Collect floating images, drawing shapes, and opaque drawings from the whole body
4505
+ const floatingImages = [];
4506
+ const drawingShapes = [];
4507
+ const opaqueDrawings = [];
4508
+ extractFloatingContent(bodyEl, floatingImages, drawingShapes, opaqueDrawings);
4509
+ for (const child of bodyEl.children) {
4510
+ if (child.type !== "element") {
4511
+ continue;
4512
+ }
4513
+ const name = child.name.replace(/^w:/, "");
4514
+ switch (name) {
4515
+ case "p":
4516
+ body.push(parseParagraph(child));
4517
+ break;
4518
+ case "tbl":
4519
+ body.push(parseTable(child));
4520
+ break;
4521
+ case "sectPr":
4522
+ // Final section properties at the body level
4523
+ sectionProperties = parseSectionProperties(child);
4524
+ break;
4525
+ case "sdt": {
4526
+ const sdtResult = parseSdt(child);
4527
+ if (sdtResult) {
4528
+ body.push(sdtResult);
4529
+ }
4530
+ break;
4531
+ }
4532
+ case "altChunk": {
4533
+ const rId = child.attributes["r:id"] ?? child.attributes["id"];
4534
+ if (rId) {
4535
+ body.push({ type: "altChunk", rId });
4536
+ }
4537
+ break;
4538
+ }
4539
+ default: {
4540
+ // Check for math namespace
4541
+ if (child.name === "m:oMathPara") {
4542
+ body.push(parseMathBlock(child));
4543
+ }
4544
+ else if (child.name === "m:oMath") {
4545
+ body.push({ type: "math", content: parseMathContent(child) });
4546
+ }
4547
+ // Check for VML pict (textbox)
4548
+ if (name === "pict" || child.name === "w:pict") {
4549
+ const tb = parseTextBox(child);
4550
+ if (tb) {
4551
+ body.push(tb);
4552
+ }
4553
+ }
4554
+ break;
4555
+ }
4556
+ }
4557
+ }
4558
+ // Append floating images as top-level body content
4559
+ for (const fi of floatingImages) {
4560
+ body.push(fi);
4561
+ }
4562
+ // Append drawing shapes as top-level body content
4563
+ for (const ds of drawingShapes) {
4564
+ body.push(ds);
4565
+ }
4566
+ // Append opaque drawings as top-level body content
4567
+ for (const od of opaqueDrawings) {
4568
+ body.push(od);
4569
+ }
4570
+ return { body, sectionProperties, background };
4571
+ }
4572
+ // =============================================================================
4573
+ // Public API - Read DOCX
4574
+ // =============================================================================
4575
+ /**
4576
+ * Read a DOCX file from a Uint8Array buffer and parse it into a DocxDocument model.
4577
+ */
4578
+ async function readDocx(buffer) {
4579
+ try {
4580
+ return await _readDocxInner(buffer);
4581
+ }
4582
+ catch (e) {
4583
+ if (e instanceof errors_1.DocxError) {
4584
+ throw e;
4585
+ }
4586
+ const msg = e instanceof Error ? e.message : String(e);
4587
+ throw new errors_1.DocxParseError(`Failed to read DOCX: ${msg}`, { cause: e });
4588
+ }
4589
+ }
4590
+ async function _readDocxInner(buffer) {
4591
+ const reader = (0, read_archive_1.unzip)(buffer);
4592
+ const entries = new Map();
4593
+ for await (const entry of reader.entries()) {
4594
+ const data = await entry.bytes();
4595
+ // Normalize path: remove leading slash, normalize separators
4596
+ const path = entry.path.replace(/^\//, "").replace(/\\/g, "/");
4597
+ entries.set(path, data);
4598
+ }
4599
+ const decoder = new TextDecoder("utf-8");
4600
+ const consumedPaths = new Set(["[Content_Types].xml"]);
4601
+ const getText = (path) => {
4602
+ const data = entries.get(path);
4603
+ if (data) {
4604
+ consumedPaths.add(path);
4605
+ }
4606
+ return data ? decoder.decode(data) : undefined;
4607
+ };
4608
+ // Parse document relationships (must be before parseDocumentXml for hyperlink resolution)
4609
+ const docRelsXml = getText("word/_rels/document.xml.rels");
4610
+ const docRels = docRelsXml ? parseRelationships(docRelsXml) : [];
4611
+ const _relMap = new Map(docRels.map(r => [r.id, r]));
4612
+ // Set module-level context for parseParagraph hyperlink resolution
4613
+ _parseRelMap = _relMap;
4614
+ // Parse document.xml (required)
4615
+ const documentXml = getText("word/document.xml");
4616
+ if (!documentXml) {
4617
+ throw new errors_1.DocxMissingPartError("word/document.xml");
4618
+ }
4619
+ const { body, sectionProperties, background } = parseDocumentXml(documentXml);
4620
+ // Parse styles
4621
+ const stylesXml = getText("word/styles.xml");
4622
+ const stylesResult = stylesXml ? parseStyles(stylesXml) : undefined;
4623
+ // Parse numbering
4624
+ const numberingXml = getText("word/numbering.xml");
4625
+ const numberingResult = numberingXml ? parseNumberingXml(numberingXml) : undefined;
4626
+ // Parse footnotes/endnotes
4627
+ const footnotesXml = getText("word/footnotes.xml");
4628
+ const footnotes = footnotesXml ? parseNotesXml(footnotesXml, "footnote") : undefined;
4629
+ const endnotesXml = getText("word/endnotes.xml");
4630
+ const endnotes = endnotesXml ? parseNotesXml(endnotesXml, "endnote") : undefined;
4631
+ // Parse headers/footers + detect watermarks
4632
+ const headers = new Map();
4633
+ const footers = new Map();
4634
+ let watermark;
4635
+ for (const rel of docRels) {
4636
+ if (rel.type === constants_1.RelType.Header) {
4637
+ const xml = getText(resolvePartPath("word/document.xml", rel.target));
4638
+ if (xml) {
4639
+ // Parse XML once, re-use for both header content and watermark detection
4640
+ const headerRoot = (0, dom_1.parseXml)(xml).root;
4641
+ headers.set(rel.id, { content: parseHeaderFooterRoot(headerRoot), rId: rel.id });
4642
+ if (!watermark) {
4643
+ watermark = detectWatermarkFromRoot(headerRoot);
4644
+ }
4645
+ }
4646
+ }
4647
+ else if (rel.type === constants_1.RelType.Footer) {
4648
+ const xml = getText(resolvePartPath("word/document.xml", rel.target));
4649
+ if (xml) {
4650
+ footers.set(rel.id, { content: parseHeaderFooterXml(xml), rId: rel.id });
4651
+ }
4652
+ }
4653
+ }
4654
+ // Parse settings
4655
+ const settingsXml = getText("word/settings.xml");
4656
+ const settings = settingsXml ? parseSettingsXml(settingsXml) : undefined;
4657
+ // Parse web settings
4658
+ const webSettingsXml = getText("word/webSettings.xml");
4659
+ const webSettings = webSettingsXml ? parseWebSettings(webSettingsXml) : undefined;
4660
+ // Parse people
4661
+ const peopleXml = getText("word/people.xml");
4662
+ const people = peopleXml ? parsePeople(peopleXml) : undefined;
4663
+ // Parse thumbnail (from package rels)
4664
+ let thumbnail;
4665
+ const packageRelsXml = getText("_rels/.rels");
4666
+ if (packageRelsXml) {
4667
+ const pkgRels = parseRelationships(packageRelsXml);
4668
+ for (const rel of pkgRels) {
4669
+ if (rel.type.endsWith("/thumbnail")) {
4670
+ // Target in package rels is relative to package root; may include or exclude leading slash
4671
+ let target = rel.target;
4672
+ if (target.startsWith("/")) {
4673
+ target = target.substring(1);
4674
+ }
4675
+ // If the target doesn't include docProps/ prefix, add it (some writers emit bare filenames)
4676
+ const normalized = target.includes("/") ? target : `docProps/${target}`;
4677
+ consumedPaths.add(normalized);
4678
+ const thumbData = entries.get(normalized);
4679
+ if (thumbData) {
4680
+ const ext = normalized.split(".").pop()?.toLowerCase();
4681
+ const ct = ext === "jpeg" || ext === "jpg"
4682
+ ? "image/jpeg"
4683
+ : ext === "png"
4684
+ ? "image/png"
4685
+ : "image/x-wmf";
4686
+ thumbnail = { contentType: ct, data: thumbData };
4687
+ }
4688
+ break;
4689
+ }
4690
+ }
4691
+ }
4692
+ // Parse font table
4693
+ const fontTableXml = getText("word/fontTable.xml");
4694
+ const fonts = fontTableXml ? parseFontTableXml(fontTableXml) : undefined;
4695
+ // Parse embedded fonts
4696
+ let embeddedFonts;
4697
+ const fontTableRelsXml = getText("word/_rels/fontTable.xml.rels");
4698
+ if (fontTableRelsXml && fonts) {
4699
+ const fontRels = parseRelationships(fontTableRelsXml);
4700
+ const efs = [];
4701
+ // Build rId → { key } map from font table
4702
+ const rIdToKey = new Map();
4703
+ for (const f of fonts) {
4704
+ if (f.embedRegular && f.embedRegularKey) {
4705
+ rIdToKey.set(f.embedRegular, f.embedRegularKey);
4706
+ }
4707
+ if (f.embedBold && f.embedBoldKey) {
4708
+ rIdToKey.set(f.embedBold, f.embedBoldKey);
4709
+ }
4710
+ if (f.embedItalic && f.embedItalicKey) {
4711
+ rIdToKey.set(f.embedItalic, f.embedItalicKey);
4712
+ }
4713
+ if (f.embedBoldItalic && f.embedBoldItalicKey) {
4714
+ rIdToKey.set(f.embedBoldItalic, f.embedBoldItalicKey);
4715
+ }
4716
+ }
4717
+ for (const rel of fontRels) {
4718
+ if (rel.type === constants_1.RelType.Font) {
4719
+ const fontPath = resolvePartPath("word/fontTable.xml", rel.target);
4720
+ consumedPaths.add(fontPath);
4721
+ const data = entries.get(fontPath);
4722
+ if (data) {
4723
+ const fileName = rel.target.split("/").pop() ?? "";
4724
+ const fontKey = rIdToKey.get(rel.id);
4725
+ const ef = {
4726
+ rId: rel.id,
4727
+ data,
4728
+ fileName
4729
+ };
4730
+ if (fontKey) {
4731
+ ef.fontKey = fontKey;
4732
+ }
4733
+ efs.push(ef);
4734
+ }
4735
+ }
4736
+ }
4737
+ if (efs.length > 0) {
4738
+ embeddedFonts = efs;
4739
+ }
4740
+ }
4741
+ // Parse Custom XML parts (for SDT data binding)
4742
+ const customXmlParts = [];
4743
+ for (const rel of docRels) {
4744
+ if (rel.type === constants_1.RelType.CustomXml) {
4745
+ const targetPath = resolvePartPath("word/document.xml", rel.target);
4746
+ consumedPaths.add(targetPath);
4747
+ const xmlContent = getText(targetPath);
4748
+ if (!xmlContent) {
4749
+ continue;
4750
+ }
4751
+ // Parse itemProps*.xml to get storeItemID
4752
+ const fileName = targetPath.split("/").pop() ?? "";
4753
+ // itemProps file is typically at the same directory
4754
+ const dir = targetPath.substring(0, targetPath.lastIndexOf("/"));
4755
+ // Extract item number from fileName (e.g. "item1.xml" → "1")
4756
+ const match = fileName.match(/item(\d+)\.xml$/);
4757
+ let itemId = "";
4758
+ let schemaReferences;
4759
+ if (match) {
4760
+ const num = match[1];
4761
+ const propsPath = `${dir}/itemProps${num}.xml`;
4762
+ consumedPaths.add(propsPath);
4763
+ const propsXml = getText(propsPath);
4764
+ if (propsXml) {
4765
+ const propsDoc = (0, dom_1.parseXml)(propsXml);
4766
+ const dsItemEl = propsDoc.root;
4767
+ const id = dsItemEl.attributes["ds:itemID"];
4768
+ if (id) {
4769
+ itemId = id.replace(/[{}]/g, "");
4770
+ }
4771
+ // Schema references
4772
+ const refs = [];
4773
+ const schemaRefsEl = (0, dom_1.findChild)(dsItemEl, "ds:schemaRefs") ?? (0, dom_1.findChild)(dsItemEl, "schemaRefs");
4774
+ if (schemaRefsEl) {
4775
+ for (const srChild of schemaRefsEl.children) {
4776
+ if (srChild.type === "element") {
4777
+ const uri = srChild.attributes["ds:uri"] ?? srChild.attributes["uri"];
4778
+ if (uri) {
4779
+ refs.push(uri);
4780
+ }
4781
+ }
4782
+ }
4783
+ }
4784
+ if (refs.length > 0) {
4785
+ schemaReferences = refs;
4786
+ }
4787
+ }
4788
+ }
4789
+ customXmlParts.push({
4790
+ itemId,
4791
+ xmlContent,
4792
+ fileName,
4793
+ schemaReferences
4794
+ });
4795
+ }
4796
+ }
4797
+ // Parse core properties
4798
+ const corePropsXml = getText("docProps/core.xml");
4799
+ const coreProperties = corePropsXml ? parseCoreProps(corePropsXml) : undefined;
4800
+ // Parse app properties
4801
+ const appPropsXml = getText("docProps/app.xml");
4802
+ const appProperties = appPropsXml ? parseAppProps(appPropsXml) : undefined;
4803
+ // Parse comments
4804
+ const commentsXml = getText("word/comments.xml");
4805
+ let comments = commentsXml ? parseCommentsXml(commentsXml) : undefined;
4806
+ // Merge in commentsExtended.xml data if present
4807
+ const commentsExtXml = getText("word/commentsExtended.xml");
4808
+ if (commentsExtXml && comments) {
4809
+ const extMap = parseCommentsExtendedXml(commentsExtXml);
4810
+ comments = comments.map(c => {
4811
+ const firstPara = c.content[0];
4812
+ if (!firstPara?.paraId) {
4813
+ return c;
4814
+ }
4815
+ const ext = extMap.get(firstPara.paraId);
4816
+ if (!ext) {
4817
+ return c;
4818
+ }
4819
+ return {
4820
+ ...c,
4821
+ ...(ext.done !== undefined ? { done: ext.done } : {}),
4822
+ ...(ext.parentId !== undefined ? { parentId: ext.parentId } : {})
4823
+ };
4824
+ });
4825
+ }
4826
+ // Parse custom properties
4827
+ const customPropsXml = getText("docProps/custom.xml");
4828
+ const customProperties = customPropsXml ? parseCustomPropsXml(customPropsXml) : undefined;
4829
+ // Parse theme
4830
+ const themeXml = getText("word/theme/theme1.xml");
4831
+ const theme = themeXml ? parseThemeXml(themeXml) : undefined;
4832
+ // Collect images
4833
+ const images = [];
4834
+ for (const rel of docRels) {
4835
+ if (rel.type === constants_1.RelType.Image) {
4836
+ const imgPath = resolvePartPath("word/document.xml", rel.target);
4837
+ consumedPaths.add(imgPath);
4838
+ const data = entries.get(imgPath);
4839
+ if (data) {
4840
+ const fileName = rel.target.split("/").pop() ?? "";
4841
+ const ext = fileName.split(".").pop()?.toLowerCase() ?? "png";
4842
+ images.push({
4843
+ data,
4844
+ mediaType: ext,
4845
+ fileName,
4846
+ rId: rel.id
4847
+ });
4848
+ }
4849
+ }
4850
+ }
4851
+ // Collect opaque (unrecognized) parts for round-trip preservation
4852
+ const opaqueParts = [];
4853
+ for (const [path, data] of entries) {
4854
+ // Skip consumed paths and all .rels files (structural)
4855
+ if (consumedPaths.has(path) || path.includes("_rels/")) {
4856
+ continue;
4857
+ }
4858
+ // Parse rels for this part if they exist
4859
+ const partRelsPath = getPartRelsPath(path);
4860
+ const partRelsData = entries.get(partRelsPath);
4861
+ let relationships;
4862
+ if (partRelsData) {
4863
+ const rels = parseRelationships(decoder.decode(partRelsData));
4864
+ relationships = rels.map(r => ({
4865
+ id: r.id,
4866
+ type: r.type,
4867
+ target: r.target,
4868
+ targetMode: r.targetMode === "External" ? "External" : undefined
4869
+ }));
4870
+ }
4871
+ opaqueParts.push({ path, data, relationships });
4872
+ }
4873
+ // Resolve altChunk data: body elements of type "altChunk" reference a rId.
4874
+ // The target file is stored in docRels + entries. Move target data from entries
4875
+ // (and remove from opaqueParts, since it's now part of the altChunk body element).
4876
+ for (const item of body) {
4877
+ if (item.type === "altChunk" && item.rId) {
4878
+ const rel = _relMap.get(item.rId);
4879
+ if (rel) {
4880
+ const target = resolvePartPath("word/document.xml", rel.target);
4881
+ const targetData = entries.get(target);
4882
+ if (targetData) {
4883
+ const fileName = target.split("/").pop();
4884
+ item.data = targetData;
4885
+ item.fileName = fileName;
4886
+ // Infer content type from extension
4887
+ const ext = fileName?.split(".").pop()?.toLowerCase();
4888
+ if (ext === "html" || ext === "htm") {
4889
+ item.contentType = "text/html";
4890
+ }
4891
+ else if (ext === "rtf") {
4892
+ item.contentType = "text/rtf";
4893
+ }
4894
+ else if (ext === "txt") {
4895
+ item.contentType = "text/plain";
4896
+ }
4897
+ }
4898
+ }
4899
+ }
4900
+ }
4901
+ return {
4902
+ body,
4903
+ sectionProperties,
4904
+ styles: stylesResult?.styles,
4905
+ docDefaults: stylesResult?.docDefaults,
4906
+ abstractNumberings: numberingResult?.abstractNums,
4907
+ numberingInstances: numberingResult?.instances,
4908
+ numPicBullets: numberingResult?.numPicBullets && numberingResult.numPicBullets.length > 0
4909
+ ? numberingResult.numPicBullets
4910
+ : undefined,
4911
+ headers: headers.size > 0 ? headers : undefined,
4912
+ footers: footers.size > 0 ? footers : undefined,
4913
+ footnotes: footnotes && footnotes.length > 0 ? footnotes : undefined,
4914
+ endnotes: endnotes && endnotes.length > 0 ? endnotes : undefined,
4915
+ images: images.length > 0 ? images : undefined,
4916
+ fonts: fonts && fonts.length > 0 ? fonts : undefined,
4917
+ embeddedFonts: embeddedFonts && embeddedFonts.length > 0 ? embeddedFonts : undefined,
4918
+ customXmlParts: customXmlParts.length > 0 ? customXmlParts : undefined,
4919
+ webSettings,
4920
+ thumbnail,
4921
+ people: people && people.length > 0 ? people : undefined,
4922
+ settings,
4923
+ coreProperties,
4924
+ appProperties,
4925
+ comments: comments && comments.length > 0 ? comments : undefined,
4926
+ background,
4927
+ customProperties: customProperties && customProperties.length > 0 ? customProperties : undefined,
4928
+ theme,
4929
+ watermark,
4930
+ opaqueParts: opaqueParts.length > 0 ? opaqueParts : undefined
4931
+ };
4932
+ }