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.
Files changed (188) hide show
  1. package/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
  2. package/.vscode/settings.json +16 -0
  3. package/AGENTS.md +30 -0
  4. package/README.md +206 -0
  5. package/biome.json +93 -0
  6. package/bun.lock +48 -0
  7. package/bunfig.toml +5 -0
  8. package/lib/index.ts +1 -0
  9. package/lib/sexpr/base-classes/SxClass.ts +164 -0
  10. package/lib/sexpr/base-classes/SxPrimitiveBoolean.ts +35 -0
  11. package/lib/sexpr/base-classes/SxPrimitiveNumber.ts +26 -0
  12. package/lib/sexpr/base-classes/SxPrimitiveString.ts +26 -0
  13. package/lib/sexpr/classes/At.ts +38 -0
  14. package/lib/sexpr/classes/Bus.ts +83 -0
  15. package/lib/sexpr/classes/BusEntry.ts +142 -0
  16. package/lib/sexpr/classes/Color.ts +29 -0
  17. package/lib/sexpr/classes/Dnp.ts +8 -0
  18. package/lib/sexpr/classes/EmbeddedFonts.ts +70 -0
  19. package/lib/sexpr/classes/ExcludeFromSim.ts +8 -0
  20. package/lib/sexpr/classes/FieldsAutoplaced.ts +8 -0
  21. package/lib/sexpr/classes/Footprint.ts +719 -0
  22. package/lib/sexpr/classes/FootprintAttr.ts +102 -0
  23. package/lib/sexpr/classes/FootprintAutoplaceCost180.ts +9 -0
  24. package/lib/sexpr/classes/FootprintAutoplaceCost90.ts +9 -0
  25. package/lib/sexpr/classes/FootprintClearance.ts +9 -0
  26. package/lib/sexpr/classes/FootprintDescr.ts +44 -0
  27. package/lib/sexpr/classes/FootprintLocked.ts +32 -0
  28. package/lib/sexpr/classes/FootprintModel.ts +145 -0
  29. package/lib/sexpr/classes/FootprintNetTiePadGroups.ts +50 -0
  30. package/lib/sexpr/classes/FootprintPad.ts +705 -0
  31. package/lib/sexpr/classes/FootprintPath.ts +44 -0
  32. package/lib/sexpr/classes/FootprintPlaced.ts +32 -0
  33. package/lib/sexpr/classes/FootprintPrivateLayers.ts +56 -0
  34. package/lib/sexpr/classes/FootprintSheetfile.ts +44 -0
  35. package/lib/sexpr/classes/FootprintSheetname.ts +44 -0
  36. package/lib/sexpr/classes/FootprintSolderMaskMargin.ts +9 -0
  37. package/lib/sexpr/classes/FootprintSolderPasteMargin.ts +9 -0
  38. package/lib/sexpr/classes/FootprintSolderPasteRatio.ts +9 -0
  39. package/lib/sexpr/classes/FootprintTags.ts +44 -0
  40. package/lib/sexpr/classes/FootprintTedit.ts +21 -0
  41. package/lib/sexpr/classes/FootprintThermalGap.ts +9 -0
  42. package/lib/sexpr/classes/FootprintThermalWidth.ts +9 -0
  43. package/lib/sexpr/classes/FootprintZoneConnect.ts +9 -0
  44. package/lib/sexpr/classes/FpArc.ts +289 -0
  45. package/lib/sexpr/classes/FpCircle.ts +293 -0
  46. package/lib/sexpr/classes/FpLine.ts +288 -0
  47. package/lib/sexpr/classes/FpPoly.ts +266 -0
  48. package/lib/sexpr/classes/FpPolyFill.ts +48 -0
  49. package/lib/sexpr/classes/FpPolyLocked.ts +40 -0
  50. package/lib/sexpr/classes/FpRect.ts +293 -0
  51. package/lib/sexpr/classes/FpText.ts +341 -0
  52. package/lib/sexpr/classes/FpTextBox.ts +412 -0
  53. package/lib/sexpr/classes/GrLine.ts +245 -0
  54. package/lib/sexpr/classes/GrLineAngle.ts +32 -0
  55. package/lib/sexpr/classes/GrLineEnd.ts +61 -0
  56. package/lib/sexpr/classes/GrLineLocked.ts +40 -0
  57. package/lib/sexpr/classes/GrLineStart.ts +61 -0
  58. package/lib/sexpr/classes/GrText.ts +202 -0
  59. package/lib/sexpr/classes/Image.ts +256 -0
  60. package/lib/sexpr/classes/InBom.ts +8 -0
  61. package/lib/sexpr/classes/Junction.ts +134 -0
  62. package/lib/sexpr/classes/KicadPcb.ts +313 -0
  63. package/lib/sexpr/classes/KicadSch.ts +303 -0
  64. package/lib/sexpr/classes/KicadSchGenerator.ts +32 -0
  65. package/lib/sexpr/classes/KicadSchGeneratorVersion.ts +30 -0
  66. package/lib/sexpr/classes/KicadSchVersion.ts +22 -0
  67. package/lib/sexpr/classes/Label.ts +136 -0
  68. package/lib/sexpr/classes/Layer.ts +51 -0
  69. package/lib/sexpr/classes/Layers.ts +47 -0
  70. package/lib/sexpr/classes/LibSymbols.ts +61 -0
  71. package/lib/sexpr/classes/NoConnect.ts +73 -0
  72. package/lib/sexpr/classes/OnBoard.ts +8 -0
  73. package/lib/sexpr/classes/PadChamfer.ts +50 -0
  74. package/lib/sexpr/classes/PadChamferRatio.ts +9 -0
  75. package/lib/sexpr/classes/PadClearance.ts +9 -0
  76. package/lib/sexpr/classes/PadDieLength.ts +9 -0
  77. package/lib/sexpr/classes/PadDrill.ts +145 -0
  78. package/lib/sexpr/classes/PadDrillOffset.ts +54 -0
  79. package/lib/sexpr/classes/PadLayers.ts +59 -0
  80. package/lib/sexpr/classes/PadNet.ts +56 -0
  81. package/lib/sexpr/classes/PadOptions.ts +182 -0
  82. package/lib/sexpr/classes/PadPinFunction.ts +9 -0
  83. package/lib/sexpr/classes/PadPinType.ts +9 -0
  84. package/lib/sexpr/classes/PadPrimitiveGrArc.ts +254 -0
  85. package/lib/sexpr/classes/PadPrimitiveGrCircle.ts +279 -0
  86. package/lib/sexpr/classes/PadPrimitiveGrLine.ts +126 -0
  87. package/lib/sexpr/classes/PadPrimitives.ts +289 -0
  88. package/lib/sexpr/classes/PadRectDelta.ts +57 -0
  89. package/lib/sexpr/classes/PadRoundrectRratio.ts +9 -0
  90. package/lib/sexpr/classes/PadSize.ts +54 -0
  91. package/lib/sexpr/classes/PadSolderMaskMargin.ts +9 -0
  92. package/lib/sexpr/classes/PadSolderPasteMargin.ts +9 -0
  93. package/lib/sexpr/classes/PadSolderPasteMarginRatio.ts +9 -0
  94. package/lib/sexpr/classes/PadTeardrops.ts +208 -0
  95. package/lib/sexpr/classes/PadThermalBridgeAngle.ts +9 -0
  96. package/lib/sexpr/classes/PadThermalGap.ts +9 -0
  97. package/lib/sexpr/classes/PadThermalWidth.ts +9 -0
  98. package/lib/sexpr/classes/PadZoneConnect.ts +9 -0
  99. package/lib/sexpr/classes/Paper.ts +119 -0
  100. package/lib/sexpr/classes/PcbGeneral.ts +75 -0
  101. package/lib/sexpr/classes/PcbGeneralLegacyTeardrops.ts +44 -0
  102. package/lib/sexpr/classes/PcbGeneralThickness.ts +9 -0
  103. package/lib/sexpr/classes/PcbGenerator.ts +16 -0
  104. package/lib/sexpr/classes/PcbGeneratorVersion.ts +16 -0
  105. package/lib/sexpr/classes/PcbLayerDefinition.ts +102 -0
  106. package/lib/sexpr/classes/PcbLayers.ts +34 -0
  107. package/lib/sexpr/classes/PcbNet.ts +56 -0
  108. package/lib/sexpr/classes/PcbVersion.ts +9 -0
  109. package/lib/sexpr/classes/Property.ts +246 -0
  110. package/lib/sexpr/classes/PropertyHide.ts +9 -0
  111. package/lib/sexpr/classes/PropertyUnlocked.ts +9 -0
  112. package/lib/sexpr/classes/Pts.ts +65 -0
  113. package/lib/sexpr/classes/RenderCache.ts +221 -0
  114. package/lib/sexpr/classes/SchematicText.ts +141 -0
  115. package/lib/sexpr/classes/Segment.ts +222 -0
  116. package/lib/sexpr/classes/SegmentEnd.ts +59 -0
  117. package/lib/sexpr/classes/SegmentLocked.ts +33 -0
  118. package/lib/sexpr/classes/SegmentNet.ts +62 -0
  119. package/lib/sexpr/classes/SegmentStart.ts +59 -0
  120. package/lib/sexpr/classes/Setup/PcbPlotParams.ts +729 -0
  121. package/lib/sexpr/classes/Setup/PcbPlotParamsBase.ts +9 -0
  122. package/lib/sexpr/classes/Setup/PcbPlotParamsNumericProperties.ts +105 -0
  123. package/lib/sexpr/classes/Setup/PcbPlotParamsStringPropertiesA.ts +104 -0
  124. package/lib/sexpr/classes/Setup/PcbPlotParamsStringPropertiesB.ts +105 -0
  125. package/lib/sexpr/classes/Setup/Setup.ts +573 -0
  126. package/lib/sexpr/classes/Setup/SetupPropertyTypes.ts +119 -0
  127. package/lib/sexpr/classes/Setup/Stackup.ts +140 -0
  128. package/lib/sexpr/classes/Setup/StackupLayer.ts +233 -0
  129. package/lib/sexpr/classes/Setup/StackupLayerProperties.ts +78 -0
  130. package/lib/sexpr/classes/Setup/StackupProperties.ts +41 -0
  131. package/lib/sexpr/classes/Setup/base.ts +167 -0
  132. package/lib/sexpr/classes/Setup/index.ts +14 -0
  133. package/lib/sexpr/classes/Setup/setupMultiValueProperties.ts +54 -0
  134. package/lib/sexpr/classes/Setup/setupNumericProperties.ts +151 -0
  135. package/lib/sexpr/classes/Setup/setupPropertyHandlers.ts +90 -0
  136. package/lib/sexpr/classes/Setup/setupStringProperties.ts +75 -0
  137. package/lib/sexpr/classes/Sheet.ts +205 -0
  138. package/lib/sexpr/classes/SheetFill.ts +44 -0
  139. package/lib/sexpr/classes/SheetInstances.ts +168 -0
  140. package/lib/sexpr/classes/SheetInstancesRoot.ts +165 -0
  141. package/lib/sexpr/classes/SheetPin.ts +122 -0
  142. package/lib/sexpr/classes/SheetProperty.ts +115 -0
  143. package/lib/sexpr/classes/SheetSize.ts +44 -0
  144. package/lib/sexpr/classes/Stroke.ts +58 -0
  145. package/lib/sexpr/classes/StrokeType.ts +34 -0
  146. package/lib/sexpr/classes/Symbol.ts +1541 -0
  147. package/lib/sexpr/classes/TextEffects.ts +444 -0
  148. package/lib/sexpr/classes/TitleBlock.ts +352 -0
  149. package/lib/sexpr/classes/Unit.ts +28 -0
  150. package/lib/sexpr/classes/Uuid.ts +8 -0
  151. package/lib/sexpr/classes/Via.ts +328 -0
  152. package/lib/sexpr/classes/ViaNet.ts +59 -0
  153. package/lib/sexpr/classes/Width.ts +8 -0
  154. package/lib/sexpr/classes/Wire.ts +91 -0
  155. package/lib/sexpr/classes/Xy.ts +35 -0
  156. package/lib/sexpr/classes/Zone.ts +41 -0
  157. package/lib/sexpr/index.ts +130 -0
  158. package/lib/sexpr/parseKicadSexpr.ts +5 -0
  159. package/lib/sexpr/parseToPrimitiveSExpr.ts +240 -0
  160. package/lib/sexpr/utils/indentLines.ts +3 -0
  161. package/lib/sexpr/utils/parseYesNo.ts +12 -0
  162. package/lib/sexpr/utils/quoteSExprString.ts +8 -0
  163. package/lib/sexpr/utils/strokeFromArgs.ts +19 -0
  164. package/lib/sexpr/utils/toNumberValue.ts +13 -0
  165. package/lib/sexpr/utils/toStringValue.ts +10 -0
  166. package/package.json +26 -0
  167. package/scripts/download-references.ts +66 -0
  168. package/tests/fixtures/expectEqualPrimitiveSExpr.ts +200 -0
  169. package/tests/sexpr/KicadPcbDemos.test.ts +48 -0
  170. package/tests/sexpr/KicadSchDemos.test.ts +49 -0
  171. package/tests/sexpr/classes/Footprint.test.ts +277 -0
  172. package/tests/sexpr/classes/FootprintPad.test.ts +71 -0
  173. package/tests/sexpr/classes/FpArc.test.ts +45 -0
  174. package/tests/sexpr/classes/FpCircle.test.ts +39 -0
  175. package/tests/sexpr/classes/FpPoly.test.ts +43 -0
  176. package/tests/sexpr/classes/FpRect.test.ts +40 -0
  177. package/tests/sexpr/classes/FpTextBox.test.ts +84 -0
  178. package/tests/sexpr/classes/Image.test.ts +50 -0
  179. package/tests/sexpr/classes/KicadSch.test.ts +97 -0
  180. package/tests/sexpr/classes/Paper.test.ts +30 -0
  181. package/tests/sexpr/classes/Property.test.ts +48 -0
  182. package/tests/sexpr/classes/Setup.test.ts +189 -0
  183. package/tests/sexpr/classes/Sheet.test.ts +107 -0
  184. package/tests/sexpr/classes/Stroke.test.ts +15 -0
  185. package/tests/sexpr/classes/Symbol.test.ts +96 -0
  186. package/tests/sexpr/classes/TextEffects.test.ts +56 -0
  187. package/tests/sexpr/classes/TitleBlock.test.ts +40 -0
  188. package/tsconfig.json +35 -0
@@ -0,0 +1,289 @@
1
+ import { SxClass } from "../base-classes/SxClass"
2
+ import { SxPrimitiveBoolean } from "../base-classes/SxPrimitiveBoolean"
3
+ import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
4
+ import { Pts } from "./Pts"
5
+ import { Width } from "./Width"
6
+ import { PadPrimitiveGrLine } from "./PadPrimitiveGrLine"
7
+ import { PadPrimitiveGrArc } from "./PadPrimitiveGrArc"
8
+ import { PadPrimitiveGrCircle } from "./PadPrimitiveGrCircle"
9
+
10
+ type PadPrimitiveGraphic =
11
+ | PadPrimitiveGrPoly
12
+ | PadPrimitiveGrLine
13
+ | PadPrimitiveGrArc
14
+ | PadPrimitiveGrCircle
15
+
16
+ export class PadPrimitives extends SxClass {
17
+ static override token = "primitives"
18
+ static override parentToken = "pad"
19
+ override token = "primitives"
20
+
21
+ private _graphics: PadPrimitiveGraphic[] = []
22
+ private _sxWidth?: Width
23
+ private _sxFill?: PadPrimitivesFill
24
+
25
+ static override fromSexprPrimitives(
26
+ primitiveSexprs: PrimitiveSExpr[],
27
+ ): PadPrimitives {
28
+ const primitives = new PadPrimitives()
29
+
30
+ for (const primitive of primitiveSexprs) {
31
+ if (!Array.isArray(primitive) || primitive.length === 0) {
32
+ throw new Error(
33
+ `pad primitives encountered invalid child expression: ${JSON.stringify(primitive)}`,
34
+ )
35
+ }
36
+
37
+ const parsed = SxClass.parsePrimitiveSexpr(primitive, {
38
+ parentToken: this.token,
39
+ })
40
+
41
+ if (!(parsed instanceof SxClass)) {
42
+ throw new Error(
43
+ `pad primitives child did not resolve to an SxClass: ${JSON.stringify(primitive)}`,
44
+ )
45
+ }
46
+
47
+ if (parsed instanceof Width) {
48
+ if (primitives._sxWidth) {
49
+ throw new Error("pad primitives encountered duplicate width tokens")
50
+ }
51
+ primitives._sxWidth = parsed
52
+ continue
53
+ }
54
+
55
+ if (parsed instanceof PadPrimitivesFill) {
56
+ if (primitives._sxFill) {
57
+ throw new Error("pad primitives encountered duplicate fill tokens")
58
+ }
59
+ primitives._sxFill = parsed
60
+ continue
61
+ }
62
+
63
+ if (parsed instanceof PadPrimitiveGrPoly) {
64
+ primitives._graphics.push(parsed)
65
+ continue
66
+ }
67
+
68
+ if (parsed instanceof PadPrimitiveGrLine) {
69
+ primitives._graphics.push(parsed)
70
+ continue
71
+ }
72
+
73
+ if (parsed instanceof PadPrimitiveGrArc) {
74
+ primitives._graphics.push(parsed)
75
+ continue
76
+ }
77
+
78
+ if (parsed instanceof PadPrimitiveGrCircle) {
79
+ primitives._graphics.push(parsed)
80
+ continue
81
+ }
82
+
83
+ throw new Error(`pad primitives encountered unsupported token "${parsed.token}"`)
84
+ }
85
+
86
+ return primitives
87
+ }
88
+
89
+ get graphics(): PadPrimitiveGraphic[] {
90
+ return [...this._graphics]
91
+ }
92
+
93
+ set graphics(value: PadPrimitiveGraphic[]) {
94
+ this._graphics = [...value]
95
+ }
96
+
97
+ addGraphic(graphic: PadPrimitiveGraphic) {
98
+ this._graphics.push(graphic)
99
+ }
100
+
101
+ get width(): number | undefined {
102
+ return this._sxWidth?.value
103
+ }
104
+
105
+ set width(value: number | undefined) {
106
+ this._sxWidth = value === undefined ? undefined : new Width(value)
107
+ }
108
+
109
+ get fill(): boolean | undefined {
110
+ return this._sxFill?.value
111
+ }
112
+
113
+ set fill(value: boolean | undefined) {
114
+ this._sxFill =
115
+ value === undefined ? undefined : new PadPrimitivesFill({ value })
116
+ }
117
+
118
+ override getChildren(): SxClass[] {
119
+ const children: SxClass[] = []
120
+ children.push(...this._graphics)
121
+ if (this._sxWidth) children.push(this._sxWidth)
122
+ if (this._sxFill) children.push(this._sxFill)
123
+ return children
124
+ }
125
+ }
126
+ SxClass.register(PadPrimitives)
127
+
128
+ class PadPrimitivesFill extends SxPrimitiveBoolean {
129
+ static override token = "fill"
130
+ static override parentToken = "primitives"
131
+ override token = "fill"
132
+
133
+ constructor(options: { value?: boolean } = {}) {
134
+ super(options.value ?? false)
135
+ }
136
+
137
+ static override fromSexprPrimitives(
138
+ primitiveSexprs: PrimitiveSExpr[],
139
+ ): PadPrimitivesFill {
140
+ const [raw] = primitiveSexprs
141
+ const normalized = typeof raw === "string" ? raw.toLowerCase() : raw
142
+ if (normalized === undefined) {
143
+ return new PadPrimitivesFill({ value: false })
144
+ }
145
+ if (normalized === "yes") {
146
+ return new PadPrimitivesFill({ value: true })
147
+ }
148
+ if (normalized === "no") {
149
+ return new PadPrimitivesFill({ value: false })
150
+ }
151
+ if (typeof normalized === "boolean") {
152
+ return new PadPrimitivesFill({ value: normalized })
153
+ }
154
+ throw new Error(
155
+ `pad primitives fill expects yes/no or boolean, received ${JSON.stringify(raw)}`,
156
+ )
157
+ }
158
+ }
159
+ SxClass.register(PadPrimitivesFill)
160
+
161
+ export class PadPrimitiveGrPoly extends SxClass {
162
+ static override token = "gr_poly"
163
+ static override parentToken = "primitives"
164
+ override token = "gr_poly"
165
+
166
+ private _contours: Pts[] = []
167
+ private _sxWidth?: Width
168
+ private _sxFill?: PadPrimitiveFill
169
+
170
+ static override fromSexprPrimitives(
171
+ primitiveSexprs: PrimitiveSExpr[],
172
+ ): PadPrimitiveGrPoly {
173
+ const polygon = new PadPrimitiveGrPoly()
174
+
175
+ for (const primitive of primitiveSexprs) {
176
+ if (!Array.isArray(primitive) || primitive.length === 0) {
177
+ throw new Error(
178
+ `gr_poly primitive encountered invalid child: ${JSON.stringify(primitive)}`,
179
+ )
180
+ }
181
+
182
+ const parsed = SxClass.parsePrimitiveSexpr(primitive, {
183
+ parentToken: this.token,
184
+ })
185
+
186
+ if (!(parsed instanceof SxClass)) {
187
+ throw new Error(
188
+ `gr_poly primitive child did not resolve to an SxClass: ${JSON.stringify(primitive)}`,
189
+ )
190
+ }
191
+
192
+ if (parsed instanceof Pts) {
193
+ polygon._contours.push(parsed)
194
+ continue
195
+ }
196
+
197
+ if (parsed instanceof Width) {
198
+ if (polygon._sxWidth) {
199
+ throw new Error("gr_poly encountered duplicate width tokens")
200
+ }
201
+ polygon._sxWidth = parsed
202
+ continue
203
+ }
204
+
205
+ if (parsed instanceof PadPrimitiveFill) {
206
+ if (polygon._sxFill) {
207
+ throw new Error("gr_poly encountered duplicate fill tokens")
208
+ }
209
+ polygon._sxFill = parsed
210
+ continue
211
+ }
212
+
213
+ throw new Error(`gr_poly encountered unsupported token "${parsed.token}"`)
214
+ }
215
+
216
+ if (polygon._contours.length === 0) {
217
+ throw new Error("gr_poly requires at least one pts child")
218
+ }
219
+
220
+ return polygon
221
+ }
222
+
223
+ get contours(): Pts[] {
224
+ return [...this._contours]
225
+ }
226
+
227
+ set contours(value: Pts[]) {
228
+ this._contours = [...value]
229
+ }
230
+
231
+ get width(): number | undefined {
232
+ return this._sxWidth?.value
233
+ }
234
+
235
+ set width(value: number | undefined) {
236
+ this._sxWidth = value === undefined ? undefined : new Width(value)
237
+ }
238
+
239
+ get filled(): boolean | undefined {
240
+ return this._sxFill?.value
241
+ }
242
+
243
+ set filled(value: boolean | undefined) {
244
+ this._sxFill =
245
+ value === undefined ? undefined : new PadPrimitiveFill({ value })
246
+ }
247
+
248
+ override getChildren(): SxClass[] {
249
+ const children: SxClass[] = []
250
+ children.push(...this._contours)
251
+ if (this._sxWidth) children.push(this._sxWidth)
252
+ if (this._sxFill) children.push(this._sxFill)
253
+ return children
254
+ }
255
+ }
256
+ SxClass.register(PadPrimitiveGrPoly)
257
+
258
+ class PadPrimitiveFill extends SxPrimitiveBoolean {
259
+ static override token = "fill"
260
+ static override parentToken = "gr_poly"
261
+ override token = "fill"
262
+
263
+ constructor(options: { value?: boolean } = {}) {
264
+ super(options.value ?? false)
265
+ }
266
+
267
+ static override fromSexprPrimitives(
268
+ primitiveSexprs: PrimitiveSExpr[],
269
+ ): PadPrimitiveFill {
270
+ const [raw] = primitiveSexprs
271
+ if (raw === undefined) {
272
+ return new PadPrimitiveFill({ value: false })
273
+ }
274
+ if (typeof raw === "boolean") {
275
+ return new PadPrimitiveFill({ value: raw })
276
+ }
277
+ if (typeof raw === "string") {
278
+ return new PadPrimitiveFill({ value: raw.toLowerCase() === "yes" })
279
+ }
280
+ throw new Error(
281
+ `gr_poly fill expects yes/no or boolean, received ${JSON.stringify(raw)}`,
282
+ )
283
+ }
284
+
285
+ override getString(): string {
286
+ return `(fill ${this.value ? "yes" : "no"})`
287
+ }
288
+ }
289
+ SxClass.register(PadPrimitiveFill)
@@ -0,0 +1,57 @@
1
+ import { SxClass } from "../base-classes/SxClass"
2
+ import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
3
+ import { toNumberValue } from "../utils/toNumberValue"
4
+
5
+ export class PadRectDelta extends SxClass {
6
+ static override token = "rect_delta"
7
+ static override parentToken = "pad"
8
+ override token = "rect_delta"
9
+
10
+ private _x: number
11
+ private _y: number
12
+
13
+ constructor(x = 0, y = 0) {
14
+ super()
15
+ this._x = x
16
+ this._y = y
17
+ }
18
+
19
+ static override fromSexprPrimitives(
20
+ primitiveSexprs: PrimitiveSExpr[],
21
+ ): PadRectDelta {
22
+ const [rawX, rawY] = primitiveSexprs
23
+ const x = toNumberValue(rawX)
24
+ const y = toNumberValue(rawY)
25
+
26
+ if (x === undefined || y === undefined) {
27
+ throw new Error("pad rect_delta expects two numeric arguments")
28
+ }
29
+
30
+ return new PadRectDelta(x, y)
31
+ }
32
+
33
+ get x(): number {
34
+ return this._x
35
+ }
36
+
37
+ set x(value: number) {
38
+ this._x = value
39
+ }
40
+
41
+ get y(): number {
42
+ return this._y
43
+ }
44
+
45
+ set y(value: number) {
46
+ this._y = value
47
+ }
48
+
49
+ override getChildren(): SxClass[] {
50
+ return []
51
+ }
52
+
53
+ override getString(): string {
54
+ return `(rect_delta ${this._x} ${this._y})`
55
+ }
56
+ }
57
+ SxClass.register(PadRectDelta)
@@ -0,0 +1,9 @@
1
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
2
+ import { SxClass } from "../base-classes/SxClass"
3
+
4
+ export class PadRoundrectRratio extends SxPrimitiveNumber {
5
+ static override token = "roundrect_rratio"
6
+ static override parentToken = "pad"
7
+ token = "roundrect_rratio"
8
+ }
9
+ SxClass.register(PadRoundrectRratio)
@@ -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 PadSize extends SxClass {
6
+ static override token = "size"
7
+ static override parentToken = "pad"
8
+ token = "size"
9
+
10
+ private _width: number
11
+ private _height: number
12
+
13
+ constructor(width: number, height: number) {
14
+ super()
15
+ this._width = width
16
+ this._height = height
17
+ }
18
+
19
+ static override fromSexprPrimitives(
20
+ primitiveSexprs: PrimitiveSExpr[],
21
+ ): PadSize {
22
+ const width = toNumberValue(primitiveSexprs[0])
23
+ const height = toNumberValue(primitiveSexprs[1])
24
+ if (width === undefined || height === undefined) {
25
+ throw new Error("size requires width and height numeric values")
26
+ }
27
+ return new PadSize(width, height)
28
+ }
29
+
30
+ get width(): number {
31
+ return this._width
32
+ }
33
+
34
+ set width(value: number) {
35
+ this._width = value
36
+ }
37
+
38
+ get height(): number {
39
+ return this._height
40
+ }
41
+
42
+ set height(value: number) {
43
+ this._height = value
44
+ }
45
+
46
+ override getChildren(): SxClass[] {
47
+ return []
48
+ }
49
+
50
+ override getString(): string {
51
+ return `(size ${this._width} ${this._height})`
52
+ }
53
+ }
54
+ SxClass.register(PadSize)
@@ -0,0 +1,9 @@
1
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
2
+ import { SxClass } from "../base-classes/SxClass"
3
+
4
+ export class PadSolderMaskMargin extends SxPrimitiveNumber {
5
+ static override token = "solder_mask_margin"
6
+ static override parentToken = "pad"
7
+ token = "solder_mask_margin"
8
+ }
9
+ SxClass.register(PadSolderMaskMargin)
@@ -0,0 +1,9 @@
1
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
2
+ import { SxClass } from "../base-classes/SxClass"
3
+
4
+ export class PadSolderPasteMargin extends SxPrimitiveNumber {
5
+ static override token = "solder_paste_margin"
6
+ static override parentToken = "pad"
7
+ token = "solder_paste_margin"
8
+ }
9
+ SxClass.register(PadSolderPasteMargin)
@@ -0,0 +1,9 @@
1
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
2
+ import { SxClass } from "../base-classes/SxClass"
3
+
4
+ export class PadSolderPasteMarginRatio extends SxPrimitiveNumber {
5
+ static override token = "solder_paste_margin_ratio"
6
+ static override parentToken = "pad"
7
+ token = "solder_paste_margin_ratio"
8
+ }
9
+ SxClass.register(PadSolderPasteMarginRatio)
@@ -0,0 +1,208 @@
1
+ import { SxClass } from "../base-classes/SxClass"
2
+ import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
3
+ import { toNumberValue } from "../utils/toNumberValue"
4
+ import { parseYesNo } from "../utils/parseYesNo"
5
+
6
+ type NumericTeardropProperty =
7
+ | "bestLengthRatio"
8
+ | "maxLength"
9
+ | "bestWidthRatio"
10
+ | "maxWidth"
11
+ | "filterRatio"
12
+
13
+ type BooleanTeardropProperty =
14
+ | "curvedEdges"
15
+ | "enabled"
16
+ | "allowTwoSegments"
17
+ | "preferZoneConnections"
18
+
19
+ const NUMERIC_TOKENS = new Map<string, NumericTeardropProperty>([
20
+ ["best_length_ratio", "bestLengthRatio"],
21
+ ["max_length", "maxLength"],
22
+ ["best_width_ratio", "bestWidthRatio"],
23
+ ["max_width", "maxWidth"],
24
+ ["filter_ratio", "filterRatio"],
25
+ ])
26
+
27
+ const BOOLEAN_TOKENS = new Map<string, BooleanTeardropProperty>([
28
+ ["curved_edges", "curvedEdges"],
29
+ ["enabled", "enabled"],
30
+ ["allow_two_segments", "allowTwoSegments"],
31
+ ["prefer_zone_connections", "preferZoneConnections"],
32
+ ])
33
+
34
+ export class PadTeardrops extends SxClass {
35
+ static override token = "teardrops"
36
+ static override parentToken = "pad"
37
+ override token = "teardrops"
38
+
39
+ private _bestLengthRatio?: number
40
+ private _maxLength?: number
41
+ private _bestWidthRatio?: number
42
+ private _maxWidth?: number
43
+ private _filterRatio?: number
44
+ private _curvedEdges?: boolean
45
+ private _enabled?: boolean
46
+ private _allowTwoSegments?: boolean
47
+ private _preferZoneConnections?: boolean
48
+
49
+ static override fromSexprPrimitives(
50
+ primitiveSexprs: PrimitiveSExpr[],
51
+ ): PadTeardrops {
52
+ const teardrops = new PadTeardrops()
53
+
54
+ for (const primitive of primitiveSexprs) {
55
+ if (!Array.isArray(primitive) || primitive.length === 0) {
56
+ throw new Error(
57
+ `teardrops encountered invalid child expression: ${JSON.stringify(primitive)}`,
58
+ )
59
+ }
60
+ const [rawToken, rawValue] = primitive
61
+ if (typeof rawToken !== "string") {
62
+ throw new Error(
63
+ `teardrops encountered non-string token: ${JSON.stringify(rawToken)}`,
64
+ )
65
+ }
66
+
67
+ if (NUMERIC_TOKENS.has(rawToken)) {
68
+ const property = NUMERIC_TOKENS.get(rawToken)!
69
+ const numeric = toNumberValue(rawValue)
70
+ if (numeric === undefined) {
71
+ throw new Error(
72
+ `teardrops ${rawToken} expects a numeric value, received ${JSON.stringify(rawValue)}`,
73
+ )
74
+ }
75
+ teardrops[property] = numeric
76
+ continue
77
+ }
78
+
79
+ if (BOOLEAN_TOKENS.has(rawToken)) {
80
+ const property = BOOLEAN_TOKENS.get(rawToken)!
81
+ const booleanValue = parseYesNo(rawValue)
82
+ if (booleanValue === undefined) {
83
+ throw new Error(
84
+ `teardrops ${rawToken} expects yes/no, received ${JSON.stringify(rawValue)}`,
85
+ )
86
+ }
87
+ teardrops[property] = booleanValue
88
+ continue
89
+ }
90
+
91
+ throw new Error(`teardrops encountered unsupported token "${rawToken}"`)
92
+ }
93
+
94
+ return teardrops
95
+ }
96
+
97
+ get bestLengthRatio(): number | undefined {
98
+ return this._bestLengthRatio
99
+ }
100
+
101
+ set bestLengthRatio(value: number | undefined) {
102
+ this._bestLengthRatio = value
103
+ }
104
+
105
+ get maxLength(): number | undefined {
106
+ return this._maxLength
107
+ }
108
+
109
+ set maxLength(value: number | undefined) {
110
+ this._maxLength = value
111
+ }
112
+
113
+ get bestWidthRatio(): number | undefined {
114
+ return this._bestWidthRatio
115
+ }
116
+
117
+ set bestWidthRatio(value: number | undefined) {
118
+ this._bestWidthRatio = value
119
+ }
120
+
121
+ get maxWidth(): number | undefined {
122
+ return this._maxWidth
123
+ }
124
+
125
+ set maxWidth(value: number | undefined) {
126
+ this._maxWidth = value
127
+ }
128
+
129
+ get filterRatio(): number | undefined {
130
+ return this._filterRatio
131
+ }
132
+
133
+ set filterRatio(value: number | undefined) {
134
+ this._filterRatio = value
135
+ }
136
+
137
+ get curvedEdges(): boolean | undefined {
138
+ return this._curvedEdges
139
+ }
140
+
141
+ set curvedEdges(value: boolean | undefined) {
142
+ this._curvedEdges = value
143
+ }
144
+
145
+ get enabled(): boolean | undefined {
146
+ return this._enabled
147
+ }
148
+
149
+ set enabled(value: boolean | undefined) {
150
+ this._enabled = value
151
+ }
152
+
153
+ get allowTwoSegments(): boolean | undefined {
154
+ return this._allowTwoSegments
155
+ }
156
+
157
+ set allowTwoSegments(value: boolean | undefined) {
158
+ this._allowTwoSegments = value
159
+ }
160
+
161
+ get preferZoneConnections(): boolean | undefined {
162
+ return this._preferZoneConnections
163
+ }
164
+
165
+ set preferZoneConnections(value: boolean | undefined) {
166
+ this._preferZoneConnections = value
167
+ }
168
+
169
+ override getChildren(): SxClass[] {
170
+ return []
171
+ }
172
+
173
+ override getString(): string {
174
+ const lines = ["(teardrops"]
175
+ if (this._bestLengthRatio !== undefined) {
176
+ lines.push(` (best_length_ratio ${this._bestLengthRatio})`)
177
+ }
178
+ if (this._maxLength !== undefined) {
179
+ lines.push(` (max_length ${this._maxLength})`)
180
+ }
181
+ if (this._bestWidthRatio !== undefined) {
182
+ lines.push(` (best_width_ratio ${this._bestWidthRatio})`)
183
+ }
184
+ if (this._maxWidth !== undefined) {
185
+ lines.push(` (max_width ${this._maxWidth})`)
186
+ }
187
+ if (this._curvedEdges !== undefined) {
188
+ lines.push(` (curved_edges ${this._curvedEdges ? "yes" : "no"})`)
189
+ }
190
+ if (this._filterRatio !== undefined) {
191
+ lines.push(` (filter_ratio ${this._filterRatio})`)
192
+ }
193
+ if (this._enabled !== undefined) {
194
+ lines.push(` (enabled ${this._enabled ? "yes" : "no"})`)
195
+ }
196
+ if (this._allowTwoSegments !== undefined) {
197
+ lines.push(` (allow_two_segments ${this._allowTwoSegments ? "yes" : "no"})`)
198
+ }
199
+ if (this._preferZoneConnections !== undefined) {
200
+ lines.push(
201
+ ` (prefer_zone_connections ${this._preferZoneConnections ? "yes" : "no"})`,
202
+ )
203
+ }
204
+ lines.push(")")
205
+ return lines.join("\n")
206
+ }
207
+ }
208
+ SxClass.register(PadTeardrops)
@@ -0,0 +1,9 @@
1
+ import { SxClass } from "../base-classes/SxClass"
2
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
3
+
4
+ export class PadThermalBridgeAngle extends SxPrimitiveNumber {
5
+ static override token = "thermal_bridge_angle"
6
+ static override parentToken = "pad"
7
+ override token = "thermal_bridge_angle"
8
+ }
9
+ SxClass.register(PadThermalBridgeAngle)
@@ -0,0 +1,9 @@
1
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
2
+ import { SxClass } from "../base-classes/SxClass"
3
+
4
+ export class PadThermalGap extends SxPrimitiveNumber {
5
+ static override token = "thermal_gap"
6
+ static override parentToken = "pad"
7
+ token = "thermal_gap"
8
+ }
9
+ SxClass.register(PadThermalGap)
@@ -0,0 +1,9 @@
1
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
2
+ import { SxClass } from "../base-classes/SxClass"
3
+
4
+ export class PadThermalWidth extends SxPrimitiveNumber {
5
+ static override token = "thermal_width"
6
+ static override parentToken = "pad"
7
+ token = "thermal_width"
8
+ }
9
+ SxClass.register(PadThermalWidth)
@@ -0,0 +1,9 @@
1
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
2
+ import { SxClass } from "../base-classes/SxClass"
3
+
4
+ export class PadZoneConnect extends SxPrimitiveNumber {
5
+ static override token = "zone_connect"
6
+ static override parentToken = "pad"
7
+ token = "zone_connect"
8
+ }
9
+ SxClass.register(PadZoneConnect)