graphics-debug 0.0.2 → 0.0.3
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/README.md +4 -1
- package/dist/{chunk-MADVCBD7.js → chunk-2YVICPCE.js} +2 -2
- package/dist/{chunk-4FN266Q5.js → chunk-X2DSMR32.js} +16 -1
- package/dist/chunk-X2DSMR32.js.map +1 -0
- package/dist/cli/cli.d.ts +1 -0
- package/dist/cli/cli.js +2 -2
- package/dist/lib/getGraphicsObjectsFromLogString.d.ts +9 -0
- package/dist/lib/getSvgFromGraphicsObject.d.ts +5 -0
- package/dist/lib/getSvgFromGraphicsObject.js +1 -1
- package/dist/lib/index.d.ts +12 -0
- package/dist/lib/index.js +2 -2
- package/dist/lib/types.d.ts +43 -0
- package/package.json +3 -2
- package/dist/chunk-4FN266Q5.js.map +0 -1
- package/dist/chunk-646ISP7J.js +0 -27
- package/dist/chunk-646ISP7J.js.map +0 -1
- package/dist/chunk-G7UBPMLZ.js +0 -268
- package/dist/chunk-G7UBPMLZ.js.map +0 -1
- package/dist/chunk-GDKEOGZB.js +0 -56
- package/dist/chunk-GDKEOGZB.js.map +0 -1
- package/dist/chunk-J2MYQBX3.js +0 -268
- package/dist/chunk-J2MYQBX3.js.map +0 -1
- package/dist/chunk-MJCYFLWQ.js +0 -56
- package/dist/chunk-MJCYFLWQ.js.map +0 -1
- package/dist/cli.js +0 -386
- package/dist/cli.js.map +0 -1
- /package/dist/{chunk-MADVCBD7.js.map → chunk-2YVICPCE.js.map} +0 -0
package/dist/cli.js
DELETED
|
@@ -1,386 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// cli/cli.ts
|
|
4
|
-
import { parseArgs } from "node:util";
|
|
5
|
-
import "node:fs";
|
|
6
|
-
import { writeFileSync } from "node:fs";
|
|
7
|
-
|
|
8
|
-
// lib/getGraphicsObjectsFromLogString.ts
|
|
9
|
-
function getGraphicsObjectsFromLogString(logString) {
|
|
10
|
-
const results = [];
|
|
11
|
-
const graphicsRegex = /\{[\s]*(?:"graphics"|graphics)[\s]*:[\s]*\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}[\s]*\}/g;
|
|
12
|
-
const matches = logString.match(graphicsRegex);
|
|
13
|
-
if (!matches) return results;
|
|
14
|
-
for (const match of matches) {
|
|
15
|
-
try {
|
|
16
|
-
const parsed = JSON.parse(match);
|
|
17
|
-
results.push(parsed);
|
|
18
|
-
} catch (e) {
|
|
19
|
-
try {
|
|
20
|
-
const fixed = match.replace(/(\b\w+)(?=\s*:)/g, '"$1"').replace(/,(\s*[}\]])/g, "$1").replace(/:\s*'([^']*)'/g, ':"$1"');
|
|
21
|
-
const parsed = JSON.parse(fixed);
|
|
22
|
-
results.push(parsed);
|
|
23
|
-
} catch (e2) {
|
|
24
|
-
console.warn("Failed to parse graphics object:", match, e2);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return results;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// lib/getSvgFromGraphicsObject.ts
|
|
32
|
-
import {
|
|
33
|
-
compose,
|
|
34
|
-
translate,
|
|
35
|
-
scale,
|
|
36
|
-
applyToPoint
|
|
37
|
-
} from "transformation-matrix";
|
|
38
|
-
import { stringify } from "svgson";
|
|
39
|
-
import pretty from "pretty";
|
|
40
|
-
var DEFAULT_SVG_SIZE = 640;
|
|
41
|
-
var PADDING = 40;
|
|
42
|
-
function getBounds(graphics) {
|
|
43
|
-
const points = [
|
|
44
|
-
...graphics.points || [],
|
|
45
|
-
...(graphics.lines || []).flatMap((line) => line.points),
|
|
46
|
-
...(graphics.rects || []).flatMap((rect) => {
|
|
47
|
-
const halfWidth = rect.width / 2;
|
|
48
|
-
const halfHeight = rect.height / 2;
|
|
49
|
-
return [
|
|
50
|
-
{ x: rect.center.x - halfWidth, y: rect.center.y - halfHeight },
|
|
51
|
-
{ x: rect.center.x + halfWidth, y: rect.center.y - halfHeight },
|
|
52
|
-
{ x: rect.center.x - halfWidth, y: rect.center.y + halfHeight },
|
|
53
|
-
{ x: rect.center.x + halfWidth, y: rect.center.y + halfHeight }
|
|
54
|
-
];
|
|
55
|
-
}),
|
|
56
|
-
...(graphics.circles || []).flatMap((circle) => [
|
|
57
|
-
{ x: circle.center.x - circle.radius, y: circle.center.y },
|
|
58
|
-
// left
|
|
59
|
-
{ x: circle.center.x + circle.radius, y: circle.center.y },
|
|
60
|
-
// right
|
|
61
|
-
{ x: circle.center.x, y: circle.center.y - circle.radius },
|
|
62
|
-
// top
|
|
63
|
-
{ x: circle.center.x, y: circle.center.y + circle.radius }
|
|
64
|
-
// bottom
|
|
65
|
-
])
|
|
66
|
-
];
|
|
67
|
-
if (points.length === 0) {
|
|
68
|
-
return { minX: -1, maxX: 1, minY: -1, maxY: 1 };
|
|
69
|
-
}
|
|
70
|
-
return points.reduce(
|
|
71
|
-
(bounds, point) => ({
|
|
72
|
-
minX: Math.min(bounds.minX, point.x),
|
|
73
|
-
maxX: Math.max(bounds.maxX, point.x),
|
|
74
|
-
minY: Math.min(bounds.minY, point.y),
|
|
75
|
-
maxY: Math.max(bounds.maxY, point.y)
|
|
76
|
-
}),
|
|
77
|
-
{ minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity }
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
function getProjectionMatrix(bounds, coordinateSystem) {
|
|
81
|
-
const width = bounds.maxX - bounds.minX;
|
|
82
|
-
const height = bounds.maxY - bounds.minY;
|
|
83
|
-
const scale_factor = Math.min(
|
|
84
|
-
(DEFAULT_SVG_SIZE - 2 * PADDING) / width,
|
|
85
|
-
(DEFAULT_SVG_SIZE - 2 * PADDING) / height
|
|
86
|
-
);
|
|
87
|
-
return compose(
|
|
88
|
-
translate(DEFAULT_SVG_SIZE / 2, DEFAULT_SVG_SIZE / 2),
|
|
89
|
-
scale(
|
|
90
|
-
scale_factor,
|
|
91
|
-
coordinateSystem === "screen" ? -scale_factor : scale_factor
|
|
92
|
-
),
|
|
93
|
-
translate(-(bounds.minX + width / 2), -(bounds.minY + height / 2))
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
function projectPoint(point, matrix) {
|
|
97
|
-
const projected = applyToPoint(matrix, { x: point.x, y: point.y });
|
|
98
|
-
return { ...point, ...projected };
|
|
99
|
-
}
|
|
100
|
-
function getSvgFromGraphicsObject(graphicsObj) {
|
|
101
|
-
const { graphics } = graphicsObj;
|
|
102
|
-
const bounds = getBounds(graphics);
|
|
103
|
-
const matrix = compose(getProjectionMatrix(bounds, graphics.coordinateSystem));
|
|
104
|
-
const svgObject = {
|
|
105
|
-
name: "svg",
|
|
106
|
-
type: "element",
|
|
107
|
-
attributes: {
|
|
108
|
-
width: DEFAULT_SVG_SIZE.toString(),
|
|
109
|
-
height: DEFAULT_SVG_SIZE.toString(),
|
|
110
|
-
viewBox: `0 0 ${DEFAULT_SVG_SIZE} ${DEFAULT_SVG_SIZE}`,
|
|
111
|
-
xmlns: "http://www.w3.org/2000/svg"
|
|
112
|
-
},
|
|
113
|
-
children: [
|
|
114
|
-
// Points
|
|
115
|
-
...(graphics.points || []).map((point) => {
|
|
116
|
-
const projected = projectPoint(point, matrix);
|
|
117
|
-
return {
|
|
118
|
-
name: "g",
|
|
119
|
-
type: "element",
|
|
120
|
-
children: [
|
|
121
|
-
{
|
|
122
|
-
name: "circle",
|
|
123
|
-
type: "element",
|
|
124
|
-
attributes: {
|
|
125
|
-
cx: projected.x.toString(),
|
|
126
|
-
cy: projected.y.toString(),
|
|
127
|
-
r: "3",
|
|
128
|
-
fill: point.color || "black"
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
...point.label ? [
|
|
132
|
-
{
|
|
133
|
-
name: "text",
|
|
134
|
-
type: "element",
|
|
135
|
-
attributes: {
|
|
136
|
-
x: (projected.x + 5).toString(),
|
|
137
|
-
y: (projected.y - 5).toString(),
|
|
138
|
-
"font-family": "sans-serif",
|
|
139
|
-
"font-size": "12"
|
|
140
|
-
},
|
|
141
|
-
children: [{ type: "text", value: point.label }]
|
|
142
|
-
}
|
|
143
|
-
] : []
|
|
144
|
-
]
|
|
145
|
-
};
|
|
146
|
-
}),
|
|
147
|
-
// Lines
|
|
148
|
-
...(graphics.lines || []).map((line) => ({
|
|
149
|
-
name: "polyline",
|
|
150
|
-
type: "element",
|
|
151
|
-
attributes: {
|
|
152
|
-
points: line.points.map((p) => projectPoint(p, matrix)).map((p) => `${p.x},${p.y}`).join(" "),
|
|
153
|
-
fill: "none",
|
|
154
|
-
stroke: "black",
|
|
155
|
-
"stroke-width": (line.points[0].stroke || 1).toString()
|
|
156
|
-
}
|
|
157
|
-
})),
|
|
158
|
-
// Rectangles
|
|
159
|
-
...(graphics.rects || []).map((rect) => {
|
|
160
|
-
const projected = projectPoint(rect.center, matrix);
|
|
161
|
-
const scaledWidth = rect.width * matrix.a;
|
|
162
|
-
const scaledHeight = rect.height * matrix.d;
|
|
163
|
-
return {
|
|
164
|
-
name: "rect",
|
|
165
|
-
type: "element",
|
|
166
|
-
attributes: {
|
|
167
|
-
x: (projected.x - scaledWidth / 2).toString(),
|
|
168
|
-
y: (projected.y - scaledHeight / 2).toString(),
|
|
169
|
-
width: scaledWidth.toString(),
|
|
170
|
-
height: Math.abs(scaledHeight).toString(),
|
|
171
|
-
fill: rect.fill || "none",
|
|
172
|
-
stroke: rect.stroke || "black"
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
}),
|
|
176
|
-
// Circles
|
|
177
|
-
...(graphics.circles || []).map((circle) => {
|
|
178
|
-
const projected = projectPoint(circle.center, matrix);
|
|
179
|
-
const scaledRadius = circle.radius * Math.abs(matrix.a);
|
|
180
|
-
return {
|
|
181
|
-
name: "circle",
|
|
182
|
-
type: "element",
|
|
183
|
-
attributes: {
|
|
184
|
-
cx: projected.x.toString(),
|
|
185
|
-
cy: projected.y.toString(),
|
|
186
|
-
r: scaledRadius.toString(),
|
|
187
|
-
fill: circle.fill || "none",
|
|
188
|
-
stroke: circle.stroke || "black"
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
}),
|
|
192
|
-
// Crosshair lines and coordinates (initially hidden)
|
|
193
|
-
{
|
|
194
|
-
name: "g",
|
|
195
|
-
type: "element",
|
|
196
|
-
attributes: {
|
|
197
|
-
id: "crosshair",
|
|
198
|
-
style: "display: none"
|
|
199
|
-
},
|
|
200
|
-
children: [
|
|
201
|
-
{
|
|
202
|
-
name: "line",
|
|
203
|
-
type: "element",
|
|
204
|
-
attributes: {
|
|
205
|
-
id: "crosshair-h",
|
|
206
|
-
y1: "0",
|
|
207
|
-
y2: DEFAULT_SVG_SIZE.toString(),
|
|
208
|
-
stroke: "#666",
|
|
209
|
-
"stroke-width": "0.5"
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
name: "line",
|
|
214
|
-
type: "element",
|
|
215
|
-
attributes: {
|
|
216
|
-
id: "crosshair-v",
|
|
217
|
-
x1: "0",
|
|
218
|
-
x2: DEFAULT_SVG_SIZE.toString(),
|
|
219
|
-
stroke: "#666",
|
|
220
|
-
"stroke-width": "0.5"
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
name: "text",
|
|
225
|
-
type: "element",
|
|
226
|
-
attributes: {
|
|
227
|
-
id: "coordinates",
|
|
228
|
-
"font-family": "monospace",
|
|
229
|
-
"font-size": "12",
|
|
230
|
-
fill: "#666"
|
|
231
|
-
},
|
|
232
|
-
children: [{ type: "text", value: "" }]
|
|
233
|
-
}
|
|
234
|
-
]
|
|
235
|
-
},
|
|
236
|
-
// Mouse tracking script
|
|
237
|
-
{
|
|
238
|
-
name: "script",
|
|
239
|
-
type: "element",
|
|
240
|
-
children: [
|
|
241
|
-
{
|
|
242
|
-
type: "text",
|
|
243
|
-
value: `
|
|
244
|
-
document.currentScript.parentElement.addEventListener('mousemove', (e) => {
|
|
245
|
-
const svg = e.currentTarget;
|
|
246
|
-
const rect = svg.getBoundingClientRect();
|
|
247
|
-
const x = e.clientX - rect.left;
|
|
248
|
-
const y = e.clientY - rect.top;
|
|
249
|
-
const crosshair = svg.getElementById('crosshair');
|
|
250
|
-
const h = svg.getElementById('crosshair-h');
|
|
251
|
-
const v = svg.getElementById('crosshair-v');
|
|
252
|
-
const coords = svg.getElementById('coordinates');
|
|
253
|
-
|
|
254
|
-
crosshair.style.display = 'block';
|
|
255
|
-
h.setAttribute('x1', '0');
|
|
256
|
-
h.setAttribute('x2', '${DEFAULT_SVG_SIZE}');
|
|
257
|
-
h.setAttribute('y1', y);
|
|
258
|
-
h.setAttribute('y2', y);
|
|
259
|
-
v.setAttribute('x1', x);
|
|
260
|
-
v.setAttribute('x2', x);
|
|
261
|
-
v.setAttribute('y1', '0');
|
|
262
|
-
v.setAttribute('y2', '${DEFAULT_SVG_SIZE}');
|
|
263
|
-
|
|
264
|
-
// Calculate real coordinates using inverse transformation
|
|
265
|
-
const matrix = ${JSON.stringify(matrix)};
|
|
266
|
-
// Manually invert and apply the affine transform
|
|
267
|
-
// Since we only use translate and scale, we can directly compute:
|
|
268
|
-
// x' = (x - tx) / sx
|
|
269
|
-
// y' = (y - ty) / sy
|
|
270
|
-
const sx = matrix.a;
|
|
271
|
-
const sy = matrix.d;
|
|
272
|
-
const tx = matrix.e;
|
|
273
|
-
const ty = matrix.f;
|
|
274
|
-
const realPoint = {
|
|
275
|
-
x: (x - tx) / sx,
|
|
276
|
-
y: -(y - ty) / sy // Flip y back since we used negative scale
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
coords.textContent = \`(\${realPoint.x.toFixed(2)}, \${realPoint.y.toFixed(2)})\`;
|
|
280
|
-
coords.setAttribute('x', (x + 5).toString());
|
|
281
|
-
coords.setAttribute('y', (y - 5).toString());
|
|
282
|
-
});
|
|
283
|
-
document.currentScript.parentElement.addEventListener('mouseleave', () => {
|
|
284
|
-
document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
|
|
285
|
-
});
|
|
286
|
-
`
|
|
287
|
-
}
|
|
288
|
-
]
|
|
289
|
-
}
|
|
290
|
-
]
|
|
291
|
-
};
|
|
292
|
-
return pretty(stringify(svgObject));
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// lib/index.ts
|
|
296
|
-
function getHtmlFromLogString(logString) {
|
|
297
|
-
const svgs = getSvgsFromLogString(logString);
|
|
298
|
-
if (svgs.length === 0) return "";
|
|
299
|
-
const sections = svgs.map(
|
|
300
|
-
({ title, svg }) => `
|
|
301
|
-
<section>
|
|
302
|
-
<h2>${title}</h2>
|
|
303
|
-
${svg}
|
|
304
|
-
</section>
|
|
305
|
-
`
|
|
306
|
-
).join("\n");
|
|
307
|
-
return `
|
|
308
|
-
<!DOCTYPE html>
|
|
309
|
-
<html>
|
|
310
|
-
<head>
|
|
311
|
-
<title>Graphics Debug Output</title>
|
|
312
|
-
<style>
|
|
313
|
-
body { font-family: system-ui; max-width: 1200px; margin: 0 auto; padding: 20px; }
|
|
314
|
-
h1 { color: #333; }
|
|
315
|
-
section { margin: 40px 0; }
|
|
316
|
-
svg { max-width: 100%; height: auto; border: 1px solid #eee; }
|
|
317
|
-
</style>
|
|
318
|
-
</head>
|
|
319
|
-
<body>
|
|
320
|
-
<h1>Graphics Debug Output</h1>
|
|
321
|
-
${sections}
|
|
322
|
-
</body>
|
|
323
|
-
</html>`;
|
|
324
|
-
}
|
|
325
|
-
function getSvgsFromLogString(logString) {
|
|
326
|
-
const objects = getGraphicsObjectsFromLogString(logString);
|
|
327
|
-
return objects.map((obj) => ({
|
|
328
|
-
title: obj.graphics.title || "Untitled Graphic",
|
|
329
|
-
svg: getSvgFromGraphicsObject(obj)
|
|
330
|
-
}));
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// cli/cli.ts
|
|
334
|
-
async function getInput() {
|
|
335
|
-
if (process.stdin.isTTY) {
|
|
336
|
-
console.error(
|
|
337
|
-
"Error: No input provided. Pipe in content with graphics objects."
|
|
338
|
-
);
|
|
339
|
-
process.exit(1);
|
|
340
|
-
}
|
|
341
|
-
const chunks = [];
|
|
342
|
-
for await (const chunk of process.stdin) {
|
|
343
|
-
chunks.push(chunk);
|
|
344
|
-
}
|
|
345
|
-
return chunks.join("");
|
|
346
|
-
}
|
|
347
|
-
async function main() {
|
|
348
|
-
const { values } = parseArgs({
|
|
349
|
-
options: {
|
|
350
|
-
html: { type: "boolean" },
|
|
351
|
-
help: { type: "boolean" }
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
if (values.help) {
|
|
355
|
-
console.log(`
|
|
356
|
-
Usage: graphics-debug [options]
|
|
357
|
-
|
|
358
|
-
Options:
|
|
359
|
-
--html Output a single HTML file with all graphics
|
|
360
|
-
--help Show this help message
|
|
361
|
-
|
|
362
|
-
Examples:
|
|
363
|
-
cat debug.log | graphics-debug
|
|
364
|
-
echo '{ graphics: { points: [{x: 0, y: 0}] } }' | graphics-debug --html
|
|
365
|
-
`);
|
|
366
|
-
process.exit(0);
|
|
367
|
-
}
|
|
368
|
-
const input = await getInput();
|
|
369
|
-
if (values.html) {
|
|
370
|
-
const html = getHtmlFromLogString(input);
|
|
371
|
-
writeFileSync("graphicsdebug.debug.html", html);
|
|
372
|
-
console.log('Wrote to "graphicsdebug.debug.html"');
|
|
373
|
-
} else {
|
|
374
|
-
const svgs = getSvgsFromLogString(input);
|
|
375
|
-
svgs.forEach((svg, i) => {
|
|
376
|
-
const filename = `${svg.title.toLowerCase().replace(/\s+/g, "-")}-${i + 1}.debug.svg`;
|
|
377
|
-
writeFileSync(filename, svg.svg);
|
|
378
|
-
console.log(`Wrote to "${filename}"`);
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
main().catch((err) => {
|
|
383
|
-
console.error("Error:", err);
|
|
384
|
-
process.exit(1);
|
|
385
|
-
});
|
|
386
|
-
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../cli/cli.ts","../lib/getGraphicsObjectsFromLogString.ts","../lib/getSvgFromGraphicsObject.ts","../lib/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\"\nimport { readFileSync } from \"node:fs\"\nimport { writeFileSync } from \"node:fs\"\nimport { getSvgsFromLogString, getHtmlFromLogString } from \"../lib\"\n\nasync function getInput(): Promise<string> {\n // Check if there's data being piped in\n if (process.stdin.isTTY) {\n console.error(\n \"Error: No input provided. Pipe in content with graphics objects.\",\n )\n process.exit(1)\n }\n\n const chunks = []\n for await (const chunk of process.stdin) {\n chunks.push(chunk)\n }\n return chunks.join(\"\")\n}\n\nasync function main() {\n const { values } = parseArgs({\n options: {\n html: { type: \"boolean\" },\n help: { type: \"boolean\" },\n },\n })\n\n if (values.help) {\n console.log(`\nUsage: graphics-debug [options]\n\nOptions:\n --html Output a single HTML file with all graphics\n --help Show this help message\n\nExamples:\n cat debug.log | graphics-debug\n echo '{ graphics: { points: [{x: 0, y: 0}] } }' | graphics-debug --html\n `)\n process.exit(0)\n }\n\n const input = await getInput()\n\n if (values.html) {\n const html = getHtmlFromLogString(input)\n writeFileSync(\"graphicsdebug.debug.html\", html)\n console.log('Wrote to \"graphicsdebug.debug.html\"')\n } else {\n const svgs = getSvgsFromLogString(input)\n svgs.forEach((svg, i) => {\n const filename = `${svg.title.toLowerCase().replace(/\\s+/g, \"-\")}-${i + 1}.debug.svg`\n writeFileSync(filename, svg.svg)\n console.log(`Wrote to \"${filename}\"`)\n })\n }\n}\n\nmain().catch((err) => {\n console.error(\"Error:\", err)\n process.exit(1)\n})\n","import type { GraphicsObject } from \"./types\";\n\n/**\n * Extracts graphics objects from a debug log string\n * Handles both well-formatted JSON and relaxed JSON syntax (unquoted keys)\n */\nexport function getGraphicsObjectsFromLogString(\n\tlogString: string,\n): GraphicsObject[] {\n\tconst results: GraphicsObject[] = [];\n\n\t// Match { graphics: ... } patterns, allowing for other content on same line\n\t// Use a more precise regex that handles nested structures\n\tconst graphicsRegex =\n\t\t/\\{[\\s]*(?:\"graphics\"|graphics)[\\s]*:[\\s]*\\{(?:[^{}]|\\{(?:[^{}]|\\{[^{}]*\\})*\\})*\\}[\\s]*\\}/g;\n\tconst matches = logString.match(graphicsRegex);\n\n\tif (!matches) return results;\n\n\tfor (const match of matches) {\n\t\ttry {\n\t\t\t// First try parsing as regular JSON\n\t\t\tconst parsed = JSON.parse(match);\n\t\t\tresults.push(parsed);\n\t\t} catch (e) {\n\t\t\ttry {\n\t\t\t\t// If that fails, fix JSON formatting issues:\n\t\t\t\t// 1. Add quotes around unquoted keys\n\t\t\t\t// 2. Handle potential trailing commas\n\t\t\t\tconst fixed = match\n\t\t\t\t\t.replace(/(\\b\\w+)(?=\\s*:)/g, '\"$1\"') // Quote unquoted keys more precisely\n\t\t\t\t\t.replace(/,(\\s*[}\\]])/g, \"$1\") // Remove trailing commas\n\t\t\t\t\t.replace(/:\\s*'([^']*)'/g, ':\"$1\"'); // Convert single quotes to double quotes\n\n\t\t\t\tconst parsed = JSON.parse(fixed);\n\t\t\t\tresults.push(parsed);\n\t\t\t} catch (e) {\n\t\t\t\t// Skip invalid entries but log the error and the problematic match\n\t\t\t\tconsole.warn(\"Failed to parse graphics object:\", match, e);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n}\n","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[\"graphics\"]): 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[\"graphics\"][\"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 return compose(\n translate(DEFAULT_SVG_SIZE / 2, DEFAULT_SVG_SIZE / 2),\n scale(\n scale_factor,\n coordinateSystem === \"screen\" ? -scale_factor : scale_factor,\n ),\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(graphicsObj: GraphicsObject): string {\n const { graphics } = graphicsObj\n const bounds = getBounds(graphics)\n const matrix = compose(getProjectionMatrix(bounds, graphics.coordinateSystem))\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 // Points\n ...(graphics.points || []).map((point) => {\n const projected = projectPoint(point, matrix)\n return {\n name: \"g\",\n type: \"element\",\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n cx: projected.x.toString(),\n cy: projected.y.toString(),\n r: \"3\",\n fill: point.color || \"black\",\n },\n },\n ...(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 name: \"polyline\",\n type: \"element\",\n attributes: {\n points: line.points\n .map((p) => projectPoint(p, matrix))\n .map((p) => `${p.x},${p.y}`)\n .join(\" \"),\n fill: \"none\",\n stroke: \"black\",\n \"stroke-width\": (line.points[0].stroke || 1).toString(),\n },\n })),\n // Rectangles\n ...(graphics.rects || []).map((rect) => {\n const projected = projectPoint(rect.center, matrix)\n const scaledWidth = rect.width * matrix.a\n const scaledHeight = rect.height * matrix.d\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n x: (projected.x - scaledWidth / 2).toString(),\n y: (projected.y - scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: Math.abs(scaledHeight).toString(),\n fill: rect.fill || \"none\",\n stroke: rect.stroke || \"black\",\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 cx: projected.x.toString(),\n cy: projected.y.toString(),\n r: scaledRadius.toString(),\n fill: circle.fill || \"none\",\n stroke: circle.stroke || \"black\",\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","import { getGraphicsObjectsFromLogString } from \"./getGraphicsObjectsFromLogString\"\nimport { getSvgFromGraphicsObject } from \"./getSvgFromGraphicsObject\"\n\nexport type { Point, Line, Rect, Circle, GraphicsObject } from \"./types\"\nexport { getGraphicsObjectsFromLogString } from \"./getGraphicsObjectsFromLogString\"\nexport { getSvgFromGraphicsObject } from \"./getSvgFromGraphicsObject\"\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.graphics.title || \"Untitled Graphic\",\n svg: getSvgFromGraphicsObject(obj),\n }))\n}\n"],"mappings":"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","names":["e"]}
|
|
File without changes
|