Stop text from being encoded again on every save
Umut: "Beim Startseitenbild wird der Text & umgewandelt, aber in der Ansicht nach dem Speichern wird & daraus." RichText::sanitise() treated text without a single tag as plain text and only escaped it. What the editor sends is HTML, tag or no tag - so "Freudenstadt & Umgebung" gained one level of encoding on every save (&amp;, &amp;amp; ...) until the entity stood on the page for everyone to read. The draft of the kant-it.de home page had already reached three levels. The same branch carried a second fault of the same kind: nl2br() left the newline behind the <br>, and the next pass turned it into a second <br> via breakLines() - one paragraph became two. The branch now decodes first and replaces the line break instead of adding to it, so it ends up with the same representation as the DOM branch and both are stable under repeated saves. scripts/repair-doubled-entities.php cleans up what is already stored: the published and draft revision of every page and the areas, with a dry run, each change checked against the validator. Older revisions stay as history. DEEG: favicon is now its own square mark - the roof gable from the logo, white on the logo blue, rendered from logo-deeg.png - instead of the centre crop of the wide logo, which showed the "EE" of the wordmark. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d885b3ddb5
commit
4539f357c1
6 files changed
+297
-1
No files matched your search
@@ -3111,6 +3111,46 @@ final class CmsTest extends TestCase
|
||||
$code->assertScriptsUnchanged($added, $before);
|
||||
}
|
||||
|
||||
public function testSavingTextTwiceKeepsAmpersandsAndLineBreaksAsTheyAre(): void
|
||||
{
|
||||
// Umut: „Beim Startseitenbild wird & umgewandelt, aber nach dem Speichern steht &
|
||||
// da.“ Der Editor schickt HTML - auch ein Text ohne ein einziges Tag. Wurde der nur
|
||||
// escaped statt vorher dekodiert, wuchs die Entity bei jedem Speichern um eine Stufe,
|
||||
// bis sie sichtbar auf der Seite stand. Dasselbe galt fuer den Zeilenumbruch: nl2br()
|
||||
// liess das \n hinter dem <br> stehen, und der zweite Durchlauf machte zwei daraus.
|
||||
$text = new RichText();
|
||||
foreach ([
|
||||
'Freudenstadt & Umgebung' => 'Freudenstadt & Umgebung',
|
||||
'Haus & Hof' => 'Haus & Hof',
|
||||
'5 < 7 & mehr' => '5 < 7 & mehr',
|
||||
"Zeile eins\nZeile zwei" => 'Zeile eins<br>Zeile zwei',
|
||||
'<p>A & B</p>' => '<p>A & B</p>',
|
||||
'<b>woertlich</b>' => '<b>woertlich</b>',
|
||||
] as $eingabe => $erwartet) {
|
||||
$einmal = $text->sanitise($eingabe);
|
||||
self::assertSame($erwartet, $einmal, $eingabe);
|
||||
// Und jedes weitere Speichern laesst es, wie es ist.
|
||||
self::assertSame($einmal, $text->sanitise($einmal), 'zweites Speichern: '.$eingabe);
|
||||
self::assertSame($einmal, $text->sanitise($text->sanitise($einmal)), 'drittes Speichern: '.$eingabe);
|
||||
}
|
||||
|
||||
// Und durch das ganze Dokument, so wie es beim Speichern einer Seite passiert.
|
||||
$document = DemoContent::starter('Kaufmaennisches Und');
|
||||
$document['schemaVersion'] = 17;
|
||||
$document['blocks'][0]['children'][0]['props']['text'] = 'Freudenstadt & Umgebung';
|
||||
$document['blocks'][0]['children'][1]['props']['text'] = 'Immobilien & Verwaltung';
|
||||
$id = $this->publishedPage('und', 'Und');
|
||||
for ($runde = 0; $runde < 3; ++$runde) {
|
||||
$stand = $this->pages->findForEditor($id);
|
||||
$this->pages->publish($id, $this->pages->saveDraft($id, $document, $stand['version']), $this->pages->findForEditor($id)['version']);
|
||||
$document = $this->pages->findForEditor($id)['document'];
|
||||
}
|
||||
$html = $this->request('/und')->getContent();
|
||||
self::assertStringContainsString('Freudenstadt & Umgebung', $html);
|
||||
self::assertStringContainsString('Immobilien & Verwaltung', $html);
|
||||
self::assertStringNotContainsString('&amp;', $html, 'Nach drei Speichervorgaengen steht immer noch ein einziges Und da.');
|
||||
}
|
||||
|
||||
public function testOwnHtmlReachesThePageUnchangedAndRefusesScriptAndFrame(): void
|
||||
{
|
||||
// Der Baustein „Eigenes HTML“ (Schema v24): Markup des Betreibers, unverändert auf der
|
||||
|
||||
Reference in new issue
Block a user