You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.3 KiB

  1. import unicodeMapping from './emoji_unicode_mapping_light';
  2. import Trie from 'substring-trie';
  3. const trie = new Trie(Object.keys(unicodeMapping));
  4. const assetHost = process.env.CDN_HOST || '';
  5. const emojify = (str, customEmojis = {}) => {
  6. let rtn = '';
  7. for (;;) {
  8. let match, i = 0, tag;
  9. while (i < str.length && (tag = '<&:'.indexOf(str[i])) === -1 && !(match = trie.search(str.slice(i)))) {
  10. i += str.codePointAt(i) < 65536 ? 1 : 2;
  11. }
  12. let rend, replacement = '';
  13. if (i === str.length) {
  14. break;
  15. } else if (str[i] === ':') {
  16. if (!(() => {
  17. rend = str.indexOf(':', i + 1) + 1;
  18. if (!rend) return false; // no pair of ':'
  19. const lt = str.indexOf('<', i + 1);
  20. if (!(lt === -1 || lt >= rend)) return false; // tag appeared before closing ':'
  21. const shortname = str.slice(i, rend);
  22. // now got a replacee as ':shortname:'
  23. // if you want additional emoji handler, add statements below which set replacement and return true.
  24. if (shortname in customEmojis) {
  25. replacement = `<img draggable="false" class="emojione" alt="${shortname}" title="${shortname}" src="${customEmojis[shortname]}" />`;
  26. return true;
  27. }
  28. return false;
  29. })()) rend = ++i;
  30. } else if (tag >= 0) { // <, &
  31. rend = str.indexOf('>;'[tag], i + 1) + 1;
  32. if (!rend) break;
  33. i = rend;
  34. } else { // matched to unicode emoji
  35. const { filename, shortCode } = unicodeMapping[match];
  36. const title = shortCode ? `:${shortCode}:` : '';
  37. replacement = `<img draggable="false" class="emojione" alt="${match}" title="${title}" src="${assetHost}/emoji/${filename}.svg" />`;
  38. rend = i + match.length;
  39. }
  40. rtn += str.slice(0, i) + replacement;
  41. str = str.slice(rend);
  42. }
  43. return rtn + str;
  44. };
  45. export default emojify;
  46. export const buildCustomEmojis = customEmojis => {
  47. const emojis = [];
  48. customEmojis.forEach(emoji => {
  49. const shortcode = emoji.get('shortcode');
  50. const url = emoji.get('static_url');
  51. const name = shortcode.replace(':', '');
  52. emojis.push({
  53. id: name,
  54. name,
  55. short_names: [name],
  56. text: '',
  57. emoticons: [],
  58. keywords: [name],
  59. imageUrl: url,
  60. custom: true,
  61. });
  62. });
  63. return emojis;
  64. };