notACMS 1.1.2 — Kanonische URLs und ein Builder für strukturierte Daten
1.1.2 leitet URLs mit Standardlokalisierungs-Präfix auf ihre kanonische Form ohne Präfix um, ersetzt eingebettetes JSON-LD durch einen flüssigen Schema.org-Builder und liefert zwei Sicherheitsfixes.
Eine kanonische URL pro Seite
Wenn die Standardlokalisierung deiner Site en ist, waren sowohl /en/blog/ als auch /blog/ erreichbar und lieferten denselben Inhalt aus. Das sind zwei indexierbare URLs für eine Seite — und Suchmaschinen wählen die, die ihnen gefällt, was selten die ist, die du dir wünschst.
1.1.2 ergänzt den DefaultLocaleRedirectListener. Jede Anfrage an /<standardlokalisierung>/... liefert eine 301-Weiterleitung zur URL ohne Präfix:
GET /en/blog/ → 301 Location: /blog/
GET /en/about/?ref=x → 301 Location: /about/?ref=x
GET /pl/blog/ → 200 (nicht-Standardlokalisierung, unangetastet)
Der Listener läuft vor dem Symfony-Router, sodass die Weiterleitung erfolgt, bevor das Framework überhaupt versucht, eine Route zu treffen — keine verschwendete Arbeit, kein 404-Rauschen in den Logs. Nicht-Standardlokalisierungen (pl, de, fr auf dieser Site) bleiben unangetastet.
Außerdem schließt das eine kleine SEO-Lücke: Backlinks, die das Lokalisierungspräfix versehentlich enthalten, konsolidieren sich nun zur kanonischen URL, statt die Domain-Autorität aufzuteilen.
Schema.org JSON-LD als flüssiger Builder
Bis 1.1.1 baute jedes Template, das strukturierte Daten benötigte, ein PHP-Array inline ein, leitete es durch |json_encode|raw und packte das Ergebnis in einen <script>-Tag. Sechs Templates, sechs nahezu identische Blöcke — und jeder eine neue Gelegenheit, JSON_UNESCAPED_SLASHES zu vergessen oder <script>false</script> auszuliefern, falls irgendein Frontmatter-Feld ein ungültiges Byte enthielt.
1.1.2 ersetzt das alles durch einen Service und zwei Twig-Funktionen:
{% block structured_data %}{{ json_ld(structured_data().blogPosting(
content.title(),
site_base_url ~ content.url(),
content.date(),
content.htmlContent,
site_author.name,
content.image() ? site_base_url ~ content.image() : null
)) }}{% endblock %}
structured_data() liefert den Builder; verkette eine typisierte Methode (webSite, webPage, blogPosting, collectionPage, contactPage, person, breadcrumbList, organization, imageObject) und das Ergebnis ist ein einfaches Array. json_ld(array) kodiert es und packt es in einen <script type="application/ld+json">-Tag. Leere und null-Werte werden rekursiv entfernt, sodass optionale Eingaben (eine nicht gesetzte Autor-E-Mail, ein fehlendes Bild) schlicht nicht in der Ausgabe erscheinen.
Die Kodierung verwendet jetzt JSON_THROW_ON_ERROR — fehlerhaftes UTF-8 im Frontmatter zeigt sich als echte Exception während des Renderings, statt stillschweigend einen kaputten <script>-Tag auszuliefern.
Die schlichten Kern-Templates für die Seiten contact, default und projects geben jetzt ebenfalls Schema.org-Markup aus. Bisher hatten schlichte Bereitstellungen schlechteres SEO als jedes Anpassungsbeispiel, das wir mitliefern; diese Lücke ist geschlossen.
Die vollständige Builder-API und wie du den structured_data-Block in deinem eigenen Theme überschreibst, findest du im Anpassungsleitfaden → Strukturierte Daten.
Sicherheitsfixes
Zwei Bugs sind während des 1.1.2-Reviews aufgetaucht und vor der Veröffentlichung behoben worden:
- Open-Redirect über die Pfad-Normalisierung. Die Methode
Request::getPathInfo()von Symfony fasst wiederholte Schrägstriche nicht zusammen, sodass eine Anfrage an/<standardlokalisierung>//evil.comandernfallsLocation: //evil.comerzeugt hätte — eine protokollrelative Weiterleitung, der Browser cross-origin folgen. Der neue Redirect-Listener verweigert nun Weiterleitungen auf alles, was kein lokaler Pfad mit einem einzelnen führenden Schrägstrich ist. - XSS in Suchergebnissen.
assets/search.jsband dasexcerpt-Feld von Pagefind ohne Escaping in innerHTML ein. Der Demo-Build war bereits korrekt; der Kern war auseinandergedriftet. Beide sind nun synchron. Die<mark>-Hervorhebungstags von Pagefind werden in den Suchergebnissen des Kerns nicht mehr gerendert — ein bewusster Kompromiss zugunsten der sichereren Standardausgabe.
Ebenfalls neu in 1.1.2
- Interner Twig-Refactor. Die Logik für Sidebar, Breadcrumbs, Beitragslabels, og-Bilder und Blog-Filter wurde aus den Templates in dedizierte Twig-Erweiterungen ausgelagert. Templates konzentrieren sich auf das Layout; Tests können jede Helper-Funktion direkt anvisieren. Neue Anpassungsfläche: siehe Layout-Helfer im Anpassungsleitfaden.
O(1)-Lookups nach Verzeichnisschlüssel inContentTree— eine kleine Performance-Verbesserung auf Sites mit Hunderten von Seiten.docs/customization/old-template/ist nun veraltet und wird in 1.2.0 entfernt. Es war eine einmalige Übergangshilfe für 1.0→1.1; neue Anpassungsarbeiten sollten voncustom-footer/oderself-hosted-fonts/ausgehen.- Abhängigkeitsupdates: Symfony 7.4.8 → 7.4.9 im gesamten Bundle, PHPStan 2.1.51 → 2.1.54, PHPUnit 13.1.7 → 13.1.8.
Vollständige Liste der Änderungen
Alle Änderungen mit Kategorien: CHANGELOG.md.