circuit-json-to-tscircuit 0.0.73 → 0.0.74
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-5YQBNWPZ.js → chunk-KDQXBFSE.js} +105 -2
- package/dist/cli/main.js +2 -2
- package/dist/lib/index.js +1 -1
- package/lib/generate-board-schematic-tsx/convert-box-components.ts +8 -2
- package/lib/generate-board-schematic-tsx/convert-box-port-markers.ts +114 -0
- package/package.json +1 -1
- package/tests/board-schematic-box-port-arrows.test.tsx +103 -0
- package/tests/ti-evms/__snapshots__/ti-drv8307evm-roundtrip-schematic-comparison.snap.svg +2 -2
- package/tests/ti-evms/__snapshots__/ti-drv8307evm-roundtrip.test.tsx.snap +6 -0
- package/tests/ti-evms/__snapshots__/ti-lm251772evm-pd-roundtrip-schematic-comparison.snap.svg +1 -1
- package/tests/ti-evms/__snapshots__/ti-lm251772evm-pd-roundtrip.test.tsx.snap +2 -0
- package/tests/ti-evms/__snapshots__/ti-lm5155evm-fly-roundtrip-schematic-comparison.snap.svg +1 -1
- package/tests/ti-evms/__snapshots__/ti-lmg342x-bb-evm-roundtrip-schematic-comparison.snap.svg +1 -1
- package/tests/ti-evms/__snapshots__/ti-lmg342x-bb-evm-roundtrip.test.tsx.snap +1 -0
- package/tests/ti-evms/ti-lm5155evm-fly-roundtrip.test.tsx +2 -0
|
@@ -572,6 +572,104 @@ var convertSymbolPrimitives = ({
|
|
|
572
572
|
import { su as su2 } from "@tscircuit/soup-util";
|
|
573
573
|
import "circuit-json";
|
|
574
574
|
|
|
575
|
+
// lib/generate-board-schematic-tsx/convert-box-port-markers.ts
|
|
576
|
+
var ARROW_SIZE = 0.1;
|
|
577
|
+
var ARROW_HALF_ANGLE_RADIANS = Math.PI / 6;
|
|
578
|
+
var ARROW_AXIAL_LENGTH = ARROW_SIZE * Math.cos(ARROW_HALF_ANGLE_RADIANS);
|
|
579
|
+
var ARROW_HALF_WIDTH = ARROW_SIZE * Math.sin(ARROW_HALF_ANGLE_RADIANS);
|
|
580
|
+
var MARKER_STROKE_WIDTH = 0.02 / 3;
|
|
581
|
+
var MARKER_STROKE_COLOR = "#840000";
|
|
582
|
+
var MARKER_FILL_COLOR = "#ffffff";
|
|
583
|
+
var INVERSION_BUBBLE_RADIUS = 0.06;
|
|
584
|
+
var getOutwardDirection = (side) => {
|
|
585
|
+
switch (side) {
|
|
586
|
+
case "left":
|
|
587
|
+
return { x: -1, y: 0 };
|
|
588
|
+
case "right":
|
|
589
|
+
return { x: 1, y: 0 };
|
|
590
|
+
case "top":
|
|
591
|
+
return { x: 0, y: 1 };
|
|
592
|
+
case "bottom":
|
|
593
|
+
return { x: 0, y: -1 };
|
|
594
|
+
default:
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
var createArrowPath = ({
|
|
599
|
+
tip,
|
|
600
|
+
direction
|
|
601
|
+
}) => {
|
|
602
|
+
const base = {
|
|
603
|
+
x: tip.x - direction.x * ARROW_AXIAL_LENGTH,
|
|
604
|
+
y: tip.y - direction.y * ARROW_AXIAL_LENGTH
|
|
605
|
+
};
|
|
606
|
+
const perpendicular = { x: -direction.y, y: direction.x };
|
|
607
|
+
const firstBaseCorner = {
|
|
608
|
+
x: base.x + perpendicular.x * ARROW_HALF_WIDTH,
|
|
609
|
+
y: base.y + perpendicular.y * ARROW_HALF_WIDTH
|
|
610
|
+
};
|
|
611
|
+
const secondBaseCorner = {
|
|
612
|
+
x: base.x - perpendicular.x * ARROW_HALF_WIDTH,
|
|
613
|
+
y: base.y - perpendicular.y * ARROW_HALF_WIDTH
|
|
614
|
+
};
|
|
615
|
+
return formatElement("schematicpath", {
|
|
616
|
+
points: [tip, firstBaseCorner, secondBaseCorner, tip],
|
|
617
|
+
strokeWidth: MARKER_STROKE_WIDTH,
|
|
618
|
+
strokeColor: MARKER_STROKE_COLOR,
|
|
619
|
+
fillColor: MARKER_FILL_COLOR,
|
|
620
|
+
isFilled: true
|
|
621
|
+
});
|
|
622
|
+
};
|
|
623
|
+
var convertBoxPortMarkers = ({
|
|
624
|
+
schematicPort,
|
|
625
|
+
edge
|
|
626
|
+
}) => {
|
|
627
|
+
const outward = getOutwardDirection(schematicPort.side_of_component);
|
|
628
|
+
if (!outward) return { markers: [], pinLineStart: edge };
|
|
629
|
+
const inversionOffset = schematicPort.is_drawn_with_inversion_circle ? INVERSION_BUBBLE_RADIUS * 2 : 0;
|
|
630
|
+
const pinLineStart = {
|
|
631
|
+
x: edge.x + outward.x * inversionOffset,
|
|
632
|
+
y: edge.y + outward.y * inversionOffset
|
|
633
|
+
};
|
|
634
|
+
const markers = [];
|
|
635
|
+
if (schematicPort.is_drawn_with_inversion_circle) {
|
|
636
|
+
markers.push(
|
|
637
|
+
formatElement("schematiccircle", {
|
|
638
|
+
center: {
|
|
639
|
+
x: edge.x + outward.x * INVERSION_BUBBLE_RADIUS,
|
|
640
|
+
y: edge.y + outward.y * INVERSION_BUBBLE_RADIUS
|
|
641
|
+
},
|
|
642
|
+
radius: INVERSION_BUBBLE_RADIUS,
|
|
643
|
+
strokeWidth: MARKER_STROKE_WIDTH * 3,
|
|
644
|
+
color: MARKER_STROKE_COLOR,
|
|
645
|
+
fillColor: MARKER_FILL_COLOR,
|
|
646
|
+
isFilled: true
|
|
647
|
+
})
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
if (schematicPort.has_input_arrow) {
|
|
651
|
+
markers.push(
|
|
652
|
+
createArrowPath({
|
|
653
|
+
tip: pinLineStart,
|
|
654
|
+
direction: { x: -outward.x, y: -outward.y }
|
|
655
|
+
})
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
if (schematicPort.has_output_arrow) {
|
|
659
|
+
const separation = schematicPort.has_input_arrow ? ARROW_AXIAL_LENGTH : 0;
|
|
660
|
+
markers.push(
|
|
661
|
+
createArrowPath({
|
|
662
|
+
tip: {
|
|
663
|
+
x: pinLineStart.x + outward.x * (separation + ARROW_SIZE),
|
|
664
|
+
y: pinLineStart.y + outward.y * (separation + ARROW_SIZE)
|
|
665
|
+
},
|
|
666
|
+
direction: outward
|
|
667
|
+
})
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
return { markers, pinLineStart };
|
|
671
|
+
};
|
|
672
|
+
|
|
575
673
|
// lib/generate-board-schematic-tsx/get-box-pin-display-label.ts
|
|
576
674
|
var getBoxPinDisplayLabel = ({
|
|
577
675
|
schematicPort,
|
|
@@ -624,16 +722,21 @@ var convertBoxComponent = ({
|
|
|
624
722
|
edge.y = schematicComponent.center.y - schematicComponent.size.height / 2;
|
|
625
723
|
break;
|
|
626
724
|
}
|
|
725
|
+
const { markers, pinLineStart } = convertBoxPortMarkers({
|
|
726
|
+
schematicPort,
|
|
727
|
+
edge
|
|
728
|
+
});
|
|
627
729
|
primitives.push(
|
|
628
730
|
formatElement("schematicline", {
|
|
629
|
-
x1:
|
|
630
|
-
y1:
|
|
731
|
+
x1: pinLineStart.x,
|
|
732
|
+
y1: pinLineStart.y,
|
|
631
733
|
x2: schematicPort.center.x,
|
|
632
734
|
y2: schematicPort.center.y,
|
|
633
735
|
strokeWidth: DEFAULT_BOX_BODY_STROKE_WIDTH,
|
|
634
736
|
color: DEFAULT_BOX_BODY_STROKE_COLOR
|
|
635
737
|
})
|
|
636
738
|
);
|
|
739
|
+
primitives.push(...markers);
|
|
637
740
|
const sourcePort = su2(circuitJson).source_port.get(
|
|
638
741
|
schematicPort.source_port_id
|
|
639
742
|
);
|
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-KDQXBFSE.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.73",
|
|
20
20
|
repository: {
|
|
21
21
|
type: "git",
|
|
22
22
|
url: "https://github.com/tscircuit/circuit-json-to-tscircuit.git"
|
package/dist/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { su } from "@tscircuit/soup-util"
|
|
2
2
|
import { type AnyCircuitElement, type SchematicComponent } from "circuit-json"
|
|
3
3
|
import { convertRect } from "./convert-rect"
|
|
4
|
+
import { convertBoxPortMarkers } from "./convert-box-port-markers"
|
|
4
5
|
import { formatElement } from "./format-attributes"
|
|
5
6
|
import { getBoxPinDisplayLabel } from "./get-box-pin-display-label"
|
|
6
7
|
|
|
@@ -55,16 +56,21 @@ export const convertBoxComponent = ({
|
|
|
55
56
|
schematicComponent.center.y - schematicComponent.size.height / 2
|
|
56
57
|
break
|
|
57
58
|
}
|
|
59
|
+
const { markers, pinLineStart } = convertBoxPortMarkers({
|
|
60
|
+
schematicPort,
|
|
61
|
+
edge,
|
|
62
|
+
})
|
|
58
63
|
primitives.push(
|
|
59
64
|
formatElement("schematicline", {
|
|
60
|
-
x1:
|
|
61
|
-
y1:
|
|
65
|
+
x1: pinLineStart.x,
|
|
66
|
+
y1: pinLineStart.y,
|
|
62
67
|
x2: schematicPort.center.x,
|
|
63
68
|
y2: schematicPort.center.y,
|
|
64
69
|
strokeWidth: DEFAULT_BOX_BODY_STROKE_WIDTH,
|
|
65
70
|
color: DEFAULT_BOX_BODY_STROKE_COLOR,
|
|
66
71
|
}),
|
|
67
72
|
)
|
|
73
|
+
primitives.push(...markers)
|
|
68
74
|
const sourcePort = su(circuitJson).source_port.get(
|
|
69
75
|
schematicPort.source_port_id,
|
|
70
76
|
)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Point, SchematicPort } from "circuit-json"
|
|
2
|
+
import { formatElement } from "./format-attributes"
|
|
3
|
+
|
|
4
|
+
const ARROW_SIZE = 0.1
|
|
5
|
+
const ARROW_HALF_ANGLE_RADIANS = Math.PI / 6
|
|
6
|
+
const ARROW_AXIAL_LENGTH = ARROW_SIZE * Math.cos(ARROW_HALF_ANGLE_RADIANS)
|
|
7
|
+
const ARROW_HALF_WIDTH = ARROW_SIZE * Math.sin(ARROW_HALF_ANGLE_RADIANS)
|
|
8
|
+
const MARKER_STROKE_WIDTH = 0.02 / 3
|
|
9
|
+
const MARKER_STROKE_COLOR = "#840000"
|
|
10
|
+
const MARKER_FILL_COLOR = "#ffffff"
|
|
11
|
+
const INVERSION_BUBBLE_RADIUS = 0.06
|
|
12
|
+
|
|
13
|
+
const getOutwardDirection = (
|
|
14
|
+
side: SchematicPort["side_of_component"],
|
|
15
|
+
): Point | null => {
|
|
16
|
+
switch (side) {
|
|
17
|
+
case "left":
|
|
18
|
+
return { x: -1, y: 0 }
|
|
19
|
+
case "right":
|
|
20
|
+
return { x: 1, y: 0 }
|
|
21
|
+
case "top":
|
|
22
|
+
return { x: 0, y: 1 }
|
|
23
|
+
case "bottom":
|
|
24
|
+
return { x: 0, y: -1 }
|
|
25
|
+
default:
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const createArrowPath = ({
|
|
31
|
+
tip,
|
|
32
|
+
direction,
|
|
33
|
+
}: {
|
|
34
|
+
tip: Point
|
|
35
|
+
direction: Point
|
|
36
|
+
}): string => {
|
|
37
|
+
const base = {
|
|
38
|
+
x: tip.x - direction.x * ARROW_AXIAL_LENGTH,
|
|
39
|
+
y: tip.y - direction.y * ARROW_AXIAL_LENGTH,
|
|
40
|
+
}
|
|
41
|
+
const perpendicular = { x: -direction.y, y: direction.x }
|
|
42
|
+
const firstBaseCorner = {
|
|
43
|
+
x: base.x + perpendicular.x * ARROW_HALF_WIDTH,
|
|
44
|
+
y: base.y + perpendicular.y * ARROW_HALF_WIDTH,
|
|
45
|
+
}
|
|
46
|
+
const secondBaseCorner = {
|
|
47
|
+
x: base.x - perpendicular.x * ARROW_HALF_WIDTH,
|
|
48
|
+
y: base.y - perpendicular.y * ARROW_HALF_WIDTH,
|
|
49
|
+
}
|
|
50
|
+
return formatElement("schematicpath", {
|
|
51
|
+
points: [tip, firstBaseCorner, secondBaseCorner, tip],
|
|
52
|
+
strokeWidth: MARKER_STROKE_WIDTH,
|
|
53
|
+
strokeColor: MARKER_STROKE_COLOR,
|
|
54
|
+
fillColor: MARKER_FILL_COLOR,
|
|
55
|
+
isFilled: true,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const convertBoxPortMarkers = ({
|
|
60
|
+
schematicPort,
|
|
61
|
+
edge,
|
|
62
|
+
}: {
|
|
63
|
+
schematicPort: SchematicPort
|
|
64
|
+
edge: Point
|
|
65
|
+
}): { markers: string[]; pinLineStart: Point } => {
|
|
66
|
+
const outward = getOutwardDirection(schematicPort.side_of_component)
|
|
67
|
+
if (!outward) return { markers: [], pinLineStart: edge }
|
|
68
|
+
|
|
69
|
+
const inversionOffset = schematicPort.is_drawn_with_inversion_circle
|
|
70
|
+
? INVERSION_BUBBLE_RADIUS * 2
|
|
71
|
+
: 0
|
|
72
|
+
const pinLineStart = {
|
|
73
|
+
x: edge.x + outward.x * inversionOffset,
|
|
74
|
+
y: edge.y + outward.y * inversionOffset,
|
|
75
|
+
}
|
|
76
|
+
const markers: string[] = []
|
|
77
|
+
|
|
78
|
+
if (schematicPort.is_drawn_with_inversion_circle) {
|
|
79
|
+
markers.push(
|
|
80
|
+
formatElement("schematiccircle", {
|
|
81
|
+
center: {
|
|
82
|
+
x: edge.x + outward.x * INVERSION_BUBBLE_RADIUS,
|
|
83
|
+
y: edge.y + outward.y * INVERSION_BUBBLE_RADIUS,
|
|
84
|
+
},
|
|
85
|
+
radius: INVERSION_BUBBLE_RADIUS,
|
|
86
|
+
strokeWidth: MARKER_STROKE_WIDTH * 3,
|
|
87
|
+
color: MARKER_STROKE_COLOR,
|
|
88
|
+
fillColor: MARKER_FILL_COLOR,
|
|
89
|
+
isFilled: true,
|
|
90
|
+
}),
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
if (schematicPort.has_input_arrow) {
|
|
94
|
+
markers.push(
|
|
95
|
+
createArrowPath({
|
|
96
|
+
tip: pinLineStart,
|
|
97
|
+
direction: { x: -outward.x, y: -outward.y },
|
|
98
|
+
}),
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
if (schematicPort.has_output_arrow) {
|
|
102
|
+
const separation = schematicPort.has_input_arrow ? ARROW_AXIAL_LENGTH : 0
|
|
103
|
+
markers.push(
|
|
104
|
+
createArrowPath({
|
|
105
|
+
tip: {
|
|
106
|
+
x: pinLineStart.x + outward.x * (separation + ARROW_SIZE),
|
|
107
|
+
y: pinLineStart.y + outward.y * (separation + ARROW_SIZE),
|
|
108
|
+
},
|
|
109
|
+
direction: outward,
|
|
110
|
+
}),
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
return { markers, pinLineStart }
|
|
114
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import type { CircuitJson } from "circuit-json"
|
|
3
|
+
import { convertCircuitJsonToTscircuit } from "lib"
|
|
4
|
+
import { runTscircuitCode } from "tscircuit"
|
|
5
|
+
|
|
6
|
+
test("preserves input and output arrows on imported box pins", async () => {
|
|
7
|
+
const circuitJson: CircuitJson = [
|
|
8
|
+
{
|
|
9
|
+
type: "pcb_board",
|
|
10
|
+
pcb_board_id: "board",
|
|
11
|
+
center: { x: 0, y: 0 },
|
|
12
|
+
width: 10,
|
|
13
|
+
height: 10,
|
|
14
|
+
num_layers: 2,
|
|
15
|
+
thickness: 1.6,
|
|
16
|
+
material: "fr4",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
type: "schematic_component",
|
|
20
|
+
schematic_component_id: "controller",
|
|
21
|
+
center: { x: 0, y: 0 },
|
|
22
|
+
size: { width: 2, height: 2 },
|
|
23
|
+
is_box_with_pins: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "schematic_port",
|
|
27
|
+
schematic_port_id: "output",
|
|
28
|
+
source_port_id: "output_source",
|
|
29
|
+
schematic_component_id: "controller",
|
|
30
|
+
center: { x: -1.4, y: 0 },
|
|
31
|
+
side_of_component: "left",
|
|
32
|
+
facing_direction: "left",
|
|
33
|
+
has_output_arrow: true,
|
|
34
|
+
is_drawn_with_inversion_circle: true,
|
|
35
|
+
pin_number: 1,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: "schematic_port",
|
|
39
|
+
schematic_port_id: "input",
|
|
40
|
+
source_port_id: "input_source",
|
|
41
|
+
schematic_component_id: "controller",
|
|
42
|
+
center: { x: 1.4, y: 0.4 },
|
|
43
|
+
side_of_component: "right",
|
|
44
|
+
facing_direction: "right",
|
|
45
|
+
has_input_arrow: true,
|
|
46
|
+
is_drawn_with_inversion_circle: true,
|
|
47
|
+
pin_number: 2,
|
|
48
|
+
},
|
|
49
|
+
]
|
|
50
|
+
const renderedCircuitJson = await runTscircuitCode(
|
|
51
|
+
convertCircuitJsonToTscircuit(circuitJson, {
|
|
52
|
+
componentName: "ArrowPinBoard",
|
|
53
|
+
}),
|
|
54
|
+
)
|
|
55
|
+
const arrowPaths = renderedCircuitJson.flatMap((element) =>
|
|
56
|
+
element.type === "schematic_path" &&
|
|
57
|
+
element.is_filled &&
|
|
58
|
+
element.fill_color === "#ffffff"
|
|
59
|
+
? [element]
|
|
60
|
+
: [],
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
expect(arrowPaths).toHaveLength(2)
|
|
64
|
+
expect(
|
|
65
|
+
arrowPaths.some((path) =>
|
|
66
|
+
path.points.some(
|
|
67
|
+
(point) => Math.abs(point.x + 1.22) < 0.000001 && point.y === 0,
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
).toBe(true)
|
|
71
|
+
expect(
|
|
72
|
+
arrowPaths.some((path) =>
|
|
73
|
+
path.points.some(
|
|
74
|
+
(point) =>
|
|
75
|
+
Math.abs(point.x - 1.12) < 0.000001 &&
|
|
76
|
+
Math.abs(point.y - 0.4) < 0.000001,
|
|
77
|
+
),
|
|
78
|
+
),
|
|
79
|
+
).toBe(true)
|
|
80
|
+
|
|
81
|
+
const inversionCircles = renderedCircuitJson.flatMap((element) =>
|
|
82
|
+
element.type === "schematic_circle" &&
|
|
83
|
+
element.is_filled &&
|
|
84
|
+
element.fill_color === "#ffffff" &&
|
|
85
|
+
element.radius === 0.06
|
|
86
|
+
? [element]
|
|
87
|
+
: [],
|
|
88
|
+
)
|
|
89
|
+
expect(inversionCircles).toHaveLength(2)
|
|
90
|
+
expect(inversionCircles.map((circle) => circle.center.x).sort()).toEqual([
|
|
91
|
+
-1.06, 1.06,
|
|
92
|
+
])
|
|
93
|
+
|
|
94
|
+
const shiftedPinLines = renderedCircuitJson.flatMap((element) =>
|
|
95
|
+
element.type === "schematic_line" &&
|
|
96
|
+
((Math.abs(element.x1 + 1.12) < 0.000001 && element.y1 === 0) ||
|
|
97
|
+
(Math.abs(element.x1 - 1.12) < 0.000001 &&
|
|
98
|
+
Math.abs(element.y1 - 0.4) < 0.000001))
|
|
99
|
+
? [element]
|
|
100
|
+
: [],
|
|
101
|
+
)
|
|
102
|
+
expect(shiftedPinLines).toHaveLength(2)
|
|
103
|
+
})
|