circuit-json-to-kicad 0.0.36 → 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 +159 -5
- 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
|
@@ -2705,6 +2705,7 @@ var ExtractFootprintsStage = class extends ConverterStage {
|
|
|
2705
2705
|
value: "Ref**",
|
|
2706
2706
|
position: [0, 0, 0],
|
|
2707
2707
|
layer: "F.SilkS",
|
|
2708
|
+
uuid: generateDeterministicUuid(`${footprintName}-property-Reference`),
|
|
2708
2709
|
effects: defaultEffects
|
|
2709
2710
|
}),
|
|
2710
2711
|
new Property({
|
|
@@ -2712,6 +2713,7 @@ var ExtractFootprintsStage = class extends ConverterStage {
|
|
|
2712
2713
|
value: "Val**",
|
|
2713
2714
|
position: [0, 0, 0],
|
|
2714
2715
|
layer: "F.Fab",
|
|
2716
|
+
uuid: generateDeterministicUuid(`${footprintName}-property-Value`),
|
|
2715
2717
|
effects: defaultEffects
|
|
2716
2718
|
}),
|
|
2717
2719
|
new Property({
|
|
@@ -2720,6 +2722,7 @@ var ExtractFootprintsStage = class extends ConverterStage {
|
|
|
2720
2722
|
position: [0, 0, 0],
|
|
2721
2723
|
layer: "F.Fab",
|
|
2722
2724
|
hidden: true,
|
|
2725
|
+
uuid: generateDeterministicUuid(`${footprintName}-property-Datasheet`),
|
|
2723
2726
|
effects: defaultEffects
|
|
2724
2727
|
}),
|
|
2725
2728
|
new Property({
|
|
@@ -2728,6 +2731,9 @@ var ExtractFootprintsStage = class extends ConverterStage {
|
|
|
2728
2731
|
position: [0, 0, 0],
|
|
2729
2732
|
layer: "F.Fab",
|
|
2730
2733
|
hidden: true,
|
|
2734
|
+
uuid: generateDeterministicUuid(
|
|
2735
|
+
`${footprintName}-property-Description`
|
|
2736
|
+
),
|
|
2731
2737
|
effects: defaultEffects
|
|
2732
2738
|
})
|
|
2733
2739
|
];
|
|
@@ -2742,9 +2748,14 @@ var ExtractFootprintsStage = class extends ConverterStage {
|
|
|
2742
2748
|
}
|
|
2743
2749
|
footprint.fpTexts = texts;
|
|
2744
2750
|
const pads = footprint.fpPads ?? [];
|
|
2745
|
-
for (
|
|
2746
|
-
pad
|
|
2747
|
-
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
|
+
}
|
|
2748
2759
|
}
|
|
2749
2760
|
footprint.fpPads = pads;
|
|
2750
2761
|
const models = footprint.models ?? [];
|
|
@@ -2945,6 +2956,117 @@ function renameKicadFootprint(params) {
|
|
|
2945
2956
|
};
|
|
2946
2957
|
}
|
|
2947
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
|
+
|
|
2948
3070
|
// lib/kicad-library/stages/ClassifyKicadFootprintsStage.ts
|
|
2949
3071
|
function classifyKicadFootprints(ctx) {
|
|
2950
3072
|
for (const extractedKicadComponent of ctx.extractedKicadComponents) {
|
|
@@ -2960,17 +3082,28 @@ function classifyFootprintsForComponent({
|
|
|
2960
3082
|
}) {
|
|
2961
3083
|
const { tscircuitComponentName, kicadFootprints } = extractedKicadComponent;
|
|
2962
3084
|
let hasAddedUserFootprint = false;
|
|
3085
|
+
const metadata = ctx.footprintMetadataMap.get(tscircuitComponentName);
|
|
2963
3086
|
for (const kicadFootprint of kicadFootprints) {
|
|
2964
3087
|
if (kicadFootprint.isBuiltin) {
|
|
2965
3088
|
addBuiltinFootprint({ ctx, kicadFootprint });
|
|
2966
3089
|
} else {
|
|
2967
3090
|
if (!hasAddedUserFootprint) {
|
|
2968
3091
|
hasAddedUserFootprint = true;
|
|
2969
|
-
|
|
3092
|
+
let renamedFootprint = renameKicadFootprint({
|
|
2970
3093
|
kicadFootprint,
|
|
2971
3094
|
newKicadFootprintName: tscircuitComponentName,
|
|
2972
3095
|
kicadLibraryName: ctx.kicadLibraryName
|
|
2973
3096
|
});
|
|
3097
|
+
if (metadata) {
|
|
3098
|
+
renamedFootprint = {
|
|
3099
|
+
...renamedFootprint,
|
|
3100
|
+
kicadModString: applyKicadFootprintMetadata(
|
|
3101
|
+
renamedFootprint.kicadModString,
|
|
3102
|
+
metadata,
|
|
3103
|
+
tscircuitComponentName
|
|
3104
|
+
)
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
2974
3107
|
addUserFootprint({ ctx, kicadFootprint: renamedFootprint });
|
|
2975
3108
|
} else {
|
|
2976
3109
|
addUserFootprint({ ctx, kicadFootprint });
|
|
@@ -3218,7 +3351,8 @@ var KicadLibraryConverter = class {
|
|
|
3218
3351
|
this.options = options;
|
|
3219
3352
|
this.ctx = createKicadLibraryConverterContext({
|
|
3220
3353
|
kicadLibraryName: options.kicadLibraryName ?? "tscircuit_library",
|
|
3221
|
-
includeBuiltins: options.includeBuiltins ?? true
|
|
3354
|
+
includeBuiltins: options.includeBuiltins ?? true,
|
|
3355
|
+
getComponentKicadMetadata: options.getComponentKicadMetadata
|
|
3222
3356
|
});
|
|
3223
3357
|
}
|
|
3224
3358
|
async run() {
|
|
@@ -3251,6 +3385,15 @@ var KicadLibraryConverter = class {
|
|
|
3251
3385
|
);
|
|
3252
3386
|
if (resolved) componentPath = resolved;
|
|
3253
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
|
+
}
|
|
3254
3397
|
const circuitJson = await this.options.buildFileToCircuitJson(
|
|
3255
3398
|
componentPath,
|
|
3256
3399
|
exportName
|
|
@@ -3272,6 +3415,15 @@ var KicadLibraryConverter = class {
|
|
|
3272
3415
|
if (resolved) componentPath = resolved;
|
|
3273
3416
|
}
|
|
3274
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
|
+
}
|
|
3275
3427
|
const circuitJson = await this.options.buildFileToCircuitJson(
|
|
3276
3428
|
componentPath,
|
|
3277
3429
|
"default"
|
|
@@ -3325,6 +3477,8 @@ function createKicadLibraryConverterContext(params) {
|
|
|
3325
3477
|
return {
|
|
3326
3478
|
kicadLibraryName: params.kicadLibraryName,
|
|
3327
3479
|
includeBuiltins: params.includeBuiltins,
|
|
3480
|
+
getComponentKicadMetadata: params.getComponentKicadMetadata,
|
|
3481
|
+
footprintMetadataMap: /* @__PURE__ */ new Map(),
|
|
3328
3482
|
builtTscircuitComponents: [],
|
|
3329
3483
|
extractedKicadComponents: [],
|
|
3330
3484
|
userKicadFootprints: [],
|