text: (function (root, factory) {
      'use strict';
  
      if (typeof define === 'function' && define.amd) {
          // AMD. Register as an anonymous module.
          define([], factory);
      } else if (typeof exports === 'object') {
          // Node. Does not work with strict CommonJS, but
          // only CommonJS-like environments that support module.exports,
          // like Node.
          module.exports = factory();
      } else {
          // Browser globals (root is window)
          root.emojify = factory();
      }
  }(this, function () {
          'use strict';
  
          var emojify = (function () {
              /**
               * NB!
               * The namedEmojiString variable is updated automatically by the
               * "update" gulp task. Do not remove the comment as this will
               * cause the gulp task to stop working.
               */
              var namedEmojiString =
              /*##EMOJILIST*/"+1,-1,100,1234,8ball,a,ab,abc,abcd,accept,aerial_tramway,airplane,alarm_clock,alien,ambulance,anchor,angel,anger,angry,anguished,ant,apple,aquarius,aries,arrow_backward,arrow_double_down,arrow_double_up,arrow_down,arrow_down_small,arrow_forward,arrow_heading_down,arrow_heading_up,arrow_left,arrow_lower_left,arrow_lower_right,arrow_right,arrow_right_hook,arrow_up,arrow_up_down,arrow_up_small,arrow_upper_left,arrow_upper_right,arrows_clockwise,arrows_counterclockwise,art,articulated_lorry,astonished,atm,b,baby,baby_bottle,baby_chick,baby_symbol,back,baggage_claim,balloon,ballot_box_with_check,bamboo,banana,bangbang,bank,bar_chart,barber,baseball,basketball,bath,bathtub,battery,bear,bee,beer,beers,beetle,beginner,bell,bento,bicyclist,bike,bikini,bird,birthday,black_circle,black_joker,black_medium_small_square,black_medium_square,black_nib,black_small_square,black_square,black_square_button,blossom,blowfish,blue_book,blue_car,blue_heart,blush,boar,boat,bomb,book,bookmark,bookmark_tabs,books,boom,boot,bouquet,bow,bowling,bowtie,boy,bread,bride_with_veil,bridge_at_night,briefcase,broken_heart,bug,bulb,bullettrain_front,bullettrain_side,bus,busstop,bust_in_silhouette,busts_in_silhouette,cactus,cake,calendar,calling,camel,camera,cancer,candy,capital_abcd,capricorn,car,card_index,carousel_horse,cat,cat2,cd,chart,chart_with_downwards_trend,chart_with_upwards_trend,checkered_flag,cherries,cherry_blossom,chestnut,chicken,children_crossing,chocolate_bar,christmas_tree,church,cinema,circus_tent,city_sunrise,city_sunset,cl,clap,clapper,clipboard,clock1,clock10,clock1030,clock11,clock1130,clock12,clock1230,clock130,clock2,clock230,clock3,clock330,clock4,clock430,clock5,clock530,clock6,clock630,clock7,clock730,clock8,clock830,clock9,clock930,closed_book,closed_lock_with_key,closed_umbrella,cloud,clubs,cn,cocktail,coffee,cold_sweat,collision,computer,confetti_ball,confounded,confused,congratulations,construction,construction_worker,convenience_store,cookie,cool,cop,copyright,corn,couple,couple_with_heart,couplekiss,cow,cow2,credit_card,crocodile,crossed_flags,crown,cry,crying_cat_face,crystal_ball,cupid,curly_loop,currency_exchange,curry,custard,customs,cyclone,dancer,dancers,dango,dart,dash,date,de,deciduous_tree,department_store,diamond_shape_with_a_dot_inside,diamonds,disappointed,disappointed_relieved,dizzy,dizzy_face,do_not_litter,dog,dog2,dollar,dolls,dolphin,donut,door,doughnut,dragon,dragon_face,dress,dromedary_camel,droplet,dvd,e-mail,ear,ear_of_rice,earth_africa,earth_americas,earth_asia,egg,eggplant,eight,eight_pointed_black_star,eight_spoked_asterisk,electric_plug,elephant,email,end,envelope,es,euro,european_castle,european_post_office,evergreen_tree,exclamation,expressionless,eyeglasses,eyes,facepunch,factory,fallen_leaf,family,fast_forward,fax,fearful,feelsgood,feet,ferris_wheel,file_folder,finnadie,fire,fire_engine,fireworks,first_quarter_moon,first_quarter_moon_with_face,fish,fish_cake,fishing_pole_and_fish,fist,five,flags,flashlight,floppy_disk,flower_playing_cards,flushed,foggy,football,fork_and_knife,fountain,four,four_leaf_clover,fr,free,fried_shrimp,fries,frog,frowning,fu,fuelpump,full_moon,full_moon_with_face,game_die,gb,gem,gemini,ghost,gift,gift_heart,girl,globe_with_meridians,goat,goberserk,godmode,golf,grapes,green_apple,green_book,green_heart,grey_exclamation,grey_question,grimacing,grin,grinning,guardsman,guitar,gun,haircut,hamburger,hammer,hamster,hand,handbag,hankey,hash,hatched_chick,hatching_chick,headphones,hear_no_evil,heart,heart_decoration,heart_eyes,heart_eyes_cat,heartbeat,heartpulse,hearts,heavy_check_mark,heavy_division_sign,heavy_dollar_sign,heavy_exclamation_mark,heavy_minus_sign,heavy_multiplication_x,heavy_plus_sign,helicopter,herb,hibiscus,high_brightness,high_heel,hocho,honey_pot,honeybee,horse,horse_racing,hospital,hotel,hotsprings,hourglass,hourglass_flowing_sand,house,house_with_garden,hurtrealbad,hushed,ice_cream,icecream,id,ideograph_advantage,imp,inbox_tray,incoming_envelope,information_desk_person,information_source,innocent,interrobang,iphone,it,izakaya_lantern,jack_o_lantern,japan,japanese_castle,japanese_goblin,japanese_ogre,jeans,joy,joy_cat,jp,key,keycap_ten,kimono,kiss,kissing,kissing_cat,kissing_closed_eyes,kissing_face,kissing_heart,kissing_smiling_eyes,koala,koko,kr,large_blue_circle,large_blue_diamond,large_orange_diamond,last_quarter_moon,last_quarter_moon_with_face,laughing,leaves,ledger,left_luggage,left_right_arrow,leftwards_arrow_with_hook,lemon,leo,leopard,libra,light_rail,link,lips,lipstick,lock,lock_with_ink_pen,lollipop,loop,loudspeaker,love_hotel,love_letter,low_brightness,m,mag,mag_right,mahjong,mailbox,mailbox_closed,mailbox_with_mail,mailbox_with_no_mail,man,man_with_gua_pi_mao,man_with_turban,mans_shoe,maple_leaf,mask,massage,meat_on_bone,mega,melon,memo,mens,metal,metro,microphone,microscope,milky_way,minibus,minidisc,mobile_phone_off,money_with_wings,moneybag,monkey,monkey_face,monorail,moon,mortar_board,mount_fuji,mountain_bicyclist,mountain_cableway,mountain_railway,mouse,mouse2,movie_camera,moyai,muscle,mushroom,musical_keyboard,musical_note,musical_score,mute,nail_care,name_badge,neckbeard,necktie,negative_squared_cross_mark,neutral_face,new,new_moon,new_moon_with_face,newspaper,ng,nine,no_bell,no_bicycles,no_entry,no_entry_sign,no_good,no_mobile_phones,no_mouth,no_pedestrians,no_smoking,non-potable_water,nose,notebook,notebook_with_decorative_cover,notes,nut_and_bolt,o,o2,ocean,octocat,octopus,oden,office,ok,ok_hand,ok_woman,older_man,older_woman,on,oncoming_automobile,oncoming_bus,oncoming_police_car,oncoming_taxi,one,open_file_folder,open_hands,open_mouth,ophiuchus,orange_book,outbox_tray,ox,package,page_facing_up,page_with_curl,pager,palm_tree,panda_face,paperclip,parking,part_alternation_mark,partly_sunny,passport_control,paw_prints,peach,pear,pencil,pencil2,penguin,pensive,performing_arts,persevere,person_frowning,person_with_blond_hair,person_with_pouting_face,phone,pig,pig2,pig_nose,pill,pineapple,pisces,pizza,plus1,point_down,point_left,point_right,point_up,point_up_2,police_car,poodle,poop,post_office,postal_horn,postbox,potable_water,pouch,poultry_leg,pound,pouting_cat,pray,princess,punch,purple_heart,purse,pushpin,put_litter_in_its_place,question,rabbit,rabbit2,racehorse,radio,radio_button,rage,rage1,rage2,rage3,rage4,railway_car,rainbow,raised_hand,raised_hands,raising_hand,ram,ramen,rat,recycle,red_car,red_circle,registered,relaxed,relieved,repeat,repeat_one,restroom,revolving_hearts,rewind,ribbon,rice,rice_ball,rice_cracker,rice_scene,ring,rocket,roller_coaster,rooster,rose,rotating_light,round_pushpin,rowboat,ru,rugby_football,runner,running,running_shirt_with_sash,sa,sagittarius,sailboat,sake,sandal,santa,satellite,satisfied,saxophone,school,school_satchel,scissors,scorpius,scream,scream_cat,scroll,seat,secret,see_no_evil,seedling,seven,shaved_ice,sheep,shell,ship,shipit,shirt,shit,shoe,shower,signal_strength,six,six_pointed_star,ski,skull,sleeping,sleepy,slot_machine,small_blue_diamond,small_orange_diamond,small_red_triangle,small_red_triangle_down,smile,smile_cat,smiley,smiley_cat,smiling_imp,smirk,smirk_cat,smoking,snail,snake,snowboarder,snowflake,snowman,sob,soccer,soon,sos,sound,space_invader,spades,spaghetti,sparkle,sparkler,sparkles,sparkling_heart,speak_no_evil,speaker,speech_balloon,speedboat,squirrel,star,star2,stars,station,statue_of_liberty,steam_locomotive,stew,straight_ruler,strawberry,stuck_out_tongue,stuck_out_tongue_closed_eyes,stuck_out_tongue_winking_eye,sun_with_face,sunflower,sunglasses,sunny,sunrise,sunrise_over_mountains,surfer,sushi,suspect,suspension_railway,sweat,sweat_drops,sweat_smile,sweet_potato,swimmer,symbols,syringe,tada,tanabata_tree,tangerine,taurus,taxi,tea,telephone,telephone_receiver,telescope,tennis,tent,thought_balloon,three,thumbsdown,thumbsup,ticket,tiger,tiger2,tired_face,tm,toilet,tokyo_tower,tomato,tongue,top,tophat,tractor,traffic_light,train,train2,tram,triangular_flag_on_post,triangular_ruler,trident,triumph,trolleybus,trollface,trophy,tropical_drink,tropical_fish,truck,trumpet,tshirt,tulip,turtle,tv,twisted_rightwards_arrows,two,two_hearts,two_men_holding_hands,two_women_holding_hands,u5272,u5408,u55b6,u6307,u6708,u6709,u6e80,u7121,u7533,u7981,u7a7a,uk,umbrella,unamused,underage,unlock,up,us,v,vertical_traffic_light,vhs,vibration_mode,video_camera,video_game,violin,virgo,volcano,vs,walking,waning_crescent_moon,waning_gibbous_moon,warning,watch,water_buffalo,watermelon,wave,wavy_dash,waxing_crescent_moon,waxing_gibbous_moon,wc,weary,wedding,whale,whale2,wheelchair,white_check_mark,white_circle,white_flower,white_large_square,white_medium_small_square,white_medium_square,white_small_square,white_square_button,wind_chime,wine_glass,wink,wolf,woman,womans_clothes,womans_hat,womens,worried,wrench,x,yellow_heart,yen,yum,zap,zero,zzz";
  
              var namedEmoji = namedEmojiString.split(/,/);
  
              /* A hash with the named emoji as keys */
              var namedMatchHash = namedEmoji.reduce(function(memo, v) {
                  memo[v] = true;
                  return memo;
              }, {});
  
              var emoticonsProcessed;
              var emojiMegaRe;
  
              function initEmoticonsProcessed() {
                  /* List of emoticons used in the regular expression */
                  var emoticons = {
           /* :..: */ named: /:([a-z0-9A-Z_-]+):/,
           /* :-)  */ smile: /:-?\)/g,
           /* :-o  */ scream: /:-o/gi,
           /* :-]  */ smirk: /[:;]-?]/g,
           /* :-D  */ grinning: /[:;]-?d/gi,
           /* X-D  */ stuck_out_tongue_closed_eyes: /x-d/gi,
           /* ;-p  */ stuck_out_tongue_winking_eye: /[:;]-?p/gi,
     /* :-[ / :-@  */ rage: /:-?[\[@]/g,
           /* :-(  */ frowning: /:-?\(/g,
           /* :'-( */ sob: /:['’]-?\(|:&#x27;\(/g,
           /* :-*  */ kissing_heart: /:-?\*/g,
           /* ;-)  */ wink: /;-?\)/g,
           /* :-/  */ pensive: /:-?\//g,
           /* :-s  */ confounded: /:-?s/gi,
           /* :-|  */ flushed: /:-?\|/g,
           /* :-$  */ relaxed: /:-?\$/g,
           /* :-x  */ mask: /:-x/gi,
           /* <3   */ heart: /<3|&lt;3/g,
           /* </3  */ broken_heart: /<\/3|&lt;&#x2F;3/g,
           /* :+1: */ thumbsup: /:\+1:/g,
           /* :-1: */ thumbsdown: /:\-1:/g
                  };
  
                  if (defaultConfig.ignore_emoticons) {
                      emoticons = {
               /* :..: */ named: /:([a-z0-9A-Z_-]+):/,
               /* :+1: */ thumbsup: /:\+1:/g,
               /* :-1: */ thumbsdown: /:\-1:/g
                      };
                  }
  
                  return Object.keys(emoticons).map(function(key) {
                      return [emoticons[key], key];
                  });
              }
  
              function initMegaRe() {
                  /* The source for our mega-regex */
                  var mega = emoticonsProcessed
                          .map(function(v) {
                              var re = v[0];
                              var val = re.source || re;
                              val = val.replace(/(^|[^\[])\^/g, '$1');
                              return "(" + val + ")";
                          })
                          .join('|');
  
                  /* The regex used to find emoji */
                  return new RegExp(mega, "gi");
              }
  
              var defaultConfig = {
                  blacklist: {
                      'ids': [],
                      'classes': ['no-emojify'],
                      'elements': ['script', 'textarea', 'a', 'pre', 'code']
                  },
                  tag_type: null,
                  only_crawl_id: null,
                  img_dir: 'images/emoji',
                  ignore_emoticons: false,
                  mode: 'img'
              };
  
              /* Returns true if the given char is whitespace */
              function isWhitespace(s) {
                  return s === ' ' || s === '\t' || s === '\r' || s === '\n' || s === '' || s === String.fromCharCode(160);
              }
  
              var modeToElementTagType = {
                  'img': 'img',
                  'sprite': 'span',
                  'data-uri': 'span'
              };
  
              /* Given a match in a node, replace the text with an image */
              function insertEmojicon(args) {
                  var emojiElement = null;
  
  
                  if(args.replacer){
                      emojiElement = args.replacer.apply({
                              config: defaultConfig
                          },
                          [':' + args.emojiName + ':', args.emojiName]
                      );
                  }
                  else {
                      var elementType = defaultConfig.tag_type || modeToElementTagType[defaultConfig.mode];
                      emojiElement = args.win.document.createElement(elementType);
  
                      if (elementType !== 'img') {
                          emojiElement.setAttribute('class', 'emoji emoji-' + args.emojiName);
                      } else {
                          emojiElement.setAttribute('align', 'absmiddle');
                          emojiElement.setAttribute('alt', ':' + args.emojiName + ':');
                          emojiElement.setAttribute('class', 'emoji');
                          emojiElement.setAttribute('src', defaultConfig.img_dir + '/' + args.emojiName + '.png');
                      }
  
                      emojiElement.setAttribute('title', ':' + args.emojiName + ':');
                  }
  
                  args.node.splitText(args.match.index);
                  args.node.nextSibling.nodeValue = args.node.nextSibling.nodeValue.substr(
                      args.match[0].length,
                      args.node.nextSibling.nodeValue.length
                  );
                  emojiElement.appendChild(args.node.splitText(args.match.index));
                  args.node.parentNode.insertBefore(emojiElement, args.node.nextSibling);
              }
  
              /* Given an regex match, return the name of the matching emoji */
              function getEmojiNameForMatch(match) {
                  /* Special case for named emoji */
                  if(match[1] && match[2]) {
                      var named = match[2];
                      if(namedMatchHash[named]) { return named; }
                      return;
                  }
                  for(var i = 3; i < match.length - 1; i++) {
                      if(match[i]) {
                          return emoticonsProcessed[i - 2][1];
                      }
                  }
              }
  
              function defaultReplacer(emoji, name) {
                  /*jshint validthis: true */
                  var elementType = this.config.tag_type || modeToElementTagType[this.config.mode];
                  if (elementType !== 'img') {
                      return "<" +  elementType +" class='emoji emoji-" + name + "' title=':" + name + ":'></" + elementType+ ">";
                  } else {
                      return "<img align='absmiddle' alt=':" + name + ":' class='emoji' src='" + this.config.img_dir + '/' + name + ".png' title=':" + name + ":' />";
                  }
              }
  
              function Validator() {
                  this.lastEmojiTerminatedAt = -1;
              }
  
              Validator.prototype = {
                  validate: function(match, index, input) {
                      var self = this;
  
                      /* Validator */
                      var emojiName = getEmojiNameForMatch(match);
                      if(!emojiName) { return; }
  
                      var m = match[0];
                      var length = m.length;
                      // var index = match.index;
                      // var input = match.input;
  
                      function success() {
                          self.lastEmojiTerminatedAt = length + index;
                          return emojiName;
                      }
  
                      /* At the beginning? */
                      if(index === 0) { return success(); }
  
                      /* At the end? */
                      if(input.length === m.length + index) { return success(); }
  
                      var hasEmojiBefore = this.lastEmojiTerminatedAt === index;
                      if (hasEmojiBefore) { return success();}
  
                      /* Has a whitespace before? */
                      if(isWhitespace(input.charAt(index - 1))) { return success(); }
  
                      var hasWhitespaceAfter = isWhitespace(input.charAt(m.length + index));
                      /* Has a whitespace after? */
                      if(hasWhitespaceAfter && hasEmojiBefore) { return success(); }
  
                      return;
                  }
              };
  
              function emojifyString (htmlString, replacer) {
                  if(!htmlString) { return htmlString; }
                  if(!replacer) { replacer = defaultReplacer; }
  
                  emoticonsProcessed = initEmoticonsProcessed();
                  emojiMegaRe = initMegaRe();
  
                  var validator = new Validator();
  
                  return htmlString.replace(emojiMegaRe, function() {
                      var matches = Array.prototype.slice.call(arguments, 0, -2);
                      var index = arguments[arguments.length - 2];
                      var input = arguments[arguments.length - 1];
                      var emojiName = validator.validate(matches, index, input);
                      if(emojiName) {
                          return replacer.apply({
                                  config: defaultConfig
                              },
                              [arguments[0], emojiName]
                          );
                      }
                      /* Did not validate, return the original value */
                      return arguments[0];
                  });
  
              }
              function run(el, replacer) {
  
                  // Check if an element was not passed.
                  // This will only work in the browser
                  if(typeof el === 'undefined'){
                      // Check if an element was configured. If not, default to the body.
                      if (defaultConfig.only_crawl_id) {
                          el = document.getElementById(defaultConfig.only_crawl_id);
                      } else {
                          el = document.body;
                      }
                  }
  
                  // Get the window object from the passed element.
                  var doc = el.ownerDocument,
                      win = doc.defaultView || doc.parentWindow;
  
                  var treeTraverse = function (parent, cb){
                      var child;
  
                      if (parent.hasChildNodes()) {
                          child = parent.firstChild;
                          while(child){
                              if(cb(child)) {
                                  treeTraverse(child, cb);
                              }
                              child = child.nextSibling;
                          }
                      }
                  };
  
                  var matchAndInsertEmoji = function(node) {
                      var match;
                      var matches = [];
                      var validator = new Validator();
  
                      while ((match = emojiMegaRe.exec(node.data)) !== null) {
                          if(validator.validate(match, match.index, match.input)) {
                              matches.push(match);
                          }
                      }
  
                      for (var i = matches.length; i-- > 0;) {
                          /* Replace the text with the emoji */
                          var emojiName = getEmojiNameForMatch(matches[i]);
                          insertEmojicon({
                              node: node,
                              match: matches[i],
                              emojiName: emojiName,
                              replacer: replacer,
                              win: win
                          });
                      }
                  };
  
                  emoticonsProcessed = initEmoticonsProcessed();
                  emojiMegaRe = initMegaRe();
  
                  var nodes = [];
  
                  var elementsBlacklist = new RegExp(defaultConfig.blacklist.elements.join('|'), 'i'),
                      classesBlacklist = new RegExp(defaultConfig.blacklist.classes.join('|'), 'i');
  
                  if(typeof win.document.createTreeWalker !== 'undefined') {
                      var nodeIterator = win.document.createTreeWalker(
                          el,
                          win.NodeFilter.SHOW_TEXT | win.NodeFilter.SHOW_ELEMENT,
                          function(node) {
                              if(node.nodeType !== 1) {
                                  /* Text Node? Good! */
                                  return win.NodeFilter.FILTER_ACCEPT;
                              }
                              
                              try {
                                  if(node.tagName.match(elementsBlacklist) || node.className.match(classesBlacklist)) {
                                      return win.NodeFilter.FILTER_REJECT;
                                  }
                              } catch(err) {
                                  return win.NodeFilter.FILTER_SKIP;
                              }
                              return win.NodeFilter.FILTER_SKIP;
                          },
                          false
                      );
  
                      var node;
  
                      while((node = nodeIterator.nextNode()) !== null) {
                          nodes.push(node);
                      }
                  }
                  else {
                      treeTraverse(el, function(node){
                          if(
                              (typeof node.tagName !== 'undefined' && node.tagName.match(elementsBlacklist)) ||
                              (typeof node.className !== 'undefined' && node.className.match(classesBlacklist))
                          ){
                              return false;
                          }
                          if (node.nodeType === 1) {
                              return true;
                          }
  
                          nodes.push(node);
                          return true;
                      });
                  }
  
                  nodes.forEach(matchAndInsertEmoji);
              }
  
              return {
                  // Sane defaults
                  defaultConfig: defaultConfig,
                  emojiNames: namedEmoji,
                  setConfig: function (newConfig) {
                      Object.keys(defaultConfig).forEach(function(f) {
                          if(f in newConfig) {
                              defaultConfig[f] = newConfig[f];
                          }
                      });
                  },
  
                  replace: emojifyString,
  
                  // Main method
                  run: run
              };
          })();
  
          return emojify;
      }
  ));
  