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,778 @@
1
+ import { el, group, text, circle, path, svgRoot, title, desc, defs } from './chunk-KLJEK547.js';
2
+
3
+ // src/diagrams/blockdiagram/parser.ts
4
+ var BlockDiagramParseError = class extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "BlockDiagramParseError";
8
+ }
9
+ };
10
+ var ROLE_VALUES = /* @__PURE__ */ new Set([
11
+ "plant",
12
+ "controller",
13
+ "sensor",
14
+ "actuator",
15
+ "reference",
16
+ "disturbance",
17
+ "generic"
18
+ ]);
19
+ function parseAttrs(s) {
20
+ const result = {};
21
+ const parts = [];
22
+ let cur = "";
23
+ let inQuote = false;
24
+ for (const ch of s) {
25
+ if (ch === '"') inQuote = !inQuote;
26
+ if (ch === "," && !inQuote) {
27
+ parts.push(cur);
28
+ cur = "";
29
+ } else {
30
+ cur += ch;
31
+ }
32
+ }
33
+ if (cur.trim()) parts.push(cur);
34
+ for (const raw of parts) {
35
+ const p = raw.trim();
36
+ if (!p) continue;
37
+ if (p === "discrete") {
38
+ result.discrete = true;
39
+ continue;
40
+ }
41
+ if (p.startsWith('"') && p.endsWith('"')) {
42
+ result.label = p.slice(1, -1);
43
+ continue;
44
+ }
45
+ const m = p.match(/^(\w+)\s*:\s*(.+)$/);
46
+ if (!m) continue;
47
+ const key = m[1].toLowerCase();
48
+ let val = m[2].trim();
49
+ if (val.startsWith('"') && val.endsWith('"')) val = val.slice(1, -1);
50
+ if (key === "name") result.name = val;
51
+ else if (key === "role") {
52
+ if (ROLE_VALUES.has(val)) result.role = val;
53
+ } else if (key === "label") result.label = val;
54
+ else if (key === "route") {
55
+ if (val === "above" || val === "below") result.route = val;
56
+ }
57
+ }
58
+ return result;
59
+ }
60
+ function parseBlockDiagram(text2) {
61
+ const lines = text2.split("\n").map((l) => l.replace(/\r$/, ""));
62
+ let title2;
63
+ const blocks = [];
64
+ const sums = [];
65
+ const connections = [];
66
+ const signals = /* @__PURE__ */ new Map();
67
+ for (const rawLine of lines) {
68
+ const line = rawLine.replace(/#.*$/, "").trim();
69
+ if (!line) continue;
70
+ if (/^blockdiagram\b/i.test(line)) {
71
+ const t = line.match(/"([^"]*)"/);
72
+ if (t) title2 = t[1];
73
+ continue;
74
+ }
75
+ const blockMatch = line.match(
76
+ /^([A-Za-z_]\w*)\s*=\s*block\s*\(\s*"([^"]*)"\s*\)\s*(?:\[([^\]]*)\])?\s*$/
77
+ );
78
+ if (blockMatch) {
79
+ const id = blockMatch[1];
80
+ const label = blockMatch[2];
81
+ const attrs = blockMatch[3] ? parseAttrs(blockMatch[3]) : {};
82
+ const node = { id, label, role: attrs.role ?? "generic" };
83
+ if (attrs.route) node.route = attrs.route;
84
+ blocks.push(node);
85
+ continue;
86
+ }
87
+ const sumMatch = line.match(
88
+ /^([A-Za-z_]\w*)\s*=\s*sum\s*\(([^)]*)\)\s*$/
89
+ );
90
+ if (sumMatch) {
91
+ const id = sumMatch[1];
92
+ const rawInputs = sumMatch[2].split(",").map((x) => x.trim()).filter(Boolean);
93
+ const inputs = [];
94
+ for (const tok of rawInputs) {
95
+ if (tok.startsWith("+") || tok.startsWith("-")) inputs.push(tok);
96
+ else inputs.push("+" + tok);
97
+ }
98
+ sums.push({ id, inputs });
99
+ continue;
100
+ }
101
+ const sigMatch = line.match(
102
+ /^([A-Za-z_]\w*)\s*=\s*signal\s*\(\s*"([^"]*)"\s*\)\s*(?:\[([^\]]*)\])?\s*$/
103
+ );
104
+ if (sigMatch) {
105
+ const id = sigMatch[1];
106
+ const label = sigMatch[2];
107
+ const attrs = sigMatch[3] ? parseAttrs(sigMatch[3]) : {};
108
+ signals.set(id, { id, label, discrete: !!attrs.discrete });
109
+ continue;
110
+ }
111
+ const arrowIdx = line.indexOf("->");
112
+ if (arrowIdx >= 0) {
113
+ let body = line;
114
+ let tailAttrs = {};
115
+ if (body.endsWith("]")) {
116
+ let bracketStart = -1;
117
+ let inQuote = false;
118
+ for (let i = 0; i < body.length - 1; i++) {
119
+ const ch = body[i];
120
+ if (ch === '"') inQuote = !inQuote;
121
+ else if (ch === "[" && !inQuote) {
122
+ bracketStart = i;
123
+ break;
124
+ }
125
+ }
126
+ if (bracketStart >= 0) {
127
+ const inner = body.slice(bracketStart + 1, -1).trim();
128
+ body = body.slice(0, bracketStart).trim();
129
+ if (inner.startsWith('"') && inner.endsWith('"') && !inner.slice(1, -1).includes(",")) {
130
+ tailAttrs.label = inner.slice(1, -1);
131
+ } else {
132
+ tailAttrs = parseAttrs(inner);
133
+ }
134
+ }
135
+ }
136
+ const parts = body.split("->").map((x) => x.trim()).filter(Boolean);
137
+ if (parts.length < 2) {
138
+ throw new BlockDiagramParseError(`Invalid connection: ${line}`);
139
+ }
140
+ for (let i = 0; i < parts.length - 1; i++) {
141
+ const from = parts[i];
142
+ const to = parts[i + 1];
143
+ const isLast = i === parts.length - 2;
144
+ const edge = { from, to };
145
+ if (isLast && tailAttrs.label) edge.label = tailAttrs.label;
146
+ if (isLast && tailAttrs.discrete) edge.discrete = true;
147
+ connections.push(edge);
148
+ }
149
+ continue;
150
+ }
151
+ }
152
+ if (signals.size > 0) {
153
+ const merged = [];
154
+ const bySource = /* @__PURE__ */ new Map();
155
+ const byTarget = /* @__PURE__ */ new Map();
156
+ for (const e of connections) {
157
+ if (!bySource.has(e.from)) bySource.set(e.from, []);
158
+ bySource.get(e.from).push(e);
159
+ if (!byTarget.has(e.to)) byTarget.set(e.to, []);
160
+ byTarget.get(e.to).push(e);
161
+ }
162
+ const consumed = /* @__PURE__ */ new Set();
163
+ for (const sigId of signals.keys()) {
164
+ const sig = signals.get(sigId);
165
+ const incoming = byTarget.get(sigId) ?? [];
166
+ const outgoing = bySource.get(sigId) ?? [];
167
+ for (const ine of incoming) {
168
+ for (const oute of outgoing) {
169
+ consumed.add(ine);
170
+ consumed.add(oute);
171
+ merged.push({
172
+ from: ine.from,
173
+ to: oute.to,
174
+ label: ine.label ?? oute.label ?? sig.label,
175
+ discrete: sig.discrete || ine.discrete || oute.discrete
176
+ });
177
+ }
178
+ }
179
+ }
180
+ for (const e of connections) {
181
+ if (!consumed.has(e)) merged.push(e);
182
+ }
183
+ connections.length = 0;
184
+ connections.push(...merged);
185
+ }
186
+ return {
187
+ type: "blockdiagram",
188
+ title: title2,
189
+ blocks,
190
+ sums,
191
+ connections
192
+ };
193
+ }
194
+
195
+ // src/diagrams/blockdiagram/layout.ts
196
+ var BLOCK_W = 100;
197
+ var BLOCK_H = 54;
198
+ var SUM_R = 12;
199
+ var FWD_Y = 110;
200
+ var ROW_GAP = 80;
201
+ var FIRST_ROW_OFFSET = 110;
202
+ var COL_GAP = 60;
203
+ var LEFT_PAD = 30;
204
+ var RIGHT_PAD = 30;
205
+ function layoutBlockDiagram(ast) {
206
+ const nodeIds = /* @__PURE__ */ new Set();
207
+ for (const b of ast.blocks) nodeIds.add(b.id);
208
+ for (const s of ast.sums) nodeIds.add(s.id);
209
+ for (const e of ast.connections) {
210
+ nodeIds.add(e.from);
211
+ nodeIds.add(e.to);
212
+ }
213
+ const outgoing = /* @__PURE__ */ new Map();
214
+ const incoming = /* @__PURE__ */ new Map();
215
+ for (const id of nodeIds) {
216
+ outgoing.set(id, []);
217
+ incoming.set(id, []);
218
+ }
219
+ for (const e of ast.connections) {
220
+ outgoing.get(e.from).push(e);
221
+ incoming.get(e.to).push(e);
222
+ }
223
+ const hasIn = nodeIds.has("in");
224
+ const entries = [];
225
+ if (hasIn) entries.push("in");
226
+ for (const id of nodeIds) {
227
+ if (id === "in" || id === "out") continue;
228
+ if ((incoming.get(id) ?? []).length === 0 && !entries.includes(id)) {
229
+ entries.push(id);
230
+ }
231
+ }
232
+ const col = /* @__PURE__ */ new Map();
233
+ const queue = [];
234
+ for (const e of entries) {
235
+ col.set(e, 0);
236
+ queue.push(e);
237
+ }
238
+ while (queue.length > 0) {
239
+ const cur = queue.shift();
240
+ const c = col.get(cur);
241
+ for (const edge of outgoing.get(cur) ?? []) {
242
+ if (!col.has(edge.to)) {
243
+ col.set(edge.to, c + 1);
244
+ queue.push(edge.to);
245
+ }
246
+ }
247
+ }
248
+ for (const id of nodeIds) {
249
+ if (!col.has(id)) col.set(id, 1);
250
+ }
251
+ const isFeedback = /* @__PURE__ */ new Set();
252
+ for (const id of nodeIds) {
253
+ if (id === "in" || id === "out") continue;
254
+ const myCol = col.get(id);
255
+ const outs = outgoing.get(id) ?? [];
256
+ if (outs.length === 0) continue;
257
+ const allBack = outs.every((e) => (col.get(e.to) ?? myCol) < myCol);
258
+ if (allBack) isFeedback.add(id);
259
+ }
260
+ const blockById = /* @__PURE__ */ new Map();
261
+ for (const b of ast.blocks) blockById.set(b.id, b);
262
+ const fbInfos = [];
263
+ for (const id of isFeedback) {
264
+ const outs = outgoing.get(id) ?? [];
265
+ const ins = incoming.get(id) ?? [];
266
+ const targetCols = outs.map((e) => col.get(e.to) ?? 0);
267
+ const sourceCols = ins.map((e) => col.get(e.from) ?? 0);
268
+ const minC = Math.min(...targetCols, ...sourceCols);
269
+ const maxC = Math.max(...targetCols, ...sourceCols);
270
+ const bn = blockById.get(id);
271
+ const side = bn?.route === "above" ? "above" : "below";
272
+ fbInfos.push({ id, range: [minC, maxC], side, row: 0 });
273
+ }
274
+ fbInfos.sort((a, b) => {
275
+ const wa = a.range[1] - a.range[0];
276
+ const wb = b.range[1] - b.range[0];
277
+ if (wa !== wb) return wb - wa;
278
+ return a.range[0] - b.range[0];
279
+ });
280
+ const tracks = { above: [], below: [] };
281
+ for (const fb of fbInfos) {
282
+ let row = 1;
283
+ while (true) {
284
+ const occupied = tracks[fb.side].find((t) => t.row === row);
285
+ const conflict = occupied?.ranges.some(
286
+ ([a, b]) => !(fb.range[1] < a || fb.range[0] > b)
287
+ ) ?? false;
288
+ if (!conflict) {
289
+ if (occupied) occupied.ranges.push(fb.range);
290
+ else
291
+ tracks[fb.side].push({ row, side: fb.side, ranges: [fb.range] });
292
+ fb.row = row;
293
+ break;
294
+ }
295
+ row++;
296
+ }
297
+ }
298
+ const maxBelowRow = tracks.below.reduce((m, t) => Math.max(m, t.row), 0);
299
+ const maxAboveRow = tracks.above.reduce((m, t) => Math.max(m, t.row), 0);
300
+ const yFor = (side, row) => {
301
+ const step = FIRST_ROW_OFFSET + (row - 1) * ROW_GAP;
302
+ return side === "above" ? FWD_Y - step : FWD_Y + step;
303
+ };
304
+ const topOffset = maxAboveRow > 0 ? FIRST_ROW_OFFSET + (maxAboveRow - 1) * ROW_GAP + 30 : 30;
305
+ const forwardY = FWD_Y + (topOffset - 30);
306
+ const rowY = (side, row) => yFor(side, row) + (topOffset - 30);
307
+ let maxFwdCol = 0;
308
+ for (const id of nodeIds) {
309
+ if (!isFeedback.has(id)) maxFwdCol = Math.max(maxFwdCol, col.get(id) ?? 0);
310
+ }
311
+ const colCount = maxFwdCol + 1;
312
+ const colContent = new Array(colCount).fill(BLOCK_W);
313
+ const colX = [];
314
+ {
315
+ let x = LEFT_PAD;
316
+ for (let i = 0; i < colCount; i++) {
317
+ const w = i === 0 && hasIn ? 30 : colContent[i];
318
+ colX.push(x + w / 2);
319
+ x += w + COL_GAP;
320
+ }
321
+ }
322
+ const totalWidth = colX.length ? colX[colX.length - 1] + BLOCK_W / 2 + RIGHT_PAD : 400;
323
+ const fbById = /* @__PURE__ */ new Map();
324
+ for (const f of fbInfos) fbById.set(f.id, f);
325
+ const nodes = [];
326
+ const branchCount = /* @__PURE__ */ new Map();
327
+ for (const e of ast.connections) {
328
+ branchCount.set(e.from, (branchCount.get(e.from) ?? 0) + 1);
329
+ }
330
+ const hasBranchOf = (id) => (branchCount.get(id) ?? 0) > 1;
331
+ for (const b of ast.blocks) {
332
+ const c = col.get(b.id) ?? 0;
333
+ const cx = colX[Math.min(c, colX.length - 1)];
334
+ let cy = forwardY;
335
+ const fb = fbById.get(b.id);
336
+ if (fb) cy = rowY(fb.side, fb.row);
337
+ nodes.push({
338
+ kind: "block",
339
+ id: b.id,
340
+ label: b.label,
341
+ role: b.role ?? "generic",
342
+ x: cx - BLOCK_W / 2,
343
+ y: cy - BLOCK_H / 2,
344
+ width: BLOCK_W,
345
+ height: BLOCK_H,
346
+ hasBranch: hasBranchOf(b.id)
347
+ });
348
+ }
349
+ for (const s of ast.sums) {
350
+ const c = col.get(s.id) ?? 0;
351
+ const cx = colX[Math.min(c, colX.length - 1)];
352
+ let cy = forwardY;
353
+ const fb = fbById.get(s.id);
354
+ if (fb) cy = rowY(fb.side, fb.row);
355
+ nodes.push({
356
+ kind: "sum",
357
+ id: s.id,
358
+ cx,
359
+ cy,
360
+ r: SUM_R,
361
+ hasBranch: hasBranchOf(s.id)
362
+ });
363
+ }
364
+ if (hasIn) {
365
+ nodes.push({
366
+ kind: "port",
367
+ id: "in",
368
+ label: "in",
369
+ x: LEFT_PAD,
370
+ y: forwardY,
371
+ isInput: true,
372
+ hasBranch: hasBranchOf("in")
373
+ });
374
+ }
375
+ if (nodeIds.has("out")) {
376
+ const outCol = col.get("out") ?? maxFwdCol;
377
+ const cx = colX[Math.min(outCol, colX.length - 1)];
378
+ nodes.push({
379
+ kind: "port",
380
+ id: "out",
381
+ label: "out",
382
+ x: cx,
383
+ y: forwardY,
384
+ isInput: false
385
+ });
386
+ }
387
+ const anchors = /* @__PURE__ */ new Map();
388
+ for (const n of nodes) {
389
+ if (n.kind === "block") {
390
+ anchors.set(n.id, {
391
+ left: { x: n.x, y: n.y + n.height / 2 },
392
+ right: { x: n.x + n.width, y: n.y + n.height / 2 },
393
+ top: { x: n.x + n.width / 2, y: n.y },
394
+ bottom: { x: n.x + n.width / 2, y: n.y + n.height },
395
+ cx: n.x + n.width / 2,
396
+ cy: n.y + n.height / 2
397
+ });
398
+ } else if (n.kind === "sum") {
399
+ anchors.set(n.id, {
400
+ left: { x: n.cx - n.r, y: n.cy },
401
+ right: { x: n.cx + n.r, y: n.cy },
402
+ top: { x: n.cx, y: n.cy - n.r },
403
+ bottom: { x: n.cx, y: n.cy + n.r },
404
+ cx: n.cx,
405
+ cy: n.cy
406
+ });
407
+ } else {
408
+ anchors.set(n.id, {
409
+ left: { x: n.x - 10, y: n.y },
410
+ right: { x: n.x + (n.isInput ? 20 : 0), y: n.y },
411
+ top: { x: n.x, y: n.y - 10 },
412
+ bottom: { x: n.x, y: n.y + 10 },
413
+ cx: n.x,
414
+ cy: n.y
415
+ });
416
+ }
417
+ }
418
+ const sumPolarity = /* @__PURE__ */ new Map();
419
+ for (const s of ast.sums) {
420
+ const m = /* @__PURE__ */ new Map();
421
+ for (const tok of s.inputs) {
422
+ const sign = tok.startsWith("-") ? "-" : "+";
423
+ const srcId = tok.replace(/^[+-]/, "");
424
+ m.set(srcId, sign);
425
+ }
426
+ sumPolarity.set(s.id, m);
427
+ }
428
+ const edges = [];
429
+ const sumById = /* @__PURE__ */ new Map();
430
+ for (const s of ast.sums) sumById.set(s.id, s);
431
+ for (const e of ast.connections) {
432
+ const fromA = anchors.get(e.from);
433
+ const toA = anchors.get(e.to);
434
+ if (!fromA || !toA) continue;
435
+ const fromFb = fbById.get(e.from);
436
+ const toFb = fbById.get(e.to);
437
+ const fromCol = col.get(e.from) ?? 0;
438
+ const toCol = col.get(e.to) ?? 0;
439
+ let polarity;
440
+ if (sumById.has(e.to)) {
441
+ const pm = sumPolarity.get(e.to);
442
+ const sign = pm?.get(e.from) ?? "+";
443
+ let pin = "left";
444
+ if (fromFb?.side === "below") pin = "bottom";
445
+ else if (fromFb?.side === "above") pin = "top";
446
+ else if (fromCol < toCol) pin = "left";
447
+ else pin = "bottom";
448
+ const sumNode = nodes.find(
449
+ (n) => n.kind === "sum" && n.id === e.to
450
+ );
451
+ if (sumNode) {
452
+ let px = sumNode.cx, py = sumNode.cy;
453
+ if (pin === "left") {
454
+ px = sumNode.cx - sumNode.r - 8;
455
+ py = sumNode.cy + 6;
456
+ } else if (pin === "bottom") {
457
+ px = sumNode.cx - sumNode.r - 2;
458
+ py = sumNode.cy + sumNode.r + 10;
459
+ } else if (pin === "top") {
460
+ px = sumNode.cx - sumNode.r - 2;
461
+ py = sumNode.cy - sumNode.r - 2;
462
+ }
463
+ polarity = { sign, pin, x: px, y: py };
464
+ }
465
+ }
466
+ let path2;
467
+ let midX, midY;
468
+ let isFb = false;
469
+ const fromIsFbSide = fromFb?.side;
470
+ const toIsFbSide = toFb?.side;
471
+ if (fromIsFbSide && toIsFbSide === fromIsFbSide) {
472
+ const sx = fromA.left.x;
473
+ const sy = fromA.left.y;
474
+ const tx = toA.right.x;
475
+ const ty = toA.right.y;
476
+ path2 = `M ${sx} ${sy} L ${tx} ${ty}`;
477
+ midX = (sx + tx) / 2;
478
+ midY = sy - 6;
479
+ isFb = true;
480
+ } else if (!fromIsFbSide && toIsFbSide === "below") {
481
+ const sx = fromA.bottom.x;
482
+ const sy = fromA.bottom.y;
483
+ const tx = toA.right.x;
484
+ const ty = toA.right.y;
485
+ path2 = `M ${sx} ${sy} L ${sx} ${ty} L ${tx} ${ty}`;
486
+ midX = sx;
487
+ midY = (sy + ty) / 2;
488
+ isFb = true;
489
+ } else if (!fromIsFbSide && toIsFbSide === "above") {
490
+ const sx = fromA.top.x;
491
+ const sy = fromA.top.y;
492
+ const tx = toA.right.x;
493
+ const ty = toA.right.y;
494
+ path2 = `M ${sx} ${sy} L ${sx} ${ty} L ${tx} ${ty}`;
495
+ midX = sx;
496
+ midY = (sy + ty) / 2;
497
+ isFb = true;
498
+ } else if (fromIsFbSide === "below" && !toIsFbSide) {
499
+ const sx = fromA.left.x;
500
+ const sy = fromA.left.y;
501
+ const tx = toA.bottom.x;
502
+ const ty = toA.bottom.y;
503
+ path2 = `M ${sx} ${sy} L ${tx} ${sy} L ${tx} ${ty}`;
504
+ midX = (sx + tx) / 2;
505
+ midY = sy - 6;
506
+ isFb = true;
507
+ } else if (fromIsFbSide === "above" && !toIsFbSide) {
508
+ const sx = fromA.left.x;
509
+ const sy = fromA.left.y;
510
+ const tx = toA.top.x;
511
+ const ty = toA.top.y;
512
+ path2 = `M ${sx} ${sy} L ${tx} ${sy} L ${tx} ${ty}`;
513
+ midX = (sx + tx) / 2;
514
+ midY = sy - 6;
515
+ isFb = true;
516
+ } else if (toCol < fromCol) {
517
+ const sx = fromA.right.x;
518
+ const sy = fromA.right.y;
519
+ const tx = toA.bottom.x;
520
+ const ty = toA.bottom.y;
521
+ const dipY = Math.max(sy, ty) + 60;
522
+ path2 = `M ${sx} ${sy} L ${sx} ${dipY} L ${tx} ${dipY} L ${tx} ${ty}`;
523
+ midX = (sx + tx) / 2;
524
+ midY = dipY + 10;
525
+ isFb = true;
526
+ } else {
527
+ const sx = fromA.right.x;
528
+ const sy = fromA.right.y;
529
+ const tx = toA.left.x;
530
+ const ty = toA.left.y;
531
+ if (Math.abs(sy - ty) < 0.5) {
532
+ path2 = `M ${sx} ${sy} L ${tx} ${ty}`;
533
+ } else {
534
+ const midXH = (sx + tx) / 2;
535
+ path2 = `M ${sx} ${sy} L ${midXH} ${sy} L ${midXH} ${ty} L ${tx} ${ty}`;
536
+ }
537
+ midX = (sx + tx) / 2;
538
+ midY = sy - 8;
539
+ }
540
+ edges.push({
541
+ from: e.from,
542
+ to: e.to,
543
+ label: e.label,
544
+ discrete: !!e.discrete,
545
+ path: path2,
546
+ midX,
547
+ midY,
548
+ isFeedback: isFb,
549
+ polarity
550
+ });
551
+ }
552
+ const totalTopSpace = maxAboveRow > 0 ? FIRST_ROW_OFFSET + (maxAboveRow - 1) * ROW_GAP + 60 : 30;
553
+ const totalBottomSpace = maxBelowRow > 0 ? FIRST_ROW_OFFSET + (maxBelowRow - 1) * ROW_GAP + 60 : 100;
554
+ const height = Math.max(
555
+ forwardY + totalBottomSpace,
556
+ FWD_Y + 170,
557
+ totalTopSpace + totalBottomSpace
558
+ );
559
+ return {
560
+ width: totalWidth,
561
+ height,
562
+ nodes,
563
+ edges,
564
+ title: ast.title,
565
+ topOffset
566
+ };
567
+ }
568
+
569
+ // src/diagrams/blockdiagram/renderer.ts
570
+ var ROLE_FILL = {
571
+ plant: "#ffffff",
572
+ controller: "#E3F2FD",
573
+ sensor: "#F3E5F5",
574
+ actuator: "#E8F5E9",
575
+ filter: "#FFF8E1",
576
+ reference: "#ffffff",
577
+ disturbance: "#FFF3E0",
578
+ generic: "#ffffff"
579
+ };
580
+ function renderBlockDiagram(ast) {
581
+ const layout = layoutBlockDiagram(ast);
582
+ const titleOffset = ast.title ? 26 : 0;
583
+ const { width } = layout;
584
+ const height = layout.height + titleOffset;
585
+ const css = `
586
+ .schematex-bd { background: #fff; font-family: system-ui, -apple-system, sans-serif; }
587
+ .schematex-bd-block { stroke: #333; stroke-width: 2; }
588
+ .schematex-bd-tf { font: italic 14px serif; fill: #111; }
589
+ .schematex-bd-block-name { font: 10px sans-serif; fill: #666; }
590
+ .schematex-bd-sum { fill: #fff; stroke: #333; stroke-width: 2; }
591
+ .schematex-bd-sum-sign { font: bold 11px sans-serif; fill: #333; }
592
+ .schematex-bd-signal { stroke: #333; stroke-width: 2; fill: none; }
593
+ .schematex-bd-signal-discrete { stroke: #333; stroke-width: 2; fill: none; stroke-dasharray: 6 4; }
594
+ .schematex-bd-signal-label { font: italic 12px serif; fill: #333; }
595
+ .schematex-bd-port-label { font: italic 13px serif; fill: #111; }
596
+ .schematex-bd-title { font: bold 15px sans-serif; fill: #111; }
597
+ .schematex-bd-branch { fill: #333; stroke: none; }
598
+ `.trim();
599
+ const arrowDef = el(
600
+ "marker",
601
+ {
602
+ id: "lt-bd-arrow",
603
+ markerWidth: 10,
604
+ markerHeight: 8,
605
+ refX: 9,
606
+ refY: 4,
607
+ orient: "auto"
608
+ },
609
+ [el("polygon", { points: "0 0, 10 4, 0 8", fill: "#333" })]
610
+ );
611
+ const nodeSvgs = [];
612
+ const edgeSvgs = [];
613
+ const branchSvgs = [];
614
+ for (const n of layout.nodes) {
615
+ if (n.kind === "block") {
616
+ const fill = ROLE_FILL[n.role] ?? "#fff";
617
+ nodeSvgs.push(
618
+ group(
619
+ {
620
+ transform: `translate(${n.x}, ${n.y})`,
621
+ "data-block-id": n.id,
622
+ "data-block-role": n.role
623
+ },
624
+ [
625
+ el("rect", {
626
+ width: n.width,
627
+ height: n.height,
628
+ fill,
629
+ class: "schematex-bd-block",
630
+ rx: 2
631
+ }),
632
+ text(
633
+ {
634
+ x: n.width / 2,
635
+ y: n.height / 2 + 5,
636
+ "text-anchor": "middle",
637
+ class: "schematex-bd-tf"
638
+ },
639
+ n.label
640
+ )
641
+ ]
642
+ )
643
+ );
644
+ if (n.hasBranch) {
645
+ branchSvgs.push(
646
+ circle({
647
+ cx: n.x + n.width,
648
+ cy: n.y + n.height / 2,
649
+ r: 3.5,
650
+ class: "schematex-bd-branch"
651
+ })
652
+ );
653
+ }
654
+ } else if (n.kind === "sum") {
655
+ nodeSvgs.push(
656
+ group({ "data-sum-id": n.id }, [
657
+ circle({
658
+ cx: n.cx,
659
+ cy: n.cy,
660
+ r: n.r,
661
+ class: "schematex-bd-sum"
662
+ })
663
+ ])
664
+ );
665
+ if (n.hasBranch) {
666
+ branchSvgs.push(
667
+ circle({
668
+ cx: n.cx + n.r,
669
+ cy: n.cy,
670
+ r: 3.5,
671
+ class: "schematex-bd-branch"
672
+ })
673
+ );
674
+ }
675
+ } else if (n.kind === "port") {
676
+ nodeSvgs.push(
677
+ group({ "data-port-id": n.id }, [
678
+ text(
679
+ {
680
+ x: n.isInput ? n.x - 4 : n.x + 4,
681
+ y: n.y + 4,
682
+ "text-anchor": n.isInput ? "end" : "start",
683
+ class: "schematex-bd-port-label"
684
+ },
685
+ n.label
686
+ )
687
+ ])
688
+ );
689
+ }
690
+ }
691
+ for (const e of layout.edges) {
692
+ const cls = e.discrete ? "schematex-bd-signal-discrete" : "schematex-bd-signal";
693
+ edgeSvgs.push(
694
+ path({
695
+ d: e.path,
696
+ class: cls,
697
+ "marker-end": "url(#lt-bd-arrow)",
698
+ "data-from": e.from,
699
+ "data-to": e.to
700
+ })
701
+ );
702
+ if (e.label) {
703
+ edgeSvgs.push(
704
+ text(
705
+ {
706
+ x: e.midX,
707
+ y: e.midY,
708
+ "text-anchor": "middle",
709
+ class: "schematex-bd-signal-label"
710
+ },
711
+ e.label
712
+ )
713
+ );
714
+ }
715
+ if (e.polarity) {
716
+ edgeSvgs.push(
717
+ text(
718
+ {
719
+ x: e.polarity.x,
720
+ y: e.polarity.y,
721
+ "text-anchor": "middle",
722
+ class: "schematex-bd-sum-sign"
723
+ },
724
+ e.polarity.sign === "-" ? "\u2212" : "+"
725
+ )
726
+ );
727
+ }
728
+ }
729
+ const titleSvg = ast.title ? text(
730
+ {
731
+ x: width / 2,
732
+ y: 18,
733
+ "text-anchor": "middle",
734
+ class: "schematex-bd-title"
735
+ },
736
+ ast.title
737
+ ) : "";
738
+ return svgRoot(
739
+ {
740
+ class: "schematex-bd",
741
+ viewBox: `0 0 ${width} ${height}`,
742
+ width,
743
+ height,
744
+ role: "img",
745
+ "data-diagram-type": "blockdiagram"
746
+ },
747
+ [
748
+ title(ast.title ?? "Block Diagram"),
749
+ desc(
750
+ `Block diagram with ${ast.blocks.length} blocks, ${ast.sums.length} summing junctions, ${ast.connections.length} signals`
751
+ ),
752
+ defs([el("style", {}, css), arrowDef]),
753
+ titleSvg,
754
+ group({ transform: `translate(0, ${titleOffset})` }, [
755
+ group({ class: "schematex-bd-signals" }, edgeSvgs),
756
+ group({ class: "schematex-bd-nodes" }, nodeSvgs),
757
+ group({ class: "schematex-bd-branches" }, branchSvgs)
758
+ ])
759
+ ]
760
+ );
761
+ }
762
+
763
+ // src/diagrams/blockdiagram/index.ts
764
+ var blockdiagram = {
765
+ type: "blockdiagram",
766
+ detect(text2) {
767
+ const first = text2.trim().split("\n")[0]?.trim().toLowerCase() ?? "";
768
+ return first.startsWith("blockdiagram");
769
+ },
770
+ render(text2) {
771
+ const ast = parseBlockDiagram(text2);
772
+ return renderBlockDiagram(ast);
773
+ }
774
+ };
775
+
776
+ export { blockdiagram, layoutBlockDiagram, parseBlockDiagram, renderBlockDiagram };
777
+ //# sourceMappingURL=chunk-4G7ZIBHN.js.map
778
+ //# sourceMappingURL=chunk-4G7ZIBHN.js.map