Make WordPress Core

Ticket #55695: script-loader.php

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