+<style type="text/css">
+img.wp-smiley,
+img.emoji {
+ display: inline !important;
+ border: none !important;
+ box-shadow: none !important;
+ height: 1em !important;
+ width: 1em !important;
+ margin: 0 .07em !important;
+ vertical-align: -0.1em !important;
+ background: none !important;
+ padding: 0 !important;
+}
+</style>
+<?php
+}
+
+/**
+ *
+ * @global string $wp_version
+ * @staticvar bool $printed
+ */
+function print_emoji_detection_script() {
+ global $wp_version;
+ static $printed = false;
+
+ if ( $printed ) {
+ return;
+ }
+
+ $printed = true;
+
+ $settings = array(
+ /**
+ * Filter the URL where emoji images are hosted.
+ *
+ * @since 4.2.0
+ *
+ * @param string The emoji base URL.
+ */
+ 'baseUrl' => apply_filters( 'emoji_url', set_url_scheme( '//s.w.org/images/core/emoji/72x72/' ) ),
+
+ /**
+ * Filter the extension of the emoji files.
+ *
+ * @since 4.2.0
+ *
+ * @param string The emoji extension. Default .png.
+ */
+ 'ext' => apply_filters( 'emoji_ext', '.png' ),
+ );
+
+ $version = 'ver=' . $wp_version;
+
+ if ( SCRIPT_DEBUG ) {
+ $settings['source'] = array(
+ /** This filter is documented in wp-includes/class.wp-scripts.php */
+ 'wpemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji.js?$version" ), 'wpemoji' ),
+ /** This filter is documented in wp-includes/class.wp-scripts.php */
+ 'twemoji' => apply_filters( 'script_loader_src', includes_url( "js/twemoji.js?$version" ), 'twemoji' ),
+ );
+
+ ?>
+ <script type="text/javascript">
+ window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>;
+ <?php readfile( ABSPATH . WPINC . "/js/wp-emoji-loader.js" ); ?>
+ </script>
+ <?php
+ } else {
+ $settings['source'] = array(
+ /** This filter is documented in wp-includes/class.wp-scripts.php */
+ 'concatemoji' => apply_filters( 'script_loader_src', includes_url( "js/wp-emoji-release.min.js?$version" ), 'concatemoji' ),
+ );
+
+ /*
+ * If you're looking at a src version of this file, you'll see an "include"
+ * statement below. This is used by the `grunt build` process to directly
+ * include a minified version of wp-emoji-loader.js, instead of using the
+ * readfile() method from above.
+ *
+ * If you're looking at a build version of this file, you'll see a string of
+ * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG
+ * and edit wp-emoji-loader.js directly.
+ */
+ ?>
+ <script type="text/javascript">
+ window._wpemojiSettings = <?php echo wp_json_encode( $settings ); ?>;
+ !function(a,b,c){function d(a){var c=b.createElement("canvas"),d=c.getContext&&c.getContext("2d");return d&&d.fillText?(d.textBaseline="top",d.font="600 32px Arial","flag"===a?(d.fillText(String.fromCharCode(55356,56812,55356,56807),0,0),c.toDataURL().length>3e3):(d.fillText(String.fromCharCode(55357,56835),0,0),0!==d.getImageData(16,16,1,1).data[0])):!1}function e(a){var c=b.createElement("script");c.src=a,c.type="text/javascript",b.getElementsByTagName("head")[0].appendChild(c)}var f,g;c.supports={simple:d("simple"),flag:d("flag")},c.DOMReady=!1,c.readyCallback=function(){c.DOMReady=!0},c.supports.simple&&c.supports.flag||(g=function(){c.readyCallback()},b.addEventListener?(b.addEventListener("DOMContentLoaded",g,!1),a.addEventListener("load",g,!1)):(a.attachEvent("onload",g),b.attachEvent("onreadystatechange",function(){"complete"===b.readyState&&c.readyCallback()})),f=c.source||{},f.concatemoji?e(f.concatemoji):f.wpemoji&&f.twemoji&&(e(f.twemoji),e(f.wpemoji)))}(window,document,window._wpemojiSettings);
+ </script>
+ <?php
+ }
+}
+
+/**
+ * Convert any 4 byte emoji in a string to their equivalent HTML entity.
+ *
+ * Currently, only Unicode 7 emoji are supported. Skin tone modifiers are allowed,
+ * all other Unicode 8 emoji will be added when the spec is finalised.
+ *
+ * This allows us to store emoji in a DB using the utf8 character set.
+ *
+ * @since 4.2.0
+ *
+ * @param string $content The content to encode.
+ * @return string The encoded content.
+ */
+function wp_encode_emoji( $content ) {
+ if ( function_exists( 'mb_convert_encoding' ) ) {
+ $regex = '/(
+ \x23\xE2\x83\xA3 # Digits
+ [\x30-\x39]\xE2\x83\xA3
+ | \xF0\x9F[\x85-\x88][\xA6-\xBF] # Enclosed characters
+ | \xF0\x9F[\x8C-\x97][\x80-\xBF] # Misc
+ | \xF0\x9F\x98[\x80-\xBF] # Smilies
+ | \xF0\x9F\x99[\x80-\x8F]
+ | \xF0\x9F\x9A[\x80-\xBF] # Transport and map symbols
+ )/x';
+
+ $matches = array();
+ if ( preg_match_all( $regex, $content, $matches ) ) {
+ if ( ! empty( $matches[1] ) ) {
+ foreach( $matches[1] as $emoji ) {
+ /*
+ * UTF-32's hex encoding is the same as HTML's hex encoding.
+ * So, by converting the emoji from UTF-8 to UTF-32, we magically
+ * get the correct hex encoding.
+ */
+ $unpacked = unpack( 'H*', mb_convert_encoding( $emoji, 'UTF-32', 'UTF-8' ) );
+ if ( isset( $unpacked[1] ) ) {
+ $entity = '&#x' . ltrim( $unpacked[1], '0' ) . ';';
+ $content = str_replace( $emoji, $entity, $content );
+ }
+ }
+ }
+ }
+ }
+
+ return $content;
+}
+
+/**
+ * Convert emoji to a static img element.
+ *
+ * @since 4.2.0
+ *
+ * @param string $text The content to encode.
+ * @return string The encoded content.
+ */
+function wp_staticize_emoji( $text ) {
+ $text = wp_encode_emoji( $text );
+
+ /** This filter is documented in wp-includes/formatting.php */
+ $cdn_url = apply_filters( 'emoji_url', set_url_scheme( '//s.w.org/images/core/emoji/72x72/' ) );
+
+ /** This filter is documented in wp-includes/formatting.php */
+ $ext = apply_filters( 'emoji_ext', '.png' );
+
+ $output = '';
+ /*
+ * HTML loop taken from smiley function, which was taken from texturize function.
+ * It'll never be consolidated.
+ *
+ * First, capture the tags as well as in between.
+ */
+ $textarr = preg_split( '/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE );
+ $stop = count( $textarr );
+
+ // Ignore processing of specific tags.
+ $tags_to_ignore = 'code|pre|style|script|textarea';
+ $ignore_block_element = '';
+
+ for ( $i = 0; $i < $stop; $i++ ) {
+ $content = $textarr[$i];
+
+ // If we're in an ignore block, wait until we find its closing tag.
+ if ( '' == $ignore_block_element && preg_match( '/^<(' . $tags_to_ignore . ')>/', $content, $matches ) ) {
+ $ignore_block_element = $matches[1];
+ }
+
+ // If it's not a tag and not in ignore block.
+ if ( '' == $ignore_block_element && strlen( $content ) > 0 && '<' != $content[0] ) {
+ $matches = array();
+ if ( preg_match_all( '/(DZ(e[6-9a-f]|f[0-9a-f]);){2}/', $content, $matches ) ) {
+ if ( ! empty( $matches[0] ) ) {
+ foreach ( $matches[0] as $flag ) {
+ $chars = str_replace( array( '&#x', ';'), '', $flag );
+
+ list( $char1, $char2 ) = str_split( $chars, 5 );
+ $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 ) );
+
+ $content = str_replace( $flag, $entity, $content );
+ }
+ }
+ }
+
+ // Loosely match the Emoji Unicode range.
+ $regex = '/(&#x[2-3][0-9a-f]{3};|[1-6][0-9a-f]{2};)/';
+
+ $matches = array();
+ if ( preg_match_all( $regex, $content, $matches ) ) {
+ if ( ! empty( $matches[1] ) ) {
+ foreach ( $matches[1] as $emoji ) {
+ $char = str_replace( array( '&#x', ';'), '', $emoji );
+ $entity = sprintf( '<img src="%s" alt="%s" class="wp-smiley" style="height: 1em; max-height: 1em;" />', $cdn_url . $char . $ext, html_entity_decode( $emoji ) );
+
+ $content = str_replace( $emoji, $entity, $content );
+ }
+ }
+ }
+ }
+
+ // Did we exit ignore block.
+ if ( '' != $ignore_block_element && '</' . $ignore_block_element . '>' == $content ) {
+ $ignore_block_element = '';
+ }
+
+ $output .= $content;
+ }
+
+ return $output;
+}
+
+/**
+ * Convert emoji in emails into static images.
+ *
+ * @since 4.2.0
+ *
+ * @param array $mail The email data array.
+ * @return array The email data array, with emoji in the message staticized.
+ */
+function wp_staticize_emoji_for_email( $mail ) {
+ if ( ! isset( $mail['message'] ) ) {
+ return $mail;
+ }
+
+ /*
+ * We can only transform the emoji into images if it's a text/html email.
+ * To do that, here's a cut down version of the same process that happens
+ * in wp_mail() - get the Content-Type from the headers, if there is one,
+ * then pass it through the wp_mail_content_type filter, in case a plugin
+ * is handling changing the Content-Type.
+ */
+ $headers = array();
+ if ( isset( $mail['headers'] ) ) {
+ if ( is_array( $mail['headers'] ) ) {
+ $headers = $mail['headers'];
+ } else {
+ $headers = explode( "\n", str_replace( "\r\n", "\n", $mail['headers'] ) );
+ }
+ }
+
+ foreach ( $headers as $header ) {
+ if ( strpos($header, ':') === false ) {
+ continue;
+ }
+
+ // Explode them out.
+ list( $name, $content ) = explode( ':', trim( $header ), 2 );
+
+ // Cleanup crew.
+ $name = trim( $name );
+ $content = trim( $content );
+
+ if ( 'content-type' === strtolower( $name ) ) {
+ if ( strpos( $content, ';' ) !== false ) {
+ list( $type, $charset ) = explode( ';', $content );
+ $content_type = trim( $type );
+ } else {
+ $content_type = trim( $content );
+ }
+ break;
+ }
+ }
+
+ // Set Content-Type if we don't have a content-type from the input headers.
+ if ( ! isset( $content_type ) ) {
+ $content_type = 'text/plain';
+ }
+
+ /** This filter is documented in wp-includes/pluggable.php */
+ $content_type = apply_filters( 'wp_mail_content_type', $content_type );
+
+ if ( 'text/html' === $content_type ) {
+ $mail['message'] = wp_staticize_emoji( $mail['message'] );
+ }
+
+ return $mail;
+}