diff --git a/src/Integrations/Divi/Compose/AttrWriter.php b/src/Integrations/Divi/Compose/AttrWriter.php index 2c2e528..3a71f70 100644 --- a/src/Integrations/Divi/Compose/AttrWriter.php +++ b/src/Integrations/Divi/Compose/AttrWriter.php @@ -35,10 +35,11 @@ final class AttrWriter private const URL_SEGMENT = '/url$/i'; /** - * Raw HTML/CSS fields, and the ones Divi re-serializes whole pages for (ruling S7), at any - * depth: module.advanced.html, module.advanced.html.htmlBefore, css.advanced.customCss. + * Raw HTML/CSS fields, and the ones Divi re-serializes whole pages for (rulings S7/S26), by + * path shape at any depth: module.advanced.html(.htmlBefore), module.decoration.attributes, + * any free-form custom CSS path of any module (css, css.*, title.css.*, css.advanced.customCss). */ - private const BUILDER_ONLY = '/(^|\.)(decoration\.attributes|advanced\.html|advanced\.customCss)(\.|$)/'; + private const BUILDER_ONLY = '/(^|\.)(decoration\.attributes|advanced\.html|advanced\.customCss|css)(\.|$)/'; public function __construct( private ModuleCatalog $catalog, diff --git a/src/Integrations/Divi/Compose/VariableRef.php b/src/Integrations/Divi/Compose/VariableRef.php index 65fc4f4..eb7a945 100644 --- a/src/Integrations/Divi/Compose/VariableRef.php +++ b/src/Integrations/Divi/Compose/VariableRef.php @@ -22,7 +22,7 @@ use stdClass; * Allowed names: * - type "color": a global color ID of the design system or a global variable of type "colors"; * settings hue/saturation/lightness/opacity, numbers only. - * - type "content": a non-color global variable or a theme font (settings DESIGN_SETTINGS); + * - type "content": a non-color global variable or a theme font (no settings, DESIGN_SETTINGS, S27); * custom_meta_ with META_KEY (no leading "_", ruling S12; settings from the map entry of * that exact name, else META_SETTINGS); or a key of the dynamic content map. * @@ -59,8 +59,13 @@ final class VariableRef /** Settings of custom_meta_ without a map entry of its own. */ public const META_SETTINGS = self::BEFORE_AFTER; - /** Settings of content references to global variables and theme fonts. */ - public const DESIGN_SETTINGS = self::BEFORE_AFTER; + /** + * Settings of content references to global variables and theme fonts: none (ruling S27). + * Divi ignores them: theme fonts resolve to var() (DynamicData.php:300), and the gvid + * option "doesn't have any settings" and renders without them + * (DynamicContentGlobalVariableOptions.php:66-69, 155-161). + */ + public const DESIGN_SETTINGS = []; private const BEFORE_AFTER = ['before' => 'richtext', 'after' => 'richtext']; diff --git a/tests/Unit/Integrations/Divi/Compose/AttrWriterTest.php b/tests/Unit/Integrations/Divi/Compose/AttrWriterTest.php index f2082af..1291fdd 100644 --- a/tests/Unit/Integrations/Divi/Compose/AttrWriterTest.php +++ b/tests/Unit/Integrations/Divi/Compose/AttrWriterTest.php @@ -263,6 +263,26 @@ final class AttrWriterTest extends TestCase ComposeFixture::attrWriter()->cleanValue('divi/button', 'module.decoration.attributes', ['attributes' => []]); } + /** Ruling S26: every free-form custom CSS path (css.*) is builder-only for editors, by path shape. */ + public function testCustomCssPathsNeedUnfilteredHtml(): void + { + $css = ['mainElement' => 'color:red;} body{display:none']; + foreach (['css', 'css.desktop', 'css.advanced.customCss', 'css.advanced.mainElement', 'title.css'] as $path) { + try { + ComposeFixture::attrWriter()->cleanValue('divi/text', $path, $css); + self::fail('Accepted for an editor: ' . $path); + } catch (InvalidArgumentException $e) { + self::assertStringContainsString('nur im Divi-Builder', $e->getMessage()); + } + + self::assertSame($css, ComposeFixture::attrWriter(true)->cleanValue('divi/text', $path, $css)); + } + + // Only a whole "css" segment counts. + self::assertSame('x', ComposeFixture::attrWriter()->cleanValue('divi/text', 'module.advanced.cssClass', 'x')); + self::assertSame('x', ComposeFixture::attrWriter()->cleanValue('divi/text', 'module.cssish', 'x')); + } + /** Ruling S23: content.innerContent of unknown kind (defined only in Divi's JS) is rich text. */ public function testUnknownContentInnerContentIsRichText(): void { diff --git a/tests/Unit/Integrations/Divi/Compose/VariableRefTest.php b/tests/Unit/Integrations/Divi/Compose/VariableRefTest.php index 548412c..c351c94 100644 --- a/tests/Unit/Integrations/Divi/Compose/VariableRefTest.php +++ b/tests/Unit/Integrations/Divi/Compose/VariableRefTest.php @@ -134,6 +134,8 @@ final class VariableRefTest extends TestCase '$variable({"type":"color","value":{"name":"gcid-a1b2;}","settings":{}}})$', 'Name', ], + 'settings on a global variable' => [self::content('gvid-s1', '{"before":"x"}'), 'before'], + 'settings on a theme font' => [self::content('--et_global_heading_font', '{"after":""}'), 'after'], 'unknown settings key' => [self::content('post_title', '{"before":"","foo":"1"}'), 'foo'], 'setting the option lacks' => [self::content('post_featured_image', '{"before":"x"}'), 'before'], 'enable_html' => [self::content('custom_meta_telefon', '{"before":"","after":"","enable_html":"on"}'), 'enable_html'],