@@ -3643,8 +3643,25 @@ function wp_hoist_late_printed_styles() {
36433643 return ;
36443644 }
36453645
3646+ // Capture the styles enqueued at the enqueue_block_assets action, so that non-core block styles and global styles can be inserted afterwards during hoisting.
3647+ $ style_handles_at_enqueue_block_assets = array ();
3648+ add_action (
3649+ 'enqueue_block_assets ' ,
3650+ static function () use ( &$ style_handles_at_enqueue_block_assets ) {
3651+ $ style_handles_at_enqueue_block_assets = wp_styles ()->queue ;
3652+ },
3653+ PHP_INT_MIN
3654+ );
3655+ add_action (
3656+ 'enqueue_block_assets ' ,
3657+ static function () use ( &$ style_handles_at_enqueue_block_assets ) {
3658+ $ style_handles_at_enqueue_block_assets = array_values ( array_diff ( wp_styles ()->queue , $ style_handles_at_enqueue_block_assets ) );
3659+ },
3660+ PHP_INT_MAX
3661+ );
3662+
36463663 /*
3647- * Add a placeholder comment into the inline styles for wp-block-library, after which where the late block styles
3664+ * Add a placeholder comment into the inline styles for wp-block-library, after which the late block styles
36483665 * can be hoisted from the footer to be printed in the header by means of a filter below on the template enhancement
36493666 * output buffer. The `wp_print_styles` action is used to ensure that if the inline style gets replaced at
36503667 * `enqueue_block_assets` or `wp_enqueue_scripts` that the placeholder will be sure to be present.
@@ -3663,35 +3680,51 @@ static function () use ( $placeholder ) {
36633680 * later hoisted to the HEAD in the template enhancement output buffer. This will run at `wp_print_footer_scripts`
36643681 * before `print_footer_scripts()` is called.
36653682 */
3666- $ printed_block_styles = '' ;
3667- $ printed_late_styles = '' ;
3668- $ capture_late_styles = static function () use ( &$ printed_block_styles , &$ printed_late_styles ) {
3683+ $ printed_core_block_styles = '' ;
3684+ $ printed_other_block_styles = '' ;
3685+ $ printed_global_styles = '' ;
3686+ $ printed_late_styles = '' ;
3687+
3688+ $ capture_late_styles = static function () use ( &$ printed_core_block_styles , &$ printed_other_block_styles , &$ printed_global_styles , &$ printed_late_styles ) {
36693689 // Gather the styles related to on-demand block enqueues.
3670- $ all_block_style_handles = array ();
3690+ $ all_core_block_style_handles = array ();
3691+ $ all_other_block_style_handles = array ();
36713692 foreach ( WP_Block_Type_Registry::get_instance ()->get_all_registered () as $ block_type ) {
3672- foreach ( $ block_type ->style_handles as $ style_handle ) {
3673- $ all_block_style_handles [] = $ style_handle ;
3693+ if ( str_starts_with ( $ block_type ->name , 'core/ ' ) ) {
3694+ foreach ( $ block_type ->style_handles as $ style_handle ) {
3695+ $ all_core_block_style_handles [] = $ style_handle ;
3696+ }
3697+ } else {
3698+ foreach ( $ block_type ->style_handles as $ style_handle ) {
3699+ $ all_other_block_style_handles [] = $ style_handle ;
3700+ }
36743701 }
36753702 }
3676- $ all_block_style_handles = array_merge (
3677- $ all_block_style_handles ,
3678- array (
3679- 'global-styles ' ,
3680- 'block-style-variation-styles ' ,
3681- 'core-block-supports ' ,
3682- 'core-block-supports-duotone ' ,
3683- )
3684- );
36853703
36863704 /*
3687- * First print all styles related to blocks which should inserted right after the wp-block-library stylesheet
3705+ * First print all styles related to blocks which should be inserted right after the wp-block-library stylesheet
36883706 * to preserve the CSS cascade. The logic in this `if` statement is derived from `wp_print_styles()`.
36893707 */
3690- $ enqueued_block_styles = array_values ( array_intersect ( $ all_block_style_handles , wp_styles ()->queue ) );
3691- if ( count ( $ enqueued_block_styles ) > 0 ) {
3708+ $ enqueued_core_block_styles = array_values ( array_intersect ( $ all_core_block_style_handles , wp_styles ()->queue ) );
3709+ if ( count ( $ enqueued_core_block_styles ) > 0 ) {
36923710 ob_start ();
3693- wp_styles ()->do_items ( $ enqueued_block_styles );
3694- $ printed_block_styles = ob_get_clean ();
3711+ wp_styles ()->do_items ( $ enqueued_core_block_styles );
3712+ $ printed_core_block_styles = ob_get_clean ();
3713+ }
3714+
3715+ // Non-core block styles get printed after the classic-theme-styles stylesheet.
3716+ $ enqueued_other_block_styles = array_values ( array_intersect ( $ all_other_block_style_handles , wp_styles ()->queue ) );
3717+ if ( count ( $ enqueued_other_block_styles ) > 0 ) {
3718+ ob_start ();
3719+ wp_styles ()->do_items ( $ enqueued_other_block_styles );
3720+ $ printed_other_block_styles = ob_get_clean ();
3721+ }
3722+
3723+ // Capture the global-styles so that it can be printed separately after classic-theme-styles and other styles enqueued at enqueue_block_assets.
3724+ if ( wp_style_is ( 'global-styles ' ) ) {
3725+ ob_start ();
3726+ wp_styles ()->do_items ( array ( 'global-styles ' ) );
3727+ $ printed_global_styles = ob_get_clean ();
36953728 }
36963729
36973730 /*
@@ -3732,7 +3765,7 @@ static function () use ( $capture_late_styles ) {
37323765 // Replace placeholder with the captured late styles.
37333766 add_filter (
37343767 'wp_template_enhancement_output_buffer ' ,
3735- static function ( $ buffer ) use ( $ placeholder , &$ printed_block_styles , &$ printed_late_styles ) {
3768+ static function ( $ buffer ) use ( $ placeholder , &$ style_handles_at_enqueue_block_assets , & $ printed_core_block_styles , & $ printed_other_block_styles , & $ printed_global_styles , &$ printed_late_styles ) {
37363769
37373770 // Anonymous subclass of WP_HTML_Tag_Processor which exposes underlying bookmark spans.
37383771 $ processor = new class ( $ buffer ) extends WP_HTML_Tag_Processor {
@@ -3777,53 +3810,116 @@ public function remove() {
37773810 }
37783811 };
37793812
3780- /*
3781- * Insert block styles right after wp-block-library (if it is present), and then insert any remaining styles
3782- * at </head> (or else print everything there). The placeholder CSS comment will always be added to the
3783- * wp-block-library inline style since it gets printed at `wp_head` before the blocks are rendered.
3784- * This means that there may not actually be any block styles to hoist from the footer to insert after this
3785- * inline style. The placeholder CSS comment needs to be added so that the inline style gets printed, but
3786- * if the resulting inline style is empty after the placeholder is removed, then the inline style is
3787- * removed.
3788- */
3813+ // Locate the insertion points in the HEAD.
37893814 while ( $ processor ->next_tag ( array ( 'tag_closers ' => 'visit ' ) ) ) {
37903815 if (
37913816 'STYLE ' === $ processor ->get_tag () &&
37923817 'wp-block-library-inline-css ' === $ processor ->get_attribute ( 'id ' )
37933818 ) {
3794- $ css_text = $ processor ->get_modifiable_text ( );
3795-
3796- /*
3797- * A placeholder CSS comment is added to the inline style in order to force an inline STYLE tag to
3798- * be printed. Now that we've located the inline style, the placeholder comment can be removed. If
3799- * there is no CSS left in the STYLE tag after removing the placeholder (aside from the sourceURL
3800- * comment, then remove the STYLE entirely.)
3801- */
3802- $ css_text = str_replace ( $ placeholder , '' , $ css_text );
3803- if ( preg_match ( ' :^/\*# sourceURL=\S+? \*/$: ' , trim ( $ css_text ) ) ) {
3804- $ processor -> remove ();
3805- } else {
3806- $ processor -> set_modifiable_text ( $ css_text ) ;
3819+ $ processor ->set_bookmark ( ' wp_block_library ' );
3820+ } elseif ( ' HEAD ' === $ processor -> get_tag () && $ processor -> is_tag_closer () ) {
3821+ $ processor -> set_bookmark ( ' head_end ' );
3822+ break ;
3823+ } elseif ( ( ' STYLE ' === $ processor -> get_tag () || ' LINK ' === $ processor -> get_tag () ) && $ processor -> get_attribute ( ' id ' ) ) {
3824+ $ id = $ processor -> get_attribute ( ' id ' );
3825+ $ handle = null ;
3826+ if ( ' STYLE ' === $ processor -> get_tag () ) {
3827+ if ( preg_match ( ' /^(.+)-inline-css$/ ' , $ id , $ matches ) ) {
3828+ $ handle = $ matches [ 1 ];
3829+ }
3830+ } elseif ( preg_match ( ' /^(.+)-css$/ ' , $ id , $ matches ) ) {
3831+ $ handle = $ matches [ 1 ] ;
38073832 }
38083833
3809- // Insert the $printed_late_styles immediately after the closing inline STYLE tag. This preserves the CSS cascade.
3810- if ( '' !== $ printed_block_styles ) {
3811- $ processor -> insert_after ( $ printed_block_styles );
3834+ if ( ' classic-theme-styles ' === $ handle ) {
3835+ $ processor -> set_bookmark ( 'classic_theme_styles ' );
3836+ }
38123837
3813- // Prevent printing them again at </head>.
3814- $ printed_block_styles = '' ;
3838+ if ( $ handle && in_array ( $ handle , $ style_handles_at_enqueue_block_assets , true ) ) {
3839+ if ( ! $ processor ->has_bookmark ( 'first_style_at_enqueue_block_assets ' ) ) {
3840+ $ processor ->set_bookmark ( 'first_style_at_enqueue_block_assets ' );
3841+ }
3842+ $ processor ->set_bookmark ( 'last_style_at_enqueue_block_assets ' );
38153843 }
3844+ }
3845+ }
3846+
3847+ /*
3848+ * Insert block styles right after wp-block-library (if it is present). The placeholder CSS comment will
3849+ * always be added to the wp-block-library inline style since it gets printed at `wp_head` before the blocks
3850+ * are rendered. This means that there may not actually be any block styles to hoist from the footer to
3851+ * insert after this inline style. The placeholder CSS comment needs to be added so that the inline style
3852+ * gets printed, but if the resulting inline style is empty after the placeholder is removed, then the
3853+ * inline style is removed.
3854+ */
3855+ if ( $ processor ->has_bookmark ( 'wp_block_library ' ) ) {
3856+ $ processor ->seek ( 'wp_block_library ' );
3857+
3858+ $ css_text = $ processor ->get_modifiable_text ();
3859+
3860+ /*
3861+ * A placeholder CSS comment is added to the inline style in order to force an inline STYLE tag to
3862+ * be printed. Now that we've located the inline style, the placeholder comment can be removed. If
3863+ * there is no CSS left in the STYLE tag after removing the placeholder (aside from the sourceURL
3864+ * comment), then remove the STYLE entirely.
3865+ */
3866+ $ css_text = str_replace ( $ placeholder , '' , $ css_text );
3867+ if ( preg_match ( ':^/\*# sourceURL=\S+? \*/$: ' , trim ( $ css_text ) ) ) {
3868+ $ processor ->remove ();
3869+ } else {
3870+ $ processor ->set_modifiable_text ( $ css_text );
3871+ }
3872+
3873+ $ inserted_after = $ printed_core_block_styles ;
3874+ $ printed_core_block_styles = '' ;
38163875
3817- // If there aren't any late styles, there's no need to continue to finding </head>.
3818- if ( '' === $ printed_late_styles ) {
3819- break ;
3876+ // If the classic-theme-styles is absent, then the third-party block styles cannot be inserted after it, so they get inserted here.
3877+ if ( ! $ processor ->has_bookmark ( 'classic_theme_styles ' ) ) {
3878+ if ( '' !== $ printed_other_block_styles ) {
3879+ $ inserted_after .= $ printed_other_block_styles ;
38203880 }
3821- } elseif ( 'HEAD ' === $ processor ->get_tag () && $ processor ->is_tag_closer () ) {
3822- $ processor ->insert_before ( $ printed_block_styles . $ printed_late_styles );
3823- break ;
3881+ $ printed_other_block_styles = '' ;
3882+
3883+ // If there aren't any other styles printed at enqueue_block_assets either, then the global styles need to also be printed here.
3884+ if ( ! $ processor ->has_bookmark ( 'last_style_at_enqueue_block_assets ' ) ) {
3885+ if ( '' !== $ printed_global_styles ) {
3886+ $ inserted_after .= $ printed_global_styles ;
3887+ }
3888+ $ printed_global_styles = '' ;
3889+ }
3890+ }
3891+
3892+ if ( '' !== $ inserted_after ) {
3893+ $ processor ->insert_after ( "\n" . $ inserted_after );
3894+ }
3895+ }
3896+
3897+ // Insert global-styles after the styles enqueued at enqueue_block_assets.
3898+ if ( '' !== $ printed_global_styles && $ processor ->has_bookmark ( 'last_style_at_enqueue_block_assets ' ) ) {
3899+ $ processor ->seek ( 'last_style_at_enqueue_block_assets ' );
3900+
3901+ $ processor ->insert_after ( "\n" . $ printed_global_styles );
3902+ $ printed_global_styles = '' ;
3903+
3904+ if ( ! $ processor ->has_bookmark ( 'classic_theme_styles ' ) && '' !== $ printed_other_block_styles ) {
3905+ $ processor ->insert_after ( "\n" . $ printed_other_block_styles );
3906+ $ printed_other_block_styles = '' ;
38243907 }
38253908 }
38263909
3910+ // Insert third-party block styles right after the classic-theme-styles.
3911+ if ( '' !== $ printed_other_block_styles && $ processor ->has_bookmark ( 'classic_theme_styles ' ) ) {
3912+ $ processor ->seek ( 'classic_theme_styles ' );
3913+ $ processor ->insert_after ( "\n" . $ printed_other_block_styles );
3914+ $ printed_other_block_styles = '' ;
3915+ }
3916+
3917+ // Print all remaining styles.
3918+ $ remaining_styles = $ printed_core_block_styles . $ printed_other_block_styles . $ printed_global_styles . $ printed_late_styles ;
3919+ if ( $ remaining_styles && $ processor ->has_bookmark ( 'head_end ' ) ) {
3920+ $ processor ->seek ( 'head_end ' );
3921+ $ processor ->insert_before ( $ remaining_styles . "\n" );
3922+ }
38273923 return $ processor ->get_updated_html ();
38283924 }
38293925 );
0 commit comments