Files
DogFatherGitandClaude Opus 5 87db17704a Test: kein Bild / keine eingebundene Datei fehlt
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 <[email protected]>
2026-08-27 15:07:55 +02:00

91 lines
3.8 KiB
JavaScript

/* =====================================================================
Fehlt irgendein Bild oder eine eingebundene Datei?
Der Link-Test (pruef-links.mjs) prüft <a href>. Dieser hier prüft, was
die Seite selbst LÄDT: Bilder (<img>, 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 <head>. */
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;