Fix: Delete key on empty heading transforms following paragraph into heading - #78779
Fix: Delete key on empty heading transforms following paragraph into heading#78779coderGtm wants to merge 9 commits into
Conversation
|
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 If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Nice, thanks for the PR! Confirming it works for me, and I personally appreciate this a great deal as far as the writing experience. Since this touches a sensitive part of the code, I will ultimately defer to developers familar with this code to approve or not. @ellatrix has worked a lot on writing flow. |
|
Can you check the e2e test failures? It seems this could have introduced regressions on the list block no? |
| // and keep blockB focused. Without this check, merging would transform | ||
| // blockB into blockA's type (e.g. paragraph → heading), which is | ||
| // unexpected when the leading block is simply empty. | ||
| if ( blockAType.merge && isUnmodifiedBlock( blockA, 'content' ) ) { |
There was a problem hiding this comment.
We probably need to check if blockA.name !== blockB.name and also it would be better to have the code below the if ( ! blockAType.merge ) { block for two reasons:
- We remove the
blockAType.mergecheck - Preserve the
if ( isUnmodifiedDefaultBlock( blockB ) ) {block flow. Placement here changes the current behavior a bit right now and we can avoid it.
There was a problem hiding this comment.
Thanks @ntsekouras! That actually is a better way. I made the change and tested the behaviour and It works flawlessly.
There was a problem hiding this comment.
Failing list tests seem that something different (or more) is needed. --cc @ellatrix for any quick insights due to the heavy work on this area.
|
So I have fixed the logic and updated the test. There is still a keyboard testcase failing which I will try solving. |
What?
Closes #78767
Fix a bug where pressing Delete on an empty heading block incorrectly transforms the following paragraph block into a heading.
Why?
When a heading block is emptied and the user presses Delete, the expected behaviour is that the empty heading is removed and the paragraph below is left unchanged. Instead, the paragraph was being converted into a heading — matching the type of the block that was being deleted.
This only occurred with the Delete key (forward merge). Backspace was unaffected because pressing Backspace on an empty heading with no preceding block triggers
switchToDefaultOrRemove(), which converts the heading itself to a paragraph without ever reaching the merge path.How?
The bug was in the
mergeBlocksaction (packages/block-editor/src/store/actions.js). WhenmergeBlocks(blockA, blockB)is called,blockA's type is preserved andblockB's content is merged in. Two existing guard conditions short-circuit this behaviour:isUnmodifiedDefaultBlock(blockA)→ removesblockA(handles an empty default/paragraph block)isUnmodifiedDefaultBlock(blockB)→ removesblockB(handles an empty following block)Neither condition matched for an empty heading (
blockA) above a paragraph with content (blockB): a heading is not the default block type, so the first check failed, and the paragraph had content, so the second also failed. The code then fell through to the merge logic, which callsswitchToBlockType(blockB, blockA.name)— transforming the paragraph into a heading before merging.The fix adds a new guard: if
blockAhas amergefunction but its content-role attributes are empty (isUnmodifiedBlock(blockA, 'content')), simply removeblockAand focusblockBinstead of merging. A unit test covering this case is included.Testing Instructions
Testing Instructions for Keyboard
Screenshots or screencast
Screen.Recording.2026-05-28.at.7.24.19.PM.mov
Screen.Recording.2026-05-28.at.7.31.40.PM.mov
Use of AI Tools
This PR was developed with the assistance of GitHub Copilot (code exploration, fix implementation, and test authoring). The change was reviewed and verified manually.