Skip to content

replace_text() destroys nested markup in wrapper blocks #11

Description

@kadamwhite

update_block_text_content() finds the first tag in innerHTML, keeps its name and attributes, and replaces everything inside with the new text.

That's correct when the first tag is the text container, like a paragraph or heading, but wrong whenever it's a block like core/button which renders a wrapping div surrounding the a tag. Calling replace_text() on a button to set the text of the link returns <div class="wp-block-button">Link Text</div> with no nested <a>. Also true for core accordion headings and pullquotes; and anything after the first tag's closing tag is dropped as well, so it also can't be safely used for sequential sibling blocks.

This doesn't throw an error so it's only visible when you see a validation warning in the editor.

We could probably fix by calling WP_HTML_Tag_Processor::set_modifiable_text() on the first #text token instead of rebuilding the tag wholesale. That said, it looks like set_modifiable_text() escapes and replace_text() doesn't, so anything that passes esc_html()-wrapped values would start double-escaping.

Therefore, a question: would we want to introduce a new method like replace_inner_text() (and formally document replace_text() as "first tag only, no escaping"), or are we OK with a breaking API change?

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions