Emoji: Clean up the emoji browser support tests.

As new sets of emoji are added to Unicode, and browsers add support for them at random intervals, we'll inevitably need to add new tests to the emoji loader. This change makes it much easier to add new tests as they're needed.

Fixes #35300.



git-svn-id: https://develop.svn.wordpress.org/trunk@36816 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Gary Pendergast 2016-03-03 05:16:53 +00:00
parent fa4b1164c3
commit 637ea44652
2 changed files with 51 additions and 41 deletions

View File

@ -1,5 +1,5 @@
( function( window, document, settings ) {
var src, ready;
var src, ready, ii, tests;
/**
* Detect if the browser supports rendering emoji or flag emoji. Flag emoji are a single glyph
@ -7,7 +7,7 @@
*
* @since 4.2.0
*
* @param type {String} Whether to test for support of "simple" or "flag" emoji.
* @param type {String} Whether to test for support of "simple", "flag", "diversity" or "unicode8" emoji.
* @return {Boolean} True if the browser can render emoji, false if it cannot.
*/
function browserSupportsEmoji( type ) {
@ -28,46 +28,48 @@
context.textBaseline = 'top';
context.font = '600 32px Arial';
if ( 'flag' === type ) {
/*
* This works because the image will be one of three things:
* - Two empty squares, if the browser doesn't render emoji
* - Two squares with 'A' and 'U' in them, if the browser doesn't render flag emoji
* - The Australian flag
*
* The first two will encode to small images (1-2KB data URLs), the third will encode
* to a larger image (4-5KB data URL).
*/
context.fillText( stringFromCharCode( 55356, 56806, 55356, 56826 ), 0, 0 );
return canvas.toDataURL().length > 3000;
} else if ( 'diversity' === type ) {
/*
* This tests if the browser supports the Emoji Diversity specification, by rendering an
* emoji with no skin tone specified (in this case, Santa). It then adds a skin tone, and
* compares if the emoji rendering has changed.
*/
context.fillText( stringFromCharCode( 55356, 57221 ), 0, 0 );
tone = context.getImageData( 16, 16, 1, 1 ).data.toString();
context.fillText( stringFromCharCode( 55356, 57221, 55356, 57343 ), 0, 0 );
// Chrome has issues comparing arrays, so we compare it as a string, instead.
return tone !== context.getImageData( 16, 16, 1, 1 ).data.toString();
} else {
if ( 'simple' === type ) {
switch ( type ) {
case 'flag':
/*
* This works because the image will be one of three things:
* - Two empty squares, if the browser doesn't render emoji
* - Two squares with 'A' and 'U' in them, if the browser doesn't render flag emoji
* - The Australian flag
*
* The first two will encode to small images (1-2KB data URLs), the third will encode
* to a larger image (4-5KB data URL).
*/
context.fillText( stringFromCharCode( 55356, 56806, 55356, 56826 ), 0, 0 );
return canvas.toDataURL().length > 3000;
case 'diversity':
/*
* This tests if the browser supports the Emoji Diversity specification, by rendering an
* emoji with no skin tone specified (in this case, Santa). It then adds a skin tone, and
* compares if the emoji rendering has changed.
*/
context.fillText( stringFromCharCode( 55356, 57221 ), 0, 0 );
tone = context.getImageData( 16, 16, 1, 1 ).data.toString();
context.fillText( stringFromCharCode( 55356, 57221, 55356, 57343 ), 0, 0 );
// Chrome has issues comparing arrays, so we compare it as a string, instead.
return tone !== context.getImageData( 16, 16, 1, 1 ).data.toString();
case 'simple':
/*
* This creates a smiling emoji, and checks to see if there is any image data in the
* center pixel. In browsers that don't support emoji, the character will be rendered
* as an empty square, so the center pixel will be blank.
*/
context.fillText( stringFromCharCode( 55357, 56835 ), 0, 0 );
} else {
return context.getImageData( 16, 16, 1, 1 ).data[0] !== 0;
case 'unicode8':
/*
* To check for Unicode 8 support, let's try rendering the most important advancement
* that the Unicode Consortium have made in years: the burrito.
*/
context.fillText( stringFromCharCode( 55356, 57135 ), 0, 0 );
}
return context.getImageData( 16, 16, 1, 1 ).data[0] !== 0;
return context.getImageData( 16, 16, 1, 1 ).data[0] !== 0;
}
return false;
}
function addScript( src ) {
@ -78,19 +80,30 @@
document.getElementsByTagName( 'head' )[0].appendChild( script );
}
tests = Array( 'simple', 'flag', 'unicode8', 'diversity' );
settings.supports = {
simple: browserSupportsEmoji( 'simple' ),
flag: browserSupportsEmoji( 'flag' ),
unicode8: browserSupportsEmoji( 'unicode8' ),
diversity: browserSupportsEmoji( 'diversity' )
everything: true
};
for( ii = 0; ii < tests.length; ii++ ) {
settings.supports[ tests[ ii ] ] = browserSupportsEmoji( tests[ ii ] );
settings.supports.everything = settings.supports.everything && settings.supports[ tests[ ii ] ];
if ( 'flag' !== tests[ ii ] ) {
settings.supports.everythingExceptFlag = settings.supports.everythingExceptFlag && settings.supports[ tests[ ii ] ];
}
}
settings.supports.everythingExceptFlag = settings.supports.everythingExceptFlag && ! settings.supports.flag;
settings.DOMReady = false;
settings.readyCallback = function() {
settings.DOMReady = true;
};
if ( ! settings.supports.simple || ! settings.supports.flag || ! settings.supports.unicode8 || ! settings.supports.diversity ) {
if ( ! settings.supports.everything ) {
ready = function() {
settings.readyCallback();
};

View File

@ -124,7 +124,7 @@
function parse( object, args ) {
var params;
if ( ! replaceEmoji || ! twemoji || ! object ||
if ( settings.supports.everything || ! twemoji || ! object ||
( 'string' !== typeof object && ( ! object.childNodes || ! object.childNodes.length ) ) ) {
return object;
@ -136,6 +136,7 @@
ext: settings.ext,
className: args.className || 'emoji',
callback: function( icon, options ) {
var keys, ii;
// Ignore some standard characters that TinyMCE recommends in its character map.
switch ( icon ) {
case 'a9':
@ -149,8 +150,7 @@
return false;
}
if ( ! settings.supports.flag && settings.supports.simple && settings.supports.unicode8 && settings.supports.diversity &&
! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) ) {
if ( settings.supports.everythingExceptFlag && ! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) ) {
return false;
}
@ -178,8 +178,6 @@
* Initialize our emoji support, and set up listeners.
*/
if ( settings ) {
replaceEmoji = ! settings.supports.simple || ! settings.supports.flag || ! settings.supports.unicode8 || ! settings.supports.diversity;
if ( settings.DOMReady ) {
load();
} else {
@ -188,7 +186,6 @@
}
return {
replaceEmoji: replaceEmoji,
parse: parse,
test: test
};