From 8723e1f77b9ab70f98e5bd49f7452adac21ed2df Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Mon, 6 Jul 2015 10:58:05 +0200 Subject: [PATCH] Added support for attachments --- .../js/3rdParty/redactor/plugins/wbbcode.js | 164 +++--------------- .../3rdParty/redactor/plugins/wmonkeypatch.js | 17 +- .../files/js/WoltLab/WCF/BBCode/FromHtml.js | 22 ++- .../files/js/WoltLab/WCF/BBCode/ToHtml.js | 130 +++++++++----- 4 files changed, 127 insertions(+), 206 deletions(-) diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js index 9f9eb20a12..e8a2b8f026 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js @@ -295,78 +295,20 @@ RedactorPlugins.wbbcode = function() { * @param string message */ convertFromHtml: function(message) { - // DEBUG ONLY - return __REDACTOR_AMD_DEPENDENCIES.BBCodeFromHTML.convert(message); + var obj = { html: message }; - var $searchFor = [ ]; + /** @deprecated legacy event */ + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'beforeConvertFromHtml', obj); - WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'beforeConvertFromHtml', { html: html }); + /** @deprecated legacy event */ + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'convertFromHtml', obj); - // remove zero-width space sometimes slipping through - html = html.replace(/&#(8203|x200b);/g, ''); + obj.html = __REDACTOR_AMD_DEPENDENCIES.BBCodeFromHTML.convert(obj.html); - // revert conversion of special characters - html = html.replace(/™/gi, '\u2122'); - html = html.replace(/©/gi, '\u00a9'); - html = html.replace(/…/gi, '\u2026'); - html = html.replace(/—/gi, '\u2014'); - html = html.replace(/‐/gi, '\u2010'); + /** @deprecated legacy event */ + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'afterConvertFromHtml', obj); - // attachments - html = html.replace(/]*?)class="[^"]*redactorEmbeddedAttachment[^"]*"([^>]*?)>/gi, function(match, attributesBefore, attributesAfter) { - var $attributes = attributesBefore + ' ' + attributesAfter; - var $attachmentID; - if ($attributes.match(/data-attachment-id="(\d+)"/)) { - $attachmentID = RegExp.$1; - } - else { - return match; - } - - var $float = 'none'; - var $width = null; - - if ($attributes.match(/style="([^"]+)"/)) { - var $styles = RegExp.$1.split(';'); - - for (var $i = 0; $i < $styles.length; $i++) { - var $style = $.trim($styles[$i]); - if ($style.match(/^float: (left|right)$/)) { - $float = RegExp.$1; - } - else if ($style.match(/^width: (\d+)px$/)) { - $width = RegExp.$1; - } - } - - if ($width !== null) { - return '[attach=' + $attachmentID + ',' + $float + ',' + $width + '][/attach]'; - } - else if ($float !== 'none') { - return '[attach=' + $attachmentID + ',' + $float + '][/attach]'; - } - } - - return '[attach=' + $attachmentID + '][/attach]'; - }); - - WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'convertFromHtml', { html: html }); - - // Remove remaining tags. - html = html.replace(/<[^(<|>)]+>/g, ''); - - // Restore <, > and & - html = html.replace(/</g, '<'); - html = html.replace(/>/g, '>'); - html = html.replace(/&/g, '&'); - - // Restore ( and ) - html = html.replace(/%28/g, '('); - html = html.replace(/%29/g, ')'); - - WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'afterConvertFromHtml', { html: html }); - - return html; + return obj.html; }, /** @@ -375,85 +317,23 @@ RedactorPlugins.wbbcode = function() { * @param string message */ convertToHtml: function(message) { - // DEBUG ONLY - return __REDACTOR_AMD_DEPENDENCIES.BBCodeToHTML.convert(message); + var obj = { data: message }; - WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'beforeConvertToHtml', { data: data }); - - // remove 0x200B (unicode zero width space) - data = this.wutil.removeZeroWidthSpace(data); - - // attachments - var $attachmentUrl = this.wutil.getOption('woltlab.attachmentUrl'); - var $attachmentThumbnailUrl = this.wutil.getOption('woltlab.attachmentThumbnailUrl'); - if ($attachmentUrl) { - var $imageAttachments = this.wbbcode._getImageAttachments(); - - data = data.replace(/\[attach=(\d+)\]\[\/attach\]/g, function(match, attachmentID, alignment) { - attachmentID = parseInt(attachmentID); - - if ($imageAttachments[attachmentID] !== undefined) { - return ''; - } - - return match; - }); - - data = data.replace(/\[attach=(\d+),(left|right|none)\]\[\/attach\]/g, function(match, attachmentID, alignment) { - attachmentID = parseInt(attachmentID); - - if ($imageAttachments[attachmentID] !== undefined) { - var $style = ''; - if (alignment === 'left' || alignment === 'right') { - $style = 'float: ' + alignment + ';'; - - if (alignment === 'left') { - $style += 'margin: 0 15px 7px 0'; - } - else { - $style += 'margin: 0 0 7px 15px'; - } - } - - $style = ' style="' + $style + '"'; - - return ''; - } - - return match; - }); - - data = data.replace(/\[attach=(\d+),(left|right|none),(\d+)\]\[\/attach\]/g, function(match, attachmentID, alignment, width) { - attachmentID = parseInt(attachmentID); - - if ($imageAttachments[attachmentID] !== undefined) { - var $style = 'width: ' + width + 'px; max-height: ' + $imageAttachments[attachmentID].height + 'px; max-width: ' + $imageAttachments[attachmentID].width + 'px;'; - if (alignment === 'left' || alignment === 'right') { - $style += 'float: ' + alignment + ';'; - - if (alignment === 'left') { - $style += 'margin: 0 15px 7px 0'; - } - else { - $style += 'margin: 0 0 7px 15px'; - } - } - - $style = ' style="' + $style + '"'; - - return ''; - } - - return match; - }); - } + /** @deprecated legacy event */ + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'beforeConvertToHtml', obj); - // remove "javascript:" - data = data.replace(/(javascript):/gi, '$1:'); + obj.data = __REDACTOR_AMD_DEPENDENCIES.BBCodeToHTML.convert(obj.data, { + attachments: { + images: this.wbbcode._getImageAttachments(), + thumbnailUrl: this.wutil.getOption('woltlab.attachmentThumbnailUrl'), + url: this.wutil.getOption('woltlab.attachmentUrl') + } + }); - WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'afterConvertToHtml', { data: data }); + /** @deprecated legacy event */ + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'afterConvertToHtml', obj); - return data; + return obj.data; }, /** diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js index d83e38fcd8..7e5c6e2e7d 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js @@ -225,14 +225,9 @@ RedactorPlugins.wmonkeypatch = function() { } } else if (container.nextSibling === container.nextElementSibling) { - console.debug("this!"); if (container.nextElementSibling.nodeName === 'KBD' || container.nextElementSibling.nodeName === 'BR') { setCaretBeforeOrAfter(container, false); } - else { - console.debug(container.nextSibling); - console.debug(container.nextElementSibling); - } } if (container === editor.lastElementChild) { @@ -662,21 +657,12 @@ RedactorPlugins.wmonkeypatch = function() { }).bind(this); // image.update - var $moveImage = (function(image) { - var $parent = image.parent(); - image = image.detach(); - image.prependTo($parent); - - this.caret.setAfter(image); - }).bind(this); - this.image.update = (function(image) { this.image.hideResize(); this.buffer.set(); image.attr('src', $('#redactor-image-link-source').val()); this.image.setFloating(image); - $moveImage(image); var link = $('#redactor-image-link-href').val().trim(); var anchor = image.closest('a', this.$editor[0]); @@ -1113,14 +1099,13 @@ RedactorPlugins.wmonkeypatch = function() { var element = this.selection.getCurrent(); if (element === false) { - console.debug("nope"); return; } if (element.nodeType === Node.TEXT_NODE) { element = element.parentNode; } - console.debug(element); + if (element === this.$editor[0]) { return; } diff --git a/wcfsetup/install/files/js/WoltLab/WCF/BBCode/FromHtml.js b/wcfsetup/install/files/js/WoltLab/WCF/BBCode/FromHtml.js index 71aefab413..f05b2bef0a 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/BBCode/FromHtml.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/BBCode/FromHtml.js @@ -188,15 +188,29 @@ define(['EventHandler', 'StringUtil', 'DOM/Traverse'], function(EventHandler, St if (element.classList.contains('smiley')) { // smiley element.outerHTML = (addSmileyPadding(element, true) ? ' ' : '') + element.getAttribute('alt') + (addSmileyPadding(element, false) ? ' ' : ''); + return; } - else if (element.classList.contains('redactorEmbeddedAttachment')) { - // TODO: handle attachments + + var float = element.style.getPropertyValue('float') || 'none'; + var width = element.style.getPropertyValue('width'); + width = (typeof width === 'string') ? ~~width.replace(/px$/, '') : 0; + + if (element.classList.contains('redactorEmbeddedAttachment')) { + var attachmentId = element.getAttribute('data-attachment-id'); + + if (width > 0) { + element.outerHTML = "[attach=" + attachmentId + "," + float + "," + width + "][/attach]"; + } + else if (float !== 'none') { + element.outerHTML = "[attach=" + attachmentId + "," + float + "][/attach]"; + } + else { + element.outerHTML = "[attach=" + attachmentId + "][/attach]"; + } } else { // regular image - var float = element.style.getPropertyValue('float') || 'none'; var source = element.src.trim(); - var width = ~~element.style.getPropertyValue('width').replace(/px$/, '') || 0; if (width > 0) { element.outerHTML = "[img='" + source + "'," + float + "," + width + "][/img]"; diff --git a/wcfsetup/install/files/js/WoltLab/WCF/BBCode/ToHtml.js b/wcfsetup/install/files/js/WoltLab/WCF/BBCode/ToHtml.js index ab11409b1f..7d7d87af75 100644 --- a/wcfsetup/install/files/js/WoltLab/WCF/BBCode/ToHtml.js +++ b/wcfsetup/install/files/js/WoltLab/WCF/BBCode/ToHtml.js @@ -1,7 +1,8 @@ -define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], function(EventHandler, Language, StringUtil, BBCodeParser) { +define(['Core', 'EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], function(Core, EventHandler, Language, StringUtil, BBCodeParser) { "use strict"; var _bbcodes = null; + var _options = {}; var _removeNewlineAfter = []; var _removeNewlineBefore = []; @@ -10,7 +11,15 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], function isHighlighter(value) { return __REDACTOR_CODE_HIGHLIGHTERS.hasOwnProperty(value); } var BBCodeToHtml = { - convert: function(message) { + convert: function(message, options) { + _options = Core.extend({ + attachments: { + images: {}, + thumbnailUrl: '', + url: '' + } + }, options); + this._convertSpecials(message); var stack = BBCodeParser.parse(message); @@ -19,12 +28,19 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], this._initBBCodes(); } - var item; + var item, value; for (var i = 0, length = stack.length; i < length; i++) { item = stack[i]; if (typeof item === 'object') { - stack[i] = this._replace(stack, item, i); + value = this._replace(stack, item, i); + if (Array.isArray(value)) { + stack[i] = (value[0] === null ? item.source : value[0]); + stack[item.pair] = (value[1] === null ? stack[item.pair].source : value[1]); + } + else { + stack[i] = value; + } } } @@ -62,6 +78,7 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], tt: 'kbd', // callback replacement + attach: this._replaceAttachment.bind(this), color: this._replaceColor.bind(this), code: this._replaceCode.bind(this), email: this._replaceEmail.bind(this), @@ -86,11 +103,7 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], if (replace === undefined) { // treat as plain text - console.debug(item); - console.debug(stack); - stack[item.pair] = stack[item.pair].source; - - return item.source; + return [null, null]; } if (_removeNewlineAfter.indexOf(item.name) !== -1) { @@ -125,15 +138,57 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], this._replaceSmilies(stack); if (typeof replace === 'string') { - stack[item.pair] = ''; - - return '<' + replace + '>'; + return ['<' + replace + '>', '']; } else { return replace(stack, item, index); } }, + _replaceAttachment: function(stack, item, index) { + var attachmentId = 0, attributes = item.attributes, length = attributes.length; + if (!_options.attachments.url) { + length = 0; + } + else if (length > 0) { + attachmentId = ~~attributes[0]; + if (!_options.attachments.images.hasOwnProperty(attachmentId)) { + length = 0; + } + } + + if (length === 0) { + return [null, null]; + } + + var maxHeight = ~~_options.attachments.images[attachmentId].height; + var maxWidth = ~~_options.attachments.images[attachmentId].width; + var styles = ['max-height: ' + maxHeight + 'px', 'max-width: ' + maxWidth + 'px']; + + if (length > 1) { + if (item.attributes[1] === 'left' || attributes[1] === 'right') { + styles.push('float: ' + attributes[1]); + styles.push('margin: ' + (attributes[1] === 'left' ? '0 15px 7px 0' : '0 0 7px 15px')); + } + } + + var baseUrl = _options.attachments.thumbnailUrl; + if (length > 2) { + width = ~~attributes[2] || 0; + if (width) { + if (width > maxWidth) width = maxWidth; + + styles.push('width: ' + width + 'px'); + baseUrl = _options.attachments.url; + } + } + + return [ + '', + '' + ]; + }, + _replaceCode: function(stack, item, index) { var attributes = item.attributes, filename = '', highlighter = 'auto', lineNumber = 0; @@ -206,26 +261,23 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], } } - stack[item.pair] = ''; - - return '
' + return [ + '
' + '
' + '
' + '

' + __REDACTOR_CODE_HIGHLIGHTERS[highlighter] + (filename ? ': ' + StringUtil.escapeHTML(filename) : '') + '

' + '
' - + '
    '; + + '
      ', + '
' + ]; }, _replaceColor: function(stack, item, index) { if (!item.attributes.length || !item.attributes[0].match(/^[a-z0-9#]+$/i)) { - stack[item.pair] = ''; - - return ''; + return [null, null]; } - stack[item.pair] = ''; - - return ''; + return ['', '']; }, _replaceEmail: function(stack, item, index) { @@ -249,20 +301,14 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], // no attribute present and element is empty, handle as plain text if (email.trim() === '') { - stack[item.pair] = stack[item.pair].source; - - return item.source; + return [null, null]; } } - stack[item.pair] = ''; - - return ''; + return ['', '']; }, _replaceImage: function(stack, item, index) { - stack[item.pair] = ''; - var float = 'none', source = '', width = 0; switch (item.attributes.length) { @@ -305,7 +351,7 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], styles.push('margin: ' + (float === 'left' ? '0 15px 7px 0' : '0 0 7px 15px')); } - return ''; + return ['', '']; }, _replaceList: function(stack, item, index) { @@ -319,17 +365,14 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], } if (type == '1' || type === 'decimal') { - stack[item.pair] = ''; - - return '
    '; + return ['
      ', '
    ']; } - stack[item.pair] = ''; if (type.length && type.match(/^(?:none|circle|square|disc|decimal|lower-roman|upper-roman|decimal-leading-zero|lower-greek|lower-latin|upper-latin|armenian|georgian)$/)) { - return '
      '; + return ['
        ', '
      ']; } - return '
        '; + return ['
          ', '
        ']; }, _replaceQuote: function(stack, item, index) { @@ -342,8 +385,6 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], author = item.attributes[0]; } - stack[item.pair] = '
'; - // get rid of the trailing newline for quote content for (var i = item.pair - 1; i > index; i--) { if (typeof stack[i] === 'string') { @@ -362,14 +403,17 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], header = '' + Language.get('wcf.bbcode.quote.title.clickToSet') + ''; } - return '
' + return [ + '
' + '
' + '

' + header + '

' + '' + '
' - + '
\u200b'; + + '
\u200b', + '
' + ]; }, _replaceSmilies: function(stack) { @@ -403,9 +447,7 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'], return ''; } - stack[item.pair] = ''; - - return ''; + return ['', '']; } }; -- 2.20.1