circuit-to-svg 0.0.226 → 0.0.227

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
@@ -35,7 +35,7 @@ function createSvgObjectsFromPcbTraceError(pcbTraceError, circuitJson, ctx) {
35
35
  x: pcbTraceError.center.x,
36
36
  y: pcbTraceError.center.y
37
37
  });
38
- return [
38
+ return annotateTraceErrorSvgObjects([
39
39
  {
40
40
  name: "rect",
41
41
  type: "element",
@@ -72,7 +72,7 @@ function createSvgObjectsFromPcbTraceError(pcbTraceError, circuitJson, ctx) {
72
72
  ],
73
73
  value: ""
74
74
  }
75
- ];
75
+ ]);
76
76
  } else return [];
77
77
  }
78
78
  const screenPort1 = applyToPoint(transform, {
@@ -158,7 +158,7 @@ function createSvgObjectsFromPcbTraceError(pcbTraceError, circuitJson, ctx) {
158
158
  value: ""
159
159
  }
160
160
  ];
161
- return svgObjects;
161
+ return annotateTraceErrorSvgObjects(svgObjects);
162
162
  }
163
163
  function createSvgObjectsForViaTraceError(pcbTraceError, via, ctx) {
164
164
  const { transform } = ctx;
@@ -180,7 +180,7 @@ function createSvgObjectsForViaTraceError(pcbTraceError, via, ctx) {
180
180
  const boxHeight = 20;
181
181
  const midX = (screenCenter.x + screenVia.x) / 2;
182
182
  const midY = (screenCenter.y + screenVia.y) / 2;
183
- return [
183
+ return annotateTraceErrorSvgObjects([
184
184
  // Rotated bounding box
185
185
  {
186
186
  name: "rect",
@@ -237,10 +237,33 @@ function createSvgObjectsForViaTraceError(pcbTraceError, via, ctx) {
237
237
  ],
238
238
  value: ""
239
239
  }
240
- ];
240
+ ]);
241
241
  }
242
242
  return [];
243
243
  }
244
+ function annotateTraceErrorSvgObjects(objects) {
245
+ return objects.map((object) => ({
246
+ ...object,
247
+ attributes: {
248
+ ...object.attributes ?? {},
249
+ "data-type": object.attributes?.["data-type"] ?? "pcb_trace_error",
250
+ "data-pcb-layer": object.attributes?.["data-pcb-layer"] ?? "overlay"
251
+ },
252
+ children: (object.children ?? []).map((child) => {
253
+ if (child?.type === "element") {
254
+ return {
255
+ ...child,
256
+ attributes: {
257
+ ...child.attributes ?? {},
258
+ "data-type": child.attributes?.["data-type"] ?? "pcb_trace_error",
259
+ "data-pcb-layer": child.attributes?.["data-pcb-layer"] ?? "overlay"
260
+ }
261
+ };
262
+ }
263
+ return child;
264
+ })
265
+ }));
266
+ }
244
267
 
245
268
  // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path.ts
246
269
  import { applyToPoint as applyToPoint2 } from "transformation-matrix";
@@ -265,7 +288,9 @@ function createSvgObjectsFromPcbFabricationNotePath(fabNotePath, ctx) {
265
288
  d: path,
266
289
  "stroke-width": (fabNotePath.stroke_width * Math.abs(transform.a)).toString(),
267
290
  "data-pcb-component-id": fabNotePath.pcb_component_id,
268
- "data-pcb-fabrication-note-path-id": fabNotePath.pcb_fabrication_note_path_id
291
+ "data-pcb-fabrication-note-path-id": fabNotePath.pcb_fabrication_note_path_id,
292
+ "data-type": "pcb_fabrication_note_path",
293
+ "data-pcb-layer": "overlay"
269
294
  },
270
295
  value: "",
271
296
  children: []
@@ -314,7 +339,9 @@ function createSvgObjectsFromPcbFabricationNoteText(pcbFabNoteText, ctx) {
314
339
  "dominant-baseline": "central",
315
340
  transform: matrixToString(textTransform),
316
341
  class: "pcb-fabrication-note-text",
317
- fill: color || "rgba(255,255,255,0.5)"
342
+ fill: color || "rgba(255,255,255,0.5)",
343
+ "data-type": "pcb_fabrication_note_text",
344
+ "data-pcb-layer": "overlay"
318
345
  },
319
346
  children: [
320
347
  {
@@ -335,6 +362,7 @@ import { applyToPoint as applyToPoint4 } from "transformation-matrix";
335
362
  function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
336
363
  const { transform, colorMap: colorMap2 } = ctx;
337
364
  const [x, y] = applyToPoint4(transform, [hole.x, hole.y]);
365
+ const copperLayer = Array.isArray(hole.layers) && hole.layers[0] || hole.layer || "top";
338
366
  if (hole.shape === "pill") {
339
367
  const scaledOuterWidth = hole.outer_width * Math.abs(transform.a);
340
368
  const scaledOuterHeight = hole.outer_height * Math.abs(transform.a);
@@ -352,6 +380,10 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
352
380
  {
353
381
  name: "g",
354
382
  type: "element",
383
+ attributes: {
384
+ "data-type": "pcb_plated_hole",
385
+ "data-pcb-layer": "through"
386
+ },
355
387
  children: [
356
388
  // Outer pill shape
357
389
  {
@@ -361,7 +393,9 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
361
393
  class: "pcb-hole-outer",
362
394
  fill: colorMap2.copper.top,
363
395
  d: `M${-outerRadiusX},${-straightLength / 2} v${straightLength} a${outerRadiusX},${outerRadiusX} 0 0 0 ${scaledOuterWidth},0 v-${straightLength} a${outerRadiusX},${outerRadiusX} 0 0 0 -${scaledOuterWidth},0 z`,
364
- transform: outerTransform
396
+ transform: outerTransform,
397
+ "data-type": "pcb_plated_hole",
398
+ "data-pcb-layer": copperLayer
365
399
  },
366
400
  value: "",
367
401
  children: []
@@ -374,14 +408,15 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
374
408
  class: "pcb-hole-inner",
375
409
  fill: colorMap2.drill,
376
410
  d: `M${-innerRadiusX},${-(scaledHoleHeight - scaledHoleWidth) / 2} v${scaledHoleHeight - scaledHoleWidth} a${innerRadiusX},${innerRadiusX} 0 0 0 ${scaledHoleWidth},0 v-${scaledHoleHeight - scaledHoleWidth} a${innerRadiusX},${innerRadiusX} 0 0 0 -${scaledHoleWidth},0 z`,
377
- transform: innerTransform
411
+ transform: innerTransform,
412
+ "data-type": "pcb_plated_hole_drill",
413
+ "data-pcb-layer": "drill"
378
414
  },
379
415
  value: "",
380
416
  children: []
381
417
  }
382
418
  ],
383
- value: "",
384
- attributes: {}
419
+ value: ""
385
420
  }
386
421
  ];
387
422
  }
@@ -396,6 +431,10 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
396
431
  {
397
432
  name: "g",
398
433
  type: "element",
434
+ attributes: {
435
+ "data-type": "pcb_plated_hole",
436
+ "data-pcb-layer": "through"
437
+ },
399
438
  children: [
400
439
  {
401
440
  name: "circle",
@@ -405,7 +444,9 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
405
444
  fill: colorMap2.copper.top,
406
445
  cx: x.toString(),
407
446
  cy: y.toString(),
408
- r: outerRadius.toString()
447
+ r: outerRadius.toString(),
448
+ "data-type": "pcb_plated_hole",
449
+ "data-pcb-layer": copperLayer
409
450
  },
410
451
  value: "",
411
452
  children: []
@@ -418,14 +459,15 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
418
459
  fill: colorMap2.drill,
419
460
  cx: x.toString(),
420
461
  cy: y.toString(),
421
- r: innerRadius.toString()
462
+ r: innerRadius.toString(),
463
+ "data-type": "pcb_plated_hole_drill",
464
+ "data-pcb-layer": "drill"
422
465
  },
423
466
  value: "",
424
467
  children: []
425
468
  }
426
469
  ],
427
- value: "",
428
- attributes: {}
470
+ value: ""
429
471
  }
430
472
  ];
431
473
  }
@@ -444,6 +486,10 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
444
486
  {
445
487
  name: "g",
446
488
  type: "element",
489
+ attributes: {
490
+ "data-type": "pcb_plated_hole",
491
+ "data-pcb-layer": "through"
492
+ },
447
493
  children: [
448
494
  // Rectangular pad (outer shape)
449
495
  {
@@ -459,7 +505,9 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
459
505
  ...scaledRectBorderRadius ? {
460
506
  rx: scaledRectBorderRadius.toString(),
461
507
  ry: scaledRectBorderRadius.toString()
462
- } : {}
508
+ } : {},
509
+ "data-type": "pcb_plated_hole",
510
+ "data-pcb-layer": copperLayer
463
511
  },
464
512
  value: "",
465
513
  children: []
@@ -473,14 +521,15 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
473
521
  fill: colorMap2.drill,
474
522
  cx: holeCx.toString(),
475
523
  cy: holeCy.toString(),
476
- r: holeRadius.toString()
524
+ r: holeRadius.toString(),
525
+ "data-type": "pcb_plated_hole_drill",
526
+ "data-pcb-layer": "drill"
477
527
  },
478
528
  value: "",
479
529
  children: []
480
530
  }
481
531
  ],
482
- value: "",
483
- attributes: {}
532
+ value: ""
484
533
  }
485
534
  ];
486
535
  }
@@ -503,6 +552,10 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
503
552
  {
504
553
  name: "g",
505
554
  type: "element",
555
+ attributes: {
556
+ "data-type": "pcb_plated_hole",
557
+ "data-pcb-layer": "through"
558
+ },
506
559
  children: [
507
560
  // Rectangular pad (outer shape)
508
561
  {
@@ -518,7 +571,9 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
518
571
  ...scaledRectBorderRadius ? {
519
572
  rx: scaledRectBorderRadius.toString(),
520
573
  ry: scaledRectBorderRadius.toString()
521
- } : {}
574
+ } : {},
575
+ "data-type": "pcb_plated_hole",
576
+ "data-pcb-layer": copperLayer
522
577
  },
523
578
  value: "",
524
579
  children: []
@@ -535,14 +590,15 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
535
590
  width: scaledHoleWidth.toString(),
536
591
  height: scaledHoleHeight.toString(),
537
592
  rx: holeRadius.toString(),
538
- ry: holeRadius.toString()
593
+ ry: holeRadius.toString(),
594
+ "data-type": "pcb_plated_hole_drill",
595
+ "data-pcb-layer": "drill"
539
596
  },
540
597
  value: "",
541
598
  children: []
542
599
  }
543
600
  ],
544
- value: "",
545
- attributes: {}
601
+ value: ""
546
602
  }
547
603
  ];
548
604
  }
@@ -565,6 +621,10 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
565
621
  {
566
622
  name: "g",
567
623
  type: "element",
624
+ attributes: {
625
+ "data-type": "pcb_plated_hole",
626
+ "data-pcb-layer": "through"
627
+ },
568
628
  children: [
569
629
  {
570
630
  name: "rect",
@@ -580,7 +640,9 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
580
640
  ...scaledRectBorderRadius ? {
581
641
  rx: scaledRectBorderRadius.toString(),
582
642
  ry: scaledRectBorderRadius.toString()
583
- } : {}
643
+ } : {},
644
+ "data-type": "pcb_plated_hole",
645
+ "data-pcb-layer": copperLayer
584
646
  },
585
647
  value: "",
586
648
  children: []
@@ -597,14 +659,15 @@ function createSvgObjectsFromPcbPlatedHole(hole, ctx) {
597
659
  height: scaledHoleHeight.toString(),
598
660
  rx: holeRadius.toString(),
599
661
  ry: holeRadius.toString(),
600
- transform: `translate(${holeCenterX} ${holeCenterY}) rotate(${-rotatedHole.hole_ccw_rotation})`
662
+ transform: `translate(${holeCenterX} ${holeCenterY}) rotate(${-rotatedHole.hole_ccw_rotation})`,
663
+ "data-type": "pcb_plated_hole_drill",
664
+ "data-pcb-layer": "drill"
601
665
  },
602
666
  value: "",
603
667
  children: []
604
668
  }
605
669
  ],
606
- value: "",
607
- attributes: {}
670
+ value: ""
608
671
  }
609
672
  ];
610
673
  }
@@ -641,7 +704,9 @@ function createSvgObjectsFromPcbSilkscreenPath(silkscreenPath, ctx) {
641
704
  "stroke-linecap": "round",
642
705
  "stroke-linejoin": "round",
643
706
  "data-pcb-component-id": silkscreenPath.pcb_component_id,
644
- "data-pcb-silkscreen-path-id": silkscreenPath.pcb_silkscreen_path_id
707
+ "data-pcb-silkscreen-path-id": silkscreenPath.pcb_silkscreen_path_id,
708
+ "data-type": "pcb_silkscreen_path",
709
+ "data-pcb-layer": layer
645
710
  },
646
711
  value: "",
647
712
  children: []
@@ -770,7 +835,9 @@ function createSvgObjectsFromPcbSilkscreenText(pcbSilkscreenText, ctx) {
770
835
  transform: matrixToString2(textTransform),
771
836
  class: `pcb-silkscreen-text pcb-silkscreen-${layer}`,
772
837
  "data-pcb-silkscreen-text-id": pcbSilkscreenText.pcb_component_id,
773
- stroke: "none"
838
+ stroke: "none",
839
+ "data-type": "pcb_silkscreen_text",
840
+ "data-pcb-layer": layer
774
841
  },
775
842
  children,
776
843
  value: ""
@@ -812,7 +879,9 @@ function createSvgObjectsFromPcbSilkscreenRect(pcbSilkscreenRect, ctx) {
812
879
  width: transformedWidth.toString(),
813
880
  height: transformedHeight.toString(),
814
881
  class: `pcb-silkscreen-rect pcb-silkscreen-${layer}`,
815
- "data-pcb-silkscreen-rect-id": pcb_silkscreen_rect_id
882
+ "data-pcb-silkscreen-rect-id": pcb_silkscreen_rect_id,
883
+ "data-type": "pcb_silkscreen_rect",
884
+ "data-pcb-layer": layer
816
885
  };
817
886
  attributes.fill = is_filled ? color : "none";
818
887
  let actualHasStroke;
@@ -875,7 +944,9 @@ function createSvgObjectsFromPcbSilkscreenCircle(pcbSilkscreenCircle, ctx) {
875
944
  class: `pcb-silkscreen-circle pcb-silkscreen-${layer}`,
876
945
  stroke: color,
877
946
  "stroke-width": transformedStrokeWidth.toString(),
878
- "data-pcb-silkscreen-circle-id": pcb_silkscreen_circle_id
947
+ "data-pcb-silkscreen-circle-id": pcb_silkscreen_circle_id,
948
+ "data-type": "pcb_silkscreen_circle",
949
+ "data-pcb-layer": layer
879
950
  },
880
951
  value: "",
881
952
  children: []
@@ -917,7 +988,9 @@ function createSvgObjectsFromPcbSilkscreenLine(pcbSilkscreenLine, ctx) {
917
988
  stroke: color,
918
989
  "stroke-width": transformedStrokeWidth.toString(),
919
990
  class: `pcb-silkscreen-line pcb-silkscreen-${layer}`,
920
- "data-pcb-silkscreen-line-id": pcb_silkscreen_line_id
991
+ "data-pcb-silkscreen-line-id": pcb_silkscreen_line_id,
992
+ "data-type": "pcb_silkscreen_line",
993
+ "data-pcb-layer": layer
921
994
  },
922
995
  value: "",
923
996
  children: []
@@ -1015,7 +1088,8 @@ function createSvgObjectsFromPcbTrace(trace, ctx) {
1015
1088
  "stroke-linecap": "round",
1016
1089
  "stroke-linejoin": "round",
1017
1090
  "shape-rendering": "crispEdges",
1018
- "data-layer": layer
1091
+ "data-type": "pcb_trace",
1092
+ "data-pcb-layer": layer
1019
1093
  }
1020
1094
  };
1021
1095
  const maskObject = {
@@ -1032,7 +1106,8 @@ function createSvgObjectsFromPcbTrace(trace, ctx) {
1032
1106
  "stroke-linecap": "round",
1033
1107
  "stroke-linejoin": "round",
1034
1108
  "shape-rendering": "crispEdges",
1035
- "data-layer": layer
1109
+ "data-type": "pcb_soldermask",
1110
+ "data-pcb-layer": layer
1036
1111
  }
1037
1112
  };
1038
1113
  svgObjects.push(maskObject, copperObject);
@@ -1051,23 +1126,13 @@ function createSvgObjectsFromPcbTrace(trace, ctx) {
1051
1126
  "stroke-linecap": "round",
1052
1127
  "stroke-linejoin": "round",
1053
1128
  "shape-rendering": "crispEdges",
1054
- "data-layer": layer
1129
+ "data-type": renderSolderMask ? "pcb_soldermask" : "pcb_trace",
1130
+ "data-pcb-layer": layer
1055
1131
  }
1056
1132
  };
1057
1133
  svgObjects.push(maskOnlyObject);
1058
1134
  }
1059
1135
  }
1060
- svgObjects.sort((a, b) => {
1061
- const layerA = a.attributes["data-layer"];
1062
- const layerB = b.attributes["data-layer"];
1063
- if (layerA === "bottom" && layerB !== "bottom") {
1064
- return -1;
1065
- }
1066
- if (layerA === "top" && layerB !== "top") {
1067
- return 1;
1068
- }
1069
- return 0;
1070
- });
1071
1136
  return svgObjects;
1072
1137
  }
1073
1138
 
@@ -1098,7 +1163,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1098
1163
  width: width.toString(),
1099
1164
  height: height.toString(),
1100
1165
  transform: `translate(${x} ${y}) rotate(${-pad.ccw_rotation})`,
1101
- "data-layer": pad.layer,
1166
+ "data-type": "pcb_smtpad",
1167
+ "data-pcb-layer": pad.layer,
1102
1168
  ...scaledBorderRadius ? {
1103
1169
  rx: scaledBorderRadius.toString(),
1104
1170
  ry: scaledBorderRadius.toString()
@@ -1116,7 +1182,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1116
1182
  attributes: {
1117
1183
  ...padElement2.attributes,
1118
1184
  class: "pcb-solder-mask",
1119
- fill: solderMaskColor
1185
+ fill: solderMaskColor,
1186
+ "data-type": "pcb_soldermask"
1120
1187
  }
1121
1188
  };
1122
1189
  return [padElement2, maskElement2];
@@ -1133,7 +1200,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1133
1200
  y: (y - height / 2).toString(),
1134
1201
  width: width.toString(),
1135
1202
  height: height.toString(),
1136
- "data-layer": pad.layer,
1203
+ "data-type": "pcb_smtpad",
1204
+ "data-pcb-layer": pad.layer,
1137
1205
  ...scaledBorderRadius ? {
1138
1206
  rx: scaledBorderRadius.toString(),
1139
1207
  ry: scaledBorderRadius.toString()
@@ -1151,7 +1219,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1151
1219
  attributes: {
1152
1220
  ...padElement.attributes,
1153
1221
  class: "pcb-solder-mask",
1154
- fill: solderMaskColor
1222
+ fill: solderMaskColor,
1223
+ "data-type": "pcb_soldermask"
1155
1224
  }
1156
1225
  };
1157
1226
  return [padElement, maskElement];
@@ -1175,7 +1244,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1175
1244
  height: height.toString(),
1176
1245
  rx: radius.toString(),
1177
1246
  ry: radius.toString(),
1178
- "data-layer": pad.layer
1247
+ "data-type": "pcb_smtpad",
1248
+ "data-pcb-layer": pad.layer
1179
1249
  }
1180
1250
  };
1181
1251
  if (!shouldRenderSolderMask) {
@@ -1189,7 +1259,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1189
1259
  attributes: {
1190
1260
  ...padElement.attributes,
1191
1261
  class: "pcb-solder-mask",
1192
- fill: solderMaskColor
1262
+ fill: solderMaskColor,
1263
+ "data-type": "pcb_soldermask"
1193
1264
  }
1194
1265
  };
1195
1266
  return [padElement, maskElement];
@@ -1208,7 +1279,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1208
1279
  cx: x.toString(),
1209
1280
  cy: y.toString(),
1210
1281
  r: radius.toString(),
1211
- "data-layer": pad.layer
1282
+ "data-type": "pcb_smtpad",
1283
+ "data-pcb-layer": pad.layer
1212
1284
  }
1213
1285
  };
1214
1286
  if (!shouldRenderSolderMask) {
@@ -1222,7 +1294,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1222
1294
  attributes: {
1223
1295
  ...padElement.attributes,
1224
1296
  class: "pcb-solder-mask",
1225
- fill: solderMaskColor
1297
+ fill: solderMaskColor,
1298
+ "data-type": "pcb_soldermask"
1226
1299
  }
1227
1300
  };
1228
1301
  return [padElement, maskElement];
@@ -1240,7 +1313,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1240
1313
  class: "pcb-pad",
1241
1314
  fill: layerNameToColor(pad.layer, colorMap2),
1242
1315
  points: points.map((p) => p.join(",")).join(" "),
1243
- "data-layer": pad.layer
1316
+ "data-type": "pcb_smtpad",
1317
+ "data-pcb-layer": pad.layer
1244
1318
  }
1245
1319
  };
1246
1320
  if (!shouldRenderSolderMask) {
@@ -1254,7 +1328,8 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
1254
1328
  attributes: {
1255
1329
  ...padElement.attributes,
1256
1330
  class: "pcb-solder-mask",
1257
- fill: solderMaskColor
1331
+ fill: solderMaskColor,
1332
+ "data-type": "pcb_soldermask"
1258
1333
  }
1259
1334
  };
1260
1335
  return [padElement, maskElement];
@@ -1306,7 +1381,9 @@ function createSvgObjectsFromPcbBoard(pcbBoard, ctx) {
1306
1381
  d: path,
1307
1382
  fill: "none",
1308
1383
  stroke: colorMap2.boardOutline,
1309
- "stroke-width": (0.1 * Math.abs(transform.a)).toString()
1384
+ "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
1385
+ "data-type": "pcb_board",
1386
+ "data-pcb-layer": "board"
1310
1387
  }
1311
1388
  }
1312
1389
  ];
@@ -1326,6 +1403,10 @@ function createSvgObjectsFromPcbVia(hole, ctx) {
1326
1403
  return {
1327
1404
  name: "g",
1328
1405
  type: "element",
1406
+ attributes: {
1407
+ "data-type": "pcb_via",
1408
+ "data-pcb-layer": "through"
1409
+ },
1329
1410
  children: [
1330
1411
  {
1331
1412
  name: "circle",
@@ -1335,7 +1416,9 @@ function createSvgObjectsFromPcbVia(hole, ctx) {
1335
1416
  fill: colorMap2.copper.top,
1336
1417
  cx: x.toString(),
1337
1418
  cy: y.toString(),
1338
- r: outerRadius.toString()
1419
+ r: outerRadius.toString(),
1420
+ "data-type": "pcb_via",
1421
+ "data-pcb-layer": "top"
1339
1422
  }
1340
1423
  },
1341
1424
  {
@@ -1346,7 +1429,9 @@ function createSvgObjectsFromPcbVia(hole, ctx) {
1346
1429
  fill: colorMap2.drill,
1347
1430
  cx: x.toString(),
1348
1431
  cy: y.toString(),
1349
- r: innerRadius.toString()
1432
+ r: innerRadius.toString(),
1433
+ "data-type": "pcb_via",
1434
+ "data-pcb-layer": "drill"
1350
1435
  }
1351
1436
  }
1352
1437
  ]
@@ -1371,7 +1456,9 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
1371
1456
  cx: x.toString(),
1372
1457
  cy: y.toString(),
1373
1458
  r: radius.toString(),
1374
- fill: colorMap2.drill
1459
+ fill: colorMap2.drill,
1460
+ "data-type": "pcb_hole",
1461
+ "data-pcb-layer": "drill"
1375
1462
  },
1376
1463
  children: [],
1377
1464
  value: ""
@@ -1388,7 +1475,9 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
1388
1475
  y: (y - radius).toString(),
1389
1476
  width: scaledDiameter.toString(),
1390
1477
  height: scaledDiameter.toString(),
1391
- fill: colorMap2.drill
1478
+ fill: colorMap2.drill,
1479
+ "data-type": "pcb_hole",
1480
+ "data-pcb-layer": "drill"
1392
1481
  },
1393
1482
  children: [],
1394
1483
  value: ""
@@ -1410,7 +1499,9 @@ function createSvgObjectsFromPcbHole(hole, ctx) {
1410
1499
  cy: y.toString(),
1411
1500
  rx: rx.toString(),
1412
1501
  ry: ry.toString(),
1413
- fill: colorMap2.drill
1502
+ fill: colorMap2.drill,
1503
+ "data-type": "pcb_hole",
1504
+ "data-pcb-layer": "drill"
1414
1505
  },
1415
1506
  children: [],
1416
1507
  value: ""
@@ -1520,7 +1611,9 @@ function createSvgObjectsForRatsNest(circuitJson, ctx) {
1520
1611
  y2: transformedEnd[1].toString(),
1521
1612
  stroke: "white",
1522
1613
  "stroke-width": "1",
1523
- "stroke-dasharray": "6,6"
1614
+ "stroke-dasharray": "6,6",
1615
+ "data-type": "pcb_rats_nest",
1616
+ "data-pcb-layer": "overlay"
1524
1617
  };
1525
1618
  svgObjects.push({
1526
1619
  name: "line",
@@ -1565,7 +1658,9 @@ function createSvgObjectsFromPcbCutout(cutout, ctx) {
1565
1658
  fill: colorMap2.drill,
1566
1659
  transform: matrixToString6(
1567
1660
  compose3(translate3(cx, cy), rotate3(svgRotation * Math.PI / 180))
1568
- )
1661
+ ),
1662
+ "data-type": "pcb_cutout",
1663
+ "data-pcb-layer": "drill"
1569
1664
  },
1570
1665
  children: [],
1571
1666
  value: ""
@@ -1588,7 +1683,9 @@ function createSvgObjectsFromPcbCutout(cutout, ctx) {
1588
1683
  cx: cx.toString(),
1589
1684
  cy: cy.toString(),
1590
1685
  r: scaledRadius.toString(),
1591
- fill: colorMap2.drill
1686
+ fill: colorMap2.drill,
1687
+ "data-type": "pcb_cutout",
1688
+ "data-pcb-layer": "drill"
1592
1689
  },
1593
1690
  children: [],
1594
1691
  value: ""
@@ -1609,7 +1706,9 @@ function createSvgObjectsFromPcbCutout(cutout, ctx) {
1609
1706
  attributes: {
1610
1707
  class: "pcb-cutout pcb-cutout-polygon",
1611
1708
  points: pointsString,
1612
- fill: colorMap2.drill
1709
+ fill: colorMap2.drill,
1710
+ "data-type": "pcb_cutout",
1711
+ "data-pcb-layer": "drill"
1613
1712
  },
1614
1713
  children: [],
1615
1714
  value: ""
@@ -1685,7 +1784,8 @@ function createSvgObjectsFromPcbCopperPour(pour, ctx) {
1685
1784
  transform: matrixToString7(
1686
1785
  compose4(translate4(cx, cy), rotate4(svgRotation * Math.PI / 180))
1687
1786
  ),
1688
- "data-layer": layer
1787
+ "data-type": "pcb_copper_pour",
1788
+ "data-pcb-layer": layer
1689
1789
  },
1690
1790
  children: [],
1691
1791
  value: ""
@@ -1707,7 +1807,8 @@ function createSvgObjectsFromPcbCopperPour(pour, ctx) {
1707
1807
  points: pointsString,
1708
1808
  fill: color,
1709
1809
  "fill-opacity": opacity,
1710
- "data-layer": layer
1810
+ "data-type": "pcb_copper_pour",
1811
+ "data-pcb-layer": layer
1711
1812
  },
1712
1813
  children: [],
1713
1814
  value: ""
@@ -1730,7 +1831,8 @@ function createSvgObjectsFromPcbCopperPour(pour, ctx) {
1730
1831
  fill: color,
1731
1832
  "fill-rule": "evenodd",
1732
1833
  "fill-opacity": opacity,
1733
- "data-layer": layer
1834
+ "data-type": "pcb_copper_pour",
1835
+ "data-pcb-layer": layer
1734
1836
  },
1735
1837
  children: [],
1736
1838
  value: ""
@@ -1756,7 +1858,11 @@ function createSvgObjectsFromPcbComponent(component, ctx) {
1756
1858
  {
1757
1859
  name: "g",
1758
1860
  type: "element",
1759
- attributes: { transform: transformStr },
1861
+ attributes: {
1862
+ transform: transformStr,
1863
+ "data-type": "pcb_component",
1864
+ "data-pcb-layer": component.layer ?? "top"
1865
+ },
1760
1866
  children: [
1761
1867
  {
1762
1868
  name: "rect",
@@ -1768,7 +1874,9 @@ function createSvgObjectsFromPcbComponent(component, ctx) {
1768
1874
  width: scaledWidth.toString(),
1769
1875
  height: scaledHeight.toString(),
1770
1876
  fill: ctx.colorMap.debugComponent.fill ?? "transparent",
1771
- stroke: ctx.colorMap.debugComponent.stroke ?? "transparent"
1877
+ stroke: ctx.colorMap.debugComponent.stroke ?? "transparent",
1878
+ "data-type": "pcb_component",
1879
+ "data-pcb-layer": component.layer ?? "top"
1772
1880
  }
1773
1881
  }
1774
1882
  ],
@@ -1789,7 +1897,7 @@ function getSoftwareUsedString(circuitJson) {
1789
1897
  var package_default = {
1790
1898
  name: "circuit-to-svg",
1791
1899
  type: "module",
1792
- version: "0.0.225",
1900
+ version: "0.0.226",
1793
1901
  description: "Convert Circuit JSON to SVG",
1794
1902
  main: "dist/index.js",
1795
1903
  files: [
@@ -1835,23 +1943,76 @@ var package_default = {
1835
1943
  // lib/package-version.ts
1836
1944
  var CIRCUIT_TO_SVG_VERSION = package_default.version;
1837
1945
 
1946
+ // lib/pcb/sort-svg-objects-by-pcb-layer.ts
1947
+ var TYPE_PRIORITY = {
1948
+ pcb_background: 0,
1949
+ pcb_boundary: 1,
1950
+ pcb_board: 10,
1951
+ pcb_cutout: 15,
1952
+ pcb_hole: 18,
1953
+ pcb_plated_hole_drill: 19,
1954
+ pcb_plated_hole: 20,
1955
+ pcb_trace: 30,
1956
+ pcb_smtpad: 30,
1957
+ pcb_copper_pour: 35,
1958
+ pcb_via: 36,
1959
+ pcb_soldermask: 40,
1960
+ pcb_solder_paste: 45,
1961
+ pcb_silkscreen_text: 50,
1962
+ pcb_silkscreen_path: 50,
1963
+ pcb_silkscreen_rect: 50,
1964
+ pcb_silkscreen_circle: 50,
1965
+ pcb_silkscreen_line: 50,
1966
+ pcb_component: 60,
1967
+ pcb_fabrication_note_text: 70,
1968
+ pcb_fabrication_note_path: 70,
1969
+ pcb_trace_error: 80,
1970
+ pcb_rats_nest: 85
1971
+ };
1972
+ var DEFAULT_TYPE_PRIORITY = 100;
1973
+ function sortSvgObjectsByPcbLayer(objects) {
1974
+ return objects.map((object, index) => ({
1975
+ object,
1976
+ index,
1977
+ layerPriority: getLayerPriority(
1978
+ object.attributes?.["data-pcb-layer"] ?? void 0
1979
+ ),
1980
+ typePriority: getTypePriority(
1981
+ object.attributes?.["data-type"] ?? void 0
1982
+ )
1983
+ })).sort((a, b) => {
1984
+ if (a.layerPriority !== b.layerPriority) {
1985
+ return a.layerPriority - b.layerPriority;
1986
+ }
1987
+ if (a.typePriority !== b.typePriority) {
1988
+ return a.typePriority - b.typePriority;
1989
+ }
1990
+ return a.index - b.index;
1991
+ }).map(({ object }) => object);
1992
+ }
1993
+ function getLayerPriority(layer) {
1994
+ if (!layer) return 500;
1995
+ const normalized = layer.toLowerCase();
1996
+ if (normalized === "global") return -100;
1997
+ if (normalized === "bottom") return 0;
1998
+ if (normalized === "board") return 2;
1999
+ if (normalized.startsWith("inner")) {
2000
+ const match = normalized.match(/\d+/);
2001
+ const layerIndex = match ? parseInt(match[0], 10) : 0;
2002
+ return 5 + layerIndex;
2003
+ }
2004
+ if (normalized === "through") return 18;
2005
+ if (normalized === "top") return 20;
2006
+ if (normalized === "drill") return 30;
2007
+ if (normalized === "overlay") return 40;
2008
+ return 10;
2009
+ }
2010
+ function getTypePriority(type) {
2011
+ if (!type) return DEFAULT_TYPE_PRIORITY;
2012
+ return TYPE_PRIORITY[type] ?? DEFAULT_TYPE_PRIORITY;
2013
+ }
2014
+
1838
2015
  // lib/pcb/convert-circuit-json-to-pcb-svg.ts
1839
- var OBJECT_ORDER = [
1840
- "pcb_trace_error",
1841
- "pcb_plated_hole",
1842
- "pcb_fabrication_note_text",
1843
- "pcb_fabrication_note_path",
1844
- "pcb_silkscreen_text",
1845
- "pcb_silkscreen_path",
1846
- "pcb_via",
1847
- "pcb_cutout",
1848
- "pcb_copper_pour",
1849
- // Draw traces before SMT pads so pads appear on top
1850
- "pcb_smtpad",
1851
- "pcb_trace",
1852
- "pcb_component",
1853
- "pcb_board"
1854
- ];
1855
2016
  function convertCircuitJsonToPcbSvg(circuitJson, options) {
1856
2017
  const drawPaddingOutsideBoard = options?.drawPaddingOutsideBoard ?? true;
1857
2018
  const layer = options?.layer;
@@ -1985,34 +2146,10 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
1985
2146
  colorMap: colorMap2,
1986
2147
  renderSolderMask: options?.renderSolderMask
1987
2148
  };
1988
- function getLayer(elm) {
1989
- if (elm.type === "pcb_smtpad") {
1990
- return elm.layer === "top" || elm.layer === "bottom" ? elm.layer : void 0;
1991
- }
1992
- if (elm.type === "pcb_trace") {
1993
- for (const seg of elm.route ?? []) {
1994
- const candidate = "layer" in seg && seg.layer || "from_layer" in seg && seg.from_layer || "to_layer" in seg && seg.to_layer || void 0;
1995
- if (candidate === "top" || candidate === "bottom") {
1996
- return candidate;
1997
- }
1998
- }
1999
- }
2000
- return void 0;
2001
- }
2002
- function isCopper(elm) {
2003
- return elm.type === "pcb_trace" || elm.type === "pcb_smtpad";
2004
- }
2005
- let svgObjects = circuitJson.sort((a, b) => {
2006
- const layerA = getLayer(a);
2007
- const layerB = getLayer(b);
2008
- if (isCopper(a) && isCopper(b) && layerA !== layerB) {
2009
- if (layerA === "top") return 1;
2010
- if (layerB === "top") return -1;
2011
- if (layerA === "bottom") return -1;
2012
- if (layerB === "bottom") return 1;
2013
- }
2014
- return (OBJECT_ORDER.indexOf(b.type) ?? 9999) - (OBJECT_ORDER.indexOf(a.type) ?? 9999);
2015
- }).flatMap((elm) => createSvgObjects({ elm, circuitJson, ctx }));
2149
+ const unsortedSvgObjects = circuitJson.flatMap(
2150
+ (elm) => createSvgObjects({ elm, circuitJson, ctx })
2151
+ );
2152
+ let svgObjects = sortSvgObjectsByPcbLayer(unsortedSvgObjects);
2016
2153
  let strokeWidth = String(0.05 * scaleFactor);
2017
2154
  for (const element of circuitJson) {
2018
2155
  if ("stroke_width" in element) {
@@ -2022,7 +2159,7 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
2022
2159
  }
2023
2160
  if (options?.shouldDrawRatsNest) {
2024
2161
  const ratsNestObjects = createSvgObjectsForRatsNest(circuitJson, ctx);
2025
- svgObjects = svgObjects.concat(ratsNestObjects);
2162
+ svgObjects = sortSvgObjectsByPcbLayer([...svgObjects, ...ratsNestObjects]);
2026
2163
  }
2027
2164
  const children = [
2028
2165
  {
@@ -2050,7 +2187,9 @@ function convertCircuitJsonToPcbSvg(circuitJson, options) {
2050
2187
  y: "0",
2051
2188
  fill: options?.backgroundColor ?? "#000",
2052
2189
  width: svgWidth.toString(),
2053
- height: svgHeight.toString()
2190
+ height: svgHeight.toString(),
2191
+ "data-type": "pcb_background",
2192
+ "data-pcb-layer": "global"
2054
2193
  },
2055
2194
  children: []
2056
2195
  }
@@ -2216,7 +2355,9 @@ function createSvgObjectFromPcbBoundary(transform, minX, minY, maxX, maxY) {
2216
2355
  x: x.toString(),
2217
2356
  y: y.toString(),
2218
2357
  width: width.toString(),
2219
- height: height.toString()
2358
+ height: height.toString(),
2359
+ "data-type": "pcb_boundary",
2360
+ "data-pcb-layer": "global"
2220
2361
  }
2221
2362
  };
2222
2363
  }
@@ -2945,7 +3086,7 @@ function createSvgObjectsFromAssemblySmtPad(pad, ctx) {
2945
3086
  }
2946
3087
 
2947
3088
  // lib/assembly/convert-circuit-json-to-assembly-svg.ts
2948
- var OBJECT_ORDER2 = [
3089
+ var OBJECT_ORDER = [
2949
3090
  "pcb_component",
2950
3091
  "pcb_smtpad",
2951
3092
  "pcb_hole",
@@ -2988,7 +3129,7 @@ function convertCircuitJsonToAssemblySvg(soup, options) {
2988
3129
  );
2989
3130
  const ctx = { transform };
2990
3131
  const svgObjects = soup.sort(
2991
- (a, b) => (OBJECT_ORDER2.indexOf(b.type) ?? 9999) - (OBJECT_ORDER2.indexOf(a.type) ?? 9999)
3132
+ (a, b) => (OBJECT_ORDER.indexOf(b.type) ?? 9999) - (OBJECT_ORDER.indexOf(a.type) ?? 9999)
2992
3133
  ).flatMap((item) => createSvgObjects2(item, ctx, soup));
2993
3134
  const softwareUsedString = getSoftwareUsedString(soup);
2994
3135
  const version = CIRCUIT_TO_SVG_VERSION;
@@ -4161,7 +4302,7 @@ function getClosestEdge(port_pos_real, board_bounds) {
4161
4302
  }
4162
4303
 
4163
4304
  // lib/pinout/convert-circuit-json-to-pinout-svg.ts
4164
- var OBJECT_ORDER3 = [
4305
+ var OBJECT_ORDER2 = [
4165
4306
  "pcb_board",
4166
4307
  "pcb_smtpad",
4167
4308
  "pcb_hole",
@@ -4321,7 +4462,7 @@ function convertCircuitJsonToPinoutSvg(soup, options) {
4321
4462
  label_positions
4322
4463
  };
4323
4464
  const svgObjects = soup.sort(
4324
- (a, b) => (OBJECT_ORDER3.indexOf(a.type) ?? 9999) - (OBJECT_ORDER3.indexOf(b.type) ?? 9999)
4465
+ (a, b) => (OBJECT_ORDER2.indexOf(a.type) ?? 9999) - (OBJECT_ORDER2.indexOf(b.type) ?? 9999)
4325
4466
  ).flatMap((item) => createSvgObjects3(item, ctx, soup));
4326
4467
  const softwareUsedString = getSoftwareUsedString(soup);
4327
4468
  const version = CIRCUIT_TO_SVG_VERSION;
@@ -8888,7 +9029,9 @@ function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
8888
9029
  y: (-height / 2).toString(),
8889
9030
  width: width.toString(),
8890
9031
  height: height.toString(),
8891
- transform: `translate(${x} ${y}) rotate(${-solderPaste.ccw_rotation})`
9032
+ transform: `translate(${x} ${y}) rotate(${-solderPaste.ccw_rotation})`,
9033
+ "data-type": "pcb_solder_paste",
9034
+ "data-pcb-layer": solderPaste.layer
8892
9035
  }
8893
9036
  }
8894
9037
  ];
@@ -8903,7 +9046,9 @@ function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
8903
9046
  x: (x - width / 2).toString(),
8904
9047
  y: (y - height / 2).toString(),
8905
9048
  width: width.toString(),
8906
- height: height.toString()
9049
+ height: height.toString(),
9050
+ "data-type": "pcb_solder_paste",
9051
+ "data-pcb-layer": solderPaste.layer
8907
9052
  }
8908
9053
  }
8909
9054
  ];
@@ -8923,7 +9068,9 @@ function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
8923
9068
  y: (y - height / 2).toString(),
8924
9069
  width: width.toString(),
8925
9070
  height: height.toString(),
8926
- rx: radius.toString()
9071
+ rx: radius.toString(),
9072
+ "data-type": "pcb_solder_paste",
9073
+ "data-pcb-layer": solderPaste.layer
8927
9074
  }
8928
9075
  }
8929
9076
  ];
@@ -8939,7 +9086,9 @@ function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
8939
9086
  fill: solderPasteLayerNameToColor(solderPaste.layer),
8940
9087
  cx: x.toString(),
8941
9088
  cy: y.toString(),
8942
- r: radius.toString()
9089
+ r: radius.toString(),
9090
+ "data-type": "pcb_solder_paste",
9091
+ "data-pcb-layer": solderPaste.layer
8943
9092
  }
8944
9093
  }
8945
9094
  ];
@@ -8947,7 +9096,7 @@ function createSvgObjectsFromSolderPaste(solderPaste, ctx) {
8947
9096
  }
8948
9097
 
8949
9098
  // lib/pcb/convert-circuit-json-to-solder-paste-mask.ts
8950
- var OBJECT_ORDER4 = [
9099
+ var OBJECT_ORDER3 = [
8951
9100
  "pcb_board",
8952
9101
  "pcb_solder_paste"
8953
9102
  ];
@@ -8994,7 +9143,7 @@ function convertCircuitJsonToSolderPasteMask(circuitJson, options) {
8994
9143
  colorMap: DEFAULT_PCB_COLOR_MAP
8995
9144
  };
8996
9145
  const svgObjects = filteredCircuitJson.sort(
8997
- (a, b) => (OBJECT_ORDER4.indexOf(b.type) ?? 9999) - (OBJECT_ORDER4.indexOf(a.type) ?? 9999)
9146
+ (a, b) => (OBJECT_ORDER3.indexOf(b.type) ?? 9999) - (OBJECT_ORDER3.indexOf(a.type) ?? 9999)
8998
9147
  ).flatMap((item) => createSvgObjects4({ elm: item, ctx }));
8999
9148
  const softwareUsedString = getSoftwareUsedString(circuitJson);
9000
9149
  const version = CIRCUIT_TO_SVG_VERSION;