From dc43b1fd017cda691b4424079c5fc0700fcc393d Mon Sep 17 00:00:00 2001 From: dhba-odoo Date: Fri, 7 Apr 2023 12:51:23 +0530 Subject: [PATCH] [FIX] web_editor: format and style are lost when copy content MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit: Format and style are lost when copying content that has some style or format applied on it. After this commit: Now, able to copy content with its format and style. Task-3263360 closes odoo/odoo#142984 X-original-commit: 8083b990845eeb5b1fa6aaaa21617f16d4d5a780 Signed-off-by: Geelen Sébastien (sge) --- .../js/editor/odoo-editor/src/OdooEditor.js | 13 +++ .../odoo-editor/test/spec/copyPaste.test.js | 82 +++++++++++++++++-- 2 files changed, 87 insertions(+), 8 deletions(-) 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 e177cdd53de..a79334a99b4 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 @@ -3783,6 +3783,19 @@ export class OdooEditor extends EventTarget { rangeContent.lastChild.remove(); } + const commonAncestorElement = closestElement(range.commonAncestorContainer); + if (commonAncestorElement && !isBlock(rangeContent.firstChild)) { + // Get the list of ancestor elements starting from the provided + // commonAncestorElement up to the block-level element. + const blockEl = closestBlock(commonAncestorElement); + const ancestorsList = [commonAncestorElement, ...ancestors(commonAncestorElement, blockEl)]; + // Wrap rangeContent with clones of their ancestors to keep the styles. + for (const ancestor of ancestorsList) { + const clone = ancestor.cloneNode(); + clone.append(...rangeContent.childNodes); + rangeContent.appendChild(clone); + } + } const dataHtmlElement = document.createElement('data'); dataHtmlElement.append(rangeContent); const odooHtml = dataHtmlElement.innerHTML; diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/copyPaste.test.js b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/copyPaste.test.js index 708046c18e0..9cf5a3b4974 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/copyPaste.test.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/copyPaste.test.js @@ -46,8 +46,8 @@ describe('Copy', () => { const clipboardData = new DataTransfer(); await triggerEvent(editor.editable, 'copy', { clipboardData }); window.chai.expect(clipboardData.getData('text/plain')).to.be.equal('bcd'); - window.chai.expect(clipboardData.getData('text/html')).to.be.equal('bcd'); - window.chai.expect(clipboardData.getData('text/odoo-editor')).to.be.equal('bcd'); + window.chai.expect(clipboardData.getData('text/html')).to.be.equal('

bcd

'); + window.chai.expect(clipboardData.getData('text/odoo-editor')).to.be.equal('

bcd

'); }, }); await testEditor(BasicEditor, { @@ -56,8 +56,8 @@ describe('Copy', () => { const clipboardData = new DataTransfer(); await triggerEvent(editor.editable, 'copy', { clipboardData }); window.chai.expect(clipboardData.getData('text/plain')).to.be.equal('abc\nefg'); - window.chai.expect(clipboardData.getData('text/html')).to.be.equal('abc
efg'); - window.chai.expect(clipboardData.getData('text/odoo-editor')).to.be.equal('abc
efg'); + window.chai.expect(clipboardData.getData('text/html')).to.be.equal('

abc
efg

'); + window.chai.expect(clipboardData.getData('text/odoo-editor')).to.be.equal('

abc
efg

'); }, }); await testEditor(BasicEditor, { @@ -71,6 +71,72 @@ describe('Copy', () => { }, }); }); + it('should wrap the selected text with clones of ancestors up to a block element to keep styles', async () => { + await testEditor(BasicEditor, { + contentBefore: '

[Test Test]

', + stepFunction: async editor => { + const clipboardData = new DataTransfer(); + triggerEvent(editor.editable, 'copy', { clipboardData }); + window.chai.expect(clipboardData.getData('text/plain')).to.be.equal('Test Test'); + window.chai.expect(clipboardData.getData('text/html')).to.be.equal('

Test Test

'); + window.chai.expect(clipboardData.getData('text/odoo-editor')).to.be.equal('

Test Test

'); + }, + }); + await testEditor(BasicEditor, { + contentBefore: '

hello [there]

', + stepFunction: async editor => { + const clipboardData = new DataTransfer(); + triggerEvent(editor.editable, 'copy', { clipboardData }); + window.chai.expect(clipboardData.getData('text/plain')).to.be.equal('there'); + window.chai.expect(clipboardData.getData('text/html')).to.be.equal('

there

'); + window.chai.expect(clipboardData.getData('text/odoo-editor')).to.be.equal('

there

'); + }, + }); + }); + it('should copy the selection as a single list item', async () => { + await testEditor(BasicEditor, { + contentBefore: '