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', () => {
'- 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(`
+
+
+
+ | []
|
+
|
+
|
+
+
+
|
+
|
+
|
+
+
+
+ `),
+ });
+ });
});
});
});