Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
28 KiB
Etappe 4 – Designsystem schreiben – Design-Spezifikation
- Datum: 2026-10-16
- 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.
1. Ziel und Kontext
1.1 Problem
Das Plugin liest das Designsystem (lit/divi-design-system: Farben, Variablen, Theme-Schriften/-Größen, Presets mit Name und ID) und kann einem Modul beim Einfügen/Ändern ein Modul-Preset per Name geben ("preset": "<Name>"). Es fehlt:
- 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) 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
- Ein Corporate Design lässt sich über die Tools vollständig übernehmen: Farben, Variablen, Schriften, Theme-Optionen, Presets – und auf bestehende Seiten ausrollen.
- Jede site-weite Änderung: Probelauf mit Diff und betroffenen Seiten, erst
confirm: trueschreibt, vorher immer ein Snapshot (G2, G6). - Schreiben nur über Divis eigene Funktionen, abgesichert über Manifest und Freigabe (Divi-Absicherung).
- Schleifen-Inhalte in Modulen innerhalb einer Divi-Schleife setzen können (G12).
1.3 Erfolgskriterien
- Ein Preset lässt sich lesen (Kurz- und Vollform), anlegen (aus
set/attrsoder aus einem Modul), ändern, als Standard setzen und – wenn unbenutzt – löschen; die Frontend-Ausgabe entspricht einem im Builder angelegten Preset (Integrationstest gegen echtes Divi). - Modul- und Gruppen-Presets, auch gestapelt, lassen sich einzelnen Modulen und per Massenzuweisung vielen Seiten zuweisen; Verweise lassen sich überall entfernen.
- Farben, Variablen, Design-Theme-Optionen und Schriften lassen sich schreiben; der Builder zeigt sie danach unverändert an.
- Jede Änderung eines Bereichs erzeugt vorher einen Snapshot;
lit/divi-design-restorestellt ihn mit Probelauf wieder her. {{…}}/Vollform mitloop_post_datein einem Modul unter einer Spalte mit aktiver Schleife wird gespeichert; ohne Schleifen-Kontext kommt eine verständliche Ablehnung.- Architekturtest (Divi-Grenze) grün; alle bestehenden Tests grün; Security-Audit ohne offene kritische/hohe Punkte.
1.4 Nicht Teil dieser Etappe
- SEO-Optionen, Logo (
divi_logo), Button-Standards (all_buttons_*) (G3, A1). - MCP-Prompts und eigener Guide „Corporate Design übernehmen“ (G11) – nur Tools; Tool-Beschreibungen tragen die Reihenfolge.
- Echtes Löschen von Farben (nur
inactive, wie Divi); Löschen hochgeladener Schriften (A2). - Loop Builder anlegen (Schleife an einem Container einschalten/konfigurieren) – nur Inhalte innerhalb bestehender Schleifen (A3).
- Snapshots von Seiteninhalten (dafür WordPress-Revisionen).
2. Begriffe
- Bereich:
colors,variables,presets,theme_options– Einheit für Snapshot,design_revund Rechte. design_rev: Hash über den gelesenen Rohbestand eines Bereichs; Sperre gegen gleichzeitige Änderungen (wietree_revbei Seiten).- Änderungs-Pipeline: gemeinsamer Ablauf aller Schreib-Tools des Designsystems (§4).
- Seiten-Umschreiber: gemeinsamer Baustein, der Verweise in vielen Seiten ändert (§6.6).
- Fundstellen: Seiten, Bibliothekseinträge und Theme-Builder-Layouts, die ein Preset, eine Farbe oder Variable verwenden.
3. Architektur
Tools (Abilities) Pipeline / Domäne (reines PHP) Adapter (Divi-Grenze)
lit/divi-presets-set ─┐ DesignChange (Rechte→Prüfung→Diff→ Designsystem-Adapter
lit/divi-colors-set ─┤ confirm→Snapshot→Schreiben→Protokoll) ├ Reader (vorhanden)
lit/divi-variables-set┤──────────▶ PresetStore / ColorStore / … ──────▶ └ Writer (neu)
lit/divi-theme-options-* SnapshotStore Katalog-Adapter
lit/divi-design-restore DesignUsages (Fundstellen) (Gruppen-Namen, Preset-
lit/divi-presets-assign ─┐ SiteRewrite (Seiten-Umschreiber) ─────▶ Attr-Mapping, Google-Fonts)
lit/divi-design-detach ─┘ Seiten-Adapter (DiviSaver)
- 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/SerializerundDiviSaver(Revision je Seite, Cache), Rechte und Grenzen wieGlobalUsages/VisibleEdits. - 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)
Jedes Schreib-Tool des Designsystems:
- Rechte des Bereichs (§10).
- Eingabe prüfen: JSON-Schema, dann fachlich (Namen, IDs, Platzhalter
{{color:…}}/{{var:…}}/{{font:…}}, Werte überValueCleaner/Composer mit denselben Sperren wie bei Modulen: Lottie, Interactions, rohes HTML/CSS ohneunfiltered_html). Fehler gesammelt alsvalidation_failedmitfields. - Neuen Bestand berechnen aus aktuellem Rohbestand (live gelesen) + Änderung.
- Probelauf (ohne
confirm):diff(je Eintrag vorher/nachher, Eintragsartadded|changed|removed|deactivated),affected(Fundstellen überDesignUsages, Regeln wieUsageReport: lesbare Seiten mit Titel, sonst Anzahl;blocked_ids),design_rev. Nichts gespeichert. - Mit
confirm: true:design_revvergleichen (sonstconflict, nichts geschrieben) → Snapshot → Schreiben über Divi → nach dem Schreiben zurücklesen und mit dem erwarteten Bestand vergleichen (fängt stille Fehlschläge wie beiset_global_variables) → Caches → Protokoll. - Antwort:
ToolResultmitdiff,snapshot_id,log_id, neuemdesign_rev,warnings. - Fehler beim Schreiben oder Zurücklesen: Snapshot zurückschreiben (
Rollback),WriteFailed(rolled_back/partial).
Jedes Tool nimmt mehrere Einträge eines Bereichs je Aufruf (ein Snapshot, ein Diff) (A4). Keine Ausnahme für „harmlose“ Änderungen: auch ein neues, unbenutztes Preset braucht Probelauf + confirm.
5. Snapshots (freigegeben)
- Speicher: je Bereich eine Option
lit_mcp_snapshots_<bereich>(autoload aus), höchstens 20 Einträge (FIFO). Eintrag:id,created(UTC),user_id,ability,log_id,size,data(Rohbestand wie Divi ihn speichert; Farben inkl. der fünf Customizer-Farben auset_divi). - Größe: Snapshot über 2 MB → Änderung abgelehnt (
snapshot_too_large), statt ohne Sicherung zu schreiben. lit/divi-design-snapshots(lesen): je Bereich die Liste ohnedata, mitcursor/limit.lit/divi-design-restore(snapshot_id): Probelauf = Diff Snapshot ↔ aktueller Stand; mitconfirmSnapshot des aktuellen Stands, dann Zurückschreiben über dieselben Divi-Funktionen wie beim Schreiben. Presets:save_data()mit dem Snapshot-Bestand (ohnevalidate_preset_count, weil das Wiederherstellen Presets entfernen darf); verwaiste Verweise in Seiten meldet der Probelauf als Warnung.- Deinstallation entfernt die Snapshot-Optionen.
6. Presets
6.1 Identifikation
- Modul-Presets über
module(buttonoderdivi/button), Gruppen-Presets übergroup(font-bodyoderdivi/font-body). - Ein Preset wird über
idodernameangesprochen. Namen sind in Divi nicht eindeutig: Ein mehrdeutiger Name ist ein Fehler mit den passenden IDs (wie Ruling S13a). Neue Presets mit einem schon vergebenen Namen desselben Moduls/derselben Gruppe werden abgelehnt (A5) – strenger als Divi, damit Namen beim Zuweisen eindeutig bleiben.
6.2 Lesen: lit/divi-preset-get
- Eingabe:
moduleodergroup,idodername. - Antwort:
id,name,kind,module/group,default(Standard-Preset?),set(Einstellungen in Kurzform, soweit abbildbar),attrs(Vollform, nur was nicht insetsteht), verschachteltegroup_presetsmit Namen, Werte im selben Format wielit-divi-node-get(Roh-Verweise$variable(…)$; Namen und Platzhalter liefertlit-divi-design-system),usage(Fundstellen wie §4 Schritt 4, gekappt),design_rev. lit-divi-design-systembleibt die Übersicht (Name, ID, Standard).
6.3 Anlegen und ändern: lit/divi-presets-set
items = Liste von Einträgen:
{ "module": "button", "name": "CTA primär", // oder "group": "font-body"; "id" zum Ändern
"rename": "CTA Primär", // optional, nur beim Ändern
"set": { "background_color": "{{color:primary}}", "text_color": "#ffffff" },
"attrs": { "button.decoration.border.desktop.value.radius": "{{var:Eckenradius}}" },
"from_node": { "post_id": 12, "id": "s0.r0.c1.m2" },
"group_presets": { "font": "Button-Schrift" }, // verschachtelte Gruppen-Presets (nur Modul-Presets)
"make_default": false }
- Ohne
idund ohne gleichnamiges Preset → anlegen; mitid(oder eindeutigemname) → ändern. Ändern mischt: genannte Pfade werden gesetzt,nullentfernt einen Pfad/Breakpoint, Nicht-Genanntes bleibt (wielit-divi-update). set/attrslaufen durch den Composer des Moduls (module) bzw. des Quellmoduls der Gruppe: dieselbe Kurzform, Pfadprüfung, Platzhalter, Bereinigung und Sperren wie bei Modulen. Nur Pfade, die Divis Preset-Attribut-Mapping des Moduls kennt (Conversion::get_preset_attrs_mapping), sind erlaubt; Inhalte (Texte, URLs, Bilder-IDs …) werden abgelehnt (validation_failedmit Pfad).- Gruppen-Presets: nur Pfade unterhalb der Gruppe (
groupId, z. B.content.decoration.bodyFont); Speicherung mitgroupName,groupId, Quell-moduleNamewie der Builder (Formate §3). from_node: liest den Knoten (Leserecht auf die Seite), übernimmt alle Attribute, die das Preset-Mapping des Moduls als Preset-Attribute führt; Inhalte nicht. Kombinierbar mitset/attrs(gehen vor). Gruppen: nur die Pfade der Gruppe.styleAttrs/renderAttrswerden serverseitig mit DivisConversion::get_preset_attrs(…)berechnet,version= installierte Builder-Version,created/updatedin Millisekunden, IDs 10 Zeichen[0-9a-z](Formate §3).make_default: true: wird Standard-Preset des Moduls/der Gruppe; Probelauf nennt alle Seiten mit Modulen dieses Typs ohne eigenes Preset als betroffen.- Schreiben: vollständiger Bestand →
prepare_data()(Sanitize wie der Controller) →validate_preset_count()→save_data().
6.4 Löschen: lit/divi-presets-delete
items= Presets (module/group+id/name).- Nur unbenutzte Presets (G5): Fundstellen in Seiten, Bibliothek, Theme Builder und als verschachteltes Gruppen-Preset in anderen Presets. Sonst Fehler
in_usemit Fundstellen und dem Hinweis auflit/divi-design-detach. - Ein Standard-Preset wird erst gelöscht, nachdem
defaultauf""gesetzt ist (im selben Aufruf automatisch, im Diff sichtbar). - Schreiben wie §6.3 mit
actionType-SemantikDELETE_*(keinpreset_count_decreased); Divi-4-Altoption wie der Controller bereinigen (remove_preset_from_legacy_option).
6.5 Zuweisen an einzelne Module (lit-divi-insert, lit-divi-update, lit-content-create)
"preset": Name oder Liste von Namen (Stapel, letzter gewinnt wie in Divi);nullentfernt. SpeicherungmodulePreset: [ids]."group_presets":{ "<Gruppe>": "<Name>" | ["<Name>", …] | null }, Gruppe als Kurzname (font-body) oderdivi/font-body; Zuordnung zum Attributpfad über Divis Gruppenliste des Moduls (get_group_preset_default_attr). SpeicherunggroupPreset: { "<groupId>": { presetId: [ids], groupName } }.- Überdeckungen (G9): Lokale Werte des Moduls auf denselben Pfaden (Pfad + Breakpoint + Zustand) wie das Preset werden gemeldet (
warnings: „s0.r0.c1.m2: Hintergrundfarbe, Schriftgröße überdecken ‚CTA primär‘“).clear_overrides: trueentfernt genau diese lokalen Werte. lit-divi-outlinezeigt Gruppen-Presets mit Namen zusätzlich zu Modul-Presets.
6.6 Seiten-Umschreiber (gemeinsam für §6.7 und §6.8)
- Findet Fundstellen (
DesignUsages: lesbare Seiten, Bibliothekseinträge, Theme-Builder-Layouts; Rechte- und Theme-Builder-Regeln wieGlobalUsages), ändert je Seite den Baum überTreeEditor/Composer und speichert überDiviSaver(Revision je Seite, Cache, Protokoll). - Probelauf: je Seite die betroffenen Knoten (Pfad-ID, Modul, Label) und Überdeckungen;
blocked_idsfür Live-Seiten ohneedit_post; keine Änderung, wenn eine Seite blockiert ist (wieGlobalEdits). - Grenze je Aufruf (A6): höchstens 50 Seiten werden mit
confirmgeschrieben; die Antwort nenntremaining. Beide Operationen sind wiederholbar (Filter treffen bereits geänderte Module nicht mehr), der nächste Aufruf macht weiter. ÜberGlobalUsages::HARD_CAPLive-Seiten: Ablehnung wie bisher. - Seiten mit globalen Modulen: Instanzen werden nicht umgeschrieben, sondern der Bibliothekseintrag (eigene Fundstelle, F7-Regeln); nicht bearbeitbare/gesperrte Knoten (StoredNodeGuard) bleiben unverändert und werden gemeldet.
- Pro Seite gilt ein frisch gelesener Baum (kein
tree_revnötig); schlägt eine Seite fehl, sind die bereits gespeicherten Seiten gespeichert (Revisionen in der Antwort), die Antwort meldetpartial.
6.7 Massenzuweisung: lit/divi-presets-assign
- Eingabe:
module(Pflicht),preset(Name/Liste) und/odergroup_presets, Filter:post_ids(optional, sonst alle Fundstellen mit diesem Modultyp),only_without_preset(bool) oderonly_with_preset(Name),clear_overrides(bool, G9). - Probelauf →
confirmwie §6.6.
6.8 Verweise überall entfernen: lit/divi-design-detach
- Eingabe:
preset(module/group+ Name/ID) odervariable(Name/ID). Optionalpost_ids. - Preset: entfernt die ID aus
modulePreset/groupPreset-Stapeln; Module fallen auf das nächste Preset im Stapel bzw. das Standard-Preset zurück (G5 a). Verschachtelte Verwendung in anderen Presets entfernt der Aufruf im selben Schritt über die Pipeline (Snapshotpresets). - Variable: ersetzt die Referenz durch ihren aktuellen Wert als festen Wert (A7) – „Verweis entfernen“ ohne Wert würde Inhalte leeren; bei Farben entfällt detach (sie werden nur deaktiviert).
- Danach ist das Löschen (Presets, §6.4) bzw. das Archivieren (Variablen, §7.2) möglich.
7. Farben und Variablen
7.1 lit/divi-colors-set
items:{ id?, "label": "Primär", "color": "#5b3a29" | "{{color:Primär}}" + "relative": {hue, saturation, lightness, opacity}, "folder"?, "status": "active"|"inactive" }.idnennt eine vorhandene Farbe (ID, Name, Alias oder Optionsname); ohneidwird neu angelegt. Die fünf Hauptfarben über ihre festen Namen (accent_color…). Unbekannte Felder (z. B.delete) lehnt das Tool ab.- Schreiben über
set_global_colors($data, true)(mischen), Hauptfarben nur, wenn sie geändert werden (Standardwert-Abweichung Formate §4). Neue IDsgcid-+ 10 Zeichen. - „Löschen“ =
status: inactive; der Probelauf nennt Fundstellen in Seiten, Bibliothek und Theme Builder unteraffected; nur Presets und relative Farben, die auf die Farbe bauen, sindwarnings(Ruling V8). - Zyklen bei relativen Farben (Tiefe max. 10 wie Divi) →
validation_failed.
7.2 lit/divi-variables-set
items:{ id?, "type": "numbers|strings|images|links|fonts", "label", "value", "status": "active"|"archived" }. Echtes Löschen gibt es nicht: Divi 5.15.1 verweigert jeden Bestand, dem eine gespeichertegvid--ID fehlt (Plan 4c, Ruling V1).idnennt eine vorhandene Variable (ID, Name oder Alias); ohneidwird neu angelegt. Unbekannte Felder (z. B.delete) lehnt das Tool ab.- Prüfung je Typ (Zahlen: CSS-Ausdruck ohne
;{}, Links: URL, Bilder: Anhang-ID/URL der Mediathek, Schriften: §8.2, Strings: Text). - Schreiben: vollständig lesen,
stdClass→ Array,allowedActionsund Customizer-Schriften entfernen,set_global_variables()(ersetzt), zurücklesen (stiller Fehlschlag bei fehlendemvariables_manager). - Archivieren geht immer (Divi-Verhalten); der Probelauf nennt Fundstellen in Seiten, Bibliothek und Theme Builder unter
affected; nur Presets sindwarnings(Ruling V8).lit/divi-design-detachlöst die Verweise vorher (§6.8). Ein Restore behält später angelegte Variablen archiviert.
8. Theme-Optionen und Schriften
8.1 lit/divi-theme-options-get / lit/divi-theme-options-update
- Whitelist (G3 a): Schriften (
heading_font,body_font,primary_nav_font,secondary_nav_font,heading_font_weight,body_font_weight), Größen (body_font_size,tablet_…,phone_…,body_header_size,tablet_header_font_size,phone_header_font_size,body_font_height,body_header_height,body_header_spacing,body_header_style), Layout (content_width,gutter_width,section_padding,row_padding). - Die fünf Hauptfarben listet
getnicht; es verweist für sie nur auflit/divi-colors-set(eine Quelle, Snapshotcolors) (A8). getliefert je Feld Typ, Beschreibung, aktuellen Wert und Divi-Standard;updatebereinigt mit Divis Customizer-Sanitize-Callbacks (Katalog-Adapter), schreibt mitet_update_option()und leert die Caches wie der Customizer (remove_static_resources,et_pb_force_regenerate_templates).body_header_stylenimmt genau einen Wert (italic,uppercaseoderunderline); Divis Sanitizer lehnt Kombinationen ab.nullsetzt einen Schlüssel auf den Divi-Standard zurück (et_delete_option);'none'undfalsewerden abgelehnt.
8.2 Schriften
- Schriftnamen werden für Theme-Optionen und Schrift-Variablen geprüft (Preset- und Modul-Schriftattribute folgen in 4e), und zwar gegen Divis Google-Fonts-Liste, hochgeladene Schriften (
et_uploaded_fonts) und Web-Safe-Schriften; Unbekanntes → Fehler mit ähnlichen Namen. lit/divi-fonts-upload(G10 b):name,files({ "woff2": "<URL>", "woff": …, "ttf": …, "otf": … }),weights(alloder Liste),generic_family. Laden mitwp_safe_remote_get(Größenlimit wie Medien, Grenze je Datei 5 MB (A9)), Dateityp über Inhalt prüfen (Magic Bytes), Installation im Prozess überFontsUtility::font_add()mit Temp-Dateien (action: wp_handle_upload_rest, wie Divis KI-Pfadinstall_to_custom_fonts()); Divi legt Datei undet_uploaded_fonts-Eintrag selbst an, ein Mirrorfont-installsichert die Aufrufkonvention. Formate:woff2,woff,ttf,otf. Namensregeln wie Divi (Sonderzeichen, Länge, kein Google-/vorhandener Name).- Keine Snapshots für Schriften: ein Upload legt nur neu an, überschreibt nie (A2). Probelauf +
confirmgelten trotzdem. - DSGVO: lokales Laden der Google-Fonts bleibt Theme-Einstellung; Tool-Beschreibung weist auf hochgeladene Schriften als datensparsame Variante hin.
9. Schleifen-Inhalte (G12, umgesetzt in 4e; aus Divi 5.15.1 abgeleitet)
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.enablegenau"on"ist (Tablet-, Phone- und Hover-Varianten zählen nicht, wie bei Divi).queryTypewird wie bei Divi mitsanitize_keygelesen; fehlt er (auchnull), giltpost_types;termsunduserssind Aliase für Term- und Benutzer-Schleifen (L2). Verschachtelte Schleifen: die innerste gilt für alles darunter; fürloop_<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/VariableRefnehmen einenLoopScope. - Typabgleich als Sicherheitsgrenze: Ein
loop_*-Wert ist nur erlaubt, wenn die Art des Kontexts zur Art der Option passt; ohne Schleife ist jedeloop_*-Option abgelehnt. Grund: Divi liestloop_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ürloop_*_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 TabelleLOOPinPlaceholdersordnet Kurznamen den Optionen zu. lit/divi-dynamic-sources(X6): optionalpost_id+node(Pfad-ID): zusätzlich die zur Schleife dieses Knotens passendenloop_*-Optionen; ohne Schleife im Kontext ein Hinweis statt einer Liste; Leserecht auf die Seite wielit-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, neueloop-Attribute desselben Aufrufs zählen) und warnt, wenn der Wechsel der Schleifen-Art unveränderte Kinder mitloop_*betrifft. Move prüft am Ziel und warnt (lehnt nicht ab; A11), wennloop_*-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-createund Theme-Builder-Anlage haben nie einen Schleifen-Kontext. - Rechte (Audit L1, Option B): Eine Schleife in
module.advanced.loop, die Benutzer (user_roles) ausgibt, verlangtlist_users; eine Beitrags-Schleife mit leeren,any- oderattachment-subTypesverlangtread_private_posts; das gilt auch beim Kopieren. - Grenzen (X7, dokumentiert): Schleifen schalten über
attrsbleibt 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 mitunfiltered_htmlprü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
| Bereich / Tool | Voraussetzung |
|---|---|
Lesen (preset-get, theme-options-get, design-snapshots) |
wie lit/divi-design-system (edit_posts) |
| Farben, Presets schreiben, Restore (Farben/Presets/Variablen) | edit_theme_options (strenger als Divi, Formate §7.4) + Divi-Rolle use_visual_builder |
| Variablen | zusätzlich variables_manager |
| Theme-Optionen (schreiben, Restore) | edit_theme_options + Divi-Rolle theme_customizer (kein Visual Builder) |
| Fonts-Upload | upload_files + edit_theme_options + Divi-Rolle custom_fonts_management |
| Massenzuweisung, Detach | Recht des Bereichs + edit_post für jede Live-Fundstelle (Regeln P8/P8a), Theme-Builder-Zugriff wie bisher |
set mit rohem HTML/CSS, Lottie, Interactions |
wie bei Modulen (unfiltered_html) |
Alle Schreib-Tools sind Divi-Schreib-Tools im Sinne der Divi-Absicherung (gesperrt bei divi_untested/divi_incompatible).
11. Fehler und Antworten
- Neue Codes:
conflict(design_rev; alternativrev_mismatchmit eigener Meldung, Plan entscheidet nach Bestand),in_use(vorhandener Code, mit Fundstellen),ambiguous_name(mit IDs),snapshot_too_large,snapshot_not_found,font_fetch_failed,font_invalid. - Vorhandene:
validation_failed(fields),forbidden,confirm_required(Probelauf-Antwort wie bei globalen Modulen undlit/tb-activate: Fehlerobjekt mitdiff,affected,design_revin den Details),divi_untested/divi_incompatible,write_failed(rolled_back/partial). - Jede Antwort mit
hintbei Fehlern; Probeläufe nennen den nächsten Schritt (confirm: true,remaining).
12. Daten, Deinstallation, Sicherheit
- Neue Optionen:
lit_mcp_snapshots_{colors,variables,presets,theme_options}; Deinstallation entfernt sie. Hochgeladene Schriften bleiben (gehören Divi). - Protokoll: je Aufruf ein Eintrag mit Bereich, Anzahl Einträge,
snapshot_id, betroffene Seiten-IDs (keine Inhalte). - Security-Audit am Ende: Preset-
attrs(XSS über Style-/Render-Attribute,unfiltered_html), Font-Upload (SSRF, Dateityp, Pfad), Massen-Schreibrechte, Schleifen-Optionen (Meta-Schlüssel), Snapshot-Restore (Rechte, Größe).
13. Tests
Unit (reines PHP): Bestandsberechnung je Bereich (anlegen/ändern/mischen/löschen/deaktivieren), Diff, design_rev-Konflikt, Snapshot-FIFO und Größenlimit, Restore-Diff; Preset-Pfadfilter (Mapping, Gruppen-Pfade, Inhalte abgelehnt), from_node, Namensregeln, Stapel und Gruppen-Zuweisung, Überdeckungen und clear_overrides; Fundstellen-Erkennung (Modul-/Gruppen-Preset, verschachtelt, Variablen in Seiten/Presets/Farben); Seiten-Umschreiber (Grenze 50, remaining, blockierte Seiten, globale Module, partial); Schleifen-Kontext (selbst, Vorfahre, verschachtelt, falscher Typ, keiner), Meldungen; Rechte-Matrix; Architekturtest.
Integration gegen echtes Divi (Smoke-Skripte, Fixture-Seite 3182): Preset anlegen → Frontend-Klassen und CSS wie beim Builder-Preset; Gruppen-Preset und Stapel zuweisen; Massenzuweisung über zwei Seiten; detach + delete; Farben/Variablen schreiben und im Builder-Lesepfad unverändert; Variablen ohne variables_manager → Fehler statt stiller Erfolg; Theme-Option schreiben; Font-Upload (woff2) und Verwendung in Preset; Snapshot + Restore je Bereich; Loop-Karte mit loop_post_date speichern und rendern.
Regression: alle bestehenden Unit-Tests und Smoke-Skripte grün; lit-divi-design-system-Antwort unverändert bis auf neue Felder.
14. Umsetzungsreihenfolge
- 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.
- Pipeline,
design_rev, SnapshotStore,design-snapshots/design-restore(zuerst mit Bereichpresets). - Presets:
preset-get,presets-set(inkl.from_node, Gruppen, Standard),presets-delete. - Zuweisen an Module: Stapel,
group_presets, Überdeckungen/clear_overrides, Outline mit Gruppen-Presets. - Fundstellen (
DesignUsages) und Seiten-Umschreiber;presets-assign,design-detach. - Farben, Variablen (inkl. detach für Variablen).
- Theme-Optionen, Schriftprüfung, Fonts-Upload.
- Schleifen-Inhalte.
- Guides (
divi-design-system,divi-shortform,workflows) nachführen; Security-Audit; Version.