@tscircuit/checks 0.0.173 → 0.0.175

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
+ | [`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`. |
18
19
  | [`checkDifferentNetViaSpacing`](./lib/check-different-net-via-spacing.ts) | Returns `pcb_via_clearance_error` if vias on different nets are too close together. |
19
20
  | [`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. |
20
21
  | [`checkEachPcbTraceNonOverlapping`](./lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts) | Returns `pcb_trace_error` when `pcb_trace` segments physically overlap incompatible geometry on the same layer. Pad/via near-misses are reported by the typed clearance checks instead. |
package/dist/index.d.ts CHANGED
@@ -168,6 +168,13 @@ declare function checkNoGroundPinDefined(circuitJson: AnyCircuitElement[]): Sour
168
168
  */
169
169
  declare function checkSchematicComponentExcessiveVerticalPadding(circuitJson: AnyCircuitElement[]): SchematicComponentStylingWarning[];
170
170
 
171
+ /**
172
+ * Warns when a box-style component's pins are positioned beyond the body edge
173
+ * they enter. Left/right pins are checked against the body's vertical span,
174
+ * while top/bottom pins are checked against its horizontal span.
175
+ */
176
+ declare function checkSchematicComponentPortsOutsideBody(circuitJson: AnyCircuitElement[]): SchematicComponentStylingWarning[];
177
+
171
178
  declare function runAllPlacementChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPlacementError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbFootprintOverlapError | circuit_json.PcbComponentMissingCourtyardWarning | circuit_json.PcbPadPadClearanceError | circuit_json.PcbConnectorNotInAccessibleOrientationWarning | circuit_json.PcbCourtyardOverlapError)[]>;
172
179
  declare function runAllNetlistChecks(circuitJson: AnyCircuitElement[]): Promise<{
173
180
  type: "source_pin_must_be_connected_error";
@@ -200,4 +207,4 @@ declare function checkConnectorAccessibleOrientation(circuitJson: AnyCircuitElem
200
207
  */
201
208
  declare function checkTestPointAccessibility(circuitJson: AnyCircuitElement[]): PcbPlacementError[];
202
209
 
203
- export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkCopperToBoardEdgeClearance, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverCutout, checkPcbComponentOverlap, checkPcbComponentsMissingCourtyard, checkPcbComponentsOutOfBoard, checkPcbCopperOverKeepout, checkPcbTraceLengths, checkPcbTraceViaCounts, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSchematicComponentExcessiveVerticalPadding, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTestPointAccessibility, checkTracesAreContiguous, checkViaPadClearance, checkViaTraceClearance, checkViasInPads, checkViasOffBoard, dedupePcbDrcErrors, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks, runAllSchematicChecks };
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 };
package/dist/index.js CHANGED
@@ -3960,6 +3960,106 @@ function checkSchematicComponentExcessiveVerticalPadding(circuitJson) {
3960
3960
  return warnings;
3961
3961
  }
3962
3962
 
3963
+ // lib/check-schematic-component-ports-outside-body.ts
3964
+ var FLOATING_POINT_TOLERANCE2 = 1e-9;
3965
+ var getPortLabel = (port) => port.display_pin_label ?? `pin ${port.pin_number}`;
3966
+ function checkSchematicComponentPortsOutsideBody(circuitJson) {
3967
+ const schematicComponents = circuitJson.filter(
3968
+ (element) => element.type === "schematic_component"
3969
+ );
3970
+ const schematicPorts = circuitJson.filter(
3971
+ (element) => element.type === "schematic_port"
3972
+ );
3973
+ const sourceComponents = circuitJson.filter(
3974
+ (element) => element.type === "source_component"
3975
+ );
3976
+ const sourceComponentById = new Map(
3977
+ sourceComponents.map((component) => [
3978
+ component.source_component_id,
3979
+ component
3980
+ ])
3981
+ );
3982
+ const portsByComponentId = /* @__PURE__ */ new Map();
3983
+ for (const port of schematicPorts) {
3984
+ if (!port.schematic_component_id) continue;
3985
+ const componentPorts = portsByComponentId.get(port.schematic_component_id) ?? [];
3986
+ componentPorts.push(port);
3987
+ portsByComponentId.set(port.schematic_component_id, componentPorts);
3988
+ }
3989
+ const warnings = [];
3990
+ for (const component of schematicComponents) {
3991
+ if (component.is_box_with_pins === false || component.size.width <= 0 || component.size.height <= 0) {
3992
+ continue;
3993
+ }
3994
+ const componentLeftX = component.center.x - component.size.width / 2;
3995
+ const componentRightX = component.center.x + component.size.width / 2;
3996
+ const componentBottomY = component.center.y - component.size.height / 2;
3997
+ const componentTopY = component.center.y + component.size.height / 2;
3998
+ const componentPorts = portsByComponentId.get(component.schematic_component_id) ?? [];
3999
+ const portsOutsideBody = componentPorts.filter((port) => {
4000
+ if (port.side_of_component === "left" || port.side_of_component === "right") {
4001
+ return port.center.y < componentBottomY - FLOATING_POINT_TOLERANCE2 || port.center.y > componentTopY + FLOATING_POINT_TOLERANCE2;
4002
+ }
4003
+ if (port.side_of_component === "top" || port.side_of_component === "bottom") {
4004
+ return port.center.x < componentLeftX - FLOATING_POINT_TOLERANCE2 || port.center.x > componentRightX + FLOATING_POINT_TOLERANCE2;
4005
+ }
4006
+ return false;
4007
+ }).sort((portA, portB) => {
4008
+ const portAIsVertical = portA.side_of_component === "left" || portA.side_of_component === "right";
4009
+ const portBIsVertical = portB.side_of_component === "left" || portB.side_of_component === "right";
4010
+ if (portAIsVertical && portBIsVertical) {
4011
+ return portB.center.y - portA.center.y;
4012
+ }
4013
+ if (!portAIsVertical && !portBIsVertical) {
4014
+ return portA.center.x - portB.center.x;
4015
+ }
4016
+ return portAIsVertical ? -1 : 1;
4017
+ });
4018
+ if (portsOutsideBody.length === 0) continue;
4019
+ const requiredHeight = Math.max(
4020
+ component.size.height,
4021
+ ...portsOutsideBody.filter(
4022
+ (port) => port.side_of_component === "left" || port.side_of_component === "right"
4023
+ ).map((port) => 2 * Math.abs(port.center.y - component.center.y))
4024
+ );
4025
+ const requiredWidth = Math.max(
4026
+ component.size.width,
4027
+ ...portsOutsideBody.filter(
4028
+ (port) => port.side_of_component === "top" || port.side_of_component === "bottom"
4029
+ ).map((port) => 2 * Math.abs(port.center.x - component.center.x))
4030
+ );
4031
+ const suggestedDimensionChanges = [];
4032
+ if (requiredHeight > component.size.height + FLOATING_POINT_TOLERANCE2) {
4033
+ suggestedDimensionChanges.push(
4034
+ `increase schHeight to at least ${requiredHeight.toFixed(2)}mm`
4035
+ );
4036
+ }
4037
+ if (requiredWidth > component.size.width + FLOATING_POINT_TOLERANCE2) {
4038
+ suggestedDimensionChanges.push(
4039
+ `increase schWidth to at least ${requiredWidth.toFixed(2)}mm`
4040
+ );
4041
+ }
4042
+ const sourceComponent = component.source_component_id ? sourceComponentById.get(component.source_component_id) : void 0;
4043
+ const componentName = sourceComponent?.name ?? component.schematic_component_id;
4044
+ const portLabels = portsOutsideBody.map(getPortLabel).join(", ");
4045
+ warnings.push({
4046
+ type: "schematic_component_styling_warning",
4047
+ schematic_component_styling_warning_id: `schematic_component_styling_warning_${component.schematic_component_id}_ports_outside_body`,
4048
+ warning_type: "schematic_component_styling_warning",
4049
+ message: `${componentName} has schematic pins outside its body (${portLabels}); ${suggestedDimensionChanges.join(" and ")}`,
4050
+ schematic_component_id: component.schematic_component_id,
4051
+ styling_issue_type: "ports_outside_body",
4052
+ schematic_port_ids: portsOutsideBody.map(
4053
+ (port) => port.schematic_port_id
4054
+ ),
4055
+ source_component_id: component.source_component_id,
4056
+ schematic_sheet_id: component.schematic_sheet_id,
4057
+ subcircuit_id: component.subcircuit_id
4058
+ });
4059
+ }
4060
+ return warnings;
4061
+ }
4062
+
3963
4063
  // lib/check-connector-accessible-orientation.ts
3964
4064
  import { getBoardBounds } from "@tscircuit/circuit-json-util";
3965
4065
  function getFacingDirectionFromInsertionDirection(component) {
@@ -4247,7 +4347,10 @@ async function runAllNetlistChecks(circuitJson) {
4247
4347
  return [...checkPinMustBeConnected(circuitJson)];
4248
4348
  }
4249
4349
  async function runAllSchematicChecks(circuitJson) {
4250
- return checkSchematicComponentExcessiveVerticalPadding(circuitJson);
4350
+ return [
4351
+ ...checkSchematicComponentExcessiveVerticalPadding(circuitJson),
4352
+ ...checkSchematicComponentPortsOutsideBody(circuitJson)
4353
+ ];
4251
4354
  }
4252
4355
  async function runAllPinSpecificationChecks(circuitJson) {
4253
4356
  return [
@@ -4304,6 +4407,7 @@ export {
4304
4407
  checkPinMustBeConnected,
4305
4408
  checkSameNetViaSpacing,
4306
4409
  checkSchematicComponentExcessiveVerticalPadding,
4410
+ checkSchematicComponentPortsOutsideBody,
4307
4411
  checkSourceTracesHavePcbTraces,
4308
4412
  checkSourceTracesMatchPcbTraceThickness,
4309
4413
  checkTestPointAccessibility,