Make WordPress Core

Changeset 41069


Ignore:
Timestamp:
07/18/2017 03:47:29 AM (9 years ago)
Author:
pento
Message:

Emoji: Port the Twemoji regex to PHP.

Previously, wp_encode_emoji() and wp_staticize_emoji() used inaccurate regular expressions to find emoji, and transform then into HTML entities or <img>s, respectively. This would result in emoji not being correctly transformed, or occasionally, non-emoji being incorrectly transformed.

This commit adds a new grunt task - grunt precommit:emoji. It finds the regex in twemoji.js, transforms it into a PHP-friendly version, and adds it to formatting.php. This task is also automatically run by grunt precommit, when it detects that twemoji.js has changed.

The new regex requires features introduced in PCRE 8.32, which was introduced in PHP 5.4.14, though it was also backported to later releases of the PHP 5.3 series. For versions of PHP that don't support this, it will fall back to an updated version of the loose-matching regex.

For short posts, the performance difference between the old and new regex is negligible. As the posts get longer, however, the new method is exponentially faster.

Merges [41043], [41045], and [41046] to the 4.8 branch.

Fixes #35293.

Location:
branches/4.8
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • branches/4.8

  • branches/4.8/Gruntfile.js

    r40810 r41069  
    608608                        }
    609609                },
     610                replace: {
     611                        emojiRegex: {
     612                                options: {
     613                                        patterns: [
     614                                                {
     615                                                        match: /\/\/ START: emoji regex[\S\s]*\/\/ END: emoji regex/g,
     616                                                        replacement: function () {
     617                                                                var twemoji = grunt.file.read( SOURCE_DIR + 'wp-includes/js/twemoji.js' ),
     618                                                                        found = twemoji.match( /re = \/(.*)\/g,/ ),
     619                                                                        emojiRegex = found[1],
     620                                                                        regex = '',
     621                                                                        entities = '';
     622
     623                                                                /*
     624                                                                 * Twemoji does some nifty regex optimisations, splitting up surrogate pairs unit, searching by
     625                                                                 * ranges of individual units, and compressing sets of individual units. This is super useful for
     626                                                                 * reducing the size of the regex.
     627                                                                 *
     628                                                                 * Unfortunately, PCRE doesn't allow regexes to search for individual units, so we can't just
     629                                                                 * blindly copy the Twemoji regex.
     630                                                                 *
     631                                                                 * The good news is, we don't have to worry about size restrictions, so we can just unravel the
     632                                                                 * entire regex, and convert it to a PCRE-friendly format.
     633                                                                 */
     634
     635                                                                // Convert ranges: "\udc68-\udc6a" becomes "\udc68\udc69\udc6a".
     636                                                                emojiRegex = emojiRegex.replace( /(\\u\w{4})\-(\\u\w{4})/g, function ( match, first, last ) {
     637                                                                        var start = parseInt( first.substr( 2 ), 16 );
     638                                                                        var end = parseInt( last.substr( 2 ), 16 );
     639
     640                                                                        var replace = '';
     641
     642                                                                        for( var counter = start; counter <= end; counter++ ) {
     643                                                                                replace += '\\u' + counter.toString( 16 );
     644                                                                        }
     645
     646                                                                        return replace;
     647                                                                } );
     648
     649                                                                // Convert sets: "\u200d[\u2640\u2642]\ufe0f" becomes "\u200d\u2640\ufe0f|\u200d\u2642\ufe0f".
     650                                                                emojiRegex = emojiRegex.replace( /((?:\\u\w{4})*)\[((?:\\u\w{4})+)\]((?:\\u\w{4})*)/g, function ( match, before, middle, after ) {
     651                                                                        //return params[1].split( '\\u' ).join( '|' + params[0] + '\\u' ).substr( 1 );
     652                                                                        if ( ! before && ! after ) {
     653                                                                                return match;
     654                                                                        }
     655                                                                        var set = middle.match( /.{1,6}/g );
     656
     657                                                                        return before + set.join( after + '|' + before ) + after;
     658                                                                } );
     659
     660                                                                // Convert surrogate pairs to their equivalent unicode scalar: "\ud83d\udc68" becomes "\u1f468".
     661                                                                emojiRegex = emojiRegex.replace( /(\\ud[89a-f][0-9a-f]{2})(\\ud[89a-f][0-9a-f]{2})/g, function ( match, first, second ) {
     662                                                                        var high = parseInt( first.substr( 2 ), 16 );
     663                                                                        var low = parseInt( second.substr( 2 ), 16 );
     664
     665                                                                        var scalar = ( ( high - 0xD800 ) * 0x400 ) + ( low - 0xDC00 ) + 0x10000;
     666
     667                                                                        return '\\u' + scalar.toString( 16 );
     668                                                                } );
     669
     670                                                                // Convert JavaScript-style code points to PHP-style: "\u1f468" becomes "\x{1f468}".
     671                                                                emojiRegex = emojiRegex.replace( /\\u(\w+)/g, '\\x{$1}' );
     672
     673                                                                // Convert PHP-style code points to HTML entities: "\x{1f468}" becomes "&#x1f468;".
     674                                                                entities = emojiRegex.replace( /\\x{(\w+)}/g, '&#x$1;' );
     675                                                                entities = entities.replace( /\[([^\]]+)\]/g, function( match, codepoint ) {
     676                                                                        return '(?:' + codepoint.replace( /;&/g, ';|&' ) + ')';
     677                                                                } );
     678
     679                                                                regex += '// START: emoji regex\n';
     680                                                                regex += '\t$codepoints = \'/(' + emojiRegex + ')/u\';\n';
     681                                                                regex += '\t$entities = \'/(' + entities + ')/u\';\n';
     682                                                                regex += '\t// END: emoji regex';
     683
     684                                                                return regex;
     685                                                        }
     686                                                }
     687                                        ]
     688                                },
     689                                files: [
     690                                        {
     691                                                expand: true,
     692                                                flatten: true,
     693                                                src: [
     694                                                        SOURCE_DIR + 'wp-includes/formatting.php'
     695                                                ],
     696                                                dest: SOURCE_DIR + 'wp-includes/'
     697                                        }
     698                                ]
     699                        }
     700                },
    610701                _watch: {
    611702                        all: {
     
    719810        ] );
    720811
     812        grunt.registerTask( 'precommit:emoji', [
     813                'replace:emojiRegex'
     814        ] );
     815
    721816        grunt.registerTask( 'precommit', 'Runs test and build tasks in preparation for a commit', function() {
    722817                var done = this.async();
     
    784879                                                }
    785880                                        } );
     881
     882                                        if ( [ 'twemoji.js' ].some( testPath ) ) {
     883                                                grunt.log.writeln( 'twemoji.js has updated. Running `precommit:emoji.' );
     884                                                taskList.push( 'precommit:emoji' );
     885                                        }
    786886                                }
    787887
  • branches/4.8/package.json

    r39478 r41069  
    3131    "grunt-patch-wordpress": "~0.4.2",
    3232    "grunt-postcss": "~0.7.1",
     33    "grunt-replace": "~1.0.1",
    3334    "grunt-rtlcss": "~2.0.1",
    3435    "grunt-sass": "~1.2.1",
  • branches/4.8/src/wp-includes/formatting.php

    r40837 r41069  
    50855085
    50865086/**
    5087  * Convert any 4 byte emoji in a string to their equivalent HTML entity.
    5088  *
    5089  * Currently, only Unicode 7 emoji are supported. Skin tone modifiers are allowed,
    5090  * all other Unicode 8 emoji will be added when the spec is finalised.
     5087 * Convert emoji characters to their equivalent HTML entity.
    50915088 *
    50925089 * This allows us to store emoji in a DB using the utf8 character set.
     
    50995096function wp_encode_emoji( $content ) {
    51005097        if ( function_exists( 'mb_convert_encoding' ) ) {
    5101                 $regex = '/(
    5102                      \x23\xE2\x83\xA3               # Digits
    5103                      [\x30-\x39]\xE2\x83\xA3
    5104                    | \xF0\x9F[\x85-\x88][\xA6-\xBF] # Enclosed characters
    5105                    | \xF0\x9F[\x8C-\x97][\x80-\xBF] # Misc
    5106                    | \xF0\x9F\x98[\x80-\xBF]        # Smilies
    5107                    | \xF0\x9F\x99[\x80-\x8F]
    5108                    | \xF0\x9F\x9A[\x80-\xBF]        # Transport and map symbols
    5109                 )/x';
     5098                $regex = wp_emoji_regex( 'codepoints' );
    51105099
    51115100                $matches = array();
    51125101                if ( preg_match_all( $regex, $content, $matches ) ) {
    51135102                        if ( ! empty( $matches[1] ) ) {
    5114                                 foreach ( $matches[1] as $emoji ) {
     5103                                foreach ( array_unique( $matches[1] ) as $emoji ) {
    51155104                                        /*
    51165105                                         * UTF-32's hex encoding is the same as HTML's hex encoding.
    51175106                                         * So, by converting the emoji from UTF-8 to UTF-32, we magically
    5118                                          * get the correct hex encoding.
     5107                                         * get the correct hex encoding, 0 padded to 8 characters.
    51195108                                         */
    51205109                                        $unpacked = unpack( 'H*', mb_convert_encoding( $emoji, 'UTF-32', 'UTF-8' ) );
    51215110                                        if ( isset( $unpacked[1] ) ) {
    5122                                                 $entity = '&#x' . ltrim( $unpacked[1], '0' ) . ';';
     5111                                                $parts = str_split( $unpacked[1], 8 );
     5112                                                $entity = '';
     5113
     5114                                                foreach ( $parts as $part ) {
     5115                                                        $entity .= '&#x' . ltrim( $part, '0' ) . ';';
     5116                                                }
     5117
    51235118                                                $content = str_replace( $emoji, $entity, $content );
    51245119                                        }
     
    51425137        $text = wp_encode_emoji( $text );
    51435138
    5144         /** This filter is documented in wp-includes/formatting.php */
    5145         $cdn_url = apply_filters( 'emoji_url', 'https://s.w.org/images/core/emoji/2.3/72x72/' );
    5146 
    5147         /** This filter is documented in wp-includes/formatting.php */
    5148         $ext = apply_filters( 'emoji_ext', '.png' );
    5149 
    51505139        $output = '';
    51515140        /*
     
    51625151        $ignore_block_element = '';
    51635152
     5153        $regex = wp_emoji_regex( 'entities' );
     5154
    51645155        for ( $i = 0; $i < $stop; $i++ ) {
    51655156                $content = $textarr[$i];
     
    51725163                // If it's not a tag and not in ignore block.
    51735164                if ( '' ==  $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] ) {
    5174                         $matches = array();
    5175                         if ( preg_match_all( '/(&#x1f1(e[6-9a-f]|f[0-9a-f]);){2}/', $content, $matches ) ) {
    5176                                 if ( ! empty( $matches[0] ) ) {
    5177                                         foreach ( $matches[0] as $flag ) {
    5178                                                 $chars = str_replace( array( '&#x', ';'), '', $flag );
    5179 
    5180                                                 list( $char1, $char2 ) = str_split( $chars, 5 );
    5181                                                 $entity = sprintf( '<img src="%s" alt="%s" class="wp-smiley" style="height: 1em; max-height: 1em;" />', $cdn_url . $char1 . '-' . $char2 . $ext, html_entity_decode( $flag ) );
    5182 
    5183                                                 $content = str_replace( $flag, $entity, $content );
    5184                                         }
    5185                                 }
    5186                         }
    5187 
    5188                         // Loosely match the Emoji Unicode range.
    5189                         $regex = '/(&#x[2-3][0-9a-f]{3};|&#x1f[1-6][0-9a-f]{2};)/';
    5190 
    5191                         $matches = array();
    5192                         if ( preg_match_all( $regex, $content, $matches ) ) {
    5193                                 if ( ! empty( $matches[1] ) ) {
    5194                                         foreach ( $matches[1] as $emoji ) {
    5195                                                 $char = str_replace( array( '&#x', ';'), '', $emoji );
    5196                                                 $entity = sprintf( '<img src="%s" alt="%s" class="wp-smiley" style="height: 1em; max-height: 1em;" />', $cdn_url . $char . $ext, html_entity_decode( $emoji ) );
    5197 
    5198                                                 $content = str_replace( $emoji, $entity, $content );
    5199                                         }
    5200                                 }
    5201                         }
     5165                        $content = preg_replace_callback( $regex, '_wp_staticize_emoji', $content );
    52025166                }
    52035167
     
    52115175
    52125176        return $output;
     5177}
     5178
     5179/**
     5180 * Callback for wp_staticize_emoji() to turn matched emoji glyphs into images.
     5181 *
     5182 * @since 4.8.1
     5183 * @access private
     5184 *
     5185 * @see wp_staticize_emoji()
     5186 * @staticvar string $cdn_url The CDN url returned by the {@see 'emoji_url'} filter.
     5187 * @staticvar string $ext     The file extension returned by the {@see 'emoji_ext'} filter.
     5188 *
     5189 * @param  array $matches The matched data.
     5190 * @return string HTML for the static emoji image.
     5191 */
     5192function _wp_staticize_emoji( $matches ) {
     5193        static $cdn_url;
     5194        if ( ! $cdn_url ) {
     5195                /** This filter is documented in wp-includes/formatting.php */
     5196                $cdn_url = apply_filters( 'emoji_url', 'https://s.w.org/images/core/emoji/2.3/72x72/' );
     5197        }
     5198
     5199        static $ext;
     5200        if ( ! $ext ) {
     5201                /** This filter is documented in wp-includes/formatting.php */
     5202                $ext = apply_filters( 'emoji_ext', '.png' );
     5203        }
     5204
     5205        $char = str_replace( ';&#x', '-', $matches[1] );
     5206        $char = str_replace( array( '&#x', ';'), '', $char );
     5207
     5208        return sprintf( '<img src="%s" alt="%s" class="wp-smiley" style="height: 1em; max-height: 1em;" />', $cdn_url . $char . $ext, html_entity_decode( $matches[1] ) );
    52135209}
    52145210
     
    52815277
    52825278/**
     5279 * Returns a regex string to match all emoji that WordPress recognises.
     5280 *
     5281 * This regex is automatically built from the regex in twemoji.js - if it needs to be updated,
     5282 * you should update the regex there, then run the `grunt precommit:emoji` job.
     5283 *
     5284 * @since 4.8.1
     5285 *
     5286 * @param string $type Optional. Which regex type to return. Accepts 'codepoints' or 'entities', default 'coidepoints'.
     5287 * @return string A regex to match all emoji that WordPress recognises.
     5288 */
     5289function wp_emoji_regex( $type = 'codepoints' ) {
     5290        // If we're using a PCRE version that doesn't support Unicode, return a loose match regex.
     5291        if ( 'codepoints' === $type && ( ! defined( 'PCRE_VERSION' ) || version_compare( PCRE_VERSION, '8.32', '<=' ) ) ) {
     5292                return '/(
     5293                     \xE2\x99[\x80-\x82]            # Male and female symbols
     5294                   | [\x23\x30-\x39]\xE2\x83\xA3    # Digits
     5295                   | \xF0\x9F[\x85-\x88][\xA6-\xBF] # Enclosed characters
     5296                   | \xF0\x9F[\x8C-\x97][\x80-\xBF] # Misc
     5297                   | \xF0\x9F\x98[\x80-\xBF]        # Smilies
     5298                   | \xF0\x9F\x99[\x80-\x8F]
     5299                   | \xF0\x9F[\xA4-\xA7][\x00-\xFF]
     5300                   | \xF0\x9F\x9A[\x80-\xBF]        # Transport and map symbols
     5301                   | \xE2\x80\x8D                   # Zero Width Joiner
     5302                   | \xEF\xB8\x8F                   # Emoji Variation Selector
     5303                )/x';
     5304        }
     5305
     5306        // Do not remove the START/END comments - they're used to find where to insert the regex.
     5307
     5308        // START: emoji regex
     5309        $codepoints = '/(\x{1f468}|\x{1f469}(?:\x{1f3fb}|\x{1f3fc}|\x{1f3fd}|\x{1f3fe}|\x{1f3ff})?\x{200d}(?:\x{2695}\x{fe0f}|\x{2696}\x{fe0f}|\x{2708}\x{fe0f}|\x{1f33e}|\x{1f373}|\x{1f393}|\x{1f3a4}|\x{1f3a8}|\x{1f3eb}|\x{1f3ed}|\x{1f4bb}|\x{1f4bc}|\x{1f527}|\x{1f52c}|\x{1f680}|\x{1f692})|(?:\x{1f3cb}|\x{1f3cc}|\x{1f575}|\x{26f9})(?:\x{fe0f}|\x{1f3fb}|\x{1f3fc}|\x{1f3fd}|\x{1f3fe}|\x{1f3ff})\x{200d}\x{2640}\x{fe0f}|\x{200d}\x{2642}\x{fe0f}|(?:\x{1f3c3}|\x{1f3c4}|\x{1f3ca}|\x{1f46e}|\x{1f471}|\x{1f473}|\x{1f477}|\x{1f481}|\x{1f482}|\x{1f486}|\x{1f487}|\x{1f645}|\x{1f646}|\x{1f647}|\x{1f64b}|\x{1f64d}|\x{1f64e}|\x{1f6a3}|\x{1f6b4}|\x{1f6b5}|\x{1f6b6}|\x{1f926}|\x{1f937}|\x{1f938}|\x{1f939}|\x{1f93d}|\x{1f93e}|\x{1f9d6}|\x{1f9d7}|\x{1f9d8}|\x{1f9d9}|\x{1f9da}|\x{1f9db}|\x{1f9dc}|\x{1f9dd})(?:\x{1f3fb}|\x{1f3fc}|\x{1f3fd}|\x{1f3fe}|\x{1f3ff})?\x{200d}\x{2640}\x{fe0f}|\x{200d}\x{2642}\x{fe0f}|\x{1f468}\x{200d}\x{2764}\x{fe0f}\x{200d}\x{1f48b}\x{200d}\x{1f468}|\x{1f468}\x{200d}\x{1f468}\x{200d}\x{1f466}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f468}\x{200d}\x{1f467}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f468}\x{200d}\x{1f467}\x{200d}\x{1f467}|\x{1f468}\x{200d}\x{1f469}\x{200d}\x{1f466}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f469}\x{200d}\x{1f467}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f469}\x{200d}\x{1f467}\x{200d}\x{1f467}|\x{1f469}\x{200d}\x{2764}\x{fe0f}\x{200d}\x{1f48b}\x{200d}\x{1f468}|\x{1f469}\x{200d}\x{2764}\x{fe0f}\x{200d}\x{1f48b}\x{200d}\x{1f469}|\x{1f469}\x{200d}\x{1f469}\x{200d}\x{1f466}\x{200d}\x{1f466}|\x{1f469}\x{200d}\x{1f469}\x{200d}\x{1f467}\x{200d}\x{1f466}|\x{1f469}\x{200d}\x{1f469}\x{200d}\x{1f467}\x{200d}\x{1f467}|\x{1f468}\x{200d}\x{2764}\x{fe0f}\x{200d}\x{1f468}|\x{1f468}\x{200d}\x{1f466}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f467}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f467}\x{200d}\x{1f467}|\x{1f468}\x{200d}\x{1f468}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f468}\x{200d}\x{1f467}|\x{1f468}\x{200d}\x{1f469}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f469}\x{200d}\x{1f467}|\x{1f469}\x{200d}\x{2764}\x{fe0f}\x{200d}\x{1f468}|\x{1f469}\x{200d}\x{2764}\x{fe0f}\x{200d}\x{1f469}|\x{1f469}\x{200d}\x{1f466}\x{200d}\x{1f466}|\x{1f469}\x{200d}\x{1f467}\x{200d}\x{1f466}|\x{1f469}\x{200d}\x{1f467}\x{200d}\x{1f467}|\x{1f469}\x{200d}\x{1f469}\x{200d}\x{1f466}|\x{1f469}\x{200d}\x{1f469}\x{200d}\x{1f467}|\x{1f3f3}\x{fe0f}\x{200d}\x{1f308}|\x{1f3f4}\x{200d}\x{2620}\x{fe0f}|\x{1f441}\x{200d}\x{1f5e8}|\x{1f468}\x{200d}\x{1f466}|\x{1f468}\x{200d}\x{1f467}|\x{1f469}\x{200d}\x{1f466}|\x{1f469}\x{200d}\x{1f467}|\x{1f46f}\x{200d}\x{2640}\x{fe0f}|\x{1f46f}\x{200d}\x{2642}\x{fe0f}|\x{1f93c}\x{200d}\x{2640}\x{fe0f}|\x{1f93c}\x{200d}\x{2642}\x{fe0f}|\x{1f9de}\x{200d}\x{2640}\x{fe0f}|\x{1f9de}\x{200d}\x{2642}\x{fe0f}|\x{1f9df}\x{200d}\x{2640}\x{fe0f}|\x{1f9df}\x{200d}\x{2642}\x{fe0f}|(?:[\x{0023}\x{002a}\x{30}\x{31}\x{32}\x{33}\x{34}\x{35}\x{36}\x{37}\x{38}\x{39}])\x{fe0f}?\x{20e3}|(?:(?:\x{1f3cb}|\x{1f3cc}|\x{1f574}|\x{1f575}|\x{1f590}|[\x{261d}\x{26f7}\x{26f9}\x{270c}\x{270d}])(?:\x{fe0f}|(?!\x{fe0e}))|\x{1f385}|\x{1f3c2}|\x{1f3c3}|\x{1f3c4}|\x{1f3c7}|\x{1f3ca}|\x{1f442}|\x{1f443}|\x{1f446}|\x{1f447}|\x{1f448}|\x{1f449}|\x{1f44a}|\x{1f44b}|\x{1f44c}|\x{1f44d}|\x{1f44e}|\x{1f44f}|\x{1f450}|\x{1f466}|\x{1f467}|\x{1f468}|\x{1f469}|\x{1f46e}|\x{1f470}|\x{1f471}|\x{1f472}|\x{1f473}|\x{1f474}|\x{1f475}|\x{1f476}|\x{1f477}|\x{1f478}|\x{1f47c}|\x{1f481}|\x{1f482}|\x{1f483}|\x{1f485}|\x{1f486}|\x{1f487}|\x{1f4aa}|\x{1f57a}|\x{1f595}|\x{1f596}|\x{1f645}|\x{1f646}|\x{1f647}|\x{1f64b}|\x{1f64c}|\x{1f64d}|\x{1f64e}|\x{1f64f}|\x{1f6a3}|\x{1f6b4}|\x{1f6b5}|\x{1f6b6}|\x{1f6c0}|\x{1f6cc}|\x{1f918}|\x{1f919}|\x{1f91a}|\x{1f91b}|\x{1f91c}|\x{1f91e}|\x{1f91f}|\x{1f926}|\x{1f930}|\x{1f931}|\x{1f932}|\x{1f933}|\x{1f934}|\x{1f935}|\x{1f936}|\x{1f937}|\x{1f938}|\x{1f939}|\x{1f93d}|\x{1f93e}|\x{1f9d1}|\x{1f9d2}|\x{1f9d3}|\x{1f9d4}|\x{1f9d5}|\x{1f9d6}|\x{1f9d7}|\x{1f9d8}|\x{1f9d9}|\x{1f9da}|\x{1f9db}|\x{1f9dc}|\x{1f9dd}|[\x{270a}\x{270b}])(?:\x{1f3fb}|\x{1f3fc}|\x{1f3fd}|\x{1f3fe}|\x{1f3ff}|)|\x{1f3f4}\x{e0067}\x{e0062}\x{e0065}\x{e006e}\x{e0067}\x{e007f}|\x{1f3f4}\x{e0067}\x{e0062}\x{e0073}\x{e0063}\x{e0074}\x{e007f}|\x{1f3f4}\x{e0067}\x{e0062}\x{e0077}\x{e006c}\x{e0073}\x{e007f}|\x{1f1e6}\x{1f1e8}|\x{1f1e6}\x{1f1e9}|\x{1f1e6}\x{1f1ea}|\x{1f1e6}\x{1f1eb}|\x{1f1e6}\x{1f1ec}|\x{1f1e6}\x{1f1ee}|\x{1f1e6}\x{1f1f1}|\x{1f1e6}\x{1f1f2}|\x{1f1e6}\x{1f1f4}|\x{1f1e6}\x{1f1f6}|\x{1f1e6}\x{1f1f7}|\x{1f1e6}\x{1f1f8}|\x{1f1e6}\x{1f1f9}|\x{1f1e6}\x{1f1fa}|\x{1f1e6}\x{1f1fc}|\x{1f1e6}\x{1f1fd}|\x{1f1e6}\x{1f1ff}|\x{1f1e7}\x{1f1e6}|\x{1f1e7}\x{1f1e7}|\x{1f1e7}\x{1f1e9}|\x{1f1e7}\x{1f1ea}|\x{1f1e7}\x{1f1eb}|\x{1f1e7}\x{1f1ec}|\x{1f1e7}\x{1f1ed}|\x{1f1e7}\x{1f1ee}|\x{1f1e7}\x{1f1ef}|\x{1f1e7}\x{1f1f1}|\x{1f1e7}\x{1f1f2}|\x{1f1e7}\x{1f1f3}|\x{1f1e7}\x{1f1f4}|\x{1f1e7}\x{1f1f6}|\x{1f1e7}\x{1f1f7}|\x{1f1e7}\x{1f1f8}|\x{1f1e7}\x{1f1f9}|\x{1f1e7}\x{1f1fb}|\x{1f1e7}\x{1f1fc}|\x{1f1e7}\x{1f1fe}|\x{1f1e7}\x{1f1ff}|\x{1f1e8}\x{1f1e6}|\x{1f1e8}\x{1f1e8}|\x{1f1e8}\x{1f1e9}|\x{1f1e8}\x{1f1eb}|\x{1f1e8}\x{1f1ec}|\x{1f1e8}\x{1f1ed}|\x{1f1e8}\x{1f1ee}|\x{1f1e8}\x{1f1f0}|\x{1f1e8}\x{1f1f1}|\x{1f1e8}\x{1f1f2}|\x{1f1e8}\x{1f1f3}|\x{1f1e8}\x{1f1f4}|\x{1f1e8}\x{1f1f5}|\x{1f1e8}\x{1f1f7}|\x{1f1e8}\x{1f1fa}|\x{1f1e8}\x{1f1fb}|\x{1f1e8}\x{1f1fc}|\x{1f1e8}\x{1f1fd}|\x{1f1e8}\x{1f1fe}|\x{1f1e8}\x{1f1ff}|\x{1f1e9}\x{1f1ea}|\x{1f1e9}\x{1f1ec}|\x{1f1e9}\x{1f1ef}|\x{1f1e9}\x{1f1f0}|\x{1f1e9}\x{1f1f2}|\x{1f1e9}\x{1f1f4}|\x{1f1e9}\x{1f1ff}|\x{1f1ea}\x{1f1e6}|\x{1f1ea}\x{1f1e8}|\x{1f1ea}\x{1f1ea}|\x{1f1ea}\x{1f1ec}|\x{1f1ea}\x{1f1ed}|\x{1f1ea}\x{1f1f7}|\x{1f1ea}\x{1f1f8}|\x{1f1ea}\x{1f1f9}|\x{1f1ea}\x{1f1fa}|\x{1f1eb}\x{1f1ee}|\x{1f1eb}\x{1f1ef}|\x{1f1eb}\x{1f1f0}|\x{1f1eb}\x{1f1f2}|\x{1f1eb}\x{1f1f4}|\x{1f1eb}\x{1f1f7}|\x{1f1ec}\x{1f1e6}|\x{1f1ec}\x{1f1e7}|\x{1f1ec}\x{1f1e9}|\x{1f1ec}\x{1f1ea}|\x{1f1ec}\x{1f1eb}|\x{1f1ec}\x{1f1ec}|\x{1f1ec}\x{1f1ed}|\x{1f1ec}\x{1f1ee}|\x{1f1ec}\x{1f1f1}|\x{1f1ec}\x{1f1f2}|\x{1f1ec}\x{1f1f3}|\x{1f1ec}\x{1f1f5}|\x{1f1ec}\x{1f1f6}|\x{1f1ec}\x{1f1f7}|\x{1f1ec}\x{1f1f8}|\x{1f1ec}\x{1f1f9}|\x{1f1ec}\x{1f1fa}|\x{1f1ec}\x{1f1fc}|\x{1f1ec}\x{1f1fe}|\x{1f1ed}\x{1f1f0}|\x{1f1ed}\x{1f1f2}|\x{1f1ed}\x{1f1f3}|\x{1f1ed}\x{1f1f7}|\x{1f1ed}\x{1f1f9}|\x{1f1ed}\x{1f1fa}|\x{1f1ee}\x{1f1e8}|\x{1f1ee}\x{1f1e9}|\x{1f1ee}\x{1f1ea}|\x{1f1ee}\x{1f1f1}|\x{1f1ee}\x{1f1f2}|\x{1f1ee}\x{1f1f3}|\x{1f1ee}\x{1f1f4}|\x{1f1ee}\x{1f1f6}|\x{1f1ee}\x{1f1f7}|\x{1f1ee}\x{1f1f8}|\x{1f1ee}\x{1f1f9}|\x{1f1ef}\x{1f1ea}|\x{1f1ef}\x{1f1f2}|\x{1f1ef}\x{1f1f4}|\x{1f1ef}\x{1f1f5}|\x{1f1f0}\x{1f1ea}|\x{1f1f0}\x{1f1ec}|\x{1f1f0}\x{1f1ed}|\x{1f1f0}\x{1f1ee}|\x{1f1f0}\x{1f1f2}|\x{1f1f0}\x{1f1f3}|\x{1f1f0}\x{1f1f5}|\x{1f1f0}\x{1f1f7}|\x{1f1f0}\x{1f1fc}|\x{1f1f0}\x{1f1fe}|\x{1f1f0}\x{1f1ff}|\x{1f1f1}\x{1f1e6}|\x{1f1f1}\x{1f1e7}|\x{1f1f1}\x{1f1e8}|\x{1f1f1}\x{1f1ee}|\x{1f1f1}\x{1f1f0}|\x{1f1f1}\x{1f1f7}|\x{1f1f1}\x{1f1f8}|\x{1f1f1}\x{1f1f9}|\x{1f1f1}\x{1f1fa}|\x{1f1f1}\x{1f1fb}|\x{1f1f1}\x{1f1fe}|\x{1f1f2}\x{1f1e6}|\x{1f1f2}\x{1f1e8}|\x{1f1f2}\x{1f1e9}|\x{1f1f2}\x{1f1ea}|\x{1f1f2}\x{1f1eb}|\x{1f1f2}\x{1f1ec}|\x{1f1f2}\x{1f1ed}|\x{1f1f2}\x{1f1f0}|\x{1f1f2}\x{1f1f1}|\x{1f1f2}\x{1f1f2}|\x{1f1f2}\x{1f1f3}|\x{1f1f2}\x{1f1f4}|\x{1f1f2}\x{1f1f5}|\x{1f1f2}\x{1f1f6}|\x{1f1f2}\x{1f1f7}|\x{1f1f2}\x{1f1f8}|\x{1f1f2}\x{1f1f9}|\x{1f1f2}\x{1f1fa}|\x{1f1f2}\x{1f1fb}|\x{1f1f2}\x{1f1fc}|\x{1f1f2}\x{1f1fd}|\x{1f1f2}\x{1f1fe}|\x{1f1f2}\x{1f1ff}|\x{1f1f3}\x{1f1e6}|\x{1f1f3}\x{1f1e8}|\x{1f1f3}\x{1f1ea}|\x{1f1f3}\x{1f1eb}|\x{1f1f3}\x{1f1ec}|\x{1f1f3}\x{1f1ee}|\x{1f1f3}\x{1f1f1}|\x{1f1f3}\x{1f1f4}|\x{1f1f3}\x{1f1f5}|\x{1f1f3}\x{1f1f7}|\x{1f1f3}\x{1f1fa}|\x{1f1f3}\x{1f1ff}|\x{1f1f4}\x{1f1f2}|\x{1f1f5}\x{1f1e6}|\x{1f1f5}\x{1f1ea}|\x{1f1f5}\x{1f1eb}|\x{1f1f5}\x{1f1ec}|\x{1f1f5}\x{1f1ed}|\x{1f1f5}\x{1f1f0}|\x{1f1f5}\x{1f1f1}|\x{1f1f5}\x{1f1f2}|\x{1f1f5}\x{1f1f3}|\x{1f1f5}\x{1f1f7}|\x{1f1f5}\x{1f1f8}|\x{1f1f5}\x{1f1f9}|\x{1f1f5}\x{1f1fc}|\x{1f1f5}\x{1f1fe}|\x{1f1f6}\x{1f1e6}|\x{1f1f7}\x{1f1ea}|\x{1f1f7}\x{1f1f4}|\x{1f1f7}\x{1f1f8}|\x{1f1f7}\x{1f1fa}|\x{1f1f7}\x{1f1fc}|\x{1f1f8}\x{1f1e6}|\x{1f1f8}\x{1f1e7}|\x{1f1f8}\x{1f1e8}|\x{1f1f8}\x{1f1e9}|\x{1f1f8}\x{1f1ea}|\x{1f1f8}\x{1f1ec}|\x{1f1f8}\x{1f1ed}|\x{1f1f8}\x{1f1ee}|\x{1f1f8}\x{1f1ef}|\x{1f1f8}\x{1f1f0}|\x{1f1f8}\x{1f1f1}|\x{1f1f8}\x{1f1f2}|\x{1f1f8}\x{1f1f3}|\x{1f1f8}\x{1f1f4}|\x{1f1f8}\x{1f1f7}|\x{1f1f8}\x{1f1f8}|\x{1f1f8}\x{1f1f9}|\x{1f1f8}\x{1f1fb}|\x{1f1f8}\x{1f1fd}|\x{1f1f8}\x{1f1fe}|\x{1f1f8}\x{1f1ff}|\x{1f1f9}\x{1f1e6}|\x{1f1f9}\x{1f1e8}|\x{1f1f9}\x{1f1e9}|\x{1f1f9}\x{1f1eb}|\x{1f1f9}\x{1f1ec}|\x{1f1f9}\x{1f1ed}|\x{1f1f9}\x{1f1ef}|\x{1f1f9}\x{1f1f0}|\x{1f1f9}\x{1f1f1}|\x{1f1f9}\x{1f1f2}|\x{1f1f9}\x{1f1f3}|\x{1f1f9}\x{1f1f4}|\x{1f1f9}\x{1f1f7}|\x{1f1f9}\x{1f1f9}|\x{1f1f9}\x{1f1fb}|\x{1f1f9}\x{1f1fc}|\x{1f1f9}\x{1f1ff}|\x{1f1fa}\x{1f1e6}|\x{1f1fa}\x{1f1ec}|\x{1f1fa}\x{1f1f2}|\x{1f1fa}\x{1f1f3}|\x{1f1fa}\x{1f1f8}|\x{1f1fa}\x{1f1fe}|\x{1f1fa}\x{1f1ff}|\x{1f1fb}\x{1f1e6}|\x{1f1fb}\x{1f1e8}|\x{1f1fb}\x{1f1ea}|\x{1f1fb}\x{1f1ec}|\x{1f1fb}\x{1f1ee}|\x{1f1fb}\x{1f1f3}|\x{1f1fb}\x{1f1fa}|\x{1f1fc}\x{1f1eb}|\x{1f1fc}\x{1f1f8}|\x{1f1fd}\x{1f1f0}|\x{1f1fe}\x{1f1ea}|\x{1f1fe}\x{1f1f9}|\x{1f1ff}\x{1f1e6}|\x{1f1ff}\x{1f1f2}|\x{1f1ff}\x{1f1fc}|\x{10000}|\x{1f0cf}|\x{1f18e}|\x{1f191}|\x{1f192}|\x{1f193}|\x{1f194}|\x{1f195}|\x{1f196}|\x{1f197}|\x{1f198}|\x{1f199}|\x{1f19a}|\x{1f1e6}|\x{1f1e7}|\x{1f1e8}|\x{1f1e9}|\x{1f1ea}|\x{1f1eb}|\x{1f1ec}|\x{1f1ed}|\x{1f1ee}|\x{1f1ef}|\x{1f1f0}|\x{1f1f1}|\x{1f1f2}|\x{1f1f3}|\x{1f1f4}|\x{1f1f5}|\x{1f1f6}|\x{1f1f7}|\x{1f1f8}|\x{1f1f9}|\x{1f1fa}|\x{1f1fb}|\x{1f1fc}|\x{1f1fd}|\x{1f1fe}|\x{1f1ff}|\x{1f201}|\x{1f232}|\x{1f233}|\x{1f234}|\x{1f235}|\x{1f236}|\x{1f238}|\x{1f239}|\x{1f23a}|\x{1f250}|\x{1f251}|\x{1f300}|\x{1f301}|\x{1f302}|\x{1f303}|\x{1f304}|\x{1f305}|\x{1f306}|\x{1f307}|\x{1f308}|\x{1f309}|\x{1f30a}|\x{1f30b}|\x{1f30c}|\x{1f30d}|\x{1f30e}|\x{1f30f}|\x{1f310}|\x{1f311}|\x{1f312}|\x{1f313}|\x{1f314}|\x{1f315}|\x{1f316}|\x{1f317}|\x{1f318}|\x{1f319}|\x{1f31a}|\x{1f31b}|\x{1f31c}|\x{1f31d}|\x{1f31e}|\x{1f31f}|\x{1f320}|\x{1f32d}|\x{1f32e}|\x{1f32f}|\x{1f330}|\x{1f331}|\x{1f332}|\x{1f333}|\x{1f334}|\x{1f335}|\x{1f337}|\x{1f338}|\x{1f339}|\x{1f33a}|\x{1f33b}|\x{1f33c}|\x{1f33d}|\x{1f33e}|\x{1f33f}|\x{1f340}|\x{1f341}|\x{1f342}|\x{1f343}|\x{1f344}|\x{1f345}|\x{1f346}|\x{1f347}|\x{1f348}|\x{1f349}|\x{1f34a}|\x{1f34b}|\x{1f34c}|\x{1f34d}|\x{1f34e}|\x{1f34f}|\x{1f350}|\x{1f351}|\x{1f352}|\x{1f353}|\x{1f354}|\x{1f355}|\x{1f356}|\x{1f357}|\x{1f358}|\x{1f359}|\x{1f35a}|\x{1f35b}|\x{1f35c}|\x{1f35d}|\x{1f35e}|\x{1f35f}|\x{1f360}|\x{1f361}|\x{1f362}|\x{1f363}|\x{1f364}|\x{1f365}|\x{1f366}|\x{1f367}|\x{1f368}|\x{1f369}|\x{1f36a}|\x{1f36b}|\x{1f36c}|\x{1f36d}|\x{1f36e}|\x{1f36f}|\x{1f370}|\x{1f371}|\x{1f372}|\x{1f373}|\x{1f374}|\x{1f375}|\x{1f376}|\x{1f377}|\x{1f378}|\x{1f379}|\x{1f37a}|\x{1f37b}|\x{1f37c}|\x{1f37e}|\x{1f37f}|\x{1f380}|\x{1f381}|\x{1f382}|\x{1f383}|\x{1f384}|\x{1f386}|\x{1f387}|\x{1f388}|\x{1f389}|\x{1f38a}|\x{1f38b}|\x{1f38c}|\x{1f38d}|\x{1f38e}|\x{1f38f}|\x{1f390}|\x{1f391}|\x{1f392}|\x{1f393}|\x{1f3a0}|\x{1f3a1}|\x{1f3a2}|\x{1f3a3}|\x{1f3a4}|\x{1f3a5}|\x{1f3a6}|\x{1f3a7}|\x{1f3a8}|\x{1f3a9}|\x{1f3aa}|\x{1f3ab}|\x{1f3ac}|\x{1f3ad}|\x{1f3ae}|\x{1f3af}|\x{1f3b0}|\x{1f3b1}|\x{1f3b2}|\x{1f3b3}|\x{1f3b4}|\x{1f3b5}|\x{1f3b6}|\x{1f3b7}|\x{1f3b8}|\x{1f3b9}|\x{1f3ba}|\x{1f3bb}|\x{1f3bc}|\x{1f3bd}|\x{1f3be}|\x{1f3bf}|\x{1f3c0}|\x{1f3c1}|\x{1f3c5}|\x{1f3c6}|\x{1f3c8}|\x{1f3c9}|\x{1f3cf}|\x{1f3d0}|\x{1f3d1}|\x{1f3d2}|\x{1f3d3}|\x{1f3e0}|\x{1f3e1}|\x{1f3e2}|\x{1f3e3}|\x{1f3e4}|\x{1f3e5}|\x{1f3e6}|\x{1f3e7}|\x{1f3e8}|\x{1f3e9}|\x{1f3ea}|\x{1f3eb}|\x{1f3ec}|\x{1f3ed}|\x{1f3ee}|\x{1f3ef}|\x{1f3f0}|\x{1f3f4}|\x{1f3f8}|\x{1f3f9}|\x{1f3fa}|\x{1f3fb}|\x{1f3fc}|\x{1f3fd}|\x{1f3fe}|\x{1f3ff}|\x{1f400}|\x{1f401}|\x{1f402}|\x{1f403}|\x{1f404}|\x{1f405}|\x{1f406}|\x{1f407}|\x{1f408}|\x{1f409}|\x{1f40a}|\x{1f40b}|\x{1f40c}|\x{1f40d}|\x{1f40e}|\x{1f40f}|\x{1f410}|\x{1f411}|\x{1f412}|\x{1f413}|\x{1f414}|\x{1f415}|\x{1f416}|\x{1f417}|\x{1f418}|\x{1f419}|\x{1f41a}|\x{1f41b}|\x{1f41c}|\x{1f41d}|\x{1f41e}|\x{1f41f}|\x{1f420}|\x{1f421}|\x{1f422}|\x{1f423}|\x{1f424}|\x{1f425}|\x{1f426}|\x{1f427}|\x{1f428}|\x{1f429}|\x{1f42a}|\x{1f42b}|\x{1f42c}|\x{1f42d}|\x{1f42e}|\x{1f42f}|\x{1f430}|\x{1f431}|\x{1f432}|\x{1f433}|\x{1f434}|\x{1f435}|\x{1f436}|\x{1f437}|\x{1f438}|\x{1f439}|\x{1f43a}|\x{1f43b}|\x{1f43c}|\x{1f43d}|\x{1f43e}|\x{1f440}|\x{1f444}|\x{1f445}|\x{1f451}|\x{1f452}|\x{1f453}|\x{1f454}|\x{1f455}|\x{1f456}|\x{1f457}|\x{1f458}|\x{1f459}|\x{1f45a}|\x{1f45b}|\x{1f45c}|\x{1f45d}|\x{1f45e}|\x{1f45f}|\x{1f460}|\x{1f461}|\x{1f462}|\x{1f463}|\x{1f464}|\x{1f465}|\x{1f46a}|\x{1f46b}|\x{1f46c}|\x{1f46d}|\x{1f46f}|\x{1f479}|\x{1f47a}|\x{1f47b}|\x{1f47d}|\x{1f47e}|\x{1f47f}|\x{1f480}|\x{1f484}|\x{1f488}|\x{1f489}|\x{1f48a}|\x{1f48b}|\x{1f48c}|\x{1f48d}|\x{1f48e}|\x{1f48f}|\x{1f490}|\x{1f491}|\x{1f492}|\x{1f493}|\x{1f494}|\x{1f495}|\x{1f496}|\x{1f497}|\x{1f498}|\x{1f499}|\x{1f49a}|\x{1f49b}|\x{1f49c}|\x{1f49d}|\x{1f49e}|\x{1f49f}|\x{1f4a0}|\x{1f4a1}|\x{1f4a2}|\x{1f4a3}|\x{1f4a4}|\x{1f4a5}|\x{1f4a6}|\x{1f4a7}|\x{1f4a8}|\x{1f4a9}|\x{1f4ab}|\x{1f4ac}|\x{1f4ad}|\x{1f4ae}|\x{1f4af}|\x{1f4b0}|\x{1f4b1}|\x{1f4b2}|\x{1f4b3}|\x{1f4b4}|\x{1f4b5}|\x{1f4b6}|\x{1f4b7}|\x{1f4b8}|\x{1f4b9}|\x{1f4ba}|\x{1f4bb}|\x{1f4bc}|\x{1f4bd}|\x{1f4be}|\x{1f4bf}|\x{1f4c0}|\x{1f4c1}|\x{1f4c2}|\x{1f4c3}|\x{1f4c4}|\x{1f4c5}|\x{1f4c6}|\x{1f4c7}|\x{1f4c8}|\x{1f4c9}|\x{1f4ca}|\x{1f4cb}|\x{1f4cc}|\x{1f4cd}|\x{1f4ce}|\x{1f4cf}|\x{1f4d0}|\x{1f4d1}|\x{1f4d2}|\x{1f4d3}|\x{1f4d4}|\x{1f4d5}|\x{1f4d6}|\x{1f4d7}|\x{1f4d8}|\x{1f4d9}|\x{1f4da}|\x{1f4db}|\x{1f4dc}|\x{1f4dd}|\x{1f4de}|\x{1f4df}|\x{1f4e0}|\x{1f4e1}|\x{1f4e2}|\x{1f4e3}|\x{1f4e4}|\x{1f4e5}|\x{1f4e6}|\x{1f4e7}|\x{1f4e8}|\x{1f4e9}|\x{1f4ea}|\x{1f4eb}|\x{1f4ec}|\x{1f4ed}|\x{1f4ee}|\x{1f4ef}|\x{1f4f0}|\x{1f4f1}|\x{1f4f2}|\x{1f4f3}|\x{1f4f4}|\x{1f4f5}|\x{1f4f6}|\x{1f4f7}|\x{1f4f8}|\x{1f4f9}|\x{1f4fa}|\x{1f4fb}|\x{1f4fc}|\x{1f4ff}|\x{1f500}|\x{1f501}|\x{1f502}|\x{1f503}|\x{1f504}|\x{1f505}|\x{1f506}|\x{1f507}|\x{1f508}|\x{1f509}|\x{1f50a}|\x{1f50b}|\x{1f50c}|\x{1f50d}|\x{1f50e}|\x{1f50f}|\x{1f510}|\x{1f511}|\x{1f512}|\x{1f513}|\x{1f514}|\x{1f515}|\x{1f516}|\x{1f517}|\x{1f518}|\x{1f519}|\x{1f51a}|\x{1f51b}|\x{1f51c}|\x{1f51d}|\x{1f51e}|\x{1f51f}|\x{1f520}|\x{1f521}|\x{1f522}|\x{1f523}|\x{1f524}|\x{1f525}|\x{1f526}|\x{1f527}|\x{1f528}|\x{1f529}|\x{1f52a}|\x{1f52b}|\x{1f52c}|\x{1f52d}|\x{1f52e}|\x{1f52f}|\x{1f530}|\x{1f531}|\x{1f532}|\x{1f533}|\x{1f534}|\x{1f535}|\x{1f536}|\x{1f537}|\x{1f538}|\x{1f539}|\x{1f53a}|\x{1f53b}|\x{1f53c}|\x{1f53d}|\x{1f54b}|\x{1f54c}|\x{1f54d}|\x{1f54e}|\x{1f550}|\x{1f551}|\x{1f552}|\x{1f553}|\x{1f554}|\x{1f555}|\x{1f556}|\x{1f557}|\x{1f558}|\x{1f559}|\x{1f55a}|\x{1f55b}|\x{1f55c}|\x{1f55d}|\x{1f55e}|\x{1f55f}|\x{1f560}|\x{1f561}|\x{1f562}|\x{1f563}|\x{1f564}|\x{1f565}|\x{1f566}|\x{1f567}|\x{1f5a4}|\x{1f5fb}|\x{1f5fc}|\x{1f5fd}|\x{1f5fe}|\x{1f5ff}|\x{1f600}|\x{1f601}|\x{1f602}|\x{1f603}|\x{1f604}|\x{1f605}|\x{1f606}|\x{1f607}|\x{1f608}|\x{1f609}|\x{1f60a}|\x{1f60b}|\x{1f60c}|\x{1f60d}|\x{1f60e}|\x{1f60f}|\x{1f610}|\x{1f611}|\x{1f612}|\x{1f613}|\x{1f614}|\x{1f615}|\x{1f616}|\x{1f617}|\x{1f618}|\x{1f619}|\x{1f61a}|\x{1f61b}|\x{1f61c}|\x{1f61d}|\x{1f61e}|\x{1f61f}|\x{1f620}|\x{1f621}|\x{1f622}|\x{1f623}|\x{1f624}|\x{1f625}|\x{1f626}|\x{1f627}|\x{1f628}|\x{1f629}|\x{1f62a}|\x{1f62b}|\x{1f62c}|\x{1f62d}|\x{1f62e}|\x{1f62f}|\x{1f630}|\x{1f631}|\x{1f632}|\x{1f633}|\x{1f634}|\x{1f635}|\x{1f636}|\x{1f637}|\x{1f638}|\x{1f639}|\x{1f63a}|\x{1f63b}|\x{1f63c}|\x{1f63d}|\x{1f63e}|\x{1f63f}|\x{1f640}|\x{1f641}|\x{1f642}|\x{1f643}|\x{1f644}|\x{1f648}|\x{1f649}|\x{1f64a}|\x{1f680}|\x{1f681}|\x{1f682}|\x{1f683}|\x{1f684}|\x{1f685}|\x{1f686}|\x{1f687}|\x{1f688}|\x{1f689}|\x{1f68a}|\x{1f68b}|\x{1f68c}|\x{1f68d}|\x{1f68e}|\x{1f68f}|\x{1f690}|\x{1f691}|\x{1f692}|\x{1f693}|\x{1f694}|\x{1f695}|\x{1f696}|\x{1f697}|\x{1f698}|\x{1f699}|\x{1f69a}|\x{1f69b}|\x{1f69c}|\x{1f69d}|\x{1f69e}|\x{1f69f}|\x{1f6a0}|\x{1f6a1}|\x{1f6a2}|\x{1f6a4}|\x{1f6a5}|\x{1f6a6}|\x{1f6a7}|\x{1f6a8}|\x{1f6a9}|\x{1f6aa}|\x{1f6ab}|\x{1f6ac}|\x{1f6ad}|\x{1f6ae}|\x{1f6af}|\x{1f6b0}|\x{1f6b1}|\x{1f6b2}|\x{1f6b3}|\x{1f6b7}|\x{1f6b8}|\x{1f6b9}|\x{1f6ba}|\x{1f6bb}|\x{1f6bc}|\x{1f6bd}|\x{1f6be}|\x{1f6bf}|\x{1f6c1}|\x{1f6c2}|\x{1f6c3}|\x{1f6c4}|\x{1f6c5}|\x{1f6d0}|\x{1f6d1}|\x{1f6d2}|\x{1f6eb}|\x{1f6ec}|\x{1f6f4}|\x{1f6f5}|\x{1f6f6}|\x{1f6f7}|\x{1f6f8}|\x{1f910}|\x{1f911}|\x{1f912}|\x{1f913}|\x{1f914}|\x{1f915}|\x{1f916}|\x{1f917}|\x{1f91d}|\x{1f920}|\x{1f921}|\x{1f922}|\x{1f923}|\x{1f924}|\x{1f925}|\x{1f927}|\x{1f928}|\x{1f929}|\x{1f92a}|\x{1f92b}|\x{1f92c}|\x{1f92d}|\x{1f92e}|\x{1f92f}|\x{1f93a}|\x{1f93c}|\x{1f940}|\x{1f941}|\x{1f942}|\x{1f943}|\x{1f944}|\x{1f945}|\x{1f947}|\x{1f948}|\x{1f949}|\x{1f94a}|\x{1f94b}|\x{1f94c}|\x{1f950}|\x{1f951}|\x{1f952}|\x{1f953}|\x{1f954}|\x{1f955}|\x{1f956}|\x{1f957}|\x{1f958}|\x{1f959}|\x{1f95a}|\x{1f95b}|\x{1f95c}|\x{1f95d}|\x{1f95e}|\x{1f95f}|\x{1f960}|\x{1f961}|\x{1f962}|\x{1f963}|\x{1f964}|\x{1f965}|\x{1f966}|\x{1f967}|\x{1f968}|\x{1f969}|\x{1f96a}|\x{1f96b}|\x{1f980}|\x{1f981}|\x{1f982}|\x{1f983}|\x{1f984}|\x{1f985}|\x{1f986}|\x{1f987}|\x{1f988}|\x{1f989}|\x{1f98a}|\x{1f98b}|\x{1f98c}|\x{1f98d}|\x{1f98e}|\x{1f98f}|\x{1f990}|\x{1f991}|\x{1f992}|\x{1f993}|\x{1f994}|\x{1f995}|\x{1f996}|\x{1f997}|\x{1f9c0}|\x{1f9d0}|\x{1f9de}|\x{1f9df}|\x{1f9e0}|\x{1f9e1}|\x{1f9e2}|\x{1f9e3}|\x{1f9e4}|\x{1f9e5}|\x{1f9e6}|[\x{23e9}\x{23ea}\x{23eb}\x{23ec}\x{23f0}\x{23f3}\x{2640}\x{2642}\x{2695}\x{26ce}\x{2705}\x{2728}\x{274c}\x{274e}\x{2753}\x{2754}\x{2755}\x{2795}\x{2796}\x{2797}\x{27b0}\x{27bf}\x{e50a}]|(?:\x{1f004}|\x{1f170}|\x{1f171}|\x{1f17e}|\x{1f17f}|\x{1f202}|\x{1f21a}|\x{1f22f}|\x{1f237}|\x{1f321}|\x{1f324}|\x{1f325}|\x{1f326}|\x{1f327}|\x{1f328}|\x{1f329}|\x{1f32a}|\x{1f32b}|\x{1f32c}|\x{1f336}|\x{1f37d}|\x{1f396}|\x{1f397}|\x{1f399}|\x{1f39a}|\x{1f39b}|\x{1f39e}|\x{1f39f}|\x{1f3cd}|\x{1f3ce}|\x{1f3d4}|\x{1f3d5}|\x{1f3d6}|\x{1f3d7}|\x{1f3d8}|\x{1f3d9}|\x{1f3da}|\x{1f3db}|\x{1f3dc}|\x{1f3dd}|\x{1f3de}|\x{1f3df}|\x{1f3f3}|\x{1f3f5}|\x{1f3f7}|\x{1f43f}|\x{1f441}|\x{1f4fd}|\x{1f549}|\x{1f54a}|\x{1f56f}|\x{1f570}|\x{1f573}|\x{1f576}|\x{1f577}|\x{1f578}|\x{1f579}|\x{1f587}|\x{1f58a}|\x{1f58b}|\x{1f58c}|\x{1f58d}|\x{1f5a5}|\x{1f5a8}|\x{1f5b1}|\x{1f5b2}|\x{1f5bc}|\x{1f5c2}|\x{1f5c3}|\x{1f5c4}|\x{1f5d1}|\x{1f5d2}|\x{1f5d3}|\x{1f5dc}|\x{1f5dd}|\x{1f5de}|\x{1f5e1}|\x{1f5e3}|\x{1f5e8}|\x{1f5ef}|\x{1f5f3}|\x{1f5fa}|\x{1f6cb}|\x{1f6cd}|\x{1f6ce}|\x{1f6cf}|\x{1f6e0}|\x{1f6e1}|\x{1f6e2}|\x{1f6e3}|\x{1f6e4}|\x{1f6e5}|\x{1f6e9}|\x{1f6f0}|\x{1f6f3}|[\x{00a9}\x{00ae}\x{203c}\x{2049}\x{2122}\x{2139}\x{2194}\x{2195}\x{2196}\x{2197}\x{2198}\x{2199}\x{21a9}\x{21aa}\x{231a}\x{231b}\x{2328}\x{23cf}\x{23ed}\x{23ee}\x{23ef}\x{23f1}\x{23f2}\x{23f8}\x{23f9}\x{23fa}\x{24c2}\x{25aa}\x{25ab}\x{25b6}\x{25c0}\x{25fb}\x{25fc}\x{25fd}\x{25fe}\x{2600}\x{2601}\x{2602}\x{2603}\x{2604}\x{260e}\x{2611}\x{2614}\x{2615}\x{2618}\x{2620}\x{2622}\x{2623}\x{2626}\x{262a}\x{262e}\x{262f}\x{2638}\x{2639}\x{263a}\x{2648}\x{2649}\x{264a}\x{264b}\x{264c}\x{264d}\x{264e}\x{264f}\x{2650}\x{2651}\x{2652}\x{2653}\x{2660}\x{2663}\x{2665}\x{2666}\x{2668}\x{267b}\x{267f}\x{2692}\x{2693}\x{2694}\x{2696}\x{2697}\x{2699}\x{269b}\x{269c}\x{26a0}\x{26a1}\x{26aa}\x{26ab}\x{26b0}\x{26b1}\x{26bd}\x{26be}\x{26c4}\x{26c5}\x{26c8}\x{26cf}\x{26d1}\x{26d3}\x{26d4}\x{26e9}\x{26ea}\x{26f0}\x{26f1}\x{26f2}\x{26f3}\x{26f4}\x{26f5}\x{26f8}\x{26fa}\x{26fd}\x{2702}\x{2708}\x{2709}\x{270f}\x{2712}\x{2714}\x{2716}\x{271d}\x{2721}\x{2733}\x{2734}\x{2744}\x{2747}\x{2757}\x{2763}\x{2764}\x{27a1}\x{2934}\x{2935}\x{2b05}\x{2b06}\x{2b07}\x{2b1b}\x{2b1c}\x{2b50}\x{2b55}\x{3030}\x{303d}\x{3297}\x{3299}])(?:\x{fe0f}|(?!\x{fe0e})))/u';
     5310        $entities = '/(&#x1f468;|&#x1f469;(?:&#x1f3fb;|&#x1f3fc;|&#x1f3fd;|&#x1f3fe;|&#x1f3ff;)?&#x200d;(?:&#x2695;&#xfe0f;|&#x2696;&#xfe0f;|&#x2708;&#xfe0f;|&#x1f33e;|&#x1f373;|&#x1f393;|&#x1f3a4;|&#x1f3a8;|&#x1f3eb;|&#x1f3ed;|&#x1f4bb;|&#x1f4bc;|&#x1f527;|&#x1f52c;|&#x1f680;|&#x1f692;)|(?:&#x1f3cb;|&#x1f3cc;|&#x1f575;|&#x26f9;)(?:&#xfe0f;|&#x1f3fb;|&#x1f3fc;|&#x1f3fd;|&#x1f3fe;|&#x1f3ff;)&#x200d;&#x2640;&#xfe0f;|&#x200d;&#x2642;&#xfe0f;|(?:&#x1f3c3;|&#x1f3c4;|&#x1f3ca;|&#x1f46e;|&#x1f471;|&#x1f473;|&#x1f477;|&#x1f481;|&#x1f482;|&#x1f486;|&#x1f487;|&#x1f645;|&#x1f646;|&#x1f647;|&#x1f64b;|&#x1f64d;|&#x1f64e;|&#x1f6a3;|&#x1f6b4;|&#x1f6b5;|&#x1f6b6;|&#x1f926;|&#x1f937;|&#x1f938;|&#x1f939;|&#x1f93d;|&#x1f93e;|&#x1f9d6;|&#x1f9d7;|&#x1f9d8;|&#x1f9d9;|&#x1f9da;|&#x1f9db;|&#x1f9dc;|&#x1f9dd;)(?:&#x1f3fb;|&#x1f3fc;|&#x1f3fd;|&#x1f3fe;|&#x1f3ff;)?&#x200d;&#x2640;&#xfe0f;|&#x200d;&#x2642;&#xfe0f;|&#x1f468;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;|&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f466;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f467;|&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;|&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f468;|&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f48b;&#x200d;&#x1f469;|&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;|&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;|&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;|&#x1f468;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f468;|&#x1f468;&#x200d;&#x1f466;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f467;&#x200d;&#x1f467;|&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f468;&#x200d;&#x1f467;|&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f469;&#x200d;&#x1f467;|&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f468;|&#x1f469;&#x200d;&#x2764;&#xfe0f;&#x200d;&#x1f469;|&#x1f469;&#x200d;&#x1f466;&#x200d;&#x1f466;|&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f466;|&#x1f469;&#x200d;&#x1f467;&#x200d;&#x1f467;|&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f466;|&#x1f469;&#x200d;&#x1f469;&#x200d;&#x1f467;|&#x1f3f3;&#xfe0f;&#x200d;&#x1f308;|&#x1f3f4;&#x200d;&#x2620;&#xfe0f;|&#x1f441;&#x200d;&#x1f5e8;|&#x1f468;&#x200d;&#x1f466;|&#x1f468;&#x200d;&#x1f467;|&#x1f469;&#x200d;&#x1f466;|&#x1f469;&#x200d;&#x1f467;|&#x1f46f;&#x200d;&#x2640;&#xfe0f;|&#x1f46f;&#x200d;&#x2642;&#xfe0f;|&#x1f93c;&#x200d;&#x2640;&#xfe0f;|&#x1f93c;&#x200d;&#x2642;&#xfe0f;|&#x1f9de;&#x200d;&#x2640;&#xfe0f;|&#x1f9de;&#x200d;&#x2642;&#xfe0f;|&#x1f9df;&#x200d;&#x2640;&#xfe0f;|&#x1f9df;&#x200d;&#x2642;&#xfe0f;|(?:(?:&#x0023;|&#x002a;|&#x30;|&#x31;|&#x32;|&#x33;|&#x34;|&#x35;|&#x36;|&#x37;|&#x38;|&#x39;))&#xfe0f;?&#x20e3;|(?:(?:&#x1f3cb;|&#x1f3cc;|&#x1f574;|&#x1f575;|&#x1f590;|(?:&#x261d;|&#x26f7;|&#x26f9;|&#x270c;|&#x270d;))(?:&#xfe0f;|(?!&#xfe0e;))|&#x1f385;|&#x1f3c2;|&#x1f3c3;|&#x1f3c4;|&#x1f3c7;|&#x1f3ca;|&#x1f442;|&#x1f443;|&#x1f446;|&#x1f447;|&#x1f448;|&#x1f449;|&#x1f44a;|&#x1f44b;|&#x1f44c;|&#x1f44d;|&#x1f44e;|&#x1f44f;|&#x1f450;|&#x1f466;|&#x1f467;|&#x1f468;|&#x1f469;|&#x1f46e;|&#x1f470;|&#x1f471;|&#x1f472;|&#x1f473;|&#x1f474;|&#x1f475;|&#x1f476;|&#x1f477;|&#x1f478;|&#x1f47c;|&#x1f481;|&#x1f482;|&#x1f483;|&#x1f485;|&#x1f486;|&#x1f487;|&#x1f4aa;|&#x1f57a;|&#x1f595;|&#x1f596;|&#x1f645;|&#x1f646;|&#x1f647;|&#x1f64b;|&#x1f64c;|&#x1f64d;|&#x1f64e;|&#x1f64f;|&#x1f6a3;|&#x1f6b4;|&#x1f6b5;|&#x1f6b6;|&#x1f6c0;|&#x1f6cc;|&#x1f918;|&#x1f919;|&#x1f91a;|&#x1f91b;|&#x1f91c;|&#x1f91e;|&#x1f91f;|&#x1f926;|&#x1f930;|&#x1f931;|&#x1f932;|&#x1f933;|&#x1f934;|&#x1f935;|&#x1f936;|&#x1f937;|&#x1f938;|&#x1f939;|&#x1f93d;|&#x1f93e;|&#x1f9d1;|&#x1f9d2;|&#x1f9d3;|&#x1f9d4;|&#x1f9d5;|&#x1f9d6;|&#x1f9d7;|&#x1f9d8;|&#x1f9d9;|&#x1f9da;|&#x1f9db;|&#x1f9dc;|&#x1f9dd;|(?:&#x270a;|&#x270b;))(?:&#x1f3fb;|&#x1f3fc;|&#x1f3fd;|&#x1f3fe;|&#x1f3ff;|)|&#x1f3f4;&#xe0067;&#xe0062;&#xe0065;&#xe006e;&#xe0067;&#xe007f;|&#x1f3f4;&#xe0067;&#xe0062;&#xe0073;&#xe0063;&#xe0074;&#xe007f;|&#x1f3f4;&#xe0067;&#xe0062;&#xe0077;&#xe006c;&#xe0073;&#xe007f;|&#x1f1e6;&#x1f1e8;|&#x1f1e6;&#x1f1e9;|&#x1f1e6;&#x1f1ea;|&#x1f1e6;&#x1f1eb;|&#x1f1e6;&#x1f1ec;|&#x1f1e6;&#x1f1ee;|&#x1f1e6;&#x1f1f1;|&#x1f1e6;&#x1f1f2;|&#x1f1e6;&#x1f1f4;|&#x1f1e6;&#x1f1f6;|&#x1f1e6;&#x1f1f7;|&#x1f1e6;&#x1f1f8;|&#x1f1e6;&#x1f1f9;|&#x1f1e6;&#x1f1fa;|&#x1f1e6;&#x1f1fc;|&#x1f1e6;&#x1f1fd;|&#x1f1e6;&#x1f1ff;|&#x1f1e7;&#x1f1e6;|&#x1f1e7;&#x1f1e7;|&#x1f1e7;&#x1f1e9;|&#x1f1e7;&#x1f1ea;|&#x1f1e7;&#x1f1eb;|&#x1f1e7;&#x1f1ec;|&#x1f1e7;&#x1f1ed;|&#x1f1e7;&#x1f1ee;|&#x1f1e7;&#x1f1ef;|&#x1f1e7;&#x1f1f1;|&#x1f1e7;&#x1f1f2;|&#x1f1e7;&#x1f1f3;|&#x1f1e7;&#x1f1f4;|&#x1f1e7;&#x1f1f6;|&#x1f1e7;&#x1f1f7;|&#x1f1e7;&#x1f1f8;|&#x1f1e7;&#x1f1f9;|&#x1f1e7;&#x1f1fb;|&#x1f1e7;&#x1f1fc;|&#x1f1e7;&#x1f1fe;|&#x1f1e7;&#x1f1ff;|&#x1f1e8;&#x1f1e6;|&#x1f1e8;&#x1f1e8;|&#x1f1e8;&#x1f1e9;|&#x1f1e8;&#x1f1eb;|&#x1f1e8;&#x1f1ec;|&#x1f1e8;&#x1f1ed;|&#x1f1e8;&#x1f1ee;|&#x1f1e8;&#x1f1f0;|&#x1f1e8;&#x1f1f1;|&#x1f1e8;&#x1f1f2;|&#x1f1e8;&#x1f1f3;|&#x1f1e8;&#x1f1f4;|&#x1f1e8;&#x1f1f5;|&#x1f1e8;&#x1f1f7;|&#x1f1e8;&#x1f1fa;|&#x1f1e8;&#x1f1fb;|&#x1f1e8;&#x1f1fc;|&#x1f1e8;&#x1f1fd;|&#x1f1e8;&#x1f1fe;|&#x1f1e8;&#x1f1ff;|&#x1f1e9;&#x1f1ea;|&#x1f1e9;&#x1f1ec;|&#x1f1e9;&#x1f1ef;|&#x1f1e9;&#x1f1f0;|&#x1f1e9;&#x1f1f2;|&#x1f1e9;&#x1f1f4;|&#x1f1e9;&#x1f1ff;|&#x1f1ea;&#x1f1e6;|&#x1f1ea;&#x1f1e8;|&#x1f1ea;&#x1f1ea;|&#x1f1ea;&#x1f1ec;|&#x1f1ea;&#x1f1ed;|&#x1f1ea;&#x1f1f7;|&#x1f1ea;&#x1f1f8;|&#x1f1ea;&#x1f1f9;|&#x1f1ea;&#x1f1fa;|&#x1f1eb;&#x1f1ee;|&#x1f1eb;&#x1f1ef;|&#x1f1eb;&#x1f1f0;|&#x1f1eb;&#x1f1f2;|&#x1f1eb;&#x1f1f4;|&#x1f1eb;&#x1f1f7;|&#x1f1ec;&#x1f1e6;|&#x1f1ec;&#x1f1e7;|&#x1f1ec;&#x1f1e9;|&#x1f1ec;&#x1f1ea;|&#x1f1ec;&#x1f1eb;|&#x1f1ec;&#x1f1ec;|&#x1f1ec;&#x1f1ed;|&#x1f1ec;&#x1f1ee;|&#x1f1ec;&#x1f1f1;|&#x1f1ec;&#x1f1f2;|&#x1f1ec;&#x1f1f3;|&#x1f1ec;&#x1f1f5;|&#x1f1ec;&#x1f1f6;|&#x1f1ec;&#x1f1f7;|&#x1f1ec;&#x1f1f8;|&#x1f1ec;&#x1f1f9;|&#x1f1ec;&#x1f1fa;|&#x1f1ec;&#x1f1fc;|&#x1f1ec;&#x1f1fe;|&#x1f1ed;&#x1f1f0;|&#x1f1ed;&#x1f1f2;|&#x1f1ed;&#x1f1f3;|&#x1f1ed;&#x1f1f7;|&#x1f1ed;&#x1f1f9;|&#x1f1ed;&#x1f1fa;|&#x1f1ee;&#x1f1e8;|&#x1f1ee;&#x1f1e9;|&#x1f1ee;&#x1f1ea;|&#x1f1ee;&#x1f1f1;|&#x1f1ee;&#x1f1f2;|&#x1f1ee;&#x1f1f3;|&#x1f1ee;&#x1f1f4;|&#x1f1ee;&#x1f1f6;|&#x1f1ee;&#x1f1f7;|&#x1f1ee;&#x1f1f8;|&#x1f1ee;&#x1f1f9;|&#x1f1ef;&#x1f1ea;|&#x1f1ef;&#x1f1f2;|&#x1f1ef;&#x1f1f4;|&#x1f1ef;&#x1f1f5;|&#x1f1f0;&#x1f1ea;|&#x1f1f0;&#x1f1ec;|&#x1f1f0;&#x1f1ed;|&#x1f1f0;&#x1f1ee;|&#x1f1f0;&#x1f1f2;|&#x1f1f0;&#x1f1f3;|&#x1f1f0;&#x1f1f5;|&#x1f1f0;&#x1f1f7;|&#x1f1f0;&#x1f1fc;|&#x1f1f0;&#x1f1fe;|&#x1f1f0;&#x1f1ff;|&#x1f1f1;&#x1f1e6;|&#x1f1f1;&#x1f1e7;|&#x1f1f1;&#x1f1e8;|&#x1f1f1;&#x1f1ee;|&#x1f1f1;&#x1f1f0;|&#x1f1f1;&#x1f1f7;|&#x1f1f1;&#x1f1f8;|&#x1f1f1;&#x1f1f9;|&#x1f1f1;&#x1f1fa;|&#x1f1f1;&#x1f1fb;|&#x1f1f1;&#x1f1fe;|&#x1f1f2;&#x1f1e6;|&#x1f1f2;&#x1f1e8;|&#x1f1f2;&#x1f1e9;|&#x1f1f2;&#x1f1ea;|&#x1f1f2;&#x1f1eb;|&#x1f1f2;&#x1f1ec;|&#x1f1f2;&#x1f1ed;|&#x1f1f2;&#x1f1f0;|&#x1f1f2;&#x1f1f1;|&#x1f1f2;&#x1f1f2;|&#x1f1f2;&#x1f1f3;|&#x1f1f2;&#x1f1f4;|&#x1f1f2;&#x1f1f5;|&#x1f1f2;&#x1f1f6;|&#x1f1f2;&#x1f1f7;|&#x1f1f2;&#x1f1f8;|&#x1f1f2;&#x1f1f9;|&#x1f1f2;&#x1f1fa;|&#x1f1f2;&#x1f1fb;|&#x1f1f2;&#x1f1fc;|&#x1f1f2;&#x1f1fd;|&#x1f1f2;&#x1f1fe;|&#x1f1f2;&#x1f1ff;|&#x1f1f3;&#x1f1e6;|&#x1f1f3;&#x1f1e8;|&#x1f1f3;&#x1f1ea;|&#x1f1f3;&#x1f1eb;|&#x1f1f3;&#x1f1ec;|&#x1f1f3;&#x1f1ee;|&#x1f1f3;&#x1f1f1;|&#x1f1f3;&#x1f1f4;|&#x1f1f3;&#x1f1f5;|&#x1f1f3;&#x1f1f7;|&#x1f1f3;&#x1f1fa;|&#x1f1f3;&#x1f1ff;|&#x1f1f4;&#x1f1f2;|&#x1f1f5;&#x1f1e6;|&#x1f1f5;&#x1f1ea;|&#x1f1f5;&#x1f1eb;|&#x1f1f5;&#x1f1ec;|&#x1f1f5;&#x1f1ed;|&#x1f1f5;&#x1f1f0;|&#x1f1f5;&#x1f1f1;|&#x1f1f5;&#x1f1f2;|&#x1f1f5;&#x1f1f3;|&#x1f1f5;&#x1f1f7;|&#x1f1f5;&#x1f1f8;|&#x1f1f5;&#x1f1f9;|&#x1f1f5;&#x1f1fc;|&#x1f1f5;&#x1f1fe;|&#x1f1f6;&#x1f1e6;|&#x1f1f7;&#x1f1ea;|&#x1f1f7;&#x1f1f4;|&#x1f1f7;&#x1f1f8;|&#x1f1f7;&#x1f1fa;|&#x1f1f7;&#x1f1fc;|&#x1f1f8;&#x1f1e6;|&#x1f1f8;&#x1f1e7;|&#x1f1f8;&#x1f1e8;|&#x1f1f8;&#x1f1e9;|&#x1f1f8;&#x1f1ea;|&#x1f1f8;&#x1f1ec;|&#x1f1f8;&#x1f1ed;|&#x1f1f8;&#x1f1ee;|&#x1f1f8;&#x1f1ef;|&#x1f1f8;&#x1f1f0;|&#x1f1f8;&#x1f1f1;|&#x1f1f8;&#x1f1f2;|&#x1f1f8;&#x1f1f3;|&#x1f1f8;&#x1f1f4;|&#x1f1f8;&#x1f1f7;|&#x1f1f8;&#x1f1f8;|&#x1f1f8;&#x1f1f9;|&#x1f1f8;&#x1f1fb;|&#x1f1f8;&#x1f1fd;|&#x1f1f8;&#x1f1fe;|&#x1f1f8;&#x1f1ff;|&#x1f1f9;&#x1f1e6;|&#x1f1f9;&#x1f1e8;|&#x1f1f9;&#x1f1e9;|&#x1f1f9;&#x1f1eb;|&#x1f1f9;&#x1f1ec;|&#x1f1f9;&#x1f1ed;|&#x1f1f9;&#x1f1ef;|&#x1f1f9;&#x1f1f0;|&#x1f1f9;&#x1f1f1;|&#x1f1f9;&#x1f1f2;|&#x1f1f9;&#x1f1f3;|&#x1f1f9;&#x1f1f4;|&#x1f1f9;&#x1f1f7;|&#x1f1f9;&#x1f1f9;|&#x1f1f9;&#x1f1fb;|&#x1f1f9;&#x1f1fc;|&#x1f1f9;&#x1f1ff;|&#x1f1fa;&#x1f1e6;|&#x1f1fa;&#x1f1ec;|&#x1f1fa;&#x1f1f2;|&#x1f1fa;&#x1f1f3;|&#x1f1fa;&#x1f1f8;|&#x1f1fa;&#x1f1fe;|&#x1f1fa;&#x1f1ff;|&#x1f1fb;&#x1f1e6;|&#x1f1fb;&#x1f1e8;|&#x1f1fb;&#x1f1ea;|&#x1f1fb;&#x1f1ec;|&#x1f1fb;&#x1f1ee;|&#x1f1fb;&#x1f1f3;|&#x1f1fb;&#x1f1fa;|&#x1f1fc;&#x1f1eb;|&#x1f1fc;&#x1f1f8;|&#x1f1fd;&#x1f1f0;|&#x1f1fe;&#x1f1ea;|&#x1f1fe;&#x1f1f9;|&#x1f1ff;&#x1f1e6;|&#x1f1ff;&#x1f1f2;|&#x1f1ff;&#x1f1fc;|&#x10000;|&#x1f0cf;|&#x1f18e;|&#x1f191;|&#x1f192;|&#x1f193;|&#x1f194;|&#x1f195;|&#x1f196;|&#x1f197;|&#x1f198;|&#x1f199;|&#x1f19a;|&#x1f1e6;|&#x1f1e7;|&#x1f1e8;|&#x1f1e9;|&#x1f1ea;|&#x1f1eb;|&#x1f1ec;|&#x1f1ed;|&#x1f1ee;|&#x1f1ef;|&#x1f1f0;|&#x1f1f1;|&#x1f1f2;|&#x1f1f3;|&#x1f1f4;|&#x1f1f5;|&#x1f1f6;|&#x1f1f7;|&#x1f1f8;|&#x1f1f9;|&#x1f1fa;|&#x1f1fb;|&#x1f1fc;|&#x1f1fd;|&#x1f1fe;|&#x1f1ff;|&#x1f201;|&#x1f232;|&#x1f233;|&#x1f234;|&#x1f235;|&#x1f236;|&#x1f238;|&#x1f239;|&#x1f23a;|&#x1f250;|&#x1f251;|&#x1f300;|&#x1f301;|&#x1f302;|&#x1f303;|&#x1f304;|&#x1f305;|&#x1f306;|&#x1f307;|&#x1f308;|&#x1f309;|&#x1f30a;|&#x1f30b;|&#x1f30c;|&#x1f30d;|&#x1f30e;|&#x1f30f;|&#x1f310;|&#x1f311;|&#x1f312;|&#x1f313;|&#x1f314;|&#x1f315;|&#x1f316;|&#x1f317;|&#x1f318;|&#x1f319;|&#x1f31a;|&#x1f31b;|&#x1f31c;|&#x1f31d;|&#x1f31e;|&#x1f31f;|&#x1f320;|&#x1f32d;|&#x1f32e;|&#x1f32f;|&#x1f330;|&#x1f331;|&#x1f332;|&#x1f333;|&#x1f334;|&#x1f335;|&#x1f337;|&#x1f338;|&#x1f339;|&#x1f33a;|&#x1f33b;|&#x1f33c;|&#x1f33d;|&#x1f33e;|&#x1f33f;|&#x1f340;|&#x1f341;|&#x1f342;|&#x1f343;|&#x1f344;|&#x1f345;|&#x1f346;|&#x1f347;|&#x1f348;|&#x1f349;|&#x1f34a;|&#x1f34b;|&#x1f34c;|&#x1f34d;|&#x1f34e;|&#x1f34f;|&#x1f350;|&#x1f351;|&#x1f352;|&#x1f353;|&#x1f354;|&#x1f355;|&#x1f356;|&#x1f357;|&#x1f358;|&#x1f359;|&#x1f35a;|&#x1f35b;|&#x1f35c;|&#x1f35d;|&#x1f35e;|&#x1f35f;|&#x1f360;|&#x1f361;|&#x1f362;|&#x1f363;|&#x1f364;|&#x1f365;|&#x1f366;|&#x1f367;|&#x1f368;|&#x1f369;|&#x1f36a;|&#x1f36b;|&#x1f36c;|&#x1f36d;|&#x1f36e;|&#x1f36f;|&#x1f370;|&#x1f371;|&#x1f372;|&#x1f373;|&#x1f374;|&#x1f375;|&#x1f376;|&#x1f377;|&#x1f378;|&#x1f379;|&#x1f37a;|&#x1f37b;|&#x1f37c;|&#x1f37e;|&#x1f37f;|&#x1f380;|&#x1f381;|&#x1f382;|&#x1f383;|&#x1f384;|&#x1f386;|&#x1f387;|&#x1f388;|&#x1f389;|&#x1f38a;|&#x1f38b;|&#x1f38c;|&#x1f38d;|&#x1f38e;|&#x1f38f;|&#x1f390;|&#x1f391;|&#x1f392;|&#x1f393;|&#x1f3a0;|&#x1f3a1;|&#x1f3a2;|&#x1f3a3;|&#x1f3a4;|&#x1f3a5;|&#x1f3a6;|&#x1f3a7;|&#x1f3a8;|&#x1f3a9;|&#x1f3aa;|&#x1f3ab;|&#x1f3ac;|&#x1f3ad;|&#x1f3ae;|&#x1f3af;|&#x1f3b0;|&#x1f3b1;|&#x1f3b2;|&#x1f3b3;|&#x1f3b4;|&#x1f3b5;|&#x1f3b6;|&#x1f3b7;|&#x1f3b8;|&#x1f3b9;|&#x1f3ba;|&#x1f3bb;|&#x1f3bc;|&#x1f3bd;|&#x1f3be;|&#x1f3bf;|&#x1f3c0;|&#x1f3c1;|&#x1f3c5;|&#x1f3c6;|&#x1f3c8;|&#x1f3c9;|&#x1f3cf;|&#x1f3d0;|&#x1f3d1;|&#x1f3d2;|&#x1f3d3;|&#x1f3e0;|&#x1f3e1;|&#x1f3e2;|&#x1f3e3;|&#x1f3e4;|&#x1f3e5;|&#x1f3e6;|&#x1f3e7;|&#x1f3e8;|&#x1f3e9;|&#x1f3ea;|&#x1f3eb;|&#x1f3ec;|&#x1f3ed;|&#x1f3ee;|&#x1f3ef;|&#x1f3f0;|&#x1f3f4;|&#x1f3f8;|&#x1f3f9;|&#x1f3fa;|&#x1f3fb;|&#x1f3fc;|&#x1f3fd;|&#x1f3fe;|&#x1f3ff;|&#x1f400;|&#x1f401;|&#x1f402;|&#x1f403;|&#x1f404;|&#x1f405;|&#x1f406;|&#x1f407;|&#x1f408;|&#x1f409;|&#x1f40a;|&#x1f40b;|&#x1f40c;|&#x1f40d;|&#x1f40e;|&#x1f40f;|&#x1f410;|&#x1f411;|&#x1f412;|&#x1f413;|&#x1f414;|&#x1f415;|&#x1f416;|&#x1f417;|&#x1f418;|&#x1f419;|&#x1f41a;|&#x1f41b;|&#x1f41c;|&#x1f41d;|&#x1f41e;|&#x1f41f;|&#x1f420;|&#x1f421;|&#x1f422;|&#x1f423;|&#x1f424;|&#x1f425;|&#x1f426;|&#x1f427;|&#x1f428;|&#x1f429;|&#x1f42a;|&#x1f42b;|&#x1f42c;|&#x1f42d;|&#x1f42e;|&#x1f42f;|&#x1f430;|&#x1f431;|&#x1f432;|&#x1f433;|&#x1f434;|&#x1f435;|&#x1f436;|&#x1f437;|&#x1f438;|&#x1f439;|&#x1f43a;|&#x1f43b;|&#x1f43c;|&#x1f43d;|&#x1f43e;|&#x1f440;|&#x1f444;|&#x1f445;|&#x1f451;|&#x1f452;|&#x1f453;|&#x1f454;|&#x1f455;|&#x1f456;|&#x1f457;|&#x1f458;|&#x1f459;|&#x1f45a;|&#x1f45b;|&#x1f45c;|&#x1f45d;|&#x1f45e;|&#x1f45f;|&#x1f460;|&#x1f461;|&#x1f462;|&#x1f463;|&#x1f464;|&#x1f465;|&#x1f46a;|&#x1f46b;|&#x1f46c;|&#x1f46d;|&#x1f46f;|&#x1f479;|&#x1f47a;|&#x1f47b;|&#x1f47d;|&#x1f47e;|&#x1f47f;|&#x1f480;|&#x1f484;|&#x1f488;|&#x1f489;|&#x1f48a;|&#x1f48b;|&#x1f48c;|&#x1f48d;|&#x1f48e;|&#x1f48f;|&#x1f490;|&#x1f491;|&#x1f492;|&#x1f493;|&#x1f494;|&#x1f495;|&#x1f496;|&#x1f497;|&#x1f498;|&#x1f499;|&#x1f49a;|&#x1f49b;|&#x1f49c;|&#x1f49d;|&#x1f49e;|&#x1f49f;|&#x1f4a0;|&#x1f4a1;|&#x1f4a2;|&#x1f4a3;|&#x1f4a4;|&#x1f4a5;|&#x1f4a6;|&#x1f4a7;|&#x1f4a8;|&#x1f4a9;|&#x1f4ab;|&#x1f4ac;|&#x1f4ad;|&#x1f4ae;|&#x1f4af;|&#x1f4b0;|&#x1f4b1;|&#x1f4b2;|&#x1f4b3;|&#x1f4b4;|&#x1f4b5;|&#x1f4b6;|&#x1f4b7;|&#x1f4b8;|&#x1f4b9;|&#x1f4ba;|&#x1f4bb;|&#x1f4bc;|&#x1f4bd;|&#x1f4be;|&#x1f4bf;|&#x1f4c0;|&#x1f4c1;|&#x1f4c2;|&#x1f4c3;|&#x1f4c4;|&#x1f4c5;|&#x1f4c6;|&#x1f4c7;|&#x1f4c8;|&#x1f4c9;|&#x1f4ca;|&#x1f4cb;|&#x1f4cc;|&#x1f4cd;|&#x1f4ce;|&#x1f4cf;|&#x1f4d0;|&#x1f4d1;|&#x1f4d2;|&#x1f4d3;|&#x1f4d4;|&#x1f4d5;|&#x1f4d6;|&#x1f4d7;|&#x1f4d8;|&#x1f4d9;|&#x1f4da;|&#x1f4db;|&#x1f4dc;|&#x1f4dd;|&#x1f4de;|&#x1f4df;|&#x1f4e0;|&#x1f4e1;|&#x1f4e2;|&#x1f4e3;|&#x1f4e4;|&#x1f4e5;|&#x1f4e6;|&#x1f4e7;|&#x1f4e8;|&#x1f4e9;|&#x1f4ea;|&#x1f4eb;|&#x1f4ec;|&#x1f4ed;|&#x1f4ee;|&#x1f4ef;|&#x1f4f0;|&#x1f4f1;|&#x1f4f2;|&#x1f4f3;|&#x1f4f4;|&#x1f4f5;|&#x1f4f6;|&#x1f4f7;|&#x1f4f8;|&#x1f4f9;|&#x1f4fa;|&#x1f4fb;|&#x1f4fc;|&#x1f4ff;|&#x1f500;|&#x1f501;|&#x1f502;|&#x1f503;|&#x1f504;|&#x1f505;|&#x1f506;|&#x1f507;|&#x1f508;|&#x1f509;|&#x1f50a;|&#x1f50b;|&#x1f50c;|&#x1f50d;|&#x1f50e;|&#x1f50f;|&#x1f510;|&#x1f511;|&#x1f512;|&#x1f513;|&#x1f514;|&#x1f515;|&#x1f516;|&#x1f517;|&#x1f518;|&#x1f519;|&#x1f51a;|&#x1f51b;|&#x1f51c;|&#x1f51d;|&#x1f51e;|&#x1f51f;|&#x1f520;|&#x1f521;|&#x1f522;|&#x1f523;|&#x1f524;|&#x1f525;|&#x1f526;|&#x1f527;|&#x1f528;|&#x1f529;|&#x1f52a;|&#x1f52b;|&#x1f52c;|&#x1f52d;|&#x1f52e;|&#x1f52f;|&#x1f530;|&#x1f531;|&#x1f532;|&#x1f533;|&#x1f534;|&#x1f535;|&#x1f536;|&#x1f537;|&#x1f538;|&#x1f539;|&#x1f53a;|&#x1f53b;|&#x1f53c;|&#x1f53d;|&#x1f54b;|&#x1f54c;|&#x1f54d;|&#x1f54e;|&#x1f550;|&#x1f551;|&#x1f552;|&#x1f553;|&#x1f554;|&#x1f555;|&#x1f556;|&#x1f557;|&#x1f558;|&#x1f559;|&#x1f55a;|&#x1f55b;|&#x1f55c;|&#x1f55d;|&#x1f55e;|&#x1f55f;|&#x1f560;|&#x1f561;|&#x1f562;|&#x1f563;|&#x1f564;|&#x1f565;|&#x1f566;|&#x1f567;|&#x1f5a4;|&#x1f5fb;|&#x1f5fc;|&#x1f5fd;|&#x1f5fe;|&#x1f5ff;|&#x1f600;|&#x1f601;|&#x1f602;|&#x1f603;|&#x1f604;|&#x1f605;|&#x1f606;|&#x1f607;|&#x1f608;|&#x1f609;|&#x1f60a;|&#x1f60b;|&#x1f60c;|&#x1f60d;|&#x1f60e;|&#x1f60f;|&#x1f610;|&#x1f611;|&#x1f612;|&#x1f613;|&#x1f614;|&#x1f615;|&#x1f616;|&#x1f617;|&#x1f618;|&#x1f619;|&#x1f61a;|&#x1f61b;|&#x1f61c;|&#x1f61d;|&#x1f61e;|&#x1f61f;|&#x1f620;|&#x1f621;|&#x1f622;|&#x1f623;|&#x1f624;|&#x1f625;|&#x1f626;|&#x1f627;|&#x1f628;|&#x1f629;|&#x1f62a;|&#x1f62b;|&#x1f62c;|&#x1f62d;|&#x1f62e;|&#x1f62f;|&#x1f630;|&#x1f631;|&#x1f632;|&#x1f633;|&#x1f634;|&#x1f635;|&#x1f636;|&#x1f637;|&#x1f638;|&#x1f639;|&#x1f63a;|&#x1f63b;|&#x1f63c;|&#x1f63d;|&#x1f63e;|&#x1f63f;|&#x1f640;|&#x1f641;|&#x1f642;|&#x1f643;|&#x1f644;|&#x1f648;|&#x1f649;|&#x1f64a;|&#x1f680;|&#x1f681;|&#x1f682;|&#x1f683;|&#x1f684;|&#x1f685;|&#x1f686;|&#x1f687;|&#x1f688;|&#x1f689;|&#x1f68a;|&#x1f68b;|&#x1f68c;|&#x1f68d;|&#x1f68e;|&#x1f68f;|&#x1f690;|&#x1f691;|&#x1f692;|&#x1f693;|&#x1f694;|&#x1f695;|&#x1f696;|&#x1f697;|&#x1f698;|&#x1f699;|&#x1f69a;|&#x1f69b;|&#x1f69c;|&#x1f69d;|&#x1f69e;|&#x1f69f;|&#x1f6a0;|&#x1f6a1;|&#x1f6a2;|&#x1f6a4;|&#x1f6a5;|&#x1f6a6;|&#x1f6a7;|&#x1f6a8;|&#x1f6a9;|&#x1f6aa;|&#x1f6ab;|&#x1f6ac;|&#x1f6ad;|&#x1f6ae;|&#x1f6af;|&#x1f6b0;|&#x1f6b1;|&#x1f6b2;|&#x1f6b3;|&#x1f6b7;|&#x1f6b8;|&#x1f6b9;|&#x1f6ba;|&#x1f6bb;|&#x1f6bc;|&#x1f6bd;|&#x1f6be;|&#x1f6bf;|&#x1f6c1;|&#x1f6c2;|&#x1f6c3;|&#x1f6c4;|&#x1f6c5;|&#x1f6d0;|&#x1f6d1;|&#x1f6d2;|&#x1f6eb;|&#x1f6ec;|&#x1f6f4;|&#x1f6f5;|&#x1f6f6;|&#x1f6f7;|&#x1f6f8;|&#x1f910;|&#x1f911;|&#x1f912;|&#x1f913;|&#x1f914;|&#x1f915;|&#x1f916;|&#x1f917;|&#x1f91d;|&#x1f920;|&#x1f921;|&#x1f922;|&#x1f923;|&#x1f924;|&#x1f925;|&#x1f927;|&#x1f928;|&#x1f929;|&#x1f92a;|&#x1f92b;|&#x1f92c;|&#x1f92d;|&#x1f92e;|&#x1f92f;|&#x1f93a;|&#x1f93c;|&#x1f940;|&#x1f941;|&#x1f942;|&#x1f943;|&#x1f944;|&#x1f945;|&#x1f947;|&#x1f948;|&#x1f949;|&#x1f94a;|&#x1f94b;|&#x1f94c;|&#x1f950;|&#x1f951;|&#x1f952;|&#x1f953;|&#x1f954;|&#x1f955;|&#x1f956;|&#x1f957;|&#x1f958;|&#x1f959;|&#x1f95a;|&#x1f95b;|&#x1f95c;|&#x1f95d;|&#x1f95e;|&#x1f95f;|&#x1f960;|&#x1f961;|&#x1f962;|&#x1f963;|&#x1f964;|&#x1f965;|&#x1f966;|&#x1f967;|&#x1f968;|&#x1f969;|&#x1f96a;|&#x1f96b;|&#x1f980;|&#x1f981;|&#x1f982;|&#x1f983;|&#x1f984;|&#x1f985;|&#x1f986;|&#x1f987;|&#x1f988;|&#x1f989;|&#x1f98a;|&#x1f98b;|&#x1f98c;|&#x1f98d;|&#x1f98e;|&#x1f98f;|&#x1f990;|&#x1f991;|&#x1f992;|&#x1f993;|&#x1f994;|&#x1f995;|&#x1f996;|&#x1f997;|&#x1f9c0;|&#x1f9d0;|&#x1f9de;|&#x1f9df;|&#x1f9e0;|&#x1f9e1;|&#x1f9e2;|&#x1f9e3;|&#x1f9e4;|&#x1f9e5;|&#x1f9e6;|(?:&#x23e9;|&#x23ea;|&#x23eb;|&#x23ec;|&#x23f0;|&#x23f3;|&#x2640;|&#x2642;|&#x2695;|&#x26ce;|&#x2705;|&#x2728;|&#x274c;|&#x274e;|&#x2753;|&#x2754;|&#x2755;|&#x2795;|&#x2796;|&#x2797;|&#x27b0;|&#x27bf;|&#xe50a;)|(?:&#x1f004;|&#x1f170;|&#x1f171;|&#x1f17e;|&#x1f17f;|&#x1f202;|&#x1f21a;|&#x1f22f;|&#x1f237;|&#x1f321;|&#x1f324;|&#x1f325;|&#x1f326;|&#x1f327;|&#x1f328;|&#x1f329;|&#x1f32a;|&#x1f32b;|&#x1f32c;|&#x1f336;|&#x1f37d;|&#x1f396;|&#x1f397;|&#x1f399;|&#x1f39a;|&#x1f39b;|&#x1f39e;|&#x1f39f;|&#x1f3cd;|&#x1f3ce;|&#x1f3d4;|&#x1f3d5;|&#x1f3d6;|&#x1f3d7;|&#x1f3d8;|&#x1f3d9;|&#x1f3da;|&#x1f3db;|&#x1f3dc;|&#x1f3dd;|&#x1f3de;|&#x1f3df;|&#x1f3f3;|&#x1f3f5;|&#x1f3f7;|&#x1f43f;|&#x1f441;|&#x1f4fd;|&#x1f549;|&#x1f54a;|&#x1f56f;|&#x1f570;|&#x1f573;|&#x1f576;|&#x1f577;|&#x1f578;|&#x1f579;|&#x1f587;|&#x1f58a;|&#x1f58b;|&#x1f58c;|&#x1f58d;|&#x1f5a5;|&#x1f5a8;|&#x1f5b1;|&#x1f5b2;|&#x1f5bc;|&#x1f5c2;|&#x1f5c3;|&#x1f5c4;|&#x1f5d1;|&#x1f5d2;|&#x1f5d3;|&#x1f5dc;|&#x1f5dd;|&#x1f5de;|&#x1f5e1;|&#x1f5e3;|&#x1f5e8;|&#x1f5ef;|&#x1f5f3;|&#x1f5fa;|&#x1f6cb;|&#x1f6cd;|&#x1f6ce;|&#x1f6cf;|&#x1f6e0;|&#x1f6e1;|&#x1f6e2;|&#x1f6e3;|&#x1f6e4;|&#x1f6e5;|&#x1f6e9;|&#x1f6f0;|&#x1f6f3;|(?:&#x00a9;|&#x00ae;|&#x203c;|&#x2049;|&#x2122;|&#x2139;|&#x2194;|&#x2195;|&#x2196;|&#x2197;|&#x2198;|&#x2199;|&#x21a9;|&#x21aa;|&#x231a;|&#x231b;|&#x2328;|&#x23cf;|&#x23ed;|&#x23ee;|&#x23ef;|&#x23f1;|&#x23f2;|&#x23f8;|&#x23f9;|&#x23fa;|&#x24c2;|&#x25aa;|&#x25ab;|&#x25b6;|&#x25c0;|&#x25fb;|&#x25fc;|&#x25fd;|&#x25fe;|&#x2600;|&#x2601;|&#x2602;|&#x2603;|&#x2604;|&#x260e;|&#x2611;|&#x2614;|&#x2615;|&#x2618;|&#x2620;|&#x2622;|&#x2623;|&#x2626;|&#x262a;|&#x262e;|&#x262f;|&#x2638;|&#x2639;|&#x263a;|&#x2648;|&#x2649;|&#x264a;|&#x264b;|&#x264c;|&#x264d;|&#x264e;|&#x264f;|&#x2650;|&#x2651;|&#x2652;|&#x2653;|&#x2660;|&#x2663;|&#x2665;|&#x2666;|&#x2668;|&#x267b;|&#x267f;|&#x2692;|&#x2693;|&#x2694;|&#x2696;|&#x2697;|&#x2699;|&#x269b;|&#x269c;|&#x26a0;|&#x26a1;|&#x26aa;|&#x26ab;|&#x26b0;|&#x26b1;|&#x26bd;|&#x26be;|&#x26c4;|&#x26c5;|&#x26c8;|&#x26cf;|&#x26d1;|&#x26d3;|&#x26d4;|&#x26e9;|&#x26ea;|&#x26f0;|&#x26f1;|&#x26f2;|&#x26f3;|&#x26f4;|&#x26f5;|&#x26f8;|&#x26fa;|&#x26fd;|&#x2702;|&#x2708;|&#x2709;|&#x270f;|&#x2712;|&#x2714;|&#x2716;|&#x271d;|&#x2721;|&#x2733;|&#x2734;|&#x2744;|&#x2747;|&#x2757;|&#x2763;|&#x2764;|&#x27a1;|&#x2934;|&#x2935;|&#x2b05;|&#x2b06;|&#x2b07;|&#x2b1b;|&#x2b1c;|&#x2b50;|&#x2b55;|&#x3030;|&#x303d;|&#x3297;|&#x3299;))(?:&#xfe0f;|(?!&#xfe0e;)))/u';
     5311        // END: emoji regex
     5312
     5313        if ( 'entities' === $type ) {
     5314                return $entities;
     5315        }
     5316
     5317        return $codepoints;
     5318}
     5319
     5320/**
    52835321 * Shorten a URL, to be used as link text.
    52845322 *
  • branches/4.8/tests/phpunit/tests/formatting/Emoji.php

    r40837 r41069  
    33/**
    44 * @group formatting
     5 * @group emoji
    56 */
    67class Tests_Formatting_Emoji extends WP_UnitTestCase {
     8
     9        private $png_cdn = 'https://s.w.org/images/core/emoji/2.3/72x72/';
     10        private $svn_cdn = 'https://s.w.org/images/core/emoji/2.3/svg/';
     11
    712        /**
    813         * @ticket 36525
    914         */
    1015        public function test_unfiltered_emoji_cdns() {
    11                 $png_cdn = 'https://s.w.org/images/core/emoji/2.3/72x72/';
    12                 $svn_cdn = 'https://s.w.org/images/core/emoji/2.3/svg/';
    13 
    1416                $output = get_echo( '_print_emoji_detection_script' );
    1517
    16                 $this->assertContains( wp_json_encode( $png_cdn ), $output );
    17                 $this->assertContains( wp_json_encode( $svn_cdn ), $output );
     18                $this->assertContains( wp_json_encode( $this->png_cdn ), $output );
     19                $this->assertContains( wp_json_encode( $this->svn_cdn ), $output );
    1820        }
    1921
     
    2628         */
    2729        public function test_filtered_emoji_svn_cdn() {
    28                 $png_cdn = 'https://s.w.org/images/core/emoji/2.3/72x72/';
    29                 $svn_cdn = 'https://s.w.org/images/core/emoji/2.3/svg/';
    30 
    3130                $filtered_svn_cdn = $this->_filtered_emoji_svn_cdn();
    3231
     
    3534                $output = get_echo( '_print_emoji_detection_script' );
    3635
    37                 $this->assertContains( wp_json_encode( $png_cdn ), $output );
    38                 $this->assertNotContains( wp_json_encode( $svn_cdn ), $output );
     36                $this->assertContains( wp_json_encode( $this->png_cdn ), $output );
     37                $this->assertNotContains( wp_json_encode( $this->svn_cdn ), $output );
    3938                $this->assertContains( wp_json_encode( $filtered_svn_cdn ), $output );
    4039
     
    5049         */
    5150        public function test_filtered_emoji_png_cdn() {
    52                 $png_cdn = 'https://s.w.org/images/core/emoji/2.3/72x72/';
    53                 $svn_cdn = 'https://s.w.org/images/core/emoji/2.3/svg/';
    54 
    5551                $filtered_png_cdn = $this->_filtered_emoji_png_cdn();
    5652
     
    6056
    6157                $this->assertContains( wp_json_encode( $filtered_png_cdn ), $output );
    62                 $this->assertNotContains( wp_json_encode( $png_cdn ), $output );
    63                 $this->assertContains( wp_json_encode( $svn_cdn ), $output );
     58                $this->assertNotContains( wp_json_encode( $this->png_cdn ), $output );
     59                $this->assertContains( wp_json_encode( $this->svn_cdn ), $output );
    6460
    6561                remove_filter( 'emoji_url', array( $this, '_filtered_emoji_png_cdn' ) );
    6662        }
    6763
     64        /**
     65         * @ticket 35293
     66         */
     67        public function test_wp_emoji_regex_returns_regexen() {
     68                $default = wp_emoji_regex();
     69                $this->assertNotEmpty( $default );
     70
     71                $codepoints = wp_emoji_regex( 'codepoints' );
     72                $this->assertNotEmpty( $codepoints );
     73
     74                $this->assertSame( $default, $codepoints );
     75
     76                $entities = wp_emoji_regex( 'entities' );
     77                $this->assertNotEmpty( $entities );
     78
     79                $this->assertNotSame( $default, $entities );
     80        }
     81
     82        public function data_wp_encode_emoji() {
     83                return array(
     84                        array(
     85                                // Not emoji
     86                                '’',
     87                                '’',
     88                        ),
     89                        array(
     90                                // Simple emoji
     91                                '🙂',
     92                                '&#x1f642;',
     93                        ),
     94                        array(
     95                                // Skin tone, gender, ZWJ, emoji selector
     96                                '👮🏼‍♀️',
     97                                '&#x1f46e;&#x1f3fc;&#x200d;&#x2640;&#xfe0f;',
     98                        ),
     99                        array(
     100                                // Unicode 10
     101                                '🧚',
     102                                '&#x1f9da;',
     103                        ),
     104                );
     105        }
     106
     107        /**
     108         * @ticket 35293
     109         * @dataProvider data_wp_encode_emoji
     110         */
     111        public function test_wp_encode_emoji( $emoji, $expected ) {
     112                $this->assertSame( $expected, wp_encode_emoji( $emoji ) );
     113        }
     114
     115        public function data_wp_staticize_emoji() {
     116                $data = array(
     117                        array(
     118                                // Not emoji
     119                                '’',
     120                                '’',
     121                        ),
     122                        array(
     123                                // Simple emoji
     124                                '🙂',
     125                                '<img src="' . $this->png_cdn . '1f642.png" alt="" class="wp-smiley" style="height: 1em; max-height: 1em;" />',
     126                        ),
     127                        array(
     128                                // Skin tone, gender, ZWJ, emoji selector
     129                                '👮🏼‍♀️',
     130                                '<img src="' . $this->png_cdn . '1f46e-1f3fc-200d-2640-fe0f.png" alt="" class="wp-smiley" style="height: 1em; max-height: 1em;" />',
     131                        ),
     132                        array(
     133                                // Unicode 10
     134                                '🧚',
     135                                '<img src="' . $this->png_cdn . '1f9da.png" alt="" class="wp-smiley" style="height: 1em; max-height: 1em;" />',
     136                        ),
     137                );
     138
     139                // Older versions of PHP don't html_entity_decode() emoji, so we need to make sure they're testing in the expected form.
     140                foreach ( $data as $key => $datum ) {
     141                        $emoji = html_entity_decode( wp_encode_emoji( $datum[0] ) );
     142                        $data[ $key ][1] = str_replace( 'alt=""', 'alt="' . $emoji . '"', $datum[1] );
     143                }
     144
     145                return $data;
     146        }
     147
     148        /**
     149         * @ticket 35293
     150         * @dataProvider data_wp_staticize_emoji
     151         */
     152        public function test_wp_staticize_emoji( $emoji, $expected ) {
     153                $this->assertSame( $expected, wp_staticize_emoji( $emoji ) );
     154        }
    68155}
  • branches/4.8/tests/phpunit/tests/formatting/Smilies.php

    r38504 r41069  
    33/**
    44 * @group formatting
     5 * @group emoji
    56 */
    67class Tests_Formatting_Smilies extends WP_UnitTestCase {
Note: See TracChangeset for help on using the changeset viewer.