@tscircuit/checks 0.0.177 → 0.0.179

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.
package/README.md CHANGED
@@ -15,6 +15,7 @@ and output an array of arrays for any issues found.
15
15
  | [`checkNoPowerPinDefined`](./lib/check-no-power-pin-defined.ts) | Returns `source_no_power_pin_defined_warning` when a chip has no pin with `requires_power=true`. |
16
16
  | [`checkNoGroundPinDefined`](./lib/check-no-ground-pin-defined.ts) | Returns `source_no_ground_pin_defined_warning` when a chip has no pin with `requires_ground=true`. |
17
17
  | [`checkSchematicComponentExcessiveVerticalPadding`](./lib/check-schematic-component-excessive-vertical-padding.ts) | Returns a `schematic_component_styling_warning` with `styling_issue_type: "excessive_top_padding"` or `"excessive_bottom_padding"` when a box-style component has more than three pin spacings of empty space above or below its left/right pins. |
18
+ | [`checkSchematicComponentMissingReferenceDesignatorText`](./lib/check-schematic-component-missing-reference-designator-text.ts) | Returns a `schematic_component_styling_warning` with `styling_issue_type: "missing_reference_designator_text"` when a schematic component has no attached text matching its reference designator or display-name override. |
18
19
  | [`checkSchematicComponentPortsOutsideBody`](./lib/check-schematic-component-ports-outside-body.ts) | Returns a `schematic_component_styling_warning` with `styling_issue_type: "ports_outside_body"` when pins fall beyond the body edge they enter, with an actionable minimum `schHeight` or `schWidth`. |
19
20
  | [`checkDifferentNetViaSpacing`](./lib/check-different-net-via-spacing.ts) | Returns `pcb_via_clearance_error` if vias on different nets are too close together. |
20
21
  | [`checkEachPcbPortConnectedToPcbTraces`](./lib/check-each-pcb-port-connected-to-pcb-trace.ts) | Returns `pcb_trace_error` if any `source_port` is not connected to its corresponding PCB traces. |
@@ -39,7 +40,7 @@ and output an array of arrays for any issues found.
39
40
  | [`runAllPlacementChecks`](./lib/run-all-checks.ts) | Runs placement checks (`checkCopperToBoardEdgeClearance`, `checkPcbComponentsOutOfBoard`, `checkPcbCopperOverKeepout`, `checkPcbComponentOverlap`, `checkPadPadClearance`, `checkCourtyardOverlap`, `checkConnectorAccessibleOrientation`, and `checkTestPointAccessibility`). |
40
41
  | [`runAllNetlistChecks`](./lib/run-all-checks.ts) | Runs netlist connectivity checks (currently `checkPinMustBeConnected`). |
41
42
  | [`runAllPinSpecificationChecks`](./lib/run-all-checks.ts) | Runs pin specification checks (e.g. `checkAllPinsInComponentAreUnderspecified`, `checkNoPowerPinDefined`, and `checkNoGroundPinDefined`). |
42
- | [`runAllSchematicChecks`](./lib/run-all-checks.ts) | Runs schematic-layout checks (currently `checkSchematicComponentExcessiveVerticalPadding`). |
43
+ | [`runAllSchematicChecks`](./lib/run-all-checks.ts) | Runs schematic-layout checks (`checkSchematicComponentExcessiveVerticalPadding`, `checkSchematicComponentMissingReferenceDesignatorText`, and `checkSchematicComponentPortsOutsideBody`). |
43
44
  | [`runAllRoutingChecks`](./lib/run-all-checks.ts) | Runs all routing checks currently enabled (`checkEachPcbPortConnectedToPcbTraces`, `checkSourceTracesHavePcbTraces`, `checkEachPcbTraceNonOverlapping`, `checkPadTraceClearance`, `checkViaTraceClearance`, same/different net via spacing, and `checkPcbTracesOutOfBoard`). Trace-obstacle pairs are classified before aggregation, so each pair produces one overlap or clearance diagnostic, never both. |
44
45
  | [`runAllChecks`](./lib/run-all-checks.ts) | Runs placement, schematic, netlist, pin specification, and routing checks and returns a combined list of issues. |
45
46
 
package/dist/index.d.ts CHANGED
@@ -168,6 +168,12 @@ declare function checkNoGroundPinDefined(circuitJson: AnyCircuitElement[]): Sour
168
168
  */
169
169
  declare function checkSchematicComponentExcessiveVerticalPadding(circuitJson: AnyCircuitElement[]): SchematicComponentStylingWarning[];
170
170
 
171
+ /**
172
+ * Warns when a schematic component does not have attached text displaying its
173
+ * reference designator (or the component's display-name override).
174
+ */
175
+ declare function checkSchematicComponentMissingReferenceDesignatorText(circuitJson: AnyCircuitElement[]): SchematicComponentStylingWarning[];
176
+
171
177
  /**
172
178
  * Warns when a box-style component's pins are positioned beyond the body edge
173
179
  * they enter. Left/right pins are checked against the body's vertical span,
@@ -207,4 +213,4 @@ declare function checkConnectorAccessibleOrientation(circuitJson: AnyCircuitElem
207
213
  */
208
214
  declare function checkTestPointAccessibility(circuitJson: AnyCircuitElement[]): PcbPlacementError[];
209
215
 
210
- export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkCopperToBoardEdgeClearance, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverCutout, checkPcbComponentOverlap, checkPcbComponentsMissingCourtyard, checkPcbComponentsOutOfBoard, checkPcbCopperOverKeepout, checkPcbTraceLengths, checkPcbTraceViaCounts, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSchematicComponentExcessiveVerticalPadding, checkSchematicComponentPortsOutsideBody, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTestPointAccessibility, checkTracesAreContiguous, checkViaPadClearance, checkViaTraceClearance, checkViasInPads, checkViasOffBoard, dedupePcbDrcErrors, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks, runAllSchematicChecks };
216
+ export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkCopperToBoardEdgeClearance, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverCutout, checkPcbComponentOverlap, checkPcbComponentsMissingCourtyard, checkPcbComponentsOutOfBoard, checkPcbCopperOverKeepout, checkPcbTraceLengths, checkPcbTraceViaCounts, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSchematicComponentExcessiveVerticalPadding, checkSchematicComponentMissingReferenceDesignatorText, checkSchematicComponentPortsOutsideBody, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTestPointAccessibility, checkTracesAreContiguous, checkViaPadClearance, checkViaTraceClearance, checkViasInPads, checkViasOffBoard, dedupePcbDrcErrors, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks, runAllSchematicChecks };
package/dist/index.js CHANGED
@@ -3383,6 +3383,19 @@ var getPcbTraceLength = (pcbTrace) => {
3383
3383
  }
3384
3384
  return traceLength;
3385
3385
  };
3386
+ var getReferencedPcbPortIds = (pcbTrace) => {
3387
+ const pcbPortIds = /* @__PURE__ */ new Set();
3388
+ for (const routePoint of pcbTrace.route) {
3389
+ if (routePoint.route_type !== "wire") continue;
3390
+ if (routePoint.start_pcb_port_id) {
3391
+ pcbPortIds.add(routePoint.start_pcb_port_id);
3392
+ }
3393
+ if (routePoint.end_pcb_port_id) {
3394
+ pcbPortIds.add(routePoint.end_pcb_port_id);
3395
+ }
3396
+ }
3397
+ return pcbPortIds;
3398
+ };
3386
3399
  var checkPcbTraceLengths = (circuitJson) => {
3387
3400
  const sourceTraces = circuitJson.filter(
3388
3401
  (element) => element.type === "source_trace"
@@ -3390,12 +3403,53 @@ var checkPcbTraceLengths = (circuitJson) => {
3390
3403
  const pcbTraces = circuitJson.filter(
3391
3404
  (element) => element.type === "pcb_trace"
3392
3405
  );
3406
+ const pcbPorts = circuitJson.filter(
3407
+ (element) => element.type === "pcb_port"
3408
+ );
3393
3409
  const sourceTracesById = new Map(
3394
3410
  sourceTraces.map((sourceTrace) => [
3395
3411
  sourceTrace.source_trace_id,
3396
3412
  sourceTrace
3397
3413
  ])
3398
3414
  );
3415
+ const pcbPortIdsBySourcePortId = /* @__PURE__ */ new Map();
3416
+ for (const pcbPort of pcbPorts) {
3417
+ if (!pcbPort.source_port_id) continue;
3418
+ const pcbPortIds = pcbPortIdsBySourcePortId.get(pcbPort.source_port_id) ?? /* @__PURE__ */ new Set();
3419
+ pcbPortIds.add(pcbPort.pcb_port_id);
3420
+ pcbPortIdsBySourcePortId.set(pcbPort.source_port_id, pcbPortIds);
3421
+ }
3422
+ const pcbTracesBySourceTraceId = /* @__PURE__ */ new Map();
3423
+ for (const pcbTrace of pcbTraces) {
3424
+ if (!pcbTrace.source_trace_id) continue;
3425
+ const matchingPcbTraces = pcbTracesBySourceTraceId.get(pcbTrace.source_trace_id) ?? [];
3426
+ matchingPcbTraces.push(pcbTrace);
3427
+ pcbTracesBySourceTraceId.set(pcbTrace.source_trace_id, matchingPcbTraces);
3428
+ }
3429
+ const exactEndpointPcbTraceIdsBySourceTraceId = /* @__PURE__ */ new Map();
3430
+ for (const sourceTrace of sourceTraces) {
3431
+ if (sourceTrace.connected_source_port_ids.length !== 2) continue;
3432
+ const endpointPcbPortIds = sourceTrace.connected_source_port_ids.map(
3433
+ (sourcePortId) => pcbPortIdsBySourcePortId.get(sourcePortId)
3434
+ );
3435
+ if (endpointPcbPortIds.some((pcbPortIds) => !pcbPortIds?.size)) continue;
3436
+ const exactEndpointPcbTraceIds = new Set(
3437
+ (pcbTracesBySourceTraceId.get(sourceTrace.source_trace_id) ?? []).filter((pcbTrace) => {
3438
+ const referencedPcbPortIds = getReferencedPcbPortIds(pcbTrace);
3439
+ return endpointPcbPortIds.every(
3440
+ (pcbPortIds) => [...pcbPortIds].some(
3441
+ (pcbPortId) => referencedPcbPortIds.has(pcbPortId)
3442
+ )
3443
+ );
3444
+ }).map((pcbTrace) => pcbTrace.pcb_trace_id)
3445
+ );
3446
+ if (exactEndpointPcbTraceIds.size > 0) {
3447
+ exactEndpointPcbTraceIdsBySourceTraceId.set(
3448
+ sourceTrace.source_trace_id,
3449
+ exactEndpointPcbTraceIds
3450
+ );
3451
+ }
3452
+ }
3399
3453
  const warnings = [];
3400
3454
  for (const pcbTrace of pcbTraces) {
3401
3455
  if (!pcbTrace.source_trace_id) continue;
@@ -3403,6 +3457,10 @@ var checkPcbTraceLengths = (circuitJson) => {
3403
3457
  if (!sourceTrace) continue;
3404
3458
  const maximumTraceLength = sourceTrace.max_length;
3405
3459
  if (typeof maximumTraceLength !== "number") continue;
3460
+ const exactEndpointPcbTraceIds = exactEndpointPcbTraceIdsBySourceTraceId.get(sourceTrace.source_trace_id);
3461
+ if (exactEndpointPcbTraceIds && !exactEndpointPcbTraceIds.has(pcbTrace.pcb_trace_id)) {
3462
+ continue;
3463
+ }
3406
3464
  const actualTraceLength = getPcbTraceLength(pcbTrace);
3407
3465
  if (actualTraceLength <= maximumTraceLength) continue;
3408
3466
  warnings.push({
@@ -4062,6 +4120,85 @@ function checkSchematicComponentExcessiveVerticalPadding(circuitJson) {
4062
4120
  return warnings;
4063
4121
  }
4064
4122
 
4123
+ // lib/check-schematic-component-missing-reference-designator-text.ts
4124
+ var isFallbackReferenceDesignator = (name) => /^unnamed_[a-z0-9_-]+\d+$/i.test(name);
4125
+ var isTextWithinComponentBounds = (schematicText, schematicComponent) => {
4126
+ const { center, size } = schematicComponent;
4127
+ const tolerance = 1e-9;
4128
+ return schematicText.position.x >= center.x - size.width / 2 - tolerance && schematicText.position.x <= center.x + size.width / 2 + tolerance && schematicText.position.y >= center.y - size.height / 2 - tolerance && schematicText.position.y <= center.y + size.height / 2 + tolerance;
4129
+ };
4130
+ function checkSchematicComponentMissingReferenceDesignatorText(circuitJson) {
4131
+ const schematicComponents = circuitJson.filter(
4132
+ (element) => element.type === "schematic_component"
4133
+ );
4134
+ const sourceComponents = circuitJson.filter(
4135
+ (element) => element.type === "source_component"
4136
+ );
4137
+ const schematicTexts = circuitJson.filter(
4138
+ (element) => element.type === "schematic_text"
4139
+ );
4140
+ const sourceComponentById = new Map(
4141
+ sourceComponents.map((component) => [
4142
+ component.source_component_id,
4143
+ component
4144
+ ])
4145
+ );
4146
+ const textBySchematicComponentId = /* @__PURE__ */ new Map();
4147
+ const customSymbolTexts = [];
4148
+ for (const schematicText of schematicTexts) {
4149
+ if (!schematicText.schematic_component_id) {
4150
+ if (schematicText.schematic_symbol_id) {
4151
+ customSymbolTexts.push(schematicText);
4152
+ }
4153
+ continue;
4154
+ }
4155
+ const componentTexts = textBySchematicComponentId.get(schematicText.schematic_component_id) ?? /* @__PURE__ */ new Set();
4156
+ componentTexts.add(schematicText.text.trim());
4157
+ textBySchematicComponentId.set(
4158
+ schematicText.schematic_component_id,
4159
+ componentTexts
4160
+ );
4161
+ }
4162
+ const warnings = [];
4163
+ for (const schematicComponent of schematicComponents) {
4164
+ if (!schematicComponent.source_component_id) continue;
4165
+ const sourceComponent = sourceComponentById.get(
4166
+ schematicComponent.source_component_id
4167
+ );
4168
+ if (!sourceComponent) continue;
4169
+ const referenceDesignators = new Set(
4170
+ [sourceComponent.name, sourceComponent.display_name].map((name) => name?.trim()).filter((name) => Boolean(name))
4171
+ );
4172
+ const nonFallbackReferenceDesignator = [...referenceDesignators].find(
4173
+ (referenceDesignator) => !isFallbackReferenceDesignator(referenceDesignator)
4174
+ );
4175
+ const componentTexts = textBySchematicComponentId.get(
4176
+ schematicComponent.schematic_component_id
4177
+ );
4178
+ const hasReferenceDesignatorText = [...referenceDesignators].some(
4179
+ (referenceDesignator) => componentTexts?.has(referenceDesignator)
4180
+ ) || customSymbolTexts.some(
4181
+ (schematicText) => referenceDesignators.has(schematicText.text.trim()) && isTextWithinComponentBounds(schematicText, schematicComponent)
4182
+ );
4183
+ if (nonFallbackReferenceDesignator && hasReferenceDesignatorText) {
4184
+ continue;
4185
+ }
4186
+ const readableComponentName = nonFallbackReferenceDesignator ?? "Schematic component";
4187
+ warnings.push({
4188
+ type: "schematic_component_styling_warning",
4189
+ schematic_component_styling_warning_id: `schematic_component_styling_warning_${schematicComponent.schematic_component_id}_missing_reference_designator_text`,
4190
+ warning_type: "schematic_component_styling_warning",
4191
+ message: `${readableComponentName} is missing schematic reference designator text. For a custom symbol, add name="{REFDES}" inside the symbol.`,
4192
+ schematic_component_id: schematicComponent.schematic_component_id,
4193
+ styling_issue_type: "missing_reference_designator_text",
4194
+ source_component_id: schematicComponent.source_component_id,
4195
+ schematic_sheet_id: schematicComponent.schematic_sheet_id,
4196
+ subcircuit_id: schematicComponent.subcircuit_id
4197
+ });
4198
+ }
4199
+ return warnings;
4200
+ }
4201
+
4065
4202
  // lib/check-schematic-component-ports-outside-body.ts
4066
4203
  var FLOATING_POINT_TOLERANCE2 = 1e-9;
4067
4204
  var getPortLabel = (port) => port.display_pin_label ?? `pin ${port.pin_number}`;
@@ -4451,6 +4588,7 @@ async function runAllNetlistChecks(circuitJson) {
4451
4588
  async function runAllSchematicChecks(circuitJson) {
4452
4589
  return [
4453
4590
  ...checkSchematicComponentExcessiveVerticalPadding(circuitJson),
4591
+ ...checkSchematicComponentMissingReferenceDesignatorText(circuitJson),
4454
4592
  ...checkSchematicComponentPortsOutsideBody(circuitJson)
4455
4593
  ];
4456
4594
  }
@@ -4509,6 +4647,7 @@ export {
4509
4647
  checkPinMustBeConnected,
4510
4648
  checkSameNetViaSpacing,
4511
4649
  checkSchematicComponentExcessiveVerticalPadding,
4650
+ checkSchematicComponentMissingReferenceDesignatorText,
4512
4651
  checkSchematicComponentPortsOutsideBody,
4513
4652
  checkSourceTracesHavePcbTraces,
4514
4653
  checkSourceTracesMatchPcbTraceThickness,