PluginProbe
Gutenberg / 16.2.0
Gutenberg v16.2.0
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
← All changes | lib/block-supports/elements.php +76 -243 23.7.0 → 16.2.0 View file →
@@ -5,282 +5,115 @@
5 5 * @package gutenberg
6 6 */
7 7
8 8 /**
9 - * Update the block content with elements class names.
9 + * Get the elements class names.
10 10 *
11 - * @deprecated 6.6.0 Use `gutenberg_render_elements_class_name` instead.
12 - *
13 - * @param string $block_content Rendered block content.
14 - * @return string Filtered block content.
11 + * @param array $block Block object.
12 + * @return string The unique class name.
15 13 */
16 -function gutenberg_render_elements_support( $block_content ) {
17 - _deprecated_function( __FUNCTION__, '6.6.0', 'gutenberg_render_elements_class_name' );
18 - return $block_content;
14 +function gutenberg_get_elements_class_name( $block ) {
15 + return 'wp-elements-' . md5( serialize( $block ) );
19 16 }
20 17
21 18 /**
22 - * Determines whether an elements class name should be added to the block.
19 + * Update the block content with elements class names.
23 20 *
24 - * @param array $block Block object.
25 - * @param array $options Per element type options e.g. whether to skip serialization.
26 - *
27 - * @return boolean Whether the block needs an elements class name.
21 + * @param string $block_content Rendered block content.
22 + * @param array $block Block object.
23 + * @return string Filtered block content.
28 24 */
29 -function gutenberg_should_add_elements_class_name( $block, $options ) {
30 - if ( ! isset( $block['attrs']['style']['elements'] ) ) {
31 - return false;
25 +function gutenberg_render_elements_support( $block_content, $block ) {
26 + if ( ! $block_content ) {
27 + return $block_content;
32 28 }
33 29
34 - $element_color_properties = array(
35 - 'button' => array(
36 - 'skip' => $options['button']['skip'] ?? false,
37 - 'paths' => array(
38 - array( 'button', 'color', 'text' ),
39 - array( 'button', 'color', 'background' ),
40 - array( 'button', 'color', 'gradient' ),
41 - ),
42 - ),
43 - 'link' => array(
44 - 'skip' => $options['link']['skip'] ?? false,
45 - 'paths' => array(
46 - array( 'link', 'color', 'text' ),
47 - array( 'link', ':hover', 'color', 'text' ),
48 - ),
49 - ),
50 - 'heading' => array(
51 - 'skip' => $options['heading']['skip'] ?? false,
52 - 'paths' => array(
53 - array( 'heading', 'color', 'text' ),
54 - array( 'heading', 'color', 'background' ),
55 - array( 'heading', 'color', 'gradient' ),
56 - array( 'h1', 'color', 'text' ),
57 - array( 'h1', 'color', 'background' ),
58 - array( 'h1', 'color', 'gradient' ),
59 - array( 'h2', 'color', 'text' ),
60 - array( 'h2', 'color', 'background' ),
61 - array( 'h2', 'color', 'gradient' ),
62 - array( 'h3', 'color', 'text' ),
63 - array( 'h3', 'color', 'background' ),
64 - array( 'h3', 'color', 'gradient' ),
65 - array( 'h4', 'color', 'text' ),
66 - array( 'h4', 'color', 'background' ),
67 - array( 'h4', 'color', 'gradient' ),
68 - array( 'h5', 'color', 'text' ),
69 - array( 'h5', 'color', 'background' ),
70 - array( 'h5', 'color', 'gradient' ),
71 - array( 'h6', 'color', 'text' ),
72 - array( 'h6', 'color', 'background' ),
73 - array( 'h6', 'color', 'gradient' ),
74 - ),
75 - ),
76 - );
30 + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
31 + $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
77 32
78 - $elements_style_attributes = $block['attrs']['style']['elements'];
33 + if ( $skip_link_color_serialization ) {
34 + return $block_content;
35 + }
79 36
80 - foreach ( $element_color_properties as $element_config ) {
81 - if ( $element_config['skip'] ) {
82 - continue;
83 - }
37 + $link_color = null;
38 + if ( ! empty( $block['attrs'] ) ) {
39 + $link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', 'color', 'text' ), null );
40 + }
84 41
85 - foreach ( $element_config['paths'] as $path ) {
86 - if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) {
87 - return true;
88 - }
89 - }
42 + $hover_link_color = null;
43 + if ( ! empty( $block['attrs'] ) ) {
44 + $hover_link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', ':hover', 'color', 'text' ), null );
90 45 }
91 46
92 - return false;
47 + /*
48 + * For now we only care about link colors.
49 + * This code in the future when we have a public API
50 + * should take advantage of WP_Theme_JSON_Gutenberg::compute_style_properties
51 + * and work for any element and style.
52 + */
53 + if ( null === $link_color && null === $hover_link_color ) {
54 + return $block_content;
55 + }
56 +
57 + // Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
58 + // Add the class name to the first element, presuming it's the wrapper, if it exists.
59 + $tags = new WP_HTML_Tag_Processor( $block_content );
60 + if ( $tags->next_tag() ) {
61 + $tags->add_class( gutenberg_get_elements_class_name( $block ) );
62 + }
63 +
64 + return $tags->get_updated_html();
93 65 }
94 66
95 67 /**
96 - * Render the elements stylesheet and adds elements class name to block as required.
68 + * Render the elements stylesheet.
97 69 *
98 70 * In the case of nested blocks we want the parent element styles to be rendered before their descendants.
99 71 * This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant:
100 72 * we want the descendant style to take priority, and this is done by loading it after, in DOM order.
101 73 *
102 - * @since 6.6.0 Element block support class and styles are generated via the `render_block_data` filter instead of `pre_render_block`
74 + * @param string|null $pre_render The pre-rendered content. Default null.
75 + * @param array $block The block being rendered.
103 76 *
104 - * @param array $parsed_block The parsed block.
105 - *
106 - * @return array The same parsed block with elements classname added if appropriate.
77 + * @return null
107 78 */
108 -function gutenberg_render_elements_support_styles( $parsed_block ) {
79 +function gutenberg_render_elements_support_styles( $pre_render, $block ) {
80 + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
81 + $element_block_styles = isset( $block['attrs']['style']['elements'] ) ? $block['attrs']['style']['elements'] : null;
82 +
109 83 /*
110 - * The generation of element styles and classname were moved to the
111 - * `render_block_data` filter in 6.6.0 to avoid filtered attributes
112 - * breaking the application of the elements CSS class.
113 - *
114 - * @link https://github.com/WordPress/gutenberg/pull/59535
115 - *
116 - * The change in filter means, the argument types for this function
117 - * have changed and require deprecating.
118 - */
119 - if ( is_string( $parsed_block ) ) {
120 - _deprecated_argument(
121 - __FUNCTION__,
122 - '6.6.0',
123 - __( 'Use as a `pre_render_block` filter is deprecated. Use with `render_block_data` instead.', 'gutenberg' )
124 - );
125 - }
84 + * For now we only care about link color.
85 + */
86 + $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
126 87
127 - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] );
128 - $element_block_styles = $parsed_block['attrs']['style']['elements'] ?? null;
129 -
130 - if ( ! $element_block_styles ) {
131 - return $parsed_block;
88 + if ( $skip_link_color_serialization ) {
89 + return null;
132 90 }
91 + $class_name = gutenberg_get_elements_class_name( $block );
92 + $link_block_styles = isset( $element_block_styles['link'] ) ? $element_block_styles['link'] : null;
133 93
134 - $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
135 - $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' );
136 - $skip_button_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' );
137 - $skips_all_element_color_serialization = $skip_link_color_serialization &&
138 - $skip_heading_color_serialization &&
139 - $skip_button_color_serialization;
140 -
141 - if ( $skips_all_element_color_serialization ) {
142 - return $parsed_block;
143 - }
144 -
145 - $options = array(
146 - 'button' => array( 'skip' => $skip_button_color_serialization ),
147 - 'link' => array( 'skip' => $skip_link_color_serialization ),
148 - 'heading' => array( 'skip' => $skip_heading_color_serialization ),
94 + gutenberg_style_engine_get_styles(
95 + $link_block_styles,
96 + array(
97 + 'selector' => ".$class_name a",
98 + 'context' => 'block-supports',
99 + )
149 100 );
150 101
151 - if ( ! gutenberg_should_add_elements_class_name( $parsed_block, $options ) ) {
152 - return $parsed_block;
102 + if ( isset( $link_block_styles[':hover'] ) ) {
103 + gutenberg_style_engine_get_styles(
104 + $link_block_styles[':hover'],
105 + array(
106 + 'selector' => ".$class_name a:hover",
107 + 'context' => 'block-supports',
108 + )
109 + );
153 110 }
154 111
155 - $class_name = wp_get_elements_class_name( $parsed_block );
156 - $updated_class_name = isset( $parsed_block['attrs']['className'] ) ? $parsed_block['attrs']['className'] . " $class_name" : $class_name;
157 -
158 - _wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );
159 -
160 - // Generate element styles based on selector and store in style engine for enqueuing.
161 - $element_types = array(
162 - 'button' => array(
163 - 'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link",
164 - 'skip' => $skip_button_color_serialization,
165 - ),
166 - 'link' => array(
167 - // :where(:not) matches theme.json selector.
168 - 'selector' => ".$class_name a:where(:not(.wp-element-button))",
169 - 'hover_selector' => ".$class_name a:where(:not(.wp-element-button)):hover",
170 - 'skip' => $skip_link_color_serialization,
171 - ),
172 - 'heading' => array(
173 - 'selector' => ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6",
174 - 'skip' => $skip_heading_color_serialization,
175 - 'elements' => array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ),
176 - ),
177 - );
178 -
179 - foreach ( $element_types as $element_type => $element_config ) {
180 - if ( $element_config['skip'] ) {
181 - continue;
182 - }
183 -
184 - $element_style_object = _wp_array_get( $element_block_styles, array( $element_type ), null );
185 -
186 - // Process primary element type styles.
187 - if ( $element_style_object ) {
188 - gutenberg_style_engine_get_styles(
189 - $element_style_object,
190 - array(
191 - 'selector' => $element_config['selector'],
192 - 'context' => 'block-supports',
193 - )
194 - );
195 -
196 - if ( isset( $element_style_object[':hover'], $element_config['hover_selector'] ) ) {
197 - gutenberg_style_engine_get_styles(
198 - $element_style_object[':hover'],
199 - array(
200 - 'selector' => $element_config['hover_selector'],
201 - 'context' => 'block-supports',
202 - )
203 - );
204 - }
205 - }
206 -
207 - // Process related elements e.g. h1-h6 for headings.
208 - if ( isset( $element_config['elements'] ) ) {
209 - foreach ( $element_config['elements'] as $element ) {
210 - $element_style_object = _wp_array_get( $element_block_styles, array( $element ), null );
211 -
212 - if ( $element_style_object ) {
213 - gutenberg_style_engine_get_styles(
214 - $element_style_object,
215 - array(
216 - 'selector' => ".$class_name $element",
217 - 'context' => 'block-supports',
218 - )
219 - );
220 - }
221 - }
222 - }
223 - }
224 -
225 - return $parsed_block;
112 + return null;
226 113 }
227 114
228 -/**
229 - * Ensure the elements block support class name generated, and added to
230 - * block attributes, in the `render_block_data` filter gets applied to the
231 - * block's markup.
232 - *
233 - * @see gutenberg_render_elements_support_styles
234 - *
235 - * @param string $block_content Rendered block content.
236 - * @param array $block Block object.
237 - * @return string Filtered block content.
238 - *
239 - * @phpstan-param array{
240 - * attrs: array{
241 - * className?: string,
242 - * ...
243 - * },
244 - * ...
245 - * } $block
246 - */
247 -function gutenberg_render_elements_class_name( $block_content, $block ) {
248 - $class_name_attr = $block['attrs']['className'] ?? null;
249 - $class_name_prefix = 'wp-elements-';
250 - if ( ! is_string( $class_name_attr ) || ! str_contains( $class_name_attr, $class_name_prefix ) ) {
251 - return $block_content;
252 - }
253 -
254 - // Parse out the 'wp-elements-*' class name.
255 - $matched_class_name = null;
256 - $token_delimiter = " \t\f\r\n";
257 - $class_token = strtok( $class_name_attr, $token_delimiter );
258 - while ( false !== $class_token ) {
259 - if ( str_starts_with( $class_token, $class_name_prefix ) ) {
260 - $matched_class_name = $class_token;
261 - break;
262 - }
263 - $class_token = strtok( $token_delimiter );
264 - }
265 - if ( null === $matched_class_name ) {
266 - return $block_content;
267 - }
268 -
269 - $tags = new WP_HTML_Tag_Processor( $block_content );
270 - if ( $tags->next_tag() ) {
271 - $tags->add_class( $matched_class_name );
272 - }
273 -
274 - return $tags->get_updated_html();
275 -}
276 -
277 -// Remove deprecated WordPress core filters.
278 -remove_filter( 'render_block', 'wp_render_elements_support', 10 );
279 -remove_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10 );
280 -
281 115 // Remove WordPress core filters to avoid rendering duplicate elements stylesheet & attaching classes twice.
282 -remove_filter( 'render_block', 'wp_render_elements_class_name', 10 );
283 -remove_filter( 'render_block_data', 'wp_render_elements_support_styles', 10 );
284 -
285 -add_filter( 'render_block', 'gutenberg_render_elements_class_name', 10, 2 );
286 -add_filter( 'render_block_data', 'gutenberg_render_elements_support_styles', 10, 1 );
116 +remove_filter( 'render_block', 'wp_render_elements_support', 10, 2 );
117 +remove_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10, 2 );
118 +add_filter( 'render_block', 'gutenberg_render_elements_support', 10, 2 );
119 +add_filter( 'pre_render_block', 'gutenberg_render_elements_support_styles', 10, 2 );