-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Try adding layout classnames to inner block wrapper #44600
Changes from all commits
7e34fb5
a29bd4a
d291f82
1315784
0d0f24f
1327338
95a330b
0ad7274
03757a2
06ad2b5
8295cbd
d34bb68
e87b92b
4074881
5381d2b
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 |
---|---|---|
|
@@ -291,6 +291,23 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support | |
return ''; | ||
} | ||
|
||
/** | ||
* Gets classname from last tag in a string of HTML. | ||
* | ||
* @param string $html markup to be processed. | ||
* @return string String of inner wrapper classnames. | ||
*/ | ||
function gutenberg_get_classnames_from_last_tag( $html ) { | ||
$tags = new WP_HTML_Tag_Processor( $html ); | ||
$last_classnames = ''; | ||
|
||
while ( $tags->next_tag() ) { | ||
$last_classnames = $tags->get_attribute( 'class' ); | ||
} | ||
|
||
return $last_classnames; | ||
} | ||
|
||
/** | ||
* Renders the layout config to the block wrapper. | ||
* | ||
|
@@ -320,7 +337,6 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { | |
|
||
$class_names = array(); | ||
$layout_definitions = _wp_array_get( $global_layout_settings, array( 'definitions' ), array() ); | ||
$block_classname = wp_get_block_default_classname( $block['blockName'] ); | ||
$container_class = wp_unique_id( 'wp-container-' ); | ||
$layout_classname = ''; | ||
|
||
|
@@ -397,7 +413,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { | |
$should_skip_gap_serialization = gutenberg_should_skip_block_supports_serialization( $block_type, 'spacing', 'blockGap' ); | ||
|
||
$style = gutenberg_get_layout_style( | ||
".$block_classname.$container_class", | ||
".$container_class.$container_class", | ||
$used_layout, | ||
$has_block_gap_support, | ||
$gap_value, | ||
|
@@ -412,16 +428,22 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { | |
} | ||
} | ||
|
||
/* | ||
* This assumes the hook only applies to blocks with a single wrapper. | ||
* A limitation of this hook is that nested inner blocks wrappers are not yet supported. | ||
*/ | ||
$content = preg_replace( | ||
'/' . preg_quote( 'class="', '/' ) . '/', | ||
'class="' . esc_attr( implode( ' ', $class_names ) ) . ' ', | ||
$block_content, | ||
1 | ||
); | ||
/** | ||
* The first chunk of innerContent contains the block markup up until the inner blocks start. | ||
* We want to target the opening tag of the inner blocks wrapper, which is the last tag in that chunk. | ||
*/ | ||
$inner_content_classnames = isset( $block['innerContent'][0] ) && 'string' === gettype( $block['innerContent'][0] ) ? gutenberg_get_classnames_from_last_tag( $block['innerContent'][0] ) : ''; | ||
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. Is it worth adding a comment to explain what the
Please correct me, though, if I've misunderstood how this is working, I just looked up the block parser class, so I think that's what it's doing, but could very well be wrong 🙂 From the comment in that class, it sounds like there's the potential for blocks to have another string between For now, looking at the last tag in the opening string sounds good to me! 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. Yes, that's exactly how it works! Good idea to add a comment, as it's not immediately obvious. |
||
|
||
$content = new WP_HTML_Tag_Processor( $block_content ); | ||
if ( $inner_content_classnames ) { | ||
$content->next_tag( array( 'class_name' => $inner_content_classnames ) ); | ||
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 does what you want it to do, but it surprised me that it did, because we intended to search for individual class names and not the entire list of classes. it would be good to be aware that if we were to chop out one of the classes this would fail because the classes in 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. I think it's safe to take that risk here because we haven't changed anything in 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. @tellthemachines you could filter the tag openers manually: $sought_class_names = $inner_content_classnames;
while( $content->next_tag() ) {
$tag_class_names = preg_split('/\s+/', $content->get_attribute( 'class' ));
if ( /* the two overlap */ ) {
// ...
}
} I dislike the 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. @adamziel my spidey-sense suggests it wouldn't be that much of an added value above what I don't want people to do is what we have in your code example. we provide semantic operations to add and remove CSS classes. if we're encouraging people to extract the raw value(s) and perform their own twiddling then we're just pushing them away from a robust framework and towards multiple ad-hoc implementations of the same thing. it highlights the elephant in the room, which are class names with HTML entities. we may have to come back and revisit those; maybe we could find a way to detect if we think we have an entity (a character is point being is that I think still it's more ideal to focus on intended behaviors instead of internal mechanics. why do we want 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. Such a good point @dmsnell, let's explore adding 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. 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. @getdave what is the good example in that taking a guess, it looks like the goal is to only seek out if we want to know if any inner block HTML contains the class, the tag processor already includes this functionality. $inner_tags = new WP_HTML_Tag_Processor( $inner_blocks_html );
$has_current_menu_item = $inner_tags->next_tag( [ 'class_name' => 'current-menu-item' ] ); Secondly, I don't know that the 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. @dmsnell Using
Now that I think about it, the 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. @adamziel apart from the HTML entities, which we currently don't match, the on the one hand, in terms of the general case I'd really want measured data showing that the additional complexity is worth it. my guess is that sometimes it would be faster and sometimes it would be slower, but in all cases it would add additional complexity. 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. |
||
foreach ( $class_names as $class_name ) { | ||
$content->add_class( $class_name ); | ||
} | ||
} else { | ||
$content->next_tag(); | ||
$content->add_class( implode( ' ', $class_names ) ); | ||
} | ||
|
||
return $content; | ||
} | ||
|
@@ -433,6 +455,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { | |
'register_attribute' => 'gutenberg_register_layout_support', | ||
) | ||
); | ||
|
||
if ( function_exists( 'wp_render_layout_support_flag' ) ) { | ||
remove_filter( 'render_block', 'wp_render_layout_support_flag' ); | ||
} | ||
|
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.
This change looks good to me. Is the reason we needed to do it because in the JS side of things we won't always have access to the block classname, is that right? Either way, I think the block classname was only there to increase specificity of this selector, so the change sounds good to me.
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.
This is needed because the block class is attached to the outer wrapper, and because we're now adding the container class to the inner wrapper this style block will no longer work with that combination.