// This code is largely borrowed from: // https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/emoji-index.js import data from './emoji_mart_data_light'; import { getData, getSanitizedData, uniq, intersect } from './emoji_utils'; let originalPool = {}; let index = {}; let emojisList = {}; let emoticonsList = {}; let customEmojisList = []; for (let emoji in data.emojis) { let emojiData = data.emojis[emoji]; let { short_names, emoticons } = emojiData; let id = short_names[0]; if (emoticons) { emoticons.forEach(emoticon => { if (emoticonsList[emoticon]) { return; } emoticonsList[emoticon] = id; }); } emojisList[id] = getSanitizedData(id); originalPool[id] = emojiData; } function clearCustomEmojis(pool) { customEmojisList.forEach((emoji) => { let emojiId = emoji.id || emoji.short_names[0]; delete pool[emojiId]; delete emojisList[emojiId]; }); } function addCustomToPool(custom, pool) { if (customEmojisList.length) clearCustomEmojis(pool); custom.forEach((emoji) => { let emojiId = emoji.id || emoji.short_names[0]; if (emojiId && !pool[emojiId]) { pool[emojiId] = getData(emoji); emojisList[emojiId] = getSanitizedData(emoji); } }); customEmojisList = custom; index = {}; } function search(value, { emojisToShowFilter, maxResults, include, exclude, custom } = {}) { if (custom !== undefined) { if (customEmojisList !== custom) addCustomToPool(custom, originalPool); } else { custom = []; } maxResults = maxResults || 75; include = include || []; exclude = exclude || []; let results = null, pool = originalPool; if (value.length) { if (value === '-' || value === '-1') { return [emojisList['-1']]; } let values = value.toLowerCase().split(/[\s|,\-_]+/), allResults = []; if (values.length > 2) { values = [values[0], values[1]]; } if (include.length || exclude.length) { pool = {}; data.categories.forEach(category => { let isIncluded = include && include.length ? include.indexOf(category.name.toLowerCase()) > -1 : true; let isExcluded = exclude && exclude.length ? exclude.indexOf(category.name.toLowerCase()) > -1 : false; if (!isIncluded || isExcluded) { return; } category.emojis.forEach(emojiId => pool[emojiId] = data.emojis[emojiId]); }); if (custom.length) { let customIsIncluded = include && include.length ? include.indexOf('custom') > -1 : true; let customIsExcluded = exclude && exclude.length ? exclude.indexOf('custom') > -1 : false; if (customIsIncluded && !customIsExcluded) { addCustomToPool(custom, pool); } } } const searchValue = (value) => { let aPool = pool, aIndex = index, length = 0; for (let charIndex = 0; charIndex < value.length; charIndex++) { const char = value[charIndex]; length++; aIndex[char] = aIndex[char] || {}; aIndex = aIndex[char]; if (!aIndex.results) { let scores = {}; aIndex.results = []; aIndex.pool = {}; for (let id in aPool) { let emoji = aPool[id], { search } = emoji, sub = value.slice(0, length), subIndex = search.indexOf(sub); if (subIndex !== -1) { let score = subIndex + 1; if (sub === id) score = 0; aIndex.results.push(emojisList[id]); aIndex.pool[id] = emoji; scores[id] = score; } } aIndex.results.sort((a, b) => { let aScore = scores[a.id], bScore = scores[b.id]; return aScore - bScore; }); } aPool = aIndex.pool; } return aIndex.results; }; if (values.length > 1) { results = searchValue(value); } else { results = []; } allResults = values.map(searchValue).filter(a => a); if (allResults.length > 1) { allResults = intersect.apply(null, allResults); } else if (allResults.length) { allResults = allResults[0]; } results = uniq(results.concat(allResults)); } if (results) { if (emojisToShowFilter) { results = results.filter((result) => emojisToShowFilter(data.emojis[result.id])); } if (results && results.length > maxResults) { results = results.slice(0, maxResults); } } return results; } export { search };