diff --git a/addons/web_editor/static/lib/odoo-editor/src/utils/sanitize.js b/addons/web_editor/static/lib/odoo-editor/src/utils/sanitize.js index 8ea53d29b1e..498f83bd6e7 100644 --- a/addons/web_editor/static/lib/odoo-editor/src/utils/sanitize.js +++ b/addons/web_editor/static/lib/odoo-editor/src/utils/sanitize.js @@ -104,93 +104,97 @@ class Sanitize { } _parse(node) { - if (!node) { - return; - } - - // Merge identical elements together - while (areSimilarElements(node, node.previousSibling) && !isUnbreakable(node)) { - getDeepRange(this.root, { select: true }); - const restoreCursor = node.isConnected && preserveCursor(this.root.ownerDocument); - const nodeP = node.previousSibling; - moveNodes(...endPos(node.previousSibling), node); - if (restoreCursor) { - restoreCursor(); - }; - node = nodeP; - } - - // Remove zero-width spaces added by `fillEmpty` when there is content - // and the selection is not next to it. - const anchor = this.root.ownerDocument.getSelection().anchorNode; - if ( - node.nodeType === Node.TEXT_NODE && - node.textContent.includes('\u200B') && - ( - node.textContent.length > 1 || - // There can be multiple ajacent text nodes, in which case the - // zero-width space is not needed either, despite being alone - // (length === 1) in its own text node. - Array.from(node.parentNode.childNodes).find( - sibling => - sibling !== node && - sibling.nodeType === Node.TEXT_NODE && - sibling.length > 0 - ) - ) && - !isBlock(node.parentElement) && - anchor !== node - ) { - const restoreCursor = node.isConnected && preserveCursor(this.root.ownerDocument); - node.textContent = node.textContent.replace('\u200B', ''); - node.parentElement.removeAttribute("data-oe-zws-empty-inline"); - if (restoreCursor) { - restoreCursor(); - }; - } - - // Remove empty blocks in
  • - if (node.nodeName === 'P' && node.parentElement.tagName === 'LI') { - const next = node.nextSibling; - const pnode = node.parentElement; - if (isEmptyBlock(node)) { - const restoreCursor = node.isConnected && preserveCursor(this.root.ownerDocument); - node.remove(); - fillEmpty(pnode); - this._parse(next); + while (node) { + // Merge identical elements together + while ( + areSimilarElements(node, node.previousSibling) && + !isUnbreakable(node) + ) { + getDeepRange(this.root, { select: true }); + const restoreCursor = node.isConnected && + preserveCursor(this.root.ownerDocument); + const nodeP = node.previousSibling; + moveNodes(...endPos(node.previousSibling), node); if (restoreCursor) { - restoreCursor(new Map([[node, pnode]])); - }; - return; + restoreCursor(); + } + node = nodeP; + } + + // Remove zero-width spaces added by `fillEmpty` when there is + // content and the selection is not next to it. + const anchor = this.root.ownerDocument.getSelection().anchorNode; + if ( + node.nodeType === Node.TEXT_NODE && + node.textContent.includes('\u200B') && + ( + node.textContent.length > 1 || + // There can be multiple ajacent text nodes, in which case + // the zero-width space is not needed either, despite being + // alone (length === 1) in its own text node. + Array.from(node.parentNode.childNodes).find( + sibling => + sibling !== node && + sibling.nodeType === Node.TEXT_NODE && + sibling.length > 0 + ) + ) && + !isBlock(node.parentElement) && + anchor !== node + ) { + const restoreCursor = node.isConnected && + preserveCursor(this.root.ownerDocument); + node.textContent = node.textContent.replace('\u200B', ''); + node.parentElement.removeAttribute("data-oe-zws-empty-inline"); + if (restoreCursor) { + restoreCursor(); + } + } + + // Remove empty blocks in
  • + if ( + node.nodeName === 'P' && + node.parentElement.tagName === 'LI' && + isEmptyBlock(node) + ) { + const parent = node.parentElement; + const restoreCursor = node.isConnected && + preserveCursor(this.root.ownerDocument); + node.remove(); + fillEmpty(parent); + if (restoreCursor) { + restoreCursor(new Map([[node, parent]])); + } + } + + // Transform
  • into

    if they are not in a