From 0d77895b098a8dade0faa87f0e1fc6a99e3674b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Geelen=20=28sge=29?= Date: Thu, 9 Jun 2022 12:54:06 +0000 Subject: [PATCH] [FIX] web_editor: inlines should be pasted inside container During paste HTML, an inline element or a textNode should never be inserted outside of the targeted initial container. Those kind of orphans elements should never be present in an HTML paste data, but better safe than sorry. Part-of: odoo/odoo#95347 # Conflicts: # addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js Part-of: odoo/odoo#95445 --- .../js/editor/odoo-editor/src/OdooEditor.js | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js index 33efa429900..502e475c4a5 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js @@ -55,6 +55,7 @@ import { getAdjacentPreviousSiblings, getAdjacentNextSiblings, rightLeafOnlyNotBlockPath, + isBlock, } from './utils/utils.js'; import { editorCommands } from './commands/commands.js'; import { Powerbox } from './powerbox/Powerbox.js'; @@ -2198,7 +2199,31 @@ export class OdooEditor extends EventTarget { for (const child of [...container.childNodes]) { this._cleanForPaste(child); } - return container.innerHTML; + // Force inline nodes at the root of the container into separate P + // elements. This is a tradeoff to ensure some features that rely on + // nodes having a parent (e.g. convert to list, title, etc.) can work + // properly on such nodes without having to actually handle that + // particular case in all of those functions. In fact, this case cannot + // happen on a new document created using this editor, but will happen + // instantly when editing a document that was created from Etherpad. + const temporaryContainer = document.createElement('template'); + let temporaryP = document.createElement('p'); + for (const child of [...container.childNodes]) { + if (isBlock(child)) { + if (temporaryP.childNodes.length > 0) { + temporaryContainer.content.appendChild(temporaryP); + temporaryP = document.createElement('p'); + } + temporaryContainer.content.appendChild(child); + } else { + temporaryP.appendChild(child); + } + + if (temporaryP.childNodes.length > 0) { + temporaryContainer.content.appendChild(temporaryP); + } + } + return temporaryContainer.innerHTML; } /** * Clean a node for safely pasting. Cleaning an element involves unwrapping