@cardenelabs/dragon 0.36.3 → 0.37.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/dist/cli.js CHANGED
@@ -275,13 +275,46 @@ var LOOK = {
275
275
  region: { pad: 18, gap: 10, radius: 14, inset: 14, icon: 24, iconRadius: 7, iconScale: 0.68, nameY: 58, line: 16, minH: 108 },
276
276
  architecture: { columns: 4, columnGap: 56, maxColumnGap: 160, rowGap: 44, labelRoom: 16 },
277
277
  sequence: { columnGap: 40, labelRoom: 16, firstRow: 22, rowGap: 14, stepGap: 8, minPitch: 40, tail: 18, selfW: 34, selfH: 18 },
278
- edge: { inset: 3, arrow: 6, arrowHalf: 3.5, parallel: 5, ghostDash: 5, flowDash: 9 },
278
+ /**
279
+ * 状態遷移図 (#3163)。状態は `columns` つずつ並べて次の段へ折り返し、段の間 (`rowGap`) の真ん中を、段をまたぐ線が通る。
280
+ * `start` と `end` は始まりと終わりの印の半径と、印の中の丸の半径。`drop` は最初の状態の上端から始まりの印の中心まで、
281
+ * `below` は状態の下端から終わりの印の中心まで、`beside` は状態の右端から右に置く終わりの印の中心まで、`text` は印の中心から字の左端まで。
282
+ * `loop` は同じ状態へ戻る輪の幅と深さ。`side` は脇道の囲みの内側の余白、1 段目の上端との間、脇道へ入る線が横に通る所の囲みの下端からの離れ、
283
+ * 点線の線が箱へ入る所を箱の端から離す幅。
284
+ * `ghost` は脇道の点線の札で、絵柄を左に、名前と下の字を右に並べる (#3171)。`h` は札の高さ、`pad` は左右の余白、`gap` は絵柄と字の間、
285
+ * `nameY` と `subY` は札の真ん中から名前と下の字の基準線まで。
286
+ * `done` は出た状態の右上の済んだ印の半径と、箱の右上の角からの離れ。
287
+ * `loop` の `samples` は同じ状態へ戻る弧を区切る点の数、`badgeAt` は弧の段の番号を弧の上端から深さのどこに置くかの割合。
288
+ * `pastLabel` は段が終わった後に薄く残す線の名前の濃さ (#3171)
289
+ */
290
+ state: {
291
+ columns: 4,
292
+ columnGap: 64,
293
+ rowGap: 108,
294
+ labelRoom: 16,
295
+ start: 7,
296
+ end: { r: 9, inner: 5 },
297
+ drop: 56,
298
+ below: 64,
299
+ beside: 38,
300
+ text: 16,
301
+ loop: { w: 24, h: 34, samples: 12, badgeAt: 0.6 },
302
+ side: { pad: 16, gap: 76, lane: 30, entry: 28 },
303
+ ghost: { h: 52, pad: 12, gap: 10, nameY: -2, subY: 14 },
304
+ done: { r: 6.5, inset: 13 },
305
+ pastLabel: 0.85
306
+ },
307
+ /** `bend` は線の曲がりを丸める半径 (#3171) */
308
+ edge: { inset: 3, arrow: 6, arrowHalf: 3.5, parallel: 5, ghostDash: 5, flowDash: 9, bend: 12 },
279
309
  label: { h: 20, padX: 9, radius: 10, offset: 22, side: 14, search: 4, searchMax: 400, soft: 6 },
280
310
  action: { h: 22, padX: 10, radius: 11 },
281
311
  badge: { r: 9.5, ring: 9, inset: 4, along: 14, short: 44 },
282
312
  carrier: { envW: 24, envH: 17, coinR: 6.5, coinIn: 3.8, tagH: 18, tagPadX: 8, samples: 16 },
283
- strip: { h: 72, line: 44, pad: 12, icon: 24, titleX: 44, fieldGap: 22, sepInset: 14, tagGap: 6, tagH: 15, tagPadX: 7, nameY: 22, valueY: 43 },
284
- stroke: { hair: 1, edge: 1.7, edgeOn: 2.25, arrow: 1.5, flow: 1.3, halo: 7, on: 1.75, glyph: 2, lifeline: 1.2, envelope: 1.5, badgeRing: 1.5 },
313
+ /**
314
+ * `trail` は状態遷移図の帯の最後の、通った状態の点 (#3171)。`r` は点の半径、`step` は点の中心どうしの間、`now` は変わった値の欄の名前の横の点の半径と、名前からの離れ
315
+ */
316
+ strip: { h: 72, line: 44, pad: 12, icon: 24, titleX: 44, fieldGap: 22, sepInset: 14, tagGap: 6, tagH: 15, tagPadX: 7, nameY: 22, valueY: 43, trail: { r: 5.4, step: 16 }, now: { r: 3, gap: 7 } },
317
+ stroke: { hair: 1, edge: 1.7, edgeOn: 2.25, arrow: 1.5, flow: 1.3, halo: 7, on: 1.75, glyph: 2, lifeline: 1.2, envelope: 1.5, badgeRing: 1.5, path: 1.6, end: 1.6, done: 1.2, trail: 1.2 },
285
318
  shadow: { near: 0.8, far: 4, nearY: 1, farY: 3 },
286
319
  mini: { w: 168, pad: 8, title: 14, inset: 12, radius: 10 },
287
320
  /**
@@ -295,9 +328,9 @@ var LOOK = {
295
328
  */
296
329
  follow: { aspect: 0.75, minH: 320, fitMinH: 160, ease: 0.6, narrow: 440, badgeRoom: 8, headRoom: 10, head: { pad: 8, h: 40, nameY: 17, subY: 31 } },
297
330
  /** 色を混ぜる割合 (%) */
298
- mix: { icon: 14, regionIcon: 16, regionIconEdge: 34, cap: 12, capEdge: 42, badgePast: 14, badgePastEdge: 70, mini: 62, miniBand: 16, miniBandEdge: 36, view: 6 },
331
+ mix: { icon: 14, regionIcon: 16, regionIconEdge: 34, cap: 12, capEdge: 42, badgePast: 14, badgePastEdge: 70, mini: 62, miniBand: 16, miniBandEdge: 36, view: 6, side: 4, sideEdge: 36, ghostEdge: 60, path: 55, past: 72 },
299
332
  /** 字の並びの基準線を、置きたい高さの真ん中からどれだけ下げるか */
300
- baseline: { label: 3.8, badge: 3.5, carrier: 3.7, stripTitle: 4.5, tag: 3.6, action: 3.8 },
333
+ baseline: { label: 3.8, badge: 3.5, carrier: 3.7, stripTitle: 4.5, tag: 3.6, action: 3.8, mark: 4 },
301
334
  /** 浮いて出る物が下から上がる長さと、弾んで出る物の始まりの大きさ */
302
335
  rise: 5,
303
336
  popFrom: 0.4};
@@ -331,7 +364,9 @@ var MOTION = {
331
364
  popFade: 0.4,
332
365
  untilFade: 0.2,
333
366
  /** 段の止め絵を撮る時刻を、段の終わりからどれだけ前にするか */
334
- still: 0.45
367
+ still: 0.45,
368
+ /** 状態遷移図で、札が状態を出てから済んだ印が出るまで */
369
+ done: 0.3
335
370
  };
336
371
  var READABLE_PX = 10.5;
337
372
  var EASE = {
@@ -349,7 +384,13 @@ var FIGURE_TEXT = {
349
384
  pause: "\u6B62\u3081\u308B",
350
385
  play: "\u52D5\u304B\u3059",
351
386
  next: "\u6B21\u306E\u6BB5",
352
- steps: (title) => `${title} \u306E\u6BB5`
387
+ steps: (title) => `${title} \u306E\u6BB5`,
388
+ side: "\u8107\u9053",
389
+ sideNote: "\u4ECA\u56DE\u306F\u901A\u3089\u306A\u3044",
390
+ sideFrom: (count) => `${count} \u3064\u306E\u72B6\u614B\u304B\u3089\u5165\u308C\u308B`,
391
+ trail: "\u901A\u3063\u305F\u72B6\u614B",
392
+ start: "\u59CB\u307E\u308A",
393
+ end: "\u7D42\u308F\u308A"
353
394
  },
354
395
  en: {
355
396
  cannotDraw: (detail2) => `Cannot draw the diagram: ${detail2}`,
@@ -358,7 +399,13 @@ var FIGURE_TEXT = {
358
399
  pause: "Pause",
359
400
  play: "Play",
360
401
  next: "Next step",
361
- steps: (title) => `Steps of ${title}`
402
+ steps: (title) => `Steps of ${title}`,
403
+ side: "Side path",
404
+ sideNote: "Not taken this time",
405
+ sideFrom: (count) => `Enterable from ${count} ${count === 1 ? "state" : "states"}`,
406
+ trail: "States passed",
407
+ start: "Start",
408
+ end: "End"
362
409
  }
363
410
  };
364
411
 
@@ -453,12 +500,12 @@ function placeLabel(request, obstacles) {
453
500
  const segment = longest(request.points);
454
501
  const mx = (segment.a[0] + segment.b[0]) / 2;
455
502
  const my = (segment.a[1] + segment.b[1]) / 2;
456
- const side = request.side ?? (segment.vertical ? "right" : "above");
503
+ const side2 = request.side ?? (segment.vertical ? "right" : "above");
457
504
  const { offset, side: sideGap } = LOOK.label;
458
- const base = side === "above" ? { x: mx - w / 2, y: my - offset - h / 2, w, h } : side === "below" ? { x: mx - w / 2, y: my + offset - h / 2, w, h } : side === "left" ? { x: mx - sideGap - w, y: my - h / 2, w, h } : { x: mx + sideGap, y: my - h / 2, w, h };
459
- const away = side === "above" ? [0, -1] : side === "below" ? [0, 1] : side === "left" ? [-1, 0] : [1, 0];
505
+ const base = side2 === "above" ? { x: mx - w / 2, y: my - offset - h / 2, w, h } : side2 === "below" ? { x: mx - w / 2, y: my + offset - h / 2, w, h } : side2 === "left" ? { x: mx - sideGap - w, y: my - h / 2, w, h } : { x: mx + sideGap, y: my - h / 2, w, h };
506
+ const away = side2 === "above" ? [0, -1] : side2 === "below" ? [0, 1] : side2 === "left" ? [-1, 0] : [1, 0];
460
507
  const slideAxis = [Math.abs(away[1]), Math.abs(away[0])];
461
- const slideMax = side === "above" || side === "below" ? w : h * 4;
508
+ const slideMax = side2 === "above" || side2 === "below" ? w : h * 4;
462
509
  const clear = (rect) => obstacles.hard.every((box) => gapBetween(rect, box) >= LOOK.gap) && obstacles.soft.every((other) => gapBetween(rect, other) >= LOOK.label.soft);
463
510
  const { search, searchMax } = LOOK.label;
464
511
  for (let d = 0; d <= searchMax; d += search) {
@@ -484,29 +531,36 @@ function fieldWidth(diagram, name) {
484
531
  const both = value + (tag > 0 ? (value > 0 ? LOOK.strip.tagGap : 0) + tag : 0);
485
532
  return Math.max(textWidth(name, TYPE.fieldName), both);
486
533
  }
487
- function stripNeed(diagram) {
534
+ var trailWidth = (trail) => Math.max(textWidth(trail.title, TYPE.fieldName), trail.states.length * LOOK.strip.trail.step);
535
+ function stripNeed(diagram, trail) {
488
536
  if (!diagram.strip) return 0;
489
537
  const { titleX, fieldGap, pad: pad2 } = LOOK.strip;
490
538
  const start = titleX + textWidth(diagram.strip.title, TYPE.stripTitle) + fieldGap;
491
- return start + diagram.strip.fields.reduce((sum, name) => sum + fieldWidth(diagram, name) + fieldGap, 0) - fieldGap + pad2;
539
+ const widths = [...diagram.strip.fields.map((name) => fieldWidth(diagram, name)), ...trail ? [trailWidth(trail)] : []];
540
+ return start + widths.reduce((sum, w) => sum + w + fieldGap, 0) - fieldGap + pad2;
492
541
  }
493
- function layoutStrip(diagram, x, y, width) {
542
+ function layoutStrip(diagram, x, y, width, trail) {
494
543
  if (!diagram.strip) return void 0;
495
544
  const { titleX, fieldGap, pad: pad2, line, h } = LOOK.strip;
496
545
  const start = titleX + textWidth(diagram.strip.title, TYPE.stripTitle) + fieldGap;
497
546
  const fields = [];
498
547
  let cx = start;
499
548
  let row = 0;
500
- for (const name of diagram.strip.fields) {
501
- const w = fieldWidth(diagram, name);
549
+ const place = (w) => {
502
550
  if (cx > start && cx + w > width - pad2) {
503
551
  cx = start;
504
552
  row++;
505
553
  }
506
- fields.push({ name, x: x + cx, y: y + row * line, w });
554
+ const at2 = { x: x + cx, y: y + row * line };
507
555
  cx += w + fieldGap;
556
+ return at2;
557
+ };
558
+ for (const name of diagram.strip.fields) {
559
+ const w = fieldWidth(diagram, name);
560
+ fields.push({ name, ...place(w), w });
508
561
  }
509
- return { x, y, w: width, h: h + row * line, title: diagram.strip.title, fields };
562
+ const laidTrail = trail ? { ...trail, ...place(trailWidth(trail)), w: trailWidth(trail) } : void 0;
563
+ return { x, y, w: width, h: h + row * line, title: diagram.strip.title, fields, ...laidTrail ? { trail: laidTrail } : {} };
510
564
  }
511
565
  function shiftContent(layout, dx, dy) {
512
566
  const move = (rect) => {
@@ -532,6 +586,15 @@ function shiftContent(layout, dx, dy) {
532
586
  if (edge2.settle) edge2.settle = [edge2.settle[0] + dx, edge2.settle[1] + dy];
533
587
  }
534
588
  for (const label2 of layout.labels) move(label2);
589
+ for (const path2 of layout.paths) {
590
+ path2.points = path2.points.map(([px, py]) => [px + dx, py + dy]);
591
+ if (path2.label) move(path2.label);
592
+ }
593
+ for (const end of layout.ends) {
594
+ end.x += dx;
595
+ end.y += dy;
596
+ }
597
+ if (layout.side) move(layout.side);
535
598
  for (const action2 of layout.actions) move(action2);
536
599
  for (const badge2 of layout.badges) {
537
600
  badge2.x += dx;
@@ -543,6 +606,10 @@ function shiftContent(layout, dx, dy) {
543
606
  field.x += dx;
544
607
  field.y += dy;
545
608
  }
609
+ if (layout.strip.trail) {
610
+ layout.strip.trail.x += dx;
611
+ layout.strip.trail.y += dy;
612
+ }
546
613
  }
547
614
  }
548
615
  function cornerBadge(events, step, layout) {
@@ -574,7 +641,7 @@ function groupsOf(diagram) {
574
641
  if (loose.length > 0) groups.push({ members: loose });
575
642
  return groups;
576
643
  }
577
- var vertical = (side) => side === "left" || side === "right";
644
+ var vertical = (side2) => side2 === "left" || side2 === "right";
578
645
  function placeBoxes(diagram, groups) {
579
646
  const columns = LOOK.architecture.columns;
580
647
  const edges = edgesOf(diagram).map((e) => e.edge);
@@ -821,7 +888,7 @@ function arrange(diagram, groups, slots, rooms) {
821
888
  )
822
889
  );
823
890
  }
824
- const layout = { kind: "architecture", width: 0, height: 0, regions, boxes, lifelines: [], edges: sceneEdges, labels, actions: [], badges: [] };
891
+ const layout = { kind: "architecture", width: 0, height: 0, regions, boxes, lifelines: [], edges: sceneEdges, labels, actions: [], badges: [], paths: [], ends: [] };
825
892
  const shift = labels.length > 0 ? Math.max(0, margin + LOOK.label.soft - Math.min(...labels.map((l) => l.x))) : 0;
826
893
  if (shift > 0) shiftContent(layout, shift, 0);
827
894
  const contentRight = Math.max(...boxes.map((b) => b.x + b.w + R.pad), ...labels.map((l) => l.x + l.w + LOOK.label.soft), ...sceneEdges.flatMap((e) => e.points.map((p) => p[0] + R.pad)));
@@ -928,11 +995,11 @@ function layoutSequence(diagram) {
928
995
  let above;
929
996
  let under;
930
997
  if (event.type === "edge") {
931
- const side = event.labelSide ?? "above";
998
+ const side2 = event.labelSide ?? "above";
932
999
  const self = event.from === event.to;
933
1000
  const named = event.label !== void 0;
934
- above = named && side === "above" ? L.offset + L.h / 2 : gap;
935
- under = self ? Q.selfH + gap : named && side === "below" ? L.offset + L.h / 2 : gap;
1001
+ above = named && side2 === "above" ? L.offset + L.h / 2 : gap;
1002
+ under = self ? Q.selfH + gap : named && side2 === "below" ? L.offset + L.h / 2 : gap;
936
1003
  } else {
937
1004
  above = LOOK.action.h / 2;
938
1005
  under = LOOK.action.h / 2;
@@ -979,7 +1046,7 @@ function layoutSequence(diagram) {
979
1046
  const soft = [...labels.filter((l) => l.step === request.step), ...actions];
980
1047
  labels.push(placeLabel(request, { hard: boxes, soft }));
981
1048
  }
982
- const layout = { kind: "sequence", width: 0, height: 0, regions: [], boxes, lifelines, edges, labels, actions, badges: [] };
1049
+ const layout = { kind: "sequence", width: 0, height: 0, regions: [], boxes, lifelines, edges, labels, actions, badges: [], paths: [], ends: [] };
983
1050
  const lefts = [...boxes.map((b) => b.x), ...labels.map((l) => l.x), ...actions.map((a) => a.x)];
984
1051
  const shift = Math.max(0, margin - Math.min(...lefts));
985
1052
  if (shift > 0) shiftContent(layout, shift, 0);
@@ -1006,6 +1073,326 @@ function badges(diagram, layout) {
1006
1073
  });
1007
1074
  }
1008
1075
 
1076
+ // src/words.ts
1077
+ var keys = (table) => Object.keys(table);
1078
+ var KINDS = keys({ sequence: true, architecture: true, state: true });
1079
+ var STATE_ENDS = ["start", "finish"];
1080
+ var HEADS = ["group", "end", "box", "strip", "step", "say", "code", "act", "note", "set"];
1081
+ var AS = "as";
1082
+ var ATTRS = {
1083
+ diagram: ["view"],
1084
+ group: ["note", "color", "icon"],
1085
+ box: ["note", "color", "icon"],
1086
+ edge: ["carry", "tag", "side"],
1087
+ set: ["tag"]
1088
+ };
1089
+ var CARRIES = keys({ coin: true, none: true });
1090
+ var VIEWS = keys({ fixed: true, follow: true });
1091
+ var SIDES = keys({ above: true, below: true, left: true, right: true });
1092
+ var OLD_HEADS = {
1093
+ \u6642\u7CFB\u5217\u56F3: "sequence",
1094
+ \u69CB\u6210\u56F3: "architecture",
1095
+ \u533A\u753B: "group",
1096
+ \u898B\u305B\u65B9: "view",
1097
+ region: "group",
1098
+ view: "view"
1099
+ };
1100
+
1101
+ // src/layout/state.ts
1102
+ var isEnd = (id) => STATE_ENDS.includes(id);
1103
+ function visitOrder(diagram) {
1104
+ const order = [];
1105
+ const add = (id) => {
1106
+ if (!isEnd(id) && !order.includes(id)) order.push(id);
1107
+ };
1108
+ for (const { edge: edge2 } of edgesOf(diagram)) {
1109
+ add(edge2.from);
1110
+ add(edge2.to);
1111
+ }
1112
+ return order;
1113
+ }
1114
+ function carrierHalf(carry) {
1115
+ const C = LOOK.carrier;
1116
+ if (carry.kind === "tag") return (textWidth(carry.text, hasWide(carry.text) ? TYPE.carrierJa : TYPE.carrier) + C.tagPadX * 2) / 2;
1117
+ if (carry.kind === "coin") return C.coinR;
1118
+ return C.envW / 2;
1119
+ }
1120
+ var same = (a, b) => a.from === b.from && a.to === b.to;
1121
+ function layoutState(diagram, lang) {
1122
+ const { box: B, state: T, margin, gap } = LOOK;
1123
+ const inset = LOOK.edge.inset;
1124
+ const words = FIGURE_TEXT[lang];
1125
+ const colors = boxColors(diagram);
1126
+ const steps = edgesOf(diagram);
1127
+ const walked = visitOrder(diagram);
1128
+ const ghosts = diagram.boxes.map((b) => b.id).filter((id) => !walked.includes(id));
1129
+ const notTaken = (diagram.state?.paths ?? []).filter((p) => !steps.some(({ edge: edge2 }) => same(edge2, p)));
1130
+ const lines = [...steps.map(({ edge: edge2 }) => edge2), ...notTaken];
1131
+ const G = T.ghost;
1132
+ const ghostWidth = (id) => {
1133
+ const source = diagram.boxes.find((b) => b.id === id);
1134
+ return G.pad * 2 + B.icon + G.gap + Math.max(textWidth(source?.name ?? id, TYPE.boxName), textWidth(source?.sub ?? "", TYPE.boxSub));
1135
+ };
1136
+ const widths = new Map(diagram.boxes.map((b) => [b.id, ghosts.includes(b.id) ? ghostWidth(b.id) : boxWidth(diagram, b.id, true)]));
1137
+ const columnCount = Math.max(1, Math.min(T.columns, walked.length));
1138
+ const rowCount = Math.max(1, Math.ceil(walked.length / T.columns));
1139
+ const slot = new Map(
1140
+ walked.map((id, k) => {
1141
+ const row = Math.floor(k / T.columns);
1142
+ const at2 = k % T.columns;
1143
+ return [id, { row, col: row % 2 === 0 ? at2 : columnCount - 1 - at2 }];
1144
+ })
1145
+ );
1146
+ const colW = Array.from({ length: columnCount }, (_, c) => Math.max(B.minW, ...walked.filter((id) => slot.get(id)?.col === c).map((id) => widths.get(id) ?? B.minW)));
1147
+ const between = Array.from({ length: Math.max(0, columnCount - 1) }, () => T.columnGap);
1148
+ for (const line of lines) {
1149
+ const a = slot.get(line.from);
1150
+ const b = slot.get(line.to);
1151
+ if (!a || !b || line.label === void 0 || a.row !== b.row || Math.abs(a.col - b.col) !== 1) continue;
1152
+ const i = Math.min(a.col, b.col);
1153
+ between[i] = Math.max(between[i] ?? 0, textWidth(line.label, labelStyle(line.label)) + LOOK.label.padX * 2 + T.labelRoom * 2);
1154
+ }
1155
+ const colLeft = [];
1156
+ for (let c = 0; c < columnCount; c++) colLeft.push(c === 0 ? margin : colLeft[c - 1] + colW[c - 1] + between[c - 1]);
1157
+ const center = (c) => colLeft[c] + colW[c] / 2;
1158
+ const isGhost = (id) => ghosts.includes(id);
1159
+ const enteringFrom = new Set(notTaken.filter((p) => isGhost(p.to) && !isGhost(p.from) && !isEnd(p.from)).map((p) => p.from));
1160
+ const notes = [words.sideNote, ...enteringFrom.size > 0 ? [words.sideFrom(enteringFrom.size)] : []];
1161
+ const titleW = Math.max(textWidth(words.side, TYPE.regionName), ...notes.map((note) => textWidth(note, TYPE.regionNote)));
1162
+ const sideH = T.side.pad * 2 + Math.max(G.h, TYPE.regionName.size + LOOK.region.line * notes.length + T.side.pad / 4);
1163
+ const starts = lines.some((line) => line.from === "start");
1164
+ const top0 = margin + (ghosts.length > 0 ? sideH + T.side.gap : starts ? T.start + T.drop : 0);
1165
+ const rowY = (row) => top0 + row * (B.h + T.rowGap);
1166
+ const boxOf = (id, cx, y, ghost) => {
1167
+ const source = diagram.boxes.find((b) => b.id === id);
1168
+ const w = widths.get(id) ?? B.minW;
1169
+ const h = ghost ? G.h : B.h;
1170
+ return {
1171
+ id,
1172
+ name: source?.name ?? id,
1173
+ ...source?.sub !== void 0 ? { sub: source.sub } : {},
1174
+ ...source?.icon !== void 0 ? { icon: source.icon } : {},
1175
+ color: colors.get(id) ?? "slate",
1176
+ x: cx - w / 2,
1177
+ y,
1178
+ w,
1179
+ h,
1180
+ cx,
1181
+ cy: y + h / 2,
1182
+ ...ghost ? { ghost: true } : {}
1183
+ };
1184
+ };
1185
+ const boxes = walked.map((id) => {
1186
+ const s = slot.get(id);
1187
+ return boxOf(id, center(s.col), rowY(s.row), false);
1188
+ });
1189
+ const byId = new Map(boxes.map((b) => [b.id, b]));
1190
+ const below = (box) => boxes.some((other) => other !== box && Math.abs(other.cx - box.cx) < 0.5 && other.y > box.y);
1191
+ const ends = [];
1192
+ const first = boxes[0];
1193
+ const contentRight = Math.max(...boxes.map((b) => b.x + b.w));
1194
+ let side2;
1195
+ const lane = margin + sideH + T.side.lane;
1196
+ if (ghosts.length > 0) {
1197
+ const sourcesOf = (id) => notTaken.filter((p) => p.to === id).flatMap((p) => byId.get(p.from) ?? []);
1198
+ const all = ghosts.flatMap(sourcesOf);
1199
+ const x = Math.max(margin, Math.min(...all.length > 0 ? all.map((b) => b.x) : [margin + T.side.pad]) - T.side.pad);
1200
+ let cursor = x + T.side.pad + titleW + gap * 2;
1201
+ const wanted = ghosts.map((id) => {
1202
+ const from = sourcesOf(id);
1203
+ return { id, cx: from.length > 0 ? from.reduce((sum, b) => sum + b.cx, 0) / from.length : cursor };
1204
+ });
1205
+ wanted.sort((a, b) => a.cx - b.cx);
1206
+ let right = x;
1207
+ for (const { id, cx } of wanted) {
1208
+ const w = widths.get(id) ?? B.minW;
1209
+ const left = Math.max(cx - w / 2, cursor);
1210
+ const ghost = boxOf(id, left + w / 2, margin + (sideH - G.h) / 2, true);
1211
+ boxes.push(ghost);
1212
+ byId.set(id, ghost);
1213
+ const finishes = notTaken.some((p) => p.from === id && p.to === "finish");
1214
+ if (finishes) ends.push({ kind: "finish", x: ghost.x + ghost.w + T.beside, y: ghost.cy, r: T.end.r, ghost: true, text: "", box: id });
1215
+ right = finishes ? ghost.x + ghost.w + T.beside + T.end.r : ghost.x + ghost.w;
1216
+ cursor = right + gap * 2;
1217
+ }
1218
+ const rightmost = Math.max(right + T.side.pad, contentRight);
1219
+ side2 = { x, y: margin, w: rightmost - x, h: sideH, title: words.side, notes };
1220
+ }
1221
+ if (first && starts) {
1222
+ const reach = first.cx + T.start + T.text + textWidth(words.start, TYPE.regionNote) + gap;
1223
+ const y = side2 && reach < side2.x ? side2.y + T.side.pad + T.start : first.y - T.drop;
1224
+ ends.unshift({ kind: "start", x: first.cx, y, r: T.start, ghost: false, text: words.start });
1225
+ }
1226
+ for (const box of boxes.filter((b) => !b.ghost && lines.some((line) => line.from === b.id && line.to === "finish"))) {
1227
+ ends.push(
1228
+ below(box) ? { kind: "finish", x: box.x + box.w + T.beside, y: box.cy, r: T.end.r, ghost: false, text: words.end, box: box.id } : { kind: "finish", x: box.cx, y: box.y + box.h + T.below, r: T.end.r, ghost: false, text: words.end, box: box.id }
1229
+ );
1230
+ }
1231
+ const between2 = (a, b) => {
1232
+ const sa = slot.get(a.id);
1233
+ const sb = slot.get(b.id);
1234
+ if (!sa || !sb) return [[a.cx, a.y + a.h], [b.cx, b.y - inset]];
1235
+ if (sa.row === sb.row && Math.abs(sa.col - sb.col) === 1) {
1236
+ return b.cx > a.cx ? [[a.x + a.w, a.cy], [b.x - inset, b.cy]] : [[a.x, a.cy], [b.x + b.w + inset, b.cy]];
1237
+ }
1238
+ if (sa.row === sb.row) {
1239
+ const y2 = a.y + a.h + T.rowGap / 4;
1240
+ return [[a.cx, a.y + a.h], [a.cx, y2], [b.cx, y2], [b.cx, b.y + b.h + inset]];
1241
+ }
1242
+ if (sb.row > sa.row) {
1243
+ if (Math.abs(a.cx - b.cx) < 0.5) return [[a.cx, a.y + a.h], [b.cx, b.y - inset]];
1244
+ const y2 = a.y + a.h + T.rowGap / 2;
1245
+ return [[a.cx, a.y + a.h], [a.cx, y2], [b.cx, y2], [b.cx, b.y - inset]];
1246
+ }
1247
+ if (Math.abs(a.cx - b.cx) < 0.5) return [[a.cx, a.y], [b.cx, b.y + b.h + inset]];
1248
+ const y = b.y + b.h + T.rowGap / 2;
1249
+ return [[a.cx, a.y], [a.cx, y], [b.cx, y], [b.cx, b.y + b.h + inset]];
1250
+ };
1251
+ const entryOf = (from, to) => {
1252
+ const sources = notTaken.filter((p) => p.to === to.id).flatMap((p) => byId.get(p.from) ?? []).sort((a, b) => a.cx - b.cx);
1253
+ const k = sources.findIndex((b) => b.id === from);
1254
+ if (sources.length <= 1) return Math.min(Math.max(sources[0]?.cx ?? to.cx, to.x + T.side.entry), to.x + to.w - T.side.entry);
1255
+ return to.x + T.side.entry + (to.w - T.side.entry * 2) * Math.max(0, k) / (sources.length - 1);
1256
+ };
1257
+ const exitX = (box) => starts && box === first ? box.cx + T.side.entry : box.cx;
1258
+ const finishOf = (id) => ends.find((e) => e.kind === "finish" && e.box === id);
1259
+ const loopOf = (box) => {
1260
+ const { w, h, samples } = T.loop;
1261
+ const bottom2 = box.y + box.h;
1262
+ const p0 = [box.cx + w / 2, bottom2];
1263
+ const c1 = [box.cx + w * 3 / 4, bottom2 + h * 4 / 3];
1264
+ const c2 = [box.cx - w * 3 / 4, bottom2 + h * 4 / 3];
1265
+ const p3 = [box.cx - w / 2, bottom2 + inset];
1266
+ return Array.from({ length: samples + 1 }, (_, k) => {
1267
+ const t = k / samples;
1268
+ const u = 1 - t;
1269
+ const at2 = (i) => u * u * u * p0[i] + 3 * u * u * t * c1[i] + 3 * u * t * t * c2[i] + t * t * t * p3[i];
1270
+ return [at2(0), at2(1)];
1271
+ });
1272
+ };
1273
+ const route = (from, to) => {
1274
+ if (from === "start") {
1275
+ const start = ends.find((e) => e.kind === "start");
1276
+ const target = byId.get(to);
1277
+ if (!start || !target) return [];
1278
+ return [[start.x, start.y + start.r], [target.cx, target.y - inset]];
1279
+ }
1280
+ const a = byId.get(from);
1281
+ if (!a) return [];
1282
+ if (to === "finish") {
1283
+ const end = finishOf(from);
1284
+ if (!end) return [];
1285
+ return Math.abs(end.x - a.cx) < 0.5 ? [[a.cx, a.y + a.h], [a.cx, end.y - end.r - inset]] : [[a.x + a.w, a.cy], [end.x - end.r - inset, a.cy]];
1286
+ }
1287
+ const b = byId.get(to);
1288
+ if (!b) return [];
1289
+ if (from === to) return loopOf(a);
1290
+ if (b.ghost && !a.ghost) {
1291
+ const sx = exitX(a);
1292
+ const ex = entryOf(from, b);
1293
+ return Math.abs(sx - ex) < 0.5 ? [[sx, a.y], [ex, b.y + b.h + inset]] : [[sx, a.y], [sx, lane], [ex, lane], [ex, b.y + b.h + inset]];
1294
+ }
1295
+ if (a.ghost && b.ghost) return [[a.x + a.w, a.cy], [b.x - inset, b.cy]];
1296
+ if (a.ghost) return [[a.cx, a.y + a.h], [a.cx, lane], [b.cx, lane], [b.cx, b.y - inset]];
1297
+ return between2(a, b);
1298
+ };
1299
+ const settleOf = (edge2) => {
1300
+ const target = byId.get(edge2.to);
1301
+ if (target) return [target.cx, target.cy + B.iconY];
1302
+ const end = edge2.to === "finish" ? finishOf(edge2.from) : void 0;
1303
+ if (!end) return void 0;
1304
+ const from = byId.get(edge2.from);
1305
+ return from && Math.abs(end.x - from.cx) < 0.5 ? [end.x - end.r - gap - carrierHalf(edge2.carry), end.y] : [end.x, end.y + end.r + gap + LOOK.carrier.tagH / 2];
1306
+ };
1307
+ const sceneEdges = steps.map(({ step, event, edge: edge2 }) => {
1308
+ const settle = settleOf(edge2);
1309
+ return {
1310
+ step,
1311
+ event,
1312
+ from: edge2.from,
1313
+ to: edge2.to,
1314
+ points: route(edge2.from, edge2.to),
1315
+ color: colorOf(edge2, colors),
1316
+ carry: edge2.carry,
1317
+ ...settle ? { settle } : {}
1318
+ };
1319
+ });
1320
+ for (const e of sceneEdges) {
1321
+ if (e.points.length !== 2 || !sceneEdges.some((o) => o.from === e.to && o.to === e.from && o.points.length === 2)) continue;
1322
+ const [p, q] = e.points;
1323
+ const flat = Math.abs(q[1] - p[1]) < Math.abs(q[0] - p[0]);
1324
+ const d = (e.from < e.to ? 1 : -1) * LOOK.edge.parallel;
1325
+ e.points = e.points.map(([x, y]) => flat ? [x, y + d] : [x + d, y]);
1326
+ }
1327
+ const paths = notTaken.map((p) => ({ from: p.from, to: p.to, points: route(p.from, p.to) }));
1328
+ const labels = [];
1329
+ const soft = side2 ? [{ x: side2.x, y: side2.y, w: T.side.pad + titleW, h: side2.h }] : [];
1330
+ for (const e of sceneEdges) {
1331
+ const source = diagram.steps[e.step]?.events[e.event];
1332
+ if (source?.type !== "edge" || source.label === void 0) continue;
1333
+ const style = labelStyle(source.label);
1334
+ if (e.from === e.to) {
1335
+ const w = textWidth(source.label, style) + LOOK.label.padX * 2;
1336
+ const bottom2 = Math.max(...e.points.map(([, y]) => y));
1337
+ labels.push({ step: e.step, event: e.event, text: source.label, family: style.family, color: e.color, x: (e.points[0]?.[0] ?? 0) - T.loop.w / 2 - w / 2, y: bottom2 + LOOK.label.soft, w, h: LOOK.label.h });
1338
+ continue;
1339
+ }
1340
+ const side22 = source.labelSide ?? (e.to === "finish" ? "left" : void 0);
1341
+ labels.push(
1342
+ placeLabel(
1343
+ { step: e.step, event: e.event, text: source.label, points: e.points, color: e.color, ...side22 ? { side: side22 } : {} },
1344
+ { hard: boxes, soft: [...soft, ...labels.filter((l) => l.step === e.step)] }
1345
+ )
1346
+ );
1347
+ }
1348
+ notTaken.forEach((p, i) => {
1349
+ const path2 = paths[i];
1350
+ if (p.label === void 0 || path2.points.length === 0) return;
1351
+ const style = labelStyle(p.label);
1352
+ const into = byId.get(p.to)?.ghost === true && byId.get(p.from)?.ghost !== true;
1353
+ const rect = into ? { x: path2.points[0][0] + LOOK.label.soft, y: lane + LOOK.label.soft, w: textWidth(p.label, style) + LOOK.label.padX * 2, h: LOOK.label.h } : placeLabel({ step: -1, event: i, text: p.label, points: path2.points, color: "slate" }, { hard: boxes, soft });
1354
+ path2.label = { x: rect.x, y: rect.y, w: rect.w, h: rect.h, text: p.label, family: style.family };
1355
+ });
1356
+ const layout = { kind: "state", width: 0, height: 0, regions: [], boxes, lifelines: [], edges: sceneEdges, labels, actions: [], badges: [], paths, ends, ...side2 ? { side: side2 } : {} };
1357
+ const lefts = [...boxes.map((b) => b.x), ...labels.map((l) => l.x), ...paths.flatMap((p) => p.label ? [p.label.x] : [])];
1358
+ const shift = Math.max(0, margin - Math.min(...lefts));
1359
+ if (shift > 0) shiftContent(layout, shift, 0);
1360
+ const endRight = (e) => e.x + (e.text === "" ? e.r : T.text + textWidth(e.text, TYPE.regionNote));
1361
+ const rights = [
1362
+ ...boxes.map((b) => b.x + b.w),
1363
+ ...labels.map((l) => l.x + l.w),
1364
+ ...ends.map(endRight),
1365
+ ...sceneEdges.flatMap((e) => e.points.map((p) => p[0])),
1366
+ ...paths.flatMap((p) => [...p.points.map((q) => q[0]), ...p.label ? [p.label.x + p.label.w] : []]),
1367
+ ...side2 ? [side2.x + side2.w] : []
1368
+ ];
1369
+ const bottoms = [...boxes.map((b) => b.y + b.h), ...labels.map((l) => l.y + l.h), ...ends.map((e) => e.y + e.r), ...sceneEdges.flatMap((e) => e.points.map((p) => p[1]))];
1370
+ const trail = { title: words.trail, states: walked.map((id) => ({ box: id, color: colors.get(id) ?? "slate" })) };
1371
+ const width = Math.max(Math.max(...rights) + margin, stripNeed(diagram, trail) + margin * 2);
1372
+ const bottom = Math.max(...bottoms, rowY(rowCount - 1) + B.h);
1373
+ const strip2 = layoutStrip(diagram, margin, bottom + gap, width - margin * 2, trail);
1374
+ layout.width = width;
1375
+ layout.height = (strip2 ? strip2.y + strip2.h : bottom) + margin;
1376
+ if (strip2) layout.strip = strip2;
1377
+ layout.badges = diagram.steps.map((step, s) => {
1378
+ const edge2 = sceneEdges.find((e) => e.step === s && e.points.length > 0);
1379
+ if (!edge2) return cornerBadge(step.events, s, layout);
1380
+ if (edge2.from === edge2.to) {
1381
+ const right = Math.max(...edge2.points.map(([px]) => px));
1382
+ const top = edge2.points[0][1];
1383
+ const deep = Math.max(...edge2.points.map(([, py]) => py));
1384
+ return { step: s, x: right + LOOK.badge.r + LOOK.badge.inset, y: top + (deep - top) * T.loop.badgeAt, color: edge2.color };
1385
+ }
1386
+ const [x, y] = badgeOnPath(edge2.points);
1387
+ return { step: s, x, y, color: edge2.color };
1388
+ });
1389
+ return layout;
1390
+ }
1391
+ function colorOf(edge2, colors) {
1392
+ if (edge2.carry.kind === "coin") return edgeColor(edge2, colors);
1393
+ return colors.get(edge2.to === "finish" ? edge2.from : edge2.to) ?? "slate";
1394
+ }
1395
+
1009
1396
  // src/field-messages.ts
1010
1397
  var TYPES_JA = {
1011
1398
  string: "\u6587\u5B57\u5217\u306B\u3059\u308B",
@@ -1037,6 +1424,7 @@ var ja = {
1037
1424
  minimum: (limit) => `${limit} \u4EE5\u4E0A\u306B\u3059\u308B`,
1038
1425
  const: (value) => `${value} \u306B\u3059\u308B`,
1039
1426
  not: (allowed) => allowed ? `${allowed.field} \u306E\u6B04\u306F kind \u304C ${allowed.kind} \u306E\u6642\u3060\u3051\u66F8\u3051\u308B` : "\u3053\u306E\u6B04\u306E\u7D44\u307F\u5408\u308F\u305B\u306F\u66F8\u3051\u306A\u3044",
1427
+ reserved: (names) => `${names.join(" \u3068 ")} \u306F\u72B6\u614B\u9077\u79FB\u56F3\u306E\u59CB\u307E\u308A\u3068\u7D42\u308F\u308A\u306E\u5370\u306E\u540D\u524D\u3067\u3001\u7BB1\u306E\u540D\u672D\u306B\u4F7F\u3048\u306A\u3044`,
1040
1428
  anyOf: (fields) => fields.length > 0 ? `${fields.join(" \u304B ")} \u306E${fields.length === 2 ? "\u3069\u3061\u3089\u304B" : "\u3069\u308C\u304B"}\u306E\u6B04\u304C\u8981\u308B` : "\u66F8\u3051\u308B\u5F62\u306E\u3069\u308C\u306B\u3082\u5408\u308F\u306A\u3044",
1041
1429
  oneOf: "\u66F8\u3051\u308B\u5F62\u306E\u3069\u308C\u304B 1 \u3064\u3060\u3051\u306B\u5408\u308F\u305B\u308B",
1042
1430
  discriminator: (tag, values) => `${tag} \u306F ${values.join(" / ")} \u306E\u3069\u308C\u304B\u306B\u3059\u308B`,
@@ -1053,6 +1441,7 @@ var en = {
1053
1441
  minimum: (limit) => `Use ${limit} or greater`,
1054
1442
  const: (value) => `Use ${value}`,
1055
1443
  not: (allowed) => allowed ? `The ${allowed.field} field is allowed only when kind is ${allowed.kind}` : "This combination of fields is not allowed",
1444
+ reserved: (names) => `${names.join(" and ")} name the start and end marks of a state diagram and cannot be box ids`,
1056
1445
  anyOf: (fields) => fields.length > 0 ? `Write one of the ${fields.join(" or ")} fields` : "Does not match any of the allowed shapes",
1057
1446
  oneOf: "Match exactly one of the allowed shapes",
1058
1447
  discriminator: (tag, values) => `${tag} is one of ${values.join(" / ")}`,
@@ -1067,7 +1456,7 @@ function ucs2length(str) {
1067
1456
  return length;
1068
1457
  }
1069
1458
  var validate_diagram_default = validate10;
1070
- var schema11 = { "properties": { "version": { "description": "\u5F62\u5F0F\u306E\u7248", "type": "integer", "minimum": 1 }, "kind": { "description": "\u56F3\u306E\u7A2E\u985E", "enum": ["sequence", "architecture"] }, "title": { "$ref": "#/definitions/text" }, "view": { "description": "\u898B\u305B\u65B9\u3002\u66F8\u304B\u306A\u3051\u308C\u3070\u5B57\u306E\u5927\u304D\u3055\u3067\u9078\u3076\u3002fixed \u306F\u5168\u4F53\u3092\u6B62\u3081\u3066\u4E2D\u3060\u3051\u52D5\u304B\u3057\u3001follow \u306F\u5BC4\u3063\u3066\u52D5\u304B\u3057\u5168\u4F53\u56F3\u3067\u4ECA\u3069\u3053\u304B\u3092\u793A\u3059", "enum": ["fixed", "follow"] }, "regions": { "type": "array", "items": { "$ref": "#/definitions/region" } }, "boxes": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/box" } }, "strip": { "$ref": "#/definitions/strip" }, "steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/step" } }, "sequence": { "$ref": "#/definitions/sequence" } }};
1459
+ var schema11 = { "properties": { "version": { "description": "\u5F62\u5F0F\u306E\u7248", "type": "integer", "minimum": 1 }, "kind": { "description": "\u56F3\u306E\u7A2E\u985E", "enum": ["sequence", "architecture", "state"] }, "title": { "$ref": "#/definitions/text" }, "view": { "description": "\u898B\u305B\u65B9\u3002\u66F8\u304B\u306A\u3051\u308C\u3070\u5B57\u306E\u5927\u304D\u3055\u3067\u9078\u3076\u3002fixed \u306F\u5168\u4F53\u3092\u6B62\u3081\u3066\u4E2D\u3060\u3051\u52D5\u304B\u3057\u3001follow \u306F\u5BC4\u3063\u3066\u52D5\u304B\u3057\u5168\u4F53\u56F3\u3067\u4ECA\u3069\u3053\u304B\u3092\u793A\u3059", "enum": ["fixed", "follow"] }, "regions": { "type": "array", "items": { "$ref": "#/definitions/region" } }, "boxes": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/box" } }, "strip": { "$ref": "#/definitions/strip" }, "steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/step" } }, "sequence": { "$ref": "#/definitions/sequence" }, "state": { "$ref": "#/definitions/state" } }};
1071
1460
  var func2 = Object.prototype.hasOwnProperty;
1072
1461
  var func3 = ucs2length;
1073
1462
  var schema17 = { "enum": ["blue", "amber", "green", "violet", "rose", "slate", "coin"] };
@@ -2461,6 +2850,182 @@ function validate23(data, { instancePath = "", parentData, parentDataProperty, r
2461
2850
  validate23.errors = vErrors;
2462
2851
  return errors === 0;
2463
2852
  }
2853
+ function validate26(data, { instancePath = "", parentData, parentDataProperty, rootData = data } = {}) {
2854
+ let vErrors = null;
2855
+ let errors = 0;
2856
+ if (data && typeof data == "object" && !Array.isArray(data)) {
2857
+ if (data.from === void 0) {
2858
+ const err0 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "from" }, message: "must have required property 'from'" };
2859
+ if (vErrors === null) {
2860
+ vErrors = [err0];
2861
+ } else {
2862
+ vErrors.push(err0);
2863
+ }
2864
+ errors++;
2865
+ }
2866
+ if (data.to === void 0) {
2867
+ const err1 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "to" }, message: "must have required property 'to'" };
2868
+ if (vErrors === null) {
2869
+ vErrors = [err1];
2870
+ } else {
2871
+ vErrors.push(err1);
2872
+ }
2873
+ errors++;
2874
+ }
2875
+ for (const key0 in data) {
2876
+ if (!(key0 === "from" || key0 === "to" || key0 === "label")) {
2877
+ const err2 = { instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" };
2878
+ if (vErrors === null) {
2879
+ vErrors = [err2];
2880
+ } else {
2881
+ vErrors.push(err2);
2882
+ }
2883
+ errors++;
2884
+ }
2885
+ }
2886
+ if (data.from !== void 0) {
2887
+ let data0 = data.from;
2888
+ if (typeof data0 === "string") {
2889
+ if (!pattern0.test(data0)) {
2890
+ const err3 = { instancePath: instancePath + "/from", schemaPath: "#/definitions/id/pattern", keyword: "pattern", params: { pattern: "^[^\\s\\[\\]\u300C\u300D=:]+$" }, message: 'must match pattern "^[^\\s\\[\\]\u300C\u300D=:]+$"' };
2891
+ if (vErrors === null) {
2892
+ vErrors = [err3];
2893
+ } else {
2894
+ vErrors.push(err3);
2895
+ }
2896
+ errors++;
2897
+ }
2898
+ } else {
2899
+ const err4 = { instancePath: instancePath + "/from", schemaPath: "#/definitions/id/type", keyword: "type", params: { type: "string" }, message: "must be string" };
2900
+ if (vErrors === null) {
2901
+ vErrors = [err4];
2902
+ } else {
2903
+ vErrors.push(err4);
2904
+ }
2905
+ errors++;
2906
+ }
2907
+ }
2908
+ if (data.to !== void 0) {
2909
+ let data1 = data.to;
2910
+ if (typeof data1 === "string") {
2911
+ if (!pattern0.test(data1)) {
2912
+ const err5 = { instancePath: instancePath + "/to", schemaPath: "#/definitions/id/pattern", keyword: "pattern", params: { pattern: "^[^\\s\\[\\]\u300C\u300D=:]+$" }, message: 'must match pattern "^[^\\s\\[\\]\u300C\u300D=:]+$"' };
2913
+ if (vErrors === null) {
2914
+ vErrors = [err5];
2915
+ } else {
2916
+ vErrors.push(err5);
2917
+ }
2918
+ errors++;
2919
+ }
2920
+ } else {
2921
+ const err6 = { instancePath: instancePath + "/to", schemaPath: "#/definitions/id/type", keyword: "type", params: { type: "string" }, message: "must be string" };
2922
+ if (vErrors === null) {
2923
+ vErrors = [err6];
2924
+ } else {
2925
+ vErrors.push(err6);
2926
+ }
2927
+ errors++;
2928
+ }
2929
+ }
2930
+ if (data.label !== void 0) {
2931
+ let data2 = data.label;
2932
+ if (typeof data2 === "string") {
2933
+ if (func3(data2) < 1) {
2934
+ const err7 = { instancePath: instancePath + "/label", schemaPath: "#/definitions/text/minLength", keyword: "minLength", params: { limit: 1 }, message: "must NOT have fewer than 1 characters" };
2935
+ if (vErrors === null) {
2936
+ vErrors = [err7];
2937
+ } else {
2938
+ vErrors.push(err7);
2939
+ }
2940
+ errors++;
2941
+ }
2942
+ } else {
2943
+ const err8 = { instancePath: instancePath + "/label", schemaPath: "#/definitions/text/type", keyword: "type", params: { type: "string" }, message: "must be string" };
2944
+ if (vErrors === null) {
2945
+ vErrors = [err8];
2946
+ } else {
2947
+ vErrors.push(err8);
2948
+ }
2949
+ errors++;
2950
+ }
2951
+ }
2952
+ } else {
2953
+ const err9 = { instancePath, schemaPath: "#/type", keyword: "type", params: { type: "object" }, message: "must be object" };
2954
+ if (vErrors === null) {
2955
+ vErrors = [err9];
2956
+ } else {
2957
+ vErrors.push(err9);
2958
+ }
2959
+ errors++;
2960
+ }
2961
+ validate26.errors = vErrors;
2962
+ return errors === 0;
2963
+ }
2964
+ function validate25(data, { instancePath = "", parentData, parentDataProperty, rootData = data } = {}) {
2965
+ let vErrors = null;
2966
+ let errors = 0;
2967
+ if (data && typeof data == "object" && !Array.isArray(data)) {
2968
+ if (data.paths === void 0) {
2969
+ const err0 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "paths" }, message: "must have required property 'paths'" };
2970
+ if (vErrors === null) {
2971
+ vErrors = [err0];
2972
+ } else {
2973
+ vErrors.push(err0);
2974
+ }
2975
+ errors++;
2976
+ }
2977
+ for (const key0 in data) {
2978
+ if (!(key0 === "paths")) {
2979
+ const err1 = { instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" };
2980
+ if (vErrors === null) {
2981
+ vErrors = [err1];
2982
+ } else {
2983
+ vErrors.push(err1);
2984
+ }
2985
+ errors++;
2986
+ }
2987
+ }
2988
+ if (data.paths !== void 0) {
2989
+ let data0 = data.paths;
2990
+ if (Array.isArray(data0)) {
2991
+ if (data0.length < 1) {
2992
+ const err2 = { instancePath: instancePath + "/paths", schemaPath: "#/properties/paths/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
2993
+ if (vErrors === null) {
2994
+ vErrors = [err2];
2995
+ } else {
2996
+ vErrors.push(err2);
2997
+ }
2998
+ errors++;
2999
+ }
3000
+ const len0 = data0.length;
3001
+ for (let i0 = 0; i0 < len0; i0++) {
3002
+ if (!validate26(data0[i0], { instancePath: instancePath + "/paths/" + i0, parentData: data0, parentDataProperty: i0, rootData })) {
3003
+ vErrors = vErrors === null ? validate26.errors : vErrors.concat(validate26.errors);
3004
+ errors = vErrors.length;
3005
+ }
3006
+ }
3007
+ } else {
3008
+ const err3 = { instancePath: instancePath + "/paths", schemaPath: "#/properties/paths/type", keyword: "type", params: { type: "array" }, message: "must be array" };
3009
+ if (vErrors === null) {
3010
+ vErrors = [err3];
3011
+ } else {
3012
+ vErrors.push(err3);
3013
+ }
3014
+ errors++;
3015
+ }
3016
+ }
3017
+ } else {
3018
+ const err4 = { instancePath, schemaPath: "#/type", keyword: "type", params: { type: "object" }, message: "must be object" };
3019
+ if (vErrors === null) {
3020
+ vErrors = [err4];
3021
+ } else {
3022
+ vErrors.push(err4);
3023
+ }
3024
+ errors++;
3025
+ }
3026
+ validate25.errors = vErrors;
3027
+ return errors === 0;
3028
+ }
2464
3029
  function validate10(data, { instancePath = "", parentData, parentDataProperty, rootData = data } = {}) {
2465
3030
  let vErrors = null;
2466
3031
  let errors = 0;
@@ -2502,9 +3067,11 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2502
3067
  let ifClause0;
2503
3068
  if (_valid0) {
2504
3069
  const _errs4 = errors;
3070
+ const _errs5 = errors;
3071
+ const _errs6 = errors;
2505
3072
  if (data && typeof data == "object" && !Array.isArray(data)) {
2506
- if (data.sequence === void 0) {
2507
- const err2 = { instancePath, schemaPath: "#/then/required", keyword: "required", params: { missingProperty: "sequence" }, message: "must have required property 'sequence'" };
3073
+ if (data.state === void 0 && ("state")) {
3074
+ const err2 = {};
2508
3075
  if (vErrors === null) {
2509
3076
  vErrors = [err2];
2510
3077
  } else {
@@ -2513,227 +3080,391 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2513
3080
  errors++;
2514
3081
  }
2515
3082
  }
3083
+ var valid2 = _errs6 === errors;
3084
+ if (valid2) {
3085
+ const err3 = { instancePath, schemaPath: "#/then/not", keyword: "not", params: {}, message: "must NOT be valid" };
3086
+ if (vErrors === null) {
3087
+ vErrors = [err3];
3088
+ } else {
3089
+ vErrors.push(err3);
3090
+ }
3091
+ errors++;
3092
+ } else {
3093
+ errors = _errs5;
3094
+ if (vErrors !== null) {
3095
+ if (_errs5) {
3096
+ vErrors.length = _errs5;
3097
+ } else {
3098
+ vErrors = null;
3099
+ }
3100
+ }
3101
+ }
3102
+ if (data && typeof data == "object" && !Array.isArray(data)) {
3103
+ if (data.sequence === void 0) {
3104
+ const err4 = { instancePath, schemaPath: "#/then/required", keyword: "required", params: { missingProperty: "sequence" }, message: "must have required property 'sequence'" };
3105
+ if (vErrors === null) {
3106
+ vErrors = [err4];
3107
+ } else {
3108
+ vErrors.push(err4);
3109
+ }
3110
+ errors++;
3111
+ }
3112
+ }
2516
3113
  var _valid0 = _errs4 === errors;
2517
3114
  valid0 = _valid0;
2518
3115
  ifClause0 = "then";
2519
3116
  } else {
2520
- const _errs5 = errors;
2521
- const _errs6 = errors;
2522
3117
  const _errs7 = errors;
3118
+ const _errs8 = errors;
3119
+ const _errs9 = errors;
2523
3120
  if (data && typeof data == "object" && !Array.isArray(data)) {
2524
3121
  if (data.sequence === void 0 && ("sequence")) {
2525
- const err3 = {};
3122
+ const err5 = {};
2526
3123
  if (vErrors === null) {
2527
- vErrors = [err3];
3124
+ vErrors = [err5];
2528
3125
  } else {
2529
- vErrors.push(err3);
3126
+ vErrors.push(err5);
2530
3127
  }
2531
3128
  errors++;
2532
3129
  }
2533
3130
  }
2534
- var valid2 = _errs7 === errors;
2535
- if (valid2) {
2536
- const err4 = { instancePath, schemaPath: "#/else/not", keyword: "not", params: {}, message: "must NOT be valid" };
3131
+ var valid3 = _errs9 === errors;
3132
+ if (valid3) {
3133
+ const err6 = { instancePath, schemaPath: "#/else/not", keyword: "not", params: {}, message: "must NOT be valid" };
2537
3134
  if (vErrors === null) {
2538
- vErrors = [err4];
3135
+ vErrors = [err6];
2539
3136
  } else {
2540
- vErrors.push(err4);
3137
+ vErrors.push(err6);
2541
3138
  }
2542
3139
  errors++;
2543
3140
  } else {
2544
- errors = _errs6;
3141
+ errors = _errs8;
2545
3142
  if (vErrors !== null) {
2546
- if (_errs6) {
2547
- vErrors.length = _errs6;
3143
+ if (_errs8) {
3144
+ vErrors.length = _errs8;
2548
3145
  } else {
2549
3146
  vErrors = null;
2550
3147
  }
2551
3148
  }
2552
3149
  }
2553
- var _valid0 = _errs5 === errors;
3150
+ const _errs10 = errors;
3151
+ let valid4 = true;
3152
+ const _errs11 = errors;
3153
+ if (data && typeof data == "object" && !Array.isArray(data)) {
3154
+ if (data.kind === void 0 && ("kind")) {
3155
+ const err7 = {};
3156
+ if (vErrors === null) {
3157
+ vErrors = [err7];
3158
+ } else {
3159
+ vErrors.push(err7);
3160
+ }
3161
+ errors++;
3162
+ } else {
3163
+ if (data.kind !== void 0) {
3164
+ if ("state" !== data.kind) {
3165
+ const err8 = {};
3166
+ if (vErrors === null) {
3167
+ vErrors = [err8];
3168
+ } else {
3169
+ vErrors.push(err8);
3170
+ }
3171
+ errors++;
3172
+ }
3173
+ }
3174
+ }
3175
+ }
3176
+ var _valid1 = _errs11 === errors;
3177
+ errors = _errs10;
3178
+ if (vErrors !== null) {
3179
+ if (_errs10) {
3180
+ vErrors.length = _errs10;
3181
+ } else {
3182
+ vErrors = null;
3183
+ }
3184
+ }
3185
+ let ifClause1;
3186
+ if (_valid1) {
3187
+ const _errs13 = errors;
3188
+ if (data && typeof data == "object" && !Array.isArray(data)) {
3189
+ if (data.boxes !== void 0) {
3190
+ let data2 = data.boxes;
3191
+ if (Array.isArray(data2)) {
3192
+ const len0 = data2.length;
3193
+ for (let i0 = 0; i0 < len0; i0++) {
3194
+ let data3 = data2[i0];
3195
+ if (data3 && typeof data3 == "object" && !Array.isArray(data3)) {
3196
+ if (data3.id !== void 0) {
3197
+ let data4 = data3.id;
3198
+ const _errs17 = errors;
3199
+ const _errs18 = errors;
3200
+ if (!(data4 === "start" || data4 === "finish")) {
3201
+ const err9 = {};
3202
+ if (vErrors === null) {
3203
+ vErrors = [err9];
3204
+ } else {
3205
+ vErrors.push(err9);
3206
+ }
3207
+ errors++;
3208
+ }
3209
+ var valid10 = _errs18 === errors;
3210
+ if (valid10) {
3211
+ const err10 = { instancePath: instancePath + "/boxes/" + i0 + "/id", schemaPath: "#/else/then/properties/boxes/items/properties/id/not", keyword: "not", params: {}, message: "must NOT be valid" };
3212
+ if (vErrors === null) {
3213
+ vErrors = [err10];
3214
+ } else {
3215
+ vErrors.push(err10);
3216
+ }
3217
+ errors++;
3218
+ } else {
3219
+ errors = _errs17;
3220
+ if (vErrors !== null) {
3221
+ if (_errs17) {
3222
+ vErrors.length = _errs17;
3223
+ } else {
3224
+ vErrors = null;
3225
+ }
3226
+ }
3227
+ }
3228
+ }
3229
+ }
3230
+ }
3231
+ }
3232
+ }
3233
+ }
3234
+ var _valid1 = _errs13 === errors;
3235
+ valid4 = _valid1;
3236
+ ifClause1 = "then";
3237
+ } else {
3238
+ const _errs19 = errors;
3239
+ const _errs20 = errors;
3240
+ const _errs21 = errors;
3241
+ if (data && typeof data == "object" && !Array.isArray(data)) {
3242
+ if (data.state === void 0 && ("state")) {
3243
+ const err11 = {};
3244
+ if (vErrors === null) {
3245
+ vErrors = [err11];
3246
+ } else {
3247
+ vErrors.push(err11);
3248
+ }
3249
+ errors++;
3250
+ }
3251
+ }
3252
+ var valid11 = _errs21 === errors;
3253
+ if (valid11) {
3254
+ const err12 = { instancePath, schemaPath: "#/else/else/not", keyword: "not", params: {}, message: "must NOT be valid" };
3255
+ if (vErrors === null) {
3256
+ vErrors = [err12];
3257
+ } else {
3258
+ vErrors.push(err12);
3259
+ }
3260
+ errors++;
3261
+ } else {
3262
+ errors = _errs20;
3263
+ if (vErrors !== null) {
3264
+ if (_errs20) {
3265
+ vErrors.length = _errs20;
3266
+ } else {
3267
+ vErrors = null;
3268
+ }
3269
+ }
3270
+ }
3271
+ var _valid1 = _errs19 === errors;
3272
+ valid4 = _valid1;
3273
+ ifClause1 = "else";
3274
+ }
3275
+ if (!valid4) {
3276
+ const err13 = { instancePath, schemaPath: "#/else/if", keyword: "if", params: { failingKeyword: ifClause1 }, message: 'must match "' + ifClause1 + '" schema' };
3277
+ if (vErrors === null) {
3278
+ vErrors = [err13];
3279
+ } else {
3280
+ vErrors.push(err13);
3281
+ }
3282
+ errors++;
3283
+ }
3284
+ var _valid0 = _errs7 === errors;
2554
3285
  valid0 = _valid0;
2555
3286
  ifClause0 = "else";
2556
3287
  }
2557
3288
  if (!valid0) {
2558
- const err5 = { instancePath, schemaPath: "#/if", keyword: "if", params: { failingKeyword: ifClause0 }, message: 'must match "' + ifClause0 + '" schema' };
3289
+ const err14 = { instancePath, schemaPath: "#/if", keyword: "if", params: { failingKeyword: ifClause0 }, message: 'must match "' + ifClause0 + '" schema' };
2559
3290
  if (vErrors === null) {
2560
- vErrors = [err5];
3291
+ vErrors = [err14];
2561
3292
  } else {
2562
- vErrors.push(err5);
3293
+ vErrors.push(err14);
2563
3294
  }
2564
3295
  errors++;
2565
3296
  }
2566
3297
  if (data && typeof data == "object" && !Array.isArray(data)) {
2567
3298
  if (data.version === void 0) {
2568
- const err6 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "version" }, message: "must have required property 'version'" };
3299
+ const err15 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "version" }, message: "must have required property 'version'" };
2569
3300
  if (vErrors === null) {
2570
- vErrors = [err6];
3301
+ vErrors = [err15];
2571
3302
  } else {
2572
- vErrors.push(err6);
3303
+ vErrors.push(err15);
2573
3304
  }
2574
3305
  errors++;
2575
3306
  }
2576
3307
  if (data.kind === void 0) {
2577
- const err7 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "kind" }, message: "must have required property 'kind'" };
3308
+ const err16 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "kind" }, message: "must have required property 'kind'" };
2578
3309
  if (vErrors === null) {
2579
- vErrors = [err7];
3310
+ vErrors = [err16];
2580
3311
  } else {
2581
- vErrors.push(err7);
3312
+ vErrors.push(err16);
2582
3313
  }
2583
3314
  errors++;
2584
3315
  }
2585
3316
  if (data.title === void 0) {
2586
- const err8 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "title" }, message: "must have required property 'title'" };
3317
+ const err17 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "title" }, message: "must have required property 'title'" };
2587
3318
  if (vErrors === null) {
2588
- vErrors = [err8];
3319
+ vErrors = [err17];
2589
3320
  } else {
2590
- vErrors.push(err8);
3321
+ vErrors.push(err17);
2591
3322
  }
2592
3323
  errors++;
2593
3324
  }
2594
3325
  if (data.boxes === void 0) {
2595
- const err9 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "boxes" }, message: "must have required property 'boxes'" };
3326
+ const err18 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "boxes" }, message: "must have required property 'boxes'" };
2596
3327
  if (vErrors === null) {
2597
- vErrors = [err9];
3328
+ vErrors = [err18];
2598
3329
  } else {
2599
- vErrors.push(err9);
3330
+ vErrors.push(err18);
2600
3331
  }
2601
3332
  errors++;
2602
3333
  }
2603
3334
  if (data.steps === void 0) {
2604
- const err10 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "steps" }, message: "must have required property 'steps'" };
3335
+ const err19 = { instancePath, schemaPath: "#/required", keyword: "required", params: { missingProperty: "steps" }, message: "must have required property 'steps'" };
2605
3336
  if (vErrors === null) {
2606
- vErrors = [err10];
3337
+ vErrors = [err19];
2607
3338
  } else {
2608
- vErrors.push(err10);
3339
+ vErrors.push(err19);
2609
3340
  }
2610
3341
  errors++;
2611
3342
  }
2612
3343
  for (const key0 in data) {
2613
3344
  if (!func2.call(schema11.properties, key0)) {
2614
- const err11 = { instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" };
3345
+ const err20 = { instancePath, schemaPath: "#/additionalProperties", keyword: "additionalProperties", params: { additionalProperty: key0 }, message: "must NOT have additional properties" };
2615
3346
  if (vErrors === null) {
2616
- vErrors = [err11];
3347
+ vErrors = [err20];
2617
3348
  } else {
2618
- vErrors.push(err11);
3349
+ vErrors.push(err20);
2619
3350
  }
2620
3351
  errors++;
2621
3352
  }
2622
3353
  }
2623
3354
  if (data.version !== void 0) {
2624
- let data1 = data.version;
2625
- if (!(typeof data1 == "number" && (!(data1 % 1) && !isNaN(data1)) && isFinite(data1))) {
2626
- const err12 = { instancePath: instancePath + "/version", schemaPath: "#/properties/version/type", keyword: "type", params: { type: "integer" }, message: "must be integer" };
3355
+ let data5 = data.version;
3356
+ if (!(typeof data5 == "number" && (!(data5 % 1) && !isNaN(data5)) && isFinite(data5))) {
3357
+ const err21 = { instancePath: instancePath + "/version", schemaPath: "#/properties/version/type", keyword: "type", params: { type: "integer" }, message: "must be integer" };
2627
3358
  if (vErrors === null) {
2628
- vErrors = [err12];
3359
+ vErrors = [err21];
2629
3360
  } else {
2630
- vErrors.push(err12);
3361
+ vErrors.push(err21);
2631
3362
  }
2632
3363
  errors++;
2633
3364
  }
2634
- if (typeof data1 == "number" && isFinite(data1)) {
2635
- if (data1 < 1 || isNaN(data1)) {
2636
- const err13 = { instancePath: instancePath + "/version", schemaPath: "#/properties/version/minimum", keyword: "minimum", params: { comparison: ">=", limit: 1 }, message: "must be >= 1" };
3365
+ if (typeof data5 == "number" && isFinite(data5)) {
3366
+ if (data5 < 1 || isNaN(data5)) {
3367
+ const err22 = { instancePath: instancePath + "/version", schemaPath: "#/properties/version/minimum", keyword: "minimum", params: { comparison: ">=", limit: 1 }, message: "must be >= 1" };
2637
3368
  if (vErrors === null) {
2638
- vErrors = [err13];
3369
+ vErrors = [err22];
2639
3370
  } else {
2640
- vErrors.push(err13);
3371
+ vErrors.push(err22);
2641
3372
  }
2642
3373
  errors++;
2643
3374
  }
2644
3375
  }
2645
3376
  }
2646
3377
  if (data.kind !== void 0) {
2647
- let data2 = data.kind;
2648
- if (!(data2 === "sequence" || data2 === "architecture")) {
2649
- const err14 = { instancePath: instancePath + "/kind", schemaPath: "#/properties/kind/enum", keyword: "enum", params: { allowedValues: schema11.properties.kind.enum }, message: "must be equal to one of the allowed values" };
3378
+ let data6 = data.kind;
3379
+ if (!(data6 === "sequence" || data6 === "architecture" || data6 === "state")) {
3380
+ const err23 = { instancePath: instancePath + "/kind", schemaPath: "#/properties/kind/enum", keyword: "enum", params: { allowedValues: schema11.properties.kind.enum }, message: "must be equal to one of the allowed values" };
2650
3381
  if (vErrors === null) {
2651
- vErrors = [err14];
3382
+ vErrors = [err23];
2652
3383
  } else {
2653
- vErrors.push(err14);
3384
+ vErrors.push(err23);
2654
3385
  }
2655
3386
  errors++;
2656
3387
  }
2657
3388
  }
2658
3389
  if (data.title !== void 0) {
2659
- let data3 = data.title;
2660
- if (typeof data3 === "string") {
2661
- if (func3(data3) < 1) {
2662
- const err15 = { instancePath: instancePath + "/title", schemaPath: "#/definitions/text/minLength", keyword: "minLength", params: { limit: 1 }, message: "must NOT have fewer than 1 characters" };
3390
+ let data7 = data.title;
3391
+ if (typeof data7 === "string") {
3392
+ if (func3(data7) < 1) {
3393
+ const err24 = { instancePath: instancePath + "/title", schemaPath: "#/definitions/text/minLength", keyword: "minLength", params: { limit: 1 }, message: "must NOT have fewer than 1 characters" };
2663
3394
  if (vErrors === null) {
2664
- vErrors = [err15];
3395
+ vErrors = [err24];
2665
3396
  } else {
2666
- vErrors.push(err15);
3397
+ vErrors.push(err24);
2667
3398
  }
2668
3399
  errors++;
2669
3400
  }
2670
3401
  } else {
2671
- const err16 = { instancePath: instancePath + "/title", schemaPath: "#/definitions/text/type", keyword: "type", params: { type: "string" }, message: "must be string" };
3402
+ const err25 = { instancePath: instancePath + "/title", schemaPath: "#/definitions/text/type", keyword: "type", params: { type: "string" }, message: "must be string" };
2672
3403
  if (vErrors === null) {
2673
- vErrors = [err16];
3404
+ vErrors = [err25];
2674
3405
  } else {
2675
- vErrors.push(err16);
3406
+ vErrors.push(err25);
2676
3407
  }
2677
3408
  errors++;
2678
3409
  }
2679
3410
  }
2680
3411
  if (data.view !== void 0) {
2681
- let data4 = data.view;
2682
- if (!(data4 === "fixed" || data4 === "follow")) {
2683
- const err17 = { instancePath: instancePath + "/view", schemaPath: "#/properties/view/enum", keyword: "enum", params: { allowedValues: schema11.properties.view.enum }, message: "must be equal to one of the allowed values" };
3412
+ let data8 = data.view;
3413
+ if (!(data8 === "fixed" || data8 === "follow")) {
3414
+ const err26 = { instancePath: instancePath + "/view", schemaPath: "#/properties/view/enum", keyword: "enum", params: { allowedValues: schema11.properties.view.enum }, message: "must be equal to one of the allowed values" };
2684
3415
  if (vErrors === null) {
2685
- vErrors = [err17];
3416
+ vErrors = [err26];
2686
3417
  } else {
2687
- vErrors.push(err17);
3418
+ vErrors.push(err26);
2688
3419
  }
2689
3420
  errors++;
2690
3421
  }
2691
3422
  }
2692
3423
  if (data.regions !== void 0) {
2693
- let data5 = data.regions;
2694
- if (Array.isArray(data5)) {
2695
- const len0 = data5.length;
2696
- for (let i0 = 0; i0 < len0; i0++) {
2697
- if (!validate11(data5[i0], { instancePath: instancePath + "/regions/" + i0, parentData: data5, parentDataProperty: i0, rootData })) {
3424
+ let data9 = data.regions;
3425
+ if (Array.isArray(data9)) {
3426
+ const len1 = data9.length;
3427
+ for (let i1 = 0; i1 < len1; i1++) {
3428
+ if (!validate11(data9[i1], { instancePath: instancePath + "/regions/" + i1, parentData: data9, parentDataProperty: i1, rootData })) {
2698
3429
  vErrors = vErrors === null ? validate11.errors : vErrors.concat(validate11.errors);
2699
3430
  errors = vErrors.length;
2700
3431
  }
2701
3432
  }
2702
3433
  } else {
2703
- const err18 = { instancePath: instancePath + "/regions", schemaPath: "#/properties/regions/type", keyword: "type", params: { type: "array" }, message: "must be array" };
3434
+ const err27 = { instancePath: instancePath + "/regions", schemaPath: "#/properties/regions/type", keyword: "type", params: { type: "array" }, message: "must be array" };
2704
3435
  if (vErrors === null) {
2705
- vErrors = [err18];
3436
+ vErrors = [err27];
2706
3437
  } else {
2707
- vErrors.push(err18);
3438
+ vErrors.push(err27);
2708
3439
  }
2709
3440
  errors++;
2710
3441
  }
2711
3442
  }
2712
3443
  if (data.boxes !== void 0) {
2713
- let data7 = data.boxes;
2714
- if (Array.isArray(data7)) {
2715
- if (data7.length < 1) {
2716
- const err19 = { instancePath: instancePath + "/boxes", schemaPath: "#/properties/boxes/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
3444
+ let data11 = data.boxes;
3445
+ if (Array.isArray(data11)) {
3446
+ if (data11.length < 1) {
3447
+ const err28 = { instancePath: instancePath + "/boxes", schemaPath: "#/properties/boxes/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
2717
3448
  if (vErrors === null) {
2718
- vErrors = [err19];
3449
+ vErrors = [err28];
2719
3450
  } else {
2720
- vErrors.push(err19);
3451
+ vErrors.push(err28);
2721
3452
  }
2722
3453
  errors++;
2723
3454
  }
2724
- const len1 = data7.length;
2725
- for (let i1 = 0; i1 < len1; i1++) {
2726
- if (!validate13(data7[i1], { instancePath: instancePath + "/boxes/" + i1, parentData: data7, parentDataProperty: i1, rootData })) {
3455
+ const len2 = data11.length;
3456
+ for (let i2 = 0; i2 < len2; i2++) {
3457
+ if (!validate13(data11[i2], { instancePath: instancePath + "/boxes/" + i2, parentData: data11, parentDataProperty: i2, rootData })) {
2727
3458
  vErrors = vErrors === null ? validate13.errors : vErrors.concat(validate13.errors);
2728
3459
  errors = vErrors.length;
2729
3460
  }
2730
3461
  }
2731
3462
  } else {
2732
- const err20 = { instancePath: instancePath + "/boxes", schemaPath: "#/properties/boxes/type", keyword: "type", params: { type: "array" }, message: "must be array" };
3463
+ const err29 = { instancePath: instancePath + "/boxes", schemaPath: "#/properties/boxes/type", keyword: "type", params: { type: "array" }, message: "must be array" };
2733
3464
  if (vErrors === null) {
2734
- vErrors = [err20];
3465
+ vErrors = [err29];
2735
3466
  } else {
2736
- vErrors.push(err20);
3467
+ vErrors.push(err29);
2737
3468
  }
2738
3469
  errors++;
2739
3470
  }
@@ -2745,30 +3476,30 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2745
3476
  }
2746
3477
  }
2747
3478
  if (data.steps !== void 0) {
2748
- let data10 = data.steps;
2749
- if (Array.isArray(data10)) {
2750
- if (data10.length < 1) {
2751
- const err21 = { instancePath: instancePath + "/steps", schemaPath: "#/properties/steps/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
3479
+ let data14 = data.steps;
3480
+ if (Array.isArray(data14)) {
3481
+ if (data14.length < 1) {
3482
+ const err30 = { instancePath: instancePath + "/steps", schemaPath: "#/properties/steps/minItems", keyword: "minItems", params: { limit: 1 }, message: "must NOT have fewer than 1 items" };
2752
3483
  if (vErrors === null) {
2753
- vErrors = [err21];
3484
+ vErrors = [err30];
2754
3485
  } else {
2755
- vErrors.push(err21);
3486
+ vErrors.push(err30);
2756
3487
  }
2757
3488
  errors++;
2758
3489
  }
2759
- const len2 = data10.length;
2760
- for (let i2 = 0; i2 < len2; i2++) {
2761
- if (!validate17(data10[i2], { instancePath: instancePath + "/steps/" + i2, parentData: data10, parentDataProperty: i2, rootData })) {
3490
+ const len3 = data14.length;
3491
+ for (let i3 = 0; i3 < len3; i3++) {
3492
+ if (!validate17(data14[i3], { instancePath: instancePath + "/steps/" + i3, parentData: data14, parentDataProperty: i3, rootData })) {
2762
3493
  vErrors = vErrors === null ? validate17.errors : vErrors.concat(validate17.errors);
2763
3494
  errors = vErrors.length;
2764
3495
  }
2765
3496
  }
2766
3497
  } else {
2767
- const err22 = { instancePath: instancePath + "/steps", schemaPath: "#/properties/steps/type", keyword: "type", params: { type: "array" }, message: "must be array" };
3498
+ const err31 = { instancePath: instancePath + "/steps", schemaPath: "#/properties/steps/type", keyword: "type", params: { type: "array" }, message: "must be array" };
2768
3499
  if (vErrors === null) {
2769
- vErrors = [err22];
3500
+ vErrors = [err31];
2770
3501
  } else {
2771
- vErrors.push(err22);
3502
+ vErrors.push(err31);
2772
3503
  }
2773
3504
  errors++;
2774
3505
  }
@@ -2779,12 +3510,18 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2779
3510
  errors = vErrors.length;
2780
3511
  }
2781
3512
  }
3513
+ if (data.state !== void 0) {
3514
+ if (!validate25(data.state, { instancePath: instancePath + "/state", parentData: data, parentDataProperty: "state", rootData })) {
3515
+ vErrors = vErrors === null ? validate25.errors : vErrors.concat(validate25.errors);
3516
+ errors = vErrors.length;
3517
+ }
3518
+ }
2782
3519
  } else {
2783
- const err23 = { instancePath, schemaPath: "#/type", keyword: "type", params: { type: "object" }, message: "must be object" };
3520
+ const err32 = { instancePath, schemaPath: "#/type", keyword: "type", params: { type: "object" }, message: "must be object" };
2784
3521
  if (vErrors === null) {
2785
- vErrors = [err23];
3522
+ vErrors = [err32];
2786
3523
  } else {
2787
- vErrors.push(err23);
3524
+ vErrors.push(err32);
2788
3525
  }
2789
3526
  errors++;
2790
3527
  }
@@ -2795,10 +3532,15 @@ function validate10(data, { instancePath = "", parentData, parentDataProperty, r
2795
3532
  // src/schema.ts
2796
3533
  var COLORS = ["blue", "amber", "green", "violet", "rose", "slate", "coin"];
2797
3534
  var EVENT_TYPES = ["edge", "action", "swap", "strip"];
3535
+ var ROOT_NOT_ALLOWED = {
3536
+ "#/else/not": { field: "sequence", kind: "sequence" },
3537
+ "#/then/not": { field: "state", kind: "state" },
3538
+ "#/else/else/not": { field: "state", kind: "state" }
3539
+ };
2798
3540
  var NOT_ALLOWED = {
2799
- "": { field: "sequence", kind: "sequence" },
2800
3541
  carry: { field: "text", kind: "tag" }
2801
3542
  };
3543
+ var RESERVED_ID = /\/boxes\/items\/properties\/id\/not$/u;
2802
3544
  var escape = (key) => key.replaceAll("~", "~0").replaceAll("/", "~1");
2803
3545
  function forbiddenOf(pattern) {
2804
3546
  const inside = /^\^\[\^(.+)\]\+\$$/u.exec(pattern)?.[1];
@@ -2822,7 +3564,8 @@ function toFieldError(error, errors, m) {
2822
3564
  return { pointer: `${at2}/${escape(key)}`, message: m.required(key) };
2823
3565
  }
2824
3566
  case "not": {
2825
- const allowed = NOT_ALLOWED[at2.slice(at2.lastIndexOf("/") + 1)];
3567
+ if (RESERVED_ID.test(error.schemaPath)) return { pointer: at2, message: m.reserved(STATE_ENDS) };
3568
+ const allowed = at2 === "" ? ROOT_NOT_ALLOWED[error.schemaPath] : NOT_ALLOWED[at2.slice(at2.lastIndexOf("/") + 1)];
2826
3569
  return { pointer: allowed ? `${at2}/${allowed.field}` : at2, message: m.not(allowed) };
2827
3570
  }
2828
3571
  case "anyOf": {
@@ -2941,6 +3684,7 @@ function buildTimeline(diagram) {
2941
3684
  const later = named[k + 2];
2942
3685
  if (later) label2.end = Math.min(label2.end, later.start);
2943
3686
  });
3687
+ if (diagram.kind === "state") for (const label2 of named) label2.after = { start: label2.end, end: last };
2944
3688
  labels.push(...named);
2945
3689
  for (const event of p.events) events.push({ step: s, event: event.event, at: span.start + event.at });
2946
3690
  });
@@ -2964,6 +3708,7 @@ function buildTimeline(diagram) {
2964
3708
  });
2965
3709
  }
2966
3710
  carriers.sort((x, y) => x.depart - y.depart);
3711
+ const states = diagram.kind === "state" ? stateTimes(diagram, edges, last) : void 0;
2967
3712
  return {
2968
3713
  total,
2969
3714
  last,
@@ -2973,8 +3718,32 @@ function buildTimeline(diagram) {
2973
3718
  labels,
2974
3719
  badges: steps.map((span, s) => ({ step: s, appears: span.start })),
2975
3720
  events,
2976
- stills: steps.map((span) => span.end - MOTION.still)
3721
+ stills: steps.map((span) => span.end - MOTION.still),
3722
+ ...states ? { states } : {}
3723
+ };
3724
+ }
3725
+ var isEnd2 = (id) => STATE_ENDS.includes(id);
3726
+ function stateTimes(diagram, edges, last) {
3727
+ const times = /* @__PURE__ */ new Map();
3728
+ const of = (box) => {
3729
+ const found = times.get(box) ?? { box, lit: [] };
3730
+ times.set(box, found);
3731
+ return found;
2977
3732
  };
3733
+ let on;
3734
+ for (const edge2 of edges) {
3735
+ const event = diagram.steps[edge2.step]?.events[edge2.event];
3736
+ if (event?.type !== "edge" || event.from === event.to) continue;
3737
+ if (on) {
3738
+ const left = of(on.box);
3739
+ left.lit.push({ start: on.since, end: edge2.start });
3740
+ if (on.box === event.from && left.done === void 0) left.done = edge2.start + MOTION.done;
3741
+ on = void 0;
3742
+ }
3743
+ if (!isEnd2(event.to)) on = { box: event.to, since: edge2.drawn };
3744
+ }
3745
+ if (on) of(on.box).lit.push({ start: on.since, end: last });
3746
+ return [...times.values()];
2978
3747
  }
2979
3748
 
2980
3749
  // src/render/icons.ts
@@ -3009,6 +3778,8 @@ var ICONS = {
3009
3778
  branch: "M -4 -4.5 v9 M 5 0.5 c0 4 -9 3 -9 6.5 M -6.2 -7 a2.2 2.2 0 1 0 4.4 0 a2.2 2.2 0 1 0 -4.4 0 M -6.2 7 a2.2 2.2 0 1 0 4.4 0 a2.2 2.2 0 1 0 -4.4 0 M 2.8 -2 a2.2 2.2 0 1 0 4.4 0 a2.2 2.2 0 1 0 -4.4 0",
3010
3779
  cloud: "M -7 6 h13 a4.5 4.5 0 0 0 0.5 -9 a6 6 0 0 0 -11.5 -1 a4.5 4.5 0 0 0 -2 10 z",
3011
3780
  refresh: "M 7 -3 a7.5 7.5 0 1 0 0.5 5 M 7.5 -8 v5 h-5",
3781
+ undo: "M -7 -2 h10 a5 5 0 0 1 0 10 h-6 M -3 -6 l-4 4 l4 4",
3782
+ yen: "M -6 -8 l6 7 l6 -7 M 0 -1 v9 M -5 1.5 h10 M -5 5 h10",
3012
3783
  layers: "M 0 -8 l9 4.5 l-9 4.5 l-9 -4.5 z M -9 2.5 l9 4.5 l9 -4.5",
3013
3784
  code: "M -4 -6 l-5 6 l5 6 M 4 -6 l5 6 l-5 6",
3014
3785
  paint: "M -8 8 c 0 -3 2 -5 4.5 -5 l 9 -9 l 3.5 3.5 l -9 9 c 0 2.5 -2 4.5 -5 4.5 z",
@@ -3023,7 +3794,25 @@ function glyph(name, x, y, scale, cls = "dg-gl") {
3023
3794
  const d = name === void 0 ? void 0 : ICONS[name];
3024
3795
  return d ? `<path class="${cls}" transform="translate(${r1(x)} ${r1(y)}) scale(${scale})" d="${d}"/>` : "";
3025
3796
  }
3026
- var pathOf = (points) => points.map(([x, y], i) => `${i === 0 ? "M" : "L"} ${r1(x)} ${r1(y)}`).join(" ");
3797
+ function pathOf(points) {
3798
+ const pts = points.filter((p, i) => i === 0 || p[0] !== points[i - 1][0] || p[1] !== points[i - 1][1]);
3799
+ const [x0, y0] = pts[0];
3800
+ let d = `M ${r1(x0)} ${r1(y0)}`;
3801
+ for (let i = 1; i < pts.length - 1; i++) {
3802
+ const [ax, ay] = pts[i - 1];
3803
+ const [bx, by] = pts[i];
3804
+ const [cx, cy] = pts[i + 1];
3805
+ const l1 = Math.hypot(bx - ax, by - ay);
3806
+ const l2 = Math.hypot(cx - bx, cy - by);
3807
+ const a = Math.min(LOOK.edge.bend, l1 / 2, l2 / 2);
3808
+ d += ` L ${r1(bx - (bx - ax) / l1 * a)} ${r1(by - (by - ay) / l1 * a)} Q ${r1(bx)} ${r1(by)} ${r1(bx + (cx - bx) / l2 * a)} ${r1(by + (cy - by) / l2 * a)}`;
3809
+ }
3810
+ if (pts.length > 1) {
3811
+ const [lx, ly] = pts[pts.length - 1];
3812
+ d += ` L ${r1(lx)} ${r1(ly)}`;
3813
+ }
3814
+ return d;
3815
+ }
3027
3816
  function arrowHead(points) {
3028
3817
  const [ex, ey] = points[points.length - 1];
3029
3818
  const [px, py] = points[points.length - 2];
@@ -3070,10 +3859,10 @@ function cardFrame(box, ctx, act, y, h) {
3070
3859
  const rect = (cls, extra = "") => `<rect class="${cls}" x="${r1(box.x)}" y="${r1(y)}" width="${r1(box.w)}" height="${h}" rx="${LOOK.box.radius}"${extra}/>`;
3071
3860
  return `${act ? `<g class="dg-a" style="${act}">${rect("dg-halo")}</g>` : ""}${rect("dg-st", ` ${ctx.sh}`)}${act ? `<g class="dg-a" style="${act}">${rect("dg-on")}</g>` : ""}`;
3072
3861
  }
3073
- function card(box, ctx, on, changes) {
3862
+ function card(box, ctx, on, changes, lit) {
3074
3863
  const { icon, iconRadius, iconScale, iconY, nameY, subY } = LOOK.box;
3075
3864
  const subs = subLines(box, ctx.m, changes, box.cy + subY);
3076
- const act = on.length > 0 ? activeKf(ctx, on) : void 0;
3865
+ const act = lit ? lit.length > 0 ? rangeKf(ctx.m, lit.map((s) => [s.start, s.end])) : void 0 : on.length > 0 ? activeKf(ctx, on) : void 0;
3077
3866
  const mark = box.icon && ICONS[box.icon] ? `<rect class="dg-ic" x="${r1(box.cx - icon / 2)}" y="${r1(box.cy + iconY - icon / 2)}" width="${icon}" height="${icon}" rx="${iconRadius}"/>${glyph(box.icon, box.cx, box.cy + iconY, iconScale)}` : "";
3078
3867
  return `<g style="${cs(box.color)}">${cardFrame(box, ctx, act, box.y, box.h)}${mark}<text class="dg-sn" x="${r1(box.cx)}" y="${r1(box.cy + nameY)}" text-anchor="middle">${esc(box.name)}</text>${subs}</g>`;
3079
3868
  }
@@ -3083,15 +3872,54 @@ function headCard(box, ctx, on, changes) {
3083
3872
  const act = on.length > 0 ? activeKf(ctx, on) : void 0;
3084
3873
  return `<g style="${cs(box.color)}">${cardFrame(box, ctx, act, pad2, h)}<text class="dg-sn" x="${r1(box.cx)}" y="${r1(pad2 + nameY)}" text-anchor="middle">${esc(box.name)}</text>${subs}</g>`;
3085
3874
  }
3875
+ function ghostCard(box) {
3876
+ const { icon, iconRadius, iconScale, radius } = LOOK.box;
3877
+ const G = LOOK.state.ghost;
3878
+ const ix = box.x + G.pad + icon / 2;
3879
+ const tx = box.x + G.pad + icon + G.gap;
3880
+ const mark = box.icon && ICONS[box.icon] ? `<rect class="dg-ic" x="${r1(ix - icon / 2)}" y="${r1(box.cy - icon / 2)}" width="${icon}" height="${icon}" rx="${iconRadius}"/>${glyph(box.icon, ix, box.cy, iconScale)}` : "";
3881
+ const nameY = box.sub ? G.nameY : LOOK.baseline.mark;
3882
+ const sub = box.sub ? `<text class="dg-ss" x="${r1(tx)}" y="${r1(box.cy + G.subY)}" text-anchor="start">${esc(box.sub)}</text>` : "";
3883
+ return `<g data-ghost="${esc(box.id)}" style="${cs(box.color)}"><rect class="dg-ghost" x="${r1(box.x)}" y="${r1(box.y)}" width="${r1(box.w)}" height="${box.h}" rx="${radius}"/>${mark}<text class="dg-sn" x="${r1(tx)}" y="${r1(box.cy + nameY)}" text-anchor="start">${esc(box.name)}</text>${sub}</g>`;
3884
+ }
3885
+ function doneMark(box, at2, ctx) {
3886
+ const { r, inset } = LOOK.state.done;
3887
+ const x = box.x + box.w - inset;
3888
+ const y = box.y + inset;
3889
+ return `<g class="dg-popc dg-a" data-done="${esc(box.id)}" style="${cs(box.color)};${ctx.m.pop(at2)}"><circle class="dg-done" cx="${r1(x)}" cy="${r1(y)}" r="${r}"/>${glyph("check", x, y, 0.5, "dg-done-ck")}</g>`;
3890
+ }
3891
+ function path(p, color) {
3892
+ const label2 = p.label ? `<text class="dg-path-t${p.label.family === "sans" ? " dg-path-tj" : ""}" x="${r1(p.label.x + LOOK.label.padX)}" y="${r1(p.label.y + p.label.h / 2 + LOOK.baseline.label)}">${esc(p.label.text)}</text>` : "";
3893
+ return `<g data-path="${esc(`${p.from}->${p.to}`)}" style="${cs(color)}"><path class="dg-path" d="${pathOf(p.points)}"/><path class="dg-path-h" d="${arrowHead(p.points)}"/>${label2}</g>`;
3894
+ }
3895
+ function side(s, color) {
3896
+ const { pad: pad2 } = LOOK.state.side;
3897
+ const title = s.y + pad2 + TYPE.regionName.size;
3898
+ const notes = s.notes.map((note, k) => `<text class="dg-side-n" x="${r1(s.x + pad2)}" y="${r1(title + LOOK.region.line * (k + 1))}">${esc(note)}</text>`).join("");
3899
+ return `<g style="${cs(color)}"><rect class="dg-side" x="${r1(s.x + 0.5)}" y="${r1(s.y + 0.5)}" width="${r1(s.w - 1)}" height="${r1(s.h - 1)}" rx="${LOOK.region.radius}"/><text class="dg-side-t" x="${r1(s.x + pad2)}" y="${r1(title)}">${esc(s.title)}</text>${notes}</g>`;
3900
+ }
3901
+ function endMark(e, color) {
3902
+ const { end } = LOOK.state;
3903
+ const text2 = e.text === "" ? "" : `<text class="dg-mark" x="${r1(e.x + LOOK.state.text)}" y="${r1(e.y + LOOK.baseline.mark)}">${esc(e.text)}</text>`;
3904
+ const x = r1(e.x);
3905
+ const y = r1(e.y);
3906
+ if (e.kind === "start") return `<g data-end="start"><circle class="dg-start" cx="${x}" cy="${y}" r="${e.r}"/>${text2}</g>`;
3907
+ if (e.ghost) return `<g data-end="finish" style="${cs(color)}"><circle class="dg-end-x" cx="${x}" cy="${y}" r="${e.r}"/><circle class="dg-end-xi" cx="${x}" cy="${y}" r="${end.inner}"/>${text2}</g>`;
3908
+ return `<g data-end="finish"><circle class="dg-end" cx="${x}" cy="${y}" r="${e.r}"/><circle class="dg-end-in" cx="${x}" cy="${y}" r="${end.inner}"/>${text2}</g>`;
3909
+ }
3086
3910
  function lifeline(x, y1, y2) {
3087
3911
  return `<line class="dg-ll" x1="${r1(x)}" y1="${r1(y1)}" x2="${r1(x)}" y2="${r1(y2)}"/>`;
3088
3912
  }
3089
- function edge(e, time, ctx) {
3913
+ function edge(e, time, ctx, past = false) {
3090
3914
  const { m } = ctx;
3091
3915
  const d = pathOf(e.points);
3092
3916
  const head = arrowHead(e.points);
3093
3917
  const { start: a, drawn: b, end } = time;
3094
- const tail = [
3918
+ const tail = past ? [
3919
+ [end, { opacity: 1 }, EASE.inOut],
3920
+ [end + 0.4, { opacity: 0 }],
3921
+ [m.total, { opacity: 0 }]
3922
+ ] : [
3095
3923
  [end, { opacity: 1 }, EASE.inOut],
3096
3924
  [end + 0.4, { opacity: 0.45 }],
3097
3925
  [ctx.end + 0.3, { opacity: 0.45 }, EASE.inOut],
@@ -3118,15 +3946,19 @@ function edge(e, time, ctx) {
3118
3946
  [end + 0.2, { opacity: 0, "stroke-dashoffset": run }],
3119
3947
  [m.total, { opacity: 0, "stroke-dashoffset": run }]
3120
3948
  ]);
3949
+ const grey = past ? m.kf([[0, { opacity: 0 }], [end, { opacity: 0 }, EASE.inOut], [end + 0.4, { opacity: 1 }], [m.last, { opacity: 1 }, EASE.inOut], [m.total, { opacity: 0 }]]) : "";
3121
3950
  return {
3122
- base: `<path class="dg-e" d="${d}"/><path class="dg-eh" d="${head}"/>`,
3951
+ base: `<path class="dg-e" d="${d}"/><path class="dg-eh" d="${head}"/>${past ? `<path class="dg-e-past dg-a" d="${d}" style="${grey}"/><path class="dg-eh-past dg-a" d="${head}" style="${grey}"/>` : ""}`,
3123
3952
  lit: `<g style="${cs(e.color)}"><path class="dg-e-on dg-a" pathLength="1" d="${d}" style="${line}"/><path class="dg-eh-on dg-a" d="${head}" style="${hk}"/><path class="dg-flow dg-a" d="${d}" style="${flow}"/></g>`
3124
3953
  };
3125
3954
  }
3126
3955
  function label(l, time, ctx) {
3127
3956
  const ja3 = l.family === "sans" ? " dg-capj" : "";
3128
3957
  const { radius } = LOOK.label;
3129
- return `<g class="dg-cap${ja3} dg-a" style="${cs(l.color)};${ctx.m.rise(time.start, time.end, true)}"><rect x="${r1(l.x)}" y="${r1(l.y)}" width="${r1(l.w)}" height="${l.h}" rx="${radius}"/><text x="${r1(l.x + l.w / 2)}" y="${r1(l.y + l.h / 2 + LOOK.baseline.label)}" text-anchor="middle">${esc(l.text)}</text></g>`;
3958
+ const x = r1(l.x + l.w / 2);
3959
+ const y = r1(l.y + l.h / 2 + LOOK.baseline.label);
3960
+ const past = time.after ? `<g class="dg-cap-past${l.family === "sans" ? " dg-cap-pastj" : ""} dg-a" style="${ctx.m.vis(time.after.start, time.after.end)}"><text x="${x}" y="${y}" text-anchor="middle">${esc(l.text)}</text></g>` : "";
3961
+ return `${past}<g class="dg-cap${ja3} dg-a" style="${cs(l.color)};${ctx.m.rise(time.start, time.end, true)}"><rect x="${r1(l.x)}" y="${r1(l.y)}" width="${r1(l.w)}" height="${l.h}" rx="${radius}"/><text x="${x}" y="${y}" text-anchor="middle">${esc(l.text)}</text></g>`;
3130
3962
  }
3131
3963
  function action(a, at2, until, ctx) {
3132
3964
  return `<g class="dg-act dg-a" style="${cs(a.color)};${ctx.m.rise(at2, until, true)}"><rect x="${r1(a.x)}" y="${r1(a.y)}" width="${r1(a.w)}" height="${a.h}" rx="${LOOK.action.radius}"/><text x="${r1(a.x + a.w / 2)}" y="${r1(a.y + a.h / 2 + LOOK.baseline.action)}" text-anchor="middle">${esc(a.text)}</text></g>`;
@@ -3148,21 +3980,21 @@ function carrier(e, time, ctx) {
3148
3980
  const n = LOOK.carrier.samples;
3149
3981
  const length = pathLength(e.points);
3150
3982
  const { depart: a, arrive: b, start: from, end: gone } = time;
3151
- const path = [];
3983
+ const path2 = [];
3152
3984
  for (let k = 0; k <= n; k++) {
3153
3985
  const [x, y] = along(e.points, easeInOut(k / n) * length);
3154
- path.push([a + (b - a) * k / n, x, y]);
3986
+ path2.push([a + (b - a) * k / n, x, y]);
3155
3987
  }
3156
- const first = path[0];
3157
- const lastPoint = path[path.length - 1];
3988
+ const first = path2[0];
3989
+ const lastPoint = path2[path2.length - 1];
3158
3990
  const rest = e.settle ?? [lastPoint[1], lastPoint[2]];
3159
- const pts = [[0, first[1], first[2]], ...path];
3991
+ const pts = [[0, first[1], first[2]], ...path2];
3160
3992
  if (e.settle) pts.push([Math.min(b + 0.3, Math.max(gone, b + 0.01)), rest[0], rest[1]]);
3161
3993
  pts.push([gone, rest[0], rest[1]], [m.total, rest[0], rest[1]]);
3162
3994
  const fade = gone < m.last ? 0.05 : 0.18;
3163
3995
  return `<g class="dg-a" style="${m.move(pts, m.blink(from + 0.02, gone, fade))}">${carrierShape(e, ctx.sh)}</g>`;
3164
3996
  }
3165
- function badge(b, ctx) {
3997
+ function badge(b, ctx, grey = false) {
3166
3998
  const { m } = ctx;
3167
3999
  const span = ctx.t.steps[b.step];
3168
4000
  const a = span.start;
@@ -3188,9 +4020,9 @@ function badge(b, ctx) {
3188
4020
  const y = r1(b.y);
3189
4021
  const ty = r1(b.y + LOOK.baseline.badge);
3190
4022
  const no = b.step + 1;
3191
- return `<g class="dg-bd" data-step="${b.step}" style="${cs(b.color)}"><circle class="dg-bdr dg-popc dg-a" cx="${x}" cy="${y}" r="${rr}" style="${ring}"/><g class="dg-a" style="${past}"><circle class="dg-bdp" cx="${x}" cy="${y}" r="${rr}"/><text class="dg-bdpt" x="${x}" y="${ty}" text-anchor="middle">${no}</text></g><g class="dg-popc dg-a" style="${fill}"><circle class="dg-bdf" cx="${x}" cy="${y}" r="${r}"/><text class="dg-bdft" x="${x}" y="${ty}" text-anchor="middle">${no}</text></g></g>`;
4023
+ return `<g class="dg-bd" data-step="${b.step}" style="${cs(b.color)}"><circle class="dg-bdr dg-popc dg-a" cx="${x}" cy="${y}" r="${rr}" style="${ring}"/><g class="dg-a" style="${past}"><circle class="${grey ? "dg-bdp-g" : "dg-bdp"}" cx="${x}" cy="${y}" r="${rr}"/><text class="${grey ? "dg-bdpt-g" : "dg-bdpt"}" x="${x}" y="${ty}" text-anchor="middle">${no}</text></g><g class="dg-popc dg-a" style="${fill}"><circle class="dg-bdf" cx="${x}" cy="${y}" r="${r}"/><text class="dg-bdft" x="${x}" y="${ty}" text-anchor="middle">${no}</text></g></g>`;
3192
4024
  }
3193
- function strip(s, changes, ctx) {
4025
+ function strip(s, changes, ctx, now = false, arrivals = /* @__PURE__ */ new Map()) {
3194
4026
  const { m, sh } = ctx;
3195
4027
  const S2 = LOOK.strip;
3196
4028
  const my = s.y + S2.h / 2;
@@ -3212,8 +4044,18 @@ function strip(s, changes, ctx) {
3212
4044
  values.forEach((c, k) => {
3213
4045
  const next = values[k + 1]?.at;
3214
4046
  const value = c.value;
3215
- const anim = next === void 0 ? m.rise(c.at) : m.rise(c.at, next - MOTION.untilFade);
3216
- parts.push(`<g class="dg-a" style="${anim}"><text class="${hasWide(value) ? "dg-fvj" : "dg-fv"}" x="${r1(field.x)}" y="${r1(field.y + S2.valueY)}">${esc(value)}</text></g>`);
4047
+ const cls = hasWide(value) ? "dg-fvj" : "dg-fv";
4048
+ const textOf = (c2) => `<text class="${c2}" x="${r1(field.x)}" y="${r1(field.y + S2.valueY)}">${esc(value)}</text>`;
4049
+ const text2 = textOf(cls);
4050
+ if (!now) {
4051
+ const anim = next === void 0 ? m.rise(c.at) : m.rise(c.at, next - MOTION.untilFade);
4052
+ parts.push(`<g class="dg-a" style="${anim}">${text2}</g>`);
4053
+ return;
4054
+ }
4055
+ const until = Math.min(c.until, next ?? c.until);
4056
+ const dot = `<circle class="dg-fl-now" cx="${r1(field.x + textWidth(field.name, TYPE.fieldName) + S2.now.gap)}" cy="${r1(field.y + S2.nameY - TYPE.fieldName.size / 3)}" r="${S2.now.r}"/>`;
4057
+ parts.push(`<g class="dg-fv-now dg-a" data-step="${c.step}" style="${cs(c.color)};${m.rise(c.at, until - MOTION.untilFade)}">${textOf(`${cls} dg-fv-c`)}${dot}</g>`);
4058
+ if (next === void 0 || next > until) parts.push(`<g class="dg-a" style="${m.vis(until - MOTION.untilFade, next === void 0 ? m.last : next - MOTION.untilFade)}">${text2}</g>`);
3217
4059
  });
3218
4060
  tags.forEach((c, k) => {
3219
4061
  const next = tags[k + 1]?.at;
@@ -3227,6 +4069,22 @@ function strip(s, changes, ctx) {
3227
4069
  );
3228
4070
  });
3229
4071
  });
4072
+ if (s.trail) {
4073
+ const t = s.trail;
4074
+ const last = s.fields[s.fields.length - 1];
4075
+ if (last && last.y === t.y) {
4076
+ const sx = t.x - S2.fieldGap / 2;
4077
+ parts.push(`<line class="dg-sep" x1="${r1(sx)}" y1="${r1(t.y + S2.sepInset)}" x2="${r1(sx)}" y2="${r1(t.y + S2.h - S2.sepInset)}"/>`);
4078
+ }
4079
+ parts.push(`<text class="dg-fl" x="${r1(t.x)}" y="${r1(t.y + S2.nameY)}">${esc(t.title)}</text>`);
4080
+ const dy = t.y + S2.valueY - TYPE.fieldValue.size / 3;
4081
+ t.states.forEach((state, k) => {
4082
+ const cx = r1(t.x + S2.trail.r + k * S2.trail.step);
4083
+ const at2 = arrivals.get(state.box);
4084
+ const fill = at2 === void 0 ? "" : `<circle class="dg-tr-fill dg-a" cx="${cx}" cy="${r1(dy)}" r="${S2.trail.r}" style="${m.pop(at2)}"/>`;
4085
+ parts.push(`<g data-trail="${esc(state.box)}" style="${cs(state.color)}"><circle class="dg-tr-ring" cx="${cx}" cy="${r1(dy)}" r="${S2.trail.r}"/>${fill}</g>`);
4086
+ });
4087
+ }
3230
4088
  return parts.join("");
3231
4089
  }
3232
4090
 
@@ -3323,6 +4181,7 @@ var font = (t) => `font:${t.weight} ${t.size}px var(--${t.family})`;
3323
4181
  var mix = (pct, base = "var(--surf)") => `color-mix(in srgb,var(--c) ${pct}%,${base})`;
3324
4182
  var S = LOOK.stroke;
3325
4183
  var X = LOOK.mix;
4184
+ var PAST = `color-mix(in srgb,var(--mute) ${X.past}%,var(--bg))`;
3326
4185
  var PART_CSS = [
3327
4186
  ".dg{display:block;width:100%;height:auto;overflow:visible}",
3328
4187
  ".dg .dg-a{animation-duration:var(--T);animation-timing-function:linear;animation-iteration-count:infinite;animation-fill-mode:both;animation-delay:calc(var(--at,0) * -1s);animation-play-state:var(--play,running)}",
@@ -3347,15 +4206,21 @@ var PART_CSS = [
3347
4206
  `.dg-e-on{fill:none;stroke:var(--c);stroke-width:${S.edgeOn};stroke-linecap:round;stroke-dasharray:1 2}`,
3348
4207
  `.dg-eh-on{fill:none;stroke:var(--c);stroke-width:${S.edgeOn};stroke-linecap:round;stroke-linejoin:round}`,
3349
4208
  `.dg-flow{fill:none;stroke:var(--surf);stroke-width:${S.flow};stroke-linecap:round;stroke-dasharray:1.5 ${LOOK.edge.flowDash}}`,
4209
+ `.dg-e-past{fill:none;stroke:${PAST};stroke-width:${S.edge};stroke-linecap:round}`,
4210
+ `.dg-eh-past{fill:none;stroke:${PAST};stroke-width:${S.arrow};stroke-linecap:round;stroke-linejoin:round}`,
3350
4211
  ".dg-bd{cursor:pointer}",
3351
4212
  ".dg-bdf{fill:var(--c)}",
3352
4213
  `.dg-bdft{${font(TYPE.badge)};fill:var(--on-c)}`,
3353
4214
  `.dg-bdr{fill:none;stroke:var(--c);stroke-width:${S.badgeRing}}`,
3354
4215
  `.dg-bdp{fill:${mix(X.badgePast)};stroke:${mix(X.badgePastEdge, "transparent")};stroke-width:${S.hair}}`,
3355
4216
  `.dg-bdpt{${font(TYPE.badge)};fill:var(--ct)}`,
4217
+ `.dg-bdp-g{fill:var(--surf);stroke:${PAST};stroke-width:${S.hair}}`,
4218
+ `.dg-bdpt-g{${font(TYPE.badge)};fill:var(--mute)}`,
3356
4219
  `.dg-cap rect,.dg-act rect{fill:${mix(X.cap)};stroke:${mix(X.capEdge, "transparent")}}`,
3357
4220
  `.dg-cap text{${font(TYPE.label)};fill:var(--ct)}`,
3358
4221
  `.dg-capj text{${font(TYPE.labelJa)}}`,
4222
+ `.dg-cap-past text{${font(TYPE.label)};fill:var(--mute);fill-opacity:${LOOK.state.pastLabel}}`,
4223
+ `.dg-cap-pastj text{${font(TYPE.labelJa)}}`,
3359
4224
  `.dg-act text{${font(TYPE.action)};fill:var(--ct)}`,
3360
4225
  ".dg-car{fill:var(--carry,var(--ink))}",
3361
4226
  `.dg-car-t{${font(TYPE.carrier)};fill:var(--bg)}`,
@@ -3370,8 +4235,28 @@ var PART_CSS = [
3370
4235
  `.dg-fl{${font(TYPE.fieldName)};fill:var(--mute)}`,
3371
4236
  `.dg-fv{${font(TYPE.fieldValue)};fill:var(--ink)}`,
3372
4237
  `.dg-fvj{${font(TYPE.fieldValueJa)};fill:var(--ink)}`,
4238
+ ".dg-fv-c{fill:var(--ct)}",
4239
+ ".dg-fl-now{fill:var(--c)}",
4240
+ `.dg-tr-ring{fill:none;stroke:var(--line);stroke-width:${S.trail}}`,
4241
+ ".dg-tr-fill{fill:var(--c)}",
3373
4242
  ".dg-tg rect{fill:var(--c)}",
3374
4243
  `.dg-tg text{${font(TYPE.tag)};fill:var(--on-c)}`,
4244
+ `.dg-side{fill:color-mix(in srgb,var(--c) ${X.side}%,var(--bg));stroke:${mix(X.sideEdge, "transparent")};stroke-dasharray:4 4}`,
4245
+ `.dg-side-t{${font(TYPE.regionName)};fill:var(--ct)}`,
4246
+ `.dg-side-n{${font(TYPE.regionNote)};fill:var(--mute)}`,
4247
+ `.dg-ghost{fill:var(--surf);stroke:${mix(X.ghostEdge, "transparent")};stroke-dasharray:4 3}`,
4248
+ `.dg-path{fill:none;stroke:${mix(X.path, "transparent")};stroke-width:${S.path};stroke-linecap:round;stroke-dasharray:0 ${LOOK.edge.ghostDash}}`,
4249
+ `.dg-path-h{fill:none;stroke:${mix(X.path, "transparent")};stroke-width:${S.arrow};stroke-linecap:round;stroke-linejoin:round}`,
4250
+ `.dg-path-t{${font(TYPE.label)};fill:var(--ct)}`,
4251
+ `.dg-path-tj{${font(TYPE.labelJa)}}`,
4252
+ ".dg-start{fill:var(--ink)}",
4253
+ `.dg-end{fill:var(--bg);stroke:var(--ink);stroke-width:${S.end}}`,
4254
+ ".dg-end-in{fill:var(--ink)}",
4255
+ `.dg-end-x{fill:var(--bg);stroke:${mix(X.path, "transparent")};stroke-width:${S.arrow};stroke-dasharray:2 2.5}`,
4256
+ `.dg-end-xi{fill:${mix(X.path, "transparent")}}`,
4257
+ `.dg-mark{${font(TYPE.regionNote)};fill:var(--mute)}`,
4258
+ `.dg-done{fill:var(--ink);stroke:var(--surf);stroke-width:${S.done}}`,
4259
+ `.dg-done-ck{fill:none;stroke:var(--surf);stroke-width:${S.glyph};stroke-linecap:round;stroke-linejoin:round}`,
3375
4260
  ".dg-vp-bg{fill:var(--bg)}",
3376
4261
  ".dg-vp-frame{fill:none;stroke:var(--hair)}",
3377
4262
  ".dg-hd-bg{fill:var(--bg)}",
@@ -3449,7 +4334,8 @@ function fieldChanges(diagram, timeline, layout) {
3449
4334
  if (event?.type !== "strip") continue;
3450
4335
  const color = layout.badges[time.step]?.color ?? "slate";
3451
4336
  const list2 = out.get(event.field) ?? [];
3452
- list2.push({ at: time.at, color, ...event.value !== void 0 ? { value: event.value } : {}, ...event.tag !== void 0 ? { tag: event.tag } : {} });
4337
+ const until = timeline.steps[time.step].end;
4338
+ list2.push({ at: time.at, color, step: time.step, until, ...event.value !== void 0 ? { value: event.value } : {}, ...event.tag !== void 0 ? { tag: event.tag } : {} });
3453
4339
  out.set(event.field, list2);
3454
4340
  }
3455
4341
  return out;
@@ -3459,20 +4345,36 @@ function drawSvg(diagram, layout, timeline, palette, theme, follow) {
3459
4345
  const m = new Motion(`dg${id}`, timeline.total, timeline.last);
3460
4346
  const ctx = { m, t: timeline, sh: `filter="url(#dg-sh-${id})"`, end: timeline.steps[timeline.steps.length - 1].end };
3461
4347
  const on = involved(diagram);
3462
- const subs = subChanges(diagram, timeline, layout.kind === "architecture");
4348
+ const subs = subChanges(diagram, timeline, layout.kind !== "sequence");
3463
4349
  const L = { band: [], base: [], lit: [], node: [], badge: [], top: [] };
3464
4350
  for (const region of layout.regions) L.band.push(band(region));
3465
- if (layout.strip) L.band.push(strip(layout.strip, fieldChanges(diagram, timeline, layout), ctx));
4351
+ const ghostColor = layout.boxes.find((b) => b.ghost)?.color ?? "slate";
4352
+ if (layout.side) L.band.push(side(layout.side, ghostColor));
4353
+ const boxColor = (id2, ghost) => layout.boxes.find((b) => b.id === id2 && (ghost === void 0 || b.ghost === ghost))?.color;
4354
+ for (const p of layout.paths) L.base.push(path(p, boxColor(p.to, true) ?? boxColor(p.from) ?? ghostColor));
4355
+ for (const e of layout.ends) L.node.push(endMark(e, ghostColor));
4356
+ const isState = layout.kind === "state";
4357
+ const arrivals = new Map((timeline.states ?? []).flatMap((s) => s.lit[0] ? [[s.box, s.lit[0].start]] : []));
4358
+ if (layout.strip) L.band.push(strip(layout.strip, fieldChanges(diagram, timeline, layout), ctx, isState, arrivals));
3466
4359
  for (const line of layout.lifelines) L.base.push(lifeline(line.x, line.y1, line.y2));
3467
4360
  for (const e of layout.edges) {
3468
4361
  const time = timeline.edges.find((t) => t.step === e.step && t.event === e.event);
3469
4362
  if (!time) continue;
3470
- const drawn = edge(e, time, ctx);
4363
+ const drawn = edge(e, time, ctx, isState);
3471
4364
  L.base.push(drawn.base);
3472
4365
  L.lit.push(drawn.lit);
3473
4366
  }
3474
- for (const box of layout.boxes) L.node.push(card(box, ctx, on.get(box.id) ?? [], subs.get(box.id) ?? []));
3475
- for (const b of layout.badges) L.badge.push(badge(b, ctx));
4367
+ const states = new Map((timeline.states ?? []).map((s) => [s.box, s]));
4368
+ for (const box of layout.boxes) {
4369
+ if (box.ghost) {
4370
+ L.node.push(ghostCard(box));
4371
+ continue;
4372
+ }
4373
+ const state = states.get(box.id);
4374
+ L.node.push(card(box, ctx, on.get(box.id) ?? [], subs.get(box.id) ?? [], isState ? state?.lit ?? [] : void 0));
4375
+ if (state?.done !== void 0) L.node.push(doneMark(box, state.done, ctx));
4376
+ }
4377
+ for (const b of layout.badges) L.badge.push(badge(b, ctx, isState));
3476
4378
  for (const l of layout.labels) {
3477
4379
  const time = timeline.labels.find((t) => t.step === l.step && t.event === l.event);
3478
4380
  if (time) L.top.push(label(l, time, ctx));
@@ -3608,7 +4510,7 @@ function renderDiagram(input, options = {}) {
3608
4510
  const diagram = read2.diagram;
3609
4511
  const palette = resolvePalette(options.palette);
3610
4512
  const theme = options.theme === "dark" ? "dark" : "light";
3611
- const layout = diagram.kind === "sequence" ? layoutSequence(diagram) : layoutArchitecture(diagram);
4513
+ const layout = diagram.kind === "sequence" ? layoutSequence(diagram) : diagram.kind === "state" ? layoutState(diagram, lang) : layoutArchitecture(diagram);
3612
4514
  const timeline = buildTimeline(diagram);
3613
4515
  return {
3614
4516
  svg: drawSvg(diagram, layout, timeline, palette, theme),
@@ -3679,9 +4581,9 @@ async function stage(browser, svg, fontCss, body) {
3679
4581
  const paused = svg.replace(/^<svg\b/, '<svg style="--play:paused;--at:0"');
3680
4582
  const html = `<!doctype html><html><head><meta charset="utf-8"><style>${fontCss}html,body{margin:0}body{${body}}svg{display:block}</style><script type="module">import * as mb from "/mediabunny.js";import * as gif from "/gifenc.js";window.__tools={mb,gif};</script></head><body>${paused}</body></html>`;
3681
4583
  await page.route("http://localhost/**", async (route) => {
3682
- const path = new URL(route.request().url()).pathname;
3683
- if (path === "/") return route.fulfill({ contentType: "text/html; charset=utf-8", body: html });
3684
- const script = SCRIPTS[path];
4584
+ const path2 = new URL(route.request().url()).pathname;
4585
+ if (path2 === "/") return route.fulfill({ contentType: "text/html; charset=utf-8", body: html });
4586
+ const script = SCRIPTS[path2];
3685
4587
  return script ? route.fulfill({ contentType: "text/javascript", body: readFileSync(script) }) : route.fulfill({ status: 404 });
3686
4588
  });
3687
4589
  await page.goto("http://localhost/");
@@ -3959,9 +4861,9 @@ function writeOutputs(outDir, name, outputs) {
3959
4861
  const files = {};
3960
4862
  try {
3961
4863
  for (const [format, data] of outputs) {
3962
- const path = join(outDir, `${name}.${format}`);
3963
- writeFileSync(path, data);
3964
- files[format] = path;
4864
+ const path2 = join(outDir, `${name}.${format}`);
4865
+ writeFileSync(path2, data);
4866
+ files[format] = path2;
3965
4867
  }
3966
4868
  } catch (error) {
3967
4869
  if (created !== void 0) rmSync(created, { recursive: true, force: true });
@@ -3970,30 +4872,6 @@ function writeOutputs(outDir, name, outputs) {
3970
4872
  return files;
3971
4873
  }
3972
4874
 
3973
- // src/words.ts
3974
- var keys = (table) => Object.keys(table);
3975
- var KINDS = keys({ sequence: true, architecture: true });
3976
- var HEADS = ["group", "end", "box", "strip", "step", "say", "code", "act", "note", "set"];
3977
- var AS = "as";
3978
- var ATTRS = {
3979
- diagram: ["view"],
3980
- group: ["note", "color", "icon"],
3981
- box: ["note", "color", "icon"],
3982
- edge: ["carry", "tag", "side"],
3983
- set: ["tag"]
3984
- };
3985
- var CARRIES = keys({ coin: true, none: true });
3986
- var VIEWS = keys({ fixed: true, follow: true });
3987
- var SIDES = keys({ above: true, below: true, left: true, right: true });
3988
- var OLD_HEADS = {
3989
- \u6642\u7CFB\u5217\u56F3: "sequence",
3990
- \u69CB\u6210\u56F3: "architecture",
3991
- \u533A\u753B: "group",
3992
- \u898B\u305B\u65B9: "view",
3993
- region: "group",
3994
- view: "view"
3995
- };
3996
-
3997
4875
  // src/messages.ts
3998
4876
  var list = (words) => words.join(" / ");
3999
4877
  var ja2 = () => {
@@ -4058,7 +4936,11 @@ var ja2 = () => {
4058
4936
  badView: `view \u306F ${list(VIEWS)} \u306E\u3069\u308C\u304B`,
4059
4937
  badCarry: `carry \u306F ${list(CARRIES)} \u306E\u3069\u308C\u304B\u3002\u672D\u306F tag: <\u5024> \u3067\u66F8\u304F`,
4060
4938
  badSide: `side \u306F ${list(SIDES)} \u306E\u3069\u308C\u304B`,
4061
- carryTwice: "\u904B\u3076\u7269\u306F 1 \u672C\u306E\u7DDA\u306B 1 \u3064\u307E\u3067\u3002carry \u3068 tag \u306F\u4E00\u7DD2\u306B\u66F8\u304B\u306A\u3044"
4939
+ carryTwice: "\u904B\u3076\u7269\u306F 1 \u672C\u306E\u7DDA\u306B 1 \u3064\u307E\u3067\u3002carry \u3068 tag \u306F\u4E00\u7DD2\u306B\u66F8\u304B\u306A\u3044",
4940
+ reservedId: (id) => `${id} \u306F\u72B6\u614B\u9077\u79FB\u56F3\u306E\u59CB\u307E\u308A\u3068\u7D42\u308F\u308A\u306E\u5370\u306E\u540D\u524D\u3067\u3001\u7BB1\u306E\u540D\u672D\u306B\u4F7F\u3048\u306A\u3044`,
4941
+ intoStart: "start \u3078\u5165\u308B\u7DDA\u306F\u66F8\u3051\u306A\u3044\u3002start \u306F\u59CB\u307E\u308A\u306E\u5370\u3067\u3001\u7DDA\u306F start \u304B\u3089\u51FA\u308B",
4942
+ outOfFinish: "finish \u304B\u3089\u51FA\u308B\u7DDA\u306F\u66F8\u3051\u306A\u3044\u3002finish \u306F\u7D42\u308F\u308A\u306E\u5370\u3067\u3001\u7DDA\u306F finish \u3078\u5165\u308B",
4943
+ pathNoAttrs: "\u6700\u521D\u306E step \u3088\u308A\u524D\u306E\u7DDA\u306F\u4ECA\u56DE\u306F\u901A\u3089\u306A\u3044\u9053\u306A\u306E\u3067\u3001\u5C5E\u6027 (carry \u3068 tag \u3068 side) \u3092\u66F8\u3051\u306A\u3044"
4062
4944
  };
4063
4945
  };
4064
4946
  var en2 = () => {
@@ -4123,7 +5005,11 @@ var en2 = () => {
4123
5005
  badView: `view is one of ${list(VIEWS)}`,
4124
5006
  badCarry: `carry is one of ${list(CARRIES)}. Write a tag as tag: <value>`,
4125
5007
  badSide: `side is one of ${list(SIDES)}`,
4126
- carryTwice: "A line carries one thing. Do not write carry and tag together"
5008
+ carryTwice: "A line carries one thing. Do not write carry and tag together",
5009
+ reservedId: (id) => `${id} names the start or end mark of a state diagram and cannot be a box id`,
5010
+ intoStart: "A line cannot go into start. start is the start mark, and lines leave it",
5011
+ outOfFinish: "A line cannot leave finish. finish is the end mark, and lines go into it",
5012
+ pathNoAttrs: "A line before the first step is a path not taken, so it takes no attributes (carry, tag, side)"
4127
5013
  };
4128
5014
  };
4129
5015
  var MESSAGES = { ja: ja2(), en: en2() };
@@ -4301,8 +5187,10 @@ function parseLines(lines, m) {
4301
5187
  const shown = titled.rest < head.text.length ? readAttrs(head, titled.rest, ATTRS.diagram, m).get("view") : void 0;
4302
5188
  if (shown && !isOneOf(VIEWS, shown.value)) throw fail(head, shown.at, m.badView);
4303
5189
  const view = shown?.value;
5190
+ const isState = kind === "state";
4304
5191
  const regions = [];
4305
5192
  const boxes = [];
5193
+ const paths = [];
4306
5194
  const ids = /* @__PURE__ */ new Set();
4307
5195
  let strip2;
4308
5196
  const steps = [];
@@ -4316,6 +5204,14 @@ function parseLines(lines, m) {
4316
5204
  if (!boxes.some((box) => box.id === id)) throw fail(source, at2, m.undeclaredBox(id));
4317
5205
  return id;
4318
5206
  };
5207
+ const endAt = (source, id, at2, side2) => {
5208
+ if (!isState || !isOneOf(STATE_ENDS, id)) return boxAt(source, id, at2);
5209
+ if (id === "start" !== (side2 === "from")) throw fail(source, at2, id === "start" ? m.intoStart : m.outOfFinish);
5210
+ return id;
5211
+ };
5212
+ const notReserved = (source, id, at2) => {
5213
+ if (isState && isOneOf(STATE_ENDS, id)) throw fail(source, at2, m.reservedId(id));
5214
+ };
4319
5215
  const inStep = (source) => {
4320
5216
  if (!building) throw fail(source, 0, m.stepLineBeforeStep);
4321
5217
  return building;
@@ -4340,7 +5236,8 @@ function parseLines(lines, m) {
4340
5236
  const text2 = source.text;
4341
5237
  const edge2 = EDGE.exec(text2);
4342
5238
  if (edge2) {
4343
- inStep(source).events.push(readEdge(source, edge2));
5239
+ if (isState && !building) paths.push(readPath(source, edge2));
5240
+ else inStep(source).events.push(readEdge(source, edge2));
4344
5241
  continue;
4345
5242
  }
4346
5243
  const word = text2.split(/\s/u)[0] ?? "";
@@ -4412,7 +5309,8 @@ function parseLines(lines, m) {
4412
5309
  boxes,
4413
5310
  ...strip2 ? { strip: strip2 } : {},
4414
5311
  steps,
4415
- ...kind === "sequence" ? { sequence: { lifelines: boxes.map((box) => box.id) } } : {}
5312
+ ...kind === "sequence" ? { sequence: { lifelines: boxes.map((box) => box.id) } } : {},
5313
+ ...paths.length > 0 ? { state: { paths } } : {}
4416
5314
  };
4417
5315
  function readGroup(source) {
4418
5316
  beforeSteps(source);
@@ -4421,6 +5319,7 @@ function parseLines(lines, m) {
4421
5319
  if (regions.some((region) => region.id === declared.id)) {
4422
5320
  if (declared.name !== void 0 || declared.attrs.size > 0) throw fail(source, 0, m.regionReopened(declared.id));
4423
5321
  } else {
5322
+ notReserved(source, declared.id, declared.idAt);
4424
5323
  declare(source, declared.id, declared.idAt);
4425
5324
  regions.push({ id: declared.id, name: declared.name ?? declared.id, ...lookOf(source, declared.attrs, m) });
4426
5325
  }
@@ -4429,6 +5328,7 @@ function parseLines(lines, m) {
4429
5328
  function readBox(source) {
4430
5329
  beforeSteps(source);
4431
5330
  const declared = readDeclared(source, "box", ATTRS.box, m);
5331
+ notReserved(source, declared.id, declared.idAt);
4432
5332
  declare(source, declared.id, declared.idAt);
4433
5333
  const { note, ...look } = lookOf(source, declared.attrs, m);
4434
5334
  boxes.push({
@@ -4486,26 +5386,32 @@ function parseLines(lines, m) {
4486
5386
  if (!found || idAt === void 0 || (found[2] ?? "") === "") throw fail(source, 0, shape);
4487
5387
  return { box: boxAt(source, found[1] ?? "", idAt), text: found[2] ?? "" };
4488
5388
  }
5389
+ function readLine(source, edge2) {
5390
+ const text2 = source.text;
5391
+ const from = endAt(source, edge2[1] ?? "", edge2.indices?.[1]?.[0] ?? 0, "from");
5392
+ const to = endAt(source, edge2[2] ?? "", edge2.indices?.[2]?.[0] ?? 0, "to");
5393
+ const at2 = skipSpaces(text2, edge2[0].length);
5394
+ if (text2[at2] !== ":") return { from, to, at: at2 };
5395
+ const named = readName(source, at2 + 1, m);
5396
+ if (named.value === "") throw fail(source, at2, m.emptyLabel);
5397
+ return { from, to, label: named.value, at: named.rest };
5398
+ }
5399
+ function readPath(source, edge2) {
5400
+ const { from, to, label: label2, at: at2 } = readLine(source, edge2);
5401
+ if (at2 < source.text.length) throw fail(source, at2, source.text[at2] === "[" ? m.pathNoAttrs : m.edgeShape);
5402
+ return { from, to, ...label2 !== void 0 ? { label: label2 } : {} };
5403
+ }
4489
5404
  function readEdge(source, edge2) {
4490
5405
  const text2 = source.text;
4491
- const from = boxAt(source, edge2[1] ?? "", edge2.indices?.[1]?.[0] ?? 0);
4492
- const to = boxAt(source, edge2[2] ?? "", edge2.indices?.[2]?.[0] ?? 0);
4493
- let at2 = skipSpaces(text2, edge2[0].length);
4494
- let label2;
4495
- if (text2[at2] === ":") {
4496
- const named = readName(source, at2 + 1, m);
4497
- if (named.value === "") throw fail(source, at2, m.emptyLabel);
4498
- label2 = named.value;
4499
- at2 = named.rest;
4500
- }
5406
+ const { from, to, label: label2, at: at2 } = readLine(source, edge2);
4501
5407
  if (at2 < text2.length && text2[at2] !== "[") throw fail(source, at2, m.edgeShape);
4502
5408
  const attrs = at2 < text2.length ? readAttrs(source, at2, ATTRS.edge, m) : /* @__PURE__ */ new Map();
4503
5409
  const tag = attrs.get("tag");
4504
5410
  const carried = attrs.get("carry");
4505
5411
  if (tag && carried) throw fail(source, Math.max(tag.at, carried.at), m.carryTwice);
4506
5412
  if (carried && !isOneOf(CARRIES, carried.value)) throw fail(source, carried.at, m.badCarry);
4507
- const side = attrs.get("side");
4508
- if (side && !isOneOf(SIDES, side.value)) throw fail(source, side.at, m.badSide);
5413
+ const side2 = attrs.get("side");
5414
+ if (side2 && !isOneOf(SIDES, side2.value)) throw fail(source, side2.at, m.badSide);
4509
5415
  let carry = { kind: "envelope" };
4510
5416
  if (tag) carry = { kind: "tag", text: tag.value };
4511
5417
  else if (carried) carry = carried.value === "coin" ? { kind: "coin" } : { kind: "none" };
@@ -4515,7 +5421,7 @@ function parseLines(lines, m) {
4515
5421
  to,
4516
5422
  ...label2 !== void 0 ? { label: label2 } : {},
4517
5423
  carry,
4518
- ...side ? { labelSide: side.value } : {}
5424
+ ...side2 ? { labelSide: side2.value } : {}
4519
5425
  };
4520
5426
  }
4521
5427
  function readSet(source) {
@@ -4591,10 +5497,10 @@ var CLI_TEXT = {
4591
5497
  unknownOption: (name) => `\u77E5\u3089\u306A\u3044\u8A2D\u5B9A: ${name}`,
4592
5498
  missingValue: (name) => `\u8A2D\u5B9A\u306B\u5024\u304C\u7121\u3044: ${name}`,
4593
5499
  extraFiles: (extra) => `\u56F3\u306E file \u306F 1 \u3064\u3060\u3051\u6E21\u3059\u3002\u4F59\u5206\u306A\u5F15\u6570: ${extra.join(" ")}`,
4594
- noFile: (path) => `\u56F3\u306E file \u304C\u7121\u3044: ${path}`,
4595
- unreadable: (path, detail2) => `\u56F3\u306E file \u3092\u8AAD\u3081\u306A\u3044: ${path} (${detail2})`,
4596
- badJson: (path, detail2) => `JSON \u3068\u3057\u3066\u8AAD\u3081\u306A\u3044: ${path} (${detail2})`,
4597
- cannotWrite: (path, detail2) => `\u66F8\u304D\u51FA\u305B\u306A\u3044: ${path} (${detail2})`,
5500
+ noFile: (path2) => `\u56F3\u306E file \u304C\u7121\u3044: ${path2}`,
5501
+ unreadable: (path2, detail2) => `\u56F3\u306E file \u3092\u8AAD\u3081\u306A\u3044: ${path2} (${detail2})`,
5502
+ badJson: (path2, detail2) => `JSON \u3068\u3057\u3066\u8AAD\u3081\u306A\u3044: ${path2} (${detail2})`,
5503
+ cannotWrite: (path2, detail2) => `\u66F8\u304D\u51FA\u305B\u306A\u3044: ${path2} (${detail2})`,
4598
5504
  badValue: (option, value, allowed) => `\u4F7F\u3048\u306A\u3044\u5024: ${option} ${value} (${allowed})`,
4599
5505
  allowed: { lang: "ja \u304B en", theme: "light \u304B dark", positive: "0 \u3088\u308A\u5927\u304D\u3044\u6570", format: `${FORMATS.join(" / ")} \u3092 , \u3067\u533A\u5207\u308B` }
4600
5506
  },
@@ -4613,10 +5519,10 @@ var CLI_TEXT = {
4613
5519
  unknownOption: (name) => `Unknown option: ${name}`,
4614
5520
  missingValue: (name) => `Option needs a value: ${name}`,
4615
5521
  extraFiles: (extra) => `Pass only one diagram file. Extra arguments: ${extra.join(" ")}`,
4616
- noFile: (path) => `No such diagram file: ${path}`,
4617
- unreadable: (path, detail2) => `Cannot read the diagram file: ${path} (${detail2})`,
4618
- badJson: (path, detail2) => `Cannot read as JSON: ${path} (${detail2})`,
4619
- cannotWrite: (path, detail2) => `Cannot write: ${path} (${detail2})`,
5522
+ noFile: (path2) => `No such diagram file: ${path2}`,
5523
+ unreadable: (path2, detail2) => `Cannot read the diagram file: ${path2} (${detail2})`,
5524
+ badJson: (path2, detail2) => `Cannot read as JSON: ${path2} (${detail2})`,
5525
+ cannotWrite: (path2, detail2) => `Cannot write: ${path2} (${detail2})`,
4620
5526
  badValue: (option, value, allowed) => `Invalid value: ${option} ${value} (${allowed})`,
4621
5527
  allowed: { lang: "ja or en", theme: "light or dark", positive: "a number above 0", format: `${FORMATS.join(" / ")} separated by ,` }
4622
5528
  }
@@ -4727,11 +5633,11 @@ ${early.usage}`);
4727
5633
  ...gifFps === void 0 ? {} : { gifFps }
4728
5634
  });
4729
5635
  } catch (error) {
4730
- const path = failedPath(error);
4731
- if (path !== void 0) throw new Error(CLI_TEXT[lang ?? "ja"].cannotWrite(path, detail(error)));
5636
+ const path2 = failedPath(error);
5637
+ if (path2 !== void 0) throw new Error(CLI_TEXT[lang ?? "ja"].cannotWrite(path2, detail(error)));
4732
5638
  throw error instanceof Error ? error : new Error(String(error));
4733
5639
  }
4734
- for (const path of Object.values(result.files)) console.log(path);
5640
+ for (const path2 of Object.values(result.files)) console.log(path2);
4735
5641
  return 0;
4736
5642
  }
4737
5643
  main(process.argv.slice(2)).then(