circuit-to-svg 0.0.279 → 0.0.281

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1582,7 +1582,8 @@ import { applyToPoint as applyToPoint12 } from "transformation-matrix";
1582
1582
  function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1583
1583
  const { transform, colorMap: colorMap2, showSolderMask } = ctx;
1584
1584
  const [x, y] = applyToPoint12(transform, [hole.x, hole.y]);
1585
- const copperLayer = Array.isArray(hole.layers) && hole.layers[0] || hole.layer || "top";
1585
+ const layer = Array.isArray(hole.layers) && hole.layers[0] || hole.layer || "top";
1586
+ const maskLayer = layer;
1586
1587
  const isCoveredWithSolderMask = Boolean(hole.is_covered_with_solder_mask);
1587
1588
  const soldermaskMargin = (hole.soldermask_margin ?? 0) * Math.abs(transform.a);
1588
1589
  const shouldShowSolderMask = showSolderMask && isCoveredWithSolderMask && soldermaskMargin !== 0;
@@ -1620,7 +1621,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1620
1621
  d: createPillPath(scaledOuterWidth, scaledOuterHeight),
1621
1622
  transform: outerTransform,
1622
1623
  "data-type": "pcb_plated_hole",
1623
- "data-pcb-layer": copperLayer
1624
+ "data-pcb-layer": layer
1624
1625
  },
1625
1626
  value: "",
1626
1627
  children: []
@@ -1656,7 +1657,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1656
1657
  d: createPillPath(scaledOuterWidth, scaledOuterHeight),
1657
1658
  transform: outerTransform,
1658
1659
  "data-type": "pcb_plated_hole",
1659
- "data-pcb-layer": copperLayer
1660
+ "data-pcb-layer": layer
1660
1661
  },
1661
1662
  value: "",
1662
1663
  children: []
@@ -1670,7 +1671,8 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1670
1671
  fill: colorMap2.copper.top,
1671
1672
  d: createPillPath(maskWidth, maskHeight),
1672
1673
  transform: outerTransform,
1673
- "data-type": "pcb_soldermask"
1674
+ "data-type": "pcb_soldermask",
1675
+ "data-pcb-layer": maskLayer
1674
1676
  },
1675
1677
  value: "",
1676
1678
  children: []
@@ -1689,7 +1691,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1689
1691
  d: createPillPath(maskWidth, maskHeight),
1690
1692
  transform: outerTransform,
1691
1693
  "data-type": "pcb_soldermask_opening",
1692
- "data-pcb-layer": "soldermask-top"
1694
+ "data-pcb-layer": maskLayer
1693
1695
  },
1694
1696
  value: "",
1695
1697
  children: []
@@ -1730,7 +1732,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1730
1732
  ry: (scaledOuterHeight / 2).toString(),
1731
1733
  transform: transformStr,
1732
1734
  "data-type": "pcb_plated_hole",
1733
- "data-pcb-layer": copperLayer
1735
+ "data-pcb-layer": layer
1734
1736
  },
1735
1737
  value: "",
1736
1738
  children: []
@@ -1785,7 +1787,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1785
1787
  cy: y.toString(),
1786
1788
  r: outerRadius.toString(),
1787
1789
  "data-type": "pcb_plated_hole",
1788
- "data-pcb-layer": copperLayer
1790
+ "data-pcb-layer": layer
1789
1791
  },
1790
1792
  value: "",
1791
1793
  children: []
@@ -1821,7 +1823,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1821
1823
  cy: y.toString(),
1822
1824
  r: outerRadius.toString(),
1823
1825
  "data-type": "pcb_plated_hole",
1824
- "data-pcb-layer": copperLayer
1826
+ "data-pcb-layer": layer
1825
1827
  },
1826
1828
  value: "",
1827
1829
  children: []
@@ -1836,7 +1838,8 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1836
1838
  cx: x.toString(),
1837
1839
  cy: y.toString(),
1838
1840
  r: maskRadius.toString(),
1839
- "data-type": "pcb_soldermask"
1841
+ "data-type": "pcb_soldermask",
1842
+ "data-pcb-layer": maskLayer
1840
1843
  },
1841
1844
  value: "",
1842
1845
  children: []
@@ -1856,7 +1859,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1856
1859
  cy: y.toString(),
1857
1860
  r: maskRadius.toString(),
1858
1861
  "data-type": "pcb_soldermask_opening",
1859
- "data-pcb-layer": "soldermask-top"
1862
+ "data-pcb-layer": maskLayer
1860
1863
  },
1861
1864
  value: "",
1862
1865
  children: []
@@ -1904,7 +1907,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1904
1907
  ry: scaledRectBorderRadius.toString()
1905
1908
  } : {},
1906
1909
  "data-type": "pcb_plated_hole",
1907
- "data-pcb-layer": copperLayer
1910
+ "data-pcb-layer": layer
1908
1911
  },
1909
1912
  value: "",
1910
1913
  children: []
@@ -1948,7 +1951,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1948
1951
  ry: scaledRectBorderRadius.toString()
1949
1952
  } : {},
1950
1953
  "data-type": "pcb_plated_hole",
1951
- "data-pcb-layer": copperLayer
1954
+ "data-pcb-layer": layer
1952
1955
  },
1953
1956
  value: "",
1954
1957
  children: []
@@ -1968,7 +1971,8 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1968
1971
  rx: maskBorderRadius.toString(),
1969
1972
  ry: maskBorderRadius.toString()
1970
1973
  } : {},
1971
- "data-type": "pcb_soldermask"
1974
+ "data-type": "pcb_soldermask",
1975
+ "data-pcb-layer": maskLayer
1972
1976
  },
1973
1977
  value: "",
1974
1978
  children: []
@@ -1993,7 +1997,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
1993
1997
  ry: maskBorderRadius.toString()
1994
1998
  } : {},
1995
1999
  "data-type": "pcb_soldermask_opening",
1996
- "data-pcb-layer": "soldermask-top"
2000
+ "data-pcb-layer": maskLayer
1997
2001
  },
1998
2002
  value: "",
1999
2003
  children: []
@@ -2045,7 +2049,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2045
2049
  ry: scaledRectBorderRadius.toString()
2046
2050
  } : {},
2047
2051
  "data-type": "pcb_plated_hole",
2048
- "data-pcb-layer": copperLayer
2052
+ "data-pcb-layer": layer
2049
2053
  },
2050
2054
  value: "",
2051
2055
  children: []
@@ -2092,7 +2096,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2092
2096
  ry: scaledRectBorderRadius.toString()
2093
2097
  } : {},
2094
2098
  "data-type": "pcb_plated_hole",
2095
- "data-pcb-layer": copperLayer
2099
+ "data-pcb-layer": layer
2096
2100
  },
2097
2101
  value: "",
2098
2102
  children: []
@@ -2112,7 +2116,8 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2112
2116
  rx: maskBorderRadius.toString(),
2113
2117
  ry: maskBorderRadius.toString()
2114
2118
  } : {},
2115
- "data-type": "pcb_soldermask"
2119
+ "data-type": "pcb_soldermask",
2120
+ "data-pcb-layer": maskLayer
2116
2121
  },
2117
2122
  value: "",
2118
2123
  children: []
@@ -2137,7 +2142,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2137
2142
  ry: maskBorderRadius.toString()
2138
2143
  } : {},
2139
2144
  "data-type": "pcb_soldermask_opening",
2140
- "data-pcb-layer": "soldermask-top"
2145
+ "data-pcb-layer": maskLayer
2141
2146
  },
2142
2147
  value: "",
2143
2148
  children: []
@@ -2189,7 +2194,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2189
2194
  ry: scaledRectBorderRadius.toString()
2190
2195
  } : {},
2191
2196
  "data-type": "pcb_plated_hole",
2192
- "data-pcb-layer": copperLayer
2197
+ "data-pcb-layer": layer
2193
2198
  },
2194
2199
  value: "",
2195
2200
  children: []
@@ -2237,7 +2242,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2237
2242
  ry: scaledRectBorderRadius.toString()
2238
2243
  } : {},
2239
2244
  "data-type": "pcb_plated_hole",
2240
- "data-pcb-layer": copperLayer
2245
+ "data-pcb-layer": layer
2241
2246
  },
2242
2247
  value: "",
2243
2248
  children: []
@@ -2258,7 +2263,8 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2258
2263
  rx: maskBorderRadius.toString(),
2259
2264
  ry: maskBorderRadius.toString()
2260
2265
  } : {},
2261
- "data-type": "pcb_soldermask"
2266
+ "data-type": "pcb_soldermask",
2267
+ "data-pcb-layer": maskLayer
2262
2268
  },
2263
2269
  value: "",
2264
2270
  children: []
@@ -2283,7 +2289,8 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2283
2289
  rx: maskBorderRadius.toString(),
2284
2290
  ry: maskBorderRadius.toString()
2285
2291
  } : {},
2286
- "data-type": "pcb_soldermask"
2292
+ "data-type": "pcb_soldermask",
2293
+ "data-pcb-layer": maskLayer
2287
2294
  },
2288
2295
  value: "",
2289
2296
  children: []
@@ -2408,7 +2415,7 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
2408
2415
  fill: colorMap2.copper.top,
2409
2416
  points: padPointsString,
2410
2417
  "data-type": "pcb_plated_hole",
2411
- "data-pcb-layer": copperLayer
2418
+ "data-pcb-layer": layer
2412
2419
  },
2413
2420
  value: "",
2414
2421
  children: []
@@ -2838,7 +2845,11 @@ var DEFAULT_PCB_COLOR_MAP = {
2838
2845
  },
2839
2846
  soldermask: {
2840
2847
  top: "rgb(12, 55, 33)",
2841
- bottom: "rgb(52, 87, 136)"
2848
+ bottom: "rgb(12, 55, 33)"
2849
+ },
2850
+ soldermaskOverCopper: {
2851
+ top: "rgb(52, 135, 73)",
2852
+ bottom: "rgb(52, 135, 73)"
2842
2853
  },
2843
2854
  substrate: "rgb(201, 162, 110)",
2844
2855
  // FR4 substrate color (tan/beige)
@@ -2886,29 +2897,12 @@ function createSvgObjectsFromPcbTrace(trace, ctx) {
2886
2897
  const layer = "layer" in start ? start.layer : "layer" in end ? end.layer : null;
2887
2898
  if (!layer) continue;
2888
2899
  if (layerFilter && layer !== layerFilter) continue;
2900
+ const maskLayer = layer;
2889
2901
  const copperColor = layerNameToColor(layer, colorMap2);
2890
2902
  const maskColor = colorMap2.soldermaskWithCopperUnderneath[layer];
2891
2903
  const traceWidth = "width" in start ? start.width : "width" in end ? end.width : null;
2892
2904
  const width = traceWidth ? (traceWidth * Math.abs(transform.a)).toString() : "0.3";
2893
2905
  if (showSolderMask) {
2894
- const copperObject = {
2895
- name: "path",
2896
- type: "element",
2897
- value: "",
2898
- children: [],
2899
- attributes: {
2900
- class: "pcb-trace",
2901
- stroke: copperColor,
2902
- fill: "none",
2903
- d: `M ${startPoint[0]} ${startPoint[1]} L ${endPoint[0]} ${endPoint[1]}`,
2904
- "stroke-width": width,
2905
- "stroke-linecap": "round",
2906
- "stroke-linejoin": "round",
2907
- "shape-rendering": "crispEdges",
2908
- "data-type": "pcb_trace",
2909
- "data-pcb-layer": layer
2910
- }
2911
- };
2912
2906
  const maskObject = {
2913
2907
  name: "path",
2914
2908
  type: "element",
@@ -2923,11 +2917,11 @@ function createSvgObjectsFromPcbTrace(trace, ctx) {
2923
2917
  "stroke-linecap": "round",
2924
2918
  "stroke-linejoin": "round",
2925
2919
  "shape-rendering": "crispEdges",
2926
- "data-type": "pcb_soldermask",
2920
+ "data-type": "pcb_trace_soldermask",
2927
2921
  "data-pcb-layer": layer
2928
2922
  }
2929
2923
  };
2930
- svgObjects.push(maskObject, copperObject);
2924
+ svgObjects.push(maskObject);
2931
2925
  } else {
2932
2926
  const maskOnlyObject = {
2933
2927
  name: "path",
@@ -2959,7 +2953,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
2959
2953
  const { transform, layer: layerFilter, colorMap: colorMap2, showSolderMask } = ctx;
2960
2954
  if (layerFilter && pad.layer !== layerFilter) return [];
2961
2955
  const isCoveredWithSolderMask = Boolean(pad?.is_covered_with_solder_mask);
2962
- const shouldshowSolderMask = showSolderMask && isCoveredWithSolderMask;
2956
+ const shouldShowSolderMask = showSolderMask && isCoveredWithSolderMask;
2963
2957
  const soldermaskWithCopperUnderneathColor = colorMap2.soldermaskWithCopperUnderneath[pad.layer] ?? colorMap2.soldermaskWithCopperUnderneath.top;
2964
2958
  const soldermaskMargin = (pad.soldermask_margin ?? 0) * Math.abs(transform.a);
2965
2959
  if (pad.shape === "rect" || pad.shape === "rotated_rect") {
@@ -2990,7 +2984,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
2990
2984
  } : {}
2991
2985
  }
2992
2986
  };
2993
- if (!shouldshowSolderMask) {
2987
+ if (!shouldShowSolderMask) {
2994
2988
  return [padElement2];
2995
2989
  }
2996
2990
  const maskWidth2 = width + 2 * soldermaskMargin;
@@ -3083,7 +3077,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3083
3077
  ry: maskBorderRadius2.toString()
3084
3078
  } : {},
3085
3079
  "data-type": "pcb_soldermask_opening",
3086
- "data-pcb-layer": `soldermask-${pad.layer}`
3080
+ "data-pcb-layer": pad.layer
3087
3081
  }
3088
3082
  };
3089
3083
  return [substrateElement2, padElement2];
@@ -3108,7 +3102,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3108
3102
  } : {}
3109
3103
  }
3110
3104
  };
3111
- if (!shouldshowSolderMask) {
3105
+ if (!shouldShowSolderMask) {
3112
3106
  return [padElement];
3113
3107
  }
3114
3108
  const maskWidth = width + 2 * soldermaskMargin;
@@ -3197,7 +3191,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3197
3191
  ry: maskBorderRadius.toString()
3198
3192
  } : {},
3199
3193
  "data-type": "pcb_soldermask_opening",
3200
- "data-pcb-layer": `soldermask-${pad.layer}`
3194
+ "data-pcb-layer": pad.layer
3201
3195
  }
3202
3196
  };
3203
3197
  return [substrateElement, padElement];
@@ -3225,7 +3219,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3225
3219
  "data-pcb-layer": pad.layer
3226
3220
  }
3227
3221
  };
3228
- if (!shouldshowSolderMask) {
3222
+ if (!shouldShowSolderMask) {
3229
3223
  return [padElement];
3230
3224
  }
3231
3225
  const maskWidth = width + 2 * soldermaskMargin;
@@ -3306,7 +3300,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3306
3300
  rx: maskRadius.toString(),
3307
3301
  ry: maskRadius.toString(),
3308
3302
  "data-type": "pcb_soldermask_opening",
3309
- "data-pcb-layer": `soldermask-${pad.layer}`
3303
+ "data-pcb-layer": pad.layer
3310
3304
  }
3311
3305
  };
3312
3306
  return [substrateElement, padElement];
@@ -3329,7 +3323,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3329
3323
  "data-pcb-layer": pad.layer
3330
3324
  }
3331
3325
  };
3332
- if (!shouldshowSolderMask) {
3326
+ if (!shouldShowSolderMask) {
3333
3327
  return [padElement];
3334
3328
  }
3335
3329
  const maskRadius = radius + soldermaskMargin;
@@ -3396,7 +3390,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3396
3390
  cy: y.toString(),
3397
3391
  r: maskRadius.toString(),
3398
3392
  "data-type": "pcb_soldermask_opening",
3399
- "data-pcb-layer": `soldermask-${pad.layer}`
3393
+ "data-pcb-layer": pad.layer
3400
3394
  }
3401
3395
  };
3402
3396
  return [substrateElement, padElement];
@@ -3418,7 +3412,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3418
3412
  "data-pcb-layer": pad.layer
3419
3413
  }
3420
3414
  };
3421
- if (!shouldshowSolderMask) {
3415
+ if (!shouldShowSolderMask) {
3422
3416
  return [padElement];
3423
3417
  }
3424
3418
  let maskPoints = points;
@@ -3493,7 +3487,7 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3493
3487
  fill: colorMap2.substrate,
3494
3488
  points: maskPoints.map((p) => p.join(",")).join(" "),
3495
3489
  "data-type": "pcb_soldermask_opening",
3496
- "data-pcb-layer": `soldermask-${pad.layer}`
3490
+ "data-pcb-layer": pad.layer
3497
3491
  }
3498
3492
  };
3499
3493
  return [substrateElement, padElement];
@@ -3536,6 +3530,8 @@ function createSvgObjectsFromPcbBoard(pcbBoard, ctx) {
3536
3530
  path += " Z";
3537
3531
  const svgObjects = [];
3538
3532
  if (showSolderMask) {
3533
+ const layer = ctx.layer ?? "top";
3534
+ const maskLayer = layer === "bottom" ? "soldermask-bottom" : "soldermask-top";
3539
3535
  svgObjects.push({
3540
3536
  name: "path",
3541
3537
  type: "element",
@@ -3548,7 +3544,7 @@ function createSvgObjectsFromPcbBoard(pcbBoard, ctx) {
3548
3544
  "fill-opacity": "0.8",
3549
3545
  stroke: "none",
3550
3546
  "data-type": "pcb_soldermask",
3551
- "data-pcb-layer": "soldermask-top"
3547
+ "data-pcb-layer": maskLayer
3552
3548
  }
3553
3549
  });
3554
3550
  }
@@ -3597,7 +3593,7 @@ function createSvgObjectsFromPcbPanel(pcbPanel, ctx) {
3597
3593
  ]);
3598
3594
  const path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]} Z`;
3599
3595
  const isCoveredWithSolderMask = pcbPanel.covered_with_solder_mask !== false;
3600
- const shouldshowSolderMask = Boolean(
3596
+ const shouldShowSolderMask = Boolean(
3601
3597
  showSolderMask && isCoveredWithSolderMask
3602
3598
  );
3603
3599
  return [
@@ -3672,6 +3668,7 @@ function createSvgObjectsFromPcbVia(hole, ctx) {
3672
3668
  import { applyToPoint as applyToPoint24 } from "transformation-matrix";
3673
3669
  function createSvgObjectsFromPcbHole(hole, ctx) {
3674
3670
  const { transform, colorMap: colorMap2, showSolderMask } = ctx;
3671
+ const layer = ctx.layer ?? "top";
3675
3672
  const [x, y] = applyToPoint24(transform, [hole.x, hole.y]);
3676
3673
  const isCoveredWithSolderMask = Boolean(hole.is_covered_with_solder_mask);
3677
3674
  const soldermaskMargin = (hole.soldermask_margin ?? 0) * Math.abs(transform.a);
@@ -3727,7 +3724,8 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
3727
3724
  cx: x.toString(),
3728
3725
  cy: y.toString(),
3729
3726
  r: maskRadius.toString(),
3730
- "data-type": "pcb_soldermask"
3727
+ "data-type": "pcb_soldermask",
3728
+ "data-pcb-layer": "drill"
3731
3729
  }
3732
3730
  };
3733
3731
  return [coveredElement, exposedElement];
@@ -3744,7 +3742,7 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
3744
3742
  cy: y.toString(),
3745
3743
  r: maskRadius.toString(),
3746
3744
  "data-type": "pcb_soldermask_opening",
3747
- "data-pcb-layer": "soldermask-top"
3745
+ "data-pcb-layer": layer
3748
3746
  }
3749
3747
  };
3750
3748
  return [substrateElement2, holeElement2];
@@ -3798,7 +3796,8 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
3798
3796
  y: (y - maskDiameter / 2).toString(),
3799
3797
  width: maskDiameter.toString(),
3800
3798
  height: maskDiameter.toString(),
3801
- "data-type": "pcb_soldermask"
3799
+ "data-type": "pcb_soldermask",
3800
+ "data-pcb-layer": "drill"
3802
3801
  }
3803
3802
  };
3804
3803
  return [coveredElement, exposedElement];
@@ -3816,7 +3815,7 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
3816
3815
  width: maskDiameter.toString(),
3817
3816
  height: maskDiameter.toString(),
3818
3817
  "data-type": "pcb_soldermask_opening",
3819
- "data-pcb-layer": "soldermask-top"
3818
+ "data-pcb-layer": layer
3820
3819
  }
3821
3820
  };
3822
3821
  return [substrateElement, holeElement];
@@ -3876,7 +3875,8 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
3876
3875
  cy: y.toString(),
3877
3876
  rx: maskRx.toString(),
3878
3877
  ry: maskRy.toString(),
3879
- "data-type": "pcb_soldermask"
3878
+ "data-type": "pcb_soldermask",
3879
+ "data-pcb-layer": "drill"
3880
3880
  }
3881
3881
  };
3882
3882
  return [coveredElement, exposedElement];
@@ -3894,7 +3894,7 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
3894
3894
  rx: maskRx.toString(),
3895
3895
  ry: maskRy.toString(),
3896
3896
  "data-type": "pcb_soldermask_opening",
3897
- "data-pcb-layer": "soldermask-top"
3897
+ "data-pcb-layer": layer
3898
3898
  }
3899
3899
  };
3900
3900
  return [substrateElement, holeElement];
@@ -3952,7 +3952,8 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
3952
3952
  y: (y - maskHeight / 2).toString(),
3953
3953
  width: maskWidth.toString(),
3954
3954
  height: maskHeight.toString(),
3955
- "data-type": "pcb_soldermask"
3955
+ "data-type": "pcb_soldermask",
3956
+ "data-pcb-layer": "drill"
3956
3957
  }
3957
3958
  };
3958
3959
  return [coveredElement, exposedElement];
@@ -3970,7 +3971,7 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
3970
3971
  width: maskWidth.toString(),
3971
3972
  height: maskHeight.toString(),
3972
3973
  "data-type": "pcb_soldermask_opening",
3973
- "data-pcb-layer": "soldermask-top"
3974
+ "data-pcb-layer": layer
3974
3975
  }
3975
3976
  };
3976
3977
  return [substrateElement, holeElement];
@@ -4043,7 +4044,8 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
4043
4044
  class: "pcb-hole-exposed",
4044
4045
  fill: colorMap2.drill,
4045
4046
  d: maskPathD,
4046
- "data-type": "pcb_soldermask"
4047
+ "data-type": "pcb_soldermask",
4048
+ "data-pcb-layer": "drill"
4047
4049
  }
4048
4050
  };
4049
4051
  return [coveredElement, exposedElement];
@@ -4058,7 +4060,7 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
4058
4060
  fill: colorMap2.substrate,
4059
4061
  d: maskPathD,
4060
4062
  "data-type": "pcb_soldermask_opening",
4061
- "data-pcb-layer": "soldermask-top"
4063
+ "data-pcb-layer": layer
4062
4064
  }
4063
4065
  };
4064
4066
  return [substrateElement, holeElement];
@@ -4135,7 +4137,8 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
4135
4137
  fill: colorMap2.drill,
4136
4138
  d: maskPathD,
4137
4139
  transform: `translate(${x} ${y}) rotate(${-rotation})`,
4138
- "data-type": "pcb_soldermask"
4140
+ "data-type": "pcb_soldermask",
4141
+ "data-pcb-layer": "drill"
4139
4142
  }
4140
4143
  };
4141
4144
  return [coveredElement, exposedElement];
@@ -4150,7 +4153,7 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
4150
4153
  fill: colorMap2.substrate,
4151
4154
  d: maskPathD,
4152
4155
  "data-type": "pcb_soldermask_opening",
4153
- "data-pcb-layer": "soldermask-top"
4156
+ "data-pcb-layer": layer
4154
4157
  }
4155
4158
  };
4156
4159
  return [substrateElement, holeElement];
@@ -4415,40 +4418,118 @@ function ringToPathD(vertices, transform) {
4415
4418
  return d;
4416
4419
  }
4417
4420
 
4421
+ // lib/pcb/svg-object-fns/create-soldermask-cutout-element.ts
4422
+ function createSoldermaskCutoutElement({
4423
+ elementType,
4424
+ shapeAttributes,
4425
+ layer,
4426
+ colorMap: colorMap2,
4427
+ additionalAttributes
4428
+ }) {
4429
+ const baseAttributes = {
4430
+ class: "pcb-soldermask-cutout",
4431
+ fill: colorMap2.substrate,
4432
+ "data-type": "pcb_soldermask_opening",
4433
+ "data-pcb-layer": layer,
4434
+ ...shapeAttributes,
4435
+ ...additionalAttributes
4436
+ };
4437
+ return {
4438
+ name: elementType,
4439
+ type: "element",
4440
+ value: "",
4441
+ children: [],
4442
+ attributes: baseAttributes
4443
+ };
4444
+ }
4445
+
4446
+ // lib/pcb/svg-object-fns/create-soldermask-overlay-element.ts
4447
+ function createSoldermaskOverlayElement({
4448
+ elementType,
4449
+ shapeAttributes,
4450
+ layer,
4451
+ fillColor,
4452
+ fillOpacity,
4453
+ className,
4454
+ additionalAttributes
4455
+ }) {
4456
+ const baseAttributes = {
4457
+ class: className,
4458
+ fill: fillColor,
4459
+ "fill-opacity": fillOpacity,
4460
+ "data-type": "pcb_soldermask",
4461
+ "data-pcb-layer": layer,
4462
+ ...shapeAttributes,
4463
+ ...additionalAttributes
4464
+ };
4465
+ return {
4466
+ name: elementType,
4467
+ type: "element",
4468
+ value: "",
4469
+ children: [],
4470
+ attributes: baseAttributes
4471
+ };
4472
+ }
4473
+
4418
4474
  // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-copper-pour.ts
4419
4475
  function createSvgObjectsFromPcbCopperPour(pour, ctx) {
4420
- const { transform, layer: layerFilter, colorMap: colorMap2 } = ctx;
4476
+ const { transform, layer: layerFilter, colorMap: colorMap2, showSolderMask } = ctx;
4421
4477
  const { layer } = pour;
4422
4478
  if (layerFilter && layer !== layerFilter) return [];
4423
4479
  const color = layerNameToColor(layer, colorMap2);
4424
4480
  const opacity = "0.5";
4481
+ const isCoveredWithSolderMask = pour.covered_with_solder_mask !== false;
4482
+ const maskOverlayColor = layer === "bottom" ? colorMap2.soldermaskOverCopper.bottom : colorMap2.soldermaskOverCopper.top;
4483
+ const maskOverlayOpacity = "0.9";
4425
4484
  if (pour.shape === "rect") {
4426
4485
  const [cx, cy] = applyToPoint28(transform, [pour.center.x, pour.center.y]);
4427
4486
  const scaledWidth = pour.width * Math.abs(transform.a);
4428
4487
  const scaledHeight = pour.height * Math.abs(transform.d);
4429
4488
  const svgRotation = -(pour.rotation ?? 0);
4430
- return [
4431
- {
4432
- name: "rect",
4433
- type: "element",
4434
- attributes: {
4435
- class: "pcb-copper-pour pcb-copper-pour-rect",
4436
- x: (-scaledWidth / 2).toString(),
4437
- y: (-scaledHeight / 2).toString(),
4438
- width: scaledWidth.toString(),
4439
- height: scaledHeight.toString(),
4440
- fill: color,
4441
- "fill-opacity": opacity,
4442
- transform: matrixToString7(
4443
- compose4(translate4(cx, cy), rotate4(svgRotation * Math.PI / 180))
4444
- ),
4445
- "data-type": "pcb_copper_pour",
4446
- "data-pcb-layer": layer
4447
- },
4448
- children: [],
4449
- value: ""
4489
+ const rectAttributes = {
4490
+ x: (-scaledWidth / 2).toString(),
4491
+ y: (-scaledHeight / 2).toString(),
4492
+ width: scaledWidth.toString(),
4493
+ height: scaledHeight.toString(),
4494
+ transform: matrixToString7(
4495
+ compose4(translate4(cx, cy), rotate4(svgRotation * Math.PI / 180))
4496
+ )
4497
+ };
4498
+ const copperRect = {
4499
+ name: "rect",
4500
+ type: "element",
4501
+ value: "",
4502
+ children: [],
4503
+ attributes: {
4504
+ class: "pcb-copper-pour pcb-copper-pour-rect",
4505
+ ...rectAttributes,
4506
+ fill: color,
4507
+ "fill-opacity": opacity,
4508
+ "data-type": "pcb_copper_pour",
4509
+ "data-pcb-layer": layer
4450
4510
  }
4451
- ];
4511
+ };
4512
+ const maskRect = showSolderMask ? isCoveredWithSolderMask ? createSoldermaskOverlayElement({
4513
+ elementType: "rect",
4514
+ shapeAttributes: rectAttributes,
4515
+ layer,
4516
+ fillColor: maskOverlayColor,
4517
+ fillOpacity: maskOverlayOpacity,
4518
+ className: "pcb-soldermask-covered-pour"
4519
+ }) : createSoldermaskCutoutElement({
4520
+ elementType: "rect",
4521
+ shapeAttributes: rectAttributes,
4522
+ layer,
4523
+ colorMap: colorMap2
4524
+ }) : null;
4525
+ if (!maskRect) {
4526
+ return [copperRect];
4527
+ }
4528
+ const isSubstrateOnly = !isCoveredWithSolderMask && pour.pcb_copper_pour_id?.includes("substrate_only");
4529
+ if (isSubstrateOnly) {
4530
+ return [maskRect];
4531
+ }
4532
+ return [copperRect, maskRect];
4452
4533
  }
4453
4534
  if (pour.shape === "polygon") {
4454
4535
  if (!pour.points || pour.points.length === 0) return [];
@@ -4456,22 +4537,41 @@ function createSvgObjectsFromPcbCopperPour(pour, ctx) {
4456
4537
  (p) => applyToPoint28(transform, [p.x, p.y])
4457
4538
  );
4458
4539
  const pointsString = transformedPoints.map((p) => `${p[0]},${p[1]}`).join(" ");
4459
- return [
4460
- {
4461
- name: "polygon",
4462
- type: "element",
4463
- attributes: {
4464
- class: "pcb-copper-pour pcb-copper-pour-polygon",
4465
- points: pointsString,
4466
- fill: color,
4467
- "fill-opacity": opacity,
4468
- "data-type": "pcb_copper_pour",
4469
- "data-pcb-layer": layer
4470
- },
4471
- children: [],
4472
- value: ""
4540
+ const copperPolygon = {
4541
+ name: "polygon",
4542
+ type: "element",
4543
+ value: "",
4544
+ children: [],
4545
+ attributes: {
4546
+ class: "pcb-copper-pour pcb-copper-pour-polygon",
4547
+ points: pointsString,
4548
+ fill: color,
4549
+ "fill-opacity": opacity,
4550
+ "data-type": "pcb_copper_pour",
4551
+ "data-pcb-layer": layer
4473
4552
  }
4474
- ];
4553
+ };
4554
+ const maskPolygon = showSolderMask ? isCoveredWithSolderMask ? createSoldermaskOverlayElement({
4555
+ elementType: "polygon",
4556
+ shapeAttributes: { points: pointsString },
4557
+ layer,
4558
+ fillColor: maskOverlayColor,
4559
+ fillOpacity: maskOverlayOpacity,
4560
+ className: "pcb-soldermask-covered-pour"
4561
+ }) : createSoldermaskCutoutElement({
4562
+ elementType: "polygon",
4563
+ shapeAttributes: { points: pointsString },
4564
+ layer,
4565
+ colorMap: colorMap2
4566
+ }) : null;
4567
+ if (!maskPolygon) {
4568
+ return [copperPolygon];
4569
+ }
4570
+ const isSubstrateOnly = !isCoveredWithSolderMask && pour.pcb_copper_pour_id?.includes("substrate_only");
4571
+ if (isSubstrateOnly) {
4572
+ return [maskPolygon];
4573
+ }
4574
+ return [copperPolygon, maskPolygon];
4475
4575
  }
4476
4576
  if (pour.shape === "brep") {
4477
4577
  const { brep_shape } = pour;
@@ -4479,23 +4579,42 @@ function createSvgObjectsFromPcbCopperPour(pour, ctx) {
4479
4579
  for (const inner_ring of brep_shape.inner_rings ?? []) {
4480
4580
  d += ` ${ringToPathD(inner_ring.vertices, transform)}`;
4481
4581
  }
4482
- return [
4483
- {
4484
- name: "path",
4485
- type: "element",
4486
- attributes: {
4487
- class: "pcb-copper-pour pcb-copper-pour-brep",
4488
- d,
4489
- fill: color,
4490
- "fill-rule": "evenodd",
4491
- "fill-opacity": opacity,
4492
- "data-type": "pcb_copper_pour",
4493
- "data-pcb-layer": layer
4494
- },
4495
- children: [],
4496
- value: ""
4582
+ const copperPath = {
4583
+ name: "path",
4584
+ type: "element",
4585
+ value: "",
4586
+ children: [],
4587
+ attributes: {
4588
+ class: "pcb-copper-pour pcb-copper-pour-brep",
4589
+ d,
4590
+ fill: color,
4591
+ "fill-rule": "evenodd",
4592
+ "fill-opacity": opacity,
4593
+ "data-type": "pcb_copper_pour",
4594
+ "data-pcb-layer": layer
4497
4595
  }
4498
- ];
4596
+ };
4597
+ const maskPath = showSolderMask ? isCoveredWithSolderMask ? createSoldermaskOverlayElement({
4598
+ elementType: "path",
4599
+ shapeAttributes: { d, "fill-rule": "evenodd" },
4600
+ layer,
4601
+ fillColor: maskOverlayColor,
4602
+ fillOpacity: maskOverlayOpacity,
4603
+ className: "pcb-soldermask-covered-pour"
4604
+ }) : createSoldermaskCutoutElement({
4605
+ elementType: "path",
4606
+ shapeAttributes: { d, "fill-rule": "evenodd" },
4607
+ layer,
4608
+ colorMap: colorMap2
4609
+ }) : null;
4610
+ if (!maskPath) {
4611
+ return [copperPath];
4612
+ }
4613
+ const isSubstrateOnly = !isCoveredWithSolderMask && pour.pcb_copper_pour_id?.includes("substrate_only");
4614
+ if (isSubstrateOnly) {
4615
+ return [maskPath];
4616
+ }
4617
+ return [copperPath, maskPath];
4499
4618
  }
4500
4619
  return [];
4501
4620
  }
@@ -5092,7 +5211,7 @@ function getSoftwareUsedString(circuitJson) {
5092
5211
  var package_default = {
5093
5212
  name: "circuit-to-svg",
5094
5213
  type: "module",
5095
- version: "0.0.278",
5214
+ version: "0.0.280",
5096
5215
  description: "Convert Circuit JSON to SVG",
5097
5216
  main: "dist/index.js",
5098
5217
  files: [
@@ -5121,7 +5240,7 @@ var package_default = {
5121
5240
  "react-cosmos": "7.0.0",
5122
5241
  "react-cosmos-plugin-vite": "7.0.0",
5123
5242
  "react-dom": "19.1.0",
5124
- tscircuit: "^0.0.827",
5243
+ tscircuit: "^0.0.937",
5125
5244
  tsup: "^8.0.2",
5126
5245
  typescript: "^5.4.5",
5127
5246
  "vite-tsconfig-paths": "^5.0.1"
@@ -5148,12 +5267,13 @@ var TYPE_PRIORITY = {
5148
5267
  pcb_hole: 18,
5149
5268
  pcb_plated_hole_drill: 19,
5150
5269
  pcb_plated_hole: 20,
5270
+ pcb_trace_soldermask: 25,
5151
5271
  pcb_trace: 30,
5152
5272
  pcb_smtpad: 30,
5153
5273
  pcb_copper_pour: 35,
5154
5274
  pcb_via: 36,
5155
5275
  pcb_soldermask: 40,
5156
- pcb_soldermask_opening: 41,
5276
+ pcb_soldermask_opening: 25,
5157
5277
  pcb_solder_paste: 45,
5158
5278
  pcb_silkscreen_text: 50,
5159
5279
  pcb_silkscreen_path: 50,
@@ -5198,13 +5318,13 @@ function getLayerPriority(layer) {
5198
5318
  if (!layer) return 500;
5199
5319
  const normalized = layer.toLowerCase();
5200
5320
  if (normalized === "global") return -100;
5201
- if (normalized === "bottom") return 0;
5321
+ if (normalized === "bottom") return 4;
5202
5322
  if (normalized === "board") return 2;
5203
5323
  if (normalized === "soldermask-top" || normalized === "soldermask-bottom")
5204
5324
  return 3;
5205
5325
  if (normalized.startsWith("inner")) {
5206
5326
  const match = normalized.match(/\d+/);
5207
- const layerIndex = match ? parseInt(match[0], 10) : 0;
5327
+ const layerIndex = match ? Number.parseInt(match[0], 10) : 0;
5208
5328
  return 5 + layerIndex;
5209
5329
  }
5210
5330
  if (normalized === "through") return 18;
@@ -5292,6 +5412,10 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
5292
5412
  top: colorOverrides?.soldermask?.top ?? DEFAULT_PCB_COLOR_MAP.soldermask.top,
5293
5413
  bottom: colorOverrides?.soldermask?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermask.bottom
5294
5414
  },
5415
+ soldermaskOverCopper: {
5416
+ top: colorOverrides?.soldermaskOverCopper?.top ?? DEFAULT_PCB_COLOR_MAP.soldermaskOverCopper.top,
5417
+ bottom: colorOverrides?.soldermaskOverCopper?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermaskOverCopper.bottom
5418
+ },
5295
5419
  soldermaskWithCopperUnderneath: {
5296
5420
  top: colorOverrides?.soldermaskWithCopperUnderneath?.top ?? DEFAULT_PCB_COLOR_MAP.soldermaskWithCopperUnderneath.top,
5297
5421
  bottom: colorOverrides?.soldermaskWithCopperUnderneath?.bottom ?? DEFAULT_PCB_COLOR_MAP.soldermaskWithCopperUnderneath.bottom
@@ -5441,10 +5565,9 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
5441
5565
  showAnchorOffsets: options?.showAnchorOffsets,
5442
5566
  circuitJson
5443
5567
  };
5444
- const unsortedSvgObjects = circuitJson.flatMap(
5568
+ let unsortedSvgObjects = circuitJson.flatMap(
5445
5569
  (elm) => createSvgObjects({ elm, circuitJson, ctx })
5446
5570
  );
5447
- let svgObjects = sortSvgObjectsByPcbLayer(unsortedSvgObjects);
5448
5571
  let strokeWidth = String(0.05 * scaleFactor);
5449
5572
  for (const element of circuitJson) {
5450
5573
  if ("stroke_width" in element) {
@@ -5454,8 +5577,9 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
5454
5577
  }
5455
5578
  if (options?.shouldDrawRatsNest) {
5456
5579
  const ratsNestObjects = createSvgObjectsForRatsNest(circuitJson, ctx);
5457
- svgObjects = sortSvgObjectsByPcbLayer([...svgObjects, ...ratsNestObjects]);
5580
+ unsortedSvgObjects = [...unsortedSvgObjects, ...ratsNestObjects];
5458
5581
  }
5582
+ const svgObjects = sortSvgObjectsByPcbLayer(unsortedSvgObjects);
5459
5583
  const children = [
5460
5584
  {
5461
5585
  name: "style",