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 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 (const pad of pads) {
2746
- pad.uuid = void 0;
2747
- pad.net = void 0;
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
- const renamedFootprint = renameKicadFootprint({
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: [],
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.36",
4
+ "version": "0.0.37",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"