-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Elements: Merge element style and classname generation to single filter #59535
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,37 +6,36 @@ | |
*/ | ||
|
||
/** | ||
* Update the block content with elements class names. | ||
* Determines whether an elements class name should be added to the block. | ||
* | ||
* @param string $block_content Rendered block content. | ||
* @param array $block Block object. | ||
* @return string Filtered block content. | ||
* @param array $block Block object. | ||
* @param array $options Per element type options e.g. whether to skip serialization. | ||
* | ||
* @return boolean Whether the block needs an elements class name. | ||
*/ | ||
function gutenberg_render_elements_support( $block_content, $block ) { | ||
if ( ! $block_content || ! isset( $block['attrs']['style']['elements'] ) ) { | ||
return $block_content; | ||
function gutenberg_should_add_elements_class_name( $block, $options ) { | ||
if ( ! isset( $block['attrs']['style']['elements'] ) ) { | ||
return false; | ||
} | ||
|
||
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); | ||
|
||
$element_color_properties = array( | ||
'button' => array( | ||
'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ), | ||
'skip' => $options['button']['skip'] ?? false, | ||
'paths' => array( | ||
array( 'button', 'color', 'text' ), | ||
array( 'button', 'color', 'background' ), | ||
array( 'button', 'color', 'gradient' ), | ||
), | ||
), | ||
'link' => array( | ||
'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ), | ||
'skip' => $options['link']['skip'] ?? false, | ||
'paths' => array( | ||
array( 'link', 'color', 'text' ), | ||
array( 'link', ':hover', 'color', 'text' ), | ||
), | ||
), | ||
'heading' => array( | ||
'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ), | ||
'skip' => $options['heading']['skip'] ?? false, | ||
'paths' => array( | ||
array( 'heading', 'color', 'text' ), | ||
array( 'heading', 'color', 'background' ), | ||
|
@@ -63,14 +62,6 @@ function gutenberg_render_elements_support( $block_content, $block ) { | |
), | ||
); | ||
|
||
$skip_all_element_color_serialization = $element_color_properties['button']['skip'] && | ||
$element_color_properties['link']['skip'] && | ||
$element_color_properties['heading']['skip']; | ||
|
||
if ( $skip_all_element_color_serialization ) { | ||
return $block_content; | ||
} | ||
|
||
$elements_style_attributes = $block['attrs']['style']['elements']; | ||
|
||
foreach ( $element_color_properties as $element_config ) { | ||
|
@@ -80,47 +71,31 @@ function gutenberg_render_elements_support( $block_content, $block ) { | |
|
||
foreach ( $element_config['paths'] as $path ) { | ||
if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) { | ||
/* | ||
* It only takes a single custom attribute to require that the custom | ||
* class name be added to the block, so once one is found there's no | ||
* need to continue looking for others. | ||
* | ||
* As is done with the layout hook, this code assumes that the block | ||
* contains a single wrapper and that it's the first element in the | ||
* rendered output. That first element, if it exists, gets the class. | ||
*/ | ||
$tags = new WP_HTML_Tag_Processor( $block_content ); | ||
if ( $tags->next_tag() ) { | ||
$tags->add_class( wp_get_elements_class_name( $elements_style_attributes ) ); | ||
} | ||
|
||
return $tags->get_updated_html(); | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
// If no custom attributes were found then there's nothing to modify. | ||
return $block_content; | ||
return false; | ||
} | ||
|
||
/** | ||
* Render the elements stylesheet. | ||
* Render the elements stylesheet and adds elements class name to block as required. | ||
* | ||
* In the case of nested blocks we want the parent element styles to be rendered before their descendants. | ||
* This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant: | ||
* we want the descendant style to take priority, and this is done by loading it after, in DOM order. | ||
* | ||
* @param string|null $pre_render The pre-rendered content. Default null. | ||
* @param array $block The block being rendered. | ||
* @param array $parsed_block The parsed block. | ||
* | ||
* @return null | ||
* @return array The same parsed block with elements classname added if appropriate. | ||
*/ | ||
function gutenberg_render_elements_support_styles( $pre_render, $block ) { | ||
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); | ||
$element_block_styles = isset( $block['attrs']['style']['elements'] ) ? $block['attrs']['style']['elements'] : null; | ||
function gutenberg_render_elements_support_styles( $parsed_block ) { | ||
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] ); | ||
$element_block_styles = $parsed_block['attrs']['style']['elements'] ?? null; | ||
|
||
if ( ! $element_block_styles ) { | ||
return null; | ||
return $parsed_block; | ||
} | ||
|
||
$skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ); | ||
|
@@ -131,11 +106,25 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { | |
$skip_button_color_serialization; | ||
|
||
if ( $skips_all_element_color_serialization ) { | ||
return null; | ||
return $parsed_block; | ||
} | ||
|
||
$options = array( | ||
'button' => array( 'skip' => $skip_button_color_serialization ), | ||
'link' => array( 'skip' => $skip_link_color_serialization ), | ||
'heading' => array( 'skip' => $skip_heading_color_serialization ), | ||
); | ||
|
||
if ( ! gutenberg_should_add_elements_class_name( $parsed_block, $options ) ) { | ||
return $parsed_block; | ||
} | ||
|
||
$class_name = wp_get_elements_class_name( $element_block_styles ); | ||
$class_name = wp_get_elements_class_name( $parsed_block ); | ||
$updated_class_name = isset( $parsed_block['attrs']['className'] ) ? $parsed_block['attrs']['className'] . " $class_name" : $class_name; | ||
|
||
_wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name ); | ||
|
||
// Generate element styles based on selector and store in style engine for enqueuing. | ||
$element_types = array( | ||
'button' => array( | ||
'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link", | ||
|
@@ -200,11 +189,43 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { | |
} | ||
} | ||
|
||
return null; | ||
return $parsed_block; | ||
} | ||
|
||
/** | ||
* Ensure the elements block support class name generated and added to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be a bug; I'd expect it to not be necessary to add the attributes manually to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My inclination was that it was due to the block being static and the markup having been generated at the point it was saved rather than render. |
||
* block attributes in the `render_block_data` filter gets applied to the | ||
* block's markup. | ||
* | ||
* @see gutenberg_render_elements_support_styles | ||
* | ||
* @param string $block_content Rendered block content. | ||
* @param array $block Block object. | ||
* | ||
* @return string Filtered block content. | ||
*/ | ||
function gutenberg_render_elements_class_name( $block_content, $block ) { | ||
$class_string = $block['attrs']['className'] ?? ''; | ||
preg_match( '/\bwp-elements-\S+\b/', $class_string, $matches ); | ||
ramonjd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if ( empty( $matches ) ) { | ||
return $block_content; | ||
} | ||
|
||
$tags = new WP_HTML_Tag_Processor( $block_content ); | ||
|
||
if ( $tags->next_tag() ) { | ||
// Ensure the elements class name set in render_block_data filter is applied in markup. | ||
// See `gutenberg_render_elements_support_styles`. | ||
Comment on lines
+218
to
+219
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above re comment formatting. |
||
$tags->add_class( $matches[0] ); | ||
} | ||
|
||
return $tags->get_updated_html(); | ||
} | ||
|
||
// Remove WordPress core filters to avoid rendering duplicate elements stylesheet & attaching classes twice. | ||
remove_filter( 'render_block', 'wp_render_elements_support', 10, 2 ); | ||
remove_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10, 2 ); | ||
add_filter( 'render_block', 'gutenberg_render_elements_support', 10, 2 ); | ||
add_filter( 'pre_render_block', 'gutenberg_render_elements_support_styles', 10, 2 ); | ||
remove_filter( 'render_block', 'wp_render_elements_class_name', 10, 2 ); | ||
add_filter( 'render_block', 'gutenberg_render_elements_class_name', 10, 2 ); | ||
add_filter( 'render_block_data', 'gutenberg_render_elements_support_styles', 10, 2 ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,7 +72,12 @@ public function test_elements_block_support_class( $color_settings, $elements_st | |
), | ||
); | ||
|
||
$actual = gutenberg_render_elements_support( $block_markup, $block ); | ||
// To ensure a consistent elements class name it is generated within a | ||
// `render_block_data` filter and stored in the `className` attribute. | ||
// As a result the block data needs to be passed through the same | ||
// function for this test. | ||
Comment on lines
+75
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Per WP Coding standards for PHP and JS. https://developer.wordpress.org/coding-standards/inline-documentation-standards/php/#5-inline-comments A common gotcha is to start wiht |
||
$filtered_block = gutenberg_render_elements_support_styles( $block ); | ||
$actual = gutenberg_render_elements_class_name( $block_markup, $filtered_block ); | ||
|
||
$this->assertMatchesRegularExpression( | ||
$expected_markup, | ||
|
@@ -192,7 +197,7 @@ public function test_elements_block_support_styles( $color_settings, $elements_s | |
), | ||
); | ||
|
||
gutenberg_render_elements_support_styles( null, $block ); | ||
gutenberg_render_elements_support_styles( $block ); | ||
$actual_stylesheet = gutenberg_style_engine_get_stylesheet_from_context( 'block-supports' ); | ||
|
||
$this->assertMatchesRegularExpression( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wp_render_elements_support_styles has been a public function since WP 6.0.
I searched on wpdirectory.net and there doesn't appear to be any usages, but I'm wondering if we should formally deprecate this one to make sure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure on this one. These filters weren't designed to be reused. They're also not publicly documented as part of our API, and only really useful as a filter for this specific use case.
Given that, I'm leaning towards handling any deprecation requirements in the core backport.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend handling it consistently in Gutenberg if the intent is to convert the parameter to
$deprecated
in Core.It's the kind of thing that can be easily missed when merging to the wp-dev repo so it would be good to avoid any risk.
It's also hooked on to
render_block_data
with10, 2
so may end up throwing an error. I'm unable to see if the filterrender_block_data
has changed in GB but it's pretty old so is probably only in WP-Dev now days.