diff --git a/server/pruef-css-klassen.mjs b/server/pruef-css-klassen.mjs index 57e92de6..45a65aa7 100644 --- a/server/pruef-css-klassen.mjs +++ b/server/pruef-css-klassen.mjs @@ -899,5 +899,90 @@ function formfehler(text) { : `Gegenprobe: alle ${proben.length} Faelle richtig eingeordnet`); } +/* ==== ZWEI GRUNDREGELN, EIN NAME, ZWEI BAUARTEN ===================== + + Gebaut am 28.09.2026 fuer `reaktion.css`, wo `.stufen` zweimal + stand: einmal fuer die Stufenleiter der Spenden (`display: grid`), + 600 Zeilen spaeter fuer die Chat-Leiste (`display: flex`). Die + spaetere gewinnt -- und die Stufenleiter stellte ihre drei Stufen + nebeneinander, 572 Pixel in einer 327 Pixel schmalen Spalte, mit + waagerechter Rollleiste. Auf dem Bildschirmfoto sah das aus wie + ein Platzproblem. + + AB JETZT FUER ALLE STILVORLAGEN. Eine Wache, die nur eine Datei + ansieht, findet genau die Fehler dieser einen Datei -- und der + zweite Fund lag in gate.css. + + GEZAEHLT WIRD NUR, WAS SICH WIDERSPRECHEN KANN: + - Die Auswahl muss GENAU die Klasse sein. `.saal .pult { … }` + ist dieselbe Klasse in einem Zusammenhang, kein zweites + Bauteil. + - Regeln in einer Medienabfrage zaehlen nicht -- sie sind per + Definition Varianten fuer eine andere Umgebung. + - `display: none` zaehlt nicht. „Erst versteckt, dann gezeigt" + ist das haeufigste Paar im Haus; wer es meldet, baut eine + Warnung, die immer kommt. */ +{ + const ordner = join(HIER, "..", "workspace", "assets", "css"); + const ohneMedien = (t) => t.replace( + /@media[^{]*\{(?:[^{}]|\{[^{}]*\})*\}/g, + (m) => m.replace(new RegExp("[^" + String.fromCharCode(10) + "]", "g"), " ")); + const positiv = (w) => w && w !== "none" && !/^none\b/.test(w); + /* LOOKBEHIND STATT VERBRAUCHEN: Mit `(^|[};])` frisst der erste + Treffer die Klammer, die der naechste als Anfang braeuchte -- + `.a { … } .a { … }` liefert dann nur EINEN Treffer, und genau + der Fall, um den es geht, faellt durch. */ + const grundregeln = (roh) => { + const raus = {}; + const text = ohneMedien(roh.replace(/\/\*[\s\S]*?\*\//g, + (m) => m.replace(new RegExp("[^" + String.fromCharCode(10) + "]", "g"), " "))); + for (const m of text.matchAll( + /(?:^|(?<=[};]))\s*(\.(-?[a-zA-Z_][a-zA-Z0-9_-]*))\s*\{([^{}]*)\}/g)) { + const w = (m[3].match(/(?:^|[\s;])display\s*:\s*([^;]+)/) || [, ""])[1].trim(); + if (!positiv(w)) continue; + (raus[m[2]] ||= []).push(w); + } + return raus; + }; + const streitIn = (roh) => Object.entries(grundregeln(roh)) + .filter(([, was]) => new Set(was).size > 1) + .map(([name, was]) => `${name} (${[...new Set(was)].join(" vs. ")})`); + + const dateien = readdirSync(ordner).filter((n) => n.endsWith(".css")); + const funde = []; + let geprueft = 0; + for (const name of dateien) { + const roh = readFileSync(join(ordner, name), "utf8"); + geprueft += Object.keys(grundregeln(roh)).length; + for (const z of streitIn(roh)) funde.push(`${name}: ${z}`); + } + ok(geprueft > 100 && funde.length === 0, + funde.length ? `Namensstreit: ${funde.join(" | ")}` + : `${geprueft} Grundregeln in ${dateien.length} Stilvorlagen -- ` + + "keine Klasse zweimal verschieden gebaut"); + + /* GEGENPROBEN IN BEIDE RICHTUNGEN. */ + const faelle = [ + ["der Fall vom 28.09. (zwei Grundregeln, anderes display)", + ".stufen { display: grid; } .stufen { display: flex; }", true], + ["verstecken und zeigen", + ".probe { display: none; } .probe { display: grid; }", false], + ["dieselbe Klasse in einem Zusammenhang", + ".pult { display: grid; } .saal .pult { display: flex; }", false], + ["eine Variante in einer Medienabfrage", + ".paar { display: grid; } @media (pointer: coarse) { .paar { display: flex; } }", false], + ["zweimal dasselbe display", + ".gleich { display: grid; } .gleich { display: grid; }", false], + ["eine Klasse im Kommentar", + "/* .a { display: flex; } */ .a { display: grid; }", false], + ]; + const daneben = faelle + .filter(([, text, soll]) => (streitIn(text).length > 0) !== soll) + .map(([name]) => name); + ok(daneben.length === 0, + daneben.length ? `Gegenprobe daneben bei: ${daneben.join(", ")}` + : `Gegenprobe: alle ${faelle.length} Faelle richtig eingeordnet`); +} + console.log(`\n${fehler === 0 ? "ALLES IN ORDNUNG" : `${fehler} FEHLER`}`); process.exit(fehler ? 1 : 0); diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 8341cf27..7dec16d9 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,8 +16,8 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +