altium-toolkit 1.1.22 → 1.1.23

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 (99) hide show
  1. package/README.md +34 -5
  2. package/docs/api.md +134 -23
  3. package/docs/model-format.md +174 -20
  4. package/docs/schemas/altium_toolkit/embedded_assets_a1.schema.json +56 -0
  5. package/docs/schemas/altium_toolkit/fixture_coverage_matrix_a1.schema.json +89 -0
  6. package/docs/schemas/altium_toolkit/geometry_bounds_a1.schema.json +86 -0
  7. package/docs/schemas/altium_toolkit/library_catalog_a1.schema.json +65 -0
  8. package/docs/schemas/altium_toolkit/library_diff_a1.schema.json +54 -0
  9. package/docs/schemas/altium_toolkit/library_inspection_a1.schema.json +94 -0
  10. package/docs/schemas/altium_toolkit/library_qa_a1.schema.json +4 -0
  11. package/docs/schemas/altium_toolkit/native_stream_inventory_a1.schema.json +66 -0
  12. package/docs/schemas/altium_toolkit/normalized_model_a1.schema.json +511 -1
  13. package/docs/schemas/altium_toolkit/parameter_record_inventory_a1.schema.json +84 -0
  14. package/docs/schemas/altium_toolkit/parser_diagnostics_a1.schema.json +63 -0
  15. package/docs/schemas/altium_toolkit/parser_value_verification_a1.schema.json +74 -0
  16. package/docs/schemas/altium_toolkit/pcb_class_report_a1.schema.json +79 -0
  17. package/docs/schemas/altium_toolkit/pcb_inspection_a1.schema.json +65 -0
  18. package/docs/schemas/altium_toolkit/pcb_net_membership_a1.schema.json +98 -0
  19. package/docs/schemas/altium_toolkit/project_bundle_a1.schema.json +3 -0
  20. package/docs/schemas/altium_toolkit/project_hierarchy_a1.schema.json +79 -0
  21. package/docs/schemas/altium_toolkit/unsupported_features_a1.schema.json +212 -0
  22. package/docs/testing.md +2 -0
  23. package/examples/README.md +21 -0
  24. package/examples/cli-utils.mjs +148 -0
  25. package/examples/corpus-smoke.mjs +523 -0
  26. package/examples/extract-bom.mjs +47 -0
  27. package/examples/generate-pnp.mjs +59 -0
  28. package/examples/inspect-board.mjs +70 -0
  29. package/examples/inspect-schematic.mjs +406 -0
  30. package/examples/library-catalog.mjs +115 -0
  31. package/examples/net-report.mjs +61 -0
  32. package/examples/validate-library.mjs +59 -0
  33. package/package.json +1 -1
  34. package/src/core/BinaryReader.mjs +213 -2
  35. package/src/core/altium/AltiumParser.mjs +352 -14
  36. package/src/core/altium/AltiumUnits.mjs +205 -0
  37. package/src/core/altium/AsciiRecordParser.mjs +9 -0
  38. package/src/core/altium/EmbeddedAssetReportBuilder.mjs +383 -0
  39. package/src/core/altium/FixtureCoverageMatrixBuilder.mjs +304 -0
  40. package/src/core/altium/GeometryBoundsReportBuilder.mjs +935 -0
  41. package/src/core/altium/LibraryCatalogArtifactBuilder.mjs +296 -0
  42. package/src/core/altium/LibraryDiffReportBuilder.mjs +260 -0
  43. package/src/core/altium/LibraryInspectionReportBuilder.mjs +156 -0
  44. package/src/core/altium/LibraryQaReportBuilder.mjs +374 -1
  45. package/src/core/altium/NativeStreamInventoryBuilder.mjs +177 -0
  46. package/src/core/altium/NormalizedModelSchema.mjs +3 -31
  47. package/src/core/altium/ParameterCollection.mjs +431 -0
  48. package/src/core/altium/ParameterRecordInventoryBuilder.mjs +274 -0
  49. package/src/core/altium/ParserCompatibilityFuzzer.mjs +106 -2
  50. package/src/core/altium/ParserDiagnosticNormalizer.mjs +213 -0
  51. package/src/core/altium/ParserErrors.mjs +90 -0
  52. package/src/core/altium/ParserFieldCoverageReportBuilder.mjs +656 -0
  53. package/src/core/altium/ParserUtils.mjs +24 -0
  54. package/src/core/altium/ParserValueVerificationReportBuilder.mjs +323 -0
  55. package/src/core/altium/PcbClassReportBuilder.mjs +366 -0
  56. package/src/core/altium/PcbInspectionReportBuilder.mjs +313 -0
  57. package/src/core/altium/PcbLayerGroups.mjs +308 -0
  58. package/src/core/altium/PcbLayerStackCustomDataParser.mjs +183 -0
  59. package/src/core/altium/PcbLayerStackInterchangeParser.mjs +473 -4
  60. package/src/core/altium/PcbLayerStackReadModelBuilder.mjs +83 -15
  61. package/src/core/altium/PcbLayerStackSourceMetadataParser.mjs +74 -4
  62. package/src/core/altium/PcbLibModelParser.mjs +20 -4
  63. package/src/core/altium/PcbLibStreamExtractor.mjs +49 -6
  64. package/src/core/altium/PcbModelParser.mjs +223 -4
  65. package/src/core/altium/PcbNetMembershipReportBuilder.mjs +270 -0
  66. package/src/core/altium/PcbStreamExtractor.mjs +130 -6
  67. package/src/core/altium/PcbTrackPrimitiveParser.mjs +66 -2
  68. package/src/core/altium/ProjectDesignBundleBuilder.mjs +15 -0
  69. package/src/core/altium/ProjectHierarchyReportBuilder.mjs +660 -0
  70. package/src/core/altium/ProjectNetlistExporter.mjs +2 -0
  71. package/src/core/altium/RawDataPreservationReportBuilder.mjs +348 -0
  72. package/src/core/altium/SchLibModelParser.mjs +840 -0
  73. package/src/core/altium/SchLibStreamExtractor.mjs +586 -0
  74. package/src/core/altium/SchematicBusEntryParser.mjs +3 -2
  75. package/src/core/altium/SchematicCodeSymbolParser.mjs +663 -0
  76. package/src/core/altium/SchematicConnectivityQaBuilder.mjs +177 -2
  77. package/src/core/altium/SchematicDisplayModeCatalogParser.mjs +10 -1
  78. package/src/core/altium/SchematicFieldCoverageReportBuilder.mjs +549 -0
  79. package/src/core/altium/SchematicHarnessParser.mjs +9 -3
  80. package/src/core/altium/SchematicHyperlinkParser.mjs +122 -0
  81. package/src/core/altium/SchematicNetlistBuilder.mjs +271 -8
  82. package/src/core/altium/SchematicOwnershipGraphParser.mjs +102 -3
  83. package/src/core/altium/SchematicPinParser.mjs +12 -45
  84. package/src/core/altium/SchematicPrimitiveParser.mjs +9 -14
  85. package/src/core/altium/SchematicQaReportBuilder.mjs +2 -0
  86. package/src/core/altium/SchematicRecordStreamParser.mjs +183 -0
  87. package/src/core/altium/SchematicRecordTypeRegistry.mjs +6 -1
  88. package/src/core/altium/SchematicSheetParser.mjs +8 -2
  89. package/src/core/altium/SchematicStreamExtractor.mjs +64 -25
  90. package/src/core/altium/SchematicTextOrientationResolver.mjs +76 -0
  91. package/src/core/altium/SchematicTextParser.mjs +28 -12
  92. package/src/core/altium/SchematicTextRunParser.mjs +81 -0
  93. package/src/core/altium/SchematicThumbnailParser.mjs +425 -0
  94. package/src/core/altium/UnsupportedFeatureReportBuilder.mjs +380 -0
  95. package/src/parser.mjs +35 -1
  96. package/src/renderers.mjs +1 -0
  97. package/src/ui/SchematicShapeRenderer.mjs +49 -6
  98. package/src/ui/SchematicSvgRenderer.mjs +37 -8
  99. package/src/ui/SchematicTypography.mjs +4 -3
@@ -45,7 +45,7 @@ export class SchematicSvgRenderer {
45
45
 
46
46
  /**
47
47
  * Renders a normalized schematic model into SVG markup.
48
- * @param {{ fileName?: string, summary: { title?: string }, schematic?: { sheet: { width: number, height: number, sourceWidth?: number, sourceHeight?: number, paperSize?: string, borderOn?: boolean, titleBlockOn?: boolean, marginWidth?: number, xZones?: number, yZones?: number, titleBlock?: { title?: string, revision?: string, documentNumber?: string, sheetNumber?: string, sheetTotal?: string, date?: string, drawnBy?: string } }, lines: { x1: number, y1: number, x2: number, y2: number, color: string, width: number, lineStyle?: number, isBus?: boolean, ownerIndex?: string, renderOrder?: number, recordType?: string }[], polygons?: { points: { x: number, y: number }[], color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, ownerIndex?: string, renderOrder?: number }[], rectangles?: { x: number, y: number, width: number, height: number, color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, ownerIndex?: string, renderOrder?: number }[], regions?: { x: number, y: number, width: number, height: number, color: string, fill: string, renderOrder?: number }[], ellipses?: { x: number, y: number, radiusX: number, radiusY: number, color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, ownerIndex?: string, renderOrder?: number }[], arcs?: { x: number, y: number, radius: number, startAngle: number, endAngle: number, color: string, width: number, ownerIndex?: string, renderOrder?: number }[], directives?: { x: number, y: number, color: string, name: string, orientation?: number }[], texts: { x: number, y: number, text: string, color: string, recordType?: string, style?: number, fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, rotation?: number, sourceOrientation?: number, isMirrored?: boolean, anchor?: 'start' | 'middle' | 'end', powerPortDirection?: 'up' | 'down' | 'left' | 'right', cornerX?: number, cornerY?: number, fill?: string, borderColor?: string, isSolid?: boolean, showBorder?: boolean, textMargin?: number, noteLines?: string[] }[], components: { x: number, y: number, designator: string }[], pins?: { x: number, y: number, length: number, name: string, nameSegments?: { text: string, overline: boolean }[], designator: string, orientation: 'left' | 'right' | 'top' | 'bottom', electrical?: number, symbolOuter?: number, color: string, labelColor?: string, labelMode?: 'hidden' | 'number-only' | 'name-only' | 'name-and-number', ownerIndex?: string }[], ports?: { x: number, y: number, width: number, height: number, name: string, fill: string, color: string, direction?: 'left' | 'right' | 'up' | 'down', shape?: 'single' | 'double' | 'plain' }[], crosses?: { x: number, y: number, size: number, color: string }[] } }} documentModel
48
+ * @param {{ fileName?: string, summary: { title?: string }, schematic?: { sheet: { width: number, height: number, sourceWidth?: number, sourceHeight?: number, paperSize?: string, borderOn?: boolean, titleBlockOn?: boolean, marginWidth?: number, xZones?: number, yZones?: number, titleBlock?: { title?: string, revision?: string, documentNumber?: string, sheetNumber?: string, sheetTotal?: string, date?: string, drawnBy?: string } }, lines: { x1: number, y1: number, x2: number, y2: number, color: string, width: number, lineStyle?: number, isBus?: boolean, ownerIndex?: string, renderOrder?: number, recordType?: string }[], polygons?: { points: { x: number, y: number }[], color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, ownerIndex?: string, renderOrder?: number }[], rectangles?: { x: number, y: number, width: number, height: number, color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, ownerIndex?: string, renderOrder?: number }[], regions?: { x: number, y: number, width: number, height: number, color: string, fill: string, renderOrder?: number }[], ellipses?: { x: number, y: number, radiusX: number, radiusY: number, color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, ownerIndex?: string, renderOrder?: number }[], arcs?: { x: number, y: number, radius: number, startAngle: number, endAngle: number, color: string, width: number, ownerIndex?: string, renderOrder?: number }[], directives?: { x: number, y: number, color: string, name: string, orientation?: number }[], texts: { x: number, y: number, text: string, textSegments?: { text: string, overline: boolean }[], color: string, recordType?: string, style?: number, fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, rotation?: number, sourceOrientation?: number, isMirrored?: boolean, anchor?: 'start' | 'middle' | 'end', powerPortDirection?: 'up' | 'down' | 'left' | 'right', cornerX?: number, cornerY?: number, fill?: string, borderColor?: string, isSolid?: boolean, showBorder?: boolean, textMargin?: number, noteLines?: string[] }[], components: { x: number, y: number, designator: string }[], pins?: { x: number, y: number, length: number, name: string, nameSegments?: { text: string, overline: boolean }[], designator: string, orientation: 'left' | 'right' | 'top' | 'bottom', electrical?: number, symbolOuter?: number, color: string, labelColor?: string, labelMode?: 'hidden' | 'number-only' | 'name-only' | 'name-and-number', ownerIndex?: string }[], ports?: { x: number, y: number, width: number, height: number, name: string, fill: string, color: string, direction?: 'left' | 'right' | 'up' | 'down', shape?: 'single' | 'double' | 'plain' }[], crosses?: { x: number, y: number, size: number, color: string }[] } }} documentModel
49
49
  * @param {{ projectParameters?: Record<string, string | number | boolean | null | undefined>, colorizeImages?: boolean, colorize_images?: boolean }} options Render options.
50
50
  * @returns {string}
51
51
  */
@@ -1081,7 +1081,9 @@ export class SchematicSvgRenderer {
1081
1081
  const id = SchematicSvgRenderer.#schematicLineMarkerId(marker)
1082
1082
  const shapeName = String(marker?.shapeName || '')
1083
1083
  const fill =
1084
- shapeName === 'filled-arrow' || shapeName === 'square'
1084
+ shapeName === 'filled-arrow' ||
1085
+ shapeName === 'filled-tail' ||
1086
+ shapeName === 'square'
1085
1087
  ? 'context-stroke'
1086
1088
  : 'none'
1087
1089
  const shape =
@@ -1089,9 +1091,13 @@ export class SchematicSvgRenderer {
1089
1091
  ? '<circle cx="5" cy="5" r="3.2" fill="none" stroke="context-stroke" stroke-width="1.4" />'
1090
1092
  : shapeName === 'square'
1091
1093
  ? '<rect x="2" y="2" width="6" height="6" fill="context-stroke" stroke="context-stroke" stroke-width="1" />'
1092
- : '<path d="M 1 1 L 9 5 L 1 9" fill="' +
1093
- fill +
1094
- '" stroke="context-stroke" stroke-width="1.4" stroke-linejoin="round" />'
1094
+ : shapeName === 'tail' || shapeName === 'filled-tail'
1095
+ ? '<path d="M 9 1 L 1 5 L 9 9" fill="' +
1096
+ fill +
1097
+ '" stroke="context-stroke" stroke-width="1.4" stroke-linejoin="round" />'
1098
+ : '<path d="M 1 1 L 9 5 L 1 9" fill="' +
1099
+ fill +
1100
+ '" stroke="context-stroke" stroke-width="1.4" stroke-linejoin="round" />'
1095
1101
 
1096
1102
  return (
1097
1103
  '<marker id="' +
@@ -2608,7 +2614,7 @@ export class SchematicSvgRenderer {
2608
2614
 
2609
2615
  /**
2610
2616
  * Builds one free text primitive with font metadata.
2611
- * @param {{ x: number, y: number, text: string, color: string, recordType?: string, style?: number, fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, rotation?: number, sourceOrientation?: number, isMirrored?: boolean, anchor?: 'start' | 'middle' | 'end', cornerX?: number, cornerY?: number, fill?: string, borderColor?: string, isSolid?: boolean, showBorder?: boolean, textMargin?: number, noteLines?: string[] }} text
2617
+ * @param {{ x: number, y: number, text: string, textSegments?: { text: string, overline: boolean }[], color: string, recordType?: string, style?: number, fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, rotation?: number, sourceOrientation?: number, isMirrored?: boolean, anchor?: 'start' | 'middle' | 'end', cornerX?: number, cornerY?: number, fill?: string, borderColor?: string, isSolid?: boolean, showBorder?: boolean, textMargin?: number, noteLines?: string[] }} text
2612
2618
  * @param {number} sheetHeight
2613
2619
  * @param {{ x1: number, y1: number, x2: number, y2: number }[]} lines
2614
2620
  * @param {{ x: number, y: number, length: number, name?: string, ownerIndex?: string, orientation: 'left' | 'right' | 'top' | 'bottom' }[]} pins
@@ -2696,7 +2702,7 @@ export class SchematicSvgRenderer {
2696
2702
 
2697
2703
  /**
2698
2704
  * Resolves final text placement for schematic free-text annotations.
2699
- * @param {{ x: number, y: number, text: string, ownerIndex?: string, recordType?: string, fontSize?: number, rotation?: number, anchor?: 'start' | 'middle' | 'end' }} text
2705
+ * @param {{ x: number, y: number, text: string, ownerIndex?: string, recordType?: string, fontSize?: number, rotation?: number, anchor?: 'start' | 'middle' | 'end', verticalAnchor?: 'top' }} text
2700
2706
  * @param {number} sheetHeight
2701
2707
  * @param {{ x1: number, y1: number, x2: number, y2: number, lineStyle?: number }[]} lines
2702
2708
  * @param {{ x: number, y: number, name?: string, ownerIndex?: string, orientation: 'left' | 'right' | 'top' | 'bottom' } | null} matchedOwnerPin
@@ -2737,8 +2743,17 @@ export class SchematicSvgRenderer {
2737
2743
  matchedOwnerPin,
2738
2744
  ownerTextBodyBounds
2739
2745
  )
2746
+ const verticalAnchorBaselineOffset =
2747
+ SchematicSvgRenderer.#resolveVerticalAnchorBaselineOffset(
2748
+ text,
2749
+ fontSize
2750
+ )
2740
2751
 
2741
- const unclampedY = projectedY - baselineLift + ownerBodyBaselineOffset
2752
+ const unclampedY =
2753
+ projectedY -
2754
+ baselineLift +
2755
+ ownerBodyBaselineOffset +
2756
+ verticalAnchorBaselineOffset
2742
2757
 
2743
2758
  return {
2744
2759
  x,
@@ -2806,6 +2821,20 @@ export class SchematicSvgRenderer {
2806
2821
  )
2807
2822
  }
2808
2823
 
2824
+ /**
2825
+ * Converts top-anchored text coordinates into SVG baseline coordinates.
2826
+ * @param {{ verticalAnchor?: 'top' }} text Text primitive.
2827
+ * @param {number} fontSize Viewer font size.
2828
+ * @returns {number}
2829
+ */
2830
+ static #resolveVerticalAnchorBaselineOffset(text, fontSize) {
2831
+ if (text?.verticalAnchor !== 'top') {
2832
+ return 0
2833
+ }
2834
+
2835
+ return Number.isFinite(fontSize) && fontSize > 0 ? fontSize : 0
2836
+ }
2837
+
2809
2838
  /**
2810
2839
  * Resolves the owner body or internal owner body cell containing text.
2811
2840
  * @param {{ ownerIndex?: string, recordType?: string, rotation?: number }} text Text primitive.
@@ -104,8 +104,8 @@ export class SchematicTypography {
104
104
  * Builds render options for one schematic text label, including the signed
105
105
  * SVG rotation derived from the original Altium orientation and mirrored
106
106
  * source state.
107
- * @param {{ fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, rotation?: number, sourceOrientation?: number, isMirrored?: boolean }} text
108
- * @returns {{ fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, rotation?: number }}
107
+ * @param {{ fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, rotation?: number, sourceOrientation?: number, isMirrored?: boolean, textSegments?: { text: string, overline: boolean }[] }} text
108
+ * @returns {{ fontSize?: number, fontFamily?: string, fontWeight?: number, fontStyle?: string, rotation?: number, segments?: { text: string, overline: boolean }[] }}
109
109
  */
110
110
  static buildSchematicTextRenderOptions(text) {
111
111
  return {
@@ -117,7 +117,8 @@ export class SchematicTypography {
117
117
  text.rotation,
118
118
  text.sourceOrientation,
119
119
  text.isMirrored
120
- )
120
+ ),
121
+ segments: text.textSegments
121
122
  }
122
123
  }
123
124