Umlaute: der Export prueft sie, statt sich aufs Erinnern zu verlassen

Auf einer Slide stand "Sanitaer" und "Klima / Lueftung". Beides kam
woertlich aus dem Klickdummy, wo es schludrig eingetippt ist, und beides
las sich im fertigen Beitrag wie ein Fehler -- weil es einer ist.
Gefunden hat es niemand beim Bauen, sondern jemand, der auf den fertigen
Post geschaut hat.

Ein reines Muster genuegt als Pruefung nicht: Deutsch schreibt "neue",
"Dauer" und "Michael" voellig zu Recht mit ae/oe/ue. Nachgezaehlt ueber
den gezeichneten Text aller sieben Projekte sind es aber nur acht solche
Woerter, alle davon richtig oder gewollt (die Kanal-Handles). Also
Muster plus kurze Ausnahmeliste -- null Fehlalarme, "Sanitaer" faellt
trotzdem auf.

Bei ss ist es umgekehrt: 15 Treffer im gezeichneten Text, alle richtig
(dass, Schluss, Netzanschluss). Deshalb dort eine Liste der wenigen
Woerter, die ein scharfes s brauchen, statt eines Musters.

Geprueft wird an zwei Stellen, weil es zwei Wege zum fertigen Bild gibt:

  renderSlide()   bricht ab, bevor ein PNG entsteht
  animation.mjs   an 24 Stellen ueber den Ablauf

Der zweite Punkt war ein eigener Fehler: der erste Anlauf prueft nur den
Anfangszustand und fand nichts, weil die falschen Woerter dort erst ab
t = 0,4 erscheinen. Der Text einer Animation aendert sich mit der Zeit,
die Pruefung muss es auch.

Beide Tore sind mit absichtlich wieder eingebautem "Sanitaer" scheitern
gesehen worden. Eine Pruefung, die man nie hat scheitern sehen, ist
keine -- der erste Test lief durch, weil mein Testskript htmlToImage
direkt aufruft und renderSlide dabei umgeht.

Regel und Begruendung stehen in rules.md 4, die Falle in 8.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U7RZ6ZpLD8Dp84Rtt4KHfv
This commit is contained in:
dejanandClaude Opus 5 committed 2026-09-01 19:45:08 +02:00
1 parent 6b9f7a4ccf
commit 344645cb77
9 files changed
+406

No files matched your search

+51
View File
@@ -2263,6 +2263,52 @@ if (location.search.indexOf("nur=streifen") >= 0)
return n < 20 ? 1 : dunkel / n;
}
/* ─── Umlaute im gezeichneten Text ───────────────────────────────────────
Auf einer Slide stand einmal "Sanitaer" und "Klima / Lueftung". Beides
kam woertlich aus der Quelle -- im Klickdummy war es dort schludrig
eingetippt --, und beides las sich im fertigen Beitrag wie ein Fehler,
weil es einer ist. Gefunden hat es niemand beim Bauen, sondern erst
jemand, der auf den fertigen Post geschaut hat.
Deshalb prueft es jetzt der Export. Ein reines Muster genuegt dafuer
nicht: Deutsch schreibt "neue", "Dauer", "Michael" voellig zu Recht mit
ae/oe/ue. Nachgezaehlt ueber den gezeichneten Text aller Projekte sind es
aber nur eine Handvoll solcher Woerter -- eine Ausnahmeliste ist also
kurz und trifft trotzdem alles andere.
ss ist der umgekehrte Fall: fast immer richtig (dass, Schluss, Adresse,
Netzanschluss), nur ein paar Woerter brauchen ein scharfes s. Die stehen
deshalb einzeln als Liste und nicht als Muster.
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
const UMLAUT_ERLAUBT = new Set([
"michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
"aufmass", "strasse", "groesse", "groesser", "fuss", "fussboden",
"mass", "masse", "weiss", "heisst", "aussen", "gross", "grosse", "spass",
]);
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
if (!w) return;
const k = w.toLowerCase().replace(/^[@#]+/, "").replace(/[.,;:!?)(]+$/, "");
if (!k || UMLAUT_ERLAUBT.has(k) || raus.includes(w)) return;
if (/ae|oe|ue/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
}
/* Fuer animation.mjs: das Bewegtbild laeuft nicht durch renderSlide und
braucht deshalb eine eigene Tuer zu derselben Pruefung. */
window.TEXT_PRUEFUNG = () => umlautFehler(document);
async function renderSlide(i) {
// Hilfslinien sind Werkzeug: koennten sie aus einem Tastendruck noch
// stehen, landeten sie im Bild.
@@ -2279,6 +2325,11 @@ if (location.search.indexOf("nur=streifen") >= 0)
el.dataset.editmode = "aus";
try {
await document.fonts.ready;
/* Umlaute pruefen, bevor gerendert wird. Lieber ein Abbruch mit
klarer Meldung als ein fertiges PNG mit "Sanitaer" darauf. */
const uf = umlautFehler(el);
if (uf.length) throw new Error("Slide " + (i + 1) + ": Umlaut fehlt bei " +
uf.join(", ") + ". Wenn das Wort so richtig ist, gehoert es in UMLAUT_ERLAUBT.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})