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