|
|
|
@ -1,11 +1,9 @@ |
|
|
|
|
// This code is largely borrowed from:
|
|
|
|
|
// https://github.com/missive/emoji-mart/blob/bbd4fbe/src/utils/index.js
|
|
|
|
|
// https://github.com/missive/emoji-mart/blob/5f2ffcc/src/utils/index.js
|
|
|
|
|
|
|
|
|
|
import data from './emoji_mart_data_light'; |
|
|
|
|
|
|
|
|
|
const COLONS_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/; |
|
|
|
|
|
|
|
|
|
function buildSearch(thisData) { |
|
|
|
|
const buildSearch = (data) => { |
|
|
|
|
const search = []; |
|
|
|
|
|
|
|
|
|
let addToSearch = (strings, split) => { |
|
|
|
@ -24,19 +22,68 @@ function buildSearch(thisData) { |
|
|
|
|
}); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
addToSearch(thisData.short_names, true); |
|
|
|
|
addToSearch(thisData.name, true); |
|
|
|
|
addToSearch(thisData.keywords, false); |
|
|
|
|
addToSearch(thisData.emoticons, false); |
|
|
|
|
addToSearch(data.short_names, true); |
|
|
|
|
addToSearch(data.name, true); |
|
|
|
|
addToSearch(data.keywords, false); |
|
|
|
|
addToSearch(data.emoticons, false); |
|
|
|
|
|
|
|
|
|
return search; |
|
|
|
|
} |
|
|
|
|
return search.join(','); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const _String = String; |
|
|
|
|
|
|
|
|
|
const stringFromCodePoint = _String.fromCodePoint || function () { |
|
|
|
|
let MAX_SIZE = 0x4000; |
|
|
|
|
let codeUnits = []; |
|
|
|
|
let highSurrogate; |
|
|
|
|
let lowSurrogate; |
|
|
|
|
let index = -1; |
|
|
|
|
let length = arguments.length; |
|
|
|
|
if (!length) { |
|
|
|
|
return ''; |
|
|
|
|
} |
|
|
|
|
let result = ''; |
|
|
|
|
while (++index < length) { |
|
|
|
|
let codePoint = Number(arguments[index]); |
|
|
|
|
if ( |
|
|
|
|
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
|
|
|
|
|
codePoint < 0 || // not a valid Unicode code point
|
|
|
|
|
codePoint > 0x10FFFF || // not a valid Unicode code point
|
|
|
|
|
Math.floor(codePoint) !== codePoint // not an integer
|
|
|
|
|
) { |
|
|
|
|
throw RangeError('Invalid code point: ' + codePoint); |
|
|
|
|
} |
|
|
|
|
if (codePoint <= 0xFFFF) { // BMP code point
|
|
|
|
|
codeUnits.push(codePoint); |
|
|
|
|
} else { // Astral code point; split in surrogate halves
|
|
|
|
|
// http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
|
|
|
|
codePoint -= 0x10000; |
|
|
|
|
highSurrogate = (codePoint >> 10) + 0xD800; |
|
|
|
|
lowSurrogate = (codePoint % 0x400) + 0xDC00; |
|
|
|
|
codeUnits.push(highSurrogate, lowSurrogate); |
|
|
|
|
} |
|
|
|
|
if (index + 1 === length || codeUnits.length > MAX_SIZE) { |
|
|
|
|
result += String.fromCharCode.apply(null, codeUnits); |
|
|
|
|
codeUnits.length = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const _JSON = JSON; |
|
|
|
|
|
|
|
|
|
const COLONS_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/; |
|
|
|
|
const SKINS = [ |
|
|
|
|
'1F3FA', '1F3FB', '1F3FC', |
|
|
|
|
'1F3FD', '1F3FE', '1F3FF', |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
function unifiedToNative(unified) { |
|
|
|
|
let unicodes = unified.split('-'), |
|
|
|
|
codePoints = unicodes.map((u) => `0x${u}`); |
|
|
|
|
|
|
|
|
|
return String.fromCodePoint(...codePoints); |
|
|
|
|
return stringFromCodePoint.apply(null, codePoints); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function sanitize(emoji) { |
|
|
|
@ -70,11 +117,11 @@ function sanitize(emoji) { |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getSanitizedData(emoji) { |
|
|
|
|
return sanitize(getData(emoji)); |
|
|
|
|
function getSanitizedData() { |
|
|
|
|
return sanitize(getData(...arguments)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getData(emoji) { |
|
|
|
|
function getData(emoji, skin, set) { |
|
|
|
|
let emojiData = {}; |
|
|
|
|
|
|
|
|
|
if (typeof emoji === 'string') { |
|
|
|
@ -83,6 +130,9 @@ function getData(emoji) { |
|
|
|
|
if (matches) { |
|
|
|
|
emoji = matches[1]; |
|
|
|
|
|
|
|
|
|
if (matches[2]) { |
|
|
|
|
skin = parseInt(matches[2]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (data.short_names.hasOwnProperty(emoji)) { |
|
|
|
@ -92,17 +142,6 @@ function getData(emoji) { |
|
|
|
|
if (data.emojis.hasOwnProperty(emoji)) { |
|
|
|
|
emojiData = data.emojis[emoji]; |
|
|
|
|
} |
|
|
|
|
} else if (emoji.custom) { |
|
|
|
|
emojiData = emoji; |
|
|
|
|
|
|
|
|
|
emojiData.search = buildSearch({ |
|
|
|
|
short_names: emoji.short_names, |
|
|
|
|
name: emoji.name, |
|
|
|
|
keywords: emoji.keywords, |
|
|
|
|
emoticons: emoji.emoticons, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
emojiData.search = emojiData.search.join(','); |
|
|
|
|
} else if (emoji.id) { |
|
|
|
|
if (data.short_names.hasOwnProperty(emoji.id)) { |
|
|
|
|
emoji.id = data.short_names[emoji.id]; |
|
|
|
@ -110,31 +149,110 @@ function getData(emoji) { |
|
|
|
|
|
|
|
|
|
if (data.emojis.hasOwnProperty(emoji.id)) { |
|
|
|
|
emojiData = data.emojis[emoji.id]; |
|
|
|
|
skin = skin || emoji.skin; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!Object.keys(emojiData).length) { |
|
|
|
|
emojiData = emoji; |
|
|
|
|
emojiData.custom = true; |
|
|
|
|
|
|
|
|
|
if (!emojiData.search) { |
|
|
|
|
emojiData.search = buildSearch(emoji); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
emojiData.emoticons = emojiData.emoticons || []; |
|
|
|
|
emojiData.variations = emojiData.variations || []; |
|
|
|
|
|
|
|
|
|
if (emojiData.skin_variations && skin > 1 && set) { |
|
|
|
|
emojiData = JSON.parse(_JSON.stringify(emojiData)); |
|
|
|
|
|
|
|
|
|
let skinKey = SKINS[skin - 1], |
|
|
|
|
variationData = emojiData.skin_variations[skinKey]; |
|
|
|
|
|
|
|
|
|
if (!variationData.variations && emojiData.variations) { |
|
|
|
|
delete emojiData.variations; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (variationData[`has_img_${set}`]) { |
|
|
|
|
emojiData.skin_tone = skin; |
|
|
|
|
|
|
|
|
|
for (let k in variationData) { |
|
|
|
|
let v = variationData[k]; |
|
|
|
|
emojiData[k] = v; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (emojiData.variations && emojiData.variations.length) { |
|
|
|
|
emojiData = JSON.parse(JSON.stringify(emojiData)); |
|
|
|
|
emojiData = JSON.parse(_JSON.stringify(emojiData)); |
|
|
|
|
emojiData.unified = emojiData.variations.shift(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return emojiData; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function uniq(arr) { |
|
|
|
|
return arr.reduce((acc, item) => { |
|
|
|
|
if (acc.indexOf(item) === -1) { |
|
|
|
|
acc.push(item); |
|
|
|
|
} |
|
|
|
|
return acc; |
|
|
|
|
}, []); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function intersect(a, b) { |
|
|
|
|
let set; |
|
|
|
|
let list; |
|
|
|
|
if (a.length < b.length) { |
|
|
|
|
set = new Set(a); |
|
|
|
|
list = b; |
|
|
|
|
} else { |
|
|
|
|
set = new Set(b); |
|
|
|
|
list = a; |
|
|
|
|
const uniqA = uniq(a); |
|
|
|
|
const uniqB = uniq(b); |
|
|
|
|
|
|
|
|
|
return uniqA.filter(item => uniqB.indexOf(item) >= 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function deepMerge(a, b) { |
|
|
|
|
let o = {}; |
|
|
|
|
|
|
|
|
|
for (let key in a) { |
|
|
|
|
let originalValue = a[key], |
|
|
|
|
value = originalValue; |
|
|
|
|
|
|
|
|
|
if (b.hasOwnProperty(key)) { |
|
|
|
|
value = b[key]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (typeof value === 'object') { |
|
|
|
|
value = deepMerge(originalValue, value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
o[key] = value; |
|
|
|
|
} |
|
|
|
|
return Array.from(new Set(list.filter(x => set.has(x)))); |
|
|
|
|
|
|
|
|
|
return o; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// https://github.com/sonicdoe/measure-scrollbar
|
|
|
|
|
function measureScrollbar() { |
|
|
|
|
const div = document.createElement('div'); |
|
|
|
|
|
|
|
|
|
div.style.width = '100px'; |
|
|
|
|
div.style.height = '100px'; |
|
|
|
|
div.style.overflow = 'scroll'; |
|
|
|
|
div.style.position = 'absolute'; |
|
|
|
|
div.style.top = '-9999px'; |
|
|
|
|
|
|
|
|
|
document.body.appendChild(div); |
|
|
|
|
const scrollbarWidth = div.offsetWidth - div.clientWidth; |
|
|
|
|
document.body.removeChild(div); |
|
|
|
|
|
|
|
|
|
return scrollbarWidth; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export { getData, getSanitizedData, intersect }; |
|
|
|
|
export { |
|
|
|
|
getData, |
|
|
|
|
getSanitizedData, |
|
|
|
|
uniq, |
|
|
|
|
intersect, |
|
|
|
|
deepMerge, |
|
|
|
|
unifiedToNative, |
|
|
|
|
measureScrollbar, |
|
|
|
|
}; |
|
|
|
|