circuit-json-to-kicad 0.0.35 → 0.0.37
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 +39 -1
- package/dist/index.js +223 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -212,6 +212,38 @@ declare class CircuitJsonToKicadLibraryConverter {
|
|
|
212
212
|
getModel3dSourcePaths(): string[];
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
+
/**
|
|
216
|
+
* KiCad footprint metadata that can be extracted from component props.
|
|
217
|
+
* This mirrors the KicadFootprintMetadata type from @tscircuit/props.
|
|
218
|
+
*/
|
|
219
|
+
interface KicadFootprintMetadata {
|
|
220
|
+
footprintName?: string;
|
|
221
|
+
layer?: string;
|
|
222
|
+
properties?: {
|
|
223
|
+
Reference?: KicadPropertyMetadata;
|
|
224
|
+
Value?: KicadPropertyMetadata;
|
|
225
|
+
Datasheet?: KicadPropertyMetadata;
|
|
226
|
+
Description?: KicadPropertyMetadata;
|
|
227
|
+
};
|
|
228
|
+
attributes?: {
|
|
229
|
+
through_hole?: boolean;
|
|
230
|
+
smd?: boolean;
|
|
231
|
+
exclude_from_pos_files?: boolean;
|
|
232
|
+
exclude_from_bom?: boolean;
|
|
233
|
+
};
|
|
234
|
+
embeddedFonts?: boolean;
|
|
235
|
+
}
|
|
236
|
+
interface KicadPropertyMetadata {
|
|
237
|
+
value: string;
|
|
238
|
+
at?: {
|
|
239
|
+
x: number | string;
|
|
240
|
+
y: number | string;
|
|
241
|
+
rotation?: number | string;
|
|
242
|
+
};
|
|
243
|
+
layer?: string;
|
|
244
|
+
uuid?: string;
|
|
245
|
+
hide?: boolean;
|
|
246
|
+
}
|
|
215
247
|
interface KicadLibraryConverterOptions {
|
|
216
248
|
/**
|
|
217
249
|
* Name for the generated KiCad library (e.g., "my-library").
|
|
@@ -248,6 +280,12 @@ interface KicadLibraryConverterOptions {
|
|
|
248
280
|
* Default: true
|
|
249
281
|
*/
|
|
250
282
|
includeBuiltins?: boolean;
|
|
283
|
+
/**
|
|
284
|
+
* Callback to get KiCad footprint metadata from a component via prop introspection.
|
|
285
|
+
* This allows extracting kicadFootprintMetadata props without rendering the component.
|
|
286
|
+
* Return null if no metadata is available.
|
|
287
|
+
*/
|
|
288
|
+
getComponentKicadMetadata?: (filePath: string, componentName: string) => Promise<KicadFootprintMetadata | null>;
|
|
251
289
|
}
|
|
252
290
|
interface KicadLibraryConverterOutput {
|
|
253
291
|
/**
|
|
@@ -280,4 +318,4 @@ declare class KicadLibraryConverter {
|
|
|
280
318
|
getOutput(): KicadLibraryConverterOutput;
|
|
281
319
|
}
|
|
282
320
|
|
|
283
|
-
export { CircuitJsonToKicadLibraryConverter, CircuitJsonToKicadPcbConverter, CircuitJsonToKicadProConverter, CircuitJsonToKicadSchConverter, type FootprintEntry, KicadLibraryConverter, type KicadLibraryConverterOptions, type KicadLibraryConverterOutput, type KicadLibraryOutput, type SymbolEntry };
|
|
321
|
+
export { CircuitJsonToKicadLibraryConverter, CircuitJsonToKicadPcbConverter, CircuitJsonToKicadProConverter, CircuitJsonToKicadSchConverter, type FootprintEntry, type KicadFootprintMetadata, KicadLibraryConverter, type KicadLibraryConverterOptions, type KicadLibraryConverterOutput, type KicadLibraryOutput, type KicadPropertyMetadata, type SymbolEntry };
|
package/dist/index.js
CHANGED
|
@@ -1911,6 +1911,9 @@ var AddFootprintsStage = class extends ConverterStage {
|
|
|
1911
1911
|
componentRotation: component.rotation || 0
|
|
1912
1912
|
});
|
|
1913
1913
|
if (fpText) {
|
|
1914
|
+
if (sourceComponent?.name && textElement.text === sourceComponent.name) {
|
|
1915
|
+
fpText.type = "reference";
|
|
1916
|
+
}
|
|
1914
1917
|
fpTexts.push(fpText);
|
|
1915
1918
|
}
|
|
1916
1919
|
}
|
|
@@ -2585,7 +2588,12 @@ import {
|
|
|
2585
2588
|
parseKicadSexpr as parseKicadSexpr2,
|
|
2586
2589
|
KicadPcb as KicadPcb2,
|
|
2587
2590
|
FootprintModel as FootprintModel2,
|
|
2588
|
-
At as At2
|
|
2591
|
+
At as At2,
|
|
2592
|
+
EmbeddedFonts as EmbeddedFonts4,
|
|
2593
|
+
FootprintAttr,
|
|
2594
|
+
Property,
|
|
2595
|
+
TextEffects as TextEffects6,
|
|
2596
|
+
TextEffectsFont as TextEffectsFont6
|
|
2589
2597
|
} from "kicadts";
|
|
2590
2598
|
function getBasename(filePath) {
|
|
2591
2599
|
const parts = filePath.split(/[/\\]/);
|
|
@@ -2664,11 +2672,71 @@ var ExtractFootprintsStage = class extends ConverterStage {
|
|
|
2664
2672
|
footprint.position = At2.from([0, 0, 0]);
|
|
2665
2673
|
footprint.locked = false;
|
|
2666
2674
|
footprint.placed = false;
|
|
2675
|
+
if (!footprint.descr) {
|
|
2676
|
+
footprint.descr = "";
|
|
2677
|
+
}
|
|
2678
|
+
if (!footprint.tags) {
|
|
2679
|
+
footprint.tags = "";
|
|
2680
|
+
}
|
|
2681
|
+
if (!footprint.embeddedFonts) {
|
|
2682
|
+
footprint.embeddedFonts = new EmbeddedFonts4(false);
|
|
2683
|
+
}
|
|
2684
|
+
if (!footprint.attr) {
|
|
2685
|
+
const attr = new FootprintAttr();
|
|
2686
|
+
const padTypes = (footprint.fpPads ?? []).map((pad) => pad.padType);
|
|
2687
|
+
if (padTypes.some((padType) => padType.includes("thru_hole"))) {
|
|
2688
|
+
attr.type = "through_hole";
|
|
2689
|
+
} else if (padTypes.some((padType) => padType.includes("smd"))) {
|
|
2690
|
+
attr.type = "smd";
|
|
2691
|
+
}
|
|
2692
|
+
footprint.attr = attr;
|
|
2693
|
+
}
|
|
2667
2694
|
footprint.uuid = void 0;
|
|
2668
2695
|
footprint.path = void 0;
|
|
2669
2696
|
footprint.sheetfile = void 0;
|
|
2670
2697
|
footprint.sheetname = void 0;
|
|
2671
|
-
|
|
2698
|
+
const defaultFont = new TextEffectsFont6();
|
|
2699
|
+
defaultFont.size = { width: 1.27, height: 1.27 };
|
|
2700
|
+
defaultFont.thickness = 0.15;
|
|
2701
|
+
const defaultEffects = new TextEffects6({ font: defaultFont });
|
|
2702
|
+
footprint.properties = [
|
|
2703
|
+
new Property({
|
|
2704
|
+
key: "Reference",
|
|
2705
|
+
value: "Ref**",
|
|
2706
|
+
position: [0, 0, 0],
|
|
2707
|
+
layer: "F.SilkS",
|
|
2708
|
+
uuid: generateDeterministicUuid(`${footprintName}-property-Reference`),
|
|
2709
|
+
effects: defaultEffects
|
|
2710
|
+
}),
|
|
2711
|
+
new Property({
|
|
2712
|
+
key: "Value",
|
|
2713
|
+
value: "Val**",
|
|
2714
|
+
position: [0, 0, 0],
|
|
2715
|
+
layer: "F.Fab",
|
|
2716
|
+
uuid: generateDeterministicUuid(`${footprintName}-property-Value`),
|
|
2717
|
+
effects: defaultEffects
|
|
2718
|
+
}),
|
|
2719
|
+
new Property({
|
|
2720
|
+
key: "Datasheet",
|
|
2721
|
+
value: "",
|
|
2722
|
+
position: [0, 0, 0],
|
|
2723
|
+
layer: "F.Fab",
|
|
2724
|
+
hidden: true,
|
|
2725
|
+
uuid: generateDeterministicUuid(`${footprintName}-property-Datasheet`),
|
|
2726
|
+
effects: defaultEffects
|
|
2727
|
+
}),
|
|
2728
|
+
new Property({
|
|
2729
|
+
key: "Description",
|
|
2730
|
+
value: "",
|
|
2731
|
+
position: [0, 0, 0],
|
|
2732
|
+
layer: "F.Fab",
|
|
2733
|
+
hidden: true,
|
|
2734
|
+
uuid: generateDeterministicUuid(
|
|
2735
|
+
`${footprintName}-property-Description`
|
|
2736
|
+
),
|
|
2737
|
+
effects: defaultEffects
|
|
2738
|
+
})
|
|
2739
|
+
];
|
|
2672
2740
|
const texts = footprint.fpTexts ?? [];
|
|
2673
2741
|
for (const text of texts) {
|
|
2674
2742
|
text.uuid = void 0;
|
|
@@ -2680,9 +2748,14 @@ var ExtractFootprintsStage = class extends ConverterStage {
|
|
|
2680
2748
|
}
|
|
2681
2749
|
footprint.fpTexts = texts;
|
|
2682
2750
|
const pads = footprint.fpPads ?? [];
|
|
2683
|
-
for (
|
|
2684
|
-
pad
|
|
2685
|
-
pad
|
|
2751
|
+
for (let i = 0; i < pads.length; i++) {
|
|
2752
|
+
const pad = pads[i];
|
|
2753
|
+
if (pad) {
|
|
2754
|
+
pad.uuid = generateDeterministicUuid(
|
|
2755
|
+
`${footprintName}-pad-${pad.number ?? i}`
|
|
2756
|
+
);
|
|
2757
|
+
pad.net = void 0;
|
|
2758
|
+
}
|
|
2686
2759
|
}
|
|
2687
2760
|
footprint.fpPads = pads;
|
|
2688
2761
|
const models = footprint.models ?? [];
|
|
@@ -2883,6 +2956,117 @@ function renameKicadFootprint(params) {
|
|
|
2883
2956
|
};
|
|
2884
2957
|
}
|
|
2885
2958
|
|
|
2959
|
+
// lib/kicad-library/kicad-library-converter-utils/applyKicadFootprintMetadata.ts
|
|
2960
|
+
import {
|
|
2961
|
+
parseKicadSexpr as parseKicadSexpr3,
|
|
2962
|
+
Footprint as Footprint3,
|
|
2963
|
+
Property as Property2,
|
|
2964
|
+
TextEffects as TextEffects7,
|
|
2965
|
+
TextEffectsFont as TextEffectsFont7
|
|
2966
|
+
} from "kicadts";
|
|
2967
|
+
function applyKicadFootprintMetadata(kicadModString, metadata, footprintName) {
|
|
2968
|
+
try {
|
|
2969
|
+
const parsed = parseKicadSexpr3(kicadModString);
|
|
2970
|
+
const footprint = parsed.find(
|
|
2971
|
+
(node) => node instanceof Footprint3
|
|
2972
|
+
);
|
|
2973
|
+
if (!footprint) {
|
|
2974
|
+
return kicadModString;
|
|
2975
|
+
}
|
|
2976
|
+
if (metadata.embeddedFonts !== void 0) {
|
|
2977
|
+
}
|
|
2978
|
+
if (metadata.properties) {
|
|
2979
|
+
const defaultFont = new TextEffectsFont7();
|
|
2980
|
+
defaultFont.size = { width: 1.27, height: 1.27 };
|
|
2981
|
+
defaultFont.thickness = 0.15;
|
|
2982
|
+
const defaultEffects = new TextEffects7({ font: defaultFont });
|
|
2983
|
+
const newProperties = [];
|
|
2984
|
+
const refMeta = metadata.properties.Reference;
|
|
2985
|
+
newProperties.push(
|
|
2986
|
+
new Property2({
|
|
2987
|
+
key: "Reference",
|
|
2988
|
+
value: refMeta?.value ?? "REF**",
|
|
2989
|
+
position: refMeta?.at ? [
|
|
2990
|
+
Number(refMeta.at.x),
|
|
2991
|
+
Number(refMeta.at.y),
|
|
2992
|
+
Number(refMeta.at.rotation ?? 0)
|
|
2993
|
+
] : [0, 0, 0],
|
|
2994
|
+
layer: refMeta?.layer ?? "F.SilkS",
|
|
2995
|
+
uuid: refMeta?.uuid ?? generateDeterministicUuid(`${footprintName}-property-Reference`),
|
|
2996
|
+
effects: defaultEffects,
|
|
2997
|
+
hidden: refMeta?.hide
|
|
2998
|
+
})
|
|
2999
|
+
);
|
|
3000
|
+
const valMeta = metadata.properties.Value;
|
|
3001
|
+
newProperties.push(
|
|
3002
|
+
new Property2({
|
|
3003
|
+
key: "Value",
|
|
3004
|
+
value: valMeta?.value ?? footprintName,
|
|
3005
|
+
position: valMeta?.at ? [
|
|
3006
|
+
Number(valMeta.at.x),
|
|
3007
|
+
Number(valMeta.at.y),
|
|
3008
|
+
Number(valMeta.at.rotation ?? 0)
|
|
3009
|
+
] : [0, 0, 0],
|
|
3010
|
+
layer: valMeta?.layer ?? "F.Fab",
|
|
3011
|
+
uuid: valMeta?.uuid ?? generateDeterministicUuid(`${footprintName}-property-Value`),
|
|
3012
|
+
effects: defaultEffects,
|
|
3013
|
+
hidden: valMeta?.hide
|
|
3014
|
+
})
|
|
3015
|
+
);
|
|
3016
|
+
const dsMeta = metadata.properties.Datasheet;
|
|
3017
|
+
newProperties.push(
|
|
3018
|
+
new Property2({
|
|
3019
|
+
key: "Datasheet",
|
|
3020
|
+
value: dsMeta?.value ?? "",
|
|
3021
|
+
position: dsMeta?.at ? [
|
|
3022
|
+
Number(dsMeta.at.x),
|
|
3023
|
+
Number(dsMeta.at.y),
|
|
3024
|
+
Number(dsMeta.at.rotation ?? 0)
|
|
3025
|
+
] : [0, 0, 0],
|
|
3026
|
+
layer: dsMeta?.layer ?? "F.Fab",
|
|
3027
|
+
uuid: dsMeta?.uuid ?? generateDeterministicUuid(`${footprintName}-property-Datasheet`),
|
|
3028
|
+
effects: defaultEffects,
|
|
3029
|
+
hidden: dsMeta?.hide ?? true
|
|
3030
|
+
})
|
|
3031
|
+
);
|
|
3032
|
+
const descMeta = metadata.properties.Description;
|
|
3033
|
+
newProperties.push(
|
|
3034
|
+
new Property2({
|
|
3035
|
+
key: "Description",
|
|
3036
|
+
value: descMeta?.value ?? "",
|
|
3037
|
+
position: descMeta?.at ? [
|
|
3038
|
+
Number(descMeta.at.x),
|
|
3039
|
+
Number(descMeta.at.y),
|
|
3040
|
+
Number(descMeta.at.rotation ?? 0)
|
|
3041
|
+
] : [0, 0, 0],
|
|
3042
|
+
layer: descMeta?.layer ?? "F.Fab",
|
|
3043
|
+
uuid: descMeta?.uuid ?? generateDeterministicUuid(`${footprintName}-property-Description`),
|
|
3044
|
+
effects: defaultEffects,
|
|
3045
|
+
hidden: descMeta?.hide ?? true
|
|
3046
|
+
})
|
|
3047
|
+
);
|
|
3048
|
+
footprint.properties = newProperties;
|
|
3049
|
+
}
|
|
3050
|
+
if (metadata.attributes && footprint.attr) {
|
|
3051
|
+
if (metadata.attributes.through_hole) {
|
|
3052
|
+
footprint.attr.type = "through_hole";
|
|
3053
|
+
} else if (metadata.attributes.smd) {
|
|
3054
|
+
footprint.attr.type = "smd";
|
|
3055
|
+
}
|
|
3056
|
+
if (metadata.attributes.exclude_from_pos_files !== void 0) {
|
|
3057
|
+
footprint.attr.excludeFromPosFiles = metadata.attributes.exclude_from_pos_files;
|
|
3058
|
+
}
|
|
3059
|
+
if (metadata.attributes.exclude_from_bom !== void 0) {
|
|
3060
|
+
footprint.attr.excludeFromBom = metadata.attributes.exclude_from_bom;
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
return footprint.getString();
|
|
3064
|
+
} catch (error) {
|
|
3065
|
+
console.warn(`Failed to apply kicadFootprintMetadata:`, error);
|
|
3066
|
+
return kicadModString;
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
|
|
2886
3070
|
// lib/kicad-library/stages/ClassifyKicadFootprintsStage.ts
|
|
2887
3071
|
function classifyKicadFootprints(ctx) {
|
|
2888
3072
|
for (const extractedKicadComponent of ctx.extractedKicadComponents) {
|
|
@@ -2898,17 +3082,28 @@ function classifyFootprintsForComponent({
|
|
|
2898
3082
|
}) {
|
|
2899
3083
|
const { tscircuitComponentName, kicadFootprints } = extractedKicadComponent;
|
|
2900
3084
|
let hasAddedUserFootprint = false;
|
|
3085
|
+
const metadata = ctx.footprintMetadataMap.get(tscircuitComponentName);
|
|
2901
3086
|
for (const kicadFootprint of kicadFootprints) {
|
|
2902
3087
|
if (kicadFootprint.isBuiltin) {
|
|
2903
3088
|
addBuiltinFootprint({ ctx, kicadFootprint });
|
|
2904
3089
|
} else {
|
|
2905
3090
|
if (!hasAddedUserFootprint) {
|
|
2906
3091
|
hasAddedUserFootprint = true;
|
|
2907
|
-
|
|
3092
|
+
let renamedFootprint = renameKicadFootprint({
|
|
2908
3093
|
kicadFootprint,
|
|
2909
3094
|
newKicadFootprintName: tscircuitComponentName,
|
|
2910
3095
|
kicadLibraryName: ctx.kicadLibraryName
|
|
2911
3096
|
});
|
|
3097
|
+
if (metadata) {
|
|
3098
|
+
renamedFootprint = {
|
|
3099
|
+
...renamedFootprint,
|
|
3100
|
+
kicadModString: applyKicadFootprintMetadata(
|
|
3101
|
+
renamedFootprint.kicadModString,
|
|
3102
|
+
metadata,
|
|
3103
|
+
tscircuitComponentName
|
|
3104
|
+
)
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
2912
3107
|
addUserFootprint({ ctx, kicadFootprint: renamedFootprint });
|
|
2913
3108
|
} else {
|
|
2914
3109
|
addUserFootprint({ ctx, kicadFootprint });
|
|
@@ -3156,7 +3351,8 @@ var KicadLibraryConverter = class {
|
|
|
3156
3351
|
this.options = options;
|
|
3157
3352
|
this.ctx = createKicadLibraryConverterContext({
|
|
3158
3353
|
kicadLibraryName: options.kicadLibraryName ?? "tscircuit_library",
|
|
3159
|
-
includeBuiltins: options.includeBuiltins ?? true
|
|
3354
|
+
includeBuiltins: options.includeBuiltins ?? true,
|
|
3355
|
+
getComponentKicadMetadata: options.getComponentKicadMetadata
|
|
3160
3356
|
});
|
|
3161
3357
|
}
|
|
3162
3358
|
async run() {
|
|
@@ -3189,6 +3385,15 @@ var KicadLibraryConverter = class {
|
|
|
3189
3385
|
);
|
|
3190
3386
|
if (resolved) componentPath = resolved;
|
|
3191
3387
|
}
|
|
3388
|
+
if (this.ctx.getComponentKicadMetadata) {
|
|
3389
|
+
const metadata = await this.ctx.getComponentKicadMetadata(
|
|
3390
|
+
componentPath,
|
|
3391
|
+
exportName
|
|
3392
|
+
);
|
|
3393
|
+
if (metadata) {
|
|
3394
|
+
this.ctx.footprintMetadataMap.set(exportName, metadata);
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3192
3397
|
const circuitJson = await this.options.buildFileToCircuitJson(
|
|
3193
3398
|
componentPath,
|
|
3194
3399
|
exportName
|
|
@@ -3210,6 +3415,15 @@ var KicadLibraryConverter = class {
|
|
|
3210
3415
|
if (resolved) componentPath = resolved;
|
|
3211
3416
|
}
|
|
3212
3417
|
const componentName = deriveComponentNameFromPath(componentPath);
|
|
3418
|
+
if (this.ctx.getComponentKicadMetadata) {
|
|
3419
|
+
const metadata = await this.ctx.getComponentKicadMetadata(
|
|
3420
|
+
componentPath,
|
|
3421
|
+
"default"
|
|
3422
|
+
);
|
|
3423
|
+
if (metadata) {
|
|
3424
|
+
this.ctx.footprintMetadataMap.set(componentName, metadata);
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3213
3427
|
const circuitJson = await this.options.buildFileToCircuitJson(
|
|
3214
3428
|
componentPath,
|
|
3215
3429
|
"default"
|
|
@@ -3263,6 +3477,8 @@ function createKicadLibraryConverterContext(params) {
|
|
|
3263
3477
|
return {
|
|
3264
3478
|
kicadLibraryName: params.kicadLibraryName,
|
|
3265
3479
|
includeBuiltins: params.includeBuiltins,
|
|
3480
|
+
getComponentKicadMetadata: params.getComponentKicadMetadata,
|
|
3481
|
+
footprintMetadataMap: /* @__PURE__ */ new Map(),
|
|
3266
3482
|
builtTscircuitComponents: [],
|
|
3267
3483
|
extractedKicadComponents: [],
|
|
3268
3484
|
userKicadFootprints: [],
|