From: Alexander Ebert Date: Sun, 24 Mar 2019 12:30:59 +0000 (+0100) Subject: New handling of empty lines when removing text formatting X-Git-Tag: 3.1.9~14 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=e2860f350d239daa331b066b4117a299443c34e1;p=GitHub%2FWoltLab%2FWCF.git New handling of empty lines when removing text formatting --- diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/Format.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/Format.js index 31fa3e3a04..74d9b8540f 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/Format.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/Format.js @@ -230,6 +230,53 @@ define(['Dom/Util'], function(DomUtil) { return; } + // Removing a span from an empty selection in an empty line containing a `
` causes a selection + // shift where the caret is moved into the span again. Unlike inline changes to the formatting, any + // removal of the format in an empty line should remove it from its entirely, instead of just around + // the caret position. + var range = selection.getRangeAt(0); + if (range.collapsed) { + var container = range.startContainer; + var tree = [container]; + while (true) { + var parent = container.parentNode; + if (parent === editorElement || parent.nodeName === 'TD') { + break; + } + + container = parent; + tree.push(container); + } + + if (this._isEmpty(container.innerHTML)) { + var marker = document.createElement('woltlab-format-marker'); + range.insertNode(marker); + + // Find the offending span and remove it entirely. + tree.forEach(function (element) { + if (element.nodeName === 'SPAN') { + if (element.style.getPropertyValue(property)) { + DomUtil.unwrapChildNodes(element); + } + } + }); + + // Firefox messes up the selection if the ancestor element was removed and there is + // an adjacent `
` present. Instead of keeping the caret in front of the
, it + // is implicitly moved behind it. + range = document.createRange(); + range.selectNode(marker); + range.collapse(true); + + selection.removeAllRanges(); + selection.addRange(range); + + elRemove(marker); + + return; + } + } + var strikeElements = elByTag('strike', editorElement); // remove any element first, all though there shouldn't be any at all @@ -421,6 +468,29 @@ define(['Dom/Util'], function(DomUtil) { } return [tag.toLowerCase(), tag.toLowerCase() + 'script']; + }, + + /** + * Slightly modified version of Redactor's `utils.isEmpty()`. + * + * @param {string} html + * @returns {boolean} + * @protected + */ + _isEmpty: function(html) { + html = html.replace(/[\u200B-\u200D\uFEFF]/g, ''); + html = html.replace(/ /gi, ''); + html = html.replace(/<\/?br\s?\/?>/g, ''); + html = html.replace(/\s/g, ''); + html = html.replace(/^

[^\W\w\D\d]*?<\/p>$/i, ''); + html = html.replace(/])>$/i, 'iframe'); + html = html.replace(/])>$/i, 'source'); + + // remove empty tags + html = html.replace(/<[^\/>][^>]*><\/[^>]+>/gi, ''); + html = html.replace(/<[^\/>][^>]*><\/[^>]+>/gi, ''); + + return html.trim() === ''; } }; });