diff options
author | Nolan Lawson <nolan@nolanlawson.com> | 2017-10-05 18:42:34 -0700 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2017-10-06 03:42:34 +0200 |
commit | fd7f0732fe26554c51218c4f67955e8050590d2c (patch) | |
tree | 2d0bacca4d9097035afe4f60e570bfc0f5221bb5 /app/javascript/mastodon/features/emoji/emoji.js | |
parent | eb5ac234342db46c881d8e69644d3292b5eabb54 (diff) |
Compress and combine emoji data (#5229)
Diffstat (limited to 'app/javascript/mastodon/features/emoji/emoji.js')
-rw-r--r-- | app/javascript/mastodon/features/emoji/emoji.js | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/app/javascript/mastodon/features/emoji/emoji.js b/app/javascript/mastodon/features/emoji/emoji.js new file mode 100644 index 000000000..998cb0a06 --- /dev/null +++ b/app/javascript/mastodon/features/emoji/emoji.js @@ -0,0 +1,72 @@ +import unicodeMapping from './emoji_unicode_mapping_light'; +import Trie from 'substring-trie'; + +const trie = new Trie(Object.keys(unicodeMapping)); + +const assetHost = process.env.CDN_HOST || ''; + +const emojify = (str, customEmojis = {}) => { + 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; + } + let rend, replacement = ''; + if (i === str.length) { + break; + } else if (str[i] === ':') { + if (!(() => { + rend = str.indexOf(':', i + 1) + 1; + if (!rend) return false; // no pair of ':' + const lt = str.indexOf('<', i + 1); + if (!(lt === -1 || lt >= rend)) return false; // tag appeared before closing ':' + const shortname = str.slice(i, rend); + // now got a replacee as ':shortname:' + // if you want additional emoji handler, add statements below which set replacement and return true. + if (shortname in customEmojis) { + replacement = `<img draggable="false" class="emojione" alt="${shortname}" title="${shortname}" src="${customEmojis[shortname]}" />`; + return true; + } + return false; + })()) rend = ++i; + } else if (tag >= 0) { // <, & + rend = str.indexOf('>;'[tag], i + 1) + 1; + if (!rend) break; + i = rend; + } else { // matched to unicode emoji + const { filename, shortCode } = unicodeMapping[match]; + const title = shortCode ? `:${shortCode}:` : ''; + replacement = `<img draggable="false" class="emojione" alt="${match}" title="${title}" src="${assetHost}/emoji/${filename}.svg" />`; + rend = i + match.length; + } + rtn += str.slice(0, i) + replacement; + str = str.slice(rend); + } + return rtn + str; +}; + +export default emojify; + +export const buildCustomEmojis = customEmojis => { + const emojis = []; + + customEmojis.forEach(emoji => { + const shortcode = emoji.get('shortcode'); + const url = emoji.get('static_url'); + const name = shortcode.replace(':', ''); + + emojis.push({ + id: name, + name, + short_names: [name], + text: '', + emoticons: [], + keywords: [name], + imageUrl: url, + custom: true, + }); + }); + + return emojis; +}; |