Unbekannte Blöcke erhalten statt abweisen (Dokumentschema v4)

Der Lesevalidator wies bisher jeden unbekannten Blocktyp ab, womit der
Fallback im Renderer unerreichbar war: eine Seite mit Bausteinen aus
einer deaktivierten Erweiterung wäre nicht mehr ladbar gewesen. Ab
Schema v4 gilt ein Typ mit Namensraum (acme.slider) als Baustein einer
Erweiterung und bleibt erhalten. Der Kern prüft weiterhin ID, Tiefe,
Blockanzahl und Dokumentgröße, aber bewusst nicht die Props - er kennt
das Schema der Erweiterung nicht.

Damit ungeprüfte Werte nie ausgegeben werden, rendert der Kern aus
einem solchen Block nichts: öffentlich nur ein HTML-Kommentar, in der
Editorvorschau ein Platzhalter. Im Editor bleiben die Blöcke
auswählbar, verschiebbar, duplizierbar und löschbar, aber nicht
bearbeitbar, und es lässt sich nichts in sie einfügen.

Testumgebung: Twig lädt Vorlagen jetzt automatisch neu. Ohne Debug
konnte eine kompilierte Vorlage im Cache den Ausgang eines Testlaufs
bestimmen.

Geprüft: 64 PHP-Tests / 229 Assertions unter PHP 8.2.12 und 8.4.22,
11 JavaScript-Modelltests, Lint/Format/Container. Keine Browser- oder
Lighthouse-Läufe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5 committed 2026-09-12 10:37:30 +02:00
1 parent a6ffb9bdfd
commit 8e0006f883
13 files changed
+157 -26

No files matched your search

+9 -3
View File
@@ -10,7 +10,7 @@
{% set tag = type == 'section' ? 'section' : 'div' %}
<{{ tag }} id="{{ block.id }}" class="block-{{ type }} tone-{{ layout.tone|default('paper') }} width-{{ layout.width|default('normal') }}{{ designClasses }}">
{% if type == 'section' %}<div class="shell section-inner">{% endif %}
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child} only %}{% endfor %}
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false)} only %}{% endfor %}
{% if type == 'section' %}</div>{% endif %}
</{{ tag }}>
{% elseif type == 'heading' %}
@@ -23,8 +23,14 @@
<figure id="{{ block.id }}" class="block-image{{ designClasses }}"><img src="{{ props.src }}" alt="{{ props.alt }}" width="{{ props.width }}" height="{{ props.height }}" loading="lazy" decoding="async"{% if props.sources|default([]) %} srcset="{% for source in props.sources %}{{ source.src }} {{ source.width }}w{% if not loop.last %}, {% endif %}{% endfor %}" sizes="(max-width: 650px) 100vw, (max-width: 1024px) 50vw, 800px"{% endif %}>{% if props.caption|default('') %}<figcaption>{{ props.caption }}</figcaption>{% endif %}</figure>
{% elseif type == 'gallery' %}
<div id="{{ block.id }}" class="block-gallery{{ designClasses }}" role="group" aria-label="Bildergalerie">
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child} only %}{% endfor %}
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false)} only %}{% endfor %}
</div>
{% else %}
<p>Dieser Inhaltsblock ist derzeit nicht verfügbar.</p>
{#
A block whose plugin is not available. Its stored content stays in the document; the core
renders nothing from its unvalidated props. Visitors see no broken fragment, while the
editor preview shows a placeholder so the block can still be found and moved.
#}
<!-- Block {{ block.id }} ({{ type }}) wird von dieser Installation nicht dargestellt. -->
{% if editing|default(false) %}<p id="{{ block.id }}" class="block-unavailable" role="note">Baustein „{{ type }}“ ist in dieser Installation nicht verfügbar. Der Inhalt bleibt gespeichert.</p>{% endif %}
{% endif %}