@pixerate/editor 0.162.1 → 0.163.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 +1 -1
- package/dist/agent/index.cjs +34 -34
- package/dist/agent/index.js +5 -5
- package/dist/canvas/index.cjs +6 -6
- package/dist/canvas/index.js +2 -2
- package/dist/chart/commands.d.cts +2 -1
- package/dist/chart/commands.d.ts +2 -1
- package/dist/chart/controller.d.cts +109 -1
- package/dist/chart/controller.d.ts +109 -1
- package/dist/chart/index.cjs +605 -130
- package/dist/chart/index.d.cts +1 -0
- package/dist/chart/index.d.ts +1 -0
- package/dist/chart/index.js +490 -15
- package/dist/chart/layout-annotations.d.cts +29 -0
- package/dist/chart/layout-annotations.d.ts +29 -0
- package/dist/chart/layout-families.d.cts +23 -0
- package/dist/chart/layout-families.d.ts +23 -0
- package/dist/chart/mermaid.d.cts +2 -1
- package/dist/chart/mermaid.d.ts +2 -1
- package/dist/chart/schemas.d.cts +13 -0
- package/dist/chart/schemas.d.ts +13 -0
- package/dist/chart/spec.d.cts +30 -5
- package/dist/chart/spec.d.ts +30 -5
- package/dist/chart/stats.d.cts +9 -1
- package/dist/chart/stats.d.ts +9 -1
- package/dist/chart/tools.d.cts +1 -1
- package/dist/chart/tools.d.ts +1 -1
- package/dist/chart/tree.d.cts +62 -0
- package/dist/chart/tree.d.ts +62 -0
- package/dist/chart/types.d.cts +77 -3
- package/dist/chart/types.d.ts +77 -3
- package/dist/{chunk-7YBDRJXT.cjs → chunk-22KLZZGH.cjs} +8 -8
- package/dist/{chunk-HLOKB7WW.js → chunk-3NEZJCBY.js} +366 -6
- package/dist/{chunk-EVPZ5IKN.js → chunk-5FNGLV2D.js} +65 -3
- package/dist/{chunk-EQ46F75O.cjs → chunk-D54JHQK2.cjs} +51 -51
- package/dist/{chunk-NO5QQDHZ.js → chunk-DAPQGA55.js} +2 -2
- package/dist/{chunk-3IHNXRUV.cjs → chunk-GKNEJ6EN.cjs} +399 -67
- package/dist/{chunk-4NGVHHJB.cjs → chunk-NZD2MZJC.cjs} +80 -18
- package/dist/{chunk-CX6JLDFC.js → chunk-OXERWBKE.js} +3 -3
- package/dist/{chunk-7CKPUUN4.js → chunk-POR54B55.js} +61 -10
- package/dist/{chunk-LL3H5XUH.cjs → chunk-R3P2M7HU.cjs} +367 -7
- package/dist/{chunk-HDGBM7EA.cjs → chunk-SBQVEBSU.cjs} +580 -53
- package/dist/{chunk-XDCFJEU7.js → chunk-SZA42R4N.js} +346 -14
- package/dist/{chunk-GLMP22FT.js → chunk-TALQONZ5.js} +3 -3
- package/dist/{chunk-NA4UVVJ4.cjs → chunk-YGG7WDWT.cjs} +76 -25
- package/dist/{chunk-EY22AY6R.cjs → chunk-YSAGBIRW.cjs} +16 -16
- package/dist/{chunk-DTSTNRPH.js → chunk-Z4P2RBMJ.js} +536 -9
- package/dist/export/index.cjs +4 -4
- package/dist/export/index.js +3 -3
- package/dist/extensions/index.cjs +7 -7
- package/dist/extensions/index.js +6 -6
- package/dist/index.cjs +13 -13
- package/dist/index.js +7 -7
- package/dist/paint-editor/index.cjs +0 -20
- package/dist/paint-editor/index.js +0 -20
- package/package.json +1 -1
- package/skills/pixerate-canvas/SKILL.md +16 -0
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
var _chunkR3P2M7HUcjs = require('./chunk-R3P2M7HU.cjs');
|
|
18
21
|
|
|
19
22
|
// src/chart/schemas.ts
|
|
20
23
|
var VALUE = { type: ["number", "string", "null"], description: 'A number, numeric text ("1,200", "12%", "$40", "(3)") or null for a gap.' };
|
|
@@ -26,7 +29,7 @@ var FORMAT = {
|
|
|
26
29
|
type: "object",
|
|
27
30
|
description: "How numbers are written on this axis or series.",
|
|
28
31
|
properties: {
|
|
29
|
-
style: { type: "string", enum: [...
|
|
32
|
+
style: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_NUMBER_STYLES], description: "number (default), percent (0.25 \u2192 25%), currency or compact (1.2K)." },
|
|
30
33
|
decimals: { type: "integer", minimum: 0, maximum: 10, description: "Fixed decimals (default: what the ticks need)." },
|
|
31
34
|
currency: { type: "string", description: 'ISO currency code for style "currency", e.g. "EUR" (default USD).' },
|
|
32
35
|
prefix: { type: "string", description: "Text before every number." },
|
|
@@ -46,10 +49,10 @@ var AXIS = (what) => ({
|
|
|
46
49
|
step: { type: ["number", "null"], exclusiveMinimum: 0, description: "Fixed distance between ticks, or null for automatic." },
|
|
47
50
|
gridlines: { type: "boolean", description: "Grid lines at each tick." },
|
|
48
51
|
format: FORMAT,
|
|
49
|
-
kind: { type: ["string", "null"], enum: [...
|
|
52
|
+
kind: { type: ["string", "null"], enum: [..._chunkR3P2M7HUcjs.CHART_AXIS_KINDS, null], description: 'Category axis only: "date" reads categories as dates and labels them by calendar steps.' },
|
|
50
53
|
scale: {
|
|
51
54
|
type: ["string", "null"],
|
|
52
|
-
enum: [...
|
|
55
|
+
enum: [..._chunkR3P2M7HUcjs.CHART_AXIS_SCALES, null],
|
|
53
56
|
description: 'Value axes and the numeric x axis of scatter / bubble charts: "log" spaces ticks by powers of logBase (values of 0 or less are skipped; min and max must be above 0; not with percent stacking). "linear" or null is the default. Ignored on a category axis.'
|
|
54
57
|
},
|
|
55
58
|
logBase: { type: ["number", "null"], minimum: 2, maximum: 1e3, description: "Base of a log axis, 2 to 1000 (default 10; null resets)." },
|
|
@@ -58,7 +61,7 @@ var AXIS = (what) => ({
|
|
|
58
61
|
additionalProperties: false
|
|
59
62
|
});
|
|
60
63
|
var TRENDLINE_PROPS = {
|
|
61
|
-
type: { type: "string", enum: [...
|
|
64
|
+
type: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_TRENDLINE_TYPES], description: "Fit: linear, exponential, logarithmic, power, polynomial or moving-average." },
|
|
62
65
|
order: { type: "integer", minimum: 2, maximum: 6, description: "Polynomial order (default 2)." },
|
|
63
66
|
period: { type: "integer", minimum: 2, description: "Moving-average period in points (default 2)." },
|
|
64
67
|
forward: { type: "number", minimum: 0, description: "Extend the line this many x units past the last point (default 0)." },
|
|
@@ -69,19 +72,59 @@ var TRENDLINE_PROPS = {
|
|
|
69
72
|
name: { type: "string", description: 'Legend name (default e.g. "Linear (Sales)").' },
|
|
70
73
|
color: { type: "string", description: "CSS colour (default: the series colour)." }
|
|
71
74
|
};
|
|
75
|
+
var REFERENCE_COMMON = {
|
|
76
|
+
label: { type: "string", description: 'Text written on it, e.g. "Target" (default none).' },
|
|
77
|
+
axis: {
|
|
78
|
+
type: "string",
|
|
79
|
+
enum: [..._chunkR3P2M7HUcjs.CHART_REFERENCE_AXES],
|
|
80
|
+
description: "Axis it is measured on: y (default) is the value axis, y2 the secondary value axis (needs a series there), x the numeric x axis of a scatter or bubble chart."
|
|
81
|
+
},
|
|
82
|
+
color: { type: "string", description: "CSS colour (default: the text colour)." }
|
|
83
|
+
};
|
|
84
|
+
var REFERENCE_LINE_PROPS = {
|
|
85
|
+
value: { type: "number", description: "Where the line crosses its axis, in data units." },
|
|
86
|
+
...REFERENCE_COMMON
|
|
87
|
+
};
|
|
88
|
+
var REFERENCE_BAND_PROPS = {
|
|
89
|
+
from: { type: "number", description: "One end of the band on its axis, in data units." },
|
|
90
|
+
to: { type: "number", description: "The other end of the band, in data units (ends may come in either order)." },
|
|
91
|
+
...REFERENCE_COMMON
|
|
92
|
+
};
|
|
93
|
+
var REFERENCE_COMMON_PATCH = {
|
|
94
|
+
label: { type: ["string", "null"], description: "Text written on it; null removes it." },
|
|
95
|
+
axis: { type: ["string", "null"], enum: [..._chunkR3P2M7HUcjs.CHART_REFERENCE_AXES, null], description: "Axis it is measured on (y, y2 or x); null goes back to y." },
|
|
96
|
+
color: { type: ["string", "null"], description: "CSS colour; null goes back to the text colour." }
|
|
97
|
+
};
|
|
98
|
+
var REFERENCE_LINE_PATCH = { value: REFERENCE_LINE_PROPS.value, ...REFERENCE_COMMON_PATCH };
|
|
99
|
+
var REFERENCE_BAND_PATCH = { from: REFERENCE_BAND_PROPS.from, to: REFERENCE_BAND_PROPS.to, ...REFERENCE_COMMON_PATCH };
|
|
100
|
+
var REFERENCE_INDEX = (what) => ({ type: "integer", minimum: 0, description: `${what} index (0 = first), as get_chart lists them in spec.${what === "Reference line" ? "referenceLines" : "referenceBands"}.` });
|
|
101
|
+
var TREE_NODE = {
|
|
102
|
+
type: "object",
|
|
103
|
+
description: 'An item ({"name", "value"}) or a group ({"name", "children": [nodes]}, whose value is the sum of its items).',
|
|
104
|
+
properties: {
|
|
105
|
+
name: { type: "string", description: "Label; unique among its siblings." },
|
|
106
|
+
value: { type: "number", minimum: 0, description: "Items only: the amount, 0 or more." },
|
|
107
|
+
children: { type: "array", items: { $ref: "#/$defs/chartTreeNode" }, description: "Groups only: the nodes inside it (up to 6 levels in all)." },
|
|
108
|
+
color: { type: "string", description: "CSS colour (default: the palette colour of its top-level group, lighter further in)." }
|
|
109
|
+
},
|
|
110
|
+
required: ["name"],
|
|
111
|
+
additionalProperties: false
|
|
112
|
+
};
|
|
113
|
+
var TREE_DEFS = { chartTreeNode: TREE_NODE };
|
|
114
|
+
var TREE_PATH = { type: "array", items: { type: "string" }, minItems: 1, description: 'Names from the top level down to the node, e.g. ["Europe", "France"] (from get_chart treeTable or spec.tree).' };
|
|
72
115
|
var ERROR_BARS = (what) => ({
|
|
73
116
|
type: ["object", "null"],
|
|
74
117
|
description: `${what} null removes them.`,
|
|
75
118
|
properties: {
|
|
76
119
|
type: {
|
|
77
120
|
type: "string",
|
|
78
|
-
enum: [...
|
|
121
|
+
enum: [..._chunkR3P2M7HUcjs.CHART_ERROR_BAR_TYPES],
|
|
79
122
|
description: "fixed: the same amount at every point; percent: a percentage of each value; stddev: value standard deviations of the series, drawn around the series mean (as Excel does); stderr: the standard error of the series at every point; custom: per-point plus / minus amounts."
|
|
80
123
|
},
|
|
81
124
|
value: { type: "number", minimum: 0, description: "Amount in data units for fixed (default 1), percent of each value for percent (default 5), number of standard deviations for stddev (default 1). Not for stderr or custom." },
|
|
82
125
|
plus: { type: "array", items: VALUE, description: "custom only: amount above each point, one per category, in data units (0 or more; null for none)." },
|
|
83
126
|
minus: { type: "array", items: VALUE, description: "custom only: amount below each point, one per category (default: the plus amounts)." },
|
|
84
|
-
direction: { type: "string", enum: [...
|
|
127
|
+
direction: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_ERROR_BAR_DIRECTIONS], description: "both (default), plus (only above) or minus (only below)." },
|
|
85
128
|
cap: { type: "boolean", description: "Draw end caps (default true)." }
|
|
86
129
|
},
|
|
87
130
|
required: ["type"],
|
|
@@ -91,21 +134,22 @@ var SERIES_PROPS = {
|
|
|
91
134
|
name: { type: "string", description: "Series name (legend and data grid header)." },
|
|
92
135
|
values: { type: "array", items: VALUE, description: "One value per category, in category order (padded with gaps)." },
|
|
93
136
|
color: { type: ["string", "null"], description: "CSS colour, or null for the palette colour." },
|
|
94
|
-
type: { type: ["string", "null"], enum: [...
|
|
137
|
+
type: { type: ["string", "null"], enum: [..._chunkR3P2M7HUcjs.CHART_SERIES_TYPES, null], description: "Draw this series as bar, line, area or scatter (a combo chart); null follows the chart type." },
|
|
95
138
|
hidden: { type: "boolean", description: "Hide the series (its data is kept)." },
|
|
96
139
|
axis: { type: ["string", "null"], enum: ["primary", "secondary", null], description: "Value axis: secondary is drawn on the right with its own scale." },
|
|
97
140
|
x: { type: ["array", "null"], items: VALUE, description: "Numeric x per category, for scatter and bubble charts." },
|
|
98
141
|
sizes: { type: ["array", "null"], items: VALUE, description: "Bubble sizes per category (area is proportional to size)." },
|
|
99
142
|
pointColors: { type: ["array", "null"], items: { type: ["string", "null"] }, description: "Colour per category (null keeps the series colour)." },
|
|
100
|
-
|
|
101
|
-
|
|
143
|
+
callouts: { type: ["array", "null"], items: { type: ["string", "null"] }, description: "A label pinned to each point that matters, one per category (null: none); null removes them all. Bar, line, area and scatter charts. set_chart_callout sets one." },
|
|
144
|
+
marker: { type: ["string", "null"], enum: [..._chunkR3P2M7HUcjs.CHART_MARKERS, null], description: "Point marker shape for line, area and scatter series." },
|
|
145
|
+
curve: { type: ["string", "null"], enum: [..._chunkR3P2M7HUcjs.CHART_CURVES, null], description: "Line shape for this series: linear, smooth or step." },
|
|
102
146
|
dataLabels: { type: ["boolean", "null"], description: "Value labels for this series (null follows the chart)." },
|
|
103
147
|
format: { ...FORMAT, type: ["object", "null"], description: "How this series' labels are written (null follows the value axis)." },
|
|
104
148
|
errorBars: ERROR_BARS("Error bars along the value axis (bar, line, area and scatter series; on stacked charts they sit on the stack top)."),
|
|
105
149
|
xErrorBars: ERROR_BARS("Error bars along the x axis (scatter and bubble charts with numeric x values; amounts in x units).")
|
|
106
150
|
};
|
|
107
151
|
var CHART_UPDATE_PROPERTIES = {
|
|
108
|
-
type: { type: "string", enum: [...
|
|
152
|
+
type: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_TYPES], description: "Chart type. slope joins each category from the first series (before) to the second (after); likert reads each category as a question and the series as answers from most negative to most positive; parliament draws the first series as seats; sunburst draws the grouped data (set_chart_tree) as rings, and a treemap with grouped data nests its groups." },
|
|
109
153
|
title: { type: "string", description: 'Title ("" for none).' },
|
|
110
154
|
subtitle: { type: "string", description: 'Subtitle ("" for none).' },
|
|
111
155
|
xAxis: AXIS("Category axis (or numeric x axis of scatter / bubble charts)."),
|
|
@@ -114,15 +158,15 @@ var CHART_UPDATE_PROPERTIES = {
|
|
|
114
158
|
legend: {
|
|
115
159
|
type: "object",
|
|
116
160
|
description: "Legend.",
|
|
117
|
-
properties: { show: { type: "boolean", description: "Show the legend." }, position: { type: "string", enum: [...
|
|
161
|
+
properties: { show: { type: "boolean", description: "Show the legend." }, position: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_LEGEND_POSITIONS], description: "Where the legend goes." } },
|
|
118
162
|
additionalProperties: false
|
|
119
163
|
},
|
|
120
|
-
stacking: { type: "string", enum: [...
|
|
121
|
-
orientation: { type: "string", enum: [...
|
|
122
|
-
curve: { type: "string", enum: [...
|
|
164
|
+
stacking: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_STACKINGS], description: "none, stacked, or percent (each category scaled to 100%)." },
|
|
165
|
+
orientation: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_ORIENTATIONS], description: "horizontal draws bars sideways." },
|
|
166
|
+
curve: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_CURVES], description: "Line shape: linear, smooth or step." },
|
|
123
167
|
points: { type: "boolean", description: "Dots on line and area series." },
|
|
124
168
|
dataLabels: { type: "boolean", description: "Value labels on bars, points and slices." },
|
|
125
|
-
labelPosition: { type: "string", enum: [...
|
|
169
|
+
labelPosition: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_LABEL_POSITIONS], description: "Bar label position; auto drops labels that do not fit." },
|
|
126
170
|
palette: { type: "array", items: { type: "string" }, minItems: 1, description: "Series colours in order (CSS colours)." },
|
|
127
171
|
innerRadius: { type: "number", minimum: 0, maximum: 0.9, description: "Donut hole as a fraction of the radius." },
|
|
128
172
|
gapWidth: { type: "number", minimum: 0, maximum: 0.9, description: "Space between bar groups as a fraction of the category (default 0.28)." },
|
|
@@ -130,7 +174,18 @@ var CHART_UPDATE_PROPERTIES = {
|
|
|
130
174
|
bins: { type: ["integer", "null"], minimum: 1, maximum: 500, description: "Histogram bin count, or null for \u221An." },
|
|
131
175
|
showTotal: { type: "boolean", description: "Waterfall: append a total bar." },
|
|
132
176
|
radarTicks: { type: ["integer", "null"], minimum: 1, maximum: 50, description: "Radar: number of evenly spaced rings from the value axis min to max, or null for round-number rings (default null)." },
|
|
133
|
-
radarGraticule: { type: "string", enum: [...
|
|
177
|
+
radarGraticule: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_RADAR_GRATICULES], description: "Radar: draw rings as polygons through the spokes or as circles (default polygon)." },
|
|
178
|
+
note: { type: "string", description: 'A source or footnote written under the chart ("" for none).' },
|
|
179
|
+
highlight: { type: "array", items: { type: "string" }, description: "Category labels and series names (or ids) to draw normally while the rest are muted; [] shows everything. highlight_chart checks the names." },
|
|
180
|
+
referenceLines: { type: "array", items: { type: "object", properties: REFERENCE_LINE_PROPS, required: ["value"], additionalProperties: false }, description: "Replaces every reference line (targets, floors, averages across the plot). add_chart_reference_line adds one." },
|
|
181
|
+
referenceBands: { type: "array", items: { type: "object", properties: REFERENCE_BAND_PROPS, required: ["from", "to"], additionalProperties: false }, description: "Replaces every reference band (target ranges across the plot). add_chart_reference_band adds one." },
|
|
182
|
+
varyColors: { type: "boolean", description: "A one-series bar, line, area or scatter chart colours each category from the palette, and its legend lists the categories (default false)." },
|
|
183
|
+
likertNeutral: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_LIKERT_NEUTRALS], description: "Likert with an odd number of answers: split (default) puts the middle answer across the centre line; separate draws it in its own column on the right." },
|
|
184
|
+
likertSort: { type: "string", enum: [..._chunkR3P2M7HUcjs.CHART_LIKERT_SORTS], description: "Likert: order the questions by agreement (positive), by disagreement (negative) or as given (none, default)." },
|
|
185
|
+
parliamentArc: { type: "number", minimum: 90, maximum: 360, description: "Parliament: sweep of the hemicycle in degrees (default 180)." },
|
|
186
|
+
parliamentMajority: { type: ["integer", "null"], minimum: 1, description: "Parliament: seats needed for a majority, drawn as a dashed line (null: half of the seats plus one)." },
|
|
187
|
+
parliamentLabel: { type: "string", description: 'Parliament: caption under the seat total ("" writes "seats").' },
|
|
188
|
+
sunburstLabel: { type: "string", description: 'Sunburst: caption under the total in the centre ("" for none).' }
|
|
134
189
|
};
|
|
135
190
|
|
|
136
191
|
|
|
@@ -142,4 +197,11 @@ var CHART_UPDATE_PROPERTIES = {
|
|
|
142
197
|
|
|
143
198
|
|
|
144
199
|
|
|
145
|
-
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
exports.VALUE = VALUE; exports.SERIES_REF = SERIES_REF; exports.CATEGORY_REF = CATEGORY_REF; exports.WIDTH = WIDTH; exports.HEIGHT = HEIGHT; exports.TRENDLINE_PROPS = TRENDLINE_PROPS; exports.REFERENCE_LINE_PROPS = REFERENCE_LINE_PROPS; exports.REFERENCE_BAND_PROPS = REFERENCE_BAND_PROPS; exports.REFERENCE_LINE_PATCH = REFERENCE_LINE_PATCH; exports.REFERENCE_BAND_PATCH = REFERENCE_BAND_PATCH; exports.REFERENCE_INDEX = REFERENCE_INDEX; exports.TREE_DEFS = TREE_DEFS; exports.TREE_PATH = TREE_PATH; exports.SERIES_PROPS = SERIES_PROPS; exports.CHART_UPDATE_PROPERTIES = CHART_UPDATE_PROPERTIES;
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
chartToMermaid,
|
|
6
6
|
describeChart,
|
|
7
7
|
layoutSparkline
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SZA42R4N.js";
|
|
9
9
|
import {
|
|
10
10
|
layoutChart
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-Z4P2RBMJ.js";
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_CHART_THEME,
|
|
14
14
|
normalizeChartSpec
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-3NEZJCBY.js";
|
|
16
16
|
import {
|
|
17
17
|
plainTextToSlice
|
|
18
18
|
} from "./chunk-2INPJDNY.js";
|
|
@@ -2,11 +2,13 @@ import {
|
|
|
2
2
|
chartFamily,
|
|
3
3
|
chartRgbToHex,
|
|
4
4
|
chartSeriesType,
|
|
5
|
+
chartTreeFromRows,
|
|
6
|
+
chartVariesColors,
|
|
5
7
|
defaultChartAxis,
|
|
6
8
|
isCartesianChart,
|
|
7
9
|
normalizeChartSpec,
|
|
8
10
|
parseChartColor
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-3NEZJCBY.js";
|
|
10
12
|
|
|
11
13
|
// src/chart/ooxml.ts
|
|
12
14
|
var CHART_OOXML_NS = "http://schemas.openxmlformats.org/drawingml/2006/chart";
|
|
@@ -295,7 +297,7 @@ function chartFromOoxml(xml, options = {}) {
|
|
|
295
297
|
input.orientation = orientation;
|
|
296
298
|
input.dataLabels = dataLabels;
|
|
297
299
|
input.points = points || first !== "line";
|
|
298
|
-
if (bool(val(groups[0], "varyColors")) &&
|
|
300
|
+
if (bool(val(groups[0], "varyColors")) && !combo && isCartesianChart(first) && series.length === 1) input.varyColors = true;
|
|
299
301
|
const readAxis = (a, fallback) => {
|
|
300
302
|
const axis = { ...fallback, format: {} };
|
|
301
303
|
if (!a) return axis;
|
|
@@ -340,6 +342,29 @@ function readChartex(root, issues, unsupported) {
|
|
|
340
342
|
const numDim = kids(d, "numDim")[0];
|
|
341
343
|
const lvl = (dim) => kids(dim, "lvl")[0];
|
|
342
344
|
const cats = kids(lvl(strDim), "pt").map((p) => p.textContent ?? "");
|
|
345
|
+
const levels = kids(strDim, "lvl").map((l) => {
|
|
346
|
+
const out = [];
|
|
347
|
+
for (const p of kids(l, "pt")) out[Number(p.getAttribute("idx") ?? out.length)] = (p.textContent ?? "").trim();
|
|
348
|
+
return out;
|
|
349
|
+
});
|
|
350
|
+
let paths;
|
|
351
|
+
if (levels.length > 1) {
|
|
352
|
+
const carried = [];
|
|
353
|
+
paths = levels[0].map((_, i) => {
|
|
354
|
+
const path2 = [];
|
|
355
|
+
for (let k = levels.length - 1; k >= 1; k--) {
|
|
356
|
+
const name = levels[k][i];
|
|
357
|
+
if (name) {
|
|
358
|
+
carried[k] = name;
|
|
359
|
+
carried.length = Math.max(carried.length, k + 1);
|
|
360
|
+
for (let j = 1; j < k; j++) carried[j] = "";
|
|
361
|
+
}
|
|
362
|
+
if (carried[k]) path2.push(carried[k]);
|
|
363
|
+
}
|
|
364
|
+
if (levels[0][i]) path2.push(levels[0][i]);
|
|
365
|
+
return path2;
|
|
366
|
+
});
|
|
367
|
+
}
|
|
343
368
|
const values = [];
|
|
344
369
|
const nl = lvl(numDim);
|
|
345
370
|
for (const p of kids(nl, "pt")) {
|
|
@@ -347,19 +372,18 @@ function readChartex(root, issues, unsupported) {
|
|
|
347
372
|
while (values.length < i) values.push(null);
|
|
348
373
|
values[i] = numberOf((p.textContent ?? "").trim());
|
|
349
374
|
}
|
|
350
|
-
data.set(id, { categories: cats, values, code: nl?.getAttribute("formatCode") ?? void 0 });
|
|
375
|
+
data.set(id, { categories: cats, values, code: nl?.getAttribute("formatCode") ?? void 0, paths });
|
|
351
376
|
}
|
|
352
377
|
const chart = kid(root, "chart");
|
|
353
378
|
const region = path(chart, "plotArea", "plotAreaRegion");
|
|
354
379
|
const seriesEls = kids(region, "series");
|
|
355
|
-
const layouts = { waterfall: "waterfall", funnel: "funnel", treemap: "treemap", sunburst: "
|
|
380
|
+
const layouts = { waterfall: "waterfall", funnel: "funnel", treemap: "treemap", sunburst: "sunburst", boxWhisker: "box", clusteredColumn: "histogram", paretoLine: "histogram" };
|
|
356
381
|
const layout = seriesEls[0]?.getAttribute("layoutId") ?? "";
|
|
357
382
|
const type = layouts[layout];
|
|
358
383
|
if (!type) {
|
|
359
384
|
issues.push({ path: "plotArea", message: `The chart layout "${layout || "unknown"}" is not supported.` });
|
|
360
385
|
return { spec: normalizeChartSpec({}).spec, issues, unsupported: [layout || "unknown chartex layout"], lossless: false };
|
|
361
386
|
}
|
|
362
|
-
if (layout === "sunburst") unsupported.push("sunburst (drawn as a treemap of the innermost level)");
|
|
363
387
|
if (layout === "paretoLine") unsupported.push("pareto line");
|
|
364
388
|
const series = [];
|
|
365
389
|
let categories = [];
|
|
@@ -382,6 +406,12 @@ function readChartex(root, issues, unsupported) {
|
|
|
382
406
|
categories: categories.length >= longest ? categories : Array.from({ length: longest }, (_, i) => categories[i] ?? `${i + 1}`)
|
|
383
407
|
};
|
|
384
408
|
if (type === "waterfall") input.showTotal = false;
|
|
409
|
+
const first = data.get(kid(seriesEls[0], "dataId")?.getAttribute("val") ?? "0");
|
|
410
|
+
if ((type === "treemap" || type === "sunburst") && first?.paths) {
|
|
411
|
+
const treeIssues = [];
|
|
412
|
+
input.tree = chartTreeFromRows(first.paths.map((path2, i) => ({ path: path2, value: first.values[i] ?? 0 })), treeIssues);
|
|
413
|
+
for (const t of treeIssues) issues.push({ path: "chartData", message: t.message });
|
|
414
|
+
}
|
|
385
415
|
const { spec, issues: specIssues } = normalizeChartSpec(input);
|
|
386
416
|
issues.push(...specIssues);
|
|
387
417
|
return { spec, issues, unsupported, lossless: unsupported.length === 0 && specIssues.length === 0 };
|
|
@@ -440,10 +470,30 @@ function chartToOoxml(spec) {
|
|
|
440
470
|
issues.push(`${spec.type} charts are written as bar charts: DrawingML has no ${spec.type} type (Office 2016 stores it as chartex).`);
|
|
441
471
|
type = "bar";
|
|
442
472
|
} else if (family === "treemap") {
|
|
443
|
-
issues.push(
|
|
473
|
+
issues.push(`Treemaps are written as pie charts${spec.tree.length ? " of the top-level group totals" : ""}: DrawingML has no treemap type.`);
|
|
444
474
|
type = "pie";
|
|
475
|
+
} else if (family === "sunburst") {
|
|
476
|
+
issues.push(`Sunburst charts are written as doughnut charts of the ${spec.tree.length ? "top-level group totals" : "values"}: DrawingML has no sunburst type (Office 2016 stores it as chartex).`);
|
|
477
|
+
type = "donut";
|
|
478
|
+
} else if (family === "parliament") {
|
|
479
|
+
issues.push("Parliament charts are written as doughnut charts of the seats: DrawingML has no parliament type.");
|
|
480
|
+
type = "donut";
|
|
481
|
+
} else if (family === "slope") {
|
|
482
|
+
issues.push("Slope charts are written as line charts with the two series as lines over the categories: DrawingML has no slope type.");
|
|
483
|
+
type = "line";
|
|
484
|
+
} else if (family === "likert") {
|
|
485
|
+
issues.push("Likert charts are written as 100% stacked horizontal bars: DrawingML has no diverging bar.");
|
|
486
|
+
spec = { ...spec, type: "bar", stacking: "percent", orientation: "horizontal" };
|
|
487
|
+
type = "bar";
|
|
445
488
|
}
|
|
446
489
|
const visible = spec.series.filter((s) => !s.hidden);
|
|
490
|
+
const annotations = [
|
|
491
|
+
spec.referenceLines.length || spec.referenceBands.length ? "reference lines and bands" : "",
|
|
492
|
+
spec.series.some((s) => s.callouts) ? "callouts" : "",
|
|
493
|
+
spec.highlight.length ? "the highlight" : "",
|
|
494
|
+
spec.note ? "the note" : ""
|
|
495
|
+
].filter(Boolean);
|
|
496
|
+
if (annotations.length) issues.push(`${annotations.join(", ").replace(/^./, (c) => c.toUpperCase())} ${annotations.length === 1 && !annotations[0].endsWith("s") ? "is" : "are"} not written: DrawingML has no equivalent.`);
|
|
447
497
|
if (visible.length < spec.series.length) issues.push(`${spec.series.length - visible.length} hidden series ${spec.series.length - visible.length === 1 ? "is" : "are"} left out.`);
|
|
448
498
|
const grouping = spec.stacking === "stacked" ? "stacked" : spec.stacking === "percent" ? "percentStacked" : "standard";
|
|
449
499
|
const ids = { cat: 500000001, val: 500000002, cat2: 500000003, val2: 500000004 };
|
|
@@ -512,6 +562,7 @@ function chartToOoxml(spec) {
|
|
|
512
562
|
return `<c:ser>${parts.join("")}</c:ser>`;
|
|
513
563
|
};
|
|
514
564
|
const dLbls = `<c:dLbls><c:showLegendKey val="0"/><c:showVal val="${spec.dataLabels ? 1 : 0}"/><c:showCatName val="0"/><c:showSerName val="0"/><c:showPercent val="0"/><c:showBubbleSize val="0"/></c:dLbls>`;
|
|
565
|
+
const vary = chartVariesColors(spec) ? 1 : 0;
|
|
515
566
|
const groupXml = groups.map((g) => {
|
|
516
567
|
const axes2 = g.secondary ? `<c:axId val="${ids.cat2}"/><c:axId val="${ids.val2}"/>` : `<c:axId val="${ids.cat}"/><c:axId val="${ids.val}"/>`;
|
|
517
568
|
const sers = g.series.map(({ s, index }) => serXml(g.kind, s, index)).join("");
|
|
@@ -521,14 +572,14 @@ function chartToOoxml(spec) {
|
|
|
521
572
|
const barsWidth = spec.stacking === "none" ? n - (n - 1) * spec.overlap : 1;
|
|
522
573
|
const gapPct = Math.round(Math.min(500, spec.gapWidth / Math.max(0.01, 1 - spec.gapWidth) * barsWidth * 100));
|
|
523
574
|
const overlapPct = spec.stacking === "none" ? Math.round(spec.overlap * 100) : 100;
|
|
524
|
-
return `<c:barChart><c:barDir val="${spec.orientation === "horizontal" ? "bar" : "col"}"/><c:grouping val="${spec.stacking === "none" ? "clustered" : grouping}"/><c:varyColors val="
|
|
575
|
+
return `<c:barChart><c:barDir val="${spec.orientation === "horizontal" ? "bar" : "col"}"/><c:grouping val="${spec.stacking === "none" ? "clustered" : grouping}"/><c:varyColors val="${vary}"/>${sers}${dLbls}<c:gapWidth val="${gapPct}"/><c:overlap val="${overlapPct}"/>${axes2}</c:barChart>`;
|
|
525
576
|
}
|
|
526
577
|
case "line":
|
|
527
|
-
return `<c:lineChart><c:grouping val="${spec.stacking === "none" ? "standard" : "standard"}"/><c:varyColors val="
|
|
578
|
+
return `<c:lineChart><c:grouping val="${spec.stacking === "none" ? "standard" : "standard"}"/><c:varyColors val="${vary}"/>${sers}${dLbls}<c:marker val="1"/>${axes2}</c:lineChart>`;
|
|
528
579
|
case "area":
|
|
529
|
-
return `<c:areaChart><c:grouping val="${grouping}"/><c:varyColors val="
|
|
580
|
+
return `<c:areaChart><c:grouping val="${grouping}"/><c:varyColors val="${vary}"/>${sers}${dLbls}${axes2}</c:areaChart>`;
|
|
530
581
|
case "scatter":
|
|
531
|
-
return `<c:scatterChart><c:scatterStyle val="lineMarker"/><c:varyColors val="
|
|
582
|
+
return `<c:scatterChart><c:scatterStyle val="lineMarker"/><c:varyColors val="${vary}"/>${sers}${dLbls}${axes2}</c:scatterChart>`;
|
|
532
583
|
case "bubble":
|
|
533
584
|
return `<c:bubbleChart><c:varyColors val="0"/>${sers}${dLbls}<c:bubbleScale val="100"/>${axes2}</c:bubbleChart>`;
|
|
534
585
|
case "radar":
|