|
|
/**
|
|
|
* __shot — the 2× capture of PLAN-theming §7.2.6 / §7.4.13.
|
|
|
*
|
|
|
* node scripts/__shot.ts <component> <out.png> [url] [--open[=selector]]
|
|
|
*
|
|
|
* The URL is an ARGUMENT, not a constant: the port lived hard-coded at 5173
|
|
|
* here while the probe and the guard already took it, so every call from a
|
|
|
* 5180 session died with ERR_EMPTY_RESPONSE — which is why the step was easy
|
|
|
* to skip (measured 2026-08-23). `--open` clicks the component's trigger
|
|
|
* first, for the components whose surface only exists open.
|
|
|
*/
|
|
|
import { chromium } from 'playwright';
|
|
|
|
|
|
const args = process.argv.slice(2);
|
|
|
const flags = args.filter((a) => a.startsWith('--'));
|
|
|
const [component, out, urlArg] = args.filter((a) => !a.startsWith('--'));
|
|
|
if (!component || !out) throw new Error('usage: <component> <out.png> [url] [--open[=selector]]');
|
|
|
const url = urlArg ?? `http://localhost:5180/uix/components/${component}`;
|
|
|
const openFlag = flags.find((f) => f.startsWith('--open'));
|
|
|
|
|
|
const b = await chromium.launch();
|
|
|
const p = await b.newPage({ viewport: { width: 1280, height: 900 }, deviceScaleFactor: 2 });
|
|
|
try {
|
|
|
await p.goto(url, { waitUntil: 'networkidle', timeout: 20000 });
|
|
|
} catch {
|
|
|
await p.goto(url, { waitUntil: 'load', timeout: 20000 });
|
|
|
}
|
|
|
await p.waitForTimeout(900);
|
|
|
if (openFlag) {
|
|
|
const sel = openFlag.includes('=') ? openFlag.split('=').slice(1).join('=') : `[data-${component}-trigger]`;
|
|
|
const el = p.locator(sel).first();
|
|
|
if (await el.count()) {
|
|
|
await el.click({ timeout: 4000 }).catch(() => {});
|
|
|
await p.waitForTimeout(700);
|
|
|
}
|
|
|
}
|
|
|
const stage = p.locator('[data-uix-stage]').first();
|
|
|
await ((await stage.count()) ? stage : p.locator('body')).screenshot({ path: out });
|
|
|
console.log('shot ->', out);
|
|
|
await b.close();
|