diff options
Diffstat (limited to 'app/javascript/mastodon/emoji_index_light.js')
-rw-r--r-- | app/javascript/mastodon/emoji_index_light.js | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/app/javascript/mastodon/emoji_index_light.js b/app/javascript/mastodon/emoji_index_light.js new file mode 100644 index 000000000..0719eda5e --- /dev/null +++ b/app/javascript/mastodon/emoji_index_light.js @@ -0,0 +1,154 @@ +// 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 }; |