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
← All changes | lib/client-assets.php +269 -352 7.4.017.0.2 View file →
@@ -1,8 +1,8 @@
1 1 <?php
2 2 /**
3 - * Functions to register client-side assets (scripts and stylesheets) for the
4 - * Gutenberg editor plugin.
3 + * Functions to register client-side assets (scripts and stylesheets) specific
4 + * for the Gutenberg editor plugin.
5 5 *
6 6 * @package gutenberg
7 7 */
8 8
@@ -17,9 +17,9 @@
17 17 *
18 18 * @since 0.1.0
19 19 */
20 20 function gutenberg_dir_path() {
21 - return plugin_dir_path( dirname( __FILE__ ) );
21 + return plugin_dir_path( __DIR__ );
22 22 }
23 23
24 24 /**
25 25 * Retrieves a URL to a file in the gutenberg plugin.
@@ -30,9 +30,9 @@
30 30 *
31 31 * @since 0.1.0
32 32 */
33 33 function gutenberg_url( $path ) {
34 - return plugins_url( $path, dirname( __FILE__ ) );
34 + return plugins_url( $path, __DIR__ );
35 35 }
36 36
37 37 /**
38 38 * Registers a script according to `wp_register_script`. Honors this request by
@@ -41,9 +41,9 @@
41 41 * avoid losing inline scripts which may have been attached.
42 42 *
43 43 * @since 4.1.0
44 44 *
45 - * @param WP_Scripts $scripts WP_Scripts instance (passed by reference).
45 + * @param WP_Scripts $scripts WP_Scripts instance.
46 46 * @param string $handle Name of the script. Should be unique.
47 47 * @param string $src Full URL of the script, or path of the script relative to the WordPress root directory.
48 48 * @param array $deps Optional. An array of registered script handles this script depends on. Default empty array.
49 49 * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL
@@ -52,9 +52,15 @@
52 52 * If set to null, no version is added.
53 53 * @param bool $in_footer Optional. Whether to enqueue the script before </body> instead of in the <head>.
54 54 * Default 'false'.
55 55 */
56 -function gutenberg_override_script( &$scripts, $handle, $src, $deps = array(), $ver = false, $in_footer = false ) {
56 +function gutenberg_override_script( $scripts, $handle, $src, $deps = array(), $ver = false, $in_footer = false ) {
57 + /*
58 + * Force `wp-i18n` script to be registered in the <head> as a
59 + * temporary workaround for https://meta.trac.wordpress.org/ticket/6195.
60 + */
61 + $in_footer = 'wp-i18n' === $handle ? false : $in_footer;
62 +
57 63 $script = $scripts->query( $handle, 'registered' );
58 64 if ( $script ) {
59 65 /*
60 66 * In many ways, this is a reimplementation of `wp_register_script` but
@@ -65,36 +71,29 @@
65 71 // See: `_WP_Dependency::__construct` .
66 72 $script->src = $src;
67 73 $script->deps = $deps;
68 74 $script->ver = $ver;
69 - $script->args = $in_footer;
75 + $script->args = $in_footer ? 1 : null;
76 + } else {
77 + $scripts->add( $handle, $src, $deps, $ver, ( $in_footer ? 1 : null ) );
78 + }
70 79
71 - /*
72 - * The script's `group` designation is an indication of whether it is
73 - * to be printed in the header or footer. The behavior here defers to
74 - * the arguments as passed. Specifically, group data is not assigned
75 - * for a script unless it is designated to be printed in the footer.
76 - */
77 -
78 - // See: `wp_register_script` .
79 - unset( $script->extra['group'] );
80 - if ( $in_footer ) {
81 - $script->add_data( 'group', 1 );
82 - }
83 - } else {
84 - $scripts->add( $handle, $src, $deps, $ver, $in_footer );
80 + if ( in_array( 'wp-i18n', $deps, true ) ) {
81 + $scripts->set_translations( $handle );
85 82 }
86 83
87 84 /*
88 - * `WP_Dependencies::set_translations` will fall over on itself if setting
89 - * translations on the `wp-i18n` handle, since it internally adds `wp-i18n`
90 - * as a dependency of itself, exhausting memory. The same applies for the
91 - * polyfill script, which is a dependency _of_ `wp-i18n`.
92 - *
93 - * See: https://core.trac.wordpress.org/ticket/46089
85 + * Wp-editor module is exposed as window.wp.editor.
86 + * Problem: there is quite some code expecting window.wp.oldEditor object available under window.wp.editor.
87 + * Solution: fuse the two objects together to maintain backward compatibility.
88 + * For more context, see https://github.com/WordPress/gutenberg/issues/33203
94 89 */
95 - if ( 'wp-i18n' !== $handle && 'wp-polyfill' !== $handle ) {
96 - $scripts->set_translations( $handle, 'default' );
90 + if ( 'wp-editor' === $handle ) {
91 + $scripts->add_inline_script(
92 + 'wp-editor',
93 + 'Object.assign( window.wp.editor, window.wp.oldEditor );',
94 + 'after'
95 + );
97 96 }
98 97 }
99 98
100 99 /**
@@ -114,14 +113,14 @@
114 113 return $file;
115 114 }
116 115
117 116 // Ignore scripts whose handle does not have the "wp-" prefix.
118 - if ( 'wp-' !== substr( $handle, 0, 3 ) ) {
117 + if ( ! str_starts_with( $handle, 'wp-' ) ) {
119 118 return $file;
120 119 }
121 120
122 121 // Ignore scripts that are not found in the expected `build/` location.
123 - $script_path = gutenberg_dir_path() . 'build/' . substr( $handle, 3 ) . '/index.js';
122 + $script_path = gutenberg_dir_path() . 'build/' . substr( $handle, 3 ) . '/index.min.js';
124 123 if ( ! file_exists( $script_path ) ) {
125 124 return $file;
126 125 }
127 126
@@ -149,33 +148,14 @@
149 148 }
150 149 add_filter( 'load_script_translation_file', 'gutenberg_override_translation_file', 10, 2 );
151 150
152 151 /**
153 - * Filters the default labels for common post types to change the case style
154 - * from capitalized (e.g. "Featured Image") to sentence-style (e.g. "Featured
155 - * image").
156 - *
157 - * See: https://github.com/WordPress/gutenberg/pull/18758
158 - *
159 - * @param object $labels Object with all the labels as member variables.
160 - *
161 - * @return object Object with all the labels, including overridden ones.
162 - */
163 -function gutenberg_override_posttype_labels( $labels ) {
164 - $labels->featured_image = __( 'Featured image', 'gutenberg' );
165 - return $labels;
166 -}
167 -foreach ( array( 'post', 'page' ) as $post_type ) {
168 - add_filter( "post_type_labels_{$post_type}", 'gutenberg_override_posttype_labels' );
169 -}
170 -
171 -/**
172 152 * Registers a style according to `wp_register_style`. Honors this request by
173 153 * deregistering any style by the same handler before registration.
174 154 *
175 155 * @since 4.1.0
176 156 *
177 - * @param WP_Styles $styles WP_Styles instance (passed by reference).
157 + * @param WP_Styles $styles WP_Styles instance.
178 158 * @param string $handle Name of the stylesheet. Should be unique.
179 159 * @param string $src Full URL of the stylesheet, or path of the stylesheet relative to the WordPress root directory.
180 160 * @param array $deps Optional. An array of registered stylesheet handles this stylesheet depends on. Default empty array.
181 161 * @param string|bool|null $ver Optional. String specifying stylesheet version number, if it has one, which is added to the URL
@@ -185,9 +165,9 @@
185 165 * @param string $media Optional. The media for which this stylesheet has been defined.
186 166 * Default 'all'. Accepts media types like 'all', 'print' and 'screen', or media queries like
187 167 * '(orientation: portrait)' and '(max-width: 640px)'.
188 168 */
189 -function gutenberg_override_style( &$styles, $handle, $src, $deps = array(), $ver = false, $media = 'all' ) {
169 +function gutenberg_override_style( $styles, $handle, $src, $deps = array(), $ver = false, $media = 'all' ) {
190 170 $style = $styles->query( $handle, 'registered' );
191 171 if ( $style ) {
192 172 $styles->remove( $handle );
193 173 }
@@ -194,79 +174,43 @@
194 174 $styles->add( $handle, $src, $deps, $ver, $media );
195 175 }
196 176
197 177 /**
198 - * Registers vendor JavaScript files to be used as dependencies of the editor
199 - * and plugins.
200 - *
201 - * This function is called from a script during the plugin build process, so it
202 - * should not call any WordPress PHP functions.
203 - *
204 - * @since 0.1.0
205 - *
206 - * @param WP_Scripts $scripts WP_Scripts instance (passed by reference).
207 - */
208 -function gutenberg_register_vendor_scripts( &$scripts ) {
209 - $suffix = SCRIPT_DEBUG ? '' : '.min';
210 -
211 - // Vendor Scripts.
212 - $react_suffix = ( SCRIPT_DEBUG ? '.development' : '.production' ) . $suffix;
213 -
214 - // TODO: Overrides for react, react-dom and lodash are necessary
215 - // until WordPress 5.3 is released.
216 - gutenberg_register_vendor_script(
217 - $scripts,
218 - 'react',
219 - 'https://unpkg.com/react@16.9.0/umd/react' . $react_suffix . '.js',
220 - array( 'wp-polyfill' ),
221 - '16.9.0',
222 - true
223 - );
224 - gutenberg_register_vendor_script(
225 - $scripts,
226 - 'react-dom',
227 - 'https://unpkg.com/react-dom@16.9.0/umd/react-dom' . $react_suffix . '.js',
228 - array( 'react' ),
229 - '16.9.0',
230 - true
231 - );
232 - gutenberg_register_vendor_script(
233 - $scripts,
234 - 'lodash',
235 - 'https://unpkg.com/lodash@4.17.15/lodash' . $suffix . '.js',
236 - array(),
237 - '4.17.15',
238 - true
239 - );
240 -}
241 -add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' );
242 -
243 -/**
244 178 * Registers all the WordPress packages scripts that are in the standardized
245 179 * `build/` location.
246 180 *
247 181 * @since 4.5.0
248 182 *
249 - * @param WP_Scripts $scripts WP_Scripts instance (passed by reference).
183 + * @param WP_Scripts $scripts WP_Scripts instance.
250 184 */
251 -function gutenberg_register_packages_scripts( &$scripts ) {
252 - foreach ( glob( gutenberg_dir_path() . 'build/*/index.js' ) as $path ) {
185 +function gutenberg_register_packages_scripts( $scripts ) {
186 + // When in production, use the plugin's version as the default asset version;
187 + // else (for development or test) default to use the current time.
188 + $default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();
189 +
190 + foreach ( glob( gutenberg_dir_path() . 'build/*/index.min.js' ) as $path ) {
253 191 // Prefix `wp-` to package directory to get script handle.
254 - // For example, `…/build/a11y/index.js` becomes `wp-a11y`.
192 + // For example, `…/build/a11y/index.min.js` becomes `wp-a11y`.
255 193 $handle = 'wp-' . basename( dirname( $path ) );
256 194
257 - // Replace `.js` extension with `.asset.php` to find the generated dependencies file.
258 - $asset_file = substr( $path, 0, -3 ) . '.asset.php';
195 + // Replace extension with `.asset.php` to find the generated dependencies file.
196 + $asset_file = substr( $path, 0, -( strlen( '.js' ) ) ) . '.asset.php';
259 197 $asset = file_exists( $asset_file )
260 - ? require( $asset_file )
198 + ? require $asset_file
261 199 : null;
262 200 $dependencies = isset( $asset['dependencies'] ) ? $asset['dependencies'] : array();
263 - $version = isset( $asset['version'] ) ? $asset['version'] : filemtime( $path );
201 + $version = isset( $asset['version'] ) ? $asset['version'] : $default_version;
264 202
265 203 // Add dependencies that cannot be detected and generated by build tools.
266 204 switch ( $handle ) {
267 205 case 'wp-block-library':
268 - array_push( $dependencies, 'editor' );
206 + if (
207 + ! gutenberg_is_experiment_enabled( 'gutenberg-no-tinymce' ) ||
208 + ! empty( $_GET['requiresTinymce'] ) ||
209 + gutenberg_post_being_edited_requires_classic_block()
210 + ) {
211 + array_push( $dependencies, 'editor' );
212 + }
269 213 break;
270 214
271 215 case 'wp-edit-post':
272 216 array_push( $dependencies, 'media-models', 'media-views', 'postbox' );
@@ -274,8 +218,11 @@
274 218
275 219 case 'wp-edit-site':
276 220 array_push( $dependencies, 'wp-dom-ready' );
277 221 break;
222 + case 'wp-preferences':
223 + array_push( $dependencies, 'wp-preferences-persistence' );
224 + break;
278 225 }
279 226
280 227 // Get the path from Gutenberg directory as expected by `gutenberg_url`.
281 228 $gutenberg_path = substr( $path, strlen( gutenberg_dir_path() ) );
@@ -297,18 +244,31 @@
297 244 * `build/` location.
298 245 *
299 246 * @since 6.7.0
300 247
301 - * @param WP_Styles $styles WP_Styles instance (passed by reference).
248 + * @param WP_Styles $styles WP_Styles instance.
302 249 */
303 -function gutenberg_register_packages_styles( &$styles ) {
250 +function gutenberg_register_packages_styles( $styles ) {
251 + // When in production, use the plugin's version as the asset version;
252 + // else (for development or test) default to use the current time.
253 + $version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();
254 +
255 + gutenberg_override_style(
256 + $styles,
257 + 'wp-block-editor-content',
258 + gutenberg_url( 'build/block-editor/content.css' ),
259 + array( 'wp-components' ),
260 + $version
261 + );
262 + $styles->add_data( 'wp-block-editor-content', 'rtl', 'replace' );
263 +
304 264 // Editor Styles.
305 265 gutenberg_override_style(
306 266 $styles,
307 267 'wp-block-editor',
308 268 gutenberg_url( 'build/block-editor/style.css' ),
309 - array( 'wp-components', 'wp-editor-font' ),
310 - filemtime( gutenberg_dir_path() . 'build/editor/style.css' )
269 + array( 'wp-components' ),
270 + $version
311 271 );
312 272 $styles->add_data( 'wp-block-editor', 'rtl', 'replace' );
313 273
314 274 gutenberg_override_style(
@@ -314,10 +274,10 @@
314 274 gutenberg_override_style(
315 275 $styles,
316 276 'wp-editor',
317 277 gutenberg_url( 'build/editor/style.css' ),
318 - array( 'wp-components', 'wp-block-editor', 'wp-nux' ),
319 - filemtime( gutenberg_dir_path() . 'build/editor/style.css' )
278 + array( 'wp-components', 'wp-block-editor', 'wp-patterns', 'wp-reusable-blocks' ),
279 + $version
320 280 );
321 281 $styles->add_data( 'wp-editor', 'rtl', 'replace' );
322 282
323 283 gutenberg_override_style(
@@ -323,10 +283,10 @@
323 283 gutenberg_override_style(
324 284 $styles,
325 285 'wp-edit-post',
326 286 gutenberg_url( 'build/edit-post/style.css' ),
327 - array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-block-library', 'wp-nux' ),
328 - filemtime( gutenberg_dir_path() . 'build/edit-post/style.css' )
287 + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-block-library', 'wp-commands' ),
288 + $version
329 289 );
330 290 $styles->add_data( 'wp-edit-post', 'rtl', 'replace' );
331 291
332 292 gutenberg_override_style(
@@ -332,21 +292,23 @@
332 292 gutenberg_override_style(
333 293 $styles,
334 294 'wp-components',
335 295 gutenberg_url( 'build/components/style.css' ),
336 - array(),
337 - filemtime( gutenberg_dir_path() . 'build/components/style.css' )
296 + array( 'dashicons' ),
297 + $version
338 298 );
339 299 $styles->add_data( 'wp-components', 'rtl', 'replace' );
340 300
301 + $block_library_filename = wp_should_load_separate_core_block_assets() ? 'common' : 'style';
341 302 gutenberg_override_style(
342 303 $styles,
343 304 'wp-block-library',
344 - gutenberg_url( 'build/block-library/style.css' ),
305 + gutenberg_url( 'build/block-library/' . $block_library_filename . '.css' ),
345 306 array(),
346 - filemtime( gutenberg_dir_path() . 'build/block-library/style.css' )
307 + $version
347 308 );
348 309 $styles->add_data( 'wp-block-library', 'rtl', 'replace' );
310 + $styles->add_data( 'wp-block-library', 'path', gutenberg_dir_path() . 'build/block-library/' . $block_library_filename . '.css' );
349 311
350 312 gutenberg_override_style(
351 313 $styles,
352 314 'wp-format-library',
@@ -351,24 +313,60 @@
351 313 $styles,
352 314 'wp-format-library',
353 315 gutenberg_url( 'build/format-library/style.css' ),
354 316 array( 'wp-block-editor', 'wp-components' ),
355 - filemtime( gutenberg_dir_path() . 'build/format-library/style.css' )
317 + $version
356 318 );
357 319 $styles->add_data( 'wp-format-library', 'rtl', 'replace' );
358 320
321 + $wp_edit_blocks_dependencies = array(
322 + 'wp-components',
323 + // This need to be added before the block library styles,
324 + // The block library styles override the "reset" styles.
325 + 'wp-reset-editor-styles',
326 + 'wp-block-library',
327 + 'wp-patterns',
328 + 'wp-reusable-blocks',
329 + // Until #37466, we can't specifically add them as editor styles yet,
330 + // so we must hard-code it here as a dependency.
331 + 'wp-block-editor-content',
332 + );
333 +
334 + // Only load the default layout and margin styles for themes without theme.json file.
335 + if ( ! wp_theme_has_theme_json() ) {
336 + $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles';
337 + }
338 +
339 + global $editor_styles;
340 + if ( current_theme_supports( 'wp-block-styles' ) && ( ! is_array( $editor_styles ) || count( $editor_styles ) === 0 ) ) {
341 + // Include opinionated block styles if the theme supports block styles and no $editor_styles are declared, so the editor never appears broken.
342 + $wp_edit_blocks_dependencies[] = 'wp-block-library-theme';
343 + }
344 +
359 345 gutenberg_override_style(
360 346 $styles,
347 + 'wp-reset-editor-styles',
348 + gutenberg_url( 'build/block-library/reset.css' ),
349 + array( 'common', 'forms' ), // Make sure the reset is loaded after the default WP Admin styles.
350 + $version
351 + );
352 + $styles->add_data( 'wp-reset-editor-styles', 'rtl', 'replace' );
353 +
354 + gutenberg_override_style(
355 + $styles,
356 + 'wp-editor-classic-layout-styles',
357 + gutenberg_url( 'build/edit-post/classic.css' ),
358 + array(),
359 + $version
360 + );
361 + $styles->add_data( 'wp-editor-classic-layout-styles', 'rtl', 'replace' );
362 +
363 + gutenberg_override_style(
364 + $styles,
361 365 'wp-edit-blocks',
362 366 gutenberg_url( 'build/block-library/editor.css' ),
363 - array(
364 - 'wp-components',
365 - 'wp-editor',
366 - 'wp-block-library',
367 - // Always include visual styles so the editor never appears broken.
368 - 'wp-block-library-theme',
369 - ),
370 - filemtime( gutenberg_dir_path() . 'build/block-library/editor.css' )
367 + $wp_edit_blocks_dependencies,
368 + $version
371 369 );
372 370 $styles->add_data( 'wp-edit-blocks', 'rtl', 'replace' );
373 371
374 372 gutenberg_override_style(
@@ -375,9 +373,9 @@
375 373 $styles,
376 374 'wp-nux',
377 375 gutenberg_url( 'build/nux/style.css' ),
378 376 array( 'wp-components' ),
379 - filemtime( gutenberg_dir_path() . 'build/nux/style.css' )
377 + $version
380 378 );
381 379 $styles->add_data( 'wp-nux', 'rtl', 'replace' );
382 380
383 381 gutenberg_override_style(
@@ -384,9 +382,9 @@
384 382 $styles,
385 383 'wp-block-library-theme',
386 384 gutenberg_url( 'build/block-library/theme.css' ),
387 385 array(),
388 - filemtime( gutenberg_dir_path() . 'build/block-library/theme.css' )
386 + $version
389 387 );
390 388 $styles->add_data( 'wp-block-library-theme', 'rtl', 'replace' );
391 389
392 390 gutenberg_override_style(
@@ -393,18 +391,27 @@
393 391 $styles,
394 392 'wp-list-reusable-blocks',
395 393 gutenberg_url( 'build/list-reusable-blocks/style.css' ),
396 394 array( 'wp-components' ),
397 - filemtime( gutenberg_dir_path() . 'build/list-reusable-blocks/style.css' )
395 + $version
398 396 );
399 397 $styles->add_data( 'wp-list-reusable-block', 'rtl', 'replace' );
400 398
401 399 gutenberg_override_style(
402 400 $styles,
401 + 'wp-commands',
402 + gutenberg_url( 'build/commands/style.css' ),
403 + array( 'wp-components' ),
404 + $version
405 + );
406 + $styles->add_data( 'wp-commands', 'rtl', 'replace' );
407 +
408 + gutenberg_override_style(
409 + $styles,
403 410 'wp-edit-site',
404 411 gutenberg_url( 'build/edit-site/style.css' ),
405 - array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ),
406 - filemtime( gutenberg_dir_path() . 'build/edit-site/style.css' )
412 + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-commands' ),
413 + $version
407 414 );
408 415 $styles->add_data( 'wp-edit-site', 'rtl', 'replace' );
409 416
410 417 gutenberg_override_style(
@@ -410,10 +417,10 @@
410 417 gutenberg_override_style(
411 418 $styles,
412 419 'wp-edit-widgets',
413 420 gutenberg_url( 'build/edit-widgets/style.css' ),
414 - array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ),
415 - filemtime( gutenberg_dir_path() . 'build/edit-widgets/style.css' )
421 + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-patterns', 'wp-reusable-blocks', 'wp-widgets' ),
422 + $version
416 423 );
417 424 $styles->add_data( 'wp-edit-widgets', 'rtl', 'replace' );
418 425
419 426 gutenberg_override_style(
@@ -420,260 +427,170 @@
420 427 $styles,
421 428 'wp-block-directory',
422 429 gutenberg_url( 'build/block-directory/style.css' ),
423 430 array( 'wp-block-editor', 'wp-components' ),
424 - filemtime( gutenberg_dir_path() . 'build/block-directory/style.css' )
431 + $version
425 432 );
426 433 $styles->add_data( 'wp-block-directory', 'rtl', 'replace' );
427 -}
428 -add_action( 'wp_default_styles', 'gutenberg_register_packages_styles' );
429 434
430 -/**
431 - * Registers common scripts and styles to be used as dependencies of the editor
432 - * and plugins.
433 - *
434 - * @since 0.1.0
435 - */
436 -function gutenberg_enqueue_block_editor_assets() {
437 - wp_add_inline_script(
438 - 'wp-api-fetch',
439 - sprintf(
440 - 'wp.apiFetch.nonceMiddleware = wp.apiFetch.createNonceMiddleware( "%s" );' .
441 - 'wp.apiFetch.use( wp.apiFetch.nonceMiddleware );' .
442 - 'wp.apiFetch.nonceEndpoint = "%s";' .
443 - 'wp.apiFetch.use( wp.apiFetch.mediaUploadMiddleware );',
444 - ( wp_installing() && ! is_multisite() ) ? '' : wp_create_nonce( 'wp_rest' ),
445 - admin_url( 'admin-ajax.php?action=gutenberg_rest_nonce' )
446 - ),
447 - 'after'
435 + gutenberg_override_style(
436 + $styles,
437 + 'wp-customize-widgets',
438 + gutenberg_url( 'build/customize-widgets/style.css' ),
439 + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-widgets' ),
440 + $version
448 441 );
442 + $styles->add_data( 'wp-customize-widgets', 'rtl', 'replace' );
449 443
450 - if ( defined( 'GUTENBERG_LIVE_RELOAD' ) && GUTENBERG_LIVE_RELOAD ) {
451 - $live_reload_url = ( GUTENBERG_LIVE_RELOAD === true ) ? 'http://localhost:35729/livereload.js' : GUTENBERG_LIVE_RELOAD;
444 + gutenberg_override_style(
445 + $styles,
446 + 'wp-patterns',
447 + gutenberg_url( 'build/patterns/style.css' ),
448 + array( 'wp-components' ),
449 + $version
450 + );
451 + $styles->add_data( 'wp-patterns', 'rtl', 'replace' );
452 452
453 - wp_enqueue_script(
454 - 'gutenberg-live-reload',
455 - $live_reload_url
456 - );
457 - }
453 + gutenberg_override_style(
454 + $styles,
455 + 'wp-reusable-blocks',
456 + gutenberg_url( 'build/reusable-blocks/style.css' ),
457 + array( 'wp-components' ),
458 + $version
459 + );
460 + $styles->add_data( 'wp-reusable-blocks', 'rtl', 'replace' );
461 +
462 + gutenberg_override_style(
463 + $styles,
464 + 'wp-widgets',
465 + gutenberg_url( 'build/widgets/style.css' ),
466 + array( 'wp-components' )
467 + );
468 + $styles->add_data( 'wp-widgets', 'rtl', 'replace' );
458 469 }
459 -add_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_block_editor_assets' );
470 +add_action( 'wp_default_styles', 'gutenberg_register_packages_styles' );
460 471
461 472 /**
462 - * Retrieves a unique and reasonably short and human-friendly filename for a
463 - * vendor script based on a URL and the script handle.
473 + * Fetches, processes and compiles stored core styles, then combines and renders them to the page.
474 + * Styles are stored via the Style Engine API.
464 475 *
465 - * @param string $handle The name of the script.
466 - * @param string $src Full URL of the external script.
476 + * This hook also exists, and should be backported to Core in future versions.
477 + * However, it is envisaged that Gutenberg will continue to use the Style Engine's `gutenberg_*` functions and `_Gutenberg` classes to aid continuous development.
467 478 *
468 - * @return string Script filename suitable for local caching.
479 + * See: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/
469 480 *
470 - * @since 0.1.0
471 - */
472 -function gutenberg_vendor_script_filename( $handle, $src ) {
473 - $filename = basename( $src );
474 - $match = preg_match(
475 - '/^'
476 - . '(?P<ignore>.*?)'
477 - . '(?P<suffix>\.min)?'
478 - . '(?P<extension>\.js)'
479 - . '(?P<extra>.*)'
480 - . '$/',
481 - $filename,
482 - $filename_pieces
483 - );
484 -
485 - $prefix = $handle;
486 - $suffix = $match ? $filename_pieces['suffix'] : '';
487 - $hash = substr( md5( $src ), 0, 8 );
488 -
489 - return "${prefix}${suffix}.${hash}.js";
490 -}
491 -
492 -/**
493 - * Registers a vendor script from a URL, preferring a locally cached version if
494 - * possible, or downloading it if the cached version is unavailable or
495 - * outdated.
481 + * @param array $options {
482 + * Optional. An array of options to pass to gutenberg_style_engine_get_stylesheet_from_context(). Default empty array.
496 483 *
497 - * @param WP_Scripts $scripts WP_Scripts instance (passed by reference).
498 - * @param string $handle Name of the script.
499 - * @param string $src Full URL of the external script.
500 - * @param array $deps Optional. An array of registered script handles this
501 - * script depends on.
502 - * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL
503 - * as a query string for cache busting purposes. If version is set to false, a version
504 - * number is automatically added equal to current installed WordPress version.
505 - * If set to null, no version is added.
506 - * @param bool $in_footer Optional. Whether to enqueue the script before </body> instead of in the <head>.
507 - * Default 'false'.
484 + * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
485 + * @type bool $prettify Whether to add new lines and indents to output. Default is the test of whether the global constant `SCRIPT_DEBUG` is defined.
486 + * }
508 487 *
509 - * @since 0.1.0
488 + * @since 6.1
489 + *
490 + * @return void
510 491 */
511 -function gutenberg_register_vendor_script( &$scripts, $handle, $src, $deps = array(), $ver = null, $in_footer = false ) {
512 - if ( defined( 'GUTENBERG_LOAD_VENDOR_SCRIPTS' ) && ! GUTENBERG_LOAD_VENDOR_SCRIPTS ) {
492 +function gutenberg_enqueue_stored_styles( $options = array() ) {
493 + $is_block_theme = wp_is_block_theme();
494 + $is_classic_theme = ! $is_block_theme;
495 +
496 + /*
497 + * For block themes, print stored styles in the header.
498 + * For classic themes, in the footer.
499 + */
500 + if (
501 + ( $is_block_theme && doing_action( 'wp_footer' ) ) ||
502 + ( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) )
503 + ) {
513 504 return;
514 505 }
515 506
516 - $filename = gutenberg_vendor_script_filename( $handle, $src );
517 -
518 - if ( defined( 'GUTENBERG_LIST_VENDOR_ASSETS' ) && GUTENBERG_LIST_VENDOR_ASSETS ) {
519 - echo "$src|$filename\n";
520 - return;
507 + $core_styles_keys = array( 'block-supports' );
508 + $compiled_core_stylesheet = '';
509 + $style_tag_id = 'core';
510 + foreach ( $core_styles_keys as $style_key ) {
511 + // Adds comment if code is prettified to identify core styles sections in debugging.
512 + $should_prettify = isset( $options['prettify'] ) ? true === $options['prettify'] : SCRIPT_DEBUG;
513 + if ( $should_prettify ) {
514 + $compiled_core_stylesheet .= "/**\n * Core styles: $style_key\n */\n";
515 + }
516 + // Chains core store ids to signify what the styles contain.
517 + $style_tag_id .= '-' . $style_key;
518 + $compiled_core_stylesheet .= gutenberg_style_engine_get_stylesheet_from_context( $style_key, $options );
521 519 }
522 520
523 - $full_path = gutenberg_dir_path() . 'vendor/' . $filename;
524 -
525 - $needs_fetch = (
526 - defined( 'GUTENBERG_DEVELOPMENT_MODE' ) && GUTENBERG_DEVELOPMENT_MODE && (
527 - ! file_exists( $full_path ) ||
528 - time() - filemtime( $full_path ) >= DAY_IN_SECONDS
529 - )
530 - );
531 -
532 - if ( $needs_fetch ) {
533 - // Determine whether we can write to this file. If not, don't waste
534 - // time doing a network request.
535 - // @codingStandardsIgnoreStart
536 - $f = @fopen( $full_path, 'a' );
537 - // @codingStandardsIgnoreEnd
538 - if ( ! $f ) {
539 - // Failed to open the file for writing, probably due to server
540 - // permissions. Enqueue the script directly from the URL instead.
541 - gutenberg_override_script( $scripts, $handle, $src, $deps, $ver, $in_footer );
542 - return;
543 - }
544 - fclose( $f );
545 - $response = wp_remote_get( $src );
546 - if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
547 - $f = fopen( $full_path, 'w' );
548 - fwrite( $f, wp_remote_retrieve_body( $response ) );
549 - fclose( $f );
550 - } elseif ( ! filesize( $full_path ) ) {
551 - // The request failed. If the file is already cached, continue to
552 - // use this file. If not, then unlink the 0 byte file, and enqueue
553 - // the script directly from the URL.
554 - gutenberg_override_script( $scripts, $handle, $src, $deps, $ver, $in_footer );
555 - unlink( $full_path );
556 - return;
557 - }
521 + // Combines Core styles.
522 + if ( ! empty( $compiled_core_stylesheet ) ) {
523 + wp_register_style( $style_tag_id, false, array(), true, true );
524 + wp_add_inline_style( $style_tag_id, $compiled_core_stylesheet );
525 + wp_enqueue_style( $style_tag_id );
558 526 }
559 - gutenberg_override_script(
560 - $scripts,
561 - $handle,
562 - gutenberg_url( 'vendor/' . $filename ),
563 - $deps,
564 - $ver,
565 - $in_footer
566 - );
567 -}
568 527
569 -/**
570 - * Extends block editor settings to include Gutenberg's `editor-styles.css` as
571 - * taking precedent those styles shipped with core.
572 - *
573 - * @param array $settings Default editor settings.
574 - *
575 - * @return array Filtered editor settings.
576 - */
577 -function gutenberg_extend_block_editor_styles( $settings ) {
578 - $editor_styles_file = gutenberg_dir_path() . 'build/editor/editor-styles.css';
528 + // If there are any other stores registered by themes etc., print them out.
529 + $additional_stores = WP_Style_Engine_CSS_Rules_Store_Gutenberg::get_stores();
579 530
580 531 /*
581 - * If, for whatever reason, the built editor styles do not exist, avoid
582 - * override and fall back to the default.
532 + * Since the corresponding action hook in Core is removed below,
533 + * this function should still honour any styles stored using the Core Style Engine store.
583 534 */
584 - if ( ! file_exists( $editor_styles_file ) ) {
585 - return $settings;
535 + if ( class_exists( 'WP_Style_Engine_CSS_Rules_Store' ) ) {
536 + $additional_stores = array_merge( $additional_stores, WP_Style_Engine_CSS_Rules_Store::get_stores() );
586 537 }
587 538
588 - if ( empty( $settings['styles'] ) ) {
589 - $settings['styles'] = array();
590 - } else {
591 - /*
592 - * The styles setting is an array of CSS strings, so there is no direct
593 - * way to find the default styles. To maximize stability, load (again)
594 - * the default styles from disk and find its place in the array.
595 - *
596 - * See: https://github.com/WordPress/wordpress-develop/blob/5.0.3/src/wp-admin/edit-form-blocks.php#L168-L175
597 - */
598 -
599 - $default_styles = file_get_contents(
600 - ABSPATH . WPINC . '/css/dist/editor/editor-styles.css'
601 - );
602 -
603 - /*
604 - * Iterate backwards from the end of the array since the preferred
605 - * insertion point in case not found is prepended as first entry.
606 - */
607 - for ( $i = count( $settings['styles'] ) - 1; $i >= 0; $i-- ) {
608 - if ( isset( $settings['styles'][ $i ]['css'] ) &&
609 - $default_styles === $settings['styles'][ $i ]['css'] ) {
610 - break;
611 - }
539 + foreach ( array_keys( $additional_stores ) as $store_name ) {
540 + if ( in_array( $store_name, $core_styles_keys, true ) ) {
541 + continue;
612 542 }
543 + $styles = gutenberg_style_engine_get_stylesheet_from_context( $store_name, $options );
544 + if ( ! empty( $styles ) ) {
545 + $key = "wp-style-engine-$store_name";
546 + wp_register_style( $key, false, array(), true, true );
547 + wp_add_inline_style( $key, $styles );
548 + wp_enqueue_style( $key );
549 + }
613 550 }
614 -
615 - $editor_styles = array(
616 - 'css' => file_get_contents( $editor_styles_file ),
617 - );
618 -
619 - // Substitute default styles if found. Otherwise, prepend to setting array.
620 - if ( isset( $i ) && $i >= 0 ) {
621 - $settings['styles'][ $i ] = $editor_styles;
622 - } else {
623 - array_unshift( $settings['styles'], $editor_styles );
624 - }
625 -
626 - return $settings;
627 551 }
628 -add_filter( 'block_editor_settings', 'gutenberg_extend_block_editor_styles' );
629 552
630 553 /**
631 - * Extends block editor preload paths to preload additional data. Note that any
632 - * additions here should be complemented with a corresponding core ticket to
633 - * reconcile the change upstream for future removal from Gutenberg.
554 + * Registers vendor JavaScript files to be used as dependencies of the editor
555 + * and plugins.
634 556 *
635 - * @param array $preload_paths Array of paths to preload.
636 - * @param WP_Post $post Post being edited.
557 + * This function is called from a script during the plugin build process, so it
558 + * should not call any WordPress PHP functions.
637 559 *
638 - * @return array Filtered array of paths to preload.
560 + * @since 13.0
561 + *
562 + * @param WP_Scripts $scripts WP_Scripts instance.
639 563 */
640 -function gutenberg_extend_block_editor_preload_paths( $preload_paths, $post ) {
641 - /*
642 - * Preload any autosaves for the post. (see https://github.com/WordPress/gutenberg/pull/7945)
643 - *
644 - * Trac ticket: https://core.trac.wordpress.org/ticket/46974
645 - *
646 - * At the time of writing, the change is not committed or released
647 - * in core. This path should be removed from Gutenberg when the code is
648 - * released in core, and the corresponding release version becomes
649 - * the minimum supported version.
650 - */
651 - $post_type_object = get_post_type_object( $post->post_type );
564 +function gutenberg_register_vendor_scripts( $scripts ) {
565 + $extension = SCRIPT_DEBUG ? '.js' : '.min.js';
652 566
653 - if ( isset( $post_type_object ) ) {
654 - $rest_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name;
655 - $autosaves_path = sprintf( '/wp/v2/%s/%d/autosaves?context=edit', $rest_base, $post->ID );
567 + gutenberg_override_script(
568 + $scripts,
569 + 'react',
570 + gutenberg_url( 'build/vendors/react' . $extension ),
571 + // See https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react.
572 + SCRIPT_DEBUG ? array( 'wp-react-refresh-entry', 'wp-polyfill' ) : array( 'wp-polyfill' ),
573 + '18'
574 + );
575 + gutenberg_override_script(
576 + $scripts,
577 + 'react-dom',
578 + gutenberg_url( 'build/vendors/react-dom' . $extension ),
579 + array( 'react' ),
580 + '18'
581 + );
582 +}
583 +add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' );
656 584
657 - if ( ! in_array( $autosaves_path, $preload_paths, true ) ) {
658 - $preload_paths[] = $autosaves_path;
659 - }
660 - }
661 585
662 - /*
663 - * Used in considering user permissions for creating and updating blocks,
664 - * as condition for displaying relevant actions in the interface.
665 - *
666 - * Trac ticket: https://core.trac.wordpress.org/ticket/46429
667 - *
668 - * This is present in WordPress 5.2 and should be removed from Gutenberg
669 - * once WordPress 5.2 is the minimum supported version.
670 - */
671 - $blocks_path = array( '/wp/v2/blocks', 'OPTIONS' );
586 +/*
587 + * Always remove the Core action hook while gutenberg_enqueue_stored_styles() exists to avoid styles being printed twice.
588 + * This is also because gutenberg_enqueue_stored_styles uses the Style Engine's `gutenberg_*` functions and `_Gutenberg` classes,
589 + * which are in continuous development and generally ahead of Core.
590 + */
591 +remove_action( 'wp_enqueue_scripts', 'wp_enqueue_stored_styles' );
592 +remove_action( 'wp_footer', 'wp_enqueue_stored_styles', 1 );
672 593
673 - if ( ! in_array( $blocks_path, $preload_paths, true ) ) {
674 - $preload_paths[] = $blocks_path;
675 - }
676 -
677 - return $preload_paths;
678 -}
679 -add_filter( 'block_editor_preload_paths', 'gutenberg_extend_block_editor_preload_paths', 10, 2 );
594 +// Enqueue stored styles.
595 +add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_stored_styles' );
596 +add_action( 'wp_footer', 'gutenberg_enqueue_stored_styles', 1 );