@cardenelabs/dragon 0.15.0 → 0.17.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/README.md +10 -0
- package/dist/index.cjs +628 -379
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +217 -7
- package/dist/index.d.ts +217 -7
- package/dist/index.js +629 -381
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/compile.ts +567 -725
- package/src/index.ts +1 -0
- package/src/json-parser.ts +145 -2
- package/src/schemas/diagram.json +74 -3
- package/src/tokenize.ts +5 -5
- package/src/types.ts +84 -1
- package/src/v05/parser.ts +216 -6
package/src/v05/parser.ts
CHANGED
|
@@ -41,8 +41,9 @@
|
|
|
41
41
|
* 出力は v0.4 と同じ DslDocument。 既存 compile.ts で CdlDiagram に変換できる。
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
|
-
import type { NodeKind, Tone, EdgeStyle } from "@cardenelabs/cdl";
|
|
45
|
-
import { TONES, NODE_KINDS, parseFormula } from "@cardenelabs/cdl";
|
|
44
|
+
import type { NodeKind, Tone, EdgeStyle, EdgeHead, EdgeHeadFill, ClassRelationType, SequenceMessageKind } from "@cardenelabs/cdl";
|
|
45
|
+
import { TONES, NODE_KINDS, EDGE_HEADS, EDGE_HEAD_FILLS, EDGE_STYLES, EDGE_REVEALS, CLASS_RELATION_LOOK, SEQUENCE_MESSAGE_LOOK, parseFormula } from "@cardenelabs/cdl";
|
|
46
|
+
import type { EdgeReveal } from "@cardenelabs/cdl";
|
|
46
47
|
import { TONE_ALIAS, NODE_KIND_ALIAS } from "../keywords";
|
|
47
48
|
import { parseRelativePos, orderByDependency } from "../relative-pos";
|
|
48
49
|
import {
|
|
@@ -74,6 +75,7 @@ import type {
|
|
|
74
75
|
DslError,
|
|
75
76
|
PresetType,
|
|
76
77
|
DslLane,
|
|
78
|
+
DslBand,
|
|
77
79
|
DslGroup,
|
|
78
80
|
DslViewport,
|
|
79
81
|
} from "../types";
|
|
@@ -83,6 +85,26 @@ export type V05ParseResult = { ok: true; doc: DslDocument } | { ok: false; error
|
|
|
83
85
|
/** 矢印を出す辺。 Text DSL / JSON validator / 公開 schema の 3 経路で同じ 4 値を使う。 */
|
|
84
86
|
export const EDGE_SIDE_VALUES = ["top", "right", "bottom", "left"] as const;
|
|
85
87
|
|
|
88
|
+
/**
|
|
89
|
+
* 矢印の先の形として書ける語 (#1462)。
|
|
90
|
+
*
|
|
91
|
+
* **描画側から導く**。 手で並べると、描画側が形を増やした時に書けないままになる。
|
|
92
|
+
*/
|
|
93
|
+
export const EDGE_HEAD_VALUES: readonly string[] = EDGE_HEADS;
|
|
94
|
+
|
|
95
|
+
/** 端の印の塗り方 (#1466)。 描画側の一覧から導く = 描画側が増やせば書ける */
|
|
96
|
+
export const EDGE_HEAD_FILL_VALUES: readonly string[] = EDGE_HEAD_FILLS;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* クラス図の関係の種類 (#1466)。 描画側の表 (`CLASS_RELATION_LOOK`) の key から導く。
|
|
100
|
+
*
|
|
101
|
+
* 手で並べると、描画側が種類を足した時にここだけ取り残されて書けないままになる。
|
|
102
|
+
*/
|
|
103
|
+
export const CLASS_RELATION_VALUES: readonly string[] = Object.keys(CLASS_RELATION_LOOK);
|
|
104
|
+
|
|
105
|
+
/** 順序図の言づての種類 (#1466)。 描画側の表から導く */
|
|
106
|
+
export const SEQ_MESSAGE_VALUES: readonly string[] = Object.keys(SEQUENCE_MESSAGE_LOOK);
|
|
107
|
+
|
|
86
108
|
/**
|
|
87
109
|
* 記法が受ける top-level の項目 (#1190)。
|
|
88
110
|
*
|
|
@@ -115,6 +137,10 @@ export const TOP_LEVEL_KEYS = [
|
|
|
115
137
|
"events",
|
|
116
138
|
// 巻き上げに応じて進む値 (#1393)
|
|
117
139
|
"scrolls",
|
|
140
|
+
// 動いている間の帯 (#1466)。 順序図だけが読む
|
|
141
|
+
"bands",
|
|
142
|
+
// 矢印をいつ出すか (#1470)
|
|
143
|
+
"reveal",
|
|
118
144
|
] as const;
|
|
119
145
|
|
|
120
146
|
/**
|
|
@@ -249,6 +275,11 @@ export const PRESET_TYPES: ReadonlySet<PresetType> = new Set([
|
|
|
249
275
|
"pie",
|
|
250
276
|
"bar",
|
|
251
277
|
"line",
|
|
278
|
+
"gauge",
|
|
279
|
+
"radial",
|
|
280
|
+
"stat",
|
|
281
|
+
"waffle",
|
|
282
|
+
"stacked",
|
|
252
283
|
"funnel",
|
|
253
284
|
"tree",
|
|
254
285
|
"journey",
|
|
@@ -330,11 +361,14 @@ export const NODE_KIND_VALID: ReadonlySet<string> = new Set<string>([
|
|
|
330
361
|
const TONE_VALID: ReadonlySet<string> = new Set<string>(TONES);
|
|
331
362
|
|
|
332
363
|
/**
|
|
333
|
-
* 受理する線種。
|
|
364
|
+
* 受理する線種。 **描画側の一覧から導く** (#1466)。
|
|
365
|
+
*
|
|
366
|
+
* 以前は手で並べており、描画側が `dashed` を足した時にここだけ取り残されて「線種が
|
|
367
|
+
* 読めません」 で落ちた (実測)。 色名 (`TONE_VALID`) と同じく描画側を出どころにする。
|
|
334
368
|
*
|
|
335
|
-
* JSON 経路も同じ集合を読む (#1304)。
|
|
369
|
+
* JSON 経路も同じ集合を読む (#1304)。 別に持つと、線種が増えた時に片方だけ取り残される。
|
|
336
370
|
*/
|
|
337
|
-
export const STYLE_VALID: ReadonlySet<string> = new Set<string>(
|
|
371
|
+
export const STYLE_VALID: ReadonlySet<string> = new Set<string>(EDGE_STYLES);
|
|
338
372
|
|
|
339
373
|
/**
|
|
340
374
|
* 色の名前として書ける語の一覧 (#1304)。 知らせの `hint` に出す。
|
|
@@ -391,6 +425,7 @@ export function parseTextDslV05(src: string): V05ParseResult {
|
|
|
391
425
|
let type: PresetType | null = null;
|
|
392
426
|
let eyebrow: string | null = null;
|
|
393
427
|
let eyebrowLine = 0;
|
|
428
|
+
let reveal: EdgeReveal | null = null;
|
|
394
429
|
let axes: DslAxes | undefined = undefined;
|
|
395
430
|
let axesLine = 0;
|
|
396
431
|
let actors: DslActor[] = [];
|
|
@@ -399,6 +434,8 @@ export function parseTextDslV05(src: string): V05ParseResult {
|
|
|
399
434
|
const values: DslValue[] = [];
|
|
400
435
|
let viewport: DslViewport | undefined = undefined;
|
|
401
436
|
let lanesMap: Record<string, DslLane> | undefined = undefined;
|
|
437
|
+
// 動いている間の帯 (#1466)。 順序図だけが読む
|
|
438
|
+
let bands: DslBand[] | undefined = undefined;
|
|
402
439
|
let readoutsList: DslReadout[] | undefined = undefined;
|
|
403
440
|
let inputsList: DslInput[] | undefined = undefined;
|
|
404
441
|
let formulasList: DslFormula[] | undefined = undefined;
|
|
@@ -432,6 +469,29 @@ export function parseTextDslV05(src: string): V05ParseResult {
|
|
|
432
469
|
i += 1;
|
|
433
470
|
continue;
|
|
434
471
|
}
|
|
472
|
+
if (head.key === "reveal") {
|
|
473
|
+
/*
|
|
474
|
+
* 矢印をいつ出すか (#1470)。
|
|
475
|
+
*
|
|
476
|
+
* 既定 (`phase`) は「段が名指しする矢印は、その段が来るまで描かない」。 段を進めるごとに
|
|
477
|
+
* 関係が増える図で、全ての矢印が 1 段目から見えていたことへの対処 (`cdl#582`)。
|
|
478
|
+
* `all` と書くと段に関わらず最初から全部描く。
|
|
479
|
+
*/
|
|
480
|
+
const v = (head.value ?? "").trim();
|
|
481
|
+
if (v.length > 0) {
|
|
482
|
+
if ((EDGE_REVEALS as readonly string[]).includes(v)) {
|
|
483
|
+
reveal = v as EdgeReveal;
|
|
484
|
+
} else {
|
|
485
|
+
errors.push({
|
|
486
|
+
line: line.no,
|
|
487
|
+
message: `reveal が読めません (書いた値: ${v})`,
|
|
488
|
+
hint: `使える語 = ${EDGE_REVEALS.join(" / ")}`,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
i += 1;
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
435
495
|
if (head.key === "eyebrow") {
|
|
436
496
|
// 空で書いた形 (`eyebrow:`) は「書かなかった」 と同じにする。 空文字を残すと
|
|
437
497
|
// 描画側が中身のない帯を出す
|
|
@@ -640,6 +700,31 @@ export function parseTextDslV05(src: string): V05ParseResult {
|
|
|
640
700
|
i = next;
|
|
641
701
|
continue;
|
|
642
702
|
}
|
|
703
|
+
if (head.key === "bands") {
|
|
704
|
+
/*
|
|
705
|
+
* 動いている間の帯 (#1466)。 `- DB: 1..2` の形で、段の番号の区間を書く。
|
|
706
|
+
*
|
|
707
|
+
* 面ごとに 2 行以上書ける = 途中で手が空く面はそこで切れる。 書かない図は
|
|
708
|
+
* 組み立て器が「最初に関わった段から最後まで」 の 1 本にする。
|
|
709
|
+
*/
|
|
710
|
+
const { items, next } = collectIndentedList(lines, i + 1, line.indent);
|
|
711
|
+
bands = [];
|
|
712
|
+
for (const it of items) {
|
|
713
|
+
// 一覧の読み手が先頭の `- ` を落とす形と落とさない形の両方を受ける
|
|
714
|
+
const m = it.trimmed.match(/^(?:-\s*)?(.+?)\s*:\s*(\d+)\s*\.\.\s*(\d+)\s*$/);
|
|
715
|
+
if (!m) {
|
|
716
|
+
errors.push({
|
|
717
|
+
line: it.no,
|
|
718
|
+
message: `帯の書き方が読めません: "${it.trimmed}"`,
|
|
719
|
+
hint: "use `- DB: 1..2` (面の名前と、段の番号の区間)",
|
|
720
|
+
});
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
723
|
+
bands.push({ actor: m[1]!, from: Number(m[2]), to: Number(m[3]) });
|
|
724
|
+
}
|
|
725
|
+
i = next;
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
643
728
|
if (head.key === "lanes") {
|
|
644
729
|
// lanes:\n l1: { x: 0, width: 320, label: "..." }\n l2: { ... }
|
|
645
730
|
const { items, next } = collectIndentedList(lines, i + 1, line.indent);
|
|
@@ -880,6 +965,7 @@ export function parseTextDslV05(src: string): V05ParseResult {
|
|
|
880
965
|
title: title!,
|
|
881
966
|
type: type!,
|
|
882
967
|
...(eyebrow !== null ? { eyebrow, eyebrowPos: { line: eyebrowLine } } : {}),
|
|
968
|
+
...(reveal !== null ? { reveal } : {}),
|
|
883
969
|
...(axes !== undefined ? { axes, axesPos: { line: axesLine } } : {}),
|
|
884
970
|
actors,
|
|
885
971
|
flow,
|
|
@@ -887,6 +973,7 @@ export function parseTextDslV05(src: string): V05ParseResult {
|
|
|
887
973
|
...(values.length > 0 ? { values } : {}),
|
|
888
974
|
viewport,
|
|
889
975
|
lanes: lanesMap,
|
|
976
|
+
...(bands && bands.length > 0 ? { bands } : {}),
|
|
890
977
|
readouts: readoutsList,
|
|
891
978
|
inputs: inputsList,
|
|
892
979
|
formulas: formulasList,
|
|
@@ -2376,6 +2463,11 @@ function applyContinuationLines(actor: DslActor, rest: Line[], errors: DslError[
|
|
|
2376
2463
|
case "値":
|
|
2377
2464
|
out.value = stripQuotes(raw);
|
|
2378
2465
|
break;
|
|
2466
|
+
// 前の時点の値 (#1450)。 内訳を帯で示す図と値 1 つを大きく示す図が読む
|
|
2467
|
+
case "previous":
|
|
2468
|
+
case "前の値":
|
|
2469
|
+
out.previous = stripQuotes(raw);
|
|
2470
|
+
break;
|
|
2379
2471
|
case "shape":
|
|
2380
2472
|
case "図形":
|
|
2381
2473
|
out.shape = 図形として読む(raw, ln.no, errors);
|
|
@@ -2413,6 +2505,22 @@ function applyContinuationLines(actor: DslActor, rest: Line[], errors: DslError[
|
|
|
2413
2505
|
.map((x) => stripQuotes(x.trim()))
|
|
2414
2506
|
.filter(Boolean);
|
|
2415
2507
|
break;
|
|
2508
|
+
/*
|
|
2509
|
+
* 行頭の印 (#1466)。 `rows` と同じ並びで、空文字はその行に印を付けない。
|
|
2510
|
+
*
|
|
2511
|
+
* **語の意味は図の種類が決める**。 ER は `pk` / `fk` / `opt`、状態遷移は
|
|
2512
|
+
* `entry` / `exit` / `do` / `internal`。 印の 2 軸 (形 × 塗り) は共通だが、その軸が
|
|
2513
|
+
* 何を指すかは種類ごとに違う = 1 つの語彙に畳むと、どの図でも意味が合わない語が残る。
|
|
2514
|
+
*
|
|
2515
|
+
* 空の要素を捨てない (`filter(Boolean)` を掛けない) = 並びが `rows` とずれる。
|
|
2516
|
+
*/
|
|
2517
|
+
case "marks":
|
|
2518
|
+
case "印":
|
|
2519
|
+
out.marks = raw
|
|
2520
|
+
.replace(/^\[|\]$/g, "")
|
|
2521
|
+
.split(/,(?![^[]*\])/)
|
|
2522
|
+
.map((x) => stripQuotes(x.trim()));
|
|
2523
|
+
break;
|
|
2416
2524
|
case "位置":
|
|
2417
2525
|
case "pos": {
|
|
2418
2526
|
// `位置: 300,200` の形。 posX と posY は両方揃わないと効かないので、 1 つの項目に
|
|
@@ -2572,8 +2680,14 @@ export const ACTOR_ITEM_KEYS: ReadonlySet<string> = new Set([
|
|
|
2572
2680
|
"補足",
|
|
2573
2681
|
"value",
|
|
2574
2682
|
"値",
|
|
2683
|
+
// 前の時点の値 (#1450)。 内訳の変化を帯で示す図と、値 1 つを大きく示す図が読む
|
|
2684
|
+
"previous",
|
|
2685
|
+
"前の値",
|
|
2575
2686
|
"rows",
|
|
2576
2687
|
"行",
|
|
2688
|
+
// 行頭の印 (#1466)。 `rows` と同じ並びで、形 × 塗り の 2 軸を語で書く
|
|
2689
|
+
"marks",
|
|
2690
|
+
"印",
|
|
2577
2691
|
// 箱の中に描く図形 (#1374)
|
|
2578
2692
|
"shape",
|
|
2579
2693
|
"図形",
|
|
@@ -2736,7 +2850,9 @@ const ACTOR_RESERVED_FIELDS: ReadonlySet<string> = new Set([
|
|
|
2736
2850
|
"subtitle",
|
|
2737
2851
|
"eyebrow",
|
|
2738
2852
|
"value",
|
|
2853
|
+
"previous",
|
|
2739
2854
|
"rows",
|
|
2855
|
+
"marks",
|
|
2740
2856
|
"lane",
|
|
2741
2857
|
"stack",
|
|
2742
2858
|
"initial",
|
|
@@ -2888,7 +3004,9 @@ export const INLINE_ACTOR_ALIASES: Record<string, string> = {
|
|
|
2888
3004
|
種類: "kind",
|
|
2889
3005
|
補足: "subtitle",
|
|
2890
3006
|
値: "value",
|
|
3007
|
+
前の値: "previous",
|
|
2891
3008
|
行: "rows",
|
|
3009
|
+
印: "marks",
|
|
2892
3010
|
};
|
|
2893
3011
|
|
|
2894
3012
|
/** 中括弧に書かれた日本語の項目名を、同じ意味の英語名に寄せる (#1301) */
|
|
@@ -2910,7 +3028,9 @@ export const INLINE_ACTOR_KEYS: ReadonlySet<string> = new Set([
|
|
|
2910
3028
|
"subtitle",
|
|
2911
3029
|
"eyebrow",
|
|
2912
3030
|
"value",
|
|
3031
|
+
"previous",
|
|
2913
3032
|
"rows",
|
|
3033
|
+
"marks",
|
|
2914
3034
|
"lane",
|
|
2915
3035
|
"stack",
|
|
2916
3036
|
"initial",
|
|
@@ -2973,6 +3093,33 @@ const FLOW_INLINE_READERS = {
|
|
|
2973
3093
|
v !== undefined && (EDGE_SIDE_VALUES as readonly string[]).includes(v)
|
|
2974
3094
|
? (v as "top" | "right" | "bottom" | "left")
|
|
2975
3095
|
: undefined,
|
|
3096
|
+
// 矢印の先の形 (#1462)。 書かなければ描画側の既定 (塗った三角) になる
|
|
3097
|
+
head: (v: string | undefined) =>
|
|
3098
|
+
v !== undefined && EDGE_HEAD_VALUES.includes(v) ? (v as EdgeHead) : undefined,
|
|
3099
|
+
// 出どころ側の端の形 (#1466)。 ER は端ごとに違う個数を示すので両端に要る
|
|
3100
|
+
tailHead: (v: string | undefined) =>
|
|
3101
|
+
v !== undefined && EDGE_HEAD_VALUES.includes(v) ? (v as EdgeHead) : undefined,
|
|
3102
|
+
// 端の印の塗り (#1466)。 白抜きの菱が「持つ」、塗った菱が「抱える」
|
|
3103
|
+
headFill: (v: string | undefined) =>
|
|
3104
|
+
v !== undefined && EDGE_HEAD_FILL_VALUES.includes(v) ? (v as EdgeHeadFill) : undefined,
|
|
3105
|
+
tailHeadFill: (v: string | undefined) =>
|
|
3106
|
+
v !== undefined && EDGE_HEAD_FILL_VALUES.includes(v) ? (v as EdgeHeadFill) : undefined,
|
|
3107
|
+
/*
|
|
3108
|
+
* クラス図の関係の種類 (#1466)。 書くと **線と端の形と塗りと付く側** がまとめて決まる
|
|
3109
|
+
* (`CLASS_RELATION_LOOK`)。
|
|
3110
|
+
*
|
|
3111
|
+
* 4 つを個別に書かせない = 組合せは 6 通りしか無く、1 つでも書き違えると読み手に別の意味で
|
|
3112
|
+
* 伝わる (菱を逆に置くと持ち主が入れ替わる)。 種類で書けばその 6 通りから外れない。
|
|
3113
|
+
*/
|
|
3114
|
+
relation: (v: string | undefined) =>
|
|
3115
|
+
v !== undefined && CLASS_RELATION_VALUES.includes(v) ? (v as ClassRelationType) : undefined,
|
|
3116
|
+
/*
|
|
3117
|
+
* 順序図の言づての種類 (#1466)。 書くと線と矢の形がまとめて決まる。
|
|
3118
|
+
*
|
|
3119
|
+
* 呼ぶ (実線 + 塗った矢) / 返す (破線 + 開いた矢) / 投げる (実線 + 開いた矢) の 3 つ。
|
|
3120
|
+
*/
|
|
3121
|
+
kind: (v: string | undefined) =>
|
|
3122
|
+
v !== undefined && SEQ_MESSAGE_VALUES.includes(v) ? (v as SequenceMessageKind) : undefined,
|
|
2976
3123
|
/*
|
|
2977
3124
|
* 矢印を値に追随させる 3 欄 (#1396)。 箱の `wBind` (#1392) と同じく文字列だけを取る。
|
|
2978
3125
|
*
|
|
@@ -3080,6 +3227,7 @@ function parseActor(line: Line, errors: DslError[]): DslActor | null {
|
|
|
3080
3227
|
owner: isPart ? undefined : opts.owner,
|
|
3081
3228
|
end: isPart ? undefined : opts.end,
|
|
3082
3229
|
value: opts.value,
|
|
3230
|
+
previous: opts.previous,
|
|
3083
3231
|
rows: opts.rows
|
|
3084
3232
|
? opts.rows
|
|
3085
3233
|
.replace(/^\[|\]$/g, "")
|
|
@@ -3087,6 +3235,13 @@ function parseActor(line: Line, errors: DslError[]): DslActor | null {
|
|
|
3087
3235
|
.map((x) => stripQuotes(x.trim()))
|
|
3088
3236
|
.filter(Boolean)
|
|
3089
3237
|
: undefined,
|
|
3238
|
+
// 行頭の印 (#1466)。 `rows` と同じ並びなので **空の要素を捨てない**
|
|
3239
|
+
marks: opts.marks
|
|
3240
|
+
? opts.marks
|
|
3241
|
+
.replace(/^\[|\]$/g, "")
|
|
3242
|
+
.split(/,(?![^[]*\])/)
|
|
3243
|
+
.map((x) => stripQuotes(x.trim()))
|
|
3244
|
+
: undefined,
|
|
3090
3245
|
lane: opts.lane,
|
|
3091
3246
|
// 箱の中に描く図形 (#1374)。 パーツでは状態の上書きとして意味を持つため横取りしない
|
|
3092
3247
|
shape:
|
|
@@ -3219,6 +3374,26 @@ function parseFlowStep(line: Line, no: number, errors: DslError[]): DslStep | nu
|
|
|
3219
3374
|
hint: `使える値 = ${EDGE_SIDE_VALUES.join(", ")}`,
|
|
3220
3375
|
});
|
|
3221
3376
|
}
|
|
3377
|
+
// 読めない語を黙って捨てない (#1462)。 捨てると「書いたのに端の形が変わらない」 が
|
|
3378
|
+
// 手掛かりなしで起きる
|
|
3379
|
+
// 読めない語を黙って捨てない (#1462 / #1466)。 捨てると「書いたのに見た目が変わらない」 が
|
|
3380
|
+
// 手掛かりなしで起きる。 端の 3 欄と関係の種類を同じ形で見る
|
|
3381
|
+
for (const [欄, 使える] of [
|
|
3382
|
+
["head", EDGE_HEAD_VALUES],
|
|
3383
|
+
["tailHead", EDGE_HEAD_VALUES],
|
|
3384
|
+
["headFill", EDGE_HEAD_FILL_VALUES],
|
|
3385
|
+
["tailHeadFill", EDGE_HEAD_FILL_VALUES],
|
|
3386
|
+
["relation", CLASS_RELATION_VALUES],
|
|
3387
|
+
["kind", SEQ_MESSAGE_VALUES],
|
|
3388
|
+
] as const) {
|
|
3389
|
+
if (opts[欄] !== undefined && 中括弧[欄] === undefined) {
|
|
3390
|
+
errors.push({
|
|
3391
|
+
line: line.no,
|
|
3392
|
+
message: `矢印の ${欄} が読めません: "${opts[欄]}"`,
|
|
3393
|
+
hint: `使える値 = ${使える.join(", ")}`,
|
|
3394
|
+
});
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3222
3397
|
数と真偽 = 表で読む(FLOW_INLINE_VALUE_KINDS, opts, "矢印の ", line.no, errors);
|
|
3223
3398
|
rest = 塊.前.trim();
|
|
3224
3399
|
}
|
|
@@ -3226,6 +3401,12 @@ function parseFlowStep(line: Line, no: number, errors: DslError[]): DslStep | nu
|
|
|
3226
3401
|
const guard = 中括弧.guard as string | undefined;
|
|
3227
3402
|
const cardinality = 中括弧.cardinality as string | undefined;
|
|
3228
3403
|
const side = 中括弧.side as "top" | "right" | "bottom" | "left" | undefined;
|
|
3404
|
+
const head = 中括弧.head as EdgeHead | undefined;
|
|
3405
|
+
const tailHead = 中括弧.tailHead as EdgeHead | undefined;
|
|
3406
|
+
const headFill = 中括弧.headFill as EdgeHeadFill | undefined;
|
|
3407
|
+
const tailHeadFill = 中括弧.tailHeadFill as EdgeHeadFill | undefined;
|
|
3408
|
+
const relation = 中括弧.relation as ClassRelationType | undefined;
|
|
3409
|
+
const msgKind = 中括弧.kind as SequenceMessageKind | undefined;
|
|
3229
3410
|
// 値に追随する 3 欄 (#1396)。 空は捨てずに知らせる = 描画側は空文字を既定値へ落とさず
|
|
3230
3411
|
// そのまま置換に使うため、書き忘れが「線が消えた」 形で出る
|
|
3231
3412
|
const widthBind = 追随する大きさとして読む(
|
|
@@ -3306,6 +3487,12 @@ function parseFlowStep(line: Line, no: number, errors: DslError[]): DslStep | nu
|
|
|
3306
3487
|
guard,
|
|
3307
3488
|
cardinality,
|
|
3308
3489
|
side,
|
|
3490
|
+
head,
|
|
3491
|
+
tailHead,
|
|
3492
|
+
headFill,
|
|
3493
|
+
tailHeadFill,
|
|
3494
|
+
relation,
|
|
3495
|
+
msgKind,
|
|
3309
3496
|
widthBind,
|
|
3310
3497
|
strokeBind,
|
|
3311
3498
|
dashOffsetBind,
|
|
@@ -3512,7 +3699,10 @@ function parsePhase(block: Line[], errors: DslError[]): DslPhase | null {
|
|
|
3512
3699
|
continue;
|
|
3513
3700
|
}
|
|
3514
3701
|
if (key === "draw") {
|
|
3515
|
-
|
|
3702
|
+
// `draw: line 0.4` = 語の後ろに「描き終えるまでに段の何割を使うか」 を書ける (#1441)。
|
|
3703
|
+
// 割合を別の項目にすると「割合だけ書いて `draw` が無い段」 が書けてしまい、
|
|
3704
|
+
// 何も起きない指定になる。 同じ行なら書けない
|
|
3705
|
+
const [語 = "", 割合の文字, ...余り] = stripQuotes(value).trim().split(/\s+/);
|
|
3516
3706
|
// **読めない語を黙って捨てない** (#1304 / #1306 と同じ扱い)。 受ける語は 1 つだけで、
|
|
3517
3707
|
// 書き間違いはその段が何も描かない形になって手掛かりが残らない
|
|
3518
3708
|
if (!DRAW_WORDS.has(語)) {
|
|
@@ -3521,9 +3711,29 @@ function parsePhase(block: Line[], errors: DslError[]): DslPhase | null {
|
|
|
3521
3711
|
message: `draw に書けない語です: "${語}"`,
|
|
3522
3712
|
hint: `使える語 = ${[...DRAW_WORDS].join(", ")}`,
|
|
3523
3713
|
});
|
|
3714
|
+
} else if (余り.length > 0) {
|
|
3715
|
+
errors.push({
|
|
3716
|
+
line: ln.no,
|
|
3717
|
+
message: `draw に書ける項目は語と割合の 2 つまでです: "${stripQuotes(value).trim()}"`,
|
|
3718
|
+
hint: "use `draw: line 0.4`",
|
|
3719
|
+
});
|
|
3524
3720
|
} else {
|
|
3525
3721
|
phase.draw = 語;
|
|
3526
3722
|
phase.drawPos = { line: ln.no };
|
|
3723
|
+
if (割合の文字 !== undefined) {
|
|
3724
|
+
const 割合 = Number(割合の文字);
|
|
3725
|
+
// 範囲外を黙って捨てない。 描画側は 1 に落として図を出すため、
|
|
3726
|
+
// 知らせが無いと「書いたのに速さが変わらない」 が手掛かりなしで起きる
|
|
3727
|
+
if (!Number.isFinite(割合) || 割合 <= 0 || 割合 > 1) {
|
|
3728
|
+
errors.push({
|
|
3729
|
+
line: ln.no,
|
|
3730
|
+
message: `draw の割合が範囲外です: "${割合の文字}"`,
|
|
3731
|
+
hint: "0 より大きく 1 以下で書きます (例 `draw: line 0.4`)",
|
|
3732
|
+
});
|
|
3733
|
+
} else {
|
|
3734
|
+
phase.drawRatio = 割合;
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3527
3737
|
}
|
|
3528
3738
|
i += 1;
|
|
3529
3739
|
continue;
|