reamkit 1.32.0 → 1.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +5 -4
  2. package/dist/esm/core/bidi/algorithm.js +2 -2
  3. package/dist/esm/core/bidi/char-types.js +1 -1
  4. package/dist/esm/core/bidi/index.js +3 -3
  5. package/dist/esm/core/bytes.js +1 -1
  6. package/dist/esm/core/converter/facade.js +3 -2
  7. package/dist/esm/core/converter/ream.js +12 -5
  8. package/dist/esm/core/crypto/asn1.js +2 -2
  9. package/dist/esm/core/crypto/cms.js +5 -3
  10. package/dist/esm/core/crypto/index.js +2 -1
  11. package/dist/esm/core/crypto/offcrypto.js +64 -19
  12. package/dist/esm/core/crypto/primitives.js +16 -16
  13. package/dist/esm/core/document-model/index.d.ts +1 -1
  14. package/dist/esm/core/document-model/types.d.ts +174 -2
  15. package/dist/esm/core/drawingml/chart-geometry.d.ts +45 -17
  16. package/dist/esm/core/drawingml/chart-geometry.js +1090 -257
  17. package/dist/esm/core/drawingml/chart-parser.d.ts +24 -1
  18. package/dist/esm/core/drawingml/chart-parser.js +334 -41
  19. package/dist/esm/core/drawingml/chart-text.d.ts +41 -0
  20. package/dist/esm/core/drawingml/chart-text.js +93 -0
  21. package/dist/esm/core/drawingml/colors.js +5 -5
  22. package/dist/esm/core/drawingml/diagram/layout-engine.js +1 -4
  23. package/dist/esm/core/drawingml/diagram/run.js +2 -1
  24. package/dist/esm/core/drawingml/preset-geometry.js +4 -6
  25. package/dist/esm/core/drawingml/shape-render.js +1 -1
  26. package/dist/esm/core/drawingml/text-warp.js +4 -16
  27. package/dist/esm/core/drawingml/theme-parser.js +14 -8
  28. package/dist/esm/core/font/arabic-joining.js +2 -2
  29. package/dist/esm/core/font/binary-reader.js +2 -0
  30. package/dist/esm/core/font/font-registry.js +1 -0
  31. package/dist/esm/core/font/ligatures.js +1 -1
  32. package/dist/esm/core/font/opentype-layout.js +11 -5
  33. package/dist/esm/core/font/ttf-build.js +6 -10
  34. package/dist/esm/core/font/ttf-parser.js +2 -1
  35. package/dist/esm/core/font/ttf-subset.js +8 -8
  36. package/dist/esm/core/fonts/families.js +1 -1
  37. package/dist/esm/core/fonts/remote-fonts.js +4 -4
  38. package/dist/esm/core/hyphenation/index.js +1 -1
  39. package/dist/esm/core/images.js +8 -8
  40. package/dist/esm/core/ir/loss.js +1 -0
  41. package/dist/esm/core/line-breaker/cjk.js +1 -1
  42. package/dist/esm/core/line-breaker/index.js +4 -3
  43. package/dist/esm/core/links.js +1 -1
  44. package/dist/esm/core/lzw.js +1 -1
  45. package/dist/esm/core/metafile/blit.js +1 -1
  46. package/dist/esm/core/metafile/emf.js +5 -7
  47. package/dist/esm/core/metafile/picture.js +1 -1
  48. package/dist/esm/core/metafile/symbol-fonts.js +7 -7
  49. package/dist/esm/core/metafile/wmf.js +5 -7
  50. package/dist/esm/core/number-format.d.ts +40 -15
  51. package/dist/esm/core/number-format.js +284 -79
  52. package/dist/esm/core/numbering/index.js +3 -2
  53. package/dist/esm/core/ole/cfb.js +4 -4
  54. package/dist/esm/core/ole/escher-blip.js +1 -1
  55. package/dist/esm/core/opc/index.js +5 -4
  56. package/dist/esm/core/opc/package.js +3 -1
  57. package/dist/esm/core/opc/tag-scan.d.ts +15 -0
  58. package/dist/esm/core/opc/tag-scan.js +41 -0
  59. package/dist/esm/core/opc/xml-entities.js +40 -3
  60. package/dist/esm/core/outline.js +1 -1
  61. package/dist/esm/core/png-encode.js +3 -3
  62. package/dist/esm/core/po-helpers.js +1 -1
  63. package/dist/esm/core/spreadsheet-model/types.d.ts +6 -0
  64. package/dist/esm/core/style-cascade/index.js +4 -3
  65. package/dist/esm/core/tiff.js +3 -1
  66. package/dist/esm/excel/activex-parser.js +1 -1
  67. package/dist/esm/excel/conditional-format.js +7 -7
  68. package/dist/esm/excel/formula/functions.js +45 -18
  69. package/dist/esm/excel/formula/index.js +3 -3
  70. package/dist/esm/excel/formula/lexer.js +2 -2
  71. package/dist/esm/excel/formula/parser.js +4 -3
  72. package/dist/esm/excel/formula/value.js +1 -1
  73. package/dist/esm/excel/index.js +7 -6
  74. package/dist/esm/excel/print-model.js +18 -7
  75. package/dist/esm/excel/printer-settings.js +6 -7
  76. package/dist/esm/excel/rich-value.js +1 -1
  77. package/dist/esm/excel/sheet-shape-parser.js +4 -2
  78. package/dist/esm/excel/sheet-to-flow.js +13 -11
  79. package/dist/esm/excel/styles-parser.js +5 -3
  80. package/dist/esm/excel/tint.js +5 -5
  81. package/dist/esm/excel/vml-drawing.js +3 -3
  82. package/dist/esm/excel/worksheet-parser.js +5 -5
  83. package/dist/esm/excel/xls/biff-chart.js +1 -3
  84. package/dist/esm/excel/xls/biff-reader.js +10 -11
  85. package/dist/esm/excel/xls/xls-reader.js +1 -1
  86. package/dist/esm/excel/xlsx-reader.js +56 -9
  87. package/dist/esm/excel/xlsx-to-pdf.js +1 -1
  88. package/dist/esm/excel/xlsx-writer.js +2 -2
  89. package/dist/esm/html/html-writer.js +18 -10
  90. package/dist/esm/layout/line-paint.js +1 -1
  91. package/dist/esm/layout/math-layout.js +5 -8
  92. package/dist/esm/layout/styled-layout.js +104 -32
  93. package/dist/esm/layout/turned-section.js +2 -2
  94. package/dist/esm/markdown/markdown-writer.js +59 -8
  95. package/dist/esm/pdf/encryption.js +9 -9
  96. package/dist/esm/pdf/icc-profile.js +2 -2
  97. package/dist/esm/pdf/index.js +3 -2
  98. package/dist/esm/pdf/objects.js +7 -0
  99. package/dist/esm/pdf/serialize.js +1 -1
  100. package/dist/esm/pdf/struct-tree.js +3 -1
  101. package/dist/esm/pdf/styled-page-emitter.js +23 -15
  102. package/dist/esm/pdf/styled-page-renderer.js +9 -5
  103. package/dist/esm/pdf-reader/annot-draw.js +5 -5
  104. package/dist/esm/pdf-reader/annots.js +3 -1
  105. package/dist/esm/pdf-reader/ccitt.js +2 -1
  106. package/dist/esm/pdf-reader/cff-outline.js +1 -4
  107. package/dist/esm/pdf-reader/content.js +13 -15
  108. package/dist/esm/pdf-reader/decrypt.js +5 -4
  109. package/dist/esm/pdf-reader/document.js +6 -2
  110. package/dist/esm/pdf-reader/encodings.js +1 -1
  111. package/dist/esm/pdf-reader/flow-build.js +4 -6
  112. package/dist/esm/pdf-reader/font.js +4 -4
  113. package/dist/esm/pdf-reader/function.js +8 -7
  114. package/dist/esm/pdf-reader/icc.js +1 -1
  115. package/dist/esm/pdf-reader/images.js +1 -1
  116. package/dist/esm/pdf-reader/jbig2.js +36 -38
  117. package/dist/esm/pdf-reader/jpeg.js +14 -13
  118. package/dist/esm/pdf-reader/layout.js +13 -10
  119. package/dist/esm/pdf-reader/lexer.js +2 -1
  120. package/dist/esm/pdf-reader/math-rows.js +2 -2
  121. package/dist/esm/pdf-reader/optional-content.js +1 -1
  122. package/dist/esm/pdf-reader/page-numbers.js +1 -1
  123. package/dist/esm/pdf-reader/pattern-tint.js +1 -2
  124. package/dist/esm/pdf-reader/reader.js +2 -2
  125. package/dist/esm/pdf-reader/struct-tree.js +1 -1
  126. package/dist/esm/pdf-reader/tagged.js +3 -2
  127. package/dist/esm/pdf-reader/text.js +2 -2
  128. package/dist/esm/pdf-reader/type1-outline.js +1 -3
  129. package/dist/esm/pptx/embedded-fonts.js +3 -5
  130. package/dist/esm/pptx/placeholder-cascade.js +1 -1
  131. package/dist/esm/pptx/ppt/ppt-reader.js +5 -4
  132. package/dist/esm/pptx/ppt/ppt-text.js +9 -10
  133. package/dist/esm/pptx/pptx-reader.js +6 -5
  134. package/dist/esm/pptx/preset-table-styles.js +1 -1
  135. package/dist/esm/pptx/slide-parser.js +6 -4
  136. package/dist/esm/pptx/sp-helpers.js +1 -1
  137. package/dist/esm/pptx/table-style.js +2 -1
  138. package/dist/esm/svg/svg-writer.js +1 -1
  139. package/dist/esm/word/doc/doc-reader.js +2 -2
  140. package/dist/esm/word/doc/doc-text.js +20 -22
  141. package/dist/esm/word/document-parser.js +27 -22
  142. package/dist/esm/word/docx-reader.js +15 -10
  143. package/dist/esm/word/docx-to-pdf.js +6 -6
  144. package/dist/esm/word/docx-writer.js +10 -6
  145. package/dist/esm/word/drawing-parser.js +18 -18
  146. package/dist/esm/word/font-table.js +90 -11
  147. package/dist/esm/word/index.js +6 -5
  148. package/dist/esm/word/numbering-parser.js +5 -4
  149. package/dist/esm/word/omml-parser.js +1 -1
  150. package/dist/esm/word/paragraph-properties.js +11 -10
  151. package/dist/esm/word/run-properties.js +4 -4
  152. package/dist/esm/word/settings-parser.js +2 -1
  153. package/dist/esm/word/shading.js +1 -1
  154. package/dist/esm/word/styles-parser.js +5 -4
  155. package/dist/esm/word/table-parser.js +4 -4
  156. package/dist/esm/word/theme-fonts.js +1 -1
  157. package/package.json +10 -4
@@ -2,6 +2,26 @@ import { Chart } from '../document-model/index.js';
2
2
  import { ResourceId } from '../ir/index.js';
3
3
  import { OpcPackage } from '../opc/index.js';
4
4
  import { ColorResolver } from './colors.js';
5
+ import { ChartTextDefaults } from './chart-text.js';
6
+ /**
7
+ * The most points a chart keeps, all its series together: as many as a sheet
8
+ * has rows, the longest range a series can name. A chart part states its own
9
+ * point counts — a cache's `c:ptCount`, each point's `idx`, the range of a
10
+ * `c:f` — and taken at their word, a count of two billion in a part a few
11
+ * hundred bytes long asked for a dense array that ran the process out of
12
+ * memory, and one past 2³² − 1 threw.
13
+ */
14
+ export declare const MOST_CHART_POINTS = 1048576;
15
+ /**
16
+ * How many points each of a chart's `seriesCount` series keeps: an even share
17
+ * of {@link MOST_CHART_POINTS}, so that the bound holds for the chart and not
18
+ * series by series — two thousand series, each declaring a sheet's worth of
19
+ * points, are two billion. A series' points past its share are not read.
20
+ *
21
+ * @param seriesCount How many series the chart has.
22
+ * @returns The points each keeps, at least one.
23
+ */
24
+ export declare function pointsPerSeries(seriesCount: number): number;
5
25
  /**
6
26
  * Parse a DrawingML chart part (chart1.xml) into a {@link Chart}, reading the
7
27
  * CACHED data (`c:numCache` / `c:strCache`) rather than the embedded spreadsheet
@@ -13,9 +33,12 @@ import { ColorResolver } from './colors.js';
13
33
  *
14
34
  * @param chartXml The raw chart1.xml part bytes.
15
35
  * @param resolveColor Maps a DrawingML colour reference to a 6-hex string.
36
+ * @param resolveImage Maps a blip's relationship id to its image resource.
37
+ * @param textDefaults The host's defaults for chart text; given, the chart's
38
+ * text is resolved role by role ({@link Chart.text}).
16
39
  * @returns The parsed chart, or `null` when there is no `c:chart` / `c:plotArea`.
17
40
  */
18
- export declare function parseChart(chartXml: Uint8Array, resolveColor: ColorResolver, resolveImage?: (relId: string) => ResourceId | undefined): Chart | null;
41
+ export declare function parseChart(chartXml: Uint8Array, resolveColor: ColorResolver, resolveImage?: (relId: string) => ResourceId | undefined, textDefaults?: ChartTextDefaults): Chart | null;
19
42
  /**
20
43
  * MS-ODRAWXML chartColorStyle (charts/colorsN.xml): the top-level colour list is
21
44
  * the series cycle (`meth="cycle"` — the common case; variations are luminance
@@ -1,4 +1,5 @@
1
1
  import { poAttr, poChildren, poFindByPath, poFindDescendant, poIntAttr, poIs, poTag, poText, poVal } from "../po-helpers.js";
2
+ import { chartTextStyles } from "./chart-text.js";
2
3
  import { resolveColorNode } from "./colors.js";
3
4
  import { XMLParser } from "fast-xml-parser";
4
5
  //#region src/core/drawingml/chart-parser.ts
@@ -25,6 +26,27 @@ var TYPE_OF_TAG = {
25
26
  "c:scatterChart": "scatter"
26
27
  };
27
28
  /**
29
+ * The most points a chart keeps, all its series together: as many as a sheet
30
+ * has rows, the longest range a series can name. A chart part states its own
31
+ * point counts — a cache's `c:ptCount`, each point's `idx`, the range of a
32
+ * `c:f` — and taken at their word, a count of two billion in a part a few
33
+ * hundred bytes long asked for a dense array that ran the process out of
34
+ * memory, and one past 2³² − 1 threw.
35
+ */
36
+ var MOST_CHART_POINTS = 1048576;
37
+ /**
38
+ * How many points each of a chart's `seriesCount` series keeps: an even share
39
+ * of {@link MOST_CHART_POINTS}, so that the bound holds for the chart and not
40
+ * series by series — two thousand series, each declaring a sheet's worth of
41
+ * points, are two billion. A series' points past its share are not read.
42
+ *
43
+ * @param seriesCount How many series the chart has.
44
+ * @returns The points each keeps, at least one.
45
+ */
46
+ function pointsPerSeries(seriesCount) {
47
+ return Math.max(1, Math.floor(MOST_CHART_POINTS / Math.max(1, seriesCount)));
48
+ }
49
+ /**
28
50
  * Parse a DrawingML chart part (chart1.xml) into a {@link Chart}, reading the
29
51
  * CACHED data (`c:numCache` / `c:strCache`) rather than the embedded spreadsheet
30
52
  * — the cache holds the last-computed categories and values, exactly what Word
@@ -35,9 +57,12 @@ var TYPE_OF_TAG = {
35
57
  *
36
58
  * @param chartXml The raw chart1.xml part bytes.
37
59
  * @param resolveColor Maps a DrawingML colour reference to a 6-hex string.
60
+ * @param resolveImage Maps a blip's relationship id to its image resource.
61
+ * @param textDefaults The host's defaults for chart text; given, the chart's
62
+ * text is resolved role by role ({@link Chart.text}).
38
63
  * @returns The parsed chart, or `null` when there is no `c:chart` / `c:plotArea`.
39
64
  */
40
- function parseChart(chartXml, resolveColor, resolveImage) {
65
+ function parseChart(chartXml, resolveColor, resolveImage, textDefaults) {
41
66
  const tree = parser.parse(decoder.decode(chartXml));
42
67
  const chart = poFindByPath(tree, ["c:chartSpace", "c:chart"]);
43
68
  if (!chart) return null;
@@ -48,6 +73,7 @@ function parseChart(chartXml, resolveColor, resolveImage) {
48
73
  const type = group ? TYPE_OF_TAG[poTag(group)] ?? "unknown" : "unknown";
49
74
  const groupAxIds = (g) => poChildren(g).filter((c) => poIs(c, "c:axId")).map((c) => poAttr(c, "val") ?? "");
50
75
  const primaryAxIds = new Set(group ? groupAxIds(group) : []);
76
+ const most = pointsPerSeries(groups.reduce((n, g) => n + poChildren(g).filter((c) => poIs(c, "c:ser")).length, 0));
51
77
  const serNodes = [];
52
78
  const series = [];
53
79
  let secondaryValAxId;
@@ -58,7 +84,7 @@ function parseChart(chartXml, resolveColor, resolveImage) {
58
84
  for (const s of poChildren(g).filter((c) => poIs(c, "c:ser"))) {
59
85
  serNodes.push(s);
60
86
  series.push({
61
- ...parseSeries(s, resolveColor),
87
+ ...parseSeries(s, resolveColor, most),
62
88
  ...groupType === type ? {} : { type: groupType },
63
89
  ...secondary ? { secondaryAxis: true } : {}
64
90
  });
@@ -75,8 +101,8 @@ function parseChart(chartXml, resolveColor, resolveImage) {
75
101
  for (const s of serNodes) {
76
102
  const cat = poChildren(s).find((c) => poIs(c, "c:cat"));
77
103
  if (cat) {
78
- const levels = multiLevelCategories(cat);
79
- categories = levels ? levels.categories : denseStrings(cat);
104
+ const levels = multiLevelCategories(cat, most);
105
+ categories = levels ? levels.categories : denseStrings(cat, most);
80
106
  categoryGroups = levels?.groups;
81
107
  categoriesRef ??= refFormula(cat);
82
108
  break;
@@ -88,21 +114,55 @@ function parseChart(chartXml, resolveColor, resolveImage) {
88
114
  const barDir = group ? poVal(poChildren(group).find((c) => poIs(c, "c:barDir"))) : void 0;
89
115
  const grouping = group ? poVal(poChildren(group).find((c) => poIs(c, "c:grouping"))) : void 0;
90
116
  const doughnut = group ? poIs(group, "c:doughnutChart") : false;
117
+ const view3D = poChildren(chart).find((c) => poIs(c, "c:view3D"));
118
+ const viewAngle = (tag, fallback) => {
119
+ const v = Number(poVal(view3D ? poChildren(view3D).find((c) => poIs(c, tag)) : void 0));
120
+ return Number.isFinite(v) ? v : fallback;
121
+ };
122
+ const pie3D = group && poIs(group, "c:pie3DChart") ? {
123
+ rotX: viewAngle("c:rotX", 0),
124
+ rotY: viewAngle("c:rotY", 0)
125
+ } : void 0;
126
+ const gapDepthRaw = group && poIs(group, "c:bar3DChart") ? Number(poVal(poChildren(group).find((c) => poIs(c, "c:gapDepth"))) ?? NaN) : NaN;
127
+ const bar3D = group && poIs(group, "c:bar3DChart") ? {
128
+ rotX: Math.min(90, Math.max(-90, viewAngle("c:rotX", 0))),
129
+ rotY: (viewAngle("c:rotY", 0) % 360 + 360) % 360,
130
+ depthPercent: Math.min(2e3, Math.max(20, viewAngle("c:depthPercent", 100))),
131
+ gapDepth: Number.isFinite(gapDepthRaw) ? Math.min(500, Math.max(0, gapDepthRaw)) : 150
132
+ } : void 0;
133
+ const floor = bar3D ? surfaceOf(poChildren(chart).find((c) => poIs(c, "c:floor")), resolveColor) : void 0;
134
+ const backWall = bar3D ? surfaceOf(poChildren(chart).find((c) => poIs(c, "c:backWall")), resolveColor) : void 0;
135
+ const sideWall = bar3D ? surfaceOf(poChildren(chart).find((c) => poIs(c, "c:sideWall")), resolveColor) : void 0;
136
+ const plotBox = plotBoxOf(plotArea);
137
+ const firstSliceRaw = group && (poIs(group, "c:pieChart") || poIs(group, "c:doughnutChart")) ? Number(poVal(poChildren(group).find((c) => poIs(c, "c:firstSliceAng")))) : NaN;
138
+ const firstSliceAngle = Number.isFinite(firstSliceRaw) ? firstSliceRaw : void 0;
91
139
  const showValues = group ? chartShowsValues(group) : false;
92
- const catAxisTitle = axisTitle(plotArea, "c:catAx");
93
- const valAxisTitle = axisTitle(plotArea, "c:valAx");
140
+ const dataLabels = dataLabelsOf(group, group ? poChildren(group).find((c) => poIs(c, "c:ser")) : void 0);
94
141
  const catAxNode = poChildren(plotArea).find((c) => poIs(c, "c:catAx"));
95
142
  const valAxNode = poChildren(plotArea).find((c) => poIs(c, "c:valAx"));
96
143
  const axisAt = (...where) => poChildren(plotArea).find((c) => (poIs(c, "c:catAx") || poIs(c, "c:valAx") || poIs(c, "c:dateAx")) && c !== secondaryValAx && where.includes(poVal(poChildren(c).find((k) => poIs(k, "c:axPos"))) ?? ""));
97
144
  const bottomAxNode = axisAt("b", "t") ?? catAxNode;
98
145
  const leftAxNode = axisAt("l", "r") ?? valAxNode;
99
- const catAxisLine = lineStyleOf(bottomAxNode, resolveColor);
100
- const valAxisLine = lineStyleOf(leftAxNode, resolveColor);
146
+ const isScatter = type === "scatter";
147
+ const valRoleAx = isScatter ? leftAxNode : poChildren(plotArea).find((c) => poIs(c, "c:valAx") && c !== secondaryValAx);
148
+ const catRoleAx = isScatter ? bottomAxNode : catAxNode ?? poChildren(plotArea).find((c) => poIs(c, "c:dateAx"));
149
+ const catAxisDeleted = isDeletedAxis(catRoleAx);
150
+ const valAxisDeleted = isDeletedAxis(valRoleAx);
151
+ const ruleOf = (ax) => isDeletedAxis(ax) ? { none: true } : lineStyleOf(ax, resolveColor);
152
+ const catAxisLine = ruleOf(bottomAxNode);
153
+ const valAxisLine = ruleOf(leftAxNode);
101
154
  const secondaryValAxisLine = lineStyleOf(secondaryValAx, resolveColor);
102
- const gridLine = lineStyleOf(leftAxNode ? poChildren(leftAxNode).find((c) => poIs(c, "c:majorGridlines")) : void 0, resolveColor);
103
- const valAxisMin = axisScaling(plotArea, "c:min");
104
- const valAxisMax = axisScaling(plotArea, "c:max");
105
- const valAxisMajorUnit = majorUnitOf(plotArea);
155
+ const gridLine = gridlinesOf(valRoleAx, resolveColor);
156
+ const xGridLine = isScatter ? gridlinesOf(bottomAxNode, resolveColor) : void 0;
157
+ const catAxisTitle = isScatter ? axisTitleOf(bottomAxNode) : axisTitle(plotArea, "c:catAx");
158
+ const valAxisTitle = isScatter ? axisTitleOf(leftAxNode) : axisTitle(plotArea, "c:valAx");
159
+ const valAxisMin = isScatter ? axisScalingOf(leftAxNode, "c:min") : axisScaling(plotArea, "c:min");
160
+ const valAxisMax = isScatter ? axisScalingOf(leftAxNode, "c:max") : axisScaling(plotArea, "c:max");
161
+ const valAxisMajorUnit = isScatter ? majorUnitOfAxis(leftAxNode) : majorUnitOf(plotArea);
162
+ const xAxisMin = isScatter ? axisScalingOf(bottomAxNode, "c:min") : void 0;
163
+ const xAxisMax = isScatter ? axisScalingOf(bottomAxNode, "c:max") : void 0;
164
+ const xAxisMajorUnit = isScatter ? majorUnitOfAxis(bottomAxNode) : void 0;
165
+ const xNumberFormat = isScatter ? formatCodeOf(bottomAxNode) : void 0;
106
166
  const catAxisReversed = axisOrientation(catAxNode) === "maxMin";
107
167
  const catAxisCrosses = axisCrossing(catAxNode);
108
168
  const valAxisCrosses = axisCrossing(valAxNode);
@@ -118,17 +178,32 @@ function parseChart(chartXml, resolveColor, resolveImage) {
118
178
  const plotFillHex = plotSpPr ? frameFillOf(plotSpPr, resolveColor) : void 0;
119
179
  const plotLine = lineStyleOf(plotArea, resolveColor);
120
180
  const frameLineHex = spaceSpPr ? frameLine ? frameFillOf(frameLine, resolveColor) : void 0 : "D9D9D9";
121
- const numberFormat = valueFormatCode(plotArea);
181
+ const numberFormat = isScatter ? formatCodeOf(leftAxNode) : valueFormatCode(plotArea);
122
182
  const legend = poChildren(chart).find((c) => poIs(c, "c:legend"));
123
183
  const legendPos = legend ? poVal(poChildren(legend).find((c) => poIs(c, "c:legendPos"))) : void 0;
184
+ const firstSer = serNodes[0];
185
+ const text = textDefaults ? chartTextStyles({
186
+ ...chartSpace ? { chartSpace } : {},
187
+ ...withNode("title", poChildren(chart).find((c) => poIs(c, "c:title"))),
188
+ ...withNode("legend", legend),
189
+ ...withNode("catAxis", catRoleAx),
190
+ ...withNode("valAxis", valRoleAx),
191
+ ...withNode("secondaryValAxis", secondaryValAx),
192
+ ...withNode("dataLabels", (firstSer ? poChildren(firstSer).find((c) => poIs(c, "c:dLbls")) : void 0) ?? (group ? poChildren(group).find((c) => poIs(c, "c:dLbls")) : void 0))
193
+ }, resolveColor, (fill) => colorFromSolidFill(fill, resolveColor), textDefaults) : void 0;
124
194
  const title = chartTitle(chart, series);
125
195
  const gapNode = poChildren(plotArea).flatMap((g) => poChildren(g)).find((c) => poIs(c, "c:gapWidth"));
126
196
  const gapRaw = gapNode ? poVal(gapNode) : void 0;
127
197
  const gapPercent = gapRaw === void 0 ? NaN : Number(gapRaw);
198
+ const overlapNode = poChildren(plotArea).flatMap((g) => poChildren(g)).find((c) => poIs(c, "c:overlap"));
199
+ const overlapRaw = overlapNode ? poVal(overlapNode) : void 0;
200
+ const overlapPercent = overlapRaw === void 0 ? NaN : Number(overlapRaw);
128
201
  return {
129
202
  type,
130
203
  ...title ? { title } : {},
204
+ ...text ? { text } : {},
131
205
  ...Number.isFinite(gapPercent) && gapPercent >= 0 ? { gapPercent } : {},
206
+ ...Number.isFinite(overlapPercent) && overlapPercent !== 0 ? { overlapPercent: Math.min(100, Math.max(-100, overlapPercent)) } : {},
132
207
  categories,
133
208
  ...categoriesRef ? { categoriesRef } : {},
134
209
  ...categoryGroups && categoryGroups.length > 0 ? { categoryGroups } : {},
@@ -138,7 +213,15 @@ function parseChart(chartXml, resolveColor, resolveImage) {
138
213
  ...barDir === "col" || barDir === "bar" ? { barDir } : {},
139
214
  ...isGrouping(grouping) ? { grouping } : {},
140
215
  ...doughnut ? { doughnut: true } : {},
216
+ ...pie3D ? { pie3D } : {},
217
+ ...bar3D ? { bar3D } : {},
218
+ ...floor ? { floor } : {},
219
+ ...backWall ? { backWall } : {},
220
+ ...sideWall ? { sideWall } : {},
221
+ ...plotBox ? { plotBox } : {},
222
+ ...firstSliceAngle ? { firstSliceAngle } : {},
141
223
  ...showValues ? { showValues: true } : {},
224
+ ...dataLabels ? { dataLabels } : {},
142
225
  ...catAxisTitle ? { catAxisTitle } : {},
143
226
  ...catAxisReversed ? { catAxisReversed } : {},
144
227
  ...catAxisCrosses !== void 0 ? { catAxisCrosses } : {},
@@ -152,9 +235,16 @@ function parseChart(chartXml, resolveColor, resolveImage) {
152
235
  ...valAxisLine ? { valAxisLine } : {},
153
236
  ...secondaryValAxisLine ? { secondaryValAxisLine } : {},
154
237
  ...gridLine ? { gridLine } : {},
238
+ ...xGridLine ? { xGridLine } : {},
239
+ ...catAxisDeleted ? { catAxisDeleted: true } : {},
240
+ ...valAxisDeleted ? { valAxisDeleted: true } : {},
155
241
  ...valAxisMin !== void 0 ? { valAxisMin } : {},
156
242
  ...valAxisMax !== void 0 ? { valAxisMax } : {},
157
243
  ...valAxisMajorUnit !== void 0 ? { valAxisMajorUnit } : {},
244
+ ...xAxisMin !== void 0 ? { xAxisMin } : {},
245
+ ...xAxisMax !== void 0 ? { xAxisMax } : {},
246
+ ...xAxisMajorUnit !== void 0 ? { xAxisMajorUnit } : {},
247
+ ...xNumberFormat ? { xNumberFormat } : {},
158
248
  ...frameFillHex ? { frameFillHex } : {},
159
249
  ...frameFillImage ? { frameFillImage } : {},
160
250
  ...frameLineHex ? { frameLineHex } : {},
@@ -165,15 +255,29 @@ function parseChart(chartXml, resolveColor, resolveImage) {
165
255
  ...numberFormat ? { numberFormat } : {}
166
256
  };
167
257
  }
168
- function parseSeries(ser, resolveColor) {
258
+ /** `{ [role]: node }` when there is a node — the shape `ChartTextNodes` takes. */
259
+ function withNode(role, node) {
260
+ return node ? { [role]: node } : {};
261
+ }
262
+ function parseSeries(ser, resolveColor, most) {
169
263
  const valNode = poChildren(ser).find((c) => poIs(c, "c:val")) ?? poChildren(ser).find((c) => poIs(c, "c:yVal"));
170
- const values = valNode ? denseNumbers(valNode) : [];
264
+ const values = valNode ? denseNumbers(valNode, most) : [];
171
265
  const xValNode = poChildren(ser).find((c) => poIs(c, "c:xVal"));
172
- const xValues = xValNode ? denseNumbers(xValNode) : void 0;
266
+ const xValues = xValNode ? denseNumbers(xValNode, most) : void 0;
173
267
  const name = seriesName(ser);
174
268
  const colorHex = fillColorOf(poChildren(ser).find((c) => poIs(c, "c:spPr")), resolveColor);
175
269
  const pointColors = dataPointColors(ser, resolveColor);
176
270
  const pointLabels = customDataLabels(ser);
271
+ const explosion = explosionOf(ser);
272
+ const pointExplosions = poChildren(ser).filter((c) => poIs(c, "c:dPt")).flatMap((dPt) => {
273
+ const percent = explosionOf(dPt);
274
+ const idx = poIntAttr(poChildren(dPt).find((c) => poIs(c, "c:idx")), "val");
275
+ return percent !== void 0 && idx !== void 0 ? [{
276
+ idx,
277
+ percent
278
+ }] : [];
279
+ });
280
+ const pointLabelPlacements = labelPlacements(ser);
177
281
  const marker = seriesMarker(ser);
178
282
  const line = lineStyleOf(ser, resolveColor);
179
283
  const valuesRef = valNode ? refFormula(valNode) : void 0;
@@ -187,11 +291,14 @@ function parseSeries(ser, resolveColor) {
187
291
  ...colorHex ? { colorHex } : {},
188
292
  ...pointColors.length > 0 ? { pointColors } : {},
189
293
  ...pointLabels.length > 0 ? { pointLabels } : {},
294
+ ...explosion ? { explosion } : {},
295
+ ...pointExplosions.length > 0 ? { pointExplosions } : {},
296
+ ...pointLabelPlacements.length > 0 ? { pointLabelPlacements } : {},
190
297
  ...marker ? { marker } : {},
191
298
  ...line ? { line } : {}
192
299
  };
193
300
  }
194
- var MARKER_SYMBOLS = new Set([
301
+ var MARKER_SYMBOLS = /* @__PURE__ */ new Set([
195
302
  "circle",
196
303
  "dash",
197
304
  "diamond",
@@ -230,6 +337,43 @@ function seriesName(ser) {
230
337
  * its own `<c:tx><c:rich>` replaces whatever the chart would have computed for
231
338
  * that point, and it is the only place that text exists.
232
339
  */
340
+ /**
341
+ * §21.2.2.104 — the plot area's box where the author sized it: `edge` mode,
342
+ * every one of x, y, w and h stated, each a fraction of the chart.
343
+ */
344
+ function plotBoxOf(plotArea) {
345
+ const layout = poChildren(plotArea).find((c) => poIs(c, "c:layout"));
346
+ const manual = layout ? poChildren(layout).find((c) => poIs(c, "c:manualLayout")) : void 0;
347
+ if (!manual) return void 0;
348
+ const kids = poChildren(manual);
349
+ const val = (tag) => poVal(kids.find((c) => poIs(c, tag)));
350
+ if (val("c:xMode") !== "edge" || val("c:yMode") !== "edge") return void 0;
351
+ const [x, y, w, h] = [
352
+ "c:x",
353
+ "c:y",
354
+ "c:w",
355
+ "c:h"
356
+ ].map((tag) => Number(val(tag)));
357
+ if (![
358
+ x,
359
+ y,
360
+ w,
361
+ h
362
+ ].every((v) => v !== void 0 && Number.isFinite(v))) return void 0;
363
+ if (w <= 0 || h <= 0) return void 0;
364
+ return {
365
+ x,
366
+ y,
367
+ w,
368
+ h,
369
+ ...val("c:layoutTarget") === "inner" ? { inner: true } : {}
370
+ };
371
+ }
372
+ /** §21.2.2.61 `c:explosion` — a percentage of the pie's radius, at most 400. */
373
+ function explosionOf(owner) {
374
+ const v = Number(poVal(poChildren(owner).find((c) => poIs(c, "c:explosion"))));
375
+ return Number.isFinite(v) && v >= 0 ? Math.min(v, 400) : void 0;
376
+ }
233
377
  function customDataLabels(ser) {
234
378
  const dLbls = poChildren(ser).find((c) => poIs(c, "c:dLbls"));
235
379
  if (!dLbls) return [];
@@ -375,11 +519,14 @@ function cachedTitleText(title) {
375
519
  const tx = poChildren(title).find((c) => poIs(c, "c:tx"));
376
520
  const ref = tx ? poChildren(tx).find((c) => poIs(c, "c:strRef")) : void 0;
377
521
  if (!ref) return void 0;
378
- const cached = denseStrings(ref).filter((t) => t.length > 0);
522
+ const cached = denseStrings(ref, MOST_CHART_POINTS).filter((t) => t.length > 0);
379
523
  return cached.length > 0 ? cached.join(" ") : void 0;
380
524
  }
381
525
  function axisTitle(plotArea, axTag) {
382
- const ax = poChildren(plotArea).find((c) => poIs(c, axTag));
526
+ return axisTitleOf(poChildren(plotArea).find((c) => poIs(c, axTag)));
527
+ }
528
+ /** An axis node's own `c:title` text. */
529
+ function axisTitleOf(ax) {
383
530
  const title = ax ? poChildren(ax).find((c) => poIs(c, "c:title")) : void 0;
384
531
  if (!title) return void 0;
385
532
  return collectAT(title) || cachedTitleText(title) || "Axis Title";
@@ -411,15 +558,19 @@ function axisOrientation(ax) {
411
558
  const scaling = ax ? poChildren(ax).find((c) => poIs(c, "c:scaling")) : void 0;
412
559
  return scaling ? poVal(poChildren(scaling).find((c) => poIs(c, "c:orientation"))) : void 0;
413
560
  }
414
- /** §21.2.2.98 `c:valAx/c:majorUnit` — a positive step, or undefined for "auto". */
561
+ /** §21.2.2.103 `c:valAx/c:majorUnit` — a positive step, or undefined for "auto". */
415
562
  function majorUnitOf(plotArea) {
416
- const ax = poChildren(plotArea).find((c) => poIs(c, "c:valAx"));
563
+ return majorUnitOfAxis(poChildren(plotArea).find((c) => poIs(c, "c:valAx")));
564
+ }
565
+ function majorUnitOfAxis(ax) {
417
566
  const node = ax ? poChildren(ax).find((c) => poIs(c, "c:majorUnit")) : void 0;
418
567
  const v = node ? Number(poAttr(node, "val")) : NaN;
419
568
  return Number.isFinite(v) && v > 0 ? v : void 0;
420
569
  }
421
570
  function axisScaling(plotArea, tag) {
422
- const ax = poChildren(plotArea).find((c) => poIs(c, "c:valAx"));
571
+ return axisScalingOf(poChildren(plotArea).find((c) => poIs(c, "c:valAx")), tag);
572
+ }
573
+ function axisScalingOf(ax, tag) {
423
574
  const scaling = ax ? poChildren(ax).find((c) => poIs(c, "c:scaling")) : void 0;
424
575
  const node = scaling ? poChildren(scaling).find((c) => poIs(c, tag)) : void 0;
425
576
  const v = node ? Number(poAttr(node, "val")) : NaN;
@@ -436,7 +587,7 @@ function axisScaling(plotArea, tag) {
436
587
  * @param resolveColor Maps a DrawingML colour reference to 6 hex digits.
437
588
  * @returns The rule, or undefined when the node says nothing about it.
438
589
  */
439
- var DASHES = new Set([
590
+ var DASHES = /* @__PURE__ */ new Set([
440
591
  "solid",
441
592
  "dot",
442
593
  "dash",
@@ -446,6 +597,30 @@ var DASHES = new Set([
446
597
  "sysDash",
447
598
  "sysDot"
448
599
  ]);
600
+ /** A 3-D chart's wall or floor: what its `c:spPr` fills and rules it with. */
601
+ function surfaceOf(node, resolveColor) {
602
+ const spPr = node ? poChildren(node).find((c) => poIs(c, "c:spPr")) : void 0;
603
+ if (!spPr) return void 0;
604
+ const fillHex = frameFillOf(spPr, resolveColor);
605
+ const line = lineStyleOf(node, resolveColor);
606
+ return {
607
+ ...fillHex ? { fillHex } : {},
608
+ ...line ? { line } : {}
609
+ };
610
+ }
611
+ /** §21.2.2.40 — whether the author deleted an axis. */
612
+ function isDeletedAxis(ax) {
613
+ const del = ax ? poVal(poChildren(ax).find((c) => poIs(c, "c:delete"))) : void 0;
614
+ return del === "1" || del === "true";
615
+ }
616
+ /**
617
+ * §21.2.2.100 — an axis's major gridlines: their rule, the default one where
618
+ * they state none (undefined), and none at all where the axis has none.
619
+ */
620
+ function gridlinesOf(ax, resolveColor) {
621
+ const grid = ax ? poChildren(ax).find((c) => poIs(c, "c:majorGridlines")) : void 0;
622
+ return grid ? lineStyleOf(grid, resolveColor) : { none: true };
623
+ }
449
624
  function lineStyleOf(owner, resolveColor) {
450
625
  const spPr = owner ? poChildren(owner).find((c) => poIs(c, "c:spPr")) : void 0;
451
626
  const ln = spPr ? poChildren(spPr).find((c) => poIs(c, "a:ln")) : void 0;
@@ -466,7 +641,9 @@ function lineStyleOf(owner, resolveColor) {
466
641
  };
467
642
  }
468
643
  function valueFormatCode(plotArea) {
469
- const ax = poChildren(plotArea).find((c) => poIs(c, "c:valAx"));
644
+ return formatCodeOf(poChildren(plotArea).find((c) => poIs(c, "c:valAx")));
645
+ }
646
+ function formatCodeOf(ax) {
470
647
  const numFmt = ax ? poChildren(ax).find((c) => poIs(c, "c:numFmt")) : void 0;
471
648
  const code = numFmt ? poAttr(numFmt, "formatCode") : void 0;
472
649
  if (code === void 0 || code.trim().length === 0) return void 0;
@@ -477,6 +654,107 @@ function dLblsShowVal(dLbls) {
477
654
  const v = poVal(poChildren(dLbls).find((c) => poIs(c, "c:showVal")));
478
655
  return v === "1" || v === "true";
479
656
  }
657
+ /**
658
+ * §21.2.2.49 — what a chart's data labels show: its group's `c:dLbls` with the
659
+ * first series' own over it. `c:delete` shows nothing; a chart with no
660
+ * `c:dLbls` anywhere has no labels, which is not a chart that shows its
661
+ * percentages — Excel prints nothing on such a pie.
662
+ *
663
+ * @param group The chart group (`c:pieChart`, …).
664
+ * @param firstSer Its first series.
665
+ * @returns The switches, or undefined for a chart without data labels.
666
+ */
667
+ function dataLabelsOf(group, firstSer) {
668
+ const own = (owner) => owner ? poChildren(owner).find((c) => poIs(c, "c:dLbls")) : void 0;
669
+ const groupLabels = own(group);
670
+ const seriesLabels = own(firstSer);
671
+ if (!groupLabels && !seriesLabels) return void 0;
672
+ const read = (dLbls) => {
673
+ if (!dLbls) return {};
674
+ const kids = poChildren(dLbls);
675
+ const deleted = poVal(kids.find((c) => poIs(c, "c:delete")));
676
+ if (deleted === "1" || deleted === "true") return {
677
+ showVal: false,
678
+ showCatName: false,
679
+ showSerName: false,
680
+ showPercent: false
681
+ };
682
+ const flag = (tag) => {
683
+ const v = poVal(kids.find((c) => poIs(c, tag)));
684
+ return v === void 0 ? {} : { [tag.slice(2)]: v === "1" || v === "true" };
685
+ };
686
+ const separatorNode = kids.find((c) => poIs(c, "c:separator"));
687
+ const numFmt = kids.find((c) => poIs(c, "c:numFmt"));
688
+ const code = numFmt ? poAttr(numFmt, "formatCode") : void 0;
689
+ const linked = numFmt ? poAttr(numFmt, "sourceLinked") : void 0;
690
+ const position = labelPosition(kids);
691
+ return {
692
+ ...flag("c:showVal"),
693
+ ...flag("c:showCatName"),
694
+ ...flag("c:showSerName"),
695
+ ...flag("c:showPercent"),
696
+ ...flag("c:showLeaderLines"),
697
+ ...position ? { position } : {},
698
+ ...separatorNode ? { separator: poText(separatorNode) } : {},
699
+ ...code && code.trim() !== "" && code.trim().toLowerCase() !== "general" && linked !== "1" ? { numberFormat: code } : {}
700
+ };
701
+ };
702
+ return {
703
+ ...read(groupLabels),
704
+ ...read(seriesLabels)
705
+ };
706
+ }
707
+ var LABEL_POSITIONS = /* @__PURE__ */ new Set([
708
+ "bestFit",
709
+ "b",
710
+ "ctr",
711
+ "inBase",
712
+ "inEnd",
713
+ "l",
714
+ "outEnd",
715
+ "r",
716
+ "t"
717
+ ]);
718
+ /** §21.2.2.48 — a label's `c:dLblPos` among its siblings, when it states one. */
719
+ function labelPosition(kids) {
720
+ const v = poVal(kids.find((c) => poIs(c, "c:dLblPos")));
721
+ return v !== void 0 && LABEL_POSITIONS.has(v) ? v : void 0;
722
+ }
723
+ /**
724
+ * §21.2.2.47 — where each point's own label stands, for the points that say:
725
+ * their `c:dLblPos`, and the `c:manualLayout` an author dragged them to
726
+ * (45544.xlsx sets every one of its slices' names out by hand).
727
+ */
728
+ function labelPlacements(ser) {
729
+ const dLbls = poChildren(ser).find((c) => poIs(c, "c:dLbls"));
730
+ if (!dLbls) return [];
731
+ const out = [];
732
+ for (const dLbl of poChildren(dLbls)) {
733
+ if (!poIs(dLbl, "c:dLbl")) continue;
734
+ const kids = poChildren(dLbl);
735
+ const idx = poIntAttr(kids.find((c) => poIs(c, "c:idx")), "val") ?? 0;
736
+ const position = labelPosition(kids);
737
+ const layout = kids.find((c) => poIs(c, "c:layout"));
738
+ const manual = layout ? poChildren(layout).find((c) => poIs(c, "c:manualLayout")) : void 0;
739
+ const num = (tag) => {
740
+ const v = Number(poVal(manual ? poChildren(manual).find((c) => poIs(c, tag)) : void 0));
741
+ return Number.isFinite(v) ? v : void 0;
742
+ };
743
+ const x = num("c:x");
744
+ const y = num("c:y");
745
+ const mode = (tag) => poVal(manual ? poChildren(manual).find((c) => poIs(c, tag)) : void 0);
746
+ const edge = mode("c:xMode") === "edge" && mode("c:yMode") === "edge";
747
+ if (position === void 0 && x === void 0 && y === void 0) continue;
748
+ out.push({
749
+ idx,
750
+ ...position ? { position } : {},
751
+ ...x !== void 0 ? { x } : {},
752
+ ...y !== void 0 ? { y } : {},
753
+ ...edge ? { edge: true } : {}
754
+ });
755
+ }
756
+ return out;
757
+ }
480
758
  function chartShowsValues(group) {
481
759
  if (dLblsShowVal(poChildren(group).find((c) => poIs(c, "c:dLbls")))) return true;
482
760
  for (const ser of poChildren(group)) if (poIs(ser, "c:ser") && dLblsShowVal(poChildren(ser).find((c) => poIs(c, "c:dLbls")))) return true;
@@ -509,24 +787,36 @@ function ptCountOf(container) {
509
787
  const pc = cache ? poChildren(cache).find((c) => poIs(c, "c:ptCount")) : void 0;
510
788
  return pc ? poIntAttr(pc, "val") ?? 0 : 0;
511
789
  }
512
- function denseLength(container, pts) {
513
- let max = ptCountOf(container);
514
- for (const p of pts) max = Math.max(max, p.idx + 1);
515
- return max;
790
+ /** Whether `n` can index a point: a whole number from zero. */
791
+ var isPointIndex = (n) => Number.isInteger(n) && n >= 0;
792
+ /**
793
+ * How many slots `count` points and those at `indexes` take — the count, or
794
+ * past it the last of them, and never more than `most`. A count or an index
795
+ * that is no whole number (2.5) asked for an array of no possible length and
796
+ * threw; it counts for nothing.
797
+ */
798
+ function denseLength(count, indexes, most) {
799
+ let length = isPointIndex(count) ? count : 0;
800
+ for (const idx of indexes) if (isPointIndex(idx)) length = Math.max(length, idx + 1);
801
+ return Math.min(length, most);
516
802
  }
517
- function denseNumbers(container) {
803
+ /** A cache's values by point index, gaps 0, at most `most` of them. */
804
+ function denseNumbers(container, most) {
518
805
  const pts = readPts(container);
519
- const arr = new Array(denseLength(container, pts)).fill(0);
806
+ const length = denseLength(ptCountOf(container), pts.map((p) => p.idx), most);
807
+ const arr = new Array(length).fill(0);
520
808
  for (const p of pts) {
521
809
  const n = Number(p.v);
522
- if (Number.isFinite(n)) arr[p.idx] = n;
810
+ if (Number.isFinite(n) && isPointIndex(p.idx) && p.idx < length) arr[p.idx] = n;
523
811
  }
524
812
  return arr;
525
813
  }
526
- function denseStrings(container) {
814
+ /** A cache's texts by point index, gaps empty, at most `most` of them. */
815
+ function denseStrings(container, most) {
527
816
  const pts = readPts(container);
528
- const arr = new Array(denseLength(container, pts)).fill("");
529
- for (const p of pts) arr[p.idx] = p.v;
817
+ const length = denseLength(ptCountOf(container), pts.map((p) => p.idx), most);
818
+ const arr = new Array(length).fill("");
819
+ for (const p of pts) if (isPointIndex(p.idx) && p.idx < length) arr[p.idx] = p.v;
530
820
  return arr;
531
821
  }
532
822
  /**
@@ -537,11 +827,12 @@ function denseStrings(container) {
537
827
  * names, both columns of them in turn: WithChartSheet.xlsx's six bars stood in
538
828
  * the first six of sixteen slots under a jumble of years and measure names.
539
829
  *
540
- * @param cat The `c:cat` element.
830
+ * @param cat The `c:cat` element.
831
+ * @param most The most categories it keeps (see {@link pointsPerSeries}).
541
832
  * @returns The innermost labels and the outer levels' groups, or undefined
542
833
  * for a category axis of one level.
543
834
  */
544
- function multiLevelCategories(cat) {
835
+ function multiLevelCategories(cat, most) {
545
836
  const cache = poFindDescendant(cat, "c:multiLvlStrCache");
546
837
  if (!cache) return void 0;
547
838
  const count = poIntAttr(poChildren(cache).find((c) => poIs(c, "c:ptCount")) ?? cache, "val") ?? 0;
@@ -553,11 +844,13 @@ function multiLevelCategories(cat) {
553
844
  };
554
845
  }));
555
846
  if (!inner) return void 0;
556
- const categories = new Array(Math.max(count, ...inner.map((p) => p.start + 1))).fill("");
557
- for (const p of inner) categories[p.start] = p.label;
847
+ const length = denseLength(count, inner.map((p) => p.start), most);
848
+ const categories = new Array(length).fill("");
849
+ const kept = (p) => isPointIndex(p.start) && p.start < length;
850
+ for (const p of inner) if (kept(p)) categories[p.start] = p.label;
558
851
  return {
559
852
  categories,
560
- groups: outer.map((level) => [...level].sort((a, b) => a.start - b.start))
853
+ groups: outer.map((level) => level.filter(kept).sort((a, b) => a.start - b.start))
561
854
  };
562
855
  }
563
856
  function isLegendPos(v) {
@@ -626,7 +919,7 @@ var ACCENT_SLOTS = [
626
919
  "accent5",
627
920
  "accent6"
628
921
  ];
629
- var SCATTER_STYLES = new Set([
922
+ var SCATTER_STYLES = /* @__PURE__ */ new Set([
630
923
  "none",
631
924
  "line",
632
925
  "lineMarker",
@@ -636,4 +929,4 @@ var SCATTER_STYLES = new Set([
636
929
  ]);
637
930
  var REL_CHART_COLOR_STYLE = "http://schemas.microsoft.com/office/2011/relationships/chartColorStyle";
638
931
  //#endregion
639
- export { parseChart, withChartColorStyle };
932
+ export { MOST_CHART_POINTS, parseChart, parseChartColorStyle, pointsPerSeries, withChartColorStyle };
@@ -0,0 +1,41 @@
1
+ import { PoNode } from '../po-helpers.js';
2
+ import { ChartTextStyles } from '../document-model/index.js';
3
+ import { ColorResolver } from './colors.js';
4
+ import { ThemeFonts } from './theme-parser.js';
5
+ /**
6
+ * What a host application sets the chart text a chart leaves unsaid in.
7
+ * Passing it asks for the text to be resolved at all; without it a chart
8
+ * carries no {@link ChartTextStyles} and the renderer keeps its own defaults.
9
+ */
10
+ export interface ChartTextDefaults {
11
+ /** The theme's font scheme — what `+mn-lt` and `+mj-lt` stand for. */
12
+ readonly themeFonts?: ThemeFonts;
13
+ /** The family of text no run names. */
14
+ readonly family?: string;
15
+ }
16
+ /** Excel's size for chart text no run sizes. */
17
+ export declare const EXCEL_CHART_TEXT_PT = 10;
18
+ /** The nodes each role's own text properties hang from. */
19
+ export interface ChartTextNodes {
20
+ readonly chartSpace?: PoNode;
21
+ readonly title?: PoNode;
22
+ readonly legend?: PoNode;
23
+ readonly catAxis?: PoNode;
24
+ readonly valAxis?: PoNode;
25
+ readonly secondaryValAxis?: PoNode;
26
+ /** `c:dLbls` — the first series' own, else its group's. */
27
+ readonly dataLabels?: PoNode;
28
+ }
29
+ /** Reads an `a:solidFill` as a chart reads it, to RRGGBB. */
30
+ export type ChartFillReader = (solidFill: PoNode) => string | undefined;
31
+ /**
32
+ * Resolve a chart's text, role by role: the element's own run properties over
33
+ * the chart's over the host's defaults.
34
+ *
35
+ * @param nodes Where each role's properties hang.
36
+ * @param resolveColor Maps a colour reference to RRGGBB — the default text colour.
37
+ * @param readFill Reads a run's `a:solidFill`.
38
+ * @param defaults The host's defaults and theme fonts.
39
+ * @returns Every role, resolved.
40
+ */
41
+ export declare function chartTextStyles(nodes: ChartTextNodes, resolveColor: ColorResolver, readFill: ChartFillReader, defaults: ChartTextDefaults): ChartTextStyles;