Add an own-HTML block, and build the DEEG offers page on the embed block

Umut asked for a block that takes custom HTML, and for an iframe on a new
DEEG offers page. Only one of those was missing.

New core block "Eigenes HTML" (document schema v24): one property, the
markup, up to 20.000 characters, written to the page unchanged. Changing it
is reserved for administrators and compared against what is stored - on
saving, on saving an area, and on restoring an older revision - exactly like
an own script. <script> and <iframe> are refused with the way to the right
place instead of being swallowed by the content security policy: scripts
belong in the script field, frames in the "Externer Inhalt" block, because
only that one asks for consent and puts the host into frame-src (ADR 106).

DEEG: /angebote existed as a draft with placeholder text. It is now built
like the legal pages - small caps line, large light heading, lead on the
tinted band - with the IS24 result list below it and a line pointing to the
portal and to the contact form. Navigation and the offers band on the home
page point there. The consent question is switched on, so the frame loads
only after the visitor agrees, and both the banner and the placeholder carry
the site's own shapes and colours.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5 committed 2026-09-16 08:27:43 +02:00
1 parent 6b1aa50d02
commit 59a40157a4
15 files changed
+465 -8

No files matched your search

+12
View File
@@ -2,6 +2,18 @@
Stand: 15.09.2026. Arbeitstitel KantSites; Produktname offen.
## ADR 106 – „Eigenes HTML“ als Baustein, und warum der Rahmen trotzdem „Externer Inhalt“ bleibt (16.09.2026)
Umut: „Als Baustein im Editor, dass man individuelles HTML einfügen kann. Z. B. möchte ich eine neue Angebotsseite bei DEEG, da soll ein iframe rein.“ Das sind zwei Wünsche, und nur einer davon fehlte.
**Den Rahmen gab es schon.** Der Baustein `embed` („Externer Inhalt“, Schema v14) bettet eine fremde Seite ein: Adresse, Titel, Anbieter, Höhe – und davor die Einwilligungsfrage. Vor der Einwilligung wird nichts geladen, kein Bild und keine Anfrage; erst danach kommt der Host in `frame-src` der Sicherheitsrichtlinie. Ein `<iframe>`, das jemand als rohes Markup einfügt, hätte beides nicht: keine Frage, und der Browser lädt es gar nicht erst, weil `frame-src` den Host nicht kennt. Deshalb ist `<iframe>` im HTML-Baustein eine Fehlermeldung mit dem Weg zum richtigen Baustein – nicht etwas, das man einfügen kann und das dann schweigend nichts tut. Dasselbe gilt für `<script>`: das Feld „Eigenes Skript“ unter „Erweitert“ liefert es als eigene Datei aus, inline würde die Richtlinie es ohnehin blockieren.
**Der Baustein (Schema v24).** `html` mit einer einzigen Eigenschaft: das Markup, bis 20.000 Zeichen, unverändert ausgegeben. Es gibt keine Filterliste – wer ihn setzen darf, ist die eigentliche Antwort, und die ist dieselbe wie beim eigenen Skript: **nur ein Administrator**. Geprüft wird wie dort gegen den gespeicherten Stand (`CustomCode::assertHtmlUnchanged()`), in beiden Controllern und auch beim Zurückholen einer alten Fassung – ein Redakteur kann eine Seite mit HTML also weiter bearbeiten, ohne das HTML anfassen zu können. Im Editor ist das Feld für ihn sichtbar und schreibgeschützt, wie das Skriptfeld.
**Warum keine Filterung wie bei Rich Text.** Genau die Fälle, für die man den Baustein nimmt – ein fremdes Widget, eine eigene Tabelle, eine Auszeichnung, die es als Baustein nicht gibt – fallen durch jede Whitelist. Ein gefilterter HTML-Baustein hätte den Wunsch nicht erfüllt, sondern nur verschoben.
**Folgen.** `README.md` nennt den Baustein und seine Rolle. Nicht gebaut: eine Vorschau, die fremde Skripte ausführt (die Editorvorschau führt keine aus, das bleibt so), und eine Ausnahme von der Administratorregel für einzelne Seiten.
## ADR 105 – Designpakete in Plugins zurückgenommen: das Design gehört der Website (16.09.2026)
Umut hatte auf der DEEG-Installation „Nachtblau“ eingeschaltet und wieder ausgeschaltet – und die Farben blieben. Die Ursache war nicht der Schalter (`activate()`/`deactivate()` fassen das Design nie an), sondern der zweite Knopf daneben: „Designpaket übernehmen“ schrieb die Palette des Plugins über `Theme::save()` endgültig in die Website. Technisch war das gewollt (ADR 103: ein Import, damit sich das Ergebnis unter Design weiter anpassen lässt und beim Ausschalten nichts verlorengeht) – in der Bedienung war es eine Falle: eine Aktion, die die gesamte Palette ersetzt, ohne Rückfrage und ohne Weg zurück, auf einem Bildschirm, wo daneben ein Schalter sitzt, den man gefahrlos umlegen kann.
+16
View File
@@ -1,5 +1,21 @@
# Projektstatus
## Baustein „Eigenes HTML“, DEEG-Angebotsseite (16.09.2026)
**Anlass:** Umut: „Als Baustein im Editor, dass man individuelles HTML einfügen kann … z. B. eine neue Angebotsseite bei DEEG, da soll ein iframe rein, im gleichen Stil wie das Impressum.“
**Gebaut.** Neuer Kernbaustein `html` („Eigenes HTML“, Dokumentschema **v24**): eine Eigenschaft, das Markup bis 20.000 Zeichen, unverändert ausgegeben. `CustomCode::checkHtml()` weist `<script>` und `<iframe>` mit dem Weg zum richtigen Ort ab; `CustomCode::assertHtmlUnchanged()` hält Änderungen auf die Administratorrolle fest – in `EditorController` (Speichern und Zurückholen einer Fassung) und in `PartialController`, wie beim eigenen Skript. Im Editor: Eintrag in der Gruppe „Seite und Daten“, mehrzeiliges Feld, schreibgeschützt ohne Administratorrolle. In `site.css` nur so viel Regel, dass fremdes Markup die Spalte nicht sprengt.
**Nicht gebaut, weil vorhanden:** der iframe. Der Baustein „Externer Inhalt“ (v14) macht das seit Langem – mit Einwilligung davor und dem Host in `frame-src`. Begründung in ADR 106.
**DEEG.** Die Seite `/angebote` gab es schon (im Editor angelegt, Starterabschnitt plus Rahmen mit Platzhaltertexten „test“). Sie ist jetzt im Stil der Rechtsseiten aufgebaut: Kleinzeile, große leichte Überschrift „Unsere Angebote“, Vorspann auf heller Fläche, darunter die IS24-Ergebnisliste (Portal 16200281, Höhe 1000) und eine Hinweiszeile zum Portal und zum Kontakt. „Immobilien“ in der Navigation und der Knopf im Angebote-Band der Startseite zeigen auf `/angebote` statt auf die alte Website. Aufbau per Skript: `scripts/add-immobilien-deeg-angebote.php`.
**Einwilligung und Gestaltung (DEEG).** Die Gruppe „Externe Inhalte“ ist eingeschaltet (`consentBanner`, `consentGroups`), der Balken trägt die Farben der Website (eckig, Logo-Blau als Akzent, Papier als Fläche). Vor der Zustimmung steht der Platzhalter, und der trägt über eigenes CSS am Block denselben Zuschnitt wie die Vorlage: eckiger Rahmen auf heller Fläche, linksbündig, blauer Knopf. **Gestaltbar ist der Rahmen, nicht sein Inhalt** – Abstände, Breite, Rand, Ecken und Höhe gehören dieser Website, die Darstellung der Liste gehört ImmobilienScout24; an fremdes Dokument im iframe kommt kein CSS heran, das trennt der Browser. Im Browser geprüft: Platzhalter, Zustimmung, geladene Liste.
**Nicht mehr offen:** Die Einwilligungsfrage war auf dieser Installation aus (`consentBanner` false, keine Gruppen). Das ist erledigt: Umut hat die Einwilligung eingeschaltet, ein fremder Rahmen lädt jetzt erst nach der Zustimmung.
**Geprüft:** `phpunit` 574 Tests grün, `npm test` 35 (neu: der Baustein startet leer, steht im Werkzeugkasten, hebt das Dokument auf v24). `npm run test:editor` um den ganzen Weg erweitert und bestanden: Baustein aus dem Werkzeugkasten einfügen, Markup eintippen, in der Vorschau sehen, veröffentlichen, auf der Website Zeichen für Zeichen wiederfinden – und `<script>` wie `<iframe>` werden mit ihrer Meldung abgewiesen (422, Meldung in der Leiste über dem Editor), ohne die veröffentlichte Seite anzufassen. Zwei neue PHP-Tests: Markup erscheint unverändert auf der veröffentlichten Seite und `<script>`, `<iframe>` sowie Schema v23 werden abgewiesen; HTML-Änderungen werden gegen den gespeicherten Stand geprüft.
## Fassung 1.19.0 veröffentlicht (16.09.2026)
**Anlass:** Umut: „Ja committe das bitte und push mit neuem Release.“ Die Rücknahme der Designpakete geht als 1.19.0 heraus.