@aparte/plugin-echarts 0.0.0-stage → 0.29.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 +200 -2
- package/dist/core.d.ts +64 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +974 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/option.d.ts +63 -0
- package/dist/option.d.ts.map +1 -0
- package/dist/strings.d.ts +103 -0
- package/dist/strings.d.ts.map +1 -0
- package/dist/theme.d.ts +56 -0
- package/dist/theme.d.ts.map +1 -0
- package/package.json +64 -3
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sources":["../src/option.ts","../src/theme.ts","../src/strings.ts","../src/core.ts"],"sourcesContent":["/**\n * Reading an ECharts `option` that a model wrote or a tool returned: making it harmless,\n * reading a fence that is still arriving, and the words and numbers a screen reader gets.\n * Pure — no DOM, no ECharts — so all of it can be checked in Node.\n */\n\nexport type EChartsOption = Record<string, unknown>;\n\n/** Deeper than any real option; past it, the rest is dropped rather than walked. */\nconst MAX_DEPTH = 64;\n/** The most rows the hidden table reads out. */\nconst MAX_ROWS = 1000;\n/** The most columns it reads out: a category and 49 series. */\nconst MAX_COLUMNS = 50;\n/** The most cells, its header included, whatever the rows and columns: the table is rebuilt on every frame. */\nconst MAX_CELLS = 10_000;\n\n/** Keys that would reach an object's prototype once an option is merged into another. */\nconst PROTO_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * The keys ECharts writes into a text's `style` attribute in its SVG output\n * (`style=\"font-size:…;font-family:…\"`): a value with a `;` in it would add declarations\n * of its own — a `fill: url(https://…)` that fetches.\n */\nconst FONT_KEYS = new Set(['font', 'fontFamily', 'fontStyle', 'fontWeight', 'fontSize']);\n/** What a font name, size, style or weight is made of — and nothing a declaration needs. */\nexport const SAFE_FONT = /^[\\p{L}\\p{N}\\s,'\"._/%-]*$/u;\n\n/**\n * A string ECharts turns into a request: `image://…` (a symbol, a legend icon, a handle drawn\n * from a picture) and a CSS `url(…)` (a fill or a stroke pointing at another document).\n * Not `curl (…)`: the `url` must start a word. Tested on the string with its CSS escapes\n * read (`cssUnescape`), since zrender copies a colour into a `fill` / `stroke` attribute as\n * it is, and CSS reads `u\\rl(` or `\\75 rl(` as `url(` there.\n */\nconst IMAGE_SCHEME = /^\\s*image:\\/\\//i;\nconst CSS_URL = /(^|[^\\w-])(url|src)\\s*\\(/i;\n/** A CSS escape: up to six hex digits and the one space that may end them, or any other character. */\nconst CSS_ESCAPE = /\\\\(?:([0-9a-f]{1,6})[ \\t\\n\\r\\f]?|([^\\n\\r\\f]))/gi;\n\n/**\n * What a colour may be where ECharts draws one: a name (`red`, `transparent`, `none`, and the\n * words ECharts reads itself — `auto`, `inherit`, `source`), `#hex`, or `rgb()` / `rgba()` /\n * `hsl()` / `hsla()` holding only numbers. A gradient or a pattern is an OBJECT, which ECharts\n * builds itself, and is walked like any other.\n */\nconst SAFE_COLOUR = /^\\s*(?:[a-z]+|#[0-9a-f]{3,8}|(?:rgba?|hsla?)\\(\\s*[\\d.,%\\s/+-]*(?:deg)?[\\d.,%\\s/+-]*\\))\\s*$/i;\n/**\n * The keys zrender reads a colour from: `fill`, `stroke`, and any key naming a colour —\n * `color`, every `…Color`, a candlestick's `color0` / `borderColor0` / `borderColorDoji`. The\n * few that hold no colour (`colorBy`, `colorAlpha`…) hold a word or a number, which pass.\n */\nconst isColourKey = (key: string): boolean => key === 'fill' || key === 'stroke' || /(^c|C)olor/.test(key);\n\n/** `s` as CSS reads it once its escapes are decoded. */\nfunction cssUnescape(s: string): string {\n return s.replace(CSS_ESCAPE, (_all, hex: string | undefined, other: string | undefined) => {\n if (other !== undefined) return other;\n const code = parseInt(hex!, 16);\n return code === 0 || code > 0x10ffff || (code >= 0xd800 && code <= 0xdfff) ? '�' :String.fromCodePoint(code);\n });\n}\n\n/**\n * Keys ECharts compiles: a dataset `filter` transform's `reg` is `new RegExp(…)` run on every\n * value, and a pattern a model wrote can backtrack for minutes (`^(a+)+$`).\n */\nconst COMPILED_KEYS = new Set(['reg']);\n\n/** The tooltip options that only an HTML tooltip reads: its class, its CSS, where it is put. */\nconst HTML_TOOLTIP_KEYS = ['extraCssText', 'className', 'appendTo', 'appendToBody'];\n/** The toolbox buttons that leave the drawing: a download / new tab, and an HTML table. */\nconst HTML_FEATURES = ['saveAsImage', 'dataView'];\n\nconst isObject = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v);\n\n/**\n * An ECharts option made harmless to draw. The option comes from a model or a tool, so\n * whatever in it ECharts would turn into HTML, a request or a navigation goes:\n *\n * - every `tooltip` (the root's, a series', a data item's) is drawn, not written as HTML:\n * `renderMode: 'richText'`, and the HTML-only `extraCssText`, `className`, `appendTo`,\n * `appendToBody` go. A string `formatter` stays — in rich-text mode it is drawn as text;\n * - `toolbox.feature.saveAsImage` (a download, or a new tab) and `dataView` (an HTML table\n * with a textarea) go;\n * - a value with an `image` (a picture fill, a rich-text background) or an `svgElement` (an\n * SVG pattern ECharts would build node by node — a `<script>` included) goes whole, and so\n * does a `graphic` element of `type: 'image'`;\n * - a string `image://…` (a symbol, an icon) or holding a CSS `url(…)` goes, its CSS escapes\n * read first; so does any string pairing a backslash with a bracket;\n * - where a colour goes (`color`, `fill`, `stroke`, any `…Color`), only colour syntax stays:\n * zrender copies it into an SVG attribute as it is;\n * - a dataset filter's `reg` goes: ECharts compiles it, and a pattern can backtrack for minutes;\n * - a string `link` / `sublink` (a title, a treemap or sunburst node: ECharts opens it on a\n * click, and a `javascript:` URL would run in the page) goes;\n * - a font value with anything beyond a font name in it (`;`, `:`, brackets) goes: ECharts\n * writes it into a `style` attribute;\n * - `__proto__`, `constructor` and `prototype` keys go.\n *\n * Anything else is kept as it was. `null` when the option is not an object.\n */\nexport function sanitizeEChartsOption(option: unknown): EChartsOption | null {\n if (!isObject(option)) return null;\n const clean = walk(option, '', 0);\n return isObject(clean) ? clean : null;\n}\n\nfunction walk(value: unknown, key: string, depth: number): unknown {\n if (depth > MAX_DEPTH) return undefined;\n if (typeof value === 'string') {\n if (IMAGE_SCHEME.test(value) || CSS_URL.test(value) || CSS_URL.test(cssUnescape(value))) return undefined;\n // Whatever an escape could spell, a backslash beside a bracket is no label anyone writes.\n if (value.includes('\\\\') && value.includes('(')) return undefined;\n if (isColourKey(key) && !SAFE_COLOUR.test(value)) return undefined;\n if (FONT_KEYS.has(key) && !SAFE_FONT.test(value)) return undefined;\n if (key === 'link' || key === 'sublink') return undefined;\n return value;\n }\n if (Array.isArray(value)) {\n const out: unknown[] = [];\n for (const item of value) {\n const clean = walk(item, key, depth + 1);\n // A dropped object leaves no hole (a graphic element, a feature); a dropped\n // value keeps its place, so the data after it keeps its index.\n if (clean !== undefined) out.push(clean);\n else if (!isObject(item)) out.push(null);\n }\n return out;\n }\n if (!isObject(value)) return value;\n if ('image' in value || 'svgElement' in value || value['type'] === 'image') return undefined;\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n if (PROTO_KEYS.has(k) || COMPILED_KEYS.has(k)) continue;\n const clean = walk(v, k, depth + 1);\n if (clean !== undefined) out[k] = clean;\n }\n if (key === 'tooltip') {\n out['renderMode'] = 'richText';\n for (const k of HTML_TOOLTIP_KEYS) delete out[k];\n }\n if (key === 'feature') for (const k of HTML_FEATURES) delete out[k];\n return out;\n}\n\n/**\n * The option a fence holds, read as JSON: the whole of it once it parses, else — while it is\n * still arriving (`open`) — the longest prefix that does once its open brackets are closed,\n * so a series appears as its numbers arrive. `undefined` when nothing parses.\n */\nexport function parseOption(source: string, open = false): unknown {\n try { return JSON.parse(source); } catch { /* still arriving, or broken */ }\n return open ? parsePrefix(source) : undefined;\n}\n\n/**\n * The longest complete-looking prefix of a JSON text, closed. The places it may be cut are\n * where a value has just ended — before a `,`, after a `}` or a `]` — or a container has\n * just opened, and at each the brackets still open are known. Never inside a string: a\n * label half written is not drawn.\n */\nfunction parsePrefix(source: string): unknown {\n const stack: string[] = [];\n const cuts: Array<{ at: number; closers: string }> = [];\n const cut = (at: number): void => {\n cuts.push({ at, closers: stack.slice().reverse().join('') });\n if (cuts.length > 8) cuts.shift();\n };\n let inString = false;\n let escaped = false;\n for (let i = 0; i < source.length; i++) {\n const ch = source[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') inString = true;\n else if (ch === '{' || ch === '[') { stack.push(ch === '{' ? '}' : ']'); cut(i + 1); }\n else if (ch === '}' || ch === ']') { stack.pop(); cut(i + 1); }\n else if (ch === ',') cut(i);\n }\n for (let i = cuts.length - 1; i >= 0; i--) {\n const { at, closers } = cuts[i]!;\n try { return JSON.parse(source.slice(0, at) + closers); } catch { /* an earlier cut */ }\n }\n return undefined;\n}\n\nconst list = (v: unknown): unknown[] => (Array.isArray(v) ? v : v === undefined ? [] : [v]);\n\n/**\n * Whether an option has something to draw yet: a series, or a dataset — at its root, or in\n * the `baseOption` (and timeline `options`) an option with a timeline or media queries keeps\n * them in.\n */\nexport function drawable(option: EChartsOption): boolean {\n const has = (o: unknown): boolean => {\n if (!isObject(o)) return false;\n const series = o['series'];\n if (Array.isArray(series) ? series.some(isObject) : isObject(series)) return true;\n return o['dataset'] !== undefined;\n };\n return has(option) || has(option['baseOption']) || list(option['options']).some(has);\n}\n\n/** The option's own title — its first `title.text` — if it has one. */\nexport function titleOf(option: EChartsOption): string | undefined {\n const title = list(option['title'])[0];\n const text = isObject(title) ? title['text'] : undefined;\n return typeof text === 'string' && text.trim() ? text.trim() : undefined;\n}\n\n/** One cell as a screen reader hears it. */\nfunction cell(v: unknown): string {\n if (v === null || v === undefined) return '';\n if (typeof v === 'string') return v;\n if (typeof v === 'number' || typeof v === 'boolean') return String(v);\n if (Array.isArray(v)) return v.map(cell).join(', ');\n if (isObject(v)) return cell(v['value']);\n return '';\n}\n\nexport interface ChartTable {\n head: string[];\n rows: string[][];\n /** Set when the chart holds more than the table lists: past `MAX_COLUMNS`, `MAX_ROWS` or `MAX_CELLS`. */\n cut?: true;\n}\n\n/**\n * A table `width` columns by `height` rows, read cell by cell, held to the bounds: a model's\n * few bytes (ten thousand empty series beside a thousand categories) never become millions of\n * cells, built again on every frame of a chart still arriving. `null` when it has no column.\n */\nfunction grid(width: number, height: number, headAt: (c: number) => string, cellAt: (r: number, c: number) => string): ChartTable | null {\n const columns = Math.min(width, MAX_COLUMNS);\n if (columns <= 0) return null;\n // The header row counts: columns × (rows + 1) stays within MAX_CELLS.\n const rows = Math.max(0, Math.min(height, MAX_ROWS, Math.floor(MAX_CELLS / columns) - 1));\n const table: ChartTable = {\n head: Array.from({ length: columns }, (_, c) => headAt(c)),\n rows: Array.from({ length: rows }, (_, r) => Array.from({ length: columns }, (_, c) => cellAt(r, c))),\n };\n if (columns < width || rows < height) table.cut = true;\n return table;\n}\n\n/**\n * How many rows of a dataset are its header, as ECharts reads `sourceHeader`: a number, `true`\n * for one, `false` for none, and — `'auto'`, the default — one when the first values of the\n * first row hold a string and no number (`null` and `'-'` say nothing).\n */\nfunction headerRows(dataset: Record<string, unknown>, first: unknown[]): number {\n const option = dataset['sourceHeader'];\n if (typeof option === 'number') return Number.isFinite(option) && option > 0 ? Math.floor(option) : 0;\n if (typeof option === 'boolean') return option ? 1 : 0;\n let rows: number | undefined;\n for (const v of first.slice(0, 10)) {\n if (v === null || v === undefined || v === '-') continue;\n if (typeof v === 'string') rows ??= 1;\n else rows = 0;\n }\n return rows ?? 0;\n}\n\n/**\n * The numbers of a chart as a table, when its shape says plainly what they are: a\n * `dataset.source` (rows of values, or of objects), a category axis with series beside it,\n * or a series of named values (a pie, a funnel). `null` for anything else — a scatter of\n * pairs, a graph — which ECharts' own description still reads out. A series with no data\n * has no column; past the bounds, the table is `cut`.\n */\nexport function tableOf(option: EChartsOption): ChartTable | null {\n const dataset = list(option['dataset'])[0];\n const source = isObject(dataset) ? dataset['source'] : undefined;\n if (isObject(dataset) && Array.isArray(source) && source.length > 0) {\n const named = Array.isArray(dataset['dimensions'])\n ? dataset['dimensions'].map((d) => (isObject(d) ? cell(d['name']) : cell(d)))\n : undefined;\n if (Array.isArray(source[0])) {\n const skip = headerRows(dataset, source[0]);\n const rows = source.slice(skip);\n const head = named ?? (skip > 0 ? source[0].map(cell) : []);\n const width = Math.max(head.length, ...rows.slice(0, MAX_ROWS).map((r) => list(r).length));\n return grid(width, rows.length, (c) => head[c] ?? '', (r, c) => cell(list(rows[r])[c]));\n }\n if (isObject(source[0])) {\n const dims = named ?? Object.keys(source[0]);\n return grid(dims.length, source.length, (c) => dims[c]!, (r, c) => {\n const row = source[r];\n return cell(isObject(row) ? row[dims[c]!] : undefined);\n });\n }\n }\n // Each series with its rank among all of them, which an unnamed one is called by.\n const series = list(option['series'])\n .map((s, i) => ({ s, i }))\n .filter((e): e is { s: Record<string, unknown>; i: number } => isObject(e.s) && Array.isArray(e.s['data']) && e.s['data'].length > 0);\n if (series.length === 0) return null;\n const axis = [...list(option['xAxis']), ...list(option['yAxis'])]\n .find((a): a is Record<string, unknown> => isObject(a) && Array.isArray(a['data']));\n const name = ({ s, i }: { s: Record<string, unknown>; i: number }): string => cell(s['name']) || `${i + 1}`;\n const dataOf = (c: number): unknown[] => series[c]!.s['data'] as unknown[];\n if (axis) {\n const categories = axis['data'] as unknown[];\n return grid(series.length + 1, categories.length,\n (c) => (c === 0 ? cell(axis['name']) : name(series[c - 1]!)),\n (r, c) => cell(c === 0 ? categories[r] : dataOf(c - 1)[r]));\n }\n const named = series.find(({ s }) => (s['data'] as unknown[]).some((d) => isObject(d) && 'name' in d));\n if (named) {\n const data = named.s['data'] as unknown[];\n return grid(2, data.length, (c) => (c === 0 ? '' : name(named)), (r, c) => {\n const d = data[r];\n return c === 0 ? cell(isObject(d) ? d['name'] : '') : cell(d);\n });\n }\n return null;\n}\n","/**\n * The chat's look as an ECharts theme.\n *\n * A theme, not values merged into the option, because that is how ECharts layers a look:\n * it sits under every component of its kind (each axis, each legend, each series of a\n * type), and anything the option sets itself wins over it, by ECharts' own rule. And\n * `setTheme()` swaps it on a chart already drawn, so a light/dark switch recolours the\n * chart without drawing it again from nothing.\n */\nimport { SAFE_FONT } from './option.js';\n\n/** The chat's colours and font, resolved, as the theme is built from them. */\nexport interface EChartsTokens {\n /** Text: titles, legends, values (`--aparte-text`). */\n text: string;\n /** Quieter text: axis labels, subtitles (`--aparte-text-muted`). */\n muted: string;\n /** Lines: axes, grid, the tooltip's edge (`--aparte-border`). */\n border: string;\n /** The tooltip's ground (`--aparte-surface-1`). */\n surface: string;\n /** The page behind the chart (`--aparte-bg`): decides dark or light, and the gap between slices. */\n background: string;\n /** The first series' colour (`--aparte-primary`). */\n primary: string;\n /** The chat's font (`--aparte-font-family`). Left out, ECharts' own. */\n fontFamily?: string;\n /** Dark or light; left out, read from `background`. */\n dark?: boolean;\n}\n\n/**\n * The series colours after the primary, light and dark. They are the eight hues of a\n * palette validated for colour-vision deficiency (adjacent pairs ≥ 8 ΔE in OKLab ×100 under\n * protanopia, deuteranopia and tritanopia, ≥ 15 for full-colour vision), each stepped once for\n * a light ground and once for a dark one — so a series stays the same hue across the switch\n * and keeps 3:1 against the dark ground. Not cycled from a generator: a ninth series repeats.\n */\nexport const ECHARTS_SERIES_HUES = {\n light: ['#2a78d6', '#eb6834', '#1baf7a', '#eda100', '#e87ba4', '#008300', '#6250d6', '#e34948'],\n dark: ['#3987e5', '#d95926', '#199e70', '#c98500', '#d55181', '#008300', '#9085e9', '#e66767'],\n} as const;\n\n/** `#rgb`, `#rrggbb`, `rgb()` / `rgba()` as 0–255 channels; `null` for anything else. */\nexport function rgbOf(color: string): [number, number, number] | null {\n const c = color.trim();\n const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})(?:[0-9a-f]{2})?$/i.exec(c)?.[1];\n if (hex) {\n const full = hex.length === 3 ? hex.split('').map((h) => h + h).join('') : hex;\n return [0, 2, 4].map((i) => parseInt(full.slice(i, i + 2), 16)) as [number, number, number];\n }\n const fn = /^rgba?\\(\\s*([\\d.]+)[\\s,]+([\\d.]+)[\\s,]+([\\d.]+)/i.exec(c);\n return fn ? [Number(fn[1]), Number(fn[2]), Number(fn[3])] : null;\n}\n\n/** sRGB → OKLab: the space where a distance is a difference a person sees. */\nfunction oklab([r, g, b]: [number, number, number]): [number, number, number] {\n const lin = (v: number): number => { const s = v / 255; return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4; };\n const [lr, lg, lb] = [lin(r), lin(g), lin(b)];\n const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);\n const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);\n const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);\n return [\n 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n ];\n}\n\n/** Whether a ground is dark: its OKLab lightness under 0.6. An unreadable colour reads light. */\nexport function isDark(color: string): boolean {\n const rgb = rgbOf(color);\n return rgb ? oklab(rgb)[0] < 0.6 : false;\n}\n\n/**\n * The series colours: the chat's primary first, then the validated hues. The primary takes\n * the place of the hue nearest to it, and the ring is read on from there — so a brass\n * primary does not sit beside the yellow it nearly is, and every pair that ends up side by\n * side is one the validation already passed.\n */\nexport function echartsPalette(primary: string, dark = false): string[] {\n const ring: string[] = [...(dark ? ECHARTS_SERIES_HUES.dark : ECHARTS_SERIES_HUES.light)];\n const rgb = rgbOf(primary);\n if (!rgb) return [primary, ...ring];\n const p = oklab(rgb);\n // Nearest by hue — a brass is the yellow's twin however much darker it is — unless the\n // primary is all but grey, where a hue means nothing and the plain distance decides.\n const grey = Math.hypot(p[1], p[2]) < 0.04;\n const hueOf = (c: number[]): number => Math.atan2(c[2]!, c[1]!);\n const distance = (q: number[]): number => {\n if (grey) return Math.hypot(p[0] - q[0]!, p[1] - q[1]!, p[2] - q[2]!);\n const d = Math.abs(hueOf(p) - hueOf(q));\n return Math.min(d, 2 * Math.PI - d);\n };\n let nearest = 0;\n let best = Infinity;\n ring.forEach((hue, i) => {\n const d = distance(oklab(rgbOf(hue)!));\n if (d < best) { best = d; nearest = i; }\n });\n return [primary, ...ring.slice(nearest + 1), ...ring.slice(0, nearest)];\n}\n\n/**\n * The ECharts theme the chat's tokens make: text, muted axis labels, grid and axis lines,\n * a transparent ground, the chat's font, the series palette, a tooltip on the chat's\n * surface. Hand it to `init` or `setTheme`; whatever the option sets itself wins over it.\n * Pure: the same tokens make the same theme, in Node as in a browser.\n */\nexport function echartsTheme(tokens: EChartsTokens): Record<string, unknown> {\n const { text, muted, border, surface, background } = tokens;\n const dark = tokens.dark ?? isDark(background);\n const font = tokens.fontFamily && SAFE_FONT.test(tokens.fontFamily) ? { fontFamily: tokens.fontFamily } : {};\n const axis = (splitLine: boolean) => ({\n axisLine: { lineStyle: { color: border } },\n axisTick: { lineStyle: { color: border } },\n axisLabel: { color: muted },\n nameTextStyle: { color: muted },\n splitLine: { show: splitLine, lineStyle: { color: border } },\n minorSplitLine: { lineStyle: { color: border } },\n splitArea: { areaStyle: { color: ['transparent', surface] } },\n });\n return {\n darkMode: dark,\n color: echartsPalette(tokens.primary, dark),\n backgroundColor: 'transparent',\n textStyle: { color: text, ...font },\n title: { textStyle: { color: text }, subtextStyle: { color: muted } },\n legend: {\n textStyle: { color: text },\n pageTextStyle: { color: muted },\n pageIconColor: text,\n pageIconInactiveColor: border,\n inactiveColor: border,\n },\n tooltip: { backgroundColor: surface, borderColor: border, textStyle: { color: text } },\n axisPointer: {\n lineStyle: { color: muted },\n crossStyle: { color: muted },\n label: { color: surface, backgroundColor: muted },\n },\n // A category axis draws no grid by default, in ECharts as here.\n categoryAxis: axis(false),\n valueAxis: axis(true),\n logAxis: axis(true),\n timeAxis: axis(true),\n radar: {\n axisName: { color: muted },\n axisLine: { lineStyle: { color: border } },\n splitLine: { lineStyle: { color: border } },\n splitArea: { areaStyle: { color: ['transparent', surface] } },\n },\n dataZoom: {\n borderColor: border,\n textStyle: { color: muted },\n handleStyle: { color: surface, borderColor: muted },\n moveHandleStyle: { color: muted },\n dataBackground: { lineStyle: { color: muted }, areaStyle: { color: border } },\n },\n visualMap: { textStyle: { color: text } },\n timeline: {\n lineStyle: { color: border },\n label: { color: muted },\n controlStyle: { color: muted, borderColor: muted },\n },\n toolbox: { iconStyle: { borderColor: muted } },\n calendar: {\n itemStyle: { color: 'transparent', borderColor: border },\n splitLine: { lineStyle: { color: muted } },\n dayLabel: { color: muted },\n monthLabel: { color: muted },\n yearLabel: { color: text },\n },\n gauge: { title: { color: muted }, detail: { color: text }, axisLabel: { color: muted } },\n // The gap between two slices is the ground showing through.\n pie: { itemStyle: { borderColor: background } },\n funnel: { itemStyle: { borderColor: background } },\n sunburst: { itemStyle: { borderColor: background } },\n map: { label: { color: text }, itemStyle: { areaColor: surface, borderColor: border } },\n geo: { label: { color: text }, itemStyle: { areaColor: surface, borderColor: border } },\n };\n}\n\n/** The tokens a chart reads, with the colour each falls back to. */\nconst TOKENS = {\n text: ['--aparte-text', '#1a1a1a'],\n muted: ['--aparte-text-muted', '#666666'],\n border: ['--aparte-border', '#d0d0d0'],\n surface: ['--aparte-surface-1', '#fafafa'],\n background: ['--aparte-bg', '#ffffff'],\n primary: ['--aparte-primary', '#3b5bdb'],\n} as const;\n\n/**\n * The tokens as they apply at `el`, each resolved by the browser. A token may be\n * `color-mix()` or `oklch()`, which ECharts' colour parser cannot read (it derives hover and\n * label colours from them), so each is painted on a one-pixel canvas and read back as\n * `rgb()` — whatever the browser's own serialisation of it.\n */\nexport function readTokens(el: HTMLElement): EChartsTokens {\n const style = getComputedStyle(el);\n const probe = document.createElement('span');\n probe.style.display = 'none';\n el.appendChild(probe);\n const canvas = document.createElement('canvas');\n canvas.width = canvas.height = 1;\n const paint = canvas.getContext?.('2d', { willReadFrequently: true }) ?? null;\n const read = (token: string, fallback: string): string => {\n probe.style.color = `var(${token}, ${fallback})`;\n const computed = getComputedStyle(probe).color || fallback;\n if (!paint) return computed;\n paint.clearRect(0, 0, 1, 1);\n paint.fillStyle = '#000';\n paint.fillStyle = computed;\n paint.fillRect(0, 0, 1, 1);\n const [r, g, b, a] = paint.getImageData(0, 0, 1, 1).data;\n return a === 255 ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${((a ?? 0) / 255).toFixed(3)})`;\n };\n try {\n const tokens = Object.fromEntries(\n Object.entries(TOKENS).map(([name, [token, fallback]]) => [name, read(token, fallback)]),\n ) as unknown as EChartsTokens;\n const font = style.getPropertyValue('--aparte-font-family').trim() || style.fontFamily;\n if (font) tokens.fontFamily = font;\n return tokens;\n } finally {\n probe.remove();\n }\n}\n","/**\n * The words a chart draws, in the chat's language.\n *\n * Core's locale is a closed list of what CORE draws, so a plugin reads its own keys off\n * `getLocale()` and defaults them at the call site. This package carries its few words in\n * the ten languages `@aparte/locales` ships, picked by the locale's `tag`; a key the app\n * sets wins, and a language the table does not have reads English.\n *\n * aparteGlobalConfig.extendLocale({ echartsChart: 'Courbe' });\n */\nimport type { AparteConfig } from '@aparte/core';\n\ntype Language = 'fr' | 'de' | 'es' | 'it' | 'ja' | 'ko' | 'pt' | 'ru' | 'zh';\ntype Word = { en: string } & Record<Language, string>;\n\nexport const WORDS = {\n echartsChart: {\n en: 'Chart', fr: 'Graphique', de: 'Diagramm', es: 'Gráfico', it: 'Grafico',\n ja: 'グラフ', ko: '차트', pt: 'Gráfico', ru: 'Диаграмма', zh: '图表',\n },\n echartsError: {\n en: 'This chart could not be drawn.', fr: 'Ce graphique n’a pas pu être dessiné.',\n de: 'Dieses Diagramm konnte nicht gezeichnet werden.', es: 'No se pudo dibujar este gráfico.',\n it: 'Impossibile disegnare questo grafico.', ja: 'このグラフを描画できませんでした。',\n ko: '이 차트를 그릴 수 없습니다.', pt: 'Não foi possível desenhar este gráfico.',\n ru: 'Не удалось построить эту диаграмму.', zh: '无法绘制此图表。',\n },\n echartsLoading: {\n en: 'Loading chart', fr: 'Chargement du graphique', de: 'Diagramm wird geladen', es: 'Cargando gráfico',\n it: 'Caricamento del grafico', ja: 'グラフを読み込み中', ko: '차트 불러오는 중', pt: 'Carregando gráfico',\n ru: 'Загрузка диаграммы', zh: '正在加载图表',\n },\n echartsWaiting: {\n en: 'Waiting for your approval', fr: 'En attente de votre accord', de: 'Wartet auf Ihre Zustimmung',\n es: 'Esperando tu aprobación', it: 'In attesa della tua approvazione', ja: '承認を待っています',\n ko: '승인을 기다리는 중', pt: 'Aguardando sua aprovação', ru: 'Ожидает вашего подтверждения', zh: '等待您的批准',\n },\n echartsNotRun: {\n en: 'No chart: the tool did not run.', fr: 'Pas de graphique : l’outil n’a pas été exécuté.',\n de: 'Kein Diagramm: Das Werkzeug wurde nicht ausgeführt.', es: 'Sin gráfico: la herramienta no se ejecutó.',\n it: 'Nessun grafico: lo strumento non è stato eseguito.', ja: 'グラフなし:ツールは実行されませんでした。',\n ko: '차트 없음: 도구가 실행되지 않았습니다.', pt: 'Sem gráfico: a ferramenta não foi executada.',\n ru: 'Нет диаграммы: инструмент не был запущен.', zh: '无图表:工具未运行。',\n },\n echartsFailed: {\n en: 'No chart: the tool failed.', fr: 'Pas de graphique : l’outil a échoué.',\n de: 'Kein Diagramm: Das Werkzeug ist fehlgeschlagen.', es: 'Sin gráfico: la herramienta falló.',\n it: 'Nessun grafico: lo strumento non è riuscito.', ja: 'グラフなし:ツールが失敗しました。',\n ko: '차트 없음: 도구가 실패했습니다.', pt: 'Sem gráfico: a ferramenta falhou.',\n ru: 'Нет диаграммы: инструмент завершился с ошибкой.', zh: '无图表:工具运行失败。',\n },\n echartsTableCut: {\n en: 'Only part of the data is listed.', fr: 'Seule une partie des données est listée.',\n de: 'Nur ein Teil der Daten ist aufgeführt.', es: 'Solo se muestra una parte de los datos.',\n it: 'È elencata solo una parte dei dati.', ja: 'データの一部のみを表示しています。',\n ko: '데이터의 일부만 표시됩니다.', pt: 'Apenas parte dos dados está listada.',\n ru: 'Показана только часть данных.', zh: '仅列出部分数据。',\n },\n} satisfies Record<string, Word>;\n\nexport type WordKey = keyof typeof WORDS;\n\n/** The language part of the locale's tag: `pt-BR` → `pt`, none → `en`. */\nexport function languageOf(config: AparteConfig): string {\n const tag = config.getLocale().tag;\n return typeof tag === 'string' && tag ? tag.split('-')[0]!.toLowerCase() : 'en';\n}\n\n/** The word for `key`: the app's locale first, then this package's table, then English. */\nexport function word(config: AparteConfig, key: WordKey): string {\n const fromApp = (config.getLocale() as Record<string, unknown>)[key];\n if (typeof fromApp === 'string' && fromApp) return fromApp;\n const table: Word = WORDS[key];\n return table[languageOf(config) as Language] ?? table.en;\n}\n","import {\n aparteGlobalConfig,\n escapeAttr,\n type AparteConfig,\n type AparteCodeLanguageContext,\n type AparteToolCallSegment,\n type AparteToolMatcher,\n type AparteToolRenderer,\n} from '@aparte/core';\nimport { drawable, parseOption, sanitizeEChartsOption, tableOf, titleOf, type EChartsOption } from './option.js';\nimport { echartsTheme, readTokens } from './theme.js';\nimport { languageOf, word, type WordKey } from './strings.js';\n\nexport { sanitizeEChartsOption, type EChartsOption } from './option.js';\nexport { echartsTheme, echartsPalette, ECHARTS_SERIES_HUES, type EChartsTokens } from './theme.js';\n\n/** The part of a chart ECharts hands back from `init` that this plugin calls. */\nexport interface EChartsInstanceLike {\n setOption(option: Record<string, unknown>, opts?: { notMerge?: boolean }): void;\n setTheme(theme: Record<string, unknown>): void;\n resize(): void;\n dispose(): void;\n}\n\n/**\n * The part of ECharts this plugin calls. Structural, so this module imports nothing from\n * `echarts` — a bundle that hands over its own build (`echarts/core` with the charts it\n * uses) carries one copy.\n */\nexport interface EChartsLike {\n init(dom: HTMLElement, theme?: Record<string, unknown> | string | null, opts?: { renderer?: 'svg' | 'canvas'; locale?: string }): EChartsInstanceLike;\n}\n\nexport interface EChartsOptions {\n /**\n * Redraw a chart while its fence arrives, from the part of its JSON that has arrived\n * (default `true`). `false` draws it once the fence has closed.\n */\n progressive?: boolean;\n /** The chart's height: pixels, or a CSS length (`'18rem'`, the default). It fills the width, up to 40rem. */\n height?: number | string;\n /**\n * ECharts' renderer (default `'svg'`): crisp at any zoom, sized by the page like any\n * element, and its text is real text. `'canvas'` for a chart with tens of thousands of\n * points, where an SVG node per mark costs more than a bitmap.\n */\n renderer?: 'svg' | 'canvas';\n /**\n * The tool (or tools) whose result IS an ECharts option: it is drawn as the chart in\n * place of the tool's row. Its `structuredContent` when it has one, else its text read\n * as JSON — or what `map` makes of it.\n */\n tool?: AparteToolMatcher | AparteToolMatcher[];\n /**\n * Turn a tool's own result (and the arguments it was called with) into an ECharts option.\n * The result is `any`, as in `@aparte/plugin-cards`: its shape is your tool's, and `map` is\n * where you read it.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n map?: (result: any, input: Record<string, unknown>) => unknown;\n}\n\n/** The fence languages this plugin draws. */\nconst LANGUAGES = ['echarts', 'echart'] as const;\n/** The element a chart lives in: its own lifetime is the chart's — see `defineElement`. */\nconst TAG = 'aparte-echarts';\nconst DEFAULT_HEIGHT = '18rem';\nconst MAX_WIDTH = '40rem';\n/** The least time between two drawings of a chart still arriving. */\nconst PROGRESSIVE_MS = 300;\n/**\n * How long a chart taken off the page waits before it is disposed. A Markdown provider\n * rebuilds a block, and core moves a drawing across, within a pass or two: a chart that\n * comes back in that time keeps its instance rather than being drawn again from nothing.\n */\nconst LINGER_MS = 1000;\n/** Unique to this copy of the plugin, so two bundles on one page never answer each other's charts. */\nconst ID_PREFIX = `aparte-echarts-${Math.random().toString(36).slice(2, 8)}`;\nlet setups = 0;\nlet streamIds = 0;\n\nconst isObject = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v);\n\n/**\n * The plugin's setups on this page, by id, shared across copies of the plugin through a\n * global symbol: whichever copy defined the element, the setup that drew a chart answers it.\n */\ninterface Charts {\n connected(el: HTMLElement): void;\n disconnected(el: HTMLElement): void;\n}\nconst REGISTRY = Symbol.for('aparte.plugin-echarts.setups');\nfunction registry(): Map<string, Charts> {\n const scope = globalThis as unknown as Record<symbol, Map<string, Charts> | undefined>;\n return (scope[REGISTRY] ??= new Map());\n}\n\n/**\n * `<aparte-echarts>`: a chart's box. A code-language renderer hands core markup, not a node,\n * and ECharts needs a live element to draw in and to be disposed with — so the markup is\n * this element, which mounts its chart when it reaches the page and lets it go when it\n * leaves. The class only forwards to the setup that drew it.\n */\nfunction defineElement(): void {\n if (typeof customElements === 'undefined' || typeof HTMLElement === 'undefined' || customElements.get(TAG)) return;\n customElements.define(TAG, class extends HTMLElement {\n connectedCallback(): void { registry().get(this.getAttribute('data-aparte-echarts') ?? '')?.connected(this); }\n disconnectedCallback(): void { registry().get(this.getAttribute('data-aparte-echarts') ?? '')?.disconnected(this); }\n });\n}\n\n/**\n * Draw charts with an ECharts you provide — the module, or a function that loads it on the\n * first chart. The entry point for a bundle that controls what it ships:\n * `@aparte/plugin-echarts` itself is this, with `() => import('echarts')`.\n *\n * @returns a disposer that unregisters the renderers, stops watching the theme and\n * disposes every chart on the page.\n * @example\n * import * as echarts from 'echarts';\n * import { setupEChartsWith } from '@aparte/plugin-echarts/core';\n * setupEChartsWith(echarts);\n */\nexport function setupEChartsWith(\n echarts: EChartsLike | (() => Promise<EChartsLike>),\n options: EChartsOptions = {},\n config: AparteConfig = aparteGlobalConfig,\n): () => void {\n const load = typeof echarts === 'function' ? echarts : () => Promise.resolve(echarts);\n defineElement();\n const id = `${ID_PREFIX}-${++setups}`;\n const charts = createCharts(load, options, config);\n registry().set(id, charts);\n const unregister = config.registerCodeLanguageRenderer(createFenceRenderer(id, options, charts));\n const matchers = options.tool === undefined ? [] : Array.isArray(options.tool) ? options.tool : [options.tool];\n const tool = createToolRenderer(id, options, config, charts);\n for (const match of matchers) config.registerToolRenderer(match, tool);\n return () => {\n for (const match of matchers) config.unregisterToolRenderer(match);\n unregister();\n charts.stop();\n registry().delete(id);\n };\n}\n\n/** A height the option gave, as CSS; anything else is the default. */\nfunction cssLength(height: number | string | undefined): string {\n if (typeof height === 'number' && height > 0) return `${height}px`;\n if (typeof height === 'string' && /^\\d+(\\.\\d+)?(px|rem|em|vh|svh|dvh|lh|%)$/.test(height.trim())) return height.trim();\n return DEFAULT_HEIGHT;\n}\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/** A quiet box where a chart will be. */\nfunction skeleton(height: string): HTMLElement {\n const box = document.createElement('span');\n box.className = 'aparte-skeleton aparte-skeleton--rect';\n box.setAttribute('aria-hidden', 'true');\n box.style.setProperty('block-size', height);\n box.style.setProperty('max-inline-size', MAX_WIDTH);\n return box;\n}\n\n/** A sentence in place of a chart. Its text follows the locale (`relabelWords`). */\nfunction note(config: AparteConfig, key: WordKey, className = 'aparte-echarts-note'): HTMLElement {\n const p = document.createElement('p');\n p.className = className;\n p.setAttribute('role', 'note');\n p.setAttribute('data-aparte-echarts-word', key);\n p.textContent = word(config, key);\n return p;\n}\n\nfunction relabelWords(root: Element, config: AparteConfig): void {\n for (const el of Array.from(root.querySelectorAll<HTMLElement>('[data-aparte-echarts-word]'))) {\n el.textContent = word(config, el.getAttribute('data-aparte-echarts-word') as WordKey);\n }\n}\n\n/**\n * The option with what the plugin keeps. ECharts' own description is on, in the plugin's\n * settings: an option's `aria.label.enabled: false`, or a `description` of its own, would\n * make what a screen reader hears differ from what is drawn — only its `decal` (patterns\n * that tell the series apart without colour) is the option's to set. And no motion when it\n * is unwanted (`motionless`).\n */\nfunction finalOption(option: EChartsOption, width = 0): EChartsOption {\n const decal = isObject(option['aria']) && isObject(option['aria']['decal']) ? { decal: option['aria']['decal'] } : {};\n const out: EChartsOption = { ...option, aria: { enabled: true, label: { enabled: true }, ...decal } };\n const title = fittedTitles(option, width);\n if (title !== undefined) out['title'] = title;\n return prefersReducedMotion() ? motionless(out) : out;\n}\n\n/**\n * The option's titles held to the chart's width. ECharts never wraps a title: one a model\n * wrote long (\"Thousands of trips, April 2025 – March 2026\") ran off both sides of a narrow\n * chart. Each is cut with an ellipsis instead — the full title stays the figure's name and\n * the table's caption, so nothing is lost to a screen reader. A title that sets its own\n * width is left as it is.\n */\nfunction fittedTitles(option: EChartsOption, width: number): unknown {\n const titles = option['title'];\n if (width <= 0 || titles === undefined) return undefined;\n const fit = (t: unknown): unknown => {\n if (!isObject(t)) return t;\n const style = isObject(t['textStyle']) ? t['textStyle'] : {};\n if (style['width'] !== undefined) return t;\n return { ...t, textStyle: { ...style, width: Math.max(60, width - 32), overflow: 'truncate' } };\n };\n return Array.isArray(titles) ? titles.map(fit) : fit(titles);\n}\n\n/**\n * `option` with nothing that moves. A root `animation: false` is not enough: ECharts lets a\n * series, a `graphic` component and an option's `baseOption` / timeline `options` / `media`\n * turn it back on, and some motion is not an animation at all — an `effectScatter`'s ripple\n * and a `lines` series' trail loop forever, a timeline plays itself.\n */\nfunction motionless(option: EChartsOption): EChartsOption {\n const still = (o: unknown): unknown => {\n if (!isObject(o)) return o;\n const out: Record<string, unknown> = { ...o, animation: false };\n const series = (s: unknown): unknown => {\n if (!isObject(s)) return s;\n const next: Record<string, unknown> = { ...s, animation: false };\n // The ripple then shows on hover only, the trail not at all.\n if (s['type'] === 'effectScatter') next['showEffectOn'] = 'emphasis';\n if (isObject(s['effect'])) next['effect'] = { ...s['effect'], show: false };\n return next;\n };\n const each = (v: unknown, f: (x: unknown) => unknown): unknown => (Array.isArray(v) ? v.map(f) : f(v));\n if (o['series'] !== undefined) out['series'] = each(o['series'], series);\n if (o['graphic'] !== undefined) out['graphic'] = each(o['graphic'], (g) => (isObject(g) ? { ...g, animation: false } : g));\n if (o['timeline'] !== undefined) out['timeline'] = each(o['timeline'], (t) => (isObject(t) ? { ...t, autoPlay: false } : t));\n return out;\n };\n const out = still(option) as EChartsOption;\n if (isObject(option['baseOption'])) out['baseOption'] = still(option['baseOption']);\n if (Array.isArray(option['options'])) out['options'] = option['options'].map(still);\n if (Array.isArray(option['media'])) {\n out['media'] = option['media'].map((m) => (isObject(m) && isObject(m['option']) ? { ...m, option: still(m['option']) } : m));\n }\n return out;\n}\n\n/** The chart's numbers for a screen reader, or `null` when its shape does not say plainly what they are. */\nfunction tableElement(option: EChartsOption, name: string, config: AparteConfig): HTMLTableElement | null {\n const data = tableOf(option);\n if (!data) return null;\n const table = document.createElement('table');\n table.className = 'aparte-sr-only aparte-echarts-table';\n const caption = table.createCaption();\n caption.textContent = name;\n const headRow = table.createTHead().insertRow();\n for (const text of data.head) {\n const th = document.createElement('th');\n th.scope = 'col';\n th.textContent = text;\n headRow.append(th);\n }\n if (data.cut) {\n // Visually hidden like the table: a reader told the list stops, not left to think the chart does.\n const cell = table.createTFoot().insertRow().insertCell();\n cell.colSpan = data.head.length;\n cell.setAttribute('data-aparte-echarts-word', 'echartsTableCut');\n cell.textContent = word(config, 'echartsTableCut');\n }\n const body = table.createTBody();\n for (const row of data.rows) {\n const tr = body.insertRow();\n row.forEach((text, i) => {\n const cell = document.createElement(i === 0 ? 'th' : 'td');\n if (i === 0) (cell as HTMLTableCellElement).scope = 'row';\n cell.textContent = text;\n tr.append(cell);\n });\n }\n return table;\n}\n\n/** One chart on the page: the box ECharts draws in, its instance, and what it last drew. */\ninterface Chart {\n el: HTMLElement;\n box: HTMLElement;\n table: HTMLTableElement | null;\n instance: EChartsInstanceLike | null;\n option: EChartsOption;\n /** The colours the instance was themed with, so a theme change that changes nothing costs nothing. */\n colours: string;\n observer: ResizeObserver | undefined;\n linger: ReturnType<typeof setTimeout> | undefined;\n dead: boolean;\n}\n\n/** Every chart of one setup: mounting, adopting, theming, resizing and disposing them. */\nfunction createCharts(load: () => Promise<EChartsLike>, options: EChartsOptions, config: AparteConfig) {\n const height = cssLength(options.height);\n let library: Promise<EChartsLike> | undefined;\n // Not poisoned: a failed load is tried again on the next chart.\n const libraryOf = (): Promise<EChartsLike> => (library ??= load().catch((error: unknown) => { library = undefined; throw error; }));\n const states = new WeakMap<HTMLElement, Chart>();\n /** Every chart with an instance or about to have one: what `stop()` disposes. */\n const all = new Set<Chart>();\n /** The charts on the page: what a theme change recolours. */\n const live = new Set<Chart>();\n /** The element showing each chart still arriving: its next frame takes the instance over. */\n const streams = new Map<string, HTMLElement>();\n /** The config each element was drawn for, as core hands it over: its locale names the chart. */\n const configs = new WeakMap<HTMLElement, AparteConfig>();\n const roots = new WeakSet<Node>();\n let warned = false;\n const warnOnce = (error: unknown): void => {\n if (warned) return;\n warned = true;\n console.warn('[aparte-echarts] a chart could not be drawn; a note is shown instead.', error);\n };\n\n const configOf = (el: HTMLElement): AparteConfig => configs.get(el) ?? config;\n const nameOf = (c: Chart): string => titleOf(c.option) ?? word(configOf(c.el), 'echartsChart');\n\n const themeAt = (el: HTMLElement): { theme: Record<string, unknown>; key: string } => {\n const tokens = readTokens(el);\n return { theme: echartsTheme(tokens), key: JSON.stringify(tokens) };\n };\n\n const retheme = (c: Chart): void => {\n if (!c.instance || !c.el.isConnected) return;\n const { theme, key } = themeAt(c.el);\n if (key === c.colours) return;\n c.colours = key;\n c.instance.setTheme(theme);\n };\n const watch = watchTheme(() => { for (const c of live) retheme(c); });\n\n const destroy = (c: Chart): void => {\n c.dead = true;\n clearTimeout(c.linger);\n c.observer?.disconnect();\n c.instance?.dispose();\n c.instance = null;\n live.delete(c);\n all.delete(c);\n if (states.get(c.el) === c) states.delete(c.el);\n const stream = c.el.getAttribute('data-aparte-echarts-stream');\n if (stream && streams.get(stream) === c.el) streams.delete(stream);\n };\n\n const fail = (c: Chart, error: unknown): void => {\n warnOnce(error);\n destroy(c);\n c.el.replaceChildren(note(configOf(c.el), 'echartsError', 'aparte-code-error'));\n };\n\n /** Draw `option` in `c`: its name, its table, and — once ECharts is there — the chart. */\n const apply = (c: Chart, option: EChartsOption, fresh: boolean): void => {\n c.option = option;\n const name = nameOf(c);\n c.el.setAttribute('aria-label', name);\n c.table?.remove();\n c.table = tableElement(option, name, configOf(c.el));\n if (c.table) c.el.append(c.table);\n if (!c.instance) return;\n try {\n // A chart still arriving only grows, so a newer frame is merged into the drawing\n // and ECharts animates the bars that appeared; a chart drawn anew replaces it.\n c.instance.setOption(finalOption(option, c.box.clientWidth), fresh ? { notMerge: true } : undefined);\n } catch (error) {\n fail(c, error);\n }\n };\n\n const watchRoot = (el: HTMLElement): void => {\n const root = el.getRootNode();\n if (typeof ShadowRoot === 'undefined' || !(root instanceof ShadowRoot) || roots.has(root)) return;\n roots.add(root);\n watch.add(root);\n };\n\n const mount = (el: HTMLElement, option: EChartsOption): void => {\n const box = document.createElement('div');\n box.className = 'aparte-echarts-chart';\n box.style.setProperty('block-size', height);\n box.style.setProperty('inline-size', '100%');\n const waiting = skeleton('100%');\n box.append(waiting);\n el.replaceChildren(box);\n const c: Chart = { el, box, table: null, instance: null, option, colours: '', observer: undefined, linger: undefined, dead: false };\n states.set(el, c);\n all.add(c);\n live.add(c);\n apply(c, option, true);\n libraryOf().then((lib) => {\n if (c.dead) return;\n const { theme, key } = themeAt(c.el);\n c.colours = key;\n waiting.remove();\n c.instance = lib.init(box, theme, {\n renderer: options.renderer ?? 'svg',\n // ECharts' own description (aria) in the chat's language, when that language\n // is registered with ECharts; English otherwise.\n locale: languageOf(configOf(c.el)).toUpperCase(),\n });\n if (typeof ResizeObserver !== 'undefined') {\n c.observer = new ResizeObserver(() => {\n if (!c.instance) return;\n try {\n c.instance.resize();\n // The titles are held to the width, which just changed.\n const title = fittedTitles(c.option, c.box.clientWidth);\n if (title !== undefined) c.instance.setOption({ title });\n } catch (error) {\n fail(c, error);\n }\n });\n c.observer.observe(box);\n }\n apply(c, c.option, true);\n }).catch((error: unknown) => { if (!c.dead) fail(c, error); });\n };\n\n return {\n connected(el: HTMLElement): void {\n el.style.setProperty('display', 'block');\n el.style.setProperty('inline-size', '100%');\n el.style.setProperty('max-inline-size', MAX_WIDTH);\n el.setAttribute('role', 'figure');\n watchRoot(el);\n const kept = states.get(el);\n if (kept) {\n // Moved, not replaced: the chart is still in it.\n clearTimeout(kept.linger);\n kept.linger = undefined;\n live.add(kept);\n return;\n }\n const option = sanitizeEChartsOption(parseOption(el.getAttribute('data-aparte-echarts-option') ?? ''));\n if (!option) {\n el.replaceChildren(note(configOf(el), 'echartsError', 'aparte-code-error'));\n return;\n }\n const stream = el.getAttribute('data-aparte-echarts-stream');\n const before = stream ? streams.get(stream) : undefined;\n if (stream) streams.set(stream, el);\n const adopted = before && before !== el && !before.isConnected ? states.get(before) : undefined;\n if (adopted && !adopted.dead) {\n // The next frame of a chart still arriving: it takes the drawing over and\n // updates it, rather than drawing the chart again from nothing.\n clearTimeout(adopted.linger);\n adopted.linger = undefined;\n states.delete(adopted.el);\n adopted.el = el;\n states.set(el, adopted);\n live.add(adopted);\n el.replaceChildren(adopted.box);\n apply(adopted, option, false);\n return;\n }\n mount(el, option);\n },\n disconnected(el: HTMLElement): void {\n const c = states.get(el);\n if (!c) return;\n live.delete(c);\n clearTimeout(c.linger);\n c.linger = setTimeout(() => { if (c.el === el && !el.isConnected) destroy(c); }, LINGER_MS);\n },\n /** The element is gone for good (a tool row's cleanup): no linger. */\n dispose(el: HTMLElement): void {\n const c = states.get(el);\n if (c) destroy(c);\n },\n /** Name a chart in the locale of `cfg`, and keep that config for its later words. */\n label(el: HTMLElement, cfg: AparteConfig): void {\n configs.set(el, cfg);\n const c = states.get(el);\n const name = c ? nameOf(c) : word(cfg, 'echartsChart');\n el.setAttribute('aria-label', name);\n const caption = el.querySelector('caption');\n if (caption) caption.textContent = name;\n relabelWords(el, cfg);\n },\n stop(): void {\n watch.stop();\n for (const c of [...all]) destroy(c);\n },\n };\n}\n\ntype ChartsOf = ReturnType<typeof createCharts>;\n\n/** The ```` ```echarts ```` fence: a chart's box as markup, paced while the fence arrives. */\nfunction createFenceRenderer(setupId: string, options: EChartsOptions, charts: ChartsOf) {\n const progressive = options.progressive !== false;\n const height = cssLength(options.height);\n /**\n * A chart still arriving, by the part of the reply it is in and its rank there — a\n * rebuild replaces its placeholder, never its part: the id its frames share (so each\n * takes the drawing over from the last), the latest source waiting to be drawn, the\n * time of the last drawing, and what it drew.\n */\n interface Arriving {\n id: string;\n waiting: { source: string; answer: (html: string | null) => void } | null;\n timer: ReturnType<typeof setTimeout> | undefined;\n at: number;\n /** The source of the chart this position has started showing, or `null` before its first frame. */\n started: string | null;\n /** The option last drawn, as JSON: a frame that changes nothing is not drawn again. */\n drawn: string | null;\n }\n const parts = new WeakMap<Element, Map<number, Arriving>>();\n\n const arrivingOf = (host: HTMLElement): Arriving => {\n const part = host.closest('[data-segment-id]') ?? host.closest('pre')?.parentElement ?? host.parentElement ?? host;\n const fences = Array.from(part.querySelectorAll(LANGUAGES.map((l) => `code.language-${l}`).join(', ')));\n const rank = Math.max(0, fences.indexOf(host));\n let byRank = parts.get(part);\n if (!byRank) { byRank = new Map(); parts.set(part, byRank); }\n let state = byRank.get(rank);\n if (!state) {\n state = { id: `${setupId}-s${++streamIds}`, waiting: null, timer: undefined, at: 0, started: null, drawn: null };\n byRank.set(rank, state);\n }\n return state;\n };\n\n const markup = (json: string, stream: string): string =>\n `<aparte-echarts class=\"aparte-echarts\" data-aparte-echarts=\"${escapeAttr(setupId)}\" data-aparte-echarts-stream=\"${escapeAttr(stream)}\" data-aparte-echarts-option=\"${escapeAttr(json)}\"></aparte-echarts>`;\n /** A chart's first frame, before it has a series: a quiet box, not its JSON scrolling by. */\n const PENDING = '<span class=\"aparte-skeleton aparte-skeleton--rect aparte-echarts-pending\" aria-hidden=\"true\"></span>';\n /** The note and the source, for a fence that is not an option. Their text is set by `relabel`. */\n const FAILED = '<span class=\"aparte-code-error\" role=\"note\" data-aparte-echarts-error></span><pre class=\"aparte-code-error\" data-aparte-echarts-source></pre>';\n\n const schedule = (state: Arriving): void => {\n if (state.timer !== undefined || !state.waiting) return;\n const wait = Math.max(0, state.at + PROGRESSIVE_MS - performance.now());\n state.timer = setTimeout(() => {\n state.timer = undefined;\n const job = state.waiting;\n state.waiting = null;\n if (!job) return;\n state.at = performance.now();\n const option = sanitizeEChartsOption(parseOption(job.source, true));\n const json = option && drawable(option) ? JSON.stringify(option) : null;\n if (json === null || json === state.drawn) { job.answer(null); return; }\n state.drawn = json;\n job.answer(markup(json, state.id));\n }, wait);\n };\n\n return {\n languages: LANGUAGES,\n lazy: true,\n render(ctx: AparteCodeLanguageContext): string | null | Promise<string | null> {\n if (!ctx.display) return null;\n const state = arrivingOf(ctx.host);\n // A newer source, or the end of this one, supersedes the frame still waiting.\n state.waiting?.answer(null);\n state.waiting = null;\n if (!ctx.open) {\n state.started = null;\n state.drawn = null;\n // Valid JSON with no series and no dataset draws an empty box: the note says so,\n // as it does for a tool's result.\n const option = sanitizeEChartsOption(parseOption(ctx.source));\n return option && drawable(option) ? markup(JSON.stringify(option), state.id) : FAILED;\n }\n if (!progressive) return null;\n // A chart's first frame: the box it will be drawn in, at once, in place of its\n // JSON. The frames after it draw what has arrived, and a frame that draws nothing\n // new keeps what is shown.\n if (state.started === null || !ctx.source.startsWith(state.started)) {\n state.started = ctx.source;\n state.drawn = null;\n return PENDING;\n }\n return new Promise<string | null>((answer) => {\n state.waiting = { source: ctx.source, answer };\n schedule(state);\n });\n },\n relabel(drawing: HTMLElement, ctx: AparteCodeLanguageContext): void {\n const error = drawing.querySelector<HTMLElement>('[data-aparte-echarts-error]');\n if (error) error.textContent = word(ctx.config, 'echartsError');\n const source = drawing.querySelector<HTMLElement>('[data-aparte-echarts-source]');\n if (source) source.textContent = ctx.source;\n for (const box of Array.from(drawing.querySelectorAll<HTMLElement>('.aparte-echarts-pending'))) {\n box.style.setProperty('block-size', height);\n box.style.setProperty('max-inline-size', MAX_WIDTH);\n }\n for (const el of Array.from(drawing.querySelectorAll<HTMLElement>(TAG))) charts.label(el, ctx.config);\n },\n };\n}\n\n/** A tool whose result is an ECharts option: the chart in place of its row. */\nfunction createToolRenderer(setupId: string, options: EChartsOptions, config: AparteConfig, charts: ChartsOf): AparteToolRenderer {\n const height = cssLength(options.height);\n /** What each element shows, so an update that changes nothing redraws nothing. */\n const shown = new WeakMap<HTMLElement, string>();\n let warned = false;\n\n const optionOf = (segment: AparteToolCallSegment): EChartsOption | null => {\n let raw: unknown = segment.structuredResult;\n if (raw === undefined && typeof segment.result === 'string') raw = parseOption(segment.result.trim()) ?? segment.result;\n const input = isObject(segment.toolCall?.input) ? segment.toolCall.input : {};\n try {\n if (options.map) raw = options.map(raw, input);\n } catch (error) {\n if (!warned) { warned = true; console.warn(`[aparte-echarts] the \\`map\\` for tool \"${segment.toolCall?.name}\" threw:`, error); }\n return null;\n }\n const option = sanitizeEChartsOption(raw);\n return option && drawable(option) ? option : null;\n };\n\n const chartOf = (option: EChartsOption): HTMLElement => {\n const el = document.createElement(TAG);\n el.className = 'aparte-echarts';\n el.setAttribute('data-aparte-echarts', setupId);\n el.setAttribute('data-aparte-echarts-option', JSON.stringify(option));\n return el;\n };\n\n const fill = (root: HTMLElement, segment: AparteToolCallSegment): void => {\n let structured = '';\n try { structured = JSON.stringify(segment.structuredResult) ?? ''; } catch { /* a cycle: compared by the text alone */ }\n const signature = `${segment.status}\\u0001${segment.result ?? ''}\\u0001${structured}`;\n if (shown.get(root) === signature) return;\n shown.set(root, signature);\n for (const el of Array.from(root.querySelectorAll<HTMLElement>(TAG))) charts.dispose(el);\n root.removeAttribute('aria-busy');\n root.removeAttribute('aria-label');\n root.removeAttribute('data-aparte-echarts-label');\n switch (segment.status) {\n case 'pending':\n root.setAttribute('aria-busy', 'true');\n root.setAttribute('data-aparte-echarts-label', 'echartsLoading');\n root.setAttribute('aria-label', word(config, 'echartsLoading'));\n root.replaceChildren(skeleton(height));\n return;\n case 'resolved': {\n const option = optionOf(segment);\n root.replaceChildren(option ? chartOf(option) : note(config, 'echartsError'));\n return;\n }\n case 'awaiting-approval':\n root.replaceChildren(note(config, 'echartsWaiting'));\n return;\n case 'rejected':\n case 'aborted':\n root.replaceChildren(note(config, 'echartsNotRun'));\n return;\n default:\n root.replaceChildren(note(config, 'echartsFailed'));\n }\n };\n\n return {\n render(segment) {\n const root = document.createElement('div');\n root.className = 'aparte-echarts-tool';\n fill(root, segment);\n return root;\n },\n // Same element, new inside only when the call changed: a chart the reader is\n // looking at is not drawn again because an approval or a relabel passed by.\n update: (root, segment) => fill(root, segment),\n relabel(root) {\n const key = root.getAttribute('data-aparte-echarts-label') as WordKey | null;\n if (key) root.setAttribute('aria-label', word(config, key));\n relabelWords(root, config);\n for (const el of Array.from(root.querySelectorAll<HTMLElement>(TAG))) charts.label(el, config);\n },\n cleanup(root) {\n for (const el of Array.from(root.querySelectorAll<HTMLElement>(TAG))) charts.dispose(el);\n },\n };\n}\n\n/**\n * Call `changed` when the chat's theme or the system's colour scheme changes — on the\n * page, and in each shadow root handed to `add`.\n */\nfunction watchTheme(changed: () => void): { add: (root: ShadowRoot) => void; stop: () => void } {\n if (typeof MutationObserver === 'undefined' || typeof document === 'undefined') return { add: () => {}, stop: () => {} };\n const observer = new MutationObserver(changed);\n const init: MutationObserverInit = { attributes: true, subtree: true, attributeFilter: ['data-aparte-theme'] };\n observer.observe(document.documentElement, init);\n const media = typeof matchMedia === 'function' ? matchMedia('(prefers-color-scheme: dark)') : null;\n media?.addEventListener?.('change', changed);\n return {\n add: (root) => observer.observe(root, init),\n stop: () => { observer.disconnect(); media?.removeEventListener?.('change', changed); },\n };\n}\n"],"names":["isObject","out","_","named","s","cell"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type AparteConfig } from '@aparte/core';
|
|
2
|
+
import { type EChartsOptions } from './core.js';
|
|
3
|
+
export { setupEChartsWith, sanitizeEChartsOption, echartsTheme, echartsPalette, ECHARTS_SERIES_HUES } from './core.js';
|
|
4
|
+
export type { EChartsLike, EChartsInstanceLike, EChartsOptions, EChartsOption, EChartsTokens } from './core.js';
|
|
5
|
+
/**
|
|
6
|
+
* Draw charts with [Apache ECharts](https://echarts.apache.org): every ```` ```echarts ````
|
|
7
|
+
* fence in a reply — an ECharts `option` as JSON — whichever Markdown provider is
|
|
8
|
+
* installed, or none, and, with `tool`, a tool whose result is one. The chart is drawn as
|
|
9
|
+
* its fence arrives, from the part of the JSON that has; once the fence closes, one that is
|
|
10
|
+
* not an option shows a note and its source.
|
|
11
|
+
*
|
|
12
|
+
* Its colours and font come from the chat's theme and follow a light/dark switch; it is
|
|
13
|
+
* drawn as SVG, without HTML tooltips, images, links or downloads a model could steer.
|
|
14
|
+
* ECharts is loaded on the first chart, and a chart is drawn only once it comes near the
|
|
15
|
+
* screen, so reopening a long conversation stays fast.
|
|
16
|
+
*
|
|
17
|
+
* @returns a disposer that unregisters the renderers and disposes the charts.
|
|
18
|
+
* @example
|
|
19
|
+
* import { setupECharts } from '@aparte/plugin-echarts';
|
|
20
|
+
* setupECharts();
|
|
21
|
+
*/
|
|
22
|
+
export declare function setupECharts(options?: EChartsOptions, config?: AparteConfig): () => void;
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACvH,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAEhH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,cAAmB,EAAE,MAAM,GAAE,YAAiC,GAAG,MAAM,IAAI,CAMhH"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { aparteGlobalConfig } from "@aparte/core";
|
|
2
|
+
import { setupEChartsWith } from "./core.js";
|
|
3
|
+
import { ECHARTS_SERIES_HUES, echartsPalette, echartsTheme, sanitizeEChartsOption } from "./core.js";
|
|
4
|
+
function setupECharts(options = {}, config = aparteGlobalConfig) {
|
|
5
|
+
return setupEChartsWith(
|
|
6
|
+
() => import("echarts"),
|
|
7
|
+
options,
|
|
8
|
+
config
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
ECHARTS_SERIES_HUES,
|
|
13
|
+
echartsPalette,
|
|
14
|
+
echartsTheme,
|
|
15
|
+
sanitizeEChartsOption,
|
|
16
|
+
setupECharts,
|
|
17
|
+
setupEChartsWith
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { aparteGlobalConfig, type AparteConfig } from '@aparte/core';\nimport { setupEChartsWith, type EChartsOptions } from './core.js';\n\nexport { setupEChartsWith, sanitizeEChartsOption, echartsTheme, echartsPalette, ECHARTS_SERIES_HUES } from './core.js';\nexport type { EChartsLike, EChartsInstanceLike, EChartsOptions, EChartsOption, EChartsTokens } from './core.js';\n\n/**\n * Draw charts with [Apache ECharts](https://echarts.apache.org): every ```` ```echarts ````\n * fence in a reply — an ECharts `option` as JSON — whichever Markdown provider is\n * installed, or none, and, with `tool`, a tool whose result is one. The chart is drawn as\n * its fence arrives, from the part of the JSON that has; once the fence closes, one that is\n * not an option shows a note and its source.\n *\n * Its colours and font come from the chat's theme and follow a light/dark switch; it is\n * drawn as SVG, without HTML tooltips, images, links or downloads a model could steer.\n * ECharts is loaded on the first chart, and a chart is drawn only once it comes near the\n * screen, so reopening a long conversation stays fast.\n *\n * @returns a disposer that unregisters the renderers and disposes the charts.\n * @example\n * import { setupECharts } from '@aparte/plugin-echarts';\n * setupECharts();\n */\nexport function setupECharts(options: EChartsOptions = {}, config: AparteConfig = aparteGlobalConfig): () => void {\n return setupEChartsWith(\n () => import('echarts'),\n options,\n config,\n );\n}\n"],"names":[],"mappings":";;;AAuBO,SAAS,aAAa,UAA0B,IAAI,SAAuB,oBAAgC;AAC9G,SAAO;AAAA,IACH,MAAM,OAAO,SAAS;AAAA,IACtB;AAAA,IACA;AAAA,EAAA;AAER;"}
|
package/dist/option.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading an ECharts `option` that a model wrote or a tool returned: making it harmless,
|
|
3
|
+
* reading a fence that is still arriving, and the words and numbers a screen reader gets.
|
|
4
|
+
* Pure — no DOM, no ECharts — so all of it can be checked in Node.
|
|
5
|
+
*/
|
|
6
|
+
export type EChartsOption = Record<string, unknown>;
|
|
7
|
+
/** What a font name, size, style or weight is made of — and nothing a declaration needs. */
|
|
8
|
+
export declare const SAFE_FONT: RegExp;
|
|
9
|
+
/**
|
|
10
|
+
* An ECharts option made harmless to draw. The option comes from a model or a tool, so
|
|
11
|
+
* whatever in it ECharts would turn into HTML, a request or a navigation goes:
|
|
12
|
+
*
|
|
13
|
+
* - every `tooltip` (the root's, a series', a data item's) is drawn, not written as HTML:
|
|
14
|
+
* `renderMode: 'richText'`, and the HTML-only `extraCssText`, `className`, `appendTo`,
|
|
15
|
+
* `appendToBody` go. A string `formatter` stays — in rich-text mode it is drawn as text;
|
|
16
|
+
* - `toolbox.feature.saveAsImage` (a download, or a new tab) and `dataView` (an HTML table
|
|
17
|
+
* with a textarea) go;
|
|
18
|
+
* - a value with an `image` (a picture fill, a rich-text background) or an `svgElement` (an
|
|
19
|
+
* SVG pattern ECharts would build node by node — a `<script>` included) goes whole, and so
|
|
20
|
+
* does a `graphic` element of `type: 'image'`;
|
|
21
|
+
* - a string `image://…` (a symbol, an icon) or holding a CSS `url(…)` goes, its CSS escapes
|
|
22
|
+
* read first; so does any string pairing a backslash with a bracket;
|
|
23
|
+
* - where a colour goes (`color`, `fill`, `stroke`, any `…Color`), only colour syntax stays:
|
|
24
|
+
* zrender copies it into an SVG attribute as it is;
|
|
25
|
+
* - a dataset filter's `reg` goes: ECharts compiles it, and a pattern can backtrack for minutes;
|
|
26
|
+
* - a string `link` / `sublink` (a title, a treemap or sunburst node: ECharts opens it on a
|
|
27
|
+
* click, and a `javascript:` URL would run in the page) goes;
|
|
28
|
+
* - a font value with anything beyond a font name in it (`;`, `:`, brackets) goes: ECharts
|
|
29
|
+
* writes it into a `style` attribute;
|
|
30
|
+
* - `__proto__`, `constructor` and `prototype` keys go.
|
|
31
|
+
*
|
|
32
|
+
* Anything else is kept as it was. `null` when the option is not an object.
|
|
33
|
+
*/
|
|
34
|
+
export declare function sanitizeEChartsOption(option: unknown): EChartsOption | null;
|
|
35
|
+
/**
|
|
36
|
+
* The option a fence holds, read as JSON: the whole of it once it parses, else — while it is
|
|
37
|
+
* still arriving (`open`) — the longest prefix that does once its open brackets are closed,
|
|
38
|
+
* so a series appears as its numbers arrive. `undefined` when nothing parses.
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseOption(source: string, open?: boolean): unknown;
|
|
41
|
+
/**
|
|
42
|
+
* Whether an option has something to draw yet: a series, or a dataset — at its root, or in
|
|
43
|
+
* the `baseOption` (and timeline `options`) an option with a timeline or media queries keeps
|
|
44
|
+
* them in.
|
|
45
|
+
*/
|
|
46
|
+
export declare function drawable(option: EChartsOption): boolean;
|
|
47
|
+
/** The option's own title — its first `title.text` — if it has one. */
|
|
48
|
+
export declare function titleOf(option: EChartsOption): string | undefined;
|
|
49
|
+
export interface ChartTable {
|
|
50
|
+
head: string[];
|
|
51
|
+
rows: string[][];
|
|
52
|
+
/** Set when the chart holds more than the table lists: past `MAX_COLUMNS`, `MAX_ROWS` or `MAX_CELLS`. */
|
|
53
|
+
cut?: true;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The numbers of a chart as a table, when its shape says plainly what they are: a
|
|
57
|
+
* `dataset.source` (rows of values, or of objects), a category axis with series beside it,
|
|
58
|
+
* or a series of named values (a pie, a funnel). `null` for anything else — a scatter of
|
|
59
|
+
* pairs, a graph — which ECharts' own description still reads out. A series with no data
|
|
60
|
+
* has no column; past the bounds, the table is `cut`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function tableOf(option: EChartsOption): ChartTable | null;
|
|
63
|
+
//# sourceMappingURL=option.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"option.d.ts","sourceRoot":"","sources":["../src/option.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAoBpD,4FAA4F;AAC5F,eAAO,MAAM,SAAS,QAA+B,CAAC;AAkDtD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAI3E;AAwCD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,UAAQ,GAAG,OAAO,CAGjE;AAuCD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAQvD;AAED,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAIjE;AAYD,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACjB,yGAAyG;IACzG,GAAG,CAAC,EAAE,IAAI,CAAC;CACd;AAsCD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,GAAG,IAAI,CA8ChE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words a chart draws, in the chat's language.
|
|
3
|
+
*
|
|
4
|
+
* Core's locale is a closed list of what CORE draws, so a plugin reads its own keys off
|
|
5
|
+
* `getLocale()` and defaults them at the call site. This package carries its few words in
|
|
6
|
+
* the ten languages `@aparte/locales` ships, picked by the locale's `tag`; a key the app
|
|
7
|
+
* sets wins, and a language the table does not have reads English.
|
|
8
|
+
*
|
|
9
|
+
* aparteGlobalConfig.extendLocale({ echartsChart: 'Courbe' });
|
|
10
|
+
*/
|
|
11
|
+
import type { AparteConfig } from '@aparte/core';
|
|
12
|
+
export declare const WORDS: {
|
|
13
|
+
echartsChart: {
|
|
14
|
+
en: string;
|
|
15
|
+
fr: string;
|
|
16
|
+
de: string;
|
|
17
|
+
es: string;
|
|
18
|
+
it: string;
|
|
19
|
+
ja: string;
|
|
20
|
+
ko: string;
|
|
21
|
+
pt: string;
|
|
22
|
+
ru: string;
|
|
23
|
+
zh: string;
|
|
24
|
+
};
|
|
25
|
+
echartsError: {
|
|
26
|
+
en: string;
|
|
27
|
+
fr: string;
|
|
28
|
+
de: string;
|
|
29
|
+
es: string;
|
|
30
|
+
it: string;
|
|
31
|
+
ja: string;
|
|
32
|
+
ko: string;
|
|
33
|
+
pt: string;
|
|
34
|
+
ru: string;
|
|
35
|
+
zh: string;
|
|
36
|
+
};
|
|
37
|
+
echartsLoading: {
|
|
38
|
+
en: string;
|
|
39
|
+
fr: string;
|
|
40
|
+
de: string;
|
|
41
|
+
es: string;
|
|
42
|
+
it: string;
|
|
43
|
+
ja: string;
|
|
44
|
+
ko: string;
|
|
45
|
+
pt: string;
|
|
46
|
+
ru: string;
|
|
47
|
+
zh: string;
|
|
48
|
+
};
|
|
49
|
+
echartsWaiting: {
|
|
50
|
+
en: string;
|
|
51
|
+
fr: string;
|
|
52
|
+
de: string;
|
|
53
|
+
es: string;
|
|
54
|
+
it: string;
|
|
55
|
+
ja: string;
|
|
56
|
+
ko: string;
|
|
57
|
+
pt: string;
|
|
58
|
+
ru: string;
|
|
59
|
+
zh: string;
|
|
60
|
+
};
|
|
61
|
+
echartsNotRun: {
|
|
62
|
+
en: string;
|
|
63
|
+
fr: string;
|
|
64
|
+
de: string;
|
|
65
|
+
es: string;
|
|
66
|
+
it: string;
|
|
67
|
+
ja: string;
|
|
68
|
+
ko: string;
|
|
69
|
+
pt: string;
|
|
70
|
+
ru: string;
|
|
71
|
+
zh: string;
|
|
72
|
+
};
|
|
73
|
+
echartsFailed: {
|
|
74
|
+
en: string;
|
|
75
|
+
fr: string;
|
|
76
|
+
de: string;
|
|
77
|
+
es: string;
|
|
78
|
+
it: string;
|
|
79
|
+
ja: string;
|
|
80
|
+
ko: string;
|
|
81
|
+
pt: string;
|
|
82
|
+
ru: string;
|
|
83
|
+
zh: string;
|
|
84
|
+
};
|
|
85
|
+
echartsTableCut: {
|
|
86
|
+
en: string;
|
|
87
|
+
fr: string;
|
|
88
|
+
de: string;
|
|
89
|
+
es: string;
|
|
90
|
+
it: string;
|
|
91
|
+
ja: string;
|
|
92
|
+
ko: string;
|
|
93
|
+
pt: string;
|
|
94
|
+
ru: string;
|
|
95
|
+
zh: string;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
export type WordKey = keyof typeof WORDS;
|
|
99
|
+
/** The language part of the locale's tag: `pt-BR` → `pt`, none → `en`. */
|
|
100
|
+
export declare function languageOf(config: AparteConfig): string;
|
|
101
|
+
/** The word for `key`: the app's locale first, then this package's table, then English. */
|
|
102
|
+
export declare function word(config: AparteConfig, key: WordKey): string;
|
|
103
|
+
//# sourceMappingURL=strings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../src/strings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2Cc,CAAC;AAEjC,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,KAAK,CAAC;AAEzC,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAGvD;AAED,2FAA2F;AAC3F,wBAAgB,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAK/D"}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** The chat's colours and font, resolved, as the theme is built from them. */
|
|
2
|
+
export interface EChartsTokens {
|
|
3
|
+
/** Text: titles, legends, values (`--aparte-text`). */
|
|
4
|
+
text: string;
|
|
5
|
+
/** Quieter text: axis labels, subtitles (`--aparte-text-muted`). */
|
|
6
|
+
muted: string;
|
|
7
|
+
/** Lines: axes, grid, the tooltip's edge (`--aparte-border`). */
|
|
8
|
+
border: string;
|
|
9
|
+
/** The tooltip's ground (`--aparte-surface-1`). */
|
|
10
|
+
surface: string;
|
|
11
|
+
/** The page behind the chart (`--aparte-bg`): decides dark or light, and the gap between slices. */
|
|
12
|
+
background: string;
|
|
13
|
+
/** The first series' colour (`--aparte-primary`). */
|
|
14
|
+
primary: string;
|
|
15
|
+
/** The chat's font (`--aparte-font-family`). Left out, ECharts' own. */
|
|
16
|
+
fontFamily?: string;
|
|
17
|
+
/** Dark or light; left out, read from `background`. */
|
|
18
|
+
dark?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The series colours after the primary, light and dark. They are the eight hues of a
|
|
22
|
+
* palette validated for colour-vision deficiency (adjacent pairs ≥ 8 ΔE in OKLab ×100 under
|
|
23
|
+
* protanopia, deuteranopia and tritanopia, ≥ 15 for full-colour vision), each stepped once for
|
|
24
|
+
* a light ground and once for a dark one — so a series stays the same hue across the switch
|
|
25
|
+
* and keeps 3:1 against the dark ground. Not cycled from a generator: a ninth series repeats.
|
|
26
|
+
*/
|
|
27
|
+
export declare const ECHARTS_SERIES_HUES: {
|
|
28
|
+
readonly light: readonly ["#2a78d6", "#eb6834", "#1baf7a", "#eda100", "#e87ba4", "#008300", "#6250d6", "#e34948"];
|
|
29
|
+
readonly dark: readonly ["#3987e5", "#d95926", "#199e70", "#c98500", "#d55181", "#008300", "#9085e9", "#e66767"];
|
|
30
|
+
};
|
|
31
|
+
/** `#rgb`, `#rrggbb`, `rgb()` / `rgba()` as 0–255 channels; `null` for anything else. */
|
|
32
|
+
export declare function rgbOf(color: string): [number, number, number] | null;
|
|
33
|
+
/** Whether a ground is dark: its OKLab lightness under 0.6. An unreadable colour reads light. */
|
|
34
|
+
export declare function isDark(color: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* The series colours: the chat's primary first, then the validated hues. The primary takes
|
|
37
|
+
* the place of the hue nearest to it, and the ring is read on from there — so a brass
|
|
38
|
+
* primary does not sit beside the yellow it nearly is, and every pair that ends up side by
|
|
39
|
+
* side is one the validation already passed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function echartsPalette(primary: string, dark?: boolean): string[];
|
|
42
|
+
/**
|
|
43
|
+
* The ECharts theme the chat's tokens make: text, muted axis labels, grid and axis lines,
|
|
44
|
+
* a transparent ground, the chat's font, the series palette, a tooltip on the chat's
|
|
45
|
+
* surface. Hand it to `init` or `setTheme`; whatever the option sets itself wins over it.
|
|
46
|
+
* Pure: the same tokens make the same theme, in Node as in a browser.
|
|
47
|
+
*/
|
|
48
|
+
export declare function echartsTheme(tokens: EChartsTokens): Record<string, unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* The tokens as they apply at `el`, each resolved by the browser. A token may be
|
|
51
|
+
* `color-mix()` or `oklch()`, which ECharts' colour parser cannot read (it derives hover and
|
|
52
|
+
* label colours from them), so each is painted on a one-pixel canvas and read back as
|
|
53
|
+
* `rgb()` — whatever the browser's own serialisation of it.
|
|
54
|
+
*/
|
|
55
|
+
export declare function readTokens(el: HTMLElement): EChartsTokens;
|
|
56
|
+
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAWA,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC1B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,oGAAoG;IACpG,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;;;CAGtB,CAAC;AAEX,yFAAyF;AACzF,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CASpE;AAgBD,iGAAiG;AACjG,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG7C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,UAAQ,GAAG,MAAM,EAAE,CAqBtE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwE3E;AAYD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,aAAa,CA6BzD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,67 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aparte/plugin-echarts",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
3
|
+
"version": "0.29.0",
|
|
4
|
+
"homepage": "https://apartejs.dev/guides/charts/",
|
|
5
|
+
"description": "Charts for aparté via Apache ECharts — an ECharts option a model writes, or a tool returns, drawn as it streams.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"@aparte-workspace/source": "./src/index.ts",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./core": {
|
|
19
|
+
"@aparte-workspace/source": "./src/core.ts",
|
|
20
|
+
"types": "./dist/core.d.ts",
|
|
21
|
+
"import": "./dist/core.js",
|
|
22
|
+
"default": "./dist/core.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@aparte/core": ">=0.29.0 <1.0.0",
|
|
35
|
+
"echarts": ">=6.0.0 <7.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"echarts": "^6.1.0",
|
|
39
|
+
"typescript": "~5.7.0",
|
|
40
|
+
"vite": "^6.0.0",
|
|
41
|
+
"@aparte/core": "0.29.0"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"aparte",
|
|
45
|
+
"plugin",
|
|
46
|
+
"echarts",
|
|
47
|
+
"charts",
|
|
48
|
+
"data-visualization"
|
|
49
|
+
],
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://github.com/apartejs/aparte.git",
|
|
54
|
+
"directory": "packages/plugins/echarts"
|
|
55
|
+
},
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/apartejs/aparte/issues"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"dev": "vite",
|
|
61
|
+
"build": "vite build && tsc -b --emitDeclarationOnly --force && node ../../../scripts/stamp-dist.mjs",
|
|
62
|
+
"preview": "vite preview",
|
|
63
|
+
"test": "vitest",
|
|
64
|
+
"test:run": "vitest run",
|
|
65
|
+
"test:coverage": "vitest run --coverage"
|
|
66
|
+
}
|
|
6
67
|
}
|