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