From: Alexander Ebert Date: Sun, 14 Sep 2014 00:44:51 +0000 (+0200) Subject: Improved editor handling of BBCode <-> HTML X-Git-Tag: 2.1.0_Alpha_1~344^2~14 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=262f60834adc08347b407a5fabd00fcdc0732010;p=GitHub%2FWoltLab%2FWCF.git Improved editor handling of BBCode <-> HTML --- diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js index 44f037c4b1..91c7268c5d 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js @@ -8,8 +8,6 @@ if (!RedactorPlugins) var RedactorPlugins = {}; * @license GNU Lesser General Public License */ RedactorPlugins.wbbcode = { - wBlockTest: /^(BLOCKQUOTE|DIV)$/, - /** * Initializes the RedactorPlugins.wbbcode plugin. */ @@ -151,14 +149,13 @@ RedactorPlugins.wbbcode = { if (this.opts.visual) { this.sync(undefined, true); this.toggleCode(direct); - this._convertFromHtml(); + this.$source.val(this.convertFromHtml(this.$source.val())); this.buttonGet('html').children('i').removeClass('fa-square-o').addClass('fa-square'); } else { - this._convertToHtml(); + this.$source.val(this.convertToHtml(this.$source.val())); this.toggleVisual(); - this.fixQuoteContent(); this._observeQuotes(); this.buttonGet('html').children('i').removeClass('fa-square').addClass('fa-square-o'); @@ -167,10 +164,10 @@ RedactorPlugins.wbbcode = { /** * Converts source contents from HTML into BBCode. + * + * @param string html */ - _convertFromHtml: function() { - var html = this.$source.val(); - + convertFromHtml: function(html) { WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'beforeConvertFromHtml', { html: html }); // revert conversion of special characters @@ -464,15 +461,19 @@ RedactorPlugins.wbbcode = { } } - this.$source.val(html); + // remove all leading and trailing whitespaces, but add one empty line at the end + html = $.trim(html); + html += "\n"; + + return html; }, /** * Converts source contents from BBCode to HTML. + * + * @param string data */ - _convertToHtml: function() { - var data = this.$source.val(); - + convertToHtml: function(data) { WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'beforeConvertToHtml', { data: data }); // remove 0x200B (unicode zero width space) @@ -661,96 +662,78 @@ RedactorPlugins.wbbcode = { // insert quotes if ($.getLength($cachedQuotes)) { // [quote] - for (var $key in $cachedQuotes) { - var $regex = new RegExp('@@' + $key + '@@', 'g'); - data = data.replace($regex, this.transformQuote($cachedQuotes[$key])); - } - } - - WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'afterConvertToHtml', { data: data }); - - this.$source.val(data); - }, - - unquoteString: function(quotedString) { - return quotedString.replace(/^['"]/, '').replace(/['"]$/, ''); - }, - - transformQuote: function(quote) { - var self = this; - quote = quote.replace(/\[quote([^\]]+)?\]/gi, function(match, attributes, innerContent) { - var $author = ''; - var $link = ''; + var $unquoteString = function(quotedString) { + return quotedString.replace(/^['"]/, '').replace(/['"]$/, ''); + }; - if (attributes) { - attributes = attributes.substr(1); - attributes = attributes.split(','); - - switch (attributes.length) { - case 1: - $author = attributes[0]; - break; + var self = this; + var $transformQuote = function(quote) { + return quote.replace(/\[quote([^\]]+)?\]([\S\s]*)\[\/quote\]?/gi, $.proxy(function(match, attributes, innerContent) { + var $author = ''; + var $link = ''; - case 2: - $author = attributes[0]; - $link = attributes[1]; - break; - } - - $author = WCF.String.escapeHTML(self.unquoteString($.trim($author))); - $link = WCF.String.escapeHTML(self.unquoteString($.trim($link))); - } - - var $quote = '
' - + '
' - + '
' - + '

' - + self._buildQuoteHeader($author, $link) - + '

' - + '' - + '
' - + '
'; - - return $quote; - }); - - return quote.replace(/\[\/quote\]/gi, '
'); - }, - - /** - * Fixes quote content by converting newlines into own paragraphs. - */ - fixQuoteContent: function() { - var $count = this.$editor.find('.redactorQuoteContent').length; - var self = this; - while ($count > 0) { - var $content = this.$editor.find('.redactorQuoteContent:eq(0)').removeClass('redactorQuoteContent'); - $content.contents().each(function(index, node) { - if (node.nodeType === Element.ELEMENT_NODE) { - if (self.opts.rBlockTest.test(this.tagName) || self.wBlockTest.test(this.tagName)) { - $(node).wrap('
'); + if (attributes) { + attributes = attributes.substr(1); + attributes = attributes.split(','); + + switch (attributes.length) { + case 1: + $author = attributes[0]; + break; + + case 2: + $author = attributes[0]; + $link = attributes[1]; + break; + } + + $author = WCF.String.escapeHTML($unquoteString($.trim($author))); + $link = WCF.String.escapeHTML($unquoteString($.trim($link))); } - } - else if (node.nodeType === Element.TEXT_NODE) { - var $node = $(node); - // split text nodes - var $parts = node.nodeValue.split(/\n/); - for (var $i = 0; $i < $parts.length; $i++) { - var $part = $.trim($parts[$i]); - if (!$part.length) { - $part = self.opts.invisibleSpace; + var $quote = '
' + + '
' + + '
' + + '

' + + self._buildQuoteHeader($author, $link) + + '

' + + '' + + '
'; + + innerContent = $.trim(innerContent); + var $tmp = ''; + + if (innerContent.length) { + var $lines = innerContent.split('\n'); + for (var $i = 0; $i < $lines.length; $i++) { + var $line = $lines[$i]; + if ($line.length === 0) { + $line = self.opts.invisibleSpace; + } + + $tmp += '
' + $line + '
'; } - - $('
' + $part + '
').insertAfter($node); + } + else { + $tmp = '
' + self.opts.invisibleSpace + '
'; } - $node.remove(); - } - }); + $quote += $tmp; + $quote += '
'; + + return $quote; + }, this)); + }; - $count--; + for (var $key in $cachedQuotes) { + var $regex = new RegExp('@@' + $key + '@@', 'g'); + data = data.replace($regex, $transformQuote($cachedQuotes[$key])); + } } + + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'afterConvertToHtml', { data: data }); + + return data; }, /** @@ -1046,8 +1029,21 @@ RedactorPlugins.wbbcode = { * @param string plainText */ insertQuoteBBCode: function(author, link, html, plainText) { + var $bbcode = '[quote]'; + if (author) { + if (link) { + $bbcode = "[quote='" + author + "','" + link + "']"; + } + else { + $bbcode = "[quote='" + author + "']"; + } + } + + if (plainText) $bbcode += plainText; + $bbcode += '[/quote]'; + if (this.inWysiwygMode()) { - var $html = '
' + /*var $html = '
' + '
' + '
' + '

' @@ -1064,25 +1060,16 @@ RedactorPlugins.wbbcode = { var $container = $('
' + (html ? html : this.opts.invisibleSpace) + '
').insertAfter($quote.find('> div > header')); $quote.removeAttr('id'); - this.selectionStart($container[0]); + this.selectionStart($container[0]);*/ + + $bbcode = this.convertToHtml($bbcode); + this.insertHtml($bbcode); + this._observeQuotes(); this.$toolbar.find('a.re-__wcf_quote').addClass('redactor_button_disabled'); } else { - var $bbcode = '[quote]'; - if (author) { - if (link) { - $bbcode = "[quote='" + author + "','" + link + "']"; - } - else { - $bbcode = "[quote='" + author + "']"; - } - } - - if (plainText) $bbcode += plainText; - $bbcode += '[/quote]'; - this.insertAtCaret($bbcode); } }, diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js index 45f9c47b39..f72b91d6df 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js @@ -538,4 +538,14 @@ RedactorPlugins.wmonkeypatch = { cleanGetTabs: function() { return ''; }, + + /** + * Overwrites $.Redactor.cleanRemoveEmptyTags() to prevent empty tags being discarded, they + * are required to properly transform HTML -> BBCode. + * + * @see $.Redactor.cleanRemoveEmptyTags() + */ + cleanRemoveEmptyTags: function(html) { + return html; + } }; diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js index aaab56e5c6..726a90fb9a 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js @@ -302,8 +302,7 @@ RedactorPlugins.wutil = { */ wSync: function() { this.sync(undefined, true); - this.$source.val(this.cleanHtml(this.$source.val())); - this._convertFromHtml(); + this.$source.val(this.convertFromHtml(this.cleanHtml(this.$source.val()))); }, /** diff --git a/wcfsetup/install/files/js/WCF.Message.js b/wcfsetup/install/files/js/WCF.Message.js index fd6119cfd5..ee9f03c7de 100644 --- a/wcfsetup/install/files/js/WCF.Message.js +++ b/wcfsetup/install/files/js/WCF.Message.js @@ -2711,10 +2711,10 @@ WCF.Message.Quote.Manager = Class.extend({ // insert into editor if ($.browser.redactor) { if (this._editorElementAlternative === null) { - this._editorElement.redactor('insertQuoteBBCode', $message.attr('data-username'), $message.data('link'), $quote, $quote);// $quote); + this._editorElement.redactor('insertQuoteBBCode', $message.attr('data-username'), $message.data('link'), $quote, $quote); } else { - this._editorElementAlternative.redactor('insertQuoteBBCode', $message.attr('data-username'), $message.data('link'), $quote, $quote);// $quote); + this._editorElementAlternative.redactor('insertQuoteBBCode', $message.attr('data-username'), $message.data('link'), $quote, $quote); } } else {