Fassung 1.5.3: der Editor blieb nach dem Update schwarz
Nach 1.5.2 meldete der Editor im Browser "The requested module './editor-model.js' does not provide an export named 'dropList'", und der Werkzeugkasten war leer. Ursache war nicht der Code, sondern das Zwischenspeichern. public/.htaccess setzt fuer jede .js-Datei Cache-Control: immutable, max-age=31536000 - ein Jahr. Die Fassungskennung haengt aber nur an den Einstiegsdateien, die die Vorlage schreibt. Die fuenf Module, die der Editor ueber import './...js' laedt, tragen keine: der Browser holte das neue editor.js und behielt das alte editor-model.js. Ein neues canvas-overlay.js traf damit auf ein Modell ohne dropList. Beide gemeldeten Symptome hatten diese eine Wurzel. Seit 1.5.1 baut das Skript den Werkzeugkasten auf, und editor.js importiert canvas-overlay.js in Zeile 5; bricht der Import, laeuft keine Zeile danach und die Elementliste bleibt leer. Das gemeldete fehlende Menue war der Werkzeugkasten, nicht die Verwaltungsnavigation - die wurde geprueft und ist in Chrome 152 in Ordnung. Behebung: eine Importkarte in base.html.twig haengt die Fassung an die aufgeloeste Adresse jedes Moduls, ohne dass eine Importzeile sie kennen muss. Das Zwischenspeichern ueber ein Jahr bleibt - die Leistung war nie das Problem, nur die fehlende Kennung. Eine Importkarte muss eingebettet sein; die Spezifikation kennt keine externe. Unter script-src 'self' wurde sie wortlos verworfen. AdminHeadersSubscriber erzeugt deshalb je Verwaltungsseite einen Nonce, nennt ihn in der Richtlinie und legt ihn in die Anfrage; csp_nonce() gibt ihn der Karte mit. Der Nonce erlaubt genau dieses eine Skript, 'self' gilt unveraendert fuer alles andere. Geprueft: der Browsertest verlangt an jeder angeforderten .js-Adresse eine Fassungskennung (vorher fehlten fuenf, jetzt tragen alle acht), dazu ein Test, der jeden Modulimport gegen die Importkarte haelt - Gegenprobe gemacht. npm test 28/28, phpunit 452/452, npm run test:editor vollstaendig. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7225ae052e
commit
9726af9254
7 files changed
+162
-6
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { readFileSync, readdirSync } from 'node:fs';
|
||||
import { EditorHistory, createBlock, locate, insertBlock, insertBlockAt, moveBlockTo, dropList, insertionTarget, insertRowAt, CATEGORIES, labels as blockLabels, duplicateBlock, moveBlock, upgradeDocument, effectiveDesign, setDesign, insertPreset, insertRow, blockPath, insertMedia, setEffect, isPluginBlock, blockLabel, blockIcon, canContain, isContainer, setStyle, effectiveStyle, hoverStyle, resetStyleDevice, clearStyle, copyStyle, SCHEMA_VERSION } from '../public/assets/editor-model.js';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { designCss } from '../scripts/build-design.mjs';
|
||||
@@ -492,3 +492,27 @@ test('a row dropped at an exact position brings its columns along', () => {
|
||||
// Und in eine Zeile hinein gibt es keine zweite Zeile.
|
||||
assert.equal(insertRowAt(document, 2, row.id, 0), null);
|
||||
});
|
||||
|
||||
// --- Fassungskennung an den Modulen ---------------------------------------------------------
|
||||
|
||||
test('every module imported by another one is listed in the import map', () => {
|
||||
// `public/.htaccess` laesst jede .js-Datei ein Jahr lang als `immutable` zwischenspeichern.
|
||||
// Die Einstiegsdatei bekommt ihr `?v=` aus der Vorlage, ein `import './editor-model.js'` darin
|
||||
// nicht - der Browser behielte das alte Modul und der Editor braeche mit "does not provide an
|
||||
// export named ..." ab. Genau das ist nach 1.5.0 passiert. Die Importkarte haengt die Fassung
|
||||
// an; ein neues Modul, das dort fehlt, faellt hier auf und nicht erst beim naechsten Update.
|
||||
const quellen = readdirSync('public/assets').filter(name => name.endsWith('.js'));
|
||||
const importiert = new Set();
|
||||
for (const name of quellen) {
|
||||
for (const treffer of readFileSync(`public/assets/${name}`, 'utf8').matchAll(/from '\.\/([\w-]+\.js)'/g)) {
|
||||
importiert.add(treffer[1]);
|
||||
}
|
||||
}
|
||||
assert.ok(importiert.size > 0, 'es gibt ueberhaupt Modulimporte');
|
||||
const vorlage = readFileSync('templates/admin/base.html.twig', 'utf8');
|
||||
const karte = /<script type="importmap"[\s\S]*?<\/script>/.exec(vorlage);
|
||||
assert.ok(karte, 'base.html.twig traegt eine Importkarte');
|
||||
const eingetragen = new Set([...karte[0].matchAll(/'([\w-]+)'/g)].map(treffer => `${treffer[1]}.js`));
|
||||
const fehlend = [...importiert].filter(name => !eingetragen.has(name)).sort();
|
||||
assert.deepEqual(fehlend, [], `ohne Fassungskennung in der Importkarte: ${fehlend.join(', ')}`);
|
||||
});
|
||||
Reference in new issue
Block a user