@cj-tech-master/excelts 9.5.4 → 9.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (767) hide show
  1. package/dist/browser/modules/archive/compression/streaming-compress.browser.js +29 -0
  2. package/dist/browser/modules/archive/compression/streaming-compress.js +9 -0
  3. package/dist/browser/modules/archive/compression/worker-pool/pool.browser.js +26 -1
  4. package/dist/browser/modules/archive/fs/archive-file.d.ts +8 -5
  5. package/dist/browser/modules/archive/fs/archive-file.js +78 -16
  6. package/dist/browser/modules/archive/unzip/stream.browser.js +43 -2
  7. package/dist/browser/modules/excel/chart/chart-ex-builder.js +7 -2
  8. package/dist/browser/modules/excel/chart/chart-ex-renderer.js +4 -9
  9. package/dist/browser/modules/excel/chart/chart-ex-types.d.ts +0 -12
  10. package/dist/browser/modules/excel/chart/chart.d.ts +1 -5
  11. package/dist/browser/modules/excel/chart/chart.js +1 -7
  12. package/dist/browser/modules/excel/chart/types.d.ts +0 -6
  13. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +25 -1
  14. package/dist/browser/modules/excel/stream/workbook-reader.js +9 -0
  15. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +40 -0
  16. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +228 -13
  17. package/dist/browser/modules/excel/utils/string-buf.d.ts +5 -26
  18. package/dist/browser/modules/excel/utils/string-buf.js +4 -81
  19. package/dist/browser/modules/excel/workbook.browser.js +135 -25
  20. package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.js +6 -20
  21. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +19 -9
  22. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +32 -8
  23. package/dist/browser/modules/excel/xlsx/xlsx.d.ts +10 -2
  24. package/dist/browser/modules/excel/xlsx/xlsx.js +9 -1
  25. package/dist/browser/modules/pdf/excel-bridge.d.ts +30 -1
  26. package/dist/browser/modules/pdf/excel-bridge.js +32 -0
  27. package/dist/browser/modules/pdf/font/metrics.d.ts +3 -52
  28. package/dist/browser/modules/pdf/font/metrics.js +3 -237
  29. package/dist/browser/modules/pdf/index.d.ts +1 -1
  30. package/dist/browser/modules/pdf/index.js +1 -1
  31. package/dist/browser/modules/pdf/render-layout-to-pdf.d.ts +66 -0
  32. package/dist/browser/modules/pdf/render-layout-to-pdf.js +647 -0
  33. package/dist/browser/modules/pdf/word-bridge.d.ts +80 -12
  34. package/dist/browser/modules/pdf/word-bridge.js +122 -274
  35. package/dist/browser/modules/stream/index.base.d.ts +2 -0
  36. package/dist/browser/modules/stream/index.base.js +2 -1
  37. package/dist/browser/modules/stream/internal/sink-adapter.d.ts +65 -0
  38. package/dist/browser/modules/stream/internal/sink-adapter.js +198 -0
  39. package/dist/browser/modules/stream/pull-stream.d.ts +19 -2
  40. package/dist/browser/modules/stream/pull-stream.js +51 -5
  41. package/dist/browser/modules/stream/types.d.ts +13 -1
  42. package/dist/browser/modules/word/advanced/diff.d.ts +61 -0
  43. package/dist/browser/modules/word/advanced/diff.js +167 -0
  44. package/dist/browser/modules/word/advanced/drawing-shapes.d.ts +269 -0
  45. package/dist/browser/modules/word/advanced/drawing-shapes.js +268 -0
  46. package/dist/browser/modules/word/advanced/field-engine.d.ts +43 -0
  47. package/dist/browser/modules/word/advanced/field-engine.js +1225 -0
  48. package/dist/browser/modules/word/advanced/glossary.d.ts +86 -0
  49. package/dist/browser/modules/word/advanced/glossary.js +79 -0
  50. package/dist/browser/modules/word/advanced/math-convert.d.ts +30 -0
  51. package/dist/browser/modules/word/advanced/math-convert.js +595 -0
  52. package/dist/browser/modules/word/advanced/ole-objects.d.ts +115 -0
  53. package/dist/browser/modules/word/advanced/ole-objects.js +271 -0
  54. package/dist/browser/modules/word/advanced/style-map.d.ts +105 -0
  55. package/dist/browser/modules/word/advanced/style-map.js +322 -0
  56. package/dist/browser/modules/word/advanced/validation.d.ts +56 -0
  57. package/dist/browser/modules/word/advanced/validation.js +1065 -0
  58. package/dist/browser/modules/word/advanced/vba-project.d.ts +91 -0
  59. package/dist/browser/modules/word/advanced/vba-project.js +265 -0
  60. package/dist/browser/modules/word/bridge/excel-bridge.d.ts +127 -0
  61. package/dist/browser/modules/word/bridge/excel-bridge.js +980 -0
  62. package/dist/browser/modules/word/builder/document-handle.d.ts +151 -0
  63. package/dist/browser/modules/word/builder/document-handle.js +664 -0
  64. package/dist/browser/modules/word/builder/paragraph-builders.d.ts +61 -0
  65. package/dist/browser/modules/word/builder/paragraph-builders.js +90 -0
  66. package/dist/browser/modules/word/builder/run-builders.d.ts +374 -0
  67. package/dist/browser/modules/word/builder/run-builders.js +600 -0
  68. package/dist/browser/modules/word/builder/table-builders.d.ts +23 -0
  69. package/dist/browser/modules/word/builder/table-builders.js +45 -0
  70. package/dist/browser/modules/word/constants.d.ts +39 -1
  71. package/dist/browser/modules/word/constants.js +109 -1
  72. package/dist/browser/modules/word/convert/conversion-ir.d.ts +210 -0
  73. package/dist/browser/modules/word/convert/conversion-ir.js +31 -0
  74. package/dist/browser/modules/word/convert/docx-to-semantic.d.ts +39 -0
  75. package/dist/browser/modules/word/convert/docx-to-semantic.js +499 -0
  76. package/dist/browser/modules/word/convert/flat-opc.d.ts +44 -0
  77. package/dist/browser/modules/word/convert/flat-opc.js +385 -0
  78. package/dist/browser/modules/word/convert/html/html-import.d.ts +50 -0
  79. package/dist/browser/modules/word/convert/html/html-import.js +1907 -0
  80. package/dist/{types/modules/word → browser/modules/word/convert/html}/html-renderer.d.ts +14 -1
  81. package/dist/{esm/modules/word → browser/modules/word/convert/html}/html-renderer.js +420 -69
  82. package/dist/browser/modules/word/convert/html/html.d.ts +15 -0
  83. package/dist/browser/modules/word/convert/html/html.js +15 -0
  84. package/dist/browser/modules/word/convert/markdown/markdown-import.d.ts +68 -0
  85. package/dist/browser/modules/word/convert/markdown/markdown-import.js +1325 -0
  86. package/dist/browser/modules/word/convert/markdown/markdown-renderer.d.ts +25 -0
  87. package/dist/browser/modules/word/convert/markdown/markdown-renderer.js +634 -0
  88. package/dist/browser/modules/word/convert/markdown/markdown.d.ts +15 -0
  89. package/dist/browser/modules/word/convert/markdown/markdown.js +15 -0
  90. package/dist/browser/modules/word/convert/odt/odt.d.ts +41 -0
  91. package/dist/browser/modules/word/convert/odt/odt.js +1932 -0
  92. package/dist/browser/modules/word/{color-utils.d.ts → core/color-utils.d.ts} +8 -1
  93. package/dist/browser/modules/word/core/color-utils.js +43 -0
  94. package/dist/browser/modules/word/core/internal-utils.d.ts +90 -0
  95. package/dist/browser/modules/word/core/internal-utils.js +209 -0
  96. package/dist/browser/modules/word/core/mapper.d.ts +44 -0
  97. package/dist/browser/modules/word/core/mapper.js +427 -0
  98. package/dist/browser/modules/word/core/opc-paths.d.ts +33 -0
  99. package/dist/browser/modules/word/core/opc-paths.js +48 -0
  100. package/dist/browser/modules/word/core/text-utils.d.ts +38 -0
  101. package/dist/browser/modules/word/core/text-utils.js +202 -0
  102. package/dist/browser/modules/word/core/walker.d.ts +119 -0
  103. package/dist/browser/modules/word/core/walker.js +570 -0
  104. package/dist/browser/modules/word/crypto.d.ts +14 -9
  105. package/dist/browser/modules/word/crypto.js +13 -7
  106. package/dist/browser/modules/word/document-io.d.ts +59 -27
  107. package/dist/browser/modules/word/document-io.js +80 -197
  108. package/dist/browser/modules/word/errors.d.ts +44 -1
  109. package/dist/browser/modules/word/errors.js +54 -2
  110. package/dist/browser/modules/word/excel.d.ts +14 -0
  111. package/dist/browser/modules/word/excel.js +13 -0
  112. package/dist/browser/modules/word/font/font-embed.d.ts +112 -0
  113. package/dist/browser/modules/word/font/font-embed.js +646 -0
  114. package/dist/{esm/modules/word → browser/modules/word/font}/font-obfuscation.js +4 -9
  115. package/dist/browser/modules/word/font/hyphenation.d.ts +65 -0
  116. package/dist/browser/modules/word/font/hyphenation.js +4210 -0
  117. package/dist/browser/modules/word/font/text-shaping.d.ts +58 -0
  118. package/dist/browser/modules/word/font/text-shaping.js +635 -0
  119. package/dist/browser/modules/word/html.d.ts +7 -6
  120. package/dist/browser/modules/word/html.js +6 -5
  121. package/dist/browser/modules/word/incremental-edit.d.ts +123 -0
  122. package/dist/browser/modules/word/incremental-edit.js +361 -0
  123. package/dist/browser/modules/word/index.base.d.ts +194 -10
  124. package/dist/browser/modules/word/index.base.js +138 -29
  125. package/dist/browser/modules/word/layout/layout-constants.d.ts +17 -0
  126. package/dist/browser/modules/word/layout/layout-constants.js +17 -0
  127. package/dist/browser/modules/word/layout/layout-full.d.ts +53 -0
  128. package/dist/browser/modules/word/layout/layout-full.js +1696 -0
  129. package/dist/browser/modules/word/layout/layout-model.d.ts +344 -0
  130. package/dist/browser/modules/word/layout/layout-model.js +16 -0
  131. package/dist/browser/modules/word/layout/layout.d.ts +63 -0
  132. package/dist/browser/modules/word/layout/layout.js +1167 -0
  133. package/dist/browser/modules/word/layout/render-page.d.ts +57 -0
  134. package/dist/browser/modules/word/layout/render-page.js +1238 -0
  135. package/dist/browser/modules/word/markdown.d.ts +14 -0
  136. package/dist/browser/modules/word/markdown.js +13 -0
  137. package/dist/browser/modules/word/patcher.d.ts +62 -0
  138. package/dist/browser/modules/word/patcher.js +537 -0
  139. package/dist/browser/modules/word/query/compat.d.ts +25 -0
  140. package/dist/browser/modules/word/query/compat.js +58 -0
  141. package/dist/browser/modules/word/query/data-binding.d.ts +22 -0
  142. package/dist/browser/modules/word/query/data-binding.js +392 -0
  143. package/dist/browser/modules/word/query/form-fields.d.ts +41 -0
  144. package/dist/browser/modules/word/query/form-fields.js +268 -0
  145. package/dist/browser/modules/word/query/format-search.d.ts +99 -0
  146. package/dist/browser/modules/word/query/format-search.js +329 -0
  147. package/dist/browser/modules/word/query/mail-merge.d.ts +25 -0
  148. package/dist/browser/modules/word/query/mail-merge.js +111 -0
  149. package/dist/browser/modules/word/query/merge.d.ts +50 -0
  150. package/dist/browser/modules/word/query/merge.js +617 -0
  151. package/dist/browser/modules/word/query/replace.d.ts +47 -0
  152. package/dist/browser/modules/word/query/replace.js +301 -0
  153. package/dist/browser/modules/word/query/revisions.d.ts +67 -0
  154. package/dist/browser/modules/word/query/revisions.js +879 -0
  155. package/dist/browser/modules/word/query/search.d.ts +129 -0
  156. package/dist/browser/modules/word/query/search.js +346 -0
  157. package/dist/browser/modules/word/query/split.d.ts +44 -0
  158. package/dist/browser/modules/word/query/split.js +135 -0
  159. package/dist/browser/modules/word/query/style-resolve.d.ts +104 -0
  160. package/dist/browser/modules/word/query/style-resolve.js +368 -0
  161. package/dist/browser/modules/word/reader/chart-parser.d.ts +20 -0
  162. package/dist/browser/modules/word/reader/chart-parser.js +810 -0
  163. package/dist/browser/modules/word/reader/comments-parser.d.ts +26 -0
  164. package/dist/browser/modules/word/reader/comments-parser.js +92 -0
  165. package/dist/browser/modules/word/reader/doc-props-parsers.d.ts +15 -0
  166. package/dist/browser/modules/word/reader/doc-props-parsers.js +190 -0
  167. package/dist/browser/modules/word/reader/docx-reader.d.ts +27 -0
  168. package/dist/browser/modules/word/reader/docx-reader.js +2557 -0
  169. package/dist/browser/modules/word/reader/drawing-helpers.d.ts +27 -0
  170. package/dist/browser/modules/word/reader/drawing-helpers.js +84 -0
  171. package/dist/browser/modules/word/reader/form-field-parser.d.ts +21 -0
  172. package/dist/browser/modules/word/reader/form-field-parser.js +82 -0
  173. package/dist/browser/modules/word/reader/image-parsers.d.ts +11 -0
  174. package/dist/browser/modules/word/reader/image-parsers.js +291 -0
  175. package/dist/browser/modules/word/reader/math-parser.d.ts +12 -0
  176. package/dist/browser/modules/word/reader/math-parser.js +422 -0
  177. package/dist/browser/modules/word/reader/metadata-parsers.d.ts +17 -0
  178. package/dist/browser/modules/word/reader/metadata-parsers.js +87 -0
  179. package/dist/browser/modules/word/reader/numbering-parser.d.ts +13 -0
  180. package/dist/browser/modules/word/reader/numbering-parser.js +166 -0
  181. package/dist/browser/modules/word/reader/paragraph-section-parsers.d.ts +12 -0
  182. package/dist/browser/modules/word/reader/paragraph-section-parsers.js +503 -0
  183. package/dist/browser/modules/word/reader/parse-utils.d.ts +91 -0
  184. package/dist/browser/modules/word/reader/parse-utils.js +249 -0
  185. package/dist/browser/modules/word/reader/properties-parsers.d.ts +21 -0
  186. package/dist/browser/modules/word/reader/properties-parsers.js +332 -0
  187. package/dist/browser/modules/word/reader/reader-context.d.ts +69 -0
  188. package/dist/browser/modules/word/reader/reader-context.js +61 -0
  189. package/dist/browser/modules/word/reader/sdt-helpers.d.ts +29 -0
  190. package/dist/browser/modules/word/reader/sdt-helpers.js +111 -0
  191. package/dist/browser/modules/word/reader/settings-parser.d.ts +8 -0
  192. package/dist/browser/modules/word/reader/settings-parser.js +263 -0
  193. package/dist/browser/modules/word/reader/styles-parser.d.ts +12 -0
  194. package/dist/browser/modules/word/reader/styles-parser.js +147 -0
  195. package/dist/browser/modules/word/reader/table-properties-parsers.d.ts +12 -0
  196. package/dist/browser/modules/word/reader/table-properties-parsers.js +234 -0
  197. package/dist/browser/modules/word/reader/theme-parser.d.ts +8 -0
  198. package/dist/browser/modules/word/reader/theme-parser.js +167 -0
  199. package/dist/browser/modules/word/reader/watermark-parser.d.ts +15 -0
  200. package/dist/browser/modules/word/reader/watermark-parser.js +110 -0
  201. package/dist/browser/modules/word/security/cfb-reader.d.ts +37 -0
  202. package/dist/browser/modules/word/security/cfb-reader.js +410 -0
  203. package/dist/browser/modules/word/{digital-signatures.d.ts → security/digital-signatures.d.ts} +19 -11
  204. package/dist/browser/modules/word/{digital-signatures.js → security/digital-signatures.js} +34 -34
  205. package/dist/browser/modules/word/security/document-protection.d.ts +93 -0
  206. package/dist/browser/modules/word/security/document-protection.js +201 -0
  207. package/dist/{types/modules/word → browser/modules/word/security}/encryption.d.ts +51 -4
  208. package/dist/browser/modules/word/security/encryption.js +602 -0
  209. package/dist/browser/modules/word/security/policy.d.ts +80 -0
  210. package/dist/browser/modules/word/security/policy.js +102 -0
  211. package/dist/browser/modules/word/template/template-chart.d.ts +56 -0
  212. package/dist/browser/modules/word/template/template-chart.js +167 -0
  213. package/dist/browser/modules/word/template/template-datasource.d.ts +154 -0
  214. package/dist/browser/modules/word/template/template-datasource.js +541 -0
  215. package/dist/browser/modules/word/template/template-engine.d.ts +121 -0
  216. package/dist/browser/modules/word/template/template-engine.js +1435 -0
  217. package/dist/browser/modules/word/types.d.ts +224 -25
  218. package/dist/browser/modules/word/units.d.ts +26 -0
  219. package/dist/browser/modules/word/units.js +43 -14
  220. package/dist/browser/modules/word/{writers → writer}/chart-writer.js +164 -23
  221. package/dist/browser/modules/word/writer/checkbox-writer.d.ts +17 -0
  222. package/dist/browser/modules/word/writer/checkbox-writer.js +79 -0
  223. package/dist/{types/modules/word/writers → browser/modules/word/writer}/comment-writer.d.ts +2 -1
  224. package/dist/browser/modules/word/{writers → writer}/comment-writer.js +8 -6
  225. package/dist/browser/modules/word/writer/common-parts.d.ts +57 -0
  226. package/dist/browser/modules/word/writer/common-parts.js +101 -0
  227. package/dist/{types/modules/word → browser/modules/word/writer}/content-types.d.ts +2 -2
  228. package/dist/{esm/modules/word → browser/modules/word/writer}/content-types.js +14 -6
  229. package/dist/browser/modules/word/writer/document-writer.d.ts +24 -0
  230. package/dist/browser/modules/word/writer/document-writer.js +473 -0
  231. package/dist/browser/modules/word/writer/docx-packager.d.ts +35 -0
  232. package/dist/browser/modules/word/writer/docx-packager.js +1515 -0
  233. package/dist/{types/modules/word/writers → browser/modules/word/writer}/footnote-writer.d.ts +3 -2
  234. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/footnote-writer.js +13 -10
  235. package/dist/{types/modules/word/writers → browser/modules/word/writer}/header-footer-writer.d.ts +3 -2
  236. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/header-footer-writer.js +39 -21
  237. package/dist/{types/modules/word/writers → browser/modules/word/writer}/image-writer.d.ts +1 -1
  238. package/dist/browser/modules/word/{writers → writer}/image-writer.js +11 -7
  239. package/dist/browser/modules/word/writer/math-writer.d.ts +20 -0
  240. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/math-writer.js +21 -1
  241. package/dist/browser/modules/word/{writers → writer}/numbering-writer.d.ts +1 -1
  242. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/numbering-writer.js +11 -4
  243. package/dist/browser/modules/word/{writers → writer}/paragraph-writer.d.ts +2 -1
  244. package/dist/browser/modules/word/{writers → writer}/paragraph-writer.js +73 -38
  245. package/dist/browser/modules/word/{writers → writer}/parts-writer.d.ts +3 -3
  246. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/parts-writer.js +91 -12
  247. package/dist/browser/modules/word/writer/reference-scanners.d.ts +42 -0
  248. package/dist/browser/modules/word/writer/reference-scanners.js +111 -0
  249. package/dist/browser/modules/word/writer/relationships.d.ts +52 -0
  250. package/dist/browser/modules/word/writer/relationships.js +117 -0
  251. package/dist/browser/modules/word/writer/render-context.d.ts +124 -0
  252. package/dist/browser/modules/word/writer/render-context.js +46 -0
  253. package/dist/browser/modules/word/{writers → writer}/run-writer.d.ts +10 -1
  254. package/dist/{esm/modules/word/writers → browser/modules/word/writer}/run-writer.js +126 -24
  255. package/dist/browser/modules/word/writer/sdt-writer.d.ts +25 -0
  256. package/dist/browser/modules/word/writer/sdt-writer.js +189 -0
  257. package/dist/browser/modules/word/writer/stream-buf.d.ts +37 -0
  258. package/dist/browser/modules/word/writer/stream-buf.js +73 -0
  259. package/dist/browser/modules/word/writer/streaming-writer.d.ts +344 -0
  260. package/dist/browser/modules/word/writer/streaming-writer.js +1382 -0
  261. package/dist/browser/modules/word/writer/string-buf.d.ts +8 -0
  262. package/dist/browser/modules/word/writer/string-buf.js +7 -0
  263. package/dist/browser/modules/word/{writers → writer}/styles-writer.js +32 -1
  264. package/dist/browser/modules/word/{writers → writer}/table-writer.d.ts +2 -1
  265. package/dist/browser/modules/word/{writers → writer}/table-writer.js +94 -11
  266. package/dist/browser/modules/xml/types.d.ts +22 -0
  267. package/dist/browser/utils/crypto.browser.d.ts +3 -1
  268. package/dist/browser/utils/crypto.browser.js +3 -1
  269. package/dist/browser/utils/crypto.d.ts +4 -1
  270. package/dist/browser/utils/crypto.js +4 -1
  271. package/dist/browser/utils/font-metrics.d.ts +63 -0
  272. package/dist/browser/utils/font-metrics.js +293 -0
  273. package/dist/browser/utils/string-buf.d.ts +42 -0
  274. package/dist/browser/utils/string-buf.js +89 -0
  275. package/dist/browser/utils/theme-colors.d.ts +55 -0
  276. package/dist/browser/utils/theme-colors.js +120 -0
  277. package/dist/cjs/modules/archive/compression/streaming-compress.browser.js +29 -0
  278. package/dist/cjs/modules/archive/compression/streaming-compress.js +9 -0
  279. package/dist/cjs/modules/archive/compression/worker-pool/pool.browser.js +26 -1
  280. package/dist/cjs/modules/archive/fs/archive-file.js +78 -16
  281. package/dist/cjs/modules/archive/unzip/stream.browser.js +43 -2
  282. package/dist/cjs/modules/excel/chart/chart-ex-builder.js +7 -2
  283. package/dist/cjs/modules/excel/chart/chart-ex-renderer.js +4 -9
  284. package/dist/cjs/modules/excel/chart/chart.js +1 -7
  285. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +25 -1
  286. package/dist/cjs/modules/excel/stream/workbook-reader.js +9 -0
  287. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +228 -13
  288. package/dist/cjs/modules/excel/utils/string-buf.js +5 -81
  289. package/dist/cjs/modules/excel/workbook.browser.js +135 -25
  290. package/dist/cjs/modules/excel/xlsx/xform/chart/chart-space-xform.js +6 -20
  291. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +32 -8
  292. package/dist/cjs/modules/excel/xlsx/xlsx.js +9 -1
  293. package/dist/cjs/modules/pdf/excel-bridge.js +33 -0
  294. package/dist/cjs/modules/pdf/font/metrics.js +11 -244
  295. package/dist/cjs/modules/pdf/index.js +2 -1
  296. package/dist/cjs/modules/pdf/render-layout-to-pdf.js +651 -0
  297. package/dist/cjs/modules/pdf/word-bridge.js +155 -274
  298. package/dist/cjs/modules/stream/index.base.js +4 -2
  299. package/dist/cjs/modules/stream/internal/sink-adapter.js +202 -0
  300. package/dist/cjs/modules/stream/pull-stream.js +51 -5
  301. package/dist/cjs/modules/word/advanced/diff.js +170 -0
  302. package/dist/cjs/modules/word/advanced/drawing-shapes.js +279 -0
  303. package/dist/cjs/modules/word/advanced/field-engine.js +1229 -0
  304. package/dist/cjs/modules/word/advanced/glossary.js +87 -0
  305. package/dist/cjs/modules/word/advanced/math-convert.js +599 -0
  306. package/dist/cjs/modules/word/advanced/ole-objects.js +277 -0
  307. package/dist/cjs/modules/word/advanced/style-map.js +329 -0
  308. package/dist/cjs/modules/word/advanced/validation.js +1068 -0
  309. package/dist/cjs/modules/word/advanced/vba-project.js +274 -0
  310. package/dist/cjs/modules/word/bridge/excel-bridge.js +1020 -0
  311. package/dist/cjs/modules/word/builder/document-handle.js +667 -0
  312. package/dist/cjs/modules/word/builder/paragraph-builders.js +109 -0
  313. package/dist/cjs/modules/word/builder/run-builders.js +676 -0
  314. package/dist/cjs/modules/word/builder/table-builders.js +53 -0
  315. package/dist/cjs/modules/word/constants.js +111 -2
  316. package/dist/cjs/modules/word/convert/conversion-ir.js +34 -0
  317. package/dist/cjs/modules/word/convert/docx-to-semantic.js +502 -0
  318. package/dist/cjs/modules/word/convert/flat-opc.js +390 -0
  319. package/dist/cjs/modules/word/convert/html/html-import.js +1910 -0
  320. package/dist/cjs/modules/word/{html-renderer.js → convert/html/html-renderer.js} +420 -69
  321. package/dist/cjs/modules/word/convert/html/html.js +20 -0
  322. package/dist/cjs/modules/word/convert/markdown/markdown-import.js +1329 -0
  323. package/dist/cjs/modules/word/convert/markdown/markdown-renderer.js +637 -0
  324. package/dist/cjs/modules/word/convert/markdown/markdown.js +21 -0
  325. package/dist/cjs/modules/word/convert/odt/odt.js +1936 -0
  326. package/dist/cjs/modules/word/core/color-utils.js +47 -0
  327. package/dist/cjs/modules/word/core/internal-utils.js +219 -0
  328. package/dist/cjs/modules/word/core/mapper.js +430 -0
  329. package/dist/cjs/modules/word/core/opc-paths.js +53 -0
  330. package/dist/cjs/modules/word/core/text-utils.js +210 -0
  331. package/dist/cjs/modules/word/core/walker.js +577 -0
  332. package/dist/cjs/modules/word/crypto.js +19 -8
  333. package/dist/cjs/modules/word/document-io.js +117 -197
  334. package/dist/cjs/modules/word/errors.js +59 -13
  335. package/dist/cjs/modules/word/excel.js +22 -0
  336. package/dist/cjs/modules/word/font/font-embed.js +652 -0
  337. package/dist/cjs/modules/word/{font-obfuscation.js → font/font-obfuscation.js} +4 -9
  338. package/dist/cjs/modules/word/font/hyphenation.js +4216 -0
  339. package/dist/cjs/modules/word/font/text-shaping.js +640 -0
  340. package/dist/cjs/modules/word/html.js +9 -7
  341. package/dist/cjs/modules/word/incremental-edit.js +366 -0
  342. package/dist/cjs/modules/word/index.base.js +370 -137
  343. package/dist/cjs/modules/word/layout/layout-constants.js +20 -0
  344. package/dist/cjs/modules/word/layout/layout-full.js +1699 -0
  345. package/dist/cjs/modules/word/layout/layout-model.js +17 -0
  346. package/dist/cjs/modules/word/layout/layout.js +1170 -0
  347. package/dist/cjs/modules/word/layout/render-page.js +1243 -0
  348. package/dist/cjs/modules/word/markdown.js +19 -0
  349. package/dist/cjs/modules/word/patcher.js +539 -0
  350. package/dist/cjs/modules/word/query/compat.js +61 -0
  351. package/dist/cjs/modules/word/query/data-binding.js +395 -0
  352. package/dist/cjs/modules/word/query/form-fields.js +272 -0
  353. package/dist/cjs/modules/word/query/format-search.js +334 -0
  354. package/dist/cjs/modules/word/query/mail-merge.js +114 -0
  355. package/dist/cjs/modules/word/query/merge.js +620 -0
  356. package/dist/cjs/modules/word/query/replace.js +304 -0
  357. package/dist/cjs/modules/word/query/revisions.js +885 -0
  358. package/dist/cjs/modules/word/query/search.js +361 -0
  359. package/dist/cjs/modules/word/query/split.js +138 -0
  360. package/dist/cjs/modules/word/query/style-resolve.js +374 -0
  361. package/dist/cjs/modules/word/reader/chart-parser.js +814 -0
  362. package/dist/cjs/modules/word/reader/comments-parser.js +96 -0
  363. package/dist/cjs/modules/word/reader/doc-props-parsers.js +194 -0
  364. package/dist/cjs/modules/word/reader/docx-reader.js +2560 -0
  365. package/dist/cjs/modules/word/reader/drawing-helpers.js +90 -0
  366. package/dist/cjs/modules/word/reader/form-field-parser.js +85 -0
  367. package/dist/cjs/modules/word/reader/image-parsers.js +293 -0
  368. package/dist/cjs/modules/word/reader/math-parser.js +424 -0
  369. package/dist/cjs/modules/word/reader/metadata-parsers.js +93 -0
  370. package/dist/cjs/modules/word/reader/numbering-parser.js +168 -0
  371. package/dist/cjs/modules/word/reader/paragraph-section-parsers.js +505 -0
  372. package/dist/cjs/modules/word/reader/parse-utils.js +271 -0
  373. package/dist/cjs/modules/word/reader/properties-parsers.js +338 -0
  374. package/dist/cjs/modules/word/reader/reader-context.js +66 -0
  375. package/dist/cjs/modules/word/reader/sdt-helpers.js +114 -0
  376. package/dist/cjs/modules/word/reader/settings-parser.js +265 -0
  377. package/dist/cjs/modules/word/reader/styles-parser.js +149 -0
  378. package/dist/cjs/modules/word/reader/table-properties-parsers.js +237 -0
  379. package/dist/cjs/modules/word/reader/theme-parser.js +169 -0
  380. package/dist/cjs/modules/word/reader/watermark-parser.js +113 -0
  381. package/dist/cjs/modules/word/security/cfb-reader.js +414 -0
  382. package/dist/cjs/modules/word/{digital-signatures.js → security/digital-signatures.js} +34 -34
  383. package/dist/cjs/modules/word/security/document-protection.js +208 -0
  384. package/dist/cjs/modules/word/security/encryption.js +612 -0
  385. package/dist/cjs/modules/word/security/policy.js +106 -0
  386. package/dist/cjs/modules/word/template/template-chart.js +170 -0
  387. package/dist/cjs/modules/word/template/template-datasource.js +549 -0
  388. package/dist/cjs/modules/word/template/template-engine.js +1430 -0
  389. package/dist/cjs/modules/word/units.js +44 -14
  390. package/dist/cjs/modules/word/{writers → writer}/chart-writer.js +163 -22
  391. package/dist/cjs/modules/word/writer/checkbox-writer.js +82 -0
  392. package/dist/cjs/modules/word/{writers → writer}/comment-writer.js +8 -6
  393. package/dist/cjs/modules/word/writer/common-parts.js +104 -0
  394. package/dist/cjs/modules/word/{content-types.js → writer/content-types.js} +14 -6
  395. package/dist/cjs/modules/word/writer/document-writer.js +478 -0
  396. package/dist/cjs/modules/word/writer/docx-packager.js +1551 -0
  397. package/dist/cjs/modules/word/{writers → writer}/footnote-writer.js +13 -10
  398. package/dist/cjs/modules/word/{writers → writer}/header-footer-writer.js +38 -20
  399. package/dist/cjs/modules/word/{writers → writer}/image-writer.js +11 -7
  400. package/dist/cjs/modules/word/{writers → writer}/math-writer.js +21 -1
  401. package/dist/cjs/modules/word/{writers → writer}/numbering-writer.js +11 -4
  402. package/dist/cjs/modules/word/{writers → writer}/paragraph-writer.js +72 -37
  403. package/dist/cjs/modules/word/{writers → writer}/parts-writer.js +91 -12
  404. package/dist/cjs/modules/word/writer/reference-scanners.js +120 -0
  405. package/dist/cjs/modules/word/writer/relationships.js +124 -0
  406. package/dist/cjs/modules/word/writer/render-context.js +51 -0
  407. package/dist/cjs/modules/word/{writers → writer}/run-writer.js +127 -24
  408. package/dist/cjs/modules/word/writer/sdt-writer.js +192 -0
  409. package/dist/cjs/modules/word/writer/stream-buf.js +76 -0
  410. package/dist/cjs/modules/word/writer/streaming-writer.js +1387 -0
  411. package/dist/cjs/modules/word/writer/string-buf.js +11 -0
  412. package/dist/cjs/modules/word/{writers → writer}/styles-writer.js +32 -1
  413. package/dist/cjs/modules/word/{writers → writer}/table-writer.js +94 -11
  414. package/dist/cjs/utils/crypto.browser.js +3 -1
  415. package/dist/cjs/utils/crypto.js +4 -1
  416. package/dist/cjs/utils/font-metrics.js +303 -0
  417. package/dist/cjs/utils/string-buf.js +92 -0
  418. package/dist/cjs/utils/theme-colors.js +126 -0
  419. package/dist/esm/modules/archive/compression/streaming-compress.browser.js +29 -0
  420. package/dist/esm/modules/archive/compression/streaming-compress.js +9 -0
  421. package/dist/esm/modules/archive/compression/worker-pool/pool.browser.js +26 -1
  422. package/dist/esm/modules/archive/fs/archive-file.js +78 -16
  423. package/dist/esm/modules/archive/unzip/stream.browser.js +43 -2
  424. package/dist/esm/modules/excel/chart/chart-ex-builder.js +7 -2
  425. package/dist/esm/modules/excel/chart/chart-ex-renderer.js +4 -9
  426. package/dist/esm/modules/excel/chart/chart.js +1 -7
  427. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +25 -1
  428. package/dist/esm/modules/excel/stream/workbook-reader.js +9 -0
  429. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +228 -13
  430. package/dist/esm/modules/excel/utils/string-buf.js +4 -81
  431. package/dist/esm/modules/excel/workbook.browser.js +135 -25
  432. package/dist/esm/modules/excel/xlsx/xform/chart/chart-space-xform.js +6 -20
  433. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +32 -8
  434. package/dist/esm/modules/excel/xlsx/xlsx.js +9 -1
  435. package/dist/esm/modules/pdf/excel-bridge.js +32 -0
  436. package/dist/esm/modules/pdf/font/metrics.js +3 -237
  437. package/dist/esm/modules/pdf/index.js +1 -1
  438. package/dist/esm/modules/pdf/render-layout-to-pdf.js +647 -0
  439. package/dist/esm/modules/pdf/word-bridge.js +122 -274
  440. package/dist/esm/modules/stream/index.base.js +2 -1
  441. package/dist/esm/modules/stream/internal/sink-adapter.js +198 -0
  442. package/dist/esm/modules/stream/pull-stream.js +51 -5
  443. package/dist/esm/modules/word/advanced/diff.js +167 -0
  444. package/dist/esm/modules/word/advanced/drawing-shapes.js +268 -0
  445. package/dist/esm/modules/word/advanced/field-engine.js +1225 -0
  446. package/dist/esm/modules/word/advanced/glossary.js +79 -0
  447. package/dist/esm/modules/word/advanced/math-convert.js +595 -0
  448. package/dist/esm/modules/word/advanced/ole-objects.js +271 -0
  449. package/dist/esm/modules/word/advanced/style-map.js +322 -0
  450. package/dist/esm/modules/word/advanced/validation.js +1065 -0
  451. package/dist/esm/modules/word/advanced/vba-project.js +265 -0
  452. package/dist/esm/modules/word/bridge/excel-bridge.js +980 -0
  453. package/dist/esm/modules/word/builder/document-handle.js +664 -0
  454. package/dist/esm/modules/word/builder/paragraph-builders.js +90 -0
  455. package/dist/esm/modules/word/builder/run-builders.js +600 -0
  456. package/dist/esm/modules/word/builder/table-builders.js +45 -0
  457. package/dist/esm/modules/word/constants.js +109 -1
  458. package/dist/esm/modules/word/convert/conversion-ir.js +31 -0
  459. package/dist/esm/modules/word/convert/docx-to-semantic.js +499 -0
  460. package/dist/esm/modules/word/convert/flat-opc.js +385 -0
  461. package/dist/esm/modules/word/convert/html/html-import.js +1907 -0
  462. package/dist/{browser/modules/word → esm/modules/word/convert/html}/html-renderer.js +420 -69
  463. package/dist/esm/modules/word/convert/html/html.js +15 -0
  464. package/dist/esm/modules/word/convert/markdown/markdown-import.js +1325 -0
  465. package/dist/esm/modules/word/convert/markdown/markdown-renderer.js +634 -0
  466. package/dist/esm/modules/word/convert/markdown/markdown.js +15 -0
  467. package/dist/esm/modules/word/convert/odt/odt.js +1932 -0
  468. package/dist/esm/modules/word/core/color-utils.js +43 -0
  469. package/dist/esm/modules/word/core/internal-utils.js +209 -0
  470. package/dist/esm/modules/word/core/mapper.js +427 -0
  471. package/dist/esm/modules/word/core/opc-paths.js +48 -0
  472. package/dist/esm/modules/word/core/text-utils.js +202 -0
  473. package/dist/esm/modules/word/core/walker.js +570 -0
  474. package/dist/esm/modules/word/crypto.js +13 -7
  475. package/dist/esm/modules/word/document-io.js +80 -197
  476. package/dist/esm/modules/word/errors.js +54 -2
  477. package/dist/esm/modules/word/excel.js +13 -0
  478. package/dist/esm/modules/word/font/font-embed.js +646 -0
  479. package/dist/{browser/modules/word → esm/modules/word/font}/font-obfuscation.js +4 -9
  480. package/dist/esm/modules/word/font/hyphenation.js +4210 -0
  481. package/dist/esm/modules/word/font/text-shaping.js +635 -0
  482. package/dist/esm/modules/word/html.js +6 -5
  483. package/dist/esm/modules/word/incremental-edit.js +361 -0
  484. package/dist/esm/modules/word/index.base.js +138 -29
  485. package/dist/esm/modules/word/layout/layout-constants.js +17 -0
  486. package/dist/esm/modules/word/layout/layout-full.js +1696 -0
  487. package/dist/esm/modules/word/layout/layout-model.js +16 -0
  488. package/dist/esm/modules/word/layout/layout.js +1167 -0
  489. package/dist/esm/modules/word/layout/render-page.js +1238 -0
  490. package/dist/esm/modules/word/markdown.js +13 -0
  491. package/dist/esm/modules/word/patcher.js +537 -0
  492. package/dist/esm/modules/word/query/compat.js +58 -0
  493. package/dist/esm/modules/word/query/data-binding.js +392 -0
  494. package/dist/esm/modules/word/query/form-fields.js +268 -0
  495. package/dist/esm/modules/word/query/format-search.js +329 -0
  496. package/dist/esm/modules/word/query/mail-merge.js +111 -0
  497. package/dist/esm/modules/word/query/merge.js +617 -0
  498. package/dist/esm/modules/word/query/replace.js +301 -0
  499. package/dist/esm/modules/word/query/revisions.js +879 -0
  500. package/dist/esm/modules/word/query/search.js +346 -0
  501. package/dist/esm/modules/word/query/split.js +135 -0
  502. package/dist/esm/modules/word/query/style-resolve.js +368 -0
  503. package/dist/esm/modules/word/reader/chart-parser.js +810 -0
  504. package/dist/esm/modules/word/reader/comments-parser.js +92 -0
  505. package/dist/esm/modules/word/reader/doc-props-parsers.js +190 -0
  506. package/dist/esm/modules/word/reader/docx-reader.js +2557 -0
  507. package/dist/esm/modules/word/reader/drawing-helpers.js +84 -0
  508. package/dist/esm/modules/word/reader/form-field-parser.js +82 -0
  509. package/dist/esm/modules/word/reader/image-parsers.js +291 -0
  510. package/dist/esm/modules/word/reader/math-parser.js +422 -0
  511. package/dist/esm/modules/word/reader/metadata-parsers.js +87 -0
  512. package/dist/esm/modules/word/reader/numbering-parser.js +166 -0
  513. package/dist/esm/modules/word/reader/paragraph-section-parsers.js +503 -0
  514. package/dist/esm/modules/word/reader/parse-utils.js +249 -0
  515. package/dist/esm/modules/word/reader/properties-parsers.js +332 -0
  516. package/dist/esm/modules/word/reader/reader-context.js +61 -0
  517. package/dist/esm/modules/word/reader/sdt-helpers.js +111 -0
  518. package/dist/esm/modules/word/reader/settings-parser.js +263 -0
  519. package/dist/esm/modules/word/reader/styles-parser.js +147 -0
  520. package/dist/esm/modules/word/reader/table-properties-parsers.js +234 -0
  521. package/dist/esm/modules/word/reader/theme-parser.js +167 -0
  522. package/dist/esm/modules/word/reader/watermark-parser.js +110 -0
  523. package/dist/esm/modules/word/security/cfb-reader.js +410 -0
  524. package/dist/esm/modules/word/{digital-signatures.js → security/digital-signatures.js} +34 -34
  525. package/dist/esm/modules/word/security/document-protection.js +201 -0
  526. package/dist/esm/modules/word/security/encryption.js +602 -0
  527. package/dist/esm/modules/word/security/policy.js +102 -0
  528. package/dist/esm/modules/word/template/template-chart.js +167 -0
  529. package/dist/esm/modules/word/template/template-datasource.js +541 -0
  530. package/dist/esm/modules/word/template/template-engine.js +1435 -0
  531. package/dist/esm/modules/word/units.js +43 -14
  532. package/dist/esm/modules/word/{writers → writer}/chart-writer.js +164 -23
  533. package/dist/esm/modules/word/writer/checkbox-writer.js +79 -0
  534. package/dist/esm/modules/word/{writers → writer}/comment-writer.js +8 -6
  535. package/dist/esm/modules/word/writer/common-parts.js +101 -0
  536. package/dist/{browser/modules/word → esm/modules/word/writer}/content-types.js +14 -6
  537. package/dist/esm/modules/word/writer/document-writer.js +473 -0
  538. package/dist/esm/modules/word/writer/docx-packager.js +1515 -0
  539. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/footnote-writer.js +13 -10
  540. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/header-footer-writer.js +39 -21
  541. package/dist/esm/modules/word/{writers → writer}/image-writer.js +11 -7
  542. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/math-writer.js +21 -1
  543. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/numbering-writer.js +11 -4
  544. package/dist/esm/modules/word/{writers → writer}/paragraph-writer.js +73 -38
  545. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/parts-writer.js +91 -12
  546. package/dist/esm/modules/word/writer/reference-scanners.js +111 -0
  547. package/dist/esm/modules/word/writer/relationships.js +117 -0
  548. package/dist/esm/modules/word/writer/render-context.js +46 -0
  549. package/dist/{browser/modules/word/writers → esm/modules/word/writer}/run-writer.js +126 -24
  550. package/dist/esm/modules/word/writer/sdt-writer.js +189 -0
  551. package/dist/esm/modules/word/writer/stream-buf.js +73 -0
  552. package/dist/esm/modules/word/writer/streaming-writer.js +1382 -0
  553. package/dist/esm/modules/word/writer/string-buf.js +7 -0
  554. package/dist/esm/modules/word/{writers → writer}/styles-writer.js +32 -1
  555. package/dist/esm/modules/word/{writers → writer}/table-writer.js +94 -11
  556. package/dist/esm/utils/crypto.browser.js +3 -1
  557. package/dist/esm/utils/crypto.js +4 -1
  558. package/dist/esm/utils/font-metrics.js +293 -0
  559. package/dist/esm/utils/string-buf.js +89 -0
  560. package/dist/esm/utils/theme-colors.js +120 -0
  561. package/dist/iife/excelts.iife.js +70692 -70337
  562. package/dist/iife/excelts.iife.js.map +1 -1
  563. package/dist/iife/excelts.iife.min.js +57 -57
  564. package/dist/types/modules/archive/fs/archive-file.d.ts +8 -5
  565. package/dist/types/modules/excel/chart/chart-ex-types.d.ts +0 -12
  566. package/dist/types/modules/excel/chart/chart.d.ts +1 -5
  567. package/dist/types/modules/excel/chart/types.d.ts +0 -6
  568. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +40 -0
  569. package/dist/types/modules/excel/utils/string-buf.d.ts +5 -26
  570. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +19 -9
  571. package/dist/types/modules/excel/xlsx/xlsx.d.ts +10 -2
  572. package/dist/types/modules/pdf/excel-bridge.d.ts +30 -1
  573. package/dist/types/modules/pdf/font/metrics.d.ts +3 -52
  574. package/dist/types/modules/pdf/index.d.ts +1 -1
  575. package/dist/types/modules/pdf/render-layout-to-pdf.d.ts +66 -0
  576. package/dist/types/modules/pdf/word-bridge.d.ts +80 -12
  577. package/dist/types/modules/stream/index.base.d.ts +2 -0
  578. package/dist/types/modules/stream/internal/sink-adapter.d.ts +65 -0
  579. package/dist/types/modules/stream/pull-stream.d.ts +19 -2
  580. package/dist/types/modules/stream/types.d.ts +13 -1
  581. package/dist/types/modules/word/advanced/diff.d.ts +61 -0
  582. package/dist/types/modules/word/advanced/drawing-shapes.d.ts +269 -0
  583. package/dist/types/modules/word/advanced/field-engine.d.ts +43 -0
  584. package/dist/types/modules/word/advanced/glossary.d.ts +86 -0
  585. package/dist/types/modules/word/advanced/math-convert.d.ts +30 -0
  586. package/dist/types/modules/word/advanced/ole-objects.d.ts +115 -0
  587. package/dist/types/modules/word/advanced/style-map.d.ts +105 -0
  588. package/dist/types/modules/word/advanced/validation.d.ts +56 -0
  589. package/dist/types/modules/word/advanced/vba-project.d.ts +91 -0
  590. package/dist/types/modules/word/bridge/excel-bridge.d.ts +127 -0
  591. package/dist/types/modules/word/builder/document-handle.d.ts +151 -0
  592. package/dist/types/modules/word/builder/paragraph-builders.d.ts +61 -0
  593. package/dist/types/modules/word/builder/run-builders.d.ts +374 -0
  594. package/dist/types/modules/word/builder/table-builders.d.ts +23 -0
  595. package/dist/types/modules/word/constants.d.ts +39 -1
  596. package/dist/types/modules/word/convert/conversion-ir.d.ts +210 -0
  597. package/dist/types/modules/word/convert/docx-to-semantic.d.ts +39 -0
  598. package/dist/types/modules/word/convert/flat-opc.d.ts +44 -0
  599. package/dist/types/modules/word/convert/html/html-import.d.ts +50 -0
  600. package/dist/{browser/modules/word → types/modules/word/convert/html}/html-renderer.d.ts +14 -1
  601. package/dist/types/modules/word/convert/html/html.d.ts +15 -0
  602. package/dist/types/modules/word/convert/markdown/markdown-import.d.ts +68 -0
  603. package/dist/types/modules/word/convert/markdown/markdown-renderer.d.ts +25 -0
  604. package/dist/types/modules/word/convert/markdown/markdown.d.ts +15 -0
  605. package/dist/types/modules/word/convert/odt/odt.d.ts +41 -0
  606. package/dist/types/modules/word/{color-utils.d.ts → core/color-utils.d.ts} +8 -1
  607. package/dist/types/modules/word/core/internal-utils.d.ts +90 -0
  608. package/dist/types/modules/word/core/mapper.d.ts +44 -0
  609. package/dist/types/modules/word/core/opc-paths.d.ts +33 -0
  610. package/dist/types/modules/word/core/text-utils.d.ts +38 -0
  611. package/dist/types/modules/word/core/walker.d.ts +119 -0
  612. package/dist/types/modules/word/crypto.d.ts +14 -9
  613. package/dist/types/modules/word/document-io.d.ts +59 -27
  614. package/dist/types/modules/word/errors.d.ts +44 -1
  615. package/dist/types/modules/word/excel.d.ts +14 -0
  616. package/dist/types/modules/word/font/font-embed.d.ts +112 -0
  617. package/dist/types/modules/word/font/hyphenation.d.ts +65 -0
  618. package/dist/types/modules/word/font/text-shaping.d.ts +58 -0
  619. package/dist/types/modules/word/html.d.ts +7 -6
  620. package/dist/types/modules/word/incremental-edit.d.ts +123 -0
  621. package/dist/types/modules/word/index.base.d.ts +194 -10
  622. package/dist/types/modules/word/layout/layout-constants.d.ts +17 -0
  623. package/dist/types/modules/word/layout/layout-full.d.ts +53 -0
  624. package/dist/types/modules/word/layout/layout-model.d.ts +344 -0
  625. package/dist/types/modules/word/layout/layout.d.ts +63 -0
  626. package/dist/types/modules/word/layout/render-page.d.ts +57 -0
  627. package/dist/types/modules/word/markdown.d.ts +14 -0
  628. package/dist/types/modules/word/patcher.d.ts +62 -0
  629. package/dist/types/modules/word/query/compat.d.ts +25 -0
  630. package/dist/types/modules/word/query/data-binding.d.ts +22 -0
  631. package/dist/types/modules/word/query/form-fields.d.ts +41 -0
  632. package/dist/types/modules/word/query/format-search.d.ts +99 -0
  633. package/dist/types/modules/word/query/mail-merge.d.ts +25 -0
  634. package/dist/types/modules/word/query/merge.d.ts +50 -0
  635. package/dist/types/modules/word/query/replace.d.ts +47 -0
  636. package/dist/types/modules/word/query/revisions.d.ts +67 -0
  637. package/dist/types/modules/word/query/search.d.ts +129 -0
  638. package/dist/types/modules/word/query/split.d.ts +44 -0
  639. package/dist/types/modules/word/query/style-resolve.d.ts +104 -0
  640. package/dist/types/modules/word/reader/chart-parser.d.ts +20 -0
  641. package/dist/types/modules/word/reader/comments-parser.d.ts +26 -0
  642. package/dist/types/modules/word/reader/doc-props-parsers.d.ts +15 -0
  643. package/dist/types/modules/word/reader/docx-reader.d.ts +27 -0
  644. package/dist/types/modules/word/reader/drawing-helpers.d.ts +27 -0
  645. package/dist/types/modules/word/reader/form-field-parser.d.ts +21 -0
  646. package/dist/types/modules/word/reader/image-parsers.d.ts +11 -0
  647. package/dist/types/modules/word/reader/math-parser.d.ts +12 -0
  648. package/dist/types/modules/word/reader/metadata-parsers.d.ts +17 -0
  649. package/dist/types/modules/word/reader/numbering-parser.d.ts +13 -0
  650. package/dist/types/modules/word/reader/paragraph-section-parsers.d.ts +12 -0
  651. package/dist/types/modules/word/reader/parse-utils.d.ts +91 -0
  652. package/dist/types/modules/word/reader/properties-parsers.d.ts +21 -0
  653. package/dist/types/modules/word/reader/reader-context.d.ts +69 -0
  654. package/dist/types/modules/word/reader/sdt-helpers.d.ts +29 -0
  655. package/dist/types/modules/word/reader/settings-parser.d.ts +8 -0
  656. package/dist/types/modules/word/reader/styles-parser.d.ts +12 -0
  657. package/dist/types/modules/word/reader/table-properties-parsers.d.ts +12 -0
  658. package/dist/types/modules/word/reader/theme-parser.d.ts +8 -0
  659. package/dist/types/modules/word/reader/watermark-parser.d.ts +15 -0
  660. package/dist/types/modules/word/security/cfb-reader.d.ts +37 -0
  661. package/dist/types/modules/word/{digital-signatures.d.ts → security/digital-signatures.d.ts} +19 -11
  662. package/dist/types/modules/word/security/document-protection.d.ts +93 -0
  663. package/dist/{browser/modules/word → types/modules/word/security}/encryption.d.ts +51 -4
  664. package/dist/types/modules/word/security/policy.d.ts +80 -0
  665. package/dist/types/modules/word/template/template-chart.d.ts +56 -0
  666. package/dist/types/modules/word/template/template-datasource.d.ts +154 -0
  667. package/dist/types/modules/word/template/template-engine.d.ts +121 -0
  668. package/dist/types/modules/word/types.d.ts +224 -25
  669. package/dist/types/modules/word/units.d.ts +26 -0
  670. package/dist/types/modules/word/writer/checkbox-writer.d.ts +17 -0
  671. package/dist/{browser/modules/word/writers → types/modules/word/writer}/comment-writer.d.ts +2 -1
  672. package/dist/types/modules/word/writer/common-parts.d.ts +57 -0
  673. package/dist/{browser/modules/word → types/modules/word/writer}/content-types.d.ts +2 -2
  674. package/dist/types/modules/word/writer/document-writer.d.ts +24 -0
  675. package/dist/types/modules/word/writer/docx-packager.d.ts +35 -0
  676. package/dist/{browser/modules/word/writers → types/modules/word/writer}/footnote-writer.d.ts +3 -2
  677. package/dist/{browser/modules/word/writers → types/modules/word/writer}/header-footer-writer.d.ts +3 -2
  678. package/dist/{browser/modules/word/writers → types/modules/word/writer}/image-writer.d.ts +1 -1
  679. package/dist/types/modules/word/writer/math-writer.d.ts +20 -0
  680. package/dist/types/modules/word/{writers → writer}/numbering-writer.d.ts +1 -1
  681. package/dist/types/modules/word/{writers → writer}/paragraph-writer.d.ts +2 -1
  682. package/dist/types/modules/word/{writers → writer}/parts-writer.d.ts +3 -3
  683. package/dist/types/modules/word/writer/reference-scanners.d.ts +42 -0
  684. package/dist/types/modules/word/writer/relationships.d.ts +52 -0
  685. package/dist/types/modules/word/writer/render-context.d.ts +124 -0
  686. package/dist/types/modules/word/{writers → writer}/run-writer.d.ts +10 -1
  687. package/dist/types/modules/word/writer/sdt-writer.d.ts +25 -0
  688. package/dist/types/modules/word/writer/stream-buf.d.ts +37 -0
  689. package/dist/types/modules/word/writer/streaming-writer.d.ts +344 -0
  690. package/dist/types/modules/word/writer/string-buf.d.ts +8 -0
  691. package/dist/types/modules/word/{writers → writer}/table-writer.d.ts +2 -1
  692. package/dist/types/modules/xml/types.d.ts +22 -0
  693. package/dist/types/utils/crypto.browser.d.ts +3 -1
  694. package/dist/types/utils/crypto.d.ts +4 -1
  695. package/dist/types/utils/font-metrics.d.ts +63 -0
  696. package/dist/types/utils/string-buf.d.ts +42 -0
  697. package/dist/types/utils/theme-colors.d.ts +55 -0
  698. package/package.json +121 -39
  699. package/dist/browser/modules/word/color-utils.js +0 -94
  700. package/dist/browser/modules/word/document.d.ts +0 -657
  701. package/dist/browser/modules/word/document.js +0 -1533
  702. package/dist/browser/modules/word/docx-packager.d.ts +0 -14
  703. package/dist/browser/modules/word/docx-packager.js +0 -822
  704. package/dist/browser/modules/word/docx-reader.d.ts +0 -11
  705. package/dist/browser/modules/word/docx-reader.js +0 -4929
  706. package/dist/browser/modules/word/encryption.js +0 -274
  707. package/dist/browser/modules/word/internal-utils.d.ts +0 -23
  708. package/dist/browser/modules/word/internal-utils.js +0 -54
  709. package/dist/browser/modules/word/namespaces.d.ts +0 -159
  710. package/dist/browser/modules/word/namespaces.js +0 -189
  711. package/dist/browser/modules/word/relationships.d.ts +0 -30
  712. package/dist/browser/modules/word/relationships.js +0 -48
  713. package/dist/browser/modules/word/writers/checkbox-writer.d.ts +0 -9
  714. package/dist/browser/modules/word/writers/checkbox-writer.js +0 -42
  715. package/dist/browser/modules/word/writers/document-writer.d.ts +0 -16
  716. package/dist/browser/modules/word/writers/document-writer.js +0 -461
  717. package/dist/browser/modules/word/writers/math-writer.d.ts +0 -9
  718. package/dist/cjs/modules/word/color-utils.js +0 -97
  719. package/dist/cjs/modules/word/document.js +0 -1645
  720. package/dist/cjs/modules/word/docx-packager.js +0 -825
  721. package/dist/cjs/modules/word/docx-reader.js +0 -4932
  722. package/dist/cjs/modules/word/encryption.js +0 -282
  723. package/dist/cjs/modules/word/internal-utils.js +0 -59
  724. package/dist/cjs/modules/word/namespaces.js +0 -192
  725. package/dist/cjs/modules/word/relationships.js +0 -55
  726. package/dist/cjs/modules/word/writers/checkbox-writer.js +0 -45
  727. package/dist/cjs/modules/word/writers/document-writer.js +0 -465
  728. package/dist/esm/modules/word/color-utils.js +0 -94
  729. package/dist/esm/modules/word/document.js +0 -1533
  730. package/dist/esm/modules/word/docx-packager.js +0 -822
  731. package/dist/esm/modules/word/docx-reader.js +0 -4929
  732. package/dist/esm/modules/word/encryption.js +0 -274
  733. package/dist/esm/modules/word/internal-utils.js +0 -54
  734. package/dist/esm/modules/word/namespaces.js +0 -189
  735. package/dist/esm/modules/word/relationships.js +0 -48
  736. package/dist/esm/modules/word/writers/checkbox-writer.js +0 -42
  737. package/dist/esm/modules/word/writers/document-writer.js +0 -461
  738. package/dist/types/modules/word/document.d.ts +0 -657
  739. package/dist/types/modules/word/docx-packager.d.ts +0 -14
  740. package/dist/types/modules/word/docx-reader.d.ts +0 -11
  741. package/dist/types/modules/word/internal-utils.d.ts +0 -23
  742. package/dist/types/modules/word/namespaces.d.ts +0 -159
  743. package/dist/types/modules/word/relationships.d.ts +0 -30
  744. package/dist/types/modules/word/writers/checkbox-writer.d.ts +0 -9
  745. package/dist/types/modules/word/writers/document-writer.d.ts +0 -16
  746. package/dist/types/modules/word/writers/math-writer.d.ts +0 -9
  747. /package/dist/browser/modules/word/{font-obfuscation.d.ts → font/font-obfuscation.d.ts} +0 -0
  748. /package/dist/browser/modules/word/{writers → writer}/chart-writer.d.ts +0 -0
  749. /package/dist/browser/modules/word/{writers → writer}/section-writer.d.ts +0 -0
  750. /package/dist/browser/modules/word/{writers → writer}/section-writer.js +0 -0
  751. /package/dist/browser/modules/word/{writers → writer}/styles-writer.d.ts +0 -0
  752. /package/dist/browser/modules/word/{writers → writer}/textbox-writer.d.ts +0 -0
  753. /package/dist/browser/modules/word/{writers → writer}/textbox-writer.js +0 -0
  754. /package/dist/browser/modules/word/{writers → writer}/toc-writer.d.ts +0 -0
  755. /package/dist/browser/modules/word/{writers → writer}/toc-writer.js +0 -0
  756. /package/dist/cjs/modules/word/{writers → writer}/section-writer.js +0 -0
  757. /package/dist/cjs/modules/word/{writers → writer}/textbox-writer.js +0 -0
  758. /package/dist/cjs/modules/word/{writers → writer}/toc-writer.js +0 -0
  759. /package/dist/esm/modules/word/{writers → writer}/section-writer.js +0 -0
  760. /package/dist/esm/modules/word/{writers → writer}/textbox-writer.js +0 -0
  761. /package/dist/esm/modules/word/{writers → writer}/toc-writer.js +0 -0
  762. /package/dist/types/modules/word/{font-obfuscation.d.ts → font/font-obfuscation.d.ts} +0 -0
  763. /package/dist/types/modules/word/{writers → writer}/chart-writer.d.ts +0 -0
  764. /package/dist/types/modules/word/{writers → writer}/section-writer.d.ts +0 -0
  765. /package/dist/types/modules/word/{writers → writer}/styles-writer.d.ts +0 -0
  766. /package/dist/types/modules/word/{writers → writer}/textbox-writer.d.ts +0 -0
  767. /package/dist/types/modules/word/{writers → writer}/toc-writer.d.ts +0 -0
@@ -0,0 +1,1699 @@
1
+ "use strict";
2
+ /**
3
+ * Full Layout Engine — produces a complete LayoutDocument with positioned elements.
4
+ *
5
+ * Uses the pagination result from layoutDocument() for page assignments,
6
+ * then computes precise positions (x, y, width, height) for every body
7
+ * element on each page.
8
+ *
9
+ * This is the bridge between the page-number-only LayoutResult and the
10
+ * fully positioned LayoutDocument that renderers (SVG, PDF, Canvas) can consume.
11
+ *
12
+ * Coverage: every variant of `BodyContent` from `../types` produces a
13
+ * `PageContent` variant in the output. The `default:` branch of the
14
+ * dispatch switch in `buildPage()` is a `never`-typed exhaustiveness
15
+ * guard — adding a new body variant without a matching layout function
16
+ * is a build error, never a silent drop.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.layoutDocumentFull = layoutDocumentFull;
20
+ const font_metrics_1 = require("../../../utils/font-metrics.js");
21
+ const math_convert_1 = require("../advanced/math-convert");
22
+ const text_utils_1 = require("../core/text-utils");
23
+ const units_1 = require("../units");
24
+ const layout_1 = require("./layout");
25
+ const layout_constants_1 = require("./layout-constants");
26
+ /**
27
+ * Perform full document layout, producing a LayoutDocument with precise positions.
28
+ *
29
+ * @param doc - The parsed DOCX document.
30
+ * @param options - Layout and font options.
31
+ * @returns A fully positioned LayoutDocument.
32
+ */
33
+ function layoutDocumentFull(doc, options) {
34
+ // First pass: get page assignments via the existing lightweight layout
35
+ const layoutResult = (0, layout_1.layoutDocument)(doc, options);
36
+ // Second pass: compute precise positions for each page. Footnote
37
+ // ids that don't fit on a given page are carried over to the next
38
+ // (a later page may still have room thanks to less body content
39
+ // or fewer of its own newly-introduced notes).
40
+ const pages = [];
41
+ const bodyPageCount = layoutResult.pageCount;
42
+ let pendingFootnoteIds = [];
43
+ for (let pageNum = 1; pageNum <= bodyPageCount; pageNum++) {
44
+ const result = buildPage(doc, pageNum, layoutResult, options, pendingFootnoteIds);
45
+ pages.push(result.page);
46
+ pendingFootnoteIds = result.deferredFootnoteIds;
47
+ }
48
+ // Defensive: if the last page still has deferred footnotes, append
49
+ // a synthetic page that hosts them. Without this, references would
50
+ // silently lose their content. This is rare (it only fires when an
51
+ // oversized footnote stack on the last body page didn't fit).
52
+ if (pendingFootnoteIds.length > 0 && bodyPageCount > 0) {
53
+ const overflowResult = buildPage(doc, bodyPageCount + 1,
54
+ // Reuse the last page's `LayoutResult` shape: contentPages
55
+ // entries for already-placed body items still point at earlier
56
+ // pages, so the synthetic page won't pick up extra body
57
+ // content; only the carried footnote queue renders.
58
+ layoutResult, options, pendingFootnoteIds);
59
+ pages.push(overflowResult.page);
60
+ }
61
+ return {
62
+ pages,
63
+ totalPages: pages.length,
64
+ bookmarkPages: layoutResult.bookmarkPages,
65
+ sectionBreaks: computeSectionBreaks(layoutResult)
66
+ };
67
+ }
68
+ // =============================================================================
69
+ // Internal: Page Building
70
+ // =============================================================================
71
+ const DEFAULT_FONT_SIZE_PT = 12;
72
+ /**
73
+ * Compute the longest available horizontal slot on the line whose
74
+ * vertical span is `[lineY, lineY + lineHeight)`. Returns `xOffset`
75
+ * (relative to the content-area's left edge) and `width`. When no
76
+ * exclusion intersects the line the result is `{ xOffset: 0, width:
77
+ * contentWidth }` (full width).
78
+ *
79
+ * Algorithm:
80
+ * 1. Collect all exclusions whose y-band intersects the line.
81
+ * 2. For each, derive the "blocked" x-interval on the content axis
82
+ * based on `wrapSide`:
83
+ * - `bothSides` blocks `[xLeft, xRight]` only.
84
+ * - `left` blocks `[xLeft, contentWidth]` (text wraps on the
85
+ * float's left side only).
86
+ * - `right` blocks `[0, xRight]`.
87
+ * - `largest` picks whichever side of the float is wider; the
88
+ * narrower side is blocked.
89
+ * 3. Subtract every blocked interval from `[0, contentWidth]` and
90
+ * return the longest remaining gap.
91
+ */
92
+ function availableSlotForLine(ctx, lineY, lineHeight) {
93
+ const lineBottom = lineY + lineHeight;
94
+ const blocked = [];
95
+ for (const ex of ctx.exclusions) {
96
+ // Strict overlap check: a line that just touches the float's
97
+ // bottom edge (`lineY === ex.yBottom`) does NOT need to wrap.
98
+ if (lineBottom <= ex.yTop || lineY >= ex.yBottom) {
99
+ continue;
100
+ }
101
+ const exLeft = Math.max(0, ex.xLeft);
102
+ const exRight = Math.min(ctx.contentWidth, ex.xRight);
103
+ if (exLeft >= exRight) {
104
+ continue;
105
+ }
106
+ switch (ex.wrapSide) {
107
+ case "bothSides":
108
+ blocked.push({ lo: exLeft, hi: exRight });
109
+ break;
110
+ case "left":
111
+ // Float blocks the right half of the line.
112
+ blocked.push({ lo: exLeft, hi: ctx.contentWidth });
113
+ break;
114
+ case "right":
115
+ blocked.push({ lo: 0, hi: exRight });
116
+ break;
117
+ case "largest": {
118
+ const leftSpace = exLeft;
119
+ const rightSpace = ctx.contentWidth - exRight;
120
+ if (rightSpace >= leftSpace) {
121
+ // Wrap on the right (block to the left of the float).
122
+ blocked.push({ lo: 0, hi: exRight });
123
+ }
124
+ else {
125
+ blocked.push({ lo: exLeft, hi: ctx.contentWidth });
126
+ }
127
+ break;
128
+ }
129
+ }
130
+ }
131
+ if (blocked.length === 0) {
132
+ return { xOffset: 0, width: ctx.contentWidth };
133
+ }
134
+ // Merge overlapping blocked intervals.
135
+ blocked.sort((a, b) => a.lo - b.lo);
136
+ const merged = [];
137
+ for (const seg of blocked) {
138
+ const last = merged[merged.length - 1];
139
+ if (last && seg.lo <= last.hi) {
140
+ last.hi = Math.max(last.hi, seg.hi);
141
+ }
142
+ else {
143
+ merged.push({ lo: seg.lo, hi: seg.hi });
144
+ }
145
+ }
146
+ // Build available gaps in [0, contentWidth] minus the merged blocks.
147
+ const gaps = [];
148
+ let cursor = 0;
149
+ for (const seg of merged) {
150
+ if (seg.lo > cursor) {
151
+ gaps.push({ x: cursor, width: seg.lo - cursor });
152
+ }
153
+ cursor = Math.max(cursor, seg.hi);
154
+ }
155
+ if (cursor < ctx.contentWidth) {
156
+ gaps.push({ x: cursor, width: ctx.contentWidth - cursor });
157
+ }
158
+ if (gaps.length === 0) {
159
+ // Line entirely blocked. Fall back to full content width to avoid
160
+ // pathological zero-width wraps that would loop forever; the line
161
+ // visually overlaps the float (fail-safe behaviour).
162
+ return { xOffset: 0, width: ctx.contentWidth };
163
+ }
164
+ // Pick the widest gap.
165
+ let best = gaps[0];
166
+ for (let i = 1; i < gaps.length; i++) {
167
+ if (gaps[i].width > best.width) {
168
+ best = gaps[i];
169
+ }
170
+ }
171
+ return { xOffset: best.x, width: best.width };
172
+ }
173
+ function twipsToPt(twips) {
174
+ return twips / 20;
175
+ }
176
+ function buildPage(doc, pageNumber, layout, options, pendingFootnoteIds) {
177
+ const sectionProps = doc.sectionProperties;
178
+ const geometry = computePageGeometry(sectionProps, options?.pageGeometry);
179
+ const content = [];
180
+ const imageMap = buildImageMap(doc.images);
181
+ /**
182
+ * Footnote ids referenced from the raw `BodyContent` items assigned
183
+ * to this page, collected as we iterate so the order is the
184
+ * document-reading order. Pending ids carried over from the
185
+ * previous page are queued ahead so they render before this page's
186
+ * own newly-introduced notes.
187
+ */
188
+ const footnoteRefIds = [...pendingFootnoteIds];
189
+ /**
190
+ * Wrap exclusion zones from floats with `square` / `tight` /
191
+ * `through` wrap, populated as we iterate so subsequent paragraphs
192
+ * (later in document order) avoid them line-by-line. Floats that
193
+ * appear AFTER a paragraph in the source do not push back into
194
+ * preceding lines — this matches Word's behaviour where re-flow on
195
+ * insertion happens at edit time, not render time.
196
+ */
197
+ const pageExclusions = [];
198
+ let cursorY = 0; // relative to content area top
199
+ for (let i = 0; i < doc.body.length; i++) {
200
+ if (layout.contentPages[i] !== pageNumber) {
201
+ continue;
202
+ }
203
+ const item = doc.body[i];
204
+ collectFootnoteRefsFromBody(item, footnoteRefIds);
205
+ const pageContext = {
206
+ exclusions: pageExclusions,
207
+ contentWidth: geometry.contentWidth
208
+ };
209
+ switch (item.type) {
210
+ case "paragraph": {
211
+ const laid = layoutParagraph(item, cursorY, geometry.contentWidth, options, pageContext, imageMap);
212
+ content.push({ ...laid, sourceIndex: i });
213
+ cursorY = laid.rect.y + laid.rect.height;
214
+ break;
215
+ }
216
+ case "table": {
217
+ const laid = layoutTable(item, cursorY, geometry.contentWidth, i, options, imageMap);
218
+ content.push(laid);
219
+ cursorY = laid.rect.y + laid.rect.height;
220
+ break;
221
+ }
222
+ case "floatingImage": {
223
+ const laid = layoutFloatingImage(item, cursorY, geometry.contentWidth, geometry.contentHeight, geometry, i, imageMap);
224
+ content.push(laid);
225
+ // Cursor advancement strategy:
226
+ // - `wrap.style === "topAndBottom"` (or no wrap and not
227
+ // behindDoc) forces body content to clear the float
228
+ // vertically; advance the cursor to the float's bottom edge
229
+ // plus the wrap.bottom margin.
230
+ // - `square` / `tight` / `through` register an exclusion zone
231
+ // so subsequent paragraph wrap avoids the float laterally;
232
+ // the body cursor is NOT advanced (text wraps around).
233
+ // - Behind-document floats never displace text.
234
+ // - Inline-like floats (no anchor, no behindDoc) keep the
235
+ // backwards-compatible advance behaviour.
236
+ const hasAnchor = item.simplePos != null ||
237
+ item.horizontalPosition != null ||
238
+ item.verticalPosition != null;
239
+ const wrapStyle = item.wrap?.style;
240
+ const isWrapAround = wrapStyle === "square" || wrapStyle === "tight" || wrapStyle === "through";
241
+ const advanceCursor = (!hasAnchor && !item.behindDoc && !isWrapAround) || wrapStyle === "topAndBottom";
242
+ if (advanceCursor) {
243
+ const padBottom = item.wrap?.margins?.bottom ? emuToPt(item.wrap.margins.bottom) : 0;
244
+ cursorY = laid.rect.y + laid.rect.height + padBottom;
245
+ }
246
+ if (isWrapAround && !item.behindDoc) {
247
+ // Add an exclusion band covering the float's rect plus its
248
+ // wrap padding margins. Subsequent paragraphs (later in doc
249
+ // order) will wrap their lines around this rectangle.
250
+ const padL = laid.wrap?.margins?.left ?? 0;
251
+ const padR = laid.wrap?.margins?.right ?? 0;
252
+ const padT = laid.wrap?.margins?.top ?? 0;
253
+ const padB = laid.wrap?.margins?.bottom ?? 0;
254
+ pageExclusions.push({
255
+ xLeft: laid.rect.x - padL,
256
+ xRight: laid.rect.x + laid.rect.width + padR,
257
+ yTop: laid.rect.y - padT,
258
+ yBottom: laid.rect.y + laid.rect.height + padB,
259
+ wrapSide: laid.wrap?.side ?? "bothSides"
260
+ });
261
+ }
262
+ break;
263
+ }
264
+ case "textBox": {
265
+ const laid = layoutTextBox(item, cursorY, geometry.contentWidth, i, options, imageMap);
266
+ content.push(laid);
267
+ cursorY = laid.rect.y + laid.rect.height;
268
+ break;
269
+ }
270
+ case "drawingShape": {
271
+ const laid = layoutDrawingShape(item, cursorY, geometry.contentWidth, i, options, imageMap);
272
+ content.push(laid);
273
+ cursorY = laid.rect.y + laid.rect.height;
274
+ break;
275
+ }
276
+ case "chart":
277
+ case "chartEx": {
278
+ const laid = layoutChart(item, cursorY, geometry.contentWidth, i);
279
+ content.push(laid);
280
+ cursorY = laid.rect.y + laid.rect.height;
281
+ break;
282
+ }
283
+ case "sdt": {
284
+ const laid = layoutSdt(item, cursorY, geometry.contentWidth, i, options, imageMap);
285
+ content.push(laid);
286
+ cursorY = laid.rect.y + laid.rect.height;
287
+ break;
288
+ }
289
+ case "math": {
290
+ const laid = layoutMath(item, cursorY, geometry.contentWidth, i, options);
291
+ content.push(laid);
292
+ cursorY = laid.rect.y + laid.rect.height;
293
+ break;
294
+ }
295
+ case "checkBox": {
296
+ const laid = layoutCheckBox(item, cursorY, i, options);
297
+ content.push(laid);
298
+ cursorY = laid.rect.y + laid.rect.height;
299
+ break;
300
+ }
301
+ case "tableOfContents": {
302
+ const laid = layoutTableOfContents(item, cursorY, geometry.contentWidth, i, options, imageMap);
303
+ content.push(laid);
304
+ cursorY = laid.rect.y + laid.rect.height;
305
+ break;
306
+ }
307
+ case "altChunk": {
308
+ const laid = layoutAltChunk(item, cursorY, geometry.contentWidth, i);
309
+ content.push(laid);
310
+ cursorY = laid.rect.y + laid.rect.height;
311
+ break;
312
+ }
313
+ case "opaqueDrawing": {
314
+ const laid = layoutOpaqueDrawing(item, cursorY, geometry.contentWidth, i);
315
+ content.push(laid);
316
+ cursorY = laid.rect.y + laid.rect.height;
317
+ break;
318
+ }
319
+ default: {
320
+ // Compile-time exhaustiveness check. Adding a new variant to
321
+ // `BodyContent` triggers a TypeScript error here until a
322
+ // corresponding case + layout function are added above. This
323
+ // replaces the previous "Skip unsupported types" silent drop.
324
+ const _exhaustive = item;
325
+ throw new Error(`layoutDocumentFull: unhandled BodyContent variant ${_exhaustive.type}`);
326
+ }
327
+ }
328
+ }
329
+ const header = layoutHeader(doc, pageNumber, geometry, options, imageMap);
330
+ const footer = layoutFooter(doc, pageNumber, geometry, options, imageMap);
331
+ // Compute the absolute (page-y) lower edge of body content so the
332
+ // footnote layout knows how much vertical room is actually free.
333
+ // `cursorY` is content-area-relative; convert by adding `marginTop`.
334
+ const bodyBottomPageY = geometry.marginTop + cursorY;
335
+ const footnoteResult = layoutFootnotes(doc, footnoteRefIds, geometry, options, bodyBottomPageY, imageMap);
336
+ // Decide whether the visual separator above the footnote area is the
337
+ // standard "separator" or the wider "continuationSeparator".
338
+ // A continuation page is one whose footnote area is *entirely*
339
+ // composed of notes deferred from a previous page (no body item on
340
+ // this page introduces a new reference). Detect by comparing the
341
+ // footnote-id sequence against the supplied `pendingFootnoteIds`.
342
+ let footnoteSeparator;
343
+ if (footnoteResult.laid.length > 0) {
344
+ const introducedHere = footnoteRefIds.length > pendingFootnoteIds.length;
345
+ const sepKind = introducedHere
346
+ ? "separator"
347
+ : "continuationSeparator";
348
+ // Place the rule a few points above the first footnote paragraph.
349
+ const stackTop = footnoteResult.laid[0].rect.y;
350
+ footnoteSeparator = { y: stackTop - 4, kind: sepKind };
351
+ }
352
+ return {
353
+ page: {
354
+ pageNumber,
355
+ geometry,
356
+ content,
357
+ ...(header.length > 0 ? { header } : {}),
358
+ ...(footer.length > 0 ? { footer } : {}),
359
+ ...(footnoteResult.laid.length > 0 ? { footnoteArea: footnoteResult.laid } : {}),
360
+ ...(footnoteSeparator ? { footnoteSeparator } : {})
361
+ },
362
+ deferredFootnoteIds: footnoteResult.deferred
363
+ };
364
+ }
365
+ function layoutFootnotes(doc, ids, geometry, options, bodyBottomPageY, imageMap) {
366
+ if (ids.length === 0 || !doc.footnotes || doc.footnotes.length === 0) {
367
+ return { laid: [], deferred: [] };
368
+ }
369
+ const noteById = new Map();
370
+ for (const note of doc.footnotes) {
371
+ const kind = note.type ?? "normal";
372
+ if (kind === "normal") {
373
+ noteById.set(note.id, note);
374
+ }
375
+ }
376
+ const footerOffsetPt = geometry.height - twipsToPt(doc.sectionProperties?.margins?.footer ?? 720);
377
+ /**
378
+ * Vertical room available for the footnote stack on this page.
379
+ * The stack must sit between `bodyBottomPageY` (top) and
380
+ * `footerOffsetPt` (bottom); anything that doesn't fit gets
381
+ * deferred. A small minimum is enforced so a page that's almost
382
+ * full still flushes at least one footnote (the alternative —
383
+ * deferring everything indefinitely — would loop forever in
384
+ * pathological inputs).
385
+ */
386
+ const availableSpace = Math.max(0, footerOffsetPt - bodyBottomPageY);
387
+ const seen = new Set();
388
+ const laidPerNote = [];
389
+ const heightPerNote = [];
390
+ const idsLaid = [];
391
+ for (const id of ids) {
392
+ if (seen.has(id)) {
393
+ continue;
394
+ }
395
+ seen.add(id);
396
+ const note = noteById.get(id);
397
+ if (!note) {
398
+ continue;
399
+ }
400
+ const note_paragraphs = [];
401
+ let cursor = 0;
402
+ for (const para of note.content) {
403
+ if (para.type !== "paragraph") {
404
+ continue;
405
+ }
406
+ const p = layoutParagraph(para, cursor, geometry.contentWidth, options, undefined, imageMap);
407
+ note_paragraphs.push(p);
408
+ cursor = p.rect.y + p.rect.height;
409
+ }
410
+ laidPerNote.push(note_paragraphs);
411
+ heightPerNote.push(cursor);
412
+ idsLaid.push(id);
413
+ }
414
+ // Greedily fit notes into the available space. The first note is
415
+ // always laid out — even if it overflows — so a page that
416
+ // references a single oversized note still renders something
417
+ // (avoids losing data); the renderer will visually clip into the
418
+ // bottom margin in that pathological case.
419
+ const fitNotes = [];
420
+ const fitHeights = [];
421
+ const deferred = [];
422
+ let stackHeight = 0;
423
+ for (let i = 0; i < idsLaid.length; i++) {
424
+ const noteHeight = heightPerNote[i];
425
+ const wouldBe = stackHeight + noteHeight;
426
+ const fitsCleanly = wouldBe <= availableSpace;
427
+ const isFirstAndForced = fitNotes.length === 0;
428
+ if (fitsCleanly || isFirstAndForced) {
429
+ fitNotes.push(laidPerNote[i]);
430
+ fitHeights.push(noteHeight);
431
+ stackHeight = wouldBe;
432
+ }
433
+ else {
434
+ deferred.push(idsLaid[i]);
435
+ }
436
+ }
437
+ if (fitNotes.length === 0) {
438
+ return { laid: [], deferred };
439
+ }
440
+ // Translate the whole stack so its bottom edge is at footerOffsetPt.
441
+ const top = footerOffsetPt - stackHeight;
442
+ const flat = [];
443
+ let runningOffset = top;
444
+ for (let i = 0; i < fitNotes.length; i++) {
445
+ for (const p of fitNotes[i]) {
446
+ flat.push({
447
+ ...p,
448
+ rect: { ...p.rect, y: p.rect.y + runningOffset }
449
+ });
450
+ }
451
+ runningOffset += fitHeights[i];
452
+ }
453
+ return { laid: flat, deferred };
454
+ }
455
+ /**
456
+ * Walk a `BodyContent` item's run-level descendants and append every
457
+ * `FootnoteRefContent` id to `out`, in document order. Recurses into
458
+ * the few container variants whose children embed paragraphs (textBox,
459
+ * drawingShape, sdt, tableOfContents, table cells).
460
+ */
461
+ function collectFootnoteRefsFromBody(item, out) {
462
+ switch (item.type) {
463
+ case "paragraph":
464
+ collectFootnoteRefsFromParagraph(item, out);
465
+ return;
466
+ case "table":
467
+ for (const r of item.rows) {
468
+ for (const c of r.cells) {
469
+ for (const inner of c.content) {
470
+ collectFootnoteRefsFromBody(inner, out);
471
+ }
472
+ }
473
+ }
474
+ return;
475
+ case "textBox":
476
+ for (const child of item.content) {
477
+ collectFootnoteRefsFromBody(child, out);
478
+ }
479
+ return;
480
+ case "drawingShape":
481
+ if (item.textContent) {
482
+ for (const child of item.textContent) {
483
+ collectFootnoteRefsFromBody(child, out);
484
+ }
485
+ }
486
+ return;
487
+ case "sdt":
488
+ for (const child of item.content) {
489
+ if (child && typeof child === "object" && "type" in child) {
490
+ collectFootnoteRefsFromBody(child, out);
491
+ }
492
+ }
493
+ return;
494
+ case "tableOfContents":
495
+ if (item.cachedParagraphs) {
496
+ for (const para of item.cachedParagraphs) {
497
+ collectFootnoteRefsFromBody(para, out);
498
+ }
499
+ }
500
+ return;
501
+ case "floatingImage":
502
+ case "math":
503
+ case "checkBox":
504
+ case "chart":
505
+ case "chartEx":
506
+ case "altChunk":
507
+ case "opaqueDrawing":
508
+ return;
509
+ default: {
510
+ const _exhaustive = item;
511
+ void _exhaustive;
512
+ }
513
+ }
514
+ }
515
+ function collectFootnoteRefsFromParagraph(para, out) {
516
+ for (const child of para.children) {
517
+ if ("type" in child && child.type === "hyperlink") {
518
+ collectFootnoteRefsFromHyperlink(child, out);
519
+ }
520
+ else if (!("type" in child) || child.type === undefined) {
521
+ // Plain Run (no `type` discriminator).
522
+ collectFootnoteRefsFromRun(child, out);
523
+ }
524
+ else if (child.type === "insertedRun" ||
525
+ child.type === "deletedRun" ||
526
+ child.type === "movedFromRun" ||
527
+ child.type === "movedToRun") {
528
+ // Tracked-change wrappers carry a single `run` (singular) per
529
+ // ECMA-376 — see `InsertedRun.run`, `DeletedRun.run`, etc.
530
+ collectFootnoteRefsFromRun(child.run, out);
531
+ }
532
+ // BookmarkStart / BookmarkEnd / Comment* / MoveRangeMarker /
533
+ // CustomXmlTrackingMarker carry no runnable text — nothing to
534
+ // collect.
535
+ }
536
+ }
537
+ function collectFootnoteRefsFromHyperlink(link, out) {
538
+ for (const child of link.children) {
539
+ if (!("type" in child) || child.type === undefined) {
540
+ collectFootnoteRefsFromRun(child, out);
541
+ }
542
+ }
543
+ }
544
+ function collectFootnoteRefsFromRun(run, out) {
545
+ if (!run || !Array.isArray(run.content)) {
546
+ return;
547
+ }
548
+ for (const c of run.content) {
549
+ if (c.type === "footnoteRef") {
550
+ out.push(c.id);
551
+ }
552
+ }
553
+ }
554
+ /**
555
+ * Resolve which header reference to use for a given page within a
556
+ * section, per ECMA-376 §17.10:
557
+ *
558
+ * - `titlePage === true` and `pageNumber === 1` → the `"first"` reference
559
+ * - `evenAndOddHeaders === true` (settings) and even page number → `"even"`
560
+ * - otherwise → the `"default"` reference
561
+ *
562
+ * Each rule falls back to `"default"` (then to the first available ref)
563
+ * if its preferred type isn't declared in the section's references.
564
+ */
565
+ function pickHeaderFooterRef(refs, pageNumber, titlePage, evenAndOdd) {
566
+ const find = (t) => refs.find(r => r.type === t);
567
+ if (titlePage && pageNumber === 1) {
568
+ const first = find("first");
569
+ if (first) {
570
+ return first;
571
+ }
572
+ }
573
+ if (evenAndOdd && pageNumber % 2 === 0) {
574
+ const even = find("even");
575
+ if (even) {
576
+ return even;
577
+ }
578
+ }
579
+ return find("default") ?? refs[0];
580
+ }
581
+ /**
582
+ * Lay out the paragraphs and tables of the resolved header for a page.
583
+ *
584
+ * Resolution order: first/even/default per `pickHeaderFooterRef`.
585
+ * The header band's local y-axis starts at the section's
586
+ * `pgMar.header` (in pt) below the page top, mirroring Word's
587
+ * "Header from top" setting; renderers consume the resulting layout-y
588
+ * directly as a page-y offset.
589
+ *
590
+ * Tables in header content are laid out with the same `layoutTable`
591
+ * that body content uses, and surfaced via the union type on
592
+ * `LayoutPage.header` so renderers can pick them up alongside
593
+ * paragraphs without a special path.
594
+ */
595
+ function layoutHeader(doc, pageNumber, geometry, options, imageMap) {
596
+ const refs = doc.sectionProperties?.headers;
597
+ if (!refs || refs.length === 0) {
598
+ return [];
599
+ }
600
+ const titlePage = doc.sectionProperties?.titlePage === true;
601
+ const evenAndOdd = doc.settings?.evenAndOddHeaders === true;
602
+ const ref = pickHeaderFooterRef(refs, pageNumber, titlePage, evenAndOdd);
603
+ if (!ref) {
604
+ return [];
605
+ }
606
+ const part = doc.headers?.get(ref.rId);
607
+ if (!part) {
608
+ return [];
609
+ }
610
+ const headerOffsetPt = twipsToPt(doc.sectionProperties?.margins?.header ?? 720);
611
+ return layoutHeaderFooterChildren(part.content.children, headerOffsetPt, geometry, options, imageMap);
612
+ }
613
+ function layoutFooter(doc, pageNumber, geometry, options, imageMap) {
614
+ const refs = doc.sectionProperties?.footers;
615
+ if (!refs || refs.length === 0) {
616
+ return [];
617
+ }
618
+ const titlePage = doc.sectionProperties?.titlePage === true;
619
+ const evenAndOdd = doc.settings?.evenAndOddHeaders === true;
620
+ const ref = pickHeaderFooterRef(refs, pageNumber, titlePage, evenAndOdd);
621
+ if (!ref) {
622
+ return [];
623
+ }
624
+ const part = doc.footers?.get(ref.rId);
625
+ if (!part) {
626
+ return [];
627
+ }
628
+ // Footer band starts at `pageHeight - pgMar.footer` so layout-y is
629
+ // already a page-absolute coordinate (matching the header path,
630
+ // where `pgMar.header` is the absolute offset of the band from the
631
+ // page top). Renderers consume both bands with the same
632
+ // "treat layout-y as page-y" rule.
633
+ const footerOffsetPt = geometry.height - twipsToPt(doc.sectionProperties?.margins?.footer ?? 720);
634
+ return layoutHeaderFooterChildren(part.content.children, footerOffsetPt, geometry, options, imageMap);
635
+ }
636
+ function layoutHeaderFooterChildren(children, initialCursorY, geometry, options, imageMap) {
637
+ const out = [];
638
+ let cursor = initialCursorY;
639
+ for (let idx = 0; idx < children.length; idx++) {
640
+ const child = children[idx];
641
+ if (child.type === "paragraph") {
642
+ const laid = layoutParagraph(child, cursor, geometry.contentWidth, options, undefined, imageMap);
643
+ out.push(laid);
644
+ cursor = laid.rect.y + laid.rect.height;
645
+ }
646
+ else if (child.type === "table") {
647
+ const laid = layoutTable(child, cursor, geometry.contentWidth, idx, options, imageMap);
648
+ out.push(laid);
649
+ cursor = laid.rect.y + laid.rect.height;
650
+ }
651
+ }
652
+ return out;
653
+ }
654
+ function computePageGeometry(sectionProps, override) {
655
+ const widthTwips = sectionProps?.pageSize?.width ?? layout_constants_1.DEFAULT_PAGE_WIDTH_TWIPS;
656
+ const heightTwips = sectionProps?.pageSize?.height ?? layout_constants_1.DEFAULT_PAGE_HEIGHT_TWIPS;
657
+ const sectionWidth = twipsToPt(widthTwips);
658
+ const sectionHeight = twipsToPt(heightTwips);
659
+ const sectionMarginTop = twipsToPt(sectionProps?.margins?.top ?? layout_constants_1.DEFAULT_PAGE_MARGIN_TWIPS);
660
+ const sectionMarginBottom = twipsToPt(sectionProps?.margins?.bottom ?? layout_constants_1.DEFAULT_PAGE_MARGIN_TWIPS);
661
+ const sectionMarginLeft = twipsToPt(sectionProps?.margins?.left ?? layout_constants_1.DEFAULT_PAGE_MARGIN_TWIPS);
662
+ const sectionMarginRight = twipsToPt(sectionProps?.margins?.right ?? layout_constants_1.DEFAULT_PAGE_MARGIN_TWIPS);
663
+ // Per-axis override: callers (PDF bridge, custom hosts) may want to
664
+ // pin the page size or margin on one axis without disturbing the
665
+ // others — `pageWidth` doesn't imply overriding margins, etc.
666
+ const width = override?.pageWidth ?? sectionWidth;
667
+ const height = override?.pageHeight ?? sectionHeight;
668
+ const marginTop = override?.marginTop ?? sectionMarginTop;
669
+ const marginBottom = override?.marginBottom ?? sectionMarginBottom;
670
+ const marginLeft = override?.marginLeft ?? sectionMarginLeft;
671
+ const marginRight = override?.marginRight ?? sectionMarginRight;
672
+ return {
673
+ width,
674
+ height,
675
+ marginTop,
676
+ marginBottom,
677
+ marginLeft,
678
+ marginRight,
679
+ contentWidth: width - marginLeft - marginRight,
680
+ contentHeight: height - marginTop - marginBottom
681
+ };
682
+ }
683
+ function computeSectionBreaks(layout) {
684
+ const breaks = [0]; // First section starts at page 0
685
+ let prevSection = 0;
686
+ for (let i = 0; i < layout.contentPages.length; i++) {
687
+ const section = layout.contentSections[i];
688
+ if (section > prevSection) {
689
+ breaks.push(layout.contentPages[i] - 1);
690
+ prevSection = section;
691
+ }
692
+ }
693
+ return breaks;
694
+ }
695
+ // =============================================================================
696
+ // Internal: Paragraph Layout
697
+ // =============================================================================
698
+ function layoutParagraph(para, startY, contentWidth, options, pageContext, imageMap) {
699
+ const props = para.properties;
700
+ const spacing = props?.spacing;
701
+ const headingScale = getHeadingFontScale(getHeadingLevel(props));
702
+ // Space before
703
+ let spaceBefore = 0;
704
+ if (spacing?.beforeAutoSpacing) {
705
+ spaceBefore = 5;
706
+ }
707
+ else if (spacing?.before != null) {
708
+ spaceBefore = twipsToPt(spacing.before);
709
+ }
710
+ const indent = props?.indent;
711
+ const leftIndentPt = indent?.left ? twipsToPt(indent.left) : 0;
712
+ const firstLineIndentPt = indent?.firstLine ? twipsToPt(indent.firstLine) : 0;
713
+ const alignment = props?.alignment ?? "left";
714
+ // Line height
715
+ let lineHeightPt = DEFAULT_FONT_SIZE_PT * 1.2;
716
+ if (spacing?.line) {
717
+ const rule = spacing.lineRule ?? "auto";
718
+ switch (rule) {
719
+ case "exact":
720
+ lineHeightPt = twipsToPt(spacing.line);
721
+ break;
722
+ case "atLeast":
723
+ lineHeightPt = Math.max(twipsToPt(spacing.line), lineHeightPt);
724
+ break;
725
+ case "auto":
726
+ lineHeightPt = DEFAULT_FONT_SIZE_PT * 1.2 * (spacing.line / 240);
727
+ break;
728
+ }
729
+ }
730
+ lineHeightPt *= headingScale;
731
+ // Collect runs
732
+ const segments = collectParagraphSegments(para);
733
+ const fullAvailableWidth = contentWidth - leftIndentPt;
734
+ // When a page has wrap exclusions (square / tight / through floats)
735
+ // we wrap line-by-line, asking the page context for the widest free
736
+ // slot at the line's actual y-position. Otherwise we use the
737
+ // legacy single-width path which never re-evaluates width across
738
+ // lines — this preserves the existing layout output for documents
739
+ // with no wrap (the overwhelming majority).
740
+ let lines;
741
+ let perLineSlots;
742
+ if (pageContext && pageContext.exclusions.length > 0) {
743
+ const result = wrapSegmentsToLinesWithExclusions(segments, leftIndentPt, firstLineIndentPt, headingScale, lineHeightPt, startY + spaceBefore, pageContext);
744
+ lines = result.lines;
745
+ perLineSlots = result.slots;
746
+ }
747
+ else {
748
+ lines = wrapSegmentsToLines(segments, fullAvailableWidth, firstLineIndentPt, headingScale);
749
+ }
750
+ // Build line boxes
751
+ const lineBoxes = [];
752
+ let yOffset = spaceBefore;
753
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
754
+ const lineSegments = lines[lineIdx];
755
+ const runs = [];
756
+ // Resolve the line's effective slot. With exclusions each line has
757
+ // its own usable [xOffset, width]; otherwise we keep the legacy
758
+ // single-width behaviour and place the first line indent.
759
+ const slot = perLineSlots?.[lineIdx] ?? {
760
+ xOffset: 0,
761
+ width: fullAvailableWidth
762
+ };
763
+ const lineLeftIndent = perLineSlots ? slot.xOffset : leftIndentPt;
764
+ const lineAvailableWidth = perLineSlots ? slot.width : fullAvailableWidth;
765
+ let xPos = lineIdx === 0 ? firstLineIndentPt : 0;
766
+ // Calculate line width for alignment, and find the tallest item
767
+ // so the line's height accommodates inline images.
768
+ let lineWidth = 0;
769
+ let lineMaxHeight = lineHeightPt;
770
+ for (const seg of lineSegments) {
771
+ if ("type" in seg && seg.type === "image") {
772
+ const w = emuToPt(seg.content.width);
773
+ const h = emuToPt(seg.content.height);
774
+ lineWidth += w;
775
+ if (h > lineMaxHeight) {
776
+ lineMaxHeight = h;
777
+ }
778
+ }
779
+ else {
780
+ const fontSize = getRunFontSizePt(seg.properties) * headingScale;
781
+ const fontName = (0, font_metrics_1.mapToStandardFont)(resolveRunFontName(seg.properties));
782
+ lineWidth += (0, font_metrics_1.measureTextWidth)(seg.text, fontName, fontSize);
783
+ }
784
+ }
785
+ // Apply alignment
786
+ if (alignment === "center") {
787
+ xPos = (lineAvailableWidth - lineWidth) / 2;
788
+ }
789
+ else if (alignment === "right" || alignment === "end") {
790
+ xPos = lineAvailableWidth - lineWidth;
791
+ }
792
+ xPos += lineLeftIndent;
793
+ for (const seg of lineSegments) {
794
+ if ("type" in seg && seg.type === "image") {
795
+ const widthPt = emuToPt(seg.content.width);
796
+ const heightPt = emuToPt(seg.content.height);
797
+ const img = seg.content.rId ? imageMap?.get(seg.content.rId) : undefined;
798
+ runs.push({
799
+ type: "image",
800
+ x: xPos,
801
+ width: widthPt,
802
+ height: heightPt,
803
+ data: img?.data ?? new Uint8Array(0),
804
+ mimeType: mediaTypeToMime(img?.mediaType),
805
+ altText: seg.content.altText
806
+ });
807
+ xPos += widthPt;
808
+ continue;
809
+ }
810
+ const fontSize = getRunFontSizePt(seg.properties) * headingScale;
811
+ const fontName = resolveRunFontName(seg.properties);
812
+ const measuredFont = (0, font_metrics_1.mapToStandardFont)(fontName);
813
+ const segWidth = (0, font_metrics_1.measureTextWidth)(seg.text, measuredFont, fontSize);
814
+ runs.push({
815
+ text: seg.text,
816
+ x: xPos,
817
+ width: segWidth,
818
+ font: fontName,
819
+ fontSize,
820
+ bold: seg.properties?.bold || undefined,
821
+ italic: seg.properties?.italic || undefined,
822
+ color: resolveColorHex(seg.properties?.color),
823
+ underline: seg.properties?.underline !== undefined ? true : undefined,
824
+ strikethrough: seg.properties?.strike || undefined,
825
+ verticalAlign: seg.properties?.vertAlign === "superscript" || seg.properties?.vertAlign === "subscript"
826
+ ? seg.properties.vertAlign
827
+ : undefined
828
+ });
829
+ xPos += segWidth;
830
+ }
831
+ const mappedAlignment = alignment === "both"
832
+ ? "justify"
833
+ : alignment === "end"
834
+ ? "right"
835
+ : alignment === "start"
836
+ ? "left"
837
+ : alignment;
838
+ lineBoxes.push({
839
+ y: yOffset,
840
+ height: lineMaxHeight,
841
+ // Baseline for text sits at 80% of line height; for an
842
+ // image-dominant line this puts the image's bottom near the
843
+ // baseline, matching Word's default inline-image alignment.
844
+ baseline: lineMaxHeight * 0.8,
845
+ runs,
846
+ alignment: mappedAlignment
847
+ });
848
+ yOffset += lineMaxHeight;
849
+ }
850
+ // If empty paragraph, still advance by one line
851
+ if (lineBoxes.length === 0) {
852
+ yOffset += lineHeightPt;
853
+ }
854
+ // Space after
855
+ let spaceAfter = 0;
856
+ if (spacing?.afterAutoSpacing) {
857
+ spaceAfter = 5;
858
+ }
859
+ else if (spacing?.after != null) {
860
+ spaceAfter = twipsToPt(spacing.after);
861
+ }
862
+ const totalHeight = yOffset + spaceAfter;
863
+ return {
864
+ type: "paragraph",
865
+ rect: { x: 0, y: startY, width: contentWidth, height: totalHeight },
866
+ lines: lineBoxes,
867
+ sourceIndex: 0 // overwritten by caller
868
+ };
869
+ }
870
+ // =============================================================================
871
+ // Internal: Table Layout
872
+ // =============================================================================
873
+ function layoutTable(table, startY, contentWidth, sourceIndex, options, imageMap) {
874
+ const numCols = table.rows.length > 0 ? table.rows[0].cells.length : 0;
875
+ const colWidth = numCols > 0 ? contentWidth / numCols : contentWidth;
876
+ const cells = [];
877
+ let cursorY = 0;
878
+ for (let ri = 0; ri < table.rows.length; ri++) {
879
+ const row = table.rows[ri];
880
+ let maxRowHeight = DEFAULT_FONT_SIZE_PT * 1.5; // minimum row height
881
+ for (let ci = 0; ci < row.cells.length; ci++) {
882
+ const cell = row.cells[ci];
883
+ const cellX = ci * colWidth;
884
+ const cellContent = [];
885
+ let cellCursorY = 2; // cell padding top
886
+ for (const block of cell.content) {
887
+ if (block.type === "paragraph") {
888
+ const laid = layoutParagraph(block, cellCursorY, colWidth - 4, options, undefined, imageMap);
889
+ cellContent.push({ ...laid, sourceIndex: -1 });
890
+ cellCursorY = laid.rect.y + laid.rect.height;
891
+ }
892
+ // nested tables skipped for simplicity
893
+ }
894
+ const cellHeight = cellCursorY + 2; // cell padding bottom
895
+ if (cellHeight > maxRowHeight) {
896
+ maxRowHeight = cellHeight;
897
+ }
898
+ cells.push({
899
+ rect: { x: cellX, y: startY + cursorY, width: colWidth, height: cellHeight },
900
+ row: ri,
901
+ col: ci,
902
+ content: cellContent
903
+ });
904
+ }
905
+ // Normalize cell heights to row max
906
+ for (const c of cells) {
907
+ if (c.row === ri) {
908
+ c.rect.height = maxRowHeight;
909
+ }
910
+ }
911
+ cursorY += maxRowHeight;
912
+ }
913
+ return {
914
+ type: "table",
915
+ rect: { x: 0, y: startY, width: contentWidth, height: cursorY },
916
+ cells,
917
+ sourceIndex
918
+ };
919
+ }
920
+ /**
921
+ * Walk a paragraph's children and emit a flat sequence of paragraph
922
+ * segments — text runs preserve their formatting; inline images become
923
+ * dedicated `ImageSegment` tokens so the wrap engine treats them as
924
+ * unbreakable atoms positioned in document order. Hyperlinks are
925
+ * descended into; bookmark / comment / track-change wrappers are
926
+ * ignored for layout purposes.
927
+ */
928
+ function collectParagraphSegments(para) {
929
+ const segments = [];
930
+ for (const child of para.children) {
931
+ if ((0, text_utils_1.isRun)(child)) {
932
+ pushRunSegments(child, segments);
933
+ }
934
+ else if ((0, text_utils_1.isHyperlink)(child)) {
935
+ for (const run of child.children) {
936
+ pushRunSegments(run, segments);
937
+ }
938
+ }
939
+ }
940
+ return segments;
941
+ }
942
+ /**
943
+ * Emit `ParagraphSegment` tokens for a single run, preserving the
944
+ * relative order of text fragments and inline images. Consecutive
945
+ * text-bearing entries are coalesced into one `TextSegment` so the
946
+ * wrap engine sees fewer atoms.
947
+ */
948
+ function pushRunSegments(run, out) {
949
+ let pending = "";
950
+ for (const item of run.content) {
951
+ if (item.type === "text") {
952
+ pending += item.text;
953
+ }
954
+ else if (item.type === "tab") {
955
+ pending += " ";
956
+ }
957
+ else if (item.type === "break") {
958
+ pending += "\n";
959
+ }
960
+ else if (item.type === "image") {
961
+ if (pending.length > 0) {
962
+ out.push({ text: pending, properties: run.properties });
963
+ pending = "";
964
+ }
965
+ out.push({ type: "image", content: item, properties: run.properties });
966
+ }
967
+ }
968
+ if (pending.length > 0) {
969
+ out.push({ text: pending, properties: run.properties });
970
+ }
971
+ }
972
+ /**
973
+ * Wrap a paragraph's text segments into lines whose available widths
974
+ * vary based on per-line wrap exclusions (square / tight / through
975
+ * floats). Word-level break points only — character-level shaping is
976
+ * out of scope for the layout engine.
977
+ *
978
+ * Returns both the per-line `TextSegment[]` and a parallel array of
979
+ * `{ xOffset, width }` describing where each line is placed within
980
+ * the content area. Callers use the slot to set per-line indent /
981
+ * available width for alignment.
982
+ */
983
+ function wrapSegmentsToLinesWithExclusions(segments, leftIndentPt, firstLineIndentPt, headingScale, lineHeightPt, paragraphTopPageY, pageContext) {
984
+ const atoms = [];
985
+ for (const seg of segments) {
986
+ if ("type" in seg && seg.type === "image") {
987
+ atoms.push({
988
+ width: emuToPt(seg.content.width),
989
+ isSpace: false,
990
+ isImage: true,
991
+ properties: seg.properties,
992
+ imageContent: seg.content
993
+ });
994
+ continue;
995
+ }
996
+ const fontSize = getRunFontSizePt(seg.properties) * headingScale;
997
+ const fontName = (0, font_metrics_1.mapToStandardFont)(resolveRunFontName(seg.properties));
998
+ // Split on runs of whitespace, keeping the whitespace tokens so
999
+ // wrapping can decide whether to drop trailing space at line end.
1000
+ const tokens = seg.text.split(/(\s+)/);
1001
+ for (const tok of tokens) {
1002
+ if (tok.length === 0) {
1003
+ continue;
1004
+ }
1005
+ atoms.push({
1006
+ text: tok,
1007
+ width: (0, font_metrics_1.measureTextWidth)(tok, fontName, fontSize),
1008
+ properties: seg.properties,
1009
+ isSpace: /^\s+$/.test(tok),
1010
+ isImage: false
1011
+ });
1012
+ }
1013
+ }
1014
+ const lines = [];
1015
+ const slots = [];
1016
+ if (atoms.length === 0) {
1017
+ return { lines, slots };
1018
+ }
1019
+ let cursorAtom = 0;
1020
+ let lineIdx = 0;
1021
+ while (cursorAtom < atoms.length) {
1022
+ const lineY = paragraphTopPageY + lineIdx * lineHeightPt;
1023
+ const slot = availableSlotForLine(pageContext, lineY, lineHeightPt);
1024
+ // The first line of a paragraph may carry an extra `firstLineIndent`
1025
+ // (from `<w:ind firstLine="…"/>`) which subtracts from the usable
1026
+ // width on that line only. Subsequent lines use the full slot width
1027
+ // (offset by the paragraph's `leftIndentPt`, which is applied by
1028
+ // the caller's run x-positioning logic, not here).
1029
+ const indentForThisLine = lineIdx === 0 ? firstLineIndentPt : 0;
1030
+ let usable = slot.width - indentForThisLine;
1031
+ let lineXOffset = slot.xOffset + indentForThisLine;
1032
+ // Also subtract the paragraph's own leftIndentPt (which the legacy
1033
+ // path applies through `availableWidth = contentWidth -
1034
+ // leftIndentPt`). We mirror that here so wrap behaviour matches
1035
+ // when no exclusion is in play.
1036
+ if (slot.xOffset === 0 && leftIndentPt > 0) {
1037
+ usable -= leftIndentPt;
1038
+ lineXOffset += leftIndentPt;
1039
+ }
1040
+ if (usable <= 0) {
1041
+ // Pathological — the line is fully blocked or narrower than the
1042
+ // first-line indent. Skip the y position by advancing one line
1043
+ // height; placing zero-content lines indefinitely is worse than
1044
+ // leaving a small visual gap.
1045
+ lines.push([]);
1046
+ slots.push({ xOffset: lineXOffset, width: Math.max(0, usable) });
1047
+ lineIdx++;
1048
+ // Re-evaluate without retrying same atoms (no progress -> bail
1049
+ // after a sane number of retries to avoid infinite loops on a
1050
+ // degenerate page).
1051
+ if (lineIdx > 1000) {
1052
+ break;
1053
+ }
1054
+ continue;
1055
+ }
1056
+ // Greedily pack atoms into the line until the next atom would
1057
+ // overflow `usable`. A leading whitespace atom on a fresh line is
1058
+ // dropped (matches typical text engines).
1059
+ if (atoms[cursorAtom].isSpace) {
1060
+ cursorAtom++;
1061
+ if (cursorAtom >= atoms.length) {
1062
+ break;
1063
+ }
1064
+ }
1065
+ const lineAtoms = [];
1066
+ let lineWidth = 0;
1067
+ while (cursorAtom < atoms.length) {
1068
+ const atom = atoms[cursorAtom];
1069
+ const next = lineWidth + atom.width;
1070
+ if (next > usable && lineAtoms.length > 0) {
1071
+ // Atom would overflow; commit the line and go to next.
1072
+ break;
1073
+ }
1074
+ lineAtoms.push(atom);
1075
+ lineWidth = next;
1076
+ cursorAtom++;
1077
+ }
1078
+ // Trim trailing whitespace so alignment computation is correct.
1079
+ // Don't trim trailing image atoms (they're not whitespace).
1080
+ while (lineAtoms.length > 0 && lineAtoms[lineAtoms.length - 1].isSpace) {
1081
+ const drop = lineAtoms.pop();
1082
+ lineWidth -= drop.width;
1083
+ }
1084
+ // Reassemble the line into `ParagraphSegment[]`. Adjacent text
1085
+ // atoms with identical properties merge; image atoms remain
1086
+ // standalone.
1087
+ const merged = [];
1088
+ for (const atom of lineAtoms) {
1089
+ if (atom.isImage) {
1090
+ merged.push({
1091
+ type: "image",
1092
+ content: atom.imageContent,
1093
+ properties: atom.properties
1094
+ });
1095
+ continue;
1096
+ }
1097
+ const last = merged[merged.length - 1];
1098
+ const lastIsText = last && !("type" in last);
1099
+ if (lastIsText && last.properties === atom.properties) {
1100
+ merged[merged.length - 1] = {
1101
+ text: last.text + atom.text,
1102
+ properties: atom.properties
1103
+ };
1104
+ }
1105
+ else {
1106
+ merged.push({ text: atom.text, properties: atom.properties });
1107
+ }
1108
+ }
1109
+ lines.push(merged);
1110
+ slots.push({ xOffset: lineXOffset, width: usable });
1111
+ lineIdx++;
1112
+ if (lineIdx > 100000) {
1113
+ // Defensive — degenerate inputs shouldn't loop the engine.
1114
+ break;
1115
+ }
1116
+ }
1117
+ return { lines, slots };
1118
+ }
1119
+ function wrapSegmentsToLines(segments, availableWidth, firstLineIndent, headingScale) {
1120
+ const lines = [];
1121
+ let currentLine = [];
1122
+ let currentLineWidth = 0;
1123
+ let isFirstLine = true;
1124
+ let effectiveWidth = availableWidth - firstLineIndent;
1125
+ const flushLine = () => {
1126
+ lines.push(currentLine);
1127
+ currentLine = [];
1128
+ currentLineWidth = 0;
1129
+ if (isFirstLine) {
1130
+ isFirstLine = false;
1131
+ effectiveWidth = availableWidth;
1132
+ }
1133
+ };
1134
+ for (const segment of segments) {
1135
+ if ("type" in segment && segment.type === "image") {
1136
+ // Inline images are unbreakable atoms. Width comes from the
1137
+ // source EMU; if the image alone exceeds the line we still
1138
+ // place it (avoids losing content) — the renderer will overflow
1139
+ // visually on that line, matching Word's behaviour for
1140
+ // oversized inline images.
1141
+ const imageWidth = emuToPt(segment.content.width);
1142
+ const fitsCurrent = currentLineWidth + imageWidth <= effectiveWidth || currentLine.length === 0;
1143
+ if (!fitsCurrent) {
1144
+ flushLine();
1145
+ }
1146
+ currentLine.push(segment);
1147
+ currentLineWidth += imageWidth;
1148
+ continue;
1149
+ }
1150
+ const text = segment.text;
1151
+ const fontSize = getRunFontSizePt(segment.properties) * headingScale;
1152
+ const fontName = (0, font_metrics_1.mapToStandardFont)(resolveRunFontName(segment.properties));
1153
+ const segmentWidth = (0, font_metrics_1.measureTextWidth)(text, fontName, fontSize);
1154
+ if (currentLineWidth + segmentWidth <= effectiveWidth || currentLine.length === 0) {
1155
+ currentLine.push(segment);
1156
+ currentLineWidth += segmentWidth;
1157
+ }
1158
+ else {
1159
+ // Word-level splitting
1160
+ const words = text.split(/(\s+)/);
1161
+ let bufferedText = "";
1162
+ let bufferedWidth = 0;
1163
+ for (const word of words) {
1164
+ const wordWidth = (0, font_metrics_1.measureTextWidth)(word, fontName, fontSize);
1165
+ if (currentLineWidth + bufferedWidth + wordWidth <= effectiveWidth ||
1166
+ (currentLine.length === 0 && bufferedText.length === 0)) {
1167
+ bufferedText += word;
1168
+ bufferedWidth += wordWidth;
1169
+ }
1170
+ else {
1171
+ if (bufferedText.length > 0) {
1172
+ currentLine.push({ text: bufferedText, properties: segment.properties });
1173
+ }
1174
+ flushLine();
1175
+ bufferedText = word;
1176
+ bufferedWidth = wordWidth;
1177
+ }
1178
+ }
1179
+ if (bufferedText.length > 0) {
1180
+ currentLine.push({ text: bufferedText, properties: segment.properties });
1181
+ currentLineWidth += bufferedWidth;
1182
+ }
1183
+ }
1184
+ }
1185
+ if (currentLine.length > 0) {
1186
+ lines.push(currentLine);
1187
+ }
1188
+ if (lines.length === 0 && segments.length > 0) {
1189
+ lines.push(segments);
1190
+ }
1191
+ return lines;
1192
+ }
1193
+ function getHeadingLevel(props) {
1194
+ if (!props) {
1195
+ return 0;
1196
+ }
1197
+ if (props.outlineLevel !== undefined && props.outlineLevel >= 0 && props.outlineLevel <= 5) {
1198
+ return props.outlineLevel + 1;
1199
+ }
1200
+ if (props.style) {
1201
+ const match = /^[Hh]eading\s*(\d)$/i.exec(props.style);
1202
+ if (match) {
1203
+ return parseInt(match[1], 10);
1204
+ }
1205
+ }
1206
+ return 0;
1207
+ }
1208
+ function getHeadingFontScale(level) {
1209
+ switch (level) {
1210
+ case 1:
1211
+ return 2.0;
1212
+ case 2:
1213
+ return 1.5;
1214
+ case 3:
1215
+ return 1.17;
1216
+ case 4:
1217
+ return 1.0;
1218
+ case 5:
1219
+ return 0.83;
1220
+ case 6:
1221
+ return 0.67;
1222
+ default:
1223
+ return 1.0;
1224
+ }
1225
+ }
1226
+ /**
1227
+ * Resolve the effective font size in points for a run.
1228
+ *
1229
+ * `<w:sz w:val="…"/>` is in half-points; we halve.
1230
+ *
1231
+ * Sub/superscript runs are conventionally rendered at ~65 % of the
1232
+ * surrounding text's size with a vertical baseline shift. The size
1233
+ * scaling lives here so every measurement (line width, line height,
1234
+ * wrap) sees the same value; the y-shift is applied at render time
1235
+ * via `PositionedRun.verticalAlign`.
1236
+ */
1237
+ function getRunFontSizePt(props) {
1238
+ const base = props?.size ? props.size / 2 : DEFAULT_FONT_SIZE_PT;
1239
+ if (props?.vertAlign === "superscript" || props?.vertAlign === "subscript") {
1240
+ return base * 0.65;
1241
+ }
1242
+ return base;
1243
+ }
1244
+ function resolveRunFontName(props) {
1245
+ if (!props?.font) {
1246
+ return "Calibri";
1247
+ }
1248
+ if (typeof props.font === "string") {
1249
+ return props.font;
1250
+ }
1251
+ return props.font.ascii ?? "Calibri";
1252
+ }
1253
+ function resolveColorHex(color) {
1254
+ if (!color) {
1255
+ return undefined;
1256
+ }
1257
+ if (typeof color === "string") {
1258
+ return color;
1259
+ }
1260
+ if (typeof color === "object" && color !== null && "value" in color) {
1261
+ return color.value;
1262
+ }
1263
+ return undefined;
1264
+ }
1265
+ // =============================================================================
1266
+ // Internal: Image / Geometry Helpers
1267
+ // =============================================================================
1268
+ function emuToPt(emu) {
1269
+ return emu / units_1.EMU_PER_POINT;
1270
+ }
1271
+ /**
1272
+ * Convert the docx-internal `ImageMediaType` (`"png"`, `"jpeg"`, …)
1273
+ * to the standard MIME string consumers expect on
1274
+ * `LayoutImage.mimeType` / `PositionedInlineImage.mimeType`. Unknown
1275
+ * tags fall back to `application/octet-stream` so renderers can
1276
+ * decide whether to skip or draw a placeholder.
1277
+ */
1278
+ function mediaTypeToMime(mt) {
1279
+ switch (mt) {
1280
+ case "png":
1281
+ return "image/png";
1282
+ case "jpeg":
1283
+ return "image/jpeg";
1284
+ case "gif":
1285
+ return "image/gif";
1286
+ case "bmp":
1287
+ return "image/bmp";
1288
+ case "tiff":
1289
+ return "image/tiff";
1290
+ case "svg":
1291
+ return "image/svg+xml";
1292
+ case "webp":
1293
+ return "image/webp";
1294
+ case "emf":
1295
+ return "image/x-emf";
1296
+ case "wmf":
1297
+ return "image/x-wmf";
1298
+ default:
1299
+ return "application/octet-stream";
1300
+ }
1301
+ }
1302
+ function buildImageMap(images) {
1303
+ const map = new Map();
1304
+ if (!images) {
1305
+ return map;
1306
+ }
1307
+ for (const img of images) {
1308
+ if (img.rId) {
1309
+ map.set(img.rId, img);
1310
+ }
1311
+ // Some images carry additional rIds (header/footer parts use their own
1312
+ // local id space). Index by every known rId so layout can resolve
1313
+ // either flavour.
1314
+ if (Array.isArray(img.altRIds)) {
1315
+ for (const aux of img.altRIds) {
1316
+ map.set(aux, img);
1317
+ }
1318
+ }
1319
+ }
1320
+ return map;
1321
+ }
1322
+ // =============================================================================
1323
+ // Internal: FloatingImage / TextBox / Shape / Chart / SDT / Math / CheckBox
1324
+ // =============================================================================
1325
+ /**
1326
+ * Resolve the page-content-area position of a floating image per
1327
+ * ECMA-376 §20.4.2.10. Layout coordinates have origin at the top-left
1328
+ * of the **content area**; floating-image anchors are normally
1329
+ * expressed against the **page** or **margin**, so we translate
1330
+ * accordingly.
1331
+ *
1332
+ * Resolution order:
1333
+ * 1. `simplePos="1"` (we currently see only `simplePos.x`/`simplePos.y`
1334
+ * in the model; we treat its presence as the simplePos override)
1335
+ * — page-absolute EMU.
1336
+ * 2. `horizontalPosition` / `verticalPosition` with `align` keywords
1337
+ * (left/center/right/inside/outside, top/center/bottom).
1338
+ * 3. `horizontalPosition` / `verticalPosition` with `offset` (EMU)
1339
+ * relative to the chosen `relativeTo` reference.
1340
+ * 4. Fall back to the cursor (inline-like behaviour).
1341
+ *
1342
+ * `relativeTo` reference points (subset we resolve):
1343
+ * - `"page"` — page top-left corner
1344
+ * - `"margin"` — margin box top-left corner (same as content area
1345
+ * origin in our coordinate system)
1346
+ * - `"column"` / `"character"` / `"paragraph"` etc. — fall back to the
1347
+ * cursor; reproducing them faithfully would require column/text-flow
1348
+ * info we don't keep at this stage.
1349
+ */
1350
+ function resolveFloatingImageRect(fi, cursorY, contentWidth, contentHeight, geometry, widthPt, heightPt) {
1351
+ const usingSimplePos = fi.simplePos !== undefined;
1352
+ // 1. simplePos: page-absolute. Translate into content-area coords by
1353
+ // subtracting the page margins.
1354
+ if (usingSimplePos) {
1355
+ const pageX = emuToPt(fi.simplePos.x ?? 0);
1356
+ const pageY = emuToPt(fi.simplePos.y ?? 0);
1357
+ return {
1358
+ x: pageX - geometry.marginLeft,
1359
+ y: pageY - geometry.marginTop
1360
+ };
1361
+ }
1362
+ // 2/3. positionH / positionV
1363
+ const xPt = resolveHorizontal(fi, contentWidth, geometry, widthPt) ?? 0;
1364
+ const yPt = resolveVertical(fi, cursorY, contentHeight, geometry, heightPt) ?? cursorY;
1365
+ return { x: xPt, y: yPt };
1366
+ }
1367
+ function resolveHorizontal(fi, contentWidth, geometry, widthPt) {
1368
+ const h = fi.horizontalPosition;
1369
+ if (!h) {
1370
+ return undefined;
1371
+ }
1372
+ const relTo = h.relativeTo ?? "column";
1373
+ // Reference origin (in content-area coordinates) and width to anchor against.
1374
+ let originX = 0;
1375
+ let refWidth = contentWidth;
1376
+ if (relTo === "page") {
1377
+ originX = -geometry.marginLeft;
1378
+ refWidth = geometry.width;
1379
+ }
1380
+ else if (relTo === "margin" || relTo === "leftMargin" || relTo === "rightMargin") {
1381
+ originX = 0;
1382
+ refWidth = contentWidth;
1383
+ } // else: column/character/insideMargin/outsideMargin — fall back to content area
1384
+ if (h.align) {
1385
+ switch (h.align) {
1386
+ case "left":
1387
+ case "inside":
1388
+ return originX;
1389
+ case "right":
1390
+ case "outside":
1391
+ return originX + refWidth - widthPt;
1392
+ case "center":
1393
+ return originX + (refWidth - widthPt) / 2;
1394
+ }
1395
+ }
1396
+ if (h.offset != null) {
1397
+ return originX + emuToPt(h.offset);
1398
+ }
1399
+ return undefined;
1400
+ }
1401
+ function resolveVertical(fi, cursorY, contentHeight, geometry, heightPt) {
1402
+ const v = fi.verticalPosition;
1403
+ if (!v) {
1404
+ return undefined;
1405
+ }
1406
+ const relTo = v.relativeTo ?? "paragraph";
1407
+ let originY = cursorY;
1408
+ let refHeight = contentHeight;
1409
+ if (relTo === "page") {
1410
+ originY = -geometry.marginTop;
1411
+ refHeight = geometry.height;
1412
+ }
1413
+ else if (relTo === "margin" || relTo === "topMargin" || relTo === "bottomMargin") {
1414
+ originY = 0;
1415
+ refHeight = contentHeight;
1416
+ } // else paragraph/line/text-anchored — keep cursor as origin
1417
+ if (v.align) {
1418
+ switch (v.align) {
1419
+ case "top":
1420
+ case "inside":
1421
+ return originY;
1422
+ case "bottom":
1423
+ case "outside":
1424
+ return originY + refHeight - heightPt;
1425
+ case "center":
1426
+ return originY + (refHeight - heightPt) / 2;
1427
+ }
1428
+ }
1429
+ if (v.offset != null) {
1430
+ return originY + emuToPt(v.offset);
1431
+ }
1432
+ return undefined;
1433
+ }
1434
+ function layoutFloatingImage(fi, cursorY, contentWidth, contentHeight, geometry, sourceIndex, imageMap) {
1435
+ const widthPt = emuToPt(fi.width);
1436
+ const heightPt = emuToPt(fi.height);
1437
+ const { x: xPt, y: yPt } = resolveFloatingImageRect(fi, cursorY, contentWidth, contentHeight, geometry, widthPt, heightPt);
1438
+ const img = fi.rId ? imageMap.get(fi.rId) : undefined;
1439
+ const imageContent = img
1440
+ ? {
1441
+ type: "image",
1442
+ rect: { x: xPt, y: yPt, width: widthPt, height: heightPt },
1443
+ data: img.data,
1444
+ mimeType: mediaTypeToMime(img.mediaType),
1445
+ altText: fi.altText,
1446
+ sourceIndex
1447
+ }
1448
+ : {
1449
+ type: "image",
1450
+ rect: { x: xPt, y: yPt, width: widthPt, height: heightPt },
1451
+ data: new Uint8Array(0),
1452
+ mimeType: "application/octet-stream",
1453
+ altText: fi.altText,
1454
+ sourceIndex
1455
+ };
1456
+ return {
1457
+ type: "float",
1458
+ rect: { x: xPt, y: yPt, width: widthPt, height: heightPt },
1459
+ content: imageContent,
1460
+ behindText: fi.behindDoc === true,
1461
+ ...(fi.wrap ? { wrap: convertWrap(fi.wrap) } : {}),
1462
+ sourceIndex
1463
+ };
1464
+ }
1465
+ /**
1466
+ * Translate the source `FloatingImage.wrap` (with `WrapMargins` in EMU)
1467
+ * into the layout-side `LayoutFloatWrap` (with margins already in
1468
+ * points so renderers don't need to know about EMU).
1469
+ */
1470
+ function convertWrap(wrap) {
1471
+ const out = {
1472
+ style: wrap.style
1473
+ };
1474
+ if (wrap.side) {
1475
+ out.side = wrap.side;
1476
+ }
1477
+ if (wrap.margins) {
1478
+ const m = {};
1479
+ if (wrap.margins.top != null) {
1480
+ m.top = emuToPt(wrap.margins.top);
1481
+ }
1482
+ if (wrap.margins.bottom != null) {
1483
+ m.bottom = emuToPt(wrap.margins.bottom);
1484
+ }
1485
+ if (wrap.margins.left != null) {
1486
+ m.left = emuToPt(wrap.margins.left);
1487
+ }
1488
+ if (wrap.margins.right != null) {
1489
+ m.right = emuToPt(wrap.margins.right);
1490
+ }
1491
+ if (Object.keys(m).length > 0) {
1492
+ out.margins = m;
1493
+ }
1494
+ }
1495
+ return out;
1496
+ }
1497
+ function layoutTextBox(tb, startY, contentWidth, sourceIndex, options, imageMap) {
1498
+ const widthPt = tb.width != null ? twipsToPt(tb.width) : contentWidth;
1499
+ // Lay out inner paragraphs against the text-box width; their positions
1500
+ // are returned relative to the box's top-left so renderers translate
1501
+ // by `rect.x`/`rect.y`.
1502
+ const inner = [];
1503
+ let innerCursor = 0;
1504
+ for (const child of tb.content) {
1505
+ const laid = layoutParagraph(child, innerCursor, widthPt, options, undefined, imageMap);
1506
+ inner.push({ ...laid, sourceIndex });
1507
+ innerCursor = laid.rect.y + laid.rect.height;
1508
+ }
1509
+ const heightPt = tb.height != null ? twipsToPt(tb.height) : Math.max(innerCursor, 12);
1510
+ return {
1511
+ type: "textBox",
1512
+ rect: { x: 0, y: startY, width: widthPt, height: heightPt },
1513
+ content: inner,
1514
+ border: tb.stroke && tb.strokeColor
1515
+ ? { width: 0.75, color: normaliseHex(tb.strokeColor) }
1516
+ : undefined,
1517
+ background: tb.fill && tb.fillColor ? normaliseHex(tb.fillColor) : undefined,
1518
+ sourceIndex
1519
+ };
1520
+ }
1521
+ function layoutDrawingShape(shape, startY, contentWidth, sourceIndex, options, imageMap) {
1522
+ const widthPt = emuToPt(shape.width);
1523
+ const heightPt = emuToPt(shape.height);
1524
+ const innerWidth = Math.min(widthPt, contentWidth);
1525
+ const innerContent = [];
1526
+ if (shape.textContent && shape.textContent.length > 0) {
1527
+ let cursor = 0;
1528
+ for (const para of shape.textContent) {
1529
+ const laid = layoutParagraph(para, cursor, innerWidth, options, undefined, imageMap);
1530
+ innerContent.push({ ...laid, sourceIndex });
1531
+ cursor = laid.rect.y + laid.rect.height;
1532
+ }
1533
+ }
1534
+ return {
1535
+ type: "shape",
1536
+ rect: { x: 0, y: startY, width: widthPt, height: heightPt },
1537
+ preset: shape.shapeType,
1538
+ fillColor: shape.noFill ? undefined : normaliseHexOrUndefined(shape.fillColor),
1539
+ strokeColor: shape.noOutline ? undefined : normaliseHexOrUndefined(shape.outlineColor),
1540
+ strokeWidth: shape.outlineWidth != null ? emuToPt(shape.outlineWidth) : undefined,
1541
+ textContent: innerContent.length > 0 ? innerContent : undefined,
1542
+ sourceIndex
1543
+ };
1544
+ }
1545
+ function layoutChart(ch, startY, contentWidth, sourceIndex) {
1546
+ // Source dimensions:
1547
+ // - ChartContent stores width/height inside the inner Chart model
1548
+ // (writer emits `<wp:extent>` from `chart.width/height`; reader
1549
+ // populates them from the original drawing's `<wp:extent>`).
1550
+ // - ChartExContent carries width/height directly on the content.
1551
+ // Both fall back to a 6"×3.5" default that matches Microsoft Word's
1552
+ // default insert size when the source supplied none.
1553
+ const widthEmu = ch.type === "chart" ? (ch.chart?.width ?? 5486400) : (ch.width ?? 5486400);
1554
+ const heightEmu = ch.type === "chart" ? (ch.chart?.height ?? 3200400) : (ch.height ?? 3200400);
1555
+ const widthPt = Math.min(emuToPt(widthEmu), contentWidth);
1556
+ const heightPt = emuToPt(heightEmu);
1557
+ const title = ch.type === "chart" ? (ch.chart?.title ?? ch.name) : ch.name;
1558
+ return {
1559
+ type: "chart",
1560
+ rect: { x: 0, y: startY, width: widthPt, height: heightPt },
1561
+ chartKind: ch.type === "chart" ? "chart" : "chartEx",
1562
+ title,
1563
+ altText: ch.altText,
1564
+ source: ch,
1565
+ sourceIndex
1566
+ };
1567
+ }
1568
+ function layoutSdt(sdt, startY, contentWidth, sourceIndex, options, imageMap) {
1569
+ // SDT is a transparent flow container in layout terms: lay out its
1570
+ // children inline and report a rect that encloses them. Inline-only
1571
+ // children (bare runs) are skipped — the SDT-as-block contract is
1572
+ // what layout cares about.
1573
+ const inner = [];
1574
+ let cursor = 0;
1575
+ for (const child of sdt.content) {
1576
+ if ("type" in child) {
1577
+ if (child.type === "paragraph") {
1578
+ const laid = layoutParagraph(child, cursor, contentWidth, options, undefined, imageMap);
1579
+ inner.push({ ...laid, sourceIndex });
1580
+ cursor = laid.rect.y + laid.rect.height;
1581
+ }
1582
+ else if (child.type === "table") {
1583
+ const laid = layoutTable(child, cursor, contentWidth, sourceIndex, options, imageMap);
1584
+ inner.push(laid);
1585
+ cursor = laid.rect.y + laid.rect.height;
1586
+ }
1587
+ // Run-only SDT children are not flowed at the block level.
1588
+ }
1589
+ }
1590
+ return {
1591
+ type: "sdt",
1592
+ rect: { x: 0, y: startY, width: contentWidth, height: cursor },
1593
+ content: inner,
1594
+ tag: sdt.properties?.tag,
1595
+ alias: sdt.properties?.alias,
1596
+ sourceIndex
1597
+ };
1598
+ }
1599
+ function layoutMath(mb, startY, contentWidth, sourceIndex, options) {
1600
+ const text = (0, text_utils_1.extractMathText)(mb.content);
1601
+ let mathML;
1602
+ try {
1603
+ mathML = (0, math_convert_1.ommlToMathML)(mb.content);
1604
+ }
1605
+ catch {
1606
+ mathML = undefined;
1607
+ }
1608
+ const fontSize = DEFAULT_FONT_SIZE_PT;
1609
+ const lineHeight = fontSize * 1.2;
1610
+ // Width is approximated from the plain-text fallback so renderers that
1611
+ // don't handle MathML still see a reasonable bounding box.
1612
+ const fontName = (0, font_metrics_1.mapToStandardFont)(options?.fonts?.get("Cambria Math") ?? "Cambria Math");
1613
+ const widthPt = Math.min((0, font_metrics_1.measureTextWidth)(text, fontName, fontSize), contentWidth);
1614
+ return {
1615
+ type: "math",
1616
+ rect: { x: 0, y: startY, width: widthPt, height: lineHeight },
1617
+ text,
1618
+ mathML,
1619
+ sourceIndex
1620
+ };
1621
+ }
1622
+ function layoutCheckBox(cb, startY, sourceIndex, options) {
1623
+ const fontSize = DEFAULT_FONT_SIZE_PT;
1624
+ const checked = cb.checked === true;
1625
+ const glyph = checked
1626
+ ? (cb.checkedState?.value ?? "\u2611") // ☑
1627
+ : (cb.uncheckedState?.value ?? "\u2610"); // ☐
1628
+ const fontName = (0, font_metrics_1.mapToStandardFont)(cb.checkedState?.font ?? options?.fonts?.get("MS Gothic") ?? "MS Gothic");
1629
+ const widthPt = (0, font_metrics_1.measureTextWidth)(glyph, fontName, fontSize);
1630
+ return {
1631
+ type: "checkBox",
1632
+ rect: { x: 0, y: startY, width: widthPt, height: fontSize * 1.2 },
1633
+ checked,
1634
+ glyph,
1635
+ fontSize,
1636
+ sourceIndex
1637
+ };
1638
+ }
1639
+ function layoutTableOfContents(toc, startY, contentWidth, sourceIndex, options, imageMap) {
1640
+ const entries = [];
1641
+ let cursor = 0;
1642
+ if (toc.cachedParagraphs && toc.cachedParagraphs.length > 0) {
1643
+ for (const para of toc.cachedParagraphs) {
1644
+ const laid = layoutParagraph(para, cursor, contentWidth, options, undefined, imageMap);
1645
+ entries.push({ ...laid, sourceIndex });
1646
+ cursor = laid.rect.y + laid.rect.height;
1647
+ }
1648
+ }
1649
+ else {
1650
+ // Stub: emit a single placeholder paragraph so renderers always have
1651
+ // something to render. Consumers wanting a real TOC should run
1652
+ // `updateTableOfContents()` before layout.
1653
+ const stub = {
1654
+ type: "paragraph",
1655
+ children: [{ content: [{ type: "text", text: "[Table of Contents]" }] }]
1656
+ };
1657
+ const laid = layoutParagraph(stub, 0, contentWidth, options, undefined, imageMap);
1658
+ entries.push({ ...laid, sourceIndex });
1659
+ cursor = laid.rect.height;
1660
+ }
1661
+ return {
1662
+ type: "tableOfContents",
1663
+ rect: { x: 0, y: startY, width: contentWidth, height: cursor },
1664
+ entries,
1665
+ sourceIndex
1666
+ };
1667
+ }
1668
+ function layoutAltChunk(ac, startY, contentWidth, sourceIndex) {
1669
+ // Layout cannot interpret HTML / RTF / MHT payloads; reserve a
1670
+ // placeholder rect proportional to a small fixed height so renderers
1671
+ // can show a substitution glyph or run their own foreign-content
1672
+ // pipeline.
1673
+ const heightPt = DEFAULT_FONT_SIZE_PT * 3;
1674
+ return {
1675
+ type: "altChunk",
1676
+ rect: { x: 0, y: startY, width: contentWidth, height: heightPt },
1677
+ contentType: ac.contentType ?? "application/octet-stream",
1678
+ fileName: ac.fileName,
1679
+ sourceIndex
1680
+ };
1681
+ }
1682
+ function layoutOpaqueDrawing(od, startY, contentWidth, sourceIndex) {
1683
+ // We have no idea how big the drawing is from XML alone; reserve a
1684
+ // square-ish placeholder roughly matching a typical chart slot. High-
1685
+ // fidelity renderers can re-parse `rawXml` if they need exact size.
1686
+ const heightPt = DEFAULT_FONT_SIZE_PT * 12;
1687
+ return {
1688
+ type: "opaqueDrawing",
1689
+ rect: { x: 0, y: startY, width: contentWidth, height: heightPt },
1690
+ rawXml: od.rawXml,
1691
+ sourceIndex
1692
+ };
1693
+ }
1694
+ function normaliseHex(hex) {
1695
+ return hex.startsWith("#") ? hex.slice(1) : hex;
1696
+ }
1697
+ function normaliseHexOrUndefined(hex) {
1698
+ return hex ? normaliseHex(hex) : undefined;
1699
+ }