feat: strengthen design skill and refresh all showcases
Some checks failed
ci / build (push) Has been cancelled

This commit is contained in:
Yun Chan 2026-09-12 18:16:33 +09:00
parent 69e5cc1efd
commit e09d4efb1c
257 changed files with 8196 additions and 2374 deletions

View file

@ -8,10 +8,19 @@ import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import {
collectPageFailures,
prepareStillPage,
resolveChrome,
routeForFile,
startPublicServer,
waitForStableVisual,
} from "./capture-stable.mjs";
const here = path.dirname(url.fileURLToPath(import.meta.url));
const root = path.resolve(here, "..");
const shots = path.join(root, "src", "assets", "shots");
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const publicRoot = path.join(root, "public");
function requestedSlugs(argv) {
const slugs = new Set();
@ -31,17 +40,6 @@ function requestedSlugs(argv) {
return slugs;
}
const CHROME = [
"C:/Program Files/Google/Chrome/Application/chrome.exe",
"C:/Program Files (x86)/Google/Chrome/Application/chrome.exe",
process.env.CHROME_PATH,
].filter(Boolean).find((p) => fs.existsSync(p));
if (!CHROME) {
console.error("크롬을 찾지 못했다.");
process.exit(2);
}
const JOBS = [
{
slug: "rfs-cfd",
@ -68,42 +66,56 @@ const unknown = [...requested].filter((slug) => !known.has(slug));
if (unknown.length) throw new Error(`Unknown showcase slug(s): ${unknown.join(", ")}`);
const selectedJobs = requested.size ? JOBS.filter((job) => requested.has(job.slug)) : JOBS;
const browser = await puppeteer.launch({
executablePath: CHROME,
headless: "new",
args: [
"--no-sandbox",
"--use-angle=swiftshader",
"--enable-unsafe-swiftshader",
"--force-device-scale-factor=1",
],
defaultViewport: { width: 1440, height: 900 },
});
const server = await startPublicServer(publicRoot);
let browser;
for (const job of selectedJobs) {
const page = await browser.newPage();
await page.setCacheEnabled(false);
const file = path.join(root, "public/work", job.slug, "index.html");
await page.goto(url.pathToFileURL(file).href, { waitUntil: "networkidle0" });
await page.evaluate(() => document.fonts.ready);
await sleep(job.settle);
try {
browser = await puppeteer.launch({
executablePath: resolveChrome(),
headless: "new",
args: [
"--no-sandbox",
"--use-angle=swiftshader",
"--enable-unsafe-swiftshader",
"--force-device-scale-factor=1",
],
defaultViewport: { width: 1440, height: 900, deviceScaleFactor: 1 },
});
const main = path.join(shots, `work-${job.slug}.png`);
await page.screenshot({ path: main });
await page.screenshot({ path: path.join(root, "public/work", job.slug, "og.png") });
for (const job of selectedJobs) {
const page = await browser.newPage();
const failures = collectPageFailures(page, server.origin);
try {
await prepareStillPage(page);
const file = path.join(publicRoot, "work", job.slug, "index.html");
const response = await page.goto(server.origin + routeForFile(publicRoot, file), {
waitUntil: "domcontentloaded",
timeout: 30000,
});
if (!response?.ok()) throw new Error(`${job.slug} returned ${response?.status() ?? "no response"}`);
await waitForStableVisual(page, { settleMs: job.settle });
if (failures.length) throw new Error(failures.join(" · "));
await page.evaluate((sel) => {
document.querySelector(sel)?.scrollIntoView({ behavior: "instant", block: "start" });
}, job.second.scrollTo);
await sleep(job.second.wait);
const main = path.join(shots, `work-${job.slug}.png`);
await page.screenshot({ path: main });
await page.screenshot({ path: path.join(publicRoot, "work", job.slug, "og.png") });
const alt = path.join(shots, `work-${job.slug}-2.png`);
await page.screenshot({ path: alt });
await page.close();
await page.evaluate((selector) => {
document.querySelector(selector)?.scrollIntoView({ behavior: "auto", block: "start" });
}, job.second.scrollTo);
await new Promise((resolve) => setTimeout(resolve, job.second.wait));
const kb = (p) => Math.round(fs.statSync(p).size / 1024);
console.log(`${job.slug}: 본컷 ${kb(main)}KB · 2컷 ${kb(alt)}KB`);
const alt = path.join(shots, `work-${job.slug}-2.png`);
await page.screenshot({ path: alt });
const kb = (filePath) => Math.round(fs.statSync(filePath).size / 1024);
console.log(`${job.slug}: 본컷 ${kb(main)}KB · 2컷 ${kb(alt)}KB`);
} finally {
await page.close();
}
}
} finally {
if (browser) await browser.close();
await server.close();
}
await browser.close();
console.log("촬영 완료");
console.log("정착 상태 촬영 완료");