From 482575b73270d2621ea74cc1eb705b34da24500c Mon Sep 17 00:00:00 2001 From: Jan-Niclas Loosen Date: Sat, 26 Sep 2026 18:36:47 +0200 Subject: [PATCH] fix: a nested row gets its own auto label (ledger T3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A row inside a column is labelled " – Zeile (innen)" instead of repeating its outer row's " – Zeile". Guide updated. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7 --- docs/guides/divi-shortform.md | 4 ++-- src/Integrations/Divi/Compose/Composer.php | 11 +++++---- .../Divi/Compose/ComposerTest.php | 23 +++++++++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/docs/guides/divi-shortform.md b/docs/guides/divi-shortform.md index d20d59a..f9b40c3 100644 --- a/docs/guides/divi-shortform.md +++ b/docs/guides/divi-shortform.md @@ -29,8 +29,8 @@ Neue Divi-Inhalte beschreibt man als JSON-Knoten. `lit-divi-insert` (in `nodes`) Spalte eine Liste (bei einer Spalte reicht eine einfache Liste). - **Module** mit Kind-Modulen (Akkordeon, Tabs, Slider, Kontaktformular, Karte, Social-Media-Follow, Icon-Liste) bekommen ihre Einträge in `items`; der Eintragstyp ergibt sich von selbst. -- `label` fehlt → Admin-Label „ – “, z. B. „Hero – Button“. Abschnitten deshalb ein Label - geben. +- `label` fehlt → Admin-Label „ – “, z. B. „Hero – Button“; Zeilen „Hero – Zeile“, eine Zeile + in einer Spalte „Hero – Zeile (innen)“. Abschnitten deshalb ein Label geben. - `heading` ohne `level` wird `h2` (eine Seite hat meist schon eine `h1` im Titel). ## Kurzform-Felder diff --git a/src/Integrations/Divi/Compose/Composer.php b/src/Integrations/Divi/Compose/Composer.php index 92bf105..aa0ab04 100644 --- a/src/Integrations/Divi/Compose/Composer.php +++ b/src/Integrations/Divi/Compose/Composer.php @@ -263,7 +263,7 @@ final class Composer return match ($type) { 'divi/section' => $this->section($spec, $path), - 'divi/row' => $this->row($spec, $path, $context), + 'divi/row' => $this->row($spec, $path, $context, $parent !== null && $parent->name() !== 'divi/section'), default => $this->module($type, $spec, $path, $context), }; } @@ -330,8 +330,11 @@ final class Composer return $section; } - /** @param array $spec */ - private function row(array $spec, string $path, string $context): Block + /** + * @param array $spec + * @param bool $nested In a column (Divi 5 rows nest): own auto label (ledger T3). + */ + private function row(array $spec, string $path, string $context, bool $nested): Block { $this->unknownKeys($spec, array_merge(self::COMMON, self::ROW), $path); $parsed = ColumnWidths::parse($spec['columns'] ?? '4_4'); @@ -339,7 +342,7 @@ final class Composer $this->errors[$path . '.columns'] = $parsed['error']; } $widths = $parsed['widths']; - $label = $context === '' ? null : $context . ' – Zeile'; + $label = $context === '' ? null : $context . ($nested ? ' – Zeile (innen)' : ' – Zeile'); $attrs = $this->common('divi/row', ['builderVersion' => $this->builderVersion], $spec, $path, $label); $row = Block::create('divi/row', $attrs); diff --git a/tests/Unit/Integrations/Divi/Compose/ComposerTest.php b/tests/Unit/Integrations/Divi/Compose/ComposerTest.php index 05bc4ee..c1876d3 100644 --- a/tests/Unit/Integrations/Divi/Compose/ComposerTest.php +++ b/tests/Unit/Integrations/Divi/Compose/ComposerTest.php @@ -488,6 +488,29 @@ final class ComposerTest extends TestCase self::assertSame('divi/text', $nested->children()[0]->children()[0]->name()); } + /** Ledger T3: a nested row's auto label differs from its outer row's label. */ + public function testNestedRowGetsItsOwnAutoLabel(): void + { + $label = static fn (Block $block): mixed => $block->attrs()['module']['meta']['adminLabel']['desktop']['value'] ?? null; + $result = ComposeFixture::composer()->compose([['type' => 'section', 'label' => 'Hero', 'rows' => [[ + 'columns' => '1_2,1_2', + 'modules' => [[['type' => 'row', 'modules' => [['type' => 'text', 'content' => '

a

']]]], []], + ]]]], null, 'nodes'); + + self::assertSame([], $result['errors']); + $outer = $result['blocks'][0]->children()[0]; + $nested = $outer->children()[0]->children()[0]; + self::assertSame('Hero – Zeile', $label($outer)); + self::assertSame('Hero – Zeile (innen)', $label($nested)); + self::assertSame('Hero – Text', $label($nested->children()[0]->children()[0])); + + // Inserted straight into an existing column (lit-divi-insert parent = column): nested as well. + $inserted = ComposeFixture::composer()->compose([['type' => 'row']], Block::create('divi/column'), 'nodes', 'Hero'); + self::assertSame('Hero – Zeile (innen)', $label($inserted['blocks'][0])); + $intoSection = ComposeFixture::composer()->compose([['type' => 'row']], Block::create('divi/section'), 'nodes', 'Hero'); + self::assertSame('Hero – Zeile', $label($intoSection['blocks'][0])); + } + public function testRejectsNonObjectsAndMissingTypes(): void { $result = ComposeFixture::composer()->compose(['section', [], ['label' => 'x']], null, 'nodes');