@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,2125 @@
1
+ /**
2
+ * Chart / chartEx internal structure check.
3
+ *
4
+ * Classic charts (`xl/charts/chartN.xml`) must contain both `c:chart` and
5
+ * `c:plotArea`. ChartEx charts must contain `cx:chart`, `cx:plotArea`
6
+ * and at least one `cx:series`; series must carry `layoutId` and their
7
+ * `dataId`/`axisId` back-references must resolve inside the chart.
8
+ * `cx:externalData` nodes must refer to a declared relationship.
9
+ *
10
+ * In addition we catch five chartEx schema-violation patterns that
11
+ * cause Excel 2016+ to drop the whole chartEx part with "Removed Part:
12
+ * /xl/drawings/drawingN.xml (Drawing shape)":
13
+ *
14
+ * - `<cx:series>` with more than one `<cx:dataId>` child
15
+ * (`CT_Series/dataId` has `maxOccurs="1"`; multi-dim series must
16
+ * use a single `<cx:data>` wrapper with multiple strDim/numDim).
17
+ * - `<cx:axisId>N</cx:axisId>`, `<cx:dataId>N</cx:dataId>`,
18
+ * `<cx:binCount>N</cx:binCount>`, `<cx:binSize>N</cx:binSize>`
19
+ * emitted as text content instead of `val="N"` attribute. The
20
+ * underlying types are `CT_UnsignedInteger`/`CT_Double`, which
21
+ * Excel's strict loader only accepts via the attribute form.
22
+ * - `<cx:auto/>` element anywhere in the chartEx. Auto binning is
23
+ * expressed by the ABSENCE of `binSize`/`binCount`, not a
24
+ * dedicated `<cx:auto/>` tag. The tag is schema-invalid.
25
+ * - `<cx:paretoLine>` child of `<cx:layoutPr>`. Not in the
26
+ * CT_SeriesLayoutProperties schema. A real pareto chart adds a
27
+ * second series with `layoutId="paretoLine"`.
28
+ * - `<cx:title>` with a direct `<cx:layout>` child. Title layout
29
+ * belongs in `extLst`-based extensions.
30
+ */
31
+ import { attrByLocalName, collectDescendantsLocal, findChildLocal, findChildrenLocal, hasDescendantLocal, localName, matchesLocal } from "./xml-utils.js";
32
+ const CHART_PATH_RE = /^xl\/charts\/chart\d+\.xml$/;
33
+ const CHARTEX_PATH_RE = /^xl\/charts\/chartEx\d+\.xml$/;
34
+ export function checkChart(ctx) {
35
+ for (const [path, entry] of ctx.files()) {
36
+ if (ctx.reporter.capped) {
37
+ return;
38
+ }
39
+ if (entry.type === "directory") {
40
+ continue;
41
+ }
42
+ if (CHART_PATH_RE.test(path)) {
43
+ checkClassicChart(ctx, path);
44
+ }
45
+ else if (CHARTEX_PATH_RE.test(path)) {
46
+ checkChartEx(ctx, path);
47
+ }
48
+ }
49
+ }
50
+ function checkClassicChart(ctx, path) {
51
+ const dom = ctx.readDom(path);
52
+ if (!dom) {
53
+ return;
54
+ }
55
+ const root = dom.root;
56
+ if (!hasDescendantLocal(root, "chart")) {
57
+ ctx.reporter.error("chart-missing-chart", `${path}: missing c:chart`, path);
58
+ }
59
+ if (!hasDescendantLocal(root, "plotArea")) {
60
+ ctx.reporter.error("chart-missing-plotArea", `${path}: missing c:plotArea`, path);
61
+ }
62
+ // Schema-conformance pass: verifies child-element order, required
63
+ // child counts, enumerated attribute values and numeric ranges
64
+ // against ECMA-376 Part 1 §21.2.x / Microsoft OpenXML SDK
65
+ // ChildElementInfo. See the tables below.
66
+ checkClassicChartSchema(ctx, path, root);
67
+ }
68
+ const CT_CHART_TYPE_TAGS = [
69
+ "areaChart",
70
+ "area3DChart",
71
+ "lineChart",
72
+ "line3DChart",
73
+ "stockChart",
74
+ "radarChart",
75
+ "scatterChart",
76
+ "pieChart",
77
+ "pie3DChart",
78
+ "doughnutChart",
79
+ "barChart",
80
+ "bar3DChart",
81
+ "ofPieChart",
82
+ "surfaceChart",
83
+ "surface3DChart",
84
+ "bubbleChart"
85
+ ];
86
+ const CT_AXIS_TAGS = ["catAx", "valAx", "dateAx", "serAx"];
87
+ const CLASSIC_ORDER_RULES = [
88
+ // CT_ChartSpace (§21.2.2.29)
89
+ {
90
+ parent: "chartSpace",
91
+ order: [
92
+ "lang",
93
+ "roundedCorners",
94
+ "style",
95
+ "clrMapOvr",
96
+ "pivotSource",
97
+ "protection",
98
+ "chart",
99
+ "spPr",
100
+ "txPr",
101
+ "externalData",
102
+ "printSettings",
103
+ "userShapes",
104
+ "extLst"
105
+ ]
106
+ },
107
+ // CT_Chart (§21.2.2.27)
108
+ {
109
+ parent: "chart",
110
+ order: [
111
+ "title",
112
+ "autoTitleDeleted",
113
+ "pivotFmts",
114
+ "view3D",
115
+ "floor",
116
+ "sideWall",
117
+ "backWall",
118
+ "plotArea",
119
+ "legend",
120
+ "plotVisOnly",
121
+ "dispBlanksAs",
122
+ "showDLblsOverMax",
123
+ "extLst"
124
+ ]
125
+ },
126
+ // CT_PlotArea (§21.2.2.145). Two `<xsd:choice maxOccurs="unbounded">`
127
+ // groups — chart-type elements and axis elements — collapse into
128
+ // bucket placeholders.
129
+ {
130
+ parent: "plotArea",
131
+ order: ["layout", "__CHART_TYPES__", "__AXES__", "dTable", "spPr", "extLst"],
132
+ choiceGroups: [CT_CHART_TYPE_TAGS, CT_AXIS_TAGS]
133
+ },
134
+ // CT_DLbls (§21.2.2.49) — the biggest historical offender.
135
+ // Separator MUST come before showLeaderLines / leaderLines.
136
+ {
137
+ parent: "dLbls",
138
+ order: [
139
+ "dLbl",
140
+ "delete",
141
+ "numFmt",
142
+ "spPr",
143
+ "txPr",
144
+ "dLblPos",
145
+ "showLegendKey",
146
+ "showVal",
147
+ "showCatName",
148
+ "showSerName",
149
+ "showPercent",
150
+ "showBubbleSize",
151
+ "separator",
152
+ "showLeaderLines",
153
+ "leaderLines",
154
+ "extLst"
155
+ ]
156
+ },
157
+ // CT_DLbl (§21.2.2.47). The `delete` branch is mutually exclusive
158
+ // with the display-flag branch but we allow the tag here for
159
+ // ordering purposes; the choice violation is caught separately by
160
+ // `checkClassicDLblChoice` below.
161
+ {
162
+ parent: "dLbl",
163
+ order: [
164
+ "idx",
165
+ "delete",
166
+ "layout",
167
+ "tx",
168
+ "numFmt",
169
+ "spPr",
170
+ "txPr",
171
+ "dLblPos",
172
+ "showLegendKey",
173
+ "showVal",
174
+ "showCatName",
175
+ "showSerName",
176
+ "showPercent",
177
+ "showBubbleSize",
178
+ "separator",
179
+ "extLst"
180
+ ]
181
+ },
182
+ // CT_Scaling (§21.2.2.195). `max` precedes `min`.
183
+ { parent: "scaling", order: ["logBase", "orientation", "max", "min", "extLst"] },
184
+ // CT_CatAx (§21.2.2.25)
185
+ {
186
+ parent: "catAx",
187
+ order: [
188
+ "axId",
189
+ "scaling",
190
+ "delete",
191
+ "axPos",
192
+ "majorGridlines",
193
+ "minorGridlines",
194
+ "title",
195
+ "numFmt",
196
+ "majorTickMark",
197
+ "minorTickMark",
198
+ "tickLblPos",
199
+ "spPr",
200
+ "txPr",
201
+ "crossAx",
202
+ "crosses",
203
+ "crossesAt",
204
+ "auto",
205
+ "lblAlgn",
206
+ "lblOffset",
207
+ "tickLblSkip",
208
+ "tickMarkSkip",
209
+ "noMultiLvlLbl",
210
+ "extLst"
211
+ ]
212
+ },
213
+ // CT_ValAx (§21.2.2.226)
214
+ {
215
+ parent: "valAx",
216
+ order: [
217
+ "axId",
218
+ "scaling",
219
+ "delete",
220
+ "axPos",
221
+ "majorGridlines",
222
+ "minorGridlines",
223
+ "title",
224
+ "numFmt",
225
+ "majorTickMark",
226
+ "minorTickMark",
227
+ "tickLblPos",
228
+ "spPr",
229
+ "txPr",
230
+ "crossAx",
231
+ "crosses",
232
+ "crossesAt",
233
+ "crossBetween",
234
+ "majorUnit",
235
+ "minorUnit",
236
+ "dispUnits",
237
+ "extLst"
238
+ ]
239
+ },
240
+ // CT_DateAx (§21.2.2.39)
241
+ {
242
+ parent: "dateAx",
243
+ order: [
244
+ "axId",
245
+ "scaling",
246
+ "delete",
247
+ "axPos",
248
+ "majorGridlines",
249
+ "minorGridlines",
250
+ "title",
251
+ "numFmt",
252
+ "majorTickMark",
253
+ "minorTickMark",
254
+ "tickLblPos",
255
+ "spPr",
256
+ "txPr",
257
+ "crossAx",
258
+ "crosses",
259
+ "crossesAt",
260
+ "auto",
261
+ "lblOffset",
262
+ "baseTimeUnit",
263
+ "majorUnit",
264
+ "majorTimeUnit",
265
+ "minorUnit",
266
+ "minorTimeUnit",
267
+ "extLst"
268
+ ]
269
+ },
270
+ // CT_SerAx (§21.2.2.175)
271
+ {
272
+ parent: "serAx",
273
+ order: [
274
+ "axId",
275
+ "scaling",
276
+ "delete",
277
+ "axPos",
278
+ "majorGridlines",
279
+ "minorGridlines",
280
+ "title",
281
+ "numFmt",
282
+ "majorTickMark",
283
+ "minorTickMark",
284
+ "tickLblPos",
285
+ "spPr",
286
+ "txPr",
287
+ "crossAx",
288
+ "crosses",
289
+ "crossesAt",
290
+ "tickLblSkip",
291
+ "tickMarkSkip",
292
+ "extLst"
293
+ ]
294
+ },
295
+ // CT_Trendline (§21.2.2.211)
296
+ {
297
+ parent: "trendline",
298
+ order: [
299
+ "name",
300
+ "spPr",
301
+ "trendlineType",
302
+ "order",
303
+ "period",
304
+ "forward",
305
+ "backward",
306
+ "intercept",
307
+ "dispRSqr",
308
+ "dispEq",
309
+ "trendlineLbl",
310
+ "extLst"
311
+ ]
312
+ },
313
+ // CT_ErrBars (§21.2.2.55)
314
+ {
315
+ parent: "errBars",
316
+ order: [
317
+ "errDir",
318
+ "errBarType",
319
+ "errValType",
320
+ "noEndCap",
321
+ "plus",
322
+ "minus",
323
+ "val",
324
+ "spPr",
325
+ "extLst"
326
+ ]
327
+ },
328
+ // CT_View3D (§21.2.2.228)
329
+ {
330
+ parent: "view3D",
331
+ order: ["rotX", "hPercent", "rotY", "depthPercent", "rAngAx", "perspective", "extLst"]
332
+ },
333
+ // CT_Legend (§21.2.2.93)
334
+ {
335
+ parent: "legend",
336
+ order: ["legendPos", "legendEntry", "layout", "overlay", "spPr", "txPr", "extLst"]
337
+ },
338
+ // CT_Title (§21.2.2.210)
339
+ { parent: "title", order: ["tx", "layout", "overlay", "spPr", "txPr", "extLst"] },
340
+ // ---------------------------------------------------------------------------
341
+ // Chart-type elements (§21.2.2.4 — §21.2.2.198). Each plotArea
342
+ // child must list its children in the canonical sequence. Excel
343
+ // tolerates many mis-orderings but LibreOffice strict mode
344
+ // rejects them; third-party OOXML validators (Microsoft's SDK,
345
+ // Calligra, xmllint + XSD) refuse too.
346
+ // ---------------------------------------------------------------------------
347
+ // CT_AreaChart (§21.2.2.5)
348
+ {
349
+ parent: "areaChart",
350
+ order: ["grouping", "varyColors", "ser", "dLbls", "dropLines", "axId", "extLst"]
351
+ },
352
+ // CT_Area3DChart (§21.2.2.4)
353
+ {
354
+ parent: "area3DChart",
355
+ order: ["grouping", "varyColors", "ser", "dLbls", "dropLines", "gapDepth", "axId", "extLst"]
356
+ },
357
+ // CT_BarChart (§21.2.2.16)
358
+ {
359
+ parent: "barChart",
360
+ order: [
361
+ "barDir",
362
+ "grouping",
363
+ "varyColors",
364
+ "ser",
365
+ "dLbls",
366
+ "gapWidth",
367
+ "overlap",
368
+ "serLines",
369
+ "axId",
370
+ "extLst"
371
+ ]
372
+ },
373
+ // CT_Bar3DChart (§21.2.2.15)
374
+ {
375
+ parent: "bar3DChart",
376
+ order: [
377
+ "barDir",
378
+ "grouping",
379
+ "varyColors",
380
+ "ser",
381
+ "dLbls",
382
+ "gapWidth",
383
+ "gapDepth",
384
+ "shape",
385
+ "axId",
386
+ "extLst"
387
+ ]
388
+ },
389
+ // CT_LineChart (§21.2.2.97)
390
+ {
391
+ parent: "lineChart",
392
+ order: [
393
+ "grouping",
394
+ "varyColors",
395
+ "ser",
396
+ "dLbls",
397
+ "dropLines",
398
+ "hiLowLines",
399
+ "upDownBars",
400
+ "marker",
401
+ "smooth",
402
+ "axId",
403
+ "extLst"
404
+ ]
405
+ },
406
+ // CT_Line3DChart (§21.2.2.96)
407
+ {
408
+ parent: "line3DChart",
409
+ order: ["grouping", "varyColors", "ser", "dLbls", "dropLines", "gapDepth", "axId", "extLst"]
410
+ },
411
+ // CT_PieChart (§21.2.2.141)
412
+ { parent: "pieChart", order: ["varyColors", "ser", "dLbls", "firstSliceAng", "extLst"] },
413
+ // CT_Pie3DChart (§21.2.2.140) — no firstSliceAng, no holeSize.
414
+ { parent: "pie3DChart", order: ["varyColors", "ser", "dLbls", "extLst"] },
415
+ // CT_DoughnutChart (§21.2.2.50)
416
+ {
417
+ parent: "doughnutChart",
418
+ order: ["varyColors", "ser", "dLbls", "firstSliceAng", "holeSize", "extLst"]
419
+ },
420
+ // CT_OfPieChart (§21.2.2.126)
421
+ {
422
+ parent: "ofPieChart",
423
+ order: [
424
+ "ofPieType",
425
+ "varyColors",
426
+ "ser",
427
+ "dLbls",
428
+ "gapWidth",
429
+ "splitType",
430
+ "splitPos",
431
+ "custSplit",
432
+ "secondPieSize",
433
+ "serLines",
434
+ "extLst"
435
+ ]
436
+ },
437
+ // CT_ScatterChart (§21.2.2.161)
438
+ {
439
+ parent: "scatterChart",
440
+ order: ["scatterStyle", "varyColors", "ser", "dLbls", "axId", "extLst"]
441
+ },
442
+ // CT_BubbleChart (§21.2.2.20)
443
+ {
444
+ parent: "bubbleChart",
445
+ order: [
446
+ "varyColors",
447
+ "ser",
448
+ "dLbls",
449
+ "bubble3D",
450
+ "bubbleScale",
451
+ "showNegBubbles",
452
+ "sizeRepresents",
453
+ "axId",
454
+ "extLst"
455
+ ]
456
+ },
457
+ // CT_RadarChart (§21.2.2.153)
458
+ {
459
+ parent: "radarChart",
460
+ order: ["radarStyle", "varyColors", "ser", "dLbls", "axId", "extLst"]
461
+ },
462
+ // CT_StockChart (§21.2.2.198)
463
+ {
464
+ parent: "stockChart",
465
+ order: ["ser", "dLbls", "dropLines", "hiLowLines", "upDownBars", "axId", "extLst"]
466
+ },
467
+ // CT_SurfaceChart (§21.2.2.193) / CT_Surface3DChart
468
+ { parent: "surfaceChart", order: ["wireframe", "ser", "bandFmts", "axId", "extLst"] },
469
+ { parent: "surface3DChart", order: ["wireframe", "ser", "bandFmts", "axId", "extLst"] },
470
+ // ---------------------------------------------------------------------------
471
+ // Auxiliary complex types (§21.2.2.x). Sequences that appear
472
+ // throughout the chart graph — getting them out of order is a
473
+ // common bug source (and historically Excel tolerates it while
474
+ // LibreOffice strict refuses the file).
475
+ // ---------------------------------------------------------------------------
476
+ // CT_DPt (§21.2.2.52)
477
+ {
478
+ parent: "dPt",
479
+ order: [
480
+ "idx",
481
+ "invertIfNegative",
482
+ "marker",
483
+ "bubble3D",
484
+ "explosion",
485
+ "spPr",
486
+ "pictureOptions",
487
+ "extLst"
488
+ ]
489
+ },
490
+ // CT_Marker (§21.2.2.106)
491
+ { parent: "marker", order: ["symbol", "size", "spPr", "extLst"] },
492
+ // CT_UpDownBars (§21.2.2.218)
493
+ { parent: "upDownBars", order: ["gapWidth", "upBars", "downBars", "extLst"] },
494
+ // CT_NumRef / CT_StrRef / CT_MultiLvlStrRef (§21.2.2.121 / .189 / .113)
495
+ { parent: "numRef", order: ["f", "numCache", "extLst"] },
496
+ { parent: "strRef", order: ["f", "strCache", "extLst"] },
497
+ { parent: "multiLvlStrRef", order: ["f", "multiLvlStrCache", "extLst"] },
498
+ // CT_NumData / CT_StrData (§21.2.2.122 / .188)
499
+ { parent: "numCache", order: ["formatCode", "ptCount", "pt", "extLst"] },
500
+ { parent: "strCache", order: ["ptCount", "pt", "extLst"] },
501
+ { parent: "multiLvlStrCache", order: ["ptCount", "lvl", "extLst"] },
502
+ // CT_NumLit / CT_StrLit
503
+ { parent: "numLit", order: ["formatCode", "ptCount", "pt", "extLst"] },
504
+ { parent: "strLit", order: ["ptCount", "pt", "extLst"] },
505
+ // CT_Pt (§21.2.2.146): v element; idx is an attribute.
506
+ { parent: "pt", order: ["v"] },
507
+ // CT_Layout (§21.2.2.88) / CT_ManualLayout (§21.2.2.105)
508
+ { parent: "layout", order: ["manualLayout", "extLst"] },
509
+ {
510
+ parent: "manualLayout",
511
+ order: ["layoutTarget", "xMode", "yMode", "wMode", "hMode", "x", "y", "w", "h", "extLst"]
512
+ },
513
+ // CT_DTable (§21.2.2.54)
514
+ {
515
+ parent: "dTable",
516
+ order: ["showHorzBorder", "showVertBorder", "showOutline", "showKeys", "spPr", "txPr", "extLst"]
517
+ },
518
+ // CT_BandFormats (§21.2.2.12) / CT_BandFormat (§21.2.2.11)
519
+ { parent: "bandFmts", order: ["bandFmt"] },
520
+ { parent: "bandFmt", order: ["idx", "spPr"] },
521
+ // CT_TrendlineLbl (§21.2.2.212) — layout? tx? numFmt? spPr? txPr? extLst?
522
+ {
523
+ parent: "trendlineLbl",
524
+ order: ["layout", "tx", "numFmt", "spPr", "txPr", "extLst"]
525
+ },
526
+ // CT_PictureOptions (§21.2.2.144)
527
+ {
528
+ parent: "pictureOptions",
529
+ order: ["applyToFront", "applyToSides", "applyToEnd", "pictureFormat", "pictureStackUnit"]
530
+ }
531
+ ];
532
+ const SERIES_ORDER_RULES = [
533
+ // CT_BarSer (§21.2.2.17)
534
+ {
535
+ chartTypes: ["barChart", "bar3DChart"],
536
+ order: [
537
+ "idx",
538
+ "order",
539
+ "tx",
540
+ "spPr",
541
+ "invertIfNegative",
542
+ "pictureOptions",
543
+ "dPt",
544
+ "dLbls",
545
+ "trendline",
546
+ "errBars",
547
+ "cat",
548
+ "val",
549
+ "shape",
550
+ "extLst"
551
+ ]
552
+ },
553
+ // CT_LineSer (§21.2.2.99) — line3D uses same structure.
554
+ {
555
+ chartTypes: ["lineChart", "line3DChart", "stockChart"],
556
+ order: [
557
+ "idx",
558
+ "order",
559
+ "tx",
560
+ "spPr",
561
+ "marker",
562
+ "dPt",
563
+ "dLbls",
564
+ "trendline",
565
+ "errBars",
566
+ "cat",
567
+ "val",
568
+ "smooth",
569
+ "extLst"
570
+ ]
571
+ },
572
+ // CT_PieSer (§21.2.2.149) — pie / pie3D / doughnut / ofPie share.
573
+ {
574
+ chartTypes: ["pieChart", "pie3DChart", "doughnutChart", "ofPieChart"],
575
+ order: ["idx", "order", "tx", "spPr", "explosion", "dPt", "dLbls", "cat", "val", "extLst"]
576
+ },
577
+ // CT_AreaSer (§21.2.2.3)
578
+ {
579
+ chartTypes: ["areaChart", "area3DChart"],
580
+ order: [
581
+ "idx",
582
+ "order",
583
+ "tx",
584
+ "spPr",
585
+ "pictureOptions",
586
+ "dPt",
587
+ "dLbls",
588
+ "trendline",
589
+ "errBars",
590
+ "cat",
591
+ "val",
592
+ "extLst"
593
+ ]
594
+ },
595
+ // CT_ScatterSer (§21.2.2.167)
596
+ {
597
+ chartTypes: ["scatterChart"],
598
+ order: [
599
+ "idx",
600
+ "order",
601
+ "tx",
602
+ "spPr",
603
+ "marker",
604
+ "dPt",
605
+ "dLbls",
606
+ "trendline",
607
+ "errBars",
608
+ "xVal",
609
+ "yVal",
610
+ "smooth",
611
+ "extLst"
612
+ ]
613
+ },
614
+ // CT_BubbleSer (§21.2.2.19)
615
+ {
616
+ chartTypes: ["bubbleChart"],
617
+ order: [
618
+ "idx",
619
+ "order",
620
+ "tx",
621
+ "spPr",
622
+ "invertIfNegative",
623
+ "dPt",
624
+ "dLbls",
625
+ "trendline",
626
+ "errBars",
627
+ "xVal",
628
+ "yVal",
629
+ "bubbleSize",
630
+ "bubble3D",
631
+ "extLst"
632
+ ]
633
+ },
634
+ // CT_RadarSer (§21.2.2.153)
635
+ {
636
+ chartTypes: ["radarChart"],
637
+ order: ["idx", "order", "tx", "spPr", "marker", "dPt", "dLbls", "cat", "val", "extLst"]
638
+ },
639
+ // CT_SurfaceSer (§21.2.2.191)
640
+ {
641
+ chartTypes: ["surfaceChart", "surface3DChart"],
642
+ order: ["idx", "order", "tx", "spPr", "cat", "val", "extLst"]
643
+ }
644
+ ];
645
+ const CLASSIC_REQUIRED_CHILDREN = [
646
+ // Chart types that plot against a Cartesian coordinate system
647
+ // reference their axes by `c:axId`. 2-D variants need exactly two
648
+ // axis references, 3-D variants need three (X / Y / Z / series).
649
+ { parent: "barChart", child: "axId", min: 2, max: 2 },
650
+ { parent: "barChart", child: "barDir", min: 1, max: 1 },
651
+ { parent: "bar3DChart", child: "axId", min: 3, max: 3 },
652
+ { parent: "bar3DChart", child: "barDir", min: 1, max: 1 },
653
+ { parent: "lineChart", child: "axId", min: 2, max: 2 },
654
+ { parent: "lineChart", child: "grouping", min: 1, max: 1 },
655
+ { parent: "line3DChart", child: "axId", min: 3, max: 3 },
656
+ { parent: "line3DChart", child: "grouping", min: 1, max: 1 },
657
+ { parent: "areaChart", child: "axId", min: 2, max: 2 },
658
+ { parent: "area3DChart", child: "axId", min: 3, max: 3 },
659
+ { parent: "scatterChart", child: "axId", min: 2, max: 2 },
660
+ { parent: "scatterChart", child: "scatterStyle", min: 1, max: 1 },
661
+ { parent: "bubbleChart", child: "axId", min: 2, max: 2 },
662
+ { parent: "radarChart", child: "axId", min: 2, max: 2 },
663
+ { parent: "radarChart", child: "radarStyle", min: 1, max: 1 },
664
+ { parent: "stockChart", child: "axId", min: 2, max: 2 },
665
+ { parent: "surfaceChart", child: "axId", min: 3, max: 3 },
666
+ { parent: "surface3DChart", child: "axId", min: 3, max: 3 },
667
+ { parent: "ofPieChart", child: "ofPieType", min: 1, max: 1 },
668
+ // Axes require axId / scaling / axPos / crossAx.
669
+ { parent: "catAx", child: "axId", min: 1, max: 1 },
670
+ { parent: "catAx", child: "scaling", min: 1, max: 1 },
671
+ { parent: "catAx", child: "axPos", min: 1, max: 1 },
672
+ { parent: "catAx", child: "crossAx", min: 1, max: 1 },
673
+ { parent: "valAx", child: "axId", min: 1, max: 1 },
674
+ { parent: "valAx", child: "scaling", min: 1, max: 1 },
675
+ { parent: "valAx", child: "axPos", min: 1, max: 1 },
676
+ { parent: "valAx", child: "crossAx", min: 1, max: 1 },
677
+ { parent: "dateAx", child: "axId", min: 1, max: 1 },
678
+ { parent: "dateAx", child: "scaling", min: 1, max: 1 },
679
+ { parent: "dateAx", child: "axPos", min: 1, max: 1 },
680
+ { parent: "dateAx", child: "crossAx", min: 1, max: 1 },
681
+ { parent: "serAx", child: "axId", min: 1, max: 1 },
682
+ { parent: "serAx", child: "scaling", min: 1, max: 1 },
683
+ { parent: "serAx", child: "axPos", min: 1, max: 1 },
684
+ { parent: "serAx", child: "crossAx", min: 1, max: 1 },
685
+ // Every series carries idx + order.
686
+ { parent: "ser", child: "idx", min: 1, max: 1 },
687
+ { parent: "ser", child: "order", min: 1, max: 1 },
688
+ // Trendline / errBars / dPt / dLbl header attributes.
689
+ { parent: "trendline", child: "trendlineType", min: 1, max: 1 },
690
+ { parent: "errBars", child: "errBarType", min: 1, max: 1 },
691
+ { parent: "errBars", child: "errValType", min: 1, max: 1 },
692
+ { parent: "dPt", child: "idx", min: 1, max: 1 },
693
+ { parent: "dLbl", child: "idx", min: 1, max: 1 }
694
+ ];
695
+ const CLASSIC_ENUM_RULES = [
696
+ { element: "barDir", attr: "val", allowed: ["bar", "col"] },
697
+ {
698
+ element: "grouping",
699
+ attr: "val",
700
+ allowed: ["standard", "stacked", "percentStacked", "clustered"]
701
+ },
702
+ { element: "orientation", attr: "val", allowed: ["minMax", "maxMin"] },
703
+ { element: "ofPieType", attr: "val", allowed: ["pie", "bar"] },
704
+ {
705
+ element: "dLblPos",
706
+ attr: "val",
707
+ allowed: ["b", "bestFit", "ctr", "inBase", "inEnd", "l", "outEnd", "r", "t"]
708
+ },
709
+ { element: "legendPos", attr: "val", allowed: ["b", "l", "r", "t", "tr"] },
710
+ {
711
+ element: "scatterStyle",
712
+ attr: "val",
713
+ allowed: ["none", "line", "lineMarker", "marker", "smooth", "smoothMarker"]
714
+ },
715
+ { element: "radarStyle", attr: "val", allowed: ["standard", "marker", "filled"] },
716
+ { element: "dispBlanksAs", attr: "val", allowed: ["span", "gap", "zero"] },
717
+ { element: "splitType", attr: "val", allowed: ["auto", "cust", "percent", "pos", "val"] },
718
+ {
719
+ element: "shape",
720
+ attr: "val",
721
+ allowed: ["cone", "coneToMax", "box", "cylinder", "pyramid", "pyramidToMax"]
722
+ },
723
+ { element: "crosses", attr: "val", allowed: ["autoZero", "min", "max"] },
724
+ { element: "crossBetween", attr: "val", allowed: ["between", "midCat"] },
725
+ { element: "lblAlgn", attr: "val", allowed: ["ctr", "l", "r"] },
726
+ { element: "axPos", attr: "val", allowed: ["b", "l", "r", "t"] },
727
+ { element: "majorTickMark", attr: "val", allowed: ["cross", "in", "none", "out"] },
728
+ { element: "minorTickMark", attr: "val", allowed: ["cross", "in", "none", "out"] },
729
+ { element: "tickLblPos", attr: "val", allowed: ["high", "low", "nextTo", "none"] },
730
+ { element: "baseTimeUnit", attr: "val", allowed: ["days", "months", "years"] },
731
+ { element: "majorTimeUnit", attr: "val", allowed: ["days", "months", "years"] },
732
+ { element: "minorTimeUnit", attr: "val", allowed: ["days", "months", "years"] },
733
+ {
734
+ element: "trendlineType",
735
+ attr: "val",
736
+ allowed: ["exp", "linear", "log", "movingAvg", "poly", "power"]
737
+ },
738
+ { element: "errDir", attr: "val", allowed: ["x", "y"] },
739
+ { element: "errBarType", attr: "val", allowed: ["both", "minus", "plus"] },
740
+ {
741
+ element: "errValType",
742
+ attr: "val",
743
+ allowed: ["cust", "fixedVal", "percentage", "stdDev", "stdErr"]
744
+ },
745
+ {
746
+ element: "symbol",
747
+ attr: "val",
748
+ allowed: [
749
+ "auto",
750
+ "circle",
751
+ "dash",
752
+ "diamond",
753
+ "dot",
754
+ "none",
755
+ "picture",
756
+ "plus",
757
+ "square",
758
+ "star",
759
+ "triangle",
760
+ "x"
761
+ ]
762
+ },
763
+ { element: "sizeRepresents", attr: "val", allowed: ["area", "w"] },
764
+ // DrawingML theme-palette slots — `<a:schemeClr val>` must be one
765
+ // of the 17 canonical slot names per ECMA-376 §20.1.10.54
766
+ // (`ST_SchemeColorVal`). Typos here either inherit Excel's
767
+ // "Accent 1" default or strip the fill entirely depending on
768
+ // build.
769
+ {
770
+ element: "schemeClr",
771
+ attr: "val",
772
+ allowed: [
773
+ "bg1",
774
+ "bg2",
775
+ "tx1",
776
+ "tx2",
777
+ "accent1",
778
+ "accent2",
779
+ "accent3",
780
+ "accent4",
781
+ "accent5",
782
+ "accent6",
783
+ "hlink",
784
+ "folHlink",
785
+ "phClr",
786
+ "dk1",
787
+ "dk2",
788
+ "lt1",
789
+ "lt2"
790
+ ]
791
+ }
792
+ ];
793
+ const CLASSIC_RANGE_RULES = [
794
+ { element: "holeSize", attr: "val", min: 10, max: 90 },
795
+ { element: "firstSliceAng", attr: "val", min: 0, max: 360 },
796
+ { element: "overlap", attr: "val", min: -100, max: 100 },
797
+ { element: "gapWidth", attr: "val", min: 0, max: 500 },
798
+ { element: "gapDepth", attr: "val", min: 0, max: 500 },
799
+ { element: "rotX", attr: "val", min: -90, max: 90 },
800
+ { element: "rotY", attr: "val", min: 0, max: 360 },
801
+ { element: "perspective", attr: "val", min: 0, max: 240 },
802
+ { element: "hPercent", attr: "val", min: 5, max: 500 },
803
+ { element: "depthPercent", attr: "val", min: 20, max: 2000 },
804
+ { element: "bubbleScale", attr: "val", min: 0, max: 300 },
805
+ { element: "secondPieSize", attr: "val", min: 5, max: 200 },
806
+ // Axis units must be strictly positive. `Number.EPSILON` is a
807
+ // close-to-zero sentinel that rejects 0 and negatives while
808
+ // permitting the smallest finite positive a double can express.
809
+ { element: "majorUnit", attr: "val", min: Number.EPSILON, max: Number.MAX_VALUE },
810
+ { element: "minorUnit", attr: "val", min: Number.EPSILON, max: Number.MAX_VALUE },
811
+ // Tick-label / tick-mark skip: 1 = every tick, so >= 1 per schema
812
+ // (CT_Skip uses `xsd:unsignedInt` with a required minimum of 1).
813
+ { element: "tickLblSkip", attr: "val", min: 1, max: Number.MAX_SAFE_INTEGER },
814
+ { element: "tickMarkSkip", attr: "val", min: 1, max: Number.MAX_SAFE_INTEGER },
815
+ // DrawingML `<a:alpha val>` is CT_PositiveFixedPercentage
816
+ // (0 to 100000 representing 0% to 100%).
817
+ { element: "alpha", attr: "val", min: 0, max: 100000 }
818
+ ];
819
+ function checkClassicChartSchema(ctx, path, root) {
820
+ checkClassicChildOrder(ctx, path, root);
821
+ checkClassicRequiredChildren(ctx, path, root);
822
+ checkClassicEnumValues(ctx, path, root);
823
+ checkClassicNumericRanges(ctx, path, root);
824
+ checkClassicDLblChoice(ctx, path, root);
825
+ checkContextAwareChartRules(ctx, path, root);
826
+ checkDataReferenceStructure(ctx, path, root);
827
+ checkSeriesChildOrder(ctx, path, root);
828
+ checkAxIdResolution(ctx, path, root);
829
+ checkErrBarsConditionalChildren(ctx, path, root);
830
+ checkTxChoice(ctx, path, root);
831
+ checkSeriesChildWhitelist(ctx, path, root);
832
+ checkSrgbClrFormat(ctx, path, root);
833
+ checkNumFmtFormatCode(ctx, path, root);
834
+ checkRichStructure(ctx, path, root);
835
+ // Cross-part reference checks — these reach into `xl/theme/theme1.xml`
836
+ // and `xl/workbook.xml` via ctx.readDom (cached).
837
+ checkThemeSchemeColorSlots(ctx, path, root);
838
+ checkFormulaSyntax(ctx, path, root);
839
+ checkDefinedNameResolution(ctx, path, root);
840
+ }
841
+ function checkClassicChildOrder(ctx, path, root) {
842
+ for (const rule of CLASSIC_ORDER_RULES) {
843
+ for (const parent of collectDescendantsLocal(root, rule.parent)) {
844
+ if (ctx.reporter.capped) {
845
+ return;
846
+ }
847
+ const children = parent.children.filter(c => c.type === "element");
848
+ const rankOf = (tag) => {
849
+ if (rule.choiceGroups) {
850
+ for (let i = 0; i < rule.choiceGroups.length; i++) {
851
+ if (rule.choiceGroups[i].includes(tag)) {
852
+ // Every tag in the same choice group maps to the same
853
+ // virtual bucket ("__CHART_TYPES__" / "__AXES__") so
854
+ // they compare equal in sibling-order checks.
855
+ return rule.order.indexOf(`__${i === 0 ? "CHART_TYPES" : "AXES"}__`);
856
+ }
857
+ }
858
+ }
859
+ return rule.order.indexOf(tag);
860
+ };
861
+ let lastRank = -1;
862
+ let lastTag = "";
863
+ for (const child of children) {
864
+ const name = localName(child.name);
865
+ const rank = rankOf(name);
866
+ if (rank < 0) {
867
+ continue;
868
+ }
869
+ if (rank < lastRank) {
870
+ ctx.reporter.error("chart-child-out-of-order", `${path}: <c:${rule.parent}> child <c:${name}> appears after <c:${lastTag}> — ECMA-376 requires it before per CT_${capitalise(rule.parent)}.`, path);
871
+ }
872
+ if (rank >= lastRank) {
873
+ lastRank = rank;
874
+ lastTag = name;
875
+ }
876
+ }
877
+ }
878
+ }
879
+ }
880
+ function checkClassicRequiredChildren(ctx, path, root) {
881
+ for (const rule of CLASSIC_REQUIRED_CHILDREN) {
882
+ for (const parent of collectDescendantsLocal(root, rule.parent)) {
883
+ if (ctx.reporter.capped) {
884
+ return;
885
+ }
886
+ const n = findChildrenLocal(parent, rule.child).length;
887
+ if (n < rule.min) {
888
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:${rule.parent}> has ${n} <c:${rule.child}> child(ren); schema requires at least ${rule.min}.`, path);
889
+ }
890
+ if (rule.max !== undefined && n > rule.max) {
891
+ ctx.reporter.error("chart-wrong-child-count", `${path}: <c:${rule.parent}> has ${n} <c:${rule.child}> child(ren); schema permits at most ${rule.max}.`, path);
892
+ }
893
+ }
894
+ }
895
+ }
896
+ function checkClassicEnumValues(ctx, path, root) {
897
+ for (const rule of CLASSIC_ENUM_RULES) {
898
+ for (const el of collectDescendantsLocal(root, rule.element)) {
899
+ if (ctx.reporter.capped) {
900
+ return;
901
+ }
902
+ const val = attrByLocalName(el, rule.attr);
903
+ if (val === undefined) {
904
+ continue;
905
+ }
906
+ if (!rule.allowed.includes(val)) {
907
+ ctx.reporter.error("chart-invalid-enum-value", `${path}: <c:${rule.element} ${rule.attr}="${val}"> — ${val} is not in {${rule.allowed.join(", ")}}.`, path);
908
+ }
909
+ }
910
+ }
911
+ }
912
+ function checkClassicNumericRanges(ctx, path, root) {
913
+ for (const rule of CLASSIC_RANGE_RULES) {
914
+ for (const el of collectDescendantsLocal(root, rule.element)) {
915
+ if (ctx.reporter.capped) {
916
+ return;
917
+ }
918
+ const raw = attrByLocalName(el, rule.attr);
919
+ if (raw === undefined) {
920
+ continue;
921
+ }
922
+ const num = parseFloat(raw);
923
+ if (!Number.isFinite(num)) {
924
+ ctx.reporter.error("chart-value-out-of-range", `${path}: <c:${rule.element} ${rule.attr}="${raw}"> is not a finite number.`, path);
925
+ continue;
926
+ }
927
+ if (num < rule.min || num > rule.max) {
928
+ ctx.reporter.error("chart-value-out-of-range", `${path}: <c:${rule.element} ${rule.attr}="${num}"> outside [${rule.min}, ${rule.max}].`, path);
929
+ }
930
+ }
931
+ }
932
+ }
933
+ /**
934
+ * `CT_DLbl` is `idx, choice(delete | (layout, tx, numFmt, spPr,
935
+ * txPr, dLblPos, show*..., separator)), extLst?`. The two choice
936
+ * branches are mutually exclusive — emitting `delete` alongside
937
+ * any display-flag child is a schema violation that Excel's
938
+ * loader has been observed to handle inconsistently (some builds
939
+ * strip the label wholesale, others silently drop `delete`).
940
+ */
941
+ function checkClassicDLblChoice(ctx, path, root) {
942
+ const displayBranchTags = new Set([
943
+ "layout",
944
+ "tx",
945
+ "numFmt",
946
+ "spPr",
947
+ "txPr",
948
+ "dLblPos",
949
+ "showLegendKey",
950
+ "showVal",
951
+ "showCatName",
952
+ "showSerName",
953
+ "showPercent",
954
+ "showBubbleSize",
955
+ "separator"
956
+ ]);
957
+ for (const dLbl of collectDescendantsLocal(root, "dLbl")) {
958
+ if (ctx.reporter.capped) {
959
+ return;
960
+ }
961
+ const hasDelete = findChildLocal(dLbl, "delete") !== undefined;
962
+ if (!hasDelete) {
963
+ continue;
964
+ }
965
+ const conflictingChild = dLbl.children.find(c => c.type === "element" && displayBranchTags.has(localName(c.name)));
966
+ if (conflictingChild) {
967
+ ctx.reporter.error("chart-child-out-of-order", `${path}: <c:dLbl> has both <c:delete> and <c:${localName(conflictingChild.name)}>; CT_DLbl's choice group requires one branch or the other, never both.`, path);
968
+ }
969
+ }
970
+ }
971
+ function capitalise(s) {
972
+ return s.length === 0 ? s : s.charAt(0).toUpperCase() + s.slice(1);
973
+ }
974
+ // -----------------------------------------------------------------------------
975
+ // Context-aware rules — chart-type-specific restrictions that the
976
+ // generic schema tables above cannot express. Each rule scopes itself
977
+ // to one or more `c:*Chart` parents so the same child element gets
978
+ // validated differently based on where it lives.
979
+ // -----------------------------------------------------------------------------
980
+ /**
981
+ * Per-chart-type `c:dLblPos` allow-list. Although ECMA-376 `ST_DLblPos`
982
+ * permits all nine values globally, Excel's reader applies a stricter
983
+ * per-context filter that mirrors the "Label Position" picker in the
984
+ * Format Data Labels panel. Emitting a value outside the allow-list
985
+ * triggers "Repaired Records: Drawing" on open, and — for doughnut —
986
+ * causes the entire `drawing*.xml` part to be stripped.
987
+ *
988
+ * - `doughnut`: Excel's UI exposes no position choices at all; any
989
+ * `c:dLblPos` in a doughnut chart's `c:dLbls` causes the drawing
990
+ * part to be removed on open.
991
+ * - `bar` / `bar3D`: only the four "in/out/base/centre" positions.
992
+ * `inBase` is unique to bar and anchors the label to the axis end.
993
+ * - `line`, `line3D`, `scatter`, `bubble`, `radar`, `stock`: only the
994
+ * five cartesian positions (centre, above, below, left, right).
995
+ * - `pie`, `pie3D`, `ofPie`: the pie label set — bestFit is Excel's
996
+ * default and the only value that lets Excel place labels with
997
+ * automatic leader lines.
998
+ * - `area`, `area3D`: Excel only accepts `ctr` for area fills.
999
+ * - `surface`, `surface3D`: data labels are forbidden entirely (see
1000
+ * `FORBIDDEN_CHILDREN_BY_CHART_TYPE` below).
1001
+ */
1002
+ const VALID_DLBL_POSITIONS_BY_CHART_TYPE = {
1003
+ barChart: new Set(["ctr", "inBase", "inEnd", "outEnd"]),
1004
+ bar3DChart: new Set(["ctr", "inBase", "inEnd", "outEnd"]),
1005
+ lineChart: new Set(["ctr", "l", "r", "t", "b"]),
1006
+ line3DChart: new Set(["ctr", "l", "r", "t", "b"]),
1007
+ scatterChart: new Set(["ctr", "l", "r", "t", "b"]),
1008
+ bubbleChart: new Set(["ctr", "l", "r", "t", "b"]),
1009
+ radarChart: new Set(["ctr", "l", "r", "t", "b"]),
1010
+ stockChart: new Set(["ctr", "l", "r", "t", "b"]),
1011
+ pieChart: new Set(["bestFit", "ctr", "inEnd", "outEnd"]),
1012
+ pie3DChart: new Set(["bestFit", "ctr", "inEnd", "outEnd"]),
1013
+ ofPieChart: new Set(["bestFit", "ctr", "inEnd", "outEnd"]),
1014
+ doughnutChart: new Set(),
1015
+ areaChart: new Set(["ctr"]),
1016
+ area3DChart: new Set(["ctr"])
1017
+ };
1018
+ /**
1019
+ * `c:trendline` and `c:errBars` are forbidden inside pie-family
1020
+ * series (`CT_PieSer` has neither slot per schema). They are also
1021
+ * forbidden on surface series. Emitting one produces a series Excel
1022
+ * refuses to render. `c:dataLabels` is forbidden on surface series.
1023
+ */
1024
+ const FORBIDDEN_CHILDREN_BY_CHART_TYPE = {
1025
+ pieChart: new Set(["trendline", "errBars"]),
1026
+ pie3DChart: new Set(["trendline", "errBars"]),
1027
+ doughnutChart: new Set(["trendline", "errBars"]),
1028
+ ofPieChart: new Set(["trendline", "errBars"]),
1029
+ surfaceChart: new Set(["trendline", "errBars", "dLbls", "marker"]),
1030
+ surface3DChart: new Set(["trendline", "errBars", "dLbls", "marker"])
1031
+ };
1032
+ /**
1033
+ * `c:errBars` maxOccurs per series, per parent chart type.
1034
+ *
1035
+ * Scatter and bubble series use `CT_ScatterSer` / `CT_BubbleSer` whose
1036
+ * `errBars` element has `maxOccurs="2"` — one for direction `x`, one
1037
+ * for direction `y`. Every other series type caps at 1. Two entries
1038
+ * with the same `c:errDir` inside the same series are a schema
1039
+ * violation; Excel silently drops the duplicate (first one wins).
1040
+ */
1041
+ const ERRBARS_MAX_BY_CHART_TYPE = {
1042
+ scatterChart: 2,
1043
+ bubbleChart: 2,
1044
+ barChart: 1,
1045
+ bar3DChart: 1,
1046
+ lineChart: 1,
1047
+ line3DChart: 1,
1048
+ areaChart: 1,
1049
+ area3DChart: 1,
1050
+ radarChart: 1,
1051
+ stockChart: 1
1052
+ };
1053
+ /**
1054
+ * Required series count per chart type. `stockChart` needs 3 or 4
1055
+ * series (HLC or OHLC); everything else needs at least 1.
1056
+ */
1057
+ const SERIES_COUNT_BY_CHART_TYPE = {
1058
+ barChart: { min: 1 },
1059
+ bar3DChart: { min: 1 },
1060
+ lineChart: { min: 1 },
1061
+ line3DChart: { min: 1 },
1062
+ areaChart: { min: 1 },
1063
+ area3DChart: { min: 1 },
1064
+ scatterChart: { min: 1 },
1065
+ bubbleChart: { min: 1 },
1066
+ radarChart: { min: 1 },
1067
+ pieChart: { min: 1 },
1068
+ pie3DChart: { min: 1 },
1069
+ doughnutChart: { min: 1 },
1070
+ ofPieChart: { min: 1 },
1071
+ surfaceChart: { min: 1 },
1072
+ surface3DChart: { min: 1 },
1073
+ stockChart: { min: 3, max: 4 }
1074
+ };
1075
+ /**
1076
+ * Walk each chart-type group in the plot area and apply the
1077
+ * context-sensitive rules above:
1078
+ * - `c:dLblPos` value matches the allow-list for this type.
1079
+ * - `c:trendline` / `c:errBars` not present when forbidden.
1080
+ * - `c:errBars` cardinality + `c:errDir` uniqueness.
1081
+ * - Series count within the schema-permitted range.
1082
+ * - Series `c:idx` / `c:order` values unique inside the group.
1083
+ */
1084
+ function checkContextAwareChartRules(ctx, path, root) {
1085
+ for (const chartType of Object.keys(VALID_DLBL_POSITIONS_BY_CHART_TYPE)) {
1086
+ for (const group of collectDescendantsLocal(root, chartType)) {
1087
+ if (ctx.reporter.capped) {
1088
+ return;
1089
+ }
1090
+ checkDLblPosForChartType(ctx, path, group, chartType);
1091
+ checkForbiddenSeriesChildren(ctx, path, group, chartType);
1092
+ checkErrBarsCardinality(ctx, path, group, chartType);
1093
+ checkSeriesIdxOrderUnique(ctx, path, group, chartType);
1094
+ checkSeriesCount(ctx, path, group, chartType);
1095
+ }
1096
+ }
1097
+ // Surface / surface3D only participate in series-count + forbidden-
1098
+ // children checks — no dLblPos allow-list because Excel rejects
1099
+ // data labels on them wholesale.
1100
+ for (const chartType of ["surfaceChart", "surface3DChart"]) {
1101
+ for (const group of collectDescendantsLocal(root, chartType)) {
1102
+ if (ctx.reporter.capped) {
1103
+ return;
1104
+ }
1105
+ checkForbiddenSeriesChildren(ctx, path, group, chartType);
1106
+ checkSeriesCount(ctx, path, group, chartType);
1107
+ checkSeriesIdxOrderUnique(ctx, path, group, chartType);
1108
+ }
1109
+ }
1110
+ }
1111
+ function checkDLblPosForChartType(ctx, path, group, chartType) {
1112
+ const allowed = VALID_DLBL_POSITIONS_BY_CHART_TYPE[chartType];
1113
+ if (!allowed) {
1114
+ return;
1115
+ }
1116
+ for (const pos of collectDescendantsLocal(group, "dLblPos")) {
1117
+ if (ctx.reporter.capped) {
1118
+ return;
1119
+ }
1120
+ const val = attrByLocalName(pos, "val");
1121
+ if (val === undefined) {
1122
+ continue;
1123
+ }
1124
+ if (!allowed.has(val)) {
1125
+ const allowedList = allowed.size === 0
1126
+ ? "(none — this chart type does not accept c:dLblPos)"
1127
+ : [...allowed].sort().join(", ");
1128
+ ctx.reporter.error("chart-invalid-enum-value", `${path}: <c:dLblPos val="${val}"> inside <c:${chartType}> — Excel only accepts {${allowedList}} for this chart type.`, path);
1129
+ }
1130
+ }
1131
+ }
1132
+ function checkForbiddenSeriesChildren(ctx, path, group, chartType) {
1133
+ const forbidden = FORBIDDEN_CHILDREN_BY_CHART_TYPE[chartType];
1134
+ if (!forbidden || forbidden.size === 0) {
1135
+ return;
1136
+ }
1137
+ for (const series of findChildrenLocal(group, "ser")) {
1138
+ for (const child of series.children) {
1139
+ if (ctx.reporter.capped) {
1140
+ return;
1141
+ }
1142
+ if (child.type !== "element") {
1143
+ continue;
1144
+ }
1145
+ const name = localName(child.name);
1146
+ if (forbidden.has(name)) {
1147
+ ctx.reporter.error("chart-forbidden-child", `${path}: <c:ser> inside <c:${chartType}> contains <c:${name}>, which is not allowed for this chart type per ECMA-376.`, path);
1148
+ }
1149
+ }
1150
+ }
1151
+ // Surface charts forbid dLbls at the GROUP level too.
1152
+ if (forbidden.has("dLbls")) {
1153
+ for (const dLbls of findChildrenLocal(group, "dLbls")) {
1154
+ if (ctx.reporter.capped) {
1155
+ return;
1156
+ }
1157
+ void dLbls;
1158
+ ctx.reporter.error("chart-forbidden-child", `${path}: <c:${chartType}> contains group-level <c:dLbls>, which is not allowed for this chart type.`, path);
1159
+ }
1160
+ }
1161
+ }
1162
+ function checkErrBarsCardinality(ctx, path, group, chartType) {
1163
+ const max = ERRBARS_MAX_BY_CHART_TYPE[chartType];
1164
+ if (max === undefined) {
1165
+ return;
1166
+ }
1167
+ for (const series of findChildrenLocal(group, "ser")) {
1168
+ if (ctx.reporter.capped) {
1169
+ return;
1170
+ }
1171
+ const errBars = findChildrenLocal(series, "errBars");
1172
+ if (errBars.length > max) {
1173
+ ctx.reporter.error("chart-wrong-child-count", `${path}: <c:ser> inside <c:${chartType}> has ${errBars.length} <c:errBars> children; schema permits at most ${max}.`, path);
1174
+ }
1175
+ // When maxOccurs=2 (scatter/bubble), the two entries must carry
1176
+ // distinct `c:errDir` values.
1177
+ if (errBars.length === 2) {
1178
+ const dirs = errBars.map(eb => {
1179
+ const dirEl = findChildLocal(eb, "errDir");
1180
+ return dirEl ? attrByLocalName(dirEl, "val") : undefined;
1181
+ });
1182
+ if (dirs[0] !== undefined && dirs[1] !== undefined && dirs[0] === dirs[1]) {
1183
+ ctx.reporter.error("chart-duplicate-errBars-direction", `${path}: <c:ser> inside <c:${chartType}> has two <c:errBars> with the same <c:errDir val="${dirs[0]}"> — schema requires distinct directions (x + y).`, path);
1184
+ }
1185
+ }
1186
+ }
1187
+ }
1188
+ function checkSeriesIdxOrderUnique(ctx, path, group, chartType) {
1189
+ const series = findChildrenLocal(group, "ser");
1190
+ const seenIdx = new Set();
1191
+ const seenOrder = new Set();
1192
+ for (const s of series) {
1193
+ if (ctx.reporter.capped) {
1194
+ return;
1195
+ }
1196
+ const idxEl = findChildLocal(s, "idx");
1197
+ const orderEl = findChildLocal(s, "order");
1198
+ const idx = idxEl ? attrByLocalName(idxEl, "val") : undefined;
1199
+ const order = orderEl ? attrByLocalName(orderEl, "val") : undefined;
1200
+ if (idx !== undefined) {
1201
+ if (seenIdx.has(idx)) {
1202
+ ctx.reporter.error("chart-duplicate-series-idx", `${path}: <c:${chartType}> has two <c:ser> entries with <c:idx val="${idx}">; idx must be unique within a chart-type group.`, path);
1203
+ }
1204
+ seenIdx.add(idx);
1205
+ }
1206
+ if (order !== undefined) {
1207
+ if (seenOrder.has(order)) {
1208
+ ctx.reporter.error("chart-duplicate-series-order", `${path}: <c:${chartType}> has two <c:ser> entries with <c:order val="${order}">; order must be unique within a chart-type group.`, path);
1209
+ }
1210
+ seenOrder.add(order);
1211
+ }
1212
+ }
1213
+ }
1214
+ function checkSeriesCount(ctx, path, group, chartType) {
1215
+ const bounds = SERIES_COUNT_BY_CHART_TYPE[chartType];
1216
+ if (!bounds) {
1217
+ return;
1218
+ }
1219
+ const count = findChildrenLocal(group, "ser").length;
1220
+ if (count < bounds.min) {
1221
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:${chartType}> has ${count} <c:ser> children; schema requires at least ${bounds.min}${bounds.max !== undefined ? ` (and at most ${bounds.max})` : ""}.`, path);
1222
+ }
1223
+ if (bounds.max !== undefined && count > bounds.max) {
1224
+ ctx.reporter.error("chart-wrong-child-count", `${path}: <c:${chartType}> has ${count} <c:ser> children; schema permits at most ${bounds.max}.`, path);
1225
+ }
1226
+ }
1227
+ // -----------------------------------------------------------------------------
1228
+ // Data-reference structural checks — `c:numRef` / `c:strRef` /
1229
+ // `c:multiLvlStrRef` require `c:f`; their caches require `c:ptCount`;
1230
+ // every `c:pt` inside a cache needs `@idx` and a `c:v` child; `c:pt
1231
+ // idx` must stay inside the declared cache range.
1232
+ // -----------------------------------------------------------------------------
1233
+ const REF_ELEMENTS = ["numRef", "strRef", "multiLvlStrRef"];
1234
+ const LIT_ELEMENTS = ["numLit", "strLit"];
1235
+ const CACHE_ELEMENTS = ["numCache", "strCache", "multiLvlStrCache"];
1236
+ function checkDataReferenceStructure(ctx, path, root) {
1237
+ // `c:numRef`, `c:strRef`, `c:multiLvlStrRef` must carry `c:f`.
1238
+ for (const refName of REF_ELEMENTS) {
1239
+ for (const ref of collectDescendantsLocal(root, refName)) {
1240
+ if (ctx.reporter.capped) {
1241
+ return;
1242
+ }
1243
+ if (!findChildLocal(ref, "f")) {
1244
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:${refName}> is missing the required <c:f> formula child.`, path);
1245
+ }
1246
+ }
1247
+ }
1248
+ // `c:numLit` / `c:strLit` should carry `c:ptCount`.
1249
+ for (const litName of LIT_ELEMENTS) {
1250
+ for (const lit of collectDescendantsLocal(root, litName)) {
1251
+ if (ctx.reporter.capped) {
1252
+ return;
1253
+ }
1254
+ if (!findChildLocal(lit, "ptCount")) {
1255
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:${litName}> is missing the required <c:ptCount> child.`, path);
1256
+ }
1257
+ }
1258
+ }
1259
+ // Caches + `c:pt` integrity.
1260
+ for (const cacheName of CACHE_ELEMENTS) {
1261
+ for (const cache of collectDescendantsLocal(root, cacheName)) {
1262
+ if (ctx.reporter.capped) {
1263
+ return;
1264
+ }
1265
+ const ptCountEl = findChildLocal(cache, "ptCount");
1266
+ const ptCountVal = ptCountEl ? parseInt(attrByLocalName(ptCountEl, "val") ?? "", 10) : NaN;
1267
+ const points = findChildrenLocal(cache, "pt");
1268
+ for (const pt of points) {
1269
+ const idxRaw = attrByLocalName(pt, "idx");
1270
+ if (idxRaw === undefined) {
1271
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:pt> inside <c:${cacheName}> is missing the required idx attribute.`, path);
1272
+ continue;
1273
+ }
1274
+ const idx = parseInt(idxRaw, 10);
1275
+ if (Number.isFinite(ptCountVal) && (idx < 0 || idx >= ptCountVal)) {
1276
+ ctx.reporter.error("chart-pt-idx-out-of-range", `${path}: <c:pt idx="${idx}"> outside declared range [0, ${ptCountVal - 1}] (from <c:ptCount val="${ptCountVal}">).`, path);
1277
+ }
1278
+ // `numCache` / `strCache` points need a `c:v` child carrying
1279
+ // the cached value.
1280
+ if (cacheName !== "multiLvlStrCache" && !findChildLocal(pt, "v")) {
1281
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:pt idx="${idx}"> inside <c:${cacheName}> is missing the required <c:v> value child.`, path);
1282
+ }
1283
+ }
1284
+ }
1285
+ }
1286
+ }
1287
+ // -----------------------------------------------------------------------------
1288
+ // End of classic chart schema conformance
1289
+ // -----------------------------------------------------------------------------
1290
+ function checkChartEx(ctx, path) {
1291
+ const dom = ctx.readDom(path);
1292
+ if (!dom) {
1293
+ return;
1294
+ }
1295
+ const root = dom.root;
1296
+ if (!hasDescendantLocal(root, "chart")) {
1297
+ ctx.reporter.error("chartEx-missing-chart", `${path}: missing cx:chart`, path);
1298
+ }
1299
+ if (!hasDescendantLocal(root, "plotArea")) {
1300
+ ctx.reporter.error("chartEx-missing-plotArea", `${path}: missing cx:plotArea`, path);
1301
+ }
1302
+ const seriesList = collectDescendantsLocal(root, "series");
1303
+ if (seriesList.length === 0) {
1304
+ ctx.reporter.error("chartEx-missing-series", `${path}: missing cx:series`, path);
1305
+ return;
1306
+ }
1307
+ const dataIds = new Set(collectDescendantsLocal(root, "data")
1308
+ .map(el => parseInt(attrByLocalName(el, "id") ?? "", 10))
1309
+ .filter(Number.isFinite));
1310
+ const axisIds = new Set(collectDescendantsLocal(root, "axis")
1311
+ .map(el => parseInt(attrByLocalName(el, "id") ?? "", 10))
1312
+ .filter(Number.isFinite));
1313
+ for (const series of seriesList) {
1314
+ if (!attrByLocalName(series, "layoutId")) {
1315
+ ctx.reporter.error("chartEx-series-missing-layoutId", `${path}: cx:series missing layoutId`, path);
1316
+ }
1317
+ const dataIdChildren = findChildrenLocal(series, "dataId");
1318
+ // Schema cardinality: `CT_Series/dataId` has `maxOccurs="1"`.
1319
+ // Multi-dimensional series (box-whisker, sunburst, treemap) must
1320
+ // point at a single `<cx:data>` entry that holds every strDim /
1321
+ // numDim they need; emitting multiple dataIds tells Excel the
1322
+ // series references multiple data entries which is the "Removed
1323
+ // Part: drawingN.xml" trigger.
1324
+ if (dataIdChildren.length > 1) {
1325
+ ctx.reporter.error("chartEx-series-too-many-dataId", `${path}: cx:series has ${dataIdChildren.length} <cx:dataId> children; schema permits at most 1. ` +
1326
+ `Consolidate the referenced <cx:data> entries into a single entry.`, path);
1327
+ }
1328
+ for (const dataId of dataIdChildren) {
1329
+ const id = parseInt(attrByLocalName(dataId, "val") ?? "", 10);
1330
+ if (!dataIds.has(id)) {
1331
+ ctx.reporter.error("chartEx-series-missing-data-id", `${path}: cx:series references missing cx:data id ${attrByLocalName(dataId, "val")}`, path);
1332
+ }
1333
+ }
1334
+ for (const axisId of findChildrenLocal(series, "axisId")) {
1335
+ const id = parseInt(attrByLocalName(axisId, "val") ?? "", 10);
1336
+ if (!axisIds.has(id)) {
1337
+ ctx.reporter.error("chartEx-series-missing-axis-id", `${path}: cx:series references missing cx:axis id ${attrByLocalName(axisId, "val")}`, path);
1338
+ }
1339
+ }
1340
+ }
1341
+ // externalData (e.g. cx:externalData r:id="...") must resolve in the chart's rels.
1342
+ const externalDataRids = collectDescendantsLocal(root, "externalData")
1343
+ .map(el => attrByLocalName(el, "id"))
1344
+ .filter((id) => !!id);
1345
+ if (externalDataRids.length > 0) {
1346
+ const relsPath = chartRelsPath(path);
1347
+ const rels = ctx.readRels(relsPath);
1348
+ for (const rid of externalDataRids) {
1349
+ if (!rels.byId.has(rid)) {
1350
+ ctx.reporter.error("chartEx-externalData-missing-rel", `${path}: cx:externalData references missing relationship ${rid}`, path);
1351
+ }
1352
+ }
1353
+ }
1354
+ // Schema-conformance checks: text-form violations of typed elements,
1355
+ // invalid `<cx:auto/>` element, `<cx:paretoLine>` in layoutPr, and
1356
+ // direct `<cx:layout>` child of `<cx:title>`.
1357
+ checkTypedElementAttrForm(ctx, path, root);
1358
+ checkInvalidAutoElement(ctx, path, root);
1359
+ checkParetoLineInLayoutPr(ctx, path, root);
1360
+ checkTitleDirectLayoutChild(ctx, path, root);
1361
+ // Tier-2 semantic checks.
1362
+ checkAxisPosAndType(ctx, path, root);
1363
+ checkSeriesFDefinedName(ctx, path, root);
1364
+ checkWaterfallSubtotals(ctx, path, root);
1365
+ }
1366
+ /**
1367
+ * `<cx:axisId>`, `<cx:dataId>`, `<cx:binCount>`, `<cx:binSize>` and
1368
+ * their siblings use the `val="N"` attribute form. Earlier writer
1369
+ * revisions serialised them as text content (`<cx:axisId>2</cx:axisId>`),
1370
+ * which Excel's strict loader rejects. Flag every occurrence so the
1371
+ * output never regresses to the broken shape.
1372
+ */
1373
+ const TYPED_ATTR_ONLY_ELEMENTS = ["axisId", "dataId", "binCount", "binSize"];
1374
+ function checkTypedElementAttrForm(ctx, path, root) {
1375
+ for (const name of TYPED_ATTR_ONLY_ELEMENTS) {
1376
+ for (const el of collectDescendantsLocal(root, name)) {
1377
+ if (ctx.reporter.capped) {
1378
+ return;
1379
+ }
1380
+ const val = attrByLocalName(el, "val");
1381
+ const text = directTextContent(el).trim();
1382
+ // Missing `val` AND present non-empty text = the broken text-form.
1383
+ if (val === undefined && text.length > 0) {
1384
+ ctx.reporter.error("chartEx-typed-element-text-form", `${path}: <cx:${name}>${text}</cx:${name}> uses text-content form; schema requires val="${text}" attribute.`, path);
1385
+ }
1386
+ }
1387
+ }
1388
+ }
1389
+ /**
1390
+ * `<cx:auto/>` is NOT a valid element — auto binning is expressed by
1391
+ * the absence of both `binSize` and `binCount` inside `<cx:binning>`.
1392
+ * A literal `<cx:auto/>` tag anywhere in the chartEx makes Excel drop
1393
+ * the part on load.
1394
+ */
1395
+ function checkInvalidAutoElement(ctx, path, root) {
1396
+ for (const _el of collectDescendantsLocal(root, "auto")) {
1397
+ if (ctx.reporter.capped) {
1398
+ return;
1399
+ }
1400
+ ctx.reporter.error("chartEx-invalid-auto-element", `${path}: <cx:auto/> element is not in the chartEx schema. ` +
1401
+ `Auto binning is expressed by omitting both <cx:binSize> and <cx:binCount>.`, path);
1402
+ }
1403
+ }
1404
+ /**
1405
+ * `<cx:paretoLine>` is not a child of `<cx:layoutPr>` in the schema.
1406
+ * A real pareto chart expresses the line as a second `<cx:series>` with
1407
+ * `layoutId="paretoLine"`. The mis-placed child made earlier Excel
1408
+ * builds reject the chartEx.
1409
+ */
1410
+ function checkParetoLineInLayoutPr(ctx, path, root) {
1411
+ for (const lp of collectDescendantsLocal(root, "layoutPr")) {
1412
+ if (ctx.reporter.capped) {
1413
+ return;
1414
+ }
1415
+ const pl = findChildLocal(lp, "paretoLine");
1416
+ if (pl) {
1417
+ ctx.reporter.error("chartEx-paretoLine-in-layoutPr", `${path}: <cx:paretoLine> is not a valid child of <cx:layoutPr>. ` +
1418
+ `Add a second <cx:series layoutId="paretoLine"/> instead.`, path);
1419
+ }
1420
+ }
1421
+ }
1422
+ /**
1423
+ * `<cx:title><cx:layout/></cx:title>` is schema-invalid. Title layout
1424
+ * lives in `extLst`-based extensions or (in some clients) `<cx:offset>`
1425
+ * — never as a direct `<cx:layout>` child.
1426
+ */
1427
+ function checkTitleDirectLayoutChild(ctx, path, root) {
1428
+ for (const title of collectDescendantsLocal(root, "title")) {
1429
+ if (ctx.reporter.capped) {
1430
+ return;
1431
+ }
1432
+ const layout = findChildLocal(title, "layout");
1433
+ if (layout) {
1434
+ ctx.reporter.error("chartEx-title-direct-layout", `${path}: <cx:title> has a direct <cx:layout> child. Title layout ` +
1435
+ `information belongs in extLst-based extensions.`, path);
1436
+ }
1437
+ }
1438
+ }
1439
+ /**
1440
+ * Concatenate direct text/cdata children of an element, ignoring any
1441
+ * nested elements. Useful for "typed element with stray text content"
1442
+ * detection where a nested element's text should NOT count as the
1443
+ * offending text form.
1444
+ */
1445
+ function directTextContent(el) {
1446
+ let out = "";
1447
+ for (const child of el.children) {
1448
+ if (child.type === "text" || child.type === "cdata") {
1449
+ out += child.value;
1450
+ }
1451
+ }
1452
+ return out;
1453
+ }
1454
+ // -----------------------------------------------------------------------------
1455
+ // Tier-2 semantic checks
1456
+ // -----------------------------------------------------------------------------
1457
+ /**
1458
+ * `<cx:axis>` must declare its axis role — either via a structural
1459
+ * `<cx:catScaling>` / `<cx:valScaling>` CHILD element (the form Excel
1460
+ * itself emits; the role is inferred from which scaling child is
1461
+ * present) OR via legacy `pos` / `type` attributes. When NONE of
1462
+ * these are present, Excel's loader cannot disambiguate the axis
1463
+ * role and drops the whole `<cx:chartSpace>` on open, cascading
1464
+ * into "Removed Part: /xl/charts/chartExN.xml".
1465
+ *
1466
+ * Verified against Excel 2021's own output (`tmp/aaaaa.xlsx`,
1467
+ * `tmp/ttttt.xlsx`): every `<cx:axis>` it emits omits the
1468
+ * `pos` / `type` attributes and relies on the scaling child.
1469
+ */
1470
+ function checkAxisPosAndType(ctx, path, root) {
1471
+ for (const axis of collectDescendantsLocal(root, "axis")) {
1472
+ if (ctx.reporter.capped) {
1473
+ return;
1474
+ }
1475
+ const pos = attrByLocalName(axis, "pos");
1476
+ const type = attrByLocalName(axis, "type");
1477
+ const id = attrByLocalName(axis, "id") ?? "?";
1478
+ // Accept either legacy attribute form OR the schema-native
1479
+ // `<cx:catScaling>` / `<cx:valScaling>` child.
1480
+ const hasCatScaling = axis.children.some(c => c.type === "element" && matchesLocal(c.name, "catScaling"));
1481
+ const hasValScaling = axis.children.some(c => c.type === "element" && matchesLocal(c.name, "valScaling"));
1482
+ if (pos === undefined && type === undefined && !hasCatScaling && !hasValScaling) {
1483
+ ctx.reporter.error("chartEx-axis-missing-pos-and-type", `${path}: <cx:axis id="${id}"> has no role marker — emit either a ` +
1484
+ `<cx:catScaling>/<cx:valScaling> child (preferred, matches Excel) ` +
1485
+ `or a pos/type attribute. Excel's loader drops the chartEx otherwise.`, path);
1486
+ }
1487
+ }
1488
+ }
1489
+ /**
1490
+ * `<cx:f>` formulas must point at hidden defined names (the
1491
+ * `_xlchart.v1.0`, `_xlchart.v1.1`, … convention Excel itself uses),
1492
+ * NOT directly at worksheet ranges. A bare `<cx:f>Sheet1!$A$1:$A$3</cx:f>`
1493
+ * is rejected on open with "Removed Part: /xl/drawings/drawingN.xml".
1494
+ *
1495
+ * Detection heuristic: a formula body that contains `!$` or `!` followed
1496
+ * by absolute cell references is a direct sheet reference. Defined-name
1497
+ * references are bare identifiers like `_xlchart.v1.0` (no `!`).
1498
+ */
1499
+ function checkSeriesFDefinedName(ctx, path, root) {
1500
+ for (const f of collectDescendantsLocal(root, "f")) {
1501
+ if (ctx.reporter.capped) {
1502
+ return;
1503
+ }
1504
+ const formula = directTextContent(f).trim();
1505
+ if (formula === "") {
1506
+ continue;
1507
+ }
1508
+ // Heuristic for a direct sheet-qualified range:
1509
+ // - Contains "!" (sheet qualifier), AND
1510
+ // - Does NOT start with `_xl` or other defined-name prefix.
1511
+ if (!formula.includes("!")) {
1512
+ continue; // bare defined name like `_xlchart.v1.0`
1513
+ }
1514
+ if (formula.startsWith("_xlchart.") || formula.startsWith("_xlfn.")) {
1515
+ continue; // defined-name-qualified alias
1516
+ }
1517
+ // Looks like `Sheet1!$A$1:$A$3` or `'Some Name'!$A$1`.
1518
+ ctx.reporter.error("chartEx-f-uses-direct-range-not-defined-name", `${path}: <cx:f>${formula}</cx:f> points at a worksheet range directly. ` +
1519
+ `ChartEx requires an indirection through hidden defined names ` +
1520
+ `(e.g. _xlchart.v1.0) — otherwise Excel 2016+ drops the chartEx part on load.`, path);
1521
+ }
1522
+ }
1523
+ /**
1524
+ * Waterfall charts must have `layoutPr.subtotals` on their series —
1525
+ * even empty `<cx:subtotals/>` is meaningful: it marks the plot as
1526
+ * subtotals-aware. Without it Excel falls back to generic series
1527
+ * rendering and has been observed to reject the chartEx as malformed
1528
+ * at load time.
1529
+ */
1530
+ function checkWaterfallSubtotals(ctx, path, root) {
1531
+ for (const series of collectDescendantsLocal(root, "series")) {
1532
+ if (ctx.reporter.capped) {
1533
+ return;
1534
+ }
1535
+ const layoutId = attrByLocalName(series, "layoutId");
1536
+ if (layoutId !== "waterfall") {
1537
+ continue;
1538
+ }
1539
+ const layoutPr = findChildLocal(series, "layoutPr");
1540
+ const hasSubtotals = !!layoutPr && findChildLocal(layoutPr, "subtotals") !== undefined;
1541
+ if (!hasSubtotals) {
1542
+ ctx.reporter.error("chartEx-waterfall-missing-subtotals", `${path}: waterfall series has no <cx:layoutPr><cx:subtotals/> marker. ` +
1543
+ `Emit the element (even empty) so Excel renders the series as ` +
1544
+ `waterfall-aware instead of rejecting the chartEx.`, path);
1545
+ }
1546
+ }
1547
+ }
1548
+ // -----------------------------------------------------------------------------
1549
+ // Series child order — context-aware, since `c:ser` has a different
1550
+ // content model under each chart-type element (CT_BarSer, CT_LineSer,
1551
+ // CT_PieSer, CT_AreaSer, CT_ScatterSer, CT_BubbleSer, CT_RadarSer,
1552
+ // CT_SurfaceSer). See {@link SERIES_ORDER_RULES} for the table.
1553
+ // -----------------------------------------------------------------------------
1554
+ function checkSeriesChildOrder(ctx, path, root) {
1555
+ for (const rule of SERIES_ORDER_RULES) {
1556
+ for (const chartType of rule.chartTypes) {
1557
+ for (const group of collectDescendantsLocal(root, chartType)) {
1558
+ for (const series of findChildrenLocal(group, "ser")) {
1559
+ if (ctx.reporter.capped) {
1560
+ return;
1561
+ }
1562
+ const children = series.children.filter(c => c.type === "element");
1563
+ let lastRank = -1;
1564
+ let lastTag = "";
1565
+ for (const child of children) {
1566
+ const name = localName(child.name);
1567
+ const rank = rule.order.indexOf(name);
1568
+ if (rank < 0) {
1569
+ continue;
1570
+ }
1571
+ if (rank < lastRank) {
1572
+ ctx.reporter.error("chart-child-out-of-order", `${path}: <c:ser> inside <c:${chartType}> has <c:${name}> after <c:${lastTag}>; CT_${seriesTypeNameFor(chartType)}Ser requires <c:${name}> earlier in the sequence.`, path);
1573
+ }
1574
+ if (rank >= lastRank) {
1575
+ lastRank = rank;
1576
+ lastTag = name;
1577
+ }
1578
+ }
1579
+ }
1580
+ }
1581
+ }
1582
+ }
1583
+ }
1584
+ /** Map a chart-type tag to the series content-type short name. */
1585
+ function seriesTypeNameFor(chartType) {
1586
+ if (chartType.startsWith("bar")) {
1587
+ return "Bar";
1588
+ }
1589
+ if (chartType.startsWith("line") || chartType === "stockChart") {
1590
+ return "Line";
1591
+ }
1592
+ if (chartType.startsWith("pie") || chartType === "doughnutChart" || chartType === "ofPieChart") {
1593
+ return "Pie";
1594
+ }
1595
+ if (chartType.startsWith("area")) {
1596
+ return "Area";
1597
+ }
1598
+ if (chartType === "scatterChart") {
1599
+ return "Scatter";
1600
+ }
1601
+ if (chartType === "bubbleChart") {
1602
+ return "Bubble";
1603
+ }
1604
+ if (chartType === "radarChart") {
1605
+ return "Radar";
1606
+ }
1607
+ if (chartType.startsWith("surface")) {
1608
+ return "Surface";
1609
+ }
1610
+ return chartType;
1611
+ }
1612
+ // -----------------------------------------------------------------------------
1613
+ // axId cross-reference resolution — every `c:axId` inside a chart-type
1614
+ // element must match one of the axis `c:axId` values in the enclosing
1615
+ // plot area; every axis `c:crossAx` must reference another axis in
1616
+ // the same plot area. Unresolved references are schema-valid (they
1617
+ // parse) but produce charts Excel renders with phantom / missing
1618
+ // axes — a common symptom when combo charts are hand-edited.
1619
+ // -----------------------------------------------------------------------------
1620
+ const ALL_CHART_TYPE_NAMES = new Set(CT_CHART_TYPE_TAGS);
1621
+ const ALL_AXIS_NAMES = new Set(CT_AXIS_TAGS);
1622
+ function checkAxIdResolution(ctx, path, root) {
1623
+ for (const plotArea of collectDescendantsLocal(root, "plotArea")) {
1624
+ if (ctx.reporter.capped) {
1625
+ return;
1626
+ }
1627
+ // Gather every axis axId declared in this plot area.
1628
+ const axisIds = new Set();
1629
+ for (const child of plotArea.children) {
1630
+ if (child.type !== "element") {
1631
+ continue;
1632
+ }
1633
+ const name = localName(child.name);
1634
+ if (!ALL_AXIS_NAMES.has(name)) {
1635
+ continue;
1636
+ }
1637
+ const axIdEl = findChildLocal(child, "axId");
1638
+ const val = axIdEl ? attrByLocalName(axIdEl, "val") : undefined;
1639
+ if (val !== undefined) {
1640
+ axisIds.add(val);
1641
+ }
1642
+ }
1643
+ // Chart-type groups must reference an axis that exists.
1644
+ for (const child of plotArea.children) {
1645
+ if (child.type !== "element") {
1646
+ continue;
1647
+ }
1648
+ const name = localName(child.name);
1649
+ if (!ALL_CHART_TYPE_NAMES.has(name)) {
1650
+ continue;
1651
+ }
1652
+ for (const axIdEl of findChildrenLocal(child, "axId")) {
1653
+ const val = attrByLocalName(axIdEl, "val");
1654
+ if (val === undefined) {
1655
+ continue;
1656
+ }
1657
+ if (!axisIds.has(val)) {
1658
+ ctx.reporter.error("chart-axid-unresolved", `${path}: <c:${name}> references <c:axId val="${val}"> but no matching axis exists in the enclosing <c:plotArea>.`, path);
1659
+ }
1660
+ }
1661
+ }
1662
+ // Each axis's `crossAx` must resolve to another axis in the
1663
+ // same plot area.
1664
+ for (const child of plotArea.children) {
1665
+ if (child.type !== "element") {
1666
+ continue;
1667
+ }
1668
+ const name = localName(child.name);
1669
+ if (!ALL_AXIS_NAMES.has(name)) {
1670
+ continue;
1671
+ }
1672
+ const crossAxEl = findChildLocal(child, "crossAx");
1673
+ const val = crossAxEl ? attrByLocalName(crossAxEl, "val") : undefined;
1674
+ if (val !== undefined && !axisIds.has(val)) {
1675
+ ctx.reporter.error("chart-axid-unresolved", `${path}: <c:${name}> has <c:crossAx val="${val}"> but no matching axis exists in the enclosing <c:plotArea>.`, path);
1676
+ }
1677
+ }
1678
+ }
1679
+ }
1680
+ // -----------------------------------------------------------------------------
1681
+ // ErrBars conditional children — `c:val` is required when
1682
+ // `c:errValType` is NOT "cust", and forbidden when it IS. `c:plus`
1683
+ // and `c:minus` are required for custom error bars and forbidden
1684
+ // otherwise. stdErr allows `c:val` to be absent (Excel defaults to
1685
+ // 1) so we skip the required-child check for that type.
1686
+ // -----------------------------------------------------------------------------
1687
+ function checkErrBarsConditionalChildren(ctx, path, root) {
1688
+ for (const eb of collectDescendantsLocal(root, "errBars")) {
1689
+ if (ctx.reporter.capped) {
1690
+ return;
1691
+ }
1692
+ const typeEl = findChildLocal(eb, "errValType");
1693
+ const type = typeEl ? attrByLocalName(typeEl, "val") : undefined;
1694
+ const hasVal = findChildLocal(eb, "val") !== undefined;
1695
+ const hasPlus = findChildLocal(eb, "plus") !== undefined;
1696
+ const hasMinus = findChildLocal(eb, "minus") !== undefined;
1697
+ if (type === "cust") {
1698
+ if (!hasPlus || !hasMinus) {
1699
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:errBars> with <c:errValType val="cust"> requires both <c:plus> and <c:minus> children.`, path);
1700
+ }
1701
+ if (hasVal) {
1702
+ ctx.reporter.error("chart-forbidden-child", `${path}: <c:errBars> with <c:errValType val="cust"> must not contain <c:val>; use <c:plus> / <c:minus> for custom bounds.`, path);
1703
+ }
1704
+ }
1705
+ else if (type === "fixedVal" || type === "percentage" || type === "stdDev") {
1706
+ if (!hasVal) {
1707
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:errBars> with <c:errValType val="${type}"> requires a <c:val> child.`, path);
1708
+ }
1709
+ if (hasPlus || hasMinus) {
1710
+ ctx.reporter.error("chart-forbidden-child", `${path}: <c:errBars> with <c:errValType val="${type}"> must not contain <c:plus> or <c:minus> — those belong to "cust" only.`, path);
1711
+ }
1712
+ }
1713
+ // `stdErr` leaves `val` optional and disallows plus/minus — enforce
1714
+ // the disallowed side only.
1715
+ if (type === "stdErr" && (hasPlus || hasMinus)) {
1716
+ ctx.reporter.error("chart-forbidden-child", `${path}: <c:errBars> with <c:errValType val="stdErr"> must not contain <c:plus> or <c:minus>.`, path);
1717
+ }
1718
+ }
1719
+ }
1720
+ // -----------------------------------------------------------------------------
1721
+ // CT_Tx / CT_SerTx choice exclusivity — `c:tx` is
1722
+ // `choice(strRef | rich)` at chart / axis / legend-entry level and
1723
+ // `choice(strRef | v)` at series level. Having more than one branch
1724
+ // is a schema violation; Excel silently keeps the first and drops
1725
+ // the rest, so the feature authors intended gets lost on save.
1726
+ // -----------------------------------------------------------------------------
1727
+ function checkTxChoice(ctx, path, root) {
1728
+ for (const tx of collectDescendantsLocal(root, "tx")) {
1729
+ if (ctx.reporter.capped) {
1730
+ return;
1731
+ }
1732
+ const hasStrRef = findChildLocal(tx, "strRef") !== undefined;
1733
+ const hasRich = findChildLocal(tx, "rich") !== undefined;
1734
+ const hasV = findChildLocal(tx, "v") !== undefined;
1735
+ const branches = [hasStrRef, hasRich, hasV].filter(Boolean).length;
1736
+ // Zero branches is tolerated by Excel (auto-generated title / blank
1737
+ // series name) — we intentionally don't flag it to avoid noise on
1738
+ // round-tripped files. More than one branch is a real schema
1739
+ // violation.
1740
+ if (branches > 1) {
1741
+ ctx.reporter.error("chart-child-out-of-order", `${path}: <c:tx> must contain at most one of <c:strRef>, <c:rich>, or <c:v>; found ${branches} branches.`, path);
1742
+ }
1743
+ }
1744
+ }
1745
+ // -----------------------------------------------------------------------------
1746
+ // Series-child whitelist — every `c:ser` element may only contain
1747
+ // children declared in its per-chart-type CT_*Ser content model.
1748
+ // Elements from the global "known chart child" set that aren't
1749
+ // declared for this parent are schema violations even though the
1750
+ // tag name is otherwise valid OOXML. Catches e.g. `<c:bubbleSize>`
1751
+ // inside a `<c:barChart>` series, `<c:explosion>` inside a line
1752
+ // series, or `<c:smooth>` on a bar series.
1753
+ // -----------------------------------------------------------------------------
1754
+ /**
1755
+ * Union of every element name that appears in at least one
1756
+ * `SERIES_ORDER_RULES` entry. A series child inside this set that
1757
+ * isn't in the current chart type's allow-list is a schema
1758
+ * violation; a child outside this set is probably a vendor
1759
+ * extension we should leave alone.
1760
+ */
1761
+ const ALL_KNOWN_SERIES_CHILDREN = new Set(SERIES_ORDER_RULES.flatMap(r => r.order));
1762
+ function checkSeriesChildWhitelist(ctx, path, root) {
1763
+ for (const rule of SERIES_ORDER_RULES) {
1764
+ const allowed = new Set(rule.order);
1765
+ for (const chartType of rule.chartTypes) {
1766
+ for (const group of collectDescendantsLocal(root, chartType)) {
1767
+ for (const series of findChildrenLocal(group, "ser")) {
1768
+ if (ctx.reporter.capped) {
1769
+ return;
1770
+ }
1771
+ for (const child of series.children) {
1772
+ if (child.type !== "element") {
1773
+ continue;
1774
+ }
1775
+ const name = localName(child.name);
1776
+ if (!ALL_KNOWN_SERIES_CHILDREN.has(name)) {
1777
+ continue; // unknown tag — vendor extension, leave alone
1778
+ }
1779
+ if (!allowed.has(name)) {
1780
+ ctx.reporter.error("chart-forbidden-child", `${path}: <c:ser> inside <c:${chartType}> contains <c:${name}>, which is not in CT_${seriesTypeNameFor(chartType)}Ser's schema.`, path);
1781
+ }
1782
+ }
1783
+ }
1784
+ }
1785
+ }
1786
+ }
1787
+ }
1788
+ // -----------------------------------------------------------------------------
1789
+ // `<a:srgbClr val>` — CT_SRgbColor requires a 6-hex-digit value.
1790
+ // Excel reliably ignores malformed colours; callers pay the cost of
1791
+ // a silently-grey series. Matches uppercase and lowercase hex.
1792
+ // -----------------------------------------------------------------------------
1793
+ const SRGB_HEX_RE = /^[0-9A-Fa-f]{6}$/;
1794
+ function checkSrgbClrFormat(ctx, path, root) {
1795
+ for (const el of collectDescendantsLocal(root, "srgbClr")) {
1796
+ if (ctx.reporter.capped) {
1797
+ return;
1798
+ }
1799
+ const val = attrByLocalName(el, "val");
1800
+ if (val === undefined) {
1801
+ ctx.reporter.error("chart-missing-required-child", `${path}: <a:srgbClr> is missing the required val attribute.`, path);
1802
+ continue;
1803
+ }
1804
+ if (!SRGB_HEX_RE.test(val)) {
1805
+ ctx.reporter.error("chart-invalid-enum-value", `${path}: <a:srgbClr val="${val}"> must be a 6-digit hex colour (e.g. "4472C4").`, path);
1806
+ }
1807
+ }
1808
+ }
1809
+ // -----------------------------------------------------------------------------
1810
+ // `<c:numFmt formatCode>` is required by CT_NumFmt. The OOXML
1811
+ // serialiser always emits it, but round-tripped / hand-edited files
1812
+ // sometimes drop the attribute; Excel falls back to "General" and
1813
+ // loses the author's intended format.
1814
+ // -----------------------------------------------------------------------------
1815
+ function checkNumFmtFormatCode(ctx, path, root) {
1816
+ for (const el of collectDescendantsLocal(root, "numFmt")) {
1817
+ if (ctx.reporter.capped) {
1818
+ return;
1819
+ }
1820
+ const formatCode = attrByLocalName(el, "formatCode");
1821
+ if (formatCode === undefined) {
1822
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:numFmt> is missing the required formatCode attribute.`, path);
1823
+ }
1824
+ }
1825
+ }
1826
+ // -----------------------------------------------------------------------------
1827
+ // `<c:rich>` wraps a DrawingML `CT_TextBody`: required children are
1828
+ // `<a:bodyPr>` (first, exactly 1) and `<a:p>` (1+). The list style
1829
+ // `<a:lstStyle>` is optional and goes between them. Without
1830
+ // `<a:bodyPr>` or `<a:p>` Excel renders the title / label blank.
1831
+ // -----------------------------------------------------------------------------
1832
+ function checkRichStructure(ctx, path, root) {
1833
+ for (const rich of collectDescendantsLocal(root, "rich")) {
1834
+ if (ctx.reporter.capped) {
1835
+ return;
1836
+ }
1837
+ const hasBodyPr = findChildLocal(rich, "bodyPr") !== undefined;
1838
+ const paragraphs = findChildrenLocal(rich, "p").length;
1839
+ if (!hasBodyPr) {
1840
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:rich> is missing the required <a:bodyPr> child (CT_TextBody requires it first).`, path);
1841
+ }
1842
+ if (paragraphs === 0) {
1843
+ ctx.reporter.error("chart-missing-required-child", `${path}: <c:rich> has no <a:p> children; CT_TextBody requires at least one paragraph.`, path);
1844
+ }
1845
+ }
1846
+ }
1847
+ // -----------------------------------------------------------------------------
1848
+ // Cross-part references
1849
+ //
1850
+ // These checks leave the chart XML boundary and validate links
1851
+ // against sibling parts in the xlsx package:
1852
+ // - `<a:schemeClr val>` must reference a colour slot actually
1853
+ // declared in `xl/theme/theme1.xml`'s `<a:clrScheme>`.
1854
+ // - `<c:f>` formula bodies must parse as a valid cell reference,
1855
+ // range, or defined-name identifier.
1856
+ // - `<c:f>` defined-name references must resolve against
1857
+ // `xl/workbook.xml`'s `<definedNames>` or be a reserved
1858
+ // Excel-internal name (`_xlnm.*`, `_xlchart.*`, `_xlfn.*`).
1859
+ // -----------------------------------------------------------------------------
1860
+ /**
1861
+ * Theme's `<a:clrScheme>` declares twelve colour slots under the
1862
+ * short names `dk1, lt1, dk2, lt2, accent1..6, hlink, folHlink`. The
1863
+ * four workbook-facing aliases (`bg1, tx1, bg2, tx2`) resolve through
1864
+ * `<a:clrMap>` — the default Office map is `bg1=lt1, tx1=dk1,
1865
+ * bg2=lt2, tx2=dk2`. `phClr` is a run-time placeholder that's always
1866
+ * valid. Anything else is theme-missing.
1867
+ */
1868
+ const SCHEME_COLOR_ALIASES = {
1869
+ bg1: "lt1",
1870
+ tx1: "dk1",
1871
+ bg2: "lt2",
1872
+ tx2: "dk2"
1873
+ };
1874
+ function collectThemeColorSlots(ctx) {
1875
+ const dom = ctx.readDom("xl/theme/theme1.xml");
1876
+ if (!dom) {
1877
+ return undefined;
1878
+ }
1879
+ const clrScheme = findFirstDescendantLocal(dom.root, "clrScheme");
1880
+ if (!clrScheme) {
1881
+ return undefined;
1882
+ }
1883
+ const slots = new Set();
1884
+ for (const child of clrScheme.children) {
1885
+ if (child.type === "element") {
1886
+ slots.add(localName(child.name));
1887
+ }
1888
+ }
1889
+ return slots;
1890
+ }
1891
+ function findFirstDescendantLocal(root, local) {
1892
+ const hits = collectDescendantsLocal(root, local);
1893
+ return hits.length > 0 ? hits[0] : undefined;
1894
+ }
1895
+ function checkThemeSchemeColorSlots(ctx, path, root) {
1896
+ const slots = collectThemeColorSlots(ctx);
1897
+ // Skip silently when the theme is absent or doesn't declare a
1898
+ // `<a:clrScheme>`: either situation is flagged by the content-
1899
+ // types / relationships checkers and we'd just produce duplicate
1900
+ // noise here. We also skip when the slot set is empty — that
1901
+ // would reject every `schemeClr` reference as "missing" which
1902
+ // isn't the author's mistake.
1903
+ if (!slots || slots.size === 0) {
1904
+ return;
1905
+ }
1906
+ for (const el of collectDescendantsLocal(root, "schemeClr")) {
1907
+ if (ctx.reporter.capped) {
1908
+ return;
1909
+ }
1910
+ const val = attrByLocalName(el, "val");
1911
+ if (!val) {
1912
+ continue;
1913
+ }
1914
+ if (val === "phClr") {
1915
+ continue; // placeholder colour — always valid at run time
1916
+ }
1917
+ const resolved = SCHEME_COLOR_ALIASES[val] ?? val;
1918
+ if (!slots.has(resolved)) {
1919
+ ctx.reporter.error("chart-theme-missing-schemeClr-slot", `${path}: <a:schemeClr val="${val}"> references theme slot <a:${resolved}> which is not declared in xl/theme/theme1.xml's <a:clrScheme>.`, path);
1920
+ }
1921
+ }
1922
+ }
1923
+ /**
1924
+ * `<c:f>` bodies used by classic charts come in several flavours:
1925
+ * - `Sheet1!$A$1[:$B$2]` — qualified cell / range
1926
+ * - `'Quoted Sheet'!$A$1` — quoted sheet with spaces / specials
1927
+ * - `DefinedName` — bare defined-name identifier
1928
+ * - `Sheet1!LocalName` — sheet-qualified defined name
1929
+ * - `TableName[ColumnName]` — Excel structured reference
1930
+ * - `TableName[[#Headers],[Col]]` — structured ref with specifier
1931
+ * - `(f1,f2)` — multi-range (scatter / combo)
1932
+ * - `SUM(A1:A10)` — function call (rare but valid)
1933
+ * - `_xl*.*` — reserved Excel-internal prefix
1934
+ * (`_xlnm.Print_Area`, `_xlchart.v1.0`, `_xlfn.IFS`…)
1935
+ *
1936
+ * Full formula parsing would require the `@formula` tokenizer;
1937
+ * instead we apply a structural sanity check (balanced brackets /
1938
+ * parens / quotes, non-empty body) plus quick classification for
1939
+ * the two common forms that route into the defined-name resolver
1940
+ * (`bare identifier` and `Sheet!identifier`). Everything else is
1941
+ * assumed to be a valid complex expression — false-negatives here
1942
+ * are preferable to flagging legitimate structured references like
1943
+ * `Transactions[Revenue]`.
1944
+ */
1945
+ /** Cell or range reference like `A1`, `$A$1`, or `A1:B10`. */
1946
+ const A1_REF_RE = /^\$?[A-Z]+\$?\d+(?::\$?[A-Z]+\$?\d+)?$/;
1947
+ /** Unicode-aware identifier regex matching Excel defined-name rules. */
1948
+ const IDENTIFIER_RE = /^[A-Za-z_\\\u00C0-\uFFFF][A-Za-z0-9_.\\\u00C0-\uFFFF]*$/;
1949
+ /**
1950
+ * Balanced-bracket / paren / quote check — returns `false` when
1951
+ * the formula is syntactically broken (unclosed bracket, orphan
1952
+ * quote, etc.). Excel silently swallows such formulas on open; the
1953
+ * chart loses its backing data.
1954
+ */
1955
+ function isFormulaBalanced(body) {
1956
+ let parens = 0;
1957
+ let brackets = 0;
1958
+ let inQuote = false;
1959
+ for (let i = 0; i < body.length; i++) {
1960
+ const c = body[i];
1961
+ if (c === "'") {
1962
+ inQuote = !inQuote;
1963
+ continue;
1964
+ }
1965
+ if (inQuote) {
1966
+ continue;
1967
+ }
1968
+ if (c === "(") {
1969
+ parens++;
1970
+ }
1971
+ else if (c === ")") {
1972
+ parens--;
1973
+ }
1974
+ else if (c === "[") {
1975
+ brackets++;
1976
+ }
1977
+ else if (c === "]") {
1978
+ brackets--;
1979
+ }
1980
+ if (parens < 0 || brackets < 0) {
1981
+ return false;
1982
+ }
1983
+ }
1984
+ return parens === 0 && brackets === 0 && !inQuote;
1985
+ }
1986
+ function parseCFBody(raw) {
1987
+ let body = raw.trim();
1988
+ if (body.startsWith("=")) {
1989
+ body = body.substring(1).trim();
1990
+ }
1991
+ if (body === "") {
1992
+ return { kind: "invalid" };
1993
+ }
1994
+ if (!isFormulaBalanced(body)) {
1995
+ return { kind: "invalid" };
1996
+ }
1997
+ // `_xl`-prefixed names are reserved: `_xlnm.*`, `_xlchart.*`,
1998
+ // `_xlfn.*`. Always treat as valid without cross-reference.
1999
+ if (body.startsWith("_xl")) {
2000
+ return { kind: "special" };
2001
+ }
2002
+ // Expressions wrapped in parens cover multi-range references
2003
+ // (`(Sheet1!$A$1:$A$5,Sheet1!$C$1:$C$5)` on scatter / combo charts)
2004
+ // and function-call formulas (`SUM(A1:A10)`). The balanced-bracket
2005
+ // check above already caught unclosed parens; the full inner
2006
+ // grammar is out of scope for this schema check, so trust the
2007
+ // author and skip.
2008
+ if (body.startsWith("(")) {
2009
+ return { kind: "special" };
2010
+ }
2011
+ // Bare defined-name identifier (no punctuation, no !).
2012
+ if (IDENTIFIER_RE.test(body)) {
2013
+ return { kind: "name", name: body };
2014
+ }
2015
+ // Sheet-qualified form `Sheet!xxx`. Only classify as a defined-
2016
+ // name reference when the RHS is a pure identifier — structured
2017
+ // refs like `Table[Col]` or cell ranges like `$A$1:$B$10` route
2018
+ // through the generic "special" bucket so the defined-name check
2019
+ // skips them.
2020
+ const bangIdx = body.indexOf("!");
2021
+ if (bangIdx >= 0) {
2022
+ const sheet = body.substring(0, bangIdx);
2023
+ const ref = body.substring(bangIdx + 1);
2024
+ const sheetValid = (sheet.startsWith("'") && sheet.endsWith("'") && sheet.length >= 3) ||
2025
+ IDENTIFIER_RE.test(sheet);
2026
+ if (!sheetValid || ref === "") {
2027
+ return { kind: "invalid" };
2028
+ }
2029
+ if (A1_REF_RE.test(ref)) {
2030
+ return { kind: ref.includes(":") ? "range" : "cell" };
2031
+ }
2032
+ // Reserved `_xl*` names also appear sheet-qualified
2033
+ // (`Sheet1!_xlchart.v1.0`). Treat them as special regardless of
2034
+ // which side of the `!` they sit on.
2035
+ if (ref.startsWith("_xl")) {
2036
+ return { kind: "special" };
2037
+ }
2038
+ if (IDENTIFIER_RE.test(ref)) {
2039
+ return { kind: "name", name: ref };
2040
+ }
2041
+ // Anything else (structured table ref, function call, complex
2042
+ // expression) — assume valid, skip further validation.
2043
+ return { kind: "special" };
2044
+ }
2045
+ // Unqualified and not a bare identifier: could be a structured
2046
+ // reference (`Table[Col]`, `Table[#All]`) or an expression. Both
2047
+ // legal in `<c:f>`; accept without further validation.
2048
+ return { kind: "special" };
2049
+ }
2050
+ function extractTextContent(el) {
2051
+ let out = "";
2052
+ for (const child of el.children) {
2053
+ if (child.type === "text" || child.type === "cdata") {
2054
+ out += child.value;
2055
+ }
2056
+ }
2057
+ return out;
2058
+ }
2059
+ function checkFormulaSyntax(ctx, path, root) {
2060
+ for (const f of collectDescendantsLocal(root, "f")) {
2061
+ if (ctx.reporter.capped) {
2062
+ return;
2063
+ }
2064
+ const body = extractTextContent(f);
2065
+ const parsed = parseCFBody(body);
2066
+ if (parsed.kind === "invalid") {
2067
+ ctx.reporter.error("chart-f-invalid-syntax", `${path}: <c:f>${body}</c:f> is not a valid cell reference, range, or defined name.`, path);
2068
+ }
2069
+ }
2070
+ }
2071
+ /**
2072
+ * Collect every defined-name declared in `xl/workbook.xml`, plus the
2073
+ * well-known built-in reserved names that don't appear in the file
2074
+ * but Excel always recognises (`_xlnm.*` family).
2075
+ */
2076
+ function collectWorkbookDefinedNames(ctx) {
2077
+ const names = new Set();
2078
+ // Built-in reserved names Excel treats as always-defined.
2079
+ names.add("_xlnm.Print_Area");
2080
+ names.add("_xlnm.Print_Titles");
2081
+ names.add("_xlnm.Database");
2082
+ names.add("_xlnm.Criteria");
2083
+ names.add("_xlnm.Extract");
2084
+ names.add("_xlnm.Sheet_Title");
2085
+ names.add("_xlnm._FilterDatabase");
2086
+ names.add("_xlnm.Auto_Open");
2087
+ names.add("_xlnm.Auto_Close");
2088
+ const dom = ctx.readDom("xl/workbook.xml");
2089
+ if (!dom) {
2090
+ return names;
2091
+ }
2092
+ for (const dn of collectDescendantsLocal(dom.root, "definedName")) {
2093
+ const name = attrByLocalName(dn, "name");
2094
+ if (name) {
2095
+ names.add(name);
2096
+ }
2097
+ }
2098
+ return names;
2099
+ }
2100
+ function checkDefinedNameResolution(ctx, path, root) {
2101
+ let names;
2102
+ for (const f of collectDescendantsLocal(root, "f")) {
2103
+ if (ctx.reporter.capped) {
2104
+ return;
2105
+ }
2106
+ const body = extractTextContent(f);
2107
+ const parsed = parseCFBody(body);
2108
+ if (parsed.kind !== "name" || !parsed.name) {
2109
+ continue;
2110
+ }
2111
+ // Lazily load the workbook's defined names on first need.
2112
+ if (!names) {
2113
+ names = collectWorkbookDefinedNames(ctx);
2114
+ }
2115
+ if (!names.has(parsed.name)) {
2116
+ ctx.reporter.error("chart-f-undefined-name", `${path}: <c:f>${body}</c:f> references defined name "${parsed.name}" but no matching <definedName> exists in xl/workbook.xml.`, path);
2117
+ }
2118
+ }
2119
+ }
2120
+ function chartRelsPath(chartPath) {
2121
+ const slash = chartPath.lastIndexOf("/");
2122
+ const dir = slash >= 0 ? chartPath.slice(0, slash) : "";
2123
+ const name = slash >= 0 ? chartPath.slice(slash + 1) : chartPath;
2124
+ return dir ? `${dir}/_rels/${name}.rels` : `_rels/${name}.rels`;
2125
+ }