diff options
author | MIYAGI Hikaru <hcmiya@users.noreply.github.com> | 2017-09-19 21:27:29 +0000 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2017-09-19 23:27:29 +0200 |
commit | 8e33fc29d747b19ad1bab5a0a8b015ad84469329 (patch) | |
tree | e581bc80101240cbc8bc9d315b500ad320d59374 | |
parent | 1de6c52545681345e9515b5df7dc0a7e228be098 (diff) |
redo #4500 with customEmojis (#5016)
-rw-r--r-- | app/javascript/mastodon/emoji.js | 66 |
1 files changed, 29 insertions, 37 deletions
diff --git a/app/javascript/mastodon/emoji.js b/app/javascript/mastodon/emoji.js index 865b85b61..e586a3442 100644 --- a/app/javascript/mastodon/emoji.js +++ b/app/javascript/mastodon/emoji.js @@ -4,47 +4,39 @@ import Trie from 'substring-trie'; const trie = new Trie(Object.keys(unicodeMapping)); const emojify = (str, customEmojis = {}) => { - // This walks through the string from start to end, ignoring any tags (<p>, <br>, etc.) - // and replacing valid unicode strings - // that _aren't_ within tags with an <img> version. - // The goal is to be the same as an emojione.regUnicode replacement, but faster. - let i = -1; - let insideTag = false; - let insideShortname = false; - let shortnameStartIndex = -1; - let match; - while (++i < str.length) { - const char = str.charAt(i); - if (insideShortname && char === ':') { - const shortname = str.substring(shortnameStartIndex, i + 1); - if (shortname in customEmojis) { - const replacement = `<img draggable="false" class="emojione" alt="${shortname}" title="${shortname}" src="${customEmojis[shortname]}" />`; - str = str.substring(0, shortnameStartIndex) + replacement + str.substring(i + 1); - i += (replacement.length - shortname.length - 1); // jump ahead the length we've added to the string + let rtn = ''; + for (;;) { + let match, i = 0, tag; + while (i < str.length && (tag = '<&:'.indexOf(str[i])) === -1 && !(match = trie.search(str.slice(i)))) { + i += str.codePointAt(i) < 65536 ? 1 : 2; + } + if (i === str.length) + break; + else if (tag >= 0) { + let tagend = str.indexOf('>;:'[tag], i + 1) + 1; + if (!tagend) + break; + if (str[i] === ':') { + const shortname = str.slice(i, tagend); + const lt = str.indexOf('<', i + 1); + if ((lt === -1 || lt >= tagend) && shortname in customEmojis) { + rtn += str.slice(0, i) + `<img draggable="false" class="emojione" alt="${shortname}" title="${shortname}" src="${customEmojis[shortname]}" />`; + str = str.slice(tagend); + } else { + rtn += str.slice(0, i + 1); + str = str.slice(i + 1); + } } else { - i--; - } - insideShortname = false; - } else if (insideTag && char === '>') { - insideTag = false; - } else if (char === '<') { - insideTag = true; - insideShortname = false; - } else if (!insideTag && char === ':') { - insideShortname = true; - shortnameStartIndex = i; - } else if (!insideTag && (match = trie.search(str.substring(i)))) { - const unicodeStr = match; - if (unicodeStr in unicodeMapping) { - const [filename, shortCode] = unicodeMapping[unicodeStr]; - const alt = unicodeStr; - const replacement = `<img draggable="false" class="emojione" alt="${alt}" title=":${shortCode}:" src="/emoji/${filename}.svg" />`; - str = str.substring(0, i) + replacement + str.substring(i + unicodeStr.length); - i += (replacement.length - unicodeStr.length); // jump ahead the length we've added to the string + rtn += str.slice(0, tagend); + str = str.slice(tagend); } + } else { + const [filename, shortCode] = unicodeMapping[match]; + rtn += str.slice(0, i) + `<img draggable="false" class="emojione" alt="${match}" title=":${shortCode}:" src="/emoji/${filename}.svg" />`; + str = str.slice(i + match.length); } } - return str; + return rtn + str; }; export default emojify; |