about summary refs log tree commit diff
path: root/app/javascript/mastodon/features/emoji/emoji.js
diff options
context:
space:
mode:
authorNolan Lawson <nolan@nolanlawson.com>2017-10-05 18:42:34 -0700
committerEugen Rochko <eugen@zeonfederated.com>2017-10-06 03:42:34 +0200
commitfd7f0732fe26554c51218c4f67955e8050590d2c (patch)
tree2d0bacca4d9097035afe4f60e570bfc0f5221bb5 /app/javascript/mastodon/features/emoji/emoji.js
parenteb5ac234342db46c881d8e69644d3292b5eabb54 (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.js72
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;
+};