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,869 @@
1
+ import { resolveIndustrialTheme } from './chunk-IX554O5K.js';
2
+ import { group, el, text, circle, path, svgRoot, title, desc, defs, polygon } from './chunk-KLJEK547.js';
3
+
4
+ // src/diagrams/logic/parser.ts
5
+ var LogicParseError = class extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = "LogicParseError";
9
+ }
10
+ };
11
+ var GATE_TYPES = /* @__PURE__ */ new Set([
12
+ "AND",
13
+ "OR",
14
+ "NOT",
15
+ "NAND",
16
+ "NOR",
17
+ "XOR",
18
+ "XNOR",
19
+ "BUF",
20
+ "TRISTATE_BUF",
21
+ "TRISTATE_INV",
22
+ "OPEN_DRAIN",
23
+ "SCHMITT",
24
+ "DFF",
25
+ "JKFF",
26
+ "SRFF",
27
+ "TFF",
28
+ "LATCH_SR",
29
+ "LATCH_D",
30
+ "MUX",
31
+ "DEMUX",
32
+ "DECODER",
33
+ "ENCODER",
34
+ "COUNTER",
35
+ "SHIFT_REG"
36
+ ]);
37
+ function splitIds(s) {
38
+ return s.split(",").map((x) => x.trim()).filter(Boolean);
39
+ }
40
+ function parseInputList(s) {
41
+ return s.split(",").map((x) => x.trim()).filter(Boolean).map((tok) => {
42
+ const eq = tok.indexOf("=");
43
+ return eq >= 0 ? tok.slice(eq + 1).trim() : tok;
44
+ });
45
+ }
46
+ function parseLogic(text2) {
47
+ const lines = text2.split("\n").map((l) => l.replace(/\r$/, "").trim());
48
+ let title2;
49
+ let style;
50
+ const inputs = [];
51
+ const outputs = [];
52
+ const gates = [];
53
+ const modules = [];
54
+ const moduleStack = [];
55
+ let moduleCounter = 0;
56
+ const explicitOutputFrom = /* @__PURE__ */ new Map();
57
+ for (const rawLine of lines) {
58
+ const line = rawLine.replace(/#.*$/, "").replace(/--.*$/, "").trim();
59
+ if (!line) continue;
60
+ const modOpen = line.match(/^module\s+(?:"([^"]+)"|([a-zA-Z_][\w]*))\s*\{$/);
61
+ if (modOpen) {
62
+ const label = modOpen[1] ?? modOpen[2];
63
+ const id = `mod_${moduleCounter++}`;
64
+ modules.push({ id, label });
65
+ moduleStack.push(id);
66
+ continue;
67
+ }
68
+ if (line === "}") {
69
+ if (moduleStack.length === 0) {
70
+ throw new LogicParseError("Unmatched `}` \u2014 no open module");
71
+ }
72
+ moduleStack.pop();
73
+ continue;
74
+ }
75
+ if (/^logic\b/i.test(line)) {
76
+ const t = line.match(/"([^"]*)"/);
77
+ if (t) title2 = t[1];
78
+ const s = line.match(/style\s*:\s*(ansi|iec)/i);
79
+ if (s) style = s[1].toLowerCase();
80
+ continue;
81
+ }
82
+ const inputMatch = line.match(/^input\s+(.+)$/i);
83
+ if (inputMatch) {
84
+ for (const id of splitIds(inputMatch[1])) {
85
+ const isLow = id.startsWith("~");
86
+ const clean = isLow ? id.slice(1) : id;
87
+ inputs.push({ id: clean, label: clean, isActiveLow: isLow || void 0 });
88
+ }
89
+ continue;
90
+ }
91
+ const outputMatch = line.match(/^output\s+(.+)$/i);
92
+ if (outputMatch) {
93
+ for (const id of splitIds(outputMatch[1])) {
94
+ outputs.push({ id, label: id, from: id });
95
+ }
96
+ continue;
97
+ }
98
+ const assignMatch = line.match(/^([a-zA-Z_][\w]*)\s*<-\s*([a-zA-Z_][\w]*)$/);
99
+ if (assignMatch) {
100
+ explicitOutputFrom.set(assignMatch[1], assignMatch[2]);
101
+ continue;
102
+ }
103
+ const gateMatch = line.match(/^([a-zA-Z_][\w]*)\s*=\s*([A-Za-z_][\w]*)\s*\(([^)]*)\)$/);
104
+ if (gateMatch) {
105
+ const id = gateMatch[1];
106
+ const rawType = gateMatch[2].toUpperCase();
107
+ if (!GATE_TYPES.has(rawType)) {
108
+ throw new LogicParseError(`Unknown gate type: ${rawType}`);
109
+ }
110
+ const gInputs = parseInputList(gateMatch[3]);
111
+ const moduleId = moduleStack[moduleStack.length - 1];
112
+ gates.push({ id, gateType: rawType, inputs: gInputs, moduleId });
113
+ continue;
114
+ }
115
+ }
116
+ if (moduleStack.length > 0) {
117
+ throw new LogicParseError(`Unclosed module (${moduleStack.length} open)`);
118
+ }
119
+ for (const out of outputs) {
120
+ const mapped = explicitOutputFrom.get(out.id);
121
+ if (mapped) out.from = mapped;
122
+ else if (gates.some((g) => g.id === out.id)) out.from = out.id;
123
+ }
124
+ const known = /* @__PURE__ */ new Set([
125
+ ...inputs.map((i) => i.id),
126
+ ...gates.map((g) => g.id)
127
+ ]);
128
+ for (const g of gates) {
129
+ for (const inp of g.inputs) {
130
+ const clean = inp.startsWith("~") ? inp.slice(1) : inp;
131
+ if (!known.has(clean)) {
132
+ throw new LogicParseError(`Unknown signal "${clean}" in gate ${g.id}`);
133
+ }
134
+ }
135
+ }
136
+ return {
137
+ type: "logic",
138
+ title: title2,
139
+ style: style ?? "ansi",
140
+ inputs,
141
+ outputs,
142
+ gates,
143
+ modules: modules.length > 0 ? modules : void 0
144
+ };
145
+ }
146
+
147
+ // src/diagrams/logic/symbols.ts
148
+ function combPins(nInputs, _width, leftX) {
149
+ const pins = [];
150
+ if (nInputs === 1) {
151
+ pins.push({ id: "in1", x: leftX, y: 30 });
152
+ } else if (nInputs === 2) {
153
+ pins.push({ id: "in1", x: leftX, y: 15 });
154
+ pins.push({ id: "in2", x: leftX, y: 45 });
155
+ } else {
156
+ const step = 50 / (nInputs - 1);
157
+ for (let i = 0; i < nInputs; i++) {
158
+ pins.push({ id: `in${i + 1}`, x: leftX, y: 5 + step * i });
159
+ }
160
+ }
161
+ return pins;
162
+ }
163
+ function getGateGeometry(gateType, inputCount) {
164
+ switch (gateType) {
165
+ case "AND":
166
+ case "NAND": {
167
+ const bubble = gateType === "NAND";
168
+ return {
169
+ width: bubble ? 90 : 80,
170
+ height: 60,
171
+ inputPins: combPins(inputCount, 80, 20).map((p) => ({ ...p, x: 20 })),
172
+ outputPins: [{ id: "out", x: bubble ? 90 : 80, y: 30, bubble }],
173
+ ansiPath: "M 20,60 L 20,0 Q 80,0 80,30 Q 80,60 20,60 Z",
174
+ outputBubble: bubble,
175
+ iecLabel: "&"
176
+ };
177
+ }
178
+ case "OR":
179
+ case "NOR": {
180
+ const bubble = gateType === "NOR";
181
+ return {
182
+ width: bubble ? 80 : 70,
183
+ height: 60,
184
+ inputPins: combPins(inputCount, 80, 18).map((p) => ({ ...p, x: 18 })),
185
+ outputPins: [{ id: "out", x: bubble ? 80 : 70, y: 30, bubble }],
186
+ ansiPath: "M 15,60 Q 10,30 15,0 Q 30,15 70,30 Q 30,45 15,60 Z",
187
+ outputBubble: bubble,
188
+ iecLabel: "\u22651"
189
+ };
190
+ }
191
+ case "XOR":
192
+ case "XNOR": {
193
+ const bubble = gateType === "XNOR";
194
+ return {
195
+ width: bubble ? 80 : 70,
196
+ height: 60,
197
+ inputPins: combPins(inputCount, 80, 12).map((p) => ({ ...p, x: 12 })),
198
+ outputPins: [{ id: "out", x: bubble ? 80 : 70, y: 30, bubble }],
199
+ ansiPath: "M 15,60 Q 10,30 15,0 Q 30,15 70,30 Q 30,45 15,60 Z M 8,60 Q 3,30 8,0",
200
+ outputBubble: bubble,
201
+ iecLabel: "=1"
202
+ };
203
+ }
204
+ case "NOT": {
205
+ return {
206
+ width: 70,
207
+ height: 60,
208
+ inputPins: [{ id: "in1", x: 10, y: 30 }],
209
+ outputPins: [{ id: "out", x: 70, y: 30, bubble: true }],
210
+ ansiPath: "M 10,55 L 60,30 L 10,5 Z",
211
+ outputBubble: true,
212
+ iecLabel: "1"
213
+ };
214
+ }
215
+ case "BUF":
216
+ case "SCHMITT": {
217
+ return {
218
+ width: 60,
219
+ height: 60,
220
+ inputPins: [{ id: "in1", x: 10, y: 30 }],
221
+ outputPins: [{ id: "out", x: 60, y: 30 }],
222
+ ansiPath: "M 10,55 L 60,30 L 10,5 Z",
223
+ iecLabel: "1"
224
+ };
225
+ }
226
+ case "TRISTATE_BUF":
227
+ case "TRISTATE_INV":
228
+ case "OPEN_DRAIN": {
229
+ const bubble = gateType === "TRISTATE_INV";
230
+ return {
231
+ width: bubble ? 70 : 60,
232
+ height: 70,
233
+ inputPins: [
234
+ { id: "in1", x: 10, y: 30 },
235
+ { id: "en", x: 35, y: 65, label: "EN" }
236
+ ],
237
+ outputPins: [{ id: "out", x: bubble ? 70 : 60, y: 30, bubble }],
238
+ ansiPath: "M 10,55 L 60,30 L 10,5 Z",
239
+ outputBubble: bubble,
240
+ iecLabel: "1"
241
+ };
242
+ }
243
+ case "DFF": {
244
+ return {
245
+ width: 60,
246
+ height: 80,
247
+ inputPins: [
248
+ { id: "D", x: 0, y: 20, label: "D" },
249
+ { id: "CLK", x: 0, y: 50, label: "" }
250
+ ],
251
+ outputPins: [
252
+ { id: "Q", x: 60, y: 20, label: "Q" },
253
+ { id: "Qn", x: 60, y: 60, label: "Q\u0304", bubble: true }
254
+ ],
255
+ ansiPath: "M 0,0 H 60 V 80 H 0 Z",
256
+ clockPin: "CLK",
257
+ iecLabel: "DFF"
258
+ };
259
+ }
260
+ case "JKFF": {
261
+ return {
262
+ width: 60,
263
+ height: 80,
264
+ inputPins: [
265
+ { id: "J", x: 0, y: 15, label: "J" },
266
+ { id: "CLK", x: 0, y: 40 },
267
+ { id: "K", x: 0, y: 65, label: "K" }
268
+ ],
269
+ outputPins: [
270
+ { id: "Q", x: 60, y: 20, label: "Q" },
271
+ { id: "Qn", x: 60, y: 60, label: "Q\u0304", bubble: true }
272
+ ],
273
+ ansiPath: "M 0,0 H 60 V 80 H 0 Z",
274
+ clockPin: "CLK",
275
+ iecLabel: "JK"
276
+ };
277
+ }
278
+ case "SRFF":
279
+ case "LATCH_SR": {
280
+ return {
281
+ width: 60,
282
+ height: 80,
283
+ inputPins: [
284
+ { id: "S", x: 0, y: 20, label: "S" },
285
+ { id: "R", x: 0, y: 60, label: "R" }
286
+ ],
287
+ outputPins: [
288
+ { id: "Q", x: 60, y: 20, label: "Q" },
289
+ { id: "Qn", x: 60, y: 60, label: "Q\u0304", bubble: true }
290
+ ],
291
+ ansiPath: "M 0,0 H 60 V 80 H 0 Z",
292
+ iecLabel: "SR"
293
+ };
294
+ }
295
+ case "TFF": {
296
+ return {
297
+ width: 60,
298
+ height: 80,
299
+ inputPins: [
300
+ { id: "T", x: 0, y: 20, label: "T" },
301
+ { id: "CLK", x: 0, y: 50 }
302
+ ],
303
+ outputPins: [
304
+ { id: "Q", x: 60, y: 20, label: "Q" },
305
+ { id: "Qn", x: 60, y: 60, label: "Q\u0304", bubble: true }
306
+ ],
307
+ ansiPath: "M 0,0 H 60 V 80 H 0 Z",
308
+ clockPin: "CLK",
309
+ iecLabel: "T"
310
+ };
311
+ }
312
+ case "LATCH_D": {
313
+ return {
314
+ width: 60,
315
+ height: 80,
316
+ inputPins: [
317
+ { id: "D", x: 0, y: 20, label: "D" },
318
+ { id: "E", x: 0, y: 60, label: "E" }
319
+ ],
320
+ outputPins: [
321
+ { id: "Q", x: 60, y: 20, label: "Q" },
322
+ { id: "Qn", x: 60, y: 60, label: "Q\u0304", bubble: true }
323
+ ],
324
+ ansiPath: "M 0,0 H 60 V 80 H 0 Z",
325
+ iecLabel: "D"
326
+ };
327
+ }
328
+ default: {
329
+ const ins = Math.max(inputCount, 2);
330
+ const inputPins = combPins(ins, 100, 0).map((p, i) => ({
331
+ ...p,
332
+ x: 0,
333
+ label: `I${i}`
334
+ }));
335
+ return {
336
+ width: 100,
337
+ height: 80,
338
+ inputPins,
339
+ outputPins: [{ id: "out", x: 100, y: 40 }],
340
+ ansiPath: "M 0,0 H 100 V 80 H 0 Z",
341
+ iecLabel: gateType
342
+ };
343
+ }
344
+ }
345
+ }
346
+
347
+ // src/diagrams/logic/layout.ts
348
+ var LAYER_GAP = 80;
349
+ var ROW_GAP = 40;
350
+ var PORT_SIZE = 40;
351
+ var PORT_H = 30;
352
+ function layoutLogic(ast) {
353
+ const layerOf = /* @__PURE__ */ new Map();
354
+ for (const inp of ast.inputs) layerOf.set(inp.id, 0);
355
+ const pending = new Set(ast.gates.map((g) => g.id));
356
+ let safety = 0;
357
+ while (pending.size > 0 && safety++ < 1e3) {
358
+ for (const g of ast.gates) {
359
+ if (!pending.has(g.id)) continue;
360
+ let maxDep = -1;
361
+ let ready = true;
362
+ for (const inp of g.inputs) {
363
+ const clean = inp.startsWith("~") ? inp.slice(1) : inp;
364
+ const l = layerOf.get(clean);
365
+ if (l === void 0) {
366
+ ready = false;
367
+ break;
368
+ }
369
+ if (l > maxDep) maxDep = l;
370
+ }
371
+ if (ready) {
372
+ layerOf.set(g.id, maxDep + 1);
373
+ pending.delete(g.id);
374
+ }
375
+ }
376
+ }
377
+ if (pending.size > 0) {
378
+ for (const id of pending) layerOf.set(id, 1);
379
+ }
380
+ const outputLayer = Math.max(0, ...Array.from(layerOf.values())) + 1;
381
+ const outTermId = (o) => `$out$${o.id}`;
382
+ const portOutputs = ast.outputs.map((o) => ({
383
+ ...o,
384
+ termId: outTermId(o),
385
+ source: o.from
386
+ }));
387
+ for (const o of portOutputs) layerOf.set(o.termId, outputLayer);
388
+ const layers = /* @__PURE__ */ new Map();
389
+ const addToLayer = (id, layer) => {
390
+ if (!layers.has(layer)) layers.set(layer, []);
391
+ layers.get(layer).push(id);
392
+ };
393
+ for (const i of ast.inputs) addToLayer(i.id, 0);
394
+ for (const g of ast.gates) addToLayer(g.id, layerOf.get(g.id));
395
+ for (const o of portOutputs) addToLayer(o.termId, outputLayer);
396
+ const gateGeoms = /* @__PURE__ */ new Map();
397
+ for (const g of ast.gates) {
398
+ gateGeoms.set(g.id, getGateGeometry(g.gateType, g.inputs.length));
399
+ }
400
+ const nodes = [];
401
+ const sortedLayers = Array.from(layers.keys()).sort((a, b) => a - b);
402
+ const layerWidth = /* @__PURE__ */ new Map();
403
+ for (const [layerIdx, ids] of layers) {
404
+ let maxW = 60;
405
+ for (const id of ids) {
406
+ const g = gateGeoms.get(id);
407
+ if (g && g.width > maxW) maxW = g.width;
408
+ if (!g && layerIdx === 0) maxW = Math.max(maxW, PORT_SIZE);
409
+ if (!g && layerIdx === outputLayer) maxW = Math.max(maxW, PORT_SIZE);
410
+ }
411
+ layerWidth.set(layerIdx, maxW);
412
+ }
413
+ let cursorX = 20;
414
+ const layerStartMap = /* @__PURE__ */ new Map();
415
+ for (const layerIdx of sortedLayers) {
416
+ layerStartMap.set(layerIdx, cursorX);
417
+ cursorX += (layerWidth.get(layerIdx) ?? 60) + LAYER_GAP;
418
+ }
419
+ const totalW = cursorX;
420
+ const heightOf = (id) => {
421
+ const g = gateGeoms.get(id);
422
+ if (g) return g.height;
423
+ return PORT_H;
424
+ };
425
+ let maxColH = 0;
426
+ for (const ids of layers.values()) {
427
+ const total = ids.reduce((s, id) => s + heightOf(id), 0) + (ids.length - 1) * ROW_GAP;
428
+ if (total > maxColH) maxColH = total;
429
+ }
430
+ const totalH = maxColH + 80;
431
+ const nodeInfo = /* @__PURE__ */ new Map();
432
+ for (const [layerIdx, ids] of layers) {
433
+ const xStart = layerStartMap.get(layerIdx);
434
+ const total = ids.reduce((s, id) => s + heightOf(id), 0) + (ids.length - 1) * ROW_GAP;
435
+ let y = 40 + (maxColH - total) / 2;
436
+ for (const id of ids) {
437
+ const h = heightOf(id);
438
+ const g = gateGeoms.get(id);
439
+ let node;
440
+ if (layerIdx === 0) {
441
+ const inp = ast.inputs.find((i) => i.id === id);
442
+ node = {
443
+ id,
444
+ kind: "input",
445
+ x: xStart,
446
+ y,
447
+ layer: 0,
448
+ label: inp.label,
449
+ isActiveLow: inp.isActiveLow
450
+ };
451
+ } else if (layerIdx === outputLayer && !g && id.startsWith("$out$")) {
452
+ const out = portOutputs.find((o) => o.termId === id);
453
+ node = {
454
+ id,
455
+ kind: "output",
456
+ x: xStart,
457
+ y,
458
+ layer: outputLayer,
459
+ label: out.label,
460
+ isActiveLow: out.isActiveLow
461
+ };
462
+ } else {
463
+ node = {
464
+ id,
465
+ kind: "gate",
466
+ x: xStart,
467
+ y,
468
+ layer: layerIdx,
469
+ geometry: g,
470
+ gateType: ast.gates.find((gg) => gg.id === id).gateType,
471
+ label: id
472
+ };
473
+ }
474
+ nodes.push(node);
475
+ nodeInfo.set(id, node);
476
+ y += h + ROW_GAP;
477
+ }
478
+ }
479
+ const wires = [];
480
+ const getSourcePoint = (id) => {
481
+ const n = nodeInfo.get(id);
482
+ if (!n) return null;
483
+ if (n.kind === "input") return { x: n.x + PORT_SIZE, y: n.y + PORT_H / 2 };
484
+ if (n.kind === "gate" && n.geometry) {
485
+ const out = n.geometry.outputPins[0];
486
+ return { x: n.x + out.x, y: n.y + out.y };
487
+ }
488
+ return null;
489
+ };
490
+ for (const g of ast.gates) {
491
+ const target = nodeInfo.get(g.id);
492
+ if (!target || !target.geometry) continue;
493
+ g.inputs.forEach((rawInp, idx) => {
494
+ const isLow = rawInp.startsWith("~");
495
+ const srcId = isLow ? rawInp.slice(1) : rawInp;
496
+ const src = getSourcePoint(srcId);
497
+ if (!src) return;
498
+ const pin = target.geometry.inputPins[idx];
499
+ if (!pin) return;
500
+ const toX = target.x + pin.x;
501
+ const toY = target.y + pin.y;
502
+ const midX = (src.x + toX) / 2;
503
+ const path2 = `M ${src.x},${src.y} L ${midX},${src.y} L ${midX},${toY} L ${toX},${toY}`;
504
+ wires.push({
505
+ fromNode: srcId,
506
+ fromX: src.x,
507
+ fromY: src.y,
508
+ toNode: g.id,
509
+ toX,
510
+ toY,
511
+ isActiveLow: isLow,
512
+ path: path2
513
+ });
514
+ });
515
+ }
516
+ for (const o of portOutputs) {
517
+ const src = getSourcePoint(o.source);
518
+ const target = nodeInfo.get(o.termId);
519
+ if (!src || !target || target.kind !== "output") continue;
520
+ const toX = target.x;
521
+ const toY = target.y + PORT_H / 2;
522
+ let path2;
523
+ if (Math.abs(src.y - toY) < 0.5) {
524
+ path2 = `M ${src.x},${src.y} L ${toX},${toY}`;
525
+ } else {
526
+ const midX = (src.x + toX) / 2;
527
+ path2 = `M ${src.x},${src.y} L ${midX},${src.y} L ${midX},${toY} L ${toX},${toY}`;
528
+ }
529
+ wires.push({
530
+ fromNode: o.source,
531
+ fromX: src.x,
532
+ fromY: src.y,
533
+ toNode: o.termId,
534
+ toX,
535
+ toY,
536
+ path: path2
537
+ });
538
+ }
539
+ const modules = [];
540
+ if (ast.modules && ast.modules.length > 0) {
541
+ const PAD = 14;
542
+ for (const mod of ast.modules) {
543
+ const memberIds = new Set(
544
+ ast.gates.filter((g) => g.moduleId === mod.id).map((g) => g.id)
545
+ );
546
+ if (memberIds.size === 0) continue;
547
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
548
+ for (const n of nodes) {
549
+ if (!memberIds.has(n.id)) continue;
550
+ const w = n.geometry?.width ?? 60;
551
+ const h = n.geometry?.height ?? 60;
552
+ if (n.x < minX) minX = n.x;
553
+ if (n.y < minY) minY = n.y;
554
+ if (n.x + w > maxX) maxX = n.x + w;
555
+ if (n.y + h > maxY) maxY = n.y + h;
556
+ }
557
+ if (!isFinite(minX)) continue;
558
+ modules.push({
559
+ id: mod.id,
560
+ label: mod.label,
561
+ x: minX - PAD,
562
+ y: minY - PAD - 4,
563
+ width: maxX - minX + PAD * 2,
564
+ height: maxY - minY + PAD * 2 + 4
565
+ });
566
+ }
567
+ }
568
+ return { width: totalW, height: totalH, nodes, wires, modules };
569
+ }
570
+
571
+ // src/diagrams/logic/renderer.ts
572
+ var PORT_SIZE2 = 40;
573
+ var PORT_H2 = 30;
574
+ function renderGateBody(n, style) {
575
+ const out = [];
576
+ if (!n.geometry) return out;
577
+ const g = n.geometry;
578
+ if (style === "iec") {
579
+ out.push(
580
+ el("rect", {
581
+ x: 0,
582
+ y: 0,
583
+ width: g.width,
584
+ height: g.height,
585
+ class: "schematex-logic-gate-body"
586
+ })
587
+ );
588
+ if (g.iecLabel) {
589
+ out.push(
590
+ text(
591
+ {
592
+ x: g.width / 2,
593
+ y: g.height / 2 + 4,
594
+ class: "schematex-logic-gate-iec-label",
595
+ "text-anchor": "middle"
596
+ },
597
+ g.iecLabel
598
+ )
599
+ );
600
+ }
601
+ } else {
602
+ out.push(
603
+ el("path", { d: g.ansiPath, class: "schematex-logic-gate-body" })
604
+ );
605
+ }
606
+ if (g.outputBubble) {
607
+ const op = g.outputPins[0];
608
+ out.push(
609
+ circle({
610
+ cx: op.x - 4,
611
+ cy: op.y,
612
+ r: 4,
613
+ class: "schematex-logic-bubble"
614
+ })
615
+ );
616
+ }
617
+ if (g.clockPin) {
618
+ const cp = g.inputPins.find((p) => p.id === g.clockPin);
619
+ if (cp) {
620
+ out.push(
621
+ polygon({
622
+ points: `${cp.x},${cp.y - 5} ${cp.x + 8},${cp.y} ${cp.x},${cp.y + 5}`,
623
+ class: "schematex-logic-clock-tri"
624
+ })
625
+ );
626
+ }
627
+ }
628
+ for (const op of g.outputPins) {
629
+ if (op.bubble && op.id !== "out") {
630
+ out.push(
631
+ circle({
632
+ cx: op.x + 4,
633
+ cy: op.y,
634
+ r: 4,
635
+ class: "schematex-logic-bubble"
636
+ })
637
+ );
638
+ }
639
+ }
640
+ for (const pin of g.inputPins) {
641
+ if (pin.label && pin.id !== g.clockPin) {
642
+ out.push(
643
+ text(
644
+ {
645
+ x: pin.x + 5,
646
+ y: pin.y + 3,
647
+ class: "schematex-logic-pin-label"
648
+ },
649
+ pin.label
650
+ )
651
+ );
652
+ }
653
+ }
654
+ for (const pin of g.outputPins) {
655
+ if (pin.label) {
656
+ out.push(
657
+ text(
658
+ {
659
+ x: pin.x - 6,
660
+ y: pin.y + 3,
661
+ class: "schematex-logic-pin-label",
662
+ "text-anchor": "end"
663
+ },
664
+ pin.label
665
+ )
666
+ );
667
+ }
668
+ }
669
+ if (style === "ansi" && g.iecLabel && g.height >= 60) {
670
+ const labelX = g.width / 2;
671
+ const labelY = g.height + 14;
672
+ out.push(
673
+ text(
674
+ {
675
+ x: labelX,
676
+ y: labelY,
677
+ class: "schematex-logic-gate-type",
678
+ "text-anchor": "middle"
679
+ },
680
+ n.gateType ?? ""
681
+ )
682
+ );
683
+ }
684
+ return out;
685
+ }
686
+ function renderLogic(ast, config) {
687
+ const style = ast.style ?? "ansi";
688
+ const layout = layoutLogic(ast);
689
+ const { width, height } = layout;
690
+ const t = resolveIndustrialTheme(config?.theme ?? "default");
691
+ const gateSvgs = [];
692
+ const portSvgs = [];
693
+ const moduleSvgs = [];
694
+ for (const m of layout.modules) {
695
+ moduleSvgs.push(
696
+ group({ "data-module-id": m.id }, [
697
+ el("rect", {
698
+ x: m.x,
699
+ y: m.y,
700
+ width: m.width,
701
+ height: m.height,
702
+ rx: 6,
703
+ class: "schematex-logic-module"
704
+ }),
705
+ text(
706
+ {
707
+ x: m.x + 10,
708
+ y: m.y + 14,
709
+ class: "schematex-logic-module-label"
710
+ },
711
+ m.label
712
+ )
713
+ ])
714
+ );
715
+ }
716
+ for (const n of layout.nodes) {
717
+ if (n.kind === "gate") {
718
+ gateSvgs.push(
719
+ group(
720
+ {
721
+ transform: `translate(${n.x}, ${n.y})`,
722
+ "data-gate-id": n.id,
723
+ "data-gate-type": n.gateType ?? ""
724
+ },
725
+ renderGateBody(n, style)
726
+ )
727
+ );
728
+ } else if (n.kind === "input") {
729
+ const cy = PORT_H2 / 2;
730
+ portSvgs.push(
731
+ group({ transform: `translate(${n.x}, ${n.y})`, "data-port": "input" }, [
732
+ text(
733
+ {
734
+ x: 0,
735
+ y: cy + 4,
736
+ "text-anchor": "start",
737
+ class: "schematex-logic-port-label"
738
+ },
739
+ n.label
740
+ ),
741
+ el("line", {
742
+ x1: PORT_SIZE2 - 12,
743
+ y1: cy,
744
+ x2: n.isActiveLow ? PORT_SIZE2 - 8 : PORT_SIZE2,
745
+ y2: cy,
746
+ class: "schematex-logic-wire"
747
+ }),
748
+ n.isActiveLow ? circle({
749
+ cx: PORT_SIZE2 - 4,
750
+ cy,
751
+ r: 4,
752
+ class: "schematex-logic-bubble"
753
+ }) : ""
754
+ ])
755
+ );
756
+ } else if (n.kind === "output") {
757
+ const cy = PORT_H2 / 2;
758
+ portSvgs.push(
759
+ group({ transform: `translate(${n.x}, ${n.y})`, "data-port": "output" }, [
760
+ el("line", {
761
+ x1: 0,
762
+ y1: cy,
763
+ x2: 12,
764
+ y2: cy,
765
+ class: "schematex-logic-wire"
766
+ }),
767
+ text(
768
+ {
769
+ x: 16,
770
+ y: cy + 4,
771
+ "text-anchor": "start",
772
+ class: "schematex-logic-port-label"
773
+ },
774
+ n.label
775
+ )
776
+ ])
777
+ );
778
+ }
779
+ }
780
+ const wireSvgs = layout.wires.map((w) => {
781
+ const extras = [];
782
+ if (w.isActiveLow) {
783
+ extras.push(
784
+ circle({
785
+ cx: w.toX - 4,
786
+ cy: w.toY,
787
+ r: 4,
788
+ class: "schematex-logic-bubble"
789
+ })
790
+ );
791
+ }
792
+ return [
793
+ path({
794
+ d: w.path,
795
+ class: "schematex-logic-wire",
796
+ "data-from": w.fromNode,
797
+ "data-to": w.toNode
798
+ }),
799
+ ...extras
800
+ ].join("");
801
+ });
802
+ const css = `
803
+ .schematex-logic { background: ${t.bg}; font-family: system-ui, -apple-system, sans-serif; }
804
+ .schematex-logic-gate-body { fill: none; stroke: ${t.strokeHeavy}; stroke-width: 1.75; stroke-linejoin: round; }
805
+ .schematex-logic-bubble { fill: ${t.bg}; stroke: ${t.strokeHeavy}; stroke-width: 1.5; }
806
+ .schematex-logic-clock-tri { fill: none; stroke: ${t.strokeHeavy}; stroke-width: 1.5; stroke-linejoin: round; }
807
+ .schematex-logic-wire { stroke: ${t.strokeHeavy}; stroke-width: 1.5; fill: none; stroke-linecap: square; }
808
+ .schematex-logic-port-label { font: 13px system-ui, sans-serif; fill: ${t.text}; }
809
+ .schematex-logic-pin-label { font: 9px sans-serif; fill: ${t.stroke}; }
810
+ .schematex-logic-gate-type { font: 10px sans-serif; fill: ${t.textMuted}; }
811
+ .schematex-logic-gate-iec-label { font: bold 13px sans-serif; fill: ${t.text}; }
812
+ .schematex-logic-title { font: bold 14px sans-serif; fill: ${t.text}; }
813
+ .schematex-logic-module { fill: none; stroke: ${t.textMuted}; stroke-width: 1.25; stroke-dasharray: 6 4; }
814
+ .schematex-logic-module-label { font: 11px sans-serif; fill: ${t.textMuted}; font-style: italic; }
815
+ `.trim();
816
+ const titleSvg = ast.title ? text(
817
+ {
818
+ x: width / 2,
819
+ y: 18,
820
+ "text-anchor": "middle",
821
+ class: "schematex-logic-title"
822
+ },
823
+ ast.title
824
+ ) : "";
825
+ return svgRoot(
826
+ {
827
+ class: "schematex-logic",
828
+ viewBox: `0 0 ${width} ${height + (ast.title ? 20 : 0)}`,
829
+ width,
830
+ height: height + (ast.title ? 20 : 0),
831
+ role: "img",
832
+ "data-diagram-type": "logic"
833
+ },
834
+ [
835
+ title(ast.title ?? "Logic Gate Diagram"),
836
+ desc(
837
+ `Logic gate diagram with ${ast.gates.length} gates, ${ast.inputs.length} inputs, ${ast.outputs.length} outputs`
838
+ ),
839
+ defs([el("style", {}, css)]),
840
+ group(
841
+ { transform: `translate(0, ${ast.title ? 20 : 0})` },
842
+ [
843
+ group({ class: "schematex-logic-modules" }, moduleSvgs),
844
+ group({ class: "schematex-logic-wires" }, wireSvgs),
845
+ group({ class: "schematex-logic-gates" }, gateSvgs),
846
+ group({ class: "schematex-logic-ports" }, portSvgs)
847
+ ]
848
+ ),
849
+ titleSvg
850
+ ]
851
+ );
852
+ }
853
+
854
+ // src/diagrams/logic/index.ts
855
+ var logic = {
856
+ type: "logic",
857
+ detect(text2) {
858
+ const first = text2.trim().split("\n")[0]?.trim().toLowerCase() ?? "";
859
+ return first.startsWith("logic");
860
+ },
861
+ render(text2, config) {
862
+ const ast = parseLogic(text2);
863
+ return renderLogic(ast, config);
864
+ }
865
+ };
866
+
867
+ export { layoutLogic, logic, parseLogic, renderLogic };
868
+ //# sourceMappingURL=chunk-VFQCTXOX.js.map
869
+ //# sourceMappingURL=chunk-VFQCTXOX.js.map