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.
- package/README.md +5 -4
- package/dist/esm/core/bidi/algorithm.js +2 -2
- package/dist/esm/core/bidi/char-types.js +1 -1
- package/dist/esm/core/bidi/index.js +3 -3
- package/dist/esm/core/bytes.js +1 -1
- package/dist/esm/core/converter/facade.js +3 -2
- package/dist/esm/core/converter/ream.js +12 -5
- package/dist/esm/core/crypto/asn1.js +2 -2
- package/dist/esm/core/crypto/cms.js +5 -3
- package/dist/esm/core/crypto/index.js +2 -1
- package/dist/esm/core/crypto/offcrypto.js +64 -19
- package/dist/esm/core/crypto/primitives.js +16 -16
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +174 -2
- package/dist/esm/core/drawingml/chart-geometry.d.ts +45 -17
- package/dist/esm/core/drawingml/chart-geometry.js +1090 -257
- package/dist/esm/core/drawingml/chart-parser.d.ts +24 -1
- package/dist/esm/core/drawingml/chart-parser.js +334 -41
- package/dist/esm/core/drawingml/chart-text.d.ts +41 -0
- package/dist/esm/core/drawingml/chart-text.js +93 -0
- package/dist/esm/core/drawingml/colors.js +5 -5
- package/dist/esm/core/drawingml/diagram/layout-engine.js +1 -4
- package/dist/esm/core/drawingml/diagram/run.js +2 -1
- package/dist/esm/core/drawingml/preset-geometry.js +4 -6
- package/dist/esm/core/drawingml/shape-render.js +1 -1
- package/dist/esm/core/drawingml/text-warp.js +4 -16
- package/dist/esm/core/drawingml/theme-parser.js +14 -8
- package/dist/esm/core/font/arabic-joining.js +2 -2
- package/dist/esm/core/font/binary-reader.js +2 -0
- package/dist/esm/core/font/font-registry.js +1 -0
- package/dist/esm/core/font/ligatures.js +1 -1
- package/dist/esm/core/font/opentype-layout.js +11 -5
- package/dist/esm/core/font/ttf-build.js +6 -10
- package/dist/esm/core/font/ttf-parser.js +2 -1
- package/dist/esm/core/font/ttf-subset.js +8 -8
- package/dist/esm/core/fonts/families.js +1 -1
- package/dist/esm/core/fonts/remote-fonts.js +4 -4
- package/dist/esm/core/hyphenation/index.js +1 -1
- package/dist/esm/core/images.js +8 -8
- package/dist/esm/core/ir/loss.js +1 -0
- package/dist/esm/core/line-breaker/cjk.js +1 -1
- package/dist/esm/core/line-breaker/index.js +4 -3
- package/dist/esm/core/links.js +1 -1
- package/dist/esm/core/lzw.js +1 -1
- package/dist/esm/core/metafile/blit.js +1 -1
- package/dist/esm/core/metafile/emf.js +5 -7
- package/dist/esm/core/metafile/picture.js +1 -1
- package/dist/esm/core/metafile/symbol-fonts.js +7 -7
- package/dist/esm/core/metafile/wmf.js +5 -7
- package/dist/esm/core/number-format.d.ts +40 -15
- package/dist/esm/core/number-format.js +284 -79
- package/dist/esm/core/numbering/index.js +3 -2
- package/dist/esm/core/ole/cfb.js +4 -4
- package/dist/esm/core/ole/escher-blip.js +1 -1
- package/dist/esm/core/opc/index.js +5 -4
- package/dist/esm/core/opc/package.js +3 -1
- package/dist/esm/core/opc/tag-scan.d.ts +15 -0
- package/dist/esm/core/opc/tag-scan.js +41 -0
- package/dist/esm/core/opc/xml-entities.js +40 -3
- package/dist/esm/core/outline.js +1 -1
- package/dist/esm/core/png-encode.js +3 -3
- package/dist/esm/core/po-helpers.js +1 -1
- package/dist/esm/core/spreadsheet-model/types.d.ts +6 -0
- package/dist/esm/core/style-cascade/index.js +4 -3
- package/dist/esm/core/tiff.js +3 -1
- package/dist/esm/excel/activex-parser.js +1 -1
- package/dist/esm/excel/conditional-format.js +7 -7
- package/dist/esm/excel/formula/functions.js +45 -18
- package/dist/esm/excel/formula/index.js +3 -3
- package/dist/esm/excel/formula/lexer.js +2 -2
- package/dist/esm/excel/formula/parser.js +4 -3
- package/dist/esm/excel/formula/value.js +1 -1
- package/dist/esm/excel/index.js +7 -6
- package/dist/esm/excel/print-model.js +18 -7
- package/dist/esm/excel/printer-settings.js +6 -7
- package/dist/esm/excel/rich-value.js +1 -1
- package/dist/esm/excel/sheet-shape-parser.js +4 -2
- package/dist/esm/excel/sheet-to-flow.js +13 -11
- package/dist/esm/excel/styles-parser.js +5 -3
- package/dist/esm/excel/tint.js +5 -5
- package/dist/esm/excel/vml-drawing.js +3 -3
- package/dist/esm/excel/worksheet-parser.js +5 -5
- package/dist/esm/excel/xls/biff-chart.js +1 -3
- package/dist/esm/excel/xls/biff-reader.js +10 -11
- package/dist/esm/excel/xls/xls-reader.js +1 -1
- package/dist/esm/excel/xlsx-reader.js +56 -9
- package/dist/esm/excel/xlsx-to-pdf.js +1 -1
- package/dist/esm/excel/xlsx-writer.js +2 -2
- package/dist/esm/html/html-writer.js +18 -10
- package/dist/esm/layout/line-paint.js +1 -1
- package/dist/esm/layout/math-layout.js +5 -8
- package/dist/esm/layout/styled-layout.js +104 -32
- package/dist/esm/layout/turned-section.js +2 -2
- package/dist/esm/markdown/markdown-writer.js +59 -8
- package/dist/esm/pdf/encryption.js +9 -9
- package/dist/esm/pdf/icc-profile.js +2 -2
- package/dist/esm/pdf/index.js +3 -2
- package/dist/esm/pdf/objects.js +7 -0
- package/dist/esm/pdf/serialize.js +1 -1
- package/dist/esm/pdf/struct-tree.js +3 -1
- package/dist/esm/pdf/styled-page-emitter.js +23 -15
- package/dist/esm/pdf/styled-page-renderer.js +9 -5
- package/dist/esm/pdf-reader/annot-draw.js +5 -5
- package/dist/esm/pdf-reader/annots.js +3 -1
- package/dist/esm/pdf-reader/ccitt.js +2 -1
- package/dist/esm/pdf-reader/cff-outline.js +1 -4
- package/dist/esm/pdf-reader/content.js +13 -15
- package/dist/esm/pdf-reader/decrypt.js +5 -4
- package/dist/esm/pdf-reader/document.js +6 -2
- package/dist/esm/pdf-reader/encodings.js +1 -1
- package/dist/esm/pdf-reader/flow-build.js +4 -6
- package/dist/esm/pdf-reader/font.js +4 -4
- package/dist/esm/pdf-reader/function.js +8 -7
- package/dist/esm/pdf-reader/icc.js +1 -1
- package/dist/esm/pdf-reader/images.js +1 -1
- package/dist/esm/pdf-reader/jbig2.js +36 -38
- package/dist/esm/pdf-reader/jpeg.js +14 -13
- package/dist/esm/pdf-reader/layout.js +13 -10
- package/dist/esm/pdf-reader/lexer.js +2 -1
- package/dist/esm/pdf-reader/math-rows.js +2 -2
- package/dist/esm/pdf-reader/optional-content.js +1 -1
- package/dist/esm/pdf-reader/page-numbers.js +1 -1
- package/dist/esm/pdf-reader/pattern-tint.js +1 -2
- package/dist/esm/pdf-reader/reader.js +2 -2
- package/dist/esm/pdf-reader/struct-tree.js +1 -1
- package/dist/esm/pdf-reader/tagged.js +3 -2
- package/dist/esm/pdf-reader/text.js +2 -2
- package/dist/esm/pdf-reader/type1-outline.js +1 -3
- package/dist/esm/pptx/embedded-fonts.js +3 -5
- package/dist/esm/pptx/placeholder-cascade.js +1 -1
- package/dist/esm/pptx/ppt/ppt-reader.js +5 -4
- package/dist/esm/pptx/ppt/ppt-text.js +9 -10
- package/dist/esm/pptx/pptx-reader.js +6 -5
- package/dist/esm/pptx/preset-table-styles.js +1 -1
- package/dist/esm/pptx/slide-parser.js +6 -4
- package/dist/esm/pptx/sp-helpers.js +1 -1
- package/dist/esm/pptx/table-style.js +2 -1
- package/dist/esm/svg/svg-writer.js +1 -1
- package/dist/esm/word/doc/doc-reader.js +2 -2
- package/dist/esm/word/doc/doc-text.js +20 -22
- package/dist/esm/word/document-parser.js +27 -22
- package/dist/esm/word/docx-reader.js +15 -10
- package/dist/esm/word/docx-to-pdf.js +6 -6
- package/dist/esm/word/docx-writer.js +10 -6
- package/dist/esm/word/drawing-parser.js +18 -18
- package/dist/esm/word/font-table.js +90 -11
- package/dist/esm/word/index.js +6 -5
- package/dist/esm/word/numbering-parser.js +5 -4
- package/dist/esm/word/omml-parser.js +1 -1
- package/dist/esm/word/paragraph-properties.js +11 -10
- package/dist/esm/word/run-properties.js +4 -4
- package/dist/esm/word/settings-parser.js +2 -1
- package/dist/esm/word/shading.js +1 -1
- package/dist/esm/word/styles-parser.js +5 -4
- package/dist/esm/word/table-parser.js +4 -4
- package/dist/esm/word/theme-fonts.js +1 -1
- 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
|
|
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
|
|
100
|
-
const
|
|
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 =
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
561
|
+
/** §21.2.2.103 `c:valAx/c:majorUnit` — a positive step, or undefined for "auto". */
|
|
415
562
|
function majorUnitOf(plotArea) {
|
|
416
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
529
|
-
|
|
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
|
|
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
|
|
557
|
-
|
|
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) =>
|
|
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;
|