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


Generated : Tue Apr 23 08:20:01 2024 Cross-referenced by PHPXref