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.

154 lines
3.8 KiB

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