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


Generated : Sun Jun 4 08:20:02 2023 Cross-referenced by PHPXref