From 87db17704a98ebdcbc853b5a62cd9074a35579de Mon Sep 17 00:00:00 2001 From: Dogfather Date: Thu, 27 Aug 2026 15:07:55 +0200 Subject: [PATCH] Test: kein Bild / keine eingebundene Datei fehlt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prüft, was die öffentlichen Seiten laden: Bilder, og:image/twitter:image, Favicon, Manifest. Eine fehlende Datei zeigt sich als leerer Kasten oder kaputte Teilen-Vorschau, oft unbemerkt. Ergebnis: 67 eigene Ressourcen, alle vorhanden, 0 fehlen. Co-Authored-By: Claude Opus 5 --- pruef-assets.mjs | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 pruef-assets.mjs diff --git a/pruef-assets.mjs b/pruef-assets.mjs new file mode 100644 index 00000000..56e69098 --- /dev/null +++ b/pruef-assets.mjs @@ -0,0 +1,90 @@ +/* ===================================================================== + Fehlt irgendein Bild oder eine eingebundene Datei? + + Der Link-Test (pruef-links.mjs) prüft . Dieser hier prüft, was + die Seite selbst LÄDT: Bilder (, CSS-Hintergründe über inline + style), das Social-Preview-Bild (og:image, twitter:image), Favicon und + das PWA-Manifest. Eine fehlende Datei zeigt sich als leerer Kasten, + kaputtes Vorschaubild beim Teilen oder fehlendem App-Symbol -- oft + unbemerkt, weil die Seite sonst funktioniert. + + Gegen die echte Domain. + ===================================================================== */ +import { chromium } from "playwright"; + +const BASIS = "https://dogfather-universe.com"; +const SEITEN = [ + "/", "/dogfather.html", "/hasidog.html", "/manager.html", "/casper.html", + "/vanvan.html", "/tt-muddi.html", "/zeitreise.html", "/streamer.html", + "/community.html", "/stimmen.html", "/streamplan.html", "/team-modis.html", + "/team-scouts.html", "/creator.html", "/werte.html", "/bewerben.html", + "/kontakt.html", "/links.html", "/supporter.html", "/abonnieren.html", + "/medien-dogfather.html", "/medien-hasidog.html", "/medien-casper.html", +]; + +const browser = await chromium.launch(); + +const ziele = new Map(); // url -> { typ, seiten:Set } +const merke = (url, typ, seite) => { + if (!ziele.has(url)) ziele.set(url, { typ, seiten: new Set() }); + ziele.get(url).seiten.add(seite); +}; + +for (const pfad of SEITEN) { + const seite = await browser.newPage(); + try { + await seite.goto(BASIS + pfad, { waitUntil: "networkidle", timeout: 30000 }); + const funde = await seite.evaluate(() => { + const raus = []; + /* Sichtbare Bilder (currentSrc löst srcset/lazy korrekt auf). */ + for (const im of document.querySelectorAll("img")) { + const s = im.currentSrc || im.src; + if (s && !s.startsWith("data:")) raus.push({ url: s, typ: "img" }); + } + /* Social-Preview + Favicon + Manifest aus dem . */ + const meta = (sel, attr) => document.querySelector(sel)?.getAttribute(attr); + const og = meta('meta[property="og:image"]', "content"); + if (og) raus.push({ url: og, typ: "og:image" }); + const tw = meta('meta[name="twitter:image"]', "content"); + if (tw) raus.push({ url: tw, typ: "twitter:image" }); + const fav = meta('link[rel="icon"]', "href"); + if (fav) raus.push({ url: fav, typ: "favicon" }); + const man = meta('link[rel="manifest"]', "href"); + if (man) raus.push({ url: man, typ: "manifest" }); + return raus; + }); + for (const f of funde) { + let url; + try { url = new URL(f.url, BASIS + pfad); } catch { continue; } + if (url.origin !== BASIS) continue; // nur eigene Assets + merke(url.pathname, f.typ, pfad); + } + } catch (e) { + console.log(` (Seite ${pfad} nicht ladbar: ${String(e.message).slice(0, 40)})`); + } + await seite.close(); +} + +console.log(`\n${ziele.size} verschiedene eigene Ressourcen gesammelt. Jede einmal geprüft:\n`); + +const pruef = await browser.newPage(); +let ok = 0; +const fehlt = []; +for (const [url, info] of [...ziele].sort()) { + try { + const a = await pruef.goto(BASIS + url, { waitUntil: "commit", timeout: 20000 }); + const code = a ? a.status() : 0; + if (code < 400) ok++; + else fehlt.push({ url, typ: info.typ, code, seiten: [...info.seiten] }); + } catch (e) { + fehlt.push({ url, typ: info.typ, code: String(e.message).slice(0, 24), seiten: [...info.seiten] }); + } +} +await browser.close(); + +console.log(`===== ${ok} Ressourcen vorhanden, ${fehlt.length} fehlen =====`); +if (fehlt.length) { + console.log("\nFehlende Dateien (Typ, Adresse -> Code, benutzt auf):"); + for (const f of fehlt) console.log(` - [${f.typ}] ${f.url} -> ${f.code} (${f.seiten.slice(0, 3).join(", ")}${f.seiten.length > 3 ? " …" : ""})`); +} +process.exitCode = fehlt.length ? 1 : 0;