feat(*): svelte 5 panel view sharing the gateway ui, obsidian theme, preview and tests

This commit is contained in:
hh
2026-08-29 18:30:31 +02:00
parent a1bf4db905
commit 04400c5076
33 changed files with 3378 additions and 1803 deletions
+81
View File
@@ -0,0 +1,81 @@
// bun preview/shot.ts <out.png> <url> [width] [height]
// Headless Chrome over CDP: the preview server must be running.
const [out, url, w = "340", h = "720"] = process.argv.slice(2);
const port = 9334;
const proc = Bun.spawn(
[
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"--headless=new",
"--disable-gpu",
"--hide-scrollbars",
`--remote-debugging-port=${port}`,
`--window-size=${w},${h}`,
"--user-data-dir=/tmp/beaver-preview-chrome",
"about:blank",
],
{ stderr: "ignore", stdout: "ignore" }
);
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
let targets: { type: string; webSocketDebuggerUrl: string }[] = [];
for (let i = 0; i < 40; i += 1) {
try {
// biome-ignore lint/performance/noAwaitInLoops: polling until Chrome is up
targets = await (await fetch(`http://127.0.0.1:${port}/json`)).json();
if (targets.length) {
break;
}
} catch {
/* not up yet */
}
await wait(250);
}
const page = targets.find((t) => t.type === "page");
if (!page) {
proc.kill();
throw new Error("no page target");
}
const ws = new WebSocket(page.webSocketDebuggerUrl);
await new Promise((resolve) => {
ws.onopen = resolve;
});
let id = 0;
const pending = new Map<number, (v: { result?: { data?: string } }) => void>();
ws.onmessage = (m) => {
const d = JSON.parse(String(m.data));
if (d.id && pending.has(d.id)) {
pending.get(d.id)?.(d);
pending.delete(d.id);
}
};
const send = (method: string, params: Record<string, unknown> = {}) =>
new Promise<{ result?: { data?: string } }>((resolve) => {
id += 1;
pending.set(id, resolve);
ws.send(JSON.stringify({ id, method, params }));
});
await send("Emulation.setDeviceMetricsOverride", {
deviceScaleFactor: 2,
height: Number(h),
mobile: Number(w) < 500,
width: Number(w),
});
await send("Page.enable");
await send("Page.navigate", { url });
await wait(2500);
if (process.env.EVAL) {
const evaluated = await send("Runtime.evaluate", {
expression: process.env.EVAL,
returnByValue: true,
});
console.log(
JSON.stringify(
(evaluated.result as { result?: { value?: unknown } }).result?.value
)
);
await wait(400);
}
const shot = await send("Page.captureScreenshot", { format: "png" });
await Bun.write(out, Buffer.from(shot.result?.data ?? "", "base64"));
console.log(`wrote ${out}`);
ws.close();
proc.kill();