scripts/screenshots.ts nimmt Uebersicht und Schluesseldetail bei 1440x900 und 390x844 auf und meldet nebenbei horizontalen Ueberlauf, damit es fuer die Anleitung (#029) und als schneller Layout-Test taugt. Issue #002 ist damit erledigt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
83 lines
2.9 KiB
TypeScript
83 lines
2.9 KiB
TypeScript
/**
|
||
* Screenshots der Oberfläche für Anleitung und Design-Abnahme (#002).
|
||
*
|
||
* pnpm build && pnpm start # erstes Terminal
|
||
* pnpm exec tsx scripts/screenshots.ts # zweites Terminal
|
||
*
|
||
* Umgebung:
|
||
* SSHKV_URL Basis-URL (Standard http://localhost:3400)
|
||
* SSHKV_BILDER Zielordner (Standard docs/anleitung/bilder)
|
||
* SSHKV_SEITEN Kommagetrennte Auswahl der Seitennamen (Standard: alle)
|
||
*
|
||
* Prüft nebenbei, dass keine Seite horizontal scrollt (Design-Vorgabe ab 390 px), und
|
||
* endet dann mit Fehlercode – so taugt das Skript auch als schneller Layout-Test.
|
||
*/
|
||
import { mkdir } from "node:fs/promises";
|
||
import { join } from "node:path";
|
||
import { chromium } from "@playwright/test";
|
||
|
||
const BASIS = (process.env["SSHKV_URL"] ?? "http://localhost:3400").replace(/\/$/, "");
|
||
const ZIEL = process.env["SSHKV_BILDER"] ?? join(process.cwd(), "docs/anleitung/bilder");
|
||
|
||
const SEITEN = [
|
||
{ name: "uebersicht", pfad: "/" },
|
||
{ name: "schluessel-detail", pfad: "/schluessel/beispiel" },
|
||
];
|
||
|
||
const ANSICHTEN = [
|
||
{ name: "desktop", width: 1440, height: 900 },
|
||
{ name: "mobil", width: 390, height: 844 },
|
||
];
|
||
|
||
async function main() {
|
||
const auswahl = process.env["SSHKV_SEITEN"]?.split(",").map((s) => s.trim());
|
||
const seiten = auswahl ? SEITEN.filter((s) => auswahl.includes(s.name)) : SEITEN;
|
||
await mkdir(ZIEL, { recursive: true });
|
||
|
||
const browser = await chromium.launch();
|
||
const fehler: string[] = [];
|
||
try {
|
||
for (const ansicht of ANSICHTEN) {
|
||
const kontext = await browser.newContext({
|
||
viewport: { width: ansicht.width, height: ansicht.height },
|
||
deviceScaleFactor: 1,
|
||
locale: "de-DE",
|
||
timezoneId: "Europe/Berlin",
|
||
colorScheme: "dark",
|
||
});
|
||
const seite = await kontext.newPage();
|
||
for (const s of seiten) {
|
||
const antwort = await seite.goto(`${BASIS}${s.pfad}`, { waitUntil: "networkidle" });
|
||
if (!antwort?.ok()) {
|
||
fehler.push(`${s.pfad}: HTTP ${antwort?.status() ?? "keine Antwort"}`);
|
||
continue;
|
||
}
|
||
// Erst nach dem Laden der selbst gehosteten Schriften fotografieren, sonst
|
||
// stehen Fallback-Schriften im Bild.
|
||
await seite.evaluate(() => document.fonts.ready);
|
||
|
||
const ueberlauf = await seite.evaluate(
|
||
() => document.documentElement.scrollWidth - document.documentElement.clientWidth,
|
||
);
|
||
if (ueberlauf > 0) {
|
||
fehler.push(`${s.pfad} @ ${ansicht.width}px: ${ueberlauf}px horizontaler Überlauf`);
|
||
}
|
||
|
||
const datei = join(ZIEL, `${s.name}-${ansicht.name}.png`);
|
||
await seite.screenshot({ path: datei, fullPage: true });
|
||
console.log(`✓ ${datei}`);
|
||
}
|
||
await kontext.close();
|
||
}
|
||
} finally {
|
||
await browser.close();
|
||
}
|
||
|
||
if (fehler.length > 0) {
|
||
console.error(`\n${fehler.length} Problem(e):\n- ${fehler.join("\n- ")}`);
|
||
process.exitCode = 1;
|
||
}
|
||
}
|
||
|
||
await main();
|