163 lines
4.3 KiB
JavaScript
163 lines
4.3 KiB
JavaScript
import puppeteer from "puppeteer";
|
|
import { createServer } from "http";
|
|
import { readFileSync, existsSync } from "fs";
|
|
import { join, dirname, extname } from "path";
|
|
import { fileURLToPath } from "url";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const root = join(__dirname, "..");
|
|
const distDir = join(root, "dist");
|
|
const PORT = 5174;
|
|
|
|
async function startServer() {
|
|
const httpServer = createServer((req, res) => {
|
|
const decodedUrl = decodeURIComponent(req.url || "/");
|
|
let filePath = join(distDir, decodedUrl === "/" ? "index.html" : decodedUrl);
|
|
|
|
if (!existsSync(filePath) || extname(filePath) === "") {
|
|
filePath = join(distDir, "index.html");
|
|
}
|
|
|
|
if (existsSync(filePath)) {
|
|
const content = readFileSync(filePath);
|
|
const ext = extname(filePath);
|
|
const contentType =
|
|
ext === ".html" ? "text/html" :
|
|
ext === ".js" ? "application/javascript" :
|
|
ext === ".css" ? "text/css" :
|
|
ext === ".json" ? "application/json" :
|
|
ext === ".png" ? "image/png" :
|
|
ext === ".jpg" || ext === ".jpeg" ? "image/jpeg" :
|
|
"application/octet-stream";
|
|
|
|
res.writeHead(200, { "Content-Type": contentType });
|
|
res.end(content);
|
|
} else {
|
|
res.writeHead(404);
|
|
res.end("Not found");
|
|
}
|
|
});
|
|
|
|
await new Promise((resolve, reject) => {
|
|
httpServer.listen(PORT, () => {
|
|
console.log(`Preview server running on http://localhost:${PORT}`);
|
|
resolve();
|
|
});
|
|
httpServer.on("error", reject);
|
|
});
|
|
|
|
return httpServer;
|
|
}
|
|
|
|
async function generatePreview(outputPath, uri, selector) {
|
|
const browser = await puppeteer.launch({
|
|
headless: true,
|
|
args: ["--no-sandbox", "--disable-setuid-sandbox"]
|
|
});
|
|
|
|
try {
|
|
const page = await browser.newPage();
|
|
|
|
await page.setViewport({
|
|
width: 1400,
|
|
height: 2000,
|
|
deviceScaleFactor: 2
|
|
});
|
|
|
|
await page.goto(`http://localhost:${PORT}${uri}`, {
|
|
waitUntil: "networkidle0"
|
|
});
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
await page.waitForSelector(selector, { timeout: 10000 });
|
|
|
|
// Wait for images to load
|
|
await page.evaluate(() => {
|
|
return Promise.all(
|
|
Array.from(document.images).map((img) => {
|
|
if (img.complete) return Promise.resolve();
|
|
return new Promise((resolve) => {
|
|
img.onload = resolve;
|
|
img.onerror = resolve;
|
|
setTimeout(resolve, 3000);
|
|
});
|
|
})
|
|
);
|
|
});
|
|
|
|
// For tank page, ensure stage renders at full size and wait for layers
|
|
if (uri === "/") {
|
|
await page.evaluate(() => {
|
|
const layout = document.querySelector(".layout");
|
|
if (layout) {
|
|
layout.style.width = "1400px";
|
|
layout.style.minWidth = "1200px";
|
|
}
|
|
const stage = document.querySelector(".stage");
|
|
if (stage) {
|
|
stage.style.flex = "1 1 1200px";
|
|
stage.style.width = "1200px";
|
|
stage.style.maxWidth = "1200px";
|
|
}
|
|
});
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
|
|
// Wait for liquid layers to appear and have height
|
|
await page.waitForFunction(
|
|
() => {
|
|
const layers = document.querySelectorAll(".liquid-layer");
|
|
return layers.length > 0 && Array.from(layers).some(l => l.offsetHeight > 0);
|
|
},
|
|
{ timeout: 10000 }
|
|
);
|
|
}
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
|
|
const element = await page.$(selector);
|
|
if (element) {
|
|
await element.screenshot({
|
|
path: outputPath,
|
|
type: "png"
|
|
});
|
|
console.log(`✓ Generated preview: ${outputPath}`);
|
|
}
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
}
|
|
|
|
export async function generateClonesPreview() {
|
|
if (!existsSync(distDir) || !existsSync(join(distDir, "index.html"))) {
|
|
return;
|
|
}
|
|
|
|
let httpServer;
|
|
|
|
try {
|
|
httpServer = await startServer();
|
|
|
|
await generatePreview(
|
|
join(distDir, "vixiclones-preview.png"),
|
|
"/vixiclones",
|
|
".clones-rows"
|
|
);
|
|
|
|
await generatePreview(
|
|
join(distDir, "main-preview.png"),
|
|
"/",
|
|
".stage"
|
|
);
|
|
} catch (error) {
|
|
console.error("Failed to generate previews:", error);
|
|
throw error;
|
|
} finally {
|
|
if (httpServer) {
|
|
await new Promise((resolve) => {
|
|
httpServer.close(() => resolve());
|
|
});
|
|
}
|
|
}
|
|
}
|