Diff: STRATO-apps/wordpress_03/app/wp-includes/js/wp-emoji.js

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + /**
2 + * wp-emoji.js is used to replace emoji with images in browsers when the browser
3 + * doesn't support emoji natively.
4 + *
5 + * @output wp-includes/js/wp-emoji.js
6 + */
7 +
8 + ( function( window, settings ) {
9 + /**
10 + * Replaces emoji with images when browsers don't support emoji.
11 + *
12 + * @since 4.2.0
13 + * @access private
14 + *
15 + * @class
16 + *
17 + * @see Twitter Emoji library
18 + * @link https://github.com/twitter/twemoji
19 + *
20 + * @return {Object} The wpEmoji parse and test functions.
21 + */
22 + function wpEmoji() {
23 + var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
24 +
25 + // Compression and maintain local scope.
26 + document = window.document,
27 +
28 + // Private.
29 + twemoji, timer,
30 + loaded = false,
31 + count = 0,
32 + ie11 = window.navigator.userAgent.indexOf( 'Trident/7.0' ) > 0;
33 +
34 + /**
35 + * Detect if the browser supports SVG.
36 + *
37 + * @since 4.6.0
38 + * @private
39 + *
40 + * @see Modernizr
41 + * @link https://github.com/Modernizr/Modernizr/blob/master/feature-detects/svg/asimg.js
42 + *
43 + * @return {boolean} True if the browser supports svg, false if not.
44 + */
45 + function browserSupportsSvgAsImage() {
46 + if ( !! document.implementation.hasFeature ) {
47 + return document.implementation.hasFeature( 'http://www.w3.org/TR/SVG11/feature#Image', '1.1' );
48 + }
49 +
50 + // document.implementation.hasFeature is deprecated. It can be presumed
51 + // if future browsers remove it, the browser will support SVGs as images.
52 + return true;
53 + }
54 +
55 + /**
56 + * Runs when the document load event is fired, so we can do our first parse of
57 + * the page.
58 + *
59 + * Listens to all the DOM mutations and checks for added nodes that contain
60 + * emoji characters and replaces those with twitter emoji images.
61 + *
62 + * @since 4.2.0
63 + * @private
64 + */
65 + function load() {
66 + if ( loaded ) {
67 + return;
68 + }
69 +
70 + // Ensure twemoji is available on the global window before proceeding.
71 + if ( typeof window.twemoji === 'undefined' ) {
72 + // Break if waiting for longer than 30 seconds.
73 + if ( count > 600 ) {
74 + return;
75 + }
76 +
77 + // Still waiting.
78 + window.clearTimeout( timer );
79 + timer = window.setTimeout( load, 50 );
80 + count++;
81 +
82 + return;
83 + }
84 +
85 + twemoji = window.twemoji;
86 + loaded = true;
87 +
88 + // Initialize the mutation observer, which checks all added nodes for
89 + // replaceable emoji characters.
90 + if ( MutationObserver ) {
91 + new MutationObserver( function( mutationRecords ) {
92 + var i = mutationRecords.length,
93 + addedNodes, removedNodes, ii, node;
94 +
95 + while ( i-- ) {
96 + addedNodes = mutationRecords[ i ].addedNodes;
97 + removedNodes = mutationRecords[ i ].removedNodes;
98 + ii = addedNodes.length;
99 +
100 + /*
101 + * Checks if an image has been replaced by a text element
102 + * with the same text as the alternate description of the replaced image.
103 + * (presumably because the image could not be loaded).
104 + * If it is, do absolutely nothing.
105 + *
106 + * Node type 3 is a TEXT_NODE.
107 + *
108 + * @link https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
109 + */
110 + if (
111 + ii === 1 && removedNodes.length === 1 &&
112 + addedNodes[0].nodeType === 3 &&
113 + removedNodes[0].nodeName === 'IMG' &&
114 + addedNodes[0].data === removedNodes[0].alt &&
115 + 'load-failed' === removedNodes[0].getAttribute( 'data-error' )
116 + ) {
117 + return;
118 + }
119 +
120 + // Loop through all the added nodes.
121 + while ( ii-- ) {
122 + node = addedNodes[ ii ];
123 +
124 + // Node type 3 is a TEXT_NODE.
125 + if ( node.nodeType === 3 ) {
126 + if ( ! node.parentNode ) {
127 + continue;
128 + }
129 +
130 + if ( ie11 ) {
131 + /*
132 + * IE 11's implementation of MutationObserver is buggy.
133 + * It unnecessarily splits text nodes when it encounters a HTML
134 + * template interpolation symbol ( "{{", for example ). So, we
135 + * join the text nodes back together as a work-around.
136 + *
137 + * Node type 3 is a TEXT_NODE.
138 + */
139 + while( node.nextSibling && 3 === node.nextSibling.nodeType ) {
140 + node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
141 + node.parentNode.removeChild( node.nextSibling );
142 + }
143 + }
144 +
145 + node = node.parentNode;
146 + }
147 +
148 + if ( test( node.textContent ) ) {
149 + parse( node );
150 + }
151 + }
152 + }
153 + } ).observe( document.body, {
154 + childList: true,
155 + subtree: true
156 + } );
157 + }
158 +
159 + parse( document.body );
160 + }
161 +
162 + /**
163 + * Tests if a text string contains emoji characters.
164 + *
165 + * @since 4.3.0
166 + *
167 + * @memberOf wp.emoji
168 + *
169 + * @param {string} text The string to test.
170 + *
171 + * @return {boolean} Whether the string contains emoji characters.
172 + */
173 + function test( text ) {
174 + // Single char. U+20E3 to detect keycaps. U+00A9 "copyright sign" and U+00AE "registered sign" not included.
175 + 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]/,
176 + // Surrogate pair range. Only tests for the second half.
177 + pair = /[\uDC00-\uDFFF]/;
178 +
179 + if ( text ) {
180 + return pair.test( text ) || single.test( text );
181 + }
182 +
183 + return false;
184 + }
185 +
186 + /**
187 + * Parses any emoji characters into Twemoji images.
188 + *
189 + * - When passed an element the emoji characters are replaced inline.
190 + * - When passed a string the emoji characters are replaced and the result is
191 + * returned.
192 + *
193 + * @since 4.2.0
194 + *
195 + * @memberOf wp.emoji
196 + *
197 + * @param {HTMLElement|string} object The element or string to parse.
198 + * @param {Object} args Additional options for Twemoji.
199 + *
200 + * @return {HTMLElement|string} A string where all emoji are now image tags of
201 + * emoji. Or the element that was passed as the first argument.
202 + */
203 + function parse( object, args ) {
204 + var params;
205 +
206 + /*
207 + * If the browser has full support, twemoji is not loaded or our
208 + * object is not what was expected, we do not parse anything.
209 + */
210 + if ( settings.supports.everything || ! twemoji || ! object ||
211 + ( 'string' !== typeof object && ( ! object.childNodes || ! object.childNodes.length ) ) ) {
212 +
213 + return object;
214 + }
215 +
216 + // Compose the params for the twitter emoji library.
217 + args = args || {};
218 + params = {
219 + base: browserSupportsSvgAsImage() ? settings.svgUrl : settings.baseUrl,
220 + ext: browserSupportsSvgAsImage() ? settings.svgExt : settings.ext,
221 + className: args.className || 'emoji',
222 + callback: function( icon, options ) {
223 + // Ignore some standard characters that TinyMCE recommends in its character map.
224 + switch ( icon ) {
225 + case 'a9':
226 + case 'ae':
227 + case '2122':
228 + case '2194':
229 + case '2660':
230 + case '2663':
231 + case '2665':
232 + case '2666':
233 + return false;
234 + }
235 +
236 + if ( settings.supports.everythingExceptFlag &&
237 + ! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) && // Country flags.
238 + ! /^(1f3f3-fe0f-200d-1f308|1f3f4-200d-2620-fe0f)$/.test( icon ) // Rainbow and pirate flags.
239 + ) {
240 + return false;
241 + }
242 +
243 + return ''.concat( options.base, icon, options.ext );
244 + },
245 + attributes: function() {
246 + return {
247 + role: 'img'
248 + };
249 + },
250 + onerror: function() {
251 + if ( twemoji.parentNode ) {
252 + this.setAttribute( 'data-error', 'load-failed' );
253 + twemoji.parentNode.replaceChild( document.createTextNode( twemoji.alt ), twemoji );
254 + }
255 + },
256 + doNotParse: function( node ) {
257 + if (
258 + node &&
259 + node.className &&
260 + typeof node.className === 'string' &&
261 + node.className.indexOf( 'wp-exclude-emoji' ) !== -1
262 + ) {
263 + // Do not parse this node. Emojis will not be replaced in this node and all sub-nodes.
264 + return true;
265 + }
266 +
267 + return false;
268 + }
269 + };
270 +
271 + if ( typeof args.imgAttr === 'object' ) {
272 + params.attributes = function() {
273 + return args.imgAttr;
274 + };
275 + }
276 +
277 + return twemoji.parse( object, params );
278 + }
279 +
280 + load();
281 +
282 + return {
283 + parse: parse,
284 + test: test
285 + };
286 + }
287 +
288 + window.wp = window.wp || {};
289 +
290 + /**
291 + * @namespace wp.emoji
292 + */
293 + window.wp.emoji = new wpEmoji();
294 +
295 + } )( window, window._wpemojiSettings );
296 +