@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 +3 -0
- package/dist/compile.js +103 -8
- package/dist/dottie-compile.mjs +104 -9
- package/dist/dottie-player.js +339 -71
- package/dist/dottie-player.min.js +55 -55
- package/dist/dottie-sim.min.js +4 -4
- package/dist/dottie.js +337 -71
- package/dist/types/elbow.d.ts +18 -0
- package/dist/types/flows.d.ts +2 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/measure.d.ts +11 -0
- package/dist/types/model.d.ts +32 -0
- package/dist/types/theme.d.ts +13 -1
- package/package.json +1 -1
package/dist/dottie.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! dottie.js 0.
|
|
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, value2) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value: value2 }) : obj[key] = value2;
|
|
4
4
|
var __publicField = (obj, key, value2) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value2);
|
|
@@ -134,19 +134,80 @@ function trim(s) {
|
|
|
134
134
|
return s.replace(/^[ \t ]+|[ \t ]+$/g, "");
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
// src/theme.ts
|
|
138
|
+
var rgb = (r, g, b) => ({ r, g, b, a: 1 });
|
|
139
|
+
function hex(h) {
|
|
140
|
+
const n = parseInt(h.slice(1), 16);
|
|
141
|
+
return { r: (n >> 16 & 255) / 255, g: (n >> 8 & 255) / 255, b: (n & 255) / 255, a: 1 };
|
|
142
|
+
}
|
|
143
|
+
var PALETTE_NAMES = ["accent", "muted", "danger", "warning", "success", "info"];
|
|
144
|
+
var palette = (colors) => PALETTE_NAMES.map((name, i) => ({ name, color: hex(colors[i]) }));
|
|
145
|
+
var LIGHT_PALETTE = palette(["#2563eb", "#6b7280", "#dc2626", "#d97706", "#16a34a", "#0891b2"]);
|
|
146
|
+
var DARK_PALETTE = palette(["#93c5fd", "#cbd5e1", "#fca5a5", "#fcd34d", "#86efac", "#67e8f9"]);
|
|
147
|
+
var themes = [
|
|
148
|
+
{ id: "paper", name: "Paper", background: rgb(0.984, 0.98, 0.965), ink: rgb(0.12, 0.12, 0.13), palette: LIGHT_PALETTE },
|
|
149
|
+
{ id: "white", name: "White", background: rgb(1, 1, 1), ink: rgb(0.12, 0.12, 0.13), palette: LIGHT_PALETTE },
|
|
150
|
+
{
|
|
151
|
+
id: "sepia",
|
|
152
|
+
name: "Sepia",
|
|
153
|
+
background: rgb(0.953, 0.914, 0.824),
|
|
154
|
+
ink: rgb(0.23, 0.18, 0.13),
|
|
155
|
+
palette: palette(["#9a3412", "#78716c", "#b91c1c", "#b45309", "#4d7c0f", "#0e7490"])
|
|
156
|
+
},
|
|
157
|
+
{ id: "blueprint", name: "Blueprint", background: rgb(0.106, 0.227, 0.361), ink: rgb(0.91, 0.945, 0.984), palette: DARK_PALETTE },
|
|
158
|
+
{ id: "chalkboard", name: "Chalkboard", background: rgb(0.169, 0.227, 0.2), ink: rgb(0.945, 0.945, 0.918), palette: DARK_PALETTE },
|
|
159
|
+
{ id: "midnight", name: "Midnight", background: rgb(0.082, 0.086, 0.102), ink: rgb(0.925, 0.925, 0.94), palette: DARK_PALETTE }
|
|
160
|
+
];
|
|
161
|
+
function themeNamed(id) {
|
|
162
|
+
return themes.find((t) => t.id === id) ?? null;
|
|
163
|
+
}
|
|
164
|
+
function pageTheme(page) {
|
|
165
|
+
const c = page.customTheme;
|
|
166
|
+
if (c) return { id: "custom", name: c.name, background: c.background, ink: c.ink, palette: c.palette };
|
|
167
|
+
return themeNamed(page.theme);
|
|
168
|
+
}
|
|
169
|
+
function paletteColor(page, name) {
|
|
170
|
+
const n = name.trim().toLowerCase();
|
|
171
|
+
return (pageTheme(page)?.palette ?? LIGHT_PALETTE).find((p) => p.name.toLowerCase() === n)?.color ?? null;
|
|
172
|
+
}
|
|
173
|
+
function resolvingPalette(page) {
|
|
174
|
+
const named = (e) => !!e.style.named;
|
|
175
|
+
if (!page.elements.some(named) && !(page.symbols ?? []).some((s) => s.elements.some(named))) return page;
|
|
176
|
+
const resolve2 = (e) => {
|
|
177
|
+
const n = e.style.named;
|
|
178
|
+
if (!n) return e;
|
|
179
|
+
const style2 = { ...e.style };
|
|
180
|
+
const f = n.fill !== null ? paletteColor(page, n.fill) : null;
|
|
181
|
+
const s = n.stroke !== null ? paletteColor(page, n.stroke) : null;
|
|
182
|
+
const t = n.textColor !== null ? paletteColor(page, n.textColor) : null;
|
|
183
|
+
if (f) style2.fill = { ...f };
|
|
184
|
+
if (s) style2.stroke = { ...s };
|
|
185
|
+
if (t) style2.textColor = { ...t };
|
|
186
|
+
return { ...e, style: style2 };
|
|
187
|
+
};
|
|
188
|
+
return {
|
|
189
|
+
...page,
|
|
190
|
+
elements: page.elements.map(resolve2),
|
|
191
|
+
symbols: page.symbols ? page.symbols.map((s) => ({ ...s, elements: s.elements.map(resolve2) })) : page.symbols
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
137
195
|
// src/model.ts
|
|
138
196
|
var SUPPORTED_VERSION = 2;
|
|
139
197
|
var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image", "symbol"];
|
|
140
198
|
var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
|
|
141
199
|
var KNOWN_FIELDS = {
|
|
142
200
|
file: ["version", "pages", "images"],
|
|
143
|
-
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
|
|
201
|
+
page: ["id", "name", "layers", "elements", "theme", "customTheme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
|
|
144
202
|
flow: ["id", "from", "to", "every", "speed", "color", "size", "when", "spread", "volume", "overrides"],
|
|
145
203
|
flowOverride: ["when", "volume"],
|
|
146
204
|
symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button", "params"],
|
|
147
205
|
layer: ["id", "name", "visible", "locked"],
|
|
148
206
|
rgba: ["r", "g", "b", "a"],
|
|
149
|
-
style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "font", "gridSize", "opacity", "dashOffset", "textColor"],
|
|
207
|
+
style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "font", "gridSize", "opacity", "dashOffset", "textColor", "named"],
|
|
208
|
+
colorNames: ["fill", "stroke", "textColor"],
|
|
209
|
+
customTheme: ["name", "background", "ink", "palette", "base"],
|
|
210
|
+
paletteColor: ["name", "color"],
|
|
150
211
|
element: [
|
|
151
212
|
"id",
|
|
152
213
|
"kind",
|
|
@@ -184,8 +245,11 @@ var KNOWN_FIELDS = {
|
|
|
184
245
|
"capacity",
|
|
185
246
|
"delay",
|
|
186
247
|
"queue",
|
|
187
|
-
"gauge"
|
|
248
|
+
"gauge",
|
|
249
|
+
"containerID",
|
|
250
|
+
"container"
|
|
188
251
|
],
|
|
252
|
+
container: ["fixed", "lanes"],
|
|
189
253
|
gauge: ["metric", "of", "max", "warn", "alarm", "style", "label"],
|
|
190
254
|
strokePoint: ["x", "y"],
|
|
191
255
|
subpath: ["closed", "coords"],
|
|
@@ -194,7 +258,7 @@ var KNOWN_FIELDS = {
|
|
|
194
258
|
extensionRef: ["id", "shape", "version", "params"],
|
|
195
259
|
normalizedPoint: ["x", "y"],
|
|
196
260
|
normalizedRect: ["x", "y", "width", "height"],
|
|
197
|
-
connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "cost"],
|
|
261
|
+
connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "avoid", "cost"],
|
|
198
262
|
waypoint: ["x", "y"],
|
|
199
263
|
timeline: ["fps", "duration", "boil", "settle", "poster", "tracks", "camera", "markers"],
|
|
200
264
|
track: ["element", "keys", "boil", "follow", "repeats", "march"],
|
|
@@ -281,9 +345,36 @@ var Reader = class {
|
|
|
281
345
|
gridSize: num(s.gridSize) ?? null,
|
|
282
346
|
opacity: num(s.opacity) ?? null,
|
|
283
347
|
dashOffset: num(s.dashOffset) ?? null,
|
|
284
|
-
textColor: rgba(s.textColor) ?? null
|
|
348
|
+
textColor: rgba(s.textColor) ?? null,
|
|
349
|
+
named: this.colorNames(s.named)
|
|
285
350
|
};
|
|
286
351
|
}
|
|
352
|
+
container(v) {
|
|
353
|
+
if (!isObj(v)) return null;
|
|
354
|
+
this.fields(v, "container");
|
|
355
|
+
return { fixed: v.fixed === true ? true : null, lanes: v.lanes === "rows" || v.lanes === "columns" ? v.lanes : null };
|
|
356
|
+
}
|
|
357
|
+
colorNames(v) {
|
|
358
|
+
if (!isObj(v)) return null;
|
|
359
|
+
this.fields(v, "colorNames");
|
|
360
|
+
const n = { fill: str(v.fill) ?? null, stroke: str(v.stroke) ?? null, textColor: str(v.textColor) ?? null };
|
|
361
|
+
return n.fill === null && n.stroke === null && n.textColor === null ? null : n;
|
|
362
|
+
}
|
|
363
|
+
customTheme(v) {
|
|
364
|
+
if (!isObj(v)) return null;
|
|
365
|
+
this.fields(v, "customTheme");
|
|
366
|
+
const background = rgba(v.background), ink = rgba(v.ink);
|
|
367
|
+
if (!background || !ink) {
|
|
368
|
+
this.warn("A custom theme needs a background and an ink; drawn without it");
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
const palette2 = (Array.isArray(v.palette) ? v.palette : []).filter(isObj).flatMap((p) => {
|
|
372
|
+
this.fields(p, "paletteColor");
|
|
373
|
+
const name = str(p.name), color2 = rgba(p.color);
|
|
374
|
+
return name && color2 ? [{ name, color: color2 }] : [];
|
|
375
|
+
});
|
|
376
|
+
return { name: str(v.name) ?? "Custom", background, ink, palette: palette2, base: str(v.base) ?? null };
|
|
377
|
+
}
|
|
287
378
|
endpoint(v) {
|
|
288
379
|
const e = isObj(v) ? v : {};
|
|
289
380
|
const port = str(e.port);
|
|
@@ -315,6 +406,7 @@ var Reader = class {
|
|
|
315
406
|
return { x: num(w.x) ?? 0, y: num(w.y) ?? 0 };
|
|
316
407
|
}) : null,
|
|
317
408
|
hops: typeof v.hops === "boolean" ? v.hops : null,
|
|
409
|
+
avoid: typeof v.avoid === "boolean" ? v.avoid : null,
|
|
318
410
|
cost: typeof v.cost === "number" && Number.isFinite(v.cost) ? v.cost : null
|
|
319
411
|
};
|
|
320
412
|
}
|
|
@@ -383,7 +475,9 @@ var Reader = class {
|
|
|
383
475
|
capacity: num(v.capacity) ?? null,
|
|
384
476
|
delay: num(v.delay) ?? null,
|
|
385
477
|
queue: v.queue === true ? true : null,
|
|
386
|
-
gauge: this.gauge(v.gauge)
|
|
478
|
+
gauge: this.gauge(v.gauge),
|
|
479
|
+
containerID: uuid(v.containerID) ?? null,
|
|
480
|
+
container: this.container(v.container)
|
|
387
481
|
};
|
|
388
482
|
}
|
|
389
483
|
gauge(v) {
|
|
@@ -604,6 +698,7 @@ var Reader = class {
|
|
|
604
698
|
layers,
|
|
605
699
|
elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
|
|
606
700
|
theme: str(v.theme) ?? null,
|
|
701
|
+
customTheme: this.customTheme(v.customTheme),
|
|
607
702
|
timeline: this.timeline(v.timeline),
|
|
608
703
|
symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null,
|
|
609
704
|
variables: this.variables(v.variables),
|
|
@@ -667,7 +762,7 @@ function parseDottie(source) {
|
|
|
667
762
|
if (isObj(v) && typeof v.data === "string") images[k] = reader.picture(v.data, str(v.format));
|
|
668
763
|
}
|
|
669
764
|
}
|
|
670
|
-
const pages = json.pages.map((p, i) => reader.page(p, images, i + 1));
|
|
765
|
+
const pages = json.pages.map((p, i) => resolvingPalette(reader.page(p, images, i + 1)));
|
|
671
766
|
if (new Set(pages.map((p) => p.id)).size !== pages.length) throw new DottieFormatError("Two pages share an id");
|
|
672
767
|
return { version, pages, warnings: reader.warnings };
|
|
673
768
|
}
|
|
@@ -687,7 +782,8 @@ function cloneElement(e) {
|
|
|
687
782
|
...e.style,
|
|
688
783
|
stroke: { ...e.style.stroke },
|
|
689
784
|
fill: { ...e.style.fill },
|
|
690
|
-
textColor: e.style.textColor ? { ...e.style.textColor } : null
|
|
785
|
+
textColor: e.style.textColor ? { ...e.style.textColor } : null,
|
|
786
|
+
named: e.style.named ? { ...e.style.named } : e.style.named
|
|
691
787
|
},
|
|
692
788
|
connector: e.connector ? {
|
|
693
789
|
...e.connector,
|
|
@@ -1177,6 +1273,165 @@ function shapePath(e) {
|
|
|
1177
1273
|
return path;
|
|
1178
1274
|
}
|
|
1179
1275
|
|
|
1276
|
+
// src/elbow.ts
|
|
1277
|
+
var MARGIN = 16;
|
|
1278
|
+
var BEND = 24;
|
|
1279
|
+
var SMALLEST = 24;
|
|
1280
|
+
var MOST = 48;
|
|
1281
|
+
function obstacle(e) {
|
|
1282
|
+
if (e.kind === "connector" || e.kind === "text" || e.kind === "freehand") return null;
|
|
1283
|
+
if (e.kind === "path" && !e.extension) return null;
|
|
1284
|
+
if (e.style.opacity !== null && e.style.opacity <= 0) return null;
|
|
1285
|
+
const r = rotatedBounds(e);
|
|
1286
|
+
return r.width < SMALLEST || r.height < SMALLEST ? null : r;
|
|
1287
|
+
}
|
|
1288
|
+
function crosses(points, r) {
|
|
1289
|
+
const x1 = r.x + r.width, y1 = r.y + r.height;
|
|
1290
|
+
for (let k = 1; k < points.length; k++) {
|
|
1291
|
+
const p = points[k - 1], q = points[k];
|
|
1292
|
+
if (p.y === q.y) {
|
|
1293
|
+
if (r.y < p.y && p.y < y1 && Math.min(p.x, q.x) < x1 && Math.max(p.x, q.x) > r.x) return true;
|
|
1294
|
+
} else if (p.x === q.x) {
|
|
1295
|
+
if (r.x < p.x && p.x < x1 && Math.min(p.y, q.y) < y1 && Math.max(p.y, q.y) > r.y) return true;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return false;
|
|
1299
|
+
}
|
|
1300
|
+
var padded = (r) => ({ x: r.x - MARGIN, y: r.y - MARGIN, width: r.width + 2 * MARGIN, height: r.height + 2 * MARGIN });
|
|
1301
|
+
var inside = (p, r) => r.x < p.x && p.x < r.x + r.width && r.y < p.y && p.y < r.y + r.height;
|
|
1302
|
+
var memo = /* @__PURE__ */ new Map();
|
|
1303
|
+
function avoiding(plain, a, b, startVertical, endVertical, elements, except) {
|
|
1304
|
+
const usable = (r) => !inside(a, padded(r)) && !inside(b, padded(r));
|
|
1305
|
+
const all = [];
|
|
1306
|
+
let crossed = false;
|
|
1307
|
+
for (const e of elements) {
|
|
1308
|
+
if (except.has(e.id)) continue;
|
|
1309
|
+
const r = obstacle(e);
|
|
1310
|
+
if (!r || !usable(r)) continue;
|
|
1311
|
+
all.push(r);
|
|
1312
|
+
if (!crossed && crosses(plain, r)) crossed = true;
|
|
1313
|
+
}
|
|
1314
|
+
if (!crossed) return plain;
|
|
1315
|
+
const key = JSON.stringify([a.x, a.y, b.x, b.y, startVertical, endVertical, all.map((r) => [r.x, r.y, r.width, r.height])]);
|
|
1316
|
+
const hit = memo.get(key);
|
|
1317
|
+
if (hit) return hit;
|
|
1318
|
+
const out = route(plain, a, b, startVertical, endVertical, all);
|
|
1319
|
+
if (memo.size >= 512) memo.clear();
|
|
1320
|
+
memo.set(key, out);
|
|
1321
|
+
return out;
|
|
1322
|
+
}
|
|
1323
|
+
function route(plain, a, b, startVertical, endVertical, usable) {
|
|
1324
|
+
let chosen = usable.map((_, i) => i).filter((i) => crosses(plain, usable[i]));
|
|
1325
|
+
if (chosen.length === 0) return plain;
|
|
1326
|
+
for (let round = 0; round < 4; round++) {
|
|
1327
|
+
if (chosen.length > MOST) return plain;
|
|
1328
|
+
const path = grid(a, b, startVertical, endVertical, chosen.map((i) => padded(usable[i])));
|
|
1329
|
+
if (!path) return plain;
|
|
1330
|
+
const more = usable.map((_, i) => i).filter((i) => !chosen.includes(i) && crosses(path, usable[i]));
|
|
1331
|
+
if (more.length === 0) return path;
|
|
1332
|
+
chosen = [...chosen, ...more].sort((p, q) => p - q);
|
|
1333
|
+
}
|
|
1334
|
+
return plain;
|
|
1335
|
+
}
|
|
1336
|
+
function grid(a, b, startVertical, endVertical, boxes) {
|
|
1337
|
+
let xs = [a.x, b.x, (a.x + b.x) / 2], ys = [a.y, b.y, (a.y + b.y) / 2];
|
|
1338
|
+
for (const r of boxes) {
|
|
1339
|
+
xs.push(r.x, r.x + r.width);
|
|
1340
|
+
ys.push(r.y, r.y + r.height);
|
|
1341
|
+
}
|
|
1342
|
+
xs = [...new Set(xs)].sort((p, q) => p - q);
|
|
1343
|
+
ys = [...new Set(ys)].sort((p, q) => p - q);
|
|
1344
|
+
const nx = xs.length, ny = ys.length;
|
|
1345
|
+
const ia = xs.indexOf(a.x), ja = ys.indexOf(a.y), ib = xs.indexOf(b.x), jb = ys.indexOf(b.y);
|
|
1346
|
+
if (ia < 0 || ja < 0 || ib < 0 || jb < 0) return null;
|
|
1347
|
+
const at = new Map(xs.map((x, k) => [x, k])), bt = new Map(ys.map((y, k) => [y, k]));
|
|
1348
|
+
const inner = new Uint8Array(nx * ny), acrossBlocked = new Uint8Array(nx * ny), downBlocked = new Uint8Array(nx * ny);
|
|
1349
|
+
for (const r of boxes) {
|
|
1350
|
+
const i0 = at.get(r.x), i1 = at.get(r.x + r.width), j0 = bt.get(r.y), j1 = bt.get(r.y + r.height);
|
|
1351
|
+
if (i0 === void 0 || i1 === void 0 || j0 === void 0 || j1 === void 0) continue;
|
|
1352
|
+
for (let i = i0; i < i1; i++) for (let j = j0; j < j1; j++) {
|
|
1353
|
+
if (j > j0) acrossBlocked[i * ny + j] = 1;
|
|
1354
|
+
if (i > i0) downBlocked[i * ny + j] = 1;
|
|
1355
|
+
if (i > i0 && j > j0) inner[i * ny + j] = 1;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
const blocked = (i, j) => inner[i * ny + j] === 1;
|
|
1359
|
+
const across = (i0, i1, j) => acrossBlocked[Math.min(i0, i1) * ny + j] === 1;
|
|
1360
|
+
const down = (j0, j1, i) => downBlocked[i * ny + Math.min(j0, j1)] === 1;
|
|
1361
|
+
const count = nx * ny * 2;
|
|
1362
|
+
const dist = new Array(count).fill(Infinity), prev = new Array(count).fill(-1);
|
|
1363
|
+
const done = new Array(count).fill(false);
|
|
1364
|
+
const heap = new Frontier();
|
|
1365
|
+
const first = (ia * ny + ja) * 2 + (startVertical ? 1 : 0);
|
|
1366
|
+
dist[first] = 0;
|
|
1367
|
+
heap.push(0, first);
|
|
1368
|
+
const want = (ib * ny + jb) * 2 + (endVertical ? 1 : 0);
|
|
1369
|
+
for (let top = heap.pop(); top; top = heap.pop()) {
|
|
1370
|
+
const [cost, s] = top;
|
|
1371
|
+
if (done[s]) continue;
|
|
1372
|
+
done[s] = true;
|
|
1373
|
+
if (s === want) break;
|
|
1374
|
+
const node = Math.floor(s / 2), axis = s % 2, i = Math.floor(node / ny), j = node % ny;
|
|
1375
|
+
for (const [di, dj] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) {
|
|
1376
|
+
const ni = i + di, nj = j + dj;
|
|
1377
|
+
if (ni < 0 || ni >= nx || nj < 0 || nj >= ny || blocked(ni, nj)) continue;
|
|
1378
|
+
const turn = di !== 0 ? 0 : 1;
|
|
1379
|
+
if (di !== 0 ? across(i, ni, j) : down(j, nj, i)) continue;
|
|
1380
|
+
const length = Math.abs(xs[ni] - xs[i]) + Math.abs(ys[nj] - ys[j]);
|
|
1381
|
+
const c = cost + length + (turn !== axis ? BEND : 0);
|
|
1382
|
+
const t = (ni * ny + nj) * 2 + turn;
|
|
1383
|
+
if (c < dist[t]) {
|
|
1384
|
+
dist[t] = c;
|
|
1385
|
+
prev[t] = s;
|
|
1386
|
+
heap.push(c, t);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
if (!done[want]) return null;
|
|
1391
|
+
const points = [];
|
|
1392
|
+
for (let s = want; s >= 0; s = prev[s]) {
|
|
1393
|
+
const node = Math.floor(s / 2);
|
|
1394
|
+
points.push({ x: xs[Math.floor(node / ny)], y: ys[node % ny] });
|
|
1395
|
+
}
|
|
1396
|
+
return points.reverse();
|
|
1397
|
+
}
|
|
1398
|
+
var Frontier = class {
|
|
1399
|
+
constructor() {
|
|
1400
|
+
__publicField(this, "heap", []);
|
|
1401
|
+
__publicField(this, "next", 0);
|
|
1402
|
+
}
|
|
1403
|
+
less(i, j) {
|
|
1404
|
+
const a = this.heap[i], b = this.heap[j];
|
|
1405
|
+
return a[0] < b[0] || a[0] === b[0] && a[1] < b[1];
|
|
1406
|
+
}
|
|
1407
|
+
push(cost, state) {
|
|
1408
|
+
this.heap.push([cost, this.next++, state]);
|
|
1409
|
+
for (let i = this.heap.length - 1; i > 0; ) {
|
|
1410
|
+
const up = i - 1 >> 1;
|
|
1411
|
+
if (!this.less(i, up)) break;
|
|
1412
|
+
[this.heap[i], this.heap[up]] = [this.heap[up], this.heap[i]];
|
|
1413
|
+
i = up;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
pop() {
|
|
1417
|
+
if (this.heap.length === 0) return null;
|
|
1418
|
+
const top = this.heap[0], last = this.heap.pop();
|
|
1419
|
+
if (this.heap.length > 0) {
|
|
1420
|
+
this.heap[0] = last;
|
|
1421
|
+
for (let i = 0; ; ) {
|
|
1422
|
+
const l = 2 * i + 1, r = l + 1;
|
|
1423
|
+
let m = i;
|
|
1424
|
+
if (l < this.heap.length && this.less(l, m)) m = l;
|
|
1425
|
+
if (r < this.heap.length && this.less(r, m)) m = r;
|
|
1426
|
+
if (m === i) break;
|
|
1427
|
+
[this.heap[i], this.heap[m]] = [this.heap[m], this.heap[i]];
|
|
1428
|
+
i = m;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
return [top[0], top[2]];
|
|
1432
|
+
}
|
|
1433
|
+
};
|
|
1434
|
+
|
|
1180
1435
|
// src/connector.ts
|
|
1181
1436
|
function portPoint(shape, port) {
|
|
1182
1437
|
const r = frame(shape);
|
|
@@ -1320,7 +1575,7 @@ function routeThrough(p, c) {
|
|
|
1320
1575
|
}
|
|
1321
1576
|
}
|
|
1322
1577
|
}
|
|
1323
|
-
function
|
|
1578
|
+
function route2(e, index) {
|
|
1324
1579
|
const c = e.connector;
|
|
1325
1580
|
if (!c) return { kind: "polyline", points: [] };
|
|
1326
1581
|
const [a, b] = endpoints(e, index);
|
|
@@ -1336,16 +1591,19 @@ function route(e, index) {
|
|
|
1336
1591
|
case "elbow": {
|
|
1337
1592
|
const startV = vertical(c.start.port) ?? !horizontal;
|
|
1338
1593
|
const endV = vertical(c.end.port) ?? !horizontal;
|
|
1594
|
+
let plain;
|
|
1339
1595
|
if (startV && endV) {
|
|
1340
1596
|
const my = a.y + dy / 2;
|
|
1341
|
-
|
|
1342
|
-
}
|
|
1343
|
-
if (!startV && !endV) {
|
|
1597
|
+
plain = [a, { x: a.x, y: my }, { x: b.x, y: my }, b];
|
|
1598
|
+
} else if (!startV && !endV) {
|
|
1344
1599
|
const mx = a.x + dx / 2;
|
|
1345
|
-
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
return { kind: "polyline", points:
|
|
1600
|
+
plain = [a, { x: mx, y: a.y }, { x: mx, y: b.y }, b];
|
|
1601
|
+
} else if (startV) plain = [a, { x: a.x, y: b.y }, b];
|
|
1602
|
+
else plain = [a, { x: b.x, y: a.y }, b];
|
|
1603
|
+
if (c.avoid !== true) return { kind: "polyline", points: plain };
|
|
1604
|
+
const ends = new Set([c.start.elementID, c.end.elementID].filter((x) => x !== null));
|
|
1605
|
+
const routed = avoiding(plain, a, b, startV, endV, index.values(), ends);
|
|
1606
|
+
return { kind: "polyline", points: routed === plain ? plain : simplified(routed) };
|
|
1349
1607
|
}
|
|
1350
1608
|
}
|
|
1351
1609
|
}
|
|
@@ -1356,7 +1614,7 @@ function arrowhead(tip, from, size) {
|
|
|
1356
1614
|
return [wing(spread), wing(-spread)];
|
|
1357
1615
|
}
|
|
1358
1616
|
function connectorBounds(e, index) {
|
|
1359
|
-
const pts = routePoints(
|
|
1617
|
+
const pts = routePoints(route2(e, index));
|
|
1360
1618
|
if (pts.length === 0) return { x: 0, y: 0, width: 0, height: 0 };
|
|
1361
1619
|
let x0 = pts[0].x, y0 = pts[0].y, x1 = x0, y1 = y0;
|
|
1362
1620
|
for (const p of pts) {
|
|
@@ -1368,7 +1626,7 @@ function connectorBounds(e, index) {
|
|
|
1368
1626
|
return { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
1369
1627
|
}
|
|
1370
1628
|
function midpoint(e, index) {
|
|
1371
|
-
const pts = routePoints(
|
|
1629
|
+
const pts = routePoints(route2(e, index));
|
|
1372
1630
|
if (pts.length <= 1) return pts[0] ?? { x: 0, y: 0 };
|
|
1373
1631
|
const lengths = [];
|
|
1374
1632
|
let total = 0;
|
|
@@ -1517,7 +1775,7 @@ function graphOf(frame2) {
|
|
|
1517
1775
|
graphs.set(els, { members: [...els], graph });
|
|
1518
1776
|
return graph;
|
|
1519
1777
|
}
|
|
1520
|
-
var
|
|
1778
|
+
var Frontier2 = class {
|
|
1521
1779
|
constructor() {
|
|
1522
1780
|
__publicField(this, "heap", []);
|
|
1523
1781
|
}
|
|
@@ -1571,7 +1829,7 @@ function grow({ shapes: shapes2, next }, from, offline, until) {
|
|
|
1571
1829
|
const dist = /* @__PURE__ */ new Map([[from, 0]]), order = /* @__PURE__ */ new Map([[from, 0]]);
|
|
1572
1830
|
let counter = 1;
|
|
1573
1831
|
const tree = new FlowTree(from);
|
|
1574
|
-
const open = new
|
|
1832
|
+
const open = new Frontier2();
|
|
1575
1833
|
open.push(from, 0, 0);
|
|
1576
1834
|
while (open.size > 0) {
|
|
1577
1835
|
const { id: n, order: o } = open.pop();
|
|
@@ -1677,6 +1935,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1677
1935
|
return pts;
|
|
1678
1936
|
};
|
|
1679
1937
|
const metrics2 = emptyMetrics();
|
|
1938
|
+
const routes = /* @__PURE__ */ new Map();
|
|
1680
1939
|
for (const e of frame2.elements) {
|
|
1681
1940
|
if (e.kind === "connector" && !e.connector) continue;
|
|
1682
1941
|
metrics2.elements.set(e.id, { throughput: 0, load: null, delay: e.kind !== "connector" ? delayOf(e) : 0, backlog: 0, inFlight: 0, depth: 0 });
|
|
@@ -1688,7 +1947,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1688
1947
|
if (c !== null && Number.isFinite(c)) room.set(e.id, Math.max(c, 0));
|
|
1689
1948
|
}
|
|
1690
1949
|
const full = () => new Set([...room].filter(([, v]) => v <= TINY).map(([id]) => id));
|
|
1691
|
-
const
|
|
1950
|
+
const route3 = (tree, goal) => {
|
|
1692
1951
|
const hops = [], shapes2 = [];
|
|
1693
1952
|
let at = goal;
|
|
1694
1953
|
for (let step = tree.came.get(at); step; step = tree.came.get(at)) {
|
|
@@ -1700,7 +1959,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1700
1959
|
return { hops: hops.reverse(), shapes: shapes2.reverse() };
|
|
1701
1960
|
};
|
|
1702
1961
|
const way = (hops, shapes2) => {
|
|
1703
|
-
const points = [],
|
|
1962
|
+
const points = [], inside2 = [], stretches = [];
|
|
1704
1963
|
let length = 0;
|
|
1705
1964
|
hops.forEach(([id, back], k) => {
|
|
1706
1965
|
const c = byID.get(id);
|
|
@@ -1711,7 +1970,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1711
1970
|
if (last) {
|
|
1712
1971
|
const gap = Math.hypot(line2[0].x - last.x, line2[0].y - last.y);
|
|
1713
1972
|
const shape = byID.get(shapes2[k]);
|
|
1714
|
-
|
|
1973
|
+
inside2.push([length, length + gap, shape ? delayOf(shape) : 0]);
|
|
1715
1974
|
length += gap;
|
|
1716
1975
|
}
|
|
1717
1976
|
const start2 = length;
|
|
@@ -1719,7 +1978,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1719
1978
|
stretches.push([id, start2, length]);
|
|
1720
1979
|
points.push(...line2);
|
|
1721
1980
|
});
|
|
1722
|
-
return length > 0 ? { line: new Polyline(points), length, inside, stretches } : null;
|
|
1981
|
+
return length > 0 ? { line: new Polyline(points), length, inside: inside2, stretches } : null;
|
|
1723
1982
|
};
|
|
1724
1983
|
const along = (w, elapsedAt, speed) => {
|
|
1725
1984
|
let elapsed = elapsedAt, d = 0;
|
|
@@ -1760,6 +2019,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1760
2019
|
if (flow.when !== null && values !== null && !holds(flow.when, values)) continue;
|
|
1761
2020
|
const source = byID.get(flow.from);
|
|
1762
2021
|
const base2 = source ? baseTree(flow.from) : null;
|
|
2022
|
+
routes.set(flow.id, []);
|
|
1763
2023
|
if (!source || !base2) continue;
|
|
1764
2024
|
const volume = amountIn(flow, values);
|
|
1765
2025
|
const fm = { volume, placed: 0, backlog: 0, backup: 0, transit: null };
|
|
@@ -1774,7 +2034,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1774
2034
|
const tree = flowTree(flow.from, frame2, union2(offline, full()), candidates[0]);
|
|
1775
2035
|
const goal2 = tree?.goals(candidates, false)[0];
|
|
1776
2036
|
if (!tree || goal2 === void 0) break;
|
|
1777
|
-
const r =
|
|
2037
|
+
const r = route3(tree, goal2);
|
|
1778
2038
|
const ids = [...r.shapes, ...r.hops.map(([id]) => id)];
|
|
1779
2039
|
const rooms = ids.filter((id) => room.has(id)).map((id) => room.get(id));
|
|
1780
2040
|
const fits = Math.min(left, rooms.length > 0 ? Math.min(...rooms) : Infinity);
|
|
@@ -1787,7 +2047,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1787
2047
|
let at = flow.from;
|
|
1788
2048
|
const goal = base2.goals(candidates, false)[0];
|
|
1789
2049
|
if (goal !== void 0) {
|
|
1790
|
-
const r =
|
|
2050
|
+
const r = route3(base2, goal), done = full();
|
|
1791
2051
|
const sequence = [[r.shapes[0], r.shapes[0]]];
|
|
1792
2052
|
r.hops.forEach(([id], k) => {
|
|
1793
2053
|
sequence.push([id, r.shapes[k]], [r.shapes[k + 1], r.shapes[k]]);
|
|
@@ -1816,6 +2076,13 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1816
2076
|
else waiting2.push([at, left]);
|
|
1817
2077
|
}
|
|
1818
2078
|
waitingBy.set(flow.id, waiting2);
|
|
2079
|
+
routes.set(flow.id, placements.map((p) => ({
|
|
2080
|
+
goal: p.goal,
|
|
2081
|
+
hops: p.hops,
|
|
2082
|
+
amount: p.amount,
|
|
2083
|
+
waits: p.waits === true,
|
|
2084
|
+
cost: p.hops.reduce((s, [id]) => s + routeCost(byID.get(id)?.connector?.cost ?? null), 0)
|
|
2085
|
+
})));
|
|
1819
2086
|
for (const p of placements) {
|
|
1820
2087
|
for (const id of [...p.shapes, ...p.hops.map(([h]) => h)]) bump(id, (m) => {
|
|
1821
2088
|
m.throughput += p.amount;
|
|
@@ -1898,7 +2165,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1898
2165
|
const tree = flowTree(at, frame2, union2(offline, blocked), flow.to[0]);
|
|
1899
2166
|
const goal = tree?.goals(flow.to, false)[0];
|
|
1900
2167
|
if (!tree || goal === void 0) break;
|
|
1901
|
-
const r =
|
|
2168
|
+
const r = route3(tree, goal);
|
|
1902
2169
|
const ids = [...r.shapes.slice(1), ...r.hops.map(([id]) => id)];
|
|
1903
2170
|
const rooms = ids.filter((id) => trial.has(id)).map((id) => trial.get(id));
|
|
1904
2171
|
const spare = rooms.length > 0 ? Math.min(...rooms) : Infinity;
|
|
@@ -1953,7 +2220,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1953
2220
|
if (c === null || !Number.isFinite(c) || !m) continue;
|
|
1954
2221
|
m.load = c > 0 ? m.throughput / c : 1;
|
|
1955
2222
|
}
|
|
1956
|
-
return { packets, metrics: metrics2 };
|
|
2223
|
+
return { packets, metrics: metrics2, routes };
|
|
1957
2224
|
}
|
|
1958
2225
|
var BLANK = {
|
|
1959
2226
|
seed: 1,
|
|
@@ -2047,16 +2314,16 @@ function finishing(elements, metrics2, values, frame2, flows, since = Infinity,
|
|
|
2047
2314
|
}
|
|
2048
2315
|
var gaugeKey = (id) => "gauge|" + id;
|
|
2049
2316
|
var GAUGE_EASE = 1;
|
|
2050
|
-
var
|
|
2317
|
+
var hex2 = (h) => {
|
|
2051
2318
|
const v = parseInt(h.slice(1), 16);
|
|
2052
2319
|
return { r: (v >> 16 & 255) / 255, g: (v >> 8 & 255) / 255, b: (v & 255) / 255, a: 1 };
|
|
2053
2320
|
};
|
|
2054
|
-
var GAUGE_GREEN =
|
|
2055
|
-
var GAUGE_AMBER =
|
|
2056
|
-
var GAUGE_RED =
|
|
2057
|
-
var GAUGE_BLUE =
|
|
2058
|
-
var GAUGE_TRACK =
|
|
2059
|
-
var GAUGE_GRAY =
|
|
2321
|
+
var GAUGE_GREEN = hex2("#16a34a");
|
|
2322
|
+
var GAUGE_AMBER = hex2("#d97706");
|
|
2323
|
+
var GAUGE_RED = hex2("#dc2626");
|
|
2324
|
+
var GAUGE_BLUE = hex2("#2f6fdf");
|
|
2325
|
+
var GAUGE_TRACK = hex2("#e5e7eb");
|
|
2326
|
+
var GAUGE_GRAY = hex2("#9ca3af");
|
|
2060
2327
|
function formatted(metric, v) {
|
|
2061
2328
|
if (v === null || !Number.isFinite(v)) return "\u2013";
|
|
2062
2329
|
switch (metric) {
|
|
@@ -2342,17 +2609,17 @@ function clusterStrokes(c, angle2, size) {
|
|
|
2342
2609
|
});
|
|
2343
2610
|
}
|
|
2344
2611
|
function contains(contours, p) {
|
|
2345
|
-
let
|
|
2612
|
+
let inside2 = false;
|
|
2346
2613
|
for (const poly of contours) {
|
|
2347
2614
|
if (poly.length < 3) continue;
|
|
2348
2615
|
let k = poly.length - 1;
|
|
2349
2616
|
for (let i = 0; i < poly.length; i++) {
|
|
2350
2617
|
const a = poly[i], b = poly[k];
|
|
2351
|
-
if (a.y > p.y !== b.y > p.y && p.x < (b.x - a.x) * (p.y - a.y) / (b.y - a.y) + a.x)
|
|
2618
|
+
if (a.y > p.y !== b.y > p.y && p.x < (b.x - a.x) * (p.y - a.y) / (b.y - a.y) + a.x) inside2 = !inside2;
|
|
2352
2619
|
k = i;
|
|
2353
2620
|
}
|
|
2354
2621
|
}
|
|
2355
|
-
return
|
|
2622
|
+
return inside2;
|
|
2356
2623
|
}
|
|
2357
2624
|
function distance(p, contours) {
|
|
2358
2625
|
let best = Infinity;
|
|
@@ -2629,7 +2896,7 @@ function connectorParts(e, index, page) {
|
|
|
2629
2896
|
const c = e.connector;
|
|
2630
2897
|
if (!c) return [new Path(), new Path()];
|
|
2631
2898
|
const [a, b] = endpoints(e, index);
|
|
2632
|
-
const r =
|
|
2899
|
+
const r = route2(e, index);
|
|
2633
2900
|
const hops = c.hops === true && page ? hopCrossings(e, r, page, index) : [];
|
|
2634
2901
|
const key = [
|
|
2635
2902
|
e.seed,
|
|
@@ -2717,7 +2984,7 @@ function linesBeneath(e, page, index) {
|
|
|
2717
2984
|
}
|
|
2718
2985
|
const count = f.first.get(e.id) ?? f.under.length;
|
|
2719
2986
|
while (f.lines.length < count) {
|
|
2720
|
-
const points = routePoints(
|
|
2987
|
+
const points = routePoints(route2(f.under[f.lines.length], index));
|
|
2721
2988
|
f.lines.push({ points, box: boxOf(points) });
|
|
2722
2989
|
}
|
|
2723
2990
|
return { lines: f.lines, count };
|
|
@@ -3021,7 +3288,7 @@ function followSpan(track, t) {
|
|
|
3021
3288
|
return f;
|
|
3022
3289
|
}
|
|
3023
3290
|
function tracing(e, page, index = indexOf(page)) {
|
|
3024
|
-
if (e.kind === "connector") return new Polyline(routePoints(
|
|
3291
|
+
if (e.kind === "connector") return new Polyline(routePoints(route2(e, index)));
|
|
3025
3292
|
const clean = cloneElement(e);
|
|
3026
3293
|
clean.style.roughness = 0;
|
|
3027
3294
|
const pts = outline(clean).contours()[0] ?? [];
|
|
@@ -3301,10 +3568,10 @@ var Expansions = class {
|
|
|
3301
3568
|
this.posing = posing;
|
|
3302
3569
|
}
|
|
3303
3570
|
};
|
|
3304
|
-
function expandingSymbols(page, t, posing = true, times = /* @__PURE__ */ new Map(),
|
|
3571
|
+
function expandingSymbols(page, t, posing = true, times = /* @__PURE__ */ new Map(), memo2) {
|
|
3305
3572
|
if (!hasInstances(page)) return page;
|
|
3306
3573
|
const budget = { left: MAX_ELEMENTS };
|
|
3307
|
-
const m =
|
|
3574
|
+
const m = memo2 && memo2.page === page && memo2.t === t && memo2.posing === posing ? memo2 : void 0;
|
|
3308
3575
|
return { ...page, elements: expand(page.elements, page, t, symbolTable(page), [], posing, budget, times, m) };
|
|
3309
3576
|
}
|
|
3310
3577
|
function symbolTable(page) {
|
|
@@ -3312,7 +3579,7 @@ function symbolTable(page) {
|
|
|
3312
3579
|
for (const s of page.symbols ?? []) if (!table.has(s.id)) table.set(s.id, s);
|
|
3313
3580
|
return table;
|
|
3314
3581
|
}
|
|
3315
|
-
function expand(elements, page, t, table, stack, posing, budget, times = /* @__PURE__ */ new Map(),
|
|
3582
|
+
function expand(elements, page, t, table, stack, posing, budget, times = /* @__PURE__ */ new Map(), memo2) {
|
|
3316
3583
|
const instances = new Set(elements.filter((e) => e.kind === "symbol").map((e) => e.id));
|
|
3317
3584
|
if (instances.size === 0) {
|
|
3318
3585
|
budget.left -= elements.length;
|
|
@@ -3338,7 +3605,7 @@ function expand(elements, page, t, table, stack, posing, budget, times = /* @__P
|
|
|
3338
3605
|
continue;
|
|
3339
3606
|
}
|
|
3340
3607
|
const override0 = stack.length === 0 ? times.get(e.id) : void 0;
|
|
3341
|
-
const was =
|
|
3608
|
+
const was = memo2?.made.get(e);
|
|
3342
3609
|
if (was && was.override === override0 && was.after > 0 && budget.left - (was.before - was.after) > 0) {
|
|
3343
3610
|
budget.left -= was.before - was.after;
|
|
3344
3611
|
for (const x of was.out) out.push(x);
|
|
@@ -3360,7 +3627,7 @@ function expand(elements, page, t, table, stack, posing, budget, times = /* @__P
|
|
|
3360
3627
|
layers: [{ id: e.layerID, name: "", visible: true, locked: false }]
|
|
3361
3628
|
};
|
|
3362
3629
|
for (const x of expand(drawn.elements, drawn, u, table, [...stack, id], posing, budget)) out.push(placed(x, e, symbol));
|
|
3363
|
-
if (
|
|
3630
|
+
if (memo2 && stack.length === 0 && !was) memo2.made.set(e, { override: override0, before, after: budget.left, out: out.slice(from) });
|
|
3364
3631
|
}
|
|
3365
3632
|
return out;
|
|
3366
3633
|
}
|
|
@@ -3413,8 +3680,8 @@ function mix2(x) {
|
|
|
3413
3680
|
return z ^ z >> 31n;
|
|
3414
3681
|
}
|
|
3415
3682
|
function halves(id) {
|
|
3416
|
-
const
|
|
3417
|
-
return [BigInt(`0x${
|
|
3683
|
+
const hex3 = id.replace(/-/g, "").padStart(32, "0").slice(-32);
|
|
3684
|
+
return [BigInt(`0x${hex3.slice(0, 16)}`), BigInt(`0x${hex3.slice(16)}`)];
|
|
3418
3685
|
}
|
|
3419
3686
|
function derivedID(instance, inner) {
|
|
3420
3687
|
const [a, b] = halves(instance), [c, d] = halves(inner);
|
|
@@ -3742,12 +4009,23 @@ function inline(src, style2 = {}) {
|
|
|
3742
4009
|
i += m[0].length;
|
|
3743
4010
|
continue;
|
|
3744
4011
|
}
|
|
3745
|
-
if (m = /^(
|
|
4012
|
+
if (m = /^(\*\*\*|___)(?=\S)([\s\S]*?\S)\1(?!\*|_)/.exec(rest)) {
|
|
3746
4013
|
emit();
|
|
3747
|
-
out.push(...inline(m[2], { ...style2, bold: true }));
|
|
4014
|
+
out.push(...inline(m[2], { ...style2, bold: true, italic: true }));
|
|
3748
4015
|
i += m[0].length;
|
|
3749
4016
|
continue;
|
|
3750
4017
|
}
|
|
4018
|
+
if (m = /^(\*\*|__)(?=\S)([\s\S]*?\S)\1/.exec(rest)) {
|
|
4019
|
+
let body = m[2], length = m[0].length;
|
|
4020
|
+
if (m[1] === "**" && rest[length] === "*" && (body.replace(/\*\*/g, "").match(/\*/g) ?? []).length % 2 === 1) {
|
|
4021
|
+
body += "*";
|
|
4022
|
+
length++;
|
|
4023
|
+
}
|
|
4024
|
+
emit();
|
|
4025
|
+
out.push(...inline(body, { ...style2, bold: true }));
|
|
4026
|
+
i += length;
|
|
4027
|
+
continue;
|
|
4028
|
+
}
|
|
3751
4029
|
if ((m = /^(\*|_)(?=\S)([\s\S]*?\S)\1(?!\1)/.exec(rest)) && (m[1] === "*" || !/\w/.test(src[i - 1] ?? ""))) {
|
|
3752
4030
|
emit();
|
|
3753
4031
|
out.push(...inline(m[2], { ...style2, italic: true }));
|
|
@@ -4131,20 +4409,6 @@ function sameStyle(a, b) {
|
|
|
4131
4409
|
return a === b || a.size === b.size && a.bold === b.bold && a.italic === b.italic && a.mono === b.mono && a.strike === b.strike && a.underline === b.underline && a.alpha === b.alpha;
|
|
4132
4410
|
}
|
|
4133
4411
|
|
|
4134
|
-
// src/theme.ts
|
|
4135
|
-
var rgb = (r, g, b) => ({ r, g, b, a: 1 });
|
|
4136
|
-
var themes = [
|
|
4137
|
-
{ id: "paper", name: "Paper", background: rgb(0.984, 0.98, 0.965), ink: rgb(0.12, 0.12, 0.13) },
|
|
4138
|
-
{ id: "white", name: "White", background: rgb(1, 1, 1), ink: rgb(0.12, 0.12, 0.13) },
|
|
4139
|
-
{ id: "sepia", name: "Sepia", background: rgb(0.953, 0.914, 0.824), ink: rgb(0.23, 0.18, 0.13) },
|
|
4140
|
-
{ id: "blueprint", name: "Blueprint", background: rgb(0.106, 0.227, 0.361), ink: rgb(0.91, 0.945, 0.984) },
|
|
4141
|
-
{ id: "chalkboard", name: "Chalkboard", background: rgb(0.169, 0.227, 0.2), ink: rgb(0.945, 0.945, 0.918) },
|
|
4142
|
-
{ id: "midnight", name: "Midnight", background: rgb(0.082, 0.086, 0.102), ink: rgb(0.925, 0.925, 0.94) }
|
|
4143
|
-
];
|
|
4144
|
-
function themeNamed(id) {
|
|
4145
|
-
return themes.find((t) => t.id === id) ?? null;
|
|
4146
|
-
}
|
|
4147
|
-
|
|
4148
4412
|
// src/svg.ts
|
|
4149
4413
|
function bounds(page, padding = 24) {
|
|
4150
4414
|
if (hasInstances(page)) return bounds(expandingSymbols(page, 0), padding);
|
|
@@ -4210,7 +4474,7 @@ function svgOpen(b, background, paint) {
|
|
|
4210
4474
|
}
|
|
4211
4475
|
function svgParts(page, background, fixed, links = false, only) {
|
|
4212
4476
|
if (hasInstances(page)) return svgParts(expandingSymbols(page, 0), background, fixed, links, only);
|
|
4213
|
-
const theme =
|
|
4477
|
+
const theme = pageTheme(page);
|
|
4214
4478
|
const bg = background ? theme?.background ?? background : null;
|
|
4215
4479
|
const ink = theme?.ink ?? black;
|
|
4216
4480
|
const d = { ...page, elements: page.elements.map((e) => resolvingInk(e, ink)) };
|
|
@@ -4246,7 +4510,7 @@ ${body}</a>
|
|
|
4246
4510
|
}
|
|
4247
4511
|
function svg(page, background = { r: 1, g: 1, b: 1, a: 1 }, fixed) {
|
|
4248
4512
|
const { bounds: b, parts } = svgParts(page, background, fixed, true);
|
|
4249
|
-
return svgOpen(b,
|
|
4513
|
+
return svgOpen(b, pageTheme(page)?.background ?? background, background !== null) + parts.map((p) => p.markup).join("") + "</svg>\n";
|
|
4250
4514
|
}
|
|
4251
4515
|
function labelRect(e, index) {
|
|
4252
4516
|
const m = midpoint(e, index);
|
|
@@ -4340,7 +4604,7 @@ function svgElement(e, index, labelBackground, page) {
|
|
|
4340
4604
|
}
|
|
4341
4605
|
s += `<path d="${outline(e).data()}" fill="none" ${strokeAttrs}/>
|
|
4342
4606
|
`;
|
|
4343
|
-
if (text) s += e.kind === "note" ? noteMarkup(text, e) : textElement(text, e.kind === "path" ? pathLabelBox(e) : frame(e), e, true);
|
|
4607
|
+
if (text) s += e.kind === "note" ? noteMarkup(text, e) : textElement(text, e.kind === "path" || e.kind === "rectangle" ? pathLabelBox(e) : frame(e), e, true);
|
|
4344
4608
|
return s;
|
|
4345
4609
|
}
|
|
4346
4610
|
default:
|
|
@@ -4568,7 +4832,7 @@ var Playback = class {
|
|
|
4568
4832
|
this.sceneNames = (page.timeline?.markers ?? []).map((m) => m.name);
|
|
4569
4833
|
this.sceneLoops = (page.timeline?.markers ?? []).map((m) => m.loop === true);
|
|
4570
4834
|
this.state = { ...page.variables ?? {} };
|
|
4571
|
-
const theme =
|
|
4835
|
+
const theme = pageTheme(page);
|
|
4572
4836
|
this.background = theme?.background ?? WHITE;
|
|
4573
4837
|
this.ink = theme?.ink ?? { r: 0.12, g: 0.12, b: 0.13, a: 1 };
|
|
4574
4838
|
const ns = "http://www.w3.org/2000/svg";
|
|
@@ -5222,7 +5486,7 @@ function inspectFrame(page, t) {
|
|
|
5222
5486
|
const [a, b] = endpoints(e, index);
|
|
5223
5487
|
d.start = pt(a);
|
|
5224
5488
|
d.end = pt(b);
|
|
5225
|
-
d.route = routePoints(
|
|
5489
|
+
d.route = routePoints(route2(e, index)).map(pt);
|
|
5226
5490
|
}
|
|
5227
5491
|
return d;
|
|
5228
5492
|
});
|
|
@@ -5261,7 +5525,7 @@ function render(source, options = {}) {
|
|
|
5261
5525
|
function isFile(v) {
|
|
5262
5526
|
return typeof v === "object" && v !== null && Array.isArray(v.pages) && Array.isArray(v.warnings);
|
|
5263
5527
|
}
|
|
5264
|
-
var VERSION = "0.
|
|
5528
|
+
var VERSION = "0.10.0";
|
|
5265
5529
|
export {
|
|
5266
5530
|
BOIL_DRAWINGS,
|
|
5267
5531
|
BUNDLED_FONTS,
|
|
@@ -5297,6 +5561,8 @@ export {
|
|
|
5297
5561
|
luminance,
|
|
5298
5562
|
orderedElements,
|
|
5299
5563
|
pageIndex,
|
|
5564
|
+
pageTheme,
|
|
5565
|
+
paletteColor,
|
|
5300
5566
|
parseDottie,
|
|
5301
5567
|
plan,
|
|
5302
5568
|
posterTime,
|