@phin-tech/dottie 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/PARITY.md CHANGED
@@ -24,6 +24,9 @@ fixture, so the gap is visible rather than silent.
24
24
  | Ports and edge-following, rotated shapes, free ends | Supported | [edge/connectors](../fixtures/edge/connectors.dottie) | |
25
25
  | Connectors and labels on outlines (ADR 0001) | Supported | [edge/extensions](../fixtures/edge/extensions.dottie) | Edge-following meets a `.path`'s actual outline, not its box (ray against 16-step flattened curves). Endpoints pinned with `portIndex` attach to the element's `ports`. A path's label goes in its `labelRect`. |
26
26
  | Extension shapes as stored (ADR 0001) | Supported | [edge/extensions](../fixtures/edge/extensions.dottie) | Drawn from the stored path with no extension installed. The `extension` field is kept as metadata and nothing runs. Parameters, commands and handles are Dottie-only. |
27
+ | Containers and swimlanes | Supported | [edge/containers](../fixtures/edge/containers.dottie) | Drawn from the stored frame and title band (`labelRect`); the app keeps them fitted (ADR 0006). |
28
+ | Themes of a page's own, and palette colors by name | Supported | [edge/palette](../fixtures/edge/palette.dottie) | Names are resolved when a file is read, by the same rules in `Theme.swift` and `theme.ts` (ADR 0005). |
29
+ | Elbows that go round shapes (`avoid`) | Supported | [edge/elbow-around](../fixtures/edge/elbow-around.dottie) | The same grid router, point for point (`ElbowRouter.swift`, `elbow.ts`). |
27
30
  | Waypoints (bends) on every routing, and hops | Supported | [edge/waypoints](../fixtures/edge/waypoints.dottie), [edge/waypoints-symbol](../fixtures/edge/waypoints-symbol.dottie) | Hops need the page, so `connectorParts` takes it; without one a line draws none. |
28
31
  | Arrowheads: arrow, triangle, dot, bar | Supported | [edge/connectors](../fixtures/edge/connectors.dottie) | |
29
32
  | Label colors (`textColor`, apart from the stroke) | Supported | [edge/text-colors](../fixtures/edge/text-colors.dottie) | Text boxes and notes ignore it, as in Dottie |
package/dist/compile.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! dottie.js 0.9.0 | Apache-2.0 | https://github.com/phin-tech/dottie */
1
+ /*! dottie.js 0.10.0 | Apache-2.0 | https://github.com/phin-tech/dottie */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -50,19 +50,80 @@ function isName(name) {
50
50
  return name.length <= MAX_NAME && /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
51
51
  }
52
52
 
53
+ // src/theme.ts
54
+ var rgb = (r, g, b) => ({ r, g, b, a: 1 });
55
+ function hex(h) {
56
+ const n = parseInt(h.slice(1), 16);
57
+ return { r: (n >> 16 & 255) / 255, g: (n >> 8 & 255) / 255, b: (n & 255) / 255, a: 1 };
58
+ }
59
+ var PALETTE_NAMES = ["accent", "muted", "danger", "warning", "success", "info"];
60
+ var palette = (colors) => PALETTE_NAMES.map((name, i) => ({ name, color: hex(colors[i]) }));
61
+ var LIGHT_PALETTE = palette(["#2563eb", "#6b7280", "#dc2626", "#d97706", "#16a34a", "#0891b2"]);
62
+ var DARK_PALETTE = palette(["#93c5fd", "#cbd5e1", "#fca5a5", "#fcd34d", "#86efac", "#67e8f9"]);
63
+ var themes = [
64
+ { id: "paper", name: "Paper", background: rgb(0.984, 0.98, 0.965), ink: rgb(0.12, 0.12, 0.13), palette: LIGHT_PALETTE },
65
+ { id: "white", name: "White", background: rgb(1, 1, 1), ink: rgb(0.12, 0.12, 0.13), palette: LIGHT_PALETTE },
66
+ {
67
+ id: "sepia",
68
+ name: "Sepia",
69
+ background: rgb(0.953, 0.914, 0.824),
70
+ ink: rgb(0.23, 0.18, 0.13),
71
+ palette: palette(["#9a3412", "#78716c", "#b91c1c", "#b45309", "#4d7c0f", "#0e7490"])
72
+ },
73
+ { id: "blueprint", name: "Blueprint", background: rgb(0.106, 0.227, 0.361), ink: rgb(0.91, 0.945, 0.984), palette: DARK_PALETTE },
74
+ { id: "chalkboard", name: "Chalkboard", background: rgb(0.169, 0.227, 0.2), ink: rgb(0.945, 0.945, 0.918), palette: DARK_PALETTE },
75
+ { id: "midnight", name: "Midnight", background: rgb(0.082, 0.086, 0.102), ink: rgb(0.925, 0.925, 0.94), palette: DARK_PALETTE }
76
+ ];
77
+ function themeNamed(id) {
78
+ return themes.find((t) => t.id === id) ?? null;
79
+ }
80
+ function pageTheme(page) {
81
+ const c = page.customTheme;
82
+ if (c) return { id: "custom", name: c.name, background: c.background, ink: c.ink, palette: c.palette };
83
+ return themeNamed(page.theme);
84
+ }
85
+ function paletteColor(page, name) {
86
+ const n = name.trim().toLowerCase();
87
+ return (pageTheme(page)?.palette ?? LIGHT_PALETTE).find((p) => p.name.toLowerCase() === n)?.color ?? null;
88
+ }
89
+ function resolvingPalette(page) {
90
+ const named = (e) => !!e.style.named;
91
+ if (!page.elements.some(named) && !(page.symbols ?? []).some((s) => s.elements.some(named))) return page;
92
+ const resolve = (e) => {
93
+ const n = e.style.named;
94
+ if (!n) return e;
95
+ const style = { ...e.style };
96
+ const f = n.fill !== null ? paletteColor(page, n.fill) : null;
97
+ const s = n.stroke !== null ? paletteColor(page, n.stroke) : null;
98
+ const t = n.textColor !== null ? paletteColor(page, n.textColor) : null;
99
+ if (f) style.fill = { ...f };
100
+ if (s) style.stroke = { ...s };
101
+ if (t) style.textColor = { ...t };
102
+ return { ...e, style };
103
+ };
104
+ return {
105
+ ...page,
106
+ elements: page.elements.map(resolve),
107
+ symbols: page.symbols ? page.symbols.map((s) => ({ ...s, elements: s.elements.map(resolve) })) : page.symbols
108
+ };
109
+ }
110
+
53
111
  // src/model.ts
54
112
  var SUPPORTED_VERSION = 2;
55
113
  var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image", "symbol"];
56
114
  var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
57
115
  var KNOWN_FIELDS = {
58
116
  file: ["version", "pages", "images"],
59
- page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
117
+ page: ["id", "name", "layers", "elements", "theme", "customTheme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
60
118
  flow: ["id", "from", "to", "every", "speed", "color", "size", "when", "spread", "volume", "overrides"],
61
119
  flowOverride: ["when", "volume"],
62
120
  symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button", "params"],
63
121
  layer: ["id", "name", "visible", "locked"],
64
122
  rgba: ["r", "g", "b", "a"],
65
- style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "font", "gridSize", "opacity", "dashOffset", "textColor"],
123
+ style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "font", "gridSize", "opacity", "dashOffset", "textColor", "named"],
124
+ colorNames: ["fill", "stroke", "textColor"],
125
+ customTheme: ["name", "background", "ink", "palette", "base"],
126
+ paletteColor: ["name", "color"],
66
127
  element: [
67
128
  "id",
68
129
  "kind",
@@ -100,8 +161,11 @@ var KNOWN_FIELDS = {
100
161
  "capacity",
101
162
  "delay",
102
163
  "queue",
103
- "gauge"
164
+ "gauge",
165
+ "containerID",
166
+ "container"
104
167
  ],
168
+ container: ["fixed", "lanes"],
105
169
  gauge: ["metric", "of", "max", "warn", "alarm", "style", "label"],
106
170
  strokePoint: ["x", "y"],
107
171
  subpath: ["closed", "coords"],
@@ -110,7 +174,7 @@ var KNOWN_FIELDS = {
110
174
  extensionRef: ["id", "shape", "version", "params"],
111
175
  normalizedPoint: ["x", "y"],
112
176
  normalizedRect: ["x", "y", "width", "height"],
113
- connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "cost"],
177
+ connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "avoid", "cost"],
114
178
  waypoint: ["x", "y"],
115
179
  timeline: ["fps", "duration", "boil", "settle", "poster", "tracks", "camera", "markers"],
116
180
  track: ["element", "keys", "boil", "follow", "repeats", "march"],
@@ -192,9 +256,36 @@ var Reader = class {
192
256
  gridSize: num(s.gridSize) ?? null,
193
257
  opacity: num(s.opacity) ?? null,
194
258
  dashOffset: num(s.dashOffset) ?? null,
195
- textColor: rgba(s.textColor) ?? null
259
+ textColor: rgba(s.textColor) ?? null,
260
+ named: this.colorNames(s.named)
196
261
  };
197
262
  }
263
+ container(v) {
264
+ if (!isObj(v)) return null;
265
+ this.fields(v, "container");
266
+ return { fixed: v.fixed === true ? true : null, lanes: v.lanes === "rows" || v.lanes === "columns" ? v.lanes : null };
267
+ }
268
+ colorNames(v) {
269
+ if (!isObj(v)) return null;
270
+ this.fields(v, "colorNames");
271
+ const n = { fill: str(v.fill) ?? null, stroke: str(v.stroke) ?? null, textColor: str(v.textColor) ?? null };
272
+ return n.fill === null && n.stroke === null && n.textColor === null ? null : n;
273
+ }
274
+ customTheme(v) {
275
+ if (!isObj(v)) return null;
276
+ this.fields(v, "customTheme");
277
+ const background = rgba(v.background), ink = rgba(v.ink);
278
+ if (!background || !ink) {
279
+ this.warn("A custom theme needs a background and an ink; drawn without it");
280
+ return null;
281
+ }
282
+ const palette2 = (Array.isArray(v.palette) ? v.palette : []).filter(isObj).flatMap((p) => {
283
+ this.fields(p, "paletteColor");
284
+ const name = str(p.name), color = rgba(p.color);
285
+ return name && color ? [{ name, color }] : [];
286
+ });
287
+ return { name: str(v.name) ?? "Custom", background, ink, palette: palette2, base: str(v.base) ?? null };
288
+ }
198
289
  endpoint(v) {
199
290
  const e = isObj(v) ? v : {};
200
291
  const port = str(e.port);
@@ -226,6 +317,7 @@ var Reader = class {
226
317
  return { x: num(w.x) ?? 0, y: num(w.y) ?? 0 };
227
318
  }) : null,
228
319
  hops: typeof v.hops === "boolean" ? v.hops : null,
320
+ avoid: typeof v.avoid === "boolean" ? v.avoid : null,
229
321
  cost: typeof v.cost === "number" && Number.isFinite(v.cost) ? v.cost : null
230
322
  };
231
323
  }
@@ -294,7 +386,9 @@ var Reader = class {
294
386
  capacity: num(v.capacity) ?? null,
295
387
  delay: num(v.delay) ?? null,
296
388
  queue: v.queue === true ? true : null,
297
- gauge: this.gauge(v.gauge)
389
+ gauge: this.gauge(v.gauge),
390
+ containerID: uuid(v.containerID) ?? null,
391
+ container: this.container(v.container)
298
392
  };
299
393
  }
300
394
  gauge(v) {
@@ -515,6 +609,7 @@ var Reader = class {
515
609
  layers,
516
610
  elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
517
611
  theme: str(v.theme) ?? null,
612
+ customTheme: this.customTheme(v.customTheme),
518
613
  timeline: this.timeline(v.timeline),
519
614
  symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null,
520
615
  variables: this.variables(v.variables),
@@ -578,7 +673,7 @@ function parseDottie(source) {
578
673
  if (isObj(v) && typeof v.data === "string") images[k] = reader.picture(v.data, str(v.format));
579
674
  }
580
675
  }
581
- const pages = json.pages.map((p, i) => reader.page(p, images, i + 1));
676
+ const pages = json.pages.map((p, i) => resolvingPalette(reader.page(p, images, i + 1)));
582
677
  if (new Set(pages.map((p) => p.id)).size !== pages.length) throw new DottieFormatError("Two pages share an id");
583
678
  return { version, pages, warnings: reader.warnings };
584
679
  }
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- /*! dottie.js 0.9.0 | Apache-2.0 | https://github.com/phin-tech/dottie */
2
+ /*! dottie.js 0.10.0 | Apache-2.0 | https://github.com/phin-tech/dottie */
3
3
  var __defProp = Object.defineProperty;
4
4
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
5
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -58,19 +58,80 @@ function isName(name) {
58
58
  return name.length <= MAX_NAME && /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
59
59
  }
60
60
 
61
+ // src/theme.ts
62
+ var rgb = (r, g, b) => ({ r, g, b, a: 1 });
63
+ function hex(h) {
64
+ const n = parseInt(h.slice(1), 16);
65
+ return { r: (n >> 16 & 255) / 255, g: (n >> 8 & 255) / 255, b: (n & 255) / 255, a: 1 };
66
+ }
67
+ var PALETTE_NAMES = ["accent", "muted", "danger", "warning", "success", "info"];
68
+ var palette = (colors) => PALETTE_NAMES.map((name, i) => ({ name, color: hex(colors[i]) }));
69
+ var LIGHT_PALETTE = palette(["#2563eb", "#6b7280", "#dc2626", "#d97706", "#16a34a", "#0891b2"]);
70
+ var DARK_PALETTE = palette(["#93c5fd", "#cbd5e1", "#fca5a5", "#fcd34d", "#86efac", "#67e8f9"]);
71
+ var themes = [
72
+ { id: "paper", name: "Paper", background: rgb(0.984, 0.98, 0.965), ink: rgb(0.12, 0.12, 0.13), palette: LIGHT_PALETTE },
73
+ { id: "white", name: "White", background: rgb(1, 1, 1), ink: rgb(0.12, 0.12, 0.13), palette: LIGHT_PALETTE },
74
+ {
75
+ id: "sepia",
76
+ name: "Sepia",
77
+ background: rgb(0.953, 0.914, 0.824),
78
+ ink: rgb(0.23, 0.18, 0.13),
79
+ palette: palette(["#9a3412", "#78716c", "#b91c1c", "#b45309", "#4d7c0f", "#0e7490"])
80
+ },
81
+ { id: "blueprint", name: "Blueprint", background: rgb(0.106, 0.227, 0.361), ink: rgb(0.91, 0.945, 0.984), palette: DARK_PALETTE },
82
+ { id: "chalkboard", name: "Chalkboard", background: rgb(0.169, 0.227, 0.2), ink: rgb(0.945, 0.945, 0.918), palette: DARK_PALETTE },
83
+ { id: "midnight", name: "Midnight", background: rgb(0.082, 0.086, 0.102), ink: rgb(0.925, 0.925, 0.94), palette: DARK_PALETTE }
84
+ ];
85
+ function themeNamed(id) {
86
+ return themes.find((t) => t.id === id) ?? null;
87
+ }
88
+ function pageTheme(page) {
89
+ const c = page.customTheme;
90
+ if (c) return { id: "custom", name: c.name, background: c.background, ink: c.ink, palette: c.palette };
91
+ return themeNamed(page.theme);
92
+ }
93
+ function paletteColor(page, name) {
94
+ const n = name.trim().toLowerCase();
95
+ return (pageTheme(page)?.palette ?? LIGHT_PALETTE).find((p) => p.name.toLowerCase() === n)?.color ?? null;
96
+ }
97
+ function resolvingPalette(page) {
98
+ const named = (e) => !!e.style.named;
99
+ if (!page.elements.some(named) && !(page.symbols ?? []).some((s) => s.elements.some(named))) return page;
100
+ const resolve = (e) => {
101
+ const n = e.style.named;
102
+ if (!n) return e;
103
+ const style = { ...e.style };
104
+ const f = n.fill !== null ? paletteColor(page, n.fill) : null;
105
+ const s = n.stroke !== null ? paletteColor(page, n.stroke) : null;
106
+ const t = n.textColor !== null ? paletteColor(page, n.textColor) : null;
107
+ if (f) style.fill = { ...f };
108
+ if (s) style.stroke = { ...s };
109
+ if (t) style.textColor = { ...t };
110
+ return { ...e, style };
111
+ };
112
+ return {
113
+ ...page,
114
+ elements: page.elements.map(resolve),
115
+ symbols: page.symbols ? page.symbols.map((s) => ({ ...s, elements: s.elements.map(resolve) })) : page.symbols
116
+ };
117
+ }
118
+
61
119
  // src/model.ts
62
120
  var SUPPORTED_VERSION = 2;
63
121
  var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image", "symbol"];
64
122
  var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
65
123
  var KNOWN_FIELDS = {
66
124
  file: ["version", "pages", "images"],
67
- page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
125
+ page: ["id", "name", "layers", "elements", "theme", "customTheme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
68
126
  flow: ["id", "from", "to", "every", "speed", "color", "size", "when", "spread", "volume", "overrides"],
69
127
  flowOverride: ["when", "volume"],
70
128
  symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button", "params"],
71
129
  layer: ["id", "name", "visible", "locked"],
72
130
  rgba: ["r", "g", "b", "a"],
73
- style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "font", "gridSize", "opacity", "dashOffset", "textColor"],
131
+ style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "font", "gridSize", "opacity", "dashOffset", "textColor", "named"],
132
+ colorNames: ["fill", "stroke", "textColor"],
133
+ customTheme: ["name", "background", "ink", "palette", "base"],
134
+ paletteColor: ["name", "color"],
74
135
  element: [
75
136
  "id",
76
137
  "kind",
@@ -108,8 +169,11 @@ var KNOWN_FIELDS = {
108
169
  "capacity",
109
170
  "delay",
110
171
  "queue",
111
- "gauge"
172
+ "gauge",
173
+ "containerID",
174
+ "container"
112
175
  ],
176
+ container: ["fixed", "lanes"],
113
177
  gauge: ["metric", "of", "max", "warn", "alarm", "style", "label"],
114
178
  strokePoint: ["x", "y"],
115
179
  subpath: ["closed", "coords"],
@@ -118,7 +182,7 @@ var KNOWN_FIELDS = {
118
182
  extensionRef: ["id", "shape", "version", "params"],
119
183
  normalizedPoint: ["x", "y"],
120
184
  normalizedRect: ["x", "y", "width", "height"],
121
- connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "cost"],
185
+ connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "avoid", "cost"],
122
186
  waypoint: ["x", "y"],
123
187
  timeline: ["fps", "duration", "boil", "settle", "poster", "tracks", "camera", "markers"],
124
188
  track: ["element", "keys", "boil", "follow", "repeats", "march"],
@@ -200,9 +264,36 @@ var Reader = class {
200
264
  gridSize: num(s.gridSize) ?? null,
201
265
  opacity: num(s.opacity) ?? null,
202
266
  dashOffset: num(s.dashOffset) ?? null,
203
- textColor: rgba(s.textColor) ?? null
267
+ textColor: rgba(s.textColor) ?? null,
268
+ named: this.colorNames(s.named)
204
269
  };
205
270
  }
271
+ container(v) {
272
+ if (!isObj(v)) return null;
273
+ this.fields(v, "container");
274
+ return { fixed: v.fixed === true ? true : null, lanes: v.lanes === "rows" || v.lanes === "columns" ? v.lanes : null };
275
+ }
276
+ colorNames(v) {
277
+ if (!isObj(v)) return null;
278
+ this.fields(v, "colorNames");
279
+ const n = { fill: str(v.fill) ?? null, stroke: str(v.stroke) ?? null, textColor: str(v.textColor) ?? null };
280
+ return n.fill === null && n.stroke === null && n.textColor === null ? null : n;
281
+ }
282
+ customTheme(v) {
283
+ if (!isObj(v)) return null;
284
+ this.fields(v, "customTheme");
285
+ const background = rgba(v.background), ink = rgba(v.ink);
286
+ if (!background || !ink) {
287
+ this.warn("A custom theme needs a background and an ink; drawn without it");
288
+ return null;
289
+ }
290
+ const palette2 = (Array.isArray(v.palette) ? v.palette : []).filter(isObj).flatMap((p) => {
291
+ this.fields(p, "paletteColor");
292
+ const name = str(p.name), color = rgba(p.color);
293
+ return name && color ? [{ name, color }] : [];
294
+ });
295
+ return { name: str(v.name) ?? "Custom", background, ink, palette: palette2, base: str(v.base) ?? null };
296
+ }
206
297
  endpoint(v) {
207
298
  const e = isObj(v) ? v : {};
208
299
  const port = str(e.port);
@@ -234,6 +325,7 @@ var Reader = class {
234
325
  return { x: num(w.x) ?? 0, y: num(w.y) ?? 0 };
235
326
  }) : null,
236
327
  hops: typeof v.hops === "boolean" ? v.hops : null,
328
+ avoid: typeof v.avoid === "boolean" ? v.avoid : null,
237
329
  cost: typeof v.cost === "number" && Number.isFinite(v.cost) ? v.cost : null
238
330
  };
239
331
  }
@@ -302,7 +394,9 @@ var Reader = class {
302
394
  capacity: num(v.capacity) ?? null,
303
395
  delay: num(v.delay) ?? null,
304
396
  queue: v.queue === true ? true : null,
305
- gauge: this.gauge(v.gauge)
397
+ gauge: this.gauge(v.gauge),
398
+ containerID: uuid(v.containerID) ?? null,
399
+ container: this.container(v.container)
306
400
  };
307
401
  }
308
402
  gauge(v) {
@@ -523,6 +617,7 @@ var Reader = class {
523
617
  layers,
524
618
  elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
525
619
  theme: str(v.theme) ?? null,
620
+ customTheme: this.customTheme(v.customTheme),
526
621
  timeline: this.timeline(v.timeline),
527
622
  symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null,
528
623
  variables: this.variables(v.variables),
@@ -586,7 +681,7 @@ function parseDottie(source2) {
586
681
  if (isObj(v) && typeof v.data === "string") images[k] = reader.picture(v.data, str(v.format));
587
682
  }
588
683
  }
589
- const pages = json.pages.map((p, i) => reader.page(p, images, i + 1));
684
+ const pages = json.pages.map((p, i) => resolvingPalette(reader.page(p, images, i + 1)));
590
685
  if (new Set(pages.map((p) => p.id)).size !== pages.length) throw new DottieFormatError("Two pages share an id");
591
686
  return { version, pages, warnings: reader.warnings };
592
687
  }
@@ -703,7 +798,7 @@ function compile(source2, runtime, options2 = {}) {
703
798
  }
704
799
 
705
800
  // src/index.ts
706
- var VERSION = "0.9.0";
801
+ var VERSION = "0.10.0";
707
802
 
708
803
  // src/cli.ts
709
804
  var usage = `dottie-compile ${VERSION}: a Dottie drawing as one script that plays it on any page.