kicadts 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.github/workflows/bun-formatcheck.yml +26 -0
  2. package/.github/workflows/bun-pver-release.yml +70 -0
  3. package/.github/workflows/bun-test.yml +32 -0
  4. package/.github/workflows/bun-typecheck.yml +26 -0
  5. package/.vscode/settings.json +1 -1
  6. package/AGENTS.md +1 -0
  7. package/LICENSE +21 -0
  8. package/README.md +101 -91
  9. package/TODO.md +46 -0
  10. package/bunfig.toml +2 -2
  11. package/lib/sexpr/classes/At.ts +15 -0
  12. package/lib/sexpr/classes/Bus.ts +23 -3
  13. package/lib/sexpr/classes/BusEntry.ts +30 -3
  14. package/lib/sexpr/classes/EmbeddedFonts.ts +1 -3
  15. package/lib/sexpr/classes/Footprint.ts +157 -27
  16. package/lib/sexpr/classes/FootprintAttr.ts +3 -1
  17. package/lib/sexpr/classes/FootprintModel.ts +1 -4
  18. package/lib/sexpr/classes/FootprintNetTiePadGroups.ts +3 -1
  19. package/lib/sexpr/classes/FootprintPad.ts +206 -54
  20. package/lib/sexpr/classes/FpArc.ts +23 -0
  21. package/lib/sexpr/classes/FpCircle.ts +24 -3
  22. package/lib/sexpr/classes/FpLine.ts +31 -3
  23. package/lib/sexpr/classes/FpPoly.ts +24 -4
  24. package/lib/sexpr/classes/FpRect.ts +24 -3
  25. package/lib/sexpr/classes/FpText.ts +43 -9
  26. package/lib/sexpr/classes/FpTextBox.ts +43 -5
  27. package/lib/sexpr/classes/GrLine.ts +20 -1
  28. package/lib/sexpr/classes/GrText.ts +38 -12
  29. package/lib/sexpr/classes/Image.ts +38 -11
  30. package/lib/sexpr/classes/Junction.ts +36 -4
  31. package/lib/sexpr/classes/KicadPcb.ts +49 -1
  32. package/lib/sexpr/classes/KicadSch.ts +119 -25
  33. package/lib/sexpr/classes/Label.ts +45 -5
  34. package/lib/sexpr/classes/NoConnect.ts +20 -3
  35. package/lib/sexpr/classes/PadLayers.ts +13 -1
  36. package/lib/sexpr/classes/PadOptions.ts +4 -5
  37. package/lib/sexpr/classes/PadPrimitiveGrArc.ts +22 -4
  38. package/lib/sexpr/classes/PadPrimitiveGrCircle.ts +23 -4
  39. package/lib/sexpr/classes/PadPrimitives.ts +3 -1
  40. package/lib/sexpr/classes/PadSize.ts +15 -0
  41. package/lib/sexpr/classes/PadTeardrops.ts +3 -1
  42. package/lib/sexpr/classes/PcbGeneral.ts +14 -7
  43. package/lib/sexpr/classes/PcbLayerDefinition.ts +5 -1
  44. package/lib/sexpr/classes/Property.ts +64 -9
  45. package/lib/sexpr/classes/Pts.ts +7 -5
  46. package/lib/sexpr/classes/SchematicText.ts +39 -9
  47. package/lib/sexpr/classes/Segment.ts +21 -0
  48. package/lib/sexpr/classes/SegmentNet.ts +3 -1
  49. package/lib/sexpr/classes/Setup/PcbPlotParams.ts +10 -50
  50. package/lib/sexpr/classes/Setup/Setup.ts +12 -11
  51. package/lib/sexpr/classes/Setup/Stackup.ts +14 -19
  52. package/lib/sexpr/classes/Setup/StackupLayerProperties.ts +3 -1
  53. package/lib/sexpr/classes/Setup/StackupProperties.ts +0 -1
  54. package/lib/sexpr/classes/Setup/base.ts +1 -3
  55. package/lib/sexpr/classes/Setup/setupMultiValueProperties.ts +0 -1
  56. package/lib/sexpr/classes/Sheet.ts +85 -3
  57. package/lib/sexpr/classes/SheetPin.ts +4 -1
  58. package/lib/sexpr/classes/Symbol.ts +176 -51
  59. package/lib/sexpr/classes/TextEffects.ts +25 -8
  60. package/lib/sexpr/classes/TitleBlock.ts +21 -4
  61. package/lib/sexpr/classes/Via.ts +38 -3
  62. package/lib/sexpr/classes/ViaNet.ts +2 -1
  63. package/lib/sexpr/classes/Wire.ts +23 -3
  64. package/lib/sexpr/classes/Xy.ts +1 -3
  65. package/lib/sexpr/classes/Zone.ts +1 -3
  66. package/lib/sexpr/parseToPrimitiveSExpr.ts +6 -1
  67. package/lib/sexpr/utils/strokeFromArgs.ts +5 -6
  68. package/lib/sexpr/utils/toStringValue.ts +2 -1
  69. package/package.json +2 -1
  70. package/scripts/download-references.ts +24 -22
  71. package/tests/fixtures/expectEqualPrimitiveSExpr.ts +6 -7
  72. package/tests/fixtures/png-matcher.ts +109 -0
  73. package/tests/fixtures/preload.ts +1 -0
  74. package/tests/sexpr/classes/FootprintPad.test.ts +8 -1
  75. package/tests/sexpr/classes/Image.test.ts +9 -1
  76. package/tests/sexpr/classes/KicadSch.test.ts +1 -3
  77. package/tests/sexpr/classes/Setup.test.ts +0 -1
  78. package/bun.lock +0 -48
@@ -46,6 +46,26 @@ const SUPPORTED_CHILD_TOKENS = new Set([
46
46
  ...MULTI_CHILD_TOKENS,
47
47
  ])
48
48
 
49
+ export interface KicadSchConstructorParams {
50
+ version?: number | KicadSchVersion
51
+ generator?: string | KicadSchGenerator
52
+ generatorVersion?: string | KicadSchGeneratorVersion
53
+ uuid?: string | Uuid
54
+ paper?: Paper
55
+ titleBlock?: TitleBlock
56
+ libSymbols?: LibSymbols
57
+ sheetInstances?: SheetInstances
58
+ embeddedFonts?: EmbeddedFonts
59
+ properties?: Property[]
60
+ images?: Image[]
61
+ sheets?: Sheet[]
62
+ symbols?: SchematicSymbol[]
63
+ texts?: SchematicText[]
64
+ labels?: Label[]
65
+ wires?: Wire[]
66
+ junctions?: Junction[]
67
+ }
68
+
49
69
  export class KicadSch extends SxClass {
50
70
  static override token = "kicad_sch"
51
71
  token = "kicad_sch"
@@ -68,11 +88,87 @@ export class KicadSch extends SxClass {
68
88
  private _wires: Wire[] = []
69
89
  private _junctions: Junction[] = []
70
90
 
91
+ constructor(params: KicadSchConstructorParams = {}) {
92
+ super()
93
+
94
+ if (params.version instanceof KicadSchVersion) {
95
+ this._sxVersion = params.version
96
+ } else if (params.version !== undefined) {
97
+ this.version = params.version
98
+ }
99
+
100
+ if (params.generator instanceof KicadSchGenerator) {
101
+ this._sxGenerator = params.generator
102
+ } else if (params.generator !== undefined) {
103
+ this.generator = params.generator
104
+ }
105
+
106
+ if (params.generatorVersion instanceof KicadSchGeneratorVersion) {
107
+ this._sxGeneratorVersion = params.generatorVersion
108
+ } else if (params.generatorVersion !== undefined) {
109
+ this.generatorVersion = params.generatorVersion
110
+ }
111
+
112
+ if (params.uuid !== undefined) {
113
+ this.uuid = params.uuid
114
+ }
115
+
116
+ if (params.paper !== undefined) {
117
+ this.paper = params.paper
118
+ }
119
+
120
+ if (params.titleBlock !== undefined) {
121
+ this.titleBlock = params.titleBlock
122
+ }
123
+
124
+ if (params.libSymbols !== undefined) {
125
+ this.libSymbols = params.libSymbols
126
+ }
127
+
128
+ if (params.sheetInstances !== undefined) {
129
+ this.sheetInstances = params.sheetInstances
130
+ }
131
+
132
+ if (params.embeddedFonts !== undefined) {
133
+ this.embeddedFonts = params.embeddedFonts
134
+ }
135
+
136
+ if (params.properties !== undefined) {
137
+ this.properties = params.properties
138
+ }
139
+
140
+ if (params.images !== undefined) {
141
+ this.images = params.images
142
+ }
143
+
144
+ if (params.sheets !== undefined) {
145
+ this.sheets = params.sheets
146
+ }
147
+
148
+ if (params.symbols !== undefined) {
149
+ this.symbols = params.symbols
150
+ }
151
+
152
+ if (params.texts !== undefined) {
153
+ this.texts = params.texts
154
+ }
155
+
156
+ if (params.labels !== undefined) {
157
+ this.labels = params.labels
158
+ }
159
+
160
+ if (params.wires !== undefined) {
161
+ this.wires = params.wires
162
+ }
163
+
164
+ if (params.junctions !== undefined) {
165
+ this.junctions = params.junctions
166
+ }
167
+ }
168
+
71
169
  static override fromSexprPrimitives(
72
170
  primitiveSexprs: PrimitiveSExpr[],
73
171
  ): KicadSch {
74
- const kicadSch = new KicadSch()
75
-
76
172
  for (const primitive of primitiveSexprs) {
77
173
  if (!Array.isArray(primitive)) {
78
174
  throw new Error(
@@ -110,29 +206,27 @@ export class KicadSch extends SxClass {
110
206
  }
111
207
  }
112
208
 
113
- kicadSch._sxVersion = propertyMap.version as KicadSchVersion | undefined
114
- kicadSch._sxGenerator = propertyMap.generator as
115
- | KicadSchGenerator
116
- | undefined
117
- kicadSch._sxGeneratorVersion = propertyMap.generator_version as
118
- | KicadSchGeneratorVersion
119
- | undefined
120
- kicadSch._sxUuid = propertyMap.uuid as Uuid | undefined
121
- kicadSch._sxPaper = propertyMap.paper as Paper | undefined
122
- kicadSch._sxTitleBlock = propertyMap.title_block as TitleBlock | undefined
123
- kicadSch._sxLibSymbols = propertyMap.lib_symbols as LibSymbols | undefined
124
- kicadSch._sxSheetInstances = propertyMap.sheet_instances as SheetInstances | undefined
125
- kicadSch._sxEmbeddedFonts = propertyMap.embedded_fonts as EmbeddedFonts | undefined
126
- kicadSch._properties = (arrayPropertyMap.property as Property[]) ?? []
127
- kicadSch._images = (arrayPropertyMap.image as Image[]) ?? []
128
- kicadSch._sheets = (arrayPropertyMap.sheet as Sheet[]) ?? []
129
- kicadSch._symbols = (arrayPropertyMap.symbol as SchematicSymbol[]) ?? []
130
- kicadSch._texts = (arrayPropertyMap.text as SchematicText[]) ?? []
131
- kicadSch._labels = (arrayPropertyMap.label as Label[]) ?? []
132
- kicadSch._junctions = (arrayPropertyMap.junction as Junction[]) ?? []
133
- kicadSch._wires = (arrayPropertyMap.wire as Wire[]) ?? []
134
-
135
- return kicadSch
209
+ return new KicadSch({
210
+ version: propertyMap.version as KicadSchVersion | undefined,
211
+ generator: propertyMap.generator as KicadSchGenerator | undefined,
212
+ generatorVersion: propertyMap.generator_version as
213
+ | KicadSchGeneratorVersion
214
+ | undefined,
215
+ uuid: propertyMap.uuid as Uuid | undefined,
216
+ paper: propertyMap.paper as Paper | undefined,
217
+ titleBlock: propertyMap.title_block as TitleBlock | undefined,
218
+ libSymbols: propertyMap.lib_symbols as LibSymbols | undefined,
219
+ sheetInstances: propertyMap.sheet_instances as SheetInstances | undefined,
220
+ embeddedFonts: propertyMap.embedded_fonts as EmbeddedFonts | undefined,
221
+ properties: (arrayPropertyMap.property as Property[]) ?? [],
222
+ images: (arrayPropertyMap.image as Image[]) ?? [],
223
+ sheets: (arrayPropertyMap.sheet as Sheet[]) ?? [],
224
+ symbols: (arrayPropertyMap.symbol as SchematicSymbol[]) ?? [],
225
+ texts: (arrayPropertyMap.text as SchematicText[]) ?? [],
226
+ labels: (arrayPropertyMap.label as Label[]) ?? [],
227
+ junctions: (arrayPropertyMap.junction as Junction[]) ?? [],
228
+ wires: (arrayPropertyMap.wire as Wire[]) ?? [],
229
+ })
136
230
  }
137
231
 
138
232
  get version(): number | undefined {
@@ -2,13 +2,21 @@ import { SxClass } from "../base-classes/SxClass"
2
2
  import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
3
3
  import { quoteSExprString } from "../utils/quoteSExprString"
4
4
  import { toStringValue } from "../utils/toStringValue"
5
- import { At } from "./At"
5
+ import { At, type AtInput } from "./At"
6
6
  import { TextEffects } from "./TextEffects"
7
7
  import { Uuid } from "./Uuid"
8
8
  import { FieldsAutoplaced } from "./FieldsAutoplaced"
9
9
 
10
10
  const SUPPORTED_TOKENS = new Set(["at", "effects", "uuid", "fields_autoplaced"])
11
11
 
12
+ export interface LabelConstructorParams {
13
+ value?: string
14
+ at?: AtInput
15
+ effects?: TextEffects
16
+ uuid?: string | Uuid
17
+ fieldsAutoplaced?: boolean | FieldsAutoplaced
18
+ }
19
+
12
20
  export class Label extends SxClass {
13
21
  static override token = "label"
14
22
  static override parentToken = "kicad_sch"
@@ -20,6 +28,34 @@ export class Label extends SxClass {
20
28
  private _sxUuid?: Uuid
21
29
  private _sxFieldsAutoplaced?: FieldsAutoplaced
22
30
 
31
+ constructor(params: LabelConstructorParams = {}) {
32
+ super()
33
+
34
+ if (params.value !== undefined) {
35
+ this.value = params.value
36
+ }
37
+
38
+ if (params.at !== undefined) {
39
+ this.at = params.at
40
+ }
41
+
42
+ if (params.effects !== undefined) {
43
+ this.effects = params.effects
44
+ }
45
+
46
+ if (params.uuid !== undefined) {
47
+ this.uuid = params.uuid
48
+ }
49
+
50
+ if (params.fieldsAutoplaced !== undefined) {
51
+ if (params.fieldsAutoplaced instanceof FieldsAutoplaced) {
52
+ this._sxFieldsAutoplaced = params.fieldsAutoplaced
53
+ } else {
54
+ this.fieldsAutoplaced = params.fieldsAutoplaced
55
+ }
56
+ }
57
+ }
58
+
23
59
  static override fromSexprPrimitives(
24
60
  primitiveSexprs: PrimitiveSExpr[],
25
61
  ): Label {
@@ -51,7 +87,9 @@ export class Label extends SxClass {
51
87
  )
52
88
  }
53
89
  if (entries.length > 1) {
54
- throw new Error(`label does not support repeated child tokens: ${token}`)
90
+ throw new Error(
91
+ `label does not support repeated child tokens: ${token}`,
92
+ )
55
93
  }
56
94
  }
57
95
 
@@ -65,7 +103,9 @@ export class Label extends SxClass {
65
103
  (arrayPropertyMap.uuid?.[0] as Uuid | undefined) ??
66
104
  (propertyMap.uuid as Uuid | undefined)
67
105
  label._sxFieldsAutoplaced =
68
- (arrayPropertyMap.fields_autoplaced?.[0] as FieldsAutoplaced | undefined) ??
106
+ (arrayPropertyMap.fields_autoplaced?.[0] as
107
+ | FieldsAutoplaced
108
+ | undefined) ??
69
109
  (propertyMap.fields_autoplaced as FieldsAutoplaced | undefined)
70
110
 
71
111
  return label
@@ -83,8 +123,8 @@ export class Label extends SxClass {
83
123
  return this._sxAt
84
124
  }
85
125
 
86
- set at(value: At | undefined) {
87
- this._sxAt = value
126
+ set at(value: AtInput | undefined) {
127
+ this._sxAt = value !== undefined ? At.from(value) : undefined
88
128
  }
89
129
 
90
130
  get effects(): TextEffects | undefined {
@@ -1,10 +1,15 @@
1
1
  import { SxClass } from "../base-classes/SxClass"
2
2
  import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
3
- import { At } from "./At"
3
+ import { At, type AtInput } from "./At"
4
4
  import { Uuid } from "./Uuid"
5
5
 
6
6
  const SUPPORTED_TOKENS = new Set(["at", "uuid"])
7
7
 
8
+ export interface NoConnectConstructorParams {
9
+ at?: AtInput
10
+ uuid?: string | Uuid
11
+ }
12
+
8
13
  export class NoConnect extends SxClass {
9
14
  static override token = "no_connect"
10
15
  static override parentToken = "kicad_sch"
@@ -13,6 +18,18 @@ export class NoConnect extends SxClass {
13
18
  private _sxAt?: At
14
19
  private _sxUuid?: Uuid
15
20
 
21
+ constructor(params: NoConnectConstructorParams = {}) {
22
+ super()
23
+
24
+ if (params.at !== undefined) {
25
+ this.at = params.at
26
+ }
27
+
28
+ if (params.uuid !== undefined) {
29
+ this.uuid = params.uuid
30
+ }
31
+ }
32
+
16
33
  static override fromSexprPrimitives(
17
34
  primitiveSexprs: PrimitiveSExpr[],
18
35
  ): NoConnect {
@@ -47,8 +64,8 @@ export class NoConnect extends SxClass {
47
64
  return this._sxAt
48
65
  }
49
66
 
50
- set at(value: At | undefined) {
51
- this._sxAt = value
67
+ set at(value: AtInput | undefined) {
68
+ this._sxAt = value !== undefined ? At.from(value) : undefined
52
69
  }
53
70
 
54
71
  get uuid(): Uuid | undefined {
@@ -4,6 +4,8 @@ import { printSExpr } from "../parseToPrimitiveSExpr"
4
4
  import { quoteSExprString } from "../utils/quoteSExprString"
5
5
  import { toStringValue } from "../utils/toStringValue"
6
6
 
7
+ export type PadLayersInput = PadLayers | string[]
8
+
7
9
  export class PadLayers extends SxClass {
8
10
  static override token = "layers"
9
11
  static override parentToken = "pad"
@@ -16,6 +18,13 @@ export class PadLayers extends SxClass {
16
18
  this.layers = layers
17
19
  }
18
20
 
21
+ static from(input: PadLayersInput): PadLayers {
22
+ if (input instanceof PadLayers) {
23
+ return input
24
+ }
25
+ return new PadLayers(input)
26
+ }
27
+
19
28
  static override fromSexprPrimitives(
20
29
  primitiveSexprs: PrimitiveSExpr[],
21
30
  ): PadLayers {
@@ -47,7 +56,10 @@ export class PadLayers extends SxClass {
47
56
  }
48
57
  const rendered = this._layers
49
58
  .map((layer) => {
50
- if (/^[^\s()"]+$/u.test(layer) && !["nil", "#t", "#f"].includes(layer)) {
59
+ if (
60
+ /^[^\s()"]+$/u.test(layer) &&
61
+ !["nil", "#t", "#f"].includes(layer)
62
+ ) {
51
63
  return layer
52
64
  }
53
65
  return quoteSExprString(layer)
@@ -5,10 +5,7 @@ import { toStringValue } from "../utils/toStringValue"
5
5
  export type PadOptionsClearanceType = "outline" | "convexhull"
6
6
  export type PadOptionsAnchorShape = "rect" | "circle"
7
7
 
8
- const CLEARANCE_TYPES: PadOptionsClearanceType[] = [
9
- "outline",
10
- "convexhull",
11
- ]
8
+ const CLEARANCE_TYPES: PadOptionsClearanceType[] = ["outline", "convexhull"]
12
9
 
13
10
  const ANCHOR_SHAPES: PadOptionsAnchorShape[] = ["rect", "circle"]
14
11
 
@@ -58,7 +55,9 @@ export class PadOptions extends SxClass {
58
55
  continue
59
56
  }
60
57
 
61
- throw new Error(`pad options encountered unsupported token "${parsed.token}"`)
58
+ throw new Error(
59
+ `pad options encountered unsupported token "${parsed.token}"`,
60
+ )
62
61
  }
63
62
 
64
63
  return options
@@ -5,6 +5,13 @@ import { toNumberValue } from "../utils/toNumberValue"
5
5
 
6
6
  const SUPPORTED_TOKENS = new Set(["start", "mid", "end", "width"])
7
7
 
8
+ export interface PadPrimitiveGrArcConstructorParams {
9
+ start?: PadPrimitiveGrArcStart | { x: number; y: number }
10
+ mid?: PadPrimitiveGrArcMid | { x: number; y: number }
11
+ end?: PadPrimitiveGrArcEnd | { x: number; y: number }
12
+ width?: Width | number
13
+ }
14
+
8
15
  export class PadPrimitiveGrArc extends SxClass {
9
16
  static override token = "gr_arc"
10
17
  static override parentToken = "primitives"
@@ -15,6 +22,14 @@ export class PadPrimitiveGrArc extends SxClass {
15
22
  private _sxEnd?: PadPrimitiveGrArcEnd
16
23
  private _sxWidth?: Width
17
24
 
25
+ constructor(params: PadPrimitiveGrArcConstructorParams = {}) {
26
+ super()
27
+ if (params.start !== undefined) this.start = params.start
28
+ if (params.mid !== undefined) this.mid = params.mid
29
+ if (params.end !== undefined) this.end = params.end
30
+ if (params.width !== undefined) this.width = params.width
31
+ }
32
+
18
33
  static override fromSexprPrimitives(
19
34
  primitiveSexprs: PrimitiveSExpr[],
20
35
  ): PadPrimitiveGrArc {
@@ -66,9 +81,10 @@ export class PadPrimitiveGrArc extends SxClass {
66
81
  return this._sxStart
67
82
  }
68
83
 
69
- set start(
70
- value: PadPrimitiveGrArcStart | { x: number; y: number } | undefined,
71
- ) {
84
+ set start(value:
85
+ | PadPrimitiveGrArcStart
86
+ | { x: number; y: number }
87
+ | undefined,) {
72
88
  this._sxStart = normalizeArcPoint(value, PadPrimitiveGrArcStart)
73
89
  }
74
90
 
@@ -195,7 +211,9 @@ class PadPrimitiveGrArcStart extends PadPrimitiveGrArcPoint {
195
211
  const y = toNumberValue(rawY)
196
212
 
197
213
  if (x === undefined || y === undefined) {
198
- throw new Error("pad primitive gr_arc start expects two numeric arguments")
214
+ throw new Error(
215
+ "pad primitive gr_arc start expects two numeric arguments",
216
+ )
199
217
  }
200
218
 
201
219
  return new PadPrimitiveGrArcStart(x, y)
@@ -6,6 +6,13 @@ import { toNumberValue } from "../utils/toNumberValue"
6
6
 
7
7
  const SUPPORTED_TOKENS = new Set(["center", "end", "width", "fill"])
8
8
 
9
+ export interface PadPrimitiveGrCircleConstructorParams {
10
+ center?: PadPrimitiveGrCircleCenter | { x: number; y: number }
11
+ end?: PadPrimitiveGrCircleEnd | { x: number; y: number }
12
+ width?: Width | number
13
+ fill?: PadPrimitiveGrCircleFill | boolean
14
+ }
15
+
9
16
  export class PadPrimitiveGrCircle extends SxClass {
10
17
  static override token = "gr_circle"
11
18
  static override parentToken = "primitives"
@@ -16,6 +23,14 @@ export class PadPrimitiveGrCircle extends SxClass {
16
23
  private _sxWidth?: Width
17
24
  private _sxFill?: PadPrimitiveGrCircleFill
18
25
 
26
+ constructor(params: PadPrimitiveGrCircleConstructorParams = {}) {
27
+ super()
28
+ if (params.center !== undefined) this.center = params.center
29
+ if (params.end !== undefined) this.end = params.end
30
+ if (params.width !== undefined) this.width = params.width
31
+ if (params.fill !== undefined) this.fill = params.fill
32
+ }
33
+
19
34
  static override fromSexprPrimitives(
20
35
  primitiveSexprs: PrimitiveSExpr[],
21
36
  ): PadPrimitiveGrCircle {
@@ -66,9 +81,10 @@ export class PadPrimitiveGrCircle extends SxClass {
66
81
  return this._sxCenter
67
82
  }
68
83
 
69
- set center(
70
- value: PadPrimitiveGrCircleCenter | { x: number; y: number } | undefined,
71
- ) {
84
+ set center(value:
85
+ | PadPrimitiveGrCircleCenter
86
+ | { x: number; y: number }
87
+ | undefined,) {
72
88
  this._sxCenter = normalizeCirclePoint(value, PadPrimitiveGrCircleCenter)
73
89
  }
74
90
 
@@ -76,7 +92,10 @@ export class PadPrimitiveGrCircle extends SxClass {
76
92
  return this._sxEnd
77
93
  }
78
94
 
79
- set end(value: PadPrimitiveGrCircleEnd | { x: number; y: number } | undefined) {
95
+ set end(value:
96
+ | PadPrimitiveGrCircleEnd
97
+ | { x: number; y: number }
98
+ | undefined) {
80
99
  this._sxEnd = normalizeCirclePoint(value, PadPrimitiveGrCircleEnd)
81
100
  }
82
101
 
@@ -80,7 +80,9 @@ export class PadPrimitives extends SxClass {
80
80
  continue
81
81
  }
82
82
 
83
- throw new Error(`pad primitives encountered unsupported token "${parsed.token}"`)
83
+ throw new Error(
84
+ `pad primitives encountered unsupported token "${parsed.token}"`,
85
+ )
84
86
  }
85
87
 
86
88
  return primitives
@@ -2,6 +2,11 @@ import { SxClass } from "../base-classes/SxClass"
2
2
  import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
3
3
  import { toNumberValue } from "../utils/toNumberValue"
4
4
 
5
+ export type PadSizeInput =
6
+ | PadSize
7
+ | [width: number, height: number]
8
+ | { width: number; height: number }
9
+
5
10
  export class PadSize extends SxClass {
6
11
  static override token = "size"
7
12
  static override parentToken = "pad"
@@ -16,6 +21,16 @@ export class PadSize extends SxClass {
16
21
  this._height = height
17
22
  }
18
23
 
24
+ static from(input: PadSizeInput): PadSize {
25
+ if (input instanceof PadSize) {
26
+ return input
27
+ }
28
+ if (Array.isArray(input)) {
29
+ return new PadSize(input[0], input[1])
30
+ }
31
+ return new PadSize(input.width, input.height)
32
+ }
33
+
19
34
  static override fromSexprPrimitives(
20
35
  primitiveSexprs: PrimitiveSExpr[],
21
36
  ): PadSize {
@@ -194,7 +194,9 @@ export class PadTeardrops extends SxClass {
194
194
  lines.push(` (enabled ${this._enabled ? "yes" : "no"})`)
195
195
  }
196
196
  if (this._allowTwoSegments !== undefined) {
197
- lines.push(` (allow_two_segments ${this._allowTwoSegments ? "yes" : "no"})`)
197
+ lines.push(
198
+ ` (allow_two_segments ${this._allowTwoSegments ? "yes" : "no"})`,
199
+ )
198
200
  }
199
201
  if (this._preferZoneConnections !== undefined) {
200
202
  lines.push(
@@ -22,24 +22,30 @@ export class PcbGeneral extends SxClass {
22
22
 
23
23
  for (const token of Object.keys(propertyMap)) {
24
24
  if (!SINGLE_TOKENS.has(token)) {
25
- throw new Error(`general encountered unsupported child token "${token}"`)
25
+ throw new Error(
26
+ `general encountered unsupported child token "${token}"`,
27
+ )
26
28
  }
27
29
  }
28
30
 
29
31
  for (const [token, entries] of Object.entries(arrayPropertyMap)) {
30
32
  if (!SINGLE_TOKENS.has(token)) {
31
- throw new Error(`general encountered unsupported child token "${token}"`)
33
+ throw new Error(
34
+ `general encountered unsupported child token "${token}"`,
35
+ )
32
36
  }
33
37
  if (entries.length > 1) {
34
38
  throw new Error(`general encountered repeated child token "${token}"`)
35
39
  }
36
40
  }
37
41
 
38
- general._sxThickness = (arrayPropertyMap.thickness?.[0] as
39
- | PcbGeneralThickness
40
- | undefined) ?? (propertyMap.thickness as PcbGeneralThickness | undefined)
42
+ general._sxThickness =
43
+ (arrayPropertyMap.thickness?.[0] as PcbGeneralThickness | undefined) ??
44
+ (propertyMap.thickness as PcbGeneralThickness | undefined)
41
45
  general._sxLegacyTeardrops =
42
- (arrayPropertyMap.legacy_teardrops?.[0] as PcbGeneralLegacyTeardrops | undefined) ??
46
+ (arrayPropertyMap.legacy_teardrops?.[0] as
47
+ | PcbGeneralLegacyTeardrops
48
+ | undefined) ??
43
49
  (propertyMap.legacy_teardrops as PcbGeneralLegacyTeardrops | undefined)
44
50
 
45
51
  return general
@@ -50,7 +56,8 @@ export class PcbGeneral extends SxClass {
50
56
  }
51
57
 
52
58
  set thickness(value: number | undefined) {
53
- this._sxThickness = value === undefined ? undefined : new PcbGeneralThickness(value)
59
+ this._sxThickness =
60
+ value === undefined ? undefined : new PcbGeneralThickness(value)
54
61
  }
55
62
 
56
63
  get legacyTeardrops(): boolean | undefined {
@@ -85,7 +85,11 @@ export class PcbLayerDefinition extends SxClass {
85
85
  }
86
86
 
87
87
  override getString(): string {
88
- if (this._index === undefined || this._name === undefined || this._type === undefined) {
88
+ if (
89
+ this._index === undefined ||
90
+ this._name === undefined ||
91
+ this._type === undefined
92
+ ) {
89
93
  return "()"
90
94
  }
91
95
  const tokens = [