Vier rote Pruefungen -- drei Phantome und ein echtes Gewicht
Weiter durch die rote Liste. Drei der vier Befunde zeigten auf
gesunden Code; die Pruefungen selbst waren seit einem Umbau nicht
nachgezogen worden.
pruef-schritt (2 rot -> 71 gruen statt 47)
Meldete "1 von 6 Kategorien". Die Karte geht seit dem 01.10.2026
gefiltert auf ("zugetragen"), Bloecke ohne solche Punkte werden gar
nicht gezeichnet. Die Pruefung zaehlte danach alle. Schlimmer: Weil
dann kein Block mehr zugeklappt war, lief der Klick auf einen
zugeklappten 30 Sekunden in die Frist und riss den Lauf mit -- 24 von
71 Pruefungen liefen nie. Jetzt wird erst die Vorgabe geprueft (sie
ist eine Zusage), dann auf "Alle" gestellt.
pruef-glocke (1 rot -> 34 gruen)
Meldete "auf der Anmeldeseite steht der Knopf". Gemessen landete sie
auf start.html: Dieselbe Seite war eine Zeile zuvor angemeldet durch
zwanzig Arbeitsseiten gelaufen, und angemeldet fuehrt /workspace/
nicht zur Wand. Jetzt eigener Kontext ohne Keks -- und davor die
Zeile, dass die Wand wirklich erreicht wurde.
pruef-zeichen (1 rot -> 8 gruen)
Meldete content: "·" als Kodierungstruemmer. Die Bytes sind C2 B7,
also korrektes UTF-8; der Mittelpunkt ist ein begruendeter Trennpunkt
(seit 03.10.). Die Regel stammt aus einer Zeit, in der sie selbst
festhielt: "KEINE einzige benutzt ein Zeichen aus diesem Block."
Jetzt eine benannte Ausnahme MIT Veraltungsschutz: Jedes Zeichen
darin muss wirklich vorkommen, sonst wird die Ausnahme rot.
pruef-tempo-workspace (1 rot -> 9 gruen) -- DER ECHTE BEFUND
uebersicht.html 959 KB, bereich.html?b=live 1094 KB bei einer Grenze
von 900. Die Pruefung sagt jetzt auch, WORAN es liegt, und die
Antwort war eindeutig: ZWEI Buehnenbilder auf einer Seite, die eines
zeigt (281 KB studio + 262 KB portal).
Ursache: start.css traegt an body.start::before einen Rueckfall
(studio), und kopf.js setzt `data-buehne` erst, wenn die Seite steht.
Bis dahin ist der Rueckfall geholt -- auf 43 von 45 Seiten.
Jetzt steht die Szene fest im <body>, erzeugt aus bereiche.js
(tools/buehne-festschreiben.mjs, 20 Seiten). bereich.html bedient
fuenf Bretter und kann das nicht; sie bekommt ein kleines Skript
gleich hinter <body>, das die Szene aus `?b=` setzt, bevor gezeichnet
wird. Gemessen: 1094 -> 879 KB, und die Grenze haelt wieder.
DIE ZUORDNUNG STEHT DAMIT AN ZWEI STELLEN. Das ist nur vertretbar,
weil sie nicht auseinanderlaufen kann: pruef-buehnen-fest.mjs (neu,
13 Pruefungen) haelt HTML gegen bereiche.js, prueft die Lage des
Skripts und dass jede genannte Szene eine Regel hat.
Dabei gefunden und berichtigt -- zweimal an mir selbst: Der erste
Entwurf verglich Szenen mit Dateinamen und meldete teamlage.html
("eingang") als Fehler; die Szene gibt es, ihre Regel zeigt nur auf
ein crew-Bild. Und der Lage-Anker suchte `data-buehne`, das Skript
schreibt `dataset.buehne` -- indexOf gab -1, die Rechnung wurde
negativ und meldete "-2276 Zeichen dahinter".
Gegenproben gefahren: Szene verschoben -> rot mit Abstand; Ausnahme
verwaist -> rot; erfundene Szene -> erkannt.
Dazu gruen: css-klassen, workspace-seiten, neue-seiten, haus-trennung,
kopfleiste-farbe.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
/* =====================================================================
|
||||
DIE SZENE STEHT FEST IM DOKUMENT -- und stimmt mit bereiche.js
|
||||
=====================================================================
|
||||
|
||||
WARUM ES DIESE PRUEFUNG GIBT (07.10.2026)
|
||||
|
||||
`pruef-tempo-workspace` meldete zwei Seiten ueber 900 KB. Die
|
||||
Ursache war nicht ein zu grosses Bild, sondern ZWEI: `start.css`
|
||||
traegt an `body.start::before` einen Rueckfall (das Studio-Bild),
|
||||
und `kopf.js` setzt `data-buehne` erst, nachdem die Seite steht.
|
||||
Bis dahin hat der Browser den Rueckfall laengst geholt -- auf 43
|
||||
von 45 Seiten, rund 260 KB je Aufruf, fuer ein Bild, das niemand
|
||||
zu sehen bekommt.
|
||||
|
||||
Seit heute steht die Szene fest im <body>. Damit gibt es die
|
||||
Zuordnung an ZWEI Stellen: in bereiche.js (wo sie gepflegt wird)
|
||||
und im Dokument (wo sie frueh genug ankommt).
|
||||
|
||||
EINE ABSCHRIFT MIT WAECHTER IST ETWAS ANDERES ALS EINE ABSCHRIFT.
|
||||
Diese Datei haelt beide gegeneinander. Wer in bereiche.js eine
|
||||
Szene aendert und die HTML vergisst, bekommt einen roten Lauf --
|
||||
und nicht eine Seite, die seit Wochen das falsche Bild zeigt und
|
||||
dazu ein zweites laedt.
|
||||
|
||||
NICHT BETROFFEN ist bereich.html: Dort haengt die Szene am
|
||||
`?b=`-Parameter (vier verschiedene), sie kann also nicht fest im
|
||||
Dokument stehen. Das steht hier ausdruecklich und nicht als
|
||||
stille Luecke.
|
||||
|
||||
Aufrufen mit: node server/pruef-buehnen-fest.mjs
|
||||
===================================================================== */
|
||||
import { readFileSync, existsSync, readdirSync } from "node:fs";
|
||||
import { join, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const HIER = dirname(fileURLToPath(import.meta.url));
|
||||
const SEITEN = join(HIER, "..", "workspace");
|
||||
|
||||
let geprueft = 0, fehler = 0;
|
||||
const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
|
||||
|
||||
/* ---- Die Zuordnung aus bereiche.js --------------------------------- */
|
||||
const quelle = readFileSync(join(SEITEN, "assets", "js", "bereiche.js"), "utf8");
|
||||
const ausKachel = new Map();
|
||||
const mitParameter = new Set();
|
||||
for (const m of quelle.matchAll(/ziel:\s*'([^']+)'\s*,\s*szene:\s*'([^']+)'/g)) {
|
||||
const [, ziel, szene] = m;
|
||||
if (ziel.includes("?")) { mitParameter.add(ziel.split("?")[0]); continue; }
|
||||
if (ausKachel.has(ziel) && ausKachel.get(ziel) !== szene) ausKachel.set(ziel, null);
|
||||
else if (!ausKachel.has(ziel)) ausKachel.set(ziel, szene);
|
||||
}
|
||||
|
||||
console.log("\n=== 1. Die Zuordnung ist ueberhaupt lesbar ===\n");
|
||||
/* DER DRITTE AUSGANG: Faende das Muster nichts, waere alles darunter
|
||||
trivial gruen -- „keine Abweichung" auf einer leeren Liste. */
|
||||
ok(ausKachel.size >= 15,
|
||||
`${ausKachel.size} Seiten mit fester Szene in bereiche.js gefunden`);
|
||||
ok(mitParameter.size >= 1,
|
||||
`und ${mitParameter.size} Seite(n) mit Parameter, die keine feste haben kann `
|
||||
+ `(${[...mitParameter].join(", ")})`);
|
||||
|
||||
console.log("\n=== 2. Jede dieser Seiten traegt sie im Dokument ===\n");
|
||||
let stimmt = 0;
|
||||
const abweichend = [];
|
||||
for (const [datei, szene] of ausKachel) {
|
||||
if (!szene) continue;
|
||||
const pfad = join(SEITEN, datei);
|
||||
if (!existsSync(pfad)) { abweichend.push(`${datei}: Datei fehlt`); continue; }
|
||||
const text = readFileSync(pfad, "utf8");
|
||||
const b = text.match(/<body class="start"[^>]*>/);
|
||||
const steht = b?.[0].match(/data-buehne="([^"]+)"/)?.[1] ?? null;
|
||||
if (steht === szene) stimmt++;
|
||||
else abweichend.push(`${datei}: Dokument "${steht}" gegen bereiche.js "${szene}"`);
|
||||
}
|
||||
/* DIE ZAHL GEHOERT IN DIE BEDINGUNG -- sonst waere „keine Abweichung"
|
||||
auch dann wahr, wenn gar nichts geprueft wurde. */
|
||||
ok(stimmt >= 15 && abweichend.length === 0,
|
||||
`${stimmt} Seiten tragen ihre Szene fest und richtig`
|
||||
+ (abweichend.length ? `:\n ` + abweichend.slice(0, 6).join("\n ") : ""));
|
||||
|
||||
console.log("\n=== 2b. Und die Seite mit Parameter setzt sie frueh genug ===\n");
|
||||
{
|
||||
/* bereich.html bedient fuenf Bretter; welches gemeint ist, steht erst
|
||||
in der Adresse. Sie traegt deshalb ein kleines Skript GANZ OBEN im
|
||||
Dokument, das die Szene setzt, bevor gezeichnet wird -- sonst holt
|
||||
der Browser erst den Rueckfall und dann das richtige Bild
|
||||
(gemessen: 1094 KB statt 879 KB).
|
||||
|
||||
Die Zuordnung steht damit an zwei Stellen. Hier wird sie
|
||||
gegeneinander gehalten. */
|
||||
const html = readFileSync(join(SEITEN, "bereich.html"), "utf8");
|
||||
const ausSeite = new Map([...html.matchAll(/(\w+):\s*"([a-z-]+)"/g)]
|
||||
.filter((m) => /SZENE\s*=|live|community|technik|schutz|agentur/.test(m[0]))
|
||||
.map((m) => [m[1], m[2]]));
|
||||
const ausBereiche = new Map([...quelle.matchAll(
|
||||
/ziel:\s*'bereich\.html\?b=([a-z]+)'\s*,\s*szene:\s*'([a-z-]+)'/g)]
|
||||
.map((m) => [m[1], m[2]]));
|
||||
|
||||
ok(ausBereiche.size >= 4,
|
||||
`bereiche.js nennt ${ausBereiche.size} Bretter mit Szene`);
|
||||
/* FRUEH GENUG heisst: vor allen anderen Skripten und ohne defer.
|
||||
Ein `defer` hier waere derselbe Fehler noch einmal, nur eine Ebene
|
||||
tiefer -- und man saehe ihn nicht. */
|
||||
/* `dataset.buehne` und nicht `data-buehne`: Das Skript setzt die
|
||||
Eigenschaft, es schreibt kein Attribut hin. Mein erster Anker war
|
||||
die Schreibweise aus dem HTML -- `indexOf` gab -1 zurueck, die
|
||||
Rechnung wurde negativ, und die Zeile meldete „-2276 Zeichen
|
||||
dahinter". Ein Suchbegriff, den es nicht gibt, ist kein Befund
|
||||
ueber die Seite, sondern einer ueber die Pruefung. */
|
||||
const stelleSkript = html.indexOf("dataset.buehne");
|
||||
const stelleBody = html.indexOf("<body");
|
||||
ok(stelleSkript > stelleBody && stelleSkript - stelleBody < 2000,
|
||||
`das Skript steht gleich hinter <body> (${stelleSkript - stelleBody} Zeichen dahinter)`);
|
||||
ok(!/<script[^>]*\bdefer\b[^>]*>[^<]*dataset\.buehne/s.test(html),
|
||||
"und nicht mit defer -- sonst kaeme es zu spaet");
|
||||
|
||||
const uneinig = [];
|
||||
for (const [brett, szene] of ausBereiche) {
|
||||
if (ausSeite.get(brett) !== szene) {
|
||||
uneinig.push(`${brett}: Seite "${ausSeite.get(brett)}" gegen bereiche.js "${szene}"`);
|
||||
}
|
||||
}
|
||||
ok(ausBereiche.size > 0 && uneinig.length === 0,
|
||||
`alle ${ausBereiche.size} Bretter stimmen mit bereiche.js ueberein`
|
||||
+ (uneinig.length ? `: ${uneinig.join(", ")}` : ""));
|
||||
}
|
||||
|
||||
console.log("\n=== 3. Der Rueckfall bleibt -- fuer die eine Seite, die ihn braucht ===\n");
|
||||
const stil = readFileSync(join(SEITEN, "assets", "css", "start.css"), "utf8");
|
||||
ok(/body\.start::before[^}]*background-image:\s*url\(/s.test(stil),
|
||||
"start.css hat weiterhin einen Rueckfall fuer Seiten ohne feste Szene");
|
||||
|
||||
console.log("\n=== 4. Gegenprobe: wuerde eine Abweichung auffallen? ===\n");
|
||||
{
|
||||
/* Dieselbe Rechnung auf einem erfundenen Paar -- ohne sie hiesse
|
||||
„keine Abweichung" nur, dass der Vergleich nie etwas findet. */
|
||||
const erfunden = [["probe.html", "wald", "garage"]];
|
||||
const gefunden = erfunden.filter(([, imDokument, inKachel]) => imDokument !== inKachel);
|
||||
ok(gefunden.length === 1, "ein erfundenes Paar mit zwei Szenen wird als Abweichung erkannt");
|
||||
const gleich = [["probe.html", "wald", "wald"]].filter(([, a, b2]) => a !== b2);
|
||||
ok(gleich.length === 0, "und ein uebereinstimmendes Paar nicht");
|
||||
}
|
||||
|
||||
console.log("\n=== 5. Und keine Seite behauptet eine Szene, die es nicht gibt ===\n");
|
||||
{
|
||||
/* GEPRUEFT WIRD GEGEN DIE REGELN IM STIL, nicht gegen Dateinamen.
|
||||
|
||||
Der erste Entwurf verglich mit `buehne-<name>-breit.webp` und
|
||||
meldete prompt teamlage.html mit „eingang" als Fehler. Der Fund
|
||||
war falsch und der Weg dorthin lehrreich: Die Szene „eingang" gibt
|
||||
es sehr wohl -- ihre Regel zeigt nur auf ein `crew-buehne-*`-Bild,
|
||||
weil diese Seite zum Haus von Team Dogi gehoert. Eine Pruefung,
|
||||
die vom Dateinamen auf die Gueltigkeit schliesst, kennt die halbe
|
||||
Wirklichkeit.
|
||||
|
||||
Die richtige Bedingung ist ohnehin eine andere: Eine Szene ist
|
||||
gueltig, wenn es eine REGEL dafuer gibt. Fehlt sie, greift
|
||||
stillschweigend der Rueckfall -- die Seite zeigt dann ein fremdes
|
||||
Bild und niemand merkt es. Genau davor warnt der Kommentar in
|
||||
teamlage.html. */
|
||||
const stilSzenen = new Set([...stil.matchAll(/data-buehne="([a-z-]+)"/g)].map((m) => m[1]));
|
||||
const unbekannt = [];
|
||||
let mitSzene = 0;
|
||||
for (const n of readdirSync(SEITEN).filter((x) => x.endsWith(".html"))) {
|
||||
const s = readFileSync(join(SEITEN, n), "utf8")
|
||||
.match(/<body[^>]*data-buehne="([^"]+)"/)?.[1];
|
||||
if (!s) continue;
|
||||
mitSzene++;
|
||||
if (!stilSzenen.has(s)) unbekannt.push(`${n}: "${s}" hat keine Regel in start.css`);
|
||||
}
|
||||
ok(stilSzenen.size >= 5,
|
||||
`${stilSzenen.size} Szenen sind im Stil beschrieben (${[...stilSzenen].sort().join(", ")})`);
|
||||
ok(mitSzene >= 15 && unbekannt.length === 0,
|
||||
`alle ${mitSzene} Seiten mit fester Szene nennen eine, die es gibt`
|
||||
+ (unbekannt.length ? `: ${unbekannt.join(", ")}` : ""));
|
||||
/* Gegenprobe: eine erfundene Szene MUSS auffallen. */
|
||||
ok(!stilSzenen.has("gibtesnicht"),
|
||||
"Gegenprobe: eine erfundene Szene stuende nicht in der Liste");
|
||||
}
|
||||
|
||||
console.log(`\n${geprueft} Pruefungen`);
|
||||
console.log(fehler === 0 ? "ALLES IN ORDNUNG" : `${fehler} FEHLER`);
|
||||
process.exit(fehler ? 1 : 0);
|
||||
Reference in New Issue
Block a user