| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * WordPress scripts and styles default loader. 4 * 5 * Several constants are used to manage the loading, concatenating and compression of scripts and CSS: 6 * define('SCRIPT_DEBUG', true); loads the development (non-minified) versions of all scripts and CSS, and disables compression and concatenation, 7 * define('CONCATENATE_SCRIPTS', false); disables compression and concatenation of scripts and CSS, 8 * define('COMPRESS_SCRIPTS', false); disables compression of scripts, 9 * define('COMPRESS_CSS', false); disables compression of CSS, 10 * define('ENFORCE_GZIP', true); forces gzip for compression (default is deflate). 11 * 12 * The globals $concatenate_scripts, $compress_scripts and $compress_css can be set by plugins 13 * to temporarily override the above settings. Also a compression test is run once and the result is saved 14 * as option 'can_compress_scripts' (0/1). The test will run again if that option is deleted. 15 * 16 * @package WordPress 17 */ 18 19 /** WordPress Dependency Class */ 20 require ABSPATH . WPINC . '/class-wp-dependency.php'; 21 22 /** WordPress Dependencies Class */ 23 require ABSPATH . WPINC . '/class-wp-dependencies.php'; 24 25 /** WordPress Scripts Class */ 26 require ABSPATH . WPINC . '/class-wp-scripts.php'; 27 28 /** WordPress Scripts Functions */ 29 require ABSPATH . WPINC . '/functions.wp-scripts.php'; 30 31 /** WordPress Styles Class */ 32 require ABSPATH . WPINC . '/class-wp-styles.php'; 33 34 /** WordPress Styles Functions */ 35 require ABSPATH . WPINC . '/functions.wp-styles.php'; 36 37 /** 38 * Registers TinyMCE scripts. 39 * 40 * @since 5.0.0 41 * 42 * @global string $tinymce_version 43 * @global bool $concatenate_scripts 44 * @global bool $compress_scripts 45 * 46 * @param WP_Scripts $scripts WP_Scripts object. 47 * @param bool $force_uncompressed Whether to forcibly prevent gzip compression. Default false. 48 */ 49 function wp_register_tinymce_scripts( $scripts, $force_uncompressed = false ) { 50 global $tinymce_version, $concatenate_scripts, $compress_scripts; 51 52 $suffix = wp_scripts_get_suffix(); 53 $dev_suffix = wp_scripts_get_suffix( 'dev' ); 54 55 script_concat_settings(); 56 57 $compressed = $compress_scripts && $concatenate_scripts && ! $force_uncompressed; 58 59 /* 60 * Load tinymce.js when running from /src, otherwise load wp-tinymce.js (in production) 61 * or tinymce.min.js (when SCRIPT_DEBUG is true). 62 */ 63 if ( $compressed ) { 64 $scripts->add( 'wp-tinymce', includes_url( 'js/tinymce/' ) . 'wp-tinymce.js', array(), $tinymce_version ); 65 } else { 66 $scripts->add( 'wp-tinymce-root', includes_url( 'js/tinymce/' ) . "tinymce$dev_suffix.js", array(), $tinymce_version ); 67 $scripts->add( 'wp-tinymce', includes_url( 'js/tinymce/' ) . "plugins/compat3x/plugin$dev_suffix.js", array( 'wp-tinymce-root' ), $tinymce_version ); 68 } 69 70 $scripts->add( 'wp-tinymce-lists', includes_url( "js/tinymce/plugins/lists/plugin$suffix.js" ), array( 'wp-tinymce' ), $tinymce_version ); 71 } 72 73 /** 74 * Registers all the WordPress vendor scripts that are in the standardized 75 * `js/dist/vendor/` location. 76 * 77 * For the order of `$scripts->add` see `wp_default_scripts`. 78 * 79 * @since 5.0.0 80 * 81 * @global WP_Locale $wp_locale WordPress date and time locale object. 82 * 83 * @param WP_Scripts $scripts WP_Scripts object. 84 */ 85 function wp_default_packages_vendor( $scripts ) { 86 global $wp_locale; 87 88 $suffix = wp_scripts_get_suffix(); 89 90 $vendor_scripts = array( 91 'react' => array(), 92 'react-dom' => array( 'react' ), 93 'react-jsx-runtime' => array( 'react' ), 94 'regenerator-runtime' => array(), 95 'moment' => array(), 96 'lodash' => array(), 97 'wp-polyfill-fetch' => array(), 98 'wp-polyfill-formdata' => array(), 99 'wp-polyfill-node-contains' => array(), 100 'wp-polyfill-url' => array(), 101 'wp-polyfill-dom-rect' => array(), 102 'wp-polyfill-element-closest' => array(), 103 'wp-polyfill-object-fit' => array(), 104 'wp-polyfill-inert' => array(), 105 'wp-polyfill' => array(), 106 ); 107 108 $vendor_scripts_versions = array( 109 'react' => '18.3.1.1', // Final .1 due to switch to UMD build, can be removed in the next update. 110 'react-dom' => '18.3.1.1', // Final .1 due to switch to UMD build, can be removed in the next update. 111 'react-jsx-runtime' => '18.3.1', 112 'regenerator-runtime' => '0.14.1', 113 'moment' => '2.30.1', 114 'lodash' => '4.17.21', 115 'wp-polyfill-fetch' => '3.6.20', 116 'wp-polyfill-formdata' => '4.0.10', 117 'wp-polyfill-node-contains' => '4.8.0', 118 'wp-polyfill-url' => '3.6.4', 119 'wp-polyfill-dom-rect' => '4.8.0', 120 'wp-polyfill-element-closest' => '3.0.2', 121 'wp-polyfill-object-fit' => '2.3.5', 122 'wp-polyfill-inert' => '3.1.3', 123 'wp-polyfill' => '3.15.0', 124 ); 125 126 foreach ( $vendor_scripts as $handle => $dependencies ) { 127 $scripts->add( 128 $handle, 129 "/wp-includes/js/dist/vendor/$handle$suffix.js", 130 $dependencies, 131 $vendor_scripts_versions[ $handle ], 132 1 133 ); 134 } 135 136 did_action( 'init' ) && $scripts->add_inline_script( 'lodash', 'window.lodash = _.noConflict();' ); 137 138 did_action( 'init' ) && $scripts->add_inline_script( 139 'moment', 140 sprintf( 141 "moment.updateLocale( '%s', %s );", 142 esc_js( get_user_locale() ), 143 wp_json_encode( 144 array( 145 'months' => array_values( $wp_locale->month ), 146 'monthsShort' => array_values( $wp_locale->month_abbrev ), 147 'weekdays' => array_values( $wp_locale->weekday ), 148 'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ), 149 'week' => array( 150 'dow' => (int) get_option( 'start_of_week', 0 ), 151 ), 152 'longDateFormat' => array( 153 'LT' => get_option( 'time_format', __( 'g:i a' ) ), 154 'LTS' => null, 155 'L' => null, 156 'LL' => get_option( 'date_format', __( 'F j, Y' ) ), 157 'LLL' => __( 'F j, Y g:i a' ), 158 'LLLL' => null, 159 ), 160 ), 161 JSON_HEX_TAG | JSON_UNESCAPED_SLASHES 162 ) 163 ), 164 'after' 165 ); 166 } 167 168 /** 169 * Returns contents of an inline script used in appending polyfill scripts for 170 * browsers which fail the provided tests. The provided array is a mapping from 171 * a condition to verify feature support to its polyfill script handle. 172 * 173 * @since 5.0.0 174 * 175 * @param WP_Scripts $scripts WP_Scripts object. 176 * @param string[] $tests Features to detect. 177 * @return string Conditional polyfill inline script. 178 */ 179 function wp_get_script_polyfill( $scripts, $tests ) { 180 $polyfill = ''; 181 foreach ( $tests as $test => $handle ) { 182 if ( ! array_key_exists( $handle, $scripts->registered ) ) { 183 continue; 184 } 185 186 $src = $scripts->registered[ $handle ]->src; 187 $ver = $scripts->registered[ $handle ]->ver; 188 189 if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $scripts->content_url && str_starts_with( $src, $scripts->content_url ) ) ) { 190 $src = $scripts->base_url . $src; 191 } 192 193 if ( ! empty( $ver ) ) { 194 $src = add_query_arg( 'ver', $ver, $src ); 195 } 196 197 /** This filter is documented in wp-includes/class-wp-scripts.php */ 198 $src = esc_url( apply_filters( 'script_loader_src', $src, $handle ) ); 199 200 if ( ! $src ) { 201 continue; 202 } 203 204 $polyfill .= ( 205 // Test presence of feature... 206 '( ' . $test . ' ) || ' . 207 /* 208 * ...appending polyfill on any failures. Cautious viewers may balk 209 * at the `document.write`. Its caveat of synchronous mid-stream 210 * blocking write is exactly the behavior we need though. 211 */ 212 'document.write( \'<script src="' . 213 $src . 214 '"></scr\' + \'ipt>\' );' 215 ); 216 } 217 218 return $polyfill; 219 } 220 221 /** 222 * Registers all the WordPress packages scripts that are in the standardized 223 * `js/dist/` location. 224 * 225 * For the order of `$scripts->add` see `wp_default_scripts`. 226 * 227 * @since 5.0.0 228 * 229 * @param WP_Scripts $scripts WP_Scripts object. 230 */ 231 function wp_default_packages_scripts( $scripts ) { 232 $suffix = defined( 'WP_RUN_CORE_TESTS' ) ? '.min' : wp_scripts_get_suffix(); 233 /* 234 * Expects multidimensional array like: 235 * 236 * 'a11y.js' => array('dependencies' => array(...), 'version' => '...'), 237 * 'annotations.js' => array('dependencies' => array(...), 'version' => '...'), 238 * 'api-fetch.js' => array(... 239 */ 240 $assets = include ABSPATH . WPINC . "/assets/script-loader-packages{$suffix}.php"; 241 242 foreach ( $assets as $file_name => $package_data ) { 243 $basename = str_replace( $suffix . '.js', '', basename( $file_name ) ); 244 $handle = 'wp-' . $basename; 245 $path = "/wp-includes/js/dist/{$basename}{$suffix}.js"; 246 247 if ( ! empty( $package_data['dependencies'] ) ) { 248 $dependencies = $package_data['dependencies']; 249 } else { 250 $dependencies = array(); 251 } 252 253 // Add dependencies that cannot be detected and generated by build tools. 254 switch ( $handle ) { 255 case 'wp-block-library': 256 array_push( $dependencies, 'editor' ); 257 break; 258 case 'wp-edit-post': 259 array_push( $dependencies, 'media-models', 'media-views', 'postbox', 'wp-dom-ready' ); 260 break; 261 case 'wp-preferences': 262 array_push( $dependencies, 'wp-preferences-persistence' ); 263 break; 264 } 265 266 $scripts->add( $handle, $path, $dependencies, $package_data['version'], 1 ); 267 268 if ( in_array( 'wp-i18n', $dependencies, true ) ) { 269 $scripts->set_translations( $handle ); 270 } 271 272 /* 273 * Manually set the text direction localization after wp-i18n is printed. 274 * This ensures that wp.i18n.isRTL() returns true in RTL languages. 275 * We cannot use $scripts->set_translations( 'wp-i18n' ) to do this 276 * because WordPress prints a script's translations *before* the script, 277 * which means, in the case of wp-i18n, that wp.i18n.setLocaleData() 278 * is called before wp.i18n is defined. 279 */ 280 if ( 'wp-i18n' === $handle ) { 281 $ltr = _x( 'ltr', 'text direction' ); 282 $script = sprintf( "wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ '%s' ] } );", $ltr ); 283 $scripts->add_inline_script( $handle, $script, 'after' ); 284 } 285 } 286 } 287 288 /** 289 * Adds inline scripts required for the WordPress JavaScript packages. 290 * 291 * @since 5.0.0 292 * @since 6.4.0 Added relative time strings for the `wp-date` inline script output. 293 * 294 * @global WP_Locale $wp_locale WordPress date and time locale object. 295 * @global wpdb $wpdb WordPress database abstraction object. 296 * 297 * @param WP_Scripts $scripts WP_Scripts object. 298 */ 299 function wp_default_packages_inline_scripts( $scripts ) { 300 global $wp_locale, $wpdb; 301 302 if ( isset( $scripts->registered['wp-api-fetch'] ) ) { 303 $scripts->registered['wp-api-fetch']->deps[] = 'wp-hooks'; 304 } 305 $scripts->add_inline_script( 306 'wp-api-fetch', 307 sprintf( 308 'wp.apiFetch.use( wp.apiFetch.createRootURLMiddleware( "%s" ) );', 309 sanitize_url( get_rest_url() ) 310 ), 311 'after' 312 ); 313 $scripts->add_inline_script( 314 'wp-api-fetch', 315 implode( 316 "\n", 317 array( 318 sprintf( 319 'wp.apiFetch.nonceMiddleware = wp.apiFetch.createNonceMiddleware( "%s" );', 320 wp_installing() ? '' : wp_create_nonce( 'wp_rest' ) 321 ), 322 'wp.apiFetch.use( wp.apiFetch.nonceMiddleware );', 323 'wp.apiFetch.use( wp.apiFetch.mediaUploadMiddleware );', 324 sprintf( 325 'wp.apiFetch.nonceEndpoint = "%s";', 326 admin_url( 'admin-ajax.php?action=rest-nonce' ) 327 ), 328 ) 329 ), 330 'after' 331 ); 332 333 $meta_key = $wpdb->get_blog_prefix() . 'persisted_preferences'; 334 $user_id = get_current_user_id(); 335 $preload_data = get_user_meta( $user_id, $meta_key, true ); 336 $scripts->add_inline_script( 337 'wp-preferences', 338 sprintf( 339 '( function() { 340 var serverData = %s; 341 var userId = "%d"; 342 var persistenceLayer = wp.preferencesPersistence.__unstableCreatePersistenceLayer( serverData, userId ); 343 var preferencesStore = wp.preferences.store; 344 wp.data.dispatch( preferencesStore ).setPersistenceLayer( persistenceLayer ); 345 } ) ();', 346 wp_json_encode( $preload_data, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), 347 $user_id 348 ) 349 ); 350 351 // Backwards compatibility - configure the old wp-data persistence system. 352 $scripts->add_inline_script( 353 'wp-data', 354 implode( 355 "\n", 356 array( 357 '( function() {', 358 ' var userId = ' . get_current_user_id() . ';', 359 ' var storageKey = "WP_DATA_USER_" + userId;', 360 ' wp.data', 361 ' .use( wp.data.plugins.persistence, { storageKey: storageKey } );', 362 '} )();', 363 ) 364 ) 365 ); 366 367 // Calculate the timezone abbr (EDT, PST) if possible. 368 $timezone_string = get_option( 'timezone_string', 'UTC' ); 369 $timezone_abbr = ''; 370 371 if ( ! empty( $timezone_string ) ) { 372 $timezone_date = new DateTime( 'now', new DateTimeZone( $timezone_string ) ); 373 $timezone_abbr = $timezone_date->format( 'T' ); 374 } 375 376 $gmt_offset = get_option( 'gmt_offset', 0 ); 377 378 $scripts->add_inline_script( 379 'wp-date', 380 sprintf( 381 'wp.date.setSettings( %s );', 382 wp_json_encode( 383 array( 384 'l10n' => array( 385 'locale' => get_user_locale(), 386 'months' => array_values( $wp_locale->month ), 387 'monthsShort' => array_values( $wp_locale->month_abbrev ), 388 'weekdays' => array_values( $wp_locale->weekday ), 389 'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ), 390 'meridiem' => (object) $wp_locale->meridiem, 391 'relative' => array( 392 /* translators: %s: Duration. */ 393 'future' => __( '%s from now' ), 394 /* translators: %s: Duration. */ 395 'past' => __( '%s ago' ), 396 /* translators: One second from or to a particular datetime, e.g., "a second ago" or "a second from now". */ 397 's' => __( 'a second' ), 398 /* translators: %d: Duration in seconds from or to a particular datetime, e.g., "4 seconds ago" or "4 seconds from now". */ 399 'ss' => __( '%d seconds' ), 400 /* translators: One minute from or to a particular datetime, e.g., "a minute ago" or "a minute from now". */ 401 'm' => __( 'a minute' ), 402 /* translators: %d: Duration in minutes from or to a particular datetime, e.g., "4 minutes ago" or "4 minutes from now". */ 403 'mm' => __( '%d minutes' ), 404 /* translators: One hour from or to a particular datetime, e.g., "an hour ago" or "an hour from now". */ 405 'h' => __( 'an hour' ), 406 /* translators: %d: Duration in hours from or to a particular datetime, e.g., "4 hours ago" or "4 hours from now". */ 407 'hh' => __( '%d hours' ), 408 /* translators: One day from or to a particular datetime, e.g., "a day ago" or "a day from now". */ 409 'd' => __( 'a day' ), 410 /* translators: %d: Duration in days from or to a particular datetime, e.g., "4 days ago" or "4 days from now". */ 411 'dd' => __( '%d days' ), 412 /* translators: One month from or to a particular datetime, e.g., "a month ago" or "a month from now". */ 413 'M' => __( 'a month' ), 414 /* translators: %d: Duration in months from or to a particular datetime, e.g., "4 months ago" or "4 months from now". */ 415 'MM' => __( '%d months' ), 416 /* translators: One year from or to a particular datetime, e.g., "a year ago" or "a year from now". */ 417 'y' => __( 'a year' ), 418 /* translators: %d: Duration in years from or to a particular datetime, e.g., "4 years ago" or "4 years from now". */ 419 'yy' => __( '%d years' ), 420 ), 421 'startOfWeek' => (int) get_option( 'start_of_week', 0 ), 422 ), 423 'formats' => array( 424 /* translators: Time format, see https://www.php.net/manual/datetime.format.php */ 425 'time' => get_option( 'time_format', __( 'g:i a' ) ), 426 /* translators: Date format, see https://www.php.net/manual/datetime.format.php */ 427 'date' => get_option( 'date_format', __( 'F j, Y' ) ), 428 /* translators: Date/Time format, see https://www.php.net/manual/datetime.format.php */ 429 'datetime' => __( 'F j, Y g:i a' ), 430 /* translators: Abbreviated date/time format, see https://www.php.net/manual/datetime.format.php */ 431 'datetimeAbbreviated' => __( 'M j, Y g:i a' ), 432 ), 433 'timezone' => array( 434 'offset' => (float) $gmt_offset, 435 'offsetFormatted' => str_replace( array( '.25', '.5', '.75' ), array( ':15', ':30', ':45' ), (string) $gmt_offset ), 436 'string' => $timezone_string, 437 'abbr' => $timezone_abbr, 438 ), 439 ), 440 JSON_HEX_TAG | JSON_UNESCAPED_SLASHES 441 ) 442 ), 443 'after' 444 ); 445 446 // Loading the old editor and its config to ensure the classic block works as expected. 447 $scripts->add_inline_script( 448 'editor', 449 'window.wp.oldEditor = window.wp.editor;', 450 'after' 451 ); 452 453 /* 454 * wp-editor module is exposed as window.wp.editor. 455 * Problem: there is quite some code expecting window.wp.oldEditor object available under window.wp.editor. 456 * Solution: fuse the two objects together to maintain backward compatibility. 457 * For more context, see https://github.com/WordPress/gutenberg/issues/33203. 458 */ 459 $scripts->add_inline_script( 460 'wp-editor', 461 'Object.assign( window.wp.editor, window.wp.oldEditor );', 462 'after' 463 ); 464 } 465 466 /** 467 * Adds inline scripts required for the TinyMCE in the block editor. 468 * 469 * These TinyMCE init settings are used to extend and override the default settings 470 * from `_WP_Editors::default_settings()` for the Classic block. 471 * 472 * @since 5.0.0 473 * 474 * @global WP_Scripts $wp_scripts 475 */ 476 function wp_tinymce_inline_scripts() { 477 global $wp_scripts; 478 479 /** This filter is documented in wp-includes/class-wp-editor.php */ 480 $editor_settings = apply_filters( 'wp_editor_settings', array( 'tinymce' => true ), 'classic-block' ); 481 482 $tinymce_plugins = array( 483 'charmap', 484 'colorpicker', 485 'hr', 486 'lists', 487 'media', 488 'paste', 489 'tabfocus', 490 'textcolor', 491 'fullscreen', 492 'wordpress', 493 'wpautoresize', 494 'wpeditimage', 495 'wpemoji', 496 'wpgallery', 497 'wplink', 498 'wpdialogs', 499 'wptextpattern', 500 'wpview', 501 ); 502 503 /** This filter is documented in wp-includes/class-wp-editor.php */ 504 $tinymce_plugins = apply_filters( 'tiny_mce_plugins', $tinymce_plugins, 'classic-block' ); 505 $tinymce_plugins = array_unique( $tinymce_plugins ); 506 507 $disable_captions = false; 508 // Runs after `tiny_mce_plugins` but before `mce_buttons`. 509 /** This filter is documented in wp-admin/includes/media.php */ 510 if ( apply_filters( 'disable_captions', '' ) ) { 511 $disable_captions = true; 512 } 513 514 $toolbar1 = array( 515 'formatselect', 516 'bold', 517 'italic', 518 'bullist', 519 'numlist', 520 'blockquote', 521 'alignleft', 522 'aligncenter', 523 'alignright', 524 'link', 525 'unlink', 526 'wp_more', 527 'spellchecker', 528 'wp_add_media', 529 'wp_adv', 530 ); 531 532 /** This filter is documented in wp-includes/class-wp-editor.php */ 533 $toolbar1 = apply_filters( 'mce_buttons', $toolbar1, 'classic-block' ); 534 535 $toolbar2 = array( 536 'strikethrough', 537 'hr', 538 'forecolor', 539 'pastetext', 540 'removeformat', 541 'charmap', 542 'outdent', 543 'indent', 544 'undo', 545 'redo', 546 'wp_help', 547 ); 548 549 /** This filter is documented in wp-includes/class-wp-editor.php */ 550 $toolbar2 = apply_filters( 'mce_buttons_2', $toolbar2, 'classic-block' ); 551 /** This filter is documented in wp-includes/class-wp-editor.php */ 552 $toolbar3 = apply_filters( 'mce_buttons_3', array(), 'classic-block' ); 553 /** This filter is documented in wp-includes/class-wp-editor.php */ 554 $toolbar4 = apply_filters( 'mce_buttons_4', array(), 'classic-block' ); 555 /** This filter is documented in wp-includes/class-wp-editor.php */ 556 $external_plugins = apply_filters( 'mce_external_plugins', array(), 'classic-block' ); 557 558 $tinymce_settings = array( 559 'plugins' => implode( ',', $tinymce_plugins ), 560 'toolbar1' => implode( ',', $toolbar1 ), 561 'toolbar2' => implode( ',', $toolbar2 ), 562 'toolbar3' => implode( ',', $toolbar3 ), 563 'toolbar4' => implode( ',', $toolbar4 ), 564 'external_plugins' => wp_json_encode( $external_plugins ), 565 'classic_block_editor' => true, 566 ); 567 568 if ( $disable_captions ) { 569 $tinymce_settings['wpeditimage_disable_captions'] = true; 570 } 571 572 if ( ! empty( $editor_settings['tinymce'] ) && is_array( $editor_settings['tinymce'] ) ) { 573 $tinymce_settings = array_merge( $tinymce_settings, $editor_settings['tinymce'] ); 574 } 575 576 /** This filter is documented in wp-includes/class-wp-editor.php */ 577 $tinymce_settings = apply_filters( 'tiny_mce_before_init', $tinymce_settings, 'classic-block' ); 578 579 /* 580 * Do "by hand" translation from PHP array to js object. 581 * Prevents breakage in some custom settings. 582 */ 583 $init_obj = ''; 584 foreach ( $tinymce_settings as $key => $value ) { 585 if ( is_bool( $value ) ) { 586 $val = $value ? 'true' : 'false'; 587 $init_obj .= $key . ':' . $val . ','; 588 continue; 589 } elseif ( ! empty( $value ) && is_string( $value ) && ( 590 ( '{' === $value[0] && '}' === $value[ strlen( $value ) - 1 ] ) || 591 ( '[' === $value[0] && ']' === $value[ strlen( $value ) - 1 ] ) || 592 preg_match( '/^\(?function ?\(/', $value ) ) ) { 593 $init_obj .= $key . ':' . $value . ','; 594 continue; 595 } 596 $init_obj .= $key . ':"' . $value . '",'; 597 } 598 599 $init_obj = '{' . trim( $init_obj, ' ,' ) . '}'; 600 601 $script = 'window.wpEditorL10n = { 602 tinymce: { 603 baseURL: ' . wp_json_encode( includes_url( 'js/tinymce' ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ', 604 suffix: ' . ( SCRIPT_DEBUG ? '""' : '".min"' ) . ', 605 settings: ' . $init_obj . ', 606 } 607 }'; 608 609 $wp_scripts->add_inline_script( 'wp-block-library', $script, 'before' ); 610 } 611 612 /** 613 * Registers all the WordPress packages scripts. 614 * 615 * @since 5.0.0 616 * 617 * @param WP_Scripts $scripts WP_Scripts object. 618 */ 619 function wp_default_packages( $scripts ) { 620 wp_default_packages_vendor( $scripts ); 621 wp_register_tinymce_scripts( $scripts ); 622 wp_default_packages_scripts( $scripts ); 623 624 if ( did_action( 'init' ) ) { 625 wp_default_packages_inline_scripts( $scripts ); 626 } 627 } 628 629 /** 630 * Returns the suffix that can be used for the scripts. 631 * 632 * There are two suffix types, the normal one and the dev suffix. 633 * 634 * @since 5.0.0 635 * 636 * @param string $type The type of suffix to retrieve. 637 * @return string The script suffix. 638 */ 639 function wp_scripts_get_suffix( $type = '' ) { 640 static $suffixes; 641 642 if ( null === $suffixes ) { 643 /* 644 * Include an unmodified $wp_version. 645 * 646 * Note: wp_get_wp_version() is not used here, as this file can be included 647 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case 648 * wp-includes/functions.php is not loaded. 649 */ 650 require ABSPATH . WPINC . '/version.php'; 651 652 /* 653 * Note: str_contains() is not used here, as this file can be included 654 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case 655 * the polyfills from wp-includes/compat.php are not loaded. 656 */ 657 $develop_src = false !== strpos( $wp_version, '-src' ); 658 659 if ( ! defined( 'SCRIPT_DEBUG' ) ) { 660 define( 'SCRIPT_DEBUG', $develop_src ); 661 } 662 $suffix = SCRIPT_DEBUG ? '' : '.min'; 663 $dev_suffix = $develop_src ? '' : '.min'; 664 665 $suffixes = array( 666 'suffix' => $suffix, 667 'dev_suffix' => $dev_suffix, 668 ); 669 } 670 671 if ( 'dev' === $type ) { 672 return $suffixes['dev_suffix']; 673 } 674 675 return $suffixes['suffix']; 676 } 677 678 /** 679 * Registers all WordPress scripts. 680 * 681 * Localizes some of them. 682 * args order: `$scripts->add( 'handle', 'url', 'dependencies', 'query-string', 1 );` 683 * when last arg === 1 queues the script for the footer 684 * 685 * @since 2.6.0 686 * 687 * @param WP_Scripts $scripts WP_Scripts object. 688 */ 689 function wp_default_scripts( $scripts ) { 690 $suffix = wp_scripts_get_suffix(); 691 $dev_suffix = wp_scripts_get_suffix( 'dev' ); 692 $guessurl = site_url(); 693 694 if ( ! $guessurl ) { 695 $guessed_url = true; 696 $guessurl = wp_guess_url(); 697 } 698 699 $scripts->base_url = $guessurl; 700 $scripts->content_url = defined( 'WP_CONTENT_URL' ) ? WP_CONTENT_URL : ''; 701 $scripts->default_version = get_bloginfo( 'version' ); 702 $scripts->default_dirs = array( '/wp-admin/js/', '/wp-includes/js/' ); 703 704 $scripts->add( 'utils', "/wp-includes/js/utils$suffix.js" ); 705 did_action( 'init' ) && $scripts->localize( 706 'utils', 707 'userSettings', 708 array( 709 'url' => (string) SITECOOKIEPATH, 710 'uid' => (string) get_current_user_id(), 711 'time' => (string) time(), 712 'secure' => (string) ( 'https' === parse_url( site_url(), PHP_URL_SCHEME ) ), 713 ) 714 ); 715 716 $scripts->add( 'common', "/wp-admin/js/common$suffix.js", array( 'jquery', 'hoverIntent', 'utils', 'wp-a11y' ), false, 1 ); 717 $scripts->set_translations( 'common' ); 718 719 $bulk_action_observer_ids = array( 720 'bulk_action' => 'action', 721 'changeit' => 'new_role', 722 ); 723 did_action( 'init' ) && $scripts->localize( 724 'common', 725 'bulkActionObserverIds', 726 /** 727 * Filters the array of field name attributes for bulk actions. 728 * 729 * @since 6.8.1 730 * 731 * @param array $bulk_action_observer_ids { 732 * An array of field name attributes for bulk actions. 733 * 734 * @type string $bulk_action The bulk action field name. Default 'action'. 735 * @type string $changeit The new role field name. Default 'new_role'. 736 * } 737 */ 738 apply_filters( 'bulk_action_observer_ids', $bulk_action_observer_ids ) 739 ); 740 741 $scripts->add( 'wp-sanitize', "/wp-includes/js/wp-sanitize$suffix.js", array(), false, 1 ); 742 743 $scripts->add( 'sack', "/wp-includes/js/tw-sack$suffix.js", array(), '1.6.1', 1 ); 744 745 $scripts->add( 'quicktags', "/wp-includes/js/quicktags$suffix.js", array(), false, 1 ); 746 did_action( 'init' ) && $scripts->localize( 747 'quicktags', 748 'quicktagsL10n', 749 array( 750 'closeAllOpenTags' => __( 'Close all open tags' ), 751 'closeTags' => __( 'close tags' ), 752 'enterURL' => __( 'Enter the URL' ), 753 'enterImageURL' => __( 'Enter the URL of the image' ), 754 'enterImageDescription' => __( 'Enter a description of the image' ), 755 'textdirection' => __( 'text direction' ), 756 'toggleTextdirection' => __( 'Toggle Editor Text Direction' ), 757 'dfw' => __( 'Distraction-free writing mode' ), 758 'strong' => __( 'Bold' ), 759 'strongClose' => __( 'Close bold tag' ), 760 'em' => __( 'Italic' ), 761 'emClose' => __( 'Close italic tag' ), 762 'link' => __( 'Insert link' ), 763 'blockquote' => __( 'Blockquote' ), 764 'blockquoteClose' => __( 'Close blockquote tag' ), 765 'del' => __( 'Deleted text (strikethrough)' ), 766 'delClose' => __( 'Close deleted text tag' ), 767 'ins' => __( 'Inserted text' ), 768 'insClose' => __( 'Close inserted text tag' ), 769 'image' => __( 'Insert image' ), 770 'ul' => __( 'Bulleted list' ), 771 'ulClose' => __( 'Close bulleted list tag' ), 772 'ol' => __( 'Numbered list' ), 773 'olClose' => __( 'Close numbered list tag' ), 774 'li' => __( 'List item' ), 775 'liClose' => __( 'Close list item tag' ), 776 'code' => __( 'Code' ), 777 'codeClose' => __( 'Close code tag' ), 778 'more' => __( 'Insert Read More tag' ), 779 ) 780 ); 781 782 $scripts->add( 'colorpicker', "/wp-includes/js/colorpicker$suffix.js", array( 'prototype' ), '3517m' ); 783 784 $scripts->add( 'editor', "/wp-admin/js/editor$suffix.js", array( 'utils', 'jquery' ), false, 1 ); 785 786 $scripts->add( 'clipboard', "/wp-includes/js/clipboard$suffix.js", array(), '2.0.11', 1 ); 787 788 $scripts->add( 'wp-ajax-response', "/wp-includes/js/wp-ajax-response$suffix.js", array( 'jquery', 'wp-a11y' ), false, 1 ); 789 did_action( 'init' ) && $scripts->localize( 790 'wp-ajax-response', 791 'wpAjax', 792 array( 793 'noPerm' => __( 'Sorry, you are not allowed to do that.' ), 794 'broken' => __( 'An error occurred while processing your request. Please try again later.' ), 795 ) 796 ); 797 798 $scripts->add( 'wp-api-request', "/wp-includes/js/api-request$suffix.js", array( 'jquery' ), false, 1 ); 799 // `wpApiSettings` is also used by `wp-api`, which depends on this script. 800 did_action( 'init' ) && $scripts->localize( 801 'wp-api-request', 802 'wpApiSettings', 803 array( 804 'root' => sanitize_url( get_rest_url() ), 805 'nonce' => wp_installing() ? '' : wp_create_nonce( 'wp_rest' ), 806 'versionString' => 'wp/v2/', 807 ) 808 ); 809 810 $scripts->add( 'wp-pointer', "/wp-includes/js/wp-pointer$suffix.js", array( 'jquery-ui-core' ), false, 1 ); 811 $scripts->set_translations( 'wp-pointer' ); 812 813 $scripts->add( 'autosave', "/wp-includes/js/autosave$suffix.js", array( 'heartbeat' ), false, 1 ); 814 815 $scripts->add( 'heartbeat', "/wp-includes/js/heartbeat$suffix.js", array( 'jquery', 'wp-hooks' ), false, 1 ); 816 did_action( 'init' ) && $scripts->localize( 817 'heartbeat', 818 'heartbeatSettings', 819 /** 820 * Filters the Heartbeat settings. 821 * 822 * @since 3.6.0 823 * 824 * @param array $settings Heartbeat settings array. 825 */ 826 apply_filters( 'heartbeat_settings', array() ) 827 ); 828 829 $scripts->add( 'wp-auth-check', "/wp-includes/js/wp-auth-check$suffix.js", array( 'heartbeat' ), false, 1 ); 830 $scripts->set_translations( 'wp-auth-check' ); 831 832 $scripts->add( 'wp-lists', "/wp-includes/js/wp-lists$suffix.js", array( 'wp-ajax-response', 'jquery-color' ), false, 1 ); 833 834 $scripts->add( 'site-icon', '/wp-admin/js/site-icon.js', array( 'jquery' ), false, 1 ); 835 $scripts->set_translations( 'site-icon' ); 836 837 // WordPress no longer uses or bundles Prototype or script.aculo.us. These are now pulled from an external source. 838 $scripts->add( 'prototype', 'https://ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js', array(), '1.7.1' ); 839 $scripts->add( 'scriptaculous-root', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/scriptaculous.js', array( 'prototype' ), '1.9.0' ); 840 $scripts->add( 'scriptaculous-builder', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/builder.js', array( 'scriptaculous-root' ), '1.9.0' ); 841 $scripts->add( 'scriptaculous-dragdrop', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/dragdrop.js', array( 'scriptaculous-builder', 'scriptaculous-effects' ), '1.9.0' ); 842 $scripts->add( 'scriptaculous-effects', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/effects.js', array( 'scriptaculous-root' ), '1.9.0' ); 843 $scripts->add( 'scriptaculous-slider', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/slider.js', array( 'scriptaculous-effects' ), '1.9.0' ); 844 $scripts->add( 'scriptaculous-sound', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/sound.js', array( 'scriptaculous-root' ), '1.9.0' ); 845 $scripts->add( 'scriptaculous-controls', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/controls.js', array( 'scriptaculous-root' ), '1.9.0' ); 846 $scripts->add( 'scriptaculous', false, array( 'scriptaculous-dragdrop', 'scriptaculous-slider', 'scriptaculous-controls' ) ); 847 848 // Not used in core, replaced by Jcrop.js. 849 $scripts->add( 'cropper', '/wp-includes/js/crop/cropper.js', array( 'scriptaculous-dragdrop' ) ); 850 851 /* 852 * jQuery. 853 * The unminified jquery.js and jquery-migrate.js are included to facilitate debugging. 854 */ 855 $scripts->add( 'jquery', false, array( 'jquery-core', 'jquery-migrate' ), '3.7.1' ); 856 $scripts->add( 'jquery-core', "/wp-includes/js/jquery/jquery$suffix.js", array(), '3.7.1' ); 857 $scripts->add( 'jquery-migrate', "/wp-includes/js/jquery/jquery-migrate$suffix.js", array(), '3.4.1' ); 858 859 /* 860 * Full jQuery UI. 861 * The build process in 1.12.1 has changed significantly. 862 * In order to keep backwards compatibility, and to keep the optimized loading, 863 * the source files were flattened and included with some modifications for AMD loading. 864 * A notable change is that 'jquery-ui-core' now contains 'jquery-ui-position' and 'jquery-ui-widget'. 865 */ 866 $scripts->add( 'jquery-ui-core', "/wp-includes/js/jquery/ui/core$suffix.js", array( 'jquery' ), '1.13.3', 1 ); 867 $scripts->add( 'jquery-effects-core', "/wp-includes/js/jquery/ui/effect$suffix.js", array( 'jquery' ), '1.13.3', 1 ); 868 869 $scripts->add( 'jquery-effects-blind', "/wp-includes/js/jquery/ui/effect-blind$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 870 $scripts->add( 'jquery-effects-bounce', "/wp-includes/js/jquery/ui/effect-bounce$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 871 $scripts->add( 'jquery-effects-clip', "/wp-includes/js/jquery/ui/effect-clip$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 872 $scripts->add( 'jquery-effects-drop', "/wp-includes/js/jquery/ui/effect-drop$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 873 $scripts->add( 'jquery-effects-explode', "/wp-includes/js/jquery/ui/effect-explode$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 874 $scripts->add( 'jquery-effects-fade', "/wp-includes/js/jquery/ui/effect-fade$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 875 $scripts->add( 'jquery-effects-fold', "/wp-includes/js/jquery/ui/effect-fold$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 876 $scripts->add( 'jquery-effects-highlight', "/wp-includes/js/jquery/ui/effect-highlight$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 877 $scripts->add( 'jquery-effects-puff', "/wp-includes/js/jquery/ui/effect-puff$suffix.js", array( 'jquery-effects-core', 'jquery-effects-scale' ), '1.13.3', 1 ); 878 $scripts->add( 'jquery-effects-pulsate', "/wp-includes/js/jquery/ui/effect-pulsate$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 879 $scripts->add( 'jquery-effects-scale', "/wp-includes/js/jquery/ui/effect-scale$suffix.js", array( 'jquery-effects-core', 'jquery-effects-size' ), '1.13.3', 1 ); 880 $scripts->add( 'jquery-effects-shake', "/wp-includes/js/jquery/ui/effect-shake$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 881 $scripts->add( 'jquery-effects-size', "/wp-includes/js/jquery/ui/effect-size$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 882 $scripts->add( 'jquery-effects-slide', "/wp-includes/js/jquery/ui/effect-slide$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 883 $scripts->add( 'jquery-effects-transfer', "/wp-includes/js/jquery/ui/effect-transfer$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 ); 884 885 // Widgets 886 $scripts->add( 'jquery-ui-accordion', "/wp-includes/js/jquery/ui/accordion$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 887 $scripts->add( 'jquery-ui-autocomplete', "/wp-includes/js/jquery/ui/autocomplete$suffix.js", array( 'jquery-ui-menu', 'wp-a11y' ), '1.13.3', 1 ); 888 $scripts->add( 'jquery-ui-button', "/wp-includes/js/jquery/ui/button$suffix.js", array( 'jquery-ui-core', 'jquery-ui-controlgroup', 'jquery-ui-checkboxradio' ), '1.13.3', 1 ); 889 $scripts->add( 'jquery-ui-datepicker', "/wp-includes/js/jquery/ui/datepicker$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 890 $scripts->add( 'jquery-ui-dialog', "/wp-includes/js/jquery/ui/dialog$suffix.js", array( 'jquery-ui-resizable', 'jquery-ui-draggable', 'jquery-ui-button' ), '1.13.3', 1 ); 891 $scripts->add( 'jquery-ui-menu', "/wp-includes/js/jquery/ui/menu$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 892 $scripts->add( 'jquery-ui-mouse', "/wp-includes/js/jquery/ui/mouse$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 893 $scripts->add( 'jquery-ui-progressbar', "/wp-includes/js/jquery/ui/progressbar$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 894 $scripts->add( 'jquery-ui-selectmenu', "/wp-includes/js/jquery/ui/selectmenu$suffix.js", array( 'jquery-ui-menu' ), '1.13.3', 1 ); 895 $scripts->add( 'jquery-ui-slider', "/wp-includes/js/jquery/ui/slider$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 ); 896 $scripts->add( 'jquery-ui-spinner', "/wp-includes/js/jquery/ui/spinner$suffix.js", array( 'jquery-ui-button' ), '1.13.3', 1 ); 897 $scripts->add( 'jquery-ui-tabs', "/wp-includes/js/jquery/ui/tabs$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 898 $scripts->add( 'jquery-ui-tooltip', "/wp-includes/js/jquery/ui/tooltip$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 899 900 // New in 1.12.1 901 $scripts->add( 'jquery-ui-checkboxradio', "/wp-includes/js/jquery/ui/checkboxradio$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 902 $scripts->add( 'jquery-ui-controlgroup', "/wp-includes/js/jquery/ui/controlgroup$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 ); 903 904 // Interactions 905 $scripts->add( 'jquery-ui-draggable', "/wp-includes/js/jquery/ui/draggable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 ); 906 $scripts->add( 'jquery-ui-droppable', "/wp-includes/js/jquery/ui/droppable$suffix.js", array( 'jquery-ui-draggable' ), '1.13.3', 1 ); 907 $scripts->add( 'jquery-ui-resizable', "/wp-includes/js/jquery/ui/resizable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 ); 908 $scripts->add( 'jquery-ui-selectable', "/wp-includes/js/jquery/ui/selectable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 ); 909 $scripts->add( 'jquery-ui-sortable', "/wp-includes/js/jquery/ui/sortable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 ); 910 911 /* 912 * As of 1.12.1 `jquery-ui-position` and `jquery-ui-widget` are part of `jquery-ui-core`. 913 * Listed here for back-compat. 914 */ 915 $scripts->add( 'jquery-ui-position', false, array( 'jquery-ui-core' ), '1.13.3', 1 ); 916 $scripts->add( 'jquery-ui-widget', false, array( 'jquery-ui-core' ), '1.13.3', 1 ); 917 918 // Deprecated, not used in core, most functionality is included in jQuery 1.3. 919 $scripts->add( 'jquery-form', "/wp-includes/js/jquery/jquery.form$suffix.js", array( 'jquery' ), '4.3.0', 1 ); 920 921 // jQuery plugins. 922 $scripts->add( 'jquery-color', '/wp-includes/js/jquery/jquery.color.min.js', array( 'jquery' ), '3.0.0', 1 ); 923 $scripts->add( 'schedule', '/wp-includes/js/jquery/jquery.schedule.js', array( 'jquery' ), '20m', 1 ); 924 $scripts->add( 'jquery-query', '/wp-includes/js/jquery/jquery.query.js', array( 'jquery' ), '2.2.3', 1 ); 925 $scripts->add( 'jquery-serialize-object', '/wp-includes/js/jquery/jquery.serialize-object.js', array( 'jquery' ), '0.2-wp', 1 ); 926 $scripts->add( 'jquery-hotkeys', "/wp-includes/js/jquery/jquery.hotkeys$suffix.js", array( 'jquery' ), '0.0.2m', 1 ); 927 $scripts->add( 'jquery-table-hotkeys', "/wp-includes/js/jquery/jquery.table-hotkeys$suffix.js", array( 'jquery', 'jquery-hotkeys' ), false, 1 ); 928 $scripts->add( 'jquery-touch-punch', '/wp-includes/js/jquery/jquery.ui.touch-punch.js', array( 'jquery-ui-core', 'jquery-ui-mouse' ), '0.2.2', 1 ); 929 930 // Not used any more, registered for backward compatibility. 931 $scripts->add( 'suggest', "/wp-includes/js/jquery/suggest$suffix.js", array( 'jquery' ), '1.1-20110113', 1 ); 932 933 /* 934 * Masonry v2 depended on jQuery. v3 does not. The older jquery-masonry handle is a shiv. 935 * It sets jQuery as a dependency, as the theme may have been implicitly loading it this way. 936 */ 937 $scripts->add( 'imagesloaded', '/wp-includes/js/imagesloaded.min.js', array(), '5.0.0', 1 ); 938 $scripts->add( 'masonry', '/wp-includes/js/masonry.min.js', array( 'imagesloaded' ), '4.2.2', 1 ); 939 $scripts->add( 'jquery-masonry', '/wp-includes/js/jquery/jquery.masonry.min.js', array( 'jquery', 'masonry' ), '3.1.2b', 1 ); 940 941 $scripts->add( 'thickbox', '/wp-includes/js/thickbox/thickbox.js', array( 'jquery' ), '3.1-20121105', 1 ); 942 did_action( 'init' ) && $scripts->localize( 943 'thickbox', 944 'thickboxL10n', 945 array( 946 'next' => __( 'Next >' ), 947 'prev' => __( '< Prev' ), 948 'image' => __( 'Image' ), 949 'of' => __( 'of' ), 950 'close' => __( 'Close' ), 951 'noiframes' => __( 'This feature requires inline frames. You have iframes disabled or your browser does not support them.' ), 952 'loadingAnimation' => includes_url( 'js/thickbox/loadingAnimation.gif' ), 953 ) 954 ); 955 956 // Not used in core, replaced by imgAreaSelect. 957 $scripts->add( 'jcrop', '/wp-includes/js/jcrop/jquery.Jcrop.min.js', array( 'jquery' ), '0.9.15' ); 958 959 // Error messages for Plupload. 960 $uploader_l10n = array( 961 'queue_limit_exceeded' => __( 'You have attempted to queue too many files.' ), 962 /* translators: %s: File name. */ 963 'file_exceeds_size_limit' => __( '%s exceeds the maximum upload size for this site.' ), 964 'zero_byte_file' => __( 'This file is empty. Please try another.' ), 965 'invalid_filetype' => __( 'This file cannot be processed by the web server.' ), 966 'not_an_image' => __( 'This file is not an image. Please try another.' ), 967 'image_memory_exceeded' => __( 'Memory exceeded. Please try another smaller file.' ), 968 'image_dimensions_exceeded' => __( 'This is larger than the maximum size. Please try another.' ), 969 'default_error' => __( 'An error occurred in the upload. Please try again later.' ), 970 'missing_upload_url' => __( 'There was a configuration error. Please contact the server administrator.' ), 971 'upload_limit_exceeded' => __( 'You may only upload 1 file.' ), 972 'http_error' => __( 'Unexpected response from the server. The file may have been uploaded successfully. Check in the Media Library or reload the page.' ), 973 'http_error_image' => __( 'The server cannot process the image. This can happen if the server is busy or does not have enough resources to complete the task. Uploading a smaller image may help. Suggested maximum size is 2560 pixels.' ), 974 'upload_failed' => __( 'Upload failed.' ), 975 /* translators: 1: Opening link tag, 2: Closing link tag. */ 976 'big_upload_failed' => __( 'Please try uploading this file with the %1$sbrowser uploader%2$s.' ), 977 /* translators: %s: File name. */ 978 'big_upload_queued' => __( '%s exceeds the maximum upload size for the multi-file uploader when used in your browser.' ), 979 'io_error' => __( 'IO error.' ), 980 'security_error' => __( 'Security error.' ), 981 'file_cancelled' => __( 'File canceled.' ), 982 'upload_stopped' => __( 'Upload stopped.' ), 983 'dismiss' => __( 'Dismiss' ), 984 'crunching' => __( 'Crunching…' ), 985 'deleted' => __( 'moved to the Trash.' ), 986 /* translators: %s: File name. */ 987 'error_uploading' => __( '“%s” has failed to upload.' ), 988 'unsupported_image' => __( 'This image cannot be displayed in a web browser. For best results convert it to JPEG before uploading.' ), 989 'noneditable_image' => __( 'The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading.' ), 990 'file_url_copied' => __( 'The file URL has been copied to your clipboard' ), 991 ); 992 993 $scripts->add( 'moxiejs', "/wp-includes/js/plupload/moxie$suffix.js", array(), '1.3.5.1' ); 994 $scripts->add( 'plupload', "/wp-includes/js/plupload/plupload$suffix.js", array( 'moxiejs' ), '2.1.9' ); 995 // Back compat handles: 996 foreach ( array( 'all', 'html5', 'flash', 'silverlight', 'html4' ) as $handle ) { 997 $scripts->add( "plupload-$handle", false, array( 'plupload' ), '2.1.1' ); 998 } 999 1000 $scripts->add( 'plupload-handlers', "/wp-includes/js/plupload/handlers$suffix.js", array( 'clipboard', 'jquery', 'plupload', 'underscore', 'wp-a11y', 'wp-i18n' ) ); 1001 did_action( 'init' ) && $scripts->localize( 'plupload-handlers', 'pluploadL10n', $uploader_l10n ); 1002 1003 $scripts->add( 'wp-plupload', "/wp-includes/js/plupload/wp-plupload$suffix.js", array( 'plupload', 'jquery', 'media-models' ), false, 1 ); 1004 did_action( 'init' ) && $scripts->localize( 'wp-plupload', 'pluploadL10n', $uploader_l10n ); 1005 1006 $scripts->add( 'comment-reply', "/wp-includes/js/comment-reply$suffix.js", array(), false, 1 ); 1007 if ( did_action( 'init' ) ) { 1008 $scripts->add_data( 'comment-reply', 'strategy', 'async' ); 1009 $scripts->add_data( 'comment-reply', 'fetchpriority', 'low' ); // In Chrome this is automatically low due to the async strategy, but in Firefox and Safari the priority is normal/medium. 1010 } 1011 1012 // Not used in core, obsolete. Registered for backward compatibility. 1013 $scripts->add( 'json2', "/wp-includes/js/json2$suffix.js", array(), '2015-05-03' ); 1014 did_action( 'init' ) && $scripts->add_data( 'json2', 'conditional', '_required-conditional-dependency_' ); 1015 1016 $scripts->add( 'underscore', "/wp-includes/js/underscore$dev_suffix.js", array(), '1.13.7', 1 ); 1017 $scripts->add( 'backbone', "/wp-includes/js/backbone$dev_suffix.js", array( 'underscore', 'jquery' ), '1.6.0', 1 ); 1018 1019 $scripts->add( 'wp-util', "/wp-includes/js/wp-util$suffix.js", array( 'underscore', 'jquery' ), false, 1 ); 1020 did_action( 'init' ) && $scripts->localize( 1021 'wp-util', 1022 '_wpUtilSettings', 1023 array( 1024 'ajax' => array( 1025 'url' => admin_url( 'admin-ajax.php', 'relative' ), 1026 ), 1027 ) 1028 ); 1029 1030 $scripts->add( 'wp-backbone', "/wp-includes/js/wp-backbone$suffix.js", array( 'backbone', 'wp-util' ), false, 1 ); 1031 1032 $scripts->add( 'revisions', "/wp-admin/js/revisions$suffix.js", array( 'wp-backbone', 'jquery-ui-slider', 'hoverIntent' ), false, 1 ); 1033 1034 $scripts->add( 'imgareaselect', "/wp-includes/js/imgareaselect/jquery.imgareaselect$suffix.js", array( 'jquery' ), false, 1 ); 1035 1036 $scripts->add( 'mediaelement', false, array( 'jquery', 'mediaelement-core', 'mediaelement-migrate' ), '4.2.17', 1 ); 1037 $scripts->add( 'mediaelement-core', "/wp-includes/js/mediaelement/mediaelement-and-player$suffix.js", array(), '4.2.17', 1 ); 1038 $scripts->add( 'mediaelement-migrate', "/wp-includes/js/mediaelement/mediaelement-migrate$suffix.js", array(), false, 1 ); 1039 1040 did_action( 'init' ) && $scripts->add_inline_script( 1041 'mediaelement-core', 1042 sprintf( 1043 'var mejsL10n = %s;', 1044 wp_json_encode( 1045 array( 1046 'language' => strtolower( strtok( determine_locale(), '_-' ) ), 1047 'strings' => array( 1048 'mejs.download-file' => __( 'Download File' ), 1049 'mejs.install-flash' => __( 'You are using a browser that does not have Flash player enabled or installed. Please turn on your Flash player plugin or download the latest version from https://get.adobe.com/flashplayer/' ), 1050 'mejs.fullscreen' => __( 'Fullscreen' ), 1051 'mejs.play' => __( 'Play' ), 1052 'mejs.pause' => __( 'Pause' ), 1053 'mejs.time-slider' => __( 'Time Slider' ), 1054 'mejs.time-help-text' => __( 'Use Left/Right Arrow keys to advance one second, Up/Down arrows to advance ten seconds.' ), 1055 'mejs.live-broadcast' => __( 'Live Broadcast' ), 1056 'mejs.volume-help-text' => __( 'Use Up/Down Arrow keys to increase or decrease volume.' ), 1057 'mejs.unmute' => __( 'Unmute' ), 1058 'mejs.mute' => __( 'Mute' ), 1059 'mejs.volume-slider' => __( 'Volume Slider' ), 1060 'mejs.video-player' => __( 'Video Player' ), 1061 'mejs.audio-player' => __( 'Audio Player' ), 1062 'mejs.captions-subtitles' => __( 'Captions/Subtitles' ), 1063 'mejs.captions-chapters' => __( 'Chapters' ), 1064 'mejs.none' => __( 'None' ), 1065 'mejs.afrikaans' => __( 'Afrikaans' ), 1066 'mejs.albanian' => __( 'Albanian' ), 1067 'mejs.arabic' => __( 'Arabic' ), 1068 'mejs.belarusian' => __( 'Belarusian' ), 1069 'mejs.bulgarian' => __( 'Bulgarian' ), 1070 'mejs.catalan' => __( 'Catalan' ), 1071 'mejs.chinese' => __( 'Chinese' ), 1072 'mejs.chinese-simplified' => __( 'Chinese (Simplified)' ), 1073 'mejs.chinese-traditional' => __( 'Chinese (Traditional)' ), 1074 'mejs.croatian' => __( 'Croatian' ), 1075 'mejs.czech' => __( 'Czech' ), 1076 'mejs.danish' => __( 'Danish' ), 1077 'mejs.dutch' => __( 'Dutch' ), 1078 'mejs.english' => __( 'English' ), 1079 'mejs.estonian' => __( 'Estonian' ), 1080 'mejs.filipino' => __( 'Filipino' ), 1081 'mejs.finnish' => __( 'Finnish' ), 1082 'mejs.french' => __( 'French' ), 1083 'mejs.galician' => __( 'Galician' ), 1084 'mejs.german' => __( 'German' ), 1085 'mejs.greek' => __( 'Greek' ), 1086 'mejs.haitian-creole' => __( 'Haitian Creole' ), 1087 'mejs.hebrew' => __( 'Hebrew' ), 1088 'mejs.hindi' => __( 'Hindi' ), 1089 'mejs.hungarian' => __( 'Hungarian' ), 1090 'mejs.icelandic' => __( 'Icelandic' ), 1091 'mejs.indonesian' => __( 'Indonesian' ), 1092 'mejs.irish' => __( 'Irish' ), 1093 'mejs.italian' => __( 'Italian' ), 1094 'mejs.japanese' => __( 'Japanese' ), 1095 'mejs.korean' => __( 'Korean' ), 1096 'mejs.latvian' => __( 'Latvian' ), 1097 'mejs.lithuanian' => __( 'Lithuanian' ), 1098 'mejs.macedonian' => __( 'Macedonian' ), 1099 'mejs.malay' => __( 'Malay' ), 1100 'mejs.maltese' => __( 'Maltese' ), 1101 'mejs.norwegian' => __( 'Norwegian' ), 1102 'mejs.persian' => __( 'Persian' ), 1103 'mejs.polish' => __( 'Polish' ), 1104 'mejs.portuguese' => __( 'Portuguese' ), 1105 'mejs.romanian' => __( 'Romanian' ), 1106 'mejs.russian' => __( 'Russian' ), 1107 'mejs.serbian' => __( 'Serbian' ), 1108 'mejs.slovak' => __( 'Slovak' ), 1109 'mejs.slovenian' => __( 'Slovenian' ), 1110 'mejs.spanish' => __( 'Spanish' ), 1111 'mejs.swahili' => __( 'Swahili' ), 1112 'mejs.swedish' => __( 'Swedish' ), 1113 'mejs.tagalog' => __( 'Tagalog' ), 1114 'mejs.thai' => __( 'Thai' ), 1115 'mejs.turkish' => __( 'Turkish' ), 1116 'mejs.ukrainian' => __( 'Ukrainian' ), 1117 'mejs.vietnamese' => __( 'Vietnamese' ), 1118 'mejs.welsh' => __( 'Welsh' ), 1119 'mejs.yiddish' => __( 'Yiddish' ), 1120 ), 1121 ), 1122 JSON_HEX_TAG | JSON_UNESCAPED_SLASHES 1123 ) 1124 ), 1125 'before' 1126 ); 1127 1128 $scripts->add( 'mediaelement-vimeo', '/wp-includes/js/mediaelement/renderers/vimeo.min.js', array( 'mediaelement' ), '4.2.17', 1 ); 1129 $scripts->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement$suffix.js", array( 'mediaelement' ), false, 1 ); 1130 $mejs_settings = array( 1131 'pluginPath' => includes_url( 'js/mediaelement/', 'relative' ), 1132 'classPrefix' => 'mejs-', 1133 'stretching' => 'responsive', 1134 /** This filter is documented in wp-includes/media.php */ 1135 'audioShortcodeLibrary' => apply_filters( 'wp_audio_shortcode_library', 'mediaelement' ), 1136 /** This filter is documented in wp-includes/media.php */ 1137 'videoShortcodeLibrary' => apply_filters( 'wp_video_shortcode_library', 'mediaelement' ), 1138 ); 1139 did_action( 'init' ) && $scripts->localize( 1140 'mediaelement', 1141 '_wpmejsSettings', 1142 /** 1143 * Filters the MediaElement configuration settings. 1144 * 1145 * @since 4.4.0 1146 * 1147 * @param array $mejs_settings MediaElement settings array. 1148 */ 1149 apply_filters( 'mejs_settings', $mejs_settings ) 1150 ); 1151 1152 $scripts->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.29.1-alpha-ee20357' ); 1153 $scripts->add( 'csslint', '/wp-includes/js/codemirror/csslint.js', array(), '1.0.5' ); 1154 $scripts->add( 'esprima', '/wp-includes/js/codemirror/esprima.js', array(), '4.0.0' ); 1155 $scripts->add( 'jshint', '/wp-includes/js/codemirror/fakejshint.js', array( 'esprima' ), '2.9.5' ); 1156 $scripts->add( 'jsonlint', '/wp-includes/js/codemirror/jsonlint.js', array(), '1.6.2' ); 1157 $scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '0.9.14-xwp' ); 1158 $scripts->add( 'htmlhint-kses', '/wp-includes/js/codemirror/htmlhint-kses.js', array( 'htmlhint' ) ); 1159 $scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'wp-codemirror', 'underscore' ) ); 1160 $scripts->add( 'wp-theme-plugin-editor', "/wp-admin/js/theme-plugin-editor$suffix.js", array( 'common', 'wp-util', 'wp-sanitize', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ), false, 1 ); 1161 $scripts->set_translations( 'wp-theme-plugin-editor' ); 1162 1163 $scripts->add( 'wp-playlist', "/wp-includes/js/mediaelement/wp-playlist$suffix.js", array( 'wp-util', 'backbone', 'mediaelement' ), false, 1 ); 1164 1165 $scripts->add( 'zxcvbn-async', "/wp-includes/js/zxcvbn-async$suffix.js", array(), '1.0' ); 1166 did_action( 'init' ) && $scripts->localize( 1167 'zxcvbn-async', 1168 '_zxcvbnSettings', 1169 array( 1170 'src' => empty( $guessed_url ) ? includes_url( '/js/zxcvbn.min.js' ) : $scripts->base_url . '/wp-includes/js/zxcvbn.min.js', 1171 ) 1172 ); 1173 1174 $scripts->add( 'password-strength-meter', "/wp-admin/js/password-strength-meter$suffix.js", array( 'jquery', 'zxcvbn-async' ), false, 1 ); 1175 did_action( 'init' ) && $scripts->localize( 1176 'password-strength-meter', 1177 'pwsL10n', 1178 array( 1179 'unknown' => _x( 'Password strength unknown', 'password strength' ), 1180 'short' => _x( 'Very weak', 'password strength' ), 1181 'bad' => _x( 'Weak', 'password strength' ), 1182 'good' => _x( 'Medium', 'password strength' ), 1183 'strong' => _x( 'Strong', 'password strength' ), 1184 'mismatch' => _x( 'Mismatch', 'password mismatch' ), 1185 ) 1186 ); 1187 $scripts->set_translations( 'password-strength-meter' ); 1188 1189 $scripts->add( 'password-toggle', "/wp-admin/js/password-toggle$suffix.js", array(), false, 1 ); 1190 $scripts->set_translations( 'password-toggle' ); 1191 1192 $scripts->add( 'application-passwords', "/wp-admin/js/application-passwords$suffix.js", array( 'jquery', 'wp-util', 'wp-api-request', 'wp-date', 'wp-i18n', 'wp-hooks' ), false, 1 ); 1193 $scripts->set_translations( 'application-passwords' ); 1194 1195 $scripts->add( 'auth-app', "/wp-admin/js/auth-app$suffix.js", array( 'jquery', 'wp-api-request', 'wp-i18n', 'wp-hooks' ), false, 1 ); 1196 $scripts->set_translations( 'auth-app' ); 1197 1198 $scripts->add( 'user-profile', "/wp-admin/js/user-profile$suffix.js", array( 'clipboard', 'jquery', 'password-strength-meter', 'wp-util', 'wp-a11y' ), false, 1 ); 1199 $scripts->set_translations( 'user-profile' ); 1200 $user_id = isset( $_GET['user_id'] ) ? (int) $_GET['user_id'] : 0; 1201 did_action( 'init' ) && $scripts->localize( 1202 'user-profile', 1203 'userProfileL10n', 1204 array( 1205 'user_id' => $user_id, 1206 'nonce' => wp_installing() ? '' : wp_create_nonce( 'reset-password-for-' . $user_id ), 1207 ) 1208 ); 1209 1210 $scripts->add( 'language-chooser', "/wp-admin/js/language-chooser$suffix.js", array( 'jquery' ), false, 1 ); 1211 1212 $scripts->add( 'user-suggest', "/wp-admin/js/user-suggest$suffix.js", array( 'jquery-ui-autocomplete' ), false, 1 ); 1213 1214 $scripts->add( 'admin-bar', "/wp-includes/js/admin-bar$suffix.js", array( 'hoverintent-js' ), false, 1 ); 1215 1216 $scripts->add( 'wplink', "/wp-includes/js/wplink$suffix.js", array( 'common', 'jquery', 'wp-a11y', 'wp-i18n' ), false, 1 ); 1217 $scripts->set_translations( 'wplink' ); 1218 did_action( 'init' ) && $scripts->localize( 1219 'wplink', 1220 'wpLinkL10n', 1221 array( 1222 'title' => __( 'Insert/edit link' ), 1223 'update' => __( 'Update' ), 1224 'save' => __( 'Add Link' ), 1225 'noTitle' => __( '(no title)' ), 1226 'noMatchesFound' => __( 'No results found.' ), 1227 'linkSelected' => __( 'Link selected.' ), 1228 'linkInserted' => __( 'Link inserted.' ), 1229 /* translators: Minimum input length in characters to start searching posts in the "Insert/edit link" modal. */ 1230 'minInputLength' => (int) _x( '3', 'minimum input length for searching post links' ), 1231 ) 1232 ); 1233 1234 $scripts->add( 'wpdialogs', "/wp-includes/js/wpdialog$suffix.js", array( 'jquery-ui-dialog' ), false, 1 ); 1235 1236 $scripts->add( 'word-count', "/wp-admin/js/word-count$suffix.js", array(), false, 1 ); 1237 1238 $scripts->add( 'media-upload', "/wp-admin/js/media-upload$suffix.js", array( 'thickbox', 'shortcode' ), false, 1 ); 1239 1240 $scripts->add( 'hoverIntent', "/wp-includes/js/hoverIntent$suffix.js", array( 'jquery' ), '1.10.2', 1 ); 1241 1242 // JS-only version of hoverintent (no dependencies). 1243 $scripts->add( 'hoverintent-js', '/wp-includes/js/hoverintent-js.min.js', array(), '2.2.1', 1 ); 1244 1245 $scripts->add( 'customize-base', "/wp-includes/js/customize-base$suffix.js", array( 'jquery', 'underscore' ), false, 1 ); 1246 $scripts->add( 'customize-loader', "/wp-includes/js/customize-loader$suffix.js", array( 'customize-base' ), false, 1 ); 1247 $scripts->add( 'customize-preview', "/wp-includes/js/customize-preview$suffix.js", array( 'wp-a11y', 'customize-base' ), false, 1 ); 1248 $scripts->add( 'customize-models', '/wp-includes/js/customize-models.js', array( 'underscore', 'backbone' ), false, 1 ); 1249 $scripts->add( 'customize-views', '/wp-includes/js/customize-views.js', array( 'jquery', 'underscore', 'imgareaselect', 'customize-models', 'media-editor', 'media-views' ), false, 1 ); 1250 $scripts->add( 'customize-controls', "/wp-admin/js/customize-controls$suffix.js", array( 'customize-base', 'wp-a11y', 'wp-util', 'jquery-ui-core' ), false, 1 ); 1251 did_action( 'init' ) && $scripts->localize( 1252 'customize-controls', 1253 '_wpCustomizeControlsL10n', 1254 array( 1255 'activate' => __( 'Activate & Publish' ), 1256 'save' => __( 'Save & Publish' ), // @todo Remove as not required. 1257 'publish' => __( 'Publish' ), 1258 'published' => __( 'Published' ), 1259 'saveDraft' => __( 'Save Draft' ), 1260 'draftSaved' => __( 'Draft Saved' ), 1261 'updating' => __( 'Updating' ), 1262 'schedule' => _x( 'Schedule', 'customizer changeset action/button label' ), 1263 'scheduled' => _x( 'Scheduled', 'customizer changeset status' ), 1264 'invalid' => __( 'Invalid' ), 1265 'saveBeforeShare' => __( 'Please save your changes in order to share the preview.' ), 1266 'futureDateError' => __( 'You must supply a future date to schedule.' ), 1267 'saveAlert' => __( 'The changes you made will be lost if you navigate away from this page.' ), 1268 'saved' => __( 'Saved' ), 1269 'cancel' => __( 'Cancel' ), 1270 'close' => __( 'Close' ), 1271 'action' => __( 'Action' ), 1272 'discardChanges' => __( 'Discard changes' ), 1273 'cheatin' => __( 'An error occurred. Please try again later.' ), 1274 'notAllowedHeading' => __( 'You need a higher level of permission.' ), 1275 'notAllowed' => __( 'Sorry, you are not allowed to customize this site.' ), 1276 'previewIframeTitle' => __( 'Site Preview' ), 1277 'loginIframeTitle' => __( 'Session expired' ), 1278 'collapseSidebar' => _x( 'Hide Controls', 'label for hide controls button without length constraints' ), 1279 'expandSidebar' => _x( 'Show Controls', 'label for hide controls button without length constraints' ), 1280 'untitledBlogName' => __( '(Untitled)' ), 1281 'unknownRequestFail' => __( 'Looks like something’s gone wrong. Wait a couple seconds, and then try again.' ), 1282 'themeDownloading' => __( 'Downloading your new theme…' ), 1283 'themePreviewWait' => __( 'Setting up your live preview. This may take a bit.' ), 1284 'revertingChanges' => __( 'Reverting unpublished changes…' ), 1285 'trashConfirm' => __( 'Are you sure you want to discard your unpublished changes?' ), 1286 /* translators: %s: Display name of the user who has taken over the changeset in customizer. */ 1287 'takenOverMessage' => __( '%s has taken over and is currently customizing.' ), 1288 /* translators: %s: URL to the Customizer to load the autosaved version. */ 1289 'autosaveNotice' => __( 'There is a more recent autosave of your changes than the one you are previewing. <a href="%s">Restore the autosave</a>' ), 1290 'videoHeaderNotice' => __( 'This theme does not support video headers on this page. Navigate to the front page or another page that supports video headers.' ), 1291 // Used for overriding the file types allowed in Plupload. 1292 'allowedFiles' => __( 'Allowed Files' ), 1293 'customCssError' => array( 1294 /* translators: %d: Error count. */ 1295 'singular' => _n( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.', 1 ), 1296 /* translators: %d: Error count. */ 1297 'plural' => _n( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.', 2 ), 1298 // @todo This is lacking, as some languages have a dedicated dual form. For proper handling of plurals in JS, see #20491. 1299 ), 1300 'pageOnFrontError' => __( 'Homepage and posts page must be different.' ), 1301 'saveBlockedError' => array( 1302 /* translators: %s: Number of invalid settings. */ 1303 'singular' => _n( 'Unable to save due to %s invalid setting.', 'Unable to save due to %s invalid settings.', 1 ), 1304 /* translators: %s: Number of invalid settings. */ 1305 'plural' => _n( 'Unable to save due to %s invalid setting.', 'Unable to save due to %s invalid settings.', 2 ), 1306 // @todo This is lacking, as some languages have a dedicated dual form. For proper handling of plurals in JS, see #20491. 1307 ), 1308 'scheduleDescription' => __( 'Schedule your customization changes to publish ("go live") at a future date.' ), 1309 'themePreviewUnavailable' => __( 'Sorry, you cannot preview new themes when you have changes scheduled or saved as a draft. Please publish your changes, or wait until they publish to preview new themes.' ), 1310 'themeInstallUnavailable' => sprintf( 1311 /* translators: %s: URL to Add Themes admin screen. */ 1312 __( 'You will not be able to install new themes from here yet since your install requires SFTP credentials. For now, please <a href="%s">add themes in the admin</a>.' ), 1313 esc_url( admin_url( 'theme-install.php' ) ) 1314 ), 1315 'publishSettings' => __( 'Publish Settings' ), 1316 'invalidDate' => __( 'Invalid date.' ), 1317 'invalidValue' => __( 'Invalid value.' ), 1318 'blockThemeNotification' => sprintf( 1319 /* translators: 1: Link to Site Editor documentation on HelpHub, 2: HTML button. */ 1320 __( 'Hurray! Your theme supports site editing with blocks. <a href="%1$s">Tell me more</a>. %2$s' ), 1321 __( 'https://wordpress.org/documentation/article/site-editor/' ), 1322 sprintf( 1323 '<button type="button" data-action="%1$s" class="button switch-to-editor">%2$s</button>', 1324 esc_url( admin_url( 'site-editor.php' ) ), 1325 __( 'Use Site Editor' ) 1326 ) 1327 ), 1328 ) 1329 ); 1330 $scripts->add( 'customize-selective-refresh', "/wp-includes/js/customize-selective-refresh$suffix.js", array( 'jquery', 'wp-util', 'customize-preview' ), false, 1 ); 1331 1332 $scripts->add( 'customize-widgets', "/wp-admin/js/customize-widgets$suffix.js", array( 'jquery', 'jquery-ui-sortable', 'jquery-ui-droppable', 'wp-backbone', 'customize-controls' ), false, 1 ); 1333 $scripts->add( 'customize-preview-widgets', "/wp-includes/js/customize-preview-widgets$suffix.js", array( 'jquery', 'wp-util', 'customize-preview', 'customize-selective-refresh' ), false, 1 ); 1334 1335 $scripts->add( 'customize-nav-menus', "/wp-admin/js/customize-nav-menus$suffix.js", array( 'jquery', 'wp-backbone', 'customize-controls', 'accordion', 'nav-menu', 'wp-sanitize' ), false, 1 ); 1336 $scripts->add( 'customize-preview-nav-menus', "/wp-includes/js/customize-preview-nav-menus$suffix.js", array( 'jquery', 'wp-util', 'customize-preview', 'customize-selective-refresh' ), false, 1 ); 1337 1338 $scripts->add( 'wp-custom-header', "/wp-includes/js/wp-custom-header$suffix.js", array( 'wp-a11y' ), false, 1 ); 1339 1340 $scripts->add( 'accordion', "/wp-admin/js/accordion$suffix.js", array( 'jquery' ), false, 1 ); 1341 1342 $scripts->add( 'shortcode', "/wp-includes/js/shortcode$suffix.js", array( 'underscore' ), false, 1 ); 1343 $scripts->add( 'media-models', "/wp-includes/js/media-models$suffix.js", array( 'wp-backbone' ), false, 1 ); 1344 did_action( 'init' ) && $scripts->localize( 1345 'media-models', 1346 '_wpMediaModelsL10n', 1347 array( 1348 'settings' => array( 1349 'ajaxurl' => admin_url( 'admin-ajax.php', 'relative' ), 1350 'post' => array( 'id' => 0 ), 1351 ), 1352 ) 1353 ); 1354 1355 $scripts->add( 'wp-embed', "/wp-includes/js/wp-embed$suffix.js" ); 1356 did_action( 'init' ) && $scripts->add_data( 'wp-embed', 'strategy', 'defer' ); 1357 1358 /* 1359 * To enqueue media-views or media-editor, call wp_enqueue_media(). 1360 * Both rely on numerous settings, styles, and templates to operate correctly. 1361 */ 1362 $scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement', 'wp-api-request', 'wp-a11y', 'clipboard' ), false, 1 ); 1363 $scripts->set_translations( 'media-views' ); 1364 1365 $scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 ); 1366 $scripts->set_translations( 'media-editor' ); 1367 $scripts->add( 'media-audiovideo', "/wp-includes/js/media-audiovideo$suffix.js", array( 'media-editor' ), false, 1 ); 1368 $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'jquery', 'media-views', 'media-audiovideo' ), false, 1 ); 1369 1370 $scripts->add( 'wp-api', "/wp-includes/js/wp-api$suffix.js", array( 'jquery', 'backbone', 'underscore', 'wp-api-request' ), false, 1 ); 1371 1372 if ( is_admin() ) { 1373 $scripts->add( 'admin-tags', "/wp-admin/js/tags$suffix.js", array( 'jquery', 'wp-ajax-response' ), false, 1 ); 1374 $scripts->set_translations( 'admin-tags' ); 1375 1376 $scripts->add( 'admin-comments', "/wp-admin/js/edit-comments$suffix.js", array( 'wp-lists', 'quicktags', 'jquery-query', 'wp-a11y' ), false, 1 ); 1377 $scripts->set_translations( 'admin-comments' ); 1378 did_action( 'init' ) && $scripts->localize( 1379 'admin-comments', 1380 'adminCommentsSettings', 1381 array( 1382 'hotkeys_highlight_first' => isset( $_GET['hotkeys_highlight_first'] ), 1383 'hotkeys_highlight_last' => isset( $_GET['hotkeys_highlight_last'] ), 1384 ) 1385 ); 1386 1387 $scripts->add( 'xfn', "/wp-admin/js/xfn$suffix.js", array( 'jquery' ), false, 1 ); 1388 1389 $scripts->add( 'postbox', "/wp-admin/js/postbox$suffix.js", array( 'jquery-ui-sortable', 'wp-a11y' ), false, 1 ); 1390 $scripts->set_translations( 'postbox' ); 1391 1392 $scripts->add( 'tags-box', "/wp-admin/js/tags-box$suffix.js", array( 'jquery', 'tags-suggest' ), false, 1 ); 1393 $scripts->set_translations( 'tags-box' ); 1394 1395 $scripts->add( 'tags-suggest', "/wp-admin/js/tags-suggest$suffix.js", array( 'common', 'jquery-ui-autocomplete', 'wp-a11y', 'wp-i18n' ), false, 1 ); 1396 $scripts->set_translations( 'tags-suggest' ); 1397 1398 $scripts->add( 'post', "/wp-admin/js/post$suffix.js", array( 'suggest', 'wp-lists', 'postbox', 'tags-box', 'underscore', 'word-count', 'wp-a11y', 'wp-sanitize', 'clipboard' ), false, 1 ); 1399 $scripts->set_translations( 'post' ); 1400 1401 $scripts->add( 'editor-expand', "/wp-admin/js/editor-expand$suffix.js", array( 'jquery', 'underscore' ), false, 1 ); 1402 1403 $scripts->add( 'link', "/wp-admin/js/link$suffix.js", array( 'wp-lists', 'postbox' ), false, 1 ); 1404 1405 $scripts->add( 'comment', "/wp-admin/js/comment$suffix.js", array( 'jquery', 'postbox' ), false, 1 ); 1406 $scripts->set_translations( 'comment' ); 1407 1408 $scripts->add( 'admin-gallery', "/wp-admin/js/gallery$suffix.js", array( 'jquery-ui-sortable' ) ); 1409 1410 $scripts->add( 'admin-widgets', "/wp-admin/js/widgets$suffix.js", array( 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable', 'wp-a11y' ), false, 1 ); 1411 $scripts->set_translations( 'admin-widgets' ); 1412 1413 $scripts->add( 'media-widgets', "/wp-admin/js/widgets/media-widgets$suffix.js", array( 'jquery', 'media-models', 'media-views', 'wp-api-request' ) ); 1414 $scripts->add_inline_script( 'media-widgets', 'wp.mediaWidgets.init();', 'after' ); 1415 1416 $scripts->add( 'media-audio-widget', "/wp-admin/js/widgets/media-audio-widget$suffix.js", array( 'media-widgets', 'media-audiovideo' ) ); 1417 $scripts->add( 'media-image-widget', "/wp-admin/js/widgets/media-image-widget$suffix.js", array( 'media-widgets' ) ); 1418 $scripts->add( 'media-gallery-widget', "/wp-admin/js/widgets/media-gallery-widget$suffix.js", array( 'media-widgets' ) ); 1419 $scripts->add( 'media-video-widget', "/wp-admin/js/widgets/media-video-widget$suffix.js", array( 'media-widgets', 'media-audiovideo', 'wp-api-request' ) ); 1420 $scripts->add( 'text-widgets', "/wp-admin/js/widgets/text-widgets$suffix.js", array( 'jquery', 'backbone', 'editor', 'wp-util', 'wp-a11y' ) ); 1421 $scripts->add( 'custom-html-widgets', "/wp-admin/js/widgets/custom-html-widgets$suffix.js", array( 'jquery', 'backbone', 'wp-util', 'jquery-ui-core', 'wp-a11y' ) ); 1422 1423 $scripts->add( 'theme', "/wp-admin/js/theme$suffix.js", array( 'wp-backbone', 'wp-a11y', 'customize-base' ), false, 1 ); 1424 1425 $scripts->add( 'inline-edit-post', "/wp-admin/js/inline-edit-post$suffix.js", array( 'jquery', 'tags-suggest', 'wp-a11y' ), false, 1 ); 1426 $scripts->set_translations( 'inline-edit-post' ); 1427 1428 $scripts->add( 'inline-edit-tax', "/wp-admin/js/inline-edit-tax$suffix.js", array( 'jquery', 'wp-a11y' ), false, 1 ); 1429 $scripts->set_translations( 'inline-edit-tax' ); 1430 1431 $scripts->add( 'plugin-install', "/wp-admin/js/plugin-install$suffix.js", array( 'jquery', 'jquery-ui-core', 'thickbox' ), false, 1 ); 1432 $scripts->set_translations( 'plugin-install' ); 1433 1434 $scripts->add( 'site-health', "/wp-admin/js/site-health$suffix.js", array( 'clipboard', 'jquery', 'wp-util', 'wp-a11y', 'wp-api-request', 'wp-url', 'wp-i18n', 'wp-hooks' ), false, 1 ); 1435 $scripts->set_translations( 'site-health' ); 1436 1437 $scripts->add( 'privacy-tools', "/wp-admin/js/privacy-tools$suffix.js", array( 'jquery', 'wp-a11y' ), false, 1 ); 1438 $scripts->set_translations( 'privacy-tools' ); 1439 1440 $scripts->add( 'updates', "/wp-admin/js/updates$suffix.js", array( 'common', 'jquery', 'wp-util', 'wp-a11y', 'wp-sanitize', 'wp-i18n' ), false, 1 ); 1441 $scripts->set_translations( 'updates' ); 1442 did_action( 'init' ) && $scripts->localize( 1443 'updates', 1444 '_wpUpdatesSettings', 1445 array( 1446 'ajax_nonce' => wp_installing() ? '' : wp_create_nonce( 'updates' ), 1447 ) 1448 ); 1449 1450 $scripts->add( 'farbtastic', '/wp-admin/js/farbtastic.js', array( 'jquery' ), '1.2' ); 1451 1452 $scripts->add( 'iris', '/wp-admin/js/iris.min.js', array( 'jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch' ), '1.1.1', 1 ); 1453 $scripts->add( 'wp-color-picker', "/wp-admin/js/color-picker$suffix.js", array( 'iris' ), false, 1 ); 1454 $scripts->set_translations( 'wp-color-picker' ); 1455 1456 $scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'common', 'jquery', 'admin-comments', 'postbox', 'wp-util', 'wp-a11y', 'wp-date' ), false, 1 ); 1457 $scripts->set_translations( 'dashboard' ); 1458 1459 $scripts->add( 'list-revisions', "/wp-includes/js/wp-list-revisions$suffix.js" ); 1460 1461 $scripts->add( 'media-grid', "/wp-includes/js/media-grid$suffix.js", array( 'media-editor' ), false, 1 ); 1462 $scripts->add( 'media', "/wp-admin/js/media$suffix.js", array( 'jquery', 'clipboard', 'wp-i18n', 'wp-a11y' ), false, 1 ); 1463 $scripts->set_translations( 'media' ); 1464 1465 $scripts->add( 'image-edit', "/wp-admin/js/image-edit$suffix.js", array( 'jquery', 'jquery-ui-core', 'imgareaselect', 'wp-a11y' ), false, 1 ); 1466 $scripts->set_translations( 'image-edit' ); 1467 1468 $scripts->add( 'set-post-thumbnail', "/wp-admin/js/set-post-thumbnail$suffix.js", array( 'jquery' ), false, 1 ); 1469 $scripts->set_translations( 'set-post-thumbnail' ); 1470 1471 /* 1472 * Navigation Menus: Adding underscore as a dependency to utilize _.debounce 1473 * see https://core.trac.wordpress.org/ticket/42321 1474 */ 1475 $scripts->add( 'nav-menu', "/wp-admin/js/nav-menu$suffix.js", array( 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable', 'wp-lists', 'postbox', 'underscore' ) ); 1476 $scripts->set_translations( 'nav-menu' ); 1477 1478 $scripts->add( 'custom-header', '/wp-admin/js/custom-header.js', array( 'jquery-masonry' ), false, 1 ); 1479 $scripts->add( 'custom-background', "/wp-admin/js/custom-background$suffix.js", array( 'wp-color-picker', 'media-views' ), false, 1 ); 1480 $scripts->add( 'media-gallery', "/wp-admin/js/media-gallery$suffix.js", array( 'jquery' ), false, 1 ); 1481 1482 $scripts->add( 'svg-painter', '/wp-admin/js/svg-painter.js', array( 'jquery' ), false, 1 ); 1483 } 1484 } 1485 1486 /** 1487 * Assigns default styles to $styles object. 1488 * 1489 * Nothing is returned, because the $styles parameter is passed by reference. 1490 * Meaning that whatever object is passed will be updated without having to 1491 * reassign the variable that was passed back to the same value. This saves 1492 * memory. 1493 * 1494 * Adding default styles is not the only task, it also assigns the base_url 1495 * property, the default version, and text direction for the object. 1496 * 1497 * @since 2.6.0 1498 * 1499 * @global array $editor_styles 1500 * 1501 * @param WP_Styles $styles 1502 */ 1503 function wp_default_styles( $styles ) { 1504 global $editor_styles; 1505 1506 /* 1507 * Include an unmodified $wp_version. 1508 * 1509 * Note: wp_get_wp_version() is not used here, as this file can be included 1510 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case 1511 * wp-includes/functions.php is not loaded. 1512 */ 1513 require ABSPATH . WPINC . '/version.php'; 1514 1515 if ( ! defined( 'SCRIPT_DEBUG' ) ) { 1516 /* 1517 * Note: str_contains() is not used here, as this file can be included 1518 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case 1519 * the polyfills from wp-includes/compat.php are not loaded. 1520 */ 1521 define( 'SCRIPT_DEBUG', false !== strpos( $wp_version, '-src' ) ); 1522 } 1523 1524 $guessurl = site_url(); 1525 1526 if ( ! $guessurl ) { 1527 $guessurl = wp_guess_url(); 1528 } 1529 1530 $styles->base_url = $guessurl; 1531 $styles->content_url = defined( 'WP_CONTENT_URL' ) ? WP_CONTENT_URL : ''; 1532 $styles->default_version = get_bloginfo( 'version' ); 1533 $styles->text_direction = function_exists( 'is_rtl' ) && is_rtl() ? 'rtl' : 'ltr'; 1534 $styles->default_dirs = array( '/wp-admin/', '/wp-includes/css/' ); 1535 1536 // Open Sans is no longer used by core, but may be relied upon by themes and plugins. 1537 $open_sans_font_url = ''; 1538 1539 /* 1540 * translators: If there are characters in your language that are not supported 1541 * by Open Sans, translate this to 'off'. Do not translate into your own language. 1542 */ 1543 if ( 'off' !== _x( 'on', 'Open Sans font: on or off' ) ) { 1544 $subsets = 'latin,latin-ext'; 1545 1546 /* 1547 * translators: To add an additional Open Sans character subset specific to your language, 1548 * translate this to 'greek', 'cyrillic' or 'vietnamese'. Do not translate into your own language. 1549 */ 1550 $subset = _x( 'no-subset', 'Open Sans font: add new subset (greek, cyrillic, vietnamese)' ); 1551 1552 if ( 'cyrillic' === $subset ) { 1553 $subsets .= ',cyrillic,cyrillic-ext'; 1554 } elseif ( 'greek' === $subset ) { 1555 $subsets .= ',greek,greek-ext'; 1556 } elseif ( 'vietnamese' === $subset ) { 1557 $subsets .= ',vietnamese'; 1558 } 1559 1560 // Hotlink Open Sans, for now. 1561 $open_sans_font_url = "https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,300,400,600&subset=$subsets&display=fallback"; 1562 } 1563 1564 // Register a stylesheet for the selected admin color scheme. 1565 $styles->add( 'colors', true, array( 'wp-admin', 'buttons' ) ); 1566 1567 $suffix = SCRIPT_DEBUG ? '' : '.min'; 1568 1569 // Admin CSS. 1570 $styles->add( 'common', "/wp-admin/css/common$suffix.css" ); 1571 $styles->add( 'forms', "/wp-admin/css/forms$suffix.css" ); 1572 $styles->add( 'admin-menu', "/wp-admin/css/admin-menu$suffix.css" ); 1573 $styles->add( 'dashboard', "/wp-admin/css/dashboard$suffix.css" ); 1574 $styles->add( 'list-tables', "/wp-admin/css/list-tables$suffix.css" ); 1575 $styles->add( 'edit', "/wp-admin/css/edit$suffix.css" ); 1576 $styles->add( 'revisions', "/wp-admin/css/revisions$suffix.css" ); 1577 $styles->add( 'media', "/wp-admin/css/media$suffix.css" ); 1578 $styles->add( 'themes', "/wp-admin/css/themes$suffix.css" ); 1579 $styles->add( 'about', "/wp-admin/css/about$suffix.css" ); 1580 $styles->add( 'nav-menus', "/wp-admin/css/nav-menus$suffix.css" ); 1581 $styles->add( 'widgets', "/wp-admin/css/widgets$suffix.css", array( 'wp-pointer' ) ); 1582 $styles->add( 'site-icon', "/wp-admin/css/site-icon$suffix.css" ); 1583 $styles->add( 'l10n', "/wp-admin/css/l10n$suffix.css" ); 1584 $styles->add( 'code-editor', "/wp-admin/css/code-editor$suffix.css", array( 'wp-codemirror' ) ); 1585 $styles->add( 'site-health', "/wp-admin/css/site-health$suffix.css" ); 1586 1587 $styles->add( 'wp-admin', false, array( 'dashicons', 'common', 'forms', 'admin-menu', 'dashboard', 'list-tables', 'edit', 'revisions', 'media', 'themes', 'about', 'nav-menus', 'widgets', 'site-icon', 'l10n' ) ); 1588 1589 $styles->add( 'login', "/wp-admin/css/login$suffix.css", array( 'dashicons', 'buttons', 'forms', 'l10n' ) ); 1590 $styles->add( 'install', "/wp-admin/css/install$suffix.css", array( 'dashicons', 'buttons', 'forms', 'l10n' ) ); 1591 $styles->add( 'wp-color-picker', "/wp-admin/css/color-picker$suffix.css" ); 1592 $styles->add( 'customize-controls', "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'imgareaselect' ) ); 1593 $styles->add( 'customize-widgets', "/wp-admin/css/customize-widgets$suffix.css", array( 'wp-admin', 'colors' ) ); 1594 $styles->add( 'customize-nav-menus', "/wp-admin/css/customize-nav-menus$suffix.css", array( 'wp-admin', 'colors' ) ); 1595 1596 // Common dependencies. 1597 $styles->add( 'buttons', "/wp-includes/css/buttons$suffix.css" ); 1598 $styles->add( 'dashicons', "/wp-includes/css/dashicons$suffix.css" ); 1599 1600 // Includes CSS. 1601 $styles->add( 'admin-bar', "/wp-includes/css/admin-bar$suffix.css", array( 'dashicons' ) ); 1602 $styles->add( 'wp-auth-check', "/wp-includes/css/wp-auth-check$suffix.css", array( 'dashicons' ) ); 1603 $styles->add( 'editor-buttons', "/wp-includes/css/editor$suffix.css", array( 'dashicons' ) ); 1604 $styles->add( 'media-views', "/wp-includes/css/media-views$suffix.css", array( 'buttons', 'dashicons', 'wp-mediaelement' ) ); 1605 $styles->add( 'wp-pointer', "/wp-includes/css/wp-pointer$suffix.css", array( 'dashicons' ) ); 1606 $styles->add( 'customize-preview', "/wp-includes/css/customize-preview$suffix.css", array( 'dashicons' ) ); 1607 $styles->add( 'wp-empty-template-alert', "/wp-includes/css/wp-empty-template-alert$suffix.css" ); 1608 $skip_link_style_path = WPINC . "/css/wp-block-template-skip-link$suffix.css"; 1609 $styles->add( 'wp-block-template-skip-link', "/$skip_link_style_path" ); 1610 $styles->add_data( 'wp-block-template-skip-link', 'path', ABSPATH . $skip_link_style_path ); 1611 1612 // External libraries and friends. 1613 $styles->add( 'imgareaselect', '/wp-includes/js/imgareaselect/imgareaselect.css', array(), '0.9.8' ); 1614 $styles->add( 'wp-jquery-ui-dialog', "/wp-includes/css/jquery-ui-dialog$suffix.css", array( 'dashicons' ) ); 1615 $styles->add( 'mediaelement', '/wp-includes/js/mediaelement/mediaelementplayer-legacy.min.css', array(), '4.2.17' ); 1616 $styles->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement$suffix.css", array( 'mediaelement' ) ); 1617 $styles->add( 'thickbox', '/wp-includes/js/thickbox/thickbox.css', array( 'dashicons' ) ); 1618 $styles->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.css', array(), '5.29.1-alpha-ee20357' ); 1619 1620 // Deprecated CSS. 1621 $styles->add( 'deprecated-media', "/wp-admin/css/deprecated-media$suffix.css" ); 1622 $styles->add( 'farbtastic', "/wp-admin/css/farbtastic$suffix.css", array(), '1.3u1' ); 1623 $styles->add( 'jcrop', '/wp-includes/js/jcrop/jquery.Jcrop.min.css', array(), '0.9.15' ); 1624 $styles->add( 'colors-fresh', false, array( 'wp-admin', 'buttons' ) ); // Old handle. 1625 $styles->add( 'open-sans', $open_sans_font_url ); // No longer used in core as of 4.6. 1626 $styles->add( 'wp-embed-template-ie', false ); 1627 $styles->add_data( 'wp-embed-template-ie', 'conditional', '_required-conditional-dependency_' ); 1628 1629 // Noto Serif is no longer used by core, but may be relied upon by themes and plugins. 1630 $fonts_url = ''; 1631 1632 /* 1633 * translators: Use this to specify the proper Google Font name and variants 1634 * to load that is supported by your language. Do not translate. 1635 * Set to 'off' to disable loading. 1636 */ 1637 $font_family = _x( 'Noto Serif:400,400i,700,700i', 'Google Font Name and Variants' ); 1638 if ( 'off' !== $font_family ) { 1639 $fonts_url = 'https://fonts.googleapis.com/css?family=' . urlencode( $font_family ); 1640 } 1641 $styles->add( 'wp-editor-font', $fonts_url ); // No longer used in core as of 5.7. 1642 $block_library_theme_path = WPINC . "/css/dist/block-library/theme$suffix.css"; 1643 $styles->add( 'wp-block-library-theme', "/$block_library_theme_path" ); 1644 $styles->add_data( 'wp-block-library-theme', 'path', ABSPATH . $block_library_theme_path ); 1645 1646 $classic_theme_styles_path = WPINC . "/css/classic-themes$suffix.css"; 1647 $styles->add( 'classic-theme-styles', "/$classic_theme_styles_path" ); 1648 $styles->add_data( 'classic-theme-styles', 'path', ABSPATH . $classic_theme_styles_path ); 1649 1650 $styles->add( 1651 'wp-reset-editor-styles', 1652 "/wp-includes/css/dist/block-library/reset$suffix.css", 1653 array( 'common', 'forms' ) // Make sure the reset is loaded after the default WP Admin styles. 1654 ); 1655 1656 $styles->add( 1657 'wp-editor-classic-layout-styles', 1658 "/wp-includes/css/dist/edit-post/classic$suffix.css", 1659 array() 1660 ); 1661 1662 $styles->add( 1663 'wp-block-editor-content', 1664 "/wp-includes/css/dist/block-editor/content$suffix.css", 1665 array( 'wp-components' ) 1666 ); 1667 1668 // Only add CONTENT styles here that should be enqueued in the iframe! 1669 $wp_edit_blocks_dependencies = array( 1670 'wp-components', 1671 /* 1672 * This needs to be added before the block library styles, 1673 * The block library styles override the "reset" styles. 1674 */ 1675 'wp-reset-editor-styles', 1676 'wp-block-library', 1677 'wp-block-editor-content', 1678 ); 1679 1680 // Only load the default layout and margin styles for themes without theme.json file. 1681 if ( ! wp_theme_has_theme_json() ) { 1682 $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles'; 1683 } 1684 1685 if ( 1686 current_theme_supports( 'wp-block-styles' ) && 1687 ( ! is_array( $editor_styles ) || count( $editor_styles ) === 0 ) 1688 ) { 1689 /* 1690 * Include opinionated block styles if the theme supports block styles and 1691 * no $editor_styles are declared, so the editor never appears broken. 1692 */ 1693 $wp_edit_blocks_dependencies[] = 'wp-block-library-theme'; 1694 } 1695 1696 $styles->add( 1697 'wp-edit-blocks', 1698 "/wp-includes/css/dist/block-library/editor$suffix.css", 1699 $wp_edit_blocks_dependencies 1700 ); 1701 1702 $package_styles = array( 1703 'block-editor' => array( 'wp-components', 'wp-preferences' ), 1704 'block-library' => array(), 1705 'block-directory' => array(), 1706 'components' => array(), 1707 'commands' => array( 'wp-components' ), 1708 'edit-post' => array( 1709 'wp-components', 1710 'wp-block-editor', 1711 'wp-editor', 1712 'wp-edit-blocks', 1713 'wp-block-library', 1714 'wp-commands', 1715 'wp-preferences', 1716 ), 1717 'editor' => array( 1718 'wp-components', 1719 'wp-block-editor', 1720 'wp-reusable-blocks', 1721 'wp-patterns', 1722 'wp-preferences', 1723 ), 1724 'format-library' => array(), 1725 'list-reusable-blocks' => array( 'wp-components' ), 1726 'reusable-blocks' => array( 'wp-components' ), 1727 'patterns' => array( 'wp-components' ), 1728 'preferences' => array( 'wp-components' ), 1729 'nux' => array( 'wp-components' ), 1730 'widgets' => array( 1731 'wp-components', 1732 ), 1733 'edit-widgets' => array( 1734 'wp-widgets', 1735 'wp-block-editor', 1736 'wp-editor', 1737 'wp-edit-blocks', 1738 'wp-block-library', 1739 'wp-patterns', 1740 'wp-preferences', 1741 ), 1742 'customize-widgets' => array( 1743 'wp-widgets', 1744 'wp-block-editor', 1745 'wp-editor', 1746 'wp-edit-blocks', 1747 'wp-block-library', 1748 'wp-patterns', 1749 'wp-preferences', 1750 ), 1751 'edit-site' => array( 1752 'wp-components', 1753 'wp-block-editor', 1754 'wp-editor', 1755 'wp-edit-blocks', 1756 'wp-commands', 1757 'wp-preferences', 1758 ), 1759 ); 1760 1761 foreach ( $package_styles as $package => $dependencies ) { 1762 $handle = 'wp-' . $package; 1763 $path = "/wp-includes/css/dist/$package/style$suffix.css"; 1764 1765 if ( 'block-library' === $package && wp_should_load_separate_core_block_assets() ) { 1766 $path = "/wp-includes/css/dist/$package/common$suffix.css"; 1767 } 1768 $styles->add( $handle, $path, $dependencies ); 1769 $styles->add_data( $handle, 'path', ABSPATH . $path ); 1770 } 1771 1772 // RTL CSS. 1773 $rtl_styles = array( 1774 // Admin CSS. 1775 'common', 1776 'forms', 1777 'admin-menu', 1778 'dashboard', 1779 'list-tables', 1780 'edit', 1781 'revisions', 1782 'media', 1783 'themes', 1784 'about', 1785 'nav-menus', 1786 'widgets', 1787 'site-icon', 1788 'l10n', 1789 'install', 1790 'wp-color-picker', 1791 'customize-controls', 1792 'customize-widgets', 1793 'customize-nav-menus', 1794 'customize-preview', 1795 'login', 1796 'site-health', 1797 'wp-empty-template-alert', 1798 // Includes CSS. 1799 'buttons', 1800 'admin-bar', 1801 'wp-auth-check', 1802 'editor-buttons', 1803 'media-views', 1804 'wp-pointer', 1805 'wp-jquery-ui-dialog', 1806 'wp-block-template-skip-link', 1807 // Package styles. 1808 'wp-reset-editor-styles', 1809 'wp-editor-classic-layout-styles', 1810 'wp-block-library-theme', 1811 'wp-edit-blocks', 1812 'wp-block-editor', 1813 'wp-block-library', 1814 'wp-block-directory', 1815 'wp-commands', 1816 'wp-components', 1817 'wp-customize-widgets', 1818 'wp-edit-post', 1819 'wp-edit-site', 1820 'wp-edit-widgets', 1821 'wp-editor', 1822 'wp-format-library', 1823 'wp-list-reusable-blocks', 1824 'wp-reusable-blocks', 1825 'wp-patterns', 1826 'wp-nux', 1827 'wp-widgets', 1828 // Deprecated CSS. 1829 'deprecated-media', 1830 'farbtastic', 1831 ); 1832 1833 foreach ( $rtl_styles as $rtl_style ) { 1834 $styles->add_data( $rtl_style, 'rtl', 'replace' ); 1835 if ( $suffix ) { 1836 $styles->add_data( $rtl_style, 'suffix', $suffix ); 1837 } 1838 } 1839 } 1840 1841 /** 1842 * Reorders JavaScript scripts array to place prototype before jQuery. 1843 * 1844 * @since 2.3.1 1845 * 1846 * @param string[] $js_array JavaScript scripts array 1847 * @return string[] Reordered array, if needed. 1848 */ 1849 function wp_prototype_before_jquery( $js_array ) { 1850 $prototype = array_search( 'prototype', $js_array, true ); 1851 1852 if ( false === $prototype ) { 1853 return $js_array; 1854 } 1855 1856 $jquery = array_search( 'jquery', $js_array, true ); 1857 1858 if ( false === $jquery ) { 1859 return $js_array; 1860 } 1861 1862 if ( $prototype < $jquery ) { 1863 return $js_array; 1864 } 1865 1866 unset( $js_array[ $prototype ] ); 1867 1868 array_splice( $js_array, $jquery, 0, 'prototype' ); 1869 1870 return $js_array; 1871 } 1872 1873 /** 1874 * Loads localized data on print rather than initialization. 1875 * 1876 * These localizations require information that may not be loaded even by init. 1877 * 1878 * @since 2.5.0 1879 * 1880 * @global array $shortcode_tags 1881 */ 1882 function wp_just_in_time_script_localization() { 1883 1884 wp_localize_script( 1885 'autosave', 1886 'autosaveL10n', 1887 array( 1888 'autosaveInterval' => AUTOSAVE_INTERVAL, 1889 'blog_id' => get_current_blog_id(), 1890 ) 1891 ); 1892 1893 wp_localize_script( 1894 'mce-view', 1895 'mceViewL10n', 1896 array( 1897 'shortcodes' => ! empty( $GLOBALS['shortcode_tags'] ) ? array_keys( $GLOBALS['shortcode_tags'] ) : array(), 1898 ) 1899 ); 1900 1901 wp_localize_script( 1902 'word-count', 1903 'wordCountL10n', 1904 array( 1905 'type' => wp_get_word_count_type(), 1906 'shortcodes' => ! empty( $GLOBALS['shortcode_tags'] ) ? array_keys( $GLOBALS['shortcode_tags'] ) : array(), 1907 ) 1908 ); 1909 } 1910 1911 /** 1912 * Localizes the jQuery UI datepicker. 1913 * 1914 * @since 4.6.0 1915 * 1916 * @link https://api.jqueryui.com/datepicker/#options 1917 * 1918 * @global WP_Locale $wp_locale WordPress date and time locale object. 1919 */ 1920 function wp_localize_jquery_ui_datepicker() { 1921 global $wp_locale; 1922 1923 if ( ! wp_script_is( 'jquery-ui-datepicker', 'enqueued' ) ) { 1924 return; 1925 } 1926 1927 // Convert the PHP date format into jQuery UI's format. 1928 $datepicker_date_format = str_replace( 1929 array( 1930 'd', 1931 'j', 1932 'l', 1933 'z', // Day. 1934 'F', 1935 'M', 1936 'n', 1937 'm', // Month. 1938 'Y', 1939 'y', // Year. 1940 ), 1941 array( 1942 'dd', 1943 'd', 1944 'DD', 1945 'o', 1946 'MM', 1947 'M', 1948 'm', 1949 'mm', 1950 'yy', 1951 'y', 1952 ), 1953 get_option( 'date_format' ) 1954 ); 1955 1956 $datepicker_defaults = wp_json_encode( 1957 array( 1958 'closeText' => __( 'Close' ), 1959 'currentText' => __( 'Today' ), 1960 'monthNames' => array_values( $wp_locale->month ), 1961 'monthNamesShort' => array_values( $wp_locale->month_abbrev ), 1962 'nextText' => __( 'Next' ), 1963 'prevText' => __( 'Previous' ), 1964 'dayNames' => array_values( $wp_locale->weekday ), 1965 'dayNamesShort' => array_values( $wp_locale->weekday_abbrev ), 1966 'dayNamesMin' => array_values( $wp_locale->weekday_initial ), 1967 'dateFormat' => $datepicker_date_format, 1968 'firstDay' => absint( get_option( 'start_of_week' ) ), 1969 'isRTL' => $wp_locale->is_rtl(), 1970 ), 1971 JSON_HEX_TAG | JSON_UNESCAPED_SLASHES 1972 ); 1973 1974 wp_add_inline_script( 'jquery-ui-datepicker', "jQuery(function(jQuery){jQuery.datepicker.setDefaults({$datepicker_defaults});});" ); 1975 } 1976 1977 /** 1978 * Localizes community events data that needs to be passed to dashboard.js. 1979 * 1980 * @since 4.8.0 1981 */ 1982 function wp_localize_community_events() { 1983 if ( ! wp_script_is( 'dashboard' ) ) { 1984 return; 1985 } 1986 1987 require_once ABSPATH . 'wp-admin/includes/class-wp-community-events.php'; 1988 1989 $user_id = get_current_user_id(); 1990 $saved_location = get_user_option( 'community-events-location', $user_id ); 1991 $saved_ip_address = $saved_location['ip'] ?? false; 1992 $current_ip_address = WP_Community_Events::get_unsafe_client_ip(); 1993 1994 /* 1995 * If the user's location is based on their IP address, then update their 1996 * location when their IP address changes. This allows them to see events 1997 * in their current city when travelling. Otherwise, they would always be 1998 * shown events in the city where they were when they first loaded the 1999 * Dashboard, which could have been months or years ago. 2000 */ 2001 if ( $saved_ip_address && $current_ip_address && $current_ip_address !== $saved_ip_address ) { 2002 $saved_location['ip'] = $current_ip_address; 2003 update_user_meta( $user_id, 'community-events-location', $saved_location ); 2004 } 2005 2006 $events_client = new WP_Community_Events( $user_id, $saved_location ); 2007 2008 wp_localize_script( 2009 'dashboard', 2010 'communityEventsData', 2011 array( 2012 'nonce' => wp_create_nonce( 'community_events' ), 2013 'cache' => $events_client->get_cached_events(), 2014 'time_format' => get_option( 'time_format' ), 2015 ) 2016 ); 2017 } 2018 2019 /** 2020 * Administration Screen CSS for changing the styles. 2021 * 2022 * If installing the 'wp-admin/' directory will be replaced with './'. 2023 * 2024 * The $_wp_admin_css_colors global manages the Administration Screens CSS 2025 * stylesheet that is loaded. The option that is set is 'admin_color' and is the 2026 * color and key for the array. The value for the color key is an object with 2027 * a 'url' parameter that has the URL path to the CSS file. 2028 * 2029 * The query from $src parameter will be appended to the URL that is given from 2030 * the $_wp_admin_css_colors array value URL. 2031 * 2032 * @since 2.6.0 2033 * 2034 * @global array $_wp_admin_css_colors 2035 * 2036 * @param string $src Source URL. 2037 * @param string $handle Either 'colors' or 'colors-rtl'. 2038 * @return string|false URL path to CSS stylesheet for Administration Screens. 2039 */ 2040 function wp_style_loader_src( $src, $handle ) { 2041 global $_wp_admin_css_colors; 2042 2043 if ( wp_installing() ) { 2044 return preg_replace( '#^wp-admin/#', './', $src ); 2045 } 2046 2047 if ( 'colors' === $handle ) { 2048 $color = get_user_option( 'admin_color' ); 2049 2050 if ( empty( $color ) || ! isset( $_wp_admin_css_colors[ $color ] ) ) { 2051 $color = 'fresh'; 2052 } 2053 2054 $color = $_wp_admin_css_colors[ $color ] ?? null; 2055 $url = $color->url ?? ''; 2056 2057 if ( ! $url ) { 2058 return false; 2059 } 2060 2061 $parsed = parse_url( $src ); 2062 if ( isset( $parsed['query'] ) && $parsed['query'] ) { 2063 wp_parse_str( $parsed['query'], $qv ); 2064 $url = add_query_arg( $qv, $url ); 2065 } 2066 2067 return $url; 2068 } 2069 2070 return $src; 2071 } 2072 2073 /** 2074 * Prints the script queue in the HTML head on admin pages. 2075 * 2076 * Postpones the scripts that were queued for the footer. 2077 * print_footer_scripts() is called in the footer to print these scripts. 2078 * 2079 * @since 2.8.0 2080 * 2081 * @see wp_print_scripts() 2082 * 2083 * @global bool $concatenate_scripts 2084 * 2085 * @return string[] Handles of the scripts that were printed. 2086 */ 2087 function print_head_scripts() { 2088 global $concatenate_scripts; 2089 2090 if ( ! did_action( 'wp_print_scripts' ) ) { 2091 /** This action is documented in wp-includes/functions.wp-scripts.php */ 2092 do_action( 'wp_print_scripts' ); 2093 } 2094 2095 $wp_scripts = wp_scripts(); 2096 2097 script_concat_settings(); 2098 $wp_scripts->do_concat = $concatenate_scripts; 2099 $wp_scripts->do_head_items(); 2100 2101 /** 2102 * Filters whether to print the head scripts. 2103 * 2104 * @since 2.8.0 2105 * 2106 * @param bool $print Whether to print the head scripts. Default true. 2107 */ 2108 if ( apply_filters( 'print_head_scripts', true ) ) { 2109 _print_scripts(); 2110 } 2111 2112 $wp_scripts->reset(); 2113 return $wp_scripts->done; 2114 } 2115 2116 /** 2117 * Prints the scripts that were queued for the footer or too late for the HTML head. 2118 * 2119 * @since 2.8.0 2120 * 2121 * @global WP_Scripts $wp_scripts 2122 * @global bool $concatenate_scripts 2123 * 2124 * @return string[] Handles of the scripts that were printed. 2125 */ 2126 function print_footer_scripts() { 2127 global $wp_scripts, $concatenate_scripts; 2128 2129 if ( ! ( $wp_scripts instanceof WP_Scripts ) ) { 2130 return array(); // No need to run if not instantiated. 2131 } 2132 script_concat_settings(); 2133 $wp_scripts->do_concat = $concatenate_scripts; 2134 $wp_scripts->do_footer_items(); 2135 2136 /** 2137 * Filters whether to print the footer scripts. 2138 * 2139 * @since 2.8.0 2140 * 2141 * @param bool $print Whether to print the footer scripts. Default true. 2142 */ 2143 if ( apply_filters( 'print_footer_scripts', true ) ) { 2144 _print_scripts(); 2145 } 2146 2147 $wp_scripts->reset(); 2148 return $wp_scripts->done; 2149 } 2150 2151 /** 2152 * Prints scripts (internal use only) 2153 * 2154 * @since 2.8.0 2155 * 2156 * @ignore 2157 * 2158 * @global WP_Scripts $wp_scripts 2159 * @global bool $compress_scripts 2160 */ 2161 function _print_scripts() { 2162 global $wp_scripts, $compress_scripts; 2163 2164 $zip = $compress_scripts ? 1 : 0; 2165 if ( $zip && defined( 'ENFORCE_GZIP' ) && ENFORCE_GZIP ) { 2166 $zip = 'gzip'; 2167 } 2168 2169 $concat = trim( $wp_scripts->concat, ', ' ); 2170 2171 if ( $concat ) { 2172 if ( ! empty( $wp_scripts->print_code ) ) { 2173 echo "\n<script>\n"; 2174 echo $wp_scripts->print_code; 2175 echo sprintf( "\n//# sourceURL=%s\n", rawurlencode( 'js-inline-concat-' . $concat ) ); 2176 echo "</script>\n"; 2177 } 2178 2179 $concat = str_split( $concat, 128 ); 2180 $concatenated = ''; 2181 2182 foreach ( $concat as $key => $chunk ) { 2183 $concatenated .= "&load%5Bchunk_{$key}%5D={$chunk}"; 2184 } 2185 2186 $src = $wp_scripts->base_url . "/wp-admin/load-scripts.php?c={$zip}" . $concatenated . '&ver=' . $wp_scripts->default_version; 2187 echo "<script src='" . esc_attr( $src ) . "'></script>\n"; 2188 } 2189 2190 if ( ! empty( $wp_scripts->print_html ) ) { 2191 echo $wp_scripts->print_html; 2192 } 2193 } 2194 2195 /** 2196 * Prints the script queue in the HTML head on the front end. 2197 * 2198 * Postpones the scripts that were queued for the footer. 2199 * wp_print_footer_scripts() is called in the footer to print these scripts. 2200 * 2201 * @since 2.8.0 2202 * 2203 * @global WP_Scripts $wp_scripts 2204 * 2205 * @return string[] Handles of the scripts that were printed. 2206 */ 2207 function wp_print_head_scripts() { 2208 global $wp_scripts; 2209 2210 if ( ! did_action( 'wp_print_scripts' ) ) { 2211 /** This action is documented in wp-includes/functions.wp-scripts.php */ 2212 do_action( 'wp_print_scripts' ); 2213 } 2214 2215 if ( ! ( $wp_scripts instanceof WP_Scripts ) ) { 2216 return array(); // No need to run if nothing is queued. 2217 } 2218 2219 return print_head_scripts(); 2220 } 2221 2222 /** 2223 * Private, for use in *_footer_scripts hooks 2224 * 2225 * In classic themes, when block styles are loaded on demand via wp_load_classic_theme_block_styles_on_demand(), 2226 * this function is replaced by a closure in wp_hoist_late_printed_styles() which will capture the printing of 2227 * two sets of "late" styles to be hoisted to the HEAD by means of the template enhancement output buffer: 2228 * 2229 * 1. Styles related to blocks are inserted right after the wp-block-library stylesheet. 2230 * 2. All other styles are appended to the end of the HEAD. 2231 * 2232 * The closure calls print_footer_scripts() to print scripts in the footer as usual. 2233 * 2234 * @since 3.3.0 2235 */ 2236 function _wp_footer_scripts() { 2237 print_late_styles(); 2238 print_footer_scripts(); 2239 } 2240 2241 /** 2242 * Hooks to print the scripts and styles in the footer. 2243 * 2244 * @since 2.8.0 2245 */ 2246 function wp_print_footer_scripts() { 2247 /** 2248 * Fires when footer scripts are printed. 2249 * 2250 * @since 2.8.0 2251 */ 2252 do_action( 'wp_print_footer_scripts' ); 2253 } 2254 2255 /** 2256 * Wrapper for do_action( 'wp_enqueue_scripts' ). 2257 * 2258 * Allows plugins to queue scripts for the front end using wp_enqueue_script(). 2259 * Runs first in wp_head() where all is_home(), is_page(), etc. functions are available. 2260 * 2261 * @since 2.8.0 2262 */ 2263 function wp_enqueue_scripts() { 2264 /** 2265 * Fires when scripts and styles are enqueued. 2266 * 2267 * @since 2.8.0 2268 */ 2269 do_action( 'wp_enqueue_scripts' ); 2270 } 2271 2272 /** 2273 * Prints the styles queue in the HTML head on admin pages. 2274 * 2275 * @since 2.8.0 2276 * 2277 * @global bool $concatenate_scripts 2278 * 2279 * @return string[] Handles of the styles that were printed. 2280 */ 2281 function print_admin_styles() { 2282 global $concatenate_scripts; 2283 2284 $wp_styles = wp_styles(); 2285 2286 script_concat_settings(); 2287 $wp_styles->do_concat = $concatenate_scripts; 2288 $wp_styles->do_items( false ); 2289 2290 /** 2291 * Filters whether to print the admin styles. 2292 * 2293 * @since 2.8.0 2294 * 2295 * @param bool $print Whether to print the admin styles. Default true. 2296 */ 2297 if ( apply_filters( 'print_admin_styles', true ) ) { 2298 _print_styles(); 2299 } 2300 2301 $wp_styles->reset(); 2302 return $wp_styles->done; 2303 } 2304 2305 /** 2306 * Prints the styles that were queued too late for the HTML head. 2307 * 2308 * @since 3.3.0 2309 * 2310 * @global WP_Styles $wp_styles 2311 * @global bool $concatenate_scripts 2312 * 2313 * @return string[]|void 2314 */ 2315 function print_late_styles() { 2316 global $wp_styles, $concatenate_scripts; 2317 2318 if ( ! ( $wp_styles instanceof WP_Styles ) ) { 2319 return; 2320 } 2321 2322 script_concat_settings(); 2323 $wp_styles->do_concat = $concatenate_scripts; 2324 $wp_styles->do_footer_items(); 2325 2326 /** 2327 * Filters whether to print the styles queued too late for the HTML head. 2328 * 2329 * @since 3.3.0 2330 * 2331 * @param bool $print Whether to print the 'late' styles. Default true. 2332 */ 2333 if ( apply_filters( 'print_late_styles', true ) ) { 2334 _print_styles(); 2335 } 2336 2337 $wp_styles->reset(); 2338 return $wp_styles->done; 2339 } 2340 2341 /** 2342 * Prints styles (internal use only). 2343 * 2344 * @ignore 2345 * @since 3.3.0 2346 * 2347 * @global bool $compress_css 2348 */ 2349 function _print_styles() { 2350 global $compress_css; 2351 2352 $wp_styles = wp_styles(); 2353 2354 $zip = $compress_css ? 1 : 0; 2355 if ( $zip && defined( 'ENFORCE_GZIP' ) && ENFORCE_GZIP ) { 2356 $zip = 'gzip'; 2357 } 2358 2359 $concat = trim( $wp_styles->concat, ', ' ); 2360 2361 if ( $concat ) { 2362 $dir = $wp_styles->text_direction; 2363 $ver = $wp_styles->default_version; 2364 2365 $concat_source_url = 'css-inline-concat-' . $concat; 2366 $concat = str_split( $concat, 128 ); 2367 $concatenated = ''; 2368 2369 foreach ( $concat as $key => $chunk ) { 2370 $concatenated .= "&load%5Bchunk_{$key}%5D={$chunk}"; 2371 } 2372 2373 $href = $wp_styles->base_url . "/wp-admin/load-styles.php?c={$zip}&dir={$dir}" . $concatenated . '&ver=' . $ver; 2374 echo "<link rel='stylesheet' href='" . esc_attr( $href ) . "' media='all' />\n"; 2375 2376 if ( ! empty( $wp_styles->print_code ) ) { 2377 $processor = new WP_HTML_Tag_Processor( '<style></style>' ); 2378 $processor->next_tag(); 2379 $style_tag_contents = "\n{$wp_styles->print_code}\n" 2380 . sprintf( "/*# sourceURL=%s */\n", rawurlencode( $concat_source_url ) ); 2381 $processor->set_modifiable_text( $style_tag_contents ); 2382 echo "{$processor->get_updated_html()}\n"; 2383 } 2384 } 2385 2386 if ( ! empty( $wp_styles->print_html ) ) { 2387 echo $wp_styles->print_html; 2388 } 2389 } 2390 2391 /** 2392 * Determines the concatenation and compression settings for scripts and styles. 2393 * 2394 * @since 2.8.0 2395 * 2396 * @global bool $concatenate_scripts 2397 * @global bool $compress_scripts 2398 * @global bool $compress_css 2399 */ 2400 function script_concat_settings() { 2401 global $concatenate_scripts, $compress_scripts, $compress_css; 2402 2403 $compressed_output = ( ini_get( 'zlib.output_compression' ) || 'ob_gzhandler' === ini_get( 'output_handler' ) ); 2404 2405 $can_compress_scripts = ! wp_installing() && get_site_option( 'can_compress_scripts' ); 2406 2407 if ( ! isset( $concatenate_scripts ) ) { 2408 $concatenate_scripts = defined( 'CONCATENATE_SCRIPTS' ) ? CONCATENATE_SCRIPTS : true; 2409 if ( ( ! is_admin() && ! did_action( 'login_init' ) ) || ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ) { 2410 $concatenate_scripts = false; 2411 } 2412 } 2413 2414 if ( ! isset( $compress_scripts ) ) { 2415 $compress_scripts = defined( 'COMPRESS_SCRIPTS' ) ? COMPRESS_SCRIPTS : true; 2416 if ( $compress_scripts && ( ! $can_compress_scripts || $compressed_output ) ) { 2417 $compress_scripts = false; 2418 } 2419 } 2420 2421 if ( ! isset( $compress_css ) ) { 2422 $compress_css = defined( 'COMPRESS_CSS' ) ? COMPRESS_CSS : true; 2423 if ( $compress_css && ( ! $can_compress_scripts || $compressed_output ) ) { 2424 $compress_css = false; 2425 } 2426 } 2427 } 2428 2429 /** 2430 * Handles the enqueueing of block scripts and styles that are common to both 2431 * the editor and the front-end. 2432 * 2433 * @since 5.0.0 2434 */ 2435 function wp_common_block_scripts_and_styles() { 2436 if ( is_admin() && ! wp_should_load_block_editor_scripts_and_styles() ) { 2437 return; 2438 } 2439 2440 wp_enqueue_style( 'wp-block-library' ); 2441 2442 if ( current_theme_supports( 'wp-block-styles' ) && ! wp_should_load_separate_core_block_assets() ) { 2443 wp_enqueue_style( 'wp-block-library-theme' ); 2444 } 2445 2446 /** 2447 * Fires after enqueuing block assets for both editor and front-end. 2448 * 2449 * Call `add_action` on any hook before 'wp_enqueue_scripts'. 2450 * 2451 * In the function call you supply, simply use `wp_enqueue_script` and 2452 * `wp_enqueue_style` to add your functionality to the Gutenberg editor. 2453 * 2454 * @since 5.0.0 2455 */ 2456 do_action( 'enqueue_block_assets' ); 2457 } 2458 2459 /** 2460 * Applies a filter to the list of style nodes that comes from WP_Theme_JSON::get_style_nodes(). 2461 * 2462 * This particular filter removes all of the blocks from the array. 2463 * 2464 * We want WP_Theme_JSON to be ignorant of the implementation details of how the CSS is being used. 2465 * This filter allows us to modify the output of WP_Theme_JSON depending on whether or not we are 2466 * loading separate assets, without making the class aware of that detail. 2467 * 2468 * @since 6.1.0 2469 * 2470 * @param array<array<string, mixed>> $nodes The nodes to filter. 2471 * @return array<array<string, mixed>> A filtered array of style nodes. 2472 */ 2473 function wp_filter_out_block_nodes( $nodes ) { 2474 return array_filter( 2475 $nodes, 2476 static function ( $node ) { 2477 return ! in_array( 'blocks', $node['path'], true ); 2478 }, 2479 ARRAY_FILTER_USE_BOTH 2480 ); 2481 } 2482 2483 /** 2484 * Enqueues the global styles defined via theme.json. 2485 * 2486 * @since 5.8.0 2487 */ 2488 function wp_enqueue_global_styles() { 2489 $assets_on_demand = wp_should_load_block_assets_on_demand(); 2490 $is_block_theme = wp_is_block_theme(); 2491 $is_classic_theme = ! $is_block_theme; 2492 2493 /* 2494 * Global styles should be printed in the head for block themes, or for classic themes when loading assets on 2495 * demand is disabled, which is the default. 2496 * The footer should only be used for classic themes when loading assets on demand is enabled. 2497 * 2498 * See https://core.trac.wordpress.org/ticket/53494 and https://core.trac.wordpress.org/ticket/61965. 2499 */ 2500 if ( 2501 ( $is_block_theme && doing_action( 'wp_footer' ) ) || 2502 ( $is_classic_theme && doing_action( 'wp_footer' ) && ! $assets_on_demand ) || 2503 ( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) && $assets_on_demand ) 2504 ) { 2505 return; 2506 } 2507 2508 /* 2509 * If loading the CSS for each block separately, then load the theme.json CSS conditionally. 2510 * This removes the CSS from the global-styles stylesheet and adds it to the inline CSS for each block. 2511 * This filter must be registered before calling wp_get_global_stylesheet(); 2512 */ 2513 add_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' ); 2514 2515 $stylesheet = wp_get_global_stylesheet(); 2516 2517 /* 2518 * For block themes, merge Customizer's custom CSS into the global styles stylesheet 2519 * before the global styles custom CSS, ensuring proper cascade order. 2520 * For classic themes, let the Customizer CSS print separately via wp_custom_css_cb() 2521 * at priority 101 in wp_head, preserving its position at the end of the <head>. 2522 */ 2523 if ( $is_block_theme ) { 2524 /* 2525 * Dequeue the Customizer's custom CSS 2526 * and add it before the global styles custom CSS. 2527 */ 2528 remove_action( 'wp_head', 'wp_custom_css_cb', 101 ); 2529 2530 /* 2531 * Get the custom CSS from the Customizer and add it to the global stylesheet. 2532 * Always do this in Customizer preview for the sake of live preview since it be empty. 2533 */ 2534 $custom_css = trim( wp_get_custom_css() ); 2535 if ( $custom_css || is_customize_preview() ) { 2536 if ( is_customize_preview() ) { 2537 /* 2538 * When in the Customizer preview, wrap the Custom CSS in milestone comments to allow customize-preview.js 2539 * to locate the CSS to replace for live previewing. Make sure that the milestone comments are omitted from 2540 * the stored Custom CSS if by chance someone tried to add them, which would be highly unlikely, but it 2541 * would break live previewing. 2542 */ 2543 $before_milestone = '/*BEGIN_CUSTOMIZER_CUSTOM_CSS*/'; 2544 $after_milestone = '/*END_CUSTOMIZER_CUSTOM_CSS*/'; 2545 $custom_css = str_replace( array( $before_milestone, $after_milestone ), '', $custom_css ); 2546 $custom_css = $before_milestone . "\n" . $custom_css . "\n" . $after_milestone; 2547 } 2548 $custom_css = "\n" . $custom_css; 2549 } 2550 $stylesheet .= $custom_css; 2551 2552 // Add the global styles custom CSS at the end. 2553 $stylesheet .= wp_get_global_stylesheet( array( 'custom-css' ) ); 2554 } 2555 2556 if ( empty( $stylesheet ) ) { 2557 return; 2558 } 2559 2560 wp_register_style( 'global-styles', false ); 2561 wp_add_inline_style( 'global-styles', $stylesheet ); 2562 wp_enqueue_style( 'global-styles' ); 2563 2564 // Add each block as an inline css. 2565 wp_add_global_styles_for_blocks(); 2566 } 2567 2568 /** 2569 * Checks if the editor scripts and styles for all registered block types 2570 * should be enqueued on the current screen. 2571 * 2572 * @since 5.6.0 2573 * 2574 * @global WP_Screen $current_screen WordPress current screen object. 2575 * 2576 * @return bool Whether scripts and styles should be enqueued. 2577 */ 2578 function wp_should_load_block_editor_scripts_and_styles() { 2579 global $current_screen; 2580 2581 $is_block_editor_screen = ( $current_screen instanceof WP_Screen ) && $current_screen->is_block_editor(); 2582 2583 /** 2584 * Filters the flag that decides whether or not block editor scripts and styles 2585 * are going to be enqueued on the current screen. 2586 * 2587 * @since 5.6.0 2588 * 2589 * @param bool $is_block_editor_screen Current value of the flag. 2590 */ 2591 return apply_filters( 'should_load_block_editor_scripts_and_styles', $is_block_editor_screen ); 2592 } 2593 2594 /** 2595 * Checks whether separate styles should be loaded for core blocks. 2596 * 2597 * When this function returns true, other functions ensure that core blocks use their own separate stylesheets. 2598 * When this function returns false, all core blocks will use the single combined 'wp-block-library' stylesheet. 2599 * 2600 * As a side effect, the return value will by default result in block assets to be loaded on demand, via the 2601 * {@see wp_should_load_block_assets_on_demand()} function. This behavior can be separately altered via that function. 2602 * 2603 * This only affects front end and not the block editor screens. 2604 * 2605 * @since 5.8.0 2606 * @see @see wp_should_load_block_assets_on_demand() 2607 * @see wp_enqueue_registered_block_scripts_and_styles() 2608 * @see register_block_style_handle() 2609 * 2610 * @return bool Whether separate core block assets will be loaded. 2611 */ 2612 function wp_should_load_separate_core_block_assets() { 2613 if ( is_admin() || is_feed() || wp_is_rest_endpoint() ) { 2614 return false; 2615 } 2616 2617 /** 2618 * Filters whether block styles should be loaded separately. 2619 * 2620 * Returning false loads all core block assets, regardless of whether they are rendered 2621 * in a page or not. Returning true loads core block assets only when they are rendered. 2622 * 2623 * @since 5.8.0 2624 * 2625 * @param bool $load_separate_assets Whether separate assets will be loaded. 2626 * Default false (all block assets are loaded, even when not used). 2627 */ 2628 return apply_filters( 'should_load_separate_core_block_assets', false ); 2629 } 2630 2631 /** 2632 * Checks whether block styles should be loaded only on-render. 2633 * 2634 * When this function returns true, other functions ensure that blocks only load their assets on-render. 2635 * When this function returns false, all block assets are loaded regardless of whether they are rendered in a page. 2636 * 2637 * The default return value depends on the result of {@see wp_should_load_separate_core_block_assets()}, which controls 2638 * whether Core block stylesheets should be loaded separately or via a combined 'wp-block-library' stylesheet. 2639 * 2640 * This only affects front end and not the block editor screens. 2641 * 2642 * @since 6.8.0 2643 * @see wp_should_load_separate_core_block_assets() 2644 * 2645 * @return bool Whether to load block assets only when they are rendered. 2646 */ 2647 function wp_should_load_block_assets_on_demand() { 2648 if ( is_admin() || is_feed() || wp_is_rest_endpoint() ) { 2649 return false; 2650 } 2651 2652 /* 2653 * For backward compatibility, the default return value for this function is based on the return value of 2654 * `wp_should_load_separate_core_block_assets()`. Initially, this function used to control both of these concerns. 2655 */ 2656 $load_assets_on_demand = wp_should_load_separate_core_block_assets(); 2657 2658 /** 2659 * Filters whether block styles should be loaded on demand. 2660 * 2661 * Returning false loads all block assets, regardless of whether they are rendered in a page or not. 2662 * Returning true loads block assets only when they are rendered. 2663 * 2664 * The default value of the filter depends on the result of {@see wp_should_load_separate_core_block_assets()}, 2665 * which controls whether Core block stylesheets should be loaded separately or via a combined 'wp-block-library' 2666 * stylesheet. 2667 * 2668 * @since 6.8.0 2669 * 2670 * @param bool $load_assets_on_demand Whether to load block assets only when they are rendered. 2671 */ 2672 return apply_filters( 'should_load_block_assets_on_demand', $load_assets_on_demand ); 2673 } 2674 2675 /** 2676 * Enqueues registered block scripts and styles, depending on current rendered 2677 * context (only enqueuing editor scripts while in context of the editor). 2678 * 2679 * @since 5.0.0 2680 */ 2681 function wp_enqueue_registered_block_scripts_and_styles() { 2682 if ( wp_should_load_block_assets_on_demand() ) { 2683 return; 2684 } 2685 2686 $load_editor_scripts_and_styles = is_admin() && wp_should_load_block_editor_scripts_and_styles(); 2687 2688 $block_registry = WP_Block_Type_Registry::get_instance(); 2689 2690 /* 2691 * Block styles are only enqueued if they're registered. For core blocks, this is only the case if 2692 * `wp_should_load_separate_core_block_assets()` returns true. Otherwise they use the single combined 2693 * 'wp-block-library` stylesheet. See also `register_core_block_style_handles()`. 2694 * Since `wp_enqueue_style()` does not trigger warnings if the style is not registered, it is okay to not cater for 2695 * this behavior here and simply call `wp_enqueue_style()` unconditionally. 2696 */ 2697 foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) { 2698 // Front-end and editor styles. 2699 foreach ( $block_type->style_handles as $style_handle ) { 2700 wp_enqueue_style( $style_handle ); 2701 } 2702 2703 // Front-end and editor scripts. 2704 foreach ( $block_type->script_handles as $script_handle ) { 2705 wp_enqueue_script( $script_handle ); 2706 } 2707 2708 if ( $load_editor_scripts_and_styles ) { 2709 // Editor styles. 2710 foreach ( $block_type->editor_style_handles as $editor_style_handle ) { 2711 wp_enqueue_style( $editor_style_handle ); 2712 } 2713 2714 // Editor scripts. 2715 foreach ( $block_type->editor_script_handles as $editor_script_handle ) { 2716 wp_enqueue_script( $editor_script_handle ); 2717 } 2718 } 2719 } 2720 } 2721 2722 /** 2723 * Function responsible for enqueuing the styles required for block styles functionality on the editor and on the frontend. 2724 * 2725 * @since 5.3.0 2726 * 2727 * @global WP_Styles $wp_styles 2728 */ 2729 function enqueue_block_styles_assets() { 2730 global $wp_styles; 2731 2732 $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered(); 2733 2734 foreach ( $block_styles as $block_name => $styles ) { 2735 foreach ( $styles as $style_properties ) { 2736 if ( isset( $style_properties['style_handle'] ) ) { 2737 2738 // If the site loads block styles on demand, enqueue the stylesheet on render. 2739 if ( wp_should_load_block_assets_on_demand() ) { 2740 add_filter( 2741 'render_block', 2742 static function ( $html, $block ) use ( $block_name, $style_properties ) { 2743 if ( $block['blockName'] === $block_name ) { 2744 wp_enqueue_style( $style_properties['style_handle'] ); 2745 } 2746 return $html; 2747 }, 2748 10, 2749 2 2750 ); 2751 } else { 2752 wp_enqueue_style( $style_properties['style_handle'] ); 2753 } 2754 } 2755 if ( isset( $style_properties['inline_style'] ) ) { 2756 2757 // Default to "wp-block-library". 2758 $handle = 'wp-block-library'; 2759 2760 // If the site loads block styles on demand, check if the block has a stylesheet registered. 2761 if ( wp_should_load_block_assets_on_demand() ) { 2762 $block_stylesheet_handle = generate_block_asset_handle( $block_name, 'style' ); 2763 2764 if ( isset( $wp_styles->registered[ $block_stylesheet_handle ] ) ) { 2765 $handle = $block_stylesheet_handle; 2766 } 2767 } 2768 2769 // Add inline styles to the calculated handle. 2770 wp_add_inline_style( $handle, $style_properties['inline_style'] ); 2771 } 2772 } 2773 } 2774 } 2775 2776 /** 2777 * Function responsible for enqueuing the assets required for block styles functionality on the editor. 2778 * 2779 * @since 5.3.0 2780 */ 2781 function enqueue_editor_block_styles_assets() { 2782 $block_styles = WP_Block_Styles_Registry::get_instance()->get_all_registered(); 2783 2784 $register_script_lines = array( '( function() {' ); 2785 foreach ( $block_styles as $block_name => $styles ) { 2786 foreach ( $styles as $style_properties ) { 2787 $block_style = array( 2788 'name' => $style_properties['name'], 2789 'label' => $style_properties['label'], 2790 ); 2791 if ( isset( $style_properties['is_default'] ) ) { 2792 $block_style['isDefault'] = $style_properties['is_default']; 2793 } 2794 $register_script_lines[] = sprintf( 2795 ' wp.blocks.registerBlockStyle( \'%s\', %s );', 2796 $block_name, 2797 wp_json_encode( $block_style, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) 2798 ); 2799 } 2800 } 2801 $register_script_lines[] = '} )();'; 2802 $inline_script = implode( "\n", $register_script_lines ); 2803 2804 wp_register_script( 'wp-block-styles', false, array( 'wp-blocks' ), true, array( 'in_footer' => true ) ); 2805 wp_add_inline_script( 'wp-block-styles', $inline_script ); 2806 wp_enqueue_script( 'wp-block-styles' ); 2807 } 2808 2809 /** 2810 * Enqueues the assets required for the block directory within the block editor. 2811 * 2812 * @since 5.5.0 2813 */ 2814 function wp_enqueue_editor_block_directory_assets() { 2815 wp_enqueue_script( 'wp-block-directory' ); 2816 wp_enqueue_style( 'wp-block-directory' ); 2817 } 2818 2819 /** 2820 * Enqueues the assets required for the format library within the block editor. 2821 * 2822 * @since 5.8.0 2823 */ 2824 function wp_enqueue_editor_format_library_assets() { 2825 wp_enqueue_script( 'wp-format-library' ); 2826 wp_enqueue_style( 'wp-format-library' ); 2827 } 2828 2829 /** 2830 * Sanitizes an attributes array into an attributes string to be placed inside a `<script>` tag. 2831 * 2832 * Automatically injects type attribute if needed. 2833 * Used by {@see wp_get_script_tag()} and {@see wp_get_inline_script_tag()}. 2834 * 2835 * @since 5.7.0 2836 * 2837 * @param array<string, string|bool> $attributes Key-value pairs representing `<script>` tag attributes. 2838 * @return string String made of sanitized `<script>` tag attributes. 2839 */ 2840 function wp_sanitize_script_attributes( $attributes ) { 2841 $attributes_string = ''; 2842 2843 /* 2844 * If HTML5 script tag is supported, only the attribute name is added 2845 * to $attributes_string for entries with a boolean value, and that are true. 2846 */ 2847 foreach ( $attributes as $attribute_name => $attribute_value ) { 2848 if ( is_bool( $attribute_value ) ) { 2849 if ( $attribute_value ) { 2850 $attributes_string .= ' ' . esc_attr( $attribute_name ); 2851 } 2852 } else { 2853 $attributes_string .= sprintf( ' %1$s="%2$s"', esc_attr( $attribute_name ), esc_attr( $attribute_value ) ); 2854 } 2855 } 2856 2857 return $attributes_string; 2858 } 2859 2860 /** 2861 * Formats `<script>` loader tags. 2862 * 2863 * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter. 2864 * Automatically injects type attribute if needed. 2865 * 2866 * @since 5.7.0 2867 * 2868 * @param array<string, string|bool> $attributes Key-value pairs representing `<script>` tag attributes. 2869 * @return string String containing `<script>` opening and closing tags. 2870 */ 2871 function wp_get_script_tag( $attributes ) { 2872 /** 2873 * Filters attributes to be added to a script tag. 2874 * 2875 * @since 5.7.0 2876 * 2877 * @param array $attributes Key-value pairs representing `<script>` tag attributes. 2878 * Only the attribute name is added to the `<script>` tag for 2879 * entries with a boolean value, and that are true. 2880 */ 2881 $attributes = apply_filters( 'wp_script_attributes', $attributes ); 2882 2883 return sprintf( "<script%s></script>\n", wp_sanitize_script_attributes( $attributes ) ); 2884 } 2885 2886 /** 2887 * Prints formatted `<script>` loader tag. 2888 * 2889 * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_script_attributes'} filter. 2890 * Automatically injects type attribute if needed. 2891 * 2892 * @since 5.7.0 2893 * 2894 * @param array<string, string|bool> $attributes Key-value pairs representing `<script>` tag attributes. 2895 */ 2896 function wp_print_script_tag( $attributes ) { 2897 echo wp_get_script_tag( $attributes ); 2898 } 2899 2900 /** 2901 * Constructs an inline script tag. 2902 * 2903 * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_inline_script_attributes'} filter. 2904 * Automatically injects type attribute if needed. 2905 * 2906 * @since 5.7.0 2907 * 2908 * @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc. 2909 * @param array<string, string|bool> $attributes Optional. Key-value pairs representing `<script>` tag attributes. 2910 * @return string String containing inline JavaScript code wrapped around `<script>` tag. 2911 */ 2912 function wp_get_inline_script_tag( $data, $attributes = array() ) { 2913 $data = "\n" . trim( $data, "\n\r " ) . "\n"; 2914 2915 /** 2916 * Filters attributes to be added to a script tag. 2917 * 2918 * @since 5.7.0 2919 * 2920 * @param array<string, string|bool> $attributes Key-value pairs representing `<script>` tag attributes. 2921 * Only the attribute name is added to the `<script>` tag for 2922 * entries with a boolean value, and that are true. 2923 * @param string $data Inline data. 2924 */ 2925 $attributes = apply_filters( 'wp_inline_script_attributes', $attributes, $data ); 2926 2927 return sprintf( "<script%s>%s</script>\n", wp_sanitize_script_attributes( $attributes ), $data ); 2928 } 2929 2930 /** 2931 * Prints an inline script tag. 2932 * 2933 * It is possible to inject attributes in the `<script>` tag via the {@see 'wp_inline_script_attributes'} filter. 2934 * Automatically injects type attribute if needed. 2935 * 2936 * @since 5.7.0 2937 * 2938 * @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc. 2939 * @param array<string, string|bool> $attributes Optional. Key-value pairs representing `<script>` tag attributes. 2940 */ 2941 function wp_print_inline_script_tag( $data, $attributes = array() ) { 2942 echo wp_get_inline_script_tag( $data, $attributes ); 2943 } 2944 2945 /** 2946 * Allows small styles to be inlined. 2947 * 2948 * This improves performance and sustainability, and is opt-in. Stylesheets can opt in 2949 * by adding `path` data using `wp_style_add_data`, and defining the file's absolute path: 2950 * 2951 * wp_style_add_data( $style_handle, 'path', $file_path ); 2952 * 2953 * @since 5.8.0 2954 * 2955 * @global WP_Styles $wp_styles 2956 */ 2957 function wp_maybe_inline_styles() { 2958 global $wp_styles; 2959 2960 $total_inline_limit = 40000; 2961 /** 2962 * The maximum size of inlined styles in bytes. 2963 * 2964 * @since 5.8.0 2965 * @since 6.9.0 The default limit increased from 20K to 40K. 2966 * 2967 * @param int $total_inline_limit The file-size threshold, in bytes. Default 40000. 2968 */ 2969 $total_inline_limit = apply_filters( 'styles_inline_size_limit', $total_inline_limit ); 2970 2971 $styles = array(); 2972 2973 // Build an array of styles that have a path defined. 2974 foreach ( $wp_styles->queue as $handle ) { 2975 if ( ! isset( $wp_styles->registered[ $handle ] ) ) { 2976 continue; 2977 } 2978 $src = $wp_styles->registered[ $handle ]->src; 2979 $path = $wp_styles->get_data( $handle, 'path' ); 2980 if ( $path && $src ) { 2981 $size = wp_filesize( $path ); 2982 if ( 0 === $size && ! file_exists( $path ) ) { 2983 _doing_it_wrong( 2984 __FUNCTION__, 2985 sprintf( 2986 /* translators: 1: 'path', 2: filesystem path, 3: style handle */ 2987 __( 'Unable to read the "%1$s" key with value "%2$s" for stylesheet "%3$s".' ), 2988 'path', 2989 esc_html( $path ), 2990 esc_html( $handle ) 2991 ), 2992 '7.0.0' 2993 ); 2994 continue; 2995 } 2996 $styles[] = array( 2997 'handle' => $handle, 2998 'src' => $src, 2999 'path' => $path, 3000 'size' => $size, 3001 ); 3002 } 3003 } 3004 3005 if ( ! empty( $styles ) ) { 3006 // Reorder styles array based on size. 3007 usort( 3008 $styles, 3009 static function ( $a, $b ) { 3010 return $a['size'] <=> $b['size']; 3011 } 3012 ); 3013 3014 /* 3015 * The total inlined size. 3016 * 3017 * On each iteration of the loop, if a style gets added inline the value of this var increases 3018 * to reflect the total size of inlined styles. 3019 */ 3020 $total_inline_size = 0; 3021 3022 // Loop styles. 3023 foreach ( $styles as $style ) { 3024 3025 // Size check. Since styles are ordered by size, we can break the loop. 3026 if ( $total_inline_size + $style['size'] > $total_inline_limit ) { 3027 break; 3028 } 3029 3030 // Get the styles if we don't already have them. 3031 if ( ! is_readable( $style['path'] ) ) { 3032 _doing_it_wrong( 3033 __FUNCTION__, 3034 sprintf( 3035 /* translators: 1: 'path', 2: filesystem path, 3: style handle */ 3036 __( 'Unable to read the "%1$s" key with value "%2$s" for stylesheet "%3$s".' ), 3037 'path', 3038 esc_html( $style['path'] ), 3039 esc_html( $style['handle'] ) 3040 ), 3041 '7.0.0' 3042 ); 3043 continue; 3044 } 3045 $style['css'] = file_get_contents( $style['path'] ); 3046 3047 /* 3048 * Check if the style contains relative URLs that need to be modified. 3049 * URLs relative to the stylesheet's path should be converted to relative to the site's root. 3050 */ 3051 $style['css'] = _wp_normalize_relative_css_links( $style['css'], $style['src'] ); 3052 3053 // Keep track of the original `src` for the style that was inlined so that the `sourceURL` comment can be added. 3054 $wp_styles->add_data( $style['handle'], 'inlined_src', $style['src'] ); 3055 3056 // Set `src` to `false` and add styles inline. 3057 $wp_styles->registered[ $style['handle'] ]->src = false; 3058 if ( empty( $wp_styles->registered[ $style['handle'] ]->extra['after'] ) ) { 3059 $wp_styles->registered[ $style['handle'] ]->extra['after'] = array(); 3060 } 3061 array_unshift( $wp_styles->registered[ $style['handle'] ]->extra['after'], $style['css'] ); 3062 3063 // Add the styles size to the $total_inline_size var. 3064 $total_inline_size += (int) $style['size']; 3065 } 3066 } 3067 } 3068 3069 /** 3070 * Makes URLs relative to the WordPress installation. 3071 * 3072 * @since 5.9.0 3073 * @access private 3074 * 3075 * @param string $css The CSS to make URLs relative to the WordPress installation. 3076 * @param string $stylesheet_url The URL to the stylesheet. 3077 * 3078 * @return string The CSS with URLs made relative to the WordPress installation. 3079 */ 3080 function _wp_normalize_relative_css_links( $css, $stylesheet_url ) { 3081 return preg_replace_callback( 3082 '#(url\s*\(\s*[\'"]?\s*)([^\'"\)]+)#', 3083 static function ( $matches ) use ( $stylesheet_url ) { 3084 list( , $prefix, $url ) = $matches; 3085 3086 // Short-circuit if the URL does not require normalization. 3087 if ( 3088 str_starts_with( $url, 'http:' ) || 3089 str_starts_with( $url, 'https:' ) || 3090 str_starts_with( $url, '/' ) || 3091 str_starts_with( $url, '#' ) || 3092 str_starts_with( $url, 'data:' ) 3093 ) { 3094 return $matches[0]; 3095 } 3096 3097 // Build the absolute URL. 3098 $absolute_url = dirname( $stylesheet_url ) . '/' . $url; 3099 $absolute_url = str_replace( '/./', '/', $absolute_url ); 3100 3101 // Convert to URL related to the site root. 3102 $url = wp_make_link_relative( $absolute_url ); 3103 3104 return $prefix . $url; 3105 }, 3106 $css 3107 ); 3108 } 3109 3110 /** 3111 * Function that enqueues the CSS Custom Properties coming from theme.json. 3112 * 3113 * @since 5.9.0 3114 */ 3115 function wp_enqueue_global_styles_css_custom_properties() { 3116 wp_register_style( 'global-styles-css-custom-properties', false ); 3117 wp_add_inline_style( 'global-styles-css-custom-properties', wp_get_global_stylesheet( array( 'variables' ) ) ); 3118 wp_enqueue_style( 'global-styles-css-custom-properties' ); 3119 } 3120 3121 /** 3122 * Hooks inline styles in the proper place, depending on the active theme. 3123 * 3124 * @since 5.9.1 3125 * @since 6.1.0 Added the `$priority` parameter. 3126 * 3127 * For block themes, styles are loaded in the head. 3128 * For classic ones, styles are loaded in the body because the wp_head action happens before render_block. 3129 * 3130 * @link https://core.trac.wordpress.org/ticket/53494. 3131 * 3132 * @param string $style String containing the CSS styles to be added. 3133 * @param int $priority To set the priority for the add_action. 3134 */ 3135 function wp_enqueue_block_support_styles( $style, $priority = 10 ) { 3136 $action_hook_name = 'wp_footer'; 3137 if ( wp_is_block_theme() ) { 3138 $action_hook_name = 'wp_head'; 3139 } 3140 add_action( 3141 $action_hook_name, 3142 static function () use ( $style ) { 3143 $processor = new WP_HTML_Tag_Processor( '<style></style>' ); 3144 $processor->next_tag(); 3145 $processor->set_modifiable_text( $style ); 3146 echo "{$processor->get_updated_html()}\n"; 3147 }, 3148 $priority 3149 ); 3150 } 3151 3152 /** 3153 * Fetches, processes and compiles stored core styles, then combines and renders them to the page. 3154 * Styles are stored via the style engine API. 3155 * 3156 * @link https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/ 3157 * 3158 * @since 6.1.0 3159 * 3160 * @param array<string, bool> $options { 3161 * Optional. An array of options to pass to wp_style_engine_get_stylesheet_from_context(). 3162 * Default empty array. 3163 * 3164 * @type bool $optimize Whether to optimize the CSS output, e.g., combine rules. 3165 * Default false. 3166 * @type bool $prettify Whether to add new lines and indents to output. 3167 * Default to whether the `SCRIPT_DEBUG` constant is defined. 3168 * } 3169 */ 3170 function wp_enqueue_stored_styles( $options = array() ) { 3171 // Note: Styles printed at wp_footer for classic themes may still end up in the head due to wp_load_classic_theme_block_styles_on_demand(). 3172 $is_block_theme = wp_is_block_theme(); 3173 $is_classic_theme = ! $is_block_theme; 3174 3175 /* 3176 * For block themes, this function prints stored styles in the header. 3177 * For classic themes, in the footer. 3178 */ 3179 if ( 3180 ( $is_block_theme && doing_action( 'wp_footer' ) ) || 3181 ( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) ) 3182 ) { 3183 return; 3184 } 3185 3186 $core_styles_keys = array( 'block-supports' ); 3187 $compiled_core_stylesheet = ''; 3188 $style_tag_id = 'core'; 3189 // Adds comment if code is prettified to identify core styles sections in debugging. 3190 $should_prettify = isset( $options['prettify'] ) ? true === $options['prettify'] : defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; 3191 foreach ( $core_styles_keys as $style_key ) { 3192 if ( $should_prettify ) { 3193 $compiled_core_stylesheet .= "/**\n * Core styles: $style_key\n */\n"; 3194 } 3195 // Chains core store ids to signify what the styles contain. 3196 $style_tag_id .= '-' . $style_key; 3197 $compiled_core_stylesheet .= wp_style_engine_get_stylesheet_from_context( $style_key, $options ); 3198 } 3199 3200 // Combines Core styles. 3201 if ( ! empty( $compiled_core_stylesheet ) ) { 3202 wp_register_style( $style_tag_id, false ); 3203 wp_add_inline_style( $style_tag_id, $compiled_core_stylesheet ); 3204 wp_enqueue_style( $style_tag_id ); 3205 } 3206 3207 // Prints out any other stores registered by themes or otherwise. 3208 $additional_stores = WP_Style_Engine_CSS_Rules_Store::get_stores(); 3209 foreach ( array_keys( $additional_stores ) as $store_name ) { 3210 if ( in_array( $store_name, $core_styles_keys, true ) ) { 3211 continue; 3212 } 3213 $styles = wp_style_engine_get_stylesheet_from_context( $store_name, $options ); 3214 if ( ! empty( $styles ) ) { 3215 $key = "wp-style-engine-$store_name"; 3216 wp_register_style( $key, false ); 3217 wp_add_inline_style( $key, $styles ); 3218 wp_enqueue_style( $key ); 3219 } 3220 } 3221 } 3222 3223 /** 3224 * Enqueues a stylesheet for a specific block. 3225 * 3226 * If the theme has opted-in to load block styles on demand, 3227 * then the stylesheet will be enqueued on-render, 3228 * otherwise when the block inits. 3229 * 3230 * @since 5.9.0 3231 * 3232 * @param string $block_name The block-name, including namespace. 3233 * @param array<string, string|string[]|bool|null> $args { 3234 * An array of arguments. See wp_register_style() for full information about each argument. 3235 * 3236 * @type string $handle The handle for the stylesheet. 3237 * @type string|false $src The source URL of the stylesheet. 3238 * @type string[] $deps Array of registered stylesheet handles this stylesheet depends on. 3239 * @type string|bool|null $ver Stylesheet version number. 3240 * @type string $media The media for which this stylesheet has been defined. 3241 * @type string|null $path Absolute path to the stylesheet, so that it can potentially be inlined. 3242 * } 3243 */ 3244 function wp_enqueue_block_style( $block_name, $args ) { 3245 $args = wp_parse_args( 3246 $args, 3247 array( 3248 'handle' => '', 3249 'src' => '', 3250 'deps' => array(), 3251 'ver' => false, 3252 'media' => 'all', 3253 ) 3254 ); 3255 3256 /** 3257 * Callback function to register and enqueue styles. 3258 * 3259 * @param string $content When the callback is used for the render_block filter, 3260 * the content needs to be returned so the function parameter 3261 * is to ensure the content exists. 3262 * @return string Block content. 3263 */ 3264 $callback = static function ( $content ) use ( $args ) { 3265 // Register the stylesheet. 3266 if ( ! empty( $args['src'] ) ) { 3267 wp_register_style( $args['handle'], $args['src'], $args['deps'], $args['ver'], $args['media'] ); 3268 } 3269 3270 // Add `path` data if provided. 3271 if ( isset( $args['path'] ) ) { 3272 wp_style_add_data( $args['handle'], 'path', $args['path'] ); 3273 3274 // Get the RTL file path. 3275 $rtl_file_path = str_replace( '.css', '-rtl.css', $args['path'] ); 3276 3277 // Add RTL stylesheet. 3278 if ( file_exists( $rtl_file_path ) ) { 3279 wp_style_add_data( $args['handle'], 'rtl', 'replace' ); 3280 3281 if ( is_rtl() ) { 3282 wp_style_add_data( $args['handle'], 'path', $rtl_file_path ); 3283 } 3284 } 3285 } 3286 3287 // Enqueue the stylesheet. 3288 wp_enqueue_style( $args['handle'] ); 3289 3290 return $content; 3291 }; 3292 3293 $hook = did_action( 'wp_enqueue_scripts' ) ? 'wp_footer' : 'wp_enqueue_scripts'; 3294 if ( wp_should_load_block_assets_on_demand() ) { 3295 /** 3296 * Callback function to register and enqueue styles. 3297 * 3298 * @param string $content The block content. 3299 * @param array $block The full block, including name and attributes. 3300 * @return string Block content. 3301 */ 3302 $callback_separate = static function ( $content, $block ) use ( $block_name, $callback ) { 3303 if ( ! empty( $block['blockName'] ) && $block_name === $block['blockName'] ) { 3304 return $callback( $content ); 3305 } 3306 return $content; 3307 }; 3308 3309 /* 3310 * The filter's callback here is an anonymous function because 3311 * using a named function in this case is not possible. 3312 * 3313 * The function cannot be unhooked, however, users are still able 3314 * to dequeue the stylesheets registered/enqueued by the callback 3315 * which is why in this case, using an anonymous function 3316 * was deemed acceptable. 3317 */ 3318 add_filter( 'render_block', $callback_separate, 10, 2 ); 3319 return; 3320 } 3321 3322 /* 3323 * The filter's callback here is an anonymous function because 3324 * using a named function in this case is not possible. 3325 * 3326 * The function cannot be unhooked, however, users are still able 3327 * to dequeue the stylesheets registered/enqueued by the callback 3328 * which is why in this case, using an anonymous function 3329 * was deemed acceptable. 3330 */ 3331 add_filter( $hook, $callback ); 3332 3333 // Enqueue assets in the editor. 3334 add_action( 'enqueue_block_assets', $callback ); 3335 } 3336 3337 /** 3338 * Loads classic theme styles when the current theme lacks a theme.json file. 3339 * 3340 * This is used for backwards compatibility for Button and File blocks specifically. 3341 * 3342 * @since 6.1.0 3343 * @since 6.2.0 Added File block styles. 3344 * @since 6.8.0 Moved stylesheet registration outside of this function. 3345 */ 3346 function wp_enqueue_classic_theme_styles() { 3347 if ( ! wp_theme_has_theme_json() ) { 3348 wp_enqueue_style( 'classic-theme-styles' ); 3349 } 3350 } 3351 3352 /** 3353 * Enqueues the assets required for the Command Palette. 3354 * 3355 * @since 6.9.0 3356 * 3357 * @global array $menu 3358 * @global array $submenu 3359 */ 3360 function wp_enqueue_command_palette_assets() { 3361 global $menu, $submenu; 3362 3363 $command_palette_settings = array( 3364 'is_network_admin' => is_network_admin(), 3365 ); 3366 3367 /** 3368 * Extracts root-level text nodes from HTML string. 3369 * 3370 * @ignore 3371 * @param string $label HTML string to extract text from. 3372 * @return string Extracted text content, trimmed. 3373 */ 3374 $extract_root_text = static function ( string $label ): string { 3375 if ( '' === $label ) { 3376 return ''; 3377 } 3378 3379 $processor = new WP_HTML_Tag_Processor( $label ); 3380 $text_parts = array(); 3381 $depth = 0; 3382 3383 while ( $processor->next_token() ) { 3384 $token_type = $processor->get_token_type(); 3385 3386 if ( '#text' === $token_type ) { 3387 if ( 0 === $depth ) { 3388 $text_parts[] = $processor->get_modifiable_text(); 3389 } 3390 continue; 3391 } 3392 3393 if ( '#tag' !== $token_type ) { 3394 continue; 3395 } 3396 3397 if ( $processor->is_tag_closer() ) { 3398 if ( $depth > 0 ) { 3399 --$depth; 3400 } 3401 continue; 3402 } 3403 3404 $token_name = $processor->get_tag(); 3405 if ( $token_name && ! WP_HTML_Processor::is_void( $token_name ) ) { 3406 ++$depth; 3407 } 3408 } 3409 3410 return trim( implode( '', $text_parts ) ); 3411 }; 3412 3413 if ( $menu ) { 3414 $menu_commands = array(); 3415 foreach ( $menu as $menu_item ) { 3416 if ( empty( $menu_item[0] ) || ! is_string( $menu_item[0] ) || ! empty( $menu_item[1] ) && ! current_user_can( $menu_item[1] ) ) { 3417 continue; 3418 } 3419 3420 $menu_label = $extract_root_text( $menu_item[0] ); 3421 $menu_url = ''; 3422 $menu_slug = $menu_item[2]; 3423 3424 if ( preg_match( '/\.php($|\?)/', $menu_slug ) || wp_http_validate_url( $menu_slug ) ) { 3425 $menu_url = $menu_slug; 3426 } elseif ( ! empty( menu_page_url( $menu_slug, false ) ) ) { 3427 $menu_url = WP_HTML_Decoder::decode_attribute( menu_page_url( $menu_slug, false ) ); 3428 } 3429 3430 if ( $menu_url ) { 3431 $menu_commands[] = array( 3432 'label' => $menu_label, 3433 'url' => $menu_url, 3434 'name' => $menu_slug, 3435 ); 3436 } 3437 3438 if ( array_key_exists( $menu_slug, $submenu ) ) { 3439 foreach ( $submenu[ $menu_slug ] as $submenu_item ) { 3440 if ( empty( $submenu_item[0] ) || ! empty( $submenu_item[1] ) && ! current_user_can( $submenu_item[1] ) ) { 3441 continue; 3442 } 3443 3444 $submenu_label = $extract_root_text( $submenu_item[0] ); 3445 $submenu_url = ''; 3446 $submenu_slug = $submenu_item[2]; 3447 3448 if ( preg_match( '/\.php($|\?)/', $submenu_slug ) || wp_http_validate_url( $submenu_slug ) ) { 3449 $submenu_url = $submenu_slug; 3450 } elseif ( ! empty( menu_page_url( $submenu_slug, false ) ) ) { 3451 $submenu_url = WP_HTML_Decoder::decode_attribute( menu_page_url( $submenu_slug, false ) ); 3452 } 3453 if ( $submenu_url ) { 3454 $menu_commands[] = array( 3455 'label' => sprintf( 3456 /* translators: 1: Menu label, 2: Submenu label. */ 3457 __( '%1$s > %2$s' ), 3458 $menu_label, 3459 $submenu_label 3460 ), 3461 'url' => $submenu_url, 3462 'name' => $menu_slug . '-' . $submenu_item[2], 3463 ); 3464 } 3465 } 3466 } 3467 } 3468 $command_palette_settings['menu_commands'] = $menu_commands; 3469 } 3470 3471 wp_enqueue_script( 'wp-commands' ); 3472 wp_enqueue_style( 'wp-commands' ); 3473 wp_enqueue_script( 'wp-core-commands' ); 3474 3475 wp_add_inline_script( 3476 'wp-core-commands', 3477 sprintf( 3478 'wp.coreCommands.initializeCommandPalette( %s );', 3479 wp_json_encode( $command_palette_settings, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) 3480 ) 3481 ); 3482 } 3483 3484 /** 3485 * Removes leading and trailing _empty_ script tags. 3486 * 3487 * This is a helper meant to be used for literal script tag construction 3488 * within `wp_get_inline_script_tag()` or `wp_print_inline_script_tag()`. 3489 * It removes the literal values of "<script>" and "</script>" from 3490 * around an inline script after trimming whitespace. Typically this 3491 * is used in conjunction with output buffering, where `ob_get_clean()` 3492 * is passed as the `$contents` argument. 3493 * 3494 * Example: 3495 * 3496 * // Strips exact literal empty SCRIPT tags. 3497 * $js = '<script>sayHello();</script>; 3498 * 'sayHello();' === wp_remove_surrounding_empty_script_tags( $js ); 3499 * 3500 * // Otherwise if anything is different it warns in the JS console. 3501 * $js = '<script type="module">console.log( "hi" );</script>'; 3502 * 'console.error( ... )' === wp_remove_surrounding_empty_script_tags( $js ); 3503 * 3504 * @since 6.4.0 3505 * @access private 3506 * 3507 * @see wp_print_inline_script_tag() 3508 * @see wp_get_inline_script_tag() 3509 * 3510 * @param string $contents Script body with manually created SCRIPT tag literals. 3511 * @return string Script body without surrounding script tag literals, or 3512 * original contents if both exact literals aren't present. 3513 */ 3514 function wp_remove_surrounding_empty_script_tags( $contents ) { 3515 $contents = trim( $contents ); 3516 $opener = '<SCRIPT>'; 3517 $closer = '</SCRIPT>'; 3518 3519 if ( 3520 strlen( $contents ) > strlen( $opener ) + strlen( $closer ) && 3521 strtoupper( substr( $contents, 0, strlen( $opener ) ) ) === $opener && 3522 strtoupper( substr( $contents, -strlen( $closer ) ) ) === $closer 3523 ) { 3524 return substr( $contents, strlen( $opener ), -strlen( $closer ) ); 3525 } else { 3526 $error_message = __( 'Expected string to start with script tag (without attributes) and end with script tag, with optional whitespace.' ); 3527 _doing_it_wrong( __FUNCTION__, $error_message, '6.4' ); 3528 return sprintf( 3529 'console.error(%s)', 3530 wp_json_encode( 3531 sprintf( 3532 /* translators: %s: wp_remove_surrounding_empty_script_tags() */ 3533 __( 'Function %s used incorrectly in PHP.' ), 3534 'wp_remove_surrounding_empty_script_tags()' 3535 ) . ' ' . $error_message 3536 ) 3537 ); 3538 } 3539 } 3540 3541 /** 3542 * Adds hooks to load block styles on demand in classic themes. 3543 * 3544 * @since 6.9.0 3545 * 3546 * @see _add_default_theme_supports() 3547 */ 3548 function wp_load_classic_theme_block_styles_on_demand() { 3549 // This is not relevant to block themes, as they are opted in to loading separate styles on demand via _add_default_theme_supports(). 3550 if ( wp_is_block_theme() ) { 3551 return; 3552 } 3553 3554 /* 3555 * Make sure that wp_should_output_buffer_template_for_enhancement() returns true even if there aren't any 3556 * `wp_template_enhancement_output_buffer` filters added, but do so at priority zero so that applications which 3557 * wish to stream responses can more easily turn this off. 3558 */ 3559 add_filter( 'wp_should_output_buffer_template_for_enhancement', '__return_true', 0 ); 3560 3561 // If a site has opted out of the template enhancement output buffer, then bail. 3562 if ( ! wp_should_output_buffer_template_for_enhancement() ) { 3563 return; 3564 } 3565 3566 // The following two filters are added by default for block themes in _add_default_theme_supports(). 3567 3568 /* 3569 * Load separate block styles so that the large block-library stylesheet is not enqueued unconditionally, and so 3570 * that block-specific styles will only be enqueued when they are used on the page. A priority of zero allows for 3571 * this to be easily overridden by themes which wish to opt out. If a site has explicitly opted out of loading 3572 * separate block styles, then abort. 3573 */ 3574 add_filter( 'should_load_separate_core_block_assets', '__return_true', 0 ); 3575 if ( ! wp_should_load_separate_core_block_assets() ) { 3576 return; 3577 } 3578 3579 /* 3580 * Also ensure that block assets are loaded on demand (although the default value is from should_load_separate_core_block_assets). 3581 * As above, a priority of zero allows for this to be easily overridden by themes which wish to opt out. If a site 3582 * has explicitly opted out of loading block styles on demand, then abort. 3583 */ 3584 add_filter( 'should_load_block_assets_on_demand', '__return_true', 0 ); 3585 if ( ! wp_should_load_block_assets_on_demand() ) { 3586 return; 3587 } 3588 3589 // Add hooks which require the presence of the output buffer. Ideally the above two filters could be added here, but they run too early. 3590 add_action( 'wp_template_enhancement_output_buffer_started', 'wp_hoist_late_printed_styles' ); 3591 } 3592 3593 /** 3594 * Adds the hooks needed for CSS output to be delayed until after the content of the page has been established. 3595 * 3596 * @since 6.9.0 3597 * 3598 * @see wp_load_classic_theme_block_styles_on_demand() 3599 * @see _wp_footer_scripts() 3600 */ 3601 function wp_hoist_late_printed_styles() { 3602 // Skip the embed template on-demand styles aren't relevant, and there is no wp_head action. 3603 if ( is_embed() ) { 3604 return; 3605 } 3606 3607 /* 3608 * Add a placeholder comment into the inline styles for wp-block-library, after which where the late block styles 3609 * can be hoisted from the footer to be printed in the header by means of a filter below on the template enhancement 3610 * output buffer. The `wp_print_styles` action is used to ensure that if the inline style gets replaced at 3611 * `enqueue_block_assets` or `wp_enqueue_scripts` that the placeholder will be sure to be present. 3612 */ 3613 $placeholder = sprintf( '/*%s*/', uniqid( 'wp_block_styles_on_demand_placeholder:' ) ); 3614 add_action( 3615 'wp_print_styles', 3616 static function () use ( $placeholder ) { 3617 wp_add_inline_style( 'wp-block-library', $placeholder ); 3618 } 3619 ); 3620 3621 /* 3622 * Create a substitute for `print_late_styles()` which is aware of block styles. This substitute does not print 3623 * the styles, but it captures what would be printed for block styles and non-block styles so that they can be 3624 * later hoisted to the HEAD in the template enhancement output buffer. This will run at `wp_print_footer_scripts` 3625 * before `print_footer_scripts()` is called. 3626 */ 3627 $printed_block_styles = ''; 3628 $printed_late_styles = ''; 3629 $capture_late_styles = static function () use ( &$printed_block_styles, &$printed_late_styles ) { 3630 // Gather the styles related to on-demand block enqueues. 3631 $all_block_style_handles = array(); 3632 foreach ( WP_Block_Type_Registry::get_instance()->get_all_registered() as $block_type ) { 3633 foreach ( $block_type->style_handles as $style_handle ) { 3634 $all_block_style_handles[] = $style_handle; 3635 } 3636 } 3637 $all_block_style_handles = array_merge( 3638 $all_block_style_handles, 3639 array( 3640 'global-styles', 3641 'block-style-variation-styles', 3642 'core-block-supports', 3643 'core-block-supports-duotone', 3644 ) 3645 ); 3646 3647 /* 3648 * First print all styles related to blocks which should inserted right after the wp-block-library stylesheet 3649 * to preserve the CSS cascade. The logic in this `if` statement is derived from `wp_print_styles()`. 3650 */ 3651 $enqueued_block_styles = array_values( array_intersect( $all_block_style_handles, wp_styles()->queue ) ); 3652 if ( count( $enqueued_block_styles ) > 0 ) { 3653 ob_start(); 3654 wp_styles()->do_items( $enqueued_block_styles ); 3655 $printed_block_styles = ob_get_clean(); 3656 } 3657 3658 /* 3659 * Print all remaining styles not related to blocks. This contains a subset of the logic from 3660 * `print_late_styles()`, without admin-specific logic and the `print_late_styles` filter to control whether 3661 * late styles are printed (since they are being hoisted anyway). 3662 */ 3663 ob_start(); 3664 wp_styles()->do_footer_items(); 3665 $printed_late_styles = ob_get_clean(); 3666 }; 3667 3668 /* 3669 * If `_wp_footer_scripts()` was unhooked from the `wp_print_footer_scripts` action, or if `wp_print_footer_scripts()` 3670 * was unhooked from running at the `wp_footer` action, then only add a callback to `wp_footer` which will capture the 3671 * late-printed styles. 3672 * 3673 * Otherwise, in the normal case where `_wp_footer_scripts()` will run at the `wp_print_footer_scripts` action, then 3674 * swap out `_wp_footer_scripts()` with an alternative which captures the printed styles (for hoisting to HEAD) before 3675 * proceeding with printing the footer scripts. 3676 */ 3677 $wp_print_footer_scripts_priority = has_action( 'wp_print_footer_scripts', '_wp_footer_scripts' ); 3678 if ( false === $wp_print_footer_scripts_priority || false === has_action( 'wp_footer', 'wp_print_footer_scripts' ) ) { 3679 // The normal priority for wp_print_footer_scripts() is to run at 20. 3680 add_action( 'wp_footer', $capture_late_styles, 20 ); 3681 } else { 3682 remove_action( 'wp_print_footer_scripts', '_wp_footer_scripts', $wp_print_footer_scripts_priority ); 3683 add_action( 3684 'wp_print_footer_scripts', 3685 static function () use ( $capture_late_styles ) { 3686 $capture_late_styles(); 3687 print_footer_scripts(); 3688 }, 3689 $wp_print_footer_scripts_priority 3690 ); 3691 } 3692 3693 // Replace placeholder with the captured late styles. 3694 add_filter( 3695 'wp_template_enhancement_output_buffer', 3696 static function ( $buffer ) use ( $placeholder, &$printed_block_styles, &$printed_late_styles ) { 3697 3698 // Anonymous subclass of WP_HTML_Tag_Processor which exposes underlying bookmark spans. 3699 $processor = new class( $buffer ) extends WP_HTML_Tag_Processor { 3700 /** 3701 * Gets the span for the current token. 3702 * 3703 * @return WP_HTML_Span Current token span. 3704 */ 3705 private function get_span(): WP_HTML_Span { 3706 // Note: This call will never fail according to the usage of this class, given it is always called after ::next_tag() is true. 3707 $this->set_bookmark( 'here' ); 3708 return $this->bookmarks['here']; 3709 } 3710 3711 /** 3712 * Inserts text before the current token. 3713 * 3714 * @param string $text Text to insert. 3715 */ 3716 public function insert_before( string $text ) { 3717 $this->lexical_updates[] = new WP_HTML_Text_Replacement( $this->get_span()->start, 0, $text ); 3718 } 3719 3720 /** 3721 * Inserts text after the current token. 3722 * 3723 * @param string $text Text to insert. 3724 */ 3725 public function insert_after( string $text ) { 3726 $span = $this->get_span(); 3727 3728 $this->lexical_updates[] = new WP_HTML_Text_Replacement( $span->start + $span->length, 0, $text ); 3729 } 3730 3731 /** 3732 * Removes the current token. 3733 */ 3734 public function remove() { 3735 $span = $this->get_span(); 3736 3737 $this->lexical_updates[] = new WP_HTML_Text_Replacement( $span->start, $span->length, '' ); 3738 } 3739 }; 3740 3741 /* 3742 * Insert block styles right after wp-block-library (if it is present), and then insert any remaining styles 3743 * at </head> (or else print everything there). The placeholder CSS comment will always be added to the 3744 * wp-block-library inline style since it gets printed at `wp_head` before the blocks are rendered. 3745 * This means that there may not actually be any block styles to hoist from the footer to insert after this 3746 * inline style. The placeholder CSS comment needs to be added so that the inline style gets printed, but 3747 * if the resulting inline style is empty after the placeholder is removed, then the inline style is 3748 * removed. 3749 */ 3750 while ( $processor->next_tag( array( 'tag_closers' => 'visit' ) ) ) { 3751 if ( 3752 'STYLE' === $processor->get_tag() && 3753 'wp-block-library-inline-css' === $processor->get_attribute( 'id' ) 3754 ) { 3755 $css_text = $processor->get_modifiable_text(); 3756 3757 /* 3758 * A placeholder CSS comment is added to the inline style in order to force an inline STYLE tag to 3759 * be printed. Now that we've located the inline style, the placeholder comment can be removed. If 3760 * there is no CSS left in the STYLE tag after removing the placeholder (aside from the sourceURL 3761 * comment, then remove the STYLE entirely.) 3762 */ 3763 $css_text = str_replace( $placeholder, '', $css_text ); 3764 if ( preg_match( ':^/\*# sourceURL=\S+? \*/$:', trim( $css_text ) ) ) { 3765 $processor->remove(); 3766 } else { 3767 $processor->set_modifiable_text( $css_text ); 3768 } 3769 3770 // Insert the $printed_late_styles immediately after the closing inline STYLE tag. This preserves the CSS cascade. 3771 if ( '' !== $printed_block_styles ) { 3772 $processor->insert_after( $printed_block_styles ); 3773 3774 // Prevent printing them again at </head>. 3775 $printed_block_styles = ''; 3776 } 3777 3778 // If there aren't any late styles, there's no need to continue to finding </head>. 3779 if ( '' === $printed_late_styles ) { 3780 break; 3781 } 3782 } elseif ( 'HEAD' === $processor->get_tag() && $processor->is_tag_closer() ) { 3783 $processor->insert_before( $printed_block_styles . $printed_late_styles ); 3784 break; 3785 } 3786 } 3787 3788 return $processor->get_updated_html(); 3789 } 3790 ); 3791 } 3792 3793 /** 3794 * Return the corresponding JavaScript `dataset` name for an attribute 3795 * if it represents a custom data attribute, or `null` if not. 3796 * 3797 * Custom data attributes appear in an element's `dataset` property in a 3798 * browser, but there's a specific way the names are translated from HTML 3799 * into JavaScript. This function indicates how the name would appear in 3800 * JavaScript if a browser would recognize it as a custom data attribute. 3801 * 3802 * Example: 3803 * 3804 * // Dash-letter pairs turn into capital letters. 3805 * 'postId' === wp_js_dataset_name( 'data-post-id' ); 3806 * 'Before' === wp_js_dataset_name( 'data--before' ); 3807 * '-One--Two---' === wp_js_dataset_name( 'data---one---two---' ); 3808 * 3809 * // Not every attribute name will be interpreted as a custom data attribute. 3810 * null === wp_js_dataset_name( 'post-id' ); 3811 * null === wp_js_dataset_name( 'data' ); 3812 * 3813 * // Some very surprising names will; for example, a property whose name is the empty string. 3814 * '' === wp_js_dataset_name( 'data-' ); 3815 * 0 === strlen( wp_js_dataset_name( 'data-' ) ); 3816 * 3817 * @since 6.9.0 3818 * 3819 * @see https://html.spec.whatwg.org/#concept-domstringmap-pairs 3820 * @see \wp_html_custom_data_attribute_name() 3821 * 3822 * @param string $html_attribute_name Raw attribute name as found in the source HTML. 3823 * @return string|null Transformed `dataset` name, if interpretable as a custom data attribute, else `null`. 3824 */ 3825 function wp_js_dataset_name( string $html_attribute_name ): ?string { 3826 if ( 0 !== substr_compare( $html_attribute_name, 'data-', 0, 5, true ) ) { 3827 return null; 3828 } 3829 3830 $end = strlen( $html_attribute_name ); 3831 3832 /* 3833 * If it contains characters which would end the attribute name parsing then 3834 * something else is wrong and this contains more than just an attribute name. 3835 */ 3836 if ( ( $end - 5 ) !== strcspn( $html_attribute_name, "=/> \t\f\r\n", 5 ) ) { 3837 return null; 3838 } 3839 3840 /** 3841 * > For each name in list, for each U+002D HYPHEN-MINUS character (-) 3842 * > in the name that is followed by an ASCII lower alpha, remove the 3843 * > U+002D HYPHEN-MINUS character (-) and replace the character that 3844 * > followed it by the same character converted to ASCII uppercase. 3845 * 3846 * @see https://html.spec.whatwg.org/#concept-domstringmap-pairs 3847 */ 3848 $custom_name = ''; 3849 $at = 5; 3850 $was_at = $at; 3851 3852 while ( $at < $end ) { 3853 $next_dash_at = strpos( $html_attribute_name, '-', $at ); 3854 if ( false === $next_dash_at || $next_dash_at === $end - 1 ) { 3855 break; 3856 } 3857 3858 // Transform `-a` to `A`, for example. 3859 $c = $html_attribute_name[ $next_dash_at + 1 ]; 3860 if ( ( $c >= 'A' && $c <= 'Z' ) || ( $c >= 'a' && $c <= 'z' ) ) { 3861 $prefix = substr( $html_attribute_name, $was_at, $next_dash_at - $was_at ); 3862 $custom_name .= strtolower( $prefix ); 3863 $custom_name .= strtoupper( $c ); 3864 $at = $next_dash_at + 2; 3865 $was_at = $at; 3866 continue; 3867 } 3868 3869 $at = $next_dash_at + 1; 3870 } 3871 3872 // If nothing has been added it means there are no dash-letter pairs; return the name as-is. 3873 return '' === $custom_name 3874 ? strtolower( substr( $html_attribute_name, 5 ) ) 3875 : ( $custom_name . strtolower( substr( $html_attribute_name, $was_at ) ) ); 3876 } 3877 3878 /** 3879 * Returns a corresponding HTML attribute name for the given name, 3880 * if that name were found in a JS element’s `dataset` property. 3881 * 3882 * Example: 3883 * 3884 * 'data-post-id' === wp_html_custom_data_attribute_name( 'postId' ); 3885 * 'data--before' === wp_html_custom_data_attribute_name( 'Before' ); 3886 * 'data---one---two---' === wp_html_custom_data_attribute_name( '-One--Two---' ); 3887 * 3888 * // Not every attribute name will be interpreted as a custom data attribute. 3889 * null === wp_html_custom_data_attribute_name( '/not-an-attribute/' ); 3890 * null === wp_html_custom_data_attribute_name( 'no spaces' ); 3891 * 3892 * // Some very surprising names will; for example, a property whose name is the empty string. 3893 * 'data-' === wp_html_custom_data_attribute_name( '' ); 3894 * 3895 * @since 6.9.0 3896 * 3897 * @see https://html.spec.whatwg.org/#concept-domstringmap-pairs 3898 * @see \wp_js_dataset_name() 3899 * 3900 * @param string $js_dataset_name Name of JS `dataset` property to transform. 3901 * @return string|null Corresponding name of an HTML custom data attribute for the given dataset name, 3902 * if possible to represent in HTML, otherwise `null`. 3903 */ 3904 function wp_html_custom_data_attribute_name( string $js_dataset_name ): ?string { 3905 $end = strlen( $js_dataset_name ); 3906 if ( 0 === $end ) { 3907 return 'data-'; 3908 } 3909 3910 /* 3911 * If it contains characters which would end the attribute name parsing then 3912 * something it’s not possible to represent this in HTML. 3913 */ 3914 if ( strcspn( $js_dataset_name, "=/> \t\f\r\n" ) !== $end ) { 3915 return null; 3916 } 3917 3918 $html_name = 'data-'; 3919 $at = 0; 3920 $was_at = $at; 3921 3922 while ( $at < $end ) { 3923 $next_upper_after = strcspn( $js_dataset_name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', $at ); 3924 $next_upper_at = $at + $next_upper_after; 3925 if ( $next_upper_at >= $end ) { 3926 break; 3927 } 3928 3929 $prefix = substr( $js_dataset_name, $was_at, $next_upper_at - $was_at ); 3930 $html_name .= strtolower( $prefix ); 3931 $html_name .= '-' . strtolower( $js_dataset_name[ $next_upper_at ] ); 3932 $at = $next_upper_at + 1; 3933 $was_at = $at; 3934 } 3935 3936 if ( $was_at < $end ) { 3937 $html_name .= strtolower( substr( $js_dataset_name, $was_at ) ); 3938 } 3939 3940 return $html_name; 3941 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Wed Apr 15 08:20:10 2026 | Cross-referenced by PHPXref |