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


Generated : Thu Sep 19 08:20:01 2024 Cross-referenced by PHPXref