PluginProbe
Gutenberg / 17.0.2
Gutenberg v17.0.2
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
gutenberg / lib / block-supports / elements.php

elements.php in Gutenberg 17.0.2, at lib/block-supports/elements.php

210 lines 7.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Elements styles block support.
4 *
5 * @package gutenberg
6 */
7
8 /**
9 * Update the block content with elements class names.
10 *
11 * @param string $block_content Rendered block content.
12 * @param array $block Block object.
13 * @return string Filtered block content.
14 */
15 function gutenberg_render_elements_support( $block_content, $block ) {
16 if ( ! $block_content || ! isset( $block['attrs']['style']['elements'] ) ) {
17 return $block_content;
18 }
19
20 $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
21
22 $element_color_properties = array(
23 'button' => array(
24 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ),
25 'paths' => array(
26 array( 'button', 'color', 'text' ),
27 array( 'button', 'color', 'background' ),
28 array( 'button', 'color', 'gradient' ),
29 ),
30 ),
31 'link' => array(
32 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ),
33 'paths' => array(
34 array( 'link', 'color', 'text' ),
35 array( 'link', ':hover', 'color', 'text' ),
36 ),
37 ),
38 'heading' => array(
39 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ),
40 'paths' => array(
41 array( 'heading', 'color', 'text' ),
42 array( 'heading', 'color', 'background' ),
43 array( 'heading', 'color', 'gradient' ),
44 array( 'h1', 'color', 'text' ),
45 array( 'h1', 'color', 'background' ),
46 array( 'h1', 'color', 'gradient' ),
47 array( 'h2', 'color', 'text' ),
48 array( 'h2', 'color', 'background' ),
49 array( 'h2', 'color', 'gradient' ),
50 array( 'h3', 'color', 'text' ),
51 array( 'h3', 'color', 'background' ),
52 array( 'h3', 'color', 'gradient' ),
53 array( 'h4', 'color', 'text' ),
54 array( 'h4', 'color', 'background' ),
55 array( 'h4', 'color', 'gradient' ),
56 array( 'h5', 'color', 'text' ),
57 array( 'h5', 'color', 'background' ),
58 array( 'h5', 'color', 'gradient' ),
59 array( 'h6', 'color', 'text' ),
60 array( 'h6', 'color', 'background' ),
61 array( 'h6', 'color', 'gradient' ),
62 ),
63 ),
64 );
65
66 $skip_all_element_color_serialization = $element_color_properties['button']['skip'] &&
67 $element_color_properties['link']['skip'] &&
68 $element_color_properties['heading']['skip'];
69
70 if ( $skip_all_element_color_serialization ) {
71 return $block_content;
72 }
73
74 $elements_style_attributes = $block['attrs']['style']['elements'];
75
76 foreach ( $element_color_properties as $element_config ) {
77 if ( $element_config['skip'] ) {
78 continue;
79 }
80
81 foreach ( $element_config['paths'] as $path ) {
82 if ( null !== _wp_array_get( $elements_style_attributes, $path, null ) ) {
83 /*
84 * It only takes a single custom attribute to require that the custom
85 * class name be added to the block, so once one is found there's no
86 * need to continue looking for others.
87 *
88 * As is done with the layout hook, this code assumes that the block
89 * contains a single wrapper and that it's the first element in the
90 * rendered output. That first element, if it exists, gets the class.
91 */
92 $tags = new WP_HTML_Tag_Processor( $block_content );
93 if ( $tags->next_tag() ) {
94 $tags->add_class( wp_get_elements_class_name( $block ) );
95 }
96
97 return $tags->get_updated_html();
98 }
99 }
100 }
101
102 // If no custom attributes were found then there's nothing to modify.
103 return $block_content;
104 }
105
106 /**
107 * Render the elements stylesheet.
108 *
109 * In the case of nested blocks we want the parent element styles to be rendered before their descendants.
110 * This solves the issue of an element (e.g.: link color) being styled in both the parent and a descendant:
111 * we want the descendant style to take priority, and this is done by loading it after, in DOM order.
112 *
113 * @param string|null $pre_render The pre-rendered content. Default null.
114 * @param array $block The block being rendered.
115 *
116 * @return null
117 */
118 function gutenberg_render_elements_support_styles( $pre_render, $block ) {
119 $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
120 $element_block_styles = isset( $block['attrs']['style']['elements'] ) ? $block['attrs']['style']['elements'] : null;
121
122 if ( ! $element_block_styles ) {
123 return null;
124 }
125
126 $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
127 $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' );
128 $skip_button_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' );
129 $skips_all_element_color_serialization = $skip_link_color_serialization &&
130 $skip_heading_color_serialization &&
131 $skip_button_color_serialization;
132
133 if ( $skips_all_element_color_serialization ) {
134 return null;
135 }
136
137 $class_name = wp_get_elements_class_name( $block );
138
139 $element_types = array(
140 'button' => array(
141 'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link",
142 'skip' => $skip_button_color_serialization,
143 ),
144 'link' => array(
145 'selector' => ".$class_name a",
146 'hover_selector' => ".$class_name a:hover",
147 'skip' => $skip_link_color_serialization,
148 ),
149 'heading' => array(
150 'selector' => ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6",
151 'skip' => $skip_heading_color_serialization,
152 'elements' => array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ),
153 ),
154 );
155
156 foreach ( $element_types as $element_type => $element_config ) {
157 if ( $element_config['skip'] ) {
158 continue;
159 }
160
161 $element_style_object = _wp_array_get( $element_block_styles, array( $element_type ), null );
162
163 // Process primary element type styles.
164 if ( $element_style_object ) {
165 gutenberg_style_engine_get_styles(
166 $element_style_object,
167 array(
168 'selector' => $element_config['selector'],
169 'context' => 'block-supports',
170 )
171 );
172
173 if ( isset( $element_style_object[':hover'] ) ) {
174 gutenberg_style_engine_get_styles(
175 $element_style_object[':hover'],
176 array(
177 'selector' => $element_config['hover_selector'],
178 'context' => 'block-supports',
179 )
180 );
181 }
182 }
183
184 // Process related elements e.g. h1-h6 for headings.
185 if ( isset( $element_config['elements'] ) ) {
186 foreach ( $element_config['elements'] as $element ) {
187 $element_style_object = _wp_array_get( $element_block_styles, array( $element ), null );
188
189 if ( $element_style_object ) {
190 gutenberg_style_engine_get_styles(
191 $element_style_object,
192 array(
193 'selector' => ".$class_name $element",
194 'context' => 'block-supports',
195 )
196 );
197 }
198 }
199 }
200 }
201
202 return null;
203 }
204
205 // Remove WordPress core filters to avoid rendering duplicate elements stylesheet & attaching classes twice.
206 remove_filter( 'render_block', 'wp_render_elements_support', 10, 2 );
207 remove_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10, 2 );
208 add_filter( 'render_block', 'gutenberg_render_elements_support', 10, 2 );
209 add_filter( 'pre_render_block', 'gutenberg_render_elements_support_styles', 10, 2 );
210