@cardenelabs/dragon 0.27.0 → 0.28.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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { NODE_KINDS, TONES, EDGE_STYLES, EDGE_REVEALS, parseFormula, EDGE_HEADS, EDGE_HEAD_FILLS, extractIdentifiers, inputDefaultValue, layout, applyDerivedValues, diagram, classDiagram, sequence, sequenceStepId, flow, swimlane, er, stateMachine, topology, CLASS_RELATION_LOOK, SEQUENCE_MESSAGE_LOOK, FSM_ACTION_MARK } from '@cardenelabs/cdl';
1
+ import { NODE_KINDS, TONES, EDGE_STYLES, EDGE_REVEALS, RELATION_FOCUSES, parseFormula, EDGE_HEADS, EDGE_HEAD_FILLS, extractIdentifiers, inputDefaultValue, layout, applyDerivedValues, diagram, classDiagram, sequence, sequenceStepId, flow, swimlane, er, stateMachine, topology, CLASS_RELATION_LOOK, SEQUENCE_MESSAGE_LOOK, FSM_ACTION_MARK } from '@cardenelabs/cdl';
2
2
 
3
3
  // src/keywords.ts
4
4
  var HEADERS = {
@@ -1795,7 +1795,7 @@ var \u3064\u307E\u307F\u306E\u8868 = {
1795
1795
  dropdown: {
1796
1796
  \u5FC5\u9808: ["options", "defaultValue"],
1797
1797
  \u6B04: {
1798
- options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1798
+ options: "\u9078\u629E\u80A2\u306E\u4E26\u3073",
1799
1799
  defaultValue: "\u6587\u5B57\u5217",
1800
1800
  label: "\u6587\u5B57\u5217"
1801
1801
  }
@@ -1803,7 +1803,7 @@ var \u3064\u307E\u307F\u306E\u8868 = {
1803
1803
  "multi-select": {
1804
1804
  \u5FC5\u9808: ["options", "defaultValues"],
1805
1805
  \u6B04: {
1806
- options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1806
+ options: "\u9078\u629E\u80A2\u306E\u4E26\u3073",
1807
1807
  defaultValues: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1808
1808
  label: "\u6587\u5B57\u5217"
1809
1809
  }
@@ -1820,7 +1820,7 @@ var \u3064\u307E\u307F\u306E\u8868 = {
1820
1820
  radio: {
1821
1821
  \u5FC5\u9808: ["options", "defaultValue"],
1822
1822
  \u6B04: {
1823
- options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1823
+ options: "\u9078\u629E\u80A2\u306E\u4E26\u3073",
1824
1824
  defaultValue: "\u6587\u5B57\u5217",
1825
1825
  label: "\u6587\u5B57\u5217"
1826
1826
  }
@@ -1859,7 +1859,7 @@ var \u3064\u307E\u307F\u306E\u8868 = {
1859
1859
  tabs: {
1860
1860
  \u5FC5\u9808: ["options", "defaultValue"],
1861
1861
  \u6B04: {
1862
- options: "\u6587\u5B57\u5217\u306E\u4E26\u3073",
1862
+ options: "\u9078\u629E\u80A2\u306E\u4E26\u3073",
1863
1863
  defaultValue: "\u6587\u5B57\u5217",
1864
1864
  label: "\u6587\u5B57\u5217"
1865
1865
  }
@@ -1888,7 +1888,9 @@ var \u3064\u307E\u307F\u306E\u8868 = {
1888
1888
  \u5FC5\u9808: ["defaultValue"],
1889
1889
  \u6B04: {
1890
1890
  defaultValue: "\u771F\u507D",
1891
- label: "\u6587\u5B57\u5217"
1891
+ label: "\u6587\u5B57\u5217",
1892
+ onLabel: "\u6587\u5B57\u5217",
1893
+ offLabel: "\u6587\u5B57\u5217"
1892
1894
  }
1893
1895
  },
1894
1896
  xypad: {
@@ -1942,6 +1944,8 @@ var TOP_LEVEL_KEYS = [
1942
1944
  "bands",
1943
1945
  // 矢印をいつ出すか (#1470)
1944
1946
  "reveal",
1947
+ // 箱に触れると関係する線だけを光らせるか (#1757)
1948
+ "relations",
1945
1949
  /*
1946
1950
  * 図の並ぶ向き (#1494)。
1947
1951
  *
@@ -2126,6 +2130,7 @@ function parseTextDslV05(src) {
2126
2130
  let eyebrow = null;
2127
2131
  let eyebrowLine = 0;
2128
2132
  let reveal = null;
2133
+ let relations = null;
2129
2134
  let direction = null;
2130
2135
  let directionLine = 0;
2131
2136
  let palette = null;
@@ -2186,6 +2191,22 @@ function parseTextDslV05(src) {
2186
2191
  i += 1;
2187
2192
  continue;
2188
2193
  }
2194
+ if (head.key === "relations") {
2195
+ const v = (head.value ?? "").trim();
2196
+ if (v.length > 0) {
2197
+ if (RELATION_FOCUSES.includes(v)) {
2198
+ relations = v;
2199
+ } else {
2200
+ errors.push({
2201
+ line: line.no,
2202
+ message: `relations \u304C\u8AAD\u3081\u307E\u305B\u3093 (\u66F8\u3044\u305F\u5024: ${v})`,
2203
+ hint: `\u4F7F\u3048\u308B\u8A9E = ${RELATION_FOCUSES.join(" / ")}`
2204
+ });
2205
+ }
2206
+ }
2207
+ i += 1;
2208
+ continue;
2209
+ }
2189
2210
  if (head.key === "direction") {
2190
2211
  const v = (head.value ?? "").trim();
2191
2212
  if (v.length > 0) {
@@ -2340,6 +2361,13 @@ function parseTextDslV05(src) {
2340
2361
  const inline = head.value?.trim();
2341
2362
  if (inline && inline.startsWith("{") && inline.endsWith("}")) {
2342
2363
  const opts2 = parseInlineMapping(inline.slice(1, -1));
2364
+ \u4E2D\u62EC\u5F27\u306E\u77E5\u3089\u306A\u3044\u9805\u76EE\u540D\u3092\u77E5\u3089\u305B\u308B(
2365
+ inline.slice(1, -1),
2366
+ Object.keys(VIEWPORT_VALUE_KINDS),
2367
+ "viewport \u306E ",
2368
+ line.no,
2369
+ errors
2370
+ );
2343
2371
  viewport = {
2344
2372
  ...\u8868\u3067\u8AAD\u3080(VIEWPORT_VALUE_KINDS, opts2, "viewport \u306E ", line.no, errors),
2345
2373
  pos: { line: line.no }
@@ -2347,13 +2375,31 @@ function parseTextDslV05(src) {
2347
2375
  i += 1;
2348
2376
  continue;
2349
2377
  }
2350
- const { items, next } = collectIndentedList(lines, i + 1, line.indent);
2378
+ const { items, next } = collectIndentedRaw(lines, i + 1, line.indent);
2351
2379
  const opts = {};
2352
2380
  const optLines = {};
2381
+ const \u4F7F\u3048\u308B = Object.keys(VIEWPORT_VALUE_KINDS);
2353
2382
  for (const it of items) {
2354
- const m = it.trimmed.match(/^([a-zA-Z][a-zA-Z0-9_]*)\s*:\s*(.+)$/);
2355
- if (!m) continue;
2383
+ const \u884C = it.trimmed.replace(/^-\s+/, "");
2384
+ const m = \u884C.match(/^([a-zA-Z][a-zA-Z0-9_]*)\s*:\s*(.*)$/);
2385
+ if (!m) {
2386
+ errors.push({
2387
+ line: it.no,
2388
+ message: `viewport \u306E\u884C\u304C\u8AAD\u3081\u307E\u305B\u3093: "${it.trimmed}"`,
2389
+ hint: `use \`width: 1400\` (\u4F7F\u3048\u308B\u9805\u76EE = ${\u4F7F\u3048\u308B.join(", ")})`
2390
+ });
2391
+ continue;
2392
+ }
2356
2393
  const \u6B04 = m[1] ?? "";
2394
+ if (!\u4F7F\u3048\u308B.includes(\u6B04)) {
2395
+ errors.push({
2396
+ line: it.no,
2397
+ message: `viewport \u306E\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u6B04}"`,
2398
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = ${\u4F7F\u3048\u308B.join(", ")}`
2399
+ });
2400
+ continue;
2401
+ }
2402
+ if ((m[2] ?? "").trim() === "") continue;
2357
2403
  opts[\u6B04] = stripQuotes((m[2] ?? "").trim());
2358
2404
  optLines[\u6B04] = it.no;
2359
2405
  }
@@ -2394,6 +2440,13 @@ function parseTextDslV05(src) {
2394
2440
  continue;
2395
2441
  }
2396
2442
  const opts = parseInlineMapping(m[2] ?? "");
2443
+ \u4E2D\u62EC\u5F27\u306E\u77E5\u3089\u306A\u3044\u9805\u76EE\u540D\u3092\u77E5\u3089\u305B\u308B(
2444
+ m[2] ?? "",
2445
+ m[1] === "x" ? AXIS_X_KEYS : AXIS_Y_KEYS,
2446
+ `\u8EF8 ${m[1]} \u306E `,
2447
+ it.no,
2448
+ errors
2449
+ );
2397
2450
  if (m[1] === "x") \u7D44\u307F\u7ACB\u3066.x = { left: opts.left, right: opts.right };
2398
2451
  else \u7D44\u307F\u7ACB\u3066.y = { bottom: opts.bottom, top: opts.top };
2399
2452
  }
@@ -2427,10 +2480,21 @@ function parseTextDslV05(src) {
2427
2480
  if (m) {
2428
2481
  const id = m[1];
2429
2482
  const opts = parseInlineMapping(m[2]);
2483
+ \u4E2D\u62EC\u5F27\u306E\u77E5\u3089\u306A\u3044\u9805\u76EE\u540D\u3092\u77E5\u3089\u305B\u308B(
2484
+ m[2],
2485
+ LANE_INLINE_KEYS,
2486
+ `\u7E26\u5217 ${id} \u306E `,
2487
+ it.no,
2488
+ errors
2489
+ );
2430
2490
  lanesMap[id] = {
2431
2491
  id,
2432
2492
  ...\u8868\u3067\u8AAD\u3080(LANE_VALUE_KINDS, opts, `\u7E26\u5217 ${id} \u306E `, it.no, errors),
2433
2493
  label: opts.label,
2494
+ // 位置のずらし (#1971)
2495
+ layoutPos: \u305A\u3089\u3057\u306B\u307E\u3068\u3081\u308B(
2496
+ \u8868\u3067\u8AAD\u3080(OFFSET_VALUE_KINDS, opts, `\u7E26\u5217 ${id} \u306E `, it.no, errors)
2497
+ ),
2434
2498
  pos: { line: it.no }
2435
2499
  };
2436
2500
  } else {
@@ -2586,6 +2650,7 @@ function parseTextDslV05(src) {
2586
2650
  if (m) {
2587
2651
  const id = m[1];
2588
2652
  const opts = parseInlineMapping(m[2]);
2653
+ \u4E2D\u62EC\u5F27\u306E\u77E5\u3089\u306A\u3044\u9805\u76EE\u540D\u3092\u77E5\u3089\u305B\u308B(m[2], GROUP_INLINE_KEYS, `\u7D44 ${id} \u306E `, it.no, errors);
2589
2654
  const lanesList = (opts.lanes ?? "").replace(/^\[|\]$/g, "").split(",").map((x) => x.trim()).filter(Boolean);
2590
2655
  groupsMap[id] = {
2591
2656
  id,
@@ -2634,6 +2699,7 @@ function parseTextDslV05(src) {
2634
2699
  type,
2635
2700
  ...eyebrow !== null ? { eyebrow, eyebrowPos: { line: eyebrowLine } } : {},
2636
2701
  ...reveal !== null ? { reveal } : {},
2702
+ ...relations !== null ? { relations } : {},
2637
2703
  ...direction !== null ? { direction, directionPos: { line: directionLine } } : {},
2638
2704
  ...palette !== null ? { palette } : {},
2639
2705
  ...axes !== void 0 ? { axes, axesPos: { line: axesLine } } : {},
@@ -2838,12 +2904,29 @@ var VIEWPORT_VALUE_KINDS = {
2838
2904
  nodeGap: "\u6570",
2839
2905
  labelMargin: "\u6570"
2840
2906
  };
2907
+ var OFFSET_VALUE_KINDS = {
2908
+ offsetX: "\u6570",
2909
+ offsetY: "\u6570"
2910
+ };
2911
+ function \u305A\u3089\u3057\u306B\u307E\u3068\u3081\u308B(v) {
2912
+ if (v.offsetX === void 0 && v.offsetY === void 0) return void 0;
2913
+ return { x: v.offsetX ?? 0, y: v.offsetY ?? 0 };
2914
+ }
2841
2915
  var LANE_VALUE_KINDS = {
2842
2916
  x: "\u6570",
2843
2917
  width: "\u6570",
2844
2918
  contain: "\u771F\u507D",
2845
2919
  lifeline: "\u771F\u507D"
2846
2920
  };
2921
+ var LANE_INLINE_KEYS = [
2922
+ ...Object.keys(LANE_VALUE_KINDS),
2923
+ // 位置のずらし (#1971)。 JSON の縦列の `pos` と同じ `layoutPos` に入る
2924
+ ...Object.keys(OFFSET_VALUE_KINDS),
2925
+ "label"
2926
+ ];
2927
+ var GROUP_INLINE_KEYS = ["label", "lanes"];
2928
+ var AXIS_X_KEYS = ["left", "right"];
2929
+ var AXIS_Y_KEYS = ["bottom", "top"];
2847
2930
  var \u56F3\u5F62\u306E\u8868 = {
2848
2931
  rect: {
2849
2932
  \u5FC5\u9808: ["source", "fillMax"],
@@ -2954,6 +3037,42 @@ function \u7D44\u306E\u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(raw) {
2954
3037
  }
2955
3038
  return \u51FA;
2956
3039
  }
3040
+ var \u9078\u629E\u80A2\u306E\u7D44\u306E\u9805\u76EE = ["value", "label"];
3041
+ function \u9078\u629E\u80A2\u306E\u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024, \u540D, line, errors) {
3042
+ const \u4E2D\u8EAB = \u5024.trim();
3043
+ if (!\u4E2D\u8EAB.startsWith("[") || !\u4E2D\u8EAB.endsWith("]")) {
3044
+ errors.push({ line, message: `${\u540D} \u306E\u4E26\u3073\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u5024}"`, hint: '`["green", { value: "red", label: "\u5931\u6557" }]` \u306E\u5F62\u3067\u66F8\u304F' });
3045
+ return void 0;
3046
+ }
3047
+ const \u51FA = [];
3048
+ const \u8AA4\u308A\u306E\u6570 = errors.length;
3049
+ splitInlineFields(\u4E2D\u8EAB.slice(1, -1)).forEach((\u751F, i) => {
3050
+ const \u8981\u7D20 = \u751F.trim();
3051
+ if (!\u8981\u7D20.startsWith("{")) {
3052
+ const \u6587\u5B57\u5217 = stripQuotes(\u8981\u7D20);
3053
+ if (\u6587\u5B57\u5217 !== "") \u51FA.push(\u6587\u5B57\u5217);
3054
+ return;
3055
+ }
3056
+ if (!\u8981\u7D20.endsWith("}")) {
3057
+ errors.push({ line, message: `${\u540D}[${i}] \u306E\u7D44\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u8981\u7D20}"`, hint: '`{ value: "red", label: "\u5931\u6557" }` \u306E\u5F62\u3067\u66F8\u304F' });
3058
+ return;
3059
+ }
3060
+ const \u7D44 = parseInlineMapping(\u8981\u7D20.slice(1, -1));
3061
+ for (const k of Object.keys(\u7D44)) {
3062
+ if (\u9078\u629E\u80A2\u306E\u7D44\u306E\u9805\u76EE.includes(k)) continue;
3063
+ errors.push({ line, message: `${\u540D}[${i}] \u306E\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${k}"`, hint: `\u4F7F\u3048\u308B\u9805\u76EE = ${\u9078\u629E\u80A2\u306E\u7D44\u306E\u9805\u76EE.join(", ")}` });
3064
+ }
3065
+ for (const k of \u9078\u629E\u80A2\u306E\u7D44\u306E\u9805\u76EE) {
3066
+ if (\u7D44[k] === void 0) {
3067
+ errors.push({ line, message: `${\u540D}[${i}].${k} \u306F\u5FC5\u305A\u66F8\u304D\u307E\u3059`, hint: `\u5FC5\u9808\u306E\u9805\u76EE = ${\u9078\u629E\u80A2\u306E\u7D44\u306E\u9805\u76EE.join(", ")}` });
3068
+ } else if (\u7D44[k] === "") {
3069
+ errors.push({ line, message: `${\u540D}[${i}].${k} \u304C\u7A7A\u3067\u3059`, hint: k === "label" ? "\u540D\u524D\u3092\u66F8\u304B\u306A\u3044\u306A\u3089\u6587\u5B57\u5217\u3060\u3051\u3092\u4E26\u3079\u308B" : "\u5024\u3092 1 \u6587\u5B57\u4EE5\u4E0A\u66F8\u304F" });
3070
+ }
3071
+ }
3072
+ if (\u7D44.value && \u7D44.label) \u51FA.push({ value: \u7D44.value, label: \u7D44.label });
3073
+ });
3074
+ return errors.length === \u8AA4\u308A\u306E\u6570 ? \u51FA : void 0;
3075
+ }
2957
3076
  function \u90E8\u54C1\u306E\u7D44\u3092\u691C\u67FB\u3059\u308B(kind, \u8AAD\u3081\u305F, line, errors) {
2958
3077
  for (const [\u6B04, \u5B9A\u7FA9] of Object.entries(\u90E8\u54C1\u306E\u7D44\u306E\u8868[kind] ?? {})) {
2959
3078
  const \u4E26\u3073 = \u8AAD\u3081\u305F[\u6B04];
@@ -2987,7 +3106,8 @@ function \u8868\u306B\u5F93\u3063\u3066\u8AAD\u3080(\u5B9A\u7FA9, opts, \u63A5\u
2987
3106
  if (\u5F62 === void 0) {
2988
3107
  errors.push({
2989
3108
  line,
2990
- message: `${\u63A5\u982D}\u306E\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u6B04}"`,
3109
+ // 接頭は呼び手が「の」 まで書く (`図形の ` / `部品 ring の `)。 ここで足すと「の の」 に重なる (#1968)
3110
+ message: `${\u63A5\u982D.trimEnd()}\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u6B04}"`,
2991
3111
  hint: `\u4F7F\u3048\u308B\u9805\u76EE = ${Object.keys(\u5B9A\u7FA9.\u6B04).join(", ")}`
2992
3112
  });
2993
3113
  continue;
@@ -3013,6 +3133,9 @@ function \u8868\u306B\u5F93\u3063\u3066\u8AAD\u3080(\u5B9A\u7FA9, opts, \u63A5\u
3013
3133
  } else {
3014
3134
  out[\u6B04] = \u6570;
3015
3135
  }
3136
+ } else if (\u5F62 === "\u9078\u629E\u80A2\u306E\u4E26\u3073") {
3137
+ const \u9078\u629E\u80A2 = \u9078\u629E\u80A2\u306E\u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024, `${\u63A5\u982D}${\u6B04}`, line, errors);
3138
+ if (\u9078\u629E\u80A2 !== void 0) out[\u6B04] = \u9078\u629E\u80A2;
3016
3139
  } else if (\u5F62 === "\u7D44\u306E\u4E26\u3073") {
3017
3140
  const \u7D44 = \u7D44\u306E\u4E26\u3073\u3068\u3057\u3066\u8AAD\u3080(\u5024);
3018
3141
  if (\u7D44 !== void 0) out[\u6B04] = \u7D44;
@@ -3288,11 +3411,21 @@ function \u5F0F\u3068\u3057\u3066\u8AAD\u3080(\u884C, line, errors) {
3288
3411
  return void 0;
3289
3412
  }
3290
3413
  const \u540D\u524D = \u884C.slice(0, c).trim();
3291
- const \u5F0F = stripQuotes(\u884C.slice(c + 1).trim());
3292
3414
  if (!isValueName(\u540D\u524D)) {
3293
3415
  errors.push({ line, ...valueNameIssue(\u540D\u524D) });
3294
3416
  return void 0;
3295
3417
  }
3418
+ const \u7D44 = \u5F0F\u306E\u7D44\u306B\u5272\u308B(\u884C);
3419
+ let \u5F0F;
3420
+ let \u540D\u672D;
3421
+ if (\u7D44 === void 0) {
3422
+ \u5F0F = stripQuotes(\u884C.slice(c + 1).trim());
3423
+ } else {
3424
+ const \u8AAD\u3081\u305F = \u5F0F\u306E\u7D44\u3092\u8AAD\u3080(\u540D\u524D, \u7D44, line, errors);
3425
+ if (\u8AAD\u3081\u305F === void 0) return void 0;
3426
+ \u5F0F = \u8AAD\u3081\u305F.expression;
3427
+ \u540D\u672D = \u8AAD\u3081\u305F.label;
3428
+ }
3296
3429
  if (\u5F0F === "") {
3297
3430
  errors.push({
3298
3431
  line,
@@ -3311,7 +3444,50 @@ function \u5F0F\u3068\u3057\u3066\u8AAD\u3080(\u884C, line, errors) {
3311
3444
  });
3312
3445
  return void 0;
3313
3446
  }
3314
- return { id: \u540D\u524D, expression: \u5F0F, pos: { line } };
3447
+ return { id: \u540D\u524D, expression: \u5F0F, ...\u540D\u672D !== void 0 ? { label: \u540D\u672D } : {}, pos: { line } };
3448
+ }
3449
+ var \u7D44\u306E\u9805\u76EE\u540D = /^([^\s:,{}[\]"']+)\s*:\s*(.*)$/s;
3450
+ function \u5F0F\u306E\u7D44\u306B\u5272\u308B(\u884C) {
3451
+ const \u5272\u308C\u305F = \u540D\u524D\u3068\u4E2D\u62EC\u5F27\u306B\u5272\u308B(\u884C);
3452
+ if (\u5272\u308C\u305F === void 0) return void 0;
3453
+ const \u6700\u521D = splitInlineFields(\u5272\u308C\u305F[1])[0]?.trim() ?? "";
3454
+ return \u7D44\u306E\u9805\u76EE\u540D.test(\u6700\u521D) ? \u5272\u308C\u305F[1] : void 0;
3455
+ }
3456
+ function \u5F0F\u306E\u7D44\u3092\u8AAD\u3080(\u540D\u524D, \u4E2D\u8EAB, line, errors) {
3457
+ const \u4F7F\u3048\u308B = ["expression", "label"];
3458
+ const \u8AAD\u3081\u305F = {};
3459
+ for (const \u6B04 of splitInlineFields(\u4E2D\u8EAB).map((s) => s.trim()).filter((s) => s !== "")) {
3460
+ const m = \u6B04.match(\u7D44\u306E\u9805\u76EE\u540D);
3461
+ if (!m) {
3462
+ errors.push({
3463
+ line,
3464
+ message: `\u5F0F "${\u540D\u524D}" \u306E\u9805\u76EE\u304C\u8AAD\u3081\u307E\u305B\u3093: "${\u6B04}"`,
3465
+ hint: '`{ expression: "input * 2", label: "2 \u500D" }` \u306E\u5F62\u3067\u66F8\u304F\u3002 `,` \u3092\u542B\u3080\u5F0F\u306F\u5F15\u7528\u7B26\u3067\u56F2\u3080'
3466
+ });
3467
+ return void 0;
3468
+ }
3469
+ if (!\u4F7F\u3048\u308B.includes(m[1])) {
3470
+ errors.push({
3471
+ line,
3472
+ message: `\u5F0F "${\u540D\u524D}" \u306E\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${m[1]}"`,
3473
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = ${\u4F7F\u3048\u308B.join(", ")}`
3474
+ });
3475
+ return void 0;
3476
+ }
3477
+ \u8AAD\u3081\u305F[m[1]] = stripQuotes(m[2].trim());
3478
+ }
3479
+ if (\u8AAD\u3081\u305F.label !== void 0 && \u8AAD\u3081\u305F.label.trim() === "") {
3480
+ errors.push({
3481
+ line,
3482
+ message: `\u5F0F "${\u540D\u524D}" \u306E\u540D\u672D\u304C\u7A7A\u3067\u3059`,
3483
+ hint: '\u540D\u672D\u3092\u4ED8\u3051\u306A\u3044\u306A\u3089 `label` \u3092\u66F8\u304B\u306A\u3044\u3002 \u4ED8\u3051\u308B\u306A\u3089 `label: "2 \u500D"` \u306E\u3088\u3046\u306B\u66F8\u304F'
3484
+ });
3485
+ return void 0;
3486
+ }
3487
+ return {
3488
+ expression: \u8AAD\u3081\u305F.expression ?? "",
3489
+ ...\u8AAD\u3081\u305F.label !== void 0 ? { label: \u8AAD\u3081\u305F.label } : {}
3490
+ };
3315
3491
  }
3316
3492
  function \u3064\u307E\u307F\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors) {
3317
3493
  const opts = parseInlineMapping(raw);
@@ -3329,12 +3505,6 @@ function \u3064\u307E\u307F\u3068\u3057\u3066\u8AAD\u3080(id, raw, line, errors)
3329
3505
  for (const \u6B04 of \u5B9A\u7FA9.\u5FC5\u9808) if (\u8AAD\u3081\u305F[\u6B04] === void 0) return void 0;
3330
3506
  return { id, kind, ...\u8AAD\u3081\u305F };
3331
3507
  }
3332
- var ACTOR_NODE_VALUE_KINDS = {
3333
- posX: "\u6570",
3334
- posY: "\u6570",
3335
- posW: "\u6570",
3336
- posH: "\u6570"
3337
- };
3338
3508
  var ACTOR_INLINE_VALUE_KINDS = {
3339
3509
  stack: "\u6570",
3340
3510
  initial: "\u771F\u507D",
@@ -3650,6 +3820,17 @@ function applyContinuationLines(actor, rest, errors) {
3650
3820
  case "posY":
3651
3821
  out.posY = \u6570\u3068\u3057\u3066\u8AAD\u3080(raw, "\u7BB1\u306E posY", ln.no, errors);
3652
3822
  break;
3823
+ // 位置のずらし (#1971)。 中括弧の形と同じ表で読み、片方だけ書いた時は残りを 0 とする
3824
+ case "offsetX":
3825
+ case "offsetY": {
3826
+ const \u8AAD\u3081\u305F = \u8868\u3067\u8AAD\u3080(OFFSET_VALUE_KINDS, { [key]: raw }, "\u7BB1\u306E ", ln.no, errors);
3827
+ const \u524D = out.layoutPos;
3828
+ out.layoutPos = \u305A\u3089\u3057\u306B\u307E\u3068\u3081\u308B({
3829
+ offsetX: key === "offsetX" ? \u8AAD\u3081\u305F.offsetX : \u524D?.x,
3830
+ offsetY: key === "offsetY" ? \u8AAD\u3081\u305F.offsetY : \u524D?.y
3831
+ });
3832
+ break;
3833
+ }
3653
3834
  case "\u5927\u304D\u3055":
3654
3835
  case "size": {
3655
3836
  const value = stripQuotes(raw);
@@ -3707,6 +3888,10 @@ function applyContinuationLines(actor, rest, errors) {
3707
3888
  touchedState = true;
3708
3889
  }
3709
3890
  if (touchedState) out.stateOverride = state;
3891
+ if (out.tone !== void 0) {
3892
+ out.partColorName = out.tone;
3893
+ delete out.tone;
3894
+ }
3710
3895
  return out;
3711
3896
  }
3712
3897
  for (const [\u6B04, { \u5024, line }] of \u8FFD\u968F\u3059\u308B\u6B04\u306E\u751F\u5024) {
@@ -3760,6 +3945,9 @@ var ACTOR_ITEM_KEYS = /* @__PURE__ */ new Set([
3760
3945
  "pos",
3761
3946
  "posX",
3762
3947
  "posY",
3948
+ // 位置のずらし (#1971)
3949
+ "offsetX",
3950
+ "offsetY",
3763
3951
  "\u5927\u304D\u3055",
3764
3952
  "size",
3765
3953
  "\u500D\u7387",
@@ -3880,11 +4068,15 @@ var ACTOR_RESERVED_FIELDS = /* @__PURE__ */ new Set([
3880
4068
  "posY",
3881
4069
  "posW",
3882
4070
  "posH",
3883
- // canvas pivot UX 修正 (B1) = sub-node 単位 override map (nested `nodes: { header: {...} }`)
3884
- "nodes",
4071
+ // 位置のずらし (#1971)。 見本では見本 1 つ分をまとめてずらす欄で、状態の名前としては読まない
4072
+ "offsetX",
4073
+ "offsetY",
3885
4074
  // 図形の倍率 (#1026)。 状態の名前としては読まない
3886
4075
  "scale",
3887
4076
  "\u500D\u7387",
4077
+ // 色番号 (#1973)。 見本の色の状態へまとめて入れる欄で、状態の名前としては読まない。
4078
+ // 縦に並べた形 (`COLOR_KEYS`) と JSON は元から色として読んでいた
4079
+ "color",
3888
4080
  // 日本語の項目名 (#1026)。 中括弧の形が日本語の項目名を読めるようになったため、
3889
4081
  // ここに載せないと状態の名前として拾われる。 縦に並べた形での意味 (位置 / 大きさ 等) は
3890
4082
  // 中括弧の形では未対応なので、これまでどおり落とす方に揃える
@@ -3915,39 +4107,6 @@ function extractStateOverride(opts) {
3915
4107
  }
3916
4108
  return count > 0 ? out : void 0;
3917
4109
  }
3918
- function parseActorNodesField(raw, line, errors) {
3919
- if (!raw) return void 0;
3920
- const trimmed = raw.trim();
3921
- if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return void 0;
3922
- const inner = trimmed.slice(1, -1).trim();
3923
- if (!inner) return void 0;
3924
- const parts = [];
3925
- let depth = 0;
3926
- let buf = "";
3927
- for (let i = 0; i < inner.length; i += 1) {
3928
- const c = inner[i];
3929
- if (c === "[" || c === "{") depth += 1;
3930
- else if (c === "]" || c === "}") depth -= 1;
3931
- if (c === "," && depth === 0) {
3932
- parts.push(buf);
3933
- buf = "";
3934
- continue;
3935
- }
3936
- buf += c;
3937
- }
3938
- if (buf.trim()) parts.push(buf);
3939
- const out = {};
3940
- for (const p of parts) {
3941
- const colonIdx = p.indexOf(":");
3942
- if (colonIdx < 0) continue;
3943
- const key = p.slice(0, colonIdx).trim();
3944
- const val = p.slice(colonIdx + 1).trim();
3945
- if (!key || !val.startsWith("{") || !val.endsWith("}")) continue;
3946
- const nodeOpts = parseInlineMapping(val.slice(1, -1));
3947
- out[key] = \u8868\u3067\u8AAD\u3080(ACTOR_NODE_VALUE_KINDS, nodeOpts, `nodes \u306E ${key} \u306E `, line, errors);
3948
- }
3949
- return Object.keys(out).length > 0 ? out : void 0;
3950
- }
3951
4110
  function coerceStateValue(raw) {
3952
4111
  const stripped = stripQuotes(raw);
3953
4112
  if (stripped === "true") return true;
@@ -3996,7 +4155,9 @@ var INLINE_ACTOR_KEYS = /* @__PURE__ */ new Set([
3996
4155
  "initial",
3997
4156
  "final",
3998
4157
  "tone",
3999
- "nodes",
4158
+ // 色の欄 (#1969)。 縦に並べた形と JSON は `color` を受けるのに、中括弧の形だけが知らない
4159
+ // 項目名として落としていた。 見本 (parts) では従来どおり状態の上書きとして読む
4160
+ "color",
4000
4161
  // 体験の道筋の欄 (#1251)。 他の図種では組み立て側が知らせる
4001
4162
  "touchpoint",
4002
4163
  "opportunity",
@@ -4007,6 +4168,9 @@ var INLINE_ACTOR_KEYS = /* @__PURE__ */ new Set([
4007
4168
  "posY",
4008
4169
  "posW",
4009
4170
  "posH",
4171
+ // 位置のずらし (#1971)
4172
+ "offsetX",
4173
+ "offsetY",
4010
4174
  // 箱の中に描く図形 (#1374)
4011
4175
  "shape",
4012
4176
  // その箱を出すかどうかの条件 (#1381)
@@ -4026,6 +4190,9 @@ var INLINE_ACTOR_KEYS = /* @__PURE__ */ new Set([
4026
4190
  // 英語が読める欄の日本語別名 (#1301)。 一覧は `INLINE_ACTOR_ALIASES` が持つ
4027
4191
  ...Object.keys(INLINE_ACTOR_ALIASES)
4028
4192
  ]);
4193
+ var PART_INLINE_UNREADABLE_KEYS = new Set(
4194
+ [...ACTOR_RESERVED_FIELDS].filter((key) => !INLINE_ACTOR_KEYS.has(key) && key !== "state")
4195
+ );
4029
4196
  var EDGE_BIND_INLINE_READERS = {
4030
4197
  widthBind: (v) => v,
4031
4198
  strokeBind: (v) => v,
@@ -4033,6 +4200,8 @@ var EDGE_BIND_INLINE_READERS = {
4033
4200
  };
4034
4201
  var FLOW_INLINE_READERS = {
4035
4202
  sub: (v) => v,
4203
+ // クラス図の出どころ側の多重度 (#1771)。 `sub` (行き先の端) と対
4204
+ tailSub: (v) => v,
4036
4205
  guard: (v) => v,
4037
4206
  cardinality: (v) => v,
4038
4207
  /*
@@ -4054,7 +4223,7 @@ var FLOW_INLINE_READERS = {
4054
4223
  head: (v) => v !== void 0 && EDGE_HEAD_VALUES.includes(v) ? v : void 0,
4055
4224
  // 出どころ側の端の形 (#1466)。 ER は端ごとに違う個数を示すので両端に要る
4056
4225
  tailHead: (v) => v !== void 0 && EDGE_HEAD_VALUES.includes(v) ? v : void 0,
4057
- // 端の印の塗り (#1466)。 白抜きの菱が「持つ」、塗った菱が「抱える」
4226
+ // 端の印の塗り (#1466)。 白抜きの菱が集約、塗った菱がコンポジション
4058
4227
  headFill: (v) => v !== void 0 && EDGE_HEAD_FILL_VALUES.includes(v) ? v : void 0,
4059
4228
  tailHeadFill: (v) => v !== void 0 && EDGE_HEAD_FILL_VALUES.includes(v) ? v : void 0,
4060
4229
  /*
@@ -4078,6 +4247,12 @@ var FLOW_INLINE_READERS = {
4078
4247
  * 持たないため、知らせを出せる場所で見る)。
4079
4248
  */
4080
4249
  ...EDGE_BIND_INLINE_READERS,
4250
+ /*
4251
+ * 部品の端で矢印を繋ぐ要素の id (#1979)。 部品かどうか、要素が在るかは組み立てで部品の図を
4252
+ * 引いてから決まるため、ここでは字をそのまま通す
4253
+ */
4254
+ fromPartNode: (v) => v,
4255
+ toPartNode: (v) => v,
4081
4256
  // 数と真偽の欄は `FLOW_INLINE_VALUE_KINDS` の表が読む (#1306)。 ここでは名前だけを持つ =
4082
4257
  // 読める欄の一覧 (`FLOW_INLINE_KEYS`) は本表から導くため、載せないと欄ごと消える
4083
4258
  labelOffsetX: null,
@@ -4088,12 +4263,20 @@ var FLOW_INLINE_KEYS = Object.keys(
4088
4263
  FLOW_INLINE_READERS
4089
4264
  );
4090
4265
  function reportUnknownInlineKeys(isPart, inner, line, errors) {
4091
- if (isPart) return;
4092
4266
  for (const field of splitInlineFields(inner)) {
4093
4267
  const idx = field.indexOf(":");
4094
4268
  if (idx < 0) continue;
4095
4269
  const key = field.slice(0, idx).trim();
4096
4270
  if (!key) continue;
4271
+ if (isPart) {
4272
+ if (!PART_INLINE_UNREADABLE_KEYS.has(key)) continue;
4273
+ errors.push({
4274
+ line,
4275
+ message: `\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${key}"`,
4276
+ hint: `1 \u884C\u306E\u4E2D\u62EC\u5F27\u3067\u306F\u8AAD\u3081\u307E\u305B\u3093\u3002\u540D\u524D\u306E\u4E0B\u306B\u6BB5\u3092\u5206\u3051\u305F\u5F62\u3067\u66F8\u304F\u3068\u52B9\u304D\u307E\u3059`
4277
+ });
4278
+ continue;
4279
+ }
4097
4280
  if (INLINE_ACTOR_KEYS.has(key)) continue;
4098
4281
  errors.push({
4099
4282
  line,
@@ -4102,6 +4285,19 @@ function reportUnknownInlineKeys(isPart, inner, line, errors) {
4102
4285
  });
4103
4286
  }
4104
4287
  }
4288
+ function \u4E2D\u62EC\u5F27\u306E\u77E5\u3089\u306A\u3044\u9805\u76EE\u540D\u3092\u77E5\u3089\u305B\u308B(inner, \u4F7F\u3048\u308B, \u63A5\u982D, line, errors) {
4289
+ for (const field of splitInlineFields(inner)) {
4290
+ const idx = field.indexOf(":");
4291
+ if (idx < 0) continue;
4292
+ const key = field.slice(0, idx).trim();
4293
+ if (!key || \u4F7F\u3048\u308B.includes(key)) continue;
4294
+ errors.push({
4295
+ line,
4296
+ message: `${\u63A5\u982D.trimEnd()}\u9805\u76EE\u540D\u304C\u8AAD\u3081\u307E\u305B\u3093: "${key}"`,
4297
+ hint: `\u4F7F\u3048\u308B\u9805\u76EE = ${\u4F7F\u3048\u308B.join(", ")}`
4298
+ });
4299
+ }
4300
+ }
4105
4301
  function parseActor2(line, errors) {
4106
4302
  const raw = line.trimmed.trim();
4107
4303
  if (!raw) return null;
@@ -4119,6 +4315,10 @@ function parseActor2(line, errors) {
4119
4315
  if (!isPart && opts.tone !== void 0 && resolveTone(opts.tone) === void 0) {
4120
4316
  report\u8AAD\u3081\u306A\u3044\u8272(opts.tone, line.no, errors, { \u7DDA\u7A2E\u3082\u53D7\u3051\u308B: false });
4121
4317
  }
4318
+ const \u8272 = opts.color !== void 0 ? splitColorValue(opts.color) : {};
4319
+ if (opts.color !== void 0 && !\u8272.tone && !\u8272.hex) {
4320
+ report\u8AAD\u3081\u306A\u3044\u8272(opts.color, line.no, errors, { \u7DDA\u7A2E\u3082\u53D7\u3051\u308B: false });
4321
+ }
4122
4322
  const kind = isPart ? NODE_KIND_DEFAULT : resolveNodeKind(NODE_KIND_VALID.has(kindRaw) ? kindRaw : "");
4123
4323
  return {
4124
4324
  name: namePart2,
@@ -4155,15 +4355,18 @@ function parseActor2(line, errors) {
4155
4355
  renderOffsetY: isPart ? void 0 : \u5024\u306B\u8FFD\u968F\u3059\u308B\u6B04\u3068\u3057\u3066\u8AAD\u3080(opts.renderOffsetY, "\u7BB1\u306E renderOffsetY ", line.no, errors),
4156
4356
  ...\u8868\u3067\u8AAD\u3080(ACTOR_INLINE_VALUE_KINDS, opts, "\u7BB1\u306E ", line.no, errors),
4157
4357
  // parts では `tone` を状態の上書きとして従来から使えるため、 色として横取りしない
4158
- tone: isPart ? void 0 : resolveTone(opts.tone),
4358
+ // `tone` と `color` を両方書いた時は `tone` を採る (JSON の読み方と揃える)
4359
+ tone: isPart ? void 0 : resolveTone(opts.tone) ?? \u8272.tone,
4360
+ colorHex: \u8272.hex,
4361
+ partColorName: isPart ? \u8272.tone : void 0,
4159
4362
  partId: isPart ? kindRaw : void 0,
4160
4363
  stateOverride: isPart ? extractStateOverride(opts) : void 0,
4161
4364
  // canvas pivot 新 spec = 絶対座標 field は `ACTOR_INLINE_VALUE_KINDS` の表が読む (#1306)
4162
4365
  // 図形の倍率 (#1026)。 どれが効くかは `resolveScale` が 1 箇所で決める
4163
4366
  scale: inlineScale.scale,
4164
4367
  scaleKeys: inlineScale.keys.length ? inlineScale.keys : void 0,
4165
- // canvas pivot UX 修正 (B1) = sub-node 単位 override map (`nodes: { header: {posX:..., ...}, ...}`)
4166
- nodes: parseActorNodesField(opts.nodes, line.no, errors),
4368
+ // 位置のずらし (#1971)。 見本 (parts) でも見本 1 つ分をまとめてずらす
4369
+ layoutPos: \u305A\u3089\u3057\u306B\u307E\u3068\u3081\u308B(\u8868\u3067\u8AAD\u3080(OFFSET_VALUE_KINDS, opts, "\u7BB1\u306E ", line.no, errors)),
4167
4370
  pos: { line: line.no }
4168
4371
  };
4169
4372
  }
@@ -4215,6 +4418,7 @@ function parseFlowStep(line, no, errors) {
4215
4418
  let \u6570\u3068\u771F\u507D;
4216
4419
  if (\u584A) {
4217
4420
  const opts = parseInlineMapping(\u584A.\u4E2D\u8EAB);
4421
+ \u4E2D\u62EC\u5F27\u306E\u77E5\u3089\u306A\u3044\u9805\u76EE\u540D\u3092\u77E5\u3089\u305B\u308B(\u584A.\u4E2D\u8EAB, FLOW_INLINE_KEYS, "\u77E2\u5370\u306E ", line.no, errors);
4218
4422
  for (const field of splitInlineFields(\u584A.\u4E2D\u8EAB)) {
4219
4423
  const idx = field.indexOf(":");
4220
4424
  if (idx < 0) continue;
@@ -4254,6 +4458,7 @@ function parseFlowStep(line, no, errors) {
4254
4458
  rest = \u584A.\u524D.trim();
4255
4459
  }
4256
4460
  const sub = \u4E2D\u62EC\u5F27.sub;
4461
+ const tailSub = \u4E2D\u62EC\u5F27.tailSub;
4257
4462
  const guard = \u4E2D\u62EC\u5F27.guard;
4258
4463
  const cardinality = \u4E2D\u62EC\u5F27.cardinality;
4259
4464
  const side = \u4E2D\u62EC\u5F27.side;
@@ -4286,6 +4491,8 @@ function parseFlowStep(line, no, errors) {
4286
4491
  const labelOffsetX = \u6570\u3068\u771F\u507D?.labelOffsetX;
4287
4492
  const labelOffsetY = \u6570\u3068\u771F\u507D?.labelOffsetY;
4288
4493
  const overlay = \u6570\u3068\u771F\u507D?.overlay;
4494
+ const fromPartNode = \u4E2D\u62EC\u5F27.fromPartNode || void 0;
4495
+ const toPartNode = \u4E2D\u62EC\u5F27.toPartNode || void 0;
4289
4496
  const optMatch = rest.match(/\s*\(([^)]*)\)\s*$/);
4290
4497
  if (optMatch) {
4291
4498
  const opts = (optMatch[1] ?? "").split(",").map((s) => s.trim());
@@ -4331,6 +4538,7 @@ function parseFlowStep(line, no, errors) {
4331
4538
  tone,
4332
4539
  style,
4333
4540
  sub,
4541
+ tailSub,
4334
4542
  guard,
4335
4543
  cardinality,
4336
4544
  side,
@@ -4348,6 +4556,8 @@ function parseFlowStep(line, no, errors) {
4348
4556
  labelOffsetX,
4349
4557
  labelOffsetY,
4350
4558
  overlay,
4559
+ ...fromPartNode !== void 0 ? { fromPartNode } : {},
4560
+ ...toPartNode !== void 0 ? { toPartNode } : {},
4351
4561
  pos: { line: line.no }
4352
4562
  };
4353
4563
  }
@@ -4610,7 +4820,11 @@ var DRAW_TARGETS = /* @__PURE__ */ new Map([
4610
4820
  ["tree", "tree"],
4611
4821
  ["gantt", "gantt"],
4612
4822
  ["funnel", "funnel"],
4613
- ["slope", "slope"]
4823
+ ["slope", "slope"],
4824
+ ["gauge", "gauge"],
4825
+ ["radial", "radial"],
4826
+ ["stacked", "stacked"],
4827
+ ["waffle", "waffle"]
4614
4828
  ]);
4615
4829
  var DRAW_WORDS = new Set(DRAW_TARGETS.keys());
4616
4830
  var \u6BB5\u306E\u9805\u76EE\u306E\u65E5\u672C\u8A9E = {
@@ -5040,7 +5254,7 @@ function compileToCdl(doc, opts) {
5040
5254
  diagram2 = compileSequence(doc);
5041
5255
  break;
5042
5256
  case "flow":
5043
- diagram2 = compileFlow(doc);
5257
+ diagram2 = compileFlow(doc, opts?.partsCatalog);
5044
5258
  break;
5045
5259
  case "swimlane":
5046
5260
  diagram2 = compileSwimlane(doc);
@@ -5113,22 +5327,25 @@ function compileToCdl(doc, opts) {
5113
5327
  }
5114
5328
  const \u4F5C\u308A\u66FF\u3048\u305F\u5BFE\u8C61 = collectRenamedTargets(diagram2, \u5206\u3051\u305F.\u5143\u306E\u540D\u524D);
5115
5329
  const edgeSourceLines = opts?.onEdgeSource ? /* @__PURE__ */ new Map() : void 0;
5116
- applyEdgeInlineOptions(diagram2, doc, edgeSourceLines);
5117
- applyGroupContainers(diagram2, doc);
5330
+ const \u77E2\u5370\u306E\u884C = /* @__PURE__ */ new Map();
5331
+ applyEdgeInlineOptions(diagram2, doc, edgeSourceLines, \u77E2\u5370\u306E\u884C, opts?.partsCatalog);
5332
+ const \u4F5C\u3063\u305F\u7D44\u306E\u67A0 = applyGroupContainers(diagram2, doc);
5118
5333
  applyNodeTones(diagram2, doc);
5119
5334
  reportMissingFocusTargets(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5120
5335
  reportMissingFlowActors(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5121
- reportFlowEndpointNotHonored(doc, \u5206\u3051\u305F.\u5143\u306E\u540D\u524D, opts?.onNotice);
5336
+ reportFlowEndpointNotHonored(doc, \u5206\u3051\u305F.\u5143\u306E\u540D\u524D, opts?.onNotice, opts?.partsCatalog);
5122
5337
  reportLaneNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5123
5338
  reportActorKindNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5124
5339
  reportMessageOptionNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5340
+ reportFlowOffsetNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5125
5341
  reportDocEyebrowNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5126
5342
  reportDirectionNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5127
5343
  reportDrawNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5128
5344
  reportChartFieldsNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5129
5345
  reportAxesNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5346
+ reportPartNodeNotHonored(\u66F8\u3044\u305F\u307E\u307E, opts?.onNotice);
5130
5347
  const placed = resolveRelativeDoc(diagram2, doc, opts?.onNotice, opts?.partsCatalog);
5131
- applyCanvasPivotPositions(diagram2, placed, opts?.onNotice);
5348
+ applyCanvasPivotPositions(diagram2, placed);
5132
5349
  const \u8FFD\u52A0\u3057\u305F\u7E26\u5217 = [];
5133
5350
  const extended = applyV05Extensions(diagram2, placed, \u8FFD\u52A0\u3057\u305F\u7E26\u5217);
5134
5351
  const inheritedDerivedSourceLines = opts?.onNotice ? /* @__PURE__ */ new Map() : void 0;
@@ -5140,7 +5357,8 @@ function compileToCdl(doc, opts) {
5140
5357
  placed,
5141
5358
  opts?.partsCatalog,
5142
5359
  opts?.onNotice,
5143
- inheritedDerivedSourceLines
5360
+ inheritedDerivedSourceLines,
5361
+ \u77E2\u5370\u306E\u884C
5144
5362
  );
5145
5363
  reportEmptyDeclaredLanes(merged, \u8FFD\u52A0\u3057\u305F\u7E26\u5217, opts?.onNotice);
5146
5364
  if (edgeSourceLines && opts?.onEdgeSource) {
@@ -5152,6 +5370,7 @@ function compileToCdl(doc, opts) {
5152
5370
  injectStaticPhase(merged);
5153
5371
  materializeStates(merged, doc);
5154
5372
  if (doc.reveal !== void 0) merged.edgeReveal = doc.reveal;
5373
+ if (doc.relations !== void 0) merged.relationFocus = doc.relations;
5155
5374
  \u8A9E\u306E\u72B6\u614B\u3092\u56F3\u306E\u8A9E\u3078\u76F4\u3059(merged);
5156
5375
  const \u7573\u3093\u3060\u304D\u3063\u304B\u3051 = foldValueTriggers(merged, doc, opts?.onNotice);
5157
5376
  attachDerivedValues(merged, doc, opts?.onNotice, inheritedDerivedSourceLines, \u7573\u3093\u3060\u304D\u3063\u304B\u3051);
@@ -5171,6 +5390,8 @@ function compileToCdl(doc, opts) {
5171
5390
  const ownFormulas = doc.formulas.map((formula) => ({
5172
5391
  id: formula.id,
5173
5392
  expression: formula.expression,
5393
+ // 名札は操作部が式の名前として描く (#1916、cdl#853)。 書かなければ欄ごと付けない
5394
+ ...formula.label !== void 0 ? { label: formula.label } : {},
5174
5395
  line: formula.pos?.line ?? 0
5175
5396
  }));
5176
5397
  const \u3064\u307E\u307F = new Map((merged.inputs ?? []).map((input) => [input.id, input]));
@@ -5220,7 +5441,11 @@ function compileToCdl(doc, opts) {
5220
5441
  });
5221
5442
  }
5222
5443
  if (\u89E3\u3051\u306A\u3044) continue;
5223
- \u8F09\u305B\u308B\u5F0F.push({ id: formula.id, expression: formula.expression });
5444
+ \u8F09\u305B\u308B\u5F0F.push({
5445
+ id: formula.id,
5446
+ expression: formula.expression,
5447
+ ...formula.label !== void 0 ? { label: formula.label } : {}
5448
+ });
5224
5449
  \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F.add(formula.id);
5225
5450
  }
5226
5451
  if (\u8F09\u305B\u308B\u5F0F.length > 0) merged.formulas = \u8F09\u305B\u308B\u5F0F;
@@ -5268,6 +5493,8 @@ function compileToCdl(doc, opts) {
5268
5493
  restoreActorNames(merged, \u5206\u3051\u305F.\u5143\u306E\u540D\u524D, \u4F5C\u308A\u66FF\u3048\u305F\u5BFE\u8C61);
5269
5494
  \u914D\u8272\u3068\u7E1E\u3092\u5F53\u3066\u308B(merged, doc);
5270
5495
  \u9759\u6B62\u3057\u305F\u56F3\u306E\u7126\u70B9\u3092\u5916\u3059(merged, doc);
5496
+ applyLayoutOffsets(merged, doc, opts?.onNotice);
5497
+ applyGroupFrames(merged, doc, \u4F5C\u3063\u305F\u7D44\u306E\u67A0, opts?.onNotice);
5271
5498
  return merged;
5272
5499
  }
5273
5500
  function \u9759\u6B62\u3057\u305F\u56F3\u306E\u7126\u70B9\u3092\u5916\u3059(diagram2, doc) {
@@ -5444,13 +5671,14 @@ function reportLaneMixed(doc, onNotice) {
5444
5671
  hint: "\u66F8\u304B\u306A\u304B\u3063\u305F\u7BB1\u3092\u3069\u306E\u7E26\u5217\u306B\u7F6E\u304F\u304B\u3092\u6C7A\u3081\u3089\u308C\u306A\u3044\u305F\u3081\u3001\u5168\u90E8\u66F8\u304F\u304B 1 \u3064\u3082\u66F8\u304B\u306A\u3044\u304B\u306B\u3057\u3066\u304F\u3060\u3055\u3044"
5445
5672
  });
5446
5673
  }
5447
- function reportFlowEndpointNotHonored(doc, \u5143\u306E\u540D\u524D, onNotice) {
5674
+ function reportFlowEndpointNotHonored(doc, \u5143\u306E\u540D\u524D, onNotice, partsCatalog) {
5448
5675
  if (!onNotice) return;
5449
5676
  if (!\u9396\u3067\u3064\u306A\u3050\u5F62\u304B(doc)) return;
5450
5677
  const \u66F8\u3044\u305F\u540D\u524D = (name) => \u5143\u306E\u540D\u524D.get(name) ?? name;
5451
5678
  const \u9396\u306E\u7D44 = /* @__PURE__ */ new Set();
5452
- doc.actors.forEach((a, i) => {
5453
- const \u6B21 = doc.actors[i + 1];
5679
+ const \u4E26\u3073 = \u9396\u306B\u4E26\u3079\u308B\u767B\u5834\u4EBA\u7269(doc, partsCatalog);
5680
+ \u4E26\u3073.forEach((a, i) => {
5681
+ const \u6B21 = \u4E26\u3073[i + 1];
5454
5682
  if (\u6B21 === void 0) return;
5455
5683
  \u9396\u306E\u7D44.add(`${a.name}\0${\u6B21.name}`);
5456
5684
  });
@@ -5461,7 +5689,7 @@ function reportFlowEndpointNotHonored(doc, \u5143\u306E\u540D\u524D, onNotice) {
5461
5689
  actor: \u66F8\u3044\u305F\u540D\u524D(s.from),
5462
5690
  line: s.pos.line,
5463
5691
  message: `"${truncateForMessage(\u66F8\u3044\u305F\u540D\u524D(s.from))} -> ${truncateForMessage(\u66F8\u3044\u305F\u540D\u524D(s.to))}" \u306E\u7AEF\u306F\u4F7F\u308F\u308C\u307E\u305B\u3093 (type: flow \u306F\u767B\u5834\u4EBA\u7269\u3092\u66F8\u3044\u305F\u9806\u306B\u7E4B\u304E\u307E\u3059)`,
5464
- hint: "\u66F8\u3044\u305F\u7AEF\u3069\u304A\u308A\u306B\u7E4B\u3050\u306B\u306F\u3001\u7BB1\u306B lane: \u3092\u66F8\u3044\u3066\u304F\u3060\u3055\u3044 (\u7E26\u5217\u3092\u66F8\u3044\u305F\u5F62\u306F\u66F8\u3044\u305F\u7AEF\u304C\u305D\u306E\u307E\u307E\u77E2\u5370\u306B\u306A\u308A\u307E\u3059)"
5692
+ hint: "\u66F8\u3044\u305F\u7AEF\u3069\u304A\u308A\u306B\u7E4B\u3050\u306B\u306F\u3001direction: \u7E26 \u3092\u66F8\u304F\u304B\u7BB1\u306B lane: \u3092\u66F8\u3044\u3066\u304F\u3060\u3055\u3044 (\u5411\u304D\u304B\u7E26\u5217\u3092\u66F8\u3044\u305F\u5F62\u306F\u66F8\u3044\u305F\u7AEF\u304C\u305D\u306E\u307E\u307E\u77E2\u5370\u306B\u306A\u308A\u307E\u3059)"
5465
5693
  });
5466
5694
  }
5467
5695
  }
@@ -5472,7 +5700,9 @@ function reportMessageOptionNotHonored(doc, onNotice) {
5472
5700
  const \u52B9\u304B\u306A\u3044 = [
5473
5701
  s.tone !== void 0 ? "\u8272\u5473" : "",
5474
5702
  s.sub !== void 0 ? "\u6DFB\u3048\u5B57" : "",
5475
- s.side !== void 0 ? "\u5BC4\u305B" : ""
5703
+ s.side !== void 0 ? "\u5BC4\u305B" : "",
5704
+ // 名前のずらしも板には載せる先が無い (#1971)。 位置のずらし (`pos`) は名前のずらしに足す欄なので同じ扱い
5705
+ s.layoutPos !== void 0 || s.labelOffsetX !== void 0 || s.labelOffsetY !== void 0 ? "\u540D\u524D\u306E\u305A\u3089\u3057" : ""
5476
5706
  ].filter((x) => x !== "");
5477
5707
  if (\u52B9\u304B\u306A\u3044.length === 0) continue;
5478
5708
  onNotice({
@@ -5484,6 +5714,21 @@ function reportMessageOptionNotHonored(doc, onNotice) {
5484
5714
  });
5485
5715
  }
5486
5716
  }
5717
+ function reportFlowOffsetNotHonored(doc, onNotice) {
5718
+ if (!onNotice) return;
5719
+ if (doc.type === "sequence" || doc.type === "solidity") return;
5720
+ for (const s of doc.flow) {
5721
+ if (s.layoutPos === void 0) continue;
5722
+ if (s.label !== void 0 && s.label.trim() !== "") continue;
5723
+ onNotice({
5724
+ kind: "position-offset-ignored",
5725
+ actor: s.from,
5726
+ line: s.pos?.line ?? 0,
5727
+ message: `${s.from} -> ${s.to} \u306E\u4F4D\u7F6E\u306E\u305A\u3089\u3057\u306F\u3001\u540D\u524D\u306E\u7121\u3044\u77E2\u5370\u3067\u306F\u52D5\u304B\u3059\u3082\u306E\u304C\u3042\u308A\u307E\u305B\u3093`,
5728
+ hint: "\u77E2\u5370\u306E\u4F4D\u7F6E\u306E\u305A\u3089\u3057\u306F\u540D\u524D\u3092\u305A\u3089\u3057\u307E\u3059\u3002 \u540D\u524D\u3092\u66F8\u304F\u304B\u3001\u305A\u3089\u3057\u3092\u5916\u3059"
5729
+ });
5730
+ }
5731
+ }
5487
5732
  function reportActorKindNotHonored(doc, onNotice) {
5488
5733
  if (!onNotice) return;
5489
5734
  if (doc.type !== "sequence" && doc.type !== "solidity") return;
@@ -5501,7 +5746,8 @@ function reportActorKindNotHonored(doc, onNotice) {
5501
5746
  */
5502
5747
  doc.type === "sequence" && a.kindWritten !== false && a.kind !== void 0 ? "\u7A2E\u985E" : "",
5503
5748
  a.posW !== void 0 || a.posH !== void 0 ? "\u5927\u304D\u3055" : "",
5504
- a.posX !== void 0 || a.posY !== void 0 || a.posRel !== void 0 ? "\u4F4D\u7F6E" : "",
5749
+ a.posX !== void 0 || a.posY !== void 0 || a.posRel !== void 0 || // 位置のずらし (#1971)。 板は面ごとの箱を持たないので動かす相手が無い
5750
+ a.layoutPos !== void 0 ? "\u4F4D\u7F6E" : "",
5505
5751
  a.rows !== void 0 ? "\u884C" : "",
5506
5752
  a.tone !== void 0 ? "\u8272" : "",
5507
5753
  a.eyebrow !== void 0 ? "\u5C0F\u898B\u51FA\u3057" : "",
@@ -5910,6 +6156,220 @@ function withPositions(diagram2, doc, assign) {
5910
6156
  applyCanvasPivotPositions(probe, withDocPositions(doc, assign));
5911
6157
  return probe;
5912
6158
  }
6159
+ function applyLayoutOffsets(diagram2, doc, onNotice) {
6160
+ const \u305A\u3089\u3059\u7BB1 = doc.type === "mind" ? [] : doc.actors.filter((a) => a.layoutPos !== void 0);
6161
+ const \u305A\u3089\u3059\u7E26\u5217 = Object.entries(doc.lanes ?? {}).filter(([, l]) => l.layoutPos !== void 0);
6162
+ if (\u305A\u3089\u3059\u7BB1.length === 0 && \u305A\u3089\u3059\u7E26\u5217.length === 0) return;
6163
+ if (doc.type === "sequence" || doc.type === "solidity") return;
6164
+ const \u524D = layout(diagram2);
6165
+ const \u7BB1\u306E\u914D\u7F6E = new Map(\u524D.nodes.map((n) => [n.id, n]));
6166
+ const \u7E26\u5217\u306E\u914D\u7F6E = new Map(\u524D.lanes.map((l) => [l.id, l]));
6167
+ const \u76F8\u624B\u305F\u3061 = [];
6168
+ const \u7E26\u5217\u306E\u305A\u3089\u3057 = /* @__PURE__ */ new Map();
6169
+ const \u7BB1\u3060\u3051\u306E\u72D9\u3044 = /* @__PURE__ */ new Map();
6170
+ for (const [id, lane] of \u305A\u3089\u3059\u7E26\u5217) {
6171
+ const laid = \u7E26\u5217\u306E\u914D\u7F6E.get(id);
6172
+ const d = lane.layoutPos;
6173
+ if (!laid) {
6174
+ onNotice?.({
6175
+ kind: "position-offset-ignored",
6176
+ actor: id,
6177
+ line: lane.pos?.line ?? 0,
6178
+ message: `\u7E26\u5217 "${id}" \u306E\u4F4D\u7F6E\u306E\u305A\u3089\u3057\u3092\u8F09\u305B\u308B\u7E26\u5217\u304C\u56F3\u306B\u3042\u308A\u307E\u305B\u3093 (type: ${doc.type})`,
6179
+ hint: "\u7E26\u5217\u3092\u4F5C\u308B\u56F3\u7A2E\u3067\u66F8\u304F\u304B\u3001\u305A\u3089\u3057\u3092\u5916\u3059"
6180
+ });
6181
+ continue;
6182
+ }
6183
+ \u7E26\u5217\u306E\u305A\u3089\u3057.set(id, d);
6184
+ \u76F8\u624B\u305F\u3061.push({
6185
+ \u540D\u524D: id,
6186
+ line: lane.pos?.line ?? 0,
6187
+ // 縦列を固定しただけでは、中の箱は縦列の並ぶ向きにしか付いて来ない (実測 = flow の縦列を
6188
+ // 右へ 120、下へ 40 ずらすと、見出しは両方動き箱は右へ 120 だけ動いた)。 箱も同じ量で固定する
6189
+ \u7BB1: diagram2.nodes.flatMap((n) => {
6190
+ const \u7BB1laid = n.lane === id ? \u7BB1\u306E\u914D\u7F6E.get(n.id) : void 0;
6191
+ return \u7BB1laid ? [{ id: n.id, \u72D9\u3044X: \u7BB1laid.cx + d.x, \u72D9\u3044Y: \u7BB1laid.cy + d.y }] : [];
6192
+ }),
6193
+ \u7E26\u5217: [{ id, \u72D9\u3044X: (laid.x ?? 0) + d.x, \u72D9\u3044Y: (laid.y ?? 0) + d.y }],
6194
+ \u305A\u3089\u3057\u305F\u7E26\u5217: id
6195
+ });
6196
+ }
6197
+ for (const a of \u305A\u3089\u3059\u7BB1) {
6198
+ const d = a.layoutPos;
6199
+ const \u524D\u7F6E\u304D = `${a.name}__`;
6200
+ const \u7BB1 = a.partId !== void 0 ? diagram2.nodes.filter((n) => n.id.startsWith(\u524D\u7F6E\u304D)) : diagram2.nodes.filter((n) => n.id === slugify(a.name));
6201
+ const \u7E26\u5217 = a.partId !== void 0 ? diagram2.lanes.filter((l) => l.id.startsWith(\u524D\u7F6E\u304D)) : [];
6202
+ if (\u7BB1.length === 0) {
6203
+ onNotice?.({
6204
+ kind: "position-offset-ignored",
6205
+ actor: a.name,
6206
+ line: a.pos?.line ?? 0,
6207
+ message: `"${truncateForMessage(a.name)}" \u306E\u4F4D\u7F6E\u306E\u305A\u3089\u3057\u3092\u8F09\u305B\u308B\u7BB1\u304C\u56F3\u306B\u3042\u308A\u307E\u305B\u3093 (type: ${doc.type})`,
6208
+ hint: "\u7BB1\u3092\u63CF\u304F\u56F3\u7A2E\u3067\u66F8\u304F\u304B\u3001\u305A\u3089\u3057\u3092\u5916\u3059"
6209
+ });
6210
+ continue;
6211
+ }
6212
+ \u76F8\u624B\u305F\u3061.push({
6213
+ \u540D\u524D: a.name,
6214
+ line: a.pos?.line ?? 0,
6215
+ \u7BB1: \u7BB1.map((n) => {
6216
+ const laid = \u7BB1\u306E\u914D\u7F6E.get(n.id);
6217
+ \u7BB1\u3060\u3051\u306E\u72D9\u3044.set(n.id, { x: laid.cx + d.x, y: laid.cy + d.y });
6218
+ const \u5217 = \u7E26\u5217\u306E\u305A\u3089\u3057.get(n.lane);
6219
+ return { id: n.id, \u72D9\u3044X: laid.cx + d.x + (\u5217?.x ?? 0), \u72D9\u3044Y: laid.cy + d.y + (\u5217?.y ?? 0) };
6220
+ }),
6221
+ \u7E26\u5217: \u7E26\u5217.map((l) => {
6222
+ const laid = \u7E26\u5217\u306E\u914D\u7F6E.get(l.id);
6223
+ return { id: l.id, \u72D9\u3044X: (laid.x ?? 0) + d.x, \u72D9\u3044Y: (laid.y ?? 0) + d.y };
6224
+ })
6225
+ });
6226
+ }
6227
+ if (\u76F8\u624B\u305F\u3061.length === 0) return;
6228
+ const \u5143\u306E\u7BB1 = new Map(diagram2.nodes.map((n) => [n.id, { posX: n.posX, posY: n.posY }]));
6229
+ const \u5143\u306E\u7E26\u5217 = new Map(
6230
+ diagram2.lanes.map((l) => [l.id, { posX: l.posX, posY: l.posY, posW: l.posW, posH: l.posH }])
6231
+ );
6232
+ const \u7BB1\u306E\u72D9\u3044 = /* @__PURE__ */ new Map();
6233
+ const \u7E26\u5217\u306E\u72D9\u3044 = /* @__PURE__ */ new Map();
6234
+ for (const t of \u76F8\u624B\u305F\u3061) {
6235
+ for (const b of t.\u7BB1) \u7BB1\u306E\u72D9\u3044.set(b.id, { x: b.\u72D9\u3044X, y: b.\u72D9\u3044Y });
6236
+ for (const l of t.\u7E26\u5217) \u7E26\u5217\u306E\u72D9\u3044.set(l.id, { x: l.\u72D9\u3044X, y: l.\u72D9\u3044Y });
6237
+ }
6238
+ const \u7E26\u5217\u3092\u56FA\u5B9A\u3059\u308B = \u7E26\u5217\u306E\u72D9\u3044.size > 0;
6239
+ const \u7559\u3081\u308B\u4F4D\u7F6E = /* @__PURE__ */ new Map();
6240
+ if (\u7E26\u5217\u3092\u56FA\u5B9A\u3059\u308B) {
6241
+ let \u57FA\u6E96 = \u524D;
6242
+ if (\u7BB1\u3060\u3051\u306E\u72D9\u3044.size > 0) {
6243
+ for (const node of diagram2.nodes) {
6244
+ const \u72D9\u3044 = \u7BB1\u3060\u3051\u306E\u72D9\u3044.get(node.id);
6245
+ if (!\u72D9\u3044) continue;
6246
+ node.posX = \u72D9\u3044.x;
6247
+ node.posY = \u72D9\u3044.y;
6248
+ }
6249
+ \u57FA\u6E96 = layout(diagram2);
6250
+ for (const node of diagram2.nodes) {
6251
+ if (!\u7BB1\u3060\u3051\u306E\u72D9\u3044.has(node.id)) continue;
6252
+ const \u5143 = \u5143\u306E\u7BB1.get(node.id);
6253
+ node.posX = \u5143.posX;
6254
+ node.posY = \u5143.posY;
6255
+ }
6256
+ }
6257
+ const \u57FA\u6E96\u306E\u7BB1 = new Map(\u57FA\u6E96.nodes.map((n) => [n.id, n]));
6258
+ for (const t of \u76F8\u624B\u305F\u3061) {
6259
+ const d = t.\u305A\u3089\u3057\u305F\u7E26\u5217 === void 0 ? void 0 : \u7E26\u5217\u306E\u305A\u3089\u3057.get(t.\u305A\u3089\u3057\u305F\u7E26\u5217);
6260
+ if (!d) continue;
6261
+ for (const b of t.\u7BB1) {
6262
+ const n = \u57FA\u6E96\u306E\u7BB1.get(b.id);
6263
+ if (!n || \u7BB1\u3060\u3051\u306E\u72D9\u3044.has(b.id)) continue;
6264
+ \u7BB1\u306E\u72D9\u3044.set(b.id, { x: n.cx + d.x, y: n.cy + d.y });
6265
+ }
6266
+ }
6267
+ for (const n of \u57FA\u6E96.nodes) {
6268
+ if (!\u7BB1\u306E\u72D9\u3044.has(n.id)) \u7559\u3081\u308B\u4F4D\u7F6E.set(n.id, { x: n.cx, y: n.cy });
6269
+ }
6270
+ }
6271
+ const \u7559\u3081\u305F\u7BB1 = /* @__PURE__ */ new Set();
6272
+ const \u66F8\u304F = (\u76F4\u30572) => {
6273
+ if (\u7E26\u5217\u3092\u56FA\u5B9A\u3059\u308B) {
6274
+ for (const lane of diagram2.lanes) {
6275
+ const laid = \u7E26\u5217\u306E\u914D\u7F6E.get(lane.id);
6276
+ if (!laid) continue;
6277
+ const \u72D9\u3044 = \u7E26\u5217\u306E\u72D9\u3044.get(lane.id) ?? { x: laid.x ?? 0, y: laid.y ?? 0 };
6278
+ const \u5DEE2 = \u76F4\u30572.get(`lane:${lane.id}`) ?? { x: 0, y: 0 };
6279
+ lane.posX = \u72D9\u3044.x - \u5DEE2.x;
6280
+ lane.posY = \u72D9\u3044.y - \u5DEE2.y;
6281
+ lane.posW = laid.width;
6282
+ lane.posH = laid.height;
6283
+ }
6284
+ }
6285
+ for (const node of diagram2.nodes) {
6286
+ const \u72D9\u3044 = \u7BB1\u306E\u72D9\u3044.get(node.id);
6287
+ const \u7559\u3081\u308B = \u7559\u3081\u305F\u7BB1.has(node.id) ? \u7559\u3081\u308B\u4F4D\u7F6E.get(node.id) : void 0;
6288
+ if (!\u72D9\u3044 && !\u7559\u3081\u308B) continue;
6289
+ const \u5DEE2 = \u76F4\u30572.get(\u72D9\u3044 ? `node:${node.id}` : `keep:${node.id}`) ?? { x: 0, y: 0 };
6290
+ node.posX = (\u72D9\u3044 ?? \u7559\u3081\u308B).x - \u5DEE2.x;
6291
+ node.posY = (\u72D9\u3044 ?? \u7559\u3081\u308B).y - \u5DEE2.y;
6292
+ }
6293
+ };
6294
+ const \u6E2C\u308B = () => {
6295
+ const \u5F8C = layout(diagram2);
6296
+ const \u5DEE2 = /* @__PURE__ */ new Map();
6297
+ for (const n of \u5F8C.nodes) {
6298
+ const \u72D9\u3044 = \u7BB1\u306E\u72D9\u3044.get(n.id);
6299
+ if (\u72D9\u3044) \u5DEE2.set(`node:${n.id}`, { x: n.cx - \u72D9\u3044.x, y: n.cy - \u72D9\u3044.y });
6300
+ const \u7559\u3081\u308B = \u7559\u3081\u308B\u4F4D\u7F6E.get(n.id);
6301
+ if (\u7559\u3081\u308B) \u5DEE2.set(`keep:${n.id}`, { x: n.cx - \u7559\u3081\u308B.x, y: n.cy - \u7559\u3081\u308B.y });
6302
+ }
6303
+ if (\u7E26\u5217\u3092\u56FA\u5B9A\u3059\u308B) {
6304
+ for (const l of \u5F8C.lanes) {
6305
+ const laid = \u7E26\u5217\u306E\u914D\u7F6E.get(l.id);
6306
+ if (!laid) continue;
6307
+ const \u72D9\u3044 = \u7E26\u5217\u306E\u72D9\u3044.get(l.id) ?? { x: laid.x ?? 0, y: laid.y ?? 0 };
6308
+ \u5DEE2.set(`lane:${l.id}`, { x: (l.x ?? 0) - \u72D9\u3044.x, y: (l.y ?? 0) - \u72D9\u3044.y });
6309
+ }
6310
+ }
6311
+ return \u5DEE2;
6312
+ };
6313
+ const \u305A\u308C\u305F = (\u5DEE2) => \u5DEE2 !== void 0 && (Math.abs(\u5DEE2.x) > PLACEMENT_TOLERANCE || Math.abs(\u5DEE2.y) > PLACEMENT_TOLERANCE);
6314
+ const \u76F4\u3057 = /* @__PURE__ */ new Map();
6315
+ \u66F8\u304F(\u76F4\u3057);
6316
+ let \u5DEE = \u6E2C\u308B();
6317
+ for (let \u56DE = 0; \u56DE < 2 && [...\u5DEE.values()].some(\u305A\u308C\u305F); \u56DE++) {
6318
+ for (const [k, v] of \u5DEE) {
6319
+ if (!\u305A\u308C\u305F(v)) continue;
6320
+ const id = k.slice(k.indexOf(":") + 1);
6321
+ if (k.startsWith("keep:") && !\u7559\u3081\u305F\u7BB1.has(id)) {
6322
+ \u7559\u3081\u305F\u7BB1.add(id);
6323
+ continue;
6324
+ }
6325
+ const \u524D\u306E\u76F4\u3057 = \u76F4\u3057.get(k) ?? { x: 0, y: 0 };
6326
+ \u76F4\u3057.set(k, { x: \u524D\u306E\u76F4\u3057.x + v.x, y: \u524D\u306E\u76F4\u3057.y + v.y });
6327
+ }
6328
+ \u66F8\u304F(\u76F4\u3057);
6329
+ \u5DEE = \u6E2C\u308B();
6330
+ }
6331
+ const \u623B\u3059\u7BB1 = (t) => {
6332
+ for (const b of t.\u7BB1) {
6333
+ const node = diagram2.nodes.find((n) => n.id === b.id);
6334
+ const \u5143 = \u5143\u306E\u7BB1.get(b.id);
6335
+ node.posX = \u5143.posX;
6336
+ node.posY = \u5143.posY;
6337
+ }
6338
+ };
6339
+ const \u77E5\u3089\u305B\u308B = (t) => onNotice?.({
6340
+ kind: "position-offset-ignored",
6341
+ actor: t.\u540D\u524D,
6342
+ line: t.line,
6343
+ message: `"${truncateForMessage(t.\u540D\u524D)}" \u306E\u4F4D\u7F6E\u306E\u305A\u3089\u3057\u306F type: ${doc.type} \u306E\u56F3\u3067\u306F\u66F8\u3044\u305F\u91CF\u3060\u3051\u52D5\u304B\u305B\u307E\u305B\u3093`,
6344
+ hint: "\u305A\u3089\u3057\u3092\u5916\u3059\u304B\u3001\u5EA7\u6A19 (`\u4F4D\u7F6E: 300,200`) \u3067\u7F6E\u304F"
6345
+ });
6346
+ if ([...\u5DEE].some(([k, v]) => (k.startsWith("lane:") || k.startsWith("keep:")) && \u305A\u308C\u305F(v))) {
6347
+ for (const lane of diagram2.lanes) {
6348
+ const \u5143 = \u5143\u306E\u7E26\u5217.get(lane.id);
6349
+ if (!\u5143) continue;
6350
+ lane.posX = \u5143.posX;
6351
+ lane.posY = \u5143.posY;
6352
+ lane.posW = \u5143.posW;
6353
+ lane.posH = \u5143.posH;
6354
+ }
6355
+ for (const node of diagram2.nodes) {
6356
+ if (!\u7559\u3081\u305F\u7BB1.has(node.id)) continue;
6357
+ const \u5143 = \u5143\u306E\u7BB1.get(node.id);
6358
+ node.posX = \u5143.posX;
6359
+ node.posY = \u5143.posY;
6360
+ }
6361
+ for (const t of \u76F8\u624B\u305F\u3061) {
6362
+ \u623B\u3059\u7BB1(t);
6363
+ \u77E5\u3089\u305B\u308B(t);
6364
+ }
6365
+ return;
6366
+ }
6367
+ for (const t of \u76F8\u624B\u305F\u3061) {
6368
+ if (!t.\u7BB1.some((b) => \u305A\u308C\u305F(\u5DEE.get(`node:${b.id}`)))) continue;
6369
+ \u623B\u3059\u7BB1(t);
6370
+ \u77E5\u3089\u305B\u308B(t);
6371
+ }
6372
+ }
5913
6373
  function applyNodeTones(diagram2, doc) {
5914
6374
  for (const actor of doc.actors) {
5915
6375
  if (actor.tone === void 0) continue;
@@ -5918,7 +6378,7 @@ function applyNodeTones(diagram2, doc) {
5918
6378
  }
5919
6379
  }
5920
6380
  }
5921
- function applyCanvasPivotPositions(diagram2, doc, onNotice) {
6381
+ function applyCanvasPivotPositions(diagram2, doc) {
5922
6382
  for (const actor of doc.actors) {
5923
6383
  if (actor.partId !== void 0) continue;
5924
6384
  const aliasSlug = slugify(actor.name);
@@ -5940,30 +6400,6 @@ function applyCanvasPivotPositions(diagram2, doc, onNotice) {
5940
6400
  }
5941
6401
  }
5942
6402
  }
5943
- if (actor.nodes) {
5944
- for (const [subKey, override] of Object.entries(actor.nodes)) {
5945
- if (override.posX === void 0 || override.posY === void 0) continue;
5946
- let \u5F53\u305F\u3063\u305F = 0;
5947
- for (const node of diagram2.nodes) {
5948
- if (node.id === `${aliasSlug}-${subKey}` || node.id === `${subKey}-${aliasSlug}`) {
5949
- node.posX = override.posX;
5950
- node.posY = override.posY;
5951
- if (override.posW !== void 0) node.posW = override.posW;
5952
- if (override.posH !== void 0) node.posH = override.posH;
5953
- \u5F53\u305F\u3063\u305F += 1;
5954
- }
5955
- }
5956
- if (\u5F53\u305F\u3063\u305F === 0) {
5957
- onNotice?.({
5958
- kind: "sub-node-not-found",
5959
- actor: actor.name,
5960
- line: actor.pos?.line ?? 0,
5961
- message: `"${truncateForMessage(actor.name)}" \u306E nodes \u306B\u66F8\u3044\u305F "${truncateForMessage(subKey)}" \u306B\u5F53\u305F\u308B\u7BB1\u304C\u56F3\u306B\u3042\u308A\u307E\u305B\u3093`,
5962
- hint: "1 \u4EBA\u306B\u8907\u6570\u306E\u7BB1\u3092\u4F5C\u308B\u56F3\u7A2E\u3067\u3060\u3051\u52B9\u304D\u307E\u3059\u3002 \u7BB1\u305D\u306E\u3082\u306E\u306E\u4F4D\u7F6E\u306F actor \u5074\u306E \u4F4D\u7F6E: \u306B\u66F8\u3044\u3066\u304F\u3060\u3055\u3044"
5963
- });
5964
- }
5965
- }
5966
- }
5967
6403
  }
5968
6404
  }
5969
6405
  function lookupPart(partsCatalog, partId) {
@@ -6022,21 +6458,12 @@ function partTargetSize(part, posW, posH, scale) {
6022
6458
  };
6023
6459
  }
6024
6460
  function partScaleBase(part) {
6025
- const lanes = Array.isArray(part.lanes) ? part.lanes : [];
6026
6461
  const nodes = Array.isArray(part.nodes) ? part.nodes : [];
6027
- const lefts = [];
6028
- const rights = [];
6029
- for (const l of lanes) {
6030
- const lx = typeof l.x === "number" && Number.isFinite(l.x) ? l.x : 0;
6031
- const lw = positiveOr(l.width, 400);
6032
- lefts.push(lx);
6033
- rights.push(lx + lw);
6034
- }
6035
6462
  const stacks = nodes.map(
6036
6463
  (n) => typeof n.stack === "number" && Number.isFinite(n.stack) ? n.stack : 0
6037
6464
  );
6038
6465
  return {
6039
- w: positiveOr(maxOf(rights, 400) - minOf(lefts, 0), 400),
6466
+ w: \u90E8\u54C1\u306E\u7F6E\u304D\u65B9\u3092\u8AAD\u3080(part).\u5E45,
6040
6467
  h: Math.max(1, (maxOf(stacks, 0) - minOf(stacks, 0) + 1) * PART_STACK_PITCH)
6041
6468
  };
6042
6469
  }
@@ -6049,33 +6476,15 @@ function partExtent(part, targetW, targetH) {
6049
6476
  const fallback = { w: 400, h: 200, dx: 0, dy: 0 };
6050
6477
  if (!Array.isArray(part.lanes) || !Array.isArray(part.nodes)) return fallback;
6051
6478
  if (part.nodes.length === 0) return fallback;
6052
- const lanes = /* @__PURE__ */ new Map();
6053
- const laneLefts = [];
6054
- const laneRights = [];
6055
- for (const l of part.lanes) {
6056
- const x = typeof l.x === "number" && Number.isFinite(l.x) ? l.x : 0;
6057
- const w = positiveOr(l.width, 400);
6058
- lanes.set(l.id, { x, w });
6059
- laneLefts.push(x);
6060
- laneRights.push(x + w);
6061
- }
6062
- const bboxW = positiveOr(maxOf(laneRights, 400) - minOf(laneLefts, 0), 400);
6063
- const bboxCenterX = minOf(laneLefts, 0) + bboxW / 2;
6479
+ const \u7F6E\u304D\u65B9 = \u90E8\u54C1\u306E\u7F6E\u304D\u65B9\u3092\u8AAD\u3080(part);
6064
6480
  const { x: scaleX, y: scaleY } = partTargetScale(part, targetW, targetH);
6065
- const stacks = part.nodes.map(
6066
- (n) => typeof n.stack === "number" && Number.isFinite(n.stack) ? n.stack : 0
6067
- );
6068
- const maxStack = maxOf(stacks, 0);
6069
- const minStack = minOf(stacks, 0);
6070
- const centerStack = (minStack + maxStack) / 2;
6071
6481
  const tops = [];
6072
6482
  const bottoms = [];
6073
6483
  const lefts = [];
6074
6484
  const rights = [];
6075
6485
  part.nodes.forEach((n, i) => {
6076
- const lane = lanes.get(n.lane) ?? { x: 0, w: 320 };
6077
- const cx = (lane.x + lane.w / 2 - bboxCenterX) * scaleX;
6078
- const cy = ((stacks[i] ?? 0) - centerStack) * PART_STACK_PITCH * scaleY;
6486
+ const \u9801 = \u7F6E\u304D\u65B9.\u8981\u7D20[i] ?? { x: \u7F6E\u304D\u65B9.\u5DE6\u7AEF + \u7F6E\u304D\u65B9.\u5E45 / 2, y: 0 };
6487
+ const { dx: cx, dy: cy } = \u90E8\u54C1\u306E\u8981\u7D20\u306E\u305A\u308C(n, \u9801, \u7F6E\u304D\u65B9, scaleX, scaleY);
6079
6488
  const halfW = positiveOr(n.w, CDL_DEFAULT_NODE_W) * scaleX / 2;
6080
6489
  const halfH = positiveOr(n.h, CDL_DEFAULT_NODE_H) * scaleY / 2;
6081
6490
  lefts.push(cx - halfW);
@@ -6117,43 +6526,121 @@ function partFrameGeometry(part) {
6117
6526
  if (cached) return cached;
6118
6527
  const fallback = { w: 400, h: 200, left: 0, top: 0, boxW: 400, boxH: 200 };
6119
6528
  let out = fallback;
6120
- if (countDiagramElements(part) <= MAX_INPUT_ELEMENTS) {
6121
- try {
6122
- const own = layout(part);
6123
- const vb = own.viewBox;
6124
- const w = positiveOr(vb.w, 400);
6125
- const h = positiveOr(vb.h, 200);
6126
- if (own.nodes.length === 0) {
6127
- out = { w, h, left: 0, top: 0, boxW: w, boxH: h };
6128
- } else {
6129
- let x0 = Infinity;
6130
- let y0 = Infinity;
6131
- let x1 = -Infinity;
6132
- let y1 = -Infinity;
6133
- for (const n of own.nodes) {
6134
- x0 = Math.min(x0, n.cx - n.w / 2);
6135
- x1 = Math.max(x1, n.cx + n.w / 2);
6136
- y0 = Math.min(y0, n.cy - n.h / 2);
6137
- y1 = Math.max(y1, n.cy + n.h / 2);
6138
- }
6139
- const left = x0 - vb.x;
6140
- const top = y0 - vb.y;
6141
- out = {
6142
- w,
6143
- h,
6144
- left: Number.isFinite(left) ? left : 0,
6145
- top: Number.isFinite(top) ? top : 0,
6146
- boxW: positiveOr(x1 - x0, w),
6147
- boxH: positiveOr(y1 - y0, h)
6148
- };
6149
- }
6150
- } catch {
6151
- out = fallback;
6529
+ const own = \u90E8\u54C1\u306E\u9801\u3092\u914D\u7F6E\u3059\u308B(part);
6530
+ if (own !== void 0) {
6531
+ const vb = own.viewBox;
6532
+ const w = positiveOr(vb.w, 400);
6533
+ const h = positiveOr(vb.h, 200);
6534
+ if (own.nodes.length === 0) {
6535
+ out = { w, h, left: 0, top: 0, boxW: w, boxH: h };
6536
+ } else {
6537
+ let x0 = Infinity;
6538
+ let y0 = Infinity;
6539
+ let x1 = -Infinity;
6540
+ let y1 = -Infinity;
6541
+ for (const n of own.nodes) {
6542
+ x0 = Math.min(x0, n.cx - n.w / 2);
6543
+ x1 = Math.max(x1, n.cx + n.w / 2);
6544
+ y0 = Math.min(y0, n.cy - n.h / 2);
6545
+ y1 = Math.max(y1, n.cy + n.h / 2);
6546
+ }
6547
+ const left = x0 - vb.x;
6548
+ const top = y0 - vb.y;
6549
+ out = {
6550
+ w,
6551
+ h,
6552
+ left: Number.isFinite(left) ? left : 0,
6553
+ top: Number.isFinite(top) ? top : 0,
6554
+ boxW: positiveOr(x1 - x0, w),
6555
+ boxH: positiveOr(y1 - y0, h)
6556
+ };
6152
6557
  }
6153
6558
  }
6154
6559
  PART_FRAME_CACHE.set(part, out);
6155
6560
  return out;
6156
6561
  }
6562
+ var PART_PAGE_CACHE = /* @__PURE__ */ new WeakMap();
6563
+ function \u90E8\u54C1\u306E\u9801\u3092\u914D\u7F6E\u3059\u308B(part) {
6564
+ const cached = PART_PAGE_CACHE.get(part);
6565
+ if (cached !== void 0) return cached ?? void 0;
6566
+ let out = null;
6567
+ if (countDiagramElements(part) <= MAX_INPUT_ELEMENTS) {
6568
+ try {
6569
+ out = layout(part);
6570
+ } catch {
6571
+ out = null;
6572
+ }
6573
+ }
6574
+ PART_PAGE_CACHE.set(part, out);
6575
+ return out ?? void 0;
6576
+ }
6577
+ var \u90E8\u54C1\u306E\u7F6E\u304D\u65B9\u306E\u63A7\u3048 = /* @__PURE__ */ new WeakMap();
6578
+ function \u90E8\u54C1\u306E\u7F6E\u304D\u65B9\u3092\u8AAD\u3080(part) {
6579
+ const \u63A7\u3048 = \u90E8\u54C1\u306E\u7F6E\u304D\u65B9\u306E\u63A7\u3048.get(part);
6580
+ if (\u63A7\u3048) return \u63A7\u3048;
6581
+ const \u7F6E\u304D\u65B9 = \u9801\u306E\u7F6E\u304D\u65B9(part) ?? \u66F8\u3044\u305F\u7F6E\u304D\u65B9(part);
6582
+ \u90E8\u54C1\u306E\u7F6E\u304D\u65B9\u306E\u63A7\u3048.set(part, \u7F6E\u304D\u65B9);
6583
+ return \u7F6E\u304D\u65B9;
6584
+ }
6585
+ function \u7E26\u5217\u306E\u5916\u63A5(\u7E26\u5217) {
6586
+ const \u5024 = [...\u7E26\u5217.values()];
6587
+ const \u5DE6\u7AEF = minOf(\u5024.map((g) => g.x), 0);
6588
+ const \u53F3\u7AEF = maxOf(\u5024.map((g) => g.x + g.w), 400);
6589
+ return { \u5DE6\u7AEF, \u5E45: positiveOr(\u53F3\u7AEF - \u5DE6\u7AEF, 400) };
6590
+ }
6591
+ function \u9801\u306E\u7F6E\u304D\u65B9(part) {
6592
+ if (!Array.isArray(part.lanes) || !Array.isArray(part.nodes)) return void 0;
6593
+ const laid = \u90E8\u54C1\u306E\u9801\u3092\u914D\u7F6E\u3059\u308B(part);
6594
+ if (laid === void 0) return void 0;
6595
+ const \u7E26\u5217 = /* @__PURE__ */ new Map();
6596
+ for (const l of laid.lanes) {
6597
+ if (!Number.isFinite(l.x) || !Number.isFinite(l.width) || !(l.width > 0)) return void 0;
6598
+ \u7E26\u5217.set(l.id, { x: l.x, w: l.width });
6599
+ }
6600
+ const \u9801\u306E\u7BB1 = new Map(laid.nodes.map((n) => [n.id, n]));
6601
+ const \u7BB1\u305F\u3061 = [];
6602
+ for (const n of part.nodes) {
6603
+ const \u7BB1 = \u9801\u306E\u7BB1.get(n.id);
6604
+ if (\u7BB1 === void 0 || !Number.isFinite(\u7BB1.cx) || !Number.isFinite(\u7BB1.cy)) return void 0;
6605
+ \u7BB1\u305F\u3061.push(\u7BB1);
6606
+ }
6607
+ const \u7E26\u305F\u3061 = \u7BB1\u305F\u3061.map((b) => b.cy);
6608
+ const \u7E26\u306E\u4E2D\u5FC3 = (minOf(\u7E26\u305F\u3061, 0) + maxOf(\u7E26\u305F\u3061, 0)) / 2;
6609
+ return {
6610
+ \u7E26\u5217,
6611
+ ...\u7E26\u5217\u306E\u5916\u63A5(\u7E26\u5217),
6612
+ \u8981\u7D20: \u7BB1\u305F\u3061.map((b) => ({ x: b.cx, y: b.cy - \u7E26\u306E\u4E2D\u5FC3 }))
6613
+ };
6614
+ }
6615
+ function \u66F8\u3044\u305F\u7F6E\u304D\u65B9(part) {
6616
+ const lanes = Array.isArray(part.lanes) ? part.lanes : [];
6617
+ const nodes = Array.isArray(part.nodes) ? part.nodes : [];
6618
+ const \u7E26\u5217 = /* @__PURE__ */ new Map();
6619
+ for (const l of lanes) {
6620
+ \u7E26\u5217.set(l.id, {
6621
+ x: typeof l.x === "number" && Number.isFinite(l.x) ? l.x : 0,
6622
+ w: positiveOr(l.width, 400)
6623
+ });
6624
+ }
6625
+ const stacks = nodes.map(
6626
+ (n) => typeof n.stack === "number" && Number.isFinite(n.stack) ? n.stack : 0
6627
+ );
6628
+ const \u4E2D\u592E\u306E\u6BB5 = (minOf(stacks, 0) + maxOf(stacks, 0)) / 2;
6629
+ return {
6630
+ \u7E26\u5217,
6631
+ ...\u7E26\u5217\u306E\u5916\u63A5(\u7E26\u5217),
6632
+ \u8981\u7D20: nodes.map((n, i) => {
6633
+ const l = \u7E26\u5217.get(n.lane) ?? { x: 0, w: 320 };
6634
+ return { x: l.x + l.w / 2, y: ((stacks[i] ?? 0) - \u4E2D\u592E\u306E\u6BB5) * PART_STACK_PITCH };
6635
+ })
6636
+ };
6637
+ }
6638
+ function \u90E8\u54C1\u306E\u8981\u7D20\u306E\u305A\u308C(node, \u9801, \u7F6E\u304D\u65B9, scaleX, scaleY) {
6639
+ return {
6640
+ dx: ((node.posX ?? \u9801.x) - (\u7F6E\u304D\u65B9.\u5DE6\u7AEF + \u7F6E\u304D\u65B9.\u5E45 / 2)) * scaleX,
6641
+ dy: node.posY ?? \u9801.y * scaleY
6642
+ };
6643
+ }
6157
6644
  function partFrameExtent(part, targetW, targetH) {
6158
6645
  const box = partExtent(part, targetW, targetH);
6159
6646
  const geom = partFrameGeometry(part);
@@ -6183,15 +6670,14 @@ function partVisualSize(part, targetW, targetH) {
6183
6670
  }
6184
6671
  var PARTS_PER_ROW = 3;
6185
6672
  var PARTS_GAP = 120;
6186
- var STACK_PITCH = 280;
6187
- function partsBaseRows(nodes) {
6188
- return nodes.reduce((acc, n) => acc + Math.max(1, Math.ceil(positiveOr(n.h, 0) / STACK_PITCH)), 0);
6673
+ function partsBaseBottom(laid) {
6674
+ if (laid.nodes.length === 0) return void 0;
6675
+ return laid.viewBox.y + laid.viewBox.h;
6189
6676
  }
6190
- function partsGridCenters(baseRows, items) {
6677
+ function partsGridCenters(baseBottom, items) {
6191
6678
  const out = /* @__PURE__ */ new Map();
6192
6679
  if (items.length === 0) return out;
6193
- const safeCount = Number.isSafeInteger(baseRows) && baseRows >= 0 ? baseRows : 0;
6194
- const top = safeCount * STACK_PITCH + PARTS_GAP * 2;
6680
+ const top = baseBottom === void 0 || !Number.isFinite(baseBottom) ? PARTS_GAP * 2 : baseBottom + PARTS_GAP;
6195
6681
  const seen = /* @__PURE__ */ new Set();
6196
6682
  const unique = items.filter((i) => {
6197
6683
  if (seen.has(i.id)) return false;
@@ -6237,10 +6723,23 @@ function partsBudget(target, partsActors, partsCatalog) {
6237
6723
  });
6238
6724
  return accepted;
6239
6725
  }
6726
+ function baseDiagramBottom(target, baseNodes, partsLaneIds) {
6727
+ if (baseNodes.length === 0) return void 0;
6728
+ const baseIds = new Set(baseNodes.map((n) => n.id));
6729
+ return partsBaseBottom(
6730
+ layout({
6731
+ ...target,
6732
+ lanes: target.lanes.filter((l) => !partsLaneIds.has(l.id)),
6733
+ nodes: [...baseNodes],
6734
+ edges: target.edges.filter((e) => baseIds.has(e.from) && baseIds.has(e.to))
6735
+ })
6736
+ );
6737
+ }
6240
6738
  function partGridCenters(target, doc, partsCatalog, accepted, acceptedFrom) {
6241
6739
  const partsActors = doc.actors.filter((a) => a.partId !== void 0);
6740
+ const \u7E26\u5217\u306E\u90E8\u54C1 = \u7E26\u5217\u306B\u7F6E\u304F\u90E8\u54C1(target, doc).\u7E26\u5217;
6242
6741
  const autoActors = partsActors.filter(
6243
- (a) => a.posX === void 0 && a.posY === void 0 && a.posRel === void 0
6742
+ (a) => a.posX === void 0 && a.posY === void 0 && a.posRel === void 0 && !\u7E26\u5217\u306E\u90E8\u54C1.has(a.name)
6244
6743
  );
6245
6744
  if (autoActors.length === 0) return /* @__PURE__ */ new Map();
6246
6745
  const otherActorNames = new Set(
@@ -6273,7 +6772,7 @@ function partGridCenters(target, doc, partsCatalog, accepted, acceptedFrom) {
6273
6772
  extents.set(a.name, partFrameExtent(part, t.w, t.h));
6274
6773
  }
6275
6774
  const centers = partsGridCenters(
6276
- partsBaseRows(baseNodes),
6775
+ baseDiagramBottom(target, baseNodes, partsLaneIds),
6277
6776
  placedActors.map((a) => ({ id: a.name, ...extents.get(a.name) }))
6278
6777
  );
6279
6778
  const out = /* @__PURE__ */ new Map();
@@ -6310,7 +6809,126 @@ function partBoxes(target, doc, partsCatalog) {
6310
6809
  }
6311
6810
  return out;
6312
6811
  }
6313
- function cleanupPlaceholderActor(target, doc, a) {
6812
+ function \u90E8\u54C1\u306E\u8981\u7D20\u3078\u7E4B\u3050(\u90E8\u54C1\u306E\u540D\u524D, partId, part, edgeSteps, onNotice) {
6813
+ const \u8981\u7D20 = (part?.nodes ?? []).map((n) => n.id);
6814
+ const \u898B\u305B\u308B\u6570 = 8;
6815
+ const \u8981\u7D20\u306E\u4E00\u89A7 = `${\u8981\u7D20.slice(0, \u898B\u305B\u308B\u6570).map(truncateForMessage).join(", ")}${\u8981\u7D20.length > \u898B\u305B\u308B\u6570 ? ` \u307B\u304B ${\u8981\u7D20.length - \u898B\u305B\u308B\u6570} \u4EF6` : ""}`;
6816
+ return (edge, \u7AEF) => {
6817
+ const s = edgeSteps?.get(edge.id);
6818
+ const \u7E4B\u3044\u3060 = { ...edge };
6819
+ for (const \u5074 of ["from", "to"]) {
6820
+ if (!\u7AEF[\u5074]) continue;
6821
+ if (s === void 0 || s[\u5074] !== \u90E8\u54C1\u306E\u540D\u524D) return void 0;
6822
+ const \u6B04 = \u5074 === "from" ? "fromPartNode" : "toPartNode";
6823
+ const \u540D\u6307\u3057 = s[\u6B04];
6824
+ let \u7406\u7531;
6825
+ if (part === void 0) {
6826
+ \u7406\u7531 = {
6827
+ message: "\u3092\u56F3\u306B\u53D6\u308A\u8FBC\u307E\u306A\u304B\u3063\u305F",
6828
+ hint: "\u90E8\u54C1\u304C\u56F3\u306B\u5165\u3089\u306A\u3044\u305F\u3081\u3001\u77E2\u5370\u306E\u7AEF\u306B\u3067\u304D\u307E\u305B\u3093"
6829
+ };
6830
+ } else if (\u540D\u6307\u3057 !== void 0) {
6831
+ if (\u8981\u7D20.includes(\u540D\u6307\u3057)) \u7E4B\u3044\u3060[\u5074] = `${\u90E8\u54C1\u306E\u540D\u524D}__${\u540D\u6307\u3057}`;
6832
+ else
6833
+ \u7406\u7531 = {
6834
+ message: `\u306E\u4E2D\u306B ${\u6B04} \u306B\u66F8\u3044\u305F "${truncateForMessage(\u540D\u6307\u3057)}" \u3068\u3044\u3046\u8981\u7D20\u304C\u7121\u3044`,
6835
+ hint: `\u3053\u306E\u90E8\u54C1\u306E\u8981\u7D20 = ${\u8981\u7D20\u306E\u4E00\u89A7}`
6836
+ };
6837
+ } else if (\u8981\u7D20.length === 1) {
6838
+ \u7E4B\u3044\u3060[\u5074] = `${\u90E8\u54C1\u306E\u540D\u524D}__${\u8981\u7D20[0]}`;
6839
+ } else {
6840
+ \u7406\u7531 = \u8981\u7D20.length === 0 ? { message: "\u306E\u4E2D\u306B\u7E4B\u3052\u308B\u8981\u7D20\u304C\u7121\u3044", hint: "\u3053\u306E\u90E8\u54C1\u306F\u8981\u7D20\u3092\u6301\u305F\u306A\u3044\u305F\u3081\u3001\u77E2\u5370\u306E\u7AEF\u306B\u3067\u304D\u307E\u305B\u3093" } : {
6841
+ message: "\u306E\u4E2D\u306E\u3069\u306E\u8981\u7D20\u306B\u7E4B\u3050\u304B\u304C\u6C7A\u307E\u3089\u306A\u3044",
6842
+ hint: `\u8981\u7D20\u304C 2 \u3064\u4EE5\u4E0A\u3042\u308B\u90E8\u54C1\u306F\u3001\u77E2\u5370\u306B ${\u6B04}: <\u8981\u7D20\u306E id> \u3092\u66F8\u3044\u3066\u7E4B\u3050\u8981\u7D20\u3092\u9078\u3076 (\u8981\u7D20 = ${\u8981\u7D20\u306E\u4E00\u89A7})`
6843
+ };
6844
+ }
6845
+ if (\u7406\u7531 === void 0) continue;
6846
+ const \u77E2\u5370 = `"${truncateForMessage(s.from)}" \u304B\u3089 "${truncateForMessage(s.to)}" \u3078\u306E\u77E2\u5370`;
6847
+ onNotice?.({
6848
+ kind: "part-edge-dropped",
6849
+ actor: \u90E8\u54C1\u306E\u540D\u524D,
6850
+ line: s.pos.line,
6851
+ message: `${\u77E2\u5370}\u306F\u3001"${truncateForMessage(\u90E8\u54C1\u306E\u540D\u524D)}" (${truncateForMessage(partId)}) ${\u7406\u7531.message}\u305F\u3081\u5916\u3057\u307E\u3057\u305F`,
6852
+ hint: \u7406\u7531.hint
6853
+ });
6854
+ return void 0;
6855
+ }
6856
+ return \u7E4B\u3044\u3060;
6857
+ };
6858
+ }
6859
+ function reportPartNodeNotHonored(doc, onNotice) {
6860
+ if (!onNotice) return;
6861
+ const \u9806\u5E8F\u56F3 = doc.type === "sequence" || doc.type === "solidity";
6862
+ const \u90E8\u54C1 = new Set(doc.actors.filter((a) => a.partId !== void 0).map((a) => a.name));
6863
+ const \u5C45\u308B = new Set(doc.actors.map((a) => a.name));
6864
+ for (const s of doc.flow) {
6865
+ for (const [\u5074, \u6B04] of [
6866
+ ["from", "fromPartNode"],
6867
+ ["to", "toPartNode"]
6868
+ ]) {
6869
+ const \u5024 = s[\u6B04];
6870
+ if (\u5024 === void 0) continue;
6871
+ const \u540D = s[\u5074];
6872
+ if (!\u5C45\u308B.has(\u540D)) continue;
6873
+ if (!\u9806\u5E8F\u56F3 && \u90E8\u54C1.has(\u540D)) continue;
6874
+ onNotice({
6875
+ kind: "part-node-ignored",
6876
+ actor: \u540D,
6877
+ line: s.pos.line,
6878
+ message: \u9806\u5E8F\u56F3 ? `\u9806\u5E8F\u56F3\u306E\u8A00\u3065\u3066\u306F "${truncateForMessage(\u540D)}" \u306E\u7E26\u306E\u7DDA\u306B\u5C4A\u304F\u305F\u3081\u3001${\u6B04} \u306B\u66F8\u3044\u305F "${truncateForMessage(\u5024)}" \u306F\u52B9\u304D\u307E\u305B\u3093` : `"${truncateForMessage(\u540D)}" \u306F\u90E8\u54C1\u3067\u306F\u306A\u3044\u305F\u3081\u3001${\u6B04} \u306B\u66F8\u3044\u305F "${truncateForMessage(\u5024)}" \u306F\u52B9\u304D\u307E\u305B\u3093`,
6879
+ hint: \u9806\u5E8F\u56F3 ? "\u90E8\u54C1\u306E\u4E2D\u306E\u8981\u7D20\u3078\u77E2\u5370\u3092\u7E4B\u3050\u306E\u306F\u3001\u77E2\u5370\u3092\u7BB1\u306E\u9593\u306B\u5F15\u304F\u56F3\u7A2E (flow / swimlane \u306A\u3069)" : "\u90E8\u54C1\u306E\u4E2D\u306E\u8981\u7D20\u306E\u540D\u6307\u3057\u306F\u3001kind \u306B\u90E8\u54C1\u306E\u540D\u524D\u3092\u66F8\u3044\u305F\u7BB1\u306E\u7AEF\u306B\u3060\u3051\u52B9\u304F"
6880
+ });
6881
+ }
6882
+ }
6883
+ }
6884
+ function \u4EEE\u306E\u7BB1\u306Eid\u304B(doc, name) {
6885
+ const aliasSlug = slugify(name);
6886
+ const \u7D20\u306E\u7BB1\u306Eid = new Set(
6887
+ doc.actors.filter((x) => x.partId === void 0).map((x) => slugify(x.name))
6888
+ );
6889
+ const \u982D\u304C\u91CD\u306A\u308Bid = [
6890
+ ...new Set(
6891
+ doc.actors.filter((x) => x.name !== name).map((x) => slugify(x.name)).filter((s) => s.startsWith(`${aliasSlug}-`) || s.endsWith(`-${aliasSlug}`))
6892
+ )
6893
+ ];
6894
+ const \u81EA\u5206\u306E\u5F62\u304B = (id, slug) => id === slug || id.startsWith(`${slug}-`) || /^s\d+-/.test(id) && id.endsWith(`-${slug}`);
6895
+ return (id) => {
6896
+ if (\u7D20\u306E\u7BB1\u306Eid.has(id)) return false;
6897
+ if (\u982D\u304C\u91CD\u306A\u308Bid.some((s) => \u81EA\u5206\u306E\u5F62\u304B(id, s))) return false;
6898
+ return \u81EA\u5206\u306E\u5F62\u304B(id, aliasSlug);
6899
+ };
6900
+ }
6901
+ function \u7E26\u5217\u306B\u7F6E\u304F\u90E8\u54C1(target, doc) {
6902
+ const \u7E26\u5217 = /* @__PURE__ */ new Map();
6903
+ const \u57FA\u6E96\u306E\u305F\u3081\u5916\u3057\u305F = /* @__PURE__ */ new Map();
6904
+ if (doc.type === "sequence" || doc.type === "solidity") return { \u7E26\u5217, \u57FA\u6E96\u306E\u305F\u3081\u5916\u3057\u305F };
6905
+ const \u57FA\u6E96\u306E\u540D\u524D = new Set(
6906
+ doc.actors.map((a) => a.posRel?.anchor).filter((n) => n !== void 0)
6907
+ );
6908
+ const \u7E26\u5217\u306Eid = new Set(target.lanes.map((l) => l.id));
6909
+ for (const a of doc.actors) {
6910
+ if (a.partId === void 0) continue;
6911
+ if (\u7E26\u5217.has(a.name) || \u57FA\u6E96\u306E\u305F\u3081\u5916\u3057\u305F.has(a.name)) continue;
6912
+ if (a.posX !== void 0 || a.posY !== void 0 || a.posRel !== void 0) continue;
6913
+ const \u7F6E\u304F\u7E26\u5217 = \u90E8\u54C1\u306E\u7E26\u5217(target, doc, a, \u7E26\u5217\u306Eid);
6914
+ if (\u7F6E\u304F\u7E26\u5217 === void 0) continue;
6915
+ if (\u57FA\u6E96\u306E\u540D\u524D.has(a.name)) \u57FA\u6E96\u306E\u305F\u3081\u5916\u3057\u305F.set(a.name, \u7F6E\u304F\u7E26\u5217);
6916
+ else \u7E26\u5217.set(a.name, \u7F6E\u304F\u7E26\u5217);
6917
+ }
6918
+ return { \u7E26\u5217, \u57FA\u6E96\u306E\u305F\u3081\u5916\u3057\u305F };
6919
+ }
6920
+ function \u90E8\u54C1\u306E\u7E26\u5217(target, doc, a, \u7E26\u5217\u306Eid) {
6921
+ if (a.lane !== void 0) return \u7E26\u5217\u306Eid.has(a.lane) ? a.lane : void 0;
6922
+ if (target.lanes.length < 2) return void 0;
6923
+ const \u4EEE\u306E\u7BB1\u304B = \u4EEE\u306E\u7BB1\u306Eid\u304B(doc, a.name);
6924
+ const \u4EEE\u306E\u7BB1\u306E\u7E26\u5217 = new Set(target.nodes.filter((n) => \u4EEE\u306E\u7BB1\u304B(n.id)).map((n) => n.lane));
6925
+ if (\u4EEE\u306E\u7BB1\u306E\u7E26\u5217.size > 1) return void 0;
6926
+ const [\u5165\u3063\u3066\u3044\u305F] = [...\u4EEE\u306E\u7BB1\u306E\u7E26\u5217];
6927
+ const \u5019\u88DC = \u5165\u3063\u3066\u3044\u305F ?? target.lanes.find((l) => l.label === a.name && !target.nodes.some((n) => n.lane === l.id))?.id;
6928
+ if (\u5019\u88DC === void 0) return void 0;
6929
+ return target.nodes.some((n) => n.lane === \u5019\u88DC && !\u4EEE\u306E\u7BB1\u304B(n.id)) ? void 0 : \u5019\u88DC;
6930
+ }
6931
+ function cleanupPlaceholderActor(target, doc, a, \u7E4B\u304E\u76F4\u3059) {
6314
6932
  const aliasSlug = slugify(a.name);
6315
6933
  const ownedLaneIds = /* @__PURE__ */ new Set();
6316
6934
  if (doc.type === "sequence" || doc.type === "solidity") {
@@ -6323,37 +6941,37 @@ function cleanupPlaceholderActor(target, doc, a) {
6323
6941
  for (const n of target.nodes) {
6324
6942
  if (ownedLaneIds.has(n.lane)) ownedNodeIds.add(n.id);
6325
6943
  }
6326
- const \u7D20\u306E\u7BB1\u306Eid = new Set(
6327
- doc.actors.filter((x) => x.partId === void 0).map((x) => slugify(x.name))
6328
- );
6329
- const matchesAliasSlug = (id) => {
6330
- if (\u7D20\u306E\u7BB1\u306Eid.has(id)) return false;
6331
- if (id === aliasSlug) return true;
6332
- if (id.startsWith(`${aliasSlug}-`)) return true;
6333
- if (/^s\d+-/.test(id) && id.endsWith(`-${aliasSlug}`)) return true;
6334
- return false;
6335
- };
6944
+ const matchesAliasSlug = \u4EEE\u306E\u7BB1\u306Eid\u304B(doc, a.name);
6336
6945
  const relatedToActor = (id) => ownedLaneIds.size > 0 ? ownedNodeIds.has(id) : matchesAliasSlug(id);
6946
+ const \u4EEE\u306E\u7BB1\u306E\u7E26\u5217 = new Set(target.nodes.filter((n) => relatedToActor(n.id)).map((n) => n.lane));
6337
6947
  target.nodes = target.nodes.filter((n) => !relatedToActor(n.id));
6338
6948
  const removedEdgeIds = /* @__PURE__ */ new Set();
6339
- target.edges = target.edges.filter((e) => {
6340
- const drop = relatedToActor(e.from) || relatedToActor(e.to);
6341
- if (drop) removedEdgeIds.add(e.id);
6342
- return !drop;
6343
- });
6949
+ const \u6B8B\u3059\u77E2\u5370 = [];
6950
+ for (const e of target.edges) {
6951
+ const \u7AEF = { from: relatedToActor(e.from), to: relatedToActor(e.to) };
6952
+ if (!\u7AEF.from && !\u7AEF.to) {
6953
+ \u6B8B\u3059\u77E2\u5370.push(e);
6954
+ continue;
6955
+ }
6956
+ const \u7E4B\u3044\u3060 = \u7E4B\u304E\u76F4\u3059?.(e, \u7AEF);
6957
+ if (\u7E4B\u3044\u3060) \u6B8B\u3059\u77E2\u5370.push(\u7E4B\u3044\u3060);
6958
+ else removedEdgeIds.add(e.id);
6959
+ }
6960
+ target.edges = \u6B8B\u3059\u77E2\u5370;
6344
6961
  const \u6B8B\u308B\u7BB1\u3092\u6301\u3064 = new Set(target.nodes.map((n) => n.lane));
6345
6962
  target.lanes = target.lanes.filter((l) => {
6346
6963
  if (a.lane !== void 0 && l.id === a.lane) return true;
6347
6964
  if (\u6B8B\u308B\u7BB1\u3092\u6301\u3064.has(l.id)) return true;
6348
6965
  if (l.label === a.name) return false;
6349
6966
  if (l.id === aliasSlug) return false;
6967
+ if (\u4EEE\u306E\u7BB1\u306E\u7E26\u5217.has(l.id) && !Object.hasOwn(doc.lanes ?? {}, l.id)) return false;
6350
6968
  return true;
6351
6969
  });
6352
6970
  for (const phase of target.phases) {
6353
6971
  phase.activate = phase.activate.filter((id) => !relatedToActor(id) && !removedEdgeIds.has(id));
6354
6972
  }
6355
6973
  }
6356
- function mergePartsFromActors(target, doc, partsCatalog, onNotice, derivedSourceLines) {
6974
+ function mergePartsFromActors(target, doc, partsCatalog, onNotice, derivedSourceLines, edgeSteps) {
6357
6975
  const partsActors = doc.actors.filter((a) => a.partId !== void 0);
6358
6976
  if (partsActors.length === 0) return target;
6359
6977
  const \u5024\u306E\u524D\u7F6E\u304D = \u5024\u306E\u524D\u7F6E\u304D\u3092\u4F5C\u308B(partsActors.map((a) => a.name));
@@ -6366,6 +6984,9 @@ function mergePartsFromActors(target, doc, partsCatalog, onNotice, derivedSource
6366
6984
  }
6367
6985
  const budget = partsBudget(target, partsActors, partsCatalog);
6368
6986
  const gridCenters = partGridCenters(target, doc, partsCatalog, budget, partsActors);
6987
+ const { \u7E26\u5217: \u7E26\u5217\u306E\u90E8\u54C1, \u57FA\u6E96\u306E\u305F\u3081\u5916\u3057\u305F } = \u7E26\u5217\u306B\u7F6E\u304F\u90E8\u54C1(target, doc);
6988
+ const \u7E26\u5217\u306B\u7F6E\u3044\u305F = [];
6989
+ const \u81EA\u5206\u306E\u7E26\u5217\u306B\u7F6E\u3044\u305F = [];
6369
6990
  for (const [actorIndex, actor] of partsActors.entries()) {
6370
6991
  const partId = actor.partId;
6371
6992
  if (typeof partId !== "string" || partId.length === 0) continue;
@@ -6379,7 +7000,12 @@ function mergePartsFromActors(target, doc, partsCatalog, onNotice, derivedSource
6379
7000
  message: `"${actor.name}" (${partId}) \u306F\u5927\u304D\u3059\u304E\u308B\u305F\u3081\u53D6\u308A\u8FBC\u307F\u307E\u305B\u3093\u3002`,
6380
7001
  hint: overOne ? `\u8981\u7D20\u6570\u304C\u4E0A\u9650 (${MAX_INPUT_ELEMENTS}) \u3092\u8D85\u3048\u3066\u3044\u307E\u3059` : `\u56F3\u5168\u4F53\u306E\u8981\u7D20\u6570\u304C\u4E0A\u9650 (${MAX_INPUT_ELEMENTS}) \u3092\u8D85\u3048\u307E\u3059`
6381
7002
  });
6382
- cleanupPlaceholderActor(target, doc, actor);
7003
+ cleanupPlaceholderActor(
7004
+ target,
7005
+ doc,
7006
+ actor,
7007
+ \u90E8\u54C1\u306E\u8981\u7D20\u3078\u7E4B\u3050(actor.name, partId, void 0, edgeSteps, onNotice)
7008
+ );
6383
7009
  continue;
6384
7010
  }
6385
7011
  const part = found;
@@ -6389,13 +7015,81 @@ function mergePartsFromActors(target, doc, partsCatalog, onNotice, derivedSource
6389
7015
  `[dragon] parts kind "${partId}" not found in partsCatalog (actor: ${actor.name})`
6390
7016
  );
6391
7017
  }
7018
+ for (const s of doc.flow) {
7019
+ for (const [\u5074, \u6B04] of [
7020
+ ["from", "fromPartNode"],
7021
+ ["to", "toPartNode"]
7022
+ ]) {
7023
+ const \u5024 = s[\u6B04];
7024
+ if (\u5024 === void 0 || s[\u5074] !== actor.name) continue;
7025
+ if (doc.type === "sequence" || doc.type === "solidity") continue;
7026
+ onNotice?.({
7027
+ kind: "part-node-ignored",
7028
+ actor: actor.name,
7029
+ line: s.pos.line,
7030
+ message: `"${truncateForMessage(actor.name)}" (${truncateForMessage(partId)}) \u306F\u90E8\u54C1\u306E\u4E00\u89A7\u306B\u7121\u3044\u305F\u3081\u3001${\u6B04} \u306B\u66F8\u3044\u305F "${truncateForMessage(\u5024)}" \u306F\u52B9\u304D\u307E\u305B\u3093`,
7031
+ hint: "kind \u306B\u90E8\u54C1\u306E\u540D\u524D\u3092\u66F8\u304F (\u7DB4\u308A\u3092\u78BA\u304B\u3081\u308B)"
7032
+ });
7033
+ }
7034
+ }
6392
7035
  continue;
6393
7036
  }
6394
- cleanupPlaceholderActor(target, doc, actor);
7037
+ const \u7F6E\u304F\u7E26\u5217 = \u7E26\u5217\u306E\u90E8\u54C1.get(actor.name);
7038
+ cleanupPlaceholderActor(
7039
+ target,
7040
+ doc,
7041
+ \u7F6E\u304F\u7E26\u5217 !== void 0 ? { name: actor.name, lane: \u7F6E\u304F\u7E26\u5217 } : actor,
7042
+ \u90E8\u54C1\u306E\u8981\u7D20\u3078\u7E4B\u3050(actor.name, partId, part, edgeSteps, onNotice)
7043
+ );
7044
+ const \u5916\u3057\u305F\u7E26\u5217 = \u57FA\u6E96\u306E\u305F\u3081\u5916\u3057\u305F.get(actor.name);
7045
+ if (\u5916\u3057\u305F\u7E26\u5217 !== void 0) {
7046
+ onNotice?.({
7047
+ kind: "part-lane-ignored",
7048
+ actor: actor.name,
7049
+ line: actor.pos?.line ?? 0,
7050
+ message: `"${actor.name}" \u306F\u4ED6\u306E\u7BB1\u306E\u4F4D\u7F6E\u306E\u57FA\u6E96\u306B\u306A\u3063\u3066\u3044\u308B\u305F\u3081\u3001\u7E26\u5217 "${target.lanes.find((l) => l.id === \u5916\u3057\u305F\u7E26\u5217)?.label ?? \u5916\u3057\u305F\u7E26\u5217}" \u306B\u306F\u7F6E\u304B\u305A\u56F3\u306E\u4E0B\u306B\u4E26\u3079\u307E\u3057\u305F`,
7051
+ hint: `\u7E26\u5217\u306B\u7F6E\u304D\u305F\u3044\u6642\u306F\u3001"${actor.name}" \u3092\u57FA\u6E96\u306B\u3057\u305F\u4F4D\u7F6E (\u4F4D\u7F6E: ${actor.name} \u306E\u53F3 200 \u306A\u3069) \u3092\u5EA7\u6A19\u3067\u66F8\u304F`
7052
+ });
7053
+ }
6395
7054
  const merged = applyColorHex(part, actor.colorHex, actor.stateOverride ?? {});
7055
+ if (actor.colorHex && !(part.states ?? []).some((st) => isColorValue(st.initial))) {
7056
+ onNotice?.({
7057
+ kind: "part-color-ignored",
7058
+ actor: actor.name,
7059
+ line: actor.pos?.line ?? 0,
7060
+ message: `"${actor.name}" (${partId}) \u306F\u8272\u3092\u5909\u3048\u3089\u308C\u308B\u72B6\u614B\u3092\u6301\u305F\u306A\u3044\u305F\u3081\u3001\u8272\u756A\u53F7 ${actor.colorHex} \u306F\u52B9\u304D\u307E\u305B\u3093`,
7061
+ hint: "\u8272\u3092\u5909\u3048\u3089\u308C\u308B\u90E8\u54C1\u306F\u3001\u521D\u671F\u5024\u304C\u8272\u756A\u53F7\u306E\u72B6\u614B\u3092\u6301\u3064\u3082\u306E (\u4F8B = state-indicator)"
7062
+ });
7063
+ }
7064
+ if (actor.partColorName) {
7065
+ onNotice?.({
7066
+ kind: "part-color-ignored",
7067
+ actor: actor.name,
7068
+ line: actor.pos?.line ?? 0,
7069
+ // 残っている名前は読み替えた後の正規の名前 (`成功` なら `success`) なので文には出さない
7070
+ message: `"${actor.name}" (${partId}) \u306E\u8272\u306F\u8272\u306E\u540D\u524D\u3067\u306F\u5909\u308F\u308A\u307E\u305B\u3093`,
7071
+ hint: '\u90E8\u54C1\u306E\u8272\u306F\u8272\u756A\u53F7\u3067\u66F8\u304F (\u4F8B = color: "#d9534f")'
7072
+ });
7073
+ }
7074
+ const \u90E8\u54C1\u306E\u72B6\u614B = new Set((part.states ?? []).map((st) => st.id));
7075
+ const \u7121\u3044\u72B6\u614B = Object.keys(actor.stateOverride ?? {}).filter(
7076
+ (k) => k !== "phase" && !\u90E8\u54C1\u306E\u72B6\u614B.has(k)
7077
+ );
7078
+ if (\u7121\u3044\u72B6\u614B.length > 0) {
7079
+ onNotice?.({
7080
+ kind: "part-state-missing",
7081
+ actor: actor.name,
7082
+ line: actor.pos?.line ?? 0,
7083
+ message: `"${actor.name}" (${partId}) \u306F ${\u7121\u3044\u72B6\u614B.map((k) => `"${truncateForMessage(k)}"`).join(" / ")} \u3068\u3044\u3046\u72B6\u614B\u3092\u6301\u305F\u306A\u3044\u305F\u3081\u3001\u66F8\u3044\u305F\u5024\u306F\u52B9\u304D\u307E\u305B\u3093`,
7084
+ hint: \u90E8\u54C1\u306E\u72B6\u614B.size > 0 ? `\u3053\u306E\u90E8\u54C1\u306E\u72B6\u614B = ${[...\u90E8\u54C1\u306E\u72B6\u614B].join(", ")}` : "\u3053\u306E\u90E8\u54C1\u306F\u72B6\u614B\u3092\u6301\u305F\u306A\u3044\u305F\u3081\u3001\u5024\u3092\u66F8\u3044\u3066\u3082\u5909\u308F\u308A\u307E\u305B\u3093"
7085
+ });
7086
+ }
6396
7087
  let placeX = actor.posX;
6397
7088
  let placeY = actor.posY;
6398
- if (placeX === void 0 && placeY === void 0) {
7089
+ if (\u7F6E\u304F\u7E26\u5217 !== void 0) {
7090
+ placeX = 0;
7091
+ placeY = 0;
7092
+ } else if (placeX === void 0 && placeY === void 0) {
6399
7093
  const center = gridCenters.get(actor.name);
6400
7094
  placeX = center?.cx;
6401
7095
  placeY = center?.cy;
@@ -6414,12 +7108,13 @@ function mergePartsFromActors(target, doc, partsCatalog, onNotice, derivedSource
6414
7108
  }
6415
7109
  }
6416
7110
  const t = partTargetSize(part, actor.posW, actor.posH, actor.scale);
6417
- mergePartIntoDiagram(
7111
+ const \u7D44\u307F\u8FBC\u3080\u524D\u306E\u7BB1\u306E\u6570 = target.nodes.length;
7112
+ const \u4F5C\u3063\u305F\u7E26\u5217 = mergePartIntoDiagram(
6418
7113
  target,
6419
7114
  part,
6420
7115
  actor.name,
6421
7116
  merged,
6422
- actor.lane,
7117
+ \u7F6E\u304F\u7E26\u5217 ?? actor.lane,
6423
7118
  placeX,
6424
7119
  placeY,
6425
7120
  t.w,
@@ -6429,9 +7124,122 @@ function mergePartsFromActors(target, doc, partsCatalog, onNotice, derivedSource
6429
7124
  derivedSourceLines,
6430
7125
  \u5024\u306E\u524D\u7F6E\u304D.get(actor.name)
6431
7126
  );
7127
+ const \u8981\u7D20 = new Set(target.nodes.slice(\u7D44\u307F\u8FBC\u3080\u524D\u306E\u7BB1\u306E\u6570).map((n) => n.id));
7128
+ if (\u7F6E\u304F\u7E26\u5217 !== void 0) {
7129
+ \u7E26\u5217\u306B\u7F6E\u3044\u305F.push({ \u7E26\u5217: \u7F6E\u304F\u7E26\u5217, \u8981\u7D20 });
7130
+ } else if (\u4F5C\u3063\u305F\u7E26\u5217.length > 0) {
7131
+ \u81EA\u5206\u306E\u7E26\u5217\u306B\u7F6E\u3044\u305F.push({ \u540D\u524D: actor.name, \u7E26\u5217: \u4F5C\u3063\u305F\u7E26\u5217, \u8981\u7D20 });
7132
+ }
6432
7133
  }
7134
+ \u90E8\u54C1\u306E\u7E26\u5217\u3092\u90E8\u54C1\u306B\u56FA\u5B9A\u3059\u308B(target, \u81EA\u5206\u306E\u7E26\u5217\u306B\u7F6E\u3044\u305F);
7135
+ \u7E26\u5217\u306B\u7F6E\u3044\u305F\u90E8\u54C1\u3092\u63C3\u3048\u308B(target, \u7E26\u5217\u306B\u7F6E\u3044\u305F);
6433
7136
  return target;
6434
7137
  }
7138
+ var \u90E8\u54C1\u306E\u7E26\u5217\u306E\u540D\u672D\u306E\u9AD8\u3055 = 60;
7139
+ function \u90E8\u54C1\u306E\u7E26\u5217\u3092\u90E8\u54C1\u306B\u56FA\u5B9A\u3059\u308B(target, \u90E8\u54C1\u305F\u3061) {
7140
+ const \u5EA7\u6A19\u3067\u7F6E\u3044\u305F = (id) => {
7141
+ const n = target.nodes.find((x) => x.id === id);
7142
+ return n !== void 0 && n.posX !== void 0 && n.posY !== void 0;
7143
+ };
7144
+ const \u5BFE\u8C61 = \u90E8\u54C1\u305F\u3061.filter((p) => [...p.\u8981\u7D20].every(\u5EA7\u6A19\u3067\u7F6E\u3044\u305F));
7145
+ if (\u5BFE\u8C61.length === 0) return;
7146
+ let laid;
7147
+ try {
7148
+ laid = layout(target);
7149
+ } catch {
7150
+ return;
7151
+ }
7152
+ for (const p of \u5BFE\u8C61) {
7153
+ const \u7BB1 = laid.nodes.filter((n) => p.\u8981\u7D20.has(n.id));
7154
+ if (\u7BB1.length === 0) continue;
7155
+ const \u4E0A\u7AEF = Math.min(...\u7BB1.map((n) => n.cy - n.h / 2));
7156
+ const \u4E0B\u7AEF = Math.max(...\u7BB1.map((n) => n.cy + n.h / 2));
7157
+ const \u7E26\u5217\u305F\u3061 = p.\u7E26\u5217.flatMap((l) => {
7158
+ const \u7E26\u5217 = target.lanes.find((x) => x.id === l.id);
7159
+ return \u7E26\u5217 ? [{ ...l, \u7E26\u5217 }] : [];
7160
+ });
7161
+ let \u540D\u672D\u306E\u7E26\u5217;
7162
+ for (const l of \u7E26\u5217\u305F\u3061) {
7163
+ if (\u540D\u672D\u306E\u7E26\u5217 === void 0 || (l.\u7E26\u5217.x ?? 0) < (\u540D\u672D\u306E\u7E26\u5217.\u7E26\u5217.x ?? 0)) \u540D\u672D\u306E\u7E26\u5217 = l;
7164
+ }
7165
+ for (const l of \u7E26\u5217\u305F\u3061) {
7166
+ l.\u7E26\u5217.posX = l.\u7E26\u5217.x ?? 0;
7167
+ l.\u7E26\u5217.posY = \u4E0A\u7AEF - \u90E8\u54C1\u306E\u7E26\u5217\u306E\u540D\u672D\u306E\u9AD8\u3055;
7168
+ l.\u7E26\u5217.posH = \u4E0B\u7AEF - \u4E0A\u7AEF + \u90E8\u54C1\u306E\u7E26\u5217\u306E\u540D\u672D\u306E\u9AD8\u3055;
7169
+ const \u540D\u672D = l === \u540D\u672D\u306E\u7E26\u5217 ? l.\u90E8\u54C1\u306E\u540D\u672D ?? p.\u540D\u524D : l.\u90E8\u54C1\u306E\u540D\u672D;
7170
+ if (\u540D\u672D === void 0) delete l.\u7E26\u5217.label;
7171
+ else l.\u7E26\u5217.label = \u540D\u672D;
7172
+ }
7173
+ }
7174
+ }
7175
+ var \u90E8\u54C1\u306E\u7E26\u5217\u306E\u4F59\u767D = 25;
7176
+ function \u7E26\u5217\u306B\u7F6E\u3044\u305F\u90E8\u54C1\u3092\u63C3\u3048\u308B(target, \u7F6E\u3044\u305F) {
7177
+ if (\u7F6E\u3044\u305F.length === 0) return;
7178
+ const \u914D\u7F6E\u3059\u308B = () => {
7179
+ try {
7180
+ return layout(target);
7181
+ } catch {
7182
+ return void 0;
7183
+ }
7184
+ };
7185
+ let laid = \u914D\u7F6E\u3059\u308B();
7186
+ if (!laid) return;
7187
+ const \u7BC4\u56F2 = (d, \u8981\u7D20) => {
7188
+ const \u7BB1 = d.nodes.filter((n) => \u8981\u7D20.has(n.id));
7189
+ if (\u7BB1.length === 0) return void 0;
7190
+ return {
7191
+ x0: Math.min(...\u7BB1.map((n) => n.cx - n.w / 2)),
7192
+ x1: Math.max(...\u7BB1.map((n) => n.cx + n.w / 2)),
7193
+ y0: Math.min(...\u7BB1.map((n) => n.cy - n.h / 2)),
7194
+ y1: Math.max(...\u7BB1.map((n) => n.cy + n.h / 2))
7195
+ };
7196
+ };
7197
+ let \u5E83\u3052\u305F = false;
7198
+ for (const p of \u7F6E\u3044\u305F) {
7199
+ const r = \u7BC4\u56F2(laid, p.\u8981\u7D20);
7200
+ const \u7E26\u5217 = target.lanes.find((l) => l.id === p.\u7E26\u5217);
7201
+ const \u63CF\u3044\u305F\u7E26\u5217 = laid.lanes.find((l) => l.id === p.\u7E26\u5217);
7202
+ if (!r || !\u7E26\u5217 || !\u63CF\u3044\u305F\u7E26\u5217) continue;
7203
+ const \u8981\u308B\u5E45 = r.x1 - r.x0 + \u90E8\u54C1\u306E\u7E26\u5217\u306E\u4F59\u767D * 2;
7204
+ if (\u8981\u308B\u5E45 > \u63CF\u3044\u305F\u7E26\u5217.width && \u8981\u308B\u5E45 > \u7E26\u5217.width) {
7205
+ \u7E26\u5217.width = \u8981\u308B\u5E45;
7206
+ \u5E83\u3052\u305F = true;
7207
+ }
7208
+ }
7209
+ if (\u5E83\u3052\u305F) {
7210
+ laid = \u914D\u7F6E\u3059\u308B();
7211
+ if (!laid) return;
7212
+ }
7213
+ const \u90E8\u54C1\u306E\u8981\u7D20 = new Set(\u7F6E\u3044\u305F.flatMap((p) => [...p.\u8981\u7D20]));
7214
+ for (let \u56DE = 0; \u56DE < \u90E8\u54C1\u3092\u63C3\u3048\u76F4\u3059\u4E0A\u9650; \u56DE += 1) {
7215
+ const \u4ED6\u306E\u7BB1\u306E\u4E0B\u7AEF = Math.max(
7216
+ ...laid.nodes.filter((n) => !\u90E8\u54C1\u306E\u8981\u7D20.has(n.id)).map((n) => n.cy + n.h / 2),
7217
+ ...laid.lanes.filter((l) => !l.contain).map((l) => l.y + l.height)
7218
+ );
7219
+ const \u6B21\u306E\u4E0A\u7AEF = /* @__PURE__ */ new Map();
7220
+ let \u52D5\u304B\u3057\u305F = false;
7221
+ for (const p of \u7F6E\u3044\u305F) {
7222
+ const r = \u7BC4\u56F2(laid, p.\u8981\u7D20);
7223
+ const \u7E26\u5217 = laid.lanes.find((l) => l.id === p.\u7E26\u5217);
7224
+ if (!r || !\u7E26\u5217) continue;
7225
+ const \u4E0A\u7AEF = \u6B21\u306E\u4E0A\u7AEF.get(p.\u7E26\u5217) ?? \u4ED6\u306E\u7BB1\u306E\u4E0B\u7AEF + PARTS_GAP;
7226
+ const dx = \u7E26\u5217.x + \u7E26\u5217.width / 2 - (r.x0 + r.x1) / 2;
7227
+ const dy = \u4E0A\u7AEF - r.y0;
7228
+ \u6B21\u306E\u4E0A\u7AEF.set(p.\u7E26\u5217, \u4E0A\u7AEF + (r.y1 - r.y0) + PARTS_GAP);
7229
+ if (Math.abs(dx) <= PLACEMENT_TOLERANCE && Math.abs(dy) <= PLACEMENT_TOLERANCE) continue;
7230
+ for (const n of target.nodes) {
7231
+ if (!p.\u8981\u7D20.has(n.id) || n.posX === void 0 || n.posY === void 0) continue;
7232
+ n.posX += dx;
7233
+ n.posY += dy;
7234
+ }
7235
+ \u52D5\u304B\u3057\u305F = true;
7236
+ }
7237
+ if (!\u52D5\u304B\u3057\u305F) return;
7238
+ laid = \u914D\u7F6E\u3059\u308B();
7239
+ if (!laid) return;
7240
+ }
7241
+ }
7242
+ var \u90E8\u54C1\u3092\u63C3\u3048\u76F4\u3059\u4E0A\u9650 = 3;
6435
7243
  function resolveStateOverride(original, override) {
6436
7244
  if (override === void 0) return { initial: original, rejected: false };
6437
7245
  if (isColorValue(original) && !isColorValue(override))
@@ -6448,6 +7256,19 @@ function applyColorHex(part, colorHex, stateOverride) {
6448
7256
  }
6449
7257
  return out;
6450
7258
  }
7259
+ function \u90E8\u54C1\u306B\u4E0A\u66F8\u304D\u3092\u5F53\u3066\u308B(part, actor) {
7260
+ const \u4E0A\u66F8\u304D = applyColorHex(part, actor.colorHex, actor.stateOverride ?? {});
7261
+ const \u6BB5\u3092\u5916\u3059 = \u4E0A\u66F8\u304D["phase"] === false;
7262
+ if (Object.keys(\u4E0A\u66F8\u304D).length === 0) return part;
7263
+ return {
7264
+ ...part,
7265
+ states: part.states.map((st) => ({
7266
+ ...st,
7267
+ initial: resolveStateOverride(st.initial, \u4E0A\u66F8\u304D[st.id]).initial
7268
+ })),
7269
+ phases: \u6BB5\u3092\u5916\u3059 ? part.phases.map((ph) => ({ ...ph, activate: [], tweens: [], sets: [] })) : part.phases
7270
+ };
7271
+ }
6451
7272
  function \u5024\u306E\u524D\u7F6E\u304D\u3092\u4F5C\u308B(\u540D\u524D\u305F\u3061) {
6452
7273
  const \u51FA\u529B = /* @__PURE__ */ new Map();
6453
7274
  const \u4F7F\u7528\u4E2D = /* @__PURE__ */ new Set();
@@ -6491,25 +7312,15 @@ function mergePartIntoDiagram(target, part, alias, stateOverride, laneMapping, o
6491
7312
  };
6492
7313
  const targetLaneId = laneMapping;
6493
7314
  const laneIdMap = /* @__PURE__ */ new Map();
7315
+ const \u4F5C\u3063\u305F\u7E26\u5217 = [];
6494
7316
  const PARTS_LANE_GAP = 300;
6495
7317
  const existingLaneMaxX = target.lanes.length > 0 ? Math.max(...target.lanes.map((l) => (l.x ?? 0) + l.width)) : 0;
6496
- const partLaneGeom = /* @__PURE__ */ new Map();
6497
- for (const l of part.lanes) {
6498
- partLaneGeom.set(l.id, {
6499
- x: typeof l.x === "number" && Number.isFinite(l.x) ? l.x : 0,
6500
- w: positiveOr(l.width, 400)
6501
- });
6502
- }
6503
- const laneXs = [...partLaneGeom.values()].map((g) => g.x);
6504
- const laneRights = [...partLaneGeom.values()].map((g) => g.x + g.w);
6505
- const partMinLaneX = minOf(laneXs, 0);
6506
- const partMaxLaneRight = maxOf(laneRights, 400);
6507
- const rawBboxW = partMaxLaneRight - partMinLaneX;
6508
- const partsBboxW = rawBboxW > 0 ? rawBboxW : 1;
6509
- const rawLaneScaleX = targetW !== void 0 && targetW > 0 ? targetW / partsBboxW : 1;
7318
+ const \u7F6E\u304D\u65B9 = \u90E8\u54C1\u306E\u7F6E\u304D\u65B9\u3092\u8AAD\u3080(part);
7319
+ const \u4F38\u7E2E\u306E\u57FA\u6E96 = partScaleBase(part);
7320
+ const rawLaneScaleX = targetW !== void 0 && targetW > 0 ? targetW / \u4F38\u7E2E\u306E\u57FA\u6E96.w : 1;
6510
7321
  const laneScaleX = Number.isFinite(rawLaneScaleX) && rawLaneScaleX > 0 ? rawLaneScaleX : 1;
6511
- const partOrigBboxCenterX = partMinLaneX + partsBboxW / 2;
6512
- const dropCenterX = offsetX !== void 0 ? offsetX : existingLaneMaxX + PARTS_LANE_GAP + partsBboxW * laneScaleX / 2;
7322
+ const partOrigBboxCenterX = \u7F6E\u304D\u65B9.\u5DE6\u7AEF + \u7F6E\u304D\u65B9.\u5E45 / 2;
7323
+ const dropCenterX = offsetX !== void 0 ? offsetX : existingLaneMaxX + PARTS_LANE_GAP + \u7F6E\u304D\u65B9.\u5E45 * laneScaleX / 2;
6513
7324
  const mapLaneX = (x) => (x - partOrigBboxCenterX) * laneScaleX + dropCenterX;
6514
7325
  for (const laneOrig of part.lanes) {
6515
7326
  if (targetLaneId) {
@@ -6517,7 +7328,7 @@ function mergePartIntoDiagram(target, part, alias, stateOverride, laneMapping, o
6517
7328
  } else {
6518
7329
  const newLaneId = prefix(laneOrig.id);
6519
7330
  laneIdMap.set(laneOrig.id, newLaneId);
6520
- const geom = partLaneGeom.get(laneOrig.id) ?? { x: 0, w: 400 };
7331
+ const geom = \u7F6E\u304D\u65B9.\u7E26\u5217.get(laneOrig.id) ?? { x: 0, w: 400 };
6521
7332
  target.lanes.push({
6522
7333
  ...laneOrig,
6523
7334
  id: newLaneId,
@@ -6525,24 +7336,18 @@ function mergePartIntoDiagram(target, part, alias, stateOverride, laneMapping, o
6525
7336
  x: mapLaneX(geom.x),
6526
7337
  width: geom.w * laneScaleX
6527
7338
  });
7339
+ \u4F5C\u3063\u305F\u7E26\u5217.push({ id: newLaneId, \u90E8\u54C1\u306E\u540D\u672D: laneOrig.label });
6528
7340
  }
6529
7341
  }
6530
7342
  const STACK_ISOLATION_OFFSET = 1e3;
6531
7343
  const shouldForcePos = offsetX !== void 0 || offsetY !== void 0;
6532
7344
  const targetMaxStack = shouldForcePos && target.nodes.length > 0 ? Math.max(...target.nodes.map((n) => n.stack ?? 0)) : 0;
6533
7345
  const stackShiftBase = shouldForcePos ? targetMaxStack + STACK_ISOLATION_OFFSET : 0;
6534
- const STACK_PITCH_APPROX = 220;
6535
- const partStacks = part.nodes.map(
6536
- (n) => typeof n.stack === "number" && Number.isFinite(n.stack) ? n.stack : 0
6537
- );
6538
- const minStack = partStacks.length > 0 ? Math.min(...partStacks) : 0;
6539
- const maxStack = partStacks.length > 0 ? Math.max(...partStacks) : 0;
6540
- const partCenterStack = (minStack + maxStack) / 2;
6541
- const partOrigH = Math.max(1, (maxStack - minStack + 1) * STACK_PITCH_APPROX);
6542
7346
  const scaleX = laneScaleX;
6543
- const rawScaleY = targetH !== void 0 && targetH > 0 ? targetH / partOrigH : 1;
7347
+ const rawScaleY = targetH !== void 0 && targetH > 0 ? targetH / \u4F38\u7E2E\u306E\u57FA\u6E96.h : 1;
6544
7348
  const scaleY = Number.isFinite(rawScaleY) && rawScaleY > 0 ? rawScaleY : 1;
6545
- for (const nodeOrig of part.nodes) {
7349
+ const \u6BB5\u3092\u632F\u308A\u76F4\u3059 = targetLaneId !== void 0 && shouldForcePos && part.lanes.length > 1;
7350
+ for (const [nodeIndex, nodeOrig] of part.nodes.entries()) {
6546
7351
  const mappedLane = laneIdMap.get(nodeOrig.lane) ?? nodeOrig.lane;
6547
7352
  let newShape = nodeOrig.shape ? deepRewriteStrings(nodeOrig.shape, rewriteTemplate) : void 0;
6548
7353
  if (newShape && (scaleX !== 1 || scaleY !== 1)) {
@@ -6565,16 +7370,10 @@ function mergePartIntoDiagram(target, part, alias, stateOverride, laneMapping, o
6565
7370
  };
6566
7371
  newShape = scaleGeom(newShape);
6567
7372
  }
6568
- let nodePosX = nodeOrig.posX !== void 0 ? mapLaneX(nodeOrig.posX) : void 0;
6569
- let nodePosY = nodeOrig.posY !== void 0 ? nodeOrig.posY + (offsetY ?? 0) : void 0;
6570
- if (shouldForcePos && nodePosX === void 0) {
6571
- const geom = partLaneGeom.get(nodeOrig.lane) ?? { x: 0, w: 320 };
6572
- nodePosX = mapLaneX(geom.x + geom.w / 2);
6573
- }
6574
- if (shouldForcePos && nodePosY === void 0) {
6575
- const stack = nodeOrig.stack ?? 0;
6576
- nodePosY = (stack - partCenterStack) * STACK_PITCH_APPROX * scaleY + (offsetY ?? 0);
6577
- }
7373
+ const \u9801 = \u7F6E\u304D\u65B9.\u8981\u7D20[nodeIndex] ?? { x: partOrigBboxCenterX, y: 0 };
7374
+ const \u305A\u308C = \u90E8\u54C1\u306E\u8981\u7D20\u306E\u305A\u308C(nodeOrig, \u9801, \u7F6E\u304D\u65B9, scaleX, scaleY);
7375
+ const nodePosX = shouldForcePos || nodeOrig.posX !== void 0 ? dropCenterX + \u305A\u308C.dx : void 0;
7376
+ const nodePosY = shouldForcePos ? (offsetY ?? 0) + \u305A\u308C.dy : void 0;
6578
7377
  const rawNodeW = nodeOrig.w !== void 0 ? positiveOr(nodeOrig.w, 200) : void 0;
6579
7378
  const rawNodeH = nodeOrig.h !== void 0 ? positiveOr(nodeOrig.h, 200) : void 0;
6580
7379
  const nodeW = rawNodeW !== void 0 && (scaleX !== 1 || scaleY !== 1) ? rawNodeW * scaleX : rawNodeW;
@@ -6587,7 +7386,7 @@ function mergePartIntoDiagram(target, part, alias, stateOverride, laneMapping, o
6587
7386
  subtitle: rewriteTemplate(nodeOrig.subtitle),
6588
7387
  value: rewriteTemplate(nodeOrig.value),
6589
7388
  // parts stack を target 側と分離 (D2 fix、 posX/posY 明示との 2 段防御)
6590
- stack: (nodeOrig.stack ?? 0) + stackShiftBase,
7389
+ stack: (\u6BB5\u3092\u632F\u308A\u76F4\u3059 ? nodeIndex : nodeOrig.stack ?? 0) + stackShiftBase,
6591
7390
  ...newShape ? { shape: newShape } : {},
6592
7391
  ...nodePosX !== void 0 ? { posX: nodePosX } : {},
6593
7392
  ...nodePosY !== void 0 ? { posY: nodePosY } : {},
@@ -6643,7 +7442,7 @@ function mergePartIntoDiagram(target, part, alias, stateOverride, laneMapping, o
6643
7442
  }
6644
7443
  const phaseOptOut = stateOverride["phase"] === false;
6645
7444
  if (phaseOptOut) {
6646
- return;
7445
+ return \u4F5C\u3063\u305F\u7E26\u5217;
6647
7446
  }
6648
7447
  if (target.phases.length === 0) {
6649
7448
  for (const phaseOrig of part.phases) {
@@ -6684,6 +7483,7 @@ function mergePartIntoDiagram(target, part, alias, stateOverride, laneMapping, o
6684
7483
  });
6685
7484
  }
6686
7485
  }
7486
+ return \u4F5C\u3063\u305F\u7E26\u5217;
6687
7487
  }
6688
7488
  function deepRewriteStrings(value, rewrite, seen = /* @__PURE__ */ new WeakSet()) {
6689
7489
  if (typeof value === "string") return rewrite(value) ?? value;
@@ -6699,12 +7499,14 @@ function deepRewriteStrings(value, rewrite, seen = /* @__PURE__ */ new WeakSet()
6699
7499
  }
6700
7500
  return out;
6701
7501
  }
6702
- function applyEdgeInlineOptions(diagram2, doc, sourceLines) {
7502
+ function applyEdgeInlineOptions(diagram2, doc, sourceLines, edgeSteps, partsCatalog) {
6703
7503
  if (\u9396\u3067\u3064\u306A\u3050\u5F62\u304B(doc)) {
7504
+ const \u4E26\u3073 = \u9396\u306B\u4E26\u3079\u308B\u767B\u5834\u4EBA\u7269(doc, partsCatalog);
6704
7505
  diagram2.edges.forEach((e, idx) => {
6705
- const s = \u9396\u306E\u3069\u306E\u884C\u304B\u3089\u6765\u305F\u304B(doc, idx);
7506
+ const s = \u9396\u306E\u3069\u306E\u884C\u304B\u3089\u6765\u305F\u304B(doc, \u4E26\u3073, idx);
6706
7507
  if (s === void 0) return;
6707
7508
  sourceLines?.set(e.id, s.pos.line);
7509
+ edgeSteps?.set(e.id, s);
6708
7510
  \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(e, s, doc);
6709
7511
  });
6710
7512
  return;
@@ -6720,6 +7522,7 @@ function applyEdgeInlineOptions(diagram2, doc, sourceLines) {
6720
7522
  if (!target) return;
6721
7523
  used.add(target.id);
6722
7524
  sourceLines?.set(target.id, s.pos.line);
7525
+ edgeSteps?.set(target.id, s);
6723
7526
  \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc);
6724
7527
  });
6725
7528
  }
@@ -6753,7 +7556,7 @@ function \u51FA\u6765\u4E8B\u306E\u76F8\u624B\u3092\u89E3\u304F(diagram2, doc, e
6753
7556
  return \u5217 ? { kind: "lane", id: \u5217.id } : void 0;
6754
7557
  }
6755
7558
  function \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc) {
6756
- if (s.sub !== void 0) target.sub = s.sub;
7559
+ if (s.sub !== void 0 && doc.type !== "class") target.sub = s.sub;
6757
7560
  if (s.guard !== void 0) {
6758
7561
  target.guard = s.guard;
6759
7562
  if (doc.type === "state" && target.sub === void 0) target.sub = s.guard;
@@ -6773,6 +7576,10 @@ function \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc) {
6773
7576
  if (s.labelPlate !== void 0) target.labelPlate = s.labelPlate;
6774
7577
  if (s.labelOffsetX !== void 0) target.labelOffsetX = s.labelOffsetX;
6775
7578
  if (s.labelOffsetY !== void 0) target.labelOffsetY = s.labelOffsetY;
7579
+ if (s.layoutPos !== void 0) {
7580
+ target.labelOffsetX = (s.labelOffsetX ?? 0) + s.layoutPos.x;
7581
+ target.labelOffsetY = (s.labelOffsetY ?? 0) + s.layoutPos.y;
7582
+ }
6776
7583
  if (s.overlay !== void 0) target.overlay = s.overlay;
6777
7584
  if (s.widthBind !== void 0) target.widthBind = s.widthBind;
6778
7585
  if (s.strokeBind !== void 0) target.strokeBind = s.strokeBind;
@@ -6781,10 +7588,18 @@ function \u77E2\u5370\u3078\u66F8\u304D\u5199\u3059(target, s, doc) {
6781
7588
  function \u9396\u3067\u3064\u306A\u3050\u5F62\u304B(doc) {
6782
7589
  if (doc.type !== "flow") return false;
6783
7590
  if (doc.animate && doc.animate.phases.length > 0) return false;
7591
+ if (doc.direction !== void 0) return false;
6784
7592
  return !\u66F8\u3044\u305F\u7E26\u5217\u306B\u7F6E\u304F("flow", doc);
6785
7593
  }
6786
- function \u9396\u306E\u3069\u306E\u884C\u304B\u3089\u6765\u305F\u304B(doc, edgeIndex) {
6787
- const to = doc.actors[edgeIndex + 1];
7594
+ function \u9396\u306B\u4E26\u3079\u308B\u767B\u5834\u4EBA\u7269(doc, partsCatalog) {
7595
+ if (!partsCatalog) return doc.actors;
7596
+ const \u884C\u306B\u66F8\u304B\u308C\u305F = new Set(doc.flow.flatMap((s) => [s.from, s.to]));
7597
+ return doc.actors.filter(
7598
+ (a) => \u884C\u306B\u66F8\u304B\u308C\u305F.has(a.name) || lookupPartRaw(partsCatalog, a.partId) === void 0
7599
+ );
7600
+ }
7601
+ function \u9396\u306E\u3069\u306E\u884C\u304B\u3089\u6765\u305F\u304B(doc, \u4E26\u3073, edgeIndex) {
7602
+ const to = \u4E26\u3073[edgeIndex + 1];
6788
7603
  if (to === void 0) return void 0;
6789
7604
  return doc.flow.find((s) => s.to === to.name);
6790
7605
  }
@@ -7115,13 +7930,22 @@ var SINGLE_BOX_KINDS = /* @__PURE__ */ new Set([
7115
7930
  "tree-hierarchy",
7116
7931
  "journey-map",
7117
7932
  // 2 時点を直線でつなぐ図も 1 箱で全体を描く (#1647)
7118
- "chart-slope"
7933
+ "chart-slope",
7934
+ // 弧と帯で量を表す 3 種も 1 箱で全体を描く (#1668)
7935
+ "chart-gauge",
7936
+ "chart-radial",
7937
+ "chart-stacked-bar",
7938
+ // 値 1 つを大きく示す図と、1 個 = 1% の印を埋める図も同じ (#1668)。
7939
+ // 段の `draw:` は受けない (描画側が起点から描く動きを持たない) が、性質は同じなので載せる
7940
+ "chart-stat",
7941
+ "chart-waffle"
7119
7942
  ]);
7120
7943
  function applyGroupContainers(diagram2, doc) {
7121
- if (!doc.groups || Object.keys(doc.groups).length === 0) return;
7944
+ const \u4F5C\u3063\u305F = /* @__PURE__ */ new Set();
7945
+ if (!doc.groups || Object.keys(doc.groups).length === 0) return \u4F5C\u3063\u305F;
7122
7946
  for (const [id, g] of Object.entries(doc.groups)) {
7123
7947
  const containerId = `group-${id}`;
7124
- if (diagram2.lanes.some((l) => l.id === containerId)) continue;
7948
+ if (diagram2.lanes.some((l) => l.id === containerId) || doc.lanes?.[containerId]) continue;
7125
7949
  diagram2.lanes.push({
7126
7950
  id: containerId,
7127
7951
  width: 800,
@@ -7129,8 +7953,84 @@ function applyGroupContainers(diagram2, doc) {
7129
7953
  contain: true,
7130
7954
  // 束ねる lane 群に重ねて描く枠。 横に並べる lane ではないので、 engine の間隔調整
7131
7955
  // (lane を詰めた分を幅で埋め合わせる処理) の対象から外す。
7132
- role: "overlay"
7956
+ role: "overlay",
7957
+ // 置き直すまでは座標を固定しておく。 固定しない枠は縦列の並びに加わり、 他の縦列の間隔を
7958
+ // 広げる (実測 = 3 本の縦列の 2 本目が 666 から 710 へ動いた)。 並びから外した配置で測らないと、
7959
+ // 枠を置いた後に縦列が詰め直されて枠から外れる
7960
+ posX: 0,
7961
+ posY: 0,
7962
+ posW: 1,
7963
+ posH: 1
7133
7964
  });
7965
+ \u4F5C\u3063\u305F.add(containerId);
7966
+ }
7967
+ return \u4F5C\u3063\u305F;
7968
+ }
7969
+ var \u7D44\u306E\u67A0\u306E\u4F59\u767D = { \u4E0A: 40, \u4E0B: 20, \u56F2\u3044\u306E\u6A2A: 20, \u56F2\u3044\u306E\u7121\u3044\u6A2A: 0 };
7970
+ function applyGroupFrames(diagram2, doc, \u4F5C\u3063\u305F\u67A0, onNotice) {
7971
+ if (\u4F5C\u3063\u305F\u67A0.size === 0) return;
7972
+ const \u7F6E\u304F = [];
7973
+ for (const [id, g] of Object.entries(doc.groups ?? {})) {
7974
+ const \u67A0 = diagram2.lanes.find((l) => l.id === `group-${id}`);
7975
+ if (!\u67A0 || !\u4F5C\u3063\u305F\u67A0.has(\u67A0.id)) continue;
7976
+ const \u66F8\u3044\u305F = Array.isArray(g.lanes) ? g.lanes : [];
7977
+ const \u5728\u308B = \u66F8\u3044\u305F.filter((x) => diagram2.lanes.some((l) => l.id === x && !\u4F5C\u3063\u305F\u67A0.has(l.id)));
7978
+ const \u7121\u3044 = \u66F8\u3044\u305F.filter((x) => !\u5728\u308B.includes(x));
7979
+ if (\u5728\u308B.length === 0) {
7980
+ diagram2.lanes = diagram2.lanes.filter((l) => l !== \u67A0);
7981
+ onNotice?.({
7982
+ kind: "group-lane-missing",
7983
+ actor: id,
7984
+ line: g.pos?.line ?? 0,
7985
+ message: \u66F8\u3044\u305F.length === 0 ? `\u7D44 "${truncateForMessage(id)}" \u306F\u675F\u306D\u308B\u7E26\u5217\u3092\u66F8\u3044\u3066\u3044\u306A\u3044\u306E\u3067\u3001\u67A0\u3092\u63CF\u304D\u307E\u305B\u3093` : `\u7D44 "${truncateForMessage(id)}" \u304C\u675F\u306D\u308B\u7E26\u5217 ${\u7121\u3044.map((x) => `"${truncateForMessage(x)}"`).join(", ")} \u304C\u56F3\u306B\u7121\u3044\u306E\u3067\u3001\u67A0\u3092\u63CF\u304D\u307E\u305B\u3093`,
7986
+ hint: "`lanes: [\u7E26\u5217\u306E\u540D\u524D, ...]` \u306B `lanes:` \u3067\u66F8\u3044\u305F\u7E26\u5217\u306E\u540D\u524D\u3092\u4E26\u3079\u308B"
7987
+ });
7988
+ continue;
7989
+ }
7990
+ if (\u7121\u3044.length > 0) {
7991
+ onNotice?.({
7992
+ kind: "group-lane-missing",
7993
+ actor: id,
7994
+ line: g.pos?.line ?? 0,
7995
+ message: `\u7D44 "${truncateForMessage(id)}" \u304C\u675F\u306D\u308B\u7E26\u5217 ${\u7121\u3044.map((x) => `"${truncateForMessage(x)}"`).join(", ")} \u304C\u56F3\u306B\u7121\u3044\u306E\u3067\u3001\u6B8B\u308A\u306E\u7E26\u5217\u3060\u3051\u3092\u56F2\u307F\u307E\u3059`,
7996
+ hint: "`lanes:` \u3067\u66F8\u3044\u305F\u7E26\u5217\u306E\u540D\u524D\u304B\u78BA\u304B\u3081\u308B"
7997
+ });
7998
+ }
7999
+ \u7F6E\u304F.push({ \u67A0, \u540D\u524D: id, line: g.pos?.line ?? 0, \u7E26\u5217: \u5728\u308B });
8000
+ }
8001
+ if (\u7F6E\u304F.length === 0) return;
8002
+ const \u914D\u7F6E = layout(diagram2);
8003
+ const \u4E26\u3073\u306E\u7E26\u5217 = \u914D\u7F6E.lanes.filter((l) => !\u4F5C\u3063\u305F\u67A0.has(l.id));
8004
+ for (const { \u67A0, \u540D\u524D, line, \u7E26\u5217 } of \u7F6E\u304F) {
8005
+ const \u675F = \u4E26\u3073\u306E\u7E26\u5217.filter((l) => \u7E26\u5217.includes(l.id));
8006
+ const \u5DE6 = Math.min(...\u675F.map((l) => l.x ?? 0));
8007
+ const \u53F3 = Math.max(...\u675F.map((l) => (l.x ?? 0) + l.width));
8008
+ const \u631F\u3093\u3060 = \u4E26\u3073\u306E\u7E26\u5217.filter(
8009
+ (l) => !\u7E26\u5217.includes(l.id) && (l.x ?? 0) < \u53F3 && (l.x ?? 0) + l.width > \u5DE6
8010
+ );
8011
+ if (\u631F\u3093\u3060.length > 0) {
8012
+ onNotice?.({
8013
+ kind: "group-lanes-apart",
8014
+ actor: \u540D\u524D,
8015
+ line,
8016
+ message: `\u7D44 "${truncateForMessage(\u540D\u524D)}" \u304C\u675F\u306D\u308B\u7E26\u5217\u306E\u9593\u306B ${\u631F\u3093\u3060.map((l) => `"${truncateForMessage(l.id)}"`).join(", ")} \u304C\u3042\u308B\u306E\u3067\u3001\u305D\u306E\u7E26\u5217\u3082\u67A0\u306B\u5165\u308A\u307E\u3059`,
8017
+ hint: "\u675F\u306D\u308B\u7E26\u5217\u3092 `lanes:` \u3067\u96A3\u308A\u5408\u3046\u9806\u306B\u4E26\u3079\u308B"
8018
+ });
8019
+ }
8020
+ const \u56F2\u3080\u7E26\u5217 = new Set([...\u675F, ...\u631F\u3093\u3060].map((l) => l.id));
8021
+ const \u56F2\u3080 = [...\u675F, ...\u631F\u3093\u3060];
8022
+ const \u7BB1 = \u914D\u7F6E.nodes.filter((n) => \u56F2\u3080\u7E26\u5217.has(n.lane));
8023
+ const \u4E0A = Math.min(...\u56F2\u3080.map((l) => l.y ?? 0));
8024
+ const \u4E0B = Math.max(
8025
+ ...\u56F2\u3080.map((l) => (l.y ?? 0) + (l.height ?? 0)),
8026
+ ...\u7BB1.map((n) => n.cy + n.h / 2)
8027
+ );
8028
+ const \u56F2\u3044\u3092\u6301\u3064 = diagram2.lanes.some((l) => \u56F2\u3080\u7E26\u5217.has(l.id) && l.contain === true);
8029
+ const \u6A2A = \u56F2\u3044\u3092\u6301\u3064 ? \u7D44\u306E\u67A0\u306E\u4F59\u767D.\u56F2\u3044\u306E\u6A2A : \u7D44\u306E\u67A0\u306E\u4F59\u767D.\u56F2\u3044\u306E\u7121\u3044\u6A2A;
8030
+ \u67A0.posX = \u5DE6 - \u6A2A;
8031
+ \u67A0.posY = \u4E0A - \u7D44\u306E\u67A0\u306E\u4F59\u767D.\u4E0A;
8032
+ \u67A0.posW = \u53F3 - \u5DE6 + \u6A2A * 2;
8033
+ \u67A0.posH = \u4E0B - \u4E0A + \u7D44\u306E\u67A0\u306E\u4F59\u767D.\u4E0A + \u7D44\u306E\u67A0\u306E\u4F59\u767D.\u4E0B;
7134
8034
  }
7135
8035
  }
7136
8036
  function compileSolidity(doc) {
@@ -7315,6 +8215,8 @@ function compileClass(doc) {
7315
8215
  type: s2.relation ?? "uses",
7316
8216
  ...s2.label ? { label: s2.label } : {},
7317
8217
  ...s2.sub ? { cardinality: s2.sub } : {},
8218
+ // 出どころ側の多重度 (#1771)。 engine が出どころの端に添える (cdl#825)
8219
+ ...s2.tailSub ? { tailCardinality: s2.tailSub } : {},
7318
8220
  ...s2.tone ? { tone: s2.tone } : {},
7319
8221
  ...s2.style ? { style: s2.style } : {},
7320
8222
  ...s2.head ? { head: s2.head } : {},
@@ -7866,7 +8768,7 @@ function compileC4(doc) {
7866
8768
  const b = diagram(slugify(doc.title), { topic: doc.title, type: "infrastructure" });
7867
8769
  const LANE_W = 400;
7868
8770
  const LANE_GAP = 80;
7869
- const \u6BB5\u306E\u540D\u524D = { 1: "System Context", 2: "Container", 3: "Component" };
8771
+ const \u6BB5\u306E\u540D\u524D = { 1: "\u5168\u4F53\u306E\u898B\u53D6\u308A\u56F3", 2: "\u52D5\u304B\u3059\u5358\u4F4D", 3: "\u90E8\u54C1" };
7870
8772
  const \u5272\u5F53 = doc.actors.map((a, idx) => {
7871
8773
  const { \u6BB5, \u8AAC\u660E } = \u6BB5\u3092\u8AAD\u307F\u53D6\u308B(a.subtitle);
7872
8774
  return { \u6BB5, \u8AAC\u660E, id: slugify(a.name), actor: a };
@@ -7966,6 +8868,7 @@ var \u653E\u5C04\u3067\u63CF\u3051\u306A\u3044\u6B04\u306E\u540D\u524D = {
7966
8868
  final: "\u59CB\u307E\u308A / \u7D42\u308F\u308A \u306E\u5370",
7967
8869
  previous: "\u524D\u306E\u6642\u70B9\u306E\u5024",
7968
8870
  colorHex: "\u8272\u756A\u53F7",
8871
+ partColorName: "\u8272\u306E\u540D\u524D",
7969
8872
  stateOverride: "\u72B6\u614B\u306E\u4E0A\u66F8\u304D",
7970
8873
  // 位置は「登場人物ごとの箱をどこに置くか」 の指定で、 箱が 1 つの図では置く先が無い
7971
8874
  posX: "\u4F4D\u7F6E (\u5EA7\u6A19)",
@@ -7975,7 +8878,6 @@ var \u653E\u5C04\u3067\u63CF\u3051\u306A\u3044\u6B04\u306E\u540D\u524D = {
7975
8878
  scale: "\u500D\u7387",
7976
8879
  scaleKeys: "\u500D\u7387",
7977
8880
  posRel: "\u4F4D\u7F6E (\u76F8\u5BFE)",
7978
- nodes: "\u4E2D\u306E\u7BB1\u3054\u3068\u306E\u6307\u5B9A",
7979
8881
  layoutPos: "\u914D\u7F6E\u306E\u305A\u3089\u3057",
7980
8882
  shape: "\u7BB1\u306E\u4E2D\u306E\u56F3\u5F62",
7981
8883
  visibleIf: "\u51FA\u3059\u6761\u4EF6",
@@ -7996,7 +8898,7 @@ function \u653E\u5C04\u306B\u51FA\u3059\u6587\u5B57(a) {
7996
8898
  return { title: \u7BB1\u306E\u984C(a), ...\u7D9A\u304D.length > 0 ? { subtitle: \u7D9A\u304D.join(" ") } : {} };
7997
8899
  }
7998
8900
  function compileMind(doc, onNotice) {
7999
- const b = diagram(slugify(doc.title), { topic: doc.title, type: "mindmap" });
8901
+ const b = diagram(slugify(doc.title), { topic: doc.title, type: "mind" });
8000
8902
  const { w: W, h: H } = \u56F3\u8868\u306E\u5927\u304D\u3055.mind;
8001
8903
  const \u4F1D\u3048\u308B = (kind, \u540D, message, line = 0) => {
8002
8904
  onNotice?.({ kind, actor: \u540D, line, message });
@@ -8367,19 +9269,20 @@ function slugLookup(byName, wanted) {
8367
9269
  }
8368
9270
  return hit;
8369
9271
  }
8370
- function compileFlow(doc) {
8371
- if (doc.animate && doc.animate.phases.length > 0 || \u66F8\u3044\u305F\u7E26\u5217\u306B\u7F6E\u304F("flow", doc) || doc.direction !== void 0) {
9272
+ function compileFlow(doc, partsCatalog) {
9273
+ if (!\u9396\u3067\u3064\u306A\u3050\u5F62\u304B(doc)) {
8372
9274
  return compileGenericWithAnimate(doc, { kind: "flow", laneId: "main", laneWidth: 400 });
8373
9275
  }
8374
- if (doc.actors.length === 0) {
9276
+ const \u4E26\u3073 = \u9396\u306B\u4E26\u3079\u308B\u767B\u5834\u4EBA\u7269(doc, partsCatalog);
9277
+ if (\u4E26\u3073.length === 0) {
8375
9278
  return diagram(slugify(doc.title), { topic: doc.title, type: "flow" }).build();
8376
9279
  }
8377
9280
  const flowBuilder = flow({
8378
9281
  id: slugify(doc.title),
8379
9282
  topic: doc.title
8380
9283
  });
8381
- for (let i = 0; i < doc.actors.length; i++) {
8382
- const a = doc.actors[i];
9284
+ for (const a of \u4E26\u3073) {
9285
+ doc.actors.indexOf(a);
8383
9286
  const incomingEdge = doc.flow.find((s) => s.to === a.name);
8384
9287
  const edgeLabel = incomingEdge?.label;
8385
9288
  flowBuilder.step(
@@ -8813,10 +9716,13 @@ function stripCardinality(label) {
8813
9716
 
8814
9717
  // src/notation-lint.ts
8815
9718
  var REDUNDANT_TOPIC_PATTERNS = [
8816
- { pattern: /\bpreset\s*\(/i, hint: "\u300C\u301C preset (\u8A73\u7D30)\u300D \u306F\u5B9F\u88C5\u8868\u73FE\u3001 \u300C\u301C \u3092\u793A\u3059\u56F3\u300D \u306E\u3088\u3046\u306B\u8AAD\u8005\u5411\u3051\u8AAC\u660E\u306B" },
8817
- { pattern: /render\s*未実装/, hint: "\u300Crender \u672A\u5B9F\u88C5\u300D \u306F\u958B\u767A\u8005\u5411\u3051\u5185\u90E8\u30E1\u30E2\u3001 catalog \u8868\u793A\u3067\u306F\u7701\u304F" },
8818
- { pattern: /SVG\s+(polyline|arc|rect|path)/i, hint: "\u300CSVG polyline / arc / rect / path\u300D \u306F\u5B9F\u88C5\u8A73\u7D30\u3001 \u300C\u301C \u3092\u793A\u3059\u56F3\u300D \u306B\u7F6E\u63DB" },
8819
- { pattern: /\bpolygon\b/i, hint: "\u300Cpolygon\u300D \u306F\u5B9F\u88C5\u7528\u8A9E\u3001 \u56F3\u306E\u610F\u5473\u3092\u8AAC\u660E\u3059\u308B\u81EA\u7136\u6587\u306B\u7F6E\u63DB" }
9719
+ { pattern: /\bpreset\s*\(/i, hint: "`preset (\u2026)` \u306F\u4F5C\u308A\u624B\u306E\u66F8\u304D\u65B9\u3067\u3001 \u8AAD\u3080\u4EBA\u306B\u306F\u4F55\u3092\u793A\u3059\u56F3\u304B\u304C\u4F1D\u308F\u3089\u306A\u3044" },
9720
+ { pattern: /render\s*未実装/, hint: "`render \u672A\u5B9F\u88C5` \u306F\u4F5C\u308A\u624B\u5411\u3051\u306E\u63A7\u3048\u3067\u3001 \u30AB\u30BF\u30ED\u30B0\u306B\u51FA\u3059\u8AAC\u660E\u306B\u306F\u8981\u3089\u306A\u3044" },
9721
+ {
9722
+ pattern: /SVG\s+(polyline|arc|rect|path)/i,
9723
+ hint: "`SVG` \u306E\u63CF\u304D\u65B9\u306E\u540D\u524D (`polyline` / `arc` / `rect` / `path`) \u306F\u5B9F\u88C5\u306E\u8A73\u7D30\u3067\u3001 \u4F55\u3092\u793A\u3059\u56F3\u304B\u304C\u4F1D\u308F\u3089\u306A\u3044"
9724
+ },
9725
+ { pattern: /\bpolygon\b/i, hint: "`polygon` \u306F\u5B9F\u88C5\u306E\u8A00\u8449\u3067\u3001 \u4F55\u3092\u793A\u3059\u56F3\u304B\u304C\u4F1D\u308F\u3089\u306A\u3044" }
8820
9726
  ];
8821
9727
  function lintDiagram(d) {
8822
9728
  const issues = [];
@@ -8842,27 +9748,27 @@ function autoFix(d) {
8842
9748
  return patched;
8843
9749
  }
8844
9750
  var KIND_TO_JA = {
8845
- chart: "\u7D71\u8A08\u30C1\u30E3\u30FC\u30C8",
8846
- "line chart": "\u6298\u308C\u7DDA\u30B0\u30E9\u30D5",
8847
- "pie chart": "\u5186\u30B0\u30E9\u30D5",
8848
- "bar chart": "\u68D2\u30B0\u30E9\u30D5",
8849
- flow: "\u51E6\u7406\u306E\u6D41\u308C",
8850
- swimlane: "\u30B9\u30A4\u30E0\u30EC\u30FC\u30F3 (\u5F79\u5272\u5225\u30EC\u30FC\u30F3)",
8851
- sequence: "\u6642\u7CFB\u5217\u306E\u3084\u308A\u53D6\u308A",
8852
- topology: "\u30B7\u30B9\u30C6\u30E0\u69CB\u6210",
8853
- er: "\u30C6\u30FC\u30D6\u30EB\u95A2\u4FC2 (ER \u56F3)",
8854
- stateMachine: "\u72B6\u614B\u9077\u79FB (\u30B9\u30C6\u30FC\u30C8\u56F3)",
8855
- stateMachine2: "\u62E1\u5F35\u30B9\u30C6\u30FC\u30C8\u56F3 (\u968E\u5C64\u72B6\u614B)",
8856
- infrastructure: "\u30AF\u30E9\u30A6\u30C9\u69CB\u6210",
8857
- classDiagram: "UML \u30AF\u30E9\u30B9\u56F3",
8858
- tree: "\u968E\u5C64\u30C4\u30EA\u30FC",
8859
- userJourney: "\u30E6\u30FC\u30B6\u30FC\u30B8\u30E3\u30FC\u30CB\u30FC",
8860
- mindMap: "\u30DE\u30A4\u30F3\u30C9\u30DE\u30C3\u30D7",
8861
- funnel: "\u30D5\u30A1\u30CD\u30EB (\u6BB5\u968E\u5225\u96E2\u8131)",
8862
- quadrant: "\u56DB\u8C61\u9650\u30DE\u30C8\u30EA\u30AF\u30B9",
8863
- gantt: "\u30AC\u30F3\u30C8\u30C1\u30E3\u30FC\u30C8",
8864
- flowchart: "\u5206\u5C90\u30D5\u30ED\u30FC\u30C1\u30E3\u30FC\u30C8",
8865
- network: "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u69CB\u6210"
9751
+ chart: { shows: "\u9805\u76EE\u3054\u3068\u306E\u6570\u5024", name: "\u30B0\u30E9\u30D5" },
9752
+ "line chart": { shows: "\u5024\u306E\u79FB\u308A\u5909\u308F\u308A", name: "\u6298\u308C\u7DDA\u30B0\u30E9\u30D5" },
9753
+ "pie chart": { shows: "\u5168\u4F53\u306B\u5BFE\u3059\u308B\u5185\u8A33\u306E\u5272\u5408", name: "\u5186\u30B0\u30E9\u30D5" },
9754
+ "bar chart": { shows: "\u9805\u76EE\u3054\u3068\u306E\u5024\u306E\u5927\u304D\u3055", name: "\u68D2\u30B0\u30E9\u30D5" },
9755
+ flow: { shows: "\u51E6\u7406\u306E\u9806\u756A", name: "\u30D5\u30ED\u30FC" },
9756
+ swimlane: { shows: "\u5F79\u5272\u3054\u3068\u306E\u7E26\u5217\u306B\u5206\u3051\u305F\u51E6\u7406\u306E\u6D41\u308C", name: "\u30B9\u30A4\u30E0\u30EC\u30FC\u30F3" },
9757
+ sequence: { shows: "\u8981\u7D20\u3069\u3046\u3057\u306E\u3084\u308A\u53D6\u308A\u306E\u9806\u756A", name: "\u30B7\u30FC\u30B1\u30F3\u30B9\u56F3" },
9758
+ topology: { shows: "\u30B7\u30B9\u30C6\u30E0\u306E\u69CB\u6210\u8981\u7D20\u3068\u63A5\u7D9A", name: "\u30C8\u30DD\u30ED\u30B8\u30FC\u56F3" },
9759
+ er: { shows: "\u8868\u3069\u3046\u3057\u306E\u95A2\u4FC2", name: "ER\u56F3" },
9760
+ stateMachine: { shows: "\u72B6\u614B\u3068\u9077\u79FB\u306E\u6761\u4EF6", name: "\u72B6\u614B\u9077\u79FB\u56F3" },
9761
+ stateMachine2: { shows: "\u89AA\u306E\u72B6\u614B\u306E\u4E2D\u306B\u7F6E\u3044\u305F\u5B50\u306E\u72B6\u614B\u3068\u9077\u79FB\u306E\u6761\u4EF6", name: "\u5165\u308C\u5B50\u306E\u72B6\u614B\u9077\u79FB\u56F3" },
9762
+ infrastructure: { shows: "\u30AF\u30E9\u30A6\u30C9\u3068\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u306E\u69CB\u6210", name: "\u968E\u5C64\u69CB\u6210\u56F3" },
9763
+ classDiagram: { shows: "\u30AF\u30E9\u30B9\u3069\u3046\u3057\u306E\u95A2\u4FC2", name: "\u30AF\u30E9\u30B9\u56F3" },
9764
+ tree: { shows: "\u7D44\u7E54\u3084\u5206\u985E\u306E\u89AA\u5B50\u306E\u95A2\u4FC2", name: "\u968E\u5C64\u56F3" },
9765
+ userJourney: { shows: "\u5229\u7528\u8005\u306E\u6C17\u6301\u3061\u306E\u79FB\u308A\u5909\u308F\u308A", name: "\u4F53\u9A13\u306E\u9053\u7B4B" },
9766
+ mindMap: { shows: "\u4E2D\u5FC3\u306E\u4E3B\u984C\u304B\u3089\u5E83\u304C\u308B\u767A\u60F3", name: "\u679D\u5206\u304B\u308C\u56F3" },
9767
+ funnel: { shows: "\u6BB5\u968E\u3054\u3068\u306B\u6B8B\u308B\u6570\u3068\u96E2\u308C\u308B\u6570", name: "\u7D5E\u308A\u8FBC\u307F\u56F3" },
9768
+ quadrant: { shows: "2 \u3064\u306E\u8EF8\u3067\u5206\u3051\u305F\u9805\u76EE\u306E\u4F4D\u7F6E", name: "\u56DB\u8C61\u9650\u56F3" },
9769
+ gantt: { shows: "\u4F5C\u696D\u306E\u671F\u9593\u3068\u524D\u5F8C\u306E\u95A2\u4FC2", name: "\u5DE5\u7A0B\u8868" },
9770
+ flowchart: { shows: "\u5206\u5C90\u3084\u5224\u5B9A\u3092\u542B\u3080\u51E6\u7406\u306E\u9806\u756A", name: "\u6D41\u308C\u56F3" },
9771
+ network: { shows: "\u6A5F\u5668\u3068\u533A\u753B\u306E\u3064\u306A\u304C\u308A", name: "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u56F3" }
8866
9772
  };
8867
9773
  function applyTopicAutoFix(topic) {
8868
9774
  const kindMatch = topic.match(
@@ -8872,7 +9778,8 @@ function applyTopicAutoFix(topic) {
8872
9778
  const kind = kindMatch[1].toLowerCase();
8873
9779
  const canonical = Object.keys(KIND_TO_JA).find((k) => k.toLowerCase() === kind);
8874
9780
  if (canonical) {
8875
- return `${KIND_TO_JA[canonical]} \u3092\u793A\u3059\u56F3`;
9781
+ const { shows, name } = KIND_TO_JA[canonical];
9782
+ return `${shows}\u3092\u793A\u3059${name}`;
8876
9783
  }
8877
9784
  }
8878
9785
  let out = topic;
@@ -8883,20 +9790,20 @@ function applyTopicAutoFix(topic) {
8883
9790
  return out;
8884
9791
  }
8885
9792
  function ruleTopicRedundancy(d) {
8886
- const out = [];
8887
- for (const { pattern, hint } of REDUNDANT_TOPIC_PATTERNS) {
8888
- if (pattern.test(d.topic)) {
8889
- out.push({
8890
- rule: "topic-redundant-implementation-detail",
8891
- severity: "warn",
8892
- target: d.id,
8893
- message: `topic \u306B\u5B9F\u88C5\u8A73\u7D30\u304C\u542B\u307E\u308C\u308B: "${d.topic}"`,
8894
- suggestion: hint,
8895
- autoFixable: true
8896
- });
8897
- }
8898
- }
8899
- return out;
9793
+ const \u5F53\u305F\u308B = REDUNDANT_TOPIC_PATTERNS.filter(({ pattern }) => pattern.test(d.topic));
9794
+ if (\u5F53\u305F\u308B.length === 0) return [];
9795
+ const \u76F4\u3057\u305F\u5F8C = applyTopicAutoFix(d.topic);
9796
+ const \u76F4\u305B\u308B = !REDUNDANT_TOPIC_PATTERNS.some(({ pattern }) => pattern.test(\u76F4\u3057\u305F\u5F8C));
9797
+ const \u4F8B = KIND_TO_JA.gantt;
9798
+ const \u624B\u3067\u76F4\u3059 = `\u4F55\u3092\u793A\u3059\u56F3\u304B\u3092\u6587\u3067\u66F8\u304D\u76F4\u3059 (\u300C${\u4F8B.shows}\u3092\u793A\u3059${\u4F8B.name}\u300D \u306E\u3088\u3046\u306B)`;
9799
+ return \u5F53\u305F\u308B.map(({ hint }) => ({
9800
+ rule: "topic-redundant-implementation-detail",
9801
+ severity: "warn",
9802
+ target: d.id,
9803
+ message: `\u56F3\u306E\u8AAC\u660E \`${d.topic}\` \u306B\u5B9F\u88C5\u306E\u66F8\u304D\u65B9\u304C\u5165\u3063\u3066\u3044\u308B\u3002 ${hint}`,
9804
+ suggestion: \u76F4\u305B\u308B ? \u76F4\u3057\u305F\u5F8C : \u624B\u3067\u76F4\u3059,
9805
+ autoFixable: \u76F4\u305B\u308B
9806
+ }));
8900
9807
  }
8901
9808
  function ruleEmptyChartData(d) {
8902
9809
  const out = [];
@@ -8908,8 +9815,8 @@ function ruleEmptyChartData(d) {
8908
9815
  rule: "chart-empty-datum",
8909
9816
  severity: "warn",
8910
9817
  target: n.id,
8911
- message: `chart node "${n.id}" \u304C datum 0 \u4EF6\u3001 chart \u306F\u975E\u8868\u793A\u306B\u306A\u308B`,
8912
- suggestion: `.datum({ id: ..., label: ..., value: ... }) \u3092 1 \u4EF6\u4EE5\u4E0A\u8FFD\u52A0`,
9818
+ message: `\u56F3\u8868 \`${n.id}\` \u306B\u5024 (\`datum\`) \u304C 1 \u4EF6\u3082\u7121\u304F\u3001 \u56F3\u8868\u304C\u63CF\u304B\u308C\u306A\u3044`,
9819
+ suggestion: `\`.datum({ id, label, value })\` \u3067\u5024\u3092 1 \u4EF6\u4EE5\u4E0A\u8DB3\u3059`,
8913
9820
  autoFixable: false
8914
9821
  });
8915
9822
  }
@@ -8918,8 +9825,8 @@ function ruleEmptyChartData(d) {
8918
9825
  rule: "chart-single-datum",
8919
9826
  severity: "info",
8920
9827
  target: n.id,
8921
- message: `chart node "${n.id}" \u304C datum 1 \u4EF6\u3001 \u6BD4\u8F03 / \u63A8\u79FB\u3068\u3057\u3066\u610F\u5473\u304C\u8584\u3044`,
8922
- suggestion: `2 \u4EF6\u4EE5\u4E0A\u306E datum \u3092\u63A8\u5968 (line \u7CFB\u306F 3 \u4EF6\u4EE5\u4E0A\u3067 trend \u304C\u898B\u3048\u308B)`,
9828
+ message: `\u56F3\u8868 \`${n.id}\` \u306E\u5024 (\`datum\`) \u304C 1 \u4EF6\u3060\u3051\u3067\u3001 \u6BD4\u3079\u308B\u3053\u3068\u3082\u79FB\u308A\u5909\u308F\u308A\u3092\u8FFD\u3046\u3053\u3068\u3082\u3067\u304D\u306A\u3044`,
9829
+ suggestion: `\u5024\u3092 2 \u4EF6\u4EE5\u4E0A\u306B\u3059\u308B (\u6298\u308C\u7DDA\u30B0\u30E9\u30D5\u306F 3 \u4EF6\u4EE5\u4E0A\u3067\u50BE\u304D\u304C\u8AAD\u3081\u308B)`,
8923
9830
  autoFixable: false
8924
9831
  });
8925
9832
  }
@@ -8939,8 +9846,8 @@ function ruleGanttUnknownDependsOn(d) {
8939
9846
  rule: "gantt-unknown-depends-on",
8940
9847
  severity: "warn",
8941
9848
  target: t.id,
8942
- message: `task "${t.id}" \u304C\u672A\u5B9A\u7FA9 task "${t.dependsOn}" \u306B dependsOn \u53C2\u7167`,
8943
- suggestion: `\u53C2\u7167\u5148 id \u3092\u4FEE\u6B63 or dependsOn \u3092\u9664\u53BB`,
9849
+ message: `\u4F5C\u696D \`${t.id}\` \u306E \`dependsOn\` \u304C\u3001 \u7121\u3044\u4F5C\u696D \`${t.dependsOn}\` \u3092\u6307\u3057\u3066\u3044\u308B`,
9850
+ suggestion: `\`dependsOn\` \u3092\u65E2\u306B\u3042\u308B\u4F5C\u696D\u306E \`id\` \u306B\u76F4\u3059\u304B\u3001 \`dependsOn\` \u3092\u5916\u3059`,
8944
9851
  autoFixable: false
8945
9852
  });
8946
9853
  }
@@ -8961,8 +9868,8 @@ function ruleMindMapParentReference(d) {
8961
9868
  rule: "mindmap-unknown-parent",
8962
9869
  severity: "warn",
8963
9870
  target: b.id,
8964
- message: `branch "${b.id}" \u304C\u672A\u5B9A\u7FA9 parent "${b.parent}" \u3092\u53C2\u7167`,
8965
- suggestion: `parent \u3092 rootId ("${n.mindData.rootId}") \u307E\u305F\u306F\u65E2\u5B58 branch id \u306B\u4FEE\u6B63`,
9871
+ message: `\u679D \`${b.id}\` \u306E \`parent\` \u304C\u3001 \u7121\u3044\u679D \`${b.parent}\` \u3092\u6307\u3057\u3066\u3044\u308B`,
9872
+ suggestion: `\`parent\` \u3092\u4E2D\u5FC3 (\`${n.mindData.rootId}\`) \u304B\u3001 \u65E2\u306B\u3042\u308B\u679D\u306E \`id\` \u306B\u76F4\u3059`,
8966
9873
  autoFixable: false
8967
9874
  });
8968
9875
  }
@@ -8982,8 +9889,8 @@ function ruleTreeParentReference(d) {
8982
9889
  rule: "tree-unknown-parent",
8983
9890
  severity: "warn",
8984
9891
  target: t.id,
8985
- message: `tree node "${t.id}" \u304C\u672A\u5B9A\u7FA9 parent "${t.parent}" \u3092\u53C2\u7167`,
8986
- suggestion: `parent id \u3092\u65E2\u5B58 tree node \u306B\u4FEE\u6B63 or parent \u9664\u53BB (root \u306B\u3059\u308B)`,
9892
+ message: `\u968E\u5C64\u56F3\u306E\u9805\u76EE \`${t.id}\` \u306E \`parent\` \u304C\u3001 \u7121\u3044\u9805\u76EE \`${t.parent}\` \u3092\u6307\u3057\u3066\u3044\u308B`,
9893
+ suggestion: `\`parent\` \u3092\u65E2\u306B\u3042\u308B\u9805\u76EE\u306E \`id\` \u306B\u76F4\u3059\u304B\u3001 \`parent\` \u3092\u5916\u3057\u3066\u4E00\u756A\u4E0A\u306E\u9805\u76EE\u306B\u3059\u308B`,
8987
9894
  autoFixable: false
8988
9895
  });
8989
9896
  }
@@ -9002,8 +9909,8 @@ function ruleQuadrantMissingItems(d) {
9002
9909
  rule: "quadrant-empty",
9003
9910
  severity: "warn",
9004
9911
  target: n.id,
9005
- message: `quadrant "${n.id}" \u304C item 0 \u4EF6\u3001 \u8EF8\u306E\u307F\u8868\u793A\u3055\u308C\u308B`,
9006
- suggestion: `.item({ id: ..., title: ..., quadrant: "topLeft" | ... }) \u3092 1 \u4EF6\u4EE5\u4E0A\u8FFD\u52A0`,
9912
+ message: `\u56DB\u8C61\u9650\u56F3 \`${n.id}\` \u306B\u9805\u76EE (\`item\`) \u304C 1 \u4EF6\u3082\u7121\u304F\u3001 \u8EF8\u3060\u3051\u304C\u63CF\u304B\u308C\u308B`,
9913
+ suggestion: `\`.item({ id, title, quadrant })\` \u3067\u9805\u76EE\u3092 1 \u4EF6\u4EE5\u4E0A\u8DB3\u3059 (\`quadrant\` \u306F \`topLeft\` \u306A\u3069\u306E 4 \u533A\u753B\u304B\u3089\u9078\u3076)`,
9007
9914
  autoFixable: false
9008
9915
  });
9009
9916
  }
@@ -9013,8 +9920,8 @@ function ruleQuadrantMissingItems(d) {
9013
9920
  rule: "quadrant-single-quadrant",
9014
9921
  severity: "info",
9015
9922
  target: n.id,
9016
- message: `quadrant "${n.id}" \u306E item \u304C 1 \u8C61\u9650\u306B\u96C6\u4E2D\u3001 \u30DE\u30C8\u30EA\u30AF\u30B9\u306E\u610F\u5473\u304C\u8584\u3044`,
9017
- suggestion: `2 \u8C61\u9650\u4EE5\u4E0A\u306B item \u3092\u5206\u6563 (SWOT / Priority matrix \u7B49\u306F 4 \u8C61\u9650 balanced \u3092\u63A8\u5968)`,
9923
+ message: `\u56DB\u8C61\u9650\u56F3 \`${n.id}\` \u306E\u9805\u76EE\u304C\u3059\u3079\u3066 1 \u3064\u306E\u533A\u753B\u306B\u96C6\u307E\u308A\u3001 4 \u3064\u306B\u5206\u3051\u305F\u610F\u5473\u304C\u8584\u3044`,
9924
+ suggestion: `\u9805\u76EE\u3092 2 \u3064\u4EE5\u4E0A\u306E\u533A\u753B\u306B\u5206\u3051\u308B\u3002 \u5F37\u307F\u3068\u5F31\u307F\u3092\u4E26\u3079\u308B\u5206\u6790 (\`SWOT\`) \u3084\u512A\u5148\u5EA6\u3092\u6C7A\u3081\u308B\u56F3\u306F\u3001 4 \u3064\u306E\u533A\u753B\u306B\u6563\u3089\u3057\u3066\u4F7F\u3046`,
9018
9925
  autoFixable: false
9019
9926
  });
9020
9927
  }
@@ -9036,8 +9943,8 @@ function ruleFunnelMonotonicCount(d) {
9036
9943
  rule: "funnel-increasing-count",
9037
9944
  severity: "warn",
9038
9945
  target: stages[i].id,
9039
- message: `stage "${stages[i].id}" (${stages[i].count}) \u304C\u524D\u6BB5 (${stages[i - 1].count}) \u3088\u308A\u5897\u52A0\u3001 funnel \u306F\u5358\u8ABF\u6E1B\u5C11\u304C\u671F\u5F85\u3055\u308C\u308B`,
9040
- suggestion: `stage \u9806\u3092\u518D\u78BA\u8A8D\u3001 \u5897\u52A0 pattern \u306A\u3089\u5225 preset (chart-line \u7B49) \u3092\u691C\u8A0E`,
9946
+ message: `\u6BB5\u968E \`${stages[i].id}\` \u306E\u6570 (${\u4ECA}) \u304C\u524D\u306E\u6BB5\u968E (${\u524D}) \u3088\u308A\u591A\u3044\u3002 \u7D5E\u308A\u8FBC\u307F\u56F3\u306F\u6BB5\u968E\u304C\u9032\u3080\u307B\u3069\u6570\u304C\u6E1B\u308B`,
9947
+ suggestion: `\u6BB5\u968E\u306E\u9806\u756A\u3092\u78BA\u304B\u3081\u308B\u3002 \u6570\u304C\u5897\u3048\u308B\u6D41\u308C\u3092\u793A\u3059\u306A\u3089\u3001 \u6298\u308C\u7DDA\u30B0\u30E9\u30D5 (\`chart-line\`) \u306A\u3069\u306E\u5225\u306E\u56F3\u306B\u3059\u308B`,
9041
9948
  autoFixable: false
9042
9949
  });
9043
9950
  }
@@ -9410,6 +10317,8 @@ var ACCEPTED_KEYS = {
9410
10317
  "bands",
9411
10318
  // 矢印をいつ出すか (#1470)
9412
10319
  "reveal",
10320
+ // 箱に触れると関係する線だけを光らせるか (#1757)
10321
+ "relations",
9413
10322
  // 図の並ぶ向き (#1494)
9414
10323
  "direction",
9415
10324
  // 図の配色 (#1553)
@@ -9438,7 +10347,6 @@ var ACCEPTED_KEYS = {
9438
10347
  "posY",
9439
10348
  "posW",
9440
10349
  "posH",
9441
- "nodes",
9442
10350
  "scale",
9443
10351
  "state",
9444
10352
  "pos",
@@ -9470,6 +10378,8 @@ var ACCEPTED_KEYS = {
9470
10378
  "tailHead",
9471
10379
  "headFill",
9472
10380
  "tailHeadFill",
10381
+ // クラス図の出どころ側の多重度 (#1771)
10382
+ "tailSub",
9473
10383
  "relation",
9474
10384
  // 辺の役目と名前の下地 (cdl#618)
9475
10385
  "role",
@@ -9486,13 +10396,15 @@ var ACCEPTED_KEYS = {
9486
10396
  "labelOffsetX",
9487
10397
  "labelOffsetY",
9488
10398
  "overlay",
9489
- "pos"
10399
+ "pos",
10400
+ // 部品の端で繋ぐ要素の id (#1979)
10401
+ "fromPartNode",
10402
+ "toPartNode"
9490
10403
  ],
9491
10404
  phase: ["step", "duration", "focus", "body", "badge", "tween", "set", "draw", "drawRatio"],
9492
10405
  viewport: ["width", "height", "scale", "laneWidth", "gap", "laneGap", "nodeGap", "labelMargin"],
9493
10406
  lane: ["x", "width", "label", "contain", "lifeline", "pos"],
9494
10407
  group: ["label", "lanes"],
9495
- actorNode: ["posX", "posY", "posW", "posH"],
9496
10408
  axes: ["x", "y"],
9497
10409
  axesX: ["left", "right"],
9498
10410
  axesY: ["bottom", "top"],
@@ -9525,6 +10437,8 @@ var \u6B04\u306E\u578B\u8868 = {
9525
10437
  bands: "\u4E26\u3073",
9526
10438
  // 矢印をいつ出すか (#1470)
9527
10439
  reveal: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
10440
+ // 箱に触れると関係する線だけを光らせるか (#1757)
10441
+ relations: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9528
10442
  // 図の並ぶ向き (#1494)
9529
10443
  direction: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9530
10444
  // 図の配色 (#1553)
@@ -9552,7 +10466,6 @@ var \u6B04\u306E\u578B\u8868 = {
9552
10466
  posY: "\u6570",
9553
10467
  posW: "\u6570",
9554
10468
  posH: "\u6570",
9555
- nodes: "object",
9556
10469
  scale: "\u6570",
9557
10470
  state: "object",
9558
10471
  pos: "object",
@@ -9583,6 +10496,8 @@ var \u6B04\u306E\u578B\u8868 = {
9583
10496
  tailHead: "\u7AEF\u306E\u5F62",
9584
10497
  headFill: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9585
10498
  tailHeadFill: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
10499
+ // クラス図の出どころ側の多重度 (#1771)
10500
+ tailSub: "\u6587\u5B57\u5217",
9586
10501
  relation: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
9587
10502
  // 辺の役目と名前の下地 (cdl#618)
9588
10503
  role: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
@@ -9599,7 +10514,10 @@ var \u6B04\u306E\u578B\u8868 = {
9599
10514
  labelOffsetX: "\u6570",
9600
10515
  labelOffsetY: "\u6570",
9601
10516
  overlay: "\u771F\u507D",
9602
- pos: "object"
10517
+ pos: "object",
10518
+ // 部品の端で繋ぐ要素の id (#1979)。 空の id は要素を指せないので受けない
10519
+ fromPartNode: "\u975E\u7A7A\u306E\u6587\u5B57\u5217",
10520
+ toPartNode: "\u975E\u7A7A\u306E\u6587\u5B57\u5217"
9603
10521
  },
9604
10522
  phase: {
9605
10523
  step: "\u5FC5\u9808\u306E\u975E\u7A7A\u6587\u5B57\u5217",
@@ -9631,7 +10549,6 @@ var \u6B04\u306E\u578B\u8868 = {
9631
10549
  pos: "object"
9632
10550
  },
9633
10551
  group: { label: "\u6587\u5B57\u5217", lanes: "\u6587\u5B57\u5217\u306E\u4E26\u3073" },
9634
- actorNode: { posX: "\u6570", posY: "\u6570", posW: "\u6570", posH: "\u6570" },
9635
10552
  axes: { x: "object", y: "object" },
9636
10553
  axesX: { left: "\u6587\u5B57\u5217", right: "\u6587\u5B57\u5217" },
9637
10554
  axesY: { bottom: "\u6587\u5B57\u5217", top: "\u6587\u5B57\u5217" },
@@ -9887,26 +10804,6 @@ function \u898B\u672C\u306E\u540D\u524D\u304B(kind) {
9887
10804
  if (typeof kind !== "string" || kind.length === 0) return false;
9888
10805
  return kind !== "actor" && !VALID_KIND_SET.has(kind);
9889
10806
  }
9890
- function validateActorNodes(v, path, errors) {
9891
- if (v === void 0) return;
9892
- if (!v || typeof v !== "object" || Array.isArray(v)) {
9893
- errors.push({
9894
- path,
9895
- message: "actor.nodes must be a plain object of name -> { posX, posY, posW, posH }"
9896
- });
9897
- return;
9898
- }
9899
- for (const [name, o] of Object.entries(v)) {
9900
- const nodePath = `${path}.${name}`;
9901
- if (!o || typeof o !== "object" || Array.isArray(o)) {
9902
- errors.push({ path: nodePath, message: "actor.nodes entry must be a plain object" });
9903
- continue;
9904
- }
9905
- const n = o;
9906
- checkUnknownKeys(n, "actorNode", nodePath, errors);
9907
- \u8868\u3067\u691C\u67FB(n, "actorNode", nodePath, `nodes.${name}`, errors);
9908
- }
9909
- }
9910
10807
  function validateViewport(v, errors) {
9911
10808
  if (v === void 0) return;
9912
10809
  if (!v || typeof v !== "object" || Array.isArray(v)) {
@@ -9916,6 +10813,47 @@ function validateViewport(v, errors) {
9916
10813
  checkUnknownKeys(v, "viewport", "$.viewport", errors);
9917
10814
  \u8868\u3067\u691C\u67FB(v, "viewport", "$.viewport", "viewport", errors);
9918
10815
  }
10816
+ function \u9078\u629E\u80A2\u306E\u4E26\u3073\u3092\u691C\u67FB\u3059\u308B(\u5024, path, errors) {
10817
+ if (!Array.isArray(\u5024)) {
10818
+ errors.push({
10819
+ path,
10820
+ message: "options must be \u9078\u629E\u80A2\u306E\u4E26\u3073",
10821
+ hint: `got ${\u5024 === null ? "null" : typeof \u5024}`
10822
+ });
10823
+ return;
10824
+ }
10825
+ \u5024.forEach((x, i) => {
10826
+ const here = `${path}[${i}]`;
10827
+ if (typeof x === "string") return;
10828
+ if (typeof x !== "object" || x === null || Array.isArray(x)) {
10829
+ errors.push({
10830
+ path: here,
10831
+ message: "option must be a string or { value, label }",
10832
+ hint: `got ${Array.isArray(x) ? "array" : x === null ? "null" : typeof x}`
10833
+ });
10834
+ return;
10835
+ }
10836
+ const \u7D44 = x;
10837
+ for (const k of Object.keys(\u7D44)) {
10838
+ if (k === "value" || k === "label") continue;
10839
+ errors.push({ path: `${here}.${k}`, message: `unknown key "${k}"`, hint: "\u4F7F\u3048\u308B\u9805\u76EE = value, label" });
10840
+ }
10841
+ for (const k of ["value", "label"]) {
10842
+ const v = \u7D44[k];
10843
+ if (v === void 0) {
10844
+ errors.push({ path: `${here}.${k}`, message: `${k} is required`, hint: "\u5FC5\u9808\u306E\u9805\u76EE = value, label" });
10845
+ } else if (typeof v !== "string") {
10846
+ errors.push({ path: `${here}.${k}`, message: `${k} must be \u6587\u5B57\u5217`, hint: `got ${v === null ? "null" : typeof v}` });
10847
+ } else if (v === "") {
10848
+ errors.push({
10849
+ path: `${here}.${k}`,
10850
+ message: `${k} must not be empty`,
10851
+ hint: k === "label" ? "\u540D\u524D\u3092\u66F8\u304B\u306A\u3044\u306A\u3089\u6587\u5B57\u5217\u3060\u3051\u3092\u4E26\u3079\u308B" : "\u5024\u3092 1 \u6587\u5B57\u4EE5\u4E0A\u66F8\u304F"
10852
+ });
10853
+ }
10854
+ }
10855
+ });
10856
+ }
9919
10857
  function \u8868\u3067\u4E2D\u8EAB\u3092\u691C\u67FB\u3059\u308B(o, \u8868, path, \u4F55, errors) {
9920
10858
  const kind = typeof o.kind === "string" ? o.kind : "";
9921
10859
  const \u5B9A\u7FA9 = Object.hasOwn(\u8868, kind) ? \u8868[kind] : void 0;
@@ -9940,6 +10878,10 @@ function \u8868\u3067\u4E2D\u8EAB\u3092\u691C\u67FB\u3059\u308B(o, \u8868, path,
9940
10878
  });
9941
10879
  continue;
9942
10880
  }
10881
+ if (\u5F62 === "\u9078\u629E\u80A2\u306E\u4E26\u3073") {
10882
+ \u9078\u629E\u80A2\u306E\u4E26\u3073\u3092\u691C\u67FB\u3059\u308B(\u5024, `${path}.${\u6B04}`, errors);
10883
+ continue;
10884
+ }
9943
10885
  const \u578B\u304C\u5408\u3046 = \u5F62 === "\u6570" ? typeof \u5024 === "number" && Number.isFinite(\u5024) : \u5F62 === "\u6570\u304B\u6587\u5B57\u5217" ? typeof \u5024 === "number" && Number.isFinite(\u5024) || typeof \u5024 === "string" : \u5F62 === "\u6587\u5B57\u5217\u306E\u4E26\u3073" ? Array.isArray(\u5024) && \u5024.every((x) => typeof x === "string") : \u5F62 === "\u6570\u306E\u4E26\u3073" ? Array.isArray(\u5024) && \u5024.every((x) => typeof x === "number" && Number.isFinite(x)) : \u5F62 === "\u771F\u507D" ? typeof \u5024 === "boolean" : \u5F62 === "\u7D44\u306E\u4E26\u3073" ? Array.isArray(\u5024) && \u5024.length > 0 && \u5024.every(
9944
10886
  (x) => typeof x === "object" && x !== null && !Array.isArray(x) && Object.keys(x).length > 0 && Object.values(x).every(
9945
10887
  (y) => typeof y === "string" || typeof y === "number" && Number.isFinite(y)
@@ -10093,12 +11035,15 @@ function validateFormulas(v, inputs, errors) {
10093
11035
  }
10094
11036
  }
10095
11037
  const \u5148\u306B\u66F8\u304B\u308C\u305F\u5F0F = /* @__PURE__ */ new Set();
10096
- for (const [\u540D\u524D, \u5F0F] of Object.entries(v)) {
11038
+ for (const [\u540D\u524D, \u5024] of Object.entries(v)) {
10097
11039
  const path = `$.formulas.${\u540D\u524D}`;
10098
11040
  if (!isValueName(\u540D\u524D)) {
10099
11041
  errors.push({ path, ...valueNameIssue(\u540D\u524D) });
10100
11042
  continue;
10101
11043
  }
11044
+ const \u691C\u67FB\u7D50\u679C = \u5F0F\u306E\u7D44\u3092\u691C\u67FB\u3059\u308B(\u5024, path, errors);
11045
+ if (!\u691C\u67FB\u7D50\u679C.\u8AAD\u3081\u305F) continue;
11046
+ const \u5F0F = \u691C\u67FB\u7D50\u679C.\u5024;
10102
11047
  if (typeof \u5F0F !== "string" || \u5F0F.trim() === "") {
10103
11048
  errors.push({
10104
11049
  path,
@@ -10139,6 +11084,37 @@ function validateFormulas(v, inputs, errors) {
10139
11084
  }
10140
11085
  }
10141
11086
  }
11087
+ function \u5F0F\u306E\u7D44\u3092\u691C\u67FB\u3059\u308B(\u5024, path, errors) {
11088
+ if (!\u5024 || typeof \u5024 !== "object" || Array.isArray(\u5024)) return { \u8AAD\u3081\u305F: true, \u5024 };
11089
+ const \u7D44 = \u5024;
11090
+ let \u8AAD\u3081\u305F = true;
11091
+ for (const \u9375 of Object.keys(\u7D44)) {
11092
+ if (\u9375 === "expression" || \u9375 === "label") continue;
11093
+ \u8AAD\u3081\u305F = false;
11094
+ errors.push({
11095
+ path: `${path}.${\u9375}`,
11096
+ message: `unknown formula field: ${\u9375}`,
11097
+ hint: "\u4F7F\u3048\u308B\u9805\u76EE = expression, label"
11098
+ });
11099
+ }
11100
+ if (typeof \u7D44.expression !== "string" || \u7D44.expression.trim() === "") {
11101
+ \u8AAD\u3081\u305F = false;
11102
+ errors.push({
11103
+ path: `${path}.expression`,
11104
+ message: "expression must be a non-empty expression string",
11105
+ hint: `got ${\u7D44.expression === void 0 ? "nothing" : JSON.stringify(\u7D44.expression)}`
11106
+ });
11107
+ }
11108
+ if (\u7D44.label !== void 0 && (typeof \u7D44.label !== "string" || \u7D44.label.trim() === "")) {
11109
+ \u8AAD\u3081\u305F = false;
11110
+ errors.push({
11111
+ path: `${path}.label`,
11112
+ message: "label must be a non-empty string",
11113
+ hint: "\u540D\u672D\u3092\u4ED8\u3051\u306A\u3044\u306A\u3089 label \u3092\u66F8\u304B\u306A\u3044"
11114
+ });
11115
+ }
11116
+ return \u8AAD\u3081\u305F ? { \u8AAD\u3081\u305F: true, \u5024: \u7D44.expression } : { \u8AAD\u3081\u305F: false };
11117
+ }
10142
11118
  function validateEvents(v, errors) {
10143
11119
  if (v === void 0) return;
10144
11120
  if (!Array.isArray(v)) {
@@ -10498,7 +11474,6 @@ function validateJson(json) {
10498
11474
  });
10499
11475
  }
10500
11476
  }
10501
- validateActorNodes(ao.nodes, `$.actors[${i}].nodes`, errors);
10502
11477
  if (ao.state !== void 0) {
10503
11478
  if (!ao.state || typeof ao.state !== "object" || Array.isArray(ao.state)) {
10504
11479
  errors.push({
@@ -10715,18 +11690,13 @@ function jsonToDoc(json) {
10715
11690
  opportunity: a.opportunity
10716
11691
  },
10717
11692
  colorHex: \u8272.hex,
11693
+ // 部品に書いた色の名前は効かない。 記法と同じく書いた名前として残し、組み立て側が知らせる (#1973)
11694
+ partColorName: isPart ? \u8272.tone : void 0,
10718
11695
  // 絶対座標と大きさ (#1294)。 `pos` (ずらし幅) とは別経路
10719
11696
  posX: a.posX,
10720
11697
  posY: a.posY,
10721
11698
  posW: a.posW,
10722
11699
  posH: a.posH,
10723
- // 箱の中の要素ごとの固定 (#1294)。 写しを作って外から書き換えられないようにする
10724
- nodes: a.nodes ? Object.fromEntries(
10725
- Object.entries(a.nodes).map(([id, o]) => [
10726
- id,
10727
- { posX: o.posX, posY: o.posY, posW: o.posW, posH: o.posH }
10728
- ])
10729
- ) : void 0,
10730
11700
  // 倍率は見本にしか効かない (検査が見本でない箱を弾く)。 書かれた名前は JSON では
10731
11701
  // 常に `scale` で、記法の別名 (`倍率`) は JSON に持ち込まない
10732
11702
  scale: isPart ? a.scale : void 0,
@@ -10752,6 +11722,8 @@ function jsonToDoc(json) {
10752
11722
  tailHead: s.tailHead,
10753
11723
  headFill: s.headFill,
10754
11724
  tailHeadFill: s.tailHeadFill,
11725
+ // クラス図の出どころ側の多重度 (#1771)
11726
+ tailSub: s.tailSub,
10755
11727
  relation: s.relation,
10756
11728
  // 辺の役目と名前の下地 (cdl#618)
10757
11729
  role: s.role,
@@ -10770,6 +11742,9 @@ function jsonToDoc(json) {
10770
11742
  labelOffsetX: s.labelOffsetX,
10771
11743
  labelOffsetY: s.labelOffsetY,
10772
11744
  overlay: s.overlay,
11745
+ // 部品の端で繋ぐ要素の id (#1979)。 書かない矢印には欄を足さない = 記法と同じ形になる
11746
+ ...s.fromPartNode !== void 0 ? { fromPartNode: s.fromPartNode } : {},
11747
+ ...s.toPartNode !== void 0 ? { toPartNode: s.toPartNode } : {},
10773
11748
  // CAR-1693 Phase 1: DSL 表面 pos → 内部 AST layoutPos
10774
11749
  layoutPos: s.pos,
10775
11750
  pos: p0
@@ -10787,7 +11762,14 @@ function jsonToDoc(json) {
10787
11762
  pos: p0
10788
11763
  }));
10789
11764
  const scrolls = json.scrolls ? Object.entries(json.scrolls).map(([id, spec]) => ({ id, ...spec })) : void 0;
10790
- const formulas = json.formulas ? Object.entries(json.formulas).map(([id, expression]) => ({ id, expression, pos: p0 })) : void 0;
11765
+ const formulas = json.formulas ? Object.entries(json.formulas).map(
11766
+ ([id, \u5024]) => typeof \u5024 === "string" ? { id, expression: \u5024, pos: p0 } : {
11767
+ id,
11768
+ expression: \u5024.expression,
11769
+ ...\u5024.label !== void 0 ? { label: \u5024.label } : {},
11770
+ pos: p0
11771
+ }
11772
+ ) : void 0;
10791
11773
  const states = Object.entries(json.states ?? {}).map(([name, initial]) => ({
10792
11774
  name,
10793
11775
  initial,
@@ -10856,6 +11838,8 @@ function jsonToDoc(json) {
10856
11838
  bands: json.bands,
10857
11839
  // 矢印をいつ出すか (#1470)
10858
11840
  reveal: json.reveal,
11841
+ // 箱に触れると関係する線だけを光らせるか (#1757)
11842
+ relations: json.relations,
10859
11843
  // 図の並ぶ向き (#1494)。 JSON は英語で書くので、記法と同じ語に直してから渡す
10860
11844
  ...json.direction !== void 0 ? { direction: json.direction === "horizontal" ? "\u6A2A" : "\u7E26" } : {},
10861
11845
  // 図の配色 (#1553)。 記法と同じ解決を通す = 別名 (`生成り` / `青磁`) の受け方がずれない。
@@ -11122,28 +12106,6 @@ var diagram_default = {
11122
12106
  type: "number",
11123
12107
  description: "\u7BB1\u306E\u9AD8\u3055\u3002"
11124
12108
  },
11125
- nodes: {
11126
- type: "object",
11127
- description: "\u7BB1\u306E\u4E2D\u306E\u8981\u7D20\u3054\u3068\u306E\u4F4D\u7F6E\u3068\u5927\u304D\u3055\u3002 key \u306F header / footer / s0 \u7B49\u306E\u8981\u7D20\u540D\u3002",
11128
- additionalProperties: {
11129
- type: "object",
11130
- additionalProperties: false,
11131
- properties: {
11132
- posX: {
11133
- type: "number"
11134
- },
11135
- posY: {
11136
- type: "number"
11137
- },
11138
- posW: {
11139
- type: "number"
11140
- },
11141
- posH: {
11142
- type: "number"
11143
- }
11144
- }
11145
- }
11146
- },
11147
12109
  scale: {
11148
12110
  type: "number",
11149
12111
  description: "parts \u306E\u63CF\u753B\u500D\u7387\u3002 kind \u306B parts identifier \u3092\u6307\u5B9A\u3057\u305F\u6642\u3060\u3051\u4F7F\u3048\u308B\u3002"
@@ -11404,6 +12366,10 @@ var diagram_default = {
11404
12366
  type: "string",
11405
12367
  description: "\u30E9\u30D9\u30EB\u4E0B\u306E\u88DC\u8DB3"
11406
12368
  },
12369
+ tailSub: {
12370
+ type: "string",
12371
+ description: '\u30AF\u30E9\u30B9\u56F3\u306E\u51FA\u3069\u3053\u308D\u5074\u306E\u591A\u91CD\u5EA6 (\u4F8B "1")\u3002 sub \u304C\u884C\u304D\u5148\u306E\u7AEF\u306E\u591A\u91CD\u5EA6\u3002 \u30AF\u30E9\u30B9\u56F3\u3067\u3060\u3051\u52B9\u304F'
12372
+ },
11407
12373
  tone: {
11408
12374
  type: "string",
11409
12375
  enum: [
@@ -11462,7 +12428,7 @@ var diagram_default = {
11462
12428
  "many",
11463
12429
  "zero-many"
11464
12430
  ],
11465
- description: "\u7740\u304D\u5148\u5074\u306E\u7AEF\u306E\u5F62\u3002 \u7AEF\u306E\u5F62\u3067\u95A2\u4FC2\u306E\u7A2E\u985E\u3092\u793A\u3059 = triangle (\u7D99\u3050) / diamond (\u6301\u3064) / open (\u4F7F\u3046) / crow (\u591A) / one / zero-one / many / zero-many (\u500B\u6570)\u3002 \u66F8\u304B\u306A\u3051\u308C\u3070\u5857\u3063\u305F\u4E09\u89D2\u306B\u306A\u308B\u3002"
12431
+ description: "\u7740\u304D\u5148\u5074\u306E\u7AEF\u306E\u5F62\u3002 \u7AEF\u306E\u5F62\u3067\u95A2\u4FC2\u306E\u7A2E\u985E\u3092\u793A\u3059 = triangle (\u7D99\u627F\u30FB\u5B9F\u88C5) / diamond (\u96C6\u7D04\u30FB\u30B3\u30F3\u30DD\u30B8\u30B7\u30E7\u30F3) / open (\u95A2\u9023\u30FB\u4F9D\u5B58) / crow (\u591A) / one / zero-one / many / zero-many (\u500B\u6570)\u3002 \u66F8\u304B\u306A\u3051\u308C\u3070\u5857\u3063\u305F\u4E09\u89D2\u306B\u306A\u308B\u3002"
11466
12432
  },
11467
12433
  tailHead: {
11468
12434
  type: "string",
@@ -11539,6 +12505,18 @@ var diagram_default = {
11539
12505
  type: "boolean",
11540
12506
  description: "true \u3067\u8AAC\u660E\u6587\u3092\u77E2\u5370\u306E\u7DDA\u306E\u4E0A\u306B\u91CD\u306D\u308B (\u5206\u5C90\u56F3\u306E\u6761\u4EF6\u30E9\u30D9\u30EB\u7528)"
11541
12507
  },
12508
+ fromPartNode: {
12509
+ type: "string",
12510
+ minLength: 1,
12511
+ pattern: "\\S",
12512
+ description: "from \u304C\u90E8\u54C1\u306E\u6642\u3001\u77E2\u5370\u3092\u7E4B\u3050\u90E8\u54C1\u306E\u4E2D\u306E\u8981\u7D20\u306E id\u3002 \u8981\u7D20\u3092 1 \u3064\u3060\u3051\u6301\u3064\u90E8\u54C1\u306F\u66F8\u304B\u306A\u304F\u3066\u3082\u305D\u306E\u8981\u7D20\u306B\u7E4B\u3050\u3002 \u8981\u7D20\u3092 2 \u3064\u4EE5\u4E0A\u6301\u3064\u90E8\u54C1\u306F\u66F8\u304B\u306A\u3044\u3068\u77E2\u5370\u3092\u5916\u3057\u3066\u77E5\u3089\u305B\u308B"
12513
+ },
12514
+ toPartNode: {
12515
+ type: "string",
12516
+ minLength: 1,
12517
+ pattern: "\\S",
12518
+ description: "to \u304C\u90E8\u54C1\u306E\u6642\u3001\u77E2\u5370\u3092\u7E4B\u3050\u90E8\u54C1\u306E\u4E2D\u306E\u8981\u7D20\u306E id\u3002 \u8981\u7D20\u3092 1 \u3064\u3060\u3051\u6301\u3064\u90E8\u54C1\u306F\u66F8\u304B\u306A\u304F\u3066\u3082\u305D\u306E\u8981\u7D20\u306B\u7E4B\u3050\u3002 \u8981\u7D20\u3092 2 \u3064\u4EE5\u4E0A\u6301\u3064\u90E8\u54C1\u306F\u66F8\u304B\u306A\u3044\u3068\u77E2\u5370\u3092\u5916\u3057\u3066\u77E5\u3089\u305B\u308B"
12519
+ },
11542
12520
  pos: {
11543
12521
  type: "object",
11544
12522
  additionalProperties: false,
@@ -11661,9 +12639,13 @@ var diagram_default = {
11661
12639
  "tree",
11662
12640
  "gantt",
11663
12641
  "funnel",
11664
- "slope"
12642
+ "slope",
12643
+ "gauge",
12644
+ "radial",
12645
+ "stacked",
12646
+ "waffle"
11665
12647
  ],
11666
- description: "\u3053\u306E phase \u3067\u8D77\u70B9\u304B\u3089\u63CF\u304F\u3082\u306E\u3002 \u8A9E\u306F\u56F3\u7A2E\u3068\u63C3\u3048\u308B\u3002 line / journey = \u7DDA\u304C\u5DE6\u7AEF\u304B\u3089\u53F3\u3078\u4F38\u3073\u308B / bar = \u68D2\u304C\u6A2A\u8EF8\u304B\u3089\u4E0A\u3078\u4F38\u3073\u308B / pie = \u6247\u304C 12 \u6642\u304B\u3089\u6642\u8A08\u56DE\u308A\u306B\u958B\u304F / mind = \u679D\u304C\u4E2D\u5FC3\u304B\u3089\u5916\u3078\u4F38\u3073\u308B / tree = \u679D\u304C\u6839\u304B\u3089\u4E0B\u3078\u4F38\u3073\u308B / gantt = \u5E2F\u304C\u5404\u59CB\u7AEF\u304B\u3089\u53F3\u3078\u4F38\u3073\u308B / funnel = \u6BB5\u304C\u4E0A\u7AEF\u304B\u3089\u9806\u306B\u7A4D\u307E\u308C\u308B / slope = \u7DDA\u304C\u5DE6\u306E\u8EF8\u304B\u3089\u53F3\u306E\u8EF8\u3078\u4F38\u3073\u308B"
12648
+ description: "\u3053\u306E phase \u3067\u8D77\u70B9\u304B\u3089\u63CF\u304F\u3082\u306E\u3002 \u8A9E\u306F\u56F3\u7A2E\u3068\u63C3\u3048\u308B\u3002 line / journey = \u7DDA\u304C\u5DE6\u7AEF\u304B\u3089\u53F3\u3078\u4F38\u3073\u308B / bar = \u68D2\u304C\u6A2A\u8EF8\u304B\u3089\u4E0A\u3078\u4F38\u3073\u308B / pie = \u6247\u304C 12 \u6642\u304B\u3089\u6642\u8A08\u56DE\u308A\u306B\u958B\u304F / mind = \u679D\u304C\u4E2D\u5FC3\u304B\u3089\u5916\u3078\u4F38\u3073\u308B / tree = \u679D\u304C\u6839\u304B\u3089\u4E0B\u3078\u4F38\u3073\u308B / gantt = \u5E2F\u304C\u5404\u59CB\u7AEF\u304B\u3089\u53F3\u3078\u4F38\u3073\u308B / funnel = \u6BB5\u304C\u4E0A\u7AEF\u304B\u3089\u9806\u306B\u7A4D\u307E\u308C\u308B / slope = \u7DDA\u304C\u5DE6\u306E\u8EF8\u304B\u3089\u53F3\u306E\u8EF8\u3078\u4F38\u3073\u308B / gauge = \u5F27\u304C 9 \u6642\u304B\u3089\u4E0A\u3092\u901A\u3063\u3066 3 \u6642\u3078\u4F38\u3073\u308B / radial = \u5404\u8F2A\u304C 12 \u6642\u304B\u3089\u6642\u8A08\u56DE\u308A\u306B\u958B\u304F / stacked = \u5E2F\u304C\u5DE6\u7AEF\u304B\u3089\u53F3\u3078\u4F38\u3073\u308B / waffle = \u5370\u304C\u5DE6\u4E0A\u304B\u3089\u8AAD\u3080\u5411\u304D\u306B 1 \u500B\u305A\u3064\u57CB\u307E\u308B"
11667
12649
  },
11668
12650
  drawRatio: {
11669
12651
  type: "number",
@@ -12898,10 +13880,43 @@ var diagram_default = {
12898
13880
  min: {
12899
13881
  type: "number"
12900
13882
  },
13883
+ offLabel: {
13884
+ type: "string",
13885
+ minLength: 1,
13886
+ description: "\u5207\u308A\u66FF\u3048 (toggle) \u304C\u5207\u306E\u6642\u306B\u3001\u7BB1\u306E\u5B57\u306E\u5DEE\u3057\u8FBC\u307F\u3078\u63CF\u304F\u540D\u524D\u3002 \u7701\u7565\u3059\u308B\u3068 false \u3092\u63CF\u304F\u3002"
13887
+ },
13888
+ onLabel: {
13889
+ type: "string",
13890
+ minLength: 1,
13891
+ description: "\u5207\u308A\u66FF\u3048 (toggle) \u304C\u5165\u306E\u6642\u306B\u3001\u7BB1\u306E\u5B57\u306E\u5DEE\u3057\u8FBC\u307F\u3078\u63CF\u304F\u540D\u524D\u3002 \u7701\u7565\u3059\u308B\u3068 true \u3092\u63CF\u304F\u3002"
13892
+ },
12901
13893
  options: {
12902
13894
  type: "array",
13895
+ description: "\u9078\u629E\u80A2\u3002 \u6587\u5B57\u5217\u306F\u5024\u3068\u540D\u524D\u3092\u517C\u306D\u3001{ value, label } \u306E\u7D44\u306F value \u3092\u5024\u306B\u3057\u3066 label \u3092\u64CD\u4F5C\u90E8\u306E\u9078\u629E\u80A2\u3068\u7BB1\u306E\u5B57\u306E\u5DEE\u3057\u8FBC\u307F\u306B\u63CF\u304F\u3002 2 \u3064\u3092\u6DF7\u305C\u3066\u66F8\u3051\u308B\u3002",
12903
13896
  items: {
12904
- type: "string"
13897
+ oneOf: [
13898
+ {
13899
+ type: "string"
13900
+ },
13901
+ {
13902
+ type: "object",
13903
+ additionalProperties: false,
13904
+ required: [
13905
+ "value",
13906
+ "label"
13907
+ ],
13908
+ properties: {
13909
+ value: {
13910
+ type: "string",
13911
+ minLength: 1
13912
+ },
13913
+ label: {
13914
+ type: "string",
13915
+ minLength: 1
13916
+ }
13917
+ }
13918
+ }
13919
+ ]
12905
13920
  }
12906
13921
  },
12907
13922
  placeholder: {
@@ -13075,11 +14090,34 @@ var diagram_default = {
13075
14090
  },
13076
14091
  formulas: {
13077
14092
  type: "object",
13078
- description: '\u3064\u307E\u307F\u306E\u5024\u304B\u3089\u6C7A\u307E\u308B\u5024\u3002 \u540D\u524D\u3092\u9375\u3001\u5F0F\u3092\u5024\u306B\u66F8\u304F\u3002 `values` \u3068\u306F\u7D4C\u8DEF\u304C\u5225\u3067\u3001\u5F0F\u306F\u540D\u524D\u3092\u4E2D\u62EC\u5F27\u3067\u56F2\u308F\u306A\u3044 (\u4F8B "input * 2")\u3002',
14093
+ description: '\u3064\u307E\u307F\u306E\u5024\u304B\u3089\u6C7A\u307E\u308B\u5024\u3002 \u540D\u524D\u3092\u9375\u3001\u5F0F\u3092\u5024\u306B\u66F8\u304F\u3002 `values` \u3068\u306F\u7D4C\u8DEF\u304C\u5225\u3067\u3001\u5F0F\u306F\u540D\u524D\u3092\u4E2D\u62EC\u5F27\u3067\u56F2\u308F\u306A\u3044 (\u4F8B "input * 2")\u3002 \u64CD\u4F5C\u90E8\u306B\u51FA\u3059\u540D\u672D\u3092\u4ED8\u3051\u308B\u6642\u306F { "expression": "input * 2", "label": "2 \u500D" } \u306E\u7D44\u3067\u66F8\u304F\u3002',
13079
14094
  additionalProperties: {
13080
- type: "string",
13081
- minLength: 1,
13082
- pattern: "\\S"
14095
+ oneOf: [
14096
+ {
14097
+ type: "string",
14098
+ minLength: 1,
14099
+ pattern: "\\S"
14100
+ },
14101
+ {
14102
+ type: "object",
14103
+ additionalProperties: false,
14104
+ required: ["expression"],
14105
+ properties: {
14106
+ expression: {
14107
+ type: "string",
14108
+ minLength: 1,
14109
+ pattern: "\\S",
14110
+ description: '\u5F0F (\u4F8B "input * 2")'
14111
+ },
14112
+ label: {
14113
+ type: "string",
14114
+ minLength: 1,
14115
+ pattern: "\\S",
14116
+ description: "\u64CD\u4F5C\u90E8\u306B\u5F0F\u306E\u540D\u524D\u3068\u3057\u3066\u51FA\u3059\u540D\u672D\u3002 \u66F8\u304B\u306A\u3051\u308C\u3070\u540D\u524D\u3092\u305D\u306E\u307E\u307E\u51FA\u3059"
14117
+ }
14118
+ }
14119
+ }
14120
+ ]
13083
14121
  },
13084
14122
  propertyNames: {
13085
14123
  pattern: "^[A-Za-z_][A-Za-z0-9_]*$"
@@ -13109,6 +14147,14 @@ var diagram_default = {
13109
14147
  ],
13110
14148
  description: "\u77E2\u5370\u3092\u3044\u3064\u51FA\u3059\u304B\u3002 phase (\u65E2\u5B9A) = \u6BB5\u304C\u540D\u6307\u3057\u3059\u308B\u77E2\u5370\u306F\u305D\u306E\u6BB5\u304C\u6765\u308B\u307E\u3067\u63CF\u304B\u306A\u3044\u3002 all = \u6BB5\u306B\u95A2\u308F\u3089\u305A\u6700\u521D\u304B\u3089\u5168\u90E8\u63CF\u304F\u3002"
13111
14149
  },
14150
+ relations: {
14151
+ type: "string",
14152
+ enum: [
14153
+ "off",
14154
+ "hover"
14155
+ ],
14156
+ description: "\u7BB1\u306B\u89E6\u308C\u308B\u3068\u95A2\u4FC2\u3059\u308B\u7DDA\u3060\u3051\u3092\u5149\u3089\u305B\u308B\u304B\u3002 off (\u65E2\u5B9A) = \u4F55\u3082\u3057\u306A\u3044\u3002 hover = \u7BB1\u306B\u89E6\u308C\u305F\u6642\u306B\u305D\u306E\u7BB1\u3068\u7E4B\u304C\u308B\u7DDA\u3068\u76F8\u624B\u306E\u7BB1\u3060\u3051\u304C\u5149\u308A\u3001\u4ED6\u304C\u6C88\u3080\u3002 \u9806\u756A\u3092\u6301\u305F\u306A\u3044\u30AF\u30E9\u30B9\u56F3\u3068 ER \u56F3\u3067\u4F7F\u3046\u3002"
14157
+ },
13112
14158
  bands: {
13113
14159
  type: "array",
13114
14160
  description: "\u9806\u5E8F\u56F3\u3067\u9762\u304C\u52D5\u3044\u3066\u3044\u308B\u9593\u306E\u5E2F\u3002 \u66F8\u304B\u306A\u3051\u308C\u3070\u9762\u3054\u3068\u306B\u300C\u6700\u521D\u306B\u95A2\u308F\u3063\u305F\u6BB5\u304B\u3089\u6700\u5F8C\u307E\u3067\u300D \u306E 1 \u672C\u306B\u306A\u308B\u3002",
@@ -13324,6 +14370,6 @@ function isV05Source(src) {
13324
14370
  return true;
13325
14371
  }
13326
14372
 
13327
- export { DIAGRAM_BOUNDARY_PADDING, DRAW_TARGETS, DRAW_WORDS, JSONを分解する, MAX_INPUT_BYTES, MAX_INPUT_ELEMENTS, MAX_PART_SCALE, NODE_KIND_ALIAS, NODE_KIND_VALID, PHASE_ITEM_WORDS, PRESET_TYPES, RELATIVE_GAP_DEFAULT, TONE_ALIAS, TOP_LEVEL_KEYS, autoFix, compileToCdl, computeDiagramBoundingBox, countBytes, countDiagramElements, countDocElements, describeOversize, describeOversizeSource, diagramJsonSchema, isColorValue, jsonToDiagram, lintDiagram, measureActorBoxes, normalizePartScale, orderByDependency, parseFocusEntry, parseRelativePos, parseTextDsl, parseTextDslV05, partBoxInFrame, partDrawsInDiagram, partIsMeasurable, partRenderSize, partScaleFactor, partTargetScale, partTargetSize, partVisualSize, partsBaseRows, partsGridCenters, pointsOutside, rectsOverlap, resolveRelativePos, stripExternalPaint, stripQuotes, textDslToDiagram, validateDragonJson, writeActorPosition, 区間に広げる, 記法を分解する };
14373
+ export { DIAGRAM_BOUNDARY_PADDING, DIRECTION_ALIAS, DRAW_TARGETS, DRAW_WORDS, JSONを分解する, MAX_INPUT_BYTES, MAX_INPUT_ELEMENTS, MAX_PART_SCALE, NODE_KIND_ALIAS, NODE_KIND_VALID, PHASE_ITEM_WORDS, PRESET_TYPES, RELATIVE_GAP_DEFAULT, TONE_ALIAS, TOP_LEVEL_KEYS, autoFix, compileToCdl, computeDiagramBoundingBox, countBytes, countDiagramElements, countDocElements, describeOversize, describeOversizeSource, diagramJsonSchema, isColorValue, jsonToDiagram, lintDiagram, measureActorBoxes, normalizePartScale, orderByDependency, parseFocusEntry, parseRelativePos, parseTextDsl, parseTextDslV05, partBoxInFrame, partDrawsInDiagram, partIsMeasurable, partRenderSize, partScaleFactor, partTargetScale, partTargetSize, partVisualSize, partsBaseBottom, partsGridCenters, pointsOutside, rectsOverlap, resolveRelativePos, stripExternalPaint, stripQuotes, textDslToDiagram, validateDragonJson, writeActorPosition, 区間に広げる, 記法を分解する, 部品に上書きを当てる };
13328
14374
  //# sourceMappingURL=index.js.map
13329
14375
  //# sourceMappingURL=index.js.map