WordPress/wp-includes/js/wp-emoji.js

193 lines
4.8 KiB
JavaScript
Raw Normal View History

window.wp = window.wp || {};
( function( window, wp, twemoji, settings ) {
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
var emoji = {
/**
* Flag to determine if we should parse all emoji characters into Twemoji images.
*
* @since 4.2.0
*
* @var Boolean
*/
parseAllEmoji: false,
/**
* Flag to determine if we should consider parsing emoji characters into Twemoji images.
*
* @since 4.2.0
*
* @var Boolean
*/
parseEmoji: false,
/**
* Flag to determine if we should parse flag characters into Twemoji images.
*
* @since 4.2.0
*
* @var Boolean
*/
parseFlags: false,
/**
* Initialize our emoji support, and set up listeners.
*
* @since 4.2.0
*/
init: function() {
emoji.parseAllEmoji = ! emoji.browserSupportsEmoji();
emoji.parseFlags = ! emoji.browserSupportsFlagEmoji();
emoji.parseEmoji = emoji.parseAllEmoji || emoji.parseFlags;
if ( window.addEventListener ) {
window.addEventListener( 'load', emoji.load, false );
} else if ( window.attachEvent ) {
window.attachEvent( 'onload', emoji.load );
}
},
/**
* Runs when the document load event is fired, so we can do our first parse of the page.
*
* @since 4.2.0
*/
load: function() {
if ( MutationObserver ) {
new MutationObserver( function( mutationRecords ) {
var i = mutationRecords.length,
ii,
node;
while ( i-- ) {
ii = mutationRecords[ i ].addedNodes.length;
while ( ii-- ) {
node = mutationRecords[ i ].addedNodes[ ii ];
if ( node.nodeType === 3 ) {
node = node.parentNode;
}
if ( node && node.nodeType === 1 ) {
emoji.parse( node );
}
}
}
} )
.observe( document.body, {
childList: true,
subtree: true
} );
}
emoji.parse( document.body );
},
/**
* Detect if the browser supports rendering emoji.
*
* @since 4.2.0
*
* @return {Boolean} True if the browser can render emoji, false if it cannot.
*/
browserSupportsEmoji: function() {
var canvas = document.createElement( 'canvas' ),
context = canvas.getContext && canvas.getContext( '2d' );
if ( ! context || ! context.fillText ) {
return false;
}
/*
* 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.
*/
context.textBaseline = 'top';
context.font = '600 32px Arial';
context.fillText( String.fromCharCode( 55357, 56835 ), 0, 0 );
return context.getImageData( 16, 16, 1, 1 ).data[0] !== 0;
},
/**
* Detect if the browser supports rendering flag emoji. Flag emoji are a single glyph
* made of two characters, so some browsers (notably, Firefox OS X) don't support them.
*
* @since 4.2.0
*
* @return {Boolean} True if the browser renders flag characters as a flag glyph, false if it does not.
*/
browserSupportsFlagEmoji: function() {
var canvas = document.createElement( 'canvas' ),
context = canvas.getContext && canvas.getContext( '2d' );
if ( ! context || ! context.fillText ) {
return false;
}
context.textBaseline = 'top';
context.font = '32px Arial';
context.fillText( String.fromCharCode( 55356, 56812, 55356, 56807 ), 0, 0 );
/*
* This works because the image will be one of three things:
* - Two empty squares, if the browser doen't render emoji
* - Two squares with 'G' and 'B' in them, if the browser doen't render flag emoji
* - The British 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).
*/
return canvas.toDataURL().length > 3000;
},
/**
* Given an element or string, parse any emoji characters into Twemoji images.
*
* @since 4.2.0
*
* @param {HTMLElement|String} object The element or string to parse.
*/
parse: function( object ) {
if ( ! emoji.parseEmoji ) {
return object;
}
return twemoji.parse( object, {
base: settings.baseUrl,
ext: settings.ext,
callback: function( icon, options ) {
// Ignore some standard characters that TinyMCE recommends in its character map.
switch ( icon ) {
case 'a9':
case 'ae':
case '2122':
case '2194':
case '2660':
case '2663':
case '2665':
case '2666':
return false;
}
if ( emoji.parseFlags && ! emoji.parseAllEmoji &&
! /^1f1(?:e[6-9a-f]|f[1-9a-f])-1f1(?:e[6-9a-f]|f[1-9a-f])$/.test( icon ) ) {
return false;
}
return ''.concat( options.base, '/', icon, options.ext );
}
} );
}
};
emoji.init();
wp.emoji = emoji;
} )( window, window.wp, window.twemoji, window._wpemojiSettings );