diff --git a/app/helpers.php b/app/helpers.php index cd907f8..008b12a 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -55,6 +55,30 @@ function asset(string $path): string return '/assets/' . $path . '?v=' . $version; } +/** + * Bootstrap-Icon als Inline-SVG ausgeben (lokal aus public/assets/icons/.svg). + * Standard: dekorativ (aria-hidden). Mit $label wird es als beschriftetes Bild + * (role="img") ausgegeben. Größe/Farbe steuert CSS über die Klasse .icon. + * Quelle: Bootstrap Icons (MIT) — neue Icons via bin/icons-add.php hinzufügen. + */ +function icon(string $name, string $class = '', ?string $label = null): string +{ + static $cache = []; + if (!array_key_exists($name, $cache)) { + $file = PUBLIC_PATH . '/assets/icons/' . basename($name) . '.svg'; + $cache[$name] = is_file($file) ? trim((string) file_get_contents($file)) : ''; + } + if ($cache[$name] === '') { + return ''; + } + $attrs = 'class="icon' . ($class !== '' ? ' ' . e($class) : '') . '"'; + $attrs .= $label !== null && $label !== '' + ? ' role="img" aria-label="' . e($label) . '"' + : ' aria-hidden="true" focusable="false"'; + + return preg_replace('/.json) mit Request-weitem Cache. * Wirft bei kaputtem JSON — Datenfehler sollen laut scheitern, nicht leise. diff --git a/bin/icons-add.php b/bin/icons-add.php new file mode 100644 index 0000000..d91eaff --- /dev/null +++ b/bin/icons-add.php @@ -0,0 +1,61 @@ +.svg ab (nur viewBox + Pfade, + * Größe/Farbe steuert CSS über die .icon-Klasse bzw. currentColor). + * + * NUR CLI/Build — nie im Request-Pfad. Besucher laden ausschließlich die lokalen + * SVGs (inline via icon()-Helper), niemals ein CDN. + * + * Aufruf: php bin/icons-add.php pause-fill play-fill arrow-right ... + * Icon-Namen siehe https://icons.getbootstrap.com (Dateiname ohne .svg). + */ +if (PHP_SAPI !== 'cli') { + exit(1); +} + +require dirname(__DIR__) . '/app/bootstrap.php'; + +const BI_VERSION = '1.11.3'; +const BI_BASE = 'https://cdn.jsdelivr.net/npm/bootstrap-icons@' . BI_VERSION . '/icons/'; + +$names = array_slice($argv, 1); +if ($names === []) { + fwrite(STDERR, "Usage: php bin/icons-add.php [ ...]\n"); + exit(1); +} + +$dir = PUBLIC_PATH . '/assets/icons'; +if (!is_dir($dir) && !mkdir($dir, 0775, true) && !is_dir($dir)) { + fwrite(STDERR, "Kann Verzeichnis nicht anlegen: {$dir}\n"); + exit(1); +} + +$failed = 0; +foreach ($names as $name) { + $name = basename(trim($name)); + if ($name === '' || !preg_match('/^[a-z0-9-]+$/', $name)) { + fwrite(STDERR, "Übersprungen (ungültiger Name): {$name}\n"); + $failed++; + continue; + } + + $raw = @file_get_contents(BI_BASE . $name . '.svg'); + if ($raw === false || !str_contains($raw, ']*>/s', '#\s*$#s'], '', $raw); + $svg = '' . trim((string) $inner) . '' . "\n"; + + file_put_contents($dir . '/' . $name . '.svg', $svg); + echo "✓ {$name}\n"; +} + +exit($failed > 0 ? 1 : 0); diff --git a/public/assets/css/utilities.css b/public/assets/css/utilities.css index a05ff8d..3f44e18 100644 --- a/public/assets/css/utilities.css +++ b/public/assets/css/utilities.css @@ -44,6 +44,16 @@ border: 0; } +/* Inline-Icons (Bootstrap Icons via icon()-Helper). Größe = font-size, Farbe = currentColor. */ +.icon { + display: inline-block; + width: 1em; + height: 1em; + fill: currentColor; + vertical-align: -0.125em; + flex: none; +} + .text-center { text-align: center; } diff --git a/public/assets/icons/arrow-right.svg b/public/assets/icons/arrow-right.svg new file mode 100644 index 0000000..c6cbb27 --- /dev/null +++ b/public/assets/icons/arrow-right.svg @@ -0,0 +1 @@ + diff --git a/public/assets/icons/chevron-down.svg b/public/assets/icons/chevron-down.svg new file mode 100644 index 0000000..8c288ab --- /dev/null +++ b/public/assets/icons/chevron-down.svg @@ -0,0 +1 @@ + diff --git a/public/assets/icons/clock.svg b/public/assets/icons/clock.svg new file mode 100644 index 0000000..97bc49d --- /dev/null +++ b/public/assets/icons/clock.svg @@ -0,0 +1,2 @@ + + diff --git a/public/assets/icons/pause-fill.svg b/public/assets/icons/pause-fill.svg new file mode 100644 index 0000000..054c8cf --- /dev/null +++ b/public/assets/icons/pause-fill.svg @@ -0,0 +1 @@ + diff --git a/public/assets/icons/people-fill.svg b/public/assets/icons/people-fill.svg new file mode 100644 index 0000000..32ae592 --- /dev/null +++ b/public/assets/icons/people-fill.svg @@ -0,0 +1 @@ + diff --git a/public/assets/icons/play-fill.svg b/public/assets/icons/play-fill.svg new file mode 100644 index 0000000..ea3702f --- /dev/null +++ b/public/assets/icons/play-fill.svg @@ -0,0 +1 @@ + diff --git a/public/assets/icons/trophy.svg b/public/assets/icons/trophy.svg new file mode 100644 index 0000000..c0a1ce0 --- /dev/null +++ b/public/assets/icons/trophy.svg @@ -0,0 +1 @@ + diff --git a/public/assets/icons/youtube.svg b/public/assets/icons/youtube.svg new file mode 100644 index 0000000..51da11b --- /dev/null +++ b/public/assets/icons/youtube.svg @@ -0,0 +1 @@ +