@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,1435 @@
1
+ /**
2
+ * DOCX Module - Template Engine
3
+ *
4
+ * A template engine for DOCX documents supporting:
5
+ * - Variable interpolation: {{name}}, {{user.name}}
6
+ * - Conditionals: {{#if cond}}...{{/if}}, {{#if cond}}...{{else}}...{{/if}}
7
+ * - Loops: {{#each items}}...{{/each}} with {{.}}, {{.prop}}, {{@index}}
8
+ * - Table row loops: auto-duplicates table rows when {{#each}} is in a row
9
+ * - Table column loops: {{#cols items}}...{{/cols}} duplicates columns
10
+ * - Image placeholders: {{%image}} resolves to an inline image
11
+ * - RichText placeholders: {{&richText}} resolves to paragraph children
12
+ * - Sub-document insertion: {{>subDoc}} resolves to body content blocks
13
+ * - Chart placeholders: {{^chart}} resolves to chart content
14
+ *
15
+ * Handles cross-run placeholders (Word often splits {{name}} across runs).
16
+ */
17
+ import { utf8Encoder } from "../core/internal-utils.js";
18
+ import { isRun } from "../core/text-utils.js";
19
+ import { DocxError } from "../errors.js";
20
+ /** Error thrown when template processing fails. */
21
+ export class TemplateError extends DocxError {
22
+ constructor(message, placeholder, location, options) {
23
+ super(message, options);
24
+ this.name = "TemplateError";
25
+ this.placeholder = placeholder;
26
+ this.location = location;
27
+ this.tagName = options?.tagName;
28
+ this.paragraphIndex = options?.paragraphIndex;
29
+ this.sectionPath = options?.sectionPath;
30
+ }
31
+ }
32
+ // =============================================================================
33
+ // Token Types (internal)
34
+ // =============================================================================
35
+ var TokenType;
36
+ (function (TokenType) {
37
+ TokenType[TokenType["Text"] = 0] = "Text";
38
+ TokenType[TokenType["Variable"] = 1] = "Variable";
39
+ TokenType[TokenType["IfOpen"] = 2] = "IfOpen";
40
+ TokenType[TokenType["Else"] = 3] = "Else";
41
+ TokenType[TokenType["IfClose"] = 4] = "IfClose";
42
+ TokenType[TokenType["EachOpen"] = 5] = "EachOpen";
43
+ TokenType[TokenType["EachClose"] = 6] = "EachClose";
44
+ })(TokenType || (TokenType = {}));
45
+ // =============================================================================
46
+ // Core: fillTemplate
47
+ // =============================================================================
48
+ /**
49
+ * Fill a DOCX template document with data.
50
+ *
51
+ * Processes all body content, headers, footers, footnotes, and endnotes.
52
+ * Operates on the document model in-place and returns it.
53
+ *
54
+ * @param doc - The parsed DocxDocument model.
55
+ * @param data - Data to fill into the template.
56
+ * @param options - Optional template settings.
57
+ * @returns The same DocxDocument with placeholders resolved.
58
+ */
59
+ export function fillTemplate(doc, data, options) {
60
+ const open = options?.delimiters?.[0] ?? "{{";
61
+ const close = options?.delimiters?.[1] ?? "}}";
62
+ const strict = options?.strict ?? true;
63
+ const ctx = { open, close, strict, data };
64
+ // Process body
65
+ const newBody = processBodyContent(doc.body, ctx, "body");
66
+ doc.body = newBody;
67
+ // Process headers
68
+ if (doc.headers) {
69
+ for (const [key, headerDef] of doc.headers) {
70
+ const newChildren = processBlockList(headerDef.content.children, ctx, `header:${key}`);
71
+ headerDef.content.children = newChildren;
72
+ }
73
+ }
74
+ // Process footers
75
+ if (doc.footers) {
76
+ for (const [key, footerDef] of doc.footers) {
77
+ const newChildren = processBlockList(footerDef.content.children, ctx, `footer:${key}`);
78
+ footerDef.content.children = newChildren;
79
+ }
80
+ }
81
+ // Process footnotes
82
+ if (doc.footnotes) {
83
+ for (const note of doc.footnotes) {
84
+ if (note.id <= 0) {
85
+ continue;
86
+ }
87
+ const processed = processBlockList(note.content, ctx, `footnote:${note.id}`);
88
+ note.content = processed;
89
+ }
90
+ }
91
+ // Process endnotes
92
+ if (doc.endnotes) {
93
+ for (const note of doc.endnotes) {
94
+ if (note.id <= 0) {
95
+ continue;
96
+ }
97
+ const processed = processBlockList(note.content, ctx, `endnote:${note.id}`);
98
+ note.content = processed;
99
+ }
100
+ }
101
+ return doc;
102
+ }
103
+ // =============================================================================
104
+ // Cross-run text merging
105
+ // =============================================================================
106
+ /**
107
+ * Merge all text content from a paragraph's runs into a single string.
108
+ * This is intentionally simple — only extracts raw text from runs (no hyperlinks,
109
+ * no tracked changes) as template placeholders only exist in direct run content.
110
+ */
111
+ function extractParagraphText(para) {
112
+ let result = "";
113
+ for (const child of para.children) {
114
+ if (!isRun(child)) {
115
+ continue;
116
+ }
117
+ for (const c of child.content) {
118
+ if (c.type === "text" && "text" in c) {
119
+ result += c.text;
120
+ }
121
+ }
122
+ }
123
+ return result;
124
+ }
125
+ // =============================================================================
126
+ // Tokenizer
127
+ // =============================================================================
128
+ function tokenize(text, open, close) {
129
+ const tokens = [];
130
+ let pos = 0;
131
+ while (pos < text.length) {
132
+ const startIdx = text.indexOf(open, pos);
133
+ if (startIdx === -1) {
134
+ tokens.push({ type: TokenType.Text, value: text.slice(pos) });
135
+ break;
136
+ }
137
+ if (startIdx > pos) {
138
+ tokens.push({ type: TokenType.Text, value: text.slice(pos, startIdx) });
139
+ }
140
+ const endIdx = text.indexOf(close, startIdx + open.length);
141
+ if (endIdx === -1) {
142
+ // Unclosed delimiter — treat rest as text
143
+ tokens.push({ type: TokenType.Text, value: text.slice(startIdx) });
144
+ break;
145
+ }
146
+ const expr = text.slice(startIdx + open.length, endIdx).trim();
147
+ pos = endIdx + close.length;
148
+ if (expr.startsWith("#if ")) {
149
+ tokens.push({ type: TokenType.IfOpen, condition: expr.slice(4).trim() });
150
+ }
151
+ else if (expr === "else") {
152
+ tokens.push({ type: TokenType.Else });
153
+ }
154
+ else if (expr === "/if") {
155
+ tokens.push({ type: TokenType.IfClose });
156
+ }
157
+ else if (expr.startsWith("#each ")) {
158
+ tokens.push({ type: TokenType.EachOpen, collection: expr.slice(6).trim() });
159
+ }
160
+ else if (expr === "/each") {
161
+ tokens.push({ type: TokenType.EachClose });
162
+ }
163
+ else {
164
+ tokens.push({ type: TokenType.Variable, path: expr });
165
+ }
166
+ }
167
+ return tokens;
168
+ }
169
+ // =============================================================================
170
+ // Value resolution
171
+ // =============================================================================
172
+ function resolvePath(data, path) {
173
+ if (path === ".") {
174
+ // In loop context, "." refers to the current item stored at key "."
175
+ if (data != null && typeof data === "object" && Object.hasOwn(data, ".")) {
176
+ return data["."];
177
+ }
178
+ return data;
179
+ }
180
+ const startPath = path.startsWith(".") ? path.slice(1) : path;
181
+ const parts = startPath.split(".");
182
+ let current = data;
183
+ for (const part of parts) {
184
+ if (current == null || typeof current !== "object") {
185
+ return undefined;
186
+ }
187
+ // Use Object.hasOwn so a template path can never traverse prototype
188
+ // properties (`{{constructor}}`, `{{__proto__.something}}`, …) and
189
+ // surface JS internals into the rendered document. Arrays are
190
+ // handled the same way — numeric indices are own properties.
191
+ if (!Object.hasOwn(current, part)) {
192
+ return undefined;
193
+ }
194
+ current = current[part];
195
+ }
196
+ return current;
197
+ }
198
+ function isTruthy(value) {
199
+ if (Array.isArray(value)) {
200
+ return value.length > 0;
201
+ }
202
+ return !!value;
203
+ }
204
+ function valueToString(value) {
205
+ if (value == null) {
206
+ return "";
207
+ }
208
+ if (typeof value === "object") {
209
+ return JSON.stringify(value);
210
+ }
211
+ return String(value);
212
+ }
213
+ // =============================================================================
214
+ // Processing body content (handles block-level #each and #if)
215
+ // =============================================================================
216
+ function processBodyContent(blocks, ctx, location) {
217
+ const result = [];
218
+ let i = 0;
219
+ while (i < blocks.length) {
220
+ const block = blocks[i];
221
+ if (block.type === "paragraph") {
222
+ const text = extractParagraphText(block);
223
+ // Check if this paragraph starts a block-level #each
224
+ if (hasBlockDirective(text, ctx.open, ctx.close, "#each ")) {
225
+ const collectionExpr = extractDirectiveArg(text, ctx.open, ctx.close, "#each ");
226
+ const endIdx = findClosingBlock(blocks, i, ctx, "#each ", "/each");
227
+ if (endIdx === -1) {
228
+ throw new TemplateError(`Unclosed {{#each ${collectionExpr}}}`, `#each ${collectionExpr}`, location, {
229
+ tagName: `#each ${collectionExpr}`,
230
+ paragraphIndex: i,
231
+ sectionPath: location
232
+ });
233
+ }
234
+ const innerBlocks = blocks.slice(i + 1, endIdx);
235
+ const items = resolvePath(ctx.data, collectionExpr);
236
+ if (Array.isArray(items)) {
237
+ for (let idx = 0; idx < items.length; idx++) {
238
+ const itemData = buildLoopData(items[idx], idx, ctx.data);
239
+ const innerCtx = { ...ctx, data: itemData };
240
+ const processed = processBodyContent(cloneBlocks(innerBlocks), innerCtx, `${location}[${idx}]`);
241
+ result.push(...processed);
242
+ }
243
+ }
244
+ else if (ctx.strict && items !== undefined && items !== null) {
245
+ throw new TemplateError(`{{#each ${collectionExpr}}} expects an array, got ${typeof items}`, `#each ${collectionExpr}`, location, {
246
+ tagName: `#each ${collectionExpr}`,
247
+ paragraphIndex: i,
248
+ sectionPath: location
249
+ });
250
+ }
251
+ i = endIdx + 1;
252
+ continue;
253
+ }
254
+ // Check if this paragraph starts a block-level #if
255
+ if (hasBlockDirective(text, ctx.open, ctx.close, "#if ")) {
256
+ const condExpr = extractDirectiveArg(text, ctx.open, ctx.close, "#if ");
257
+ const { elseIdx, endIdx } = findIfBlock(blocks, i, ctx);
258
+ if (endIdx === -1) {
259
+ throw new TemplateError(`Unclosed {{#if ${condExpr}}}`, `#if ${condExpr}`, location, {
260
+ tagName: `#if ${condExpr}`,
261
+ paragraphIndex: i,
262
+ sectionPath: location
263
+ });
264
+ }
265
+ const condValue = resolvePath(ctx.data, condExpr);
266
+ let innerBlocks;
267
+ if (isTruthy(condValue)) {
268
+ innerBlocks = blocks.slice(i + 1, elseIdx !== -1 ? elseIdx : endIdx);
269
+ }
270
+ else {
271
+ innerBlocks = elseIdx !== -1 ? blocks.slice(elseIdx + 1, endIdx) : [];
272
+ }
273
+ const processed = processBodyContent(cloneBlocks(innerBlocks), ctx, location);
274
+ result.push(...processed);
275
+ i = endIdx + 1;
276
+ continue;
277
+ }
278
+ // Regular paragraph — process inline templates
279
+ try {
280
+ const processed = processParagraph(block, ctx, `${location} para ${i}`);
281
+ result.push(processed);
282
+ }
283
+ catch (err) {
284
+ if (err instanceof TemplateError && err.tagName === undefined) {
285
+ throw new TemplateError(err.message, err.placeholder, err.location, {
286
+ cause: err.cause,
287
+ tagName: err.placeholder,
288
+ paragraphIndex: i,
289
+ sectionPath: location
290
+ });
291
+ }
292
+ throw err;
293
+ }
294
+ i++;
295
+ }
296
+ else if (block.type === "table") {
297
+ const processed = processTable(block, ctx, `${location} table ${i}`);
298
+ result.push(processed);
299
+ i++;
300
+ }
301
+ else if (block.type === "sdt") {
302
+ // Recursively process SDT content (StructuredDocumentTag)
303
+ const sdt = block;
304
+ const processedContent = processBodyContent(sdt.content, ctx, `${location} sdt ${i}`);
305
+ result.push({
306
+ ...sdt,
307
+ content: processedContent
308
+ });
309
+ i++;
310
+ }
311
+ else {
312
+ result.push(block);
313
+ i++;
314
+ }
315
+ }
316
+ return result;
317
+ }
318
+ function processBlockList(blocks, ctx, location) {
319
+ // Reuse body content processing, filtering to Paragraph | Table
320
+ return processBodyContent(blocks, ctx, location);
321
+ }
322
+ // =============================================================================
323
+ // Paragraph processing (inline variable substitution)
324
+ // =============================================================================
325
+ function processParagraph(para, ctx, location) {
326
+ // Merge all run text, resolve inline variables, then rebuild runs
327
+ const fullText = extractParagraphText(para);
328
+ // Quick check: does this paragraph contain any delimiters?
329
+ if (!fullText.includes(ctx.open)) {
330
+ return para;
331
+ }
332
+ // Tokenize and evaluate inline expressions
333
+ const tokens = tokenize(fullText, ctx.open, ctx.close);
334
+ const resolved = evaluateInlineTokens(tokens, ctx, location);
335
+ // If the text didn't change, return as-is
336
+ if (resolved === fullText) {
337
+ return para;
338
+ }
339
+ // Rebuild the paragraph runs with the resolved text
340
+ return rebuildParagraphText(para, resolved);
341
+ }
342
+ /**
343
+ * Evaluate inline tokens (only variables and inline if/each within a single paragraph line).
344
+ * For simplicity, inline conditionals and loops are evaluated as text.
345
+ */
346
+ function evaluateInlineTokens(tokens, ctx, location) {
347
+ let result = "";
348
+ let i = 0;
349
+ while (i < tokens.length) {
350
+ const token = tokens[i];
351
+ switch (token.type) {
352
+ case TokenType.Text:
353
+ result += token.value;
354
+ i++;
355
+ break;
356
+ case TokenType.Variable: {
357
+ const path = token.path;
358
+ let value;
359
+ if (path === "@index") {
360
+ value = resolvePath(ctx.data, "@index");
361
+ }
362
+ else {
363
+ value = resolvePath(ctx.data, path);
364
+ }
365
+ if (value === undefined && ctx.strict) {
366
+ throw new TemplateError(`Unresolved variable: {{${path}}}`, path, location, {
367
+ tagName: path,
368
+ sectionPath: location
369
+ });
370
+ }
371
+ result += valueToString(value);
372
+ i++;
373
+ break;
374
+ }
375
+ case TokenType.IfOpen: {
376
+ // Inline if: collect tokens until matching /if
377
+ const condValue = resolvePath(ctx.data, token.condition);
378
+ const { trueBranch, falseBranch, endIndex } = collectInlineIf(tokens, i);
379
+ if (endIndex === -1) {
380
+ throw new TemplateError(`Unclosed inline {{#if ${token.condition}}}`, `#if ${token.condition}`, location, { tagName: `#if ${token.condition}`, sectionPath: location });
381
+ }
382
+ if (isTruthy(condValue)) {
383
+ result += evaluateInlineTokens(trueBranch, ctx, location);
384
+ }
385
+ else {
386
+ result += evaluateInlineTokens(falseBranch, ctx, location);
387
+ }
388
+ i = endIndex + 1;
389
+ break;
390
+ }
391
+ case TokenType.EachOpen: {
392
+ // Inline each: collect tokens until matching /each
393
+ const items = resolvePath(ctx.data, token.collection);
394
+ const { body, endIndex } = collectInlineEach(tokens, i);
395
+ if (endIndex === -1) {
396
+ throw new TemplateError(`Unclosed inline {{#each ${token.collection}}}`, `#each ${token.collection}`, location, { tagName: `#each ${token.collection}`, sectionPath: location });
397
+ }
398
+ if (Array.isArray(items)) {
399
+ for (let idx = 0; idx < items.length; idx++) {
400
+ const itemData = buildLoopData(items[idx], idx, ctx.data);
401
+ const innerCtx = { ...ctx, data: itemData };
402
+ result += evaluateInlineTokens(body, innerCtx, location);
403
+ }
404
+ }
405
+ i = endIndex + 1;
406
+ break;
407
+ }
408
+ default:
409
+ // Stray else/close tokens — skip
410
+ i++;
411
+ break;
412
+ }
413
+ }
414
+ return result;
415
+ }
416
+ function collectInlineIf(tokens, startIdx) {
417
+ let depth = 0;
418
+ const trueBranch = [];
419
+ const falseBranch = [];
420
+ let inElse = false;
421
+ let endIndex = -1;
422
+ for (let i = startIdx + 1; i < tokens.length; i++) {
423
+ const t = tokens[i];
424
+ if (t.type === TokenType.IfOpen) {
425
+ depth++;
426
+ (inElse ? falseBranch : trueBranch).push(t);
427
+ }
428
+ else if (t.type === TokenType.IfClose) {
429
+ if (depth === 0) {
430
+ endIndex = i;
431
+ break;
432
+ }
433
+ depth--;
434
+ (inElse ? falseBranch : trueBranch).push(t);
435
+ }
436
+ else if (t.type === TokenType.Else && depth === 0) {
437
+ inElse = true;
438
+ }
439
+ else {
440
+ (inElse ? falseBranch : trueBranch).push(t);
441
+ }
442
+ }
443
+ return { trueBranch, falseBranch, endIndex };
444
+ }
445
+ function collectInlineEach(tokens, startIdx) {
446
+ let depth = 0;
447
+ const body = [];
448
+ let endIndex = -1;
449
+ for (let i = startIdx + 1; i < tokens.length; i++) {
450
+ const t = tokens[i];
451
+ if (t.type === TokenType.EachOpen) {
452
+ depth++;
453
+ body.push(t);
454
+ }
455
+ else if (t.type === TokenType.EachClose) {
456
+ if (depth === 0) {
457
+ endIndex = i;
458
+ break;
459
+ }
460
+ depth--;
461
+ body.push(t);
462
+ }
463
+ else {
464
+ body.push(t);
465
+ }
466
+ }
467
+ return { body, endIndex };
468
+ }
469
+ // =============================================================================
470
+ // Rebuild paragraph with new text content
471
+ // =============================================================================
472
+ /**
473
+ * Rebuild a paragraph's run text content with a new resolved string.
474
+ * Preserves the formatting of the first text run.
475
+ */
476
+ function rebuildParagraphText(para, newText) {
477
+ // Find the first run with text content to use as formatting reference
478
+ let refProperties;
479
+ for (const child of para.children) {
480
+ if (!isRun(child)) {
481
+ continue;
482
+ }
483
+ for (const c of child.content) {
484
+ if (c.type === "text") {
485
+ refProperties = child.properties;
486
+ break;
487
+ }
488
+ }
489
+ if (refProperties !== undefined) {
490
+ break;
491
+ }
492
+ }
493
+ // If no text runs found, get properties from first run
494
+ if (refProperties === undefined) {
495
+ for (const child of para.children) {
496
+ if (isRun(child)) {
497
+ refProperties = child.properties;
498
+ break;
499
+ }
500
+ }
501
+ }
502
+ // Build new children:
503
+ // - replace the first Run we see with `newRun` (carrying the resolved text);
504
+ // - drop every other Run (their text was already concatenated into newText);
505
+ // - keep non-Run children (bookmarkStart / bookmarkEnd / commentRangeStart /
506
+ // commentRangeEnd / hyperlink / insertedRun / movedToRun / etc.) at
507
+ // their original index. Reordering these silently miswires bookmark and
508
+ // comment ranges, since the start/end markers stop bracketing the
509
+ // intended content.
510
+ const newRun = {
511
+ properties: refProperties,
512
+ content: [{ type: "text", text: newText }]
513
+ };
514
+ const newChildren = [];
515
+ let runReplaced = false;
516
+ for (const child of para.children) {
517
+ if (isRun(child)) {
518
+ if (!runReplaced) {
519
+ newChildren.push(newRun);
520
+ runReplaced = true;
521
+ }
522
+ // Subsequent runs are absorbed into newRun's text — drop them.
523
+ }
524
+ else {
525
+ newChildren.push(child);
526
+ }
527
+ }
528
+ // If the paragraph had no runs at all (rare — typically all bookmark
529
+ // markers), append newRun at the end so the rendered text still appears.
530
+ if (!runReplaced) {
531
+ newChildren.push(newRun);
532
+ }
533
+ return {
534
+ ...para,
535
+ children: newChildren
536
+ };
537
+ }
538
+ // =============================================================================
539
+ // Table processing (row-level loops)
540
+ // =============================================================================
541
+ function processTable(table, ctx, location) {
542
+ const newRows = [];
543
+ let i = 0;
544
+ while (i < table.rows.length) {
545
+ const row = table.rows[i];
546
+ const rowText = extractRowText(row);
547
+ // Check if this row contains a #each directive
548
+ if (rowText.includes(ctx.open + "#each ") || rowText.includes(ctx.open + " #each ")) {
549
+ const collectionExpr = extractDirectiveFromText(rowText, ctx.open, ctx.close, "#each ");
550
+ if (collectionExpr) {
551
+ // Find the closing row
552
+ const endRowIdx = findClosingTableRow(table.rows, i, ctx);
553
+ if (endRowIdx === -1) {
554
+ throw new TemplateError(`Unclosed {{#each ${collectionExpr}}} in table row`, `#each ${collectionExpr}`, location, {
555
+ tagName: `#each ${collectionExpr}`,
556
+ paragraphIndex: i,
557
+ sectionPath: location
558
+ });
559
+ }
560
+ const items = resolvePath(ctx.data, collectionExpr);
561
+ if (Array.isArray(items)) {
562
+ // If the loop is on a single row (open and close on same row)
563
+ if (endRowIdx === i) {
564
+ for (let idx = 0; idx < items.length; idx++) {
565
+ const itemData = buildLoopData(items[idx], idx, ctx.data);
566
+ const innerCtx = { ...ctx, data: itemData };
567
+ const clonedRow = cloneRow(row);
568
+ const processedRow = processTableRow(clonedRow, innerCtx, location);
569
+ // Strip the #each and /each tags from the row
570
+ const cleanedRow = stripDirectivesFromRow(processedRow, ctx, "#each ", "/each");
571
+ newRows.push(cleanedRow);
572
+ }
573
+ }
574
+ else {
575
+ // Multi-row loop: duplicate all rows between open and close
576
+ const templateRows = table.rows.slice(i, endRowIdx + 1);
577
+ for (let idx = 0; idx < items.length; idx++) {
578
+ const itemData = buildLoopData(items[idx], idx, ctx.data);
579
+ const innerCtx = { ...ctx, data: itemData };
580
+ for (const templateRow of templateRows) {
581
+ const clonedRow = cloneRow(templateRow);
582
+ const processedRow = processTableRow(clonedRow, innerCtx, location);
583
+ const cleanedRow = stripDirectivesFromRow(processedRow, ctx, "#each ", "/each");
584
+ newRows.push(cleanedRow);
585
+ }
586
+ }
587
+ }
588
+ }
589
+ i = endRowIdx + 1;
590
+ continue;
591
+ }
592
+ }
593
+ // Regular row: process inline templates in each cell
594
+ const processedRow = processTableRow(row, ctx, location);
595
+ newRows.push(processedRow);
596
+ i++;
597
+ }
598
+ return {
599
+ ...table,
600
+ rows: newRows
601
+ };
602
+ }
603
+ function processTableRow(row, ctx, location) {
604
+ const newCells = [];
605
+ for (const cell of row.cells) {
606
+ const newContent = [];
607
+ for (const block of cell.content) {
608
+ if (block.type === "paragraph") {
609
+ newContent.push(processParagraph(block, ctx, location));
610
+ }
611
+ else if (block.type === "table") {
612
+ newContent.push(processTable(block, ctx, location));
613
+ }
614
+ else {
615
+ newContent.push(block);
616
+ }
617
+ }
618
+ newCells.push({ ...cell, content: newContent });
619
+ }
620
+ return { ...row, cells: newCells };
621
+ }
622
+ function extractRowText(row) {
623
+ let text = "";
624
+ for (const cell of row.cells) {
625
+ for (const block of cell.content) {
626
+ if (block.type === "paragraph") {
627
+ text += extractParagraphText(block);
628
+ }
629
+ }
630
+ }
631
+ return text;
632
+ }
633
+ function findClosingTableRow(rows, startIdx, ctx) {
634
+ // We start AFTER having seen exactly one `{{#each ...}}` token, so the
635
+ // virtual depth at the boundary into row `startIdx` is 1. Each row can
636
+ // contain any mix of `{{#each ...}}` opens and `{{/each}}` closes; we
637
+ // increment the depth by `opens` and decrement by `closes`. The first
638
+ // row where depth hits zero is the closing row.
639
+ //
640
+ // A previous implementation lumped both adjustments together and
641
+ // returned as soon as `depth === 0 && closes > 0`, which mis-handled
642
+ // rows containing two opens and one close (depth ends at 1, but the
643
+ // intermediate calculation hit a transient zero).
644
+ let depth = 1;
645
+ for (let i = startIdx; i < rows.length; i++) {
646
+ const text = extractRowText(rows[i]);
647
+ let opens = countOccurrences(text, ctx.open + "#each ");
648
+ const closes = countOccurrences(text, ctx.open + "/each" + ctx.close);
649
+ // The opening `{{#each ...}}` of the current loop is in row
650
+ // startIdx; don't count it as opening a new nested loop.
651
+ if (i === startIdx && opens > 0) {
652
+ opens--;
653
+ }
654
+ // Walk the row token-by-token in opens-then-closes order. We don't
655
+ // know the actual interleave from raw counts, so we apply opens
656
+ // first, then closes — opens always come before their matching
657
+ // close in valid templates, and a row that closes more than it
658
+ // opens (other than the top-level close in this very row) is
659
+ // malformed input we should still terminate on.
660
+ depth += opens;
661
+ if (depth <= 0 && opens === 0 && closes === 0) {
662
+ // Defensive: should never happen because we entered with depth=1.
663
+ return -1;
664
+ }
665
+ if (closes >= depth) {
666
+ // Consume `depth` worth of closes in this row; the remainder, if
667
+ // any, is malformed but stops the search here.
668
+ return i;
669
+ }
670
+ depth -= closes;
671
+ }
672
+ return -1;
673
+ }
674
+ function stripDirectivesFromRow(row, ctx, openDir, closeDir) {
675
+ const newCells = [];
676
+ for (const cell of row.cells) {
677
+ const newContent = [];
678
+ for (const block of cell.content) {
679
+ if (block.type === "paragraph") {
680
+ const text = extractParagraphText(block);
681
+ // Remove directive tags
682
+ const openPattern = ctx.open + openDir;
683
+ const closePattern = ctx.open + closeDir + ctx.close;
684
+ if (text.includes(openPattern) || text.includes(closePattern)) {
685
+ let cleaned = text;
686
+ // Remove the entire {{#each ...}} tag
687
+ const eachOpenRegex = new RegExp(escapeRegex(ctx.open) +
688
+ "\\s*" +
689
+ escapeRegex(openDir) +
690
+ "[^" +
691
+ escapeRegex(ctx.close.charAt(0)) +
692
+ "]*" +
693
+ escapeRegex(ctx.close), "g");
694
+ cleaned = cleaned.replace(eachOpenRegex, "");
695
+ // Remove {{/each}}
696
+ const eachCloseRegex = new RegExp(escapeRegex(ctx.open) +
697
+ "\\s*" +
698
+ escapeRegex(closeDir) +
699
+ "\\s*" +
700
+ escapeRegex(ctx.close), "g");
701
+ cleaned = cleaned.replace(eachCloseRegex, "");
702
+ cleaned = cleaned.trim();
703
+ if (cleaned.length > 0) {
704
+ newContent.push(rebuildParagraphText(block, cleaned));
705
+ }
706
+ else {
707
+ // Keep at least one paragraph in a cell
708
+ newContent.push(rebuildParagraphText(block, ""));
709
+ }
710
+ }
711
+ else {
712
+ newContent.push(block);
713
+ }
714
+ }
715
+ else {
716
+ newContent.push(block);
717
+ }
718
+ }
719
+ newCells.push({
720
+ ...cell,
721
+ content: newContent.length > 0 ? newContent : [{ type: "paragraph", children: [] }]
722
+ });
723
+ }
724
+ return { ...row, cells: newCells };
725
+ }
726
+ // =============================================================================
727
+ // Block-level directive helpers
728
+ // =============================================================================
729
+ function hasBlockDirective(text, open, close, directive) {
730
+ // Block-level directives must occupy the *entire* paragraph (modulo
731
+ // surrounding whitespace). A paragraph like "Hello {{#if x}}A{{/if}}"
732
+ // contains an *inline* directive and must not be re-classified as a block
733
+ // directive — otherwise the engine tries to find the block close on
734
+ // following paragraphs and emits "Unclosed {{#if x}}" errors.
735
+ const trimmed = text.trim();
736
+ const opener = open + directive;
737
+ if (!trimmed.startsWith(opener)) {
738
+ return false;
739
+ }
740
+ // The opener tag must close before any other text follows. e.g. valid:
741
+ // "{{#if x}}" → block
742
+ // "{{#if x}}\n" → block
743
+ // "{{#if x}}foo" → inline (has trailing content on same paragraph)
744
+ const tagEnd = trimmed.indexOf(close, opener.length);
745
+ if (tagEnd === -1) {
746
+ return false;
747
+ }
748
+ const afterTag = trimmed.slice(tagEnd + close.length).trim();
749
+ return afterTag.length === 0;
750
+ }
751
+ function extractDirectiveArg(text, open, close, directive) {
752
+ const startIdx = text.indexOf(open + directive);
753
+ if (startIdx === -1) {
754
+ // Try with space variations
755
+ const idx = text.indexOf(open + " " + directive);
756
+ if (idx === -1) {
757
+ return "";
758
+ }
759
+ const argStart = idx + open.length + 1 + directive.length;
760
+ const endIdx = text.indexOf(close, argStart);
761
+ if (endIdx === -1) {
762
+ return "";
763
+ }
764
+ return text.slice(argStart, endIdx).trim();
765
+ }
766
+ const argStart = startIdx + open.length + directive.length;
767
+ const endIdx = text.indexOf(close, argStart);
768
+ if (endIdx === -1) {
769
+ return "";
770
+ }
771
+ return text.slice(argStart, endIdx).trim();
772
+ }
773
+ function extractDirectiveFromText(text, open, close, directive) {
774
+ const pattern = open + directive;
775
+ const idx = text.indexOf(pattern);
776
+ if (idx === -1) {
777
+ return null;
778
+ }
779
+ const argStart = idx + pattern.length;
780
+ const endIdx = text.indexOf(close, argStart);
781
+ if (endIdx === -1) {
782
+ return null;
783
+ }
784
+ return text.slice(argStart, endIdx).trim();
785
+ }
786
+ function findClosingBlock(blocks, startIdx, ctx, openDir, closeDir) {
787
+ let depth = 0;
788
+ for (let i = startIdx + 1; i < blocks.length; i++) {
789
+ const block = blocks[i];
790
+ if (block.type !== "paragraph") {
791
+ continue;
792
+ }
793
+ const text = extractParagraphText(block);
794
+ if (hasBlockDirective(text, ctx.open, ctx.close, openDir)) {
795
+ depth++;
796
+ }
797
+ if (text.includes(ctx.open + closeDir + ctx.close) ||
798
+ text.includes(ctx.open + " " + closeDir + " " + ctx.close)) {
799
+ if (depth === 0) {
800
+ return i;
801
+ }
802
+ depth--;
803
+ }
804
+ }
805
+ return -1;
806
+ }
807
+ function findIfBlock(blocks, startIdx, ctx) {
808
+ let depth = 0;
809
+ let elseIdx = -1;
810
+ for (let i = startIdx + 1; i < blocks.length; i++) {
811
+ const block = blocks[i];
812
+ if (block.type !== "paragraph") {
813
+ continue;
814
+ }
815
+ const text = extractParagraphText(block);
816
+ // A single paragraph can legitimately contain both `{{#if cond}}` and
817
+ // `{{/if}}` (an inline if). Count opens and closes independently so the
818
+ // pairing logic stays correct in that case — the previous else-if chain
819
+ // would advance `depth` and then skip the close, leaving the block
820
+ // permanently unterminated.
821
+ const openCount = countOccurrences(text, ctx.open + "#if ");
822
+ const closeCount = countOccurrences(text, ctx.open + "/if" + ctx.close) +
823
+ countOccurrences(text, ctx.open + " /if " + ctx.close);
824
+ if (closeCount > 0) {
825
+ // Account for inline opens first, then balance closes against the
826
+ // outstanding depth.
827
+ depth += openCount;
828
+ for (let c = 0; c < closeCount; c++) {
829
+ if (depth === 0) {
830
+ return { elseIdx, endIdx: i };
831
+ }
832
+ depth--;
833
+ }
834
+ }
835
+ else if (openCount > 0) {
836
+ depth += openCount;
837
+ }
838
+ else if (depth === 0 &&
839
+ (text.trim() === ctx.open + "else" + ctx.close ||
840
+ text.includes(ctx.open + "else" + ctx.close))) {
841
+ elseIdx = i;
842
+ }
843
+ }
844
+ return { elseIdx, endIdx: -1 };
845
+ }
846
+ // =============================================================================
847
+ // Loop data construction
848
+ // =============================================================================
849
+ function buildLoopData(item, index, parentData) {
850
+ // Build the loop context on a null-prototype object so that an item
851
+ // like `{ "__proto__": { injected: "X" } }` (which JSON.parse will
852
+ // produce as an own enumerable data property — a known
853
+ // prototype-pollution vector) cannot retarget the result's prototype
854
+ // and leak hidden fields into the rendered document.
855
+ const result = Object.create(null);
856
+ for (const key of Object.keys(parentData)) {
857
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
858
+ // Skip dangerous keys at the parent level too.
859
+ continue;
860
+ }
861
+ result[key] = parentData[key];
862
+ }
863
+ result["@index"] = index;
864
+ result["."] = item;
865
+ // If item is an object, spread its OWN properties so {{.name}} and
866
+ // {{name}} both work. Skip the same dangerous key set defensively.
867
+ if (item != null && typeof item === "object" && !Array.isArray(item)) {
868
+ const obj = item;
869
+ for (const key of Object.keys(obj)) {
870
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
871
+ continue;
872
+ }
873
+ // Object.hasOwn ensures we never copy something that came from the
874
+ // prototype (Object.keys already returns only own enumerables, but
875
+ // belt-and-braces).
876
+ if (Object.hasOwn(obj, key)) {
877
+ result[key] = obj[key];
878
+ }
879
+ }
880
+ }
881
+ return result;
882
+ }
883
+ // =============================================================================
884
+ // Cloning helpers
885
+ // =============================================================================
886
+ function cloneBlocks(blocks) {
887
+ return structuredClone(blocks);
888
+ }
889
+ function cloneRow(row) {
890
+ return structuredClone(row);
891
+ }
892
+ // =============================================================================
893
+ // Utility
894
+ // =============================================================================
895
+ function countOccurrences(text, search) {
896
+ let count = 0;
897
+ let pos = 0;
898
+ while (true) {
899
+ const idx = text.indexOf(search, pos);
900
+ if (idx === -1) {
901
+ break;
902
+ }
903
+ count++;
904
+ pos = idx + search.length;
905
+ }
906
+ return count;
907
+ }
908
+ function escapeRegex(str) {
909
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
910
+ }
911
+ // =============================================================================
912
+ // Tag Listing: discover all template placeholders in a document
913
+ // =============================================================================
914
+ /**
915
+ * List all template tags found in a document.
916
+ *
917
+ * Scans body, headers, footers, footnotes, and endnotes for template
918
+ * placeholders. Useful for validating data objects against templates.
919
+ *
920
+ * @param doc - The parsed DocxDocument model.
921
+ * @param options - Optional settings (custom delimiters).
922
+ * @returns Array of all discovered template tags.
923
+ */
924
+ export function listTemplateTags(doc, options) {
925
+ const open = options?.delimiters?.[0] ?? "{{";
926
+ const close = options?.delimiters?.[1] ?? "}}";
927
+ const tags = [];
928
+ function scanBlocks(blocks, location) {
929
+ for (let i = 0; i < blocks.length; i++) {
930
+ const block = blocks[i];
931
+ if (block.type === "paragraph") {
932
+ scanParagraph(block, `${location} paragraph ${i}`);
933
+ }
934
+ else if (block.type === "table") {
935
+ scanTable(block, `${location} table ${i}`);
936
+ }
937
+ }
938
+ }
939
+ function scanParagraph(para, location) {
940
+ const text = extractParagraphText(para);
941
+ scanText(text, location);
942
+ }
943
+ function scanTable(table, location) {
944
+ for (let r = 0; r < table.rows.length; r++) {
945
+ const row = table.rows[r];
946
+ for (let c = 0; c < row.cells.length; c++) {
947
+ const cell = row.cells[c];
948
+ for (let b = 0; b < cell.content.length; b++) {
949
+ const block = cell.content[b];
950
+ if (block.type === "paragraph") {
951
+ scanParagraph(block, `${location} row ${r} cell ${c}`);
952
+ }
953
+ else if (block.type === "table") {
954
+ scanTable(block, `${location} row ${r} cell ${c}`);
955
+ }
956
+ }
957
+ }
958
+ }
959
+ }
960
+ function scanText(text, location) {
961
+ let pos = 0;
962
+ while (pos < text.length) {
963
+ const startIdx = text.indexOf(open, pos);
964
+ if (startIdx === -1) {
965
+ break;
966
+ }
967
+ const endIdx = text.indexOf(close, startIdx + open.length);
968
+ if (endIdx === -1) {
969
+ break;
970
+ }
971
+ const expr = text.slice(startIdx + open.length, endIdx).trim();
972
+ pos = endIdx + close.length;
973
+ if (expr.startsWith("#if ")) {
974
+ tags.push({ expression: expr, type: "ifOpen", location });
975
+ }
976
+ else if (expr === "else") {
977
+ tags.push({ expression: expr, type: "else", location });
978
+ }
979
+ else if (expr === "/if") {
980
+ tags.push({ expression: expr, type: "ifClose", location });
981
+ }
982
+ else if (expr.startsWith("#each ")) {
983
+ tags.push({ expression: expr, type: "eachOpen", location });
984
+ }
985
+ else if (expr === "/each") {
986
+ tags.push({ expression: expr, type: "eachClose", location });
987
+ }
988
+ else if (expr.startsWith("#cols ")) {
989
+ tags.push({ expression: expr, type: "colsOpen", location });
990
+ }
991
+ else if (expr === "/cols") {
992
+ tags.push({ expression: expr, type: "colsClose", location });
993
+ }
994
+ else if (expr.startsWith("%")) {
995
+ tags.push({ expression: expr, type: "image", location });
996
+ }
997
+ else if (expr.startsWith("&")) {
998
+ tags.push({ expression: expr, type: "richText", location });
999
+ }
1000
+ else if (expr.startsWith(">")) {
1001
+ tags.push({ expression: expr, type: "subDocument", location });
1002
+ }
1003
+ else if (expr.startsWith("^")) {
1004
+ tags.push({ expression: expr, type: "chart", location });
1005
+ }
1006
+ else if (expr.startsWith("!")) {
1007
+ tags.push({ expression: expr, type: "htmlChunk", location });
1008
+ }
1009
+ else {
1010
+ tags.push({ expression: expr, type: "variable", location });
1011
+ }
1012
+ }
1013
+ }
1014
+ // Scan body
1015
+ scanBlocks(doc.body, "body");
1016
+ // Scan headers
1017
+ if (doc.headers) {
1018
+ for (const [key, headerDef] of doc.headers) {
1019
+ scanBlocks(headerDef.content.children, `header:${key}`);
1020
+ }
1021
+ }
1022
+ // Scan footers
1023
+ if (doc.footers) {
1024
+ for (const [key, footerDef] of doc.footers) {
1025
+ scanBlocks(footerDef.content.children, `footer:${key}`);
1026
+ }
1027
+ }
1028
+ // Scan footnotes
1029
+ if (doc.footnotes) {
1030
+ for (const note of doc.footnotes) {
1031
+ if (note.id <= 0) {
1032
+ continue;
1033
+ }
1034
+ scanBlocks(note.content, `footnote:${note.id}`);
1035
+ }
1036
+ }
1037
+ // Scan endnotes
1038
+ if (doc.endnotes) {
1039
+ for (const note of doc.endnotes) {
1040
+ if (note.id <= 0) {
1041
+ continue;
1042
+ }
1043
+ scanBlocks(note.content, `endnote:${note.id}`);
1044
+ }
1045
+ }
1046
+ return tags;
1047
+ }
1048
+ // =============================================================================
1049
+ // Enhanced value resolution for image/richText/subDocument
1050
+ // =============================================================================
1051
+ function isTemplateImage(v) {
1052
+ return v != null && typeof v === "object" && "image" in v && "width" in v && "height" in v;
1053
+ }
1054
+ function isTemplateRichText(v) {
1055
+ if (!Array.isArray(v)) {
1056
+ return false;
1057
+ }
1058
+ // Check that it looks like an array of Run objects (has .content array)
1059
+ return v.length > 0 && "content" in v[0] && Array.isArray(v[0].content);
1060
+ }
1061
+ function isTemplateSubDocument(v) {
1062
+ if (!Array.isArray(v)) {
1063
+ return false;
1064
+ }
1065
+ // Check that it looks like body content blocks (has .type)
1066
+ return v.length > 0 && "type" in v[0];
1067
+ }
1068
+ export function isTemplateChart(v) {
1069
+ return v != null && typeof v === "object" && "chart" in v && !("type" in v);
1070
+ }
1071
+ function isTemplateHtmlChunk(v) {
1072
+ return (v != null &&
1073
+ typeof v === "object" &&
1074
+ "html" in v &&
1075
+ typeof v.html === "string");
1076
+ }
1077
+ /**
1078
+ * Enhanced fillTemplate that supports image (%img), richText (&rt),
1079
+ * subDocument (>sub), and chart (^chart) placeholders in addition to the
1080
+ * standard variable, conditional, and loop directives.
1081
+ *
1082
+ * Image placeholder: {{%imagePath}} — value must be a TemplateImage object.
1083
+ * RichText placeholder: {{&richPath}} — value must be TemplateRichText (Run[]).
1084
+ * SubDocument placeholder: {{>subPath}} — value must be TemplateSubDocument (BodyContent[]).
1085
+ * Chart placeholder: {{^chartPath}} — value must be a TemplateChart object.
1086
+ */
1087
+ export function fillTemplateEnhanced(doc, data, options) {
1088
+ const open = options?.delimiters?.[0] ?? "{{";
1089
+ const close = options?.delimiters?.[1] ?? "}}";
1090
+ const strict = options?.strict ?? true;
1091
+ // First pass: handle image / richText / subDocument in body
1092
+ const collectedImages = [];
1093
+ const newBody = processEnhancedBody(doc.body, data, open, close, strict, collectedImages);
1094
+ // Merge collected images into doc.images (avoid duplicates by fileName)
1095
+ const images = doc.images ? [...doc.images] : [];
1096
+ for (const img of collectedImages) {
1097
+ if (!images.some(existing => existing.fileName === img.fileName)) {
1098
+ images.push(img);
1099
+ }
1100
+ }
1101
+ // Second pass: standard fillTemplate. Note that `fillTemplate` mutates
1102
+ // its input doc in place (it edits `headerDef.content.children` and the
1103
+ // body array directly), so we hand it a deep-cloned wrapper to avoid
1104
+ // sneaking edits back into the caller's doc through shared references
1105
+ // (`modifiedDoc.headers === doc.headers` would otherwise propagate
1106
+ // mutations into `doc`).
1107
+ const modifiedDoc = {
1108
+ ...doc,
1109
+ body: newBody,
1110
+ images: images.length > 0 ? images : undefined,
1111
+ ...(doc.headers
1112
+ ? {
1113
+ headers: new Map(Array.from(doc.headers, ([k, h]) => [
1114
+ k,
1115
+ {
1116
+ ...h,
1117
+ content: { ...h.content, children: [...h.content.children] }
1118
+ }
1119
+ ]))
1120
+ }
1121
+ : {}),
1122
+ ...(doc.footers
1123
+ ? {
1124
+ footers: new Map(Array.from(doc.footers, ([k, f]) => [
1125
+ k,
1126
+ {
1127
+ ...f,
1128
+ content: { ...f.content, children: [...f.content.children] }
1129
+ }
1130
+ ]))
1131
+ }
1132
+ : {}),
1133
+ ...(doc.footnotes
1134
+ ? { footnotes: doc.footnotes.map(fn => ({ ...fn, content: [...fn.content] })) }
1135
+ : {}),
1136
+ ...(doc.endnotes
1137
+ ? { endnotes: doc.endnotes.map(en => ({ ...en, content: [...en.content] })) }
1138
+ : {})
1139
+ };
1140
+ return fillTemplate(modifiedDoc, data, options);
1141
+ }
1142
+ function processEnhancedBody(blocks, data, open, close, strict, collectedImages) {
1143
+ const result = [];
1144
+ for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) {
1145
+ const block = blocks[blockIndex];
1146
+ if (block.type === "paragraph") {
1147
+ const text = extractParagraphText(block);
1148
+ // Check for HTML chunk placeholder ({{!htmlPath}})
1149
+ const htmlMatch = matchSinglePlaceholder(text, open, close, "!");
1150
+ if (htmlMatch) {
1151
+ const value = resolvePath(data, htmlMatch);
1152
+ if (isTemplateHtmlChunk(value)) {
1153
+ const seq = nextAltChunkSeq();
1154
+ const altChunk = {
1155
+ type: "altChunk",
1156
+ // Use a process-monotonic sequence so two `fillTemplate`
1157
+ // calls on the same template don't collide on rId or path.
1158
+ rId: `rId_altchunk_${seq}`,
1159
+ contentType: value.contentType ?? "text/html",
1160
+ data: utf8Encoder.encode(value.html),
1161
+ fileName: `afchunk${seq}.html`
1162
+ };
1163
+ result.push(altChunk);
1164
+ continue;
1165
+ }
1166
+ }
1167
+ // Check for sub-document placeholder (entire paragraph is the placeholder)
1168
+ const subMatch = matchSinglePlaceholder(text, open, close, ">");
1169
+ if (subMatch) {
1170
+ const value = resolvePath(data, subMatch);
1171
+ if (isTemplateSubDocument(value)) {
1172
+ result.push(...value);
1173
+ continue;
1174
+ }
1175
+ }
1176
+ // Check for image placeholder (with optional conditional prefix)
1177
+ const imgMatch = matchSinglePlaceholder(text, open, close, "%");
1178
+ if (imgMatch) {
1179
+ // Check for conditional image: {{%?condPath.imagePath}}
1180
+ if (imgMatch.startsWith("?")) {
1181
+ const rest = imgMatch.slice(1); // remove leading '?'
1182
+ const dotIdx = rest.indexOf(".");
1183
+ if (dotIdx !== -1) {
1184
+ const condPath = rest.slice(0, dotIdx);
1185
+ const imagePath = rest.slice(dotIdx + 1);
1186
+ const condValue = resolvePath(data, condPath);
1187
+ if (!isTruthy(condValue)) {
1188
+ // Condition is falsy — skip, don't insert anything
1189
+ continue;
1190
+ }
1191
+ // Condition is truthy — resolve the image
1192
+ const value = resolvePath(data, imagePath);
1193
+ if (isTemplateImage(value)) {
1194
+ const safeFileName = sanitizeTemplateImageFileName(value.image.fileName);
1195
+ const rId = value.image.rId ?? `rId_tpl_${nextTemplateImageSeq()}`;
1196
+ const imgContent = {
1197
+ type: "image",
1198
+ rId,
1199
+ width: value.width,
1200
+ height: value.height,
1201
+ altText: value.altText ?? safeFileName,
1202
+ name: safeFileName
1203
+ };
1204
+ const newPara = {
1205
+ type: "paragraph",
1206
+ properties: block.properties,
1207
+ children: [{ content: [imgContent] }]
1208
+ };
1209
+ result.push(newPara);
1210
+ collectedImages.push({ ...value.image, rId, fileName: safeFileName });
1211
+ continue;
1212
+ }
1213
+ }
1214
+ }
1215
+ // Standard image placeholder (no conditional)
1216
+ const value = resolvePath(data, imgMatch);
1217
+ if (isTemplateImage(value)) {
1218
+ const safeFileName = sanitizeTemplateImageFileName(value.image.fileName);
1219
+ const rId = value.image.rId ?? `rId_tpl_${nextTemplateImageSeq()}`;
1220
+ const imgContent = {
1221
+ type: "image",
1222
+ rId,
1223
+ width: value.width,
1224
+ height: value.height,
1225
+ altText: value.altText ?? safeFileName,
1226
+ name: safeFileName
1227
+ };
1228
+ const newPara = {
1229
+ type: "paragraph",
1230
+ properties: block.properties,
1231
+ children: [{ content: [imgContent] }]
1232
+ };
1233
+ result.push(newPara);
1234
+ // Register image for packaging
1235
+ collectedImages.push({ ...value.image, rId, fileName: safeFileName });
1236
+ continue;
1237
+ }
1238
+ }
1239
+ // Check for richText placeholder
1240
+ const rtMatch = matchSinglePlaceholder(text, open, close, "&");
1241
+ if (rtMatch) {
1242
+ const value = resolvePath(data, rtMatch);
1243
+ if (isTemplateRichText(value)) {
1244
+ const newPara = {
1245
+ type: "paragraph",
1246
+ properties: block.properties,
1247
+ children: [...value]
1248
+ };
1249
+ result.push(newPara);
1250
+ continue;
1251
+ }
1252
+ }
1253
+ // Check for chart placeholder
1254
+ const chartMatch = matchSinglePlaceholder(text, open, close, "^");
1255
+ if (chartMatch) {
1256
+ const value = resolvePath(data, chartMatch);
1257
+ if (isTemplateChart(value)) {
1258
+ const chartContent = {
1259
+ type: "chart",
1260
+ chart: value.chart,
1261
+ altText: value.altText,
1262
+ name: value.name
1263
+ };
1264
+ result.push(chartContent);
1265
+ continue;
1266
+ }
1267
+ }
1268
+ result.push(block);
1269
+ }
1270
+ else if (block.type === "table") {
1271
+ // Process table column loops
1272
+ const processed = processTableColumnLoop(block, data, open, close, strict);
1273
+ result.push(processed);
1274
+ }
1275
+ else if (block.type === "sdt") {
1276
+ // Recursively process SDT content
1277
+ const sdt = block;
1278
+ const processedContent = processEnhancedBody(sdt.content, data, open, close, strict, collectedImages);
1279
+ result.push({
1280
+ ...sdt,
1281
+ content: processedContent
1282
+ });
1283
+ }
1284
+ else {
1285
+ result.push(block);
1286
+ }
1287
+ }
1288
+ return result;
1289
+ }
1290
+ /** Match a single-placeholder paragraph: {{<prefix><path>}} */
1291
+ function matchSinglePlaceholder(text, open, close, prefix) {
1292
+ const trimmed = text.trim();
1293
+ if (!trimmed.startsWith(open) || !trimmed.endsWith(close)) {
1294
+ return null;
1295
+ }
1296
+ const inner = trimmed.slice(open.length, trimmed.length - close.length).trim();
1297
+ if (!inner.startsWith(prefix)) {
1298
+ return null;
1299
+ }
1300
+ return inner.slice(prefix.length).trim();
1301
+ }
1302
+ // =============================================================================
1303
+ // Table Column Loop: {{#cols items}}...{{/cols}}
1304
+ // =============================================================================
1305
+ function processTableColumnLoop(table, data, open, close, _strict) {
1306
+ // Check if any cell in the first row contains a #cols directive
1307
+ if (table.rows.length === 0) {
1308
+ return table;
1309
+ }
1310
+ const firstRow = table.rows[0];
1311
+ let colsExpr = null;
1312
+ let templateColIdx = -1;
1313
+ for (let c = 0; c < firstRow.cells.length; c++) {
1314
+ const cell = firstRow.cells[c];
1315
+ for (const block of cell.content) {
1316
+ if (block.type === "paragraph") {
1317
+ const text = extractParagraphText(block);
1318
+ const pattern = open + "#cols ";
1319
+ if (text.includes(pattern)) {
1320
+ colsExpr = extractDirectiveFromText(text, open, close, "#cols ");
1321
+ templateColIdx = c;
1322
+ break;
1323
+ }
1324
+ }
1325
+ }
1326
+ if (colsExpr) {
1327
+ break;
1328
+ }
1329
+ }
1330
+ if (!colsExpr || templateColIdx === -1) {
1331
+ return table;
1332
+ }
1333
+ // Find closing {{/cols}} column
1334
+ let closeColIdx = templateColIdx;
1335
+ for (let c = templateColIdx; c < firstRow.cells.length; c++) {
1336
+ const cell = firstRow.cells[c];
1337
+ for (const block of cell.content) {
1338
+ if (block.type === "paragraph") {
1339
+ const text = extractParagraphText(block);
1340
+ if (text.includes(open + "/cols" + close) || text.includes(open + " /cols " + close)) {
1341
+ closeColIdx = c;
1342
+ break;
1343
+ }
1344
+ }
1345
+ }
1346
+ }
1347
+ const items = resolvePath(data, colsExpr);
1348
+ if (!Array.isArray(items)) {
1349
+ return table;
1350
+ }
1351
+ // For each row, duplicate the template columns for each item
1352
+ const newRows = [];
1353
+ for (const row of table.rows) {
1354
+ const beforeCells = row.cells.slice(0, templateColIdx);
1355
+ const templateCells = row.cells.slice(templateColIdx, closeColIdx + 1);
1356
+ const afterCells = row.cells.slice(closeColIdx + 1);
1357
+ const expandedCells = [...beforeCells];
1358
+ for (let idx = 0; idx < items.length; idx++) {
1359
+ for (const templateCell of templateCells) {
1360
+ const clonedCell = structuredClone(templateCell);
1361
+ // Strip #cols and /cols directives from text
1362
+ for (let b = 0; b < clonedCell.content.length; b++) {
1363
+ const block = clonedCell.content[b];
1364
+ if (block.type === "paragraph") {
1365
+ const text = extractParagraphText(block);
1366
+ let cleaned = text;
1367
+ const colsOpenRegex = new RegExp(escapeRegex(open) +
1368
+ "\\s*#cols\\s+[^" +
1369
+ escapeRegex(close.charAt(0)) +
1370
+ "]*" +
1371
+ escapeRegex(close), "g");
1372
+ cleaned = cleaned.replace(colsOpenRegex, "");
1373
+ const colsCloseRegex = new RegExp(escapeRegex(open) + "\\s*/cols\\s*" + escapeRegex(close), "g");
1374
+ cleaned = cleaned.replace(colsCloseRegex, "");
1375
+ // Resolve item variables
1376
+ const itemData = buildLoopData(items[idx], idx, data);
1377
+ const tokens = tokenize(cleaned, open, close);
1378
+ const ctx = { open, close, strict: false, data: itemData };
1379
+ const resolved = evaluateInlineTokens(tokens, ctx, "colLoop");
1380
+ if (resolved !== text) {
1381
+ clonedCell.content[b] = rebuildParagraphText(block, resolved);
1382
+ }
1383
+ else if (cleaned !== text) {
1384
+ clonedCell.content[b] = rebuildParagraphText(block, cleaned);
1385
+ }
1386
+ }
1387
+ }
1388
+ expandedCells.push(clonedCell);
1389
+ }
1390
+ }
1391
+ expandedCells.push(...afterCells);
1392
+ // Update grid (tblGrid) if needed: we'll leave that to the caller
1393
+ newRows.push({ ...row, cells: expandedCells });
1394
+ }
1395
+ return { ...table, rows: newRows };
1396
+ }
1397
+ // =============================================================================
1398
+ // rId allocation helpers
1399
+ // =============================================================================
1400
+ //
1401
+ // Template-generated parts (alt chunks, dynamic images) need stable but
1402
+ // non-colliding rIds. Earlier versions of this module derived the rId
1403
+ // from `blockIndex` or the image's `fileName`, which collided as soon as
1404
+ // the same template was filled twice or two distinct images shared a
1405
+ // file name. We now use module-level monotonic counters so each generated
1406
+ // part gets a unique rId for the lifetime of the process.
1407
+ let _altChunkSeq = 0;
1408
+ let _templateImageSeq = 0;
1409
+ function nextAltChunkSeq() {
1410
+ _altChunkSeq++;
1411
+ return _altChunkSeq;
1412
+ }
1413
+ function nextTemplateImageSeq() {
1414
+ _templateImageSeq++;
1415
+ return _templateImageSeq;
1416
+ }
1417
+ /**
1418
+ * Strip path-traversal segments and other unsafe characters from a
1419
+ * caller-supplied image file name so it can be safely used as a ZIP
1420
+ * entry path inside the package. Mirrors the equivalent helper in
1421
+ * `convert/odt/odt.ts`.
1422
+ */
1423
+ function sanitizeTemplateImageFileName(raw) {
1424
+ if (!raw) {
1425
+ return "image.bin";
1426
+ }
1427
+ const lastSep = Math.max(raw.lastIndexOf("/"), raw.lastIndexOf("\\"));
1428
+ let leaf = lastSep >= 0 ? raw.substring(lastSep + 1) : raw;
1429
+ while (leaf.startsWith(".")) {
1430
+ leaf = leaf.substring(1);
1431
+ }
1432
+ leaf = leaf.replace(/[^A-Za-z0-9._-]/g, "_");
1433
+ leaf = leaf.replace(/\.{2,}/g, ".");
1434
+ return leaf || "image.bin";
1435
+ }