circuit-to-canvas 0.0.1 → 0.0.3
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/.github/workflows/bun-formatcheck.yml +26 -0
- package/.github/workflows/bun-pver-release.yml +77 -0
- package/.github/workflows/bun-test.yml +31 -0
- package/.github/workflows/bun-typecheck.yml +26 -0
- package/LICENSE +21 -0
- package/README.md +66 -0
- package/dist/index.d.ts +146 -2
- package/dist/index.js +620 -0
- package/lib/drawer/CircuitToCanvasDrawer.ts +138 -1
- package/lib/drawer/elements/index.ts +30 -0
- package/lib/drawer/elements/pcb-board.ts +62 -0
- package/lib/drawer/elements/pcb-copper-pour.ts +84 -0
- package/lib/drawer/elements/pcb-cutout.ts +53 -0
- package/lib/drawer/elements/pcb-hole.ts +90 -0
- package/lib/drawer/elements/pcb-silkscreen.ts +171 -0
- package/lib/drawer/elements/pcb-smtpad.ts +108 -0
- package/lib/drawer/elements/pcb-trace.ts +59 -0
- package/lib/drawer/elements/pcb-via.ts +33 -0
- package/lib/drawer/shapes/index.ts +3 -0
- package/lib/drawer/shapes/line.ts +37 -0
- package/lib/drawer/shapes/path.ts +61 -0
- package/lib/drawer/shapes/polygon.ts +38 -0
- package/lib/drawer/types.ts +16 -0
- package/package.json +2 -2
- package/tests/elements/__snapshots__/board-with-elements.snap.png +0 -0
- package/tests/elements/__snapshots__/bottom-layer-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/bottom-layer-trace.snap.png +0 -0
- package/tests/elements/__snapshots__/circular-cutout.snap.png +0 -0
- package/tests/elements/__snapshots__/circular-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/copper-pour-with-trace.snap.png +0 -0
- package/tests/elements/__snapshots__/custom-outline-board.snap.png +0 -0
- package/tests/elements/__snapshots__/multi-segment-trace.snap.png +0 -0
- package/tests/elements/__snapshots__/multiple-traces.snap.png +0 -0
- package/tests/elements/__snapshots__/multiple-vias.snap.png +0 -0
- package/tests/elements/__snapshots__/oval-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-board.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-copper-pour.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-cutout.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-silkscreen.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-smtpad.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-trace.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-via.snap.png +0 -0
- package/tests/elements/__snapshots__/pill-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pill-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/polygon-copper-pour.snap.png +0 -0
- package/tests/elements/__snapshots__/polygon-cutout.snap.png +0 -0
- package/tests/elements/__snapshots__/polygon-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/rect-pad-with-border-radius.snap.png +0 -0
- package/tests/elements/__snapshots__/rotated-rect-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-circle.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-line.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-on-component.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-path.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-rect.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-text-bottom.snap.png +0 -0
- package/tests/elements/__snapshots__/square-hole.snap.png +0 -0
- package/tests/elements/pcb-board.test.ts +155 -0
- package/tests/elements/pcb-copper-pour.test.ts +120 -0
- package/tests/elements/pcb-cutout.test.ts +82 -0
- package/tests/elements/pcb-hole.test.ts +105 -0
- package/tests/elements/pcb-silkscreen.test.ts +245 -0
- package/tests/elements/pcb-smtpad.test.ts +198 -0
- package/tests/elements/pcb-trace.test.ts +116 -0
- package/tests/elements/pcb-via.test.ts +75 -0
- package/.claude/settings.local.json +0 -7
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "canvas"
|
|
3
|
+
import type { PcbSmtPad } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw rectangular smt pad", async () => {
|
|
7
|
+
const canvas = createCanvas(100, 100)
|
|
8
|
+
const ctx = canvas.getContext("2d")
|
|
9
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
10
|
+
|
|
11
|
+
ctx.fillStyle = "#1a1a1a"
|
|
12
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
13
|
+
|
|
14
|
+
const pad: PcbSmtPad = {
|
|
15
|
+
type: "pcb_smtpad",
|
|
16
|
+
pcb_smtpad_id: "pad1",
|
|
17
|
+
shape: "rect",
|
|
18
|
+
x: 50,
|
|
19
|
+
y: 50,
|
|
20
|
+
width: 40,
|
|
21
|
+
height: 20,
|
|
22
|
+
layer: "top",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
drawer.drawElements([pad])
|
|
26
|
+
|
|
27
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
28
|
+
import.meta.path,
|
|
29
|
+
)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test("draw rectangular smt pad with border radius", async () => {
|
|
33
|
+
const canvas = createCanvas(100, 100)
|
|
34
|
+
const ctx = canvas.getContext("2d")
|
|
35
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
36
|
+
|
|
37
|
+
ctx.fillStyle = "#1a1a1a"
|
|
38
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
39
|
+
|
|
40
|
+
const pad: PcbSmtPad = {
|
|
41
|
+
type: "pcb_smtpad",
|
|
42
|
+
pcb_smtpad_id: "pad1",
|
|
43
|
+
shape: "rect",
|
|
44
|
+
x: 50,
|
|
45
|
+
y: 50,
|
|
46
|
+
width: 40,
|
|
47
|
+
height: 20,
|
|
48
|
+
layer: "top",
|
|
49
|
+
rect_border_radius: 5,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
drawer.drawElements([pad])
|
|
53
|
+
|
|
54
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
55
|
+
import.meta.path,
|
|
56
|
+
"rect-pad-with-border-radius",
|
|
57
|
+
)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test("draw rotated rectangular smt pad", async () => {
|
|
61
|
+
const canvas = createCanvas(100, 100)
|
|
62
|
+
const ctx = canvas.getContext("2d")
|
|
63
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
64
|
+
|
|
65
|
+
ctx.fillStyle = "#1a1a1a"
|
|
66
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
67
|
+
|
|
68
|
+
const pad: PcbSmtPad = {
|
|
69
|
+
type: "pcb_smtpad",
|
|
70
|
+
pcb_smtpad_id: "pad1",
|
|
71
|
+
shape: "rotated_rect",
|
|
72
|
+
x: 50,
|
|
73
|
+
y: 50,
|
|
74
|
+
width: 40,
|
|
75
|
+
height: 20,
|
|
76
|
+
layer: "top",
|
|
77
|
+
ccw_rotation: 45,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
drawer.drawElements([pad])
|
|
81
|
+
|
|
82
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
83
|
+
import.meta.path,
|
|
84
|
+
"rotated-rect-pad",
|
|
85
|
+
)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test("draw circular smt pad", async () => {
|
|
89
|
+
const canvas = createCanvas(100, 100)
|
|
90
|
+
const ctx = canvas.getContext("2d")
|
|
91
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
92
|
+
|
|
93
|
+
ctx.fillStyle = "#1a1a1a"
|
|
94
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
95
|
+
|
|
96
|
+
const pad: PcbSmtPad = {
|
|
97
|
+
type: "pcb_smtpad",
|
|
98
|
+
pcb_smtpad_id: "pad1",
|
|
99
|
+
shape: "circle",
|
|
100
|
+
x: 50,
|
|
101
|
+
y: 50,
|
|
102
|
+
radius: 20,
|
|
103
|
+
layer: "top",
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
drawer.drawElements([pad])
|
|
107
|
+
|
|
108
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
109
|
+
import.meta.path,
|
|
110
|
+
"circular-pad",
|
|
111
|
+
)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test("draw pill smt pad", async () => {
|
|
115
|
+
const canvas = createCanvas(100, 100)
|
|
116
|
+
const ctx = canvas.getContext("2d")
|
|
117
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
118
|
+
|
|
119
|
+
ctx.fillStyle = "#1a1a1a"
|
|
120
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
121
|
+
|
|
122
|
+
const pad: PcbSmtPad = {
|
|
123
|
+
type: "pcb_smtpad",
|
|
124
|
+
pcb_smtpad_id: "pad1",
|
|
125
|
+
shape: "pill",
|
|
126
|
+
x: 50,
|
|
127
|
+
y: 50,
|
|
128
|
+
width: 50,
|
|
129
|
+
height: 25,
|
|
130
|
+
radius: 12.5,
|
|
131
|
+
layer: "top",
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
drawer.drawElements([pad])
|
|
135
|
+
|
|
136
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
137
|
+
import.meta.path,
|
|
138
|
+
"pill-pad",
|
|
139
|
+
)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test("draw polygon smt pad", async () => {
|
|
143
|
+
const canvas = createCanvas(100, 100)
|
|
144
|
+
const ctx = canvas.getContext("2d")
|
|
145
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
146
|
+
|
|
147
|
+
ctx.fillStyle = "#1a1a1a"
|
|
148
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
149
|
+
|
|
150
|
+
const pad: PcbSmtPad = {
|
|
151
|
+
type: "pcb_smtpad",
|
|
152
|
+
pcb_smtpad_id: "pad1",
|
|
153
|
+
shape: "polygon",
|
|
154
|
+
layer: "top",
|
|
155
|
+
points: [
|
|
156
|
+
{ x: 30, y: 30 },
|
|
157
|
+
{ x: 70, y: 30 },
|
|
158
|
+
{ x: 80, y: 50 },
|
|
159
|
+
{ x: 70, y: 70 },
|
|
160
|
+
{ x: 30, y: 70 },
|
|
161
|
+
{ x: 20, y: 50 },
|
|
162
|
+
],
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
drawer.drawElements([pad])
|
|
166
|
+
|
|
167
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
168
|
+
import.meta.path,
|
|
169
|
+
"polygon-pad",
|
|
170
|
+
)
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
test("draw bottom layer smt pad", async () => {
|
|
174
|
+
const canvas = createCanvas(100, 100)
|
|
175
|
+
const ctx = canvas.getContext("2d")
|
|
176
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
177
|
+
|
|
178
|
+
ctx.fillStyle = "#1a1a1a"
|
|
179
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
180
|
+
|
|
181
|
+
const pad: PcbSmtPad = {
|
|
182
|
+
type: "pcb_smtpad",
|
|
183
|
+
pcb_smtpad_id: "pad1",
|
|
184
|
+
shape: "rect",
|
|
185
|
+
x: 50,
|
|
186
|
+
y: 50,
|
|
187
|
+
width: 40,
|
|
188
|
+
height: 20,
|
|
189
|
+
layer: "bottom",
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
drawer.drawElements([pad])
|
|
193
|
+
|
|
194
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
195
|
+
import.meta.path,
|
|
196
|
+
"bottom-layer-pad",
|
|
197
|
+
)
|
|
198
|
+
})
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "canvas"
|
|
3
|
+
import type { PCBTrace } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw simple trace", async () => {
|
|
7
|
+
const canvas = createCanvas(100, 100)
|
|
8
|
+
const ctx = canvas.getContext("2d")
|
|
9
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
10
|
+
|
|
11
|
+
ctx.fillStyle = "#1a1a1a"
|
|
12
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
13
|
+
|
|
14
|
+
const trace: PCBTrace = {
|
|
15
|
+
type: "pcb_trace",
|
|
16
|
+
pcb_trace_id: "trace1",
|
|
17
|
+
route: [
|
|
18
|
+
{ route_type: "wire", x: 20, y: 50, width: 5, layer: "top" },
|
|
19
|
+
{ route_type: "wire", x: 80, y: 50, width: 5, layer: "top" },
|
|
20
|
+
],
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
drawer.drawElements([trace])
|
|
24
|
+
|
|
25
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
26
|
+
import.meta.path,
|
|
27
|
+
)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test("draw multi-segment trace", async () => {
|
|
31
|
+
const canvas = createCanvas(100, 100)
|
|
32
|
+
const ctx = canvas.getContext("2d")
|
|
33
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
34
|
+
|
|
35
|
+
ctx.fillStyle = "#1a1a1a"
|
|
36
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
37
|
+
|
|
38
|
+
const trace: PCBTrace = {
|
|
39
|
+
type: "pcb_trace",
|
|
40
|
+
pcb_trace_id: "trace1",
|
|
41
|
+
route: [
|
|
42
|
+
{ route_type: "wire", x: 10, y: 10, width: 3, layer: "top" },
|
|
43
|
+
{ route_type: "wire", x: 50, y: 10, width: 3, layer: "top" },
|
|
44
|
+
{ route_type: "wire", x: 50, y: 50, width: 3, layer: "top" },
|
|
45
|
+
{ route_type: "wire", x: 90, y: 50, width: 3, layer: "top" },
|
|
46
|
+
{ route_type: "wire", x: 90, y: 90, width: 3, layer: "top" },
|
|
47
|
+
],
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
drawer.drawElements([trace])
|
|
51
|
+
|
|
52
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
53
|
+
import.meta.path,
|
|
54
|
+
"multi-segment-trace",
|
|
55
|
+
)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test("draw trace on bottom layer", async () => {
|
|
59
|
+
const canvas = createCanvas(100, 100)
|
|
60
|
+
const ctx = canvas.getContext("2d")
|
|
61
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
62
|
+
|
|
63
|
+
ctx.fillStyle = "#1a1a1a"
|
|
64
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
65
|
+
|
|
66
|
+
const trace: PCBTrace = {
|
|
67
|
+
type: "pcb_trace",
|
|
68
|
+
pcb_trace_id: "trace1",
|
|
69
|
+
route: [
|
|
70
|
+
{ route_type: "wire", x: 20, y: 30, width: 6, layer: "bottom" },
|
|
71
|
+
{ route_type: "wire", x: 80, y: 70, width: 6, layer: "bottom" },
|
|
72
|
+
],
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
drawer.drawElements([trace])
|
|
76
|
+
|
|
77
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
78
|
+
import.meta.path,
|
|
79
|
+
"bottom-layer-trace",
|
|
80
|
+
)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test("draw multiple traces", async () => {
|
|
84
|
+
const canvas = createCanvas(100, 100)
|
|
85
|
+
const ctx = canvas.getContext("2d")
|
|
86
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
87
|
+
|
|
88
|
+
ctx.fillStyle = "#1a1a1a"
|
|
89
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
90
|
+
|
|
91
|
+
const traces: PCBTrace[] = [
|
|
92
|
+
{
|
|
93
|
+
type: "pcb_trace",
|
|
94
|
+
pcb_trace_id: "trace1",
|
|
95
|
+
route: [
|
|
96
|
+
{ route_type: "wire", x: 10, y: 30, width: 4, layer: "top" },
|
|
97
|
+
{ route_type: "wire", x: 90, y: 30, width: 4, layer: "top" },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
type: "pcb_trace",
|
|
102
|
+
pcb_trace_id: "trace2",
|
|
103
|
+
route: [
|
|
104
|
+
{ route_type: "wire", x: 10, y: 70, width: 4, layer: "bottom" },
|
|
105
|
+
{ route_type: "wire", x: 90, y: 70, width: 4, layer: "bottom" },
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
drawer.drawElements(traces)
|
|
111
|
+
|
|
112
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
113
|
+
import.meta.path,
|
|
114
|
+
"multiple-traces",
|
|
115
|
+
)
|
|
116
|
+
})
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "canvas"
|
|
3
|
+
import type { PCBVia } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw via", async () => {
|
|
7
|
+
const canvas = createCanvas(100, 100)
|
|
8
|
+
const ctx = canvas.getContext("2d")
|
|
9
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
10
|
+
|
|
11
|
+
ctx.fillStyle = "#1a1a1a"
|
|
12
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
13
|
+
|
|
14
|
+
const via: PCBVia = {
|
|
15
|
+
type: "pcb_via",
|
|
16
|
+
pcb_via_id: "via1",
|
|
17
|
+
x: 50,
|
|
18
|
+
y: 50,
|
|
19
|
+
outer_diameter: 40,
|
|
20
|
+
hole_diameter: 20,
|
|
21
|
+
layers: ["top", "bottom"],
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
drawer.drawElements([via])
|
|
25
|
+
|
|
26
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
27
|
+
import.meta.path,
|
|
28
|
+
)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test("draw multiple vias", async () => {
|
|
32
|
+
const canvas = createCanvas(200, 100)
|
|
33
|
+
const ctx = canvas.getContext("2d")
|
|
34
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
35
|
+
|
|
36
|
+
ctx.fillStyle = "#1a1a1a"
|
|
37
|
+
ctx.fillRect(0, 0, 200, 100)
|
|
38
|
+
|
|
39
|
+
const vias: PCBVia[] = [
|
|
40
|
+
{
|
|
41
|
+
type: "pcb_via",
|
|
42
|
+
pcb_via_id: "via1",
|
|
43
|
+
x: 50,
|
|
44
|
+
y: 50,
|
|
45
|
+
outer_diameter: 30,
|
|
46
|
+
hole_diameter: 15,
|
|
47
|
+
layers: ["top", "bottom"],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: "pcb_via",
|
|
51
|
+
pcb_via_id: "via2",
|
|
52
|
+
x: 100,
|
|
53
|
+
y: 50,
|
|
54
|
+
outer_diameter: 25,
|
|
55
|
+
hole_diameter: 12,
|
|
56
|
+
layers: ["top", "bottom"],
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: "pcb_via",
|
|
60
|
+
pcb_via_id: "via3",
|
|
61
|
+
x: 150,
|
|
62
|
+
y: 50,
|
|
63
|
+
outer_diameter: 35,
|
|
64
|
+
hole_diameter: 18,
|
|
65
|
+
layers: ["top", "bottom"],
|
|
66
|
+
},
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
drawer.drawElements(vias)
|
|
70
|
+
|
|
71
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
72
|
+
import.meta.path,
|
|
73
|
+
"multiple-vias",
|
|
74
|
+
)
|
|
75
|
+
})
|