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