@chartguard/schema-generator 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +17 -2
- package/dist/index.d.mts +6 -0
- package/dist/lib/chartjs-effects.d.mts +5 -0
- package/dist/lib/chartjs-plugins.d.mts +23 -0
- package/dist/lib/chartjs-scopes.d.mts +30 -0
- package/dist/lib/chartjs.d.mts +32 -0
- package/dist/lib/deprecation.d.mts +9 -0
- package/dist/lib/digest.d.mts +12 -0
- package/dist/lib/echarts-components.d.mts +2 -0
- package/dist/lib/echarts-deprecations.d.mts +5 -0
- package/dist/lib/echarts-handlers.d.mts +2 -0
- package/dist/lib/echarts-runtime.d.mts +2 -0
- package/dist/lib/echarts.d.mts +26 -0
- package/dist/lib/emitter.d.mts +173 -0
- package/dist/lib/generate.d.mts +14 -0
- package/dist/lib/highcharts-runtime.d.mts +2 -0
- package/dist/lib/highcharts.d.mts +26 -0
- package/dist/lib/local.d.mts +14 -0
- package/dist/lib/lock.d.mts +31 -0
- package/dist/lib/nodes.d.mts +4 -0
- package/dist/lib/paths.d.mts +22 -0
- package/dist/lib/program.d.mts +13 -0
- package/dist/lib/provenance.d.mts +46 -0
- package/dist/lib/runtime.d.mts +24 -0
- package/dist/lib/scriptable.d.mts +13 -0
- package/dist/lib/trace.d.mts +8 -0
- package/dist/lib/types.d.mts +52 -0
- package/index.mjs +20 -0
- package/lib/chartjs-effects.mjs +36 -0
- package/lib/chartjs-plugins.mjs +41 -0
- package/lib/chartjs-scopes.mjs +96 -0
- package/lib/chartjs.mjs +275 -0
- package/lib/deprecation.mjs +21 -0
- package/lib/digest.mjs +33 -0
- package/lib/echarts-components.mjs +176 -0
- package/lib/echarts-deprecations.mjs +206 -0
- package/lib/echarts-handlers.mjs +31 -0
- package/lib/echarts-runtime.mjs +311 -0
- package/lib/echarts.mjs +89 -0
- package/lib/emitter.mjs +333 -0
- package/lib/generate.mjs +35 -0
- package/lib/highcharts-runtime.mjs +198 -0
- package/lib/highcharts.mjs +105 -0
- package/lib/local.mjs +33 -0
- package/lib/lock.mjs +123 -0
- package/lib/nodes.mjs +17 -0
- package/lib/paths.mjs +50 -0
- package/lib/program.mjs +46 -0
- package/lib/provenance.mjs +100 -0
- package/lib/runtime.mjs +38 -0
- package/lib/scriptable.mjs +57 -0
- package/lib/trace.mjs +124 -0
- package/lib/types.mjs +74 -0
- package/package.json +47 -5
- package/upstream-sources.json +102 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { upstreamChanged } from './nodes.mjs';
|
|
2
|
+
import { runtimePointer } from './runtime.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Where echarts 6.1.0 declares less than its runtime reads, shown by the official examples once
|
|
6
|
+
* recursive definitions were checked at every depth (CG-02-03): the matrix dimension reads every
|
|
7
|
+
* level of cells with the same `traverseInitCells` (lib/coord/matrix/MatrixDim.js), where a cell is
|
|
8
|
+
* a string or an object, while the declarations allow strings only at the top level.
|
|
9
|
+
*/
|
|
10
|
+
const CELLS = {
|
|
11
|
+
file: 'lib/coord/matrix/MatrixDim.js',
|
|
12
|
+
pattern: 'var childrenSpan = traverseInitCells(cellOption.children, firstLeafLocator, level + 1);'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* How the graphic component reads its option (lib/component/graphic/install.js and GraphicView.js):
|
|
17
|
+
* with `elements` it is the component, otherwise it is an element (or a list of them) and wrapped as
|
|
18
|
+
* one; an element's `type` is looked up among the elements that are not shapes (`group`, `image`,
|
|
19
|
+
* `text`) and the shapes registered with `registerShape`, so a path element's `type` is one of those
|
|
20
|
+
* shapes, or one an application registered (extensible).
|
|
21
|
+
*/
|
|
22
|
+
const GRAPHIC = {
|
|
23
|
+
component: {
|
|
24
|
+
file: 'lib/component/graphic/install.js',
|
|
25
|
+
pattern: '} else if (graphicOption && !graphicOption.elements) {'
|
|
26
|
+
},
|
|
27
|
+
shapes: { file: 'lib/util/graphic.js', pattern: "registerShape('circle', Circle);" },
|
|
28
|
+
lookup: {
|
|
29
|
+
file: 'lib/component/graphic/GraphicView.js',
|
|
30
|
+
pattern: '? nonShapeGraphicElements[graphicType] : graphicUtil.getShapeClass(graphicType);'
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
/** The element union `elements` and a group's `children` share, stored once (D2). */
|
|
34
|
+
const ELEMENT_UNION = 'GraphicComponentElementOption';
|
|
35
|
+
const SHAPE_TYPE = 'GraphicShapeType';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* EC4 style keys echarts still reads on a text element (`convertFromEC4CompatibleStyle`,
|
|
39
|
+
* lib/util/styleCompat.js): each is copied into its current key. Deprecated aliases without a
|
|
40
|
+
* rename: the copy happens only while the style counts as legacy (`isEC4CompatibleStyle`), so
|
|
41
|
+
* renaming could change what is drawn.
|
|
42
|
+
*/
|
|
43
|
+
const EC4_TEXT = {
|
|
44
|
+
file: 'lib/util/styleCompat.js',
|
|
45
|
+
keys: {
|
|
46
|
+
textStrokeWidth: 'lineWidth',
|
|
47
|
+
textAlign: 'align',
|
|
48
|
+
textVerticalAlign: 'verticalAlign',
|
|
49
|
+
textLineHeight: 'lineHeight',
|
|
50
|
+
textWidth: 'width',
|
|
51
|
+
textHeight: 'height',
|
|
52
|
+
textBackgroundColor: 'backgroundColor',
|
|
53
|
+
textPadding: 'padding',
|
|
54
|
+
textBorderColor: 'borderColor',
|
|
55
|
+
textBorderWidth: 'borderWidth',
|
|
56
|
+
textBorderRadius: 'borderRadius',
|
|
57
|
+
textBoxShadowColor: 'shadowColor',
|
|
58
|
+
textBoxShadowBlur: 'shadowBlur',
|
|
59
|
+
textBoxShadowOffsetX: 'shadowOffsetX',
|
|
60
|
+
textBoxShadowOffsetY: 'shadowOffsetY'
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const TEXT_STYLE = 'TextStyleProps & TransitionOptionMixin<TextStyleProps>';
|
|
64
|
+
/** The shapes echarts 6.1.0 registers (the `registerShape` calls after `GRAPHIC.shapes`). */
|
|
65
|
+
const SHAPES = ['circle', 'ellipse', 'sector', 'ring', 'polygon', 'polyline', 'rect', 'line', 'bezierCurve', 'arc'];
|
|
66
|
+
const ELEMENTS = [
|
|
67
|
+
'GraphicComponentGroupOption',
|
|
68
|
+
'GraphicComponentZRPathOption',
|
|
69
|
+
'GraphicComponentImageOption',
|
|
70
|
+
'GraphicComponentTextOption'
|
|
71
|
+
];
|
|
72
|
+
const COMPONENT = 'GraphicComponentOption';
|
|
73
|
+
|
|
74
|
+
const changed = upstreamChanged('echarts types');
|
|
75
|
+
|
|
76
|
+
/** The element or component a definition name is (with or without the `mainType` intersection). */
|
|
77
|
+
const graphicKind = (ref) => [...ELEMENTS, COMPONENT].find((name) => ref === name || ref.startsWith(`${name} & `));
|
|
78
|
+
|
|
79
|
+
/** A union of graphic element (and component) references, told apart as the graphic component does. */
|
|
80
|
+
function graphicUnion(node, sources, shared) {
|
|
81
|
+
if (node.kind !== 'union') return node;
|
|
82
|
+
const kinds = node.anyOf.map((member) => {
|
|
83
|
+
if (member.kind === 'ref') return graphicKind(member.ref);
|
|
84
|
+
return member.kind === 'array' ? 'array' : undefined;
|
|
85
|
+
});
|
|
86
|
+
const objects = kinds.filter((kind) => kind !== 'array');
|
|
87
|
+
if (objects.length < 2 || !objects.every((kind) => kind !== undefined)) return node;
|
|
88
|
+
const component = kinds.indexOf(COMPONENT);
|
|
89
|
+
const union = {
|
|
90
|
+
...node,
|
|
91
|
+
discriminator: 'type',
|
|
92
|
+
extensible: true,
|
|
93
|
+
...(component < 0 ? {} : { selectWhen: [{ test: 'truthy', property: 'elements', variant: component }] }),
|
|
94
|
+
provenance: { confidence: 'authoritative', sources }
|
|
95
|
+
};
|
|
96
|
+
if (component >= 0) return union;
|
|
97
|
+
// The element union of `elements` and `children` appears under many properties: stored once.
|
|
98
|
+
shared.set(ELEMENT_UNION, union);
|
|
99
|
+
return { kind: 'ref', ref: ELEMENT_UNION };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** The text element's style with the EC4 keys echarts still reads, each a deprecated alias of its current key. */
|
|
103
|
+
function withEc4TextStyle(root, definitions) {
|
|
104
|
+
const style = definitions[TEXT_STYLE];
|
|
105
|
+
if (style?.kind !== 'object') throw changed(TEXT_STYLE);
|
|
106
|
+
const aliases = Object.entries(EC4_TEXT.keys).map(([key, to]) => {
|
|
107
|
+
const target = style.properties[to];
|
|
108
|
+
if (target === undefined) throw changed(`${TEXT_STYLE}.${to}`);
|
|
109
|
+
const pattern = `hasOwn(richItem, '${key}') && (out.${to} = richItem.${key});`;
|
|
110
|
+
const pointer = runtimePointer(root, 'echarts', { file: EC4_TEXT.file, pattern });
|
|
111
|
+
return [
|
|
112
|
+
key,
|
|
113
|
+
{
|
|
114
|
+
node: target.node,
|
|
115
|
+
provenance: { confidence: 'authoritative', sources: [{ source: 'echarts', pointer }] },
|
|
116
|
+
deprecated: { message: `${key} is an echarts 4 style; use ${to} instead.`, replacement: to }
|
|
117
|
+
}
|
|
118
|
+
];
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
...definitions,
|
|
122
|
+
[TEXT_STYLE]: { ...style, properties: { ...style.properties, ...Object.fromEntries(aliases) } }
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Every graphic element union, at any depth of any definition. */
|
|
127
|
+
function mapNodes(node, map) {
|
|
128
|
+
if (node === null || typeof node !== 'object') return node;
|
|
129
|
+
const mapped = Array.isArray(node)
|
|
130
|
+
? node.map((item) => mapNodes(item, map))
|
|
131
|
+
: Object.fromEntries(Object.entries(node).map(([key, value]) => [key, mapNodes(value, map)]));
|
|
132
|
+
return Array.isArray(node) ? mapped : map(mapped);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** New definitions where graphic elements are told apart by `type`, and a path element's `type` is a registered shape. */
|
|
136
|
+
function withGraphicFacts(root, definitions) {
|
|
137
|
+
const cite = (fact) => ({ source: 'echarts', pointer: runtimePointer(root, 'echarts', fact) });
|
|
138
|
+
const sources = [cite(GRAPHIC.component), cite(GRAPHIC.lookup)];
|
|
139
|
+
const shared = new Map();
|
|
140
|
+
const next = Object.fromEntries(
|
|
141
|
+
Object.entries(definitions).map(([name, definition]) => [
|
|
142
|
+
name,
|
|
143
|
+
mapNodes(definition, (node) => graphicUnion(node, sources, shared))
|
|
144
|
+
])
|
|
145
|
+
);
|
|
146
|
+
for (const [name, union] of shared) next[name] = union;
|
|
147
|
+
const paths = Object.keys(next).filter(
|
|
148
|
+
(name) =>
|
|
149
|
+
graphicKind(name) === 'GraphicComponentZRPathOption' || name === 'Omit<GraphicComponentZRPathOption, "clipPath">'
|
|
150
|
+
);
|
|
151
|
+
if (paths.length === 0) throw changed('GraphicComponentZRPathOption');
|
|
152
|
+
// The shape names, stored once for every path element definition (D2).
|
|
153
|
+
next[SHAPE_TYPE] = { kind: 'union', anyOf: SHAPES.map((value) => ({ kind: 'literal', value })) };
|
|
154
|
+
for (const name of paths) {
|
|
155
|
+
const type = next[name].properties?.type;
|
|
156
|
+
if (type?.node.kind !== 'string') throw changed(`${name}.type`);
|
|
157
|
+
const node = { kind: 'ref', ref: SHAPE_TYPE };
|
|
158
|
+
const provenance = { ...type.provenance, sources: [...type.provenance.sources, cite(GRAPHIC.shapes)] };
|
|
159
|
+
next[name] = { ...next[name], properties: { ...next[name].properties, type: { ...type, node, provenance } } };
|
|
160
|
+
}
|
|
161
|
+
return next;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* How echarts merges the root option (`GlobalModel._mergeOption`, lib/model/Global.js): a `null`
|
|
166
|
+
* root option is skipped like an absent one; a root option of a component (`ComponentModel.hasClass`)
|
|
167
|
+
* is read as a list (`normalizeToArray`: one value is a list of one), and `mappingToExists`
|
|
168
|
+
* (lib/util/model.js) sets every entry that is not an object to `null` and skips it (CG-02-10).
|
|
169
|
+
* The components are the root options of `EChartsOption` the full bundle registers a model for
|
|
170
|
+
* (`aria` is a global option), checked against the runtime's `hasClass` by the generator tests.
|
|
171
|
+
*
|
|
172
|
+
* Preprocessors read some components before that skip, and throw on what they cannot read: the
|
|
173
|
+
* layout compatibility runs `'x' in option` on every truthy entry of nine components; the radar,
|
|
174
|
+
* polar, brush, toolbox and timeline preprocessors read a property of every listed entry, so a
|
|
175
|
+
* listed `null` throws; axisPointer reads the model of its first entry while drawing; and any
|
|
176
|
+
* brush value but `null` adds the brush buttons to the toolbox, so none is without effect. Which kinds
|
|
177
|
+
* of value each component skips, given alone (`value`) or listed (`entries`), follows from those
|
|
178
|
+
* lines; the conformance tests run every kind on every component against the runtime.
|
|
179
|
+
*/
|
|
180
|
+
const ROOT_MERGE = {
|
|
181
|
+
nullSkipped: { file: 'lib/model/Global.js', pattern: 'if (componentOption == null) {' },
|
|
182
|
+
listed: {
|
|
183
|
+
file: 'lib/model/Global.js',
|
|
184
|
+
pattern:
|
|
185
|
+
'var newCmptOptionList = concatInternalOptions(this, mainType, modelUtil.normalizeToArray(newOption[mainType]));'
|
|
186
|
+
},
|
|
187
|
+
skipped: { file: 'lib/util/model.js', pattern: 'if (!isObject(cmptOption)) {' }
|
|
188
|
+
};
|
|
189
|
+
const THROWS = {
|
|
190
|
+
layout: { file: 'lib/preprocessor/backwardCompat.js', pattern: 'if (prop[0] in option && !(prop[1] in option)) {' },
|
|
191
|
+
radar: {
|
|
192
|
+
file: 'lib/preprocessor/helper/compatStyle.js',
|
|
193
|
+
pattern: 'if (radarOpt.name && radarOpt.axisName == null) {'
|
|
194
|
+
},
|
|
195
|
+
polar: { file: 'lib/chart/radar/backwardCompat.js', pattern: 'if (polarOpt.indicator) {' },
|
|
196
|
+
brush: {
|
|
197
|
+
file: 'lib/component/brush/preprocessor.js',
|
|
198
|
+
pattern: "var tbs = brushOpt.hasOwnProperty('toolbox') ? brushOpt.toolbox : [];"
|
|
199
|
+
},
|
|
200
|
+
brushToolbox: {
|
|
201
|
+
file: 'lib/component/brush/preprocessor.js',
|
|
202
|
+
pattern: 'var brushComponents = normalizeToArray(option ? option.brush : []);'
|
|
203
|
+
},
|
|
204
|
+
toolbox: {
|
|
205
|
+
file: 'lib/preprocessor/helper/compatStyle.js',
|
|
206
|
+
pattern: 'each(toolboxOpt.feature, function (featureOpt) {'
|
|
207
|
+
},
|
|
208
|
+
timeline: { file: 'lib/preprocessor/helper/compatStyle.js', pattern: 'var data = timelineOpt.data;' },
|
|
209
|
+
axisPointer: {
|
|
210
|
+
file: 'lib/component/axisPointer/modelHelper.js',
|
|
211
|
+
pattern: "var linksOption = globalAxisPointerModel.get('link', true) || [];"
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
const EVERY = { value: ['falsy', 'truthy'], entries: ['null', 'falsy', 'truthy'] };
|
|
215
|
+
const FALSY = { value: ['falsy'], entries: ['null', 'falsy'] };
|
|
216
|
+
const NOT_NULL = { value: ['falsy', 'truthy'], entries: ['falsy', 'truthy'] };
|
|
217
|
+
const FALSY_NOT_NULL = { value: ['falsy'], entries: ['falsy'] };
|
|
218
|
+
/** By component: which kinds it skips, and the lines that throw on the others. */
|
|
219
|
+
const COMPONENTS = {
|
|
220
|
+
dataset: [EVERY],
|
|
221
|
+
title: [FALSY, 'layout'],
|
|
222
|
+
grid: [FALSY, 'layout'],
|
|
223
|
+
radar: [NOT_NULL, 'radar'],
|
|
224
|
+
polar: [NOT_NULL, 'polar'],
|
|
225
|
+
geo: [FALSY, 'layout'],
|
|
226
|
+
angleAxis: [EVERY],
|
|
227
|
+
radiusAxis: [EVERY],
|
|
228
|
+
xAxis: [EVERY],
|
|
229
|
+
yAxis: [EVERY],
|
|
230
|
+
singleAxis: [EVERY],
|
|
231
|
+
parallel: [FALSY, 'layout'],
|
|
232
|
+
parallelAxis: [EVERY],
|
|
233
|
+
calendar: [EVERY],
|
|
234
|
+
matrix: [EVERY],
|
|
235
|
+
toolbox: [FALSY_NOT_NULL, 'layout', 'toolbox'],
|
|
236
|
+
tooltip: [EVERY],
|
|
237
|
+
axisPointer: [{ value: ['falsy'], entries: [] }, 'axisPointer'],
|
|
238
|
+
// Any brush value but `null` adds the brush buttons to the toolbox: none is without effect.
|
|
239
|
+
brush: [{ value: [], entries: [] }, 'brush', 'brushToolbox'],
|
|
240
|
+
timeline: [FALSY_NOT_NULL, 'layout', 'timeline'],
|
|
241
|
+
legend: [FALSY, 'layout'],
|
|
242
|
+
dataZoom: [FALSY, 'layout'],
|
|
243
|
+
visualMap: [FALSY, 'layout'],
|
|
244
|
+
thumbnail: [EVERY],
|
|
245
|
+
graphic: [EVERY],
|
|
246
|
+
series: [EVERY]
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/** The option with `null` root options absent and each component option skipping what its runtime skips. */
|
|
250
|
+
function withRootMerge(root, definitions, optionName) {
|
|
251
|
+
const option = definitions[optionName];
|
|
252
|
+
if (option?.kind !== 'object') throw changed(optionName);
|
|
253
|
+
const cite = (fact) => ({ source: 'echarts', pointer: runtimePointer(root, 'echarts', fact) });
|
|
254
|
+
const listed = [cite(ROOT_MERGE.listed), cite(ROOT_MERGE.skipped)];
|
|
255
|
+
const properties = { ...option.properties };
|
|
256
|
+
for (const [key, [skips, ...throwing]] of Object.entries(COMPONENTS)) {
|
|
257
|
+
const property = properties[key];
|
|
258
|
+
if (property === undefined) throw changed(`${optionName}.${key}`);
|
|
259
|
+
const sources = [...property.provenance.sources, ...listed, ...throwing.map((name) => cite(THROWS[name]))];
|
|
260
|
+
properties[key] = { ...property, skips, provenance: { ...property.provenance, sources } };
|
|
261
|
+
}
|
|
262
|
+
const provenance = { ...option.provenance, sources: [...option.provenance.sources, cite(ROOT_MERGE.nullSkipped)] };
|
|
263
|
+
return { ...definitions, [optionName]: { ...option, nullAsAbsent: true, provenance, properties } };
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* `hoverOffset` on a pie or gauge series: the backward-compat preprocessor means to copy it into
|
|
268
|
+
* `emphasis.scaleSize`, but its test is an assignment (`if (seriesOpt.emphasis.scaleSize = null)`),
|
|
269
|
+
* so it never copies and it erases `emphasis.scaleSize`. Declared, citing that line, so the
|
|
270
|
+
* `echarts/hover-offset` rule can say what it does instead of an unknown key; any value has the same
|
|
271
|
+
* effect, so its type is not stated (CG-02-11).
|
|
272
|
+
*/
|
|
273
|
+
const HOVER_OFFSET = { file: 'lib/preprocessor/backwardCompat.js', pattern: 'if (seriesOpt.hoverOffset != null) {' };
|
|
274
|
+
const HOVER_OFFSET_SERIES = ['PieSeriesOption$1', 'GaugeSeriesOption$1'];
|
|
275
|
+
|
|
276
|
+
function withHoverOffset(root, definitions) {
|
|
277
|
+
const pointer = runtimePointer(root, 'echarts', HOVER_OFFSET);
|
|
278
|
+
const next = { ...definitions };
|
|
279
|
+
for (const name of HOVER_OFFSET_SERIES) {
|
|
280
|
+
const series = next[name];
|
|
281
|
+
if (series?.kind !== 'object' || series.properties.hoverOffset !== undefined) throw changed(`${name}.hoverOffset`);
|
|
282
|
+
const hoverOffset = {
|
|
283
|
+
node: { kind: 'unknown' },
|
|
284
|
+
provenance: { confidence: 'authoritative', sources: [{ source: 'echarts', pointer }] }
|
|
285
|
+
};
|
|
286
|
+
next[name] = { ...series, properties: { ...series.properties, hoverOffset } };
|
|
287
|
+
}
|
|
288
|
+
return next;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/** New definitions where a matrix cell's `children` also take strings, citing the runtime line. */
|
|
292
|
+
export function withRuntimeFacts(root, definitions, optionName) {
|
|
293
|
+
const cell = definitions.MatrixDimensionCellOption;
|
|
294
|
+
const children = cell?.properties.children;
|
|
295
|
+
if (children?.node.kind !== 'array') throw changed('MatrixDimensionCellOption.children');
|
|
296
|
+
const pointer = runtimePointer(root, 'echarts', CELLS);
|
|
297
|
+
const items = { kind: 'union', anyOf: [{ kind: 'string' }, children.node.items] };
|
|
298
|
+
const provenance = {
|
|
299
|
+
...children.provenance,
|
|
300
|
+
sources: [...children.provenance.sources, { source: 'echarts', pointer }]
|
|
301
|
+
};
|
|
302
|
+
const widened = { ...children, node: { kind: 'array', items }, provenance };
|
|
303
|
+
const facts = withEc4TextStyle(
|
|
304
|
+
root,
|
|
305
|
+
withGraphicFacts(root, {
|
|
306
|
+
...definitions,
|
|
307
|
+
MatrixDimensionCellOption: { ...cell, properties: { ...cell.properties, children: widened } }
|
|
308
|
+
})
|
|
309
|
+
);
|
|
310
|
+
return withHoverOffset(root, withRootMerge(root, facts, optionName));
|
|
311
|
+
}
|
package/lib/echarts.mjs
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { resolveComponentSubtypes } from './echarts-components.mjs';
|
|
2
|
+
import { withDeprecatedAliases } from './echarts-deprecations.mjs';
|
|
3
|
+
import { addComponentHandlers } from './echarts-handlers.mjs';
|
|
4
|
+
import { withRuntimeFacts } from './echarts-runtime.mjs';
|
|
5
|
+
import { TypeEmitter } from './emitter.mjs';
|
|
6
|
+
import { upstreamChanged } from './nodes.mjs';
|
|
7
|
+
import { createEntryProgram, exportedAliasTypes } from './program.mjs';
|
|
8
|
+
import { runtimeProvenance } from './runtime.mjs';
|
|
9
|
+
import { artifactOf, typeLookups, unionMembers } from './types.mjs';
|
|
10
|
+
|
|
11
|
+
const SOURCE_ID = 'echarts';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* `EChartsOption` is what `chart.setOption(option)` accepts with the full `echarts` bundle.
|
|
15
|
+
* `echarts/core` + `use([...])` registers fewer: the runtime rejects an unregistered series or
|
|
16
|
+
* component subtype. Each variant is registered as `<mainType>.<subType>` (`series.bar`,
|
|
17
|
+
* `dataZoom.inside`), which the series and component unions name as their registry.
|
|
18
|
+
*/
|
|
19
|
+
const ENTRY = ["import type { EChartsOption } from 'echarts';", 'export type Option = EChartsOption;'].join('\n');
|
|
20
|
+
|
|
21
|
+
const changed = upstreamChanged('echarts types');
|
|
22
|
+
const SERIES_LOOKUP = {
|
|
23
|
+
file: 'lib/model/Global.js',
|
|
24
|
+
pattern: 'error("Series " + subType + " is used but not imported.'
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** The `xAxis` variant whose `type` literal is `axisType`. */
|
|
28
|
+
function axisVariant(lookups, checker, option, axisType) {
|
|
29
|
+
const variant = unionMembers(lookups.propertyType(option, 'xAxis')).find((member) => {
|
|
30
|
+
if (checker.isArrayType(member)) return false;
|
|
31
|
+
const type = checker.getPropertyOfType(member, 'type');
|
|
32
|
+
return type !== undefined && checker.typeToString(checker.getTypeOfSymbol(type)).includes(`"${axisType}"`);
|
|
33
|
+
});
|
|
34
|
+
if (variant === undefined) throw changed(`no "${axisType}" xAxis variant`);
|
|
35
|
+
return variant;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* `NumericAxisBaseOptionCommon.boundaryGap` is declared as a `[gap, gap]` tuple, but the runtime
|
|
40
|
+
* (lib/coord/scaleRawExtentInfo.js `parseBoundaryGapOption`) accepts a boolean on value, log and
|
|
41
|
+
* time axes and treats it as no gap; the official examples use `boundaryGap: false` on time axes.
|
|
42
|
+
*/
|
|
43
|
+
function boundaryGapDeclaration(lookups, checker, option) {
|
|
44
|
+
const declaration = lookups.property(axisVariant(lookups, checker, option, 'value'), 'boundaryGap').declarations?.[0];
|
|
45
|
+
if (declaration?.parent?.name?.text !== 'NumericAxisBaseOptionCommon')
|
|
46
|
+
throw changed('boundaryGap is no longer declared on NumericAxisBaseOptionCommon');
|
|
47
|
+
return declaration;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Positions where the declarations are narrower or wider than the runtime contract:
|
|
52
|
+
* `RegisteredSeriesOption` is documented as the declaration-merging point for extension
|
|
53
|
+
* series (`echarts-wordcloud`, `echarts-liquidfill`), so the series union is extensible;
|
|
54
|
+
* numeric axes accept a boolean `boundaryGap` (see `boundaryGapDeclaration`).
|
|
55
|
+
*/
|
|
56
|
+
function contractAdjustments(root, lookups, checker, aliases) {
|
|
57
|
+
const option = aliases.get('Option');
|
|
58
|
+
const series = lookups.propertyType(option, 'series');
|
|
59
|
+
const list = unionMembers(series).find((member) => checker.isArrayType(member));
|
|
60
|
+
if (list === undefined) throw changed('series is no longer `SeriesOption | SeriesOption[]`');
|
|
61
|
+
const registered = {
|
|
62
|
+
registry: { id: 'echarts', prefix: 'series.', enforced: true },
|
|
63
|
+
// Extension series (`series.wordCloud`) are added through `withExtensions` (CG-02-05).
|
|
64
|
+
extensionPoint: 'echarts',
|
|
65
|
+
provenance: runtimeProvenance(root, { sourceId: SOURCE_ID, packageName: 'echarts' }, SERIES_LOOKUP)
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
registries: new Map([series, lookups.elementType(list)].map((type) => [type, registered])),
|
|
69
|
+
widened: new Map([[boundaryGapDeclaration(lookups, checker, option), [{ kind: 'boolean' }]]])
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function generateEcharts(root, pin) {
|
|
74
|
+
const { program, checker, entry } = createEntryProgram(root, ENTRY);
|
|
75
|
+
const aliases = exportedAliasTypes(checker, entry);
|
|
76
|
+
const adjustments = contractAdjustments(root, typeLookups(checker, 'echarts'), checker, aliases);
|
|
77
|
+
const emitter = new TypeEmitter({ program, checker, sourceId: SOURCE_ID, packageName: pin.package, ...adjustments });
|
|
78
|
+
const optionRef = emitter.reference(aliases.get('Option'));
|
|
79
|
+
resolveComponentSubtypes(root, emitter.definitions, emitter.definitions[optionRef.ref]);
|
|
80
|
+
addComponentHandlers(root, emitter.definitions[optionRef.ref]);
|
|
81
|
+
const definitions = withRuntimeFacts(
|
|
82
|
+
root,
|
|
83
|
+
withDeprecatedAliases(root, emitter.definitions, optionRef.ref),
|
|
84
|
+
optionRef.ref
|
|
85
|
+
);
|
|
86
|
+
// `EChartsOption` is open: extension components (`bmap`, echarts-gl's `globe`) are root options (CG-02-05).
|
|
87
|
+
definitions[optionRef.ref] = { ...definitions[optionRef.ref], extensionPoint: 'echarts.options' };
|
|
88
|
+
return artifactOf({ library: 'echarts', sourceId: SOURCE_ID, pin, definitions, root: optionRef });
|
|
89
|
+
}
|