feat: strengthen design skill and refresh all showcases
Some checks failed
ci / build (push) Has been cancelled
Some checks failed
ci / build (push) Has been cancelled
This commit is contained in:
parent
69e5cc1efd
commit
e09d4efb1c
257 changed files with 8196 additions and 2374 deletions
|
|
@ -1,12 +1,21 @@
|
|||
import { execFileSync } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import puppeteer from "puppeteer-core";
|
||||
|
||||
import {
|
||||
collectPageFailures,
|
||||
prepareStillPage,
|
||||
resolveChrome,
|
||||
routeForFile,
|
||||
startPublicServer,
|
||||
waitForStableVisual,
|
||||
} from "./capture-stable.mjs";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const rootDir = path.resolve(__dirname, "..");
|
||||
const chromePath = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
|
||||
const shotsDir = path.join(rootDir, "src", "assets", "shots");
|
||||
const publicRoot = path.join(rootDir, "public");
|
||||
|
||||
function requestedSlugs(argv) {
|
||||
const slugs = new Set();
|
||||
|
|
@ -110,6 +119,24 @@ const targets = [
|
|||
altUrl: path.join(rootDir, "public", "work", "dure-enrollment", "index.html"),
|
||||
altOut: path.join(shotsDir, "work-dure-enrollment-2.png"),
|
||||
},
|
||||
{
|
||||
url: path.join(rootDir, "public", "work", "cheongon-care", "index.html"),
|
||||
out: path.join(shotsDir, "work-cheongon-care.png"),
|
||||
altUrl: path.join(rootDir, "public", "work", "cheongon-care", "protocol", "index.html"),
|
||||
altOut: path.join(shotsDir, "work-cheongon-care-2.png"),
|
||||
},
|
||||
{
|
||||
url: path.join(rootDir, "public", "work", "cask-archive", "index.html"),
|
||||
out: path.join(shotsDir, "work-cask-archive.png"),
|
||||
altUrl: path.join(rootDir, "public", "work", "cask-archive", "docent", "index.html"),
|
||||
altOut: path.join(shotsDir, "work-cask-archive-2.png"),
|
||||
},
|
||||
{
|
||||
url: path.join(rootDir, "public", "work", "materia-interior", "index.html"),
|
||||
out: path.join(shotsDir, "work-materia-interior.png"),
|
||||
altUrl: path.join(rootDir, "public", "work", "materia-interior", "projects", "hannam-duplex", "index.html"),
|
||||
altOut: path.join(shotsDir, "work-materia-interior-2.png"),
|
||||
},
|
||||
];
|
||||
|
||||
const requested = requestedSlugs(process.argv);
|
||||
|
|
@ -119,39 +146,49 @@ const unknown = [...requested].filter((slug) => !known.has(slug));
|
|||
if (unknown.length) throw new Error(`Unknown showcase slug(s): ${unknown.join(", ")}`);
|
||||
const selectedTargets = requested.size ? targets.filter((target) => requested.has(slugOf(target))) : targets;
|
||||
|
||||
console.log("📸 Capturing high-resolution screenshots...");
|
||||
console.log("📸 Capturing settled, high-resolution screenshots...");
|
||||
|
||||
const shot = (t, url, out) => {
|
||||
const flags = t.webgl
|
||||
? ["--no-sandbox", "--use-angle=swiftshader"] // --disable-gpu 는 WebGL 을 죽인다
|
||||
: ["--disable-gpu", "--no-sandbox"];
|
||||
execFileSync(chromePath, [
|
||||
"--headless=new",
|
||||
"--hide-scrollbars",
|
||||
...flags,
|
||||
"--force-device-scale-factor=1",
|
||||
"--window-size=1440,900",
|
||||
`--screenshot=${out}`,
|
||||
`file://${url}`,
|
||||
]);
|
||||
};
|
||||
const server = await startPublicServer(publicRoot);
|
||||
let browser;
|
||||
|
||||
for (const t of selectedTargets) {
|
||||
console.log(`- Capturing ${path.basename(t.out)}`);
|
||||
async function shot(file, output) {
|
||||
const page = await browser.newPage();
|
||||
const failures = collectPageFailures(page, server.origin);
|
||||
try {
|
||||
shot(t, t.url, t.out);
|
||||
} catch (e) {
|
||||
console.error(`Error capturing ${t.out}:`, e.message);
|
||||
}
|
||||
|
||||
if (t.altOut) {
|
||||
console.log(`- Capturing ${path.basename(t.altOut)}`);
|
||||
try {
|
||||
shot(t, t.altUrl, t.altOut);
|
||||
} catch (e) {
|
||||
console.error(`Error capturing ${t.altOut}:`, e.message);
|
||||
}
|
||||
await prepareStillPage(page);
|
||||
await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
|
||||
const route = routeForFile(publicRoot, file);
|
||||
const response = await page.goto(server.origin + route, { waitUntil: "domcontentloaded", timeout: 30000 });
|
||||
if (!response?.ok()) throw new Error(`${route} returned ${response?.status() ?? "no response"}`);
|
||||
await waitForStableVisual(page);
|
||||
if (failures.length) throw new Error(failures.join(" · "));
|
||||
await page.screenshot({ path: output, type: "png", fullPage: false });
|
||||
const size = Math.round(fs.statSync(output).size / 1024);
|
||||
console.log(`CAPTURE ${path.basename(output)} (${size}KB)`);
|
||||
} finally {
|
||||
await page.close();
|
||||
}
|
||||
}
|
||||
|
||||
console.log("✅ All screenshots captured successfully!");
|
||||
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 },
|
||||
});
|
||||
for (const target of selectedTargets) {
|
||||
await shot(target.url, target.out);
|
||||
if (target.altOut) await shot(target.altUrl, target.altOut);
|
||||
}
|
||||
} finally {
|
||||
if (browser) await browser.close();
|
||||
await server.close();
|
||||
}
|
||||
|
||||
console.log("✅ All requested screenshots captured after visual settling.");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue