diff --git a/lib/block-supports/colors.php b/lib/block-supports/colors.php
index 06c6649a1cd4d..afdc3500d3164 100644
--- a/lib/block-supports/colors.php
+++ b/lib/block-supports/colors.php
@@ -99,24 +99,6 @@ function gutenberg_apply_colors_support( $block_type, $block_attributes ) {
}
}
- // Link Colors.
- if ( $has_link_colors_support ) {
- $has_link_color = isset( $block_attributes['style']['color']['link'] );
- // Apply required class and style.
- if ( $has_link_color ) {
- $classes[] = 'has-link-color';
- // If link is a named color.
- if ( strpos( $block_attributes['style']['color']['link'], 'var:preset|color|' ) !== false ) {
- // Get the name from the string and add proper styles.
- $index_to_splice = strrpos( $block_attributes['style']['color']['link'], '|' ) + 1;
- $link_color_name = substr( $block_attributes['style']['color']['link'], $index_to_splice );
- $styles[] = sprintf( '--wp--style--color--link: var(--wp--preset--color--%s);', $link_color_name );
- } else {
- $styles[] = sprintf( '--wp--style--color--link: %s;', $block_attributes['style']['color']['link'] );
- }
- }
- }
-
// Background colors.
if ( $has_background_colors_support ) {
$has_named_background_color = array_key_exists( 'backgroundColor', $block_attributes );
diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php
new file mode 100644
index 0000000000000..a55bffe1c2e84
--- /dev/null
+++ b/lib/block-supports/elements.php
@@ -0,0 +1,65 @@
+get_registered( $block['blockName'] );
+ $link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', 'color', 'text' ), null );
+
+ /*
+ * For now we only care about link color.
+ * This code in the future when we have a public API
+ * should take advantage of WP_Theme_JSON::compute_style_properties
+ * and work for any element and style.
+ */
+ if ( null === $link_color ) {
+ return $block_content;
+ }
+
+ $class_name = 'wp-elements-' . uniqid();
+
+ if ( strpos( $link_color, 'var:preset|color|' ) !== false ) {
+ // Get the name from the string and add proper styles.
+ $index_to_splice = strrpos( $link_color, '|' ) + 1;
+ $link_color_name = substr( $link_color, $index_to_splice );
+ $link_color = "var(--wp--preset--color--$link_color_name)";
+ }
+ $link_color_declaration = esc_html( safecss_filter_attr( "color: $link_color" ) );
+
+ $style = "\n";
+
+ // Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
+ // Retrieve the opening tag of the first HTML element.
+ $html_element_matches;
+ preg_match( '/<[^>]+>/', $block_content, $html_element_matches, PREG_OFFSET_CAPTURE );
+ $first_element = $html_element_matches[0][0];
+ // If the first HTML element has a class attribute just add the new class
+ // as we do on layout and duotone.
+ if ( strpos( $first_element, 'class="' ) !== false ) {
+ $content = preg_replace(
+ '/' . preg_quote( 'class="', '/' ) . '/',
+ 'class="' . $class_name . ' ',
+ $block_content,
+ 1
+ );
+ } else {
+ // If the first HTML element has no class attribute we should inject the attribute before the attribute at the end.
+ $first_element_offset = $html_element_matches[0][1];
+ $content = substr_replace( $block_content, ' class="' . $class_name . '"', $first_element_offset + strlen( $first_element ) - 1, 0 );
+ }
+ return $content . $style;
+
+}
+
+
+add_filter( 'render_block', 'gutenberg_render_elements_support', 10, 2 );
diff --git a/lib/class-wp-theme-json.php b/lib/class-wp-theme-json.php
index 60d3f2eaabae4..6734d439b10f9 100644
--- a/lib/class-wp-theme-json.php
+++ b/lib/class-wp-theme-json.php
@@ -205,9 +205,6 @@ class WP_Theme_JSON {
* - 'value': path to the value in theme.json and block attributes.
*/
const PROPERTIES_METADATA = array(
- '--wp--style--color--link' => array(
- 'value' => array( 'color', 'link' ),
- ),
'background' => array(
'value' => array( 'color', 'gradient' ),
),
@@ -836,7 +833,7 @@ private function get_css_variables( $nodes ) {
* @return string The new stylesheet.
*/
private function get_block_styles( $style_nodes, $setting_nodes ) {
- $block_rules = self::ELEMENTS['link'] . '{color: var(--wp--style--color--link, #00e);}';
+ $block_rules = '';
foreach ( $style_nodes as $metadata ) {
if ( null === $metadata['selector'] ) {
continue;
@@ -845,53 +842,7 @@ private function get_block_styles( $style_nodes, $setting_nodes ) {
$node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
$selector = $metadata['selector'];
$declarations = self::compute_style_properties( $node );
-
- $is_link_element = self::is_link_element( $metadata['selector'] );
- if ( ! $is_link_element ) {
- $block_rules .= self::to_ruleset( $selector, $declarations );
- } else {
- /*
- * To be removed when the user provided styles for link color
- * no longer use the --wp--style--link-color variable.
- *
- * We need to:
- *
- * 1. For the color property, output:
- *
- * $selector_without_the_link_element_selector {
- * --wp--style--color--link: value
- * }
- *
- * 2. For the rest of the properties:
- *
- * $selector {
- * other-prop: value;
- * other-prop: value;
- * }
- *
- * The reason for 1 is that user styles are attached to the block wrapper.
- * If 1 targets the a element is going to have higher specificity
- * and will overwrite the user preferences.
- *
- * Once the user styles are updated to output an `a` element instead
- * this can be removed.
- */
- $declarations_color = array();
- $declarations_other = array();
- foreach ( $declarations as $declaration ) {
- if ( 'color' === $declaration['name'] ) {
- $declarations_color[] = array(
- 'name' => '--wp--style--color--link',
- 'value' => $declaration['value'],
- );
- } else {
- $declarations_other[] = $declaration;
- }
- }
-
- $block_rules .= self::to_ruleset( $selector, $declarations_other );
- $block_rules .= self::to_ruleset( self::without_link_selector( $selector ), $declarations_color );
- }
+ $block_rules .= self::to_ruleset( $selector, $declarations );
}
$preset_rules = '';
@@ -1219,15 +1170,6 @@ private static function remove_insecure_settings( $input ) {
private static function remove_insecure_styles( $input, $selector ) {
$output = array();
$declarations = self::compute_style_properties( $input );
- // To be removed once the user styles
- // no longer use the --wp--style--color--link.
- if ( self::is_link_element( $selector ) ) {
- foreach ( $declarations as $index => $declaration ) {
- if ( 'color' === $declaration['name'] ) {
- $declarations[ $index ]['name'] = '--wp--style--color--link';
- }
- }
- }
foreach ( $declarations as $declaration ) {
if ( self::is_safe_css_declaration( $declaration['name'], $declaration['value'] ) ) {
@@ -1256,45 +1198,6 @@ private static function is_safe_css_declaration( $property_name, $property_value
return ! empty( trim( $filtered ) );
}
- /**
- * Whether the selector contains a link element.
- *
- * @param string $selector The selector to check.
- *
- * @return boolean
- */
- private static function is_link_element( $selector ) {
- if ( self::ELEMENTS['link'] === $selector ) {
- return true;
- }
-
- $result = true;
- if ( false === stripos( $selector, ' ' . self::ELEMENTS['link'] ) ) {
- $result = false;
- }
-
- return $result;
- }
-
- /**
- * Remove the link selector from the input.
- *
- * @param string $selector CSS selector to process.
- *
- * @return string
- */
- private static function without_link_selector( $selector ) {
- if ( self::ELEMENTS['link'] === $selector ) {
- return $selector;
- }
-
- // The selector consist of "
Hello WordPress!
' . "\n" + ); + } + + /** + * Test gutenberg_render_elements_support() with a paragraph containing a class. + */ + public function test_class_paragraph_link_color() { + $result = self::make_unique_id_one( + gutenberg_render_elements_support( + 'Hello WordPress!
', + array( + 'blockName' => 'core/paragraph', + 'attrs' => array( + 'style' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'red', + ), + ), + ), + ), + 'backgroundColor' => 'dark-gray', + ), + ) + ) + ); + $this->assertSame( + $result, + 'Hello WordPress!
' . "\n" + ); + } + + /** + * Test gutenberg_render_elements_support() with a paragraph containing a anchor. + */ + public function test_anchor_paragraph_link_color() { + $result = self::make_unique_id_one( + gutenberg_render_elements_support( + 'Hello WordPress!
', + array( + 'blockName' => 'core/paragraph', + 'attrs' => array( + 'style' => array( + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => '#fff000', + ), + ), + ), + ), + ), + ) + ) + ); + $this->assertSame( + $result, + 'Hello WordPress!
' . "\n" + ); + } +} diff --git a/phpunit/class-wp-theme-json-schema-v0-test.php b/phpunit/class-wp-theme-json-schema-v0-test.php index 624d5856b74fc..7e79e598d60e7 100644 --- a/phpunit/class-wp-theme-json-schema-v0-test.php +++ b/phpunit/class-wp-theme-json-schema-v0-test.php @@ -461,11 +461,11 @@ function test_get_stylesheet() { ); $this->assertEquals( - 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}a{color: var(--wp--style--color--link, #00e);}body{color: var(--wp--preset--color--grey);}a{--wp--style--color--link: #111;}h1{font-size: 1em;}h2{font-size: 2em;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group{--wp--style--color--link: #333;}h1,h2,h3,h4,h5,h6{--wp--style--color--link: #222;}.wp-block-post-title{font-size: 5em;}.wp-block-post-title{--wp--style--color--link: #555;}.wp-block-query-title{font-size: 5em;}.wp-block-query-title{--wp--style--color--link: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', + 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}body{color: var(--wp--preset--color--grey);}a{color: #111;}h1{font-size: 1em;}h2{font-size: 2em;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #333;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: #222;}.wp-block-post-title{font-size: 5em;}.wp-block-post-title a{color: #555;}.wp-block-query-title{font-size: 5em;}.wp-block-query-title a{color: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', $theme_json->get_stylesheet() ); $this->assertEquals( - 'a{color: var(--wp--style--color--link, #00e);}body{color: var(--wp--preset--color--grey);}a{--wp--style--color--link: #111;}h1{font-size: 1em;}h2{font-size: 2em;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group{--wp--style--color--link: #333;}h1,h2,h3,h4,h5,h6{--wp--style--color--link: #222;}.wp-block-post-title{font-size: 5em;}.wp-block-post-title{--wp--style--color--link: #555;}.wp-block-query-title{font-size: 5em;}.wp-block-query-title{--wp--style--color--link: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', + 'body{color: var(--wp--preset--color--grey);}a{color: #111;}h1{font-size: 1em;}h2{font-size: 2em;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #333;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: #222;}.wp-block-post-title{font-size: 5em;}.wp-block-post-title a{color: #555;}.wp-block-query-title{font-size: 5em;}.wp-block-query-title a{color: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', $theme_json->get_stylesheet( 'block_styles' ) ); $this->assertEquals( diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 81ab493724332..5b6d02059829f 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -27,8 +27,12 @@ function test_get_settings() { ), ), 'styles' => array( - 'color' => array( - 'link' => 'blue', + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => '#111', + ), + ), ), ), ) @@ -157,11 +161,11 @@ function test_get_stylesheet() { ); $this->assertEquals( - 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}a{color: var(--wp--style--color--link, #00e);}body{color: var(--wp--preset--color--grey);}a{background-color: #333;}a{--wp--style--color--link: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group{--wp--style--color--link: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;font-size: 60px;}h1,h2,h3,h4,h5,h6{--wp--style--color--link: #111;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;}.wp-block-post-date{--wp--style--color--link: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', + 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', $theme_json->get_stylesheet() ); $this->assertEquals( - 'a{color: var(--wp--style--color--link, #00e);}body{color: var(--wp--preset--color--grey);}a{background-color: #333;}a{--wp--style--color--link: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group{--wp--style--color--link: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;font-size: 60px;}h1,h2,h3,h4,h5,h6{--wp--style--color--link: #111;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;}.wp-block-post-date{--wp--style--color--link: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', + 'body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', $theme_json->get_stylesheet( 'block_styles' ) ); $this->assertEquals( @@ -201,11 +205,11 @@ function test_get_stylesheet_preset_rules_come_after_block_rules() { ); $this->assertEquals( - '.wp-block-group{--wp--preset--color--grey: grey;}a{color: var(--wp--style--color--link, #00e);}.wp-block-group{color: red;}.wp-block-group.has-grey-color{color: grey !important;}.wp-block-group.has-grey-background-color{background-color: grey !important;}.wp-block-group.has-grey-border-color{border-color: grey !important;}', + '.wp-block-group{--wp--preset--color--grey: grey;}.wp-block-group{color: red;}.wp-block-group.has-grey-color{color: grey !important;}.wp-block-group.has-grey-background-color{background-color: grey !important;}.wp-block-group.has-grey-border-color{border-color: grey !important;}', $theme_json->get_stylesheet() ); $this->assertEquals( - 'a{color: var(--wp--style--color--link, #00e);}.wp-block-group{color: red;}.wp-block-group.has-grey-color{color: grey !important;}.wp-block-group.has-grey-background-color{background-color: grey !important;}.wp-block-group.has-grey-border-color{border-color: grey !important;}', + '.wp-block-group{color: red;}.wp-block-group.has-grey-color{color: grey !important;}.wp-block-group.has-grey-background-color{background-color: grey !important;}.wp-block-group.has-grey-border-color{border-color: grey !important;}', $theme_json->get_stylesheet( 'block_styles' ) ); } @@ -242,7 +246,7 @@ public function test_get_stylesheet_preset_values_are_marked_as_important() { ); $this->assertEquals( - 'body{--wp--preset--color--grey: grey;}a{color: var(--wp--style--color--link, #00e);}p{background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', + 'body{--wp--preset--color--grey: grey;}p{background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}.has-grey-border-color{border-color: grey !important;}', $theme_json->get_stylesheet() ); } @@ -535,11 +539,7 @@ function test_remove_insecure_properties_removes_unsafe_styles() { 'elements' => array( 'link' => array( 'color' => array( - // We should also allow links but at the moment we don't - // because they're transformed to --wp--style--color-link - // due to how user styles work. - // 'text' => 'var:preset|color|dark-pink', - // . + 'text' => 'var:preset|color|dark-pink', 'background' => 'var:preset|color|dark-red', ), ), @@ -549,17 +549,13 @@ function test_remove_insecure_properties_removes_unsafe_styles() { 'color' => array( 'text' => 'var:preset|color|dark-gray', ), - // We should also allow links but at the moment we don't - // because they're transformed to --wp--style--color-link - // due to how user styles work. - // 'elements' => array( - // 'link' => array( - // 'color' => array( - // 'text' => 'var:preset|color|dark-pink', - // ), - // ), - // ), - // . + 'elements' => array( + 'link' => array( + 'color' => array( + 'text' => 'var:preset|color|dark-pink', + ), + ), + ), ), ), ),