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,1844 @@
1
+ import { resolveIndustrialTheme } from './chunk-IX554O5K.js';
2
+ import { text, svgRoot, title, desc, defs, el, group, circle, escapeXml } from './chunk-KLJEK547.js';
3
+
4
+ // src/diagrams/circuit/netlist.ts
5
+ var NetlistParseError = class extends Error {
6
+ constructor(message, line) {
7
+ super(message);
8
+ this.line = line;
9
+ this.name = "NetlistParseError";
10
+ }
11
+ line;
12
+ };
13
+ var PREFIX_MAP = {
14
+ R: { type: "resistor", pins: ["start", "end"] },
15
+ C: { type: "capacitor", pins: ["start", "end"] },
16
+ L: { type: "inductor", pins: ["start", "end"] },
17
+ D: { type: "diode", pins: ["start", "end"] },
18
+ // anode → start, cathode → end
19
+ V: { type: "voltage_source", pins: ["plus", "minus"] },
20
+ I: { type: "current_source", pins: ["plus", "minus"] },
21
+ Q: { type: "npn", pins: ["c", "b", "e"] },
22
+ M: { type: "nmos", pins: ["d", "g", "s"] },
23
+ J: { type: "jfet_n", pins: ["d", "g", "s"] },
24
+ S: { type: "switch_spst", pins: ["start", "end"] },
25
+ F: { type: "fuse", pins: ["start", "end"] },
26
+ B: { type: "battery", pins: ["plus", "minus"] },
27
+ K: { type: "relay_coil", pins: ["start", "end"] },
28
+ U: { type: "generic_ic", pins: [] },
29
+ // pins declared via pins="..." attr
30
+ X: { type: "generic_ic", pins: [] }
31
+ };
32
+ var TYPE_ALIASES = {
33
+ vsource: "voltage_source",
34
+ isource: "current_source",
35
+ acsource: "ac_source",
36
+ ecap: "electrolytic_cap",
37
+ pot: "potentiometer",
38
+ gnd: "ground",
39
+ ic: "generic_ic",
40
+ reg: "voltage_regulator",
41
+ timer555: "555_timer",
42
+ transistor: "npn"
43
+ };
44
+ var GROUND_NETS = /* @__PURE__ */ new Set(["0", "gnd", "GND", "Gnd", "ground", "Ground"]);
45
+ function tokenize(line) {
46
+ const tokens = [];
47
+ let i = 0;
48
+ while (i < line.length) {
49
+ const ch = line[i];
50
+ if (ch === " " || ch === " ") {
51
+ i++;
52
+ continue;
53
+ }
54
+ if (ch === '"') {
55
+ const end = line.indexOf('"', i + 1);
56
+ tokens.push(line.slice(i, end < 0 ? line.length : end + 1));
57
+ i = end < 0 ? line.length : end + 1;
58
+ continue;
59
+ }
60
+ let j = i;
61
+ while (j < line.length && line[j] !== " " && line[j] !== " ") {
62
+ if (line[j] === "=" && line[j + 1] === '"') {
63
+ const end = line.indexOf('"', j + 2);
64
+ j = end < 0 ? line.length : end + 1;
65
+ break;
66
+ }
67
+ j++;
68
+ }
69
+ tokens.push(line.slice(i, j));
70
+ i = j;
71
+ }
72
+ return tokens;
73
+ }
74
+ function isKeyEqVal(tok) {
75
+ const eq = tok.indexOf("=");
76
+ return eq > 0 && /^[a-zA-Z_][\w]*$/.test(tok.slice(0, eq));
77
+ }
78
+ function parseKV(tok) {
79
+ const eq = tok.indexOf("=");
80
+ const key = tok.slice(0, eq).trim();
81
+ let val = tok.slice(eq + 1).trim();
82
+ if (val.startsWith('"') && val.endsWith('"')) val = val.slice(1, -1);
83
+ return [key, val];
84
+ }
85
+ function parseNetlist(body, title2) {
86
+ const components = [];
87
+ const netByName = /* @__PURE__ */ new Map();
88
+ const pinMap = {};
89
+ let autoGnd = 0;
90
+ const ensureNet = (name) => {
91
+ let n = netByName.get(name);
92
+ if (!n) {
93
+ n = { id: name, anchors: [] };
94
+ netByName.set(name, n);
95
+ }
96
+ return n;
97
+ };
98
+ const lines = body.split("\n").map((l) => l.replace(/\r$/, ""));
99
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
100
+ const raw = lines[lineIdx];
101
+ const stripped = raw.replace(/#.*$/, "").trim();
102
+ if (!stripped) continue;
103
+ const tokens = tokenize(stripped);
104
+ if (tokens.length < 2) {
105
+ throw new NetlistParseError(
106
+ `Netlist line must have at least ID + one net: "${stripped}"`,
107
+ lineIdx + 1
108
+ );
109
+ }
110
+ const id = tokens[0];
111
+ if (!/^[a-zA-Z_][\w]*$/.test(id)) {
112
+ throw new NetlistParseError(`Invalid component id: "${id}"`, lineIdx + 1);
113
+ }
114
+ let cursor = 1;
115
+ const netRefs = [];
116
+ while (cursor < tokens.length && !isKeyEqVal(tokens[cursor])) {
117
+ netRefs.push(tokens[cursor]);
118
+ cursor++;
119
+ }
120
+ const kv = {};
121
+ for (; cursor < tokens.length; cursor++) {
122
+ if (!isKeyEqVal(tokens[cursor])) {
123
+ throw new NetlistParseError(
124
+ `Expected key=value after nets, got "${tokens[cursor]}"`,
125
+ lineIdx + 1
126
+ );
127
+ }
128
+ const [k, v] = parseKV(tokens[cursor]);
129
+ kv[k] = v;
130
+ }
131
+ const prefix = id[0].toUpperCase();
132
+ const defaults = PREFIX_MAP[prefix];
133
+ let cType;
134
+ let pinOrder;
135
+ if (kv.type) {
136
+ const t = kv.type.toLowerCase();
137
+ cType = TYPE_ALIASES[t] ?? t;
138
+ pinOrder = defaults?.pins ?? ["p1", "p2"];
139
+ } else if (defaults) {
140
+ cType = defaults.type;
141
+ pinOrder = defaults.pins;
142
+ } else {
143
+ throw new NetlistParseError(
144
+ `Cannot infer type from id "${id}" \u2014 use type= override`,
145
+ lineIdx + 1
146
+ );
147
+ }
148
+ const expectedPins = pinOrder.length;
149
+ let valueFromTail;
150
+ if (netRefs.length > expectedPins && expectedPins > 0) {
151
+ const tail = netRefs.slice(expectedPins);
152
+ netRefs.length = expectedPins;
153
+ const first = tail[0].toLowerCase();
154
+ if (TYPE_ALIASES[first]) {
155
+ cType = TYPE_ALIASES[first];
156
+ } else if (first === "npn" || first === "pnp" || first === "nmos" || first === "pmos" || first === "jfet_n" || first === "jfet_p" || first === "zener" || first === "schottky" || first === "led" || first === "photodiode") {
157
+ cType = first;
158
+ if (first === "pnp") pinOrder = ["c", "b", "e"];
159
+ if (first === "pmos" || first === "jfet_p") pinOrder = ["d", "g", "s"];
160
+ } else {
161
+ valueFromTail = tail.join(" ");
162
+ }
163
+ if (tail.length > 1 && !valueFromTail) {
164
+ valueFromTail = tail.slice(1).join(" ");
165
+ }
166
+ }
167
+ if (cType === "ground" || cType === "gnd_signal" || cType === "gnd_chassis" || cType === "gnd_digital") {
168
+ pinOrder = ["start"];
169
+ }
170
+ if (netRefs.length < pinOrder.length) {
171
+ throw new NetlistParseError(
172
+ `Component ${id} (${cType}) expects ${pinOrder.length} nets, got ${netRefs.length}`,
173
+ lineIdx + 1
174
+ );
175
+ }
176
+ const pins = {};
177
+ for (let p = 0; p < pinOrder.length; p++) {
178
+ let net = netRefs[p];
179
+ if (GROUND_NETS.has(net)) net = "GND";
180
+ pins[pinOrder[p]] = net;
181
+ ensureNet(net).anchors.push(`${id}.${pinOrder[p]}`);
182
+ }
183
+ pinMap[id] = pins;
184
+ const comp = {
185
+ id,
186
+ componentType: cType,
187
+ direction: "right",
188
+ label: kv.label ?? id,
189
+ value: kv.value ?? valueFromTail,
190
+ attrs: {}
191
+ };
192
+ for (const [k, v] of Object.entries(kv)) {
193
+ if (k === "label" || k === "value" || k === "type") continue;
194
+ comp.attrs[k] = v;
195
+ }
196
+ components.push(comp);
197
+ }
198
+ if (netByName.has("GND")) {
199
+ const hasGroundSym = components.some(
200
+ (c) => c.componentType === "ground" || c.componentType === "gnd_signal" || c.componentType === "gnd_chassis" || c.componentType === "gnd_digital"
201
+ );
202
+ if (!hasGroundSym) {
203
+ const gId = `_GND${autoGnd++}`;
204
+ components.push({
205
+ id: gId,
206
+ componentType: "ground",
207
+ direction: "down",
208
+ label: void 0,
209
+ value: void 0,
210
+ attrs: { auto: "true" }
211
+ });
212
+ pinMap[gId] = { start: "GND" };
213
+ ensureNet("GND").anchors.push(`${gId}.start`);
214
+ }
215
+ }
216
+ const nets = Array.from(netByName.values());
217
+ return {
218
+ type: "circuit",
219
+ title: title2,
220
+ components,
221
+ nets,
222
+ pinMap,
223
+ mode: "netlist"
224
+ };
225
+ }
226
+
227
+ // src/diagrams/circuit/parser.ts
228
+ var CircuitParseError = class extends Error {
229
+ constructor(message) {
230
+ super(message);
231
+ this.name = "CircuitParseError";
232
+ }
233
+ };
234
+ var COMPONENT_TYPES = /* @__PURE__ */ new Set([
235
+ "resistor",
236
+ "potentiometer",
237
+ "rheostat",
238
+ "thermistor_ntc",
239
+ "thermistor_ptc",
240
+ "ldr",
241
+ "varistor",
242
+ "fuse",
243
+ "fuse_slow",
244
+ "capacitor",
245
+ "electrolytic_cap",
246
+ "variable_cap",
247
+ "inductor",
248
+ "inductor_iron",
249
+ "inductor_ferrite",
250
+ "variable_inductor",
251
+ "ferrite_bead",
252
+ "crystal",
253
+ "transformer",
254
+ "diode",
255
+ "zener",
256
+ "schottky",
257
+ "led",
258
+ "photodiode",
259
+ "varactor",
260
+ "tvs_diode",
261
+ "bridge_rectifier",
262
+ "npn",
263
+ "pnp",
264
+ "darlington_npn",
265
+ "darlington_pnp",
266
+ "nmos",
267
+ "pmos",
268
+ "nmos_depletion",
269
+ "jfet_n",
270
+ "jfet_p",
271
+ "igbt",
272
+ "scr",
273
+ "triac",
274
+ "diac",
275
+ "phototransistor",
276
+ "optocoupler",
277
+ "opamp",
278
+ "comparator",
279
+ "schmitt_buffer",
280
+ "tri_state_buffer",
281
+ "instrumentation_amp",
282
+ "generic_ic",
283
+ "voltage_regulator",
284
+ "dc_dc_converter",
285
+ "555_timer",
286
+ "voltage_source",
287
+ "current_source",
288
+ "ac_source",
289
+ "battery",
290
+ "vcc",
291
+ "ground",
292
+ "gnd_signal",
293
+ "gnd_chassis",
294
+ "gnd_digital",
295
+ "switch_spst",
296
+ "switch_spdt",
297
+ "switch_dpdt",
298
+ "push_no",
299
+ "push_nc",
300
+ "relay_coil",
301
+ "relay_no",
302
+ "relay_nc",
303
+ "motor",
304
+ "speaker",
305
+ "microphone",
306
+ "buzzer",
307
+ "ammeter",
308
+ "voltmeter",
309
+ "wattmeter",
310
+ "oscilloscope",
311
+ "wire",
312
+ "dot",
313
+ "label",
314
+ "port",
315
+ "test_point",
316
+ "no_connect",
317
+ "antenna"
318
+ ]);
319
+ var ALIASES = {
320
+ vsource: "voltage_source",
321
+ isource: "current_source",
322
+ acsource: "ac_source",
323
+ ecap: "electrolytic_cap",
324
+ pot: "potentiometer",
325
+ xtal: "crystal",
326
+ xfmr: "transformer",
327
+ transistor: "npn",
328
+ bjt_npn: "npn",
329
+ bjt_pnp: "pnp",
330
+ mosfet_n: "nmos",
331
+ mosfet_p: "pmos",
332
+ gnd: "ground",
333
+ ic: "generic_ic",
334
+ reg: "voltage_regulator",
335
+ timer555: "555_timer",
336
+ therm: "thermistor_ntc",
337
+ ntc: "thermistor_ntc",
338
+ ptc: "thermistor_ptc",
339
+ ths: "thermistor_ntc"
340
+ };
341
+ var EXTRA_TYPES = /* @__PURE__ */ new Set(["lamp"]);
342
+ function normalizeType(raw) {
343
+ const lower = raw.toLowerCase();
344
+ if (ALIASES[lower]) return ALIASES[lower];
345
+ if (COMPONENT_TYPES.has(lower)) {
346
+ return lower;
347
+ }
348
+ if (EXTRA_TYPES.has(lower)) {
349
+ return lower;
350
+ }
351
+ return null;
352
+ }
353
+ var DIRECTIONS = /* @__PURE__ */ new Set(["right", "left", "up", "down"]);
354
+ function parseAttrs(rest) {
355
+ const out = { attrs: {} };
356
+ const tokens = [];
357
+ let i = 0;
358
+ while (i < rest.length) {
359
+ const ch = rest[i];
360
+ if (ch === " " || ch === " ") {
361
+ i++;
362
+ continue;
363
+ }
364
+ if (ch === '"') {
365
+ const end = rest.indexOf('"', i + 1);
366
+ const tok = rest.slice(i, end < 0 ? rest.length : end + 1);
367
+ tokens.push(tok);
368
+ i = end < 0 ? rest.length : end + 1;
369
+ continue;
370
+ }
371
+ let j = i;
372
+ while (j < rest.length && rest[j] !== " " && rest[j] !== " ") {
373
+ if (rest[j] === "=" && rest[j + 1] === '"') {
374
+ const end = rest.indexOf('"', j + 2);
375
+ j = end < 0 ? rest.length : end + 1;
376
+ break;
377
+ }
378
+ j++;
379
+ }
380
+ tokens.push(rest.slice(i, j));
381
+ i = j;
382
+ }
383
+ for (const tok of tokens) {
384
+ if (!tok) continue;
385
+ if (DIRECTIONS.has(tok.toLowerCase())) {
386
+ out.direction = tok.toLowerCase();
387
+ continue;
388
+ }
389
+ const eq = tok.indexOf("=");
390
+ if (eq > 0) {
391
+ const key = tok.slice(0, eq).trim();
392
+ let val = tok.slice(eq + 1).trim();
393
+ if (val.startsWith('"') && val.endsWith('"')) {
394
+ val = val.slice(1, -1);
395
+ }
396
+ if (key === "label") out.label = val;
397
+ else if (key === "value") out.value = val;
398
+ else if (key === "at") out.at = val;
399
+ else if (key === "length") out.length = val;
400
+ else out.attrs[key] = val;
401
+ continue;
402
+ }
403
+ out.attrs[tok] = "true";
404
+ }
405
+ return out;
406
+ }
407
+ function parseCircuit(text2) {
408
+ const rawLines = text2.split("\n");
409
+ const firstMeaningful = rawLines.map((l) => l.replace(/#.*$/, "").trim()).find((l) => l.length > 0) ?? "";
410
+ if (/^circuit\b.*\bnetlist\s*$/i.test(firstMeaningful)) {
411
+ const titleMatch = firstMeaningful.match(/"([^"]*)"/);
412
+ let headerIdx = -1;
413
+ for (let i = 0; i < rawLines.length; i++) {
414
+ const s = rawLines[i].replace(/#.*$/, "").trim();
415
+ if (s.length > 0) {
416
+ headerIdx = i;
417
+ break;
418
+ }
419
+ }
420
+ const body = rawLines.slice(headerIdx + 1).join("\n");
421
+ return parseNetlist(body, titleMatch?.[1]);
422
+ }
423
+ const lines = text2.split("\n").map((l) => l.replace(/\r$/, ""));
424
+ let title2;
425
+ const components = [];
426
+ const nets = [];
427
+ const netByName = /* @__PURE__ */ new Map();
428
+ let autoId = 0;
429
+ let pendingAt;
430
+ const mkId = (prefix) => `${prefix}_${autoId++}`;
431
+ for (const rawLine of lines) {
432
+ const stripped = rawLine.replace(/#.*$/, "").trim();
433
+ if (!stripped) continue;
434
+ if (/^circuit\b/i.test(stripped)) {
435
+ const t = stripped.match(/"([^"]*)"/);
436
+ if (t) title2 = t[1];
437
+ continue;
438
+ }
439
+ const atMatch = stripped.match(/^at:\s*(.+)$/i);
440
+ if (atMatch) {
441
+ pendingAt = atMatch[1].trim();
442
+ continue;
443
+ }
444
+ const netDecl = stripped.match(/^net\s+([a-zA-Z_][\w]*)\s*$/i);
445
+ if (netDecl) {
446
+ const name = netDecl[1];
447
+ if (!netByName.has(name)) {
448
+ const n = { id: name, anchors: [] };
449
+ netByName.set(name, n);
450
+ nets.push(n);
451
+ }
452
+ continue;
453
+ }
454
+ const netDotMatch = stripped.match(/^net\s+([a-zA-Z_][\w]*)\s*:\s*dot\s*$/i);
455
+ if (netDotMatch) {
456
+ const name = netDotMatch[1];
457
+ let n = netByName.get(name);
458
+ if (!n) {
459
+ n = { id: name, anchors: [] };
460
+ netByName.set(name, n);
461
+ nets.push(n);
462
+ }
463
+ const id = mkId("dot");
464
+ components.push({
465
+ id,
466
+ componentType: "dot",
467
+ direction: "right",
468
+ at: pendingAt,
469
+ attrs: { net: name }
470
+ });
471
+ n.anchors.push(`${id}.end`);
472
+ pendingAt = `${id}.end`;
473
+ continue;
474
+ }
475
+ const labelMatch = stripped.match(/^label\s+"([^"]*)"(?:\s+(right|left|up|down))?\s*$/i);
476
+ if (labelMatch) {
477
+ const id = mkId("lbl");
478
+ components.push({
479
+ id,
480
+ componentType: "label",
481
+ direction: labelMatch[2]?.toLowerCase() ?? "right",
482
+ at: pendingAt,
483
+ label: labelMatch[1]
484
+ });
485
+ continue;
486
+ }
487
+ const wireMatch = stripped.match(/^wire(?:\s+(right|left|up|down))?(?:\s+(\d+)(?:px)?)?\s*$/i);
488
+ if (wireMatch) {
489
+ const id = mkId("w");
490
+ components.push({
491
+ id,
492
+ componentType: "wire",
493
+ direction: wireMatch[1]?.toLowerCase() ?? "right",
494
+ at: pendingAt,
495
+ attrs: wireMatch[2] ? { length: wireMatch[2] } : {}
496
+ });
497
+ pendingAt = `${id}.end`;
498
+ continue;
499
+ }
500
+ const bareMatch = stripped.match(/^([a-zA-Z_][\w]*)(\s+.*)?$/);
501
+ const colonMatch = stripped.match(/^([a-zA-Z_][\w]*)\s*:\s*([a-zA-Z_][\w]*)(\s+.*)?$/);
502
+ if (colonMatch) {
503
+ const id = colonMatch[1];
504
+ const typeStr = colonMatch[2];
505
+ const norm = normalizeType(typeStr);
506
+ if (!norm) {
507
+ throw new CircuitParseError(`Unknown component type: ${typeStr}`);
508
+ }
509
+ const rest = colonMatch[3] ?? "";
510
+ const parsed = parseAttrs(rest);
511
+ const comp = {
512
+ id,
513
+ componentType: norm,
514
+ direction: parsed.direction ?? "right",
515
+ at: parsed.at ?? pendingAt,
516
+ label: parsed.label,
517
+ value: parsed.value,
518
+ attrs: parsed.attrs
519
+ };
520
+ if (parsed.length) {
521
+ comp.attrs = { ...comp.attrs, length: parsed.length };
522
+ }
523
+ components.push(comp);
524
+ pendingAt = `${id}.end`;
525
+ continue;
526
+ }
527
+ if (bareMatch) {
528
+ const typeStr = bareMatch[1];
529
+ const norm = normalizeType(typeStr);
530
+ if (!norm) {
531
+ continue;
532
+ }
533
+ const rest = bareMatch[2] ?? "";
534
+ const parsed = parseAttrs(rest);
535
+ const id = mkId(norm);
536
+ const comp = {
537
+ id,
538
+ componentType: norm,
539
+ direction: parsed.direction ?? "right",
540
+ at: parsed.at ?? pendingAt,
541
+ label: parsed.label,
542
+ value: parsed.value,
543
+ attrs: parsed.attrs
544
+ };
545
+ components.push(comp);
546
+ pendingAt = `${id}.end`;
547
+ continue;
548
+ }
549
+ }
550
+ return {
551
+ type: "circuit",
552
+ title: title2,
553
+ components,
554
+ nets,
555
+ mode: "positional"
556
+ };
557
+ }
558
+
559
+ // src/diagrams/circuit/symbols.ts
560
+ var BODY = 'class="schematex-circuit-body"';
561
+ var FILL = 'class="schematex-circuit-fill"';
562
+ var WIRE = 'class="schematex-circuit-wire"';
563
+ function lineWire(x1, y1, x2, y2) {
564
+ return `<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" ${WIRE}/>`;
565
+ }
566
+ var resistor = {
567
+ length: 40,
568
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
569
+ svg: () => `<path d="M 0,0 L 5,0 L 8,-8 L 12,8 L 16,-8 L 20,8 L 24,-8 L 28,8 L 32,-8 L 35,0 L 40,0" ${BODY}/>`
570
+ };
571
+ var capacitor = {
572
+ length: 20,
573
+ anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
574
+ svg: () => [
575
+ lineWire(0, 0, 8, 0),
576
+ `<line x1="8" y1="-10" x2="8" y2="10" ${BODY}/>`,
577
+ `<line x1="12" y1="-10" x2="12" y2="10" ${BODY}/>`,
578
+ lineWire(12, 0, 20, 0)
579
+ ].join("")
580
+ };
581
+ var electrolytic_cap = {
582
+ length: 20,
583
+ anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
584
+ svg: () => [
585
+ lineWire(0, 0, 8, 0),
586
+ `<line x1="8" y1="-10" x2="8" y2="10" ${BODY}/>`,
587
+ `<path d="M 12,-10 Q 16,0 12,10" fill="none" class="schematex-circuit-body"/>`,
588
+ lineWire(12, 0, 20, 0),
589
+ `<text x="5" y="-12" class="schematex-circuit-pol">\u2212</text>`,
590
+ `<text x="15" y="-12" class="schematex-circuit-pol">+</text>`
591
+ ].join("")
592
+ };
593
+ var inductor = {
594
+ length: 40,
595
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
596
+ svg: () => `<path d="M 0,0 L 5,0 A 5,5 0 0 1 15,0 A 5,5 0 0 1 25,0 A 5,5 0 0 1 35,0 L 40,0" fill="none" ${BODY}/>`
597
+ };
598
+ var fuse = {
599
+ length: 30,
600
+ anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
601
+ svg: () => [
602
+ lineWire(0, 0, 5, 0),
603
+ `<rect x="5" y="-5" width="20" height="10" rx="5" fill="none" ${BODY}/>`,
604
+ `<line x1="5" y1="0" x2="25" y2="0" ${BODY}/>`,
605
+ lineWire(25, 0, 30, 0)
606
+ ].join("")
607
+ };
608
+ var crystal = {
609
+ length: 40,
610
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
611
+ svg: () => [
612
+ lineWire(0, 0, 10, 0),
613
+ `<line x1="10" y1="-9" x2="10" y2="9" ${BODY}/>`,
614
+ `<rect x="14" y="-7" width="12" height="14" fill="none" ${BODY}/>`,
615
+ `<line x1="30" y1="-9" x2="30" y2="9" ${BODY}/>`,
616
+ lineWire(30, 0, 40, 0)
617
+ ].join("")
618
+ };
619
+ var transformer = {
620
+ length: 60,
621
+ anchors: {
622
+ start: { x: 0, y: 0 },
623
+ end: { x: 60, y: 0 },
624
+ p1: { x: 0, y: 0 },
625
+ p2: { x: 0, y: 0 },
626
+ s1: { x: 60, y: 0 },
627
+ s2: { x: 60, y: 0 }
628
+ },
629
+ svg: () => [
630
+ // Primary coils (left)
631
+ `<path d="M 5,-18 A 5,5 0 0 1 5,-8 A 5,5 0 0 1 5,2 A 5,5 0 0 1 5,12 A 5,5 0 0 1 5,22" fill="none" ${BODY}/>`,
632
+ lineWire(0, 0, 5, 0),
633
+ // Core lines
634
+ `<line x1="28" y1="-20" x2="28" y2="22" ${BODY}/>`,
635
+ `<line x1="32" y1="-20" x2="32" y2="22" ${BODY}/>`,
636
+ // Secondary coils (right)
637
+ `<path d="M 55,-18 A 5,5 0 0 0 55,-8 A 5,5 0 0 0 55,2 A 5,5 0 0 0 55,12 A 5,5 0 0 0 55,22" fill="none" ${BODY}/>`,
638
+ lineWire(55, 0, 60, 0)
639
+ ].join("")
640
+ };
641
+ var voltage_source = {
642
+ length: 40,
643
+ // plus/minus aliases: end = +, start = − (matches on-symbol label)
644
+ anchors: {
645
+ start: { x: 0, y: 0 },
646
+ end: { x: 40, y: 0 },
647
+ minus: { x: 0, y: 0 },
648
+ plus: { x: 40, y: 0 }
649
+ },
650
+ svg: () => [
651
+ lineWire(0, 0, 8, 0),
652
+ `<circle cx="20" cy="0" r="12" fill="white" ${BODY}/>`,
653
+ `<text x="16" y="-2" class="schematex-circuit-pol">+</text>`,
654
+ `<text x="23" y="8" class="schematex-circuit-pol">\u2212</text>`,
655
+ lineWire(32, 0, 40, 0)
656
+ ].join("")
657
+ };
658
+ var current_source = {
659
+ length: 40,
660
+ anchors: {
661
+ start: { x: 0, y: 0 },
662
+ end: { x: 40, y: 0 },
663
+ minus: { x: 0, y: 0 },
664
+ plus: { x: 40, y: 0 }
665
+ },
666
+ svg: () => [
667
+ lineWire(0, 0, 8, 0),
668
+ `<circle cx="20" cy="0" r="12" fill="white" ${BODY}/>`,
669
+ `<line x1="14" y1="0" x2="24" y2="0" ${BODY}/>`,
670
+ `<polygon points="26,0 20,-4 20,4" ${FILL}/>`,
671
+ lineWire(32, 0, 40, 0)
672
+ ].join("")
673
+ };
674
+ var ac_source = {
675
+ length: 40,
676
+ anchors: {
677
+ start: { x: 0, y: 0 },
678
+ end: { x: 40, y: 0 },
679
+ minus: { x: 0, y: 0 },
680
+ plus: { x: 40, y: 0 }
681
+ },
682
+ svg: () => [
683
+ lineWire(0, 0, 8, 0),
684
+ `<circle cx="20" cy="0" r="12" fill="white" ${BODY}/>`,
685
+ `<path d="M 14,0 Q 17,-6 20,0 Q 23,6 26,0" fill="none" ${BODY}/>`,
686
+ lineWire(32, 0, 40, 0)
687
+ ].join("")
688
+ };
689
+ var battery = {
690
+ length: 24,
691
+ anchors: {
692
+ start: { x: 0, y: 0 },
693
+ end: { x: 24, y: 0 },
694
+ minus: { x: 0, y: 0 },
695
+ plus: { x: 24, y: 0 }
696
+ },
697
+ svg: () => [
698
+ lineWire(0, 0, 8, 0),
699
+ `<line x1="8" y1="-8" x2="8" y2="8" ${BODY}/>`,
700
+ `<line x1="12" y1="-4" x2="12" y2="4" ${BODY}/>`,
701
+ `<line x1="14" y1="-8" x2="14" y2="8" ${BODY}/>`,
702
+ `<line x1="18" y1="-4" x2="18" y2="4" ${BODY}/>`,
703
+ lineWire(18, 0, 24, 0)
704
+ ].join("")
705
+ };
706
+ var ground = {
707
+ length: 20,
708
+ anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
709
+ // Drawn as a "terminal" — vertical connection at start, earth lines below
710
+ svg: () => [
711
+ `<line x1="0" y1="0" x2="10" y2="0" ${WIRE}/>`,
712
+ `<line x1="10" y1="-8" x2="10" y2="8" ${BODY}/>`,
713
+ `<line x1="6" y1="4" x2="14" y2="4" ${BODY}/>`,
714
+ `<line x1="8" y1="8" x2="12" y2="8" ${BODY}/>`
715
+ ].join("")
716
+ };
717
+ var gnd_signal = {
718
+ length: 20,
719
+ anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
720
+ svg: () => [
721
+ `<line x1="0" y1="0" x2="8" y2="0" ${WIRE}/>`,
722
+ `<polygon points="8,-6 8,6 16,0" ${FILL}/>`
723
+ ].join("")
724
+ };
725
+ var vcc = {
726
+ length: 20,
727
+ anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
728
+ svg: () => [
729
+ `<line x1="0" y1="0" x2="10" y2="0" ${WIRE}/>`,
730
+ `<line x1="4" y1="-6" x2="16" y2="-6" ${BODY}/>`
731
+ ].join("")
732
+ };
733
+ var diode = {
734
+ length: 30,
735
+ anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
736
+ svg: () => [
737
+ lineWire(0, 0, 8, 0),
738
+ `<polygon points="8,-8 8,8 22,0" ${FILL}/>`,
739
+ `<line x1="22" y1="-8" x2="22" y2="8" ${BODY}/>`,
740
+ lineWire(22, 0, 30, 0)
741
+ ].join("")
742
+ };
743
+ var zener = {
744
+ length: 30,
745
+ anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
746
+ svg: () => [
747
+ lineWire(0, 0, 8, 0),
748
+ `<polygon points="8,-8 8,8 22,0" ${FILL}/>`,
749
+ `<path d="M 18,-10 L 22,-8 L 22,8 L 26,10" fill="none" ${BODY}/>`,
750
+ lineWire(22, 0, 30, 0)
751
+ ].join("")
752
+ };
753
+ var schottky = {
754
+ length: 30,
755
+ anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
756
+ svg: () => [
757
+ lineWire(0, 0, 8, 0),
758
+ `<polygon points="8,-8 8,8 22,0" ${FILL}/>`,
759
+ `<path d="M 18,-4 L 18,-8 L 22,-8 L 22,8 L 26,8 L 26,4" fill="none" ${BODY}/>`,
760
+ lineWire(22, 0, 30, 0)
761
+ ].join("")
762
+ };
763
+ var led = {
764
+ length: 30,
765
+ anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
766
+ svg: () => [
767
+ lineWire(0, 0, 8, 0),
768
+ `<polygon points="8,-8 8,8 22,0" ${FILL}/>`,
769
+ `<line x1="22" y1="-8" x2="22" y2="8" ${BODY}/>`,
770
+ lineWire(22, 0, 30, 0),
771
+ // outward light arrows
772
+ `<path d="M 12,-10 L 20,-18 M 18,-18 L 20,-18 L 20,-16" fill="none" ${BODY}/>`,
773
+ `<path d="M 16,-10 L 24,-18 M 22,-18 L 24,-18 L 24,-16" fill="none" ${BODY}/>`
774
+ ].join("")
775
+ };
776
+ var photodiode = {
777
+ length: 30,
778
+ anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
779
+ svg: () => [
780
+ lineWire(0, 0, 8, 0),
781
+ `<polygon points="8,-8 8,8 22,0" ${FILL}/>`,
782
+ `<line x1="22" y1="-8" x2="22" y2="8" ${BODY}/>`,
783
+ lineWire(22, 0, 30, 0),
784
+ // inward light arrows
785
+ `<path d="M 20,-18 L 12,-10 M 12,-12 L 12,-10 L 14,-10" fill="none" ${BODY}/>`,
786
+ `<path d="M 24,-18 L 16,-10 M 16,-12 L 16,-10 L 18,-10" fill="none" ${BODY}/>`
787
+ ].join("")
788
+ };
789
+ var npn = {
790
+ length: 40,
791
+ // base at left, collector up-right, emitter down-right
792
+ anchors: {
793
+ start: { x: 0, y: 0 },
794
+ end: { x: 40, y: -16 },
795
+ base: { x: 0, y: 0 },
796
+ collector: { x: 40, y: -16 },
797
+ emitter: { x: 40, y: 16 },
798
+ b: { x: 0, y: 0 },
799
+ c: { x: 40, y: -16 },
800
+ e: { x: 40, y: 16 }
801
+ },
802
+ svg: () => [
803
+ `<circle cx="20" cy="0" r="16" fill="white" ${BODY}/>`,
804
+ `<line x1="14" y1="-10" x2="14" y2="10" ${BODY}/>`,
805
+ lineWire(0, 0, 14, 0),
806
+ `<line x1="14" y1="-6" x2="30" y2="-12" ${BODY}/>`,
807
+ lineWire(30, -12, 40, -16),
808
+ `<line x1="14" y1="6" x2="30" y2="12" ${BODY}/>`,
809
+ lineWire(30, 12, 40, 16),
810
+ // NPN arrow (outward on emitter)
811
+ `<polygon points="30,12 24,10 26,16" ${FILL}/>`
812
+ ].join("")
813
+ };
814
+ var pnp = {
815
+ length: 40,
816
+ anchors: {
817
+ start: { x: 0, y: 0 },
818
+ end: { x: 40, y: -16 },
819
+ base: { x: 0, y: 0 },
820
+ collector: { x: 40, y: 16 },
821
+ emitter: { x: 40, y: -16 },
822
+ b: { x: 0, y: 0 },
823
+ c: { x: 40, y: 16 },
824
+ e: { x: 40, y: -16 }
825
+ },
826
+ svg: () => [
827
+ `<circle cx="20" cy="0" r="16" fill="white" ${BODY}/>`,
828
+ `<line x1="14" y1="-10" x2="14" y2="10" ${BODY}/>`,
829
+ lineWire(0, 0, 14, 0),
830
+ `<line x1="14" y1="-6" x2="30" y2="-12" ${BODY}/>`,
831
+ lineWire(30, -12, 40, -16),
832
+ `<line x1="14" y1="6" x2="30" y2="12" ${BODY}/>`,
833
+ lineWire(30, 12, 40, 16),
834
+ // PNP arrow (inward on emitter → toward base line)
835
+ `<polygon points="14,-6 20,-4 18,-10" ${FILL}/>`
836
+ ].join("")
837
+ };
838
+ var nmos = {
839
+ length: 40,
840
+ anchors: {
841
+ start: { x: 0, y: 0 },
842
+ end: { x: 40, y: -16 },
843
+ gate: { x: 0, y: 0 },
844
+ drain: { x: 40, y: -16 },
845
+ source: { x: 40, y: 16 },
846
+ g: { x: 0, y: 0 },
847
+ d: { x: 40, y: -16 },
848
+ s: { x: 40, y: 16 }
849
+ },
850
+ svg: () => [
851
+ lineWire(0, 0, 14, 0),
852
+ `<line x1="14" y1="-12" x2="14" y2="12" ${BODY}/>`,
853
+ `<line x1="18" y1="-10" x2="18" y2="-4" ${BODY}/>`,
854
+ `<line x1="18" y1="-2" x2="18" y2="2" ${BODY}/>`,
855
+ `<line x1="18" y1="4" x2="18" y2="10" ${BODY}/>`,
856
+ `<line x1="18" y1="-8" x2="32" y2="-8" ${BODY}/>`,
857
+ lineWire(32, -8, 40, -16),
858
+ `<line x1="18" y1="8" x2="32" y2="8" ${BODY}/>`,
859
+ lineWire(32, 8, 40, 16),
860
+ `<polygon points="22,0 18,-4 18,4" ${FILL}/>`
861
+ ].join("")
862
+ };
863
+ var pmos = {
864
+ length: 40,
865
+ anchors: {
866
+ start: { x: 0, y: 0 },
867
+ end: { x: 40, y: -16 },
868
+ gate: { x: 0, y: 0 },
869
+ source: { x: 40, y: -16 },
870
+ drain: { x: 40, y: 16 },
871
+ g: { x: 0, y: 0 },
872
+ s: { x: 40, y: -16 },
873
+ d: { x: 40, y: 16 }
874
+ },
875
+ svg: () => [
876
+ lineWire(0, 0, 14, 0),
877
+ `<line x1="14" y1="-12" x2="14" y2="12" ${BODY}/>`,
878
+ `<line x1="18" y1="-10" x2="18" y2="-4" ${BODY}/>`,
879
+ `<line x1="18" y1="-2" x2="18" y2="2" ${BODY}/>`,
880
+ `<line x1="18" y1="4" x2="18" y2="10" ${BODY}/>`,
881
+ `<line x1="18" y1="-8" x2="32" y2="-8" ${BODY}/>`,
882
+ lineWire(32, -8, 40, -16),
883
+ `<line x1="18" y1="8" x2="32" y2="8" ${BODY}/>`,
884
+ lineWire(32, 8, 40, 16),
885
+ `<polygon points="14,0 18,-4 18,4" ${FILL}/>`
886
+ ].join("")
887
+ };
888
+ var jfet_n = {
889
+ length: 40,
890
+ anchors: {
891
+ start: { x: 0, y: 0 },
892
+ end: { x: 40, y: -16 },
893
+ gate: { x: 0, y: 0 },
894
+ drain: { x: 40, y: -16 },
895
+ source: { x: 40, y: 16 }
896
+ },
897
+ svg: () => [
898
+ lineWire(0, 0, 14, 0),
899
+ `<line x1="14" y1="-12" x2="14" y2="12" ${BODY}/>`,
900
+ `<line x1="14" y1="-8" x2="32" y2="-8" ${BODY}/>`,
901
+ lineWire(32, -8, 40, -16),
902
+ `<line x1="14" y1="8" x2="32" y2="8" ${BODY}/>`,
903
+ lineWire(32, 8, 40, 16),
904
+ `<polygon points="14,0 10,-4 10,4" ${FILL}/>`
905
+ ].join("")
906
+ };
907
+ var jfet_p = {
908
+ length: 40,
909
+ anchors: {
910
+ start: { x: 0, y: 0 },
911
+ end: { x: 40, y: -16 },
912
+ gate: { x: 0, y: 0 },
913
+ drain: { x: 40, y: -16 },
914
+ source: { x: 40, y: 16 }
915
+ },
916
+ svg: () => [
917
+ lineWire(0, 0, 14, 0),
918
+ `<line x1="14" y1="-12" x2="14" y2="12" ${BODY}/>`,
919
+ `<line x1="14" y1="-8" x2="32" y2="-8" ${BODY}/>`,
920
+ lineWire(32, -8, 40, -16),
921
+ `<line x1="14" y1="8" x2="32" y2="8" ${BODY}/>`,
922
+ lineWire(32, 8, 40, 16),
923
+ `<polygon points="10,0 14,-4 14,4" ${FILL}/>`
924
+ ].join("")
925
+ };
926
+ var opamp = {
927
+ length: 50,
928
+ anchors: {
929
+ start: { x: 0, y: 0 },
930
+ end: { x: 50, y: 0 },
931
+ plus: { x: 0, y: -10 },
932
+ minus: { x: 0, y: 10 },
933
+ out: { x: 50, y: 0 },
934
+ "supply+": { x: 25, y: -20 },
935
+ "supply-": { x: 25, y: 20 }
936
+ },
937
+ svg: () => [
938
+ `<polygon points="0,-20 0,20 50,0" fill="white" ${BODY}/>`,
939
+ `<text x="5" y="-6" class="schematex-circuit-pol">+</text>`,
940
+ `<text x="5" y="14" class="schematex-circuit-pol">\u2212</text>`
941
+ ].join("")
942
+ };
943
+ var comparator = {
944
+ length: 50,
945
+ anchors: {
946
+ start: { x: 0, y: 0 },
947
+ end: { x: 50, y: 0 },
948
+ plus: { x: 0, y: -10 },
949
+ minus: { x: 0, y: 10 },
950
+ out: { x: 50, y: 0 }
951
+ },
952
+ svg: () => [
953
+ `<polygon points="0,-20 0,20 50,0" fill="white" ${BODY}/>`,
954
+ `<text x="5" y="-6" class="schematex-circuit-pol">+</text>`,
955
+ `<text x="5" y="14" class="schematex-circuit-pol">\u2212</text>`,
956
+ `<circle cx="48" cy="0" r="3" fill="white" ${BODY}/>`
957
+ ].join("")
958
+ };
959
+ var switch_spst = {
960
+ length: 40,
961
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
962
+ svg: () => [
963
+ lineWire(0, 0, 10, 0),
964
+ `<line x1="10" y1="0" x2="30" y2="-10" ${BODY}/>`,
965
+ `<circle cx="10" cy="0" r="2" ${FILL}/>`,
966
+ `<circle cx="30" cy="0" r="2" ${FILL}/>`,
967
+ lineWire(30, 0, 40, 0)
968
+ ].join("")
969
+ };
970
+ var push_no = {
971
+ length: 40,
972
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
973
+ svg: () => [
974
+ lineWire(0, 0, 12, 0),
975
+ lineWire(28, 0, 40, 0),
976
+ `<circle cx="12" cy="0" r="2" ${FILL}/>`,
977
+ `<circle cx="28" cy="0" r="2" ${FILL}/>`,
978
+ `<line x1="12" y1="-4" x2="28" y2="-4" ${BODY}/>`,
979
+ `<line x1="20" y1="-4" x2="20" y2="-12" ${BODY}/>`,
980
+ `<line x1="14" y1="-12" x2="26" y2="-12" ${BODY}/>`
981
+ ].join("")
982
+ };
983
+ var meterSvg = (letter) => () => [
984
+ lineWire(0, 0, 8, 0),
985
+ `<circle cx="20" cy="0" r="12" fill="white" ${BODY}/>`,
986
+ `<text x="20" y="4" text-anchor="middle" class="schematex-circuit-meter">${letter}</text>`,
987
+ lineWire(32, 0, 40, 0)
988
+ ].join("");
989
+ var ammeter = { length: 40, anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } }, svg: meterSvg("A") };
990
+ var voltmeter = { length: 40, anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } }, svg: meterSvg("V") };
991
+ var wattmeter = { length: 40, anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } }, svg: meterSvg("W") };
992
+ var motor = { length: 40, anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } }, svg: meterSvg("M") };
993
+ var lamp = {
994
+ length: 40,
995
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
996
+ svg: () => [
997
+ lineWire(0, 0, 8, 0),
998
+ `<circle cx="20" cy="0" r="12" fill="white" ${BODY}/>`,
999
+ `<line x1="12" y1="-8" x2="28" y2="8" ${BODY}/>`,
1000
+ `<line x1="12" y1="8" x2="28" y2="-8" ${BODY}/>`,
1001
+ lineWire(32, 0, 40, 0)
1002
+ ].join("")
1003
+ };
1004
+ var buzzer = {
1005
+ length: 40,
1006
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
1007
+ svg: () => [
1008
+ lineWire(0, 0, 8, 0),
1009
+ `<path d="M 8,0 A 12,12 0 0 1 32,0 L 8,0 Z" fill="white" ${BODY}/>`,
1010
+ lineWire(32, 0, 40, 0)
1011
+ ].join("")
1012
+ };
1013
+ var speaker = {
1014
+ length: 40,
1015
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
1016
+ svg: () => [
1017
+ lineWire(0, 0, 6, 0),
1018
+ `<rect x="6" y="-8" width="10" height="16" fill="white" ${BODY}/>`,
1019
+ `<path d="M 16,-8 L 28,-16 L 28,16 L 16,8 Z" fill="white" ${BODY}/>`,
1020
+ lineWire(0, 8, 6, 8)
1021
+ ].join("")
1022
+ };
1023
+ var microphone = {
1024
+ length: 40,
1025
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
1026
+ svg: () => [
1027
+ lineWire(0, 0, 8, 0),
1028
+ `<circle cx="20" cy="0" r="12" fill="white" ${BODY}/>`,
1029
+ `<line x1="20" y1="-10" x2="20" y2="10" ${BODY}/>`,
1030
+ lineWire(32, 0, 40, 0)
1031
+ ].join("")
1032
+ };
1033
+ var rheostat = {
1034
+ length: 50,
1035
+ anchors: { start: { x: 0, y: 0 }, end: { x: 50, y: 0 } },
1036
+ svg: () => [
1037
+ `<path d="M 0,0 L 10,0 L 13,-8 L 18,8 L 23,-8 L 28,8 L 33,-8 L 38,8 L 40,0 L 50,0" ${BODY}/>`,
1038
+ `<line x1="5" y1="12" x2="45" y2="-12" ${BODY}/>`,
1039
+ `<polygon points="45,-12 40,-9 44,-5" ${FILL}/>`
1040
+ ].join("")
1041
+ };
1042
+ var thermistor_ntc = {
1043
+ length: 50,
1044
+ anchors: { start: { x: 0, y: 0 }, end: { x: 50, y: 0 } },
1045
+ svg: () => [
1046
+ `<path d="M 0,0 L 10,0 L 13,-8 L 18,8 L 23,-8 L 28,8 L 33,-8 L 38,8 L 40,0 L 50,0" ${BODY}/>`,
1047
+ `<line x1="5" y1="10" x2="45" y2="-10" ${BODY}/>`,
1048
+ `<text x="40" y="-14" class="schematex-circuit-pol">-t\xB0</text>`
1049
+ ].join("")
1050
+ };
1051
+ var thermistor_ptc = {
1052
+ length: 50,
1053
+ anchors: { start: { x: 0, y: 0 }, end: { x: 50, y: 0 } },
1054
+ svg: () => [
1055
+ `<path d="M 0,0 L 10,0 L 13,-8 L 18,8 L 23,-8 L 28,8 L 33,-8 L 38,8 L 40,0 L 50,0" ${BODY}/>`,
1056
+ `<line x1="5" y1="10" x2="45" y2="-10" ${BODY}/>`,
1057
+ `<text x="40" y="-14" class="schematex-circuit-pol">+t\xB0</text>`
1058
+ ].join("")
1059
+ };
1060
+ var ldr = {
1061
+ length: 50,
1062
+ anchors: { start: { x: 0, y: 0 }, end: { x: 50, y: 0 } },
1063
+ svg: () => [
1064
+ `<path d="M 0,0 L 10,0 L 13,-8 L 18,8 L 23,-8 L 28,8 L 33,-8 L 38,8 L 40,0 L 50,0" ${BODY}/>`,
1065
+ `<circle cx="25" cy="-2" r="14" fill="none" ${BODY}/>`,
1066
+ `<path d="M 10,-24 L 18,-16 M 14,-16 L 18,-16 L 18,-20" fill="none" ${BODY}/>`,
1067
+ `<path d="M 20,-24 L 28,-16 M 24,-16 L 28,-16 L 28,-20" fill="none" ${BODY}/>`
1068
+ ].join("")
1069
+ };
1070
+ var variable_cap = {
1071
+ length: 24,
1072
+ anchors: { start: { x: 0, y: 0 }, end: { x: 24, y: 0 } },
1073
+ svg: () => [
1074
+ lineWire(0, 0, 10, 0),
1075
+ `<line x1="10" y1="-10" x2="10" y2="10" ${BODY}/>`,
1076
+ `<line x1="14" y1="-10" x2="14" y2="10" ${BODY}/>`,
1077
+ lineWire(14, 0, 24, 0),
1078
+ `<line x1="3" y1="10" x2="21" y2="-12" ${BODY}/>`,
1079
+ `<polygon points="21,-12 15,-10 19,-6" ${FILL}/>`
1080
+ ].join("")
1081
+ };
1082
+ var variable_inductor = {
1083
+ length: 40,
1084
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
1085
+ svg: () => [
1086
+ `<path d="M 0,0 L 5,0 A 5,5 0 0 1 15,0 A 5,5 0 0 1 25,0 A 5,5 0 0 1 35,0 L 40,0" fill="none" ${BODY}/>`,
1087
+ `<line x1="0" y1="10" x2="38" y2="-14" ${BODY}/>`,
1088
+ `<polygon points="38,-14 32,-12 36,-8" ${FILL}/>`
1089
+ ].join("")
1090
+ };
1091
+ var switch_spdt = {
1092
+ length: 50,
1093
+ anchors: {
1094
+ start: { x: 0, y: 0 },
1095
+ end: { x: 50, y: 0 },
1096
+ common: { x: 0, y: 0 },
1097
+ nc: { x: 50, y: -12 },
1098
+ no: { x: 50, y: 12 }
1099
+ },
1100
+ svg: () => [
1101
+ lineWire(0, 0, 10, 0),
1102
+ `<circle cx="10" cy="0" r="2" ${FILL}/>`,
1103
+ `<line x1="10" y1="0" x2="40" y2="-12" ${BODY}/>`,
1104
+ `<circle cx="42" cy="-12" r="2" ${FILL}/>`,
1105
+ lineWire(42, -12, 50, -12),
1106
+ `<circle cx="42" cy="12" r="2" ${FILL}/>`,
1107
+ lineWire(42, 12, 50, 12)
1108
+ ].join("")
1109
+ };
1110
+ var push_nc = {
1111
+ length: 40,
1112
+ anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
1113
+ svg: () => [
1114
+ lineWire(0, 0, 12, 0),
1115
+ lineWire(28, 0, 40, 0),
1116
+ `<circle cx="12" cy="0" r="2" ${FILL}/>`,
1117
+ `<circle cx="28" cy="0" r="2" ${FILL}/>`,
1118
+ `<line x1="10" y1="0" x2="30" y2="0" ${BODY}/>`,
1119
+ `<line x1="20" y1="0" x2="20" y2="-10" ${BODY}/>`,
1120
+ `<line x1="14" y1="-10" x2="26" y2="-10" ${BODY}/>`
1121
+ ].join("")
1122
+ };
1123
+ var gnd_chassis = {
1124
+ length: 20,
1125
+ anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
1126
+ svg: () => [
1127
+ `<line x1="0" y1="0" x2="10" y2="0" ${WIRE}/>`,
1128
+ `<line x1="10" y1="-6" x2="10" y2="6" ${BODY}/>`,
1129
+ `<line x1="10" y1="6" x2="14" y2="10" ${BODY}/>`,
1130
+ `<line x1="10" y1="2" x2="14" y2="6" ${BODY}/>`,
1131
+ `<line x1="10" y1="-2" x2="14" y2="2" ${BODY}/>`
1132
+ ].join("")
1133
+ };
1134
+ var gnd_digital = {
1135
+ length: 20,
1136
+ anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
1137
+ svg: () => [
1138
+ `<line x1="0" y1="0" x2="10" y2="0" ${WIRE}/>`,
1139
+ `<polygon points="8,-6 8,6 16,0" fill="none" ${BODY}/>`
1140
+ ].join("")
1141
+ };
1142
+ var test_point = {
1143
+ length: 16,
1144
+ anchors: { start: { x: 0, y: 0 }, end: { x: 16, y: 0 } },
1145
+ svg: () => [
1146
+ lineWire(0, 0, 6, 0),
1147
+ `<circle cx="10" cy="0" r="4" fill="white" ${BODY}/>`
1148
+ ].join("")
1149
+ };
1150
+ var no_connect = {
1151
+ length: 0,
1152
+ anchors: { start: { x: 0, y: 0 }, end: { x: 0, y: 0 } },
1153
+ svg: () => [
1154
+ `<line x1="-5" y1="-5" x2="5" y2="5" ${BODY}/>`,
1155
+ `<line x1="5" y1="-5" x2="-5" y2="5" ${BODY}/>`
1156
+ ].join("")
1157
+ };
1158
+ var antenna = {
1159
+ length: 30,
1160
+ anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
1161
+ svg: () => [
1162
+ lineWire(0, 0, 0, -10),
1163
+ `<line x1="0" y1="-10" x2="-10" y2="-24" ${BODY}/>`,
1164
+ `<line x1="0" y1="-10" x2="10" y2="-24" ${BODY}/>`
1165
+ ].join("")
1166
+ };
1167
+ function icSymbol(defaultLeft, defaultRight, bodyLabel) {
1168
+ const BODY_W = 80;
1169
+ return {
1170
+ length: BODY_W,
1171
+ anchors: {
1172
+ start: { x: 0, y: 0 },
1173
+ end: { x: BODY_W, y: 0 }
1174
+ },
1175
+ svg: (_label, _value, attrs) => {
1176
+ const left = attrs?.pins_left ? attrs.pins_left.split(",").map((s) => s.trim()) : defaultLeft;
1177
+ const right = attrs?.pins_right ? attrs.pins_right.split(",").map((s) => s.trim()) : defaultRight;
1178
+ const n = Math.max(left.length, right.length, 2);
1179
+ const pitch = 16;
1180
+ const bodyH = pitch * (n + 1);
1181
+ const topY = -bodyH / 2;
1182
+ const parts = [];
1183
+ parts.push(`<rect x="0" y="${topY}" width="${BODY_W}" height="${bodyH}" fill="white" ${BODY}/>`);
1184
+ const labelText = attrs?.ic_label ?? bodyLabel ?? "";
1185
+ if (labelText) {
1186
+ parts.push(`<text x="${BODY_W / 2}" y="3" text-anchor="middle" class="schematex-circuit-meter">${labelText}</text>`);
1187
+ }
1188
+ for (let i = 0; i < left.length; i++) {
1189
+ const y = topY + pitch * (i + 1);
1190
+ parts.push(`<line x1="-8" y1="${y}" x2="0" y2="${y}" ${WIRE}/>`);
1191
+ parts.push(`<text x="4" y="${y + 3}" class="schematex-circuit-pol">${left[i]}</text>`);
1192
+ }
1193
+ for (let i = 0; i < right.length; i++) {
1194
+ const y = topY + pitch * (i + 1);
1195
+ parts.push(`<line x1="${BODY_W}" y1="${y}" x2="${BODY_W + 8}" y2="${y}" ${WIRE}/>`);
1196
+ parts.push(`<text x="${BODY_W - 4}" y="${y + 3}" text-anchor="end" class="schematex-circuit-pol">${right[i]}</text>`);
1197
+ }
1198
+ return parts.join("");
1199
+ }
1200
+ };
1201
+ }
1202
+ var generic_ic = icSymbol(
1203
+ ["1", "2", "3", "4"],
1204
+ ["8", "7", "6", "5"],
1205
+ "IC"
1206
+ );
1207
+ var timer_555 = (() => {
1208
+ const left = ["GND", "TRG", "OUT", "RST"];
1209
+ const right = ["VCC", "DIS", "THR", "CTL"];
1210
+ const sym = icSymbol(left, right, "555");
1211
+ const BODY_W = 80;
1212
+ const pitch = 16;
1213
+ const n = 4;
1214
+ const topY = -80 / 2;
1215
+ const anchors = {
1216
+ start: { x: 0, y: 0 },
1217
+ end: { x: BODY_W, y: 0 }
1218
+ };
1219
+ const leftNames = ["gnd", "trg", "out", "rst"];
1220
+ const rightNames = ["vcc", "dis", "thr", "ctl"];
1221
+ for (let i = 0; i < n; i++) {
1222
+ const y = topY + pitch * (i + 1);
1223
+ anchors[leftNames[i]] = { x: -8, y };
1224
+ anchors[rightNames[i]] = { x: BODY_W + 8, y };
1225
+ }
1226
+ return { ...sym, anchors };
1227
+ })();
1228
+ var voltage_regulator = {
1229
+ length: 60,
1230
+ anchors: {
1231
+ start: { x: 0, y: 0 },
1232
+ end: { x: 60, y: 0 },
1233
+ in: { x: 0, y: 0 },
1234
+ out: { x: 60, y: 0 },
1235
+ gnd: { x: 30, y: 20 }
1236
+ },
1237
+ svg: (_l, _v, attrs) => [
1238
+ lineWire(0, 0, 10, 0),
1239
+ `<rect x="10" y="-15" width="40" height="30" fill="white" ${BODY}/>`,
1240
+ `<text x="30" y="4" text-anchor="middle" class="schematex-circuit-meter">${attrs?.model ?? "REG"}</text>`,
1241
+ lineWire(50, 0, 60, 0),
1242
+ lineWire(30, 15, 30, 20)
1243
+ ].join("")
1244
+ };
1245
+ var potentiometer = {
1246
+ length: 50,
1247
+ anchors: {
1248
+ start: { x: 0, y: 0 },
1249
+ end: { x: 50, y: 0 },
1250
+ wiper: { x: 25, y: -22 }
1251
+ },
1252
+ svg: () => [
1253
+ `<path d="M 0,0 L 10,0 L 13,-8 L 18,8 L 23,-8 L 28,8 L 33,-8 L 38,8 L 40,0 L 50,0" ${BODY}/>`,
1254
+ `<line x1="25" y1="-22" x2="25" y2="-10" ${BODY}/>`,
1255
+ `<polygon points="25,-10 21,-16 29,-16" ${FILL}/>`
1256
+ ].join("")
1257
+ };
1258
+ var SYMBOLS = {
1259
+ resistor,
1260
+ capacitor,
1261
+ electrolytic_cap,
1262
+ inductor,
1263
+ fuse,
1264
+ crystal,
1265
+ transformer,
1266
+ voltage_source,
1267
+ current_source,
1268
+ ac_source,
1269
+ battery,
1270
+ ground,
1271
+ gnd_signal,
1272
+ vcc,
1273
+ diode,
1274
+ zener,
1275
+ schottky,
1276
+ led,
1277
+ photodiode,
1278
+ npn,
1279
+ pnp,
1280
+ nmos,
1281
+ pmos,
1282
+ jfet_n,
1283
+ jfet_p,
1284
+ opamp,
1285
+ comparator,
1286
+ switch_spst,
1287
+ push_no,
1288
+ ammeter,
1289
+ voltmeter,
1290
+ wattmeter,
1291
+ motor,
1292
+ speaker,
1293
+ microphone,
1294
+ buzzer,
1295
+ potentiometer,
1296
+ rheostat,
1297
+ thermistor_ntc,
1298
+ thermistor_ptc,
1299
+ ldr,
1300
+ variable_cap,
1301
+ variable_inductor,
1302
+ switch_spdt,
1303
+ push_nc,
1304
+ gnd_chassis,
1305
+ gnd_digital,
1306
+ test_point,
1307
+ no_connect,
1308
+ antenna,
1309
+ generic_ic,
1310
+ "555_timer": timer_555,
1311
+ voltage_regulator
1312
+ // Lamp reuses buzzer slot? No, needs its own entry but our CircuitComponentType
1313
+ // doesn't have "lamp". We map it via parser alias to "buzzer" or add specifically.
1314
+ };
1315
+ var EXTRA_SYMBOLS = {
1316
+ lamp
1317
+ };
1318
+ function getSymbol(t) {
1319
+ return SYMBOLS[t] ?? EXTRA_SYMBOLS[t];
1320
+ }
1321
+
1322
+ // src/diagrams/circuit/layout.ts
1323
+ function rotationDeg(d) {
1324
+ return d === "right" ? 0 : d === "down" ? 90 : d === "left" ? 180 : 270;
1325
+ }
1326
+ function rotatePoint(p, angleDeg) {
1327
+ const r = angleDeg * Math.PI / 180;
1328
+ const c = Math.cos(r);
1329
+ const s = Math.sin(r);
1330
+ return { x: p.x * c - p.y * s, y: p.x * s + p.y * c };
1331
+ }
1332
+ function resolveAnchorRef(ref, byId, nets) {
1333
+ if (ref === "origin") return { x: 0, y: 0 };
1334
+ if (nets.has(ref)) return nets.get(ref);
1335
+ const dot = ref.indexOf(".");
1336
+ if (dot < 0) {
1337
+ const c2 = byId.get(ref);
1338
+ if (c2) return c2.anchors.end ?? c2.anchors.center ?? { x: c2.x, y: c2.y };
1339
+ return void 0;
1340
+ }
1341
+ const id = ref.slice(0, dot);
1342
+ const pin = ref.slice(dot + 1);
1343
+ const c = byId.get(id);
1344
+ if (!c) return void 0;
1345
+ return c.anchors[pin];
1346
+ }
1347
+ function layoutCircuit(ast) {
1348
+ const items = [];
1349
+ const byId = /* @__PURE__ */ new Map();
1350
+ const nets = /* @__PURE__ */ new Map();
1351
+ let cursor = { x: 0, y: 0 };
1352
+ for (const comp of ast.components) {
1353
+ let startPt = cursor;
1354
+ if (comp.at) {
1355
+ const resolved = resolveAnchorRef(comp.at, byId, nets);
1356
+ if (resolved) startPt = resolved;
1357
+ }
1358
+ const sym = getSymbol(comp.componentType);
1359
+ const rot = rotationDeg(comp.direction);
1360
+ if (comp.componentType === "wire") {
1361
+ const len = parseInt(comp.attrs?.length ?? "20", 10);
1362
+ const endOffset = rotatePoint({ x: len, y: 0 }, rot);
1363
+ const end = { x: startPt.x + endOffset.x, y: startPt.y + endOffset.y };
1364
+ const laid2 = {
1365
+ component: comp,
1366
+ x: startPt.x,
1367
+ y: startPt.y,
1368
+ rotation: rot,
1369
+ length: len,
1370
+ anchors: { start: startPt, end }
1371
+ };
1372
+ items.push(laid2);
1373
+ byId.set(comp.id, laid2);
1374
+ cursor = end;
1375
+ continue;
1376
+ }
1377
+ if (comp.componentType === "dot") {
1378
+ const laid2 = {
1379
+ component: comp,
1380
+ x: startPt.x,
1381
+ y: startPt.y,
1382
+ rotation: 0,
1383
+ length: 0,
1384
+ anchors: { start: startPt, end: startPt, center: startPt }
1385
+ };
1386
+ items.push(laid2);
1387
+ byId.set(comp.id, laid2);
1388
+ if (comp.attrs?.net) nets.set(comp.attrs.net, startPt);
1389
+ cursor = startPt;
1390
+ continue;
1391
+ }
1392
+ if (comp.componentType === "label") {
1393
+ const laid2 = {
1394
+ component: comp,
1395
+ x: startPt.x,
1396
+ y: startPt.y,
1397
+ rotation: rot,
1398
+ length: 0,
1399
+ anchors: { start: startPt, end: startPt }
1400
+ };
1401
+ items.push(laid2);
1402
+ byId.set(comp.id, laid2);
1403
+ continue;
1404
+ }
1405
+ if (!sym) {
1406
+ const endOffset = rotatePoint({ x: 30, y: 0 }, rot);
1407
+ const end = { x: startPt.x + endOffset.x, y: startPt.y + endOffset.y };
1408
+ const laid2 = {
1409
+ component: comp,
1410
+ x: startPt.x,
1411
+ y: startPt.y,
1412
+ rotation: rot,
1413
+ length: 30,
1414
+ anchors: { start: startPt, end }
1415
+ };
1416
+ items.push(laid2);
1417
+ byId.set(comp.id, laid2);
1418
+ cursor = end;
1419
+ continue;
1420
+ }
1421
+ const worldAnchors = {};
1422
+ for (const [name, pt] of Object.entries(sym.anchors)) {
1423
+ const rp = rotatePoint(pt, rot);
1424
+ worldAnchors[name] = { x: startPt.x + rp.x, y: startPt.y + rp.y };
1425
+ }
1426
+ const laid = {
1427
+ component: comp,
1428
+ x: startPt.x,
1429
+ y: startPt.y,
1430
+ rotation: rot,
1431
+ length: sym.length,
1432
+ anchors: worldAnchors
1433
+ };
1434
+ items.push(laid);
1435
+ byId.set(comp.id, laid);
1436
+ cursor = worldAnchors.end ?? startPt;
1437
+ }
1438
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
1439
+ for (const it of items) {
1440
+ for (const a of Object.values(it.anchors)) {
1441
+ if (a.x < minX) minX = a.x;
1442
+ if (a.y < minY) minY = a.y;
1443
+ if (a.x > maxX) maxX = a.x;
1444
+ if (a.y > maxY) maxY = a.y;
1445
+ }
1446
+ }
1447
+ if (!isFinite(minX)) {
1448
+ minX = 0;
1449
+ minY = 0;
1450
+ maxX = 100;
1451
+ maxY = 100;
1452
+ }
1453
+ const pad = 40;
1454
+ minX -= pad;
1455
+ minY -= pad;
1456
+ maxX += pad;
1457
+ maxY += pad;
1458
+ const width = maxX - minX;
1459
+ const height = maxY - minY;
1460
+ return {
1461
+ width,
1462
+ height,
1463
+ offsetX: -minX,
1464
+ offsetY: -minY,
1465
+ items
1466
+ };
1467
+ }
1468
+
1469
+ // src/diagrams/circuit/autolayout.ts
1470
+ var COL_W = 120;
1471
+ var ROW_H = 100;
1472
+ var RAIL_PAD = 60;
1473
+ var LEFT_MARGIN = 80;
1474
+ var TOP_MARGIN = 60;
1475
+ function isPowerSource(c) {
1476
+ return c.componentType === "voltage_source" || c.componentType === "current_source" || c.componentType === "ac_source" || c.componentType === "battery" || c.componentType === "vcc";
1477
+ }
1478
+ function isGround(c) {
1479
+ return c.componentType === "ground" || c.componentType === "gnd_signal" || c.componentType === "gnd_chassis" || c.componentType === "gnd_digital";
1480
+ }
1481
+ function rotatePt(p, angleDeg) {
1482
+ const r = angleDeg * Math.PI / 180;
1483
+ const c = Math.cos(r);
1484
+ const s = Math.sin(r);
1485
+ return { x: p.x * c - p.y * s, y: p.x * s + p.y * c };
1486
+ }
1487
+ function rotationOf(dir) {
1488
+ return dir === "right" ? 0 : dir === "down" ? 90 : dir === "left" ? 180 : 270;
1489
+ }
1490
+ function defaultDirection(c) {
1491
+ if (isPowerSource(c)) return "up";
1492
+ if (isGround(c)) return "down";
1493
+ return "right";
1494
+ }
1495
+ function extendBBox(bbox, pt) {
1496
+ if (pt.x < bbox.minX) bbox.minX = pt.x;
1497
+ if (pt.y < bbox.minY) bbox.minY = pt.y;
1498
+ if (pt.x > bbox.maxX) bbox.maxX = pt.x;
1499
+ if (pt.y > bbox.maxY) bbox.maxY = pt.y;
1500
+ }
1501
+ function layoutCircuitNetlist(ast) {
1502
+ const pinMap = ast.pinMap ?? {};
1503
+ const powerComps = [];
1504
+ const groundComps = [];
1505
+ const middleComps = [];
1506
+ for (const c of ast.components) {
1507
+ if (isPowerSource(c)) powerComps.push(c);
1508
+ else if (isGround(c)) groundComps.push(c);
1509
+ else middleComps.push(c);
1510
+ }
1511
+ const ranks = [];
1512
+ const mainRank = [...powerComps, ...middleComps];
1513
+ if (mainRank.length) ranks.push(mainRank);
1514
+ if (groundComps.length) ranks.push(groundComps);
1515
+ if (ranks.length === 0) ranks.push(ast.components);
1516
+ const placed = /* @__PURE__ */ new Map();
1517
+ const items = [];
1518
+ let maxCols = 0;
1519
+ for (const rank of ranks) maxCols = Math.max(maxCols, rank.length);
1520
+ for (let r = 0; r < ranks.length; r++) {
1521
+ const rank = ranks[r];
1522
+ const rowY = TOP_MARGIN + r * (ROW_H + RAIL_PAD);
1523
+ const startX = LEFT_MARGIN + (maxCols - rank.length) * COL_W / 2;
1524
+ for (let i = 0; i < rank.length; i++) {
1525
+ const comp = rank[i];
1526
+ const direction = defaultDirection(comp);
1527
+ comp.direction = direction;
1528
+ const rot = rotationOf(direction);
1529
+ const sym = getSymbol(comp.componentType);
1530
+ const x = startX + i * COL_W;
1531
+ const y = rowY;
1532
+ const worldAnchors = {};
1533
+ if (sym) {
1534
+ for (const [name, pt] of Object.entries(sym.anchors)) {
1535
+ const rp = rotatePt(pt, rot);
1536
+ worldAnchors[name] = { x: x + rp.x, y: y + rp.y };
1537
+ }
1538
+ } else {
1539
+ worldAnchors.start = { x, y };
1540
+ worldAnchors.end = { x: x + 30, y };
1541
+ }
1542
+ const laid = {
1543
+ component: comp,
1544
+ x,
1545
+ y,
1546
+ rotation: rot,
1547
+ length: sym?.length ?? 30,
1548
+ anchors: worldAnchors
1549
+ };
1550
+ items.push(laid);
1551
+ placed.set(comp.id, laid);
1552
+ }
1553
+ }
1554
+ const netPins = /* @__PURE__ */ new Map();
1555
+ for (const comp of ast.components) {
1556
+ const pins = pinMap[comp.id];
1557
+ if (!pins) continue;
1558
+ const laid = placed.get(comp.id);
1559
+ if (!laid) continue;
1560
+ for (const [pinName, netId] of Object.entries(pins)) {
1561
+ const pt = laid.anchors[pinName];
1562
+ if (!pt) continue;
1563
+ if (!netPins.has(netId)) netPins.set(netId, []);
1564
+ netPins.get(netId).push({ compId: comp.id, pinName, pt });
1565
+ }
1566
+ }
1567
+ const routes = [];
1568
+ const bbox = {
1569
+ minX: Infinity,
1570
+ minY: Infinity,
1571
+ maxX: -Infinity,
1572
+ maxY: -Infinity
1573
+ };
1574
+ for (const it of items) {
1575
+ for (const a of Object.values(it.anchors)) extendBBox(bbox, a);
1576
+ }
1577
+ if (!isFinite(bbox.minX)) {
1578
+ bbox.minX = 0;
1579
+ bbox.minY = 0;
1580
+ bbox.maxX = 200;
1581
+ bbox.maxY = 200;
1582
+ }
1583
+ for (const [netId, pins] of netPins) {
1584
+ if (pins.length < 2) continue;
1585
+ if (netId === "GND") {
1586
+ const railY = bbox.maxY + 30;
1587
+ const minX2 = Math.min(...pins.map((p) => p.pt.x));
1588
+ const maxX2 = Math.max(...pins.map((p) => p.pt.x));
1589
+ if (pins.length > 1) {
1590
+ routes.push({
1591
+ netId,
1592
+ points: [
1593
+ { x: minX2, y: railY },
1594
+ { x: maxX2, y: railY }
1595
+ ]
1596
+ });
1597
+ }
1598
+ for (const p of pins) {
1599
+ routes.push({
1600
+ netId: `${netId}.${p.compId}`,
1601
+ points: [
1602
+ p.pt,
1603
+ { x: p.pt.x, y: railY }
1604
+ ]
1605
+ });
1606
+ }
1607
+ bbox.maxY = Math.max(bbox.maxY, railY);
1608
+ continue;
1609
+ }
1610
+ const touchesPowerSource = pins.some((p) => {
1611
+ const comp = ast.components.find((c) => c.id === p.compId);
1612
+ return !!comp && isPowerSource(comp);
1613
+ });
1614
+ if (touchesPowerSource && pins.length > 1) {
1615
+ const railY = bbox.minY - 30;
1616
+ const minX2 = Math.min(...pins.map((p) => p.pt.x));
1617
+ const maxX2 = Math.max(...pins.map((p) => p.pt.x));
1618
+ routes.push({
1619
+ netId,
1620
+ points: [
1621
+ { x: minX2, y: railY },
1622
+ { x: maxX2, y: railY }
1623
+ ]
1624
+ });
1625
+ for (const p of pins) {
1626
+ routes.push({
1627
+ netId: `${netId}.${p.compId}`,
1628
+ points: [p.pt, { x: p.pt.x, y: railY }]
1629
+ });
1630
+ }
1631
+ bbox.minY = Math.min(bbox.minY, railY);
1632
+ continue;
1633
+ }
1634
+ if (pins.length === 2) {
1635
+ const [a, b] = pins;
1636
+ const points = Math.abs(a.pt.y - b.pt.y) < 0.5 ? [a.pt, b.pt] : Math.abs(a.pt.x - b.pt.x) < 0.5 ? [a.pt, b.pt] : [a.pt, { x: a.pt.x, y: b.pt.y }, b.pt];
1637
+ routes.push({ netId, points });
1638
+ } else {
1639
+ const ys = pins.map((p) => p.pt.y).sort((x, y) => x - y);
1640
+ const spineY = ys[Math.floor(ys.length / 2)];
1641
+ const xs = pins.map((p) => p.pt.x).sort((x, y) => x - y);
1642
+ const spineLeft = xs[0];
1643
+ const spineRight = xs[xs.length - 1];
1644
+ routes.push({
1645
+ netId,
1646
+ points: [
1647
+ { x: spineLeft, y: spineY },
1648
+ { x: spineRight, y: spineY }
1649
+ ]
1650
+ });
1651
+ const junctions = [];
1652
+ for (const p of pins) {
1653
+ if (Math.abs(p.pt.y - spineY) < 0.5) {
1654
+ if (p.pt.x > spineLeft && p.pt.x < spineRight) {
1655
+ junctions.push(p.pt);
1656
+ }
1657
+ continue;
1658
+ }
1659
+ routes.push({
1660
+ netId: `${netId}.${p.compId}`,
1661
+ points: [p.pt, { x: p.pt.x, y: spineY }]
1662
+ });
1663
+ if (p.pt.x > spineLeft && p.pt.x < spineRight) {
1664
+ junctions.push({ x: p.pt.x, y: spineY });
1665
+ }
1666
+ }
1667
+ if (junctions.length > 0) {
1668
+ routes[routes.length - 1 - pins.filter(
1669
+ (p) => Math.abs(p.pt.y - spineY) >= 0.5
1670
+ ).length].junctions = junctions;
1671
+ }
1672
+ }
1673
+ }
1674
+ for (const r of routes) {
1675
+ for (const p of r.points) extendBBox(bbox, p);
1676
+ }
1677
+ const pad = 40;
1678
+ const minX = bbox.minX - pad;
1679
+ const minY = bbox.minY - pad;
1680
+ const maxX = bbox.maxX + pad;
1681
+ const maxY = bbox.maxY + pad;
1682
+ return {
1683
+ width: maxX - minX,
1684
+ height: maxY - minY,
1685
+ offsetX: -minX,
1686
+ offsetY: -minY,
1687
+ items,
1688
+ routes
1689
+ };
1690
+ }
1691
+
1692
+ // src/diagrams/circuit/renderer.ts
1693
+ function renderItem(it, offX, offY) {
1694
+ const comp = it.component;
1695
+ const tx = it.x + offX;
1696
+ const ty = it.y + offY;
1697
+ if (comp.componentType === "wire") {
1698
+ const x2 = it.anchors.end.x + offX;
1699
+ const y2 = it.anchors.end.y + offY;
1700
+ return `<line x1="${tx}" y1="${ty}" x2="${x2}" y2="${y2}" class="schematex-circuit-wire"/>`;
1701
+ }
1702
+ if (comp.componentType === "dot") {
1703
+ return circle({
1704
+ cx: tx,
1705
+ cy: ty,
1706
+ r: 3.5,
1707
+ class: "schematex-circuit-dot",
1708
+ "data-id": comp.id
1709
+ });
1710
+ }
1711
+ if (comp.componentType === "label") {
1712
+ const dir = comp.direction;
1713
+ const anchor = dir === "left" ? "end" : dir === "right" ? "start" : "middle";
1714
+ const dx = dir === "right" ? 6 : dir === "left" ? -6 : 0;
1715
+ const dy = dir === "down" ? 14 : dir === "up" ? -6 : 4;
1716
+ return text(
1717
+ {
1718
+ x: tx + dx,
1719
+ y: ty + dy,
1720
+ class: "schematex-circuit-net-label",
1721
+ "text-anchor": anchor
1722
+ },
1723
+ comp.label ?? ""
1724
+ );
1725
+ }
1726
+ const sym = getSymbol(comp.componentType);
1727
+ if (!sym) {
1728
+ return `<rect x="${tx - 10}" y="${ty - 10}" width="20" height="20" fill="none" class="schematex-circuit-err" stroke-dasharray="3,2"/><text x="${tx}" y="${ty + 3}" text-anchor="middle" font-size="9" class="schematex-circuit-err">?${escapeXml(comp.componentType)}</text>`;
1729
+ }
1730
+ const body = sym.svg(comp.label, comp.value, comp.attrs);
1731
+ const transform = `translate(${tx}, ${ty}) rotate(${it.rotation})`;
1732
+ const labels = [];
1733
+ if (comp.label || comp.value) {
1734
+ const labelX = it.x + offX + it.length * Math.cos(it.rotation * Math.PI / 180) / 2;
1735
+ const labelY = it.y + offY + it.length * Math.sin(it.rotation * Math.PI / 180) / 2;
1736
+ const perpDX = Math.sin(it.rotation * Math.PI / 180);
1737
+ const perpDY = -Math.cos(it.rotation * Math.PI / 180);
1738
+ const off = 16;
1739
+ if (comp.label) {
1740
+ labels.push(
1741
+ text(
1742
+ {
1743
+ x: labelX + perpDX * off,
1744
+ y: labelY + perpDY * off - 2,
1745
+ class: "schematex-circuit-label",
1746
+ "text-anchor": "middle"
1747
+ },
1748
+ comp.label
1749
+ )
1750
+ );
1751
+ }
1752
+ if (comp.value) {
1753
+ labels.push(
1754
+ text(
1755
+ {
1756
+ x: labelX + perpDX * off,
1757
+ y: labelY + perpDY * off + 10,
1758
+ class: "schematex-circuit-value",
1759
+ "text-anchor": "middle"
1760
+ },
1761
+ comp.value
1762
+ )
1763
+ );
1764
+ }
1765
+ }
1766
+ return `<g transform="${transform}" data-id="${escapeXml(comp.id)}" data-type="${escapeXml(comp.componentType)}">${body}</g>` + labels.join("");
1767
+ }
1768
+ function renderRoute(r, offX, offY) {
1769
+ if (r.points.length < 2) return "";
1770
+ const pts = r.points.map((p) => `${p.x + offX},${p.y + offY}`).join(" ");
1771
+ const line = `<polyline points="${pts}" class="schematex-circuit-wire" fill="none"/>`;
1772
+ const dots = (r.junctions ?? []).map(
1773
+ (j) => `<circle cx="${j.x + offX}" cy="${j.y + offY}" r="3.5" class="schematex-circuit-dot"/>`
1774
+ ).join("");
1775
+ return line + dots;
1776
+ }
1777
+ function renderCircuit(ast, config) {
1778
+ const isNetlist = ast.mode === "netlist";
1779
+ const layout = isNetlist ? layoutCircuitNetlist(ast) : layoutCircuit(ast);
1780
+ const { width, height, offsetX, offsetY } = layout;
1781
+ const t = resolveIndustrialTheme(config?.theme ?? "default");
1782
+ const routeSvg = (layout.routes ?? []).map((r) => renderRoute(r, offsetX, offsetY)).join("");
1783
+ const items = layout.items.map((it) => renderItem(it, offsetX, offsetY)).join("");
1784
+ const css = `
1785
+ .schematex-circuit { background: ${t.bg}; font-family: system-ui, -apple-system, sans-serif; }
1786
+ .schematex-circuit-body { stroke: ${t.stroke}; stroke-width: 1.75; fill: none; stroke-linejoin: round; stroke-linecap: round; }
1787
+ .schematex-circuit-fill { stroke: ${t.stroke}; stroke-width: 1.5; fill: ${t.stroke}; }
1788
+ .schematex-circuit-wire { stroke: ${t.stroke}; stroke-width: 1.75; fill: none; stroke-linecap: square; }
1789
+ .schematex-circuit-dot { fill: ${t.stroke}; stroke: none; }
1790
+ .schematex-circuit-label { font: 600 11px system-ui, sans-serif; fill: ${t.text}; }
1791
+ .schematex-circuit-value { font: italic 10px system-ui, sans-serif; fill: ${t.textMuted}; }
1792
+ .schematex-circuit-net-label { font: 600 11px system-ui, sans-serif; fill: ${t.accent}; }
1793
+ .schematex-circuit-pol { font: 9px sans-serif; fill: ${t.stroke}; }
1794
+ .schematex-circuit-meter { font: bold 12px sans-serif; fill: ${t.stroke}; }
1795
+ .schematex-circuit-title { font: bold 14px sans-serif; fill: ${t.text}; }
1796
+ .schematex-circuit-err { stroke: ${t.error}; fill: ${t.error}; }
1797
+ `.trim();
1798
+ const titleBar = ast.title ? text(
1799
+ {
1800
+ x: width / 2,
1801
+ y: 18,
1802
+ "text-anchor": "middle",
1803
+ class: "schematex-circuit-title"
1804
+ },
1805
+ ast.title
1806
+ ) : "";
1807
+ const topOff = ast.title ? 24 : 0;
1808
+ return svgRoot(
1809
+ {
1810
+ class: "schematex-circuit",
1811
+ viewBox: `0 0 ${Math.round(width)} ${Math.round(height + topOff)}`,
1812
+ width: Math.round(width),
1813
+ height: Math.round(height + topOff),
1814
+ role: "img",
1815
+ "data-diagram-type": "circuit"
1816
+ },
1817
+ [
1818
+ title(ast.title ?? "Circuit Schematic"),
1819
+ desc(
1820
+ `Circuit schematic with ${ast.components.length} components`
1821
+ ),
1822
+ defs([el("style", {}, css)]),
1823
+ titleBar,
1824
+ group({ transform: `translate(0, ${topOff})` }, [routeSvg + items])
1825
+ ]
1826
+ );
1827
+ }
1828
+
1829
+ // src/diagrams/circuit/index.ts
1830
+ var circuit = {
1831
+ type: "circuit",
1832
+ detect(text2) {
1833
+ const first = text2.trim().split("\n")[0]?.trim().toLowerCase() ?? "";
1834
+ return first.startsWith("circuit");
1835
+ },
1836
+ render(text2, config) {
1837
+ const ast = parseCircuit(text2);
1838
+ return renderCircuit(ast, config);
1839
+ }
1840
+ };
1841
+
1842
+ export { circuit, layoutCircuit, layoutCircuitNetlist, parseCircuit, parseNetlist, renderCircuit };
1843
+ //# sourceMappingURL=chunk-XXU36667.js.map
1844
+ //# sourceMappingURL=chunk-XXU36667.js.map