fix: add country flag emoji on windows (#2117)

* fix: add country flag emoji on windows

* fix: missing file

* fix: cache font file on-demand

* fix: attempt to fix

* fix: working

* fix: ordering

* fix: ordering

* fix: ordering

* fix: fixup

* fix: fixup

* fix: add comment

* fix: fix vercel

* fix: fix vercel.json

* fix: vercel

* refactor: refactor
This commit is contained in:
Nolan Lawson 2022-03-27 20:59:02 -07:00 committed by GitHub
parent fd6bb63450
commit f2d752bfc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 335 additions and 11 deletions

View file

@ -7,6 +7,7 @@ import { getIntl, trimWhitespace } from './getIntl.js'
const __dirname = path.dirname(new URL(import.meta.url).pathname) const __dirname = path.dirname(new URL(import.meta.url).pathname)
const readFile = promisify(fs.readFile) const readFile = promisify(fs.readFile)
const writeFile = promisify(fs.writeFile) const writeFile = promisify(fs.writeFile)
const copyFile = promisify(fs.copyFile)
// Try 'en-US' first, then 'en' if that doesn't exist // Try 'en-US' first, then 'en' if that doesn't exist
const PREFERRED_LOCALES = [LOCALE, LOCALE.split('-')[0]] const PREFERRED_LOCALES = [LOCALE, LOCALE.split('-')[0]]
@ -63,10 +64,20 @@ async function buildManifestJson () {
) )
} }
async function buildFlagEmojiFile () {
await copyFile(path.resolve(
__dirname,
'../node_modules/country-flag-emoji-polyfill/dist/TwemojiCountryFlags.woff2'
), path.resolve(
__dirname, '../static/TwemojiCountryFlags.woff2'
))
}
async function main () { async function main () {
await Promise.all([ await Promise.all([
buildEmojiI18nFile(), buildEmojiI18nFile(),
buildManifestJson() buildManifestJson(),
buildFlagEmojiFile()
]) ])
} }

View file

@ -51,7 +51,7 @@ const JSON_TEMPLATE = {
} }
}, },
{ {
src: '^/.*\\.(png|css|json|svg|jpe?g|map|txt|gz|webapp)$', src: '^/.*\\.(png|css|json|svg|jpe?g|map|txt|gz|webapp|woff|woff2)$',
headers: { headers: {
'cache-control': 'public,max-age=3600' 'cache-control': 'public,max-age=3600'
} }

View file

@ -61,6 +61,7 @@
"chokidar": "^3.5.3", "chokidar": "^3.5.3",
"circular-dependency-plugin": "^5.2.2", "circular-dependency-plugin": "^5.2.2",
"compression": "^1.7.4", "compression": "^1.7.4",
"country-flag-emoji-polyfill": "^0.1.1",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"css-dedoupe": "^0.1.1", "css-dedoupe": "^0.1.1",
"emoji-picker-element": "^1.11.1", "emoji-picker-element": "^1.11.1",

View file

@ -98,7 +98,7 @@
fill: var(--deemphasized-text-color); fill: var(--deemphasized-text-color);
} }
.compose-autosuggest-list-item-native-emoji { .compose-autosuggest-list-item-native-emoji {
font-family: PinaforeEmoji; font-family: CountryFlagEmojiPolyfill, PinaforeEmoji;
font-size: 32px; font-size: 32px;
line-height: 1; line-height: 1;
display: flex; display: flex;

View file

@ -0,0 +1,30 @@
import { polyfillCountryFlagEmojis } from 'country-flag-emoji-polyfill'
import { store } from '../store.js'
let polyfilled = false
const COUNTRY_FLAG_FONT_URL = '/TwemojiCountryFlags.woff2'
export function countryFlagEmojiPolyfill () {
if (!polyfilled) {
polyfilled = true
const numStylesBefore = document.head.querySelectorAll('style').length
polyfillCountryFlagEmojis('Twemoji Mozilla', COUNTRY_FLAG_FONT_URL)
const numStylesAfter = document.head.querySelectorAll('style').length
// if a style was added, then the polyfill was activated
const polyfillActivated = numStylesAfter !== numStylesBefore
if (polyfillActivated) {
const style = document.createElement('style')
style.textContent = `
@font-face {
font-family: CountryFlagEmojiPolyfill;
src: url(${JSON.stringify(COUNTRY_FLAG_FONT_URL)});
}
`
document.head.appendChild(style)
// "Twemoji Mozilla" is for emoji-picker-element, since it lists that font first.
// "CountryFlagEmojiPolyfill" is for us so we can set it before everything else in our own font family lists.
}
store.set({ polyfilledCountryFlagEmoji: polyfillActivated })
}
}

View file

@ -9,6 +9,7 @@ import { cleanup } from './cleanup.js'
import { wordFilterObservers } from './wordFilterObservers.js' import { wordFilterObservers } from './wordFilterObservers.js'
import { showComposeDialogObservers } from './showComposeDialogObservers.js' import { showComposeDialogObservers } from './showComposeDialogObservers.js'
import { badgeObservers } from './badgeObservers.js' import { badgeObservers } from './badgeObservers.js'
import { countryFlagEmojiPolyfill } from './countryFlagEmojiPolyfill.js'
// These observers can be lazy-loaded when the user is actually logged in. // These observers can be lazy-loaded when the user is actually logged in.
// Prevents circular dependencies and reduces the size of main.js // Prevents circular dependencies and reduces the size of main.js
@ -24,4 +25,5 @@ export function loggedInObservers () {
showComposeDialogObservers() showComposeDialogObservers()
badgeObservers() badgeObservers()
cleanup() cleanup()
countryFlagEmojiPolyfill()
} }

View file

@ -1,8 +1,280 @@
import { isEmojiSupported, setCacheHandler } from 'is-emoji-supported' import { isEmojiSupported, setCacheHandler } from 'is-emoji-supported'
import { QuickLRU } from '../_thirdparty/quick-lru/quick-lru.js' import { QuickLRU } from '../_thirdparty/quick-lru/quick-lru.js'
import { store } from '../_store/store.js'
// avoid recomputing emoji support over and over again // avoid recomputing emoji support over and over again
// use our own LRU since the built-in one grows forever, which is a small memory leak, but still // use our own LRU since the built-in one grows forever, which is a small memory leak, but still
setCacheHandler(new QuickLRU({ maxSize: 500 })) setCacheHandler(new QuickLRU({ maxSize: 500 }))
export const testEmojiSupported = isEmojiSupported const COUNTRY_FLAG_EMOJI = new Set(
[
'🇦🇨',
'🇦🇩',
'🇦🇪',
'🇦🇫',
'🇦🇬',
'🇦🇮',
'🇦🇱',
'🇦🇲',
'🇦🇴',
'🇦🇶',
'🇦🇷',
'🇦🇸',
'🇦🇹',
'🇦🇺',
'🇦🇼',
'🇦🇽',
'🇦🇿',
'🇧🇦',
'🇧🇧',
'🇧🇩',
'🇧🇪',
'🇧🇫',
'🇧🇬',
'🇧🇭',
'🇧🇮',
'🇧🇯',
'🇧🇱',
'🇧🇲',
'🇧🇳',
'🇧🇴',
'🇧🇶',
'🇧🇷',
'🇧🇸',
'🇧🇹',
'🇧🇻',
'🇧🇼',
'🇧🇾',
'🇧🇿',
'🇨🇦',
'🇨🇨',
'🇨🇩',
'🇨🇫',
'🇨🇬',
'🇨🇭',
'🇨🇮',
'🇨🇰',
'🇨🇱',
'🇨🇲',
'🇨🇳',
'🇨🇴',
'🇨🇵',
'🇨🇷',
'🇨🇺',
'🇨🇻',
'🇨🇼',
'🇨🇽',
'🇨🇾',
'🇨🇿',
'🇩🇪',
'🇩🇬',
'🇩🇯',
'🇩🇰',
'🇩🇲',
'🇩🇴',
'🇩🇿',
'🇪🇦',
'🇪🇨',
'🇪🇪',
'🇪🇬',
'🇪🇭',
'🇪🇷',
'🇪🇸',
'🇪🇹',
'🇪🇺',
'🇫🇮',
'🇫🇯',
'🇫🇰',
'🇫🇲',
'🇫🇴',
'🇫🇷',
'🇬🇦',
'🇬🇧',
'🇬🇩',
'🇬🇪',
'🇬🇫',
'🇬🇬',
'🇬🇭',
'🇬🇮',
'🇬🇱',
'🇬🇲',
'🇬🇳',
'🇬🇵',
'🇬🇶',
'🇬🇷',
'🇬🇸',
'🇬🇹',
'🇬🇺',
'🇬🇼',
'🇬🇾',
'🇭🇰',
'🇭🇲',
'🇭🇳',
'🇭🇷',
'🇭🇹',
'🇭🇺',
'🇮🇨',
'🇮🇩',
'🇮🇪',
'🇮🇱',
'🇮🇲',
'🇮🇳',
'🇮🇴',
'🇮🇶',
'🇮🇷',
'🇮🇸',
'🇮🇹',
'🇯🇪',
'🇯🇲',
'🇯🇴',
'🇯🇵',
'🇰🇪',
'🇰🇬',
'🇰🇭',
'🇰🇮',
'🇰🇲',
'🇰🇳',
'🇰🇵',
'🇰🇷',
'🇰🇼',
'🇰🇾',
'🇰🇿',
'🇱🇦',
'🇱🇧',
'🇱🇨',
'🇱🇮',
'🇱🇰',
'🇱🇷',
'🇱🇸',
'🇱🇹',
'🇱🇺',
'🇱🇻',
'🇱🇾',
'🇲🇦',
'🇲🇨',
'🇲🇩',
'🇲🇪',
'🇲🇫',
'🇲🇬',
'🇲🇭',
'🇲🇰',
'🇲🇱',
'🇲🇲',
'🇲🇳',
'🇲🇴',
'🇲🇵',
'🇲🇶',
'🇲🇷',
'🇲🇸',
'🇲🇹',
'🇲🇺',
'🇲🇻',
'🇲🇼',
'🇲🇽',
'🇲🇾',
'🇲🇿',
'🇳🇦',
'🇳🇨',
'🇳🇪',
'🇳🇫',
'🇳🇬',
'🇳🇮',
'🇳🇱',
'🇳🇴',
'🇳🇵',
'🇳🇷',
'🇳🇺',
'🇳🇿',
'🇴🇲',
'🇵🇦',
'🇵🇪',
'🇵🇫',
'🇵🇬',
'🇵🇭',
'🇵🇰',
'🇵🇱',
'🇵🇲',
'🇵🇳',
'🇵🇷',
'🇵🇸',
'🇵🇹',
'🇵🇼',
'🇵🇾',
'🇶🇦',
'🇷🇪',
'🇷🇴',
'🇷🇸',
'🇷🇺',
'🇷🇼',
'🇸🇦',
'🇸🇧',
'🇸🇨',
'🇸🇩',
'🇸🇪',
'🇸🇬',
'🇸🇭',
'🇸🇮',
'🇸🇯',
'🇸🇰',
'🇸🇱',
'🇸🇲',
'🇸🇳',
'🇸🇴',
'🇸🇷',
'🇸🇸',
'🇸🇹',
'🇸🇻',
'🇸🇽',
'🇸🇾',
'🇸🇿',
'🇹🇦',
'🇹🇨',
'🇹🇩',
'🇹🇫',
'🇹🇬',
'🇹🇭',
'🇹🇯',
'🇹🇰',
'🇹🇱',
'🇹🇲',
'🇹🇳',
'🇹🇴',
'🇹🇷',
'🇹🇹',
'🇹🇻',
'🇹🇼',
'🇹🇿',
'🇺🇦',
'🇺🇬',
'🇺🇲',
'🇺🇳',
'🇺🇸',
'🇺🇾',
'🇺🇿',
'🇻🇦',
'🇻🇨',
'🇻🇪',
'🇻🇬',
'🇻🇮',
'🇻🇳',
'🇻🇺',
'🇼🇫',
'🇼🇸',
'🇽🇰',
'🇾🇪',
'🇾🇹',
'🇿🇦',
'🇿🇲',
'🇿🇼',
'🏴󠁧󠁢󠁥󠁮󠁧󠁿',
'🏴󠁧󠁢󠁳󠁣󠁴󠁿',
'🏴󠁧󠁢󠁷󠁬󠁳󠁿'
]
)
export function testEmojiSupported (unicode) {
if (store.get().polyfilledCountryFlagEmoji && COUNTRY_FLAG_EMOJI.has(unicode)) {
return true // just assume it's supported; is-emoji-supported doesn't work in this case
}
return isEmojiSupported(unicode)
}

View file

@ -97,10 +97,6 @@ input, textarea {
color: inherit; color: inherit;
} }
textarea {
font-family: system-ui, -apple-system, PinaforeRegular, sans-serif, PinaforeEmoji;
}
button, .button { button, .button {
font-size: 1.2em; font-size: 1.2em;
background: var(--button-bg); background: var(--button-bg);
@ -164,7 +160,7 @@ input:required, input:invalid {
} }
textarea { textarea {
font-family: inherit; font-family: CountryFlagEmojiPolyfill, system-ui, -apple-system, PinaforeRegular, sans-serif, PinaforeEmoji;
font-size: inherit; font-size: inherit;
box-sizing: border-box; box-sizing: border-box;
} }
@ -208,5 +204,5 @@ textarea {
} }
.inline-emoji { .inline-emoji {
font-family: PinaforeEmoji, sans-serif; font-family: CountryFlagEmojiPolyfill, PinaforeEmoji, sans-serif;
} }

View file

@ -22,6 +22,10 @@ const ON_DEMAND_CACHE = [
{ {
regex: /\$polyfill\$/, regex: /\$polyfill\$/,
cache: WEBPACK_ASSETS cache: WEBPACK_ASSETS
},
{
regex: /TwemojiCountryFlags\.woff2/,
cache: ASSETS
} }
] ]
@ -34,6 +38,7 @@ const assets = __assets__
.filter(filename => !filename.endsWith('.webapp')) // KaiOS manifest .filter(filename => !filename.endsWith('.webapp')) // KaiOS manifest
.filter(filename => !/emoji-.*?\.json$/.test(filename)) // useless to cache; it already goes in IndexedDB .filter(filename => !/emoji-.*?\.json$/.test(filename)) // useless to cache; it already goes in IndexedDB
.filter(filename => !/screenshot-.*?\.png/.test(filename)) // only used during PWA installation, don't bother caching .filter(filename => !/screenshot-.*?\.png/.test(filename)) // only used during PWA installation, don't bother caching
.filter(filename => !/TwemojiCountryFlags\.woff2/.test(filename)) // cache on-demand
// `shell` is an array of all the files generated by webpack // `shell` is an array of all the files generated by webpack
// also contains '/index.html' for some reason // also contains '/index.html' for some reason

Binary file not shown.

View file

@ -36,7 +36,7 @@
} }
}, },
{ {
"src": "^/.*\\.(png|css|json|svg|jpe?g|map|txt|gz|webapp)$", "src": "^/.*\\.(png|css|json|svg|jpe?g|map|txt|gz|webapp|woff|woff2)$",
"headers": { "headers": {
"cache-control": "public,max-age=3600" "cache-control": "public,max-age=3600"
} }

View file

@ -2415,6 +2415,13 @@ cosmiconfig@^7.0.0:
path-type "^4.0.0" path-type "^4.0.0"
yaml "^1.10.0" yaml "^1.10.0"
country-flag-emoji-polyfill@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/country-flag-emoji-polyfill/-/country-flag-emoji-polyfill-0.1.1.tgz#1fab7b364c2631f7e7949fbd98659552f401596e"
integrity sha512-H4iB8BAnlcLxE9mxVXm9vY28zKtqjEYRCO+vz1x4u6IsmomHQd/EQfR/Py0YmxeVYkBAOUPJBcY3KJPd+BQe6Q==
dependencies:
is-emoji-supported "^0.0.5"
cross-env@^7.0.3: cross-env@^7.0.3:
version "7.0.3" version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"