kicad-to-circuit-json 0.0.113 → 0.0.115

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 (2) hide show
  1. package/dist/index.js +177 -159
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -12,6 +12,122 @@ function upgradeKicad5FootprintToKicad6(content) {
12
12
  // lib/stages/pcb/CollectFootprintsStage/process-footprint.ts
13
13
  import { applyToPoint as applyToPoint4 } from "transformation-matrix";
14
14
 
15
+ // lib/stages/pcb/CollectFootprintsStage/footprint-properties.ts
16
+ function getFootprintProperties(footprint) {
17
+ const properties = footprint.properties || [];
18
+ return Array.isArray(properties) ? properties : [properties];
19
+ }
20
+ function getFootprintPropertyName(property) {
21
+ return property?.key;
22
+ }
23
+ function getFootprintPropertyValue(property) {
24
+ return property?.value;
25
+ }
26
+ function findFootprintProperty(footprint, propertyNames) {
27
+ const names = Array.isArray(propertyNames) ? propertyNames : [propertyNames];
28
+ return getFootprintProperties(footprint).find(
29
+ (property) => names.includes(getFootprintPropertyName(property) ?? "")
30
+ );
31
+ }
32
+ function findFootprintPropertyValue(footprint, propertyNames) {
33
+ const property = findFootprintProperty(footprint, propertyNames);
34
+ return getFootprintPropertyValue(property);
35
+ }
36
+ function getFootprintReference(footprint) {
37
+ const propertyValue = findFootprintPropertyValue(footprint, "Reference");
38
+ if (propertyValue) return propertyValue;
39
+ const textItems = footprint.fpTexts || [];
40
+ const textArray = Array.isArray(textItems) ? textItems : [textItems];
41
+ for (const text of textArray) {
42
+ if (text.type === "reference" && text.text) {
43
+ return text.text;
44
+ }
45
+ }
46
+ return void 0;
47
+ }
48
+ function parseSupplierPartNumbers(value) {
49
+ if (!value) return void 0;
50
+ const partNumbers = value.split(/[,;]/).map((partNumber) => partNumber.trim()).filter(Boolean);
51
+ return partNumbers.length > 0 ? partNumbers : void 0;
52
+ }
53
+
54
+ // lib/stages/pcb/CollectFootprintsStage/infer-component-type.ts
55
+ function inferComponentType(reference, footprint) {
56
+ if (!reference && !footprint) return "simple_chip";
57
+ const normalizedReference = reference?.trim();
58
+ const prefix = normalizedReference?.match(/^([A-Z]+)/)?.[1];
59
+ if (isFiducialReference(normalizedReference) || isFiducialFootprint(footprint)) {
60
+ return "simple_fiducial";
61
+ }
62
+ if (prefix === "TP" || isTestPointReference(normalizedReference) || isTestPointFootprint(footprint)) {
63
+ return "simple_test_point";
64
+ }
65
+ switch (prefix) {
66
+ case "R":
67
+ return "simple_resistor";
68
+ case "C":
69
+ return "simple_capacitor";
70
+ case "L":
71
+ return "simple_inductor";
72
+ case "D":
73
+ if (isLedFootprint(footprint)) return "simple_led";
74
+ return "simple_diode";
75
+ case "LED":
76
+ return "simple_led";
77
+ case "SW":
78
+ return "simple_switch";
79
+ case "Q":
80
+ return "simple_transistor";
81
+ case "U":
82
+ case "IC":
83
+ return "simple_chip";
84
+ case "J":
85
+ case "P":
86
+ return "simple_chip";
87
+ // Connectors treated as chips
88
+ default:
89
+ return "simple_chip";
90
+ }
91
+ }
92
+ function isFiducialReference(reference) {
93
+ return /^FID\d+/i.test(reference || "");
94
+ }
95
+ function isFiducialFootprint(footprint) {
96
+ return getFootprintMetadata(footprint).includes("fiducial");
97
+ }
98
+ function isLedFootprint(footprint) {
99
+ const metadata = getFootprintMetadata(footprint);
100
+ return metadata.includes("led") || metadata.includes("light emitting diode");
101
+ }
102
+ function isTestPointReference(reference) {
103
+ return /^TP\d+/i.test(reference || "");
104
+ }
105
+ function isTestPointFootprint(footprint) {
106
+ const metadata = getFootprintMetadata(footprint);
107
+ return metadata.includes("testpoint") || metadata.includes("test point");
108
+ }
109
+ function getFootprintMetadata(footprint) {
110
+ if (!footprint) return "";
111
+ return [
112
+ footprint.libraryLink,
113
+ footprint.descr?.value,
114
+ footprint.tags?.value,
115
+ findFootprintPropertyValue(footprint, "Footprint"),
116
+ findFootprintPropertyValue(footprint, "Description"),
117
+ findFootprintPropertyValue(footprint, "Value")
118
+ ].filter(Boolean).join(" ").toLowerCase();
119
+ }
120
+ function inferTransistorTypeFromFootprint(footprint, value) {
121
+ const lowerValue = (value || "").toLowerCase();
122
+ if (lowerValue.includes("pnp")) return "pnp";
123
+ if (lowerValue.includes("npn")) return "npn";
124
+ const libId = footprint.libraryId;
125
+ const lowerLibId = (libId || "").toLowerCase();
126
+ if (lowerLibId.includes("pnp")) return "pnp";
127
+ if (lowerLibId.includes("npn")) return "npn";
128
+ return "npn";
129
+ }
130
+
15
131
  // lib/stages/pcb/layer-mapping.ts
16
132
  var INNER_COPPER_LAYER_REGEX = /^In([1-9]\d*)\.Cu$/;
17
133
  function dedupeLayerRefs(layers) {
@@ -142,40 +258,6 @@ function mapTextLayer(kicadLayer) {
142
258
  return mapKicadLayerToVisibleLayer(kicadLayer);
143
259
  }
144
260
 
145
- // lib/stages/pcb/CollectFootprintsStage/process-pads.ts
146
- import { applyToPoint as applyToPoint2 } from "transformation-matrix";
147
-
148
- // lib/stages/pcb/pad-source-port-id.ts
149
- function getPadNetNum(pad) {
150
- const net = pad?._sxNet || pad?.net;
151
- if (!net) return null;
152
- if (typeof net === "number") return net;
153
- if (typeof net === "object") {
154
- return net._id ?? net.number ?? net.ordinal ?? null;
155
- }
156
- return null;
157
- }
158
- function getSourcePortIdForPad(params) {
159
- const { componentId, footprint, pad } = params;
160
- const padNumber = pad.number?.toString();
161
- if (!padNumber) return void 0;
162
- const baseSourcePortId = `${componentId}_port_${padNumber}`;
163
- if (!hasDuplicatePadNumberOnDifferentNets(footprint, padNumber)) {
164
- return baseSourcePortId;
165
- }
166
- return `${baseSourcePortId}_net_${getPadNetNum(pad) ?? "none"}`;
167
- }
168
- function hasDuplicatePadNumberOnDifferentNets(footprint, padNumber) {
169
- const pads = footprint.fpPads || [];
170
- const padArray = Array.isArray(pads) ? pads : [pads];
171
- const netKeys = /* @__PURE__ */ new Set();
172
- for (const pad of padArray) {
173
- if (pad.number?.toString() !== padNumber) continue;
174
- netKeys.add(String(getPadNetNum(pad) ?? "none"));
175
- }
176
- return netKeys.size > 1;
177
- }
178
-
179
261
  // lib/stages/pcb/CollectFootprintsStage/process-graphics.ts
180
262
  import { applyToPoint } from "transformation-matrix";
181
263
  function insertFootprintRoute(options) {
@@ -594,6 +676,40 @@ function createFootprintPoly(params) {
594
676
  });
595
677
  }
596
678
 
679
+ // lib/stages/pcb/CollectFootprintsStage/process-pads.ts
680
+ import { applyToPoint as applyToPoint2 } from "transformation-matrix";
681
+
682
+ // lib/stages/pcb/pad-source-port-id.ts
683
+ function getPadNetNum(pad) {
684
+ const net = pad?._sxNet || pad?.net;
685
+ if (!net) return null;
686
+ if (typeof net === "number") return net;
687
+ if (typeof net === "object") {
688
+ return net._id ?? net.number ?? net.ordinal ?? null;
689
+ }
690
+ return null;
691
+ }
692
+ function getSourcePortIdForPad(params) {
693
+ const { componentId, footprint, pad } = params;
694
+ const padNumber = pad.number?.toString();
695
+ if (!padNumber) return void 0;
696
+ const baseSourcePortId = `${componentId}_port_${padNumber}`;
697
+ if (!hasDuplicatePadNumberOnDifferentNets(footprint, padNumber)) {
698
+ return baseSourcePortId;
699
+ }
700
+ return `${baseSourcePortId}_net_${getPadNetNum(pad) ?? "none"}`;
701
+ }
702
+ function hasDuplicatePadNumberOnDifferentNets(footprint, padNumber) {
703
+ const pads = footprint.fpPads || [];
704
+ const padArray = Array.isArray(pads) ? pads : [pads];
705
+ const netKeys = /* @__PURE__ */ new Set();
706
+ for (const pad of padArray) {
707
+ if (pad.number?.toString() !== padNumber) continue;
708
+ netKeys.add(String(getPadNetNum(pad) ?? "none"));
709
+ }
710
+ return netKeys.size > 1;
711
+ }
712
+
597
713
  // lib/stages/pcb/CollectFootprintsStage/process-ports.ts
598
714
  function createPcbPort({
599
715
  ctx,
@@ -669,7 +785,13 @@ function attachPadPolygonContours(pad, contours) {
669
785
  });
670
786
  }
671
787
  function processPads(params) {
672
- const { ctx, footprint, componentId, footprintPlacement } = params;
788
+ const {
789
+ ctx,
790
+ footprint,
791
+ componentId,
792
+ footprintPlacement,
793
+ shouldCreatePorts = true
794
+ } = params;
673
795
  if (!ctx.k2cMatPcb) return;
674
796
  const pads = footprint.fpPads || [];
675
797
  const padArray = Array.isArray(pads) ? pads : [pads];
@@ -679,7 +801,8 @@ function processPads(params) {
679
801
  footprint,
680
802
  pad,
681
803
  componentId,
682
- footprintPlacement
804
+ footprintPlacement,
805
+ shouldCreatePorts
683
806
  });
684
807
  }
685
808
  }
@@ -688,7 +811,8 @@ function processPad({
688
811
  footprint,
689
812
  pad,
690
813
  componentId,
691
- footprintPlacement
814
+ footprintPlacement,
815
+ shouldCreatePorts = true
692
816
  }) {
693
817
  if (!ctx.k2cMatPcb) return;
694
818
  const padAt = pad.at || { x: 0, y: 0, angle: 0 };
@@ -721,13 +845,13 @@ function processPad({
721
845
  const padNumber = pad.number?.toString();
722
846
  let pcbPortId;
723
847
  let sourcePortId;
724
- if (padNumber) {
848
+ if (padNumber && shouldCreatePorts) {
725
849
  sourcePortId = getSourcePortIdForPad({
726
850
  componentId,
727
851
  footprint,
728
852
  pad
729
853
  });
730
- const padLayers = padType === "smd" ? copperLayers.slice(0, 1) : padType === "thru_hole" ? copperLayers : [];
854
+ const padLayers = padType === "smd" || padType === "connect" ? copperLayers.slice(0, 1) : padType === "thru_hole" ? copperLayers : [];
731
855
  const padPortInfo = {
732
856
  padNumber,
733
857
  sourcePortId,
@@ -742,7 +866,7 @@ function processPad({
742
866
  });
743
867
  if (!pcbPortId) sourcePortId = void 0;
744
868
  }
745
- if (padType === "smd") {
869
+ if (padType === "smd" || padType === "connect") {
746
870
  if (copperLayers.length === 0) {
747
871
  return;
748
872
  }
@@ -1506,110 +1630,6 @@ function createGraphicText(params) {
1506
1630
  }
1507
1631
  }
1508
1632
 
1509
- // lib/stages/pcb/CollectFootprintsStage/footprint-properties.ts
1510
- function getFootprintProperties(footprint) {
1511
- const properties = footprint.properties || [];
1512
- return Array.isArray(properties) ? properties : [properties];
1513
- }
1514
- function getFootprintPropertyName(property) {
1515
- return property?.key;
1516
- }
1517
- function getFootprintPropertyValue(property) {
1518
- return property?.value;
1519
- }
1520
- function findFootprintProperty(footprint, propertyNames) {
1521
- const names = Array.isArray(propertyNames) ? propertyNames : [propertyNames];
1522
- return getFootprintProperties(footprint).find(
1523
- (property) => names.includes(getFootprintPropertyName(property) ?? "")
1524
- );
1525
- }
1526
- function findFootprintPropertyValue(footprint, propertyNames) {
1527
- const property = findFootprintProperty(footprint, propertyNames);
1528
- return getFootprintPropertyValue(property);
1529
- }
1530
- function parseSupplierPartNumbers(value) {
1531
- if (!value) return void 0;
1532
- const partNumbers = value.split(/[,;]/).map((partNumber) => partNumber.trim()).filter(Boolean);
1533
- return partNumbers.length > 0 ? partNumbers : void 0;
1534
- }
1535
-
1536
- // lib/stages/pcb/CollectFootprintsStage/infer-component-type.ts
1537
- function inferComponentType(reference, footprint) {
1538
- if (!reference && !footprint) return "simple_chip";
1539
- const normalizedReference = reference?.trim();
1540
- const prefix = normalizedReference?.match(/^([A-Z]+)/)?.[1];
1541
- if (isFiducialReference(normalizedReference) || isFiducialFootprint(footprint)) {
1542
- return "simple_fiducial";
1543
- }
1544
- if (prefix === "TP" || isTestPointReference(normalizedReference) || isTestPointFootprint(footprint)) {
1545
- return "simple_test_point";
1546
- }
1547
- switch (prefix) {
1548
- case "R":
1549
- return "simple_resistor";
1550
- case "C":
1551
- return "simple_capacitor";
1552
- case "L":
1553
- return "simple_inductor";
1554
- case "D":
1555
- if (isLedFootprint(footprint)) return "simple_led";
1556
- return "simple_diode";
1557
- case "LED":
1558
- return "simple_led";
1559
- case "SW":
1560
- return "simple_switch";
1561
- case "Q":
1562
- return "simple_transistor";
1563
- case "U":
1564
- case "IC":
1565
- return "simple_chip";
1566
- case "J":
1567
- case "P":
1568
- return "simple_chip";
1569
- // Connectors treated as chips
1570
- default:
1571
- return "simple_chip";
1572
- }
1573
- }
1574
- function isFiducialReference(reference) {
1575
- return /^FID\d+/i.test(reference || "");
1576
- }
1577
- function isFiducialFootprint(footprint) {
1578
- return getFootprintMetadata(footprint).includes("fiducial");
1579
- }
1580
- function isLedFootprint(footprint) {
1581
- const metadata = getFootprintMetadata(footprint);
1582
- return metadata.includes("led") || metadata.includes("light emitting diode");
1583
- }
1584
- function isTestPointReference(reference) {
1585
- return /^TP\d+/i.test(reference || "");
1586
- }
1587
- function isTestPointFootprint(footprint) {
1588
- const metadata = getFootprintMetadata(footprint);
1589
- return metadata.includes("testpoint") || metadata.includes("test point");
1590
- }
1591
- function getFootprintMetadata(footprint) {
1592
- if (!footprint) return "";
1593
- return [
1594
- footprint.libraryLink,
1595
- footprint.descr?.value,
1596
- footprint.tags?.value,
1597
- findFootprintPropertyValue(footprint, "Footprint"),
1598
- findFootprintPropertyValue(footprint, "Description"),
1599
- findFootprintPropertyValue(footprint, "Value")
1600
- ].filter(Boolean).join(" ").toLowerCase();
1601
- }
1602
- function inferTransistorTypeFromFootprint(footprint, value) {
1603
- const lowerValue = (value || "").toLowerCase();
1604
- if (lowerValue.includes("pnp")) return "pnp";
1605
- if (lowerValue.includes("npn")) return "npn";
1606
- const libId = footprint.libraryId;
1607
- const lowerLibId = (libId || "").toLowerCase();
1608
- if (lowerLibId.includes("pnp")) return "pnp";
1609
- if (lowerLibId.includes("npn")) return "npn";
1610
- return "npn";
1611
- }
1612
-
1613
1633
  // lib/stages/pcb/CollectFootprintsStage/process-footprint.ts
1614
1634
  function processFootprint(ctx, footprint) {
1615
1635
  if (!ctx.k2cMatPcb) return;
@@ -1620,11 +1640,12 @@ function processFootprint(ctx, footprint) {
1620
1640
  const uuid = footprint.uuid?.value || footprint.tstamp?.value;
1621
1641
  if (!uuid) return;
1622
1642
  const refdes = getFootprintReference(footprint);
1643
+ const hasReference = Boolean(refdes?.trim());
1623
1644
  const value = getFootprintValue(footprint);
1624
1645
  const jlcpcbPartNumbers = getJlcpcbPartNumbers(footprint);
1625
1646
  const ftype = inferComponentType(refdes, footprint);
1626
1647
  const sourceComponentData = {
1627
- name: refdes || "U",
1648
+ name: refdes ?? "",
1628
1649
  ftype
1629
1650
  };
1630
1651
  if (ftype === "simple_transistor") {
@@ -1675,7 +1696,8 @@ function processFootprint(ctx, footprint) {
1675
1696
  ctx,
1676
1697
  footprint,
1677
1698
  componentId,
1678
- footprintPlacement
1699
+ footprintPlacement,
1700
+ shouldCreatePorts: hasReference
1679
1701
  });
1680
1702
  processFootprintText({
1681
1703
  ctx,
@@ -1693,18 +1715,6 @@ function processFootprint(ctx, footprint) {
1693
1715
  ctx.stats.components = (ctx.stats.components || 0) + 1;
1694
1716
  }
1695
1717
  }
1696
- function getFootprintReference(footprint) {
1697
- const propertyValue = findFootprintPropertyValue(footprint, "Reference");
1698
- if (propertyValue) return propertyValue;
1699
- const textItems = footprint.fpTexts || [];
1700
- const textArray = Array.isArray(textItems) ? textItems : [textItems];
1701
- for (const text of textArray) {
1702
- if (text.type === "reference") {
1703
- return text.text;
1704
- }
1705
- }
1706
- return void 0;
1707
- }
1708
1718
  function getFootprintValue(footprint) {
1709
1719
  const propertyValue = findFootprintPropertyValue(footprint, "Value");
1710
1720
  if (propertyValue) return propertyValue;
@@ -3646,6 +3656,7 @@ var CollectSourceTracesStage = class extends ConverterStage {
3646
3656
  return null;
3647
3657
  }
3648
3658
  processFootprintPads(footprint, netToPads) {
3659
+ if (!getFootprintReference(footprint)?.trim()) return;
3649
3660
  const footprintUuid = footprint.uuid?.value || footprint.tstamp?.value;
3650
3661
  if (!footprintUuid) return;
3651
3662
  const componentId = this.ctx.footprintUuidToComponentId?.get(footprintUuid);
@@ -4135,7 +4146,14 @@ var CollectTracesStage = class extends ConverterStage {
4135
4146
  findPortAtPosition(point, layer, netNum) {
4136
4147
  const portAtCenter = this.findPortCenterAtPosition(point, layer, netNum);
4137
4148
  if (portAtCenter) return portAtCenter;
4138
- return this.findPortContainingPoint(point, layer, netNum);
4149
+ const portContainingPoint = this.findPortContainingPoint(
4150
+ point,
4151
+ layer,
4152
+ netNum
4153
+ );
4154
+ if (portContainingPoint) return portContainingPoint;
4155
+ if (netNum === null) return void 0;
4156
+ return this.findPortCenterAtPosition(point, layer, null) ?? this.findPortContainingPoint(point, layer, null);
4139
4157
  }
4140
4158
  findPortCenterAtPosition(point, layer, netNum) {
4141
4159
  const ports = this.ctx.db.pcb_port.list();
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "kicad-to-circuit-json",
3
3
  "main": "dist/index.js",
4
4
  "type": "module",
5
- "version": "0.0.113",
5
+ "version": "0.0.115",
6
6
  "files": [
7
7
  "dist"
8
8
  ],
@@ -32,7 +32,7 @@
32
32
  "@vitejs/plugin-react": "^6.0.1",
33
33
  "bun-match-svg": "^0.0.14",
34
34
  "circuit-json-to-connectivity-map": "^0.0.25",
35
- "kicadts": "^0.0.49",
35
+ "kicadts": "^0.0.52",
36
36
  "react": "^19.2.0",
37
37
  "react-dom": "^19.2.5",
38
38
  "tscircuit": "^0.0.2040",