circuit-json-to-lbrn 0.0.1 → 0.0.2
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 +71 -0
- package/.github/workflows/bun-test.yml +31 -0
- package/.github/workflows/bun-typecheck.yml +26 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +162 -162
- package/lib/ConvertContext.ts +10 -0
- package/lib/element-handlers/addPcbTrace/circle-to-polygon.ts +15 -0
- package/lib/element-handlers/addPcbTrace/index.ts +90 -0
- package/lib/element-handlers/addSmtPad/addRectSmtPad.ts +15 -26
- package/lib/index.ts +91 -4
- package/lib/polygon-to-shape-path.ts +49 -0
- package/lib/writeDebugSvg.ts +43 -0
- package/package.json +4 -2
- package/site/index.html +0 -0
- package/site/main.tsx +0 -0
- package/tests/assets/lga-interconnect.circuit.json +1681 -1321
- package/tests/examples/__snapshots__/lga-interconnect.snap.svg +2 -2
- package/tests/examples/__snapshots__/single-trace.snap.svg +8 -0
- package/tests/examples/lga-interconnect.test.ts +4 -0
- package/tests/examples/single-trace.test.ts +67 -0
- package/tests/fixtures/preload.ts +1 -1
- package/tests/svg.test.ts +10 -11
- package/.claude/settings.local.json +0 -9
- package/tests/plated-hole.test.ts +0 -70
|
@@ -12,6 +12,10 @@ test("lga-interconnect", async () => {
|
|
|
12
12
|
|
|
13
13
|
const project = convertCircuitJsonToLbrn(circuitJson)
|
|
14
14
|
|
|
15
|
+
Bun.write("debug-output/lga-interconnect.lbrn2", project.getString(), {
|
|
16
|
+
createPath: true,
|
|
17
|
+
})
|
|
18
|
+
|
|
15
19
|
const lbrnSvg = await generateLightBurnSvg(project)
|
|
16
20
|
|
|
17
21
|
expect(stackSvgsVertically([pcbSvg, lbrnSvg])).toMatchSvgSnapshot(
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { test, expect } from "bun:test"
|
|
2
|
+
import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
|
|
3
|
+
import { generateLightBurnSvg } from "lbrnts"
|
|
4
|
+
import { convertCircuitJsonToLbrn } from "../../lib"
|
|
5
|
+
import { stackSvgsVertically } from "stack-svgs"
|
|
6
|
+
import type { CircuitJson, SourceTrace } from "circuit-json"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* This test demonstrates a bug where standalone traces (traces not connected
|
|
10
|
+
* to any ports/nets) are not being converted to cut shapes in the LightBurn output.
|
|
11
|
+
*
|
|
12
|
+
* Expected: The trace should appear as a cut shape in the bottom SVG
|
|
13
|
+
* Actual: The trace is missing from the LightBurn output (only CutSetting is present)
|
|
14
|
+
*
|
|
15
|
+
* Root cause: addPcbTrace gets netId=undefined for unconnected traces, and
|
|
16
|
+
* netGeoms.get(undefined) returns undefined, so the trace polygon is never added.
|
|
17
|
+
*/
|
|
18
|
+
test("single-trace", async () => {
|
|
19
|
+
const circuitJson = [
|
|
20
|
+
{
|
|
21
|
+
type: "pcb_board",
|
|
22
|
+
pcb_board_id: "board_1",
|
|
23
|
+
width: 20,
|
|
24
|
+
height: 20,
|
|
25
|
+
center: { x: 0, y: 0 },
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: "pcb_trace",
|
|
29
|
+
pcb_trace_id: "trace_1",
|
|
30
|
+
source_trace_id: "trace_1",
|
|
31
|
+
route: [
|
|
32
|
+
{
|
|
33
|
+
x: -5,
|
|
34
|
+
y: -5,
|
|
35
|
+
width: 0.5,
|
|
36
|
+
layer: "top",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
x: 5,
|
|
40
|
+
y: 5,
|
|
41
|
+
width: 0.5,
|
|
42
|
+
layer: "top",
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: "source_trace",
|
|
48
|
+
source_trace_id: "trace_2",
|
|
49
|
+
connected_source_net_ids: [],
|
|
50
|
+
connected_source_port_ids: [],
|
|
51
|
+
} as SourceTrace,
|
|
52
|
+
] as CircuitJson
|
|
53
|
+
|
|
54
|
+
const pcbSvg = await convertCircuitJsonToPcbSvg(circuitJson)
|
|
55
|
+
|
|
56
|
+
const project = convertCircuitJsonToLbrn(circuitJson)
|
|
57
|
+
|
|
58
|
+
Bun.write("debug-output/single-trace.lbrn2", project.getString(), {
|
|
59
|
+
createPath: true,
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const lbrnSvg = await generateLightBurnSvg(project)
|
|
63
|
+
|
|
64
|
+
expect(stackSvgsVertically([pcbSvg, lbrnSvg])).toMatchSvgSnapshot(
|
|
65
|
+
import.meta.filename,
|
|
66
|
+
)
|
|
67
|
+
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import "bun-match-svg"
|
|
1
|
+
import "bun-match-svg"
|
package/tests/svg.test.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { expect, test } from "bun:test"
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
|
|
3
|
+
const testSvg = `<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
|
|
4
4
|
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
|
|
5
|
-
</svg>`
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
</svg>`
|
|
6
|
+
|
|
7
|
+
test("svg snapshot example", async () => {
|
|
8
|
+
// First run will create the snapshot
|
|
9
|
+
// Subsequent runs will compare against the saved snapshot
|
|
10
|
+
await expect(testSvg).toMatchSvgSnapshot(import.meta.path)
|
|
11
|
+
})
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "bun:test"
|
|
2
|
-
import { convertCircuitJsonToLbrn } from "../lib/index"
|
|
3
|
-
import type { CircuitJson } from "circuit-json"
|
|
4
|
-
|
|
5
|
-
test("plated hole generates circular path", () => {
|
|
6
|
-
const circuitJson: CircuitJson = [
|
|
7
|
-
{
|
|
8
|
-
type: "pcb_board",
|
|
9
|
-
pcb_board_id: "test_board",
|
|
10
|
-
width: 100,
|
|
11
|
-
height: 100,
|
|
12
|
-
center: { x: 0, y: 0 },
|
|
13
|
-
thickness: 1.6,
|
|
14
|
-
num_layers: 2,
|
|
15
|
-
material: "fr4",
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
type: "pcb_plated_hole",
|
|
19
|
-
shape: "circle",
|
|
20
|
-
pcb_plated_hole_id: "test_hole",
|
|
21
|
-
outer_diameter: 2,
|
|
22
|
-
hole_diameter: 1,
|
|
23
|
-
x: 10,
|
|
24
|
-
y: 20,
|
|
25
|
-
layers: ["top"],
|
|
26
|
-
},
|
|
27
|
-
]
|
|
28
|
-
|
|
29
|
-
const project = convertCircuitJsonToLbrn(circuitJson)
|
|
30
|
-
|
|
31
|
-
// Should have 1 CutSetting and 1 ShapePath
|
|
32
|
-
expect(project.children.length).toBe(2)
|
|
33
|
-
|
|
34
|
-
// First child should be CutSetting
|
|
35
|
-
const cutSetting = project.children.find(
|
|
36
|
-
(child) => child.token === "CutSetting",
|
|
37
|
-
)!
|
|
38
|
-
expect(cutSetting.token).toBe("CutSetting")
|
|
39
|
-
|
|
40
|
-
// Second child should be ShapePath (the plated hole)
|
|
41
|
-
const shapePath = project.children.find(
|
|
42
|
-
(child) => child.token === "Shape.Path",
|
|
43
|
-
)!
|
|
44
|
-
expect(shapePath.token).toBe("Shape.Path")
|
|
45
|
-
|
|
46
|
-
// Verify the shape path has the expected properties
|
|
47
|
-
if (shapePath.token === "Shape.Path") {
|
|
48
|
-
expect((shapePath as any).isClosed).toBe(true)
|
|
49
|
-
expect((shapePath as any).cutIndex).toBe(0)
|
|
50
|
-
expect((shapePath as any).verts).toBeDefined()
|
|
51
|
-
expect((shapePath as any).prims).toBeDefined()
|
|
52
|
-
|
|
53
|
-
// Should have 5 vertices (4 bezier curve points + 1 to close)
|
|
54
|
-
const vertsLength = (shapePath as any).verts?.length
|
|
55
|
-
const primsLength = (shapePath as any).prims?.length
|
|
56
|
-
expect(vertsLength).toBe(5)
|
|
57
|
-
expect(primsLength).toBe(4)
|
|
58
|
-
|
|
59
|
-
// Verify all primitives are bezier curves
|
|
60
|
-
const prims = (shapePath as any).prims || []
|
|
61
|
-
for (const prim of prims) {
|
|
62
|
-
expect(prim.type).toBe(1) // 1 = BezierTo
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Verify the circle is centered at (10, 20) with radius 1
|
|
66
|
-
const firstVert = (shapePath as any).verts?.[0]
|
|
67
|
-
expect(firstVert?.x).toBeCloseTo(11, 5) // 10 + 1 (radius)
|
|
68
|
-
expect(firstVert?.y).toBeCloseTo(20, 5)
|
|
69
|
-
}
|
|
70
|
-
})
|