altium-toolkit 0.1.0 → 0.1.16

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 (54) hide show
  1. package/README.md +24 -6
  2. package/docs/api.md +42 -4
  3. package/docs/model-format.md +95 -5
  4. package/docs/schemas/altium_toolkit/normalized_model_a1.schema.json +553 -0
  5. package/docs/testing.md +7 -2
  6. package/package.json +21 -2
  7. package/spec/library-scope.md +7 -1
  8. package/src/core/altium/AltiumParser.mjs +22 -325
  9. package/src/core/altium/NormalizedModelSchema.mjs +28 -0
  10. package/src/core/altium/PcbArcPrimitiveParser.mjs +87 -0
  11. package/src/core/altium/PcbBinaryPrimitiveParser.mjs +43 -370
  12. package/src/core/altium/PcbBoardRegionSemanticsParser.mjs +477 -0
  13. package/src/core/altium/PcbComponentAnnotationNormalizer.mjs +290 -0
  14. package/src/core/altium/PcbComponentBodyPlacementNormalizer.mjs +52 -0
  15. package/src/core/altium/PcbComponentPrimitiveIndexer.mjs +109 -0
  16. package/src/core/altium/PcbEmbeddedFontExtractor.mjs +484 -0
  17. package/src/core/altium/PcbFillPrimitiveParser.mjs +84 -0
  18. package/src/core/altium/PcbFontMetricsParser.mjs +308 -0
  19. package/src/core/altium/PcbGeometryFlipper.mjs +244 -0
  20. package/src/core/altium/PcbLayerIdCodec.mjs +136 -0
  21. package/src/core/altium/PcbLibModelParser.mjs +202 -0
  22. package/src/core/altium/PcbLibStreamExtractor.mjs +968 -0
  23. package/src/core/altium/PcbModelParser.mjs +618 -66
  24. package/src/core/altium/PcbOutlineRecovery.mjs +4 -112
  25. package/src/core/altium/PcbPadPrimitiveParser.mjs +347 -0
  26. package/src/core/altium/PcbPadShapeCodec.mjs +158 -0
  27. package/src/core/altium/PcbPadStackParser.mjs +903 -0
  28. package/src/core/altium/PcbPrimitiveOwnershipIndexParser.mjs +60 -0
  29. package/src/core/altium/PcbPrimitiveParameterParser.mjs +212 -0
  30. package/src/core/altium/PcbPrimitiveRecordSlicer.mjs +243 -0
  31. package/src/core/altium/PcbRawRecordRegistry.mjs +831 -0
  32. package/src/core/altium/PcbRegionPrimitiveParser.mjs +317 -0
  33. package/src/core/altium/PcbRuleParser.mjs +587 -0
  34. package/src/core/altium/PcbStreamExtractor.mjs +127 -4
  35. package/src/core/altium/PcbTextPrimitiveParser.mjs +537 -0
  36. package/src/core/altium/PcbTrackPrimitiveParser.mjs +87 -0
  37. package/src/core/altium/PcbViaPrimitiveParser.mjs +88 -0
  38. package/src/core/altium/PcbViaStackParser.mjs +548 -0
  39. package/src/core/altium/PcbWideStringTableParser.mjs +108 -0
  40. package/src/core/altium/PrjPcbModelParser.mjs +797 -0
  41. package/src/core/altium/SchematicComponentTextResolver.mjs +355 -0
  42. package/src/parser.mjs +13 -0
  43. package/src/renderers.mjs +5 -0
  44. package/src/styles/altium-renderers.css +11 -6
  45. package/src/ui/PcbCopperPrimitiveSplitter.mjs +113 -0
  46. package/src/ui/PcbEdgeFacingGlyphNormalizer.mjs +6 -5
  47. package/src/ui/PcbEmbeddedFontFaceRenderer.mjs +126 -0
  48. package/src/ui/PcbFootprintPrimitiveSelector.mjs +27 -6
  49. package/src/ui/PcbRegionPrimitiveRenderer.mjs +243 -0
  50. package/src/ui/PcbSideResolvedRenderModel.mjs +336 -0
  51. package/src/ui/PcbSvgRenderer.mjs +101 -109
  52. package/src/ui/PcbTextPrimitiveRenderer.mjs +252 -0
  53. package/src/ui/SchematicSheetChromeRenderer.mjs +2 -93
  54. package/src/ui/SchematicSheetZoneRenderer.mjs +104 -0
@@ -0,0 +1,553 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:altium-toolkit:normalized-model:a1",
4
+ "$comment": "SPDX-FileCopyrightText: 2026 André Fiedler; SPDX-License-Identifier: CC-BY-SA-4.0",
5
+ "title": "Altium Toolkit Normalized Model A1",
6
+ "description": "Root contract for normalized models emitted by Altium Toolkit parser entrypoints.",
7
+ "type": "object",
8
+ "required": [
9
+ "schema",
10
+ "kind",
11
+ "fileType",
12
+ "fileName",
13
+ "summary",
14
+ "diagnostics",
15
+ "bom"
16
+ ],
17
+ "properties": {
18
+ "schema": {
19
+ "const": "urn:altium-toolkit:normalized-model:a1"
20
+ },
21
+ "kind": {
22
+ "enum": ["schematic", "pcb", "pcb-library", "project"]
23
+ },
24
+ "fileType": {
25
+ "enum": ["SchDoc", "PcbDoc", "PcbLib", "PrjPcb"]
26
+ },
27
+ "fileName": {
28
+ "type": "string"
29
+ },
30
+ "summary": {
31
+ "type": "object",
32
+ "additionalProperties": {
33
+ "type": ["number", "string", "boolean", "null"]
34
+ }
35
+ },
36
+ "diagnostics": {
37
+ "type": "array",
38
+ "items": {
39
+ "type": "object",
40
+ "required": ["severity", "message"],
41
+ "properties": {
42
+ "severity": {
43
+ "enum": ["info", "warning"]
44
+ },
45
+ "message": {
46
+ "type": "string"
47
+ }
48
+ },
49
+ "additionalProperties": true
50
+ }
51
+ },
52
+ "schematic": {
53
+ "type": "object"
54
+ },
55
+ "pcb": {
56
+ "type": "object",
57
+ "properties": {
58
+ "components": {
59
+ "type": "array",
60
+ "items": {
61
+ "$ref": "#/$defs/pcbComponent"
62
+ }
63
+ },
64
+ "embeddedFonts": {
65
+ "$ref": "#/$defs/embeddedFonts"
66
+ },
67
+ "rawRecords": {
68
+ "$ref": "#/$defs/rawRecords"
69
+ },
70
+ "layerSubstacks": {
71
+ "$ref": "#/$defs/layerSubstacks"
72
+ },
73
+ "boardRegionContexts": {
74
+ "$ref": "#/$defs/boardRegionContexts"
75
+ },
76
+ "componentPrimitives": {
77
+ "type": "array",
78
+ "items": {
79
+ "anyOf": [
80
+ {
81
+ "$ref": "#/$defs/componentPrimitiveGroup"
82
+ },
83
+ {
84
+ "type": "null"
85
+ }
86
+ ]
87
+ }
88
+ },
89
+ "componentPrimitiveGroups": {
90
+ "type": "array",
91
+ "items": {
92
+ "$ref": "#/$defs/componentPrimitiveGroup"
93
+ }
94
+ },
95
+ "texts": {
96
+ "type": "array",
97
+ "items": {
98
+ "$ref": "#/$defs/pcbText"
99
+ }
100
+ }
101
+ },
102
+ "additionalProperties": true
103
+ },
104
+ "pcbLibrary": {
105
+ "type": "object",
106
+ "properties": {
107
+ "embeddedFonts": {
108
+ "$ref": "#/$defs/embeddedFonts"
109
+ },
110
+ "footprints": {
111
+ "type": "array",
112
+ "items": {
113
+ "type": "object",
114
+ "properties": {
115
+ "rawRecords": {
116
+ "$ref": "#/$defs/rawRecords"
117
+ }
118
+ },
119
+ "additionalProperties": true
120
+ }
121
+ }
122
+ },
123
+ "additionalProperties": true
124
+ },
125
+ "project": {
126
+ "type": "object"
127
+ },
128
+ "bom": {
129
+ "type": "array",
130
+ "items": {
131
+ "type": "object"
132
+ }
133
+ }
134
+ },
135
+ "oneOf": [
136
+ {
137
+ "required": ["schematic"],
138
+ "properties": {
139
+ "kind": {
140
+ "const": "schematic"
141
+ },
142
+ "fileType": {
143
+ "const": "SchDoc"
144
+ }
145
+ }
146
+ },
147
+ {
148
+ "required": ["pcb"],
149
+ "properties": {
150
+ "kind": {
151
+ "const": "pcb"
152
+ },
153
+ "fileType": {
154
+ "const": "PcbDoc"
155
+ }
156
+ }
157
+ },
158
+ {
159
+ "required": ["pcbLibrary"],
160
+ "properties": {
161
+ "kind": {
162
+ "const": "pcb-library"
163
+ },
164
+ "fileType": {
165
+ "const": "PcbLib"
166
+ }
167
+ }
168
+ },
169
+ {
170
+ "required": ["project"],
171
+ "properties": {
172
+ "kind": {
173
+ "const": "project"
174
+ },
175
+ "fileType": {
176
+ "const": "PrjPcb"
177
+ }
178
+ }
179
+ }
180
+ ],
181
+ "$defs": {
182
+ "rawRecords": {
183
+ "type": "array",
184
+ "items": {
185
+ "type": "object",
186
+ "required": [
187
+ "registryId",
188
+ "source",
189
+ "sourceStream",
190
+ "family",
191
+ "type",
192
+ "recordIndex",
193
+ "offset",
194
+ "byteLength",
195
+ "encoding",
196
+ "supported",
197
+ "parsed",
198
+ "rawBase64"
199
+ ],
200
+ "properties": {
201
+ "registryId": {
202
+ "type": "string"
203
+ },
204
+ "source": {
205
+ "enum": ["pcbdoc", "pcblib"]
206
+ },
207
+ "sourceStorage": {
208
+ "type": "string"
209
+ },
210
+ "sourceStream": {
211
+ "type": "string"
212
+ },
213
+ "headerStream": {
214
+ "type": "string"
215
+ },
216
+ "family": {
217
+ "type": "string"
218
+ },
219
+ "type": {
220
+ "type": "string"
221
+ },
222
+ "typeId": {
223
+ "type": ["number", "null"]
224
+ },
225
+ "recordIndex": {
226
+ "type": "number"
227
+ },
228
+ "offset": {
229
+ "type": "number"
230
+ },
231
+ "byteLength": {
232
+ "type": "number"
233
+ },
234
+ "payloadByteLength": {
235
+ "type": ["number", "null"]
236
+ },
237
+ "encoding": {
238
+ "type": "string"
239
+ },
240
+ "supported": {
241
+ "type": "boolean"
242
+ },
243
+ "parsed": {
244
+ "type": "boolean"
245
+ },
246
+ "rawBase64": {
247
+ "type": "string"
248
+ }
249
+ },
250
+ "additionalProperties": true
251
+ }
252
+ },
253
+ "pcbComponent": {
254
+ "type": "object",
255
+ "required": [
256
+ "componentIndex",
257
+ "designator",
258
+ "x",
259
+ "y",
260
+ "layer",
261
+ "pattern",
262
+ "rotation",
263
+ "source",
264
+ "description",
265
+ "height"
266
+ ],
267
+ "properties": {
268
+ "componentIndex": {
269
+ "type": "number"
270
+ },
271
+ "designator": {
272
+ "type": "string"
273
+ },
274
+ "baseDesignator": {
275
+ "type": "string"
276
+ },
277
+ "displayDesignator": {
278
+ "type": "string"
279
+ },
280
+ "designatorSource": {
281
+ "const": "Texts6/Data"
282
+ },
283
+ "uniqueId": {
284
+ "type": "string"
285
+ },
286
+ "parameters": {
287
+ "type": "object",
288
+ "additionalProperties": {
289
+ "type": "string"
290
+ }
291
+ },
292
+ "parameterSource": {
293
+ "const": "PrimitiveParameters/Data"
294
+ },
295
+ "x": {
296
+ "type": "number"
297
+ },
298
+ "y": {
299
+ "type": "number"
300
+ },
301
+ "layer": {
302
+ "type": "string"
303
+ },
304
+ "pattern": {
305
+ "type": "string"
306
+ },
307
+ "rotation": {
308
+ "type": "number"
309
+ },
310
+ "source": {
311
+ "type": "string"
312
+ },
313
+ "description": {
314
+ "type": "string"
315
+ },
316
+ "height": {
317
+ "type": ["number", "null"]
318
+ }
319
+ },
320
+ "additionalProperties": true
321
+ },
322
+ "pcbText": {
323
+ "type": "object",
324
+ "properties": {
325
+ "text": {
326
+ "type": "string"
327
+ },
328
+ "textSource": {
329
+ "const": "WideStrings6/Data"
330
+ },
331
+ "role": {
332
+ "type": "string"
333
+ },
334
+ "isDesignator": {
335
+ "type": "boolean"
336
+ },
337
+ "isComment": {
338
+ "type": "boolean"
339
+ },
340
+ "isPlaceholder": {
341
+ "type": "boolean"
342
+ },
343
+ "componentIndex": {
344
+ "type": ["number", "null"]
345
+ },
346
+ "embeddedFontIndex": {
347
+ "type": "number"
348
+ },
349
+ "fontMetrics": {
350
+ "type": "object",
351
+ "additionalProperties": {
352
+ "type": ["number", "string", "boolean", "null"]
353
+ }
354
+ }
355
+ },
356
+ "additionalProperties": true
357
+ },
358
+ "layerSubstacks": {
359
+ "type": "array",
360
+ "items": {
361
+ "type": "object",
362
+ "required": ["index", "fieldFamily", "id", "name"],
363
+ "properties": {
364
+ "index": {
365
+ "type": "number"
366
+ },
367
+ "fieldFamily": {
368
+ "type": "string"
369
+ },
370
+ "id": {
371
+ "type": "string"
372
+ },
373
+ "name": {
374
+ "type": "string"
375
+ },
376
+ "isFlex": {
377
+ "type": ["boolean", "null"]
378
+ },
379
+ "showTopDielectric": {
380
+ "type": ["boolean", "null"]
381
+ },
382
+ "showBottomDielectric": {
383
+ "type": ["boolean", "null"]
384
+ },
385
+ "serviceStackup": {
386
+ "type": ["boolean", "null"]
387
+ },
388
+ "usedByPrimitives": {
389
+ "type": ["boolean", "null"]
390
+ },
391
+ "rawStackupType": {
392
+ "type": "string"
393
+ }
394
+ },
395
+ "additionalProperties": true
396
+ }
397
+ },
398
+ "boardRegionContexts": {
399
+ "type": "array",
400
+ "items": {
401
+ "type": "object",
402
+ "required": [
403
+ "regionIndex",
404
+ "name",
405
+ "layerStackId",
406
+ "substackIndex",
407
+ "substackName",
408
+ "isFlex",
409
+ "locked3d",
410
+ "bendingLineCount"
411
+ ],
412
+ "properties": {
413
+ "regionIndex": {
414
+ "type": "number"
415
+ },
416
+ "name": {
417
+ "type": "string"
418
+ },
419
+ "layerStackId": {
420
+ "type": "string"
421
+ },
422
+ "substackIndex": {
423
+ "type": ["number", "null"]
424
+ },
425
+ "substackName": {
426
+ "type": "string"
427
+ },
428
+ "isFlex": {
429
+ "type": ["boolean", "null"]
430
+ },
431
+ "locked3d": {
432
+ "type": "boolean"
433
+ },
434
+ "bendingLineCount": {
435
+ "type": "number"
436
+ }
437
+ },
438
+ "additionalProperties": true
439
+ }
440
+ },
441
+ "embeddedFonts": {
442
+ "type": "array",
443
+ "items": {
444
+ "type": "object",
445
+ "required": [
446
+ "index",
447
+ "name",
448
+ "style",
449
+ "fileName",
450
+ "sourceStream",
451
+ "format",
452
+ "mimeType",
453
+ "byteCount",
454
+ "compressedByteCount",
455
+ "payloadBase64",
456
+ "metrics"
457
+ ],
458
+ "properties": {
459
+ "index": {
460
+ "type": "number"
461
+ },
462
+ "name": {
463
+ "type": "string"
464
+ },
465
+ "style": {
466
+ "type": "string"
467
+ },
468
+ "fileName": {
469
+ "type": "string"
470
+ },
471
+ "sourceStream": {
472
+ "type": "string"
473
+ },
474
+ "format": {
475
+ "enum": ["truetype", "opentype", "unknown"]
476
+ },
477
+ "mimeType": {
478
+ "type": "string"
479
+ },
480
+ "byteCount": {
481
+ "type": "number"
482
+ },
483
+ "compressedByteCount": {
484
+ "type": "number"
485
+ },
486
+ "payloadBase64": {
487
+ "type": "string"
488
+ },
489
+ "metrics": {
490
+ "type": "object",
491
+ "additionalProperties": {
492
+ "type": ["number", "string", "boolean", "null"]
493
+ }
494
+ }
495
+ },
496
+ "additionalProperties": true
497
+ }
498
+ },
499
+ "componentPrimitiveGroup": {
500
+ "type": "object",
501
+ "required": [
502
+ "componentIndex",
503
+ "designator",
504
+ "pads",
505
+ "tracks",
506
+ "arcs",
507
+ "fills",
508
+ "vias",
509
+ "regions",
510
+ "shapeBasedRegions",
511
+ "texts",
512
+ "componentBodies"
513
+ ],
514
+ "properties": {
515
+ "componentIndex": {
516
+ "type": "number"
517
+ },
518
+ "designator": {
519
+ "type": "string"
520
+ },
521
+ "pads": {
522
+ "type": "array"
523
+ },
524
+ "tracks": {
525
+ "type": "array"
526
+ },
527
+ "arcs": {
528
+ "type": "array"
529
+ },
530
+ "fills": {
531
+ "type": "array"
532
+ },
533
+ "vias": {
534
+ "type": "array"
535
+ },
536
+ "regions": {
537
+ "type": "array"
538
+ },
539
+ "shapeBasedRegions": {
540
+ "type": "array"
541
+ },
542
+ "texts": {
543
+ "type": "array"
544
+ },
545
+ "componentBodies": {
546
+ "type": "array"
547
+ }
548
+ },
549
+ "additionalProperties": true
550
+ }
551
+ },
552
+ "additionalProperties": true
553
+ }
package/docs/testing.md CHANGED
@@ -15,9 +15,14 @@ npm test
15
15
  The tests cover:
16
16
 
17
17
  - Binary and OLE helpers
18
- - Printable and binary Altium parser recovery
18
+ - Printable and binary Altium parser recovery for `.SchDoc`, `.PcbDoc`,
19
+ `.PcbLib`, and `.PrjPcb` entrypoints
20
+ - PCB primitive stream slicing and focused decoders for tracks, fills, arcs,
21
+ vias, pads, text, regions, rules, raw records, board regions, ownership
22
+ indexes, sidecar PrimitiveParameters/Text tables, and embedded font metadata
19
23
  - Obfuscated fake schematic and PCB fixture shards
20
- - Schematic SVG, PCB SVG, BOM HTML, and static 3D summary renderers
24
+ - Schematic SVG, side-resolved PCB SVG, BOM HTML, and static 3D summary
25
+ renderers
21
26
  - Non-interactive PCB 3D scene-description builders and model registry logic
22
27
 
23
28
  Fixture data must remain repo-owned and obfuscated. Do not add native provided
package/package.json CHANGED
@@ -1,7 +1,22 @@
1
1
  {
2
2
  "name": "altium-toolkit",
3
- "version": "0.1.0",
3
+ "version": "0.1.16",
4
4
  "description": "Altium document parsing and non-interactive rendering utilities",
5
+ "keywords": [
6
+ "altium",
7
+ "altium-designer",
8
+ "schdoc",
9
+ "pcbdoc",
10
+ "ecad",
11
+ "eda",
12
+ "pcb",
13
+ "schematic",
14
+ "parser",
15
+ "renderer",
16
+ "svg",
17
+ "bom",
18
+ "3d"
19
+ ],
5
20
  "license": "GPL-3.0-or-later",
6
21
  "type": "module",
7
22
  "main": "./src/index.mjs",
@@ -16,6 +31,10 @@
16
31
  "files": [
17
32
  "src",
18
33
  "docs",
34
+ "!docs/.superpowers",
35
+ "!docs/.superpowers/**",
36
+ "!docs/superpowers",
37
+ "!docs/superpowers/**",
19
38
  "examples",
20
39
  "spec",
21
40
  "LICENSE",
@@ -34,7 +53,7 @@
34
53
  },
35
54
  "dependencies": {
36
55
  "fflate": "^0.8.2",
37
- "three": "^0.183.2"
56
+ "three": "^0.184.0"
38
57
  },
39
58
  "devDependencies": {
40
59
  "prettier": "^3.4.2"
@@ -11,15 +11,21 @@ rendering primitives.
11
11
 
12
12
  ## In Scope
13
13
 
14
- - `.SchDoc` and `.PcbDoc` parsing from `ArrayBuffer`
14
+ - `.SchDoc`, `.PcbDoc`, `.PcbLib`, and `.PrjPcb` parsing from `ArrayBuffer`
15
15
  - OLE and binary stream helpers needed by parser recovery
16
16
  - Schematic SVG rendering
17
17
  - PCB SVG rendering
18
18
  - BOM HTML rendering
19
19
  - PCB 3D scene-description data
20
+ - Embedded PCB/PcbLib font extraction and basic text metrics for deterministic
21
+ SVG rendering
22
+ - Read-only PCB primitive record registry metadata and base64 raw-record
23
+ preservation for unsupported or partially decoded PcbDoc/PcbLib streams
20
24
  - Static 3D summary HTML
21
25
  - Parser worker entrypoint for host applications
22
26
  - Optional renderer CSS
27
+ - Versioned normalized model schema identifiers and machine-readable schema
28
+ contracts
23
29
 
24
30
  ## Out Of Scope
25
31