@blueprint-chart/lib 1.8.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/charts/axis-options.d.ts +3 -0
  2. package/dist/charts/canvas/canvas.d.ts +2 -5
  3. package/dist/charts/category-label-line.d.ts +16 -0
  4. package/dist/charts/chart-helpers.d.ts +2 -3
  5. package/dist/charts/chart-options.d.ts +2 -0
  6. package/dist/charts/contrast.d.ts +4 -3
  7. package/dist/charts/date-parse.d.ts +6 -0
  8. package/dist/charts/frame/frame.d.ts +6 -0
  9. package/dist/charts/parse-data.d.ts +2 -0
  10. package/dist/charts/plugins/annotations/position-helpers.d.ts +7 -0
  11. package/dist/charts/plugins/highlight.d.ts +9 -3
  12. package/dist/charts/scale-helpers.d.ts +15 -8
  13. package/dist/charts/series-helpers.d.ts +22 -1
  14. package/dist/charts/stack-helpers.d.ts +1 -1
  15. package/dist/charts/themes/index.d.ts +6 -0
  16. package/dist/charts/types.d.ts +10 -4
  17. package/dist/charts/value-label-fit.d.ts +31 -0
  18. package/dist/dsl/converter.d.ts +5 -0
  19. package/dist/dsl/quoting.d.ts +16 -0
  20. package/dist/dsl/types.d.ts +42 -0
  21. package/dist/dsl/validate.d.ts +6 -0
  22. package/dist/embed.js +1 -1
  23. package/dist/enums.d.ts +23 -0
  24. package/dist/index.d.ts +9 -1
  25. package/dist/index.js +615 -296
  26. package/dist/lib/lib.iife.js +44 -15
  27. package/dist/node-backend/index.js +3192 -2108
  28. package/dist/render/chart-a11y.d.ts +14 -0
  29. package/dist/render/frame-svg.d.ts +51 -0
  30. package/dist/render/index.d.ts +3 -0
  31. package/dist/render/post-render.d.ts +2 -0
  32. package/dist/{render-bpc-By-iMMKD.js → render-bpc-BWiUALXY.js} +3976 -2860
  33. package/dist/runtime/chart-css.d.ts +1 -1
  34. package/dist/runtime-DDhsXDn5.js +84 -0
  35. package/dist/runtime.js +2 -2
  36. package/dist/transforms/applyFilter.d.ts +2 -0
  37. package/dist/transforms/applyGroupBy.d.ts +2 -0
  38. package/dist/transforms/applyHideColumns.d.ts +2 -0
  39. package/dist/transforms/applyParse.d.ts +3 -0
  40. package/dist/transforms/applyRename.d.ts +2 -0
  41. package/dist/transforms/applySort.d.ts +2 -0
  42. package/dist/transforms/applyTranspose.d.ts +2 -0
  43. package/dist/transforms/index.d.ts +30 -0
  44. package/dist/transforms/parseOperations.d.ts +15 -0
  45. package/dist/transforms/shared.d.ts +4 -0
  46. package/dist/transforms/table.d.ts +22 -0
  47. package/dist/transforms/transformValue.d.ts +1 -0
  48. package/dist/transforms/types.d.ts +13 -0
  49. package/package.json +1 -1
  50. package/src/charts/chart.scss +29 -4
  51. package/dist/runtime-BnrDRLyH.js +0 -84
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { $ as e, A as t, B as n, C as r, Ct as i, D as a, E as o, Et as s, F as c, G as l, H as ee, I as te, J as u, K as ne, L as re, M as ie, N as ae, O as oe, P as se, Q as d, R as ce, S as f, St as le, T as ue, Tt as de, U as fe, V as pe, W as me, X as p, Y as he, Z as ge, _ as _e, _t as ve, a as ye, at as be, b as xe, bt as Se, c as Ce, ct as we, d as Te, dt as Ee, et as De, f as Oe, ft as ke, g as Ae, gt as je, h as Me, ht as Ne, i as m, it as Pe, j as Fe, k as Ie, l as Le, lt as h, m as g, mt as Re, n as _, nt as ze, o as Be, ot as Ve, p as v, pt as He, q as Ue, r as We, rt as Ge, s as Ke, st as qe, t as Je, tt as y, u as Ye, ut as Xe, v as Ze, vt as Qe, w as $e, wt as et, x as b, xt as tt, y as nt, yt as rt, z as it } from "./render-bpc-By-iMMKD.js";
2
- import { t as at } from "./runtime-BnrDRLyH.js";
3
- import x from "chroma-js";
1
+ import { $ as e, A as t, At as n, B as r, Bt as i, C as a, Ct as o, D as s, Dt as c, E as l, Et as u, F as d, Ft as f, G as p, Gt as m, H as h, Ht as ee, I as te, It as g, J as _, Jt as ne, K as re, Kt as ie, L as ae, Lt as oe, M as se, Mt as ce, N as le, Nt as ue, O as de, Ot as fe, P as v, Pt as pe, Q as me, R as he, Rt as ge, S as _e, St as ve, T as ye, Tt as be, U as y, Ut as xe, V as Se, Vt as Ce, W as we, Wt as Te, X as Ee, Xt as De, Y as Oe, Yt as ke, Z as Ae, Zt as je, _ as Me, _t as Ne, a as b, at as Pe, b as Fe, bt as x, c as Ie, ct as Le, d as Re, dt as ze, et as Be, f as Ve, ft as He, g as Ue, gt as We, h as Ge, ht as Ke, i as S, it as qe, j as Je, jt as Ye, k as Xe, kt as Ze, l as Qe, lt as $e, m as et, mt as tt, n as nt, nt as rt, o as it, ot as at, p as ot, pt as st, q as ct, qt as lt, r as ut, rt as dt, s as ft, st as pt, t as mt, tt as ht, u as gt, ut as _t, v as vt, vt as C, w as yt, wt as bt, x as xt, xt as St, y as Ct, yt as wt, z as w, zt as Tt } from "./render-bpc-BWiUALXY.js";
2
+ import { t as Et } from "./runtime-DDhsXDn5.js";
3
+ import T from "chroma-js";
4
4
  //#region src/recommendations/intent.ts
5
- var ot = [
5
+ var Dt = [
6
6
  {
7
7
  intent: "range",
8
8
  pattern: /\b(range|high and low|high\/low|margin of error|confidence interval|confidence|interval|plus or minus|spread between)\b/i
@@ -28,92 +28,92 @@ var ot = [
28
28
  pattern: /\b(compares?|compared|comparison|versus|vs\.?|more than|difference between|across|than)\b/i
29
29
  }
30
30
  ];
31
- function S(e) {
31
+ function E(e) {
32
32
  if (e === void 0 || e.trim() === "") return "none";
33
- for (let t of ot) if (t.pattern.test(e)) return t.intent;
33
+ for (let t of Dt) if (t.pattern.test(e)) return t.intent;
34
34
  return "none";
35
35
  }
36
36
  //#endregion
37
37
  //#region src/recommendations/decisionTable.ts
38
- var C = (e, t, n) => ({
38
+ var D = (e, t, n) => ({
39
39
  type: e,
40
40
  fitness: t,
41
41
  reason: n
42
- }), w = {
42
+ }), O = {
43
43
  "1cat+1num": {
44
44
  none: (e) => {
45
- let t = [C("bar-vertical", "best", "1 categorical + 1 numeric — classic bar chart"), C("bar-horizontal", "good", "Horizontal bars work well for long labels")];
46
- return e <= 8 && (t.push(C("donut", "good", `${e} items — suitable for part-of-whole`)), t.push(C("pie", "alternative", "Pie chart for part-of-whole"))), t;
45
+ let t = [D("bar-vertical", "best", "1 categorical + 1 numeric — classic bar chart"), D("bar-horizontal", "good", "Horizontal bars work well for long labels")];
46
+ return e <= 8 && (t.push(D("donut", "good", `${e} items — suitable for part-of-whole`)), t.push(D("pie", "alternative", "Pie chart for part-of-whole"))), t;
47
47
  },
48
- comparison: (e) => w["1cat+1num"].none(e),
49
- ranking: () => [C("bar-horizontal", "best", "Ranked categories read best as horizontal bars"), C("bar-vertical", "good", "Vertical bars also work for ranking")],
48
+ comparison: (e) => O["1cat+1num"].none(e),
49
+ ranking: () => [D("bar-horizontal", "best", "Ranked categories read best as horizontal bars"), D("bar-vertical", "good", "Vertical bars also work for ranking")],
50
50
  "part-to-whole": (e) => e <= 5 ? [
51
- C("pie", "best", `${e} slices — pie reads cleanly for very small N`),
52
- C("donut", "good", "Donut for part-of-whole with a center label"),
53
- C("bar-vertical", "alternative", "Bars if precise comparison matters")
51
+ D("pie", "best", `${e} slices — pie reads cleanly for very small N`),
52
+ D("donut", "good", "Donut for part-of-whole with a center label"),
53
+ D("bar-vertical", "alternative", "Bars if precise comparison matters")
54
54
  ] : e <= 8 ? [
55
- C("donut", "best", `${e} slices — donut for part-of-whole`),
56
- C("pie", "good", "Pie for part-of-whole"),
57
- C("bar-vertical", "alternative", "Bars if precise comparison matters")
58
- ] : [C("bar-vertical", "best", `${e} categories — too many for a readable pie`), C("bar-horizontal", "good", "Horizontal bars for long labels")],
59
- range: () => [C("bar-split", "best", "Diverging bars show a value against a shared baseline"), C("bar-vertical", "alternative", "Plain bars if the baseline is zero")]
55
+ D("donut", "best", `${e} slices — donut for part-of-whole`),
56
+ D("pie", "good", "Pie for part-of-whole"),
57
+ D("bar-vertical", "alternative", "Bars if precise comparison matters")
58
+ ] : [D("bar-vertical", "best", `${e} categories — too many for a readable pie`), D("bar-horizontal", "good", "Horizontal bars for long labels")],
59
+ range: () => [D("bar-vertical", "best", "A single numeric column carries no range — plain bars read the value directly"), D("bar-horizontal", "good", "Horizontal bars work well for long labels")]
60
60
  },
61
61
  "1cat+Nnum": {
62
- none: () => [C("bar-multi", "best", "1 categorical + multiple numeric columns — compare groups"), C("line-multi", "good", "Can also show as a multi-line chart")],
63
- comparison: (e) => w["1cat+Nnum"].none(e),
64
- ranking: (e) => w["1cat+Nnum"].none(e),
65
- trend: () => [C("line-multi", "best", "A trend or crossover story reads best as lines, even over categorical periods"), C("bar-multi", "alternative", "Grouped bars if per-period comparison matters more than the trend")],
62
+ none: () => [D("bar-multi", "best", "1 categorical + multiple numeric columns — compare groups"), D("line-multi", "good", "Can also show as a multi-line chart")],
63
+ comparison: (e) => O["1cat+Nnum"].none(e),
64
+ ranking: (e) => O["1cat+Nnum"].none(e),
65
+ trend: () => [D("line-multi", "best", "A trend or crossover story reads best as lines, even over categorical periods"), D("bar-multi", "alternative", "Grouped bars if per-period comparison matters more than the trend")],
66
66
  "part-to-whole": () => [
67
- C("bar-stacked", "best", "Stacked bars show composition within each category"),
68
- C("column-stacked", "good", "Stacked columns for the same composition"),
69
- C("bar-multi", "alternative", "Grouped bars if comparison beats composition")
67
+ D("bar-stacked", "best", "Stacked bars show composition within each category"),
68
+ D("column-stacked", "good", "Stacked columns for the same composition"),
69
+ D("bar-multi", "alternative", "Grouped bars if comparison beats composition")
70
70
  ],
71
71
  "composition-over-time": () => [
72
- C("column-stacked", "best", "Stacked columns show composition across discrete periods"),
73
- C("bar-stacked", "good", "Stacked bars for the same composition"),
74
- C("area-stacked", "alternative", "Stacked area if the periods are continuous time")
72
+ D("column-stacked", "best", "Stacked columns show composition across discrete periods"),
73
+ D("bar-stacked", "good", "Stacked bars for the same composition"),
74
+ D("area-stacked", "alternative", "Stacked area if the periods are continuous time")
75
75
  ],
76
- range: () => [C("bar-split", "best", "Diverging bars show values around a shared baseline"), C("bar-multi", "alternative", "Grouped bars if there is no shared baseline")]
76
+ range: () => [D("bar-split", "best", "Diverging bars show values around a shared baseline"), D("bar-multi", "alternative", "Grouped bars if there is no shared baseline")]
77
77
  },
78
78
  "1date+1num": {
79
- none: () => [C("line", "best", "1 date + 1 numeric column — ideal for trend"), C("bar-vertical", "alternative", "Can also show as bars")],
79
+ none: () => [D("line", "best", "1 date + 1 numeric column — ideal for trend"), D("bar-vertical", "alternative", "Can also show as bars")],
80
80
  trend: () => [
81
- C("line", "best", "1 date + 1 numeric column — ideal for trend"),
82
- C("area", "good", "Filled area emphasizes magnitude over time"),
83
- C("bar-vertical", "alternative", "Can also show as bars")
81
+ D("line", "best", "1 date + 1 numeric column — ideal for trend"),
82
+ D("area", "good", "Filled area emphasizes magnitude over time"),
83
+ D("bar-vertical", "alternative", "Can also show as bars")
84
84
  ],
85
- comparison: () => [C("bar-vertical", "best", "Bars for comparing discrete time points"), C("line", "good", "Line if the trend matters more than the comparison")],
86
- ranking: () => [C("bar-vertical", "best", "Bars for ranking discrete time points"), C("line", "good", "Line for the underlying trend")],
87
- "part-to-whole": () => [C("area", "best", "Filled area reads as magnitude/share over time"), C("line", "good", "Line for the underlying trend")],
88
- "composition-over-time": () => [C("area", "best", "Filled area shows magnitude over time"), C("line", "good", "Line for the underlying trend")]
85
+ comparison: () => [D("bar-vertical", "best", "Bars for comparing discrete time points"), D("line", "good", "Line if the trend matters more than the comparison")],
86
+ ranking: () => [D("bar-vertical", "best", "Bars for ranking discrete time points"), D("line", "good", "Line for the underlying trend")],
87
+ "part-to-whole": () => [D("area", "best", "Filled area reads as magnitude/share over time"), D("line", "good", "Line for the underlying trend")],
88
+ "composition-over-time": () => [D("area", "best", "Filled area shows magnitude over time"), D("line", "good", "Line for the underlying trend")]
89
89
  },
90
90
  "1date+Nnum": {
91
- none: () => [C("line-multi", "best", "1 date + multiple numeric columns — compare trends"), C("bar-multi", "alternative", "Can also show as grouped bars")],
92
- trend: (e) => w["1date+Nnum"].none(e),
93
- comparison: (e) => w["1date+Nnum"].none(e),
94
- ranking: (e) => w["1date+Nnum"].none(e),
91
+ none: () => [D("line-multi", "best", "1 date + multiple numeric columns — compare trends"), D("bar-multi", "alternative", "Can also show as grouped bars")],
92
+ trend: (e) => O["1date+Nnum"].none(e),
93
+ comparison: (e) => O["1date+Nnum"].none(e),
94
+ ranking: (e) => O["1date+Nnum"].none(e),
95
95
  "composition-over-time": () => [
96
- C("area-stacked", "best", "Stacked area shows composition over continuous time"),
97
- C("column-stacked", "good", "Stacked columns for the same composition"),
98
- C("line-multi", "alternative", "Multi-line if composition is not the point")
96
+ D("area-stacked", "best", "Stacked area shows composition over continuous time"),
97
+ D("column-stacked", "good", "Stacked columns for the same composition"),
98
+ D("line-multi", "alternative", "Multi-line if composition is not the point")
99
99
  ],
100
- "part-to-whole": () => [C("area-stacked", "best", "Stacked area shows share over time"), C("line-multi", "good", "Multi-line if absolute trends matter more")]
100
+ "part-to-whole": () => [D("area-stacked", "best", "Stacked area shows share over time"), D("line-multi", "good", "Multi-line if absolute trends matter more")]
101
101
  },
102
- other: { none: () => [C("bar-vertical", "good", "Default bar chart recommendation")] }
102
+ other: { none: () => [D("bar-vertical", "good", "Default bar chart recommendation")] }
103
103
  };
104
- function st(e, t, n) {
105
- let r = w[e], i = r[t] ?? r.none;
106
- return i ? i(n) : [C("bar-vertical", "good", "Default bar chart recommendation")];
104
+ function Ot(e, t, n) {
105
+ let r = O[e], i = r[t] ?? r.none;
106
+ return i ? i(n) : [D("bar-vertical", "good", "Default bar chart recommendation")];
107
107
  }
108
108
  //#endregion
109
109
  //#region src/recommendations/shape.ts
110
- function T(e, t) {
110
+ function kt(e, t) {
111
111
  let n = e.filter((e) => e === "string").length, r = e.filter((e) => e === "number").length, i = e.filter((e) => e === "date").length;
112
112
  return i === 1 && n === 0 && r >= 1 ? r === 1 ? "1date+1num" : "1date+Nnum" : n === 1 && i === 0 && r >= 1 ? r === 1 ? "1cat+1num" : "1cat+Nnum" : "other";
113
113
  }
114
114
  //#endregion
115
115
  //#region src/recommendations/types.ts
116
- var ct = {
116
+ var At = {
117
117
  "bar-vertical": "Vertical Bar Chart",
118
118
  "bar-horizontal": "Horizontal Bar Chart",
119
119
  "bar-multi": "Grouped Bar Chart",
@@ -130,21 +130,43 @@ var ct = {
130
130
  };
131
131
  //#endregion
132
132
  //#region src/recommendations/recommend.ts
133
- function lt(e, t, n) {
134
- return e.length === 0 ? [] : st(T(e, t), S(n), t).map((e) => ({
133
+ function jt(e, t, n) {
134
+ return e.length === 0 ? [] : Ot(kt(e, t), E(n), t).map((e) => ({
135
135
  chartType: e.type,
136
- label: ct[e.type] ?? e.type,
136
+ label: At[e.type] ?? e.type,
137
137
  fitness: e.fitness,
138
138
  reason: e.reason
139
139
  }));
140
140
  }
141
141
  //#endregion
142
+ //#region src/charts/themes/index.ts
143
+ var Mt = [
144
+ {
145
+ name: "blueprint",
146
+ label: "Blueprint",
147
+ description: "The default Blueprint Chart theme"
148
+ },
149
+ {
150
+ name: "blueprint-framed",
151
+ label: "Blueprint Framed",
152
+ description: "Adds borders and a tinted footer"
153
+ },
154
+ {
155
+ name: "blueprint-bold",
156
+ label: "Blueprint Bold",
157
+ description: "Charts on the blueprint canvas with the full brand palette"
158
+ }
159
+ ];
160
+ function Nt() {
161
+ return Mt;
162
+ }
163
+ //#endregion
142
164
  //#region src/charts/colorblind.ts
143
- var ut = {
165
+ var Pt = {
144
166
  protanopia: "Protanopia (no red)",
145
167
  deuteranopia: "Deuteranopia (no green)",
146
168
  tritanopia: "Tritanopia (no blue)"
147
- }, E = {
169
+ }, Ft = {
148
170
  protanopia: [
149
171
  .152286,
150
172
  1.052583,
@@ -212,27 +234,27 @@ var ut = {
212
234
  0
213
235
  ]
214
236
  };
215
- function D(e) {
237
+ function It(e) {
216
238
  return `bc-cvd-${e}`;
217
239
  }
218
- function dt(e) {
240
+ function Lt(e) {
219
241
  let t = "http://www.w3.org/2000/svg", n = document.createElementNS(t, "filter");
220
- n.setAttribute("id", D(e)), n.setAttribute("color-interpolation-filters", "linearRGB");
242
+ n.setAttribute("id", It(e)), n.setAttribute("color-interpolation-filters", "linearRGB");
221
243
  let r = document.createElementNS(t, "feColorMatrix");
222
- return r.setAttribute("type", "matrix"), r.setAttribute("values", E[e].join(" ")), n.appendChild(r), n;
244
+ return r.setAttribute("type", "matrix"), r.setAttribute("values", Ft[e].join(" ")), n.appendChild(r), n;
223
245
  }
224
- function ft(e) {
246
+ function Rt(e) {
225
247
  return e <= .04045 ? e / 12.92 : ((e + .055) / 1.055) ** 2.4;
226
248
  }
227
- function O(e) {
249
+ function k(e) {
228
250
  return e <= .0031308 ? 12.92 * e : 1.055 * e ** (1 / 2.4) - .055;
229
251
  }
230
- function k(e, t) {
231
- let [n, r, i] = x(e).rgb().map((e) => ft(e / 255)), a = E[t], o = O(a[0] * n + a[1] * r + a[2] * i), s = O(a[5] * n + a[6] * r + a[7] * i), c = O(a[10] * n + a[11] * r + a[12] * i), l = (e) => Math.min(255, Math.max(0, Math.round(e * 255)));
232
- return x(l(o), l(s), l(c)).hex();
252
+ function zt(e, t) {
253
+ let [n, r, i] = (T.valid(e) ? T(e) : T("#000")).rgb().map((e) => Rt(e / 255)), a = Ft[t], o = k(a[0] * n + a[1] * r + a[2] * i), s = k(a[5] * n + a[6] * r + a[7] * i), c = k(a[10] * n + a[11] * r + a[12] * i), l = (e) => Math.min(255, Math.max(0, Math.round(e * 255)));
254
+ return T(l(o), l(s), l(c)).hex();
233
255
  }
234
- var pt = 10;
235
- function mt(e) {
256
+ var Bt = 10;
257
+ function Vt(e) {
236
258
  if (e.length < 2) return [];
237
259
  let t = [
238
260
  "protanopia",
@@ -240,10 +262,10 @@ function mt(e) {
240
262
  "tritanopia"
241
263
  ], n = [];
242
264
  for (let r of t) {
243
- let t = e.map((e) => k(e, r)), i = [];
265
+ let t = e.map((e) => zt(e, r)), i = [];
244
266
  for (let n = 0; n < t.length; n++) for (let r = n + 1; r < t.length; r++) {
245
- let a = x.deltaE(t[n], t[r]);
246
- a < pt && i.push({
267
+ let a = T.deltaE(t[n], t[r]);
268
+ a < Bt && i.push({
247
269
  a: e[n],
248
270
  b: e[r],
249
271
  deltaE: a
@@ -251,7 +273,7 @@ function mt(e) {
251
273
  }
252
274
  i.length > 0 && n.push({
253
275
  type: r,
254
- label: ut[r],
276
+ label: Pt[r],
255
277
  pairs: i
256
278
  });
257
279
  }
@@ -262,150 +284,159 @@ function mt(e) {
262
284
  function A(e, t) {
263
285
  return (e ?? []).flatMap((e) => e.split("\n").map((e) => `${t}// ${e.trim()}`));
264
286
  }
265
- function j(e) {
266
- return typeof e.value == "number" ? e.isPercentage ? `${e.value}%` : `${e.value}` : typeof e.value == "string" && e.value.startsWith("#") ? `"${e.value}"` : typeof e.value == "string" && /^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(e.value) ? e.value : `"${String(e.value).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
287
+ function j(e, t) {
288
+ return t == null ? e : t.includes("\n") ? `${e} /* ${t} */` : `${e} // ${t}`;
267
289
  }
268
290
  function M(e, t) {
269
- let n = `${t}${/^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(e.key) ? e.key : `"${e.key}"`} = ${j(e)}`;
270
- return [...A(e.leadingComments, t), n].join("\n");
291
+ return [...A(e.trailingComments, `${t} `), j(`${t}}`, e.trailingComment)];
271
292
  }
272
- function ht(e, t) {
273
- let n;
274
- return n = e.key === "series" && e.quotedKey && !(e.values && e.values.length > 1) ? `${t}"series" = ${j(e)}` : e.values && e.values.length > 1 ? `${t}${e.key === "series" && !e.quotedKey ? e.key : `"${e.key}"`} = ${e.values.map((e) => typeof e == "number" ? `${e}` : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",")}` : `${t}${/^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(e.key) ? e.key : `"${e.key}"`} = ${j(e)}`, [...A(e.leadingComments, t), n].join("\n");
293
+ function N(e) {
294
+ return typeof e.value == "number" ? e.isPercentage ? `${e.value}%` : `${e.value}` : typeof e.value == "string" && e.value.startsWith("#") ? w(e.value) : typeof e.value == "string" && /^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(e.value) ? e.value : w(String(e.value));
275
295
  }
276
- function N(e, t) {
277
- let n = [...A(e.leadingComments, t), `${t}data {`];
278
- for (let r of e.entries) n.push(ht(r, `${t} `));
279
- return n.push(`${t}}`), n.join("\n");
296
+ function Ht(e) {
297
+ return /^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(e) ? e : w(e);
280
298
  }
281
299
  function P(e, t) {
282
- let n = e.fromHighlight ? "highlight" : "colorize", r = [...A(e.leadingComments, t), `${t}${n} "${e.target}" {`];
283
- for (let n of e.properties) r.push(M(n, `${t} `));
284
- return r.push(`${t}}`), r.join("\n");
300
+ let n = j(`${t}${Ht(e.key)} = ${N(e)}`, e.trailingComment);
301
+ return [...A(e.leadingComments, t), n].join("\n");
302
+ }
303
+ function Ut(e, t) {
304
+ let n;
305
+ return n = e.key === "series" && e.quotedKey && !(e.values && e.values.length > 1) ? `${t}"series" = ${N(e)}` : e.values && e.values.length > 1 ? `${t}${e.key === "series" && !e.quotedKey ? e.key : w(e.key)} = ${e.values.map((e) => typeof e == "number" ? `${e}` : w(String(e))).join(",")}` : `${t}${Ht(e.key)} = ${N(e)}`, [...A(e.leadingComments, t), j(n, e.trailingComment)].join("\n");
285
306
  }
286
307
  function F(e, t) {
287
- return [...A(e.leadingComments, t), `${t}highlight "${e.target}"`].join("\n");
308
+ let n = [...A(e.leadingComments, t), `${t}data {`];
309
+ for (let r of e.entries) n.push(Ut(r, `${t} `));
310
+ return n.push(...M(e, t)), n.join("\n");
288
311
  }
289
312
  function I(e, t) {
290
- let n = [...A(e.leadingComments, t), `${t}area-fill "${e.from}" "${e.to}" {`];
291
- for (let r of e.properties) n.push(M(r, `${t} `));
292
- return n.push(`${t}}`), n.join("\n");
313
+ let n = e.fromHighlight ? "highlight" : "colorize", r = [...A(e.leadingComments, t), `${t}${n} ${w(e.target)} {`];
314
+ for (let n of e.properties) r.push(P(n, `${t} `));
315
+ return r.push(...M(e, t)), r.join("\n");
293
316
  }
294
317
  function L(e, t) {
295
- let n = e.kind ?? d.Point;
296
- if (n === d.Range) {
318
+ return [...A(e.leadingComments, t), j(`${t}highlight ${w(e.target)}`, e.trailingComment)].join("\n");
319
+ }
320
+ function R(e, t) {
321
+ let n = [...A(e.leadingComments, t), `${t}area-fill ${w(e.from)} ${w(e.to)} {`];
322
+ for (let r of e.properties) n.push(P(r, `${t} `));
323
+ return n.push(...M(e, t)), n.join("\n");
324
+ }
325
+ function z(e, t) {
326
+ let n = e.kind ?? x.Point;
327
+ if (n === x.Range) {
297
328
  let n = [...A(e.leadingComments, t), `${t}range {`];
298
- for (let r of e.properties) n.push(M(r, `${t} `));
299
- return n.push(`${t}}`), n.join("\n");
329
+ for (let r of e.properties) n.push(P(r, `${t} `));
330
+ return n.push(...M(e, t)), n.join("\n");
300
331
  }
301
- if (n === d.Free) {
332
+ if (n === x.Free) {
302
333
  let n = [...A(e.leadingComments, t), `${t}note {`];
303
- for (let r of e.properties) n.push(M(r, `${t} `));
304
- return n.push(`${t}}`), n.join("\n");
334
+ for (let r of e.properties) n.push(P(r, `${t} `));
335
+ return n.push(...M(e, t)), n.join("\n");
305
336
  }
306
- let r = "target" in e ? e.target : "", i = [...A(e.leadingComments, t), `${t}annotation "${r}" {`];
307
- for (let n of e.properties) i.push(M(n, `${t} `));
308
- return i.push(`${t}}`), i.join("\n");
337
+ let r = "target" in e ? e.target : "", i = [...A(e.leadingComments, t), `${t}annotation ${w(r)} {`];
338
+ for (let n of e.properties) i.push(P(n, `${t} `));
339
+ return i.push(...M(e, t)), i.join("\n");
309
340
  }
310
- function R(e, t) {
311
- let n = [...A(e.leadingComments, t), `${t}series "${e.name}" {`];
312
- for (let r of e.properties) n.push(M(r, `${t} `));
313
- return n.push(`${t}}`), n.join("\n");
341
+ function B(e, t) {
342
+ let n = [...A(e.leadingComments, t), `${t}series ${w(e.name)} {`];
343
+ for (let r of e.properties) n.push(P(r, `${t} `));
344
+ return n.push(...M(e, t)), n.join("\n");
314
345
  }
315
- function z(e, t) {
316
- let n = e.name == null ? `${t}scene {` : `${t}scene "${e.name}" {`, r = [...A(e.leadingComments, t), n];
317
- for (let n of e.properties) r.push(M(n, `${t} `));
318
- e.data && r.push(N(e.data, `${t} `));
319
- for (let n of e.colorizes) r.push(P(n, `${t} `));
320
- for (let n of e.highlights) r.push(F(n, `${t} `));
321
- for (let n of e.areaFills) r.push(I(n, `${t} `));
322
- for (let n of e.annotations) r.push(L(n, `${t} `));
323
- for (let n of e.series) r.push(R(n, `${t} `));
324
- for (let n of e.transforms) r.push(B(n, `${t} `));
325
- return r.push(`${t}}`), r.join("\n");
346
+ function Wt(e, t) {
347
+ let n = e.name == null ? `${t}scene {` : `${t}scene ${w(e.name)} {`, r = [...A(e.leadingComments, t), n];
348
+ for (let n of e.properties) r.push(P(n, `${t} `));
349
+ e.data && r.push(F(e.data, `${t} `));
350
+ for (let n of e.colorizes) r.push(I(n, `${t} `));
351
+ for (let n of e.highlights) r.push(L(n, `${t} `));
352
+ for (let n of e.areaFills) r.push(R(n, `${t} `));
353
+ for (let n of e.annotations) r.push(z(n, `${t} `));
354
+ for (let n of e.series) r.push(B(n, `${t} `));
355
+ for (let n of e.transforms) r.push(V(n, `${t} `));
356
+ return r.push(...M(e, t)), r.join("\n");
326
357
  }
327
- function B(e, t) {
358
+ function V(e, t) {
328
359
  let n = [...A(e.leadingComments, t), `${t}transform ${e.transformType} {`];
329
- for (let r of e.properties) n.push(M(r, `${t} `));
330
- return n.push(`${t}}`), n.join("\n");
360
+ for (let r of e.properties) n.push(P(r, `${t} `));
361
+ return n.push(...M(e, t)), n.join("\n");
331
362
  }
332
- function gt(e, t, n) {
333
- let r = b(n).find((t) => t.key === e);
363
+ function Gt(e, t, n) {
364
+ let r = h(n).find((t) => t.key === e);
334
365
  return !r || r.default === void 0 ? !1 : String(r.default) === String(t);
335
366
  }
336
- function _t(e) {
367
+ function Kt(e) {
337
368
  let t = [`chart ${e.chartType} {`];
338
- for (let n of e.properties) t.push(M(n, " "));
339
- e.data && t.push(N(e.data, " "));
340
- for (let n of e.colorizes) t.push(P(n, " "));
341
- for (let n of e.highlights) t.push(F(n, " "));
342
- for (let n of e.areaFills) t.push(I(n, " "));
343
- for (let n of e.annotations) t.push(L(n, " "));
344
- for (let n of e.series) t.push(R(n, " "));
345
- for (let n of e.scenes) t.push(z(n, " "));
346
- for (let n of e.transforms) t.push(B(n, " "));
347
- return t.push("}"), t.join("\n");
348
- }
349
- function vt(e) {
369
+ for (let n of e.properties) t.push(P(n, " "));
370
+ e.data && t.push(F(e.data, " "));
371
+ for (let n of e.colorizes) t.push(I(n, " "));
372
+ for (let n of e.highlights) t.push(L(n, " "));
373
+ for (let n of e.areaFills) t.push(R(n, " "));
374
+ for (let n of e.annotations) t.push(z(n, " "));
375
+ for (let n of e.series) t.push(B(n, " "));
376
+ for (let n of e.scenes) t.push(Wt(n, " "));
377
+ for (let n of e.transforms) t.push(V(n, " "));
378
+ return t.push(...A(e.trailingComments, " "), "}"), t.join("\n");
379
+ }
380
+ function qt(e) {
350
381
  return new Map(e.map((e) => [e.key, e.value]));
351
382
  }
352
- function V(e, t, n, r) {
353
- let i = b(n).find((t) => t.key === e);
383
+ function H(e, t, n, r) {
384
+ let i = h(n).find((t) => t.key === e);
354
385
  return i ? r.has(e) ? String(r.get(e)) === String(t) : i.default !== void 0 && String(i.default) === String(t) : !1;
355
386
  }
356
- function H(e, t, n, r) {
357
- let i = [...A(e.leadingComments, t), `${t}series "${e.name}" {`];
358
- for (let a of e.properties) (a.isPercentage || !V(a.key, a.value, n, r)) && i.push(M(a, `${t} `));
359
- return i.push(`${t}}`), i.join("\n");
387
+ function Jt(e, t, n, r) {
388
+ let i = [...A(e.leadingComments, t), `${t}series ${w(e.name)} {`];
389
+ for (let a of e.properties) (a.isPercentage || !H(a.key, a.value, n, r)) && i.push(P(a, `${t} `));
390
+ return i.push(...M(e, t)), i.join("\n");
360
391
  }
361
- function yt(e, t, n, r) {
362
- let i = e.properties.find((e) => e.key === "type"), a = i ? String(i.value) : n, o = e.name == null ? `${t}scene {` : `${t}scene "${e.name}" {`, s = [...A(e.leadingComments, t), o], c = new Map(r);
392
+ function Yt(e, t, n, r) {
393
+ let i = e.properties.find((e) => e.key === "type"), a = i ? String(i.value) : n, o = e.name == null ? `${t}scene {` : `${t}scene ${w(e.name)} {`, s = [...A(e.leadingComments, t), o], c = new Map(r);
363
394
  for (let n of e.properties) {
364
395
  if (n.key === "type") {
365
- s.push(M(n, `${t} `));
396
+ s.push(P(n, `${t} `));
366
397
  continue;
367
398
  }
368
- c.set(n.key, n.value), (n.isPercentage || !V(n.key, n.value, a, r)) && s.push(M(n, `${t} `));
399
+ c.set(n.key, n.value), (n.isPercentage || !H(n.key, n.value, a, r)) && s.push(P(n, `${t} `));
369
400
  }
370
- e.data && s.push(N(e.data, `${t} `));
371
- for (let n of e.colorizes) s.push(P(n, `${t} `));
372
- for (let n of e.highlights) s.push(F(n, `${t} `));
373
- for (let n of e.areaFills) s.push(I(n, `${t} `));
374
- for (let n of e.annotations) s.push(L(n, `${t} `));
375
- for (let n of e.series) s.push(H(n, `${t} `, a, c));
376
- for (let n of e.transforms) s.push(B(n, `${t} `));
377
- return s.push(`${t}}`), s.join("\n");
378
- }
379
- function bt(e) {
401
+ e.data && s.push(F(e.data, `${t} `));
402
+ for (let n of e.colorizes) s.push(I(n, `${t} `));
403
+ for (let n of e.highlights) s.push(L(n, `${t} `));
404
+ for (let n of e.areaFills) s.push(R(n, `${t} `));
405
+ for (let n of e.annotations) s.push(z(n, `${t} `));
406
+ for (let n of e.series) s.push(Jt(n, `${t} `, a, c));
407
+ for (let n of e.transforms) s.push(V(n, `${t} `));
408
+ return s.push(...M(e, t)), s.join("\n");
409
+ }
410
+ function Xt(e) {
380
411
  let t = [`chart ${e.chartType} {`], n = /* @__PURE__ */ new Map();
381
- for (let r of e.properties) (r.isPercentage || !V(r.key, r.value, e.chartType, n)) && t.push(M(r, " "));
382
- e.data && t.push(N(e.data, " "));
383
- for (let n of e.colorizes) t.push(P(n, " "));
384
- for (let n of e.highlights) t.push(F(n, " "));
385
- for (let n of e.areaFills) t.push(I(n, " "));
386
- for (let n of e.annotations) t.push(L(n, " "));
387
- let r = vt(e.properties);
388
- for (let n of e.series) t.push(H(n, " ", e.chartType, r));
389
- for (let n of e.scenes) t.push(yt(n, " ", e.chartType, r));
390
- for (let n of e.transforms) t.push(B(n, " "));
391
- return t.push("}"), t.join("\n");
392
- }
393
- function xt(e) {
412
+ for (let r of e.properties) (r.isPercentage || !H(r.key, r.value, e.chartType, n)) && t.push(P(r, " "));
413
+ e.data && t.push(F(e.data, " "));
414
+ for (let n of e.colorizes) t.push(I(n, " "));
415
+ for (let n of e.highlights) t.push(L(n, " "));
416
+ for (let n of e.areaFills) t.push(R(n, " "));
417
+ for (let n of e.annotations) t.push(z(n, " "));
418
+ let r = qt(e.properties);
419
+ for (let n of e.series) t.push(Jt(n, " ", e.chartType, r));
420
+ for (let n of e.scenes) t.push(Yt(n, " ", e.chartType, r));
421
+ for (let n of e.transforms) t.push(V(n, " "));
422
+ return t.push(...A(e.trailingComments, " "), "}"), t.join("\n");
423
+ }
424
+ function Zt(e) {
394
425
  let t = [`chart ${e.chartType} {`];
395
- for (let n of e.properties) gt(n.key, n.value, e.chartType) || t.push(M(n, " "));
396
- e.data && t.push(N(e.data, " "));
397
- for (let n of e.colorizes) t.push(P(n, " "));
398
- for (let n of e.highlights) t.push(F(n, " "));
399
- for (let n of e.areaFills) t.push(I(n, " "));
400
- for (let n of e.annotations) t.push(L(n, " "));
401
- for (let n of e.series) t.push(R(n, " "));
402
- for (let n of e.scenes) t.push(z(n, " "));
403
- for (let n of e.transforms) t.push(B(n, " "));
404
- return t.push("}"), t.join("\n");
426
+ for (let n of e.properties) Gt(n.key, n.value, e.chartType) || t.push(P(n, " "));
427
+ e.data && t.push(F(e.data, " "));
428
+ for (let n of e.colorizes) t.push(I(n, " "));
429
+ for (let n of e.highlights) t.push(L(n, " "));
430
+ for (let n of e.areaFills) t.push(R(n, " "));
431
+ for (let n of e.annotations) t.push(z(n, " "));
432
+ for (let n of e.series) t.push(B(n, " "));
433
+ for (let n of e.scenes) t.push(Wt(n, " "));
434
+ for (let n of e.transforms) t.push(V(n, " "));
435
+ return t.push(...A(e.trailingComments, " "), "}"), t.join("\n");
405
436
  }
406
437
  //#endregion
407
438
  //#region src/dsl/validate.ts
408
- var U = /* @__PURE__ */ new Set([
439
+ var Qt = /* @__PURE__ */ new Set([
409
440
  "title",
410
441
  "description",
411
442
  "byline",
@@ -420,8 +451,32 @@ var U = /* @__PURE__ */ new Set([
420
451
  "theme",
421
452
  "heightMode",
422
453
  "aspectRatio",
423
- "fixedHeight"
424
- ]), W = /* @__PURE__ */ new Set(["sort"]), St = /* @__PURE__ */ new Set([
454
+ "fixedHeight",
455
+ "sizing",
456
+ "fixedWidth",
457
+ "maxWidth",
458
+ "player",
459
+ "playerPosition"
460
+ ]), $t = /* @__PURE__ */ new Map([
461
+ ["theme", Nt().map((e) => e.name)],
462
+ ["player", [
463
+ "buttons",
464
+ "progress-bar",
465
+ "dot-stepper",
466
+ "minimal-arrows",
467
+ "none"
468
+ ]],
469
+ ["playerPosition", [
470
+ "left",
471
+ "center",
472
+ "right"
473
+ ]]
474
+ ]), en = /* @__PURE__ */ new Set([
475
+ "lineSymbolSize",
476
+ "fixedHeight",
477
+ "fixedWidth",
478
+ "maxWidth"
479
+ ]), U = it, tn = /* @__PURE__ */ new Set([
425
480
  "text",
426
481
  "repeat",
427
482
  "textColor",
@@ -439,7 +494,26 @@ var U = /* @__PURE__ */ new Set([
439
494
  "circleSize",
440
495
  "circleStyle",
441
496
  "circleColor"
442
- ]), Ct = /* @__PURE__ */ new Set([
497
+ ]), nn = /* @__PURE__ */ new Set([
498
+ "color",
499
+ "lineWidth",
500
+ "dash",
501
+ "interpolation",
502
+ "labelMode",
503
+ "labelText",
504
+ "valueLabels",
505
+ "lineSymbols",
506
+ "hidden",
507
+ "symbolShape",
508
+ "symbolShowOn",
509
+ "symbolStyle",
510
+ "symbolSize",
511
+ "symbolOpacity"
512
+ ]), rn = /* @__PURE__ */ new Map([
513
+ ["symbolShape", "lineSymbolShape"],
514
+ ["symbolShowOn", "lineSymbolShowOn"],
515
+ ["symbolStyle", "lineSymbolStyle"]
516
+ ]), an = /* @__PURE__ */ new Set([
443
517
  "start",
444
518
  "end",
445
519
  "repeat",
@@ -451,7 +525,7 @@ var U = /* @__PURE__ */ new Set([
451
525
  "direction",
452
526
  "text",
453
527
  "textColor"
454
- ]), wt = /* @__PURE__ */ new Set([
528
+ ]), on = /* @__PURE__ */ new Set([
455
529
  "text",
456
530
  "x",
457
531
  "y",
@@ -460,7 +534,7 @@ var U = /* @__PURE__ */ new Set([
460
534
  "maxWidth",
461
535
  "textOutline"
462
536
  ]);
463
- function Tt(e, t) {
537
+ function sn(e, t) {
464
538
  let n = e.length, r = t.length;
465
539
  if (n === 0) return r;
466
540
  if (r === 0) return n;
@@ -475,22 +549,39 @@ function Tt(e, t) {
475
549
  }
476
550
  return i[r];
477
551
  }
478
- function G(e, t) {
552
+ function W(e, t) {
479
553
  let n, r = Infinity;
480
554
  for (let i of t) {
481
- let t = Tt(e.toLowerCase(), i.toLowerCase());
555
+ let t = sn(e.toLowerCase(), i.toLowerCase());
482
556
  t < r && (r = t, n = i);
483
557
  }
484
558
  if (n === void 0) return;
485
559
  let i = Math.max(1, Math.min(3, Math.floor(e.length / 2)));
486
560
  return r <= i ? n : void 0;
487
561
  }
488
- function Et(e, t) {
562
+ function cn(e, t) {
489
563
  return e.find((e) => e.key === t);
490
564
  }
491
- function Dt(e, t, n, r) {
565
+ function G(e, t, n, r, i) {
566
+ i.push({
567
+ code: "invalid-choice",
568
+ path: r,
569
+ message: `${e} must be one of: ${n.map((e) => `"${e}"`).join(", ")}; got "${t}".`,
570
+ suggestion: W(String(t), n.filter((e) => e !== ""))
571
+ });
572
+ }
573
+ function ln(e, t, n) {
574
+ if (!en.has(e.key)) return;
575
+ let r = parseFloat(String(e.value));
576
+ Number.isFinite(r) && r < 0 && n.push({
577
+ code: "invalid-number",
578
+ path: t,
579
+ message: `${e.key} must not be negative; got "${e.value}".`
580
+ });
581
+ }
582
+ function un(e, t, n, r) {
492
583
  let i = t.value, a = String(i).toLowerCase();
493
- if (e.type === y.Boolean) {
584
+ if (e.type === o.Boolean) {
494
585
  if (e.key === "valueLabels" && a === "percent" || i === !0 || i === !1 || a === "true" || a === "false") return;
495
586
  r.push({
496
587
  code: "invalid-boolean",
@@ -503,88 +594,150 @@ function Dt(e, t, n, r) {
503
594
  if (e.choices && e.choices.length > 0) {
504
595
  let t = e.choices.map((e) => e.value);
505
596
  if (t.includes(String(i)) || String(i) === "" && t.includes("")) return;
506
- let a = G(String(i), t.filter((e) => e !== ""));
507
- r.push({
508
- code: "invalid-choice",
509
- path: n,
510
- message: `${e.key} must be one of: ${t.map((e) => `"${e}"`).join(", ")}; got "${i}".`,
511
- suggestion: a
512
- });
597
+ G(e.key, i, t, n, r);
513
598
  }
514
599
  }
515
600
  function K(e, t, n, r) {
516
- let i = b(e), a = /* @__PURE__ */ new Set([...i.map((e) => e.key), ...U]);
601
+ let i = h(e), a = /* @__PURE__ */ new Set([...i.map((e) => e.key), ...Qt]);
517
602
  for (let o of t) {
518
603
  let t = `${n}.${o.key}`;
519
- if (U.has(o.key)) continue;
520
- let s = Et(i, o.key);
521
- if (!s) {
604
+ ln(o, t, r);
605
+ let s = $t.get(o.key);
606
+ if (s && String(o.value) !== "" && !s.includes(String(o.value)) && G(o.key, o.value, s, t, r), Qt.has(o.key)) continue;
607
+ let c = cn(i, o.key);
608
+ if (!c) {
522
609
  r.push({
523
610
  code: "unknown-property",
524
611
  path: t,
525
612
  message: `Unknown property "${o.key}" for chart type "${e}".`,
526
- suggestion: G(o.key, a)
613
+ suggestion: W(o.key, a)
527
614
  });
528
615
  continue;
529
616
  }
530
- Dt(s, o, t, r);
617
+ un(c, o, t, r);
531
618
  }
532
619
  }
533
- function Ot(e) {
534
- return e === d.Range ? Ct : e === d.Free ? wt : St;
620
+ function dn(e) {
621
+ return e === x.Range ? an : e === x.Free ? on : tn;
535
622
  }
536
- function kt(e) {
537
- return p[e];
623
+ function fn(e) {
624
+ return C[e];
538
625
  }
539
- function q(e, t, n) {
626
+ function pn(e, t, n) {
540
627
  e.forEach((e, r) => {
541
- let i = e.kind ?? d.Point, a = Ot(i), o = kt(i);
628
+ let i = e.kind ?? x.Point, a = dn(i), o = fn(i);
542
629
  for (let i of e.properties) a.has(i.key) || n.push({
543
630
  code: "unknown-annotation-property",
544
631
  path: `${t}.${o}[${r}].${i.key}`,
545
632
  message: `Unknown ${o} property "${i.key}"; it will be silently ignored.`,
546
- suggestion: G(i.key, a)
633
+ suggestion: W(i.key, a)
547
634
  });
548
- let s = v(e.properties).get("repeat");
549
- s !== void 0 && (s === "true" || s === "false" || s === !0 || s === !1 || typeof s == "number" && Number.isInteger(s) && s >= 1 || n.push({
550
- code: "invalid-annotation-repeat",
551
- message: `repeat must be false, true, or a positive integer (got ${String(s)})`,
552
- path: `${t}.${o}[${r}].repeat`
553
- }));
635
+ let s = se(e.properties).get("repeat");
636
+ if (s !== void 0) {
637
+ let e = String(s).toLowerCase();
638
+ e === "true" || e === "false" || typeof s == "number" && Number.isInteger(s) && s >= 1 || n.push({
639
+ code: "invalid-annotation-repeat",
640
+ message: `repeat must be false, true, or a positive integer (got ${String(s)})`,
641
+ path: `${t}.${o}[${r}].repeat`
642
+ });
643
+ }
554
644
  });
555
645
  }
556
- function J(e, t, n) {
646
+ function mn(e, t, n, r) {
647
+ let i = h(e);
648
+ t.forEach((e, t) => {
649
+ for (let a of e.properties) {
650
+ let e = `${n}.series[${t}].${a.key}`;
651
+ if (!nn.has(a.key)) {
652
+ r.push({
653
+ code: "unknown-series-property",
654
+ path: e,
655
+ message: `Unknown series property "${a.key}"; it will be silently ignored.`,
656
+ suggestion: W(a.key, nn)
657
+ });
658
+ continue;
659
+ }
660
+ let o = cn(i, rn.get(a.key) ?? a.key)?.choices?.map((e) => e.value);
661
+ o?.length && !o.includes(String(a.value)) && G(a.key, a.value, o, e, r);
662
+ }
663
+ });
664
+ }
665
+ function hn(e, t, n) {
557
666
  e.forEach((e, r) => {
558
- W.has(e.transformType) || n.push({
667
+ U.has(e.transformType) || n.push({
559
668
  code: "unknown-transform",
560
669
  path: `${t}.transform[${r}]`,
561
- message: `Unknown transform type "${e.transformType}". Known types: ${[...W].map((e) => `"${e}"`).join(", ")}.`,
562
- suggestion: G(e.transformType, W)
670
+ message: `Unknown transform type "${e.transformType}". Known types: ${[...U].map((e) => `"${e}"`).join(", ")}.`,
671
+ suggestion: W(e.transformType, U)
563
672
  });
564
673
  });
565
674
  }
566
- function At(e) {
567
- let t = [], n = [], r = f(), i = r.includes(e.chartType);
675
+ function gn(e) {
676
+ let t = /* @__PURE__ */ new Set();
677
+ for (let n of [e.data, ...e.scenes.map((e) => e.data)]) for (let e of n?.entries ?? []) {
678
+ if (e.key === "series" && !e.quotedKey) {
679
+ for (let n of e.values ?? [e.value]) t.add(String(n));
680
+ continue;
681
+ }
682
+ t.add(e.key);
683
+ }
684
+ return t;
685
+ }
686
+ function _n(e, t) {
687
+ let n = gn(e);
688
+ if (n.size === 0) return;
689
+ let r = [
690
+ {
691
+ basePath: "chart",
692
+ keyword: "highlight",
693
+ nodes: e.highlights
694
+ },
695
+ {
696
+ basePath: "chart",
697
+ keyword: "colorize",
698
+ nodes: e.colorizes
699
+ },
700
+ ...e.scenes.flatMap((e, t) => [{
701
+ basePath: `scene[${t}]`,
702
+ keyword: "highlight",
703
+ nodes: e.highlights
704
+ }, {
705
+ basePath: `scene[${t}]`,
706
+ keyword: "colorize",
707
+ nodes: e.colorizes
708
+ }])
709
+ ];
710
+ for (let { basePath: e, keyword: i, nodes: a } of r) a.forEach((r, a) => {
711
+ n.has(r.target) || t.push({
712
+ code: "unresolved-target",
713
+ path: `${e}.${i}[${a}]`,
714
+ message: `${i} "${r.target}" matches no category or series; it has no effect.`,
715
+ suggestion: W(r.target, n)
716
+ });
717
+ });
718
+ }
719
+ function vn(e) {
720
+ let t = [], n = [], r = y(), i = r.includes(e.chartType);
568
721
  i || t.push({
569
722
  code: "unknown-chart-type",
570
723
  path: "chartType",
571
724
  message: `Unknown chart type "${e.chartType}".`,
572
- suggestion: G(e.chartType, r)
573
- }), i && K(e.chartType, e.properties, "chart", t), J(e.transforms, "chart", t), q(e.annotations, "chart", t);
725
+ suggestion: W(e.chartType, r)
726
+ }), i && K(e.chartType, e.properties, "chart", t), hn(e.transforms, "chart", t), pn(e.annotations, "chart", t), i && mn(e.chartType, e.series, "chart", t);
574
727
  let a = !!e.data && e.data.entries.length > 0, o = e.scenes.some((e) => !!e.data && e.data.entries.length > 0);
575
728
  return !a && !o && t.push({
576
729
  code: "missing-data",
577
730
  path: "data",
578
731
  message: e.data && e.data.entries.length === 0 ? "Data block is empty." : "Chart has no data."
579
- }), e.data && jt(e.data.entries, n), e.scenes.forEach((n, r) => {
580
- Mt(n, e.chartType, r, t);
732
+ }), e.data && yn(e.data.entries, n), e.data && bn(e.data.entries, n), _n(e, n), e.scenes.forEach((n, r) => {
733
+ xn(n, e.chartType, r, t);
581
734
  }), {
582
735
  valid: t.length === 0,
583
736
  errors: t,
584
737
  warnings: n
585
738
  };
586
739
  }
587
- function jt(e, t) {
740
+ function yn(e, t) {
588
741
  let n = e.findIndex((e) => e.key === "series" && !e.quotedKey);
589
742
  if (n === -1) return;
590
743
  let r = e[n], i = r.values ?? [r.value];
@@ -600,25 +753,35 @@ function jt(e, t) {
600
753
  suggestion: "Move the series row to the top of the data block."
601
754
  });
602
755
  }
603
- function Mt(e, t, n, r) {
756
+ function bn(e, t) {
757
+ let n = /* @__PURE__ */ new Map();
758
+ for (let t of e) t.key === "series" && !t.quotedKey || n.set(t.key, (n.get(t.key) ?? 0) + 1);
759
+ for (let [e, r] of n) r > 1 && t.push({
760
+ code: "duplicate-data-key",
761
+ path: `data.${e}`,
762
+ message: `${r} rows share the label "${e}", so the chart numbers the repeats "${e} (2)" and up. Rename them, or combine the rows, if they are the same category.`,
763
+ suggestion: `"${e} (2)"`
764
+ });
765
+ }
766
+ function xn(e, t, n, r) {
604
767
  let i = `scene[${n}]`, a = e.properties.find((e) => e.key === "type")?.value, o = a == null ? t : String(a);
605
- a != null && !f().includes(o) ? r.push({
768
+ a != null && !y().includes(o) ? r.push({
606
769
  code: "unknown-chart-type",
607
770
  path: `${i}.type`,
608
771
  message: `Unknown chart type "${o}".`,
609
- suggestion: G(o, f())
610
- }) : K(o, e.properties, i, r), J(e.transforms, i, r), q(e.annotations, i, r);
772
+ suggestion: W(o, y())
773
+ }) : (K(o, e.properties, i, r), mn(o, e.series, i, r)), hn(e.transforms, i, r), pn(e.annotations, i, r);
611
774
  }
612
775
  //#endregion
613
776
  //#region src/samples/letter-frequency.bpc?raw
614
- var Nt = "chart bar-vertical {\n title = \"E is the most frequent letter in English\"\n description = \"How often each letter appears in typical English text\"\n byline = \"Pierre Romera\"\n source = \"Lewand, Cryptological Mathematics\"\n sourceUrl = \"https://en.wikipedia.org/wiki/Letter_frequency\"\n note = \"Based on analysis of 40,000 words from English prose\"\n colorPalette = \"London\"\n sort = descending\n\n highlight \"E\"\n\n data {\n \"E\" = 12.70\n \"T\" = 9.06\n \"A\" = 8.17\n \"O\" = 7.51\n \"I\" = 6.97\n \"N\" = 6.75\n \"S\" = 6.33\n \"H\" = 6.09\n \"R\" = 5.99\n \"D\" = 4.25\n }\n}\n", Pt = "chart bar-vertical {\n // the headline above the chart\n title = \"China emits more CO₂ than the US and India combined\"\n description = \"Annual emissions in billion tonnes, 2023\"\n source = \"Our World in Data\"\n sourceUrl = \"https://ourworldindata.org/co2-emissions\"\n\n // one row per country: \"label\" = value\n data {\n \"China\" = 12.17\n \"United States\" = 4.92\n \"India\" = 3.06\n \"Russia\" = 1.73\n \"Japan\" = 0.99\n \"Germany\" = 0.59\n }\n\n // highlight pops one bar in the accent color\n highlight \"China\"\n\n // an annotation points a callout at a single bar\n annotation \"India\" {\n text = \"Surpassed EU in 2023\"\n showLine = true\n anchorDirection = N\n textOffsetX = 66\n textOffsetY = -41\n lineStyle = curve-left\n showArrow = true\n lineTargetDistance = 26\n showCircle = false\n }\n}\n", Ft = "chart bar-horizontal {\n title = \"Mandarin has nearly twice as many native speakers as Spanish\"\n description = \"Number of native speakers worldwide, in millions\"\n source = \"Ethnologue\"\n sourceUrl = \"https://ethnologue.com\"\n byline = \"Pierre Romera\"\n sort = descending\n\n highlight \"Mandarin\"\n\n data {\n \"Mandarin\" = 988\n \"Spanish\" = 487\n \"English\" = 372\n \"Hindi\" = 347\n \"Bengali\" = 232\n \"Portuguese\" = 252\n \"Russian\" = 133\n \"Japanese\" = 124\n }\n}\n", It = "chart line-multi {\n title = \"China now buys more electric cars than the rest of the world combined\"\n description = \"Electric car sales by region, millions per year\"\n source = \"IEA Global EV Outlook 2024\"\n sourceUrl = \"https://www.iea.org/reports/global-ev-outlook-2024\"\n colorPalette = \"Maya\"\n tooltips = true\n\n data {\n series = \"China\",\"Europe\",\"United States\",\"Rest of world\"\n \"2018\" = 1.1,0.4,0.36,0.1\n \"2020\" = 1.3,1.4,0.30,0.2\n \"2021\" = 3.3,2.3,0.63,0.4\n \"2022\" = 6.0,2.7,1.0,0.7\n \"2023\" = 8.1,3.2,1.4,1.0\n }\n}\n", Lt = "chart bar-multi {\n title = \"USA tops Paris 2024 with 126 medals across all categories\"\n description = \"2024 Paris Summer Games — top six nations\"\n source = \"Olympics.com\"\n sourceUrl = \"https://olympics.com\"\n colors = \"#eeca3b, #c0c0c0, #cd7f32\"\n sort = descending\n\n data {\n series = \"Gold\",\"Silver\",\"Bronze\"\n \"USA\" = 40,44,42\n \"China\" = 40,27,24\n \"Japan\" = 20,12,13\n \"Great Britain\" = 14,22,29\n \"Australia\" = 18,19,16\n \"France\" = 16,26,22\n }\n}\n", Rt = "chart line {\n title = \"2024 was the hottest year on record\"\n description = \"Deviation from the 1951–1980 average, in °C\"\n source = \"NASA GISS\"\n sourceUrl = \"https://data.giss.nasa.gov/gistemp/\"\n tooltips = true\n crosshair = false\n lineSymbols = true\n\n data {\n \"1980\" = 0.26\n \"1985\" = 0.12\n \"1990\" = 0.45\n \"1995\" = 0.45\n \"2000\" = 0.39\n \"2005\" = 0.68\n \"2010\" = 0.73\n \"2015\" = 0.9\n \"2020\" = 1.01\n \"2024\" = 1.28\n }\n\n annotation \"2015\" {\n text = \"2015 Paris Agreement to limit global warming to 1.5°C \"\n maxWidth = 224\n showLine = true\n lineStyle = curve-right\n showArrow = true\n showCircle = true\n }\n}\n", zt = "chart line {\n title = \"Bitcoin surged past $90,000 in 2024\"\n description = \"USD, year-end closing price\"\n source = \"CoinGecko\"\n sourceUrl = \"https://www.coingecko.com\"\n colors = \"#f7931a\"\n lineSymbols = true\n lineSymbolShowOn = \"all\"\n lineSymbolShape = \"diamond\"\n verticalNumberFormat = \",.0f\"\n tooltips = true\n\n annotation \"2021\" {\n text = \"All-time high cycle\"\n textOffsetY = -12\n showArrow = true\n }\n\n data {\n \"2016\" = 963\n \"2017\" = 14156\n \"2018\" = 3742\n \"2019\" = 7194\n \"2020\" = 29080\n \"2021\" = 46306\n \"2022\" = 16547\n \"2023\" = 42258\n \"2024\" = 93429\n }\n}\n", Bt = "chart line-multi {\n title = \"The income share of the top 1% has surged since 1980\"\n description = \"Pre-tax national income captured by the top 1%, percent\"\n source = \"World Inequality Database\"\n sourceUrl = \"https://wid.world\"\n colorPalette = \"Egypt\"\n tooltips = true\n lineSymbols = true\n lineSymbolShowOn = \"all\"\n\n data {\n series = \"United States\",\"India\",\"China\",\"France\"\n \"1980\" = 10.4,7.5,6.6,7.5\n \"1990\" = 14.7,10.7,8.3,9.0\n \"2000\" = 17.3,10.5,10.5,11.3\n \"2010\" = 17.9,16.4,15.2,11.0\n \"2021\" = 19.9,22.1,15.7,12.7\n }\n\n scene \"US doubles\" {\n title = \"The US top 1% nearly doubled its income share since 1980\"\n highlight \"United States\"\n }\n\n scene \"India overtakes\" {\n title = \"India is now the most unequal of these major economies\"\n highlight \"India\"\n }\n\n scene \"France's modest rise\" {\n title = \"France's top 1% rose far less than the US or India\"\n highlight \"France\"\n }\n}\n", Vt = "chart pie {\n title = \"Asia is home to nearly 60% of the world's population\"\n description = \"Estimated share, 2024\"\n source = \"United Nations\"\n sourceUrl = \"https://population.un.org\"\n colorPalette = \"Klimt\"\n legendPosition = \"right\"\n tooltips = true\n\n data {\n \"Asia\" = 58.9\n \"Africa\" = 18.6\n \"Europe\" = 9.1\n \"Latin America\" = 8.1\n \"North America\" = 4.7\n }\n}\n", Ht = "chart bar-vertical {\n title = \"Brazil produces more coffee than the next three countries combined\"\n description = \"Million 60-kg bags, 2023/24 crop year\"\n source = \"USDA Foreign Agricultural Service\"\n sourceUrl = \"https://www.fas.usda.gov/data/coffee-world-markets-and-trade\"\n colorPalette = \"Harvey\"\n\n data {\n \"Brazil\" = 66.4\n \"Vietnam\" = 27.5\n \"Colombia\" = 12.76\n \"Ethiopia\" = 9.13\n \"Indonesia\" = 7.65\n \"Honduras\" = 5.5\n }\n\n highlight \"Brazil\"\n\n transform sort {\n column = \"value\"\n direction = descending\n }\n}\n", Ut = "chart donut {\n title = \"The richest 1% own more wealth than the entire bottom 90% combined\"\n description = \"Share of global wealth by group, 2021\"\n source = \"World Inequality Report 2022\"\n sourceUrl = \"https://wir2022.wid.world\"\n colorPalette = \"Imperator\"\n legendPosition = \"right\"\n displayAsPercentage = true\n tooltips = true\n\n data {\n \"Top 1%\" = 38\n \"Next 9%\" = 38\n \"Middle 40%\" = 22\n \"Bottom 50%\" = 2\n }\n\n scene \"Top 1% spotlight\" {\n title = \"The top 1% hold 38% of all global wealth\"\n description = \"Share of global wealth by group, 2021\"\n highlight \"Top 1%\"\n }\n\n scene \"Bottom half\" {\n title = \"The bottom half of humanity owns just 2%\"\n description = \"Share of global wealth by group, 2021\"\n highlight \"Bottom 50%\"\n }\n\n scene \"Income tells a softer story\" {\n title = \"Income is concentrated too — but less than wealth\"\n description = \"Share of global income by the same groups, 2021\"\n highlight \"Top 1%\"\n data {\n \"Top 1%\" = 19\n \"Next 9%\" = 33\n \"Middle 40%\" = 39\n \"Bottom 50%\" = 9\n }\n }\n}\n", Wt = "chart area {\n title = \"The US national debt has more than tripled since 2008\"\n description = \"Total federal debt outstanding, trillions of dollars\"\n source = \"U.S. Treasury, Fiscal Data\"\n sourceUrl = \"https://fiscaldata.treasury.gov\"\n\n annotation \"2008\" {\n text = \"Financial crisis\"\n showArrow = true\n textOffsetY = -14\n }\n\n data {\n \"2000\" = 5.7\n \"2004\" = 7.4\n \"2008\" = 10.0\n \"2012\" = 16.1\n \"2016\" = 19.6\n \"2020\" = 26.9\n \"2024\" = 35.5\n }\n}\n", Gt = "chart area-stacked {\n title = \"Renewables' share of global energy has more than doubled since 2000\"\n description = \"Share of global primary energy by source, 2000–2023\"\n source = \"Our World in Data\"\n sourceUrl = \"https://ourworldindata.org/energy-mix\"\n stackPercent = true\n areaSortMode = descending\n\n data {\n series = \"Coal\",\"Oil\",\"Gas\",\"Renewables\"\n \"2000\" = 27456,43017,23994,2997\n \"2005\" = 36201,47017,27439,3510\n \"2010\" = 42016,48193,31593,4868\n \"2015\" = 43695,51294,34780,6400\n \"2020\" = 42316,49101,38704,8569\n \"2023\" = 45319,54839,40151,10325\n }\n}\n", Kt = "chart column-stacked {\n title = \"Natural gas and renewables pushed coal off the US power grid\"\n description = \"Share of US electricity generation by source, percent\"\n source = \"U.S. Energy Information Administration\"\n sourceUrl = \"https://www.eia.gov/electricity\"\n stackMode = \"percent\"\n\n data {\n series = \"Coal\",\"Natural gas\",\"Nuclear\",\"Renewables\"\n \"2010\" = 45,24,20,10\n \"2015\" = 33,33,20,13\n \"2020\" = 19,39,20,20\n \"2023\" = 16,43,19,21\n }\n}\n", qt = "chart bar-stacked {\n title = \"India has far more children than China, and a workforce nearly as large\"\n description = \"Millions of people, 2023\"\n source = \"UN Population Division\"\n sourceUrl = \"https://population.un.org\"\n colorPalette = \"London\"\n\n data {\n series = \"0-14\",\"15-64\",\"65+\"\n \"China\" = 232,988,200\n \"India\" = 354,978,97\n \"USA\" = 58,216,59\n \"Indonesia\" = 67,189,21\n \"Brazil\" = 43,148,24\n }\n}\n", Jt = "chart area-stacked {\n title = \"EU subsidies to new members surged after enlargement\"\n description = \"Agricultural subsidies to post-socialist EU members, million euros\"\n source = \"Eurostat\"\n sourceUrl = \"https://ec.europa.eu/eurostat\"\n colorPalette = \"Enara\"\n interpolation = \"linear\"\n heightMode = \"aspect-ratio\"\n aspectRatio = \"1:1\"\n\n data {\n series = \"Indirect subsidies\",\"Direct subsidies\"\n \"2000\" = 370,800\n \"2001\" = 445,896\n \"2002\" = 567,816\n \"2003\" = 641,950\n \"2004\" = 1908,2434\n \"2005\" = 2234,3509\n \"2006\" = 2576,4356\n \"2007\" = 2467,5429\n \"2008\" = 2672,6655\n \"2009\" = 2474,7195\n \"2010\" = 2117,8207\n \"2011\" = 1863,9230\n \"2012\" = 1528,9191\n \"2013\" = 1251,10252\n \"2014\" = 1132,10987\n \"2015\" = 1687,10145\n }\n\n scene \"Indirect subsidies shrank\" {\n title = \"Indirect subsidies were cut under WTO pressure\"\n description = \"Subsidies tied to specific crops fell foul of World Trade Organization rules\"\n\n highlight \"Indirect subsidies\"\n }\n\n scene \"Direct subsidies dominate\" {\n title = \"Direct per-hectare payments now dominate\"\n description = \"The larger the fields, the more money farmers receive\"\n\n highlight \"Direct subsidies\"\n }\n\n scene \"Bulgaria: subsidies explode\" {\n title = \"Bulgarian farmers received almost nothing before 2007 accession\"\n description = \"More than three-quarters of Bulgarian subsidies are direct payments — the highest share among new members\"\n\n data {\n series = \"Indirect subsidies\",\"Direct subsidies\"\n \"2000\" = 0,5\n \"2001\" = 0,33\n \"2002\" = 0,48\n \"2003\" = 0,69\n \"2004\" = 0,67\n \"2005\" = 0,87\n \"2006\" = 0,57\n \"2007\" = 59,250\n \"2008\" = 75,484\n \"2009\" = 97,415\n \"2010\" = 79,466\n \"2011\" = 94,458\n \"2012\" = 120,617\n \"2013\" = 132,852\n \"2014\" = 143,821\n \"2015\" = 213,677\n }\n\n highlight \"Direct subsidies\"\n }\n\n scene \"Bulgarian farms grew\" {\n title = \"Average farm size in Bulgaria quadrupled\"\n description = \"Average farm size in hectares\"\n type = line\n\n data {\n \"2005\" = 5\n \"2007\" = 6\n \"2010\" = 12\n \"2013\" = 18\n }\n }\n\n scene \"Production rose\" {\n title = \"Bulgarian farm production rose from 3 to 4 billion euros\"\n description = \"Total production of Bulgarian farms, million euros\"\n type = area\n\n data {\n \"2000\" = 2933\n \"2001\" = 3240\n \"2002\" = 3051\n \"2003\" = 2816\n \"2004\" = 3049\n \"2005\" = 3011\n \"2006\" = 3111\n \"2007\" = 3038\n \"2008\" = 4148\n \"2009\" = 3437\n \"2010\" = 3486\n \"2011\" = 4038\n \"2012\" = 4161\n \"2013\" = 4115\n \"2014\" = 4138\n \"2015\" = 3915\n }\n }\n\n scene \"Cash crops replaced vegetables\" {\n title = \"Cash crops replaced vegetables in Bulgaria\"\n description = \"Production of Bulgarian farms, million euros\"\n type = area-stacked\n\n data {\n series = \"Vegetables\",\"Cash crops\",\"Other production\"\n \"2000\" = 464,615,1854\n \"2001\" = 458,777,2005\n \"2002\" = 577,850,1624\n \"2003\" = 539,818,1459\n \"2004\" = 483,1103,1463\n \"2005\" = 492,994,1525\n \"2006\" = 510,1083,1518\n \"2007\" = 436,936,1666\n \"2008\" = 541,2045,1563\n \"2009\" = 243,1553,1641\n \"2010\" = 184,2173,1128\n \"2011\" = 120,2853,1065\n \"2012\" = 117,2900,1144\n \"2013\" = 139,2802,1174\n \"2014\" = 143,3082,914\n \"2015\" = 144,2986,785\n }\n\n highlight \"Cash crops\"\n }\n\n scene \"Vegetables collapsed\" {\n title = \"Vegetable production fell by a factor of three\"\n description = \"A traditional Bulgarian cultivation shrank as subsidies favoured large fields\"\n\n highlight \"Vegetables\"\n }\n\n scene \"Every vegetable declined\" {\n title = \"Bulgarian vegetable production collapsed across the board\"\n description = \"Production volume indexed to 2001 = 100\"\n type = line-multi\n lineSymbols = false\n\n data {\n series = \"Cabbages\",\"Tomatoes\",\"Watermelons\",\"Carrots\",\"Onions\",\"Garlic\",\"Strawberries\"\n \"2001\" = 100,100,100,100,100,100,100\n \"2002\" = 79,90,124,64,106,95,100\n \"2003\" = 100,157,177,142,118,98,72\n \"2004\" = 84,87,83,245,124,138,74\n \"2005\" = 50,46,62,30,40,93,42\n \"2006\" = 52,78,113,95,56,80,56\n \"2007\" = 36,49,64,74,29,30,38\n \"2008\" = 47,49,66,97,44,29,55\n \"2009\" = 28,38,74,105,23,39,55\n \"2010\" = 57,42,51,76,53,57,37\n \"2011\" = 32,38,56,86,47,43,45\n \"2012\" = 34,34,46,69,29,43,31\n \"2013\" = 33,43,53,39,36,40,24\n \"2014\" = 31,44,28,69,37,8,27\n \"2015\" = 31,45,50,57,25,18,32\n }\n }\n\n scene \"Jobs disappeared\" {\n title = \"Family farmers disappeared while salaried ag jobs held steady\"\n description = \"EU agricultural employment, thousands of full-time equivalents\"\n type = line-multi\n lineSymbols = false\n\n data {\n series = \"Salaried workers\",\"Non-salaried workers\"\n \"2000\" = 2678,12194\n \"2001\" = 2598,11586\n \"2002\" = 2658,10795\n \"2003\" = 2563,10609\n \"2004\" = 2560,9999\n \"2005\" = 2501,10047\n \"2006\" = 2499,9782\n \"2007\" = 2437,9231\n \"2008\" = 2416,8971\n \"2009\" = 2348,8672\n \"2010\" = 2335,7808\n \"2011\" = 2322,7551\n \"2012\" = 2325,7501\n \"2013\" = 2297,7425\n \"2014\" = 2366,7183\n \"2015\" = 2413,6928\n \"2016\" = 2457,6741\n }\n\n highlight \"Non-salaried workers\"\n }\n}\n", Yt = "chart bar-horizontal {\n title = \"China emits more CO₂ than the US and India combined\"\n description = \"Annual emissions in billion tonnes, 2023\"\n source = \"Our World in Data\"\n sourceUrl = \"https://ourworldindata.org/co2-emissions\"\n byline = \"Pierre Romera\"\n\n data {\n \"China\" = 12.17\n \"United States\" = 4.92\n \"India\" = 3.06\n \"Russia\" = 1.73\n \"Japan\" = 0.99\n \"Germany\" = 0.59\n }\n\n scene \"China spotlight\" {\n title = \"China alone emits more than the US and India together\"\n highlight \"China\"\n }\n\n scene \"India rising\" {\n title = \"India passed the EU to become the third-largest emitter\"\n highlight \"India\"\n }\n\n scene \"Japan declining\" {\n title = \"Japan's emissions have fallen since their 2013 peak\"\n highlight \"Japan\"\n }\n\n scene \"Per capita reframe\" {\n title = \"Per person, Gulf states dwarf the biggest emitters\"\n description = \"CO₂ emissions per capita, tonnes per person, 2023\"\n highlight \"Qatar\"\n data {\n \"Qatar\" = 40.13\n \"United Arab Emirates\" = 19.77\n \"United States\" = 14.32\n \"China\" = 8.56\n \"India\" = 2.13\n }\n }\n}\n", Xt = "chart bar-split {\n title = \"CDU/CSU led German polls at 29 % ahead of the 2021 election\"\n description = \"How Germany would vote in the September 2021 federal election, according to polling in the previous June\"\n source = \"FG Wahlen\"\n sourceUrl = \"https://www.forschungsgruppe.de\"\n note = \"Margin of error at 10%: +/- 2 percentage points; at 40%: +/- 3 percentage points\"\n\n data {\n series = \"Poll\",\"High\",\"Low\"\n \"CDU/CSU\" = 29,32,27\n \"Greens\" = 22,25,20\n \"SPD\" = 14,16,12\n \"AfD\" = 10,12,8\n \"FDP\" = 10,12,8\n \"Left\" = 7,9,5\n }\n}\n", Zt = "chart bar-grouped {\n title = \"Asia Pacific holds more renewable capacity than all other regions combined\"\n description = \"Installed capacity in gigawatts (GW), 2023\"\n source = \"IRENA\"\n sourceUrl = \"https://www.irena.org/Publications/2024/Mar/Renewable-capacity-statistics-2024\"\n colorPalette = \"Folklore\"\n\n data {\n series = \"Solar\",\"Wind\",\"Hydro\"\n \"Asia Pacific\" = 870,520,650\n \"Europe\" = 290,260,230\n \"North America\" = 150,170,200\n \"Latin America\" = 50,40,190\n \"Africa\" = 12,9,40\n }\n}\n";
777
+ var Sn = "chart bar-vertical {\n title = \"E is the most frequent letter in English\"\n description = \"How often each letter appears in typical English text\"\n byline = \"Pierre Romera\"\n source = \"Lewand, Cryptological Mathematics\"\n sourceUrl = \"https://en.wikipedia.org/wiki/Letter_frequency\"\n note = \"Based on analysis of 40,000 words from English prose\"\n colorPalette = \"London\"\n sort = descending\n\n highlight \"E\"\n\n data {\n \"E\" = 12.70\n \"T\" = 9.06\n \"A\" = 8.17\n \"O\" = 7.51\n \"I\" = 6.97\n \"N\" = 6.75\n \"S\" = 6.33\n \"H\" = 6.09\n \"R\" = 5.99\n \"D\" = 4.25\n }\n}\n", Cn = "chart bar-vertical {\n // the headline above the chart\n title = \"China emits more CO₂ than the US and India combined\"\n description = \"Annual emissions in billion tonnes, 2023\"\n source = \"Our World in Data\"\n sourceUrl = \"https://ourworldindata.org/co2-emissions\"\n\n // one row per country: \"label\" = value\n data {\n \"China\" = 12.17\n \"United States\" = 4.92\n \"India\" = 3.06\n \"Russia\" = 1.73\n \"Japan\" = 0.99\n \"Germany\" = 0.59\n }\n\n // highlight pops one bar in the accent color\n highlight \"China\"\n\n // an annotation points a callout at a single bar\n annotation \"India\" {\n text = \"Surpassed EU in 2023\"\n showLine = true\n anchorDirection = N\n textOffsetX = 66\n textOffsetY = -41\n lineStyle = curve-left\n showArrow = true\n lineTargetDistance = 26\n showCircle = false\n }\n}\n", wn = "chart bar-horizontal {\n title = \"Mandarin has nearly twice as many native speakers as Spanish\"\n description = \"Number of native speakers worldwide, in millions\"\n source = \"Ethnologue\"\n sourceUrl = \"https://ethnologue.com\"\n byline = \"Pierre Romera\"\n sort = descending\n\n highlight \"Mandarin\"\n\n data {\n \"Mandarin\" = 988\n \"Spanish\" = 487\n \"English\" = 372\n \"Hindi\" = 347\n \"Bengali\" = 232\n \"Portuguese\" = 252\n \"Russian\" = 133\n \"Japanese\" = 124\n }\n}\n", Tn = "chart line-multi {\n title = \"China now buys more electric cars than the rest of the world combined\"\n description = \"Electric car sales by region, millions per year\"\n source = \"IEA Global EV Outlook 2024\"\n sourceUrl = \"https://www.iea.org/reports/global-ev-outlook-2024\"\n colorPalette = \"Maya\"\n tooltips = true\n\n data {\n series = \"China\",\"Europe\",\"United States\",\"Rest of world\"\n \"2018\" = 1.1,0.4,0.36,0.1\n \"2020\" = 1.3,1.4,0.30,0.2\n \"2021\" = 3.3,2.3,0.63,0.4\n \"2022\" = 6.0,2.7,1.0,0.7\n \"2023\" = 8.1,3.2,1.4,1.0\n }\n}\n", En = "chart bar-multi {\n title = \"USA tops Paris 2024 with 126 medals across all categories\"\n description = \"2024 Paris Summer Games — top six nations\"\n source = \"Olympics.com\"\n sourceUrl = \"https://olympics.com\"\n colors = \"#eeca3b, #c0c0c0, #cd7f32\"\n sort = descending\n\n data {\n series = \"Gold\",\"Silver\",\"Bronze\"\n \"USA\" = 40,44,42\n \"China\" = 40,27,24\n \"Japan\" = 20,12,13\n \"Great Britain\" = 14,22,29\n \"Australia\" = 18,19,16\n \"France\" = 16,26,22\n }\n}\n", Dn = "chart line {\n title = \"2024 was the hottest year on record\"\n description = \"Deviation from the 1951–1980 average, in °C\"\n source = \"NASA GISS\"\n sourceUrl = \"https://data.giss.nasa.gov/gistemp/\"\n tooltips = true\n crosshair = false\n lineSymbols = true\n\n data {\n \"1980\" = 0.26\n \"1985\" = 0.12\n \"1990\" = 0.45\n \"1995\" = 0.45\n \"2000\" = 0.39\n \"2005\" = 0.68\n \"2010\" = 0.73\n \"2015\" = 0.9\n \"2020\" = 1.01\n \"2024\" = 1.28\n }\n\n annotation \"2015\" {\n text = \"2015 Paris Agreement to limit global warming to 1.5°C \"\n maxWidth = 224\n showLine = true\n lineStyle = curve-right\n showArrow = true\n showCircle = true\n }\n}\n", On = "chart line {\n title = \"Bitcoin surged past $90,000 in 2024\"\n description = \"USD, year-end closing price\"\n source = \"CoinGecko\"\n sourceUrl = \"https://www.coingecko.com\"\n colors = \"#f7931a\"\n lineSymbols = true\n lineSymbolShowOn = \"all\"\n lineSymbolShape = \"diamond\"\n verticalNumberFormat = \",.0f\"\n tooltips = true\n\n annotation \"2021\" {\n text = \"All-time high cycle\"\n textOffsetY = -12\n showArrow = true\n }\n\n data {\n \"2016\" = 963\n \"2017\" = 14156\n \"2018\" = 3742\n \"2019\" = 7194\n \"2020\" = 29080\n \"2021\" = 46306\n \"2022\" = 16547\n \"2023\" = 42258\n \"2024\" = 93429\n }\n}\n", kn = "chart line-multi {\n title = \"The income share of the top 1% has surged since 1980\"\n description = \"Pre-tax national income captured by the top 1%, percent\"\n source = \"World Inequality Database\"\n sourceUrl = \"https://wid.world\"\n colorPalette = \"Egypt\"\n tooltips = true\n lineSymbols = true\n lineSymbolShowOn = \"all\"\n\n data {\n series = \"United States\",\"India\",\"China\",\"France\"\n \"1980\" = 10.4,7.5,6.6,7.5\n \"1990\" = 14.7,10.7,8.3,9.0\n \"2000\" = 17.3,10.5,10.5,11.3\n \"2010\" = 17.9,16.4,15.2,11.0\n \"2021\" = 19.9,22.1,15.7,12.7\n }\n\n scene \"US doubles\" {\n title = \"The US top 1% nearly doubled its income share since 1980\"\n highlight \"United States\"\n }\n\n scene \"India overtakes\" {\n title = \"India is now the most unequal of these major economies\"\n highlight \"India\"\n }\n\n scene \"France's modest rise\" {\n title = \"France's top 1% rose far less than the US or India\"\n highlight \"France\"\n }\n}\n", An = "chart pie {\n title = \"Asia is home to nearly 60% of the world's population\"\n description = \"Estimated share, 2024\"\n source = \"United Nations\"\n sourceUrl = \"https://population.un.org\"\n colorPalette = \"Klimt\"\n legendPosition = \"right\"\n tooltips = true\n\n data {\n \"Asia\" = 58.9\n \"Africa\" = 18.6\n \"Europe\" = 9.1\n \"Latin America\" = 8.1\n \"North America\" = 4.7\n }\n}\n", jn = "chart bar-vertical {\n title = \"Brazil produces more coffee than the next three countries combined\"\n description = \"Million 60-kg bags, 2023/24 crop year\"\n source = \"USDA Foreign Agricultural Service\"\n sourceUrl = \"https://www.fas.usda.gov/data/coffee-world-markets-and-trade\"\n colorPalette = \"Harvey\"\n\n data {\n \"Brazil\" = 66.4\n \"Vietnam\" = 27.5\n \"Colombia\" = 12.76\n \"Ethiopia\" = 9.13\n \"Indonesia\" = 7.65\n \"Honduras\" = 5.5\n }\n\n highlight \"Brazil\"\n\n transform sort {\n column = \"value\"\n direction = descending\n }\n}\n", Mn = "chart donut {\n title = \"The richest 1% own more wealth than the entire bottom 90% combined\"\n description = \"Share of global wealth by group, 2021\"\n source = \"World Inequality Report 2022\"\n sourceUrl = \"https://wir2022.wid.world\"\n colorPalette = \"Imperator\"\n legendPosition = \"right\"\n displayAsPercentage = true\n tooltips = true\n\n data {\n \"Top 1%\" = 38\n \"Next 9%\" = 38\n \"Middle 40%\" = 22\n \"Bottom 50%\" = 2\n }\n\n scene \"Top 1% spotlight\" {\n title = \"The top 1% hold 38% of all global wealth\"\n description = \"Share of global wealth by group, 2021\"\n highlight \"Top 1%\"\n }\n\n scene \"Bottom half\" {\n title = \"The bottom half of humanity owns just 2%\"\n description = \"Share of global wealth by group, 2021\"\n highlight \"Bottom 50%\"\n }\n\n scene \"Income tells a softer story\" {\n title = \"Income is concentrated too — but less than wealth\"\n description = \"Share of global income by the same groups, 2021\"\n highlight \"Top 1%\"\n data {\n \"Top 1%\" = 19\n \"Next 9%\" = 33\n \"Middle 40%\" = 39\n \"Bottom 50%\" = 9\n }\n }\n}\n", Nn = "chart area {\n title = \"The US national debt has more than tripled since 2008\"\n description = \"Total federal debt outstanding, trillions of dollars\"\n source = \"U.S. Treasury, Fiscal Data\"\n sourceUrl = \"https://fiscaldata.treasury.gov\"\n\n annotation \"2008\" {\n text = \"Financial crisis\"\n showArrow = true\n textOffsetY = -14\n }\n\n data {\n \"2000\" = 5.7\n \"2004\" = 7.4\n \"2008\" = 10.0\n \"2012\" = 16.1\n \"2016\" = 19.6\n \"2020\" = 26.9\n \"2024\" = 35.5\n }\n}\n", Pn = "chart area-stacked {\n title = \"Renewables' share of global energy has more than doubled since 2000\"\n description = \"Share of global primary energy by source, 2000–2023\"\n source = \"Our World in Data\"\n sourceUrl = \"https://ourworldindata.org/energy-mix\"\n stackPercent = true\n areaSortMode = descending\n\n data {\n series = \"Coal\",\"Oil\",\"Gas\",\"Renewables\"\n \"2000\" = 27456,43017,23994,2997\n \"2005\" = 36201,47017,27439,3510\n \"2010\" = 42016,48193,31593,4868\n \"2015\" = 43695,51294,34780,6400\n \"2020\" = 42316,49101,38704,8569\n \"2023\" = 45319,54839,40151,10325\n }\n}\n", Fn = "chart column-stacked {\n title = \"Natural gas and renewables pushed coal off the US power grid\"\n description = \"Share of US electricity generation by source, percent\"\n source = \"U.S. Energy Information Administration\"\n sourceUrl = \"https://www.eia.gov/electricity\"\n stackMode = \"percent\"\n\n data {\n series = \"Coal\",\"Natural gas\",\"Nuclear\",\"Renewables\"\n \"2010\" = 45,24,20,10\n \"2015\" = 33,33,20,13\n \"2020\" = 19,39,20,20\n \"2023\" = 16,43,19,21\n }\n}\n", In = "chart bar-stacked {\n title = \"India has far more children than China, and a workforce nearly as large\"\n description = \"Millions of people, 2023\"\n source = \"UN Population Division\"\n sourceUrl = \"https://population.un.org\"\n colorPalette = \"London\"\n\n data {\n series = \"0-14\",\"15-64\",\"65+\"\n \"China\" = 232,988,200\n \"India\" = 354,978,97\n \"USA\" = 58,216,59\n \"Indonesia\" = 67,189,21\n \"Brazil\" = 43,148,24\n }\n}\n", Ln = "chart area-stacked {\n title = \"EU subsidies to new members surged after enlargement\"\n description = \"Agricultural subsidies to post-socialist EU members, million euros\"\n source = \"Eurostat\"\n sourceUrl = \"https://ec.europa.eu/eurostat\"\n colorPalette = \"Enara\"\n interpolation = \"linear\"\n heightMode = \"aspect-ratio\"\n aspectRatio = \"1:1\"\n\n data {\n series = \"Indirect subsidies\",\"Direct subsidies\"\n \"2000\" = 370,800\n \"2001\" = 445,896\n \"2002\" = 567,816\n \"2003\" = 641,950\n \"2004\" = 1908,2434\n \"2005\" = 2234,3509\n \"2006\" = 2576,4356\n \"2007\" = 2467,5429\n \"2008\" = 2672,6655\n \"2009\" = 2474,7195\n \"2010\" = 2117,8207\n \"2011\" = 1863,9230\n \"2012\" = 1528,9191\n \"2013\" = 1251,10252\n \"2014\" = 1132,10987\n \"2015\" = 1687,10145\n }\n\n scene \"Indirect subsidies shrank\" {\n title = \"Indirect subsidies were cut under WTO pressure\"\n description = \"Subsidies tied to specific crops fell foul of World Trade Organization rules\"\n\n highlight \"Indirect subsidies\"\n }\n\n scene \"Direct subsidies dominate\" {\n title = \"Direct per-hectare payments now dominate\"\n description = \"The larger the fields, the more money farmers receive\"\n\n highlight \"Direct subsidies\"\n }\n\n scene \"Bulgaria: subsidies explode\" {\n title = \"Bulgarian farmers received almost nothing before 2007 accession\"\n description = \"More than three-quarters of Bulgarian subsidies are direct payments — the highest share among new members\"\n\n data {\n series = \"Indirect subsidies\",\"Direct subsidies\"\n \"2000\" = 0,5\n \"2001\" = 0,33\n \"2002\" = 0,48\n \"2003\" = 0,69\n \"2004\" = 0,67\n \"2005\" = 0,87\n \"2006\" = 0,57\n \"2007\" = 59,250\n \"2008\" = 75,484\n \"2009\" = 97,415\n \"2010\" = 79,466\n \"2011\" = 94,458\n \"2012\" = 120,617\n \"2013\" = 132,852\n \"2014\" = 143,821\n \"2015\" = 213,677\n }\n\n highlight \"Direct subsidies\"\n }\n\n scene \"Bulgarian farms grew\" {\n title = \"Average farm size in Bulgaria quadrupled\"\n description = \"Average farm size in hectares\"\n type = line\n\n data {\n \"2005\" = 5\n \"2007\" = 6\n \"2010\" = 12\n \"2013\" = 18\n }\n }\n\n scene \"Production rose\" {\n title = \"Bulgarian farm production rose from 3 to 4 billion euros\"\n description = \"Total production of Bulgarian farms, million euros\"\n type = area\n\n data {\n \"2000\" = 2933\n \"2001\" = 3240\n \"2002\" = 3051\n \"2003\" = 2816\n \"2004\" = 3049\n \"2005\" = 3011\n \"2006\" = 3111\n \"2007\" = 3038\n \"2008\" = 4148\n \"2009\" = 3437\n \"2010\" = 3486\n \"2011\" = 4038\n \"2012\" = 4161\n \"2013\" = 4115\n \"2014\" = 4138\n \"2015\" = 3915\n }\n }\n\n scene \"Cash crops replaced vegetables\" {\n title = \"Cash crops replaced vegetables in Bulgaria\"\n description = \"Production of Bulgarian farms, million euros\"\n type = area-stacked\n\n data {\n series = \"Vegetables\",\"Cash crops\",\"Other production\"\n \"2000\" = 464,615,1854\n \"2001\" = 458,777,2005\n \"2002\" = 577,850,1624\n \"2003\" = 539,818,1459\n \"2004\" = 483,1103,1463\n \"2005\" = 492,994,1525\n \"2006\" = 510,1083,1518\n \"2007\" = 436,936,1666\n \"2008\" = 541,2045,1563\n \"2009\" = 243,1553,1641\n \"2010\" = 184,2173,1128\n \"2011\" = 120,2853,1065\n \"2012\" = 117,2900,1144\n \"2013\" = 139,2802,1174\n \"2014\" = 143,3082,914\n \"2015\" = 144,2986,785\n }\n\n highlight \"Cash crops\"\n }\n\n scene \"Vegetables collapsed\" {\n title = \"Vegetable production fell by a factor of three\"\n description = \"A traditional Bulgarian cultivation shrank as subsidies favoured large fields\"\n\n highlight \"Vegetables\"\n }\n\n scene \"Every vegetable declined\" {\n title = \"Bulgarian vegetable production collapsed across the board\"\n description = \"Production volume indexed to 2001 = 100\"\n type = line-multi\n lineSymbols = false\n\n data {\n series = \"Cabbages\",\"Tomatoes\",\"Watermelons\",\"Carrots\",\"Onions\",\"Garlic\",\"Strawberries\"\n \"2001\" = 100,100,100,100,100,100,100\n \"2002\" = 79,90,124,64,106,95,100\n \"2003\" = 100,157,177,142,118,98,72\n \"2004\" = 84,87,83,245,124,138,74\n \"2005\" = 50,46,62,30,40,93,42\n \"2006\" = 52,78,113,95,56,80,56\n \"2007\" = 36,49,64,74,29,30,38\n \"2008\" = 47,49,66,97,44,29,55\n \"2009\" = 28,38,74,105,23,39,55\n \"2010\" = 57,42,51,76,53,57,37\n \"2011\" = 32,38,56,86,47,43,45\n \"2012\" = 34,34,46,69,29,43,31\n \"2013\" = 33,43,53,39,36,40,24\n \"2014\" = 31,44,28,69,37,8,27\n \"2015\" = 31,45,50,57,25,18,32\n }\n }\n\n scene \"Jobs disappeared\" {\n title = \"Family farmers disappeared while salaried ag jobs held steady\"\n description = \"EU agricultural employment, thousands of full-time equivalents\"\n type = line-multi\n lineSymbols = false\n\n data {\n series = \"Salaried workers\",\"Non-salaried workers\"\n \"2000\" = 2678,12194\n \"2001\" = 2598,11586\n \"2002\" = 2658,10795\n \"2003\" = 2563,10609\n \"2004\" = 2560,9999\n \"2005\" = 2501,10047\n \"2006\" = 2499,9782\n \"2007\" = 2437,9231\n \"2008\" = 2416,8971\n \"2009\" = 2348,8672\n \"2010\" = 2335,7808\n \"2011\" = 2322,7551\n \"2012\" = 2325,7501\n \"2013\" = 2297,7425\n \"2014\" = 2366,7183\n \"2015\" = 2413,6928\n \"2016\" = 2457,6741\n }\n\n highlight \"Non-salaried workers\"\n }\n}\n", Rn = "chart bar-horizontal {\n title = \"China emits more CO₂ than the US and India combined\"\n description = \"Annual emissions in billion tonnes, 2023\"\n source = \"Our World in Data\"\n sourceUrl = \"https://ourworldindata.org/co2-emissions\"\n byline = \"Pierre Romera\"\n\n data {\n \"China\" = 12.17\n \"United States\" = 4.92\n \"India\" = 3.06\n \"Russia\" = 1.73\n \"Japan\" = 0.99\n \"Germany\" = 0.59\n }\n\n scene \"China spotlight\" {\n title = \"China alone emits more than the US and India together\"\n highlight \"China\"\n }\n\n scene \"India rising\" {\n title = \"India passed the EU to become the third-largest emitter\"\n highlight \"India\"\n }\n\n scene \"Japan declining\" {\n title = \"Japan's emissions have fallen since their 2013 peak\"\n highlight \"Japan\"\n }\n\n scene \"Per capita reframe\" {\n title = \"Per person, Gulf states dwarf the biggest emitters\"\n description = \"CO₂ emissions per capita, tonnes per person, 2023\"\n highlight \"Qatar\"\n data {\n \"Qatar\" = 40.13\n \"United Arab Emirates\" = 19.77\n \"United States\" = 14.32\n \"China\" = 8.56\n \"India\" = 2.13\n }\n }\n}\n", zn = "chart bar-split {\n title = \"CDU/CSU led German polls at 29 % ahead of the 2021 election\"\n description = \"How Germany would vote in the September 2021 federal election, according to polling in the previous June\"\n source = \"FG Wahlen\"\n sourceUrl = \"https://www.forschungsgruppe.de\"\n note = \"Margin of error at 10%: +/- 2 percentage points; at 40%: +/- 3 percentage points\"\n\n data {\n series = \"Poll\",\"High\",\"Low\"\n \"CDU/CSU\" = 29,32,27\n \"Greens\" = 22,25,20\n \"SPD\" = 14,16,12\n \"AfD\" = 10,12,8\n \"FDP\" = 10,12,8\n \"Left\" = 7,9,5\n }\n}\n", Bn = "chart bar-grouped {\n title = \"Asia Pacific holds more renewable capacity than all other regions combined\"\n description = \"Installed capacity in gigawatts (GW), 2023\"\n source = \"IRENA\"\n sourceUrl = \"https://www.irena.org/Publications/2024/Mar/Renewable-capacity-statistics-2024\"\n colorPalette = \"Folklore\"\n\n data {\n series = \"Solar\",\"Wind\",\"Hydro\"\n \"Asia Pacific\" = 870,520,650\n \"Europe\" = 290,260,230\n \"North America\" = 150,170,200\n \"Latin America\" = 50,40,190\n \"Africa\" = 12,9,40\n }\n}\n";
615
778
  //#endregion
616
779
  //#region src/samples.ts
617
- function Y(e, t) {
780
+ function Vn(e, t) {
618
781
  let n = e.properties.find((e) => e.key === t);
619
782
  return n ? String(n.value) : "";
620
783
  }
621
- function Qt(e) {
784
+ function Hn(e) {
622
785
  if (!e.data) return "";
623
786
  let t = e.data.entries, n = t.find((e) => e.key === "series" && !e.quotedKey);
624
787
  return n ? [["category", ...String(n.value).split(",")].join(" "), ...t.filter((e) => !(e.key === "series" && !e.quotedKey)).map((e) => {
@@ -626,70 +789,70 @@ function Qt(e) {
626
789
  return [e.key, ...t].join(" ");
627
790
  })].join("\n") : [["label", "value"].join(" "), ...t.map((e) => [e.key, String(e.value)].join(" "))].join("\n");
628
791
  }
629
- function $t(e) {
792
+ function Un(e) {
630
793
  if (!e.data) return "";
631
794
  let t = e.data.entries, n = t.find((e) => e.key === "series" && !e.quotedKey);
632
795
  return n ? [`series = "${String(n.value)}"`, ...t.filter((e) => !(e.key === "series" && !e.quotedKey)).map((e) => `"${e.key}" = "${String(e.value)}"`)].join("\n") : t.map((e) => `"${e.key}" = ${String(e.value)}`).join("\n");
633
796
  }
634
- function X(e, t) {
635
- let n = g(t);
797
+ function q(e, t) {
798
+ let n = v(t);
636
799
  return {
637
800
  id: e,
638
- title: Y(n, "title"),
639
- description: Y(n, "description"),
801
+ title: Vn(n, "title"),
802
+ description: Vn(n, "description"),
640
803
  chartType: n.chartType,
641
- tsvData: Qt(n),
642
- serializedData: $t(n),
804
+ tsvData: Hn(n),
805
+ serializedData: Un(n),
643
806
  dsl: t
644
807
  };
645
808
  }
646
- var en = [
647
- X("letter-frequency", Nt),
648
- X("co2-emissions", Pt),
649
- X("coffee-production", Ht),
650
- X("spoken-languages", Ft),
651
- X("quarterly-revenue", It),
652
- X("medal-count", Lt),
653
- X("temperature-anomaly", Rt),
654
- X("bitcoin-price", zt),
655
- X("unemployment-rates", Bt),
656
- X("browser-market", Ut),
657
- X("world-population", Vt),
658
- X("stock-price-area", Wt),
659
- X("energy-mix-stacked-area", Gt),
660
- X("quarterly-stacked-columns", Kt),
661
- X("population-stacked-bar", qt),
662
- X("election-polls", Xt),
663
- X("renewable-capacity", Zt),
664
- X("farm-compass", Jt),
665
- X("co2-emissions-story", Yt)
666
- ], Z = class extends Error {
809
+ var Wn = [
810
+ q("letter-frequency", Sn),
811
+ q("co2-emissions", Cn),
812
+ q("coffee-production", jn),
813
+ q("spoken-languages", wn),
814
+ q("quarterly-revenue", Tn),
815
+ q("medal-count", En),
816
+ q("temperature-anomaly", Dn),
817
+ q("bitcoin-price", On),
818
+ q("unemployment-rates", kn),
819
+ q("browser-market", Mn),
820
+ q("world-population", An),
821
+ q("stock-price-area", Nn),
822
+ q("energy-mix-stacked-area", Pn),
823
+ q("quarterly-stacked-columns", Fn),
824
+ q("population-stacked-bar", In),
825
+ q("election-polls", zn),
826
+ q("renewable-capacity", Bn),
827
+ q("farm-compass", Ln),
828
+ q("co2-emissions-story", Rn)
829
+ ], Gn = class extends Error {
667
830
  constructor(e, t) {
668
831
  super(e, t), this.name = "ChartParseError";
669
832
  }
670
- }, Q = class extends Error {
833
+ }, Kn = class extends Error {
671
834
  constructor(e = "PNG export is only available in Node. Use toSvg() in the browser.") {
672
835
  super(e), this.name = "PngBrowserUnsupportedError";
673
836
  }
674
- }, tn = class extends Error {
837
+ }, qn = class extends Error {
675
838
  constructor(e) {
676
839
  super(e), this.name = "MissingNodeRenderDepsError";
677
840
  }
678
841
  };
679
842
  //#endregion
680
843
  //#region src/render/backends/dom-backend.ts
681
- function nn() {
844
+ function Jn() {
682
845
  return {
683
846
  kind: "dom",
684
847
  createContainer(e, t) {
685
848
  let n = document.createElement("div");
686
- return n.style.cssText = `position:absolute;left:-99999px;top:0;width:${e}px;height:${t}px`, document.body.appendChild(n), {
849
+ return n.style.cssText = `position:absolute;left:-99999px;top:0;width:${e}px;height:${t}px`, n.dataset.bcContentWidth = String(e), n.dataset.bcContentHeight = String(t), document.body.appendChild(n), {
687
850
  container: n,
688
851
  cleanup: () => n.remove()
689
852
  };
690
853
  },
691
854
  renderToContainer(e, t, n) {
692
- _(e, t, {
855
+ nt(e, t, {
693
856
  sceneIndex: n.sceneIndex,
694
857
  thumbnail: n.thumbnail ?? !1,
695
858
  transition: !1,
@@ -708,78 +871,234 @@ function nn() {
708
871
  throw Error("dom-backend: renderToContainer produced no frame");
709
872
  },
710
873
  rasterizePng() {
711
- return Promise.reject(new Q());
874
+ return Promise.reject(new Kn());
712
875
  }
713
876
  };
714
877
  }
715
878
  //#endregion
879
+ //#region src/render/frame-svg.ts
880
+ var Yn = {
881
+ background: "#ffffff",
882
+ color: "#333333"
883
+ }, Xn = {
884
+ background: "#1c1c1c",
885
+ color: "rgba(255, 255, 255, 0.9)"
886
+ }, Zn = "sans-serif", Qn = 20, $n = 14, J = 12, Y = 1.25, er = 4, tr = 8, nr = 12, rr = 40, ir = "16px", ar = "Blueprint Chart", or = "Source: ", sr = " · ", cr = .6;
887
+ function lr(e) {
888
+ return e === "dark" ? { ...Xn } : { ...Yn };
889
+ }
890
+ function ur() {
891
+ if (typeof document > "u") return null;
892
+ try {
893
+ return document.createElement("canvas").getContext("2d");
894
+ } catch {
895
+ return null;
896
+ }
897
+ }
898
+ function dr() {
899
+ let e = ur();
900
+ return (t, n, r) => {
901
+ let i = t.length * n * cr;
902
+ return e ? (e.font = `${r ? "bold " : ""}${n}px ${Zn}`, Math.max(e.measureText(t).width, i)) : i;
903
+ };
904
+ }
905
+ function X(e, t, n, r, i) {
906
+ let a = [];
907
+ for (let o of e.split("\n")) {
908
+ let e = o.split(/\s+/).filter(Boolean);
909
+ if (e.length === 0) continue;
910
+ let s = e[0];
911
+ for (let o of e.slice(1)) {
912
+ let e = `${s} ${o}`;
913
+ i(e, n, r) <= t ? s = e : (a.push(s), s = o);
914
+ }
915
+ a.push(s);
916
+ }
917
+ return a;
918
+ }
919
+ function Z(e, t, n) {
920
+ let r = n.top;
921
+ for (let i of t) e.push({
922
+ text: i,
923
+ x: n.x,
924
+ y: r + n.fontSize,
925
+ fontSize: n.fontSize,
926
+ fontWeight: n.fontWeight,
927
+ fontStyle: n.fontStyle,
928
+ fill: n.fill,
929
+ anchor: n.anchor
930
+ }), r += n.fontSize * Y;
931
+ return r;
932
+ }
933
+ function fr(e) {
934
+ let t = parseFloat(e) || 0;
935
+ return /r?em$/.test(e) ? t * 16 : t;
936
+ }
937
+ function pr(e) {
938
+ let t = e.frame ?? {}, n = lr(e.theme), [r, i, a, o] = Ne(t.padding ?? ir).map(fr), s = Math.max(e.width - o - i, 1), c = dr(), l = [], u = r;
939
+ t.title && (u = Z(l, X(t.title, s, Qn, !0, c), {
940
+ x: o,
941
+ top: u,
942
+ fontSize: Qn,
943
+ fontWeight: "bold",
944
+ fill: n.color
945
+ })), t.description && (u = Z(l, X(t.description, s, $n, !1, c), {
946
+ x: o,
947
+ top: t.title ? u + er : u,
948
+ fontSize: $n,
949
+ fill: n.color
950
+ }));
951
+ let d = u, f = t.note ? X(t.note, s, J, !1, c) : [], p = c(ar, J, !1), m = [t.byline, t.source ? or + t.source : ""].filter(Boolean).join(sr), h = m ? X(m, Math.max(s - p - nr, 1), J, !1, c) : [], ee = Math.max(h.length, 1), te = f.length * J * Y + tr + ee * J * Y + a, g = Math.max(e.height - d - te, rr), _ = d + g;
952
+ return _ = Z(l, f, {
953
+ x: o,
954
+ top: _,
955
+ fontSize: J,
956
+ fontStyle: "italic",
957
+ fill: n.color
958
+ }) + tr, Z(l, h, {
959
+ x: o,
960
+ top: _,
961
+ fontSize: J,
962
+ fill: n.color
963
+ }), Z(l, [ar], {
964
+ x: e.width - i,
965
+ top: _,
966
+ fontSize: J,
967
+ fontWeight: "600",
968
+ fill: n.color,
969
+ anchor: "end"
970
+ }), {
971
+ width: e.width,
972
+ height: e.height,
973
+ plot: {
974
+ x: o,
975
+ y: d,
976
+ width: s,
977
+ height: g
978
+ },
979
+ blocks: l,
980
+ background: t.transparentBackground ? null : n.background,
981
+ color: n.color,
982
+ fontFamily: Zn
983
+ };
984
+ }
985
+ function Q(e) {
986
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
987
+ }
988
+ function $(e) {
989
+ return Q(e).replace(/"/g, "&quot;");
990
+ }
991
+ function mr(e, t) {
992
+ return [
993
+ `<text x="${e.x}" y="${e.y}" font-size="${e.fontSize}px"`,
994
+ e.fontFamily ? ` font-family="${$(e.fontFamily)}"` : "",
995
+ e.fontWeight ? ` font-weight="${$(e.fontWeight)}"` : "",
996
+ e.fontStyle ? ` font-style="${$(e.fontStyle)}"` : "",
997
+ e.anchor ? ` text-anchor="${e.anchor}"` : "",
998
+ ` fill="${$(e.fill ?? t.color)}">`,
999
+ Q(e.text),
1000
+ "</text>"
1001
+ ].join("");
1002
+ }
1003
+ function hr(e, t, n) {
1004
+ return [
1005
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${e.width}" height="${e.height}"`,
1006
+ ` viewBox="0 0 ${e.width} ${e.height}" role="img" aria-label="${$(n.label)}"`,
1007
+ ` font-family="${$(e.fontFamily)}" color="${$(e.color)}">`,
1008
+ `<title>${Q(n.label)}</title>`,
1009
+ `<desc>${Q(n.description)}</desc>`,
1010
+ e.background ? `<rect width="100%" height="100%" fill="${$(e.background)}"></rect>` : "",
1011
+ ...e.blocks.map((t) => mr(t, e)),
1012
+ `<g transform="translate(${e.plot.x},${e.plot.y})">${t}</g>`,
1013
+ "</svg>"
1014
+ ].join("");
1015
+ }
1016
+ //#endregion
716
1017
  //#region src/render/public-render.ts
717
- var rn = 640, an = 400;
718
- function $() {
1018
+ var gr = 640, _r = 400;
1019
+ function vr() {
719
1020
  return typeof document < "u" && typeof document.createElement == "function";
720
1021
  }
721
- async function on() {
722
- return $() ? nn() : (await import("@blueprint-chart/lib/internal/node-backend")).createNodeBackend();
1022
+ async function yr() {
1023
+ return vr() ? Jn() : (await import("@blueprint-chart/lib/internal/node-backend")).createNodeBackend();
723
1024
  }
724
- async function sn(e, t = {}) {
1025
+ async function br(e, t = {}) {
725
1026
  let n;
726
1027
  try {
727
- n = m(g(e));
1028
+ n = b(v(e));
728
1029
  } catch (e) {
729
- throw new Z(e instanceof Error ? e.message : String(e), { cause: e });
1030
+ throw new Gn(e instanceof Error ? e.message : String(e), { cause: e });
730
1031
  }
731
- let r = await on(), i = t.frame ?? !0, a = {
1032
+ let r = await yr(), i = t.frame ?? !0, a = {
732
1033
  sceneIndex: t.scene,
733
- width: t.width ?? rn,
734
- height: t.height ?? an
1034
+ width: t.width ?? gr,
1035
+ height: t.height ?? _r
735
1036
  };
736
- function o(e) {
1037
+ function o(e, t) {
1038
+ let { background: n, color: r } = lr(t);
1039
+ e.style.backgroundColor = n, e.style.setProperty("--bc-text-color", r);
1040
+ }
1041
+ function s(e, i) {
737
1042
  r.renderToContainer(e, n, {
738
1043
  sceneIndex: a.sceneIndex,
739
- thumbnail: !i,
1044
+ thumbnail: i,
740
1045
  theme: t.theme
741
1046
  });
742
1047
  }
743
- let s = {
744
- async toSvg(e = {}) {
745
- let { container: t, cleanup: n } = r.createContainer(e.width ?? a.width, e.height ?? a.height);
1048
+ function c(e) {
1049
+ let c = e.width ?? a.width, l = e.height ?? a.height, u = S(n, a.sceneIndex), d = t.theme ?? u.theme;
1050
+ if (!i) {
1051
+ let { container: e, cleanup: t } = r.createContainer(c, l);
746
1052
  try {
747
- return o(t), r.serializeSvg(t);
1053
+ return o(e, d), s(e, !0), r.serializeSvg(e);
748
1054
  } finally {
749
- n();
1055
+ t();
750
1056
  }
1057
+ }
1058
+ let f = pr({
1059
+ width: c,
1060
+ height: l,
1061
+ frame: u.frame,
1062
+ theme: d
1063
+ }), { container: p, cleanup: m } = r.createContainer(f.plot.width, f.plot.height);
1064
+ try {
1065
+ o(p, d), s(p, !0);
1066
+ let e = ut(u.chartType, u.frame, u.data);
1067
+ return hr(f, r.serializeSvg(p), e);
1068
+ } finally {
1069
+ m();
1070
+ }
1071
+ }
1072
+ let l = {
1073
+ async toSvg(e = {}) {
1074
+ return c(e);
751
1075
  },
752
1076
  async toHtml(e = {}) {
753
1077
  let { container: t, cleanup: n } = r.createContainer(e.width ?? a.width, e.height ?? a.height);
754
1078
  try {
755
- return o(t), r.serializeFrame(t);
1079
+ return s(t, !i), r.serializeFrame(t);
756
1080
  } finally {
757
1081
  n();
758
1082
  }
759
1083
  },
760
1084
  async toPng(e = {}) {
761
- let { container: t, cleanup: n } = r.createContainer(e.width ?? a.width, e.height ?? a.height), i;
762
- try {
763
- o(t), i = r.serializeSvg(t);
764
- } finally {
765
- n();
766
- }
767
- return r.rasterizePng(i, {
1085
+ let t = c(e);
1086
+ return r.rasterizePng(t, {
768
1087
  width: e.width ?? a.width,
769
1088
  height: e.height ?? a.height
770
1089
  });
771
1090
  },
772
1091
  mount(e) {
773
- if (r.kind !== "dom") return console.warn("Blueprint Chart: mount() is a no-op outside a browser environment."), s;
1092
+ if (r.kind !== "dom") return console.warn("Blueprint Chart: mount() is a no-op outside a browser environment."), l;
774
1093
  let t = typeof e == "string" ? document.querySelector(e) : e;
775
1094
  if (!t) throw Error(`Blueprint Chart: mount target "${String(e)}" not found`);
776
- return o(t), s;
1095
+ return s(t, !i), l;
777
1096
  },
778
1097
  scene(e) {
779
- return a.sceneIndex = e, s;
1098
+ return a.sceneIndex = e, l;
780
1099
  }
781
1100
  };
782
- return s;
1101
+ return l;
783
1102
  }
784
1103
  //#endregion
785
- export { p as ANNOTATION_KIND_KEYWORD, ge as Anchor, d as AnnotationKind, e as AnnotationLineStyle, De as AxisDirection, Fe as BC_TRANSITION_NAME, y as ChartOptionType, Z as ChartParseError, ze as ChartType, Ge as CompassDirection, Pe as CrosshairDirection, be as CrosshairStyle, ae as DEFAULT_BAR_GAP, Ve as DirectLabelMode, qe as DslNodeType, we as FrameSizing, h as GridStyle, Xe as Interpolation, Ee as LabelPosition, ke as LabelRotation, He as LegendPosition, Re as LineStyle, tn as MissingNodeRenderDepsError, Ne as Orientation, Q as PngBrowserUnsupportedError, je as RangeAnchor, ve as ScaleType, Ie as SceneTransition, Qe as SortDirection, rt as SortMode, Se as StackMode, tt as StrokeStyle, le as SymbolShape, i as SymbolShowOn, et as SymbolStyle, de as TickPosition, s as ValueLabelPosition, l as adjustColorsForBackground, m as astToDefinition, _e as buildChartOptions, at as buildSrcdoc, mt as checkCvdColors, S as classifyIntent, n as commitFadeOut, xt as compactSerialize, bt as compactSerializeDeep, ye as convertAnnotations, Be as convertAreaFills, Ke as convertColorizes, Ce as convertHighlights, Le as convertSeriesOverrides, me as createCanvas, dt as createCvdSvgFilter, he as createFrame, Ye as dataEntriesToString, Te as extractChartTypeOptions, Oe as extractSceneOverrides, pe as fadeIn, a as featureJoin, ie as getCachedChart, xe as getChart, b as getChartOptions, Me as getChartTypeDefaults, D as getCvdFilterId, t as getSceneTransition, ee as getTransitionDuration, $e as isSeriesHidden, f as listCharts, c as listPalettes, g as parse, Ze as parseData, v as propertyMap, lt as recommendCharts, r as registerChart, sn as render, Je as renderBpc, _ as renderChart, ce as renderHorizontalAxis, re as renderLegend, it as renderVerticalAxis, ne as resolveBackgroundColor, se as resolveBarGapPadding, Ae as resolveChartTypeOptions, te as resolvePalette, We as resolveScene, ue as resolveSeriesColor, o as resolveSeriesInterpolation, en as samples, _t as serialize, T as shapeOf, k as simulateCvdColor, fe as snapshotForFadeOut, oe as snapshotLiveAttrs, nt as stripDigitGroupSpaces, At as validateChart, Ue as wcagContrastRatio, u as wcagLevel };
1104
+ export { C as ANNOTATION_KIND_KEYWORD, wt as Anchor, x as AnnotationKind, St as AnnotationLineStyle, ve as AxisDirection, me as BC_TRANSITION_NAME, o as ChartOptionType, Gn as ChartParseError, bt as ChartType, be as CompassDirection, u as CrosshairDirection, c as CrosshairStyle, tt as DEFAULT_BAR_GAP, fe as DirectLabelMode, Ze as DslNodeType, n as FilterCondition, Ye as FrameSizing, ce as GridStyle, ue as Interpolation, pe as LabelPosition, f as LabelRotation, g as LegendPosition, oe as LineStyle, qn as MissingNodeRenderDepsError, vt as NULL_VALUE, ge as Orientation, Tt as ParseOperationCategory, Kn as PngBrowserUnsupportedError, i as RangeAnchor, Ce as ScaleType, Ee as SceneTransition, ee as SortDirection, xe as SortMode, Te as StackMode, m as StrokeStyle, ie as SymbolShape, lt as SymbolShowOn, ne as SymbolStyle, it as TRANSFORM_TYPES, ke as TickPosition, De as TransformType, je as ValueLabelPosition, _t as adjustColorsForBackground, ft as applyTransformNodes, Ie as applyTransformNodesToChartData, Qe as applyTransformSteps, b as astToDefinition, ae as buildChartOptions, hr as buildFrameSvg, Et as buildSrcdoc, Re as chartDataToTable, Vt as checkCvdColors, E as classifyIntent, Ve as cleanNumericValue, Pe as commitFadeOut, Zt as compactSerialize, Xt as compactSerializeDeep, yt as convertAnnotations, ye as convertAreaFills, l as convertColorizes, s as convertHighlights, de as convertSeriesOverrides, $e as createCanvas, Lt as createCvdSvgFilter, We as createFrame, Xe as dataEntriesToString, ot as detectColumnTypes, t as extractChartTypeOptions, Je as extractSceneOverrides, at as fadeIn, _ as featureJoin, e as getCachedChart, Se as getChart, h as getChartOptions, d as getChartTypeDefaults, It as getCvdFilterId, Fe as getOutputType, Ae as getSceneTransition, pt as getTransitionDuration, et as isDateValue, Ge as isNumberValue, p as isSeriesHidden, xt as isTypeCompatible, y as listCharts, Be as listPalettes, Nt as listThemes, v as parse, Ue as parseBpcData, he as parseData, _e as parseOperationMap, a as parseOperations, se as propertyMap, w as quoteDslString, jt as recommendCharts, we as registerChart, br as render, mt as renderBpc, nt as renderChart, dt as renderHorizontalAxis, rt as renderLegend, qe as renderVerticalAxis, ze as resolveBackgroundColor, Ke as resolveBarGapPadding, te as resolveChartTypeOptions, ht as resolvePalette, S as resolveScene, re as resolveSeriesColor, ct as resolveSeriesInterpolation, Wn as samples, Kt as serialize, Me as serializeTableData, kt as shapeOf, zt as simulateCvdColor, Le as snapshotForFadeOut, Oe as snapshotLiveAttrs, r as stripDigitGroupSpaces, le as toBool, gt as transformNodesToSteps, Ct as transformValue, vn as validateChart, He as wcagContrastRatio, st as wcagLevel };