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,705 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import { SxPrimitiveBoolean } from "../base-classes/SxPrimitiveBoolean"
|
|
3
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
4
|
+
import { printSExpr } from "../parseToPrimitiveSExpr"
|
|
5
|
+
import { quoteSExprString } from "../utils/quoteSExprString"
|
|
6
|
+
import { toStringValue } from "../utils/toStringValue"
|
|
7
|
+
import { At } from "./At"
|
|
8
|
+
import { PadChamfer } from "./PadChamfer"
|
|
9
|
+
import { PadChamferRatio } from "./PadChamferRatio"
|
|
10
|
+
import { PadClearance } from "./PadClearance"
|
|
11
|
+
import { PadDieLength } from "./PadDieLength"
|
|
12
|
+
import { PadDrill } from "./PadDrill"
|
|
13
|
+
import { PadLayers } from "./PadLayers"
|
|
14
|
+
import { PadNet } from "./PadNet"
|
|
15
|
+
import { PadOptions } from "./PadOptions"
|
|
16
|
+
import { PadPinFunction } from "./PadPinFunction"
|
|
17
|
+
import { PadPinType } from "./PadPinType"
|
|
18
|
+
import { PadPrimitives } from "./PadPrimitives"
|
|
19
|
+
import { PadRoundrectRratio } from "./PadRoundrectRratio"
|
|
20
|
+
import { PadSize } from "./PadSize"
|
|
21
|
+
import { PadSolderMaskMargin } from "./PadSolderMaskMargin"
|
|
22
|
+
import { PadSolderPasteMargin } from "./PadSolderPasteMargin"
|
|
23
|
+
import { PadSolderPasteMarginRatio } from "./PadSolderPasteMarginRatio"
|
|
24
|
+
import { PadThermalGap } from "./PadThermalGap"
|
|
25
|
+
import { PadThermalWidth } from "./PadThermalWidth"
|
|
26
|
+
import { PadThermalBridgeAngle } from "./PadThermalBridgeAngle"
|
|
27
|
+
import { PadZoneConnect } from "./PadZoneConnect"
|
|
28
|
+
import { Property } from "./Property"
|
|
29
|
+
import { Stroke } from "./Stroke"
|
|
30
|
+
import { Uuid } from "./Uuid"
|
|
31
|
+
import { Width } from "./Width"
|
|
32
|
+
import { PadTeardrops } from "./PadTeardrops"
|
|
33
|
+
import { PadRectDelta } from "./PadRectDelta"
|
|
34
|
+
|
|
35
|
+
const SINGLE_TOKENS = new Set([
|
|
36
|
+
"at",
|
|
37
|
+
"size",
|
|
38
|
+
"drill",
|
|
39
|
+
"layers",
|
|
40
|
+
"width",
|
|
41
|
+
"stroke",
|
|
42
|
+
"rect_delta",
|
|
43
|
+
"roundrect_rratio",
|
|
44
|
+
"chamfer_ratio",
|
|
45
|
+
"chamfer",
|
|
46
|
+
"net",
|
|
47
|
+
"uuid",
|
|
48
|
+
"pinfunction",
|
|
49
|
+
"pintype",
|
|
50
|
+
"die_length",
|
|
51
|
+
"solder_mask_margin",
|
|
52
|
+
"solder_paste_margin",
|
|
53
|
+
"solder_paste_margin_ratio",
|
|
54
|
+
"clearance",
|
|
55
|
+
"zone_connect",
|
|
56
|
+
"thermal_width",
|
|
57
|
+
"thermal_gap",
|
|
58
|
+
"thermal_bridge_angle",
|
|
59
|
+
"options",
|
|
60
|
+
"primitives",
|
|
61
|
+
"remove_unused_layers",
|
|
62
|
+
"keep_end_layers",
|
|
63
|
+
"teardrops",
|
|
64
|
+
])
|
|
65
|
+
|
|
66
|
+
const MULTI_TOKENS = new Set(["property"])
|
|
67
|
+
|
|
68
|
+
const SUPPORTED_TOKENS = new Set([...SINGLE_TOKENS, ...MULTI_TOKENS])
|
|
69
|
+
|
|
70
|
+
const ensureSingle = (
|
|
71
|
+
arrayPropertyMap: Record<string, SxClass[]>,
|
|
72
|
+
token: string,
|
|
73
|
+
) => {
|
|
74
|
+
const entries = arrayPropertyMap[token]
|
|
75
|
+
if (entries && entries.length > 1) {
|
|
76
|
+
throw new Error(`pad does not support repeated "${token}" children`)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export class FootprintPad extends SxClass {
|
|
81
|
+
static override token = "pad"
|
|
82
|
+
token = "pad"
|
|
83
|
+
|
|
84
|
+
private _number = ""
|
|
85
|
+
private _padType = ""
|
|
86
|
+
private _shape = ""
|
|
87
|
+
private _locked = false
|
|
88
|
+
private _sxRemoveUnusedLayers?: PadRemoveUnusedLayers
|
|
89
|
+
private _sxKeepEndLayers?: PadKeepEndLayers
|
|
90
|
+
|
|
91
|
+
private _sxAt?: At
|
|
92
|
+
private _sxSize?: PadSize
|
|
93
|
+
private _sxDrill?: PadDrill
|
|
94
|
+
private _sxLayers?: PadLayers
|
|
95
|
+
private _sxWidth?: Width
|
|
96
|
+
private _sxStroke?: Stroke
|
|
97
|
+
private _properties: Property[] = []
|
|
98
|
+
private _sxRoundrectRatio?: PadRoundrectRratio
|
|
99
|
+
private _sxChamferRatio?: PadChamferRatio
|
|
100
|
+
private _sxChamfer?: PadChamfer
|
|
101
|
+
private _sxRectDelta?: PadRectDelta
|
|
102
|
+
private _sxNet?: PadNet
|
|
103
|
+
private _sxUuid?: Uuid
|
|
104
|
+
private _sxPinFunction?: PadPinFunction
|
|
105
|
+
private _sxPinType?: PadPinType
|
|
106
|
+
private _sxDieLength?: PadDieLength
|
|
107
|
+
private _sxSolderMaskMargin?: PadSolderMaskMargin
|
|
108
|
+
private _sxSolderPasteMargin?: PadSolderPasteMargin
|
|
109
|
+
private _sxSolderPasteMarginRatio?: PadSolderPasteMarginRatio
|
|
110
|
+
private _sxClearance?: PadClearance
|
|
111
|
+
private _sxZoneConnect?: PadZoneConnect
|
|
112
|
+
private _sxThermalWidth?: PadThermalWidth
|
|
113
|
+
private _sxThermalGap?: PadThermalGap
|
|
114
|
+
private _sxThermalBridgeAngle?: PadThermalBridgeAngle
|
|
115
|
+
private _sxOptions?: PadOptions
|
|
116
|
+
private _sxPrimitives?: PadPrimitives
|
|
117
|
+
private _sxTeardrops?: PadTeardrops
|
|
118
|
+
|
|
119
|
+
constructor(number = "", padType = "", shape = "") {
|
|
120
|
+
super()
|
|
121
|
+
this._number = number
|
|
122
|
+
this._padType = padType
|
|
123
|
+
this._shape = shape
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
static override fromSexprPrimitives(
|
|
127
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
128
|
+
): FootprintPad {
|
|
129
|
+
if (primitiveSexprs.length < 3) {
|
|
130
|
+
throw new Error("pad requires number, type, and shape arguments")
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const [rawNumber, rawType, rawShape, ...rest] = primitiveSexprs
|
|
134
|
+
const number = toStringValue(rawNumber)
|
|
135
|
+
const padType = toStringValue(rawType)
|
|
136
|
+
const shape = toStringValue(rawShape)
|
|
137
|
+
if (number === undefined || padType === undefined || shape === undefined) {
|
|
138
|
+
throw new Error("pad header tokens must be strings")
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const pad = new FootprintPad(number, padType, shape)
|
|
142
|
+
|
|
143
|
+
const primitiveStrings: string[] = []
|
|
144
|
+
const primitiveNodes: PrimitiveSExpr[] = []
|
|
145
|
+
|
|
146
|
+
for (const primitive of rest) {
|
|
147
|
+
if (typeof primitive === "string") {
|
|
148
|
+
primitiveStrings.push(primitive)
|
|
149
|
+
} else if (Array.isArray(primitive)) {
|
|
150
|
+
primitiveNodes.push(primitive)
|
|
151
|
+
} else {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`pad encountered unexpected primitive child: ${JSON.stringify(primitive)}`,
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (const flag of primitiveStrings) {
|
|
159
|
+
switch (flag) {
|
|
160
|
+
case "locked":
|
|
161
|
+
pad._locked = true
|
|
162
|
+
break
|
|
163
|
+
case "remove_unused_layer":
|
|
164
|
+
pad._sxRemoveUnusedLayers = new PadRemoveUnusedLayers({
|
|
165
|
+
value: true,
|
|
166
|
+
bareToken: "remove_unused_layer",
|
|
167
|
+
})
|
|
168
|
+
break
|
|
169
|
+
case "keep_end_layers":
|
|
170
|
+
pad._sxKeepEndLayers = new PadKeepEndLayers({
|
|
171
|
+
value: true,
|
|
172
|
+
bare: true,
|
|
173
|
+
})
|
|
174
|
+
break
|
|
175
|
+
default:
|
|
176
|
+
throw new Error(`pad encountered unsupported flag "${flag}"`)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const { propertyMap, arrayPropertyMap } =
|
|
181
|
+
SxClass.parsePrimitivesToClassProperties(primitiveNodes, this.token)
|
|
182
|
+
|
|
183
|
+
for (const token of Object.keys(propertyMap)) {
|
|
184
|
+
if (!SUPPORTED_TOKENS.has(token)) {
|
|
185
|
+
throw new Error(`pad encountered unsupported child token "${token}"`)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
for (const [token, entries] of Object.entries(arrayPropertyMap)) {
|
|
190
|
+
if (!SUPPORTED_TOKENS.has(token)) {
|
|
191
|
+
throw new Error(`pad encountered unsupported child token "${token}"`)
|
|
192
|
+
}
|
|
193
|
+
if (!MULTI_TOKENS.has(token) && entries.length > 1) {
|
|
194
|
+
throw new Error(`pad does not support repeated child "${token}"`)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
ensureSingle(arrayPropertyMap, "at")
|
|
199
|
+
ensureSingle(arrayPropertyMap, "size")
|
|
200
|
+
ensureSingle(arrayPropertyMap, "drill")
|
|
201
|
+
ensureSingle(arrayPropertyMap, "layers")
|
|
202
|
+
ensureSingle(arrayPropertyMap, "width")
|
|
203
|
+
ensureSingle(arrayPropertyMap, "stroke")
|
|
204
|
+
ensureSingle(arrayPropertyMap, "rect_delta")
|
|
205
|
+
ensureSingle(arrayPropertyMap, "roundrect_rratio")
|
|
206
|
+
ensureSingle(arrayPropertyMap, "chamfer_ratio")
|
|
207
|
+
ensureSingle(arrayPropertyMap, "chamfer")
|
|
208
|
+
ensureSingle(arrayPropertyMap, "net")
|
|
209
|
+
ensureSingle(arrayPropertyMap, "uuid")
|
|
210
|
+
ensureSingle(arrayPropertyMap, "pinfunction")
|
|
211
|
+
ensureSingle(arrayPropertyMap, "pintype")
|
|
212
|
+
ensureSingle(arrayPropertyMap, "die_length")
|
|
213
|
+
ensureSingle(arrayPropertyMap, "solder_mask_margin")
|
|
214
|
+
ensureSingle(arrayPropertyMap, "solder_paste_margin")
|
|
215
|
+
ensureSingle(arrayPropertyMap, "solder_paste_margin_ratio")
|
|
216
|
+
ensureSingle(arrayPropertyMap, "clearance")
|
|
217
|
+
ensureSingle(arrayPropertyMap, "zone_connect")
|
|
218
|
+
ensureSingle(arrayPropertyMap, "thermal_width")
|
|
219
|
+
ensureSingle(arrayPropertyMap, "thermal_gap")
|
|
220
|
+
ensureSingle(arrayPropertyMap, "thermal_bridge_angle")
|
|
221
|
+
ensureSingle(arrayPropertyMap, "options")
|
|
222
|
+
ensureSingle(arrayPropertyMap, "primitives")
|
|
223
|
+
|
|
224
|
+
pad._sxAt = propertyMap.at as At | undefined
|
|
225
|
+
pad._sxSize = propertyMap.size as PadSize | undefined
|
|
226
|
+
pad._sxDrill = propertyMap.drill as PadDrill | undefined
|
|
227
|
+
pad._sxLayers = propertyMap.layers as PadLayers | undefined
|
|
228
|
+
pad._sxWidth = propertyMap.width as Width | undefined
|
|
229
|
+
pad._sxStroke = propertyMap.stroke as Stroke | undefined
|
|
230
|
+
pad._sxRectDelta = propertyMap.rect_delta as PadRectDelta | undefined
|
|
231
|
+
|
|
232
|
+
pad._properties = (arrayPropertyMap.property as Property[]) ?? []
|
|
233
|
+
|
|
234
|
+
pad._sxRoundrectRatio = propertyMap.roundrect_rratio as
|
|
235
|
+
| PadRoundrectRratio
|
|
236
|
+
| undefined
|
|
237
|
+
pad._sxChamferRatio = propertyMap.chamfer_ratio as PadChamferRatio | undefined
|
|
238
|
+
pad._sxChamfer = propertyMap.chamfer as PadChamfer | undefined
|
|
239
|
+
pad._sxNet = propertyMap.net as PadNet | undefined
|
|
240
|
+
pad._sxUuid = propertyMap.uuid as Uuid | undefined
|
|
241
|
+
pad._sxPinFunction = propertyMap.pinfunction as PadPinFunction | undefined
|
|
242
|
+
pad._sxPinType = propertyMap.pintype as PadPinType | undefined
|
|
243
|
+
pad._sxDieLength = propertyMap.die_length as PadDieLength | undefined
|
|
244
|
+
pad._sxSolderMaskMargin = propertyMap.solder_mask_margin as
|
|
245
|
+
| PadSolderMaskMargin
|
|
246
|
+
| undefined
|
|
247
|
+
pad._sxSolderPasteMargin = propertyMap.solder_paste_margin as
|
|
248
|
+
| PadSolderPasteMargin
|
|
249
|
+
| undefined
|
|
250
|
+
pad._sxSolderPasteMarginRatio =
|
|
251
|
+
propertyMap.solder_paste_margin_ratio as PadSolderPasteMarginRatio | undefined
|
|
252
|
+
pad._sxClearance = propertyMap.clearance as PadClearance | undefined
|
|
253
|
+
pad._sxZoneConnect = propertyMap.zone_connect as PadZoneConnect | undefined
|
|
254
|
+
pad._sxThermalWidth = propertyMap.thermal_width as PadThermalWidth | undefined
|
|
255
|
+
pad._sxThermalGap = propertyMap.thermal_gap as PadThermalGap | undefined
|
|
256
|
+
pad._sxThermalBridgeAngle =
|
|
257
|
+
propertyMap.thermal_bridge_angle as PadThermalBridgeAngle | undefined
|
|
258
|
+
pad._sxOptions = propertyMap.options as PadOptions | undefined
|
|
259
|
+
pad._sxPrimitives = propertyMap.primitives as PadPrimitives | undefined
|
|
260
|
+
pad._sxRemoveUnusedLayers =
|
|
261
|
+
(arrayPropertyMap.remove_unused_layers?.[0] as
|
|
262
|
+
| PadRemoveUnusedLayers
|
|
263
|
+
| undefined) ??
|
|
264
|
+
pad._sxRemoveUnusedLayers
|
|
265
|
+
pad._sxKeepEndLayers =
|
|
266
|
+
(arrayPropertyMap.keep_end_layers?.[0] as PadKeepEndLayers | undefined) ??
|
|
267
|
+
pad._sxKeepEndLayers
|
|
268
|
+
pad._sxTeardrops =
|
|
269
|
+
(arrayPropertyMap.teardrops?.[0] as PadTeardrops | undefined) ?? undefined
|
|
270
|
+
|
|
271
|
+
return pad
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
get number(): string {
|
|
275
|
+
return this._number
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
set number(value: string) {
|
|
279
|
+
this._number = value
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
get padType(): string {
|
|
283
|
+
return this._padType
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
set padType(value: string) {
|
|
287
|
+
this._padType = value
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
get shape(): string {
|
|
291
|
+
return this._shape
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
set shape(value: string) {
|
|
295
|
+
this._shape = value
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
get locked(): boolean {
|
|
299
|
+
return this._locked
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
set locked(value: boolean) {
|
|
303
|
+
this._locked = value
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
get removeUnusedLayer(): boolean {
|
|
307
|
+
return this._sxRemoveUnusedLayers?.value ?? false
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
set removeUnusedLayer(value: boolean) {
|
|
311
|
+
this._sxRemoveUnusedLayers = value
|
|
312
|
+
? new PadRemoveUnusedLayers({ value })
|
|
313
|
+
: undefined
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
get keepEndLayers(): boolean {
|
|
317
|
+
return this._sxKeepEndLayers?.value ?? false
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
set keepEndLayers(value: boolean) {
|
|
321
|
+
this._sxKeepEndLayers = value
|
|
322
|
+
? new PadKeepEndLayers({ value })
|
|
323
|
+
: undefined
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
get at(): At | undefined {
|
|
327
|
+
return this._sxAt
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
set at(value: At | undefined) {
|
|
331
|
+
this._sxAt = value
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
get size(): PadSize | undefined {
|
|
335
|
+
return this._sxSize
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
set size(value: PadSize | undefined) {
|
|
339
|
+
this._sxSize = value
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
get drill(): PadDrill | undefined {
|
|
343
|
+
return this._sxDrill
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
set drill(value: PadDrill | undefined) {
|
|
347
|
+
this._sxDrill = value
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
get layers(): PadLayers | undefined {
|
|
351
|
+
return this._sxLayers
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
set layers(value: PadLayers | undefined) {
|
|
355
|
+
this._sxLayers = value
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
get width(): Width | undefined {
|
|
359
|
+
return this._sxWidth
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
set width(value: Width | undefined) {
|
|
363
|
+
this._sxWidth = value
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
get stroke(): Stroke | undefined {
|
|
367
|
+
return this._sxStroke
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
set stroke(value: Stroke | undefined) {
|
|
371
|
+
this._sxStroke = value
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
get properties(): Property[] {
|
|
375
|
+
return [...this._properties]
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
set properties(value: Property[]) {
|
|
379
|
+
this._properties = [...value]
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
get roundrectRatio(): number | undefined {
|
|
383
|
+
return this._sxRoundrectRatio?.value
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
set roundrectRatio(value: number | undefined) {
|
|
387
|
+
this._sxRoundrectRatio =
|
|
388
|
+
value === undefined ? undefined : new PadRoundrectRratio(value)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
get chamferRatio(): number | undefined {
|
|
392
|
+
return this._sxChamferRatio?.value
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
set chamferRatio(value: number | undefined) {
|
|
396
|
+
this._sxChamferRatio =
|
|
397
|
+
value === undefined ? undefined : new PadChamferRatio(value)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
get chamfer(): PadChamfer | undefined {
|
|
401
|
+
return this._sxChamfer
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
set chamfer(value: PadChamfer | undefined) {
|
|
405
|
+
this._sxChamfer = value
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
get chamferCorners(): string[] | undefined {
|
|
409
|
+
return this._sxChamfer?.corners
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
get rectDelta(): PadRectDelta | undefined {
|
|
413
|
+
return this._sxRectDelta
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
set rectDelta(value: PadRectDelta | { x: number; y: number } | undefined) {
|
|
417
|
+
if (value === undefined) {
|
|
418
|
+
this._sxRectDelta = undefined
|
|
419
|
+
return
|
|
420
|
+
}
|
|
421
|
+
if (value instanceof PadRectDelta) {
|
|
422
|
+
this._sxRectDelta = value
|
|
423
|
+
return
|
|
424
|
+
}
|
|
425
|
+
this._sxRectDelta = new PadRectDelta(value.x, value.y)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
get net(): PadNet | undefined {
|
|
429
|
+
return this._sxNet
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
set net(value: PadNet | undefined) {
|
|
433
|
+
this._sxNet = value
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
get uuid(): Uuid | undefined {
|
|
437
|
+
return this._sxUuid
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
set uuid(value: Uuid | string | undefined) {
|
|
441
|
+
if (value === undefined) {
|
|
442
|
+
this._sxUuid = undefined
|
|
443
|
+
return
|
|
444
|
+
}
|
|
445
|
+
this._sxUuid = value instanceof Uuid ? value : new Uuid(value)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
get pinfunction(): string | undefined {
|
|
449
|
+
return this._sxPinFunction?.value
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
set pinfunction(value: string | undefined) {
|
|
453
|
+
this._sxPinFunction =
|
|
454
|
+
value === undefined ? undefined : new PadPinFunction(value)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
get pintype(): string | undefined {
|
|
458
|
+
return this._sxPinType?.value
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
set pintype(value: string | undefined) {
|
|
462
|
+
this._sxPinType = value === undefined ? undefined : new PadPinType(value)
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
get dieLength(): number | undefined {
|
|
466
|
+
return this._sxDieLength?.value
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
set dieLength(value: number | undefined) {
|
|
470
|
+
this._sxDieLength = value === undefined ? undefined : new PadDieLength(value)
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
get solderMaskMargin(): number | undefined {
|
|
474
|
+
return this._sxSolderMaskMargin?.value
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
set solderMaskMargin(value: number | undefined) {
|
|
478
|
+
this._sxSolderMaskMargin =
|
|
479
|
+
value === undefined ? undefined : new PadSolderMaskMargin(value)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
get solderPasteMargin(): number | undefined {
|
|
483
|
+
return this._sxSolderPasteMargin?.value
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
set solderPasteMargin(value: number | undefined) {
|
|
487
|
+
this._sxSolderPasteMargin =
|
|
488
|
+
value === undefined ? undefined : new PadSolderPasteMargin(value)
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
get solderPasteMarginRatio(): number | undefined {
|
|
492
|
+
return this._sxSolderPasteMarginRatio?.value
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
set solderPasteMarginRatio(value: number | undefined) {
|
|
496
|
+
this._sxSolderPasteMarginRatio =
|
|
497
|
+
value === undefined ? undefined : new PadSolderPasteMarginRatio(value)
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
get clearance(): number | undefined {
|
|
501
|
+
return this._sxClearance?.value
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
set clearance(value: number | undefined) {
|
|
505
|
+
this._sxClearance = value === undefined ? undefined : new PadClearance(value)
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
get zoneConnect(): number | undefined {
|
|
509
|
+
return this._sxZoneConnect?.value
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
set zoneConnect(value: number | undefined) {
|
|
513
|
+
this._sxZoneConnect = value === undefined ? undefined : new PadZoneConnect(value)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
get thermalWidth(): number | undefined {
|
|
517
|
+
return this._sxThermalWidth?.value
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
set thermalWidth(value: number | undefined) {
|
|
521
|
+
this._sxThermalWidth = value === undefined ? undefined : new PadThermalWidth(value)
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
get thermalGap(): number | undefined {
|
|
525
|
+
return this._sxThermalGap?.value
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
set thermalGap(value: number | undefined) {
|
|
529
|
+
this._sxThermalGap = value === undefined ? undefined : new PadThermalGap(value)
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
get thermalBridgeAngle(): number | undefined {
|
|
533
|
+
return this._sxThermalBridgeAngle?.value
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
set thermalBridgeAngle(value: number | undefined) {
|
|
537
|
+
this._sxThermalBridgeAngle =
|
|
538
|
+
value === undefined ? undefined : new PadThermalBridgeAngle(value)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
get options(): PadOptions | undefined {
|
|
542
|
+
return this._sxOptions
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
set options(value: PadOptions | undefined) {
|
|
546
|
+
this._sxOptions = value
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
get primitives(): PadPrimitives | undefined {
|
|
550
|
+
return this._sxPrimitives
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
set primitives(value: PadPrimitives | undefined) {
|
|
554
|
+
this._sxPrimitives = value
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
get teardrops(): PadTeardrops | undefined {
|
|
558
|
+
return this._sxTeardrops
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
set teardrops(value: PadTeardrops | undefined) {
|
|
562
|
+
this._sxTeardrops = value
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
override getChildren(): SxClass[] {
|
|
566
|
+
const children: SxClass[] = []
|
|
567
|
+
if (this._sxAt) children.push(this._sxAt)
|
|
568
|
+
if (this._sxSize) children.push(this._sxSize)
|
|
569
|
+
if (this._sxDrill) children.push(this._sxDrill)
|
|
570
|
+
if (this._sxLayers) children.push(this._sxLayers)
|
|
571
|
+
if (this._sxWidth) children.push(this._sxWidth)
|
|
572
|
+
if (this._sxStroke) children.push(this._sxStroke)
|
|
573
|
+
children.push(...this._properties)
|
|
574
|
+
if (this._sxRoundrectRatio) children.push(this._sxRoundrectRatio)
|
|
575
|
+
if (this._sxChamferRatio) children.push(this._sxChamferRatio)
|
|
576
|
+
if (this._sxChamfer) children.push(this._sxChamfer)
|
|
577
|
+
if (this._sxRectDelta) children.push(this._sxRectDelta)
|
|
578
|
+
if (this._sxNet) children.push(this._sxNet)
|
|
579
|
+
if (this._sxPinFunction) children.push(this._sxPinFunction)
|
|
580
|
+
if (this._sxPinType) children.push(this._sxPinType)
|
|
581
|
+
if (this._sxDieLength) children.push(this._sxDieLength)
|
|
582
|
+
if (this._sxSolderMaskMargin) children.push(this._sxSolderMaskMargin)
|
|
583
|
+
if (this._sxSolderPasteMargin) children.push(this._sxSolderPasteMargin)
|
|
584
|
+
if (this._sxSolderPasteMarginRatio)
|
|
585
|
+
children.push(this._sxSolderPasteMarginRatio)
|
|
586
|
+
if (this._sxClearance) children.push(this._sxClearance)
|
|
587
|
+
if (this._sxZoneConnect) children.push(this._sxZoneConnect)
|
|
588
|
+
if (this._sxThermalWidth) children.push(this._sxThermalWidth)
|
|
589
|
+
if (this._sxThermalGap) children.push(this._sxThermalGap)
|
|
590
|
+
if (this._sxThermalBridgeAngle)
|
|
591
|
+
children.push(this._sxThermalBridgeAngle)
|
|
592
|
+
if (this._sxUuid) children.push(this._sxUuid)
|
|
593
|
+
if (this._sxRemoveUnusedLayers) children.push(this._sxRemoveUnusedLayers)
|
|
594
|
+
if (this._sxKeepEndLayers) children.push(this._sxKeepEndLayers)
|
|
595
|
+
if (this._sxTeardrops) children.push(this._sxTeardrops)
|
|
596
|
+
if (this._sxOptions) children.push(this._sxOptions)
|
|
597
|
+
if (this._sxPrimitives) children.push(this._sxPrimitives)
|
|
598
|
+
return children
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
override getString(): string {
|
|
602
|
+
const lines = [
|
|
603
|
+
`(pad ${quoteSExprString(this._number)} ${this._padType} ${this._shape}`,
|
|
604
|
+
]
|
|
605
|
+
for (const child of this.getChildren()) {
|
|
606
|
+
lines.push(child.getStringIndented())
|
|
607
|
+
}
|
|
608
|
+
if (this._locked) {
|
|
609
|
+
lines.push(" locked")
|
|
610
|
+
}
|
|
611
|
+
lines.push(")")
|
|
612
|
+
return lines.join("\n")
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
SxClass.register(FootprintPad)
|
|
616
|
+
|
|
617
|
+
class PadRemoveUnusedLayers extends SxPrimitiveBoolean {
|
|
618
|
+
static override token = "remove_unused_layers"
|
|
619
|
+
static override parentToken = "pad"
|
|
620
|
+
override token = "remove_unused_layers"
|
|
621
|
+
|
|
622
|
+
private readonly bareToken?: string
|
|
623
|
+
|
|
624
|
+
constructor(options: { value?: boolean; bareToken?: string } = {}) {
|
|
625
|
+
super(options.value ?? false)
|
|
626
|
+
this.bareToken = options.bareToken
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
static override fromSexprPrimitives(
|
|
630
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
631
|
+
): PadRemoveUnusedLayers {
|
|
632
|
+
const [raw] = primitiveSexprs
|
|
633
|
+
if (raw === undefined) {
|
|
634
|
+
return new PadRemoveUnusedLayers({ value: false })
|
|
635
|
+
}
|
|
636
|
+
if (typeof raw === "boolean") {
|
|
637
|
+
return new PadRemoveUnusedLayers({ value: raw })
|
|
638
|
+
}
|
|
639
|
+
if (typeof raw === "string") {
|
|
640
|
+
const normalized = raw.toLowerCase()
|
|
641
|
+
if (normalized === "yes" || normalized === "true") {
|
|
642
|
+
return new PadRemoveUnusedLayers({ value: true })
|
|
643
|
+
}
|
|
644
|
+
if (normalized === "no" || normalized === "false") {
|
|
645
|
+
return new PadRemoveUnusedLayers({ value: false })
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
throw new Error(
|
|
649
|
+
`remove_unused_layers expects yes/no or boolean, received ${JSON.stringify(raw)}`,
|
|
650
|
+
)
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
override getString(): string {
|
|
654
|
+
if (this.bareToken) {
|
|
655
|
+
return this.bareToken
|
|
656
|
+
}
|
|
657
|
+
return `(remove_unused_layers ${this.value ? "yes" : "no"})`
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
SxClass.register(PadRemoveUnusedLayers)
|
|
661
|
+
|
|
662
|
+
class PadKeepEndLayers extends SxPrimitiveBoolean {
|
|
663
|
+
static override token = "keep_end_layers"
|
|
664
|
+
static override parentToken = "pad"
|
|
665
|
+
override token = "keep_end_layers"
|
|
666
|
+
|
|
667
|
+
private readonly renderBare: boolean
|
|
668
|
+
|
|
669
|
+
constructor(options: { value?: boolean; bare?: boolean } = {}) {
|
|
670
|
+
super(options.value ?? false)
|
|
671
|
+
this.renderBare = options.bare ?? false
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
static override fromSexprPrimitives(
|
|
675
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
676
|
+
): PadKeepEndLayers {
|
|
677
|
+
const [raw] = primitiveSexprs
|
|
678
|
+
if (raw === undefined) {
|
|
679
|
+
return new PadKeepEndLayers({ value: false })
|
|
680
|
+
}
|
|
681
|
+
if (typeof raw === "boolean") {
|
|
682
|
+
return new PadKeepEndLayers({ value: raw })
|
|
683
|
+
}
|
|
684
|
+
if (typeof raw === "string") {
|
|
685
|
+
const normalized = raw.toLowerCase()
|
|
686
|
+
if (normalized === "yes" || normalized === "true") {
|
|
687
|
+
return new PadKeepEndLayers({ value: true })
|
|
688
|
+
}
|
|
689
|
+
if (normalized === "no" || normalized === "false") {
|
|
690
|
+
return new PadKeepEndLayers({ value: false })
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
throw new Error(
|
|
694
|
+
`keep_end_layers expects yes/no or boolean, received ${JSON.stringify(raw)}`,
|
|
695
|
+
)
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
override getString(): string {
|
|
699
|
+
if (this.renderBare) {
|
|
700
|
+
return "keep_end_layers"
|
|
701
|
+
}
|
|
702
|
+
return `(keep_end_layers ${this.value ? "yes" : "no"})`
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
SxClass.register(PadKeepEndLayers)
|