diff options
author | Nolan Lawson <nolan@nolanlawson.com> | 2017-10-07 03:17:02 -0700 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2017-10-07 12:17:02 +0200 |
commit | 057db0ecd0049c76c113cbe5412e098d686f0700 (patch) | |
tree | 0079a13c4b50d505554a1412f9459091b005f8b1 /app/javascript/mastodon/features/emoji/emoji_utils.js | |
parent | 11436358b4091c58532603adcd0f8b9d2e9e7775 (diff) |
Update emoji-mart to v2.1.1 (#5256)
Diffstat (limited to 'app/javascript/mastodon/features/emoji/emoji_utils.js')
-rw-r--r-- | app/javascript/mastodon/features/emoji/emoji_utils.js | 190 |
1 files changed, 154 insertions, 36 deletions
diff --git a/app/javascript/mastodon/features/emoji/emoji_utils.js b/app/javascript/mastodon/features/emoji/emoji_utils.js index 2742185d9..dbf725c1f 100644 --- a/app/javascript/mastodon/features/emoji/emoji_utils.js +++ b/app/javascript/mastodon/features/emoji/emoji_utils.js @@ -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, +}; |