@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-player.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 __export = (target, all) => {
|
|
@@ -44,6 +44,8 @@ __export(index_exports, {
|
|
|
44
44
|
luminance: () => luminance,
|
|
45
45
|
orderedElements: () => orderedElements,
|
|
46
46
|
pageIndex: () => pageIndex,
|
|
47
|
+
pageTheme: () => pageTheme,
|
|
48
|
+
paletteColor: () => paletteColor,
|
|
47
49
|
parseDottie: () => parseDottie,
|
|
48
50
|
plan: () => plan,
|
|
49
51
|
posterTime: () => posterTime,
|
|
@@ -197,19 +199,80 @@ function trim(s) {
|
|
|
197
199
|
return s.replace(/^[ \t ]+|[ \t ]+$/g, "");
|
|
198
200
|
}
|
|
199
201
|
|
|
202
|
+
// src/theme.ts
|
|
203
|
+
var rgb = (r, g, b) => ({ r, g, b, a: 1 });
|
|
204
|
+
function hex(h) {
|
|
205
|
+
const n = parseInt(h.slice(1), 16);
|
|
206
|
+
return { r: (n >> 16 & 255) / 255, g: (n >> 8 & 255) / 255, b: (n & 255) / 255, a: 1 };
|
|
207
|
+
}
|
|
208
|
+
var PALETTE_NAMES = ["accent", "muted", "danger", "warning", "success", "info"];
|
|
209
|
+
var palette = (colors) => PALETTE_NAMES.map((name, i) => ({ name, color: hex(colors[i]) }));
|
|
210
|
+
var LIGHT_PALETTE = palette(["#2563eb", "#6b7280", "#dc2626", "#d97706", "#16a34a", "#0891b2"]);
|
|
211
|
+
var DARK_PALETTE = palette(["#93c5fd", "#cbd5e1", "#fca5a5", "#fcd34d", "#86efac", "#67e8f9"]);
|
|
212
|
+
var themes = [
|
|
213
|
+
{ id: "paper", name: "Paper", background: rgb(0.984, 0.98, 0.965), ink: rgb(0.12, 0.12, 0.13), palette: LIGHT_PALETTE },
|
|
214
|
+
{ id: "white", name: "White", background: rgb(1, 1, 1), ink: rgb(0.12, 0.12, 0.13), palette: LIGHT_PALETTE },
|
|
215
|
+
{
|
|
216
|
+
id: "sepia",
|
|
217
|
+
name: "Sepia",
|
|
218
|
+
background: rgb(0.953, 0.914, 0.824),
|
|
219
|
+
ink: rgb(0.23, 0.18, 0.13),
|
|
220
|
+
palette: palette(["#9a3412", "#78716c", "#b91c1c", "#b45309", "#4d7c0f", "#0e7490"])
|
|
221
|
+
},
|
|
222
|
+
{ id: "blueprint", name: "Blueprint", background: rgb(0.106, 0.227, 0.361), ink: rgb(0.91, 0.945, 0.984), palette: DARK_PALETTE },
|
|
223
|
+
{ id: "chalkboard", name: "Chalkboard", background: rgb(0.169, 0.227, 0.2), ink: rgb(0.945, 0.945, 0.918), palette: DARK_PALETTE },
|
|
224
|
+
{ id: "midnight", name: "Midnight", background: rgb(0.082, 0.086, 0.102), ink: rgb(0.925, 0.925, 0.94), palette: DARK_PALETTE }
|
|
225
|
+
];
|
|
226
|
+
function themeNamed(id) {
|
|
227
|
+
return themes.find((t) => t.id === id) ?? null;
|
|
228
|
+
}
|
|
229
|
+
function pageTheme(page) {
|
|
230
|
+
const c = page.customTheme;
|
|
231
|
+
if (c) return { id: "custom", name: c.name, background: c.background, ink: c.ink, palette: c.palette };
|
|
232
|
+
return themeNamed(page.theme);
|
|
233
|
+
}
|
|
234
|
+
function paletteColor(page, name) {
|
|
235
|
+
const n = name.trim().toLowerCase();
|
|
236
|
+
return (pageTheme(page)?.palette ?? LIGHT_PALETTE).find((p) => p.name.toLowerCase() === n)?.color ?? null;
|
|
237
|
+
}
|
|
238
|
+
function resolvingPalette(page) {
|
|
239
|
+
const named = (e) => !!e.style.named;
|
|
240
|
+
if (!page.elements.some(named) && !(page.symbols ?? []).some((s) => s.elements.some(named))) return page;
|
|
241
|
+
const resolve2 = (e) => {
|
|
242
|
+
const n = e.style.named;
|
|
243
|
+
if (!n) return e;
|
|
244
|
+
const style2 = { ...e.style };
|
|
245
|
+
const f = n.fill !== null ? paletteColor(page, n.fill) : null;
|
|
246
|
+
const s = n.stroke !== null ? paletteColor(page, n.stroke) : null;
|
|
247
|
+
const t = n.textColor !== null ? paletteColor(page, n.textColor) : null;
|
|
248
|
+
if (f) style2.fill = { ...f };
|
|
249
|
+
if (s) style2.stroke = { ...s };
|
|
250
|
+
if (t) style2.textColor = { ...t };
|
|
251
|
+
return { ...e, style: style2 };
|
|
252
|
+
};
|
|
253
|
+
return {
|
|
254
|
+
...page,
|
|
255
|
+
elements: page.elements.map(resolve2),
|
|
256
|
+
symbols: page.symbols ? page.symbols.map((s) => ({ ...s, elements: s.elements.map(resolve2) })) : page.symbols
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
200
260
|
// src/model.ts
|
|
201
261
|
var SUPPORTED_VERSION = 2;
|
|
202
262
|
var KINDS = ["rectangle", "ellipse", "diamond", "text", "connector", "freehand", "path", "note", "image", "symbol"];
|
|
203
263
|
var EASES = ["linear", "easeIn", "easeOut", "easeInOut", "hold", "spring", "bounce", "elastic"];
|
|
204
264
|
var KNOWN_FIELDS = {
|
|
205
265
|
file: ["version", "pages", "images"],
|
|
206
|
-
page: ["id", "name", "layers", "elements", "theme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
|
|
266
|
+
page: ["id", "name", "layers", "elements", "theme", "customTheme", "guidesX", "guidesY", "guidesLocked", "timeline", "symbols", "variables", "flows"],
|
|
207
267
|
flow: ["id", "from", "to", "every", "speed", "color", "size", "when", "spread", "volume", "overrides"],
|
|
208
268
|
flowOverride: ["when", "volume"],
|
|
209
269
|
symbol: ["id", "name", "width", "height", "layers", "elements", "timeline", "button", "params"],
|
|
210
270
|
layer: ["id", "name", "visible", "locked"],
|
|
211
271
|
rgba: ["r", "g", "b", "a"],
|
|
212
|
-
style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "font", "gridSize", "opacity", "dashOffset", "textColor"],
|
|
272
|
+
style: ["stroke", "fill", "fillStyle", "strokeWidth", "dash", "roughness", "bowing", "fontSize", "font", "gridSize", "opacity", "dashOffset", "textColor", "named"],
|
|
273
|
+
colorNames: ["fill", "stroke", "textColor"],
|
|
274
|
+
customTheme: ["name", "background", "ink", "palette", "base"],
|
|
275
|
+
paletteColor: ["name", "color"],
|
|
213
276
|
element: [
|
|
214
277
|
"id",
|
|
215
278
|
"kind",
|
|
@@ -247,8 +310,11 @@ var KNOWN_FIELDS = {
|
|
|
247
310
|
"capacity",
|
|
248
311
|
"delay",
|
|
249
312
|
"queue",
|
|
250
|
-
"gauge"
|
|
313
|
+
"gauge",
|
|
314
|
+
"containerID",
|
|
315
|
+
"container"
|
|
251
316
|
],
|
|
317
|
+
container: ["fixed", "lanes"],
|
|
252
318
|
gauge: ["metric", "of", "max", "warn", "alarm", "style", "label"],
|
|
253
319
|
strokePoint: ["x", "y"],
|
|
254
320
|
subpath: ["closed", "coords"],
|
|
@@ -257,7 +323,7 @@ var KNOWN_FIELDS = {
|
|
|
257
323
|
extensionRef: ["id", "shape", "version", "params"],
|
|
258
324
|
normalizedPoint: ["x", "y"],
|
|
259
325
|
normalizedRect: ["x", "y", "width", "height"],
|
|
260
|
-
connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "cost"],
|
|
326
|
+
connector: ["start", "end", "routing", "startHead", "endHead", "waypoints", "hops", "avoid", "cost"],
|
|
261
327
|
waypoint: ["x", "y"],
|
|
262
328
|
timeline: ["fps", "duration", "boil", "settle", "poster", "tracks", "camera", "markers"],
|
|
263
329
|
track: ["element", "keys", "boil", "follow", "repeats", "march"],
|
|
@@ -344,9 +410,36 @@ var Reader = class {
|
|
|
344
410
|
gridSize: num(s.gridSize) ?? null,
|
|
345
411
|
opacity: num(s.opacity) ?? null,
|
|
346
412
|
dashOffset: num(s.dashOffset) ?? null,
|
|
347
|
-
textColor: rgba(s.textColor) ?? null
|
|
413
|
+
textColor: rgba(s.textColor) ?? null,
|
|
414
|
+
named: this.colorNames(s.named)
|
|
348
415
|
};
|
|
349
416
|
}
|
|
417
|
+
container(v) {
|
|
418
|
+
if (!isObj(v)) return null;
|
|
419
|
+
this.fields(v, "container");
|
|
420
|
+
return { fixed: v.fixed === true ? true : null, lanes: v.lanes === "rows" || v.lanes === "columns" ? v.lanes : null };
|
|
421
|
+
}
|
|
422
|
+
colorNames(v) {
|
|
423
|
+
if (!isObj(v)) return null;
|
|
424
|
+
this.fields(v, "colorNames");
|
|
425
|
+
const n = { fill: str(v.fill) ?? null, stroke: str(v.stroke) ?? null, textColor: str(v.textColor) ?? null };
|
|
426
|
+
return n.fill === null && n.stroke === null && n.textColor === null ? null : n;
|
|
427
|
+
}
|
|
428
|
+
customTheme(v) {
|
|
429
|
+
if (!isObj(v)) return null;
|
|
430
|
+
this.fields(v, "customTheme");
|
|
431
|
+
const background = rgba(v.background), ink = rgba(v.ink);
|
|
432
|
+
if (!background || !ink) {
|
|
433
|
+
this.warn("A custom theme needs a background and an ink; drawn without it");
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
const palette2 = (Array.isArray(v.palette) ? v.palette : []).filter(isObj).flatMap((p) => {
|
|
437
|
+
this.fields(p, "paletteColor");
|
|
438
|
+
const name = str(p.name), color2 = rgba(p.color);
|
|
439
|
+
return name && color2 ? [{ name, color: color2 }] : [];
|
|
440
|
+
});
|
|
441
|
+
return { name: str(v.name) ?? "Custom", background, ink, palette: palette2, base: str(v.base) ?? null };
|
|
442
|
+
}
|
|
350
443
|
endpoint(v) {
|
|
351
444
|
const e = isObj(v) ? v : {};
|
|
352
445
|
const port = str(e.port);
|
|
@@ -378,6 +471,7 @@ var Reader = class {
|
|
|
378
471
|
return { x: num(w.x) ?? 0, y: num(w.y) ?? 0 };
|
|
379
472
|
}) : null,
|
|
380
473
|
hops: typeof v.hops === "boolean" ? v.hops : null,
|
|
474
|
+
avoid: typeof v.avoid === "boolean" ? v.avoid : null,
|
|
381
475
|
cost: typeof v.cost === "number" && Number.isFinite(v.cost) ? v.cost : null
|
|
382
476
|
};
|
|
383
477
|
}
|
|
@@ -446,7 +540,9 @@ var Reader = class {
|
|
|
446
540
|
capacity: num(v.capacity) ?? null,
|
|
447
541
|
delay: num(v.delay) ?? null,
|
|
448
542
|
queue: v.queue === true ? true : null,
|
|
449
|
-
gauge: this.gauge(v.gauge)
|
|
543
|
+
gauge: this.gauge(v.gauge),
|
|
544
|
+
containerID: uuid(v.containerID) ?? null,
|
|
545
|
+
container: this.container(v.container)
|
|
450
546
|
};
|
|
451
547
|
}
|
|
452
548
|
gauge(v) {
|
|
@@ -667,6 +763,7 @@ var Reader = class {
|
|
|
667
763
|
layers,
|
|
668
764
|
elements: (Array.isArray(v.elements) ? v.elements : []).map((e) => this.element(e, images)).filter((e) => e !== null),
|
|
669
765
|
theme: str(v.theme) ?? null,
|
|
766
|
+
customTheme: this.customTheme(v.customTheme),
|
|
670
767
|
timeline: this.timeline(v.timeline),
|
|
671
768
|
symbols: Array.isArray(v.symbols) ? v.symbols.map((x) => this.symbol(x, images)).filter((x) => x !== null) : null,
|
|
672
769
|
variables: this.variables(v.variables),
|
|
@@ -730,7 +827,7 @@ function parseDottie(source) {
|
|
|
730
827
|
if (isObj(v) && typeof v.data === "string") images[k] = reader.picture(v.data, str(v.format));
|
|
731
828
|
}
|
|
732
829
|
}
|
|
733
|
-
const pages = json.pages.map((p, i) => reader.page(p, images, i + 1));
|
|
830
|
+
const pages = json.pages.map((p, i) => resolvingPalette(reader.page(p, images, i + 1)));
|
|
734
831
|
if (new Set(pages.map((p) => p.id)).size !== pages.length) throw new DottieFormatError("Two pages share an id");
|
|
735
832
|
return { version, pages, warnings: reader.warnings };
|
|
736
833
|
}
|
|
@@ -750,7 +847,8 @@ function cloneElement(e) {
|
|
|
750
847
|
...e.style,
|
|
751
848
|
stroke: { ...e.style.stroke },
|
|
752
849
|
fill: { ...e.style.fill },
|
|
753
|
-
textColor: e.style.textColor ? { ...e.style.textColor } : null
|
|
850
|
+
textColor: e.style.textColor ? { ...e.style.textColor } : null,
|
|
851
|
+
named: e.style.named ? { ...e.style.named } : e.style.named
|
|
754
852
|
},
|
|
755
853
|
connector: e.connector ? {
|
|
756
854
|
...e.connector,
|
|
@@ -1240,6 +1338,165 @@ function shapePath(e) {
|
|
|
1240
1338
|
return path;
|
|
1241
1339
|
}
|
|
1242
1340
|
|
|
1341
|
+
// src/elbow.ts
|
|
1342
|
+
var MARGIN = 16;
|
|
1343
|
+
var BEND = 24;
|
|
1344
|
+
var SMALLEST = 24;
|
|
1345
|
+
var MOST = 48;
|
|
1346
|
+
function obstacle(e) {
|
|
1347
|
+
if (e.kind === "connector" || e.kind === "text" || e.kind === "freehand") return null;
|
|
1348
|
+
if (e.kind === "path" && !e.extension) return null;
|
|
1349
|
+
if (e.style.opacity !== null && e.style.opacity <= 0) return null;
|
|
1350
|
+
const r = rotatedBounds(e);
|
|
1351
|
+
return r.width < SMALLEST || r.height < SMALLEST ? null : r;
|
|
1352
|
+
}
|
|
1353
|
+
function crosses(points, r) {
|
|
1354
|
+
const x1 = r.x + r.width, y1 = r.y + r.height;
|
|
1355
|
+
for (let k = 1; k < points.length; k++) {
|
|
1356
|
+
const p = points[k - 1], q = points[k];
|
|
1357
|
+
if (p.y === q.y) {
|
|
1358
|
+
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;
|
|
1359
|
+
} else if (p.x === q.x) {
|
|
1360
|
+
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;
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
return false;
|
|
1364
|
+
}
|
|
1365
|
+
var padded = (r) => ({ x: r.x - MARGIN, y: r.y - MARGIN, width: r.width + 2 * MARGIN, height: r.height + 2 * MARGIN });
|
|
1366
|
+
var inside = (p, r) => r.x < p.x && p.x < r.x + r.width && r.y < p.y && p.y < r.y + r.height;
|
|
1367
|
+
var memo = /* @__PURE__ */ new Map();
|
|
1368
|
+
function avoiding(plain, a, b, startVertical, endVertical, elements, except) {
|
|
1369
|
+
const usable = (r) => !inside(a, padded(r)) && !inside(b, padded(r));
|
|
1370
|
+
const all = [];
|
|
1371
|
+
let crossed = false;
|
|
1372
|
+
for (const e of elements) {
|
|
1373
|
+
if (except.has(e.id)) continue;
|
|
1374
|
+
const r = obstacle(e);
|
|
1375
|
+
if (!r || !usable(r)) continue;
|
|
1376
|
+
all.push(r);
|
|
1377
|
+
if (!crossed && crosses(plain, r)) crossed = true;
|
|
1378
|
+
}
|
|
1379
|
+
if (!crossed) return plain;
|
|
1380
|
+
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])]);
|
|
1381
|
+
const hit = memo.get(key);
|
|
1382
|
+
if (hit) return hit;
|
|
1383
|
+
const out = route(plain, a, b, startVertical, endVertical, all);
|
|
1384
|
+
if (memo.size >= 512) memo.clear();
|
|
1385
|
+
memo.set(key, out);
|
|
1386
|
+
return out;
|
|
1387
|
+
}
|
|
1388
|
+
function route(plain, a, b, startVertical, endVertical, usable) {
|
|
1389
|
+
let chosen = usable.map((_, i) => i).filter((i) => crosses(plain, usable[i]));
|
|
1390
|
+
if (chosen.length === 0) return plain;
|
|
1391
|
+
for (let round = 0; round < 4; round++) {
|
|
1392
|
+
if (chosen.length > MOST) return plain;
|
|
1393
|
+
const path = grid(a, b, startVertical, endVertical, chosen.map((i) => padded(usable[i])));
|
|
1394
|
+
if (!path) return plain;
|
|
1395
|
+
const more = usable.map((_, i) => i).filter((i) => !chosen.includes(i) && crosses(path, usable[i]));
|
|
1396
|
+
if (more.length === 0) return path;
|
|
1397
|
+
chosen = [...chosen, ...more].sort((p, q) => p - q);
|
|
1398
|
+
}
|
|
1399
|
+
return plain;
|
|
1400
|
+
}
|
|
1401
|
+
function grid(a, b, startVertical, endVertical, boxes) {
|
|
1402
|
+
let xs = [a.x, b.x, (a.x + b.x) / 2], ys = [a.y, b.y, (a.y + b.y) / 2];
|
|
1403
|
+
for (const r of boxes) {
|
|
1404
|
+
xs.push(r.x, r.x + r.width);
|
|
1405
|
+
ys.push(r.y, r.y + r.height);
|
|
1406
|
+
}
|
|
1407
|
+
xs = [...new Set(xs)].sort((p, q) => p - q);
|
|
1408
|
+
ys = [...new Set(ys)].sort((p, q) => p - q);
|
|
1409
|
+
const nx = xs.length, ny = ys.length;
|
|
1410
|
+
const ia = xs.indexOf(a.x), ja = ys.indexOf(a.y), ib = xs.indexOf(b.x), jb = ys.indexOf(b.y);
|
|
1411
|
+
if (ia < 0 || ja < 0 || ib < 0 || jb < 0) return null;
|
|
1412
|
+
const at = new Map(xs.map((x, k) => [x, k])), bt = new Map(ys.map((y, k) => [y, k]));
|
|
1413
|
+
const inner = new Uint8Array(nx * ny), acrossBlocked = new Uint8Array(nx * ny), downBlocked = new Uint8Array(nx * ny);
|
|
1414
|
+
for (const r of boxes) {
|
|
1415
|
+
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);
|
|
1416
|
+
if (i0 === void 0 || i1 === void 0 || j0 === void 0 || j1 === void 0) continue;
|
|
1417
|
+
for (let i = i0; i < i1; i++) for (let j = j0; j < j1; j++) {
|
|
1418
|
+
if (j > j0) acrossBlocked[i * ny + j] = 1;
|
|
1419
|
+
if (i > i0) downBlocked[i * ny + j] = 1;
|
|
1420
|
+
if (i > i0 && j > j0) inner[i * ny + j] = 1;
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
const blocked = (i, j) => inner[i * ny + j] === 1;
|
|
1424
|
+
const across = (i0, i1, j) => acrossBlocked[Math.min(i0, i1) * ny + j] === 1;
|
|
1425
|
+
const down = (j0, j1, i) => downBlocked[i * ny + Math.min(j0, j1)] === 1;
|
|
1426
|
+
const count = nx * ny * 2;
|
|
1427
|
+
const dist = new Array(count).fill(Infinity), prev = new Array(count).fill(-1);
|
|
1428
|
+
const done = new Array(count).fill(false);
|
|
1429
|
+
const heap = new Frontier();
|
|
1430
|
+
const first = (ia * ny + ja) * 2 + (startVertical ? 1 : 0);
|
|
1431
|
+
dist[first] = 0;
|
|
1432
|
+
heap.push(0, first);
|
|
1433
|
+
const want = (ib * ny + jb) * 2 + (endVertical ? 1 : 0);
|
|
1434
|
+
for (let top = heap.pop(); top; top = heap.pop()) {
|
|
1435
|
+
const [cost, s] = top;
|
|
1436
|
+
if (done[s]) continue;
|
|
1437
|
+
done[s] = true;
|
|
1438
|
+
if (s === want) break;
|
|
1439
|
+
const node = Math.floor(s / 2), axis = s % 2, i = Math.floor(node / ny), j = node % ny;
|
|
1440
|
+
for (const [di, dj] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) {
|
|
1441
|
+
const ni = i + di, nj = j + dj;
|
|
1442
|
+
if (ni < 0 || ni >= nx || nj < 0 || nj >= ny || blocked(ni, nj)) continue;
|
|
1443
|
+
const turn = di !== 0 ? 0 : 1;
|
|
1444
|
+
if (di !== 0 ? across(i, ni, j) : down(j, nj, i)) continue;
|
|
1445
|
+
const length = Math.abs(xs[ni] - xs[i]) + Math.abs(ys[nj] - ys[j]);
|
|
1446
|
+
const c = cost + length + (turn !== axis ? BEND : 0);
|
|
1447
|
+
const t = (ni * ny + nj) * 2 + turn;
|
|
1448
|
+
if (c < dist[t]) {
|
|
1449
|
+
dist[t] = c;
|
|
1450
|
+
prev[t] = s;
|
|
1451
|
+
heap.push(c, t);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
if (!done[want]) return null;
|
|
1456
|
+
const points = [];
|
|
1457
|
+
for (let s = want; s >= 0; s = prev[s]) {
|
|
1458
|
+
const node = Math.floor(s / 2);
|
|
1459
|
+
points.push({ x: xs[Math.floor(node / ny)], y: ys[node % ny] });
|
|
1460
|
+
}
|
|
1461
|
+
return points.reverse();
|
|
1462
|
+
}
|
|
1463
|
+
var Frontier = class {
|
|
1464
|
+
constructor() {
|
|
1465
|
+
__publicField(this, "heap", []);
|
|
1466
|
+
__publicField(this, "next", 0);
|
|
1467
|
+
}
|
|
1468
|
+
less(i, j) {
|
|
1469
|
+
const a = this.heap[i], b = this.heap[j];
|
|
1470
|
+
return a[0] < b[0] || a[0] === b[0] && a[1] < b[1];
|
|
1471
|
+
}
|
|
1472
|
+
push(cost, state) {
|
|
1473
|
+
this.heap.push([cost, this.next++, state]);
|
|
1474
|
+
for (let i = this.heap.length - 1; i > 0; ) {
|
|
1475
|
+
const up = i - 1 >> 1;
|
|
1476
|
+
if (!this.less(i, up)) break;
|
|
1477
|
+
[this.heap[i], this.heap[up]] = [this.heap[up], this.heap[i]];
|
|
1478
|
+
i = up;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
pop() {
|
|
1482
|
+
if (this.heap.length === 0) return null;
|
|
1483
|
+
const top = this.heap[0], last = this.heap.pop();
|
|
1484
|
+
if (this.heap.length > 0) {
|
|
1485
|
+
this.heap[0] = last;
|
|
1486
|
+
for (let i = 0; ; ) {
|
|
1487
|
+
const l = 2 * i + 1, r = l + 1;
|
|
1488
|
+
let m = i;
|
|
1489
|
+
if (l < this.heap.length && this.less(l, m)) m = l;
|
|
1490
|
+
if (r < this.heap.length && this.less(r, m)) m = r;
|
|
1491
|
+
if (m === i) break;
|
|
1492
|
+
[this.heap[i], this.heap[m]] = [this.heap[m], this.heap[i]];
|
|
1493
|
+
i = m;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return [top[0], top[2]];
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
|
|
1243
1500
|
// src/connector.ts
|
|
1244
1501
|
function portPoint(shape, port) {
|
|
1245
1502
|
const r = frame(shape);
|
|
@@ -1383,7 +1640,7 @@ function routeThrough(p, c) {
|
|
|
1383
1640
|
}
|
|
1384
1641
|
}
|
|
1385
1642
|
}
|
|
1386
|
-
function
|
|
1643
|
+
function route2(e, index) {
|
|
1387
1644
|
const c = e.connector;
|
|
1388
1645
|
if (!c) return { kind: "polyline", points: [] };
|
|
1389
1646
|
const [a, b] = endpoints(e, index);
|
|
@@ -1399,16 +1656,19 @@ function route(e, index) {
|
|
|
1399
1656
|
case "elbow": {
|
|
1400
1657
|
const startV = vertical(c.start.port) ?? !horizontal;
|
|
1401
1658
|
const endV = vertical(c.end.port) ?? !horizontal;
|
|
1659
|
+
let plain;
|
|
1402
1660
|
if (startV && endV) {
|
|
1403
1661
|
const my = a.y + dy / 2;
|
|
1404
|
-
|
|
1405
|
-
}
|
|
1406
|
-
if (!startV && !endV) {
|
|
1662
|
+
plain = [a, { x: a.x, y: my }, { x: b.x, y: my }, b];
|
|
1663
|
+
} else if (!startV && !endV) {
|
|
1407
1664
|
const mx = a.x + dx / 2;
|
|
1408
|
-
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
return { kind: "polyline", points:
|
|
1665
|
+
plain = [a, { x: mx, y: a.y }, { x: mx, y: b.y }, b];
|
|
1666
|
+
} else if (startV) plain = [a, { x: a.x, y: b.y }, b];
|
|
1667
|
+
else plain = [a, { x: b.x, y: a.y }, b];
|
|
1668
|
+
if (c.avoid !== true) return { kind: "polyline", points: plain };
|
|
1669
|
+
const ends = new Set([c.start.elementID, c.end.elementID].filter((x) => x !== null));
|
|
1670
|
+
const routed = avoiding(plain, a, b, startV, endV, index.values(), ends);
|
|
1671
|
+
return { kind: "polyline", points: routed === plain ? plain : simplified(routed) };
|
|
1412
1672
|
}
|
|
1413
1673
|
}
|
|
1414
1674
|
}
|
|
@@ -1419,7 +1679,7 @@ function arrowhead(tip, from, size) {
|
|
|
1419
1679
|
return [wing(spread), wing(-spread)];
|
|
1420
1680
|
}
|
|
1421
1681
|
function connectorBounds(e, index) {
|
|
1422
|
-
const pts = routePoints(
|
|
1682
|
+
const pts = routePoints(route2(e, index));
|
|
1423
1683
|
if (pts.length === 0) return { x: 0, y: 0, width: 0, height: 0 };
|
|
1424
1684
|
let x0 = pts[0].x, y0 = pts[0].y, x1 = x0, y1 = y0;
|
|
1425
1685
|
for (const p of pts) {
|
|
@@ -1431,7 +1691,7 @@ function connectorBounds(e, index) {
|
|
|
1431
1691
|
return { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };
|
|
1432
1692
|
}
|
|
1433
1693
|
function midpoint(e, index) {
|
|
1434
|
-
const pts = routePoints(
|
|
1694
|
+
const pts = routePoints(route2(e, index));
|
|
1435
1695
|
if (pts.length <= 1) return pts[0] ?? { x: 0, y: 0 };
|
|
1436
1696
|
const lengths = [];
|
|
1437
1697
|
let total = 0;
|
|
@@ -1580,7 +1840,7 @@ function graphOf(frame2) {
|
|
|
1580
1840
|
graphs.set(els, { members: [...els], graph });
|
|
1581
1841
|
return graph;
|
|
1582
1842
|
}
|
|
1583
|
-
var
|
|
1843
|
+
var Frontier2 = class {
|
|
1584
1844
|
constructor() {
|
|
1585
1845
|
__publicField(this, "heap", []);
|
|
1586
1846
|
}
|
|
@@ -1634,7 +1894,7 @@ function grow({ shapes: shapes2, next }, from, offline, until) {
|
|
|
1634
1894
|
const dist = /* @__PURE__ */ new Map([[from, 0]]), order = /* @__PURE__ */ new Map([[from, 0]]);
|
|
1635
1895
|
let counter = 1;
|
|
1636
1896
|
const tree = new FlowTree(from);
|
|
1637
|
-
const open = new
|
|
1897
|
+
const open = new Frontier2();
|
|
1638
1898
|
open.push(from, 0, 0);
|
|
1639
1899
|
while (open.size > 0) {
|
|
1640
1900
|
const { id: n, order: o } = open.pop();
|
|
@@ -1740,6 +2000,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1740
2000
|
return pts;
|
|
1741
2001
|
};
|
|
1742
2002
|
const metrics2 = emptyMetrics();
|
|
2003
|
+
const routes = /* @__PURE__ */ new Map();
|
|
1743
2004
|
for (const e of frame2.elements) {
|
|
1744
2005
|
if (e.kind === "connector" && !e.connector) continue;
|
|
1745
2006
|
metrics2.elements.set(e.id, { throughput: 0, load: null, delay: e.kind !== "connector" ? delayOf(e) : 0, backlog: 0, inFlight: 0, depth: 0 });
|
|
@@ -1751,7 +2012,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1751
2012
|
if (c !== null && Number.isFinite(c)) room.set(e.id, Math.max(c, 0));
|
|
1752
2013
|
}
|
|
1753
2014
|
const full = () => new Set([...room].filter(([, v]) => v <= TINY).map(([id]) => id));
|
|
1754
|
-
const
|
|
2015
|
+
const route3 = (tree, goal) => {
|
|
1755
2016
|
const hops = [], shapes2 = [];
|
|
1756
2017
|
let at = goal;
|
|
1757
2018
|
for (let step = tree.came.get(at); step; step = tree.came.get(at)) {
|
|
@@ -1763,7 +2024,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1763
2024
|
return { hops: hops.reverse(), shapes: shapes2.reverse() };
|
|
1764
2025
|
};
|
|
1765
2026
|
const way = (hops, shapes2) => {
|
|
1766
|
-
const points = [],
|
|
2027
|
+
const points = [], inside2 = [], stretches = [];
|
|
1767
2028
|
let length = 0;
|
|
1768
2029
|
hops.forEach(([id, back], k) => {
|
|
1769
2030
|
const c = byID.get(id);
|
|
@@ -1774,7 +2035,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1774
2035
|
if (last) {
|
|
1775
2036
|
const gap = Math.hypot(line2[0].x - last.x, line2[0].y - last.y);
|
|
1776
2037
|
const shape = byID.get(shapes2[k]);
|
|
1777
|
-
|
|
2038
|
+
inside2.push([length, length + gap, shape ? delayOf(shape) : 0]);
|
|
1778
2039
|
length += gap;
|
|
1779
2040
|
}
|
|
1780
2041
|
const start2 = length;
|
|
@@ -1782,7 +2043,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1782
2043
|
stretches.push([id, start2, length]);
|
|
1783
2044
|
points.push(...line2);
|
|
1784
2045
|
});
|
|
1785
|
-
return length > 0 ? { line: new Polyline(points), length, inside, stretches } : null;
|
|
2046
|
+
return length > 0 ? { line: new Polyline(points), length, inside: inside2, stretches } : null;
|
|
1786
2047
|
};
|
|
1787
2048
|
const along = (w, elapsedAt, speed) => {
|
|
1788
2049
|
let elapsed = elapsedAt, d = 0;
|
|
@@ -1823,6 +2084,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1823
2084
|
if (flow.when !== null && values !== null && !holds(flow.when, values)) continue;
|
|
1824
2085
|
const source = byID.get(flow.from);
|
|
1825
2086
|
const base2 = source ? baseTree(flow.from) : null;
|
|
2087
|
+
routes.set(flow.id, []);
|
|
1826
2088
|
if (!source || !base2) continue;
|
|
1827
2089
|
const volume = amountIn(flow, values);
|
|
1828
2090
|
const fm = { volume, placed: 0, backlog: 0, backup: 0, transit: null };
|
|
@@ -1837,7 +2099,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1837
2099
|
const tree = flowTree(flow.from, frame2, union2(offline, full()), candidates[0]);
|
|
1838
2100
|
const goal2 = tree?.goals(candidates, false)[0];
|
|
1839
2101
|
if (!tree || goal2 === void 0) break;
|
|
1840
|
-
const r =
|
|
2102
|
+
const r = route3(tree, goal2);
|
|
1841
2103
|
const ids = [...r.shapes, ...r.hops.map(([id]) => id)];
|
|
1842
2104
|
const rooms = ids.filter((id) => room.has(id)).map((id) => room.get(id));
|
|
1843
2105
|
const fits = Math.min(left, rooms.length > 0 ? Math.min(...rooms) : Infinity);
|
|
@@ -1850,7 +2112,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1850
2112
|
let at = flow.from;
|
|
1851
2113
|
const goal = base2.goals(candidates, false)[0];
|
|
1852
2114
|
if (goal !== void 0) {
|
|
1853
|
-
const r =
|
|
2115
|
+
const r = route3(base2, goal), done = full();
|
|
1854
2116
|
const sequence = [[r.shapes[0], r.shapes[0]]];
|
|
1855
2117
|
r.hops.forEach(([id], k) => {
|
|
1856
2118
|
sequence.push([id, r.shapes[k]], [r.shapes[k + 1], r.shapes[k]]);
|
|
@@ -1879,6 +2141,13 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1879
2141
|
else waiting2.push([at, left]);
|
|
1880
2142
|
}
|
|
1881
2143
|
waitingBy.set(flow.id, waiting2);
|
|
2144
|
+
routes.set(flow.id, placements.map((p) => ({
|
|
2145
|
+
goal: p.goal,
|
|
2146
|
+
hops: p.hops,
|
|
2147
|
+
amount: p.amount,
|
|
2148
|
+
waits: p.waits === true,
|
|
2149
|
+
cost: p.hops.reduce((s, [id]) => s + routeCost(byID.get(id)?.connector?.cost ?? null), 0)
|
|
2150
|
+
})));
|
|
1882
2151
|
for (const p of placements) {
|
|
1883
2152
|
for (const id of [...p.shapes, ...p.hops.map(([h]) => h)]) bump(id, (m) => {
|
|
1884
2153
|
m.throughput += p.amount;
|
|
@@ -1961,7 +2230,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
1961
2230
|
const tree = flowTree(at, frame2, union2(offline, blocked), flow.to[0]);
|
|
1962
2231
|
const goal = tree?.goals(flow.to, false)[0];
|
|
1963
2232
|
if (!tree || goal === void 0) break;
|
|
1964
|
-
const r =
|
|
2233
|
+
const r = route3(tree, goal);
|
|
1965
2234
|
const ids = [...r.shapes.slice(1), ...r.hops.map(([id]) => id)];
|
|
1966
2235
|
const rooms = ids.filter((id) => trial.has(id)).map((id) => trial.get(id));
|
|
1967
2236
|
const spare = rooms.length > 0 ? Math.min(...rooms) : Infinity;
|
|
@@ -2016,7 +2285,7 @@ function flowFrame(flows, frame2, t, values, offline = /* @__PURE__ */ new Set()
|
|
|
2016
2285
|
if (c === null || !Number.isFinite(c) || !m) continue;
|
|
2017
2286
|
m.load = c > 0 ? m.throughput / c : 1;
|
|
2018
2287
|
}
|
|
2019
|
-
return { packets, metrics: metrics2 };
|
|
2288
|
+
return { packets, metrics: metrics2, routes };
|
|
2020
2289
|
}
|
|
2021
2290
|
var BLANK = {
|
|
2022
2291
|
seed: 1,
|
|
@@ -2110,16 +2379,16 @@ function finishing(elements, metrics2, values, frame2, flows, since = Infinity,
|
|
|
2110
2379
|
}
|
|
2111
2380
|
var gaugeKey = (id) => "gauge|" + id;
|
|
2112
2381
|
var GAUGE_EASE = 1;
|
|
2113
|
-
var
|
|
2382
|
+
var hex2 = (h) => {
|
|
2114
2383
|
const v = parseInt(h.slice(1), 16);
|
|
2115
2384
|
return { r: (v >> 16 & 255) / 255, g: (v >> 8 & 255) / 255, b: (v & 255) / 255, a: 1 };
|
|
2116
2385
|
};
|
|
2117
|
-
var GAUGE_GREEN =
|
|
2118
|
-
var GAUGE_AMBER =
|
|
2119
|
-
var GAUGE_RED =
|
|
2120
|
-
var GAUGE_BLUE =
|
|
2121
|
-
var GAUGE_TRACK =
|
|
2122
|
-
var GAUGE_GRAY =
|
|
2386
|
+
var GAUGE_GREEN = hex2("#16a34a");
|
|
2387
|
+
var GAUGE_AMBER = hex2("#d97706");
|
|
2388
|
+
var GAUGE_RED = hex2("#dc2626");
|
|
2389
|
+
var GAUGE_BLUE = hex2("#2f6fdf");
|
|
2390
|
+
var GAUGE_TRACK = hex2("#e5e7eb");
|
|
2391
|
+
var GAUGE_GRAY = hex2("#9ca3af");
|
|
2123
2392
|
function formatted(metric, v) {
|
|
2124
2393
|
if (v === null || !Number.isFinite(v)) return "\u2013";
|
|
2125
2394
|
switch (metric) {
|
|
@@ -2405,17 +2674,17 @@ function clusterStrokes(c, angle2, size) {
|
|
|
2405
2674
|
});
|
|
2406
2675
|
}
|
|
2407
2676
|
function contains(contours, p) {
|
|
2408
|
-
let
|
|
2677
|
+
let inside2 = false;
|
|
2409
2678
|
for (const poly of contours) {
|
|
2410
2679
|
if (poly.length < 3) continue;
|
|
2411
2680
|
let k = poly.length - 1;
|
|
2412
2681
|
for (let i = 0; i < poly.length; i++) {
|
|
2413
2682
|
const a = poly[i], b = poly[k];
|
|
2414
|
-
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)
|
|
2683
|
+
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;
|
|
2415
2684
|
k = i;
|
|
2416
2685
|
}
|
|
2417
2686
|
}
|
|
2418
|
-
return
|
|
2687
|
+
return inside2;
|
|
2419
2688
|
}
|
|
2420
2689
|
function distance(p, contours) {
|
|
2421
2690
|
let best = Infinity;
|
|
@@ -2692,7 +2961,7 @@ function connectorParts(e, index, page) {
|
|
|
2692
2961
|
const c = e.connector;
|
|
2693
2962
|
if (!c) return [new Path(), new Path()];
|
|
2694
2963
|
const [a, b] = endpoints(e, index);
|
|
2695
|
-
const r =
|
|
2964
|
+
const r = route2(e, index);
|
|
2696
2965
|
const hops = c.hops === true && page ? hopCrossings(e, r, page, index) : [];
|
|
2697
2966
|
const key = [
|
|
2698
2967
|
e.seed,
|
|
@@ -2780,7 +3049,7 @@ function linesBeneath(e, page, index) {
|
|
|
2780
3049
|
}
|
|
2781
3050
|
const count = f.first.get(e.id) ?? f.under.length;
|
|
2782
3051
|
while (f.lines.length < count) {
|
|
2783
|
-
const points = routePoints(
|
|
3052
|
+
const points = routePoints(route2(f.under[f.lines.length], index));
|
|
2784
3053
|
f.lines.push({ points, box: boxOf(points) });
|
|
2785
3054
|
}
|
|
2786
3055
|
return { lines: f.lines, count };
|
|
@@ -3084,7 +3353,7 @@ function followSpan(track, t) {
|
|
|
3084
3353
|
return f;
|
|
3085
3354
|
}
|
|
3086
3355
|
function tracing(e, page, index = indexOf(page)) {
|
|
3087
|
-
if (e.kind === "connector") return new Polyline(routePoints(
|
|
3356
|
+
if (e.kind === "connector") return new Polyline(routePoints(route2(e, index)));
|
|
3088
3357
|
const clean = cloneElement(e);
|
|
3089
3358
|
clean.style.roughness = 0;
|
|
3090
3359
|
const pts = outline(clean).contours()[0] ?? [];
|
|
@@ -3364,10 +3633,10 @@ var Expansions = class {
|
|
|
3364
3633
|
this.posing = posing;
|
|
3365
3634
|
}
|
|
3366
3635
|
};
|
|
3367
|
-
function expandingSymbols(page, t, posing = true, times = /* @__PURE__ */ new Map(),
|
|
3636
|
+
function expandingSymbols(page, t, posing = true, times = /* @__PURE__ */ new Map(), memo2) {
|
|
3368
3637
|
if (!hasInstances(page)) return page;
|
|
3369
3638
|
const budget = { left: MAX_ELEMENTS };
|
|
3370
|
-
const m =
|
|
3639
|
+
const m = memo2 && memo2.page === page && memo2.t === t && memo2.posing === posing ? memo2 : void 0;
|
|
3371
3640
|
return { ...page, elements: expand(page.elements, page, t, symbolTable(page), [], posing, budget, times, m) };
|
|
3372
3641
|
}
|
|
3373
3642
|
function symbolTable(page) {
|
|
@@ -3375,7 +3644,7 @@ function symbolTable(page) {
|
|
|
3375
3644
|
for (const s of page.symbols ?? []) if (!table.has(s.id)) table.set(s.id, s);
|
|
3376
3645
|
return table;
|
|
3377
3646
|
}
|
|
3378
|
-
function expand(elements, page, t, table, stack, posing, budget, times = /* @__PURE__ */ new Map(),
|
|
3647
|
+
function expand(elements, page, t, table, stack, posing, budget, times = /* @__PURE__ */ new Map(), memo2) {
|
|
3379
3648
|
const instances = new Set(elements.filter((e) => e.kind === "symbol").map((e) => e.id));
|
|
3380
3649
|
if (instances.size === 0) {
|
|
3381
3650
|
budget.left -= elements.length;
|
|
@@ -3401,7 +3670,7 @@ function expand(elements, page, t, table, stack, posing, budget, times = /* @__P
|
|
|
3401
3670
|
continue;
|
|
3402
3671
|
}
|
|
3403
3672
|
const override0 = stack.length === 0 ? times.get(e.id) : void 0;
|
|
3404
|
-
const was =
|
|
3673
|
+
const was = memo2?.made.get(e);
|
|
3405
3674
|
if (was && was.override === override0 && was.after > 0 && budget.left - (was.before - was.after) > 0) {
|
|
3406
3675
|
budget.left -= was.before - was.after;
|
|
3407
3676
|
for (const x of was.out) out.push(x);
|
|
@@ -3423,7 +3692,7 @@ function expand(elements, page, t, table, stack, posing, budget, times = /* @__P
|
|
|
3423
3692
|
layers: [{ id: e.layerID, name: "", visible: true, locked: false }]
|
|
3424
3693
|
};
|
|
3425
3694
|
for (const x of expand(drawn.elements, drawn, u, table, [...stack, id], posing, budget)) out.push(placed(x, e, symbol));
|
|
3426
|
-
if (
|
|
3695
|
+
if (memo2 && stack.length === 0 && !was) memo2.made.set(e, { override: override0, before, after: budget.left, out: out.slice(from) });
|
|
3427
3696
|
}
|
|
3428
3697
|
return out;
|
|
3429
3698
|
}
|
|
@@ -3476,8 +3745,8 @@ function mix2(x) {
|
|
|
3476
3745
|
return z ^ z >> 31n;
|
|
3477
3746
|
}
|
|
3478
3747
|
function halves(id) {
|
|
3479
|
-
const
|
|
3480
|
-
return [BigInt(`0x${
|
|
3748
|
+
const hex3 = id.replace(/-/g, "").padStart(32, "0").slice(-32);
|
|
3749
|
+
return [BigInt(`0x${hex3.slice(0, 16)}`), BigInt(`0x${hex3.slice(16)}`)];
|
|
3481
3750
|
}
|
|
3482
3751
|
function derivedID(instance, inner) {
|
|
3483
3752
|
const [a, b] = halves(instance), [c, d] = halves(inner);
|
|
@@ -3805,12 +4074,23 @@ function inline(src, style2 = {}) {
|
|
|
3805
4074
|
i += m[0].length;
|
|
3806
4075
|
continue;
|
|
3807
4076
|
}
|
|
3808
|
-
if (m = /^(
|
|
4077
|
+
if (m = /^(\*\*\*|___)(?=\S)([\s\S]*?\S)\1(?!\*|_)/.exec(rest)) {
|
|
3809
4078
|
emit();
|
|
3810
|
-
out.push(...inline(m[2], { ...style2, bold: true }));
|
|
4079
|
+
out.push(...inline(m[2], { ...style2, bold: true, italic: true }));
|
|
3811
4080
|
i += m[0].length;
|
|
3812
4081
|
continue;
|
|
3813
4082
|
}
|
|
4083
|
+
if (m = /^(\*\*|__)(?=\S)([\s\S]*?\S)\1/.exec(rest)) {
|
|
4084
|
+
let body = m[2], length = m[0].length;
|
|
4085
|
+
if (m[1] === "**" && rest[length] === "*" && (body.replace(/\*\*/g, "").match(/\*/g) ?? []).length % 2 === 1) {
|
|
4086
|
+
body += "*";
|
|
4087
|
+
length++;
|
|
4088
|
+
}
|
|
4089
|
+
emit();
|
|
4090
|
+
out.push(...inline(body, { ...style2, bold: true }));
|
|
4091
|
+
i += length;
|
|
4092
|
+
continue;
|
|
4093
|
+
}
|
|
3814
4094
|
if ((m = /^(\*|_)(?=\S)([\s\S]*?\S)\1(?!\1)/.exec(rest)) && (m[1] === "*" || !/\w/.test(src[i - 1] ?? ""))) {
|
|
3815
4095
|
emit();
|
|
3816
4096
|
out.push(...inline(m[2], { ...style2, italic: true }));
|
|
@@ -4194,20 +4474,6 @@ function sameStyle(a, b) {
|
|
|
4194
4474
|
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;
|
|
4195
4475
|
}
|
|
4196
4476
|
|
|
4197
|
-
// src/theme.ts
|
|
4198
|
-
var rgb = (r, g, b) => ({ r, g, b, a: 1 });
|
|
4199
|
-
var themes = [
|
|
4200
|
-
{ id: "paper", name: "Paper", background: rgb(0.984, 0.98, 0.965), ink: rgb(0.12, 0.12, 0.13) },
|
|
4201
|
-
{ id: "white", name: "White", background: rgb(1, 1, 1), ink: rgb(0.12, 0.12, 0.13) },
|
|
4202
|
-
{ id: "sepia", name: "Sepia", background: rgb(0.953, 0.914, 0.824), ink: rgb(0.23, 0.18, 0.13) },
|
|
4203
|
-
{ id: "blueprint", name: "Blueprint", background: rgb(0.106, 0.227, 0.361), ink: rgb(0.91, 0.945, 0.984) },
|
|
4204
|
-
{ id: "chalkboard", name: "Chalkboard", background: rgb(0.169, 0.227, 0.2), ink: rgb(0.945, 0.945, 0.918) },
|
|
4205
|
-
{ id: "midnight", name: "Midnight", background: rgb(0.082, 0.086, 0.102), ink: rgb(0.925, 0.925, 0.94) }
|
|
4206
|
-
];
|
|
4207
|
-
function themeNamed(id) {
|
|
4208
|
-
return themes.find((t) => t.id === id) ?? null;
|
|
4209
|
-
}
|
|
4210
|
-
|
|
4211
4477
|
// src/svg.ts
|
|
4212
4478
|
function bounds(page, padding = 24) {
|
|
4213
4479
|
if (hasInstances(page)) return bounds(expandingSymbols(page, 0), padding);
|
|
@@ -4273,7 +4539,7 @@ function svgOpen(b, background, paint) {
|
|
|
4273
4539
|
}
|
|
4274
4540
|
function svgParts(page, background, fixed, links = false, only) {
|
|
4275
4541
|
if (hasInstances(page)) return svgParts(expandingSymbols(page, 0), background, fixed, links, only);
|
|
4276
|
-
const theme =
|
|
4542
|
+
const theme = pageTheme(page);
|
|
4277
4543
|
const bg = background ? theme?.background ?? background : null;
|
|
4278
4544
|
const ink = theme?.ink ?? black;
|
|
4279
4545
|
const d = { ...page, elements: page.elements.map((e) => resolvingInk(e, ink)) };
|
|
@@ -4309,7 +4575,7 @@ ${body}</a>
|
|
|
4309
4575
|
}
|
|
4310
4576
|
function svg(page, background = { r: 1, g: 1, b: 1, a: 1 }, fixed) {
|
|
4311
4577
|
const { bounds: b, parts } = svgParts(page, background, fixed, true);
|
|
4312
|
-
return svgOpen(b,
|
|
4578
|
+
return svgOpen(b, pageTheme(page)?.background ?? background, background !== null) + parts.map((p) => p.markup).join("") + "</svg>\n";
|
|
4313
4579
|
}
|
|
4314
4580
|
function labelRect(e, index) {
|
|
4315
4581
|
const m = midpoint(e, index);
|
|
@@ -4403,7 +4669,7 @@ function svgElement(e, index, labelBackground, page) {
|
|
|
4403
4669
|
}
|
|
4404
4670
|
s += `<path d="${outline(e).data()}" fill="none" ${strokeAttrs}/>
|
|
4405
4671
|
`;
|
|
4406
|
-
if (text) s += e.kind === "note" ? noteMarkup(text, e) : textElement(text, e.kind === "path" ? pathLabelBox(e) : frame(e), e, true);
|
|
4672
|
+
if (text) s += e.kind === "note" ? noteMarkup(text, e) : textElement(text, e.kind === "path" || e.kind === "rectangle" ? pathLabelBox(e) : frame(e), e, true);
|
|
4407
4673
|
return s;
|
|
4408
4674
|
}
|
|
4409
4675
|
default:
|
|
@@ -4646,7 +4912,7 @@ var Playback = class {
|
|
|
4646
4912
|
this.sceneNames = (page.timeline?.markers ?? []).map((m) => m.name);
|
|
4647
4913
|
this.sceneLoops = (page.timeline?.markers ?? []).map((m) => m.loop === true);
|
|
4648
4914
|
this.state = { ...page.variables ?? {} };
|
|
4649
|
-
const theme =
|
|
4915
|
+
const theme = pageTheme(page);
|
|
4650
4916
|
this.background = theme?.background ?? WHITE;
|
|
4651
4917
|
this.ink = theme?.ink ?? { r: 0.12, g: 0.12, b: 0.13, a: 1 };
|
|
4652
4918
|
const ns = "http://www.w3.org/2000/svg";
|
|
@@ -5300,7 +5566,7 @@ function inspectFrame(page, t) {
|
|
|
5300
5566
|
const [a, b] = endpoints(e, index);
|
|
5301
5567
|
d.start = pt(a);
|
|
5302
5568
|
d.end = pt(b);
|
|
5303
|
-
d.route = routePoints(
|
|
5569
|
+
d.route = routePoints(route2(e, index)).map(pt);
|
|
5304
5570
|
}
|
|
5305
5571
|
return d;
|
|
5306
5572
|
});
|
|
@@ -5339,7 +5605,7 @@ function render(source, options = {}) {
|
|
|
5339
5605
|
function isFile(v) {
|
|
5340
5606
|
return typeof v === "object" && v !== null && Array.isArray(v.pages) && Array.isArray(v.warnings);
|
|
5341
5607
|
}
|
|
5342
|
-
var VERSION = "0.
|
|
5608
|
+
var VERSION = "0.10.0";
|
|
5343
5609
|
|
|
5344
5610
|
// src/player-entry.ts
|
|
5345
5611
|
servePlans();
|
|
@@ -5380,6 +5646,8 @@ export {
|
|
|
5380
5646
|
luminance,
|
|
5381
5647
|
orderedElements,
|
|
5382
5648
|
pageIndex,
|
|
5649
|
+
pageTheme,
|
|
5650
|
+
paletteColor,
|
|
5383
5651
|
parseDottie,
|
|
5384
5652
|
plan,
|
|
5385
5653
|
posterTime,
|