schematex 0.1.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.
Files changed (181) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +379 -0
  3. package/dist/chunk-2MQWZ2XY.cjs +453 -0
  4. package/dist/chunk-2MQWZ2XY.cjs.map +1 -0
  5. package/dist/chunk-2UKC6ZCY.cjs +1803 -0
  6. package/dist/chunk-2UKC6ZCY.cjs.map +1 -0
  7. package/dist/chunk-34X3ZJ6E.cjs +783 -0
  8. package/dist/chunk-34X3ZJ6E.cjs.map +1 -0
  9. package/dist/chunk-3FTUWAXK.cjs +1220 -0
  10. package/dist/chunk-3FTUWAXK.cjs.map +1 -0
  11. package/dist/chunk-3J7TFUOC.js +745 -0
  12. package/dist/chunk-3J7TFUOC.js.map +1 -0
  13. package/dist/chunk-47ZC6EMJ.js +1009 -0
  14. package/dist/chunk-47ZC6EMJ.js.map +1 -0
  15. package/dist/chunk-4DBRNOPA.cjs +750 -0
  16. package/dist/chunk-4DBRNOPA.cjs.map +1 -0
  17. package/dist/chunk-4G7ZIBHN.js +778 -0
  18. package/dist/chunk-4G7ZIBHN.js.map +1 -0
  19. package/dist/chunk-5C7DPDHQ.js +1321 -0
  20. package/dist/chunk-5C7DPDHQ.js.map +1 -0
  21. package/dist/chunk-ADOXGKAK.js +1251 -0
  22. package/dist/chunk-ADOXGKAK.js.map +1 -0
  23. package/dist/chunk-BE5HNDA5.cjs +874 -0
  24. package/dist/chunk-BE5HNDA5.cjs.map +1 -0
  25. package/dist/chunk-CZRM7LT7.js +889 -0
  26. package/dist/chunk-CZRM7LT7.js.map +1 -0
  27. package/dist/chunk-D4JTSPOL.js +1795 -0
  28. package/dist/chunk-D4JTSPOL.js.map +1 -0
  29. package/dist/chunk-DS47NTWZ.cjs +1034 -0
  30. package/dist/chunk-DS47NTWZ.cjs.map +1 -0
  31. package/dist/chunk-FDLZEKEB.js +449 -0
  32. package/dist/chunk-FDLZEKEB.js.map +1 -0
  33. package/dist/chunk-FGPTCDUT.cjs +1851 -0
  34. package/dist/chunk-FGPTCDUT.cjs.map +1 -0
  35. package/dist/chunk-HDKDQAEQ.cjs +86 -0
  36. package/dist/chunk-HDKDQAEQ.cjs.map +1 -0
  37. package/dist/chunk-IX554O5K.js +346 -0
  38. package/dist/chunk-IX554O5K.js.map +1 -0
  39. package/dist/chunk-KLJEK547.js +71 -0
  40. package/dist/chunk-KLJEK547.js.map +1 -0
  41. package/dist/chunk-LMFSHK45.js +1028 -0
  42. package/dist/chunk-LMFSHK45.js.map +1 -0
  43. package/dist/chunk-MDICUK6F.cjs +1258 -0
  44. package/dist/chunk-MDICUK6F.cjs.map +1 -0
  45. package/dist/chunk-N7KOXOMX.cjs +363 -0
  46. package/dist/chunk-N7KOXOMX.cjs.map +1 -0
  47. package/dist/chunk-NYCIK4SU.cjs +775 -0
  48. package/dist/chunk-NYCIK4SU.cjs.map +1 -0
  49. package/dist/chunk-PDPHRZZT.js +770 -0
  50. package/dist/chunk-PDPHRZZT.js.map +1 -0
  51. package/dist/chunk-ROFLJ74T.js +1212 -0
  52. package/dist/chunk-ROFLJ74T.js.map +1 -0
  53. package/dist/chunk-S6BK5DB6.cjs +845 -0
  54. package/dist/chunk-S6BK5DB6.cjs.map +1 -0
  55. package/dist/chunk-U4I37IBN.js +874 -0
  56. package/dist/chunk-U4I37IBN.js.map +1 -0
  57. package/dist/chunk-U5GGE6PJ.js +839 -0
  58. package/dist/chunk-U5GGE6PJ.js.map +1 -0
  59. package/dist/chunk-UHLYS3W5.cjs +1015 -0
  60. package/dist/chunk-UHLYS3W5.cjs.map +1 -0
  61. package/dist/chunk-URSKIHSY.cjs +881 -0
  62. package/dist/chunk-URSKIHSY.cjs.map +1 -0
  63. package/dist/chunk-V6WO7RK7.cjs +1056 -0
  64. package/dist/chunk-V6WO7RK7.cjs.map +1 -0
  65. package/dist/chunk-VFQCTXOX.js +869 -0
  66. package/dist/chunk-VFQCTXOX.js.map +1 -0
  67. package/dist/chunk-XQ52ICHU.cjs +895 -0
  68. package/dist/chunk-XQ52ICHU.cjs.map +1 -0
  69. package/dist/chunk-XX4BKS7Y.js +1051 -0
  70. package/dist/chunk-XX4BKS7Y.js.map +1 -0
  71. package/dist/chunk-XXU36667.js +1844 -0
  72. package/dist/chunk-XXU36667.js.map +1 -0
  73. package/dist/chunk-ZX7QKZK2.cjs +1326 -0
  74. package/dist/chunk-ZX7QKZK2.cjs.map +1 -0
  75. package/dist/diagrams/blockdiagram/index.cjs +25 -0
  76. package/dist/diagrams/blockdiagram/index.cjs.map +1 -0
  77. package/dist/diagrams/blockdiagram/index.d.cts +67 -0
  78. package/dist/diagrams/blockdiagram/index.d.ts +67 -0
  79. package/dist/diagrams/blockdiagram/index.js +4 -0
  80. package/dist/diagrams/blockdiagram/index.js.map +1 -0
  81. package/dist/diagrams/circuit/index.cjs +34 -0
  82. package/dist/diagrams/circuit/index.cjs.map +1 -0
  83. package/dist/diagrams/circuit/index.d.cts +138 -0
  84. package/dist/diagrams/circuit/index.d.ts +138 -0
  85. package/dist/diagrams/circuit/index.js +5 -0
  86. package/dist/diagrams/circuit/index.js.map +1 -0
  87. package/dist/diagrams/ecomap/index.cjs +30 -0
  88. package/dist/diagrams/ecomap/index.cjs.map +1 -0
  89. package/dist/diagrams/ecomap/index.d.cts +15 -0
  90. package/dist/diagrams/ecomap/index.d.ts +15 -0
  91. package/dist/diagrams/ecomap/index.js +5 -0
  92. package/dist/diagrams/ecomap/index.js.map +1 -0
  93. package/dist/diagrams/entity/index.cjs +26 -0
  94. package/dist/diagrams/entity/index.cjs.map +1 -0
  95. package/dist/diagrams/entity/index.d.cts +54 -0
  96. package/dist/diagrams/entity/index.d.ts +54 -0
  97. package/dist/diagrams/entity/index.js +5 -0
  98. package/dist/diagrams/entity/index.js.map +1 -0
  99. package/dist/diagrams/fishbone/index.cjs +34 -0
  100. package/dist/diagrams/fishbone/index.cjs.map +1 -0
  101. package/dist/diagrams/fishbone/index.d.cts +185 -0
  102. package/dist/diagrams/fishbone/index.d.ts +185 -0
  103. package/dist/diagrams/fishbone/index.js +5 -0
  104. package/dist/diagrams/fishbone/index.js.map +1 -0
  105. package/dist/diagrams/flowchart/index.cjs +34 -0
  106. package/dist/diagrams/flowchart/index.cjs.map +1 -0
  107. package/dist/diagrams/flowchart/index.d.cts +2 -0
  108. package/dist/diagrams/flowchart/index.d.ts +2 -0
  109. package/dist/diagrams/flowchart/index.js +5 -0
  110. package/dist/diagrams/flowchart/index.js.map +1 -0
  111. package/dist/diagrams/genogram/index.cjs +38 -0
  112. package/dist/diagrams/genogram/index.cjs.map +1 -0
  113. package/dist/diagrams/genogram/index.d.cts +20 -0
  114. package/dist/diagrams/genogram/index.d.ts +20 -0
  115. package/dist/diagrams/genogram/index.js +5 -0
  116. package/dist/diagrams/genogram/index.js.map +1 -0
  117. package/dist/diagrams/ladder/index.cjs +26 -0
  118. package/dist/diagrams/ladder/index.cjs.map +1 -0
  119. package/dist/diagrams/ladder/index.d.cts +49 -0
  120. package/dist/diagrams/ladder/index.d.ts +49 -0
  121. package/dist/diagrams/ladder/index.js +5 -0
  122. package/dist/diagrams/ladder/index.js.map +1 -0
  123. package/dist/diagrams/logic/index.cjs +26 -0
  124. package/dist/diagrams/logic/index.cjs.map +1 -0
  125. package/dist/diagrams/logic/index.d.cts +73 -0
  126. package/dist/diagrams/logic/index.d.ts +73 -0
  127. package/dist/diagrams/logic/index.js +5 -0
  128. package/dist/diagrams/logic/index.js.map +1 -0
  129. package/dist/diagrams/orgchart/index.cjs +30 -0
  130. package/dist/diagrams/orgchart/index.cjs.map +1 -0
  131. package/dist/diagrams/orgchart/index.d.cts +100 -0
  132. package/dist/diagrams/orgchart/index.d.ts +100 -0
  133. package/dist/diagrams/orgchart/index.js +5 -0
  134. package/dist/diagrams/orgchart/index.js.map +1 -0
  135. package/dist/diagrams/pedigree/index.cjs +30 -0
  136. package/dist/diagrams/pedigree/index.cjs.map +1 -0
  137. package/dist/diagrams/pedigree/index.d.cts +15 -0
  138. package/dist/diagrams/pedigree/index.d.ts +15 -0
  139. package/dist/diagrams/pedigree/index.js +5 -0
  140. package/dist/diagrams/pedigree/index.js.map +1 -0
  141. package/dist/diagrams/phylo/index.cjs +30 -0
  142. package/dist/diagrams/phylo/index.cjs.map +1 -0
  143. package/dist/diagrams/phylo/index.d.cts +32 -0
  144. package/dist/diagrams/phylo/index.d.ts +32 -0
  145. package/dist/diagrams/phylo/index.js +5 -0
  146. package/dist/diagrams/phylo/index.js.map +1 -0
  147. package/dist/diagrams/sld/index.cjs +26 -0
  148. package/dist/diagrams/sld/index.cjs.map +1 -0
  149. package/dist/diagrams/sld/index.d.cts +58 -0
  150. package/dist/diagrams/sld/index.d.ts +58 -0
  151. package/dist/diagrams/sld/index.js +5 -0
  152. package/dist/diagrams/sld/index.js.map +1 -0
  153. package/dist/diagrams/sociogram/index.cjs +26 -0
  154. package/dist/diagrams/sociogram/index.cjs.map +1 -0
  155. package/dist/diagrams/sociogram/index.d.cts +76 -0
  156. package/dist/diagrams/sociogram/index.d.ts +76 -0
  157. package/dist/diagrams/sociogram/index.js +5 -0
  158. package/dist/diagrams/sociogram/index.js.map +1 -0
  159. package/dist/diagrams/timing/index.cjs +21 -0
  160. package/dist/diagrams/timing/index.cjs.map +1 -0
  161. package/dist/diagrams/timing/index.d.cts +9 -0
  162. package/dist/diagrams/timing/index.d.ts +9 -0
  163. package/dist/diagrams/timing/index.js +4 -0
  164. package/dist/diagrams/timing/index.js.map +1 -0
  165. package/dist/diagrams/venn/index.cjs +38 -0
  166. package/dist/diagrams/venn/index.cjs.map +1 -0
  167. package/dist/diagrams/venn/index.d.cts +69 -0
  168. package/dist/diagrams/venn/index.d.ts +69 -0
  169. package/dist/diagrams/venn/index.js +5 -0
  170. package/dist/diagrams/venn/index.js.map +1 -0
  171. package/dist/index-BSlza1YY.d.ts +150 -0
  172. package/dist/index-BXefHVce.d.cts +150 -0
  173. package/dist/index.cjs +2033 -0
  174. package/dist/index.cjs.map +1 -0
  175. package/dist/index.d.cts +29 -0
  176. package/dist/index.d.ts +29 -0
  177. package/dist/index.js +1944 -0
  178. package/dist/index.js.map +1 -0
  179. package/dist/types-DqfcYkcY.d.cts +741 -0
  180. package/dist/types-DqfcYkcY.d.ts +741 -0
  181. package/package.json +163 -0
@@ -0,0 +1,874 @@
1
+ import { resolveFishboneTheme } from './chunk-IX554O5K.js';
2
+ import { line, text, title, desc, el, defs, group, svgRoot, rect, polygon } from './chunk-KLJEK547.js';
3
+
4
+ // src/diagrams/fishbone/parser.ts
5
+ var FishboneParseError = class extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = "FishboneParseError";
9
+ }
10
+ };
11
+ var SLOPE_PRESETS = {
12
+ gentle: 0.45,
13
+ normal: 0.6,
14
+ steep: 0.75
15
+ };
16
+ function parseFishboneDSL(text2) {
17
+ const rawLines = text2.split(/\r?\n/);
18
+ let title2;
19
+ let effect = "";
20
+ let orientation = "ltr";
21
+ let width;
22
+ let height;
23
+ let sides;
24
+ let ribSlope;
25
+ let density;
26
+ let causeSide;
27
+ const categories = [];
28
+ const causesByCategory = /* @__PURE__ */ new Map();
29
+ let lastLevel1 = null;
30
+ let headerSeen = false;
31
+ const getCat = (id) => categories.find((c) => c.id === id || c.label === id);
32
+ for (let i = 0; i < rawLines.length; i++) {
33
+ const raw = rawLines[i] ?? "";
34
+ const line2 = stripComment(raw).trimEnd();
35
+ if (!line2.trim()) continue;
36
+ const indent = countIndent(raw);
37
+ const trimmed = line2.trim();
38
+ if (!headerSeen && /^fishbone\b/i.test(trimmed)) {
39
+ const m = trimmed.match(/^fishbone\s*:?\s*(.*)$/i);
40
+ if (m && m[1]) title2 = stripQuotes(m[1]);
41
+ headerSeen = true;
42
+ continue;
43
+ }
44
+ if (indent >= 2 && trimmed.startsWith("-")) {
45
+ if (!lastLevel1) {
46
+ throw new FishboneParseError(
47
+ `Sub-cause at line ${i + 1} has no preceding Level-1 cause: "${trimmed}"`
48
+ );
49
+ }
50
+ const subText = stripQuotes(trimmed.slice(1).trim());
51
+ if (!subText) continue;
52
+ lastLevel1.children.push({ label: subText, children: [] });
53
+ continue;
54
+ }
55
+ if (/^effect\b/i.test(trimmed)) {
56
+ const m = trimmed.match(/^effect\s*:?\s*(.*)$/i);
57
+ if (m) effect = stripQuotes(m[1] ?? "");
58
+ continue;
59
+ }
60
+ if (/^config\b/i.test(trimmed)) {
61
+ const m = trimmed.match(/^config\s+([a-zA-Z]+)\s*=\s*(.+)$/i);
62
+ if (m) {
63
+ const key = m[1].toLowerCase();
64
+ const val = stripQuotes(m[2].trim());
65
+ if (key === "direction") {
66
+ orientation = val === "left" || val === "rtl" ? "rtl" : "ltr";
67
+ } else if (key === "width") {
68
+ const n = Number(val);
69
+ if (Number.isFinite(n)) width = n;
70
+ } else if (key === "height") {
71
+ const n = Number(val);
72
+ if (Number.isFinite(n)) height = n;
73
+ } else if (key === "sides") {
74
+ const v = val.toLowerCase();
75
+ if (v === "both" || v === "top" || v === "bottom") sides = v;
76
+ } else if (key === "slope" || key === "ribslope") {
77
+ const preset = SLOPE_PRESETS[val.toLowerCase()];
78
+ if (preset !== void 0) ribSlope = preset;
79
+ else {
80
+ const n = Number(val);
81
+ if (Number.isFinite(n) && n > 0 && n < 3) ribSlope = n;
82
+ }
83
+ } else if (key === "density") {
84
+ const v = val.toLowerCase();
85
+ if (v === "compact" || v === "normal" || v === "spacious") density = v;
86
+ } else if (key === "causeside" || key === "cause-side") {
87
+ const v = val.toLowerCase();
88
+ if (v === "head" || v === "tail" || v === "both") causeSide = v;
89
+ }
90
+ }
91
+ continue;
92
+ }
93
+ if (/^category\b/i.test(trimmed)) {
94
+ const compact = trimmed.match(/^category\s+([^:]+?)\s*:\s*(.+)$/i);
95
+ const structured = trimmed.match(
96
+ /^category\s+([a-zA-Z][\w-]*)\s+("[^"]*"|[^\s[]+)(?:\s*(\[.*\]))?\s*$/i
97
+ );
98
+ if (structured) {
99
+ const id = structured[1];
100
+ const label = stripQuotes(structured[2]);
101
+ const props = parseProps(structured[3] ?? "");
102
+ if (!getCat(id)) {
103
+ const sideProp = props["side"]?.toLowerCase();
104
+ const side = sideProp === "top" || sideProp === "bottom" ? sideProp : void 0;
105
+ const orderProp = props["order"];
106
+ const orderNum = orderProp !== void 0 ? Number(orderProp) : NaN;
107
+ const order = Number.isFinite(orderNum) ? orderNum : void 0;
108
+ categories.push({ id, label, color: props["color"], side, order });
109
+ causesByCategory.set(id, []);
110
+ }
111
+ lastLevel1 = null;
112
+ continue;
113
+ }
114
+ if (compact) {
115
+ const label = stripQuotes(compact[1].trim());
116
+ const id = slugify(label);
117
+ const rest = compact[2].trim();
118
+ if (!getCat(id)) {
119
+ categories.push({ id, label });
120
+ causesByCategory.set(id, []);
121
+ }
122
+ const bucket = causesByCategory.get(id);
123
+ for (const part of rest.split(/[;,]/)) {
124
+ const txt = stripQuotes(part.trim());
125
+ if (txt) {
126
+ const node = { label: txt, children: [] };
127
+ bucket.push(node);
128
+ lastLevel1 = node;
129
+ }
130
+ }
131
+ continue;
132
+ }
133
+ }
134
+ const causeMatch = trimmed.match(/^([a-zA-Z][\w-]*)\s*:\s*(.+)$/);
135
+ if (causeMatch) {
136
+ const catId = causeMatch[1];
137
+ const cat = getCat(catId);
138
+ if (!cat) {
139
+ throw new FishboneParseError(
140
+ `Unknown category "${catId}" at line ${i + 1}. Declare with \`category ${catId} "..."\` first.`
141
+ );
142
+ }
143
+ const bucket = causesByCategory.get(cat.id);
144
+ const rest = causeMatch[2].trim();
145
+ const { text: causeText } = splitTrailingProps(rest);
146
+ const label = stripQuotes(causeText);
147
+ if (!label) continue;
148
+ const node = { label, children: [] };
149
+ bucket.push(node);
150
+ lastLevel1 = node;
151
+ continue;
152
+ }
153
+ }
154
+ if (!effect) {
155
+ effect = title2 ?? "";
156
+ }
157
+ if (categories.length === 0) {
158
+ throw new FishboneParseError(
159
+ "Fishbone requires at least one `category`. See docs/reference/13-FISHBONE-STANDARD.md."
160
+ );
161
+ }
162
+ const majors = categories.map((c) => ({
163
+ label: c.label,
164
+ color: c.color,
165
+ children: causesByCategory.get(c.id) ?? [],
166
+ side: c.side,
167
+ order: c.order
168
+ }));
169
+ return {
170
+ type: "fishbone",
171
+ title: title2,
172
+ effect,
173
+ majors,
174
+ orientation,
175
+ width,
176
+ height,
177
+ sides,
178
+ ribSlope,
179
+ density,
180
+ causeSide
181
+ };
182
+ }
183
+ function stripComment(s) {
184
+ let out = "";
185
+ let inQuote = false;
186
+ for (const ch of s) {
187
+ if (ch === '"') inQuote = !inQuote;
188
+ if (ch === "#" && !inQuote) break;
189
+ out += ch;
190
+ }
191
+ return out;
192
+ }
193
+ function stripQuotes(v) {
194
+ const t = v.trim();
195
+ if (t.length >= 2 && t.startsWith('"') && t.endsWith('"')) return t.slice(1, -1);
196
+ return t;
197
+ }
198
+ function countIndent(raw) {
199
+ let n = 0;
200
+ for (const ch of raw) {
201
+ if (ch === " ") n += 1;
202
+ else if (ch === " ") n += 2;
203
+ else break;
204
+ }
205
+ return n;
206
+ }
207
+ function slugify(s) {
208
+ return s.toLowerCase().replace(/[^\w\u4e00-\u9fff]+/g, "-").replace(/^-+|-+$/g, "") || "cat";
209
+ }
210
+ function splitTrailingProps(s) {
211
+ const idx = s.lastIndexOf("[");
212
+ if (idx < 0 || !s.trimEnd().endsWith("]")) return { text: s, props: {} };
213
+ const text2 = s.slice(0, idx).trim();
214
+ const props = parseProps(s.slice(idx));
215
+ return { text: text2, props };
216
+ }
217
+ function parseProps(raw) {
218
+ const out = {};
219
+ const m = raw.match(/^\[(.*)\]$/s);
220
+ if (!m) return out;
221
+ const inside = m[1];
222
+ for (const part of splitTopLevelCommas(inside)) {
223
+ const [k, ...rest] = part.split(":");
224
+ if (!k || rest.length === 0) continue;
225
+ out[k.trim()] = stripQuotes(rest.join(":").trim());
226
+ }
227
+ return out;
228
+ }
229
+ function splitTopLevelCommas(inside) {
230
+ const parts = [];
231
+ let depth = 0;
232
+ let buf = "";
233
+ let inQuote = false;
234
+ for (const ch of inside) {
235
+ if (ch === '"') inQuote = !inQuote;
236
+ if (!inQuote) {
237
+ if (ch === "[") depth += 1;
238
+ else if (ch === "]") depth -= 1;
239
+ else if (ch === "," && depth === 0) {
240
+ parts.push(buf);
241
+ buf = "";
242
+ continue;
243
+ }
244
+ }
245
+ buf += ch;
246
+ }
247
+ if (buf.trim()) parts.push(buf);
248
+ return parts;
249
+ }
250
+
251
+ // src/diagrams/fishbone/layout.ts
252
+ var FB_CONST = {
253
+ PADDING: 40,
254
+ HEAD_W: 90,
255
+ HEAD_H: 80,
256
+ TAIL_LEN: 40,
257
+ SPINE_OFFSET_FROM_TAIL: 40,
258
+ // distance from canvas left to spine start
259
+ RIB_SLOPE: 0.6,
260
+ // dx/dy — consistent across all ribs
261
+ RIB_BASE_EXTENT_Y: 30,
262
+ // vertical distance of first slot from spine
263
+ ROW_HEIGHT: 30,
264
+ // vertical gap between Level-1 slots
265
+ SUB_ROW_HEIGHT: 17,
266
+ BRANCH_LEN: 30,
267
+ // horizontal Level-1 branch length
268
+ SUB_TICK_LEN: 10,
269
+ HEADER_W: 132,
270
+ HEADER_H: 34,
271
+ HEADER_GAP: 12,
272
+ // gap between rib endpoint and header pill
273
+ COL_STEP: 130,
274
+ // spine x gap between adjacent ribs
275
+ COL_FIRST_OFFSET: 170,
276
+ // first rib's distance from spine start
277
+ LABEL_FONT: 12,
278
+ HEADER_FONT: 14,
279
+ SUB_FONT: 11,
280
+ EFFECT_FONT: 14,
281
+ LABEL_GAP: 6,
282
+ // gap from branch end to label
283
+ MIN_ROWS_PER_HALF: 4,
284
+ // aesthetic minimum rib length
285
+ COL_GAP_BETWEEN_LABELS: 18,
286
+ // min horizontal breathing between adjacent ribs' label columns
287
+ HEAD_PAD_X: 44,
288
+ // total horizontal padding around effect text inside head
289
+ HEAD_PAD_Y: 20,
290
+ // min vertical padding around effect text inside head
291
+ TITLE_CLEARANCE: 24
292
+ // extra gap between title baseline and top header pill
293
+ };
294
+ function estimateTextWidth(s, fontSize) {
295
+ let w = 0;
296
+ for (const ch of s) {
297
+ const cp = ch.codePointAt(0) ?? 0;
298
+ const isWide = cp >= 12288 && cp <= 12543 || cp >= 13312 && cp <= 40959 || cp >= 44032 && cp <= 55215 || cp >= 65280 && cp <= 65519;
299
+ w += fontSize * (isWide ? 1 : 0.56);
300
+ }
301
+ return w;
302
+ }
303
+ var DENSITY = {
304
+ compact: {
305
+ rowHeight: 24,
306
+ subRowHeight: 15,
307
+ colStep: 110,
308
+ headerW: 118,
309
+ headerH: 30,
310
+ headerGap: 8,
311
+ minRowsPerHalf: 3,
312
+ colFirstOffset: 140
313
+ },
314
+ normal: {
315
+ rowHeight: 30,
316
+ subRowHeight: 17,
317
+ colStep: 130,
318
+ headerW: 132,
319
+ headerH: 34,
320
+ headerGap: 12,
321
+ minRowsPerHalf: 4,
322
+ colFirstOffset: 170
323
+ },
324
+ spacious: {
325
+ rowHeight: 36,
326
+ subRowHeight: 19,
327
+ colStep: 150,
328
+ headerW: 148,
329
+ headerH: 38,
330
+ headerGap: 16,
331
+ minRowsPerHalf: 5,
332
+ colFirstOffset: 200
333
+ }
334
+ };
335
+ function layoutFishbone(ast, opts) {
336
+ const majors = ast.majors.length > 0 ? ast.majors : [];
337
+ majors.length;
338
+ const density = ast.density ?? "normal";
339
+ const D = DENSITY[density];
340
+ const ribSlope = ast.ribSlope ?? FB_CONST.RIB_SLOPE;
341
+ const causeSideSetting = ast.causeSide ?? "head";
342
+ const sides = ast.sides ?? "both";
343
+ const topMajors = [];
344
+ const botMajors = [];
345
+ if (sides === "top" || sides === "bottom") {
346
+ const bucket = sides === "top" ? topMajors : botMajors;
347
+ for (const m of majors) {
348
+ if (m.side === "top") topMajors.push(m);
349
+ else if (m.side === "bottom") botMajors.push(m);
350
+ else bucket.push(m);
351
+ }
352
+ } else {
353
+ const autoPool = [];
354
+ for (const m of majors) {
355
+ if (m.side === "top") topMajors.push(m);
356
+ else if (m.side === "bottom") botMajors.push(m);
357
+ else autoPool.push(m);
358
+ }
359
+ for (const m of autoPool) {
360
+ if (topMajors.length <= botMajors.length) topMajors.push(m);
361
+ else botMajors.push(m);
362
+ }
363
+ }
364
+ const byOrder = (a, b) => {
365
+ const ao = a.order ?? Number.POSITIVE_INFINITY;
366
+ const bo = b.order ?? Number.POSITIVE_INFINITY;
367
+ return ao - bo;
368
+ };
369
+ topMajors.sort(byOrder);
370
+ botMajors.sort(byOrder);
371
+ const nTop = topMajors.length;
372
+ const nBot = botMajors.length;
373
+ const ribRowHeights = (m) => {
374
+ if (m.children.length === 0) return [];
375
+ return m.children.map(
376
+ (c) => D.rowHeight + c.children.length * D.subRowHeight
377
+ );
378
+ };
379
+ const topExtents = topMajors.map(
380
+ (m) => sumOrMin(ribRowHeights(m), D.minRowsPerHalf * D.rowHeight)
381
+ );
382
+ const botExtents = botMajors.map(
383
+ (m) => sumOrMin(ribRowHeights(m), D.minRowsPerHalf * D.rowHeight)
384
+ );
385
+ const effectTextW = estimateTextWidth(ast.effect, FB_CONST.EFFECT_FONT);
386
+ const rawHeadW = effectTextW + FB_CONST.HEAD_PAD_X;
387
+ const headEffectiveH = Math.max(FB_CONST.HEAD_H, Math.ceil(rawHeadW / 2));
388
+ const taperAtText = 1 - FB_CONST.EFFECT_FONT / headEffectiveH;
389
+ const headEffectiveW = Math.max(FB_CONST.HEAD_W, Math.ceil(rawHeadW / taperAtText));
390
+ const minHalfFromHead = Math.ceil(headEffectiveH / 2) + 6;
391
+ const topHalfExtent = nTop > 0 ? Math.max(
392
+ minHalfFromHead,
393
+ D.minRowsPerHalf * D.rowHeight,
394
+ ...topExtents.length ? topExtents : [0]
395
+ ) : sides === "bottom" ? Math.max(minHalfFromHead, 0) : 0;
396
+ const botHalfExtent = nBot > 0 ? Math.max(
397
+ minHalfFromHead,
398
+ D.minRowsPerHalf * D.rowHeight,
399
+ ...botExtents.length ? botExtents : [0]
400
+ ) : sides === "top" ? Math.max(minHalfFromHead, 0) : 0;
401
+ const nCols = Math.max(nTop, nBot, 1);
402
+ let maxCauseLabelW = 0;
403
+ let maxSubLabelW = 0;
404
+ for (const m of majors) {
405
+ for (const c of m.children) {
406
+ maxCauseLabelW = Math.max(
407
+ maxCauseLabelW,
408
+ estimateTextWidth(c.label, FB_CONST.LABEL_FONT)
409
+ );
410
+ for (const sc of c.children) {
411
+ maxSubLabelW = Math.max(
412
+ maxSubLabelW,
413
+ estimateTextWidth(sc.label, FB_CONST.SUB_FONT)
414
+ );
415
+ }
416
+ }
417
+ }
418
+ const subExtent = maxSubLabelW > 0 ? FB_CONST.SUB_TICK_LEN + 4 + maxSubLabelW : 0;
419
+ const labelColW = Math.max(maxCauseLabelW, subExtent);
420
+ const labelExtentsPerCol = causeSideSetting === "both" ? 2 : 1;
421
+ const minColStep = FB_CONST.BRANCH_LEN + FB_CONST.LABEL_GAP + labelColW + FB_CONST.COL_GAP_BETWEEN_LABELS;
422
+ const colStep = Math.max(
423
+ D.colStep,
424
+ Math.ceil(minColStep * (labelExtentsPerCol === 2 ? 1.15 : 1))
425
+ );
426
+ const spineStartX = FB_CONST.PADDING + FB_CONST.TAIL_LEN + FB_CONST.SPINE_OFFSET_FROM_TAIL;
427
+ const firstRibX = spineStartX + D.colFirstOffset;
428
+ const lastRibX = firstRibX + (nCols - 1) * colStep;
429
+ const spineEndX = lastRibX + Math.max(40, FB_CONST.BRANCH_LEN + FB_CONST.LABEL_GAP + labelColW + 12);
430
+ const headX = spineEndX;
431
+ const headTipXAdj = headX + headEffectiveW;
432
+ const width = ast.width ?? Math.ceil(headTipXAdj + FB_CONST.PADDING);
433
+ const title2 = ast.title;
434
+ const titleReserve = title2 ? FB_CONST.TITLE_CLEARANCE + 20 : 0;
435
+ const spineY = FB_CONST.PADDING + titleReserve + topHalfExtent + D.headerH / 2 + 12;
436
+ const height = ast.height ?? Math.ceil(
437
+ spineY + botHalfExtent + D.headerH / 2 + 12 + FB_CONST.PADDING
438
+ );
439
+ const ribs = [];
440
+ const palette = opts?.palette ?? resolveFishboneTheme("default").palette;
441
+ const textBBoxes = [];
442
+ const buildHalfRibs = (halfMajors, startIndex, half, halfExtent) => {
443
+ for (let i = 0; i < halfMajors.length; i++) {
444
+ const major = halfMajors[i];
445
+ const globalIdx = startIndex + i;
446
+ const color = major.color ?? palette[globalIdx % palette.length];
447
+ const spineX = firstRibX + i * colStep;
448
+ const endY = half === "top" ? spineY - halfExtent : spineY + halfExtent;
449
+ const endX = spineX - halfExtent * ribSlope;
450
+ const extraDist = D.headerGap + D.headerH / 2;
451
+ const headerCenterY = half === "top" ? endY - extraDist : endY + extraDist;
452
+ const headerCenterX = endX - extraDist * ribSlope;
453
+ const headerW = Math.max(
454
+ D.headerW,
455
+ estimateTextWidth(major.label, FB_CONST.HEADER_FONT) + 28
456
+ );
457
+ const headerX = headerCenterX - headerW / 2;
458
+ const headerY = headerCenterY - D.headerH / 2;
459
+ textBBoxes.push({
460
+ x: headerX,
461
+ y: headerY,
462
+ w: headerW,
463
+ h: D.headerH
464
+ });
465
+ const causes = [];
466
+ let accum = FB_CONST.RIB_BASE_EXTENT_Y;
467
+ for (let s = 0; s < major.children.length; s++) {
468
+ const child = major.children[s];
469
+ const rowH = D.rowHeight + child.children.length * D.subRowHeight;
470
+ const slotOffset = accum + rowH / 2 - D.rowHeight / 2;
471
+ const ribY = half === "top" ? spineY - slotOffset : spineY + slotOffset;
472
+ const ribX = spineX - slotOffset * ribSlope;
473
+ const causeDir = causeSideSetting === "tail" ? "tail" : causeSideSetting === "both" ? s % 2 === 0 ? "head" : "tail" : "head";
474
+ const branchY = ribY;
475
+ const branchX = causeDir === "head" ? ribX + FB_CONST.BRANCH_LEN : ribX - FB_CONST.BRANCH_LEN;
476
+ const labelX = causeDir === "head" ? branchX + FB_CONST.LABEL_GAP : branchX - FB_CONST.LABEL_GAP;
477
+ const labelY = branchY;
478
+ const labelAnchor = causeDir === "head" ? "start" : "end";
479
+ const labelW = estimateTextWidth(child.label, FB_CONST.LABEL_FONT);
480
+ textBBoxes.push({
481
+ x: causeDir === "head" ? labelX - 2 : labelX - labelW - 2,
482
+ y: labelY - FB_CONST.LABEL_FONT / 2 - 2,
483
+ w: labelW + 4,
484
+ h: FB_CONST.LABEL_FONT + 4
485
+ });
486
+ const subCauses = [];
487
+ for (let si = 0; si < child.children.length; si++) {
488
+ const sub = child.children[si];
489
+ const subY = labelY + (si + 1) * D.subRowHeight;
490
+ const tickX1 = causeDir === "head" ? labelX + 2 : labelX - 2;
491
+ const tickX2 = causeDir === "head" ? tickX1 + FB_CONST.SUB_TICK_LEN : tickX1 - FB_CONST.SUB_TICK_LEN;
492
+ const subX = causeDir === "head" ? tickX2 + 4 : tickX2 - 4;
493
+ subCauses.push({
494
+ label: sub.label,
495
+ x: subX,
496
+ y: subY,
497
+ tickX1,
498
+ tickX2,
499
+ tickY: subY,
500
+ anchor: causeDir === "head" ? "start" : "end"
501
+ });
502
+ const subW = estimateTextWidth(sub.label, FB_CONST.SUB_FONT);
503
+ textBBoxes.push({
504
+ x: causeDir === "head" ? subX - 2 : subX - subW - 2,
505
+ y: subY - FB_CONST.SUB_FONT / 2 - 2,
506
+ w: subW + 4,
507
+ h: FB_CONST.SUB_FONT + 4
508
+ });
509
+ }
510
+ causes.push({
511
+ label: child.label,
512
+ ribIndex: globalIdx,
513
+ slotIndex: s,
514
+ ribX,
515
+ ribY,
516
+ branchX,
517
+ branchY,
518
+ labelX,
519
+ labelY,
520
+ labelAnchor,
521
+ causeSide: causeDir,
522
+ subCauses
523
+ });
524
+ accum += rowH;
525
+ }
526
+ ribs.push({
527
+ index: globalIdx,
528
+ half,
529
+ label: major.label,
530
+ color,
531
+ spineX,
532
+ spineY,
533
+ endX,
534
+ endY,
535
+ headerX,
536
+ headerY,
537
+ headerW,
538
+ headerH: D.headerH,
539
+ causes
540
+ });
541
+ }
542
+ };
543
+ buildHalfRibs(topMajors, 0, "top", topHalfExtent);
544
+ buildHalfRibs(botMajors, nTop, "bottom", botHalfExtent);
545
+ const head = {
546
+ x: headX,
547
+ y: spineY,
548
+ tipX: headTipXAdj,
549
+ tipY: spineY,
550
+ w: headEffectiveW,
551
+ h: headEffectiveH,
552
+ label: ast.effect
553
+ };
554
+ textBBoxes.push({
555
+ x: headX + 4,
556
+ y: spineY - headEffectiveH / 2 + 4,
557
+ w: headEffectiveW - 8,
558
+ h: headEffectiveH - 8
559
+ });
560
+ return {
561
+ width,
562
+ height,
563
+ orientation: ast.orientation,
564
+ spineY,
565
+ spineStartX,
566
+ spineEndX,
567
+ tailForkTipTop: { x: FB_CONST.PADDING, y: spineY - FB_CONST.TAIL_LEN },
568
+ tailForkTipBot: { x: FB_CONST.PADDING, y: spineY + FB_CONST.TAIL_LEN },
569
+ head,
570
+ ribs,
571
+ textBBoxes,
572
+ title: title2
573
+ };
574
+ }
575
+ function sumOrMin(arr, min) {
576
+ if (arr.length === 0) return min;
577
+ const s = arr.reduce((a, b) => a + b, 0);
578
+ return Math.max(s, min);
579
+ }
580
+
581
+ // src/diagrams/fishbone/renderer.ts
582
+ var CSS = `
583
+ .sx-fb { background: var(--schematex-fb-bg, #ffffff); font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }
584
+ .sx-fb-title { font: 600 16px sans-serif; fill: #111; }
585
+ .sx-fb-spine { stroke: var(--schematex-fb-spine, #141413); stroke-width: 2; stroke-linecap: butt; fill: none; }
586
+ .sx-fb-tail { stroke: var(--schematex-fb-spine, #141413); stroke-width: 2; stroke-linecap: round; fill: none; }
587
+ .sx-fb-head { stroke-width: 0.5; }
588
+ .sx-fb-head-text { font: 500 14px sans-serif; text-anchor: middle; dominant-baseline: central; }
589
+ .sx-fb-rib { stroke-width: 1.5; fill: none; }
590
+ .sx-fb-header-pill { stroke-width: 0.6; }
591
+ .sx-fb-header-text { font: 500 14px sans-serif; text-anchor: middle; dominant-baseline: central; }
592
+ .sx-fb-branch { stroke-width: 0.8; opacity: 0.6; fill: none; }
593
+ .sx-fb-cause-label { font: 400 12px sans-serif; fill: #3d3d3a; dominant-baseline: central; }
594
+ .sx-fb-sub-tick { stroke-width: 0.7; opacity: 0.5; fill: none; }
595
+ .sx-fb-sub-label { font: 400 11px sans-serif; fill: #555; dominant-baseline: central; }
596
+ `.trim();
597
+ function lighten(hex, amount) {
598
+ const m = hex.match(/^#?([0-9a-f]{6})$/i);
599
+ if (!m) return hex;
600
+ const n = parseInt(m[1], 16);
601
+ const r = n >> 16 & 255;
602
+ const g = n >> 8 & 255;
603
+ const b = n & 255;
604
+ const rr = Math.round(r + (255 - r) * amount);
605
+ const gg = Math.round(g + (255 - g) * amount);
606
+ const bb = Math.round(b + (255 - b) * amount);
607
+ return `#${[rr, gg, bb].map((v) => v.toString(16).padStart(2, "0")).join("")}`;
608
+ }
609
+ function darken(hex, amount) {
610
+ const m = hex.match(/^#?([0-9a-f]{6})$/i);
611
+ if (!m) return hex;
612
+ const n = parseInt(m[1], 16);
613
+ const r = n >> 16 & 255;
614
+ const g = n >> 8 & 255;
615
+ const b = n & 255;
616
+ const rr = Math.round(r * (1 - amount));
617
+ const gg = Math.round(g * (1 - amount));
618
+ const bb = Math.round(b * (1 - amount));
619
+ return `#${[rr, gg, bb].map((v) => v.toString(16).padStart(2, "0")).join("")}`;
620
+ }
621
+ function randomId() {
622
+ return Math.random().toString(36).slice(2, 8);
623
+ }
624
+ function buildMask(id, w, h, bboxes) {
625
+ const base = rect({ x: 0, y: 0, width: w, height: h, fill: "white" });
626
+ const holes = bboxes.map(
627
+ (b) => rect({
628
+ x: b.x,
629
+ y: b.y,
630
+ width: b.w,
631
+ height: b.h,
632
+ fill: "black",
633
+ rx: 2
634
+ })
635
+ ).join("\n");
636
+ return el("mask", { id, maskUnits: "userSpaceOnUse" }, [base, holes]);
637
+ }
638
+ function renderHead(layout, ltr) {
639
+ const h = layout.head;
640
+ const tipX = ltr ? h.tipX : h.x - (h.tipX - h.x);
641
+ const leftX = ltr ? h.x : h.x;
642
+ const rightX = ltr ? h.tipX : tipX;
643
+ const points = ltr ? `${leftX},${h.y - h.h / 2} ${leftX},${h.y + h.h / 2} ${rightX},${h.y}` : `${rightX},${h.y - h.h / 2} ${rightX},${h.y + h.h / 2} ${tipX},${h.y}`;
644
+ const fill = "#faece7";
645
+ const stroke = "#993c1d";
646
+ const textX = ltr ? leftX + h.w * 0.38 : rightX - h.w * 0.38;
647
+ return group({ class: "sx-fb-head-g" }, [
648
+ polygon({
649
+ points,
650
+ class: "sx-fb-head",
651
+ fill,
652
+ stroke
653
+ }),
654
+ text(
655
+ {
656
+ x: textX,
657
+ y: h.y,
658
+ class: "sx-fb-head-text",
659
+ fill: darken(stroke, 0.3)
660
+ },
661
+ h.label
662
+ )
663
+ ]);
664
+ }
665
+ function renderRibs(layout, maskUrl) {
666
+ const parts = [];
667
+ for (const rib of layout.ribs) {
668
+ const pillFill = lighten(rib.color, 0.82);
669
+ const pillStroke = rib.color;
670
+ const headerTextFill = darken(rib.color, 0.3);
671
+ parts.push(
672
+ line({
673
+ x1: rib.spineX,
674
+ y1: rib.spineY,
675
+ x2: rib.endX,
676
+ y2: rib.endY,
677
+ class: "sx-fb-rib",
678
+ stroke: rib.color,
679
+ mask: maskUrl
680
+ })
681
+ );
682
+ parts.push(
683
+ line({
684
+ x1: rib.endX,
685
+ y1: rib.endY,
686
+ x2: rib.headerX + rib.headerW / 2,
687
+ y2: rib.headerY + rib.headerH / 2,
688
+ class: "sx-fb-rib",
689
+ stroke: rib.color
690
+ })
691
+ );
692
+ parts.push(
693
+ rect({
694
+ x: rib.headerX,
695
+ y: rib.headerY,
696
+ width: rib.headerW,
697
+ height: rib.headerH,
698
+ rx: 8,
699
+ class: "sx-fb-header-pill",
700
+ fill: pillFill,
701
+ stroke: pillStroke
702
+ })
703
+ );
704
+ parts.push(
705
+ text(
706
+ {
707
+ x: rib.headerX + rib.headerW / 2,
708
+ y: rib.headerY + rib.headerH / 2,
709
+ class: "sx-fb-header-text",
710
+ fill: headerTextFill
711
+ },
712
+ rib.label
713
+ )
714
+ );
715
+ for (const cause of rib.causes) {
716
+ parts.push(
717
+ line({
718
+ x1: cause.ribX,
719
+ y1: cause.ribY,
720
+ x2: cause.branchX,
721
+ y2: cause.branchY,
722
+ class: "sx-fb-branch",
723
+ stroke: rib.color,
724
+ mask: maskUrl
725
+ })
726
+ );
727
+ parts.push(
728
+ text(
729
+ {
730
+ x: cause.labelX,
731
+ y: cause.labelY,
732
+ class: "sx-fb-cause-label",
733
+ "text-anchor": cause.labelAnchor
734
+ },
735
+ cause.label
736
+ )
737
+ );
738
+ for (const sub of cause.subCauses) {
739
+ parts.push(
740
+ line({
741
+ x1: sub.tickX1,
742
+ y1: sub.tickY,
743
+ x2: sub.tickX2,
744
+ y2: sub.tickY,
745
+ class: "sx-fb-sub-tick",
746
+ stroke: rib.color
747
+ })
748
+ );
749
+ parts.push(
750
+ text(
751
+ {
752
+ x: sub.x,
753
+ y: sub.y,
754
+ class: "sx-fb-sub-label",
755
+ "text-anchor": sub.anchor
756
+ },
757
+ sub.label
758
+ )
759
+ );
760
+ }
761
+ }
762
+ }
763
+ return group({ class: "sx-fb-ribs" }, parts);
764
+ }
765
+ function renderFishboneAST(ast, options = {}) {
766
+ const themeName = options.theme ?? ast.metadata?.["theme"] ?? "default";
767
+ const tokens = resolveFishboneTheme(themeName);
768
+ const layout = layoutFishbone(ast, { palette: tokens.palette });
769
+ const ltr = layout.orientation !== "rtl";
770
+ const maskId = `sx-fb-mask-${randomId()}`;
771
+ const maskUrl = `url(#${maskId})`;
772
+ const mask = buildMask(maskId, layout.width, layout.height, layout.textBBoxes);
773
+ const spine = line({
774
+ x1: layout.spineStartX,
775
+ y1: layout.spineY,
776
+ x2: layout.spineEndX,
777
+ y2: layout.spineY,
778
+ class: "sx-fb-spine"
779
+ });
780
+ const tailTop = line({
781
+ x1: layout.spineStartX,
782
+ y1: layout.spineY,
783
+ x2: layout.tailForkTipTop.x,
784
+ y2: layout.tailForkTipTop.y,
785
+ class: "sx-fb-tail"
786
+ });
787
+ const tailBot = line({
788
+ x1: layout.spineStartX,
789
+ y1: layout.spineY,
790
+ x2: layout.tailForkTipBot.x,
791
+ y2: layout.tailForkTipBot.y,
792
+ class: "sx-fb-tail"
793
+ });
794
+ const titleBlock = layout.title ? text(
795
+ {
796
+ x: layout.width / 2,
797
+ y: 28,
798
+ class: "sx-fb-title",
799
+ "text-anchor": "middle"
800
+ },
801
+ layout.title
802
+ ) : "";
803
+ const head = renderHead(layout, ltr);
804
+ const ribs = renderRibs(layout, maskUrl);
805
+ const inner = [
806
+ title(layout.title ? `${layout.title} \u2014 Fishbone diagram` : "Fishbone diagram"),
807
+ desc(
808
+ `Ishikawa cause-and-effect diagram. Effect: ${ast.effect}. ${ast.majors.length} categories.`
809
+ ),
810
+ el("style", {}, CSS),
811
+ defs([mask]),
812
+ titleBlock,
813
+ tailTop,
814
+ tailBot,
815
+ spine,
816
+ head,
817
+ ribs
818
+ ];
819
+ if (!ltr) {
820
+ const mirrored = group(
821
+ {
822
+ transform: `translate(${layout.width} 0) scale(-1 1)`
823
+ },
824
+ [tailTop, tailBot, spine, head, ribs]
825
+ );
826
+ return svgRoot(
827
+ {
828
+ viewBox: `0 0 ${layout.width} ${layout.height}`,
829
+ width: layout.width,
830
+ height: layout.height,
831
+ class: "sx-fb",
832
+ role: "img"
833
+ },
834
+ [
835
+ title(layout.title ?? "Fishbone"),
836
+ desc(`Ishikawa diagram (head-left). Effect: ${ast.effect}.`),
837
+ el("style", {}, CSS),
838
+ defs([mask]),
839
+ titleBlock,
840
+ mirrored
841
+ ]
842
+ );
843
+ }
844
+ return svgRoot(
845
+ {
846
+ viewBox: `0 0 ${layout.width} ${layout.height}`,
847
+ width: layout.width,
848
+ height: layout.height,
849
+ class: "sx-fb",
850
+ role: "img"
851
+ },
852
+ inner
853
+ );
854
+ }
855
+ function renderFishbone(text2, options = {}) {
856
+ const ast = parseFishboneDSL(text2);
857
+ return renderFishboneAST(ast, options);
858
+ }
859
+
860
+ // src/diagrams/fishbone/index.ts
861
+ var fishbone = {
862
+ type: "fishbone",
863
+ detect(text2) {
864
+ const first = text2.trim().split("\n")[0]?.trim().toLowerCase() ?? "";
865
+ return first.startsWith("fishbone");
866
+ },
867
+ render(text2) {
868
+ return renderFishbone(text2);
869
+ }
870
+ };
871
+
872
+ export { FB_CONST, fishbone, layoutFishbone, parseFishboneDSL, renderFishbone, renderFishboneAST };
873
+ //# sourceMappingURL=chunk-U4I37IBN.js.map
874
+ //# sourceMappingURL=chunk-U4I37IBN.js.map