altium-to-circuit-json 0.0.89 → 0.0.91

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.d.ts CHANGED
@@ -8,6 +8,7 @@ declare class PcbCopperLayerMap {
8
8
  private readonly mappings;
9
9
  constructor(document: AltiumPcbDocument);
10
10
  getLayer(layer: string | undefined): LayerRef | undefined;
11
+ getDisplayName(layer: string | undefined): string | undefined;
11
12
  }
12
13
 
13
14
  interface ConvertAltiumPcbDocOptions {
package/dist/index.js CHANGED
@@ -55,6 +55,36 @@ var INNER_LAYERS = all_layers.filter(
55
55
  (layer) => layer.startsWith("inner")
56
56
  );
57
57
 
58
+ // lib/pcb/layers/getAltiumPcbLayerDisplayName.ts
59
+ import { getAltiumPcbLayerAliasKey } from "altiumts";
60
+ var STANDARD_LAYER_LABELS = {
61
+ BOTTOM: "Bottom Layer",
62
+ BOTTOMOVERLAY: "Bottom Overlay",
63
+ BOTTOMPASTE: "Bottom Paste",
64
+ BOTTOMSOLDER: "Bottom Solder",
65
+ DRILLDRAWING: "Drill Drawing",
66
+ DRILLGUIDE: "Drill Guide",
67
+ KEEPOUT: "Keep-Out Layer",
68
+ MULTILAYER: "Multi-Layer",
69
+ TOP: "Top Layer",
70
+ TOPOVERLAY: "Top Overlay",
71
+ TOPPASTE: "Top Paste",
72
+ TOPSOLDER: "Top Solder"
73
+ };
74
+ function getAltiumPcbLayerDisplayName(layer) {
75
+ if (!layer) return void 0;
76
+ const layerKey = getAltiumPcbLayerAliasKey(layer);
77
+ const standardLabel = STANDARD_LAYER_LABELS[layerKey];
78
+ if (standardLabel) return standardLabel;
79
+ const signalLayerOrdinal = /^MID(\d+)$/u.exec(layerKey)?.[1];
80
+ if (signalLayerOrdinal) return `Signal Layer ${signalLayerOrdinal}`;
81
+ const planeLayerOrdinal = /^INTERNALPLANE(\d+)$/u.exec(layerKey)?.[1];
82
+ if (planeLayerOrdinal) return `Internal Plane ${planeLayerOrdinal}`;
83
+ const mechanicalLayerOrdinal = /^MECHANICAL(\d+)$/u.exec(layerKey)?.[1];
84
+ if (mechanicalLayerOrdinal) return `Mechanical ${mechanicalLayerOrdinal}`;
85
+ return layer.trim() || void 0;
86
+ }
87
+
58
88
  // lib/pcb/layers/getRecordLayer.ts
59
89
  function getRecordLayer(record) {
60
90
  return record.getDecoded("LAYER");
@@ -218,8 +248,8 @@ var PcbCopperLayerMap = class {
218
248
  if (entries.length === 0) {
219
249
  this.layers = ["top", "bottom"];
220
250
  this.mappings.push(
221
- { keys: ["TOP"], layer: "top" },
222
- { keys: ["BOTTOM"], layer: "bottom" }
251
+ { displayName: "Top Layer", keys: ["TOP"], layer: "top" },
252
+ { displayName: "Bottom Layer", keys: ["BOTTOM"], layer: "bottom" }
223
253
  );
224
254
  return;
225
255
  }
@@ -244,7 +274,9 @@ var PcbCopperLayerMap = class {
244
274
  );
245
275
  }
246
276
  }
247
- this.mappings.push({ keys, layer });
277
+ const displayName = entry.name?.trim() || getAltiumPcbLayerDisplayName(entry.layerId);
278
+ if (!displayName) throw new Error("Copper board stack layer has no name");
279
+ this.mappings.push({ displayName, keys, layer });
248
280
  }
249
281
  }
250
282
  getLayer(layer) {
@@ -259,6 +291,11 @@ var PcbCopperLayerMap = class {
259
291
  }
260
292
  return void 0;
261
293
  }
294
+ getDisplayName(layer) {
295
+ const identity = getCopperLayerIdentity(layer);
296
+ const key = identity ?? normalizeLayer(layer);
297
+ return this.mappings.find((mapping) => mapping.keys.includes(key))?.displayName;
298
+ }
262
299
  };
263
300
 
264
301
  // lib/pcb/pads/isElectricalPcbPad.ts
@@ -3313,7 +3350,7 @@ function convertOwnedComponentRecords({
3313
3350
  0.05
3314
3351
  )
3315
3352
  } : element;
3316
- return preparedElement.type === "schematic_text" ? preparedElement : {
3353
+ return {
3317
3354
  ...preparedElement,
3318
3355
  schematic_component_id: schematicComponentId
3319
3356
  };
@@ -3591,7 +3628,7 @@ function convertPrimitiveGatePin(port, context) {
3591
3628
  delete port.schematicPort.display_pin_label;
3592
3629
  delete port.schematicPort.display_pin_label_text_parts;
3593
3630
  return elements.map(
3594
- (element) => element.type === "schematic_line" || element.type === "schematic_circle" || element.type === "schematic_path" ? {
3631
+ (element) => element.type === "schematic_line" || element.type === "schematic_circle" || element.type === "schematic_path" || element.type === "schematic_text" ? {
3595
3632
  ...element,
3596
3633
  schematic_component_id: port.schematicPort.schematic_component_id
3597
3634
  } : element
@@ -3807,7 +3844,7 @@ function createNumericPinDesignatorText({
3807
3844
  font_size: Math.max(scaleLength(1.5, scale5), 0.15),
3808
3845
  position,
3809
3846
  rotation: side === "top" || side === "bottom" ? -90 : 0,
3810
- // Primitive component bodies render their text as sheet-level elements.
3847
+ schematic_component_id: schematicPort.schematic_component_id,
3811
3848
  schematic_sheet_id: schematicPort.schematic_sheet_id,
3812
3849
  schematic_text_id: `schematic_pin_designator_altium_${recordIndex}`,
3813
3850
  text: designator
@@ -6012,67 +6049,26 @@ function mapTextAnchor(justification) {
6012
6049
  return "bottom_left";
6013
6050
  }
6014
6051
 
6015
- // lib/pcb/text/convertPcbCopperText.ts
6016
- function convertPcbCopperText({
6017
- layerMap,
6018
- record,
6019
- recordIndex
6020
- }) {
6021
- if (!record.position || !record.text) return void 0;
6022
- const layer = layerMap.getLayer(record.layer);
6023
- if (!layer) return void 0;
6024
- return {
6025
- type: "pcb_copper_text",
6026
- pcb_copper_text_id: `pcb_copper_text_altium_${recordIndex}`,
6027
- pcb_component_id: getPcbComponentIdForRecord(record),
6028
- text: record.text,
6029
- font: "tscircuit2024",
6030
- font_size: milsToMillimeters(record.heightMils ?? 30),
6031
- anchor_position: toMillimeterPoint(record.position),
6032
- anchor_alignment: mapTextAnchor(record.justification),
6033
- ccw_rotation: record.rotation,
6034
- layer,
6035
- is_mirrored: record.mirrored
6036
- };
6037
- }
6038
-
6039
- // lib/pcb/text/mapFabricationTextAnchor.ts
6040
- function mapFabricationTextAnchor(justification) {
6041
- const anchor = mapTextAnchor(justification);
6042
- return anchor === "top_left" || anchor === "top_right" || anchor === "bottom_left" || anchor === "bottom_right" ? anchor : "center";
6052
+ // lib/pcb/text/escapeRegularExpression.ts
6053
+ function escapeRegularExpression(text) {
6054
+ return text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
6043
6055
  }
6044
6056
 
6045
- // lib/pcb/text/convertPcbMechanicalText.ts
6046
- function convertPcbMechanicalText({
6047
- document,
6048
- record,
6049
- recordIndex
6057
+ // lib/pcb/text/replaceMatchingSpecialString.ts
6058
+ function replaceMatchingSpecialString({
6059
+ isQuoted,
6060
+ replacement,
6061
+ text
6050
6062
  }) {
6051
- const componentIndex = record.componentIndex;
6052
- const component = document.getComponentForRecord(record);
6053
- if (!record.position || componentIndex === void 0 || !component || !record.text) {
6054
- return void 0;
6063
+ const escapedName = escapeRegularExpression(replacement.name);
6064
+ const quotedExpression = new RegExp(`'\\.${escapedName}'`, "giu");
6065
+ if (isQuoted) {
6066
+ return text.replace(quotedExpression, () => replacement.text);
6055
6067
  }
6056
- const normalizedText = record.text.trim().toUpperCase();
6057
- const isDesignator = normalizedText === ".DESIGNATOR";
6058
- const isComment = normalizedText === ".COMMENT";
6059
- if (isDesignator && component.getBoolean("NAMEON") === false) return void 0;
6060
- if (isComment && component.getBoolean("COMMENTON") === false) return void 0;
6061
- const text = isDesignator ? component.designator : isComment ? component.comment : record.text;
6062
- if (!text) return void 0;
6063
- return {
6064
- type: "pcb_fabrication_note_text",
6065
- pcb_fabrication_note_text_id: `pcb_fabrication_note_text_altium_${recordIndex}`,
6066
- pcb_component_id: getPcbComponentId(componentIndex),
6067
- text,
6068
- font: "tscircuit2024",
6069
- font_size: milsToMillimeters(record.heightMils ?? 30),
6070
- anchor_position: toMillimeterPoint(record.position),
6071
- anchor_alignment: mapFabricationTextAnchor(record.justification),
6072
- ccw_rotation: record.rotation,
6073
- layer: component.side === "bottom" ? "bottom" : "top",
6074
- color: FABRICATION_NOTE_COLOR
6075
- };
6068
+ const exactReference = `.${replacement.name}`.toLowerCase();
6069
+ return text.split("'").map(
6070
+ (segment, index) => index % 2 === 0 && segment.toLowerCase() === exactReference ? replacement.text : segment
6071
+ ).join("'");
6076
6072
  }
6077
6073
 
6078
6074
  // lib/pcb/text/getProjectTextReplacements.ts
@@ -6103,28 +6099,6 @@ function getProjectTextReplacements(project) {
6103
6099
  return replacements;
6104
6100
  }
6105
6101
 
6106
- // lib/pcb/text/escapeRegularExpression.ts
6107
- function escapeRegularExpression(text) {
6108
- return text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
6109
- }
6110
-
6111
- // lib/pcb/text/replaceMatchingSpecialString.ts
6112
- function replaceMatchingSpecialString({
6113
- isQuoted,
6114
- replacement,
6115
- text
6116
- }) {
6117
- const escapedName = escapeRegularExpression(replacement.name);
6118
- const quotedExpression = new RegExp(`'\\.${escapedName}'`, "giu");
6119
- if (isQuoted) {
6120
- return text.replace(quotedExpression, () => replacement.text);
6121
- }
6122
- const exactReference = `.${replacement.name}`.toLowerCase();
6123
- return text.split("'").map(
6124
- (segment, index) => index % 2 === 0 && segment.toLowerCase() === exactReference ? replacement.text : segment
6125
- ).join("'");
6126
- }
6127
-
6128
6102
  // lib/pcb/text/resolvePcbProjectSpecialStrings.ts
6129
6103
  function resolvePcbProjectSpecialStrings({
6130
6104
  project,
@@ -6152,6 +6126,103 @@ function resolvePcbProjectSpecialStrings({
6152
6126
  return resolvedText;
6153
6127
  }
6154
6128
 
6129
+ // lib/pcb/text/resolvePcbTextSpecialStrings.ts
6130
+ function resolvePcbTextSpecialStrings({
6131
+ layer,
6132
+ layerMap,
6133
+ project,
6134
+ text
6135
+ }) {
6136
+ if (!text.toLowerCase().includes(".layer_name")) {
6137
+ return resolvePcbProjectSpecialStrings({ project, text });
6138
+ }
6139
+ const layerDisplayName = layerMap.getDisplayName(layer) ?? getAltiumPcbLayerDisplayName(layer);
6140
+ if (!layerDisplayName)
6141
+ return resolvePcbProjectSpecialStrings({ project, text });
6142
+ const replacement = { name: "Layer_Name", text: layerDisplayName };
6143
+ const layerResolvedText = replaceMatchingSpecialString({
6144
+ isQuoted: true,
6145
+ replacement,
6146
+ text: replaceMatchingSpecialString({
6147
+ isQuoted: false,
6148
+ replacement,
6149
+ text
6150
+ })
6151
+ });
6152
+ return resolvePcbProjectSpecialStrings({ project, text: layerResolvedText });
6153
+ }
6154
+
6155
+ // lib/pcb/text/convertPcbCopperText.ts
6156
+ function convertPcbCopperText({
6157
+ context,
6158
+ record,
6159
+ recordIndex
6160
+ }) {
6161
+ if (!record.position || !record.text) return void 0;
6162
+ const { layerMap, options } = context;
6163
+ const layer = layerMap.getLayer(record.layer);
6164
+ if (!layer) return void 0;
6165
+ const text = resolvePcbTextSpecialStrings({
6166
+ layer: record.layer,
6167
+ layerMap,
6168
+ project: options.project,
6169
+ text: record.text
6170
+ });
6171
+ if (!text) return void 0;
6172
+ return {
6173
+ type: "pcb_copper_text",
6174
+ pcb_copper_text_id: `pcb_copper_text_altium_${recordIndex}`,
6175
+ pcb_component_id: getPcbComponentIdForRecord(record),
6176
+ text,
6177
+ font: "tscircuit2024",
6178
+ font_size: milsToMillimeters(record.heightMils ?? 30),
6179
+ anchor_position: toMillimeterPoint(record.position),
6180
+ anchor_alignment: mapTextAnchor(record.justification),
6181
+ ccw_rotation: record.rotation,
6182
+ layer,
6183
+ is_mirrored: record.mirrored
6184
+ };
6185
+ }
6186
+
6187
+ // lib/pcb/text/mapFabricationTextAnchor.ts
6188
+ function mapFabricationTextAnchor(justification) {
6189
+ const anchor = mapTextAnchor(justification);
6190
+ return anchor === "top_left" || anchor === "top_right" || anchor === "bottom_left" || anchor === "bottom_right" ? anchor : "center";
6191
+ }
6192
+
6193
+ // lib/pcb/text/convertPcbMechanicalText.ts
6194
+ function convertPcbMechanicalText({
6195
+ document,
6196
+ record,
6197
+ recordIndex
6198
+ }) {
6199
+ const componentIndex = record.componentIndex;
6200
+ const component = document.getComponentForRecord(record);
6201
+ if (!record.position || componentIndex === void 0 || !component || !record.text) {
6202
+ return void 0;
6203
+ }
6204
+ const normalizedText = record.text.trim().toUpperCase();
6205
+ const isDesignator = normalizedText === ".DESIGNATOR";
6206
+ const isComment = normalizedText === ".COMMENT";
6207
+ if (isDesignator && component.getBoolean("NAMEON") === false) return void 0;
6208
+ if (isComment && component.getBoolean("COMMENTON") === false) return void 0;
6209
+ const text = isDesignator ? component.designator : isComment ? component.comment : record.text;
6210
+ if (!text) return void 0;
6211
+ return {
6212
+ type: "pcb_fabrication_note_text",
6213
+ pcb_fabrication_note_text_id: `pcb_fabrication_note_text_altium_${recordIndex}`,
6214
+ pcb_component_id: getPcbComponentId(componentIndex),
6215
+ text,
6216
+ font: "tscircuit2024",
6217
+ font_size: milsToMillimeters(record.heightMils ?? 30),
6218
+ anchor_position: toMillimeterPoint(record.position),
6219
+ anchor_alignment: mapFabricationTextAnchor(record.justification),
6220
+ ccw_rotation: record.rotation,
6221
+ layer: component.side === "bottom" ? "bottom" : "top",
6222
+ color: FABRICATION_NOTE_COLOR
6223
+ };
6224
+ }
6225
+
6155
6226
  // lib/pcb/silkscreen/convertPcbSilkscreenText.ts
6156
6227
  function convertPcbSilkscreenText({
6157
6228
  context,
@@ -6159,11 +6230,13 @@ function convertPcbSilkscreenText({
6159
6230
  recordIndex
6160
6231
  }) {
6161
6232
  if (!record.position || !record.text) return void 0;
6162
- const { document, options } = context;
6233
+ const { document, layerMap, options } = context;
6163
6234
  const component = document.getComponentForRecord(record);
6164
6235
  const specialString = record.text.trim().toLowerCase();
6165
6236
  const componentText = specialString === ".designator" ? component?.designator : specialString === ".comment" ? component?.comment : record.text;
6166
- const text = resolvePcbProjectSpecialStrings({
6237
+ const text = resolvePcbTextSpecialStrings({
6238
+ layer: record.layer,
6239
+ layerMap,
6167
6240
  project: options.project,
6168
6241
  text: componentText ?? ""
6169
6242
  });
@@ -6664,7 +6737,7 @@ function convertPcbRecords(context) {
6664
6737
  const text = convertPcbSilkscreenText({ context, record, recordIndex });
6665
6738
  if (text) elements.push(text);
6666
6739
  } else {
6667
- const text = convertPcbCopperText({ layerMap, record, recordIndex });
6740
+ const text = convertPcbCopperText({ context, record, recordIndex });
6668
6741
  if (text) elements.push(text);
6669
6742
  }
6670
6743
  continue;