circuit-to-svg 0.0.14 → 0.0.16

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
@@ -66,10 +66,14 @@ function circuitJsonToPcbSvg(soup) {
66
66
  (0, import_transformation_matrix.scale)(scaleFactor, -scaleFactor)
67
67
  // Flip in y-direction
68
68
  );
69
- const svgElements = soup.map((item) => {
70
- const element = createSvgElement(item, transform);
71
- return element;
72
- }).filter((element) => element !== null);
69
+ const traceElements = soup.filter((item) => item.type === "pcb_trace").map((item) => createSvgElement(item, transform)).filter((element) => element !== null);
70
+ const holeElements = soup.filter((item) => item.type === "pcb_plated_hole").map((item) => createSvgElement(item, transform)).filter((element) => element !== null);
71
+ const silkscreenElements = soup.filter((item) => item.type === "pcb_silkscreen_path").map((item) => createPcbSilkscreenPath(item, transform)).filter((element) => element !== null);
72
+ const otherElements = soup.filter(
73
+ (item) => !["pcb_trace", "pcb_plated_hole", "pcb_silkscreen_path"].includes(
74
+ item.type
75
+ )
76
+ ).map((item) => createSvgElement(item, transform)).filter((element) => element !== null);
73
77
  let strokeWidth = String(0.05 * scaleFactor);
74
78
  for (const element of soup) {
75
79
  if ("stroke_width" in element) {
@@ -94,10 +98,14 @@ function circuitJsonToPcbSvg(soup) {
94
98
  type: "text",
95
99
  value: `
96
100
  .pcb-board { fill: #000; }
97
- .pcb-trace { stroke: #FF0000; stroke-width: 0.3; fill: none; }
98
- .pcb-hole { fill: #FF00FF; }
99
- .pcb-pad { fill: #FF0000; }
100
- .pcb-boundary { fill: none; stroke: #f2eda1; stroke-width: ${strokeWidth}; }
101
+ .pcb-trace { stroke: rgb(200, 52, 52); stroke-width: ${strokeWidth}; fill: none; }
102
+ .pcb-hole-outer { fill: rgb(200, 52, 52); }
103
+ .pcb-hole-inner { fill: rgb(255, 38, 226); }
104
+ .pcb-pad { fill: rgb(200, 52, 52); }
105
+ .pcb-boundary { fill: none; stroke: #fff; stroke-width: 0.3; }
106
+ .pcb-silkscreen { fill: none; }
107
+ .pcb-silkscreen-top { stroke: #f2eda1; }
108
+ .pcb-silkscreen-bottom { stroke: #f2eda1; }
101
109
  `
102
110
  }
103
111
  ]
@@ -113,8 +121,31 @@ function circuitJsonToPcbSvg(soup) {
113
121
  height: svgHeight.toString()
114
122
  }
115
123
  },
116
- ...svgElements,
117
- createPcbBoundary(transform, minX, minY, maxX, maxY, paths)
124
+ createPcbBoundary(transform, minX, minY, maxX, maxY),
125
+ {
126
+ name: "g",
127
+ type: "element",
128
+ attributes: { id: "other-elements" },
129
+ children: otherElements
130
+ },
131
+ {
132
+ name: "g",
133
+ type: "element",
134
+ attributes: { id: "silkscreen" },
135
+ children: silkscreenElements
136
+ },
137
+ {
138
+ name: "g",
139
+ type: "element",
140
+ attributes: { id: "traces" },
141
+ children: traceElements
142
+ },
143
+ {
144
+ name: "g",
145
+ type: "element",
146
+ attributes: { id: "holes" },
147
+ children: holeElements
148
+ }
118
149
  ].filter((child) => child !== null)
119
150
  };
120
151
  try {
@@ -192,16 +223,33 @@ function createPcbComponent(component, transform) {
192
223
  }
193
224
  function createPcbHole(hole, transform) {
194
225
  const [x, y] = (0, import_transformation_matrix.applyToPoint)(transform, [hole.x, hole.y]);
195
- const scaledRadius = hole.outer_diameter / 2 * Math.abs(transform.a);
226
+ const scaledOuterRadius = hole.outer_diameter / 2 * Math.abs(transform.a);
227
+ const scaledInnerRadius = hole.hole_diameter / 2 * Math.abs(transform.a);
196
228
  return {
197
- name: "circle",
229
+ name: "g",
198
230
  type: "element",
199
- attributes: {
200
- class: "pcb-hole",
201
- cx: x.toString(),
202
- cy: y.toString(),
203
- r: scaledRadius.toString()
204
- }
231
+ children: [
232
+ {
233
+ name: "circle",
234
+ type: "element",
235
+ attributes: {
236
+ class: "pcb-hole-outer",
237
+ cx: x.toString(),
238
+ cy: y.toString(),
239
+ r: scaledOuterRadius.toString()
240
+ }
241
+ },
242
+ {
243
+ name: "circle",
244
+ type: "element",
245
+ attributes: {
246
+ class: "pcb-hole-inner",
247
+ cx: x.toString(),
248
+ cy: y.toString(),
249
+ r: scaledInnerRadius.toString()
250
+ }
251
+ }
252
+ ]
205
253
  };
206
254
  }
207
255
  function createPcbSMTPad(pad, transform) {
@@ -235,31 +283,45 @@ function createPcbTrace(trace, transform) {
235
283
  }
236
284
  };
237
285
  }
238
- function createPcbBoundary(transform, minX, minY, maxX, maxY, routes) {
286
+ function createPcbSilkscreenPath(silkscreenPath, transform) {
287
+ if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return null;
288
+ let path = silkscreenPath.route.map((point, index) => {
289
+ const [x, y] = (0, import_transformation_matrix.applyToPoint)(transform, [point.x, point.y]);
290
+ return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
291
+ }).join(" ");
292
+ const firstPoint = silkscreenPath.route[0];
293
+ const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1];
294
+ if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {
295
+ path += " Z";
296
+ }
297
+ return {
298
+ name: "path",
299
+ type: "element",
300
+ attributes: {
301
+ class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`,
302
+ d: path,
303
+ "stroke-width": (silkscreenPath.stroke_width * Math.abs(transform.a)).toString(),
304
+ "data-pcb-component-id": silkscreenPath.pcb_component_id,
305
+ "data-pcb-silkscreen-path-id": silkscreenPath.pcb_silkscreen_path_id
306
+ }
307
+ };
308
+ }
309
+ function createPcbBoundary(transform, minX, minY, maxX, maxY) {
239
310
  const [x1, y1] = (0, import_transformation_matrix.applyToPoint)(transform, [minX, minY]);
240
311
  const [x2, y2] = (0, import_transformation_matrix.applyToPoint)(transform, [maxX, maxY]);
241
312
  const width = Math.abs(x2 - x1);
242
313
  const height = Math.abs(y2 - y1);
243
314
  const x = Math.min(x1, x2);
244
315
  const y = Math.min(y1, y2);
245
- const isPath = Array.isArray(routes) && routes.length > 0;
246
- const stringRoutes = routes?.map((route) => {
247
- return route.map((point, index) => {
248
- const [x3, y3] = (0, import_transformation_matrix.applyToPoint)(transform, [point.x, point.y]);
249
- return index === 0 ? `M ${x3} ${y3}` : `L ${x3} ${y3}`;
250
- }).join(" ");
251
- });
252
316
  return {
253
- name: isPath ? "path" : "rect",
317
+ name: "rect",
254
318
  type: "element",
255
319
  attributes: {
256
320
  class: "pcb-boundary",
257
- ...isPath ? { d: stringRoutes } : {
258
- x: x.toString(),
259
- y: y.toString(),
260
- width: width.toString(),
261
- height: height.toString()
262
- }
321
+ x: x.toString(),
322
+ y: y.toString(),
323
+ width: width.toString(),
324
+ height: height.toString()
263
325
  }
264
326
  };
265
327
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/lib/circuit-to-pcb-svg.ts","../src/lib/circuit-to-schematic-svg.ts"],"sourcesContent":["export * from \"./lib\";\n\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { stringify, type INode } from \"svgson\"\nimport { applyToPoint, compose, scale, translate } from \"transformation-matrix\"\n\ninterface SvgObject {\n name: string\n type: \"element\" | \"text\"\n attributes?: { [key: string]: string }\n children?: SvgObject[]\n value?: string\n}\n\nfunction circuitJsonToPcbSvg(soup: AnySoupElement[]): string {\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n // Process all elements to determine bounds\n for (const item of soup) {\n if (\"center\" in item && \"width\" in item && \"height\" in item) {\n updateBounds(item.center, item.width, item.height)\n } else if (\"x\" in item && \"y\" in item) {\n updateBounds({ x: item.x, y: item.y }, 0, 0)\n } else if (\"route\" in item) {\n updateTraceBounds(item.route)\n }\n }\n\n const padding = 1 // Reduced padding for tighter boundary\n const circuitWidth = maxX - minX + 2 * padding\n const circuitHeight = maxY - minY + 2 * padding\n\n const svgWidth = 800\n const svgHeight = 600\n const paths: PointObjectNotation[][] = []\n for (const item of soup) {\n if (\"route\" in item && item.route !== undefined) {\n paths.push(item.route as PointObjectNotation[])\n }\n }\n\n // Calculate scale factor to fit the circuit within the SVG, maintaining aspect ratio\n const scaleX = svgWidth / circuitWidth\n const scaleY = svgHeight / circuitHeight\n const scaleFactor = Math.min(scaleX, scaleY)\n\n // Calculate centering offsets\n const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2\n const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2\n\n const transform = compose(\n translate(\n offsetX - minX * scaleFactor + padding * scaleFactor,\n svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor,\n ),\n scale(scaleFactor, -scaleFactor), // Flip in y-direction\n )\n\n const svgElements = soup\n .map((item) => {\n const element = createSvgElement(item, transform)\n return element\n })\n .filter((element) => element !== null)\n\n let strokeWidth = String(0.05 * scaleFactor)\n\n for (const element of soup) {\n if (\"stroke_width\" in element) {\n strokeWidth = String(scaleFactor * element.stroke_width)\n break\n }\n }\n const svgObject: SvgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .pcb-board { fill: #000; }\n .pcb-trace { stroke: #FF0000; stroke-width: 0.3; fill: none; }\n .pcb-hole { fill: #FF00FF; }\n .pcb-pad { fill: #FF0000; }\n .pcb-boundary { fill: none; stroke: #f2eda1; stroke-width: ${strokeWidth}; }\n `,\n },\n ],\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-board\",\n x: \"0\",\n y: \"0\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n },\n ...svgElements,\n createPcbBoundary(transform, minX, minY, maxX, maxY, paths),\n ].filter((child) => child !== null),\n }\n\n try {\n return stringify(svgObject as INode)\n } catch (error) {\n console.error(\"Error stringifying SVG object:\", error)\n throw error\n }\n\n function updateBounds(center: any, width: any, height: any) {\n const halfWidth = width / 2\n const halfHeight = height / 2\n minX = Math.min(minX, center.x - halfWidth)\n minY = Math.min(minY, center.y - halfHeight)\n maxX = Math.max(maxX, center.x + halfWidth)\n maxY = Math.max(maxY, center.y + halfHeight)\n }\n\n function updateTraceBounds(route: any[]) {\n for (const point of route) {\n minX = Math.min(minX, point.x)\n minY = Math.min(minY, point.y)\n maxX = Math.max(maxX, point.x)\n maxY = Math.max(maxY, point.y)\n }\n }\n}\n\nfunction createSvgElement(item: AnySoupElement, transform: any): any {\n switch (item.type) {\n case \"pcb_component\":\n return createPcbComponent(item, transform)\n case \"pcb_trace\":\n return createPcbTrace(item, transform)\n case \"pcb_plated_hole\":\n return createPcbHole(item, transform)\n case \"pcb_smtpad\":\n return createPcbSMTPad(item, transform)\n default:\n return null\n }\n}\n\nfunction createPcbComponent(component: any, transform: any): any {\n const { center, width, height, rotation = 0 } = component\n const [x, y] = applyToPoint(transform, [center.x, center.y])\n const scaledWidth = width * Math.abs(transform.a)\n const scaledHeight = height * Math.abs(transform.d)\n const transformStr = `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: transformStr },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component-outline\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n ],\n }\n}\n\nfunction createPcbHole(hole: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [hole.x, hole.y])\n const scaledRadius = (hole.outer_diameter / 2) * Math.abs(transform.a)\n return {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledRadius.toString(),\n },\n }\n}\n\nfunction createPcbSMTPad(pad: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [pad.x, pad.y])\n const width = pad.width * Math.abs(transform.a)\n const height = pad.height * Math.abs(transform.d)\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-pad\",\n x: (x - width / 2).toString(),\n y: (y - height / 2).toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nfunction createPcbTrace(trace: any, transform: any): any {\n if (!trace.route || !Array.isArray(trace.route)) return null\n const path = trace.route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n return {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"pcb-trace\",\n d: path,\n },\n }\n}\n\nfunction createPcbBoundary(\n transform: any,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n routes?: { x: number; y: number }[][],\n): any {\n const [x1, y1] = applyToPoint(transform, [minX, minY])\n const [x2, y2] = applyToPoint(transform, [maxX, maxY])\n const width = Math.abs(x2 - x1)\n const height = Math.abs(y2 - y1)\n const x = Math.min(x1, x2)\n const y = Math.min(y1, y2)\n const isPath = Array.isArray(routes) && routes.length > 0\n const stringRoutes = routes?.map((route) => {\n return route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n })\n\n return {\n name: isPath ? \"path\" : \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-boundary\",\n ...(isPath\n ? { d: stringRoutes }\n : {\n x: x.toString(),\n y: y.toString(),\n width: width.toString(),\n height: height.toString(),\n }),\n },\n }\n}\n\nexport { circuitJsonToPcbSvg }\n","import type { AnySoupElement } from \"@tscircuit/soup\";\nimport { getSvg, symbols } from \"schematic-symbols\";\nimport { parseSync, stringify } from \"svgson\";\n\nfunction circuitJsonToSchematicSvg(soup: AnySoupElement[]): string {\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n const portSize = 0.2;\n const portPositions = new Map();\n\n // First pass: find the bounds and collect port positions\n for (const item of soup) {\n if (item.type === \"schematic_component\") {\n updateBounds(item.center, item.size, item.rotation || 0);\n } else if (item.type === \"schematic_port\") {\n updateBounds(item.center, { width: portSize, height: portSize }, 0);\n portPositions.set(item.schematic_port_id, item.center);\n } else if (item.type === \"schematic_text\") {\n updateBounds(item.position, { width: 0, height: 0 }, 0);\n }\n }\n\n const height = maxY - minY;\n const flipY = (y: number) => height - (y - minY) + minY;\n\n const svgChildren: any[] = [];\n\n // Process components\n const componentMap = new Map();\n for (const component of soup.filter(\n (item) => item.type === \"schematic_component\"\n )) {\n const flippedCenter = {\n x: component.center.x,\n y: flipY(component.center.y),\n };\n const svg = createSchematicComponent(\n flippedCenter,\n component.size,\n component.rotation || 0,\n component.symbol_name\n );\n svgChildren.push(svg);\n componentMap.set(component.schematic_component_id, component);\n }\n\n // Process ports and add lines to component edges\n for (const port of soup.filter((item) => item.type === \"schematic_port\")) {\n const flippedCenter = { x: port.center.x, y: flipY(port.center.y) };\n const svg = createSchematicPort(flippedCenter);\n svgChildren.push(svg);\n\n const component = componentMap.get(port.schematic_component_id);\n if (component) {\n const line = createPortToComponentLine(\n flippedCenter,\n component,\n port.facing_direction || \"right\"\n );\n svgChildren.push(line);\n }\n }\n\n // Process schematic traces\n for (const trace of soup.filter((item) => item.type === \"schematic_trace\")) {\n const svg = createSchematicTrace(trace, flipY, portPositions);\n if (svg) svgChildren.push(svg);\n }\n\n // Process text\n for (const text of soup.filter((item) => item.type === \"schematic_text\")) {\n const flippedPosition = { x: text.position.x, y: flipY(text.position.y) };\n const svg = createSchematicText(text, flippedPosition);\n svgChildren.push(svg);\n }\n\n const padding = 1;\n const width = maxX - minX + 2 * padding;\n const viewBox = `${minX - padding} ${minY - padding} ${width} ${height + 2 * padding}`;\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox,\n width: \"1200\",\n height: \"600\",\n style: \"background-color: #fff;\",\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .component { fill: none; stroke: red; stroke-width: 0.03; }\n .component-pin { fill: none; stroke: red; stroke-width: 0.03; }\n .trace { stroke: green; stroke-width: 0.03; fill: none; }\n .text { font-family: Arial, sans-serif; font-size: 0.2px; }\n .port { fill: none; stroke: blue; stroke-width: 0.03; }\n `,\n },\n ],\n },\n ...svgChildren,\n ],\n };\n\n return stringify({ value: \"\", ...svgObject });\n\n function updateBounds(center: any, size: any, rotation: number) {\n const corners = [\n { x: -size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: size.height / 2 },\n { x: -size.width / 2, y: size.height / 2 },\n ];\n\n for (const corner of corners) {\n const rotatedX =\n corner.x * Math.cos(rotation) -\n corner.y * Math.sin(rotation) +\n center.x;\n const rotatedY =\n corner.x * Math.sin(rotation) +\n corner.y * Math.cos(rotation) +\n center.y;\n minX = Math.min(minX, rotatedX);\n minY = Math.min(minY, rotatedY);\n maxX = Math.max(maxX, rotatedX);\n maxY = Math.max(maxY, rotatedY);\n }\n }\n}\n\nfunction createSchematicComponent(\n center: { x: number; y: number },\n size: { width: number; height: number },\n rotation: number,\n symbolName?: string\n): any {\n const transform = `translate(${center.x}, ${center.y}) rotate(${(rotation * 180) / Math.PI})`;\n\n if (symbolName) {\n const symbol = (symbols as any)[symbolName];\n const paths = symbol.primitives.filter((p: any) => p.type === \"path\");\n const updatedSymbol = {\n ...symbol,\n primitives: paths,\n };\n const svg = parseSync(\n getSvg(updatedSymbol, {\n width: size.width,\n height: size.height,\n })\n );\n\n // Filter out non-path elements and modify path colors\n const pathElements = svg.children\n .filter(\n (child: any) =>\n child.name === \"path\" && child.attributes.fill !== \"green\"\n )\n .map((path: any) => {\n const currentStrokeWidth = Number.parseFloat(\n path.attributes[\"stroke-width\"] || \"0.02\"\n );\n const newStrokeWidth = (currentStrokeWidth * 1.5).toString();\n\n return {\n ...path,\n attributes: {\n ...path.attributes,\n stroke:\n path.attributes.stroke === \"black\"\n ? \"red\"\n : path.attributes.stroke,\n \"stroke-width\": newStrokeWidth,\n },\n };\n });\n\n // Check if viewBox attribute exists\n const viewBoxAttr = svg.attributes.viewBox;\n if (typeof viewBoxAttr === \"undefined\") {\n throw new Error(\"SVG does not have a viewBox attribute.\");\n }\n\n // Extract viewBox values\n const viewBox = viewBoxAttr.split(\" \").map(Number);\n if (viewBox.length < 4) {\n throw new Error(\"Invalid viewBox attribute.\");\n }\n const [minX, minY, width = 0, height = 0] = viewBox;\n\n // Calculate scale factors\n const scaleX = size.width / (width || 1);\n const scaleY = size.height / (height || 1);\n\n const scale = Math.min(scaleX, scaleY);\n\n // Adjust transformation to include scaling and centering\n const adjustedTransform = `${transform} scale(${scale}) translate(${-(minX ?? 0) - width / 2}, ${-(minY ?? 0) - height / 2})`;\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: adjustedTransform },\n children: pathElements,\n };\n }\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"component\",\n x: (-size.width / 2).toString(),\n y: (-size.height / 2).toString(),\n width: size.width.toString(),\n height: size.height.toString(),\n },\n },\n ],\n };\n}\n\nfunction createSchematicPort(center: { x: number; y: number }): any {\n const portSize = 0.2;\n const x = center.x - portSize / 2;\n const y = center.y - portSize / 2;\n\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"port\",\n x: x.toString(),\n y: y.toString(),\n width: portSize.toString(),\n height: portSize.toString(),\n },\n };\n}\n\nfunction createPortToComponentLine(\n portCenter: { x: number; y: number },\n component: any,\n facingDirection: string\n): any {\n const componentCenter = { x: component.center.x, y: portCenter.y };\n const halfWidth = component.size.width / 2;\n const halfHeight = component.size.height / 2;\n\n let endX = portCenter.x;\n let endY = portCenter.y;\n\n switch (facingDirection) {\n case \"left\":\n endX = componentCenter.x - halfWidth;\n break;\n case \"right\":\n endX = componentCenter.x + halfWidth;\n break;\n case \"up\":\n endY = componentCenter.y - halfHeight;\n break;\n case \"down\":\n endY = componentCenter.y + halfHeight;\n break;\n }\n\n return {\n name: \"line\",\n type: \"element\",\n attributes: {\n class: \"component-pin\",\n x1: portCenter.x.toString(),\n y1: portCenter.y.toString(),\n x2: endX.toString(),\n y2: endY.toString(),\n },\n };\n}\n\nfunction createSchematicTrace(\n trace: any,\n flipY: (y: number) => number,\n portPositions: Map<string, { x: number; y: number }>\n): any {\n const edges = trace.edges;\n if (edges.length === 0) return null;\n\n let path = \"\";\n\n // Process all edges\n edges.forEach((edge: any, index: number) => {\n const fromPoint =\n edge.from.ti !== undefined ? portPositions.get(edge.from.ti) : edge.from;\n const toPoint =\n edge.to.ti !== undefined ? portPositions.get(edge.to.ti) : edge.to;\n\n if (!fromPoint || !toPoint) {\n return;\n }\n\n const fromCoord = `${fromPoint.x} ${flipY(fromPoint.y)}`;\n const toCoord = `${toPoint.x} ${flipY(toPoint.y)}`;\n\n if (index === 0) {\n path += `M ${fromCoord} L ${toCoord}`;\n } else {\n path += ` L ${toCoord}`;\n }\n });\n\n // Handle connection to final port if needed\n if (trace.to_schematic_port_id) {\n const finalPort = portPositions.get(trace.to_schematic_port_id);\n if (finalPort) {\n const lastFromPoint = path.split(\"M\")[1]?.split(\"L\")[0];\n const lastEdge = edges[edges.length - 1];\n const lastPoint =\n lastEdge.to.ti !== undefined\n ? portPositions.get(lastEdge.to.ti)\n : lastEdge.to;\n if (lastPoint.x !== finalPort.x || lastPoint.y !== finalPort.y) {\n const finalCoord = `${finalPort.x} ${flipY(finalPort.y)}`;\n path += ` M ${lastFromPoint} L ${finalCoord}`;\n }\n }\n }\n\n return path\n ? {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"trace\",\n d: path,\n },\n }\n : null;\n}\n\nfunction createSchematicText(\n text: any,\n position: { x: number; y: number }\n): any {\n return {\n name: \"text\",\n type: \"element\",\n attributes: {\n class: \"text\",\n x: position.x.toString(),\n y: position.y.toString(),\n \"text-anchor\": getTextAnchor(text.anchor),\n \"dominant-baseline\": \"middle\",\n },\n children: [\n {\n type: \"text\",\n value: text.text ? text.text : \"\",\n },\n ],\n };\n}\n\nfunction getTextAnchor(anchor: string): string {\n switch (anchor) {\n case \"left\":\n return \"start\";\n case \"right\":\n return \"end\";\n default:\n return \"middle\";\n }\n}\n\nexport { circuitJsonToSchematicSvg };\n"],"mappings":"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","names":["x","y","import_svgson","scale"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/circuit-to-pcb-svg.ts","../src/lib/circuit-to-schematic-svg.ts"],"sourcesContent":["export * from \"./lib\";\n\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { type INode, stringify } from \"svgson\"\nimport { applyToPoint, compose, scale, translate } from \"transformation-matrix\"\n\ninterface SvgObject {\n name: string\n type: \"element\" | \"text\"\n attributes?: { [key: string]: string }\n children?: SvgObject[]\n value?: string\n}\n\ninterface PointObjectNotation {\n x: number\n y: number\n}\n\nfunction circuitJsonToPcbSvg(soup: AnySoupElement[]): string {\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n // Process all elements to determine bounds\n for (const item of soup) {\n if (\"center\" in item && \"width\" in item && \"height\" in item) {\n updateBounds(item.center, item.width, item.height)\n } else if (\"x\" in item && \"y\" in item) {\n updateBounds({ x: item.x, y: item.y }, 0, 0)\n } else if (\"route\" in item) {\n updateTraceBounds(item.route)\n }\n }\n\n const padding = 1 // Reduced padding for tighter boundary\n const circuitWidth = maxX - minX + 2 * padding\n const circuitHeight = maxY - minY + 2 * padding\n\n const svgWidth = 800\n const svgHeight = 600\n const paths: PointObjectNotation[][] = []\n for (const item of soup) {\n if (\"route\" in item && item.route !== undefined) {\n paths.push(item.route as PointObjectNotation[])\n }\n }\n\n // Calculate scale factor to fit the circuit within the SVG, maintaining aspect ratio\n const scaleX = svgWidth / circuitWidth\n const scaleY = svgHeight / circuitHeight\n const scaleFactor = Math.min(scaleX, scaleY)\n\n // Calculate centering offsets\n const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2\n const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2\n\n const transform = compose(\n translate(\n offsetX - minX * scaleFactor + padding * scaleFactor,\n svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor,\n ),\n scale(scaleFactor, -scaleFactor), // Flip in y-direction\n )\n\n const traceElements = soup\n .filter((item) => item.type === \"pcb_trace\")\n .map((item) => createSvgElement(item, transform))\n .filter((element) => element !== null)\n\n const holeElements = soup\n .filter((item) => item.type === \"pcb_plated_hole\")\n .map((item) => createSvgElement(item, transform))\n .filter((element) => element !== null)\n\n const silkscreenElements = soup\n .filter((item) => item.type === \"pcb_silkscreen_path\")\n .map((item) => createPcbSilkscreenPath(item, transform))\n .filter((element) => element !== null)\n\n const otherElements = soup\n .filter(\n (item) =>\n ![\"pcb_trace\", \"pcb_plated_hole\", \"pcb_silkscreen_path\"].includes(\n item.type,\n ),\n )\n .map((item) => createSvgElement(item, transform))\n .filter((element) => element !== null)\n\n let strokeWidth = String(0.05 * scaleFactor)\n\n for (const element of soup) {\n if (\"stroke_width\" in element) {\n strokeWidth = String(scaleFactor * element.stroke_width)\n break\n }\n }\n\n const svgObject: SvgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .pcb-board { fill: #000; }\n .pcb-trace { stroke: rgb(200, 52, 52); stroke-width: ${strokeWidth}; fill: none; }\n .pcb-hole-outer { fill: rgb(200, 52, 52); }\n .pcb-hole-inner { fill: rgb(255, 38, 226); }\n .pcb-pad { fill: rgb(200, 52, 52); }\n .pcb-boundary { fill: none; stroke: #fff; stroke-width: 0.3; }\n .pcb-silkscreen { fill: none; }\n .pcb-silkscreen-top { stroke: #f2eda1; }\n .pcb-silkscreen-bottom { stroke: #f2eda1; }\n `,\n },\n ],\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-board\",\n x: \"0\",\n y: \"0\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n },\n createPcbBoundary(transform, minX, minY, maxX, maxY),\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"other-elements\" },\n children: otherElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"silkscreen\" },\n children: silkscreenElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"traces\" },\n children: traceElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"holes\" },\n children: holeElements,\n },\n ].filter((child) => child !== null),\n }\n\n try {\n return stringify(svgObject as INode)\n } catch (error) {\n console.error(\"Error stringifying SVG object:\", error)\n throw error\n }\n\n function updateBounds(center: any, width: any, height: any) {\n const halfWidth = width / 2\n const halfHeight = height / 2\n minX = Math.min(minX, center.x - halfWidth)\n minY = Math.min(minY, center.y - halfHeight)\n maxX = Math.max(maxX, center.x + halfWidth)\n maxY = Math.max(maxY, center.y + halfHeight)\n }\n\n function updateTraceBounds(route: any[]) {\n for (const point of route) {\n minX = Math.min(minX, point.x)\n minY = Math.min(minY, point.y)\n maxX = Math.max(maxX, point.x)\n maxY = Math.max(maxY, point.y)\n }\n }\n}\n\nfunction createSvgElement(item: AnySoupElement, transform: any): any {\n switch (item.type) {\n case \"pcb_component\":\n return createPcbComponent(item, transform)\n case \"pcb_trace\":\n return createPcbTrace(item, transform)\n case \"pcb_plated_hole\":\n return createPcbHole(item, transform)\n case \"pcb_smtpad\":\n return createPcbSMTPad(item, transform)\n default:\n return null\n }\n}\n\nfunction createPcbComponent(component: any, transform: any): any {\n const { center, width, height, rotation = 0 } = component\n const [x, y] = applyToPoint(transform, [center.x, center.y])\n const scaledWidth = width * Math.abs(transform.a)\n const scaledHeight = height * Math.abs(transform.d)\n const transformStr = `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: transformStr },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component-outline\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n ],\n }\n}\n\nfunction createPcbHole(hole: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [hole.x, hole.y])\n const scaledOuterRadius = (hole.outer_diameter / 2) * Math.abs(transform.a)\n const scaledInnerRadius = (hole.hole_diameter / 2) * Math.abs(transform.a)\n return {\n name: \"g\",\n type: \"element\",\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-outer\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledOuterRadius.toString(),\n },\n },\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-inner\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledInnerRadius.toString(),\n },\n },\n ],\n }\n}\n\nfunction createPcbSMTPad(pad: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [pad.x, pad.y])\n const width = pad.width * Math.abs(transform.a)\n const height = pad.height * Math.abs(transform.d)\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-pad\",\n x: (x - width / 2).toString(),\n y: (y - height / 2).toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nfunction createPcbTrace(trace: any, transform: any): any {\n if (!trace.route || !Array.isArray(trace.route)) return null\n const path = trace.route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n return {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"pcb-trace\",\n d: path,\n },\n }\n}\n\nfunction createPcbSilkscreenPath(silkscreenPath: any, transform: any): any {\n if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return null\n\n let path = silkscreenPath.route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n\n // Close the path if it's not already closed\n const firstPoint = silkscreenPath.route[0]\n const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1]\n if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {\n path += \" Z\"\n }\n\n return {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`,\n d: path,\n \"stroke-width\": (\n silkscreenPath.stroke_width * Math.abs(transform.a)\n ).toString(),\n \"data-pcb-component-id\": silkscreenPath.pcb_component_id,\n \"data-pcb-silkscreen-path-id\": silkscreenPath.pcb_silkscreen_path_id,\n },\n }\n}\n\nfunction createPcbBoundary(\n transform: any,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n): any {\n const [x1, y1] = applyToPoint(transform, [minX, minY])\n const [x2, y2] = applyToPoint(transform, [maxX, maxY])\n const width = Math.abs(x2 - x1)\n const height = Math.abs(y2 - y1)\n const x = Math.min(x1, x2)\n const y = Math.min(y1, y2)\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-boundary\",\n x: x.toString(),\n y: y.toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nexport { circuitJsonToPcbSvg }\n","import type { AnySoupElement } from \"@tscircuit/soup\";\nimport { getSvg, symbols } from \"schematic-symbols\";\nimport { parseSync, stringify } from \"svgson\";\n\nfunction circuitJsonToSchematicSvg(soup: AnySoupElement[]): string {\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n const portSize = 0.2;\n const portPositions = new Map();\n\n // First pass: find the bounds and collect port positions\n for (const item of soup) {\n if (item.type === \"schematic_component\") {\n updateBounds(item.center, item.size, item.rotation || 0);\n } else if (item.type === \"schematic_port\") {\n updateBounds(item.center, { width: portSize, height: portSize }, 0);\n portPositions.set(item.schematic_port_id, item.center);\n } else if (item.type === \"schematic_text\") {\n updateBounds(item.position, { width: 0, height: 0 }, 0);\n }\n }\n\n const height = maxY - minY;\n const flipY = (y: number) => height - (y - minY) + minY;\n\n const svgChildren: any[] = [];\n\n // Process components\n const componentMap = new Map();\n for (const component of soup.filter(\n (item) => item.type === \"schematic_component\"\n )) {\n const flippedCenter = {\n x: component.center.x,\n y: flipY(component.center.y),\n };\n const svg = createSchematicComponent(\n flippedCenter,\n component.size,\n component.rotation || 0,\n component.symbol_name\n );\n svgChildren.push(svg);\n componentMap.set(component.schematic_component_id, component);\n }\n\n // Process ports and add lines to component edges\n for (const port of soup.filter((item) => item.type === \"schematic_port\")) {\n const flippedCenter = { x: port.center.x, y: flipY(port.center.y) };\n const svg = createSchematicPort(flippedCenter);\n svgChildren.push(svg);\n\n const component = componentMap.get(port.schematic_component_id);\n if (component) {\n const line = createPortToComponentLine(\n flippedCenter,\n component,\n port.facing_direction || \"right\"\n );\n svgChildren.push(line);\n }\n }\n\n // Process schematic traces\n for (const trace of soup.filter((item) => item.type === \"schematic_trace\")) {\n const svg = createSchematicTrace(trace, flipY, portPositions);\n if (svg) svgChildren.push(svg);\n }\n\n // Process text\n for (const text of soup.filter((item) => item.type === \"schematic_text\")) {\n const flippedPosition = { x: text.position.x, y: flipY(text.position.y) };\n const svg = createSchematicText(text, flippedPosition);\n svgChildren.push(svg);\n }\n\n const padding = 1;\n const width = maxX - minX + 2 * padding;\n const viewBox = `${minX - padding} ${minY - padding} ${width} ${height + 2 * padding}`;\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox,\n width: \"1200\",\n height: \"600\",\n style: \"background-color: #fff;\",\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .component { fill: none; stroke: red; stroke-width: 0.03; }\n .component-pin { fill: none; stroke: red; stroke-width: 0.03; }\n .trace { stroke: green; stroke-width: 0.03; fill: none; }\n .text { font-family: Arial, sans-serif; font-size: 0.2px; }\n .port { fill: none; stroke: blue; stroke-width: 0.03; }\n `,\n },\n ],\n },\n ...svgChildren,\n ],\n };\n\n return stringify({ value: \"\", ...svgObject });\n\n function updateBounds(center: any, size: any, rotation: number) {\n const corners = [\n { x: -size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: size.height / 2 },\n { x: -size.width / 2, y: size.height / 2 },\n ];\n\n for (const corner of corners) {\n const rotatedX =\n corner.x * Math.cos(rotation) -\n corner.y * Math.sin(rotation) +\n center.x;\n const rotatedY =\n corner.x * Math.sin(rotation) +\n corner.y * Math.cos(rotation) +\n center.y;\n minX = Math.min(minX, rotatedX);\n minY = Math.min(minY, rotatedY);\n maxX = Math.max(maxX, rotatedX);\n maxY = Math.max(maxY, rotatedY);\n }\n }\n}\n\nfunction createSchematicComponent(\n center: { x: number; y: number },\n size: { width: number; height: number },\n rotation: number,\n symbolName?: string\n): any {\n const transform = `translate(${center.x}, ${center.y}) rotate(${(rotation * 180) / Math.PI})`;\n\n if (symbolName) {\n const symbol = (symbols as any)[symbolName];\n const paths = symbol.primitives.filter((p: any) => p.type === \"path\");\n const updatedSymbol = {\n ...symbol,\n primitives: paths,\n };\n const svg = parseSync(\n getSvg(updatedSymbol, {\n width: size.width,\n height: size.height,\n })\n );\n\n // Filter out non-path elements and modify path colors\n const pathElements = svg.children\n .filter(\n (child: any) =>\n child.name === \"path\" && child.attributes.fill !== \"green\"\n )\n .map((path: any) => {\n const currentStrokeWidth = Number.parseFloat(\n path.attributes[\"stroke-width\"] || \"0.02\"\n );\n const newStrokeWidth = (currentStrokeWidth * 1.5).toString();\n\n return {\n ...path,\n attributes: {\n ...path.attributes,\n stroke:\n path.attributes.stroke === \"black\"\n ? \"red\"\n : path.attributes.stroke,\n \"stroke-width\": newStrokeWidth,\n },\n };\n });\n\n // Check if viewBox attribute exists\n const viewBoxAttr = svg.attributes.viewBox;\n if (typeof viewBoxAttr === \"undefined\") {\n throw new Error(\"SVG does not have a viewBox attribute.\");\n }\n\n // Extract viewBox values\n const viewBox = viewBoxAttr.split(\" \").map(Number);\n if (viewBox.length < 4) {\n throw new Error(\"Invalid viewBox attribute.\");\n }\n const [minX, minY, width = 0, height = 0] = viewBox;\n\n // Calculate scale factors\n const scaleX = size.width / (width || 1);\n const scaleY = size.height / (height || 1);\n\n const scale = Math.min(scaleX, scaleY);\n\n // Adjust transformation to include scaling and centering\n const adjustedTransform = `${transform} scale(${scale}) translate(${-(minX ?? 0) - width / 2}, ${-(minY ?? 0) - height / 2})`;\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: adjustedTransform },\n children: pathElements,\n };\n }\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"component\",\n x: (-size.width / 2).toString(),\n y: (-size.height / 2).toString(),\n width: size.width.toString(),\n height: size.height.toString(),\n },\n },\n ],\n };\n}\n\nfunction createSchematicPort(center: { x: number; y: number }): any {\n const portSize = 0.2;\n const x = center.x - portSize / 2;\n const y = center.y - portSize / 2;\n\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"port\",\n x: x.toString(),\n y: y.toString(),\n width: portSize.toString(),\n height: portSize.toString(),\n },\n };\n}\n\nfunction createPortToComponentLine(\n portCenter: { x: number; y: number },\n component: any,\n facingDirection: string\n): any {\n const componentCenter = { x: component.center.x, y: portCenter.y };\n const halfWidth = component.size.width / 2;\n const halfHeight = component.size.height / 2;\n\n let endX = portCenter.x;\n let endY = portCenter.y;\n\n switch (facingDirection) {\n case \"left\":\n endX = componentCenter.x - halfWidth;\n break;\n case \"right\":\n endX = componentCenter.x + halfWidth;\n break;\n case \"up\":\n endY = componentCenter.y - halfHeight;\n break;\n case \"down\":\n endY = componentCenter.y + halfHeight;\n break;\n }\n\n return {\n name: \"line\",\n type: \"element\",\n attributes: {\n class: \"component-pin\",\n x1: portCenter.x.toString(),\n y1: portCenter.y.toString(),\n x2: endX.toString(),\n y2: endY.toString(),\n },\n };\n}\n\nfunction createSchematicTrace(\n trace: any,\n flipY: (y: number) => number,\n portPositions: Map<string, { x: number; y: number }>\n): any {\n const edges = trace.edges;\n if (edges.length === 0) return null;\n\n let path = \"\";\n\n // Process all edges\n edges.forEach((edge: any, index: number) => {\n const fromPoint =\n edge.from.ti !== undefined ? portPositions.get(edge.from.ti) : edge.from;\n const toPoint =\n edge.to.ti !== undefined ? portPositions.get(edge.to.ti) : edge.to;\n\n if (!fromPoint || !toPoint) {\n return;\n }\n\n const fromCoord = `${fromPoint.x} ${flipY(fromPoint.y)}`;\n const toCoord = `${toPoint.x} ${flipY(toPoint.y)}`;\n\n if (index === 0) {\n path += `M ${fromCoord} L ${toCoord}`;\n } else {\n path += ` L ${toCoord}`;\n }\n });\n\n // Handle connection to final port if needed\n if (trace.to_schematic_port_id) {\n const finalPort = portPositions.get(trace.to_schematic_port_id);\n if (finalPort) {\n const lastFromPoint = path.split(\"M\")[1]?.split(\"L\")[0];\n const lastEdge = edges[edges.length - 1];\n const lastPoint =\n lastEdge.to.ti !== undefined\n ? portPositions.get(lastEdge.to.ti)\n : lastEdge.to;\n if (lastPoint.x !== finalPort.x || lastPoint.y !== finalPort.y) {\n const finalCoord = `${finalPort.x} ${flipY(finalPort.y)}`;\n path += ` M ${lastFromPoint} L ${finalCoord}`;\n }\n }\n }\n\n return path\n ? {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"trace\",\n d: path,\n },\n }\n : null;\n}\n\nfunction createSchematicText(\n text: any,\n position: { x: number; y: number }\n): any {\n return {\n name: \"text\",\n type: \"element\",\n attributes: {\n class: \"text\",\n x: position.x.toString(),\n y: position.y.toString(),\n \"text-anchor\": getTextAnchor(text.anchor),\n \"dominant-baseline\": \"middle\",\n },\n children: [\n {\n type: \"text\",\n value: text.text ? text.text : \"\",\n },\n ],\n };\n}\n\nfunction getTextAnchor(anchor: string): string {\n switch (anchor) {\n case \"left\":\n return \"start\";\n case \"right\":\n return \"end\";\n default:\n return \"middle\";\n }\n}\n\nexport { circuitJsonToSchematicSvg };\n"],"mappings":"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","names":["import_svgson","scale"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circuit-to-svg",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "Convert Circuit JSON to SVG",
5
5
  "main": "dist/index.js",
6
6
  "files": [