From 061afc8fbb88b8d74be9ebdae18d5e379dd87696 Mon Sep 17 00:00:00 2001 From: Damien Pobel Date: Fri, 7 Oct 2016 10:45:50 +0200 Subject: [PATCH] Fix EZP-26135: Line breaks added in richtext editor when editing content twice --- .../js/views/fields/ez-richtext-editview.js | 38 ++++++++++++++++--- .../assets/ez-richtext-editview-tests.js | 34 ++++++++++++++++- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/Resources/public/js/views/fields/ez-richtext-editview.js b/Resources/public/js/views/fields/ez-richtext-editview.js index b234f2175..ac7a52fab 100644 --- a/Resources/public/js/views/fields/ez-richtext-editview.js +++ b/Resources/public/js/views/fields/ez-richtext-editview.js @@ -266,10 +266,37 @@ YUI.add('ez-richtext-editview', function (Y) { * @return {DocumentFragment} */ _getHTMLDocumentFragment: function () { - var fragment = Y.config.doc.createDocumentFragment(), - root = Y.config.doc.createElement('div'), + var fragment = Y.config.doc.implementation.createHTMLDocument().createDocumentFragment(), + root = fragment.ownerDocument.createElement('div'), doc = (new DOMParser()).parseFromString(this.get('field').fieldValue.xhtml5edit, "text/xml"), - i; + importChildNodes = function (parent, element, skipElement) { + // recursively import element and its descendants under + // parent this allows to correctly transform an `xhtml5edit` + // document (it's an XML document) to an HTML document a + // browser can understand. + var i, newElement; + + if ( skipElement ) { + newElement = parent; + } else { + if ( element.nodeType === Node.ELEMENT_NODE ) { + newElement = parent.ownerDocument.createElement(element.localName); + for (i = 0; i != element.attributes.length; i++) { + importChildNodes(newElement, element.attributes[i], false); + } + parent.appendChild(newElement); + } else if ( element.nodeType === Node.TEXT_NODE ) { + parent.appendChild(parent.ownerDocument.createTextNode(element.nodeValue)); + } else if ( element.nodeType === Node.ATTRIBUTE_NODE ) { + parent.setAttribute(element.localName, element.value); + } else { + return; + } + } + for (i = 0; i != element.childNodes.length; i++) { + importChildNodes(newElement, element.childNodes[i], false); + } + }; if ( !doc || !doc.documentElement || doc.querySelector("parsererror") ) { console.warn( @@ -279,9 +306,8 @@ YUI.add('ez-richtext-editview', function (Y) { } fragment.appendChild(root); - for (i = 0; i != doc.documentElement.childNodes.length; i++) { - root.appendChild(doc.documentElement.childNodes.item(i).cloneNode(true)); - } + + importChildNodes(root, doc.documentElement, true); return fragment; }, diff --git a/Tests/js/views/fields/assets/ez-richtext-editview-tests.js b/Tests/js/views/fields/assets/ez-richtext-editview-tests.js index 23d6f1506..3911cfabc 100644 --- a/Tests/js/views/fields/assets/ez-richtext-editview-tests.js +++ b/Tests/js/views/fields/assets/ez-richtext-editview-tests.js @@ -8,7 +8,8 @@ YUI.add('ez-richtext-editview-tests', function (Y) { editorTest, rerenderEditorTest, focusModeTest, editorFocusHandlingTest, appendToolbarConfigTest, eventForwardTest, defaultEditorProcessorsTest, defaultProcessorsTest, VALID_XHTML, INVALID_XHTML, RESULT_XHTML, EMPTY_XHTML, RESULT_EMPTY_XHTML, - VALID_XHTML_WITH_EMBED, + VALID_XHTML_WITH_EMBED, VALID_XHTML_BR, RESULT_BR_XHTML, VALID_XHTML_COMPLEX, + RESULT_COMPLEX_XHTML, Assert = Y.Assert, Mock = Y.Mock, destroyTearDown = function () { // setTimeout is needed otherwise, the editor is destroyed while @@ -27,6 +28,17 @@ YUI.add('ez-richtext-editview-tests', function (Y) { VALID_XHTML += '
'; VALID_XHTML += '

I\'m not empty

'; + VALID_XHTML_BR = ''; + VALID_XHTML_BR += '
'; + VALID_XHTML_BR += '

Line
Breaks
Line
Breaks

'; + + VALID_XHTML_COMPLEX = ''; + VALID_XHTML_COMPLEX += '
'; + VALID_XHTML_COMPLEX += ''; + VALID_XHTML_COMPLEX += '

With
breaks

'; + VALID_XHTML_COMPLEX += '
'; + VALID_XHTML_COMPLEX += '
'; + VALID_XHTML_WITH_EMBED = ''; VALID_XHTML_WITH_EMBED += '
'; VALID_XHTML_WITH_EMBED += '
'; @@ -36,6 +48,12 @@ YUI.add('ez-richtext-editview-tests', function (Y) { RESULT_EMPTY_XHTML = '

'; + RESULT_BR_XHTML = '

Line
Breaks
Line
Breaks

'; + + RESULT_COMPLEX_XHTML = ''; + RESULT_COMPLEX_XHTML += '

With
breaks

'; + RESULT_COMPLEX_XHTML += '
'; + RESULT_XHTML = '

I\'m not empty

'; CKEDITOR.plugins.add('ezaddcontent', {}); @@ -126,7 +144,10 @@ YUI.add('ez-richtext-editview-tests', function (Y) { "The editable class should be available in the template" ); Assert.areSame(expectRequired, variables.isRequired); - Assert.areSame(expectedXhtml, variables.xhtml); + Assert.areSame( + expectedXhtml, variables.xhtml, + "The HTML code should be available in the template" + ); return origTpl.call(this, variables); }; @@ -148,6 +169,15 @@ YUI.add('ez-richtext-editview-tests', function (Y) { "Should add a paragraph in empty document": function () { this._testAvailableVariables(false, false, EMPTY_XHTML, RESULT_EMPTY_XHTML); }, + + "Should transform the xhtml5edit code to HTML": function () { + this._testAvailableVariables(false, false, VALID_XHTML_COMPLEX, RESULT_COMPLEX_XHTML); + }, + + // regression test for EZP-26135 + "Should not double the br tag": function () { + this._testAvailableVariables(false, false, VALID_XHTML_BR, RESULT_BR_XHTML); + }, }); validateTest = new Y.Test.Case({