easyeda 0.0.263 → 0.0.265

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/main.cjs CHANGED
@@ -997,7 +997,7 @@ var import_promises = __toESM(require("fs/promises"), 1);
997
997
  var package_default = {
998
998
  name: "easyeda",
999
999
  type: "module",
1000
- version: "0.0.262",
1000
+ version: "0.0.264",
1001
1001
  files: [
1002
1002
  "dist"
1003
1003
  ],
@@ -1006,35 +1006,12 @@ var package_default = {
1006
1006
  type: "git",
1007
1007
  url: "https://github.com/tscircuit/easyeda-converter"
1008
1008
  },
1009
- scripts: {
1010
- test: "bun test",
1011
- cli: "bun cli/main.ts",
1012
- build: "tsup",
1013
- aider: "aider",
1014
- "format:check": "biome format .",
1015
- format: "biome format . --write",
1016
- "add-test-for-part": "bun run scripts/add-test-for-part.ts"
1017
- },
1018
1009
  main: "./dist/index.js",
1019
- types: "./dist/index.d.ts",
1020
- exports: {
1021
- ".": {
1022
- types: "./dist/index.d.ts",
1023
- default: "./dist/index.js"
1024
- },
1025
- "./browser": {
1026
- types: "./dist/browser/index.d.ts",
1027
- default: "./dist/browser/index.js"
1028
- }
1029
- },
1030
- bin: {
1031
- "easyeda-converter": "./dist/main.cjs",
1032
- easyeda: "./dist/main.cjs"
1033
- },
1034
1010
  devDependencies: {
1035
1011
  "@biomejs/biome": "^1.9.4",
1036
1012
  "@tscircuit/alphabet": "^0.0.22",
1037
1013
  "@tscircuit/circuit-json-util": "^0.0.90",
1014
+ "@tscircuit/math-utils": "^0.0.36",
1038
1015
  "@tscircuit/mm": "^0.0.9",
1039
1016
  "@types/bun": "latest",
1040
1017
  "bun-match-svg": "^0.0.13",
@@ -1049,7 +1026,31 @@ var package_default = {
1049
1026
  peerDependencies: {
1050
1027
  typescript: "^5.5.2",
1051
1028
  zod: "3"
1052
- }
1029
+ },
1030
+ exports: {
1031
+ ".": {
1032
+ types: "./dist/index.d.ts",
1033
+ default: "./dist/index.js"
1034
+ },
1035
+ "./browser": {
1036
+ types: "./dist/browser/index.d.ts",
1037
+ default: "./dist/browser/index.js"
1038
+ }
1039
+ },
1040
+ bin: {
1041
+ "easyeda-converter": "./dist/main.cjs",
1042
+ easyeda: "./dist/main.cjs"
1043
+ },
1044
+ scripts: {
1045
+ test: "bun test",
1046
+ cli: "bun cli/main.ts",
1047
+ build: "tsup",
1048
+ aider: "aider",
1049
+ "format:check": "biome format .",
1050
+ format: "biome format . --write",
1051
+ "add-test-for-part": "bun run scripts/add-test-for-part.ts"
1052
+ },
1053
+ types: "./dist/index.d.ts"
1053
1054
  };
1054
1055
 
1055
1056
  // node_modules/circuit-json/dist/index.mjs
@@ -6081,11 +6082,11 @@ function generateArcFromSweep(startX, startY, endX, endY, radius, largeArcFlag,
6081
6082
  const midY = (startY + endY) / 2;
6082
6083
  const dx = endX - startX;
6083
6084
  const dy = endY - startY;
6084
- const distance2 = Math.sqrt(dx * dx + dy * dy);
6085
- if (distance2 === 0 || radius < distance2 / 2) {
6085
+ const distance3 = Math.sqrt(dx * dx + dy * dy);
6086
+ if (distance3 === 0 || radius < distance3 / 2) {
6086
6087
  return [start, end];
6087
6088
  }
6088
- const h = Math.sqrt(radius * radius - distance2 * distance2 / 4);
6089
+ const h = Math.sqrt(radius * radius - distance3 * distance3 / 4);
6089
6090
  const angle = Math.atan2(dy, dx);
6090
6091
  const centerX = midX + h * Math.sin(angle) * (sweepFlag ? -1 : 1);
6091
6092
  const centerY = midY - h * Math.cos(angle) * (sweepFlag ? -1 : 1);
@@ -6121,6 +6122,142 @@ function generateArcFromSweep(startX, startY, endX, endY, radius, largeArcFlag,
6121
6122
  // lib/utils/easyeda-unit-to-mm.ts
6122
6123
  var mil10ToMm = (value) => value * 10 * 0.0254;
6123
6124
 
6125
+ // node_modules/@tscircuit/math-utils/dist/chunk-3WCUPG5S.js
6126
+ var getBoundsCenter = (bounds) => ({
6127
+ x: (bounds.minX + bounds.maxX) / 2,
6128
+ y: (bounds.minY + bounds.maxY) / 2
6129
+ });
6130
+
6131
+ // node_modules/@tscircuit/math-utils/dist/chunk-5N7UJNVK.js
6132
+ var getBoundsFromPoints = (points) => {
6133
+ if (points.length === 0) {
6134
+ return null;
6135
+ }
6136
+ let minX = points[0].x;
6137
+ let minY = points[0].y;
6138
+ let maxX = points[0].x;
6139
+ let maxY = points[0].y;
6140
+ for (let i = 1; i < points.length; i++) {
6141
+ const point2 = points[i];
6142
+ if (point2.x < minX) minX = point2.x;
6143
+ if (point2.y < minY) minY = point2.y;
6144
+ if (point2.x > maxX) maxX = point2.x;
6145
+ if (point2.y > maxY) maxY = point2.y;
6146
+ }
6147
+ return { minX, minY, maxX, maxY };
6148
+ };
6149
+
6150
+ // lib/websafe/get-easyeda-cad-placement-helpers.ts
6151
+ var getCadSvgNode = (easyEdaJson) => {
6152
+ const svgNode = easyEdaJson.packageDetail.dataStr.shape.find(
6153
+ (shape) => shape.type === "SVGNODE" && shape.svgData.attrs?.uuid
6154
+ );
6155
+ return svgNode?.type === "SVGNODE" ? svgNode : null;
6156
+ };
6157
+ var isSvgChildNodeWithAttrs = (childNode) => typeof childNode === "object" && childNode !== null;
6158
+ var getXyBoundsFromModelBounds = (bounds) => ({
6159
+ minX: bounds.min.x,
6160
+ minY: bounds.min.y,
6161
+ maxX: bounds.max.x,
6162
+ maxY: bounds.max.y
6163
+ });
6164
+ var rotateScenePoint = (point2, rotationDeg) => {
6165
+ switch (rotationDeg) {
6166
+ case 0:
6167
+ return point2;
6168
+ case 90:
6169
+ return { x: point2.y, y: -point2.x };
6170
+ case 180:
6171
+ return { x: -point2.x, y: -point2.y };
6172
+ case 270:
6173
+ return { x: -point2.y, y: point2.x };
6174
+ }
6175
+ };
6176
+ var getEasyEdaModelOriginOnBoardMm = ({
6177
+ svgNode,
6178
+ footprintCenterMm
6179
+ }) => {
6180
+ const points = [];
6181
+ for (const childNode of svgNode.svgData.childNodes ?? []) {
6182
+ if (!isSvgChildNodeWithAttrs(childNode)) continue;
6183
+ const rawPoints = childNode.attrs?.points;
6184
+ if (!rawPoints) continue;
6185
+ const values = String(rawPoints).trim().split(/\s+/).map(Number);
6186
+ for (let i = 0; i + 1 < values.length; i += 2) {
6187
+ const x = values[i];
6188
+ const y = values[i + 1];
6189
+ if (Number.isFinite(x) && Number.isFinite(y)) {
6190
+ points.push({ x: mil10ToMm(x), y: mil10ToMm(y) });
6191
+ }
6192
+ }
6193
+ }
6194
+ let modelOriginMm = null;
6195
+ if (points.length > 0) {
6196
+ const bounds = getBoundsFromPoints(points);
6197
+ modelOriginMm = bounds ? getBoundsCenter(bounds) : null;
6198
+ } else {
6199
+ const [originX, originY] = String(svgNode.svgData.attrs?.c_origin ?? "0,0").split(",").map((value) => Number(value.trim()));
6200
+ if (Number.isFinite(originX) && Number.isFinite(originY)) {
6201
+ modelOriginMm = { x: mil10ToMm(originX), y: mil10ToMm(originY) };
6202
+ }
6203
+ }
6204
+ if (!modelOriginMm) return null;
6205
+ return {
6206
+ x: modelOriginMm.x - footprintCenterMm.x,
6207
+ y: footprintCenterMm.y - modelOriginMm.y
6208
+ };
6209
+ };
6210
+ var snapZero = (value) => Math.abs(value) < 1e-6 ? 0 : value;
6211
+ var normalizePoint = (point2) => ({
6212
+ x: snapZero(point2.x),
6213
+ y: snapZero(point2.y)
6214
+ });
6215
+ var getCadModelOffsetMm = (easyEdaJson) => {
6216
+ const svgNode = getCadSvgNode(easyEdaJson);
6217
+ return getCadModelOffsetMmFromBounds(
6218
+ easyEdaJson,
6219
+ easyEdaJson._objMetadata?.bounds
6220
+ );
6221
+ };
6222
+ var getCadModelOffsetMmFromBounds = (easyEdaJson, bounds, {
6223
+ footprintBoundsCenterMm
6224
+ } = {}) => {
6225
+ const svgNode = getCadSvgNode(easyEdaJson);
6226
+ if (!svgNode || !bounds) return null;
6227
+ const [, , rotationZRaw] = String(
6228
+ svgNode.svgData.attrs?.c_rotation ?? "0,0,0"
6229
+ ).split(",").map((value) => Number(value.trim()));
6230
+ const rotationDeg = (rotationZRaw % 360 + 360) % 360;
6231
+ if (![0, 90, 180, 270].includes(rotationDeg)) return null;
6232
+ const modelCenter = getBoundsCenter(getXyBoundsFromModelBounds(bounds));
6233
+ const footprintCenter = easyEdaJson.packageDetail.dataStr.head;
6234
+ const footprintCenterMm = footprintBoundsCenterMm ?? {
6235
+ x: mil10ToMm(footprintCenter.x),
6236
+ y: mil10ToMm(footprintCenter.y)
6237
+ };
6238
+ const targetOriginOnBoardMm = getEasyEdaModelOriginOnBoardMm({
6239
+ svgNode,
6240
+ footprintCenterMm
6241
+ });
6242
+ if (!targetOriginOnBoardMm) return null;
6243
+ const targetOriginInModelFrame = rotateScenePoint(
6244
+ targetOriginOnBoardMm,
6245
+ rotationDeg
6246
+ );
6247
+ return normalizePoint({
6248
+ x: modelCenter.x - targetOriginInModelFrame.x,
6249
+ y: modelCenter.y - targetOriginInModelFrame.y
6250
+ });
6251
+ };
6252
+ var getCadSvgNodeZOffsetMm = (easyEdaJson) => {
6253
+ const svgNode = getCadSvgNode(easyEdaJson);
6254
+ if (!svgNode) return null;
6255
+ const svgNodeZ = Number(svgNode.svgData.attrs?.z ?? 0);
6256
+ if (!Number.isFinite(svgNodeZ)) return null;
6257
+ return mil10ToMm(svgNodeZ);
6258
+ };
6259
+ var getCadSvgNodeModelUuid = (easyEdaJson) => getCadSvgNode(easyEdaJson)?.svgData.attrs?.uuid ?? null;
6260
+
6124
6261
  // lib/utils/normalize-pin-labels.ts
6125
6262
  var normalizePinLabels = (inputPinLabels) => {
6126
6263
  const uniqueInputPinLabels = inputPinLabels.map((labels) => [
@@ -6337,6 +6474,7 @@ var convertEasyEdaJsonToCircuitJson = (easyEdaJson, {
6337
6474
  cadPositionXMm,
6338
6475
  cadPositionYMm,
6339
6476
  cadPositionZMm,
6477
+ cadModelBounds,
6340
6478
  showDesignator = false
6341
6479
  } = {}) => {
6342
6480
  const resolvedCadPositionZMm = cadPositionZMm ?? getCadPositionZMmFromMetadata(easyEdaJson);
@@ -6475,7 +6613,7 @@ var convertEasyEdaJsonToCircuitJson = (easyEdaJson, {
6475
6613
  } else if (pad.shape === "ELLIPSE") {
6476
6614
  soupShape = "rect";
6477
6615
  } else if (pad.shape === "OVAL") {
6478
- soupShape = "rect";
6616
+ soupShape = "pill";
6479
6617
  } else if (pad.shape === "POLYGON") {
6480
6618
  soupShape = "polygon";
6481
6619
  }
@@ -6495,12 +6633,17 @@ var convertEasyEdaJsonToCircuitJson = (easyEdaJson, {
6495
6633
  x: mil2mm(pad.center.x),
6496
6634
  y: mil2mm(pad.center.y)
6497
6635
  },
6498
- ...soupShape === "rect" ? rectSize : soupShape === "polygon" && pad.points ? {
6636
+ ...soupShape === "rect" ? rectSize : soupShape === "pill" ? {
6637
+ ...rectSize,
6638
+ radius: Math.min(rectSize.width, rectSize.height) / 2
6639
+ } : soupShape === "polygon" && pad.points ? {
6499
6640
  points: pad.points.map((p) => ({
6500
6641
  x: milx10(p.x),
6501
6642
  y: milx10(p.y)
6502
6643
  }))
6503
- } : { radius: Math.min(mil2mm(pad.width), mil2mm(pad.height)) / 2 },
6644
+ } : {
6645
+ radius: Math.min(mil2mm(pad.width), mil2mm(pad.height)) / 2
6646
+ },
6504
6647
  layer: "top",
6505
6648
  port_hints: [`pin${pinNumber}`],
6506
6649
  pcb_component_id: "pcb_component_1",
@@ -6689,6 +6832,14 @@ var convertEasyEdaJsonToCircuitJson = (easyEdaJson, {
6689
6832
  if (!cad.model_origin_position) {
6690
6833
  cad.model_origin_position = { x: 0, y: 0, z: 0 };
6691
6834
  }
6835
+ const resolvedCadModelBounds = cadModelBounds ?? easyEdaJson._objMetadata?.bounds;
6836
+ const recenteredCadOffset = resolvedCadModelBounds && getCadModelOffsetMmFromBounds(easyEdaJson, resolvedCadModelBounds, {
6837
+ footprintBoundsCenterMm: bounds.center
6838
+ });
6839
+ if (recenteredCadOffset) {
6840
+ cad.model_origin_position.x = recenteredCadOffset.x;
6841
+ cad.model_origin_position.y = recenteredCadOffset.y;
6842
+ }
6692
6843
  const side = pcb_component2.layer ?? "top";
6693
6844
  const t = DEFAULT_PCB_THICKNESS_MM / 2;
6694
6845
  const attrs = svgNode?.svgData?.attrs ?? {};
@@ -7513,98 +7664,6 @@ function normalizeManufacturerPartNumber(partNumber) {
7513
7664
  return normalized;
7514
7665
  }
7515
7666
 
7516
- // lib/websafe/get-easyeda-cad-placement-helpers.ts
7517
- var milToMm = (mil) => mil * 0.0254;
7518
- var getBoundsCenter = (bounds) => ({
7519
- x: (bounds.min.x + bounds.max.x) / 2,
7520
- y: (bounds.min.y + bounds.max.y) / 2
7521
- });
7522
- var getCadSvgNode = (easyEdaJson) => {
7523
- const svgNode = easyEdaJson.packageDetail.dataStr.shape.find(
7524
- (shape) => shape.type === "SVGNODE" && shape.svgData.attrs?.uuid
7525
- );
7526
- return svgNode?.type === "SVGNODE" ? svgNode : null;
7527
- };
7528
- var parseMil10Value = (value) => Number(String(value).replace("mil", "")) / 10;
7529
- var isZeroishModelCenter = (value) => Math.abs(value) < 1e-6;
7530
- var isZeroishFootprintDelta = (value) => Math.abs(value) < 1e-3;
7531
- var getPadCenter = (easyEdaJson) => {
7532
- const pads = easyEdaJson.packageDetail.dataStr.shape.filter(
7533
- (shape) => shape.type === "PAD"
7534
- );
7535
- if (pads.length === 0) return null;
7536
- const xs = pads.map((pad) => parseMil10Value(pad.center.x));
7537
- const ys = pads.map((pad) => parseMil10Value(pad.center.y));
7538
- return {
7539
- x: (Math.min(...xs) + Math.max(...xs)) / 2,
7540
- y: (Math.min(...ys) + Math.max(...ys)) / 2
7541
- };
7542
- };
7543
- var getRotatedOffsetMm = ({
7544
- bounds,
7545
- rawOffsetMil,
7546
- rotationDeg
7547
- }) => {
7548
- const center = getBoundsCenter(bounds);
7549
- const offsetX = milToMm(rawOffsetMil.x);
7550
- const offsetY = milToMm(rawOffsetMil.y);
7551
- switch (rotationDeg) {
7552
- case 0:
7553
- return { x: center.x + offsetX, y: center.y + offsetY };
7554
- case 90:
7555
- return { x: center.x + offsetY, y: center.y + offsetX };
7556
- case 180:
7557
- return { x: center.x - offsetX, y: center.y - offsetY };
7558
- case 270:
7559
- return { x: center.x - offsetY, y: center.y - offsetX };
7560
- }
7561
- };
7562
- var getCadModelOffsetMm = (easyEdaJson) => {
7563
- const svgNode = getCadSvgNode(easyEdaJson);
7564
- return getCadModelOffsetMmFromBounds(
7565
- easyEdaJson,
7566
- easyEdaJson._objMetadata?.bounds
7567
- );
7568
- };
7569
- var getCadModelOffsetMmFromBounds = (easyEdaJson, bounds) => {
7570
- const svgNode = getCadSvgNode(easyEdaJson);
7571
- if (!svgNode || !bounds) return null;
7572
- const [originX, originY] = String(svgNode.svgData.attrs?.c_origin ?? "0,0").split(",").map((value) => Number(value.trim()));
7573
- if (!Number.isFinite(originX) || !Number.isFinite(originY)) return null;
7574
- const [, , rotationZRaw] = String(
7575
- svgNode.svgData.attrs?.c_rotation ?? "0,0,0"
7576
- ).split(",").map((value) => Number(value.trim()));
7577
- const rotationDeg = (rotationZRaw % 360 + 360) % 360;
7578
- if (![0, 90, 180, 270].includes(rotationDeg)) return null;
7579
- const modelCenter = getBoundsCenter(bounds);
7580
- const footprintCenter = easyEdaJson.packageDetail.dataStr.head;
7581
- const padCenter = getPadCenter(easyEdaJson);
7582
- const padCenterDelta = padCenter ? {
7583
- x: padCenter.x - footprintCenter.x,
7584
- y: padCenter.y - footprintCenter.y
7585
- } : null;
7586
- const rawOffsetMil = {
7587
- x: (originX - footprintCenter.x) * 10,
7588
- y: (originY - footprintCenter.y) * 10
7589
- };
7590
- if (padCenter && padCenterDelta && isZeroishModelCenter(modelCenter.x) && isZeroishModelCenter(modelCenter.y) && isZeroishFootprintDelta(padCenterDelta.x) && isZeroishFootprintDelta(padCenterDelta.y)) {
7591
- return { x: 0, y: 0 };
7592
- }
7593
- return getRotatedOffsetMm({
7594
- bounds,
7595
- rawOffsetMil,
7596
- rotationDeg
7597
- });
7598
- };
7599
- var getCadSvgNodeZOffsetMm = (easyEdaJson) => {
7600
- const svgNode = getCadSvgNode(easyEdaJson);
7601
- if (!svgNode) return null;
7602
- const svgNodeZ = Number(svgNode.svgData.attrs?.z ?? 0);
7603
- if (!Number.isFinite(svgNodeZ)) return null;
7604
- return mil10ToMm(svgNodeZ);
7605
- };
7606
- var getCadSvgNodeModelUuid = (easyEdaJson) => getCadSvgNode(easyEdaJson)?.svgData.attrs?.uuid ?? null;
7607
-
7608
7667
  // lib/websafe/get-easyeda-cad-model-placement.ts
7609
7668
  var placementCache = /* @__PURE__ */ new Map();
7610
7669
  var parseObjBounds2 = (objText) => {
@@ -7755,8 +7814,14 @@ var generateFootprintTsx = (circuitJson, options = {}) => {
7755
7814
  `<smtpad portHints={${JSON.stringify(mapPortHints(smtPad.port_hints, options.portHintsMap))}} pcbX="${mmStr(smtPad.x)}" pcbY="${mmStr(smtPad.y)}" radius="${mmStr(smtPad.radius)}" shape="circle" />`
7756
7815
  );
7757
7816
  } else if (smtPad.shape === "rect") {
7817
+ const cornerRadius = smtPad.corner_radius ?? smtPad.rect_border_radius ?? void 0;
7818
+ const cornerRadiusAttr = cornerRadius !== void 0 ? ` cornerRadius="${mmStr(cornerRadius)}"` : "";
7819
+ elementStrings.push(
7820
+ `<smtpad portHints={${JSON.stringify(smtPad.port_hints)}} pcbX="${mmStr(smtPad.x)}" pcbY="${mmStr(smtPad.y)}" width="${mmStr(smtPad.width)}" height="${mmStr(smtPad.height)}"${cornerRadiusAttr} shape="rect" />`
7821
+ );
7822
+ } else if (smtPad.shape === "pill") {
7758
7823
  elementStrings.push(
7759
- `<smtpad portHints={${JSON.stringify(mapPortHints(smtPad.port_hints, options.portHintsMap))}} pcbX="${mmStr(smtPad.x)}" pcbY="${mmStr(smtPad.y)}" width="${mmStr(smtPad.width)}" height="${mmStr(smtPad.height)}" shape="rect" />`
7824
+ `<smtpad portHints={${JSON.stringify(smtPad.port_hints)}} pcbX="${mmStr(smtPad.x)}" pcbY="${mmStr(smtPad.y)}" width="${mmStr(smtPad.width)}" height="${mmStr(smtPad.height)}" radius="${mmStr(smtPad.radius)}" shape="pill" />`
7760
7825
  );
7761
7826
  } else if (smtPad.shape === "polygon") {
7762
7827
  const pointsStr = smtPad.points.map((p) => `{x: "${mmStr(p.x)}", y: "${mmStr(p.y)}"}`).join(", ");
@@ -7992,6 +8057,7 @@ var convertBetterEasyToTsx = async ({
7992
8057
  cadPositionXMm: cadPlacement?.positionXMm,
7993
8058
  cadPositionYMm: cadPlacement?.positionYMm,
7994
8059
  cadPositionZMm: cadPlacement?.positionZMm,
8060
+ cadModelBounds: cadPlacement?.bounds,
7995
8061
  showDesignator: true
7996
8062
  });
7997
8063
  const [cadComponent] = su(circuitJson).cad_component.list();