diff --git a/server/pruef-anleitung.mjs b/server/pruef-anleitung.mjs index 67bd5023..3eabf484 100644 --- a/server/pruef-anleitung.mjs +++ b/server/pruef-anleitung.mjs @@ -1442,6 +1442,88 @@ melde("\n=== Die Pflegeleiste haengt an beiden Ausgaengen ==="); `…und es gibt genau diese zwei Ausgaenge (${ausgaenge})`); } +/* ===================================================================== + KAPITEL 04 — DER KNOPF UND DER STAND DER KARTE + --------------------------------------------------------------------- + Zwei kleine Dinge aus dem Bauplan, und beide koennen lautlos falsch + sein: + + 1. DER KNOPF HEISST „HINGEHEN". So steht es im Plan, und es ist die + Sprache der Seite: Sie duzt und begruesst mit Namen. „Zur Kachel" + ist unser internes Wort; wer neu ist, hat „Kachel" noch nie + gehoert. Geprueft wird die ZAHL (genau einmal da, altes Wort + keinmal), nicht das blosse Vorkommen -- sonst waere die Zeile auch + gruen, wenn beide Woerter nebeneinander im Code stuenden. + + 2. „AKTUALISIERT AM" MUSS EIN DATUM SEIN, KEIN ZEITSTEMPEL. + Das ist der eigentliche Grund fuer diesen Block. `datumKurz` + bekommt ZWEI Formen herein, die nur am Anfang gleich aussehen: + die Stufenkarte schickt einen reinen Tag ("2026-10-13"), die + Karte einen ganzen Zeitstempel ("2026-10-06T18:22:31.123Z"). Die + Rechenvorschrift hatte ein `$` am Ende und liess die zweite Form + deshalb UNVERAENDERT durch: Auf der Karte stuende dann woertlich + „aktualisiert am 2026-10-06T18:22:31.123Z". Kein Fehler, kein + Absturz, keine rote Meldung -- genau die Sorte Schaden, die ein + `node --check` nicht sehen kann. + + DIE VORAUSSETZUNG WIRD GEMESSEN, NICHT ANGENOMMEN: Dass der Server + wirklich einen Zeitstempel schickt, fragt diese Pruefung beim Server + nach (erste Zeile). Ohne das waere die Zeile darunter eine Rechnung + gegen eine Erinnerung -- und die altert. + ===================================================================== */ +melde("\n=== Kapitel 04: der Knopf und der Stand der Karte ==="); +{ + const quelle = readFileSync( + new URL("../workspace/assets/js/anleitung.js", import.meta.url), "utf8"); + const nurCode = quelle + .replace(/\/\*[\s\S]*?\*\//g, " ") + .replace(/(^|[^:])\/\/[^\n]*/g, "$1 "); + + const hin = (nurCode.match(/'an-karte__weg', 'Hingehen'/g) || []).length; + ok(hin === 1, `der Weg-Knopf heißt „Hingehen" (${hin}x)`); + const altesWort = (nurCode.match(/Zur Kachel/g) || []).length; + ok(altesWort === 0, `…und „Zur Kachel" steht nirgends mehr (${altesWort}x)`); + + const nurPflege = (nurCode.match(/pflegeAn && eintrag\.geaendert/g) || []).length; + ok(nurPflege === 1, + `„aktualisiert am" hängt an der Pflege und steht nicht auf jeder Karte (${nurPflege}x)`); + + const css = readFileSync( + new URL("../workspace/assets/css/anleitung.css", import.meta.url), "utf8"); + ok(/\.an-karte__stand\s*\{/.test(css), + "…und hat eine eigene, stille Schrift (.an-karte__stand in der CSS)"); + + /* Die Rechenvorschrift wird AUSGEFUEHRT, nicht mit einem Muster + angesehen -- ein Muster waere eine zweite, ungenaue Nachbildung. */ + const anfang = quelle.indexOf("const datumKurz = (iso) => {"); + const ende = anfang < 0 ? -1 : quelle.indexOf("\n };", anfang); + braucht(anfang >= 0 && ende > anfang, + "datumKurz ist in anleitung.js nicht mehr zu finden — die Prüfung kann ihre Rechnung nicht holen"); + const kiste = {}; + vm.createContext(kiste); + vm.runInContext(`${quelle.slice(anfang, ende + 5)}\nglobalThis.__dk = datumKurz;\n`, + kiste, { filename: "datumKurz" }); + const datumKurz = kiste.__dk; + braucht(typeof datumKurz === "function", + "datumKurz ließ sich nicht ausführen — die Rechnung ist nicht zu messen"); + + const probe = (await holen("gast", CREW_HOST)).j?.karten || []; + braucht(probe.length > 0, + `keine einzige Karte da — ohne sie ist die Form von „geaendert" nicht zu messen`); + const mitZeit = probe.filter( + (k) => /^\d{4}-\d{2}-\d{2}T\d{2}:/.test(String(k.geaendert || ""))).length; + ok(probe.length > 0 && mitZeit === probe.length, + `der Server schickt „geaendert" als ganzen Zeitstempel (${mitZeit} von ${probe.length})`); + const lesbar = probe.filter( + (k) => /^\d{2}\.\d{2}\.\d{4}$/.test(datumKurz(k.geaendert))).length; + ok(probe.length > 0 && lesbar === probe.length, + `…und die Karte macht daraus einen lesbaren Tag (${lesbar} von ${probe.length})`); + ok(datumKurz("2026-10-13") === "13.10.2026", + "der reine Tag der Stufenkarte bleibt richtig (13.10.2026)"); + ok(datumKurz("demnächst") === "demnächst" && datumKurz("") === "", + "Gegenprobe: was kein Datum ist, wird auch zu keinem gemacht"); +} + /* ---------- Abschluss ------------------------------------------------ */ try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ } console.log(`\n${fehler ? "FEHLER: " + fehler : "Alles in Ordnung"} — ${geprueft} Prüfungen`); diff --git a/server/pruef-community-sicht.mjs b/server/pruef-community-sicht.mjs index 518c68f9..1c82a375 100644 --- a/server/pruef-community-sicht.mjs +++ b/server/pruef-community-sicht.mjs @@ -97,6 +97,16 @@ melde("=== 1. Was ueberhaupt offensteht ==="); DAS IST DIESELBE BAUART wie die festgelegten Kachelfarben: nicht „ungefaehr so viele", sondern „genau diese, und hier steht warum". */ const COMMUNITY_SEITEN = [ + /* DIE EINWEISUNG kam am 06.10.2026 dazu (Bauplan „Willkommen & + Anleitung"). Sie ist fuer ein Mitglied die ERSTE Seite ueberhaupt: + Die Kachel „Willkommen & Anleitung" steht breit und vorne in der + Gruppe „Community" und fuehrt hierher. Was darauf steht, erklaert + genau die vierzehn Kacheln, die dieses Mitglied hat -- nichts + darueber hinaus; das misst pruef-anleitung in beide Richtungen. + + Diese Zeile hat gefehlt, und die Pruefung ist deshalb rot + geworden -- richtig so: Genau dafuer gibt es sie. */ + "anleitung.html", // Willkommen & Anleitung (seit 06.10.2026) "bereich.html", // die Bretter (Highlights, Anschlag, Wunschliste ...) "bewerben.html", // Mitmachen "chat.html", // der Treff @@ -119,7 +129,11 @@ const COMMUNITY_SEITEN = [ "treff-regeln.html", // die Regeln des Rudels "unsere-seiten.html", // Draussen "unterstuetzen.html", // Unterstuetzen - "willkommen.html", // die Begruessung + /* Die alte Adresse bleibt offen -- sie leitet seit dem 06.10.2026 + auf anleitung.html weiter. Ein Lesezeichen soll nicht an einer + Schranke enden; die Weiterleitung selbst misst + pruef-willkommen. */ + "willkommen.html", // leitet auf die Anleitung weiter ]; const zuViel = erlaubt.filter((s) => !COMMUNITY_SEITEN.includes(s)); const fehltDa = COMMUNITY_SEITEN.filter((s) => !erlaubt.includes(s)); diff --git a/workspace/anleitung.html b/workspace/anleitung.html index 7b2fbd0d..35facd46 100644 --- a/workspace/anleitung.html +++ b/workspace/anleitung.html @@ -7,17 +7,17 @@ - - - - - + + + + + - - + +
@@ -289,16 +289,16 @@ Und anleitung.js braucht es doppelt: Symbol, Farbe, Name und Adresse jeder Karte kommen von dort, nicht vom Server. --> - + - - - - - - + + + + + +