<commit_before>// TODO @robin to move this whole thing to es6
Discourse.Emoji = {};
// bump up this number to expire all emojis
Discourse.Emoji.ImageVersion = "0"

var emoji = <%= Emoji.standard.map(&:name).flatten.inspect %>;
var aliases = <%= Emoji.aliases.inspect.gsub("=>", ":") %>;

var extendedEmoji = {};
Discourse.Dialect.registerEmoji = function(code, url) {
  code = code.toLowerCase();
  extendedEmoji[code] = url;
};

Discourse.Emoji.list = function(){
  var list = emoji.slice(0);
  _.each(aliases, function(v,k){ list.push(k); });
  _.each(extendedEmoji, function(v,k){ list.push(k); });
  return list;
};

var toSearch;

Discourse.Emoji.search = function(term, options) {
  var maxResults = (options && options["maxResults"]) || -1;
  if (maxResults === 0) { return []; }

  toSearch = toSearch || Discourse.Emoji.list();

  var i, results = [];

  var done = function() {
    return maxResults > 0 && results.length >= maxResults;
  }

  for (i=0; i < toSearch.length; i++) {
    if (toSearch[i].indexOf(term) === 0) {
      results.push(toSearch[i]);
      if(done()) { break; }
    }
  }

  if(!done()){
    for (i=0; i < toSearch.length; i++) {
      if (toSearch[i].indexOf(term) > 0) {
        results.push(toSearch[i]);
        if(done()) { break; }
      }
    }
  }

  return results;
}

var emojiHash = {};
// add all default emojis
emoji.forEach(function(code){ emojiHash[code] = true; });
// and their aliases
for (var name in aliases) {
  aliases[name].forEach(function(alias) {
    emojiHash[alias] = true;
  });
}

Discourse.Emoji.urlFor = urlFor = function(code) {
  var url, set = Discourse.SiteSettings.emoji_set;

  code = code.toLowerCase();

  if(extendedEmoji.hasOwnProperty(code)) {
    url = extendedEmoji[code];
  }

  if(!url && emojiHash.hasOwnProperty(code)) {
    if (aliases.hasOwnProperty(code)) { code = aliases[code]; }
    url = Discourse.getURL('/images/emoji/' + set + '/' + code + '.png');
  }

  if(url && url[0] !== 'h' && Discourse.CDN) {
    url = Discourse.CDN + url;
  }

  if(url){
    url = url + "?v=" + Discourse.Emoji.ImageVersion;
  }

  return url;
}

Discourse.Emoji.exists = function(code){
  code = code.toLowerCase();
  return !!(extendedEmoji.hasOwnProperty(code) || emojiHash.hasOwnProperty(code));
}

function imageFor(code) {
  code = code.toLowerCase();
  var url = urlFor(code);
  if (url) {
    return ['img', { href: url, title: ':' + code + ':', 'class': 'emoji', alt: code }];
  }
}

// Also support default emotions
var translations = {
  ':)'   : 'smile',
  ':-)'  : 'smile',
  ':('   : 'frowning',
  ':-('  : 'frowning',
  ';)'   : 'wink',
  ';-)'  : 'wink',
  ':\'(' : 'cry',
  ':\'-(': 'cry',
  ':-\'(': 'cry',
  ':p'   : 'stuck_out_tongue',
  ':P'   : 'stuck_out_tongue',
  ':-P'  : 'stuck_out_tongue',
  ':O'   : 'open_mouth',
  ':-O'  : 'open_mouth',
  ':D'   : 'smiley',
  ':-D'  : 'smiley',
  ':|'   : 'expressionless',
  ':-|'  : 'expressionless',
  ";P"   : 'stuck_out_tongue_winking_eye',
  ";-P"  : 'stuck_out_tongue_winking_eye',
  ":$"   : 'blush',
  ":-$"  : 'blush'
};

Discourse.Emoji.translations = translations;

function checkPrev(prev) {
  if (prev && prev.length) {
    var lastToken = prev[prev.length-1];
    if (lastToken && lastToken.charAt) {
      var lastChar = lastToken.charAt(lastToken.length-1);
      if (lastChar !== ' ' && lastChar !== "\n") return false;
    }
  }
  return true;
}

var translationsWithColon = {};
Object.keys(translations).forEach(function (t) {
  if (t[0] === ':') {
    translationsWithColon[t] = translations[t];
  } else {
    var replacement = translations[t];
    Discourse.Dialect.inlineReplace(t, function (token, match, prev) {
      if (!Discourse.SiteSettings.enable_emoji) { return token; }
      return checkPrev(prev) ? imageFor(replacement) : token;
    });
  }
});

function escapeRegExp(s) {
  return s.replace(/[-/\\^$*+?.()|[\]{}]/gi, '\\$&');
}

var translationColonRegexp = new RegExp(Object.keys(translationsWithColon).map(function (t) {
                                           return "(" + escapeRegExp(t) + ")";
                                         }).join("|"));

Discourse.Dialect.registerInline(':', function(text, match, prev) {
  if (!Discourse.SiteSettings.enable_emoji) { return; }

  var endPos = text.indexOf(':', 1),
      firstSpace = text.search(/\s/),
      contents;

  if (!checkPrev(prev)) { return; }

  // If there is no trailing colon, check our translations that begin with colons
  if (endPos === -1 || (firstSpace !== -1 && endPos > firstSpace)) {
    translationColonRegexp.lastIndex = 0;
    var m = translationColonRegexp.exec(text);
    if (m && m[0] && text.indexOf(m[0]) === 0) {

      // Check outer edge
      var lastChar = text.charAt(m[0].length);
      if (lastChar && (lastChar !== ' ' && lastChar !== "\n")) return;
      contents = imageFor(translationsWithColon[m[0]]);
      if (contents) {
        return [m[0].length, contents];
      }
    }
    return;
  }

  // Simple find and replace from our array
  var between = text.slice(1, endPos);
  contents = imageFor(between);
  if (contents) {
    return [endPos+1, contents];
  }
});

Discourse.Markdown.whiteListTag('img', 'class', 'emoji');
<commit_msg>FIX: duplicate emojis in emoji-toolbar<commit_after>// TODO @robin to move this whole thing to es6
Discourse.Emoji = {};
// bump up this number to expire all emojis
Discourse.Emoji.ImageVersion = "0"

var emoji = <%= Emoji.standard.map(&:name).flatten.inspect %>;
var aliases = <%= Emoji.aliases.inspect.gsub("=>", ":") %>;

var extendedEmoji = {};
Discourse.Dialect.registerEmoji = function(code, url) {
  code = code.toLowerCase();
  extendedEmoji[code] = url;
};

Discourse.Emoji.list = function(){
  var list = emoji.slice(0);
  _.each(extendedEmoji, function(v,k){ list.push(k); });
  return list;
};

var toSearch;

Discourse.Emoji.search = function(term, options) {
  var maxResults = (options && options["maxResults"]) || -1;
  if (maxResults === 0) { return []; }

  toSearch = toSearch || Discourse.Emoji.list();

  var i, results = [];

  var done = function() {
    return maxResults > 0 && results.length >= maxResults;
  }

  for (i=0; i < toSearch.length; i++) {
    if (toSearch[i].indexOf(term) === 0) {
      results.push(toSearch[i]);
      if(done()) { break; }
    }
  }

  if(!done()){
    for (i=0; i < toSearch.length; i++) {
      if (toSearch[i].indexOf(term) > 0) {
        results.push(toSearch[i]);
        if(done()) { break; }
      }
    }
  }

  return results;
}

var emojiHash = {};
// add all default emojis
emoji.forEach(function(code){ emojiHash[code] = true; });
// and their aliases
for (var name in aliases) {
  aliases[name].forEach(function(alias) {
    emojiHash[alias] = true;
  });
}

Discourse.Emoji.urlFor = urlFor = function(code) {
  var url, set = Discourse.SiteSettings.emoji_set;

  code = code.toLowerCase();

  if(extendedEmoji.hasOwnProperty(code)) {
    url = extendedEmoji[code];
  }

  if(!url && emojiHash.hasOwnProperty(code)) {
    url = Discourse.getURL('/images/emoji/' + set + '/' + code + '.png');
  }

  if(url && url[0] !== 'h' && Discourse.CDN) {
    url = Discourse.CDN + url;
  }

  if(url){
    url = url + "?v=" + Discourse.Emoji.ImageVersion;
  }

  return url;
}

Discourse.Emoji.exists = function(code){
  code = code.toLowerCase();
  return !!(extendedEmoji.hasOwnProperty(code) || emojiHash.hasOwnProperty(code));
}

function imageFor(code) {
  code = code.toLowerCase();
  var url = urlFor(code);
  if (url) {
    return ['img', { href: url, title: ':' + code + ':', 'class': 'emoji', alt: code }];
  }
}

// Also support default emotions
var translations = {
  ':)'   : 'smile',
  ':-)'  : 'smile',
  ':('   : 'frowning',
  ':-('  : 'frowning',
  ';)'   : 'wink',
  ';-)'  : 'wink',
  ':\'(' : 'cry',
  ':\'-(': 'cry',
  ':-\'(': 'cry',
  ':p'   : 'stuck_out_tongue',
  ':P'   : 'stuck_out_tongue',
  ':-P'  : 'stuck_out_tongue',
  ':O'   : 'open_mouth',
  ':-O'  : 'open_mouth',
  ':D'   : 'smiley',
  ':-D'  : 'smiley',
  ':|'   : 'expressionless',
  ':-|'  : 'expressionless',
  ";P"   : 'stuck_out_tongue_winking_eye',
  ";-P"  : 'stuck_out_tongue_winking_eye',
  ":$"   : 'blush',
  ":-$"  : 'blush'
};

Discourse.Emoji.translations = translations;

function checkPrev(prev) {
  if (prev && prev.length) {
    var lastToken = prev[prev.length-1];
    if (lastToken && lastToken.charAt) {
      var lastChar = lastToken.charAt(lastToken.length-1);
      if (lastChar !== ' ' && lastChar !== "\n") return false;
    }
  }
  return true;
}

var translationsWithColon = {};
Object.keys(translations).forEach(function (t) {
  if (t[0] === ':') {
    translationsWithColon[t] = translations[t];
  } else {
    var replacement = translations[t];
    Discourse.Dialect.inlineReplace(t, function (token, match, prev) {
      if (!Discourse.SiteSettings.enable_emoji) { return token; }
      return checkPrev(prev) ? imageFor(replacement) : token;
    });
  }
});

function escapeRegExp(s) {
  return s.replace(/[-/\\^$*+?.()|[\]{}]/gi, '\\$&');
}

var translationColonRegexp = new RegExp(Object.keys(translationsWithColon).map(function (t) {
                                           return "(" + escapeRegExp(t) + ")";
                                         }).join("|"));

Discourse.Dialect.registerInline(':', function(text, match, prev) {
  if (!Discourse.SiteSettings.enable_emoji) { return; }

  var endPos = text.indexOf(':', 1),
      firstSpace = text.search(/\s/),
      contents;

  if (!checkPrev(prev)) { return; }

  // If there is no trailing colon, check our translations that begin with colons
  if (endPos === -1 || (firstSpace !== -1 && endPos > firstSpace)) {
    translationColonRegexp.lastIndex = 0;
    var m = translationColonRegexp.exec(text);
    if (m && m[0] && text.indexOf(m[0]) === 0) {

      // Check outer edge
      var lastChar = text.charAt(m[0].length);
      if (lastChar && (lastChar !== ' ' && lastChar !== "\n")) return;
      contents = imageFor(translationsWithColon[m[0]]);
      if (contents) {
        return [m[0].length, contents];
      }
    }
    return;
  }

  // Simple find and replace from our array
  var between = text.slice(1, endPos);
  contents = imageFor(between);
  if (contents) {
    return [endPos+1, contents];
  }
});

Discourse.Markdown.whiteListTag('img', 'class', 'emoji');

{'fraction_non_alphanumeric': 0.1951054362545947, 'fraction_numerical': 0.005029986457728767, 'mean_word_length': 3.102777777777778, 'pattern_counts': {'":': 6, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3867793', 'n_tokens_mistral': 3813, 'n_tokens_neox': 3774, 'n_words': 739}