/** * replace all :emoji: codes with corresponding image * @param {string} inputString * @return {string} **/ function formatEmojis(inputString) { return inputString.replace(/:([^ \t:]+):/g, function(returnFailed, emoji) { var emojiDom = makeEmojiDom(emoji); if (emojiDom) { var domParent = document.createElement("span"); domParent.className = returnFailed === inputString ? R.klass.emoji.medium : R.klass.emoji.small; domParent.appendChild(emojiDom); return domParent.outerHTML; } return returnFailed; }); } /** @type {function(string):string} */ var formatText = (function() { /** * @constructor * @param {string} fullText */ function MessagePart(fullText) { /** @type {Array.} */ this.subParts = []; /** @type {string} */ this.text = ""; /** @type {string} */ this.fullText = fullText; /** @type {boolean} */ this.italic = false; /** @type {boolean} */ this.bold = false; /** @type {boolean} */ this.strike = false; /** @type {boolean} */ this.code = false; /** @type {boolean} */ this.longCode = false; /** @type {boolean} */ this.quote = false; } var isAlphadec = function(c) { return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || "àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûÂÊÎÔÛãñõÃÑÕäëïöüÿÄËÏÖÜŸçÇߨøÅ寿œ".indexOf(c) !== -1); } ,checkEnd = function(str, pos, c) { while (str[pos]) { if (isAlphadec(str[pos]) && str[pos] != c && str[pos +1] == c) { return true; } pos++; } return false; } MessagePart.prototype.isFinished = function() { var result = false; if (this.longCode) return this.text.substr(this.text.length -3) === '```'; if (this.code) return this.text[this.text.length -1] === '`' && this.text.length > 1; if (this.bold) result |= this.text[this.text.length -1] === '*' && this.text.length > 1; if (this.strike) result |= this.text[this.text.length -1] === '~' && this.text.length > 1; if (this.italic) result |= this.text[this.text.length -1] === '_' && this.text.length > 1; if (this.quote) result |= this.text[this.text.length -1] === '\n'; return result || this.isOnlyText(); }; MessagePart.prototype.addChar = function(c) { this.text += c; return this; }; MessagePart.prototype.isOnlyText = function() { return !this.italic && !this.bold && !this.strike && !this.code && !this.longCode && !this.quote; }; /** * @return {MessagePart} **/ MessagePart.prototype.finalize = function() { if (this.longCode) this.text = this.text.substr(0, this.text.length -3); else if (this.code) this.text = this.text.substr(0, this.text.length -1); else if (this.bold) this.text = this.text.substr(0, this.text.length -1); else if (this.strike) this.text = this.text.substr(0, this.text.length -1); else if (this.italic) this.text = this.text.substr(0, this.text.length -1); else if (this.quote) this.text = this.text.substr(0, this.text.length -1); return this; }; MessagePart.prototype.cloneType = function() { var clone = new MessagePart(this.fullText); clone.italic = this.italic; clone.bold = this.bold; clone.strike = this.strike; clone.code = this.code; clone.longCode = this.longCode; clone.quote = this.quote; return clone; }; /** * @param {boolean=} skipFirst **/ MessagePart.prototype.formatText = function(skipFirst) { var lastChild = new MessagePart(this.fullText); for (var i =skipFirst === true ? 1 : 0, textLength =this.fullText.length; i < textLength; i++) { //First, check if we have a ``` code block if (!lastChild.longCode && this.fullText.substr(i, 3) === '```') { this.subParts.push(lastChild.finalize()); lastChild = new MessagePart(this.fullText.substr(i)); lastChild.longCode = true; i += 2; } else if (!lastChild.longCode && !lastChild.code && this.fullText[i] === '`') { this.subParts.push(lastChild.finalize()); lastChild = new MessagePart(this.fullText.substr(i)); lastChild.code = true; } else if (!lastChild.longCode && !lastChild.italic && this.fullText[i] === '_') { this.subParts.push(lastChild.finalize()); lastChild = new MessagePart(this.fullText.substr(i)); lastChild.italic = true; } else if (!lastChild.longCode && !lastChild.bold && this.fullText[i] === '*') { this.subParts.push(lastChild.finalize()); lastChild = new MessagePart(this.fullText.substr(i)); lastChild.bold = true; } else if (!lastChild.longCode && !lastChild.strike && this.fullText[i] === '~') { this.subParts.push(lastChild.finalize()); lastChild = new MessagePart(this.fullText.substr(i)); lastChild.strike = true; } else { lastChild.addChar(this.fullText[i]); if (!lastChild.isOnlyText() && lastChild.isFinished()) { this.subParts.push(lastChild.finalize()); lastChild = new MessagePart(this.fullText.substr(i +1)); } } } if (lastChild.isFinished()) { this.subParts.push(lastChild.finalize()); } else { // Unterminated sequence var textChild = new MessagePart(lastChild.fullText[0]); textChild.text = lastChild.fullText[0]; this.subParts.push(textChild.finalize()); lastChild.formatText(true); this.subParts.push(lastChild); } /* var _msgContent = "" ,currentMods = {} ,quote = false ,i =0 var msgContent = this.text.replace(new RegExp('<([@#]?)([^>]*)>', 'g'), function(matched, type, entity) { var sub = entity.split('|'); if (type === '@') { if (!sub[1]) { var user = SLACK.context.users[sub[0]]; sub[1] = user ? ('@' +user.name) : locale.unknownMember; } else if ('@' !== sub[1][0]) { sub[1] = '@' +sub[1]; } sub[0] = '#' +sub[0]; sub[2] = R.klass.msg.link +' ' +R.klass.msg.linkuser; } else if (type === '#') { if (!sub[1]) { var chan = SLACK.context.channels[sub[0]]; sub[1] = chan ? ('#' +chan.name) : locale.unknownChannel; } else if ('#' !== sub[1][0]) { sub[1] = '#' +sub[1]; } sub[0] = '#' +sub[0]; sub[2] = R.klass.msg.link +' ' +R.klass.msg.linkchan; } else if (sub[0].indexOf("://") !== -1) { if (!sub[1]) sub[1] = sub[0]; sub[2] = R.klass.msg.link; } else { return matched; } return '' +sub[1] +''; }); msgContent = formatEmojis(msgContent); var msgLength = msgContent.length, appendMod = function(mods) { if (!Object.keys(currentMods).length) return ""; return ''; }; // Skip trailing while (i < msgLength && (msgContent[i] === ' ' || msgContent[i] === '\t')) i++; if (msgContent.substr(i, 4) === '>') { quote = true; i += 4; } for (; i < msgLength; i++) { var c = msgContent[i]; if (c === '<') { do { _msgContent += msgContent[i++]; } while (msgContent[i -1] !== '>' && msgContent[i]); i--; continue; } if (!(currentMods[R.klass.msg.style.bold]) && c === '*' && msgContent[i +1] && checkEnd(msgContent, i, c)) { if (Object.keys(currentMods).length) _msgContent += ''; currentMods[R.klass.msg.style.bold] = true; _msgContent += appendMod(currentMods); } else if (!(currentMods[R.klass.msg.style.strike]) && c === '~' && msgContent[i +1] && checkEnd(msgContent, i, c)) { if (Object.keys(currentMods).length) _msgContent += ''; currentMods[R.klass.msg.style.strike] = true; _msgContent += appendMod(currentMods); } else if (!(currentMods[R.klass.msg.style.code]) && c === '`' && msgContent[i +1] && checkEnd(msgContent, i, c)) { if (Object.keys(currentMods).length) _msgContent += ''; currentMods[R.klass.msg.style.code] = true; _msgContent += appendMod(currentMods); } else if (!(currentMods[R.klass.msg.style.italic]) && c === '_' && msgContent[i +1] && checkEnd(msgContent, i, c)) { if (Object.keys(currentMods).length) _msgContent += ''; currentMods[R.klass.msg.style.italic] = true; _msgContent += appendMod(currentMods); } else { var finalFound = false; _msgContent += c; do { if ((currentMods[R.klass.msg.style.bold]) && c !== '*' && msgContent[i +1] === '*') { delete currentMods[R.klass.msg.style.bold]; finalFound = true; } else if ((currentMods[R.klass.msg.style.strike]) && c !== '~' && msgContent[i +1] === '~') { delete currentMods[R.klass.msg.style.strike]; finalFound = true; } else if ((currentMods[R.klass.msg.style.code]) && c !== '`' && msgContent[i +1] === '`') { delete currentMods[R.klass.msg.style.code]; finalFound = true; } else if ((currentMods[R.klass.msg.style.italic]) && c !== '_' && msgContent[i +1] === '_') { delete currentMods[R.klass.msg.style.italic]; finalFound = true; } else { break; } c = msgContent[++i]; } while (i < msgLength); if (finalFound) _msgContent += '' +appendMod(currentMods); } } if (!isObjectEmpty(currentMods)) { // Should not append console.warn("formatter warning"); _msgContent += ''; } /* if (quote) msgContents[msgContentIndex] = '' +_msgContent +''; else msgContents[msgContentIndex] = _msgContent; */ }; MessagePart.prototype.getOuterClass = function() { var classList = ''; if (this.longCode) { classList += ' ' +R.klass.msg.style.longCode; } if (this.bold) { classList += ' ' +R.klass.msg.style.bold; } if (this.code) { classList += ' ' +R.klass.msg.style.code; } if (this.italic) { classList += ' ' +R.klass.msg.style.italic; } if (this.strike) { classList += ' ' +R.klass.msg.style.strike; } if (this.quote) { classList += ' ' +R.klass.msg.style.quote; } return classList; }; /** @return {string} */ MessagePart.prototype.getInnerHTML = function() { return this.text .replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ' ') // replace trailing spaces par non-secable spaces .replace(/\n/g, '
'); }; /** @return {string} */ MessagePart.prototype.toHTML = function() { if (this.subParts.length) { var result = ""; this.subParts.forEach(function(part) { result += part.toHTML(); }); return result; } else { if (this.isOnlyText() && !this.text.length) return ""; return '' +this.getInnerHTML() +''; } }; return function (fullText) { // trivial empty string var text = (fullText || "").trim(); if (text == "") return ""; var msgContent = new MessagePart(text); msgContent.formatText(); console.log(msgContent); return msgContent.toHTML(); } })();