kicadts 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 +70 -0
- package/.github/workflows/bun-test.yml +32 -0
- package/.github/workflows/bun-typecheck.yml +26 -0
- package/.vscode/settings.json +1 -1
- package/AGENTS.md +1 -0
- package/LICENSE +21 -0
- package/README.md +101 -91
- package/TODO.md +46 -0
- package/bunfig.toml +2 -2
- package/lib/sexpr/classes/At.ts +15 -0
- package/lib/sexpr/classes/Bus.ts +23 -3
- package/lib/sexpr/classes/BusEntry.ts +30 -3
- package/lib/sexpr/classes/EmbeddedFonts.ts +1 -3
- package/lib/sexpr/classes/Footprint.ts +157 -27
- package/lib/sexpr/classes/FootprintAttr.ts +3 -1
- package/lib/sexpr/classes/FootprintModel.ts +1 -4
- package/lib/sexpr/classes/FootprintNetTiePadGroups.ts +3 -1
- package/lib/sexpr/classes/FootprintPad.ts +206 -54
- package/lib/sexpr/classes/FpArc.ts +23 -0
- package/lib/sexpr/classes/FpCircle.ts +24 -3
- package/lib/sexpr/classes/FpLine.ts +31 -3
- package/lib/sexpr/classes/FpPoly.ts +24 -4
- package/lib/sexpr/classes/FpRect.ts +24 -3
- package/lib/sexpr/classes/FpText.ts +43 -9
- package/lib/sexpr/classes/FpTextBox.ts +43 -5
- package/lib/sexpr/classes/GrLine.ts +20 -1
- package/lib/sexpr/classes/GrText.ts +38 -12
- package/lib/sexpr/classes/Image.ts +38 -11
- package/lib/sexpr/classes/Junction.ts +36 -4
- package/lib/sexpr/classes/KicadPcb.ts +49 -1
- package/lib/sexpr/classes/KicadSch.ts +119 -25
- package/lib/sexpr/classes/Label.ts +45 -5
- package/lib/sexpr/classes/NoConnect.ts +20 -3
- package/lib/sexpr/classes/PadLayers.ts +13 -1
- package/lib/sexpr/classes/PadOptions.ts +4 -5
- package/lib/sexpr/classes/PadPrimitiveGrArc.ts +22 -4
- package/lib/sexpr/classes/PadPrimitiveGrCircle.ts +23 -4
- package/lib/sexpr/classes/PadPrimitives.ts +3 -1
- package/lib/sexpr/classes/PadSize.ts +15 -0
- package/lib/sexpr/classes/PadTeardrops.ts +3 -1
- package/lib/sexpr/classes/PcbGeneral.ts +14 -7
- package/lib/sexpr/classes/PcbLayerDefinition.ts +5 -1
- package/lib/sexpr/classes/Property.ts +64 -9
- package/lib/sexpr/classes/Pts.ts +7 -5
- package/lib/sexpr/classes/SchematicText.ts +39 -9
- package/lib/sexpr/classes/Segment.ts +21 -0
- package/lib/sexpr/classes/SegmentNet.ts +3 -1
- package/lib/sexpr/classes/Setup/PcbPlotParams.ts +10 -50
- package/lib/sexpr/classes/Setup/Setup.ts +12 -11
- package/lib/sexpr/classes/Setup/Stackup.ts +14 -19
- package/lib/sexpr/classes/Setup/StackupLayerProperties.ts +3 -1
- package/lib/sexpr/classes/Setup/StackupProperties.ts +0 -1
- package/lib/sexpr/classes/Setup/base.ts +1 -3
- package/lib/sexpr/classes/Setup/setupMultiValueProperties.ts +0 -1
- package/lib/sexpr/classes/Sheet.ts +85 -3
- package/lib/sexpr/classes/SheetPin.ts +4 -1
- package/lib/sexpr/classes/Symbol.ts +176 -51
- package/lib/sexpr/classes/TextEffects.ts +25 -8
- package/lib/sexpr/classes/TitleBlock.ts +21 -4
- package/lib/sexpr/classes/Via.ts +38 -3
- package/lib/sexpr/classes/ViaNet.ts +2 -1
- package/lib/sexpr/classes/Wire.ts +23 -3
- package/lib/sexpr/classes/Xy.ts +1 -3
- package/lib/sexpr/classes/Zone.ts +1 -3
- package/lib/sexpr/parseToPrimitiveSExpr.ts +6 -1
- package/lib/sexpr/utils/strokeFromArgs.ts +5 -6
- package/lib/sexpr/utils/toStringValue.ts +2 -1
- package/package.json +3 -2
- package/scripts/download-references.ts +24 -22
- package/tests/fixtures/expectEqualPrimitiveSExpr.ts +6 -7
- package/tests/fixtures/png-matcher.ts +109 -0
- package/tests/fixtures/preload.ts +1 -0
- package/tests/sexpr/classes/FootprintPad.test.ts +8 -1
- package/tests/sexpr/classes/Image.test.ts +9 -1
- package/tests/sexpr/classes/KicadSch.test.ts +1 -3
- package/tests/sexpr/classes/Setup.test.ts +0 -1
- package/bun.lock +0 -48
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Created using @tscircuit/plop (npm install -g @tscircuit/plop)
|
|
2
|
+
name: Format Check
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
format-check:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Setup bun
|
|
18
|
+
uses: oven-sh/setup-bun@v2
|
|
19
|
+
with:
|
|
20
|
+
bun-version: latest
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: bun install
|
|
24
|
+
|
|
25
|
+
- name: Run format check
|
|
26
|
+
run: bun run format:check
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Created using @tscircuit/plop (npm install -g @tscircuit/plop)
|
|
2
|
+
name: Publish to npm
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
UPSTREAM_REPOS: "" # comma-separated list, e.g. "eval,tscircuit,docs"
|
|
11
|
+
UPSTREAM_PACKAGES_TO_UPDATE: "" # comma-separated list, e.g. "@tscircuit/core,@tscircuit/protos"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
publish:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
with:
|
|
19
|
+
token: ${{ secrets.TSCIRCUIT_BOT_GITHUB_TOKEN }}
|
|
20
|
+
- name: Setup bun
|
|
21
|
+
uses: oven-sh/setup-bun@v2
|
|
22
|
+
with:
|
|
23
|
+
bun-version: latest
|
|
24
|
+
- uses: actions/setup-node@v3
|
|
25
|
+
with:
|
|
26
|
+
node-version: 20
|
|
27
|
+
registry-url: https://registry.npmjs.org/
|
|
28
|
+
- run: npm install -g pver
|
|
29
|
+
- run: bun install --frozen-lockfile
|
|
30
|
+
- run: bun run build
|
|
31
|
+
- run: pver release
|
|
32
|
+
env:
|
|
33
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
34
|
+
GITHUB_TOKEN: ${{ secrets.TSCIRCUIT_BOT_GITHUB_TOKEN }}
|
|
35
|
+
|
|
36
|
+
# - name: Create Pull Request
|
|
37
|
+
# id: create-pr
|
|
38
|
+
# uses: peter-evans/create-pull-request@v5
|
|
39
|
+
# with:
|
|
40
|
+
# commit-message: "chore: bump version"
|
|
41
|
+
# title: "chore: bump version"
|
|
42
|
+
# body: "Automated package update"
|
|
43
|
+
# branch: bump-version-${{ github.run_number }}
|
|
44
|
+
# base: main
|
|
45
|
+
# token: ${{ secrets.TSCIRCUIT_BOT_GITHUB_TOKEN }}
|
|
46
|
+
# committer: tscircuitbot <githubbot@tscircuit.com>
|
|
47
|
+
# author: tscircuitbot <githubbot@tscircuit.com>
|
|
48
|
+
|
|
49
|
+
# - name: Enable auto-merge
|
|
50
|
+
# if: steps.create-pr.outputs.pull-request-number != ''
|
|
51
|
+
# run: |
|
|
52
|
+
# gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} --rebase --delete-branch
|
|
53
|
+
# env:
|
|
54
|
+
# GH_TOKEN: ${{ secrets.TSCIRCUIT_BOT_GITHUB_TOKEN }}
|
|
55
|
+
|
|
56
|
+
# - name: Trigger upstream repo updates
|
|
57
|
+
# if: env.UPSTREAM_REPOS && env.UPSTREAM_PACKAGES_TO_UPDATE
|
|
58
|
+
# run: |
|
|
59
|
+
# IFS=',' read -ra REPOS <<< "${{ env.UPSTREAM_REPOS }}"
|
|
60
|
+
# for repo in "${REPOS[@]}"; do
|
|
61
|
+
# if [[ -n "$repo" ]]; then
|
|
62
|
+
# echo "Triggering update for repo: $repo"
|
|
63
|
+
# curl -X POST \
|
|
64
|
+
# -H "Accept: application/vnd.github.v3+json" \
|
|
65
|
+
# -H "Authorization: token ${{ secrets.TSCIRCUIT_BOT_GITHUB_TOKEN }}" \
|
|
66
|
+
# -H "Content-Type: application/json" \
|
|
67
|
+
# "https://api.github.com/repos/tscircuit/$repo/actions/workflows/update-package.yml/dispatches" \
|
|
68
|
+
# -d "{\"ref\":\"main\",\"inputs\":{\"package_names\":\"${{ env.UPSTREAM_PACKAGES_TO_UPDATE }}\"}}"
|
|
69
|
+
# fi
|
|
70
|
+
# done
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Created using @tscircuit/plop (npm install -g @tscircuit/plop)
|
|
2
|
+
name: Bun Test
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
pull_request:
|
|
6
|
+
push:
|
|
7
|
+
branches:
|
|
8
|
+
- main
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
timeout-minutes: 5
|
|
14
|
+
|
|
15
|
+
# Skip test for PRs that not chore: bump version
|
|
16
|
+
if: "${{ github.event_name != 'pull_request' || github.event.pull_request.title != 'chore: bump version' }}"
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout code
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Setup bun
|
|
23
|
+
uses: oven-sh/setup-bun@v2
|
|
24
|
+
with:
|
|
25
|
+
bun-version: latest
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: bun install
|
|
29
|
+
- run: bun run download-demos
|
|
30
|
+
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: bun test
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Created using @tscircuit/plop (npm install -g @tscircuit/plop)
|
|
2
|
+
name: Type Check
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
type-check:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Setup bun
|
|
18
|
+
uses: oven-sh/setup-bun@v2
|
|
19
|
+
with:
|
|
20
|
+
bun-version: latest
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: bun i
|
|
24
|
+
|
|
25
|
+
- name: Run type check
|
|
26
|
+
run: bunx tsc --noEmit
|
package/.vscode/settings.json
CHANGED
package/AGENTS.md
CHANGED
|
@@ -28,3 +28,4 @@ most extensive one is `references/SEXPR_MAIN.adoc` (use `bun run scripts/downloa
|
|
|
28
28
|
- NEW PATTERN: Never track the order of children unless absolutely necessary, use the `_sx*` properties and `getChildren` to return the children in a predefined order
|
|
29
29
|
- NEW PATTERN: Never track unknown children, throw an error/allow an error to be thrown if you encounter a child PrimitiveSExpr that can't be parsed. You can introduce new `_sx*` properties and a new class to prevent the error
|
|
30
30
|
- NEW PATTERN: One class per file
|
|
31
|
+
- NEW PATTERN: Ergonomic constructors for classes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 tscircuit Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -28,33 +28,33 @@ import {
|
|
|
28
28
|
Xy,
|
|
29
29
|
} from "kicadts"
|
|
30
30
|
|
|
31
|
-
const schematic = new KicadSch(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
31
|
+
const schematic = new KicadSch({
|
|
32
|
+
version: 20240101,
|
|
33
|
+
generator: "kicadts-demo",
|
|
34
|
+
titleBlock: new TitleBlock({
|
|
35
|
+
title: "Demo Schematic",
|
|
36
|
+
company: "Example Labs",
|
|
37
|
+
}),
|
|
38
|
+
paper: new Paper({ size: "A4" }),
|
|
39
|
+
properties: [new Property({ key: "Sheetfile", value: "demo.kicad_sch" })],
|
|
40
|
+
sheets: [
|
|
41
|
+
new Sheet({
|
|
42
|
+
position: [0, 0, 0], // Can use array instead of new At([0, 0, 0])
|
|
43
|
+
size: { width: 100, height: 80 },
|
|
44
|
+
}),
|
|
45
|
+
],
|
|
46
|
+
symbols: [
|
|
47
|
+
new SchematicSymbol({
|
|
48
|
+
libraryId: "Device:R",
|
|
49
|
+
at: { x: 25.4, y: 12.7 }, // Can use object instead of new At([25.4, 12.7])
|
|
50
|
+
}),
|
|
51
|
+
],
|
|
52
|
+
wires: [
|
|
53
|
+
new Wire({
|
|
54
|
+
points: new Pts([new Xy(0, 0), new Xy(25.4, 12.7)]),
|
|
55
|
+
}),
|
|
56
|
+
],
|
|
57
|
+
})
|
|
58
58
|
|
|
59
59
|
await fs.writeFile("demo.kicad_sch", schematic.getString())
|
|
60
60
|
```
|
|
@@ -78,51 +78,57 @@ import {
|
|
|
78
78
|
TextEffects,
|
|
79
79
|
} from "kicadts"
|
|
80
80
|
|
|
81
|
-
const pcb = new KicadPcb()
|
|
82
|
-
pcb.version = 20240101
|
|
83
|
-
pcb.generator = "kicadts-demo"
|
|
84
|
-
|
|
85
81
|
const netGnd = new PcbNet(1, "GND")
|
|
86
82
|
const netSignal = new PcbNet(2, "Net-(R1-Pad2)")
|
|
87
|
-
pcb.nets = [netGnd, netSignal]
|
|
88
|
-
|
|
89
|
-
const footprint = new Footprint()
|
|
90
|
-
footprint.libraryLink = "Resistor_SMD:R_0603"
|
|
91
|
-
footprint.layer = "F.Cu"
|
|
92
|
-
footprint.position = new At([10, 5, 90])
|
|
93
|
-
|
|
94
|
-
const makeText = (type: string, text: string, x: number, y: number, layer: string) => {
|
|
95
|
-
const fpText = new FpText()
|
|
96
|
-
fpText.type = type
|
|
97
|
-
fpText.text = text
|
|
98
|
-
fpText.position = new At([x, y])
|
|
99
|
-
fpText.layer = layer
|
|
100
|
-
const effects = new TextEffects()
|
|
101
|
-
effects.font.size = { height: 1, width: 1 }
|
|
102
|
-
effects.font.thickness = 0.15
|
|
103
|
-
fpText.effects = effects
|
|
104
|
-
return fpText
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
footprint.fpTexts = [
|
|
108
|
-
makeText("reference", "R1", 0, -1.5, "F.SilkS"),
|
|
109
|
-
makeText("value", "10k", 0, 1.5, "F.Fab"),
|
|
110
|
-
]
|
|
111
|
-
|
|
112
|
-
const pad = (number: string, x: number, net: PcbNet) => {
|
|
113
|
-
const fpPad = new FootprintPad(number, "smd", "roundrect")
|
|
114
|
-
fpPad.at = new At([x, 0])
|
|
115
|
-
fpPad.size = new PadSize(1.05, 0.95)
|
|
116
|
-
fpPad.layers = new PadLayers(["F.Cu", "F.Paste", "F.Mask"])
|
|
117
|
-
fpPad.roundrectRatio = 0.25
|
|
118
|
-
fpPad.net = new PadNet(net.id, net.name)
|
|
119
|
-
fpPad.pinfunction = number
|
|
120
|
-
fpPad.pintype = "passive"
|
|
121
|
-
return fpPad
|
|
122
|
-
}
|
|
123
83
|
|
|
124
|
-
|
|
125
|
-
|
|
84
|
+
const makeText = (
|
|
85
|
+
type: string,
|
|
86
|
+
text: string,
|
|
87
|
+
x: number,
|
|
88
|
+
y: number,
|
|
89
|
+
layer: string
|
|
90
|
+
) =>
|
|
91
|
+
new FpText({
|
|
92
|
+
type,
|
|
93
|
+
text,
|
|
94
|
+
position: { x, y },
|
|
95
|
+
layer,
|
|
96
|
+
effects: new TextEffects({
|
|
97
|
+
font: { size: { height: 1, width: 1 }, thickness: 0.15 },
|
|
98
|
+
}),
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const pad = (number: string, x: number, net: PcbNet) =>
|
|
102
|
+
new FootprintPad({
|
|
103
|
+
number,
|
|
104
|
+
padType: "smd",
|
|
105
|
+
shape: "roundrect",
|
|
106
|
+
at: { x, y: 0 },
|
|
107
|
+
size: { width: 1.05, height: 0.95 },
|
|
108
|
+
layers: ["F.Cu", "F.Paste", "F.Mask"],
|
|
109
|
+
roundrectRatio: 0.25,
|
|
110
|
+
net: new PadNet(net.id, net.name),
|
|
111
|
+
pinfunction: number,
|
|
112
|
+
pintype: "passive",
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
const pcb = new KicadPcb({
|
|
116
|
+
version: 20240101,
|
|
117
|
+
generator: "kicadts-demo",
|
|
118
|
+
nets: [netGnd, netSignal],
|
|
119
|
+
footprints: [
|
|
120
|
+
new Footprint({
|
|
121
|
+
libraryLink: "Resistor_SMD:R_0603",
|
|
122
|
+
layer: "F.Cu",
|
|
123
|
+
position: { x: 10, y: 5, angle: 90 },
|
|
124
|
+
fpTexts: [
|
|
125
|
+
makeText("reference", "R1", 0, -1.5, "F.SilkS"),
|
|
126
|
+
makeText("value", "10k", 0, 1.5, "F.Fab"),
|
|
127
|
+
],
|
|
128
|
+
fpPads: [pad("1", -0.8, netGnd), pad("2", 0.8, netSignal)],
|
|
129
|
+
}),
|
|
130
|
+
],
|
|
131
|
+
})
|
|
126
132
|
|
|
127
133
|
await fs.writeFile("demo.kicad_pcb", pcb.getString())
|
|
128
134
|
```
|
|
@@ -143,28 +149,32 @@ import {
|
|
|
143
149
|
TextEffects,
|
|
144
150
|
} from "kicadts"
|
|
145
151
|
|
|
146
|
-
const footprint = new Footprint(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
152
|
+
const footprint = new Footprint({
|
|
153
|
+
libraryLink: "Demo:TestPad",
|
|
154
|
+
layer: "F.Cu",
|
|
155
|
+
position: [0, 0], // Array format
|
|
156
|
+
fpTexts: [
|
|
157
|
+
new FpText({
|
|
158
|
+
type: "reference",
|
|
159
|
+
text: "REF**",
|
|
160
|
+
position: { x: 0, y: -1.5 },
|
|
161
|
+
layer: "F.SilkS",
|
|
162
|
+
effects: new TextEffects({
|
|
163
|
+
font: { size: { height: 1, width: 1 }, thickness: 0.15 },
|
|
164
|
+
}),
|
|
165
|
+
}),
|
|
166
|
+
],
|
|
167
|
+
fpPads: [
|
|
168
|
+
new FootprintPad({
|
|
169
|
+
number: "1",
|
|
170
|
+
padType: "smd",
|
|
171
|
+
shape: "rect",
|
|
172
|
+
at: [0, 0], // You can also use { x, y } form
|
|
173
|
+
size: { width: 1.5, height: 1.5 },
|
|
174
|
+
layers: ["F.Cu", "F.Paste", "F.Mask"],
|
|
175
|
+
}),
|
|
176
|
+
],
|
|
177
|
+
})
|
|
168
178
|
|
|
169
179
|
await fs.writeFile("Demo_TestPad.kicad_mod", footprint.getString())
|
|
170
180
|
```
|
package/TODO.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# TODO: Ergonomic Constructors
|
|
2
|
+
|
|
3
|
+
The following classes need ergonomic constructors created (similar to the pattern in `KicadSch.ts`):
|
|
4
|
+
|
|
5
|
+
## Main Container Classes
|
|
6
|
+
|
|
7
|
+
- [x] **KicadSch** - `lib/sexpr/classes/KicadSch.ts`
|
|
8
|
+
- [ ] **Bus** - `lib/sexpr/classes/Bus.ts`
|
|
9
|
+
- [ ] **BusEntry** - `lib/sexpr/classes/BusEntry.ts`
|
|
10
|
+
- [ ] **Footprint** - `lib/sexpr/classes/Footprint.ts`
|
|
11
|
+
- [ ] **FootprintPad** - `lib/sexpr/classes/FootprintPad.ts`
|
|
12
|
+
- [ ] **FpArc** - `lib/sexpr/classes/FpArc.ts`
|
|
13
|
+
- [ ] **FpCircle** - `lib/sexpr/classes/FpCircle.ts`
|
|
14
|
+
- [ ] **FpLine** - `lib/sexpr/classes/FpLine.ts`
|
|
15
|
+
- [ ] **FpPoly** - `lib/sexpr/classes/FpPoly.ts`
|
|
16
|
+
- [ ] **FpRect** - `lib/sexpr/classes/FpRect.ts`
|
|
17
|
+
- [ ] **FpText** - `lib/sexpr/classes/FpText.ts`
|
|
18
|
+
- [ ] **FpTextBox** - `lib/sexpr/classes/FpTextBox.ts`
|
|
19
|
+
- [ ] **GrLine** - `lib/sexpr/classes/GrLine.ts`
|
|
20
|
+
- [ ] **GrText** - `lib/sexpr/classes/GrText.ts`
|
|
21
|
+
- [ ] **Image** - `lib/sexpr/classes/Image.ts`
|
|
22
|
+
- [ ] **Junction** - `lib/sexpr/classes/Junction.ts`
|
|
23
|
+
- [ ] **KicadPcb** - `lib/sexpr/classes/KicadPcb.ts`
|
|
24
|
+
- [ ] **Label** - `lib/sexpr/classes/Label.ts`
|
|
25
|
+
- [ ] **NoConnect** - `lib/sexpr/classes/NoConnect.ts`
|
|
26
|
+
- [ ] **PadPrimitiveGrArc** - `lib/sexpr/classes/PadPrimitiveGrArc.ts`
|
|
27
|
+
- [ ] **PadPrimitiveGrCircle** - `lib/sexpr/classes/PadPrimitiveGrCircle.ts`
|
|
28
|
+
- [ ] **Property** - `lib/sexpr/classes/Property.ts`
|
|
29
|
+
- [ ] **SchematicText** - `lib/sexpr/classes/SchematicText.ts`
|
|
30
|
+
- [ ] **Segment** - `lib/sexpr/classes/Segment.ts`
|
|
31
|
+
- [ ] **Sheet** - `lib/sexpr/classes/Sheet.ts`
|
|
32
|
+
- [ ] **Symbol** (SchematicSymbol) - `lib/sexpr/classes/Symbol.ts`
|
|
33
|
+
- [ ] **TextEffects** - `lib/sexpr/classes/TextEffects.ts`
|
|
34
|
+
- [ ] **TitleBlock** - `lib/sexpr/classes/TitleBlock.ts`
|
|
35
|
+
- [ ] **Via** - `lib/sexpr/classes/Via.ts`
|
|
36
|
+
- [ ] **Wire** - `lib/sexpr/classes/Wire.ts`
|
|
37
|
+
|
|
38
|
+
## Pattern Requirements
|
|
39
|
+
|
|
40
|
+
Each class needs:
|
|
41
|
+
1. A TypeScript interface `{ClassName}ConstructorParams` with optional properties
|
|
42
|
+
2. Properties should accept either primitive values (strings, numbers) OR SxClass wrapper objects
|
|
43
|
+
3. Constructor that accepts the params interface and handles both cases
|
|
44
|
+
4. Getter/setter pairs working with primitive values while storing SxClass objects internally
|
|
45
|
+
|
|
46
|
+
See `lib/sexpr/classes/KicadSch.ts` for reference implementation.
|
package/bunfig.toml
CHANGED
package/lib/sexpr/classes/At.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { SxClass } from "../base-classes/SxClass"
|
|
2
2
|
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
3
|
|
|
4
|
+
export type AtInput =
|
|
5
|
+
| At
|
|
6
|
+
| [x: number, y: number, angle?: number]
|
|
7
|
+
| { x: number; y: number; angle?: number }
|
|
8
|
+
|
|
4
9
|
export class At extends SxClass {
|
|
5
10
|
static override token = "at"
|
|
6
11
|
token = "at"
|
|
@@ -22,6 +27,16 @@ export class At extends SxClass {
|
|
|
22
27
|
y: number
|
|
23
28
|
angle?: number
|
|
24
29
|
|
|
30
|
+
static from(input: AtInput, opts: { isTextSymbol?: boolean } = {}): At {
|
|
31
|
+
if (input instanceof At) {
|
|
32
|
+
return input
|
|
33
|
+
}
|
|
34
|
+
if (Array.isArray(input)) {
|
|
35
|
+
return new At(input, opts)
|
|
36
|
+
}
|
|
37
|
+
return new At([input.x, input.y, input.angle], opts)
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
static override fromSexprPrimitives(primitiveSexprs: PrimitiveSExpr[]): At {
|
|
26
41
|
const [x, y, angle] = primitiveSexprs
|
|
27
42
|
return new At([x as number, y as number, angle as number])
|
package/lib/sexpr/classes/Bus.ts
CHANGED
|
@@ -6,6 +6,12 @@ import { Uuid } from "./Uuid"
|
|
|
6
6
|
|
|
7
7
|
const SUPPORTED_TOKENS = new Set(["pts", "stroke", "uuid"])
|
|
8
8
|
|
|
9
|
+
export interface BusConstructorParams {
|
|
10
|
+
points?: Pts
|
|
11
|
+
stroke?: Stroke
|
|
12
|
+
uuid?: string | Uuid
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
export class Bus extends SxClass {
|
|
10
16
|
static override token = "bus"
|
|
11
17
|
static override parentToken = "kicad_sch"
|
|
@@ -15,9 +21,23 @@ export class Bus extends SxClass {
|
|
|
15
21
|
private _sxStroke?: Stroke
|
|
16
22
|
private _sxUuid?: Uuid
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
constructor(params: BusConstructorParams = {}) {
|
|
25
|
+
super()
|
|
26
|
+
|
|
27
|
+
if (params.points !== undefined) {
|
|
28
|
+
this.points = params.points
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (params.stroke !== undefined) {
|
|
32
|
+
this.stroke = params.stroke
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (params.uuid !== undefined) {
|
|
36
|
+
this.uuid = params.uuid
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static override fromSexprPrimitives(primitiveSexprs: PrimitiveSExpr[]): Bus {
|
|
21
41
|
const bus = new Bus()
|
|
22
42
|
|
|
23
43
|
const { propertyMap, arrayPropertyMap } =
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { SxClass } from "../base-classes/SxClass"
|
|
2
2
|
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
-
import { At } from "./At"
|
|
3
|
+
import { At, type AtInput } from "./At"
|
|
4
4
|
import { Stroke } from "./Stroke"
|
|
5
5
|
import { Uuid } from "./Uuid"
|
|
6
6
|
|
|
7
7
|
const SUPPORTED_TOKENS = new Set(["at", "size", "stroke", "uuid"])
|
|
8
8
|
|
|
9
|
+
export interface BusEntryConstructorParams {
|
|
10
|
+
at?: AtInput
|
|
11
|
+
size?: BusEntrySize | { x: number; y: number }
|
|
12
|
+
stroke?: Stroke
|
|
13
|
+
uuid?: string | Uuid
|
|
14
|
+
}
|
|
15
|
+
|
|
9
16
|
export class BusEntry extends SxClass {
|
|
10
17
|
static override token = "bus_entry"
|
|
11
18
|
static override parentToken = "kicad_sch"
|
|
@@ -16,6 +23,26 @@ export class BusEntry extends SxClass {
|
|
|
16
23
|
private _sxStroke?: Stroke
|
|
17
24
|
private _sxUuid?: Uuid
|
|
18
25
|
|
|
26
|
+
constructor(params: BusEntryConstructorParams = {}) {
|
|
27
|
+
super()
|
|
28
|
+
|
|
29
|
+
if (params.at !== undefined) {
|
|
30
|
+
this.at = params.at
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (params.size !== undefined) {
|
|
34
|
+
this.size = params.size
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (params.stroke !== undefined) {
|
|
38
|
+
this.stroke = params.stroke
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (params.uuid !== undefined) {
|
|
42
|
+
this.uuid = params.uuid
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
19
46
|
static override fromSexprPrimitives(
|
|
20
47
|
primitiveSexprs: PrimitiveSExpr[],
|
|
21
48
|
): BusEntry {
|
|
@@ -52,8 +79,8 @@ export class BusEntry extends SxClass {
|
|
|
52
79
|
return this._sxAt
|
|
53
80
|
}
|
|
54
81
|
|
|
55
|
-
set at(value:
|
|
56
|
-
this._sxAt = value
|
|
82
|
+
set at(value: AtInput | undefined) {
|
|
83
|
+
this._sxAt = value !== undefined ? At.from(value) : undefined
|
|
57
84
|
}
|
|
58
85
|
|
|
59
86
|
get size(): { x: number; y: number } | undefined {
|
|
@@ -41,9 +41,7 @@ export class EmbeddedFonts extends SxClass {
|
|
|
41
41
|
if (normalized === "no") {
|
|
42
42
|
return new EmbeddedFonts(false)
|
|
43
43
|
}
|
|
44
|
-
throw new Error(
|
|
45
|
-
`embedded_fonts expects "yes" or "no", received "${raw}"`,
|
|
46
|
-
)
|
|
44
|
+
throw new Error(`embedded_fonts expects "yes" or "no", received "${raw}"`)
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
throw new Error(
|