graphics-debug 0.0.46 → 0.0.48

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "graphics-debug",
3
3
  "main": "dist/lib/index.js",
4
4
  "type": "module",
5
- "version": "0.0.46",
5
+ "version": "0.0.48",
6
6
  "files": [
7
7
  "dist"
8
8
  ],
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../lib/drawGraphicsToCanvas.ts","../site/components/InteractiveGraphics/defaultColors.ts"],"sourcesContent":["import {\n compose,\n scale,\n translate,\n applyToPoint,\n type Matrix,\n} from \"transformation-matrix\"\nimport type {\n GraphicsObject,\n Viewbox,\n CenterViewbox,\n TransformOptions,\n} from \"./types\"\nimport { defaultColors } from \"site/components/InteractiveGraphics/defaultColors\"\n\n/**\n * Computes a transformation matrix based on a provided viewbox\n * Handles both min/max style viewboxes and center/width/height style viewboxes\n */\nexport function computeTransformFromViewbox(\n viewbox: Viewbox | CenterViewbox,\n canvasWidth: number,\n canvasHeight: number,\n options: { padding?: number; yFlip?: boolean } = {},\n): Matrix {\n const padding = options.padding ?? 40\n const yFlip = options.yFlip ?? false\n\n // Convert CenterViewbox to Viewbox if needed\n let bounds: Viewbox\n if (\"center\" in viewbox) {\n const halfWidth = viewbox.width / 2\n const halfHeight = viewbox.height / 2\n bounds = {\n minX: viewbox.center.x - halfWidth,\n maxX: viewbox.center.x + halfWidth,\n minY: viewbox.center.y - halfHeight,\n maxY: viewbox.center.y + halfHeight,\n }\n } else {\n bounds = viewbox\n }\n\n const width = bounds.maxX - bounds.minX\n const height = bounds.maxY - bounds.minY\n\n const scale_factor = Math.min(\n (canvasWidth - 2 * padding) / width,\n (canvasHeight - 2 * padding) / height,\n )\n\n return compose(\n translate(canvasWidth / 2, canvasHeight / 2),\n scale(scale_factor, yFlip ? -scale_factor : scale_factor),\n translate(-(bounds.minX + width / 2), -(bounds.minY + height / 2)),\n )\n}\n\n/**\n * Computes bounds for a graphics object\n */\nexport function getBounds(graphics: GraphicsObject): Viewbox {\n const points = [\n ...(graphics.points || []),\n ...(graphics.lines || []).flatMap((line) => line.points),\n ...(graphics.rects || []).flatMap((rect) => {\n const halfWidth = rect.width / 2\n const halfHeight = rect.height / 2\n return [\n { x: rect.center.x - halfWidth, y: rect.center.y - halfHeight },\n { x: rect.center.x + halfWidth, y: rect.center.y - halfHeight },\n { x: rect.center.x - halfWidth, y: rect.center.y + halfHeight },\n { x: rect.center.x + halfWidth, y: rect.center.y + halfHeight },\n ]\n }),\n ...(graphics.circles || []).flatMap((circle) => [\n { x: circle.center.x - circle.radius, y: circle.center.y }, // left\n { x: circle.center.x + circle.radius, y: circle.center.y }, // right\n { x: circle.center.x, y: circle.center.y - circle.radius }, // top\n { x: circle.center.x, y: circle.center.y + circle.radius }, // bottom\n ]),\n ]\n\n if (points.length === 0) {\n return { minX: -1, maxX: 1, minY: -1, maxY: 1 }\n }\n\n return points.reduce(\n (bounds, point) => ({\n minX: Math.min(bounds.minX, point.x),\n maxX: Math.max(bounds.maxX, point.x),\n minY: Math.min(bounds.minY, point.y),\n maxY: Math.max(bounds.maxY, point.y),\n }),\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n}\n\n/**\n * Draws a graphics object onto a canvas or context\n * @param graphics - The graphics object to draw\n * @param target - The canvas element or 2D context to draw on\n * @param options - Options for controlling the transform and rendering\n */\nexport function drawGraphicsToCanvas(\n graphics: GraphicsObject,\n target: HTMLCanvasElement | CanvasRenderingContext2D,\n options: TransformOptions = {},\n): void {\n // Get the context\n const ctx =\n target instanceof HTMLCanvasElement ? target.getContext(\"2d\") : target\n\n if (!ctx) {\n throw new Error(\"Could not get 2D context from canvas\")\n }\n\n // Get canvas dimensions\n const canvasWidth =\n target instanceof HTMLCanvasElement ? target.width : target.canvas.width\n\n const canvasHeight =\n target instanceof HTMLCanvasElement ? target.height : target.canvas.height\n\n // Get or compute the transform matrix\n let matrix: Matrix\n\n if (options.transform) {\n matrix = options.transform\n } else if (options.viewbox) {\n matrix = computeTransformFromViewbox(\n options.viewbox,\n canvasWidth,\n canvasHeight,\n {\n padding: options.padding,\n yFlip: options.yFlip,\n },\n )\n } else {\n // Auto-compute bounds and transform if not provided\n const bounds = getBounds(graphics)\n const yFlip = graphics.coordinateSystem === \"cartesian\"\n matrix = computeTransformFromViewbox(bounds, canvasWidth, canvasHeight, {\n padding: options.padding ?? 40,\n yFlip,\n })\n }\n\n // Clear the canvas\n ctx.clearRect(0, 0, canvasWidth, canvasHeight)\n\n // Save the current transform state\n ctx.save()\n\n // Draw the graphics elements\n // Draw rectangles\n if (graphics.rects && graphics.rects.length > 0) {\n graphics.rects.forEach((rect) => {\n const halfWidth = rect.width / 2\n const halfHeight = rect.height / 2\n\n const topLeft = applyToPoint(matrix, {\n x: rect.center.x - halfWidth,\n y: rect.center.y - halfHeight,\n })\n\n const bottomRight = applyToPoint(matrix, {\n x: rect.center.x + halfWidth,\n y: rect.center.y + halfHeight,\n })\n\n const width = Math.abs(bottomRight.x - topLeft.x)\n const height = Math.abs(bottomRight.y - topLeft.y)\n\n ctx.beginPath()\n ctx.rect(\n Math.min(topLeft.x, bottomRight.x),\n Math.min(topLeft.y, bottomRight.y),\n width,\n height,\n )\n\n if (rect.fill) {\n ctx.fillStyle = rect.fill\n ctx.fill()\n }\n\n if (rect.stroke) {\n ctx.strokeStyle = rect.stroke\n ctx.stroke()\n }\n })\n }\n\n // Draw circles\n if (graphics.circles && graphics.circles.length > 0) {\n graphics.circles.forEach((circle) => {\n const projected = applyToPoint(matrix, circle.center)\n const scaledRadius = circle.radius * Math.abs(matrix.a) // Use matrix scale factor\n\n ctx.beginPath()\n ctx.arc(projected.x, projected.y, scaledRadius, 0, 2 * Math.PI)\n\n if (circle.fill) {\n ctx.fillStyle = circle.fill\n ctx.fill()\n }\n\n if (circle.stroke) {\n ctx.strokeStyle = circle.stroke ?? \"transparent\"\n ctx.stroke()\n }\n })\n }\n\n // Draw lines\n if (graphics.lines && graphics.lines.length > 0) {\n graphics.lines.forEach((line, lineIndex) => {\n if (line.points.length === 0) return\n\n ctx.beginPath()\n\n const firstPoint = applyToPoint(matrix, line.points[0])\n ctx.moveTo(firstPoint.x, firstPoint.y)\n\n for (let i = 1; i < line.points.length; i++) {\n const projected = applyToPoint(matrix, line.points[i])\n ctx.lineTo(projected.x, projected.y)\n }\n\n ctx.strokeStyle =\n line.strokeColor || defaultColors[lineIndex % defaultColors.length]\n if (line.strokeWidth) {\n ctx.lineWidth = line.strokeWidth * matrix.a\n } else {\n ctx.lineWidth = 2\n }\n ctx.lineCap = \"round\"\n\n if (line.strokeDash) {\n if (typeof line.strokeDash === \"string\") {\n // Convert string to array of numbers, handling single values properly\n let dashArray: number[]\n\n // If the string contains commas, split and convert to numbers\n if (line.strokeDash.includes(\",\")) {\n dashArray = line.strokeDash\n .split(\",\")\n .map((s) => parseFloat(s.trim()))\n .filter((n) => !Number.isNaN(n))\n } else {\n // Handle single value case\n const value = parseFloat(line.strokeDash.trim())\n dashArray = !Number.isNaN(value) ? [value] : []\n }\n\n // Scale dash values based on transform matrix\n ctx.setLineDash(dashArray)\n } else {\n // Handle array format\n ctx.setLineDash(line.strokeDash.map((n) => n * Math.abs(matrix.a)))\n }\n } else {\n ctx.setLineDash([])\n }\n\n ctx.stroke()\n })\n }\n\n // Draw points\n if (graphics.points && graphics.points.length > 0) {\n graphics.points.forEach((point, pointIndex) => {\n const projected = applyToPoint(matrix, point)\n\n // Draw point as a small circle\n ctx.beginPath()\n ctx.arc(projected.x, projected.y, 3, 0, 2 * Math.PI)\n ctx.fillStyle =\n point.color || defaultColors[pointIndex % defaultColors.length]\n ctx.fill()\n\n // Draw label if present and labels aren't disabled\n if (point.label && !options.disableLabels) {\n ctx.fillStyle = point.color || \"black\"\n ctx.font = \"12px sans-serif\"\n ctx.fillText(point.label, projected.x + 5, projected.y - 5)\n }\n })\n }\n\n // Restore the original transform\n ctx.restore()\n}\n","// These are default colors if no color is provided\n// colors are made based on the index of the item in the array\n\nexport const defaultColors = [\n \"rgba(239, 68, 68, 0.8)\", // red-300\n \"rgba(249, 115, 22, 0.8)\", // orange-300\n \"rgba(245, 158, 11, 0.8)\", // amber-300\n \"rgba(234, 179, 8, 0.8)\", // yellow-300\n \"rgba(132, 204, 22, 0.8)\", // lime-300\n \"rgba(34, 197, 94, 0.8)\", // green-300\n \"rgba(16, 185, 129, 0.8)\", // emerald-300\n \"rgba(20, 184, 166, 0.8)\", // teal-300\n \"rgba(6, 182, 212, 0.8)\", // cyan-300\n \"rgba(14, 165, 233, 0.8)\", // sky-300\n \"rgba(59, 130, 246, 0.8)\", // blue-300\n \"rgba(99, 102, 241, 0.8)\", // indigo-300\n \"rgba(139, 92, 246, 0.8)\", // violet-300\n \"rgba(168, 85, 247, 0.8)\", // purple-300\n \"rgba(217, 70, 239, 0.8)\", // fuchsia-300\n \"rgba(236, 72, 153, 0.8)\", // pink-300\n \"rgba(249, 168, 212, 0.8)\", // rose-300\n \"rgba(161, 161, 170, 0.8)\", // zinc-300\n]\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../lib/getSvgFromGraphicsObject.ts"],"sourcesContent":["import {\n transform,\n compose,\n translate,\n scale,\n applyToPoint,\n identity,\n type Matrix,\n} from \"transformation-matrix\"\nimport type { GraphicsObject, Point } from \"./types\"\nimport { stringify } from \"svgson\"\nimport pretty from \"pretty\"\n\nconst DEFAULT_SVG_SIZE = 640\nconst PADDING = 40\n\ninterface Bounds {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\nfunction getBounds(graphics: GraphicsObject): Bounds {\n const points: Point[] = [\n ...(graphics.points || []),\n ...(graphics.lines || []).flatMap((line) => line.points),\n ...(graphics.rects || []).flatMap((rect) => {\n const halfWidth = rect.width / 2\n const halfHeight = rect.height / 2\n return [\n { x: rect.center.x - halfWidth, y: rect.center.y - halfHeight },\n { x: rect.center.x + halfWidth, y: rect.center.y - halfHeight },\n { x: rect.center.x - halfWidth, y: rect.center.y + halfHeight },\n { x: rect.center.x + halfWidth, y: rect.center.y + halfHeight },\n ]\n }),\n ...(graphics.circles || []).flatMap((circle) => [\n { x: circle.center.x - circle.radius, y: circle.center.y }, // left\n { x: circle.center.x + circle.radius, y: circle.center.y }, // right\n { x: circle.center.x, y: circle.center.y - circle.radius }, // top\n { x: circle.center.x, y: circle.center.y + circle.radius }, // bottom\n ]),\n ]\n\n if (points.length === 0) {\n return { minX: -1, maxX: 1, minY: -1, maxY: 1 }\n }\n\n return points.reduce(\n (bounds, point) => ({\n minX: Math.min(bounds.minX, point.x),\n maxX: Math.max(bounds.maxX, point.x),\n minY: Math.min(bounds.minY, point.y),\n maxY: Math.max(bounds.maxY, point.y),\n }),\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n}\n\nfunction getProjectionMatrix(\n bounds: Bounds,\n coordinateSystem: GraphicsObject[\"coordinateSystem\"],\n) {\n const width = bounds.maxX - bounds.minX\n const height = bounds.maxY - bounds.minY\n\n const scale_factor = Math.min(\n (DEFAULT_SVG_SIZE - 2 * PADDING) / width,\n (DEFAULT_SVG_SIZE - 2 * PADDING) / height,\n )\n\n const yFlip = coordinateSystem === \"screen\" ? 1 : -1\n\n return compose(\n translate(DEFAULT_SVG_SIZE / 2, DEFAULT_SVG_SIZE / 2),\n scale(scale_factor, yFlip * scale_factor),\n translate(-(bounds.minX + width / 2), -(bounds.minY + height / 2)),\n )\n}\n\nfunction projectPoint(point: Point, matrix: Matrix) {\n const projected = applyToPoint(matrix, { x: point.x, y: point.y })\n return { ...point, ...projected }\n}\n\nexport function getSvgFromGraphicsObject(\n graphics: GraphicsObject,\n {\n includeTextLabels = false,\n backgroundColor,\n }: {\n includeTextLabels?: boolean | Array<\"points\" | \"lines\" | \"rects\">\n backgroundColor?: string\n } = {},\n): string {\n const bounds = getBounds(graphics)\n const matrix = getProjectionMatrix(bounds, graphics.coordinateSystem)\n\n const shouldRenderLabel = (type: \"points\" | \"lines\" | \"rects\"): boolean => {\n if (typeof includeTextLabels === \"boolean\") {\n return includeTextLabels\n }\n if (Array.isArray(includeTextLabels)) {\n return includeTextLabels.includes(type)\n }\n return false\n }\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n width: DEFAULT_SVG_SIZE.toString(),\n height: DEFAULT_SVG_SIZE.toString(),\n viewBox: `0 0 ${DEFAULT_SVG_SIZE} ${DEFAULT_SVG_SIZE}`,\n xmlns: \"http://www.w3.org/2000/svg\",\n },\n children: [\n // Background rectangle (optional)\n ...(backgroundColor\n ? [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n width: \"100%\",\n height: \"100%\",\n fill: backgroundColor,\n },\n },\n ]\n : []),\n // Points\n ...(graphics.points || []).map((point) => {\n const projected = projectPoint(point, matrix)\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n \"data-type\": \"point\",\n \"data-label\": point.label || \"\",\n \"data-x\": point.x.toString(),\n \"data-y\": point.y.toString(),\n cx: projected.x.toString(),\n cy: projected.y.toString(),\n r: \"3\",\n fill: point.color || \"black\",\n },\n },\n ...(shouldRenderLabel(\"points\") && point.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (projected.x + 5).toString(),\n y: (projected.y - 5).toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n },\n children: [{ type: \"text\", value: point.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Lines\n ...(graphics.lines || []).map((line) => {\n const projectedPoints = line.points.map((p) => projectPoint(p, matrix))\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"polyline\",\n type: \"element\",\n attributes: {\n \"data-points\": line.points.map((p) => `${p.x},${p.y}`).join(\" \"),\n \"data-type\": \"line\",\n \"data-label\": line.label || \"\",\n points: projectedPoints\n .map((p) => `${p.x},${p.y}`)\n .join(\" \"),\n fill: \"none\",\n stroke: line.strokeColor || \"black\",\n \"stroke-width\": (line.strokeWidth\n ? line.strokeWidth * matrix.a\n : 1\n ).toString(),\n ...(line.strokeDash && {\n \"stroke-dasharray\": Array.isArray(line.strokeDash)\n ? line.strokeDash.join(\" \")\n : line.strokeDash,\n }),\n },\n },\n ...(shouldRenderLabel(\"lines\") && line.label && projectedPoints.length > 0\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (projectedPoints[0].x + 5).toString(),\n y: (projectedPoints[0].y - 5).toString(),\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n fill: line.strokeColor || \"black\",\n },\n children: [{ type: \"text\", value: line.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Rectangles\n ...(graphics.rects || []).map((rect) => {\n const corner1 = {\n x: rect.center.x - rect.width / 2,\n y: rect.center.y - rect.height / 2,\n }\n const projectedCorner1 = projectPoint(corner1, matrix)\n const corner2 = {\n x: rect.center.x + rect.width / 2,\n y: rect.center.y + rect.height / 2,\n }\n const projectedCorner2 = projectPoint(corner2, matrix)\n const scaledWidth = Math.abs(projectedCorner2.x - projectedCorner1.x)\n const scaledHeight = Math.abs(projectedCorner2.y - projectedCorner1.y)\n const rectX = Math.min(projectedCorner1.x, projectedCorner2.x)\n const rectY = Math.min(projectedCorner1.y, projectedCorner2.y)\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: {},\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n \"data-type\": \"rect\",\n \"data-label\": rect.label || \"\",\n \"data-x\": rect.center.x.toString(),\n \"data-y\": rect.center.y.toString(),\n x: rectX.toString(),\n y: rectY.toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n fill: rect.fill || \"none\",\n stroke: rect.stroke || \"black\",\n \"stroke-width\": Math.abs(1 / matrix.a).toString(), // Consider scaling stroke width like lines if needed\n },\n },\n ...(shouldRenderLabel(\"rects\") && rect.label\n ? [\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: (rectX + 5).toString(),\n y: (rectY - 5).toString(), // Position above the top-left corner\n \"font-family\": \"sans-serif\",\n \"font-size\": \"12\",\n fill: rect.stroke || \"black\", // Default to stroke color for label\n },\n children: [{ type: \"text\", value: rect.label }],\n },\n ]\n : []),\n ],\n }\n }),\n // Circles\n ...(graphics.circles || []).map((circle) => {\n const projected = projectPoint(circle.center, matrix)\n const scaledRadius = circle.radius * Math.abs(matrix.a)\n return {\n name: \"circle\",\n type: \"element\",\n attributes: {\n \"data-type\": \"circle\",\n \"data-label\": \"\",\n \"data-x\": circle.center.x.toString(),\n \"data-y\": circle.center.y.toString(),\n cx: projected.x.toString(),\n cy: projected.y.toString(),\n r: scaledRadius.toString(),\n fill: circle.fill || \"none\",\n stroke: circle.stroke || \"black\",\n \"stroke-width\": Math.abs(1 / matrix.a).toString(),\n },\n }\n }),\n // Crosshair lines and coordinates (initially hidden)\n {\n name: \"g\",\n type: \"element\",\n attributes: {\n id: \"crosshair\",\n style: \"display: none\",\n },\n children: [\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n id: \"crosshair-h\",\n y1: \"0\",\n y2: DEFAULT_SVG_SIZE.toString(),\n stroke: \"#666\",\n \"stroke-width\": \"0.5\",\n },\n },\n {\n name: \"line\",\n type: \"element\",\n attributes: {\n id: \"crosshair-v\",\n x1: \"0\",\n x2: DEFAULT_SVG_SIZE.toString(),\n stroke: \"#666\",\n \"stroke-width\": \"0.5\",\n },\n },\n {\n name: \"text\",\n type: \"element\",\n attributes: {\n id: \"coordinates\",\n \"font-family\": \"monospace\",\n \"font-size\": \"12\",\n fill: \"#666\",\n },\n children: [{ type: \"text\", value: \"\" }],\n },\n ],\n },\n // Mouse tracking script\n {\n name: \"script\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n document.currentScript.parentElement.addEventListener('mousemove', (e) => {\n const svg = e.currentTarget;\n const rect = svg.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n const crosshair = svg.getElementById('crosshair');\n const h = svg.getElementById('crosshair-h');\n const v = svg.getElementById('crosshair-v');\n const coords = svg.getElementById('coordinates');\n \n crosshair.style.display = 'block';\n h.setAttribute('x1', '0');\n h.setAttribute('x2', '${DEFAULT_SVG_SIZE}');\n h.setAttribute('y1', y);\n h.setAttribute('y2', y);\n v.setAttribute('x1', x);\n v.setAttribute('x2', x);\n v.setAttribute('y1', '0');\n v.setAttribute('y2', '${DEFAULT_SVG_SIZE}');\n\n // Calculate real coordinates using inverse transformation\n const matrix = ${JSON.stringify(matrix)};\n // Manually invert and apply the affine transform\n // Since we only use translate and scale, we can directly compute:\n // x' = (x - tx) / sx\n // y' = (y - ty) / sy\n const sx = matrix.a;\n const sy = matrix.d;\n const tx = matrix.e; \n const ty = matrix.f;\n const realPoint = {\n x: (x - tx) / sx,\n y: (y - ty) / sy // Flip y back since we used negative scale\n }\n \n coords.textContent = \\`(\\${realPoint.x.toFixed(2)}, \\${realPoint.y.toFixed(2)})\\`;\n coords.setAttribute('x', (x + 5).toString());\n coords.setAttribute('y', (y - 5).toString());\n });\n document.currentScript.parentElement.addEventListener('mouseleave', () => {\n document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';\n });\n `,\n },\n ],\n },\n ],\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: TODO\n return pretty(stringify(svgObject as any))\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../lib/index.ts"],"sourcesContent":["import { getGraphicsObjectsFromLogString } from \"./getGraphicsObjectsFromLogString\"\nimport { getSvgFromGraphicsObject } from \"./getSvgFromGraphicsObject\"\nimport {\n drawGraphicsToCanvas,\n computeTransformFromViewbox,\n getBounds,\n} from \"./drawGraphicsToCanvas\"\n\nexport type {\n Point,\n Line,\n Rect,\n Circle,\n GraphicsObject,\n Viewbox,\n CenterViewbox,\n TransformOptions,\n} from \"./types\"\nexport { getGraphicsObjectsFromLogString } from \"./getGraphicsObjectsFromLogString\"\nexport { getSvgFromGraphicsObject } from \"./getSvgFromGraphicsObject\"\nexport {\n drawGraphicsToCanvas,\n computeTransformFromViewbox,\n getBounds,\n} from \"./drawGraphicsToCanvas\"\n\nexport function getSvgFromLogString(logString: string): string {\n const objects = getGraphicsObjectsFromLogString(logString)\n if (objects.length === 0) return \"\"\n return getSvgFromGraphicsObject(objects[0])\n}\n\nexport function getHtmlFromLogString(logString: string): string {\n const svgs = getSvgsFromLogString(logString)\n if (svgs.length === 0) return \"\"\n\n const sections = svgs\n .map(\n ({ title, svg }) => `\n <section>\n <h2>${title}</h2>\n ${svg}\n </section>\n `,\n )\n .join(\"\\n\")\n\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <title>Graphics Debug Output</title>\n <style>\n body { font-family: system-ui; max-width: 1200px; margin: 0 auto; padding: 20px; }\n h1 { color: #333; }\n section { margin: 40px 0; }\n svg { max-width: 100%; height: auto; border: 1px solid #eee; }\n </style>\n</head>\n<body>\n <h1>Graphics Debug Output</h1>\n ${sections}\n</body>\n</html>`\n}\n\nexport function getSvgsFromLogString(\n logString: string,\n): Array<{ title: string; svg: string }> {\n const objects = getGraphicsObjectsFromLogString(logString)\n return objects.map((obj) => ({\n title: obj.title || \"Untitled Graphic\",\n svg: getSvgFromGraphicsObject(obj),\n }))\n}\n"],"mappings":";;;;;;;;AA0BO,SAAS,oBAAoB,WAA2B;AAC7D,QAAM,UAAU,gCAAgC,SAAS;AACzD,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO,yBAAyB,QAAQ,CAAC,CAAC;AAC5C;AAEO,SAAS,qBAAqB,WAA2B;AAC9D,QAAM,OAAO,qBAAqB,SAAS;AAC3C,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,QAAM,WAAW,KACd;AAAA,IACC,CAAC,EAAE,OAAO,IAAI,MAAM;AAAA;AAAA,YAEd,KAAK;AAAA,QACT,GAAG;AAAA;AAAA;AAAA,EAGP,EACC,KAAK,IAAI;AAEZ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAcL,QAAQ;AAAA;AAAA;AAGZ;AAEO,SAAS,qBACd,WACuC;AACvC,QAAM,UAAU,gCAAgC,SAAS;AACzD,SAAO,QAAQ,IAAI,CAAC,SAAS;AAAA,IAC3B,OAAO,IAAI,SAAS;AAAA,IACpB,KAAK,yBAAyB,GAAG;AAAA,EACnC,EAAE;AACJ;","names":[]}