@@ -3701,8 +3701,25 @@ function wp_hoist_late_printed_styles() {
37013701 return ;
37023702 }
37033703
3704+ // 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.
3705+ $ style_handles_at_enqueue_block_assets = array ();
3706+ add_action (
3707+ 'enqueue_block_assets ' ,
3708+ static function () use ( &$ style_handles_at_enqueue_block_assets ) {
3709+ $ style_handles_at_enqueue_block_assets = wp_styles ()->queue ;
3710+ },
3711+ PHP_INT_MIN
3712+ );
3713+ add_action (
3714+ 'enqueue_block_assets ' ,
3715+ static function () use ( &$ style_handles_at_enqueue_block_assets ) {
3716+ $ style_handles_at_enqueue_block_assets = array_values ( array_diff ( wp_styles ()->queue , $ style_handles_at_enqueue_block_assets ) );
3717+ },
3718+ PHP_INT_MAX
3719+ );
3720+
37043721 /*
3705- * Add a placeholder comment into the inline styles for wp-block-library, after which where the late block styles
3722+ * Add a placeholder comment into the inline styles for wp-block-library, after which the late block styles
37063723 * can be hoisted from the footer to be printed in the header by means of a filter below on the template enhancement
37073724 * output buffer. The `wp_print_styles` action is used to ensure that if the inline style gets replaced at
37083725 * `enqueue_block_assets` or `wp_enqueue_scripts` that the placeholder will be sure to be present.
@@ -3721,35 +3738,51 @@ static function () use ( $placeholder ) {
37213738 * later hoisted to the HEAD in the template enhancement output buffer. This will run at `wp_print_footer_scripts`
37223739 * before `print_footer_scripts()` is called.
37233740 */
3724- $ printed_block_styles = '' ;
3725- $ printed_late_styles = '' ;
3726- $ capture_late_styles = static function () use ( &$ printed_block_styles , &$ printed_late_styles ) {
3741+ $ printed_core_block_styles = '' ;
3742+ $ printed_other_block_styles = '' ;
3743+ $ printed_global_styles = '' ;
3744+ $ printed_late_styles = '' ;
3745+
3746+ $ capture_late_styles = static function () use ( &$ printed_core_block_styles , &$ printed_other_block_styles , &$ printed_global_styles , &$ printed_late_styles ) {
37273747 // Gather the styles related to on-demand block enqueues.
3728- $ all_block_style_handles = array ();
3748+ $ all_core_block_style_handles = array ();
3749+ $ all_other_block_style_handles = array ();
37293750 foreach ( WP_Block_Type_Registry::get_instance ()->get_all_registered () as $ block_type ) {
3730- foreach ( $ block_type ->style_handles as $ style_handle ) {
3731- $ all_block_style_handles [] = $ style_handle ;
3751+ if ( str_starts_with ( $ block_type ->name , 'core/ ' ) ) {
3752+ foreach ( $ block_type ->style_handles as $ style_handle ) {
3753+ $ all_core_block_style_handles [] = $ style_handle ;
3754+ }
3755+ } else {
3756+ foreach ( $ block_type ->style_handles as $ style_handle ) {
3757+ $ all_other_block_style_handles [] = $ style_handle ;
3758+ }
37323759 }
37333760 }
3734- $ all_block_style_handles = array_merge (
3735- $ all_block_style_handles ,
3736- array (
3737- 'global-styles ' ,
3738- 'block-style-variation-styles ' ,
3739- 'core-block-supports ' ,
3740- 'core-block-supports-duotone ' ,
3741- )
3742- );
37433761
37443762 /*
3745- * First print all styles related to blocks which should inserted right after the wp-block-library stylesheet
3763+ * First print all styles related to blocks which should be inserted right after the wp-block-library stylesheet
37463764 * to preserve the CSS cascade. The logic in this `if` statement is derived from `wp_print_styles()`.
37473765 */
3748- $ enqueued_block_styles = array_values ( array_intersect ( $ all_block_style_handles , wp_styles ()->queue ) );
3749- if ( count ( $ enqueued_block_styles ) > 0 ) {
3766+ $ enqueued_core_block_styles = array_values ( array_intersect ( $ all_core_block_style_handles , wp_styles ()->queue ) );
3767+ if ( count ( $ enqueued_core_block_styles ) > 0 ) {
37503768 ob_start ();
3751- wp_styles ()->do_items ( $ enqueued_block_styles );
3752- $ printed_block_styles = ob_get_clean ();
3769+ wp_styles ()->do_items ( $ enqueued_core_block_styles );
3770+ $ printed_core_block_styles = ob_get_clean ();
3771+ }
3772+
3773+ // Non-core block styles get printed after the classic-theme-styles stylesheet.
3774+ $ enqueued_other_block_styles = array_values ( array_intersect ( $ all_other_block_style_handles , wp_styles ()->queue ) );
3775+ if ( count ( $ enqueued_other_block_styles ) > 0 ) {
3776+ ob_start ();
3777+ wp_styles ()->do_items ( $ enqueued_other_block_styles );
3778+ $ printed_other_block_styles = ob_get_clean ();
3779+ }
3780+
3781+ // Capture the global-styles so that it can be printed separately after classic-theme-styles and other styles enqueued at enqueue_block_assets.
3782+ if ( wp_style_is ( 'global-styles ' ) ) {
3783+ ob_start ();
3784+ wp_styles ()->do_items ( array ( 'global-styles ' ) );
3785+ $ printed_global_styles = ob_get_clean ();
37533786 }
37543787
37553788 /*
@@ -3790,7 +3823,7 @@ static function () use ( $capture_late_styles ) {
37903823 // Replace placeholder with the captured late styles.
37913824 add_filter (
37923825 'wp_template_enhancement_output_buffer ' ,
3793- static function ( $ buffer ) use ( $ placeholder , &$ printed_block_styles , &$ printed_late_styles ) {
3826+ 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 ) {
37943827
37953828 // Anonymous subclass of WP_HTML_Tag_Processor which exposes underlying bookmark spans.
37963829 $ processor = new class ( $ buffer ) extends WP_HTML_Tag_Processor {
@@ -3835,53 +3868,116 @@ public function remove() {
38353868 }
38363869 };
38373870
3838- /*
3839- * Insert block styles right after wp-block-library (if it is present), and then insert any remaining styles
3840- * at </head> (or else print everything there). The placeholder CSS comment will always be added to the
3841- * wp-block-library inline style since it gets printed at `wp_head` before the blocks are rendered.
3842- * This means that there may not actually be any block styles to hoist from the footer to insert after this
3843- * inline style. The placeholder CSS comment needs to be added so that the inline style gets printed, but
3844- * if the resulting inline style is empty after the placeholder is removed, then the inline style is
3845- * removed.
3846- */
3871+ // Locate the insertion points in the HEAD.
38473872 while ( $ processor ->next_tag ( array ( 'tag_closers ' => 'visit ' ) ) ) {
38483873 if (
38493874 'STYLE ' === $ processor ->get_tag () &&
38503875 'wp-block-library-inline-css ' === $ processor ->get_attribute ( 'id ' )
38513876 ) {
3852- $ css_text = $ processor ->get_modifiable_text ( );
3853-
3854- /*
3855- * A placeholder CSS comment is added to the inline style in order to force an inline STYLE tag to
3856- * be printed. Now that we've located the inline style, the placeholder comment can be removed. If
3857- * there is no CSS left in the STYLE tag after removing the placeholder (aside from the sourceURL
3858- * comment, then remove the STYLE entirely.)
3859- */
3860- $ css_text = str_replace ( $ placeholder , '' , $ css_text );
3861- if ( preg_match ( ' :^/\*# sourceURL=\S+? \*/$: ' , trim ( $ css_text ) ) ) {
3862- $ processor -> remove ();
3863- } else {
3864- $ processor -> set_modifiable_text ( $ css_text ) ;
3877+ $ processor ->set_bookmark ( ' wp_block_library ' );
3878+ } elseif ( ' HEAD ' === $ processor -> get_tag () && $ processor -> is_tag_closer () ) {
3879+ $ processor -> set_bookmark ( ' head_end ' );
3880+ break ;
3881+ } elseif ( ( ' STYLE ' === $ processor -> get_tag () || ' LINK ' === $ processor -> get_tag () ) && $ processor -> get_attribute ( ' id ' ) ) {
3882+ $ id = $ processor -> get_attribute ( ' id ' );
3883+ $ handle = null ;
3884+ if ( ' STYLE ' === $ processor -> get_tag () ) {
3885+ if ( preg_match ( ' /^(.+)-inline-css$/ ' , $ id , $ matches ) ) {
3886+ $ handle = $ matches [ 1 ];
3887+ }
3888+ } elseif ( preg_match ( ' /^(.+)-css$/ ' , $ id , $ matches ) ) {
3889+ $ handle = $ matches [ 1 ] ;
38653890 }
38663891
3867- // Insert the $printed_late_styles immediately after the closing inline STYLE tag. This preserves the CSS cascade.
3868- if ( '' !== $ printed_block_styles ) {
3869- $ processor -> insert_after ( $ printed_block_styles );
3892+ if ( ' classic-theme-styles ' === $ handle ) {
3893+ $ processor -> set_bookmark ( 'classic_theme_styles ' );
3894+ }
38703895
3871- // Prevent printing them again at </head>.
3872- $ printed_block_styles = '' ;
3896+ if ( $ handle && in_array ( $ handle , $ style_handles_at_enqueue_block_assets , true ) ) {
3897+ if ( ! $ processor ->has_bookmark ( 'first_style_at_enqueue_block_assets ' ) ) {
3898+ $ processor ->set_bookmark ( 'first_style_at_enqueue_block_assets ' );
3899+ }
3900+ $ processor ->set_bookmark ( 'last_style_at_enqueue_block_assets ' );
38733901 }
3902+ }
3903+ }
3904+
3905+ /*
3906+ * Insert block styles right after wp-block-library (if it is present). The placeholder CSS comment will
3907+ * always be added to the wp-block-library inline style since it gets printed at `wp_head` before the blocks
3908+ * are rendered. This means that there may not actually be any block styles to hoist from the footer to
3909+ * insert after this inline style. The placeholder CSS comment needs to be added so that the inline style
3910+ * gets printed, but if the resulting inline style is empty after the placeholder is removed, then the
3911+ * inline style is removed.
3912+ */
3913+ if ( $ processor ->has_bookmark ( 'wp_block_library ' ) ) {
3914+ $ processor ->seek ( 'wp_block_library ' );
3915+
3916+ $ css_text = $ processor ->get_modifiable_text ();
3917+
3918+ /*
3919+ * A placeholder CSS comment is added to the inline style in order to force an inline STYLE tag to
3920+ * be printed. Now that we've located the inline style, the placeholder comment can be removed. If
3921+ * there is no CSS left in the STYLE tag after removing the placeholder (aside from the sourceURL
3922+ * comment), then remove the STYLE entirely.
3923+ */
3924+ $ css_text = str_replace ( $ placeholder , '' , $ css_text );
3925+ if ( preg_match ( ':^/\*# sourceURL=\S+? \*/$: ' , trim ( $ css_text ) ) ) {
3926+ $ processor ->remove ();
3927+ } else {
3928+ $ processor ->set_modifiable_text ( $ css_text );
3929+ }
3930+
3931+ $ inserted_after = $ printed_core_block_styles ;
3932+ $ printed_core_block_styles = '' ;
38743933
3875- // If there aren't any late styles, there's no need to continue to finding </head>.
3876- if ( '' === $ printed_late_styles ) {
3877- break ;
3934+ // If the classic-theme-styles is absent, then the third-party block styles cannot be inserted after it, so they get inserted here.
3935+ if ( ! $ processor ->has_bookmark ( 'classic_theme_styles ' ) ) {
3936+ if ( '' !== $ printed_other_block_styles ) {
3937+ $ inserted_after .= $ printed_other_block_styles ;
38783938 }
3879- } elseif ( 'HEAD ' === $ processor ->get_tag () && $ processor ->is_tag_closer () ) {
3880- $ processor ->insert_before ( $ printed_block_styles . $ printed_late_styles );
3881- break ;
3939+ $ printed_other_block_styles = '' ;
3940+
3941+ // If there aren't any other styles printed at enqueue_block_assets either, then the global styles need to also be printed here.
3942+ if ( ! $ processor ->has_bookmark ( 'last_style_at_enqueue_block_assets ' ) ) {
3943+ if ( '' !== $ printed_global_styles ) {
3944+ $ inserted_after .= $ printed_global_styles ;
3945+ }
3946+ $ printed_global_styles = '' ;
3947+ }
3948+ }
3949+
3950+ if ( '' !== $ inserted_after ) {
3951+ $ processor ->insert_after ( "\n" . $ inserted_after );
3952+ }
3953+ }
3954+
3955+ // Insert global-styles after the styles enqueued at enqueue_block_assets.
3956+ if ( '' !== $ printed_global_styles && $ processor ->has_bookmark ( 'last_style_at_enqueue_block_assets ' ) ) {
3957+ $ processor ->seek ( 'last_style_at_enqueue_block_assets ' );
3958+
3959+ $ processor ->insert_after ( "\n" . $ printed_global_styles );
3960+ $ printed_global_styles = '' ;
3961+
3962+ if ( ! $ processor ->has_bookmark ( 'classic_theme_styles ' ) && '' !== $ printed_other_block_styles ) {
3963+ $ processor ->insert_after ( "\n" . $ printed_other_block_styles );
3964+ $ printed_other_block_styles = '' ;
38823965 }
38833966 }
38843967
3968+ // Insert third-party block styles right after the classic-theme-styles.
3969+ if ( '' !== $ printed_other_block_styles && $ processor ->has_bookmark ( 'classic_theme_styles ' ) ) {
3970+ $ processor ->seek ( 'classic_theme_styles ' );
3971+ $ processor ->insert_after ( "\n" . $ printed_other_block_styles );
3972+ $ printed_other_block_styles = '' ;
3973+ }
3974+
3975+ // Print all remaining styles.
3976+ $ remaining_styles = $ printed_core_block_styles . $ printed_other_block_styles . $ printed_global_styles . $ printed_late_styles ;
3977+ if ( $ remaining_styles && $ processor ->has_bookmark ( 'head_end ' ) ) {
3978+ $ processor ->seek ( 'head_end ' );
3979+ $ processor ->insert_before ( $ remaining_styles . "\n" );
3980+ }
38853981 return $ processor ->get_updated_html ();
38863982 }
38873983 );
0 commit comments