X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/7f1521bf193b382565eb753043c161f4cb3fcda7..refs/tags/wordpress-4.3:/wp-includes/js/wp-emoji.js diff --git a/wp-includes/js/wp-emoji.js b/wp-includes/js/wp-emoji.js index 0ff3c6f6..4acf4342 100644 --- a/wp-includes/js/wp-emoji.js +++ b/wp-includes/js/wp-emoji.js @@ -3,24 +3,6 @@ function wpEmoji() { var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver, - /** - * Flag to determine if the browser and the OS support emoji. - * - * @since 4.2.0 - * - * @var Boolean - */ - supportsEmoji = false, - - /** - * Flag to determine if the browser and the OS support flag (two character) emoji. - * - * @since 4.2.0 - * - * @var Boolean - */ - supportsFlagEmoji = false, - /** * Flag to determine if we should replace emoji characters with images. * @@ -30,10 +12,9 @@ */ replaceEmoji = false, - isIE8 = window.navigator.userAgent.indexOf( 'IE 8' ) !== -1, - // Private twemoji, timer, + loaded = false, count = 0; /** @@ -42,6 +23,10 @@ * @since 4.2.0 */ function load() { + if ( loaded ) { + return; + } + if ( typeof window.twemoji === 'undefined' ) { // Break if waiting for longer than 30 sec. if ( count > 600 ) { @@ -57,23 +42,41 @@ } twemoji = window.twemoji; + loaded = true; if ( MutationObserver ) { new MutationObserver( function( mutationRecords ) { var i = mutationRecords.length, - ii, node; + addedNodes, removedNodes, ii, node; while ( i-- ) { - ii = mutationRecords[ i ].addedNodes.length; + addedNodes = mutationRecords[ i ].addedNodes; + removedNodes = mutationRecords[ i ].removedNodes; + ii = addedNodes.length; + + if ( + ii === 1 && removedNodes.length === 1 && + addedNodes[0].nodeType === 3 && + removedNodes[0].nodeName === 'IMG' && + addedNodes[0].data === removedNodes[0].alt + ) { + return; + } while ( ii-- ) { - node = mutationRecords[ i ].addedNodes[ ii ]; + node = addedNodes[ ii ]; if ( node.nodeType === 3 ) { node = node.parentNode; } - if ( node && node.nodeType === 1 ) { + if ( ! node || node.nodeType !== 1 || + ( node.className && typeof node.className === 'string' && node.className.indexOf( 'wp-exclude-emoji' ) !== -1 ) ) { + + continue; + } + + if ( test( node.textContent ) ) { parse( node ); } } @@ -87,6 +90,28 @@ parse( document.body ); } + /** + * Test if a text string contains emoji characters. + * + * @since 4.3.0 + * + * @param {String} text The string to test + * + * @return {Boolean} Whether the string contains emoji characters. + */ + function test( text ) { + // Single char. U+20E3 to detect keycaps. U+00A9 "copyright sign" and U+00AE "registered sign" not included. + var single = /[\u203C\u2049\u20E3\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2300\u231A\u231B\u2328\u2388\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638\u2639\u263A\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692\u2693\u2694\u2696\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753\u2754\u2755\u2757\u2763\u2764\u2795\u2796\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05\u2B06\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]/, + // Surrogate pair range. Only tests for the second half. + pair = /[\uDC00-\uDFFF]/; + + if ( text ) { + return pair.test( text ) || single.test( text ); + } + + return false; + } + /** * Given an element or string, parse any emoji characters into Twemoji images. * @@ -96,17 +121,19 @@ * @param {Object} args Additional options for Twemoji. */ function parse( object, args ) { - if ( ! replaceEmoji ) { + var params; + + if ( ! replaceEmoji || ! twemoji || ! object || + ( 'string' !== typeof object && ( ! object.childNodes || ! object.childNodes.length ) ) ) { + return object; } args = args || {}; - - return twemoji.parse( object, { + params = { base: settings.baseUrl, ext: settings.ext, className: args.className || 'emoji', - imgAttr: args.imgAttr, callback: function( icon, options ) { // Ignore some standard characters that TinyMCE recommends in its character map. switch ( icon ) { @@ -121,7 +148,7 @@ return false; } - if ( ! supportsFlagEmoji && supportsEmoji && + if ( ! settings.supports.flag && settings.supports.simple && ! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) ) { return false; @@ -129,38 +156,34 @@ return ''.concat( options.base, icon, options.ext ); } - } ); - } + }; - // Load when the readyState changes to 'interactive', not 'complete'. - function onLoad() { - if ( ( ! isIE8 && 'interactive' === document.readyState ) || ( isIE8 && 'complete' === document.readyState ) ) { - load(); + if ( typeof args.imgAttr === 'object' ) { + params.attributes = function() { + return args.imgAttr; + }; } + + return twemoji.parse( object, params ); } /** * Initialize our emoji support, and set up listeners. */ if ( settings ) { - supportsEmoji = window._wpemojiSettings.supports.simple; - supportsFlagEmoji = window._wpemojiSettings.supports.flag; - replaceEmoji = ! supportsEmoji || ! supportsFlagEmoji; - - if ( ( ! isIE8 && 'loading' === document.readyState ) || ( isIE8 && 'complete' !== document.readyState ) ) { - if ( document.addEventListener ) { - document.addEventListener( 'readystatechange', onLoad, false ); - } else if ( document.attachEvent ) { - document.attachEvent( 'onreadystatechange', onLoad ); - } - } else { + replaceEmoji = ! settings.supports.simple || ! settings.supports.flag; + + if ( settings.DOMReady ) { load(); + } else { + settings.readyCallback = load; } } return { replaceEmoji: replaceEmoji, - parse: parse + parse: parse, + test: test }; }