157 lines
6 KiB
JavaScript
157 lines
6 KiB
JavaScript
import { execFileSync } from "node:child_process";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
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");
|
|
|
|
function requestedSlugs(argv) {
|
|
const slugs = new Set();
|
|
for (let index = 2; index < argv.length; index += 1) {
|
|
const argument = argv[index];
|
|
if (argument === "--slug") {
|
|
const slug = argv[index + 1];
|
|
if (!slug) throw new Error("--slug requires a showcase slug");
|
|
slugs.add(slug);
|
|
index += 1;
|
|
} else if (argument.startsWith("--slug=")) {
|
|
slugs.add(argument.slice("--slug=".length));
|
|
} else {
|
|
throw new Error(`Unknown argument: ${argument}`);
|
|
}
|
|
}
|
|
return slugs;
|
|
}
|
|
|
|
if (!fs.existsSync(shotsDir)) {
|
|
fs.mkdirSync(shotsDir, { recursive: true });
|
|
}
|
|
|
|
const targets = [
|
|
{
|
|
url: path.join(rootDir, "public", "work", "thursday-flowers", "index.html"),
|
|
out: path.join(shotsDir, "work-thursday-flowers.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "thursday-flowers", "index.html"),
|
|
altOut: path.join(shotsDir, "work-thursday-flowers-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "muwol-coffee", "index.html"),
|
|
out: path.join(shotsDir, "work-muwol-coffee.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "muwol-coffee", "index.html"),
|
|
altOut: path.join(shotsDir, "work-muwol-coffee-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "pulsegate", "index.html"),
|
|
out: path.join(shotsDir, "work-pulsegate.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "pulsegate", "index.html"),
|
|
altOut: path.join(shotsDir, "work-pulsegate-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "form-architecture", "index.html"),
|
|
out: path.join(shotsDir, "work-form-architecture.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "form-architecture", "index.html"),
|
|
altOut: path.join(shotsDir, "work-form-architecture-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "overtone-sound", "index.html"),
|
|
out: path.join(shotsDir, "work-overtone-sound.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "overtone-sound", "index.html"),
|
|
altOut: path.join(shotsDir, "work-overtone-sound-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "font-foundry", "index.html"),
|
|
out: path.join(shotsDir, "work-font-foundry.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "font-foundry", "index.html"),
|
|
altOut: path.join(shotsDir, "work-font-foundry-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "lumina-optics", "index.html"),
|
|
out: path.join(shotsDir, "work-lumina-optics.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "lumina-optics", "index.html"),
|
|
altOut: path.join(shotsDir, "work-lumina-optics-2.png"),
|
|
webgl: true, // three.js 캔버스 — swiftshader 필요
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "hyang-incense", "index.html"),
|
|
out: path.join(shotsDir, "work-hyang-incense.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "hyang-incense", "index.html"),
|
|
altOut: path.join(shotsDir, "work-hyang-incense-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "synapse-bci", "index.html"),
|
|
out: path.join(shotsDir, "work-synapse-bci.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "synapse-bci", "index.html"),
|
|
altOut: path.join(shotsDir, "work-synapse-bci-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "baekje-celadon", "index.html"),
|
|
out: path.join(shotsDir, "work-baekje-celadon.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "baekje-celadon", "index.html"),
|
|
altOut: path.join(shotsDir, "work-baekje-celadon-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "orbit-aerospace", "index.html"),
|
|
out: path.join(shotsDir, "work-orbit-aerospace.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "orbit-aerospace", "index.html"),
|
|
altOut: path.join(shotsDir, "work-orbit-aerospace-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "gaon-lms", "index.html"),
|
|
out: path.join(shotsDir, "work-gaon-lms.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "gaon-lms", "index.html"),
|
|
altOut: path.join(shotsDir, "work-gaon-lms-2.png"),
|
|
},
|
|
{
|
|
url: path.join(rootDir, "public", "work", "dure-enrollment", "index.html"),
|
|
out: path.join(shotsDir, "work-dure-enrollment.png"),
|
|
altUrl: path.join(rootDir, "public", "work", "dure-enrollment", "index.html"),
|
|
altOut: path.join(shotsDir, "work-dure-enrollment-2.png"),
|
|
},
|
|
];
|
|
|
|
const requested = requestedSlugs(process.argv);
|
|
const slugOf = (target) => path.basename(path.dirname(target.url));
|
|
const known = new Set(targets.map(slugOf));
|
|
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...");
|
|
|
|
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}`,
|
|
]);
|
|
};
|
|
|
|
for (const t of selectedTargets) {
|
|
console.log(`- Capturing ${path.basename(t.out)}`);
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log("✅ All screenshots captured successfully!");
|