wp/wp-includes/script-loader.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    18 
    18 
    19 /** WordPress Dependency Class */
    19 /** WordPress Dependency Class */
    20 require ABSPATH . WPINC . '/class-wp-dependency.php';
    20 require ABSPATH . WPINC . '/class-wp-dependency.php';
    21 
    21 
    22 /** WordPress Dependencies Class */
    22 /** WordPress Dependencies Class */
    23 require ABSPATH . WPINC . '/class.wp-dependencies.php';
    23 require ABSPATH . WPINC . '/class-wp-dependencies.php';
    24 
    24 
    25 /** WordPress Scripts Class */
    25 /** WordPress Scripts Class */
    26 require ABSPATH . WPINC . '/class.wp-scripts.php';
    26 require ABSPATH . WPINC . '/class-wp-scripts.php';
    27 
    27 
    28 /** WordPress Scripts Functions */
    28 /** WordPress Scripts Functions */
    29 require ABSPATH . WPINC . '/functions.wp-scripts.php';
    29 require ABSPATH . WPINC . '/functions.wp-scripts.php';
    30 
    30 
    31 /** WordPress Styles Class */
    31 /** WordPress Styles Class */
    32 require ABSPATH . WPINC . '/class.wp-styles.php';
    32 require ABSPATH . WPINC . '/class-wp-styles.php';
    33 
    33 
    34 /** WordPress Styles Functions */
    34 /** WordPress Styles Functions */
    35 require ABSPATH . WPINC . '/functions.wp-styles.php';
    35 require ABSPATH . WPINC . '/functions.wp-styles.php';
    36 
    36 
    37 /**
    37 /**
    55 	script_concat_settings();
    55 	script_concat_settings();
    56 
    56 
    57 	$compressed = $compress_scripts && $concatenate_scripts && isset( $_SERVER['HTTP_ACCEPT_ENCODING'] )
    57 	$compressed = $compress_scripts && $concatenate_scripts && isset( $_SERVER['HTTP_ACCEPT_ENCODING'] )
    58 		&& false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) && ! $force_uncompressed;
    58 		&& false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) && ! $force_uncompressed;
    59 
    59 
    60 	// Load tinymce.js when running from /src, otherwise load wp-tinymce.js.gz (in production)
    60 	/*
    61 	// or tinymce.min.js (when SCRIPT_DEBUG is true).
    61 	 * Load tinymce.js when running from /src, otherwise load wp-tinymce.js.gz (in production)
       
    62 	 * or tinymce.min.js (when SCRIPT_DEBUG is true).
       
    63 	 */
    62 	if ( $compressed ) {
    64 	if ( $compressed ) {
    63 		$scripts->add( 'wp-tinymce', includes_url( 'js/tinymce/' ) . 'wp-tinymce.js', array(), $tinymce_version );
    65 		$scripts->add( 'wp-tinymce', includes_url( 'js/tinymce/' ) . 'wp-tinymce.js', array(), $tinymce_version );
    64 	} else {
    66 	} else {
    65 		$scripts->add( 'wp-tinymce-root', includes_url( 'js/tinymce/' ) . "tinymce$dev_suffix.js", array(), $tinymce_version );
    67 		$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 );
    68 		$scripts->add( 'wp-tinymce', includes_url( 'js/tinymce/' ) . "plugins/compat3x/plugin$dev_suffix.js", array( 'wp-tinymce-root' ), $tinymce_version );
    85 	global $wp_locale;
    87 	global $wp_locale;
    86 
    88 
    87 	$suffix = wp_scripts_get_suffix();
    89 	$suffix = wp_scripts_get_suffix();
    88 
    90 
    89 	$vendor_scripts = array(
    91 	$vendor_scripts = array(
    90 		'react'       => array( 'wp-polyfill' ),
    92 		'react',
    91 		'react-dom'   => array( 'react' ),
    93 		'react-dom'         => array( 'react' ),
       
    94 		'react-jsx-runtime' => array( 'react' ),
    92 		'regenerator-runtime',
    95 		'regenerator-runtime',
    93 		'moment',
    96 		'moment',
    94 		'lodash',
    97 		'lodash',
    95 		'wp-polyfill-fetch',
    98 		'wp-polyfill-fetch',
    96 		'wp-polyfill-formdata',
    99 		'wp-polyfill-formdata',
       
   100 		'wp-polyfill-importmap',
    97 		'wp-polyfill-node-contains',
   101 		'wp-polyfill-node-contains',
    98 		'wp-polyfill-url',
   102 		'wp-polyfill-url',
    99 		'wp-polyfill-dom-rect',
   103 		'wp-polyfill-dom-rect',
   100 		'wp-polyfill-element-closest',
   104 		'wp-polyfill-element-closest',
   101 		'wp-polyfill-object-fit',
   105 		'wp-polyfill-object-fit',
   102 		'wp-polyfill' => array( 'regenerator-runtime' ),
   106 		'wp-polyfill-inert',
       
   107 		'wp-polyfill',
   103 	);
   108 	);
   104 
   109 
   105 	$vendor_scripts_versions = array(
   110 	$vendor_scripts_versions = array(
   106 		'react'                       => '17.0.1',
   111 		'react'                       => '18.3.1',
   107 		'react-dom'                   => '17.0.1',
   112 		'react-dom'                   => '18.3.1',
   108 		'regenerator-runtime'         => '0.13.9',
   113 		'react-jsx-runtime'           => '18.3.1',
       
   114 		'regenerator-runtime'         => '0.14.0',
   109 		'moment'                      => '2.29.4',
   115 		'moment'                      => '2.29.4',
   110 		'lodash'                      => '4.17.19',
   116 		'lodash'                      => '4.17.21',
   111 		'wp-polyfill-fetch'           => '3.6.2',
   117 		'wp-polyfill-fetch'           => '3.6.17',
   112 		'wp-polyfill-formdata'        => '4.0.10',
   118 		'wp-polyfill-formdata'        => '4.0.10',
   113 		'wp-polyfill-node-contains'   => '4.0.0',
   119 		'wp-polyfill-node-contains'   => '4.8.0',
   114 		'wp-polyfill-url'             => '3.6.4',
   120 		'wp-polyfill-url'             => '3.6.4',
   115 		'wp-polyfill-dom-rect'        => '4.0.0',
   121 		'wp-polyfill-dom-rect'        => '4.8.0',
   116 		'wp-polyfill-element-closest' => '2.0.2',
   122 		'wp-polyfill-element-closest' => '3.0.2',
   117 		'wp-polyfill-object-fit'      => '2.3.5',
   123 		'wp-polyfill-object-fit'      => '2.3.5',
       
   124 		'wp-polyfill-inert'           => '3.1.2',
   118 		'wp-polyfill'                 => '3.15.0',
   125 		'wp-polyfill'                 => '3.15.0',
       
   126 		'wp-polyfill-importmap'       => '1.8.2',
   119 	);
   127 	);
   120 
   128 
   121 	foreach ( $vendor_scripts as $handle => $dependencies ) {
   129 	foreach ( $vendor_scripts as $handle => $dependencies ) {
   122 		if ( is_string( $dependencies ) ) {
   130 		if ( is_string( $dependencies ) ) {
   123 			$handle       = $dependencies;
   131 			$handle       = $dependencies;
   134 
   142 
   135 	did_action( 'init' ) && $scripts->add_inline_script(
   143 	did_action( 'init' ) && $scripts->add_inline_script(
   136 		'moment',
   144 		'moment',
   137 		sprintf(
   145 		sprintf(
   138 			"moment.updateLocale( '%s', %s );",
   146 			"moment.updateLocale( '%s', %s );",
   139 			get_user_locale(),
   147 			esc_js( get_user_locale() ),
   140 			wp_json_encode(
   148 			wp_json_encode(
   141 				array(
   149 				array(
   142 					'months'         => array_values( $wp_locale->month ),
   150 					'months'         => array_values( $wp_locale->month ),
   143 					'monthsShort'    => array_values( $wp_locale->month_abbrev ),
   151 					'monthsShort'    => array_values( $wp_locale->month_abbrev ),
   144 					'weekdays'       => array_values( $wp_locale->weekday ),
   152 					'weekdays'       => array_values( $wp_locale->weekday ),
   167  * a condition to verify feature support to its polyfill script handle.
   175  * a condition to verify feature support to its polyfill script handle.
   168  *
   176  *
   169  * @since 5.0.0
   177  * @since 5.0.0
   170  *
   178  *
   171  * @param WP_Scripts $scripts WP_Scripts object.
   179  * @param WP_Scripts $scripts WP_Scripts object.
   172  * @param array      $tests   Features to detect.
   180  * @param string[]   $tests   Features to detect.
   173  * @return string Conditional polyfill inline script.
   181  * @return string Conditional polyfill inline script.
   174  */
   182  */
   175 function wp_get_script_polyfill( $scripts, $tests ) {
   183 function wp_get_script_polyfill( $scripts, $tests ) {
   176 	$polyfill = '';
   184 	$polyfill = '';
   177 	foreach ( $tests as $test => $handle ) {
   185 	foreach ( $tests as $test => $handle ) {
   180 		}
   188 		}
   181 
   189 
   182 		$src = $scripts->registered[ $handle ]->src;
   190 		$src = $scripts->registered[ $handle ]->src;
   183 		$ver = $scripts->registered[ $handle ]->ver;
   191 		$ver = $scripts->registered[ $handle ]->ver;
   184 
   192 
   185 		if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $scripts->content_url && 0 === strpos( $src, $scripts->content_url ) ) ) {
   193 		if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $scripts->content_url && str_starts_with( $src, $scripts->content_url ) ) ) {
   186 			$src = $scripts->base_url . $src;
   194 			$src = $scripts->base_url . $src;
   187 		}
   195 		}
   188 
   196 
   189 		if ( ! empty( $ver ) ) {
   197 		if ( ! empty( $ver ) ) {
   190 			$src = add_query_arg( 'ver', $ver, $src );
   198 			$src = add_query_arg( 'ver', $ver, $src );
   191 		}
   199 		}
   192 
   200 
   193 		/** This filter is documented in wp-includes/class.wp-scripts.php */
   201 		/** This filter is documented in wp-includes/class-wp-scripts.php */
   194 		$src = esc_url( apply_filters( 'script_loader_src', $src, $handle ) );
   202 		$src = esc_url( apply_filters( 'script_loader_src', $src, $handle ) );
   195 
   203 
   196 		if ( ! $src ) {
   204 		if ( ! $src ) {
   197 			continue;
   205 			continue;
   198 		}
   206 		}
   225  */
   233  */
   226 function wp_register_development_scripts( $scripts ) {
   234 function wp_register_development_scripts( $scripts ) {
   227 	if (
   235 	if (
   228 		! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG
   236 		! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG
   229 		|| empty( $scripts->registered['react'] )
   237 		|| empty( $scripts->registered['react'] )
       
   238 		|| defined( 'WP_RUN_CORE_TESTS' )
   230 	) {
   239 	) {
   231 		return;
   240 		return;
   232 	}
   241 	}
   233 
   242 
   234 	$development_scripts = array(
   243 	$development_scripts = array(
   262  * @since 5.0.0
   271  * @since 5.0.0
   263  *
   272  *
   264  * @param WP_Scripts $scripts WP_Scripts object.
   273  * @param WP_Scripts $scripts WP_Scripts object.
   265  */
   274  */
   266 function wp_default_packages_scripts( $scripts ) {
   275 function wp_default_packages_scripts( $scripts ) {
   267 	$suffix = wp_scripts_get_suffix();
   276 	$suffix = defined( 'WP_RUN_CORE_TESTS' ) ? '.min' : wp_scripts_get_suffix();
   268 
       
   269 	/*
   277 	/*
   270 	 * Expects multidimensional array like:
   278 	 * Expects multidimensional array like:
   271 	 *
   279 	 *
   272 	 *     'a11y.js' => array('dependencies' => array(...), 'version' => '...'),
   280 	 *     'a11y.js' => array('dependencies' => array(...), 'version' => '...'),
   273 	 *     'annotations.js' => array('dependencies' => array(...), 'version' => '...'),
   281 	 *     'annotations.js' => array('dependencies' => array(...), 'version' => '...'),
   274 	 *     'api-fetch.js' => array(...
   282 	 *     'api-fetch.js' => array(...
   275 	 */
   283 	 */
   276 	$assets = include ABSPATH . WPINC . '/assets/script-loader-packages.php';
   284 	$assets = include ABSPATH . WPINC . "/assets/script-loader-packages{$suffix}.php";
   277 
   285 
   278 	foreach ( $assets as $package_name => $package_data ) {
   286 	foreach ( $assets as $file_name => $package_data ) {
   279 		$basename = basename( $package_name, '.js' );
   287 		$basename = str_replace( $suffix . '.js', '', basename( $file_name ) );
   280 		$handle   = 'wp-' . $basename;
   288 		$handle   = 'wp-' . $basename;
   281 		$path     = "/wp-includes/js/dist/{$basename}{$suffix}.js";
   289 		$path     = "/wp-includes/js/dist/{$basename}{$suffix}.js";
   282 
   290 
   283 		if ( ! empty( $package_data['dependencies'] ) ) {
   291 		if ( ! empty( $package_data['dependencies'] ) ) {
   284 			$dependencies = $package_data['dependencies'];
   292 			$dependencies = $package_data['dependencies'];
   291 			case 'wp-block-library':
   299 			case 'wp-block-library':
   292 				array_push( $dependencies, 'editor' );
   300 				array_push( $dependencies, 'editor' );
   293 				break;
   301 				break;
   294 			case 'wp-edit-post':
   302 			case 'wp-edit-post':
   295 				array_push( $dependencies, 'media-models', 'media-views', 'postbox', 'wp-dom-ready' );
   303 				array_push( $dependencies, 'media-models', 'media-views', 'postbox', 'wp-dom-ready' );
       
   304 				break;
       
   305 			case 'wp-preferences':
       
   306 				array_push( $dependencies, 'wp-preferences-persistence' );
   296 				break;
   307 				break;
   297 		}
   308 		}
   298 
   309 
   299 		$scripts->add( $handle, $path, $dependencies, $package_data['version'], 1 );
   310 		$scripts->add( $handle, $path, $dependencies, $package_data['version'], 1 );
   300 
   311 
   320 
   331 
   321 /**
   332 /**
   322  * Adds inline scripts required for the WordPress JavaScript packages.
   333  * Adds inline scripts required for the WordPress JavaScript packages.
   323  *
   334  *
   324  * @since 5.0.0
   335  * @since 5.0.0
       
   336  * @since 6.4.0 Added relative time strings for the `wp-date` inline script output.
   325  *
   337  *
   326  * @global WP_Locale $wp_locale WordPress date and time locale object.
   338  * @global WP_Locale $wp_locale WordPress date and time locale object.
       
   339  * @global wpdb      $wpdb      WordPress database abstraction object.
   327  *
   340  *
   328  * @param WP_Scripts $scripts WP_Scripts object.
   341  * @param WP_Scripts $scripts WP_Scripts object.
   329  */
   342  */
   330 function wp_default_packages_inline_scripts( $scripts ) {
   343 function wp_default_packages_inline_scripts( $scripts ) {
   331 	global $wp_locale;
   344 	global $wp_locale, $wpdb;
   332 
   345 
   333 	if ( isset( $scripts->registered['wp-api-fetch'] ) ) {
   346 	if ( isset( $scripts->registered['wp-api-fetch'] ) ) {
   334 		$scripts->registered['wp-api-fetch']->deps[] = 'wp-hooks';
   347 		$scripts->registered['wp-api-fetch']->deps[] = 'wp-hooks';
   335 	}
   348 	}
   336 	$scripts->add_inline_script(
   349 	$scripts->add_inline_script(
   337 		'wp-api-fetch',
   350 		'wp-api-fetch',
   338 		sprintf(
   351 		sprintf(
   339 			'wp.apiFetch.use( wp.apiFetch.createRootURLMiddleware( "%s" ) );',
   352 			'wp.apiFetch.use( wp.apiFetch.createRootURLMiddleware( "%s" ) );',
   340 			esc_url_raw( get_rest_url() )
   353 			sanitize_url( get_rest_url() )
   341 		),
   354 		),
   342 		'after'
   355 		'after'
   343 	);
   356 	);
   344 	$scripts->add_inline_script(
   357 	$scripts->add_inline_script(
   345 		'wp-api-fetch',
   358 		'wp-api-fetch',
   358 				),
   371 				),
   359 			)
   372 			)
   360 		),
   373 		),
   361 		'after'
   374 		'after'
   362 	);
   375 	);
       
   376 
       
   377 	$meta_key     = $wpdb->get_blog_prefix() . 'persisted_preferences';
       
   378 	$user_id      = get_current_user_id();
       
   379 	$preload_data = get_user_meta( $user_id, $meta_key, true );
       
   380 	$scripts->add_inline_script(
       
   381 		'wp-preferences',
       
   382 		sprintf(
       
   383 			'( function() {
       
   384 				var serverData = %s;
       
   385 				var userId = "%d";
       
   386 				var persistenceLayer = wp.preferencesPersistence.__unstableCreatePersistenceLayer( serverData, userId );
       
   387 				var preferencesStore = wp.preferences.store;
       
   388 				wp.data.dispatch( preferencesStore ).setPersistenceLayer( persistenceLayer );
       
   389 			} ) ();',
       
   390 			wp_json_encode( $preload_data ),
       
   391 			$user_id
       
   392 		)
       
   393 	);
       
   394 
       
   395 	// Backwards compatibility - configure the old wp-data persistence system.
   363 	$scripts->add_inline_script(
   396 	$scripts->add_inline_script(
   364 		'wp-data',
   397 		'wp-data',
   365 		implode(
   398 		implode(
   366 			"\n",
   399 			"\n",
   367 			array(
   400 			array(
   368 				'( function() {',
   401 				'( function() {',
   369 				'	var userId = ' . get_current_user_ID() . ';',
   402 				'	var userId = ' . get_current_user_ID() . ';',
   370 				'	var storageKey = "WP_DATA_USER_" + userId;',
   403 				'	var storageKey = "WP_DATA_USER_" + userId;',
   371 				'	wp.data',
   404 				'	wp.data',
   372 				'		.use( wp.data.plugins.persistence, { storageKey: storageKey } );',
   405 				'		.use( wp.data.plugins.persistence, { storageKey: storageKey } );',
   373 				'	wp.data.plugins.persistence.__unstableMigrate( { storageKey: storageKey } );',
       
   374 				'} )();',
   406 				'} )();',
   375 			)
   407 			)
   376 		)
   408 		)
   377 	);
   409 	);
   378 
   410 
   382 
   414 
   383 	if ( ! empty( $timezone_string ) ) {
   415 	if ( ! empty( $timezone_string ) ) {
   384 		$timezone_date = new DateTime( 'now', new DateTimeZone( $timezone_string ) );
   416 		$timezone_date = new DateTime( 'now', new DateTimeZone( $timezone_string ) );
   385 		$timezone_abbr = $timezone_date->format( 'T' );
   417 		$timezone_abbr = $timezone_date->format( 'T' );
   386 	}
   418 	}
       
   419 
       
   420 	$gmt_offset = get_option( 'gmt_offset', 0 );
   387 
   421 
   388 	$scripts->add_inline_script(
   422 	$scripts->add_inline_script(
   389 		'wp-date',
   423 		'wp-date',
   390 		sprintf(
   424 		sprintf(
   391 			'wp.date.setSettings( %s );',
   425 			'wp.date.setSettings( %s );',
   401 						'relative'      => array(
   435 						'relative'      => array(
   402 							/* translators: %s: Duration. */
   436 							/* translators: %s: Duration. */
   403 							'future' => __( '%s from now' ),
   437 							'future' => __( '%s from now' ),
   404 							/* translators: %s: Duration. */
   438 							/* translators: %s: Duration. */
   405 							'past'   => __( '%s ago' ),
   439 							'past'   => __( '%s ago' ),
       
   440 							/* translators: One second from or to a particular datetime, e.g., "a second ago" or "a second from now". */
       
   441 							's'      => __( 'a second' ),
       
   442 							/* translators: %d: Duration in seconds from or to a particular datetime, e.g., "4 seconds ago" or "4 seconds from now". */
       
   443 							'ss'     => __( '%d seconds' ),
       
   444 							/* translators: One minute from or to a particular datetime, e.g., "a minute ago" or "a minute from now". */
       
   445 							'm'      => __( 'a minute' ),
       
   446 							/* translators: %d: Duration in minutes from or to a particular datetime, e.g., "4 minutes ago" or "4 minutes from now". */
       
   447 							'mm'     => __( '%d minutes' ),
       
   448 							/* translators: One hour from or to a particular datetime, e.g., "an hour ago" or "an hour from now". */
       
   449 							'h'      => __( 'an hour' ),
       
   450 							/* translators: %d: Duration in hours from or to a particular datetime, e.g., "4 hours ago" or "4 hours from now". */
       
   451 							'hh'     => __( '%d hours' ),
       
   452 							/* translators: One day from or to a particular datetime, e.g., "a day ago" or "a day from now". */
       
   453 							'd'      => __( 'a day' ),
       
   454 							/* translators: %d: Duration in days from or to a particular datetime, e.g., "4 days ago" or "4 days from now". */
       
   455 							'dd'     => __( '%d days' ),
       
   456 							/* translators: One month from or to a particular datetime, e.g., "a month ago" or "a month from now". */
       
   457 							'M'      => __( 'a month' ),
       
   458 							/* translators: %d: Duration in months from or to a particular datetime, e.g., "4 months ago" or "4 months from now". */
       
   459 							'MM'     => __( '%d months' ),
       
   460 							/* translators: One year from or to a particular datetime, e.g., "a year ago" or "a year from now". */
       
   461 							'y'      => __( 'a year' ),
       
   462 							/* translators: %d: Duration in years from or to a particular datetime, e.g., "4 years ago" or "4 years from now". */
       
   463 							'yy'     => __( '%d years' ),
   406 						),
   464 						),
       
   465 						'startOfWeek'   => (int) get_option( 'start_of_week', 0 ),
   407 					),
   466 					),
   408 					'formats'  => array(
   467 					'formats'  => array(
   409 						/* translators: Time format, see https://www.php.net/manual/datetime.format.php */
   468 						/* translators: Time format, see https://www.php.net/manual/datetime.format.php */
   410 						'time'                => get_option( 'time_format', __( 'g:i a' ) ),
   469 						'time'                => get_option( 'time_format', __( 'g:i a' ) ),
   411 						/* translators: Date format, see https://www.php.net/manual/datetime.format.php */
   470 						/* translators: Date format, see https://www.php.net/manual/datetime.format.php */
   414 						'datetime'            => __( 'F j, Y g:i a' ),
   473 						'datetime'            => __( 'F j, Y g:i a' ),
   415 						/* translators: Abbreviated date/time format, see https://www.php.net/manual/datetime.format.php */
   474 						/* translators: Abbreviated date/time format, see https://www.php.net/manual/datetime.format.php */
   416 						'datetimeAbbreviated' => __( 'M j, Y g:i a' ),
   475 						'datetimeAbbreviated' => __( 'M j, Y g:i a' ),
   417 					),
   476 					),
   418 					'timezone' => array(
   477 					'timezone' => array(
   419 						'offset' => get_option( 'gmt_offset', 0 ),
   478 						'offset'          => (float) $gmt_offset,
   420 						'string' => $timezone_string,
   479 						'offsetFormatted' => str_replace( array( '.25', '.5', '.75' ), array( ':15', ':30', ':45' ), (string) $gmt_offset ),
   421 						'abbr'   => $timezone_abbr,
   480 						'string'          => $timezone_string,
       
   481 						'abbr'            => $timezone_abbr,
   422 					),
   482 					),
   423 				)
   483 				)
   424 			)
   484 			)
   425 		),
   485 		),
   426 		'after'
   486 		'after'
   557 	}
   617 	}
   558 
   618 
   559 	/** This filter is documented in wp-includes/class-wp-editor.php */
   619 	/** This filter is documented in wp-includes/class-wp-editor.php */
   560 	$tinymce_settings = apply_filters( 'tiny_mce_before_init', $tinymce_settings, 'classic-block' );
   620 	$tinymce_settings = apply_filters( 'tiny_mce_before_init', $tinymce_settings, 'classic-block' );
   561 
   621 
   562 	// Do "by hand" translation from PHP array to js object.
   622 	/*
   563 	// Prevents breakage in some custom settings.
   623 	 * Do "by hand" translation from PHP array to js object.
       
   624 	 * Prevents breakage in some custom settings.
       
   625 	 */
   564 	$init_obj = '';
   626 	$init_obj = '';
   565 	foreach ( $tinymce_settings as $key => $value ) {
   627 	foreach ( $tinymce_settings as $key => $value ) {
   566 		if ( is_bool( $value ) ) {
   628 		if ( is_bool( $value ) ) {
   567 			$val       = $value ? 'true' : 'false';
   629 			$val       = $value ? 'true' : 'false';
   568 			$init_obj .= $key . ':' . $val . ',';
   630 			$init_obj .= $key . ':' . $val . ',';
   623 
   685 
   624 	if ( null === $suffixes ) {
   686 	if ( null === $suffixes ) {
   625 		// Include an unmodified $wp_version.
   687 		// Include an unmodified $wp_version.
   626 		require ABSPATH . WPINC . '/version.php';
   688 		require ABSPATH . WPINC . '/version.php';
   627 
   689 
       
   690 		/*
       
   691 		 * Note: str_contains() is not used here, as this file can be included
       
   692 		 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case
       
   693 		 * the polyfills from wp-includes/compat.php are not loaded.
       
   694 		 */
   628 		$develop_src = false !== strpos( $wp_version, '-src' );
   695 		$develop_src = false !== strpos( $wp_version, '-src' );
   629 
   696 
   630 		if ( ! defined( 'SCRIPT_DEBUG' ) ) {
   697 		if ( ! defined( 'SCRIPT_DEBUG' ) ) {
   631 			define( 'SCRIPT_DEBUG', $develop_src );
   698 			define( 'SCRIPT_DEBUG', $develop_src );
   632 		}
   699 		}
   730 
   797 
   731 	$scripts->add( 'colorpicker', "/wp-includes/js/colorpicker$suffix.js", array( 'prototype' ), '3517m' );
   798 	$scripts->add( 'colorpicker', "/wp-includes/js/colorpicker$suffix.js", array( 'prototype' ), '3517m' );
   732 
   799 
   733 	$scripts->add( 'editor', "/wp-admin/js/editor$suffix.js", array( 'utils', 'jquery' ), false, 1 );
   800 	$scripts->add( 'editor', "/wp-admin/js/editor$suffix.js", array( 'utils', 'jquery' ), false, 1 );
   734 
   801 
   735 	$scripts->add( 'clipboard', "/wp-includes/js/clipboard$suffix.js", array(), '2.0.10', 1 );
   802 	$scripts->add( 'clipboard', "/wp-includes/js/clipboard$suffix.js", array(), '2.0.11', 1 );
   736 
   803 
   737 	$scripts->add( 'wp-ajax-response', "/wp-includes/js/wp-ajax-response$suffix.js", array( 'jquery', 'wp-a11y' ), false, 1 );
   804 	$scripts->add( 'wp-ajax-response', "/wp-includes/js/wp-ajax-response$suffix.js", array( 'jquery', 'wp-a11y' ), false, 1 );
   738 	did_action( 'init' ) && $scripts->localize(
   805 	did_action( 'init' ) && $scripts->localize(
   739 		'wp-ajax-response',
   806 		'wp-ajax-response',
   740 		'wpAjax',
   807 		'wpAjax',
   748 	// `wpApiSettings` is also used by `wp-api`, which depends on this script.
   815 	// `wpApiSettings` is also used by `wp-api`, which depends on this script.
   749 	did_action( 'init' ) && $scripts->localize(
   816 	did_action( 'init' ) && $scripts->localize(
   750 		'wp-api-request',
   817 		'wp-api-request',
   751 		'wpApiSettings',
   818 		'wpApiSettings',
   752 		array(
   819 		array(
   753 			'root'          => esc_url_raw( get_rest_url() ),
   820 			'root'          => sanitize_url( get_rest_url() ),
   754 			'nonce'         => wp_installing() ? '' : wp_create_nonce( 'wp_rest' ),
   821 			'nonce'         => wp_installing() ? '' : wp_create_nonce( 'wp_rest' ),
   755 			'versionString' => 'wp/v2/',
   822 			'versionString' => 'wp/v2/',
   756 		)
   823 		)
   757 	);
   824 	);
   758 
   825 
   778 	$scripts->add( 'wp-auth-check', "/wp-includes/js/wp-auth-check$suffix.js", array( 'heartbeat' ), false, 1 );
   845 	$scripts->add( 'wp-auth-check', "/wp-includes/js/wp-auth-check$suffix.js", array( 'heartbeat' ), false, 1 );
   779 	$scripts->set_translations( 'wp-auth-check' );
   846 	$scripts->set_translations( 'wp-auth-check' );
   780 
   847 
   781 	$scripts->add( 'wp-lists', "/wp-includes/js/wp-lists$suffix.js", array( 'wp-ajax-response', 'jquery-color' ), false, 1 );
   848 	$scripts->add( 'wp-lists', "/wp-includes/js/wp-lists$suffix.js", array( 'wp-ajax-response', 'jquery-color' ), false, 1 );
   782 
   849 
       
   850 	$scripts->add( 'site-icon', '/wp-admin/js/site-icon.js', array( 'jquery' ), false, 1 );
       
   851 	$scripts->set_translations( 'site-icon' );
       
   852 
   783 	// WordPress no longer uses or bundles Prototype or script.aculo.us. These are now pulled from an external source.
   853 	// WordPress no longer uses or bundles Prototype or script.aculo.us. These are now pulled from an external source.
   784 	$scripts->add( 'prototype', 'https://ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js', array(), '1.7.1' );
   854 	$scripts->add( 'prototype', 'https://ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js', array(), '1.7.1' );
   785 	$scripts->add( 'scriptaculous-root', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/scriptaculous.js', array( 'prototype' ), '1.9.0' );
   855 	$scripts->add( 'scriptaculous-root', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/scriptaculous.js', array( 'prototype' ), '1.9.0' );
   786 	$scripts->add( 'scriptaculous-builder', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/builder.js', array( 'scriptaculous-root' ), '1.9.0' );
   856 	$scripts->add( 'scriptaculous-builder', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/builder.js', array( 'scriptaculous-root' ), '1.9.0' );
   787 	$scripts->add( 'scriptaculous-dragdrop', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/dragdrop.js', array( 'scriptaculous-builder', 'scriptaculous-effects' ), '1.9.0' );
   857 	$scripts->add( 'scriptaculous-dragdrop', 'https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/dragdrop.js', array( 'scriptaculous-builder', 'scriptaculous-effects' ), '1.9.0' );
   792 	$scripts->add( 'scriptaculous', false, array( 'scriptaculous-dragdrop', 'scriptaculous-slider', 'scriptaculous-controls' ) );
   862 	$scripts->add( 'scriptaculous', false, array( 'scriptaculous-dragdrop', 'scriptaculous-slider', 'scriptaculous-controls' ) );
   793 
   863 
   794 	// Not used in core, replaced by Jcrop.js.
   864 	// Not used in core, replaced by Jcrop.js.
   795 	$scripts->add( 'cropper', '/wp-includes/js/crop/cropper.js', array( 'scriptaculous-dragdrop' ) );
   865 	$scripts->add( 'cropper', '/wp-includes/js/crop/cropper.js', array( 'scriptaculous-dragdrop' ) );
   796 
   866 
   797 	// jQuery.
   867 	/*
   798 	// The unminified jquery.js and jquery-migrate.js are included to facilitate debugging.
   868 	 * jQuery.
   799 	$scripts->add( 'jquery', false, array( 'jquery-core', 'jquery-migrate' ), '3.6.0' );
   869 	 * The unminified jquery.js and jquery-migrate.js are included to facilitate debugging.
   800 	$scripts->add( 'jquery-core', "/wp-includes/js/jquery/jquery$suffix.js", array(), '3.6.0' );
   870 	 */
   801 	$scripts->add( 'jquery-migrate', "/wp-includes/js/jquery/jquery-migrate$suffix.js", array(), '3.3.2' );
   871 	$scripts->add( 'jquery', false, array( 'jquery-core', 'jquery-migrate' ), '3.7.1' );
   802 
   872 	$scripts->add( 'jquery-core', "/wp-includes/js/jquery/jquery$suffix.js", array(), '3.7.1' );
   803 	// Full jQuery UI.
   873 	$scripts->add( 'jquery-migrate', "/wp-includes/js/jquery/jquery-migrate$suffix.js", array(), '3.4.1' );
   804 	// The build process in 1.12.1 has changed significantly.
   874 
   805 	// In order to keep backwards compatibility, and to keep the optimized loading,
   875 	/*
   806 	// the source files were flattened and included with some modifications for AMD loading.
   876 	 * Full jQuery UI.
   807 	// A notable change is that 'jquery-ui-core' now contains 'jquery-ui-position' and 'jquery-ui-widget'.
   877 	 * The build process in 1.12.1 has changed significantly.
   808 	$scripts->add( 'jquery-ui-core', "/wp-includes/js/jquery/ui/core$suffix.js", array( 'jquery' ), '1.13.1', 1 );
   878 	 * In order to keep backwards compatibility, and to keep the optimized loading,
   809 	$scripts->add( 'jquery-effects-core', "/wp-includes/js/jquery/ui/effect$suffix.js", array( 'jquery' ), '1.13.1', 1 );
   879 	 * the source files were flattened and included with some modifications for AMD loading.
   810 
   880 	 * A notable change is that 'jquery-ui-core' now contains 'jquery-ui-position' and 'jquery-ui-widget'.
   811 	$scripts->add( 'jquery-effects-blind', "/wp-includes/js/jquery/ui/effect-blind$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   881 	 */
   812 	$scripts->add( 'jquery-effects-bounce', "/wp-includes/js/jquery/ui/effect-bounce$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   882 	$scripts->add( 'jquery-ui-core', "/wp-includes/js/jquery/ui/core$suffix.js", array( 'jquery' ), '1.13.3', 1 );
   813 	$scripts->add( 'jquery-effects-clip', "/wp-includes/js/jquery/ui/effect-clip$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   883 	$scripts->add( 'jquery-effects-core', "/wp-includes/js/jquery/ui/effect$suffix.js", array( 'jquery' ), '1.13.3', 1 );
   814 	$scripts->add( 'jquery-effects-drop', "/wp-includes/js/jquery/ui/effect-drop$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   884 
   815 	$scripts->add( 'jquery-effects-explode', "/wp-includes/js/jquery/ui/effect-explode$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   885 	$scripts->add( 'jquery-effects-blind', "/wp-includes/js/jquery/ui/effect-blind$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   816 	$scripts->add( 'jquery-effects-fade', "/wp-includes/js/jquery/ui/effect-fade$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   886 	$scripts->add( 'jquery-effects-bounce', "/wp-includes/js/jquery/ui/effect-bounce$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   817 	$scripts->add( 'jquery-effects-fold', "/wp-includes/js/jquery/ui/effect-fold$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   887 	$scripts->add( 'jquery-effects-clip', "/wp-includes/js/jquery/ui/effect-clip$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   818 	$scripts->add( 'jquery-effects-highlight', "/wp-includes/js/jquery/ui/effect-highlight$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   888 	$scripts->add( 'jquery-effects-drop', "/wp-includes/js/jquery/ui/effect-drop$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   819 	$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 );
   889 	$scripts->add( 'jquery-effects-explode', "/wp-includes/js/jquery/ui/effect-explode$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   820 	$scripts->add( 'jquery-effects-pulsate', "/wp-includes/js/jquery/ui/effect-pulsate$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   890 	$scripts->add( 'jquery-effects-fade', "/wp-includes/js/jquery/ui/effect-fade$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   821 	$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 );
   891 	$scripts->add( 'jquery-effects-fold', "/wp-includes/js/jquery/ui/effect-fold$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   822 	$scripts->add( 'jquery-effects-shake', "/wp-includes/js/jquery/ui/effect-shake$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   892 	$scripts->add( 'jquery-effects-highlight', "/wp-includes/js/jquery/ui/effect-highlight$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   823 	$scripts->add( 'jquery-effects-size', "/wp-includes/js/jquery/ui/effect-size$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   893 	$scripts->add( 'jquery-effects-puff', "/wp-includes/js/jquery/ui/effect-puff$suffix.js", array( 'jquery-effects-core', 'jquery-effects-scale' ), '1.13.3', 1 );
   824 	$scripts->add( 'jquery-effects-slide', "/wp-includes/js/jquery/ui/effect-slide$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   894 	$scripts->add( 'jquery-effects-pulsate', "/wp-includes/js/jquery/ui/effect-pulsate$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   825 	$scripts->add( 'jquery-effects-transfer', "/wp-includes/js/jquery/ui/effect-transfer$suffix.js", array( 'jquery-effects-core' ), '1.13.1', 1 );
   895 	$scripts->add( 'jquery-effects-scale', "/wp-includes/js/jquery/ui/effect-scale$suffix.js", array( 'jquery-effects-core', 'jquery-effects-size' ), '1.13.3', 1 );
       
   896 	$scripts->add( 'jquery-effects-shake', "/wp-includes/js/jquery/ui/effect-shake$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
       
   897 	$scripts->add( 'jquery-effects-size', "/wp-includes/js/jquery/ui/effect-size$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
       
   898 	$scripts->add( 'jquery-effects-slide', "/wp-includes/js/jquery/ui/effect-slide$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
       
   899 	$scripts->add( 'jquery-effects-transfer', "/wp-includes/js/jquery/ui/effect-transfer$suffix.js", array( 'jquery-effects-core' ), '1.13.3', 1 );
   826 
   900 
   827 	// Widgets
   901 	// Widgets
   828 	$scripts->add( 'jquery-ui-accordion', "/wp-includes/js/jquery/ui/accordion$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   902 	$scripts->add( 'jquery-ui-accordion', "/wp-includes/js/jquery/ui/accordion$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   829 	$scripts->add( 'jquery-ui-autocomplete', "/wp-includes/js/jquery/ui/autocomplete$suffix.js", array( 'jquery-ui-menu', 'wp-a11y' ), '1.13.1', 1 );
   903 	$scripts->add( 'jquery-ui-autocomplete', "/wp-includes/js/jquery/ui/autocomplete$suffix.js", array( 'jquery-ui-menu', 'wp-a11y' ), '1.13.3', 1 );
   830 	$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 );
   904 	$scripts->add( 'jquery-ui-button', "/wp-includes/js/jquery/ui/button$suffix.js", array( 'jquery-ui-core', 'jquery-ui-controlgroup', 'jquery-ui-checkboxradio' ), '1.13.3', 1 );
   831 	$scripts->add( 'jquery-ui-datepicker', "/wp-includes/js/jquery/ui/datepicker$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   905 	$scripts->add( 'jquery-ui-datepicker', "/wp-includes/js/jquery/ui/datepicker$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   832 	$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 );
   906 	$scripts->add( 'jquery-ui-dialog', "/wp-includes/js/jquery/ui/dialog$suffix.js", array( 'jquery-ui-resizable', 'jquery-ui-draggable', 'jquery-ui-button' ), '1.13.3', 1 );
   833 	$scripts->add( 'jquery-ui-menu', "/wp-includes/js/jquery/ui/menu$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   907 	$scripts->add( 'jquery-ui-menu', "/wp-includes/js/jquery/ui/menu$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   834 	$scripts->add( 'jquery-ui-mouse', "/wp-includes/js/jquery/ui/mouse$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   908 	$scripts->add( 'jquery-ui-mouse', "/wp-includes/js/jquery/ui/mouse$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   835 	$scripts->add( 'jquery-ui-progressbar', "/wp-includes/js/jquery/ui/progressbar$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   909 	$scripts->add( 'jquery-ui-progressbar', "/wp-includes/js/jquery/ui/progressbar$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   836 	$scripts->add( 'jquery-ui-selectmenu', "/wp-includes/js/jquery/ui/selectmenu$suffix.js", array( 'jquery-ui-menu' ), '1.13.1', 1 );
   910 	$scripts->add( 'jquery-ui-selectmenu', "/wp-includes/js/jquery/ui/selectmenu$suffix.js", array( 'jquery-ui-menu' ), '1.13.3', 1 );
   837 	$scripts->add( 'jquery-ui-slider', "/wp-includes/js/jquery/ui/slider$suffix.js", array( 'jquery-ui-mouse' ), '1.13.1', 1 );
   911 	$scripts->add( 'jquery-ui-slider', "/wp-includes/js/jquery/ui/slider$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 );
   838 	$scripts->add( 'jquery-ui-spinner', "/wp-includes/js/jquery/ui/spinner$suffix.js", array( 'jquery-ui-button' ), '1.13.1', 1 );
   912 	$scripts->add( 'jquery-ui-spinner', "/wp-includes/js/jquery/ui/spinner$suffix.js", array( 'jquery-ui-button' ), '1.13.3', 1 );
   839 	$scripts->add( 'jquery-ui-tabs', "/wp-includes/js/jquery/ui/tabs$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   913 	$scripts->add( 'jquery-ui-tabs', "/wp-includes/js/jquery/ui/tabs$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   840 	$scripts->add( 'jquery-ui-tooltip', "/wp-includes/js/jquery/ui/tooltip$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   914 	$scripts->add( 'jquery-ui-tooltip', "/wp-includes/js/jquery/ui/tooltip$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   841 
   915 
   842 	// New in 1.12.1
   916 	// New in 1.12.1
   843 	$scripts->add( 'jquery-ui-checkboxradio', "/wp-includes/js/jquery/ui/checkboxradio$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   917 	$scripts->add( 'jquery-ui-checkboxradio', "/wp-includes/js/jquery/ui/checkboxradio$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   844 	$scripts->add( 'jquery-ui-controlgroup', "/wp-includes/js/jquery/ui/controlgroup$suffix.js", array( 'jquery-ui-core' ), '1.13.1', 1 );
   918 	$scripts->add( 'jquery-ui-controlgroup', "/wp-includes/js/jquery/ui/controlgroup$suffix.js", array( 'jquery-ui-core' ), '1.13.3', 1 );
   845 
   919 
   846 	// Interactions
   920 	// Interactions
   847 	$scripts->add( 'jquery-ui-draggable', "/wp-includes/js/jquery/ui/draggable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.1', 1 );
   921 	$scripts->add( 'jquery-ui-draggable', "/wp-includes/js/jquery/ui/draggable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 );
   848 	$scripts->add( 'jquery-ui-droppable', "/wp-includes/js/jquery/ui/droppable$suffix.js", array( 'jquery-ui-draggable' ), '1.13.1', 1 );
   922 	$scripts->add( 'jquery-ui-droppable', "/wp-includes/js/jquery/ui/droppable$suffix.js", array( 'jquery-ui-draggable' ), '1.13.3', 1 );
   849 	$scripts->add( 'jquery-ui-resizable', "/wp-includes/js/jquery/ui/resizable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.1', 1 );
   923 	$scripts->add( 'jquery-ui-resizable', "/wp-includes/js/jquery/ui/resizable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 );
   850 	$scripts->add( 'jquery-ui-selectable', "/wp-includes/js/jquery/ui/selectable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.1', 1 );
   924 	$scripts->add( 'jquery-ui-selectable', "/wp-includes/js/jquery/ui/selectable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 );
   851 	$scripts->add( 'jquery-ui-sortable', "/wp-includes/js/jquery/ui/sortable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.1', 1 );
   925 	$scripts->add( 'jquery-ui-sortable', "/wp-includes/js/jquery/ui/sortable$suffix.js", array( 'jquery-ui-mouse' ), '1.13.3', 1 );
   852 
   926 
   853 	// As of 1.12.1 `jquery-ui-position` and `jquery-ui-widget` are part of `jquery-ui-core`.
   927 	/*
   854 	// Listed here for back-compat.
   928 	 * As of 1.12.1 `jquery-ui-position` and `jquery-ui-widget` are part of `jquery-ui-core`.
   855 	$scripts->add( 'jquery-ui-position', false, array( 'jquery-ui-core' ), '1.13.1', 1 );
   929 	 * Listed here for back-compat.
   856 	$scripts->add( 'jquery-ui-widget', false, array( 'jquery-ui-core' ), '1.13.1', 1 );
   930 	 */
   857 
   931 	$scripts->add( 'jquery-ui-position', false, array( 'jquery-ui-core' ), '1.13.3', 1 );
   858 	// Strings for 'jquery-ui-autocomplete' live region messages.
   932 	$scripts->add( 'jquery-ui-widget', false, array( 'jquery-ui-core' ), '1.13.3', 1 );
   859 	did_action( 'init' ) && $scripts->localize(
       
   860 		'jquery-ui-autocomplete',
       
   861 		'uiAutocompleteL10n',
       
   862 		array(
       
   863 			'noResults'    => __( 'No results found.' ),
       
   864 			/* translators: Number of results found when using jQuery UI Autocomplete. */
       
   865 			'oneResult'    => __( '1 result found. Use up and down arrow keys to navigate.' ),
       
   866 			/* translators: %d: Number of results found when using jQuery UI Autocomplete. */
       
   867 			'manyResults'  => __( '%d results found. Use up and down arrow keys to navigate.' ),
       
   868 			'itemSelected' => __( 'Item selected.' ),
       
   869 		)
       
   870 	);
       
   871 
   933 
   872 	// Deprecated, not used in core, most functionality is included in jQuery 1.3.
   934 	// Deprecated, not used in core, most functionality is included in jQuery 1.3.
   873 	$scripts->add( 'jquery-form', "/wp-includes/js/jquery/jquery.form$suffix.js", array( 'jquery' ), '4.3.0', 1 );
   935 	$scripts->add( 'jquery-form', "/wp-includes/js/jquery/jquery.form$suffix.js", array( 'jquery' ), '4.3.0', 1 );
   874 
   936 
   875 	// jQuery plugins.
   937 	// jQuery plugins.
   882 	$scripts->add( 'jquery-touch-punch', '/wp-includes/js/jquery/jquery.ui.touch-punch.js', array( 'jquery-ui-core', 'jquery-ui-mouse' ), '0.2.2', 1 );
   944 	$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 );
   883 
   945 
   884 	// Not used any more, registered for backward compatibility.
   946 	// Not used any more, registered for backward compatibility.
   885 	$scripts->add( 'suggest', "/wp-includes/js/jquery/suggest$suffix.js", array( 'jquery' ), '1.1-20110113', 1 );
   947 	$scripts->add( 'suggest', "/wp-includes/js/jquery/suggest$suffix.js", array( 'jquery' ), '1.1-20110113', 1 );
   886 
   948 
   887 	// Masonry v2 depended on jQuery. v3 does not. The older jquery-masonry handle is a shiv.
   949 	/*
   888 	// It sets jQuery as a dependency, as the theme may have been implicitly loading it this way.
   950 	 * Masonry v2 depended on jQuery. v3 does not. The older jquery-masonry handle is a shiv.
   889 	$scripts->add( 'imagesloaded', '/wp-includes/js/imagesloaded.min.js', array(), '4.1.4', 1 );
   951 	 * It sets jQuery as a dependency, as the theme may have been implicitly loading it this way.
       
   952 	 */
       
   953 	$scripts->add( 'imagesloaded', '/wp-includes/js/imagesloaded.min.js', array(), '5.0.0', 1 );
   890 	$scripts->add( 'masonry', '/wp-includes/js/masonry.min.js', array( 'imagesloaded' ), '4.2.2', 1 );
   954 	$scripts->add( 'masonry', '/wp-includes/js/masonry.min.js', array( 'imagesloaded' ), '4.2.2', 1 );
   891 	$scripts->add( 'jquery-masonry', '/wp-includes/js/jquery/jquery.masonry.min.js', array( 'jquery', 'masonry' ), '3.1.2b', 1 );
   955 	$scripts->add( 'jquery-masonry', '/wp-includes/js/jquery/jquery.masonry.min.js', array( 'jquery', 'masonry' ), '3.1.2b', 1 );
   892 
   956 
   893 	$scripts->add( 'thickbox', '/wp-includes/js/thickbox/thickbox.js', array( 'jquery' ), '3.1-20121105', 1 );
   957 	$scripts->add( 'thickbox', '/wp-includes/js/thickbox/thickbox.js', array( 'jquery' ), '3.1-20121105', 1 );
   894 	did_action( 'init' ) && $scripts->localize(
   958 	did_action( 'init' ) && $scripts->localize(
   962 	$scripts->add( 'swfupload-all', false, array( 'swfupload' ), '2201' );
  1026 	$scripts->add( 'swfupload-all', false, array( 'swfupload' ), '2201' );
   963 	$scripts->add( 'swfupload-handlers', "/wp-includes/js/swfupload/handlers$suffix.js", array( 'swfupload-all', 'jquery' ), '2201-20110524' );
  1027 	$scripts->add( 'swfupload-handlers', "/wp-includes/js/swfupload/handlers$suffix.js", array( 'swfupload-all', 'jquery' ), '2201-20110524' );
   964 	did_action( 'init' ) && $scripts->localize( 'swfupload-handlers', 'swfuploadL10n', $uploader_l10n );
  1028 	did_action( 'init' ) && $scripts->localize( 'swfupload-handlers', 'swfuploadL10n', $uploader_l10n );
   965 
  1029 
   966 	$scripts->add( 'comment-reply', "/wp-includes/js/comment-reply$suffix.js", array(), false, 1 );
  1030 	$scripts->add( 'comment-reply', "/wp-includes/js/comment-reply$suffix.js", array(), false, 1 );
       
  1031 	did_action( 'init' ) && $scripts->add_data( 'comment-reply', 'strategy', 'async' );
   967 
  1032 
   968 	$scripts->add( 'json2', "/wp-includes/js/json2$suffix.js", array(), '2015-05-03' );
  1033 	$scripts->add( 'json2', "/wp-includes/js/json2$suffix.js", array(), '2015-05-03' );
   969 	did_action( 'init' ) && $scripts->add_data( 'json2', 'conditional', 'lt IE 8' );
  1034 	did_action( 'init' ) && $scripts->add_data( 'json2', 'conditional', 'lt IE 8' );
   970 
  1035 
   971 	$scripts->add( 'underscore', "/wp-includes/js/underscore$dev_suffix.js", array(), '1.13.3', 1 );
  1036 	$scripts->add( 'underscore', "/wp-includes/js/underscore$dev_suffix.js", array(), '1.13.4', 1 );
   972 	$scripts->add( 'backbone', "/wp-includes/js/backbone$dev_suffix.js", array( 'underscore', 'jquery' ), '1.4.1', 1 );
  1037 	$scripts->add( 'backbone', "/wp-includes/js/backbone$dev_suffix.js", array( 'underscore', 'jquery' ), '1.5.0', 1 );
   973 
  1038 
   974 	$scripts->add( 'wp-util', "/wp-includes/js/wp-util$suffix.js", array( 'underscore', 'jquery' ), false, 1 );
  1039 	$scripts->add( 'wp-util', "/wp-includes/js/wp-util$suffix.js", array( 'underscore', 'jquery' ), false, 1 );
   975 	did_action( 'init' ) && $scripts->localize(
  1040 	did_action( 'init' ) && $scripts->localize(
   976 		'wp-util',
  1041 		'wp-util',
   977 		'_wpUtilSettings',
  1042 		'_wpUtilSettings',
   986 
  1051 
   987 	$scripts->add( 'revisions', "/wp-admin/js/revisions$suffix.js", array( 'wp-backbone', 'jquery-ui-slider', 'hoverIntent' ), false, 1 );
  1052 	$scripts->add( 'revisions', "/wp-admin/js/revisions$suffix.js", array( 'wp-backbone', 'jquery-ui-slider', 'hoverIntent' ), false, 1 );
   988 
  1053 
   989 	$scripts->add( 'imgareaselect', "/wp-includes/js/imgareaselect/jquery.imgareaselect$suffix.js", array( 'jquery' ), false, 1 );
  1054 	$scripts->add( 'imgareaselect', "/wp-includes/js/imgareaselect/jquery.imgareaselect$suffix.js", array( 'jquery' ), false, 1 );
   990 
  1055 
   991 	$scripts->add( 'mediaelement', false, array( 'jquery', 'mediaelement-core', 'mediaelement-migrate' ), '4.2.16', 1 );
  1056 	$scripts->add( 'mediaelement', false, array( 'jquery', 'mediaelement-core', 'mediaelement-migrate' ), '4.2.17', 1 );
   992 	$scripts->add( 'mediaelement-core', "/wp-includes/js/mediaelement/mediaelement-and-player$suffix.js", array(), '4.2.16', 1 );
  1057 	$scripts->add( 'mediaelement-core', "/wp-includes/js/mediaelement/mediaelement-and-player$suffix.js", array(), '4.2.17', 1 );
   993 	$scripts->add( 'mediaelement-migrate', "/wp-includes/js/mediaelement/mediaelement-migrate$suffix.js", array(), false, 1 );
  1058 	$scripts->add( 'mediaelement-migrate', "/wp-includes/js/mediaelement/mediaelement-migrate$suffix.js", array(), false, 1 );
   994 
  1059 
   995 	did_action( 'init' ) && $scripts->add_inline_script(
  1060 	did_action( 'init' ) && $scripts->add_inline_script(
   996 		'mediaelement-core',
  1061 		'mediaelement-core',
   997 		sprintf(
  1062 		sprintf(
  1077 			)
  1142 			)
  1078 		),
  1143 		),
  1079 		'before'
  1144 		'before'
  1080 	);
  1145 	);
  1081 
  1146 
  1082 	$scripts->add( 'mediaelement-vimeo', '/wp-includes/js/mediaelement/renderers/vimeo.min.js', array( 'mediaelement' ), '4.2.16', 1 );
  1147 	$scripts->add( 'mediaelement-vimeo', '/wp-includes/js/mediaelement/renderers/vimeo.min.js', array( 'mediaelement' ), '4.2.17', 1 );
  1083 	$scripts->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement$suffix.js", array( 'mediaelement' ), false, 1 );
  1148 	$scripts->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement$suffix.js", array( 'mediaelement' ), false, 1 );
  1084 	$mejs_settings = array(
  1149 	$mejs_settings = array(
  1085 		'pluginPath'  => includes_url( 'js/mediaelement/', 'relative' ),
  1150 		'pluginPath'            => includes_url( 'js/mediaelement/', 'relative' ),
  1086 		'classPrefix' => 'mejs-',
  1151 		'classPrefix'           => 'mejs-',
  1087 		'stretching'  => 'responsive',
  1152 		'stretching'            => 'responsive',
       
  1153 		/** This filter is documented in wp-includes/media.php */
       
  1154 		'audioShortcodeLibrary' => apply_filters( 'wp_audio_shortcode_library', 'mediaelement' ),
       
  1155 		/** This filter is documented in wp-includes/media.php */
       
  1156 		'videoShortcodeLibrary' => apply_filters( 'wp_video_shortcode_library', 'mediaelement' ),
  1088 	);
  1157 	);
  1089 	did_action( 'init' ) && $scripts->localize(
  1158 	did_action( 'init' ) && $scripts->localize(
  1090 		'mediaelement',
  1159 		'mediaelement',
  1091 		'_wpmejsSettings',
  1160 		'_wpmejsSettings',
  1092 		/**
  1161 		/**
  1105 	$scripts->add( 'jshint', '/wp-includes/js/codemirror/fakejshint.js', array( 'esprima' ), '2.9.5' );
  1174 	$scripts->add( 'jshint', '/wp-includes/js/codemirror/fakejshint.js', array( 'esprima' ), '2.9.5' );
  1106 	$scripts->add( 'jsonlint', '/wp-includes/js/codemirror/jsonlint.js', array(), '1.6.2' );
  1175 	$scripts->add( 'jsonlint', '/wp-includes/js/codemirror/jsonlint.js', array(), '1.6.2' );
  1107 	$scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '0.9.14-xwp' );
  1176 	$scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '0.9.14-xwp' );
  1108 	$scripts->add( 'htmlhint-kses', '/wp-includes/js/codemirror/htmlhint-kses.js', array( 'htmlhint' ) );
  1177 	$scripts->add( 'htmlhint-kses', '/wp-includes/js/codemirror/htmlhint-kses.js', array( 'htmlhint' ) );
  1109 	$scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'wp-codemirror', 'underscore' ) );
  1178 	$scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'wp-codemirror', 'underscore' ) );
  1110 	$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' ) );
  1179 	$scripts->add( 'wp-theme-plugin-editor', "/wp-admin/js/theme-plugin-editor$suffix.js", array( 'common', 'wp-util', 'wp-sanitize', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ), false, 1 );
  1111 	$scripts->set_translations( 'wp-theme-plugin-editor' );
  1180 	$scripts->set_translations( 'wp-theme-plugin-editor' );
  1112 
  1181 
  1113 	$scripts->add( 'wp-playlist', "/wp-includes/js/mediaelement/wp-playlist$suffix.js", array( 'wp-util', 'backbone', 'mediaelement' ), false, 1 );
  1182 	$scripts->add( 'wp-playlist', "/wp-includes/js/mediaelement/wp-playlist$suffix.js", array( 'wp-util', 'backbone', 'mediaelement' ), false, 1 );
  1114 
  1183 
  1115 	$scripts->add( 'zxcvbn-async', "/wp-includes/js/zxcvbn-async$suffix.js", array(), '1.0' );
  1184 	$scripts->add( 'zxcvbn-async', "/wp-includes/js/zxcvbn-async$suffix.js", array(), '1.0' );
  1134 			'mismatch' => _x( 'Mismatch', 'password mismatch' ),
  1203 			'mismatch' => _x( 'Mismatch', 'password mismatch' ),
  1135 		)
  1204 		)
  1136 	);
  1205 	);
  1137 	$scripts->set_translations( 'password-strength-meter' );
  1206 	$scripts->set_translations( 'password-strength-meter' );
  1138 
  1207 
       
  1208 	$scripts->add( 'password-toggle', "/wp-admin/js/password-toggle$suffix.js", array(), false, 1 );
       
  1209 	$scripts->set_translations( 'password-toggle' );
       
  1210 
  1139 	$scripts->add( 'application-passwords', "/wp-admin/js/application-passwords$suffix.js", array( 'jquery', 'wp-util', 'wp-api-request', 'wp-date', 'wp-i18n', 'wp-hooks' ), false, 1 );
  1211 	$scripts->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 );
  1140 	$scripts->set_translations( 'application-passwords' );
  1212 	$scripts->set_translations( 'application-passwords' );
  1141 
  1213 
  1142 	$scripts->add( 'auth-app', "/wp-admin/js/auth-app$suffix.js", array( 'jquery', 'wp-api-request', 'wp-i18n', 'wp-hooks' ), false, 1 );
  1214 	$scripts->add( 'auth-app', "/wp-admin/js/auth-app$suffix.js", array( 'jquery', 'wp-api-request', 'wp-i18n', 'wp-hooks' ), false, 1 );
  1143 	$scripts->set_translations( 'auth-app' );
  1215 	$scripts->set_translations( 'auth-app' );
  1158 
  1230 
  1159 	$scripts->add( 'user-suggest', "/wp-admin/js/user-suggest$suffix.js", array( 'jquery-ui-autocomplete' ), false, 1 );
  1231 	$scripts->add( 'user-suggest', "/wp-admin/js/user-suggest$suffix.js", array( 'jquery-ui-autocomplete' ), false, 1 );
  1160 
  1232 
  1161 	$scripts->add( 'admin-bar', "/wp-includes/js/admin-bar$suffix.js", array( 'hoverintent-js' ), false, 1 );
  1233 	$scripts->add( 'admin-bar', "/wp-includes/js/admin-bar$suffix.js", array( 'hoverintent-js' ), false, 1 );
  1162 
  1234 
  1163 	$scripts->add( 'wplink', "/wp-includes/js/wplink$suffix.js", array( 'jquery', 'wp-a11y' ), false, 1 );
  1235 	$scripts->add( 'wplink', "/wp-includes/js/wplink$suffix.js", array( 'common', 'jquery', 'wp-a11y', 'wp-i18n' ), false, 1 );
       
  1236 	$scripts->set_translations( 'wplink' );
  1164 	did_action( 'init' ) && $scripts->localize(
  1237 	did_action( 'init' ) && $scripts->localize(
  1165 		'wplink',
  1238 		'wplink',
  1166 		'wpLinkL10n',
  1239 		'wpLinkL10n',
  1167 		array(
  1240 		array(
  1168 			'title'          => __( 'Insert/edit link' ),
  1241 			'title'          => __( 'Insert/edit link' ),
  1261 			'publishSettings'         => __( 'Publish Settings' ),
  1334 			'publishSettings'         => __( 'Publish Settings' ),
  1262 			'invalidDate'             => __( 'Invalid date.' ),
  1335 			'invalidDate'             => __( 'Invalid date.' ),
  1263 			'invalidValue'            => __( 'Invalid value.' ),
  1336 			'invalidValue'            => __( 'Invalid value.' ),
  1264 			'blockThemeNotification'  => sprintf(
  1337 			'blockThemeNotification'  => sprintf(
  1265 				/* translators: 1: Link to Site Editor documentation on HelpHub, 2: HTML button. */
  1338 				/* translators: 1: Link to Site Editor documentation on HelpHub, 2: HTML button. */
  1266 				__( 'Hurray! Your theme supports Full Site Editing with blocks. <a href="%1$s">Tell me more</a>. %2$s' ),
  1339 				__( 'Hurray! Your theme supports site editing with blocks. <a href="%1$s">Tell me more</a>. %2$s' ),
  1267 				__( 'https://wordpress.org/support/article/site-editor/' ),
  1340 				__( 'https://wordpress.org/documentation/article/site-editor/' ),
  1268 				sprintf(
  1341 				sprintf(
  1269 					'<button type="button" data-action="%1$s" class="button switch-to-editor">%2$s</button>',
  1342 					'<button type="button" data-action="%1$s" class="button switch-to-editor">%2$s</button>',
  1270 					esc_url( admin_url( 'site-editor.php' ) ),
  1343 					esc_url( admin_url( 'site-editor.php' ) ),
  1271 					__( 'Use Site Editor' )
  1344 					__( 'Use Site Editor' )
  1272 				)
  1345 				)
  1296 				'post'    => array( 'id' => 0 ),
  1369 				'post'    => array( 'id' => 0 ),
  1297 			),
  1370 			),
  1298 		)
  1371 		)
  1299 	);
  1372 	);
  1300 
  1373 
  1301 	$scripts->add( 'wp-embed', "/wp-includes/js/wp-embed$suffix.js", array(), false, 1 );
  1374 	$scripts->add( 'wp-embed', "/wp-includes/js/wp-embed$suffix.js" );
  1302 
  1375 	did_action( 'init' ) && $scripts->add_data( 'wp-embed', 'strategy', 'defer' );
  1303 	// To enqueue media-views or media-editor, call wp_enqueue_media().
  1376 
  1304 	// Both rely on numerous settings, styles, and templates to operate correctly.
  1377 	/*
       
  1378 	 * To enqueue media-views or media-editor, call wp_enqueue_media().
       
  1379 	 * Both rely on numerous settings, styles, and templates to operate correctly.
       
  1380 	 */
  1305 	$scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement', 'wp-api-request', 'wp-a11y', 'clipboard' ), false, 1 );
  1381 	$scripts->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 );
  1306 	$scripts->set_translations( 'media-views' );
  1382 	$scripts->set_translations( 'media-views' );
  1307 
  1383 
  1308 	$scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 );
  1384 	$scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 );
  1309 	$scripts->set_translations( 'media-editor' );
  1385 	$scripts->set_translations( 'media-editor' );
  1333 		$scripts->set_translations( 'postbox' );
  1409 		$scripts->set_translations( 'postbox' );
  1334 
  1410 
  1335 		$scripts->add( 'tags-box', "/wp-admin/js/tags-box$suffix.js", array( 'jquery', 'tags-suggest' ), false, 1 );
  1411 		$scripts->add( 'tags-box', "/wp-admin/js/tags-box$suffix.js", array( 'jquery', 'tags-suggest' ), false, 1 );
  1336 		$scripts->set_translations( 'tags-box' );
  1412 		$scripts->set_translations( 'tags-box' );
  1337 
  1413 
  1338 		$scripts->add( 'tags-suggest', "/wp-admin/js/tags-suggest$suffix.js", array( 'jquery-ui-autocomplete', 'wp-a11y' ), false, 1 );
  1414 		$scripts->add( 'tags-suggest', "/wp-admin/js/tags-suggest$suffix.js", array( 'common', 'jquery-ui-autocomplete', 'wp-a11y', 'wp-i18n' ), false, 1 );
  1339 		$scripts->set_translations( 'tags-suggest' );
  1415 		$scripts->set_translations( 'tags-suggest' );
  1340 
  1416 
  1341 		$scripts->add( 'post', "/wp-admin/js/post$suffix.js", array( 'suggest', 'wp-lists', 'postbox', 'tags-box', 'underscore', 'word-count', 'wp-a11y', 'wp-sanitize', 'clipboard' ), false, 1 );
  1417 		$scripts->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 );
  1342 		$scripts->set_translations( 'post' );
  1418 		$scripts->set_translations( 'post' );
  1343 
  1419 
  1448 
  1524 
  1449 	// Include an unmodified $wp_version.
  1525 	// Include an unmodified $wp_version.
  1450 	require ABSPATH . WPINC . '/version.php';
  1526 	require ABSPATH . WPINC . '/version.php';
  1451 
  1527 
  1452 	if ( ! defined( 'SCRIPT_DEBUG' ) ) {
  1528 	if ( ! defined( 'SCRIPT_DEBUG' ) ) {
       
  1529 		/*
       
  1530 		 * Note: str_contains() is not used here, as this file can be included
       
  1531 		 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case
       
  1532 		 * the polyfills from wp-includes/compat.php are not loaded.
       
  1533 		 */
  1453 		define( 'SCRIPT_DEBUG', false !== strpos( $wp_version, '-src' ) );
  1534 		define( 'SCRIPT_DEBUG', false !== strpos( $wp_version, '-src' ) );
  1454 	}
  1535 	}
  1455 
  1536 
  1456 	$guessurl = site_url();
  1537 	$guessurl = site_url();
  1457 
  1538 
  1540 	$styles->add_data( 'wp-embed-template-ie', 'conditional', 'lte IE 8' );
  1621 	$styles->add_data( 'wp-embed-template-ie', 'conditional', 'lte IE 8' );
  1541 
  1622 
  1542 	// External libraries and friends.
  1623 	// External libraries and friends.
  1543 	$styles->add( 'imgareaselect', '/wp-includes/js/imgareaselect/imgareaselect.css', array(), '0.9.8' );
  1624 	$styles->add( 'imgareaselect', '/wp-includes/js/imgareaselect/imgareaselect.css', array(), '0.9.8' );
  1544 	$styles->add( 'wp-jquery-ui-dialog', "/wp-includes/css/jquery-ui-dialog$suffix.css", array( 'dashicons' ) );
  1625 	$styles->add( 'wp-jquery-ui-dialog', "/wp-includes/css/jquery-ui-dialog$suffix.css", array( 'dashicons' ) );
  1545 	$styles->add( 'mediaelement', '/wp-includes/js/mediaelement/mediaelementplayer-legacy.min.css', array(), '4.2.16' );
  1626 	$styles->add( 'mediaelement', '/wp-includes/js/mediaelement/mediaelementplayer-legacy.min.css', array(), '4.2.17' );
  1546 	$styles->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement$suffix.css", array( 'mediaelement' ) );
  1627 	$styles->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement$suffix.css", array( 'mediaelement' ) );
  1547 	$styles->add( 'thickbox', '/wp-includes/js/thickbox/thickbox.css', array( 'dashicons' ) );
  1628 	$styles->add( 'thickbox', '/wp-includes/js/thickbox/thickbox.css', array( 'dashicons' ) );
  1548 	$styles->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.css', array(), '5.29.1-alpha-ee20357' );
  1629 	$styles->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.css', array(), '5.29.1-alpha-ee20357' );
  1549 
  1630 
  1550 	// Deprecated CSS.
  1631 	// Deprecated CSS.
  1581 		'wp-editor-classic-layout-styles',
  1662 		'wp-editor-classic-layout-styles',
  1582 		"/wp-includes/css/dist/edit-post/classic$suffix.css",
  1663 		"/wp-includes/css/dist/edit-post/classic$suffix.css",
  1583 		array()
  1664 		array()
  1584 	);
  1665 	);
  1585 
  1666 
       
  1667 	$styles->add(
       
  1668 		'wp-block-editor-content',
       
  1669 		"/wp-includes/css/dist/block-editor/content$suffix.css",
       
  1670 		array( 'wp-components' )
       
  1671 	);
       
  1672 
  1586 	$wp_edit_blocks_dependencies = array(
  1673 	$wp_edit_blocks_dependencies = array(
  1587 		'wp-components',
  1674 		'wp-components',
  1588 		'wp-editor',
  1675 		'wp-editor',
  1589 		// This need to be added before the block library styles,
  1676 		/*
  1590 		// The block library styles override the "reset" styles.
  1677 		 * This needs to be added before the block library styles,
       
  1678 		 * The block library styles override the "reset" styles.
       
  1679 		 */
  1591 		'wp-reset-editor-styles',
  1680 		'wp-reset-editor-styles',
  1592 		'wp-block-library',
  1681 		'wp-block-library',
  1593 		'wp-reusable-blocks',
  1682 		'wp-reusable-blocks',
       
  1683 		'wp-block-editor-content',
       
  1684 		'wp-patterns',
  1594 	);
  1685 	);
  1595 
  1686 
  1596 	// Only load the default layout and margin styles for themes without theme.json file.
  1687 	// Only load the default layout and margin styles for themes without theme.json file.
  1597 	if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) {
  1688 	if ( ! wp_theme_has_theme_json() ) {
  1598 		$wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles';
  1689 		$wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles';
  1599 	}
  1690 	}
  1600 
  1691 
  1601 	if ( ! is_array( $editor_styles ) || count( $editor_styles ) === 0 ) {
  1692 	if (
  1602 		// Include opinionated block styles if no $editor_styles are declared, so the editor never appears broken.
  1693 		current_theme_supports( 'wp-block-styles' ) &&
       
  1694 		( ! is_array( $editor_styles ) || count( $editor_styles ) === 0 )
       
  1695 	) {
       
  1696 		/*
       
  1697 		 * Include opinionated block styles if the theme supports block styles and
       
  1698 		 * no $editor_styles are declared, so the editor never appears broken.
       
  1699 		 */
  1603 		$wp_edit_blocks_dependencies[] = 'wp-block-library-theme';
  1700 		$wp_edit_blocks_dependencies[] = 'wp-block-library-theme';
  1604 	}
  1701 	}
  1605 
  1702 
  1606 	$styles->add(
  1703 	$styles->add(
  1607 		'wp-edit-blocks',
  1704 		'wp-edit-blocks',
  1608 		"/wp-includes/css/dist/block-library/editor$suffix.css",
  1705 		"/wp-includes/css/dist/block-library/editor$suffix.css",
  1609 		$wp_edit_blocks_dependencies
  1706 		$wp_edit_blocks_dependencies
  1610 	);
  1707 	);
  1611 
  1708 
  1612 	$package_styles = array(
  1709 	$package_styles = array(
  1613 		'block-editor'         => array( 'wp-components' ),
  1710 		'block-editor'         => array( 'wp-components', 'wp-preferences' ),
  1614 		'block-library'        => array(),
  1711 		'block-library'        => array(),
  1615 		'block-directory'      => array(),
  1712 		'block-directory'      => array(),
  1616 		'components'           => array(),
  1713 		'components'           => array(),
       
  1714 		'commands'             => array(),
  1617 		'edit-post'            => array(
  1715 		'edit-post'            => array(
  1618 			'wp-components',
  1716 			'wp-components',
  1619 			'wp-block-editor',
  1717 			'wp-block-editor',
  1620 			'wp-editor',
  1718 			'wp-editor',
  1621 			'wp-edit-blocks',
  1719 			'wp-edit-blocks',
  1622 			'wp-block-library',
  1720 			'wp-block-library',
  1623 			'wp-nux',
  1721 			'wp-commands',
       
  1722 			'wp-preferences',
  1624 		),
  1723 		),
  1625 		'editor'               => array(
  1724 		'editor'               => array(
  1626 			'wp-components',
  1725 			'wp-components',
  1627 			'wp-block-editor',
  1726 			'wp-block-editor',
  1628 			'wp-nux',
       
  1629 			'wp-reusable-blocks',
  1727 			'wp-reusable-blocks',
       
  1728 			'wp-patterns',
       
  1729 			'wp-preferences',
  1630 		),
  1730 		),
  1631 		'format-library'       => array(),
  1731 		'format-library'       => array(),
  1632 		'list-reusable-blocks' => array( 'wp-components' ),
  1732 		'list-reusable-blocks' => array( 'wp-components' ),
  1633 		'reusable-blocks'      => array( 'wp-components' ),
  1733 		'reusable-blocks'      => array( 'wp-components' ),
       
  1734 		'patterns'             => array( 'wp-components' ),
       
  1735 		'preferences'          => array( 'wp-components' ),
  1634 		'nux'                  => array( 'wp-components' ),
  1736 		'nux'                  => array( 'wp-components' ),
  1635 		'widgets'              => array(
  1737 		'widgets'              => array(
  1636 			'wp-components',
  1738 			'wp-components',
  1637 		),
  1739 		),
  1638 		'edit-widgets'         => array(
  1740 		'edit-widgets'         => array(
  1639 			'wp-widgets',
  1741 			'wp-widgets',
  1640 			'wp-block-editor',
  1742 			'wp-block-editor',
  1641 			'wp-edit-blocks',
  1743 			'wp-edit-blocks',
  1642 			'wp-block-library',
  1744 			'wp-block-library',
  1643 			'wp-reusable-blocks',
  1745 			'wp-reusable-blocks',
       
  1746 			'wp-patterns',
       
  1747 			'wp-preferences',
  1644 		),
  1748 		),
  1645 		'customize-widgets'    => array(
  1749 		'customize-widgets'    => array(
  1646 			'wp-widgets',
  1750 			'wp-widgets',
  1647 			'wp-block-editor',
  1751 			'wp-block-editor',
  1648 			'wp-edit-blocks',
  1752 			'wp-edit-blocks',
  1649 			'wp-block-library',
  1753 			'wp-block-library',
  1650 			'wp-reusable-blocks',
  1754 			'wp-reusable-blocks',
       
  1755 			'wp-patterns',
       
  1756 			'wp-preferences',
  1651 		),
  1757 		),
  1652 		'edit-site'            => array(
  1758 		'edit-site'            => array(
  1653 			'wp-components',
  1759 			'wp-components',
  1654 			'wp-block-editor',
  1760 			'wp-block-editor',
  1655 			'wp-edit-blocks',
  1761 			'wp-edit-blocks',
       
  1762 			'wp-commands',
       
  1763 			'wp-preferences',
  1656 		),
  1764 		),
  1657 	);
  1765 	);
  1658 
  1766 
  1659 	foreach ( $package_styles as $package => $dependencies ) {
  1767 	foreach ( $package_styles as $package => $dependencies ) {
  1660 		$handle = 'wp-' . $package;
  1768 		$handle = 'wp-' . $package;
  1706 		'wp-block-library-theme',
  1814 		'wp-block-library-theme',
  1707 		'wp-edit-blocks',
  1815 		'wp-edit-blocks',
  1708 		'wp-block-editor',
  1816 		'wp-block-editor',
  1709 		'wp-block-library',
  1817 		'wp-block-library',
  1710 		'wp-block-directory',
  1818 		'wp-block-directory',
       
  1819 		'wp-commands',
  1711 		'wp-components',
  1820 		'wp-components',
  1712 		'wp-customize-widgets',
  1821 		'wp-customize-widgets',
  1713 		'wp-edit-post',
  1822 		'wp-edit-post',
  1714 		'wp-edit-site',
  1823 		'wp-edit-site',
  1715 		'wp-edit-widgets',
  1824 		'wp-edit-widgets',
  1716 		'wp-editor',
  1825 		'wp-editor',
  1717 		'wp-format-library',
  1826 		'wp-format-library',
  1718 		'wp-list-reusable-blocks',
  1827 		'wp-list-reusable-blocks',
  1719 		'wp-reusable-blocks',
  1828 		'wp-reusable-blocks',
       
  1829 		'wp-patterns',
  1720 		'wp-nux',
  1830 		'wp-nux',
  1721 		'wp-widgets',
  1831 		'wp-widgets',
  1722 		// Deprecated CSS.
  1832 		// Deprecated CSS.
  1723 		'deprecated-media',
  1833 		'deprecated-media',
  1724 		'farbtastic',
  1834 		'farbtastic',
  1735 /**
  1845 /**
  1736  * Reorders JavaScript scripts array to place prototype before jQuery.
  1846  * Reorders JavaScript scripts array to place prototype before jQuery.
  1737  *
  1847  *
  1738  * @since 2.3.1
  1848  * @since 2.3.1
  1739  *
  1849  *
  1740  * @param array $js_array JavaScript scripts array
  1850  * @param string[] $js_array JavaScript scripts array
  1741  * @return array Reordered array, if needed.
  1851  * @return string[] Reordered array, if needed.
  1742  */
  1852  */
  1743 function wp_prototype_before_jquery( $js_array ) {
  1853 function wp_prototype_before_jquery( $js_array ) {
  1744 	$prototype = array_search( 'prototype', $js_array, true );
  1854 	$prototype = array_search( 'prototype', $js_array, true );
  1745 
  1855 
  1746 	if ( false === $prototype ) {
  1856 	if ( false === $prototype ) {
  1768  * Loads localized data on print rather than initialization.
  1878  * Loads localized data on print rather than initialization.
  1769  *
  1879  *
  1770  * These localizations require information that may not be loaded even by init.
  1880  * These localizations require information that may not be loaded even by init.
  1771  *
  1881  *
  1772  * @since 2.5.0
  1882  * @since 2.5.0
       
  1883  *
       
  1884  * @global array $shortcode_tags
  1773  */
  1885  */
  1774 function wp_just_in_time_script_localization() {
  1886 function wp_just_in_time_script_localization() {
  1775 
  1887 
  1776 	wp_localize_script(
  1888 	wp_localize_script(
  1777 		'autosave',
  1889 		'autosave',
  1792 
  1904 
  1793 	wp_localize_script(
  1905 	wp_localize_script(
  1794 		'word-count',
  1906 		'word-count',
  1795 		'wordCountL10n',
  1907 		'wordCountL10n',
  1796 		array(
  1908 		array(
  1797 			/*
  1909 			'type'       => wp_get_word_count_type(),
  1798 			 * translators: If your word count is based on single characters (e.g. East Asian characters),
       
  1799 			 * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
       
  1800 			 * Do not translate into your own language.
       
  1801 			 */
       
  1802 			'type'       => _x( 'words', 'Word count type. Do not translate!' ),
       
  1803 			'shortcodes' => ! empty( $GLOBALS['shortcode_tags'] ) ? array_keys( $GLOBALS['shortcode_tags'] ) : array(),
  1910 			'shortcodes' => ! empty( $GLOBALS['shortcode_tags'] ) ? array_keys( $GLOBALS['shortcode_tags'] ) : array(),
  1804 		)
  1911 		)
  1805 	);
  1912 	);
  1806 }
  1913 }
  1807 
  1914 
  2321 		return;
  2428 		return;
  2322 	}
  2429 	}
  2323 
  2430 
  2324 	wp_enqueue_style( 'wp-block-library' );
  2431 	wp_enqueue_style( 'wp-block-library' );
  2325 
  2432 
  2326 	if ( current_theme_supports( 'wp-block-styles' ) ) {
  2433 	if ( current_theme_supports( 'wp-block-styles' ) && ! wp_should_load_separate_core_block_assets() ) {
  2327 		if ( wp_should_load_separate_core_block_assets() ) {
  2434 		wp_enqueue_style( 'wp-block-library-theme' );
  2328 			$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'css' : 'min.css';
       
  2329 			$files  = glob( __DIR__ . "/blocks/**/theme.$suffix" );
       
  2330 			foreach ( $files as $path ) {
       
  2331 				$block_name = basename( dirname( $path ) );
       
  2332 				if ( is_rtl() && file_exists( __DIR__ . "/blocks/$block_name/theme-rtl.$suffix" ) ) {
       
  2333 					$path = __DIR__ . "/blocks/$block_name/theme-rtl.$suffix";
       
  2334 				}
       
  2335 				wp_add_inline_style( "wp-block-{$block_name}", file_get_contents( $path ) );
       
  2336 			}
       
  2337 		} else {
       
  2338 			wp_enqueue_style( 'wp-block-library-theme' );
       
  2339 		}
       
  2340 	}
  2435 	}
  2341 
  2436 
  2342 	/**
  2437 	/**
  2343 	 * Fires after enqueuing block assets for both editor and front-end.
  2438 	 * Fires after enqueuing block assets for both editor and front-end.
  2344 	 *
  2439 	 *
  2348 	 * `wp_enqueue_style` to add your functionality to the Gutenberg editor.
  2443 	 * `wp_enqueue_style` to add your functionality to the Gutenberg editor.
  2349 	 *
  2444 	 *
  2350 	 * @since 5.0.0
  2445 	 * @since 5.0.0
  2351 	 */
  2446 	 */
  2352 	do_action( 'enqueue_block_assets' );
  2447 	do_action( 'enqueue_block_assets' );
       
  2448 }
       
  2449 
       
  2450 /**
       
  2451  * Applies a filter to the list of style nodes that comes from WP_Theme_JSON::get_style_nodes().
       
  2452  *
       
  2453  * This particular filter removes all of the blocks from the array.
       
  2454  *
       
  2455  * We want WP_Theme_JSON to be ignorant of the implementation details of how the CSS is being used.
       
  2456  * This filter allows us to modify the output of WP_Theme_JSON depending on whether or not we are
       
  2457  * loading separate assets, without making the class aware of that detail.
       
  2458  *
       
  2459  * @since 6.1.0
       
  2460  *
       
  2461  * @param array $nodes The nodes to filter.
       
  2462  * @return array A filtered array of style nodes.
       
  2463  */
       
  2464 function wp_filter_out_block_nodes( $nodes ) {
       
  2465 	return array_filter(
       
  2466 		$nodes,
       
  2467 		static function ( $node ) {
       
  2468 			return ! in_array( 'blocks', $node['path'], true );
       
  2469 		},
       
  2470 		ARRAY_FILTER_USE_BOTH
       
  2471 	);
  2353 }
  2472 }
  2354 
  2473 
  2355 /**
  2474 /**
  2356  * Enqueues the global styles defined via theme.json.
  2475  * Enqueues the global styles defined via theme.json.
  2357  *
  2476  *
  2374 		( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) && $separate_assets )
  2493 		( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) && $separate_assets )
  2375 	) {
  2494 	) {
  2376 		return;
  2495 		return;
  2377 	}
  2496 	}
  2378 
  2497 
       
  2498 	/*
       
  2499 	 * If loading the CSS for each block separately, then load the theme.json CSS conditionally.
       
  2500 	 * This removes the CSS from the global-styles stylesheet and adds it to the inline CSS for each block.
       
  2501 	 * This filter must be registered before calling wp_get_global_stylesheet();
       
  2502 	 */
       
  2503 	add_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
       
  2504 
  2379 	$stylesheet = wp_get_global_stylesheet();
  2505 	$stylesheet = wp_get_global_stylesheet();
  2380 
  2506 
  2381 	if ( empty( $stylesheet ) ) {
  2507 	if ( empty( $stylesheet ) ) {
  2382 		return;
  2508 		return;
  2383 	}
  2509 	}
  2384 
  2510 
  2385 	wp_register_style( 'global-styles', false, array(), true, true );
  2511 	wp_register_style( 'global-styles', false );
  2386 	wp_add_inline_style( 'global-styles', $stylesheet );
  2512 	wp_add_inline_style( 'global-styles', $stylesheet );
  2387 	wp_enqueue_style( 'global-styles' );
  2513 	wp_enqueue_style( 'global-styles' );
  2388 }
  2514 
  2389 
  2515 	// Add each block as an inline css.
  2390 /**
  2516 	wp_add_global_styles_for_blocks();
  2391  * Renders the SVG filters supplied by theme.json.
  2517 }
  2392  *
  2518 
  2393  * Note that this doesn't render the per-block user-defined
  2519 /**
  2394  * filters which are handled by wp_render_duotone_support,
  2520  * Enqueues the global styles custom css defined via theme.json.
  2395  * but it should be rendered before the filtered content
  2521  *
  2396  * in the body to satisfy Safari's rendering quirks.
  2522  * @since 6.2.0
  2397  *
  2523  */
  2398  * @since 5.9.1
  2524 function wp_enqueue_global_styles_custom_css() {
  2399  */
  2525 	if ( ! wp_is_block_theme() ) {
  2400 function wp_global_styles_render_svg_filters() {
       
  2401 	/*
       
  2402 	 * When calling via the in_admin_header action, we only want to render the
       
  2403 	 * SVGs on block editor pages.
       
  2404 	 */
       
  2405 	if (
       
  2406 		is_admin() &&
       
  2407 		! get_current_screen()->is_block_editor()
       
  2408 	) {
       
  2409 		return;
  2526 		return;
  2410 	}
  2527 	}
  2411 
  2528 
  2412 	$filters = wp_get_global_styles_svg_filters();
  2529 	// Don't enqueue Customizer's custom CSS separately.
  2413 	if ( ! empty( $filters ) ) {
  2530 	remove_action( 'wp_head', 'wp_custom_css_cb', 101 );
  2414 		echo $filters;
  2531 
       
  2532 	$custom_css  = wp_get_custom_css();
       
  2533 	$custom_css .= wp_get_global_styles_custom_css();
       
  2534 
       
  2535 	if ( ! empty( $custom_css ) ) {
       
  2536 		wp_add_inline_style( 'global-styles', $custom_css );
  2415 	}
  2537 	}
  2416 }
  2538 }
  2417 
  2539 
  2418 /**
  2540 /**
  2419  * Checks if the editor scripts and styles for all registered block types
  2541  * Checks if the editor scripts and styles for all registered block types
  2461  * @since 5.8.0
  2583  * @since 5.8.0
  2462  *
  2584  *
  2463  * @return bool Whether separate assets will be loaded.
  2585  * @return bool Whether separate assets will be loaded.
  2464  */
  2586  */
  2465 function wp_should_load_separate_core_block_assets() {
  2587 function wp_should_load_separate_core_block_assets() {
  2466 	if ( is_admin() || is_feed() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
  2588 	if ( is_admin() || is_feed() || wp_is_rest_endpoint() ) {
  2467 		return false;
  2589 		return false;
  2468 	}
  2590 	}
  2469 
  2591 
  2470 	/**
  2592 	/**
  2471 	 * Filters whether block styles should be loaded separately.
  2593 	 * Filters whether block styles should be loaded separately.
  2494 
  2616 
  2495 	if ( wp_should_load_separate_core_block_assets() ) {
  2617 	if ( wp_should_load_separate_core_block_assets() ) {
  2496 		return;
  2618 		return;
  2497 	}
  2619 	}
  2498 
  2620 
  2499 	$load_editor_scripts = is_admin() && wp_should_load_block_editor_scripts_and_styles();
  2621 	$load_editor_scripts_and_styles = is_admin() && wp_should_load_block_editor_scripts_and_styles();
  2500 
  2622 
  2501 	$block_registry = WP_Block_Type_Registry::get_instance();
  2623 	$block_registry = WP_Block_Type_Registry::get_instance();
  2502 	foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) {
  2624 	foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) {
  2503 		// Front-end styles.
  2625 		// Front-end and editor styles.
  2504 		if ( ! empty( $block_type->style ) ) {
  2626 		foreach ( $block_type->style_handles as $style_handle ) {
  2505 			wp_enqueue_style( $block_type->style );
  2627 			wp_enqueue_style( $style_handle );
  2506 		}
  2628 		}
  2507 
  2629 
  2508 		// Front-end script.
  2630 		// Front-end and editor scripts.
  2509 		if ( ! empty( $block_type->script ) ) {
  2631 		foreach ( $block_type->script_handles as $script_handle ) {
  2510 			wp_enqueue_script( $block_type->script );
  2632 			wp_enqueue_script( $script_handle );
  2511 		}
  2633 		}
  2512 
  2634 
  2513 		// Editor styles.
  2635 		if ( $load_editor_scripts_and_styles ) {
  2514 		if ( $load_editor_scripts && ! empty( $block_type->editor_style ) ) {
  2636 			// Editor styles.
  2515 			wp_enqueue_style( $block_type->editor_style );
  2637 			foreach ( $block_type->editor_style_handles as $editor_style_handle ) {
  2516 		}
  2638 				wp_enqueue_style( $editor_style_handle );
  2517 
  2639 			}
  2518 		// Editor script.
  2640 
  2519 		if ( $load_editor_scripts && ! empty( $block_type->editor_script ) ) {
  2641 			// Editor scripts.
  2520 			wp_enqueue_script( $block_type->editor_script );
  2642 			foreach ( $block_type->editor_script_handles as $editor_script_handle ) {
       
  2643 				wp_enqueue_script( $editor_script_handle );
       
  2644 			}
  2521 		}
  2645 		}
  2522 	}
  2646 	}
  2523 }
  2647 }
  2524 
  2648 
  2525 /**
  2649 /**
  2540 
  2664 
  2541 				// If the site loads separate styles per-block, enqueue the stylesheet on render.
  2665 				// If the site loads separate styles per-block, enqueue the stylesheet on render.
  2542 				if ( wp_should_load_separate_core_block_assets() ) {
  2666 				if ( wp_should_load_separate_core_block_assets() ) {
  2543 					add_filter(
  2667 					add_filter(
  2544 						'render_block',
  2668 						'render_block',
  2545 						function( $html, $block ) use ( $block_name, $style_properties ) {
  2669 						static function ( $html, $block ) use ( $block_name, $style_properties ) {
  2546 							if ( $block['blockName'] === $block_name ) {
  2670 							if ( $block['blockName'] === $block_name ) {
  2547 								wp_enqueue_style( $style_properties['style_handle'] );
  2671 								wp_enqueue_style( $style_properties['style_handle'] );
  2548 							}
  2672 							}
  2549 							return $html;
  2673 							return $html;
  2550 						},
  2674 						},
  2602 		}
  2726 		}
  2603 	}
  2727 	}
  2604 	$register_script_lines[] = '} )();';
  2728 	$register_script_lines[] = '} )();';
  2605 	$inline_script           = implode( "\n", $register_script_lines );
  2729 	$inline_script           = implode( "\n", $register_script_lines );
  2606 
  2730 
  2607 	wp_register_script( 'wp-block-styles', false, array( 'wp-blocks' ), true, true );
  2731 	wp_register_script( 'wp-block-styles', false, array( 'wp-blocks' ), true, array( 'in_footer' => true ) );
  2608 	wp_add_inline_script( 'wp-block-styles', $inline_script );
  2732 	wp_add_inline_script( 'wp-block-styles', $inline_script );
  2609 	wp_enqueue_script( 'wp-block-styles' );
  2733 	wp_enqueue_script( 'wp-block-styles' );
  2610 }
  2734 }
  2611 
  2735 
  2612 /**
  2736 /**
  2642  */
  2766  */
  2643 function wp_sanitize_script_attributes( $attributes ) {
  2767 function wp_sanitize_script_attributes( $attributes ) {
  2644 	$html5_script_support = ! is_admin() && ! current_theme_supports( 'html5', 'script' );
  2768 	$html5_script_support = ! is_admin() && ! current_theme_supports( 'html5', 'script' );
  2645 	$attributes_string    = '';
  2769 	$attributes_string    = '';
  2646 
  2770 
  2647 	// If HTML5 script tag is supported, only the attribute name is added
  2771 	/*
  2648 	// to $attributes_string for entries with a boolean value, and that are true.
  2772 	 * If HTML5 script tag is supported, only the attribute name is added
       
  2773 	 * to $attributes_string for entries with a boolean value, and that are true.
       
  2774 	 */
  2649 	foreach ( $attributes as $attribute_name => $attribute_value ) {
  2775 	foreach ( $attributes as $attribute_name => $attribute_value ) {
  2650 		if ( is_bool( $attribute_value ) ) {
  2776 		if ( is_bool( $attribute_value ) ) {
  2651 			if ( $attribute_value ) {
  2777 			if ( $attribute_value ) {
  2652 				$attributes_string .= $html5_script_support ? sprintf( ' %1$s="%2$s"', esc_attr( $attribute_name ), esc_attr( $attribute_name ) ) : ' ' . esc_attr( $attribute_name );
  2778 				$attributes_string .= $html5_script_support ? sprintf( ' %1$s="%2$s"', esc_attr( $attribute_name ), esc_attr( $attribute_name ) ) : ' ' . esc_attr( $attribute_name );
  2653 			}
  2779 			}
  2670  * @param array $attributes Key-value pairs representing `<script>` tag attributes.
  2796  * @param array $attributes Key-value pairs representing `<script>` tag attributes.
  2671  * @return string String containing `<script>` opening and closing tags.
  2797  * @return string String containing `<script>` opening and closing tags.
  2672  */
  2798  */
  2673 function wp_get_script_tag( $attributes ) {
  2799 function wp_get_script_tag( $attributes ) {
  2674 	if ( ! isset( $attributes['type'] ) && ! is_admin() && ! current_theme_supports( 'html5', 'script' ) ) {
  2800 	if ( ! isset( $attributes['type'] ) && ! is_admin() && ! current_theme_supports( 'html5', 'script' ) ) {
  2675 		$attributes['type'] = 'text/javascript';
  2801 		// Keep the type attribute as the first for legacy reasons (it has always been this way in core).
       
  2802 		$attributes = array_merge(
       
  2803 			array( 'type' => 'text/javascript' ),
       
  2804 			$attributes
       
  2805 		);
  2676 	}
  2806 	}
  2677 	/**
  2807 	/**
  2678 	 * Filters attributes to be added to a script tag.
  2808 	 * Filters attributes to be added to a script tag.
  2679 	 *
  2809 	 *
  2680 	 * @since 5.7.0
  2810 	 * @since 5.7.0
  2701 function wp_print_script_tag( $attributes ) {
  2831 function wp_print_script_tag( $attributes ) {
  2702 	echo wp_get_script_tag( $attributes );
  2832 	echo wp_get_script_tag( $attributes );
  2703 }
  2833 }
  2704 
  2834 
  2705 /**
  2835 /**
  2706  * Wraps inline JavaScript in `<script>` tag.
  2836  * Constructs an inline script tag.
  2707  *
  2837  *
  2708  * It is possible to inject attributes in the `<script>` tag via the  {@see 'wp_script_attributes'}  filter.
  2838  * It is possible to inject attributes in the `<script>` tag via the  {@see 'wp_script_attributes'}  filter.
  2709  * Automatically injects type attribute if needed.
  2839  * Automatically injects type attribute if needed.
  2710  *
  2840  *
  2711  * @since 5.7.0
  2841  * @since 5.7.0
  2712  *
  2842  *
  2713  * @param string $javascript Inline JavaScript code.
  2843  * @param string $data       Data for script tag: JavaScript, importmap, speculationrules, etc.
  2714  * @param array  $attributes Optional. Key-value pairs representing `<script>` tag attributes.
  2844  * @param array  $attributes Optional. Key-value pairs representing `<script>` tag attributes.
  2715  * @return string String containing inline JavaScript code wrapped around `<script>` tag.
  2845  * @return string String containing inline JavaScript code wrapped around `<script>` tag.
  2716  */
  2846  */
  2717 function wp_get_inline_script_tag( $javascript, $attributes = array() ) {
  2847 function wp_get_inline_script_tag( $data, $attributes = array() ) {
  2718 	if ( ! isset( $attributes['type'] ) && ! is_admin() && ! current_theme_supports( 'html5', 'script' ) ) {
  2848 	$is_html5 = current_theme_supports( 'html5', 'script' ) || is_admin();
  2719 		$attributes['type'] = 'text/javascript';
  2849 	if ( ! isset( $attributes['type'] ) && ! $is_html5 ) {
  2720 	}
  2850 		// Keep the type attribute as the first for legacy reasons (it has always been this way in core).
       
  2851 		$attributes = array_merge(
       
  2852 			array( 'type' => 'text/javascript' ),
       
  2853 			$attributes
       
  2854 		);
       
  2855 	}
       
  2856 
       
  2857 	/*
       
  2858 	 * XHTML extracts the contents of the SCRIPT element and then the XML parser
       
  2859 	 * decodes character references and other syntax elements. This can lead to
       
  2860 	 * misinterpretation of the script contents or invalid XHTML documents.
       
  2861 	 *
       
  2862 	 * Wrapping the contents in a CDATA section instructs the XML parser not to
       
  2863 	 * transform the contents of the SCRIPT element before passing them to the
       
  2864 	 * JavaScript engine.
       
  2865 	 *
       
  2866 	 * Example:
       
  2867 	 *
       
  2868 	 *     <script>console.log('&hellip;');</script>
       
  2869 	 *
       
  2870 	 *     In an HTML document this would print "&hellip;" to the console,
       
  2871 	 *     but in an XHTML document it would print "…" to the console.
       
  2872 	 *
       
  2873 	 *     <script>console.log('An image is <img> in HTML');</script>
       
  2874 	 *
       
  2875 	 *     In an HTML document this would print "An image is <img> in HTML",
       
  2876 	 *     but it's an invalid XHTML document because it interprets the `<img>`
       
  2877 	 *     as an empty tag missing its closing `/`.
       
  2878 	 *
       
  2879 	 * @see https://www.w3.org/TR/xhtml1/#h-4.8
       
  2880 	 */
       
  2881 	if (
       
  2882 		! $is_html5 &&
       
  2883 		(
       
  2884 			! isset( $attributes['type'] ) ||
       
  2885 			'module' === $attributes['type'] ||
       
  2886 			str_contains( $attributes['type'], 'javascript' ) ||
       
  2887 			str_contains( $attributes['type'], 'ecmascript' ) ||
       
  2888 			str_contains( $attributes['type'], 'jscript' ) ||
       
  2889 			str_contains( $attributes['type'], 'livescript' )
       
  2890 		)
       
  2891 	) {
       
  2892 		/*
       
  2893 		 * If the string `]]>` exists within the JavaScript it would break
       
  2894 		 * out of any wrapping CDATA section added here, so to start, it's
       
  2895 		 * necessary to escape that sequence which requires splitting the
       
  2896 		 * content into two CDATA sections wherever it's found.
       
  2897 		 *
       
  2898 		 * Note: it's only necessary to escape the closing `]]>` because
       
  2899 		 * an additional `<![CDATA[` leaves the contents unchanged.
       
  2900 		 */
       
  2901 		$data = str_replace( ']]>', ']]]]><![CDATA[>', $data );
       
  2902 
       
  2903 		// Wrap the entire escaped script inside a CDATA section.
       
  2904 		$data = sprintf( "/* <![CDATA[ */\n%s\n/* ]]> */", $data );
       
  2905 	}
       
  2906 
       
  2907 	$data = "\n" . trim( $data, "\n\r " ) . "\n";
       
  2908 
  2721 	/**
  2909 	/**
  2722 	 * Filters attributes to be added to a script tag.
  2910 	 * Filters attributes to be added to a script tag.
  2723 	 *
  2911 	 *
  2724 	 * @since 5.7.0
  2912 	 * @since 5.7.0
  2725 	 *
  2913 	 *
  2726 	 * @param array  $attributes Key-value pairs representing `<script>` tag attributes.
  2914 	 * @param array  $attributes Key-value pairs representing `<script>` tag attributes.
  2727 	 *                           Only the attribute name is added to the `<script>` tag for
  2915 	 *                           Only the attribute name is added to the `<script>` tag for
  2728 	 *                           entries with a boolean value, and that are true.
  2916 	 *                           entries with a boolean value, and that are true.
  2729 	 * @param string $javascript Inline JavaScript code.
  2917 	 * @param string $data       Inline data.
  2730 	 */
  2918 	 */
  2731 	$attributes = apply_filters( 'wp_inline_script_attributes', $attributes, $javascript );
  2919 	$attributes = apply_filters( 'wp_inline_script_attributes', $attributes, $data );
  2732 
  2920 
  2733 	$javascript = "\n" . trim( $javascript, "\n\r " ) . "\n";
  2921 	return sprintf( "<script%s>%s</script>\n", wp_sanitize_script_attributes( $attributes ), $data );
  2734 
  2922 }
  2735 	return sprintf( "<script%s>%s</script>\n", wp_sanitize_script_attributes( $attributes ), $javascript );
  2923 
  2736 }
  2924 /**
  2737 
  2925  * Prints an inline script tag.
  2738 /**
       
  2739  * Prints inline JavaScript wrapped in `<script>` tag.
       
  2740  *
  2926  *
  2741  * It is possible to inject attributes in the `<script>` tag via the  {@see 'wp_script_attributes'}  filter.
  2927  * It is possible to inject attributes in the `<script>` tag via the  {@see 'wp_script_attributes'}  filter.
  2742  * Automatically injects type attribute if needed.
  2928  * Automatically injects type attribute if needed.
  2743  *
  2929  *
  2744  * @since 5.7.0
  2930  * @since 5.7.0
  2745  *
  2931  *
  2746  * @param string $javascript Inline JavaScript code.
  2932  * @param string $data       Data for script tag: JavaScript, importmap, speculationrules, etc.
  2747  * @param array  $attributes Optional. Key-value pairs representing `<script>` tag attributes.
  2933  * @param array  $attributes Optional. Key-value pairs representing `<script>` tag attributes.
  2748  */
  2934  */
  2749 function wp_print_inline_script_tag( $javascript, $attributes = array() ) {
  2935 function wp_print_inline_script_tag( $data, $attributes = array() ) {
  2750 	echo wp_get_inline_script_tag( $javascript, $attributes );
  2936 	echo wp_get_inline_script_tag( $data, $attributes );
  2751 }
  2937 }
  2752 
  2938 
  2753 /**
  2939 /**
  2754  * Allows small styles to be inlined.
  2940  * Allows small styles to be inlined.
  2755  *
  2941  *
  2777 
  2963 
  2778 	$styles = array();
  2964 	$styles = array();
  2779 
  2965 
  2780 	// Build an array of styles that have a path defined.
  2966 	// Build an array of styles that have a path defined.
  2781 	foreach ( $wp_styles->queue as $handle ) {
  2967 	foreach ( $wp_styles->queue as $handle ) {
  2782 		if ( wp_styles()->get_data( $handle, 'path' ) && file_exists( $wp_styles->registered[ $handle ]->extra['path'] ) ) {
  2968 		if ( ! isset( $wp_styles->registered[ $handle ] ) ) {
       
  2969 			continue;
       
  2970 		}
       
  2971 		$src  = $wp_styles->registered[ $handle ]->src;
       
  2972 		$path = $wp_styles->get_data( $handle, 'path' );
       
  2973 		if ( $path && $src ) {
       
  2974 			$size = wp_filesize( $path );
       
  2975 			if ( ! $size ) {
       
  2976 				continue;
       
  2977 			}
  2783 			$styles[] = array(
  2978 			$styles[] = array(
  2784 				'handle' => $handle,
  2979 				'handle' => $handle,
  2785 				'src'    => $wp_styles->registered[ $handle ]->src,
  2980 				'src'    => $src,
  2786 				'path'   => $wp_styles->registered[ $handle ]->extra['path'],
  2981 				'path'   => $path,
  2787 				'size'   => filesize( $wp_styles->registered[ $handle ]->extra['path'] ),
  2982 				'size'   => $size,
  2788 			);
  2983 			);
  2789 		}
  2984 		}
  2790 	}
  2985 	}
  2791 
  2986 
  2792 	if ( ! empty( $styles ) ) {
  2987 	if ( ! empty( $styles ) ) {
  2793 		// Reorder styles array based on size.
  2988 		// Reorder styles array based on size.
  2794 		usort(
  2989 		usort(
  2795 			$styles,
  2990 			$styles,
  2796 			static function( $a, $b ) {
  2991 			static function ( $a, $b ) {
  2797 				return ( $a['size'] <= $b['size'] ) ? -1 : 1;
  2992 				return ( $a['size'] <= $b['size'] ) ? -1 : 1;
  2798 			}
  2993 			}
  2799 		);
  2994 		);
  2800 
  2995 
  2801 		/*
  2996 		/*
  2815 			}
  3010 			}
  2816 
  3011 
  2817 			// Get the styles if we don't already have them.
  3012 			// Get the styles if we don't already have them.
  2818 			$style['css'] = file_get_contents( $style['path'] );
  3013 			$style['css'] = file_get_contents( $style['path'] );
  2819 
  3014 
  2820 			// Check if the style contains relative URLs that need to be modified.
  3015 			/*
  2821 			// URLs relative to the stylesheet's path should be converted to relative to the site's root.
  3016 			 * Check if the style contains relative URLs that need to be modified.
       
  3017 			 * URLs relative to the stylesheet's path should be converted to relative to the site's root.
       
  3018 			 */
  2822 			$style['css'] = _wp_normalize_relative_css_links( $style['css'], $style['src'] );
  3019 			$style['css'] = _wp_normalize_relative_css_links( $style['css'], $style['src'] );
  2823 
  3020 
  2824 			// Set `src` to `false` and add styles inline.
  3021 			// Set `src` to `false` and add styles inline.
  2825 			$wp_styles->registered[ $style['handle'] ]->src = false;
  3022 			$wp_styles->registered[ $style['handle'] ]->src = false;
  2826 			if ( empty( $wp_styles->registered[ $style['handle'] ]->extra['after'] ) ) {
  3023 			if ( empty( $wp_styles->registered[ $style['handle'] ]->extra['after'] ) ) {
  2844  * @param string $stylesheet_url The URL to the stylesheet.
  3041  * @param string $stylesheet_url The URL to the stylesheet.
  2845  *
  3042  *
  2846  * @return string The CSS with URLs made relative to the WordPress installation.
  3043  * @return string The CSS with URLs made relative to the WordPress installation.
  2847  */
  3044  */
  2848 function _wp_normalize_relative_css_links( $css, $stylesheet_url ) {
  3045 function _wp_normalize_relative_css_links( $css, $stylesheet_url ) {
  2849 	$has_src_results = preg_match_all( '#url\s*\(\s*[\'"]?\s*([^\'"\)]+)#', $css, $src_results );
  3046 	return preg_replace_callback(
  2850 	if ( $has_src_results ) {
  3047 		'#(url\s*\(\s*[\'"]?\s*)([^\'"\)]+)#',
  2851 		// Loop through the URLs to find relative ones.
  3048 		static function ( $matches ) use ( $stylesheet_url ) {
  2852 		foreach ( $src_results[1] as $src_index => $src_result ) {
  3049 			list( , $prefix, $url ) = $matches;
  2853 			// Skip if this is an absolute URL.
  3050 
  2854 			if ( 0 === strpos( $src_result, 'http' ) || 0 === strpos( $src_result, '//' ) ) {
  3051 			// Short-circuit if the URL does not require normalization.
  2855 				continue;
  3052 			if (
       
  3053 				str_starts_with( $url, 'http:' ) ||
       
  3054 				str_starts_with( $url, 'https:' ) ||
       
  3055 				str_starts_with( $url, '//' ) ||
       
  3056 				str_starts_with( $url, '#' ) ||
       
  3057 				str_starts_with( $url, 'data:' )
       
  3058 			) {
       
  3059 				return $matches[0];
  2856 			}
  3060 			}
  2857 
  3061 
  2858 			// Skip if the URL is an HTML ID.
       
  2859 			if ( str_starts_with( $src_result, '#' ) ) {
       
  2860 				continue;
       
  2861 			}
       
  2862 
       
  2863 			// Skip if the URL is a data URI.
       
  2864 			if ( str_starts_with( $src_result, 'data:' ) ) {
       
  2865 				continue;
       
  2866 			}
       
  2867 
       
  2868 			// Build the absolute URL.
  3062 			// Build the absolute URL.
  2869 			$absolute_url = dirname( $stylesheet_url ) . '/' . $src_result;
  3063 			$absolute_url = dirname( $stylesheet_url ) . '/' . $url;
  2870 			$absolute_url = str_replace( '/./', '/', $absolute_url );
  3064 			$absolute_url = str_replace( '/./', '/', $absolute_url );
       
  3065 
  2871 			// Convert to URL related to the site root.
  3066 			// Convert to URL related to the site root.
  2872 			$relative_url = wp_make_link_relative( $absolute_url );
  3067 			$url = wp_make_link_relative( $absolute_url );
  2873 
  3068 
  2874 			// Replace the URL in the CSS.
  3069 			return $prefix . $url;
  2875 			$css = str_replace(
  3070 		},
  2876 				$src_results[0][ $src_index ],
  3071 		$css
  2877 				str_replace( $src_result, $relative_url, $src_results[0][ $src_index ] ),
  3072 	);
  2878 				$css
       
  2879 			);
       
  2880 		}
       
  2881 	}
       
  2882 
       
  2883 	return $css;
       
  2884 }
  3073 }
  2885 
  3074 
  2886 /**
  3075 /**
  2887  * Function that enqueues the CSS Custom Properties coming from theme.json.
  3076  * Function that enqueues the CSS Custom Properties coming from theme.json.
  2888  *
  3077  *
  2889  * @since 5.9.0
  3078  * @since 5.9.0
  2890  */
  3079  */
  2891 function wp_enqueue_global_styles_css_custom_properties() {
  3080 function wp_enqueue_global_styles_css_custom_properties() {
  2892 	wp_register_style( 'global-styles-css-custom-properties', false, array(), true, true );
  3081 	wp_register_style( 'global-styles-css-custom-properties', false );
  2893 	wp_add_inline_style( 'global-styles-css-custom-properties', wp_get_global_stylesheet( array( 'variables' ) ) );
  3082 	wp_add_inline_style( 'global-styles-css-custom-properties', wp_get_global_stylesheet( array( 'variables' ) ) );
  2894 	wp_enqueue_style( 'global-styles-css-custom-properties' );
  3083 	wp_enqueue_style( 'global-styles-css-custom-properties' );
  2895 }
  3084 }
  2896 
  3085 
  2897 /**
  3086 /**
  2898  * This function takes care of adding inline styles
  3087  * Hooks inline styles in the proper place, depending on the active theme.
  2899  * in the proper place, depending on the theme in use.
       
  2900  *
  3088  *
  2901  * @since 5.9.1
  3089  * @since 5.9.1
  2902  *
  3090  * @since 6.1.0 Added the `$priority` parameter.
  2903  * For block themes, it's loaded in the head.
  3091  *
  2904  * For classic ones, it's loaded in the body
  3092  * For block themes, styles are loaded in the head.
  2905  * because the wp_head action happens before
  3093  * For classic ones, styles are loaded in the body because the wp_head action happens before render_block.
  2906  * the render_block.
       
  2907  *
  3094  *
  2908  * @link https://core.trac.wordpress.org/ticket/53494.
  3095  * @link https://core.trac.wordpress.org/ticket/53494.
  2909  *
  3096  *
  2910  * @param string $style String containing the CSS styles to be added.
  3097  * @param string $style    String containing the CSS styles to be added.
  2911  */
  3098  * @param int    $priority To set the priority for the add_action.
  2912 function wp_enqueue_block_support_styles( $style ) {
  3099  */
       
  3100 function wp_enqueue_block_support_styles( $style, $priority = 10 ) {
  2913 	$action_hook_name = 'wp_footer';
  3101 	$action_hook_name = 'wp_footer';
  2914 	if ( wp_is_block_theme() ) {
  3102 	if ( wp_is_block_theme() ) {
  2915 		$action_hook_name = 'wp_head';
  3103 		$action_hook_name = 'wp_head';
  2916 	}
  3104 	}
  2917 	add_action(
  3105 	add_action(
  2918 		$action_hook_name,
  3106 		$action_hook_name,
  2919 		static function () use ( $style ) {
  3107 		static function () use ( $style ) {
  2920 			echo "<style>$style</style>\n";
  3108 			echo "<style>$style</style>\n";
  2921 		}
  3109 		},
  2922 	);
  3110 		$priority
       
  3111 	);
       
  3112 }
       
  3113 
       
  3114 /**
       
  3115  * Fetches, processes and compiles stored core styles, then combines and renders them to the page.
       
  3116  * Styles are stored via the style engine API.
       
  3117  *
       
  3118  * @link https://developer.wordpress.org/block-editor/reference-guides/packages/packages-style-engine/
       
  3119  *
       
  3120  * @since 6.1.0
       
  3121  *
       
  3122  * @param array $options {
       
  3123  *     Optional. An array of options to pass to wp_style_engine_get_stylesheet_from_context().
       
  3124  *     Default empty array.
       
  3125  *
       
  3126  *     @type bool $optimize Whether to optimize the CSS output, e.g., combine rules.
       
  3127  *                          Default false.
       
  3128  *     @type bool $prettify Whether to add new lines and indents to output.
       
  3129  *                          Default to whether the `SCRIPT_DEBUG` constant is defined.
       
  3130  * }
       
  3131  */
       
  3132 function wp_enqueue_stored_styles( $options = array() ) {
       
  3133 	$is_block_theme   = wp_is_block_theme();
       
  3134 	$is_classic_theme = ! $is_block_theme;
       
  3135 
       
  3136 	/*
       
  3137 	 * For block themes, this function prints stored styles in the header.
       
  3138 	 * For classic themes, in the footer.
       
  3139 	 */
       
  3140 	if (
       
  3141 		( $is_block_theme && doing_action( 'wp_footer' ) ) ||
       
  3142 		( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) )
       
  3143 	) {
       
  3144 		return;
       
  3145 	}
       
  3146 
       
  3147 	$core_styles_keys         = array( 'block-supports' );
       
  3148 	$compiled_core_stylesheet = '';
       
  3149 	$style_tag_id             = 'core';
       
  3150 	// Adds comment if code is prettified to identify core styles sections in debugging.
       
  3151 	$should_prettify = isset( $options['prettify'] ) ? true === $options['prettify'] : defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
       
  3152 	foreach ( $core_styles_keys as $style_key ) {
       
  3153 		if ( $should_prettify ) {
       
  3154 			$compiled_core_stylesheet .= "/**\n * Core styles: $style_key\n */\n";
       
  3155 		}
       
  3156 		// Chains core store ids to signify what the styles contain.
       
  3157 		$style_tag_id             .= '-' . $style_key;
       
  3158 		$compiled_core_stylesheet .= wp_style_engine_get_stylesheet_from_context( $style_key, $options );
       
  3159 	}
       
  3160 
       
  3161 	// Combines Core styles.
       
  3162 	if ( ! empty( $compiled_core_stylesheet ) ) {
       
  3163 		wp_register_style( $style_tag_id, false );
       
  3164 		wp_add_inline_style( $style_tag_id, $compiled_core_stylesheet );
       
  3165 		wp_enqueue_style( $style_tag_id );
       
  3166 	}
       
  3167 
       
  3168 	// Prints out any other stores registered by themes or otherwise.
       
  3169 	$additional_stores = WP_Style_Engine_CSS_Rules_Store::get_stores();
       
  3170 	foreach ( array_keys( $additional_stores ) as $store_name ) {
       
  3171 		if ( in_array( $store_name, $core_styles_keys, true ) ) {
       
  3172 			continue;
       
  3173 		}
       
  3174 		$styles = wp_style_engine_get_stylesheet_from_context( $store_name, $options );
       
  3175 		if ( ! empty( $styles ) ) {
       
  3176 			$key = "wp-style-engine-$store_name";
       
  3177 			wp_register_style( $key, false );
       
  3178 			wp_add_inline_style( $key, $styles );
       
  3179 			wp_enqueue_style( $key );
       
  3180 		}
       
  3181 	}
  2923 }
  3182 }
  2924 
  3183 
  2925 /**
  3184 /**
  2926  * Enqueues a stylesheet for a specific block.
  3185  * Enqueues a stylesheet for a specific block.
  2927  *
  3186  *
  2930  * otherwise when the block inits.
  3189  * otherwise when the block inits.
  2931  *
  3190  *
  2932  * @since 5.9.0
  3191  * @since 5.9.0
  2933  *
  3192  *
  2934  * @param string $block_name The block-name, including namespace.
  3193  * @param string $block_name The block-name, including namespace.
  2935  * @param array  $args       An array of arguments [handle,src,deps,ver,media].
  3194  * @param array  $args       {
       
  3195  *     An array of arguments. See wp_register_style() for full information about each argument.
       
  3196  *
       
  3197  *     @type string           $handle The handle for the stylesheet.
       
  3198  *     @type string|false     $src    The source URL of the stylesheet.
       
  3199  *     @type string[]         $deps   Array of registered stylesheet handles this stylesheet depends on.
       
  3200  *     @type string|bool|null $ver    Stylesheet version number.
       
  3201  *     @type string           $media  The media for which this stylesheet has been defined.
       
  3202  *     @type string|null      $path   Absolute path to the stylesheet, so that it can potentially be inlined.
       
  3203  * }
  2936  */
  3204  */
  2937 function wp_enqueue_block_style( $block_name, $args ) {
  3205 function wp_enqueue_block_style( $block_name, $args ) {
  2938 	$args = wp_parse_args(
  3206 	$args = wp_parse_args(
  2939 		$args,
  3207 		$args,
  2940 		array(
  3208 		array(
  2952 	 * @param string $content When the callback is used for the render_block filter,
  3220 	 * @param string $content When the callback is used for the render_block filter,
  2953 	 *                        the content needs to be returned so the function parameter
  3221 	 *                        the content needs to be returned so the function parameter
  2954 	 *                        is to ensure the content exists.
  3222 	 *                        is to ensure the content exists.
  2955 	 * @return string Block content.
  3223 	 * @return string Block content.
  2956 	 */
  3224 	 */
  2957 	$callback = static function( $content ) use ( $args ) {
  3225 	$callback = static function ( $content ) use ( $args ) {
  2958 		// Register the stylesheet.
  3226 		// Register the stylesheet.
  2959 		if ( ! empty( $args['src'] ) ) {
  3227 		if ( ! empty( $args['src'] ) ) {
  2960 			wp_register_style( $args['handle'], $args['src'], $args['deps'], $args['ver'], $args['media'] );
  3228 			wp_register_style( $args['handle'], $args['src'], $args['deps'], $args['ver'], $args['media'] );
  2961 		}
  3229 		}
  2962 
  3230 
  2990 		 *
  3258 		 *
  2991 		 * @param string $content The block content.
  3259 		 * @param string $content The block content.
  2992 		 * @param array  $block   The full block, including name and attributes.
  3260 		 * @param array  $block   The full block, including name and attributes.
  2993 		 * @return string Block content.
  3261 		 * @return string Block content.
  2994 		 */
  3262 		 */
  2995 		$callback_separate = static function( $content, $block ) use ( $block_name, $callback ) {
  3263 		$callback_separate = static function ( $content, $block ) use ( $block_name, $callback ) {
  2996 			if ( ! empty( $block['blockName'] ) && $block_name === $block['blockName'] ) {
  3264 			if ( ! empty( $block['blockName'] ) && $block_name === $block['blockName'] ) {
  2997 				return $callback( $content );
  3265 				return $callback( $content );
  2998 			}
  3266 			}
  2999 			return $content;
  3267 			return $content;
  3000 		};
  3268 		};
  3026 	// Enqueue assets in the editor.
  3294 	// Enqueue assets in the editor.
  3027 	add_action( 'enqueue_block_assets', $callback );
  3295 	add_action( 'enqueue_block_assets', $callback );
  3028 }
  3296 }
  3029 
  3297 
  3030 /**
  3298 /**
  3031  * Runs the theme.json webfonts handler.
  3299  * Loads classic theme styles on classic themes in the frontend.
  3032  *
  3300  *
  3033  * Using `WP_Theme_JSON_Resolver`, it gets the fonts defined
  3301  * This is needed for backwards compatibility for button blocks specifically.
  3034  * in the `theme.json` for the current selection and style
  3302  *
  3035  * variations, validates the font-face properties, generates
  3303  * @since 6.1.0
  3036  * the '@font-face' style declarations, and then enqueues the
  3304  */
  3037  * styles for both the editor and front-end.
  3305 function wp_enqueue_classic_theme_styles() {
  3038  *
  3306 	if ( ! wp_theme_has_theme_json() ) {
  3039  * Design Notes:
  3307 		$suffix = wp_scripts_get_suffix();
  3040  * This is not a public API, but rather an internal handler.
  3308 		wp_register_style( 'classic-theme-styles', '/' . WPINC . "/css/classic-themes$suffix.css" );
  3041  * A future public Webfonts API will replace this stopgap code.
  3309 		wp_style_add_data( 'classic-theme-styles', 'path', ABSPATH . WPINC . "/css/classic-themes$suffix.css" );
  3042  *
  3310 		wp_enqueue_style( 'classic-theme-styles' );
  3043  * This code design is intentional.
  3311 	}
  3044  *    a. It hides the inner-workings.
  3312 }
  3045  *    b. It does not expose API ins or outs for consumption.
  3313 
  3046  *    c. It only works with a theme's `theme.json`.
  3314 /**
  3047  *
  3315  * Loads classic theme styles on classic themes in the editor.
  3048  * Why?
  3316  *
  3049  *    a. To avoid backwards-compatibility issues when
  3317  * This is needed for backwards compatibility for button blocks specifically.
  3050  *       the Webfonts API is introduced in Core.
  3318  *
  3051  *    b. To make `fontFace` declarations in `theme.json` work.
  3319  * @since 6.1.0
  3052  *
  3320  *
  3053  * @link  https://github.com/WordPress/gutenberg/issues/40472
  3321  * @param array $editor_settings The array of editor settings.
  3054  *
  3322  * @return array A filtered array of editor settings.
  3055  * @since 6.0.0
  3323  */
       
  3324 function wp_add_editor_classic_theme_styles( $editor_settings ) {
       
  3325 	if ( wp_theme_has_theme_json() ) {
       
  3326 		return $editor_settings;
       
  3327 	}
       
  3328 
       
  3329 	$suffix               = wp_scripts_get_suffix();
       
  3330 	$classic_theme_styles = ABSPATH . WPINC . "/css/classic-themes$suffix.css";
       
  3331 
       
  3332 	/*
       
  3333 	 * This follows the pattern of get_block_editor_theme_styles,
       
  3334 	 * but we can't use get_block_editor_theme_styles directly as it
       
  3335 	 * only handles external files or theme files.
       
  3336 	 */
       
  3337 	$classic_theme_styles_settings = array(
       
  3338 		'css'            => file_get_contents( $classic_theme_styles ),
       
  3339 		'__unstableType' => 'core',
       
  3340 		'isGlobalStyles' => false,
       
  3341 	);
       
  3342 
       
  3343 	// Add these settings to the start of the array so that themes can override them.
       
  3344 	array_unshift( $editor_settings['styles'], $classic_theme_styles_settings );
       
  3345 
       
  3346 	return $editor_settings;
       
  3347 }
       
  3348 
       
  3349 /**
       
  3350  * Removes leading and trailing _empty_ script tags.
       
  3351  *
       
  3352  * This is a helper meant to be used for literal script tag construction
       
  3353  * within `wp_get_inline_script_tag()` or `wp_print_inline_script_tag()`.
       
  3354  * It removes the literal values of "<script>" and "</script>" from
       
  3355  * around an inline script after trimming whitespace. Typically this
       
  3356  * is used in conjunction with output buffering, where `ob_get_clean()`
       
  3357  * is passed as the `$contents` argument.
       
  3358  *
       
  3359  * Example:
       
  3360  *
       
  3361  *     // Strips exact literal empty SCRIPT tags.
       
  3362  *     $js = '<script>sayHello();</script>;
       
  3363  *     'sayHello();' === wp_remove_surrounding_empty_script_tags( $js );
       
  3364  *
       
  3365  *     // Otherwise if anything is different it warns in the JS console.
       
  3366  *     $js = '<script type="text/javascript">console.log( "hi" );</script>';
       
  3367  *     'console.error( ... )' === wp_remove_surrounding_empty_script_tags( $js );
       
  3368  *
       
  3369  * @since 6.4.0
  3056  * @access private
  3370  * @access private
  3057  */
  3371  *
  3058 function _wp_theme_json_webfonts_handler() {
  3372  * @see wp_print_inline_script_tag()
  3059 	// Block themes are unavailable during installation.
  3373  * @see wp_get_inline_script_tag()
  3060 	if ( wp_installing() ) {
  3374  *
  3061 		return;
  3375  * @param string $contents Script body with manually created SCRIPT tag literals.
  3062 	}
  3376  * @return string Script body without surrounding script tag literals, or
  3063 
  3377  *                original contents if both exact literals aren't present.
  3064 	// Webfonts to be processed.
  3378  */
  3065 	$registered_webfonts = array();
  3379 function wp_remove_surrounding_empty_script_tags( $contents ) {
  3066 
  3380 	$contents = trim( $contents );
  3067 	/**
  3381 	$opener   = '<SCRIPT>';
  3068 	 * Gets the webfonts from theme.json.
  3382 	$closer   = '</SCRIPT>';
  3069 	 *
  3383 
  3070 	 * @since 6.0.0
  3384 	if (
  3071 	 *
  3385 		strlen( $contents ) > strlen( $opener ) + strlen( $closer ) &&
  3072 	 * @return array Array of defined webfonts.
  3386 		strtoupper( substr( $contents, 0, strlen( $opener ) ) ) === $opener &&
  3073 	 */
  3387 		strtoupper( substr( $contents, -strlen( $closer ) ) ) === $closer
  3074 	$fn_get_webfonts_from_theme_json = static function() {
  3388 	) {
  3075 		// Get settings from theme.json.
  3389 		return substr( $contents, strlen( $opener ), -strlen( $closer ) );
  3076 		$settings = WP_Theme_JSON_Resolver::get_merged_data()->get_settings();
  3390 	} else {
  3077 
  3391 		$error_message = __( 'Expected string to start with script tag (without attributes) and end with script tag, with optional whitespace.' );
  3078 		// If in the editor, add webfonts defined in variations.
  3392 		_doing_it_wrong( __FUNCTION__, $error_message, '6.4' );
  3079 		if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
  3393 		return sprintf(
  3080 			$variations = WP_Theme_JSON_Resolver::get_style_variations();
  3394 			'console.error(%s)',
  3081 			foreach ( $variations as $variation ) {
  3395 			wp_json_encode(
  3082 				// Skip if fontFamilies are not defined in the variation.
  3396 				sprintf(
  3083 				if ( empty( $variation['settings']['typography']['fontFamilies'] ) ) {
  3397 					/* translators: %s: wp_remove_surrounding_empty_script_tags() */
  3084 					continue;
  3398 					__( 'Function %s used incorrectly in PHP.' ),
  3085 				}
  3399 					'wp_remove_surrounding_empty_script_tags()'
  3086 
  3400 				) . ' ' . $error_message
  3087 				// Initialize the array structure.
       
  3088 				if ( empty( $settings['typography'] ) ) {
       
  3089 					$settings['typography'] = array();
       
  3090 				}
       
  3091 				if ( empty( $settings['typography']['fontFamilies'] ) ) {
       
  3092 					$settings['typography']['fontFamilies'] = array();
       
  3093 				}
       
  3094 				if ( empty( $settings['typography']['fontFamilies']['theme'] ) ) {
       
  3095 					$settings['typography']['fontFamilies']['theme'] = array();
       
  3096 				}
       
  3097 
       
  3098 				// Combine variations with settings. Remove duplicates.
       
  3099 				$settings['typography']['fontFamilies']['theme'] = array_merge( $settings['typography']['fontFamilies']['theme'], $variation['settings']['typography']['fontFamilies']['theme'] );
       
  3100 				$settings['typography']['fontFamilies']          = array_unique( $settings['typography']['fontFamilies'] );
       
  3101 			}
       
  3102 		}
       
  3103 
       
  3104 		// Bail out early if there are no settings for webfonts.
       
  3105 		if ( empty( $settings['typography']['fontFamilies'] ) ) {
       
  3106 			return array();
       
  3107 		}
       
  3108 
       
  3109 		$webfonts = array();
       
  3110 
       
  3111 		// Look for fontFamilies.
       
  3112 		foreach ( $settings['typography']['fontFamilies'] as $font_families ) {
       
  3113 			foreach ( $font_families as $font_family ) {
       
  3114 
       
  3115 				// Skip if fontFace is not defined.
       
  3116 				if ( empty( $font_family['fontFace'] ) ) {
       
  3117 					continue;
       
  3118 				}
       
  3119 
       
  3120 				// Skip if fontFace is not an array of webfonts.
       
  3121 				if ( ! is_array( $font_family['fontFace'] ) ) {
       
  3122 					continue;
       
  3123 				}
       
  3124 
       
  3125 				$webfonts = array_merge( $webfonts, $font_family['fontFace'] );
       
  3126 			}
       
  3127 		}
       
  3128 
       
  3129 		return $webfonts;
       
  3130 	};
       
  3131 
       
  3132 	/**
       
  3133 	 * Transforms each 'src' into an URI by replacing 'file:./'
       
  3134 	 * placeholder from theme.json.
       
  3135 	 *
       
  3136 	 * The absolute path to the webfont file(s) cannot be defined in
       
  3137 	 * theme.json. `file:./` is the placeholder which is replaced by
       
  3138 	 * the theme's URL path to the theme's root.
       
  3139 	 *
       
  3140 	 * @since 6.0.0
       
  3141 	 *
       
  3142 	 * @param array $src Webfont file(s) `src`.
       
  3143 	 * @return array Webfont's `src` in URI.
       
  3144 	 */
       
  3145 	$fn_transform_src_into_uri = static function( array $src ) {
       
  3146 		foreach ( $src as $key => $url ) {
       
  3147 			// Tweak the URL to be relative to the theme root.
       
  3148 			if ( ! str_starts_with( $url, 'file:./' ) ) {
       
  3149 				continue;
       
  3150 			}
       
  3151 
       
  3152 			$src[ $key ] = get_theme_file_uri( str_replace( 'file:./', '', $url ) );
       
  3153 		}
       
  3154 
       
  3155 		return $src;
       
  3156 	};
       
  3157 
       
  3158 	/**
       
  3159 	 * Converts the font-face properties (i.e. keys) into kebab-case.
       
  3160 	 *
       
  3161 	 * @since 6.0.0
       
  3162 	 *
       
  3163 	 * @param array $font_face Font face to convert.
       
  3164 	 * @return array Font faces with each property in kebab-case format.
       
  3165 	 */
       
  3166 	$fn_convert_keys_to_kebab_case = static function( array $font_face ) {
       
  3167 		foreach ( $font_face as $property => $value ) {
       
  3168 			$kebab_case               = _wp_to_kebab_case( $property );
       
  3169 			$font_face[ $kebab_case ] = $value;
       
  3170 			if ( $kebab_case !== $property ) {
       
  3171 				unset( $font_face[ $property ] );
       
  3172 			}
       
  3173 		}
       
  3174 
       
  3175 		return $font_face;
       
  3176 	};
       
  3177 
       
  3178 	/**
       
  3179 	 * Validates a webfont.
       
  3180 	 *
       
  3181 	 * @since 6.0.0
       
  3182 	 *
       
  3183 	 * @param array $webfont The webfont arguments.
       
  3184 	 * @return array|false The validated webfont arguments, or false if the webfont is invalid.
       
  3185 	 */
       
  3186 	$fn_validate_webfont = static function( $webfont ) {
       
  3187 		$webfont = wp_parse_args(
       
  3188 			$webfont,
       
  3189 			array(
       
  3190 				'font-family'  => '',
       
  3191 				'font-style'   => 'normal',
       
  3192 				'font-weight'  => '400',
       
  3193 				'font-display' => 'fallback',
       
  3194 				'src'          => array(),
       
  3195 			)
  3401 			)
  3196 		);
  3402 		);
  3197 
  3403 	}
  3198 		// Check the font-family.
  3404 }
  3199 		if ( empty( $webfont['font-family'] ) || ! is_string( $webfont['font-family'] ) ) {
       
  3200 			trigger_error( __( 'Webfont font family must be a non-empty string.' ) );
       
  3201 
       
  3202 			return false;
       
  3203 		}
       
  3204 
       
  3205 		// Check that the `src` property is defined and a valid type.
       
  3206 		if ( empty( $webfont['src'] ) || ( ! is_string( $webfont['src'] ) && ! is_array( $webfont['src'] ) ) ) {
       
  3207 			trigger_error( __( 'Webfont src must be a non-empty string or an array of strings.' ) );
       
  3208 
       
  3209 			return false;
       
  3210 		}
       
  3211 
       
  3212 		// Validate the `src` property.
       
  3213 		foreach ( (array) $webfont['src'] as $src ) {
       
  3214 			if ( ! is_string( $src ) || '' === trim( $src ) ) {
       
  3215 				trigger_error( __( 'Each webfont src must be a non-empty string.' ) );
       
  3216 
       
  3217 				return false;
       
  3218 			}
       
  3219 		}
       
  3220 
       
  3221 		// Check the font-weight.
       
  3222 		if ( ! is_string( $webfont['font-weight'] ) && ! is_int( $webfont['font-weight'] ) ) {
       
  3223 			trigger_error( __( 'Webfont font weight must be a properly formatted string or integer.' ) );
       
  3224 
       
  3225 			return false;
       
  3226 		}
       
  3227 
       
  3228 		// Check the font-display.
       
  3229 		if ( ! in_array( $webfont['font-display'], array( 'auto', 'block', 'fallback', 'swap' ), true ) ) {
       
  3230 			$webfont['font-display'] = 'fallback';
       
  3231 		}
       
  3232 
       
  3233 		$valid_props = array(
       
  3234 			'ascend-override',
       
  3235 			'descend-override',
       
  3236 			'font-display',
       
  3237 			'font-family',
       
  3238 			'font-stretch',
       
  3239 			'font-style',
       
  3240 			'font-weight',
       
  3241 			'font-variant',
       
  3242 			'font-feature-settings',
       
  3243 			'font-variation-settings',
       
  3244 			'line-gap-override',
       
  3245 			'size-adjust',
       
  3246 			'src',
       
  3247 			'unicode-range',
       
  3248 		);
       
  3249 
       
  3250 		foreach ( $webfont as $prop => $value ) {
       
  3251 			if ( ! in_array( $prop, $valid_props, true ) ) {
       
  3252 				unset( $webfont[ $prop ] );
       
  3253 			}
       
  3254 		}
       
  3255 
       
  3256 		return $webfont;
       
  3257 	};
       
  3258 
       
  3259 	/**
       
  3260 	 * Registers webfonts declared in theme.json.
       
  3261 	 *
       
  3262 	 * @since 6.0.0
       
  3263 	 *
       
  3264 	 * @uses $registered_webfonts To access and update the registered webfonts registry (passed by reference).
       
  3265 	 * @uses $fn_get_webfonts_from_theme_json To run the function that gets the webfonts from theme.json.
       
  3266 	 * @uses $fn_convert_keys_to_kebab_case To run the function that converts keys into kebab-case.
       
  3267 	 * @uses $fn_validate_webfont To run the function that validates each font-face (webfont) from theme.json.
       
  3268 	 */
       
  3269 	$fn_register_webfonts = static function() use ( &$registered_webfonts, $fn_get_webfonts_from_theme_json, $fn_convert_keys_to_kebab_case, $fn_validate_webfont, $fn_transform_src_into_uri ) {
       
  3270 		$registered_webfonts = array();
       
  3271 
       
  3272 		foreach ( $fn_get_webfonts_from_theme_json() as $webfont ) {
       
  3273 			if ( ! is_array( $webfont ) ) {
       
  3274 				continue;
       
  3275 			}
       
  3276 
       
  3277 			$webfont = $fn_convert_keys_to_kebab_case( $webfont );
       
  3278 
       
  3279 			$webfont = $fn_validate_webfont( $webfont );
       
  3280 
       
  3281 			$webfont['src'] = $fn_transform_src_into_uri( (array) $webfont['src'] );
       
  3282 
       
  3283 			// Skip if not valid.
       
  3284 			if ( empty( $webfont ) ) {
       
  3285 				continue;
       
  3286 			}
       
  3287 
       
  3288 			$registered_webfonts[] = $webfont;
       
  3289 		}
       
  3290 	};
       
  3291 
       
  3292 	/**
       
  3293 	 * Orders 'src' items to optimize for browser support.
       
  3294 	 *
       
  3295 	 * @since 6.0.0
       
  3296 	 *
       
  3297 	 * @param array $webfont Webfont to process.
       
  3298 	 * @return array Ordered `src` items.
       
  3299 	 */
       
  3300 	$fn_order_src = static function( array $webfont ) {
       
  3301 		$src         = array();
       
  3302 		$src_ordered = array();
       
  3303 
       
  3304 		foreach ( $webfont['src'] as $url ) {
       
  3305 			// Add data URIs first.
       
  3306 			if ( str_starts_with( trim( $url ), 'data:' ) ) {
       
  3307 				$src_ordered[] = array(
       
  3308 					'url'    => $url,
       
  3309 					'format' => 'data',
       
  3310 				);
       
  3311 				continue;
       
  3312 			}
       
  3313 			$format         = pathinfo( $url, PATHINFO_EXTENSION );
       
  3314 			$src[ $format ] = $url;
       
  3315 		}
       
  3316 
       
  3317 		// Add woff2.
       
  3318 		if ( ! empty( $src['woff2'] ) ) {
       
  3319 			$src_ordered[] = array(
       
  3320 				'url'    => sanitize_url( $src['woff2'] ),
       
  3321 				'format' => 'woff2',
       
  3322 			);
       
  3323 		}
       
  3324 
       
  3325 		// Add woff.
       
  3326 		if ( ! empty( $src['woff'] ) ) {
       
  3327 			$src_ordered[] = array(
       
  3328 				'url'    => sanitize_url( $src['woff'] ),
       
  3329 				'format' => 'woff',
       
  3330 			);
       
  3331 		}
       
  3332 
       
  3333 		// Add ttf.
       
  3334 		if ( ! empty( $src['ttf'] ) ) {
       
  3335 			$src_ordered[] = array(
       
  3336 				'url'    => sanitize_url( $src['ttf'] ),
       
  3337 				'format' => 'truetype',
       
  3338 			);
       
  3339 		}
       
  3340 
       
  3341 		// Add eot.
       
  3342 		if ( ! empty( $src['eot'] ) ) {
       
  3343 			$src_ordered[] = array(
       
  3344 				'url'    => sanitize_url( $src['eot'] ),
       
  3345 				'format' => 'embedded-opentype',
       
  3346 			);
       
  3347 		}
       
  3348 
       
  3349 		// Add otf.
       
  3350 		if ( ! empty( $src['otf'] ) ) {
       
  3351 			$src_ordered[] = array(
       
  3352 				'url'    => sanitize_url( $src['otf'] ),
       
  3353 				'format' => 'opentype',
       
  3354 			);
       
  3355 		}
       
  3356 		$webfont['src'] = $src_ordered;
       
  3357 
       
  3358 		return $webfont;
       
  3359 	};
       
  3360 
       
  3361 	/**
       
  3362 	 * Compiles the 'src' into valid CSS.
       
  3363 	 *
       
  3364 	 * @since 6.0.0
       
  3365 	 *
       
  3366 	 * @param string $font_family Font family.
       
  3367 	 * @param array  $value       Value to process.
       
  3368 	 * @return string The CSS.
       
  3369 	 */
       
  3370 	$fn_compile_src = static function( $font_family, array $value ) {
       
  3371 		$src = "local($font_family)";
       
  3372 
       
  3373 		foreach ( $value as $item ) {
       
  3374 
       
  3375 			if (
       
  3376 				str_starts_with( $item['url'], site_url() ) ||
       
  3377 				str_starts_with( $item['url'], home_url() )
       
  3378 			) {
       
  3379 				$item['url'] = wp_make_link_relative( $item['url'] );
       
  3380 			}
       
  3381 
       
  3382 			$src .= ( 'data' === $item['format'] )
       
  3383 				? ", url({$item['url']})"
       
  3384 				: ", url('{$item['url']}') format('{$item['format']}')";
       
  3385 		}
       
  3386 
       
  3387 		return $src;
       
  3388 	};
       
  3389 
       
  3390 	/**
       
  3391 	 * Compiles the font variation settings.
       
  3392 	 *
       
  3393 	 * @since 6.0.0
       
  3394 	 *
       
  3395 	 * @param array $font_variation_settings Array of font variation settings.
       
  3396 	 * @return string The CSS.
       
  3397 	 */
       
  3398 	$fn_compile_variations = static function( array $font_variation_settings ) {
       
  3399 		$variations = '';
       
  3400 
       
  3401 		foreach ( $font_variation_settings as $key => $value ) {
       
  3402 			$variations .= "$key $value";
       
  3403 		}
       
  3404 
       
  3405 		return $variations;
       
  3406 	};
       
  3407 
       
  3408 	/**
       
  3409 	 * Builds the font-family's CSS.
       
  3410 	 *
       
  3411 	 * @since 6.0.0
       
  3412 	 *
       
  3413 	 * @uses $fn_compile_src To run the function that compiles the src.
       
  3414 	 * @uses $fn_compile_variations To run the function that compiles the variations.
       
  3415 	 *
       
  3416 	 * @param array $webfont Webfont to process.
       
  3417 	 * @return string This font-family's CSS.
       
  3418 	 */
       
  3419 	$fn_build_font_face_css = static function( array $webfont ) use ( $fn_compile_src, $fn_compile_variations ) {
       
  3420 		$css = '';
       
  3421 
       
  3422 		// Wrap font-family in quotes if it contains spaces.
       
  3423 		if (
       
  3424 			str_contains( $webfont['font-family'], ' ' ) &&
       
  3425 			! str_contains( $webfont['font-family'], '"' ) &&
       
  3426 			! str_contains( $webfont['font-family'], "'" )
       
  3427 		) {
       
  3428 			$webfont['font-family'] = '"' . $webfont['font-family'] . '"';
       
  3429 		}
       
  3430 
       
  3431 		foreach ( $webfont as $key => $value ) {
       
  3432 			/*
       
  3433 			 * Skip "provider", since it's for internal API use,
       
  3434 			 * and not a valid CSS property.
       
  3435 			 */
       
  3436 			if ( 'provider' === $key ) {
       
  3437 				continue;
       
  3438 			}
       
  3439 
       
  3440 			// Compile the "src" parameter.
       
  3441 			if ( 'src' === $key ) {
       
  3442 				$value = $fn_compile_src( $webfont['font-family'], $value );
       
  3443 			}
       
  3444 
       
  3445 			// If font-variation-settings is an array, convert it to a string.
       
  3446 			if ( 'font-variation-settings' === $key && is_array( $value ) ) {
       
  3447 				$value = $fn_compile_variations( $value );
       
  3448 			}
       
  3449 
       
  3450 			if ( ! empty( $value ) ) {
       
  3451 				$css .= "$key:$value;";
       
  3452 			}
       
  3453 		}
       
  3454 
       
  3455 		return $css;
       
  3456 	};
       
  3457 
       
  3458 	/**
       
  3459 	 * Gets the '@font-face' CSS styles for locally-hosted font files.
       
  3460 	 *
       
  3461 	 * @since 6.0.0
       
  3462 	 *
       
  3463 	 * @uses $registered_webfonts To access and update the registered webfonts registry (passed by reference).
       
  3464 	 * @uses $fn_order_src To run the function that orders the src.
       
  3465 	 * @uses $fn_build_font_face_css To run the function that builds the font-face CSS.
       
  3466 	 *
       
  3467 	 * @return string The `@font-face` CSS.
       
  3468 	 */
       
  3469 	$fn_get_css = static function() use ( &$registered_webfonts, $fn_order_src, $fn_build_font_face_css ) {
       
  3470 		$css = '';
       
  3471 
       
  3472 		foreach ( $registered_webfonts as $webfont ) {
       
  3473 			// Order the webfont's `src` items to optimize for browser support.
       
  3474 			$webfont = $fn_order_src( $webfont );
       
  3475 
       
  3476 			// Build the @font-face CSS for this webfont.
       
  3477 			$css .= '@font-face{' . $fn_build_font_face_css( $webfont ) . '}';
       
  3478 		}
       
  3479 
       
  3480 		return $css;
       
  3481 	};
       
  3482 
       
  3483 	/**
       
  3484 	 * Generates and enqueues webfonts styles.
       
  3485 	 *
       
  3486 	 * @since 6.0.0
       
  3487 	 *
       
  3488 	 * @uses $fn_get_css To run the function that gets the CSS.
       
  3489 	 */
       
  3490 	$fn_generate_and_enqueue_styles = static function() use ( $fn_get_css ) {
       
  3491 		// Generate the styles.
       
  3492 		$styles = $fn_get_css();
       
  3493 
       
  3494 		// Bail out if there are no styles to enqueue.
       
  3495 		if ( '' === $styles ) {
       
  3496 			return;
       
  3497 		}
       
  3498 
       
  3499 		// Enqueue the stylesheet.
       
  3500 		wp_register_style( 'wp-webfonts', '' );
       
  3501 		wp_enqueue_style( 'wp-webfonts' );
       
  3502 
       
  3503 		// Add the styles to the stylesheet.
       
  3504 		wp_add_inline_style( 'wp-webfonts', $styles );
       
  3505 	};
       
  3506 
       
  3507 	/**
       
  3508 	 * Generates and enqueues editor styles.
       
  3509 	 *
       
  3510 	 * @since 6.0.0
       
  3511 	 *
       
  3512 	 * @uses $fn_get_css To run the function that gets the CSS.
       
  3513 	 */
       
  3514 	$fn_generate_and_enqueue_editor_styles = static function() use ( $fn_get_css ) {
       
  3515 		// Generate the styles.
       
  3516 		$styles = $fn_get_css();
       
  3517 
       
  3518 		// Bail out if there are no styles to enqueue.
       
  3519 		if ( '' === $styles ) {
       
  3520 			return;
       
  3521 		}
       
  3522 
       
  3523 		wp_add_inline_style( 'wp-block-library', $styles );
       
  3524 	};
       
  3525 
       
  3526 	add_action( 'wp_loaded', $fn_register_webfonts );
       
  3527 	add_action( 'wp_enqueue_scripts', $fn_generate_and_enqueue_styles );
       
  3528 	add_action( 'admin_init', $fn_generate_and_enqueue_editor_styles );
       
  3529 }