-
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
Site Title: Add support settings for colors, fonts, and line height #23007
Changes from all commits
805d34b
05d22e8
d652a9f
357942c
a2db6d0
3a3095b
3eb8e4d
871a272
fa6567b
76bc4f8
efc7c7b
7e659a9
c215ae9
0d40bad
229dcd6
e45898d
977384b
e1cfeaa
680a694
65c9763
9ec8584
5ca9b47
a9b1e3e
732e255
160d86f
c958549
e089533
d493142
2395a3e
fec7628
d62406e
32bd8bb
f909ab2
1bf2fc0
bf1e768
e81946e
8923bd8
a581770
7cb2693
543fb7e
806a23f
998f7f6
0559112
35a5856
aa4bbdc
1987286
ba6a395
7c17c76
9e148d1
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 |
---|---|---|
|
@@ -216,3 +216,189 @@ function gutenberg_register_legacy_social_link_blocks() { | |
} | ||
} | ||
add_action( 'init', 'gutenberg_register_legacy_social_link_blocks' ); | ||
|
||
/** | ||
* Renders the classNames and styles for blocks | ||
* | ||
* @param string $block_content Output of the current block. | ||
* @param array $block Block Object. | ||
* @return string New block output. | ||
*/ | ||
function gutenberg_experimental_apply_classnames_and_styles( $block_content, $block ) { | ||
if ( ! isset( $block['attrs'] ) ) { | ||
return $block_content; | ||
} | ||
|
||
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); | ||
// If no render_callback, assume styles have been previously handled. | ||
if ( ! $block_type || ! $block_type->render_callback ) { | ||
return $block_content; | ||
} | ||
// Check what style features the block supports. | ||
$supports = gutenberg_experimental_global_styles_get_supported_styles( $block_type->supports ); | ||
|
||
$attributes = array(); | ||
$attributes = gutenberg_experimental_build_css_colors( $attributes, $block['attrs'], $supports ); | ||
$attributes = gutenberg_experimental_build_css_typography( $attributes, $block['attrs'], $supports ); | ||
|
||
if ( ! count( $attributes ) ) { | ||
return $block_content; | ||
} | ||
|
||
$dom = new DOMDocument( '1.0', 'utf-8' ); | ||
|
||
// Suppress warnings from this method from polluting the front-end. | ||
// @codingStandardsIgnoreStart | ||
if ( ! @$dom->loadHTML( $block_content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_COMPACT ) ) { | ||
Comment on lines
+248
to
+252
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. Thanks for catching it. 👍 |
||
// @codingStandardsIgnoreEnd | ||
return $block_content; | ||
} | ||
|
||
$xpath = new DOMXPath( $dom ); | ||
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 wonder if regex is more performant. This is definitely stronger and safer but in the long run, performance is important for the frontend. I'm happy starting with this and monitor impact 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 had a similar thought about performance, but attempting to parse HTML with a regex gets messy really quickly. FWIW, I found myself in a similar situation a while ago, when adding a new sniff to WPCS. I ended up using XMLReader which out of a number of options seemed to have the smallest resource footprint. However, I only needed parsing at the time -- I didn't have to write HTML. For writing, there's however XMLWriter -- maybe it could be used in combination with XMLReader. Here's a StackOverflow post listing PHP's built-in (and external) HTML parsing options. Here's some more background on RegEx-based parsing (and why it's messy) and alternatives. |
||
$block_root = $xpath->query( '/*' )[0]; | ||
|
||
if ( empty( $block_root ) ) { | ||
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 ) ) ); | ||
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. If I am reading this correctly, the separator for Same for two lines above at the assignment of Using a
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. Do the styles in It does look like we need to update these so that they are more consistent with each other and can properly remove the duplicates. We can implode 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 didn't check to see if this was guaranteeable, but those are the styles I got after using the actual user-facing tools. I'd look at the framework to make sure. If it seems like spaces could make their way in, you can always use php > var_dump( preg_split( '/; ?/', 'color:red;color:green; color:blue' ) );
array(3) {
[0]=>
string(9) "color:red"
[1]=>
string(11) "color:green"
[2]=>
string(10) "color:blue"
} Of course, you can take it as far as you like: php > var_dump( preg_split( '/ *; */', 'color:red ; color:green; color:blue' ) );
array(3) {
[0]=>
string(9) "color:red"
[1]=>
string(11) "color:green"
[2]=>
string(10) "color:blue"
} 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'm not sure what you mean here. When wouldn't 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. Ah yeah
I just mean that currently the values 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. Thanks for pointing this out by the way. I hope to address this relatively shortly but have been preoccupied so far today. 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 proposed a fix in #24486 |
||
|
||
// Apply new styles and classes. | ||
if ( ! empty( $new_classes ) ) { | ||
$block_root->setAttribute( 'class', $new_classes ); | ||
} | ||
|
||
if ( ! empty( $new_styles ) ) { | ||
$block_root->setAttribute( 'style', $new_styles ); | ||
} | ||
|
||
return $dom->saveHtml(); | ||
} | ||
add_filter( 'render_block', 'gutenberg_experimental_apply_classnames_and_styles', 10, 2 ); | ||
|
||
/** | ||
* Build an array with CSS classes and inline styles defining the colors | ||
* which will be applied to the block markup in the front-end. | ||
* | ||
* @param array $attributes comprehensive list of attributes to be applied. | ||
* @param array $block_attributes block attributes. | ||
* @param array $supports style features the block attributes. | ||
* @return array Colors CSS classes and inline styles. | ||
*/ | ||
function gutenberg_experimental_build_css_colors( $attributes, $block_attributes, $supports ) { | ||
// Text Colors. | ||
// Check support for text colors. | ||
if ( in_array( 'color', $supports, true ) ) { | ||
$has_named_text_color = array_key_exists( 'textColor', $block_attributes ); | ||
$has_custom_text_color = isset( $block_attributes['style']['color']['text'] ); | ||
|
||
// Apply required generic class. | ||
if ( $has_custom_text_color || $has_named_text_color ) { | ||
$attributes['css_classes'][] = 'has-text-color'; | ||
} | ||
// Apply color class or inline style. | ||
if ( $has_named_text_color ) { | ||
$attributes['css_classes'][] = sprintf( 'has-%s-color', $block_attributes['textColor'] ); | ||
} elseif ( $has_custom_text_color ) { | ||
$attributes['inline_styles'][] = sprintf( 'color: %s;', $block_attributes['style']['color']['text'] ); | ||
} | ||
} | ||
|
||
// Link Colors. | ||
if ( in_array( 'link-color', $supports, true ) ) { | ||
$has_link_color = isset( $block_attributes['style']['color']['link'] ); | ||
// Apply required class and style. | ||
if ( $has_link_color ) { | ||
$attributes['css_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 ); | ||
$attributes['inline_styles'][] = sprintf( '--wp--style--color--link:var(--wp--preset--color--%s);', $link_color_name ); | ||
} else { | ||
$attributes['inline_styles'][] = sprintf( '--wp--style--color--link: %s;', $block_attributes['style']['color']['link'] ); | ||
} | ||
} | ||
} | ||
|
||
// Background Colors. | ||
if ( in_array( 'background-color', $supports, true ) ) { | ||
$has_named_background_color = array_key_exists( 'backgroundColor', $block_attributes ); | ||
$has_custom_background_color = isset( $block_attributes['style']['color']['background'] ); | ||
|
||
// Apply required background class. | ||
if ( $has_custom_background_color || $has_named_background_color ) { | ||
$attributes['css_classes'][] = 'has-background'; | ||
} | ||
// Apply background color classes or styles. | ||
if ( $has_named_background_color ) { | ||
$attributes['css_classes'][] = sprintf( 'has-%s-background-color', $block_attributes['backgroundColor'] ); | ||
} elseif ( $has_custom_background_color ) { | ||
$attributes['inline_styles'][] = sprintf( 'background-color: %s;', $block_attributes['style']['color']['background'] ); | ||
} | ||
} | ||
|
||
// Gradients. | ||
if ( in_array( 'background', $supports, true ) ) { | ||
$has_named_gradient = array_key_exists( 'gradient', $block_attributes ); | ||
$has_custom_gradient = isset( $block_attributes['style']['color']['gradient'] ); | ||
|
||
if ( $has_named_gradient || $has_custom_gradient ) { | ||
$attributes['css_classes'][] = 'has-background'; | ||
} | ||
// Apply required background class. | ||
if ( $has_named_gradient ) { | ||
$attributes['css_classes'][] = sprintf( 'has-%s-gradient-background', $block_attributes['gradient'] ); | ||
} elseif ( $has_custom_gradient ) { | ||
$attributes['inline_styles'][] = sprintf( 'background: %s;', $block_attributes['style']['color']['gradient'] ); | ||
} | ||
} | ||
Addison-Stavlo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return $attributes; | ||
} | ||
|
||
/** | ||
* Build an array with CSS classes and inline styles defining the font sizes | ||
* which will be applied to the block markup in the front-end. | ||
* | ||
* @param array $attributes comprehensive list of attributes to be applied. | ||
* @param array $block_attributes block attributes. | ||
* @param array $supports style features the block attributes. | ||
* @return array Font size CSS classes and inline styles. | ||
*/ | ||
function gutenberg_experimental_build_css_typography( $attributes, $block_attributes, $supports ) { | ||
// Font Size. | ||
if ( in_array( 'font-size', $supports, true ) ) { | ||
$has_named_font_size = array_key_exists( 'fontSize', $block_attributes ); | ||
$has_custom_font_size = isset( $block_attributes['style']['typography']['fontSize'] ); | ||
|
||
// Apply required class or style. | ||
if ( $has_named_font_size ) { | ||
$attributes['css_classes'][] = sprintf( 'has-%s-font-size', $block_attributes['fontSize'] ); | ||
} elseif ( $has_custom_font_size ) { | ||
$attributes['inline_styles'][] = sprintf( 'font-size: %spx;', $block_attributes['style']['typography']['fontSize'] ); | ||
} | ||
} | ||
|
||
// Line Height. | ||
if ( in_array( 'line-height', $supports, true ) ) { | ||
$has_line_height = isset( $block_attributes['style']['typography']['lineHeight'] ); | ||
// Add the style (no classes for line-height). | ||
if ( $has_line_height ) { | ||
$attributes['inline_styles'][] = sprintf( 'line-height: %s;', $block_attributes['style']['typography']['lineHeight'] ); | ||
} | ||
} | ||
|
||
return $attributes; | ||
} | ||
Addison-Stavlo marked this conversation as resolved.
Show resolved
Hide resolved
|
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.
what happens with existing blocks that already apply these flags on the frontend on their "save" function? how can we exclude them from this behavior?
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.
They go through this function unnecessarily. They do 'play nice', although this function handling them as well is a bit redundant.
Im not sure. There doesn't seem to be anything on the block object passed into the function that signifies anything special about this case. Maybe we can add an extra property on the block object or an attr to signal that it should be ignored by this function? Im open to ideas...
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.
wouldn't testing for the presence of "render_callback" enough maybe?
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.
That seems to do the trick! Thank you 😄 - 7c17c76