chore: Version 0.7.0 (Etappe 4); Spec und Notizen nachgeführt

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Niclas Loosen
2026-10-20 00:31:24 +02:00
co-authored by Claude Sonnet 5.5
parent 1fdcb2e075
commit b91c356a28
7 changed files with 132 additions and 15 deletions
@@ -1,7 +1,7 @@
# Etappe 4 – Designsystem schreiben – Design-Spezifikation
- **Datum:** 2026-10-16
- **Status:** Entwurf zur Freigabe
- **Status:** umgesetzt (Etappe 4a–4e, Version 0.7.0)
- **Autor:** Jan-Niclas Loosen (Loosen-IT), erarbeitet mit Claude
- **Einordnung:** Etappe 4 der Gesamt-Spec (`2026-09-25-wp-lit-mcp-design.md` §7, §13); baut auf der Divi-Absicherung (`2026-09-29-divi-absicherung-design.md`) auf. Entscheidungen G1–G12: `docs/superpowers/notes/2026-09-28-etappe-4-entscheidungen-entwurf.md`. Datenformate: `docs/superpowers/notes/2026-09-28-etappe-4-divi-formate.md` (Divi 5.2.1).
- **Annahmen** sind mit **(A…)** markiert: Punkte, die im Brainstorming nicht einzeln gefragt wurden; bei der Freigabe der Spec bestätigen oder ändern.
@@ -15,7 +15,7 @@ Das Plugin liest das Designsystem (`lit/divi-design-system`: Farben, Variablen,
- Einstellungen eines Presets lesen; Presets anlegen, ändern, löschen; Gruppen-Presets und Preset-Stapel zuweisen; Presets auf viele Seiten auf einmal ausrollen oder überall entfernen.
- Globale Farben, Variablen, Design-Theme-Optionen und Schriften schreiben.
- Eine Wiederherstellung: Divi 5 führt für Farben, Variablen und Presets keine serverseitige Historie (Formate §7.6).
- Schleifen-Inhalte (`loop_*`, z. B. Datum oder Kategorien in Karten einer Loop-Spalte) werden immer abgelehnt (Ruling S36), mit irreführender Meldung „nur innerhalb von Divi-Schleifen“ (G12).
- Schleifen-Inhalte (`loop_*`, z. B. Datum oder Kategorien in Karten einer Loop-Spalte) wurden bis 4d immer abgelehnt (Ruling S36), mit irreführender Meldung „nur innerhalb von Divi-Schleifen“ (G12); seit 4e gelten die Regeln aus §9.
### 1.2 Ziele
@@ -65,7 +65,7 @@ lit/divi-design-detach ─┘
- Neue Divi-Aufrufe liegen nur im **Designsystem-Adapter** (Schreiben: `GlobalData::set_global_colors`, `set_global_variables`, `GlobalPreset::prepare_data`, `validate_preset_count`, `save_data`, `et_update_option`, `FontsUtility`/Divis Upload-Filter) und im **Katalog-Adapter** (`GlobalPreset::get_group_preset_default_attr`, `get_default_group_name`, `Conversion::get_preset_attrs_mapping`, `get_preset_attrs`, `et_builder_get_google_fonts`, Loop-Optionen). Jeder Eintrag steht im Manifest; nachgebaute Logik bekommt einen Fingerabdruck. Divi-Funktionen werden aufgerufen, wo möglich, statt nachgebaut.
- Domänenklassen (Bestände berechnen, Diff, Prüfregeln, Überdeckungen) sind reines PHP und unit-testbar; sie arbeiten auf den Rohdaten des Adapters.
- Seitenänderungen laufen über die vorhandenen Bausteine: `Parser`/`TreeEditor`/`Composer`/`Serializer` und `DiviSaver` (Revision je Seite, Cache), Rechte und Grenzen wie `GlobalUsages`/`VisibleEdits`.
- Formate stammen aus Divi 5.2.1; freigegeben ist inzwischen 5.14.0. **Erster Umsetzungsschritt:** Formate und Funktionssignaturen gegen 5.14.0 prüfen und die Formate-Notiz nachführen (Spec §14 Gesamt-Spec: „nur aus Code abgeleitet“).
- Formate stammen aus Divi 5.2.1 (Formate aus 5.2.1/5.14.0 geprüft, 5.15.1 maßgeblich); freigegeben sind 5.2.1, 5.14.0 und 5.15.1. **Erster Umsetzungsschritt:** Formate und Funktionssignaturen gegen 5.15.1 prüfen und die Formate-Notiz nachführen (Spec §14 Gesamt-Spec: „nur aus Code abgeleitet“).
## 4. Änderungs-Pipeline (freigegeben)
@@ -190,15 +190,20 @@ Jedes Tool nimmt **mehrere Einträge** eines Bereichs je Aufruf (ein Snapshot, e
- Keine Snapshots für Schriften: ein Upload legt nur neu an, überschreibt nie (A2). Probelauf + `confirm` gelten trotzdem.
- DSGVO: lokales Laden der Google-Fonts bleibt Theme-Einstellung; Tool-Beschreibung weist auf hochgeladene Schriften als datensparsame Variante hin.
## 9. Schleifen-Inhalte (G12)
## 9. Schleifen-Inhalte (G12, umgesetzt in 4e; aus Divi 5.15.1 abgeleitet)
- **Kontext:** Für den Zielknoten wird der nächste Knoten auf dem Weg Wurzel → Knoten (einschließlich des Knotens selbst) gesucht, dessen `module.advanced.loop.desktop.value.enable` an ist; daraus `queryType` (`post_types`, `post_taxonomies`/`terms`, `user_roles`/Benutzer, Menü …). Genaue Regeln (Selbst vs. Vorfahre, verschachtelte Schleifen, Werte von `queryType`) werden im ersten Umsetzungsschritt aus Divi 5.14.0 abgeleitet (`LoopUtils`, `LoopContext`, `DynamicContentLoopOptions`, Visual-Builder-Logik) und in der Formate-Notiz festgehalten.
- **Erlaubte Optionen:** `DynamicContentMap` liefert `loop_*`-Optionen nicht mehr verworfen, sondern getrennt je Query-Typ (Optionen aus Divis Registry, Zuordnung zum Query-Typ aus Divis Code). `DynamicContentRules::fieldsFor()` bekommt den Schleifen-Kontext; `loop_*` nur, wenn eine Schleife vorhanden ist und die Option zum Query-Typ passt. Einstellungen werden wie alle Dynamic-Content-Einstellungen je Feldtyp bereinigt, Meta-Schlüssel-Regeln S29/S30 inklusive `loop_*_meta_key_`.
- **Meldungen:** ohne Schleife: „Schleifen-Inhalt "%s" braucht eine Divi-Schleife in diesem Modul oder einem übergeordneten Element (Abschnitt, Zeile, Spalte, Gruppe).“; falscher Typ: „… passt nicht zur Schleife dieses Elements (Typ: Terme).“
- **Kurzform:** Platzhalter `{{loop:<option>}}` (z. B. `{{loop:post_date}}` → `loop_post_date`) mit Einstellungen wie `{{post:…}}` (A10).
- **`lit/divi-dynamic-sources`:** optional `post_id` + `node` (Pfad-ID) → zusätzlich die `loop_*`-Optionen des Schleifen-Kontexts dieses Knotens.
- Knoten, die per Insert/Move in eine Schleife gelangen oder sie verlassen: Prüfung am Zielort; ein Move, der vorhandene `loop_*`-Inhalte aus der Schleife herausführt, erzeugt eine Warnung (nicht abgelehnt – Divi lässt das zu) (A11).
- Ruling S36 wird abgelöst; Sicherheitsblick im Audit (§12).
Belege: `docs/superpowers/notes/2026-10-19-etappe-4e-recherche-schleifen.md`; Audit: `…-etappe-4e-security-audit.md`.
- **Kontext (X1):** Der Schleifen-Kontext eines Knotens ist der des nächsten Vorfahren-oder-selbst, dessen `module.advanced.loop.desktop.value.enable` genau `"on"` ist (Tablet-, Phone- und Hover-Varianten zählen nicht, wie bei Divi). `queryType` wird wie bei Divi mit `sanitize_key` gelesen; fehlt er (auch `null`), gilt `post_types`; `terms` und `users` sind Aliase für Term- und Benutzer-Schleifen (L2). Verschachtelte Schleifen: die innerste gilt für alles darunter; für `loop_<art>_meta_key_*`-Optionen muss die Art jeder eingeschalteten Schleife der Vorfahrenkette passen, weil eine leere innere Schleife ihren Block unverändert an die äußere gibt (Kettenregel, Audit M1).
- **Arten und Optionen (X2):** `post` (`post_types`, `current_page`), `term` (`post_taxonomies`, `terms`), `user` (`user_roles`, `users`), `menu` (`menus`). Die Art einer Option folgt der Gruppe der Divi-Option, die drei Meta-Schlüssel-Optionen dem Namen; gespeichert wird der Array-Schlüssel (`loop_term_name`). `repeater_<ACF>`-Schleifen sind nicht unterstützt: `loop_*` darin wird abgelehnt (X7e). `DynamicContentMap::loopFields($art)` liefert die Optionen je Art, `DynamicContentRules`/`VariableRef` nehmen einen `LoopScope`.
- **Typabgleich als Sicherheitsgrenze:** Ein `loop_*`-Wert ist nur erlaubt, wenn die Art des Kontexts zur Art der Option passt; ohne Schleife ist jede `loop_*`-Option abgelehnt. Grund: Divi liest `loop_post_meta_key_*` in einer Term-/Benutzer-Schleife als Post-Meta des Objekts mit der Schleifen-ID (und umgekehrt). Die Meta-Schlüssel-Regeln S29/S30 gelten auch für `loop_*_meta_key_`.
- **Meldungen (X5):** ohne Schleife: „Schleifen-Inhalt "%s" braucht eine Divi-Schleife in diesem Modul oder einem übergeordneten Element (Abschnitt, Zeile, Spalte, Gruppe).“; falsche Art: „… passt nicht zur Schleife dieses Elements (Typ: Terme).“ (Typ: Beiträge, Terme, Benutzer, Menü).
- **Kurzform (X4):** `{{loop:<option>}}` (z. B. `{{loop:post_date}}` → `loop_post_date`) mit Einstellungen wie `{{post:…}}` (A10); die Tabelle `LOOP` in `Placeholders` ordnet Kurznamen den Optionen zu.
- **`lit/divi-dynamic-sources` (X6):** optional `post_id` + `node` (Pfad-ID): zusätzlich die zur Schleife dieses Knotens passenden `loop_*`-Optionen; ohne Schleife im Kontext ein Hinweis statt einer Liste; Leserecht auf die Seite wie `lit-divi-node-get`.
- **Insert, Update, Move (X3):** Insert prüft im Kontext der Zielposition; schaltet ein Aufruf eine neue Schleife und `loop_*`-Inhalt zugleich ein, wird fail closed auf den komponierten Blöcken entschieden. Update prüft im Kontext des Knotens (ein Composer je Kontext, neue `loop`-Attribute desselben Aufrufs zählen) und warnt, wenn der Wechsel der Schleifen-Art unveränderte Kinder mit `loop_*` betrifft. Move prüft am Ziel und **warnt** (lehnt nicht ab; A11), wenn `loop_*`-Inhalte ihre Schleife verlassen oder in eine andere Art kommen. Die Warnung gilt nur für Inhalte, die vorher zur Schleifen-Kette passten (M1). `lit-content-create` und Theme-Builder-Anlage haben nie einen Schleifen-Kontext.
- **Rechte (Audit L1, Option B):** Eine Schleife in `module.advanced.loop`, die Benutzer (`user_roles`) ausgibt, verlangt `list_users`; eine Beitrags-Schleife mit leeren, `any`- oder `attachment`-`subTypes` verlangt `read_private_posts`; das gilt auch beim Kopieren.
- **Grenzen (X7, dokumentiert):** Schleifen schalten über `attrs` bleibt möglich (A3 verbietet nur ein eigenes Werkzeug); globale Module werden nicht betreten, `loop_*` in Bibliothekseinträgen wird abgelehnt (die Einfügung globaler Instanzen und das Kopieren mit `unfiltered_html` prüfen die Art nicht, Audit L3, offen); Schleifen aus Presets erkennt die Baumprüfung nicht (fail closed).
- Ruling S36 ist abgelöst (X5).
## 10. Rechte
@@ -236,7 +241,7 @@ Alle Schreib-Tools sind Divi-Schreib-Tools im Sinne der Divi-Absicherung (gesper
## 14. Umsetzungsreihenfolge
1. Formate und Signaturen gegen Divi 5.14.0 prüfen (Presets, Farben, Variablen, Theme-Optionen, Fonts, Loop-Kontext); Formate-Notiz nachführen; Manifest-Einträge.
1. Formate und Signaturen gegen Divi 5.15.1 prüfen (Presets, Farben, Variablen, Theme-Optionen, Fonts, Loop-Kontext); Formate-Notiz nachführen; Manifest-Einträge.
2. Pipeline, `design_rev`, SnapshotStore, `design-snapshots`/`design-restore` (zuerst mit Bereich `presets`).
3. Presets: `preset-get`, `presets-set` (inkl. `from_node`, Gruppen, Standard), `presets-delete`.
4. Zuweisen an Module: Stapel, `group_presets`, Überdeckungen/`clear_overrides`, Outline mit Gruppen-Presets.