Commit 6c57fc84275 for woocommerce
commit 6c57fc84275c939c66df3e7ada1748370b26cdd7
Author: Rostislav Wolný <1082140+costasovo@users.noreply.github.com>
Date: Mon Sep 14 16:58:07 2026 +0200
Email Editor: De-duplicate personalization tag chip styles (#68501)
* Add a shared stylesheet for personalization tag chips
The chip styles for rich-text comments were kept in two identical copies,
one for the editor iframe and one for the sidebar fields in the admin
document. They only exist to override core's currentColor/invert look with
the admin accent colour, so a single file in the PHP package now carries the
three differing properties and is injected into both documents: through the
editor settings for the iframe and as an inline style on wp-edit-post for
the admin document. Core's block-editor content styles load in both places
and supply the border radius and padding.
The rules are flat on purpose: the editor's selector prefixing does not
handle nested CSS, so the old nested span rule only worked because the
iframed canvas skips prefixing.
* Remove the duplicated personalization tag chip styles
Both copies are replaced by rich-text-comment.css in the PHP package, which
now styles the chips in the iframe and in the admin document. The
"temporary" framing pointed at Gutenberg PR 62128, which shipped in WP 6.8.
* Add tests for the shared personalization tag chip styles
Cover both injection points so the styles cannot silently drift back into
two copies: the iframe settings must carry the file exactly once and
unchanged, the admin document must receive it exactly once on wp-edit-post,
and the file must stay flat. Enqueue registries are global and not reset by
WP_UnitTestCase, so the base class gains opt-in swap/restore helpers that
tests touching enqueue state can use.
diff --git a/packages/js/email-editor/changelog/update-wooplug-7698-rich-text-comment-styles b/packages/js/email-editor/changelog/update-wooplug-7698-rich-text-comment-styles
new file mode 100644
index 00000000000..9dc8c4b6ffd
--- /dev/null
+++ b/packages/js/email-editor/changelog/update-wooplug-7698-rich-text-comment-styles
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Remove the duplicated personalization tag chip styles from the sidebar stylesheet.
diff --git a/packages/js/email-editor/src/components/block-editor/style.scss b/packages/js/email-editor/src/components/block-editor/style.scss
index aeecd243462..c7e503e23e8 100644
--- a/packages/js/email-editor/src/components/block-editor/style.scss
+++ b/packages/js/email-editor/src/components/block-editor/style.scss
@@ -8,25 +8,6 @@
width: 100%;
}
-// Temporary styles for Rich Text HTML comments from the PR: https://github.com/WordPress/gutenberg/pull/62128/files
-[data-rich-text-comment],
-[data-rich-text-format-boundary] {
- border-radius: 2px;
-}
-
-[data-rich-text-comment] {
- background-color: var(
- --wp-components-color-accent,
- var(--wp-admin-theme-color, #3858e9)
- );
-
- span {
- color: var(--wp-components-color-accent-inverted, #fff);
- filter: none;
- padding: 0 2px;
- }
-}
-
.woocommerce-settings-panel-preheader-text {
margin-top: 9px;
}
diff --git a/packages/php/email-editor/changelog/update-wooplug-7698-rich-text-comment-styles b/packages/php/email-editor/changelog/update-wooplug-7698-rich-text-comment-styles
new file mode 100644
index 00000000000..51529124f4e
--- /dev/null
+++ b/packages/php/email-editor/changelog/update-wooplug-7698-rich-text-comment-styles
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Move the personalization tag chip styles to a single flattened stylesheet loaded into both the editor iframe and the admin document.
diff --git a/packages/php/email-editor/src/Engine/class-assets-manager.php b/packages/php/email-editor/src/Engine/class-assets-manager.php
index bfd59d371f2..30a14d4c632 100644
--- a/packages/php/email-editor/src/Engine/class-assets-manager.php
+++ b/packages/php/email-editor/src/Engine/class-assets-manager.php
@@ -119,6 +119,8 @@ class Assets_Manager {
// Load CSS from Post Editor.
wp_enqueue_style( 'wp-edit-post' );
+ // Print the personalization tag chip styles right after core's editor styles by attaching them to the wp-edit-post handle.
+ wp_add_inline_style( 'wp-edit-post', (string) file_get_contents( __DIR__ . '/rich-text-comment.css' ) );
// Load CSS for the format library - used for example in popover.
wp_enqueue_style( 'wp-format-library' );
// Enqueue CSS containing --wp--preset variables.
diff --git a/packages/php/email-editor/src/Engine/class-settings-controller.php b/packages/php/email-editor/src/Engine/class-settings-controller.php
index 2579ca02586..8b6c38c92b9 100644
--- a/packages/php/email-editor/src/Engine/class-settings-controller.php
+++ b/packages/php/email-editor/src/Engine/class-settings-controller.php
@@ -66,9 +66,11 @@ class Settings_Controller {
$settings['allowedIframeStyleHandles'] = $this->allowed_iframe_style_handles;
$editor_content_styles = file_get_contents( __DIR__ . '/content-editor.css' );
$shares_content_styles = file_get_contents( __DIR__ . '/content-shared.css' );
+ $rich_text_comment_styles = file_get_contents( __DIR__ . '/rich-text-comment.css' );
$settings['styles'] = array(
array( 'css' => $editor_content_styles ),
array( 'css' => $shares_content_styles ),
+ array( 'css' => $rich_text_comment_styles ),
);
$settings['autosaveInterval'] = 60;
diff --git a/packages/php/email-editor/src/Engine/content-editor.css b/packages/php/email-editor/src/Engine/content-editor.css
index de8999eff7a..f08becc07e3 100644
--- a/packages/php/email-editor/src/Engine/content-editor.css
+++ b/packages/php/email-editor/src/Engine/content-editor.css
@@ -153,27 +153,6 @@ ol {
display: none;
}
-/*
- * Temporary styles for Rich Text HTML comments from the PR: https://github.com/WordPress/gutenberg/pull/62128/files
- */
-[data-rich-text-comment],
-[data-rich-text-format-boundary] {
- border-radius: 2px;
-}
-
-[data-rich-text-comment] {
- background-color: var(
- --wp-components-color-accent,
- var(--wp-admin-theme-color, #3858e9)
- );
-
- span {
- color: var(--wp-components-color-accent-inverted, #fff);
- filter: none;
- padding: 0 2px;
- }
-}
-
/**
* Override the default gap for social links block in the editor.
* This is needed because we do not want to have a gap between the social links and also for a WYSIWYG experience.
diff --git a/packages/php/email-editor/src/Engine/rich-text-comment.css b/packages/php/email-editor/src/Engine/rich-text-comment.css
new file mode 100644
index 00000000000..b554a48822c
--- /dev/null
+++ b/packages/php/email-editor/src/Engine/rich-text-comment.css
@@ -0,0 +1,17 @@
+/*
+ * Personalization tags are rich-text comments. Core renders them with
+ * currentColor and an inverted filter; we use the admin accent so they read
+ * as UI chips. Loaded into both the editor iframe and the admin document,
+ * after core's block-editor content styles.
+ *
+ * Keep the rules flat: the editor prefixes every selector and does not
+ * handle nested CSS.
+ */
+[data-rich-text-comment] {
+ background-color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9));
+}
+
+[data-rich-text-comment] span {
+ color: var(--wp-components-color-accent-inverted, #fff);
+ filter: none;
+}
diff --git a/packages/php/email-editor/tests/integration/Email_Editor_Integration_Test_Case.php b/packages/php/email-editor/tests/integration/Email_Editor_Integration_Test_Case.php
index e243c560998..47e852ec0eb 100644
--- a/packages/php/email-editor/tests/integration/Email_Editor_Integration_Test_Case.php
+++ b/packages/php/email-editor/tests/integration/Email_Editor_Integration_Test_Case.php
@@ -50,6 +50,13 @@ abstract class Email_Editor_Integration_Test_Case extends \WP_UnitTestCase {
*/
public Container $di_container;
+ /**
+ * Registries replaced by swapEnqueueRegistries(), until restored.
+ *
+ * @var array{styles: mixed, scripts: mixed}|null
+ */
+ private $original_enqueue_registries;
+
/**
* Set up before each test.
*/
@@ -323,4 +330,36 @@ abstract class Email_Editor_Integration_Test_Case extends \WP_UnitTestCase {
);
$this->di_container = $container;
}
+
+ /**
+ * Replace the global styles and scripts registries with fresh ones.
+ *
+ * Enqueue state is global and WP_UnitTestCase does not reset it. Call from setUp()
+ * in tests that enqueue assets, and restoreEnqueueRegistries() from tearDown().
+ */
+ protected function swapEnqueueRegistries(): void {
+ // phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited -- Isolate enqueue state per test, as core's own script and style tests do.
+ $this->original_enqueue_registries = array(
+ 'styles' => $GLOBALS['wp_styles'] ?? null,
+ 'scripts' => $GLOBALS['wp_scripts'] ?? null,
+ );
+
+ $GLOBALS['wp_styles'] = new \WP_Styles();
+ $GLOBALS['wp_scripts'] = new \WP_Scripts();
+ // phpcs:enable
+ }
+
+ /**
+ * Restore the registries replaced by swapEnqueueRegistries().
+ */
+ protected function restoreEnqueueRegistries(): void {
+ if ( null === $this->original_enqueue_registries ) {
+ return;
+ }
+ // phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited -- Restore the registries swapped in swapEnqueueRegistries().
+ $GLOBALS['wp_styles'] = $this->original_enqueue_registries['styles'];
+ $GLOBALS['wp_scripts'] = $this->original_enqueue_registries['scripts'];
+ // phpcs:enable
+ $this->original_enqueue_registries = null;
+ }
}
diff --git a/packages/php/email-editor/tests/integration/Engine/Assets_Manager_Test.php b/packages/php/email-editor/tests/integration/Engine/Assets_Manager_Test.php
new file mode 100644
index 00000000000..4f6a05b2303
--- /dev/null
+++ b/packages/php/email-editor/tests/integration/Engine/Assets_Manager_Test.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * This file is part of the WooCommerce Email Editor package
+ *
+ * @package Automattic\WooCommerce\EmailEditor
+ */
+
+declare(strict_types = 1);
+namespace Automattic\WooCommerce\EmailEditor\Tests\Integration\Engine;
+
+use Automattic\WooCommerce\EmailEditor\Engine\Assets_Manager;
+
+/**
+ * Integration test for Assets_Manager class
+ */
+class Assets_Manager_Test extends \Email_Editor_Integration_Test_Case {
+ /**
+ * Set up before each test
+ */
+ public function setUp(): void {
+ parent::setUp();
+ $this->swapEnqueueRegistries();
+ }
+
+ /**
+ * Tear down after each test
+ */
+ public function tearDown(): void {
+ $this->restoreEnqueueRegistries();
+ parent::tearDown();
+ }
+
+ /**
+ * Test it inlines the shared rich text comment stylesheet into the admin document exactly once.
+ */
+ public function testItInlinesRichTextCommentStylesIntoAdminDocumentOnce(): void {
+ $expected_css = (string) file_get_contents( dirname( __DIR__, 3 ) . '/src/Engine/rich-text-comment.css' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local package file.
+ $assets_manager = $this->di_container->get( Assets_Manager::class );
+
+ $assets_manager->enqueue_admin_styles();
+
+ $this->assertTrue( wp_style_is( 'wp-edit-post', 'enqueued' ), 'The inline styles are only printed when wp-edit-post is enqueued' );
+ $inline_styles = wp_styles()->get_data( 'wp-edit-post', 'after' );
+ $this->assertIsArray( $inline_styles, 'Inline styles must be attached to the wp-edit-post handle' );
+ $this->assertCount( 1, array_keys( $inline_styles, $expected_css, true ), 'The admin document must receive the shared rich-text-comment.css unchanged and exactly once' );
+ }
+}
diff --git a/packages/php/email-editor/tests/integration/Engine/Settings_Controller_Test.php b/packages/php/email-editor/tests/integration/Engine/Settings_Controller_Test.php
new file mode 100644
index 00000000000..7b68d8557fb
--- /dev/null
+++ b/packages/php/email-editor/tests/integration/Engine/Settings_Controller_Test.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * This file is part of the WooCommerce Email Editor package
+ *
+ * @package Automattic\WooCommerce\EmailEditor
+ */
+
+declare(strict_types = 1);
+namespace Automattic\WooCommerce\EmailEditor\Tests\Integration\Engine;
+
+use Automattic\WooCommerce\EmailEditor\Engine\Settings_Controller;
+
+/**
+ * Integration test for Settings_Controller class
+ */
+class Settings_Controller_Test extends \Email_Editor_Integration_Test_Case {
+ /**
+ * Settings controller instance
+ *
+ * @var Settings_Controller
+ */
+ private Settings_Controller $settings_controller;
+
+ /**
+ * Set up before each test
+ */
+ public function setUp(): void {
+ parent::setUp();
+ // get_settings() collects iframe assets from the global registries, which core reads without initializing them.
+ $this->swapEnqueueRegistries();
+ $this->settings_controller = $this->di_container->get( Settings_Controller::class );
+ }
+
+ /**
+ * Tear down after each test
+ */
+ public function tearDown(): void {
+ $this->restoreEnqueueRegistries();
+ parent::tearDown();
+ }
+
+ /**
+ * Test it adds the shared rich text comment stylesheet to the editor styles exactly once.
+ */
+ public function testItAddsRichTextCommentStylesToEditorStylesOnce(): void {
+ $expected_css = (string) file_get_contents( dirname( __DIR__, 3 ) . '/src/Engine/rich-text-comment.css' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local package file.
+
+ $settings = $this->settings_controller->get_settings();
+
+ $styles_with_comment_rules = array_filter(
+ $settings['styles'],
+ function ( array $style ): bool {
+ return false !== strpos( $style['css'], '[data-rich-text-comment]' );
+ }
+ );
+
+ $this->assertCount( 1, $styles_with_comment_rules, 'Rich text comment styles must come from a single package stylesheet' );
+ $this->assertSame( $expected_css, reset( $styles_with_comment_rules )['css'], 'The iframe must receive the shared rich-text-comment.css unchanged' );
+ $this->assertDoesNotMatchRegularExpression( '/\{[^}]*\{/', $expected_css, 'Nested rules must be flattened so selector prefixing keeps them valid' );
+ }
+}