Fixed Editor insertSpoiler does not correctly handle formatting

Xon

Well-known member
Affected version
2.2.11
When using the 'insert spoiler' (and bb-code which uses wrapSelectionText) this can result in unexpectedly broken bb-code.

Given this bb-code in the rich-text editor:
line1
[b]line2[/b]
line3
line4

Drag-select line2/line3, and select insert spoiler.

This will result in the following html:
<p>line1</p
<p><strong>[SPOILER="Title"]line2</strong></p>
<p>line3[/SPOILER]</p>
<p>line4</p>

This generates the following bb-code:
line1
[b][SPOILER="Title"]line2[/b]
line3[/SPOILER]
line4

Which is rendered as:
line1
[B][SPOILER="Title"]line2[/SPOILER][/B][SPOILER="Title"]
line3[/SPOILER]
line4


The core of the issue is XF.EditorHelpers.wrapSelectionText needs to be aware of formatting to some degree to avoid the bb-code plain text causing issues when it crosses a <p> tag boundary.
 
Last edited:
@Chris D

The issue ends up being this code;
JavaScript:
var $markers = ed.$el.find('.fr-marker');
$markers.first().before(XF.htmlspecialchars(before));
$markers.last().after(XF.htmlspecialchars(after));
This skips using ed.html.insert which skips a number of auto-formatting bits which are useful for block-bbcode.

This patch appears to fix the above issue.
JavaScript:
XF.EditorHelpers.wrapSelectionText = function (ed, before, after, save, inline) {

        if (save) {
            ed.selection.save();
        }
        ed.undo.saveStep();
        var html, selectedHtml = ed.html.getSelected();

        var $markers = ed.$el.find('.fr-marker');
        var $wrapper = $('<div></div>');
        $wrapper.append($markers.last().get(0));

        html =
            XF.htmlspecialchars(before)
            + selectedHtml
            + $wrapper.html()
            + XF.htmlspecialchars(after)

        if (!inline) {
            html = '<p>' + html + '</p>';
        }
        ed.html.insert(html);

        ed.selection.restore();
        ed.placeholder.hide();
        ed.undo.saveStep();
        XF.EditorHelpers.normalizeAfterInsert(ed);
    }
}
It adds a new "inline" argument which ispoiler/icode should be updated to use. This flag allows block bb-code break out of the existing formatting preventing nested formatting causing issues.

It is inline rather than block as this allows saner defaults for block-like bb-code which are added by 3rd parties.
 
As a note; the above code requires Froala 4.0.14+, as 4.0.10 has a bug where ed.html.getSelected() will grab the entire line instead of just the selected sub-part.
 
Earlier we were running 4.0.15 but it broke iOS.

When I typed my message earlier we were back to running 4.0.10.

We're trying 4.0.14 right now.
 
At worse, you could patch the ed.html.getSelected method.

With 4.0.10; If you select a middle chunk of a line, and then click 'insert code' button in the editor; it would copy the entire line into the code editor dialog.
With 4.0.14; It works as expected.
 
I've had reports ed.html.insert() doesn't function sanely on firefox with Froala v4.0.10 resulting in the original text not being removed. I'll try to troubleshoot it more, but haven't had a chance to test this against v4.0.14

Found the bug: it is present in the [code] block handling already.

Doesn't appear to occur with v4.0.10 however
 
Last edited:
Oops. I missed the ed.selection.isCollapsed() check.

The patch I'm currently using.
JavaScript:
XF.EditorHelpers.wrapSelectionText = function (ed, before, after, save, inline) {

        if (save) {
            ed.selection.save();
        }
        ed.undo.saveStep();

        var $wrapper = $('<div></div>'),
            $markers = ed.$el.find('.fr-marker'),
            selectedHtml = '';
        if (!ed.selection.isCollapsed()) {
            // markers may be touched by getSelected
            $wrapper.append($markers.last().get(0));

            selectedHtml = ed.html.getSelected();
            selectedHtml = selectedHtml + $wrapper.html();
        } else {
            $wrapper.append($markers.first().get(0));
            $wrapper.append($markers.last().get(0));
            selectedHtml = $wrapper.html();
        }

        var html =
            XF.htmlspecialchars(before)
            + selectedHtml
            + XF.htmlspecialchars(after)

        if (!inline) {
            html = '<p>' + html + '</p>';
        }
        ed.html.insert(html);

        ed.selection.restore();
        ed.placeholder.hide();
        ed.undo.saveStep();
        XF.EditorHelpers.normalizeAfterInsert(ed);
    }
};
 
Thank you for reporting this issue, it has now been resolved. We are aiming to include any changes that have been made in a future XF release (2.2.12).

Change log:
Apply recommended fix for wrapping selection text in different editor functionality.
There may be a delay before changes are rolled out to the XenForo Community.
 
Top Bottom