author | ymh <ymh.work@gmail.com> |
Tue, 15 Dec 2020 13:49:49 +0100 | |
changeset 16 | a86126ab1dd4 |
parent 9 | 177826044cd9 |
child 18 | be944660c56a |
permissions | -rw-r--r-- |
9 | 1 |
/** |
2 |
* @output wp-includes/js/wp-emoji-loader.js |
|
3 |
*/ |
|
4 |
||
5 | 5 |
( function( window, document, settings ) { |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
6 |
var src, ready, ii, tests; |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
7 |
|
9 | 8 |
// Create a canvas element for testing native browser support of emoji. |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
9 |
var canvas = document.createElement( 'canvas' ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
10 |
var context = canvas.getContext && canvas.getContext( '2d' ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
11 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
12 |
/** |
9 | 13 |
* Checks if two sets of Emoji characters render the same visually. |
14 |
* |
|
15 |
* @since 4.9.0 |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
16 |
* |
9 | 17 |
* @private |
18 |
* |
|
19 |
* @param {number[]} set1 Set of Emoji character codes. |
|
20 |
* @param {number[]} set2 Set of Emoji character codes. |
|
21 |
* |
|
22 |
* @return {boolean} True if the two sets render the same. |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
23 |
*/ |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
24 |
function emojiSetsRenderIdentically( set1, set2 ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
25 |
var stringFromCharCode = String.fromCharCode; |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
26 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
27 |
// Cleanup from previous test. |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
28 |
context.clearRect( 0, 0, canvas.width, canvas.height ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
29 |
context.fillText( stringFromCharCode.apply( this, set1 ), 0, 0 ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
30 |
var rendered1 = canvas.toDataURL(); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
31 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
32 |
// Cleanup from previous test. |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
33 |
context.clearRect( 0, 0, canvas.width, canvas.height ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
34 |
context.fillText( stringFromCharCode.apply( this, set2 ), 0, 0 ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
35 |
var rendered2 = canvas.toDataURL(); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
36 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
37 |
return rendered1 === rendered2; |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
38 |
} |
5 | 39 |
|
40 |
/** |
|
9 | 41 |
* Detects if the browser supports rendering emoji or flag emoji. |
42 |
* |
|
43 |
* Flag emoji are a single glyph made of two characters, so some browsers |
|
44 |
* (notably, Firefox OS X) don't support them. |
|
5 | 45 |
* |
46 |
* @since 4.2.0 |
|
47 |
* |
|
9 | 48 |
* @private |
49 |
* |
|
50 |
* @param {string} type Whether to test for support of "flag" or "emoji". |
|
51 |
* |
|
52 |
* @return {boolean} True if the browser can render emoji, false if it cannot. |
|
5 | 53 |
*/ |
54 |
function browserSupportsEmoji( type ) { |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
55 |
var isIdentical; |
5 | 56 |
|
57 |
if ( ! context || ! context.fillText ) { |
|
58 |
return false; |
|
59 |
} |
|
60 |
||
61 |
/* |
|
62 |
* Chrome on OS X added native emoji rendering in M41. Unfortunately, |
|
63 |
* it doesn't work when the font is bolder than 500 weight. So, we |
|
64 |
* check for bold rendering support to avoid invisible emoji in Chrome. |
|
65 |
*/ |
|
66 |
context.textBaseline = 'top'; |
|
67 |
context.font = '600 32px Arial'; |
|
68 |
||
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
69 |
switch ( type ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
70 |
case 'flag': |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
71 |
/* |
16 | 72 |
* Test for Transgender flag compatibility. This flag is shortlisted for the Emoji 13 spec, |
73 |
* but has landed in Twemoji early, so we can add support for it, too. |
|
74 |
* |
|
75 |
* To test for support, we try to render it, and compare the rendering to how it would look if |
|
76 |
* the browser doesn't render it correctly (white flag emoji + transgender symbol). |
|
77 |
*/ |
|
78 |
isIdentical = emojiSetsRenderIdentically( |
|
79 |
[ 0x1F3F3, 0xFE0F, 0x200D, 0x26A7, 0xFE0F ], |
|
80 |
[ 0x1F3F3, 0xFE0F, 0x200B, 0x26A7, 0xFE0F ] |
|
81 |
); |
|
82 |
||
83 |
if ( isIdentical ) { |
|
84 |
return false; |
|
85 |
} |
|
86 |
||
87 |
/* |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
88 |
* Test for UN flag compatibility. This is the least supported of the letter locale flags, |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
89 |
* so gives us an easy test for full support. |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
90 |
* |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
91 |
* To test for support, we try to render it, and compare the rendering to how it would look if |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
92 |
* the browser doesn't render it correctly ([U] + [N]). |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
93 |
*/ |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
94 |
isIdentical = emojiSetsRenderIdentically( |
9 | 95 |
[ 0xD83C, 0xDDFA, 0xD83C, 0xDDF3 ], |
96 |
[ 0xD83C, 0xDDFA, 0x200B, 0xD83C, 0xDDF3 ] |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
97 |
); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
98 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
99 |
if ( isIdentical ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
100 |
return false; |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
101 |
} |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
102 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
103 |
/* |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
104 |
* Test for English flag compatibility. England is a country in the United Kingdom, it |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
105 |
* does not have a two letter locale code but rather an five letter sub-division code. |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
106 |
* |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
107 |
* To test for support, we try to render it, and compare the rendering to how it would look if |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
108 |
* the browser doesn't render it correctly (black flag emoji + [G] + [B] + [E] + [N] + [G]). |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
109 |
*/ |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
110 |
isIdentical = emojiSetsRenderIdentically( |
9 | 111 |
[ 0xD83C, 0xDFF4, 0xDB40, 0xDC67, 0xDB40, 0xDC62, 0xDB40, 0xDC65, 0xDB40, 0xDC6E, 0xDB40, 0xDC67, 0xDB40, 0xDC7F ], |
112 |
[ 0xD83C, 0xDFF4, 0x200B, 0xDB40, 0xDC67, 0x200B, 0xDB40, 0xDC62, 0x200B, 0xDB40, 0xDC65, 0x200B, 0xDB40, 0xDC6E, 0x200B, 0xDB40, 0xDC67, 0x200B, 0xDB40, 0xDC7F ] |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
113 |
); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
114 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
115 |
return ! isIdentical; |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
116 |
case 'emoji': |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
117 |
/* |
16 | 118 |
* So easy, even a baby could do it! |
119 |
* |
|
120 |
* To test for Emoji 13 support, try to render a new emoji: Man Feeding Baby. |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
121 |
* |
16 | 122 |
* The Man Feeding Baby emoji is a ZWJ sequence combining 👨 Man, a Zero Width Joiner and 🍼 Baby Bottle. |
123 |
* |
|
124 |
* 0xD83D, 0xDC68 == Man emoji. |
|
125 |
* 0x200D == Zero-Width Joiner (ZWJ) that links the two code points for the new emoji or |
|
126 |
* 0x200B == Zero-Width Space (ZWS) that is rendered for clients not supporting the new emoji. |
|
127 |
* 0xD83C, 0xDF7C == Baby Bottle. |
|
9 | 128 |
* |
129 |
* When updating this test for future Emoji releases, ensure that individual emoji that make up the |
|
130 |
* sequence come from older emoji standards. |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
131 |
*/ |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
132 |
isIdentical = emojiSetsRenderIdentically( |
16 | 133 |
[0xD83D, 0xDC68, 0x200D, 0xD83C, 0xDF7C], |
134 |
[0xD83D, 0xDC68, 0x200B, 0xD83C, 0xDF7C] |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
135 |
); |
9 | 136 |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
137 |
return ! isIdentical; |
5 | 138 |
} |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
139 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
140 |
return false; |
5 | 141 |
} |
142 |
||
9 | 143 |
/** |
144 |
* Adds a script to the head of the document. |
|
145 |
* |
|
146 |
* @ignore |
|
147 |
* |
|
148 |
* @since 4.2.0 |
|
149 |
* |
|
150 |
* @param {Object} src The url where the script is located. |
|
151 |
* @return {void} |
|
152 |
*/ |
|
5 | 153 |
function addScript( src ) { |
154 |
var script = document.createElement( 'script' ); |
|
155 |
||
156 |
script.src = src; |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
157 |
script.defer = script.type = 'text/javascript'; |
5 | 158 |
document.getElementsByTagName( 'head' )[0].appendChild( script ); |
159 |
} |
|
160 |
||
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
161 |
tests = Array( 'flag', 'emoji' ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
162 |
|
5 | 163 |
settings.supports = { |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
164 |
everything: true, |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
165 |
everythingExceptFlag: true |
5 | 166 |
}; |
167 |
||
9 | 168 |
/* |
169 |
* Tests the browser support for flag emojis and other emojis, and adjusts the |
|
170 |
* support settings accordingly. |
|
171 |
*/ |
|
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
172 |
for( ii = 0; ii < tests.length; ii++ ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
173 |
settings.supports[ tests[ ii ] ] = browserSupportsEmoji( tests[ ii ] ); |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
174 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
175 |
settings.supports.everything = settings.supports.everything && settings.supports[ tests[ ii ] ]; |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
176 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
177 |
if ( 'flag' !== tests[ ii ] ) { |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
178 |
settings.supports.everythingExceptFlag = settings.supports.everythingExceptFlag && settings.supports[ tests[ ii ] ]; |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
179 |
} |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
180 |
} |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
181 |
|
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
182 |
settings.supports.everythingExceptFlag = settings.supports.everythingExceptFlag && ! settings.supports.flag; |
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
183 |
|
9 | 184 |
// Sets DOMReady to false and assigns a ready function to settings. |
5 | 185 |
settings.DOMReady = false; |
186 |
settings.readyCallback = function() { |
|
187 |
settings.DOMReady = true; |
|
188 |
}; |
|
189 |
||
9 | 190 |
// When the browser can not render everything we need to load a polyfill. |
7
cf61fcea0001
resynchronize code repo with production
ymh <ymh.work@gmail.com>
parents:
5
diff
changeset
|
191 |
if ( ! settings.supports.everything ) { |
5 | 192 |
ready = function() { |
193 |
settings.readyCallback(); |
|
194 |
}; |
|
195 |
||
9 | 196 |
/* |
197 |
* Cross-browser version of adding a dom ready event. |
|
198 |
*/ |
|
5 | 199 |
if ( document.addEventListener ) { |
200 |
document.addEventListener( 'DOMContentLoaded', ready, false ); |
|
201 |
window.addEventListener( 'load', ready, false ); |
|
202 |
} else { |
|
203 |
window.attachEvent( 'onload', ready ); |
|
204 |
document.attachEvent( 'onreadystatechange', function() { |
|
205 |
if ( 'complete' === document.readyState ) { |
|
206 |
settings.readyCallback(); |
|
207 |
} |
|
208 |
} ); |
|
209 |
} |
|
210 |
||
211 |
src = settings.source || {}; |
|
212 |
||
213 |
if ( src.concatemoji ) { |
|
214 |
addScript( src.concatemoji ); |
|
215 |
} else if ( src.wpemoji && src.twemoji ) { |
|
216 |
addScript( src.twemoji ); |
|
217 |
addScript( src.wpemoji ); |
|
218 |
} |
|
219 |
} |
|
220 |
||
221 |
} )( window, document, window._wpemojiSettings ); |