circuit-json-to-kicad 0.0.28 → 0.0.30
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/dist/index.d.ts +47 -2
- package/dist/index.js +404 -6
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CircuitJson } from 'circuit-json';
|
|
2
2
|
import { CircuitJsonUtilObjects, cju } from '@tscircuit/circuit-json-util';
|
|
3
|
-
import { KicadSch, KicadPcb } from 'kicadts';
|
|
3
|
+
import { KicadSch, KicadPcb, SchematicSymbol } from 'kicadts';
|
|
4
4
|
import { Matrix } from 'transformation-matrix';
|
|
5
5
|
|
|
6
6
|
type PaperSize = "A0" | "A1" | "A2" | "A3" | "A4" | "A5";
|
|
@@ -17,6 +17,22 @@ interface PcbNetInfo {
|
|
|
17
17
|
id: number;
|
|
18
18
|
name: string;
|
|
19
19
|
}
|
|
20
|
+
interface SymbolEntry {
|
|
21
|
+
symbolName: string;
|
|
22
|
+
symbol: SchematicSymbol;
|
|
23
|
+
}
|
|
24
|
+
interface FootprintEntry {
|
|
25
|
+
footprintName: string;
|
|
26
|
+
kicadModString: string;
|
|
27
|
+
model3dSourcePaths: string[];
|
|
28
|
+
}
|
|
29
|
+
interface KicadLibraryOutput {
|
|
30
|
+
kicadSymString: string;
|
|
31
|
+
footprints: FootprintEntry[];
|
|
32
|
+
fpLibTableString: string;
|
|
33
|
+
symLibTableString: string;
|
|
34
|
+
model3dSourcePaths: string[];
|
|
35
|
+
}
|
|
20
36
|
interface ConverterContext {
|
|
21
37
|
db: CircuitJsonUtilObjects;
|
|
22
38
|
circuitJson: CircuitJson;
|
|
@@ -38,6 +54,13 @@ interface ConverterContext {
|
|
|
38
54
|
y: number;
|
|
39
55
|
}>;
|
|
40
56
|
pcbNetMap?: Map<string, PcbNetInfo>;
|
|
57
|
+
libraryName?: string;
|
|
58
|
+
fpLibraryName?: string;
|
|
59
|
+
kicadSchString?: string;
|
|
60
|
+
kicadPcbString?: string;
|
|
61
|
+
symbolEntries?: SymbolEntry[];
|
|
62
|
+
footprintEntries?: FootprintEntry[];
|
|
63
|
+
libraryOutput?: KicadLibraryOutput;
|
|
41
64
|
}
|
|
42
65
|
declare abstract class ConverterStage<Input, Output> {
|
|
43
66
|
MAX_ITERATIONS: number;
|
|
@@ -156,4 +179,26 @@ declare class CircuitJsonToKicadProConverter {
|
|
|
156
179
|
getOutputString(): string;
|
|
157
180
|
}
|
|
158
181
|
|
|
159
|
-
|
|
182
|
+
interface CircuitJsonToKicadLibraryOptions {
|
|
183
|
+
libraryName?: string;
|
|
184
|
+
footprintLibraryName?: string;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
declare class CircuitJsonToKicadLibraryConverter {
|
|
188
|
+
ctx: ConverterContext;
|
|
189
|
+
pipeline: ConverterStage<CircuitJson, KicadLibraryOutput>[];
|
|
190
|
+
currentStageIndex: number;
|
|
191
|
+
finished: boolean;
|
|
192
|
+
get currentStage(): ConverterStage<CircuitJson, KicadLibraryOutput> | undefined;
|
|
193
|
+
constructor(circuitJson: CircuitJson, options?: CircuitJsonToKicadLibraryOptions);
|
|
194
|
+
step(): void;
|
|
195
|
+
runUntilFinished(): void;
|
|
196
|
+
getOutput(): KicadLibraryOutput;
|
|
197
|
+
getSymbolLibraryString(): string;
|
|
198
|
+
getFootprints(): FootprintEntry[];
|
|
199
|
+
getFpLibTableString(): string;
|
|
200
|
+
getSymLibTableString(): string;
|
|
201
|
+
getModel3dSourcePaths(): string[];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export { CircuitJsonToKicadLibraryConverter, CircuitJsonToKicadPcbConverter, CircuitJsonToKicadProConverter, CircuitJsonToKicadSchConverter, type FootprintEntry, type KicadLibraryOutput, type SymbolEntry };
|
package/dist/index.js
CHANGED
|
@@ -155,6 +155,7 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
|
|
|
155
155
|
if (!symbolData) return null;
|
|
156
156
|
const libId = getLibraryId(sourceComp, schematicComponent);
|
|
157
157
|
const isChip = sourceComp.ftype === "simple_chip";
|
|
158
|
+
const footprintName = sourceComp.ftype || "";
|
|
158
159
|
return this.createLibrarySymbol({
|
|
159
160
|
libId,
|
|
160
161
|
symbolData,
|
|
@@ -162,7 +163,8 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
|
|
|
162
163
|
schematicComponent,
|
|
163
164
|
description: this.getDescription(sourceComp),
|
|
164
165
|
keywords: this.getKeywords(sourceComp),
|
|
165
|
-
fpFilters: this.getFpFilters(sourceComp)
|
|
166
|
+
fpFilters: this.getFpFilters(sourceComp),
|
|
167
|
+
footprintRef: footprintName ? `tscircuit:${footprintName}` : ""
|
|
166
168
|
});
|
|
167
169
|
}
|
|
168
170
|
/**
|
|
@@ -244,7 +246,8 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
|
|
|
244
246
|
schematicComponent,
|
|
245
247
|
description,
|
|
246
248
|
keywords,
|
|
247
|
-
fpFilters
|
|
249
|
+
fpFilters,
|
|
250
|
+
footprintRef = ""
|
|
248
251
|
}) {
|
|
249
252
|
const symbol = new SchematicSymbol({
|
|
250
253
|
libraryId: libId,
|
|
@@ -263,7 +266,8 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
|
|
|
263
266
|
libId,
|
|
264
267
|
description,
|
|
265
268
|
keywords,
|
|
266
|
-
fpFilters
|
|
269
|
+
fpFilters,
|
|
270
|
+
footprintRef
|
|
267
271
|
});
|
|
268
272
|
const drawingSymbol = this.createDrawingSubsymbol({
|
|
269
273
|
libId,
|
|
@@ -289,7 +293,8 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
|
|
|
289
293
|
libId,
|
|
290
294
|
description,
|
|
291
295
|
keywords,
|
|
292
|
-
fpFilters
|
|
296
|
+
fpFilters,
|
|
297
|
+
footprintRef = ""
|
|
293
298
|
}) {
|
|
294
299
|
const refPrefix = libId.split(":")[1]?.[0] || "U";
|
|
295
300
|
const properties = [
|
|
@@ -303,7 +308,7 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
|
|
|
303
308
|
{ key: "Value", value: refPrefix, id: 1, at: [0, 0, 90], hide: false },
|
|
304
309
|
{
|
|
305
310
|
key: "Footprint",
|
|
306
|
-
value:
|
|
311
|
+
value: footprintRef,
|
|
307
312
|
id: 2,
|
|
308
313
|
at: [-1.778, 0, 90],
|
|
309
314
|
hide: true
|
|
@@ -1398,7 +1403,7 @@ var AddNetsStage = class extends ConverterStage {
|
|
|
1398
1403
|
};
|
|
1399
1404
|
|
|
1400
1405
|
// lib/pcb/stages/AddFootprintsStage.ts
|
|
1401
|
-
import { Footprint } from "kicadts";
|
|
1406
|
+
import { Footprint, FootprintModel } from "kicadts";
|
|
1402
1407
|
import { applyToPoint as applyToPoint9 } from "transformation-matrix";
|
|
1403
1408
|
|
|
1404
1409
|
// lib/pcb/stages/utils/CreateSmdPadFromCircuitJson.ts
|
|
@@ -1781,6 +1786,44 @@ var AddFootprintsStage = class extends ConverterStage {
|
|
|
1781
1786
|
if (!connectivityKey) return void 0;
|
|
1782
1787
|
return this.ctx.pcbNetMap?.get(connectivityKey);
|
|
1783
1788
|
}
|
|
1789
|
+
/**
|
|
1790
|
+
* Gets the cad_component associated with a pcb_component
|
|
1791
|
+
*/
|
|
1792
|
+
getCadComponentForPcbComponent(pcbComponentId) {
|
|
1793
|
+
const cadComponents = this.ctx.db.cad_component?.list() || [];
|
|
1794
|
+
return cadComponents.find(
|
|
1795
|
+
(cad) => cad.pcb_component_id === pcbComponentId
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
/**
|
|
1799
|
+
* Creates FootprintModel instances from a cad_component's 3D model URLs
|
|
1800
|
+
*/
|
|
1801
|
+
create3DModelsFromCadComponent(cadComponent, componentCenter) {
|
|
1802
|
+
const models = [];
|
|
1803
|
+
const modelUrl = cadComponent.model_step_url || cadComponent.model_wrl_url;
|
|
1804
|
+
if (!modelUrl) return models;
|
|
1805
|
+
const model = new FootprintModel(modelUrl);
|
|
1806
|
+
if (cadComponent.position) {
|
|
1807
|
+
model.offset = {
|
|
1808
|
+
x: (cadComponent.position.x || 0) - componentCenter.x,
|
|
1809
|
+
y: -((cadComponent.position.y || 0) - componentCenter.y),
|
|
1810
|
+
z: cadComponent.position.z || 0
|
|
1811
|
+
};
|
|
1812
|
+
}
|
|
1813
|
+
if (cadComponent.rotation) {
|
|
1814
|
+
model.rotate = {
|
|
1815
|
+
x: cadComponent.rotation.x || 0,
|
|
1816
|
+
y: cadComponent.rotation.y || 0,
|
|
1817
|
+
z: cadComponent.rotation.z || 0
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
if (cadComponent.model_unit_to_mm_scale_factor) {
|
|
1821
|
+
const scale4 = cadComponent.model_unit_to_mm_scale_factor;
|
|
1822
|
+
model.scale = { x: scale4, y: scale4, z: scale4 };
|
|
1823
|
+
}
|
|
1824
|
+
models.push(model);
|
|
1825
|
+
return models;
|
|
1826
|
+
}
|
|
1784
1827
|
constructor(input, ctx) {
|
|
1785
1828
|
super(input, ctx);
|
|
1786
1829
|
this.pcbComponents = this.ctx.db.pcb_component.list();
|
|
@@ -1876,6 +1919,18 @@ var AddFootprintsStage = class extends ConverterStage {
|
|
|
1876
1919
|
}
|
|
1877
1920
|
}
|
|
1878
1921
|
footprint.fpPads = fpPads;
|
|
1922
|
+
const cadComponent = this.getCadComponentForPcbComponent(
|
|
1923
|
+
component.pcb_component_id
|
|
1924
|
+
);
|
|
1925
|
+
if (cadComponent) {
|
|
1926
|
+
const models = this.create3DModelsFromCadComponent(
|
|
1927
|
+
cadComponent,
|
|
1928
|
+
component.center
|
|
1929
|
+
);
|
|
1930
|
+
if (models.length > 0) {
|
|
1931
|
+
footprint.models = models;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1879
1934
|
const footprints = kicadPcb.footprints;
|
|
1880
1935
|
footprints.push(footprint);
|
|
1881
1936
|
kicadPcb.footprints = footprints;
|
|
@@ -2375,7 +2430,350 @@ var CircuitJsonToKicadProConverter = class {
|
|
|
2375
2430
|
`;
|
|
2376
2431
|
}
|
|
2377
2432
|
};
|
|
2433
|
+
|
|
2434
|
+
// lib/kicad-library/CircuitJsonToKicadLibraryConverter.ts
|
|
2435
|
+
import { cju as cju4 } from "@tscircuit/circuit-json-util";
|
|
2436
|
+
|
|
2437
|
+
// lib/kicad-library/stages/GenerateKicadSchAndPcbStage.ts
|
|
2438
|
+
var GenerateKicadSchAndPcbStage = class extends ConverterStage {
|
|
2439
|
+
_step() {
|
|
2440
|
+
const schConverter = new CircuitJsonToKicadSchConverter(
|
|
2441
|
+
this.ctx.circuitJson
|
|
2442
|
+
);
|
|
2443
|
+
schConverter.runUntilFinished();
|
|
2444
|
+
this.ctx.kicadSchString = schConverter.getOutputString();
|
|
2445
|
+
const pcbConverter = new CircuitJsonToKicadPcbConverter(
|
|
2446
|
+
this.ctx.circuitJson
|
|
2447
|
+
);
|
|
2448
|
+
pcbConverter.runUntilFinished();
|
|
2449
|
+
this.ctx.kicadPcbString = pcbConverter.getOutputString();
|
|
2450
|
+
this.finished = true;
|
|
2451
|
+
}
|
|
2452
|
+
getOutput() {
|
|
2453
|
+
return this.ctx.libraryOutput;
|
|
2454
|
+
}
|
|
2455
|
+
};
|
|
2456
|
+
|
|
2457
|
+
// lib/kicad-library/stages/ExtractSymbolsStage.ts
|
|
2458
|
+
import { parseKicadSexpr, KicadSch as KicadSch2 } from "kicadts";
|
|
2459
|
+
var ExtractSymbolsStage = class extends ConverterStage {
|
|
2460
|
+
_step() {
|
|
2461
|
+
const schContent = this.ctx.kicadSchString;
|
|
2462
|
+
const fpLibraryName = this.ctx.fpLibraryName ?? "tscircuit";
|
|
2463
|
+
if (!schContent) {
|
|
2464
|
+
throw new Error(
|
|
2465
|
+
"Schematic content not available. Run GenerateKicadSchAndPcbStage first."
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2468
|
+
const uniqueSymbols = /* @__PURE__ */ new Map();
|
|
2469
|
+
try {
|
|
2470
|
+
const parsed = parseKicadSexpr(schContent);
|
|
2471
|
+
const sch = parsed.find(
|
|
2472
|
+
(node) => node instanceof KicadSch2
|
|
2473
|
+
);
|
|
2474
|
+
if (!sch) {
|
|
2475
|
+
this.ctx.symbolEntries = [];
|
|
2476
|
+
this.finished = true;
|
|
2477
|
+
return;
|
|
2478
|
+
}
|
|
2479
|
+
const libSymbols = sch.libSymbols;
|
|
2480
|
+
if (!libSymbols) {
|
|
2481
|
+
this.ctx.symbolEntries = [];
|
|
2482
|
+
this.finished = true;
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
const symbols3 = libSymbols.symbols ?? [];
|
|
2486
|
+
for (const symbol of symbols3) {
|
|
2487
|
+
const symbolName = this.sanitizeSymbolName(symbol.libraryId);
|
|
2488
|
+
if (!uniqueSymbols.has(symbolName)) {
|
|
2489
|
+
symbol.libraryId = symbolName;
|
|
2490
|
+
this.updateFootprintProperty(symbol, fpLibraryName);
|
|
2491
|
+
uniqueSymbols.set(symbolName, {
|
|
2492
|
+
symbolName,
|
|
2493
|
+
symbol
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
} catch (error) {
|
|
2498
|
+
console.warn("Failed to parse schematic for symbol extraction:", error);
|
|
2499
|
+
}
|
|
2500
|
+
this.ctx.symbolEntries = Array.from(uniqueSymbols.values());
|
|
2501
|
+
this.finished = true;
|
|
2502
|
+
}
|
|
2503
|
+
/**
|
|
2504
|
+
* Updates the Footprint property in a symbol to use the correct library name.
|
|
2505
|
+
* Changes "tscircuit:footprint_name" to "fpLibraryName:footprint_name"
|
|
2506
|
+
*/
|
|
2507
|
+
updateFootprintProperty(symbol, fpLibraryName) {
|
|
2508
|
+
const properties = symbol.properties ?? [];
|
|
2509
|
+
for (const prop of properties) {
|
|
2510
|
+
if (prop.key === "Footprint" && prop.value) {
|
|
2511
|
+
const parts = prop.value.split(":");
|
|
2512
|
+
if (parts.length > 1) {
|
|
2513
|
+
prop.value = `${fpLibraryName}:${parts[1]}`;
|
|
2514
|
+
} else if (prop.value.trim()) {
|
|
2515
|
+
prop.value = `${fpLibraryName}:${prop.value}`;
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
sanitizeSymbolName(libraryId) {
|
|
2521
|
+
if (!libraryId) return "symbol";
|
|
2522
|
+
const parts = libraryId.split(":");
|
|
2523
|
+
const name = parts.length > 1 ? parts[1] : parts[0];
|
|
2524
|
+
return name?.replace(/[\\\/]/g, "-").trim() || "symbol";
|
|
2525
|
+
}
|
|
2526
|
+
getOutput() {
|
|
2527
|
+
return this.ctx.libraryOutput;
|
|
2528
|
+
}
|
|
2529
|
+
};
|
|
2530
|
+
|
|
2531
|
+
// lib/kicad-library/stages/ExtractFootprintsStage.ts
|
|
2532
|
+
import {
|
|
2533
|
+
parseKicadSexpr as parseKicadSexpr2,
|
|
2534
|
+
KicadPcb as KicadPcb2,
|
|
2535
|
+
FootprintModel as FootprintModel2,
|
|
2536
|
+
At as At2
|
|
2537
|
+
} from "kicadts";
|
|
2538
|
+
function getBasename(filePath) {
|
|
2539
|
+
const parts = filePath.split(/[/\\]/);
|
|
2540
|
+
return parts[parts.length - 1] || filePath;
|
|
2541
|
+
}
|
|
2542
|
+
var ExtractFootprintsStage = class extends ConverterStage {
|
|
2543
|
+
_step() {
|
|
2544
|
+
const kicadPcbString = this.ctx.kicadPcbString;
|
|
2545
|
+
const fpLibraryName = this.ctx.fpLibraryName ?? "tscircuit";
|
|
2546
|
+
if (!kicadPcbString) {
|
|
2547
|
+
throw new Error(
|
|
2548
|
+
"PCB content not available. Run GenerateKicadSchAndPcbStage first."
|
|
2549
|
+
);
|
|
2550
|
+
}
|
|
2551
|
+
const uniqueFootprints = /* @__PURE__ */ new Map();
|
|
2552
|
+
try {
|
|
2553
|
+
const parsed = parseKicadSexpr2(kicadPcbString);
|
|
2554
|
+
const pcb = parsed.find(
|
|
2555
|
+
(node) => node instanceof KicadPcb2
|
|
2556
|
+
);
|
|
2557
|
+
if (!pcb) {
|
|
2558
|
+
this.ctx.footprintEntries = [];
|
|
2559
|
+
this.finished = true;
|
|
2560
|
+
return;
|
|
2561
|
+
}
|
|
2562
|
+
const footprints = pcb.footprints ?? [];
|
|
2563
|
+
for (const footprint of footprints) {
|
|
2564
|
+
const sanitized = this.sanitizeFootprint(footprint, fpLibraryName);
|
|
2565
|
+
if (!uniqueFootprints.has(sanitized.footprintName)) {
|
|
2566
|
+
uniqueFootprints.set(sanitized.footprintName, sanitized);
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
} catch (error) {
|
|
2570
|
+
console.warn("Failed to parse PCB for footprint extraction:", error);
|
|
2571
|
+
}
|
|
2572
|
+
this.ctx.footprintEntries = Array.from(uniqueFootprints.values());
|
|
2573
|
+
this.finished = true;
|
|
2574
|
+
}
|
|
2575
|
+
sanitizeFootprint(footprint, fpLibraryName) {
|
|
2576
|
+
const libraryLink = footprint.libraryLink ?? "footprint";
|
|
2577
|
+
const parts = libraryLink.split(":");
|
|
2578
|
+
const footprintName = (parts.length > 1 ? parts[1] : parts[0])?.replace(/[\\\/]/g, "-").trim() || "footprint";
|
|
2579
|
+
footprint.libraryLink = footprintName;
|
|
2580
|
+
footprint.position = At2.from([0, 0, 0]);
|
|
2581
|
+
footprint.locked = false;
|
|
2582
|
+
footprint.placed = false;
|
|
2583
|
+
footprint.uuid = void 0;
|
|
2584
|
+
footprint.path = void 0;
|
|
2585
|
+
footprint.sheetfile = void 0;
|
|
2586
|
+
footprint.sheetname = void 0;
|
|
2587
|
+
footprint.properties = [];
|
|
2588
|
+
const texts = footprint.fpTexts ?? [];
|
|
2589
|
+
for (const text of texts) {
|
|
2590
|
+
text.uuid = void 0;
|
|
2591
|
+
if (text.type === "reference") {
|
|
2592
|
+
text.text = "REF**";
|
|
2593
|
+
} else if (text.type === "value" && text.text.trim().length === 0) {
|
|
2594
|
+
text.text = footprintName;
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
footprint.fpTexts = texts;
|
|
2598
|
+
const pads = footprint.fpPads ?? [];
|
|
2599
|
+
for (const pad of pads) {
|
|
2600
|
+
pad.uuid = void 0;
|
|
2601
|
+
pad.net = void 0;
|
|
2602
|
+
}
|
|
2603
|
+
footprint.fpPads = pads;
|
|
2604
|
+
const models = footprint.models ?? [];
|
|
2605
|
+
const updatedModels = [];
|
|
2606
|
+
const modelFiles = [];
|
|
2607
|
+
for (const model of models) {
|
|
2608
|
+
if (model.path) {
|
|
2609
|
+
const modelFilename = getBasename(model.path);
|
|
2610
|
+
const newPath = `\${KIPRJMOD}/${fpLibraryName}.3dshapes/${modelFilename}`;
|
|
2611
|
+
const newModel = new FootprintModel2(newPath);
|
|
2612
|
+
if (model.offset) newModel.offset = model.offset;
|
|
2613
|
+
if (model.scale) newModel.scale = model.scale;
|
|
2614
|
+
if (model.rotate) newModel.rotate = model.rotate;
|
|
2615
|
+
updatedModels.push(newModel);
|
|
2616
|
+
modelFiles.push(model.path);
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
footprint.models = updatedModels;
|
|
2620
|
+
return {
|
|
2621
|
+
footprintName,
|
|
2622
|
+
kicadModString: footprint.getString(),
|
|
2623
|
+
model3dSourcePaths: modelFiles
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
getOutput() {
|
|
2627
|
+
return this.ctx.libraryOutput;
|
|
2628
|
+
}
|
|
2629
|
+
};
|
|
2630
|
+
|
|
2631
|
+
// lib/kicad-library/stages/GenerateSymbolLibraryStage.ts
|
|
2632
|
+
import { KicadSymbolLib } from "kicadts";
|
|
2633
|
+
var KICAD_SYM_LIB_VERSION = 20211014;
|
|
2634
|
+
var GENERATOR = "circuit-json-to-kicad";
|
|
2635
|
+
var GenerateSymbolLibraryStage = class extends ConverterStage {
|
|
2636
|
+
_step() {
|
|
2637
|
+
const symbolEntries = this.ctx.symbolEntries ?? [];
|
|
2638
|
+
const symbolLibrary = this.generateSymbolLibrary(symbolEntries);
|
|
2639
|
+
if (!this.ctx.libraryOutput) {
|
|
2640
|
+
this.ctx.libraryOutput = {
|
|
2641
|
+
kicadSymString: "",
|
|
2642
|
+
footprints: [],
|
|
2643
|
+
fpLibTableString: "",
|
|
2644
|
+
symLibTableString: "",
|
|
2645
|
+
model3dSourcePaths: []
|
|
2646
|
+
};
|
|
2647
|
+
}
|
|
2648
|
+
this.ctx.libraryOutput.kicadSymString = symbolLibrary;
|
|
2649
|
+
this.finished = true;
|
|
2650
|
+
}
|
|
2651
|
+
generateSymbolLibrary(symbolEntries) {
|
|
2652
|
+
const symbolLib = new KicadSymbolLib({
|
|
2653
|
+
version: KICAD_SYM_LIB_VERSION,
|
|
2654
|
+
generator: GENERATOR,
|
|
2655
|
+
symbols: symbolEntries.map((entry) => entry.symbol)
|
|
2656
|
+
});
|
|
2657
|
+
return symbolLib.getString();
|
|
2658
|
+
}
|
|
2659
|
+
getOutput() {
|
|
2660
|
+
return this.ctx.libraryOutput;
|
|
2661
|
+
}
|
|
2662
|
+
};
|
|
2663
|
+
|
|
2664
|
+
// lib/kicad-library/stages/GenerateLibraryTablesStage.ts
|
|
2665
|
+
var GenerateLibraryTablesStage = class extends ConverterStage {
|
|
2666
|
+
_step() {
|
|
2667
|
+
const libraryName = this.ctx.libraryName ?? "tscircuit";
|
|
2668
|
+
const fpLibraryName = this.ctx.fpLibraryName ?? "tscircuit";
|
|
2669
|
+
const footprintEntries = this.ctx.footprintEntries ?? [];
|
|
2670
|
+
const model3dSourcePathsSet = /* @__PURE__ */ new Set();
|
|
2671
|
+
for (const fp of footprintEntries) {
|
|
2672
|
+
for (const modelPath of fp.model3dSourcePaths) {
|
|
2673
|
+
model3dSourcePathsSet.add(modelPath);
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
const fpLibTableString = this.generateFpLibTable(fpLibraryName);
|
|
2677
|
+
const symLibTableString = this.generateSymLibTable(libraryName);
|
|
2678
|
+
if (!this.ctx.libraryOutput) {
|
|
2679
|
+
this.ctx.libraryOutput = {
|
|
2680
|
+
kicadSymString: "",
|
|
2681
|
+
footprints: [],
|
|
2682
|
+
fpLibTableString: "",
|
|
2683
|
+
symLibTableString: "",
|
|
2684
|
+
model3dSourcePaths: []
|
|
2685
|
+
};
|
|
2686
|
+
}
|
|
2687
|
+
this.ctx.libraryOutput.footprints = footprintEntries;
|
|
2688
|
+
this.ctx.libraryOutput.fpLibTableString = fpLibTableString;
|
|
2689
|
+
this.ctx.libraryOutput.symLibTableString = symLibTableString;
|
|
2690
|
+
this.ctx.libraryOutput.model3dSourcePaths = Array.from(
|
|
2691
|
+
model3dSourcePathsSet
|
|
2692
|
+
);
|
|
2693
|
+
this.finished = true;
|
|
2694
|
+
}
|
|
2695
|
+
generateFpLibTable(fpLibraryName) {
|
|
2696
|
+
return `(fp_lib_table
|
|
2697
|
+
(version 7)
|
|
2698
|
+
(lib (name "${fpLibraryName}") (type "KiCad") (uri "\${KIPRJMOD}/${fpLibraryName}.pretty") (options "") (descr "Generated by circuit-json-to-kicad"))
|
|
2699
|
+
)
|
|
2700
|
+
`;
|
|
2701
|
+
}
|
|
2702
|
+
generateSymLibTable(libraryName) {
|
|
2703
|
+
return `(sym_lib_table
|
|
2704
|
+
(version 7)
|
|
2705
|
+
(lib (name "${libraryName}") (type "KiCad") (uri "\${KIPRJMOD}/${libraryName}.kicad_sym") (options "") (descr "Generated by circuit-json-to-kicad"))
|
|
2706
|
+
)
|
|
2707
|
+
`;
|
|
2708
|
+
}
|
|
2709
|
+
getOutput() {
|
|
2710
|
+
return this.ctx.libraryOutput;
|
|
2711
|
+
}
|
|
2712
|
+
};
|
|
2713
|
+
|
|
2714
|
+
// lib/kicad-library/CircuitJsonToKicadLibraryConverter.ts
|
|
2715
|
+
var CircuitJsonToKicadLibraryConverter = class {
|
|
2716
|
+
ctx;
|
|
2717
|
+
pipeline;
|
|
2718
|
+
currentStageIndex = 0;
|
|
2719
|
+
finished = false;
|
|
2720
|
+
get currentStage() {
|
|
2721
|
+
return this.pipeline[this.currentStageIndex];
|
|
2722
|
+
}
|
|
2723
|
+
constructor(circuitJson, options = {}) {
|
|
2724
|
+
this.ctx = {
|
|
2725
|
+
db: cju4(circuitJson),
|
|
2726
|
+
circuitJson,
|
|
2727
|
+
libraryName: options.libraryName ?? "tscircuit",
|
|
2728
|
+
fpLibraryName: options.footprintLibraryName ?? "tscircuit"
|
|
2729
|
+
};
|
|
2730
|
+
this.pipeline = [
|
|
2731
|
+
new GenerateKicadSchAndPcbStage(circuitJson, this.ctx),
|
|
2732
|
+
new ExtractSymbolsStage(circuitJson, this.ctx),
|
|
2733
|
+
new ExtractFootprintsStage(circuitJson, this.ctx),
|
|
2734
|
+
new GenerateSymbolLibraryStage(circuitJson, this.ctx),
|
|
2735
|
+
new GenerateLibraryTablesStage(circuitJson, this.ctx)
|
|
2736
|
+
];
|
|
2737
|
+
}
|
|
2738
|
+
step() {
|
|
2739
|
+
if (!this.currentStage) {
|
|
2740
|
+
this.finished = true;
|
|
2741
|
+
return;
|
|
2742
|
+
}
|
|
2743
|
+
this.currentStage.step();
|
|
2744
|
+
if (this.currentStage.finished) {
|
|
2745
|
+
this.currentStageIndex++;
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
runUntilFinished() {
|
|
2749
|
+
while (!this.finished) {
|
|
2750
|
+
this.step();
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
getOutput() {
|
|
2754
|
+
if (!this.ctx.libraryOutput) {
|
|
2755
|
+
throw new Error("Converter has not been run yet");
|
|
2756
|
+
}
|
|
2757
|
+
return this.ctx.libraryOutput;
|
|
2758
|
+
}
|
|
2759
|
+
getSymbolLibraryString() {
|
|
2760
|
+
return this.getOutput().kicadSymString;
|
|
2761
|
+
}
|
|
2762
|
+
getFootprints() {
|
|
2763
|
+
return this.getOutput().footprints;
|
|
2764
|
+
}
|
|
2765
|
+
getFpLibTableString() {
|
|
2766
|
+
return this.getOutput().fpLibTableString;
|
|
2767
|
+
}
|
|
2768
|
+
getSymLibTableString() {
|
|
2769
|
+
return this.getOutput().symLibTableString;
|
|
2770
|
+
}
|
|
2771
|
+
getModel3dSourcePaths() {
|
|
2772
|
+
return this.getOutput().model3dSourcePaths;
|
|
2773
|
+
}
|
|
2774
|
+
};
|
|
2378
2775
|
export {
|
|
2776
|
+
CircuitJsonToKicadLibraryConverter,
|
|
2379
2777
|
CircuitJsonToKicadPcbConverter,
|
|
2380
2778
|
CircuitJsonToKicadProConverter,
|
|
2381
2779
|
CircuitJsonToKicadSchConverter
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circuit-json-to-kicad",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.30",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@types/bun": "latest",
|
|
22
22
|
"circuit-json": "^0.0.302",
|
|
23
23
|
"circuit-to-svg": "^0.0.208",
|
|
24
|
-
"kicadts": "^0.0.
|
|
24
|
+
"kicadts": "^0.0.23",
|
|
25
25
|
"schematic-symbols": "^0.0.202",
|
|
26
26
|
"sharp": "^0.34.4",
|
|
27
27
|
"transformation-matrix": "^3.1.0",
|