@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.
- package/dist/browser/index.browser.d.ts +8 -5
- package/dist/browser/index.browser.js +19 -1
- package/dist/browser/index.d.ts +4 -2
- package/dist/browser/index.js +9 -1
- package/dist/browser/modules/excel/chart/cache-populator.d.ts +49 -0
- package/dist/browser/modules/excel/chart/cache-populator.js +1171 -0
- package/dist/browser/modules/excel/chart/chart-api.d.ts +92 -0
- package/dist/browser/modules/excel/chart/chart-api.js +364 -0
- package/dist/browser/modules/excel/chart/chart-builder.d.ts +48 -0
- package/dist/browser/modules/excel/chart/chart-builder.js +2432 -0
- package/dist/browser/modules/excel/chart/chart-ex-builder.d.ts +36 -0
- package/dist/browser/modules/excel/chart/chart-ex-builder.js +903 -0
- package/dist/browser/modules/excel/chart/chart-ex-parser.d.ts +8 -0
- package/dist/browser/modules/excel/chart/chart-ex-parser.js +1205 -0
- package/dist/browser/modules/excel/chart/chart-ex-renderer.d.ts +187 -0
- package/dist/browser/modules/excel/chart/chart-ex-renderer.js +5352 -0
- package/dist/browser/modules/excel/chart/chart-ex-types.d.ts +531 -0
- package/dist/browser/modules/excel/chart/chart-ex-types.js +11 -0
- package/dist/browser/modules/excel/chart/chart-images.d.ts +78 -0
- package/dist/browser/modules/excel/chart/chart-images.js +363 -0
- package/dist/browser/modules/excel/chart/chart-presets.d.ts +392 -0
- package/dist/browser/modules/excel/chart/chart-presets.js +179 -0
- package/dist/browser/modules/excel/chart/chart-renderer.d.ts +550 -0
- package/dist/browser/modules/excel/chart/chart-renderer.js +6440 -0
- package/dist/browser/modules/excel/chart/chart-sidecar.d.ts +21 -0
- package/dist/browser/modules/excel/chart/chart-sidecar.js +427 -0
- package/dist/browser/modules/excel/chart/chart-utils.d.ts +306 -0
- package/dist/browser/modules/excel/chart/chart-utils.js +821 -0
- package/dist/browser/modules/excel/chart/chart.d.ts +504 -0
- package/dist/browser/modules/excel/chart/chart.js +1320 -0
- package/dist/browser/modules/excel/chart/glyph-rasterizer.d.ts +62 -0
- package/dist/browser/modules/excel/chart/glyph-rasterizer.js +658 -0
- package/dist/browser/modules/excel/chart/index.d.ts +54 -0
- package/dist/browser/modules/excel/chart/index.js +46 -0
- package/dist/browser/modules/excel/chart/install.d.ts +44 -0
- package/dist/browser/modules/excel/chart/install.js +91 -0
- package/dist/browser/modules/excel/chart/shape-properties.d.ts +156 -0
- package/dist/browser/modules/excel/chart/shape-properties.js +1557 -0
- package/dist/browser/modules/excel/chart/stroke-font.d.ts +36 -0
- package/dist/browser/modules/excel/chart/stroke-font.js +1556 -0
- package/dist/browser/modules/excel/chart/topojson.d.ts +98 -0
- package/dist/browser/modules/excel/chart/topojson.js +236 -0
- package/dist/browser/modules/excel/chart/types.d.ts +2559 -0
- package/dist/browser/modules/excel/chart/types.js +8 -0
- package/dist/browser/modules/excel/chart-host-registry.d.ts +157 -0
- package/dist/browser/modules/excel/chart-host-registry.js +90 -0
- package/dist/browser/modules/excel/chartsheet.d.ts +102 -0
- package/dist/browser/modules/excel/chartsheet.js +196 -0
- package/dist/browser/modules/excel/defined-names.d.ts +35 -0
- package/dist/browser/modules/excel/defined-names.js +44 -4
- package/dist/browser/modules/excel/errors.d.ts +6 -0
- package/dist/browser/modules/excel/errors.js +9 -0
- package/dist/browser/modules/excel/form-control.d.ts +6 -0
- package/dist/browser/modules/excel/form-control.js +17 -0
- package/dist/browser/modules/excel/image.js +12 -2
- package/dist/browser/modules/excel/pivot-chart.d.ts +7 -0
- package/dist/browser/modules/excel/pivot-chart.js +53 -0
- package/dist/browser/modules/excel/pivot-table.d.ts +55 -0
- package/dist/browser/modules/excel/pivot-table.js +35 -0
- package/dist/browser/modules/excel/range.js +5 -1
- package/dist/browser/modules/excel/sparkline/index.d.ts +7 -0
- package/dist/browser/modules/excel/sparkline/index.js +7 -0
- package/dist/browser/modules/excel/sparkline/sparkline.d.ts +206 -0
- package/dist/browser/modules/excel/sparkline/sparkline.js +750 -0
- package/dist/browser/modules/excel/stream/worksheet-writer.js +3 -2
- package/dist/browser/modules/excel/table.js +42 -6
- package/dist/browser/modules/excel/types.d.ts +72 -0
- package/dist/browser/modules/excel/utils/address.d.ts +18 -0
- package/dist/browser/modules/excel/utils/address.js +28 -0
- package/dist/browser/modules/excel/utils/drawing-utils.js +11 -6
- package/dist/browser/modules/excel/utils/guid.d.ts +15 -0
- package/dist/browser/modules/excel/utils/guid.js +35 -0
- package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +74 -0
- package/dist/browser/modules/excel/utils/ooxml-paths.js +206 -9
- package/dist/browser/modules/excel/utils/ooxml-validator/check-chart-sidecar.d.ts +35 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +101 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-chart.d.ts +32 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-chart.js +2125 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-chartsheet.d.ts +9 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-chartsheet.js +26 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-content-types.d.ts +16 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-content-types.js +181 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-drawing.d.ts +34 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-drawing.js +267 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-pivot.d.ts +14 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-pivot.js +104 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-relationships.d.ts +18 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-relationships.js +184 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-structure.d.ts +21 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-structure.js +56 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-styles.d.ts +15 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-styles.js +89 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-table.d.ts +31 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-table.js +177 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-workbook.d.ts +19 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-workbook.js +163 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-worksheet.d.ts +25 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/check-worksheet.js +569 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/context.d.ts +85 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/context.js +191 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/index.d.ts +31 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/index.js +102 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/path-utils.d.ts +67 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/path-utils.js +156 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/reporter.d.ts +41 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/reporter.js +61 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/types.d.ts +109 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/types.js +12 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/xml-utils.d.ts +38 -0
- package/dist/browser/modules/excel/utils/ooxml-validator/xml-utils.js +100 -0
- package/dist/browser/modules/excel/workbook.browser.d.ts +248 -30
- package/dist/browser/modules/excel/workbook.browser.js +966 -31
- package/dist/browser/modules/excel/workbook.d.ts +43 -0
- package/dist/browser/modules/excel/workbook.js +48 -0
- package/dist/browser/modules/excel/worksheet.d.ts +157 -3
- package/dist/browser/modules/excel/worksheet.js +394 -35
- package/dist/browser/modules/excel/xlsx/rel-type.d.ts +40 -0
- package/dist/browser/modules/excel/xlsx/rel-type.js +41 -1
- package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +1 -0
- package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
- package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
- package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
- package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.d.ts +353 -0
- package/dist/browser/modules/excel/xlsx/xform/chart/chart-space-xform.js +6000 -0
- package/dist/browser/modules/excel/xlsx/xform/comment/threaded-comments-xform.d.ts +60 -0
- package/dist/browser/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +213 -0
- package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +150 -11
- package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +30 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
- package/dist/browser/modules/excel/xlsx/xform/drawing/graphic-frame-xform.d.ts +54 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +225 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +3 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
- package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +46 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
- package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +13 -2
- package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
- package/dist/browser/modules/excel/xlsx/xform/sheet/chartsheet-xform.d.ts +185 -0
- package/dist/browser/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +441 -0
- package/dist/browser/modules/excel/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -0
- package/dist/browser/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +196 -20
- package/dist/browser/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
- package/dist/browser/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
- package/dist/browser/modules/excel/xlsx/xform/xsd-values.d.ts +63 -0
- package/dist/browser/modules/excel/xlsx/xform/xsd-values.js +101 -0
- package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +115 -21
- package/dist/browser/modules/excel/xlsx/xlsx.browser.js +4422 -78
- package/dist/browser/modules/pdf/builder/document-builder.d.ts +74 -0
- package/dist/browser/modules/pdf/builder/document-builder.js +507 -2
- package/dist/browser/modules/pdf/builder/pdf-editor.js +48 -3
- package/dist/browser/modules/pdf/excel-bridge.d.ts +69 -0
- package/dist/browser/modules/pdf/excel-bridge.js +683 -12
- package/dist/browser/modules/pdf/font/font-manager.d.ts +25 -0
- package/dist/browser/modules/pdf/font/font-manager.js +39 -0
- package/dist/browser/modules/pdf/index.d.ts +5 -2
- package/dist/browser/modules/pdf/index.js +3 -1
- package/dist/browser/modules/pdf/render/chart-surface.d.ts +33 -0
- package/dist/browser/modules/pdf/render/chart-surface.js +200 -0
- package/dist/browser/modules/pdf/render/layout-engine.d.ts +22 -1
- package/dist/browser/modules/pdf/render/layout-engine.js +436 -56
- package/dist/browser/modules/pdf/render/page-renderer.js +169 -28
- package/dist/browser/modules/pdf/render/pdf-exporter.js +117 -7
- package/dist/browser/modules/pdf/types.d.ts +227 -23
- package/dist/browser/modules/pdf/types.js +4 -0
- package/dist/browser/modules/pdf/word-bridge.d.ts +47 -0
- package/dist/browser/modules/pdf/word-bridge.js +304 -0
- package/dist/browser/modules/word/constants.d.ts +179 -0
- package/dist/browser/modules/word/constants.js +231 -0
- package/dist/browser/modules/word/content-types.d.ts +27 -0
- package/dist/browser/modules/word/content-types.js +53 -0
- package/dist/browser/modules/word/digital-signatures.d.ts +87 -0
- package/dist/browser/modules/word/digital-signatures.js +134 -0
- package/dist/browser/modules/word/document.d.ts +728 -0
- package/dist/browser/modules/word/document.js +1795 -0
- package/dist/browser/modules/word/docx-packager.d.ts +14 -0
- package/dist/browser/modules/word/docx-packager.js +822 -0
- package/dist/browser/modules/word/docx-reader.d.ts +11 -0
- package/dist/browser/modules/word/docx-reader.js +4929 -0
- package/dist/browser/modules/word/encryption.d.ts +102 -0
- package/dist/browser/modules/word/encryption.js +274 -0
- package/dist/browser/modules/word/errors.d.ts +49 -0
- package/dist/browser/modules/word/errors.js +68 -0
- package/dist/browser/modules/word/font-obfuscation.d.ts +31 -0
- package/dist/browser/modules/word/font-obfuscation.js +83 -0
- package/dist/browser/modules/word/html-renderer.d.ts +38 -0
- package/dist/browser/modules/word/html-renderer.js +782 -0
- package/dist/browser/modules/word/index.base.d.ts +19 -0
- package/dist/browser/modules/word/index.base.js +51 -0
- package/dist/browser/modules/word/index.browser.d.ts +4 -0
- package/dist/browser/modules/word/index.browser.js +4 -0
- package/dist/browser/modules/word/index.d.ts +4 -0
- package/dist/browser/modules/word/index.js +4 -0
- package/dist/browser/modules/word/internal-utils.d.ts +23 -0
- package/dist/browser/modules/word/internal-utils.js +54 -0
- package/dist/browser/modules/word/relationships.d.ts +31 -0
- package/dist/browser/modules/word/relationships.js +56 -0
- package/dist/browser/modules/word/types.d.ts +2325 -0
- package/dist/browser/modules/word/types.js +10 -0
- package/dist/browser/modules/word/units.d.ts +49 -0
- package/dist/browser/modules/word/units.js +111 -0
- package/dist/browser/modules/word/writers/chart-writer.d.ts +10 -0
- package/dist/browser/modules/word/writers/chart-writer.js +385 -0
- package/dist/browser/modules/word/writers/checkbox-writer.d.ts +9 -0
- package/dist/browser/modules/word/writers/checkbox-writer.js +42 -0
- package/dist/browser/modules/word/writers/comment-writer.d.ts +15 -0
- package/dist/browser/modules/word/writers/comment-writer.js +70 -0
- package/dist/browser/modules/word/writers/document-writer.d.ts +16 -0
- package/dist/browser/modules/word/writers/document-writer.js +461 -0
- package/dist/browser/modules/word/writers/footnote-writer.d.ts +11 -0
- package/dist/browser/modules/word/writers/footnote-writer.js +72 -0
- package/dist/browser/modules/word/writers/header-footer-writer.d.ts +13 -0
- package/dist/browser/modules/word/writers/header-footer-writer.js +129 -0
- package/dist/browser/modules/word/writers/image-writer.d.ts +10 -0
- package/dist/browser/modules/word/writers/image-writer.js +185 -0
- package/dist/browser/modules/word/writers/math-writer.d.ts +9 -0
- package/dist/browser/modules/word/writers/math-writer.js +428 -0
- package/dist/browser/modules/word/writers/numbering-writer.d.ts +10 -0
- package/dist/browser/modules/word/writers/numbering-writer.js +125 -0
- package/dist/browser/modules/word/writers/paragraph-writer.d.ts +13 -0
- package/dist/browser/modules/word/writers/paragraph-writer.js +516 -0
- package/dist/browser/modules/word/writers/parts-writer.d.ts +26 -0
- package/dist/browser/modules/word/writers/parts-writer.js +660 -0
- package/dist/browser/modules/word/writers/run-writer.d.ts +15 -0
- package/dist/browser/modules/word/writers/run-writer.js +649 -0
- package/dist/browser/modules/word/writers/section-writer.d.ts +10 -0
- package/dist/browser/modules/word/writers/section-writer.js +238 -0
- package/dist/browser/modules/word/writers/styles-writer.d.ts +10 -0
- package/dist/browser/modules/word/writers/styles-writer.js +242 -0
- package/dist/browser/modules/word/writers/table-writer.d.ts +10 -0
- package/dist/browser/modules/word/writers/table-writer.js +503 -0
- package/dist/browser/modules/word/writers/textbox-writer.d.ts +9 -0
- package/dist/browser/modules/word/writers/textbox-writer.js +53 -0
- package/dist/browser/modules/word/writers/toc-writer.d.ts +9 -0
- package/dist/browser/modules/word/writers/toc-writer.js +79 -0
- package/dist/browser/modules/xml/encode.d.ts +56 -7
- package/dist/browser/modules/xml/encode.js +157 -11
- package/dist/cjs/index.js +13 -2
- package/dist/cjs/modules/excel/chart/cache-populator.js +1178 -0
- package/dist/cjs/modules/excel/chart/chart-api.js +371 -0
- package/dist/cjs/modules/excel/chart/chart-builder.js +2440 -0
- package/dist/cjs/modules/excel/chart/chart-ex-builder.js +907 -0
- package/dist/cjs/modules/excel/chart/chart-ex-parser.js +1208 -0
- package/dist/cjs/modules/excel/chart/chart-ex-renderer.js +5364 -0
- package/dist/cjs/modules/excel/chart/chart-ex-types.js +12 -0
- package/dist/cjs/modules/excel/chart/chart-images.js +366 -0
- package/dist/cjs/modules/excel/chart/chart-presets.js +184 -0
- package/dist/cjs/modules/excel/chart/chart-renderer.js +6450 -0
- package/dist/cjs/modules/excel/chart/chart-sidecar.js +433 -0
- package/dist/cjs/modules/excel/chart/chart-utils.js +845 -0
- package/dist/cjs/modules/excel/chart/chart.js +1324 -0
- package/dist/cjs/modules/excel/chart/glyph-rasterizer.js +664 -0
- package/dist/cjs/modules/excel/chart/index.js +101 -0
- package/dist/cjs/modules/excel/chart/install.js +95 -0
- package/dist/cjs/modules/excel/chart/shape-properties.js +1577 -0
- package/dist/cjs/modules/excel/chart/stroke-font.js +1559 -0
- package/dist/cjs/modules/excel/chart/topojson.js +239 -0
- package/dist/cjs/modules/excel/chart/types.js +9 -0
- package/dist/cjs/modules/excel/chart-host-registry.js +96 -0
- package/dist/cjs/modules/excel/chartsheet.js +199 -0
- package/dist/cjs/modules/excel/defined-names.js +44 -4
- package/dist/cjs/modules/excel/errors.js +11 -1
- package/dist/cjs/modules/excel/form-control.js +17 -0
- package/dist/cjs/modules/excel/image.js +12 -2
- package/dist/cjs/modules/excel/pivot-chart.js +56 -0
- package/dist/cjs/modules/excel/pivot-table.js +35 -0
- package/dist/cjs/modules/excel/range.js +5 -1
- package/dist/cjs/modules/excel/sparkline/index.js +23 -0
- package/dist/cjs/modules/excel/sparkline/sparkline.js +756 -0
- package/dist/cjs/modules/excel/stream/worksheet-writer.js +3 -2
- package/dist/cjs/modules/excel/table.js +42 -6
- package/dist/cjs/modules/excel/utils/address.js +29 -0
- package/dist/cjs/modules/excel/utils/drawing-utils.js +11 -6
- package/dist/cjs/modules/excel/utils/guid.js +38 -0
- package/dist/cjs/modules/excel/utils/ooxml-paths.js +246 -9
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +103 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-chart.js +2128 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-chartsheet.js +29 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-content-types.js +184 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-drawing.js +270 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-pivot.js +107 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-relationships.js +188 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-structure.js +60 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-styles.js +92 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-table.js +180 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-workbook.js +166 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/check-worksheet.js +572 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/context.js +196 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/index.js +105 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/path-utils.js +168 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/reporter.js +66 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/types.js +13 -0
- package/dist/cjs/modules/excel/utils/ooxml-validator/xml-utils.js +110 -0
- package/dist/cjs/modules/excel/workbook.browser.js +973 -38
- package/dist/cjs/modules/excel/workbook.js +48 -0
- package/dist/cjs/modules/excel/worksheet.js +393 -34
- package/dist/cjs/modules/excel/xlsx/rel-type.js +41 -1
- package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
- package/dist/cjs/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
- package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
- package/dist/cjs/modules/excel/xlsx/xform/chart/chart-space-xform.js +6003 -0
- package/dist/cjs/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +219 -0
- package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +149 -10
- package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
- package/dist/cjs/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +228 -0
- package/dist/cjs/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
- package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
- package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
- package/dist/cjs/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +444 -0
- package/dist/cjs/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +195 -19
- package/dist/cjs/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
- package/dist/cjs/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
- package/dist/cjs/modules/excel/xlsx/xform/xsd-values.js +106 -0
- package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +4420 -76
- package/dist/cjs/modules/pdf/builder/document-builder.js +506 -1
- package/dist/cjs/modules/pdf/builder/pdf-editor.js +48 -3
- package/dist/cjs/modules/pdf/excel-bridge.js +684 -12
- package/dist/cjs/modules/pdf/font/font-manager.js +39 -0
- package/dist/cjs/modules/pdf/index.js +5 -1
- package/dist/cjs/modules/pdf/render/chart-surface.js +203 -0
- package/dist/cjs/modules/pdf/render/layout-engine.js +437 -56
- package/dist/cjs/modules/pdf/render/page-renderer.js +169 -28
- package/dist/cjs/modules/pdf/render/pdf-exporter.js +115 -5
- package/dist/cjs/modules/pdf/types.js +5 -0
- package/dist/cjs/modules/pdf/word-bridge.js +307 -0
- package/dist/cjs/modules/word/constants.js +234 -0
- package/dist/cjs/modules/word/content-types.js +57 -0
- package/dist/cjs/modules/word/digital-signatures.js +140 -0
- package/dist/cjs/modules/word/document.js +1909 -0
- package/dist/cjs/modules/word/docx-packager.js +825 -0
- package/dist/cjs/modules/word/docx-reader.js +4932 -0
- package/dist/cjs/modules/word/encryption.js +282 -0
- package/dist/cjs/modules/word/errors.js +88 -0
- package/dist/cjs/modules/word/font-obfuscation.js +88 -0
- package/dist/cjs/modules/word/html-renderer.js +785 -0
- package/dist/cjs/modules/word/index.base.js +199 -0
- package/dist/cjs/modules/word/index.browser.js +20 -0
- package/dist/cjs/modules/word/index.js +20 -0
- package/dist/cjs/modules/word/internal-utils.js +59 -0
- package/dist/cjs/modules/word/relationships.js +60 -0
- package/dist/cjs/modules/word/types.js +11 -0
- package/dist/cjs/modules/word/units.js +135 -0
- package/dist/cjs/modules/word/writers/chart-writer.js +388 -0
- package/dist/cjs/modules/word/writers/checkbox-writer.js +45 -0
- package/dist/cjs/modules/word/writers/comment-writer.js +74 -0
- package/dist/cjs/modules/word/writers/document-writer.js +465 -0
- package/dist/cjs/modules/word/writers/footnote-writer.js +76 -0
- package/dist/cjs/modules/word/writers/header-footer-writer.js +134 -0
- package/dist/cjs/modules/word/writers/image-writer.js +188 -0
- package/dist/cjs/modules/word/writers/math-writer.js +431 -0
- package/dist/cjs/modules/word/writers/numbering-writer.js +128 -0
- package/dist/cjs/modules/word/writers/paragraph-writer.js +521 -0
- package/dist/cjs/modules/word/writers/parts-writer.js +671 -0
- package/dist/cjs/modules/word/writers/run-writer.js +655 -0
- package/dist/cjs/modules/word/writers/section-writer.js +241 -0
- package/dist/cjs/modules/word/writers/styles-writer.js +245 -0
- package/dist/cjs/modules/word/writers/table-writer.js +506 -0
- package/dist/cjs/modules/word/writers/textbox-writer.js +56 -0
- package/dist/cjs/modules/word/writers/toc-writer.js +82 -0
- package/dist/cjs/modules/xml/encode.js +158 -11
- package/dist/esm/index.browser.js +20 -2
- package/dist/esm/index.js +9 -1
- package/dist/esm/modules/excel/chart/cache-populator.js +1171 -0
- package/dist/esm/modules/excel/chart/chart-api.js +364 -0
- package/dist/esm/modules/excel/chart/chart-builder.js +2432 -0
- package/dist/esm/modules/excel/chart/chart-ex-builder.js +903 -0
- package/dist/esm/modules/excel/chart/chart-ex-parser.js +1205 -0
- package/dist/esm/modules/excel/chart/chart-ex-renderer.js +5352 -0
- package/dist/esm/modules/excel/chart/chart-ex-types.js +11 -0
- package/dist/esm/modules/excel/chart/chart-images.js +363 -0
- package/dist/esm/modules/excel/chart/chart-presets.js +179 -0
- package/dist/esm/modules/excel/chart/chart-renderer.js +6440 -0
- package/dist/esm/modules/excel/chart/chart-sidecar.js +427 -0
- package/dist/esm/modules/excel/chart/chart-utils.js +821 -0
- package/dist/esm/modules/excel/chart/chart.js +1320 -0
- package/dist/esm/modules/excel/chart/glyph-rasterizer.js +658 -0
- package/dist/esm/modules/excel/chart/index.js +46 -0
- package/dist/esm/modules/excel/chart/install.js +91 -0
- package/dist/esm/modules/excel/chart/shape-properties.js +1557 -0
- package/dist/esm/modules/excel/chart/stroke-font.js +1556 -0
- package/dist/esm/modules/excel/chart/topojson.js +236 -0
- package/dist/esm/modules/excel/chart/types.js +8 -0
- package/dist/esm/modules/excel/chart-host-registry.js +90 -0
- package/dist/esm/modules/excel/chartsheet.js +196 -0
- package/dist/esm/modules/excel/defined-names.js +44 -4
- package/dist/esm/modules/excel/errors.js +9 -0
- package/dist/esm/modules/excel/form-control.js +17 -0
- package/dist/esm/modules/excel/image.js +12 -2
- package/dist/esm/modules/excel/pivot-chart.js +53 -0
- package/dist/esm/modules/excel/pivot-table.js +35 -0
- package/dist/esm/modules/excel/range.js +5 -1
- package/dist/esm/modules/excel/sparkline/index.js +7 -0
- package/dist/esm/modules/excel/sparkline/sparkline.js +750 -0
- package/dist/esm/modules/excel/stream/worksheet-writer.js +3 -2
- package/dist/esm/modules/excel/table.js +42 -6
- package/dist/esm/modules/excel/utils/address.js +28 -0
- package/dist/esm/modules/excel/utils/drawing-utils.js +11 -6
- package/dist/esm/modules/excel/utils/guid.js +35 -0
- package/dist/esm/modules/excel/utils/ooxml-paths.js +206 -9
- package/dist/esm/modules/excel/utils/ooxml-validator/check-chart-sidecar.js +101 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-chart.js +2125 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-chartsheet.js +26 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-content-types.js +181 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-drawing.js +267 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-pivot.js +104 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-relationships.js +184 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-structure.js +56 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-styles.js +89 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-table.js +177 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-workbook.js +163 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/check-worksheet.js +569 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/context.js +191 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/index.js +102 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/path-utils.js +156 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/reporter.js +61 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/types.js +12 -0
- package/dist/esm/modules/excel/utils/ooxml-validator/xml-utils.js +100 -0
- package/dist/esm/modules/excel/workbook.browser.js +969 -34
- package/dist/esm/modules/excel/workbook.js +48 -0
- package/dist/esm/modules/excel/worksheet.js +394 -35
- package/dist/esm/modules/excel/xlsx/rel-type.js +41 -1
- package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +11 -2
- package/dist/esm/modules/excel/xlsx/xform/book/external-link-xform.js +12 -10
- package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +96 -22
- package/dist/esm/modules/excel/xlsx/xform/chart/chart-space-xform.js +6000 -0
- package/dist/esm/modules/excel/xlsx/xform/comment/threaded-comments-xform.js +213 -0
- package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +150 -11
- package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +20 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +1 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/drawing-xform.js +109 -5
- package/dist/esm/modules/excel/xlsx/xform/drawing/graphic-frame-xform.js +225 -0
- package/dist/esm/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.js +18 -3
- package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +294 -12
- package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +32 -6
- package/dist/esm/modules/excel/xlsx/xform/sheet/chartsheet-xform.js +441 -0
- package/dist/esm/modules/excel/xlsx/xform/sheet/ext-lst-xform.js +51 -2
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +196 -20
- package/dist/esm/modules/excel/xlsx/xform/table/auto-filter-xform.js +16 -1
- package/dist/esm/modules/excel/xlsx/xform/table/table-column-xform.js +17 -2
- package/dist/esm/modules/excel/xlsx/xform/xsd-values.js +101 -0
- package/dist/esm/modules/excel/xlsx/xlsx.browser.js +4422 -78
- package/dist/esm/modules/pdf/builder/document-builder.js +507 -2
- package/dist/esm/modules/pdf/builder/pdf-editor.js +48 -3
- package/dist/esm/modules/pdf/excel-bridge.js +683 -12
- package/dist/esm/modules/pdf/font/font-manager.js +39 -0
- package/dist/esm/modules/pdf/index.js +3 -1
- package/dist/esm/modules/pdf/render/chart-surface.js +200 -0
- package/dist/esm/modules/pdf/render/layout-engine.js +436 -56
- package/dist/esm/modules/pdf/render/page-renderer.js +169 -28
- package/dist/esm/modules/pdf/render/pdf-exporter.js +117 -7
- package/dist/esm/modules/pdf/types.js +4 -0
- package/dist/esm/modules/pdf/word-bridge.js +304 -0
- package/dist/esm/modules/word/constants.js +231 -0
- package/dist/esm/modules/word/content-types.js +53 -0
- package/dist/esm/modules/word/digital-signatures.js +134 -0
- package/dist/esm/modules/word/document.js +1795 -0
- package/dist/esm/modules/word/docx-packager.js +822 -0
- package/dist/esm/modules/word/docx-reader.js +4929 -0
- package/dist/esm/modules/word/encryption.js +274 -0
- package/dist/esm/modules/word/errors.js +68 -0
- package/dist/esm/modules/word/font-obfuscation.js +83 -0
- package/dist/esm/modules/word/html-renderer.js +782 -0
- package/dist/esm/modules/word/index.base.js +51 -0
- package/dist/esm/modules/word/index.browser.js +4 -0
- package/dist/esm/modules/word/index.js +4 -0
- package/dist/esm/modules/word/internal-utils.js +54 -0
- package/dist/esm/modules/word/relationships.js +56 -0
- package/dist/esm/modules/word/types.js +10 -0
- package/dist/esm/modules/word/units.js +111 -0
- package/dist/esm/modules/word/writers/chart-writer.js +385 -0
- package/dist/esm/modules/word/writers/checkbox-writer.js +42 -0
- package/dist/esm/modules/word/writers/comment-writer.js +70 -0
- package/dist/esm/modules/word/writers/document-writer.js +461 -0
- package/dist/esm/modules/word/writers/footnote-writer.js +72 -0
- package/dist/esm/modules/word/writers/header-footer-writer.js +129 -0
- package/dist/esm/modules/word/writers/image-writer.js +185 -0
- package/dist/esm/modules/word/writers/math-writer.js +428 -0
- package/dist/esm/modules/word/writers/numbering-writer.js +125 -0
- package/dist/esm/modules/word/writers/paragraph-writer.js +516 -0
- package/dist/esm/modules/word/writers/parts-writer.js +660 -0
- package/dist/esm/modules/word/writers/run-writer.js +649 -0
- package/dist/esm/modules/word/writers/section-writer.js +238 -0
- package/dist/esm/modules/word/writers/styles-writer.js +242 -0
- package/dist/esm/modules/word/writers/table-writer.js +503 -0
- package/dist/esm/modules/word/writers/textbox-writer.js +53 -0
- package/dist/esm/modules/word/writers/toc-writer.js +79 -0
- package/dist/esm/modules/xml/encode.js +157 -11
- package/dist/iife/excelts.iife.js +11789 -687
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +52 -44
- package/dist/types/index.browser.d.ts +8 -5
- package/dist/types/index.d.ts +4 -2
- package/dist/types/modules/excel/chart/cache-populator.d.ts +49 -0
- package/dist/types/modules/excel/chart/chart-api.d.ts +92 -0
- package/dist/types/modules/excel/chart/chart-builder.d.ts +48 -0
- package/dist/types/modules/excel/chart/chart-ex-builder.d.ts +36 -0
- package/dist/types/modules/excel/chart/chart-ex-parser.d.ts +8 -0
- package/dist/types/modules/excel/chart/chart-ex-renderer.d.ts +187 -0
- package/dist/types/modules/excel/chart/chart-ex-types.d.ts +531 -0
- package/dist/types/modules/excel/chart/chart-images.d.ts +78 -0
- package/dist/types/modules/excel/chart/chart-presets.d.ts +392 -0
- package/dist/types/modules/excel/chart/chart-renderer.d.ts +550 -0
- package/dist/types/modules/excel/chart/chart-sidecar.d.ts +21 -0
- package/dist/types/modules/excel/chart/chart-utils.d.ts +306 -0
- package/dist/types/modules/excel/chart/chart.d.ts +504 -0
- package/dist/types/modules/excel/chart/glyph-rasterizer.d.ts +62 -0
- package/dist/types/modules/excel/chart/index.d.ts +54 -0
- package/dist/types/modules/excel/chart/install.d.ts +44 -0
- package/dist/types/modules/excel/chart/shape-properties.d.ts +156 -0
- package/dist/types/modules/excel/chart/stroke-font.d.ts +36 -0
- package/dist/types/modules/excel/chart/topojson.d.ts +98 -0
- package/dist/types/modules/excel/chart/types.d.ts +2559 -0
- package/dist/types/modules/excel/chart-host-registry.d.ts +157 -0
- package/dist/types/modules/excel/chartsheet.d.ts +102 -0
- package/dist/types/modules/excel/defined-names.d.ts +35 -0
- package/dist/types/modules/excel/errors.d.ts +6 -0
- package/dist/types/modules/excel/form-control.d.ts +6 -0
- package/dist/types/modules/excel/pivot-chart.d.ts +7 -0
- package/dist/types/modules/excel/pivot-table.d.ts +55 -0
- package/dist/types/modules/excel/sparkline/index.d.ts +7 -0
- package/dist/types/modules/excel/sparkline/sparkline.d.ts +206 -0
- package/dist/types/modules/excel/types.d.ts +72 -0
- package/dist/types/modules/excel/utils/address.d.ts +18 -0
- package/dist/types/modules/excel/utils/guid.d.ts +15 -0
- package/dist/types/modules/excel/utils/ooxml-paths.d.ts +74 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-chart-sidecar.d.ts +35 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-chart.d.ts +32 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-chartsheet.d.ts +9 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-content-types.d.ts +16 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-drawing.d.ts +34 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-pivot.d.ts +14 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-relationships.d.ts +18 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-structure.d.ts +21 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-styles.d.ts +15 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-table.d.ts +31 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-workbook.d.ts +19 -0
- package/dist/types/modules/excel/utils/ooxml-validator/check-worksheet.d.ts +25 -0
- package/dist/types/modules/excel/utils/ooxml-validator/context.d.ts +85 -0
- package/dist/types/modules/excel/utils/ooxml-validator/index.d.ts +31 -0
- package/dist/types/modules/excel/utils/ooxml-validator/path-utils.d.ts +67 -0
- package/dist/types/modules/excel/utils/ooxml-validator/reporter.d.ts +41 -0
- package/dist/types/modules/excel/utils/ooxml-validator/types.d.ts +109 -0
- package/dist/types/modules/excel/utils/ooxml-validator/xml-utils.d.ts +38 -0
- package/dist/types/modules/excel/workbook.browser.d.ts +248 -30
- package/dist/types/modules/excel/workbook.d.ts +43 -0
- package/dist/types/modules/excel/worksheet.d.ts +157 -3
- package/dist/types/modules/excel/xlsx/rel-type.d.ts +40 -0
- package/dist/types/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +1 -0
- package/dist/types/modules/excel/xlsx/xform/chart/chart-space-xform.d.ts +353 -0
- package/dist/types/modules/excel/xlsx/xform/comment/threaded-comments-xform.d.ts +60 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/drawing-xform.d.ts +30 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/graphic-frame-xform.d.ts +54 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/one-cell-anchor-xform.d.ts +3 -1
- package/dist/types/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +46 -0
- package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +13 -2
- package/dist/types/modules/excel/xlsx/xform/sheet/chartsheet-xform.d.ts +185 -0
- package/dist/types/modules/excel/xlsx/xform/sheet/ext-lst-xform.d.ts +1 -0
- package/dist/types/modules/excel/xlsx/xform/xsd-values.d.ts +63 -0
- package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +115 -21
- package/dist/types/modules/pdf/builder/document-builder.d.ts +74 -0
- package/dist/types/modules/pdf/excel-bridge.d.ts +69 -0
- package/dist/types/modules/pdf/font/font-manager.d.ts +25 -0
- package/dist/types/modules/pdf/index.d.ts +5 -2
- package/dist/types/modules/pdf/render/chart-surface.d.ts +33 -0
- package/dist/types/modules/pdf/render/layout-engine.d.ts +22 -1
- package/dist/types/modules/pdf/types.d.ts +227 -23
- package/dist/types/modules/pdf/word-bridge.d.ts +47 -0
- package/dist/types/modules/word/constants.d.ts +179 -0
- package/dist/types/modules/word/content-types.d.ts +27 -0
- package/dist/types/modules/word/digital-signatures.d.ts +87 -0
- package/dist/types/modules/word/document.d.ts +728 -0
- package/dist/types/modules/word/docx-packager.d.ts +14 -0
- package/dist/types/modules/word/docx-reader.d.ts +11 -0
- package/dist/types/modules/word/encryption.d.ts +102 -0
- package/dist/types/modules/word/errors.d.ts +49 -0
- package/dist/types/modules/word/font-obfuscation.d.ts +31 -0
- package/dist/types/modules/word/html-renderer.d.ts +38 -0
- package/dist/types/modules/word/index.base.d.ts +19 -0
- package/dist/types/modules/word/index.browser.d.ts +4 -0
- package/dist/types/modules/word/index.d.ts +4 -0
- package/dist/types/modules/word/internal-utils.d.ts +23 -0
- package/dist/types/modules/word/relationships.d.ts +31 -0
- package/dist/types/modules/word/types.d.ts +2325 -0
- package/dist/types/modules/word/units.d.ts +49 -0
- package/dist/types/modules/word/writers/chart-writer.d.ts +10 -0
- package/dist/types/modules/word/writers/checkbox-writer.d.ts +9 -0
- package/dist/types/modules/word/writers/comment-writer.d.ts +15 -0
- package/dist/types/modules/word/writers/document-writer.d.ts +16 -0
- package/dist/types/modules/word/writers/footnote-writer.d.ts +11 -0
- package/dist/types/modules/word/writers/header-footer-writer.d.ts +13 -0
- package/dist/types/modules/word/writers/image-writer.d.ts +10 -0
- package/dist/types/modules/word/writers/math-writer.d.ts +9 -0
- package/dist/types/modules/word/writers/numbering-writer.d.ts +10 -0
- package/dist/types/modules/word/writers/paragraph-writer.d.ts +13 -0
- package/dist/types/modules/word/writers/parts-writer.d.ts +26 -0
- package/dist/types/modules/word/writers/run-writer.d.ts +15 -0
- package/dist/types/modules/word/writers/section-writer.d.ts +10 -0
- package/dist/types/modules/word/writers/styles-writer.d.ts +10 -0
- package/dist/types/modules/word/writers/table-writer.d.ts +10 -0
- package/dist/types/modules/word/writers/textbox-writer.d.ts +9 -0
- package/dist/types/modules/word/writers/toc-writer.d.ts +9 -0
- package/dist/types/modules/xml/encode.d.ts +56 -7
- package/package.json +29 -11
- package/dist/browser/modules/excel/utils/ooxml-validator.d.ts +0 -48
- package/dist/browser/modules/excel/utils/ooxml-validator.js +0 -493
- package/dist/browser/modules/excel/utils/passthrough-manager.d.ts +0 -77
- package/dist/browser/modules/excel/utils/passthrough-manager.js +0 -129
- package/dist/cjs/modules/excel/utils/ooxml-validator.js +0 -499
- package/dist/cjs/modules/excel/utils/passthrough-manager.js +0 -133
- package/dist/esm/modules/excel/utils/ooxml-validator.js +0 -493
- package/dist/esm/modules/excel/utils/passthrough-manager.js +0 -129
- package/dist/types/modules/excel/utils/ooxml-validator.d.ts +0 -48
- package/dist/types/modules/excel/utils/passthrough-manager.d.ts +0 -77
|
@@ -0,0 +1,1205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort ChartEx parser for Office 2016+ cx: chart XML.
|
|
3
|
+
*
|
|
4
|
+
* The parser captures the structured fields that ExcelTS can render and keeps
|
|
5
|
+
* the original XML on the model so clean round-trips can still use raw bytes.
|
|
6
|
+
*/
|
|
7
|
+
import { parseXml, findChild, findChildren, textContent } from "../../xml/dom.js";
|
|
8
|
+
import { escapeXml, escapeXmlAttr } from "./chart-utils.js";
|
|
9
|
+
import { parseSpPr, parseTxPr } from "./shape-properties.js";
|
|
10
|
+
// Element-name whitelists for unknown-child detection. Parents not listed here
|
|
11
|
+
// are either (a) purely raw-passthrough containers already captured via
|
|
12
|
+
// `_rawXml` / `rawXml` / `extLst`, or (b) leaf elements whose content is
|
|
13
|
+
// attributes only. Update these lists when a new cx: element is promoted into
|
|
14
|
+
// the structured model so it stops being flagged as "unknown".
|
|
15
|
+
const KNOWN_CHILDREN_CHART_SPACE = new Set([
|
|
16
|
+
"cx:chartData",
|
|
17
|
+
"cx:chart",
|
|
18
|
+
"cx:clrMapOvr",
|
|
19
|
+
"cx:spPr",
|
|
20
|
+
"cx:txPr",
|
|
21
|
+
"cx:protection",
|
|
22
|
+
"cx:printSettings",
|
|
23
|
+
"cx:externalData",
|
|
24
|
+
"cx:extLst"
|
|
25
|
+
]);
|
|
26
|
+
const KNOWN_CHILDREN_CHART = new Set([
|
|
27
|
+
"cx:title",
|
|
28
|
+
"cx:autoTitleDeleted",
|
|
29
|
+
"cx:plotArea",
|
|
30
|
+
"cx:legend",
|
|
31
|
+
"cx:spPr",
|
|
32
|
+
"cx:extLst"
|
|
33
|
+
]);
|
|
34
|
+
const KNOWN_CHILDREN_PLOT_AREA = new Set([
|
|
35
|
+
"cx:plotAreaRegion",
|
|
36
|
+
"cx:series",
|
|
37
|
+
"cx:axis",
|
|
38
|
+
"cx:spPr",
|
|
39
|
+
"cx:extLst"
|
|
40
|
+
]);
|
|
41
|
+
const KNOWN_CHILDREN_PLOT_AREA_REGION = new Set([
|
|
42
|
+
"cx:layout",
|
|
43
|
+
"cx:plotSurface",
|
|
44
|
+
"cx:spPr",
|
|
45
|
+
"cx:series",
|
|
46
|
+
"cx:extLst"
|
|
47
|
+
]);
|
|
48
|
+
const KNOWN_CHILDREN_SERIES = new Set([
|
|
49
|
+
"cx:tx",
|
|
50
|
+
"cx:spPr",
|
|
51
|
+
"cx:txPr",
|
|
52
|
+
"cx:valueColors",
|
|
53
|
+
"cx:valueColorPositions",
|
|
54
|
+
"cx:dataPt",
|
|
55
|
+
"cx:dataLabels",
|
|
56
|
+
"cx:dataId",
|
|
57
|
+
"cx:layoutPr",
|
|
58
|
+
"cx:axisId",
|
|
59
|
+
"cx:extLst"
|
|
60
|
+
]);
|
|
61
|
+
const KNOWN_CHILDREN_AXIS = new Set([
|
|
62
|
+
"cx:catScaling",
|
|
63
|
+
"cx:valScaling",
|
|
64
|
+
// `cx:hidden`, `cx:majorTickMark`, and `cx:minorTickMark` were
|
|
65
|
+
// previously emitted by this library in violation of the Chart2014
|
|
66
|
+
// schema (hidden is an attribute; the element names are plural).
|
|
67
|
+
// Keep them in the known-children set so legacy files produced by
|
|
68
|
+
// older versions don't trip the `unknownElements` collector.
|
|
69
|
+
"cx:hidden",
|
|
70
|
+
"cx:majorTickMark",
|
|
71
|
+
"cx:majorTickMarks",
|
|
72
|
+
"cx:minorTickMark",
|
|
73
|
+
"cx:minorTickMarks",
|
|
74
|
+
"cx:numFmt",
|
|
75
|
+
"cx:title",
|
|
76
|
+
"cx:units",
|
|
77
|
+
"cx:majorGridlines",
|
|
78
|
+
"cx:minorGridlines",
|
|
79
|
+
"cx:spPr",
|
|
80
|
+
"cx:txPr",
|
|
81
|
+
"cx:extLst"
|
|
82
|
+
]);
|
|
83
|
+
function collectUnknownChildren(parent, knownNames, parentPath, collector) {
|
|
84
|
+
if (!parent) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
for (const child of parent.children ?? []) {
|
|
88
|
+
if (child.type !== "element") {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (!knownNames.has(child.name)) {
|
|
92
|
+
collector.entries.push({
|
|
93
|
+
name: child.name,
|
|
94
|
+
path: `${parentPath}/${child.name}`
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function parseChartEx(rawXml) {
|
|
100
|
+
const root = parseXml(rawXml).root;
|
|
101
|
+
const chartDataEl = findChild(root, "cx:chartData");
|
|
102
|
+
const chartEl = findChild(root, "cx:chart");
|
|
103
|
+
const collector = { entries: [] };
|
|
104
|
+
collectUnknownChildren(root, KNOWN_CHILDREN_CHART_SPACE, "cx:chartSpace", collector);
|
|
105
|
+
if (chartEl) {
|
|
106
|
+
collectUnknownChildren(chartEl, KNOWN_CHILDREN_CHART, "cx:chartSpace/cx:chart", collector);
|
|
107
|
+
const plotAreaEl = findChild(chartEl, "cx:plotArea");
|
|
108
|
+
if (plotAreaEl) {
|
|
109
|
+
collectUnknownChildren(plotAreaEl, KNOWN_CHILDREN_PLOT_AREA, "cx:chartSpace/cx:chart/cx:plotArea", collector);
|
|
110
|
+
const regionEl = findChild(plotAreaEl, "cx:plotAreaRegion");
|
|
111
|
+
if (regionEl) {
|
|
112
|
+
collectUnknownChildren(regionEl, KNOWN_CHILDREN_PLOT_AREA_REGION, "cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion", collector);
|
|
113
|
+
for (const seriesEl of findChildren(regionEl, "cx:series")) {
|
|
114
|
+
collectUnknownChildren(seriesEl, KNOWN_CHILDREN_SERIES, "cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series", collector);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (const seriesEl of findChildren(plotAreaEl, "cx:series")) {
|
|
118
|
+
collectUnknownChildren(seriesEl, KNOWN_CHILDREN_SERIES, "cx:chartSpace/cx:chart/cx:plotArea/cx:series", collector);
|
|
119
|
+
}
|
|
120
|
+
for (const axisEl of findChildren(plotAreaEl, "cx:axis")) {
|
|
121
|
+
collectUnknownChildren(axisEl, KNOWN_CHILDREN_AXIS, "cx:chartSpace/cx:chart/cx:plotArea/cx:axis", collector);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// `CT_Chart` has no `spPr` child in Chart2014, but earlier versions
|
|
126
|
+
// of this library emitted chart-frame styling there. Read it
|
|
127
|
+
// defensively, then merge into the authoritative `chartSpace.spPr`
|
|
128
|
+
// slot when that is absent — preserving legacy files without
|
|
129
|
+
// re-emitting schema-invalid XML. The write path now always uses
|
|
130
|
+
// `chartSpace.spPr` (`CT_ChartSpace/cx:spPr`).
|
|
131
|
+
const legacyChartSpPr = parseRawSpPr(chartEl ? findChild(chartEl, "cx:spPr") : undefined);
|
|
132
|
+
const chartSpacespPr = parseRawSpPr(findChild(root, "cx:spPr")) ?? legacyChartSpPr;
|
|
133
|
+
// `cx:externalData` is a child of `cx:chartSpace` per the Chart2014
|
|
134
|
+
// `CT_ChartSpace` schema. Some Excel-authored files (and earlier
|
|
135
|
+
// versions of this library) misplaced it inside `cx:chartData`;
|
|
136
|
+
// read from the schema-correct location first, fall back to the
|
|
137
|
+
// legacy location. Prefer one or the other — concatenating both
|
|
138
|
+
// produces duplicate `r:id` references when a file happens to carry
|
|
139
|
+
// the element in BOTH places (rare but observed in files that
|
|
140
|
+
// migrated through multiple writers), which fails strict-open
|
|
141
|
+
// validation.
|
|
142
|
+
const externalDataAtSpace = findChildren(root, "cx:externalData").map(el => ({
|
|
143
|
+
id: el.attributes["r:id"] ?? "",
|
|
144
|
+
autoUpdate: parseBoolAttr(el, "autoUpdate")
|
|
145
|
+
}));
|
|
146
|
+
const externalDataAtChartData = chartDataEl
|
|
147
|
+
? findChildren(chartDataEl, "cx:externalData").map(el => ({
|
|
148
|
+
id: el.attributes["r:id"] ?? "",
|
|
149
|
+
autoUpdate: parseBoolAttr(el, "autoUpdate")
|
|
150
|
+
}))
|
|
151
|
+
: [];
|
|
152
|
+
const externalData = externalDataAtSpace.length > 0 ? externalDataAtSpace : externalDataAtChartData;
|
|
153
|
+
return {
|
|
154
|
+
chartSpace: {
|
|
155
|
+
chartData: parseChartData(chartDataEl, collector),
|
|
156
|
+
chart: parseChart(chartEl, collector),
|
|
157
|
+
clrMapOvr: rawElement(root, "cx:clrMapOvr"),
|
|
158
|
+
// ChartSpace-level `spPr` / `txPr` are captured as structured-
|
|
159
|
+
// with-rawXml by `parseRawSpPr` / `parseRawTxPr` so downstream
|
|
160
|
+
// mutations (setSpPrFill, etc.) still work without losing the
|
|
161
|
+
// original XML for the unchanged field subset.
|
|
162
|
+
spPr: chartSpacespPr,
|
|
163
|
+
txPr: parseRawTxPr(root, "cx:txPr"),
|
|
164
|
+
// `cx:protection` / `cx:printSettings` are kept verbatim — the
|
|
165
|
+
// structured model does not (yet) break them into typed fields.
|
|
166
|
+
protection: rawElement(root, "cx:protection"),
|
|
167
|
+
printSettings: rawElement(root, "cx:printSettings"),
|
|
168
|
+
extLst: rawElement(root, "cx:extLst"),
|
|
169
|
+
...(externalData.length > 0 ? { externalData } : {})
|
|
170
|
+
},
|
|
171
|
+
rawXml,
|
|
172
|
+
...(collector.entries.length > 0 ? { unknownElements: collector.entries } : {})
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function parseChartData(chartDataEl, collector) {
|
|
176
|
+
if (!chartDataEl) {
|
|
177
|
+
return { data: [] };
|
|
178
|
+
}
|
|
179
|
+
const data = findChildren(chartDataEl, "cx:data").flatMap(el => parseDataEntries(el, collector));
|
|
180
|
+
// `cx:externalData` now lives on `ChartExSpace` (schema-correct
|
|
181
|
+
// location). The caller (`parseChartEx`) migrates any legacy
|
|
182
|
+
// occurrences found inside `cx:chartData` up to chartSpace — this
|
|
183
|
+
// function no longer returns the field so the migration is
|
|
184
|
+
// authoritative.
|
|
185
|
+
return { data };
|
|
186
|
+
}
|
|
187
|
+
function parseDataEntry(el, collector) {
|
|
188
|
+
const strDim = findChild(el, "cx:strDim");
|
|
189
|
+
const numDim = findChild(el, "cx:numDim");
|
|
190
|
+
// `parseIndexAttr` coerces empty / missing / non-finite / negative
|
|
191
|
+
// ids to `0` (see {@link parseIndexAttr}). OOXML treats absent and
|
|
192
|
+
// empty `id=""` identically, and sparse-array-hostile sentinels
|
|
193
|
+
// (`-1`, `NaN`) would poison downstream point indexing.
|
|
194
|
+
return {
|
|
195
|
+
id: parseIndexAttr(el.attributes.id),
|
|
196
|
+
...(strDim ? { strDim: parseStringDimension(strDim, collector) } : {}),
|
|
197
|
+
...(numDim ? { numDim: parseNumericDimension(numDim, collector) } : {})
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Parse one `<cx:data id="…">` element. Per [MS-ODRAWXML] the element
|
|
202
|
+
* can hold multiple `<cx:strDim>` and `<cx:numDim>` children (the
|
|
203
|
+
* `<xsd:choice maxOccurs="unbounded">` inside CT_Data). The writer's
|
|
204
|
+
* `consolidateDataForRender` uses that to satisfy the `maxOccurs="1"`
|
|
205
|
+
* on `<cx:dataId>` in CT_Series: it packs every dimension a series
|
|
206
|
+
* references into ONE `<cx:data>`.
|
|
207
|
+
*
|
|
208
|
+
* The in-memory {@link ChartExDataEntry} shape stores one `strDim`
|
|
209
|
+
* plus one `numDim` per entry — it can't hold a 4-dimension sunburst
|
|
210
|
+
* in a single record. So on parse we EXPLODE a multi-dimension
|
|
211
|
+
* `<cx:data>` back into a contiguous run of single-dimension entries:
|
|
212
|
+
* the first uses the element's `id` attribute verbatim, the rest use
|
|
213
|
+
* fresh synthetic ids off the top of the existing id range. Series
|
|
214
|
+
* `dataRefs` that reference the original id still hit the first
|
|
215
|
+
* exploded entry, and the writer's consolidator re-merges the run on
|
|
216
|
+
* the next serialisation pass.
|
|
217
|
+
*/
|
|
218
|
+
function parseDataEntries(el, collector) {
|
|
219
|
+
const baseId = parseIndexAttr(el.attributes.id);
|
|
220
|
+
// Collect children in document order so hierarchical sunburst /
|
|
221
|
+
// treemap levels come out as they were authored.
|
|
222
|
+
const ordered = [];
|
|
223
|
+
for (const child of el.children) {
|
|
224
|
+
if (child.type !== "element") {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (child.name === "cx:strDim" || child.name === "cx:numDim") {
|
|
228
|
+
ordered.push(child);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (ordered.length <= 1) {
|
|
232
|
+
return [parseDataEntry(el, collector)];
|
|
233
|
+
}
|
|
234
|
+
// For multi-dimension entries, produce one {@link ChartExDataEntry}
|
|
235
|
+
// per child, all sharing the `baseId` prefix. Use a wide numeric
|
|
236
|
+
// gap after the chart's highest id so the synthetic identifiers
|
|
237
|
+
// don't collide with legitimate, distinct `<cx:data id>` entries
|
|
238
|
+
// further down the `cx:chartData` block.
|
|
239
|
+
const entries = [];
|
|
240
|
+
for (let i = 0; i < ordered.length; i++) {
|
|
241
|
+
const child = ordered[i];
|
|
242
|
+
// `baseId` for the first slot preserves the series' dataRef
|
|
243
|
+
// linkage. Subsequent slots get an id the writer rarely picks
|
|
244
|
+
// on its own (10M-offset above whatever the chart already uses).
|
|
245
|
+
const id = i === 0 ? baseId : baseId * 1000 + 10000000 + i;
|
|
246
|
+
if (child.name === "cx:strDim") {
|
|
247
|
+
entries.push({ id, strDim: parseStringDimension(child, collector) });
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
entries.push({ id, numDim: parseNumericDimension(child, collector) });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return entries;
|
|
254
|
+
}
|
|
255
|
+
function parseStringDimension(el, collector) {
|
|
256
|
+
return {
|
|
257
|
+
type: parseDimensionType(el.attributes.type, collector, "cx:strDim/@type"),
|
|
258
|
+
formula: childText(el, "cx:f"),
|
|
259
|
+
levels: findChildren(el, "cx:lvl").map(lvl => ({
|
|
260
|
+
ptCount: parseOptionalInt(lvl.attributes.ptCount),
|
|
261
|
+
points: findChildren(lvl, "cx:pt").map(pt => ({
|
|
262
|
+
index: parseIndexAttr(pt.attributes.idx),
|
|
263
|
+
value: textContent(pt)
|
|
264
|
+
}))
|
|
265
|
+
}))
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function parseNumericDimension(el, collector) {
|
|
269
|
+
return {
|
|
270
|
+
type: parseDimensionType(el.attributes.type, collector, "cx:numDim/@type"),
|
|
271
|
+
formula: childText(el, "cx:f"),
|
|
272
|
+
levels: findChildren(el, "cx:lvl").map(lvl => ({
|
|
273
|
+
ptCount: parseOptionalInt(lvl.attributes.ptCount),
|
|
274
|
+
formatCode: lvl.attributes.formatCode,
|
|
275
|
+
// Skip `<cx:pt>` whose text content is blank / non-numeric / an
|
|
276
|
+
// Excel error code (`"#N/A"` etc.). Previously these flowed into
|
|
277
|
+
// the model as `NaN`, polluted axis-range calculations, and
|
|
278
|
+
// produced non-numeric `<c:v>` on the round-trip write.
|
|
279
|
+
points: findChildren(lvl, "cx:pt")
|
|
280
|
+
.map(pt => {
|
|
281
|
+
const value = parseFloat(textContent(pt));
|
|
282
|
+
if (!Number.isFinite(value)) {
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
index: parseIndexAttr(pt.attributes.idx),
|
|
287
|
+
value
|
|
288
|
+
};
|
|
289
|
+
})
|
|
290
|
+
.filter((p) => p !== undefined)
|
|
291
|
+
}))
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function parseChart(chartEl, collector) {
|
|
295
|
+
const plotAreaEl = chartEl ? findChild(chartEl, "cx:plotArea") : undefined;
|
|
296
|
+
return {
|
|
297
|
+
title: chartEl ? parseTitle(findChild(chartEl, "cx:title")) : undefined,
|
|
298
|
+
autoTitleDeleted: chartEl
|
|
299
|
+
? parseBoolAttr(findChild(chartEl, "cx:autoTitleDeleted"), "val")
|
|
300
|
+
: undefined,
|
|
301
|
+
plotArea: parsePlotArea(plotAreaEl, collector),
|
|
302
|
+
legend: chartEl ? parseLegend(findChild(chartEl, "cx:legend"), collector) : undefined
|
|
303
|
+
// NOTE: `cx:spPr` on `<cx:chart>` is a schema violation (CT_Chart
|
|
304
|
+
// has no `spPr` child); the outer caller (`parseChartExXml`)
|
|
305
|
+
// migrates any legacy `chart.spPr` bytes into `chartSpace.spPr`
|
|
306
|
+
// before this return value is consumed. See the block above the
|
|
307
|
+
// `parseChart` caller for the migration path.
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
function parsePlotArea(plotAreaEl, collector) {
|
|
311
|
+
if (!plotAreaEl) {
|
|
312
|
+
return {};
|
|
313
|
+
}
|
|
314
|
+
const regionEl = findChild(plotAreaEl, "cx:plotAreaRegion");
|
|
315
|
+
const axis = findChildren(plotAreaEl, "cx:axis").map(el => parseAxis(el, collector));
|
|
316
|
+
if (regionEl) {
|
|
317
|
+
const regionSeriesPath = "cx:chartSpace/cx:chart/cx:plotArea/cx:plotAreaRegion/cx:series";
|
|
318
|
+
// `CT_PlotAreaRegion` (Chart2014) has children `plotSurface?` and
|
|
319
|
+
// `series*` — there is no `layout` or `spPr` child. The parser
|
|
320
|
+
// previously pulled `cx:spPr` directly from the region, which was a
|
|
321
|
+
// schema violation. `plotSurface` wraps an inner `cx:spPr`, so we
|
|
322
|
+
// must dig one level deeper.
|
|
323
|
+
const plotSurfaceEl = findChild(regionEl, "cx:plotSurface");
|
|
324
|
+
return {
|
|
325
|
+
plotAreaRegion: {
|
|
326
|
+
// `layout` is not a real `plotAreaRegion` child, but earlier
|
|
327
|
+
// versions of this library emitted `<cx:layout/>` there — keep
|
|
328
|
+
// parsing it so round-trip of those files doesn't drop state.
|
|
329
|
+
layout: parseRawLayout(findChild(regionEl, "cx:layout")),
|
|
330
|
+
plotSurface: plotSurfaceEl ? parseRawSpPr(findChild(plotSurfaceEl, "cx:spPr")) : undefined,
|
|
331
|
+
series: findChildren(regionEl, "cx:series").map(el => parseSeries(el, collector, regionSeriesPath)),
|
|
332
|
+
// `<cx:extLst>` nested inside `<cx:plotAreaRegion>` is a
|
|
333
|
+
// Chart2014 extension point (Excel writes `cx14:*` annotations
|
|
334
|
+
// here for pivot-backed region maps). Preserve the raw bytes
|
|
335
|
+
// for round-trip; the parser never interprets them.
|
|
336
|
+
extLst: rawElement(regionEl, "cx:extLst")
|
|
337
|
+
},
|
|
338
|
+
spPr: parseRawSpPr(findChild(plotAreaEl, "cx:spPr")),
|
|
339
|
+
extLst: rawElement(plotAreaEl, "cx:extLst"),
|
|
340
|
+
...(axis.length > 0 ? { axis } : {})
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
const plainSeriesPath = "cx:chartSpace/cx:chart/cx:plotArea/cx:series";
|
|
344
|
+
const series = findChildren(plotAreaEl, "cx:series").map(el => parseSeries(el, collector, plainSeriesPath));
|
|
345
|
+
return {
|
|
346
|
+
...(series.length > 0 ? { series } : {}),
|
|
347
|
+
spPr: parseRawSpPr(findChild(plotAreaEl, "cx:spPr")),
|
|
348
|
+
extLst: rawElement(plotAreaEl, "cx:extLst"),
|
|
349
|
+
...(axis.length > 0 ? { axis } : {})
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
// ECMA-376 §21.3 enumerates the legal `cx:series/@layoutId` values. Preserve
|
|
353
|
+
// the attribute when it matches the structured union; otherwise fall back to
|
|
354
|
+
// "clusteredColumn" (the most permissive single-axis layout) and surface the
|
|
355
|
+
// original string via `unknownElements` so callers can diagnose. Silently
|
|
356
|
+
// defaulting to e.g. "sunburst" would mis-route every unknown chart to the
|
|
357
|
+
// sunburst vector renderer.
|
|
358
|
+
const CHART_EX_SERIES_LAYOUT_IDS = new Set([
|
|
359
|
+
"clusteredColumn",
|
|
360
|
+
"waterfall",
|
|
361
|
+
"funnel",
|
|
362
|
+
"boxWhisker",
|
|
363
|
+
"paretoLine",
|
|
364
|
+
"regionMap",
|
|
365
|
+
"sunburst",
|
|
366
|
+
"treemap"
|
|
367
|
+
]);
|
|
368
|
+
function parseSeriesLayoutId(value, collector, seriesPath) {
|
|
369
|
+
if (value !== undefined && CHART_EX_SERIES_LAYOUT_IDS.has(value)) {
|
|
370
|
+
return { layoutId: value };
|
|
371
|
+
}
|
|
372
|
+
collector?.entries.push({
|
|
373
|
+
name: value === undefined ? "@layoutId(missing)" : `@layoutId=${value}`,
|
|
374
|
+
path: seriesPath
|
|
375
|
+
});
|
|
376
|
+
// "clusteredColumn" is the neutral fallback: a plain column chart will at
|
|
377
|
+
// least render bars for the available data rather than being reinterpreted
|
|
378
|
+
// as a sunburst / treemap, which have different data-shape requirements.
|
|
379
|
+
//
|
|
380
|
+
// When the original attribute was present but unknown (e.g. a future
|
|
381
|
+
// layoutId like `"funnel3D"` that this version doesn't model), keep it
|
|
382
|
+
// under `rawLayoutId` so the writer can re-emit the byte-original
|
|
383
|
+
// attribute during round-trip. Without this, re-saving a file with
|
|
384
|
+
// a vendor extension silently downgrades the chart to a plain column
|
|
385
|
+
// chart — worse than leaving the bytes alone.
|
|
386
|
+
return {
|
|
387
|
+
layoutId: "clusteredColumn",
|
|
388
|
+
rawLayoutId: value
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function parseSeries(el, collector, seriesPath) {
|
|
392
|
+
const dataRefs = findChildren(el, "cx:dataId").map(dataId => ({
|
|
393
|
+
dataId: parseIndexAttr(dataId.attributes.val)
|
|
394
|
+
}));
|
|
395
|
+
// Primary form per the ECMA-376 chartEx schema and Microsoft Excel's
|
|
396
|
+
// own output: `<cx:axisId val="N"/>` (CT_UnsignedInteger with a
|
|
397
|
+
// required `val` attribute). A previous revision of our renderer
|
|
398
|
+
// mis-read the schema and emitted `<cx:axisId>N</cx:axisId>` as a
|
|
399
|
+
// text-content form — that form is not valid chartEx and Excel
|
|
400
|
+
// rejects it on open (drops the whole drawing). Read `val` first,
|
|
401
|
+
// then fall back to text content so round-trips of files authored
|
|
402
|
+
// by that buggy writer still recover the id instead of silently
|
|
403
|
+
// dropping it to `undefined`. Filter unresolvable ids so the
|
|
404
|
+
// returned array stays `number[]`.
|
|
405
|
+
const axisId = findChildren(el, "cx:axisId")
|
|
406
|
+
.map(axis => {
|
|
407
|
+
// Prefer the `val` attribute when present and non-empty; fall
|
|
408
|
+
// back to text content for round-tripping files authored by
|
|
409
|
+
// buggy writers that emit the id as element text.
|
|
410
|
+
const rawAttr = axis.attributes.val;
|
|
411
|
+
if (rawAttr !== undefined && rawAttr !== "") {
|
|
412
|
+
return parseIndexAttr(rawAttr);
|
|
413
|
+
}
|
|
414
|
+
const text = textContent(axis).trim();
|
|
415
|
+
if (text.length > 0) {
|
|
416
|
+
const parsed = Number(text);
|
|
417
|
+
if (Number.isFinite(parsed) && parsed >= 0) {
|
|
418
|
+
return Math.round(parsed);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return undefined;
|
|
422
|
+
})
|
|
423
|
+
.filter((id) => id !== undefined);
|
|
424
|
+
const tx = parseSeriesText(findChild(el, "cx:tx"));
|
|
425
|
+
const layoutPr = parseLayoutProperties(findChild(el, "cx:layoutPr"));
|
|
426
|
+
const layoutIdResult = parseSeriesLayoutId(el.attributes.layoutId, collector, seriesPath ?? "cx:series");
|
|
427
|
+
return {
|
|
428
|
+
layoutId: layoutIdResult.layoutId,
|
|
429
|
+
...(layoutIdResult.rawLayoutId !== undefined
|
|
430
|
+
? { rawLayoutId: layoutIdResult.rawLayoutId }
|
|
431
|
+
: {}),
|
|
432
|
+
hidden: parseBoolAttr(el, "hidden"),
|
|
433
|
+
ownerIdx: parseOptionalInt(el.attributes.ownerIdx),
|
|
434
|
+
...(tx ? { tx } : {}),
|
|
435
|
+
spPr: parseRawSpPr(findChild(el, "cx:spPr")),
|
|
436
|
+
txPr: parseRawTxPr(el, "cx:txPr"),
|
|
437
|
+
// `<cx:valueColors>` and `<cx:valueColorPositions>` carry
|
|
438
|
+
// value-driven colour gradients (region map / treemap). The
|
|
439
|
+
// structured model doesn't yet interpret the stops, but we must
|
|
440
|
+
// round-trip them or the gradient evaporates on save. `rawElement`
|
|
441
|
+
// preserves the full outer element including attributes.
|
|
442
|
+
valueColors: rawElement(el, "cx:valueColors"),
|
|
443
|
+
valueColorPositions: rawElement(el, "cx:valueColorPositions"),
|
|
444
|
+
...(dataRefs.length > 0 ? { dataRefs } : {}),
|
|
445
|
+
...(layoutPr ? { layoutPr } : {}),
|
|
446
|
+
...(axisId.length > 0 ? { axisId } : {}),
|
|
447
|
+
dataLabels: parseDataLabels(findChild(el, "cx:dataLabels"), collector, seriesPath),
|
|
448
|
+
dataPt: findChildren(el, "cx:dataPt").map(pt => ({
|
|
449
|
+
idx: parseIndexAttr(pt.attributes.idx),
|
|
450
|
+
spPr: parseRawSpPr(findChild(pt, "cx:spPr"))
|
|
451
|
+
})),
|
|
452
|
+
extLst: rawElement(el, "cx:extLst")
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
function parseSeriesText(el) {
|
|
456
|
+
if (!el) {
|
|
457
|
+
return undefined;
|
|
458
|
+
}
|
|
459
|
+
// Check for structured rich-text first. `<cx:tx>/<cx:rich>…</cx:rich>`
|
|
460
|
+
// is how Excel authors encode per-run formatting on a series name
|
|
461
|
+
// (bold accent series, colour-coded series, etc.); previously the
|
|
462
|
+
// parser ignored this branch entirely and left `tx` undefined, so
|
|
463
|
+
// round-tripping such a series lost the entire name unless the raw
|
|
464
|
+
// bytes path was taken.
|
|
465
|
+
const richEl = findChild(el, "cx:rich");
|
|
466
|
+
if (richEl) {
|
|
467
|
+
const rich = parseRichText(richEl);
|
|
468
|
+
if (rich) {
|
|
469
|
+
return { rich };
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
const txData = findChild(el, "cx:txData");
|
|
473
|
+
if (!txData) {
|
|
474
|
+
return undefined;
|
|
475
|
+
}
|
|
476
|
+
const formula = childText(txData, "cx:f");
|
|
477
|
+
if (formula) {
|
|
478
|
+
// Capture the cached resolved value alongside the formula so
|
|
479
|
+
// reading clients (legend preview, title fallback, saved-chart
|
|
480
|
+
// displays before recalculation) can show the user's label
|
|
481
|
+
// immediately. Previously only the formula string was stored,
|
|
482
|
+
// so Excel-authored `<cx:tx><cx:txData><cx:f>...</cx:f><cx:v>
|
|
483
|
+
// Label</cx:v></cx:txData></cx:tx>` lost `Label` on round-trip.
|
|
484
|
+
const cachedValue = childText(txData, "cx:v");
|
|
485
|
+
return {
|
|
486
|
+
strRef: cachedValue !== undefined ? { formula, cached: cachedValue } : { formula }
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
const value = childText(txData, "cx:v");
|
|
490
|
+
return value !== undefined ? { value } : undefined;
|
|
491
|
+
}
|
|
492
|
+
function parseLayoutProperties(el) {
|
|
493
|
+
if (!el) {
|
|
494
|
+
return undefined;
|
|
495
|
+
}
|
|
496
|
+
const binning = findChild(el, "cx:binning");
|
|
497
|
+
const subtotalsEl = findChild(el, "cx:subtotals");
|
|
498
|
+
// Per the [MS-ODRAWXML] CT_Subtotals schema, children are named
|
|
499
|
+
// `<cx:idx val="N"/>` — with the INDEX in the `val` attribute.
|
|
500
|
+
// Earlier revisions of this library used a non-schema `<cx:subtotal
|
|
501
|
+
// idx="N"/>` element; accept both on parse. `<cx:idx>` schema has
|
|
502
|
+
// the index in `val`, legacy `<cx:subtotal>` had it in `idx`.
|
|
503
|
+
const subtotals = subtotalsEl
|
|
504
|
+
? [
|
|
505
|
+
...findChildren(subtotalsEl, "cx:idx").map(st => ({
|
|
506
|
+
idx: parseIndexAttr(st.attributes.val)
|
|
507
|
+
})),
|
|
508
|
+
...findChildren(subtotalsEl, "cx:subtotal").map(st => ({
|
|
509
|
+
idx: parseIndexAttr(st.attributes.idx)
|
|
510
|
+
}))
|
|
511
|
+
]
|
|
512
|
+
: undefined;
|
|
513
|
+
const parentLabelLayout = childVal(el, "cx:parentLabelLayout");
|
|
514
|
+
// Per the official [MS-ODRAWXML] CT_SeriesLayoutProperties schema,
|
|
515
|
+
// several per-type flags live on wrapper elements rather than as
|
|
516
|
+
// flat children:
|
|
517
|
+
//
|
|
518
|
+
// * `<cx:visibility>` carries the boxWhisker show* flags
|
|
519
|
+
// (`meanLine`, `meanMarker`, `nonoutliers`, `outliers`) as
|
|
520
|
+
// attributes, plus the waterfall `connectorLines` flag.
|
|
521
|
+
// * `<cx:statistics>` carries the boxWhisker `quartileMethod`
|
|
522
|
+
// attribute.
|
|
523
|
+
// * `<cx:geography>` carries regionMap `projectionType` /
|
|
524
|
+
// `viewedRegionType` attributes.
|
|
525
|
+
// * `<cx:regionLabelLayout>` carries regionMap `regionLabels` via
|
|
526
|
+
// a `val` attribute.
|
|
527
|
+
//
|
|
528
|
+
// Earlier revisions of this library wrote each of these as a flat
|
|
529
|
+
// element like `<cx:showMeanLine val="1"/>` / `<cx:projection val="…"/>`
|
|
530
|
+
// — that output was schema-invalid (Excel 2016+ rejects the whole
|
|
531
|
+
// ChartEx part on load) but we still need to parse files produced
|
|
532
|
+
// by those versions. Each property below checks the correct schema
|
|
533
|
+
// location first, then falls back to the flat form for legacy
|
|
534
|
+
// on-disk bytes.
|
|
535
|
+
const visibilityEl = findChild(el, "cx:visibility");
|
|
536
|
+
const statisticsEl = findChild(el, "cx:statistics");
|
|
537
|
+
const geographyEl = findChild(el, "cx:geography");
|
|
538
|
+
const regionLabelLayoutEl = findChild(el, "cx:regionLabelLayout");
|
|
539
|
+
const quartileMethod = statisticsEl?.attributes.quartileMethod ?? childVal(el, "cx:quartileMethod");
|
|
540
|
+
const projection = geographyEl?.attributes.projectionType ?? childVal(el, "cx:projection");
|
|
541
|
+
const regionLabelsRaw = regionLabelLayoutEl?.attributes.val ?? childVal(el, "cx:regionLabels");
|
|
542
|
+
const regionLabels = regionLabelsRaw === "bestFitOnly" ? "bestFit" : regionLabelsRaw;
|
|
543
|
+
const geoMappingLevelRaw = geographyEl?.attributes.viewedRegionType ?? childVal(el, "cx:geoMappingLevel");
|
|
544
|
+
// Map the spec-canonical `countryRegion` → public `country`;
|
|
545
|
+
// `dataOnly` → `automatic`. Other values pass through unchanged.
|
|
546
|
+
const geoMappingLevel = geoMappingLevelRaw === "countryRegion"
|
|
547
|
+
? "country"
|
|
548
|
+
: geoMappingLevelRaw === "dataOnly"
|
|
549
|
+
? "automatic"
|
|
550
|
+
: geoMappingLevelRaw;
|
|
551
|
+
// Collect each child only when the XML actually contains it. Emitting
|
|
552
|
+
// `subtotals: []` / `parentLabelLayout: undefined` triggers
|
|
553
|
+
// `hasStructuredLayoutProperties` (see chart-ex-renderer.ts) and forces the
|
|
554
|
+
// writer down the structured path, discarding `_rawXml`. That produced
|
|
555
|
+
// empty / corrupt `<cx:layoutPr>` sections for any ChartEx that was loaded
|
|
556
|
+
// and re-written without an explicit structured mutation.
|
|
557
|
+
return {
|
|
558
|
+
_rawXml: serializeElement(el),
|
|
559
|
+
...(parentLabelLayout !== undefined
|
|
560
|
+
? {
|
|
561
|
+
parentLabelLayout: parentLabelLayout
|
|
562
|
+
}
|
|
563
|
+
: {}),
|
|
564
|
+
...(subtotals !== undefined ? { subtotals } : {}),
|
|
565
|
+
...(() => {
|
|
566
|
+
// `connectorLines` (waterfall) is a `<cx:visibility>` attribute
|
|
567
|
+
// per CT_SeriesLayoutProperties. Read the attribute first; fall
|
|
568
|
+
// back to the legacy `<cx:connectorLines val="…"/>` flat element
|
|
569
|
+
// produced by older revisions of this library.
|
|
570
|
+
const raw = visibilityEl?.attributes.connectorLines;
|
|
571
|
+
if (raw !== undefined) {
|
|
572
|
+
const b = parseBoolString(raw);
|
|
573
|
+
return b !== undefined ? { connectorLines: b } : {};
|
|
574
|
+
}
|
|
575
|
+
const v = parseCtBoolean(findChild(el, "cx:connectorLines"));
|
|
576
|
+
return v !== undefined ? { connectorLines: v } : {};
|
|
577
|
+
})(),
|
|
578
|
+
...(binning
|
|
579
|
+
? {
|
|
580
|
+
binning: {
|
|
581
|
+
// Validate against `CT_Binning/@intervalClosed`
|
|
582
|
+
// enumeration (`"l" | "r"`). Unknown values are dropped
|
|
583
|
+
// rather than cast through — silently storing garbage
|
|
584
|
+
// here let injection attacks break out of the attribute
|
|
585
|
+
// on round-trip.
|
|
586
|
+
intervalClosed: (binning.attributes.intervalClosed === "l" ||
|
|
587
|
+
binning.attributes.intervalClosed === "r"
|
|
588
|
+
? binning.attributes.intervalClosed
|
|
589
|
+
: undefined),
|
|
590
|
+
underflow: parseOptionalFloat(binning.attributes.underflow),
|
|
591
|
+
overflow: parseOptionalFloat(binning.attributes.overflow),
|
|
592
|
+
// Per [MS-ODRAWXML] CT_Binning, `binSize` / `binCount` are
|
|
593
|
+
// element-content simple types (`<cx:binSize>0.5</cx:binSize>`),
|
|
594
|
+
// but Microsoft Excel 2016+ actually emits them with a `val`
|
|
595
|
+
// attribute (`<cx:binCount val="5"/>`) and rejects the text
|
|
596
|
+
// form on load. Accept both shapes so files authored by
|
|
597
|
+
// our earlier writers (text form) AND by Excel itself
|
|
598
|
+
// (attribute form) both round-trip. Nullish coalescing
|
|
599
|
+
// (`??`) is NOT enough here — self-closing `<cx:binCount/>`
|
|
600
|
+
// returns empty string from `childText` (NOT nullish),
|
|
601
|
+
// which would mask the `val` attribute. Use an explicit
|
|
602
|
+
// "non-empty-string or fall back" pattern.
|
|
603
|
+
binSize: parseOptionalFloat((childText(binning, "cx:binSize") || undefined) ?? childVal(binning, "cx:binSize")),
|
|
604
|
+
binCount: parseOptionalInt((childText(binning, "cx:binCount") || undefined) ?? childVal(binning, "cx:binCount")),
|
|
605
|
+
// `binType` is a library-internal discriminator — the
|
|
606
|
+
// official CT_Binning schema has no `<cx:auto>` /
|
|
607
|
+
// `<cx:categories>` / `<cx:manual>` elements. Map the
|
|
608
|
+
// schema-valid inputs onto the discriminator so existing
|
|
609
|
+
// callers who read `binType` continue to work; tolerate
|
|
610
|
+
// the legacy element forms on the way in.
|
|
611
|
+
binType: findChild(binning, "cx:auto")
|
|
612
|
+
? "auto"
|
|
613
|
+
: findChild(binning, "cx:categories")
|
|
614
|
+
? "categories"
|
|
615
|
+
: findChild(binning, "cx:manual")
|
|
616
|
+
? "manual"
|
|
617
|
+
: findChild(binning, "cx:binSize")
|
|
618
|
+
? "binSize"
|
|
619
|
+
: findChild(binning, "cx:binCount")
|
|
620
|
+
? "binCount"
|
|
621
|
+
: "auto"
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
: {}),
|
|
625
|
+
...(() => {
|
|
626
|
+
const v = parseCtBoolean(findChild(el, "cx:paretoLine"));
|
|
627
|
+
return v !== undefined ? { paretoLine: v } : {};
|
|
628
|
+
})(),
|
|
629
|
+
...(quartileMethod !== undefined
|
|
630
|
+
? {
|
|
631
|
+
quartileMethod: quartileMethod
|
|
632
|
+
}
|
|
633
|
+
: {}),
|
|
634
|
+
...(() => {
|
|
635
|
+
// `meanLine` / `meanMarker` / `nonoutliers` / `outliers` are
|
|
636
|
+
// `<cx:visibility>` attributes per the schema. Read the
|
|
637
|
+
// attribute first; fall back to the legacy `<cx:showMeanLine
|
|
638
|
+
// val="…"/>` flat element for files authored by older
|
|
639
|
+
// revisions of this library.
|
|
640
|
+
const raw = visibilityEl?.attributes.meanLine;
|
|
641
|
+
if (raw !== undefined) {
|
|
642
|
+
const b = parseBoolString(raw);
|
|
643
|
+
return b !== undefined ? { showMeanLine: b } : {};
|
|
644
|
+
}
|
|
645
|
+
const v = parseCtBoolean(findChild(el, "cx:showMeanLine"));
|
|
646
|
+
return v !== undefined ? { showMeanLine: v } : {};
|
|
647
|
+
})(),
|
|
648
|
+
...(() => {
|
|
649
|
+
const raw = visibilityEl?.attributes.meanMarker;
|
|
650
|
+
if (raw !== undefined) {
|
|
651
|
+
const b = parseBoolString(raw);
|
|
652
|
+
return b !== undefined ? { showMeanMarker: b } : {};
|
|
653
|
+
}
|
|
654
|
+
const v = parseCtBoolean(findChild(el, "cx:showMeanMarker"));
|
|
655
|
+
return v !== undefined ? { showMeanMarker: v } : {};
|
|
656
|
+
})(),
|
|
657
|
+
...(() => {
|
|
658
|
+
const raw = visibilityEl?.attributes.nonoutliers;
|
|
659
|
+
if (raw !== undefined) {
|
|
660
|
+
const b = parseBoolString(raw);
|
|
661
|
+
return b !== undefined ? { showInnerPoints: b } : {};
|
|
662
|
+
}
|
|
663
|
+
const v = parseCtBoolean(findChild(el, "cx:showInnerPoints"));
|
|
664
|
+
return v !== undefined ? { showInnerPoints: v } : {};
|
|
665
|
+
})(),
|
|
666
|
+
...(() => {
|
|
667
|
+
const raw = visibilityEl?.attributes.outliers;
|
|
668
|
+
if (raw !== undefined) {
|
|
669
|
+
const b = parseBoolString(raw);
|
|
670
|
+
return b !== undefined ? { showOutlierPoints: b } : {};
|
|
671
|
+
}
|
|
672
|
+
const v = parseCtBoolean(findChild(el, "cx:showOutlierPoints"));
|
|
673
|
+
return v !== undefined ? { showOutlierPoints: v } : {};
|
|
674
|
+
})(),
|
|
675
|
+
...(projection !== undefined
|
|
676
|
+
? { projection: projection }
|
|
677
|
+
: {}),
|
|
678
|
+
...(regionLabels !== undefined
|
|
679
|
+
? { regionLabels: regionLabels }
|
|
680
|
+
: {}),
|
|
681
|
+
...(geoMappingLevel !== undefined
|
|
682
|
+
? {
|
|
683
|
+
geoMappingLevel: geoMappingLevel
|
|
684
|
+
}
|
|
685
|
+
: {}),
|
|
686
|
+
extLst: rawElement(el, "cx:extLst")
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
function parseDataLabels(el, collector, parentPath) {
|
|
690
|
+
if (!el) {
|
|
691
|
+
return undefined;
|
|
692
|
+
}
|
|
693
|
+
const visibility = findChild(el, "cx:visibility");
|
|
694
|
+
// ECMA-376 `ST_DLblPosition` full enumeration (Chart2014 §21.3.2.30).
|
|
695
|
+
// Values beyond the classic-chart subset — `ctrEnd`, `inStart`,
|
|
696
|
+
// `outStart` — are emitted by Excel for waterfall / funnel / box &
|
|
697
|
+
// whisker layouts where label anchoring is richer than the basic
|
|
698
|
+
// "inside/outside/centre/best-fit" vocabulary. Previously the
|
|
699
|
+
// enum was restricted to the classic-chart subset, causing the
|
|
700
|
+
// validator to strip (and log) every richer value encountered in
|
|
701
|
+
// user files, silently reverting those labels to default placement.
|
|
702
|
+
const positionValues = [
|
|
703
|
+
"ctr",
|
|
704
|
+
"l",
|
|
705
|
+
"r",
|
|
706
|
+
"t",
|
|
707
|
+
"b",
|
|
708
|
+
"inBase",
|
|
709
|
+
"inEnd",
|
|
710
|
+
"inStart",
|
|
711
|
+
"outEnd",
|
|
712
|
+
"outStart",
|
|
713
|
+
"ctrEnd",
|
|
714
|
+
"bestFit"
|
|
715
|
+
];
|
|
716
|
+
const pathPrefix = parentPath ?? "cx:dataLabels";
|
|
717
|
+
return {
|
|
718
|
+
visibility: visibility
|
|
719
|
+
? {
|
|
720
|
+
seriesName: parseBoolAttr(visibility, "seriesName"),
|
|
721
|
+
categoryName: parseBoolAttr(visibility, "categoryName"),
|
|
722
|
+
value: parseBoolAttr(visibility, "value"),
|
|
723
|
+
numFmt: parseBoolAttr(visibility, "numFmt")
|
|
724
|
+
}
|
|
725
|
+
: undefined,
|
|
726
|
+
position: validateEnum(findChild(el, "cx:dataLabel")?.attributes.pos, positionValues, collector, `${pathPrefix}/cx:dataLabel/@pos`),
|
|
727
|
+
separator: childText(el, "cx:separator"),
|
|
728
|
+
numFmt: findChild(el, "cx:numFmt")?.attributes.formatCode,
|
|
729
|
+
spPr: parseRawSpPr(findChild(el, "cx:spPr")),
|
|
730
|
+
txPr: parseRawTxPr(el, "cx:txPr")
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Parse `<cx:majorGridlines>` / `<cx:minorGridlines>` — each element
|
|
735
|
+
* wraps a single optional `<cx:spPr>` child describing the gridline
|
|
736
|
+
* stroke. Returns an empty `ShapeProperties` when the element is
|
|
737
|
+
* present but has no `<cx:spPr>` (meaning "default-styled gridlines");
|
|
738
|
+
* `undefined` when the parent element is absent entirely.
|
|
739
|
+
*/
|
|
740
|
+
function parseGridlines(el) {
|
|
741
|
+
if (!el) {
|
|
742
|
+
return undefined;
|
|
743
|
+
}
|
|
744
|
+
const spPrEl = findChild(el, "cx:spPr");
|
|
745
|
+
if (!spPrEl) {
|
|
746
|
+
return {};
|
|
747
|
+
}
|
|
748
|
+
return parseRawSpPr(spPrEl);
|
|
749
|
+
}
|
|
750
|
+
function parseAxis(el, collector) {
|
|
751
|
+
const numFmt = findChild(el, "cx:numFmt");
|
|
752
|
+
const valScaling = findChild(el, "cx:valScaling");
|
|
753
|
+
const catScaling = findChild(el, "cx:catScaling");
|
|
754
|
+
// OOXML `ST_TickMark` values are `cross | in | out | none`; the public
|
|
755
|
+
// API uses friendlier `inside` / `outside` aliases (matching classic
|
|
756
|
+
// `types.ts:TickMark`). Map during parse so callers see a consistent
|
|
757
|
+
// vocabulary regardless of whether they came from classic or ChartEx.
|
|
758
|
+
const tickMarkOoxml = ["cross", "in", "out", "none"];
|
|
759
|
+
const mapTickMark = (v) => {
|
|
760
|
+
if (v === undefined) {
|
|
761
|
+
return undefined;
|
|
762
|
+
}
|
|
763
|
+
if (v === "in") {
|
|
764
|
+
return "inside";
|
|
765
|
+
}
|
|
766
|
+
if (v === "out") {
|
|
767
|
+
return "outside";
|
|
768
|
+
}
|
|
769
|
+
return v;
|
|
770
|
+
};
|
|
771
|
+
return {
|
|
772
|
+
axisId: parseIndexAttr(el.attributes.id),
|
|
773
|
+
type: findChild(el, "cx:valScaling") ? "val" : "cat",
|
|
774
|
+
// Per Chart2014 `CT_Axis`, `hidden` is an **attribute** on
|
|
775
|
+
// `<cx:axis>`, not a child element. Accept both forms so we can
|
|
776
|
+
// round-trip files our earlier versions incorrectly produced: check
|
|
777
|
+
// the attribute first, fall back to the legacy child element.
|
|
778
|
+
// Per Chart2014 `CT_Axis`, `hidden` is an **attribute** on
|
|
779
|
+
// `<cx:axis>`, not a child element. Accept both forms so we can
|
|
780
|
+
// round-trip files our earlier versions incorrectly produced: check
|
|
781
|
+
// the attribute first, fall back to the legacy child element.
|
|
782
|
+
// When using the legacy child form, treat a missing `val` as
|
|
783
|
+
// `true` per `CT_Boolean` (previously the library only read an
|
|
784
|
+
// explicit `val` and dropped the hidden flag when absent).
|
|
785
|
+
hidden: parseBoolAttr(el, "hidden") ?? parseCtBoolean(findChild(el, "cx:hidden")),
|
|
786
|
+
// Element names are plural in the schema (`majorTickMarks`,
|
|
787
|
+
// `minorTickMarks`). Again accept the singular form for backward
|
|
788
|
+
// compatibility with files we produced before the rename.
|
|
789
|
+
// Per [MS-ODRAWXML] CT_TickMarks the discriminator is a `type`
|
|
790
|
+
// attribute — not `val` like most other chartEx elements. Read
|
|
791
|
+
// `type` first, fall back to `val` for files authored by older
|
|
792
|
+
// revisions of this library (which wrongly used `val`).
|
|
793
|
+
majorTickMark: mapTickMark(validateEnum(findChild(el, "cx:majorTickMarks")?.attributes.type ??
|
|
794
|
+
findChild(el, "cx:majorTickMark")?.attributes.type ??
|
|
795
|
+
childVal(el, "cx:majorTickMarks") ??
|
|
796
|
+
childVal(el, "cx:majorTickMark"), tickMarkOoxml, collector, "cx:axis/cx:majorTickMarks/@type")),
|
|
797
|
+
minorTickMark: mapTickMark(validateEnum(findChild(el, "cx:minorTickMarks")?.attributes.type ??
|
|
798
|
+
findChild(el, "cx:minorTickMark")?.attributes.type ??
|
|
799
|
+
childVal(el, "cx:minorTickMarks") ??
|
|
800
|
+
childVal(el, "cx:minorTickMark"), tickMarkOoxml, collector, "cx:axis/cx:minorTickMarks/@type")),
|
|
801
|
+
numFmt: numFmt
|
|
802
|
+
? {
|
|
803
|
+
// `formatCode` is a required attribute per
|
|
804
|
+
// `CT_NumFmt/@formatCode`. When the source omits it,
|
|
805
|
+
// default to `"General"` (Excel's behaviour) rather than
|
|
806
|
+
// an empty string — the writer round-trips that default
|
|
807
|
+
// without producing a schema-invalid empty attribute.
|
|
808
|
+
formatCode: numFmt.attributes.formatCode || "General",
|
|
809
|
+
sourceLinked: parseBoolAttr(numFmt, "sourceLinked")
|
|
810
|
+
}
|
|
811
|
+
: undefined,
|
|
812
|
+
title: parseTitle(findChild(el, "cx:title")),
|
|
813
|
+
// `<cx:majorGridlines>` / `<cx:minorGridlines>` each wrap a
|
|
814
|
+
// single `<cx:spPr>` describing gridline stroke / colour. The
|
|
815
|
+
// structured `ShapeProperties` is extracted via `parseRawSpPr`
|
|
816
|
+
// so downstream consumers can read the colour without touching
|
|
817
|
+
// raw XML. Absent element → `undefined` on the model.
|
|
818
|
+
majorGridlines: parseGridlines(findChild(el, "cx:majorGridlines")),
|
|
819
|
+
minorGridlines: parseGridlines(findChild(el, "cx:minorGridlines")),
|
|
820
|
+
spPr: parseRawSpPr(findChild(el, "cx:spPr")),
|
|
821
|
+
txPr: parseRawTxPr(el, "cx:txPr"),
|
|
822
|
+
valScaling: valScaling
|
|
823
|
+
? {
|
|
824
|
+
min: parseOptionalFloat(valScaling.attributes.min),
|
|
825
|
+
max: parseOptionalFloat(valScaling.attributes.max),
|
|
826
|
+
majorUnit: parseOptionalFloat(valScaling.attributes.majorUnit),
|
|
827
|
+
minorUnit: parseOptionalFloat(valScaling.attributes.minorUnit)
|
|
828
|
+
}
|
|
829
|
+
: undefined,
|
|
830
|
+
catScaling: catScaling
|
|
831
|
+
? {
|
|
832
|
+
gapWidth: parseOptionalFloat(catScaling.attributes.gapWidth)
|
|
833
|
+
}
|
|
834
|
+
: undefined,
|
|
835
|
+
// `<cx:units>` is a value-axis display-unit scaler (thousands /
|
|
836
|
+
// millions / custom). The library doesn't yet interpret its
|
|
837
|
+
// `cx:unit` / `cx:dispUnitsLbl` children, but preserving the raw
|
|
838
|
+
// bytes keeps round-trip byte-equal for files that carry the
|
|
839
|
+
// element. Without this the element evaporated on save.
|
|
840
|
+
units: rawElement(el, "cx:units"),
|
|
841
|
+
extLst: rawElement(el, "cx:extLst")
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
function parseLegend(el, collector) {
|
|
845
|
+
if (!el) {
|
|
846
|
+
return undefined;
|
|
847
|
+
}
|
|
848
|
+
const legendPositions = ["b", "l", "r", "t", "tr"];
|
|
849
|
+
const legendAligns = ["ctr", "l", "r", "t", "b"];
|
|
850
|
+
// `CT_Legend` (Chart2014) sequence: `legendEntry* → spPr? → txPr? →
|
|
851
|
+
// extLst?`. The parser previously only read `pos` / `align` /
|
|
852
|
+
// `overlay` / `spPr` / legendEntry idx; every other field was
|
|
853
|
+
// silently dropped, breaking round-trip of legends with author-
|
|
854
|
+
// supplied text styling, per-entry deletions, and vendor
|
|
855
|
+
// extensions.
|
|
856
|
+
return {
|
|
857
|
+
legendPos: validateEnum(el.attributes.pos, legendPositions, collector, "cx:legend/@pos"),
|
|
858
|
+
align: validateEnum(el.attributes.align, legendAligns, collector, "cx:legend/@align"),
|
|
859
|
+
overlay: parseBoolAttr(el, "overlay"),
|
|
860
|
+
spPr: parseRawSpPr(findChild(el, "cx:spPr")),
|
|
861
|
+
txPr: parseRawTxPr(el, "cx:txPr"),
|
|
862
|
+
extLst: rawElement(el, "cx:extLst"),
|
|
863
|
+
legendEntries: findChildren(el, "cx:legendEntry").map(entry => ({
|
|
864
|
+
index: parseIndexAttr(entry.attributes.idx),
|
|
865
|
+
// Per `CT_LegendEntry` in the Chart2014 XSD, both `idx` and
|
|
866
|
+
// `delete` are attributes (`xsd:unsignedInt` and `xsd:boolean`
|
|
867
|
+
// respectively) — despite the type name `CT_Boolean` appearing
|
|
868
|
+
// elsewhere in the schema for CHILD-element booleans. Excel's
|
|
869
|
+
// own output is `<cx:legendEntry idx="0" delete="1"/>` with
|
|
870
|
+
// attribute form, and the matching renderer emits the same
|
|
871
|
+
// shape. Default per schema when `delete` is absent is `false`.
|
|
872
|
+
delete: parseBoolAttr(entry, "delete"),
|
|
873
|
+
txPr: parseRawTxPr(entry, "cx:txPr"),
|
|
874
|
+
extLst: rawElement(entry, "cx:extLst")
|
|
875
|
+
}))
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
function parseTitle(el) {
|
|
879
|
+
if (!el) {
|
|
880
|
+
return undefined;
|
|
881
|
+
}
|
|
882
|
+
const txEl = findChild(el, "cx:tx");
|
|
883
|
+
const text = parseRichText(findChild(txEl ?? emptyElement(), "cx:rich"));
|
|
884
|
+
// `<cx:tx>` can hold EITHER `<cx:rich>` (structured rich text) OR
|
|
885
|
+
// `<cx:txData>` (formula-backed text with cached value). The parser
|
|
886
|
+
// previously only handled the rich variant, so a title authored as
|
|
887
|
+
// `<cx:tx><cx:txData><cx:f>Sheet1!$A$1</cx:f><cx:v>Q1 Sales</cx:v></cx:txData></cx:tx>`
|
|
888
|
+
// silently dropped the formula on round-trip. Map `txData` onto the
|
|
889
|
+
// classic `ChartTitle.strRef` shape so writers / consumers can use
|
|
890
|
+
// one API for both formula-linked titles.
|
|
891
|
+
const txDataEl = findChild(txEl ?? emptyElement(), "cx:txData");
|
|
892
|
+
const formula = txDataEl ? childText(txDataEl, "cx:f") : undefined;
|
|
893
|
+
const cachedValue = txDataEl ? childText(txDataEl, "cx:v") : undefined;
|
|
894
|
+
const strRef = formula
|
|
895
|
+
? {
|
|
896
|
+
formula,
|
|
897
|
+
cache: cachedValue !== undefined
|
|
898
|
+
? { points: [{ index: 0, value: cachedValue }] }
|
|
899
|
+
: { points: [] }
|
|
900
|
+
}
|
|
901
|
+
: undefined;
|
|
902
|
+
const overlay = parseBoolAttr(findChild(el, "cx:overlay"), "val");
|
|
903
|
+
const spPr = parseRawSpPr(findChild(el, "cx:spPr"));
|
|
904
|
+
const txPr = parseRawTxPr(el, "cx:txPr");
|
|
905
|
+
const rawTx = rawElement(el, "cx:tx");
|
|
906
|
+
// Return undefined for an empty `<cx:title/>` so downstream consumers
|
|
907
|
+
// (snapshot tests, change detection) don't see a phantom title
|
|
908
|
+
// object with all fields undefined. Parsing a self-closing title
|
|
909
|
+
// element produces `rawTx` that's itself a self-closing tag —
|
|
910
|
+
// treat that as equivalent to absent unless structured state is
|
|
911
|
+
// present.
|
|
912
|
+
if (text === undefined &&
|
|
913
|
+
strRef === undefined &&
|
|
914
|
+
overlay === undefined &&
|
|
915
|
+
spPr === undefined &&
|
|
916
|
+
txPr === undefined &&
|
|
917
|
+
(rawTx === undefined || /^<cx:tx\s*\/>$/.test(rawTx.trim()))) {
|
|
918
|
+
return undefined;
|
|
919
|
+
}
|
|
920
|
+
return { text, strRef, overlay, spPr, txPr, rawTx };
|
|
921
|
+
}
|
|
922
|
+
function parseRichText(el) {
|
|
923
|
+
if (!el) {
|
|
924
|
+
return undefined;
|
|
925
|
+
}
|
|
926
|
+
const paragraphs = findChildren(el, "a:p").map(p => {
|
|
927
|
+
// Paragraph properties — `<a:pPr>` with optional `<a:defRPr>` child
|
|
928
|
+
// carrying default run formatting for the paragraph. Not fully
|
|
929
|
+
// modelled in `ChartParagraph` today; capturing it as raw XML so
|
|
930
|
+
// mutation-aware writers can still preserve author intent.
|
|
931
|
+
const runs = findChildren(p, "a:r").map(r => {
|
|
932
|
+
const runText = childText(r, "a:t") ?? "";
|
|
933
|
+
// Parse `<a:rPr>` into structured `ChartTextProperties`. Wrapping
|
|
934
|
+
// `<a:defRPr>` around the rPr attributes is the trick that lets
|
|
935
|
+
// us reuse `parseTxPr`, which expects a `defRPr`-style XML block.
|
|
936
|
+
// Previously the parser dropped run-level properties entirely —
|
|
937
|
+
// any bold/italic/colour/font on a rich-text title or series
|
|
938
|
+
// caption silently disappeared on round-trip unless the caller
|
|
939
|
+
// explicitly used the raw-bytes path.
|
|
940
|
+
const rPr = findChild(r, "a:rPr");
|
|
941
|
+
if (!rPr) {
|
|
942
|
+
return { text: runText };
|
|
943
|
+
}
|
|
944
|
+
const rPrRaw = rawElementFromNode(rPr);
|
|
945
|
+
if (!rPrRaw) {
|
|
946
|
+
return { text: runText };
|
|
947
|
+
}
|
|
948
|
+
// `parseTxPr` reads `<a:defRPr>` or `<a:rPr>` fragments from
|
|
949
|
+
// `_rawXml`; the element name doesn't matter, the attribute /
|
|
950
|
+
// child extraction does. Emit a thin `<a:defRPr>` envelope and
|
|
951
|
+
// feed the inner bytes through.
|
|
952
|
+
const innerBytes = rPrRaw
|
|
953
|
+
.replace(/^<a:rPr\b/, "<a:defRPr")
|
|
954
|
+
.replace(/<\/a:rPr>$/, "</a:defRPr>");
|
|
955
|
+
const envelope = `<a:txPr><a:p>${innerBytes}</a:p></a:txPr>`;
|
|
956
|
+
const parsed = parseTxPr({ _rawXml: envelope });
|
|
957
|
+
if (!parsed || Object.keys(parsed).length === 0) {
|
|
958
|
+
return { text: runText };
|
|
959
|
+
}
|
|
960
|
+
// Strip the `_rawXml` that `parseTxPr` may have carried through;
|
|
961
|
+
// run properties are flat, not a full `ChartTextProperties`
|
|
962
|
+
// wrapper.
|
|
963
|
+
const { _rawXml, ...structured } = parsed;
|
|
964
|
+
return {
|
|
965
|
+
text: runText,
|
|
966
|
+
properties: structured
|
|
967
|
+
};
|
|
968
|
+
});
|
|
969
|
+
return { runs };
|
|
970
|
+
});
|
|
971
|
+
return paragraphs.length > 0 ? { paragraphs } : undefined;
|
|
972
|
+
}
|
|
973
|
+
function parseRawLayout(el) {
|
|
974
|
+
const raw = rawElementFromNode(el);
|
|
975
|
+
// `ChartLayout._rawXml` was added so this path no longer needs `as any`.
|
|
976
|
+
return raw ? { _rawXml: raw } : undefined;
|
|
977
|
+
}
|
|
978
|
+
function parseRawSpPr(el) {
|
|
979
|
+
const raw = rawElementFromNode(el);
|
|
980
|
+
if (!raw) {
|
|
981
|
+
return undefined;
|
|
982
|
+
}
|
|
983
|
+
// Dual representation: keep the original XML for lossless round-trip of
|
|
984
|
+
// elements this parser does not structurally understand (a:xfrm,
|
|
985
|
+
// a:prstGeom, a:custGeom, future DrawingML extensions…) while also
|
|
986
|
+
// populating structured fields (fill / line / effectList / scene3d / sp3d)
|
|
987
|
+
// so consumers can read and mutate them programmatically.
|
|
988
|
+
//
|
|
989
|
+
// Writers (`chart-ex-renderer.renderSpPr`, `chart-space-xform._renderSpPr`)
|
|
990
|
+
// prefer `_rawXml` when present. Mutation APIs in `shape-properties.ts`
|
|
991
|
+
// (`setSpPrFill`, `setSpPrLine`, `buildSpPr`) return a new object without
|
|
992
|
+
// `_rawXml`, which causes the writer to take the structured path. This
|
|
993
|
+
// matches the contract documented at `shape-properties.ts:927`.
|
|
994
|
+
const structured = parseSpPr({ _rawXml: raw });
|
|
995
|
+
return { ...structured, _rawXml: raw };
|
|
996
|
+
}
|
|
997
|
+
function parseRawTxPr(parent, name) {
|
|
998
|
+
const raw = rawElement(parent, name);
|
|
999
|
+
if (!raw) {
|
|
1000
|
+
return undefined;
|
|
1001
|
+
}
|
|
1002
|
+
// Same dual-representation trick as `parseRawSpPr`. `parseTxPr` extracts
|
|
1003
|
+
// font size / bold / italic / colour / font family / rotation from the raw
|
|
1004
|
+
// XML so callers can read and mutate text properties structurally; the
|
|
1005
|
+
// raw XML wins at write time unless the caller rebuilds via `buildTxPr`.
|
|
1006
|
+
const structured = parseTxPr({ _rawXml: raw });
|
|
1007
|
+
return { ...structured, _rawXml: raw };
|
|
1008
|
+
}
|
|
1009
|
+
function rawElement(parent, name) {
|
|
1010
|
+
return rawElementFromNode(findChild(parent, name));
|
|
1011
|
+
}
|
|
1012
|
+
function rawElementFromNode(el) {
|
|
1013
|
+
if (!el) {
|
|
1014
|
+
return undefined;
|
|
1015
|
+
}
|
|
1016
|
+
return serializeElement(el);
|
|
1017
|
+
}
|
|
1018
|
+
function serializeElement(el) {
|
|
1019
|
+
const attrs = Object.entries(el.attributes ?? {})
|
|
1020
|
+
.map(([key, value]) => ` ${key}="${escapeXmlAttr(value)}"`)
|
|
1021
|
+
.join("");
|
|
1022
|
+
const children = el.children ?? [];
|
|
1023
|
+
if (children.length === 0) {
|
|
1024
|
+
return `<${el.name}${attrs}/>`;
|
|
1025
|
+
}
|
|
1026
|
+
return `<${el.name}${attrs}>${children.map(serializeNode).join("")}</${el.name}>`;
|
|
1027
|
+
}
|
|
1028
|
+
function serializeNode(node) {
|
|
1029
|
+
if (node.type === "text") {
|
|
1030
|
+
return escapeXml(node.value ?? "");
|
|
1031
|
+
}
|
|
1032
|
+
if (node.type === "element") {
|
|
1033
|
+
return serializeElement(node);
|
|
1034
|
+
}
|
|
1035
|
+
if (node.type === "cdata") {
|
|
1036
|
+
return `<![CDATA[${node.value ?? ""}]]>`;
|
|
1037
|
+
}
|
|
1038
|
+
if (node.type === "comment") {
|
|
1039
|
+
return `<!--${node.value ?? ""}-->`;
|
|
1040
|
+
}
|
|
1041
|
+
if (node.type === "processing-instruction") {
|
|
1042
|
+
return `<?${node.target}${node.body ? ` ${node.body}` : ""}?>`;
|
|
1043
|
+
}
|
|
1044
|
+
return "";
|
|
1045
|
+
}
|
|
1046
|
+
function childText(el, name) {
|
|
1047
|
+
const child = findChild(el, name);
|
|
1048
|
+
return child ? textContent(child) : undefined;
|
|
1049
|
+
}
|
|
1050
|
+
function childVal(el, name) {
|
|
1051
|
+
return findChild(el, name)?.attributes.val;
|
|
1052
|
+
}
|
|
1053
|
+
function parseBoolAttr(el, name) {
|
|
1054
|
+
const value = el?.attributes[name];
|
|
1055
|
+
if (value === undefined) {
|
|
1056
|
+
return undefined;
|
|
1057
|
+
}
|
|
1058
|
+
return parseBoolString(value);
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Parse an OOXML boolean string (`"1"` / `"0"` / `"true"` / `"false"`),
|
|
1062
|
+
* returning `undefined` for anything else. Used by the layoutPr parser
|
|
1063
|
+
* when reading boolean attributes off `<cx:visibility>` etc.
|
|
1064
|
+
*/
|
|
1065
|
+
function parseBoolString(value) {
|
|
1066
|
+
if (value === undefined) {
|
|
1067
|
+
return undefined;
|
|
1068
|
+
}
|
|
1069
|
+
if (value === "1" || value === "true") {
|
|
1070
|
+
return true;
|
|
1071
|
+
}
|
|
1072
|
+
if (value === "0" || value === "false") {
|
|
1073
|
+
return false;
|
|
1074
|
+
}
|
|
1075
|
+
return undefined;
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Parse a Chart2014 `CT_Boolean` child element. The element's `val`
|
|
1079
|
+
* attribute defaults to `true` when absent — see ECMA-376 Part 1
|
|
1080
|
+
* §L.4.3.2.8. Callers like `<cx:connectorLines/>`, `<cx:paretoLine/>`,
|
|
1081
|
+
* `<cx:showMeanLine/>` depend on this default; previously the parser
|
|
1082
|
+
* required an explicit `val` attribute and silently dropped the field
|
|
1083
|
+
* otherwise, losing user intent for waterfall / box-and-whisker /
|
|
1084
|
+
* pareto charts on round-trip.
|
|
1085
|
+
*
|
|
1086
|
+
* Semantics by input:
|
|
1087
|
+
* - Element missing entirely → `undefined`
|
|
1088
|
+
* - `<cx:foo/>` (no `val` attr) → `true` (schema default)
|
|
1089
|
+
* - `<cx:foo val="1"/>` / `"true"` → `true`
|
|
1090
|
+
* - `<cx:foo val="0"/>` / `"false"` → `false`
|
|
1091
|
+
* - `<cx:foo val="yes"/>` (garbage) → `undefined` (don't promote)
|
|
1092
|
+
*
|
|
1093
|
+
* The last case previously coalesced to `true` via `?? true`, silently
|
|
1094
|
+
* treating an invalid attribute as opt-in. Garbage now falls through
|
|
1095
|
+
* so callers can distinguish "attribute absent" from "attribute
|
|
1096
|
+
* invalid" and react accordingly (typically: drop the field, leaving
|
|
1097
|
+
* the caller's default in place).
|
|
1098
|
+
*/
|
|
1099
|
+
function parseCtBoolean(el) {
|
|
1100
|
+
if (!el) {
|
|
1101
|
+
return undefined;
|
|
1102
|
+
}
|
|
1103
|
+
// Distinguish "no val attribute" (schema default true) from
|
|
1104
|
+
// "val attribute present but unrecognised" (undefined).
|
|
1105
|
+
if (el.attributes.val === undefined) {
|
|
1106
|
+
return true;
|
|
1107
|
+
}
|
|
1108
|
+
return parseBoolAttr(el, "val");
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* Narrow an attribute / child-element string to a known enum value.
|
|
1112
|
+
* When the input is missing returns `undefined`; when it isn't one of
|
|
1113
|
+
* the `allowed` variants returns `undefined` and appends a diagnostic
|
|
1114
|
+
* entry to the {@link UnknownCollector}, so callers can discover
|
|
1115
|
+
* unfamiliar OOXML values via `model.unknownElements` without replacing
|
|
1116
|
+
* them with an arbitrary fallback.
|
|
1117
|
+
*/
|
|
1118
|
+
function validateEnum(value, allowed, collector, path) {
|
|
1119
|
+
if (value === undefined) {
|
|
1120
|
+
return undefined;
|
|
1121
|
+
}
|
|
1122
|
+
if (allowed.includes(value)) {
|
|
1123
|
+
return value;
|
|
1124
|
+
}
|
|
1125
|
+
collector?.entries.push({ name: `${path}=${value}`, path });
|
|
1126
|
+
return undefined;
|
|
1127
|
+
}
|
|
1128
|
+
function parseOptionalInt(value) {
|
|
1129
|
+
if (value === undefined) {
|
|
1130
|
+
return undefined;
|
|
1131
|
+
}
|
|
1132
|
+
const parsed = parseInt(value, 10);
|
|
1133
|
+
// `parseInt("Infinity", 10)` returns `NaN` — caught by the finite
|
|
1134
|
+
// check — but explicit finite testing guards against future
|
|
1135
|
+
// parser additions (e.g. `Number()` migration) still rejecting
|
|
1136
|
+
// non-finite slips. See `parseOptionalFloat`.
|
|
1137
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Parse a non-negative OOXML index attribute, falling back to `0`
|
|
1141
|
+
* when the value is absent / malformed. Use this for `idx`, `id`,
|
|
1142
|
+
* `dataId` and similar slots where `<c:pt idx="">` (empty string),
|
|
1143
|
+
* `<c:pt idx="abc">` (garbage), or `<c:pt idx="-1">` (negative)
|
|
1144
|
+
* should all coerce to 0 rather than land a poison value on the
|
|
1145
|
+
* model — `-1` silently corrupts dense arrays via property
|
|
1146
|
+
* assignment on the length slot, and `NaN` creates a string-indexed
|
|
1147
|
+
* property the rest of the code ignores.
|
|
1148
|
+
*/
|
|
1149
|
+
function parseIndexAttr(value) {
|
|
1150
|
+
if (value === undefined || value === "") {
|
|
1151
|
+
return 0;
|
|
1152
|
+
}
|
|
1153
|
+
const parsed = parseInt(value, 10);
|
|
1154
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
1155
|
+
return 0;
|
|
1156
|
+
}
|
|
1157
|
+
return parsed;
|
|
1158
|
+
}
|
|
1159
|
+
function parseOptionalFloat(value) {
|
|
1160
|
+
if (value === undefined) {
|
|
1161
|
+
return undefined;
|
|
1162
|
+
}
|
|
1163
|
+
const parsed = parseFloat(value);
|
|
1164
|
+
// Reject non-finite parses — `parseFloat("Infinity")` returns
|
|
1165
|
+
// `Infinity`, which propagates through axis scaling and collapses
|
|
1166
|
+
// the plot to an unrenderable degenerate range. Malformed input
|
|
1167
|
+
// should fall back to "absent" rather than poison downstream math.
|
|
1168
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
1169
|
+
}
|
|
1170
|
+
/**
|
|
1171
|
+
* Validate an OOXML `cx:strDim/@type` / `cx:numDim/@type` value
|
|
1172
|
+
* against {@link ChartExDimensionType}. Unknown values fall back to
|
|
1173
|
+
* `"val"` (the schema default) and are reported to the optional
|
|
1174
|
+
* {@link UnknownCollector} so `model.unknownElements` surfaces
|
|
1175
|
+
* vendor / forward-compat extensions instead of silently coercing
|
|
1176
|
+
* them into a real enum member.
|
|
1177
|
+
*/
|
|
1178
|
+
function parseDimensionType(value, collector, path) {
|
|
1179
|
+
const allowed = [
|
|
1180
|
+
"cat",
|
|
1181
|
+
"val",
|
|
1182
|
+
"x",
|
|
1183
|
+
"y",
|
|
1184
|
+
"size",
|
|
1185
|
+
"colorVal",
|
|
1186
|
+
"from",
|
|
1187
|
+
"to",
|
|
1188
|
+
"classification"
|
|
1189
|
+
];
|
|
1190
|
+
if (value === undefined) {
|
|
1191
|
+
return "val";
|
|
1192
|
+
}
|
|
1193
|
+
if (allowed.includes(value)) {
|
|
1194
|
+
return value;
|
|
1195
|
+
}
|
|
1196
|
+
const diagnosticPath = path ?? "cx:dim/@type";
|
|
1197
|
+
collector?.entries.push({
|
|
1198
|
+
name: `${diagnosticPath}=${value}`,
|
|
1199
|
+
path: diagnosticPath
|
|
1200
|
+
});
|
|
1201
|
+
return "val";
|
|
1202
|
+
}
|
|
1203
|
+
function emptyElement() {
|
|
1204
|
+
return { type: "element", name: "", attributes: {}, children: [] };
|
|
1205
|
+
}
|