Skip to content

Instantly share code, notes, and snippets.

@valterlorran
Last active June 8, 2023 12:14
Show Gist options
  • Select an option

  • Save valterlorran/426bc6ba2aaa47c17991cbf56a5f5661 to your computer and use it in GitHub Desktop.

Select an option

Save valterlorran/426bc6ba2aaa47c17991cbf56a5f5661 to your computer and use it in GitHub Desktop.
emoji-loader.js without async functions
(function (window, document, settings) {
var src, ii, tests;
let sessionSupports;
let sessionUpdated = false;
const sessionStorageKey = "wpEmojiSettingsSupports";
// Create a promise for DOMContentLoaded since the worker logic may finish after the event has fired.
const domReadyPromise = new Promise(function (resolve) {
document.addEventListener("DOMContentLoaded", resolve, { once: true });
});
/**
* Checks if two sets of Emoji characters render the same visually.
*
* @since 4.9.0
*
* @private
*
* @param {CanvasRenderingContext2D} context 2D Context.
* @param {string} set1 Set of Emoji to test.
* @param {string} set2 Set of Emoji to test.
*
* @return {boolean} True if the two sets render the same.
*/
function emojiSetsRenderIdentically( context, set1, set2 ) {
// Cleanup from previous test.
context.clearRect( 0, 0, context.canvas.width, context.canvas.height );
context.fillText( set1, 0, 0 );
var rendered1 = context.getImageData(
0,
0,
context.canvas.width,
context.canvas.height
).data;
// Cleanup from previous test.
context.clearRect( 0, 0, context.canvas.width, context.canvas.height );
context.fillText( set2, 0, 0 );
var rendered2 = context.getImageData(
0,
0,
context.canvas.width,
context.canvas.height
).data;
return rendered1.every(function (pixel, index) {
return pixel === rendered2[index];
});
}
/**
* Determines if the browser properly renders Emoji that Twemoji can supplement.
*
* @since 4.2.0
*
* @private
*
* @param {string} type Whether to test for support of "flag" or "emoji".
*
* @return {boolean} True if the browser can render emoji, false if it cannot.
*/
function browserSupportsEmoji( type ) {
var isIdentical, canvas, context;
/*
* Chrome on OS X added native emoji rendering in M41. Unfortunately,
* it doesn't work when the font is bolder than 500 weight. So, we
* check for bold rendering support to avoid invisible emoji in Chrome.
*/
if (
typeof WorkerGlobalScope !== "undefined" &&
self instanceof WorkerGlobalScope &&
typeof OffscreenCanvas !== "undefined"
) {
canvas = new OffscreenCanvas(300, 150); // Dimensions are default for HTMLCanvasElement.
} else {
canvas = document.createElement("canvas");
}
context = canvas.getContext('2d', { willReadFrequently: true });
context.textBaseline = 'top';
context.font = '600 32px Arial';
switch ( type ) {
case 'flag':
/*
* Test for Transgender flag compatibility. Added in Unicode 13.
*
* To test for support, we try to render it, and compare the rendering to how it would look if
* the browser doesn't render it correctly (white flag emoji + transgender symbol).
*/
isIdentical = emojiSetsRenderIdentically(
context,
'\uD83C\uDFF3\uFE0F\u200D\u26A7\uFE0F', // as a zero-width joiner sequence
'\uD83C\uDFF3\uFE0F\u200B\u26A7\uFE0F' // separated by a zero-width space
);
if ( isIdentical ) {
return false;
}
/*
* Test for UN flag compatibility. This is the least supported of the letter locale flags,
* so gives us an easy test for full support.
*
* To test for support, we try to render it, and compare the rendering to how it would look if
* the browser doesn't render it correctly ([U] + [N]).
*/
isIdentical = emojiSetsRenderIdentically(
context,
'\uD83C\uDDFA\uD83C\uDDF3', // as the sequence of two code points
'\uD83C\uDDFA\u200B\uD83C\uDDF3' // as the two code points separated by a zero-width space
);
if ( isIdentical ) {
return false;
}
/*
* Test for English flag compatibility. England is a country in the United Kingdom, it
* does not have a two letter locale code but rather a five letter sub-division code.
*
* To test for support, we try to render it, and compare the rendering to how it would look if
* the browser doesn't render it correctly (black flag emoji + [G] + [B] + [E] + [N] + [G]).
*/
isIdentical = emojiSetsRenderIdentically(
context,
// as the flag sequence
'\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F',
// with each code point separated by a zero-width space
'\uD83C\uDFF4\u200B\uDB40\uDC67\u200B\uDB40\uDC62\u200B\uDB40\uDC65\u200B\uDB40\uDC6E\u200B\uDB40\uDC67\u200B\uDB40\uDC7F'
);
return ! isIdentical;
case 'emoji':
/*
* Why can't we be friends? Everyone can now shake hands in emoji, regardless of skin tone!
*
* To test for Emoji 14.0 support, try to render a new emoji: Handshake: Light Skin Tone, Dark Skin Tone.
*
* The Handshake: Light Skin Tone, Dark Skin Tone emoji is a ZWJ sequence combining 🫱 Rightwards Hand,
* 🏻 Light Skin Tone, a Zero Width Joiner, 🫲 Leftwards Hand, and 🏿 Dark Skin Tone.
*
* 0x1FAF1 == Rightwards Hand
* 0x1F3FB == Light Skin Tone
* 0x200D == Zero-Width Joiner (ZWJ) that links the code points for the new emoji or
* 0x200B == Zero-Width Space (ZWS) that is rendered for clients not supporting the new emoji.
* 0x1FAF2 == Leftwards Hand
* 0x1F3FF == Dark Skin Tone.
*
* When updating this test for future Emoji releases, ensure that individual emoji that make up the
* sequence come from older emoji standards.
*/
isIdentical = emojiSetsRenderIdentically(
context,
'\uD83E\uDEF1\uD83C\uDFFB\u200D\uD83E\uDEF2\uD83C\uDFFF', // as the zero-width joiner sequence
'\uD83E\uDEF1\uD83C\uDFFB\u200B\uD83E\uDEF2\uD83C\uDFFF' // separated by a zero-width space
);
return ! isIdentical;
}
return false;
}
function browserSupportsEmojiOptimized(type) {
return new Promise(function (resolve) {
if (typeof OffscreenCanvas !== "undefined") {
const blob = new Blob([
emojiSetsRenderIdentically.toString() +
browserSupportsEmoji.toString() +
'postMessage(browserSupportsEmoji(' + JSON.stringify(type) + '))',
],
{ type: "text/javascript" }
);
const worker = new Worker(URL.createObjectURL(blob));
worker.onmessage = function (event) {
resolve(event.data);
};
} else {
resolve(browserSupportsEmoji(type));
}
});
}
function addScript(src) {
var script = document.createElement("script");
script.src = src;
script.defer = script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
}
tests = Array("flag", "emoji");
settings.supports = {
everything: true,
everythingExceptFlag: true,
};
if (
typeof sessionStorage !== "undefined" &&
sessionStorageKey in sessionStorage
) {
try {
sessionSupports = JSON.parse(sessionStorage.getItem(sessionStorageKey));
Object.assign(settings.supports, sessionSupports);
} catch (e) {
sessionSupports = {};
}
} else {
sessionSupports = {};
}
function testNextEmoji(index) {
if (index >= tests.length) {
if (sessionUpdated && typeof sessionStorage !== "undefined") {
try {
sessionStorage.setItem(
sessionStorageKey,
JSON.stringify(sessionSupports)
);
} catch (e) {}
}
return Promise.resolve();
}
const test = tests[index];
if (!(test in sessionSupports)) {
return browserSupportsEmojiOptimized(test).then(function (result) {
sessionSupports[test] = result;
settings.supports[test] = sessionSupports[test];
sessionUpdated = true;
settings.supports.everything =
settings.supports.everything && settings.supports[test];
if ("flag" !== test) {
settings.supports.everythingExceptFlag =
settings.supports.everythingExceptFlag && settings.supports[test];
}
return testNextEmoji(index + 1);
});
} else {
settings.supports.everything =
settings.supports.everything && settings.supports[test];
if ("flag" !== test) {
settings.supports.everythingExceptFlag =
settings.supports.everythingExceptFlag && settings.supports[test];
}
return testNextEmoji(index + 1);
}
}
function testEmojis() {
return testNextEmoji(0);
}
testEmojis()
.then(function () {
settings.supports.everythingExceptFlag =
settings.supports.everythingExceptFlag && !settings.supports.flag;
if (!settings.supports.everything) {
return domReadyPromise.then(function () {
settings.readyCallback();
src = settings.source || {};
if (src.concatemoji) {
addScript(src.concatemoji);
} else if (src.wpemoji && src.twemoji) {
addScript(src.twemoji);
addScript(src.wpemoji);
}
});
}
})
.catch(function (error) {
console.error(error);
});
})(window, document, window._wpemojiSettings);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment