fix: use is-emoji-supported library (#2030)
* fix: use is-emoji-supported library * fix: add code comment
This commit is contained in:
parent
bb7ebb04bc
commit
7a28bd2d88
|
@ -69,6 +69,7 @@
|
||||||
"format-message-interpret": "^6.2.3",
|
"format-message-interpret": "^6.2.3",
|
||||||
"format-message-parse": "^6.2.3",
|
"format-message-parse": "^6.2.3",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
|
"is-emoji-supported": "^0.0.5",
|
||||||
"li": "^1.3.0",
|
"li": "^1.3.0",
|
||||||
"localstorage-memory": "^1.0.3",
|
"localstorage-memory": "^1.0.3",
|
||||||
"lodash-es": "4.17.15",
|
"lodash-es": "4.17.15",
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
// Copied from
|
|
||||||
// https://github.com/nolanlawson/emoji-picker-element/blob/04f490a/src/picker/utils/testColorEmojiSupported.js
|
|
||||||
|
|
||||||
import { FONT_FAMILY } from '../_static/fonts'
|
|
||||||
|
|
||||||
const getTextFeature = (text, color) => {
|
|
||||||
try {
|
|
||||||
const canvas = document.createElement('canvas')
|
|
||||||
canvas.width = canvas.height = 1
|
|
||||||
|
|
||||||
const ctx = canvas.getContext('2d')
|
|
||||||
ctx.textBaseline = 'top'
|
|
||||||
ctx.font = `100px ${FONT_FAMILY}`
|
|
||||||
ctx.fillStyle = color
|
|
||||||
ctx.scale(0.01, 0.01)
|
|
||||||
ctx.fillText(text, 0, 0)
|
|
||||||
|
|
||||||
return ctx.getImageData(0, 0, 1, 1).data
|
|
||||||
} catch (e) { /* ignore, return undefined */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
const compareFeatures = (feature1, feature2) => {
|
|
||||||
const feature1Str = [...feature1].join(',')
|
|
||||||
const feature2Str = [...feature2].join(',')
|
|
||||||
return feature1Str === feature2Str && feature1Str !== '0,0,0,0'
|
|
||||||
}
|
|
||||||
|
|
||||||
export function testColorEmojiSupported (text) {
|
|
||||||
// Render white and black and then compare them to each other and ensure they're the same
|
|
||||||
// color, and neither one is black. This shows that the emoji was rendered in color.
|
|
||||||
const feature1 = getTextFeature(text, '#000')
|
|
||||||
const feature2 = getTextFeature(text, '#fff')
|
|
||||||
|
|
||||||
const supported = feature1 && feature2 && compareFeatures(feature1, feature2)
|
|
||||||
if (!supported) {
|
|
||||||
console.log('Filtered unsupported emoji via color test', text)
|
|
||||||
}
|
|
||||||
return supported
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Return true if the unicode is rendered as a double character, e.g.
|
|
||||||
// "black cat" or "polar bar" or "person with red hair" or other emoji
|
|
||||||
// that look like double or triple emoji if the unicode is not rendered properly
|
|
||||||
|
|
||||||
const BASELINE_EMOJI = '😀'
|
|
||||||
|
|
||||||
let baselineWidth
|
|
||||||
|
|
||||||
export function testEmojiRenderedAtCorrectSize (unicode) {
|
|
||||||
if (!unicode.includes('\u200d')) { // ZWJ
|
|
||||||
return true // benefit of the doubt
|
|
||||||
}
|
|
||||||
|
|
||||||
let emojiTestDiv = document.getElementById('emoji-test')
|
|
||||||
if (!emojiTestDiv) {
|
|
||||||
emojiTestDiv = document.createElement('div')
|
|
||||||
emojiTestDiv.id = 'emoji-test'
|
|
||||||
emojiTestDiv.ariaHidden = true
|
|
||||||
Object.assign(emojiTestDiv.style, {
|
|
||||||
position: 'absolute',
|
|
||||||
opacity: '0',
|
|
||||||
'pointer-events': 'none',
|
|
||||||
'font-family': 'PinaforeEmoji',
|
|
||||||
'font-size': '14px',
|
|
||||||
contain: 'content'
|
|
||||||
})
|
|
||||||
document.body.appendChild(emojiTestDiv)
|
|
||||||
}
|
|
||||||
emojiTestDiv.textContent = unicode
|
|
||||||
const { width } = emojiTestDiv.getBoundingClientRect()
|
|
||||||
if (typeof baselineWidth === 'undefined') {
|
|
||||||
emojiTestDiv.textContent = BASELINE_EMOJI
|
|
||||||
baselineWidth = emojiTestDiv.getBoundingClientRect().width
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebKit has some imprecision here, so round it
|
|
||||||
const emojiSupported = width.toFixed(2) === baselineWidth.toFixed(2)
|
|
||||||
if (!emojiSupported) {
|
|
||||||
console.log('Filtered unsupported emoji via size test', unicode, 'width', width, 'baselineWidth', baselineWidth)
|
|
||||||
}
|
|
||||||
|
|
||||||
return emojiSupported
|
|
||||||
}
|
|
|
@ -1,17 +1,8 @@
|
||||||
import { testColorEmojiSupported } from './testColorEmojiSupported'
|
import { isEmojiSupported, setCacheHandler } from 'is-emoji-supported'
|
||||||
import { testEmojiRenderedAtCorrectSize } from './testEmojiRenderedAtCorrectSize'
|
|
||||||
import { QuickLRU } from '../_thirdparty/quick-lru/quick-lru'
|
import { QuickLRU } from '../_thirdparty/quick-lru/quick-lru'
|
||||||
|
|
||||||
// avoid recomputing emoji support over and over again
|
// avoid recomputing emoji support over and over again
|
||||||
const emojiSupportCache = new QuickLRU({
|
// use our own LRU since the built-in one grows forever, which is a small memory leak, but still
|
||||||
maxSize: 500
|
setCacheHandler(new QuickLRU({ maxSize: 500 }))
|
||||||
})
|
|
||||||
|
|
||||||
export function testEmojiSupported (unicode) {
|
export const testEmojiSupported = isEmojiSupported
|
||||||
let supported = emojiSupportCache.get(unicode)
|
|
||||||
if (typeof supported !== 'boolean') {
|
|
||||||
supported = !!(testColorEmojiSupported(unicode) && testEmojiRenderedAtCorrectSize(unicode))
|
|
||||||
emojiSupportCache.set(unicode, supported)
|
|
||||||
}
|
|
||||||
return supported
|
|
||||||
}
|
|
||||||
|
|
|
@ -4325,6 +4325,11 @@ is-electron@^2.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.0.tgz#8943084f09e8b731b3a7a0298a7b5d56f6b7eef0"
|
resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.0.tgz#8943084f09e8b731b3a7a0298a7b5d56f6b7eef0"
|
||||||
integrity sha512-SpMppC2XR3YdxSzczXReBjqs2zGscWQpBIKqwXYBFic0ERaxNVgwLCHwOLZeESfdJQjX0RDvrJ1lBXX2ij+G1Q==
|
integrity sha512-SpMppC2XR3YdxSzczXReBjqs2zGscWQpBIKqwXYBFic0ERaxNVgwLCHwOLZeESfdJQjX0RDvrJ1lBXX2ij+G1Q==
|
||||||
|
|
||||||
|
is-emoji-supported@^0.0.5:
|
||||||
|
version "0.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-emoji-supported/-/is-emoji-supported-0.0.5.tgz#f22301b22c63d6322935e829f39dfa59d03a7fe2"
|
||||||
|
integrity sha512-WOlXUhDDHxYqcSmFZis+xWhhqXiK2SU0iYiqmth5Ip0FHLZQAt9rKL5ahnilE8/86WH8tZ3bmNNNC+bTzamqlw==
|
||||||
|
|
||||||
is-es2016-keyword@^1.0.0:
|
is-es2016-keyword@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz#f6e54e110c5e4f8d265e69d2ed0eaf8cf5f47718"
|
resolved "https://registry.yarnpkg.com/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz#f6e54e110c5e4f8d265e69d2ed0eaf8cf5f47718"
|
||||||
|
|
Loading…
Reference in a new issue