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.

71 lines
2.2 KiB

  1. import { unicodeMapping } from './emojione_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. replacement = `<img draggable="false" class="emojione" alt="${match}" title=":${shortCode}:" src="${assetHost}/emoji/${filename}.svg" />`;
  37. rend = i + match.length;
  38. }
  39. rtn += str.slice(0, i) + replacement;
  40. str = str.slice(rend);
  41. }
  42. return rtn + str;
  43. };
  44. export default emojify;
  45. export const buildCustomEmojis = customEmojis => {
  46. const emojis = [];
  47. customEmojis.forEach(emoji => {
  48. const shortcode = emoji.get('shortcode');
  49. const url = emoji.get('static_url');
  50. const name = shortcode.replace(':', '');
  51. emojis.push({
  52. id: name,
  53. name,
  54. short_names: [name],
  55. text: '',
  56. emoticons: [],
  57. keywords: [name],
  58. imageUrl: url,
  59. custom: true,
  60. });
  61. });
  62. return emojis;
  63. };