@cj-tech-master/excelts 9.4.2 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (618) hide show
  1. package/dist/browser/index.browser.d.ts +8 -5
  2. package/dist/browser/index.browser.js +19 -1
  3. package/dist/browser/index.d.ts +4 -2
  4. package/dist/browser/index.js +9 -1
  5. package/dist/browser/modules/excel/chart/cache-populator.d.ts +49 -0
  6. package/dist/browser/modules/excel/chart/cache-populator.js +1171 -0
  7. package/dist/browser/modules/excel/chart/chart-api.d.ts +92 -0
  8. package/dist/browser/modules/excel/chart/chart-api.js +364 -0
  9. package/dist/browser/modules/excel/chart/chart-builder.d.ts +48 -0
  10. package/dist/browser/modules/excel/chart/chart-builder.js +2432 -0
  11. package/dist/browser/modules/excel/chart/chart-ex-builder.d.ts +36 -0
  12. package/dist/browser/modules/excel/chart/chart-ex-builder.js +903 -0
  13. package/dist/browser/modules/excel/chart/chart-ex-parser.d.ts +8 -0
  14. package/dist/browser/modules/excel/chart/chart-ex-parser.js +1205 -0
  15. package/dist/browser/modules/excel/chart/chart-ex-renderer.d.ts +187 -0
  16. package/dist/browser/modules/excel/chart/chart-ex-renderer.js +5352 -0
  17. package/dist/browser/modules/excel/chart/chart-ex-types.d.ts +531 -0
  18. package/dist/browser/modules/excel/chart/chart-ex-types.js +11 -0
  19. package/dist/browser/modules/excel/chart/chart-images.d.ts +78 -0
  20. package/dist/browser/modules/excel/chart/chart-images.js +363 -0
  21. package/dist/browser/modules/excel/chart/chart-presets.d.ts +392 -0
  22. package/dist/browser/modules/excel/chart/chart-presets.js +179 -0
  23. package/dist/browser/modules/excel/chart/chart-renderer.d.ts +550 -0
  24. package/dist/browser/modules/excel/chart/chart-renderer.js +6440 -0
  25. package/dist/browser/modules/excel/chart/chart-sidecar.d.ts +21 -0
  26. package/dist/browser/modules/excel/chart/chart-sidecar.js +427 -0
  27. package/dist/browser/modules/excel/chart/chart-utils.d.ts +306 -0
  28. package/dist/browser/modules/excel/chart/chart-utils.js +821 -0
  29. package/dist/browser/modules/excel/chart/chart.d.ts +504 -0
  30. package/dist/browser/modules/excel/chart/chart.js +1320 -0
  31. package/dist/browser/modules/excel/chart/glyph-rasterizer.d.ts +62 -0
  32. package/dist/browser/modules/excel/chart/glyph-rasterizer.js +658 -0
  33. package/dist/browser/modules/excel/chart/index.d.ts +54 -0
  34. package/dist/browser/modules/excel/chart/index.js +46 -0
  35. package/dist/browser/modules/excel/chart/install.d.ts +44 -0
  36. package/dist/browser/modules/excel/chart/install.js +91 -0
  37. package/dist/browser/modules/excel/chart/shape-properties.d.ts +156 -0
  38. package/dist/browser/modules/excel/chart/shape-properties.js +1557 -0
  39. package/dist/browser/modules/excel/chart/stroke-font.d.ts +36 -0
  40. package/dist/browser/modules/excel/chart/stroke-font.js +1556 -0
  41. package/dist/browser/modules/excel/chart/topojson.d.ts +98 -0
  42. package/dist/browser/modules/excel/chart/topojson.js +236 -0
  43. package/dist/browser/modules/excel/chart/types.d.ts +2559 -0
  44. package/dist/browser/modules/excel/chart/types.js +8 -0
  45. package/dist/browser/modules/excel/chart-host-registry.d.ts +157 -0
  46. package/dist/browser/modules/excel/chart-host-registry.js +90 -0
  47. package/dist/browser/modules/excel/chartsheet.d.ts +102 -0
  48. package/dist/browser/modules/excel/chartsheet.js +196 -0
  49. package/dist/browser/modules/excel/defined-names.d.ts +35 -0
  50. package/dist/browser/modules/excel/defined-names.js +44 -4
  51. package/dist/browser/modules/excel/errors.d.ts +6 -0
  52. package/dist/browser/modules/excel/errors.js +9 -0
  53. package/dist/browser/modules/excel/form-control.d.ts +6 -0
  54. package/dist/browser/modules/excel/form-control.js +17 -0
  55. package/dist/browser/modules/excel/image.js +12 -2
  56. package/dist/browser/modules/excel/pivot-chart.d.ts +7 -0
  57. package/dist/browser/modules/excel/pivot-chart.js +53 -0
  58. package/dist/browser/modules/excel/pivot-table.d.ts +55 -0
  59. package/dist/browser/modules/excel/pivot-table.js +35 -0
  60. package/dist/browser/modules/excel/range.js +5 -1
  61. package/dist/browser/modules/excel/sparkline/index.d.ts +7 -0
  62. package/dist/browser/modules/excel/sparkline/index.js +7 -0
  63. package/dist/browser/modules/excel/sparkline/sparkline.d.ts +206 -0
  64. package/dist/browser/modules/excel/sparkline/sparkline.js +750 -0
  65. package/dist/browser/modules/excel/stream/worksheet-writer.js +3 -2
  66. package/dist/browser/modules/excel/table.js +42 -6
  67. package/dist/browser/modules/excel/types.d.ts +72 -0
  68. package/dist/browser/modules/excel/utils/address.d.ts +18 -0
  69. package/dist/browser/modules/excel/utils/address.js +28 -0
  70. package/dist/browser/modules/excel/utils/drawing-utils.js +11 -6
  71. package/dist/browser/modules/excel/utils/guid.d.ts +15 -0
  72. package/dist/browser/modules/excel/utils/guid.js +35 -0
  73. package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +74 -0
  74. package/dist/browser/modules/excel/utils/ooxml-paths.js +206 -9
  75. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart-sidecar.d.ts +35 -0
  76. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +101 -0
  77. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart.d.ts +32 -0
  78. package/dist/browser/modules/excel/utils/ooxml-validator/check-chart.js +2125 -0
  79. package/dist/browser/modules/excel/utils/ooxml-validator/check-chartsheet.d.ts +9 -0
  80. package/dist/browser/modules/excel/utils/ooxml-validator/check-chartsheet.js +26 -0
  81. package/dist/browser/modules/excel/utils/ooxml-validator/check-content-types.d.ts +16 -0
  82. package/dist/browser/modules/excel/utils/ooxml-validator/check-content-types.js +181 -0
  83. package/dist/browser/modules/excel/utils/ooxml-validator/check-drawing.d.ts +34 -0
  84. package/dist/browser/modules/excel/utils/ooxml-validator/check-drawing.js +267 -0
  85. package/dist/browser/modules/excel/utils/ooxml-validator/check-pivot.d.ts +14 -0
  86. package/dist/browser/modules/excel/utils/ooxml-validator/check-pivot.js +104 -0
  87. package/dist/browser/modules/excel/utils/ooxml-validator/check-relationships.d.ts +18 -0
  88. package/dist/browser/modules/excel/utils/ooxml-validator/check-relationships.js +184 -0
  89. package/dist/browser/modules/excel/utils/ooxml-validator/check-structure.d.ts +21 -0
  90. package/dist/browser/modules/excel/utils/ooxml-validator/check-structure.js +56 -0
  91. package/dist/browser/modules/excel/utils/ooxml-validator/check-styles.d.ts +15 -0
  92. package/dist/browser/modules/excel/utils/ooxml-validator/check-styles.js +89 -0
  93. package/dist/browser/modules/excel/utils/ooxml-validator/check-table.d.ts +31 -0
  94. package/dist/browser/modules/excel/utils/ooxml-validator/check-table.js +177 -0
  95. package/dist/browser/modules/excel/utils/ooxml-validator/check-workbook.d.ts +19 -0
  96. package/dist/browser/modules/excel/utils/ooxml-validator/check-workbook.js +163 -0
  97. package/dist/browser/modules/excel/utils/ooxml-validator/check-worksheet.d.ts +25 -0
  98. package/dist/browser/modules/excel/utils/ooxml-validator/check-worksheet.js +569 -0
  99. package/dist/browser/modules/excel/utils/ooxml-validator/context.d.ts +85 -0
  100. package/dist/browser/modules/excel/utils/ooxml-validator/context.js +191 -0
  101. package/dist/browser/modules/excel/utils/ooxml-validator/index.d.ts +31 -0
  102. package/dist/browser/modules/excel/utils/ooxml-validator/index.js +102 -0
  103. package/dist/browser/modules/excel/utils/ooxml-validator/path-utils.d.ts +67 -0
  104. package/dist/browser/modules/excel/utils/ooxml-validator/path-utils.js +156 -0
  105. package/dist/browser/modules/excel/utils/ooxml-validator/reporter.d.ts +41 -0
  106. package/dist/browser/modules/excel/utils/ooxml-validator/reporter.js +61 -0
  107. package/dist/browser/modules/excel/utils/ooxml-validator/types.d.ts +109 -0
  108. package/dist/browser/modules/excel/utils/ooxml-validator/types.js +12 -0
  109. package/dist/browser/modules/excel/utils/ooxml-validator/xml-utils.d.ts +38 -0
  110. package/dist/browser/modules/excel/utils/ooxml-validator/xml-utils.js +100 -0
  111. package/dist/browser/modules/excel/workbook.browser.d.ts +248 -30
  112. package/dist/browser/modules/excel/workbook.browser.js +966 -31
  113. package/dist/browser/modules/excel/workbook.d.ts +43 -0
  114. package/dist/browser/modules/excel/workbook.js +48 -0
  115. package/dist/browser/modules/excel/worksheet.d.ts +157 -3
  116. package/dist/browser/modules/excel/worksheet.js +394 -35
  117. package/dist/browser/modules/excel/xlsx/rel-type.d.ts +40 -0
  118. package/dist/browser/modules/excel/xlsx/rel-type.js +41 -1
  119. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +1 -0
  120. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  121. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  122. package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  123. package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.d.ts +353 -0
  124. package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.js +6000 -0
  125. package/dist/browser/modules/excel/xlsx/xform/comment/threaded-comments-xform.d.ts +60 -0
  126. package/dist/browser/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +213 -0
  127. package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +150 -11
  128. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  129. package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  130. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +30 -0
  131. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  132. package/dist/browser/modules/excel/xlsx/xform/drawing/graphic-frame-xform.d.ts +54 -0
  133. package/dist/browser/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +225 -0
  134. package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +3 -1
  135. package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  136. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +46 -0
  137. package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  138. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +13 -2
  139. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  140. package/dist/browser/modules/excel/xlsx/xform/sheet/chartsheet-xform.d.ts +185 -0
  141. package/dist/browser/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +441 -0
  142. package/dist/browser/modules/excel/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -0
  143. package/dist/browser/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  144. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +196 -20
  145. package/dist/browser/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  146. package/dist/browser/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  147. package/dist/browser/modules/excel/xlsx/xform/xsd-values.d.ts +63 -0
  148. package/dist/browser/modules/excel/xlsx/xform/xsd-values.js +101 -0
  149. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +115 -21
  150. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +4422 -78
  151. package/dist/browser/modules/pdf/builder/document-builder.d.ts +74 -0
  152. package/dist/browser/modules/pdf/builder/document-builder.js +507 -2
  153. package/dist/browser/modules/pdf/builder/pdf-editor.js +48 -3
  154. package/dist/browser/modules/pdf/excel-bridge.d.ts +69 -0
  155. package/dist/browser/modules/pdf/excel-bridge.js +683 -12
  156. package/dist/browser/modules/pdf/font/font-manager.d.ts +25 -0
  157. package/dist/browser/modules/pdf/font/font-manager.js +39 -0
  158. package/dist/browser/modules/pdf/index.d.ts +5 -2
  159. package/dist/browser/modules/pdf/index.js +3 -1
  160. package/dist/browser/modules/pdf/render/chart-surface.d.ts +33 -0
  161. package/dist/browser/modules/pdf/render/chart-surface.js +200 -0
  162. package/dist/browser/modules/pdf/render/layout-engine.d.ts +22 -1
  163. package/dist/browser/modules/pdf/render/layout-engine.js +436 -56
  164. package/dist/browser/modules/pdf/render/page-renderer.js +169 -28
  165. package/dist/browser/modules/pdf/render/pdf-exporter.js +117 -7
  166. package/dist/browser/modules/pdf/types.d.ts +227 -23
  167. package/dist/browser/modules/pdf/types.js +4 -0
  168. package/dist/browser/modules/pdf/word-bridge.d.ts +47 -0
  169. package/dist/browser/modules/pdf/word-bridge.js +304 -0
  170. package/dist/browser/modules/word/constants.d.ts +179 -0
  171. package/dist/browser/modules/word/constants.js +231 -0
  172. package/dist/browser/modules/word/content-types.d.ts +27 -0
  173. package/dist/browser/modules/word/content-types.js +53 -0
  174. package/dist/browser/modules/word/digital-signatures.d.ts +87 -0
  175. package/dist/browser/modules/word/digital-signatures.js +134 -0
  176. package/dist/browser/modules/word/document.d.ts +728 -0
  177. package/dist/browser/modules/word/document.js +1795 -0
  178. package/dist/browser/modules/word/docx-packager.d.ts +14 -0
  179. package/dist/browser/modules/word/docx-packager.js +822 -0
  180. package/dist/browser/modules/word/docx-reader.d.ts +11 -0
  181. package/dist/browser/modules/word/docx-reader.js +4929 -0
  182. package/dist/browser/modules/word/encryption.d.ts +102 -0
  183. package/dist/browser/modules/word/encryption.js +274 -0
  184. package/dist/browser/modules/word/errors.d.ts +49 -0
  185. package/dist/browser/modules/word/errors.js +68 -0
  186. package/dist/browser/modules/word/font-obfuscation.d.ts +31 -0
  187. package/dist/browser/modules/word/font-obfuscation.js +83 -0
  188. package/dist/browser/modules/word/html-renderer.d.ts +38 -0
  189. package/dist/browser/modules/word/html-renderer.js +782 -0
  190. package/dist/browser/modules/word/index.base.d.ts +19 -0
  191. package/dist/browser/modules/word/index.base.js +51 -0
  192. package/dist/browser/modules/word/index.browser.d.ts +4 -0
  193. package/dist/browser/modules/word/index.browser.js +4 -0
  194. package/dist/browser/modules/word/index.d.ts +4 -0
  195. package/dist/browser/modules/word/index.js +4 -0
  196. package/dist/browser/modules/word/internal-utils.d.ts +23 -0
  197. package/dist/browser/modules/word/internal-utils.js +54 -0
  198. package/dist/browser/modules/word/relationships.d.ts +31 -0
  199. package/dist/browser/modules/word/relationships.js +56 -0
  200. package/dist/browser/modules/word/types.d.ts +2325 -0
  201. package/dist/browser/modules/word/types.js +10 -0
  202. package/dist/browser/modules/word/units.d.ts +49 -0
  203. package/dist/browser/modules/word/units.js +111 -0
  204. package/dist/browser/modules/word/writers/chart-writer.d.ts +10 -0
  205. package/dist/browser/modules/word/writers/chart-writer.js +385 -0
  206. package/dist/browser/modules/word/writers/checkbox-writer.d.ts +9 -0
  207. package/dist/browser/modules/word/writers/checkbox-writer.js +42 -0
  208. package/dist/browser/modules/word/writers/comment-writer.d.ts +15 -0
  209. package/dist/browser/modules/word/writers/comment-writer.js +70 -0
  210. package/dist/browser/modules/word/writers/document-writer.d.ts +16 -0
  211. package/dist/browser/modules/word/writers/document-writer.js +461 -0
  212. package/dist/browser/modules/word/writers/footnote-writer.d.ts +11 -0
  213. package/dist/browser/modules/word/writers/footnote-writer.js +72 -0
  214. package/dist/browser/modules/word/writers/header-footer-writer.d.ts +13 -0
  215. package/dist/browser/modules/word/writers/header-footer-writer.js +129 -0
  216. package/dist/browser/modules/word/writers/image-writer.d.ts +10 -0
  217. package/dist/browser/modules/word/writers/image-writer.js +185 -0
  218. package/dist/browser/modules/word/writers/math-writer.d.ts +9 -0
  219. package/dist/browser/modules/word/writers/math-writer.js +428 -0
  220. package/dist/browser/modules/word/writers/numbering-writer.d.ts +10 -0
  221. package/dist/browser/modules/word/writers/numbering-writer.js +125 -0
  222. package/dist/browser/modules/word/writers/paragraph-writer.d.ts +13 -0
  223. package/dist/browser/modules/word/writers/paragraph-writer.js +516 -0
  224. package/dist/browser/modules/word/writers/parts-writer.d.ts +26 -0
  225. package/dist/browser/modules/word/writers/parts-writer.js +660 -0
  226. package/dist/browser/modules/word/writers/run-writer.d.ts +15 -0
  227. package/dist/browser/modules/word/writers/run-writer.js +649 -0
  228. package/dist/browser/modules/word/writers/section-writer.d.ts +10 -0
  229. package/dist/browser/modules/word/writers/section-writer.js +238 -0
  230. package/dist/browser/modules/word/writers/styles-writer.d.ts +10 -0
  231. package/dist/browser/modules/word/writers/styles-writer.js +242 -0
  232. package/dist/browser/modules/word/writers/table-writer.d.ts +10 -0
  233. package/dist/browser/modules/word/writers/table-writer.js +503 -0
  234. package/dist/browser/modules/word/writers/textbox-writer.d.ts +9 -0
  235. package/dist/browser/modules/word/writers/textbox-writer.js +53 -0
  236. package/dist/browser/modules/word/writers/toc-writer.d.ts +9 -0
  237. package/dist/browser/modules/word/writers/toc-writer.js +79 -0
  238. package/dist/browser/modules/xml/encode.d.ts +56 -7
  239. package/dist/browser/modules/xml/encode.js +157 -11
  240. package/dist/cjs/index.js +13 -2
  241. package/dist/cjs/modules/excel/chart/cache-populator.js +1178 -0
  242. package/dist/cjs/modules/excel/chart/chart-api.js +371 -0
  243. package/dist/cjs/modules/excel/chart/chart-builder.js +2440 -0
  244. package/dist/cjs/modules/excel/chart/chart-ex-builder.js +907 -0
  245. package/dist/cjs/modules/excel/chart/chart-ex-parser.js +1208 -0
  246. package/dist/cjs/modules/excel/chart/chart-ex-renderer.js +5364 -0
  247. package/dist/cjs/modules/excel/chart/chart-ex-types.js +12 -0
  248. package/dist/cjs/modules/excel/chart/chart-images.js +366 -0
  249. package/dist/cjs/modules/excel/chart/chart-presets.js +184 -0
  250. package/dist/cjs/modules/excel/chart/chart-renderer.js +6450 -0
  251. package/dist/cjs/modules/excel/chart/chart-sidecar.js +433 -0
  252. package/dist/cjs/modules/excel/chart/chart-utils.js +845 -0
  253. package/dist/cjs/modules/excel/chart/chart.js +1324 -0
  254. package/dist/cjs/modules/excel/chart/glyph-rasterizer.js +664 -0
  255. package/dist/cjs/modules/excel/chart/index.js +101 -0
  256. package/dist/cjs/modules/excel/chart/install.js +95 -0
  257. package/dist/cjs/modules/excel/chart/shape-properties.js +1577 -0
  258. package/dist/cjs/modules/excel/chart/stroke-font.js +1559 -0
  259. package/dist/cjs/modules/excel/chart/topojson.js +239 -0
  260. package/dist/cjs/modules/excel/chart/types.js +9 -0
  261. package/dist/cjs/modules/excel/chart-host-registry.js +96 -0
  262. package/dist/cjs/modules/excel/chartsheet.js +199 -0
  263. package/dist/cjs/modules/excel/defined-names.js +44 -4
  264. package/dist/cjs/modules/excel/errors.js +11 -1
  265. package/dist/cjs/modules/excel/form-control.js +17 -0
  266. package/dist/cjs/modules/excel/image.js +12 -2
  267. package/dist/cjs/modules/excel/pivot-chart.js +56 -0
  268. package/dist/cjs/modules/excel/pivot-table.js +35 -0
  269. package/dist/cjs/modules/excel/range.js +5 -1
  270. package/dist/cjs/modules/excel/sparkline/index.js +23 -0
  271. package/dist/cjs/modules/excel/sparkline/sparkline.js +756 -0
  272. package/dist/cjs/modules/excel/stream/worksheet-writer.js +3 -2
  273. package/dist/cjs/modules/excel/table.js +42 -6
  274. package/dist/cjs/modules/excel/utils/address.js +29 -0
  275. package/dist/cjs/modules/excel/utils/drawing-utils.js +11 -6
  276. package/dist/cjs/modules/excel/utils/guid.js +38 -0
  277. package/dist/cjs/modules/excel/utils/ooxml-paths.js +246 -9
  278. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +103 -0
  279. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chart.js +2128 -0
  280. package/dist/cjs/modules/excel/utils/ooxml-validator/check-chartsheet.js +29 -0
  281. package/dist/cjs/modules/excel/utils/ooxml-validator/check-content-types.js +184 -0
  282. package/dist/cjs/modules/excel/utils/ooxml-validator/check-drawing.js +270 -0
  283. package/dist/cjs/modules/excel/utils/ooxml-validator/check-pivot.js +107 -0
  284. package/dist/cjs/modules/excel/utils/ooxml-validator/check-relationships.js +188 -0
  285. package/dist/cjs/modules/excel/utils/ooxml-validator/check-structure.js +60 -0
  286. package/dist/cjs/modules/excel/utils/ooxml-validator/check-styles.js +92 -0
  287. package/dist/cjs/modules/excel/utils/ooxml-validator/check-table.js +180 -0
  288. package/dist/cjs/modules/excel/utils/ooxml-validator/check-workbook.js +166 -0
  289. package/dist/cjs/modules/excel/utils/ooxml-validator/check-worksheet.js +572 -0
  290. package/dist/cjs/modules/excel/utils/ooxml-validator/context.js +196 -0
  291. package/dist/cjs/modules/excel/utils/ooxml-validator/index.js +105 -0
  292. package/dist/cjs/modules/excel/utils/ooxml-validator/path-utils.js +168 -0
  293. package/dist/cjs/modules/excel/utils/ooxml-validator/reporter.js +66 -0
  294. package/dist/cjs/modules/excel/utils/ooxml-validator/types.js +13 -0
  295. package/dist/cjs/modules/excel/utils/ooxml-validator/xml-utils.js +110 -0
  296. package/dist/cjs/modules/excel/workbook.browser.js +973 -38
  297. package/dist/cjs/modules/excel/workbook.js +48 -0
  298. package/dist/cjs/modules/excel/worksheet.js +393 -34
  299. package/dist/cjs/modules/excel/xlsx/rel-type.js +41 -1
  300. package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  301. package/dist/cjs/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  302. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  303. package/dist/cjs/modules/excel/xlsx/xform/chart/chart-space-xform.js +6003 -0
  304. package/dist/cjs/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +219 -0
  305. package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +149 -10
  306. package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  307. package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  308. package/dist/cjs/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  309. package/dist/cjs/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +228 -0
  310. package/dist/cjs/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  311. package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  312. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  313. package/dist/cjs/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +444 -0
  314. package/dist/cjs/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  315. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +195 -19
  316. package/dist/cjs/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  317. package/dist/cjs/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  318. package/dist/cjs/modules/excel/xlsx/xform/xsd-values.js +106 -0
  319. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +4420 -76
  320. package/dist/cjs/modules/pdf/builder/document-builder.js +506 -1
  321. package/dist/cjs/modules/pdf/builder/pdf-editor.js +48 -3
  322. package/dist/cjs/modules/pdf/excel-bridge.js +684 -12
  323. package/dist/cjs/modules/pdf/font/font-manager.js +39 -0
  324. package/dist/cjs/modules/pdf/index.js +5 -1
  325. package/dist/cjs/modules/pdf/render/chart-surface.js +203 -0
  326. package/dist/cjs/modules/pdf/render/layout-engine.js +437 -56
  327. package/dist/cjs/modules/pdf/render/page-renderer.js +169 -28
  328. package/dist/cjs/modules/pdf/render/pdf-exporter.js +115 -5
  329. package/dist/cjs/modules/pdf/types.js +5 -0
  330. package/dist/cjs/modules/pdf/word-bridge.js +307 -0
  331. package/dist/cjs/modules/word/constants.js +234 -0
  332. package/dist/cjs/modules/word/content-types.js +57 -0
  333. package/dist/cjs/modules/word/digital-signatures.js +140 -0
  334. package/dist/cjs/modules/word/document.js +1909 -0
  335. package/dist/cjs/modules/word/docx-packager.js +825 -0
  336. package/dist/cjs/modules/word/docx-reader.js +4932 -0
  337. package/dist/cjs/modules/word/encryption.js +282 -0
  338. package/dist/cjs/modules/word/errors.js +88 -0
  339. package/dist/cjs/modules/word/font-obfuscation.js +88 -0
  340. package/dist/cjs/modules/word/html-renderer.js +785 -0
  341. package/dist/cjs/modules/word/index.base.js +199 -0
  342. package/dist/cjs/modules/word/index.browser.js +20 -0
  343. package/dist/cjs/modules/word/index.js +20 -0
  344. package/dist/cjs/modules/word/internal-utils.js +59 -0
  345. package/dist/cjs/modules/word/relationships.js +60 -0
  346. package/dist/cjs/modules/word/types.js +11 -0
  347. package/dist/cjs/modules/word/units.js +135 -0
  348. package/dist/cjs/modules/word/writers/chart-writer.js +388 -0
  349. package/dist/cjs/modules/word/writers/checkbox-writer.js +45 -0
  350. package/dist/cjs/modules/word/writers/comment-writer.js +74 -0
  351. package/dist/cjs/modules/word/writers/document-writer.js +465 -0
  352. package/dist/cjs/modules/word/writers/footnote-writer.js +76 -0
  353. package/dist/cjs/modules/word/writers/header-footer-writer.js +134 -0
  354. package/dist/cjs/modules/word/writers/image-writer.js +188 -0
  355. package/dist/cjs/modules/word/writers/math-writer.js +431 -0
  356. package/dist/cjs/modules/word/writers/numbering-writer.js +128 -0
  357. package/dist/cjs/modules/word/writers/paragraph-writer.js +521 -0
  358. package/dist/cjs/modules/word/writers/parts-writer.js +671 -0
  359. package/dist/cjs/modules/word/writers/run-writer.js +655 -0
  360. package/dist/cjs/modules/word/writers/section-writer.js +241 -0
  361. package/dist/cjs/modules/word/writers/styles-writer.js +245 -0
  362. package/dist/cjs/modules/word/writers/table-writer.js +506 -0
  363. package/dist/cjs/modules/word/writers/textbox-writer.js +56 -0
  364. package/dist/cjs/modules/word/writers/toc-writer.js +82 -0
  365. package/dist/cjs/modules/xml/encode.js +158 -11
  366. package/dist/esm/index.browser.js +20 -2
  367. package/dist/esm/index.js +9 -1
  368. package/dist/esm/modules/excel/chart/cache-populator.js +1171 -0
  369. package/dist/esm/modules/excel/chart/chart-api.js +364 -0
  370. package/dist/esm/modules/excel/chart/chart-builder.js +2432 -0
  371. package/dist/esm/modules/excel/chart/chart-ex-builder.js +903 -0
  372. package/dist/esm/modules/excel/chart/chart-ex-parser.js +1205 -0
  373. package/dist/esm/modules/excel/chart/chart-ex-renderer.js +5352 -0
  374. package/dist/esm/modules/excel/chart/chart-ex-types.js +11 -0
  375. package/dist/esm/modules/excel/chart/chart-images.js +363 -0
  376. package/dist/esm/modules/excel/chart/chart-presets.js +179 -0
  377. package/dist/esm/modules/excel/chart/chart-renderer.js +6440 -0
  378. package/dist/esm/modules/excel/chart/chart-sidecar.js +427 -0
  379. package/dist/esm/modules/excel/chart/chart-utils.js +821 -0
  380. package/dist/esm/modules/excel/chart/chart.js +1320 -0
  381. package/dist/esm/modules/excel/chart/glyph-rasterizer.js +658 -0
  382. package/dist/esm/modules/excel/chart/index.js +46 -0
  383. package/dist/esm/modules/excel/chart/install.js +91 -0
  384. package/dist/esm/modules/excel/chart/shape-properties.js +1557 -0
  385. package/dist/esm/modules/excel/chart/stroke-font.js +1556 -0
  386. package/dist/esm/modules/excel/chart/topojson.js +236 -0
  387. package/dist/esm/modules/excel/chart/types.js +8 -0
  388. package/dist/esm/modules/excel/chart-host-registry.js +90 -0
  389. package/dist/esm/modules/excel/chartsheet.js +196 -0
  390. package/dist/esm/modules/excel/defined-names.js +44 -4
  391. package/dist/esm/modules/excel/errors.js +9 -0
  392. package/dist/esm/modules/excel/form-control.js +17 -0
  393. package/dist/esm/modules/excel/image.js +12 -2
  394. package/dist/esm/modules/excel/pivot-chart.js +53 -0
  395. package/dist/esm/modules/excel/pivot-table.js +35 -0
  396. package/dist/esm/modules/excel/range.js +5 -1
  397. package/dist/esm/modules/excel/sparkline/index.js +7 -0
  398. package/dist/esm/modules/excel/sparkline/sparkline.js +750 -0
  399. package/dist/esm/modules/excel/stream/worksheet-writer.js +3 -2
  400. package/dist/esm/modules/excel/table.js +42 -6
  401. package/dist/esm/modules/excel/utils/address.js +28 -0
  402. package/dist/esm/modules/excel/utils/drawing-utils.js +11 -6
  403. package/dist/esm/modules/excel/utils/guid.js +35 -0
  404. package/dist/esm/modules/excel/utils/ooxml-paths.js +206 -9
  405. package/dist/esm/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +101 -0
  406. package/dist/esm/modules/excel/utils/ooxml-validator/check-chart.js +2125 -0
  407. package/dist/esm/modules/excel/utils/ooxml-validator/check-chartsheet.js +26 -0
  408. package/dist/esm/modules/excel/utils/ooxml-validator/check-content-types.js +181 -0
  409. package/dist/esm/modules/excel/utils/ooxml-validator/check-drawing.js +267 -0
  410. package/dist/esm/modules/excel/utils/ooxml-validator/check-pivot.js +104 -0
  411. package/dist/esm/modules/excel/utils/ooxml-validator/check-relationships.js +184 -0
  412. package/dist/esm/modules/excel/utils/ooxml-validator/check-structure.js +56 -0
  413. package/dist/esm/modules/excel/utils/ooxml-validator/check-styles.js +89 -0
  414. package/dist/esm/modules/excel/utils/ooxml-validator/check-table.js +177 -0
  415. package/dist/esm/modules/excel/utils/ooxml-validator/check-workbook.js +163 -0
  416. package/dist/esm/modules/excel/utils/ooxml-validator/check-worksheet.js +569 -0
  417. package/dist/esm/modules/excel/utils/ooxml-validator/context.js +191 -0
  418. package/dist/esm/modules/excel/utils/ooxml-validator/index.js +102 -0
  419. package/dist/esm/modules/excel/utils/ooxml-validator/path-utils.js +156 -0
  420. package/dist/esm/modules/excel/utils/ooxml-validator/reporter.js +61 -0
  421. package/dist/esm/modules/excel/utils/ooxml-validator/types.js +12 -0
  422. package/dist/esm/modules/excel/utils/ooxml-validator/xml-utils.js +100 -0
  423. package/dist/esm/modules/excel/workbook.browser.js +969 -34
  424. package/dist/esm/modules/excel/workbook.js +48 -0
  425. package/dist/esm/modules/excel/worksheet.js +394 -35
  426. package/dist/esm/modules/excel/xlsx/rel-type.js +41 -1
  427. package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
  428. package/dist/esm/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
  429. package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
  430. package/dist/esm/modules/excel/xlsx/xform/chart/chart-space-xform.js +6000 -0
  431. package/dist/esm/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +213 -0
  432. package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +150 -11
  433. package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
  434. package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
  435. package/dist/esm/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
  436. package/dist/esm/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +225 -0
  437. package/dist/esm/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
  438. package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
  439. package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
  440. package/dist/esm/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +441 -0
  441. package/dist/esm/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
  442. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +196 -20
  443. package/dist/esm/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
  444. package/dist/esm/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
  445. package/dist/esm/modules/excel/xlsx/xform/xsd-values.js +101 -0
  446. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +4422 -78
  447. package/dist/esm/modules/pdf/builder/document-builder.js +507 -2
  448. package/dist/esm/modules/pdf/builder/pdf-editor.js +48 -3
  449. package/dist/esm/modules/pdf/excel-bridge.js +683 -12
  450. package/dist/esm/modules/pdf/font/font-manager.js +39 -0
  451. package/dist/esm/modules/pdf/index.js +3 -1
  452. package/dist/esm/modules/pdf/render/chart-surface.js +200 -0
  453. package/dist/esm/modules/pdf/render/layout-engine.js +436 -56
  454. package/dist/esm/modules/pdf/render/page-renderer.js +169 -28
  455. package/dist/esm/modules/pdf/render/pdf-exporter.js +117 -7
  456. package/dist/esm/modules/pdf/types.js +4 -0
  457. package/dist/esm/modules/pdf/word-bridge.js +304 -0
  458. package/dist/esm/modules/word/constants.js +231 -0
  459. package/dist/esm/modules/word/content-types.js +53 -0
  460. package/dist/esm/modules/word/digital-signatures.js +134 -0
  461. package/dist/esm/modules/word/document.js +1795 -0
  462. package/dist/esm/modules/word/docx-packager.js +822 -0
  463. package/dist/esm/modules/word/docx-reader.js +4929 -0
  464. package/dist/esm/modules/word/encryption.js +274 -0
  465. package/dist/esm/modules/word/errors.js +68 -0
  466. package/dist/esm/modules/word/font-obfuscation.js +83 -0
  467. package/dist/esm/modules/word/html-renderer.js +782 -0
  468. package/dist/esm/modules/word/index.base.js +51 -0
  469. package/dist/esm/modules/word/index.browser.js +4 -0
  470. package/dist/esm/modules/word/index.js +4 -0
  471. package/dist/esm/modules/word/internal-utils.js +54 -0
  472. package/dist/esm/modules/word/relationships.js +56 -0
  473. package/dist/esm/modules/word/types.js +10 -0
  474. package/dist/esm/modules/word/units.js +111 -0
  475. package/dist/esm/modules/word/writers/chart-writer.js +385 -0
  476. package/dist/esm/modules/word/writers/checkbox-writer.js +42 -0
  477. package/dist/esm/modules/word/writers/comment-writer.js +70 -0
  478. package/dist/esm/modules/word/writers/document-writer.js +461 -0
  479. package/dist/esm/modules/word/writers/footnote-writer.js +72 -0
  480. package/dist/esm/modules/word/writers/header-footer-writer.js +129 -0
  481. package/dist/esm/modules/word/writers/image-writer.js +185 -0
  482. package/dist/esm/modules/word/writers/math-writer.js +428 -0
  483. package/dist/esm/modules/word/writers/numbering-writer.js +125 -0
  484. package/dist/esm/modules/word/writers/paragraph-writer.js +516 -0
  485. package/dist/esm/modules/word/writers/parts-writer.js +660 -0
  486. package/dist/esm/modules/word/writers/run-writer.js +649 -0
  487. package/dist/esm/modules/word/writers/section-writer.js +238 -0
  488. package/dist/esm/modules/word/writers/styles-writer.js +242 -0
  489. package/dist/esm/modules/word/writers/table-writer.js +503 -0
  490. package/dist/esm/modules/word/writers/textbox-writer.js +53 -0
  491. package/dist/esm/modules/word/writers/toc-writer.js +79 -0
  492. package/dist/esm/modules/xml/encode.js +157 -11
  493. package/dist/iife/excelts.iife.js +11789 -687
  494. package/dist/iife/excelts.iife.js.map +1 -1
  495. package/dist/iife/excelts.iife.min.js +52 -44
  496. package/dist/types/index.browser.d.ts +8 -5
  497. package/dist/types/index.d.ts +4 -2
  498. package/dist/types/modules/excel/chart/cache-populator.d.ts +49 -0
  499. package/dist/types/modules/excel/chart/chart-api.d.ts +92 -0
  500. package/dist/types/modules/excel/chart/chart-builder.d.ts +48 -0
  501. package/dist/types/modules/excel/chart/chart-ex-builder.d.ts +36 -0
  502. package/dist/types/modules/excel/chart/chart-ex-parser.d.ts +8 -0
  503. package/dist/types/modules/excel/chart/chart-ex-renderer.d.ts +187 -0
  504. package/dist/types/modules/excel/chart/chart-ex-types.d.ts +531 -0
  505. package/dist/types/modules/excel/chart/chart-images.d.ts +78 -0
  506. package/dist/types/modules/excel/chart/chart-presets.d.ts +392 -0
  507. package/dist/types/modules/excel/chart/chart-renderer.d.ts +550 -0
  508. package/dist/types/modules/excel/chart/chart-sidecar.d.ts +21 -0
  509. package/dist/types/modules/excel/chart/chart-utils.d.ts +306 -0
  510. package/dist/types/modules/excel/chart/chart.d.ts +504 -0
  511. package/dist/types/modules/excel/chart/glyph-rasterizer.d.ts +62 -0
  512. package/dist/types/modules/excel/chart/index.d.ts +54 -0
  513. package/dist/types/modules/excel/chart/install.d.ts +44 -0
  514. package/dist/types/modules/excel/chart/shape-properties.d.ts +156 -0
  515. package/dist/types/modules/excel/chart/stroke-font.d.ts +36 -0
  516. package/dist/types/modules/excel/chart/topojson.d.ts +98 -0
  517. package/dist/types/modules/excel/chart/types.d.ts +2559 -0
  518. package/dist/types/modules/excel/chart-host-registry.d.ts +157 -0
  519. package/dist/types/modules/excel/chartsheet.d.ts +102 -0
  520. package/dist/types/modules/excel/defined-names.d.ts +35 -0
  521. package/dist/types/modules/excel/errors.d.ts +6 -0
  522. package/dist/types/modules/excel/form-control.d.ts +6 -0
  523. package/dist/types/modules/excel/pivot-chart.d.ts +7 -0
  524. package/dist/types/modules/excel/pivot-table.d.ts +55 -0
  525. package/dist/types/modules/excel/sparkline/index.d.ts +7 -0
  526. package/dist/types/modules/excel/sparkline/sparkline.d.ts +206 -0
  527. package/dist/types/modules/excel/types.d.ts +72 -0
  528. package/dist/types/modules/excel/utils/address.d.ts +18 -0
  529. package/dist/types/modules/excel/utils/guid.d.ts +15 -0
  530. package/dist/types/modules/excel/utils/ooxml-paths.d.ts +74 -0
  531. package/dist/types/modules/excel/utils/ooxml-validator/check-chart-sidecar.d.ts +35 -0
  532. package/dist/types/modules/excel/utils/ooxml-validator/check-chart.d.ts +32 -0
  533. package/dist/types/modules/excel/utils/ooxml-validator/check-chartsheet.d.ts +9 -0
  534. package/dist/types/modules/excel/utils/ooxml-validator/check-content-types.d.ts +16 -0
  535. package/dist/types/modules/excel/utils/ooxml-validator/check-drawing.d.ts +34 -0
  536. package/dist/types/modules/excel/utils/ooxml-validator/check-pivot.d.ts +14 -0
  537. package/dist/types/modules/excel/utils/ooxml-validator/check-relationships.d.ts +18 -0
  538. package/dist/types/modules/excel/utils/ooxml-validator/check-structure.d.ts +21 -0
  539. package/dist/types/modules/excel/utils/ooxml-validator/check-styles.d.ts +15 -0
  540. package/dist/types/modules/excel/utils/ooxml-validator/check-table.d.ts +31 -0
  541. package/dist/types/modules/excel/utils/ooxml-validator/check-workbook.d.ts +19 -0
  542. package/dist/types/modules/excel/utils/ooxml-validator/check-worksheet.d.ts +25 -0
  543. package/dist/types/modules/excel/utils/ooxml-validator/context.d.ts +85 -0
  544. package/dist/types/modules/excel/utils/ooxml-validator/index.d.ts +31 -0
  545. package/dist/types/modules/excel/utils/ooxml-validator/path-utils.d.ts +67 -0
  546. package/dist/types/modules/excel/utils/ooxml-validator/reporter.d.ts +41 -0
  547. package/dist/types/modules/excel/utils/ooxml-validator/types.d.ts +109 -0
  548. package/dist/types/modules/excel/utils/ooxml-validator/xml-utils.d.ts +38 -0
  549. package/dist/types/modules/excel/workbook.browser.d.ts +248 -30
  550. package/dist/types/modules/excel/workbook.d.ts +43 -0
  551. package/dist/types/modules/excel/worksheet.d.ts +157 -3
  552. package/dist/types/modules/excel/xlsx/rel-type.d.ts +40 -0
  553. package/dist/types/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +1 -0
  554. package/dist/types/modules/excel/xlsx/xform/chart/chart-space-xform.d.ts +353 -0
  555. package/dist/types/modules/excel/xlsx/xform/comment/threaded-comments-xform.d.ts +60 -0
  556. package/dist/types/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +30 -0
  557. package/dist/types/modules/excel/xlsx/xform/drawing/graphic-frame-xform.d.ts +54 -0
  558. package/dist/types/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +3 -1
  559. package/dist/types/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +46 -0
  560. package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +13 -2
  561. package/dist/types/modules/excel/xlsx/xform/sheet/chartsheet-xform.d.ts +185 -0
  562. package/dist/types/modules/excel/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -0
  563. package/dist/types/modules/excel/xlsx/xform/xsd-values.d.ts +63 -0
  564. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +115 -21
  565. package/dist/types/modules/pdf/builder/document-builder.d.ts +74 -0
  566. package/dist/types/modules/pdf/excel-bridge.d.ts +69 -0
  567. package/dist/types/modules/pdf/font/font-manager.d.ts +25 -0
  568. package/dist/types/modules/pdf/index.d.ts +5 -2
  569. package/dist/types/modules/pdf/render/chart-surface.d.ts +33 -0
  570. package/dist/types/modules/pdf/render/layout-engine.d.ts +22 -1
  571. package/dist/types/modules/pdf/types.d.ts +227 -23
  572. package/dist/types/modules/pdf/word-bridge.d.ts +47 -0
  573. package/dist/types/modules/word/constants.d.ts +179 -0
  574. package/dist/types/modules/word/content-types.d.ts +27 -0
  575. package/dist/types/modules/word/digital-signatures.d.ts +87 -0
  576. package/dist/types/modules/word/document.d.ts +728 -0
  577. package/dist/types/modules/word/docx-packager.d.ts +14 -0
  578. package/dist/types/modules/word/docx-reader.d.ts +11 -0
  579. package/dist/types/modules/word/encryption.d.ts +102 -0
  580. package/dist/types/modules/word/errors.d.ts +49 -0
  581. package/dist/types/modules/word/font-obfuscation.d.ts +31 -0
  582. package/dist/types/modules/word/html-renderer.d.ts +38 -0
  583. package/dist/types/modules/word/index.base.d.ts +19 -0
  584. package/dist/types/modules/word/index.browser.d.ts +4 -0
  585. package/dist/types/modules/word/index.d.ts +4 -0
  586. package/dist/types/modules/word/internal-utils.d.ts +23 -0
  587. package/dist/types/modules/word/relationships.d.ts +31 -0
  588. package/dist/types/modules/word/types.d.ts +2325 -0
  589. package/dist/types/modules/word/units.d.ts +49 -0
  590. package/dist/types/modules/word/writers/chart-writer.d.ts +10 -0
  591. package/dist/types/modules/word/writers/checkbox-writer.d.ts +9 -0
  592. package/dist/types/modules/word/writers/comment-writer.d.ts +15 -0
  593. package/dist/types/modules/word/writers/document-writer.d.ts +16 -0
  594. package/dist/types/modules/word/writers/footnote-writer.d.ts +11 -0
  595. package/dist/types/modules/word/writers/header-footer-writer.d.ts +13 -0
  596. package/dist/types/modules/word/writers/image-writer.d.ts +10 -0
  597. package/dist/types/modules/word/writers/math-writer.d.ts +9 -0
  598. package/dist/types/modules/word/writers/numbering-writer.d.ts +10 -0
  599. package/dist/types/modules/word/writers/paragraph-writer.d.ts +13 -0
  600. package/dist/types/modules/word/writers/parts-writer.d.ts +26 -0
  601. package/dist/types/modules/word/writers/run-writer.d.ts +15 -0
  602. package/dist/types/modules/word/writers/section-writer.d.ts +10 -0
  603. package/dist/types/modules/word/writers/styles-writer.d.ts +10 -0
  604. package/dist/types/modules/word/writers/table-writer.d.ts +10 -0
  605. package/dist/types/modules/word/writers/textbox-writer.d.ts +9 -0
  606. package/dist/types/modules/word/writers/toc-writer.d.ts +9 -0
  607. package/dist/types/modules/xml/encode.d.ts +56 -7
  608. package/package.json +29 -11
  609. package/dist/browser/modules/excel/utils/ooxml-validator.d.ts +0 -48
  610. package/dist/browser/modules/excel/utils/ooxml-validator.js +0 -493
  611. package/dist/browser/modules/excel/utils/passthrough-manager.d.ts +0 -77
  612. package/dist/browser/modules/excel/utils/passthrough-manager.js +0 -129
  613. package/dist/cjs/modules/excel/utils/ooxml-validator.js +0 -499
  614. package/dist/cjs/modules/excel/utils/passthrough-manager.js +0 -133
  615. package/dist/esm/modules/excel/utils/ooxml-validator.js +0 -493
  616. package/dist/esm/modules/excel/utils/passthrough-manager.js +0 -129
  617. package/dist/types/modules/excel/utils/ooxml-validator.d.ts +0 -48
  618. package/dist/types/modules/excel/utils/passthrough-manager.d.ts +0 -77
@@ -0,0 +1,1557 @@
1
+ /**
2
+ * Shape property (spPr) and text property (txPr) utilities.
3
+ *
4
+ * During chart parsing, spPr and txPr elements are captured as raw XML strings
5
+ * for perfect round-trip fidelity. These utilities provide structured read/write
6
+ * access to the most commonly used properties:
7
+ *
8
+ * - Fill color (solid sRGB / theme)
9
+ * - Line/outline color and width
10
+ * - Font size, bold, italic, color, family
11
+ *
12
+ * The approach: parse raw XML on demand using regex extraction (no full DOM),
13
+ * and generate raw XML from structured models when creating new properties.
14
+ */
15
+ // ============================================================================
16
+ // Raw XML access helpers
17
+ // ============================================================================
18
+ /** Get the raw XML string if the object was captured as raw XML. */
19
+ function getRawXml(obj) {
20
+ return obj?._rawXml;
21
+ }
22
+ /**
23
+ * Check if the object is purely a raw XML capture — `_rawXml` is set
24
+ * and NO structured fields have been populated. The parser produces
25
+ * dual-state objects (both `_rawXml` and structured) from raw bytes so
26
+ * downstream consumers get the best of both worlds: cheap byte-perfect
27
+ * round-trip PLUS typed access. Getters (`getSpPrFillColor` et al.)
28
+ * must prefer structured when present; setters must NOT reparse from
29
+ * `_rawXml` because doing so wipes any prior structured mutation.
30
+ *
31
+ * Writers must ALSO consult this predicate before short-circuiting to
32
+ * the raw bytes: if the model has been mutated through a direct
33
+ * property assignment (`spPr.fill = {...}` without routing through
34
+ * `setSpPrFill`), the raw bytes are stale and the structured path
35
+ * must win. Exported for use by `_renderSpPr` in both the classic
36
+ * chart-space xform and the ChartEx renderer.
37
+ *
38
+ * Previously `isRawXml` returned `true` whenever `_rawXml` was a
39
+ * string, which caused `setSpPrFill` → `parseSpPr` to re-read from
40
+ * raw and discard pending `line.width` / `fill.solid` assignments.
41
+ */
42
+ export function isRawXmlShape(obj) {
43
+ return isRawXml(obj);
44
+ }
45
+ /**
46
+ * Whether a `ChartTextProperties` object is a pure raw-XML capture
47
+ * with no structured fields set. Analogous to {@link isRawXmlShape}
48
+ * for shape properties: when a caller directly assigns `txPr.color`,
49
+ * `txPr.size`, etc., the stale `_rawXml` must NOT win — the writer
50
+ * should fall through to the structured rendering path.
51
+ */
52
+ export function isRawXmlTxPr(obj) {
53
+ if (!obj || typeof obj._rawXml !== "string") {
54
+ return false;
55
+ }
56
+ const structuredKeys = [
57
+ "size",
58
+ "bold",
59
+ "italic",
60
+ "underline",
61
+ "strike",
62
+ "color",
63
+ "fontFamily",
64
+ "eastAsianFamily",
65
+ "complexScriptFamily",
66
+ "rotation",
67
+ "baseline",
68
+ "kern",
69
+ "spacing",
70
+ "cap",
71
+ "lang"
72
+ ];
73
+ for (const key of structuredKeys) {
74
+ if (obj[key] !== undefined) {
75
+ return false;
76
+ }
77
+ }
78
+ return true;
79
+ }
80
+ function isRawXml(obj) {
81
+ if (!obj || typeof obj._rawXml !== "string") {
82
+ return false;
83
+ }
84
+ // "Purely raw" when no structured field is present. Enumerate the
85
+ // fields we care about so adding new structured slots to
86
+ // `ShapeProperties` doesn't require touching this predicate —
87
+ // anything absent from this list is either raw-bytes-only (like
88
+ // `extLst`) or part of the raw payload itself.
89
+ const structuredKeys = [
90
+ "fill",
91
+ "line",
92
+ "effectList",
93
+ "scene3d",
94
+ "sp3d",
95
+ "transform",
96
+ "presetGeometry",
97
+ "customGeometry"
98
+ ];
99
+ for (const key of structuredKeys) {
100
+ if (obj[key] !== undefined) {
101
+ return false;
102
+ }
103
+ }
104
+ return true;
105
+ }
106
+ // ============================================================================
107
+ // Color parsing from raw XML
108
+ // ============================================================================
109
+ // Pre-compiled regexes for parseColorFromXml (always called with "a" prefix)
110
+ const SRGB_CLR_RE = /<a:srgbClr\s+val="([0-9A-Fa-f]{6})"/i;
111
+ const SCHEME_CLR_RE = /<a:schemeClr\s+val="([^"]+)"/i;
112
+ // Pre-compiled regexes for parseShadowElement
113
+ const OUTER_SHDW_RE = /<a:outerShdw\s+([^>]*)>([\s\S]*?)<\/a:outerShdw>/;
114
+ const INNER_SHDW_RE = /<a:innerShdw\s+([^>]*)>([\s\S]*?)<\/a:innerShdw>/;
115
+ const SHADOW_RES = {
116
+ "a:outerShdw": OUTER_SHDW_RE,
117
+ "a:innerShdw": INNER_SHDW_RE
118
+ };
119
+ /**
120
+ * Extract a region from `xml` between the opening tag match and the corresponding
121
+ * closing tag (or a reasonable fallback for self-closing elements).
122
+ */
123
+ function extractColorRegion(xml, openMatch, closeTag) {
124
+ const endIdx = xml.indexOf(closeTag, openMatch.index);
125
+ if (endIdx >= 0) {
126
+ // Stop at the close tag's `>` so the region never spills into the
127
+ // next sibling (which could itself have a colour element whose
128
+ // modifiers would then be misattributed).
129
+ const closeGt = xml.indexOf(">", endIdx);
130
+ return xml.slice(openMatch.index, closeGt >= 0 ? closeGt + 1 : endIdx + closeTag.length);
131
+ }
132
+ // No close tag — the element is self-closing (`<a:srgbClr val="FF0000"/>`)
133
+ // or truncated. DrawingML never nests modifiers inside a self-closing
134
+ // colour token, so return just the opening fragment up to the first
135
+ // `>` to avoid picking up modifiers that belong to a sibling colour.
136
+ const openEnd = xml.indexOf(">", openMatch.index);
137
+ return xml.slice(openMatch.index, openEnd >= 0 ? openEnd + 1 : openMatch.index + openMatch[0].length);
138
+ }
139
+ /**
140
+ * Parse all DrawingML color modifiers from a region of XML.
141
+ * Handles: alpha, tint, shade, satMod, lumMod, lumOff.
142
+ *
143
+ * Regexes accept `-?\d+(?:\.\d+)?` — negative and fractional values
144
+ * are legal in third-party exports (e.g. `<a:tint val="-5000"/>`,
145
+ * `<a:satMod val="123456.7"/>`); `\d+` alone dropped them silently.
146
+ * `parseFloat` with rounding preserves the intended semantics.
147
+ */
148
+ function parseColorModifiers(region, color) {
149
+ const parseModifierValue = (m) => m ? Math.round(parseFloat(m[1])) : undefined;
150
+ const alphaMatch = /<a:alpha\s+val="(-?\d+(?:\.\d+)?)"/.exec(region);
151
+ const alphaVal = parseModifierValue(alphaMatch);
152
+ if (alphaVal !== undefined) {
153
+ color.alpha = alphaVal;
154
+ }
155
+ const tintMatch = /<a:tint\s+val="(-?\d+(?:\.\d+)?)"/.exec(region);
156
+ if (tintMatch) {
157
+ color.tint = parseFloat(tintMatch[1]) / 100000;
158
+ }
159
+ const shadeMatch = /<a:shade\s+val="(-?\d+(?:\.\d+)?)"/.exec(region);
160
+ const shadeVal = parseModifierValue(shadeMatch);
161
+ if (shadeVal !== undefined) {
162
+ color.shade = shadeVal;
163
+ }
164
+ const satModMatch = /<a:satMod\s+val="(-?\d+(?:\.\d+)?)"/.exec(region);
165
+ const satModVal = parseModifierValue(satModMatch);
166
+ if (satModVal !== undefined) {
167
+ color.satMod = satModVal;
168
+ }
169
+ const lumModMatch = /<a:lumMod\s+val="(-?\d+(?:\.\d+)?)"/.exec(region);
170
+ const lumModVal = parseModifierValue(lumModMatch);
171
+ if (lumModVal !== undefined) {
172
+ color.lumMod = lumModVal;
173
+ }
174
+ const lumOffMatch = /<a:lumOff\s+val="(-?\d+(?:\.\d+)?)"/.exec(region);
175
+ const lumOffVal = parseModifierValue(lumOffMatch);
176
+ if (lumOffVal !== undefined) {
177
+ color.lumOff = lumOffVal;
178
+ }
179
+ }
180
+ // Pre-compiled regexes for sysClr / prstClr
181
+ const SYS_CLR_RE = /<a:sysClr\s+val="([^"]+)"/i;
182
+ const PRST_CLR_RE = /<a:prstClr\s+val="([^"]+)"/i;
183
+ function parseColorFromXml(xml) {
184
+ // Try srgbClr
185
+ const srgbMatch = SRGB_CLR_RE.exec(xml);
186
+ if (srgbMatch) {
187
+ const color = { srgb: srgbMatch[1].toUpperCase() };
188
+ const region = extractColorRegion(xml, srgbMatch, `</a:srgbClr`);
189
+ parseColorModifiers(region, color);
190
+ return color;
191
+ }
192
+ // Try schemeClr (theme)
193
+ const schemeMatch = SCHEME_CLR_RE.exec(xml);
194
+ if (schemeMatch) {
195
+ // Theme index → canonical scheme name. `tx1/bg1/tx2/bg2` are
196
+ // "slide"-style aliases of `dk1/lt1/dk2/lt2` defined in ECMA-376
197
+ // §20.1.2.3.29, so we fold them into the same indices rather than
198
+ // dropping them as "unknown theme" (which used to silently return
199
+ // index 0 / `dk1` and corrupt the colour on round-trip).
200
+ const themeMap = {
201
+ dk1: 0,
202
+ tx1: 0,
203
+ lt1: 1,
204
+ bg1: 1,
205
+ dk2: 2,
206
+ tx2: 2,
207
+ lt2: 3,
208
+ bg2: 3,
209
+ accent1: 4,
210
+ accent2: 5,
211
+ accent3: 6,
212
+ accent4: 7,
213
+ accent5: 8,
214
+ accent6: 9,
215
+ hlink: 10,
216
+ folHlink: 11
217
+ };
218
+ const raw = schemeMatch[1];
219
+ const idx = themeMap[raw];
220
+ // When we can't map the name to a theme index (e.g. `phClr` — the
221
+ // DrawingML "placeholder colour" token — or a future addition),
222
+ // preserve it as a scheme-name token under `schemeName` so the
223
+ // writer re-emits `<a:schemeClr val="…">` on round-trip. The old
224
+ // code stored the raw token under `sysClr`, which caused the
225
+ // writer to emit `<a:sysClr>` instead — silently changing the
226
+ // DrawingML element type and breaking theme placeholder semantics.
227
+ const color = idx !== undefined ? { theme: idx } : { schemeName: raw };
228
+ const region = extractColorRegion(xml, schemeMatch, `</a:schemeClr`);
229
+ parseColorModifiers(region, color);
230
+ return color;
231
+ }
232
+ // Try sysClr (system color)
233
+ const sysMatch = SYS_CLR_RE.exec(xml);
234
+ if (sysMatch) {
235
+ const color = { sysClr: sysMatch[1] };
236
+ const region = extractColorRegion(xml, sysMatch, `</a:sysClr`);
237
+ parseColorModifiers(region, color);
238
+ return color;
239
+ }
240
+ // Try prstClr (preset color)
241
+ const prstMatch = PRST_CLR_RE.exec(xml);
242
+ if (prstMatch) {
243
+ const color = { prstClr: prstMatch[1] };
244
+ const region = extractColorRegion(xml, prstMatch, `</a:prstClr`);
245
+ parseColorModifiers(region, color);
246
+ return color;
247
+ }
248
+ return undefined;
249
+ }
250
+ // ============================================================================
251
+ // Gradient / pattern fill parsing from raw XML
252
+ // ============================================================================
253
+ function parseGradientFill(xml) {
254
+ const gradStart = xml.indexOf("<a:gradFill");
255
+ const gradEnd = xml.indexOf("</a:gradFill");
256
+ if (gradStart < 0 || gradEnd < 0) {
257
+ return undefined;
258
+ }
259
+ const region = xml.slice(gradStart, gradEnd + 20);
260
+ // Parse gradient stops. OOXML `<a:gs pos="N">` encodes `N` as
261
+ // hundredths of a percent (0–100000), NOT thousandths. The
262
+ // previous implementation divided by 1000 — producing `stop.position`
263
+ // values that were 100× too large (e.g. a 50% stop decoded as 50
264
+ // instead of 0.5). Paired with the equally-wrong writer multiplier
265
+ // of ×1000, round-trip byte-compared equal but any freshly-built
266
+ // gradient rendered in Excel at a wildly wrong position. See the
267
+ // companion fix in `chart-ex-renderer.ts:renderSpPr` gradient path.
268
+ const stops = [];
269
+ // Find each <a:gs pos="..."> ... </a:gs>
270
+ const gsListStart = region.indexOf("<a:gsLst");
271
+ const gsListEnd = region.indexOf("</a:gsLst");
272
+ if (gsListStart >= 0 && gsListEnd >= 0) {
273
+ const gsListRegion = region.slice(gsListStart, gsListEnd + 12);
274
+ // OOXML `ST_PositiveFixedPercentage` is `xsd:int` in [0, 100000]
275
+ // — integer by schema — but third-party authors sometimes emit
276
+ // fractional values (e.g. `pos="33333.33"`) that readers tolerate.
277
+ // The previous `\d+`-only regex silently dropped stops with
278
+ // fractional positions, truncating the whole gradient on parse.
279
+ // Match fractional too so we at least preserve the author's intent.
280
+ const gsPosRegex = /<a:gs\s+pos="(-?\d+(?:\.\d+)?)"/g;
281
+ let match;
282
+ const positions = [];
283
+ while ((match = gsPosRegex.exec(gsListRegion)) !== null) {
284
+ positions.push({ pos: parseFloat(match[1]), startIdx: match.index });
285
+ }
286
+ for (let i = 0; i < positions.length; i++) {
287
+ const start = positions[i].startIdx;
288
+ const end = i + 1 < positions.length ? positions[i + 1].startIdx : gsListRegion.length;
289
+ const gsRegion = gsListRegion.slice(start, end);
290
+ const color = parseColorFromXml(gsRegion);
291
+ if (color) {
292
+ stops.push({ position: positions[i].pos / 100000, color });
293
+ }
294
+ }
295
+ }
296
+ // A legal gradient requires at least two stops — `CT_GradientStopList`
297
+ // declares `minOccurs="2"`. Reject single-stop gradients at parse so
298
+ // the writer (which gates `g.stops.length >= 2`) doesn't silently
299
+ // drop the entire `<a:gradFill>` block on round-trip, producing a
300
+ // shape with no fill attribute at all. A user authoring a malformed
301
+ // single-stop gradient is better served by a missing fill that
302
+ // surfaces in testing than by silent truncation at save.
303
+ if (stops.length < 2) {
304
+ return undefined;
305
+ }
306
+ // Parse angle from <a:lin ang="..."> — OOXML stores 60000ths of a
307
+ // degree. The attribute is an xsd:int but we accept fractional
308
+ // values too so libraries that emit millidegrees don't lose data.
309
+ // `scaled` is a sibling boolean attribute on the same element; we
310
+ // capture it only when authored so a default-scaled gradient doesn't
311
+ // round-trip as an explicit `scaled="1"` (matching Excel's emission,
312
+ // which omits the attribute when the implicit default applies).
313
+ let angle;
314
+ let scaled;
315
+ let type;
316
+ const linMatch = /<a:lin\b([^/>]*)\/?>/.exec(region);
317
+ if (linMatch) {
318
+ const linAttrs = linMatch[1];
319
+ const angMatch = /\bang="(-?\d+(?:\.\d+)?)"/.exec(linAttrs);
320
+ if (angMatch) {
321
+ angle = parseFloat(angMatch[1]) / 60000;
322
+ }
323
+ const scaledMatch = /\bscaled="(1|true|0|false)"/.exec(linAttrs);
324
+ if (scaledMatch) {
325
+ scaled = scaledMatch[1] === "1" || scaledMatch[1] === "true";
326
+ }
327
+ type = "linear";
328
+ }
329
+ // Check for path gradient — `<a:path path="circle|rect|shape">`
330
+ // optionally wrapping `<a:fillToRect l t r b/>` focal rectangle
331
+ // (each component in hundredths of a percent).
332
+ const pathMatch = /<a:path\s+path="([^"]+)"/.exec(region);
333
+ let fillToRect;
334
+ if (pathMatch) {
335
+ type = pathMatch[1];
336
+ const fillRectMatch = /<a:fillToRect\b([^/>]*)/.exec(region);
337
+ if (fillRectMatch) {
338
+ const attrs = fillRectMatch[1];
339
+ const pick = (name) => {
340
+ const m = new RegExp(`\\b${name}="(-?\\d+(?:\\.\\d+)?)"`).exec(attrs);
341
+ return m ? parseFloat(m[1]) / 100000 : undefined;
342
+ };
343
+ fillToRect = {
344
+ left: pick("l"),
345
+ top: pick("t"),
346
+ right: pick("r"),
347
+ bottom: pick("b")
348
+ };
349
+ // Drop the object entirely when every component is missing so we
350
+ // don't carry an all-undefined placeholder through the model.
351
+ if (fillToRect.left === undefined &&
352
+ fillToRect.top === undefined &&
353
+ fillToRect.right === undefined &&
354
+ fillToRect.bottom === undefined) {
355
+ fillToRect = undefined;
356
+ }
357
+ }
358
+ }
359
+ return {
360
+ gradient: {
361
+ stops,
362
+ angle,
363
+ type,
364
+ ...(scaled !== undefined ? { scaled } : {}),
365
+ ...(fillToRect ? { fillToRect } : {})
366
+ }
367
+ };
368
+ }
369
+ function parsePatternFill(xml) {
370
+ const pattMatch = /<a:pattFill\s+prst="([^"]+)"/.exec(xml);
371
+ if (!pattMatch) {
372
+ return undefined;
373
+ }
374
+ const preset = pattMatch[1];
375
+ const pattStart = pattMatch.index;
376
+ const pattEnd = xml.indexOf("</a:pattFill", pattStart);
377
+ const region = xml.slice(pattStart, pattEnd > 0 ? pattEnd + 15 : undefined);
378
+ // Slice each colour region by pair-of-tags OR by the range from the
379
+ // current open up to the next known child — matches what a real XML
380
+ // parser would do, and doesn't over-read into the sibling colour
381
+ // when the element happens to be self-closing.
382
+ const sliceChildRegion = (open, close, stopBefore) => {
383
+ const start = region.indexOf(open);
384
+ if (start < 0) {
385
+ return "";
386
+ }
387
+ const end = region.indexOf(close, start);
388
+ if (end >= 0) {
389
+ return region.slice(start, end + close.length + 1);
390
+ }
391
+ // No close tag — element is self-closing or malformed. Stop at
392
+ // the next recognised sibling child so the slice never walks into
393
+ // the neighbouring colour block.
394
+ const nextSibling = region.indexOf(stopBefore, start + open.length);
395
+ return region.slice(start, nextSibling > 0 ? nextSibling : undefined);
396
+ };
397
+ const fgRegion = sliceChildRegion("<a:fgClr", "</a:fgClr", "<a:bgClr");
398
+ const bgRegion = sliceChildRegion("<a:bgClr", "</a:bgClr", "<a:fgClr");
399
+ const foreground = fgRegion ? parseColorFromXml(fgRegion) : undefined;
400
+ const background = bgRegion ? parseColorFromXml(bgRegion) : undefined;
401
+ return { pattern: { preset, foreground, background } };
402
+ }
403
+ /**
404
+ * Remove the FIRST matching `<tag …>…</tag>` (or self-closing
405
+ * `<tag …/>`) block from the input XML, returning the remainder. Used
406
+ * by {@link parseSpPr} to isolate shape-level children (fill / effects)
407
+ * from decorative children that nest inside `<a:ln>` — the line's own
408
+ * `<a:solidFill>` / `<a:noFill/>` / `<a:gradFill>` should not be
409
+ * harvested as the shape's fill.
410
+ *
411
+ * Strips ALL occurrences of `tag` (both self-closing and paired) in
412
+ * one pass. A previous version returned after the earliest match,
413
+ * which failed on inputs like `<a:ln/>…<a:ln>…</a:ln>` — the paired
414
+ * block survived and its inner `<a:solidFill>` was then mistakenly
415
+ * parsed as the shape's fill.
416
+ *
417
+ * Not a general-purpose XML tool — does not handle same-named nested
418
+ * occurrences. Sufficient for DrawingML spPr, where `<a:ln>` never
419
+ * nests another `<a:ln>`.
420
+ */
421
+ function stripOuterElement(xml, tag) {
422
+ const selfCloseRe = new RegExp(`<${tag}\\b[^>]*/>`);
423
+ const openRe = new RegExp(`<${tag}\\b[^>]*(?<!/)>`);
424
+ const closeRe = new RegExp(`</${tag}>`);
425
+ let current = xml;
426
+ // Strip up to 8 occurrences. DrawingML spPr never has more than one
427
+ // `<a:ln>`, so the loop normally exits after the first iteration;
428
+ // the ceiling guards against pathological input causing infinite
429
+ // loops without changing the happy path.
430
+ for (let i = 0; i < 8; i++) {
431
+ const selfCloseMatch = selfCloseRe.exec(current);
432
+ const openMatch = openRe.exec(current);
433
+ const selfCloseIndex = selfCloseMatch ? selfCloseMatch.index : Infinity;
434
+ const openIndex = openMatch ? openMatch.index : Infinity;
435
+ if (selfCloseIndex === Infinity && openIndex === Infinity) {
436
+ break;
437
+ }
438
+ if (selfCloseIndex < openIndex && selfCloseMatch) {
439
+ current =
440
+ current.slice(0, selfCloseMatch.index) +
441
+ current.slice(selfCloseMatch.index + selfCloseMatch[0].length);
442
+ continue;
443
+ }
444
+ if (openMatch) {
445
+ // Find the close tag that pairs with this open — start searching
446
+ // after the open's end to avoid capturing `</tag>` that belongs
447
+ // to a prior unrelated (e.g. self-closing lookalike) open.
448
+ const openEnd = openMatch.index + openMatch[0].length;
449
+ const closeMatch = closeRe.exec(current.slice(openEnd));
450
+ if (!closeMatch) {
451
+ // Malformed — stop stripping to avoid further mutation of
452
+ // input we don't understand.
453
+ break;
454
+ }
455
+ const closeStart = openEnd + closeMatch.index;
456
+ const closeEnd = closeStart + closeMatch[0].length;
457
+ current = current.slice(0, openMatch.index) + current.slice(closeEnd);
458
+ continue;
459
+ }
460
+ break;
461
+ }
462
+ return current;
463
+ }
464
+ // ============================================================================
465
+ // spPr: Read structured properties from raw XML
466
+ // ============================================================================
467
+ /**
468
+ * Extract structured fill and line properties from a raw spPr XML string.
469
+ * Returns the structured ShapeProperties if extraction succeeds.
470
+ */
471
+ export function parseSpPr(spPr) {
472
+ const rawXml = getRawXml(spPr);
473
+ if (!rawXml) {
474
+ return spPr; // already structured
475
+ }
476
+ const result = {};
477
+ // The fill parser searches for `<a:solidFill>` at the top level — but
478
+ // `<a:ln>…<a:solidFill>…</a:solidFill></a:ln>` is a common DrawingML
479
+ // pattern where the line itself carries a solid colour. Previously
480
+ // `rawXml.includes("<a:solidFill")` matched the line's inner fill,
481
+ // picked up its colour as `result.fill.solid`, and the writer then
482
+ // emitted a phantom `<a:solidFill>` as a shape fill — silently
483
+ // painting the entire chart area with the border colour on re-save.
484
+ // Excise any `<a:ln>…</a:ln>` block before searching for the shape
485
+ // fill. The line block is parsed separately below, so nothing is
486
+ // lost. Gradient / pattern / noFill have the same issue with respect
487
+ // to `<a:ln>/<a:noFill/>`.
488
+ const fillSearchXml = stripOuterElement(rawXml, "a:ln");
489
+ // Parse fill
490
+ //
491
+ // The open/close tag search must be done defensively: `indexOf` on a
492
+ // missing close tag returns `-1`, so the naïve
493
+ // `fillSearchXml.slice(openIdx, fillSearchXml.indexOf("</a:solidFill") + 20)`
494
+ // picks up position `19` as the upper bound — either truncating the
495
+ // slice to garbage or producing an empty string. Both shapes
496
+ // silently corrupted the fill parser when a `<a:solidFill/>` was
497
+ // self-closed or when the close tag was missing.
498
+ //
499
+ // Prefer the open-tag-or-self-closing form, then only try to capture
500
+ // a close tag when we've seen a proper open tag. If we do not find a
501
+ // valid solid-fill region, fall through to the other fill branches
502
+ // so a `<a:gradFill>` that coexists with a malformed solidFill still
503
+ // gets picked up.
504
+ let fillMatched = false;
505
+ const solidFillSelfClose = /<a:solidFill\s*\/>/.exec(fillSearchXml);
506
+ const solidFillOpenIdx = fillSearchXml.indexOf("<a:solidFill");
507
+ const solidFillNonSelfClose = solidFillOpenIdx >= 0 && !solidFillSelfClose;
508
+ if (solidFillNonSelfClose) {
509
+ const closeIdx = fillSearchXml.indexOf("</a:solidFill>", solidFillOpenIdx);
510
+ if (closeIdx >= 0) {
511
+ const color = parseColorFromXml(fillSearchXml.slice(solidFillOpenIdx, closeIdx + "</a:solidFill>".length));
512
+ if (color) {
513
+ result.fill = { solid: color };
514
+ fillMatched = true;
515
+ }
516
+ }
517
+ // else: malformed solidFill (no close tag) — fall through below.
518
+ }
519
+ else if (solidFillSelfClose) {
520
+ // `<a:solidFill/>` has no child colour; DrawingML schema does not
521
+ // allow this, but some legacy exports emit it. Treat as "unknown
522
+ // fill, do not record" and fall through.
523
+ }
524
+ if (!fillMatched) {
525
+ if (fillSearchXml.includes("<a:noFill")) {
526
+ result.fill = { noFill: true };
527
+ }
528
+ else if (fillSearchXml.includes("<a:gradFill")) {
529
+ result.fill = parseGradientFill(fillSearchXml);
530
+ }
531
+ else if (fillSearchXml.includes("<a:pattFill")) {
532
+ result.fill = parsePatternFill(fillSearchXml);
533
+ }
534
+ }
535
+ // Parse line
536
+ //
537
+ // Anchor the regex on a real `<a:ln ...>` / `<a:ln>` / `<a:ln/>` — the
538
+ // lookahead `(?=[\s/>])` ensures we don't match a neighbouring element
539
+ // like `<a:lnRef>` or `<a:lnB>` (both appear in DrawingML theme /
540
+ // styleLst blocks) and silently walk the wrong region when extracting
541
+ // the stroke colour. We then parse `w` / other attributes separately
542
+ // from the captured opening-tag body — the old `(?:\s+w="(\d+)")?`
543
+ // inline group only captured `w` when it was the FIRST attribute
544
+ // after `<a:ln`, so `<a:ln cap="flat" w="12700">` silently dropped
545
+ // the width.
546
+ const lnMatch = /<a:ln(?=[\s/>])([^>]*)/.exec(rawXml);
547
+ if (lnMatch) {
548
+ // Distinguish `<a:ln/>` (self-closing, no body) from `<a:ln …>…</a:ln>`.
549
+ // The greedy `[^>]*` in the regex captures everything up to (but not
550
+ // including) the closing `>`. For `<a:ln w="12700"/>` the captured
551
+ // group is ` w="12700"/` — the `/` is THE self-close marker. Earlier
552
+ // code walked `rawXml[tokenEnd]` looking for `/`, but `tokenEnd` points
553
+ // at `>`, not `/`, so `selfClosing` was always false and the parser
554
+ // fell through to `indexOf("</a:ln", …)` (which returns -1 for a
555
+ // self-closing tag). That made `lnRegion` span to the end of the
556
+ // rawXml, causing the shape's own `<a:solidFill>` to be picked up as
557
+ // the line colour. Detect self-close by inspecting what the regex
558
+ // already captured — ignore trailing whitespace before the `/`.
559
+ const selfClosing = /\/\s*$/.test(lnMatch[1]);
560
+ const tokenEnd = lnMatch.index + lnMatch[0].length;
561
+ // The match stopped at the byte BEFORE the closing `>`; advance one
562
+ // character so the close-tag-aware slice below includes the `>`.
563
+ const openTagEnd = tokenEnd + 1;
564
+ // Use the full `</a:ln>` terminator (with the trailing `>`) instead
565
+ // of the old `</a:ln` prefix — the prefix also matches `</a:lnRef>`
566
+ // and `</a:lnB>` inside DrawingML styleLst blocks, which would
567
+ // cause the region to stop short of the real line close.
568
+ const lnEnd = selfClosing ? -1 : rawXml.indexOf("</a:ln>", lnMatch.index);
569
+ const lnRegion = selfClosing
570
+ ? rawXml.slice(lnMatch.index, openTagEnd)
571
+ : lnEnd >= 0
572
+ ? rawXml.slice(lnMatch.index, lnEnd + "</a:ln>".length)
573
+ : // Malformed (open tag with no matching close) — clip to the
574
+ // open tag only so we don't walk into unrelated XML. Previous
575
+ // behaviour sliced to `undefined` (rest of the document), which
576
+ // was the root of this bug.
577
+ rawXml.slice(lnMatch.index, openTagEnd);
578
+ const line = {};
579
+ const widthMatch = /\bw="(\d+)"/.exec(lnMatch[1]);
580
+ if (widthMatch) {
581
+ line.width = parseInt(widthMatch[1], 10);
582
+ }
583
+ if (lnRegion.includes("<a:noFill")) {
584
+ line.noFill = true;
585
+ }
586
+ else if (lnRegion.includes("<a:solidFill")) {
587
+ // Scope the colour search to the `<a:solidFill>` body so a line
588
+ // that also carries a gradient / pattern fill (rare but legal —
589
+ // `<a:ln><a:gradFill>…</a:gradFill></a:ln>`) doesn't pollute
590
+ // `parseColorFromXml` with the gradient's first stop colour. The
591
+ // previous code passed the whole `lnRegion` — if the line had
592
+ // both fills `parseColorFromXml` picked up whichever colour it
593
+ // found first in document order, silently mis-rendering the
594
+ // line. For pure-solid lines the result is identical.
595
+ const solidFillMatch = /<a:solidFill>([\s\S]*?)<\/a:solidFill>/.exec(lnRegion);
596
+ line.color = parseColorFromXml(solidFillMatch ? solidFillMatch[1] : lnRegion);
597
+ }
598
+ const dashMatch = /<a:prstDash\s+val="([^"]+)"/.exec(lnRegion);
599
+ if (dashMatch) {
600
+ line.dash = dashMatch[1];
601
+ }
602
+ result.line = line;
603
+ }
604
+ // Parse effect list
605
+ if (rawXml.includes("<a:effectLst") || rawXml.includes("<a:effectDag")) {
606
+ const effects = parseEffectList(rawXml);
607
+ if (effects) {
608
+ result.effectList = effects;
609
+ }
610
+ }
611
+ // Parse 3D scene and shape properties
612
+ if (rawXml.includes("<a:scene3d")) {
613
+ const scene = parseScene3D(rawXml);
614
+ if (scene) {
615
+ result.scene3d = scene;
616
+ }
617
+ }
618
+ if (rawXml.includes("<a:sp3d")) {
619
+ const sp3d = parseSp3D(rawXml);
620
+ if (sp3d) {
621
+ result.sp3d = sp3d;
622
+ }
623
+ }
624
+ // Transform (`a:xfrm`) — position, size, rotation, flips. The regex
625
+ // approach is a deliberate trade-off: a full XML walk would be more
626
+ // robust but also ~4x the code for a field Excel writes in a very
627
+ // constrained shape. If Excel ever nests `a:xfrm` with variants the
628
+ // round-trip raw-XML path still carries them.
629
+ if (rawXml.includes("<a:xfrm")) {
630
+ const transform = parseXfrm(rawXml);
631
+ if (transform) {
632
+ result.transform = transform;
633
+ }
634
+ }
635
+ if (rawXml.includes("<a:prstGeom")) {
636
+ const prst = parsePrstGeom(rawXml);
637
+ if (prst) {
638
+ result.presetGeometry = prst;
639
+ }
640
+ }
641
+ if (rawXml.includes("<a:custGeom")) {
642
+ const cust = parseCustGeom(rawXml);
643
+ if (cust) {
644
+ result.customGeometry = cust;
645
+ }
646
+ }
647
+ return result;
648
+ }
649
+ // ============================================================================
650
+ // Effect list parsing
651
+ // ============================================================================
652
+ // ============================================================================
653
+ /**
654
+ * Parse a single `<a:xfrm>` element out of the shape-properties raw
655
+ * XML blob. Returns `undefined` when the element is absent so callers
656
+ * can simply drop the result into a structural field.
657
+ *
658
+ * Shape: `<a:xfrm rot="…" flipH="1" flipV="1"><a:off x="…" y="…"/><a:ext cx="…" cy="…"/></a:xfrm>`.
659
+ * All five attributes and both children are optional; Excel omits
660
+ * `a:off`/`a:ext` when a shape inherits its parent's automatic
661
+ * layout.
662
+ */
663
+ function parseXfrm(xml) {
664
+ const match = /<a:xfrm\b([^>]*)(?:\/>|>([\s\S]*?)<\/a:xfrm>)/.exec(xml);
665
+ if (!match) {
666
+ return undefined;
667
+ }
668
+ const attrs = match[1] ?? "";
669
+ const inner = match[2] ?? "";
670
+ const result = {};
671
+ const rotAttr = /\brot="(-?\d+)"/.exec(attrs);
672
+ if (rotAttr) {
673
+ result.rotation = parseInt(rotAttr[1], 10);
674
+ }
675
+ if (/\bflipH="1"/.test(attrs)) {
676
+ result.flipHorizontal = true;
677
+ }
678
+ if (/\bflipV="1"/.test(attrs)) {
679
+ result.flipVertical = true;
680
+ }
681
+ const off = /<a:off\b([^/>]*)\/>/.exec(inner);
682
+ if (off) {
683
+ const x = /\bx="(-?\d+)"/.exec(off[1]);
684
+ const y = /\by="(-?\d+)"/.exec(off[1]);
685
+ if (x) {
686
+ result.offsetX = parseInt(x[1], 10);
687
+ }
688
+ if (y) {
689
+ result.offsetY = parseInt(y[1], 10);
690
+ }
691
+ }
692
+ const ext = /<a:ext\b([^/>]*)\/>/.exec(inner);
693
+ if (ext) {
694
+ const cx = /\bcx="(\d+)"/.exec(ext[1]);
695
+ const cy = /\bcy="(\d+)"/.exec(ext[1]);
696
+ if (cx) {
697
+ result.width = parseInt(cx[1], 10);
698
+ }
699
+ if (cy) {
700
+ result.height = parseInt(cy[1], 10);
701
+ }
702
+ }
703
+ return Object.keys(result).length > 0 ? result : undefined;
704
+ }
705
+ /**
706
+ * Parse `<a:prstGeom prst="…"><a:avLst>…</a:avLst></a:prstGeom>`.
707
+ * The `preset` name is mandatory; `adjustments` come from the
708
+ * optional `<a:avLst>` container whose children are `<a:gd name fmla>`
709
+ * triples. We read the raw `fmla` strings because they're a small
710
+ * OOXML sub-language (`"val 10000"` etc.) that callers rarely edit
711
+ * and would need a dedicated parser to structure further.
712
+ */
713
+ function parsePrstGeom(xml) {
714
+ const match = /<a:prstGeom\b([^>]*)(?:\/>|>([\s\S]*?)<\/a:prstGeom>)/.exec(xml);
715
+ if (!match) {
716
+ return undefined;
717
+ }
718
+ const attrs = match[1] ?? "";
719
+ const inner = match[2] ?? "";
720
+ const prstMatch = /\bprst="([^"]+)"/.exec(attrs);
721
+ if (!prstMatch) {
722
+ return undefined;
723
+ }
724
+ const result = { preset: prstMatch[1] };
725
+ const adjustments = parseAdjustmentList(inner);
726
+ if (adjustments.length > 0) {
727
+ result.adjustments = adjustments;
728
+ }
729
+ return result;
730
+ }
731
+ /**
732
+ * Parse `<a:custGeom>` into a {@link CustomGeometry}. The path-data
733
+ * parser is the focal effort: `<a:pathLst><a:path w h fill stroke>…</a:path></a:pathLst>`
734
+ * children enumerate moveTo / lnTo / arcTo / cubicBezTo / quadBezTo /
735
+ * close commands in OOXML's drawing-language flavour.
736
+ */
737
+ function parseCustGeom(xml) {
738
+ const match = /<a:custGeom\b[^>]*>([\s\S]*?)<\/a:custGeom>/.exec(xml);
739
+ if (!match) {
740
+ return undefined;
741
+ }
742
+ const body = match[1];
743
+ const result = {};
744
+ const adjustments = parseAdjustmentList(body);
745
+ if (adjustments.length > 0) {
746
+ result.adjustments = adjustments;
747
+ }
748
+ const paths = [];
749
+ const pathRe = /<a:path\b([^>]*)>([\s\S]*?)<\/a:path>/g;
750
+ let pm;
751
+ while ((pm = pathRe.exec(body)) !== null) {
752
+ const pAttrs = pm[1] ?? "";
753
+ const pBody = pm[2] ?? "";
754
+ const path = { commands: [] };
755
+ const wMatch = /\bw="(\d+)"/.exec(pAttrs);
756
+ const hMatch = /\bh="(\d+)"/.exec(pAttrs);
757
+ if (wMatch) {
758
+ path.w = parseInt(wMatch[1], 10);
759
+ }
760
+ if (hMatch) {
761
+ path.h = parseInt(hMatch[1], 10);
762
+ }
763
+ const fillMatch = /\bfill="([^"]+)"/.exec(pAttrs);
764
+ if (fillMatch) {
765
+ path.fill = fillMatch[1];
766
+ }
767
+ if (/\bstroke="1"/.test(pAttrs)) {
768
+ path.stroke = true;
769
+ }
770
+ else if (/\bstroke="0"/.test(pAttrs)) {
771
+ path.stroke = false;
772
+ }
773
+ path.commands = parseCustGeomCommands(pBody);
774
+ paths.push(path);
775
+ }
776
+ if (paths.length > 0) {
777
+ result.paths = paths;
778
+ }
779
+ return Object.keys(result).length > 0 ? result : undefined;
780
+ }
781
+ function parseAdjustmentList(xml) {
782
+ const avMatch = /<a:avLst\b[^>]*>([\s\S]*?)<\/a:avLst>/.exec(xml);
783
+ if (!avMatch) {
784
+ return [];
785
+ }
786
+ const out = [];
787
+ const gdRe = /<a:gd\b[^>]*\bname="([^"]+)"[^>]*\bfmla="([^"]+)"[^>]*\/>/g;
788
+ let m;
789
+ while ((m = gdRe.exec(avMatch[1])) !== null) {
790
+ out.push({ name: m[1], fmla: m[2] });
791
+ }
792
+ return out;
793
+ }
794
+ function parseCustGeomCommands(body) {
795
+ const commands = [];
796
+ // Walk commands in order — each `<a:moveTo>`/`<a:lnTo>`/… carries
797
+ // one or two `<a:pt x y>` children; `<a:arcTo>` carries explicit
798
+ // attributes instead. A greedy regex + lookahead captures the
799
+ // command block including the closing tag.
800
+ const cmdRe = /<a:(moveTo|lnTo|cubicBezTo|quadBezTo|arcTo|close)\b([^/>]*)(?:\/>|>([\s\S]*?)<\/a:\1>)/g;
801
+ let cm;
802
+ while ((cm = cmdRe.exec(body)) !== null) {
803
+ const kind = cm[1];
804
+ const cmdAttrs = cm[2] ?? "";
805
+ const cmdBody = cm[3] ?? "";
806
+ if (kind === "close") {
807
+ commands.push({ type: "close" });
808
+ continue;
809
+ }
810
+ if (kind === "arcTo") {
811
+ const wR = /\bwR="(-?\d+)"/.exec(cmdAttrs)?.[1];
812
+ const hR = /\bhR="(-?\d+)"/.exec(cmdAttrs)?.[1];
813
+ const stAng = /\bstAng="(-?\d+)"/.exec(cmdAttrs)?.[1];
814
+ const swAng = /\bswAng="(-?\d+)"/.exec(cmdAttrs)?.[1];
815
+ if (wR && hR && stAng && swAng) {
816
+ commands.push({
817
+ type: "arcTo",
818
+ arcParams: {
819
+ wR: parseInt(wR, 10),
820
+ hR: parseInt(hR, 10),
821
+ stAng: parseInt(stAng, 10),
822
+ swAng: parseInt(swAng, 10)
823
+ }
824
+ });
825
+ }
826
+ continue;
827
+ }
828
+ const points = [];
829
+ // Parse `<a:pt x="…" y="…"/>` without requiring a specific
830
+ // attribute order — some authors / writers emit
831
+ // `<a:pt y="100" x="200"/>` or interleave other attributes between
832
+ // `x` and `y`. The previous regex required `x` first, then only
833
+ // whitespace, then `y`, silently dropping all points on a
834
+ // legitimately-authored geometry that used the reversed order.
835
+ const ptRe = /<a:pt\b([^/>]*)\/>/g;
836
+ let pt;
837
+ while ((pt = ptRe.exec(cmdBody)) !== null) {
838
+ const attrs = pt[1];
839
+ const xAttr = /\bx="(-?\d+)"/.exec(attrs);
840
+ const yAttr = /\by="(-?\d+)"/.exec(attrs);
841
+ if (xAttr && yAttr) {
842
+ points.push({ x: parseInt(xAttr[1], 10), y: parseInt(yAttr[1], 10) });
843
+ }
844
+ }
845
+ commands.push({ type: kind, points });
846
+ }
847
+ return commands;
848
+ }
849
+ function parseEffectList(xml) {
850
+ const effStart = xml.indexOf("<a:effectLst");
851
+ const effEnd = xml.indexOf("</a:effectLst");
852
+ if (effStart < 0 || effEnd < 0) {
853
+ return undefined;
854
+ }
855
+ const region = xml.slice(effStart, effEnd + "</a:effectLst>".length);
856
+ const result = {};
857
+ // Blur
858
+ const blurMatch = /<a:blur(\s+[^/>]*)?\s*\/>/.exec(region);
859
+ if (blurMatch) {
860
+ const attrs = parseAttrs(blurMatch[0]);
861
+ result.blur = {};
862
+ if (attrs.rad) {
863
+ result.blur.radius = parseInt(attrs.rad, 10);
864
+ }
865
+ if (attrs.grow === "1") {
866
+ result.blur.grow = true;
867
+ }
868
+ }
869
+ // Outer shadow
870
+ const outerShadow = parseShadowElement(region, "a:outerShdw");
871
+ if (outerShadow) {
872
+ result.outerShadow = outerShadow;
873
+ }
874
+ // Inner shadow
875
+ const innerShadow = parseShadowElement(region, "a:innerShdw");
876
+ if (innerShadow) {
877
+ result.innerShadow = innerShadow;
878
+ }
879
+ // Preset shadow
880
+ const prstMatch = /<a:prstShdw\s+([^>]*)>([\s\S]*?)<\/a:prstShdw>/.exec(region);
881
+ if (prstMatch) {
882
+ const attrs = parseAttrs(prstMatch[0]);
883
+ const color = parseColorFromXml(prstMatch[2]);
884
+ if (attrs.prst && color) {
885
+ result.presetShadow = { preset: attrs.prst, color };
886
+ if (attrs.dist) {
887
+ result.presetShadow.distance = parseInt(attrs.dist, 10);
888
+ }
889
+ if (attrs.dir) {
890
+ result.presetShadow.direction = parseInt(attrs.dir, 10);
891
+ }
892
+ }
893
+ }
894
+ // Glow
895
+ const glowMatch = /<a:glow\s+([^>]*)>([\s\S]*?)<\/a:glow>/.exec(region);
896
+ if (glowMatch) {
897
+ const attrs = parseAttrs(glowMatch[0]);
898
+ const color = parseColorFromXml(glowMatch[2]);
899
+ if (attrs.rad && color) {
900
+ result.glow = { radius: parseInt(attrs.rad, 10), color };
901
+ }
902
+ }
903
+ // Soft edge
904
+ const softEdgeMatch = /<a:softEdge\s+([^/>]*)\s*\/>/.exec(region);
905
+ if (softEdgeMatch) {
906
+ const attrs = parseAttrs(softEdgeMatch[0]);
907
+ if (attrs.rad) {
908
+ result.softEdge = { radius: parseInt(attrs.rad, 10) };
909
+ }
910
+ }
911
+ // Reflection
912
+ const reflMatch = /<a:reflection\s+([^/>]*)\s*\/>/.exec(region);
913
+ if (reflMatch) {
914
+ const attrs = parseAttrs(reflMatch[0]);
915
+ const r = {};
916
+ if (attrs.blurRad) {
917
+ r.blurRadius = parseInt(attrs.blurRad, 10);
918
+ }
919
+ if (attrs.stA) {
920
+ r.startOpacity = parseInt(attrs.stA, 10);
921
+ }
922
+ if (attrs.stPos) {
923
+ r.startPosition = parseInt(attrs.stPos, 10);
924
+ }
925
+ if (attrs.endA) {
926
+ r.endOpacity = parseInt(attrs.endA, 10);
927
+ }
928
+ if (attrs.endPos) {
929
+ r.endPosition = parseInt(attrs.endPos, 10);
930
+ }
931
+ if (attrs.dist) {
932
+ r.distance = parseInt(attrs.dist, 10);
933
+ }
934
+ if (attrs.dir) {
935
+ r.direction = parseInt(attrs.dir, 10);
936
+ }
937
+ if (attrs.fadeDir) {
938
+ r.fadeDirection = parseInt(attrs.fadeDir, 10);
939
+ }
940
+ if (attrs.sx) {
941
+ r.scaleHorizontal = parseInt(attrs.sx, 10);
942
+ }
943
+ if (attrs.sy) {
944
+ r.scaleVertical = parseInt(attrs.sy, 10);
945
+ }
946
+ if (attrs.kx) {
947
+ r.skewHorizontal = parseInt(attrs.kx, 10);
948
+ }
949
+ if (attrs.ky) {
950
+ r.skewVertical = parseInt(attrs.ky, 10);
951
+ }
952
+ if (attrs.algn) {
953
+ r.alignment = attrs.algn;
954
+ }
955
+ if (attrs.rotWithShape === "1") {
956
+ r.rotateWithShape = true;
957
+ }
958
+ result.reflection = r;
959
+ }
960
+ if (Object.keys(result).length === 0) {
961
+ return undefined;
962
+ }
963
+ return result;
964
+ }
965
+ function parseShadowElement(xml, tag) {
966
+ const re = SHADOW_RES[tag] ?? new RegExp(`<${tag}\\s+([^>]*)>([\\s\\S]*?)<\\/${tag}>`);
967
+ const m = re.exec(xml);
968
+ if (!m) {
969
+ return undefined;
970
+ }
971
+ const attrs = parseAttrs(m[0]);
972
+ const color = parseColorFromXml(m[2]);
973
+ if (!color) {
974
+ return undefined;
975
+ }
976
+ const shadow = { color };
977
+ if (attrs.blurRad) {
978
+ shadow.blurRadius = parseInt(attrs.blurRad, 10);
979
+ }
980
+ if (attrs.dist) {
981
+ shadow.distance = parseInt(attrs.dist, 10);
982
+ }
983
+ if (attrs.dir) {
984
+ shadow.direction = parseInt(attrs.dir, 10);
985
+ }
986
+ if (attrs.algn) {
987
+ shadow.alignment = attrs.algn;
988
+ }
989
+ if (attrs.rotWithShape === "1") {
990
+ shadow.rotateWithShape = true;
991
+ }
992
+ if (attrs.sx) {
993
+ shadow.scaleHorizontal = parseInt(attrs.sx, 10);
994
+ }
995
+ if (attrs.sy) {
996
+ shadow.scaleVertical = parseInt(attrs.sy, 10);
997
+ }
998
+ if (attrs.kx) {
999
+ shadow.skewHorizontal = parseInt(attrs.kx, 10);
1000
+ }
1001
+ if (attrs.ky) {
1002
+ shadow.skewVertical = parseInt(attrs.ky, 10);
1003
+ }
1004
+ return shadow;
1005
+ }
1006
+ function parseScene3D(xml) {
1007
+ const sceneStart = xml.indexOf("<a:scene3d");
1008
+ const sceneEnd = xml.indexOf("</a:scene3d");
1009
+ if (sceneStart < 0 || sceneEnd < 0) {
1010
+ return undefined;
1011
+ }
1012
+ const region = xml.slice(sceneStart, sceneEnd + 13);
1013
+ const result = {};
1014
+ const cameraMatch = /<a:camera\s+([^>]*)(?:\/|>[\s\S]*?<\/a:camera)>/.exec(region);
1015
+ if (cameraMatch) {
1016
+ const attrs = parseAttrs(cameraMatch[0]);
1017
+ if (attrs.prst) {
1018
+ result.camera = { preset: attrs.prst };
1019
+ if (attrs.fov) {
1020
+ result.camera.fov = parseInt(attrs.fov, 10);
1021
+ }
1022
+ if (attrs.zoom) {
1023
+ result.camera.zoom = parseInt(attrs.zoom, 10);
1024
+ }
1025
+ const rotMatch = /<a:rot\s+([^/>]*)\s*\/>/.exec(cameraMatch[0]);
1026
+ if (rotMatch) {
1027
+ const ra = parseAttrs(rotMatch[0]);
1028
+ if (ra.lat && ra.lon && ra.rev) {
1029
+ result.camera.rotation = {
1030
+ lat: parseInt(ra.lat, 10),
1031
+ lon: parseInt(ra.lon, 10),
1032
+ rev: parseInt(ra.rev, 10)
1033
+ };
1034
+ }
1035
+ }
1036
+ }
1037
+ }
1038
+ const lightRigMatch = /<a:lightRig\s+([^>]*)(?:\/|>[\s\S]*?<\/a:lightRig)>/.exec(region);
1039
+ if (lightRigMatch) {
1040
+ const attrs = parseAttrs(lightRigMatch[0]);
1041
+ if (attrs.rig && attrs.dir) {
1042
+ result.lightRig = { rig: attrs.rig, direction: attrs.dir };
1043
+ }
1044
+ }
1045
+ if (!result.camera && !result.lightRig) {
1046
+ return undefined;
1047
+ }
1048
+ return result;
1049
+ }
1050
+ function parseSp3D(xml) {
1051
+ const spStart = xml.indexOf("<a:sp3d");
1052
+ if (spStart < 0) {
1053
+ return undefined;
1054
+ }
1055
+ // Determine the tag extent using indexOf (no backtracking risk).
1056
+ const selfCloseEnd = xml.indexOf("/>", spStart);
1057
+ const openTagEnd = xml.indexOf(">", spStart);
1058
+ const isSelfClose = selfCloseEnd >= 0 && (openTagEnd < 0 || selfCloseEnd < openTagEnd);
1059
+ let region;
1060
+ if (isSelfClose) {
1061
+ region = xml.slice(spStart, selfCloseEnd + 2);
1062
+ }
1063
+ else if (openTagEnd >= 0) {
1064
+ const closeTag = "</a:sp3d>";
1065
+ const closeIdx = xml.indexOf(closeTag, openTagEnd);
1066
+ region =
1067
+ closeIdx >= 0
1068
+ ? xml.slice(spStart, closeIdx + closeTag.length)
1069
+ : xml.slice(spStart, openTagEnd + 1);
1070
+ }
1071
+ else {
1072
+ region = xml.slice(spStart);
1073
+ }
1074
+ // Only parse attributes from the opening tag itself — NOT from child
1075
+ // elements (e.g. `<a:bevelT w="..." h="..."/>`) which would pollute
1076
+ // the attribute dict with unrelated keys.
1077
+ const firstClose = region.indexOf(">");
1078
+ const openTag = firstClose >= 0 ? region.slice(0, firstClose + 1) : region;
1079
+ const attrs = parseAttrs(openTag);
1080
+ const result = {};
1081
+ if (attrs.z) {
1082
+ result.z = parseInt(attrs.z, 10);
1083
+ }
1084
+ if (attrs.extrusionH) {
1085
+ result.extrusionHeight = parseInt(attrs.extrusionH, 10);
1086
+ }
1087
+ if (attrs.contourW) {
1088
+ result.contourWidth = parseInt(attrs.contourW, 10);
1089
+ }
1090
+ if (attrs.prstMaterial) {
1091
+ result.material = attrs.prstMaterial;
1092
+ }
1093
+ // Bevels — use indexOf to find the self-closing tags within the region
1094
+ const bevelTStart = region.indexOf("<a:bevelT");
1095
+ if (bevelTStart >= 0) {
1096
+ const bevelTEnd = region.indexOf("/>", bevelTStart);
1097
+ if (bevelTEnd >= 0) {
1098
+ result.bevelTop = parseBevelAttrs(region.slice(bevelTStart, bevelTEnd + 2));
1099
+ }
1100
+ }
1101
+ const bevelBStart = region.indexOf("<a:bevelB");
1102
+ if (bevelBStart >= 0) {
1103
+ const bevelBEnd = region.indexOf("/>", bevelBStart);
1104
+ if (bevelBEnd >= 0) {
1105
+ result.bevelBottom = parseBevelAttrs(region.slice(bevelBStart, bevelBEnd + 2));
1106
+ }
1107
+ }
1108
+ // Extrusion / contour colours — only present in open-close form
1109
+ if (!isSelfClose) {
1110
+ const extOpen = "<a:extrusionClr>";
1111
+ const extClose = "</a:extrusionClr>";
1112
+ const extStart = region.indexOf(extOpen);
1113
+ if (extStart >= 0) {
1114
+ const extEnd = region.indexOf(extClose, extStart);
1115
+ if (extEnd >= 0) {
1116
+ const c = parseColorFromXml(region.slice(extStart + extOpen.length, extEnd));
1117
+ if (c) {
1118
+ result.extrusionColor = c;
1119
+ }
1120
+ }
1121
+ }
1122
+ const contOpen = "<a:contourClr>";
1123
+ const contClose = "</a:contourClr>";
1124
+ const contStart = region.indexOf(contOpen);
1125
+ if (contStart >= 0) {
1126
+ const contEnd = region.indexOf(contClose, contStart);
1127
+ if (contEnd >= 0) {
1128
+ const c = parseColorFromXml(region.slice(contStart + contOpen.length, contEnd));
1129
+ if (c) {
1130
+ result.contourColor = c;
1131
+ }
1132
+ }
1133
+ }
1134
+ }
1135
+ return result;
1136
+ }
1137
+ function parseBevelAttrs(tag) {
1138
+ const attrs = parseAttrs(tag);
1139
+ const bevel = {};
1140
+ if (attrs.w) {
1141
+ bevel.width = parseInt(attrs.w, 10);
1142
+ }
1143
+ if (attrs.h) {
1144
+ bevel.height = parseInt(attrs.h, 10);
1145
+ }
1146
+ if (attrs.prst) {
1147
+ bevel.preset = attrs.prst;
1148
+ }
1149
+ return bevel;
1150
+ }
1151
+ function parseAttrs(tag) {
1152
+ const attrs = {};
1153
+ // Manual parser avoids regex backtracking on uncontrolled input.
1154
+ let i = 0;
1155
+ const len = tag.length;
1156
+ while (i < len) {
1157
+ // Skip non-word characters
1158
+ while (i < len && !isWordChar(tag.charCodeAt(i))) {
1159
+ i++;
1160
+ }
1161
+ if (i >= len) {
1162
+ break;
1163
+ }
1164
+ // Read attribute name (word chars only)
1165
+ const nameStart = i;
1166
+ while (i < len && isWordChar(tag.charCodeAt(i))) {
1167
+ i++;
1168
+ }
1169
+ const name = tag.slice(nameStart, i);
1170
+ // Expect `="`
1171
+ if (i >= len || tag.charCodeAt(i) !== 61 /* = */) {
1172
+ continue;
1173
+ }
1174
+ i++;
1175
+ if (i >= len || tag.charCodeAt(i) !== 34 /* " */) {
1176
+ continue;
1177
+ }
1178
+ i++;
1179
+ // Read attribute value until closing quote
1180
+ const valStart = i;
1181
+ while (i < len && tag.charCodeAt(i) !== 34) {
1182
+ i++;
1183
+ }
1184
+ attrs[name] = tag.slice(valStart, i);
1185
+ if (i < len) {
1186
+ i++; // skip closing quote
1187
+ }
1188
+ }
1189
+ return attrs;
1190
+ }
1191
+ /** Check if a char code is a word character [A-Za-z0-9_]. */
1192
+ function isWordChar(c) {
1193
+ return ((c >= 65 && c <= 90) || // A-Z
1194
+ (c >= 97 && c <= 122) || // a-z
1195
+ (c >= 48 && c <= 57) || // 0-9
1196
+ c === 95 // _
1197
+ );
1198
+ }
1199
+ /**
1200
+ * Extract a single attribute value from the first occurrence of `<tagName ...>`
1201
+ * in `xml`. Uses indexOf to locate the tag (no backtracking risk) then a simple
1202
+ * attribute regex on the bounded tag substring.
1203
+ */
1204
+ function findTagAttr(xml, tagName, attrName) {
1205
+ const tagStart = xml.indexOf(`<${tagName}`);
1206
+ if (tagStart < 0) {
1207
+ return undefined;
1208
+ }
1209
+ const tagEnd = xml.indexOf(">", tagStart);
1210
+ if (tagEnd < 0) {
1211
+ return undefined;
1212
+ }
1213
+ const tag = xml.slice(tagStart, tagEnd + 1);
1214
+ const re = new RegExp(`${attrName}="([^"]*)"`);
1215
+ const m = re.exec(tag);
1216
+ return m ? m[1] : undefined;
1217
+ }
1218
+ /**
1219
+ * Get the solid fill color from a ShapeProperties object.
1220
+ * Works for both raw XML and structured models.
1221
+ */
1222
+ export function getSpPrFillColor(spPr) {
1223
+ const parsed = isRawXml(spPr) ? parseSpPr(spPr) : spPr;
1224
+ return parsed.fill?.solid;
1225
+ }
1226
+ /**
1227
+ * Get the complete fill (solid / gradient / pattern / noFill) from a
1228
+ * ShapeProperties object. Works for both raw XML and structured models.
1229
+ * Prefer this over {@link getSpPrFillColor} when the caller needs to
1230
+ * distinguish between "no fill", "gradient", etc. — the color-only
1231
+ * accessor collapses all three to `undefined`.
1232
+ */
1233
+ export function getSpPrFill(spPr) {
1234
+ const parsed = isRawXml(spPr) ? parseSpPr(spPr) : spPr;
1235
+ return parsed.fill;
1236
+ }
1237
+ /**
1238
+ * Get the line/outline properties from a ShapeProperties object.
1239
+ */
1240
+ export function getSpPrLine(spPr) {
1241
+ const parsed = isRawXml(spPr) ? parseSpPr(spPr) : spPr;
1242
+ return parsed.line;
1243
+ }
1244
+ /**
1245
+ * Get the gradient fill from a ShapeProperties object.
1246
+ */
1247
+ export function getSpPrGradient(spPr) {
1248
+ const parsed = isRawXml(spPr) ? parseSpPr(spPr) : spPr;
1249
+ return parsed.fill?.gradient;
1250
+ }
1251
+ /**
1252
+ * Get the pattern fill from a ShapeProperties object.
1253
+ */
1254
+ export function getSpPrPattern(spPr) {
1255
+ const parsed = isRawXml(spPr) ? parseSpPr(spPr) : spPr;
1256
+ return parsed.fill?.pattern;
1257
+ }
1258
+ // ============================================================================
1259
+ // txPr: Read structured properties from raw XML
1260
+ // ============================================================================
1261
+ /**
1262
+ * Extract structured text properties from a raw txPr XML string.
1263
+ *
1264
+ * Parses the fields the structured {@link ChartTextProperties} model
1265
+ * declares:
1266
+ * - `size`, `bold`, `italic`, `underline`, `strike`, `cap`, `baseline`,
1267
+ * `kern`, `spacing`, `lang` (from the first `<a:defRPr>` / `<a:rPr>`)
1268
+ * - `color` (from `<a:solidFill>` inside the same element)
1269
+ * - `fontFamily`, `eastAsianFamily`, `complexScriptFamily`
1270
+ * (from `<a:latin>` / `<a:ea>` / `<a:cs>` children)
1271
+ * - `rotation` (from `<a:bodyPr/@rot>`)
1272
+ *
1273
+ * Callers that want to preserve every attribute OOXML might carry
1274
+ * (e.g. `spc="100"`, `u="sng"`, `baseline="30000"`) must not rely on
1275
+ * this function round-tripping via structured fields alone — keep the
1276
+ * `_rawXml` on the txPr. This parser is a best-effort structural view
1277
+ * for consumers that want to READ the common properties; `_rawXml`
1278
+ * remains authoritative for write-side fidelity.
1279
+ */
1280
+ export function parseTxPr(txPr) {
1281
+ const rawXml = getRawXml(txPr);
1282
+ if (!rawXml) {
1283
+ return txPr; // already structured
1284
+ }
1285
+ const result = {};
1286
+ // Font size (a:sz) — search defRPr first, then rPr
1287
+ const szVal = findTagAttr(rawXml, "a:defRPr", "sz") ?? findTagAttr(rawXml, "a:rPr", "sz");
1288
+ if (szVal) {
1289
+ result.size = parseInt(szVal, 10);
1290
+ }
1291
+ // Bold — accept `"1"` / `"true"` per XSD `xsd:boolean`. Previously
1292
+ // only `"1"` was recognised, so LibreOffice-authored files (which
1293
+ // emit `b="true"`) silently round-tripped bold text as regular.
1294
+ // An explicit `b="0"` / `b="false"` is preserved as `false` rather
1295
+ // than dropped — semantically distinct from the attribute being
1296
+ // absent (which leaves the field undefined so downstream writers
1297
+ // know not to force a value).
1298
+ const bVal = findTagAttr(rawXml, "a:defRPr", "b") ?? findTagAttr(rawXml, "a:rPr", "b");
1299
+ if (bVal) {
1300
+ result.bold = bVal === "1" || bVal === "true";
1301
+ }
1302
+ // Italic — same lenient boolean handling as `b` above.
1303
+ const iVal = findTagAttr(rawXml, "a:defRPr", "i") ?? findTagAttr(rawXml, "a:rPr", "i");
1304
+ if (iVal) {
1305
+ result.italic = iVal === "1" || iVal === "true";
1306
+ }
1307
+ // Underline style (a:rPr/@u). Values are the DrawingML `ST_TextUnderlineType`
1308
+ // enum: "none" | "sng" | "dbl" | "heavy" | "dotted" | "dottedHeavy" |
1309
+ // "dash" | "dashHeavy" | "dashLong" | "dashLongHeavy" | "dotDash" |
1310
+ // "dotDashHeavy" | "dotDotDash" | "dotDotDashHeavy" | "wavy" |
1311
+ // "wavyHeavy" | "wavyDbl".
1312
+ const uVal = findTagAttr(rawXml, "a:defRPr", "u") ?? findTagAttr(rawXml, "a:rPr", "u");
1313
+ if (uVal) {
1314
+ result.underline = uVal;
1315
+ }
1316
+ // Strike-through (a:rPr/@strike). Values: "noStrike" | "sngStrike" |
1317
+ // "dblStrike".
1318
+ const strikeVal = findTagAttr(rawXml, "a:defRPr", "strike") ?? findTagAttr(rawXml, "a:rPr", "strike");
1319
+ if (strikeVal) {
1320
+ result.strike = strikeVal;
1321
+ }
1322
+ // Capitalisation (a:rPr/@cap). Values: "none" | "small" | "all".
1323
+ const capVal = findTagAttr(rawXml, "a:defRPr", "cap") ?? findTagAttr(rawXml, "a:rPr", "cap");
1324
+ if (capVal) {
1325
+ result.cap = capVal;
1326
+ }
1327
+ // Baseline offset (a:rPr/@baseline) — percentage * 1000 per OOXML
1328
+ // (signed; positive = superscript, negative = subscript).
1329
+ const baselineVal = findTagAttr(rawXml, "a:defRPr", "baseline") ?? findTagAttr(rawXml, "a:rPr", "baseline");
1330
+ if (baselineVal) {
1331
+ result.baseline = parseInt(baselineVal, 10);
1332
+ }
1333
+ // Character kerning cut-off (a:rPr/@kern) — hundredths of a point.
1334
+ const kernVal = findTagAttr(rawXml, "a:defRPr", "kern") ?? findTagAttr(rawXml, "a:rPr", "kern");
1335
+ if (kernVal) {
1336
+ result.kern = parseInt(kernVal, 10);
1337
+ }
1338
+ // Character spacing (a:rPr/@spc) — hundredths of a point.
1339
+ const spcVal = findTagAttr(rawXml, "a:defRPr", "spc") ?? findTagAttr(rawXml, "a:rPr", "spc");
1340
+ if (spcVal) {
1341
+ result.spacing = parseInt(spcVal, 10);
1342
+ }
1343
+ // Language (a:rPr/@lang) — BCP 47 language tag (e.g. "en-US", "ja-JP").
1344
+ // Wider character class than `\w+` because tags can include hyphens
1345
+ // and digits ("zh-Hant-TW").
1346
+ const langVal = findTagAttr(rawXml, "a:defRPr", "lang") ?? findTagAttr(rawXml, "a:rPr", "lang");
1347
+ if (langVal) {
1348
+ result.lang = langVal;
1349
+ }
1350
+ // Font color. Try the paragraph-level default (`<a:defRPr>…`) first,
1351
+ // then fall back to the first run-property block (`<a:rPr>…`). Chart
1352
+ // titles / data-label rich text often carry colour on `<a:rPr>` (per
1353
+ // run), not on `<a:defRPr>` — the old implementation only checked the
1354
+ // former and silently dropped colour on round-trip.
1355
+ const extractColorFrom = (openTag, closeTag) => {
1356
+ const start = rawXml.indexOf(openTag);
1357
+ if (start < 0) {
1358
+ return undefined;
1359
+ }
1360
+ const end = rawXml.indexOf(closeTag, start);
1361
+ const region = rawXml.slice(start, end > 0 ? end + closeTag.length : undefined);
1362
+ if (!region.includes("<a:solidFill")) {
1363
+ return undefined;
1364
+ }
1365
+ return parseColorFromXml(region);
1366
+ };
1367
+ result.color =
1368
+ extractColorFrom("<a:defRPr", "</a:defRPr>") ?? extractColorFrom("<a:rPr", "</a:rPr>");
1369
+ // Latin font family (a:latin/@typeface) — structured default.
1370
+ const latinMatch = /<a:latin\s+typeface="([^"]+)"/.exec(rawXml);
1371
+ if (latinMatch) {
1372
+ result.fontFamily = latinMatch[1];
1373
+ }
1374
+ // East Asian font family (a:ea/@typeface) — used for CJK characters
1375
+ // when the primary Latin font doesn't cover them. Dropping this
1376
+ // field on round-trip made CJK-labelled charts reflow on reload.
1377
+ const eaMatch = /<a:ea\s+typeface="([^"]+)"/.exec(rawXml);
1378
+ if (eaMatch) {
1379
+ result.eastAsianFamily = eaMatch[1];
1380
+ }
1381
+ // Complex-script font family (a:cs/@typeface) — used for Arabic /
1382
+ // Hebrew / Thai fallbacks.
1383
+ const csMatch = /<a:cs\s+typeface="([^"]+)"/.exec(rawXml);
1384
+ if (csMatch) {
1385
+ result.complexScriptFamily = csMatch[1];
1386
+ }
1387
+ // Rotation (on bodyPr)
1388
+ const rotVal = findTagAttr(rawXml, "a:bodyPr", "rot");
1389
+ if (rotVal) {
1390
+ result.rotation = parseInt(rotVal, 10);
1391
+ }
1392
+ return result;
1393
+ }
1394
+ /**
1395
+ * Get font size from a ChartTextProperties object (returns points, e.g. 10).
1396
+ */
1397
+ export function getTxPrFontSize(txPr) {
1398
+ const parsed = isRawXml(txPr) ? parseTxPr(txPr) : txPr;
1399
+ return parsed.size !== undefined ? parsed.size / 100 : undefined;
1400
+ }
1401
+ /**
1402
+ * Get font color from a ChartTextProperties object.
1403
+ */
1404
+ export function getTxPrColor(txPr) {
1405
+ const parsed = isRawXml(txPr) ? parseTxPr(txPr) : txPr;
1406
+ return parsed.color;
1407
+ }
1408
+ /**
1409
+ * Get the font family (typeface) declared on `<a:latin>` / `<a:cs>`
1410
+ * within a `txPr` raw or structured object. Returns `undefined` if the
1411
+ * properties do not carry a typeface, in which case renderers should
1412
+ * use their own default.
1413
+ */
1414
+ export function getTxPrFontFamily(txPr) {
1415
+ const parsed = isRawXml(txPr) ? parseTxPr(txPr) : txPr;
1416
+ return parsed.fontFamily;
1417
+ }
1418
+ /**
1419
+ * Get the boolean bold flag from a `txPr`'s first `a:defRPr`/`a:rPr`.
1420
+ */
1421
+ export function getTxPrBold(txPr) {
1422
+ const parsed = isRawXml(txPr) ? parseTxPr(txPr) : txPr;
1423
+ return parsed.bold;
1424
+ }
1425
+ /**
1426
+ * Get the boolean italic flag from a `txPr`'s first `a:defRPr`/`a:rPr`.
1427
+ */
1428
+ export function getTxPrItalic(txPr) {
1429
+ const parsed = isRawXml(txPr) ? parseTxPr(txPr) : txPr;
1430
+ return parsed.italic;
1431
+ }
1432
+ // ============================================================================
1433
+ // Build structured spPr / txPr models
1434
+ // ============================================================================
1435
+ //
1436
+ // Previously this module also produced raw DrawingML XML for spPr / txPr via
1437
+ // a `colorToXml` helper. That path was removed because the chart writer
1438
+ // (`chart-space-xform._renderSpPr` / `_renderTxPr` / `_renderColor`) emits
1439
+ // the XML directly from structured data, and returning raw XML here forced
1440
+ // callers to rebuild `buildTxPr` after every mutation. The helper was dead
1441
+ // code and has been deleted — see the note on `buildTxPr` below.
1442
+ /**
1443
+ * Build a structured ShapeProperties object, preserving every field that
1444
+ * `parseSpPr` can produce (fill, line, effectList, scene3d, sp3d, transform,
1445
+ * presetGeometry, customGeometry, bwMode).
1446
+ *
1447
+ * Previous versions only copied a five-field subset, which caused
1448
+ * `setSpPrFill` / `setSpPrLine` to silently strip `xfrm` / `prstGeom` /
1449
+ * `custGeom` off the returned spPr whenever the input had been parsed from
1450
+ * raw XML. The earlier `_rawXml` round-trip path was dropped because it lost
1451
+ * effectList/scene3d/sp3d; we now keep all structured fields and intentionally
1452
+ * omit `_rawXml` so that `_renderSpPr` (chart-space-xform) re-emits the spPr
1453
+ * from the structured data.
1454
+ */
1455
+ export function buildSpPr(props) {
1456
+ const result = {};
1457
+ if (props.fill) {
1458
+ result.fill = props.fill;
1459
+ }
1460
+ if (props.line) {
1461
+ result.line = props.line;
1462
+ }
1463
+ if (props.effectList) {
1464
+ result.effectList = props.effectList;
1465
+ }
1466
+ if (props.scene3d) {
1467
+ result.scene3d = props.scene3d;
1468
+ }
1469
+ if (props.sp3d) {
1470
+ result.sp3d = props.sp3d;
1471
+ }
1472
+ if (props.transform) {
1473
+ result.transform = props.transform;
1474
+ }
1475
+ if (props.presetGeometry) {
1476
+ result.presetGeometry = props.presetGeometry;
1477
+ }
1478
+ if (props.customGeometry) {
1479
+ result.customGeometry = props.customGeometry;
1480
+ }
1481
+ return result;
1482
+ }
1483
+ /**
1484
+ * Build a structured {@link ChartTextProperties} object.
1485
+ *
1486
+ * Returns a plain structured copy (no `_rawXml`) so downstream mutations
1487
+ * (`props.size = 1400`) take effect when the txPr is later serialised.
1488
+ * The writer (`_renderTxPr` / `_renderRunProperties` in
1489
+ * `chart-space-xform.ts`) fully supports structured txPr data and only
1490
+ * falls back to raw XML pass-through when `_rawXml` is present; returning
1491
+ * `_rawXml` here would freeze the txPr and silently discard subsequent
1492
+ * edits, which is a trap API.
1493
+ */
1494
+ export function buildTxPr(props) {
1495
+ const result = {};
1496
+ if (props.size !== undefined) {
1497
+ result.size = props.size;
1498
+ }
1499
+ if (props.bold !== undefined) {
1500
+ result.bold = props.bold;
1501
+ }
1502
+ if (props.italic !== undefined) {
1503
+ result.italic = props.italic;
1504
+ }
1505
+ if (props.underline !== undefined) {
1506
+ result.underline = props.underline;
1507
+ }
1508
+ if (props.strike !== undefined) {
1509
+ result.strike = props.strike;
1510
+ }
1511
+ if (props.rotation !== undefined) {
1512
+ result.rotation = props.rotation;
1513
+ }
1514
+ if (props.baseline !== undefined) {
1515
+ result.baseline = props.baseline;
1516
+ }
1517
+ if (props.kern !== undefined) {
1518
+ result.kern = props.kern;
1519
+ }
1520
+ if (props.spacing !== undefined) {
1521
+ result.spacing = props.spacing;
1522
+ }
1523
+ if (props.cap !== undefined) {
1524
+ result.cap = props.cap;
1525
+ }
1526
+ if (props.lang !== undefined) {
1527
+ result.lang = props.lang;
1528
+ }
1529
+ if (props.color) {
1530
+ result.color = props.color;
1531
+ }
1532
+ if (props.fontFamily) {
1533
+ result.fontFamily = props.fontFamily;
1534
+ }
1535
+ if (props.eastAsianFamily) {
1536
+ result.eastAsianFamily = props.eastAsianFamily;
1537
+ }
1538
+ if (props.complexScriptFamily) {
1539
+ result.complexScriptFamily = props.complexScriptFamily;
1540
+ }
1541
+ return result;
1542
+ }
1543
+ /**
1544
+ * Modify a property on an existing spPr (raw or structured).
1545
+ * Returns a new ShapeProperties object with the modification applied.
1546
+ */
1547
+ export function setSpPrFill(spPr, fill) {
1548
+ const parsed = spPr && isRawXml(spPr) ? parseSpPr(spPr) : (spPr ?? {});
1549
+ return buildSpPr({ ...parsed, fill });
1550
+ }
1551
+ /**
1552
+ * Modify line properties on an existing spPr.
1553
+ */
1554
+ export function setSpPrLine(spPr, line) {
1555
+ const parsed = spPr && isRawXml(spPr) ? parseSpPr(spPr) : (spPr ?? {});
1556
+ return buildSpPr({ ...parsed, line });
1557
+ }