altium-toolkit 0.1.1 → 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 +6 -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
package/README.md CHANGED
@@ -10,14 +10,24 @@ Altium Toolkit is an ESM JavaScript library for parsing native Altium
10
10
  schematic and PCB documents and rendering deterministic, non-interactive
11
11
  outputs from the recovered model.
12
12
 
13
- The package was extracted from ECAD Forge so parser behavior, normalized model
14
- shape, and renderer output can be reused by other browser or Node-based tools.
13
+ The package was extracted from [ECAD Forge](https://ecadforge.app/), where it
14
+ is used for browser-based Altium document parsing and deterministic render
15
+ output. Its parser behavior, normalized model shape, and renderer output can be
16
+ reused by other browser or Node-based tools.
15
17
 
16
18
  ## Features
17
19
 
18
- - Parse standalone native `.SchDoc` and `.PcbDoc` files from `ArrayBuffer`
19
- - Recover schematic records, PCB outlines, placements, primitives, embedded
20
- schematic images, and embedded PCB STEP payload metadata
20
+ - Parse standalone native `.SchDoc`, `.PcbDoc`, `.PcbLib`, and `.PrjPcb` files from
21
+ `ArrayBuffer`
22
+ - Recover schematic records, PCB outlines, placements, PCB library footprints,
23
+ project document references, variants, parameters, primitives, embedded
24
+ schematic images, component annotations from PrimitiveParameters/Text streams,
25
+ embedded PCB STEP payload metadata, and embedded PCB/PcbLib font payloads with
26
+ basic text metrics
27
+ - Preserve raw PCB primitive records through a read-only record registry so
28
+ unsupported or partially decoded stream data remains inspectable
29
+ - Emit versioned normalized model roots with a machine-readable JSON Schema
30
+ contract
21
31
  - Render schematic SVG, PCB SVG, and grouped BOM HTML
22
32
  - Build non-interactive PCB 3D scene-description data for host applications
23
33
  - Render a static 3D board summary
@@ -25,6 +35,9 @@ shape, and renderer output can be reused by other browser or Node-based tools.
25
35
 
26
36
  ## Install
27
37
 
38
+ The package is published on npm as
39
+ [`altium-toolkit`](https://www.npmjs.com/package/altium-toolkit).
40
+
28
41
  ```bash
29
42
  npm install altium-toolkit
30
43
  ```
@@ -36,14 +49,18 @@ import {
36
49
  AltiumParser,
37
50
  SchematicSvgRenderer,
38
51
  PcbSvgRenderer,
52
+ preparePcbSideResolvedRenderModel,
39
53
  BomTableRenderer,
40
54
  PcbScene3dBuilder
41
55
  } from 'altium-toolkit'
42
56
 
43
57
  const documentModel = AltiumParser.parseArrayBuffer(file.name, arrayBuffer)
58
+ const backRenderModel = preparePcbSideResolvedRenderModel(documentModel, {
59
+ side: 'back'
60
+ })
44
61
 
45
62
  const schematicMarkup = SchematicSvgRenderer.render(documentModel)
46
- const pcbMarkup = PcbSvgRenderer.render(documentModel)
63
+ const pcbMarkup = PcbSvgRenderer.render(backRenderModel)
47
64
  const bomMarkup = BomTableRenderer.render(documentModel.bom || [])
48
65
  const sceneDescription = PcbScene3dBuilder.build(documentModel)
49
66
  ```
@@ -58,6 +75,7 @@ import 'altium-toolkit/styles/altium-renderers.css'
58
75
 
59
76
  - [API](docs/api.md)
60
77
  - [Model Format](docs/model-format.md)
78
+ - [Normalized Model Schema](docs/schemas/altium_toolkit/normalized_model_a1.schema.json)
61
79
  - [Testing](docs/testing.md)
62
80
  - [Scope](spec/library-scope.md)
63
81
 
package/docs/api.md CHANGED
@@ -27,10 +27,41 @@ import { AltiumParser } from 'altium-toolkit/parser'
27
27
  const documentModel = AltiumParser.parseArrayBuffer(fileName, arrayBuffer)
28
28
  ```
29
29
 
30
- `fileName` is used to infer schematic versus PCB parsing from the extension.
31
- The parser accepts native `.SchDoc` and `.PcbDoc` document bytes as an
32
- `ArrayBuffer` and returns the normalized model described in
33
- [Model Format](model-format.md).
30
+ `fileName` is used to infer schematic, PCB document, PCB footprint-library, or
31
+ PCB project parsing from the extension. The parser accepts native `.SchDoc`,
32
+ `.PcbDoc`, `.PcbLib`, and `.PrjPcb` bytes as an `ArrayBuffer` and returns the
33
+ normalized model described in [Model Format](model-format.md). Every parser
34
+ root includes a top-level `schema` id for the emitted normalized model
35
+ contract.
36
+
37
+ PCB parsing reads the main primitive streams together with sidecar streams such
38
+ as `PrimitiveParameters/Data` and `WideStrings6/Data`. Component parameters are
39
+ joined by native primitive unique id, and modern `Texts6` designator records may
40
+ resolve their display string through the wide-string table before the
41
+ normalized component list and BOM are built.
42
+
43
+ ```js
44
+ import { NormalizedModelSchema } from 'altium-toolkit/parser'
45
+
46
+ if (documentModel.schema !== NormalizedModelSchema.CURRENT_SCHEMA_ID) {
47
+ throw new Error('Unsupported normalized model schema')
48
+ }
49
+ ```
50
+
51
+ Specialized parser helpers are exported for lower-level integrations, including
52
+ `PcbBoardRegionSemanticsParser`, `PcbComponentPrimitiveIndexer`,
53
+ `PcbEmbeddedFontExtractor`, `PcbFontMetricsParser`, `PcbPadStackParser`,
54
+ `PcbViaStackParser`, `PcbRuleParser`, and `PcbRawRecordRegistry`.
55
+ `PcbBoardRegionSemanticsParser` exposes the substack and bending-line
56
+ normalization used by `.PcbDoc` models. `PcbComponentPrimitiveIndexer` exposes
57
+ the native component-index grouping used to populate
58
+ `pcb.componentPrimitives` and `pcb.componentPrimitiveGroups`. The pad, via, and
59
+ rule helpers expose the same mask/cache, stack, and typed-constraint
60
+ normalization used by `.PcbDoc` parsing. The font helpers expose the same
61
+ embedded font payload and metric shape that `.PcbDoc` and `.PcbLib` parsing adds
62
+ to normalized models. `PcbRawRecordRegistry` exposes immutable primitive stream
63
+ descriptors and the raw-record preservation helpers used by the PcbDoc/PcbLib
64
+ extractors.
34
65
 
35
66
  ## Renderers
36
67
 
@@ -38,12 +69,19 @@ The parser accepts native `.SchDoc` and `.PcbDoc` document bytes as an
38
69
  import {
39
70
  SchematicSvgRenderer,
40
71
  PcbSvgRenderer,
72
+ PcbSideResolvedRenderModel,
73
+ preparePcbSideResolvedRenderModel,
41
74
  BomTableRenderer
42
75
  } from 'altium-toolkit/renderers'
43
76
  ```
44
77
 
45
78
  - `SchematicSvgRenderer.render(documentModel)` returns schematic SVG markup.
46
79
  - `PcbSvgRenderer.render(documentModel)` returns PCB SVG markup.
80
+ - `PcbSideResolvedRenderModel.resolve(documentModel, { side })` and
81
+ `preparePcbSideResolvedRenderModel(documentModel, { side })` return a
82
+ side-specific PCB render model for top-oriented renderers. Use
83
+ `side: 'back'` to project bottom components, documentation layers, copper
84
+ primitives, vias, and pad stack geometry into the top-facing render surface.
47
85
  - `BomTableRenderer.render(rows)` returns grouped BOM table markup.
48
86
 
49
87
  Renderer output is deterministic string markup. The library does not attach DOM
@@ -11,11 +11,22 @@ The parser returns one object per parsed native document.
11
11
 
12
12
  ## Common Fields
13
13
 
14
- - `kind`: `schematic` or `pcb`
14
+ - `schema`: normalized model schema id, currently
15
+ `urn:altium-toolkit:normalized-model:a1`
16
+ - `kind`: `schematic`, `pcb`, `pcb-library`, or `project`
17
+ - `fileType`: `SchDoc`, `PcbDoc`, `PcbLib`, or `PrjPcb`
15
18
  - `fileName`: original file name passed to the parser
16
19
  - `diagnostics`: parser warnings and recovery notes
17
20
  - `bom`: grouped component metadata where available
18
21
 
22
+ ## Schema Contracts
23
+
24
+ The current root model contract is published as a JSON Schema at
25
+ [`docs/schemas/altium_toolkit/normalized_model_a1.schema.json`](schemas/altium_toolkit/normalized_model_a1.schema.json).
26
+ Parser roots expose the same id through the top-level `schema` field, and
27
+ library consumers can compare it with
28
+ `NormalizedModelSchema.CURRENT_SCHEMA_ID`.
29
+
19
30
  ## Schematic Fields
20
31
 
21
32
  Schematic documents include recovered `schematic` data with sheet metadata,
@@ -27,10 +38,89 @@ the SVG renderer maps them into SVG space.
27
38
 
28
39
  PCB documents include recovered `pcb` data with board outline geometry,
29
40
  component placements, layer metadata, primitive detail, copper, pads, vias,
30
- fills, arcs, embedded model references, and model body placement metadata.
41
+ fills, arcs, embedded model references, model body placement metadata,
42
+ `embeddedFonts`, and `rawRecords`. Embedded font entries include the recovered
43
+ family/style, source stream, self-contained base64 payload, TrueType/OpenType
44
+ format hint, MIME type, byte counts, and basic sfnt metrics such as
45
+ units-per-em, ascent, descent, cell height, cap height, average advance width,
46
+ and weight class. Decoded TrueType PCB text primitives may reference these
47
+ metrics through `embeddedFontIndex` and `fontMetrics`. Raw record entries expose
48
+ the registry id, source stream, primitive family/type, byte offsets, byte
49
+ counts, parse status, encoding style, and a base64 payload for unsupported or
50
+ partially decoded primitive stream data.
51
+
52
+ Component-owned PCB primitives are exposed directly from native Altium owner
53
+ indexes. `pcb.componentPrimitives[componentIndex]` returns the grouped pads,
54
+ tracks, arcs, fills, vias, regions, texts, and component bodies linked to that
55
+ component; missing sparse component indexes are represented as `null`. The
56
+ compatibility list `pcb.componentPrimitiveGroups` carries the same group objects
57
+ in placement order. Board-owned or net-owned primitives without a native
58
+ `componentIndex` are intentionally left out of these component groups.
59
+
60
+ Component annotations may also include `uniqueId`, `parameters`, and
61
+ `parameterSource` when the PCB contains `PrimitiveParameters/Data` entries keyed
62
+ by the component primitive ID. Modern Texts6 designator records are resolved
63
+ through `WideStrings6/Data` when Altium stores the display string in that table;
64
+ when such a Texts6 designator differs from `SOURCEDESIGNATOR`, the public
65
+ component uses the displayed designator and preserves the original value in
66
+ `baseDesignator` with `displayDesignator` and `designatorSource` metadata.
67
+ Component-owned Texts6 comment/value records are marked with `role: 'comment'`
68
+ and `isComment`; unresolved annotation slots are additionally marked with
69
+ `isPlaceholder`.
70
+
71
+ Decoded pad primitives preserve raw `padFlags` plus named tenting and testpoint
72
+ flags. Pad shape codes are kept as raw `shapeTop` / `shapeMid` / `shapeBottom`
73
+ values and mirrored through normalized `shape*Name` labels plus
74
+ `padShapeNames`. Extended pad records also expose named hole shapes, normalized
75
+ `holeGeometry` for round/square/slot drills, merged `middleLayerPads` entries
76
+ that combine middle-layer size and effective shape data, per-layer shape names,
77
+ pad-cache thermal-relief fields through `padCache`, corrected cache-validity
78
+ fields for plane/thermal/power relief, raw paste/solder mask modes, effective
79
+ mask expansions, and side-specific `hasTop*MaskOpening` /
80
+ `hasBottom*MaskOpening` booleans for renderers that need layer-accurate paste
81
+ and solder-mask decisions.
82
+
83
+ PCB design rules preserve native rule-specific `constraints` as strings and add
84
+ typed views for common consumers. `ruleType` exposes a normalized rule kind and
85
+ category, `constraintValues` parses common numeric units such as mil, mm, inch,
86
+ degrees, percentages, and booleans, and `typedConstraints` maps common Width and
87
+ Clearance rule fields to semantic names such as `minWidth`,
88
+ `preferredWidth`, `maxWidth`, `minClearance`, and `genericClearance`.
89
+
90
+ Board-planning regions are decoded separately from copper regions through
91
+ `pcb.boardRegions`. These entries retain their contour geometry and now add
92
+ rigid-flex semantics from BoardRegions/Data properties: `objectKind`, `name`,
93
+ `layerStackId`, `substackIndex`, `substackName`, flex/rigid flags, `locked3d`,
94
+ `cavityHeight`, and typed `bendingLines`. Bend lines preserve the raw
95
+ semicolon-delimited payload while exposing angle, radius, fold index, endpoint
96
+ coordinates, and calculated affected width in mils. Board-level substack
97
+ metadata is exposed in `pcb.layerSubstacks`, and
98
+ `pcb.boardRegionContexts` provides a compact region-to-substack lookup for
99
+ callers that do not need the full geometry.
100
+
101
+ ## PCB Library Fields
102
+
103
+ PCB footprint libraries include recovered `pcbLibrary` data with library header
104
+ properties, optional SectionKeys mappings, ComponentParamsTOC entries, and an
105
+ ordered `footprints` list. Each footprint exposes its source storage name,
106
+ parameters, component metadata, primitive order, unknown record markers, and
107
+ decoded pads, tracks, arcs, vias, fills, texts, and regions. Each footprint also
108
+ preserves raw mixed-format primitive records with the same registry metadata
109
+ shape used by PcbDoc raw records. Library-level `embeddedFonts` uses the same
110
+ payload and metric shape as PCB documents.
111
+
112
+ ## Project Fields
113
+
114
+ PCB projects include recovered `project` data from `.PrjPcb` files. The parser
115
+ preserves raw INI sections while also exposing normalized document entries,
116
+ document groups, project parameters, project variants, configurations, and
117
+ output groups. Reachable schematic documents follow the durable project
118
+ metadata convention used by Altium: schematic stubs with only `DocumentPath` and
119
+ `DocumentUniqueId` remain listed, but richer schematic document entries are
120
+ preferred in `project.documentGroups.reachableSchematics`.
31
121
 
32
122
  ## Compatibility Rule
33
123
 
34
- Consumers should treat unknown fields as additive. Parser fixes may add detail,
35
- but existing field names and shapes should stay compatible unless a major
36
- version explicitly documents a model migration.
124
+ Consumers should treat unknown fields as additive within the same schema id.
125
+ Parser fixes may add detail, but existing field names and shapes should stay
126
+ compatible unless a new schema id explicitly documents a model migration.