@tscircuit/circuit-json-util 0.0.41
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/LICENSE +21 -0
- package/README.md +64 -0
- package/dist/index.cjs +636 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2368 -0
- package/dist/index.d.ts +2413 -0
- package/dist/index.js +1286 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// index.ts
|
|
31
|
+
var soup_util_exports = {};
|
|
32
|
+
__export(soup_util_exports, {
|
|
33
|
+
applySelector: () => applySelector,
|
|
34
|
+
applySelectorAST: () => applySelectorAST,
|
|
35
|
+
directionToVec: () => directionToVec,
|
|
36
|
+
getBoundsOfPcbElements: () => getBoundsOfPcbElements,
|
|
37
|
+
getElementById: () => getElementById,
|
|
38
|
+
getElementId: () => getElementId,
|
|
39
|
+
getReadableNameForElement: () => getReadableNameForElement,
|
|
40
|
+
getReadableNameForPcbPort: () => getReadableNameForPcbPort,
|
|
41
|
+
getReadableNameForPcbSmtpad: () => getReadableNameForPcbSmtpad,
|
|
42
|
+
getReadableNameForPcbTrace: () => getReadableNameForPcbTrace,
|
|
43
|
+
oppositeDirection: () => oppositeDirection,
|
|
44
|
+
oppositeSide: () => oppositeSide,
|
|
45
|
+
rotateClockwise: () => rotateClockwise,
|
|
46
|
+
rotateCounterClockwise: () => rotateCounterClockwise,
|
|
47
|
+
rotateDirection: () => rotateDirection,
|
|
48
|
+
su: () => su_default,
|
|
49
|
+
transformPCBElement: () => transformPCBElement,
|
|
50
|
+
transformPCBElements: () => transformPCBElements,
|
|
51
|
+
transformSchematicElement: () => transformSchematicElement,
|
|
52
|
+
transformSchematicElements: () => transformSchematicElements,
|
|
53
|
+
vecToDirection: () => vecToDirection
|
|
54
|
+
});
|
|
55
|
+
module.exports = __toCommonJS(soup_util_exports);
|
|
56
|
+
|
|
57
|
+
// lib/su.ts
|
|
58
|
+
var Soup = __toESM(require("@tscircuit/soup"), 1);
|
|
59
|
+
var su = (soup, options = {}) => {
|
|
60
|
+
let internalStore = soup._internal_store;
|
|
61
|
+
if (!internalStore) {
|
|
62
|
+
internalStore = {
|
|
63
|
+
counts: {}
|
|
64
|
+
};
|
|
65
|
+
soup._internal_store = internalStore;
|
|
66
|
+
for (const elm of soup) {
|
|
67
|
+
const type = elm.type;
|
|
68
|
+
const idVal = elm[`${type}_id`];
|
|
69
|
+
if (!idVal)
|
|
70
|
+
continue;
|
|
71
|
+
const idNum = Number.parseInt(idVal.split("_").pop());
|
|
72
|
+
if (!Number.isNaN(idNum)) {
|
|
73
|
+
internalStore.counts[type] = Math.max(
|
|
74
|
+
internalStore.counts[type] ?? 0,
|
|
75
|
+
idNum
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const su2 = new Proxy(
|
|
81
|
+
{},
|
|
82
|
+
{
|
|
83
|
+
get: (proxy_target, component_type) => {
|
|
84
|
+
if (component_type === "toArray") {
|
|
85
|
+
return () => soup;
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
get: (id) => soup.find(
|
|
89
|
+
(e) => e.type === component_type && e[`${component_type}_id`] === id
|
|
90
|
+
),
|
|
91
|
+
getUsing: (using) => {
|
|
92
|
+
const keys = Object.keys(using);
|
|
93
|
+
if (keys.length !== 1) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
"getUsing requires exactly one key, e.g. { pcb_component_id }"
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
const join_key = keys[0];
|
|
99
|
+
const join_type = join_key.replace("_id", "");
|
|
100
|
+
const joiner = soup.find(
|
|
101
|
+
(e) => e.type === join_type && e[join_key] === using[join_key]
|
|
102
|
+
);
|
|
103
|
+
if (!joiner)
|
|
104
|
+
return null;
|
|
105
|
+
return soup.find(
|
|
106
|
+
(e) => e.type === component_type && e[`${component_type}_id`] === joiner[`${component_type}_id`]
|
|
107
|
+
);
|
|
108
|
+
},
|
|
109
|
+
getWhere: (where) => {
|
|
110
|
+
const keys = Object.keys(where);
|
|
111
|
+
return soup.find(
|
|
112
|
+
(e) => e.type === component_type && keys.every((key) => e[key] === where[key])
|
|
113
|
+
);
|
|
114
|
+
},
|
|
115
|
+
list: (where) => {
|
|
116
|
+
const keys = !where ? [] : Object.keys(where);
|
|
117
|
+
return soup.filter(
|
|
118
|
+
(e) => e.type === component_type && keys.every((key) => e[key] === where[key])
|
|
119
|
+
);
|
|
120
|
+
},
|
|
121
|
+
insert: (elm) => {
|
|
122
|
+
internalStore.counts[component_type] ??= -1;
|
|
123
|
+
internalStore.counts[component_type]++;
|
|
124
|
+
const index = internalStore.counts[component_type];
|
|
125
|
+
const newElm = {
|
|
126
|
+
type: component_type,
|
|
127
|
+
[`${component_type}_id`]: `${component_type}_${index}`,
|
|
128
|
+
...elm
|
|
129
|
+
};
|
|
130
|
+
if (options.validateInserts) {
|
|
131
|
+
const parser = Soup[component_type] ?? Soup.any_soup_element;
|
|
132
|
+
parser.parse(newElm);
|
|
133
|
+
}
|
|
134
|
+
soup.push(newElm);
|
|
135
|
+
return newElm;
|
|
136
|
+
},
|
|
137
|
+
delete: (id) => {
|
|
138
|
+
const elm = soup.find(
|
|
139
|
+
(e) => e[`${component_type}_id`] === id
|
|
140
|
+
);
|
|
141
|
+
if (!elm)
|
|
142
|
+
return;
|
|
143
|
+
soup.splice(soup.indexOf(elm), 1);
|
|
144
|
+
},
|
|
145
|
+
update: (id, newProps) => {
|
|
146
|
+
const elm = soup.find(
|
|
147
|
+
(e) => e[`${component_type}_id`] === id
|
|
148
|
+
);
|
|
149
|
+
if (!elm)
|
|
150
|
+
return;
|
|
151
|
+
Object.assign(elm, newProps);
|
|
152
|
+
return elm;
|
|
153
|
+
},
|
|
154
|
+
select: (selector) => {
|
|
155
|
+
if (component_type === "source_component") {
|
|
156
|
+
return soup.find(
|
|
157
|
+
(e) => e.type === "source_component" && e.name === selector.replace(/\./g, "")
|
|
158
|
+
);
|
|
159
|
+
} else if (component_type === "pcb_port" || component_type === "source_port" || component_type === "schematic_port") {
|
|
160
|
+
const [component_name, port_selector] = selector.replace(/\./g, "").split(/[\s\>]+/);
|
|
161
|
+
const source_component = soup.find(
|
|
162
|
+
(e) => e.type === "source_component" && e.name === component_name
|
|
163
|
+
);
|
|
164
|
+
if (!source_component)
|
|
165
|
+
return null;
|
|
166
|
+
const source_port = soup.find(
|
|
167
|
+
(e) => e.type === "source_port" && e.source_component_id === source_component.source_component_id && (e.name === port_selector || (e.port_hints ?? []).includes(port_selector))
|
|
168
|
+
);
|
|
169
|
+
if (!source_port)
|
|
170
|
+
return null;
|
|
171
|
+
if (component_type === "source_port")
|
|
172
|
+
return source_port;
|
|
173
|
+
if (component_type === "pcb_port") {
|
|
174
|
+
return soup.find(
|
|
175
|
+
(e) => e.type === "pcb_port" && e.source_port_id === source_port.source_port_id
|
|
176
|
+
);
|
|
177
|
+
} else if (component_type === "schematic_port") {
|
|
178
|
+
return soup.find(
|
|
179
|
+
(e) => e.type === "schematic_port" && e.source_port_id === source_port.source_port_id
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
return su2;
|
|
189
|
+
};
|
|
190
|
+
su.unparsed = su;
|
|
191
|
+
var su_default = su;
|
|
192
|
+
|
|
193
|
+
// lib/transform-soup-elements.ts
|
|
194
|
+
var import_transformation_matrix = require("transformation-matrix");
|
|
195
|
+
|
|
196
|
+
// lib/direction-to-vec.ts
|
|
197
|
+
var directionToVec = (direction) => {
|
|
198
|
+
if (direction === "up")
|
|
199
|
+
return { x: 0, y: 1 };
|
|
200
|
+
else if (direction === "down")
|
|
201
|
+
return { x: 0, y: -1 };
|
|
202
|
+
else if (direction === "left")
|
|
203
|
+
return { x: -1, y: 0 };
|
|
204
|
+
else if (direction === "right")
|
|
205
|
+
return { x: 1, y: 0 };
|
|
206
|
+
else
|
|
207
|
+
throw new Error("Invalid direction");
|
|
208
|
+
};
|
|
209
|
+
var vecToDirection = ({ x, y }) => {
|
|
210
|
+
if (x > y)
|
|
211
|
+
y = 0;
|
|
212
|
+
if (y > x)
|
|
213
|
+
x = 0;
|
|
214
|
+
if (x > 0 && y === 0)
|
|
215
|
+
return "right";
|
|
216
|
+
else if (x < 0 && y === 0)
|
|
217
|
+
return "left";
|
|
218
|
+
else if (x === 0 && y > 0)
|
|
219
|
+
return "up";
|
|
220
|
+
else if (x === 0 && y < 0)
|
|
221
|
+
return "down";
|
|
222
|
+
else
|
|
223
|
+
throw new Error(`Invalid vector for direction conversion (${x}, ${y})`);
|
|
224
|
+
};
|
|
225
|
+
var rotateClockwise = (direction) => {
|
|
226
|
+
if (direction === "up")
|
|
227
|
+
return "right";
|
|
228
|
+
else if (direction === "right")
|
|
229
|
+
return "down";
|
|
230
|
+
else if (direction === "down")
|
|
231
|
+
return "left";
|
|
232
|
+
else if (direction === "left")
|
|
233
|
+
return "up";
|
|
234
|
+
throw new Error(`Invalid direction: ${direction}`);
|
|
235
|
+
};
|
|
236
|
+
var rotateCounterClockwise = (direction) => {
|
|
237
|
+
if (direction === "up")
|
|
238
|
+
return "left";
|
|
239
|
+
else if (direction === "left")
|
|
240
|
+
return "down";
|
|
241
|
+
else if (direction === "down")
|
|
242
|
+
return "right";
|
|
243
|
+
else if (direction === "right")
|
|
244
|
+
return "up";
|
|
245
|
+
throw new Error(`Invalid direction: ${direction}`);
|
|
246
|
+
};
|
|
247
|
+
var rotateDirection = (direction, num90DegreeClockwiseTurns) => {
|
|
248
|
+
while (num90DegreeClockwiseTurns > 0) {
|
|
249
|
+
direction = rotateClockwise(direction);
|
|
250
|
+
num90DegreeClockwiseTurns--;
|
|
251
|
+
}
|
|
252
|
+
while (num90DegreeClockwiseTurns < 0) {
|
|
253
|
+
direction = rotateCounterClockwise(direction);
|
|
254
|
+
num90DegreeClockwiseTurns++;
|
|
255
|
+
}
|
|
256
|
+
return direction;
|
|
257
|
+
};
|
|
258
|
+
var oppositeDirection = (direction) => {
|
|
259
|
+
if (direction === "up")
|
|
260
|
+
return "down";
|
|
261
|
+
else if (direction === "down")
|
|
262
|
+
return "up";
|
|
263
|
+
else if (direction === "left")
|
|
264
|
+
return "right";
|
|
265
|
+
else if (direction === "right")
|
|
266
|
+
return "left";
|
|
267
|
+
throw new Error(`Invalid direction: ${direction}`);
|
|
268
|
+
};
|
|
269
|
+
var oppositeSide = (sideOrDir) => {
|
|
270
|
+
if (sideOrDir === "top" || sideOrDir === "up")
|
|
271
|
+
return "bottom";
|
|
272
|
+
else if (sideOrDir === "bottom" || sideOrDir === "down")
|
|
273
|
+
return "top";
|
|
274
|
+
else if (sideOrDir === "left")
|
|
275
|
+
return "right";
|
|
276
|
+
else if (sideOrDir === "right")
|
|
277
|
+
return "left";
|
|
278
|
+
throw new Error(`Invalid sideOrDir: ${sideOrDir}`);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// lib/transform-soup-elements.ts
|
|
282
|
+
var transformSchematicElement = (elm, matrix) => {
|
|
283
|
+
if (elm.type === "schematic_component") {
|
|
284
|
+
elm.center = (0, import_transformation_matrix.applyToPoint)(matrix, elm.center);
|
|
285
|
+
} else if (elm.type === "schematic_port") {
|
|
286
|
+
elm.center = (0, import_transformation_matrix.applyToPoint)(matrix, elm.center);
|
|
287
|
+
if (elm.facing_direction) {
|
|
288
|
+
elm.facing_direction = rotateDirection(
|
|
289
|
+
elm.facing_direction,
|
|
290
|
+
-(Math.atan2(matrix.b, matrix.a) / Math.PI) * 2
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
} else if (elm.type === "schematic_text") {
|
|
294
|
+
elm.position = (0, import_transformation_matrix.applyToPoint)(matrix, elm.position);
|
|
295
|
+
} else if (elm.type === "schematic_trace") {
|
|
296
|
+
} else if (elm.type === "schematic_box") {
|
|
297
|
+
const { x, y } = (0, import_transformation_matrix.applyToPoint)(matrix, { x: elm.x, y: elm.y });
|
|
298
|
+
elm.x = x;
|
|
299
|
+
elm.y = y;
|
|
300
|
+
} else if (elm.type === "schematic_line") {
|
|
301
|
+
const { x: x1, y: y1 } = (0, import_transformation_matrix.applyToPoint)(matrix, { x: elm.x1, y: elm.y1 });
|
|
302
|
+
const { x: x2, y: y2 } = (0, import_transformation_matrix.applyToPoint)(matrix, { x: elm.x2, y: elm.y2 });
|
|
303
|
+
elm.x1 = x1;
|
|
304
|
+
elm.y1 = y1;
|
|
305
|
+
elm.x2 = x2;
|
|
306
|
+
elm.y2 = y2;
|
|
307
|
+
}
|
|
308
|
+
return elm;
|
|
309
|
+
};
|
|
310
|
+
var transformSchematicElements = (elms, matrix) => {
|
|
311
|
+
return elms.map((elm) => transformSchematicElement(elm, matrix));
|
|
312
|
+
};
|
|
313
|
+
var transformPCBElement = (elm, matrix) => {
|
|
314
|
+
if (elm.type === "pcb_plated_hole" || elm.type === "pcb_hole" || elm.type === "pcb_via" || elm.type === "pcb_smtpad" || elm.type === "pcb_port") {
|
|
315
|
+
const { x, y } = (0, import_transformation_matrix.applyToPoint)(matrix, { x: elm.x, y: elm.y });
|
|
316
|
+
elm.x = x;
|
|
317
|
+
elm.y = y;
|
|
318
|
+
} else if (elm.type === "pcb_keepout" || elm.type === "pcb_board") {
|
|
319
|
+
elm.center = (0, import_transformation_matrix.applyToPoint)(matrix, elm.center);
|
|
320
|
+
} else if (elm.type === "pcb_silkscreen_text" || elm.type === "pcb_fabrication_note_text") {
|
|
321
|
+
elm.anchor_position = (0, import_transformation_matrix.applyToPoint)(matrix, elm.anchor_position);
|
|
322
|
+
} else if (elm.type === "pcb_silkscreen_circle" || elm.type === "pcb_silkscreen_rect" || elm.type === "pcb_component") {
|
|
323
|
+
elm.center = (0, import_transformation_matrix.applyToPoint)(matrix, elm.center);
|
|
324
|
+
} else if (elm.type === "pcb_silkscreen_path" || elm.type === "pcb_trace" || elm.type === "pcb_fabrication_note_path") {
|
|
325
|
+
elm.route = elm.route.map((rp) => {
|
|
326
|
+
const tp = (0, import_transformation_matrix.applyToPoint)(matrix, rp);
|
|
327
|
+
rp.x = tp.x;
|
|
328
|
+
rp.y = tp.y;
|
|
329
|
+
return rp;
|
|
330
|
+
});
|
|
331
|
+
} else if (elm.type === "pcb_silkscreen_line") {
|
|
332
|
+
const p1 = { x: elm.x1, y: elm.y1 };
|
|
333
|
+
const p2 = { x: elm.x2, y: elm.y2 };
|
|
334
|
+
const p1t = (0, import_transformation_matrix.applyToPoint)(matrix, p1);
|
|
335
|
+
const p2t = (0, import_transformation_matrix.applyToPoint)(matrix, p2);
|
|
336
|
+
elm.x1 = p1t.x;
|
|
337
|
+
elm.y1 = p1t.y;
|
|
338
|
+
elm.x2 = p2t.x;
|
|
339
|
+
elm.y2 = p2t.y;
|
|
340
|
+
} else if (elm.type === "cad_component") {
|
|
341
|
+
const newPos = (0, import_transformation_matrix.applyToPoint)(matrix, {
|
|
342
|
+
x: elm.position.x,
|
|
343
|
+
y: elm.position.y
|
|
344
|
+
});
|
|
345
|
+
elm.position.x = newPos.x;
|
|
346
|
+
elm.position.y = newPos.y;
|
|
347
|
+
}
|
|
348
|
+
return elm;
|
|
349
|
+
};
|
|
350
|
+
var transformPCBElements = (elms, matrix) => {
|
|
351
|
+
const tsr = (0, import_transformation_matrix.decomposeTSR)(matrix);
|
|
352
|
+
const flipPadWidthHeight = Math.round(tsr.rotation.angle / (Math.PI / 2)) % 2 === 1;
|
|
353
|
+
let transformedElms = elms.map((elm) => transformPCBElement(elm, matrix));
|
|
354
|
+
if (flipPadWidthHeight) {
|
|
355
|
+
transformedElms = transformedElms.map((elm) => {
|
|
356
|
+
if (elm.type === "pcb_smtpad" && elm.shape === "rect") {
|
|
357
|
+
;
|
|
358
|
+
[elm.width, elm.height] = [elm.height, elm.width];
|
|
359
|
+
}
|
|
360
|
+
return elm;
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return transformedElms;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
// lib/apply-selector.ts
|
|
367
|
+
var parsel = __toESM(require("parsel-js"), 1);
|
|
368
|
+
|
|
369
|
+
// lib/convert-abbreviation-to-soup-element-type.ts
|
|
370
|
+
var convertAbbrToType = (abbr) => {
|
|
371
|
+
switch (abbr) {
|
|
372
|
+
case "port":
|
|
373
|
+
return "source_port";
|
|
374
|
+
case "net":
|
|
375
|
+
return "source_net";
|
|
376
|
+
case "power":
|
|
377
|
+
return "simple_power_source";
|
|
378
|
+
}
|
|
379
|
+
return abbr;
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// lib/apply-selector.ts
|
|
383
|
+
var filterByType = (elements, type) => {
|
|
384
|
+
type = convertAbbrToType(type);
|
|
385
|
+
return elements.filter(
|
|
386
|
+
(elm) => "ftype" in elm && elm.ftype === type || elm.type === type
|
|
387
|
+
);
|
|
388
|
+
};
|
|
389
|
+
var applySelector = (elements, selectorRaw) => {
|
|
390
|
+
const selectorAST = parsel.parse(selectorRaw);
|
|
391
|
+
return applySelectorAST(elements, selectorAST);
|
|
392
|
+
};
|
|
393
|
+
var doesElmMatchClassName = (elm, className) => "name" in elm && elm.name === className || "port_hints" in elm && elm.port_hints?.includes(className);
|
|
394
|
+
var applySelectorAST = (elements, selectorAST) => {
|
|
395
|
+
switch (selectorAST.type) {
|
|
396
|
+
case "complex": {
|
|
397
|
+
switch (selectorAST.combinator) {
|
|
398
|
+
case " ":
|
|
399
|
+
case ">": {
|
|
400
|
+
const { left, right } = selectorAST;
|
|
401
|
+
if (left.type === "class" || left.type === "type") {
|
|
402
|
+
let matchElms;
|
|
403
|
+
if (left.type === "class") {
|
|
404
|
+
matchElms = elements.filter(
|
|
405
|
+
(elm) => doesElmMatchClassName(elm, left.name)
|
|
406
|
+
);
|
|
407
|
+
} else if (left.type === "type") {
|
|
408
|
+
matchElms = filterByType(elements, left.name);
|
|
409
|
+
} else {
|
|
410
|
+
matchElms = [];
|
|
411
|
+
}
|
|
412
|
+
const childrenOfMatchingElms = matchElms.flatMap(
|
|
413
|
+
(matchElm) => elements.filter(
|
|
414
|
+
(elm) => elm[`${matchElm.type}_id`] === matchElm[`${matchElm.type}_id`] && elm !== matchElm
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
return applySelectorAST(childrenOfMatchingElms, right);
|
|
418
|
+
} else {
|
|
419
|
+
throw new Error(`unsupported selector type "${left.type}" `);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
default: {
|
|
423
|
+
throw new Error(
|
|
424
|
+
`Couldn't apply selector AST for complex combinator "${selectorAST.combinator}"`
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return [];
|
|
429
|
+
}
|
|
430
|
+
case "compound": {
|
|
431
|
+
const conditionsToMatch = selectorAST.list.map((part) => {
|
|
432
|
+
switch (part.type) {
|
|
433
|
+
case "class": {
|
|
434
|
+
return (elm) => doesElmMatchClassName(elm, part.name);
|
|
435
|
+
}
|
|
436
|
+
case "type": {
|
|
437
|
+
const name = convertAbbrToType(part.name);
|
|
438
|
+
return (elm) => elm.type === name;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
return elements.filter(
|
|
443
|
+
(elm) => conditionsToMatch.every((condFn) => condFn?.(elm))
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
case "type": {
|
|
447
|
+
return filterByType(elements, selectorAST.name);
|
|
448
|
+
}
|
|
449
|
+
case "class": {
|
|
450
|
+
return elements.filter(
|
|
451
|
+
(elm) => doesElmMatchClassName(elm, selectorAST.name)
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
default: {
|
|
455
|
+
throw new Error(
|
|
456
|
+
`Couldn't apply selector AST for type: "${selectorAST.type}" ${JSON.stringify(selectorAST, null, " ")}`
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
// lib/get-element-id.ts
|
|
463
|
+
var getElementId = (elm) => {
|
|
464
|
+
const type = elm.type;
|
|
465
|
+
const id = elm[`${type}_id`];
|
|
466
|
+
return id;
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
// lib/get-element-by-id.ts
|
|
470
|
+
var getElementById = (soup, id) => {
|
|
471
|
+
return soup.find((elm) => getElementId(elm) === id) ?? null;
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
// lib/readable-name-functions/get-readable-name-for-pcb-trace.ts
|
|
475
|
+
function getReadableNameForPcbTrace(soup, pcb_trace_id) {
|
|
476
|
+
const pcbTrace = su(soup).pcb_trace.get(pcb_trace_id);
|
|
477
|
+
if (!pcbTrace) {
|
|
478
|
+
return `trace[${pcb_trace_id}]`;
|
|
479
|
+
}
|
|
480
|
+
const connectedPcbPortIds = pcbTrace.route.flatMap((point) => [point.start_pcb_port_id, point.end_pcb_port_id]).filter(Boolean);
|
|
481
|
+
if (connectedPcbPortIds.length === 0) {
|
|
482
|
+
return `trace[${pcb_trace_id}]`;
|
|
483
|
+
}
|
|
484
|
+
function getComponentAndPortInfo(pcb_port_id) {
|
|
485
|
+
const pcbPort = su(soup).pcb_port.get(pcb_port_id);
|
|
486
|
+
if (!pcbPort)
|
|
487
|
+
return null;
|
|
488
|
+
const pcbComponent = su(soup).pcb_component.get(pcbPort.pcb_component_id);
|
|
489
|
+
if (!pcbComponent)
|
|
490
|
+
return null;
|
|
491
|
+
const sourceComponent = su(soup).source_component.get(
|
|
492
|
+
pcbComponent.source_component_id
|
|
493
|
+
);
|
|
494
|
+
if (!sourceComponent)
|
|
495
|
+
return null;
|
|
496
|
+
const sourcePort = su(soup).source_port.get(pcbPort.source_port_id);
|
|
497
|
+
const portHint = sourcePort?.port_hints ? sourcePort.port_hints[1] : "";
|
|
498
|
+
return {
|
|
499
|
+
componentName: sourceComponent.name,
|
|
500
|
+
portHint
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
const selectorParts = connectedPcbPortIds.map((portId) => {
|
|
504
|
+
const info = getComponentAndPortInfo(portId);
|
|
505
|
+
if (info) {
|
|
506
|
+
return `.${info.componentName} > port.${info.portHint}`;
|
|
507
|
+
}
|
|
508
|
+
return `port[${portId}]`;
|
|
509
|
+
});
|
|
510
|
+
return `trace[${selectorParts.join(", ")}]`;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// lib/readable-name-functions/get-readable-name-for-pcb-port.ts
|
|
514
|
+
var getReadableNameForPcbPort = (soup, pcb_port_id) => {
|
|
515
|
+
const pcbPort = su(soup).pcb_port.get(pcb_port_id);
|
|
516
|
+
if (!pcbPort) {
|
|
517
|
+
return `pcb_port[#${pcb_port_id}]`;
|
|
518
|
+
}
|
|
519
|
+
const pcbComponent = su(soup).pcb_component.get(pcbPort?.pcb_component_id);
|
|
520
|
+
if (!pcbComponent) {
|
|
521
|
+
return `pcb_port[#${pcb_port_id}]`;
|
|
522
|
+
}
|
|
523
|
+
const sourceComponent = su(soup).source_component.get(
|
|
524
|
+
pcbComponent.source_component_id
|
|
525
|
+
);
|
|
526
|
+
if (!sourceComponent) {
|
|
527
|
+
return `pcb_port[#${pcb_port_id}]`;
|
|
528
|
+
}
|
|
529
|
+
const sourcePort = su(soup).source_port.get(pcbPort.source_port_id);
|
|
530
|
+
if (!sourcePort) {
|
|
531
|
+
return `pcb_port[#${pcb_port_id}]`;
|
|
532
|
+
}
|
|
533
|
+
let padIdentifier;
|
|
534
|
+
if (sourcePort?.port_hints && sourcePort.port_hints.length > 0) {
|
|
535
|
+
padIdentifier = sourcePort.port_hints[0];
|
|
536
|
+
} else if (sourcePort.port_hints && sourcePort.port_hints.length > 0) {
|
|
537
|
+
padIdentifier = sourcePort.port_hints[0];
|
|
538
|
+
} else {
|
|
539
|
+
padIdentifier = pcb_port_id;
|
|
540
|
+
}
|
|
541
|
+
return `pcb_port[.${sourceComponent.name} > .${padIdentifier}]`;
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// lib/readable-name-functions/get-readable-name-for-pcb-smtpad.ts
|
|
545
|
+
function getReadableNameForPcbSmtpad(soup, pcb_smtpad_id) {
|
|
546
|
+
const pcbSmtpad = su(soup).pcb_smtpad.get(pcb_smtpad_id);
|
|
547
|
+
if (!pcbSmtpad || !pcbSmtpad.pcb_port_id) {
|
|
548
|
+
return `smtpad[${pcb_smtpad_id}]`;
|
|
549
|
+
}
|
|
550
|
+
return getReadableNameForPcbPort(soup, pcbSmtpad.pcb_port_id);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// lib/readable-name-functions/get-readable-name-for-element.ts
|
|
554
|
+
var getReadableNameForElement = (soup, elm) => {
|
|
555
|
+
if (typeof elm === "string") {
|
|
556
|
+
const elmObj = getElementById(soup, elm);
|
|
557
|
+
if (!elmObj)
|
|
558
|
+
`unknown (could not find element with id ${elm})`;
|
|
559
|
+
return getReadableNameForElement(soup, elmObj);
|
|
560
|
+
}
|
|
561
|
+
switch (elm.type) {
|
|
562
|
+
case "pcb_port":
|
|
563
|
+
return getReadableNameForPcbPort(soup, elm.pcb_port_id);
|
|
564
|
+
case "pcb_smtpad":
|
|
565
|
+
return getReadableNameForPcbSmtpad(soup, elm.pcb_smtpad_id);
|
|
566
|
+
case "pcb_trace":
|
|
567
|
+
return getReadableNameForPcbTrace(soup, elm.pcb_trace_id);
|
|
568
|
+
case "source_component":
|
|
569
|
+
return `source_component[${elm.name}]`;
|
|
570
|
+
default:
|
|
571
|
+
return `${elm.type}[#${getElementId(elm)}]`;
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
// lib/get-bounds-of-pcb-elements.ts
|
|
576
|
+
var getBoundsOfPcbElements = (elements) => {
|
|
577
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
578
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
579
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
580
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
581
|
+
for (const elm of elements) {
|
|
582
|
+
if (!elm.type.startsWith("pcb_"))
|
|
583
|
+
continue;
|
|
584
|
+
if ("x" in elm && "y" in elm) {
|
|
585
|
+
minX = Math.min(minX, elm.x);
|
|
586
|
+
minY = Math.min(minY, elm.y);
|
|
587
|
+
maxX = Math.max(maxX, elm.x);
|
|
588
|
+
maxY = Math.max(maxY, elm.y);
|
|
589
|
+
if ("width" in elm) {
|
|
590
|
+
maxX = Math.max(maxX, elm.x + elm.width);
|
|
591
|
+
}
|
|
592
|
+
if ("height" in elm) {
|
|
593
|
+
maxY = Math.max(maxY, elm.y + elm.height);
|
|
594
|
+
}
|
|
595
|
+
if ("radius" in elm) {
|
|
596
|
+
minX = Math.min(minX, elm.x - elm.radius);
|
|
597
|
+
minY = Math.min(minY, elm.y - elm.radius);
|
|
598
|
+
maxX = Math.max(maxX, elm.x + elm.radius);
|
|
599
|
+
maxY = Math.max(maxY, elm.y + elm.radius);
|
|
600
|
+
}
|
|
601
|
+
} else if (elm.type === "pcb_trace") {
|
|
602
|
+
for (const point of elm.route) {
|
|
603
|
+
minX = Math.min(minX, point.x);
|
|
604
|
+
minY = Math.min(minY, point.y);
|
|
605
|
+
maxX = Math.max(maxX, point.x);
|
|
606
|
+
maxY = Math.max(maxY, point.y);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return { minX, minY, maxX, maxY };
|
|
611
|
+
};
|
|
612
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
613
|
+
0 && (module.exports = {
|
|
614
|
+
applySelector,
|
|
615
|
+
applySelectorAST,
|
|
616
|
+
directionToVec,
|
|
617
|
+
getBoundsOfPcbElements,
|
|
618
|
+
getElementById,
|
|
619
|
+
getElementId,
|
|
620
|
+
getReadableNameForElement,
|
|
621
|
+
getReadableNameForPcbPort,
|
|
622
|
+
getReadableNameForPcbSmtpad,
|
|
623
|
+
getReadableNameForPcbTrace,
|
|
624
|
+
oppositeDirection,
|
|
625
|
+
oppositeSide,
|
|
626
|
+
rotateClockwise,
|
|
627
|
+
rotateCounterClockwise,
|
|
628
|
+
rotateDirection,
|
|
629
|
+
su,
|
|
630
|
+
transformPCBElement,
|
|
631
|
+
transformPCBElements,
|
|
632
|
+
transformSchematicElement,
|
|
633
|
+
transformSchematicElements,
|
|
634
|
+
vecToDirection
|
|
635
|
+
});
|
|
636
|
+
//# sourceMappingURL=index.cjs.map
|