circuit-json-to-tscircuit 0.0.96 → 0.0.98

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 (26) hide show
  1. package/dist/{chunk-ULPDKPX5.js → chunk-3EOKTYYU.js} +129 -17
  2. package/dist/cli/main.js +2 -2
  3. package/dist/lib/index.js +1 -1
  4. package/lib/board-conversion-context.ts +1 -1
  5. package/lib/board-conversion-types.ts +1 -1
  6. package/lib/board-converter/create-component-preserving-board-conversion-context.ts +5 -15
  7. package/lib/board-converter/get-internally-connected-source-port-ids.ts +29 -0
  8. package/lib/board-converter/get-pcb-port-ids-with-safe-original-hints.ts +82 -0
  9. package/lib/board-converter/get-pin-labels.ts +14 -1
  10. package/lib/board-converter/get-unambiguous-source-port-aliases.ts +35 -0
  11. package/lib/board-converter/merge-overlapping-source-port-groups.ts +22 -0
  12. package/lib/generate-footprint-tsx/convert-smt-pads.ts +3 -2
  13. package/lib/generate-footprint-tsx/get-imported-port-hints.ts +1 -6
  14. package/package.json +1 -1
  15. package/tests/__snapshots__/board-polygon-pad-placement-pcb.snap.svg +8 -0
  16. package/tests/__snapshots__/tmds62levm-polygon-pad-placement-comparison.snap.svg +8 -0
  17. package/tests/board-ambiguous-pad-aliases.test.ts +216 -0
  18. package/tests/board-declared-internal-pin-aliases.test.ts +154 -0
  19. package/tests/board-polygon-pad-placement.test.ts +172 -0
  20. package/tests/board-sk-am62-u29-pin-aliases.test.ts +65 -0
  21. package/tests/board-transitive-internal-pin-aliases.test.ts +128 -0
  22. package/tests/fixtures/sk-am62-u29-pin-aliases.circuit.json +97 -0
  23. package/tests/fixtures/ti-evms/README.md +7 -0
  24. package/tests/fixtures/ti-evms/tmds62levm-r348-polygon-pads.circuit.json +168 -0
  25. package/tests/merge-overlapping-source-port-groups.test.ts +60 -0
  26. package/tests/tmds62levm-polygon-pad-placement.test.ts +70 -0
@@ -168,7 +168,7 @@ var createBoardConversionContext = ({
168
168
  }
169
169
  return {
170
170
  pcbChipName,
171
- pcbPortIdsWithUnambiguousComponentSelectors: /* @__PURE__ */ new Set(),
171
+ pcbPortIdsWithSafeOriginalHints: /* @__PURE__ */ new Set(),
172
172
  portHintByPcbPortId,
173
173
  runtimeNetNameBySourceNetId,
174
174
  pcbPortSelectorsBySourcePortId,
@@ -218,6 +218,59 @@ var getRuntimeNetNamesBySourcePortId = ({
218
218
  return result;
219
219
  };
220
220
 
221
+ // lib/board-converter/get-pcb-port-ids-with-safe-original-hints.ts
222
+ function getPcbPortIdsWithSafeOriginalHints({
223
+ circuitJson,
224
+ pcbComponentRuntimeNameByPcbComponentId
225
+ }) {
226
+ const sourcePortById = /* @__PURE__ */ new Map();
227
+ const sourcePortsByComponentId = /* @__PURE__ */ new Map();
228
+ const originalHintSetsByPcbPortId = /* @__PURE__ */ new Map();
229
+ for (const element of circuitJson) {
230
+ if (element.type !== "source_port") continue;
231
+ sourcePortById.set(element.source_port_id, element);
232
+ if (!element.source_component_id) continue;
233
+ const componentPorts = sourcePortsByComponentId.get(element.source_component_id) ?? [];
234
+ componentPorts.push(element);
235
+ sourcePortsByComponentId.set(element.source_component_id, componentPorts);
236
+ }
237
+ for (const element of circuitJson) {
238
+ if (element.type !== "pcb_plated_hole" && element.type !== "pcb_smtpad" || !element.pcb_port_id || !element.port_hints) {
239
+ continue;
240
+ }
241
+ const originalHintSets = originalHintSetsByPcbPortId.get(element.pcb_port_id) ?? [];
242
+ originalHintSets.push(element.port_hints);
243
+ originalHintSetsByPcbPortId.set(element.pcb_port_id, originalHintSets);
244
+ }
245
+ const safePcbPortIds = /* @__PURE__ */ new Set();
246
+ for (const element of circuitJson) {
247
+ if (element.type !== "pcb_port" || !element.pcb_component_id || !pcbComponentRuntimeNameByPcbComponentId.has(element.pcb_component_id)) {
248
+ continue;
249
+ }
250
+ const sourcePort = sourcePortById.get(element.source_port_id);
251
+ const originalHintSets = originalHintSetsByPcbPortId.get(
252
+ element.pcb_port_id
253
+ );
254
+ if (!sourcePort?.source_component_id || !originalHintSets) continue;
255
+ const aliasesOnOtherPorts = /* @__PURE__ */ new Set();
256
+ for (const siblingPort of sourcePortsByComponentId.get(
257
+ sourcePort.source_component_id
258
+ ) ?? []) {
259
+ if (siblingPort.source_port_id === sourcePort.source_port_id) continue;
260
+ aliasesOnOtherPorts.add(siblingPort.name);
261
+ for (const portHint of siblingPort.port_hints ?? []) {
262
+ aliasesOnOtherPorts.add(portHint);
263
+ }
264
+ }
265
+ if (originalHintSets.every(
266
+ (originalHints) => originalHints.some((portHint) => /^(?:pin)?\d+$/u.test(portHint)) || originalHints.every((portHint) => !aliasesOnOtherPorts.has(portHint))
267
+ )) {
268
+ safePcbPortIds.add(element.pcb_port_id);
269
+ }
270
+ }
271
+ return safePcbPortIds;
272
+ }
273
+
221
274
  // lib/board-converter/create-component-preserving-board-conversion-context.ts
222
275
  function createComponentPreservingBoardConversionContext({
223
276
  circuitJson,
@@ -232,15 +285,6 @@ function createComponentPreservingBoardConversionContext({
232
285
  }
233
286
  }
234
287
  const pcbPortSelectorsBySourcePortId = /* @__PURE__ */ new Map();
235
- const pcbPortIdsWithUnambiguousComponentSelectors = new Set(
236
- circuitJson.flatMap((element) => {
237
- if (element.type !== "pcb_port") return [];
238
- const pcbComponent = element.pcb_component_id ? pcbComponentsById.get(element.pcb_component_id) : void 0;
239
- return pcbComponent && pcbComponentRuntimeNameByPcbComponentId.has(
240
- pcbComponent.pcb_component_id
241
- ) ? [element.pcb_port_id] : [];
242
- })
243
- );
244
288
  for (const element of circuitJson) {
245
289
  if (element.type !== "pcb_port") continue;
246
290
  const pcbComponent = element.pcb_component_id ? pcbComponentsById.get(element.pcb_component_id) : void 0;
@@ -272,7 +316,10 @@ function createComponentPreservingBoardConversionContext({
272
316
  }
273
317
  return {
274
318
  ...context,
275
- pcbPortIdsWithUnambiguousComponentSelectors,
319
+ pcbPortIdsWithSafeOriginalHints: getPcbPortIdsWithSafeOriginalHints({
320
+ circuitJson,
321
+ pcbComponentRuntimeNameByPcbComponentId
322
+ }),
276
323
  pcbPortSelectorsBySourcePortId,
277
324
  pcbPortSelectorsByRuntimeNetName
278
325
  };
@@ -3656,9 +3703,7 @@ var getImportedPortHints = (primitive, context) => {
3656
3703
  if (!primitive.pcb_port_id || !context) return primitive.port_hints;
3657
3704
  const importedHint = context.portHintByPcbPortId.get(primitive.pcb_port_id);
3658
3705
  if (!importedHint) return primitive.port_hints;
3659
- if (!context.pcbPortIdsWithUnambiguousComponentSelectors.has(
3660
- primitive.pcb_port_id
3661
- )) {
3706
+ if (!context.pcbPortIdsWithSafeOriginalHints.has(primitive.pcb_port_id)) {
3662
3707
  return [importedHint];
3663
3708
  }
3664
3709
  return [.../* @__PURE__ */ new Set([importedHint, ...primitive.port_hints ?? []])];
@@ -3927,10 +3972,10 @@ var convertSmtPads = (circuitJson, context) => {
3927
3972
  if (portHints !== void 0) {
3928
3973
  commonAttrs.push(`portHints={${JSON.stringify(portHints)}}`);
3929
3974
  }
3930
- if ("x" in smtPad && smtPad.x !== void 0) {
3975
+ if (smtPad.shape !== "polygon" && "x" in smtPad && smtPad.x !== void 0) {
3931
3976
  commonAttrs.push(`pcbX="${mmStr8(smtPad.x)}"`);
3932
3977
  }
3933
- if ("y" in smtPad && smtPad.y !== void 0) {
3978
+ if (smtPad.shape !== "polygon" && "y" in smtPad && smtPad.y !== void 0) {
3934
3979
  commonAttrs.push(`pcbY="${mmStr8(smtPad.y)}"`);
3935
3980
  }
3936
3981
  if (smtPad.layer !== void 0) {
@@ -4034,6 +4079,65 @@ var getPcbComponentRenderPlacement = ({
4034
4079
  };
4035
4080
  };
4036
4081
 
4082
+ // lib/board-converter/merge-overlapping-source-port-groups.ts
4083
+ function mergeOverlappingSourcePortGroups(sourcePortGroups) {
4084
+ const groupBySourcePortId = /* @__PURE__ */ new Map();
4085
+ for (const sourcePortIds of sourcePortGroups) {
4086
+ const mergedGroup = new Set(sourcePortIds);
4087
+ for (const sourcePortId of sourcePortIds) {
4088
+ for (const connectedSourcePortId of groupBySourcePortId.get(
4089
+ sourcePortId
4090
+ ) ?? []) {
4091
+ mergedGroup.add(connectedSourcePortId);
4092
+ }
4093
+ }
4094
+ for (const sourcePortId of mergedGroup) {
4095
+ groupBySourcePortId.set(sourcePortId, mergedGroup);
4096
+ }
4097
+ }
4098
+ return [...new Set(groupBySourcePortId.values())].map((group) => [...group]);
4099
+ }
4100
+
4101
+ // lib/board-converter/get-internally-connected-source-port-ids.ts
4102
+ function getInternallyConnectedSourcePortIds({
4103
+ circuitJson,
4104
+ sourceComponent
4105
+ }) {
4106
+ const internallyConnectedSourcePortIds = [];
4107
+ if ("internally_connected_source_port_ids" in sourceComponent) {
4108
+ internallyConnectedSourcePortIds.push(
4109
+ ...sourceComponent.internally_connected_source_port_ids ?? []
4110
+ );
4111
+ }
4112
+ for (const element of circuitJson) {
4113
+ if (element.type === "source_component_internal_connection" && element.source_component_id === sourceComponent.source_component_id) {
4114
+ internallyConnectedSourcePortIds.push(element.source_port_ids);
4115
+ }
4116
+ }
4117
+ return mergeOverlappingSourcePortGroups(internallyConnectedSourcePortIds);
4118
+ }
4119
+
4120
+ // lib/board-converter/get-unambiguous-source-port-aliases.ts
4121
+ function getUnambiguousSourcePortAliases({
4122
+ sourcePort,
4123
+ sourcePorts,
4124
+ internallyConnectedSourcePortIds = []
4125
+ }) {
4126
+ return (sourcePort.port_hints ?? []).filter((alias) => {
4127
+ if (alias === sourcePort.name) return true;
4128
+ for (const canonicalPort of sourcePorts) {
4129
+ if (canonicalPort.name !== alias || canonicalPort.source_port_id === sourcePort.source_port_id) {
4130
+ continue;
4131
+ }
4132
+ const isDeclaredInternalConnection = internallyConnectedSourcePortIds.some(
4133
+ (group) => group.includes(sourcePort.source_port_id) && group.includes(canonicalPort.source_port_id)
4134
+ );
4135
+ if (!isDeclaredInternalConnection) return false;
4136
+ }
4137
+ return true;
4138
+ });
4139
+ }
4140
+
4037
4141
  // lib/board-converter/get-pin-labels.ts
4038
4142
  var getCompoundPinNumber = (sourcePort) => {
4039
4143
  if (sourcePort.pin_number !== void 0) {
@@ -4071,9 +4175,17 @@ var getPinLabels = ({
4071
4175
  const importedPortHint = footprintConversionContext.portHintByPcbPortId.get(element.pcb_port_id);
4072
4176
  return importedPortHint ? [importedPortHint] : [];
4073
4177
  });
4178
+ const sourceComponent = sourceComponents.find(
4179
+ (component) => component.source_component_id === sourcePort.source_component_id
4180
+ );
4181
+ const internallyConnectedSourcePortIds = sourceComponent ? getInternallyConnectedSourcePortIds({ circuitJson, sourceComponent }) : void 0;
4074
4182
  const aliases = [
4075
4183
  sourcePort.name,
4076
- ...sourcePort.port_hints ?? [],
4184
+ ...getUnambiguousSourcePortAliases({
4185
+ sourcePort,
4186
+ sourcePorts,
4187
+ internallyConnectedSourcePortIds
4188
+ }),
4077
4189
  ...importedPortHints
4078
4190
  ].filter(
4079
4191
  (alias, aliasIndex, allAliases) => alias.length > 0 && allAliases.indexOf(alias) === aliasIndex
package/dist/cli/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  convertCircuitJsonToTscircuit
4
- } from "../chunk-ULPDKPX5.js";
4
+ } from "../chunk-3EOKTYYU.js";
5
5
 
6
6
  // cli/main.ts
7
7
  import { Command } from "commander";
@@ -16,7 +16,7 @@ var package_default = {
16
16
  "./cli": "./dist/cli/main.js"
17
17
  },
18
18
  type: "module",
19
- version: "0.0.95",
19
+ version: "0.0.97",
20
20
  repository: {
21
21
  type: "git",
22
22
  url: "https://github.com/tscircuit/circuit-json-to-tscircuit.git"
package/dist/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  convertCircuitJsonToTscircuit
3
- } from "../chunk-ULPDKPX5.js";
3
+ } from "../chunk-3EOKTYYU.js";
4
4
  export {
5
5
  convertCircuitJsonToTscircuit
6
6
  };
@@ -69,7 +69,7 @@ export const createBoardConversionContext = ({
69
69
 
70
70
  return {
71
71
  pcbChipName,
72
- pcbPortIdsWithUnambiguousComponentSelectors: new Set<PcbPortId>(),
72
+ pcbPortIdsWithSafeOriginalHints: new Set<PcbPortId>(),
73
73
  portHintByPcbPortId,
74
74
  runtimeNetNameBySourceNetId,
75
75
  pcbPortSelectorsBySourcePortId,
@@ -10,7 +10,7 @@ export type PcbPortSelector = string
10
10
 
11
11
  export interface BoardConversionContext {
12
12
  pcbChipName: string
13
- pcbPortIdsWithUnambiguousComponentSelectors: Set<PcbPortId>
13
+ pcbPortIdsWithSafeOriginalHints: Set<PcbPortId>
14
14
  portHintByPcbPortId: Map<PcbPortId, ImportedPortHint>
15
15
  runtimeNetNameBySourceNetId: Map<SourceNetId, RuntimeNetName>
16
16
  pcbPortSelectorsBySourcePortId: Map<SourcePortId, PcbPortSelector[]>
@@ -9,6 +9,7 @@ import type {
9
9
  SourcePortId,
10
10
  } from "../board-conversion-types"
11
11
  import type { PcbComponentRuntimeNameByPcbComponentId } from "./get-board-child-runtime-names"
12
+ import { getPcbPortIdsWithSafeOriginalHints } from "./get-pcb-port-ids-with-safe-original-hints"
12
13
 
13
14
  type PcbComponentId = PcbComponent["pcb_component_id"]
14
15
  export function createComponentPreservingBoardConversionContext({
@@ -32,20 +33,6 @@ export function createComponentPreservingBoardConversionContext({
32
33
  SourcePortId,
33
34
  PcbPortSelector[]
34
35
  >()
35
- const pcbPortIdsWithUnambiguousComponentSelectors = new Set(
36
- circuitJson.flatMap((element) => {
37
- if (element.type !== "pcb_port") return []
38
- const pcbComponent = element.pcb_component_id
39
- ? pcbComponentsById.get(element.pcb_component_id)
40
- : undefined
41
- return pcbComponent &&
42
- pcbComponentRuntimeNameByPcbComponentId.has(
43
- pcbComponent.pcb_component_id,
44
- )
45
- ? [element.pcb_port_id]
46
- : []
47
- }),
48
- )
49
36
  for (const element of circuitJson) {
50
37
  if (element.type !== "pcb_port") continue
51
38
  const pcbComponent = element.pcb_component_id
@@ -91,7 +78,10 @@ export function createComponentPreservingBoardConversionContext({
91
78
 
92
79
  return {
93
80
  ...context,
94
- pcbPortIdsWithUnambiguousComponentSelectors,
81
+ pcbPortIdsWithSafeOriginalHints: getPcbPortIdsWithSafeOriginalHints({
82
+ circuitJson,
83
+ pcbComponentRuntimeNameByPcbComponentId,
84
+ }),
95
85
  pcbPortSelectorsBySourcePortId,
96
86
  pcbPortSelectorsByRuntimeNetName,
97
87
  }
@@ -0,0 +1,29 @@
1
+ import type { AnyCircuitElement } from "circuit-json"
2
+ import type { SourcePortId } from "../board-conversion-types"
3
+ import { mergeOverlappingSourcePortGroups } from "./merge-overlapping-source-port-groups"
4
+
5
+ type SourceComponent = Extract<AnyCircuitElement, { type: "source_component" }>
6
+
7
+ export function getInternallyConnectedSourcePortIds({
8
+ circuitJson,
9
+ sourceComponent,
10
+ }: {
11
+ circuitJson: AnyCircuitElement[]
12
+ sourceComponent: SourceComponent
13
+ }): SourcePortId[][] {
14
+ const internallyConnectedSourcePortIds: SourcePortId[][] = []
15
+ if ("internally_connected_source_port_ids" in sourceComponent) {
16
+ internallyConnectedSourcePortIds.push(
17
+ ...(sourceComponent.internally_connected_source_port_ids ?? []),
18
+ )
19
+ }
20
+ for (const element of circuitJson) {
21
+ if (
22
+ element.type === "source_component_internal_connection" &&
23
+ element.source_component_id === sourceComponent.source_component_id
24
+ ) {
25
+ internallyConnectedSourcePortIds.push(element.source_port_ids)
26
+ }
27
+ }
28
+ return mergeOverlappingSourcePortGroups(internallyConnectedSourcePortIds)
29
+ }
@@ -0,0 +1,82 @@
1
+ import type { AnyCircuitElement } from "circuit-json"
2
+ import type { PcbPortId, SourcePortId } from "../board-conversion-types"
3
+ import type { PcbComponentRuntimeNameByPcbComponentId } from "./get-board-child-runtime-names"
4
+
5
+ type PortHint = string
6
+ type SourceComponentId = string
7
+ type SourcePort = Extract<AnyCircuitElement, { type: "source_port" }>
8
+
9
+ export function getPcbPortIdsWithSafeOriginalHints({
10
+ circuitJson,
11
+ pcbComponentRuntimeNameByPcbComponentId,
12
+ }: {
13
+ circuitJson: AnyCircuitElement[]
14
+ pcbComponentRuntimeNameByPcbComponentId: PcbComponentRuntimeNameByPcbComponentId
15
+ }): Set<PcbPortId> {
16
+ const sourcePortById = new Map<SourcePortId, SourcePort>()
17
+ const sourcePortsByComponentId = new Map<SourceComponentId, SourcePort[]>()
18
+ const originalHintSetsByPcbPortId = new Map<PcbPortId, PortHint[][]>()
19
+
20
+ for (const element of circuitJson) {
21
+ if (element.type !== "source_port") continue
22
+ sourcePortById.set(element.source_port_id, element)
23
+ if (!element.source_component_id) continue
24
+ const componentPorts =
25
+ sourcePortsByComponentId.get(element.source_component_id) ?? []
26
+ componentPorts.push(element)
27
+ sourcePortsByComponentId.set(element.source_component_id, componentPorts)
28
+ }
29
+
30
+ for (const element of circuitJson) {
31
+ if (
32
+ (element.type !== "pcb_plated_hole" && element.type !== "pcb_smtpad") ||
33
+ !element.pcb_port_id ||
34
+ !element.port_hints
35
+ ) {
36
+ continue
37
+ }
38
+ const originalHintSets =
39
+ originalHintSetsByPcbPortId.get(element.pcb_port_id) ?? []
40
+ originalHintSets.push(element.port_hints)
41
+ originalHintSetsByPcbPortId.set(element.pcb_port_id, originalHintSets)
42
+ }
43
+
44
+ const safePcbPortIds = new Set<PcbPortId>()
45
+ for (const element of circuitJson) {
46
+ if (
47
+ element.type !== "pcb_port" ||
48
+ !element.pcb_component_id ||
49
+ !pcbComponentRuntimeNameByPcbComponentId.has(element.pcb_component_id)
50
+ ) {
51
+ continue
52
+ }
53
+ const sourcePort = sourcePortById.get(element.source_port_id)
54
+ const originalHintSets = originalHintSetsByPcbPortId.get(
55
+ element.pcb_port_id,
56
+ )
57
+ if (!sourcePort?.source_component_id || !originalHintSets) continue
58
+
59
+ const aliasesOnOtherPorts = new Set<PortHint>()
60
+ for (const siblingPort of sourcePortsByComponentId.get(
61
+ sourcePort.source_component_id,
62
+ ) ?? []) {
63
+ if (siblingPort.source_port_id === sourcePort.source_port_id) continue
64
+ aliasesOnOtherPorts.add(siblingPort.name)
65
+ for (const portHint of siblingPort.port_hints ?? []) {
66
+ aliasesOnOtherPorts.add(portHint)
67
+ }
68
+ }
69
+ // A numbered hint only disambiguates the primitive carrying it.
70
+ if (
71
+ originalHintSets.every(
72
+ (originalHints) =>
73
+ originalHints.some((portHint) => /^(?:pin)?\d+$/u.test(portHint)) ||
74
+ originalHints.every((portHint) => !aliasesOnOtherPorts.has(portHint)),
75
+ )
76
+ ) {
77
+ safePcbPortIds.add(element.pcb_port_id)
78
+ }
79
+ }
80
+
81
+ return safePcbPortIds
82
+ }
@@ -1,5 +1,7 @@
1
1
  import type { AnyCircuitElement, PcbComponent } from "circuit-json"
2
2
  import type { BoardConversionContext as FootprintConversionContext } from "../board-conversion-context"
3
+ import { getInternallyConnectedSourcePortIds } from "./get-internally-connected-source-port-ids"
4
+ import { getUnambiguousSourcePortAliases } from "./get-unambiguous-source-port-aliases"
3
5
 
4
6
  type PinLabelKey = `pin${number}`
5
7
  type PinLabels = Partial<Record<PinLabelKey, string[]>>
@@ -71,9 +73,20 @@ export const getPinLabels = ({
71
73
  footprintConversionContext.portHintByPcbPortId.get(element.pcb_port_id)
72
74
  return importedPortHint ? [importedPortHint] : []
73
75
  })
76
+ const sourceComponent = sourceComponents.find(
77
+ (component) =>
78
+ component.source_component_id === sourcePort.source_component_id,
79
+ )
80
+ const internallyConnectedSourcePortIds = sourceComponent
81
+ ? getInternallyConnectedSourcePortIds({ circuitJson, sourceComponent })
82
+ : undefined
74
83
  const aliases = [
75
84
  sourcePort.name,
76
- ...(sourcePort.port_hints ?? []),
85
+ ...getUnambiguousSourcePortAliases({
86
+ sourcePort,
87
+ sourcePorts,
88
+ internallyConnectedSourcePortIds,
89
+ }),
77
90
  ...importedPortHints,
78
91
  ].filter(
79
92
  (alias, aliasIndex, allAliases) =>
@@ -0,0 +1,35 @@
1
+ import type { AnyCircuitElement } from "circuit-json"
2
+ import type { SourcePortId } from "../board-conversion-types"
3
+
4
+ type SourcePort = Extract<AnyCircuitElement, { type: "source_port" }>
5
+
6
+ export function getUnambiguousSourcePortAliases({
7
+ sourcePort,
8
+ sourcePorts,
9
+ internallyConnectedSourcePortIds = [],
10
+ }: {
11
+ sourcePort: SourcePort
12
+ sourcePorts: SourcePort[]
13
+ internallyConnectedSourcePortIds?: SourcePortId[][]
14
+ }): string[] {
15
+ return (sourcePort.port_hints ?? []).filter((alias) => {
16
+ if (alias === sourcePort.name) return true
17
+
18
+ for (const canonicalPort of sourcePorts) {
19
+ if (
20
+ canonicalPort.name !== alias ||
21
+ canonicalPort.source_port_id === sourcePort.source_port_id
22
+ ) {
23
+ continue
24
+ }
25
+ const isDeclaredInternalConnection =
26
+ internallyConnectedSourcePortIds.some(
27
+ (group) =>
28
+ group.includes(sourcePort.source_port_id) &&
29
+ group.includes(canonicalPort.source_port_id),
30
+ )
31
+ if (!isDeclaredInternalConnection) return false
32
+ }
33
+ return true
34
+ })
35
+ }
@@ -0,0 +1,22 @@
1
+ import type { SourcePortId } from "../board-conversion-types"
2
+
3
+ export function mergeOverlappingSourcePortGroups(
4
+ sourcePortGroups: readonly (readonly SourcePortId[])[],
5
+ ): SourcePortId[][] {
6
+ const groupBySourcePortId = new Map<SourcePortId, Set<SourcePortId>>()
7
+ for (const sourcePortIds of sourcePortGroups) {
8
+ const mergedGroup = new Set<SourcePortId>(sourcePortIds)
9
+ for (const sourcePortId of sourcePortIds) {
10
+ for (const connectedSourcePortId of groupBySourcePortId.get(
11
+ sourcePortId,
12
+ ) ?? []) {
13
+ mergedGroup.add(connectedSourcePortId)
14
+ }
15
+ }
16
+ // Later declarations must see the whole group through any of its members.
17
+ for (const sourcePortId of mergedGroup) {
18
+ groupBySourcePortId.set(sourcePortId, mergedGroup)
19
+ }
20
+ }
21
+ return [...new Set(groupBySourcePortId.values())].map((group) => [...group])
22
+ }
@@ -21,10 +21,11 @@ export const convertSmtPads: FootprintElementConverter = (
21
21
  if (portHints !== undefined) {
22
22
  commonAttrs.push(`portHints={${JSON.stringify(portHints)}}`)
23
23
  }
24
- if ("x" in smtPad && smtPad.x !== undefined) {
24
+ // Polygon vertices already carry their position in the footprint frame.
25
+ if (smtPad.shape !== "polygon" && "x" in smtPad && smtPad.x !== undefined) {
25
26
  commonAttrs.push(`pcbX="${mmStr(smtPad.x)}"`)
26
27
  }
27
- if ("y" in smtPad && smtPad.y !== undefined) {
28
+ if (smtPad.shape !== "polygon" && "y" in smtPad && smtPad.y !== undefined) {
28
29
  commonAttrs.push(`pcbY="${mmStr(smtPad.y)}"`)
29
30
  }
30
31
  if (smtPad.layer !== undefined) {
@@ -8,13 +8,8 @@ export const getImportedPortHints = (
8
8
  if (!primitive.pcb_port_id || !context) return primitive.port_hints
9
9
  const importedHint = context.portHintByPcbPortId.get(primitive.pcb_port_id)
10
10
  if (!importedHint) return primitive.port_hints
11
- if (
12
- !context.pcbPortIdsWithUnambiguousComponentSelectors.has(
13
- primitive.pcb_port_id,
14
- )
15
- ) {
11
+ if (!context.pcbPortIdsWithSafeOriginalHints.has(primitive.pcb_port_id)) {
16
12
  return [importedHint]
17
13
  }
18
-
19
14
  return [...new Set([importedHint, ...(primitive.port_hints ?? [])])]
20
15
  }
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "./cli": "./dist/cli/main.js"
7
7
  },
8
8
  "type": "module",
9
- "version": "0.0.96",
9
+ "version": "0.0.98",
10
10
  "repository": {
11
11
  "type": "git",
12
12
  "url": "https://github.com/tscircuit/circuit-json-to-tscircuit.git"