@cardenelabs/dragon 0.11.0 → 0.12.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/dragon",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Dragon — Mermaid 感覚で animated SVG を生成する Text DSL。 cdl engine を内部利用。",
5
5
  "license": "MIT",
6
6
  "author": "cardene777",
@@ -56,7 +56,7 @@
56
56
  "prepublishOnly": "pnpm run typecheck && pnpm run test && pnpm run build"
57
57
  },
58
58
  "dependencies": {
59
- "@cardenelabs/cdl": "^0.13.1"
59
+ "@cardenelabs/cdl": "^0.14.0"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "react": "^19.0.0",
package/src/v05/parser.ts CHANGED
@@ -1069,24 +1069,63 @@ function writtenScaleFields(inner: string): Map<string, string> {
1069
1069
  *
1070
1070
  * `parseInlineMapping` と、倍率の「書かれた名前」 を拾う経路 (#1026) で共用する。
1071
1071
  * 割り方を 2 つ持つと、片方だけが拾える項目という食い違いが生まれる。
1072
+ *
1073
+ * **引用符の中のカンマでは割らない** (#1367)。 見ていなかった間、`{ subtitle: "a, b" }` の
1074
+ * 補足が `"a` に切れて図に出ていた (実測で見本 1 件が踏んでいた)。 配列
1075
+ * (`{ initial: '["入力", "確認"]' }`) が壊れていなかったのは角括弧の深さで守られていたためで、
1076
+ * 引用符だけで守られる値は守られていなかった。
1072
1077
  */
1073
1078
  function splitInlineFields(inner: string): string[] {
1074
- let depth = 0;
1075
- let buf = "";
1076
- const parts: string[] = [];
1077
- for (let i = 0; i < inner.length; i += 1) {
1078
- const c = inner[i]!;
1079
- if (c === "[" || c === "{") depth += 1;
1080
- else if (c === "]" || c === "}") depth -= 1;
1081
- if (c === "," && depth === 0) {
1082
- parts.push(buf);
1083
- buf = "";
1084
- continue;
1079
+ const 引用符を見て割る = (見る: boolean): { parts: string[]; 閉じた: boolean } => {
1080
+ let depth = 0;
1081
+ let 引用符: '"' | "'" | null = null;
1082
+ let 直前: string | null = null;
1083
+ let buf = "";
1084
+ const parts: string[] = [];
1085
+ for (let i = 0; i < inner.length; i += 1) {
1086
+ const c = inner[i]!;
1087
+ if (見る) {
1088
+ if (引用符 !== null) {
1089
+ // 二重引用の中では、逃がした引用符を終端と取り違えない
1090
+ if (引用符 === '"' && c === "\\" && i + 1 < inner.length) {
1091
+ buf += c;
1092
+ i += 1;
1093
+ buf += inner[i]!;
1094
+ continue;
1095
+ }
1096
+ // **開いた記号と同じものだけが閉じる**。 `"Guns N' Roses"` の `'` は文字として残す
1097
+ if (c === 引用符) 引用符 = null;
1098
+ buf += c;
1099
+ continue;
1100
+ }
1101
+ // 値の途中の apostrophe まで開始記号にすると、別 field まで引用内として飲み込む
1102
+ if ((c === '"' || c === "'") && (直前 === null || ":,{[".includes(直前))) {
1103
+ 引用符 = c;
1104
+ 直前 = c;
1105
+ buf += c;
1106
+ continue;
1107
+ }
1108
+ }
1109
+ if (c === "[" || c === "{") depth += 1;
1110
+ else if (c === "]" || c === "}") depth -= 1;
1111
+ if (c === "," && depth === 0) {
1112
+ parts.push(buf);
1113
+ buf = "";
1114
+ 直前 = c;
1115
+ continue;
1116
+ }
1117
+ buf += c;
1118
+ if (c !== " " && c !== "\t") 直前 = c;
1085
1119
  }
1086
- buf += c;
1087
- }
1088
- if (buf.trim()) parts.push(buf);
1089
- return parts;
1120
+ if (buf.trim()) parts.push(buf);
1121
+ return { parts, 閉じた: 引用符 === null };
1122
+ };
1123
+
1124
+ const 見た = 引用符を見て割る(true);
1125
+ // **閉じない引用符が残ったらこれまでどおりに割る** (#1367)。 壊れた入力で挙動が変わると、
1126
+ // 今まで通っていた書き方が黙って別の結果になる。 実測では見本 9832 件の中括弧のうち
1127
+ // 閉じない形は 0 件で、この経路は保険
1128
+ return 見た.閉じた ? 見た.parts : 引用符を見て割る(false).parts;
1090
1129
  }
1091
1130
 
1092
1131
  function collectIndentedList(