circuit-json-to-tscircuit 0.0.38 → 0.0.40
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/dist/{chunk-G5NSFWRY.js → chunk-UHPKLBYL.js} +123 -120
- package/dist/cli/main.js +2 -2
- package/dist/lib/index.js +1 -1
- package/lib/get-board-using-template.ts +3 -2
- package/package.json +1 -1
- package/tests/__snapshots__/test20-board-conversion-drops-children-pcb.snap.svg +1 -0
- package/tests/test20-board-conversion-drops-children.test.tsx +81 -0
|
@@ -1,65 +1,17 @@
|
|
|
1
1
|
// lib/get-board-using-template.ts
|
|
2
|
-
import { mmStr } from "@tscircuit/mm";
|
|
3
|
-
import { su } from "@tscircuit/soup-util";
|
|
4
|
-
var getBoardUsingTemplate = ({ circuitJson }) => {
|
|
5
|
-
const pcbBoard = su(circuitJson).pcb_board.list()[0];
|
|
6
|
-
const boardProps = [];
|
|
7
|
-
if (pcbBoard) {
|
|
8
|
-
if (pcbBoard.width !== void 0) {
|
|
9
|
-
boardProps.push(`width="${mmStr(pcbBoard.width)}"`);
|
|
10
|
-
}
|
|
11
|
-
if (pcbBoard.height !== void 0) {
|
|
12
|
-
boardProps.push(`height="${mmStr(pcbBoard.height)}"`);
|
|
13
|
-
}
|
|
14
|
-
if (pcbBoard.outline && pcbBoard.outline.length > 0) {
|
|
15
|
-
const points = pcbBoard.outline.map((p) => `{ x: ${p.x}, y: ${p.y} }`).join(", ");
|
|
16
|
-
boardProps.push(`outline={[${points}]}`);
|
|
17
|
-
}
|
|
18
|
-
if (pcbBoard.thickness !== void 0) {
|
|
19
|
-
boardProps.push(`thickness="${mmStr(pcbBoard.thickness)}"`);
|
|
20
|
-
}
|
|
21
|
-
if (pcbBoard.num_layers !== void 0) {
|
|
22
|
-
boardProps.push(`layers={${pcbBoard.num_layers}}`);
|
|
23
|
-
}
|
|
24
|
-
if (pcbBoard.material !== void 0) {
|
|
25
|
-
boardProps.push(`material="${pcbBoard.material}"`);
|
|
26
|
-
}
|
|
27
|
-
if (pcbBoard.solder_mask_color !== void 0) {
|
|
28
|
-
boardProps.push(`solderMaskColor="${pcbBoard.solder_mask_color}"`);
|
|
29
|
-
}
|
|
30
|
-
if (pcbBoard.silkscreen_color !== void 0) {
|
|
31
|
-
boardProps.push(`silkscreenColor="${pcbBoard.silkscreen_color}"`);
|
|
32
|
-
}
|
|
33
|
-
if (pcbBoard.anchor_position !== void 0) {
|
|
34
|
-
boardProps.push(
|
|
35
|
-
`boardAnchorPosition={{ x: ${pcbBoard.anchor_position.x}, y: ${pcbBoard.anchor_position.y} }}`
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
if (pcbBoard.anchor_alignment !== void 0) {
|
|
39
|
-
boardProps.push(`boardAnchorAlignment="${pcbBoard.anchor_alignment}"`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const boardPropsStr = boardProps.join(" ");
|
|
43
|
-
const children = "";
|
|
44
|
-
return `
|
|
45
|
-
export default () => (
|
|
46
|
-
<board${boardPropsStr ? ` ${boardPropsStr}` : ""}>
|
|
47
|
-
${children}
|
|
48
|
-
</board>
|
|
49
|
-
)
|
|
50
|
-
`.replace(/\n\s*\n/g, "\n").trim();
|
|
51
|
-
};
|
|
2
|
+
import { mmStr as mmStr6 } from "@tscircuit/mm";
|
|
3
|
+
import { su as su12 } from "@tscircuit/soup-util";
|
|
52
4
|
|
|
53
5
|
// lib/generate-footprint-tsx/convert-copper-text.ts
|
|
54
|
-
import { su
|
|
6
|
+
import { su } from "@tscircuit/soup-util";
|
|
55
7
|
|
|
56
8
|
// lib/generate-footprint-tsx/helpers.ts
|
|
57
|
-
import { mmStr
|
|
9
|
+
import { mmStr } from "@tscircuit/mm";
|
|
58
10
|
var escapeJsxText = (value) => String(value ?? "").replace(/"/g, '\\"');
|
|
59
|
-
var formatMm = (value) =>
|
|
11
|
+
var formatMm = (value) => mmStr(value ?? 0);
|
|
60
12
|
var formatOptionalMmAttr = (attrName, value) => {
|
|
61
13
|
if (value === void 0) return "";
|
|
62
|
-
return ` ${attrName}="${
|
|
14
|
+
return ` ${attrName}="${mmStr(value)}"`;
|
|
63
15
|
};
|
|
64
16
|
var formatSolderMaskAttrs = (platedHole) => `${platedHole.is_covered_with_solder_mask === void 0 ? "" : ` coveredWithSolderMask={${platedHole.is_covered_with_solder_mask}}`}${formatOptionalMmAttr("solderMaskMargin", platedHole.soldermask_margin)}`;
|
|
65
17
|
var formatPcbRotationAttr = (rotation, attrName = "pcbRotation") => {
|
|
@@ -70,7 +22,7 @@ var formatPcbRotationAttr = (rotation, attrName = "pcbRotation") => {
|
|
|
70
22
|
|
|
71
23
|
// lib/generate-footprint-tsx/convert-copper-text.ts
|
|
72
24
|
var convertCopperText = (circuitJson) => {
|
|
73
|
-
const copperTexts =
|
|
25
|
+
const copperTexts = su(circuitJson).pcb_copper_text.list();
|
|
74
26
|
const elementStrings = [];
|
|
75
27
|
for (const copperText of copperTexts) {
|
|
76
28
|
const anchorPosition = copperText.anchor_position ?? { x: 0, y: 0 };
|
|
@@ -104,11 +56,11 @@ var convertCopperText = (circuitJson) => {
|
|
|
104
56
|
};
|
|
105
57
|
|
|
106
58
|
// lib/generate-footprint-tsx/convert-courtyard.ts
|
|
107
|
-
import { su as
|
|
59
|
+
import { su as su2 } from "@tscircuit/soup-util";
|
|
108
60
|
var convertCourtyard = (circuitJson) => {
|
|
109
|
-
const courtyardOutlines =
|
|
110
|
-
const courtyardRects =
|
|
111
|
-
const courtyardCircles =
|
|
61
|
+
const courtyardOutlines = su2(circuitJson).pcb_courtyard_outline.list();
|
|
62
|
+
const courtyardRects = su2(circuitJson).pcb_courtyard_rect.list();
|
|
63
|
+
const courtyardCircles = su2(circuitJson).pcb_courtyard_circle.list();
|
|
112
64
|
const elementStrings = [];
|
|
113
65
|
for (const courtyardOutline of courtyardOutlines) {
|
|
114
66
|
const attrs = [
|
|
@@ -146,9 +98,9 @@ var convertCourtyard = (circuitJson) => {
|
|
|
146
98
|
};
|
|
147
99
|
|
|
148
100
|
// lib/generate-footprint-tsx/convert-cutouts.ts
|
|
149
|
-
import { su as
|
|
101
|
+
import { su as su3 } from "@tscircuit/soup-util";
|
|
150
102
|
var convertCutouts = (circuitJson) => {
|
|
151
|
-
const pcbCutouts =
|
|
103
|
+
const pcbCutouts = su3(circuitJson).pcb_cutout.list();
|
|
152
104
|
const elementStrings = [];
|
|
153
105
|
for (const cutout of pcbCutouts) {
|
|
154
106
|
if (cutout.shape === "rect") {
|
|
@@ -172,12 +124,12 @@ var convertCutouts = (circuitJson) => {
|
|
|
172
124
|
};
|
|
173
125
|
|
|
174
126
|
// lib/generate-footprint-tsx/convert-fabrication.ts
|
|
175
|
-
import { su as
|
|
127
|
+
import { su as su4 } from "@tscircuit/soup-util";
|
|
176
128
|
var convertFabrication = (circuitJson) => {
|
|
177
|
-
const fabricationNotePaths =
|
|
178
|
-
const fabricationNoteTexts =
|
|
179
|
-
const fabricationNoteRects =
|
|
180
|
-
const fabricationNoteDimensions =
|
|
129
|
+
const fabricationNotePaths = su4(circuitJson).pcb_fabrication_note_path.list();
|
|
130
|
+
const fabricationNoteTexts = su4(circuitJson).pcb_fabrication_note_text.list();
|
|
131
|
+
const fabricationNoteRects = su4(circuitJson).pcb_fabrication_note_rect.list();
|
|
132
|
+
const fabricationNoteDimensions = su4(circuitJson).pcb_fabrication_note_dimension.list();
|
|
181
133
|
const elementStrings = [];
|
|
182
134
|
for (const fabPath of fabricationNotePaths) {
|
|
183
135
|
const attrs = [`route={${JSON.stringify(fabPath.route)}}`];
|
|
@@ -281,27 +233,27 @@ var convertFabrication = (circuitJson) => {
|
|
|
281
233
|
};
|
|
282
234
|
|
|
283
235
|
// lib/generate-footprint-tsx/convert-holes.ts
|
|
284
|
-
import { su as
|
|
285
|
-
import { mmStr as
|
|
236
|
+
import { su as su5 } from "@tscircuit/soup-util";
|
|
237
|
+
import { mmStr as mmStr2 } from "@tscircuit/mm";
|
|
286
238
|
var convertHoles = (circuitJson) => {
|
|
287
|
-
const holes =
|
|
239
|
+
const holes = su5(circuitJson).pcb_hole.list();
|
|
288
240
|
const elementStrings = [];
|
|
289
241
|
for (const hole of holes) {
|
|
290
242
|
if (hole.hole_shape === "circle") {
|
|
291
243
|
elementStrings.push(
|
|
292
|
-
`<hole pcbX="${
|
|
244
|
+
`<hole pcbX="${mmStr2(hole.x)}" pcbY="${mmStr2(hole.y)}" diameter="${mmStr2(hole.hole_diameter)}" />`
|
|
293
245
|
);
|
|
294
246
|
} else if (hole.hole_shape === "rect") {
|
|
295
247
|
elementStrings.push(
|
|
296
|
-
`<hole pcbX="${
|
|
248
|
+
`<hole pcbX="${mmStr2(hole.x)}" pcbY="${mmStr2(hole.y)}" width="${mmStr2(hole.hole_width)}" height="${mmStr2(hole.hole_height)}" shape="rect" />`
|
|
297
249
|
);
|
|
298
250
|
} else if (hole.hole_shape === "oval") {
|
|
299
251
|
elementStrings.push(
|
|
300
|
-
`<hole pcbX="${
|
|
252
|
+
`<hole pcbX="${mmStr2(hole.x)}" pcbY="${mmStr2(hole.y)}" width="${mmStr2(hole.hole_width)}" height="${mmStr2(hole.hole_height)}" shape="oval" />`
|
|
301
253
|
);
|
|
302
254
|
} else if (hole.hole_shape === "pill" || hole.hole_shape === "rotated_pill") {
|
|
303
255
|
elementStrings.push(
|
|
304
|
-
`<hole pcbX="${
|
|
256
|
+
`<hole pcbX="${mmStr2(hole.x)}" pcbY="${mmStr2(hole.y)}" width="${mmStr2(hole.hole_width)}" height="${mmStr2(hole.hole_height)}" shape="pill"${formatPcbRotationAttr("ccw_rotation" in hole ? hole.ccw_rotation : void 0)} />`
|
|
305
257
|
);
|
|
306
258
|
}
|
|
307
259
|
}
|
|
@@ -309,9 +261,9 @@ var convertHoles = (circuitJson) => {
|
|
|
309
261
|
};
|
|
310
262
|
|
|
311
263
|
// lib/generate-footprint-tsx/convert-keepouts.ts
|
|
312
|
-
import { su as
|
|
264
|
+
import { su as su6 } from "@tscircuit/soup-util";
|
|
313
265
|
var convertKeepouts = (circuitJson) => {
|
|
314
|
-
const pcbKeepouts =
|
|
266
|
+
const pcbKeepouts = su6(circuitJson).pcb_keepout.list();
|
|
315
267
|
const elementStrings = [];
|
|
316
268
|
for (const keepout of pcbKeepouts) {
|
|
317
269
|
if (keepout.shape === "rect") {
|
|
@@ -330,13 +282,13 @@ var convertKeepouts = (circuitJson) => {
|
|
|
330
282
|
};
|
|
331
283
|
|
|
332
284
|
// lib/generate-footprint-tsx/convert-notes.ts
|
|
333
|
-
import { su as
|
|
285
|
+
import { su as su7 } from "@tscircuit/soup-util";
|
|
334
286
|
var convertNotes = (circuitJson) => {
|
|
335
|
-
const noteTexts =
|
|
336
|
-
const noteRects =
|
|
337
|
-
const notePaths =
|
|
338
|
-
const noteLines =
|
|
339
|
-
const noteDimensions =
|
|
287
|
+
const noteTexts = su7(circuitJson).pcb_note_text.list();
|
|
288
|
+
const noteRects = su7(circuitJson).pcb_note_rect.list();
|
|
289
|
+
const notePaths = su7(circuitJson).pcb_note_path.list();
|
|
290
|
+
const noteLines = su7(circuitJson).pcb_note_line.list();
|
|
291
|
+
const noteDimensions = su7(circuitJson).pcb_note_dimension.list();
|
|
340
292
|
const elementStrings = [];
|
|
341
293
|
for (const noteText of noteTexts) {
|
|
342
294
|
const anchorPosition = noteText.anchor_position ?? { x: 0, y: 0 };
|
|
@@ -426,34 +378,34 @@ var convertNotes = (circuitJson) => {
|
|
|
426
378
|
};
|
|
427
379
|
|
|
428
380
|
// lib/generate-footprint-tsx/convert-plated-holes.ts
|
|
429
|
-
import { su as
|
|
430
|
-
import { mmStr as
|
|
381
|
+
import { su as su8 } from "@tscircuit/soup-util";
|
|
382
|
+
import { mmStr as mmStr3 } from "@tscircuit/mm";
|
|
431
383
|
var convertPlatedHoles = (circuitJson) => {
|
|
432
|
-
const platedHoles =
|
|
384
|
+
const platedHoles = su8(circuitJson).pcb_plated_hole.list();
|
|
433
385
|
const elementStrings = [];
|
|
434
386
|
for (const platedHole of platedHoles) {
|
|
435
387
|
if (platedHole.shape === "oval" || platedHole.shape === "pill") {
|
|
436
388
|
elementStrings.push(
|
|
437
|
-
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${
|
|
389
|
+
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${mmStr3(platedHole.x)}" pcbY="${mmStr3(platedHole.y)}"${formatSolderMaskAttrs(platedHole)} outerHeight="${mmStr3(platedHole.outer_height)}" outerWidth="${mmStr3(platedHole.outer_width)}" holeHeight="${mmStr3(platedHole.hole_height)}" holeWidth="${mmStr3(platedHole.hole_width)}" height="${mmStr3(platedHole.hole_height)}" shape="${platedHole.shape}"${formatPcbRotationAttr("ccw_rotation" in platedHole ? platedHole.ccw_rotation : void 0)} />`
|
|
438
390
|
);
|
|
439
391
|
} else if (platedHole.shape === "circle") {
|
|
440
392
|
elementStrings.push(
|
|
441
|
-
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${
|
|
393
|
+
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${mmStr3(platedHole.x)}" pcbY="${mmStr3(platedHole.y)}"${formatSolderMaskAttrs(platedHole)} outerDiameter="${mmStr3(platedHole.outer_diameter)}" holeDiameter="${mmStr3(platedHole.hole_diameter)}" shape="circle" />`
|
|
442
394
|
);
|
|
443
395
|
} else if (platedHole.shape === "circular_hole_with_rect_pad") {
|
|
444
396
|
elementStrings.push(
|
|
445
|
-
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${
|
|
397
|
+
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${mmStr3(platedHole.x)}" pcbY="${mmStr3(platedHole.y)}"${platedHole.hole_shape === void 0 ? "" : ` holeShape="${platedHole.hole_shape}"`}${platedHole.pad_shape === void 0 ? "" : ` padShape="${platedHole.pad_shape}"`}${formatSolderMaskAttrs(platedHole)} holeDiameter="${mmStr3(platedHole.hole_diameter)}" rectPadWidth="${mmStr3(platedHole.rect_pad_width)}" rectPadHeight="${mmStr3(platedHole.rect_pad_height)}"${formatOptionalMmAttr("rectBorderRadius", platedHole.rect_border_radius)}${formatOptionalMmAttr("holeOffsetX", platedHole.hole_offset_x)}${formatOptionalMmAttr("holeOffsetY", platedHole.hole_offset_y)}${formatPcbRotationAttr(platedHole.rect_ccw_rotation)} shape="circular_hole_with_rect_pad" />`
|
|
446
398
|
);
|
|
447
399
|
} else if (platedHole.shape === "pill_hole_with_rect_pad" || platedHole.shape === "rotated_pill_hole_with_rect_pad") {
|
|
448
400
|
const holeShape = platedHole.shape === "rotated_pill_hole_with_rect_pad" ? "pill" : platedHole.hole_shape;
|
|
449
401
|
const rotation = platedHole.shape === "rotated_pill_hole_with_rect_pad" ? platedHole.hole_ccw_rotation : void 0;
|
|
450
402
|
elementStrings.push(
|
|
451
|
-
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${
|
|
403
|
+
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${mmStr3(platedHole.x)}" pcbY="${mmStr3(platedHole.y)}"${holeShape === void 0 ? "" : ` holeShape="${holeShape}"`}${platedHole.pad_shape === void 0 ? "" : ` padShape="${platedHole.pad_shape}"`}${formatSolderMaskAttrs(platedHole)} holeWidth="${mmStr3(platedHole.hole_width)}" holeHeight="${mmStr3(platedHole.hole_height)}" rectPadWidth="${mmStr3(platedHole.rect_pad_width)}" rectPadHeight="${mmStr3(platedHole.rect_pad_height)}"${formatOptionalMmAttr("rectBorderRadius", platedHole.rect_border_radius)}${formatOptionalMmAttr("holeOffsetX", platedHole.hole_offset_x)}${formatOptionalMmAttr("holeOffsetY", platedHole.hole_offset_y)}${formatPcbRotationAttr(rotation)} shape="pill_hole_with_rect_pad" />`
|
|
452
404
|
);
|
|
453
405
|
} else if (platedHole.shape === "hole_with_polygon_pad") {
|
|
454
|
-
const holeSizeAttrs = platedHole.hole_shape === "circle" ? ` holeDiameter="${
|
|
406
|
+
const holeSizeAttrs = platedHole.hole_shape === "circle" ? ` holeDiameter="${mmStr3(platedHole.hole_diameter ?? 0)}"` : `${formatOptionalMmAttr("holeWidth", platedHole.hole_width)}${formatOptionalMmAttr("holeHeight", platedHole.hole_height)}`;
|
|
455
407
|
elementStrings.push(
|
|
456
|
-
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${
|
|
408
|
+
`<platedhole portHints={${JSON.stringify(platedHole.port_hints)}} pcbX="${mmStr3(platedHole.x)}" pcbY="${mmStr3(platedHole.y)}"${platedHole.hole_shape === void 0 ? "" : ` holeShape="${platedHole.hole_shape}"`}${formatSolderMaskAttrs(platedHole)}${holeSizeAttrs} padOutline={${JSON.stringify(platedHole.pad_outline)}} holeOffsetX="${mmStr3(platedHole.hole_offset_x ?? 0)}" holeOffsetY="${mmStr3(platedHole.hole_offset_y ?? 0)}" shape="hole_with_polygon_pad" />`
|
|
457
409
|
);
|
|
458
410
|
}
|
|
459
411
|
}
|
|
@@ -461,12 +413,12 @@ var convertPlatedHoles = (circuitJson) => {
|
|
|
461
413
|
};
|
|
462
414
|
|
|
463
415
|
// lib/generate-footprint-tsx/convert-silkscreen.ts
|
|
464
|
-
import { su as
|
|
416
|
+
import { su as su9 } from "@tscircuit/soup-util";
|
|
465
417
|
var convertSilkscreen = (circuitJson) => {
|
|
466
|
-
const silkscreenLines =
|
|
467
|
-
const silkscreenPaths =
|
|
468
|
-
const silkscreenRects =
|
|
469
|
-
const silkscreenCircles =
|
|
418
|
+
const silkscreenLines = su9(circuitJson).pcb_silkscreen_line.list();
|
|
419
|
+
const silkscreenPaths = su9(circuitJson).pcb_silkscreen_path.list();
|
|
420
|
+
const silkscreenRects = su9(circuitJson).pcb_silkscreen_rect.list();
|
|
421
|
+
const silkscreenCircles = su9(circuitJson).pcb_silkscreen_circle.list();
|
|
470
422
|
const elementStrings = [];
|
|
471
423
|
for (const silkscreenPath of silkscreenPaths) {
|
|
472
424
|
elementStrings.push(
|
|
@@ -528,10 +480,10 @@ var convertSilkscreen = (circuitJson) => {
|
|
|
528
480
|
};
|
|
529
481
|
|
|
530
482
|
// lib/generate-footprint-tsx/convert-silkscreen-text.ts
|
|
531
|
-
import { su as
|
|
532
|
-
import { mmStr as
|
|
483
|
+
import { su as su10 } from "@tscircuit/soup-util";
|
|
484
|
+
import { mmStr as mmStr4 } from "@tscircuit/mm";
|
|
533
485
|
var convertSilkscreenText = (circuitJson) => {
|
|
534
|
-
const silkscreenTexts =
|
|
486
|
+
const silkscreenTexts = su10(circuitJson).pcb_silkscreen_text.list();
|
|
535
487
|
const elementStrings = [];
|
|
536
488
|
for (const silkscreenText of silkscreenTexts) {
|
|
537
489
|
const pcbX = silkscreenText.anchor_position?.x ?? 0;
|
|
@@ -539,17 +491,17 @@ var convertSilkscreenText = (circuitJson) => {
|
|
|
539
491
|
const knockoutPadding = silkscreenText.knockout_padding;
|
|
540
492
|
const hasUniformKnockoutPadding = knockoutPadding && knockoutPadding.left === knockoutPadding.top && knockoutPadding.top === knockoutPadding.right && knockoutPadding.right === knockoutPadding.bottom;
|
|
541
493
|
elementStrings.push(
|
|
542
|
-
`<silkscreentext pcbX={${pcbX}} pcbY={${pcbY}} anchorAlignment="${silkscreenText.anchor_alignment}" fontSize={${silkscreenText.font_size}}${silkscreenText.font !== void 0 ? ` font="${silkscreenText.font}"` : ""}${silkscreenText.ccw_rotation !== void 0 ? ` pcbRotation="${typeof silkscreenText.ccw_rotation === "number" ? `${silkscreenText.ccw_rotation}deg` : silkscreenText.ccw_rotation}"` : ""}${silkscreenText.is_knockout !== void 0 ? ` isKnockout={${silkscreenText.is_knockout}}` : ""}${knockoutPadding ? hasUniformKnockoutPadding ? ` knockoutPadding="${
|
|
494
|
+
`<silkscreentext pcbX={${pcbX}} pcbY={${pcbY}} anchorAlignment="${silkscreenText.anchor_alignment}" fontSize={${silkscreenText.font_size}}${silkscreenText.font !== void 0 ? ` font="${silkscreenText.font}"` : ""}${silkscreenText.ccw_rotation !== void 0 ? ` pcbRotation="${typeof silkscreenText.ccw_rotation === "number" ? `${silkscreenText.ccw_rotation}deg` : silkscreenText.ccw_rotation}"` : ""}${silkscreenText.is_knockout !== void 0 ? ` isKnockout={${silkscreenText.is_knockout}}` : ""}${knockoutPadding ? hasUniformKnockoutPadding ? ` knockoutPadding="${mmStr4(knockoutPadding.left)}"` : ` knockoutPaddingLeft="${mmStr4(knockoutPadding.left)}" knockoutPaddingTop="${mmStr4(knockoutPadding.top)}" knockoutPaddingRight="${mmStr4(knockoutPadding.right)}" knockoutPaddingBottom="${mmStr4(knockoutPadding.bottom)}"` : ""}${silkscreenText.is_mirrored !== void 0 ? ` mirrored={${silkscreenText.is_mirrored}}` : ""}${silkscreenText.layer !== void 0 ? ` layer="${silkscreenText.layer}"` : ""} text="${escapeJsxText(silkscreenText.text)}" />`
|
|
543
495
|
);
|
|
544
496
|
}
|
|
545
497
|
return elementStrings;
|
|
546
498
|
};
|
|
547
499
|
|
|
548
500
|
// lib/generate-footprint-tsx/convert-smt-pads.ts
|
|
549
|
-
import { su as
|
|
550
|
-
import { mmStr as
|
|
501
|
+
import { su as su11 } from "@tscircuit/soup-util";
|
|
502
|
+
import { mmStr as mmStr5 } from "@tscircuit/mm";
|
|
551
503
|
var convertSmtPads = (circuitJson) => {
|
|
552
|
-
const smtPads =
|
|
504
|
+
const smtPads = su11(circuitJson).pcb_smtpad.list();
|
|
553
505
|
const elementStrings = [];
|
|
554
506
|
for (const smtPad of smtPads) {
|
|
555
507
|
const commonAttrs = [];
|
|
@@ -557,10 +509,10 @@ var convertSmtPads = (circuitJson) => {
|
|
|
557
509
|
commonAttrs.push(`portHints={${JSON.stringify(smtPad.port_hints)}}`);
|
|
558
510
|
}
|
|
559
511
|
if ("x" in smtPad && smtPad.x !== void 0) {
|
|
560
|
-
commonAttrs.push(`pcbX="${
|
|
512
|
+
commonAttrs.push(`pcbX="${mmStr5(smtPad.x)}"`);
|
|
561
513
|
}
|
|
562
514
|
if ("y" in smtPad && smtPad.y !== void 0) {
|
|
563
|
-
commonAttrs.push(`pcbY="${
|
|
515
|
+
commonAttrs.push(`pcbY="${mmStr5(smtPad.y)}"`);
|
|
564
516
|
}
|
|
565
517
|
if (smtPad.layer !== void 0) {
|
|
566
518
|
commonAttrs.push(`layer="${smtPad.layer}"`);
|
|
@@ -571,47 +523,47 @@ var convertSmtPads = (circuitJson) => {
|
|
|
571
523
|
);
|
|
572
524
|
}
|
|
573
525
|
if (smtPad.soldermask_margin !== void 0) {
|
|
574
|
-
commonAttrs.push(`solderMaskMargin="${
|
|
526
|
+
commonAttrs.push(`solderMaskMargin="${mmStr5(smtPad.soldermask_margin)}"`);
|
|
575
527
|
}
|
|
576
528
|
if (smtPad.shape === "circle") {
|
|
577
529
|
elementStrings.push(
|
|
578
|
-
`<smtpad ${commonAttrs.join(" ")} radius="${
|
|
530
|
+
`<smtpad ${commonAttrs.join(" ")} radius="${mmStr5(smtPad.radius ?? 0)}" shape="circle" />`
|
|
579
531
|
);
|
|
580
532
|
} else if (smtPad.shape === "rect") {
|
|
581
533
|
if (smtPad.rect_border_radius !== void 0) {
|
|
582
534
|
commonAttrs.push(
|
|
583
|
-
`rectBorderRadius="${
|
|
535
|
+
`rectBorderRadius="${mmStr5(smtPad.rect_border_radius)}"`
|
|
584
536
|
);
|
|
585
537
|
}
|
|
586
538
|
if (smtPad.corner_radius !== void 0) {
|
|
587
|
-
commonAttrs.push(`cornerRadius="${
|
|
539
|
+
commonAttrs.push(`cornerRadius="${mmStr5(smtPad.corner_radius)}"`);
|
|
588
540
|
}
|
|
589
541
|
if (smtPad.soldermask_margin_left !== void 0) {
|
|
590
542
|
commonAttrs.push(
|
|
591
|
-
`solderMaskMarginLeft="${
|
|
543
|
+
`solderMaskMarginLeft="${mmStr5(smtPad.soldermask_margin_left)}"`
|
|
592
544
|
);
|
|
593
545
|
}
|
|
594
546
|
if (smtPad.soldermask_margin_top !== void 0) {
|
|
595
547
|
commonAttrs.push(
|
|
596
|
-
`solderMaskMarginTop="${
|
|
548
|
+
`solderMaskMarginTop="${mmStr5(smtPad.soldermask_margin_top)}"`
|
|
597
549
|
);
|
|
598
550
|
}
|
|
599
551
|
if (smtPad.soldermask_margin_right !== void 0) {
|
|
600
552
|
commonAttrs.push(
|
|
601
|
-
`solderMaskMarginRight="${
|
|
553
|
+
`solderMaskMarginRight="${mmStr5(smtPad.soldermask_margin_right)}"`
|
|
602
554
|
);
|
|
603
555
|
}
|
|
604
556
|
if (smtPad.soldermask_margin_bottom !== void 0) {
|
|
605
557
|
commonAttrs.push(
|
|
606
|
-
`solderMaskMarginBottom="${
|
|
558
|
+
`solderMaskMarginBottom="${mmStr5(smtPad.soldermask_margin_bottom)}"`
|
|
607
559
|
);
|
|
608
560
|
}
|
|
609
561
|
elementStrings.push(
|
|
610
|
-
`<smtpad ${commonAttrs.join(" ")} width="${
|
|
562
|
+
`<smtpad ${commonAttrs.join(" ")} width="${mmStr5(smtPad.width ?? 0)}" height="${mmStr5(smtPad.height ?? 0)}" shape="rect" />`
|
|
611
563
|
);
|
|
612
564
|
} else if (smtPad.shape === "pill") {
|
|
613
565
|
elementStrings.push(
|
|
614
|
-
`<smtpad ${commonAttrs.join(" ")} width="${
|
|
566
|
+
`<smtpad ${commonAttrs.join(" ")} width="${mmStr5(smtPad.width ?? 0)}" height="${mmStr5(smtPad.height ?? 0)}" radius="${mmStr5(smtPad.radius ?? 0)}" shape="pill" />`
|
|
615
567
|
);
|
|
616
568
|
} else if (smtPad.shape === "polygon") {
|
|
617
569
|
elementStrings.push(
|
|
@@ -620,30 +572,30 @@ var convertSmtPads = (circuitJson) => {
|
|
|
620
572
|
} else if (smtPad.shape === "rotated_rect") {
|
|
621
573
|
const cornerRadius = smtPad.corner_radius ?? smtPad.rect_border_radius ?? void 0;
|
|
622
574
|
if (cornerRadius !== void 0) {
|
|
623
|
-
commonAttrs.push(`cornerRadius="${
|
|
575
|
+
commonAttrs.push(`cornerRadius="${mmStr5(cornerRadius)}"`);
|
|
624
576
|
}
|
|
625
577
|
if (smtPad.soldermask_margin_left !== void 0) {
|
|
626
578
|
commonAttrs.push(
|
|
627
|
-
`solderMaskMarginLeft="${
|
|
579
|
+
`solderMaskMarginLeft="${mmStr5(smtPad.soldermask_margin_left)}"`
|
|
628
580
|
);
|
|
629
581
|
}
|
|
630
582
|
if (smtPad.soldermask_margin_top !== void 0) {
|
|
631
583
|
commonAttrs.push(
|
|
632
|
-
`solderMaskMarginTop="${
|
|
584
|
+
`solderMaskMarginTop="${mmStr5(smtPad.soldermask_margin_top)}"`
|
|
633
585
|
);
|
|
634
586
|
}
|
|
635
587
|
if (smtPad.soldermask_margin_right !== void 0) {
|
|
636
588
|
commonAttrs.push(
|
|
637
|
-
`solderMaskMarginRight="${
|
|
589
|
+
`solderMaskMarginRight="${mmStr5(smtPad.soldermask_margin_right)}"`
|
|
638
590
|
);
|
|
639
591
|
}
|
|
640
592
|
if (smtPad.soldermask_margin_bottom !== void 0) {
|
|
641
593
|
commonAttrs.push(
|
|
642
|
-
`solderMaskMarginBottom="${
|
|
594
|
+
`solderMaskMarginBottom="${mmStr5(smtPad.soldermask_margin_bottom)}"`
|
|
643
595
|
);
|
|
644
596
|
}
|
|
645
597
|
elementStrings.push(
|
|
646
|
-
`<smtpad ${commonAttrs.join(" ")} width="${
|
|
598
|
+
`<smtpad ${commonAttrs.join(" ")} width="${mmStr5(smtPad.width ?? 0)}" height="${mmStr5(smtPad.height ?? 0)}"${formatPcbRotationAttr(smtPad.ccw_rotation)} shape="rotated_rect" />`
|
|
647
599
|
);
|
|
648
600
|
}
|
|
649
601
|
}
|
|
@@ -676,6 +628,57 @@ var generateFootprintTsx = (circuitJson) => {
|
|
|
676
628
|
`.trim();
|
|
677
629
|
};
|
|
678
630
|
|
|
631
|
+
// lib/get-board-using-template.ts
|
|
632
|
+
var getBoardUsingTemplate = ({ circuitJson }) => {
|
|
633
|
+
const pcbBoard = su12(circuitJson).pcb_board.list()[0];
|
|
634
|
+
const boardProps = [];
|
|
635
|
+
if (pcbBoard) {
|
|
636
|
+
if (pcbBoard.width !== void 0) {
|
|
637
|
+
boardProps.push(`width="${mmStr6(pcbBoard.width)}"`);
|
|
638
|
+
}
|
|
639
|
+
if (pcbBoard.height !== void 0) {
|
|
640
|
+
boardProps.push(`height="${mmStr6(pcbBoard.height)}"`);
|
|
641
|
+
}
|
|
642
|
+
if (pcbBoard.outline && pcbBoard.outline.length > 0) {
|
|
643
|
+
const points = pcbBoard.outline.map((p) => `{ x: ${p.x}, y: ${p.y} }`).join(", ");
|
|
644
|
+
boardProps.push(`outline={[${points}]}`);
|
|
645
|
+
}
|
|
646
|
+
if (pcbBoard.thickness !== void 0) {
|
|
647
|
+
boardProps.push(`thickness="${mmStr6(pcbBoard.thickness)}"`);
|
|
648
|
+
}
|
|
649
|
+
if (pcbBoard.num_layers !== void 0) {
|
|
650
|
+
boardProps.push(`layers={${pcbBoard.num_layers}}`);
|
|
651
|
+
}
|
|
652
|
+
if (pcbBoard.material !== void 0) {
|
|
653
|
+
boardProps.push(`material="${pcbBoard.material}"`);
|
|
654
|
+
}
|
|
655
|
+
if (pcbBoard.solder_mask_color !== void 0) {
|
|
656
|
+
boardProps.push(`solderMaskColor="${pcbBoard.solder_mask_color}"`);
|
|
657
|
+
}
|
|
658
|
+
if (pcbBoard.silkscreen_color !== void 0) {
|
|
659
|
+
boardProps.push(`silkscreenColor="${pcbBoard.silkscreen_color}"`);
|
|
660
|
+
}
|
|
661
|
+
if (pcbBoard.anchor_position !== void 0) {
|
|
662
|
+
boardProps.push(
|
|
663
|
+
`boardAnchorPosition={{ x: ${pcbBoard.anchor_position.x}, y: ${pcbBoard.anchor_position.y} }}`
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
if (pcbBoard.anchor_alignment !== void 0) {
|
|
667
|
+
boardProps.push(`boardAnchorAlignment="${pcbBoard.anchor_alignment}"`);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
const boardPropsStr = boardProps.join(" ");
|
|
671
|
+
const footprintTsx = generateFootprintTsx(circuitJson);
|
|
672
|
+
const children = footprintTsx ? `<chip footprint={${footprintTsx}} />` : "";
|
|
673
|
+
return `
|
|
674
|
+
export default () => (
|
|
675
|
+
<board${boardPropsStr ? ` ${boardPropsStr}` : ""}>
|
|
676
|
+
${children}
|
|
677
|
+
</board>
|
|
678
|
+
)
|
|
679
|
+
`.replace(/\n\s*\n/g, "\n").trim();
|
|
680
|
+
};
|
|
681
|
+
|
|
679
682
|
// lib/generate-symbol-tsx.ts
|
|
680
683
|
import { su as su13 } from "@tscircuit/soup-util";
|
|
681
684
|
var escapeJsxText2 = (text) => text.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
package/dist/cli/main.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
convertCircuitJsonToTscircuit
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-UHPKLBYL.js";
|
|
5
5
|
|
|
6
6
|
// cli/main.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -16,7 +16,7 @@ var package_default = {
|
|
|
16
16
|
"./cli": "./dist/cli/main.js"
|
|
17
17
|
},
|
|
18
18
|
type: "module",
|
|
19
|
-
version: "0.0.
|
|
19
|
+
version: "0.0.39",
|
|
20
20
|
scripts: {
|
|
21
21
|
build: "tsup-node lib/index.ts cli/main.ts --format esm --dts",
|
|
22
22
|
test: "bun test",
|
package/dist/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mmStr } from "@tscircuit/mm"
|
|
2
2
|
import { su } from "@tscircuit/soup-util"
|
|
3
3
|
import type { AnyCircuitElement } from "circuit-json"
|
|
4
|
+
import { generateFootprintTsx } from "./generate-footprint-tsx"
|
|
4
5
|
|
|
5
6
|
export interface BoardTemplateParams {
|
|
6
7
|
circuitJson: AnyCircuitElement[]
|
|
@@ -50,9 +51,9 @@ export const getBoardUsingTemplate = ({ circuitJson }: BoardTemplateParams) => {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
const boardPropsStr = boardProps.join(" ")
|
|
54
|
+
const footprintTsx = generateFootprintTsx(circuitJson)
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
const children = ""
|
|
56
|
+
const children = footprintTsx ? `<chip footprint={${footprintTsx}} />` : ""
|
|
56
57
|
|
|
57
58
|
return `
|
|
58
59
|
export default () => (
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="600" data-software-used-string="@tscircuit/core@0.0.1322"><style></style><rect class="boundary" x="0" y="0" fill="#000" width="800" height="600" data-type="pcb_background" data-pcb-layer="global"/><rect class="pcb-boundary" fill="none" stroke="#fff" stroke-width="0.3" x="57.14285714285717" y="71.42857142857147" width="685.7142857142858" height="457.1428571428572" data-type="pcb_boundary" data-pcb-layer="global"/><path class="pcb-board" d="M 57.14285714285717 528.5714285714287 L 742.8571428571429 528.5714285714287 L 742.8571428571429 71.42857142857147 L 57.14285714285717 71.42857142857147 Z" fill="none" stroke="rgba(255, 255, 255, 0.5)" stroke-width="5.714285714285715" data-type="pcb_board" data-pcb-layer="board"/><rect class="pcb-pad" fill="rgb(200, 52, 52)" x="314.28571428571433" y="277.1428571428572" width="57.142857142857146" height="45.71428571428572" data-type="pcb_smtpad" data-pcb-layer="top"/><rect class="pcb-pad" fill="rgb(200, 52, 52)" x="428.57142857142867" y="277.1428571428572" width="57.142857142857146" height="45.71428571428572" data-type="pcb_smtpad" data-pcb-layer="top"/></svg>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import type { AnyCircuitElement, PcbSmtPad } from "circuit-json"
|
|
3
|
+
import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
|
|
4
|
+
import { convertCircuitJsonToTscircuit } from "lib/index"
|
|
5
|
+
import { runTscircuitCode } from "tscircuit"
|
|
6
|
+
|
|
7
|
+
const sourceTscircuit = `
|
|
8
|
+
const BoardChildChip = (props) => (
|
|
9
|
+
<chip
|
|
10
|
+
footprint={<footprint>
|
|
11
|
+
<smtpad
|
|
12
|
+
portHints={["1"]}
|
|
13
|
+
pcbX="-1mm"
|
|
14
|
+
pcbY="0mm"
|
|
15
|
+
width="1mm"
|
|
16
|
+
height="0.8mm"
|
|
17
|
+
shape="rect"
|
|
18
|
+
layer="top"
|
|
19
|
+
/>
|
|
20
|
+
<smtpad
|
|
21
|
+
portHints={["2"]}
|
|
22
|
+
pcbX="1mm"
|
|
23
|
+
pcbY="0mm"
|
|
24
|
+
width="1mm"
|
|
25
|
+
height="0.8mm"
|
|
26
|
+
shape="rect"
|
|
27
|
+
layer="top"
|
|
28
|
+
/>
|
|
29
|
+
</footprint>}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
export default () => (
|
|
35
|
+
<board width="12mm" height="8mm">
|
|
36
|
+
<BoardChildChip name="U1" />
|
|
37
|
+
</board>
|
|
38
|
+
)
|
|
39
|
+
`
|
|
40
|
+
|
|
41
|
+
test.failing(
|
|
42
|
+
"test20 board conversion drops child component geometry",
|
|
43
|
+
async () => {
|
|
44
|
+
const sourceCircuitJson = (await runTscircuitCode(
|
|
45
|
+
sourceTscircuit,
|
|
46
|
+
)) as AnyCircuitElement[]
|
|
47
|
+
|
|
48
|
+
const sourcePads = sourceCircuitJson.filter(
|
|
49
|
+
(elm): elm is PcbSmtPad => elm.type === "pcb_smtpad",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
expect(sourcePads).toHaveLength(2)
|
|
53
|
+
|
|
54
|
+
const convertedTscircuit = convertCircuitJsonToTscircuit(
|
|
55
|
+
sourceCircuitJson,
|
|
56
|
+
{
|
|
57
|
+
componentName: "ConvertedBoard",
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
expect(convertedTscircuit).toMatchInlineSnapshot(`
|
|
62
|
+
"export default () => (
|
|
63
|
+
<board width="12mm" height="8mm" thickness="1.4mm" layers={2} material="fr4">
|
|
64
|
+
</board>
|
|
65
|
+
)"
|
|
66
|
+
`)
|
|
67
|
+
|
|
68
|
+
const convertedCircuitJson = (await runTscircuitCode(
|
|
69
|
+
convertedTscircuit,
|
|
70
|
+
)) as AnyCircuitElement[]
|
|
71
|
+
|
|
72
|
+
const convertedPads = convertedCircuitJson.filter(
|
|
73
|
+
(elm): elm is PcbSmtPad => elm.type === "pcb_smtpad",
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
const pcbSvg = convertCircuitJsonToPcbSvg(convertedCircuitJson)
|
|
77
|
+
await expect(pcbSvg).toMatchSvgSnapshot(import.meta.path, "pcb")
|
|
78
|
+
|
|
79
|
+
expect(convertedPads).toHaveLength(2)
|
|
80
|
+
},
|
|
81
|
+
)
|