@cardenelabs/dragon 0.18.3 → 0.19.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/src/types.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  import type { CdlDiagram, NodeKind, Tone, EdgeStyle, EdgeHead, EdgeHeadFill, EdgeReveal, ClassRelationType, SequenceMessageKind } from "@cardenelabs/cdl";
7
7
  import type { DslOnlyKind } from "./v05/parser";
8
- import type { DslDirection } from "./keywords";
8
+ import type { DslDirection, DslPalette } from "./keywords";
9
9
 
10
10
  /**
11
11
  * 記法が書ける箱の種類 (#1420)。
@@ -178,6 +178,13 @@ export type DslDocument = {
178
178
  direction?: DslDirection;
179
179
  /** `direction:` を書いた行。 効かない時の知らせで、書いた場所を指すために持つ */
180
180
  directionPos?: { line: number };
181
+ /**
182
+ * 図の配色 (`palette:`、 #1553)。
183
+ *
184
+ * 名前だけを持つ。 実際の色は消費側 (`cdl-theme.css`) が決めるので、ここには値を書かない。
185
+ * ER 図は書かなくても `kinari` (生成りに茶) になる = 別の色みにしたい時だけ書く。
186
+ */
187
+ palette?: DslPalette;
181
188
  groups?: Record<string, DslGroup>;
182
189
  /**
183
190
  * 値を見せる部品 (`readouts:`、 #1374)。 割合の輪や数え上げを図の脇に出す。
@@ -480,6 +487,10 @@ export type DslStep = {
480
487
  * `kind` にしないのは、箱の種類 (`DslActor.kind`) と同じ語が別の意味を持つため。
481
488
  */
482
489
  msgKind?: SequenceMessageKind;
490
+ /** 辺の役目 (cdl#618)。 `main` を書いた辺だけ「いま」 の色で引く */
491
+ role?: "main";
492
+ /** 名前の下地を敷くか (cdl#618)。 書かなければ敷く */
493
+ labelPlate?: boolean;
483
494
  labelOffsetX?: number;
484
495
  labelOffsetY?: number;
485
496
  /** true で説明文を矢印の線の上に重ねる。 分岐図の条件ラベル用。 */
package/src/v05/parser.ts CHANGED
@@ -44,7 +44,8 @@
44
44
  import type { NodeKind, Tone, EdgeStyle, EdgeHead, EdgeHeadFill, ClassRelationType, SequenceMessageKind } from "@cardenelabs/cdl";
45
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
46
  import type { EdgeReveal } from "@cardenelabs/cdl";
47
- import { TONE_ALIAS, NODE_KIND_ALIAS, DIRECTIONS, resolveDirection } from "../keywords";
47
+ import { TONE_ALIAS, NODE_KIND_ALIAS, DIRECTIONS, resolveDirection, PALETTES, resolvePalette } from "../keywords";
48
+ import type { DslPalette } from "../keywords";
48
49
  import type { DslDirection } from "../keywords";
49
50
  import { parseRelativePos, orderByDependency } from "../relative-pos";
50
51
  import {
@@ -96,6 +97,22 @@ export const EDGE_HEAD_VALUES: readonly string[] = EDGE_HEADS;
96
97
  /** 端の印の塗り方 (#1466)。 描画側の一覧から導く = 描画側が増やせば書ける */
97
98
  export const EDGE_HEAD_FILL_VALUES: readonly string[] = EDGE_HEAD_FILLS;
98
99
 
100
+ /**
101
+ * 辺の役目として書ける語 (#1559)。
102
+ *
103
+ * 読み手と公開 schema の両方がここを見る。 語を 2 か所に書くと、記法では通るのに JSON では
104
+ * 弾かれる (逆も) 形が黙って生まれる。
105
+ */
106
+ export const EDGE_ROLE_VALUES = ["main"] as const;
107
+
108
+ /**
109
+ * 図形の向きとして書ける語 (#1561)。
110
+ *
111
+ * 読み手と、読めなかった時の案内と、公開 schema の 3 か所がここを見る。 値を直に書くと、
112
+ * 語を足した時にどれかが取り残される (実測 = 読み手と案内で同じ 4 語を 2 度書いていた)。
113
+ */
114
+ export const SHAPE_ORIENT_VALUES = ["up", "down", "left", "right"] as const;
115
+
99
116
  /**
100
117
  * クラス図の関係の種類 (#1466)。 描画側の表 (`CLASS_RELATION_LOOK`) の key から導く。
101
118
  *
@@ -153,6 +170,15 @@ export const TOP_LEVEL_KEYS = [
153
170
  * 日本語で書けるので、書き手が自然に言う語 (`縦` / `横`) を残せる。
154
171
  */
155
172
  "direction",
173
+ /*
174
+ * 図の配色 (#1553)。
175
+ *
176
+ * cdl は色を持たないので、名前だけを図に載せる。 消費側 (`cdl-theme.css`) が名前を見て
177
+ * 7 つの口 (台 / 行の面 / 縞 / 枠 / 字 / 型名 / 線) に色を当てる。
178
+ *
179
+ * ER 図は書かなくても `kinari` になる = 別の色みにしたい時だけ書く。
180
+ */
181
+ "palette",
156
182
  ] as const;
157
183
 
158
184
  /**
@@ -440,6 +466,7 @@ export function parseTextDslV05(src: string): V05ParseResult {
440
466
  let reveal: EdgeReveal | null = null;
441
467
  let direction: DslDirection | null = null;
442
468
  let directionLine = 0;
469
+ let palette: DslPalette | null = null;
443
470
  let axes: DslAxes | undefined = undefined;
444
471
  let axesLine = 0;
445
472
  let actors: DslActor[] = [];
@@ -532,6 +559,29 @@ export function parseTextDslV05(src: string): V05ParseResult {
532
559
  i += 1;
533
560
  continue;
534
561
  }
562
+ if (head.key === "palette") {
563
+ /*
564
+ * 図の配色 (#1553)。
565
+ *
566
+ * 読めない語はその場で知らせる。 黙って既定に落とすと、書き手には「書いたのに効かない」
567
+ * としか見えず、書き間違いか未対応かを分けられない。
568
+ */
569
+ const v = (head.value ?? "").trim();
570
+ if (v.length > 0) {
571
+ const 解けた = resolvePalette(v);
572
+ if (解けた !== null) {
573
+ palette = 解けた;
574
+ } else {
575
+ errors.push({
576
+ line: line.no,
577
+ message: `palette が読めません (書いた値: ${v})`,
578
+ hint: `使える語 = ${PALETTES.join(" / ")} / 生成り / 青磁`,
579
+ });
580
+ }
581
+ }
582
+ i += 1;
583
+ continue;
584
+ }
535
585
  if (head.key === "eyebrow") {
536
586
  // 空で書いた形 (`eyebrow:`) は「書かなかった」 と同じにする。 空文字を残すと
537
587
  // 描画側が中身のない帯を出す
@@ -1007,6 +1057,7 @@ export function parseTextDslV05(src: string): V05ParseResult {
1007
1057
  ...(eyebrow !== null ? { eyebrow, eyebrowPos: { line: eyebrowLine } } : {}),
1008
1058
  ...(reveal !== null ? { reveal } : {}),
1009
1059
  ...(direction !== null ? { direction, directionPos: { line: directionLine } } : {}),
1060
+ ...(palette !== null ? { palette } : {}),
1010
1061
  ...(axes !== undefined ? { axes, axesPos: { line: axesLine } } : {}),
1011
1062
  actors,
1012
1063
  flow,
@@ -1655,12 +1706,12 @@ function 表に従って読む(
1655
1706
  });
1656
1707
  }
1657
1708
  } else if (形 === "向き") {
1658
- if (["up", "down", "left", "right"].includes(値)) out[欄] = 値;
1709
+ if ((SHAPE_ORIENT_VALUES as readonly string[]).includes(値)) out[欄] = 値;
1659
1710
  else {
1660
1711
  errors.push({
1661
1712
  line,
1662
1713
  message: `${接頭}${欄} の向きが読めません: "${値}"`,
1663
- hint: "使える値 = up, down, left, right",
1714
+ hint: `使える値 = ${SHAPE_ORIENT_VALUES.join(", ")}`,
1664
1715
  });
1665
1716
  }
1666
1717
  } else {
@@ -3129,6 +3180,23 @@ const FLOW_INLINE_READERS = {
3129
3180
  sub: (v: string | undefined) => v,
3130
3181
  guard: (v: string | undefined) => v,
3131
3182
  cardinality: (v: string | undefined) => v,
3183
+ /*
3184
+ * 辺の役目 (cdl#618)。 `main` を書いた辺だけ「いま」 の色で引く。
3185
+ *
3186
+ * 図の中に道が 2 種 (主となる 1 本と、そこから枝分かれする先) ある時、どちらも同じ色だと
3187
+ * どこから読むかが決まらない。 主となる 1 本 (または 1 続き) にだけ書く。
3188
+ */
3189
+ role: (v: string | undefined) =>
3190
+ v !== undefined && (EDGE_ROLE_VALUES as readonly string[]).includes(v)
3191
+ ? (v as "main")
3192
+ : undefined,
3193
+ /*
3194
+ * 名前の下地を敷くか (cdl#618)。 書かなければ敷く。
3195
+ *
3196
+ * 丸い下地は箱と同じ形なので、罫の細い図では名前が小さな箱に見える。
3197
+ */
3198
+ labelPlate: (v: string | undefined) =>
3199
+ v === undefined ? undefined : v !== "false" && v !== "なし",
3132
3200
  // 矢印がどの辺から出るか (#1385)。 描画側は 4 方向を取り、書かなければ自動で選ぶ
3133
3201
  side: (v: string | undefined) =>
3134
3202
  v !== undefined && (EDGE_SIDE_VALUES as readonly string[]).includes(v)
@@ -3448,6 +3516,9 @@ function parseFlowStep(line: Line, no: number, errors: DslError[]): DslStep | nu
3448
3516
  const tailHeadFill = 中括弧.tailHeadFill as EdgeHeadFill | undefined;
3449
3517
  const relation = 中括弧.relation as ClassRelationType | undefined;
3450
3518
  const msgKind = 中括弧.kind as SequenceMessageKind | undefined;
3519
+ // 辺の役目と名前の下地 (cdl#618)
3520
+ const role = 中括弧.role as "main" | undefined;
3521
+ const labelPlate = 中括弧.labelPlate as boolean | undefined;
3451
3522
  // 値に追随する 3 欄 (#1396)。 空は捨てずに知らせる = 描画側は空文字を既定値へ落とさず
3452
3523
  // そのまま置換に使うため、書き忘れが「線が消えた」 形で出る
3453
3524
  const widthBind = 追随する大きさとして読む(
@@ -3534,6 +3605,8 @@ function parseFlowStep(line: Line, no: number, errors: DslError[]): DslStep | nu
3534
3605
  tailHeadFill,
3535
3606
  relation,
3536
3607
  msgKind,
3608
+ role,
3609
+ labelPlate,
3537
3610
  widthBind,
3538
3611
  strokeBind,
3539
3612
  dashOffsetBind,