Latest Tweets Widget - Version 1.1.1

Version Description

  • Added emoji support
Download this release

Release Info

Developer timwhitlock
Plugin Icon 128x128 Latest Tweets Widget
Version 1.1.1
Comparing to
See all releases

Code changes from version 1.1.0 to 1.1.1

api/lib/twitter-api-emoji.php ADDED
File without changes
api/lib/twitter-api-utils.php CHANGED
@@ -180,16 +180,123 @@ function twitter_api_relative_date( $strdate ){
180
 
181
 
182
  /**
183
- * Clean four-byte Emoji icons out of tweet text.
184
  * MySQL utf8 columns cannot store four byte Unicode sequences
185
  */
186
- function twitter_api_strip_emoji( $text ){
187
  // four byte utf8: 11110www 10xxxxxx 10yyyyyy 10zzzzzz
188
  return preg_replace('/[\xF0-\xF7][\x80-\xBF]{3}/', '', $text );
189
  }
190
 
191
 
192
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  /**
194
  * Resolve shortened url fields via entities
195
  * @return string
180
 
181
 
182
  /**
183
+ * Clean four-byte characters out of tweet text, includes some emoji.
184
  * MySQL utf8 columns cannot store four byte Unicode sequences
185
  */
186
+ function twitter_api_strip_quadruple_bytes( $text ){
187
  // four byte utf8: 11110www 10xxxxxx 10yyyyyy 10zzzzzz
188
  return preg_replace('/[\xF0-\xF7][\x80-\xBF]{3}/', '', $text );
189
  }
190
 
191
 
192
 
193
+ /**
194
+ * Replace Emoji characters with embedded images.
195
+ * Should be run after htmlifying tweet and before stripping quadruple bytes
196
+ */
197
+ function twitter_api_replace_emoji( $text, $callback = 'twitter_api_replace_emoji_callback' ){
198
+ // do a quick sniff to save most tweets from any replacement
199
+ // these codes are common to the first byte in all emoji that *might* be matched
200
+ if( ! preg_match('/[\xF0\xE2-\xE3\x23-\x39]/', $text ) ){
201
+ return $text;
202
+ }
203
+ // To keep regexp simpler, protect common multibyte characters we want to keep
204
+ static $protect_keys, $protect_vals;
205
+ if( ! isset($protect_keys) ){
206
+ $protect = array (
207
+ '\\u2017' => "\xE2\x80\x98", // lsquo
208
+ '\\u2018' => "\xE2\x80\x99", // rsquo
209
+ '\\u201C' => "\xE2\x80\x9C", // ldquo
210
+ '\\u201D' => "\xE2\x80\x9D", // rdquo
211
+ );
212
+ $protect_keys = array_keys( $protect );
213
+ $protect_vals = array_values( $protect );
214
+ }
215
+ $text = str_replace( $protect_vals, $protect_keys, $text );
216
+ // Do Emoji replacement ad replace protected characters afterwards
217
+ $text = preg_replace_callback('/(?:\xF0\x9F\x87[\xA6-\xBA]\xF0\x9F\x87[\xA6-\xBA]|\xF0\x9F[\x80\x83\x85-\x86\x88-\x89\x8C-\x95\x97-\x9B][\x80-\xBF]|[\xE2-\xE3][\x80\x81\x84\x86\x8A\x8C\x8F\x93\x96-\x9E\xA4\xAC-\xAD][\x80-\x82\x84-\x9D\xA0-\xA6\xA8-\xAC\xB0\xB2-\xB6\xB9-\xBF]|[\x23-\x39]\xE2\x83\xA3)/', $callback, $text );
218
+ $text = str_replace( $protect_keys, $protect_vals, $text );
219
+ return $text;
220
+ }
221
+
222
+
223
+
224
+ /**
225
+ * Convert array of unicodes to hex string for use in URLs or class names
226
+ */
227
+ function twitter_api_implode_unicode( array $codes, $glue = '-' ){
228
+ foreach( $codes as $i => $n ){
229
+ $codes[$i] = sprintf('%04x', $n );
230
+ }
231
+ return implode( $glue, $codes );
232
+ }
233
+
234
+
235
+
236
+ /**
237
+ * Utility resolves UTF-8 bytes to array of code points
238
+ */
239
+ function twitter_api_utf8_array( $s ){
240
+ $a = array();
241
+ $len = strlen($s);
242
+ for( $i = 0; $i < $len; $i++ ){
243
+ $c = $s{ $i };
244
+ $n = ord( $c );
245
+ // 7-bit ASCII
246
+ if( 0 === ( $n & 128 ) ){
247
+ $a[] = $n;
248
+ unset( $t );
249
+ }
250
+ // Subsequent 10xxxxxx character
251
+ else if( isset($t) && ( $n & 192 ) === 128 ){
252
+ $t <<= 6;
253
+ $t |= ( $n & 63 );
254
+ }
255
+ // Leading char in 2 byte sequence "110xxxxx"
256
+ else if( ( $n & 224 ) === 192 ){
257
+ isset( $t ) and $a [] = $t;
258
+ $t = ( $n & 31 );
259
+ }
260
+ // Leading char in 3 byte sequence "1110xxxx"
261
+ else if( ( $n & 240 ) === 224 ){
262
+ isset( $t ) and $a [] = $t;
263
+ $t = ( $n & 15 );
264
+ }
265
+ // Leading char in 4 byte sequence "11110xxx"
266
+ else if( ( $n & 248 ) === 240 ){
267
+ isset( $t ) and $a [] = $t;
268
+ $t = ( $n & 7 );
269
+ }
270
+ else {
271
+ throw new Exception('Invalid utf8 string, unexpected character at offset '.$i);
272
+ }
273
+ }
274
+ // left over
275
+ isset( $t ) and $a [] = $t;
276
+ return $a;
277
+ }
278
+
279
+
280
+
281
+ /**
282
+ * Default Emoji replacement callback
283
+ * @internal
284
+ */
285
+ function twitter_api_replace_emoji_callback( array $match ){
286
+ try {
287
+ $codes = twitter_api_utf8_array( $match[0] );
288
+ $class = twitter_api_implode_unicode( $codes );
289
+ $html = '<img src="https://abs.twimg.com/emoji/v1/72x72/'.$class.'.png" style="width:1em;" class="emoji emoji-'.$class.'" />';
290
+ return $html;
291
+ }
292
+ catch( Exception $e ){
293
+ WP_DEBUG and trigger_error( $e->getMessage(), E_USER_WARNING );
294
+ return '';
295
+ }
296
+ }
297
+
298
+
299
+
300
  /**
301
  * Resolve shortened url fields via entities
302
  * @return string
api/test/bootstrap.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Unit test bootstrapper.
4
+ * This is nothing close to an accurate simulation of Wordpress environment, it's just for testing utils.
5
+ * @usage phpunit --colors --bootstrap bootstrap.php .
6
+ */
7
+
8
+ function is_admin(){
9
+ return false;
10
+ }
11
+
12
+ function esc_html( $text ){
13
+ return htmlspecialchars( $text, ENT_COMPAT, 'UTF-8' );
14
+ }
15
+
16
+ require __DIR__.'/../twitter-api.php';
17
+
18
+ twitter_api_include('utils','core');
api/test/utils/EmojiTest.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @group utils
4
+ * @group emoji
5
+ */
6
+ class EmojiTest extends PHPUnit_Framework_TestCase {
7
+
8
+
9
+ public function _replace_blank(){
10
+ return '';
11
+ }
12
+
13
+
14
+ private function get_all(){
15
+ static $emoji;
16
+ if( ! isset($emoji) ){
17
+ $emoji = include __DIR__.'/inc-emoji.php';
18
+ }
19
+ return $emoji;
20
+ }
21
+
22
+
23
+ /**
24
+ * Match every emoji character with simple replacement callback
25
+ */
26
+ public function testSingleMatches(){
27
+ $blanker = array( $this, '_replace_blank' );
28
+ foreach( $this->get_all() as $key => $raw ){
29
+ $replaced = twitter_api_replace_emoji( 'o'.$raw.'k', $blanker );
30
+ $this->assertEquals( 'ok', $replaced );
31
+ }
32
+ }
33
+
34
+
35
+ /**
36
+ * Match all emoji characters in single block
37
+ */
38
+ public function testTotalMatch(){
39
+ $blanker = array( $this, '_replace_blank' );
40
+ $splurge = implode( '', $this->get_all() );
41
+ $replaced = twitter_api_replace_emoji( 'o'.$splurge.'k', $blanker );
42
+ $this->assertEquals( 'ok', $replaced );
43
+ }
44
+
45
+
46
+ /**
47
+ * Convert matched bytes back to unicode string reference
48
+ */
49
+ public function testAllSequencesResolveUnicode(){
50
+ foreach( $this->get_all() as $key => $raw ){
51
+ $codes = twitter_api_utf8_array( $raw );
52
+ $ucode = twitter_api_implode_unicode( $codes );
53
+ $this->assertEquals( $key, $ucode );
54
+ }
55
+ }
56
+
57
+
58
+ /**
59
+ * Test default URL replacement
60
+ */
61
+ public function testDefaultUrlReplacement(){
62
+ foreach( $this->get_all() as $key => $raw ){
63
+ $html = twitter_api_replace_emoji( $raw );
64
+ $want = '<img src="https://abs.twimg.com/emoji/v1/72x72/'.$key.'.png" style="width:1em;" class="emoji emoji-'.$key.'" />';
65
+ $this->assertEquals( $want, $html );
66
+ }
67
+ }
68
+
69
+
70
+ /**
71
+ * Test false positives
72
+ */
73
+ public function testFancyQuotesIntact(){
74
+ $test = array (
75
+ 0x2018,
76
+ 0x2019,
77
+ 0x201C,
78
+ 0x201D,
79
+ );
80
+ $blanker = array( $this, '_replace_blank' );
81
+ foreach( $test as $code ){
82
+ $hex = sprintf('%04x', $code );
83
+ $leave = $this->utf8_chr( $code );
84
+ $bytes = $this->utf8_debug_string( $leave );
85
+ $intact = twitter_api_replace_emoji( $leave, $blanker );
86
+ $this->assertEquals( $leave, $intact, 'U+'.$hex.' wrongly matched: '.$bytes );
87
+ }
88
+ }
89
+
90
+
91
+
92
+ /**
93
+ * split a utf-8 string into a visual representation of single bytes
94
+ */
95
+ private function utf8_debug_string( $raw ){
96
+ $debug = array();
97
+ for( $i = 0; $i < strlen($raw); $i++ ){
98
+ $debug[] = sprintf( '\\x%0X', ord( $raw{$i} ) );
99
+ }
100
+ return implode('',$debug);
101
+ }
102
+
103
+
104
+
105
+ /**
106
+ * Encode a Unicode code point to a utf-8 encoded string
107
+ * @example functions/enc/utf8_chr.php
108
+ * @param int Unicode code point up to 0x10FFFF
109
+ * @return string multibyte character sequence
110
+ */
111
+ private function utf8_chr( $u ){
112
+ if( 127 === ( $u | 127 ) ){
113
+ // 7-bit ASCII
114
+ return chr( $u );
115
+ }
116
+ // Double byte sequence ( < 0x800 )
117
+ // 00000yyy yyzzzzzz ==> 110yyyyy 10zzzzzz
118
+ // if( $u < 0x800 ) {
119
+ if( 0 === ( $u & 0xFFFFF800 ) ){
120
+ $c = chr( $u & 63 | 128 ); // "10zzzzzz"
121
+ $c = chr( ($u>>=6) & 31 | 192 ) . $c; // "110yyyyy"
122
+ }
123
+ // Triple byte sequence ( < 0x10000 )
124
+ // xxxxyyyy yyzzzzzz ==> 1110xxxx 10yyyyyy 10zzzzzz
125
+ // else if( $u < 0x10000 ) {
126
+ else if( 0 === ( $u & 0xFFFF0000 ) ){
127
+ // Table 3-7 in the Unicode 5.0 standard disalows D800-DFFF:
128
+ //if( $u >= 0xD800 && $u <= 0xDFFF ){
129
+ // trigger_error("Unicode code point $u is invalid", E_USER_NOTICE );
130
+ //}
131
+ $c = chr( $u & 63 | 128 ); // "10zzzzzz"
132
+ $c = chr( ($u>>=6) & 63 | 128 ) . $c; // "10yyyyyy"
133
+ $c = chr( ($u>>=6) & 15 | 224 ) . $c; // "1110xxxx"
134
+ }
135
+ // Four byte sequence ( < 0x10FFFF )
136
+ // 000wwwxx xxxxyyyy yyzzzzzz ==> 11110www 10xxxxxx 10yyyyyy 10zzzzzz
137
+ // else if( $u <= 0x10FFFF ) {
138
+ else if( 0 === ( $u & 0xE0000000 ) ){
139
+ $c = chr( $u & 63 | 128 ); // "10zzzzzz"
140
+ $c = chr( ($u>>=6) & 63 | 128 ) . $c; // "10yyyyyy"
141
+ $c = chr( ($u>>=6) & 63 | 128 ) . $c; // "10xxxxxx"
142
+ $c = chr( ($u>>=6) & 7 | 240 ) . $c; // "11110www"
143
+ }
144
+ else {
145
+ // integer too big
146
+ trigger_error("Unicode code point too large, $u", E_USER_NOTICE );
147
+ $c = '?';
148
+ }
149
+ return $c;
150
+ }
151
+
152
+ }
153
+
154
+
api/test/utils/HtmlTest.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @group utils
4
+ * @group html
5
+ */
6
+ class HtmlTest extends PHPUnit_Framework_TestCase {
7
+
8
+
9
+ public function testUsersLink(){
10
+ $text = 'Hi @timwhitlock!';
11
+ $html = twitter_api_html( $text );
12
+ $want = 'Hi <a class="twitter-screen-name" href="https://twitter.com/timwhitlock" target="_blank" rel="nofollow">@timwhitlock</a>!';
13
+ $this->assertEquals( $want, $html );
14
+ }
15
+
16
+ }
17
+
18
+
api/test/utils/UnicodeTest.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @group utils
4
+ * @group utf8
5
+ */
6
+ class UnicodeTest extends PHPUnit_Framework_TestCase {
7
+
8
+ public function testAsciiPassThrough(){
9
+ $ints = twitter_api_utf8_array( 'abc' );
10
+ $this->assertEquals( array(97,98,99), $ints );
11
+ }
12
+
13
+
14
+ public function testTwoByteCharacter(){
15
+ // U+00A9 copyright symbol
16
+ $text = "\xC2\xA9";
17
+ $ints = twitter_api_utf8_array( $text );
18
+ $this->assertCount( 1, $ints );
19
+ $this->assertEquals( 0x00A9, $ints[0] );
20
+ }
21
+
22
+
23
+ public function testThreeByteCharacter(){
24
+ // U+2122 trademark symbol
25
+ $text = "\xE2\x84\xA2";
26
+ $ints = twitter_api_utf8_array( $text );
27
+ $this->assertCount( 1, $ints );
28
+ $this->assertEquals( 0x2122, $ints[0] );
29
+ }
30
+
31
+
32
+
33
+ }
api/test/utils/inc-emoji.php ADDED
@@ -0,0 +1,843 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return array (
3
+ '1f601' => '😁',
4
+ '1f602' => '😂',
5
+ '1f603' => '😃',
6
+ '1f604' => '😄',
7
+ '1f605' => '😅',
8
+ '1f606' => '😆',
9
+ '1f609' => '😉',
10
+ '1f60a' => '😊',
11
+ '1f60b' => '😋',
12
+ '1f60c' => '😌',
13
+ '1f60d' => '😍',
14
+ '1f60f' => '😏',
15
+ '1f612' => '😒',
16
+ '1f613' => '😓',
17
+ '1f614' => '😔',
18
+ '1f616' => '😖',
19
+ '1f618' => '😘',
20
+ '1f61a' => '😚',
21
+ '1f61c' => '😜',
22
+ '1f61d' => '😝',
23
+ '1f61e' => '😞',
24
+ '1f620' => '😠',
25
+ '1f621' => '😡',
26
+ '1f622' => '😢',
27
+ '1f623' => '😣',
28
+ '1f624' => '😤',
29
+ '1f625' => '😥',
30
+ '1f628' => '😨',
31
+ '1f629' => '😩',
32
+ '1f62a' => '😪',
33
+ '1f62b' => '😫',
34
+ '1f62d' => '😭',
35
+ '1f630' => '😰',
36
+ '1f631' => '😱',
37
+ '1f632' => '😲',
38
+ '1f633' => '😳',
39
+ '1f635' => '😵',
40
+ '1f637' => '😷',
41
+ '1f638' => '😸',
42
+ '1f639' => '😹',
43
+ '1f63a' => '😺',
44
+ '1f63b' => '😻',
45
+ '1f63c' => '😼',
46
+ '1f63d' => '😽',
47
+ '1f63e' => '😾',
48
+ '1f63f' => '😿',
49
+ '1f640' => '🙀',
50
+ '1f645' => '🙅',
51
+ '1f646' => '🙆',
52
+ '1f647' => '🙇',
53
+ '1f648' => '🙈',
54
+ '1f649' => '🙉',
55
+ '1f64a' => '🙊',
56
+ '1f64b' => '🙋',
57
+ '1f64c' => '🙌',
58
+ '1f64d' => '🙍',
59
+ '1f64e' => '🙎',
60
+ '1f64f' => '🙏',
61
+ 2702 => '✂',
62
+ 2705 => '✅',
63
+ 2708 => '✈',
64
+ 2709 => '✉',
65
+ '270a' => '✊',
66
+ '270b' => '✋',
67
+ '270c' => '✌',
68
+ '270f' => '✏',
69
+ 2712 => '✒',
70
+ 2714 => '✔',
71
+ 2716 => '✖',
72
+ 2728 => '✨',
73
+ 2733 => '✳',
74
+ 2734 => '✴',
75
+ 2744 => '❄',
76
+ 2747 => '❇',
77
+ '274c' => '❌',
78
+ '274e' => '❎',
79
+ 2753 => '❓',
80
+ 2754 => '❔',
81
+ 2755 => '❕',
82
+ 2757 => '❗',
83
+ 2764 => '❤',
84
+ 2795 => '➕',
85
+ 2796 => '➖',
86
+ 2797 => '➗',
87
+ '27a1' => '➡',
88
+ '27b0' => '➰',
89
+ '1f680' => '🚀',
90
+ '1f683' => '🚃',
91
+ '1f684' => '🚄',
92
+ '1f685' => '🚅',
93
+ '1f687' => '🚇',
94
+ '1f689' => '🚉',
95
+ '1f68c' => '🚌',
96
+ '1f68f' => '🚏',
97
+ '1f691' => '🚑',
98
+ '1f692' => '🚒',
99
+ '1f693' => '🚓',
100
+ '1f695' => '🚕',
101
+ '1f697' => '🚗',
102
+ '1f699' => '🚙',
103
+ '1f69a' => '🚚',
104
+ '1f6a2' => '🚢',
105
+ '1f6a4' => '🚤',
106
+ '1f6a5' => '🚥',
107
+ '1f6a7' => '🚧',
108
+ '1f6a8' => '🚨',
109
+ '1f6a9' => '🚩',
110
+ '1f6aa' => '🚪',
111
+ '1f6ab' => '🚫',
112
+ '1f6ac' => '🚬',
113
+ '1f6ad' => '🚭',
114
+ '1f6b2' => '🚲',
115
+ '1f6b6' => '🚶',
116
+ '1f6b9' => '🚹',
117
+ '1f6ba' => '🚺',
118
+ '1f6bb' => '🚻',
119
+ '1f6bc' => '🚼',
120
+ '1f6bd' => '🚽',
121
+ '1f6be' => '🚾',
122
+ '1f6c0' => '🛀',
123
+ '24c2' => 'Ⓜ',
124
+ '1f170' => '🅰',
125
+ '1f171' => '🅱',
126
+ '1f17e' => '🅾',
127
+ '1f17f' => '🅿',
128
+ '1f18e' => '🆎',
129
+ '1f191' => '🆑',
130
+ '1f192' => '🆒',
131
+ '1f193' => '🆓',
132
+ '1f194' => '🆔',
133
+ '1f195' => '🆕',
134
+ '1f196' => '🆖',
135
+ '1f197' => '🆗',
136
+ '1f198' => '🆘',
137
+ '1f199' => '🆙',
138
+ '1f19a' => '🆚',
139
+ '1f1e9-1f1ea' => '🇩🇪',
140
+ '1f1ec-1f1e7' => '🇬🇧',
141
+ '1f1e8-1f1f3' => '🇨🇳',
142
+ '1f1ef-1f1f5' => '🇯🇵',
143
+ '1f1f0-1f1f7' => '🇰🇷',
144
+ '1f1eb-1f1f7' => '🇫🇷',
145
+ '1f1ea-1f1f8' => '🇪🇸',
146
+ '1f1ee-1f1f9' => '🇮🇹',
147
+ '1f1fa-1f1f8' => '🇺🇸',
148
+ '1f1f7-1f1fa' => '🇷🇺',
149
+ '1f201' => '🈁',
150
+ '1f202' => '🈂',
151
+ '1f21a' => '🈚',
152
+ '1f22f' => '🈯',
153
+ '1f232' => '🈲',
154
+ '1f233' => '🈳',
155
+ '1f234' => '🈴',
156
+ '1f235' => '🈵',
157
+ '1f236' => '🈶',
158
+ '1f237' => '🈷',
159
+ '1f238' => '🈸',
160
+ '1f239' => '🈹',
161
+ '1f23a' => '🈺',
162
+ '1f250' => '🉐',
163
+ '1f251' => '🉑',
164
+ '203c' => '‼',
165
+ 2049 => '⁉',
166
+ '0038-20e3' => '8⃣',
167
+ '0039-20e3' => '9⃣',
168
+ '0037-20e3' => '7⃣',
169
+ '0036-20e3' => '6⃣',
170
+ '0031-20e3' => '1⃣',
171
+ '0030-20e3' => '0⃣',
172
+ '0032-20e3' => '2⃣',
173
+ '0033-20e3' => '3⃣',
174
+ '0035-20e3' => '5⃣',
175
+ '0034-20e3' => '4⃣',
176
+ '0023-20e3' => '#⃣',
177
+ 2122 => '™',
178
+ 2139 => 'ℹ',
179
+ 2194 => '↔',
180
+ 2195 => '↕',
181
+ 2196 => '↖',
182
+ 2197 => '↗',
183
+ 2198 => '↘',
184
+ 2199 => '↙',
185
+ '21a9' => '↩',
186
+ '21aa' => '↪',
187
+ '231a' => '⌚',
188
+ '231b' => '⌛',
189
+ '23e9' => '⏩',
190
+ '23ea' => '⏪',
191
+ '23eb' => '⏫',
192
+ '23ec' => '⏬',
193
+ '23f0' => '⏰',
194
+ '23f3' => '⏳',
195
+ '25aa' => '▪',
196
+ '25ab' => '▫',
197
+ '25b6' => '▶',
198
+ '25c0' => '◀',
199
+ '25fb' => '◻',
200
+ '25fc' => '◼',
201
+ '25fd' => '◽',
202
+ '25fe' => '◾',
203
+ 2600 => '☀',
204
+ 2601 => '☁',
205
+ '260e' => '☎',
206
+ 2611 => '☑',
207
+ 2614 => '☔',
208
+ 2615 => '☕',
209
+ '261d' => '☝',
210
+ '263a' => '☺',
211
+ 2648 => '♈',
212
+ 2649 => '♉',
213
+ '264a' => '♊',
214
+ '264b' => '♋',
215
+ '264c' => '♌',
216
+ '264d' => '♍',
217
+ '264e' => '♎',
218
+ '264f' => '♏',
219
+ 2650 => '♐',
220
+ 2651 => '♑',
221
+ 2652 => '♒',
222
+ 2653 => '♓',
223
+ 2660 => '♠',
224
+ 2663 => '♣',
225
+ 2665 => '♥',
226
+ 2666 => '♦',
227
+ 2668 => '♨',
228
+ '267b' => '♻',
229
+ '267f' => '♿',
230
+ 2693 => '⚓',
231
+ '26a0' => '⚠',
232
+ '26a1' => '⚡',
233
+ '26aa' => '⚪',
234
+ '26ab' => '⚫',
235
+ '26bd' => '⚽',
236
+ '26be' => '⚾',
237
+ '26c4' => '⛄',
238
+ '26c5' => '⛅',
239
+ '26ce' => '⛎',
240
+ '26d4' => '⛔',
241
+ '26ea' => '⛪',
242
+ '26f2' => '⛲',
243
+ '26f3' => '⛳',
244
+ '26f5' => '⛵',
245
+ '26fa' => '⛺',
246
+ '26fd' => '⛽',
247
+ 2934 => '⤴',
248
+ 2935 => '⤵',
249
+ '2b05' => '⬅',
250
+ '2b06' => '⬆',
251
+ '2b07' => '⬇',
252
+ '2b1b' => '⬛',
253
+ '2b1c' => '⬜',
254
+ '2b50' => '⭐',
255
+ '2b55' => '⭕',
256
+ 3030 => '〰',
257
+ '303d' => '〽',
258
+ 3297 => '㊗',
259
+ 3299 => '㊙',
260
+ '1f004' => '🀄',
261
+ '1f0cf' => '🃏',
262
+ '1f300' => '🌀',
263
+ '1f301' => '🌁',
264
+ '1f302' => '🌂',
265
+ '1f303' => '🌃',
266
+ '1f304' => '🌄',
267
+ '1f305' => '🌅',
268
+ '1f306' => '🌆',
269
+ '1f307' => '🌇',
270
+ '1f308' => '🌈',
271
+ '1f309' => '🌉',
272
+ '1f30a' => '🌊',
273
+ '1f30b' => '🌋',
274
+ '1f30c' => '🌌',
275
+ '1f30f' => '🌏',
276
+ '1f311' => '🌑',
277
+ '1f313' => '🌓',
278
+ '1f314' => '🌔',
279
+ '1f315' => '🌕',
280
+ '1f319' => '🌙',
281
+ '1f31b' => '🌛',
282
+ '1f31f' => '🌟',
283
+ '1f320' => '🌠',
284
+ '1f330' => '🌰',
285
+ '1f331' => '🌱',
286
+ '1f334' => '🌴',
287
+ '1f335' => '🌵',
288
+ '1f337' => '🌷',
289
+ '1f338' => '🌸',
290
+ '1f339' => '🌹',
291
+ '1f33a' => '🌺',
292
+ '1f33b' => '🌻',
293
+ '1f33c' => '🌼',
294
+ '1f33d' => '🌽',
295
+ '1f33e' => '🌾',
296
+ '1f33f' => '🌿',
297
+ '1f340' => '🍀',
298
+ '1f341' => '🍁',
299
+ '1f342' => '🍂',
300
+ '1f343' => '🍃',
301
+ '1f344' => '🍄',
302
+ '1f345' => '🍅',
303
+ '1f346' => '🍆',
304
+ '1f347' => '🍇',
305
+ '1f348' => '🍈',
306
+ '1f349' => '🍉',
307
+ '1f34a' => '🍊',
308
+ '1f34c' => '🍌',
309
+ '1f34d' => '🍍',
310
+ '1f34e' => '🍎',
311
+ '1f34f' => '🍏',
312
+ '1f351' => '🍑',
313
+ '1f352' => '🍒',
314
+ '1f353' => '🍓',
315
+ '1f354' => '🍔',
316
+ '1f355' => '🍕',
317
+ '1f356' => '🍖',
318
+ '1f357' => '🍗',
319
+ '1f358' => '🍘',
320
+ '1f359' => '🍙',
321
+ '1f35a' => '🍚',
322
+ '1f35b' => '🍛',
323
+ '1f35c' => '🍜',
324
+ '1f35d' => '🍝',
325
+ '1f35e' => '🍞',
326
+ '1f35f' => '🍟',
327
+ '1f360' => '🍠',
328
+ '1f361' => '🍡',
329
+ '1f362' => '🍢',
330
+ '1f363' => '🍣',
331
+ '1f364' => '🍤',
332
+ '1f365' => '🍥',
333
+ '1f366' => '🍦',
334
+ '1f367' => '🍧',
335
+ '1f368' => '🍨',
336
+ '1f369' => '🍩',
337
+ '1f36a' => '🍪',
338
+ '1f36b' => '🍫',
339
+ '1f36c' => '🍬',
340
+ '1f36d' => '🍭',
341
+ '1f36e' => '🍮',
342
+ '1f36f' => '🍯',
343
+ '1f370' => '🍰',
344
+ '1f371' => '🍱',
345
+ '1f372' => '🍲',
346
+ '1f373' => '🍳',
347
+ '1f374' => '🍴',
348
+ '1f375' => '🍵',
349
+ '1f376' => '🍶',
350
+ '1f377' => '🍷',
351
+ '1f378' => '🍸',
352
+ '1f379' => '🍹',
353
+ '1f37a' => '🍺',
354
+ '1f37b' => '🍻',
355
+ '1f380' => '🎀',
356
+ '1f381' => '🎁',
357
+ '1f382' => '🎂',
358
+ '1f383' => '🎃',
359
+ '1f384' => '🎄',
360
+ '1f385' => '🎅',
361
+ '1f386' => '🎆',
362
+ '1f387' => '🎇',
363
+ '1f388' => '🎈',
364
+ '1f389' => '🎉',
365
+ '1f38a' => '🎊',
366
+ '1f38b' => '🎋',
367
+ '1f38c' => '🎌',
368
+ '1f38d' => '🎍',
369
+ '1f38e' => '🎎',
370
+ '1f38f' => '🎏',
371
+ '1f390' => '🎐',
372
+ '1f391' => '🎑',
373
+ '1f392' => '🎒',
374
+ '1f393' => '🎓',
375
+ '1f3a0' => '🎠',
376
+ '1f3a1' => '🎡',
377
+ '1f3a2' => '🎢',
378
+ '1f3a3' => '🎣',
379
+ '1f3a4' => '🎤',
380
+ '1f3a5' => '🎥',
381
+ '1f3a6' => '🎦',
382
+ '1f3a7' => '🎧',
383
+ '1f3a8' => '🎨',
384
+ '1f3a9' => '🎩',
385
+ '1f3aa' => '🎪',
386
+ '1f3ab' => '🎫',
387
+ '1f3ac' => '🎬',
388
+ '1f3ad' => '🎭',
389
+ '1f3ae' => '🎮',
390
+ '1f3af' => '🎯',
391
+ '1f3b0' => '🎰',
392
+ '1f3b1' => '🎱',
393
+ '1f3b2' => '🎲',
394
+ '1f3b3' => '🎳',
395
+ '1f3b4' => '🎴',
396
+ '1f3b5' => '🎵',
397
+ '1f3b6' => '🎶',
398
+ '1f3b7' => '🎷',
399
+ '1f3b8' => '🎸',
400
+ '1f3b9' => '🎹',
401
+ '1f3ba' => '🎺',
402
+ '1f3bb' => '🎻',
403
+ '1f3bc' => '🎼',
404
+ '1f3bd' => '🎽',
405
+ '1f3be' => '🎾',
406
+ '1f3bf' => '🎿',
407
+ '1f3c0' => '🏀',
408
+ '1f3c1' => '🏁',
409
+ '1f3c2' => '🏂',
410
+ '1f3c3' => '🏃',
411
+ '1f3c4' => '🏄',
412
+ '1f3c6' => '🏆',
413
+ '1f3c8' => '🏈',
414
+ '1f3ca' => '🏊',
415
+ '1f3e0' => '🏠',
416
+ '1f3e1' => '🏡',
417
+ '1f3e2' => '🏢',
418
+ '1f3e3' => '🏣',
419
+ '1f3e5' => '🏥',
420
+ '1f3e6' => '🏦',
421
+ '1f3e7' => '🏧',
422
+ '1f3e8' => '🏨',
423
+ '1f3e9' => '🏩',
424
+ '1f3ea' => '🏪',
425
+ '1f3eb' => '🏫',
426
+ '1f3ec' => '🏬',
427
+ '1f3ed' => '🏭',
428
+ '1f3ee' => '🏮',
429
+ '1f3ef' => '🏯',
430
+ '1f3f0' => '🏰',
431
+ '1f40c' => '🐌',
432
+ '1f40d' => '🐍',
433
+ '1f40e' => '🐎',
434
+ '1f411' => '🐑',
435
+ '1f412' => '🐒',
436
+ '1f414' => '🐔',
437
+ '1f417' => '🐗',
438
+ '1f418' => '🐘',
439
+ '1f419' => '🐙',
440
+ '1f41a' => '🐚',
441
+ '1f41b' => '🐛',
442
+ '1f41c' => '🐜',
443
+ '1f41d' => '🐝',
444
+ '1f41e' => '🐞',
445
+ '1f41f' => '🐟',
446
+ '1f420' => '🐠',
447
+ '1f421' => '🐡',
448
+ '1f422' => '🐢',
449
+ '1f423' => '🐣',
450
+ '1f424' => '🐤',
451
+ '1f425' => '🐥',
452
+ '1f426' => '🐦',
453
+ '1f427' => '🐧',
454
+ '1f428' => '🐨',
455
+ '1f429' => '🐩',
456
+ '1f42b' => '🐫',
457
+ '1f42c' => '🐬',
458
+ '1f42d' => '🐭',
459
+ '1f42e' => '🐮',
460
+ '1f42f' => '🐯',
461
+ '1f430' => '🐰',
462
+ '1f431' => '🐱',
463
+ '1f432' => '🐲',
464
+ '1f433' => '🐳',
465
+ '1f434' => '🐴',
466
+ '1f435' => '🐵',
467
+ '1f436' => '🐶',
468
+ '1f437' => '🐷',
469
+ '1f438' => '🐸',
470
+ '1f439' => '🐹',
471
+ '1f43a' => '🐺',
472
+ '1f43b' => '🐻',
473
+ '1f43c' => '🐼',
474
+ '1f43d' => '🐽',
475
+ '1f43e' => '🐾',
476
+ '1f440' => '👀',
477
+ '1f442' => '👂',
478
+ '1f443' => '👃',
479
+ '1f444' => '👄',
480
+ '1f445' => '👅',
481
+ '1f446' => '👆',
482
+ '1f447' => '👇',
483
+ '1f448' => '👈',
484
+ '1f449' => '👉',
485
+ '1f44a' => '👊',
486
+ '1f44b' => '👋',
487
+ '1f44c' => '👌',
488
+ '1f44d' => '👍',
489
+ '1f44e' => '👎',
490
+ '1f44f' => '👏',
491
+ '1f450' => '👐',
492
+ '1f451' => '👑',
493
+ '1f452' => '👒',
494
+ '1f453' => '👓',
495
+ '1f454' => '👔',
496
+ '1f455' => '👕',
497
+ '1f456' => '👖',
498
+ '1f457' => '👗',
499
+ '1f458' => '👘',
500
+ '1f459' => '👙',
501
+ '1f45a' => '👚',
502
+ '1f45b' => '👛',
503
+ '1f45c' => '👜',
504
+ '1f45d' => '👝',
505
+ '1f45e' => '👞',
506
+ '1f45f' => '👟',
507
+ '1f460' => '👠',
508
+ '1f461' => '👡',
509
+ '1f462' => '👢',
510
+ '1f463' => '👣',
511
+ '1f464' => '👤',
512
+ '1f466' => '👦',
513
+ '1f467' => '👧',
514
+ '1f468' => '👨',
515
+ '1f469' => '👩',
516
+ '1f46a' => '👪',
517
+ '1f46b' => '👫',
518
+ '1f46e' => '👮',
519
+ '1f46f' => '👯',
520
+ '1f470' => '👰',
521
+ '1f471' => '👱',
522
+ '1f472' => '👲',
523
+ '1f473' => '👳',
524
+ '1f474' => '👴',
525
+ '1f475' => '👵',
526
+ '1f476' => '👶',
527
+ '1f477' => '👷',
528
+ '1f478' => '👸',
529
+ '1f479' => '👹',
530
+ '1f47a' => '👺',
531
+ '1f47b' => '👻',
532
+ '1f47c' => '👼',
533
+ '1f47d' => '👽',
534
+ '1f47e' => '👾',
535
+ '1f47f' => '👿',
536
+ '1f480' => '💀',
537
+ '1f481' => '💁',
538
+ '1f482' => '💂',
539
+ '1f483' => '💃',
540
+ '1f484' => '💄',
541
+ '1f485' => '💅',
542
+ '1f486' => '💆',
543
+ '1f487' => '💇',
544
+ '1f488' => '💈',
545
+ '1f489' => '💉',
546
+ '1f48a' => '💊',
547
+ '1f48b' => '💋',
548
+ '1f48c' => '💌',
549
+ '1f48d' => '💍',
550
+ '1f48e' => '💎',
551
+ '1f48f' => '💏',
552
+ '1f490' => '💐',
553
+ '1f491' => '💑',
554
+ '1f492' => '💒',
555
+ '1f493' => '💓',
556
+ '1f494' => '💔',
557
+ '1f495' => '💕',
558
+ '1f496' => '💖',
559
+ '1f497' => '💗',
560
+ '1f498' => '💘',
561
+ '1f499' => '💙',
562
+ '1f49a' => '💚',
563
+ '1f49b' => '💛',
564
+ '1f49c' => '💜',
565
+ '1f49d' => '💝',
566
+ '1f49e' => '💞',
567
+ '1f49f' => '💟',
568
+ '1f4a0' => '💠',
569
+ '1f4a1' => '💡',
570
+ '1f4a2' => '💢',
571
+ '1f4a3' => '💣',
572
+ '1f4a4' => '💤',
573
+ '1f4a5' => '💥',
574
+ '1f4a6' => '💦',
575
+ '1f4a7' => '💧',
576
+ '1f4a8' => '💨',
577
+ '1f4a9' => '💩',
578
+ '1f4aa' => '💪',
579
+ '1f4ab' => '💫',
580
+ '1f4ac' => '💬',
581
+ '1f4ae' => '💮',
582
+ '1f4af' => '💯',
583
+ '1f4b0' => '💰',
584
+ '1f4b1' => '💱',
585
+ '1f4b2' => '💲',
586
+ '1f4b3' => '💳',
587
+ '1f4b4' => '💴',
588
+ '1f4b5' => '💵',
589
+ '1f4b8' => '💸',
590
+ '1f4b9' => '💹',
591
+ '1f4ba' => '💺',
592
+ '1f4bb' => '💻',
593
+ '1f4bc' => '💼',
594
+ '1f4bd' => '💽',
595
+ '1f4be' => '💾',
596
+ '1f4bf' => '💿',
597
+ '1f4c0' => '📀',
598
+ '1f4c1' => '📁',
599
+ '1f4c2' => '📂',
600
+ '1f4c3' => '📃',
601
+ '1f4c4' => '📄',
602
+ '1f4c5' => '📅',
603
+ '1f4c6' => '📆',
604
+ '1f4c7' => '📇',
605
+ '1f4c8' => '📈',
606
+ '1f4c9' => '📉',
607
+ '1f4ca' => '📊',
608
+ '1f4cb' => '📋',
609
+ '1f4cc' => '📌',
610
+ '1f4cd' => '📍',
611
+ '1f4ce' => '📎',
612
+ '1f4cf' => '📏',
613
+ '1f4d0' => '📐',
614
+ '1f4d1' => '📑',
615
+ '1f4d2' => '📒',
616
+ '1f4d3' => '📓',
617
+ '1f4d4' => '📔',
618
+ '1f4d5' => '📕',
619
+ '1f4d6' => '📖',
620
+ '1f4d7' => '📗',
621
+ '1f4d8' => '📘',
622
+ '1f4d9' => '📙',
623
+ '1f4da' => '📚',
624
+ '1f4db' => '📛',
625
+ '1f4dc' => '📜',
626
+ '1f4dd' => '📝',
627
+ '1f4de' => '📞',
628
+ '1f4df' => '📟',
629
+ '1f4e0' => '📠',
630
+ '1f4e1' => '📡',
631
+ '1f4e2' => '📢',
632
+ '1f4e3' => '📣',
633
+ '1f4e4' => '📤',
634
+ '1f4e5' => '📥',
635
+ '1f4e6' => '📦',
636
+ '1f4e7' => '📧',
637
+ '1f4e8' => '📨',
638
+ '1f4e9' => '📩',
639
+ '1f4ea' => '📪',
640
+ '1f4eb' => '📫',
641
+ '1f4ee' => '📮',
642
+ '1f4f0' => '📰',
643
+ '1f4f1' => '📱',
644
+ '1f4f2' => '📲',
645
+ '1f4f3' => '📳',
646
+ '1f4f4' => '📴',
647
+ '1f4f6' => '📶',
648
+ '1f4f7' => '📷',
649
+ '1f4f9' => '📹',
650
+ '1f4fa' => '📺',
651
+ '1f4fb' => '📻',
652
+ '1f4fc' => '📼',
653
+ '1f503' => '🔃',
654
+ '1f50a' => '🔊',
655
+ '1f50b' => '🔋',
656
+ '1f50c' => '🔌',
657
+ '1f50d' => '🔍',
658
+ '1f50e' => '🔎',
659
+ '1f50f' => '🔏',
660
+ '1f510' => '🔐',
661
+ '1f511' => '🔑',
662
+ '1f512' => '🔒',
663
+ '1f513' => '🔓',
664
+ '1f514' => '🔔',
665
+ '1f516' => '🔖',
666
+ '1f517' => '🔗',
667
+ '1f518' => '🔘',
668
+ '1f519' => '🔙',
669
+ '1f51a' => '🔚',
670
+ '1f51b' => '🔛',
671
+ '1f51c' => '🔜',
672
+ '1f51d' => '🔝',
673
+ '1f51e' => '🔞',
674
+ '1f51f' => '🔟',
675
+ '1f520' => '🔠',
676
+ '1f521' => '🔡',
677
+ '1f522' => '🔢',
678
+ '1f523' => '🔣',
679
+ '1f524' => '🔤',
680
+ '1f525' => '🔥',
681
+ '1f526' => '🔦',
682
+ '1f527' => '🔧',
683
+ '1f528' => '🔨',
684
+ '1f529' => '🔩',
685
+ '1f52a' => '🔪',
686
+ '1f52b' => '🔫',
687
+ '1f52e' => '🔮',
688
+ '1f52f' => '🔯',
689
+ '1f530' => '🔰',
690
+ '1f531' => '🔱',
691
+ '1f532' => '🔲',
692
+ '1f533' => '🔳',
693
+ '1f534' => '🔴',
694
+ '1f535' => '🔵',
695
+ '1f536' => '🔶',
696
+ '1f537' => '🔷',
697
+ '1f538' => '🔸',
698
+ '1f539' => '🔹',
699
+ '1f53a' => '🔺',
700
+ '1f53b' => '🔻',
701
+ '1f53c' => '🔼',
702
+ '1f53d' => '🔽',
703
+ '1f550' => '🕐',
704
+ '1f551' => '🕑',
705
+ '1f552' => '🕒',
706
+ '1f553' => '🕓',
707
+ '1f554' => '🕔',
708
+ '1f555' => '🕕',
709
+ '1f556' => '🕖',
710
+ '1f557' => '🕗',
711
+ '1f558' => '🕘',
712
+ '1f559' => '🕙',
713
+ '1f55a' => '🕚',
714
+ '1f55b' => '🕛',
715
+ '1f5fb' => '🗻',
716
+ '1f5fc' => '🗼',
717
+ '1f5fd' => '🗽',
718
+ '1f5fe' => '🗾',
719
+ '1f5ff' => '🗿',
720
+ '1f600' => '😀',
721
+ '1f607' => '😇',
722
+ '1f608' => '😈',
723
+ '1f60e' => '😎',
724
+ '1f610' => '😐',
725
+ '1f611' => '😑',
726
+ '1f615' => '😕',
727
+ '1f617' => '😗',
728
+ '1f619' => '😙',
729
+ '1f61b' => '😛',
730
+ '1f61f' => '😟',
731
+ '1f626' => '😦',
732
+ '1f627' => '😧',
733
+ '1f62c' => '😬',
734
+ '1f62e' => '😮',
735
+ '1f62f' => '😯',
736
+ '1f634' => '😴',
737
+ '1f636' => '😶',
738
+ '1f681' => '🚁',
739
+ '1f682' => '🚂',
740
+ '1f686' => '🚆',
741
+ '1f688' => '🚈',
742
+ '1f68a' => '🚊',
743
+ '1f68d' => '🚍',
744
+ '1f68e' => '🚎',
745
+ '1f690' => '🚐',
746
+ '1f694' => '🚔',
747
+ '1f696' => '🚖',
748
+ '1f698' => '🚘',
749
+ '1f69b' => '🚛',
750
+ '1f69c' => '🚜',
751
+ '1f69d' => '🚝',
752
+ '1f69e' => '🚞',
753
+ '1f69f' => '🚟',
754
+ '1f6a0' => '🚠',
755
+ '1f6a1' => '🚡',
756
+ '1f6a3' => '🚣',
757
+ '1f6a6' => '🚦',
758
+ '1f6ae' => '🚮',
759
+ '1f6af' => '🚯',
760
+ '1f6b0' => '🚰',
761
+ '1f6b1' => '🚱',
762
+ '1f6b3' => '🚳',
763
+ '1f6b4' => '🚴',
764
+ '1f6b5' => '🚵',
765
+ '1f6b7' => '🚷',
766
+ '1f6b8' => '🚸',
767
+ '1f6bf' => '🚿',
768
+ '1f6c1' => '🛁',
769
+ '1f6c2' => '🛂',
770
+ '1f6c3' => '🛃',
771
+ '1f6c4' => '🛄',
772
+ '1f6c5' => '🛅',
773
+ '1f30d' => '🌍',
774
+ '1f30e' => '🌎',
775
+ '1f310' => '🌐',
776
+ '1f312' => '🌒',
777
+ '1f316' => '🌖',
778
+ '1f317' => '🌗',
779
+ '1f318' => '🌘',
780
+ '1f31a' => '🌚',
781
+ '1f31c' => '🌜',
782
+ '1f31d' => '🌝',
783
+ '1f31e' => '🌞',
784
+ '1f332' => '🌲',
785
+ '1f333' => '🌳',
786
+ '1f34b' => '🍋',
787
+ '1f350' => '🍐',
788
+ '1f37c' => '🍼',
789
+ '1f3c7' => '🏇',
790
+ '1f3c9' => '🏉',
791
+ '1f3e4' => '🏤',
792
+ '1f400' => '🐀',
793
+ '1f401' => '🐁',
794
+ '1f402' => '🐂',
795
+ '1f403' => '🐃',
796
+ '1f404' => '🐄',
797
+ '1f405' => '🐅',
798
+ '1f406' => '🐆',
799
+ '1f407' => '🐇',
800
+ '1f408' => '🐈',
801
+ '1f409' => '🐉',
802
+ '1f40a' => '🐊',
803
+ '1f40b' => '🐋',
804
+ '1f40f' => '🐏',
805
+ '1f410' => '🐐',
806
+ '1f413' => '🐓',
807
+ '1f415' => '🐕',
808
+ '1f416' => '🐖',
809
+ '1f42a' => '🐪',
810
+ '1f465' => '👥',
811
+ '1f46c' => '👬',
812
+ '1f46d' => '👭',
813
+ '1f4ad' => '💭',
814
+ '1f4b6' => '💶',
815
+ '1f4b7' => '💷',
816
+ '1f4ec' => '📬',
817
+ '1f4ed' => '📭',
818
+ '1f4ef' => '📯',
819
+ '1f4f5' => '📵',
820
+ '1f500' => '🔀',
821
+ '1f501' => '🔁',
822
+ '1f502' => '🔂',
823
+ '1f504' => '🔄',
824
+ '1f505' => '🔅',
825
+ '1f506' => '🔆',
826
+ '1f507' => '🔇',
827
+ '1f509' => '🔉',
828
+ '1f515' => '🔕',
829
+ '1f52c' => '🔬',
830
+ '1f52d' => '🔭',
831
+ '1f55c' => '🕜',
832
+ '1f55d' => '🕝',
833
+ '1f55e' => '🕞',
834
+ '1f55f' => '🕟',
835
+ '1f560' => '🕠',
836
+ '1f561' => '🕡',
837
+ '1f562' => '🕢',
838
+ '1f563' => '🕣',
839
+ '1f564' => '🕤',
840
+ '1f565' => '🕥',
841
+ '1f566' => '🕦',
842
+ '1f567' => '🕧',
843
+ );
latest-tweets.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Latest Tweets Widget
4
  Plugin URI: http://wordpress.org/extend/plugins/latest-tweets-widget/
5
  Description: Provides a sidebar widget showing latest tweets - compatible with the new Twitter API 1.1
6
  Author: Tim Whitlock
7
- Version: 1.1.0
8
  Author URI: http://timwhitlock.info/
9
  */
10
 
@@ -90,6 +90,8 @@ function latest_tweets_render( $screen_name, $count, $rts, $ats, $pop = 0 ){
90
  if( $os_timezone !== $wp_timezone ){
91
  date_default_timezone_set( $wp_timezone );
92
  }
 
 
93
  // render each tweet as a block of html for the widget list items
94
  $rendered = array();
95
  foreach( $tweets as $tweet ){
@@ -115,10 +117,6 @@ function latest_tweets_render( $screen_name, $count, $rts, $ats, $pop = 0 ){
115
  if( ! function_exists('twitter_api_html') ){
116
  twitter_api_include('utils');
117
  }
118
- // strip characters that will choke Wordpress cache.
119
- if( $cachettl && ! TWITTER_CACHE_APC ){
120
- $text = twitter_api_strip_emoji( $text );
121
- }
122
  // htmlify tweet, using entities if we can
123
  if( isset($entities) && is_array($entities) ){
124
  $html = twitter_api_html_with_entities( $text, $entities );
@@ -127,6 +125,14 @@ function latest_tweets_render( $screen_name, $count, $rts, $ats, $pop = 0 ){
127
  else {
128
  $html = twitter_api_html( $text );
129
  }
 
 
 
 
 
 
 
 
130
  }
131
  // piece together the whole tweet, allowing override
132
  $final = apply_filters('latest_tweets_render_tweet', $html, $date, $link, $tweet );
4
  Plugin URI: http://wordpress.org/extend/plugins/latest-tweets-widget/
5
  Description: Provides a sidebar widget showing latest tweets - compatible with the new Twitter API 1.1
6
  Author: Tim Whitlock
7
+ Version: 1.1.1
8
  Author URI: http://timwhitlock.info/
9
  */
10
 
90
  if( $os_timezone !== $wp_timezone ){
91
  date_default_timezone_set( $wp_timezone );
92
  }
93
+ // Let theme disable or override emoji rendering
94
+ $emoji_callback = apply_filters('latest_tweets_emoji_callback', 'twitter_api_replace_emoji_callback' );
95
  // render each tweet as a block of html for the widget list items
96
  $rendered = array();
97
  foreach( $tweets as $tweet ){
117
  if( ! function_exists('twitter_api_html') ){
118
  twitter_api_include('utils');
119
  }
 
 
 
 
120
  // htmlify tweet, using entities if we can
121
  if( isset($entities) && is_array($entities) ){
122
  $html = twitter_api_html_with_entities( $text, $entities );
125
  else {
126
  $html = twitter_api_html( $text );
127
  }
128
+ // render emoji, unless filtered out
129
+ if( $emoji_callback ){
130
+ $html = twitter_api_replace_emoji( $html, $emoji_callback );
131
+ }
132
+ // strip characters that will choke mysql cache.
133
+ if( $cachettl && ! TWITTER_CACHE_APC ){
134
+ $html = twitter_api_strip_quadruple_bytes( $html );
135
+ }
136
  }
137
  // piece together the whole tweet, allowing override
138
  $final = apply_filters('latest_tweets_render_tweet', $html, $date, $link, $tweet );
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: timwhitlock
3
  Donate link: http://timwhitlock.info/donate-to-a-project/
4
  Tags: twitter, tweets, oauth, api, rest, api, widget, sidebar
5
  Requires at least: 3.5.1
6
- Tested up to: 3.5.1
7
- Stable tag: 1.1.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -73,6 +73,10 @@ If you're unable too fix your [PHP cURL](https://php.net/manual/en/book.curl.php
73
  `add_filter('https_ssl_verify', '__return_false');`
74
  Do so at your own risk.
75
 
 
 
 
 
76
 
77
  == Screenshots ==
78
 
@@ -81,6 +85,9 @@ Do so at your own risk.
81
 
82
  == Changelog ==
83
 
 
 
 
84
  = 1.1.0 =
85
  * Handling of truncated retweets
86
  * Restructured library directory
@@ -153,8 +160,8 @@ Do so at your own risk.
153
 
154
  == Upgrade Notice ==
155
 
156
- = 1.1.0 =
157
- * Bug fixes and improvements available.
158
 
159
 
160
  == Shortcodes ==
@@ -198,6 +205,9 @@ Tweets are rendered as a list which has various hooks you can use. Here's a roug
198
  .latest-tweets .tweet-text a {
199
  /* style links, hashtags and mentions */
200
  }
 
 
 
201
  .latest-tweets .tweet-details {
202
  /* style datetime and link under tweet */
203
  }
@@ -255,6 +265,22 @@ This would disable the cache (not recommended other than for debugging):
255
  }, 10, 1 );
256
 
257
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
 
259
  == Credits ==
260
 
@@ -264,3 +290,5 @@ Screenshot taken with permission from http://stayingalivefoundation.org/blog
264
 
265
  Be aware of [Twitter's display requirements](https://dev.twitter.com/terms/display-requirements) when rendering tweets on your website.
266
 
 
 
3
  Donate link: http://timwhitlock.info/donate-to-a-project/
4
  Tags: twitter, tweets, oauth, api, rest, api, widget, sidebar
5
  Requires at least: 3.5.1
6
+ Tested up to: 3.9
7
+ Stable tag: 1.1.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
73
  `add_filter('https_ssl_verify', '__return_false');`
74
  Do so at your own risk.
75
 
76
+ = Does this plugin show Emoji images in tweets? =
77
+
78
+ Yes, as of version 1.1.1 Emojis are rendered the same as on twitter.com. See the [Other Notes](http://wordpress.org/plugins/latest-tweets-widget/other_notes/) section for how to disable Emoji.
79
+
80
 
81
  == Screenshots ==
82
 
85
 
86
  == Changelog ==
87
 
88
+ = 1.1.1 =
89
+ * Added emoji support
90
+
91
  = 1.1.0 =
92
  * Handling of truncated retweets
93
  * Restructured library directory
160
 
161
  == Upgrade Notice ==
162
 
163
+ = 1.1.1 =
164
+ * Now supports Emoji rendering.
165
 
166
 
167
  == Shortcodes ==
205
  .latest-tweets .tweet-text a {
206
  /* style links, hashtags and mentions */
207
  }
208
+ .latest-tweets .tweet-text .emoji {
209
+ /* style embedded emoji image in tweet */
210
+ }
211
  .latest-tweets .tweet-details {
212
  /* style datetime and link under tweet */
213
  }
265
  }, 10, 1 );
266
 
267
 
268
+ == Emoji ==
269
+
270
+ If you want to disable Emoji image replacement, you can filter the replacement callback function to something empty, e.g:
271
+
272
+ add_filter('latest_tweets_emoji_callback', function( $func ){
273
+ return '';
274
+ } );
275
+
276
+ or to strip Emoji characters from all tweets, return your own replacement function that returns something else, e.g:
277
+
278
+ add_filter('latest_tweets_emoji_callback', function( $func ){
279
+ return function( array $match ){
280
+ return '<!-- removed emoji -->';
281
+ };
282
+ } );
283
+
284
 
285
  == Credits ==
286
 
290
 
291
  Be aware of [Twitter's display requirements](https://dev.twitter.com/terms/display-requirements) when rendering tweets on your website.
292
 
293
+ Example code here uses PHP [closures](http://www.php.net/manual/en/class.closure.php) which require PHP>=5.3.0 and won't work on older systems.
294
+