[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> script-loader.php (source)

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


Generated : Sat Jun 7 08:20:01 2025 Cross-referenced by PHPXref