Dokumentschema v17: Projektraster, verlinktes Bild, klebender Kopfbereich
Alles aus dem Nachbau von kant-it.de, den Umut durchgesehen hat. Eine Beitragsliste kann Datum, Autor, Auszug und Kategorie ausblenden und sieht damit aus wie ein Projektraster statt wie ein Blogarchiv. Beinahe lautlos danebengegangen: |default(true) macht in Twig aus einem gespeicherten false ein true - die Einstellung haette sich speichern lassen und nichts getan. Der Test prueft beide Richtungen. Ein Bild darf verlinken, damit ein Logo auf die Startseite zeigt; die Adresse geht durch dieselbe Pruefung wie jeder andere Link. Und der Kopfbereich kann beim Scrollen oben bleiben - als Einstellung der Website, weil nur das umschliessende Element kleben kann. Der groesste Fund steckt im Editor: die Liste bekannter Schemafassungen endete bei 12, waehrend Bausteine v13 bis v15 verlangen. In einem aktuellen Dokument liess sich damit kein Baustein mehr einfuegen, und Symbol, Fortschritt, Slider und externer Inhalt in gar keinem. Jetzt eine Zahl an einer Stelle, mit einem Test ueber jeden Typ und jede Fassung. Geprueft: 389 PHP-Tests unter 8.2 und 8.4, 18 JS-Tests, Editortest, Browserpruefung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
efa285c0d0
commit
70283db20a
16 files changed
+185
-12
No files matched your search
@@ -38,7 +38,7 @@ final class DocumentValidator
|
||||
public function validate(array $document, bool $requireHeading = true): void
|
||||
{
|
||||
$schemaVersion = $document['schemaVersion'] ?? null;
|
||||
$this->require(in_array($schemaVersion, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], true), 'Unsupported document schema.');
|
||||
$this->require(in_array($schemaVersion, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], true), 'Unsupported document schema.');
|
||||
$this->text($document['title'] ?? null, 160);
|
||||
$this->text($document['description'] ?? null, 320);
|
||||
$this->require(is_array($document['blocks'] ?? null) && array_is_list($document['blocks']), 'Blocks must be a list.');
|
||||
@@ -132,6 +132,16 @@ final class DocumentValidator
|
||||
$this->require(is_string($props[$kind]) && 1 === preg_match('/^[a-z0-9]+(?:-[a-z0-9]+)*$/D', $props[$kind]) && strlen($props[$kind]) <= 80, 'Ungültiger Filter für die Beitragsliste.');
|
||||
}
|
||||
}
|
||||
// Was eine Karte zeigt. Ein Projektraster besteht aus Bild und Titel; Datum, Auszug
|
||||
// und Kategorie gehören in ein Blogarchiv und lassen eine Projektseite falsch
|
||||
// aussehen. Voreinstellung ist der alte Zustand, damit bestehende Seiten sich nicht
|
||||
// ändern, wenn niemand etwas einstellt.
|
||||
foreach (['showMeta', 'showExcerpt', 'showTerms'] as $switch) {
|
||||
if (isset($props[$switch])) {
|
||||
$this->require($schemaVersion >= 17, 'Die Anzeigeoptionen der Beitragsliste brauchen Schema v17.');
|
||||
$this->require(is_bool($props[$switch]), sprintf('"%s" ist ja oder nein.', $switch));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ('button' === $type) {
|
||||
$this->url($props['href'] ?? null);
|
||||
@@ -249,6 +259,12 @@ final class DocumentValidator
|
||||
}
|
||||
if ('image' === $type) {
|
||||
$this->url($props['src'] ?? null);
|
||||
// Ein Bild darf verlinken. Klingt selbstverstaendlich, fehlte aber: ein Logo im
|
||||
// Kopfbereich ohne Verweis auf die Startseite ist der erste Klick, den jeder sucht.
|
||||
if ('' !== ($props['href'] ?? '')) {
|
||||
$this->require($schemaVersion >= 17, 'Ein verlinktes Bild braucht Schema v17.');
|
||||
$this->url($props['href']);
|
||||
}
|
||||
$this->require(is_bool($props['decorative'] ?? null), 'Image purpose is required.');
|
||||
$this->text($props['alt'] ?? null, 300, $props['decorative']);
|
||||
$this->require(!$props['decorative'] || '' === $props['alt'], 'Decorative images need empty alternative text.');
|
||||
|
||||
@@ -24,6 +24,9 @@ final class SiteSettings
|
||||
'sameAs' => [],
|
||||
'localBusiness' => false,
|
||||
'llmsTxt' => false,
|
||||
// Der Kopfbereich bleibt beim Scrollen oben stehen. Eine Eigenschaft der Website und
|
||||
// nicht des Dokuments: kleben kann nur das Element, das den Bereich umschliesst.
|
||||
'stickyHeader' => false,
|
||||
'robotsExtra' => '',
|
||||
// Which stored page answers at the site root. Everything else derives from this.
|
||||
'homePath' => 'home',
|
||||
@@ -93,6 +96,7 @@ final class SiteSettings
|
||||
throw new InvalidPage('Ein lokales Unternehmen braucht mindestens Straße und Ort.');
|
||||
}
|
||||
$values['llmsTxt'] = (bool) ($input['llmsTxt'] ?? false);
|
||||
$values['stickyHeader'] = (bool) ($input['stickyHeader'] ?? false);
|
||||
// Only comment and simple directive lines; nothing that could smuggle in a second policy.
|
||||
$extra = [];
|
||||
foreach (preg_split('/\R/', (string) ($input['robotsExtra'] ?? '')) ?: [] as $line) {
|
||||
|
||||
Reference in new issue
Block a user