PluginProbe
Gutenberg / 12.1.0
Gutenberg v12.1.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 7.4.0 All 402 releases
← All changes | lib/block-supports/elements.php +53 -236 23.1.012.1.0 View file →
@@ -5,262 +5,79 @@
5 5 * @package gutenberg
6 6 */
7 7
8 8 /**
9 - * Update the block content with elements class names.
9 + * Render the elements stylesheet.
10 10 *
11 - * @deprecated 6.6.0 Use `gutenberg_render_elements_class_name` instead.
12 - *
13 11 * @param string $block_content Rendered block content.
12 + * @param array $block Block object.
14 13 * @return string Filtered block content.
15 14 */
16 -function gutenberg_render_elements_support( $block_content ) {
17 - _deprecated_function( __FUNCTION__, '6.6.0', 'gutenberg_render_elements_class_name' );
18 - return $block_content;
19 -}
15 +function gutenberg_render_elements_support( $block_content, $block ) {
20 16
21 -/**
22 - * Determines whether an elements class name should be added to the block.
23 - *
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.
28 - */
29 -function gutenberg_should_add_elements_class_name( $block, $options ) {
30 - if ( ! isset( $block['attrs']['style']['elements'] ) ) {
31 - return false;
17 + if ( ! $block_content ) {
18 + return $block_content;
32 19 }
33 20
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 - );
77 -
78 - $elements_style_attributes = $block['attrs']['style']['elements'];
79 -
80 - foreach ( $element_color_properties as $element_config ) {
81 - if ( $element_config['skip'] ) {
82 - continue;
83 - }
84 -
85 - foreach ( $element_config['paths'] as $path ) {
86 - if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) {
87 - return true;
88 - }
89 - }
21 + $link_color = null;
22 + if ( ! empty( $block['attrs'] ) ) {
23 + $link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', 'color', 'text' ), null );
90 24 }
91 25
92 - return false;
93 -}
94 -
95 -/**
96 - * Render the elements stylesheet and adds elements class name to block as required.
97 - *
98 - * In the case of nested blocks we want the parent element styles to be rendered before their descendants.
99 - * This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant:
100 - * we want the descendant style to take priority, and this is done by loading it after, in DOM order.
101 - *
102 - * @since 6.6.0 Element block support class and styles are generated via the `render_block_data` filter instead of `pre_render_block`
103 - *
104 - * @param array $parsed_block The parsed block.
105 - *
106 - * @return array The same parsed block with elements classname added if appropriate.
107 - */
108 -function gutenberg_render_elements_support_styles( $parsed_block ) {
109 26 /*
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 - );
27 + * For now we only care about link color.
28 + * This code in the future when we have a public API
29 + * should take advantage of WP_Theme_JSON_Gutenberg::compute_style_properties
30 + * and work for any element and style.
31 + */
32 + if ( null === $link_color ) {
33 + return $block_content;
125 34 }
126 35
127 - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $parsed_block['blockName'] );
128 - $element_block_styles = $parsed_block['attrs']['style']['elements'] ?? null;
36 + $class_name = 'wp-elements-' . uniqid();
129 37
130 - if ( ! $element_block_styles ) {
131 - return $parsed_block;
38 + if ( strpos( $link_color, 'var:preset|color|' ) !== false ) {
39 + // Get the name from the string and add proper styles.
40 + $index_to_splice = strrpos( $link_color, '|' ) + 1;
41 + $link_color_name = substr( $link_color, $index_to_splice );
42 + $link_color = "var(--wp--preset--color--$link_color_name)";
132 43 }
44 + $link_color_declaration = esc_html( safecss_filter_attr( "color: $link_color" ) );
133 45
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;
46 + $style = "<style>.$class_name a{" . $link_color_declaration . ";}</style>\n";
140 47
141 - if ( $skips_all_element_color_serialization ) {
142 - return $parsed_block;
48 + // Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
49 + // Retrieve the opening tag of the first HTML element.
50 + $html_element_matches = array();
51 + preg_match( '/<[^>]+>/', $block_content, $html_element_matches, PREG_OFFSET_CAPTURE );
52 + $first_element = $html_element_matches[0][0];
53 + // If the first HTML element has a class attribute just add the new class
54 + // as we do on layout and duotone.
55 + if ( strpos( $first_element, 'class="' ) !== false ) {
56 + $content = preg_replace(
57 + '/' . preg_quote( 'class="', '/' ) . '/',
58 + 'class="' . $class_name . ' ',
59 + $block_content,
60 + 1
61 + );
62 + } else {
63 + // If the first HTML element has no class attribute we should inject the attribute before the attribute at the end.
64 + $first_element_offset = $html_element_matches[0][1];
65 + $content = substr_replace( $block_content, ' class="' . $class_name . '"', $first_element_offset + strlen( $first_element ) - 1, 0 );
143 66 }
144 67
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 ),
68 + // Ideally styles should be loaded in the head, but blocks may be parsed
69 + // after that, so loading in the footer for now.
70 + // See https://core.trac.wordpress.org/ticket/53494.
71 + add_action(
72 + 'wp_footer',
73 + function () use ( $style ) {
74 + echo $style;
75 + }
149 76 );
150 77
151 - if ( ! gutenberg_should_add_elements_class_name( $parsed_block, $options ) ) {
152 - return $parsed_block;
153 - }
154 -
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'] ) ) {
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;
78 + return $content;
226 79 }
227 80
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 - *
238 - * @return string Filtered block content.
239 - */
240 -function gutenberg_render_elements_class_name( $block_content, $block ) {
241 - $class_string = $block['attrs']['className'] ?? '';
242 - preg_match( '/\bwp-elements-\S+\b/', $class_string, $matches );
243 -
244 - if ( empty( $matches ) ) {
245 - return $block_content;
246 - }
247 -
248 - $tags = new WP_HTML_Tag_Processor( $block_content );
249 -
250 - if ( $tags->next_tag() ) {
251 - $tags->add_class( $matches[0] );
252 - }
253 -
254 - return $tags->get_updated_html();
255 -}
256 -
257 -// Remove deprecated WordPress core filters.
258 -remove_filter( 'render_block', 'wp_render_elements_support', 10 );
259 -remove_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10 );
260 -
261 -// Remove WordPress core filters to avoid rendering duplicate elements stylesheet & attaching classes twice.
262 -remove_filter( 'render_block', 'wp_render_elements_class_name', 10 );
263 -remove_filter( 'render_block_data', 'wp_render_elements_support_styles', 10 );
264 -
265 -add_filter( 'render_block', 'gutenberg_render_elements_class_name', 10, 2 );
266 -add_filter( 'render_block_data', 'gutenberg_render_elements_support_styles', 10, 1 );
81 +// Remove WordPress core filter to avoid rendering duplicate elements stylesheet.
82 +remove_filter( 'render_block', 'wp_render_elements_support', 10, 2 );
83 +add_filter( 'render_block', 'gutenberg_render_elements_support', 10, 2 );