/* ===================================================================== pruef-system.mjs — Beweist, dass das Farbsystem eines IST Ein Designsystem ist erst dann eines, wenn eine Änderung an EINER Stelle überall ankommt. Steht die Markenfarbe an 155 Stellen ausgeschrieben, hat man kein System, sondern eine Sammlung von Zufällen, die sich zufällig ähneln. WIE gemessen wird — und warum nicht anders. Der naheliegende Weg wäre, die Variable im laufenden Browser umzustellen und zu schauen, was mitgeht. Er liefert FALSCHE Ergebnisse: Chromium erneuert Teilbäume, die per innerHTML eingefügt wurden — Kopf- und Fusszeile stammen aus wd-core.js — nicht zuverlässig, wenn man eine Variable nachträglich ändert. Auch ein erzwungener Neuberechnungsstoss half nicht. Nachgewiesen am 23.08.2026: Bei Laufzeitänderung blieben 110 Elemente scheinbar "hängen". Lädt man dieselbe Seite dagegen mit bereits geänderter Variable, sind sie orange. Der Fehler lag im Messverfahren, nicht im Farbsystem. Deshalb wird die Variable VOR dem Laden überschrieben. Das entspricht genau dem, was eine Änderung in der CSS-Datei bewirkt — also dem Fall, um den es wirklich geht. ===================================================================== */ import { chromium } from "playwright"; import { createServer } from "node:http"; import { readFileSync, existsSync, readdirSync } from "node:fs"; import { join, extname } from "node:path"; const W = process.cwd(); const T = { ".html": "text/html", ".css": "text/css", ".js": "text/javascript", ".png": "image/png", ".jpg": "image/jpeg", ".svg": "image/svg+xml", ".webp": "image/webp", ".ico": "image/x-icon", ".json": "application/json" }; const srv = createServer((q, r) => { const p = join(W, decodeURIComponent(q.url.split("?")[0])); if (existsSync(p) && !p.endsWith("/")) { r.writeHead(200, { "content-type": T[extname(p)] || "text/plain" }); return r.end(readFileSync(p)); } r.writeHead(404).end(""); }); await new Promise((r) => srv.listen(4332, r)); /* diagnose.html ist bewusst ausgenommen. Sie ist das Werkzeug fuer den Fall, dass die Seite NICHT laeuft, und traegt deshalb alles fest in sich: eigene Farben, eigenes Layout, keine externe CSS- oder JS-Datei, keine Uebersetzung. Genau das ist ihr Zweck -- eine Diagnoseseite, die an derselben kaputten Stilvorlage scheitert wie das Problem, das sie untersuchen soll, waere wertlos. Sie deshalb an den Regeln fuer die eigentliche Seite zu messen, wuerde zwei Meldungen erzeugen, die man auf Dauer wegsieht -- und irgendwann sieht man dann auch eine echte weg. */ const SEITEN = readdirSync(join(W, "webdesign")) .filter((f) => f.endsWith(".html") && f !== "diagnose.html"); const ALT = "127, 208, 232"; // der bisherige Markenton const NEU = "255 120 40"; // drastisch anders, damit nichts untergeht const ergebnisse = []; function pruefe(name, ok, zusatz) { ergebnisse.push({ name, ok }); console.log((ok ? " ok " : " FEHL ") + name + (zusatz ? " -> " + zusatz : "")); } const browser = await chromium.launch(); async function seiteMitFarbe(datei, umstellen) { const s = await browser.newPage({ viewport: { width: 1280, height: 900 } }); await s.route("**/webdesign/admin/**", (r) => r.fulfill({ json: { ok: true, anfragen: [], kunden: [], projekte: [], verlaeufe: [] } })); await s.route("**/webdesign/portal/**", (r) => r.fulfill({ json: { ok: true } })); await s.route("**/webdesign/api-ausweis", (r) => r.fulfill({ json: {} })); await s.addInitScript(({ um, neu }) => { sessionStorage.setItem("wd-sitzung-aktiv", "1"); if (!um) return; const st = document.createElement("style"); st.textContent = ":root{--wd-blau-rgb: " + neu + " !important;}"; document.addEventListener("DOMContentLoaded", () => document.head.appendChild(st)); }, { um: umstellen, neu: NEU }); await s.goto("http://127.0.0.1:4332/webdesign/" + datei); await s.waitForTimeout(420); return s; } console.log("=== Kommt eine Farbänderung überall an? ===\n"); let haengen = 0; let betroffen = 0; let sichtbarGesamt = 0; for (const datei of SEITEN) { /* Erst zählen, wie viele Elemente den Markenton ÜBERHAUPT tragen — sonst wäre "0 hängen geblieben" auch dann erfüllt, wenn die Farbe auf der Seite gar nicht vorkommt. */ const vorher = await seiteMitFarbe(datei, false); const wieviele = await vorher.evaluate((alt) => { let n = 0; for (const el of document.querySelectorAll("*")) { const r = el.getBoundingClientRect(); if (r.width < 1 || r.height < 1) continue; const st = getComputedStyle(el); if ([st.color, st.backgroundColor, st.borderTopColor, st.boxShadow, st.backgroundImage] .join("|").includes(alt)) n++; } return n; }, ALT); await vorher.close(); betroffen += wieviele; const nachher = await seiteMitFarbe(datei, true); const rest = await nachher.evaluate((alt) => { const raus = []; let sichtbar = 0; for (const el of document.querySelectorAll("*")) { const r = el.getBoundingClientRect(); if (r.width < 1 || r.height < 1) continue; sichtbar++; const st = getComputedStyle(el); if ([st.color, st.backgroundColor, st.borderTopColor, st.boxShadow, st.backgroundImage] .join("|").includes(alt)) { raus.push(el.tagName.toLowerCase() + "." + (el.className || "").toString().slice(0, 34)); } } return { raus, sichtbar }; }, ALT); await nachher.close(); sichtbarGesamt += rest.sichtbar; haengen += rest.raus.length; if (rest.raus.length) { console.log(` FEHL ${datei}: ${rest.raus.length} Elemente zeigen weiter den alten Ton`); for (const h of [...new Set(rest.raus)].slice(0, 6)) console.log(" " + h); } } pruefe("die Markenfarbe kommt auf vielen Elementen vor", betroffen > 200, betroffen + " von " + sichtbarGesamt + " sichtbaren Elementen"); pruefe("nach der Umstellung bleibt KEINE Stelle beim alten Ton", haengen === 0, haengen + " hängen geblieben"); /* ---- Die vier Prozessfarben müssen an den Markenfarben hängen ---- */ const s3 = await seiteMitFarbe("ablauf.html", false); const prozess = await s3.evaluate(() => { const w = getComputedStyle(document.documentElement); const vor = ["--wd-p1", "--wd-p2", "--wd-p3", "--wd-p4"].map((v) => w.getPropertyValue(v).trim()); document.documentElement.style.setProperty("--wd-blau-rgb", "255 120 40"); document.documentElement.style.setProperty("--wd-gold-rgb", "40 255 120"); const w2 = getComputedStyle(document.documentElement); const nach = ["--wd-p1", "--wd-p2", "--wd-p3", "--wd-p4"].map((v) => w2.getPropertyValue(v).trim()); return { vor, nach }; }); pruefe("Prozessfarbe 1 (Start) hängt an der Markenfarbe Blau", prozess.vor[0] !== prozess.nach[0], prozess.vor[0] + " -> " + prozess.nach[0]); pruefe("Prozessfarbe 4 (Abschluss) hängt an der Markenfarbe Gold", prozess.vor[3] !== prozess.nach[3], prozess.vor[3] + " -> " + prozess.nach[3]); /* ---- Radien: eine knappe Skala statt Zufallswerten ---- */ const radien = await s3.evaluate(() => { const werte = new Set(); for (const el of document.querySelectorAll("*")) { if (el.getBoundingClientRect().width < 1) continue; const v = getComputedStyle(el).borderTopLeftRadius; if (v && v !== "0px" && v.endsWith("px") && parseFloat(v) < 100) werte.add(v); } return Array.from(werte).sort((a, b) => parseFloat(a) - parseFloat(b)); }); pruefe("Eckenradien folgen einer knappen Skala", radien.length <= 5, radien.join(", ")); await s3.close(); await browser.close(); srv.close(); const f = ergebnisse.filter((e) => !e.ok).length; console.log(`\n===== ${ergebnisse.length - f} bestanden, ${f} fehlgeschlagen =====`); process.exitCode = f ? 1 : 0;