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.

173 lines
4.3 KiB

  1. // This code is largely borrowed from:
  2. // https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/emoji-index.js
  3. import data from './emoji_mart_data_light';
  4. import { getData, getSanitizedData, intersect } from './emoji_utils';
  5. let originalPool = {};
  6. let index = {};
  7. let emojisList = {};
  8. let emoticonsList = {};
  9. let customEmojisList = [];
  10. for (let emoji in data.emojis) {
  11. let emojiData = data.emojis[emoji];
  12. let { short_names, emoticons } = emojiData;
  13. let id = short_names[0];
  14. if (emoticons) {
  15. emoticons.forEach(emoticon => {
  16. if (emoticonsList[emoticon]) {
  17. return;
  18. }
  19. emoticonsList[emoticon] = id;
  20. });
  21. }
  22. emojisList[id] = getSanitizedData(id);
  23. originalPool[id] = emojiData;
  24. }
  25. function clearCustomEmojis(pool) {
  26. customEmojisList.forEach((emoji) => {
  27. let emojiId = emoji.id || emoji.short_names[0];
  28. delete pool[emojiId];
  29. delete emojisList[emojiId];
  30. });
  31. }
  32. function addCustomToPool(custom, pool) {
  33. if (customEmojisList.length) clearCustomEmojis(pool);
  34. custom.forEach((emoji) => {
  35. let emojiId = emoji.id || emoji.short_names[0];
  36. if (emojiId && !pool[emojiId]) {
  37. pool[emojiId] = getData(emoji);
  38. emojisList[emojiId] = getSanitizedData(emoji);
  39. }
  40. });
  41. customEmojisList = custom;
  42. index = {};
  43. }
  44. function search(value, { emojisToShowFilter, maxResults, include, exclude, custom = [] } = {}) {
  45. if (customEmojisList !== custom)
  46. addCustomToPool(custom, originalPool);
  47. maxResults = maxResults || 75;
  48. include = include || [];
  49. exclude = exclude || [];
  50. let results = null,
  51. pool = originalPool;
  52. if (value.length) {
  53. if (value === '-' || value === '-1') {
  54. return [emojisList['-1']];
  55. }
  56. let values = value.toLowerCase().split(/[\s|,|\-|_]+/),
  57. allResults = [];
  58. if (values.length > 2) {
  59. values = [values[0], values[1]];
  60. }
  61. if (include.length || exclude.length) {
  62. pool = {};
  63. data.categories.forEach(category => {
  64. let isIncluded = include && include.length ? include.indexOf(category.name.toLowerCase()) > -1 : true;
  65. let isExcluded = exclude && exclude.length ? exclude.indexOf(category.name.toLowerCase()) > -1 : false;
  66. if (!isIncluded || isExcluded) {
  67. return;
  68. }
  69. category.emojis.forEach(emojiId => pool[emojiId] = data.emojis[emojiId]);
  70. });
  71. if (custom.length) {
  72. let customIsIncluded = include && include.length ? include.indexOf('custom') > -1 : true;
  73. let customIsExcluded = exclude && exclude.length ? exclude.indexOf('custom') > -1 : false;
  74. if (customIsIncluded && !customIsExcluded) {
  75. addCustomToPool(custom, pool);
  76. }
  77. }
  78. }
  79. allResults = values.map((value) => {
  80. let aPool = pool,
  81. aIndex = index,
  82. length = 0;
  83. for (let charIndex = 0; charIndex < value.length; charIndex++) {
  84. const char = value[charIndex];
  85. length++;
  86. aIndex[char] = aIndex[char] || {};
  87. aIndex = aIndex[char];
  88. if (!aIndex.results) {
  89. let scores = {};
  90. aIndex.results = [];
  91. aIndex.pool = {};
  92. for (let id in aPool) {
  93. let emoji = aPool[id],
  94. { search } = emoji,
  95. sub = value.substr(0, length),
  96. subIndex = search.indexOf(sub);
  97. if (subIndex !== -1) {
  98. let score = subIndex + 1;
  99. if (sub === id) score = 0;
  100. aIndex.results.push(emojisList[id]);
  101. aIndex.pool[id] = emoji;
  102. scores[id] = score;
  103. }
  104. }
  105. aIndex.results.sort((a, b) => {
  106. let aScore = scores[a.id],
  107. bScore = scores[b.id];
  108. return aScore - bScore;
  109. });
  110. }
  111. aPool = aIndex.pool;
  112. }
  113. return aIndex.results;
  114. }).filter(a => a);
  115. if (allResults.length > 1) {
  116. results = intersect.apply(null, allResults);
  117. } else if (allResults.length) {
  118. results = allResults[0];
  119. } else {
  120. results = [];
  121. }
  122. }
  123. if (results) {
  124. if (emojisToShowFilter) {
  125. results = results.filter((result) => emojisToShowFilter(data.emojis[result.id]));
  126. }
  127. if (results && results.length > maxResults) {
  128. results = results.slice(0, maxResults);
  129. }
  130. }
  131. return results;
  132. }
  133. export { search };