altium-toolkit 1.1.41 → 1.2.0

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 (58) hide show
  1. package/README.md +113 -19
  2. package/docs/api.md +224 -18
  3. package/docs/capabilities.md +65 -0
  4. package/docs/migration/legacy-001.md +309 -0
  5. package/docs/migration/legacy-002.md +309 -0
  6. package/docs/migration/legacy-003.md +309 -0
  7. package/docs/migration/legacy-004.md +309 -0
  8. package/docs/migration/legacy-005.md +111 -0
  9. package/docs/migration.md +20 -0
  10. package/docs/model-format.md +28 -3
  11. package/docs/release-notes-v1.2.0.md +147 -0
  12. package/docs/testing.md +43 -1
  13. package/examples/arduino-uno/PcbThreeSceneRenderer.mjs +1 -1
  14. package/examples/arduino-uno/example.mjs +1 -1
  15. package/examples/cli-utils.mjs +1 -1
  16. package/examples/corpus-smoke.mjs +1 -1
  17. package/examples/inspect-board.mjs +1 -1
  18. package/examples/library-catalog.mjs +1 -1
  19. package/examples/validate-library.mjs +1 -1
  20. package/package.json +20 -5
  21. package/spec/api-baseline-v1.1.41.json +1 -0
  22. package/spec/asset-baseline-v1.1.41.json +1 -0
  23. package/spec/feature-preservation.json +1 -0
  24. package/spec/library-scope.md +14 -4
  25. package/spec/native-source-manifest-v1.1.41.json +1 -0
  26. package/src/capabilities.mjs +4 -0
  27. package/src/convergence/AltiumCircuitJsonProjection.mjs +230 -0
  28. package/src/convergence/AltiumDocumentBuilder.mjs +167 -0
  29. package/src/convergence/AltiumExtensionResolver.mjs +98 -0
  30. package/src/convergence/AltiumProjectDocumentResolver.mjs +324 -0
  31. package/src/convergence/AltiumSchematicCoordinateProjection.mjs +130 -0
  32. package/src/convergence/AltiumWorkerClient.mjs +95 -0
  33. package/src/convergence/Parser.mjs +285 -0
  34. package/src/convergence/ParserInput.mjs +282 -0
  35. package/src/convergence/ProjectLoader.mjs +916 -0
  36. package/src/convergence/SchematicSvgRenderer.mjs +126 -0
  37. package/src/convergence/ToolkitCapabilities.mjs +49 -0
  38. package/src/core/circuit-json/CircuitJsonSchematicDocumentGraphicBuilder.mjs +785 -0
  39. package/src/core/circuit-json/CircuitJsonSchematicGraphicBuilder.mjs +909 -0
  40. package/src/core/circuit-json/CircuitJsonSchematicImageProjection.mjs +277 -0
  41. package/src/core/circuit-json/CircuitJsonSchematicStrokeStyle.mjs +47 -0
  42. package/src/extensions.mjs +11 -0
  43. package/src/index.mjs +20 -4
  44. package/src/interaction.mjs +7 -0
  45. package/src/legacy-netlist-query.mjs +11 -0
  46. package/src/legacy-parser.mjs +141 -0
  47. package/src/legacy-renderers.mjs +25 -0
  48. package/src/legacy-scene3d.mjs +10 -0
  49. package/src/manufacturing.mjs +4 -0
  50. package/src/parser.mjs +12 -138
  51. package/src/project.mjs +11 -0
  52. package/src/query.mjs +4 -0
  53. package/src/renderers.mjs +4 -22
  54. package/src/scene3d.mjs +5 -8
  55. package/src/simulation.mjs +4 -0
  56. package/src/styles/renderers.css +27 -0
  57. package/src/testing.mjs +8 -0
  58. package/src/workers/parser.worker.mjs +37 -0
@@ -6,13 +6,21 @@ SPDX-License-Identifier: CC-BY-SA-4.0
6
6
 
7
7
  # Library Scope
8
8
 
9
- Altium Toolkit provides reusable native Altium parsing and non-interactive
10
- rendering primitives.
9
+ Altium Toolkit provides reusable native Altium parsing behind the common ECAD
10
+ toolkit API. Canonical results use CircuitJSON; source-only facts and all
11
+ historical 1.1.41 contracts remain explicit Altium extensions.
11
12
 
12
13
  ## In Scope
13
14
 
14
- - `.SchDoc`, `.PcbDoc`, `.PcbLib`, `.PrjPcb`, and `.IntLib` parsing from
15
- `ArrayBuffer`
15
+ - Canonical `Parser`, `ProjectLoader`, error, progress, cancellation, and worker
16
+ contracts shared with CircuitJSON, Gerber, and KiCad
17
+ - Immutable CircuitJSON document envelopes, common project envelopes, and
18
+ reusable document contexts
19
+ - Shared CircuitJSON render, interaction, query, manufacturing, simulation,
20
+ and data-only 3D scene services
21
+ - Exact `/extensions` preservation of audited Altium 1.1.41 behavior
22
+ - `.SchDoc`, `.PcbDoc`, `.PCBDwf`, `.SchLib`, `.PcbLib`, `.PrjPcb`, `.PrjScr`,
23
+ and `.IntLib` parsing from `ArrayBuffer`
16
24
  - OLE and binary stream helpers needed by parser recovery
17
25
  - Schematic SVG rendering
18
26
  - PCB SVG rendering
@@ -48,3 +56,5 @@ rendering primitives.
48
56
  - Server, deployment, and app metadata endpoints
49
57
  - Native document authoring, round-trip writing, GUI automation, and compiled
50
58
  multi-sheet project netlist generation
59
+ - Pretending an Altium-only feature exists in another source toolkit when no
60
+ truthful CircuitJSON or native implementation is possible
@@ -0,0 +1 @@
1
+ {"schema":"altium-toolkit.source-manifest.v1","package":"altium-toolkit","packageVersion":"1.1.41","provenance":{"sourceCommit":"9fa22e1028d96e583275093279bf6e03e8619588","sourceTree":"1ddc290f5fc034454c5f33dac4de56b917070174","testTree":"00be0165c10e69611c8c571c9befef24b48273ae"},"files":[{"path":"src/core/altium/AltiumGeneratedLibraryRecordBuilder.mjs","sha256":"c6024166ad005c0f15a120b67ed0feb3ab7a43202065ae1aa2e983f4f7000d2e"},{"path":"src/core/altium/AltiumLayoutParser.mjs","sha256":"2ff28ea83903ef5cb95d569d6c1daae7340c8710a01d397faf5c8dbb045dad0f"},{"path":"src/core/altium/AltiumLibraryBatchExporter.mjs","sha256":"cc49aa0e106487f754d0a306cf82418bfaf1ba0eb199e9161c2b29aae89977be"},{"path":"src/core/altium/AltiumLibraryRecordBuilder.mjs","sha256":"3941b609c1536ff29e5cd4dccf8060c5524b075645fdf2c22ad153a60edfcc59"},{"path":"src/core/altium/AltiumParser.mjs","sha256":"bfae2e63ccde1a18dc50df9b661208c8d0c78ce447b0094a01187c41413b39eb"},{"path":"src/core/altium/AltiumPcbLibExporter.mjs","sha256":"384ae177fe5ceadef1a22f191e12fe7af5327dff1fee971972826a3def5b616a"},{"path":"src/core/altium/AltiumSchematicArcAngleNormalizer.mjs","sha256":"831be977a80e2a5ecb5a0987fa4587cb601afe5908344c62de3358b355af0206"},{"path":"src/core/altium/AltiumSchematicFreeGraphicStrokeNormalizer.mjs","sha256":"19b49250b16be521213d2bfa31e41436aa7c2d543d6e48c0029ffce9183900a4"},{"path":"src/core/altium/AltiumSchematicHiddenDesignatorResolver.mjs","sha256":"f49603ac7f35cc435ce5d9ff65a0ef59d1601d0445643372ceb4daf8ea05f751"},{"path":"src/core/altium/AltiumSchematicPackedImageResolver.mjs","sha256":"948fff19a9a7695687887bbc416bca182b6c717df66b3707bff45d447bc29d9c"},{"path":"src/core/altium/AltiumSchematicSheetBoundsNormalizer.mjs","sha256":"f11d853ecbfd03f83c7084e48c621234077d1d5e4f6e759070096cff3e8fde99"},{"path":"src/core/altium/AltiumSchLibExporter.mjs","sha256":"f1bc1c04e1de6b736987c4e3c036cdf8b0d21d745f2cd50b8c13bf9b62f5615c"},{"path":"src/core/altium/AltiumUnits.mjs","sha256":"e3ac28990bd40abae95d54c55852b229428d01323e694af1a8ba5ddb973b5e91"},{"path":"src/core/altium/AsciiRecordParser.mjs","sha256":"6b300d6b16e726bb7d61109b7afeec956e318e9cae531f1970f13b425fc4cac5"},{"path":"src/core/altium/CiArtifactBundleBuilder.mjs","sha256":"379efc7823bfab5902edf025cedf76b0c6147db7fa668c9560549401dcfdcbd6"},{"path":"src/core/altium/ContractGateReportBuilder.mjs","sha256":"11fdf71be9229e6a075a673065323be0fe472be2c99d6b2f6968b73852293313"},{"path":"src/core/altium/DraftsmanBoardViewMetadataBuilder.mjs","sha256":"b21c5cc9e8973aeed3d188af250ba455fc514fae7d0efec6e235c2e7dbaed367"},{"path":"src/core/altium/DraftsmanDigestParser.mjs","sha256":"d570b966a08c62c2d09e73ff7d227f5645f10961ad46aac1d706fbd15bb17a00"},{"path":"src/core/altium/DraftsmanImagePayloadManifestBuilder.mjs","sha256":"d79492cdcb886a5ae3b4a724423b71f6fd3f80bd8ef53135348b1265a4b4567c"},{"path":"src/core/altium/EmbeddedAssetReportBuilder.mjs","sha256":"e36b708738ea20a817849c88bec32de0415acc39194746a4b343890230a924b9"},{"path":"src/core/altium/EmbeddedFileInventoryBuilder.mjs","sha256":"5e86fff091cde0d493e4788b8ad85342c4fc0e54a063491e738bc58b2a95732b"},{"path":"src/core/altium/FixtureCoverageMatrixBuilder.mjs","sha256":"6dbda10369d0ec8cff69c8eb804b63405c7601525fa704b26c730664fcd27aff"},{"path":"src/core/altium/GeometryBoundsReportBuilder.mjs","sha256":"ac2e29de3266c7b9682284352c800d17ca7b2965e5a5c0169600799c64f2939c"},{"path":"src/core/altium/HostCapabilityDiagnosticsBuilder.mjs","sha256":"aa9aa1da9a608daf196e533853e9ad1d0e01b200732712547f1f5424343d4931"},{"path":"src/core/altium/IntLibModelParser.mjs","sha256":"3ea00a4ac85f4ac4994b059c02157428e211271dc2c5faecd5d5ac9c23a86d7c"},{"path":"src/core/altium/IntLibStreamExtractor.mjs","sha256":"e48a6b8b1c1efb790191175ab7f8b129c166350f8e1977b67b2d27b1f969268d"},{"path":"src/core/altium/LibraryCatalogArtifactBuilder.mjs","sha256":"bf067fa0e86d3b2b13ddfb6da2af9b1ddecc984bb25788af8b2fb45475112c70"},{"path":"src/core/altium/LibraryCompatibilityGeometry.mjs","sha256":"c6cab949fcbdad107524d60c5ddda7447ce452086f7d42a0a6a3f57df10993b4"},{"path":"src/core/altium/LibraryCompatibilityModelHintBuilder.mjs","sha256":"d365e07a481fca6330ff5362593acf5248be637d66d454c973d65bb460fece21"},{"path":"src/core/altium/LibraryCompatibilityReportBuilder.mjs","sha256":"8504e07e80900716e82ec4f3c503f9a70fd08a44fa2ae86e911858fd1c4718da"},{"path":"src/core/altium/LibraryDiffReportBuilder.mjs","sha256":"a15c8ab7b4fcc04108faad13fbd74a4df24a8ce7267b2bd2a2f14f58a4d5ad99"},{"path":"src/core/altium/LibraryInspectionReportBuilder.mjs","sha256":"464f867471a85c01d7fc906695bef10219eaddc4013a4afcf2fe4de46f32d0f1"},{"path":"src/core/altium/LibraryQaReportBuilder.mjs","sha256":"2c35077ef7140110979f35f93901aabdd1bb7b2d64879212cfd4abb5a6b3f8f3"},{"path":"src/core/altium/LibraryRenderManifestBuilder.mjs","sha256":"66b8383470d3452f4cdceffad6c8a09533bd0fb3a32a47484725ac3edd8c5fe7"},{"path":"src/core/altium/LibrarySearchIndex.mjs","sha256":"a97e0852b91e6abfc548b927e821dc950945baf85ee20f2fc4c52346ec338c8d"},{"path":"src/core/altium/NativeStreamInventoryBuilder.mjs","sha256":"2c9144c17b68e609bb27757d856887bda10a79dda0c69d8c4f789f1e7b0ccedb"},{"path":"src/core/altium/NaturalStringComparator.mjs","sha256":"d970b4c63472de2e870d08e97ea65624d161b08410a7fb4239725efc216b0722"},{"path":"src/core/altium/NormalizedModelSchema.mjs","sha256":"d12c8dad7c97adf152be00be51092307525e6bb77aaae7322c2b49e661c25564"},{"path":"src/core/altium/ParameterCollection.mjs","sha256":"61dd3309af3b1fce92223ba1223f7fefb1bb21a4d8c1d79aa4ca90d7ec654517"},{"path":"src/core/altium/ParameterRecordInventoryBuilder.mjs","sha256":"5cc461dcdbabfc9e5bdaa920dfc95b9e574ee8fdfd10014788109e42a755f754"},{"path":"src/core/altium/ParserCompatibilityFuzzer.mjs","sha256":"53c5379621bc5d03f3f222c6e9a5708c45e1037d0771a1eb293c6d78bc5b4bd1"},{"path":"src/core/altium/ParserDiagnosticNormalizer.mjs","sha256":"3528601140dccda335f1e5770888d4bbac19d732ea3b501211352ecd87d46f73"},{"path":"src/core/altium/ParserErrors.mjs","sha256":"194fdd0d5b570d981dcdd21e9041186652c8f5635d91a501f6d9e4ff8d2288a2"},{"path":"src/core/altium/ParserFieldCoverageReportBuilder.mjs","sha256":"e31a5951630a2956cc5b482e30e7b4a8c637947339cddb16619f356e369bdb9f"},{"path":"src/core/altium/ParserUtils.mjs","sha256":"0ccedb569986cf86a2cd618e6bd368b7313d0a9ad14f475de54c86f7da10c84b"},{"path":"src/core/altium/ParserValueVerificationReportBuilder.mjs","sha256":"5d5ce89942290e541b2acb79dbf67ee38fe9fae7e1af68016f093160780da2a0"},{"path":"src/core/altium/PcbArcPrimitiveParser.mjs","sha256":"3570d39234ebff7c07a1ef46b95f85a3a01ae2576b0fa5e1adf7a75098a20eca"},{"path":"src/core/altium/PcbBinaryPrimitiveParser.mjs","sha256":"b2de45c4d1fab5373f85a87673e068ead145db9092afc9703b595ae9fbd142d7"},{"path":"src/core/altium/PcbBoardRegionSemanticsParser.mjs","sha256":"792e2740142e2ddbadffee70a3af691dfd1b291d58aba0d1491d9fd47789741a"},{"path":"src/core/altium/PcbBomProfileBuilder.mjs","sha256":"18c1808428a54a515b0d0ca0dd71765b48dc174423c992180bffec8d6b54f114"},{"path":"src/core/altium/PcbClassReportBuilder.mjs","sha256":"e0522ff6603aac9747228bec70cc786cc8051e2233e5a5b241f9646954da13e0"},{"path":"src/core/altium/PcbComponentAnnotationNormalizer.mjs","sha256":"ce95d09cf256ba128b393a9ae248dff17215fc2c7861f828c32304e51d391977"},{"path":"src/core/altium/PcbComponentBodyPlacementNormalizer.mjs","sha256":"90ca987defaa709a1a994c2be65216db1d8fb2eda5ba2c8e445fac48d9737fdb"},{"path":"src/core/altium/PcbComponentKindPolicy.mjs","sha256":"c0cdf2eb55fa04acdba2b30ada85fa215cf4b22418c371fb8bbfe76d435ca98b"},{"path":"src/core/altium/PcbComponentPrimitiveIndexer.mjs","sha256":"8c6ec484f819b1faf3e55c8f5ab5be8c2079c0f16e24378298bf841ae225a733"},{"path":"src/core/altium/PcbCustomPadShapeParser.mjs","sha256":"1dd23d02e5eadbdc5b59210b31e61ea258addb923500edfb2c78f7ea5ce4bfbc"},{"path":"src/core/altium/PcbDefaultsParser.mjs","sha256":"b30b748a6e672482d9849e6ee6244d1999965256d7e9397131cc8818f77496f5"},{"path":"src/core/altium/PcbDimensionParser.mjs","sha256":"7f1676a27cfec1a9da7d8317b3f7a2191b5a41e4563b894ba357480dac360d79"},{"path":"src/core/altium/PcbDimensionReportBuilder.mjs","sha256":"b635274a67fcbec7f8dc80407b334c647bd7ee9b162bf0086a40bb82e6f89157"},{"path":"src/core/altium/PcbEmbeddedFontExtractor.mjs","sha256":"447cf031a6e36e6f8a0f6454d1d50df5617ed4590033d714df7d28bb88508b7c"},{"path":"src/core/altium/PcbEmbeddedModelExtractor.mjs","sha256":"253d297f4a402978a12fa28c060981365ab382a1d5b777e134bc1b72c8617c45"},{"path":"src/core/altium/PcbExtendedPrimitiveInformationParser.mjs","sha256":"4cc5bdccbe7f56793083fea870c39e4891786d96dc1b14ba70065f3b1eb52ad9"},{"path":"src/core/altium/PcbFabricationReadinessReportBuilder.mjs","sha256":"2d9168f0ee94feaa06500bd05f0932647855e4614639e70bd7fb39cd9cf87ad4"},{"path":"src/core/altium/PcbFillPrimitiveParser.mjs","sha256":"398c13534fdce0a66237afe522b98c8856241647f3e9adb707c29c346f0d8db7"},{"path":"src/core/altium/PcbFontMetricsParser.mjs","sha256":"18859fa2ba4fed7e1f03f7fd380201cce5963edb238ec4b6a52f93346455fbde"},{"path":"src/core/altium/PcbGeometryFlipper.mjs","sha256":"88f88696a5ef50539ab79e3fd7e155c0eeb7e54d9f6d7258278a53457e417a31"},{"path":"src/core/altium/PcbInspectionReportBuilder.mjs","sha256":"fc25424dcac7c847d5797ac987853beb8a84152cd43fa34c45f275f31bcd2fa1"},{"path":"src/core/altium/PcbLayerGroups.mjs","sha256":"09b70c09815cd3d8f91baaed24aed519f8571bfad971ae4a490f52203c8760b0"},{"path":"src/core/altium/PcbLayerIdCodec.mjs","sha256":"efa53c24a7a753bdb585398929bbe557759ceb0213410c43f6609eb365adee45"},{"path":"src/core/altium/PcbLayerStackCustomDataParser.mjs","sha256":"66995a16a42a9080279e4b8a785ab7fe85392810ca0313d8dd478c8e39dd6eb6"},{"path":"src/core/altium/PcbLayerStackFidelityReportBuilder.mjs","sha256":"5862c2b14d9ac4af13806e4608dbd2f0ae84900ce2bfbf75535bec3aca9196af"},{"path":"src/core/altium/PcbLayerStackInterchangeParser.mjs","sha256":"e75616e15db5cbd5bdb4d7dff18c8fb313100b1ce20a0f8636dbd366f52a5538"},{"path":"src/core/altium/PcbLayerStackQueryHelper.mjs","sha256":"979c64608beb3d932366955f090fbb3b8ad3e735be8d5969a59fd5e9aa8d1bd9"},{"path":"src/core/altium/PcbLayerStackReadModelBuilder.mjs","sha256":"11f6169e01742148bfc7adaf2e5319d6805fc43ec926f2f30da3ffd411ee1287"},{"path":"src/core/altium/PcbLayerStackSourceMetadataParser.mjs","sha256":"9d8ce7ee4572f4f9af11b6a50a3e34fedbf76a5ab19be0843a180abecc65a236"},{"path":"src/core/altium/PcbLibModelParser.mjs","sha256":"a0c9b2bdda831567180326174247113628598cfd4324e46908e6fe5f4a8ad241"},{"path":"src/core/altium/PcbLibParityReportBuilder.mjs","sha256":"2c54d52739ddd55eee80cd21344ba18b9db4db1f32f2de1a7805a8b6e5e4ffb6"},{"path":"src/core/altium/PcbLibStorageNameResolver.mjs","sha256":"90a6d6980400906a93c3ef8ae19575e9a11071dc647752b28a6b6576ffe4bf92"},{"path":"src/core/altium/PcbLibStreamExtractor.mjs","sha256":"ee3f2e43b63678d5187e960ae3e0ad7e124c7223bffdbbf83b3bca3e5ef754d1"},{"path":"src/core/altium/PcbMaskPasteResolver.mjs","sha256":"7f20dd398f8fdf6b90f2a71fbebc3c7f540832cfe53d60e777df0e1ffcf13e26"},{"path":"src/core/altium/PcbMechanicalLayerPairParser.mjs","sha256":"d52bb4910b4da59ce619e08cf094a04115c26732cfdde19cd909dd6cba1c2d09"},{"path":"src/core/altium/PcbModelParser.mjs","sha256":"526c021dcd5c881d4ef8497fc8bd7d0fc444481b24d455df21dc261918a6c27d"},{"path":"src/core/altium/PcbNetMembershipReportBuilder.mjs","sha256":"99eb577ed1ac1c427f18f7510b0799b16b2615ff459579b181bd4cfec2e1ac5f"},{"path":"src/core/altium/PcbOutlineRasterizer.mjs","sha256":"d6c3d258da0f6bc20984d866447610398607883efc0c1b059737db1bbcbc01a1"},{"path":"src/core/altium/PcbOutlineRecovery.mjs","sha256":"0489fa6ff8da5ade83b25b8d5593801a8624245abcc37d174d9f0a933853459b"},{"path":"src/core/altium/PcbOwnershipGraphBuilder.mjs","sha256":"72494fa6b6a226e8ae60ce6ab34b99d0a573180fd71f28a6be413b7ba2d57854"},{"path":"src/core/altium/PcbPadPrimitiveParser.mjs","sha256":"f0da55e9987e586f03d20ac900ed705fdb4b71b90eab6ecbcef6357dd7131409"},{"path":"src/core/altium/PcbPadShapeCodec.mjs","sha256":"32020d864cb2edc614fd276c205613c390ba1ab98fe6a159655dae787087f343"},{"path":"src/core/altium/PcbPadStackParser.mjs","sha256":"fd65280b9c8dab1f762f6f19a5d16bce2ac3861c096e1735cdcc4b8ba7d402ea"},{"path":"src/core/altium/PcbPickPlacePositionResolver.mjs","sha256":"05cd6ad01e0ab77bd44cb69fcf7ffe266eeb8880ac839c8e6b3c43b8763a6404"},{"path":"src/core/altium/PcbPlacedFootprintManifestBuilder.mjs","sha256":"20200b453341de5044ab4b24b21f3bf999764e23179bc153ca4da7ca74ab895e"},{"path":"src/core/altium/PcbPolygonRecordParser.mjs","sha256":"98b0e21d3acc213e60ff6aac9215864be4fbd584177581f00e78f54132efeb3c"},{"path":"src/core/altium/PcbPrimitiveFieldOffsetReportBuilder.mjs","sha256":"3e593152684685c33d978c8507201955343b22af5c9459762829215272191dc9"},{"path":"src/core/altium/PcbPrimitiveOwnershipIndexParser.mjs","sha256":"13209fe9de519e5c86682bfb7a62ca2b7804d68c17fc2d6ebef2e7523d384717"},{"path":"src/core/altium/PcbPrimitiveParameterParser.mjs","sha256":"472509419d8c208b50dc0e9d2f389bcbe7b9b5aaf11ad9f1ff759a06bdfde0a9"},{"path":"src/core/altium/PcbPrimitiveRecordSlicer.mjs","sha256":"f5f37ea1a29c8e652a3e11d47c7c3fbcd1339872a35daedf3b7393f009b83d25"},{"path":"src/core/altium/PcbRawRecordRegistry.mjs","sha256":"7267a6154ae42966e6610df11f887e793038956da496aeeadb8a4c664b3f11f6"},{"path":"src/core/altium/PcbRegionPrimitiveParser.mjs","sha256":"04f6822c60d2261af398f667a70d4aec4720aae93ed35599d8a4464b18b33876"},{"path":"src/core/altium/PcbReviewDrillMetadataBuilder.mjs","sha256":"807f67f133da728a0597d0c346648270fdd810384d3e351c21f1e7ba2822aa77"},{"path":"src/core/altium/PcbReviewMetadataBuilder.mjs","sha256":"d4f918c03ebfbda9f6cd4500be24eec45856f3c6128dcb55437a86e2bc445e28"},{"path":"src/core/altium/PcbReviewPolygonRealizationBuilder.mjs","sha256":"2dd8e2d97b1f9b35bb938f6714e1724606eebd26a7f7291ecbc1f8d5d9e5285d"},{"path":"src/core/altium/PcbReviewRouteHighlightProfileBuilder.mjs","sha256":"103d6b50f0fa41671b021702df67c40a95bfe318dc223d36e7f97bd15c155ebb"},{"path":"src/core/altium/PcbRigidFlexTopologyBuilder.mjs","sha256":"b3d71a4f8cea5b8bf90a588c0c1c6f9a9680b36a171441794f18cc34c80d9395"},{"path":"src/core/altium/PcbRouteAnalysisBuilder.mjs","sha256":"56f24354868bf82ddfd10d158accbf26677340273015c0ce424ddefd00929e3a"},{"path":"src/core/altium/PcbRuleImpactReportBuilder.mjs","sha256":"de4ed931eced6fbc2a5eda2ce87f65a745a6c78732615f1573f7b716db5f871e"},{"path":"src/core/altium/PcbRuleParser.mjs","sha256":"6dd28b296dc133de2da9fd1a9826ae1f2c3b00b0447ee05bd803d724bff3f5ff"},{"path":"src/core/altium/PcbShapeBasedBodyGeometryParser.mjs","sha256":"41f0866dffced76cb28b1db91c4d8a712b1441a3ba7e78e86836318cca7e075a"},{"path":"src/core/altium/PcbSidecarRecordParser.mjs","sha256":"69d750a911efbc29a400962e46b6accfc534f6674fcaec83226ccc5425ab4faa"},{"path":"src/core/altium/PcbSpecialStringResolver.mjs","sha256":"1cf33548eeca612f5a8ae05880e47024bcceff8b37b3c6379fa25439eafa7bbb"},{"path":"src/core/altium/PcbStatisticsBuilder.mjs","sha256":"abb489b06d5e51bc823a66f87a105f53907a0a3375ef010bcb9c6c123be973a7"},{"path":"src/core/altium/PcbStreamExtractor.mjs","sha256":"90d9a21f65db93fc7c8460e6f825d4c8a17f89d1e691840f5793c9fd21ebe29b"},{"path":"src/core/altium/PcbTextPrimitiveParser.mjs","sha256":"8769aa4a9b71d6629742f0227e9ea9eca5d76df177af1553ac2803284add0df2"},{"path":"src/core/altium/PcbTrackPrimitiveParser.mjs","sha256":"f16e311f27c579185e32828e7d58e03a9ef0d7e57ece1cf9394e3d24b4fa08a4"},{"path":"src/core/altium/PcbUnionParser.mjs","sha256":"561bc3edd615e7d0ef78926f3046dd5deb295fd14da4d7936a622bb3438676a6"},{"path":"src/core/altium/PcbViaPrimitiveParser.mjs","sha256":"c6e43d36082becbf930eade3dc06afc1e80532d6d370dcd137460bc534c5b585"},{"path":"src/core/altium/PcbViaStackParser.mjs","sha256":"f56aae32526af6e019f02e1accf2ccf606210ebce42191f2b3614cacf50dfc64"},{"path":"src/core/altium/PcbViaStructureParser.mjs","sha256":"1e5f0020689a0ad20428313b5f03b8b05cd8996373c3eeaa18416b84c2791af0"},{"path":"src/core/altium/PcbWideStringTableParser.mjs","sha256":"2b56f17232bea3b69c04f0e3b0c319649dd00210c67bfde2cff67ba54271c16a"},{"path":"src/core/altium/PrintableTextDecoder.mjs","sha256":"1a68d493221c87fd28cfe741a614b08a77428da0b689b7302399c212346880ff"},{"path":"src/core/altium/PrjPcbModelParser.mjs","sha256":"2ab110abe772a422571ced319a7e183f1c96080a1609458b069b2583a04b23fa"},{"path":"src/core/altium/PrjScrModelParser.mjs","sha256":"beb049fe0c2da57a69318870fafed491c74ee4db6aa343cae81d49ea3fbcce7e"},{"path":"src/core/altium/ProjectAnnotationParser.mjs","sha256":"263f818043abb386060e0e89cc86df166731a87e270fdddf7215ed54f55af412"},{"path":"src/core/altium/ProjectBomPnpReconciliationBuilder.mjs","sha256":"7456a9bf5c315fa69e5bf94d5570a62509f0516408478e9bffe685a895ec6ee4"},{"path":"src/core/altium/ProjectDesignBundleBuilder.mjs","sha256":"be4be530e2ce6bb241ed35a2c1d8baf714e4bdf34302a52295f66eb924957fb4"},{"path":"src/core/altium/ProjectDocumentGraphBuilder.mjs","sha256":"90f57388d12d6adb08d7c23f5505150f83ec76b8ebc67a7e01185ba6485fd6b7"},{"path":"src/core/altium/ProjectHierarchyReportBuilder.mjs","sha256":"4dffd614f1303d44b15cb935bb74114bff4494ffe2a8e435578c53efc041813b"},{"path":"src/core/altium/ProjectNetlistExporter.mjs","sha256":"d9f129172442ec6b75e6cce375f3dac71511435b9ebda3082c217e62233fa4c0"},{"path":"src/core/altium/ProjectOutJobDigestBuilder.mjs","sha256":"820a249b9358836e84a8acf23fbec493cc4ce656652d17394c2f43a554161b1c"},{"path":"src/core/altium/ProjectVariantViewBuilder.mjs","sha256":"221663cde2254f926e50bc9066d06a34c17ada90ebb33ccbc862ee1d0759d3d7"},{"path":"src/core/altium/RawDataPreservationReportBuilder.mjs","sha256":"58feb0fed1d49ca3cf7351fb9343d161a9e20dc6eb01d358a34a1bece8516abb"},{"path":"src/core/altium/SchematicAnnotationParser.mjs","sha256":"c47dda158ff5e923b41b44a900b08bdab3c7b4a11fa04e54222b00dc9f9fe636"},{"path":"src/core/altium/SchematicBindingProvenanceParser.mjs","sha256":"064ec613a13e9ce42ce58691b01618f7fcd283499112a954fee29bc87c2ea9cf"},{"path":"src/core/altium/SchematicBusEntryParser.mjs","sha256":"de0a7752a07c9b8e923917565a47f8e8c6da2d46708d11e896f4144be680969d"},{"path":"src/core/altium/SchematicCodeSymbolParser.mjs","sha256":"adbba28155e4acebd22f3784d3cc8b178bf8a33d33440e2ef0f2cceaf1f7f61e"},{"path":"src/core/altium/SchematicComponentOwnerTextResolver.mjs","sha256":"ce5dcd74a4c1e4100d20673d51547c08faffaff0dee7962627db9109997624cf"},{"path":"src/core/altium/SchematicComponentTextResolver.mjs","sha256":"c486d4c89df3713deb56e6590285917f55faf24fa9110bb39cfbb2926694ccaf"},{"path":"src/core/altium/SchematicConnectivityQaBuilder.mjs","sha256":"af1a54ed8911f5e43e08c405600f0e82c26707e6681538f067ec341122320a1b"},{"path":"src/core/altium/SchematicCrossSheetConnectorParser.mjs","sha256":"7b6f62989ec8ef6a181d676138d0db77583563c541d50a2db37f12ab703cde7d"},{"path":"src/core/altium/SchematicDirectiveParser.mjs","sha256":"f95a13b05d09cd49cb2735474564cb6739460cb6e29767071fecae1ebe815eb2"},{"path":"src/core/altium/SchematicDisplayModeCatalogParser.mjs","sha256":"0ecb3d723f09e2d53331f494c9269719783219c1f215d56ce5797133b2369767"},{"path":"src/core/altium/SchematicFieldCoverageReportBuilder.mjs","sha256":"ca0db10caf2b3968e6746acf4d501368fd9dd68dfd64e47f7b924ec74f9820ed"},{"path":"src/core/altium/SchematicHarnessParser.mjs","sha256":"3393fe30785fdc5d7b28834bc7becc8d37dcd81cd2962efc86644d4593123ceb"},{"path":"src/core/altium/SchematicHyperlinkParser.mjs","sha256":"0cf30dfd3cd1d1fecf6b8debba83d6b61bfcbe9db745f2a348f46fe3e579c696"},{"path":"src/core/altium/SchematicImageDiagnosticsBuilder.mjs","sha256":"3a0dee66b15cc8c111371596d02fb40e289ccd8ccc01d2069e98d7b3fee63704"},{"path":"src/core/altium/SchematicImageParser.mjs","sha256":"6ea901dbb70f1e6d24621ade7863a8427b6ce0db174fb7b0a6f96d90bd5da366"},{"path":"src/core/altium/SchematicImplementationParser.mjs","sha256":"1f745fa6177ce67d4a8fae881083872987a67d874333212bec24967fbb39273f"},{"path":"src/core/altium/SchematicJunctionParser.mjs","sha256":"1691240945c03286523f7be252b1462e4f6cbc16a3b951d362955c70e08aed07"},{"path":"src/core/altium/SchematicMultipartDesignatorNormalizer.mjs","sha256":"7156ed5fb9f12a26862c9017b10638ab08c8adbf7404f9a1dbf38c40ec5bb1bd"},{"path":"src/core/altium/SchematicMultipartOwnerMatcher.mjs","sha256":"49f3c937b6042555fdfdaf617ff65b7762a523dd8fe081227d70cd73f296cb20"},{"path":"src/core/altium/SchematicNetlistBuilder.mjs","sha256":"9e4bc310f86e7e981df05fb1756272702b0836616e63f117f8dd0c8fd4b9f004"},{"path":"src/core/altium/SchematicNoErcSymbolResolver.mjs","sha256":"0dd719bf87e8b2501b6cf40d32a107f2248e16c45a5ee6717bd16389651483e6"},{"path":"src/core/altium/SchematicOwnershipGraphParser.mjs","sha256":"2eecbf3803d7ffdaeec6745e62dc854a03b0648b93618fc36e27da38dcfb3f7e"},{"path":"src/core/altium/SchematicPinDesignatorInferer.mjs","sha256":"bffe94e837ca35fd8e109619cc87d620dc7a014d328aba3aec3d8f28dfa0e03c"},{"path":"src/core/altium/SchematicPinParser.mjs","sha256":"9fd88f5a143f6ed9614b4a25afc04b2aa1aca847508b2ab857703604c6bd713e"},{"path":"src/core/altium/SchematicPrimitiveParser.mjs","sha256":"28c927cef76650194cf4ac26d8034dcef65e50929714092ade601818db8fb60e"},{"path":"src/core/altium/SchematicProjectParameterResolver.mjs","sha256":"b56adcf3261bb9d2e364cc86083b8e0a37d14af26fde9cb6de18fc0a154a723d"},{"path":"src/core/altium/SchematicQaReportBuilder.mjs","sha256":"7c09f53ded67103efffd8e45f5bd3436b88b64fce03d31b7de173a1068bfb67f"},{"path":"src/core/altium/SchematicRecordStreamParser.mjs","sha256":"8e98ea0a8725d486a82c4b42f2f98e791078d17dd55c19d91845d4ed3bd9e68a"},{"path":"src/core/altium/SchematicRecordTypeRegistry.mjs","sha256":"1d9f29424d04a1655395bc40119aa10fcb037d42a5a63c822852c6278486469f"},{"path":"src/core/altium/SchematicRepeatedChannelParser.mjs","sha256":"1aba78fb0e6201ef66958648f5789c7c322bda4f62751f1dcd031be7edfecd11"},{"path":"src/core/altium/SchematicSheetParser.mjs","sha256":"1e281222e7a5a5f1ce5ebf7655c2f8f9fc4cc7be59f3f0cc319aec1b805a4122"},{"path":"src/core/altium/SchematicSheetStyleResolver.mjs","sha256":"284554aba014cfa593055d4890d731be979df6ea8abae3aa5fdd9b14d66fbda2"},{"path":"src/core/altium/SchematicStandaloneCalloutNormalizer.mjs","sha256":"c80c3317f606bee56e1b53d169cddfa2ecf7f4dc59c3c9f85058521d31dc3432"},{"path":"src/core/altium/SchematicStreamExtractor.mjs","sha256":"12113eddf53d7e75bcc87032547c242964ca4b262f4100b82fbddcd2d83fcaf0"},{"path":"src/core/altium/SchematicTemplateParser.mjs","sha256":"a5fcc74f0dd1f0f1ff65fbb33304b308c7507ee1c429d590e876f6fb4502c0e9"},{"path":"src/core/altium/SchematicTextOrientationResolver.mjs","sha256":"59c3c2c77912c913190fd49d01ba76b1165c745b5db3998ff3458b394e7a7d0e"},{"path":"src/core/altium/SchematicTextParser.mjs","sha256":"73af8b419fddfc51118a95f6d4869daa4d4e9b5aaae8cd54c5a702c2470fbc4e"},{"path":"src/core/altium/SchematicTextPostProcessor.mjs","sha256":"1e97cebf6e9593aecbb04bfe0daab277582f7dd07c0b52fd9e69f5c92afdead1"},{"path":"src/core/altium/SchematicTextRunParser.mjs","sha256":"23f57ddecfe8da72e5205d2f1755cadc12659323fa67a8bec08dc341438c3c81"},{"path":"src/core/altium/SchematicThumbnailParser.mjs","sha256":"c3f2e5597bc2a8875874a058d7ac5037a59f6e3fa973769f40ce846f9d119ef8"},{"path":"src/core/altium/SchematicTitleBlockParser.mjs","sha256":"ec4d359e24bd0cd3b31281305129771dcfb97dcb47177376ae2f748bab78eeab"},{"path":"src/core/altium/SchematicWireNormalizer.mjs","sha256":"fb9d9c4f177b2a9ebdc4cf2d817660779303c9472c21c99ceb788deeb971f093"},{"path":"src/core/altium/SchLibModelParser.mjs","sha256":"40dd14984651861b6c2c719bd5380e1259c13c9be6d46b8c034f93534a9546ce"},{"path":"src/core/altium/SchLibStreamExtractor.mjs","sha256":"70490aaa2a14777657659e60f1b48684ded19a1e050219708999e68fa968f23e"},{"path":"src/core/altium/SelectedPartAltiumExportAdapter.mjs","sha256":"79bb54584a271bf328140b6b7d58ef19835e768a91846e03f4a1a03ef39809c7"},{"path":"src/core/altium/SourceBundleExporter.mjs","sha256":"3c6edd0469cc5af513db42f8e181ab4a9823cc8502fe372aa2ec5d6f26db5046"},{"path":"src/core/altium/SourceComponentBundleNormalizer.mjs","sha256":"d593413f19ede5b8b174dd243cb4dcd2dc581516a7681c79d863b45d0054f464"},{"path":"src/core/altium/SourceComponentClient.mjs","sha256":"3a26ee1c07b4b4023af6d209215e1342387cd45bd52eba7f3b8a1f0608544023"},{"path":"src/core/altium/SvgModelCrossLinkValidator.mjs","sha256":"888f40c08aafbd7e712ba27d7cf3b359d51fdd4d92e80d5a9ce70768e81d77b2"},{"path":"src/core/altium/UnsupportedFeatureReportBuilder.mjs","sha256":"a9d6b4294a4e60ad4350b6a38de4ba906ba9fe11cc00b4ed055edba6b475b3e9"},{"path":"src/core/BinaryReader.mjs","sha256":"66fc8f8f4ae62b01eadb07af1a5270e75203b2366083103f6bbd169547433167"},{"path":"src/core/circuit-json/CircuitJsonModelAdapter.mjs","sha256":"48b96b324db706d64be136f1c0e2cef0ca361b23ec0c12af4b00331a4a30498a"},{"path":"src/core/circuit-json/CircuitJsonModelAdapterPcbElements.mjs","sha256":"e069491b5dc1c698dff3a3d68db1c2a5ebb69cec95caafdd92719aa54acd8265"},{"path":"src/core/circuit-json/CircuitJsonModelAdapterPrimitives.mjs","sha256":"29157012b29084ad74a1b75e397022a30eef9467fea2a3cd363b5b8309e93fba"},{"path":"src/core/circuit-json/CircuitJsonModelSchema.mjs","sha256":"7061b877cbfce909396908f278befe85c013582ffd33ecf61f4737a8fee27ff2"},{"path":"src/core/netlist-query/CircuitTraversal.mjs","sha256":"ac97c24c10f2cdf0f84fe080c7a1b76749a52f44b9d28461137fcd067b8fe116"},{"path":"src/core/netlist-query/ComponentGrouping.mjs","sha256":"54945b958a06b38632bec0ebe3a0947386f18acd1697a2b98d63cfaf6bf3a6b2"},{"path":"src/core/netlist-query/LoadedDesignNetlistService.mjs","sha256":"8d4c20f4f2454750459458f4896d76640777975198bdd0d1f84f16c4474118d7"},{"path":"src/core/netlist-query/QueryNetlistBuilder.mjs","sha256":"8f383d61bef2a012215e6e3ce596d26a1410ab890e56858a377dd5d66921b35a"},{"path":"src/core/netlist-query/RegexPattern.mjs","sha256":"1d40dc3362787a84e287cbe2ae99a8de46af94907009ee67432790469ae7129a"},{"path":"src/core/ole/OleCompoundDocument.mjs","sha256":"34d5771dfc5195e16d0eb167dafb3daec2ac60b214a1a57be5a7b9e78d5ca05e"},{"path":"src/core/ole/OleCompoundDocumentWriter.mjs","sha256":"387f511a4d4a6e03ca085ddf51ef9d9254910cd9cb3a140e4c9f67f90a89d7b4"},{"path":"src/core/ole/OleConstants.mjs","sha256":"dcef27b79d6d839eafcb62b51e7084f48a5567f5cf3bc09c1dd9255277ab5a6f"},{"path":"src/core/ole/OleDirectoryEntry.mjs","sha256":"dfdeba53530b63d4040582e55fc375cb708cf2c12032ca2619f171a32bcbd84e"},{"path":"src/ui/AltiumPcbBottomViewMirror.mjs","sha256":"892f549d381bc7c7b67254065f7c6ee1dd08c184ce4fccea9ac03391bde1be05"},{"path":"src/ui/AltiumScene3dAuthoredBodyAnchorAdapter.mjs","sha256":"5d9a7b036e323acdc620dcf2b8997c41606c287f75dab8f4516f07670ff6673e"},{"path":"src/ui/AltiumScene3dAuthoredConnectorYawPolicy.mjs","sha256":"f91fb4c98811a84dfc3511fb037cb9722f121344bd5056177756bf9c39fe38a2"},{"path":"src/ui/AltiumScene3dBottomPadRotationAdapter.mjs","sha256":"03fd6713891f2847b3b03808aeef00e77126b09bb372b9c112b626b83ee31f1d"},{"path":"src/ui/AltiumScene3dBottomSourceHalfTurnPolicy.mjs","sha256":"adcceb5d19085856a17b6772d2fb1520fc36d431bb4e4bdb1848e297d4ed90b7"},{"path":"src/ui/AltiumScene3dComponentBodyAdapter.mjs","sha256":"4aea27f91bad6deda2321f613eeb05bc4b6b3fcabf5b57b1515efce1b1a66ee1"},{"path":"src/ui/AltiumScene3dDisplayModuleYawPolicy.mjs","sha256":"293f0ff9c87cf560b57b14015611c24dc187514446beb03f62578aa3c2ca735a"},{"path":"src/ui/AltiumScene3dExternalPlacementAdapter.mjs","sha256":"f92410372e77df247594fd50339f19318d332da45b3d3bfdf80d23f61eb9a055"},{"path":"src/ui/AltiumScene3dIdentityTokens.mjs","sha256":"f4047d7cfb033d3f21f4a8b90bbba23f8aa408306f8ee7d44a42ccdaa178935d"},{"path":"src/ui/AltiumScene3dPlacementRotationPolicy.mjs","sha256":"32d272be4ed91616237cd8c74c7faa49f82138b7c03268490a28b2f2e2a9154a"},{"path":"src/ui/AltiumScene3dQfnFootprintDetector.mjs","sha256":"eb5ac1e634da650d0027d4b0f937ac0c4efd949c29b39bf4bd5fd03607d44518"},{"path":"src/ui/AltiumScene3dRepeatedFullFootprintBodyCollapse.mjs","sha256":"0536f4fe445d1bea5df85a6502de4ed8d1608390497eb1218da2fdbe5345573b"},{"path":"src/ui/AltiumScene3dRepeatedModelOwnerRepair.mjs","sha256":"a4b1ec5dd5abdcc17066bf66ea295eb44371af0f8a0bc47647e2f9163727424c"},{"path":"src/ui/AltiumScene3dShapeStackOwnerAdapter.mjs","sha256":"b18d55eea6a1a1837fa18e6e1d689f4fb2581e26e7a5aa7f95180b8901bf4e1d"},{"path":"src/ui/AltiumScene3dShapeStackOwnerConflictPolicy.mjs","sha256":"441c850eb6a50315ffcb0af6302473ca4f91827806c0ddb06aa051680697f605"},{"path":"src/ui/AltiumScene3dTwoRowFootprintDetector.mjs","sha256":"9a8a126ac7d1fd2e6045ec32102521a914142dc5f48cb26b94222a193e805f93"},{"path":"src/ui/BomTableRenderer.mjs","sha256":"0aa6a10bd109e50e92c6a6f67d44145f85664d37decf6d66c373a9602e7e55a8"},{"path":"src/ui/PcbArcUtils.mjs","sha256":"8ab6172352645dbf6dd6258ef5dec36cd549c5a96abcb287de5d2cd643fb4c75"},{"path":"src/ui/PcbBarcodeTextRenderer.mjs","sha256":"8d0b5ea8bf08bb91a2bced5c46e5ef8e0cae5989440e992218d8ac95413c0292"},{"path":"src/ui/PcbCopperPrimitiveSplitter.mjs","sha256":"759aa5f6d39511aac69f1f0ca3afe462b8595d4cad586c3b24d0a9064933971a"},{"path":"src/ui/PcbDimensionPrimitiveRenderer.mjs","sha256":"172f14b39b218d241fa6f2aa47cdee83ff587d9165b7c66b29a57ad4b23cf6ab"},{"path":"src/ui/PcbEdgeFacingGlyphNormalizer.mjs","sha256":"d1024e62e8cdf98f1677c1b881dc921a4533ec689d226a9fe89c9875b38875e2"},{"path":"src/ui/PcbEmbeddedFontFaceRenderer.mjs","sha256":"32e96fab5059009f199755e31bc963754073fc8a1deff400b7dc8e5951fb3a68"},{"path":"src/ui/PcbFootprintPadAxisNormalizer.mjs","sha256":"c6841ba836e6cd1aee75f8145797eac9be471b5f7d2e9f95a2a4a213d47015e2"},{"path":"src/ui/PcbFootprintPrimitiveSelector.mjs","sha256":"17264251298c1aa2265d68447829ebd78efd480307f58a9b7cda4ce1cc3a334a"},{"path":"src/ui/PcbInteractionGeometry.mjs","sha256":"fa884a3e117d3fe7618c504be5f1c79c5fc74cc78db200d617e046f7da8239f1"},{"path":"src/ui/PcbInteractionIndex.mjs","sha256":"2aad186bb1a915d8f87560fdd517687521afb3584347077051589f13feec722a"},{"path":"src/ui/PcbInteractionItemRegistry.mjs","sha256":"4acc5a0a2697bb70c107f02484e6fa24c3da1f163dad1e40436c3a84452a8cfe"},{"path":"src/ui/PcbInteractionLayerModel.mjs","sha256":"f0926044f604a4ec18107de516933208c1d63725e545522e229f280701a36cfe"},{"path":"src/ui/PcbNativeTextKnockoutDetector.mjs","sha256":"0ca6bcaab6586846c1838d457c7eb80f4458c977a210d1c263b92781edaba3ab"},{"path":"src/ui/PcbPadMaskApertureRenderer.mjs","sha256":"803a931a56a900d73bf9b49771131659b515526acf21f8ee864efdf0602e9be4"},{"path":"src/ui/PcbRegionPrimitiveRenderer.mjs","sha256":"80ffbdbaa8325959e8efa3ccc33fea9f022cbe92da997c35cd73e02a2c79ee5b"},{"path":"src/ui/PcbScene3dBoardOutlineRefiner.mjs","sha256":"aa82e2558869d071b7f482ceb292d243be16875952e454d264e17b8cd835c89d"},{"path":"src/ui/PcbScene3dBuilder.mjs","sha256":"54900524eab8486363758fceb8d3c6e4118545c3050040c54c95112527f84094"},{"path":"src/ui/PcbScene3dCopperRegionDetailBuilder.mjs","sha256":"efc6a5a93193a45d5d2502c97268e5f17935d346aadca802ee6a2d68ecbb7bac"},{"path":"src/ui/PcbScene3dDrillCutoutBuilder.mjs","sha256":"8b45e376f759f0701b367af8128854f2187143eb82d6f0e5ab0ce9d1154faaf8"},{"path":"src/ui/PcbScene3dModelRegistry.mjs","sha256":"b7ed18b37a044be3eb6772d5aa0fbce3911eb94e2efaa87e3b135ed3629cce85"},{"path":"src/ui/PcbScene3dPackageDimensionResolver.mjs","sha256":"2a7c44fa552bffecf56bc6f59a7e30b7040f489d8d2e2c66f5faf7defbe00a87"},{"path":"src/ui/PcbScene3dPackages.mjs","sha256":"44d27b169f233db741f0cb25d7a8206c7cdc079466c5efb06ca8aa4146b957f9"},{"path":"src/ui/PcbScene3dPadLocalSpanResolver.mjs","sha256":"f6ce117b38deb770a56a08ef2911319e17b688cf751867027d2d22f09c650caa"},{"path":"src/ui/PcbScene3dPadYawResolver.mjs","sha256":"ea04e8f95242437563aaa14c8a226ed53a056fe4e574249565d421d9048843dc"},{"path":"src/ui/PcbScene3dPlacementSideResolver.mjs","sha256":"ea1a40159125375c846dc82f61dbc9a2b112dacd5d0e5c4ecc589901866ed645"},{"path":"src/ui/PcbScene3dScenePreparator.mjs","sha256":"a5a12fe7b0b3e18d71268f263a221d63e47549bbf1699f9e248a1e1e8b95ac7a"},{"path":"src/ui/PcbScene3dStaticBodyOwnerPromotion.mjs","sha256":"af6c44f8b907073b71ad484c535a88a61284e7652d711fce9c2cd6bbcbe499bb"},{"path":"src/ui/PcbScene3dStaticBodyPadOwnerPromotion.mjs","sha256":"a905c4744c7df078596f8fa0b58a5e9dd2766f9535566737ea895af903a6c385"},{"path":"src/ui/PcbScene3dStaticBodyPlacementBuilder.mjs","sha256":"23bdd9151089f9a1afea5aede98c33fc7b1bf34f333df8feb91c129886e47cde"},{"path":"src/ui/PcbScene3dStaticBodyPrototypeRecovery.mjs","sha256":"48b12d3406c19a3b5727b701c9f7532a19f6bd637305fa51dfe0c24f6d9bc375"},{"path":"src/ui/PcbScene3dStaticBodyRecovery.mjs","sha256":"d868c313ab9ed8d45ef81ed1b1c1d383de148ae01c9b197bbe303d6dcdffa762"},{"path":"src/ui/PcbScene3dStaticBodySelectionKeyBuilder.mjs","sha256":"7d130e9ab1e1bfe357096241471c2a14fd904b86c612a81a4254cf9d26a985b8"},{"path":"src/ui/PcbScene3dStaticBodySymmetricOwnerPromotion.mjs","sha256":"0e3676f2f2a0466476d38314c40bba5edc11f201985da3025247a50615661f4c"},{"path":"src/ui/PcbScene3dStaticBodySymmetryRecovery.mjs","sha256":"ce20c07bd055825ed918505ab5eaa7fef5d91bd15473578835df54559569862b"},{"path":"src/ui/PcbScene3dSummaryRenderer.mjs","sha256":"3c4312018accda438d5482d3b7fb686687b328caa563c8b9806d4225b4f68acf"},{"path":"src/ui/PcbScene3dTextBoxLayoutResolver.mjs","sha256":"6e2f3083555a4cb5faedef7dbf2bf443fd94f577ea463783c3ec77eb80be6fbe"},{"path":"src/ui/PcbSideResolvedRenderModel.mjs","sha256":"62647b98263dc6cdc9a79ed6fc48705b054abc534ba6decd9582043606f25389"},{"path":"src/ui/PcbSvgRenderer.mjs","sha256":"32273a67574a2b803e80f52e178d0d8320f858bf6d9fb303b1fc28d538e982ca"},{"path":"src/ui/PcbTextPrimitiveRenderer.mjs","sha256":"d1eae1dfa71b5be8c166564595bf308990221a83328bd04a65ea89ba2b49ceed"},{"path":"src/ui/SchematicColorResolver.mjs","sha256":"ba03749bd50a9f3b5db57334ff4fc4f42b8f95a95fc30ab36b1d1199a66da731"},{"path":"src/ui/SchematicContentLayout.mjs","sha256":"bc8996084da679aa9fae0728b13117c0178363edc229f1f16b19d661cfea7486"},{"path":"src/ui/SchematicDirectiveRenderer.mjs","sha256":"c29ab1e779e8e374db3b441c6e35614ce482ddc1735a0b408f9edb8a13762066"},{"path":"src/ui/SchematicImageRenderer.mjs","sha256":"647858a10a6a5fc77af63e88fc7644c6511070ec330f7fdbfd7694f0a3377d93"},{"path":"src/ui/SchematicJunctionRenderer.mjs","sha256":"6584af8fa602aac987fe8376121d3cfe12738f67750e2830116c6cca28ae9c59"},{"path":"src/ui/SchematicLineColorResolver.mjs","sha256":"8c46bcd318e5a175ecb5ccf53477b07a1c185928695c29e45f0afe17c2fc7203"},{"path":"src/ui/SchematicNativeFooterPartitioner.mjs","sha256":"ebdee1fd03050c95180c4f301a5ecf38e7e47594b97aae65bac8f1f391183af5"},{"path":"src/ui/SchematicNoteRenderer.mjs","sha256":"85835827e14fb491a824b55b107470fb9528b5c6a642aaefe391845cbb72b901"},{"path":"src/ui/SchematicOwnerPinLabelLayout.mjs","sha256":"4379716eae1f6b35ce516aac05ca986c0c3580c0363b1b75380919b797fa0b8b"},{"path":"src/ui/SchematicOwnerPinMarkerLineThemer.mjs","sha256":"988eb199dfa2ee1a7f0f3536ec5a29b1a4872c5daa7cca2c36475823d88d472b"},{"path":"src/ui/SchematicPinSvgRenderer.mjs","sha256":"78dd0cd4b3a2ae2b4ff0b1924c76ad41cf035efe168d3e7c432b691020a4bb34"},{"path":"src/ui/SchematicPortRenderer.mjs","sha256":"ffe1c9103b3c6951e1387f0e16c8f2cf78ee3c119e798728ffcc866d966d8320"},{"path":"src/ui/SchematicPowerDiagramImageProcessor.mjs","sha256":"4cb4f144e7ab12556e66be77ee686501ffebc07696f1ca32c917faa355fc5b71"},{"path":"src/ui/SchematicPowerDiagramLineMasks.mjs","sha256":"61842c13729b9b61fb015010e281236dd8ec2295a41d93389db30b6271e61606"},{"path":"src/ui/SchematicPowerPortRenderer.mjs","sha256":"3247da347bd85729d3b3421be1395c18705fd08d85678498c521b3abb7cde0ed"},{"path":"src/ui/SchematicRegionRenderer.mjs","sha256":"b7ee4bda1feff5727db80e5b5218642a856b1d55abaedb06a4535be32e99e48e"},{"path":"src/ui/SchematicRenderOpsSidecarBuilder.mjs","sha256":"cc99e49c940b1dab0185e902b8f62eda9bbef56844421d15b6d1479e0ecdd62a"},{"path":"src/ui/SchematicShapeRenderer.mjs","sha256":"677b514a26b507308ade0c5eba137b0a958f80cd11bbc52b22a93f448951ad02"},{"path":"src/ui/SchematicSheetChromeRenderer.mjs","sha256":"53f7711cf24767e310272912178f3db31d44b55b1a5c9be6c01dfbc09306efab"},{"path":"src/ui/SchematicSheetSymbolRenderer.mjs","sha256":"a9bd87ac3e0950938276d6aaa060a060137bf3a414bb1f1b8e1ea4334c03e2c4"},{"path":"src/ui/SchematicSheetZoneRenderer.mjs","sha256":"1fe5934f7cc8c66a6215303ad4ef6f73baa9528724c3d9940aec10e04b1d3ae6"},{"path":"src/ui/SchematicSvgRenderer.mjs","sha256":"1be780c1ba094c4944db1e7ae535228a7dd54492494f2b9fc936c94adbc140f5"},{"path":"src/ui/SchematicSvgUtils.mjs","sha256":"7aabdf074d2ebbd741df6d686c794cd437c02c9e9d3c8297d52e56bdb5eac902"},{"path":"src/ui/SchematicTypography.mjs","sha256":"7910eca9a01d84eb5fec775469a9db581d35f7560ccde27a4ac818658097a65c"},{"path":"src/ui/TextGeometrySidecarBuilder.mjs","sha256":"3d00ee22ace17bec70d41c0f527779b0d7ea347b2bda1833e15910f24693e1cf"}],"artifactChecksum":"e3bfcbcdd0fdcda6de5f08c16a75949eb377749274d742a7a89ff16ad3a09c98"}
@@ -0,0 +1,4 @@
1
+ // SPDX-FileCopyrightText: 2026 André Fiedler
2
+ // SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ export { ToolkitCapabilities } from './convergence/ToolkitCapabilities.mjs'
@@ -0,0 +1,230 @@
1
+ // SPDX-FileCopyrightText: 2026 André Fiedler
2
+ // SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ import { CircuitJsonModelAdapterPrimitives } from '../core/circuit-json/CircuitJsonModelAdapterPrimitives.mjs'
5
+ import { CircuitJsonSchematicGraphicBuilder } from '../core/circuit-json/CircuitJsonSchematicGraphicBuilder.mjs'
6
+ import { AltiumSchematicCoordinateProjection } from './AltiumSchematicCoordinateProjection.mjs'
7
+
8
+ const Primitives = CircuitJsonModelAdapterPrimitives
9
+ const LEGACY_SCHEMATIC_DRAWING_TYPES = new Set([
10
+ 'schematic_line',
11
+ 'schematic_net_label',
12
+ 'schematic_text',
13
+ 'schematic_trace'
14
+ ])
15
+
16
+ /**
17
+ * Enriches the frozen native adapter output at the common API boundary.
18
+ */
19
+ export class AltiumCircuitJsonProjection {
20
+ /**
21
+ * Replaces the legacy minimal drawing subset with the rich common model.
22
+ * @param {object[]} adapted Historical adapter output.
23
+ * @param {Record<string, any>} native Native renderer model.
24
+ * @returns {object[]} Canonical CircuitJSON rows.
25
+ */
26
+ static project(adapted, native) {
27
+ const nativeSchematic = native?.schematic
28
+ if (!nativeSchematic) return [...adapted]
29
+ const schematic =
30
+ AltiumCircuitJsonProjection.#schematicWithSourceTypes(
31
+ nativeSchematic
32
+ )
33
+
34
+ const sourceFormat = Primitives.sourceFormat(native)
35
+ const idScope = Primitives.idScope(native, sourceFormat)
36
+ const componentIds = AltiumCircuitJsonProjection.#componentIds(
37
+ schematic,
38
+ idScope
39
+ )
40
+ const hiddenComponentIds = new Set(
41
+ Primitives.array(schematic.components)
42
+ .filter(
43
+ (component) =>
44
+ component?.schematicDesignatorVisible === false
45
+ )
46
+ .map((component) => componentIds.get(component))
47
+ .filter(Boolean)
48
+ )
49
+ const nativeComponentsById = new Map(
50
+ Primitives.array(schematic.components).map((component) => [
51
+ componentIds.get(component),
52
+ component
53
+ ])
54
+ )
55
+ const legacySchematicSourceTraceIds = new Set(
56
+ adapted
57
+ .filter((element) => element?.type === 'schematic_trace')
58
+ .map((element) => String(element.source_trace_id || ''))
59
+ .filter(Boolean)
60
+ )
61
+ const protectedPcbSourceTraceIds = new Set(
62
+ adapted
63
+ .filter((element) => element?.type === 'pcb_trace')
64
+ .map((element) => String(element.source_trace_id || ''))
65
+ .filter(Boolean)
66
+ )
67
+ const model = adapted
68
+ .filter((element) =>
69
+ AltiumCircuitJsonProjection.#preservesAdaptedElement(
70
+ element,
71
+ legacySchematicSourceTraceIds,
72
+ protectedPcbSourceTraceIds
73
+ )
74
+ )
75
+ .map((element) => {
76
+ if (element?.type !== 'schematic_component') return element
77
+ const component = nativeComponentsById.get(
78
+ element.schematic_component_id
79
+ )
80
+ return {
81
+ ...element,
82
+ rotation: -(
83
+ Primitives.number(
84
+ component?.rotation,
85
+ element.rotation
86
+ ) || 0
87
+ ),
88
+ ...(hiddenComponentIds.has(element.schematic_component_id)
89
+ ? { show_label: false }
90
+ : {})
91
+ }
92
+ })
93
+ const netIds = AltiumCircuitJsonProjection.#netIds(model)
94
+
95
+ model.push(
96
+ AltiumCircuitJsonProjection.#rootSheet(schematic, native, idScope)
97
+ )
98
+
99
+ CircuitJsonSchematicGraphicBuilder.append(
100
+ model,
101
+ schematic,
102
+ idScope,
103
+ componentIds,
104
+ netIds
105
+ )
106
+ return AltiumSchematicCoordinateProjection.project(
107
+ model,
108
+ schematic?.sheet?.height
109
+ )
110
+ }
111
+
112
+ /**
113
+ * Classifies native Altium record-27 wire segments at the convergence
114
+ * boundary while preserving explicit source-neutral classifications.
115
+ * @param {Record<string, any>} schematic Historical native schematic.
116
+ * @returns {Record<string, any>} Projection-owned schematic view.
117
+ */
118
+ static #schematicWithSourceTypes(schematic) {
119
+ return {
120
+ ...schematic,
121
+ lines: Primitives.array(schematic.lines).map((line) =>
122
+ Object.hasOwn(line || {}, 'sourceType')
123
+ ? line
124
+ : {
125
+ ...line,
126
+ sourceType:
127
+ String(line?.recordType || '') === '27'
128
+ ? 'wire'
129
+ : 'graphic'
130
+ }
131
+ )
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Keeps source traces unless they exclusively back the legacy schematic
137
+ * projection. PCB and unrelated source relations remain byte-for-byte.
138
+ * @param {Record<string, any>} element Adapted CircuitJSON row.
139
+ * @param {Set<string>} legacySchematicSourceTraceIds Schematic trace ids.
140
+ * @param {Set<string>} protectedPcbSourceTraceIds PCB trace ids.
141
+ * @returns {boolean} Whether the adapted row belongs in the rich model.
142
+ */
143
+ static #preservesAdaptedElement(
144
+ element,
145
+ legacySchematicSourceTraceIds,
146
+ protectedPcbSourceTraceIds
147
+ ) {
148
+ const type = String(element?.type || '')
149
+ if (LEGACY_SCHEMATIC_DRAWING_TYPES.has(type)) return false
150
+ if (type !== 'source_trace') return true
151
+
152
+ const id = String(element.source_trace_id || '')
153
+ return (
154
+ !legacySchematicSourceTraceIds.has(id) ||
155
+ protectedPcbSourceTraceIds.has(id)
156
+ )
157
+ }
158
+
159
+ /**
160
+ * Projects the source page as the root sheet, not a child-sheet symbol.
161
+ * @param {Record<string, any>} schematic Native schematic.
162
+ * @param {Record<string, any>} native Native document.
163
+ * @param {string} idScope Document id scope.
164
+ * @returns {object} Canonical root-sheet row.
165
+ */
166
+ static #rootSheet(schematic, native, idScope) {
167
+ return {
168
+ type: 'schematic_sheet',
169
+ schematic_sheet_id: Primitives.id(idScope, [
170
+ 'schematic_sheet',
171
+ 'root'
172
+ ]),
173
+ name: Primitives.string(
174
+ native?.summary?.title || native?.fileName,
175
+ 'Main'
176
+ ),
177
+ sheet_index: 0,
178
+ width: Math.max(
179
+ Primitives.number(schematic?.sheet?.width, 0) || 0,
180
+ 0
181
+ ),
182
+ height: Math.max(
183
+ Primitives.number(schematic?.sheet?.height, 0) || 0,
184
+ 0
185
+ )
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Reconstructs historical deterministic component ids without mutation.
191
+ * @param {Record<string, any>} schematic Native schematic.
192
+ * @param {string} idScope Document id scope.
193
+ * @returns {Map<object, string>} Native component id lookup.
194
+ */
195
+ static #componentIds(schematic, idScope) {
196
+ const ids = new Map()
197
+ for (const [index, component] of Primitives.array(
198
+ schematic?.components
199
+ ).entries()) {
200
+ ids.set(
201
+ component,
202
+ Primitives.id(idScope, [
203
+ 'schematic_component',
204
+ component?.designator || component?.name || index
205
+ ])
206
+ )
207
+ }
208
+ return ids
209
+ }
210
+
211
+ /**
212
+ * Indexes canonical source nets by their native names.
213
+ * @param {object[]} model Canonical rows.
214
+ * @returns {Map<string, string>} Source-net id lookup.
215
+ */
216
+ static #netIds(model) {
217
+ return new Map(
218
+ model
219
+ .filter((element) => element?.type === 'source_net')
220
+ .map((element) => [
221
+ String(element.name || ''),
222
+ String(element.source_net_id || '')
223
+ ])
224
+ .filter(([name, id]) => name && id)
225
+ )
226
+ }
227
+ }
228
+
229
+ Object.freeze(AltiumCircuitJsonProjection.prototype)
230
+ Object.freeze(AltiumCircuitJsonProjection)
@@ -0,0 +1,167 @@
1
+ // SPDX-FileCopyrightText: 2026 André Fiedler
2
+ // SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ import { DocumentResult, ToolkitAsset } from 'circuitjson-toolkit/parser'
5
+
6
+ import { AltiumParser } from '../core/altium/AltiumParser.mjs'
7
+ import { CircuitJsonModelAdapter } from '../core/circuit-json/CircuitJsonModelAdapter.mjs'
8
+ import { CircuitJsonSchematicImageProjection } from '../core/circuit-json/CircuitJsonSchematicImageProjection.mjs'
9
+ import { AltiumCircuitJsonProjection } from './AltiumCircuitJsonProjection.mjs'
10
+ import { ParserInput } from './ParserInput.mjs'
11
+
12
+ /**
13
+ * Converts one native parse into a canonical CircuitJSON document envelope.
14
+ */
15
+ export class AltiumDocumentBuilder {
16
+ /**
17
+ * Runs the native parser and CircuitJSON adapter exactly once.
18
+ * @param {{ input: { fileName: string, data: string | ArrayBuffer | Uint8Array } }} normalized Normalized request.
19
+ * @returns {{ native: Record<string, any>, model: object[], nativeSidecarCount: number }} Decoded source data.
20
+ */
21
+ static decode(normalized) {
22
+ const buffer = ParserInput.arrayBuffer(normalized.input.data)
23
+ const native = AltiumParser.parseArrayBufferToRendererModel(
24
+ normalized.input.fileName,
25
+ buffer
26
+ )
27
+ const adapted = CircuitJsonModelAdapter.fromRendererModel(native)
28
+ const projected = AltiumCircuitJsonProjection.project(adapted, native)
29
+ const model = projected.filter(
30
+ (element) =>
31
+ !String(element?.type || '').startsWith('altium_toolkit_')
32
+ )
33
+ return {
34
+ native,
35
+ model,
36
+ nativeSidecarCount: projected.length - model.length
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Parses and validates one normalized request exactly once.
42
+ * @param {{ input: { fileName: string, data: string | ArrayBuffer | Uint8Array, assets: object[] }, sourceReference: object, options: Record<string, any> }} normalized Normalized request.
43
+ * @param {{ native: Record<string, any>, model: object[], nativeSidecarCount: number } | null} [decoded] Previously decoded source data.
44
+ * @returns {Record<string, any>} Canonical immutable document.
45
+ */
46
+ static build(normalized, decoded = null) {
47
+ const prepared = decoded || AltiumDocumentBuilder.decode(normalized)
48
+ const { model, native } = prepared
49
+ const extension = AltiumDocumentBuilder.#extension(
50
+ native,
51
+ normalized.options
52
+ )
53
+ const runtime =
54
+ normalized.options.retainSource === 'reference'
55
+ ? { sourceReference: normalized.sourceReference }
56
+ : {}
57
+ return DocumentResult.createValidated(
58
+ {
59
+ model,
60
+ source: {
61
+ format: 'altium',
62
+ fileName: normalized.input.fileName,
63
+ fileType: ParserInput.suffix(normalized.input.fileName)
64
+ },
65
+ extensions: extension ? { altium: extension } : {},
66
+ assets: AltiumDocumentBuilder.#assets(
67
+ normalized.input.assets,
68
+ normalized.options.decodeAssets,
69
+ native
70
+ ),
71
+ diagnostics: [
72
+ ...(native.diagnostics || []),
73
+ ...CircuitJsonSchematicImageProjection.diagnostics(native)
74
+ ],
75
+ statistics: {
76
+ elementCount: model.length,
77
+ nativeSidecarCount: prepared.nativeSidecarCount,
78
+ nativeKind: String(native.kind || '')
79
+ }
80
+ },
81
+ runtime
82
+ )
83
+ }
84
+
85
+ /**
86
+ * Selects source-native extension facts according to common options.
87
+ * @param {Record<string, any>} native Native renderer model.
88
+ * @param {Record<string, any>} options Common options.
89
+ * @returns {Record<string, any> | null} Extension payload or null.
90
+ */
91
+ static #extension(native, options) {
92
+ if (
93
+ options.extensions === 'none' ||
94
+ (Array.isArray(options.extensions) && !options.extensions.length)
95
+ ) {
96
+ return null
97
+ }
98
+ const includeNative =
99
+ options.extensions === 'full' ||
100
+ options.preserveRaw ||
101
+ (Array.isArray(options.extensions) &&
102
+ options.extensions.includes('altium.native-model'))
103
+ const completeness =
104
+ options.extensions === 'full'
105
+ ? 'full'
106
+ : options.extensions === 'metadata'
107
+ ? 'metadata'
108
+ : 'canonical'
109
+ const projectContext = AltiumDocumentBuilder.#projectContext(native)
110
+ const metadata = {
111
+ $meta: {
112
+ schema: 'ecad-toolkit.extension.v1',
113
+ completeness,
114
+ included: [
115
+ 'altium.summary',
116
+ ...(projectContext ? ['altium.project-context'] : []),
117
+ ...(includeNative ? ['altium.native-model'] : [])
118
+ ],
119
+ omitted: []
120
+ },
121
+ kind: String(native.kind || ''),
122
+ fileType: String(native.fileType || ''),
123
+ summary: native.summary || {},
124
+ ...(projectContext ? { projectContext } : {})
125
+ }
126
+ return includeNative ? { ...metadata, native } : metadata
127
+ }
128
+
129
+ /**
130
+ * Selects compact project facts required to resolve canonical schematics.
131
+ * @param {Record<string, any>} native Native renderer model.
132
+ * @returns {{ parameters: Record<string, string>, documents: string[] } | null} Project facts.
133
+ */
134
+ static #projectContext(native) {
135
+ if (native?.kind !== 'project' || !native.project) return null
136
+ const parameters = Object.fromEntries(
137
+ (native.project.parameters?.list || []).map((parameter) => [
138
+ String(parameter?.name || ''),
139
+ String(parameter?.value || '')
140
+ ])
141
+ )
142
+ const documents = (native.project.documents || []).map((document) =>
143
+ String(document?.normalizedPath || document?.path || '')
144
+ )
145
+ return { parameters, documents }
146
+ }
147
+
148
+ /**
149
+ * Applies the common asset decode policy without sharing caller buffers.
150
+ * @param {object[]} assets Caller-supplied assets.
151
+ * @param {string} mode Decode mode.
152
+ * @param {Record<string, unknown>} native Native renderer model.
153
+ * @returns {object[]} Canonical asset records.
154
+ */
155
+ static #assets(assets, mode, native) {
156
+ return [
157
+ ...ToolkitAsset.prepareAll(assets, { mode }),
158
+ ...ToolkitAsset.prepareAll(
159
+ CircuitJsonSchematicImageProjection.assets(native),
160
+ { mode }
161
+ )
162
+ ]
163
+ }
164
+ }
165
+
166
+ Object.freeze(AltiumDocumentBuilder.prototype)
167
+ Object.freeze(AltiumDocumentBuilder)
@@ -0,0 +1,98 @@
1
+ // SPDX-FileCopyrightText: 2026 André Fiedler
2
+ // SPDX-License-Identifier: GPL-3.0-or-later
3
+
4
+ const DOCUMENT_SCHEMA = 'ecad-toolkit.document.v1'
5
+
6
+ /** Resolves explicit Altium source extensions without changing document shape. */
7
+ export class AltiumExtensionResolver {
8
+ /**
9
+ * Returns the retained native renderer model when explicitly requested.
10
+ * Historical native renderer models pass through unchanged so callers can
11
+ * use one boundary during migration.
12
+ * @param {unknown} document Canonical document or native renderer model.
13
+ * @returns {Record<string, any> | null} Retained native model.
14
+ */
15
+ static nativeModel(document) {
16
+ if (!AltiumExtensionResolver.#record(document)) return null
17
+ const schema = String(
18
+ AltiumExtensionResolver.#data(document, 'schema') || ''
19
+ )
20
+ if (schema !== DOCUMENT_SCHEMA) {
21
+ return AltiumExtensionResolver.#isLegacyModel(document, schema)
22
+ ? document
23
+ : null
24
+ }
25
+
26
+ const source = AltiumExtensionResolver.#data(document, 'source')
27
+ if (
28
+ String(AltiumExtensionResolver.#data(source, 'format') || '') !==
29
+ 'altium'
30
+ ) {
31
+ return null
32
+ }
33
+ const extensions = AltiumExtensionResolver.#data(document, 'extensions')
34
+ const altium = AltiumExtensionResolver.#data(extensions, 'altium')
35
+ const native = AltiumExtensionResolver.#data(altium, 'native')
36
+ return AltiumExtensionResolver.#record(native) ? native : null
37
+ }
38
+
39
+ /**
40
+ * Returns whether an explicit native renderer model is available.
41
+ * @param {unknown} document Canonical document or native renderer model.
42
+ * @returns {boolean} Whether native Altium data can be resolved.
43
+ */
44
+ static hasNativeModel(document) {
45
+ return AltiumExtensionResolver.nativeModel(document) !== null
46
+ }
47
+
48
+ /**
49
+ * Identifies a historical Altium renderer model by its owned schema.
50
+ * @param {Record<string, any>} value Model candidate.
51
+ * @param {string} schema Owned schema value.
52
+ * @returns {boolean} Whether the value is a native Altium model.
53
+ */
54
+ static #isLegacyModel(value, schema) {
55
+ if (
56
+ schema.startsWith('urn:altium-toolkit:') ||
57
+ schema.startsWith('altium-toolkit.')
58
+ ) {
59
+ return true
60
+ }
61
+ const sourceFormat = String(
62
+ AltiumExtensionResolver.#data(value, 'sourceFormat') || ''
63
+ )
64
+ return sourceFormat === 'altium'
65
+ }
66
+
67
+ /**
68
+ * Reads one own data property without invoking accessors.
69
+ * @param {unknown} owner Field owner.
70
+ * @param {string} key Field name.
71
+ * @returns {unknown} Own data value or undefined.
72
+ */
73
+ static #data(owner, key) {
74
+ if (!AltiumExtensionResolver.#record(owner)) return undefined
75
+ try {
76
+ const descriptor = Object.getOwnPropertyDescriptor(owner, key)
77
+ return descriptor && Object.hasOwn(descriptor, 'value')
78
+ ? descriptor.value
79
+ : undefined
80
+ } catch {
81
+ return undefined
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Returns true for non-array object records.
87
+ * @param {unknown} value Candidate value.
88
+ * @returns {boolean} Whether the value is a record.
89
+ */
90
+ static #record(value) {
91
+ return Boolean(
92
+ value && typeof value === 'object' && !Array.isArray(value)
93
+ )
94
+ }
95
+ }
96
+
97
+ Object.freeze(AltiumExtensionResolver.prototype)
98
+ Object.freeze(AltiumExtensionResolver)