Banner-Hintergründe CSP-fest: <img> statt Inline-Variable
Beim ersten Deploy blieben die Slides des Banner-Sliders schwarz. Ursache war kein fehlendes Bild, sondern die CSP: public/.htaccess setzt default-src 'self' ohne style-src, der Browser verwirft damit jedes style-Attribut — und die Komponente lieferte Bild und Akzentfarbe genau so (style="--banner-bg: url(…); --banner-accent: #6cbbbc"). Lokal war das unsichtbar, weil php -S keine .htaccess liest. Der Hintergrund ist jetzt ein <img class="ad-banner__bg"> über die bestehende img-Komponente (CSP erlaubt img-src) und bringt srcset mit: das Handy lädt die 640er statt der 1600er, die erste Slide lädt eager mit fetchpriority. Der dunkle Leseverlauf liegt auf ::before statt im background-image. Die Akzentfarbe kann als beliebiger Hex-Wert nicht ohne Inline-Style in die Seite. Sie steht deshalb als Token in tokens.css (wo Farben laut CLAUDE.md hingehören), components.css bildet den Namen darauf ab, und banners.json nennt nur noch "accent": "breadcrumb". bin/preflight.php bricht ab, wenn unter app/ wieder ein style-Attribut auftaucht — der Fehler wäre sonst erneut erst in Produktion sichtbar. Beim Bauen dieser Wache zweimal selbst hineingetappt: ein Muster mit [^>]* bricht an jedem schließenden PHP-Tag ab, und die Zeichenfolge dieses Tags beendet den PHP-Modus auch in einem //-Kommentar (preflight gab ab dort seinen eigenen Quelltext aus, php -l meldete nichts). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
This commit is contained in:
@@ -296,6 +296,49 @@ if ($cronKey === '' || $cronKey === 'CHANGE_ME') {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Inline-Styles (die CSP verwirft sie stillschweigend) ---
|
||||
// Diese Prüfung existiert wegen eines echten Ausfalls am 31.07.2026: der
|
||||
// Banner-Slider setzte sein Hintergrundbild per style="--banner-bg: url(…)". Auf
|
||||
// echtem Apache greift die CSP aus public/.htaccess (default-src 'self', KEIN
|
||||
// style-src), der Browser verwarf das Attribut, die Slides blieben schwarz. Lokal
|
||||
// war das unsichtbar, weil `php -S` keine .htaccess liest — der Fehler konnte also
|
||||
// erst in Produktion auffallen. Genau davor schützt diese Wache.
|
||||
// Hinweis: per JavaScript gesetzte Styles (element.style.…) sind NICHT betroffen,
|
||||
// die CSP prüft nur vom HTML-Parser gelesene style-Attribute und <style>-Blöcke.
|
||||
/* Zeilenweise und ohne Tag-Kontext geprüft: ein Muster, das beim öffnenden Tag
|
||||
ansetzt und mit [^>]* weitersucht, bricht sofort ab — PHP-Templates enthalten
|
||||
über das schließende PHP-Tag ständig eine spitze Klammer. Ein style-Attribut in
|
||||
einer PHP-Datei ist praktisch immer echtes Markup, diese Prüfung genügt also.
|
||||
|
||||
Dieser Kommentar ist bewusst ein Blockkommentar: die Zeichenfolge des schließenden
|
||||
PHP-Tags beendet den PHP-Modus AUCH in einem //-Kommentar. Genau daran ist diese
|
||||
Prüfung beim Bauen einmal gescheitert (preflight gab ab dort seinen eigenen
|
||||
Quelltext aus, und php -l meldete nichts, weil das gültiges PHP mit HTML ist). */
|
||||
$inlineStyles = [];
|
||||
$phpDateien = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(ROOT_PATH . '/app'));
|
||||
foreach ($phpDateien as $datei) {
|
||||
if (!$datei->isFile() || $datei->getExtension() !== 'php') {
|
||||
continue;
|
||||
}
|
||||
foreach (file($datei->getPathname()) ?: [] as $nr => $zeile) {
|
||||
$roh = ltrim($zeile);
|
||||
// Kommentarzeilen überspringen — dieser Abschnitt selbst nennt style=" ja auch.
|
||||
if ($roh === '' || str_starts_with($roh, '*') || str_starts_with($roh, '//') || str_starts_with($roh, '/*')) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/\sstyle\s*=\s*"/i', $zeile) === 1) {
|
||||
$kurz = str_replace(ROOT_PATH . '/', '', $datei->getPathname());
|
||||
$inlineStyles[] = $kurz . ':' . ($nr + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($inlineStyles !== []) {
|
||||
$errors[] = 'Inline-Style im Markup — die CSP (kein style-src) verwirft ihn, die Regel greift NUR in Produktion: '
|
||||
. implode(', ', $inlineStyles)
|
||||
. '. Bilder als <img> ausgeben, Farben als Token in tokens.css plus Klasse in components.css.';
|
||||
}
|
||||
|
||||
// --- Ausgabe ---
|
||||
foreach ($warnings as $w) {
|
||||
echo "WARNUNG {$w}\n";
|
||||
|
||||
Reference in New Issue
Block a user