diff --git a/lib/global-styles.php b/lib/global-styles.php index 10180161342fb1..201caf0eff3327 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -875,6 +875,53 @@ function gutenberg_experimental_global_styles_register_cpt() { register_post_type( 'wp_global_styles', $args ); } +/** + * Tell kses not to remove from the block markup (from style attribute) + * the CSS variables the block editor may add. + * + * @param array $allowed_attr List of allowed attributes. + * @return array Filtered result. + */ +function gutenberg_experimental_global_styles_allow_css_var_name( $allowed_attr ) { + return array_merge( + $allowed_attr, + array( + '--wp--style--color--link', + ) + ); +} + +/** + * Tell kses to allow certain values for the properties + * the block editor may add. + * + * @param boolean $allow_css Whether or not this rule should be allowed. + * @param string $css_test_string The CSS rule to process. + * @return boolean Filtered result. + */ +function gutenberg_experimental_global_styles_allow_css_var_value( $allow_css, $css_test_string ) { + $parts = explode( ':', $css_test_string, 2 ); + $property_name = trim( $parts[0] ); + $property_value = trim( $parts[1] ); + + // Pass through if we're not processing the link color property. + if ( '--wp--style--color--link' !== $property_name ) { + return $allow_css; + } + + // Pass through if $allow_css true. This means the link color has a valid color value + // (the user selected a custom color). + if ( $allow_css ) { + return $allow_css; + } + + // We want to be specific in testing that the value for link color + // matches this: var(--wp--preset--color--). + return preg_match( '/^var\(--wp--preset--color--[A-Za-z0-9-]*\)$/', $property_value ); +} + add_action( 'init', 'gutenberg_experimental_global_styles_register_cpt' ); add_filter( 'block_editor_settings', 'gutenberg_experimental_global_styles_settings' ); add_action( 'wp_enqueue_scripts', 'gutenberg_experimental_global_styles_enqueue_assets' ); +add_filter( 'safe_style_css', 'gutenberg_experimental_global_styles_allow_css_var_name' ); +add_filter( 'safecss_filter_attr_allow_css', 'gutenberg_experimental_global_styles_allow_css_var_value', 10, 2 ); diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/link-color.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/link-color.test.js.snap new file mode 100644 index 00000000000000..45427bbe1288dc --- /dev/null +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/link-color.test.js.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Link color control serializes markup properly 1`] = ` +" + +" +`; diff --git a/packages/e2e-tests/specs/editor/various/link-color.test.js b/packages/e2e-tests/specs/editor/various/link-color.test.js new file mode 100644 index 00000000000000..f0747de84956d1 --- /dev/null +++ b/packages/e2e-tests/specs/editor/various/link-color.test.js @@ -0,0 +1,73 @@ +/** + * WordPress dependencies + */ +import { + clickBlockAppender, + createNewPost, + getEditedPostContent, + pressKeyWithModifier, + publishPost, +} from '@wordpress/e2e-test-utils'; + +describe( 'Link color', () => { + beforeEach( async () => { + await createNewPost(); + } ); + + const waitForAutoFocus = async () => { + await page.waitForFunction( + () => !! document.activeElement.closest( '.block-editor-url-input' ) + ); + }; + + it( 'control serializes markup properly', async () => { + // Create a block with some text + await clickBlockAppender(); + await page.keyboard.type( 'This is Gutenberg' ); + + // Select some text + await pressKeyWithModifier( 'shiftAlt', 'ArrowLeft' ); + + // Click on the Link button + await page.click( 'button[aria-label="Link"]' ); + + // Wait for the URL field to auto-focus + await waitForAutoFocus(); + + // Type a URL + await page.keyboard.type( 'https://wordpress.org/gutenberg' ); + + // Submit the link + await page.keyboard.press( 'Enter' ); + + // Simulate the theme has support for link color + await page.evaluate( () => { + wp.data.dispatch( 'core/block-editor' ).updateSettings( { + __experimentalFeatures: { + global: { + color: { link: true }, + }, + }, + } ); + } ); + + // Open color panel + await page.click( + '.block-editor-panel-color-gradient-settings .components-panel__body-toggle' + ); + + // Select first color + await page.click( + '.block-editor-panel-color-gradient-settings > .block-editor-color-gradient-control:last-child .components-circular-option-picker__option:first-child' + ); + + // Save post. + // We want to test that the link color control data + // persists after kses runs (kses filters out some markup, + // such as CSS variables within the style property). + await publishPost(); + + // Snapshot contains .has-link-color class and inline CSS variable + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); +} );