pruef-struktur: von zehn Fehlern auf null -- vier davon waren keine
Die dritte und letzte rote Pruefung. Sie meldete zehn Fehler, und
sechs davon waren Fehlalarm.
1. SECHS SEITEN "VON NIRGENDWO VERLINKT"
Gemeldet wurden crew-index, entwicklung, rechte, talente, teamlage und
treff-moderation. Keine davon war verwaist -- man kommt auf jede, indem
man eine KACHEL antippt. Die Kacheln stehen im Server (`ziel:
"talente.html"`), und der wurde nie durchsucht. Der blinde Fleck lag in
der Pruefung.
Abgeleitet statt nachgetragen: Statt die sechs von Hand auszunehmen,
kommen workspace.js und crew-adresse.js als Quellen dazu. Wer morgen
eine Kachel anlegt, ist damit automatisch abgedeckt.
2. FALSCHE ZEILENNUMMERN
Die Ortszeit-Pruefung schnitt Blockkommentare heraus und ersetzte sie
durch EIN Leerzeichen -- ab da zaehlte split("\n") falsch. Gemeldet
wurde "pruef-eskalation.mjs:43", dort steht eine Zeile ueber Kekse. Wer
dem nachgeht, findet nichts, haelt die Pruefung fuer kaputt und sieht
beim naechsten Mal nicht mehr nach.
Mit richtigen Zeilen waren sechs der sieben Funde echt: Sie bauen ihr
Tagesdatum aus toISOString(), also aus UTC. Zwischen Mitternacht und
zwei Uhr liefert das den Vortag -- die Pruefungen waeren tagsueber
gruen und nachts rot gewesen.
Der siebte (pruef-eskalation.mjs:70) rechnet von einem FESTEN Mittag
aus und ist damit sicher; das Muster kann es nur nicht unterscheiden.
Auch umgestellt, damit es nicht beim naechsten Lesen wieder auffaellt.
Neu: server/helfer-tag.mjs -- heuteLokal, tagLokal, tagVon. Nicht aus
workspace.js importiert, weil eine Pruefung, die nur ein Datum
braucht, dafuer keinen Server hochfahren soll. pruef-backstage-import
hatte die Rechnung sogar schon richtig stehen -- und benutzte sie 1270
Zeilen weiter unten trotzdem nicht.
3. TOTES CSS
`.rolle__zeichen .nase` war tot. Beim Nachsehen: `.auge` und `.hell`
daneben auch -- sie wurden nur davon verdeckt, dass die Pruefung den
Klassennamen als TEILZEICHENKETTE gegen den Quelltext haelt, und
"auge" steckt in "Auge", "hell" in "hell". Dutzende Treffer im
Fliesstext deutscher Kommentare. `.fuell` bleibt, die wird benutzt.
Die Schwaeche der Suche steht jetzt an der Stelle notiert.
4. start.css MIT 347 KB
Die Grenze soll verhindern, "dass eine Seite unnoetig viel laedt". Auf
der echten Seite nachgemessen:
start.css auf der Platte 346 KB uebertragen 110 KB (br)
chat.css 59 KB 16 KB
entwicklung.css 33 KB 8 KB
Caddy packt unterwegs. Von start.css sind ausserdem 227 KB KOMMENTAR
(64 %) -- die Pruefung bestrafte genau das, was dieses Haus absichtlich
tut, und haette eine Datei mit 199 KB dichtem CSS durchgewunken.
Dasselbe Argument steht drei Absaetze hoeher schon fuer gestufte
Bilder.
Jetzt zwei Zahlen, weil es zwei Fragen sind: was der BESUCHER laedt
(brotli Stufe 4 -- bei 4 liefert node 111 KB, Caddy 110, jede andere
Stufe waere eine erfundene Zahl) und was ein MENSCH pflegen muss (ohne
Kommentare). Sonst koennte man die erste Zahl klein halten, indem man
immer mehr Prosa schreibt.
MIT GEGENPROBE, in drei Faellen: 281 KB dichtes CSS faellt durch,
404 KB Kommentar gehen durch, und 246 KB sich WIEDERHOLENDES CSS
faellt ebenfalls durch -- sonst koennte man die erste Grenze mit
Wiederholung unterlaufen.
pruef-struktur 0 Fehler (vorher 10)
pruef-eskalation 40, pruef-modi-livecheck 16, pruef-treff-werkzeuge 70,
pruef-backstage-import 160, pruef-css-klassen, pruef-crew-adresse 132
-- alle 0 Fehler
Damit sind alle drei roten Pruefungen gruen.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+127
-2
@@ -30,6 +30,7 @@
|
||||
import { readFileSync, readdirSync, existsSync, statSync } from "node:fs";
|
||||
import { join, dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { brotliCompressSync, constants } from "node:zlib";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const REPO = join(__dirname, "..");
|
||||
@@ -183,8 +184,33 @@ ok(nurPraefix > 0, `${nurPraefix} zusammengesetzte Aufrufe: nur Praefix pruefbar
|
||||
/* ---------- 4. Jede Seite ist erreichbar --------------------------------- */
|
||||
|
||||
console.log(`\n=== Erreichbarkeit ===`);
|
||||
/* WER AUF EINE SEITE ZEIGT, IST NICHT NUR EIN href (16.09.2026).
|
||||
|
||||
Diese Zeile meldete sechs Seiten als "von nirgendwo verlinkt":
|
||||
crew-index, entwicklung, rechte, talente, teamlage und
|
||||
treff-moderation. Keine davon war verwaist -- man kommt auf jede,
|
||||
indem man eine KACHEL antippt. Die Kacheln stehen aber im Server
|
||||
(`ziel: "talente.html"`), und der wurde hier nie durchsucht.
|
||||
|
||||
Eine Pruefung, die seit Wochen sechs Fehler meldet, die keine sind,
|
||||
ist schlimmer als keine: Man liest sie nicht mehr, und dann uebersieht
|
||||
man die siebte, die echt ist. Der blinde Fleck lag in der Pruefung,
|
||||
nicht im Haus.
|
||||
|
||||
ABGELEITET, NICHT NACHGETRAGEN: Statt die sechs von Hand
|
||||
auszunehmen, kommen die Dateien dazu, in denen die Ziele wirklich
|
||||
stehen. Wer morgen eine Kachel anlegt, ist damit automatisch
|
||||
abgedeckt -- und wer eine Seite anlegt, auf die nichts zeigt, faellt
|
||||
weiterhin auf. */
|
||||
const zeigerQuellen = [
|
||||
...quellenMitLinks,
|
||||
/* Die Kachellisten -- dort steht `ziel: "talente.html"`. */
|
||||
{ name: "server/workspace.js", pfad: join(SERVER, "workspace.js") },
|
||||
/* Die Zugangswaende -- crew-index.html wird dort ausgeliefert. */
|
||||
{ name: "server/crew-adresse.js", pfad: join(SERVER, "crew-adresse.js") },
|
||||
];
|
||||
const verlinkt = new Set(["index.html", "start.html"]);
|
||||
for (const { pfad: quelle } of quellenMitLinks) {
|
||||
for (const { pfad: quelle } of zeigerQuellen) {
|
||||
const text = readFileSync(quelle, "utf8");
|
||||
for (const m of text.matchAll(/["'`](?:\/workspace\/)?([a-z0-9-]+\.html)/g)) {
|
||||
verlinkt.add(m[1]);
|
||||
@@ -239,6 +265,23 @@ ok(reste.length === 0, reste.length ? reste.join(" · ") : "keine Entwicklungsre
|
||||
/* ---------- 7. Groesse der Assets ---------------------------------------- */
|
||||
|
||||
console.log(`\n=== Dateigroessen ===`);
|
||||
/** Ist diese Text-Datei zu schwer? Gibt den Grund oder `null`.
|
||||
*
|
||||
* ALS EIGENE FUNKTION, damit die Gegenprobe sie mit erfundenem Inhalt
|
||||
* aufrufen kann. Eine Messung, die nur ueber die echten Dateien
|
||||
* laeuft, ist genau so lange gruen, wie zufaellig keine zu gross ist
|
||||
* -- und beweist nie, dass sie ueberhaupt anschlagen kann. */
|
||||
function textZuSchwer(roh) {
|
||||
const gepackt = Math.round(brotliCompressSync(roh, {
|
||||
params: { [constants.BROTLI_PARAM_QUALITY]: 4 },
|
||||
}).length / 1024);
|
||||
if (gepackt > 200) return `${gepackt} KB uebertragen`;
|
||||
const ohneKommentar = Math.round(
|
||||
roh.toString("utf8").replace(/\/\*[\s\S]*?\*\//g, "").length / 1024);
|
||||
if (ohneKommentar > 200) return `${ohneKommentar} KB ohne Kommentare`;
|
||||
return null;
|
||||
}
|
||||
|
||||
let schwer = [];
|
||||
for (const unter of ["assets/js", "assets/css", "assets/img"]) {
|
||||
const ordner = join(WS, unter);
|
||||
@@ -300,11 +343,81 @@ for (const unter of ["assets/js", "assets/css", "assets/img"]) {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* BEI TEXT MISST DIE ROHE GROESSE DAS FALSCHE (16.09.2026).
|
||||
|
||||
Die Grenze soll verhindern, "dass eine Seite unnoetig viel
|
||||
laedt" -- so steht es oben. Fuer Bilder ist die Datei genau das,
|
||||
was geladen wird. Fuer CSS und JS nicht: Caddy komprimiert sie
|
||||
unterwegs. Nachgemessen auf der echten Seite am 16.09.:
|
||||
|
||||
start.css auf der Platte 346 KB uebertragen 110 KB (br)
|
||||
chat.css 59 KB 16 KB
|
||||
entwicklung.css 33 KB 8 KB
|
||||
|
||||
Die Pruefung meldete start.css mit 347 KB -- davon sind 227 KB
|
||||
KOMMENTAR (64 %). Sie bestrafte damit genau das, was dieses Haus
|
||||
absichtlich tut: jede Entscheidung danebenschreiben. Und sie
|
||||
haette eine Datei mit 199 KB dichtem, unkommentiertem CSS
|
||||
durchgewunken.
|
||||
|
||||
Dasselbe Argument steht drei Absaetze weiter oben schon einmal,
|
||||
fuer die gestuften Bilder: "Bei einem Bild, das in mehreren
|
||||
Groessen vorliegt, misst sie das Falsche."
|
||||
|
||||
JETZT ZWEI ZAHLEN, weil es zwei verschiedene Fragen sind:
|
||||
|
||||
1. WAS DER BESUCHER LAEDT -- brotli, Stufe 4. Die Stufe ist
|
||||
nicht geraten: Bei 4 liefert node 111 KB, Caddy liefert
|
||||
110. Jede andere Stufe waere eine Zahl, die mit der
|
||||
Wirklichkeit nichts zu tun hat.
|
||||
2. WAS EIN MENSCH PFLEGEN MUSS -- die Datei ohne Kommentare.
|
||||
Sonst koennte man die erste Zahl klein halten, indem man
|
||||
immer mehr Prosa schreibt, und niemand merkt, dass das CSS
|
||||
selbst ausgeufert ist. */
|
||||
if (/\.(css|js)$/.test(n)) {
|
||||
const grund = textZuSchwer(readFileSync(p));
|
||||
if (grund) schwer.push(`${unter}/${n} ${grund}`);
|
||||
continue;
|
||||
}
|
||||
if (kb > 200) schwer.push(`${unter}/${n} ${kb} KB`);
|
||||
}
|
||||
}
|
||||
ok(schwer.length === 0, schwer.length ? `ueber 200 KB: ${schwer.join(", ")}` : "keine Datei ueber 200 KB");
|
||||
|
||||
/* GEGENPROBE ZUR GROESSENMESSUNG. Sie ist seit dem 16.09.2026 kein
|
||||
blosser Blick auf die Dateigroesse mehr, sondern packt den Inhalt
|
||||
zusammen -- und eine Messung, die niemand je hat anschlagen sehen,
|
||||
ist eine Behauptung. Drei Faelle, und jeder muss anders ausgehen. */
|
||||
{
|
||||
/* 1. Viel echtes CSS, das sich nicht wegpacken laesst. */
|
||||
let dicht = "";
|
||||
for (let i = 0; i < 9000; i++) {
|
||||
dicht += `.k${i.toString(36)}-${(i * 7919).toString(36)} { color: #${
|
||||
(i * 2654435761 % 16777215).toString(16).padStart(6, "0")}; }\n`;
|
||||
}
|
||||
ok(textZuSchwer(Buffer.from(dicht)) !== null,
|
||||
`dichtes CSS von ${Math.round(dicht.length / 1024)} KB faellt durch `
|
||||
+ `(${textZuSchwer(Buffer.from(dicht))})`);
|
||||
|
||||
/* 2. Dieselbe Menge Text, aber als Prosa im Kommentar -- die packt
|
||||
sich auf ein Zehntel und darf durchgehen. Das ist der ganze
|
||||
Grund fuer die Umstellung. */
|
||||
const prosa = "/* " + "Jede Entscheidung gehoert danebengeschrieben. ".repeat(9000) + " */\n"
|
||||
+ ".a { color: #fff; }\n";
|
||||
ok(textZuSchwer(Buffer.from(prosa)) === null,
|
||||
`${Math.round(prosa.length / 1024)} KB Kommentar gehen durch — sie kosten `
|
||||
+ "den Besucher fast nichts");
|
||||
|
||||
/* 3. UND DIE ZWEITE ZAHL MUSS AUCH ANSCHLAGEN: viel echtes CSS, das
|
||||
sich zwar gut packt (weil es sich wiederholt), aber trotzdem
|
||||
niemand mehr pflegen kann. Ohne diesen Fall koennte man die
|
||||
erste Grenze mit Wiederholung unterlaufen. */
|
||||
const wiederholt = ".gleich { color: #ffffff; padding: 4px; }\n".repeat(6000);
|
||||
ok(textZuSchwer(Buffer.from(wiederholt)) !== null,
|
||||
`${Math.round(wiederholt.length / 1024)} KB sich wiederholendes CSS faellt `
|
||||
+ `ebenfalls durch (${textZuSchwer(Buffer.from(wiederholt))})`);
|
||||
}
|
||||
|
||||
/* ---------- 8. Totes CSS ------------------------------------------------- */
|
||||
|
||||
/* start.css wird auf JEDER Seite geladen und ist 126 KB gross. Was darin
|
||||
@@ -611,7 +724,19 @@ console.log(`\n=== Rechnen die Pruefungen mit Ortszeit? ===`);
|
||||
anzeigen -- eine Warnung, die immer kommt, und die liest bald
|
||||
niemand mehr. */
|
||||
if (datei === "pruef-struktur.mjs") continue;
|
||||
const text = readFileSync(join(SERVER, datei), "utf8").replace(/\/\*[\s\S]*?\*\//g, " ");
|
||||
/* KOMMENTARE RAUS, ZEILEN BEHALTEN (16.09.2026).
|
||||
|
||||
Hier stand `replace(…, " ")` -- ein Blockkommentar ueber zwanzig
|
||||
Zeilen wurde also zu einem Leerzeichen, und ab da zaehlte
|
||||
`split("\n").length` falsch. Gemeldet wurden Zeilennummern, die
|
||||
auf voellig anderen Code zeigten: pruef-eskalation.mjs:43 ist
|
||||
eine Zeile ueber Kekse.
|
||||
|
||||
Wer einer solchen Meldung nachgeht, findet dort nichts, haelt
|
||||
die Pruefung fuer kaputt und sieht beim naechsten Mal gar nicht
|
||||
mehr nach. Jetzt bleibt je Zeile eine Zeile stehen. */
|
||||
const text = readFileSync(join(SERVER, datei), "utf8")
|
||||
.replace(/\/\*[\s\S]*?\*\//g, (m) => m.replace(/[^\n]/g, " "));
|
||||
/* Das Muster ist eng gefasst: NUR toISOString() gefolgt von einem
|
||||
Schnitt auf zehn Zeichen -- also genau die Bildung eines
|
||||
Tagesdatums. `new Date().toISOString()` allein (ein voller
|
||||
|
||||
Reference in New Issue
Block a user