Skip to content

Block Bindings: Preserve nested lists when binding List Item content#78991

Draft
cbravobernal wants to merge 10 commits into
WordPress:trunkfrom
cbravobernal:add/list-item-block-bindings-v2
Draft

Block Bindings: Preserve nested lists when binding List Item content#78991
cbravobernal wants to merge 10 commits into
WordPress:trunkfrom
cbravobernal:add/list-item-block-bindings-v2

Conversation

@cbravobernal

@cbravobernal cbravobernal commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Part of the List Item block bindings work, split for review hygiene into two PRs (mirroring the Core split on Trac #65406):

  1. EnablementBlock bindings : add support to list-item #78947 registers core/list-item content as a bindable attribute (the block_bindings_supported_attributes filter). The filter PR. Lands first.
  2. This PR — the render-side fix: a List Item keeps its rich text and a nested List inside the same <li>, and the generic binding replacement would drop the nested list. This adds a Gutenberg-side workaround that preserves the nested inner blocks.

The first commit here is the enablement filter (same change as #78947, included so this PR builds standalone). Review from the second commit onward — the preservation fix and its tests.

Relationship to Core

This is the plugin compat counterpart of the Core fix:

  • wordpress-develop#12113 — generic WP_Block::replace_html() inner-blocks preservation (the real fix).
  • wordpress-develop#12204core/list-item enablement in Core.

The workaround here is runtime-gated: gutenberg_core_preserves_inner_blocks_in_rich_text_block_bindings() detects whether Core already has the fix (4th param on replace_html()). On fixed Core the workaround is inert and Core handles the binding. A marker comment flags the whole block for removal once the minimum required WordPress version ships the Core fix.

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @sauliusv@git.wordpress.org.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: sauliusv@git.wordpress.org.

Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@cbravobernal cbravobernal added the [Type] Enhancement A suggestion for improvement. label Jun 6, 2026
@cbravobernal cbravobernal marked this pull request as draft June 6, 2026 13:57
@cbravobernal cbravobernal force-pushed the add/list-item-block-bindings-v2 branch from 6bcecfa to dab2d81 Compare June 7, 2026 09:58
@cbravobernal cbravobernal added the No Core Sync Required Indicates that any changes do not need to be synced to WordPress Core label Jun 8, 2026
Saulius Vikerta and others added 5 commits June 9, 2026 17:21
Add server-side rendering support so a bound `core/list-item` content
attribute is replaced without dropping nested List inner blocks rendered
inside the same `<li>`.

All logic lives in the wordpress-7.1 compat layer: a `render_block_data`
filter hides the binding from Core's generic rich-text replacement, and a
`render_block` filter resolves the value through the existing
`gutenberg_process_block_bindings()` helper and applies it with a
nested-list-aware replacement. The shipped wordpress-6.9 block-bindings
code is left untouched and no new hooks are introduced.

Adds PHPUnit coverage (plain text, nested/ordered/deep lists, empty value,
pattern overrides, sanitization, non-list inner blocks) and an editor e2e
test.

Builds on WordPress#78947 (list-item block bindings support).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The compat code in this PR is a plugin-only shim that preserves nested
lists when binding list item content. It is not backported to Core: the
Core fix is a different, general implementation in
WordPress/wordpress-develop#12113, after which this workaround can be
removed. Classify the PR with the `No Core Sync Required` label instead
of a backport-changelog entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend the locked List Item case to assert the Link control is hidden
alongside Bold; since `contenteditable=false` disables the whole rich
text, these stand in for every inline format.

Add a List Item test for an unregistered binding source: editing is
locked and the "Source not registered" warning is surfaced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cbravobernal cbravobernal force-pushed the add/list-item-block-bindings-v2 branch from d4ae1c6 to 85e57e3 Compare June 9, 2026 15:21
cbravobernal and others added 4 commits June 10, 2026 00:22
The WP_Block_Processor scan re-derived what the parser already provides:
serialize_block() concatenates innerContent chunks verbatim, so the HTML
before the first inner block is exactly innerContent[0] on every WordPress
version. Reading it directly drops the redundant scan, which could also cut
early on raw text resembling a block delimiter.

Also remove the unreachable ReflectionException handling: method_exists()
already guarantees the method exists before reflection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Verifies the editor canvas and the front end both render the bound
value while preserving nested list inner blocks, complementing the
existing locking and post-meta editing coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Make SOURCE_LABEL a plain string (the registered label was a nested
array) and point the list item render tests' covers annotations at
WP_Block::render, which is what they exercise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a marker above the inner-blocks preservation workaround noting the whole
block can be removed once the minimum required WordPress version includes the
WP_Block::replace_html() fix (wordpress-develop#12113). Detection is runtime,
so the workaround is already inert on fixed Core.
@cbravobernal cbravobernal changed the title Block Bindings: Add list item content support Block Bindings: Preserve nested lists when binding List Item content Jun 17, 2026
The non-nested List Item binding tests (plain text, sanitization, inline image)
exercise only the enablement filter and now live in WordPress#78947. Keep here the cases
that depend on the inner-block preservation workaround: nested lists, ordered
and deeply nested lists, empty values, non-list inner blocks and pattern
overrides.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Block bindings No Core Sync Required Indicates that any changes do not need to be synced to WordPress Core [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants