masto-fe/app/javascript/mastodon/features/emoji/emoji_mart_search_light.js
2017-10-06 03:42:34 +02:00

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_mart_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 };