kicadts 0.0.1
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/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
- package/.vscode/settings.json +16 -0
- package/AGENTS.md +30 -0
- package/README.md +206 -0
- package/biome.json +93 -0
- package/bun.lock +48 -0
- package/bunfig.toml +5 -0
- package/lib/index.ts +1 -0
- package/lib/sexpr/base-classes/SxClass.ts +164 -0
- package/lib/sexpr/base-classes/SxPrimitiveBoolean.ts +35 -0
- package/lib/sexpr/base-classes/SxPrimitiveNumber.ts +26 -0
- package/lib/sexpr/base-classes/SxPrimitiveString.ts +26 -0
- package/lib/sexpr/classes/At.ts +38 -0
- package/lib/sexpr/classes/Bus.ts +83 -0
- package/lib/sexpr/classes/BusEntry.ts +142 -0
- package/lib/sexpr/classes/Color.ts +29 -0
- package/lib/sexpr/classes/Dnp.ts +8 -0
- package/lib/sexpr/classes/EmbeddedFonts.ts +70 -0
- package/lib/sexpr/classes/ExcludeFromSim.ts +8 -0
- package/lib/sexpr/classes/FieldsAutoplaced.ts +8 -0
- package/lib/sexpr/classes/Footprint.ts +719 -0
- package/lib/sexpr/classes/FootprintAttr.ts +102 -0
- package/lib/sexpr/classes/FootprintAutoplaceCost180.ts +9 -0
- package/lib/sexpr/classes/FootprintAutoplaceCost90.ts +9 -0
- package/lib/sexpr/classes/FootprintClearance.ts +9 -0
- package/lib/sexpr/classes/FootprintDescr.ts +44 -0
- package/lib/sexpr/classes/FootprintLocked.ts +32 -0
- package/lib/sexpr/classes/FootprintModel.ts +145 -0
- package/lib/sexpr/classes/FootprintNetTiePadGroups.ts +50 -0
- package/lib/sexpr/classes/FootprintPad.ts +705 -0
- package/lib/sexpr/classes/FootprintPath.ts +44 -0
- package/lib/sexpr/classes/FootprintPlaced.ts +32 -0
- package/lib/sexpr/classes/FootprintPrivateLayers.ts +56 -0
- package/lib/sexpr/classes/FootprintSheetfile.ts +44 -0
- package/lib/sexpr/classes/FootprintSheetname.ts +44 -0
- package/lib/sexpr/classes/FootprintSolderMaskMargin.ts +9 -0
- package/lib/sexpr/classes/FootprintSolderPasteMargin.ts +9 -0
- package/lib/sexpr/classes/FootprintSolderPasteRatio.ts +9 -0
- package/lib/sexpr/classes/FootprintTags.ts +44 -0
- package/lib/sexpr/classes/FootprintTedit.ts +21 -0
- package/lib/sexpr/classes/FootprintThermalGap.ts +9 -0
- package/lib/sexpr/classes/FootprintThermalWidth.ts +9 -0
- package/lib/sexpr/classes/FootprintZoneConnect.ts +9 -0
- package/lib/sexpr/classes/FpArc.ts +289 -0
- package/lib/sexpr/classes/FpCircle.ts +293 -0
- package/lib/sexpr/classes/FpLine.ts +288 -0
- package/lib/sexpr/classes/FpPoly.ts +266 -0
- package/lib/sexpr/classes/FpPolyFill.ts +48 -0
- package/lib/sexpr/classes/FpPolyLocked.ts +40 -0
- package/lib/sexpr/classes/FpRect.ts +293 -0
- package/lib/sexpr/classes/FpText.ts +341 -0
- package/lib/sexpr/classes/FpTextBox.ts +412 -0
- package/lib/sexpr/classes/GrLine.ts +245 -0
- package/lib/sexpr/classes/GrLineAngle.ts +32 -0
- package/lib/sexpr/classes/GrLineEnd.ts +61 -0
- package/lib/sexpr/classes/GrLineLocked.ts +40 -0
- package/lib/sexpr/classes/GrLineStart.ts +61 -0
- package/lib/sexpr/classes/GrText.ts +202 -0
- package/lib/sexpr/classes/Image.ts +256 -0
- package/lib/sexpr/classes/InBom.ts +8 -0
- package/lib/sexpr/classes/Junction.ts +134 -0
- package/lib/sexpr/classes/KicadPcb.ts +313 -0
- package/lib/sexpr/classes/KicadSch.ts +303 -0
- package/lib/sexpr/classes/KicadSchGenerator.ts +32 -0
- package/lib/sexpr/classes/KicadSchGeneratorVersion.ts +30 -0
- package/lib/sexpr/classes/KicadSchVersion.ts +22 -0
- package/lib/sexpr/classes/Label.ts +136 -0
- package/lib/sexpr/classes/Layer.ts +51 -0
- package/lib/sexpr/classes/Layers.ts +47 -0
- package/lib/sexpr/classes/LibSymbols.ts +61 -0
- package/lib/sexpr/classes/NoConnect.ts +73 -0
- package/lib/sexpr/classes/OnBoard.ts +8 -0
- package/lib/sexpr/classes/PadChamfer.ts +50 -0
- package/lib/sexpr/classes/PadChamferRatio.ts +9 -0
- package/lib/sexpr/classes/PadClearance.ts +9 -0
- package/lib/sexpr/classes/PadDieLength.ts +9 -0
- package/lib/sexpr/classes/PadDrill.ts +145 -0
- package/lib/sexpr/classes/PadDrillOffset.ts +54 -0
- package/lib/sexpr/classes/PadLayers.ts +59 -0
- package/lib/sexpr/classes/PadNet.ts +56 -0
- package/lib/sexpr/classes/PadOptions.ts +182 -0
- package/lib/sexpr/classes/PadPinFunction.ts +9 -0
- package/lib/sexpr/classes/PadPinType.ts +9 -0
- package/lib/sexpr/classes/PadPrimitiveGrArc.ts +254 -0
- package/lib/sexpr/classes/PadPrimitiveGrCircle.ts +279 -0
- package/lib/sexpr/classes/PadPrimitiveGrLine.ts +126 -0
- package/lib/sexpr/classes/PadPrimitives.ts +289 -0
- package/lib/sexpr/classes/PadRectDelta.ts +57 -0
- package/lib/sexpr/classes/PadRoundrectRratio.ts +9 -0
- package/lib/sexpr/classes/PadSize.ts +54 -0
- package/lib/sexpr/classes/PadSolderMaskMargin.ts +9 -0
- package/lib/sexpr/classes/PadSolderPasteMargin.ts +9 -0
- package/lib/sexpr/classes/PadSolderPasteMarginRatio.ts +9 -0
- package/lib/sexpr/classes/PadTeardrops.ts +208 -0
- package/lib/sexpr/classes/PadThermalBridgeAngle.ts +9 -0
- package/lib/sexpr/classes/PadThermalGap.ts +9 -0
- package/lib/sexpr/classes/PadThermalWidth.ts +9 -0
- package/lib/sexpr/classes/PadZoneConnect.ts +9 -0
- package/lib/sexpr/classes/Paper.ts +119 -0
- package/lib/sexpr/classes/PcbGeneral.ts +75 -0
- package/lib/sexpr/classes/PcbGeneralLegacyTeardrops.ts +44 -0
- package/lib/sexpr/classes/PcbGeneralThickness.ts +9 -0
- package/lib/sexpr/classes/PcbGenerator.ts +16 -0
- package/lib/sexpr/classes/PcbGeneratorVersion.ts +16 -0
- package/lib/sexpr/classes/PcbLayerDefinition.ts +102 -0
- package/lib/sexpr/classes/PcbLayers.ts +34 -0
- package/lib/sexpr/classes/PcbNet.ts +56 -0
- package/lib/sexpr/classes/PcbVersion.ts +9 -0
- package/lib/sexpr/classes/Property.ts +246 -0
- package/lib/sexpr/classes/PropertyHide.ts +9 -0
- package/lib/sexpr/classes/PropertyUnlocked.ts +9 -0
- package/lib/sexpr/classes/Pts.ts +65 -0
- package/lib/sexpr/classes/RenderCache.ts +221 -0
- package/lib/sexpr/classes/SchematicText.ts +141 -0
- package/lib/sexpr/classes/Segment.ts +222 -0
- package/lib/sexpr/classes/SegmentEnd.ts +59 -0
- package/lib/sexpr/classes/SegmentLocked.ts +33 -0
- package/lib/sexpr/classes/SegmentNet.ts +62 -0
- package/lib/sexpr/classes/SegmentStart.ts +59 -0
- package/lib/sexpr/classes/Setup/PcbPlotParams.ts +729 -0
- package/lib/sexpr/classes/Setup/PcbPlotParamsBase.ts +9 -0
- package/lib/sexpr/classes/Setup/PcbPlotParamsNumericProperties.ts +105 -0
- package/lib/sexpr/classes/Setup/PcbPlotParamsStringPropertiesA.ts +104 -0
- package/lib/sexpr/classes/Setup/PcbPlotParamsStringPropertiesB.ts +105 -0
- package/lib/sexpr/classes/Setup/Setup.ts +573 -0
- package/lib/sexpr/classes/Setup/SetupPropertyTypes.ts +119 -0
- package/lib/sexpr/classes/Setup/Stackup.ts +140 -0
- package/lib/sexpr/classes/Setup/StackupLayer.ts +233 -0
- package/lib/sexpr/classes/Setup/StackupLayerProperties.ts +78 -0
- package/lib/sexpr/classes/Setup/StackupProperties.ts +41 -0
- package/lib/sexpr/classes/Setup/base.ts +167 -0
- package/lib/sexpr/classes/Setup/index.ts +14 -0
- package/lib/sexpr/classes/Setup/setupMultiValueProperties.ts +54 -0
- package/lib/sexpr/classes/Setup/setupNumericProperties.ts +151 -0
- package/lib/sexpr/classes/Setup/setupPropertyHandlers.ts +90 -0
- package/lib/sexpr/classes/Setup/setupStringProperties.ts +75 -0
- package/lib/sexpr/classes/Sheet.ts +205 -0
- package/lib/sexpr/classes/SheetFill.ts +44 -0
- package/lib/sexpr/classes/SheetInstances.ts +168 -0
- package/lib/sexpr/classes/SheetInstancesRoot.ts +165 -0
- package/lib/sexpr/classes/SheetPin.ts +122 -0
- package/lib/sexpr/classes/SheetProperty.ts +115 -0
- package/lib/sexpr/classes/SheetSize.ts +44 -0
- package/lib/sexpr/classes/Stroke.ts +58 -0
- package/lib/sexpr/classes/StrokeType.ts +34 -0
- package/lib/sexpr/classes/Symbol.ts +1541 -0
- package/lib/sexpr/classes/TextEffects.ts +444 -0
- package/lib/sexpr/classes/TitleBlock.ts +352 -0
- package/lib/sexpr/classes/Unit.ts +28 -0
- package/lib/sexpr/classes/Uuid.ts +8 -0
- package/lib/sexpr/classes/Via.ts +328 -0
- package/lib/sexpr/classes/ViaNet.ts +59 -0
- package/lib/sexpr/classes/Width.ts +8 -0
- package/lib/sexpr/classes/Wire.ts +91 -0
- package/lib/sexpr/classes/Xy.ts +35 -0
- package/lib/sexpr/classes/Zone.ts +41 -0
- package/lib/sexpr/index.ts +130 -0
- package/lib/sexpr/parseKicadSexpr.ts +5 -0
- package/lib/sexpr/parseToPrimitiveSExpr.ts +240 -0
- package/lib/sexpr/utils/indentLines.ts +3 -0
- package/lib/sexpr/utils/parseYesNo.ts +12 -0
- package/lib/sexpr/utils/quoteSExprString.ts +8 -0
- package/lib/sexpr/utils/strokeFromArgs.ts +19 -0
- package/lib/sexpr/utils/toNumberValue.ts +13 -0
- package/lib/sexpr/utils/toStringValue.ts +10 -0
- package/package.json +26 -0
- package/scripts/download-references.ts +66 -0
- package/tests/fixtures/expectEqualPrimitiveSExpr.ts +200 -0
- package/tests/sexpr/KicadPcbDemos.test.ts +48 -0
- package/tests/sexpr/KicadSchDemos.test.ts +49 -0
- package/tests/sexpr/classes/Footprint.test.ts +277 -0
- package/tests/sexpr/classes/FootprintPad.test.ts +71 -0
- package/tests/sexpr/classes/FpArc.test.ts +45 -0
- package/tests/sexpr/classes/FpCircle.test.ts +39 -0
- package/tests/sexpr/classes/FpPoly.test.ts +43 -0
- package/tests/sexpr/classes/FpRect.test.ts +40 -0
- package/tests/sexpr/classes/FpTextBox.test.ts +84 -0
- package/tests/sexpr/classes/Image.test.ts +50 -0
- package/tests/sexpr/classes/KicadSch.test.ts +97 -0
- package/tests/sexpr/classes/Paper.test.ts +30 -0
- package/tests/sexpr/classes/Property.test.ts +48 -0
- package/tests/sexpr/classes/Setup.test.ts +189 -0
- package/tests/sexpr/classes/Sheet.test.ts +107 -0
- package/tests/sexpr/classes/Stroke.test.ts +15 -0
- package/tests/sexpr/classes/Symbol.test.ts +96 -0
- package/tests/sexpr/classes/TextEffects.test.ts +56 -0
- package/tests/sexpr/classes/TitleBlock.test.ts +40 -0
- package/tsconfig.json +35 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { At } from "./At"
|
|
4
|
+
import { Uuid } from "./Uuid"
|
|
5
|
+
|
|
6
|
+
const SUPPORTED_TOKENS = new Set(["at", "uuid"])
|
|
7
|
+
|
|
8
|
+
export class NoConnect extends SxClass {
|
|
9
|
+
static override token = "no_connect"
|
|
10
|
+
static override parentToken = "kicad_sch"
|
|
11
|
+
override token = "no_connect"
|
|
12
|
+
|
|
13
|
+
private _sxAt?: At
|
|
14
|
+
private _sxUuid?: Uuid
|
|
15
|
+
|
|
16
|
+
static override fromSexprPrimitives(
|
|
17
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
18
|
+
): NoConnect {
|
|
19
|
+
const noConnect = new NoConnect()
|
|
20
|
+
|
|
21
|
+
const { propertyMap, arrayPropertyMap } =
|
|
22
|
+
SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
|
|
23
|
+
|
|
24
|
+
if (Object.keys(arrayPropertyMap).length > 0) {
|
|
25
|
+
const tokens = Object.keys(arrayPropertyMap).join(", ")
|
|
26
|
+
throw new Error(
|
|
27
|
+
`no_connect does not support repeated child tokens: ${tokens}`,
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const unsupportedTokens = Object.keys(propertyMap).filter(
|
|
32
|
+
(token) => !SUPPORTED_TOKENS.has(token),
|
|
33
|
+
)
|
|
34
|
+
if (unsupportedTokens.length > 0) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`Unsupported child tokens inside no_connect expression: ${unsupportedTokens.join(", ")}`,
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
noConnect._sxAt = propertyMap.at as At | undefined
|
|
41
|
+
noConnect._sxUuid = propertyMap.uuid as Uuid | undefined
|
|
42
|
+
|
|
43
|
+
return noConnect
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get at(): At | undefined {
|
|
47
|
+
return this._sxAt
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
set at(value: At | undefined) {
|
|
51
|
+
this._sxAt = value
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get uuid(): Uuid | undefined {
|
|
55
|
+
return this._sxUuid
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
set uuid(value: Uuid | string | undefined) {
|
|
59
|
+
if (value === undefined) {
|
|
60
|
+
this._sxUuid = undefined
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
this._sxUuid = value instanceof Uuid ? value : new Uuid(value)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
override getChildren(): SxClass[] {
|
|
67
|
+
const children: SxClass[] = []
|
|
68
|
+
if (this._sxAt) children.push(this._sxAt)
|
|
69
|
+
if (this._sxUuid) children.push(this._sxUuid)
|
|
70
|
+
return children
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
SxClass.register(NoConnect)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import { SxPrimitiveBoolean } from "../base-classes/SxPrimitiveBoolean"
|
|
3
|
+
|
|
4
|
+
export class OnBoard extends SxPrimitiveBoolean {
|
|
5
|
+
static override token = "on_board"
|
|
6
|
+
token = "on_board"
|
|
7
|
+
}
|
|
8
|
+
SxClass.register(OnBoard)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { printSExpr } from "../parseToPrimitiveSExpr"
|
|
4
|
+
import { toStringValue } from "../utils/toStringValue"
|
|
5
|
+
|
|
6
|
+
export class PadChamfer extends SxClass {
|
|
7
|
+
static override token = "chamfer"
|
|
8
|
+
static override parentToken = "pad"
|
|
9
|
+
token = "chamfer"
|
|
10
|
+
|
|
11
|
+
private _corners: string[] = []
|
|
12
|
+
|
|
13
|
+
constructor(corners: string[]) {
|
|
14
|
+
super()
|
|
15
|
+
this.corners = corners
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static override fromSexprPrimitives(
|
|
19
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
20
|
+
): PadChamfer {
|
|
21
|
+
const corners = primitiveSexprs.map((primitive) => {
|
|
22
|
+
const corner = toStringValue(primitive)
|
|
23
|
+
if (corner === undefined) {
|
|
24
|
+
return printSExpr(primitive)
|
|
25
|
+
}
|
|
26
|
+
return corner
|
|
27
|
+
})
|
|
28
|
+
return new PadChamfer(corners)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get corners(): string[] {
|
|
32
|
+
return [...this._corners]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
set corners(values: string[]) {
|
|
36
|
+
this._corners = values.map((value) => String(value))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override getChildren(): SxClass[] {
|
|
40
|
+
return []
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override getString(): string {
|
|
44
|
+
if (this._corners.length === 0) {
|
|
45
|
+
return "(chamfer)"
|
|
46
|
+
}
|
|
47
|
+
return `(chamfer ${this._corners.join(" ")})`
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
SxClass.register(PadChamfer)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
|
|
2
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
3
|
+
|
|
4
|
+
export class PadChamferRatio extends SxPrimitiveNumber {
|
|
5
|
+
static override token = "chamfer_ratio"
|
|
6
|
+
static override parentToken = "pad"
|
|
7
|
+
token = "chamfer_ratio"
|
|
8
|
+
}
|
|
9
|
+
SxClass.register(PadChamferRatio)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
|
|
2
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
3
|
+
|
|
4
|
+
export class PadClearance extends SxPrimitiveNumber {
|
|
5
|
+
static override token = "clearance"
|
|
6
|
+
static override parentToken = "pad"
|
|
7
|
+
token = "clearance"
|
|
8
|
+
}
|
|
9
|
+
SxClass.register(PadClearance)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
|
|
2
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
3
|
+
|
|
4
|
+
export class PadDieLength extends SxPrimitiveNumber {
|
|
5
|
+
static override token = "die_length"
|
|
6
|
+
static override parentToken = "pad"
|
|
7
|
+
token = "die_length"
|
|
8
|
+
}
|
|
9
|
+
SxClass.register(PadDieLength)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { printSExpr } from "../parseToPrimitiveSExpr"
|
|
4
|
+
import { toNumberValue } from "../utils/toNumberValue"
|
|
5
|
+
import { PadDrillOffset } from "./PadDrillOffset"
|
|
6
|
+
|
|
7
|
+
export class PadDrill extends SxClass {
|
|
8
|
+
static override token = "drill"
|
|
9
|
+
static override parentToken = "pad"
|
|
10
|
+
token = "drill"
|
|
11
|
+
|
|
12
|
+
private _oval = false
|
|
13
|
+
private _diameter: number
|
|
14
|
+
private _width?: number
|
|
15
|
+
private _sxOffset?: PadDrillOffset
|
|
16
|
+
|
|
17
|
+
constructor({
|
|
18
|
+
oval = false,
|
|
19
|
+
diameter,
|
|
20
|
+
width,
|
|
21
|
+
offset,
|
|
22
|
+
}: {
|
|
23
|
+
oval?: boolean
|
|
24
|
+
diameter: number
|
|
25
|
+
width?: number
|
|
26
|
+
offset?: PadDrillOffset | { x: number; y: number }
|
|
27
|
+
}) {
|
|
28
|
+
super()
|
|
29
|
+
this._oval = oval
|
|
30
|
+
this._diameter = diameter
|
|
31
|
+
this._width = width
|
|
32
|
+
if (offset instanceof PadDrillOffset) {
|
|
33
|
+
this._sxOffset = offset
|
|
34
|
+
} else if (offset) {
|
|
35
|
+
this._sxOffset = new PadDrillOffset(offset.x, offset.y)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static override fromSexprPrimitives(
|
|
40
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
41
|
+
): PadDrill {
|
|
42
|
+
const remaining = [...primitiveSexprs]
|
|
43
|
+
let oval = false
|
|
44
|
+
if (remaining[0] === "oval") {
|
|
45
|
+
oval = true
|
|
46
|
+
remaining.shift()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const diameter = toNumberValue(remaining.shift())
|
|
50
|
+
if (diameter === undefined) {
|
|
51
|
+
throw new Error("drill requires a diameter value")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let width: number | undefined
|
|
55
|
+
const potentialWidth = toNumberValue(remaining[0])
|
|
56
|
+
if (potentialWidth !== undefined) {
|
|
57
|
+
width = potentialWidth
|
|
58
|
+
remaining.shift()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const drill = new PadDrill({ oval, diameter, width })
|
|
62
|
+
|
|
63
|
+
for (const primitive of remaining) {
|
|
64
|
+
if (!Array.isArray(primitive)) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
`drill encountered unexpected primitive child: ${JSON.stringify(primitive)}`,
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
const parsed = SxClass.parsePrimitiveSexpr(primitive, {
|
|
70
|
+
parentToken: this.token,
|
|
71
|
+
})
|
|
72
|
+
if (!(parsed instanceof PadDrillOffset)) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`drill encountered unsupported child token: ${printSExpr(primitive)}`,
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
if (drill._sxOffset) {
|
|
78
|
+
throw new Error("drill does not support multiple offset children")
|
|
79
|
+
}
|
|
80
|
+
drill._sxOffset = parsed
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return drill
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
get oval(): boolean {
|
|
87
|
+
return this._oval
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
set oval(value: boolean) {
|
|
91
|
+
this._oval = value
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get diameter(): number {
|
|
95
|
+
return this._diameter
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
set diameter(value: number) {
|
|
99
|
+
this._diameter = value
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
get width(): number | undefined {
|
|
103
|
+
return this._width
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
set width(value: number | undefined) {
|
|
107
|
+
this._width = value
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
get offset(): PadDrillOffset | undefined {
|
|
111
|
+
return this._sxOffset
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
set offset(value: PadDrillOffset | { x: number; y: number } | undefined) {
|
|
115
|
+
if (value === undefined) {
|
|
116
|
+
this._sxOffset = undefined
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
this._sxOffset =
|
|
120
|
+
value instanceof PadDrillOffset
|
|
121
|
+
? value
|
|
122
|
+
: new PadDrillOffset(value.x, value.y)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
override getChildren(): SxClass[] {
|
|
126
|
+
return this._sxOffset ? [this._sxOffset] : []
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
override getString(): string {
|
|
130
|
+
const tokens: string[] = []
|
|
131
|
+
if (this._oval) tokens.push("oval")
|
|
132
|
+
tokens.push(String(this._diameter))
|
|
133
|
+
if (this._width !== undefined) tokens.push(String(this._width))
|
|
134
|
+
|
|
135
|
+
if (!this._sxOffset) {
|
|
136
|
+
return `(drill ${tokens.join(" ")})`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const lines = [`(drill ${tokens.join(" ")}`]
|
|
140
|
+
lines.push(this._sxOffset.getStringIndented())
|
|
141
|
+
lines.push(")")
|
|
142
|
+
return lines.join("\n")
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
SxClass.register(PadDrill)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { toNumberValue } from "../utils/toNumberValue"
|
|
4
|
+
|
|
5
|
+
export class PadDrillOffset extends SxClass {
|
|
6
|
+
static override token = "offset"
|
|
7
|
+
static override parentToken = "drill"
|
|
8
|
+
token = "offset"
|
|
9
|
+
|
|
10
|
+
private _x: number
|
|
11
|
+
private _y: number
|
|
12
|
+
|
|
13
|
+
constructor(x: number, y: number) {
|
|
14
|
+
super()
|
|
15
|
+
this._x = x
|
|
16
|
+
this._y = y
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static override fromSexprPrimitives(
|
|
20
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
21
|
+
): PadDrillOffset {
|
|
22
|
+
const x = toNumberValue(primitiveSexprs[0])
|
|
23
|
+
const y = toNumberValue(primitiveSexprs[1])
|
|
24
|
+
if (x === undefined || y === undefined) {
|
|
25
|
+
throw new Error("drill offset requires x and y numeric values")
|
|
26
|
+
}
|
|
27
|
+
return new PadDrillOffset(x, y)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get x(): number {
|
|
31
|
+
return this._x
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
set x(value: number) {
|
|
35
|
+
this._x = value
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get y(): number {
|
|
39
|
+
return this._y
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
set y(value: number) {
|
|
43
|
+
this._y = value
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
override getChildren(): SxClass[] {
|
|
47
|
+
return []
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
override getString(): string {
|
|
51
|
+
return `(offset ${this._x} ${this._y})`
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
SxClass.register(PadDrillOffset)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { printSExpr } from "../parseToPrimitiveSExpr"
|
|
4
|
+
import { quoteSExprString } from "../utils/quoteSExprString"
|
|
5
|
+
import { toStringValue } from "../utils/toStringValue"
|
|
6
|
+
|
|
7
|
+
export class PadLayers extends SxClass {
|
|
8
|
+
static override token = "layers"
|
|
9
|
+
static override parentToken = "pad"
|
|
10
|
+
token = "layers"
|
|
11
|
+
|
|
12
|
+
private _layers: string[] = []
|
|
13
|
+
|
|
14
|
+
constructor(layers: string[]) {
|
|
15
|
+
super()
|
|
16
|
+
this.layers = layers
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static override fromSexprPrimitives(
|
|
20
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
21
|
+
): PadLayers {
|
|
22
|
+
const layers = primitiveSexprs.map((primitive) => {
|
|
23
|
+
const value = toStringValue(primitive)
|
|
24
|
+
if (value === undefined) {
|
|
25
|
+
return printSExpr(primitive)
|
|
26
|
+
}
|
|
27
|
+
return value
|
|
28
|
+
})
|
|
29
|
+
return new PadLayers(layers)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get layers(): string[] {
|
|
33
|
+
return [...this._layers]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
set layers(values: string[]) {
|
|
37
|
+
this._layers = values.map((value) => String(value))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override getChildren(): SxClass[] {
|
|
41
|
+
return []
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override getString(): string {
|
|
45
|
+
if (this._layers.length === 0) {
|
|
46
|
+
return "(layers)"
|
|
47
|
+
}
|
|
48
|
+
const rendered = this._layers
|
|
49
|
+
.map((layer) => {
|
|
50
|
+
if (/^[^\s()"]+$/u.test(layer) && !["nil", "#t", "#f"].includes(layer)) {
|
|
51
|
+
return layer
|
|
52
|
+
}
|
|
53
|
+
return quoteSExprString(layer)
|
|
54
|
+
})
|
|
55
|
+
.join(" ")
|
|
56
|
+
return `(layers ${rendered})`
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
SxClass.register(PadLayers)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { quoteSExprString } from "../utils/quoteSExprString"
|
|
4
|
+
import { toNumberValue } from "../utils/toNumberValue"
|
|
5
|
+
import { toStringValue } from "../utils/toStringValue"
|
|
6
|
+
|
|
7
|
+
export class PadNet extends SxClass {
|
|
8
|
+
static override token = "net"
|
|
9
|
+
static override parentToken = "pad"
|
|
10
|
+
token = "net"
|
|
11
|
+
|
|
12
|
+
private _id: number
|
|
13
|
+
private _name: string
|
|
14
|
+
|
|
15
|
+
constructor(id: number, name: string) {
|
|
16
|
+
super()
|
|
17
|
+
this._id = id
|
|
18
|
+
this._name = name
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static override fromSexprPrimitives(
|
|
22
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
23
|
+
): PadNet {
|
|
24
|
+
const id = toNumberValue(primitiveSexprs[0])
|
|
25
|
+
const name = toStringValue(primitiveSexprs[1])
|
|
26
|
+
if (id === undefined || name === undefined) {
|
|
27
|
+
throw new Error("pad net requires numeric id and string name")
|
|
28
|
+
}
|
|
29
|
+
return new PadNet(id, name)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get id(): number {
|
|
33
|
+
return this._id
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
set id(value: number) {
|
|
37
|
+
this._id = value
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get name(): string {
|
|
41
|
+
return this._name
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
set name(value: string) {
|
|
45
|
+
this._name = value
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override getChildren(): SxClass[] {
|
|
49
|
+
return []
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override getString(): string {
|
|
53
|
+
return `(net ${this._id} ${quoteSExprString(this._name)})`
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
SxClass.register(PadNet)
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { toStringValue } from "../utils/toStringValue"
|
|
4
|
+
|
|
5
|
+
export type PadOptionsClearanceType = "outline" | "convexhull"
|
|
6
|
+
export type PadOptionsAnchorShape = "rect" | "circle"
|
|
7
|
+
|
|
8
|
+
const CLEARANCE_TYPES: PadOptionsClearanceType[] = [
|
|
9
|
+
"outline",
|
|
10
|
+
"convexhull",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
const ANCHOR_SHAPES: PadOptionsAnchorShape[] = ["rect", "circle"]
|
|
14
|
+
|
|
15
|
+
export class PadOptions extends SxClass {
|
|
16
|
+
static override token = "options"
|
|
17
|
+
static override parentToken = "pad"
|
|
18
|
+
override token = "options"
|
|
19
|
+
|
|
20
|
+
private _sxClearance?: PadOptionsClearance
|
|
21
|
+
private _sxAnchor?: PadOptionsAnchor
|
|
22
|
+
|
|
23
|
+
static override fromSexprPrimitives(
|
|
24
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
25
|
+
): PadOptions {
|
|
26
|
+
const options = new PadOptions()
|
|
27
|
+
|
|
28
|
+
for (const primitive of primitiveSexprs) {
|
|
29
|
+
if (!Array.isArray(primitive) || primitive.length === 0) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`pad options encountered invalid child expression: ${JSON.stringify(primitive)}`,
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const parsed = SxClass.parsePrimitiveSexpr(primitive, {
|
|
36
|
+
parentToken: this.token,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
if (!(parsed instanceof SxClass)) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`pad options child did not resolve to an SxClass: ${JSON.stringify(primitive)}`,
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (parsed instanceof PadOptionsClearance) {
|
|
46
|
+
if (options._sxClearance) {
|
|
47
|
+
throw new Error("pad options encountered duplicate clearance tokens")
|
|
48
|
+
}
|
|
49
|
+
options._sxClearance = parsed
|
|
50
|
+
continue
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (parsed instanceof PadOptionsAnchor) {
|
|
54
|
+
if (options._sxAnchor) {
|
|
55
|
+
throw new Error("pad options encountered duplicate anchor tokens")
|
|
56
|
+
}
|
|
57
|
+
options._sxAnchor = parsed
|
|
58
|
+
continue
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
throw new Error(`pad options encountered unsupported token "${parsed.token}"`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return options
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get clearance(): PadOptionsClearanceType | undefined {
|
|
68
|
+
return this._sxClearance?.type
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
set clearance(value: PadOptionsClearanceType | undefined) {
|
|
72
|
+
this._sxClearance = value ? new PadOptionsClearance(value) : undefined
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get anchor(): PadOptionsAnchorShape | undefined {
|
|
76
|
+
return this._sxAnchor?.shape
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set anchor(value: PadOptionsAnchorShape | undefined) {
|
|
80
|
+
this._sxAnchor = value ? new PadOptionsAnchor(value) : undefined
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
override getChildren(): SxClass[] {
|
|
84
|
+
const children: SxClass[] = []
|
|
85
|
+
if (this._sxClearance) children.push(this._sxClearance)
|
|
86
|
+
if (this._sxAnchor) children.push(this._sxAnchor)
|
|
87
|
+
return children
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
SxClass.register(PadOptions)
|
|
91
|
+
|
|
92
|
+
class PadOptionsClearance extends SxClass {
|
|
93
|
+
static override token = "clearance"
|
|
94
|
+
static override parentToken = "options"
|
|
95
|
+
override token = "clearance"
|
|
96
|
+
|
|
97
|
+
private _type: PadOptionsClearanceType
|
|
98
|
+
|
|
99
|
+
constructor(type: PadOptionsClearanceType) {
|
|
100
|
+
super()
|
|
101
|
+
this._type = type
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static override fromSexprPrimitives(
|
|
105
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
106
|
+
): PadOptionsClearance {
|
|
107
|
+
const [raw] = primitiveSexprs
|
|
108
|
+
const stringValue = toStringValue(raw)
|
|
109
|
+
if (stringValue === undefined) {
|
|
110
|
+
throw new Error("pad options clearance requires a string value")
|
|
111
|
+
}
|
|
112
|
+
if (!CLEARANCE_TYPES.includes(stringValue as PadOptionsClearanceType)) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`pad options clearance must be one of ${CLEARANCE_TYPES.join(", ")}`,
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
return new PadOptionsClearance(stringValue as PadOptionsClearanceType)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
get type(): PadOptionsClearanceType {
|
|
121
|
+
return this._type
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
set type(value: PadOptionsClearanceType) {
|
|
125
|
+
this._type = value
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
override getChildren(): SxClass[] {
|
|
129
|
+
return []
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
override getString(): string {
|
|
133
|
+
return `(clearance ${this._type})`
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
SxClass.register(PadOptionsClearance)
|
|
137
|
+
|
|
138
|
+
class PadOptionsAnchor extends SxClass {
|
|
139
|
+
static override token = "anchor"
|
|
140
|
+
static override parentToken = "options"
|
|
141
|
+
override token = "anchor"
|
|
142
|
+
|
|
143
|
+
private _shape: PadOptionsAnchorShape
|
|
144
|
+
|
|
145
|
+
constructor(shape: PadOptionsAnchorShape) {
|
|
146
|
+
super()
|
|
147
|
+
this._shape = shape
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
static override fromSexprPrimitives(
|
|
151
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
152
|
+
): PadOptionsAnchor {
|
|
153
|
+
const [raw] = primitiveSexprs
|
|
154
|
+
const stringValue = toStringValue(raw)
|
|
155
|
+
if (stringValue === undefined) {
|
|
156
|
+
throw new Error("pad options anchor requires a string value")
|
|
157
|
+
}
|
|
158
|
+
if (!ANCHOR_SHAPES.includes(stringValue as PadOptionsAnchorShape)) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`pad options anchor must be one of ${ANCHOR_SHAPES.join(", ")}`,
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
return new PadOptionsAnchor(stringValue as PadOptionsAnchorShape)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
get shape(): PadOptionsAnchorShape {
|
|
167
|
+
return this._shape
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
set shape(value: PadOptionsAnchorShape) {
|
|
171
|
+
this._shape = value
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
override getChildren(): SxClass[] {
|
|
175
|
+
return []
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
override getString(): string {
|
|
179
|
+
return `(anchor ${this._shape})`
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
SxClass.register(PadOptionsAnchor)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SxPrimitiveString } from "../base-classes/SxPrimitiveString"
|
|
2
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
3
|
+
|
|
4
|
+
export class PadPinFunction extends SxPrimitiveString {
|
|
5
|
+
static override token = "pinfunction"
|
|
6
|
+
static override parentToken = "pad"
|
|
7
|
+
token = "pinfunction"
|
|
8
|
+
}
|
|
9
|
+
SxClass.register(PadPinFunction)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SxPrimitiveString } from "../base-classes/SxPrimitiveString"
|
|
2
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
3
|
+
|
|
4
|
+
export class PadPinType extends SxPrimitiveString {
|
|
5
|
+
static override token = "pintype"
|
|
6
|
+
static override parentToken = "pad"
|
|
7
|
+
token = "pintype"
|
|
8
|
+
}
|
|
9
|
+
SxClass.register(PadPinType)
|