altium-toolkit 1.0.9 → 1.0.10

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 (30) hide show
  1. package/docs/schemas/altium_toolkit/ci_artifact_bundle_a1.schema.json +76 -0
  2. package/docs/schemas/altium_toolkit/draftsman_digest_a1.schema.json +35 -0
  3. package/docs/schemas/altium_toolkit/netlist_a1.schema.json +6 -0
  4. package/docs/schemas/altium_toolkit/normalized_model_a1.schema.json +160 -1
  5. package/docs/schemas/altium_toolkit/parser_compatibility_fuzz_a1.schema.json +25 -0
  6. package/docs/schemas/altium_toolkit/pcb_svg_semantics_a1.schema.json +27 -0
  7. package/docs/schemas/altium_toolkit/project_bundle_a1.schema.json +6 -0
  8. package/docs/schemas/altium_toolkit/project_document_graph_a1.schema.json +33 -0
  9. package/docs/schemas/altium_toolkit/svg_model_cross_link_a1.schema.json +39 -0
  10. package/package.json +1 -1
  11. package/src/core/altium/AltiumParser.mjs +7 -2
  12. package/src/core/altium/CiArtifactBundleBuilder.mjs +202 -0
  13. package/src/core/altium/DraftsmanDigestParser.mjs +689 -0
  14. package/src/core/altium/ParserCompatibilityFuzzer.mjs +192 -0
  15. package/src/core/altium/PcbModelParser.mjs +29 -4
  16. package/src/core/altium/PcbPadStackParser.mjs +171 -2
  17. package/src/core/altium/PcbPickPlacePositionResolver.mjs +8 -1
  18. package/src/core/altium/PcbRegionPrimitiveParser.mjs +71 -2
  19. package/src/core/altium/PcbRouteAnalysisBuilder.mjs +730 -0
  20. package/src/core/altium/PcbStatisticsBuilder.mjs +9 -0
  21. package/src/core/altium/PrjPcbModelParser.mjs +24 -2
  22. package/src/core/altium/ProjectDesignBundleBuilder.mjs +15 -0
  23. package/src/core/altium/ProjectDocumentGraphBuilder.mjs +280 -0
  24. package/src/core/altium/ProjectNetlistExporter.mjs +5 -1
  25. package/src/core/altium/SvgModelCrossLinkValidator.mjs +402 -0
  26. package/src/core/circuit-json/CircuitJsonModelAdapter.mjs +136 -96
  27. package/src/core/circuit-json/CircuitJsonModelAdapterPcbElements.mjs +244 -0
  28. package/src/core/circuit-json/CircuitJsonModelSchema.mjs +1 -1
  29. package/src/parser.mjs +6 -0
  30. package/src/ui/PcbSvgRenderer.mjs +65 -0
@@ -0,0 +1,76 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.ci.artifact-bundle.a1",
4
+ "title": "Altium Toolkit CI Artifact Bundle A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": [
8
+ "schema",
9
+ "summary",
10
+ "designBundle",
11
+ "documentGraph",
12
+ "normalizedModels",
13
+ "netlist",
14
+ "bom",
15
+ "pnp",
16
+ "schematicSvgs",
17
+ "pcbLayerSvgs",
18
+ "statistics",
19
+ "diagnostics"
20
+ ],
21
+ "properties": {
22
+ "schema": {
23
+ "const": "altium-toolkit.ci.artifact-bundle.a1"
24
+ },
25
+ "summary": {
26
+ "type": "object",
27
+ "additionalProperties": true
28
+ },
29
+ "units": {
30
+ "type": "object",
31
+ "additionalProperties": {
32
+ "type": "string"
33
+ }
34
+ },
35
+ "designBundle": {
36
+ "type": "object"
37
+ },
38
+ "documentGraph": {
39
+ "type": "object"
40
+ },
41
+ "normalizedModels": {
42
+ "type": "array"
43
+ },
44
+ "netlist": {
45
+ "type": "object",
46
+ "required": ["json", "wirelist"],
47
+ "properties": {
48
+ "json": {
49
+ "type": "object"
50
+ },
51
+ "wirelist": {
52
+ "type": "string"
53
+ }
54
+ },
55
+ "additionalProperties": true
56
+ },
57
+ "bom": {
58
+ "type": "object"
59
+ },
60
+ "pnp": {
61
+ "type": "object"
62
+ },
63
+ "schematicSvgs": {
64
+ "type": "array"
65
+ },
66
+ "pcbLayerSvgs": {
67
+ "type": "array"
68
+ },
69
+ "statistics": {
70
+ "type": "object"
71
+ },
72
+ "diagnostics": {
73
+ "type": "array"
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.draftsman.digest.a1",
4
+ "title": "Altium Toolkit Draftsman Digest A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schema", "pages"],
8
+ "properties": {
9
+ "schema": {
10
+ "const": "altium-toolkit.draftsman.digest.a1"
11
+ },
12
+ "sourceDocumentName": {
13
+ "type": "string"
14
+ },
15
+ "pages": {
16
+ "type": "array",
17
+ "items": {
18
+ "type": "object",
19
+ "additionalProperties": true,
20
+ "required": [
21
+ "index",
22
+ "title",
23
+ "titleBlocks",
24
+ "notes",
25
+ "images",
26
+ "unsupportedRawItems"
27
+ ]
28
+ }
29
+ },
30
+ "indexes": {
31
+ "type": "object",
32
+ "additionalProperties": true
33
+ }
34
+ }
35
+ }
@@ -12,6 +12,12 @@
12
12
  "project": {
13
13
  "type": "string"
14
14
  },
15
+ "units": {
16
+ "type": "object",
17
+ "additionalProperties": {
18
+ "type": "string"
19
+ }
20
+ },
15
21
  "nets": {
16
22
  "type": "array",
17
23
  "items": {
@@ -26,6 +26,7 @@
26
26
  "project",
27
27
  "project-annotation",
28
28
  "integrated-library",
29
+ "draftsman",
29
30
  "design-bundle"
30
31
  ]
31
32
  },
@@ -37,6 +38,7 @@
37
38
  "PrjPcb",
38
39
  "Annotation",
39
40
  "IntLib",
41
+ "PCBDwf",
40
42
  "ProjectDesignBundle"
41
43
  ]
42
44
  },
@@ -187,6 +189,9 @@
187
189
  "pickPlace": {
188
190
  "$ref": "#/$defs/pickPlaceModel"
189
191
  },
192
+ "routeAnalysis": {
193
+ "$ref": "#/$defs/pcbRouteAnalysis"
194
+ },
190
195
  "embeddedFonts": {
191
196
  "$ref": "#/$defs/embeddedFonts"
192
197
  },
@@ -286,7 +291,16 @@
286
291
  "additionalProperties": true
287
292
  },
288
293
  "project": {
289
- "type": "object"
294
+ "type": "object",
295
+ "properties": {
296
+ "documentGraph": {
297
+ "$ref": "#/$defs/projectDocumentGraph"
298
+ }
299
+ },
300
+ "additionalProperties": true
301
+ },
302
+ "units": {
303
+ "$ref": "#/$defs/units"
290
304
  },
291
305
  "variants": {
292
306
  "type": "array",
@@ -329,6 +343,9 @@
329
343
  "integratedLibrary": {
330
344
  "$ref": "#/$defs/integratedLibrary"
331
345
  },
346
+ "draftsman": {
347
+ "$ref": "#/$defs/draftsmanDigest"
348
+ },
332
349
  "bom": {
333
350
  "type": "array",
334
351
  "items": {
@@ -406,6 +423,17 @@
406
423
  }
407
424
  }
408
425
  },
426
+ {
427
+ "required": ["draftsman"],
428
+ "properties": {
429
+ "kind": {
430
+ "const": "draftsman"
431
+ },
432
+ "fileType": {
433
+ "const": "PCBDwf"
434
+ }
435
+ }
436
+ },
409
437
  {
410
438
  "required": ["project", "sheets", "schematic_hierarchy", "indexes"],
411
439
  "properties": {
@@ -451,6 +479,59 @@
451
479
  },
452
480
  "additionalProperties": true
453
481
  },
482
+ "projectDocumentGraph": {
483
+ "type": "object",
484
+ "required": ["schema", "summary", "documents", "groups", "indexes"],
485
+ "properties": {
486
+ "schema": {
487
+ "const": "altium-toolkit.project.document-graph.a1"
488
+ },
489
+ "summary": {
490
+ "type": "object",
491
+ "additionalProperties": true
492
+ },
493
+ "documents": {
494
+ "type": "array",
495
+ "items": {
496
+ "type": "object",
497
+ "additionalProperties": true
498
+ }
499
+ },
500
+ "groups": {
501
+ "type": "object",
502
+ "additionalProperties": true
503
+ },
504
+ "indexes": {
505
+ "type": "object",
506
+ "additionalProperties": true
507
+ }
508
+ },
509
+ "additionalProperties": true
510
+ },
511
+ "draftsmanDigest": {
512
+ "type": "object",
513
+ "required": ["schema", "pages"],
514
+ "properties": {
515
+ "schema": {
516
+ "const": "altium-toolkit.draftsman.digest.a1"
517
+ },
518
+ "sourceDocumentName": {
519
+ "type": "string"
520
+ },
521
+ "pages": {
522
+ "type": "array",
523
+ "items": {
524
+ "type": "object",
525
+ "additionalProperties": true
526
+ }
527
+ },
528
+ "indexes": {
529
+ "type": "object",
530
+ "additionalProperties": true
531
+ }
532
+ },
533
+ "additionalProperties": true
534
+ },
454
535
  "schematicRenderDiagnostics": {
455
536
  "type": "object",
456
537
  "required": ["schema", "fontFallbacks"],
@@ -617,6 +698,39 @@
617
698
  },
618
699
  "extendedPrimitiveInformation": {
619
700
  "$ref": "#/$defs/pcbExtendedPrimitiveInformationEntry"
701
+ },
702
+ "localStack": {
703
+ "$ref": "#/$defs/pcbPadLocalStack"
704
+ }
705
+ },
706
+ "additionalProperties": true
707
+ },
708
+ "pcbPadLocalStack": {
709
+ "type": "object",
710
+ "required": ["schema", "mode", "modeName", "source", "layers"],
711
+ "properties": {
712
+ "schema": {
713
+ "const": "altium-toolkit.pcb.pad-local-stack.a1"
714
+ },
715
+ "mode": {
716
+ "type": "number"
717
+ },
718
+ "modeName": {
719
+ "type": "string"
720
+ },
721
+ "source": {
722
+ "type": "string"
723
+ },
724
+ "layers": {
725
+ "type": "array",
726
+ "items": {
727
+ "type": "object",
728
+ "additionalProperties": true
729
+ }
730
+ },
731
+ "hole": {
732
+ "type": "object",
733
+ "additionalProperties": true
620
734
  }
621
735
  },
622
736
  "additionalProperties": true
@@ -1446,6 +1560,9 @@
1446
1560
  "type": "object",
1447
1561
  "required": ["positionMode", "entries", "modes"],
1448
1562
  "properties": {
1563
+ "units": {
1564
+ "$ref": "#/$defs/units"
1565
+ },
1449
1566
  "positionMode": {
1450
1567
  "enum": ["altium-pick-place", "component-origin"]
1451
1568
  },
@@ -1462,6 +1579,9 @@
1462
1579
  "type": "object",
1463
1580
  "required": ["positionMode", "entries"],
1464
1581
  "properties": {
1582
+ "units": {
1583
+ "$ref": "#/$defs/units"
1584
+ },
1465
1585
  "positionMode": {
1466
1586
  "const": "component-origin"
1467
1587
  },
@@ -1934,6 +2054,9 @@
1934
2054
  "schema": {
1935
2055
  "const": "altium-toolkit.pcb.statistics.a1"
1936
2056
  },
2057
+ "units": {
2058
+ "$ref": "#/$defs/units"
2059
+ },
1937
2060
  "board": {
1938
2061
  "type": "object",
1939
2062
  "additionalProperties": true
@@ -1957,6 +2080,42 @@
1957
2080
  },
1958
2081
  "additionalProperties": true
1959
2082
  },
2083
+ "pcbRouteAnalysis": {
2084
+ "type": "object",
2085
+ "required": ["schema", "units", "summary", "byNet"],
2086
+ "properties": {
2087
+ "schema": {
2088
+ "const": "altium-toolkit.pcb.route-analysis.a1"
2089
+ },
2090
+ "units": {
2091
+ "$ref": "#/$defs/units"
2092
+ },
2093
+ "summary": {
2094
+ "type": "object",
2095
+ "additionalProperties": true
2096
+ },
2097
+ "byNet": {
2098
+ "type": "array",
2099
+ "items": {
2100
+ "type": "object",
2101
+ "additionalProperties": true
2102
+ }
2103
+ },
2104
+ "classes": {
2105
+ "type": "array"
2106
+ },
2107
+ "differentialPairs": {
2108
+ "type": "array"
2109
+ }
2110
+ },
2111
+ "additionalProperties": true
2112
+ },
2113
+ "units": {
2114
+ "type": "object",
2115
+ "additionalProperties": {
2116
+ "type": "string"
2117
+ }
2118
+ },
1960
2119
  "libraryRenderManifest": {
1961
2120
  "type": "object",
1962
2121
  "properties": {
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.parser-compatibility-fuzz.a1",
4
+ "title": "Altium Toolkit Parser Compatibility Fuzz A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schema", "summary", "cases"],
8
+ "properties": {
9
+ "schema": {
10
+ "const": "altium-toolkit.parser-compatibility-fuzz.a1"
11
+ },
12
+ "summary": {
13
+ "type": "object",
14
+ "additionalProperties": true
15
+ },
16
+ "cases": {
17
+ "type": "array",
18
+ "items": {
19
+ "type": "object",
20
+ "additionalProperties": true,
21
+ "required": ["key", "status"]
22
+ }
23
+ }
24
+ }
25
+ }
@@ -27,6 +27,33 @@
27
27
  "boardOutline": {
28
28
  "type": "object"
29
29
  },
30
+ "lookups": {
31
+ "type": "object",
32
+ "additionalProperties": true,
33
+ "properties": {
34
+ "netsByIndex": {
35
+ "type": "object"
36
+ },
37
+ "netIndexByName": {
38
+ "type": "object"
39
+ },
40
+ "netClassesByName": {
41
+ "type": "object"
42
+ },
43
+ "componentsByIndex": {
44
+ "type": "object"
45
+ },
46
+ "componentIndexByDesignator": {
47
+ "type": "object"
48
+ },
49
+ "layersByKey": {
50
+ "type": "object"
51
+ },
52
+ "layerKeyByDisplayName": {
53
+ "type": "object"
54
+ }
55
+ }
56
+ },
30
57
  "layers": {
31
58
  "type": "array"
32
59
  },
@@ -23,6 +23,12 @@
23
23
  "project": {
24
24
  "type": "object"
25
25
  },
26
+ "units": {
27
+ "type": "object",
28
+ "additionalProperties": {
29
+ "type": "string"
30
+ }
31
+ },
26
32
  "variants": {
27
33
  "type": "array"
28
34
  },
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.project.document-graph.a1",
4
+ "title": "Altium Toolkit Project Document Graph A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": ["schema", "summary", "documents", "groups", "indexes"],
8
+ "properties": {
9
+ "schema": {
10
+ "const": "altium-toolkit.project.document-graph.a1"
11
+ },
12
+ "summary": {
13
+ "type": "object",
14
+ "additionalProperties": true
15
+ },
16
+ "documents": {
17
+ "type": "array",
18
+ "items": {
19
+ "type": "object",
20
+ "additionalProperties": true,
21
+ "required": ["normalizedPath", "kind"]
22
+ }
23
+ },
24
+ "groups": {
25
+ "type": "object",
26
+ "additionalProperties": true
27
+ },
28
+ "indexes": {
29
+ "type": "object",
30
+ "additionalProperties": true
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "altium-toolkit.svg-model-cross-link.a1",
4
+ "title": "Altium Toolkit SVG Model Cross-Link A1",
5
+ "type": "object",
6
+ "additionalProperties": true,
7
+ "required": [
8
+ "schema",
9
+ "documentKind",
10
+ "summary",
11
+ "missingElements",
12
+ "orphanElements",
13
+ "unresolvedReferences"
14
+ ],
15
+ "properties": {
16
+ "schema": {
17
+ "const": "altium-toolkit.svg-model-cross-link.a1"
18
+ },
19
+ "documentKind": {
20
+ "enum": ["schematic", "pcb", "unknown"]
21
+ },
22
+ "summary": {
23
+ "type": "object",
24
+ "additionalProperties": true
25
+ },
26
+ "missingElements": {
27
+ "type": "array"
28
+ },
29
+ "orphanElements": {
30
+ "type": "array"
31
+ },
32
+ "unresolvedReferences": {
33
+ "type": "array"
34
+ },
35
+ "metadata": {
36
+ "type": "object"
37
+ }
38
+ }
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "altium-toolkit",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "Altium document parsing and non-interactive rendering utilities",
5
5
  "keywords": [
6
6
  "altium",
@@ -15,6 +15,7 @@ import { AltiumLayoutParser } from './AltiumLayoutParser.mjs'
15
15
  import { NormalizedModelSchema } from './NormalizedModelSchema.mjs'
16
16
  import { IntLibModelParser } from './IntLibModelParser.mjs'
17
17
  import { IntLibStreamExtractor } from './IntLibStreamExtractor.mjs'
18
+ import { DraftsmanDigestParser } from './DraftsmanDigestParser.mjs'
18
19
  import { PcbModelParser } from './PcbModelParser.mjs'
19
20
  import { PcbLibModelParser } from './PcbLibModelParser.mjs'
20
21
  import { PcbLibStreamExtractor } from './PcbLibStreamExtractor.mjs'
@@ -89,7 +90,7 @@ export class AltiumParser {
89
90
  * Parses a native Altium buffer into the renderer compatibility model.
90
91
  * @param {string} fileName
91
92
  * @param {ArrayBuffer} arrayBuffer
92
- * @returns {{ schema: string, kind: 'schematic' | 'pcb' | 'pcb-library' | 'project' | 'integrated-library', fileType: 'SchDoc' | 'PcbDoc' | 'PcbLib' | 'PrjPcb' | 'IntLib', fileName: string, summary: Record<string, number | string>, diagnostics: { severity: 'info' | 'warning', message: string }[], schematic?: Record<string, unknown>, pcb?: Record<string, unknown>, pcbLibrary?: Record<string, unknown>, project?: Record<string, unknown>, integratedLibrary?: Record<string, unknown>, bom: { designators: string[], quantity: number, pattern: string, source: string, value: string }[] }}
93
+ * @returns {{ schema: string, kind: 'schematic' | 'pcb' | 'pcb-library' | 'project' | 'integrated-library' | 'draftsman', fileType: 'SchDoc' | 'PcbDoc' | 'PcbLib' | 'PrjPcb' | 'IntLib' | 'PCBDwf', fileName: string, summary: Record<string, number | string>, diagnostics: { severity: 'info' | 'warning', message: string }[], schematic?: Record<string, unknown>, pcb?: Record<string, unknown>, pcbLibrary?: Record<string, unknown>, project?: Record<string, unknown>, integratedLibrary?: Record<string, unknown>, draftsman?: Record<string, unknown>, bom: { designators: string[], quantity: number, pattern: string, source: string, value: string }[] }}
93
94
  */
94
95
  static parseArrayBufferToRendererModel(fileName, arrayBuffer) {
95
96
  const records = AsciiRecordParser.parse(arrayBuffer)
@@ -128,6 +129,9 @@ export class AltiumParser {
128
129
  IntLibStreamExtractor.extractFromArrayBuffer(arrayBuffer)
129
130
  )
130
131
  }
132
+ if (fileType === 'PCBDwf') {
133
+ return DraftsmanDigestParser.parse(fileName, arrayBuffer)
134
+ }
131
135
  throw new Error('Unsupported file type: ' + fileName)
132
136
  }
133
137
 
@@ -135,7 +139,7 @@ export class AltiumParser {
135
139
  * Chooses the format based on extension and content.
136
140
  * @param {string} fileName
137
141
  * @param {{ fields: Record<string, string | string[]> }[]} records
138
- * @returns {'SchDoc' | 'PcbDoc' | 'PcbLib' | 'PrjPcb' | 'IntLib'}
142
+ * @returns {'SchDoc' | 'PcbDoc' | 'PcbLib' | 'PrjPcb' | 'IntLib' | 'PCBDwf'}
139
143
  */
140
144
  static #sniffFileType(fileName, records) {
141
145
  const normalized = String(fileName || '').toLowerCase()
@@ -144,6 +148,7 @@ export class AltiumParser {
144
148
  if (normalized.endsWith('.pcblib')) return 'PcbLib'
145
149
  if (normalized.endsWith('.prjpcb')) return 'PrjPcb'
146
150
  if (normalized.endsWith('.intlib')) return 'IntLib'
151
+ if (normalized.endsWith('.pcbdwf')) return 'PCBDwf'
147
152
 
148
153
  const hasSchematicHeader = records.some((record) =>
149
154
  getField(record.fields, 'HEADER').includes('Schematic')