Added support for images (embedded attachments missing for now)
authorAlexander Ebert <ebert@woltlab.com>
Fri, 3 Jul 2015 10:56:51 +0000 (12:56 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 3 Jul 2015 10:56:51 +0000 (12:56 +0200)
com.woltlab.wcf/templates/wysiwyg.tpl
wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js
wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js
wcfsetup/install/files/js/WoltLab/WCF/BBCode/FromHtml.js
wcfsetup/install/files/js/WoltLab/WCF/BBCode/Parser.js
wcfsetup/install/files/js/WoltLab/WCF/BBCode/ToHtml.js
wcfsetup/install/files/lib/system/bbcode/BBCodeHandler.class.php
wcfsetup/install/files/style/redactor.less

index c8f1477baee654eee70c815724b387d6ece0e0c5..b270eaac26c80d984c0743230909500e754c8b59 100644 (file)
@@ -2,6 +2,7 @@
 var __REDACTOR_ICON_PATH = '{@$__wcf->getPath()}icon/';
 var __REDACTOR_BUTTONS = [ {implode from=$__wcf->getBBCodeHandler()->getButtonBBCodes() item=__bbcode}{ icon: '{$__bbcode->wysiwygIcon}', label: '{$__bbcode->buttonLabel|language}', name: '{$__bbcode->bbcodeTag}' }{/implode} ];
 var __REDACTOR_SMILIES = { {implode from=$__wcf->getSmileyCache()->getCategorySmilies() item=smiley}'{@$smiley->smileyCode|encodeJS}': '{@$smiley->getURL()|encodeJS}'{/implode} };
+var __REDACTOR_BBCODES = [ {implode from=$__wcf->getBBCodeHandler()->getBBCodes() item=__bbcode}'{@$__bbcode->bbcodeTag}'{/implode} ];
 var __REDACTOR_SOURCE_BBCODES = [ {implode from=$__wcf->getBBCodeHandler()->getSourceBBCodes() item=__bbcode}'{@$__bbcode->bbcodeTag}'{/implode} ];
 var __REDACTOR_CODE_HIGHLIGHTERS = { {implode from=$__wcf->getBBCodeHandler()->getHighlighters() item=__highlighter}'{@$__highlighter}': '{lang}wcf.bbcode.code.{@$__highlighter}.title{/lang}'{/implode} };
 var __REDACTOR_AMD_DEPENDENCIES = { };
index ea74dff77298771a87717423ed4bccf90eaf2d2f..19640e5f828e5e0f9e42906b16c2d21da8a2246e 100644 (file)
@@ -302,12 +302,6 @@ RedactorPlugins.wbbcode = function() {
                        
                        WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'beforeConvertFromHtml', { html: html });
                        
-                       // remove data-redactor-tag="" attribute
-                       html = html.replace(/(<[^>]+?) data-redactor-tag="[^"]+"/g, '$1');
-                       
-                       // remove rel="" attribute
-                       html = html.replace(/(<[^>]+?) rel="[^"]+"/g, '$1');
-                       
                        // remove zero-width space sometimes slipping through
                        html = html.replace(/&#(8203|x200b);/g, '');
                        
@@ -318,78 +312,6 @@ RedactorPlugins.wbbcode = function() {
                        html = html.replace(/&mdash;/gi, '\u2014');
                        html = html.replace(/&dash;/gi, '\u2010');
                        
-                       // preserve code listings
-                       var $cachedCodeListings = { };
-                       html = html.replace(/<div([^>]+?)class="codeBox[^"]+"([^>]*?)>\n*<div>[\s\S]+?<ol start="(\d+)">([\s\S]+?)<\/ol>\n*<\/div>\n*<\/div>/g, function(match, codeBoxAttributes1, codeBoxAttributes2, lineNumber, codeContent) {
-                               var $attributes = codeBoxAttributes1 + ' ' + codeBoxAttributes2;
-                               var $highlighter = '';
-                               var $filename = '';
-                               if ($attributes.match(/data-highlighter="([a-zA-Z]+)"/)) {
-                                       $highlighter = RegExp.$1;
-                               }
-                               if ($attributes.match(/data-filename="([^"]+)"/)) {
-                                       $filename = $.trim(RegExp.$1);
-                               }
-                               
-                               var $uuid = WCF.getUUID();
-                               $cachedCodeListings[$uuid] = {
-                                       codeContent: codeContent.replace(/<li>/g, '').replace(/<\/li>/g, '\n').replace(/\n$/, ''),
-                                       filename: $filename.replace(/['"]/g, ''),
-                                       highlighter: ($highlighter === 'plain' ? '' : $highlighter),
-                                       lineNumber: (lineNumber > 1 ? lineNumber : 0)
-                               };
-                               
-                               return '@@@' + $uuid + '@@@';
-                       });
-                       
-                       // unwrap code boxes
-                       for (var $uuid in $cachedCodeListings) {
-                               html = html.replace(new RegExp('<p><\/p>@@@' + $uuid + '@@@<p><\/p>'), '@@@' + $uuid + '@@@');
-                       }
-                       
-                       // handle empty paragraphs not followed by an empty one
-                       html = html.replace(/<p><\/p><p>(?!<br>)/g, '<p>@@@wcf_empty_line@@@</p><p>');
-                       
-                       html = html.replace(/@@@wcf_empty_line@@@/g, '\n');
-                       html = html.replace(/\n\n$/, '\n');
-                       
-                       
-                       // drop <br>, they are pointless because the editor already adds a newline after them
-                       html = html.replace(/<br>/g, '');
-                       html = html.replace(/&nbsp;/gi, " ");
-                       
-                       // [quote]
-                       html = html.replace(/<blockquote([^>]+)>\n?<header[^>]*?>[\s\S]*?<\/header>/gi, function(match, attributes, innerContent) {
-                               var $quote;
-                               var $author = '';
-                               var $link = '';
-                               
-                               if (attributes.match(/data-author="([^"]+)"/)) {
-                                       $author = WCF.String.unescapeHTML(RegExp.$1);
-                               }
-                               
-                               if (attributes.match(/cite="([^"]+)"/)) {
-                                       $link = WCF.String.unescapeHTML(RegExp.$1);
-                               }
-                               
-                               if ($link) {
-                                       $quote = "[quote='" + $author + "','" + $link + "']";
-                               }
-                               else if ($author) {
-                                       $quote = "[quote='" + $author + "']";
-                               }
-                               else {
-                                       $quote = "[quote]";
-                               }
-                               
-                               return $quote;
-                       });
-                       html = html.replace(/(?:\n*)<\/blockquote>\n?/gi, '\n[/quote]\n');
-                       
-                       // smileys
-                       html = html.replace(/ ?<img [^>]*?alt="([^"]+?)"[^>]*?class="smiley"[^>]*?> ?/gi, ' $1 '); // firefox
-                       html = html.replace(/ ?<img [^>]*?class="smiley"[^>]*?alt="([^"]+?)"[^>]*?> ?/gi, ' $1 '); // chrome, ie
-                       
                        // attachments
                        html = html.replace(/<img([^>]*?)class="[^"]*redactorEmbeddedAttachment[^"]*"([^>]*?)>/gi, function(match, attributesBefore, attributesAfter) {
                                var $attributes = attributesBefore + ' ' + attributesAfter;
@@ -428,41 +350,6 @@ RedactorPlugins.wbbcode = function() {
                                return '[attach=' + $attachmentID + '][/attach]';
                        });
                        
-                       // [img]
-                       html = html.replace(/<img([^>]*)?src=(["'])([^"']+?)\2([^>]*)?>/gi, function(match, attributesBefore, quotationMarks, source, attributesAfter) {
-                               var attrs = attributesBefore + " " + attributesAfter;
-                               var style = '';
-                               if (attrs.match(/style="([^"]+)"/)) {
-                                       style = RegExp.$1;
-                               }
-                               
-                               var $float = 'none';
-                               var $width = 0;
-                               
-                               var $styles = style.split(';');
-                               for (var $i = 0; $i < $styles.length; $i++) {
-                                       var $style = $styles[$i];
-                                       if ($style.match(/float: (left|right|none)/)) {
-                                               $float = RegExp.$1;
-                                       }
-                                       else if ($style.match(/width: (\d+)px/)) {
-                                               $width = parseInt(RegExp.$1);
-                                       }
-                               }
-                               
-                               if ($width) {
-                                       return "[img='" + source + "'," + $float + "," + $width + "][/img]";
-                               }
-                               else if ($float !== 'none') {
-                                       return "[img='" + source + "'," + $float + "][/img]";
-                               }
-                               
-                               return "[img]" + source + "[/img]";
-                       });
-                       
-                       // [td]+[align]
-                       html = html.replace(/<td style="text-align: ?(left|center|right|justify);? ?">([\s\S]*?)<\/td>/gi, "[td][align=$1]$2[/align][/td]");
-                       
                        // cache redactor's selection markers
                        var $cachedMarkers = { };
                        html.replace(/<span id="selection-marker-\d+" class="redactor-selection-marker"><\/span>/, function(match) {
@@ -484,56 +371,6 @@ RedactorPlugins.wbbcode = function() {
                                }
                        }
                        
-                       // restore code listings
-                       if ($.getLength($cachedCodeListings)) {
-                               $.each($cachedCodeListings, function(uuid, listing) {
-                                       var $count = 0;
-                                       if (listing.highlighter) $count++;
-                                       if (listing.lineNumber) $count++;
-                                       if (listing.filename) $count++;
-                                       
-                                       var $attributes = '';
-                                       switch ($count) {
-                                               case 1:
-                                                       if (listing.highlighter) {
-                                                               $attributes = listing.highlighter;
-                                                       }
-                                                       else if (listing.filename) {
-                                                               $attributes = "'" + listing.filename + "'";
-                                                       }
-                                                       else {
-                                                               $attributes = listing.lineNumber;
-                                                       }
-                                               break;
-                                               
-                                               case 2:
-                                                       if (listing.lineNumber) {
-                                                               $attributes = listing.lineNumber;
-                                                       }
-                                                       
-                                                       if (listing.highlighter) {
-                                                               if ($attributes.length) $attributes += ',';
-                                                               $attributes += listing.highlighter;
-                                                       }
-                                                       
-                                                       if (listing.filename) {
-                                                               if ($attributes.length) $attributes += ',';
-                                                               
-                                                               $attributes += "'" + listing.filename + "'";
-                                                       }
-                                               break;
-                                               
-                                               case 3:
-                                                       $attributes = listing.highlighter + ',' + listing.lineNumber + ",'" + listing.filename + "'";
-                                               break;
-                                       }
-                                       
-                                       var $bbcode = '[code' + ($attributes.length ? '=' + $attributes : '') + ']' + listing.codeContent + '[/code]\n';
-                                       
-                                       html = html.replace(new RegExp('@@@' + uuid + '@@@\n?', 'g'), $bbcode);
-                               });
-                       }
-                       
                        // Restore <, > and &
                        html = html.replace(/&lt;/g, '<');
                        html = html.replace(/&gt;/g, '>');
@@ -545,12 +382,6 @@ RedactorPlugins.wbbcode = function() {
                        
                        WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'afterConvertFromHtml', { html: html });
                        
-                       // remove all leading and trailing whitespaces, but add one empty line at the end
-                       html = $.trim(html);
-                       if (html.length) {
-                               html += "\n";
-                       }
-                       
                        return html;
                },
                
@@ -568,15 +399,6 @@ RedactorPlugins.wbbcode = function() {
                        // remove 0x200B (unicode zero width space)
                        data = this.wutil.removeZeroWidthSpace(data);
                        
-                       // cache source code tags
-                       var $cachedCodes = [ ];
-                       var $regExp = new RegExp('\\[(' + __REDACTOR_SOURCE_BBCODES.join('|') + ')([\\S\\s]+?)\\[\\/\\1\\]', 'gi');
-                       data = data.replace($regExp, function(match) {
-                               var $key = match.hashCode();
-                               $cachedCodes.push({ key: $key, value: match.replace(/\$/g, '$$$$') });
-                               return '@@' + $key + '@@';
-                       });
-                       
                        // [email]
                        data = data.replace(/\[email\]([^"]+?)\[\/email]/gi, '<a href="mailto:$1">$1</a>' + this.opts.invisibleSpace);
                        data = data.replace(/\[email\=([^"\]]+)](.+?)\[\/email]/gi, '<a href="mailto:$1">$2</a>' + this.opts.invisibleSpace);
@@ -682,267 +504,6 @@ RedactorPlugins.wbbcode = function() {
                        // remove "javascript:"
                        data = data.replace(/(javascript):/gi, '$1<span></span>:');
                        
-                       // extract [quote] bbcodes to prevent line break handling below
-                       var $cachedQuotes = [ ];
-                       var $knownQuotes = [ ];
-                       
-                       var $parts = data.split(/(\[(?:\/quote|quote|quote='[^']*?'(?:,'[^']*?')?|quote="[^"]*?"(?:,"[^"]*?")?)\])/i);
-                       var $lostQuote = WCF.getUUID();
-                       while (true) {
-                               var $foundClosingTag = false;
-                               for (var $i = 0; $i < $parts.length; $i++) {
-                                       var $part = $parts[$i];
-                                       if ($part.toLowerCase() === '[/quote]') {
-                                               $foundClosingTag = true;
-                                               
-                                               var $content = '';
-                                               var $previous = $parts.slice(0, $i);
-                                               var $foundOpenTag = false;
-                                               while ($previous.length) {
-                                                       var $prev = $previous.pop();
-                                                       $content = $prev + $content;
-                                                       if ($prev.match(/^\[quote/i)) {
-                                                               $part = $content + $part;
-                                                               
-                                                               var $key = WCF.getUUID();
-                                                               $cachedQuotes.push({
-                                                                       hashCode: $key,
-                                                                       content: $part.replace(/\$/g, '$$$$')
-                                                               });
-                                                               $knownQuotes.push($key);
-                                                               
-                                                               $part = '@@' + $key + '@@';
-                                                               $foundOpenTag = true;
-                                                               break;
-                                                       }
-                                               }
-                                               
-                                               if (!$foundOpenTag) {
-                                                       $previous = $parts.slice(0, $i);
-                                                       $part = $lostQuote;
-                                               }
-                                               
-                                               // rebuild the array
-                                               $parts = $previous.concat($part, $parts.slice($i + 1));
-                                               
-                                               break;
-                                       }
-                               }
-                               
-                               if (!$foundClosingTag) {
-                                       break;
-                               }
-                       }
-                       
-                       data = $parts.join('');
-                       
-                       // restore unmatched closing quote tags
-                       data = data.replace(new RegExp($lostQuote, 'g'), '[/quote]');
-                       
-                       // drop trailing line breaks
-                       data = data.replace(/\n*$/, '');
-                       
-                       // insert quotes
-                       if ($cachedQuotes.length) {
-                               // [quote]
-                               var $unquoteString = function(quotedString) {
-                                       return quotedString.replace(/^['"]/, '').replace(/['"]$/, '');
-                               };
-                               
-                               var self = this;
-                               var $transformQuote = function(quote) {
-                                       return quote.replace(/\[quote(=(['"]).+?\2)?\]([\S\s]*)\[\/quote\]/gi, function(match, attributes, quotationMark, innerContent) {
-                                               var $author = '';
-                                               var $link = '';
-                                               
-                                               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)));
-                                               }
-                                               
-                                               var $quote = '<blockquote class="quoteBox container containerPadding quoteBoxSimple" cite="' + $link + '" data-author="' + $author + '">'
-                                                               + '<header contenteditable="false">'
-                                                                       + '<h3>'
-                                                                               + self.wbbcode._buildQuoteHeader($author, $link)
-                                                                       + '</h3>'
-                                                                       + '<a class="redactorQuoteEdit"></a>'
-                                                               + '</header>';
-                                               
-                                               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;
-                                                               }
-                                                               else if ($line.match(/^@@([0-9\-]+)@@$/)) {
-                                                                       if (WCF.inArray(RegExp.$1, $knownQuotes)) {
-                                                                               // prevent quote being nested inside a <div> block
-                                                                               $tmp += $line;
-                                                                               continue;
-                                                                       }
-                                                               }
-                                                               
-                                                               $tmp += '<div>' + $line + '</div>';
-                                                       }
-                                               }
-                                               else {
-                                                       $tmp = '<div>' + self.opts.invisibleSpace + '</div>';
-                                               }
-                                               
-                                               $quote += $tmp;
-                                               $quote += '</blockquote>';
-                                               
-                                               return $quote;
-                                       });
-                               };
-                               
-                               // reinsert quotes in reverse order, adding the most outer quotes first
-                               for (var $i = $cachedQuotes.length - 1; $i >= 0; $i--) {
-                                       var $cachedQuote = $cachedQuotes[$i];
-                                       var $regex = new RegExp('@@' + $cachedQuote.hashCode + '@@', 'g');
-                                       data = data.replace($regex, $transformQuote($cachedQuote.content));
-                               }
-                       }
-                       
-                       // insert codes
-                       if ($cachedCodes.length) {
-                               for (var $i = $cachedCodes.length - 1; $i >= 0; $i--) {
-                                       var $cachedCode = $cachedCodes[$i];
-                                       var $regex = new RegExp('@@' + $cachedCode.key + '@@', 'g');
-                                       var $value = $cachedCode.value;
-                                       
-                                       // [tt]
-                                       $value = $value.replace(/^\[tt\]([\s\S]+)\[\/tt\]/, (function(match, content) {
-                                               var $tmp = content.split("\n");
-                                               content = '';
-                                               
-                                               for (var $i = 0, $length = $tmp.length; $i < $length; $i++) {
-                                                       var $line = $tmp[$i];
-                                                       
-                                                       if ($line.length) {
-                                                               if (content.length) content += '</p><p>';
-                                                               
-                                                               content += '[tt]' + $line + '[/tt]';
-                                                       }
-                                                       else {
-                                                               if ($i === 0 || ($i + 1) === $length) {
-                                                                       // ignore the first and last empty element
-                                                                       continue;
-                                                               }
-                                                               
-                                                               if (content.match(/\[\/tt\]$/)) {
-                                                                       content += '</p><p>' + this.opts.invisibleSpace + '';
-                                                               }
-                                                               else {
-                                                                       content += '</p><p><br>';
-                                                               }
-                                                       }
-                                               }
-                                               
-                                               return content;
-                                       }).bind(this));
-                                       
-                                       // [code]
-                                       $value = $value.replace(/^\[code([^\]]*)\]([\S\s]*)\[\/code\]$/, (function(matches, parameters, content) {
-                                               var $highlighter = 'plain';
-                                               var $lineNumber = 0;
-                                               var $filename = '';
-                                               
-                                               if (parameters) {
-                                                       parameters = parameters.substring(1);
-                                                       parameters = parameters.split(',');
-                                                       
-                                                       var $isNumber = function(string) { return string.match(/^\d+$/); };
-                                                       var $isFilename = function(string) { return (string.indexOf('.') !== -1) || (string.match(/^(["']).*\1$/)); };
-                                                       var $isHighlighter = function(string) { return  (__REDACTOR_CODE_HIGHLIGHTERS[string] !== undefined); };
-                                                       
-                                                       var $unquoteFilename = function(filename) {
-                                                               return filename.replace(/^(["'])(.*)\1$/, '$2');
-                                                       };
-                                                       
-                                                       switch (parameters.length) {
-                                                               case 1:
-                                                                       if ($isNumber(parameters[0])) {
-                                                                               $lineNumber = (parseInt(parameters[0]) > 1) ? parameters[0] : 0;
-                                                                       }
-                                                                       else if ($isFilename(parameters[0])) {
-                                                                               $filename = $unquoteFilename(parameters[0]);
-                                                                       }
-                                                                       else if ($isHighlighter(parameters[0])) {
-                                                                               $highlighter = parameters[0];
-                                                                       }
-                                                               break;
-                                                               
-                                                               case 2:
-                                                                       if ($isNumber(parameters[0])) {
-                                                                               $lineNumber = (parseInt(parameters[0]) > 1) ? parameters[0] : 0;
-                                                                               
-                                                                               if ($isHighlighter(parameters[1])) {
-                                                                                       $highlighter = parameters[1];
-                                                                               }
-                                                                               else if ($isFilename(parameters[1])) {
-                                                                                       $filename = $unquoteFilename(parameters[1]);
-                                                                               }
-                                                                       }
-                                                                       else {
-                                                                               if ($isHighlighter(parameters[0])) $highlighter = parameters[0];
-                                                                               if ($isFilename(parameters[1])) $filename = $unquoteFilename(parameters[1]);
-                                                                       }
-                                                               break;
-                                                               
-                                                               case 3:
-                                                                       if ($isHighlighter(parameters[0])) $highlighter = parameters[0];
-                                                                       if ($isNumber(parameters[1])) $lineNumber = parameters[1];
-                                                                       if ($isFilename(parameters[2])) $filename = $unquoteFilename(parameters[2]);
-                                                               break;
-                                                       }
-                                               }
-                                               
-                                               content = content.replace(/^\n+/, '').replace(/\n+$/, '').split(/\n/);
-                                               var $lines = '';
-                                               for (var $i = 0; $i < content.length; $i++) {
-                                                       var $line = content[$i];
-                                                       if (!$line.length) {
-                                                               $line = this.opts.invisibleSpace;
-                                                       }
-                                                       
-                                                       $lines += '<li>' + $line + '</li>';
-                                               }
-                                               
-                                               return '<div class="codeBox container" contenteditable="false" data-highlighter="' + $highlighter + '"' + ($filename ? ' data-filename="' + WCF.String.escapeHTML($filename) + '"' : '' ) + '>'
-                                                       + '<div>'
-                                                               + '<div>'
-                                                                       + '<h3>' + __REDACTOR_CODE_HIGHLIGHTERS[$highlighter] + ($filename ? ': ' + WCF.String.escapeHTML($filename) : '') + '</h3>'
-                                                               + '</div>'
-                                                               + '<ol start="' + ($lineNumber > 1 ? $lineNumber : 1) + '">'
-                                                                       + $lines
-                                                               + '</ol>'
-                                                       + '</div>'
-                                               + '</div>';
-                                       }).bind(this));
-                                       
-                                       data = data.replace($regex, $value);
-                               }
-                       }
-                       
                        WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'afterConvertToHtml', { data: data });
                        
                        return data;
index 1aa3626fd66ed6047cd94635e19217e102ffae2d..e196979d335368d921538b6c7ffee405b003caed 100644 (file)
@@ -667,7 +667,7 @@ RedactorPlugins.wmonkeypatch = function() {
                                                anchor.attr('href', link);
                                        }
                                }
-                               else {
+                               else if (link !== '') {
                                        anchor = document.createElement('a');
                                        anchor.href = link;
                                        image[0].parentNode.insertBefore(anchor, image[0]);
index 0e3cafdffadae3aa9aeeb9c9d4c898c26c91337f..9382df05218a8883facd37e2a0eb3cce9d27dd0d 100644 (file)
@@ -95,6 +95,7 @@ define(['EventHandler', 'StringUtil', 'DOM/Traverse'], function(EventHandler, St
                                
                                // callback replacement
                                { tagName: 'A', callback: this._convertUrl.bind(this) },
+                               { tagName: 'IMG', callback: this._convertImage.bind(this) },
                                { tagName: 'LI', callback: this._convertListItem.bind(this) },
                                { tagName: 'OL', callback: this._convertList.bind(this) },
                                { tagName: 'TABLE', callback: this._convertTable.bind(this) },
@@ -173,6 +174,32 @@ define(['EventHandler', 'StringUtil', 'DOM/Traverse'], function(EventHandler, St
                        element.outerHTML = open + element.innerHTML.replace(/^\n*/, '').replace(/\n*$/, '') + '[/quote]\n';
                },
                
+               _convertImage: function(element) {
+                       if (element.classList.contains('smiley')) {
+                               // smiley
+                               element.outerHTML = ' ' + element.getAttribute('alt') + ' ';
+                       }
+                       else if (element.classList.contains('redactorEmbeddedAttachment')) {
+                               // TODO: handle attachments
+                       }
+                       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]";
+                               }
+                               else if (float !== 'none') {
+                                       element.outerHTML = "[img='" + source + "'," + float + "][/img]";
+                               }
+                               else {
+                                       element.outerHTML = "[img]" + source + "[/img]";
+                               }
+                       }
+               },
+               
                _convertList: function(element) {
                        var open;
                        
index 9e72dc9d54756662c209394d63c7bc7dc02ad725..2ea34d0f4ec31bec59b295e69b44858262b4fc29 100644 (file)
@@ -11,7 +11,7 @@ define([], function() {
                
                _splitTags: function(message) {
                        // TODO: `validTags` should be dynamic similar to the PHP implementation
-                       var validTags = 'attach|b|code|color|i|list|url|table|td|tr|quote';
+                       var validTags = __REDACTOR_BBCODES.join('|');
                        var pattern = '(\\\[(?:/(?:' + validTags + ')|(?:' + validTags + ')'
                                + '(?:='
                                        + '(?:\\\'[^\\\'\\\\]*(?:\\\\.[^\\\'\\\\]*)*\\\'|[^,\\\]]*)'
index 9a40c18d1f2f76e1bc922433601d674d5ea0b69e..8fb7e5d2def69b23f818c6a868dde34ae86d5d52 100644 (file)
@@ -65,7 +65,8 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'],
                                code: this._replaceCode.bind(this),
                                list: this._replaceList.bind(this),
                                quote: this._replaceQuote.bind(this),
-                               url: this._replaceUrl.bind(this)
+                               url: this._replaceUrl.bind(this),
+                               img: this._replaceImage.bind(this)
                        };
                        
                        _removeNewlineAfter = ['quote', 'table', 'td', 'tr'];
@@ -220,6 +221,54 @@ define(['EventHandler', 'Language', 'StringUtil', 'WoltLab/WCF/BBCode/Parser'],
                        return '<span style="color: ' + StringUtil.escapeHTML(item.attributes[0]) + '">';
                },
                
+               _replaceImage: function(stack, item, index) {
+                       stack[item.pair] = '';
+                       
+                       var float = 'none', source = '', width = 0;
+                       
+                       switch (item.attributes.length) {
+                               case 0:
+                                       if (index + 1 < item.pair && typeof stack[index + 1] === 'string') {
+                                               source = stack[index + 1];
+                                               stack[index + 1] = '';
+                                       }
+                                       else {
+                                               // [img] without attributes and content, discard
+                                               return '';
+                                       }
+                               break;
+                               
+                               case 1:
+                                       source = item.attributes[0];
+                               break;
+                               
+                               case 2:
+                                       source = item.attributes[0];
+                                       float = item.attributes[1];
+                               break;
+                               
+                               case 3:
+                                       source = item.attributes[0];
+                                       float = item.attributes[1];
+                                       width = ~~item.attributes[2];
+                               break;
+                       }
+                       
+                       if (float !== 'left' && float !== 'right') float = 'none';
+                       
+                       var styles = [];
+                       if (width > 0) {
+                               styles.push('width: ' + width + 'px');
+                       }
+                       
+                       if (float !== 'none') {
+                               styles.push('float: ' + float);
+                               styles.push('margin: ' + (float === 'left' ? '0 15px 7px 0' : '0 0 7px 15px'));
+                       }
+                       
+                       return '<img src="' + source + '"' + (styles.length ? ' style="' + styles.join(';') + '"' : '') + '>';
+               },
+               
                _replaceList: function(stack, item, index) {
                        var type = (items.attributes.length) ? item.attributes[0] : '';
                        
index be41975ce4886cdbbcf2169fee0e2b87451e9ba7..0a64c0ebf28286b547c91eedce9258d43f3637cd 100644 (file)
@@ -65,6 +65,15 @@ class BBCodeHandler extends SingletonFactory {
                return in_array($bbCodeTag, $this->allowedBBCodes);
        }
        
+       /**
+        * Returns all bbcodes.
+        * 
+        * @return      array<\wcf\data\bbcode\BBCode>
+        */
+       public function getBBCodes() {
+               return BBCodeCache::getInstance()->getBBCodes();
+       }
+       
        /**
         * Returns a list of BBCodes displayed as buttons.
         * 
index e92182fb492f6ac38eeae59cab869776cc7841cb..a49a7065f80c6cf313b1f70a57ef659deef32c3a 100644 (file)
        left: 50%;
        line-height: @wcfSmallFontSize;
        margin-top: -13px;
+       opacity: 1;
        top: 50%;
+       visibility: visible;
        z-index: 5;
 }