diff --git a/lib/block-supports/index.php b/lib/block-supports/index.php index 4fd6460234d3f6..fe0017415f9e78 100644 --- a/lib/block-supports/index.php +++ b/lib/block-supports/index.php @@ -65,27 +65,37 @@ function gutenberg_apply_block_supports( $block_content, $block ) { return $block_content; } - // Some inline styles may be added without ending ';', add this if necessary. - $current_styles = trim( $block_root->getAttribute( 'style' ), ' ' ); - if ( strlen( $current_styles ) > 0 && substr( $current_styles, -1 ) !== ';' ) { - $current_styles = $current_styles . ';'; - }; - // Merge and dedupe new and existing classes and styles. - $classes_to_add = esc_attr( implode( ' ', array_key_exists( 'css_classes', $attributes ) ? $attributes['css_classes'] : array() ) ); - $styles_to_add = esc_attr( implode( ' ', array_key_exists( 'inline_styles', $attributes ) ? $attributes['inline_styles'] : array() ) ); - $new_classes = implode( ' ', array_unique( explode( ' ', ltrim( $block_root->getAttribute( 'class' ) . ' ' ) . $classes_to_add ) ) ); - $new_styles = implode( ' ', array_unique( explode( ' ', $current_styles . ' ' . $styles_to_add ) ) ); + $current_classes = explode( ' ', trim( $block_root->getAttribute( 'class' ) ) ); + $classes_to_add = array_key_exists( 'css_classes', $attributes ) ? $attributes['css_classes'] : array(); + $new_classes = array_unique( array_filter( array_merge( $current_classes, $classes_to_add ) ) ); + + $current_styles = preg_split( '/\s*;\s*/', trim( $block_root->getAttribute( 'style' ) ) ); + $styles_to_add = array_key_exists( 'inline_styles', $attributes ) ? $attributes['inline_styles'] : array(); + $new_styles = array_unique( array_map( 'gutenberg_normalize_css_rule', array_filter( array_merge( $current_styles, $styles_to_add ) ) ) ); // Apply new styles and classes. if ( ! empty( $new_classes ) ) { - $block_root->setAttribute( 'class', $new_classes ); + $block_root->setAttribute( 'class', esc_attr( implode( ' ', $new_classes ) ) ); } if ( ! empty( $new_styles ) ) { - $block_root->setAttribute( 'style', $new_styles ); + $block_root->setAttribute( 'style', esc_attr( implode( '; ', $new_styles ) . ';' ) ); } return mb_convert_encoding( $dom->saveHtml(), 'UTF-8', 'HTML-ENTITIES' ); } add_filter( 'render_block', 'gutenberg_apply_block_supports', 10, 2 ); + +/** + * Normalizes spacing in a string representing a CSS rule + * + * @example + * 'color :red;' becomes 'color:red' + * + * @param string $css_rule_string CSS rule. + * @return string Normalized CSS rule. + */ +function gutenberg_normalize_css_rule( $css_rule_string ) { + return trim( implode( ': ', preg_split( '/\s*:\s*/', $css_rule_string, 2 ) ), ';' ); +} diff --git a/phpunit/class-block-supported-styles-test.php b/phpunit/class-block-supported-styles-test.php index f0589e3d151001..8a759b4e577451 100644 --- a/phpunit/class-block-supported-styles-test.php +++ b/phpunit/class-block-supported-styles-test.php @@ -153,7 +153,7 @@ function test_named_color_support() { ); $expected_classes = 'wp-block-example foo-bar-class has-text-color has-red-color has-background has-black-background-color'; - $expected_styles = 'test:style; '; + $expected_styles = 'test: style;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -189,7 +189,7 @@ function test_custom_color_support() { 'innerHTML' => array(), ); - $expected_styles = 'test:style; color: #000; background-color: #fff;'; + $expected_styles = 'test: style; color: #000; background-color: #fff;'; $expected_classes = 'wp-block-example foo-bar-class has-text-color has-background'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); @@ -221,7 +221,7 @@ function test_named_link_color_support() { ); $expected_classes = 'wp-block-example foo-bar-class has-link-color'; - $expected_styles = 'test:style; --wp--style--color--link:var(--wp--preset--color--red);'; + $expected_styles = 'test: style; --wp--style--color--link: var(--wp--preset--color--red);'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -252,7 +252,7 @@ function test_custom_link_color_support() { ); $expected_classes = 'wp-block-example foo-bar-class has-link-color'; - $expected_styles = 'test:style; --wp--style--color--link: #fff;'; + $expected_styles = 'test: style; --wp--style--color--link: #fff;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -283,7 +283,7 @@ function test_named_gradient_support() { ); $expected_classes = 'wp-block-example foo-bar-class has-background has-red-gradient-background'; - $expected_styles = 'test:style; '; + $expected_styles = 'test: style;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -314,7 +314,7 @@ function test_custom_gradient_support() { ); $expected_classes = 'wp-block-example foo-bar-class has-background'; - $expected_styles = 'test:style; background: some-gradient-style;'; + $expected_styles = 'test: style; background: some-gradient-style;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -379,7 +379,7 @@ function test_named_font_size() { ); $expected_classes = 'wp-block-example foo-bar-class has-large-font-size'; - $expected_styles = 'test:style; '; + $expected_styles = 'test: style;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -407,8 +407,8 @@ function test_custom_font_size() { 'innerHTML' => array(), ); - $expected_classes = 'wp-block-example foo-bar-class '; - $expected_styles = 'test:style; font-size: 10px;'; + $expected_classes = 'wp-block-example foo-bar-class'; + $expected_styles = 'test: style; font-size: 10px;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -464,8 +464,8 @@ function test_line_height() { 'innerHTML' => array(), ); - $expected_classes = 'wp-block-example foo-bar-class '; - $expected_styles = 'test:style; line-height: 10;'; + $expected_classes = 'wp-block-example foo-bar-class'; + $expected_styles = 'test: style; line-height: 10;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -521,7 +521,7 @@ function test_block_alignment() { ); $expected_classes = 'wp-block-example foo-bar-class alignwide'; - $expected_styles = 'test:style; '; + $expected_styles = 'test: style;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -595,7 +595,7 @@ function test_all_supported() { ); $expected_classes = 'wp-block-example foo-bar-class has-text-color has-background alignwide'; - $expected_styles = 'test:style; color: #000; background-color: #fff; background: some-gradient; font-size: 10px; line-height: 20;'; + $expected_styles = 'test: style; color: #000; background-color: #fff; background: some-gradient; font-size: 10px; line-height: 20;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); } @@ -636,8 +636,8 @@ function test_one_supported() { 'innerHTML' => array(), ); - $expected_classes = 'wp-block-example foo-bar-class '; - $expected_styles = 'test:style; font-size: 10px;'; + $expected_classes = 'wp-block-example foo-bar-class'; + $expected_styles = 'test: style; font-size: 10px;'; $this->assert_content_and_styles_and_classes_match( $block, $expected_classes, $expected_styles ); }