diff --git a/animation.mjs b/animation.mjs
index 7b30790..09bd219 100644
--- a/animation.mjs
+++ b/animation.mjs
@@ -177,8 +177,9 @@ try {
(f || []).forEach(w => gesehen.add(w));
}
if (gesehen.size)
- throw new Error(`${a.key}: Umlaut fehlt bei ${[...gesehen].join(", ")}. ` +
- "Wenn das Wort so richtig ist, gehoert es in UMLAUT_ERLAUBT.");
+ throw new Error(`${a.key}: ${[...gesehen].join(", ")}. ` +
+ "Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es in " +
+ "UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const ordner = await mkdtemp(path.join(tmpdir(), "postgrid-bilder-"));
process.stdout.write(` ${a.key}: ${anzahl} Bilder `);
diff --git a/post1.html b/post1.html
index 514445f..ffc4f6e 100644
--- a/post1.html
+++ b/post1.html
@@ -804,6 +804,8 @@ if (location.search.indexOf("nur=streifen") >= 0)
+
+
@@ -2284,8 +2286,17 @@ if (location.search.indexOf("nur=streifen") >= 0)
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
+ /* Woerter, in denen ae/oe/ue kein verkruepppelter Umlaut ist, sondern zwei
+ Laute an einer Silbengrenze. Die Eintraege wirken als Wortanfang.
+
+ Die Liste ist kurz geworden, weil die Regel darunter den groessten Teil
+ der Ausnahmen von selbst erledigt: ein ersatzweise geschriebener Umlaut
+ steht nie hinter einem Vokal. Vorher standen hier dauer, neue, steuer,
+ feuer, bauer -- alle nach demselben Muster, und die Liste waere mit
+ jedem Beitrag weitergewachsen. Was bleibt, sind die echten Sonderfaelle:
+ "Michael" (ae hinter h), "aktuell" (ue hinter t). */
const UMLAUT_ERLAUBT = new Set([
- "michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
+ "michael", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
@@ -2296,11 +2307,42 @@ if (location.search.indexOf("nur=streifen") >= 0)
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
- String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
+ /* Nicht textContent, sondern die Textknoten mit Leerzeichen dazwischen.
+ Eine Ueberschrift ist "Formulare selbst bauen. Per
+ Drag-and-drop." -- textContent klebt daraus "bauen.Per"
+ zusammen, ein Wort, das es nicht gibt. Ein Umbruch und eine
+ Elementgrenze sind Wortgrenzen. */
+ const stuecke = [];
+ const lauf = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
+ for (let k = lauf.nextNode(); k; k = lauf.nextNode()) stuecke.push(k.nodeValue);
+ const ganz = stuecke.join(" ");
+ /* Geviertstriche gehoeren nicht in unsere Texte. Der Halbgeviertstrich
+ als Gedankenstrich ist richtiges Deutsch und bleibt erlaubt; der
+ lange Strich ist eine englische Angewohnheit und liest sich auf einer
+ deutschen Slide fremd. Er kam nicht aus einer Quelle, sondern beim
+ Schreiben mit hinein. */
+ if (ganz.indexOf("\u2014") >= 0) {
+ const stelle = "Geviertstrich in „" + ganz.trim().slice(0, 40) + "“";
+ if (!raus.includes(stelle)) raus.push(stelle);
+ }
+ ganz.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);
+ if (!k || raus.includes(w)) return;
+ /* Mailadressen und Domains sind ausgenommen. Dort ist die
+ umlautfreie Schreibung keine Schludrigkeit, sondern Pflicht:
+ "buero@muster-shk.de" kann gar kein ue ersetzen. Ohne diese
+ Ausnahme meldete Post 8 drei Adressen als Fehler. */
+ if (/@/.test(k) || /\.(de|com|net|org|eu|at|ch|io)$/.test(k)) return;
+ if ([...UMLAUT_ERLAUBT].some(a => k.startsWith(a))) return;
+ /* ae/oe/ue nur dann als verunglueckter Umlaut, wenn kein Vokal
+ davorsteht. Ein ae, oe oder ue, das fuer ae, oe oder ue steht,
+ folgt immer einem Konsonanten oder steht am Wortanfang: "fuer",
+ "ueber", "gruen", "Sanitaer", "Lueftung". Hinter einem Vokal sind
+ es dagegen immer zwei eigene Laute: bauen, Bauer, neue, Dauer,
+ Steuer, Feuer, Mauer, genauer. Die Regel ersetzt sechs Eintraege
+ in UMLAUT_ERLAUBT und alle, die dort noch gelandet waeren. */
+ if (/(^|[^aeiou])(ae|oe|ue)/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
@@ -2326,11 +2368,12 @@ 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
+ /* Den Text 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.");
+ if (uf.length) throw new Error("Slide " + (i + 1) + ": " + uf.join(", ") +
+ ". Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es " +
+ "in UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})
diff --git a/post2-alt.html b/post2-alt.html
index a3d84b1..1d0a6b2 100644
--- a/post2-alt.html
+++ b/post2-alt.html
@@ -1107,6 +1107,8 @@ if (location.search.indexOf("nur=anim") >= 0)
+
+
@@ -4237,8 +4239,17 @@ if (location.search.indexOf("nur=anim") >= 0)
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
+ /* Woerter, in denen ae/oe/ue kein verkruepppelter Umlaut ist, sondern zwei
+ Laute an einer Silbengrenze. Die Eintraege wirken als Wortanfang.
+
+ Die Liste ist kurz geworden, weil die Regel darunter den groessten Teil
+ der Ausnahmen von selbst erledigt: ein ersatzweise geschriebener Umlaut
+ steht nie hinter einem Vokal. Vorher standen hier dauer, neue, steuer,
+ feuer, bauer -- alle nach demselben Muster, und die Liste waere mit
+ jedem Beitrag weitergewachsen. Was bleibt, sind die echten Sonderfaelle:
+ "Michael" (ae hinter h), "aktuell" (ue hinter t). */
const UMLAUT_ERLAUBT = new Set([
- "michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
+ "michael", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
@@ -4249,11 +4260,42 @@ if (location.search.indexOf("nur=anim") >= 0)
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
- String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
+ /* Nicht textContent, sondern die Textknoten mit Leerzeichen dazwischen.
+ Eine Ueberschrift ist "Formulare selbst bauen. Per
+ Drag-and-drop." -- textContent klebt daraus "bauen.Per"
+ zusammen, ein Wort, das es nicht gibt. Ein Umbruch und eine
+ Elementgrenze sind Wortgrenzen. */
+ const stuecke = [];
+ const lauf = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
+ for (let k = lauf.nextNode(); k; k = lauf.nextNode()) stuecke.push(k.nodeValue);
+ const ganz = stuecke.join(" ");
+ /* Geviertstriche gehoeren nicht in unsere Texte. Der Halbgeviertstrich
+ als Gedankenstrich ist richtiges Deutsch und bleibt erlaubt; der
+ lange Strich ist eine englische Angewohnheit und liest sich auf einer
+ deutschen Slide fremd. Er kam nicht aus einer Quelle, sondern beim
+ Schreiben mit hinein. */
+ if (ganz.indexOf("\u2014") >= 0) {
+ const stelle = "Geviertstrich in „" + ganz.trim().slice(0, 40) + "“";
+ if (!raus.includes(stelle)) raus.push(stelle);
+ }
+ ganz.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);
+ if (!k || raus.includes(w)) return;
+ /* Mailadressen und Domains sind ausgenommen. Dort ist die
+ umlautfreie Schreibung keine Schludrigkeit, sondern Pflicht:
+ "buero@muster-shk.de" kann gar kein ue ersetzen. Ohne diese
+ Ausnahme meldete Post 8 drei Adressen als Fehler. */
+ if (/@/.test(k) || /\.(de|com|net|org|eu|at|ch|io)$/.test(k)) return;
+ if ([...UMLAUT_ERLAUBT].some(a => k.startsWith(a))) return;
+ /* ae/oe/ue nur dann als verunglueckter Umlaut, wenn kein Vokal
+ davorsteht. Ein ae, oe oder ue, das fuer ae, oe oder ue steht,
+ folgt immer einem Konsonanten oder steht am Wortanfang: "fuer",
+ "ueber", "gruen", "Sanitaer", "Lueftung". Hinter einem Vokal sind
+ es dagegen immer zwei eigene Laute: bauen, Bauer, neue, Dauer,
+ Steuer, Feuer, Mauer, genauer. Die Regel ersetzt sechs Eintraege
+ in UMLAUT_ERLAUBT und alle, die dort noch gelandet waeren. */
+ if (/(^|[^aeiou])(ae|oe|ue)/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
@@ -4279,11 +4321,12 @@ if (location.search.indexOf("nur=anim") >= 0)
el.dataset.editmode = "aus";
try {
await document.fonts.ready;
- /* Umlaute pruefen, bevor gerendert wird. Lieber ein Abbruch mit
+ /* Den Text 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.");
+ if (uf.length) throw new Error("Slide " + (i + 1) + ": " + uf.join(", ") +
+ ". Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es " +
+ "in UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})
diff --git a/post2.html b/post2.html
index 7543311..9d25ae4 100644
--- a/post2.html
+++ b/post2.html
@@ -1000,6 +1000,8 @@ if (location.search.indexOf("nur=anim") >= 0)
+
+
@@ -3858,8 +3860,17 @@ if (location.search.indexOf("nur=anim") >= 0)
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
+ /* Woerter, in denen ae/oe/ue kein verkruepppelter Umlaut ist, sondern zwei
+ Laute an einer Silbengrenze. Die Eintraege wirken als Wortanfang.
+
+ Die Liste ist kurz geworden, weil die Regel darunter den groessten Teil
+ der Ausnahmen von selbst erledigt: ein ersatzweise geschriebener Umlaut
+ steht nie hinter einem Vokal. Vorher standen hier dauer, neue, steuer,
+ feuer, bauer -- alle nach demselben Muster, und die Liste waere mit
+ jedem Beitrag weitergewachsen. Was bleibt, sind die echten Sonderfaelle:
+ "Michael" (ae hinter h), "aktuell" (ue hinter t). */
const UMLAUT_ERLAUBT = new Set([
- "michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
+ "michael", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
@@ -3870,11 +3881,42 @@ if (location.search.indexOf("nur=anim") >= 0)
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
- String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
+ /* Nicht textContent, sondern die Textknoten mit Leerzeichen dazwischen.
+ Eine Ueberschrift ist "Formulare selbst bauen. Per
+ Drag-and-drop." -- textContent klebt daraus "bauen.Per"
+ zusammen, ein Wort, das es nicht gibt. Ein Umbruch und eine
+ Elementgrenze sind Wortgrenzen. */
+ const stuecke = [];
+ const lauf = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
+ for (let k = lauf.nextNode(); k; k = lauf.nextNode()) stuecke.push(k.nodeValue);
+ const ganz = stuecke.join(" ");
+ /* Geviertstriche gehoeren nicht in unsere Texte. Der Halbgeviertstrich
+ als Gedankenstrich ist richtiges Deutsch und bleibt erlaubt; der
+ lange Strich ist eine englische Angewohnheit und liest sich auf einer
+ deutschen Slide fremd. Er kam nicht aus einer Quelle, sondern beim
+ Schreiben mit hinein. */
+ if (ganz.indexOf("\u2014") >= 0) {
+ const stelle = "Geviertstrich in „" + ganz.trim().slice(0, 40) + "“";
+ if (!raus.includes(stelle)) raus.push(stelle);
+ }
+ ganz.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);
+ if (!k || raus.includes(w)) return;
+ /* Mailadressen und Domains sind ausgenommen. Dort ist die
+ umlautfreie Schreibung keine Schludrigkeit, sondern Pflicht:
+ "buero@muster-shk.de" kann gar kein ue ersetzen. Ohne diese
+ Ausnahme meldete Post 8 drei Adressen als Fehler. */
+ if (/@/.test(k) || /\.(de|com|net|org|eu|at|ch|io)$/.test(k)) return;
+ if ([...UMLAUT_ERLAUBT].some(a => k.startsWith(a))) return;
+ /* ae/oe/ue nur dann als verunglueckter Umlaut, wenn kein Vokal
+ davorsteht. Ein ae, oe oder ue, das fuer ae, oe oder ue steht,
+ folgt immer einem Konsonanten oder steht am Wortanfang: "fuer",
+ "ueber", "gruen", "Sanitaer", "Lueftung". Hinter einem Vokal sind
+ es dagegen immer zwei eigene Laute: bauen, Bauer, neue, Dauer,
+ Steuer, Feuer, Mauer, genauer. Die Regel ersetzt sechs Eintraege
+ in UMLAUT_ERLAUBT und alle, die dort noch gelandet waeren. */
+ if (/(^|[^aeiou])(ae|oe|ue)/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
@@ -3900,11 +3942,12 @@ if (location.search.indexOf("nur=anim") >= 0)
el.dataset.editmode = "aus";
try {
await document.fonts.ready;
- /* Umlaute pruefen, bevor gerendert wird. Lieber ein Abbruch mit
+ /* Den Text 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.");
+ if (uf.length) throw new Error("Slide " + (i + 1) + ": " + uf.join(", ") +
+ ". Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es " +
+ "in UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})
diff --git a/post3.html b/post3.html
index d15dd7a..3a874e9 100644
--- a/post3.html
+++ b/post3.html
@@ -1020,6 +1020,8 @@ if (location.search.indexOf("nur=anim") >= 0)
+
+
@@ -3583,8 +3585,17 @@ if (location.search.indexOf("nur=anim") >= 0)
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
+ /* Woerter, in denen ae/oe/ue kein verkruepppelter Umlaut ist, sondern zwei
+ Laute an einer Silbengrenze. Die Eintraege wirken als Wortanfang.
+
+ Die Liste ist kurz geworden, weil die Regel darunter den groessten Teil
+ der Ausnahmen von selbst erledigt: ein ersatzweise geschriebener Umlaut
+ steht nie hinter einem Vokal. Vorher standen hier dauer, neue, steuer,
+ feuer, bauer -- alle nach demselben Muster, und die Liste waere mit
+ jedem Beitrag weitergewachsen. Was bleibt, sind die echten Sonderfaelle:
+ "Michael" (ae hinter h), "aktuell" (ue hinter t). */
const UMLAUT_ERLAUBT = new Set([
- "michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
+ "michael", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
@@ -3595,11 +3606,42 @@ if (location.search.indexOf("nur=anim") >= 0)
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
- String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
+ /* Nicht textContent, sondern die Textknoten mit Leerzeichen dazwischen.
+ Eine Ueberschrift ist "Formulare selbst bauen. Per
+ Drag-and-drop." -- textContent klebt daraus "bauen.Per"
+ zusammen, ein Wort, das es nicht gibt. Ein Umbruch und eine
+ Elementgrenze sind Wortgrenzen. */
+ const stuecke = [];
+ const lauf = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
+ for (let k = lauf.nextNode(); k; k = lauf.nextNode()) stuecke.push(k.nodeValue);
+ const ganz = stuecke.join(" ");
+ /* Geviertstriche gehoeren nicht in unsere Texte. Der Halbgeviertstrich
+ als Gedankenstrich ist richtiges Deutsch und bleibt erlaubt; der
+ lange Strich ist eine englische Angewohnheit und liest sich auf einer
+ deutschen Slide fremd. Er kam nicht aus einer Quelle, sondern beim
+ Schreiben mit hinein. */
+ if (ganz.indexOf("\u2014") >= 0) {
+ const stelle = "Geviertstrich in „" + ganz.trim().slice(0, 40) + "“";
+ if (!raus.includes(stelle)) raus.push(stelle);
+ }
+ ganz.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);
+ if (!k || raus.includes(w)) return;
+ /* Mailadressen und Domains sind ausgenommen. Dort ist die
+ umlautfreie Schreibung keine Schludrigkeit, sondern Pflicht:
+ "buero@muster-shk.de" kann gar kein ue ersetzen. Ohne diese
+ Ausnahme meldete Post 8 drei Adressen als Fehler. */
+ if (/@/.test(k) || /\.(de|com|net|org|eu|at|ch|io)$/.test(k)) return;
+ if ([...UMLAUT_ERLAUBT].some(a => k.startsWith(a))) return;
+ /* ae/oe/ue nur dann als verunglueckter Umlaut, wenn kein Vokal
+ davorsteht. Ein ae, oe oder ue, das fuer ae, oe oder ue steht,
+ folgt immer einem Konsonanten oder steht am Wortanfang: "fuer",
+ "ueber", "gruen", "Sanitaer", "Lueftung". Hinter einem Vokal sind
+ es dagegen immer zwei eigene Laute: bauen, Bauer, neue, Dauer,
+ Steuer, Feuer, Mauer, genauer. Die Regel ersetzt sechs Eintraege
+ in UMLAUT_ERLAUBT und alle, die dort noch gelandet waeren. */
+ if (/(^|[^aeiou])(ae|oe|ue)/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
@@ -3625,11 +3667,12 @@ if (location.search.indexOf("nur=anim") >= 0)
el.dataset.editmode = "aus";
try {
await document.fonts.ready;
- /* Umlaute pruefen, bevor gerendert wird. Lieber ein Abbruch mit
+ /* Den Text 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.");
+ if (uf.length) throw new Error("Slide " + (i + 1) + ": " + uf.join(", ") +
+ ". Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es " +
+ "in UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})
diff --git a/post4.html b/post4.html
index 798682e..94306bb 100644
--- a/post4.html
+++ b/post4.html
@@ -1048,6 +1048,8 @@ if (location.search.indexOf("nur=anim") >= 0)
+
+
@@ -4371,8 +4373,17 @@ if (location.search.indexOf("nur=anim") >= 0)
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
+ /* Woerter, in denen ae/oe/ue kein verkruepppelter Umlaut ist, sondern zwei
+ Laute an einer Silbengrenze. Die Eintraege wirken als Wortanfang.
+
+ Die Liste ist kurz geworden, weil die Regel darunter den groessten Teil
+ der Ausnahmen von selbst erledigt: ein ersatzweise geschriebener Umlaut
+ steht nie hinter einem Vokal. Vorher standen hier dauer, neue, steuer,
+ feuer, bauer -- alle nach demselben Muster, und die Liste waere mit
+ jedem Beitrag weitergewachsen. Was bleibt, sind die echten Sonderfaelle:
+ "Michael" (ae hinter h), "aktuell" (ue hinter t). */
const UMLAUT_ERLAUBT = new Set([
- "michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
+ "michael", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
@@ -4383,11 +4394,42 @@ if (location.search.indexOf("nur=anim") >= 0)
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
- String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
+ /* Nicht textContent, sondern die Textknoten mit Leerzeichen dazwischen.
+ Eine Ueberschrift ist "Formulare selbst bauen. Per
+ Drag-and-drop." -- textContent klebt daraus "bauen.Per"
+ zusammen, ein Wort, das es nicht gibt. Ein Umbruch und eine
+ Elementgrenze sind Wortgrenzen. */
+ const stuecke = [];
+ const lauf = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
+ for (let k = lauf.nextNode(); k; k = lauf.nextNode()) stuecke.push(k.nodeValue);
+ const ganz = stuecke.join(" ");
+ /* Geviertstriche gehoeren nicht in unsere Texte. Der Halbgeviertstrich
+ als Gedankenstrich ist richtiges Deutsch und bleibt erlaubt; der
+ lange Strich ist eine englische Angewohnheit und liest sich auf einer
+ deutschen Slide fremd. Er kam nicht aus einer Quelle, sondern beim
+ Schreiben mit hinein. */
+ if (ganz.indexOf("\u2014") >= 0) {
+ const stelle = "Geviertstrich in „" + ganz.trim().slice(0, 40) + "“";
+ if (!raus.includes(stelle)) raus.push(stelle);
+ }
+ ganz.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);
+ if (!k || raus.includes(w)) return;
+ /* Mailadressen und Domains sind ausgenommen. Dort ist die
+ umlautfreie Schreibung keine Schludrigkeit, sondern Pflicht:
+ "buero@muster-shk.de" kann gar kein ue ersetzen. Ohne diese
+ Ausnahme meldete Post 8 drei Adressen als Fehler. */
+ if (/@/.test(k) || /\.(de|com|net|org|eu|at|ch|io)$/.test(k)) return;
+ if ([...UMLAUT_ERLAUBT].some(a => k.startsWith(a))) return;
+ /* ae/oe/ue nur dann als verunglueckter Umlaut, wenn kein Vokal
+ davorsteht. Ein ae, oe oder ue, das fuer ae, oe oder ue steht,
+ folgt immer einem Konsonanten oder steht am Wortanfang: "fuer",
+ "ueber", "gruen", "Sanitaer", "Lueftung". Hinter einem Vokal sind
+ es dagegen immer zwei eigene Laute: bauen, Bauer, neue, Dauer,
+ Steuer, Feuer, Mauer, genauer. Die Regel ersetzt sechs Eintraege
+ in UMLAUT_ERLAUBT und alle, die dort noch gelandet waeren. */
+ if (/(^|[^aeiou])(ae|oe|ue)/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
@@ -4413,11 +4455,12 @@ if (location.search.indexOf("nur=anim") >= 0)
el.dataset.editmode = "aus";
try {
await document.fonts.ready;
- /* Umlaute pruefen, bevor gerendert wird. Lieber ein Abbruch mit
+ /* Den Text 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.");
+ if (uf.length) throw new Error("Slide " + (i + 1) + ": " + uf.join(", ") +
+ ". Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es " +
+ "in UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})
diff --git a/post5.html b/post5.html
index d4f98a1..a31c95e 100644
--- a/post5.html
+++ b/post5.html
@@ -1048,6 +1048,8 @@ if (location.search.indexOf("nur=anim") >= 0)
+
+
@@ -4613,8 +4615,17 @@ if (location.search.indexOf("nur=anim") >= 0)
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
+ /* Woerter, in denen ae/oe/ue kein verkruepppelter Umlaut ist, sondern zwei
+ Laute an einer Silbengrenze. Die Eintraege wirken als Wortanfang.
+
+ Die Liste ist kurz geworden, weil die Regel darunter den groessten Teil
+ der Ausnahmen von selbst erledigt: ein ersatzweise geschriebener Umlaut
+ steht nie hinter einem Vokal. Vorher standen hier dauer, neue, steuer,
+ feuer, bauer -- alle nach demselben Muster, und die Liste waere mit
+ jedem Beitrag weitergewachsen. Was bleibt, sind die echten Sonderfaelle:
+ "Michael" (ae hinter h), "aktuell" (ue hinter t). */
const UMLAUT_ERLAUBT = new Set([
- "michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
+ "michael", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
@@ -4625,11 +4636,42 @@ if (location.search.indexOf("nur=anim") >= 0)
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
- String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
+ /* Nicht textContent, sondern die Textknoten mit Leerzeichen dazwischen.
+ Eine Ueberschrift ist "Formulare selbst bauen. Per
+ Drag-and-drop." -- textContent klebt daraus "bauen.Per"
+ zusammen, ein Wort, das es nicht gibt. Ein Umbruch und eine
+ Elementgrenze sind Wortgrenzen. */
+ const stuecke = [];
+ const lauf = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
+ for (let k = lauf.nextNode(); k; k = lauf.nextNode()) stuecke.push(k.nodeValue);
+ const ganz = stuecke.join(" ");
+ /* Geviertstriche gehoeren nicht in unsere Texte. Der Halbgeviertstrich
+ als Gedankenstrich ist richtiges Deutsch und bleibt erlaubt; der
+ lange Strich ist eine englische Angewohnheit und liest sich auf einer
+ deutschen Slide fremd. Er kam nicht aus einer Quelle, sondern beim
+ Schreiben mit hinein. */
+ if (ganz.indexOf("\u2014") >= 0) {
+ const stelle = "Geviertstrich in „" + ganz.trim().slice(0, 40) + "“";
+ if (!raus.includes(stelle)) raus.push(stelle);
+ }
+ ganz.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);
+ if (!k || raus.includes(w)) return;
+ /* Mailadressen und Domains sind ausgenommen. Dort ist die
+ umlautfreie Schreibung keine Schludrigkeit, sondern Pflicht:
+ "buero@muster-shk.de" kann gar kein ue ersetzen. Ohne diese
+ Ausnahme meldete Post 8 drei Adressen als Fehler. */
+ if (/@/.test(k) || /\.(de|com|net|org|eu|at|ch|io)$/.test(k)) return;
+ if ([...UMLAUT_ERLAUBT].some(a => k.startsWith(a))) return;
+ /* ae/oe/ue nur dann als verunglueckter Umlaut, wenn kein Vokal
+ davorsteht. Ein ae, oe oder ue, das fuer ae, oe oder ue steht,
+ folgt immer einem Konsonanten oder steht am Wortanfang: "fuer",
+ "ueber", "gruen", "Sanitaer", "Lueftung". Hinter einem Vokal sind
+ es dagegen immer zwei eigene Laute: bauen, Bauer, neue, Dauer,
+ Steuer, Feuer, Mauer, genauer. Die Regel ersetzt sechs Eintraege
+ in UMLAUT_ERLAUBT und alle, die dort noch gelandet waeren. */
+ if (/(^|[^aeiou])(ae|oe|ue)/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
@@ -4655,11 +4697,12 @@ if (location.search.indexOf("nur=anim") >= 0)
el.dataset.editmode = "aus";
try {
await document.fonts.ready;
- /* Umlaute pruefen, bevor gerendert wird. Lieber ein Abbruch mit
+ /* Den Text 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.");
+ if (uf.length) throw new Error("Slide " + (i + 1) + ": " + uf.join(", ") +
+ ". Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es " +
+ "in UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})
diff --git a/post6.html b/post6.html
index de7b937..968a737 100644
--- a/post6.html
+++ b/post6.html
@@ -1052,6 +1052,8 @@ if (location.search.indexOf("nur=anim") >= 0)
+
+
@@ -5550,8 +5552,17 @@ if (location.search.indexOf("nur=anim") >= 0)
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
+ /* Woerter, in denen ae/oe/ue kein verkruepppelter Umlaut ist, sondern zwei
+ Laute an einer Silbengrenze. Die Eintraege wirken als Wortanfang.
+
+ Die Liste ist kurz geworden, weil die Regel darunter den groessten Teil
+ der Ausnahmen von selbst erledigt: ein ersatzweise geschriebener Umlaut
+ steht nie hinter einem Vokal. Vorher standen hier dauer, neue, steuer,
+ feuer, bauer -- alle nach demselben Muster, und die Liste waere mit
+ jedem Beitrag weitergewachsen. Was bleibt, sind die echten Sonderfaelle:
+ "Michael" (ae hinter h), "aktuell" (ue hinter t). */
const UMLAUT_ERLAUBT = new Set([
- "michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
+ "michael", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
@@ -5562,11 +5573,42 @@ if (location.search.indexOf("nur=anim") >= 0)
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
- String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
+ /* Nicht textContent, sondern die Textknoten mit Leerzeichen dazwischen.
+ Eine Ueberschrift ist "Formulare selbst bauen. Per
+ Drag-and-drop." -- textContent klebt daraus "bauen.Per"
+ zusammen, ein Wort, das es nicht gibt. Ein Umbruch und eine
+ Elementgrenze sind Wortgrenzen. */
+ const stuecke = [];
+ const lauf = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
+ for (let k = lauf.nextNode(); k; k = lauf.nextNode()) stuecke.push(k.nodeValue);
+ const ganz = stuecke.join(" ");
+ /* Geviertstriche gehoeren nicht in unsere Texte. Der Halbgeviertstrich
+ als Gedankenstrich ist richtiges Deutsch und bleibt erlaubt; der
+ lange Strich ist eine englische Angewohnheit und liest sich auf einer
+ deutschen Slide fremd. Er kam nicht aus einer Quelle, sondern beim
+ Schreiben mit hinein. */
+ if (ganz.indexOf("\u2014") >= 0) {
+ const stelle = "Geviertstrich in „" + ganz.trim().slice(0, 40) + "“";
+ if (!raus.includes(stelle)) raus.push(stelle);
+ }
+ ganz.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);
+ if (!k || raus.includes(w)) return;
+ /* Mailadressen und Domains sind ausgenommen. Dort ist die
+ umlautfreie Schreibung keine Schludrigkeit, sondern Pflicht:
+ "buero@muster-shk.de" kann gar kein ue ersetzen. Ohne diese
+ Ausnahme meldete Post 8 drei Adressen als Fehler. */
+ if (/@/.test(k) || /\.(de|com|net|org|eu|at|ch|io)$/.test(k)) return;
+ if ([...UMLAUT_ERLAUBT].some(a => k.startsWith(a))) return;
+ /* ae/oe/ue nur dann als verunglueckter Umlaut, wenn kein Vokal
+ davorsteht. Ein ae, oe oder ue, das fuer ae, oe oder ue steht,
+ folgt immer einem Konsonanten oder steht am Wortanfang: "fuer",
+ "ueber", "gruen", "Sanitaer", "Lueftung". Hinter einem Vokal sind
+ es dagegen immer zwei eigene Laute: bauen, Bauer, neue, Dauer,
+ Steuer, Feuer, Mauer, genauer. Die Regel ersetzt sechs Eintraege
+ in UMLAUT_ERLAUBT und alle, die dort noch gelandet waeren. */
+ if (/(^|[^aeiou])(ae|oe|ue)/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
@@ -5592,11 +5634,12 @@ if (location.search.indexOf("nur=anim") >= 0)
el.dataset.editmode = "aus";
try {
await document.fonts.ready;
- /* Umlaute pruefen, bevor gerendert wird. Lieber ein Abbruch mit
+ /* Den Text 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.");
+ if (uf.length) throw new Error("Slide " + (i + 1) + ": " + uf.join(", ") +
+ ". Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es " +
+ "in UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})
diff --git a/post7.html b/post7.html
index ecc926f..10c5b90 100644
--- a/post7.html
+++ b/post7.html
@@ -1052,6 +1052,8 @@ if (location.search.indexOf("nur=anim") >= 0)
+
+
@@ -5838,8 +5840,17 @@ if (location.search.indexOf("nur=anim") >= 0)
Kanalnamen sind Absicht: "# waermepumpe-mueller" ist ein Handle, und die
schreiben Chatwerkzeuge klein und ohne Umlaute. */
+ /* Woerter, in denen ae/oe/ue kein verkruepppelter Umlaut ist, sondern zwei
+ Laute an einer Silbengrenze. Die Eintraege wirken als Wortanfang.
+
+ Die Liste ist kurz geworden, weil die Regel darunter den groessten Teil
+ der Ausnahmen von selbst erledigt: ein ersatzweise geschriebener Umlaut
+ steht nie hinter einem Vokal. Vorher standen hier dauer, neue, steuer,
+ feuer, bauer -- alle nach demselben Muster, und die Liste waere mit
+ jedem Beitrag weitergewachsen. Was bleibt, sind die echten Sonderfaelle:
+ "Michael" (ae hinter h), "aktuell" (ue hinter t). */
const UMLAUT_ERLAUBT = new Set([
- "michael", "dauer", "neue", "steuer", "feuer", "aktuell", "museum",
+ "michael", "aktuell", "museum",
"waermepumpe-mueller", "waermepumpe-abnahme",
]);
const BRAUCHT_SCHARFES_S = new Set([
@@ -5850,11 +5861,42 @@ if (location.search.indexOf("nur=anim") >= 0)
function umlautFehler(wurzel) {
const raus = [];
wurzel.querySelectorAll("text, .headline, .body, .badge").forEach(e => {
- String(e.textContent || "").split(/[^A-Za-zÄÖÜäöüß0-9./#@-]+/).forEach(w => {
+ /* Nicht textContent, sondern die Textknoten mit Leerzeichen dazwischen.
+ Eine Ueberschrift ist "Formulare selbst bauen. Per
+ Drag-and-drop." -- textContent klebt daraus "bauen.Per"
+ zusammen, ein Wort, das es nicht gibt. Ein Umbruch und eine
+ Elementgrenze sind Wortgrenzen. */
+ const stuecke = [];
+ const lauf = document.createTreeWalker(e, NodeFilter.SHOW_TEXT);
+ for (let k = lauf.nextNode(); k; k = lauf.nextNode()) stuecke.push(k.nodeValue);
+ const ganz = stuecke.join(" ");
+ /* Geviertstriche gehoeren nicht in unsere Texte. Der Halbgeviertstrich
+ als Gedankenstrich ist richtiges Deutsch und bleibt erlaubt; der
+ lange Strich ist eine englische Angewohnheit und liest sich auf einer
+ deutschen Slide fremd. Er kam nicht aus einer Quelle, sondern beim
+ Schreiben mit hinein. */
+ if (ganz.indexOf("\u2014") >= 0) {
+ const stelle = "Geviertstrich in „" + ganz.trim().slice(0, 40) + "“";
+ if (!raus.includes(stelle)) raus.push(stelle);
+ }
+ ganz.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);
+ if (!k || raus.includes(w)) return;
+ /* Mailadressen und Domains sind ausgenommen. Dort ist die
+ umlautfreie Schreibung keine Schludrigkeit, sondern Pflicht:
+ "buero@muster-shk.de" kann gar kein ue ersetzen. Ohne diese
+ Ausnahme meldete Post 8 drei Adressen als Fehler. */
+ if (/@/.test(k) || /\.(de|com|net|org|eu|at|ch|io)$/.test(k)) return;
+ if ([...UMLAUT_ERLAUBT].some(a => k.startsWith(a))) return;
+ /* ae/oe/ue nur dann als verunglueckter Umlaut, wenn kein Vokal
+ davorsteht. Ein ae, oe oder ue, das fuer ae, oe oder ue steht,
+ folgt immer einem Konsonanten oder steht am Wortanfang: "fuer",
+ "ueber", "gruen", "Sanitaer", "Lueftung". Hinter einem Vokal sind
+ es dagegen immer zwei eigene Laute: bauen, Bauer, neue, Dauer,
+ Steuer, Feuer, Mauer, genauer. Die Regel ersetzt sechs Eintraege
+ in UMLAUT_ERLAUBT und alle, die dort noch gelandet waeren. */
+ if (/(^|[^aeiou])(ae|oe|ue)/.test(k) || BRAUCHT_SCHARFES_S.has(k)) raus.push(w);
});
});
return raus;
@@ -5880,11 +5922,12 @@ if (location.search.indexOf("nur=anim") >= 0)
el.dataset.editmode = "aus";
try {
await document.fonts.ready;
- /* Umlaute pruefen, bevor gerendert wird. Lieber ein Abbruch mit
+ /* Den Text 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.");
+ if (uf.length) throw new Error("Slide " + (i + 1) + ": " + uf.join(", ") +
+ ". Fehlt ein Umlaut, schreib ihn; ist das Wort so richtig, gehoert es " +
+ "in UMLAUT_ERLAUBT. Einen Geviertstrich ersetzt ein Punkt oder ein Komma.");
const imgs = [...el.querySelectorAll("img")];
await Promise.all(imgs.map(im =>
im.complete ? im.decode().catch(() => {})