PluginProbe
Gutenberg / 19.6.1
Gutenberg v19.6.1
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 +238 -242 12.6.019.6.1 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
@@ -12,11 +12,11 @@
12 12
13 13 /**
14 14 * Retrieves the root plugin path.
15 15 *
16 + * @since 0.1.0
17 + *
16 18 * @return string Root path to the gutenberg plugin.
17 - *
18 - * @since 0.1.0
19 19 */
20 20 function gutenberg_dir_path() {
21 21 return plugin_dir_path( __DIR__ );
22 22 }
@@ -23,13 +23,13 @@
23 23
24 24 /**
25 25 * Retrieves a URL to a file in the gutenberg plugin.
26 26 *
27 + * @since 0.1.0
28 + *
27 29 * @param string $path Relative path of the desired file.
28 30 *
29 31 * @return string Fully qualified URL pointing to the desired file.
30 - *
31 - * @since 0.1.0
32 32 */
33 33 function gutenberg_url( $path ) {
34 34 return plugins_url( $path, __DIR__ );
35 35 }
@@ -53,8 +53,14 @@
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 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,15 @@
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;
70 -
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 - }
75 + $script->args = $in_footer ? 1 : null;
83 76 } else {
84 - $scripts->add( $handle, $src, $deps, $ver, $in_footer );
77 + $scripts->add( $handle, $src, $deps, $ver, ( $in_footer ? 1 : null ) );
85 78 }
86 79
87 - /*
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 and hooks scripts, which are dependencies _of_ `wp-i18n`.
92 - *
93 - * See: https://core.trac.wordpress.org/ticket/46089
94 - */
95 - if ( ! in_array( $handle, array( 'wp-i18n', 'wp-polyfill', 'wp-hooks' ), true ) ) {
96 - $scripts->set_translations( $handle, 'default' );
80 + if ( in_array( 'wp-i18n', $deps, true ) ) {
81 + $scripts->set_translations( $handle );
97 82 }
98 83
99 84 /*
100 85 * Wp-editor module is exposed as window.wp.editor.
@@ -128,9 +113,9 @@
128 113 return $file;
129 114 }
130 115
131 116 // Ignore scripts whose handle does not have the "wp-" prefix.
132 - if ( 'wp-' !== substr( $handle, 0, 3 ) ) {
117 + if ( ! str_starts_with( $handle, 'wp-' ) ) {
133 118 return $file;
134 119 }
135 120
136 121 // Ignore scripts that are not found in the expected `build/` location.
@@ -189,39 +174,8 @@
189 174 $styles->add( $handle, $src, $deps, $ver, $media );
190 175 }
191 176
192 177 /**
193 - * Registers vendor JavaScript files to be used as dependencies of the editor
194 - * and plugins.
195 - *
196 - * This function is called from a script during the plugin build process, so it
197 - * should not call any WordPress PHP functions.
198 - *
199 - * @since 0.1.0
200 - *
201 - * @param WP_Scripts $scripts WP_Scripts instance.
202 - */
203 -function gutenberg_register_vendor_scripts( $scripts ) {
204 - $suffix = SCRIPT_DEBUG ? '' : '.min';
205 -
206 - $react_suffix = ( SCRIPT_DEBUG ? '.development' : '.production' ) . $suffix;
207 - gutenberg_register_vendor_script(
208 - $scripts,
209 - 'react',
210 - 'https://unpkg.com/react@17.0.1/umd/react' . $react_suffix . '.js',
211 - // See https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react.
212 - SCRIPT_DEBUG ? array( 'wp-react-refresh-entry', 'wp-polyfill' ) : array( 'wp-polyfill' )
213 - );
214 - gutenberg_register_vendor_script(
215 - $scripts,
216 - 'react-dom',
217 - 'https://unpkg.com/react-dom@17.0.1/umd/react-dom' . $react_suffix . '.js',
218 - array( 'react' )
219 - );
220 -}
221 -add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' );
222 -
223 -/**
224 178 * Registers all the WordPress packages scripts that are in the standardized
225 179 * `build/` location.
226 180 *
227 181 * @since 4.5.0
@@ -230,9 +184,9 @@
230 184 */
231 185 function gutenberg_register_packages_scripts( $scripts ) {
232 186 // When in production, use the plugin's version as the default asset version;
233 187 // else (for development or test) default to use the current time.
234 - $default_version = defined( 'GUTENBERG_VERSION' ) && ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? GUTENBERG_VERSION : time();
188 + $default_version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();
235 189
236 190 foreach ( glob( gutenberg_dir_path() . 'build/*/index.min.js' ) as $path ) {
237 191 // Prefix `wp-` to package directory to get script handle.
238 192 // For example, `…/build/a11y/index.min.js` becomes `wp-a11y`.
@@ -240,9 +194,9 @@
240 194
241 195 // Replace extension with `.asset.php` to find the generated dependencies file.
242 196 $asset_file = substr( $path, 0, -( strlen( '.js' ) ) ) . '.asset.php';
243 197 $asset = file_exists( $asset_file )
244 - ? require( $asset_file )
198 + ? require $asset_file
245 199 : null;
246 200 $dependencies = isset( $asset['dependencies'] ) ? $asset['dependencies'] : array();
247 201 $version = isset( $asset['version'] ) ? $asset['version'] : $default_version;
248 202
@@ -248,9 +202,15 @@
248 202
249 203 // Add dependencies that cannot be detected and generated by build tools.
250 204 switch ( $handle ) {
251 205 case 'wp-block-library':
252 - 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 + }
253 213 break;
254 214
255 215 case 'wp-edit-post':
256 216 array_push( $dependencies, 'media-models', 'media-views', 'postbox' );
@@ -258,8 +218,11 @@
258 218
259 219 case 'wp-edit-site':
260 220 array_push( $dependencies, 'wp-dom-ready' );
261 221 break;
222 + case 'wp-preferences':
223 + array_push( $dependencies, 'wp-preferences-persistence' );
224 + break;
262 225 }
263 226
264 227 // Get the path from Gutenberg directory as expected by `gutenberg_url`.
265 228 $gutenberg_path = substr( $path, strlen( gutenberg_dir_path() ) );
@@ -280,22 +243,33 @@
280 243 * Registers all the WordPress packages styles that are in the standardized
281 244 * `build/` location.
282 245 *
283 246 * @since 6.7.0
284 -
247 + *
248 + * @global array $editor_styles
249 + *
285 250 * @param WP_Styles $styles WP_Styles instance.
286 251 */
287 252 function gutenberg_register_packages_styles( $styles ) {
288 253 // When in production, use the plugin's version as the asset version;
289 254 // else (for development or test) default to use the current time.
290 - $version = defined( 'GUTENBERG_VERSION' ) && ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? GUTENBERG_VERSION : time();
255 + $version = defined( 'GUTENBERG_VERSION' ) && ! SCRIPT_DEBUG ? GUTENBERG_VERSION : time();
291 256
257 + gutenberg_override_style(
258 + $styles,
259 + 'wp-block-editor-content',
260 + gutenberg_url( 'build/block-editor/content.css' ),
261 + array( 'wp-components' ),
262 + $version
263 + );
264 + $styles->add_data( 'wp-block-editor-content', 'rtl', 'replace' );
265 +
292 266 // Editor Styles.
293 267 gutenberg_override_style(
294 268 $styles,
295 269 'wp-block-editor',
296 270 gutenberg_url( 'build/block-editor/style.css' ),
297 - array( 'wp-components' ),
271 + array( 'wp-components', 'wp-preferences' ),
298 272 $version
299 273 );
300 274 $styles->add_data( 'wp-block-editor', 'rtl', 'replace' );
301 275
@@ -302,9 +276,9 @@
302 276 gutenberg_override_style(
303 277 $styles,
304 278 'wp-editor',
305 279 gutenberg_url( 'build/editor/style.css' ),
306 - array( 'wp-components', 'wp-block-editor', 'wp-nux', 'wp-reusable-blocks' ),
280 + array( 'wp-components', 'wp-block-editor', 'wp-patterns', 'wp-reusable-blocks', 'wp-preferences' ),
307 281 $version
308 282 );
309 283 $styles->add_data( 'wp-editor', 'rtl', 'replace' );
310 284
@@ -311,9 +285,9 @@
311 285 gutenberg_override_style(
312 286 $styles,
313 287 'wp-edit-post',
314 288 gutenberg_url( 'build/edit-post/style.css' ),
315 - array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-block-library', 'wp-nux' ),
289 + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-block-library', 'wp-commands', 'wp-preferences' ),
316 290 $version
317 291 );
318 292 $styles->add_data( 'wp-edit-post', 'rtl', 'replace' );
319 293
@@ -345,26 +319,28 @@
345 319 $version
346 320 );
347 321 $styles->add_data( 'wp-format-library', 'rtl', 'replace' );
348 322
323 + // Only add CONTENT styles here that should be enqueued in the iframe!
349 324 $wp_edit_blocks_dependencies = array(
350 325 'wp-components',
351 - 'wp-editor',
352 326 // This need to be added before the block library styles,
353 327 // The block library styles override the "reset" styles.
354 328 'wp-reset-editor-styles',
355 329 'wp-block-library',
356 - 'wp-reusable-blocks',
330 + // Until #37466, we can't specifically add them as editor styles yet,
331 + // so we must hard-code it here as a dependency.
332 + 'wp-block-editor-content',
357 333 );
358 334
359 335 // Only load the default layout and margin styles for themes without theme.json file.
360 - if ( ! WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) {
336 + if ( ! wp_theme_has_theme_json() ) {
361 337 $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles';
362 338 }
363 339
364 340 global $editor_styles;
365 - if ( ! is_array( $editor_styles ) || count( $editor_styles ) === 0 ) {
366 - // Include opinionated block styles if no $editor_styles are declared, so the editor never appears broken.
341 + if ( current_theme_supports( 'wp-block-styles' ) && ( ! is_array( $editor_styles ) || count( $editor_styles ) === 0 ) ) {
342 + // Include opinionated block styles if the theme supports block styles and no $editor_styles are declared, so the editor never appears broken.
367 343 $wp_edit_blocks_dependencies[] = 'wp-block-library-theme';
368 344 }
369 345
370 346 gutenberg_override_style(
@@ -386,8 +362,17 @@
386 362 $styles->add_data( 'wp-editor-classic-layout-styles', 'rtl', 'replace' );
387 363
388 364 gutenberg_override_style(
389 365 $styles,
366 + 'wp-block-library-editor',
367 + gutenberg_url( 'build/block-library/editor.css' ),
368 + array(),
369 + $version
370 + );
371 + $styles->add_data( 'wp-block-library-editor', 'rtl', 'replace' );
372 +
373 + gutenberg_override_style(
374 + $styles,
390 375 'wp-edit-blocks',
391 376 gutenberg_url( 'build/block-library/editor.css' ),
392 377 $wp_edit_blocks_dependencies,
393 378 $version
@@ -422,20 +407,20 @@
422 407 $styles->add_data( 'wp-list-reusable-block', 'rtl', 'replace' );
423 408
424 409 gutenberg_override_style(
425 410 $styles,
426 - 'wp-edit-navigation',
427 - gutenberg_url( 'build/edit-navigation/style.css' ),
428 - array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ),
411 + 'wp-commands',
412 + gutenberg_url( 'build/commands/style.css' ),
413 + array( 'wp-components' ),
429 414 $version
430 415 );
431 - $styles->add_data( 'wp-edit-navigation', 'rtl', 'replace' );
416 + $styles->add_data( 'wp-commands', 'rtl', 'replace' );
432 417
433 418 gutenberg_override_style(
434 419 $styles,
435 420 'wp-edit-site',
436 421 gutenberg_url( 'build/edit-site/style.css' ),
437 - array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks' ),
422 + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-block-library-editor', 'common', 'forms', 'wp-commands', 'wp-preferences' ),
438 423 $version
439 424 );
440 425 $styles->add_data( 'wp-edit-site', 'rtl', 'replace' );
441 426
@@ -442,9 +427,9 @@
442 427 gutenberg_override_style(
443 428 $styles,
444 429 'wp-edit-widgets',
445 430 gutenberg_url( 'build/edit-widgets/style.css' ),
446 - array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks', 'wp-reusable-blocks', 'wp-widgets' ),
431 + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-patterns', 'wp-widgets', 'wp-preferences' ),
447 432 $version
448 433 );
449 434 $styles->add_data( 'wp-edit-widgets', 'rtl', 'replace' );
450 435
@@ -460,9 +445,9 @@
460 445 gutenberg_override_style(
461 446 $styles,
462 447 'wp-customize-widgets',
463 448 gutenberg_url( 'build/customize-widgets/style.css' ),
464 - array( 'wp-components', 'wp-block-editor', 'wp-edit-blocks', 'wp-widgets' ),
449 + array( 'wp-components', 'wp-block-editor', 'wp-editor', 'wp-edit-blocks', 'wp-widgets', 'wp-preferences' ),
465 450 $version
466 451 );
467 452 $styles->add_data( 'wp-customize-widgets', 'rtl', 'replace' );
468 453
@@ -467,14 +452,23 @@
467 452 $styles->add_data( 'wp-customize-widgets', 'rtl', 'replace' );
468 453
469 454 gutenberg_override_style(
470 455 $styles,
456 + 'wp-patterns',
457 + gutenberg_url( 'build/patterns/style.css' ),
458 + array( 'wp-components' ),
459 + $version
460 + );
461 + $styles->add_data( 'wp-patterns', 'rtl', 'replace' );
462 +
463 + gutenberg_override_style(
464 + $styles,
471 465 'wp-reusable-blocks',
472 466 gutenberg_url( 'build/reusable-blocks/style.css' ),
473 467 array( 'wp-components' ),
474 468 $version
475 469 );
476 - $styles->add_data( 'wp-reusable-block', 'rtl', 'replace' );
470 + $styles->add_data( 'wp-reusable-blocks', 'rtl', 'replace' );
477 471
478 472 gutenberg_override_style(
479 473 $styles,
480 474 'wp-widgets',
@@ -481,197 +475,199 @@
481 475 gutenberg_url( 'build/widgets/style.css' ),
482 476 array( 'wp-components' )
483 477 );
484 478 $styles->add_data( 'wp-widgets', 'rtl', 'replace' );
479 +
480 + gutenberg_override_style(
481 + $styles,
482 + 'wp-preferences',
483 + gutenberg_url( 'build/preferences/style.css' ),
484 + array( 'wp-components' ),
485 + $version
486 + );
487 + $styles->add_data( 'wp-preferences', 'rtl', 'replace' );
485 488 }
486 489 add_action( 'wp_default_styles', 'gutenberg_register_packages_styles' );
487 490
488 491 /**
489 - * Retrieves a unique and reasonably short and human-friendly filename for a
490 - * vendor script based on a URL and the script handle.
492 + * Fetches, processes and compiles stored core styles, then combines and renders them to the page.
493 + * Styles are stored via the Style Engine API.
491 494 *
492 - * @param string $handle The name of the script.
493 - * @param string $src Full URL of the external script.
495 + * This hook also exists, and should be backported to Core in future versions.
496 + * However, it is envisaged that Gutenberg will continue to use the Style Engine's `gutenberg_*` functions and `_Gutenberg` classes to aid continuous development.
494 497 *
495 - * @return string Script filename suitable for local caching.
498 + * @since 6.1
496 499 *
497 - * @since 0.1.0
498 - */
499 -function gutenberg_vendor_script_filename( $handle, $src ) {
500 - $filename = basename( $src );
501 - $match = preg_match(
502 - '/^'
503 - . '(?P<ignore>.*?)'
504 - . '(?P<suffix>\.min)?'
505 - . '(?P<extension>\.js)'
506 - . '(?P<extra>.*)'
507 - . '$/',
508 - $filename,
509 - $filename_pieces
510 - );
511 -
512 - $prefix = $handle;
513 - $suffix = $match ? $filename_pieces['suffix'] : '';
514 - $hash = substr( md5( $src ), 0, 8 );
515 -
516 - return "${prefix}${suffix}.${hash}.js";
517 -}
518 -
519 -/**
520 - * Registers a vendor script from a URL, preferring a locally cached version if
521 - * possible, or downloading it if the cached version is unavailable or
522 - * outdated.
500 + * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/
523 501 *
524 - * @param WP_Scripts $scripts WP_Scripts instance.
525 - * @param string $handle Name of the script.
526 - * @param string $src Full URL of the external script.
527 - * @param array $deps Optional. An array of registered script handles this
528 - * script depends on.
529 - * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL
530 - * as a query string for cache busting purposes. If version is set to false, a version
531 - * number is automatically added equal to current installed WordPress version.
532 - * If set to null, no version is added.
533 - * @param bool $in_footer Optional. Whether to enqueue the script before </body> instead of in the <head>.
534 - * Default 'false'.
502 + * @param array $options {
503 + * Optional. An array of options to pass to gutenberg_style_engine_get_stylesheet_from_context(). Default empty array.
535 504 *
536 - * @since 0.1.0
505 + * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. Default is `false`.
506 + * @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.
507 + * }
508 + *
509 + * @return void
537 510 */
538 -function gutenberg_register_vendor_script( $scripts, $handle, $src, $deps = array(), $ver = null, $in_footer = false ) {
539 - if ( defined( 'GUTENBERG_LOAD_VENDOR_SCRIPTS' ) && ! GUTENBERG_LOAD_VENDOR_SCRIPTS ) {
511 +function gutenberg_enqueue_stored_styles( $options = array() ) {
512 + $is_block_theme = wp_is_block_theme();
513 + $is_classic_theme = ! $is_block_theme;
514 +
515 + /*
516 + * For block themes, print stored styles in the header.
517 + * For classic themes, in the footer.
518 + */
519 + if (
520 + ( $is_block_theme && doing_action( 'wp_footer' ) ) ||
521 + ( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) )
522 + ) {
540 523 return;
541 524 }
542 525
543 - $filename = gutenberg_vendor_script_filename( $handle, $src );
526 + $core_styles_keys = array( 'block-supports' );
527 + $compiled_core_stylesheet = '';
528 + $style_tag_id = 'core';
529 + foreach ( $core_styles_keys as $style_key ) {
530 + // Adds comment if code is prettified to identify core styles sections in debugging.
531 + $should_prettify = isset( $options['prettify'] ) ? true === $options['prettify'] : SCRIPT_DEBUG;
532 + if ( $should_prettify ) {
533 + $compiled_core_stylesheet .= "/**\n * Core styles: $style_key\n */\n";
534 + }
535 + // Chains core store ids to signify what the styles contain.
536 + $style_tag_id .= '-' . $style_key;
537 + $compiled_core_stylesheet .= gutenberg_style_engine_get_stylesheet_from_context( $style_key, $options );
538 + }
544 539
545 - if ( defined( 'GUTENBERG_LIST_VENDOR_ASSETS' ) && GUTENBERG_LIST_VENDOR_ASSETS ) {
546 - echo "$src|$filename\n";
547 - return;
540 + // Combines Core styles.
541 + if ( ! empty( $compiled_core_stylesheet ) ) {
542 + wp_register_style( $style_tag_id, false, array(), true, true );
543 + wp_add_inline_style( $style_tag_id, $compiled_core_stylesheet );
544 + wp_enqueue_style( $style_tag_id );
548 545 }
549 546
550 - $full_path = gutenberg_dir_path() . 'vendor/' . $filename;
547 + // If there are any other stores registered by themes etc., print them out.
548 + $additional_stores = WP_Style_Engine_CSS_Rules_Store_Gutenberg::get_stores();
551 549
552 - $needs_fetch = (
553 - defined( 'GUTENBERG_DEVELOPMENT_MODE' ) && GUTENBERG_DEVELOPMENT_MODE && (
554 - ! file_exists( $full_path ) ||
555 - time() - filemtime( $full_path ) >= DAY_IN_SECONDS
556 - )
557 - );
550 + /*
551 + * Since the corresponding action hook in Core is removed below,
552 + * this function should still honour any styles stored using the Core Style Engine store.
553 + */
554 + if ( class_exists( 'WP_Style_Engine_CSS_Rules_Store' ) ) {
555 + $additional_stores = array_merge( $additional_stores, WP_Style_Engine_CSS_Rules_Store::get_stores() );
556 + }
558 557
559 - if ( $needs_fetch ) {
560 - // Determine whether we can write to this file. If not, don't waste
561 - // time doing a network request.
562 - // @codingStandardsIgnoreStart
563 -
564 - $is_writable = is_writable( $full_path );
565 - if ( $is_writable ) {
566 - $f = @fopen( $full_path, 'a' );
567 - if ( ! $f ) {
568 - $is_writable = false;
569 - } else {
570 - fclose( $f );
571 - }
558 + foreach ( array_keys( $additional_stores ) as $store_name ) {
559 + if ( in_array( $store_name, $core_styles_keys, true ) ) {
560 + continue;
572 561 }
573 -
574 - // @codingStandardsIgnoreEnd
575 - if ( ! $is_writable ) {
576 - // Failed to open the file for writing, probably due to server
577 - // permissions. Enqueue the script directly from the URL instead.
578 - gutenberg_override_script( $scripts, $handle, $src, $deps, $ver, $in_footer );
579 - return;
562 + $styles = gutenberg_style_engine_get_stylesheet_from_context( $store_name, $options );
563 + if ( ! empty( $styles ) ) {
564 + $key = "wp-style-engine-$store_name";
565 + wp_register_style( $key, false, array(), true, true );
566 + wp_add_inline_style( $key, $styles );
567 + wp_enqueue_style( $key );
580 568 }
581 -
582 - $response = wp_remote_get( $src );
583 - if ( wp_remote_retrieve_response_code( $response ) === 200 ) {
584 - $f = fopen( $full_path, 'w' );
585 - fwrite( $f, wp_remote_retrieve_body( $response ) );
586 - fclose( $f );
587 - } elseif ( ! filesize( $full_path ) ) {
588 - // The request failed. If the file is already cached, continue to
589 - // use this file. If not, then unlink the 0 byte file, and enqueue
590 - // the script directly from the URL.
591 - gutenberg_override_script( $scripts, $handle, $src, $deps, $ver, $in_footer );
592 - unlink( $full_path );
593 - return;
594 - }
595 569 }
596 - gutenberg_override_script(
597 - $scripts,
598 - $handle,
599 - gutenberg_url( 'vendor/' . $filename ),
600 - $deps,
601 - $ver,
602 - $in_footer
603 - );
604 570 }
605 571
606 572 /**
607 - * Sets the editor styles to be consumed by JS.
573 + * Registers vendor JavaScript files to be used as dependencies of the editor
574 + * and plugins.
575 + *
576 + * This function is called from a script during the plugin build process, so it
577 + * should not call any WordPress PHP functions.
578 + *
579 + * @since 13.0
580 + *
581 + * @param WP_Scripts $scripts WP_Scripts instance.
608 582 */
609 -function gutenberg_resolve_assets() {
610 - global $pagenow;
583 +function gutenberg_register_vendor_scripts( $scripts ) {
584 + $extension = SCRIPT_DEBUG ? '.js' : '.min.js';
611 585
612 - $script_handles = array();
613 - $style_handles = array(
614 - 'wp-block-editor',
615 - 'wp-block-library',
616 - 'wp-block-library-theme',
617 - 'wp-edit-blocks',
586 + gutenberg_override_script(
587 + $scripts,
588 + 'react',
589 + gutenberg_url( 'build/vendors/react' . $extension ),
590 + // See https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#externalising-react.
591 + SCRIPT_DEBUG ? array( 'wp-react-refresh-entry', 'wp-polyfill' ) : array( 'wp-polyfill' ),
592 + '18'
618 593 );
594 + gutenberg_override_script(
595 + $scripts,
596 + 'react-dom',
597 + gutenberg_url( 'build/vendors/react-dom' . $extension ),
598 + array( 'react' ),
599 + '18'
600 + );
619 601
620 - if ( 'widgets.php' === $pagenow || 'customize.php' === $pagenow ) {
621 - $style_handles[] = 'wp-widgets';
622 - $style_handles[] = 'wp-edit-widgets';
623 - }
602 + gutenberg_override_script(
603 + $scripts,
604 + 'react-jsx-runtime',
605 + gutenberg_url( 'build/vendors/react-jsx-runtime' . $extension ),
606 + array( 'react' ),
607 + '18'
608 + );
609 +}
610 +add_action( 'wp_default_scripts', 'gutenberg_register_vendor_scripts' );
624 611
625 - $block_registry = WP_Block_Type_Registry::get_instance();
612 +/**
613 + * Registers or re-registers Gutenberg Script Modules.
614 + *
615 + * Script modules that are registered by Core will be re-registered by Gutenberg.
616 + *
617 + * @since 19.3.0
618 + */
619 +function gutenberg_default_script_modules() {
620 + /*
621 + * Expects multidimensional array like:
622 + *
623 + * 'interactivity/index.min.js' => array('dependencies' => array(…), 'version' => '…'),
624 + * 'interactivity/debug.min.js' => array('dependencies' => array(…), 'version' => '…'),
625 + * 'interactivity-router/index.min.js' => …
626 + */
627 + $assets = include gutenberg_dir_path() . '/build-module/assets.php';
626 628
627 - foreach ( $block_registry->get_all_registered() as $block_type ) {
628 - if ( ! empty( $block_type->style ) ) {
629 - $style_handles[] = $block_type->style;
629 + foreach ( $assets as $file_name => $script_module_data ) {
630 + /*
631 + * Build the WordPress Script Module ID from the file name.
632 + * Prepend `@wordpress/` and remove extensions and `/index` if present:
633 + * - interactivity/index.min.js => @wordpress/interactivity
634 + * - interactivity/debug.min.js => @wordpress/interactivity/debug
635 + * - block-library/query/view.js => @wordpress/block-library/query/view
636 + */
637 + $script_module_id = '@wordpress/' . preg_replace( '~(?:/index)?\.min\.js$~D', '', $file_name, 1 );
638 + switch ( $script_module_id ) {
639 + /*
640 + * Interactivity exposes two entrypoints, "/index" and "/debug".
641 + * "/debug" should replace "/index" in development.
642 + */
643 + case '@wordpress/interactivity/debug':
644 + if ( ! SCRIPT_DEBUG ) {
645 + continue 2;
646 + }
647 + $script_module_id = '@wordpress/interactivity';
648 + break;
649 + case '@wordpress/interactivity':
650 + if ( SCRIPT_DEBUG ) {
651 + continue 2;
652 + }
653 + break;
630 654 }
631 655
632 - if ( ! empty( $block_type->editor_style ) ) {
633 - $style_handles[] = $block_type->editor_style;
634 - }
635 -
636 - if ( ! empty( $block_type->script ) ) {
637 - $script_handles[] = $block_type->script;
638 - }
656 + $path = gutenberg_url( "build-module/{$file_name}" );
657 + wp_register_script_module( $script_module_id, $path, $script_module_data['dependencies'], $script_module_data['version'] );
639 658 }
659 +}
660 +remove_action( 'wp_default_scripts', 'wp_default_script_modules' );
661 +add_action( 'wp_default_scripts', 'gutenberg_default_script_modules' );
640 662
641 - $style_handles = array_unique( $style_handles );
642 - $done = wp_styles()->done;
663 +/*
664 + * Always remove the Core action hook while gutenberg_enqueue_stored_styles() exists to avoid styles being printed twice.
665 + * This is also because gutenberg_enqueue_stored_styles uses the Style Engine's `gutenberg_*` functions and `_Gutenberg` classes,
666 + * which are in continuous development and generally ahead of Core.
667 + */
668 +remove_action( 'wp_enqueue_scripts', 'wp_enqueue_stored_styles' );
669 +remove_action( 'wp_footer', 'wp_enqueue_stored_styles', 1 );
643 670
644 - ob_start();
645 -
646 - // We do not need reset styles for the iframed editor.
647 - wp_styles()->done = array( 'wp-reset-editor-styles' );
648 - wp_styles()->do_items( $style_handles );
649 - wp_styles()->done = $done;
650 -
651 - $styles = ob_get_clean();
652 -
653 - $script_handles = array_unique( $script_handles );
654 - $done = wp_scripts()->done;
655 -
656 - ob_start();
657 -
658 - wp_scripts()->done = array();
659 - wp_scripts()->do_items( $script_handles );
660 - wp_scripts()->done = $done;
661 -
662 - $scripts = ob_get_clean();
663 -
664 - return array(
665 - 'styles' => $styles,
666 - 'scripts' => $scripts,
667 - );
668 -}
669 -
670 -add_filter(
671 - 'block_editor_settings_all',
672 - function( $settings ) {
673 - // In the future we can allow WP Dependency handles to be passed.
674 - $settings['__unstableResolvedAssets'] = gutenberg_resolve_assets();
675 - return $settings;
676 - }
677 -);
671 +// Enqueue stored styles.
672 +add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_stored_styles' );
673 +add_action( 'wp_footer', 'gutenberg_enqueue_stored_styles', 1 );