diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js index f7747440ae2..2bd8c37ce20 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js @@ -490,7 +490,11 @@ export const editorCommands = { const li = new Set(); const blocks = new Set(); - for (const node of getTraversedNodes(editor.editable)) { + const selectedBlocks = getTraversedNodes(editor.editable); + const deepestSelectedBlocks = selectedBlocks.filter(block => ( + !descendants(block).some(descendant => selectedBlocks.includes(descendant)) + )); + for (const node of deepestSelectedBlocks) { if (node.nodeType === Node.TEXT_NODE && isWhitespace(node) && closestElement(node).isContentEditable) { node.remove(); } else { 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 032a88b761a..adac7549470 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 @@ -1023,7 +1023,7 @@ export const formatSelection = (editor, formatName, {applyStyle, formatProps} = } const selectedTextNodes = getSelectedNodes(editor.editable) - .filter(n => n.nodeType === Node.TEXT_NODE && closestElement(n).isContentEditable); + .filter(n => n.nodeType === Node.TEXT_NODE && closestElement(n).isContentEditable && (isVisibleTextNode(n) || isZWS(n))); const formatSpec = formatsSpecs[formatName]; for (const selectedTextNode of selectedTextNodes) { diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/list.test.js b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/list.test.js index 5ba40e784fa..c56e771a26e 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/list.test.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/list.test.js @@ -59,6 +59,59 @@ describe('List', () => { '', }); }); + it('should turn an empty paragraph of multiple table cells into a list', async () => { + await testEditor(BasicEditor, { + contentBefore: unformat(` + + + + + + + + + + + + + +
[





]
+ `), + stepFunction: toggleUnorderedList, + contentAfterEdit: unformat(` + + + + + + + + + + + + + +
[






]
+ `), + contentAfter: unformat(` + + + + + + + + + + + + + +
[]






+ `), + }); + }); }); describe('Remove', () => { it('should turn an empty list into a paragraph', async () => { @@ -137,6 +190,59 @@ describe('List', () => { `), }); }); + it('should turn an list of multiple table cells into a empty paragraph', async () => { + await testEditor(BasicEditor, { + contentBefore: unformat(` + + + + + + + + + + + + + +
[






]
+ `), + stepFunction: toggleUnorderedList, + contentAfterEdit: unformat(` + + + + + + + + + + + + + +
[







]
+ `), + contentAfter: unformat(` + + + + + + + + + + + + + +
[]







+ `), + }); + }); }); describe('Transform', () => { it('should turn an empty ordered list into an unordered list', async () => { @@ -194,6 +300,59 @@ describe('List', () => { '
  1. ab cd ef[]gh
', }); }); + it('should turn an empty paragraph of multiple table cells into a list', async () => { + await testEditor(BasicEditor, { + contentBefore: unformat(` + + + + + + + + + + + + + +
[





]
+ `), + stepFunction: toggleOrderedList, + contentAfterEdit: unformat(` + + + + + + + + + + + + + +
[






]
+ `), + contentAfter: unformat(` + + + + + + + + + + + + + +
[]






+ `), + }); + }); }); describe('Remove', () => { it('should turn an empty list into a paragraph', async () => { @@ -233,6 +392,59 @@ describe('List', () => { '

ab cd ef[]gh

', }); }); + it('should turn an list of multiple table cells into a empty paragraph', async () => { + await testEditor(BasicEditor, { + contentBefore: unformat(` + + + + + + + + + + + + + +
[






]
+ `), + stepFunction: toggleOrderedList, + contentAfterEdit: unformat(` + + + + + + + + + + + + + +
[







]
+ `), + contentAfter: unformat(` + + + + + + + + + + + + + +
[]







+ `), + }); + }); }); }); describe('Checklist', () => { @@ -401,6 +613,65 @@ describe('List', () => { }, }); }); + it('should turn an empty paragraph of multiple table cells into a checklist', async () => { + await testEditor(BasicEditor, { + removeCheckIds: true, + contentBefore: unformat(` + + + + + + + + + + + + + +
[





]
+ `), + stepFunction: editor => { + toggleCheckList(editor); + for (const li of editor.editable.querySelectorAll('li[id^=checkId-]')) { + li.removeAttribute('id'); + } + }, + contentAfterEdit: unformat(` + + + + + + + + + + + + + +
[






]
+ `), + contentAfter: unformat(` + + + + + + + + + + + + + +
[]






+ `), + }); + }); }); describe('Remove', () => { it('should turn an empty list into a paragraph', async () => { @@ -483,6 +754,59 @@ describe('List', () => { `), }); }); + it('should turn an list of multiple table cells into a empty paragraph', async () => { + await testEditor(BasicEditor, { + contentBefore: unformat(` + + + + + + + + + + + + + +
[






]
+ `), + stepFunction: toggleCheckList, + contentAfterEdit: unformat(` + + + + + + + + + + + + + +
[







]
+ `), + contentAfter: unformat(` + + + + + + + + + + + + + +
[]







+ `), + }); + }); }); }); });