style: format code for better readability

- Format arrays and objects on multiple lines for clarity
- Add trailing commas to arrays and objects
- Format function parameters across multiple lines when needed
- Format string concatenation and template literals consistently
- Format try-catch blocks with proper spacing
This commit is contained in:
2026-05-13 13:46:47 +02:00
parent ac759a60fe
commit 5020d2c288
+150 -46
View File
@@ -164,8 +164,8 @@ if (viewCount === 0) {
"Demo View", "Demo View",
JSON.stringify([ JSON.stringify([
{ url: "https://www.google.com", durationSec: 30, forceDarkMode: false, bakeStyles: false }, { url: "https://www.google.com", durationSec: 30, forceDarkMode: false, bakeStyles: false },
{ url: "https://duck.ai", durationSec: 30, forceDarkMode: false, bakeStyles: false }, { url: "https://duck.ai", durationSec: 30, forceDarkMode: false, bakeStyles: false },
{ url: "https://www.msn.com", durationSec: 30, forceDarkMode: false, bakeStyles: false }, { url: "https://www.msn.com", durationSec: 30, forceDarkMode: false, bakeStyles: false },
]), ]),
"ssr", "ssr",
0, 0,
@@ -229,7 +229,7 @@ function dbDelete(id: string): boolean {
function dbBanIP(ip: string, reason?: string): void { function dbBanIP(ip: string, reason?: string): void {
db.run( db.run(
"INSERT OR REPLACE INTO banned_ips (ip, banned_at, reason, banned_by) VALUES (?, ?, ?, ?)", "INSERT OR REPLACE INTO banned_ips (ip, banned_at, reason, banned_by) VALUES (?, ?, ?, ?)",
[ip, Math.floor(Date.now() / 1000), reason ?? "Manual ban", "admin"] [ip, Math.floor(Date.now() / 1000), reason ?? "Manual ban", "admin"],
); );
} }
@@ -241,7 +241,12 @@ function dbIsBanned(ip: string): boolean {
return db.query("SELECT ip FROM banned_ips WHERE ip = ?").get(ip) != null; return db.query("SELECT ip FROM banned_ips WHERE ip = ?").get(ip) != null;
} }
function dbGetBannedIPs(): Array<{ ip: string; banned_at: number; reason: string; banned_by: string }> { function dbGetBannedIPs(): Array<{
ip: string;
banned_at: number;
reason: string;
banned_by: string;
}> {
return db.query("SELECT * FROM banned_ips ORDER BY banned_at DESC").all() as Array<{ return db.query("SELECT * FROM banned_ips ORDER BY banned_at DESC").all() as Array<{
ip: string; ip: string;
banned_at: number; banned_at: number;
@@ -296,7 +301,7 @@ function deviceTrack(ip: string, viewId: string, viewName: string, userAgent: st
// First user connecting to this view - trigger warmup // First user connecting to this view - trigger warmup
if (!warmedUpViews.has(viewId)) { if (!warmedUpViews.has(viewId)) {
warmedUpViews.add(viewId); warmedUpViews.add(viewId);
warmupView(viewId).catch(err => { warmupView(viewId).catch((err) => {
console.error(`[warmup] Failed to warm up view ${viewId}:`, err); console.error(`[warmup] Failed to warm up view ${viewId}:`, err);
}); });
} }
@@ -321,7 +326,7 @@ function devicesSnapshot(): DeviceEntry[] {
// ═══════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════
function getDebugData() { function getDebugData() {
const viewsDebug = viewCacheAll().map(v => { const viewsDebug = viewCacheAll().map((v) => {
const idx = getCurrentURLIndex(v); const idx = getCurrentURLIndex(v);
return { return {
id: v.id, id: v.id,
@@ -336,7 +341,7 @@ function getDebugData() {
currentUrl: v.urls[idx]?.url ?? "", currentUrl: v.urls[idx]?.url ?? "",
remainingSec: getRemainingSec(v), remainingSec: getRemainingSec(v),
totalCycleSec: v.urls.reduce((s, u) => s + u.durationSec, 0), totalCycleSec: v.urls.reduce((s, u) => s + u.durationSec, 0),
cacheEntries: cacheStats().filter(c => c.viewId === v.id), cacheEntries: cacheStats().filter((c) => c.viewId === v.id),
}; };
}); });
@@ -438,7 +443,9 @@ class PagePool {
return true; return true;
} catch (err) { } catch (err) {
console.warn(`[page-pool] resetPage failed, discarding page: ${err}`); console.warn(`[page-pool] resetPage failed, discarding page: ${err}`);
try { await page.close(); } catch {} try {
await page.close();
} catch {}
return false; return false;
} }
} }
@@ -513,10 +520,7 @@ let pagePool: PagePool;
// WEBSOCKET DEBUG CLIENTS // WEBSOCKET DEBUG CLIENTS
// ═══════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════
const debugClients = new Map< const debugClients = new Map<any, { interval: number; timer: ReturnType<typeof setInterval> }>();
any,
{ interval: number; timer: ReturnType<typeof setInterval> }
>();
const DEBUG_DEFAULT_INTERVAL_MS = 1000; const DEBUG_DEFAULT_INTERVAL_MS = 1000;
const DEBUG_MIN_INTERVAL_MS = 100; const DEBUG_MIN_INTERVAL_MS = 100;
@@ -668,12 +672,19 @@ async function renderViewToCache(view: View, urlIndex: number, key: string): Pro
let body: string; let body: string;
if (view.method === "mjpeg") { if (view.method === "mjpeg") {
const jpeg = await renderScreenshotFrame( const jpeg = await renderScreenshotFrame(
urlItem.url, view.viewportWidth, view.viewportHeight, forceDarkMode, urlItem.url,
view.viewportWidth,
view.viewportHeight,
forceDarkMode,
); );
body = jpeg.toString("base64"); body = jpeg.toString("base64");
} else { } else {
body = await renderSSR( body = await renderSSR(
urlItem.url, view.viewportWidth, view.viewportHeight, forceDarkMode, bakeStyles, urlItem.url,
view.viewportWidth,
view.viewportHeight,
forceDarkMode,
bakeStyles,
); );
} }
@@ -823,7 +834,8 @@ function stripScriptTags(html: string): string {
// ── Recursive @import resolver (max 3 levels deep) ── // ── Recursive @import resolver (max 3 levels deep) ──
async function resolveCSSImports(cssText: string, baseUrl: string, depth = 0): Promise<string> { async function resolveCSSImports(cssText: string, baseUrl: string, depth = 0): Promise<string> {
if (depth > 3) return cssText; if (depth > 3) return cssText;
const importRe = /@import\s+(?:url\s*\(\s*["']?([^)"']+)["']?\s*\)|["']([^"']+)["'])\s*([^;]*);/gi; const importRe =
/@import\s+(?:url\s*\(\s*["']?([^)"']+)["']?\s*\)|["']([^"']+)["'])\s*([^;]*);/gi;
const replacements: Array<{ match: string; resolved: string }> = []; const replacements: Array<{ match: string; resolved: string }> = [];
let m: RegExpExecArray | null; let m: RegExpExecArray | null;
@@ -839,7 +851,10 @@ async function resolveCSSImports(cssText: string, baseUrl: string, depth = 0): P
if (!res.ok) throw new Error("failed"); if (!res.ok) throw new Error("failed");
let imported = await res.text(); let imported = await res.text();
imported = await resolveCSSImports(imported, importUrl, depth + 1); imported = await resolveCSSImports(imported, importUrl, depth + 1);
replacements.push({ match: m[0], resolved: "/* begin " + importUrl + " */\n" + imported + "\n/* end " + importUrl + " */" }); replacements.push({
match: m[0],
resolved: "/* begin " + importUrl + " */\n" + imported + "\n/* end " + importUrl + " */",
});
} catch { } catch {
replacements.push({ match: m[0], resolved: "/* unresolved import: " + importUrl + " */" }); replacements.push({ match: m[0], resolved: "/* unresolved import: " + importUrl + " */" });
} }
@@ -865,40 +880,117 @@ async function bakeComputedStyles(page: Page): Promise<void> {
await page.evaluate((): void => { await page.evaluate((): void => {
const computedProperties = [ const computedProperties = [
// Layout // Layout
"display", "position", "top", "right", "bottom", "left", "display",
"width", "height", "min-width", "min-height", "max-width", "max-height", "position",
"margin", "margin-top", "margin-right", "margin-bottom", "margin-left", "top",
"padding", "padding-top", "padding-right", "padding-bottom", "padding-left", "right",
"bottom",
"left",
"width",
"height",
"min-width",
"min-height",
"max-width",
"max-height",
"margin",
"margin-top",
"margin-right",
"margin-bottom",
"margin-left",
"padding",
"padding-top",
"padding-right",
"padding-bottom",
"padding-left",
// Flex/Grid // Flex/Grid
"flex", "flex-direction", "flex-wrap", "flex-flow", "flex-grow", "flex-shrink", "flex-basis", "flex",
"justify-content", "align-items", "align-content", "align-self", "gap", "row-gap", "column-gap", "flex-direction",
"grid", "grid-template", "grid-template-columns", "grid-template-rows", "grid-area", "flex-wrap",
"flex-flow",
"flex-grow",
"flex-shrink",
"flex-basis",
"justify-content",
"align-items",
"align-content",
"align-self",
"gap",
"row-gap",
"column-gap",
"grid",
"grid-template",
"grid-template-columns",
"grid-template-rows",
"grid-area",
// Box model // Box model
"box-sizing", "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", "box-sizing",
"border-top-style", "border-right-style", "border-bottom-style", "border-left-style", "border-top-width",
"border-top-color", "border-right-color", "border-bottom-color", "border-left-color", "border-right-width",
"border-top-left-radius", "border-top-right-radius", "border-bottom-right-radius", "border-bottom-left-radius", "border-bottom-width",
"border-left-width",
"border-top-style",
"border-right-style",
"border-bottom-style",
"border-left-style",
"border-top-color",
"border-right-color",
"border-bottom-color",
"border-left-color",
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius",
// Colors & Background // Colors & Background
"color", "background-color", "background-image", "background-size", "background-position", "color",
"background-repeat", "background-attachment", "background-clip", "background-origin", "background-color",
"background-image",
"background-size",
"background-position",
"background-repeat",
"background-attachment",
"background-clip",
"background-origin",
// Typography // Typography
"font-family", "font-size", "font-weight", "font-style", "font-variant", "font-family",
"line-height", "text-align", "text-decoration-line", "text-decoration-color", "font-size",
"text-transform", "letter-spacing", "word-spacing", "font-weight",
"white-space", "overflow-wrap", "word-break", "font-style",
"font-variant",
"line-height",
"text-align",
"text-decoration-line",
"text-decoration-color",
"text-transform",
"letter-spacing",
"word-spacing",
"white-space",
"overflow-wrap",
"word-break",
// Visual // Visual
"opacity", "visibility", "z-index", "overflow-x", "overflow-y", "opacity",
"box-shadow", "text-shadow", "transform", "transform-origin", "visibility",
"z-index",
"overflow-x",
"overflow-y",
"box-shadow",
"text-shadow",
"transform",
"transform-origin",
// List/Table // List/Table
"list-style-type", "list-style-position", "border-collapse", "border-spacing", "list-style-type",
"list-style-position",
"border-collapse",
"border-spacing",
// Cursor/pointer // Cursor/pointer
"cursor", "pointer-events", "cursor",
"pointer-events",
]; ];
// Cache of default computed values keyed by tagName // Cache of default computed values keyed by tagName
const defaultCache = new Map<string, Map<string, string>>(); const defaultCache = new Map<string, Map<string, string>>();
const hiddenContainer = document.createElement("div"); const hiddenContainer = document.createElement("div");
hiddenContainer.style.cssText = "position:absolute;visibility:hidden;pointer-events:none;top:-9999px;"; hiddenContainer.style.cssText =
"position:absolute;visibility:hidden;pointer-events:none;top:-9999px;";
document.body.appendChild(hiddenContainer); document.body.appendChild(hiddenContainer);
function getTagDefaults(tag: string): Map<string, string> { function getTagDefaults(tag: string): Map<string, string> {
@@ -913,7 +1005,9 @@ async function bakeComputedStyles(page: Page): Promise<void> {
cache.set(prop, cs.getPropertyValue(prop)); cache.set(prop, cs.getPropertyValue(prop));
} }
el.remove(); el.remove();
} catch { /* unknown tag, cache will be empty */ } } catch {
/* unknown tag, cache will be empty */
}
defaultCache.set(tag, cache); defaultCache.set(tag, cache);
return cache; return cache;
} }
@@ -921,7 +1015,8 @@ async function bakeComputedStyles(page: Page): Promise<void> {
function shouldBake(value: string, defaultValue: string): boolean { function shouldBake(value: string, defaultValue: string): boolean {
if (!value) return false; if (!value) return false;
// Skip browser keywords that cannot be serialized as inline style values // Skip browser keywords that cannot be serialized as inline style values
if (value === "initial" || value === "inherit" || value === "unset" || value === "revert") return false; if (value === "initial" || value === "inherit" || value === "unset" || value === "revert")
return false;
return value !== defaultValue; return value !== defaultValue;
} }
@@ -931,7 +1026,8 @@ async function bakeComputedStyles(page: Page): Promise<void> {
if (el === hiddenContainer) continue; if (el === hiddenContainer) continue;
// Skip non-visual tags // Skip non-visual tags
const tag = el.tagName.toLowerCase(); const tag = el.tagName.toLowerCase();
if (["script", "style", "meta", "link", "noscript", "template", "head", "html"].includes(tag)) continue; if (["script", "style", "meta", "link", "noscript", "template", "head", "html"].includes(tag))
continue;
const computed = window.getComputedStyle(el); const computed = window.getComputedStyle(el);
const defaults = getTagDefaults(tag); const defaults = getTagDefaults(tag);
@@ -1081,7 +1177,7 @@ async function inlineAllResources(page: Page, html: string): Promise<string> {
html = html.replace( html = html.replace(
linkRegex, linkRegex,
`<style${mediaAttr}>/* inlined: ${css.url} */\n${resolvedCSS}\n</style>` `<style${mediaAttr}>/* inlined: ${css.url} */\n${resolvedCSS}\n</style>`,
); );
} }
for (const img of payload.images) { for (const img of payload.images) {
@@ -1498,7 +1594,9 @@ const server = Bun.serve<{ interval: number }>({
}, interval); }, interval);
debugClients.set(ws, { interval, timer }); debugClients.set(ws, { interval, timer });
// Send initial payload immediately // Send initial payload immediately
try { ws.send(JSON.stringify(getDebugData())); } catch {} try {
ws.send(JSON.stringify(getDebugData()));
} catch {}
}, },
message(ws, msg) { message(ws, msg) {
try { try {
@@ -1510,15 +1608,21 @@ const server = Bun.serve<{ interval: number }>({
clearInterval(client.timer); clearInterval(client.timer);
client.interval = interval; client.interval = interval;
client.timer = setInterval(() => { client.timer = setInterval(() => {
try { ws.send(JSON.stringify(getDebugData())); } catch { try {
ws.send(JSON.stringify(getDebugData()));
} catch {
clearInterval(client.timer); clearInterval(client.timer);
debugClients.delete(ws); debugClients.delete(ws);
} }
}, interval); }, interval);
// Push immediately after rate change // Push immediately after rate change
try { ws.send(JSON.stringify(getDebugData())); } catch {} try {
ws.send(JSON.stringify(getDebugData()));
} catch {}
} }
} catch { /* ignore malformed messages */ } } catch {
/* ignore malformed messages */
}
}, },
close(ws) { close(ws) {
const client = debugClients.get(ws); const client = debugClients.get(ws);