]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/wp-emoji.js
WordPress 4.7-scripts
[autoinstalls/wordpress.git] / wp-includes / js / wp-emoji.js
1
2 ( function( window, settings ) {
3         function wpEmoji() {
4                 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
5
6                 // Compression and maintain local scope
7                 document = window.document,
8
9                 // Private
10                 twemoji, timer,
11                 loaded = false,
12                 count = 0,
13                 ie11 = window.navigator.userAgent.indexOf( 'Trident/7.0' ) > 0;
14
15                 /**
16                  * Detect if the browser supports SVG.
17                  *
18                  * @since 4.6.0
19                  *
20                  * @return {Boolean} True if the browser supports svg, false if not.
21                  */
22                 function browserSupportsSvgAsImage() {
23                         if ( !! document.implementation.hasFeature ) {
24                                 // Source: Modernizr
25                                 // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/svg/asimg.js
26                                 return document.implementation.hasFeature( 'http://www.w3.org/TR/SVG11/feature#Image', '1.1' );
27                         }
28
29                         // document.implementation.hasFeature is deprecated. It can be presumed
30                         // if future browsers remove it, the browser will support SVGs as images.
31                         return true;
32                 }
33
34                 /**
35                  * Runs when the document load event is fired, so we can do our first parse of the page.
36                  *
37                  * @since 4.2.0
38                  */
39                 function load() {
40                         if ( loaded ) {
41                                 return;
42                         }
43
44                         if ( typeof window.twemoji === 'undefined' ) {
45                                 // Break if waiting for longer than 30 sec.
46                                 if ( count > 600 ) {
47                                         return;
48                                 }
49
50                                 // Still waiting.
51                                 window.clearTimeout( timer );
52                                 timer = window.setTimeout( load, 50 );
53                                 count++;
54
55                                 return;
56                         }
57
58                         twemoji = window.twemoji;
59                         loaded = true;
60
61                         if ( MutationObserver ) {
62                                 new MutationObserver( function( mutationRecords ) {
63                                         var i = mutationRecords.length,
64                                                 addedNodes, removedNodes, ii, node;
65
66                                         while ( i-- ) {
67                                                 addedNodes = mutationRecords[ i ].addedNodes;
68                                                 removedNodes = mutationRecords[ i ].removedNodes;
69                                                 ii = addedNodes.length;
70
71                                                 if (
72                                                         ii === 1 && removedNodes.length === 1 &&
73                                                         addedNodes[0].nodeType === 3 &&
74                                                         removedNodes[0].nodeName === 'IMG' &&
75                                                         addedNodes[0].data === removedNodes[0].alt &&
76                                                         'load-failed' === removedNodes[0].getAttribute( 'data-error' )
77                                                 ) {
78                                                         return;
79                                                 }
80
81                                                 while ( ii-- ) {
82                                                         node = addedNodes[ ii ];
83
84                                                         if ( node.nodeType === 3 ) {
85                                                                 if ( ! node.parentNode ) {
86                                                                         continue;
87                                                                 }
88
89                                                                 if ( ie11 ) {
90                                                                         /*
91                                                                          * IE 11's implementation of MutationObserver is buggy.
92                                                                          * It unnecessarily splits text nodes when it encounters a HTML
93                                                                          * template interpolation symbol ( "{{", for example ). So, we
94                                                                          * join the text nodes back together as a work-around.
95                                                                          */
96                                                                         while( node.nextSibling && 3 === node.nextSibling.nodeType ) {
97                                                                                 node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
98                                                                                 node.parentNode.removeChild( node.nextSibling );
99                                                                         }
100                                                                 }
101
102                                                                 node = node.parentNode;
103                                                         }
104
105                                                         if ( ! node || node.nodeType !== 1 ||
106                                                                 ( node.className && typeof node.className === 'string' && node.className.indexOf( 'wp-exclude-emoji' ) !== -1 ) ) {
107
108                                                                 continue;
109                                                         }
110
111                                                         if ( test( node.textContent ) ) {
112                                                                 parse( node );
113                                                         }
114                                                 }
115                                         }
116                                 } ).observe( document.body, {
117                                         childList: true,
118                                         subtree: true
119                                 } );
120                         }
121
122                         parse( document.body );
123                 }
124
125                 /**
126                  * Test if a text string contains emoji characters.
127                  *
128                  * @since 4.3.0
129                  *
130                  * @param {String} text The string to test
131                  *
132                  * @return {Boolean} Whether the string contains emoji characters.
133                  */
134                 function test( text ) {
135                         // Single char. U+20E3 to detect keycaps. U+00A9 "copyright sign" and U+00AE "registered sign" not included.
136                         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]/,
137                         // Surrogate pair range. Only tests for the second half.
138                         pair = /[\uDC00-\uDFFF]/;
139
140                         if ( text ) {
141                                 return  pair.test( text ) || single.test( text );
142                         }
143
144                         return false;
145                 }
146
147                 /**
148                  * Given an element or string, parse any emoji characters into Twemoji images.
149                  *
150                  * @since 4.2.0
151                  *
152                  * @param {HTMLElement|String} object The element or string to parse.
153                  * @param {Object} args Additional options for Twemoji.
154                  */
155                 function parse( object, args ) {
156                         var params;
157
158                         if ( settings.supports.everything || ! twemoji || ! object ||
159                                 ( 'string' !== typeof object && ( ! object.childNodes || ! object.childNodes.length ) ) ) {
160
161                                 return object;
162                         }
163
164                         args = args || {};
165                         params = {
166                                 base: browserSupportsSvgAsImage() ? settings.svgUrl : settings.baseUrl,
167                                 ext:  browserSupportsSvgAsImage() ? settings.svgExt : settings.ext,
168                                 className: args.className || 'emoji',
169                                 callback: function( icon, options ) {
170                                         // Ignore some standard characters that TinyMCE recommends in its character map.
171                                         switch ( icon ) {
172                                                 case 'a9':
173                                                 case 'ae':
174                                                 case '2122':
175                                                 case '2194':
176                                                 case '2660':
177                                                 case '2663':
178                                                 case '2665':
179                                                 case '2666':
180                                                         return false;
181                                         }
182
183                                         if ( settings.supports.everythingExceptFlag &&
184                                                 ! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) && // Country flags
185                                                 ! /^(1f3f3-fe0f-200d-1f308|1f3f4-200d-2620-fe0f)$/.test( icon )             // Rainbow and pirate flags
186                                         ) {
187                                                 return false;
188                                         }
189
190                                         return ''.concat( options.base, icon, options.ext );
191                                 },
192                                 onerror: function() {
193                                         if ( twemoji.parentNode ) {
194                                                 this.setAttribute( 'data-error', 'load-failed' );
195                                                 twemoji.parentNode.replaceChild( document.createTextNode( twemoji.alt ), twemoji );
196                                         }
197                                 }
198                         };
199
200                         if ( typeof args.imgAttr === 'object' ) {
201                                 params.attributes = function() {
202                                         return args.imgAttr;
203                                 };
204                         }
205
206                         return twemoji.parse( object, params );
207                 }
208
209                 /**
210                  * Initialize our emoji support, and set up listeners.
211                  */
212                 if ( settings ) {
213                         if ( settings.DOMReady ) {
214                                 load();
215                         } else {
216                                 settings.readyCallback = load;
217                         }
218                 }
219
220                 return {
221                         parse: parse,
222                         test: test
223                 };
224         }
225
226         window.wp = window.wp || {};
227         window.wp.emoji = new wpEmoji();
228
229 } )( window, window._wpemojiSettings );