diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/deleteForward.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/deleteForward.js
index 94657a03b35..338f5f4ded4 100644
--- a/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/deleteForward.js
+++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/deleteForward.js
@@ -24,6 +24,8 @@ import {
boundariesOut,
isEditorTab,
isVisible,
+ isUnbreakable,
+ isEmptyBlock,
isWhitespace,
isVisibleTextNode,
} from '../utils/utils.js';
@@ -201,6 +203,16 @@ HTMLElement.prototype.oDeleteForward = function (offset) {
filterFunc,
);
if (firstOutNode) {
+ // If next sibblings is an unbreadable node, and current node is empty, we
+ // delete the current node and put the selection at the beginning of the
+ // next sibbling.
+ if (nextSibling && isUnbreakable(nextSibling) && isEmptyBlock(this)) {
+ const restore = prepareUpdate(...boundariesOut(this));
+ this.remove();
+ restore();
+ setSelection(firstOutNode, 0);
+ return;
+ }
const [node, offset] = leftPos(firstOutNode);
// If the next node is a
we call directly the htmlElement
// oDeleteBackward : because we don't want the special cases of
diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js
index 0384598605f..eeabdf815a4 100644
--- a/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js
+++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js
@@ -1309,7 +1309,7 @@ export function isUnbreakable(node) {
}
return (
isUnremovable(node) || // An unremovable node is always unbreakable.
- ['THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'SECTION', 'DIV'].includes(node.tagName) ||
+ ['TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'SECTION', 'DIV'].includes(node.tagName) ||
node.hasAttribute('t') ||
(node.nodeType === Node.ELEMENT_NODE &&
(node.nodeName === 'T' ||
diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/editor.test.js b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/editor.test.js
index 1d55b7c778c..92821b781f4 100644
--- a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/editor.test.js
+++ b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/editor.test.js
@@ -289,8 +289,8 @@ describe('Editor', () => {
`abc
`,
stepFunction: deleteForward,
contentAfter: ``,
+ ``,
});
});
it('should remove empty unbreakable', async () => {
@@ -1899,6 +1899,36 @@ X[]
``,
});
});
+
+ it('should not merge p with an unbreakable.', async () => {
+ await testEditor(BasicEditor, {
+ contentBefore: `ab[]
`,
+ stepFunction: deleteForward,
+ contentAfter: `ab[]
`,
+ });
+ await testEditor(BasicEditor, {
+ contentBefore: `ab[]
cd
`,
+ stepFunction: deleteForward,
+ contentAfter: `ab[]
cd
`,
+ });
+ });
+ it('should delete empty p just before an unbreakable.', async () => {
+ await testEditor(BasicEditor, {
+ contentBefore: `[]
`,
+ stepFunction: deleteForward,
+ contentAfter: ``,
+ });
+ await testEditor(BasicEditor, {
+ contentBefore: `[]
cd
`,
+ stepFunction: deleteForward,
+ contentAfter: `[]cd
`,
+ });
+ await testEditor(BasicEditor, {
+ contentBefore: `[]
cd
`,
+ stepFunction: deleteForward,
+ contentAfter: `[]cd
`,
+ });
+ });
it('should merge the following inline text node', async () => {
await testEditor(BasicEditor, {
contentBefore: 'abc
[]def',