schematex 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -7
- package/dist/ai/ai-sdk.cjs +32 -26
- package/dist/ai/ai-sdk.cjs.map +1 -1
- package/dist/ai/ai-sdk.d.cts +4 -3
- package/dist/ai/ai-sdk.d.ts +4 -3
- package/dist/ai/ai-sdk.js +28 -22
- package/dist/ai/ai-sdk.js.map +1 -1
- package/dist/ai/index.cjs +37 -25
- package/dist/ai/index.d.cts +20 -153
- package/dist/ai/index.d.ts +20 -153
- package/dist/ai/index.js +17 -17
- package/dist/{api-C5UcmT7n.d.cts → api-XWHHAhQI.d.ts} +12 -2
- package/dist/{api-C5UcmT7n.d.ts → api-qVDutqXH.d.cts} +12 -2
- package/dist/browser.cjs +37 -19
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +12 -3
- package/dist/browser.d.ts +12 -3
- package/dist/browser.js +27 -19
- package/dist/browser.js.map +1 -1
- package/dist/{chunk-3YUUC6RN.cjs → chunk-25ZON47K.cjs} +4105 -267
- package/dist/chunk-25ZON47K.cjs.map +1 -0
- package/dist/{chunk-N7W5KZK7.cjs → chunk-2L4YXZAZ.cjs} +4 -4
- package/dist/{chunk-N7W5KZK7.cjs.map → chunk-2L4YXZAZ.cjs.map} +1 -1
- package/dist/{chunk-ZYRCPSBU.js → chunk-3IE7KZY4.js} +4 -4
- package/dist/{chunk-ZYRCPSBU.js.map → chunk-3IE7KZY4.js.map} +1 -1
- package/dist/{chunk-ZX74KJPM.js → chunk-3VB5AT4R.js} +3 -3
- package/dist/{chunk-ZX74KJPM.js.map → chunk-3VB5AT4R.js.map} +1 -1
- package/dist/{chunk-S2KJRHDZ.cjs → chunk-4UFR2LB6.cjs} +13 -13
- package/dist/{chunk-S2KJRHDZ.cjs.map → chunk-4UFR2LB6.cjs.map} +1 -1
- package/dist/{chunk-QTNPMIO2.cjs → chunk-6JI6FWLZ.cjs} +341 -35
- package/dist/chunk-6JI6FWLZ.cjs.map +1 -0
- package/dist/{chunk-GTDQAN2Z.js → chunk-7AFW2J6J.js} +4075 -247
- package/dist/chunk-7AFW2J6J.js.map +1 -0
- package/dist/{chunk-UFTYX73U.js → chunk-7F76AWOI.js} +339 -35
- package/dist/chunk-7F76AWOI.js.map +1 -0
- package/dist/{chunk-BW4KGTV7.cjs → chunk-C5C5EF3W.cjs} +4 -4
- package/dist/{chunk-BW4KGTV7.cjs.map → chunk-C5C5EF3W.cjs.map} +1 -1
- package/dist/{chunk-VJGMEGMR.js → chunk-DOK7LKLO.js} +125 -13
- package/dist/chunk-DOK7LKLO.js.map +1 -0
- package/dist/{chunk-3M6WB62Y.cjs → chunk-ECD5XHBM.cjs} +139 -7
- package/dist/chunk-ECD5XHBM.cjs.map +1 -0
- package/dist/{chunk-L3CTXXVZ.js → chunk-FBS3PACU.js} +3 -3
- package/dist/{chunk-L3CTXXVZ.js.map → chunk-FBS3PACU.js.map} +1 -1
- package/dist/{chunk-QUKVGHN4.cjs → chunk-FKJBXGWP.cjs} +4 -4
- package/dist/{chunk-QUKVGHN4.cjs.map → chunk-FKJBXGWP.cjs.map} +1 -1
- package/dist/{chunk-SZK376QB.js → chunk-H4MT5TJP.js} +3 -3
- package/dist/{chunk-SZK376QB.js.map → chunk-H4MT5TJP.js.map} +1 -1
- package/dist/{chunk-3M6T7KB4.js → chunk-HAZALB7U.js} +3 -3
- package/dist/{chunk-3M6T7KB4.js.map → chunk-HAZALB7U.js.map} +1 -1
- package/dist/{chunk-VFZOPRQP.cjs → chunk-HWVBHU3O.cjs} +5 -5
- package/dist/{chunk-VFZOPRQP.cjs.map → chunk-HWVBHU3O.cjs.map} +1 -1
- package/dist/{chunk-D7EHZFK4.cjs → chunk-L7POWM5B.cjs} +138 -2
- package/dist/chunk-L7POWM5B.cjs.map +1 -0
- package/dist/{chunk-6OSUNBZY.js → chunk-LGABFD3L.js} +135 -7
- package/dist/chunk-LGABFD3L.js.map +1 -0
- package/dist/{chunk-2VNMKOUO.js → chunk-LRI4RH2N.js} +135 -3
- package/dist/chunk-LRI4RH2N.js.map +1 -0
- package/dist/{chunk-VDSYMSUY.js → chunk-MVIEIKOI.js} +3 -3
- package/dist/{chunk-VDSYMSUY.js.map → chunk-MVIEIKOI.js.map} +1 -1
- package/dist/{chunk-ZL5RB4UV.js → chunk-N5B242WY.js} +3 -3
- package/dist/{chunk-ZL5RB4UV.js.map → chunk-N5B242WY.js.map} +1 -1
- package/dist/{chunk-IM4RCUHA.js → chunk-P63S7P6N.js} +1309 -69
- package/dist/chunk-P63S7P6N.js.map +1 -0
- package/dist/{chunk-YLEVMOK2.cjs → chunk-R66QG3XT.cjs} +5 -4
- package/dist/{chunk-YLEVMOK2.cjs.map → chunk-R66QG3XT.cjs.map} +1 -1
- package/dist/{chunk-I55HO32M.js → chunk-RJMCWT7Z.js} +3 -3
- package/dist/{chunk-I55HO32M.js.map → chunk-RJMCWT7Z.js.map} +1 -1
- package/dist/{chunk-TZTCIAYW.cjs → chunk-S3RMAXH5.cjs} +137 -25
- package/dist/chunk-S3RMAXH5.cjs.map +1 -0
- package/dist/{chunk-IBRW3UOA.js → chunk-TWLKXV2O.js} +3 -3
- package/dist/{chunk-IBRW3UOA.js.map → chunk-TWLKXV2O.js.map} +1 -1
- package/dist/{chunk-HUPDIRBX.js → chunk-UWA5MWCI.js} +949 -918
- package/dist/chunk-UWA5MWCI.js.map +1 -0
- package/dist/{chunk-RYVV5UVI.cjs → chunk-V4GILQR6.cjs} +4 -4
- package/dist/{chunk-RYVV5UVI.cjs.map → chunk-V4GILQR6.cjs.map} +1 -1
- package/dist/{chunk-XRCY75UV.cjs → chunk-V4RO5KYY.cjs} +951 -918
- package/dist/chunk-V4RO5KYY.cjs.map +1 -0
- package/dist/{chunk-VZ5LDNHK.cjs → chunk-VTSH4YPT.cjs} +12 -12
- package/dist/{chunk-VZ5LDNHK.cjs.map → chunk-VTSH4YPT.cjs.map} +1 -1
- package/dist/{chunk-UUBNQV2T.cjs → chunk-WQDIZH2Z.cjs} +12 -12
- package/dist/{chunk-UUBNQV2T.cjs.map → chunk-WQDIZH2Z.cjs.map} +1 -1
- package/dist/{chunk-EGSUMHCS.cjs → chunk-YB4XJY5L.cjs} +12 -12
- package/dist/{chunk-EGSUMHCS.cjs.map → chunk-YB4XJY5L.cjs.map} +1 -1
- package/dist/{chunk-JHDR56XO.js → chunk-YS6CGUNH.js} +3 -3
- package/dist/{chunk-JHDR56XO.js.map → chunk-YS6CGUNH.js.map} +1 -1
- package/dist/{chunk-NWPCY65Z.cjs → chunk-YVDUEUFV.cjs} +1311 -68
- package/dist/chunk-YVDUEUFV.cjs.map +1 -0
- package/dist/{types-BOAsqHoU.d.ts → diagnostics-DRxhodP6.d.cts} +74 -2
- package/dist/{types-BOAsqHoU.d.cts → diagnostics-DRxhodP6.d.ts} +74 -2
- package/dist/diagrams/blockdiagram/index.d.cts +1 -1
- package/dist/diagrams/blockdiagram/index.d.ts +1 -1
- package/dist/diagrams/circuit/index.cjs +8 -8
- package/dist/diagrams/circuit/index.d.cts +1 -1
- package/dist/diagrams/circuit/index.d.ts +1 -1
- package/dist/diagrams/circuit/index.js +2 -2
- package/dist/diagrams/ecomap/index.cjs +7 -7
- package/dist/diagrams/ecomap/index.d.cts +1 -1
- package/dist/diagrams/ecomap/index.d.ts +1 -1
- package/dist/diagrams/ecomap/index.js +2 -2
- package/dist/diagrams/entity/index.cjs +6 -6
- package/dist/diagrams/entity/index.d.cts +1 -1
- package/dist/diagrams/entity/index.d.ts +1 -1
- package/dist/diagrams/entity/index.js +2 -2
- package/dist/diagrams/fishbone/index.cjs +8 -8
- package/dist/diagrams/fishbone/index.d.cts +1 -1
- package/dist/diagrams/fishbone/index.d.ts +1 -1
- package/dist/diagrams/fishbone/index.js +2 -2
- package/dist/diagrams/flowchart/index.cjs +8 -8
- package/dist/diagrams/flowchart/index.d.cts +2 -2
- package/dist/diagrams/flowchart/index.d.ts +2 -2
- package/dist/diagrams/flowchart/index.js +2 -2
- package/dist/diagrams/genogram/index.cjs +9 -9
- package/dist/diagrams/genogram/index.d.cts +1 -1
- package/dist/diagrams/genogram/index.d.ts +1 -1
- package/dist/diagrams/genogram/index.js +2 -2
- package/dist/diagrams/ladder/index.cjs +6 -6
- package/dist/diagrams/ladder/index.d.cts +1 -1
- package/dist/diagrams/ladder/index.d.ts +1 -1
- package/dist/diagrams/ladder/index.js +2 -2
- package/dist/diagrams/logic/index.cjs +6 -6
- package/dist/diagrams/logic/index.d.cts +1 -1
- package/dist/diagrams/logic/index.d.ts +1 -1
- package/dist/diagrams/logic/index.js +2 -2
- package/dist/diagrams/orgchart/index.cjs +7 -7
- package/dist/diagrams/orgchart/index.d.cts +1 -1
- package/dist/diagrams/orgchart/index.d.ts +1 -1
- package/dist/diagrams/orgchart/index.js +2 -2
- package/dist/diagrams/pedigree/index.cjs +7 -7
- package/dist/diagrams/pedigree/index.d.cts +1 -1
- package/dist/diagrams/pedigree/index.d.ts +1 -1
- package/dist/diagrams/pedigree/index.js +2 -2
- package/dist/diagrams/phylo/index.cjs +7 -7
- package/dist/diagrams/phylo/index.d.cts +1 -1
- package/dist/diagrams/phylo/index.d.ts +1 -1
- package/dist/diagrams/phylo/index.js +2 -2
- package/dist/diagrams/sld/index.cjs +14 -6
- package/dist/diagrams/sld/index.d.cts +14 -2
- package/dist/diagrams/sld/index.d.ts +14 -2
- package/dist/diagrams/sld/index.js +2 -2
- package/dist/diagrams/sociogram/index.cjs +6 -6
- package/dist/diagrams/sociogram/index.d.cts +1 -1
- package/dist/diagrams/sociogram/index.d.ts +1 -1
- package/dist/diagrams/sociogram/index.js +2 -2
- package/dist/diagrams/timing/index.d.cts +1 -1
- package/dist/diagrams/timing/index.d.ts +1 -1
- package/dist/diagrams/venn/index.cjs +9 -9
- package/dist/diagrams/venn/index.d.cts +1 -1
- package/dist/diagrams/venn/index.d.ts +1 -1
- package/dist/diagrams/venn/index.js +2 -2
- package/dist/{index-CJai_TEZ.d.ts → index-BRIkOPnd.d.cts} +60 -2
- package/dist/{index-C9A0h-CB.d.cts → index-C7SN-FB3.d.ts} +60 -2
- package/dist/index.cjs +351 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -4
- package/dist/index.d.ts +38 -4
- package/dist/index.js +283 -16
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +21 -23
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/react.js +21 -23
- package/dist/react.js.map +1 -1
- package/dist/tools-BVeUNdsU.d.ts +161 -0
- package/dist/tools-DdhP1kWY.d.cts +161 -0
- package/package.json +2 -2
- package/dist/chunk-2VNMKOUO.js.map +0 -1
- package/dist/chunk-3M6WB62Y.cjs.map +0 -1
- package/dist/chunk-3YUUC6RN.cjs.map +0 -1
- package/dist/chunk-6OSUNBZY.js.map +0 -1
- package/dist/chunk-D7EHZFK4.cjs.map +0 -1
- package/dist/chunk-GTDQAN2Z.js.map +0 -1
- package/dist/chunk-HUPDIRBX.js.map +0 -1
- package/dist/chunk-IM4RCUHA.js.map +0 -1
- package/dist/chunk-NWPCY65Z.cjs.map +0 -1
- package/dist/chunk-QTNPMIO2.cjs.map +0 -1
- package/dist/chunk-TZTCIAYW.cjs.map +0 -1
- package/dist/chunk-UFTYX73U.js.map +0 -1
- package/dist/chunk-VJGMEGMR.js.map +0 -1
- package/dist/chunk-XRCY75UV.cjs.map +0 -1
|
@@ -1,647 +1,57 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkL7POWM5B_cjs = require('./chunk-L7POWM5B.cjs');
|
|
4
4
|
var chunkNAGUZFXX_cjs = require('./chunk-NAGUZFXX.cjs');
|
|
5
5
|
var chunk3WNW5Y7P_cjs = require('./chunk-3WNW5Y7P.cjs');
|
|
6
6
|
|
|
7
|
-
// src/diagrams/circuit/
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
// src/diagrams/circuit/symbols.ts
|
|
8
|
+
var BODY = 'class="schematex-circuit-body"';
|
|
9
|
+
var FILL = 'class="schematex-circuit-fill"';
|
|
10
|
+
var WIRE = 'class="schematex-circuit-wire"';
|
|
11
|
+
function lineWire(x1, y1, x2, y2) {
|
|
12
|
+
return `<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" ${WIRE}/>`;
|
|
13
|
+
}
|
|
14
|
+
var resistor = {
|
|
15
|
+
length: 40,
|
|
16
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
17
|
+
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}/>`
|
|
15
18
|
};
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
M: { type: "nmos", pins: ["d", "g", "s"] },
|
|
26
|
-
J: { type: "jfet_n", pins: ["d", "g", "s"] },
|
|
27
|
-
S: { type: "switch_spst", pins: ["start", "end"] },
|
|
28
|
-
F: { type: "fuse", pins: ["start", "end"] },
|
|
29
|
-
B: { type: "battery", pins: ["plus", "minus"] },
|
|
30
|
-
K: { type: "relay_coil", pins: ["start", "end"] },
|
|
31
|
-
U: { type: "generic_ic", pins: [] },
|
|
32
|
-
// pins declared via pins="..." attr
|
|
33
|
-
X: { type: "generic_ic", pins: [] },
|
|
34
|
-
W: { type: "wire", pins: ["start", "end"] },
|
|
35
|
-
// explicit wire (non-SPICE convention, common in EE textbooks)
|
|
36
|
-
T: { type: "terminal_block", pins: [] }
|
|
37
|
-
// pins via pins="..."
|
|
19
|
+
var capacitor = {
|
|
20
|
+
length: 20,
|
|
21
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
|
|
22
|
+
svg: () => [
|
|
23
|
+
lineWire(0, 0, 8, 0),
|
|
24
|
+
`<line x1="8" y1="-10" x2="8" y2="10" ${BODY}/>`,
|
|
25
|
+
`<line x1="12" y1="-10" x2="12" y2="10" ${BODY}/>`,
|
|
26
|
+
lineWire(12, 0, 20, 0)
|
|
27
|
+
].join("")
|
|
38
28
|
};
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
tb: "terminal_block",
|
|
51
|
-
junction_box: "terminal_block",
|
|
52
|
-
jbox: "terminal_block",
|
|
53
|
-
enclosure: "terminal_block"
|
|
29
|
+
var electrolytic_cap = {
|
|
30
|
+
length: 20,
|
|
31
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
|
|
32
|
+
svg: () => [
|
|
33
|
+
lineWire(0, 0, 8, 0),
|
|
34
|
+
`<line x1="8" y1="-10" x2="8" y2="10" ${BODY}/>`,
|
|
35
|
+
`<path d="M 12,-10 Q 16,0 12,10" fill="none" class="schematex-circuit-body"/>`,
|
|
36
|
+
lineWire(12, 0, 20, 0),
|
|
37
|
+
`<text x="5" y="-12" class="schematex-circuit-pol">\u2212</text>`,
|
|
38
|
+
`<text x="15" y="-12" class="schematex-circuit-pol">+</text>`
|
|
39
|
+
].join("")
|
|
54
40
|
};
|
|
55
|
-
var
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
function tokenize(line) {
|
|
60
|
-
const tokens = [];
|
|
61
|
-
let i = 0;
|
|
62
|
-
while (i < line.length) {
|
|
63
|
-
const ch = line[i];
|
|
64
|
-
if (ch === " " || ch === " ") {
|
|
65
|
-
i++;
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
if (ch === '"') {
|
|
69
|
-
const end = line.indexOf('"', i + 1);
|
|
70
|
-
tokens.push(line.slice(i, end < 0 ? line.length : end + 1));
|
|
71
|
-
i = end < 0 ? line.length : end + 1;
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
let j = i;
|
|
75
|
-
while (j < line.length && line[j] !== " " && line[j] !== " ") {
|
|
76
|
-
if (line[j] === "=" && line[j + 1] === '"') {
|
|
77
|
-
const end = line.indexOf('"', j + 2);
|
|
78
|
-
j = end < 0 ? line.length : end + 1;
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
j++;
|
|
82
|
-
}
|
|
83
|
-
tokens.push(line.slice(i, j));
|
|
84
|
-
i = j;
|
|
85
|
-
}
|
|
86
|
-
return tokens;
|
|
87
|
-
}
|
|
88
|
-
function isKeyEqVal(tok) {
|
|
89
|
-
const eq = tok.indexOf("=");
|
|
90
|
-
return eq > 0 && /^[a-zA-Z_][\w]*$/.test(tok.slice(0, eq));
|
|
91
|
-
}
|
|
92
|
-
function parseKV(tok) {
|
|
93
|
-
const eq = tok.indexOf("=");
|
|
94
|
-
const key = tok.slice(0, eq).trim();
|
|
95
|
-
let val = tok.slice(eq + 1).trim();
|
|
96
|
-
if (val.startsWith('"') && val.endsWith('"')) val = val.slice(1, -1);
|
|
97
|
-
return [key, val];
|
|
98
|
-
}
|
|
99
|
-
function parseNetlist(body, title2) {
|
|
100
|
-
const components = [];
|
|
101
|
-
const netByName = /* @__PURE__ */ new Map();
|
|
102
|
-
const pinMap = {};
|
|
103
|
-
let autoGnd = 0;
|
|
104
|
-
const ensureNet = (name) => {
|
|
105
|
-
let n = netByName.get(name);
|
|
106
|
-
if (!n) {
|
|
107
|
-
n = { id: name, anchors: [] };
|
|
108
|
-
netByName.set(name, n);
|
|
109
|
-
}
|
|
110
|
-
return n;
|
|
111
|
-
};
|
|
112
|
-
const lines = body.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
113
|
-
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
114
|
-
const raw = lines[lineIdx];
|
|
115
|
-
const stripped = raw.replace(/#.*$/, "").trim();
|
|
116
|
-
if (!stripped) continue;
|
|
117
|
-
const tokens = tokenize(stripped);
|
|
118
|
-
if (tokens.length < 2) {
|
|
119
|
-
throw new NetlistParseError(
|
|
120
|
-
`Netlist line must have at least ID + one net: "${stripped}"`,
|
|
121
|
-
lineIdx + 1
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
const id = tokens[0];
|
|
125
|
-
if (!/^[a-zA-Z_][\w]*$/.test(id)) {
|
|
126
|
-
throw new NetlistParseError(`Invalid component id: "${id}"`, lineIdx + 1);
|
|
127
|
-
}
|
|
128
|
-
let cursor = 1;
|
|
129
|
-
const netRefs = [];
|
|
130
|
-
while (cursor < tokens.length && !isKeyEqVal(tokens[cursor])) {
|
|
131
|
-
netRefs.push(tokens[cursor]);
|
|
132
|
-
cursor++;
|
|
133
|
-
}
|
|
134
|
-
const kv = {};
|
|
135
|
-
for (; cursor < tokens.length; cursor++) {
|
|
136
|
-
if (!isKeyEqVal(tokens[cursor])) {
|
|
137
|
-
throw new NetlistParseError(
|
|
138
|
-
`Expected key=value after nets, got "${tokens[cursor]}"`,
|
|
139
|
-
lineIdx + 1
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
const [k, v] = parseKV(tokens[cursor]);
|
|
143
|
-
kv[k] = v;
|
|
144
|
-
}
|
|
145
|
-
const prefix = id[0].toUpperCase();
|
|
146
|
-
const defaults = PREFIX_MAP[prefix];
|
|
147
|
-
let cType;
|
|
148
|
-
let pinOrder;
|
|
149
|
-
if (kv.type) {
|
|
150
|
-
const t = kv.type.toLowerCase();
|
|
151
|
-
cType = TYPE_ALIASES[t] ?? t;
|
|
152
|
-
pinOrder = defaults?.pins ?? ["p1", "p2"];
|
|
153
|
-
} else if (defaults) {
|
|
154
|
-
cType = defaults.type;
|
|
155
|
-
pinOrder = defaults.pins;
|
|
156
|
-
} else if (isGroundRef(id)) {
|
|
157
|
-
cType = "ground";
|
|
158
|
-
pinOrder = ["start"];
|
|
159
|
-
} else {
|
|
160
|
-
throw new NetlistParseError(
|
|
161
|
-
`Cannot infer type from id "${id}". Either rename to a SPICE-prefix id (R*, C*, L*, D*, V*, I*, Q*, M*, J*, S*, F*, B*, K*, U*, X*, W*, T*) or pass an explicit \`type=<name>\` attribute (e.g. \`${id} ... type=resistor\`). Schematex circuit covers electrical schematics only \u2014 hydraulic/pneumatic prefixes (EV*, BOMBA*, TANK*, etc.) are not supported.`,
|
|
162
|
-
lineIdx + 1
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
const expectedPins = pinOrder.length;
|
|
166
|
-
let valueFromTail;
|
|
167
|
-
if (netRefs.length > expectedPins && expectedPins > 0) {
|
|
168
|
-
const tail = netRefs.slice(expectedPins);
|
|
169
|
-
netRefs.length = expectedPins;
|
|
170
|
-
const first = tail[0].toLowerCase();
|
|
171
|
-
if (TYPE_ALIASES[first]) {
|
|
172
|
-
cType = TYPE_ALIASES[first];
|
|
173
|
-
} else if (first === "npn" || first === "pnp" || first === "nmos" || first === "pmos" || first === "jfet_n" || first === "jfet_p" || first === "zener" || first === "schottky" || first === "led" || first === "photodiode") {
|
|
174
|
-
cType = first;
|
|
175
|
-
if (first === "pnp") pinOrder = ["c", "b", "e"];
|
|
176
|
-
if (first === "pmos" || first === "jfet_p") pinOrder = ["d", "g", "s"];
|
|
177
|
-
} else {
|
|
178
|
-
valueFromTail = tail.join(" ");
|
|
179
|
-
}
|
|
180
|
-
if (tail.length > 1 && !valueFromTail) {
|
|
181
|
-
valueFromTail = tail.slice(1).join(" ");
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
if (cType === "ground" || cType === "gnd_signal" || cType === "gnd_chassis" || cType === "gnd_digital") {
|
|
185
|
-
pinOrder = ["start"];
|
|
186
|
-
}
|
|
187
|
-
if (cType === "terminal_block") {
|
|
188
|
-
const pinsAttr = kv.pins ?? kv.terminals;
|
|
189
|
-
const labels = pinsAttr ? pinsAttr.split(",").map((s) => s.trim()).filter(Boolean) : Array.from({ length: Math.max(netRefs.length, 1) }, (_, i) => `t${i + 1}`);
|
|
190
|
-
pinOrder = labels.map(
|
|
191
|
-
(label, idx) => label.toLowerCase().replace(/[^a-z0-9]+/g, "_") || `t${idx + 1}`
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
if (netRefs.length < pinOrder.length) {
|
|
195
|
-
throw new NetlistParseError(
|
|
196
|
-
`Component ${id} (${cType}) expects ${pinOrder.length} nets, got ${netRefs.length}`,
|
|
197
|
-
lineIdx + 1
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
const pins = {};
|
|
201
|
-
for (let p = 0; p < pinOrder.length; p++) {
|
|
202
|
-
let net = netRefs[p];
|
|
203
|
-
if (isGroundRef(net)) net = "GND";
|
|
204
|
-
pins[pinOrder[p]] = net;
|
|
205
|
-
ensureNet(net).anchors.push(`${id}.${pinOrder[p]}`);
|
|
206
|
-
}
|
|
207
|
-
pinMap[id] = pins;
|
|
208
|
-
const comp = {
|
|
209
|
-
id,
|
|
210
|
-
componentType: cType,
|
|
211
|
-
direction: "right",
|
|
212
|
-
label: kv.label ?? id,
|
|
213
|
-
value: kv.value ?? valueFromTail,
|
|
214
|
-
attrs: {}
|
|
215
|
-
};
|
|
216
|
-
for (const [k, v] of Object.entries(kv)) {
|
|
217
|
-
if (k === "label" || k === "value" || k === "type") continue;
|
|
218
|
-
comp.attrs[k] = v;
|
|
219
|
-
}
|
|
220
|
-
components.push(comp);
|
|
221
|
-
}
|
|
222
|
-
if (netByName.has("GND")) {
|
|
223
|
-
const hasGroundSym = components.some(
|
|
224
|
-
(c) => c.componentType === "ground" || c.componentType === "gnd_signal" || c.componentType === "gnd_chassis" || c.componentType === "gnd_digital"
|
|
225
|
-
);
|
|
226
|
-
if (!hasGroundSym) {
|
|
227
|
-
const gId = `_GND${autoGnd++}`;
|
|
228
|
-
components.push({
|
|
229
|
-
id: gId,
|
|
230
|
-
componentType: "ground",
|
|
231
|
-
direction: "down",
|
|
232
|
-
label: void 0,
|
|
233
|
-
value: void 0,
|
|
234
|
-
attrs: { auto: "true" }
|
|
235
|
-
});
|
|
236
|
-
pinMap[gId] = { start: "GND" };
|
|
237
|
-
ensureNet("GND").anchors.push(`${gId}.start`);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
const nets = Array.from(netByName.values());
|
|
241
|
-
return {
|
|
242
|
-
type: "circuit",
|
|
243
|
-
title: title2,
|
|
244
|
-
components,
|
|
245
|
-
nets,
|
|
246
|
-
pinMap,
|
|
247
|
-
mode: "netlist"
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// src/diagrams/circuit/parser.ts
|
|
252
|
-
var CircuitParseError = class extends Error {
|
|
253
|
-
constructor(message) {
|
|
254
|
-
super(message);
|
|
255
|
-
this.name = "CircuitParseError";
|
|
256
|
-
}
|
|
41
|
+
var inductor = {
|
|
42
|
+
length: 40,
|
|
43
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
44
|
+
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}/>`
|
|
257
45
|
};
|
|
258
|
-
var
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
"
|
|
267
|
-
"fuse_slow",
|
|
268
|
-
"capacitor",
|
|
269
|
-
"electrolytic_cap",
|
|
270
|
-
"variable_cap",
|
|
271
|
-
"inductor",
|
|
272
|
-
"inductor_iron",
|
|
273
|
-
"inductor_ferrite",
|
|
274
|
-
"variable_inductor",
|
|
275
|
-
"ferrite_bead",
|
|
276
|
-
"crystal",
|
|
277
|
-
"transformer",
|
|
278
|
-
"diode",
|
|
279
|
-
"zener",
|
|
280
|
-
"schottky",
|
|
281
|
-
"led",
|
|
282
|
-
"photodiode",
|
|
283
|
-
"varactor",
|
|
284
|
-
"tvs_diode",
|
|
285
|
-
"bridge_rectifier",
|
|
286
|
-
"npn",
|
|
287
|
-
"pnp",
|
|
288
|
-
"darlington_npn",
|
|
289
|
-
"darlington_pnp",
|
|
290
|
-
"nmos",
|
|
291
|
-
"pmos",
|
|
292
|
-
"nmos_depletion",
|
|
293
|
-
"jfet_n",
|
|
294
|
-
"jfet_p",
|
|
295
|
-
"igbt",
|
|
296
|
-
"scr",
|
|
297
|
-
"triac",
|
|
298
|
-
"diac",
|
|
299
|
-
"phototransistor",
|
|
300
|
-
"optocoupler",
|
|
301
|
-
"opamp",
|
|
302
|
-
"comparator",
|
|
303
|
-
"schmitt_buffer",
|
|
304
|
-
"tri_state_buffer",
|
|
305
|
-
"instrumentation_amp",
|
|
306
|
-
"generic_ic",
|
|
307
|
-
"voltage_regulator",
|
|
308
|
-
"dc_dc_converter",
|
|
309
|
-
"555_timer",
|
|
310
|
-
"voltage_source",
|
|
311
|
-
"current_source",
|
|
312
|
-
"ac_source",
|
|
313
|
-
"battery",
|
|
314
|
-
"vcc",
|
|
315
|
-
"ground",
|
|
316
|
-
"gnd_signal",
|
|
317
|
-
"gnd_chassis",
|
|
318
|
-
"gnd_digital",
|
|
319
|
-
"switch_spst",
|
|
320
|
-
"switch_spdt",
|
|
321
|
-
"switch_dpdt",
|
|
322
|
-
"push_no",
|
|
323
|
-
"push_nc",
|
|
324
|
-
"relay_coil",
|
|
325
|
-
"relay_no",
|
|
326
|
-
"relay_nc",
|
|
327
|
-
"contactor",
|
|
328
|
-
"solenoid_valve",
|
|
329
|
-
"thermal_overload",
|
|
330
|
-
"disconnect_switch",
|
|
331
|
-
"motor",
|
|
332
|
-
"speaker",
|
|
333
|
-
"microphone",
|
|
334
|
-
"buzzer",
|
|
335
|
-
"ammeter",
|
|
336
|
-
"voltmeter",
|
|
337
|
-
"wattmeter",
|
|
338
|
-
"oscilloscope",
|
|
339
|
-
"wire",
|
|
340
|
-
"dot",
|
|
341
|
-
"label",
|
|
342
|
-
"port",
|
|
343
|
-
"test_point",
|
|
344
|
-
"no_connect",
|
|
345
|
-
"antenna"
|
|
346
|
-
]);
|
|
347
|
-
var ALIASES = {
|
|
348
|
-
vsource: "voltage_source",
|
|
349
|
-
isource: "current_source",
|
|
350
|
-
acsource: "ac_source",
|
|
351
|
-
ecap: "electrolytic_cap",
|
|
352
|
-
pot: "potentiometer",
|
|
353
|
-
xtal: "crystal",
|
|
354
|
-
xfmr: "transformer",
|
|
355
|
-
transistor: "npn",
|
|
356
|
-
bjt_npn: "npn",
|
|
357
|
-
bjt_pnp: "pnp",
|
|
358
|
-
mosfet_n: "nmos",
|
|
359
|
-
mosfet_p: "pmos",
|
|
360
|
-
gnd: "ground",
|
|
361
|
-
ic: "generic_ic",
|
|
362
|
-
reg: "voltage_regulator",
|
|
363
|
-
timer555: "555_timer",
|
|
364
|
-
therm: "thermistor_ntc",
|
|
365
|
-
ntc: "thermistor_ntc",
|
|
366
|
-
ptc: "thermistor_ptc",
|
|
367
|
-
ths: "thermistor_ntc",
|
|
368
|
-
// Industrial control aliases (IEC letter codes)
|
|
369
|
-
coil: "relay_coil",
|
|
370
|
-
relay: "relay_coil",
|
|
371
|
-
km: "contactor",
|
|
372
|
-
solenoid: "solenoid_valve",
|
|
373
|
-
ev: "solenoid_valve",
|
|
374
|
-
overload: "thermal_overload",
|
|
375
|
-
thermal: "thermal_overload",
|
|
376
|
-
disconnect: "disconnect_switch",
|
|
377
|
-
isolator: "disconnect_switch"
|
|
378
|
-
};
|
|
379
|
-
var EXTRA_TYPES = /* @__PURE__ */ new Set(["lamp"]);
|
|
380
|
-
function normalizeType(raw) {
|
|
381
|
-
const lower = raw.toLowerCase();
|
|
382
|
-
if (ALIASES[lower]) return ALIASES[lower];
|
|
383
|
-
if (COMPONENT_TYPES.has(lower)) {
|
|
384
|
-
return lower;
|
|
385
|
-
}
|
|
386
|
-
if (EXTRA_TYPES.has(lower)) {
|
|
387
|
-
return lower;
|
|
388
|
-
}
|
|
389
|
-
return null;
|
|
390
|
-
}
|
|
391
|
-
var DIRECTIONS = /* @__PURE__ */ new Set(["right", "left", "up", "down"]);
|
|
392
|
-
function parseAttrs(rest) {
|
|
393
|
-
const out = { attrs: {} };
|
|
394
|
-
const tokens = [];
|
|
395
|
-
let i = 0;
|
|
396
|
-
while (i < rest.length) {
|
|
397
|
-
const ch = rest[i];
|
|
398
|
-
if (ch === " " || ch === " ") {
|
|
399
|
-
i++;
|
|
400
|
-
continue;
|
|
401
|
-
}
|
|
402
|
-
if (ch === '"') {
|
|
403
|
-
const end = rest.indexOf('"', i + 1);
|
|
404
|
-
const tok = rest.slice(i, end < 0 ? rest.length : end + 1);
|
|
405
|
-
tokens.push(tok);
|
|
406
|
-
i = end < 0 ? rest.length : end + 1;
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
409
|
-
let j = i;
|
|
410
|
-
while (j < rest.length && rest[j] !== " " && rest[j] !== " ") {
|
|
411
|
-
if (rest[j] === "=" && rest[j + 1] === '"') {
|
|
412
|
-
const end = rest.indexOf('"', j + 2);
|
|
413
|
-
j = end < 0 ? rest.length : end + 1;
|
|
414
|
-
break;
|
|
415
|
-
}
|
|
416
|
-
j++;
|
|
417
|
-
}
|
|
418
|
-
tokens.push(rest.slice(i, j));
|
|
419
|
-
i = j;
|
|
420
|
-
}
|
|
421
|
-
for (const tok of tokens) {
|
|
422
|
-
if (!tok) continue;
|
|
423
|
-
if (DIRECTIONS.has(tok.toLowerCase())) {
|
|
424
|
-
out.direction = tok.toLowerCase();
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
const eq = tok.indexOf("=");
|
|
428
|
-
if (eq > 0) {
|
|
429
|
-
const key = tok.slice(0, eq).trim();
|
|
430
|
-
let val = tok.slice(eq + 1).trim();
|
|
431
|
-
if (val.startsWith('"') && val.endsWith('"')) {
|
|
432
|
-
val = val.slice(1, -1);
|
|
433
|
-
}
|
|
434
|
-
if (key === "label") out.label = val;
|
|
435
|
-
else if (key === "value") out.value = val;
|
|
436
|
-
else if (key === "at") out.at = val;
|
|
437
|
-
else if (key === "length") out.length = val;
|
|
438
|
-
else out.attrs[key] = val;
|
|
439
|
-
continue;
|
|
440
|
-
}
|
|
441
|
-
out.attrs[tok] = "true";
|
|
442
|
-
}
|
|
443
|
-
return out;
|
|
444
|
-
}
|
|
445
|
-
function parseCircuit(text2) {
|
|
446
|
-
const rawLines = text2.split("\n");
|
|
447
|
-
const firstMeaningful = rawLines.map((l) => l.replace(/#.*$/, "").trim()).find((l) => l.length > 0) ?? "";
|
|
448
|
-
if (/^circuit\b.*\bnetlist\s*$/i.test(firstMeaningful)) {
|
|
449
|
-
const netlistTitle = chunkNAGUZFXX_cjs.matchQuotedTitle(firstMeaningful);
|
|
450
|
-
let headerIdx = -1;
|
|
451
|
-
for (let i = 0; i < rawLines.length; i++) {
|
|
452
|
-
const s = rawLines[i].replace(/#.*$/, "").trim();
|
|
453
|
-
if (s.length > 0) {
|
|
454
|
-
headerIdx = i;
|
|
455
|
-
break;
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
const body = rawLines.slice(headerIdx + 1).join("\n");
|
|
459
|
-
return parseNetlist(body, netlistTitle);
|
|
460
|
-
}
|
|
461
|
-
const lines = text2.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
462
|
-
let title2;
|
|
463
|
-
const components = [];
|
|
464
|
-
const nets = [];
|
|
465
|
-
const netByName = /* @__PURE__ */ new Map();
|
|
466
|
-
let autoId = 0;
|
|
467
|
-
let pendingAt;
|
|
468
|
-
const mkId = (prefix) => `${prefix}_${autoId++}`;
|
|
469
|
-
for (const rawLine of lines) {
|
|
470
|
-
const stripped = rawLine.replace(/#.*$/, "").trim();
|
|
471
|
-
if (!stripped) continue;
|
|
472
|
-
if (/^circuit\b/i.test(stripped)) {
|
|
473
|
-
const t = chunkNAGUZFXX_cjs.matchQuotedTitle(stripped);
|
|
474
|
-
if (t !== void 0) title2 = t;
|
|
475
|
-
continue;
|
|
476
|
-
}
|
|
477
|
-
const atMatch = stripped.match(/^at:\s*(.+)$/i);
|
|
478
|
-
if (atMatch) {
|
|
479
|
-
pendingAt = atMatch[1].trim();
|
|
480
|
-
continue;
|
|
481
|
-
}
|
|
482
|
-
const netDecl = stripped.match(/^net\s+([a-zA-Z_][\w]*)\s*$/i);
|
|
483
|
-
if (netDecl) {
|
|
484
|
-
const name = netDecl[1];
|
|
485
|
-
if (!netByName.has(name)) {
|
|
486
|
-
const n = { id: name, anchors: [] };
|
|
487
|
-
netByName.set(name, n);
|
|
488
|
-
nets.push(n);
|
|
489
|
-
}
|
|
490
|
-
continue;
|
|
491
|
-
}
|
|
492
|
-
const netDotMatch = stripped.match(/^net\s+([a-zA-Z_][\w]*)\s*:\s*dot\s*$/i);
|
|
493
|
-
if (netDotMatch) {
|
|
494
|
-
const name = netDotMatch[1];
|
|
495
|
-
let n = netByName.get(name);
|
|
496
|
-
if (!n) {
|
|
497
|
-
n = { id: name, anchors: [] };
|
|
498
|
-
netByName.set(name, n);
|
|
499
|
-
nets.push(n);
|
|
500
|
-
}
|
|
501
|
-
const id = mkId("dot");
|
|
502
|
-
components.push({
|
|
503
|
-
id,
|
|
504
|
-
componentType: "dot",
|
|
505
|
-
direction: "right",
|
|
506
|
-
at: pendingAt,
|
|
507
|
-
attrs: { net: name }
|
|
508
|
-
});
|
|
509
|
-
n.anchors.push(`${id}.end`);
|
|
510
|
-
pendingAt = `${id}.end`;
|
|
511
|
-
continue;
|
|
512
|
-
}
|
|
513
|
-
const labelMatch = stripped.match(/^label\s+"([^"]*)"(?:\s+(right|left|up|down))?\s*$/i);
|
|
514
|
-
if (labelMatch) {
|
|
515
|
-
const id = mkId("lbl");
|
|
516
|
-
components.push({
|
|
517
|
-
id,
|
|
518
|
-
componentType: "label",
|
|
519
|
-
direction: labelMatch[2]?.toLowerCase() ?? "right",
|
|
520
|
-
at: pendingAt,
|
|
521
|
-
label: labelMatch[1]
|
|
522
|
-
});
|
|
523
|
-
continue;
|
|
524
|
-
}
|
|
525
|
-
const wireMatch = stripped.match(/^wire(?:\s+(right|left|up|down))?(?:\s+(\d+)(?:px)?)?\s*$/i);
|
|
526
|
-
if (wireMatch) {
|
|
527
|
-
const id = mkId("w");
|
|
528
|
-
components.push({
|
|
529
|
-
id,
|
|
530
|
-
componentType: "wire",
|
|
531
|
-
direction: wireMatch[1]?.toLowerCase() ?? "right",
|
|
532
|
-
at: pendingAt,
|
|
533
|
-
attrs: wireMatch[2] ? { length: wireMatch[2] } : {}
|
|
534
|
-
});
|
|
535
|
-
pendingAt = `${id}.end`;
|
|
536
|
-
continue;
|
|
537
|
-
}
|
|
538
|
-
const bareMatch = stripped.match(/^([a-zA-Z_][\w]*)(\s+.*)?$/);
|
|
539
|
-
const colonMatch = stripped.match(/^([a-zA-Z_][\w]*)\s*:\s*([a-zA-Z_][\w]*)(\s+.*)?$/);
|
|
540
|
-
if (colonMatch) {
|
|
541
|
-
const id = colonMatch[1];
|
|
542
|
-
const typeStr = colonMatch[2];
|
|
543
|
-
const norm = normalizeType(typeStr);
|
|
544
|
-
if (!norm) {
|
|
545
|
-
throw new CircuitParseError(`Unknown component type: ${typeStr}`);
|
|
546
|
-
}
|
|
547
|
-
const rest = colonMatch[3] ?? "";
|
|
548
|
-
const parsed = parseAttrs(rest);
|
|
549
|
-
const comp = {
|
|
550
|
-
id,
|
|
551
|
-
componentType: norm,
|
|
552
|
-
direction: parsed.direction ?? "right",
|
|
553
|
-
at: parsed.at ?? pendingAt,
|
|
554
|
-
label: parsed.label,
|
|
555
|
-
value: parsed.value,
|
|
556
|
-
attrs: parsed.attrs
|
|
557
|
-
};
|
|
558
|
-
if (parsed.length) {
|
|
559
|
-
comp.attrs = { ...comp.attrs, length: parsed.length };
|
|
560
|
-
}
|
|
561
|
-
components.push(comp);
|
|
562
|
-
pendingAt = `${id}.end`;
|
|
563
|
-
continue;
|
|
564
|
-
}
|
|
565
|
-
if (bareMatch) {
|
|
566
|
-
const typeStr = bareMatch[1];
|
|
567
|
-
const norm = normalizeType(typeStr);
|
|
568
|
-
if (!norm) {
|
|
569
|
-
continue;
|
|
570
|
-
}
|
|
571
|
-
const rest = bareMatch[2] ?? "";
|
|
572
|
-
const parsed = parseAttrs(rest);
|
|
573
|
-
const id = mkId(norm);
|
|
574
|
-
const comp = {
|
|
575
|
-
id,
|
|
576
|
-
componentType: norm,
|
|
577
|
-
direction: parsed.direction ?? "right",
|
|
578
|
-
at: parsed.at ?? pendingAt,
|
|
579
|
-
label: parsed.label,
|
|
580
|
-
value: parsed.value,
|
|
581
|
-
attrs: parsed.attrs
|
|
582
|
-
};
|
|
583
|
-
components.push(comp);
|
|
584
|
-
pendingAt = `${id}.end`;
|
|
585
|
-
continue;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return {
|
|
589
|
-
type: "circuit",
|
|
590
|
-
title: title2,
|
|
591
|
-
components,
|
|
592
|
-
nets,
|
|
593
|
-
mode: "positional"
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// src/diagrams/circuit/symbols.ts
|
|
598
|
-
var BODY = 'class="schematex-circuit-body"';
|
|
599
|
-
var FILL = 'class="schematex-circuit-fill"';
|
|
600
|
-
var WIRE = 'class="schematex-circuit-wire"';
|
|
601
|
-
function lineWire(x1, y1, x2, y2) {
|
|
602
|
-
return `<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" ${WIRE}/>`;
|
|
603
|
-
}
|
|
604
|
-
var resistor = {
|
|
605
|
-
length: 40,
|
|
606
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
607
|
-
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}/>`
|
|
608
|
-
};
|
|
609
|
-
var capacitor = {
|
|
610
|
-
length: 20,
|
|
611
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
|
|
612
|
-
svg: () => [
|
|
613
|
-
lineWire(0, 0, 8, 0),
|
|
614
|
-
`<line x1="8" y1="-10" x2="8" y2="10" ${BODY}/>`,
|
|
615
|
-
`<line x1="12" y1="-10" x2="12" y2="10" ${BODY}/>`,
|
|
616
|
-
lineWire(12, 0, 20, 0)
|
|
617
|
-
].join("")
|
|
618
|
-
};
|
|
619
|
-
var electrolytic_cap = {
|
|
620
|
-
length: 20,
|
|
621
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 20, y: 0 } },
|
|
622
|
-
svg: () => [
|
|
623
|
-
lineWire(0, 0, 8, 0),
|
|
624
|
-
`<line x1="8" y1="-10" x2="8" y2="10" ${BODY}/>`,
|
|
625
|
-
`<path d="M 12,-10 Q 16,0 12,10" fill="none" class="schematex-circuit-body"/>`,
|
|
626
|
-
lineWire(12, 0, 20, 0),
|
|
627
|
-
`<text x="5" y="-12" class="schematex-circuit-pol">\u2212</text>`,
|
|
628
|
-
`<text x="15" y="-12" class="schematex-circuit-pol">+</text>`
|
|
629
|
-
].join("")
|
|
630
|
-
};
|
|
631
|
-
var inductor = {
|
|
632
|
-
length: 40,
|
|
633
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
634
|
-
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}/>`
|
|
635
|
-
};
|
|
636
|
-
var fuse = {
|
|
637
|
-
length: 30,
|
|
638
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
|
|
639
|
-
svg: () => [
|
|
640
|
-
lineWire(0, 0, 5, 0),
|
|
641
|
-
`<rect x="5" y="-5" width="20" height="10" rx="5" fill="none" ${BODY}/>`,
|
|
642
|
-
`<line x1="5" y1="0" x2="25" y2="0" ${BODY}/>`,
|
|
643
|
-
lineWire(25, 0, 30, 0)
|
|
644
|
-
].join("")
|
|
46
|
+
var fuse = {
|
|
47
|
+
length: 30,
|
|
48
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 30, y: 0 } },
|
|
49
|
+
svg: () => [
|
|
50
|
+
lineWire(0, 0, 5, 0),
|
|
51
|
+
`<rect x="5" y="-5" width="20" height="10" rx="5" fill="none" ${BODY}/>`,
|
|
52
|
+
`<line x1="5" y1="0" x2="25" y2="0" ${BODY}/>`,
|
|
53
|
+
lineWire(25, 0, 30, 0)
|
|
54
|
+
].join("")
|
|
645
55
|
};
|
|
646
56
|
var crystal = {
|
|
647
57
|
length: 40,
|
|
@@ -656,6 +66,7 @@ var crystal = {
|
|
|
656
66
|
};
|
|
657
67
|
var transformer = {
|
|
658
68
|
length: 60,
|
|
69
|
+
netlistPins: ["p1", "p2", "s1", "s2"],
|
|
659
70
|
anchors: {
|
|
660
71
|
start: { x: 0, y: 0 },
|
|
661
72
|
end: { x: 60, y: 0 },
|
|
@@ -678,6 +89,7 @@ var transformer = {
|
|
|
678
89
|
};
|
|
679
90
|
var voltage_source = {
|
|
680
91
|
length: 40,
|
|
92
|
+
netlistPins: ["plus", "minus"],
|
|
681
93
|
// plus/minus aliases: end = +, start = − (matches on-symbol label)
|
|
682
94
|
anchors: {
|
|
683
95
|
start: { x: 0, y: 0 },
|
|
@@ -695,6 +107,7 @@ var voltage_source = {
|
|
|
695
107
|
};
|
|
696
108
|
var current_source = {
|
|
697
109
|
length: 40,
|
|
110
|
+
netlistPins: ["plus", "minus"],
|
|
698
111
|
anchors: {
|
|
699
112
|
start: { x: 0, y: 0 },
|
|
700
113
|
end: { x: 40, y: 0 },
|
|
@@ -711,6 +124,7 @@ var current_source = {
|
|
|
711
124
|
};
|
|
712
125
|
var ac_source = {
|
|
713
126
|
length: 40,
|
|
127
|
+
netlistPins: ["plus", "minus"],
|
|
714
128
|
anchors: {
|
|
715
129
|
start: { x: 0, y: 0 },
|
|
716
130
|
end: { x: 40, y: 0 },
|
|
@@ -726,6 +140,7 @@ var ac_source = {
|
|
|
726
140
|
};
|
|
727
141
|
var battery = {
|
|
728
142
|
length: 24,
|
|
143
|
+
netlistPins: ["plus", "minus"],
|
|
729
144
|
anchors: {
|
|
730
145
|
start: { x: 0, y: 0 },
|
|
731
146
|
end: { x: 24, y: 0 },
|
|
@@ -826,6 +241,7 @@ var photodiode = {
|
|
|
826
241
|
};
|
|
827
242
|
var npn = {
|
|
828
243
|
length: 40,
|
|
244
|
+
netlistPins: ["c", "b", "e"],
|
|
829
245
|
// base at left, collector up-right, emitter down-right
|
|
830
246
|
anchors: {
|
|
831
247
|
start: { x: 0, y: 0 },
|
|
@@ -851,6 +267,7 @@ var npn = {
|
|
|
851
267
|
};
|
|
852
268
|
var pnp = {
|
|
853
269
|
length: 40,
|
|
270
|
+
netlistPins: ["c", "b", "e"],
|
|
854
271
|
anchors: {
|
|
855
272
|
start: { x: 0, y: 0 },
|
|
856
273
|
end: { x: 40, y: -16 },
|
|
@@ -875,6 +292,7 @@ var pnp = {
|
|
|
875
292
|
};
|
|
876
293
|
var nmos = {
|
|
877
294
|
length: 40,
|
|
295
|
+
netlistPins: ["d", "g", "s"],
|
|
878
296
|
anchors: {
|
|
879
297
|
start: { x: 0, y: 0 },
|
|
880
298
|
end: { x: 40, y: -16 },
|
|
@@ -900,6 +318,7 @@ var nmos = {
|
|
|
900
318
|
};
|
|
901
319
|
var pmos = {
|
|
902
320
|
length: 40,
|
|
321
|
+
netlistPins: ["d", "g", "s"],
|
|
903
322
|
anchors: {
|
|
904
323
|
start: { x: 0, y: 0 },
|
|
905
324
|
end: { x: 40, y: -16 },
|
|
@@ -925,12 +344,16 @@ var pmos = {
|
|
|
925
344
|
};
|
|
926
345
|
var jfet_n = {
|
|
927
346
|
length: 40,
|
|
347
|
+
netlistPins: ["d", "g", "s"],
|
|
928
348
|
anchors: {
|
|
929
349
|
start: { x: 0, y: 0 },
|
|
930
350
|
end: { x: 40, y: -16 },
|
|
931
351
|
gate: { x: 0, y: 0 },
|
|
932
352
|
drain: { x: 40, y: -16 },
|
|
933
|
-
source: { x: 40, y: 16 }
|
|
353
|
+
source: { x: 40, y: 16 },
|
|
354
|
+
g: { x: 0, y: 0 },
|
|
355
|
+
d: { x: 40, y: -16 },
|
|
356
|
+
s: { x: 40, y: 16 }
|
|
934
357
|
},
|
|
935
358
|
svg: () => [
|
|
936
359
|
lineWire(0, 0, 14, 0),
|
|
@@ -944,12 +367,16 @@ var jfet_n = {
|
|
|
944
367
|
};
|
|
945
368
|
var jfet_p = {
|
|
946
369
|
length: 40,
|
|
370
|
+
netlistPins: ["d", "g", "s"],
|
|
947
371
|
anchors: {
|
|
948
372
|
start: { x: 0, y: 0 },
|
|
949
373
|
end: { x: 40, y: -16 },
|
|
950
374
|
gate: { x: 0, y: 0 },
|
|
951
375
|
drain: { x: 40, y: -16 },
|
|
952
|
-
source: { x: 40, y: 16 }
|
|
376
|
+
source: { x: 40, y: 16 },
|
|
377
|
+
g: { x: 0, y: 0 },
|
|
378
|
+
d: { x: 40, y: -16 },
|
|
379
|
+
s: { x: 40, y: 16 }
|
|
953
380
|
},
|
|
954
381
|
svg: () => [
|
|
955
382
|
lineWire(0, 0, 14, 0),
|
|
@@ -963,6 +390,7 @@ var jfet_p = {
|
|
|
963
390
|
};
|
|
964
391
|
var opamp = {
|
|
965
392
|
length: 50,
|
|
393
|
+
netlistPins: ["plus", "minus", "out"],
|
|
966
394
|
anchors: {
|
|
967
395
|
start: { x: 0, y: 0 },
|
|
968
396
|
end: { x: 50, y: 0 },
|
|
@@ -980,6 +408,7 @@ var opamp = {
|
|
|
980
408
|
};
|
|
981
409
|
var comparator = {
|
|
982
410
|
length: 50,
|
|
411
|
+
netlistPins: ["plus", "minus", "out"],
|
|
983
412
|
anchors: {
|
|
984
413
|
start: { x: 0, y: 0 },
|
|
985
414
|
end: { x: 50, y: 0 },
|
|
@@ -1128,6 +557,7 @@ var variable_inductor = {
|
|
|
1128
557
|
};
|
|
1129
558
|
var switch_spdt = {
|
|
1130
559
|
length: 50,
|
|
560
|
+
netlistPins: ["common", "nc", "no"],
|
|
1131
561
|
anchors: {
|
|
1132
562
|
start: { x: 0, y: 0 },
|
|
1133
563
|
end: { x: 50, y: 0 },
|
|
@@ -1202,292 +632,893 @@ var antenna = {
|
|
|
1202
632
|
`<line x1="0" y1="-10" x2="10" y2="-24" ${BODY}/>`
|
|
1203
633
|
].join("")
|
|
1204
634
|
};
|
|
1205
|
-
function icSymbol(defaultLeft, defaultRight, bodyLabel) {
|
|
1206
|
-
const BODY_W = 80;
|
|
1207
|
-
return {
|
|
1208
|
-
length: BODY_W,
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
const
|
|
1216
|
-
const
|
|
1217
|
-
const
|
|
1218
|
-
const
|
|
1219
|
-
const
|
|
1220
|
-
const
|
|
1221
|
-
parts
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
parts.push(`<
|
|
635
|
+
function icSymbol(defaultLeft, defaultRight, bodyLabel) {
|
|
636
|
+
const BODY_W = 80;
|
|
637
|
+
return {
|
|
638
|
+
length: BODY_W,
|
|
639
|
+
netlistPins: [],
|
|
640
|
+
anchors: {
|
|
641
|
+
start: { x: 0, y: 0 },
|
|
642
|
+
end: { x: BODY_W, y: 0 }
|
|
643
|
+
},
|
|
644
|
+
svg: (_label, _value, attrs) => {
|
|
645
|
+
const left = attrs?.pins_left ? attrs.pins_left.split(",").map((s) => s.trim()) : defaultLeft;
|
|
646
|
+
const right = attrs?.pins_right ? attrs.pins_right.split(",").map((s) => s.trim()) : defaultRight;
|
|
647
|
+
const n = Math.max(left.length, right.length, 2);
|
|
648
|
+
const pitch = 16;
|
|
649
|
+
const bodyH = pitch * (n + 1);
|
|
650
|
+
const topY = -bodyH / 2;
|
|
651
|
+
const parts = [];
|
|
652
|
+
parts.push(`<rect x="0" y="${topY}" width="${BODY_W}" height="${bodyH}" fill="white" ${BODY}/>`);
|
|
653
|
+
const labelText = attrs?.ic_label ?? bodyLabel ?? "";
|
|
654
|
+
if (labelText) {
|
|
655
|
+
parts.push(`<text x="${BODY_W / 2}" y="3" text-anchor="middle" class="schematex-circuit-meter">${labelText}</text>`);
|
|
656
|
+
}
|
|
657
|
+
for (let i = 0; i < left.length; i++) {
|
|
658
|
+
const y = topY + pitch * (i + 1);
|
|
659
|
+
parts.push(`<line x1="-8" y1="${y}" x2="0" y2="${y}" ${WIRE}/>`);
|
|
660
|
+
parts.push(`<text x="4" y="${y + 3}" class="schematex-circuit-pol">${left[i]}</text>`);
|
|
661
|
+
}
|
|
662
|
+
for (let i = 0; i < right.length; i++) {
|
|
663
|
+
const y = topY + pitch * (i + 1);
|
|
664
|
+
parts.push(`<line x1="${BODY_W}" y1="${y}" x2="${BODY_W + 8}" y2="${y}" ${WIRE}/>`);
|
|
665
|
+
parts.push(`<text x="${BODY_W - 4}" y="${y + 3}" text-anchor="end" class="schematex-circuit-pol">${right[i]}</text>`);
|
|
666
|
+
}
|
|
667
|
+
return parts.join("");
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
var generic_ic = icSymbol(
|
|
672
|
+
["1", "2", "3", "4"],
|
|
673
|
+
["8", "7", "6", "5"],
|
|
674
|
+
"IC"
|
|
675
|
+
);
|
|
676
|
+
var timer_555 = (() => {
|
|
677
|
+
const left = ["GND", "TRG", "OUT", "RST"];
|
|
678
|
+
const right = ["VCC", "DIS", "THR", "CTL"];
|
|
679
|
+
const sym = icSymbol(left, right, "555");
|
|
680
|
+
const BODY_W = 80;
|
|
681
|
+
const pitch = 16;
|
|
682
|
+
const n = 4;
|
|
683
|
+
const topY = -80 / 2;
|
|
684
|
+
const anchors = {
|
|
685
|
+
start: { x: 0, y: 0 },
|
|
686
|
+
end: { x: BODY_W, y: 0 }
|
|
687
|
+
};
|
|
688
|
+
const leftNames = ["gnd", "trg", "out", "rst"];
|
|
689
|
+
const rightNames = ["vcc", "dis", "thr", "ctl"];
|
|
690
|
+
for (let i = 0; i < n; i++) {
|
|
691
|
+
const y = topY + pitch * (i + 1);
|
|
692
|
+
anchors[leftNames[i]] = { x: -8, y };
|
|
693
|
+
anchors[rightNames[i]] = { x: BODY_W + 8, y };
|
|
694
|
+
}
|
|
695
|
+
return { ...sym, anchors };
|
|
696
|
+
})();
|
|
697
|
+
var voltage_regulator = {
|
|
698
|
+
length: 60,
|
|
699
|
+
netlistPins: ["in", "gnd", "out"],
|
|
700
|
+
anchors: {
|
|
701
|
+
start: { x: 0, y: 0 },
|
|
702
|
+
end: { x: 60, y: 0 },
|
|
703
|
+
in: { x: 0, y: 0 },
|
|
704
|
+
out: { x: 60, y: 0 },
|
|
705
|
+
gnd: { x: 30, y: 20 }
|
|
706
|
+
},
|
|
707
|
+
svg: (_l, _v, attrs) => [
|
|
708
|
+
lineWire(0, 0, 10, 0),
|
|
709
|
+
`<rect x="10" y="-15" width="40" height="30" fill="white" ${BODY}/>`,
|
|
710
|
+
`<text x="30" y="4" text-anchor="middle" class="schematex-circuit-meter">${attrs?.model ?? "REG"}</text>`,
|
|
711
|
+
lineWire(50, 0, 60, 0),
|
|
712
|
+
lineWire(30, 15, 30, 20)
|
|
713
|
+
].join("")
|
|
714
|
+
};
|
|
715
|
+
var potentiometer = {
|
|
716
|
+
length: 50,
|
|
717
|
+
netlistPins: ["start", "wiper", "end"],
|
|
718
|
+
anchors: {
|
|
719
|
+
start: { x: 0, y: 0 },
|
|
720
|
+
end: { x: 50, y: 0 },
|
|
721
|
+
wiper: { x: 25, y: -22 }
|
|
722
|
+
},
|
|
723
|
+
svg: () => [
|
|
724
|
+
`<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}/>`,
|
|
725
|
+
`<line x1="25" y1="-22" x2="25" y2="-10" ${BODY}/>`,
|
|
726
|
+
`<polygon points="25,-10 21,-16 29,-16" ${FILL}/>`
|
|
727
|
+
].join("")
|
|
728
|
+
};
|
|
729
|
+
var terminal_block = {
|
|
730
|
+
length: 80,
|
|
731
|
+
netlistPins: [],
|
|
732
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 80, y: 0 } },
|
|
733
|
+
svg: (label, _value, attrs) => {
|
|
734
|
+
const pinsAttr = attrs?.pins ?? attrs?.terminals ?? "1,2,3,4";
|
|
735
|
+
const pins = pinsAttr.split(",").map((s) => s.trim()).filter(Boolean);
|
|
736
|
+
const n = Math.max(pins.length, 1);
|
|
737
|
+
const BODY_W = 80;
|
|
738
|
+
const pitch = 18;
|
|
739
|
+
const bodyH = pitch * (n + 1);
|
|
740
|
+
const topY = -bodyH / 2;
|
|
741
|
+
const parts = [];
|
|
742
|
+
parts.push(
|
|
743
|
+
`<rect x="0" y="${topY}" width="${BODY_W}" height="${bodyH}" rx="3" fill="white" stroke-width="2" ${BODY}/>`
|
|
744
|
+
);
|
|
745
|
+
if (label) {
|
|
746
|
+
parts.push(
|
|
747
|
+
`<text x="${BODY_W / 2}" y="${topY + 14}" text-anchor="middle" class="schematex-circuit-meter">${label}</text>`
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
for (let i = 0; i < n; i++) {
|
|
751
|
+
const y = topY + pitch * (i + 1) + (label ? 8 : 0);
|
|
752
|
+
parts.push(`<line x1="-8" y1="${y}" x2="0" y2="${y}" ${WIRE}/>`);
|
|
753
|
+
parts.push(`<circle cx="6" cy="${y}" r="2" ${FILL}/>`);
|
|
754
|
+
parts.push(
|
|
755
|
+
`<text x="12" y="${y + 3}" class="schematex-circuit-pol">${pins[i] ?? `T${i + 1}`}</text>`
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
return parts.join("");
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
var relay_coil = {
|
|
762
|
+
length: 40,
|
|
763
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
764
|
+
svg: () => [
|
|
765
|
+
lineWire(0, 0, 8, 0),
|
|
766
|
+
`<rect x="8" y="-10" width="24" height="20" fill="white" ${BODY}/>`,
|
|
767
|
+
// Diagonal slash inside the box = coil winding indicator
|
|
768
|
+
`<line x1="8" y1="-10" x2="32" y2="10" ${BODY}/>`,
|
|
769
|
+
lineWire(32, 0, 40, 0)
|
|
770
|
+
].join("")
|
|
771
|
+
};
|
|
772
|
+
var relay_no = {
|
|
773
|
+
length: 40,
|
|
774
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
775
|
+
svg: () => [
|
|
776
|
+
lineWire(0, 0, 10, 0),
|
|
777
|
+
`<line x1="10" y1="0" x2="30" y2="-10" ${BODY}/>`,
|
|
778
|
+
`<circle cx="10" cy="0" r="2" ${FILL}/>`,
|
|
779
|
+
`<circle cx="30" cy="0" r="2" ${FILL}/>`,
|
|
780
|
+
// Small dashed bar above to denote actuator-driven (vs hand switch)
|
|
781
|
+
`<line x1="14" y1="-14" x2="26" y2="-14" stroke-dasharray="2,2" ${BODY}/>`,
|
|
782
|
+
lineWire(30, 0, 40, 0)
|
|
783
|
+
].join("")
|
|
784
|
+
};
|
|
785
|
+
var relay_nc = {
|
|
786
|
+
length: 40,
|
|
787
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
788
|
+
svg: () => [
|
|
789
|
+
lineWire(0, 0, 10, 0),
|
|
790
|
+
`<line x1="10" y1="-10" x2="30" y2="-10" ${BODY}/>`,
|
|
791
|
+
// NC slash: line crosses both contact endpoints (closed by default)
|
|
792
|
+
`<line x1="8" y1="2" x2="32" y2="-12" ${BODY}/>`,
|
|
793
|
+
`<circle cx="10" cy="0" r="2" ${FILL}/>`,
|
|
794
|
+
`<circle cx="30" cy="0" r="2" ${FILL}/>`,
|
|
795
|
+
`<line x1="14" y1="-14" x2="26" y2="-14" stroke-dasharray="2,2" ${BODY}/>`,
|
|
796
|
+
lineWire(30, 0, 40, 0)
|
|
797
|
+
].join("")
|
|
798
|
+
};
|
|
799
|
+
var contactor = {
|
|
800
|
+
length: 44,
|
|
801
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 44, y: 0 } },
|
|
802
|
+
svg: () => [
|
|
803
|
+
lineWire(0, 0, 10, 0),
|
|
804
|
+
// Two parallel diagonal contacts = double-break (typical of contactors)
|
|
805
|
+
`<line x1="10" y1="0" x2="30" y2="-10" stroke-width="2.5" ${BODY}/>`,
|
|
806
|
+
`<line x1="14" y1="2" x2="34" y2="-8" stroke-width="2.5" ${BODY}/>`,
|
|
807
|
+
`<circle cx="10" cy="0" r="2" ${FILL}/>`,
|
|
808
|
+
`<circle cx="34" cy="0" r="2" ${FILL}/>`,
|
|
809
|
+
// Solid bar above = electromagnetic-driven actuator
|
|
810
|
+
`<line x1="14" y1="-14" x2="30" y2="-14" stroke-width="2" ${BODY}/>`,
|
|
811
|
+
lineWire(34, 0, 44, 0)
|
|
812
|
+
].join("")
|
|
813
|
+
};
|
|
814
|
+
var solenoid_valve = {
|
|
815
|
+
length: 50,
|
|
816
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 50, y: 0 } },
|
|
817
|
+
svg: () => [
|
|
818
|
+
lineWire(0, 0, 8, 0),
|
|
819
|
+
// Solenoid box on top
|
|
820
|
+
`<rect x="8" y="-22" width="14" height="12" fill="white" ${BODY}/>`,
|
|
821
|
+
`<line x1="8" y1="-22" x2="22" y2="-10" ${BODY}/>`,
|
|
822
|
+
// Valve body (triangle pair = IEC valve symbol)
|
|
823
|
+
`<polygon points="22,0 38,-8 38,8" fill="white" ${BODY}/>`,
|
|
824
|
+
`<polygon points="22,0 8,-8 8,8" fill="white" ${BODY}/>`,
|
|
825
|
+
// Connect solenoid to valve body (actuator line)
|
|
826
|
+
`<line x1="15" y1="-10" x2="22" y2="0" ${BODY}/>`,
|
|
827
|
+
lineWire(38, 0, 50, 0)
|
|
828
|
+
].join("")
|
|
829
|
+
};
|
|
830
|
+
var thermal_overload = {
|
|
831
|
+
length: 40,
|
|
832
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
833
|
+
svg: () => [
|
|
834
|
+
lineWire(0, 0, 8, 0),
|
|
835
|
+
`<rect x="8" y="-12" width="24" height="24" fill="white" ${BODY}/>`,
|
|
836
|
+
// Bimetal element: bent line inside box
|
|
837
|
+
`<path d="M 12,-6 L 16,4 L 20,-6 L 24,4 L 28,-6" fill="none" ${BODY}/>`,
|
|
838
|
+
lineWire(32, 0, 40, 0)
|
|
839
|
+
].join("")
|
|
840
|
+
};
|
|
841
|
+
var disconnect_switch = {
|
|
842
|
+
length: 48,
|
|
843
|
+
anchors: { start: { x: 0, y: 0 }, end: { x: 48, y: 0 } },
|
|
844
|
+
svg: () => [
|
|
845
|
+
lineWire(0, 0, 10, 0),
|
|
846
|
+
`<line x1="10" y1="0" x2="34" y2="-12" ${BODY}/>`,
|
|
847
|
+
`<circle cx="10" cy="0" r="2" ${FILL}/>`,
|
|
848
|
+
// Hollow square at top of arm = visible-isolation indicator
|
|
849
|
+
`<rect x="30" y="-16" width="8" height="8" fill="white" ${BODY}/>`,
|
|
850
|
+
`<circle cx="38" cy="0" r="2" ${FILL}/>`,
|
|
851
|
+
lineWire(38, 0, 48, 0)
|
|
852
|
+
].join("")
|
|
853
|
+
};
|
|
854
|
+
var SYMBOLS = {
|
|
855
|
+
resistor,
|
|
856
|
+
capacitor,
|
|
857
|
+
electrolytic_cap,
|
|
858
|
+
inductor,
|
|
859
|
+
fuse,
|
|
860
|
+
crystal,
|
|
861
|
+
transformer,
|
|
862
|
+
voltage_source,
|
|
863
|
+
current_source,
|
|
864
|
+
ac_source,
|
|
865
|
+
battery,
|
|
866
|
+
ground,
|
|
867
|
+
gnd_signal,
|
|
868
|
+
vcc,
|
|
869
|
+
diode,
|
|
870
|
+
zener,
|
|
871
|
+
schottky,
|
|
872
|
+
led,
|
|
873
|
+
photodiode,
|
|
874
|
+
npn,
|
|
875
|
+
pnp,
|
|
876
|
+
nmos,
|
|
877
|
+
pmos,
|
|
878
|
+
jfet_n,
|
|
879
|
+
jfet_p,
|
|
880
|
+
opamp,
|
|
881
|
+
comparator,
|
|
882
|
+
switch_spst,
|
|
883
|
+
push_no,
|
|
884
|
+
ammeter,
|
|
885
|
+
voltmeter,
|
|
886
|
+
wattmeter,
|
|
887
|
+
motor,
|
|
888
|
+
speaker,
|
|
889
|
+
microphone,
|
|
890
|
+
buzzer,
|
|
891
|
+
potentiometer,
|
|
892
|
+
rheostat,
|
|
893
|
+
thermistor_ntc,
|
|
894
|
+
thermistor_ptc,
|
|
895
|
+
ldr,
|
|
896
|
+
variable_cap,
|
|
897
|
+
variable_inductor,
|
|
898
|
+
switch_spdt,
|
|
899
|
+
push_nc,
|
|
900
|
+
gnd_chassis,
|
|
901
|
+
gnd_digital,
|
|
902
|
+
test_point,
|
|
903
|
+
no_connect,
|
|
904
|
+
antenna,
|
|
905
|
+
generic_ic,
|
|
906
|
+
terminal_block,
|
|
907
|
+
"555_timer": timer_555,
|
|
908
|
+
voltage_regulator,
|
|
909
|
+
// Industrial control / power electrical (IEC 60617)
|
|
910
|
+
relay_coil,
|
|
911
|
+
relay_no,
|
|
912
|
+
relay_nc,
|
|
913
|
+
contactor,
|
|
914
|
+
solenoid_valve,
|
|
915
|
+
thermal_overload,
|
|
916
|
+
disconnect_switch
|
|
917
|
+
// Lamp reuses buzzer slot? No, needs its own entry but our CircuitComponentType
|
|
918
|
+
// doesn't have "lamp". We map it via parser alias to "buzzer" or add specifically.
|
|
919
|
+
};
|
|
920
|
+
var EXTRA_SYMBOLS = {
|
|
921
|
+
lamp
|
|
922
|
+
};
|
|
923
|
+
function getSymbol(t) {
|
|
924
|
+
return SYMBOLS[t] ?? EXTRA_SYMBOLS[t];
|
|
925
|
+
}
|
|
926
|
+
function getNetlistPinOrder(t) {
|
|
927
|
+
const sym = getSymbol(t);
|
|
928
|
+
if (!sym) return void 0;
|
|
929
|
+
if (sym.netlistPins) return [...sym.netlistPins];
|
|
930
|
+
if (sym.anchors.start && sym.anchors.end) return ["start", "end"];
|
|
931
|
+
return Object.keys(sym.anchors);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// src/diagrams/circuit/netlist.ts
|
|
935
|
+
var NetlistParseError = class extends Error {
|
|
936
|
+
constructor(message, line) {
|
|
937
|
+
super(message);
|
|
938
|
+
this.line = line;
|
|
939
|
+
this.name = "NetlistParseError";
|
|
940
|
+
}
|
|
941
|
+
line;
|
|
942
|
+
};
|
|
943
|
+
var PREFIX_MAP = {
|
|
944
|
+
R: { type: "resistor", pins: ["start", "end"] },
|
|
945
|
+
C: { type: "capacitor", pins: ["start", "end"] },
|
|
946
|
+
L: { type: "inductor", pins: ["start", "end"] },
|
|
947
|
+
D: { type: "diode", pins: ["start", "end"] },
|
|
948
|
+
// anode → start, cathode → end
|
|
949
|
+
V: { type: "voltage_source", pins: ["plus", "minus"] },
|
|
950
|
+
I: { type: "current_source", pins: ["plus", "minus"] },
|
|
951
|
+
Q: { type: "npn", pins: ["c", "b", "e"] },
|
|
952
|
+
M: { type: "nmos", pins: ["d", "g", "s"] },
|
|
953
|
+
J: { type: "jfet_n", pins: ["d", "g", "s"] },
|
|
954
|
+
S: { type: "switch_spst", pins: ["start", "end"] },
|
|
955
|
+
F: { type: "fuse", pins: ["start", "end"] },
|
|
956
|
+
B: { type: "battery", pins: ["plus", "minus"] },
|
|
957
|
+
K: { type: "relay_coil", pins: ["start", "end"] },
|
|
958
|
+
U: { type: "generic_ic", pins: [] },
|
|
959
|
+
// pins declared via pins="..." attr
|
|
960
|
+
X: { type: "generic_ic", pins: [] },
|
|
961
|
+
W: { type: "wire", pins: ["start", "end"] },
|
|
962
|
+
// explicit wire (non-SPICE convention, common in EE textbooks)
|
|
963
|
+
T: { type: "terminal_block", pins: [] }
|
|
964
|
+
// pins via pins="..."
|
|
965
|
+
};
|
|
966
|
+
var TYPE_ALIASES = {
|
|
967
|
+
vsource: "voltage_source",
|
|
968
|
+
isource: "current_source",
|
|
969
|
+
acsource: "ac_source",
|
|
970
|
+
ecap: "electrolytic_cap",
|
|
971
|
+
pot: "potentiometer",
|
|
972
|
+
gnd: "ground",
|
|
973
|
+
ic: "generic_ic",
|
|
974
|
+
reg: "voltage_regulator",
|
|
975
|
+
timer555: "555_timer",
|
|
976
|
+
transistor: "npn",
|
|
977
|
+
tb: "terminal_block",
|
|
978
|
+
junction_box: "terminal_block",
|
|
979
|
+
jbox: "terminal_block",
|
|
980
|
+
enclosure: "terminal_block"
|
|
981
|
+
};
|
|
982
|
+
var GROUND_REF = /^(0|gnd|ground|earth|pe|agnd|dgnd|gnda|gndd|vss|com)(_\w+|\d+)?$/i;
|
|
983
|
+
function isGroundRef(s) {
|
|
984
|
+
return GROUND_REF.test(s);
|
|
985
|
+
}
|
|
986
|
+
function tokenize(line) {
|
|
987
|
+
const tokens = [];
|
|
988
|
+
let i = 0;
|
|
989
|
+
while (i < line.length) {
|
|
990
|
+
const ch = line[i];
|
|
991
|
+
if (ch === " " || ch === " ") {
|
|
992
|
+
i++;
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
995
|
+
if (ch === '"') {
|
|
996
|
+
const end = line.indexOf('"', i + 1);
|
|
997
|
+
tokens.push(line.slice(i, end < 0 ? line.length : end + 1));
|
|
998
|
+
i = end < 0 ? line.length : end + 1;
|
|
999
|
+
continue;
|
|
1000
|
+
}
|
|
1001
|
+
let j = i;
|
|
1002
|
+
while (j < line.length && line[j] !== " " && line[j] !== " ") {
|
|
1003
|
+
if (line[j] === "=" && line[j + 1] === '"') {
|
|
1004
|
+
const end = line.indexOf('"', j + 2);
|
|
1005
|
+
j = end < 0 ? line.length : end + 1;
|
|
1006
|
+
break;
|
|
1007
|
+
}
|
|
1008
|
+
j++;
|
|
1009
|
+
}
|
|
1010
|
+
tokens.push(line.slice(i, j));
|
|
1011
|
+
i = j;
|
|
1012
|
+
}
|
|
1013
|
+
return tokens;
|
|
1014
|
+
}
|
|
1015
|
+
function isKeyEqVal(tok) {
|
|
1016
|
+
const eq = tok.indexOf("=");
|
|
1017
|
+
return eq > 0 && /^[a-zA-Z_][\w]*$/.test(tok.slice(0, eq));
|
|
1018
|
+
}
|
|
1019
|
+
function parseKV(tok) {
|
|
1020
|
+
const eq = tok.indexOf("=");
|
|
1021
|
+
const key = tok.slice(0, eq).trim();
|
|
1022
|
+
let val = tok.slice(eq + 1).trim();
|
|
1023
|
+
if (val.startsWith('"') && val.endsWith('"')) val = val.slice(1, -1);
|
|
1024
|
+
return [key, val];
|
|
1025
|
+
}
|
|
1026
|
+
function parseNetlist(body, title2) {
|
|
1027
|
+
const components = [];
|
|
1028
|
+
const netByName = /* @__PURE__ */ new Map();
|
|
1029
|
+
const pinMap = {};
|
|
1030
|
+
let autoGnd = 0;
|
|
1031
|
+
const ensureNet = (name) => {
|
|
1032
|
+
let n = netByName.get(name);
|
|
1033
|
+
if (!n) {
|
|
1034
|
+
n = { id: name, anchors: [] };
|
|
1035
|
+
netByName.set(name, n);
|
|
1036
|
+
}
|
|
1037
|
+
return n;
|
|
1038
|
+
};
|
|
1039
|
+
const lines = body.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
1040
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
1041
|
+
const raw = lines[lineIdx];
|
|
1042
|
+
const stripped = raw.replace(/#.*$/, "").trim();
|
|
1043
|
+
if (!stripped) continue;
|
|
1044
|
+
const tokens = tokenize(stripped);
|
|
1045
|
+
if (tokens.length < 2) {
|
|
1046
|
+
throw new NetlistParseError(
|
|
1047
|
+
`Netlist line must have at least ID + one net: "${stripped}"`,
|
|
1048
|
+
lineIdx + 1
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
const id = tokens[0];
|
|
1052
|
+
if (!/^[a-zA-Z_][\w]*$/.test(id)) {
|
|
1053
|
+
throw new NetlistParseError(`Invalid component id: "${id}"`, lineIdx + 1);
|
|
1054
|
+
}
|
|
1055
|
+
let cursor = 1;
|
|
1056
|
+
const netRefs = [];
|
|
1057
|
+
while (cursor < tokens.length && !isKeyEqVal(tokens[cursor])) {
|
|
1058
|
+
netRefs.push(tokens[cursor]);
|
|
1059
|
+
cursor++;
|
|
1060
|
+
}
|
|
1061
|
+
const kv = {};
|
|
1062
|
+
for (; cursor < tokens.length; cursor++) {
|
|
1063
|
+
if (!isKeyEqVal(tokens[cursor])) {
|
|
1064
|
+
throw new NetlistParseError(
|
|
1065
|
+
`Expected key=value after nets, got "${tokens[cursor]}"`,
|
|
1066
|
+
lineIdx + 1
|
|
1067
|
+
);
|
|
1068
|
+
}
|
|
1069
|
+
const [k, v] = parseKV(tokens[cursor]);
|
|
1070
|
+
kv[k] = v;
|
|
1071
|
+
}
|
|
1072
|
+
const prefix = id[0].toUpperCase();
|
|
1073
|
+
const defaults = PREFIX_MAP[prefix];
|
|
1074
|
+
let cType;
|
|
1075
|
+
let pinOrder;
|
|
1076
|
+
if (kv.type) {
|
|
1077
|
+
const t = kv.type.toLowerCase();
|
|
1078
|
+
cType = TYPE_ALIASES[t] ?? t;
|
|
1079
|
+
pinOrder = getNetlistPinOrder(cType) ?? defaults?.pins ?? ["start", "end"];
|
|
1080
|
+
} else if (defaults) {
|
|
1081
|
+
cType = defaults.type;
|
|
1082
|
+
pinOrder = defaults.pins;
|
|
1083
|
+
} else if (isGroundRef(id)) {
|
|
1084
|
+
cType = "ground";
|
|
1085
|
+
pinOrder = ["start"];
|
|
1086
|
+
} else {
|
|
1087
|
+
throw new NetlistParseError(
|
|
1088
|
+
`Cannot infer type from id "${id}". Either rename to a SPICE-prefix id (R*, C*, L*, D*, V*, I*, Q*, M*, J*, S*, F*, B*, K*, U*, X*, W*, T*) or pass an explicit \`type=<name>\` attribute (e.g. \`${id} ... type=resistor\`). Schematex circuit covers electrical schematics only \u2014 hydraulic/pneumatic prefixes (EV*, BOMBA*, TANK*, etc.) are not supported.`,
|
|
1089
|
+
lineIdx + 1
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1092
|
+
const expectedPins = pinOrder.length;
|
|
1093
|
+
let valueFromTail;
|
|
1094
|
+
if (netRefs.length > expectedPins && expectedPins > 0) {
|
|
1095
|
+
const tail = netRefs.slice(expectedPins);
|
|
1096
|
+
netRefs.length = expectedPins;
|
|
1097
|
+
const first = tail[0].toLowerCase();
|
|
1098
|
+
if (TYPE_ALIASES[first]) {
|
|
1099
|
+
cType = TYPE_ALIASES[first];
|
|
1100
|
+
pinOrder = getNetlistPinOrder(cType) ?? pinOrder;
|
|
1101
|
+
} else if (first === "npn" || first === "pnp" || first === "nmos" || first === "pmos" || first === "jfet_n" || first === "jfet_p" || first === "zener" || first === "schottky" || first === "led" || first === "photodiode") {
|
|
1102
|
+
cType = first;
|
|
1103
|
+
pinOrder = getNetlistPinOrder(cType) ?? pinOrder;
|
|
1104
|
+
} else {
|
|
1105
|
+
valueFromTail = tail.join(" ");
|
|
1106
|
+
}
|
|
1107
|
+
if (tail.length > 1 && !valueFromTail) {
|
|
1108
|
+
valueFromTail = tail.slice(1).join(" ");
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
if (cType === "ground" || cType === "gnd_signal" || cType === "gnd_chassis" || cType === "gnd_digital") {
|
|
1112
|
+
pinOrder = ["start"];
|
|
1113
|
+
}
|
|
1114
|
+
if (cType === "terminal_block") {
|
|
1115
|
+
const pinsAttr = kv.pins ?? kv.terminals;
|
|
1116
|
+
const labels = pinsAttr ? pinsAttr.split(",").map((s) => s.trim()).filter(Boolean) : Array.from({ length: Math.max(netRefs.length, 1) }, (_, i) => `t${i + 1}`);
|
|
1117
|
+
pinOrder = labels.map(
|
|
1118
|
+
(label, idx) => label.toLowerCase().replace(/[^a-z0-9]+/g, "_") || `t${idx + 1}`
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
if (netRefs.length < pinOrder.length) {
|
|
1122
|
+
throw new NetlistParseError(
|
|
1123
|
+
`Component ${id} (${cType}) expects ${pinOrder.length} nets, got ${netRefs.length}`,
|
|
1124
|
+
lineIdx + 1
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
|
+
const pins = {};
|
|
1128
|
+
for (let p = 0; p < pinOrder.length; p++) {
|
|
1129
|
+
let net = netRefs[p];
|
|
1130
|
+
if (isGroundRef(net)) net = "GND";
|
|
1131
|
+
pins[pinOrder[p]] = net;
|
|
1132
|
+
ensureNet(net).anchors.push(`${id}.${pinOrder[p]}`);
|
|
1133
|
+
}
|
|
1134
|
+
pinMap[id] = pins;
|
|
1135
|
+
const comp = {
|
|
1136
|
+
id,
|
|
1137
|
+
componentType: cType,
|
|
1138
|
+
direction: "right",
|
|
1139
|
+
label: kv.label ?? id,
|
|
1140
|
+
value: kv.value ?? valueFromTail,
|
|
1141
|
+
attrs: {}
|
|
1142
|
+
};
|
|
1143
|
+
for (const [k, v] of Object.entries(kv)) {
|
|
1144
|
+
if (k === "label" || k === "value" || k === "type") continue;
|
|
1145
|
+
comp.attrs[k] = v;
|
|
1146
|
+
}
|
|
1147
|
+
components.push(comp);
|
|
1148
|
+
}
|
|
1149
|
+
if (netByName.has("GND")) {
|
|
1150
|
+
const hasGroundSym = components.some(
|
|
1151
|
+
(c) => c.componentType === "ground" || c.componentType === "gnd_signal" || c.componentType === "gnd_chassis" || c.componentType === "gnd_digital"
|
|
1152
|
+
);
|
|
1153
|
+
if (!hasGroundSym) {
|
|
1154
|
+
const gId = `_GND${autoGnd++}`;
|
|
1155
|
+
components.push({
|
|
1156
|
+
id: gId,
|
|
1157
|
+
componentType: "ground",
|
|
1158
|
+
direction: "down",
|
|
1159
|
+
label: void 0,
|
|
1160
|
+
value: void 0,
|
|
1161
|
+
attrs: { auto: "true" }
|
|
1162
|
+
});
|
|
1163
|
+
pinMap[gId] = { start: "GND" };
|
|
1164
|
+
ensureNet("GND").anchors.push(`${gId}.start`);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
const nets = Array.from(netByName.values());
|
|
1168
|
+
return {
|
|
1169
|
+
type: "circuit",
|
|
1170
|
+
title: title2,
|
|
1171
|
+
components,
|
|
1172
|
+
nets,
|
|
1173
|
+
pinMap,
|
|
1174
|
+
mode: "netlist"
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// src/diagrams/circuit/parser.ts
|
|
1179
|
+
var CircuitParseError = class extends Error {
|
|
1180
|
+
constructor(message) {
|
|
1181
|
+
super(message);
|
|
1182
|
+
this.name = "CircuitParseError";
|
|
1183
|
+
}
|
|
1184
|
+
};
|
|
1185
|
+
var COMPONENT_TYPES = /* @__PURE__ */ new Set([
|
|
1186
|
+
"resistor",
|
|
1187
|
+
"potentiometer",
|
|
1188
|
+
"rheostat",
|
|
1189
|
+
"thermistor_ntc",
|
|
1190
|
+
"thermistor_ptc",
|
|
1191
|
+
"ldr",
|
|
1192
|
+
"varistor",
|
|
1193
|
+
"fuse",
|
|
1194
|
+
"fuse_slow",
|
|
1195
|
+
"capacitor",
|
|
1196
|
+
"electrolytic_cap",
|
|
1197
|
+
"variable_cap",
|
|
1198
|
+
"inductor",
|
|
1199
|
+
"inductor_iron",
|
|
1200
|
+
"inductor_ferrite",
|
|
1201
|
+
"variable_inductor",
|
|
1202
|
+
"ferrite_bead",
|
|
1203
|
+
"crystal",
|
|
1204
|
+
"transformer",
|
|
1205
|
+
"diode",
|
|
1206
|
+
"zener",
|
|
1207
|
+
"schottky",
|
|
1208
|
+
"led",
|
|
1209
|
+
"photodiode",
|
|
1210
|
+
"varactor",
|
|
1211
|
+
"tvs_diode",
|
|
1212
|
+
"bridge_rectifier",
|
|
1213
|
+
"npn",
|
|
1214
|
+
"pnp",
|
|
1215
|
+
"darlington_npn",
|
|
1216
|
+
"darlington_pnp",
|
|
1217
|
+
"nmos",
|
|
1218
|
+
"pmos",
|
|
1219
|
+
"nmos_depletion",
|
|
1220
|
+
"jfet_n",
|
|
1221
|
+
"jfet_p",
|
|
1222
|
+
"igbt",
|
|
1223
|
+
"scr",
|
|
1224
|
+
"triac",
|
|
1225
|
+
"diac",
|
|
1226
|
+
"phototransistor",
|
|
1227
|
+
"optocoupler",
|
|
1228
|
+
"opamp",
|
|
1229
|
+
"comparator",
|
|
1230
|
+
"schmitt_buffer",
|
|
1231
|
+
"tri_state_buffer",
|
|
1232
|
+
"instrumentation_amp",
|
|
1233
|
+
"generic_ic",
|
|
1234
|
+
"voltage_regulator",
|
|
1235
|
+
"dc_dc_converter",
|
|
1236
|
+
"555_timer",
|
|
1237
|
+
"voltage_source",
|
|
1238
|
+
"current_source",
|
|
1239
|
+
"ac_source",
|
|
1240
|
+
"battery",
|
|
1241
|
+
"vcc",
|
|
1242
|
+
"ground",
|
|
1243
|
+
"gnd_signal",
|
|
1244
|
+
"gnd_chassis",
|
|
1245
|
+
"gnd_digital",
|
|
1246
|
+
"switch_spst",
|
|
1247
|
+
"switch_spdt",
|
|
1248
|
+
"switch_dpdt",
|
|
1249
|
+
"push_no",
|
|
1250
|
+
"push_nc",
|
|
1251
|
+
"relay_coil",
|
|
1252
|
+
"relay_no",
|
|
1253
|
+
"relay_nc",
|
|
1254
|
+
"contactor",
|
|
1255
|
+
"solenoid_valve",
|
|
1256
|
+
"thermal_overload",
|
|
1257
|
+
"disconnect_switch",
|
|
1258
|
+
"motor",
|
|
1259
|
+
"speaker",
|
|
1260
|
+
"microphone",
|
|
1261
|
+
"buzzer",
|
|
1262
|
+
"ammeter",
|
|
1263
|
+
"voltmeter",
|
|
1264
|
+
"wattmeter",
|
|
1265
|
+
"oscilloscope",
|
|
1266
|
+
"wire",
|
|
1267
|
+
"dot",
|
|
1268
|
+
"label",
|
|
1269
|
+
"port",
|
|
1270
|
+
"test_point",
|
|
1271
|
+
"no_connect",
|
|
1272
|
+
"antenna"
|
|
1273
|
+
]);
|
|
1274
|
+
var ALIASES = {
|
|
1275
|
+
vsource: "voltage_source",
|
|
1276
|
+
isource: "current_source",
|
|
1277
|
+
acsource: "ac_source",
|
|
1278
|
+
ecap: "electrolytic_cap",
|
|
1279
|
+
pot: "potentiometer",
|
|
1280
|
+
xtal: "crystal",
|
|
1281
|
+
xfmr: "transformer",
|
|
1282
|
+
transistor: "npn",
|
|
1283
|
+
bjt_npn: "npn",
|
|
1284
|
+
bjt_pnp: "pnp",
|
|
1285
|
+
mosfet_n: "nmos",
|
|
1286
|
+
mosfet_p: "pmos",
|
|
1287
|
+
gnd: "ground",
|
|
1288
|
+
ic: "generic_ic",
|
|
1289
|
+
reg: "voltage_regulator",
|
|
1290
|
+
timer555: "555_timer",
|
|
1291
|
+
therm: "thermistor_ntc",
|
|
1292
|
+
ntc: "thermistor_ntc",
|
|
1293
|
+
ptc: "thermistor_ptc",
|
|
1294
|
+
ths: "thermistor_ntc",
|
|
1295
|
+
// Industrial control aliases (IEC letter codes)
|
|
1296
|
+
coil: "relay_coil",
|
|
1297
|
+
relay: "relay_coil",
|
|
1298
|
+
km: "contactor",
|
|
1299
|
+
solenoid: "solenoid_valve",
|
|
1300
|
+
ev: "solenoid_valve",
|
|
1301
|
+
overload: "thermal_overload",
|
|
1302
|
+
thermal: "thermal_overload",
|
|
1303
|
+
disconnect: "disconnect_switch",
|
|
1304
|
+
isolator: "disconnect_switch"
|
|
1305
|
+
};
|
|
1306
|
+
var EXTRA_TYPES = /* @__PURE__ */ new Set(["lamp"]);
|
|
1307
|
+
function normalizeType(raw) {
|
|
1308
|
+
const lower = raw.toLowerCase();
|
|
1309
|
+
if (ALIASES[lower]) return ALIASES[lower];
|
|
1310
|
+
if (COMPONENT_TYPES.has(lower)) {
|
|
1311
|
+
return lower;
|
|
1312
|
+
}
|
|
1313
|
+
if (EXTRA_TYPES.has(lower)) {
|
|
1314
|
+
return lower;
|
|
1315
|
+
}
|
|
1316
|
+
return null;
|
|
1317
|
+
}
|
|
1318
|
+
var DIRECTIONS = /* @__PURE__ */ new Set(["right", "left", "up", "down"]);
|
|
1319
|
+
function parseAttrs(rest) {
|
|
1320
|
+
const out = { attrs: {} };
|
|
1321
|
+
const tokens = [];
|
|
1322
|
+
let i = 0;
|
|
1323
|
+
while (i < rest.length) {
|
|
1324
|
+
const ch = rest[i];
|
|
1325
|
+
if (ch === " " || ch === " ") {
|
|
1326
|
+
i++;
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1329
|
+
if (ch === '"') {
|
|
1330
|
+
const end = rest.indexOf('"', i + 1);
|
|
1331
|
+
const tok = rest.slice(i, end < 0 ? rest.length : end + 1);
|
|
1332
|
+
tokens.push(tok);
|
|
1333
|
+
i = end < 0 ? rest.length : end + 1;
|
|
1334
|
+
continue;
|
|
1335
|
+
}
|
|
1336
|
+
let j = i;
|
|
1337
|
+
while (j < rest.length && rest[j] !== " " && rest[j] !== " ") {
|
|
1338
|
+
if (rest[j] === "=" && rest[j + 1] === '"') {
|
|
1339
|
+
const end = rest.indexOf('"', j + 2);
|
|
1340
|
+
j = end < 0 ? rest.length : end + 1;
|
|
1341
|
+
break;
|
|
1230
1342
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1343
|
+
j++;
|
|
1344
|
+
}
|
|
1345
|
+
tokens.push(rest.slice(i, j));
|
|
1346
|
+
i = j;
|
|
1347
|
+
}
|
|
1348
|
+
for (const tok of tokens) {
|
|
1349
|
+
if (!tok) continue;
|
|
1350
|
+
if (DIRECTIONS.has(tok.toLowerCase())) {
|
|
1351
|
+
out.direction = tok.toLowerCase();
|
|
1352
|
+
continue;
|
|
1353
|
+
}
|
|
1354
|
+
const eq = tok.indexOf("=");
|
|
1355
|
+
if (eq > 0) {
|
|
1356
|
+
const key = tok.slice(0, eq).trim();
|
|
1357
|
+
let val = tok.slice(eq + 1).trim();
|
|
1358
|
+
if (val.startsWith('"') && val.endsWith('"')) {
|
|
1359
|
+
val = val.slice(1, -1);
|
|
1235
1360
|
}
|
|
1236
|
-
|
|
1361
|
+
if (key === "label") out.label = val;
|
|
1362
|
+
else if (key === "value") out.value = val;
|
|
1363
|
+
else if (key === "at") out.at = val;
|
|
1364
|
+
else if (key === "length") out.length = val;
|
|
1365
|
+
else out.attrs[key] = val;
|
|
1366
|
+
continue;
|
|
1237
1367
|
}
|
|
1238
|
-
|
|
1368
|
+
out.attrs[tok] = "true";
|
|
1369
|
+
}
|
|
1370
|
+
return out;
|
|
1239
1371
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
);
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
end: { x: BODY_W, y: 0 }
|
|
1256
|
-
};
|
|
1257
|
-
const leftNames = ["gnd", "trg", "out", "rst"];
|
|
1258
|
-
const rightNames = ["vcc", "dis", "thr", "ctl"];
|
|
1259
|
-
for (let i = 0; i < n; i++) {
|
|
1260
|
-
const y = topY + pitch * (i + 1);
|
|
1261
|
-
anchors[leftNames[i]] = { x: -8, y };
|
|
1262
|
-
anchors[rightNames[i]] = { x: BODY_W + 8, y };
|
|
1372
|
+
function parseCircuit(text2) {
|
|
1373
|
+
const rawLines = text2.split("\n");
|
|
1374
|
+
const firstMeaningful = rawLines.map((l) => l.replace(/#.*$/, "").trim()).find((l) => l.length > 0) ?? "";
|
|
1375
|
+
if (/^circuit\b.*\bnetlist\s*$/i.test(firstMeaningful)) {
|
|
1376
|
+
const netlistTitle = chunkNAGUZFXX_cjs.matchQuotedTitle(firstMeaningful);
|
|
1377
|
+
let headerIdx = -1;
|
|
1378
|
+
for (let i = 0; i < rawLines.length; i++) {
|
|
1379
|
+
const s = rawLines[i].replace(/#.*$/, "").trim();
|
|
1380
|
+
if (s.length > 0) {
|
|
1381
|
+
headerIdx = i;
|
|
1382
|
+
break;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
const body = rawLines.slice(headerIdx + 1).join("\n");
|
|
1386
|
+
return parseNetlist(body, netlistTitle);
|
|
1263
1387
|
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1388
|
+
const lines = text2.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
1389
|
+
let title2;
|
|
1390
|
+
const components = [];
|
|
1391
|
+
const nets = [];
|
|
1392
|
+
const netByName = /* @__PURE__ */ new Map();
|
|
1393
|
+
let autoId = 0;
|
|
1394
|
+
let pendingAt;
|
|
1395
|
+
const mkId = (prefix) => `${prefix}_${autoId++}`;
|
|
1396
|
+
for (const rawLine of lines) {
|
|
1397
|
+
const stripped = rawLine.replace(/#.*$/, "").trim();
|
|
1398
|
+
if (!stripped) continue;
|
|
1399
|
+
if (/^circuit\b/i.test(stripped)) {
|
|
1400
|
+
const t = chunkNAGUZFXX_cjs.matchQuotedTitle(stripped);
|
|
1401
|
+
if (t !== void 0) title2 = t;
|
|
1402
|
+
continue;
|
|
1403
|
+
}
|
|
1404
|
+
const atMatch = stripped.match(/^at:\s*(.+)$/i);
|
|
1405
|
+
if (atMatch) {
|
|
1406
|
+
pendingAt = atMatch[1].trim();
|
|
1407
|
+
continue;
|
|
1408
|
+
}
|
|
1409
|
+
const netDecl = stripped.match(/^net\s+([a-zA-Z_][\w]*)\s*$/i);
|
|
1410
|
+
if (netDecl) {
|
|
1411
|
+
const name = netDecl[1];
|
|
1412
|
+
if (!netByName.has(name)) {
|
|
1413
|
+
const n = { id: name, anchors: [] };
|
|
1414
|
+
netByName.set(name, n);
|
|
1415
|
+
nets.push(n);
|
|
1416
|
+
}
|
|
1417
|
+
continue;
|
|
1418
|
+
}
|
|
1419
|
+
const netDotMatch = stripped.match(/^net\s+([a-zA-Z_][\w]*)\s*:\s*dot\s*$/i);
|
|
1420
|
+
if (netDotMatch) {
|
|
1421
|
+
const name = netDotMatch[1];
|
|
1422
|
+
let n = netByName.get(name);
|
|
1423
|
+
if (!n) {
|
|
1424
|
+
n = { id: name, anchors: [] };
|
|
1425
|
+
netByName.set(name, n);
|
|
1426
|
+
nets.push(n);
|
|
1427
|
+
}
|
|
1428
|
+
const id = mkId("dot");
|
|
1429
|
+
components.push({
|
|
1430
|
+
id,
|
|
1431
|
+
componentType: "dot",
|
|
1432
|
+
direction: "right",
|
|
1433
|
+
at: pendingAt,
|
|
1434
|
+
attrs: { net: name }
|
|
1435
|
+
});
|
|
1436
|
+
n.anchors.push(`${id}.end`);
|
|
1437
|
+
pendingAt = `${id}.end`;
|
|
1438
|
+
continue;
|
|
1315
1439
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1440
|
+
const labelMatch = stripped.match(/^label\s+"([^"]*)"(?:\s+(right|left|up|down))?\s*$/i);
|
|
1441
|
+
if (labelMatch) {
|
|
1442
|
+
const id = mkId("lbl");
|
|
1443
|
+
components.push({
|
|
1444
|
+
id,
|
|
1445
|
+
componentType: "label",
|
|
1446
|
+
direction: labelMatch[2]?.toLowerCase() ?? "right",
|
|
1447
|
+
at: pendingAt,
|
|
1448
|
+
label: labelMatch[1]
|
|
1449
|
+
});
|
|
1450
|
+
continue;
|
|
1451
|
+
}
|
|
1452
|
+
const wireMatch = stripped.match(/^wire(?:\s+(right|left|up|down))?(?:\s+(\d+)(?:px)?)?\s*$/i);
|
|
1453
|
+
if (wireMatch) {
|
|
1454
|
+
const id = mkId("w");
|
|
1455
|
+
components.push({
|
|
1456
|
+
id,
|
|
1457
|
+
componentType: "wire",
|
|
1458
|
+
direction: wireMatch[1]?.toLowerCase() ?? "right",
|
|
1459
|
+
at: pendingAt,
|
|
1460
|
+
attrs: wireMatch[2] ? { length: wireMatch[2] } : {}
|
|
1461
|
+
});
|
|
1462
|
+
pendingAt = `${id}.end`;
|
|
1463
|
+
continue;
|
|
1464
|
+
}
|
|
1465
|
+
const bareMatch = stripped.match(/^([a-zA-Z_][\w]*)(\s+.*)?$/);
|
|
1466
|
+
const colonMatch = stripped.match(/^([a-zA-Z_][\w]*)\s*:\s*([a-zA-Z_][\w]*)(\s+.*)?$/);
|
|
1467
|
+
if (colonMatch) {
|
|
1468
|
+
const id = colonMatch[1];
|
|
1469
|
+
const typeStr = colonMatch[2];
|
|
1470
|
+
const norm = normalizeType(typeStr);
|
|
1471
|
+
if (!norm) {
|
|
1472
|
+
throw new CircuitParseError(`Unknown component type: ${typeStr}`);
|
|
1473
|
+
}
|
|
1474
|
+
const rest = colonMatch[3] ?? "";
|
|
1475
|
+
const parsed = parseAttrs(rest);
|
|
1476
|
+
const comp = {
|
|
1477
|
+
id,
|
|
1478
|
+
componentType: norm,
|
|
1479
|
+
direction: parsed.direction ?? "right",
|
|
1480
|
+
at: parsed.at ?? pendingAt,
|
|
1481
|
+
label: parsed.label,
|
|
1482
|
+
value: parsed.value,
|
|
1483
|
+
attrs: parsed.attrs
|
|
1484
|
+
};
|
|
1485
|
+
if (parsed.length) {
|
|
1486
|
+
comp.attrs = { ...comp.attrs, length: parsed.length };
|
|
1487
|
+
}
|
|
1488
|
+
components.push(comp);
|
|
1489
|
+
pendingAt = `${id}.end`;
|
|
1490
|
+
continue;
|
|
1491
|
+
}
|
|
1492
|
+
if (bareMatch) {
|
|
1493
|
+
const typeStr = bareMatch[1];
|
|
1494
|
+
const norm = normalizeType(typeStr);
|
|
1495
|
+
if (!norm) {
|
|
1496
|
+
continue;
|
|
1497
|
+
}
|
|
1498
|
+
const rest = bareMatch[2] ?? "";
|
|
1499
|
+
const parsed = parseAttrs(rest);
|
|
1500
|
+
const id = mkId(norm);
|
|
1501
|
+
const comp = {
|
|
1502
|
+
id,
|
|
1503
|
+
componentType: norm,
|
|
1504
|
+
direction: parsed.direction ?? "right",
|
|
1505
|
+
at: parsed.at ?? pendingAt,
|
|
1506
|
+
label: parsed.label,
|
|
1507
|
+
value: parsed.value,
|
|
1508
|
+
attrs: parsed.attrs
|
|
1509
|
+
};
|
|
1510
|
+
components.push(comp);
|
|
1511
|
+
pendingAt = `${id}.end`;
|
|
1512
|
+
continue;
|
|
1323
1513
|
}
|
|
1324
|
-
return parts.join("");
|
|
1325
1514
|
}
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
// Diagonal slash inside the box = coil winding indicator
|
|
1334
|
-
`<line x1="8" y1="-10" x2="32" y2="10" ${BODY}/>`,
|
|
1335
|
-
lineWire(32, 0, 40, 0)
|
|
1336
|
-
].join("")
|
|
1337
|
-
};
|
|
1338
|
-
var relay_no = {
|
|
1339
|
-
length: 40,
|
|
1340
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
1341
|
-
svg: () => [
|
|
1342
|
-
lineWire(0, 0, 10, 0),
|
|
1343
|
-
`<line x1="10" y1="0" x2="30" y2="-10" ${BODY}/>`,
|
|
1344
|
-
`<circle cx="10" cy="0" r="2" ${FILL}/>`,
|
|
1345
|
-
`<circle cx="30" cy="0" r="2" ${FILL}/>`,
|
|
1346
|
-
// Small dashed bar above to denote actuator-driven (vs hand switch)
|
|
1347
|
-
`<line x1="14" y1="-14" x2="26" y2="-14" stroke-dasharray="2,2" ${BODY}/>`,
|
|
1348
|
-
lineWire(30, 0, 40, 0)
|
|
1349
|
-
].join("")
|
|
1350
|
-
};
|
|
1351
|
-
var relay_nc = {
|
|
1352
|
-
length: 40,
|
|
1353
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
1354
|
-
svg: () => [
|
|
1355
|
-
lineWire(0, 0, 10, 0),
|
|
1356
|
-
`<line x1="10" y1="-10" x2="30" y2="-10" ${BODY}/>`,
|
|
1357
|
-
// NC slash: line crosses both contact endpoints (closed by default)
|
|
1358
|
-
`<line x1="8" y1="2" x2="32" y2="-12" ${BODY}/>`,
|
|
1359
|
-
`<circle cx="10" cy="0" r="2" ${FILL}/>`,
|
|
1360
|
-
`<circle cx="30" cy="0" r="2" ${FILL}/>`,
|
|
1361
|
-
`<line x1="14" y1="-14" x2="26" y2="-14" stroke-dasharray="2,2" ${BODY}/>`,
|
|
1362
|
-
lineWire(30, 0, 40, 0)
|
|
1363
|
-
].join("")
|
|
1364
|
-
};
|
|
1365
|
-
var contactor = {
|
|
1366
|
-
length: 44,
|
|
1367
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 44, y: 0 } },
|
|
1368
|
-
svg: () => [
|
|
1369
|
-
lineWire(0, 0, 10, 0),
|
|
1370
|
-
// Two parallel diagonal contacts = double-break (typical of contactors)
|
|
1371
|
-
`<line x1="10" y1="0" x2="30" y2="-10" stroke-width="2.5" ${BODY}/>`,
|
|
1372
|
-
`<line x1="14" y1="2" x2="34" y2="-8" stroke-width="2.5" ${BODY}/>`,
|
|
1373
|
-
`<circle cx="10" cy="0" r="2" ${FILL}/>`,
|
|
1374
|
-
`<circle cx="34" cy="0" r="2" ${FILL}/>`,
|
|
1375
|
-
// Solid bar above = electromagnetic-driven actuator
|
|
1376
|
-
`<line x1="14" y1="-14" x2="30" y2="-14" stroke-width="2" ${BODY}/>`,
|
|
1377
|
-
lineWire(34, 0, 44, 0)
|
|
1378
|
-
].join("")
|
|
1379
|
-
};
|
|
1380
|
-
var solenoid_valve = {
|
|
1381
|
-
length: 50,
|
|
1382
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 50, y: 0 } },
|
|
1383
|
-
svg: () => [
|
|
1384
|
-
lineWire(0, 0, 8, 0),
|
|
1385
|
-
// Solenoid box on top
|
|
1386
|
-
`<rect x="8" y="-22" width="14" height="12" fill="white" ${BODY}/>`,
|
|
1387
|
-
`<line x1="8" y1="-22" x2="22" y2="-10" ${BODY}/>`,
|
|
1388
|
-
// Valve body (triangle pair = IEC valve symbol)
|
|
1389
|
-
`<polygon points="22,0 38,-8 38,8" fill="white" ${BODY}/>`,
|
|
1390
|
-
`<polygon points="22,0 8,-8 8,8" fill="white" ${BODY}/>`,
|
|
1391
|
-
// Connect solenoid to valve body (actuator line)
|
|
1392
|
-
`<line x1="15" y1="-10" x2="22" y2="0" ${BODY}/>`,
|
|
1393
|
-
lineWire(38, 0, 50, 0)
|
|
1394
|
-
].join("")
|
|
1395
|
-
};
|
|
1396
|
-
var thermal_overload = {
|
|
1397
|
-
length: 40,
|
|
1398
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 40, y: 0 } },
|
|
1399
|
-
svg: () => [
|
|
1400
|
-
lineWire(0, 0, 8, 0),
|
|
1401
|
-
`<rect x="8" y="-12" width="24" height="24" fill="white" ${BODY}/>`,
|
|
1402
|
-
// Bimetal element: bent line inside box
|
|
1403
|
-
`<path d="M 12,-6 L 16,4 L 20,-6 L 24,4 L 28,-6" fill="none" ${BODY}/>`,
|
|
1404
|
-
lineWire(32, 0, 40, 0)
|
|
1405
|
-
].join("")
|
|
1406
|
-
};
|
|
1407
|
-
var disconnect_switch = {
|
|
1408
|
-
length: 48,
|
|
1409
|
-
anchors: { start: { x: 0, y: 0 }, end: { x: 48, y: 0 } },
|
|
1410
|
-
svg: () => [
|
|
1411
|
-
lineWire(0, 0, 10, 0),
|
|
1412
|
-
`<line x1="10" y1="0" x2="34" y2="-12" ${BODY}/>`,
|
|
1413
|
-
`<circle cx="10" cy="0" r="2" ${FILL}/>`,
|
|
1414
|
-
// Hollow square at top of arm = visible-isolation indicator
|
|
1415
|
-
`<rect x="30" y="-16" width="8" height="8" fill="white" ${BODY}/>`,
|
|
1416
|
-
`<circle cx="38" cy="0" r="2" ${FILL}/>`,
|
|
1417
|
-
lineWire(38, 0, 48, 0)
|
|
1418
|
-
].join("")
|
|
1419
|
-
};
|
|
1420
|
-
var SYMBOLS = {
|
|
1421
|
-
resistor,
|
|
1422
|
-
capacitor,
|
|
1423
|
-
electrolytic_cap,
|
|
1424
|
-
inductor,
|
|
1425
|
-
fuse,
|
|
1426
|
-
crystal,
|
|
1427
|
-
transformer,
|
|
1428
|
-
voltage_source,
|
|
1429
|
-
current_source,
|
|
1430
|
-
ac_source,
|
|
1431
|
-
battery,
|
|
1432
|
-
ground,
|
|
1433
|
-
gnd_signal,
|
|
1434
|
-
vcc,
|
|
1435
|
-
diode,
|
|
1436
|
-
zener,
|
|
1437
|
-
schottky,
|
|
1438
|
-
led,
|
|
1439
|
-
photodiode,
|
|
1440
|
-
npn,
|
|
1441
|
-
pnp,
|
|
1442
|
-
nmos,
|
|
1443
|
-
pmos,
|
|
1444
|
-
jfet_n,
|
|
1445
|
-
jfet_p,
|
|
1446
|
-
opamp,
|
|
1447
|
-
comparator,
|
|
1448
|
-
switch_spst,
|
|
1449
|
-
push_no,
|
|
1450
|
-
ammeter,
|
|
1451
|
-
voltmeter,
|
|
1452
|
-
wattmeter,
|
|
1453
|
-
motor,
|
|
1454
|
-
speaker,
|
|
1455
|
-
microphone,
|
|
1456
|
-
buzzer,
|
|
1457
|
-
potentiometer,
|
|
1458
|
-
rheostat,
|
|
1459
|
-
thermistor_ntc,
|
|
1460
|
-
thermistor_ptc,
|
|
1461
|
-
ldr,
|
|
1462
|
-
variable_cap,
|
|
1463
|
-
variable_inductor,
|
|
1464
|
-
switch_spdt,
|
|
1465
|
-
push_nc,
|
|
1466
|
-
gnd_chassis,
|
|
1467
|
-
gnd_digital,
|
|
1468
|
-
test_point,
|
|
1469
|
-
no_connect,
|
|
1470
|
-
antenna,
|
|
1471
|
-
generic_ic,
|
|
1472
|
-
terminal_block,
|
|
1473
|
-
"555_timer": timer_555,
|
|
1474
|
-
voltage_regulator,
|
|
1475
|
-
// Industrial control / power electrical (IEC 60617)
|
|
1476
|
-
relay_coil,
|
|
1477
|
-
relay_no,
|
|
1478
|
-
relay_nc,
|
|
1479
|
-
contactor,
|
|
1480
|
-
solenoid_valve,
|
|
1481
|
-
thermal_overload,
|
|
1482
|
-
disconnect_switch
|
|
1483
|
-
// Lamp reuses buzzer slot? No, needs its own entry but our CircuitComponentType
|
|
1484
|
-
// doesn't have "lamp". We map it via parser alias to "buzzer" or add specifically.
|
|
1485
|
-
};
|
|
1486
|
-
var EXTRA_SYMBOLS = {
|
|
1487
|
-
lamp
|
|
1488
|
-
};
|
|
1489
|
-
function getSymbol(t) {
|
|
1490
|
-
return SYMBOLS[t] ?? EXTRA_SYMBOLS[t];
|
|
1515
|
+
return {
|
|
1516
|
+
type: "circuit",
|
|
1517
|
+
title: title2,
|
|
1518
|
+
components,
|
|
1519
|
+
nets,
|
|
1520
|
+
mode: "positional"
|
|
1521
|
+
};
|
|
1491
1522
|
}
|
|
1492
1523
|
|
|
1493
1524
|
// src/diagrams/circuit/layout.ts
|
|
@@ -1949,7 +1980,7 @@ function renderCircuit(ast, config) {
|
|
|
1949
1980
|
const isNetlist = ast.mode === "netlist";
|
|
1950
1981
|
const layout = isNetlist ? layoutCircuitNetlist(ast) : layoutCircuit(ast);
|
|
1951
1982
|
const { width, height, offsetX, offsetY } = layout;
|
|
1952
|
-
const t =
|
|
1983
|
+
const t = chunkL7POWM5B_cjs.resolveIndustrialTheme(config?.theme ?? "default");
|
|
1953
1984
|
const routeSvg = (layout.routes ?? []).map((r) => renderRoute(r, offsetX, offsetY)).join("");
|
|
1954
1985
|
const items = layout.items.map((it) => renderItem(it, offsetX, offsetY)).join("");
|
|
1955
1986
|
const css = `
|
|
@@ -2011,11 +2042,13 @@ var circuit = {
|
|
|
2011
2042
|
}
|
|
2012
2043
|
};
|
|
2013
2044
|
|
|
2045
|
+
exports.EXTRA_SYMBOLS = EXTRA_SYMBOLS;
|
|
2046
|
+
exports.SYMBOLS = SYMBOLS;
|
|
2014
2047
|
exports.circuit = circuit;
|
|
2015
2048
|
exports.layoutCircuit = layoutCircuit;
|
|
2016
2049
|
exports.layoutCircuitNetlist = layoutCircuitNetlist;
|
|
2017
2050
|
exports.parseCircuit = parseCircuit;
|
|
2018
2051
|
exports.parseNetlist = parseNetlist;
|
|
2019
2052
|
exports.renderCircuit = renderCircuit;
|
|
2020
|
-
//# sourceMappingURL=chunk-
|
|
2021
|
-
//# sourceMappingURL=chunk-
|
|
2053
|
+
//# sourceMappingURL=chunk-V4RO5KYY.cjs.map
|
|
2054
|
+
//# sourceMappingURL=chunk-V4RO5KYY.cjs.map
|