Codeinwp / Codeinwp/otter-blocks

Block assets are never enqueued when a block sits inside a nested synced pattern

Open
#2,984 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
198
Forks
36
Avg merge
3d 4h
Merged PRs (30d)
30

Description

Description

When a block sits inside a synced pattern (core/block) that is itself nested inside another block, none of that block's assets are enqueued on the frontend — neither its stylesheet nor its script. The block renders as bare markup.

I expect the pattern's blocks to get their assets registered regardless of how deeply the pattern is nested, the same way they do when the pattern sits at the top level of the page. Instead nothing is registered.

For the Form block the consequence is not only cosmetic: submission happens in JS, so the form cannot be submitted at all. .otter-form__container also loses display: flex, so field widths stop working and inputs fall back to the theme's default styling.

Step-by-step reproduction instructions
  1. Add a Form block to a page.
  2. Select it and create a synced pattern from it.
  3. On a page, place that pattern inside a Group block.
  4. View the page on the frontend and look for otter-form-style and build/blocks/form.js.

Two otherwise identical pages against the same pattern:

Page content otter-form-style form.js
core/block at top level loaded loaded
core/group > core/block missing missing
Screenshots, screen recording, code snippet or Help Scout ticket

Registration::enqueue_dependencies()inc/class-registration.php:531:

if ( has_block( 'core/block', $post ) ) {
    $blocks = parse_blocks( $content );
    $blocks = array_filter(
        $blocks,
        function ( $block ) {
            return 'core/block' === $block['blockName'] && isset( $block['attrs']['ref'] );
        }
    );

    foreach ( $blocks as $block ) {
        $this->enqueue_dependencies( $block['attrs']['ref'] );
    }
}

parse_blocks() returns a flat list of top-level blocks and innerBlocks is never walked, so a nested pattern is invisible. The has_block() guard above does match, since it searches the raw content string — only the collection step misses it.

Two things that may be worth more than adding recursion:

  1. The plugin already gets this right elsewhere. The dynamic CSS path in inc/css/class-block-frontend.php traverses nested patterns correctly. That asymmetry is what made this look like an oversight rather than a deliberate trade-off.

  2. The conditional registration is what defeats WordPress's own mechanism. The Form block declares "style": "otter-form-style" and "script": "otter-form" in its block.json, and core enqueues those handles when the block actually renders — at any depth, from a pattern or not. But the handles are only registered if this scan found the block first, so core's enqueue silently no-ops on an unregistered handle. Registration is cheap; enqueueing is what costs. Registering unconditionally and letting core enqueue at render time would make the scan, and this bug, unnecessary.

The same flat filter serves the widgets path (enqueue_dependencies( 'widgets' )), so a nested pattern in a widget area is affected too.

Environment info

Otter Blocks 3.2.2, WordPress 7.0.4, PHP 8.4, classic (non-FSE) theme — a Neve child theme. The code is unchanged on master as of this writing. No pastebin; happy to provide Site Health info if useful.

Is the issue you are reporting a regression

No. The pattern handling was added in 2.0.1 ("Fix styles not loaded for Reusable Blocks") and has only ever covered the top level. Since WP 6.3 made synced patterns the standard way to reuse content — typically nested inside a section or group — the case has become common.


Created with help of Claude Code.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at Registration::enqueue_dependencies() in inc/class-registration.php:531 and inspect how parse_blocks() collects core/block entries, then compare the nested-pattern traversal in inc/css/class-block-frontend.php. Reproduce the top-level and Group-nested cases, and verify that otter-form-style and build/blocks/form.js are loaded for the nested pattern, including in the widgets path.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, php, wordpress
Domain
backend, frontend, web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.