Vite 8 vanilla page for omarchycn.zacharyzhang.com: kami palette on a 12-col Swiss grid, self-hosted Fusion Pixel zh_hans (OFL shipped), GSAP ScrollSmoother/ScrollTrigger with reduced-motion opt-out, reicon icons, ISO download plus one-click convert command copy, real installer screenshot. shots.mjs is the rendered-state harness; deploy is npx wrangler deploy from site/ (custom domain + workers.dev). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019hLK3wsDuKVAC37GgDqg6H
71 lines
3.0 KiB
JavaScript
71 lines
3.0 KiB
JavaScript
// Rendered-state verification: full-page shots at key widths + interaction states
|
|
import puppeteer from "puppeteer-core";
|
|
import { mkdirSync } from "node:fs";
|
|
|
|
const CHROME = process.env.CHROME;
|
|
const BASE = process.env.BASE ?? "http://localhost:4173";
|
|
if (!CHROME) throw new Error("CHROME env (chrome.exe path) is required");
|
|
|
|
mkdirSync("shots", { recursive: true });
|
|
const browser = await puppeteer.launch({ executablePath: CHROME, headless: "new" });
|
|
|
|
const page = await browser.newPage();
|
|
// Layout passes: reduced motion = static truth of the full page
|
|
await page.emulateMediaFeatures([{ name: "prefers-reduced-motion", value: "reduce" }]);
|
|
for (const w of [1440, 1280, 960, 375]) {
|
|
await page.setViewport({ width: w, height: 900 });
|
|
await page.goto(BASE, { waitUntil: "networkidle0" });
|
|
await page.evaluate(() => document.fonts.ready);
|
|
await new Promise((r) => setTimeout(r, 1400));
|
|
await page.screenshot({ path: `shots/w${w}.png`, fullPage: true });
|
|
console.log(`shot w${w}`);
|
|
}
|
|
|
|
// Motion pass: real scroll, reveals must land every section at opacity 1
|
|
await page.emulateMediaFeatures([{ name: "prefers-reduced-motion", value: "no-preference" }]);
|
|
await page.setViewport({ width: 1440, height: 900 });
|
|
await page.goto(BASE, { waitUntil: "networkidle0" });
|
|
await new Promise((r) => setTimeout(r, 1200));
|
|
await page.evaluate(async () => {
|
|
for (let y = 0; y <= document.body.scrollHeight; y += 300) {
|
|
window.scrollTo(0, y);
|
|
await new Promise((r) => setTimeout(r, 60));
|
|
}
|
|
});
|
|
await new Promise((r) => setTimeout(r, 1200));
|
|
const opacities = await page.evaluate(() =>
|
|
[".shot", ".feat", ".verify h2", ".foot p"].map(
|
|
(s) => `${s}=${getComputedStyle(document.querySelector(s)).opacity}`,
|
|
),
|
|
);
|
|
console.log("post-scroll opacities:", opacities.join(" "));
|
|
await page.screenshot({ path: "shots/motion-bottom.png" });
|
|
|
|
await page.setViewport({ width: 1440, height: 900 });
|
|
await page.goto(BASE, { waitUntil: "networkidle0" });
|
|
await new Promise((r) => setTimeout(r, 1400));
|
|
|
|
await page.keyboard.press("g");
|
|
await new Promise((r) => setTimeout(r, 300));
|
|
await page.screenshot({ path: "shots/grid-overlay.png", fullPage: false });
|
|
console.log("shot grid-overlay");
|
|
await page.keyboard.press("g");
|
|
|
|
const ctx = browser.defaultBrowserContext();
|
|
await ctx.overridePermissions(BASE, ["clipboard-read", "clipboard-write", "clipboard-sanitized-write"]).catch(() => {});
|
|
await page.hover(".cmd");
|
|
await new Promise((r) => setTimeout(r, 200));
|
|
await page.screenshot({ path: "shots/cmd-hover.png" });
|
|
await page.click("#copy-btn");
|
|
await new Promise((r) => setTimeout(r, 400));
|
|
const state = await page.evaluate(() => ({
|
|
label: document.querySelector(".copy-text").textContent,
|
|
clip: navigator.clipboard.readText ? undefined : "n/a",
|
|
}));
|
|
const clip = await page.evaluate(() => navigator.clipboard.readText().catch(() => "READ-FAIL"));
|
|
console.log("copy label:", state.label, "| clipboard:", clip.slice(0, 60) + "…");
|
|
await page.screenshot({ path: "shots/cmd-copied.png" });
|
|
|
|
await browser.close();
|
|
console.log("SHOTS-DONE");
|