@tscircuit/cli 0.1.2231 → 0.1.2233

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/cli/main.js CHANGED
@@ -154298,7 +154298,7 @@ var import_perfect_cli = __toESM3(require_dist3(), 1);
154298
154298
  // lib/getVersion.ts
154299
154299
  import { createRequire as createRequire2 } from "node:module";
154300
154300
  // package.json
154301
- var version = "0.1.2230";
154301
+ var version = "0.1.2232";
154302
154302
  var package_default = {
154303
154303
  name: "@tscircuit/cli",
154304
154304
  version,
@@ -154322,7 +154322,7 @@ var package_default = {
154322
154322
  "@tscircuit/eval": "0.0.1402",
154323
154323
  "@tscircuit/fake-snippets": "^0.0.182",
154324
154324
  "@tscircuit/file-server": "^0.0.32",
154325
- "@tscircuit/footprinter": "^0.0.426",
154325
+ "@tscircuit/footprinter": "^0.0.430",
154326
154326
  "@tscircuit/image-utils": "^0.0.8",
154327
154327
  "@tscircuit/krt-wasm": "^0.1.6",
154328
154328
  "@tscircuit/math-utils": "0.0.36",
@@ -154348,7 +154348,7 @@ var package_default = {
154348
154348
  "circuit-json-to-bom-csv": "^0.0.19",
154349
154349
  "circuit-json-to-connectivity-map": "^0.0.32",
154350
154350
  "circuit-json-to-fdm-component-box": "^0.0.2",
154351
- "circuit-json-to-footprinter": "^0.0.58",
154351
+ "circuit-json-to-footprinter": "^0.0.59",
154352
154352
  "circuit-json-to-gerber": "^0.0.105",
154353
154353
  "circuit-json-to-kicad": "0.0.230",
154354
154354
  "circuit-json-to-pnp-csv": "^0.0.18",
@@ -154367,7 +154367,7 @@ var package_default = {
154367
154367
  debug: "^4.4.0",
154368
154368
  delay: "^6.0.0",
154369
154369
  "dsn-converter": "^0.0.90",
154370
- easyeda: "^0.0.366",
154370
+ easyeda: "^0.0.368",
154371
154371
  "fuse.js": "^7.1.0",
154372
154372
  "get-port": "^7.1.0",
154373
154373
  globby: "^14.1.0",
@@ -337889,7 +337889,7 @@ var convertKicadFootprintToTsx = async ({
337889
337889
  console.log(kleur_default.green(`Converted ${outputPath}`));
337890
337890
  };
337891
337891
 
337892
- // node_modules/circuit-json-to-footprinter/dist/chunk-VEAX3CQP.js
337892
+ // node_modules/circuit-json-to-footprinter/dist/chunk-K4WFTP36.js
337893
337893
  import {
337894
337894
  getBoundsCenter,
337895
337895
  getBoundsFromPoints as getBoundsFromPoints4
@@ -340635,7 +340635,7 @@ var getManifoldModule = async () => {
340635
340635
  return manifoldModulePromise;
340636
340636
  };
340637
340637
 
340638
- // node_modules/circuit-json-to-footprinter/dist/chunk-VEAX3CQP.js
340638
+ // node_modules/circuit-json-to-footprinter/dist/chunk-K4WFTP36.js
340639
340639
  import { getBoundsCenter as getBoundsCenter2, isPointInsidePolygon as isPointInsidePolygon3 } from "@tscircuit/math-utils";
340640
340640
  var HOLE_SHAPE_KIND = {
340641
340641
  circle: "circle",
@@ -341045,6 +341045,7 @@ var getNumericPinNumbers = (pad) => [
341045
341045
  return match?.[1] ? [Number.parseInt(match[1], 10)] : [];
341046
341046
  }))
341047
341047
  ];
341048
+ var getBallCoordinates = (pad) => (pad?.element.port_hints ?? []).filter((hint) => /^[A-Z]+[1-9]\d*$/.test(hint));
341048
341049
  var matchPadsByPosition = (leftPads, rightPads) => {
341049
341050
  const availableRight = new Set(rightPads.map((_, index) => index));
341050
341051
  const pairs = [];
@@ -341079,10 +341080,14 @@ var comparePinHints = (left, right) => {
341079
341080
  for (const [leftPad, rightPad] of pairs) {
341080
341081
  const leftPinNumbers = getNumericPinNumbers(leftPad);
341081
341082
  const rightPinNumbers = getNumericPinNumbers(rightPad);
341082
- if (leftPinNumbers.length === 0 && rightPinNumbers.length === 0)
341083
+ const leftBalls = getBallCoordinates(leftPad);
341084
+ const rightBalls = getBallCoordinates(rightPad);
341085
+ if (leftPinNumbers.length === 0 && rightPinNumbers.length === 0 && leftBalls.length === 0 && rightBalls.length === 0)
341083
341086
  continue;
341084
341087
  comparedPinCount += 1;
341085
- if (leftPinNumbers.some((pinNumber) => rightPinNumbers.includes(pinNumber))) {
341088
+ const hasNumericPair = leftPinNumbers.length > 0 && rightPinNumbers.length > 0;
341089
+ const hasBallPair = leftBalls.length > 0 && rightBalls.length > 0;
341090
+ if ((hasNumericPair || leftPinNumbers.length === 0 && rightPinNumbers.length === 0 && hasBallPair) && (!hasNumericPair || leftPinNumbers.some((pinNumber) => rightPinNumbers.includes(pinNumber))) && (!hasBallPair || leftBalls.some((ball) => rightBalls.includes(ball)))) {
341086
341091
  matchedPinCount += 1;
341087
341092
  continue;
341088
341093
  }
@@ -342999,36 +343004,66 @@ var getSot223Seed = (target) => {
342999
343004
  }
343000
343005
  return;
343001
343006
  };
343002
- var getBgaGridSeed = (target) => {
343007
+ var getBgaGridSeeds = (target) => {
343003
343008
  const pads = getPadGeometries(target);
343004
- if (pads.length < 4 || pads.some(({ copper, drill, element }) => element.type !== "pcb_smtpad" || drill || copper.shape !== "rect")) {
343005
- return;
343009
+ if (pads.length < 4 || pads.some(({ copper, drill, element }) => element.type !== "pcb_smtpad" || drill || copper.shape !== "rect" && copper.shape !== "circle")) {
343010
+ return [];
343006
343011
  }
343007
343012
  const bounds = pads.map(({ copper }) => getPadBounds3(copper));
343008
343013
  const pad = median(bounds.map(({ width, height }) => (width + height) / 2));
343009
343014
  const tolerance = Math.max(0.005, pad * 0.08);
343010
343015
  if (bounds.some(({ width, height }) => Math.abs(width - height) > tolerance || Math.abs(width - pad) > tolerance || Math.abs(height - pad) > tolerance)) {
343011
- return;
343016
+ return [];
343012
343017
  }
343013
343018
  const columns = clusterCoordinates(pads.map(({ copper }) => copper.x), tolerance);
343014
343019
  const rows = clusterCoordinates(pads.map(({ copper }) => copper.y), tolerance);
343015
- if (columns.length < 2 || rows.length < 2 || columns.length * rows.length !== pads.length) {
343016
- return;
343020
+ if (columns.length < 2 || rows.length < 2 || columns.length * rows.length < pads.length) {
343021
+ return [];
343017
343022
  }
343018
343023
  const columnPitches = columns.slice(1).map((coordinate, index) => coordinate - columns[index]);
343019
343024
  const rowPitches = rows.slice(1).map((coordinate, index) => coordinate - rows[index]);
343020
- const pitch = median([...columnPitches, ...rowPitches]);
343025
+ const pitch = median([
343026
+ (columns.at(-1) - columns[0]) / (columns.length - 1),
343027
+ (rows.at(-1) - rows[0]) / (rows.length - 1)
343028
+ ]);
343021
343029
  if (pitch <= pad || [...columnPitches, ...rowPitches].some((candidate) => Math.abs(candidate - pitch) > tolerance)) {
343022
- return;
343030
+ return [];
343023
343031
  }
343024
- for (const column of columns) {
343025
- for (const row of rows) {
343026
- if (pads.filter(({ copper }) => Math.abs(copper.x - column) <= tolerance && Math.abs(copper.y - row) <= tolerance).length !== 1) {
343027
- return;
343032
+ const occupied = /* @__PURE__ */ new Set;
343033
+ for (const { copper } of pads) {
343034
+ const x = columns.findIndex((column) => Math.abs(copper.x - column) <= tolerance);
343035
+ const y = rows.findIndex((row) => Math.abs(copper.y - row) <= tolerance);
343036
+ const position = y * columns.length + x;
343037
+ if (x < 0 || y < 0 || occupied.has(position))
343038
+ return [];
343039
+ occupied.add(position);
343040
+ }
343041
+ const shapes = new Set(pads.map(({ copper }) => copper.shape));
343042
+ if (shapes.size !== 1)
343043
+ return [];
343044
+ const base = `bga${pads.length}_grid${columns.length}x${rows.length}_p${formatPreciseLength(pitch)}_pad${formatPreciseLength(pad)}`;
343045
+ const padModifier = shapes.has("rect") ? "_rectpads" : "";
343046
+ const seeds = [];
343047
+ for (const origin of ["tl", "bl", "tr", "br"]) {
343048
+ const missing = [];
343049
+ for (let y = 0;y < rows.length; y++) {
343050
+ for (let x = 0;x < columns.length; x++) {
343051
+ if (occupied.has(y * columns.length + x))
343052
+ continue;
343053
+ const pinX = origin.endsWith("r") ? columns.length - 1 - x : x;
343054
+ const pinY = origin.startsWith("b") ? rows.length - 1 - y : y;
343055
+ missing.push(pinY * columns.length + pinX + 1);
343028
343056
  }
343029
343057
  }
343058
+ missing.sort((left, right) => left - right);
343059
+ const mask = missing.length ? `_missing(${missing.join(",")})` : "";
343060
+ const seed = `${base}${mask}_${origin}origin${padModifier}`;
343061
+ seeds.push(seed);
343062
+ for (const numbering of ["rowmajor", "columnmajor", "ballcoords"]) {
343063
+ seeds.push(`${seed}_pinnumbering(${numbering})`);
343064
+ }
343030
343065
  }
343031
- return `bga${pads.length}_grid${columns.length}x${rows.length}_p${formatPreciseLength(pitch)}_pad${formatPreciseLength(pad)}_rectpads`;
343066
+ return seeds;
343032
343067
  };
343033
343068
  var getStaggeredSmdPinHeaderSeed = (target) => {
343034
343069
  const description = `${target.title} ${target.subtitle} ${target.sourceHints?.join(" ") ?? ""}`.toLowerCase();
@@ -343189,9 +343224,8 @@ var generateSeeds = (target, analysis) => {
343189
343224
  if (family !== "usbcmidmount")
343190
343225
  seeds.add(family);
343191
343226
  }
343192
- const bgaGridSeed = getBgaGridSeed(target);
343193
- if (bgaGridSeed)
343194
- seeds.add(bgaGridSeed);
343227
+ for (const seed of getBgaGridSeeds(target))
343228
+ seeds.add(seed);
343195
343229
  const staggeredSmdPinHeaderSeed = getStaggeredSmdPinHeaderSeed(target);
343196
343230
  if (staggeredSmdPinHeaderSeed)
343197
343231
  seeds.add(staggeredSmdPinHeaderSeed);
@@ -343696,7 +343730,7 @@ var selectSeedsToOptimize = (candidates, analysis, target) => {
343696
343730
  return [...selected.values()].slice(0, MAX_OPTIMIZED_SEEDS);
343697
343731
  };
343698
343732
  var findActiveParameters = (seed, analysis) => {
343699
- if (seed.family === "fpc" || seed.family === "jst" && (seed.footprinterString.includes("_smd") || seed.footprinterString.includes("_zh"))) {
343733
+ if (seed.family === "bga" && seed.footprinterString.includes("_pinnumbering(") || seed.family === "fpc" || seed.family === "jst" && (seed.footprinterString.includes("_smd") || seed.footprinterString.includes("_zh"))) {
343700
343734
  return [];
343701
343735
  }
343702
343736
  const active = [];
@@ -363942,6 +363976,29 @@ function compose27(...matrices) {
363942
363976
  return transform2(...matrices);
363943
363977
  }
363944
363978
  var { cos: cos3, sin: sin3, PI: PI3 } = Math;
363979
+ function rotate20(angle, cx, cy) {
363980
+ const cosAngle = cos3(angle);
363981
+ const sinAngle = sin3(angle);
363982
+ const rotationMatrix = {
363983
+ a: cosAngle,
363984
+ c: -sinAngle,
363985
+ e: 0,
363986
+ b: sinAngle,
363987
+ d: cosAngle,
363988
+ f: 0
363989
+ };
363990
+ if (isUndefined3(cx) || isUndefined3(cy)) {
363991
+ return rotationMatrix;
363992
+ }
363993
+ return transform2([
363994
+ translate26(cx, cy),
363995
+ rotationMatrix,
363996
+ translate26(-cx, -cy)
363997
+ ]);
363998
+ }
363999
+ function rotateDEG2(angle, cx = undefined, cy = undefined) {
364000
+ return rotate20(angle * PI3 / 180, cx, cy);
364001
+ }
363945
364002
  function scale14(sx, sy = undefined, cx = undefined, cy = undefined) {
363946
364003
  if (isUndefined3(sy))
363947
364004
  sy = sx;
@@ -365428,6 +365485,95 @@ var PIN1_LOCATION_PARTS = {
365428
365485
  bottomside_right: { side: "bottomside", alignment: "right" }
365429
365486
  };
365430
365487
  var PIN1_LOCATIONS2 = Object.keys(PIN1_LOCATION_PARTS);
365488
+ var unitToMm3 = {
365489
+ in: 25.4,
365490
+ inch: 25.4,
365491
+ mil: 0.0254,
365492
+ mm: 1,
365493
+ m: 1000,
365494
+ cm: 10,
365495
+ ft: 304.8,
365496
+ feet: 304.8
365497
+ };
365498
+ var mmNumberFormatter = new Intl.NumberFormat("en-US", {
365499
+ useGrouping: false,
365500
+ notation: "standard",
365501
+ maximumFractionDigits: 12
365502
+ });
365503
+ var mm4 = (n) => {
365504
+ let unit = typeof n === "number" ? "mm" : n.replace(/^[^a-zA-Z]+/g, "").toLowerCase();
365505
+ if (!unit)
365506
+ unit = "mm";
365507
+ const val = typeof n === "number" ? n : Number.parseFloat(n.split(unit)[0]);
365508
+ if (unit in unitToMm3) {
365509
+ return val * unitToMm3[unit];
365510
+ }
365511
+ throw new Error(`Unsupported unit: ${unit}`);
365512
+ };
365513
+ var mmStr2 = (n) => {
365514
+ return `${mmNumberFormatter.format(mm4(n))}mm`;
365515
+ };
365516
+ var mil2mm = (mil) => {
365517
+ if (typeof mil === "number")
365518
+ return mm4(`${mil}mil`);
365519
+ if (mil.match(/^\d+$/))
365520
+ return mm4(`${mil}mil`);
365521
+ return mm4(mil);
365522
+ };
365523
+ var getEasyEdaPlatedHoleGeometry = (pad) => {
365524
+ const holeDiameterMm = mil2mm(pad.holeRadius) * 2;
365525
+ const holeLengthMm = pad.holeLength ? mil2mm(pad.holeLength) : 0;
365526
+ let holeWidthMm = holeDiameterMm;
365527
+ let holeHeightMm = holeDiameterMm;
365528
+ if (holeLengthMm > holeDiameterMm) {
365529
+ if (!pad.holePoints) {
365530
+ throw new Error(`Slot on pad ${pad.number} is missing hole endpoints`);
365531
+ }
365532
+ const [start, end] = pad.holePoints;
365533
+ const localHoleDirection = applyToPoint106(rotateDEG2(pad.rotation), {
365534
+ x: end.x - start.x,
365535
+ y: end.y - start.y
365536
+ });
365537
+ const absX = Math.abs(localHoleDirection.x);
365538
+ const absY = Math.abs(localHoleDirection.y);
365539
+ if (Math.min(absX, absY) > Math.max(absX, absY) * 0.001) {
365540
+ throw new Error(`Slot on pad ${pad.number} is not aligned with its pad`);
365541
+ }
365542
+ if (absX > absY)
365543
+ holeWidthMm = holeLengthMm;
365544
+ else
365545
+ holeHeightMm = holeLengthMm;
365546
+ }
365547
+ if (pad.shape === "RECT") {
365548
+ return {
365549
+ shape: "rotated_pill_hole_with_rect_pad",
365550
+ hole_shape: "rotated_pill",
365551
+ pad_shape: "rect",
365552
+ hole_width: holeWidthMm,
365553
+ hole_height: holeHeightMm,
365554
+ hole_ccw_rotation: pad.rotation,
365555
+ rect_ccw_rotation: pad.rotation,
365556
+ rect_pad_width: mil2mm(pad.width),
365557
+ rect_pad_height: mil2mm(pad.height)
365558
+ };
365559
+ }
365560
+ if (pad.shape === "OVAL" || holeLengthMm > holeDiameterMm) {
365561
+ return {
365562
+ shape: "pill",
365563
+ hole_width: holeWidthMm,
365564
+ hole_height: holeHeightMm,
365565
+ outer_width: mil2mm(pad.width),
365566
+ outer_height: mil2mm(pad.height),
365567
+ ccw_rotation: pad.rotation
365568
+ };
365569
+ }
365570
+ return {
365571
+ shape: "circle",
365572
+ hole_diameter: holeDiameterMm,
365573
+ outer_diameter: mil2mm(pad.width),
365574
+ radius: mil2mm(pad.holeRadius)
365575
+ };
365576
+ };
365431
365577
  var normalizeActiveLowPinLabel = (label) => {
365432
365578
  const hasActiveLowMarker = label.startsWith("#") || label.endsWith("#");
365433
365579
  if (!hasActiveLowMarker)
@@ -365647,41 +365793,6 @@ var getBoardOutlinePolygons3 = (tracks) => {
365647
365793
  }
365648
365794
  return polygons;
365649
365795
  };
365650
- var unitToMm3 = {
365651
- in: 25.4,
365652
- inch: 25.4,
365653
- mil: 0.0254,
365654
- mm: 1,
365655
- m: 1000,
365656
- cm: 10,
365657
- ft: 304.8,
365658
- feet: 304.8
365659
- };
365660
- var mmNumberFormatter = new Intl.NumberFormat("en-US", {
365661
- useGrouping: false,
365662
- notation: "standard",
365663
- maximumFractionDigits: 12
365664
- });
365665
- var mm4 = (n) => {
365666
- let unit = typeof n === "number" ? "mm" : n.replace(/^[^a-zA-Z]+/g, "").toLowerCase();
365667
- if (!unit)
365668
- unit = "mm";
365669
- const val = typeof n === "number" ? n : Number.parseFloat(n.split(unit)[0]);
365670
- if (unit in unitToMm3) {
365671
- return val * unitToMm3[unit];
365672
- }
365673
- throw new Error(`Unsupported unit: ${unit}`);
365674
- };
365675
- var mmStr2 = (n) => {
365676
- return `${mmNumberFormatter.format(mm4(n))}mm`;
365677
- };
365678
- var mil2mm = (mil) => {
365679
- if (typeof mil === "number")
365680
- return mm4(`${mil}mil`);
365681
- if (mil.match(/^\d+$/))
365682
- return mm4(`${mil}mil`);
365683
- return mm4(mil);
365684
- };
365685
365796
  var DEFAULT_PCB_THICKNESS_MM = 1.6;
365686
365797
  function generateArcFromSweep(startX, startY, endX, endY, radius, largeArcFlag, sweepFlag) {
365687
365798
  const start = { x: startX, y: startY };
@@ -366331,68 +366442,7 @@ var convertEasyEdaJsonToCircuitJson = (easyEdaJson, {
366331
366442
  pcb_component_id: "pcb_component_1",
366332
366443
  pcb_port_id: `pcb_port_${index + 1}`
366333
366444
  };
366334
- let additionalPlatedHoleProps;
366335
- if (pad.shape === "OVAL") {
366336
- const largestOuterDimensionName = mil2mm(pad.width) > mil2mm(pad.height) ? "width" : "height";
366337
- const smallestOuterDimension = Math.min(mil2mm(pad.width), mil2mm(pad.height));
366338
- const largestOuterDimension = Math.max(mil2mm(pad.width), mil2mm(pad.height));
366339
- const distanceFromOuterPlatingToHole = smallestOuterDimension / 2 - mil2mm(pad.holeRadius);
366340
- const largestInnerDimension = largestOuterDimension - distanceFromOuterPlatingToHole * 2;
366341
- const smallestInnerDimension = mil2mm(pad.holeRadius) * 2;
366342
- const innerWidth = largestOuterDimensionName === "width" ? largestInnerDimension : smallestInnerDimension;
366343
- const innerHeight = largestOuterDimensionName === "height" ? largestInnerDimension : smallestInnerDimension;
366344
- additionalPlatedHoleProps = {
366345
- shape: "pill",
366346
- hole_width: innerWidth,
366347
- hole_height: innerHeight,
366348
- outer_width: mil2mm(pad.width),
366349
- outer_height: mil2mm(pad.height),
366350
- ccw_rotation: pad.rotation || 0
366351
- };
366352
- } else if (pad.shape === "RECT") {
366353
- const padWidth = mil2mm(pad.width);
366354
- const padHeight = mil2mm(pad.height);
366355
- const holeRadius = mil2mm(pad.holeRadius);
366356
- const holeDiameter = holeRadius * 2;
366357
- const aspectRatio = Math.max(padWidth, padHeight) / Math.min(padWidth, padHeight);
366358
- const isSignificantlyRectangular = aspectRatio > 1.5;
366359
- if (isSignificantlyRectangular) {
366360
- const baseWidth = holeDiameter;
366361
- const pillHeight = baseWidth * 2.6;
366362
- const holeWidth = padWidth > padHeight ? pillHeight : baseWidth;
366363
- const holeHeight = padHeight > padWidth ? pillHeight : baseWidth;
366364
- additionalPlatedHoleProps = {
366365
- shape: "rotated_pill_hole_with_rect_pad",
366366
- hole_shape: "rotated_pill",
366367
- pad_shape: "rect",
366368
- hole_width: holeWidth,
366369
- hole_height: holeHeight,
366370
- hole_ccw_rotation: pad.rotation || 0,
366371
- rect_ccw_rotation: pad.rotation || 0,
366372
- rect_pad_width: padWidth,
366373
- rect_pad_height: padHeight
366374
- };
366375
- } else {
366376
- additionalPlatedHoleProps = {
366377
- shape: "rotated_pill_hole_with_rect_pad",
366378
- hole_shape: "rotated_pill",
366379
- pad_shape: "rect",
366380
- hole_width: holeDiameter,
366381
- hole_height: holeDiameter,
366382
- hole_ccw_rotation: pad.rotation || 0,
366383
- rect_ccw_rotation: pad.rotation || 0,
366384
- rect_pad_width: padWidth,
366385
- rect_pad_height: padHeight
366386
- };
366387
- }
366388
- } else {
366389
- additionalPlatedHoleProps = {
366390
- shape: "circle",
366391
- hole_diameter: mil2mm(pad.holeRadius) * 2,
366392
- outer_diameter: mil2mm(pad.width),
366393
- radius: mil2mm(pad.holeRadius)
366394
- };
366395
- }
366445
+ const additionalPlatedHoleProps = getEasyEdaPlatedHoleGeometry(pad);
366396
366446
  circuitElements.push(pcb_plated_hole.parse({
366397
366447
  ...commonPlatedHoleProps,
366398
366448
  ...additionalPlatedHoleProps
@@ -366745,6 +366795,8 @@ var PadSchema = BaseShapeSchema.extend({
366745
366795
  net: external_exports2.union([external_exports2.string(), external_exports2.number()]).optional(),
366746
366796
  number: external_exports2.union([external_exports2.string(), external_exports2.number()]),
366747
366797
  holeRadius: tenthmil,
366798
+ holeLength: tenthmil.optional(),
366799
+ holePoints: external_exports2.array(PointSchema).length(2).optional(),
366748
366800
  points: external_exports2.array(PointSchema).optional(),
366749
366801
  rotation: safeNumber(0),
366750
366802
  plated: external_exports2.boolean()
@@ -366877,6 +366929,8 @@ var ShapeItemSchema = external_exports2.object({
366877
366929
  net,
366878
366930
  number: padNumber,
366879
366931
  holeRadius,
366932
+ holeLength: rest[3] === undefined || rest[3] === "" ? undefined : rest[3],
366933
+ holePoints: rest[4] ? parsePoints(String(rest[4])) : undefined,
366880
366934
  points,
366881
366935
  rotation: rotation2,
366882
366936
  plated: rest.includes("Y")
@@ -368628,8 +368682,9 @@ var getGeneratedComponentType = (betterEasy, pinCount) => {
368628
368682
  return "pushbutton";
368629
368683
  if (isDipSwitchCategoryComponent(betterEasy))
368630
368684
  return "chip";
368631
- if (isSwitchCategoryComponent(betterEasy))
368632
- return "switch";
368685
+ if (isSwitchCategoryComponent(betterEasy)) {
368686
+ return pinCount > 2 ? "chip" : "switch";
368687
+ }
368633
368688
  if (isCapacitorComponent(betterEasy))
368634
368689
  return "capacitor";
368635
368690
  if (isResistorComponent(betterEasy) && pinCount === 2)
@@ -368721,7 +368776,7 @@ var convertBetterEasyToTsx = async ({
368721
368776
  jlcpcb: [betterEasy.lcsc.number]
368722
368777
  };
368723
368778
  const componentType = getGeneratedComponentType(betterEasy, sourcePorts.length);
368724
- const isDipSwitch = isDipSwitchCategoryComponent(betterEasy);
368779
+ const isSwitchRenderedAsChip = isDipSwitchCategoryComponent(betterEasy) || isSwitchCategoryComponent(betterEasy) && sourcePorts.length > 2;
368725
368780
  const inductance2 = componentType === "inductor" ? betterEasy.dataStr.head.c_para.Value?.trim() : undefined;
368726
368781
  const capacitance2 = componentType === "capacitor" ? normalizeCapacitanceValue(betterEasy.dataStr.head.c_para.Value) : undefined;
368727
368782
  const resistance2 = componentType === "resistor" ? normalizeResistorValue(betterEasy.dataStr.head.c_para.Value) : undefined;
@@ -368730,7 +368785,7 @@ var convertBetterEasyToTsx = async ({
368730
368785
  const isMultiPinDiode = isDiodeCategoryComponent(betterEasy) && sourcePorts.length !== 2;
368731
368786
  const isMultiPinInductor = isInductorComponent(betterEasy) && sourcePorts.length !== 2;
368732
368787
  const isPassiveWithCustomSymbol = componentType === "capacitor" && sourcePorts.length !== 2;
368733
- const symbolTsx = isPassiveWithCustomSymbol || componentType === "chip" && !isMultiPinDiode && !isMultiPinInductor && hasNonBoxSchematicSymbol(betterEasy) ? generateSymbolTsx2(betterEasy, circuitJson, {
368788
+ const symbolTsx = isPassiveWithCustomSymbol || componentType === "chip" && !isMultiPinDiode && !isMultiPinInductor && !isSwitchRenderedAsChip && hasNonBoxSchematicSymbol(betterEasy) ? generateSymbolTsx2(betterEasy, circuitJson, {
368734
368789
  alignPortsToDrawing: isPassiveWithCustomSymbol
368735
368790
  }) : undefined;
368736
368791
  const schPinArrangement = symbolTsx ? undefined : getVisibleSchematicPinArrangement(betterEasy);
@@ -368750,8 +368805,7 @@ var convertBetterEasyToTsx = async ({
368750
368805
  crystalFrequency,
368751
368806
  crystalPinVariant,
368752
368807
  symbolTsx,
368753
- schPinArrangement,
368754
- useSymbolPortsOnly: isDipSwitch && Boolean(symbolTsx)
368808
+ schPinArrangement
368755
368809
  });
368756
368810
  };
368757
368811
  var checkModelObjUrlValidity = async (url) => {
@@ -369152,6 +369206,360 @@ var __export6 = (target, all) => {
369152
369206
  for (var name in all)
369153
369207
  __defProp7(target, name, { get: all[name], enumerable: true });
369154
369208
  };
369209
+ var unitToMm4 = {
369210
+ in: 25.4,
369211
+ inch: 25.4,
369212
+ mil: 0.0254,
369213
+ mm: 1,
369214
+ m: 1000,
369215
+ cm: 10,
369216
+ ft: 304.8,
369217
+ feet: 304.8
369218
+ };
369219
+ var mmNumberFormatter2 = new Intl.NumberFormat("en-US", {
369220
+ useGrouping: false,
369221
+ notation: "standard",
369222
+ maximumFractionDigits: 12
369223
+ });
369224
+ var mm5 = (n) => {
369225
+ let unit = typeof n === "number" ? "mm" : n.replace(/^[^a-zA-Z]+/g, "").toLowerCase();
369226
+ if (!unit)
369227
+ unit = "mm";
369228
+ const val = typeof n === "number" ? n : Number.parseFloat(n.split(unit)[0]);
369229
+ if (unit in unitToMm4) {
369230
+ return val * unitToMm4[unit];
369231
+ }
369232
+ throw new Error(`Unsupported unit: ${unit}`);
369233
+ };
369234
+ var mil2mm2 = (mil) => {
369235
+ if (typeof mil === "number")
369236
+ return mm5(`${mil}mil`);
369237
+ if (mil.match(/^\d+$/))
369238
+ return mm5(`${mil}mil`);
369239
+ return mm5(mil);
369240
+ };
369241
+ function applyToPoint107(matrix, point2) {
369242
+ return Array.isArray(point2) ? [
369243
+ matrix.a * point2[0] + matrix.c * point2[1] + matrix.e,
369244
+ matrix.b * point2[0] + matrix.d * point2[1] + matrix.f
369245
+ ] : {
369246
+ x: matrix.a * point2.x + matrix.c * point2.y + matrix.e,
369247
+ y: matrix.b * point2.x + matrix.d * point2.y + matrix.f
369248
+ };
369249
+ }
369250
+ function isUndefined4(val) {
369251
+ return typeof val === "undefined";
369252
+ }
369253
+ function translate27(tx, ty = 0) {
369254
+ return {
369255
+ a: 1,
369256
+ c: 0,
369257
+ e: tx,
369258
+ b: 0,
369259
+ d: 1,
369260
+ f: ty
369261
+ };
369262
+ }
369263
+ function transform3(...matrices) {
369264
+ matrices = Array.isArray(matrices[0]) ? matrices[0] : matrices;
369265
+ const multiply = (m1, m2) => {
369266
+ return {
369267
+ a: m1.a * m2.a + m1.c * m2.b,
369268
+ c: m1.a * m2.c + m1.c * m2.d,
369269
+ e: m1.a * m2.e + m1.c * m2.f + m1.e,
369270
+ b: m1.b * m2.a + m1.d * m2.b,
369271
+ d: m1.b * m2.c + m1.d * m2.d,
369272
+ f: m1.b * m2.e + m1.d * m2.f + m1.f
369273
+ };
369274
+ };
369275
+ switch (matrices.length) {
369276
+ case 0:
369277
+ throw new Error("no matrices provided");
369278
+ case 1:
369279
+ return matrices[0];
369280
+ case 2:
369281
+ return multiply(matrices[0], matrices[1]);
369282
+ default: {
369283
+ const [m1, m2, ...rest] = matrices;
369284
+ const m3 = multiply(m1, m2);
369285
+ return transform3(m3, ...rest);
369286
+ }
369287
+ }
369288
+ }
369289
+ function compose28(...matrices) {
369290
+ return transform3(...matrices);
369291
+ }
369292
+ var { cos: cos4, sin: sin4, PI: PI4 } = Math;
369293
+ function rotate21(angle, cx, cy) {
369294
+ const cosAngle = cos4(angle);
369295
+ const sinAngle = sin4(angle);
369296
+ const rotationMatrix = {
369297
+ a: cosAngle,
369298
+ c: -sinAngle,
369299
+ e: 0,
369300
+ b: sinAngle,
369301
+ d: cosAngle,
369302
+ f: 0
369303
+ };
369304
+ if (isUndefined4(cx) || isUndefined4(cy)) {
369305
+ return rotationMatrix;
369306
+ }
369307
+ return transform3([
369308
+ translate27(cx, cy),
369309
+ rotationMatrix,
369310
+ translate27(-cx, -cy)
369311
+ ]);
369312
+ }
369313
+ function rotateDEG3(angle, cx = undefined, cy = undefined) {
369314
+ return rotate21(angle * PI4 / 180, cx, cy);
369315
+ }
369316
+ function scale15(sx, sy = undefined, cx = undefined, cy = undefined) {
369317
+ if (isUndefined4(sy))
369318
+ sy = sx;
369319
+ const scaleMatrix = {
369320
+ a: sx,
369321
+ c: 0,
369322
+ e: 0,
369323
+ b: 0,
369324
+ d: sy,
369325
+ f: 0
369326
+ };
369327
+ if (isUndefined4(cx) || isUndefined4(cy)) {
369328
+ return scaleMatrix;
369329
+ }
369330
+ return transform3([
369331
+ translate27(cx, cy),
369332
+ scaleMatrix,
369333
+ translate27(-cx, -cy)
369334
+ ]);
369335
+ }
369336
+ var { tan: tan4 } = Math;
369337
+ function peg$subclass3(child, parent) {
369338
+ function C() {
369339
+ this.constructor = child;
369340
+ }
369341
+ C.prototype = parent.prototype;
369342
+ child.prototype = new C;
369343
+ }
369344
+ function peg$SyntaxError3(message, expected, found, location) {
369345
+ var self2 = Error.call(this, message);
369346
+ if (Object.setPrototypeOf) {
369347
+ Object.setPrototypeOf(self2, peg$SyntaxError3.prototype);
369348
+ }
369349
+ self2.expected = expected;
369350
+ self2.found = found;
369351
+ self2.location = location;
369352
+ self2.name = "SyntaxError";
369353
+ return self2;
369354
+ }
369355
+ peg$subclass3(peg$SyntaxError3, Error);
369356
+ function peg$padEnd3(str, targetLength, padString) {
369357
+ padString = padString || " ";
369358
+ if (str.length > targetLength) {
369359
+ return str;
369360
+ }
369361
+ targetLength -= str.length;
369362
+ padString += padString.repeat(targetLength);
369363
+ return str + padString.slice(0, targetLength);
369364
+ }
369365
+ peg$SyntaxError3.prototype.format = function(sources) {
369366
+ var str = "Error: " + this.message;
369367
+ if (this.location) {
369368
+ var src = null;
369369
+ var k;
369370
+ for (k = 0;k < sources.length; k++) {
369371
+ if (sources[k].source === this.location.source) {
369372
+ src = sources[k].text.split(/\r\n|\n|\r/g);
369373
+ break;
369374
+ }
369375
+ }
369376
+ var s = this.location.start;
369377
+ var offset_s = this.location.source && typeof this.location.source.offset === "function" ? this.location.source.offset(s) : s;
369378
+ var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
369379
+ if (src) {
369380
+ var e = this.location.end;
369381
+ var filler = peg$padEnd3("", offset_s.line.toString().length, " ");
369382
+ var line = src[s.line - 1];
369383
+ var last = s.line === e.line ? e.column : line.length + 1;
369384
+ var hatLen = last - s.column || 1;
369385
+ str += `
369386
+ --> ` + loc + `
369387
+ ` + filler + ` |
369388
+ ` + offset_s.line + " | " + line + `
369389
+ ` + filler + " | " + peg$padEnd3("", s.column - 1, " ") + peg$padEnd3("", hatLen, "^");
369390
+ } else {
369391
+ str += `
369392
+ at ` + loc;
369393
+ }
369394
+ }
369395
+ return str;
369396
+ };
369397
+ peg$SyntaxError3.buildMessage = function(expected, found) {
369398
+ var DESCRIBE_EXPECTATION_FNS = {
369399
+ literal: function(expectation) {
369400
+ return '"' + literalEscape(expectation.text) + '"';
369401
+ },
369402
+ class: function(expectation) {
369403
+ var escapedParts = expectation.parts.map(function(part) {
369404
+ return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part);
369405
+ });
369406
+ return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
369407
+ },
369408
+ any: function() {
369409
+ return "any character";
369410
+ },
369411
+ end: function() {
369412
+ return "end of input";
369413
+ },
369414
+ other: function(expectation) {
369415
+ return expectation.description;
369416
+ }
369417
+ };
369418
+ function hex(ch) {
369419
+ return ch.charCodeAt(0).toString(16).toUpperCase();
369420
+ }
369421
+ function literalEscape(s) {
369422
+ return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
369423
+ return "\\x0" + hex(ch);
369424
+ }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
369425
+ return "\\x" + hex(ch);
369426
+ });
369427
+ }
369428
+ function classEscape(s) {
369429
+ return s.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
369430
+ return "\\x0" + hex(ch);
369431
+ }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
369432
+ return "\\x" + hex(ch);
369433
+ });
369434
+ }
369435
+ function describeExpectation(expectation) {
369436
+ return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
369437
+ }
369438
+ function describeExpected(expected2) {
369439
+ var descriptions = expected2.map(describeExpectation);
369440
+ var i, j;
369441
+ descriptions.sort();
369442
+ if (descriptions.length > 0) {
369443
+ for (i = 1, j = 1;i < descriptions.length; i++) {
369444
+ if (descriptions[i - 1] !== descriptions[i]) {
369445
+ descriptions[j] = descriptions[i];
369446
+ j++;
369447
+ }
369448
+ }
369449
+ descriptions.length = j;
369450
+ }
369451
+ switch (descriptions.length) {
369452
+ case 1:
369453
+ return descriptions[0];
369454
+ case 2:
369455
+ return descriptions[0] + " or " + descriptions[1];
369456
+ default:
369457
+ return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
369458
+ }
369459
+ }
369460
+ function describeFound(found2) {
369461
+ return found2 ? '"' + literalEscape(found2) + '"' : "end of input";
369462
+ }
369463
+ return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
369464
+ };
369465
+ function decomposeTSR3(matrix, flipX = false, flipY = false) {
369466
+ if (flipX) {
369467
+ if (flipY) {
369468
+ matrix = compose28(matrix, scale15(-1, -1));
369469
+ } else {
369470
+ matrix = compose28(matrix, scale15(1, -1));
369471
+ }
369472
+ } else if (flipY) {
369473
+ matrix = compose28(matrix, scale15(-1, 1));
369474
+ }
369475
+ const a = matrix.a;
369476
+ const b = matrix.b;
369477
+ const c = matrix.c;
369478
+ const d = matrix.d;
369479
+ let scaleX, scaleY, rotation2;
369480
+ if (a !== 0 || c !== 0) {
369481
+ const hypotAc = Math.hypot(a, c);
369482
+ scaleX = hypotAc;
369483
+ scaleY = (a * d - b * c) / hypotAc;
369484
+ const acos = Math.acos(a / hypotAc);
369485
+ rotation2 = c > 0 ? -acos : acos;
369486
+ } else if (b !== 0 || d !== 0) {
369487
+ const hypotBd = Math.hypot(b, d);
369488
+ scaleX = (a * d - b * c) / hypotBd;
369489
+ scaleY = hypotBd;
369490
+ const acos = Math.acos(b / hypotBd);
369491
+ rotation2 = Math.PI / 2 + (d > 0 ? -acos : acos);
369492
+ } else {
369493
+ scaleX = 0;
369494
+ scaleY = 0;
369495
+ rotation2 = 0;
369496
+ }
369497
+ if (flipY) {
369498
+ scaleX = -scaleX;
369499
+ }
369500
+ if (flipX) {
369501
+ scaleY = -scaleY;
369502
+ }
369503
+ return {
369504
+ translate: { tx: matrix.e, ty: matrix.f },
369505
+ scale: { sx: scaleX, sy: scaleY },
369506
+ rotation: { angle: rotation2 }
369507
+ };
369508
+ }
369509
+ var getEasyEdaPlatedHoleGeometry2 = (pad) => {
369510
+ const holeDiameterMm = mil2mm2(pad.holeRadius) * 2;
369511
+ const holeLengthMm = pad.holeLength ? mil2mm2(pad.holeLength) : 0;
369512
+ let holeWidthMm = holeDiameterMm;
369513
+ let holeHeightMm = holeDiameterMm;
369514
+ if (holeLengthMm > holeDiameterMm) {
369515
+ if (!pad.holePoints) {
369516
+ throw new Error(`Slot on pad ${pad.number} is missing hole endpoints`);
369517
+ }
369518
+ const [start, end] = pad.holePoints;
369519
+ const localHoleDirection = applyToPoint107(rotateDEG3(pad.rotation), {
369520
+ x: end.x - start.x,
369521
+ y: end.y - start.y
369522
+ });
369523
+ const absX = Math.abs(localHoleDirection.x);
369524
+ const absY = Math.abs(localHoleDirection.y);
369525
+ if (Math.min(absX, absY) > Math.max(absX, absY) * 0.001) {
369526
+ throw new Error(`Slot on pad ${pad.number} is not aligned with its pad`);
369527
+ }
369528
+ if (absX > absY)
369529
+ holeWidthMm = holeLengthMm;
369530
+ else
369531
+ holeHeightMm = holeLengthMm;
369532
+ }
369533
+ if (pad.shape === "RECT") {
369534
+ return {
369535
+ shape: "rotated_pill_hole_with_rect_pad",
369536
+ hole_shape: "rotated_pill",
369537
+ pad_shape: "rect",
369538
+ hole_width: holeWidthMm,
369539
+ hole_height: holeHeightMm,
369540
+ hole_ccw_rotation: pad.rotation,
369541
+ rect_ccw_rotation: pad.rotation,
369542
+ rect_pad_width: mil2mm2(pad.width),
369543
+ rect_pad_height: mil2mm2(pad.height)
369544
+ };
369545
+ }
369546
+ if (pad.shape === "OVAL" || holeLengthMm > holeDiameterMm) {
369547
+ return {
369548
+ shape: "pill",
369549
+ hole_width: holeWidthMm,
369550
+ hole_height: holeHeightMm,
369551
+ outer_width: mil2mm2(pad.width),
369552
+ outer_height: mil2mm2(pad.height),
369553
+ ccw_rotation: pad.rotation
369554
+ };
369555
+ }
369556
+ return {
369557
+ shape: "circle",
369558
+ hole_diameter: holeDiameterMm,
369559
+ outer_diameter: mil2mm2(pad.width),
369560
+ radius: mil2mm2(pad.holeRadius)
369561
+ };
369562
+ };
369155
369563
  var normalizeActiveLowPinLabel2 = (label) => {
369156
369564
  const hasActiveLowMarker = label.startsWith("#") || label.endsWith("#");
369157
369565
  if (!hasActiveLowMarker)
@@ -373576,251 +373984,6 @@ var any_circuit_element2 = z198.union([
373576
373984
  var any_soup_element5 = any_circuit_element2;
373577
373985
  expectTypesMatch3(true);
373578
373986
  expectStringUnionsMatch2(true);
373579
- function applyToPoint107(matrix, point2) {
373580
- return Array.isArray(point2) ? [
373581
- matrix.a * point2[0] + matrix.c * point2[1] + matrix.e,
373582
- matrix.b * point2[0] + matrix.d * point2[1] + matrix.f
373583
- ] : {
373584
- x: matrix.a * point2.x + matrix.c * point2.y + matrix.e,
373585
- y: matrix.b * point2.x + matrix.d * point2.y + matrix.f
373586
- };
373587
- }
373588
- function isUndefined4(val) {
373589
- return typeof val === "undefined";
373590
- }
373591
- function translate27(tx, ty = 0) {
373592
- return {
373593
- a: 1,
373594
- c: 0,
373595
- e: tx,
373596
- b: 0,
373597
- d: 1,
373598
- f: ty
373599
- };
373600
- }
373601
- function transform3(...matrices) {
373602
- matrices = Array.isArray(matrices[0]) ? matrices[0] : matrices;
373603
- const multiply = (m1, m2) => {
373604
- return {
373605
- a: m1.a * m2.a + m1.c * m2.b,
373606
- c: m1.a * m2.c + m1.c * m2.d,
373607
- e: m1.a * m2.e + m1.c * m2.f + m1.e,
373608
- b: m1.b * m2.a + m1.d * m2.b,
373609
- d: m1.b * m2.c + m1.d * m2.d,
373610
- f: m1.b * m2.e + m1.d * m2.f + m1.f
373611
- };
373612
- };
373613
- switch (matrices.length) {
373614
- case 0:
373615
- throw new Error("no matrices provided");
373616
- case 1:
373617
- return matrices[0];
373618
- case 2:
373619
- return multiply(matrices[0], matrices[1]);
373620
- default: {
373621
- const [m1, m2, ...rest] = matrices;
373622
- const m3 = multiply(m1, m2);
373623
- return transform3(m3, ...rest);
373624
- }
373625
- }
373626
- }
373627
- function compose28(...matrices) {
373628
- return transform3(...matrices);
373629
- }
373630
- var { cos: cos4, sin: sin4, PI: PI4 } = Math;
373631
- function scale15(sx, sy = undefined, cx = undefined, cy = undefined) {
373632
- if (isUndefined4(sy))
373633
- sy = sx;
373634
- const scaleMatrix = {
373635
- a: sx,
373636
- c: 0,
373637
- e: 0,
373638
- b: 0,
373639
- d: sy,
373640
- f: 0
373641
- };
373642
- if (isUndefined4(cx) || isUndefined4(cy)) {
373643
- return scaleMatrix;
373644
- }
373645
- return transform3([
373646
- translate27(cx, cy),
373647
- scaleMatrix,
373648
- translate27(-cx, -cy)
373649
- ]);
373650
- }
373651
- var { tan: tan4 } = Math;
373652
- function peg$subclass3(child, parent) {
373653
- function C() {
373654
- this.constructor = child;
373655
- }
373656
- C.prototype = parent.prototype;
373657
- child.prototype = new C;
373658
- }
373659
- function peg$SyntaxError3(message, expected, found, location) {
373660
- var self2 = Error.call(this, message);
373661
- if (Object.setPrototypeOf) {
373662
- Object.setPrototypeOf(self2, peg$SyntaxError3.prototype);
373663
- }
373664
- self2.expected = expected;
373665
- self2.found = found;
373666
- self2.location = location;
373667
- self2.name = "SyntaxError";
373668
- return self2;
373669
- }
373670
- peg$subclass3(peg$SyntaxError3, Error);
373671
- function peg$padEnd3(str, targetLength, padString) {
373672
- padString = padString || " ";
373673
- if (str.length > targetLength) {
373674
- return str;
373675
- }
373676
- targetLength -= str.length;
373677
- padString += padString.repeat(targetLength);
373678
- return str + padString.slice(0, targetLength);
373679
- }
373680
- peg$SyntaxError3.prototype.format = function(sources) {
373681
- var str = "Error: " + this.message;
373682
- if (this.location) {
373683
- var src = null;
373684
- var k;
373685
- for (k = 0;k < sources.length; k++) {
373686
- if (sources[k].source === this.location.source) {
373687
- src = sources[k].text.split(/\r\n|\n|\r/g);
373688
- break;
373689
- }
373690
- }
373691
- var s = this.location.start;
373692
- var offset_s = this.location.source && typeof this.location.source.offset === "function" ? this.location.source.offset(s) : s;
373693
- var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
373694
- if (src) {
373695
- var e = this.location.end;
373696
- var filler = peg$padEnd3("", offset_s.line.toString().length, " ");
373697
- var line = src[s.line - 1];
373698
- var last = s.line === e.line ? e.column : line.length + 1;
373699
- var hatLen = last - s.column || 1;
373700
- str += `
373701
- --> ` + loc + `
373702
- ` + filler + ` |
373703
- ` + offset_s.line + " | " + line + `
373704
- ` + filler + " | " + peg$padEnd3("", s.column - 1, " ") + peg$padEnd3("", hatLen, "^");
373705
- } else {
373706
- str += `
373707
- at ` + loc;
373708
- }
373709
- }
373710
- return str;
373711
- };
373712
- peg$SyntaxError3.buildMessage = function(expected, found) {
373713
- var DESCRIBE_EXPECTATION_FNS = {
373714
- literal: function(expectation) {
373715
- return '"' + literalEscape(expectation.text) + '"';
373716
- },
373717
- class: function(expectation) {
373718
- var escapedParts = expectation.parts.map(function(part) {
373719
- return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part);
373720
- });
373721
- return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
373722
- },
373723
- any: function() {
373724
- return "any character";
373725
- },
373726
- end: function() {
373727
- return "end of input";
373728
- },
373729
- other: function(expectation) {
373730
- return expectation.description;
373731
- }
373732
- };
373733
- function hex(ch) {
373734
- return ch.charCodeAt(0).toString(16).toUpperCase();
373735
- }
373736
- function literalEscape(s) {
373737
- return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
373738
- return "\\x0" + hex(ch);
373739
- }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
373740
- return "\\x" + hex(ch);
373741
- });
373742
- }
373743
- function classEscape(s) {
373744
- return s.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
373745
- return "\\x0" + hex(ch);
373746
- }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
373747
- return "\\x" + hex(ch);
373748
- });
373749
- }
373750
- function describeExpectation(expectation) {
373751
- return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
373752
- }
373753
- function describeExpected(expected2) {
373754
- var descriptions = expected2.map(describeExpectation);
373755
- var i, j;
373756
- descriptions.sort();
373757
- if (descriptions.length > 0) {
373758
- for (i = 1, j = 1;i < descriptions.length; i++) {
373759
- if (descriptions[i - 1] !== descriptions[i]) {
373760
- descriptions[j] = descriptions[i];
373761
- j++;
373762
- }
373763
- }
373764
- descriptions.length = j;
373765
- }
373766
- switch (descriptions.length) {
373767
- case 1:
373768
- return descriptions[0];
373769
- case 2:
373770
- return descriptions[0] + " or " + descriptions[1];
373771
- default:
373772
- return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
373773
- }
373774
- }
373775
- function describeFound(found2) {
373776
- return found2 ? '"' + literalEscape(found2) + '"' : "end of input";
373777
- }
373778
- return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
373779
- };
373780
- function decomposeTSR3(matrix, flipX = false, flipY = false) {
373781
- if (flipX) {
373782
- if (flipY) {
373783
- matrix = compose28(matrix, scale15(-1, -1));
373784
- } else {
373785
- matrix = compose28(matrix, scale15(1, -1));
373786
- }
373787
- } else if (flipY) {
373788
- matrix = compose28(matrix, scale15(-1, 1));
373789
- }
373790
- const a = matrix.a;
373791
- const b = matrix.b;
373792
- const c = matrix.c;
373793
- const d = matrix.d;
373794
- let scaleX, scaleY, rotation2;
373795
- if (a !== 0 || c !== 0) {
373796
- const hypotAc = Math.hypot(a, c);
373797
- scaleX = hypotAc;
373798
- scaleY = (a * d - b * c) / hypotAc;
373799
- const acos = Math.acos(a / hypotAc);
373800
- rotation2 = c > 0 ? -acos : acos;
373801
- } else if (b !== 0 || d !== 0) {
373802
- const hypotBd = Math.hypot(b, d);
373803
- scaleX = (a * d - b * c) / hypotBd;
373804
- scaleY = hypotBd;
373805
- const acos = Math.acos(b / hypotBd);
373806
- rotation2 = Math.PI / 2 + (d > 0 ? -acos : acos);
373807
- } else {
373808
- scaleX = 0;
373809
- scaleY = 0;
373810
- rotation2 = 0;
373811
- }
373812
- if (flipY) {
373813
- scaleX = -scaleX;
373814
- }
373815
- if (flipX) {
373816
- scaleY = -scaleY;
373817
- }
373818
- return {
373819
- translate: { tx: matrix.e, ty: matrix.f },
373820
- scale: { sx: scaleX, sy: scaleY },
373821
- rotation: { angle: rotation2 }
373822
- };
373823
- }
373824
373987
  function connect3(map, a, b) {
373825
373988
  if (!a || !b)
373826
373989
  return;
@@ -375113,38 +375276,6 @@ var PIN1_LOCATION_PARTS2 = {
375113
375276
  bottomside_right: { side: "bottomside", alignment: "right" }
375114
375277
  };
375115
375278
  var PIN1_LOCATIONS3 = Object.keys(PIN1_LOCATION_PARTS2);
375116
- var unitToMm4 = {
375117
- in: 25.4,
375118
- inch: 25.4,
375119
- mil: 0.0254,
375120
- mm: 1,
375121
- m: 1000,
375122
- cm: 10,
375123
- ft: 304.8,
375124
- feet: 304.8
375125
- };
375126
- var mmNumberFormatter2 = new Intl.NumberFormat("en-US", {
375127
- useGrouping: false,
375128
- notation: "standard",
375129
- maximumFractionDigits: 12
375130
- });
375131
- var mm5 = (n) => {
375132
- let unit = typeof n === "number" ? "mm" : n.replace(/^[^a-zA-Z]+/g, "").toLowerCase();
375133
- if (!unit)
375134
- unit = "mm";
375135
- const val = typeof n === "number" ? n : Number.parseFloat(n.split(unit)[0]);
375136
- if (unit in unitToMm4) {
375137
- return val * unitToMm4[unit];
375138
- }
375139
- throw new Error(`Unsupported unit: ${unit}`);
375140
- };
375141
- var mil2mm2 = (mil) => {
375142
- if (typeof mil === "number")
375143
- return mm5(`${mil}mil`);
375144
- if (mil.match(/^\d+$/))
375145
- return mm5(`${mil}mil`);
375146
- return mm5(mil);
375147
- };
375148
375279
  var DEFAULT_PCB_THICKNESS_MM2 = 1.6;
375149
375280
  function generateArcFromSweep2(startX, startY, endX, endY, radius, largeArcFlag, sweepFlag) {
375150
375281
  const start = { x: startX, y: startY };
@@ -375780,68 +375911,7 @@ var convertEasyEdaJsonToCircuitJson2 = (easyEdaJson, {
375780
375911
  pcb_component_id: "pcb_component_1",
375781
375912
  pcb_port_id: `pcb_port_${index + 1}`
375782
375913
  };
375783
- let additionalPlatedHoleProps;
375784
- if (pad.shape === "OVAL") {
375785
- const largestOuterDimensionName = mil2mm2(pad.width) > mil2mm2(pad.height) ? "width" : "height";
375786
- const smallestOuterDimension = Math.min(mil2mm2(pad.width), mil2mm2(pad.height));
375787
- const largestOuterDimension = Math.max(mil2mm2(pad.width), mil2mm2(pad.height));
375788
- const distanceFromOuterPlatingToHole = smallestOuterDimension / 2 - mil2mm2(pad.holeRadius);
375789
- const largestInnerDimension = largestOuterDimension - distanceFromOuterPlatingToHole * 2;
375790
- const smallestInnerDimension = mil2mm2(pad.holeRadius) * 2;
375791
- const innerWidth = largestOuterDimensionName === "width" ? largestInnerDimension : smallestInnerDimension;
375792
- const innerHeight = largestOuterDimensionName === "height" ? largestInnerDimension : smallestInnerDimension;
375793
- additionalPlatedHoleProps = {
375794
- shape: "pill",
375795
- hole_width: innerWidth,
375796
- hole_height: innerHeight,
375797
- outer_width: mil2mm2(pad.width),
375798
- outer_height: mil2mm2(pad.height),
375799
- ccw_rotation: pad.rotation || 0
375800
- };
375801
- } else if (pad.shape === "RECT") {
375802
- const padWidth = mil2mm2(pad.width);
375803
- const padHeight = mil2mm2(pad.height);
375804
- const holeRadius = mil2mm2(pad.holeRadius);
375805
- const holeDiameter = holeRadius * 2;
375806
- const aspectRatio = Math.max(padWidth, padHeight) / Math.min(padWidth, padHeight);
375807
- const isSignificantlyRectangular = aspectRatio > 1.5;
375808
- if (isSignificantlyRectangular) {
375809
- const baseWidth = holeDiameter;
375810
- const pillHeight = baseWidth * 2.6;
375811
- const holeWidth = padWidth > padHeight ? pillHeight : baseWidth;
375812
- const holeHeight = padHeight > padWidth ? pillHeight : baseWidth;
375813
- additionalPlatedHoleProps = {
375814
- shape: "rotated_pill_hole_with_rect_pad",
375815
- hole_shape: "rotated_pill",
375816
- pad_shape: "rect",
375817
- hole_width: holeWidth,
375818
- hole_height: holeHeight,
375819
- hole_ccw_rotation: pad.rotation || 0,
375820
- rect_ccw_rotation: pad.rotation || 0,
375821
- rect_pad_width: padWidth,
375822
- rect_pad_height: padHeight
375823
- };
375824
- } else {
375825
- additionalPlatedHoleProps = {
375826
- shape: "rotated_pill_hole_with_rect_pad",
375827
- hole_shape: "rotated_pill",
375828
- pad_shape: "rect",
375829
- hole_width: holeDiameter,
375830
- hole_height: holeDiameter,
375831
- hole_ccw_rotation: pad.rotation || 0,
375832
- rect_ccw_rotation: pad.rotation || 0,
375833
- rect_pad_width: padWidth,
375834
- rect_pad_height: padHeight
375835
- };
375836
- }
375837
- } else {
375838
- additionalPlatedHoleProps = {
375839
- shape: "circle",
375840
- hole_diameter: mil2mm2(pad.holeRadius) * 2,
375841
- outer_diameter: mil2mm2(pad.width),
375842
- radius: mil2mm2(pad.holeRadius)
375843
- };
375844
- }
375914
+ const additionalPlatedHoleProps = getEasyEdaPlatedHoleGeometry2(pad);
375845
375915
  circuitElements.push(pcb_plated_hole2.parse({
375846
375916
  ...commonPlatedHoleProps,
375847
375917
  ...additionalPlatedHoleProps
@@ -376216,6 +376286,8 @@ var PadSchema2 = BaseShapeSchema2.extend({
376216
376286
  net: z200.union([z200.string(), z200.number()]).optional(),
376217
376287
  number: z200.union([z200.string(), z200.number()]),
376218
376288
  holeRadius: tenthmil2,
376289
+ holeLength: tenthmil2.optional(),
376290
+ holePoints: z200.array(PointSchema3).length(2).optional(),
376219
376291
  points: z200.array(PointSchema3).optional(),
376220
376292
  rotation: safeNumber2(0),
376221
376293
  plated: z200.boolean()
@@ -376348,6 +376420,8 @@ var ShapeItemSchema2 = z200.object({
376348
376420
  net,
376349
376421
  number: padNumber,
376350
376422
  holeRadius,
376423
+ holeLength: rest[3] === undefined || rest[3] === "" ? undefined : rest[3],
376424
+ holePoints: rest[4] ? parsePoints3(String(rest[4])) : undefined,
376351
376425
  points,
376352
376426
  rotation: rotation2,
376353
376427
  plated: rest.includes("Y")
package/dist/lib/index.js CHANGED
@@ -69109,7 +69109,7 @@ var getNodeHandler = (winterSpec, { port, middleware = [] }) => {
69109
69109
  }));
69110
69110
  };
69111
69111
  // package.json
69112
- var version = "0.1.2230";
69112
+ var version = "0.1.2232";
69113
69113
  var package_default = {
69114
69114
  name: "@tscircuit/cli",
69115
69115
  version,
@@ -69133,7 +69133,7 @@ var package_default = {
69133
69133
  "@tscircuit/eval": "0.0.1402",
69134
69134
  "@tscircuit/fake-snippets": "^0.0.182",
69135
69135
  "@tscircuit/file-server": "^0.0.32",
69136
- "@tscircuit/footprinter": "^0.0.426",
69136
+ "@tscircuit/footprinter": "^0.0.430",
69137
69137
  "@tscircuit/image-utils": "^0.0.8",
69138
69138
  "@tscircuit/krt-wasm": "^0.1.6",
69139
69139
  "@tscircuit/math-utils": "0.0.36",
@@ -69159,7 +69159,7 @@ var package_default = {
69159
69159
  "circuit-json-to-bom-csv": "^0.0.19",
69160
69160
  "circuit-json-to-connectivity-map": "^0.0.32",
69161
69161
  "circuit-json-to-fdm-component-box": "^0.0.2",
69162
- "circuit-json-to-footprinter": "^0.0.58",
69162
+ "circuit-json-to-footprinter": "^0.0.59",
69163
69163
  "circuit-json-to-gerber": "^0.0.105",
69164
69164
  "circuit-json-to-kicad": "0.0.230",
69165
69165
  "circuit-json-to-pnp-csv": "^0.0.18",
@@ -69178,7 +69178,7 @@ var package_default = {
69178
69178
  debug: "^4.4.0",
69179
69179
  delay: "^6.0.0",
69180
69180
  "dsn-converter": "^0.0.90",
69181
- easyeda: "^0.0.366",
69181
+ easyeda: "^0.0.368",
69182
69182
  "fuse.js": "^7.1.0",
69183
69183
  "get-port": "^7.1.0",
69184
69184
  globby: "^14.1.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/cli",
3
- "version": "0.1.2231",
3
+ "version": "0.1.2233",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/tscircuit/cli"
@@ -21,7 +21,7 @@
21
21
  "@tscircuit/eval": "0.0.1402",
22
22
  "@tscircuit/fake-snippets": "^0.0.182",
23
23
  "@tscircuit/file-server": "^0.0.32",
24
- "@tscircuit/footprinter": "^0.0.426",
24
+ "@tscircuit/footprinter": "^0.0.430",
25
25
  "@tscircuit/image-utils": "^0.0.8",
26
26
  "@tscircuit/krt-wasm": "^0.1.6",
27
27
  "@tscircuit/math-utils": "0.0.36",
@@ -47,7 +47,7 @@
47
47
  "circuit-json-to-bom-csv": "^0.0.19",
48
48
  "circuit-json-to-connectivity-map": "^0.0.32",
49
49
  "circuit-json-to-fdm-component-box": "^0.0.2",
50
- "circuit-json-to-footprinter": "^0.0.58",
50
+ "circuit-json-to-footprinter": "^0.0.59",
51
51
  "circuit-json-to-gerber": "^0.0.105",
52
52
  "circuit-json-to-kicad": "0.0.230",
53
53
  "circuit-json-to-pnp-csv": "^0.0.18",
@@ -66,7 +66,7 @@
66
66
  "debug": "^4.4.0",
67
67
  "delay": "^6.0.0",
68
68
  "dsn-converter": "^0.0.90",
69
- "easyeda": "^0.0.366",
69
+ "easyeda": "^0.0.368",
70
70
  "fuse.js": "^7.1.0",
71
71
  "get-port": "^7.1.0",
72
72
  "globby": "^14.1.0",