Build Kantarci Markt as an eighth installation, allow content in own CSS and keep other fonts when fetching

- Coming-soon page "Kantarci Markt – Neueröffnung" rebuilt from the delivered package with
  imprint, privacy and 404 (scripts/reset-kantarci-markt.sh, ports 8100/8101).
- Own CSS accepts a short quoted string for `content`, so ::before/::after work.
- cms:fonts:fetch replaces only the rules of the fetched families in fonts.css.
- A variable font is linked and preloaded once with a weight range instead of once per weight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5.5 committed 2026-09-23 10:37:54 +02:00
1 parent 6fb6d30e8d
commit 5e5d380fd3
19 files changed
+994 -8

No files matched your search

+21
View File
@@ -1516,6 +1516,16 @@ final class CmsTest extends TestCase
self::assertSame('https://fonts.gstatic.com/s/lato/latein.woff2', $faces[0]['url']);
self::assertStringContainsString('U+0131', $faces[0]['range']);
// Ein neuer Abruf ersetzt nur die Regeln der geholten Familien; andere Familien, deren
// Dateien noch im Ordner liegen, bleiben im Stylesheet.
$vorher = "/* latin */\n@font-face{font-family:'Lato';font-weight:400;src:url(/assets/fonts/lato-400-latin.woff2)}\n"
."/* latin */\n@font-face{font-family:'DM Sans';font-weight:400;src:url(/assets/fonts/alt.woff2)}\n";
$neu = $fonts->combine($vorher, ["/* latin */\n@font-face{font-family:'DM Sans';font-weight:400;src:url(/assets/fonts/dm-sans-400-latin.woff2)}"], ['DM Sans']);
self::assertStringContainsString('lato-400-latin.woff2', $neu);
self::assertStringContainsString('dm-sans-400-latin.woff2', $neu);
self::assertStringNotContainsString('alt.woff2', $neu);
self::assertSame(2, substr_count($neu, '@font-face'));
// Ohne heruntergeladene Dateien bleibt es bei der Ersatzschrift - verlinkt wird Google
// nie, denn das gäbe die IP jedes Besuchers an einen Dritten weiter.
$theme = new Theme($this->db);
@@ -1547,6 +1557,11 @@ final class CmsTest extends TestCase
'/assets/fonts/lato-700-latin.woff2',
'/assets/fonts/lato-900-latin.woff2',
], $fonts->preload($theme->load()));
// Eine variable Schrift ist eine Datei für alle Schnitte: das Stylesheet nennt sie einmal
// mit Gewichtsbereich, und vorgeladen wird nur diese eine Datei statt dreimal dieselbe.
file_put_contents($this->path.'-fonts/fonts.css', "@font-face{font-family:'Lato';font-weight:400 900;src:url(/assets/fonts/lato-400-latin.woff2) format('woff2')}");
self::assertSame(['/assets/fonts/lato-400-latin.woff2'], $fonts->preload($theme->load()));
}
public function testTheStylesheetsGoOutAsOneFileWithoutComments(): void
@@ -3138,6 +3153,9 @@ final class CmsTest extends TestCase
& .card { transform: none }', '#b1 .card{border:0;transform:none}'];
yield 'element rule after a nested one' => ['& { color: red }
display: flex', '#b1{display:flex;color:red}'];
// Ein Pseudo-Element braucht content: leer fuer Striche und Verlaeufe, ein Zeichen fuer ein Wasserzeichen.
yield 'empty content' => ["&::after { content: ''; height: 2px }", "#b1::after{content:'';height:2px}"];
yield 'short content' => ['&::before { content: "K" }', '#b1::before{content:"K"}'];
}
#[DataProvider('ownCssCases')]
@@ -3161,6 +3179,9 @@ display: flex', '#b1{display:flex;color:red}'];
yield 'old expression syntax' => ['color: expression(alert(1))'];
yield 'no value' => ['color'];
yield 'nonsense property' => ['co lor: red'];
yield 'content leaving the style tag' => ['content: "</style><script>"'];
yield 'content with a second quote' => ["content: 'a' 'b'"];
yield 'quotes outside content' => ["font-family: 'Evil'"];
}
#[DataProvider('refusedOwnCss')]