return '[attach=' + $attachmentID + '][/attach]';
});
- // cache redactor's selection markers
- var $cachedMarkers = { };
- html.replace(/<span id="selection-marker-\d+" class="redactor-selection-marker"><\/span>/, function(match) {
- var $key = match.hashCode();
- $cachedMarkers[$key] = match.replace(/\$/g, '$$$$');
- return '@@' + $key + '@@';
- });
-
WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'convertFromHtml', { html: html });
// Remove remaining tags.
html = html.replace(/<[^(<|>)]+>/g, '');
- // insert redactor's selection markers
- if ($.getLength($cachedMarkers)) {
- for (var $key in $cachedMarkers) {
- var $regex = new RegExp('@@' + $key + '@@', 'g');
- data = data.replace($regex, $cachedMarkers[$key]);
- }
- }
-
// Restore <, > and &
html = html.replace(/</g, '<');
html = html.replace(/>/g, '>');
// remove 0x200B (unicode zero width space)
data = this.wutil.removeZeroWidthSpace(data);
- // [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);
-
- // [img]
- data = data.replace(/\[img\]([^"]+?)\[\/img\]/gi,'<img src="$1" />');
- data = data.replace(/\[img='?([^"]*?)'?,'?(left|right)'?\]\[\/img\]/gi, function(match, src, alignment) {
- var $style = 'float: ' + alignment + ';';
- if (alignment === 'left') {
- $style += 'margin: 0 15px 7px 0';
- }
- else {
- $style += 'margin: 0 0 7px 15px';
- }
-
- return '<img src="' + src + '" style="' + $style + '" />';
- });
- data = data.replace(/\[img='?([^"]*?)'?,'?(left|right|none)'?,'?(\d+)'?\]\[\/img\]/gi, function(match, src, alignment, width) {
- var $style = 'float: ' + alignment + '; width: ' + width + 'px;';
- if (alignment === 'left') {
- $style += 'margin: 0 15px 7px 0';
- }
- else {
- $style += 'margin: 0 0 7px 15px';
- }
-
- return '<img src="' + src + '" style="' + $style + '" />';
- });
- data = data.replace(/\[img='?([^"]*?)'?\]\[\/img\]/gi,'<img src="$1" />');
-
// attachments
var $attachmentUrl = this.wutil.getOption('woltlab.attachmentUrl');
var $attachmentThumbnailUrl = this.wutil.getOption('woltlab.attachmentThumbnailUrl');
});
}
- // smileys
- for (var smileyCode in __REDACTOR_SMILIES) {
- var $smileyCode = smileyCode.replace(/</g, '<').replace(/>/g, '>');
- var regExp = new RegExp('(\\s|>|^)' + WCF.String.escapeRegExp($smileyCode) + '(?=\\s|<|$)', 'gi');
- data = data.replace(regExp, '$1<img src="' + __REDACTOR_SMILIES[smileyCode] + '" class="smiley" alt="' + $smileyCode + '" />');
- }
-
// remove "javascript:"
data = data.replace(/(javascript):/gi, '$1<span></span>:');
var _inlineConverter = {};
var _sourceConverter = [];
+ function addSmileyPadding(element, before) {
+ var target = element[(before ? 'previousSibling' : 'nextSibling')];
+ if (target === null || target.nodeType !== Node.TEXT_NODE || !/\s$/.test(target.textContent)) {
+ return true;
+ }
+
+ return false;
+ }
+
var BBCodeFromHtml = {
convert: function(message) {
if (message.length) this._setup();
_convertImage: function(element) {
if (element.classList.contains('smiley')) {
// smiley
- element.outerHTML = ' ' + element.getAttribute('alt') + ' ';
+ element.outerHTML = (addSmileyPadding(element, true) ? ' ' : '') + element.getAttribute('alt') + (addSmileyPadding(element, false) ? ' ' : '');
}
else if (element.classList.contains('redactorEmbeddedAttachment')) {
// TODO: handle attachments
},
_convertUrl: function(element) {
- var content = element.textContent.trim(), href = element.href.trim();
+ var content = element.textContent.trim(), href = element.href.trim(), tagName = 'url';
if (href === '' || content === '') {
// empty href or content
}
if (href.indexOf('mailto:') === 0) {
- element.outerHTML = '[email=' + href.substr(6) + ']' + element.innerHTML + '[/email]';
+ href = href.substr(7);
+ tagName = 'email';
}
- else if (href === content) {
- element.outerHTML = '[url]' + href + '[/url]';
+
+ if (href === content) {
+ element.outerHTML = '[' + tagName + ']' + href + '[/' + tagName + ']';
}
else {
- element.outerHTML = "[url='" + href + "']" + element.innerHTML + "[/url]";
+ element.outerHTML = "[" + tagName + "='" + href + "']" + element.innerHTML + "[/" + tagName + "]";
}
},
// callback replacement
color: this._replaceColor.bind(this),
code: this._replaceCode.bind(this),
+ email: this._replaceEmail.bind(this),
list: this._replaceList.bind(this),
quote: this._replaceQuote.bind(this),
url: this._replaceUrl.bind(this),
}
}
+ // replace smilies
+ this._replaceSmilies(stack);
+
if (typeof replace === 'string') {
stack[item.pair] = '</' + replace + '>';
return '<span style="color: ' + StringUtil.escapeHTML(item.attributes[0]) + '">';
},
+ _replaceEmail: function(stack, item, index) {
+ var email = '';
+ if (item.attributes.length) {
+ email = item.attributes[0];
+ }
+ else {
+ var element;
+ for (var i = index + 1; i < item.pair; i++) {
+ element = stack[i];
+
+ if (typeof element === 'object') {
+ email = '';
+ break;
+ }
+ else {
+ email += element;
+ }
+ }
+
+ // no attribute present and element is empty, handle as plain text
+ if (email.trim() === '') {
+ stack[item.pair] = stack[item.pair].source;
+
+ return item.source;
+ }
+ }
+
+ stack[item.pair] = '</a>';
+
+ return '<a href="mailto:' + StringUtil.escapeHTML(email) + '">';
+ },
+
_replaceImage: function(stack, item, index) {
stack[item.pair] = '';
styles.push('margin: ' + (float === 'left' ? '0 15px 7px 0' : '0 0 7px 15px'));
}
- return '<img src="' + source + '"' + (styles.length ? ' style="' + styles.join(';') + '"' : '') + '>';
+ return '<img src="' + StringUtil.escapeHTML(source) + '"' + (styles.length ? ' style="' + styles.join(';') + '"' : '') + '>';
},
_replaceList: function(stack, item, index) {
+ '<div>\u200b';
},
+ _replaceSmilies: function(stack) {
+ var altValue, item, regexp;
+ for (var i = 0, length = stack.length; i < length; i++) {
+ item = stack[i];
+
+ if (typeof item === 'string') {
+ for (var smileyCode in __REDACTOR_SMILIES) {
+ if (__REDACTOR_SMILIES.hasOwnProperty(smileyCode)) {
+ altValue = smileyCode.replace(/</g, '<').replace(/>/g, '>');
+ regexp = new RegExp('(\\s|^)' + StringUtil.escapeRegExp(smileyCode) + '(?=\\s|$)', 'gi');
+ item = item.replace(regexp, '$1<img src="' + __REDACTOR_SMILIES[smileyCode] + '" class="smiley" alt="' + altValue + '">');
+ }
+ }
+
+ stack[i] = item;
+ }
+ else if (__REDACTOR_SOURCE_BBCODES.indexOf(item.name) !== -1) {
+ // skip processing content
+ i = item.pair;
+ }
+ }
+ },
+
_replaceUrl: function(stack, item, index) {
// ignore url bbcode without arguments
if (!item.attributes.length) {