Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 33 additions & 16 deletions inc/class-registration.php
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ function ( $content ) {

}

if ( function_exists( 'get_block_templates' ) && function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() && current_theme_supports( 'block-templates' ) ) {
if ( function_exists( 'get_block_templates' ) && ( current_theme_supports( 'block-templates' ) || current_theme_supports( 'block-template-parts' ) ) ) {
$this->enqueue_dependencies( 'block-templates' );
}
}
Expand All @@ -406,25 +406,42 @@ public function enqueue_dependencies( $post = null ) {
} elseif ( 'block-templates' === $post ) {
global $_wp_current_template_content;

$slugs = array();
$template_blocks = parse_blocks( $_wp_current_template_content );

foreach ( $template_blocks as $template_block ) {
if ( 'core/template-part' === $template_block['blockName'] ) {
$slugs[] = $template_block['attrs']['slug'];
$content = '';
$slugs = array();

// If we have template content (full block templates), extract template part slugs.
if ( ! empty( $_wp_current_template_content ) ) {
$template_blocks = parse_blocks( $_wp_current_template_content );

foreach ( $template_blocks as $template_block ) {
if ( 'core/template-part' === $template_block['blockName'] && isset( $template_block['attrs']['slug'] ) ) {
$slugs[] = $template_block['attrs']['slug'];
}
}
}

$templates_parts = get_block_templates( array( 'slugs__in' => $slugs ), 'wp_template_part' );

foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) && ! empty( $templates_part->slug ) && in_array( $templates_part->slug, $slugs ) ) {
$content .= $templates_part->content;

// Get the specific template parts referenced in the template.
$templates_parts = get_block_templates( array( 'slug__in' => $slugs ), 'wp_template_part' );
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name should be 'slugs__in' (with an 's'), not 'slug__in'. This is inconsistent with the existing usage in the codebase (see inc/class-blocks-css.php line 134) and will cause the slug filtering to not work correctly.

Suggested change
$templates_parts = get_block_templates( array( 'slug__in' => $slugs ), 'wp_template_part' );
$templates_parts = get_block_templates( array( 'slugs__in' => $slugs ), 'wp_template_part' );

Copilot uses AI. Check for mistakes.

foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) && ! empty( $templates_part->slug ) && in_array( $templates_part->slug, $slugs ) ) {
$content .= $templates_part->content;
}
}

$content .= $_wp_current_template_content;
} else {
// Fallback for classic themes with block-template-parts only.
// Get all template parts since we can't determine which ones are used.
$templates_parts = get_block_templates( array(), 'wp_template_part' );

foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) ) {
$content .= $templates_part->content;
}
}
Comment on lines +433 to 441
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading all template parts when $_wp_current_template_content is empty could have performance implications, especially on sites with many template parts. Consider documenting this as a known limitation or exploring alternative approaches to determine which template parts are actually being used.

Suggested change
// Fallback for classic themes with block-template-parts only.
// Get all template parts since we can't determine which ones are used.
$templates_parts = get_block_templates( array(), 'wp_template_part' );
foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) ) {
$content .= $templates_part->content;
}
}
// Fallback when the current template content is not available.
// We cannot reliably determine which template parts are used here.
// To avoid loading and parsing all template parts (which can have
// significant performance implications on large sites), we skip
// template-part-based dependency detection in this scenario.
$content = '';

Copilot uses AI. Check for mistakes.
}

$content .= $_wp_current_template_content;
$post = $content;
$post = $content;
} else {
$content = get_the_content( null, false, $post );
}
Expand Down
47 changes: 31 additions & 16 deletions inc/css/class-block-frontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -577,32 +577,47 @@ public function enqueue_widgets_css() {
* @access public
*/
public function enqueue_fse_css() {
if ( ! ( function_exists( 'get_block_templates' ) && function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() && current_theme_supports( 'block-templates' ) ) ) {
if ( ! ( function_exists( 'get_block_templates' ) && ( current_theme_supports( 'block-templates' ) || current_theme_supports( 'block-template-parts' ) ) ) ) {
return;
}

global $_wp_current_template_content;

$content = '';
$slugs = array();
$template_blocks = parse_blocks( $_wp_current_template_content );
$content = '';
$slugs = array();

foreach ( $template_blocks as $template_block ) {
if ( 'core/template-part' === $template_block['blockName'] ) {
$slugs[] = $template_block['attrs']['slug'];
// If we have template content (full block templates), extract template part slugs.
if ( ! empty( $_wp_current_template_content ) ) {
$template_blocks = parse_blocks( $_wp_current_template_content );

foreach ( $template_blocks as $template_block ) {
if ( 'core/template-part' === $template_block['blockName'] && isset( $template_block['attrs']['slug'] ) ) {
$slugs[] = $template_block['attrs']['slug'];
}
}
}

$templates_parts = get_block_templates( array( 'slugs__in' => $slugs ), 'wp_template_part' );

foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) && ! empty( $templates_part->slug ) && in_array( $templates_part->slug, $slugs ) ) {
$content .= $templates_part->content;

// Get the specific template parts referenced in the template.
$templates_parts = get_block_templates( array( 'slug__in' => $slugs ), 'wp_template_part' );
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name should be 'slugs__in' (with an 's'), not 'slug__in'. This is inconsistent with the existing usage in the codebase (see inc/class-blocks-css.php line 134) and will cause the slug filtering to not work correctly.

Suggested change
$templates_parts = get_block_templates( array( 'slug__in' => $slugs ), 'wp_template_part' );
$templates_parts = get_block_templates( array( 'slugs__in' => $slugs ), 'wp_template_part' );

Copilot uses AI. Check for mistakes.

foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) && ! empty( $templates_part->slug ) && in_array( $templates_part->slug, $slugs ) ) {
$content .= $templates_part->content;
}
}

$content .= $_wp_current_template_content;
} else {
// Fallback for classic themes with block-template-parts only.
// Get all template parts since we can't determine which ones are used.
$templates_parts = get_block_templates( array(), 'wp_template_part' );

foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) ) {
$content .= $templates_part->content;
Comment on lines +610 to +616
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading all template parts when $_wp_current_template_content is empty could have performance implications, especially on sites with many template parts. Consider documenting this as a known limitation or exploring alternative approaches to determine which template parts are actually being used.

Suggested change
// Fallback for classic themes with block-template-parts only.
// Get all template parts since we can't determine which ones are used.
$templates_parts = get_block_templates( array(), 'wp_template_part' );
foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) ) {
$content .= $templates_part->content;
/**
* Fallback for classic themes with block-template-parts only.
*
* Note: This fallback loads all registered template parts when
* $_wp_current_template_content is empty, because there is no reliable
* way to detect which ones are actually referenced. On sites with many
* template parts this may have performance implications, since all of
* them are queried and parsed in order to extract CSS.
*
* Developers can disable this behavior by filtering
* 'themeisle_gutenbergblocks_load_all_template_parts' and returning
* false when they do not need CSS to be generated from template parts
* in this fallback scenario.
*/
$load_all_template_parts = apply_filters( 'themeisle_gutenbergblocks_load_all_template_parts', true );
if ( $load_all_template_parts ) {
// Get all template parts since we can't determine which ones are used.
$templates_parts = get_block_templates( array(), 'wp_template_part' );
foreach ( $templates_parts as $templates_part ) {
if ( ! empty( $templates_part->content ) ) {
$content .= $templates_part->content;
}

Copilot uses AI. Check for mistakes.
}
}
}

$content .= $_wp_current_template_content;

$blocks = parse_blocks( $content );

if ( ! is_array( $blocks ) || empty( $blocks ) ) {
Expand Down
4 changes: 2 additions & 2 deletions src/blocks/test/performance/specs/post-editor.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -487,10 +487,10 @@ test.describe( 'Post Editor Performance', () => {
name: 'Block Inserter',
} );
const paragraphBlockItem = page.locator(
'.block-editor-inserter__menu .editor-block-list-item-paragraph'
'.block-editor-inserter__menu .editor-block-list-item-paragraph\\/paragraph'
);
const headingBlockItem = page.locator(
'.block-editor-inserter__menu .editor-block-list-item-heading'
'.block-editor-inserter__menu .editor-block-list-item-heading\\/heading'
);

// Open Inserter.
Expand Down
Loading