diff --git a/src/wp-includes/plugin.php b/src/wp-includes/plugin.php
index 0ca495b6f76d4..c1d68a81d713d 100644
--- a/src/wp-includes/plugin.php
+++ b/src/wp-includes/plugin.php
@@ -271,17 +271,23 @@ function apply_filters_ref_array( $hook_name, $args ) {
*
* @global WP_Hook[] $wp_filter Stores all of the filters and actions.
*
- * @param string $hook_name The name of the filter hook.
- * @param callable|string|array|false $callback Optional. The callback to check for.
- * This function can be called unconditionally to speculatively check
- * a callback that may or may not exist. Default false.
- * @param int|false $priority Optional. The specific priority at which to check for the callback.
- * Default false.
+ * @param string $hook_name The name of the filter hook.
+ * @param callable|false $callback Optional. The callback to check for.
+ * This function can be called unconditionally to speculatively check
+ * a callback that may or may not exist. Default false.
+ * @param int|false $priority Optional. The specific priority at which to check for the callback.
+ * Default false.
* @return bool|int If `$callback` is omitted, returns boolean for whether the hook has
* anything registered. When checking a specific function, the priority
* of that hook is returned, or false if the function is not attached.
* If `$callback` and `$priority` are both provided, a boolean is returned
* for whether the specific function is registered at that priority.
+ *
+ * @phpstan-return (
+ * $callback is false ? bool : (
+ * $priority is false ? int|false : bool
+ * )
+ * )
*/
function has_filter( $hook_name, $callback = false, $priority = false ) {
global $wp_filter;
@@ -583,17 +589,23 @@ function do_action_ref_array( $hook_name, $args ) {
*
* @see has_filter() This function is an alias of has_filter().
*
- * @param string $hook_name The name of the action hook.
- * @param callable|string|array|false $callback Optional. The callback to check for.
- * This function can be called unconditionally to speculatively check
- * a callback that may or may not exist. Default false.
- * @param int|false $priority Optional. The specific priority at which to check for the callback.
- * Default false.
+ * @param string $hook_name The name of the action hook.
+ * @param callable|false $callback Optional. The callback to check for.
+ * This function can be called unconditionally to speculatively check
+ * a callback that may or may not exist. Default false.
+ * @param int|false $priority Optional. The specific priority at which to check for the callback.
+ * Default false.
* @return bool|int If `$callback` is omitted, returns boolean for whether the hook has
* anything registered. When checking a specific function, the priority
* of that hook is returned, or false if the function is not attached.
* If `$callback` and `$priority` are both provided, a boolean is returned
* for whether the specific function is registered at that priority.
+ *
+ * @phpstan-return (
+ * $callback is false ? bool : (
+ * $priority is false ? int|false : bool
+ * )
+ * )
*/
function has_action( $hook_name, $callback = false, $priority = false ) {
return has_filter( $hook_name, $callback, $priority );
diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php
index f9ea36720baea..9ed8cde7e7321 100644
--- a/src/wp-includes/script-loader.php
+++ b/src/wp-includes/script-loader.php
@@ -2551,21 +2551,42 @@ function wp_enqueue_global_styles() {
$is_block_theme = wp_is_block_theme();
$is_classic_theme = ! $is_block_theme;
- /*
- * Global styles should be printed in the head for block themes, or for classic themes when loading assets on
- * demand is disabled, which is the default.
- * The footer should only be used for classic themes when loading assets on demand is enabled.
+ /**
+ * Global styles should be printed in the HEAD for block themes, or for classic themes when loading assets on
+ * demand is disabled (which is no longer the default).
*
- * See https://core.trac.wordpress.org/ticket/53494 and https://core.trac.wordpress.org/ticket/61965.
+ * @link https://core.trac.wordpress.org/ticket/53494
+ * @link https://core.trac.wordpress.org/ticket/61965
*/
if (
- ( $is_block_theme && doing_action( 'wp_footer' ) ) ||
- ( $is_classic_theme && doing_action( 'wp_footer' ) && ! $assets_on_demand ) ||
- ( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) && $assets_on_demand )
+ doing_action( 'wp_footer' ) &&
+ (
+ $is_block_theme ||
+ ( $is_classic_theme && ! $assets_on_demand )
+ )
) {
return;
}
+ /**
+ * The footer should only be used for classic themes when loading assets on demand is enabled. This is now the
+ * default with the introduction of hoisting late-printed styles (via {@see wp_load_classic_theme_block_styles_on_demand()}).
+ * So even though the main global styles are not printed here in the HEAD for classic themes with on-demand asset
+ * loading, a placeholder for the global styles is still enqueued. Then when {@see wp_hoist_late_printed_styles()}
+ * processes the output buffer, it can locate the placeholder and inject the global styles from the footer into the
+ * HEAD.
+ *
+ * @link https://core.trac.wordpress.org/ticket/64099
+ */
+ if ( $is_classic_theme && doing_action( 'wp_enqueue_scripts' ) && $assets_on_demand ) {
+ if ( has_action( 'wp_template_enhancement_output_buffer_started', 'wp_hoist_late_printed_styles' ) ) {
+ wp_register_style( 'wp-global-styles-placeholder', false );
+ wp_add_inline_style( 'wp-global-styles-placeholder', ':root { --wp-internal-comment: "Placeholder for wp_hoist_late_printed_styles() to replace with the global-styles printed at wp_footer." }' );
+ wp_enqueue_style( 'wp-global-styles-placeholder' );
+ }
+ return;
+ }
+
/*
* If loading the CSS for each block separately, then load the theme.json CSS conditionally.
* This removes the CSS from the global-styles stylesheet and adds it to the inline CSS for each block.
@@ -2741,6 +2762,16 @@ function wp_should_load_block_assets_on_demand() {
*/
function wp_enqueue_registered_block_scripts_and_styles() {
if ( wp_should_load_block_assets_on_demand() ) {
+ /**
+ * Add placeholder for where block styles would historically get enqueued in a classic theme when block assets
+ * are not loaded on demand. This happens right after {@see wp_common_block_scripts_and_styles()} is called
+ * at which time wp-block-library is enqueued.
+ */
+ if ( ! wp_is_block_theme() && has_action( 'wp_template_enhancement_output_buffer_started', 'wp_hoist_late_printed_styles' ) ) {
+ wp_register_style( 'wp-block-styles-placeholder', false );
+ wp_add_inline_style( 'wp-block-styles-placeholder', ':root { --wp-internal-comment: "Placeholder for wp_hoist_late_printed_styles() to replace with the block styles printed at wp_footer." }' );
+ wp_enqueue_style( 'wp-block-styles-placeholder' );
+ }
return;
}
@@ -3700,7 +3731,7 @@ function wp_load_classic_theme_block_styles_on_demand() {
* @see wp_load_classic_theme_block_styles_on_demand()
* @see _wp_footer_scripts()
*/
-function wp_hoist_late_printed_styles() {
+function wp_hoist_late_printed_styles(): void {
// Skip the embed template on-demand styles aren't relevant, and there is no wp_head action.
if ( is_embed() ) {
return;
@@ -3726,16 +3757,21 @@ static function () use ( &$style_handles_at_enqueue_block_assets ) {
/*
* Add a placeholder comment into the inline styles for wp-block-library, after which the late block styles
* can be hoisted from the footer to be printed in the header by means of a filter below on the template enhancement
- * output buffer. The `wp_print_styles` action is used to ensure that if the inline style gets replaced at
- * `enqueue_block_assets` or `wp_enqueue_scripts` that the placeholder will be sure to be present.
+ * output buffer.
+ *
+ * Note that wp_maybe_inline_styles() prepends the inlined style to the extra 'after' array, which happens after
+ * this code runs. This ensures that the placeholder appears right after any inlined wp-block-library styles,
+ * which would be common.css.
*/
$placeholder = sprintf( '/*%s*/', uniqid( 'wp_block_styles_on_demand_placeholder:' ) );
- add_action(
- 'wp_print_styles',
- static function () use ( $placeholder ) {
+ $dependency = wp_styles()->query( 'wp-block-library', 'registered' );
+ if ( $dependency ) {
+ if ( ! isset( $dependency->extra['after'] ) ) {
wp_add_inline_style( 'wp-block-library', $placeholder );
+ } else {
+ array_unshift( $dependency->extra['after'], $placeholder );
}
- );
+ }
/*
* Create a substitute for `print_late_styles()` which is aware of block styles. This substitute does not print
@@ -3765,29 +3801,29 @@ static function () use ( $placeholder ) {
}
/*
- * First print all styles related to blocks which should be inserted right after the wp-block-library stylesheet
+ * First print all styles related to core blocks which should be inserted right after the wp-block-library stylesheet
* to preserve the CSS cascade. The logic in this `if` statement is derived from `wp_print_styles()`.
*/
$enqueued_core_block_styles = array_values( array_intersect( $all_core_block_style_handles, wp_styles()->queue ) );
if ( count( $enqueued_core_block_styles ) > 0 ) {
ob_start();
wp_styles()->do_items( $enqueued_core_block_styles );
- $printed_core_block_styles = ob_get_clean();
+ $printed_core_block_styles = (string) ob_get_clean();
}
- // Non-core block styles get printed after the classic-theme-styles stylesheet.
+ // Capture non-core block styles so they can get printed at the point where wp_enqueue_registered_block_scripts_and_styles() runs.
$enqueued_other_block_styles = array_values( array_intersect( $all_other_block_style_handles, wp_styles()->queue ) );
if ( count( $enqueued_other_block_styles ) > 0 ) {
ob_start();
wp_styles()->do_items( $enqueued_other_block_styles );
- $printed_other_block_styles = ob_get_clean();
+ $printed_other_block_styles = (string) ob_get_clean();
}
- // Capture the global-styles so that it can be printed separately after classic-theme-styles and other styles enqueued at enqueue_block_assets.
+ // Capture the global-styles so that it can be printed at the point where wp_enqueue_global_styles() runs.
if ( wp_style_is( 'global-styles' ) ) {
ob_start();
wp_styles()->do_items( array( 'global-styles' ) );
- $printed_global_styles = ob_get_clean();
+ $printed_global_styles = (string) ob_get_clean();
}
/*
@@ -3797,7 +3833,7 @@ static function () use ( $placeholder ) {
*/
ob_start();
wp_styles()->do_footer_items();
- $printed_late_styles = ob_get_clean();
+ $printed_late_styles = (string) ob_get_clean();
};
/*
@@ -3848,7 +3884,7 @@ private function get_span(): WP_HTML_Span {
*
* @param string $text Text to insert.
*/
- public function insert_before( string $text ) {
+ public function insert_before( string $text ): void {
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $this->get_span()->start, 0, $text );
}
@@ -3857,7 +3893,7 @@ public function insert_before( string $text ) {
*
* @param string $text Text to insert.
*/
- public function insert_after( string $text ) {
+ public function insert_after( string $text ): void {
$span = $this->get_span();
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $span->start + $span->length, 0, $text );
@@ -3866,25 +3902,49 @@ public function insert_after( string $text ) {
/**
* Removes the current token.
*/
- public function remove() {
+ public function remove(): void {
$span = $this->get_span();
$this->lexical_updates[] = new WP_HTML_Text_Replacement( $span->start, $span->length, '' );
}
+
+ /**
+ * Replaces the current token.
+ *
+ * @param string $text Text to replace with.
+ */
+ public function replace( string $text ): void {
+ $span = $this->get_span();
+
+ $this->lexical_updates[] = new WP_HTML_Text_Replacement( $span->start, $span->length, $text );
+ }
};
// Locate the insertion points in the HEAD.
while ( $processor->next_tag( array( 'tag_closers' => 'visit' ) ) ) {
if (
+ 'STYLE' === $processor->get_tag() &&
+ 'wp-global-styles-placeholder-inline-css' === $processor->get_attribute( 'id' )
+ ) {
+ /** This is added in {@see wp_enqueue_global_styles()} */
+ $processor->set_bookmark( 'wp_global_styles_placeholder' );
+ } elseif (
+ 'STYLE' === $processor->get_tag() &&
+ 'wp-block-styles-placeholder-inline-css' === $processor->get_attribute( 'id' )
+ ) {
+ /** This is added in {@see wp_enqueue_registered_block_scripts_and_styles()} */
+ $processor->set_bookmark( 'wp_block_styles_placeholder' );
+ } elseif (
'STYLE' === $processor->get_tag() &&
'wp-block-library-inline-css' === $processor->get_attribute( 'id' )
) {
+ /** This is added here in {@see wp_hoist_late_printed_styles()} */
$processor->set_bookmark( 'wp_block_library' );
} elseif ( 'HEAD' === $processor->get_tag() && $processor->is_tag_closer() ) {
$processor->set_bookmark( 'head_end' );
break;
} elseif ( ( 'STYLE' === $processor->get_tag() || 'LINK' === $processor->get_tag() ) && $processor->get_attribute( 'id' ) ) {
- $id = $processor->get_attribute( 'id' );
+ $id = (string) $processor->get_attribute( 'id' );
$handle = null;
if ( 'STYLE' === $processor->get_tag() ) {
if ( preg_match( '/^(.+)-inline-css$/', $id, $matches ) ) {
@@ -3894,10 +3954,6 @@ public function remove() {
$handle = $matches[1];
}
- if ( 'classic-theme-styles' === $handle ) {
- $processor->set_bookmark( 'classic_theme_styles' );
- }
-
if ( $handle && in_array( $handle, $style_handles_at_enqueue_block_assets, true ) ) {
if ( ! $processor->has_bookmark( 'first_style_at_enqueue_block_assets' ) ) {
$processor->set_bookmark( 'first_style_at_enqueue_block_assets' );
@@ -3907,6 +3963,16 @@ public function remove() {
}
}
+ /**
+ * Replace the placeholder for global styles enqueued during {@see wp_enqueue_global_styles()}. This is done
+ * even if $printed_global_styles is empty.
+ */
+ if ( $processor->has_bookmark( 'wp_global_styles_placeholder' ) ) {
+ $processor->seek( 'wp_global_styles_placeholder' );
+ $processor->replace( $printed_global_styles );
+ $printed_global_styles = '';
+ }
+
/*
* Insert block styles right after wp-block-library (if it is present). The placeholder CSS comment will
* always be added to the wp-block-library inline style since it gets printed at `wp_head` before the blocks
@@ -3921,13 +3987,34 @@ public function remove() {
$css_text = $processor->get_modifiable_text();
/*
- * A placeholder CSS comment is added to the inline style in order to force an inline STYLE tag to
- * be printed. Now that we've located the inline style, the placeholder comment can be removed. If
- * there is no CSS left in the STYLE tag after removing the placeholder (aside from the sourceURL
- * comment), then remove the STYLE entirely.
+ * Split the block library inline style by the placeholder to identify the original inlined CSS, which
+ * likely would be common.css, followed by any inline styles which had been added by the theme or
+ * plugins via `wp_add_inline_style( 'wp-block-library', '...' )`. The separate block styles loaded on
+ * demand will get inserted after the inlined common.css and before the extra inline styles added by the
+ * user.
+ */
+ $css_text_around_placeholder = explode( $placeholder, $css_text, 2 );
+ $extra_inline_styles = '';
+ if ( count( $css_text_around_placeholder ) === 2 ) {
+ $css_text = $css_text_around_placeholder[0];
+ if ( '' !== trim( $css_text ) ) {
+ $inlined_src = wp_styles()->get_data( 'wp-block-library', 'inlined_src' );
+ if ( $inlined_src ) {
+ $css_text .= sprintf(
+ "\n/*# sourceURL=%s */\n",
+ esc_url_raw( $inlined_src )
+ );
+ }
+ }
+ $extra_inline_styles = $css_text_around_placeholder[1];
+ }
+
+ /*
+ * The placeholder CSS comment was added to the inline style in order to force an inline STYLE tag to
+ * be printed. Now that the inline style has been located and the placeholder comment has been removed, if
+ * there is no CSS left in the STYLE tag after removal, then remove the STYLE tag entirely.
*/
- $css_text = str_replace( $placeholder, '', $css_text );
- if ( preg_match( ':^/\*# sourceURL=\S+? \*/$:', trim( $css_text ) ) ) {
+ if ( '' === trim( $css_text ) ) {
$processor->remove();
} else {
$processor->set_modifiable_text( $css_text );
@@ -3936,20 +4023,18 @@ public function remove() {
$inserted_after = $printed_core_block_styles;
$printed_core_block_styles = '';
- // If the classic-theme-styles is absent, then the third-party block styles cannot be inserted after it, so they get inserted here.
- if ( ! $processor->has_bookmark( 'classic_theme_styles' ) ) {
- if ( '' !== $printed_other_block_styles ) {
- $inserted_after .= $printed_other_block_styles;
- }
- $printed_other_block_styles = '';
-
- // If there aren't any other styles printed at enqueue_block_assets either, then the global styles need to also be printed here.
- if ( ! $processor->has_bookmark( 'last_style_at_enqueue_block_assets' ) ) {
- if ( '' !== $printed_global_styles ) {
- $inserted_after .= $printed_global_styles;
- }
- $printed_global_styles = '';
- }
+ /*
+ * Add a new inline style for any user styles added via wp_add_inline_style( 'wp-block-library', '...' ).
+ * This must be added here after $printed_core_block_styles to preserve the original CSS cascade when
+ * the combined block library stylesheet was used. The pattern here is checking to see if it is not just
+ * a sourceURL comment after the placeholder above is removed.
+ */
+ if ( ! preg_match( ':^\s*(/\*# sourceURL=\S+? \*/\s*)?$:s', $extra_inline_styles ) ) {
+ $style_processor = new WP_HTML_Tag_Processor( '' );
+ $style_processor->next_tag();
+ $style_processor->set_attribute( 'id', 'wp-block-library-inline-css-extra' );
+ $style_processor->set_modifiable_text( $extra_inline_styles );
+ $inserted_after .= "{$style_processor->get_updated_html()}\n";
}
if ( '' !== $inserted_after ) {
@@ -3957,23 +4042,14 @@ public function remove() {
}
}
- // Insert global-styles after the styles enqueued at enqueue_block_assets.
- if ( '' !== $printed_global_styles && $processor->has_bookmark( 'last_style_at_enqueue_block_assets' ) ) {
- $processor->seek( 'last_style_at_enqueue_block_assets' );
-
- $processor->insert_after( "\n" . $printed_global_styles );
- $printed_global_styles = '';
-
- if ( ! $processor->has_bookmark( 'classic_theme_styles' ) && '' !== $printed_other_block_styles ) {
- $processor->insert_after( "\n" . $printed_other_block_styles );
- $printed_other_block_styles = '';
+ // Insert block styles at the point where wp_enqueue_registered_block_scripts_and_styles() normally enqueues styles.
+ if ( $processor->has_bookmark( 'wp_block_styles_placeholder' ) ) {
+ $processor->seek( 'wp_block_styles_placeholder' );
+ if ( '' !== $printed_other_block_styles ) {
+ $processor->replace( "\n" . $printed_other_block_styles );
+ } else {
+ $processor->remove();
}
- }
-
- // Insert third-party block styles right after the classic-theme-styles.
- if ( '' !== $printed_other_block_styles && $processor->has_bookmark( 'classic_theme_styles' ) ) {
- $processor->seek( 'classic_theme_styles' );
- $processor->insert_after( "\n" . $printed_other_block_styles );
$printed_other_block_styles = '';
}
diff --git a/tests/phpunit/tests/template.php b/tests/phpunit/tests/template.php
index e899ea2f06908..8ab3f0547e301 100644
--- a/tests/phpunit/tests/template.php
+++ b/tests/phpunit/tests/template.php
@@ -151,6 +151,7 @@ public function tear_down() {
$registry->unregister( 'third-party/test' );
}
+ unset( $GLOBALS['_wp_tests_development_mode'] );
parent::tear_down();
}
@@ -1477,9 +1478,17 @@ public function test_wp_load_classic_theme_block_styles_on_demand( string $theme
/**
* Data provider.
*
- * @return array
+ * @return array
*/
public function data_wp_hoist_late_printed_styles(): array {
+ $blocks_content = '
This is only a test!
';
+
$early_common_styles = array(
'wp-img-auto-sizes-contain-inline-css',
'early-css',
@@ -1487,12 +1496,14 @@ public function data_wp_hoist_late_printed_styles(): array {
'wp-emoji-styles-inline-css',
);
- $common_late_in_head = array(
- // Styles enqueued at wp_enqueue_scripts (priority 10).
+ // Styles enqueued at wp_enqueue_scripts (priority 10).
+ $common_at_wp_enqueue_scripts = array(
'normal-css',
'normal-inline-css',
+ );
- // Styles printed at wp_head priority 10.
+ $common_late_in_head = array(
+ // Styles printed at wp_head priority 101.
'wp-custom-css',
);
@@ -1521,6 +1532,7 @@ public function data_wp_hoist_late_printed_styles(): array {
// Hoisted. Enqueued by wp_enqueue_global_styles() which runs at wp_enqueue_scripts priority 10 and wp_footer priority 1.
'global-styles-inline-css',
),
+ $common_at_wp_enqueue_scripts,
$common_late_in_head,
$common_late_in_body
);
@@ -1528,14 +1540,17 @@ public function data_wp_hoist_late_printed_styles(): array {
return array(
'standard_classic_theme_config_with_min_styles_inlined' => array(
'set_up' => null,
+ 'content' => $blocks_content,
'inline_size_limit' => 0,
'expected_styles' => array(
'HEAD' => $common_expected_head_styles,
'BODY' => array(),
),
),
+
'standard_classic_theme_config_with_max_styles_inlined' => array(
'set_up' => null,
+ 'content' => $blocks_content,
'inline_size_limit' => PHP_INT_MAX,
'expected_styles' => array(
'HEAD' => array_merge(
@@ -1548,12 +1563,14 @@ public function data_wp_hoist_late_printed_styles(): array {
'custom-block-styles-css',
'global-styles-inline-css',
),
+ $common_at_wp_enqueue_scripts,
$common_late_in_head,
$common_late_in_body
),
'BODY' => array(),
),
),
+
'classic_theme_styles_omitted' => array(
'set_up' => static function () {
// Note that wp_enqueue_scripts is used instead of enqueue_block_assets because it runs again at the former action.
@@ -1565,6 +1582,7 @@ static function () {
100
);
},
+ 'content' => $blocks_content,
'inline_size_limit' => PHP_INT_MAX,
'expected_styles' => array(
'HEAD' => array_merge(
@@ -1576,12 +1594,14 @@ static function () {
'custom-block-styles-css',
'global-styles-inline-css',
),
+ $common_at_wp_enqueue_scripts,
$common_late_in_head,
$common_late_in_body
),
'BODY' => array(),
),
),
+
'no_styles_at_enqueued_block_assets' => array(
'set_up' => static function () {
add_action(
@@ -1593,6 +1613,7 @@ static function () {
100
);
},
+ 'content' => $blocks_content,
'inline_size_limit' => PHP_INT_MAX,
'expected_styles' => array(
'HEAD' => array_merge(
@@ -1603,21 +1624,23 @@ static function () {
'third-party-test-block-css',
'global-styles-inline-css',
),
+ $common_at_wp_enqueue_scripts,
$common_late_in_head,
$common_late_in_body
),
'BODY' => array(),
),
),
+
'no_global_styles' => array(
'set_up' => static function () {
- add_filter(
- 'print_styles_array',
- static function ( $handles ) {
- return array_values( array_diff( $handles, array( 'global-styles' ) ) );
- }
- );
+ $dequeue = static function () {
+ wp_dequeue_style( 'global-styles' );
+ };
+ add_action( 'wp_enqueue_scripts', $dequeue, 1000 );
+ add_action( 'wp_footer', $dequeue, 2 );
},
+ 'content' => $blocks_content,
'inline_size_limit' => PHP_INT_MAX,
'expected_styles' => array(
'HEAD' => array_merge(
@@ -1629,37 +1652,121 @@ static function ( $handles ) {
'third-party-test-block-css',
'custom-block-styles-css',
),
+ $common_at_wp_enqueue_scripts,
$common_late_in_head,
$common_late_in_body
),
'BODY' => array(),
),
),
- 'standard_classic_theme_config_extra_block_library_inline_style' => array(
+
+ 'standard_classic_theme_config_extra_block_library_inline_style_none_inlined' => array(
'set_up' => static function () {
add_action(
'enqueue_block_assets',
static function () {
- wp_add_inline_style( 'wp-block-library', '/* Extra CSS which prevents empty inline style containing placeholder from being removed. */' );
+ // Extra CSS which prevents empty inline style containing placeholder from being removed.
+ wp_add_inline_style( 'wp-block-library', '.wp-block-separator{ outline:solid 1px lime; }' );
}
);
},
+ 'content' => $blocks_content,
'inline_size_limit' => 0,
'expected_styles' => array(
- 'HEAD' => ( function ( $expected_styles ) {
- // Insert 'wp-block-library-inline-css' right after 'wp-block-library-css'.
- $i = array_search( 'wp-block-library-css', $expected_styles, true );
- $this->assertIsInt( $i, 'Expected wp-block-library-css to be among the styles.' );
- array_splice( $expected_styles, $i + 1, 0, 'wp-block-library-inline-css' );
- return $expected_styles;
- } )( $common_expected_head_styles ),
+ 'HEAD' => array_merge(
+ $early_common_styles,
+ array(
+ 'wp-block-library-css',
+ 'wp-block-separator-css',
+ 'wp-block-library-inline-css-extra',
+ 'classic-theme-styles-css',
+ 'third-party-test-block-css',
+ 'custom-block-styles-css',
+ 'global-styles-inline-css',
+ ),
+ $common_at_wp_enqueue_scripts,
+ $common_late_in_head,
+ $common_late_in_body
+ ),
'BODY' => array(),
),
+ 'assert' => function ( string $buffer, string $filtered_buffer ) {
+ $block_separator_core_style_span = null;
+ $block_separator_custom_style_span = null;
+ $processor = new class( $filtered_buffer ) extends WP_HTML_Tag_Processor {
+ public function get_span(): WP_HTML_Span {
+ $this->set_bookmark( 'here' );
+ return $this->bookmarks['here'];
+ }
+ };
+ while ( $processor->next_tag() ) {
+ if (
+ $processor->get_tag() === 'LINK' &&
+ $processor->get_attribute( 'rel' ) === 'stylesheet' &&
+ $processor->get_attribute( 'id' ) === 'wp-block-separator-css'
+ ) {
+ $block_separator_core_style_span = $processor->get_span();
+ } elseif (
+ $processor->get_tag() === 'STYLE' &&
+ $processor->get_attribute( 'id' ) === 'wp-block-library-inline-css-extra' &&
+ str_contains( $processor->get_modifiable_text(), '.wp-block-separator{ outline:solid 1px lime; }' )
+ ) {
+ $block_separator_custom_style_span = $processor->get_span();
+ }
+ }
+
+ $this->assertInstanceOf( WP_HTML_Span::class, $block_separator_core_style_span, 'Expected the block separator core style to be present.' );
+ $this->assertInstanceOf( WP_HTML_Span::class, $block_separator_custom_style_span, 'Expected the block separator custom style to be present.' );
+ $this->assertGreaterThan( $block_separator_core_style_span->start, $block_separator_custom_style_span->start, 'Expected the block separator custom style to appear after the block separator stylesheet.' );
+ },
),
+
+ 'standard_classic_theme_config_extra_block_library_inline_style_all_inlined' => array(
+ 'set_up' => static function () {
+ add_action(
+ 'enqueue_block_assets',
+ static function () {
+ // Extra CSS which prevents empty inline style containing placeholder from being removed.
+ wp_add_inline_style( 'wp-block-library', '.wp-block-separator{ outline:solid 1px lime; }' );
+ }
+ );
+ },
+ 'content' => $blocks_content,
+ 'inline_size_limit' => PHP_INT_MAX,
+ 'expected_styles' => array(
+ 'HEAD' => array_merge(
+ $early_common_styles,
+ array(
+ 'wp-block-library-inline-css',
+ 'wp-block-separator-inline-css',
+ 'wp-block-library-inline-css-extra',
+ 'classic-theme-styles-inline-css',
+ 'third-party-test-block-css',
+ 'custom-block-styles-css',
+ 'global-styles-inline-css',
+ ),
+ $common_at_wp_enqueue_scripts,
+ $common_late_in_head,
+ $common_late_in_body
+ ),
+ 'BODY' => array(),
+ ),
+ 'assert' => function ( string $buffer, string $filtered_buffer ) {
+ $block_separator_inline_style_start_tag = '