154 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // This code is largely borrowed from:
 | |
| // https://github.com/missive/emoji-mart/blob/bbd4fbe/src/utils/emoji-index.js
 | |
| 
 | |
| import data from './emoji_data_light';
 | |
| import { getData, getSanitizedData, intersect } from './emoji_utils';
 | |
| 
 | |
| let index = {};
 | |
| let emojisList = {};
 | |
| let emoticonsList = {};
 | |
| let previousInclude = [];
 | |
| let previousExclude = [];
 | |
| 
 | |
| for (let emoji in data.emojis) {
 | |
|   let emojiData = data.emojis[emoji],
 | |
|     { short_names, emoticons } = emojiData,
 | |
|     id = short_names[0];
 | |
| 
 | |
|   for (let emoticon of (emoticons || [])) {
 | |
|     if (!emoticonsList[emoticon]) {
 | |
|       emoticonsList[emoticon] = id;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   emojisList[id] = getSanitizedData(id);
 | |
| }
 | |
| 
 | |
| function search(value, { emojisToShowFilter, maxResults, include, exclude, custom = [] } = {}) {
 | |
|   maxResults = maxResults || 75;
 | |
|   include = include || [];
 | |
|   exclude = exclude || [];
 | |
| 
 | |
|   if (custom.length) {
 | |
|     for (const emoji of custom) {
 | |
|       data.emojis[emoji.id] = getData(emoji);
 | |
|       emojisList[emoji.id] = getSanitizedData(emoji);
 | |
|     }
 | |
| 
 | |
|     data.categories.push({
 | |
|       name: 'Custom',
 | |
|       emojis: custom.map(emoji => emoji.id),
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   let results = null;
 | |
|   let pool = data.emojis;
 | |
| 
 | |
|   if (value.length) {
 | |
|     if (value === '-' || value === '-1') {
 | |
|       return [emojisList['-1']];
 | |
|     }
 | |
| 
 | |
|     let values = value.toLowerCase().split(/[\s|,|\-|_]+/);
 | |
| 
 | |
|     if (values.length > 2) {
 | |
|       values = [values[0], values[1]];
 | |
|     }
 | |
| 
 | |
|     if (include.length || exclude.length) {
 | |
|       pool = {};
 | |
| 
 | |
|       if (previousInclude !== include.sort().join(',') || previousExclude !== exclude.sort().join(',')) {
 | |
|         previousInclude = include.sort().join(',');
 | |
|         previousExclude = exclude.sort().join(',');
 | |
|         index = {};
 | |
|       }
 | |
| 
 | |
|       for (let category of data.categories) {
 | |
|         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) {
 | |
|           continue;
 | |
|         }
 | |
| 
 | |
|         for (let emojiId of category.emojis) {
 | |
|           pool[emojiId] = data.emojis[emojiId];
 | |
|         }
 | |
|       }
 | |
|     } else if (previousInclude.length || previousExclude.length) {
 | |
|       index = {};
 | |
|     }
 | |
| 
 | |
|     let allResults = values.map((value) => {
 | |
|       let aPool = pool;
 | |
|       let aIndex = index;
 | |
|       let length = 0;
 | |
| 
 | |
|       for (let char of value.split('')) {
 | |
|         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.substr(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;
 | |
|     }).filter(a => a);
 | |
| 
 | |
|     if (allResults.length > 1) {
 | |
|       results = intersect(...allResults);
 | |
|     } else if (allResults.length) {
 | |
|       results = allResults[0];
 | |
|     } else {
 | |
|       results = [];
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (results) {
 | |
|     if (emojisToShowFilter) {
 | |
|       results = results.filter((result) => emojisToShowFilter(data.emojis[result.id].unified));
 | |
|     }
 | |
| 
 | |
|     if (results && results.length > maxResults) {
 | |
|       results = results.slice(0, maxResults);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return results;
 | |
| }
 | |
| 
 | |
| export { search };
 |