@tscircuit/cli 0.1.1594 → 0.1.1595

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/lib/index.js CHANGED
@@ -65850,7 +65850,7 @@ var package_default = {
65850
65850
  "circuit-json-to-3d-png": "^0.0.6",
65851
65851
  "circuit-json-to-bom-csv": "^0.0.7",
65852
65852
  "circuit-json-to-gerber": "^0.0.51",
65853
- "circuit-json-to-kicad": "0.0.153",
65853
+ "circuit-json-to-kicad": "0.0.157",
65854
65854
  "circuit-json-to-pnp-csv": "^0.0.7",
65855
65855
  "circuit-json-to-readable-netlist": "^0.0.15",
65856
65856
  "circuit-json-to-spice": "^0.0.40",
@@ -68402,11 +68402,28 @@ __export2(exports_dist, {
68402
68402
  CircuitJsonToKicadSchConverter: () => CircuitJsonToKicadSchConverter,
68403
68403
  CircuitJsonToKicadProConverter: () => CircuitJsonToKicadProConverter,
68404
68404
  CircuitJsonToKicadPcbConverter: () => CircuitJsonToKicadPcbConverter,
68405
+ CircuitJsonToKicadModConverter: () => CircuitJsonToKicadModConverter,
68405
68406
  CircuitJsonToKicadLibraryConverter: () => CircuitJsonToKicadLibraryConverter
68406
68407
  });
68407
68408
  import { cju } from "@tscircuit/circuit-json-util";
68408
68409
  import { KicadSch } from "kicadts";
68409
68410
  import { compose as compose2, scale, translate as translate2 } from "transformation-matrix";
68411
+ import {
68412
+ At,
68413
+ Color,
68414
+ Sheet,
68415
+ SheetFill,
68416
+ SheetInstancePage,
68417
+ SheetInstancePath,
68418
+ SheetInstancesForSheet,
68419
+ SheetInstancesProject,
68420
+ SheetProperty,
68421
+ SheetSize,
68422
+ Stroke,
68423
+ TextEffects,
68424
+ TextEffectsFont,
68425
+ TextEffectsJustify
68426
+ } from "kicadts";
68410
68427
  import {
68411
68428
  EmbeddedFonts,
68412
68429
  LibSymbols,
@@ -68422,36 +68439,36 @@ import {
68422
68439
  scale as createScaleMatrix,
68423
68440
  translate
68424
68441
  } from "transformation-matrix";
68425
- import { Pts, Stroke, SymbolPolyline, SymbolPolylineFill, Xy } from "kicadts";
68442
+ import { Pts, Stroke as Stroke2, SymbolPolyline, SymbolPolylineFill, Xy } from "kicadts";
68426
68443
  import { applyToPoint } from "transformation-matrix";
68427
68444
  import {
68428
- Stroke as Stroke2,
68445
+ Stroke as Stroke3,
68429
68446
  SymbolCircle,
68430
68447
  SymbolCircleCenter,
68431
68448
  SymbolCircleFill,
68432
68449
  SymbolCircleRadius
68433
68450
  } from "kicadts";
68434
68451
  import { applyToPoint as applyToPoint2 } from "transformation-matrix";
68435
- import { SymbolText, TextEffects, TextEffectsFont } from "kicadts";
68452
+ import { SymbolText, TextEffects as TextEffects2, TextEffectsFont as TextEffectsFont2 } from "kicadts";
68436
68453
  import { applyToPoint as applyToPoint3 } from "transformation-matrix";
68437
68454
  import { SymbolProperty } from "kicadts";
68438
- import { TextEffects as TextEffects2, TextEffectsFont as TextEffectsFont2 } from "kicadts";
68455
+ import { TextEffects as TextEffects3, TextEffectsFont as TextEffectsFont3 } from "kicadts";
68439
68456
  import {
68440
68457
  SchematicSymbol as SchematicSymbol3,
68441
68458
  SymbolPin,
68442
68459
  SymbolPinName,
68443
68460
  SymbolPinNumber,
68444
- TextEffects as TextEffects3,
68445
- TextEffectsFont as TextEffectsFont3
68461
+ TextEffects as TextEffects4,
68462
+ TextEffectsFont as TextEffectsFont4
68446
68463
  } from "kicadts";
68447
68464
  import { applyToPoint as applyToPoint4, scale as createScaleMatrix2 } from "transformation-matrix";
68448
68465
  import {
68449
68466
  Polyline,
68450
68467
  Pts as Pts2,
68451
68468
  SchematicText,
68452
- Stroke as Stroke3,
68453
- TextEffects as TextEffects4,
68454
- TextEffectsFont as TextEffectsFont4,
68469
+ Stroke as Stroke4,
68470
+ TextEffects as TextEffects5,
68471
+ TextEffectsFont as TextEffectsFont5,
68455
68472
  Uuid,
68456
68473
  Xy as Xy2
68457
68474
  } from "kicadts";
@@ -68464,9 +68481,9 @@ import {
68464
68481
  SymbolInstances,
68465
68482
  SymbolInstancesProject,
68466
68483
  SymbolInstancePath,
68467
- TextEffects as TextEffects5,
68468
- TextEffectsFont as TextEffectsFont5,
68469
- TextEffectsJustify,
68484
+ TextEffects as TextEffects6,
68485
+ TextEffectsFont as TextEffectsFont6,
68486
+ TextEffectsJustify as TextEffectsJustify2,
68470
68487
  GlobalLabel
68471
68488
  } from "kicadts";
68472
68489
  import { applyToPoint as applyToPoint6 } from "transformation-matrix";
@@ -68478,16 +68495,16 @@ import {
68478
68495
  SymbolInstances as SymbolInstances2,
68479
68496
  SymbolInstancesProject as SymbolInstancesProject2,
68480
68497
  SymbolInstancePath as SymbolInstancePath2,
68481
- TextEffects as TextEffects6,
68482
- TextEffectsFont as TextEffectsFont6,
68483
- TextEffectsJustify as TextEffectsJustify2,
68498
+ TextEffects as TextEffects7,
68499
+ TextEffectsFont as TextEffectsFont7,
68500
+ TextEffectsJustify as TextEffectsJustify3,
68484
68501
  EmbeddedFonts as EmbeddedFonts2,
68485
68502
  SymbolPinNames as SymbolPinNames2,
68486
68503
  SymbolPinNumbers as SymbolPinNumbers2
68487
68504
  } from "kicadts";
68488
68505
  import { applyToPoint as applyToPoint7 } from "transformation-matrix";
68489
68506
  import { symbols as symbols3 } from "schematic-symbols";
68490
- import { Wire, Pts as Pts3, Xy as Xy3, Stroke as Stroke4, Junction } from "kicadts";
68507
+ import { Wire, Pts as Pts3, Xy as Xy3, Stroke as Stroke5, Junction } from "kicadts";
68491
68508
  import { applyToPoint as applyToPoint8 } from "transformation-matrix";
68492
68509
  import {
68493
68510
  SheetInstances,
@@ -68981,28 +68998,28 @@ import {
68981
68998
  parseKicadSexpr,
68982
68999
  KicadPcb,
68983
69000
  FootprintModel,
68984
- At,
69001
+ At as At2,
68985
69002
  EmbeddedFonts as EmbeddedFonts4,
68986
69003
  FootprintAttr,
68987
69004
  Property,
68988
- TextEffects as TextEffects7,
68989
- TextEffectsFont as TextEffectsFont7
69005
+ TextEffects as TextEffects8,
69006
+ TextEffectsFont as TextEffectsFont8
68990
69007
  } from "kicadts";
68991
69008
  import { applyToPoint as applyToPoint17 } from "transformation-matrix";
68992
69009
  import {
68993
69010
  Property as Property2,
68994
- TextEffects as TextEffects8,
68995
- TextEffectsFont as TextEffectsFont8,
69011
+ TextEffects as TextEffects9,
69012
+ TextEffectsFont as TextEffectsFont9,
68996
69013
  EmbeddedFonts as EmbeddedFonts5,
68997
69014
  FootprintModel as FootprintModel2,
68998
69015
  FootprintAttr as FootprintAttr2
68999
69016
  } from "kicadts";
69000
- import { FpCircle, Stroke as Stroke5 } from "kicadts";
69001
- import { FpCircle as FpCircle2, Stroke as Stroke6 } from "kicadts";
69002
- import { FpRect, Stroke as Stroke7 } from "kicadts";
69003
- import { FpRect as FpRect2, Stroke as Stroke8 } from "kicadts";
69004
- import { FpRect as FpRect3, Stroke as Stroke9 } from "kicadts";
69005
- import { FpPoly, Pts as Pts5, Stroke as Stroke10, Xy as Xy5 } from "kicadts";
69017
+ import { FpCircle, Stroke as Stroke6 } from "kicadts";
69018
+ import { FpCircle as FpCircle2, Stroke as Stroke7 } from "kicadts";
69019
+ import { FpRect, Stroke as Stroke8 } from "kicadts";
69020
+ import { FpRect as FpRect2, Stroke as Stroke9 } from "kicadts";
69021
+ import { FpRect as FpRect3, Stroke as Stroke10 } from "kicadts";
69022
+ import { FpPoly, Pts as Pts5, Stroke as Stroke11, Xy as Xy5 } from "kicadts";
69006
69023
  import {
69007
69024
  applyToPoint as applyToPoint10,
69008
69025
  compose as compose4,
@@ -69011,11 +69028,11 @@ import {
69011
69028
  translate as translate4
69012
69029
  } from "transformation-matrix";
69013
69030
  import"kicadts";
69014
- import { FpText, TextEffects as TextEffects9, TextEffectsFont as TextEffectsFont9 } from "kicadts";
69031
+ import { FpText, TextEffects as TextEffects10, TextEffectsFont as TextEffectsFont10 } from "kicadts";
69015
69032
  import { applyToPoint as applyToPoint11, rotate as rotate3, identity } from "transformation-matrix";
69016
- import { FpLine, Stroke as Stroke11 } from "kicadts";
69033
+ import { FpLine, Stroke as Stroke12 } from "kicadts";
69017
69034
  import { applyToPoint as applyToPoint12, identity as identity2, rotate as rotate4 } from "transformation-matrix";
69018
- import { FpText as FpText3, TextEffects as TextEffects10, TextEffectsFont as TextEffectsFont10 } from "kicadts";
69035
+ import { FpText as FpText3, TextEffects as TextEffects11, TextEffectsFont as TextEffectsFont11 } from "kicadts";
69019
69036
  import { applyToPoint as applyToPoint13, rotate as rotate5, identity as identity3 } from "transformation-matrix";
69020
69037
  import { FootprintModel as FootprintModel3 } from "kicadts";
69021
69038
  import {
@@ -69046,20 +69063,20 @@ import { Footprint as Footprint4 } from "kicadts";
69046
69063
  import { applyToPoint as applyToPoint20 } from "transformation-matrix";
69047
69064
  import { GrCircle, GrLine, GrPoly } from "kicadts";
69048
69065
  import {
69049
- At as At2,
69066
+ At as At3,
69050
69067
  GrText,
69051
- TextEffects as TextEffects11,
69052
- TextEffectsFont as TextEffectsFont11,
69053
- TextEffectsJustify as TextEffectsJustify3
69068
+ TextEffects as TextEffects12,
69069
+ TextEffectsFont as TextEffectsFont12,
69070
+ TextEffectsJustify as TextEffectsJustify4
69054
69071
  } from "kicadts";
69055
69072
  import { applyToPoint as applyToPoint21 } from "transformation-matrix";
69056
69073
  import { applyToPoint as applyToPoint23, rotate as rotate9 } from "transformation-matrix";
69057
69074
  import {
69058
69075
  GrText as GrText2,
69059
- TextEffects as TextEffects12,
69060
- TextEffectsFont as TextEffectsFont12,
69061
- TextEffectsJustify as TextEffectsJustify4,
69062
- At as At3
69076
+ TextEffects as TextEffects13,
69077
+ TextEffectsFont as TextEffectsFont13,
69078
+ TextEffectsJustify as TextEffectsJustify5,
69079
+ At as At4
69063
69080
  } from "kicadts";
69064
69081
  import { applyToPoint as applyToPoint22 } from "transformation-matrix";
69065
69082
  import { cju as cju3 } from "@tscircuit/circuit-json-util";
@@ -69071,8 +69088,8 @@ import {
69071
69088
  parseKicadSexpr as parseKicadSexpr3,
69072
69089
  Footprint as Footprint5,
69073
69090
  Property as Property3,
69074
- TextEffects as TextEffects13,
69075
- TextEffectsFont as TextEffectsFont13
69091
+ TextEffects as TextEffects14,
69092
+ TextEffectsFont as TextEffectsFont14
69076
69093
  } from "kicadts";
69077
69094
  import { parseKicadMod as parseKicadMod2 } from "kicadts";
69078
69095
  import {
@@ -69080,11 +69097,89 @@ import {
69080
69097
  SymbolPinNames as SymbolPinNames3,
69081
69098
  SymbolPinNumbers as SymbolPinNumbers3,
69082
69099
  SymbolProperty as SymbolProperty4,
69083
- TextEffects as TextEffects14,
69084
- TextEffectsFont as TextEffectsFont14,
69085
- TextEffectsJustify as TextEffectsJustify5
69100
+ TextEffects as TextEffects15,
69101
+ TextEffectsFont as TextEffectsFont15,
69102
+ TextEffectsJustify as TextEffectsJustify6
69086
69103
  } from "kicadts";
69087
69104
  import { KicadSymbolLib as KicadSymbolLib2 } from "kicadts";
69105
+ var BOX_WIDTH = 40;
69106
+ var BOX_HEIGHT = 25;
69107
+ var GUTTER_X = 20;
69108
+ var GUTTER_Y = 30;
69109
+ var MARGIN = 25.4;
69110
+ var PROPERTY_FONT_SIZE = 1.524;
69111
+ var SHEET_BORDER_WIDTH = 0.1524;
69112
+ function createSheetPropertyEffects(vertical) {
69113
+ const font = new TextEffectsFont;
69114
+ font.size = { height: PROPERTY_FONT_SIZE, width: PROPERTY_FONT_SIZE };
69115
+ return new TextEffects({
69116
+ font,
69117
+ justify: new TextEffectsJustify({ horizontal: "left", vertical })
69118
+ });
69119
+ }
69120
+ function buildSheetNode(entry, rootUuid, x, y) {
69121
+ const stroke = new Stroke;
69122
+ stroke.width = SHEET_BORDER_WIDTH;
69123
+ stroke.type = "solid";
69124
+ const fill = new SheetFill;
69125
+ fill.color = new Color([0, 0, 0, 0]);
69126
+ const sheetnameProperty = new SheetProperty({
69127
+ key: "Sheetname",
69128
+ value: entry.sheetName,
69129
+ id: 0,
69130
+ at: At.from([x, y - 0.7, 0]),
69131
+ effects: createSheetPropertyEffects("bottom")
69132
+ });
69133
+ const sheetfileProperty = new SheetProperty({
69134
+ key: "Sheetfile",
69135
+ value: entry.filename,
69136
+ id: 1,
69137
+ at: At.from([x, y + BOX_HEIGHT + 0.7, 0]),
69138
+ effects: createSheetPropertyEffects("top")
69139
+ });
69140
+ const instancePath = new SheetInstancePath(`/${rootUuid}`);
69141
+ instancePath.pages = [new SheetInstancePage(entry.pageNumber)];
69142
+ const instancesProject = new SheetInstancesProject("");
69143
+ instancesProject.paths = [instancePath];
69144
+ const instances = new SheetInstancesForSheet;
69145
+ instances.projects = [instancesProject];
69146
+ return new Sheet({
69147
+ position: [x, y],
69148
+ size: new SheetSize(BOX_WIDTH, BOX_HEIGHT),
69149
+ excludeFromSim: false,
69150
+ inBom: true,
69151
+ onBoard: true,
69152
+ dnp: false,
69153
+ fieldsAutoplaced: true,
69154
+ stroke,
69155
+ fill,
69156
+ uuid: entry.sheetNodeUuid,
69157
+ properties: [sheetnameProperty, sheetfileProperty],
69158
+ instances
69159
+ });
69160
+ }
69161
+ function buildChildSheetNodes(children, rootUuid) {
69162
+ const count = children.length;
69163
+ const cols = Math.max(1, Math.ceil(Math.sqrt(count)));
69164
+ const rows = Math.max(1, Math.ceil(count / cols));
69165
+ const nodes = [];
69166
+ for (let index = 0;index < children.length; index++) {
69167
+ const col = index % cols;
69168
+ const row = Math.floor(index / cols);
69169
+ const x = MARGIN + col * (BOX_WIDTH + GUTTER_X);
69170
+ const y = MARGIN + row * (BOX_HEIGHT + GUTTER_Y);
69171
+ nodes.push(buildSheetNode(children[index], rootUuid, x, y));
69172
+ }
69173
+ const spanW = cols * BOX_WIDTH + (cols - 1) * GUTTER_X;
69174
+ const spanH = rows * BOX_HEIGHT + (rows - 1) * GUTTER_Y;
69175
+ return {
69176
+ nodes,
69177
+ extentMm: {
69178
+ width: 2 * MARGIN + spanW,
69179
+ height: 2 * MARGIN + spanH
69180
+ }
69181
+ };
69182
+ }
69088
69183
  function getSchematicBoundsAndCenter(db) {
69089
69184
  const schematicComponents = db.schematic_component.list();
69090
69185
  const schematicTraces = db.schematic_trace.list();
@@ -69129,6 +69224,86 @@ function getSchematicBoundsAndCenter(db) {
69129
69224
  }
69130
69225
  };
69131
69226
  }
69227
+ function isSchematicElement(el) {
69228
+ return typeof el.type === "string" && el.type.startsWith("schematic_");
69229
+ }
69230
+ function keepElementForSheet(el, sheetId, componentIdsOnSheet) {
69231
+ if (!isSchematicElement(el))
69232
+ return true;
69233
+ if (el.type === "schematic_sheet")
69234
+ return false;
69235
+ const hasSheetIdField = "schematic_sheet_id" in el;
69236
+ const hasComponentIdField = "schematic_component_id" in el;
69237
+ if (!hasSheetIdField && !hasComponentIdField)
69238
+ return true;
69239
+ if ((el.schematic_sheet_id ?? null) === sheetId)
69240
+ return true;
69241
+ return el.schematic_component_id != null && componentIdsOnSheet.has(el.schematic_component_id);
69242
+ }
69243
+ function partitionCircuitJsonBySheet(circuitJson, sheetId) {
69244
+ const elements = circuitJson;
69245
+ const componentIdsOnSheet = /* @__PURE__ */ new Set;
69246
+ for (const el of elements) {
69247
+ if (el.type !== "schematic_component")
69248
+ continue;
69249
+ if ((el.schematic_sheet_id ?? null) === sheetId) {
69250
+ componentIdsOnSheet.add(el.schematic_component_id);
69251
+ }
69252
+ }
69253
+ const subset = [];
69254
+ for (const el of elements) {
69255
+ if (keepElementForSheet(el, sheetId, componentIdsOnSheet)) {
69256
+ subset.push(el);
69257
+ }
69258
+ }
69259
+ return subset;
69260
+ }
69261
+ var DEFAULT_ROOT_FILENAME = "schematic.kicad_sch";
69262
+ function toFileBaseName(sheetName, fallbackIndex) {
69263
+ const baseName = sheetName.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
69264
+ return baseName.length > 0 ? baseName : `sheet_${fallbackIndex + 1}`;
69265
+ }
69266
+ function buildSchematicSheetPlan(circuitJson) {
69267
+ const rootUuid = crypto.randomUUID();
69268
+ const root = {
69269
+ schematicSheetId: null,
69270
+ sheetName: "Root",
69271
+ fileBaseName: "root",
69272
+ filename: DEFAULT_ROOT_FILENAME,
69273
+ pageNumber: "1",
69274
+ fileUuid: rootUuid
69275
+ };
69276
+ const schematicSheets = circuitJson.filter((el) => el.type === "schematic_sheet").slice().sort((a, b) => (a.sheet_index ?? 0) - (b.sheet_index ?? 0));
69277
+ const usedFileBaseNames = /* @__PURE__ */ new Set(["root"]);
69278
+ const children = [];
69279
+ for (let index = 0;index < schematicSheets.length; index++) {
69280
+ const sheet = schematicSheets[index];
69281
+ const sheetName = sheet.display_name ?? sheet.name ?? `Sheet ${index + 1}`;
69282
+ let fileBaseName = toFileBaseName(sheet.name ?? sheetName, index);
69283
+ if (usedFileBaseNames.has(fileBaseName)) {
69284
+ let suffix = 2;
69285
+ while (usedFileBaseNames.has(`${fileBaseName}_${suffix}`))
69286
+ suffix++;
69287
+ fileBaseName = `${fileBaseName}_${suffix}`;
69288
+ }
69289
+ usedFileBaseNames.add(fileBaseName);
69290
+ children.push({
69291
+ schematicSheetId: sheet.schematic_sheet_id,
69292
+ sheetName,
69293
+ fileBaseName,
69294
+ filename: `${fileBaseName}.kicad_sch`,
69295
+ pageNumber: `${index + 2}`,
69296
+ sheetNodeUuid: crypto.randomUUID(),
69297
+ fileUuid: crypto.randomUUID()
69298
+ });
69299
+ }
69300
+ return {
69301
+ rootUuid,
69302
+ root,
69303
+ children,
69304
+ isHierarchical: children.length > 0
69305
+ };
69306
+ }
69132
69307
  var PAPER_SIZES = [
69133
69308
  { name: "A4", width: 297, height: 210 },
69134
69309
  { name: "A3", width: 420, height: 297 },
@@ -69402,7 +69577,7 @@ function createPolylineFromPoints({
69402
69577
  });
69403
69578
  const pts = new Pts(xyPoints);
69404
69579
  polyline.points = pts;
69405
- const stroke = new Stroke;
69580
+ const stroke = new Stroke2;
69406
69581
  stroke.width = 0.254;
69407
69582
  stroke.type = "default";
69408
69583
  polyline.stroke = stroke;
@@ -69424,7 +69599,7 @@ function createCircleFromPrimitive({
69424
69599
  const c = circle;
69425
69600
  c._sxCenter = new SymbolCircleCenter(scaledPos.x, scaledPos.y);
69426
69601
  c._sxRadius = new SymbolCircleRadius(primitive.radius * scale5);
69427
- const stroke = new Stroke2;
69602
+ const stroke = new Stroke3;
69428
69603
  stroke.width = 0.254;
69429
69604
  stroke.type = "default";
69430
69605
  c._sxStroke = stroke;
@@ -69449,9 +69624,9 @@ function createTextFromPrimitive({
69449
69624
  symbolText.value = schText.text;
69450
69625
  symbolText.at = [scaledPos.x, scaledPos.y, 0];
69451
69626
  const scaledFontSize = schText.fontSize * scale5;
69452
- const font = new TextEffectsFont;
69627
+ const font = new TextEffectsFont2;
69453
69628
  font.size = { height: scaledFontSize, width: scaledFontSize };
69454
- symbolText.effects = new TextEffects({ font });
69629
+ symbolText.effects = new TextEffects2({ font });
69455
69630
  return symbolText;
69456
69631
  }
69457
69632
  function createDrawingSubsymbol({
@@ -69535,9 +69710,9 @@ function createGenericChipSymbolData(schematicComp, db) {
69535
69710
  };
69536
69711
  }
69537
69712
  function createTextEffects(size, hide) {
69538
- const font = new TextEffectsFont2;
69713
+ const font = new TextEffectsFont3;
69539
69714
  font.size = { height: size, width: size };
69540
- return new TextEffects2({
69715
+ return new TextEffects3({
69541
69716
  font,
69542
69717
  hiddenText: hide
69543
69718
  });
@@ -69721,14 +69896,14 @@ function createPinSubsymbol({
69721
69896
  });
69722
69897
  pin.at = [x, y, angle];
69723
69898
  pin.length = isChip ? CHIP_PIN_LENGTH : CUSTOM_SYMBOL_PIN_LENGTH;
69724
- const nameFont = new TextEffectsFont3;
69899
+ const nameFont = new TextEffectsFont4;
69725
69900
  nameFont.size = { height: 1.27, width: 1.27 };
69726
- const nameEffects = new TextEffects3({ font: nameFont });
69901
+ const nameEffects = new TextEffects4({ font: nameFont });
69727
69902
  const pinName = port.labels?.[0] || "~";
69728
69903
  pin._sxName = new SymbolPinName({ value: pinName, effects: nameEffects });
69729
- const numFont = new TextEffectsFont3;
69904
+ const numFont = new TextEffectsFont4;
69730
69905
  numFont.size = { height: 1.27, width: 1.27 };
69731
- const numEffects = new TextEffects3({ font: numFont });
69906
+ const numEffects = new TextEffects4({ font: numFont });
69732
69907
  const pinNum = port.pinNumber?.toString() || `${i + 1}`;
69733
69908
  pin._sxNumber = new SymbolPinNumber({
69734
69909
  value: pinNum,
@@ -70074,7 +70249,7 @@ var AddSchematicGraphicsStage = class extends ConverterStage {
70074
70249
  new Xy2(start.x, start.y),
70075
70250
  new Xy2(end.x, end.y)
70076
70251
  ]);
70077
- const stroke = new Stroke3;
70252
+ const stroke = new Stroke4;
70078
70253
  stroke.width = 0;
70079
70254
  stroke.type = "default";
70080
70255
  stroke.color = DEFAULT_SECTION_LINE_COLOR;
@@ -70095,13 +70270,13 @@ var AddSchematicGraphicsStage = class extends ConverterStage {
70095
70270
  x: (text.position?.x ?? 0) + DEFAULT_SECTION_TEXT_PADDING_X_MM,
70096
70271
  y: sourceY
70097
70272
  });
70098
- const font = new TextEffectsFont4;
70273
+ const font = new TextEffectsFont5;
70099
70274
  font.size = {
70100
70275
  height: DEFAULT_SECTION_TEXT_SIZE_MM,
70101
70276
  width: DEFAULT_SECTION_TEXT_SIZE_MM
70102
70277
  };
70103
70278
  font.color = DEFAULT_SECTION_TEXT_COLOR;
70104
- const effects = new TextEffects4({
70279
+ const effects = new TextEffects5({
70105
70280
  font,
70106
70281
  hiddenText: false
70107
70282
  });
@@ -70230,7 +70405,8 @@ var AddSchematicNetLabelsStage = class extends ConverterStage {
70230
70405
  const { kicadSch } = this.ctx;
70231
70406
  const instances = new SymbolInstances;
70232
70407
  const project = new SymbolInstancesProject("");
70233
- const path7 = new SymbolInstancePath(`/${kicadSch?.uuid?.value || ""}`);
70408
+ const instancePathPrefix = this.ctx.symbolInstancePathPrefix ?? `/${kicadSch?.uuid?.value || ""}`;
70409
+ const path7 = new SymbolInstancePath(instancePathPrefix);
70234
70410
  path7.reference = labelText;
70235
70411
  path7.unit = 1;
70236
70412
  project.paths.push(path7);
@@ -70271,7 +70447,7 @@ var AddSchematicNetLabelsStage = class extends ConverterStage {
70271
70447
  const orientation = orientationMap[anchorSide] || orientationMap["left"];
70272
70448
  const effects = this.createTextEffects(1.27, false);
70273
70449
  if (Object.keys(orientation.justify).length > 0) {
70274
- effects.justify = new TextEffectsJustify(orientation.justify);
70450
+ effects.justify = new TextEffectsJustify2(orientation.justify);
70275
70451
  }
70276
70452
  const globalLabel = new GlobalLabel({
70277
70453
  value: labelText,
@@ -70284,9 +70460,9 @@ var AddSchematicNetLabelsStage = class extends ConverterStage {
70284
70460
  return globalLabel;
70285
70461
  }
70286
70462
  createTextEffects(size, hide = false) {
70287
- const font = new TextEffectsFont5;
70463
+ const font = new TextEffectsFont6;
70288
70464
  font.size = { height: size, width: size };
70289
- return new TextEffects5({
70465
+ return new TextEffects6({
70290
70466
  font,
70291
70467
  hiddenText: hide
70292
70468
  });
@@ -70477,7 +70653,8 @@ var AddSchematicSymbolsStage = class extends ConverterStage {
70477
70653
  }
70478
70654
  const instances = new SymbolInstances2;
70479
70655
  const project = new SymbolInstancesProject2("");
70480
- const path7 = new SymbolInstancePath2(`/${kicadSch?.uuid?.value || ""}`);
70656
+ const instancePathPrefix = this.ctx.symbolInstancePathPrefix ?? `/${kicadSch?.uuid?.value || ""}`;
70657
+ const path7 = new SymbolInstancePath2(instancePathPrefix);
70481
70658
  path7.reference = reference;
70482
70659
  path7.unit = 1;
70483
70660
  project.paths.push(path7);
@@ -70652,10 +70829,10 @@ var AddSchematicSymbolsStage = class extends ConverterStage {
70652
70829
  };
70653
70830
  }
70654
70831
  createTextEffects(size, hide = false, justify) {
70655
- const font = new TextEffectsFont6;
70832
+ const font = new TextEffectsFont7;
70656
70833
  font.size = { height: size, width: size };
70657
- const justifyObj = justify ? new TextEffectsJustify2({ horizontal: justify }) : undefined;
70658
- const effects = new TextEffects6({
70834
+ const justifyObj = justify ? new TextEffectsJustify3({ horizontal: justify }) : undefined;
70835
+ const effects = new TextEffects7({
70659
70836
  font,
70660
70837
  hiddenText: hide,
70661
70838
  justify: justifyObj
@@ -70716,7 +70893,7 @@ var AddSchematicTracesStage = class extends ConverterStage {
70716
70893
  const y2 = to.y;
70717
70894
  const pts = new Pts3([new Xy3(x1, y1), new Xy3(x2, y2)]);
70718
70895
  wire.points = pts;
70719
- const stroke = new Stroke4;
70896
+ const stroke = new Stroke5;
70720
70897
  stroke.width = DEFAULT_LINE_WIDTH_MM;
70721
70898
  stroke.type = "default";
70722
70899
  wire.stroke = stroke;
@@ -70772,7 +70949,7 @@ var InitializeSchematicStage = class extends ConverterStage {
70772
70949
  const paper = new Paper;
70773
70950
  paper.size = schematicPaperSize?.name ?? "A4";
70774
70951
  kicadSch.paper = paper;
70775
- kicadSch.uuid = new Uuid4(crypto.randomUUID());
70952
+ kicadSch.uuid = new Uuid4(this.ctx.schematicFileUuid ?? crypto.randomUUID());
70776
70953
  this.finished = true;
70777
70954
  }
70778
70955
  getOutput() {
@@ -70780,15 +70957,22 @@ var InitializeSchematicStage = class extends ConverterStage {
70780
70957
  }
70781
70958
  };
70782
70959
  var DEFAULT_SCHEMATIC_SCALE_FACTOR = 15;
70960
+ var DEFAULT_PAPER_PADDING_MM = 20;
70783
70961
  var CircuitJsonToKicadSchConverter = class {
70784
70962
  ctx;
70785
70963
  pipeline;
70786
70964
  currentStageIndex = 0;
70787
70965
  finished = false;
70966
+ circuitJson;
70967
+ schematicSheetPlan;
70968
+ files = [];
70969
+ built = false;
70788
70970
  get currentStage() {
70789
70971
  return this.pipeline[this.currentStageIndex];
70790
70972
  }
70791
70973
  constructor(circuitJson) {
70974
+ this.circuitJson = circuitJson;
70975
+ this.schematicSheetPlan = buildSchematicSheetPlan(circuitJson);
70792
70976
  const kicadSchematicScaleFactor = DEFAULT_SCHEMATIC_SCALE_FACTOR;
70793
70977
  const db = cju(circuitJson);
70794
70978
  const { center, bounds } = getSchematicBoundsAndCenter(db);
@@ -70819,6 +71003,11 @@ var CircuitJsonToKicadSchConverter = class {
70819
71003
  ];
70820
71004
  }
70821
71005
  step() {
71006
+ if (this.schematicSheetPlan.isHierarchical) {
71007
+ this.buildAll();
71008
+ this.finished = true;
71009
+ return;
71010
+ }
70822
71011
  if (!this.currentStage) {
70823
71012
  this.finished = true;
70824
71013
  return;
@@ -70834,11 +71023,112 @@ var CircuitJsonToKicadSchConverter = class {
70834
71023
  }
70835
71024
  }
70836
71025
  getOutput() {
71026
+ if (this.schematicSheetPlan.isHierarchical) {
71027
+ this.buildAll();
71028
+ return this.files[0].kicadSch;
71029
+ }
70837
71030
  return this.ctx.kicadSch;
70838
71031
  }
70839
71032
  getOutputString() {
71033
+ if (this.schematicSheetPlan.isHierarchical) {
71034
+ this.buildAll();
71035
+ return this.files[0].content;
71036
+ }
70840
71037
  return this.ctx.kicadSch.getString();
70841
71038
  }
71039
+ getOutputFiles(options) {
71040
+ if (!this.schematicSheetPlan.isHierarchical) {
71041
+ return [
71042
+ {
71043
+ filename: options.schematicFilename,
71044
+ content: this.getOutputString()
71045
+ }
71046
+ ];
71047
+ }
71048
+ this.buildAll();
71049
+ return this.files.map((file, index) => ({
71050
+ filename: index === 0 ? options.schematicFilename : file.entry.filename,
71051
+ content: file.content
71052
+ }));
71053
+ }
71054
+ buildAll() {
71055
+ if (this.built)
71056
+ return;
71057
+ this.built = true;
71058
+ const { rootUuid, root, children } = this.schematicSheetPlan;
71059
+ const { nodes: childSheetNodes, extentMm } = buildChildSheetNodes(children, rootUuid);
71060
+ const rootSch = this.buildSheetFile({
71061
+ circuitJson: partitionCircuitJsonBySheet(this.circuitJson, null),
71062
+ fileUuid: rootUuid,
71063
+ symbolInstancePathPrefix: `/${rootUuid}`,
71064
+ emitSheetInstances: true,
71065
+ childSheetNodes,
71066
+ extraPaperExtentMm: extentMm
71067
+ });
71068
+ this.files.push({
71069
+ entry: root,
71070
+ kicadSch: rootSch,
71071
+ content: rootSch.getString()
71072
+ });
71073
+ for (const child of children) {
71074
+ const childSch = this.buildSheetFile({
71075
+ circuitJson: partitionCircuitJsonBySheet(this.circuitJson, child.schematicSheetId),
71076
+ fileUuid: child.fileUuid,
71077
+ symbolInstancePathPrefix: `/${rootUuid}/${child.sheetNodeUuid}`,
71078
+ emitSheetInstances: false
71079
+ });
71080
+ this.files.push({
71081
+ entry: child,
71082
+ kicadSch: childSch,
71083
+ content: childSch.getString()
71084
+ });
71085
+ }
71086
+ }
71087
+ buildSheetFile(options) {
71088
+ const {
71089
+ circuitJson,
71090
+ fileUuid,
71091
+ symbolInstancePathPrefix,
71092
+ emitSheetInstances,
71093
+ childSheetNodes,
71094
+ extraPaperExtentMm
71095
+ } = options;
71096
+ const kicadSchematicScaleFactor = DEFAULT_SCHEMATIC_SCALE_FACTOR;
71097
+ const db = cju(circuitJson);
71098
+ const { center, bounds } = getSchematicBoundsAndCenter(db);
71099
+ const paperSize = selectSchematicPaperSize(Math.max((bounds.maxX - bounds.minX) * kicadSchematicScaleFactor + 2 * DEFAULT_PAPER_PADDING_MM, extraPaperExtentMm?.width ?? 0), Math.max((bounds.maxY - bounds.minY) * kicadSchematicScaleFactor + 2 * DEFAULT_PAPER_PADDING_MM, extraPaperExtentMm?.height ?? 0), 0);
71100
+ const ctx = {
71101
+ db,
71102
+ circuitJson,
71103
+ kicadSch: new KicadSch({
71104
+ generator: "circuit-json-to-kicad",
71105
+ generatorVersion: "0.0.1"
71106
+ }),
71107
+ kicadSchematicScaleFactor,
71108
+ schematicPaperSize: paperSize,
71109
+ c2kMatSch: compose2(translate2(paperSize.width / 2, paperSize.height / 2), scale(kicadSchematicScaleFactor, -kicadSchematicScaleFactor), translate2(-center.x, -center.y)),
71110
+ schematicFileUuid: fileUuid,
71111
+ symbolInstancePathPrefix
71112
+ };
71113
+ const stages = [
71114
+ new InitializeSchematicStage(circuitJson, ctx),
71115
+ new AddLibrarySymbolsStage(circuitJson, ctx),
71116
+ new AddSchematicSymbolsStage(circuitJson, ctx),
71117
+ new AddSchematicNetLabelsStage(circuitJson, ctx),
71118
+ new AddSchematicTracesStage(circuitJson, ctx),
71119
+ new AddSchematicGraphicsStage(circuitJson, ctx)
71120
+ ];
71121
+ if (emitSheetInstances) {
71122
+ stages.push(new AddSheetInstancesStage(circuitJson, ctx));
71123
+ }
71124
+ for (const stage of stages)
71125
+ stage.runUntilFinished();
71126
+ const kicadSch = ctx.kicadSch;
71127
+ if (childSheetNodes && childSheetNodes.length > 0) {
71128
+ kicadSch.sheets = childSheetNodes;
71129
+ }
71130
+ return kicadSch;
71131
+ }
70842
71132
  };
70843
71133
  var circuitJsonLayerToKicadLayer = {
70844
71134
  top: "F.Cu",
@@ -70855,6 +71145,17 @@ function getKicadLayer(circuitJsonLayer) {
70855
71145
  return "F.Cu";
70856
71146
  return circuitJsonLayerToKicadLayer[circuitJsonLayer] || circuitJsonLayer || "F.Cu";
70857
71147
  }
71148
+ function getKicadCopperLayerIndex(layerName, numLayers) {
71149
+ if (layerName === "F.Cu")
71150
+ return 0;
71151
+ if (layerName === "B.Cu")
71152
+ return 31;
71153
+ const match = layerName.match(/^In(\d+)\.Cu$/);
71154
+ if (match?.[1]) {
71155
+ return parseInt(match[1], 10);
71156
+ }
71157
+ return 0;
71158
+ }
70858
71159
  function getViaLayers(numLayers) {
70859
71160
  const layers = ["F.Cu"];
70860
71161
  for (let i = 1;i < numLayers - 1; i++) {
@@ -70863,6 +71164,26 @@ function getViaLayers(numLayers) {
70863
71164
  layers.push("B.Cu");
70864
71165
  return layers;
70865
71166
  }
71167
+ function getViaLayerSpan(kicadLayers, numLayers) {
71168
+ if (kicadLayers.length <= 1)
71169
+ return kicadLayers;
71170
+ let top = kicadLayers[0];
71171
+ let bottom = kicadLayers[0];
71172
+ let topIndex = getKicadCopperLayerIndex(top, numLayers);
71173
+ let bottomIndex = topIndex;
71174
+ for (const layer of kicadLayers) {
71175
+ const index = getKicadCopperLayerIndex(layer, numLayers);
71176
+ if (index < topIndex) {
71177
+ topIndex = index;
71178
+ top = layer;
71179
+ }
71180
+ if (index > bottomIndex) {
71181
+ bottomIndex = index;
71182
+ bottom = layer;
71183
+ }
71184
+ }
71185
+ return top === bottom ? [top] : [top, bottom];
71186
+ }
70866
71187
  function simpleHash(str) {
70867
71188
  let hash = 0;
70868
71189
  for (let i = 0;i < str.length; i++) {
@@ -71243,7 +71564,7 @@ var ExtractFootprintsStage = class extends ConverterStage {
71243
71564
  const footprintName = (parts.length > 1 ? parts[1] : parts[0])?.replace(/[\\\/]/g, "-").trim() || "footprint";
71244
71565
  const isBuiltin = !customFootprintNames.has(footprintName);
71245
71566
  footprint.libraryLink = footprintName;
71246
- footprint.position = At.from([0, 0, 0]);
71567
+ footprint.position = At2.from([0, 0, 0]);
71247
71568
  footprint.locked = false;
71248
71569
  footprint.placed = false;
71249
71570
  footprint.version = KICAD_FP_VERSION;
@@ -71272,10 +71593,10 @@ var ExtractFootprintsStage = class extends ConverterStage {
71272
71593
  footprint.path = undefined;
71273
71594
  footprint.sheetfile = undefined;
71274
71595
  footprint.sheetname = undefined;
71275
- const defaultFont = new TextEffectsFont7;
71596
+ const defaultFont = new TextEffectsFont8;
71276
71597
  defaultFont.size = { width: 1.27, height: 1.27 };
71277
71598
  defaultFont.thickness = 0.15;
71278
- const defaultEffects = new TextEffects7({ font: defaultFont });
71599
+ const defaultEffects = new TextEffects8({ font: defaultFont });
71279
71600
  const fpPads = footprint.fpPads ?? [];
71280
71601
  let minY = 0;
71281
71602
  let maxY = 0;
@@ -71391,7 +71712,7 @@ var ExtractFootprintsStage = class extends ConverterStage {
71391
71712
  }
71392
71713
  };
71393
71714
  function createTextEffects2(metadataEffects) {
71394
- const font = new TextEffectsFont8;
71715
+ const font = new TextEffectsFont9;
71395
71716
  if (metadataEffects?.font?.size) {
71396
71717
  font.size = {
71397
71718
  width: Number(metadataEffects.font.size.x),
@@ -71405,7 +71726,7 @@ function createTextEffects2(metadataEffects) {
71405
71726
  } else {
71406
71727
  font.thickness = 0.15;
71407
71728
  }
71408
- return new TextEffects8({ font });
71729
+ return new TextEffects9({ font });
71409
71730
  }
71410
71731
  function applyMetadataToFootprint({
71411
71732
  footprint,
@@ -71620,7 +71941,7 @@ function convertSilkscreenCircles(silkscreenCircles, componentCenter) {
71620
71941
  center: { x: relX, y: relY },
71621
71942
  end: { x: relX + circle.radius, y: relY },
71622
71943
  layer: kicadLayer,
71623
- stroke: new Stroke5,
71944
+ stroke: new Stroke6,
71624
71945
  fill: false
71625
71946
  });
71626
71947
  if (fpCircle.stroke) {
@@ -71645,7 +71966,7 @@ function convertCourtyardCircles(courtyardCircles, componentCenter) {
71645
71966
  center: { x: relX, y: relY },
71646
71967
  end: { x: relX + circle.radius, y: relY },
71647
71968
  layer: kicadLayer,
71648
- stroke: new Stroke6,
71969
+ stroke: new Stroke7,
71649
71970
  fill: false
71650
71971
  });
71651
71972
  if (fpCircle.stroke) {
@@ -71672,7 +71993,7 @@ function convertFabricationNoteRects(fabRects, componentCenter) {
71672
71993
  start: { x: relX - halfW, y: relY - halfH },
71673
71994
  end: { x: relX + halfW, y: relY + halfH },
71674
71995
  layer: kicadLayer,
71675
- stroke: new Stroke7,
71996
+ stroke: new Stroke8,
71676
71997
  fill: false
71677
71998
  });
71678
71999
  if (fpRect.stroke) {
@@ -71695,7 +72016,7 @@ function convertNoteRects(noteRects, componentCenter) {
71695
72016
  start: { x: relX - halfW, y: relY - halfH },
71696
72017
  end: { x: relX + halfW, y: relY + halfH },
71697
72018
  layer: kicadLayer,
71698
- stroke: new Stroke8,
72019
+ stroke: new Stroke9,
71699
72020
  fill: false
71700
72021
  });
71701
72022
  if (fpRect.stroke) {
@@ -71722,7 +72043,7 @@ function convertCourtyardRects(courtyardRects, componentCenter) {
71722
72043
  start: { x: relX - halfW, y: relY - halfH },
71723
72044
  end: { x: relX + halfW, y: relY + halfH },
71724
72045
  layer: kicadLayer,
71725
- stroke: new Stroke9,
72046
+ stroke: new Stroke10,
71726
72047
  fill: false
71727
72048
  });
71728
72049
  if (fpRect.stroke) {
@@ -71754,7 +72075,7 @@ function convertCourtyardOutlines(params2) {
71754
72075
  fpPoly.layer = kicadLayer;
71755
72076
  fpPoly.fill = false;
71756
72077
  fpPoly.uuid = generateDeterministicUuid(outline.pcb_courtyard_outline_id);
71757
- const stroke = new Stroke10;
72078
+ const stroke = new Stroke11;
71758
72079
  stroke.width = 0.05;
71759
72080
  stroke.type = "default";
71760
72081
  fpPoly.stroke = stroke;
@@ -71787,9 +72108,9 @@ function createFpTextFromCircuitJson({
71787
72108
  };
71788
72109
  const kicadLayer = layerMap[textElement.layer] || textElement.layer || "F.SilkS";
71789
72110
  const fontSize = (textElement.font_size || 1) / 1.5;
71790
- const font = new TextEffectsFont9;
72111
+ const font = new TextEffectsFont10;
71791
72112
  font.size = { width: fontSize, height: fontSize };
71792
- const textEffects = new TextEffects9({
72113
+ const textEffects = new TextEffects10({
71793
72114
  font
71794
72115
  });
71795
72116
  const rotation = textElement.ccw_rotation || 0;
@@ -71856,7 +72177,7 @@ function convertSilkscreenPaths(silkscreenPaths, { componentCenter, componentRot
71856
72177
  start: { x: startRelative.x, y: startRelative.y },
71857
72178
  end: { x: endRelative.x, y: endRelative.y },
71858
72179
  layer: kicadLayer,
71859
- stroke: new Stroke11
72180
+ stroke: new Stroke12
71860
72181
  });
71861
72182
  if (fpLine.stroke) {
71862
72183
  fpLine.stroke.width = path7.stroke_width || 0.15;
@@ -71876,9 +72197,9 @@ function convertNoteTexts(params2) {
71876
72197
  const rotationMatrix = componentRotation !== 0 ? rotate5(componentRotation * Math.PI / 180) : identity3();
71877
72198
  const rotatedPos = applyToPoint13(rotationMatrix, { x: relX, y: relY });
71878
72199
  const fontSize = textElement.font_size || 1;
71879
- const font = new TextEffectsFont10;
72200
+ const font = new TextEffectsFont11;
71880
72201
  font.size = { width: fontSize, height: fontSize };
71881
- const textEffects = new TextEffects10({ font });
72202
+ const textEffects = new TextEffects11({ font });
71882
72203
  const fpText = new FpText3({
71883
72204
  type: "user",
71884
72205
  text: textElement.text,
@@ -72612,8 +72933,8 @@ var AddViasStage = class extends ConverterStage {
72612
72933
  const routeDefinedVias = (this.ctx.db.pcb_trace?.list() || []).flatMap((trace) => (trace.route || []).filter((point) => point.route_type === "via").map((point) => ({
72613
72934
  x: point.x,
72614
72935
  y: point.y,
72615
- outer_diameter: point.outer_diameter,
72616
- hole_diameter: point.hole_diameter,
72936
+ outer_diameter: point.outer_diameter ?? point.via_diameter,
72937
+ hole_diameter: point.hole_diameter ?? point.via_hole_diameter,
72617
72938
  from_layer: point.from_layer,
72618
72939
  to_layer: point.to_layer,
72619
72940
  pcb_trace_id: trace.pcb_trace_id,
@@ -72630,8 +72951,8 @@ var AddViasStage = class extends ConverterStage {
72630
72951
  return [...standaloneVias, ...routeDefinedVias];
72631
72952
  }
72632
72953
  getViaDedupeKey(via) {
72633
- const layers = this.getRawViaLayers(via).sort().join(",");
72634
- return `${via.pcb_trace_id ?? ""}:${via.x}:${via.y}:${layers}`;
72954
+ const span = [...this.getKicadViaLayers(via)].sort().join(",");
72955
+ return `${via.x}:${via.y}:${span}`;
72635
72956
  }
72636
72957
  getRawViaLayers(via) {
72637
72958
  if (via.layers?.length) {
@@ -72641,10 +72962,9 @@ var AddViasStage = class extends ConverterStage {
72641
72962
  }
72642
72963
  getKicadViaLayers(via) {
72643
72964
  const rawLayers = this.getRawViaLayers(via);
72644
- if (rawLayers.length > 0) {
72645
- return rawLayers.map((layer) => getKicadLayer(layer));
72646
- }
72647
- return getViaLayers(this.ctx.numLayers ?? 2);
72965
+ const numLayers = this.ctx.numLayers ?? 2;
72966
+ const kicadLayers = rawLayers.length > 0 ? rawLayers.map((layer) => getKicadLayer(layer)) : getViaLayers(numLayers);
72967
+ return getViaLayerSpan(kicadLayers, numLayers);
72648
72968
  }
72649
72969
  _step() {
72650
72970
  const { kicadPcb, c2kMatPcb, pcbNetMap } = this.ctx;
@@ -72911,9 +73231,9 @@ function createFabricationNoteTextFromCircuitJson({
72911
73231
  };
72912
73232
  const kicadLayer = layerMap[textElement.layer] || textElement.layer || "F.Fab";
72913
73233
  const fontSize = (textElement.font_size || 1) / 1.5;
72914
- const font = new TextEffectsFont11;
73234
+ const font = new TextEffectsFont12;
72915
73235
  font.size = { width: fontSize, height: fontSize };
72916
- const justify = new TextEffectsJustify3;
73236
+ const justify = new TextEffectsJustify4;
72917
73237
  const anchorAlignment = textElement.anchor_alignment || "center";
72918
73238
  switch (anchorAlignment) {
72919
73239
  case "top_left":
@@ -72935,13 +73255,13 @@ function createFabricationNoteTextFromCircuitJson({
72935
73255
  case "center":
72936
73256
  break;
72937
73257
  }
72938
- const textEffects = new TextEffects11({
73258
+ const textEffects = new TextEffects12({
72939
73259
  font
72940
73260
  });
72941
73261
  if (anchorAlignment !== "center") {
72942
73262
  textEffects.justify = justify;
72943
73263
  }
72944
- const position = new At2([transformedPos.x, transformedPos.y, 0]);
73264
+ const position = new At3([transformedPos.x, transformedPos.y, 0]);
72945
73265
  const grText = new GrText({
72946
73266
  text: textElement.text,
72947
73267
  layer: kicadLayer,
@@ -72968,9 +73288,9 @@ function createGrTextFromCircuitJson({
72968
73288
  };
72969
73289
  const kicadLayer = layerMap[textElement.layer] || textElement.layer || "F.SilkS";
72970
73290
  const fontSize = (textElement.font_size || 1) / 1.5;
72971
- const font = new TextEffectsFont12;
73291
+ const font = new TextEffectsFont13;
72972
73292
  font.size = { width: fontSize, height: fontSize };
72973
- const justify = new TextEffectsJustify4;
73293
+ const justify = new TextEffectsJustify5;
72974
73294
  const anchorAlignment = textElement.anchor_alignment || "center";
72975
73295
  switch (anchorAlignment) {
72976
73296
  case "top_left":
@@ -72992,14 +73312,14 @@ function createGrTextFromCircuitJson({
72992
73312
  case "center":
72993
73313
  break;
72994
73314
  }
72995
- const textEffects = new TextEffects12({
73315
+ const textEffects = new TextEffects13({
72996
73316
  font
72997
73317
  });
72998
73318
  if (anchorAlignment !== "center") {
72999
73319
  textEffects.justify = justify;
73000
73320
  }
73001
73321
  const rotation = textElement.ccw_rotation || 0;
73002
- const position = new At3([transformedPos.x, transformedPos.y, rotation]);
73322
+ const position = new At4([transformedPos.x, transformedPos.y, rotation]);
73003
73323
  const grText = new GrText2({
73004
73324
  text: textElement.text,
73005
73325
  layer: kicadLayer,
@@ -73308,6 +73628,11 @@ var CircuitJsonToKicadProConverter = class {
73308
73628
  circuitJson
73309
73629
  };
73310
73630
  const pcbBoard = circuitJson.filter((component) => component.type === "pcb_board")[0];
73631
+ const schematicSheetPlan = options.schematicSheetPlan ?? buildSchematicSheetPlan(circuitJson);
73632
+ const sheets = [[schematicSheetPlan.rootUuid, "Root"]];
73633
+ for (const child of schematicSheetPlan.children) {
73634
+ sheets.push([child.sheetNodeUuid, child.sheetName]);
73635
+ }
73311
73636
  const minViaDiameter = pcbBoard?.min_via_pad_diameter ?? 0.3;
73312
73637
  const minViaDrill = pcbBoard?.min_via_hole_diameter ?? 0.2;
73313
73638
  const minViaAnnularWidth = (minViaDiameter - minViaDrill) / 2;
@@ -73384,7 +73709,7 @@ var CircuitJsonToKicadProConverter = class {
73384
73709
  },
73385
73710
  last_opened_board: pcbFilename
73386
73711
  },
73387
- sheets: [[Math.random().toString(36).substring(2, 15), "Root"]]
73712
+ sheets
73388
73713
  };
73389
73714
  }
73390
73715
  runUntilFinished() {}
@@ -73396,57 +73721,6 @@ var CircuitJsonToKicadProConverter = class {
73396
73721
  `;
73397
73722
  }
73398
73723
  };
73399
- var isRemotePath = (modelPath) => modelPath.startsWith("http://") || modelPath.startsWith("https://");
73400
- var isBuiltinModelPath = (modelPath) => modelPath.startsWith("http://modelcdn.tscircuit.com") || modelPath.startsWith("https://modelcdn.tscircuit.com");
73401
- var getModelFileName = (modelPath) => {
73402
- const modelPathWithoutQuery = modelPath.split("?")[0] || modelPath;
73403
- const modelPathWithoutHash = modelPathWithoutQuery.split("#")[0] || modelPathWithoutQuery;
73404
- const normalizedModelPath = modelPathWithoutHash.replaceAll("\\", "/");
73405
- return normalizedModelPath.split("/").pop() || modelPath;
73406
- };
73407
- var resolveAndLoadKicad3dModelFiles = async ({
73408
- model3dSourcePaths,
73409
- projectName,
73410
- fetch: fetch2,
73411
- readFile,
73412
- onModelFile,
73413
- onError
73414
- }) => {
73415
- for (const sourcePath of model3dSourcePaths) {
73416
- let shapesDir = `${projectName}.3dshapes`;
73417
- if (isBuiltinModelPath(sourcePath)) {
73418
- shapesDir = "tscircuit_builtin.3dshapes";
73419
- }
73420
- const outputPath = `3dmodels/${shapesDir}/${getModelFileName(sourcePath)}`;
73421
- let content;
73422
- try {
73423
- if (isRemotePath(sourcePath)) {
73424
- const response = await fetch2(sourcePath);
73425
- if (!response.ok) {
73426
- throw new Error(`Failed to fetch 3D model from ${sourcePath}`);
73427
- }
73428
- content = new Uint8Array(await response.arrayBuffer());
73429
- } else {
73430
- if (!readFile) {
73431
- throw new Error(`Cannot read local 3D model without readFile: ${sourcePath}`);
73432
- }
73433
- const fileContent = await readFile(sourcePath);
73434
- if (fileContent instanceof Uint8Array) {
73435
- content = fileContent;
73436
- } else {
73437
- content = new Uint8Array(fileContent);
73438
- }
73439
- }
73440
- } catch (error) {
73441
- if (!onError) {
73442
- throw error;
73443
- }
73444
- await onError({ sourcePath, error });
73445
- continue;
73446
- }
73447
- await onModelFile({ sourcePath, outputPath, content });
73448
- }
73449
- };
73450
73724
  var GenerateKicadSchAndPcbStage = class extends ConverterStage {
73451
73725
  _step() {
73452
73726
  const schConverter = new CircuitJsonToKicadSchConverter(this.ctx.circuitJson);
@@ -73694,6 +73968,104 @@ var CircuitJsonToKicadLibraryConverter = class {
73694
73968
  return this.getOutput().model3dSourcePaths;
73695
73969
  }
73696
73970
  };
73971
+ var CircuitJsonToKicadModConverter = class {
73972
+ libraryConverter;
73973
+ footprintName;
73974
+ constructor(circuitJson, options = {}) {
73975
+ this.footprintName = options.footprintName;
73976
+ this.libraryConverter = new CircuitJsonToKicadLibraryConverter(circuitJson, {
73977
+ libraryName: options.libraryName,
73978
+ footprintLibraryName: options.footprintLibraryName
73979
+ });
73980
+ }
73981
+ get finished() {
73982
+ return this.libraryConverter.finished;
73983
+ }
73984
+ get currentStage() {
73985
+ return this.libraryConverter.currentStage;
73986
+ }
73987
+ step() {
73988
+ this.libraryConverter.step();
73989
+ }
73990
+ runUntilFinished() {
73991
+ this.libraryConverter.runUntilFinished();
73992
+ }
73993
+ getOutput() {
73994
+ const footprints = this.libraryConverter.getFootprints();
73995
+ if (this.footprintName) {
73996
+ const matchingFootprint = footprints.find((footprint) => footprint.footprintName === this.footprintName);
73997
+ if (matchingFootprint) {
73998
+ return matchingFootprint;
73999
+ }
74000
+ throw new Error(`Footprint "${this.footprintName}" not found. Available footprints: ${footprints.map((footprint) => footprint.footprintName).join(", ")}`);
74001
+ }
74002
+ if (footprints.length === 1) {
74003
+ return footprints[0];
74004
+ }
74005
+ const customFootprints = footprints.filter((footprint) => !footprint.isBuiltin);
74006
+ if (customFootprints.length === 1) {
74007
+ return customFootprints[0];
74008
+ }
74009
+ throw new Error(`Multiple footprints were generated. Pass footprintName to CircuitJsonToKicadModConverter. Available footprints: ${footprints.map((footprint) => footprint.footprintName).join(", ")}`);
74010
+ }
74011
+ getOutputString() {
74012
+ return this.getOutput().kicadModString;
74013
+ }
74014
+ getModel3dSourcePaths() {
74015
+ return this.getOutput().model3dSourcePaths;
74016
+ }
74017
+ };
74018
+ var isRemotePath = (modelPath) => modelPath.startsWith("http://") || modelPath.startsWith("https://");
74019
+ var isBuiltinModelPath = (modelPath) => modelPath.startsWith("http://modelcdn.tscircuit.com") || modelPath.startsWith("https://modelcdn.tscircuit.com");
74020
+ var getModelFileName = (modelPath) => {
74021
+ const modelPathWithoutQuery = modelPath.split("?")[0] || modelPath;
74022
+ const modelPathWithoutHash = modelPathWithoutQuery.split("#")[0] || modelPathWithoutQuery;
74023
+ const normalizedModelPath = modelPathWithoutHash.replaceAll("\\", "/");
74024
+ return normalizedModelPath.split("/").pop() || modelPath;
74025
+ };
74026
+ var resolveAndLoadKicad3dModelFiles = async ({
74027
+ model3dSourcePaths,
74028
+ projectName,
74029
+ fetch: fetch2,
74030
+ readFile,
74031
+ onModelFile,
74032
+ onError
74033
+ }) => {
74034
+ for (const sourcePath of model3dSourcePaths) {
74035
+ let shapesDir = `${projectName}.3dshapes`;
74036
+ if (isBuiltinModelPath(sourcePath)) {
74037
+ shapesDir = "tscircuit_builtin.3dshapes";
74038
+ }
74039
+ const outputPath = `3dmodels/${shapesDir}/${getModelFileName(sourcePath)}`;
74040
+ let content;
74041
+ try {
74042
+ if (isRemotePath(sourcePath)) {
74043
+ const response = await fetch2(sourcePath);
74044
+ if (!response.ok) {
74045
+ throw new Error(`Failed to fetch 3D model from ${sourcePath}`);
74046
+ }
74047
+ content = new Uint8Array(await response.arrayBuffer());
74048
+ } else {
74049
+ if (!readFile) {
74050
+ throw new Error(`Cannot read local 3D model without readFile: ${sourcePath}`);
74051
+ }
74052
+ const fileContent = await readFile(sourcePath);
74053
+ if (fileContent instanceof Uint8Array) {
74054
+ content = fileContent;
74055
+ } else {
74056
+ content = new Uint8Array(fileContent);
74057
+ }
74058
+ }
74059
+ } catch (error) {
74060
+ if (!onError) {
74061
+ throw error;
74062
+ }
74063
+ await onError({ sourcePath, error });
74064
+ continue;
74065
+ }
74066
+ await onModelFile({ sourcePath, outputPath, content });
74067
+ }
74068
+ };
73697
74069
  var KICAD_3RD_PARTY_PLACEHOLDER = "${KICAD_3RD_PARTY}";
73698
74070
  function renameKicadFootprint(params2) {
73699
74071
  const {
@@ -73726,7 +74098,7 @@ function renameKicadFootprint(params2) {
73726
74098
  };
73727
74099
  }
73728
74100
  function createTextEffects3(metadataEffects) {
73729
- const font = new TextEffectsFont13;
74101
+ const font = new TextEffectsFont14;
73730
74102
  if (metadataEffects?.font?.size) {
73731
74103
  font.size = {
73732
74104
  width: Number(metadataEffects.font.size.x),
@@ -73740,7 +74112,7 @@ function createTextEffects3(metadataEffects) {
73740
74112
  } else {
73741
74113
  font.thickness = 0.15;
73742
74114
  }
73743
- return new TextEffects13({ font });
74115
+ return new TextEffects14({ font });
73744
74116
  }
73745
74117
  function applyKicadFootprintMetadata(kicadModString, metadata, footprintName) {
73746
74118
  try {
@@ -73982,13 +74354,13 @@ var toNumber = (value, fallback) => {
73982
74354
  var createTextEffects4 = (effectsMeta, fallback) => {
73983
74355
  if (!effectsMeta)
73984
74356
  return fallback;
73985
- const effects = new TextEffects14({
74357
+ const effects = new TextEffects15({
73986
74358
  font: fallback?.font,
73987
74359
  justify: fallback?.justify,
73988
74360
  hiddenText: fallback?.hiddenText ?? false
73989
74361
  });
73990
74362
  if (!effects.font) {
73991
- const defaultFont = new TextEffectsFont14;
74363
+ const defaultFont = new TextEffectsFont15;
73992
74364
  defaultFont.size = { width: DEFAULT_TEXT_SIZE, height: DEFAULT_TEXT_SIZE };
73993
74365
  effects.font = defaultFont;
73994
74366
  }
@@ -74033,7 +74405,7 @@ var createJustify = (justifyInput) => {
74033
74405
  if (!options.horizontal && !options.vertical && !options.mirror) {
74034
74406
  return;
74035
74407
  }
74036
- return new TextEffectsJustify5(options);
74408
+ return new TextEffectsJustify6(options);
74037
74409
  };
74038
74410
  var applySymbolProperty = (symbol, key, propertyMeta) => {
74039
74411
  const existingProperty = symbol.properties.find((prop) => prop.key === key);