From c368667ad5d50306eadfcc19e91072b5cf9ffb0b Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 1 Mar 2023 15:01:21 +0000 Subject: [PATCH] Fix first/last pasted BBCode blocks being removed (#927) When pasting in BBCode format, the first and last blocks were sometimes being removed, such as: [center]test[/center][center]test[/center][center]test[/center] This also caused extra newlines to sometimes be added when pasting. --- src/formats/bbcode.js | 64 +++++------------------------------- src/lib/SCEditor.js | 2 ++ tests/unit/formats/bbcode.js | 51 +++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 57 deletions(-) diff --git a/src/formats/bbcode.js b/src/formats/bbcode.js index 24c5e278..4a25c2f5 100644 --- a/src/formats/bbcode.js +++ b/src/formats/bbcode.js @@ -854,57 +854,6 @@ }); } - /** - * Removes the first and last divs from the HTML. - * - * This is needed for pasting - * @param {string} html - * @return {string} - * @private - */ - function removeFirstLastDiv(html) { - var node, next, removeDiv, - output = document.createElement('div'); - - removeDiv = function (node, isFirst) { - // Don't remove divs that have styling - if (dom.hasStyling(node)) { - return; - } - - if ((node.childNodes.length !== 1 || - !is(node.firstChild, 'br'))) { - while ((next = node.firstChild)) { - output.insertBefore(next, node); - } - } - - if (isFirst) { - var lastChild = output.lastChild; - - if (node !== lastChild && is(lastChild, 'div') && - node.nextSibling === lastChild) { - output.insertBefore(document.createElement('br'), node); - } - } - - output.removeChild(node); - }; - - css(output, 'display', 'none'); - output.innerHTML = html.replace(/<\/div>\n/g, ''); - - if ((node = output.firstChild) && is(node, 'div')) { - removeDiv(node, true); - } - - if ((node = output.lastChild) && is(node, 'div')) { - removeDiv(node); - } - - return output.innerHTML; - } - function isFunction(fn) { return typeof fn === 'function'; } @@ -1794,6 +1743,10 @@ return convertToHTML(base.parse(str, preserveNewLines), true); }; + base.toHTMLFragment = function (str, preserveNewLines) { + return convertToHTML(base.parse(str, preserveNewLines), false); + }; + /** * @private */ @@ -2542,12 +2495,11 @@ */ function toHtml(asFragment, source, legacyAsFragment) { var parser = new BBCodeParser(base.opts.parserOptions); - var html = parser.toHTML( - base.opts.bbcodeTrim ? source.trim() : source - ); + var toHTML = (asFragment || legacyAsFragment) ? + parser.toHTMLFragment : + parser.toHTML; - return (asFragment || legacyAsFragment) ? - removeFirstLastDiv(html) : html; + return toHTML(base.opts.bbcodeTrim ? source.trim() : source); } /** diff --git a/src/lib/SCEditor.js b/src/lib/SCEditor.js index 3b1ac1b2..875ef185 100644 --- a/src/lib/SCEditor.js +++ b/src/lib/SCEditor.js @@ -1732,6 +1732,8 @@ export default function SCEditor(original, userOptions) { // into a paragraph dom.fixNesting(wysiwygBody); + wrapInlines(wysiwygBody, wysiwygDocument); + // Scroll the editor after the end of the selection marker = dom.find(wysiwygBody, '#sceditor-end-marker')[0]; dom.show(marker); diff --git a/tests/unit/formats/bbcode.js b/tests/unit/formats/bbcode.js index 04ff1c3c..b382d899 100644 --- a/tests/unit/formats/bbcode.js +++ b/tests/unit/formats/bbcode.js @@ -39,7 +39,56 @@ QUnit.test('From BBCode method as fragment', function (assert) { assert.htmlEqual( this.mockEditor.fromBBCode('[b]test[/b]', true), 'test', - 'As fragment' + 'Should not wrap fragments in blocks' + ); + + assert.htmlEqual( + this.mockEditor.fromBBCode( + 'line1[b]test[/b][center]line2[/center]line3[b]test[/b]', + true + ), + 'line1test' + + '
line2
' + + 'line3test', + 'Should not wrap inlines with a block in between' + ); + + assert.htmlEqual( + this.mockEditor.fromBBCode( + '\n\n', + true + ), + '

', + 'Should preserve newlines' + ); + + assert.htmlEqual( + this.mockEditor.fromBBCode( + '[none]test[/none]', + true + ), + '[none]test[/none]', + 'Should not alter nonexistent BBCodes' + ); + + assert.htmlEqual( + this.mockEditor.fromBBCode( + '[center]line1[/center][center]line2[/center][center]line3[/center]', + true + ), + '
line1
' + + '
line2
' + + '
line3
', + 'Should keep all styled blocks created by a BBCode' + ); + + assert.htmlEqual( + this.mockEditor.fromBBCode( + '\nline2\n', + true + ), + '
line2
', + 'Should not wrap newlines' ); });