Browsertests wiederhergestellt; drei echte Fehler gefunden

Der Playwright-Editortest war durch den Editorumbau kaputt: er
steuerte die abgeschafften Auswahllisten. Umgeschrieben auf die
freien Bedienelemente - Einheitenfelder, Vererbung über drei Geräte,
einzelnes Zurücksetzen, Palettenfarbe, Abstand je Seite, Hover-Regel,
freie Rasterspalten und die weiter vorhandenen Bewegungseffekte.

Dabei kamen drei Fehler heraus, die ohne Browserlauf unsichtbar sind:

1. Die frei gestalteten Werte wirkten in der Editorvorschau gar
   nicht. Ein srcdoc-Iframe erbt die Richtlinie des einbettenden
   Dokuments, und die Verwaltung verbietet Inline-Styles - das
   erzeugte style-Element wurde stillschweigend verworfen.
   Ausgeliefert wurde es korrekt, nur die Vorschau log. Jetzt als
   inertes template plus adoptedStyleSheets.
2. Die Einrückung der Unterseiten in der Seitenliste hat nie
   funktioniert; sie lief über ein style-Attribut, das dieselbe
   Richtlinie verwirft. Jetzt über Klassen.
3. Das Theme setzte alle Links auf die Akzentfarbe und überschrieb
   die kontextabhängigen Farben: 3,08:1 auf dunklem Grund. Die Regel
   gilt jetzt nur für Links in Textblöcken, die voreingestellte
   Linkfarbe liegt auf allen hellen Tönen über 4,5:1.

Geprüft: 155 PHP-Tests / 579 Assertions unter PHP 8.2.12 und 8.4.22,
15 JavaScript-Modelltests, vollständiger Editortest mit axe (null
Verstöße) und Lighthouse 13.4.1 mit je drei Läufen mobil und Desktop,
alle fünf Kategorien 100.

Offen: npm run test:browser schlägt wegen eines Inhalts fehl -
/grundlagen trägt einen im Editor gesetzten Textblock mit 2,75:1.
Nicht verändert, weil es eine Nutzerentscheidung ist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5 committed 2026-09-12 14:16:08 +02:00
1 parent 270cbda9ac
commit ba56add678
12 files changed
+169 -32

No files matched your search

+25 -5
View File
@@ -252,17 +252,26 @@ function renderDesign(block, panel) {
} else {
panel.append(Object.assign(document.createElement('p'), { className: 'panel-note', textContent: 'Gestaltungsoptionen werden geladen …' }));
}
const hasLegacy = Boolean(block.layout?.design) || Boolean(block.layout?.effects);
if (!hasLegacy) return;
// Entrance animations and the preset effects have no equivalent in the free system: they are
// keyframes, not declarations. They stay available for every block.
const effects = document.createElement('details'); effects.className = 'design-group';
const effectsSummary = document.createElement('summary'); effectsSummary.textContent = 'Bewegung und Effekte';
const effectsBody = document.createElement('div'); effectsBody.className = 'design-group-body';
effects.append(effectsSummary, effectsBody);
renderLegacyEffects(block, effectsBody);
panel.append(effects);
// The token values are superseded by the free panel and only shown where a page still has them.
if (!block.layout?.design) return;
const details = document.createElement('details'); details.className = 'design-group';
const summary = document.createElement('summary'); summary.textContent = 'Klassische Werte dieser Seite';
const body = document.createElement('div'); body.className = 'design-group-body';
details.append(summary, body);
renderLegacyDesign(block, body);
renderLegacyTokens(block, body);
panel.append(details);
}
function renderLegacyDesign(block, panel) {
function renderLegacyTokens(block, panel) {
// Token based values from documents written before schema v10. Shown only while a block
// still carries them, so older pages stay editable without cluttering the new panel.
const hint = document.createElement('p'); hint.className = 'design-scope';
@@ -290,7 +299,9 @@ function renderLegacyDesign(block, panel) {
history.change(doc => { const current = locate(doc.blocks, selected).block; for (const key of Object.keys(current.layout?.design?.[device] || {})) setDesign(doc, selected, device, key, ''); });
changed();
}); panel.append(reset);
const heading = document.createElement('h3'); heading.className = 'preset-heading'; heading.textContent = 'Effekte · alle Geräte'; panel.append(heading);
}
function renderLegacyEffects(block, panel) {
for (const [key, label, choices] of [
['shadow', 'Schatten', { none: 'Keiner', soft: 'Weich', strong: 'Kräftig' }],
['hover', 'Hover-Effekt', { none: 'Keiner', lift: 'Leicht anheben', zoom: 'Bild vergrößern' }],
@@ -432,6 +443,15 @@ async function updatePreview() {
if (sequence !== previewSequence) return;
const doc = frame.contentDocument;
const style = doc.createElement('link'); style.rel = 'stylesheet'; style.href = '/assets/preview.css'; doc.head.append(style);
// The preview delivers the generated stylesheet as inert template text (see page.html.twig).
// Applying it as a constructed stylesheet is not a source in the sense of the policy, so the
// preview shows exactly what the published page shows, without a single blocked style.
const generated = doc.getElementById('kant-styles')?.content.textContent ?? '';
if (generated.trim()) {
const sheet = new doc.defaultView.CSSStyleSheet();
sheet.replaceSync(generated);
doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, sheet];
}
doc.addEventListener('click', event => {
event.preventDefault();
if (inlineEdit) return;