Commit 0c9dbf79 authored by Stan Hu's avatar Stan Hu

Merge branch 'brodock/tanuki_emoji' into 'master'

Switch from `Gemojione` to `TanukiEmoji`

See merge request gitlab-org/gitlab!68787
parents 1e7c0d24 d229bbf9
...@@ -290,7 +290,7 @@ gem 'autoprefixer-rails', '10.2.5.1' ...@@ -290,7 +290,7 @@ gem 'autoprefixer-rails', '10.2.5.1'
gem 'terser', '1.0.2' gem 'terser', '1.0.2'
gem 'addressable', '~> 2.8' gem 'addressable', '~> 2.8'
gem 'gemojione', '~> 3.3' gem 'tanuki_emoji', '~> 0.5'
gem 'gon', '~> 6.4.0' gem 'gon', '~> 6.4.0'
gem 'request_store', '~> 1.5' gem 'request_store', '~> 1.5'
gem 'base32', '~> 0.3.0' gem 'base32', '~> 0.3.0'
...@@ -348,6 +348,8 @@ group :development do ...@@ -348,6 +348,8 @@ group :development do
# thin instead webrick # thin instead webrick
gem 'thin', '~> 1.8.0' gem 'thin', '~> 1.8.0'
gem 'sprite-factory', '~> 1.7'
end end
group :development, :test do group :development, :test do
......
...@@ -436,8 +436,6 @@ GEM ...@@ -436,8 +436,6 @@ GEM
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
fuzzyurl (0.9.0) fuzzyurl (0.9.0)
gemoji (3.0.1) gemoji (3.0.1)
gemojione (3.3.0)
json
get_process_mem (0.2.5) get_process_mem (0.2.5)
ffi (~> 1.0) ffi (~> 1.0)
gettext (3.3.6) gettext (3.3.6)
...@@ -1216,6 +1214,7 @@ GEM ...@@ -1216,6 +1214,7 @@ GEM
spring (2.1.1) spring (2.1.1)
spring-commands-rspec (1.0.4) spring-commands-rspec (1.0.4)
spring (>= 0.9.1) spring (>= 0.9.1)
sprite-factory (1.7.1)
sprockets (3.7.2) sprockets (3.7.2)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
...@@ -1246,6 +1245,7 @@ GEM ...@@ -1246,6 +1245,7 @@ GEM
sys-filesystem (1.1.9) sys-filesystem (1.1.9)
ffi ffi
sysexits (1.2.0) sysexits (1.2.0)
tanuki_emoji (0.5.0)
temple (0.8.2) temple (0.8.2)
terminal-table (1.8.0) terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1) unicode-display_width (~> 1.1, >= 1.1.1)
...@@ -1454,7 +1454,6 @@ DEPENDENCIES ...@@ -1454,7 +1454,6 @@ DEPENDENCIES
fog-rackspace (~> 0.1.1) fog-rackspace (~> 0.1.1)
fugit (~> 1.2.1) fugit (~> 1.2.1)
fuubar (~> 2.2.0) fuubar (~> 2.2.0)
gemojione (~> 3.3)
gettext (~> 3.3) gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3) gettext_i18n_rails_js (~> 1.3)
...@@ -1622,11 +1621,13 @@ DEPENDENCIES ...@@ -1622,11 +1621,13 @@ DEPENDENCIES
spamcheck (~> 0.1.0) spamcheck (~> 0.1.0)
spring (~> 2.1.0) spring (~> 2.1.0)
spring-commands-rspec (~> 1.0.4) spring-commands-rspec (~> 1.0.4)
sprite-factory (~> 1.7)
sprockets (~> 3.7.0) sprockets (~> 3.7.0)
sshkey (~> 2.0) sshkey (~> 2.0)
stackprof (~> 0.2.15) stackprof (~> 0.2.15)
state_machines-activerecord (~> 0.8.0) state_machines-activerecord (~> 0.8.0)
sys-filesystem (~> 1.1.6) sys-filesystem (~> 1.1.6)
tanuki_emoji (~> 0.5)
terser (= 1.0.2) terser (= 1.0.2)
test-prof (~> 1.0.7) test-prof (~> 1.0.7)
test_file_finder (~> 0.1.3) test_file_finder (~> 0.1.3)
......
...@@ -9,6 +9,7 @@ let emojiMap = null; ...@@ -9,6 +9,7 @@ let emojiMap = null;
let validEmojiNames = null; let validEmojiNames = null;
export const FALLBACK_EMOJI_KEY = 'grey_question'; export const FALLBACK_EMOJI_KEY = 'grey_question';
// Keep the version in sync with `lib/gitlab/emoji.rb`
export const EMOJI_VERSION = '1'; export const EMOJI_VERSION = '1';
const isLocalStorageAvailable = AccessorUtilities.canUseLocalStorage(); const isLocalStorageAvailable = AccessorUtilities.canUseLocalStorage();
......
...@@ -40,7 +40,7 @@ class AwardEmojisFinder ...@@ -40,7 +40,7 @@ class AwardEmojisFinder
def validate_name_param def validate_name_param
return unless params[:name] return unless params[:name]
raise ArgumentError, 'Invalid name param' unless params[:name].to_s.in?(Gitlab::Emoji.emojis_names) raise ArgumentError, 'Invalid name param' unless TanukiEmoji.find_by_alpha_code(params[:name].to_s)
end end
def validate_awarded_by_param def validate_awarded_by_param
......
# frozen_string_literal: true # frozen_string_literal: true
module EmojiHelper module EmojiHelper
def emoji_icon(*args) def emoji_icon(emoji_name, *options)
raw Gitlab::Emoji.gl_emoji_tag(*args) emoji = TanukiEmoji.find_by_alpha_code(emoji_name)
raw Gitlab::Emoji.gl_emoji_tag(emoji, *options)
end end
end end
...@@ -7,7 +7,8 @@ module ReminderEmailsHelper ...@@ -7,7 +7,8 @@ module ReminderEmailsHelper
s_('InviteReminderEmail|Invitation pending') s_('InviteReminderEmail|Invitation pending')
when 1 when 1
if format == :html if format == :html
s_('InviteReminderEmail|Hey there %{wave_emoji}').html_safe % { wave_emoji: Gitlab::Emoji.gl_emoji_tag('wave') } wave_emoji_tag = Gitlab::Emoji.gl_emoji_tag(TanukiEmoji.find_by_alpha_code('wave'))
s_('InviteReminderEmail|Hey there %{wave_emoji}').html_safe % { wave_emoji: wave_emoji_tag }
else else
s_('InviteReminderEmail|Hey there!') s_('InviteReminderEmail|Hey there!')
end end
......
...@@ -14,7 +14,7 @@ class AwardEmoji < ApplicationRecord ...@@ -14,7 +14,7 @@ class AwardEmoji < ApplicationRecord
validates :user, presence: true validates :user, presence: true
validates :awardable, presence: true, unless: :importing? validates :awardable, presence: true, unless: :importing?
validates :name, presence: true, inclusion: { in: Gitlab::Emoji.emojis_names } validates :name, presence: true, 'gitlab/emoji_name': true
validates :name, uniqueness: { scope: [:user, :awardable_type, :awardable_id] }, unless: -> { ghost_user? || importing? } validates :name, uniqueness: { scope: [:user, :awardable_type, :awardable_id] }, unless: -> { ghost_user? || importing? }
participant :user participant :user
......
...@@ -31,7 +31,7 @@ class CustomEmoji < ApplicationRecord ...@@ -31,7 +31,7 @@ class CustomEmoji < ApplicationRecord
private private
def valid_emoji_name def valid_emoji_name
if Gitlab::Emoji.emoji_exists?(name) if TanukiEmoji.find_by_alpha_code(name)
errors.add(:name, _('%{name} is already being used for another emoji') % { name: self.name }) errors.add(:name, _('%{name} is already being used for another emoji') % { name: self.name })
end end
end end
......
...@@ -22,7 +22,7 @@ class UserStatus < ApplicationRecord ...@@ -22,7 +22,7 @@ class UserStatus < ApplicationRecord
enum availability: { not_set: 0, busy: 1 } enum availability: { not_set: 0, busy: 1 }
validates :user, presence: true validates :user, presence: true
validates :emoji, inclusion: { in: Gitlab::Emoji.emojis_names } validates :emoji, 'gitlab/emoji_name': true
validates :message, length: { maximum: 100 }, allow_blank: true validates :message, length: { maximum: 100 }, allow_blank: true
scope :scheduled_for_cleanup, -> { where(arel_table[:clear_status_at].lteq(Time.current)) } scope :scheduled_for_cleanup, -> { where(arel_table[:clear_status_at].lteq(Time.current)) }
......
...@@ -4,24 +4,24 @@ class AwardEmojiPresenter < Gitlab::View::Presenter::Delegated ...@@ -4,24 +4,24 @@ class AwardEmojiPresenter < Gitlab::View::Presenter::Delegated
presents ::AwardEmoji, as: :award_emoji presents ::AwardEmoji, as: :award_emoji
def description def description
as_emoji['description'] as_emoji&.description
end end
def unicode def unicode
as_emoji['unicode'] as_emoji&.hex
end end
def emoji def emoji
as_emoji['moji'] as_emoji&.codepoints
end end
def unicode_version def unicode_version
Gitlab::Emoji.emoji_unicode_version(award_emoji.name) as_emoji&.unicode_version
end end
private private
def as_emoji def as_emoji
@emoji ||= Gitlab::Emoji.emojis[award_emoji.name] || {} @emoji ||= TanukiEmoji.find_by_alpha_code(award_emoji.name)
end end
end end
...@@ -14,7 +14,7 @@ module AwardEmojis ...@@ -14,7 +14,7 @@ module AwardEmojis
private private
def normalize_name(name) def normalize_name(name)
Gitlab::Emoji.normalize_emoji_name(name) TanukiEmoji.find_by_alpha_code(name)&.name || name
end end
# Provide more error state data than what BaseService allows. # Provide more error state data than what BaseService allows.
......
# frozen_string_literal: true
# Gitlab::EmojiNameValidator
#
# Validates that the provided value matches an indexed emoji alpha code
#
# @example Usage
# class AwardEmoji < ApplicationRecord
# validate :name, 'gitlab/emoji_name': true
# end
module Gitlab
class EmojiNameValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless TanukiEmoji.find_by_alpha_code(value.to_s)
record.errors.add(attribute, (options[:message] || 'is not a valid emoji name'))
end
end
end
end
...@@ -199,7 +199,7 @@ module Gitlab ...@@ -199,7 +199,7 @@ module Gitlab
config.assets.enabled = true config.assets.enabled = true
# Support legacy unicode file named img emojis, `1F939.png` # Support legacy unicode file named img emojis, `1F939.png`
config.assets.paths << Gemojione.images_path config.assets.paths << TanukiEmoji.images_path
config.assets.paths << "#{config.root}/vendor/assets/fonts" config.assets.paths << "#{config.root}/vendor/assets/fonts"
config.assets.precompile << "application_utilities.css" config.assets.precompile << "application_utilities.css"
......
require './spec/support/sidekiq_middleware' require './spec/support/sidekiq_middleware'
Gitlab::Seeder.quiet do Gitlab::Seeder.quiet do
EMOJI = Gitlab::Emoji.emojis.keys
def seed_award_emoji(klass) def seed_award_emoji(klass)
klass.order(Gitlab::Database.random).limit(klass.count / 2).each do |awardable| klass.order(Gitlab::Database.random).limit(klass.count / 2).each do |awardable|
awardable.project.authorized_users.where('project_authorizations.access_level > ?', Gitlab::Access::GUEST).sample(2).each do |user| awardable.project.authorized_users.where('project_authorizations.access_level > ?', Gitlab::Access::GUEST).sample(2).each do |user|
AwardEmojis::AddService.new(awardable, EMOJI.sample, user).execute AwardEmojis::AddService.new(awardable, TanukiEmoji.index.all.sample.name, user).execute
awardable.notes.user.sample(2).each do |note| awardable.notes.user.sample(2).each do |note|
AwardEmojis::AddService.new(note, EMOJI.sample, user).execute AwardEmojis::AddService.new(note, TanukiEmoji.index.all.sample.name, user).execute
end end
print '.' print '.'
......
{
"100": "6.0",
"1234": "6.0",
"grinning": "6.1",
"grin": "6.0",
"joy": "6.0",
"rofl": "9.0",
"rolling_on_the_floor_laughing": "9.0",
"smiley": "6.0",
"smile": "6.0",
"sweat_smile": "6.0",
"laughing": "6.0",
"satisfied": "6.0",
"wink": "6.0",
"blush": "6.0",
"yum": "6.0",
"sunglasses": "6.0",
"heart_eyes": "6.0",
"kissing_heart": "6.0",
"kissing": "6.1",
"kissing_smiling_eyes": "6.1",
"kissing_closed_eyes": "6.0",
"relaxed": "1.1",
"slight_smile": "7.0",
"slightly_smiling_face": "7.0",
"hugging": "8.0",
"hugging_face": "8.0",
"thinking": "8.0",
"thinking_face": "8.0",
"neutral_face": "6.0",
"expressionless": "6.1",
"no_mouth": "6.0",
"rolling_eyes": "8.0",
"face_with_rolling_eyes": "8.0",
"smirk": "6.0",
"persevere": "6.0",
"disappointed_relieved": "6.0",
"open_mouth": "6.1",
"zipper_mouth": "8.0",
"zipper_mouth_face": "8.0",
"hushed": "6.1",
"sleepy": "6.0",
"tired_face": "6.0",
"sleeping": "6.1",
"relieved": "6.0",
"nerd": "8.0",
"nerd_face": "8.0",
"stuck_out_tongue": "6.1",
"stuck_out_tongue_winking_eye": "6.0",
"stuck_out_tongue_closed_eyes": "6.0",
"drooling_face": "9.0",
"drool": "9.0",
"unamused": "6.0",
"sweat": "6.0",
"pensive": "6.0",
"confused": "6.1",
"upside_down": "8.0",
"upside_down_face": "8.0",
"money_mouth": "8.0",
"money_mouth_face": "8.0",
"astonished": "6.0",
"frowning2": "1.1",
"white_frowning_face": "1.1",
"slight_frown": "7.0",
"slightly_frowning_face": "7.0",
"confounded": "6.0",
"disappointed": "6.0",
"worried": "6.1",
"triumph": "6.0",
"cry": "6.0",
"sob": "6.0",
"frowning": "6.1",
"anguished": "6.1",
"fearful": "6.0",
"weary": "6.0",
"grimacing": "6.1",
"cold_sweat": "6.0",
"scream": "6.0",
"flushed": "6.0",
"dizzy_face": "6.0",
"rage": "6.0",
"angry": "6.0",
"innocent": "6.0",
"cowboy": "9.0",
"face_with_cowboy_hat": "9.0",
"clown": "9.0",
"clown_face": "9.0",
"lying_face": "9.0",
"liar": "9.0",
"mask": "6.0",
"thermometer_face": "8.0",
"face_with_thermometer": "8.0",
"head_bandage": "8.0",
"face_with_head_bandage": "8.0",
"nauseated_face": "9.0",
"sick": "9.0",
"sneezing_face": "9.0",
"sneeze": "9.0",
"smiling_imp": "6.0",
"imp": "6.0",
"japanese_ogre": "6.0",
"japanese_goblin": "6.0",
"skull": "6.0",
"skeleton": "6.0",
"skull_crossbones": "1.1",
"skull_and_crossbones": "1.1",
"ghost": "6.0",
"alien": "6.0",
"space_invader": "6.0",
"robot": "8.0",
"robot_face": "8.0",
"poop": "6.0",
"shit": "6.0",
"hankey": "6.0",
"poo": "6.0",
"smiley_cat": "6.0",
"smile_cat": "6.0",
"joy_cat": "6.0",
"heart_eyes_cat": "6.0",
"smirk_cat": "6.0",
"kissing_cat": "6.0",
"scream_cat": "6.0",
"crying_cat_face": "6.0",
"pouting_cat": "6.0",
"see_no_evil": "6.0",
"hear_no_evil": "6.0",
"speak_no_evil": "6.0",
"boy": "6.0",
"boy_tone1": "8.0",
"boy_tone2": "8.0",
"boy_tone3": "8.0",
"boy_tone4": "8.0",
"boy_tone5": "8.0",
"girl": "6.0",
"girl_tone1": "8.0",
"girl_tone2": "8.0",
"girl_tone3": "8.0",
"girl_tone4": "8.0",
"girl_tone5": "8.0",
"man": "6.0",
"man_tone1": "8.0",
"man_tone2": "8.0",
"man_tone3": "8.0",
"man_tone4": "8.0",
"man_tone5": "8.0",
"woman": "6.0",
"woman_tone1": "8.0",
"woman_tone2": "8.0",
"woman_tone3": "8.0",
"woman_tone4": "8.0",
"woman_tone5": "8.0",
"older_man": "6.0",
"older_man_tone1": "8.0",
"older_man_tone2": "8.0",
"older_man_tone3": "8.0",
"older_man_tone4": "8.0",
"older_man_tone5": "8.0",
"older_woman": "6.0",
"grandma": "6.0",
"older_woman_tone1": "8.0",
"grandma_tone1": "8.0",
"older_woman_tone2": "8.0",
"grandma_tone2": "8.0",
"older_woman_tone3": "8.0",
"grandma_tone3": "8.0",
"older_woman_tone4": "8.0",
"grandma_tone4": "8.0",
"older_woman_tone5": "8.0",
"grandma_tone5": "8.0",
"baby": "6.0",
"baby_tone1": "8.0",
"baby_tone2": "8.0",
"baby_tone3": "8.0",
"baby_tone4": "8.0",
"baby_tone5": "8.0",
"angel": "6.0",
"angel_tone1": "8.0",
"angel_tone2": "8.0",
"angel_tone3": "8.0",
"angel_tone4": "8.0",
"angel_tone5": "8.0",
"cop": "6.0",
"cop_tone1": "8.0",
"cop_tone2": "8.0",
"cop_tone3": "8.0",
"cop_tone4": "8.0",
"cop_tone5": "8.0",
"spy": "7.0",
"sleuth_or_spy": "7.0",
"spy_tone1": "8.0",
"sleuth_or_spy_tone1": "8.0",
"spy_tone2": "8.0",
"sleuth_or_spy_tone2": "8.0",
"spy_tone3": "8.0",
"sleuth_or_spy_tone3": "8.0",
"spy_tone4": "8.0",
"sleuth_or_spy_tone4": "8.0",
"spy_tone5": "8.0",
"sleuth_or_spy_tone5": "8.0",
"guardsman": "6.0",
"guardsman_tone1": "8.0",
"guardsman_tone2": "8.0",
"guardsman_tone3": "8.0",
"guardsman_tone4": "8.0",
"guardsman_tone5": "8.0",
"construction_worker": "6.0",
"construction_worker_tone1": "8.0",
"construction_worker_tone2": "8.0",
"construction_worker_tone3": "8.0",
"construction_worker_tone4": "8.0",
"construction_worker_tone5": "8.0",
"man_with_turban": "6.0",
"man_with_turban_tone1": "8.0",
"man_with_turban_tone2": "8.0",
"man_with_turban_tone3": "8.0",
"man_with_turban_tone4": "8.0",
"man_with_turban_tone5": "8.0",
"person_with_blond_hair": "6.0",
"person_with_blond_hair_tone1": "8.0",
"person_with_blond_hair_tone2": "8.0",
"person_with_blond_hair_tone3": "8.0",
"person_with_blond_hair_tone4": "8.0",
"person_with_blond_hair_tone5": "8.0",
"santa": "6.0",
"santa_tone1": "8.0",
"santa_tone2": "8.0",
"santa_tone3": "8.0",
"santa_tone4": "8.0",
"santa_tone5": "8.0",
"mrs_claus": "9.0",
"mother_christmas": "9.0",
"mrs_claus_tone1": "9.0",
"mother_christmas_tone1": "9.0",
"mrs_claus_tone2": "9.0",
"mother_christmas_tone2": "9.0",
"mrs_claus_tone3": "9.0",
"mother_christmas_tone3": "9.0",
"mrs_claus_tone4": "9.0",
"mother_christmas_tone4": "9.0",
"mrs_claus_tone5": "9.0",
"mother_christmas_tone5": "9.0",
"princess": "6.0",
"princess_tone1": "8.0",
"princess_tone2": "8.0",
"princess_tone3": "8.0",
"princess_tone4": "8.0",
"princess_tone5": "8.0",
"prince": "9.0",
"prince_tone1": "9.0",
"prince_tone2": "9.0",
"prince_tone3": "9.0",
"prince_tone4": "9.0",
"prince_tone5": "9.0",
"bride_with_veil": "6.0",
"bride_with_veil_tone1": "8.0",
"bride_with_veil_tone2": "8.0",
"bride_with_veil_tone3": "8.0",
"bride_with_veil_tone4": "8.0",
"bride_with_veil_tone5": "8.0",
"man_in_tuxedo": "9.0",
"man_in_tuxedo_tone1": "9.0",
"tuxedo_tone1": "9.0",
"man_in_tuxedo_tone2": "9.0",
"tuxedo_tone2": "9.0",
"man_in_tuxedo_tone3": "9.0",
"tuxedo_tone3": "9.0",
"man_in_tuxedo_tone4": "9.0",
"tuxedo_tone4": "9.0",
"man_in_tuxedo_tone5": "9.0",
"tuxedo_tone5": "9.0",
"pregnant_woman": "9.0",
"expecting_woman": "9.0",
"pregnant_woman_tone1": "9.0",
"expecting_woman_tone1": "9.0",
"pregnant_woman_tone2": "9.0",
"expecting_woman_tone2": "9.0",
"pregnant_woman_tone3": "9.0",
"expecting_woman_tone3": "9.0",
"pregnant_woman_tone4": "9.0",
"expecting_woman_tone4": "9.0",
"pregnant_woman_tone5": "9.0",
"expecting_woman_tone5": "9.0",
"man_with_gua_pi_mao": "6.0",
"man_with_gua_pi_mao_tone1": "8.0",
"man_with_gua_pi_mao_tone2": "8.0",
"man_with_gua_pi_mao_tone3": "8.0",
"man_with_gua_pi_mao_tone4": "8.0",
"man_with_gua_pi_mao_tone5": "8.0",
"person_frowning": "6.0",
"person_frowning_tone1": "8.0",
"person_frowning_tone2": "8.0",
"person_frowning_tone3": "8.0",
"person_frowning_tone4": "8.0",
"person_frowning_tone5": "8.0",
"person_with_pouting_face": "6.0",
"person_with_pouting_face_tone1": "8.0",
"person_with_pouting_face_tone2": "8.0",
"person_with_pouting_face_tone3": "8.0",
"person_with_pouting_face_tone4": "8.0",
"person_with_pouting_face_tone5": "8.0",
"no_good": "6.0",
"no_good_tone1": "8.0",
"no_good_tone2": "8.0",
"no_good_tone3": "8.0",
"no_good_tone4": "8.0",
"no_good_tone5": "8.0",
"ok_woman": "6.0",
"ok_woman_tone1": "8.0",
"ok_woman_tone2": "8.0",
"ok_woman_tone3": "8.0",
"ok_woman_tone4": "8.0",
"ok_woman_tone5": "8.0",
"information_desk_person": "6.0",
"information_desk_person_tone1": "8.0",
"information_desk_person_tone2": "8.0",
"information_desk_person_tone3": "8.0",
"information_desk_person_tone4": "8.0",
"information_desk_person_tone5": "8.0",
"raising_hand": "6.0",
"raising_hand_tone1": "8.0",
"raising_hand_tone2": "8.0",
"raising_hand_tone3": "8.0",
"raising_hand_tone4": "8.0",
"raising_hand_tone5": "8.0",
"bow": "6.0",
"bow_tone1": "8.0",
"bow_tone2": "8.0",
"bow_tone3": "8.0",
"bow_tone4": "8.0",
"bow_tone5": "8.0",
"face_palm": "9.0",
"facepalm": "9.0",
"face_palm_tone1": "9.0",
"facepalm_tone1": "9.0",
"face_palm_tone2": "9.0",
"facepalm_tone2": "9.0",
"face_palm_tone3": "9.0",
"facepalm_tone3": "9.0",
"face_palm_tone4": "9.0",
"facepalm_tone4": "9.0",
"face_palm_tone5": "9.0",
"facepalm_tone5": "9.0",
"shrug": "9.0",
"shrug_tone1": "9.0",
"shrug_tone2": "9.0",
"shrug_tone3": "9.0",
"shrug_tone4": "9.0",
"shrug_tone5": "9.0",
"massage": "6.0",
"massage_tone1": "8.0",
"massage_tone2": "8.0",
"massage_tone3": "8.0",
"massage_tone4": "8.0",
"massage_tone5": "8.0",
"haircut": "6.0",
"haircut_tone1": "8.0",
"haircut_tone2": "8.0",
"haircut_tone3": "8.0",
"haircut_tone4": "8.0",
"haircut_tone5": "8.0",
"walking": "6.0",
"walking_tone1": "8.0",
"walking_tone2": "8.0",
"walking_tone3": "8.0",
"walking_tone4": "8.0",
"walking_tone5": "8.0",
"runner": "6.0",
"runner_tone1": "8.0",
"runner_tone2": "8.0",
"runner_tone3": "8.0",
"runner_tone4": "8.0",
"runner_tone5": "8.0",
"dancer": "6.0",
"dancer_tone1": "8.0",
"dancer_tone2": "8.0",
"dancer_tone3": "8.0",
"dancer_tone4": "8.0",
"dancer_tone5": "8.0",
"man_dancing": "9.0",
"male_dancer": "9.0",
"man_dancing_tone1": "9.0",
"male_dancer_tone1": "9.0",
"man_dancing_tone2": "9.0",
"male_dancer_tone2": "9.0",
"man_dancing_tone3": "9.0",
"male_dancer_tone3": "9.0",
"man_dancing_tone4": "9.0",
"male_dancer_tone4": "9.0",
"man_dancing_tone5": "9.0",
"male_dancer_tone5": "9.0",
"dancers": "6.0",
"levitate": "7.0",
"man_in_business_suit_levitating": "7.0",
"speaking_head": "7.0",
"speaking_head_in_silhouette": "7.0",
"bust_in_silhouette": "6.0",
"busts_in_silhouette": "6.0",
"fencer": "9.0",
"fencing": "9.0",
"horse_racing": "6.0",
"horse_racing_tone1": "8.0",
"horse_racing_tone2": "8.0",
"horse_racing_tone3": "8.0",
"horse_racing_tone4": "8.0",
"horse_racing_tone5": "8.0",
"skier": "5.2",
"snowboarder": "6.0",
"golfer": "7.0",
"surfer": "6.0",
"surfer_tone1": "8.0",
"surfer_tone2": "8.0",
"surfer_tone3": "8.0",
"surfer_tone4": "8.0",
"surfer_tone5": "8.0",
"rowboat": "6.0",
"rowboat_tone1": "8.0",
"rowboat_tone2": "8.0",
"rowboat_tone3": "8.0",
"rowboat_tone4": "8.0",
"rowboat_tone5": "8.0",
"swimmer": "6.0",
"swimmer_tone1": "8.0",
"swimmer_tone2": "8.0",
"swimmer_tone3": "8.0",
"swimmer_tone4": "8.0",
"swimmer_tone5": "8.0",
"basketball_player": "5.2",
"person_with_ball": "5.2",
"basketball_player_tone1": "8.0",
"person_with_ball_tone1": "8.0",
"basketball_player_tone2": "8.0",
"person_with_ball_tone2": "8.0",
"basketball_player_tone3": "8.0",
"person_with_ball_tone3": "8.0",
"basketball_player_tone4": "8.0",
"person_with_ball_tone4": "8.0",
"basketball_player_tone5": "8.0",
"person_with_ball_tone5": "8.0",
"lifter": "7.0",
"weight_lifter": "7.0",
"lifter_tone1": "8.0",
"weight_lifter_tone1": "8.0",
"lifter_tone2": "8.0",
"weight_lifter_tone2": "8.0",
"lifter_tone3": "8.0",
"weight_lifter_tone3": "8.0",
"lifter_tone4": "8.0",
"weight_lifter_tone4": "8.0",
"lifter_tone5": "8.0",
"weight_lifter_tone5": "8.0",
"bicyclist": "6.0",
"bicyclist_tone1": "8.0",
"bicyclist_tone2": "8.0",
"bicyclist_tone3": "8.0",
"bicyclist_tone4": "8.0",
"bicyclist_tone5": "8.0",
"mountain_bicyclist": "6.0",
"mountain_bicyclist_tone1": "8.0",
"mountain_bicyclist_tone2": "8.0",
"mountain_bicyclist_tone3": "8.0",
"mountain_bicyclist_tone4": "8.0",
"mountain_bicyclist_tone5": "8.0",
"race_car": "7.0",
"racing_car": "7.0",
"motorcycle": "7.0",
"racing_motorcycle": "7.0",
"cartwheel": "9.0",
"person_doing_cartwheel": "9.0",
"cartwheel_tone1": "9.0",
"person_doing_cartwheel_tone1": "9.0",
"cartwheel_tone2": "9.0",
"person_doing_cartwheel_tone2": "9.0",
"cartwheel_tone3": "9.0",
"person_doing_cartwheel_tone3": "9.0",
"cartwheel_tone4": "9.0",
"person_doing_cartwheel_tone4": "9.0",
"cartwheel_tone5": "9.0",
"person_doing_cartwheel_tone5": "9.0",
"wrestlers": "9.0",
"wrestling": "9.0",
"wrestlers_tone1": "9.0",
"wrestling_tone1": "9.0",
"wrestlers_tone2": "9.0",
"wrestling_tone2": "9.0",
"wrestlers_tone3": "9.0",
"wrestling_tone3": "9.0",
"wrestlers_tone4": "9.0",
"wrestling_tone4": "9.0",
"wrestlers_tone5": "9.0",
"wrestling_tone5": "9.0",
"water_polo": "9.0",
"water_polo_tone1": "9.0",
"water_polo_tone2": "9.0",
"water_polo_tone3": "9.0",
"water_polo_tone4": "9.0",
"water_polo_tone5": "9.0",
"handball": "9.0",
"handball_tone1": "9.0",
"handball_tone2": "9.0",
"handball_tone3": "9.0",
"handball_tone4": "9.0",
"handball_tone5": "9.0",
"juggling": "9.0",
"juggler": "9.0",
"juggling_tone1": "9.0",
"juggler_tone1": "9.0",
"juggling_tone2": "9.0",
"juggler_tone2": "9.0",
"juggling_tone3": "9.0",
"juggler_tone3": "9.0",
"juggling_tone4": "9.0",
"juggler_tone4": "9.0",
"juggling_tone5": "9.0",
"juggler_tone5": "9.0",
"couple": "6.0",
"two_men_holding_hands": "6.0",
"two_women_holding_hands": "6.0",
"couplekiss": "6.0",
"kiss_mm": "6.0",
"couplekiss_mm": "6.0",
"kiss_ww": "6.0",
"couplekiss_ww": "6.0",
"couple_with_heart": "6.0",
"couple_mm": "6.0",
"couple_with_heart_mm": "6.0",
"couple_ww": "6.0",
"couple_with_heart_ww": "6.0",
"family": "6.0",
"family_mwg": "6.0",
"family_mwgb": "6.0",
"family_mwbb": "6.0",
"family_mwgg": "6.0",
"family_mmb": "6.0",
"family_mmg": "6.0",
"family_mmgb": "6.0",
"family_mmbb": "6.0",
"family_mmgg": "6.0",
"family_wwb": "6.0",
"family_wwg": "6.0",
"family_wwgb": "6.0",
"family_wwbb": "6.0",
"family_wwgg": "6.0",
"tone1": "8.0",
"tone2": "8.0",
"tone3": "8.0",
"tone4": "8.0",
"tone5": "8.0",
"muscle": "6.0",
"muscle_tone1": "8.0",
"muscle_tone2": "8.0",
"muscle_tone3": "8.0",
"muscle_tone4": "8.0",
"muscle_tone5": "8.0",
"selfie": "9.0",
"selfie_tone1": "9.0",
"selfie_tone2": "9.0",
"selfie_tone3": "9.0",
"selfie_tone4": "9.0",
"selfie_tone5": "9.0",
"point_left": "6.0",
"point_left_tone1": "8.0",
"point_left_tone2": "8.0",
"point_left_tone3": "8.0",
"point_left_tone4": "8.0",
"point_left_tone5": "8.0",
"point_right": "6.0",
"point_right_tone1": "8.0",
"point_right_tone2": "8.0",
"point_right_tone3": "8.0",
"point_right_tone4": "8.0",
"point_right_tone5": "8.0",
"point_up": "1.1",
"point_up_tone1": "8.0",
"point_up_tone2": "8.0",
"point_up_tone3": "8.0",
"point_up_tone4": "8.0",
"point_up_tone5": "8.0",
"point_up_2": "6.0",
"point_up_2_tone1": "8.0",
"point_up_2_tone2": "8.0",
"point_up_2_tone3": "8.0",
"point_up_2_tone4": "8.0",
"point_up_2_tone5": "8.0",
"middle_finger": "7.0",
"reversed_hand_with_middle_finger_extended": "7.0",
"middle_finger_tone1": "8.0",
"reversed_hand_with_middle_finger_extended_tone1": "8.0",
"middle_finger_tone2": "8.0",
"reversed_hand_with_middle_finger_extended_tone2": "8.0",
"middle_finger_tone3": "8.0",
"reversed_hand_with_middle_finger_extended_tone3": "8.0",
"middle_finger_tone4": "8.0",
"reversed_hand_with_middle_finger_extended_tone4": "8.0",
"middle_finger_tone5": "8.0",
"reversed_hand_with_middle_finger_extended_tone5": "8.0",
"point_down": "6.0",
"point_down_tone1": "8.0",
"point_down_tone2": "8.0",
"point_down_tone3": "8.0",
"point_down_tone4": "8.0",
"point_down_tone5": "8.0",
"v": "1.1",
"v_tone1": "8.0",
"v_tone2": "8.0",
"v_tone3": "8.0",
"v_tone4": "8.0",
"v_tone5": "8.0",
"fingers_crossed": "9.0",
"hand_with_index_and_middle_finger_crossed": "9.0",
"fingers_crossed_tone1": "9.0",
"hand_with_index_and_middle_fingers_crossed_tone1": "9.0",
"fingers_crossed_tone2": "9.0",
"hand_with_index_and_middle_fingers_crossed_tone2": "9.0",
"fingers_crossed_tone3": "9.0",
"hand_with_index_and_middle_fingers_crossed_tone3": "9.0",
"fingers_crossed_tone4": "9.0",
"hand_with_index_and_middle_fingers_crossed_tone4": "9.0",
"fingers_crossed_tone5": "9.0",
"hand_with_index_and_middle_fingers_crossed_tone5": "9.0",
"vulcan": "7.0",
"raised_hand_with_part_between_middle_and_ring_fingers": "7.0",
"vulcan_tone1": "8.0",
"raised_hand_with_part_between_middle_and_ring_fingers_tone1": "8.0",
"vulcan_tone2": "8.0",
"raised_hand_with_part_between_middle_and_ring_fingers_tone2": "8.0",
"vulcan_tone3": "8.0",
"raised_hand_with_part_between_middle_and_ring_fingers_tone3": "8.0",
"vulcan_tone4": "8.0",
"raised_hand_with_part_between_middle_and_ring_fingers_tone4": "8.0",
"vulcan_tone5": "8.0",
"raised_hand_with_part_between_middle_and_ring_fingers_tone5": "8.0",
"metal": "8.0",
"sign_of_the_horns": "8.0",
"metal_tone1": "8.0",
"sign_of_the_horns_tone1": "8.0",
"metal_tone2": "8.0",
"sign_of_the_horns_tone2": "8.0",
"metal_tone3": "8.0",
"sign_of_the_horns_tone3": "8.0",
"metal_tone4": "8.0",
"sign_of_the_horns_tone4": "8.0",
"metal_tone5": "8.0",
"sign_of_the_horns_tone5": "8.0",
"call_me": "9.0",
"call_me_hand": "9.0",
"call_me_tone1": "9.0",
"call_me_hand_tone1": "9.0",
"call_me_tone2": "9.0",
"call_me_hand_tone2": "9.0",
"call_me_tone3": "9.0",
"call_me_hand_tone3": "9.0",
"call_me_tone4": "9.0",
"call_me_hand_tone4": "9.0",
"call_me_tone5": "9.0",
"call_me_hand_tone5": "9.0",
"hand_splayed": "7.0",
"raised_hand_with_fingers_splayed": "7.0",
"hand_splayed_tone1": "8.0",
"raised_hand_with_fingers_splayed_tone1": "8.0",
"hand_splayed_tone2": "8.0",
"raised_hand_with_fingers_splayed_tone2": "8.0",
"hand_splayed_tone3": "8.0",
"raised_hand_with_fingers_splayed_tone3": "8.0",
"hand_splayed_tone4": "8.0",
"raised_hand_with_fingers_splayed_tone4": "8.0",
"hand_splayed_tone5": "8.0",
"raised_hand_with_fingers_splayed_tone5": "8.0",
"raised_hand": "6.0",
"raised_hand_tone1": "8.0",
"raised_hand_tone2": "8.0",
"raised_hand_tone3": "8.0",
"raised_hand_tone4": "8.0",
"raised_hand_tone5": "8.0",
"ok_hand": "6.0",
"ok_hand_tone1": "8.0",
"ok_hand_tone2": "8.0",
"ok_hand_tone3": "8.0",
"ok_hand_tone4": "8.0",
"ok_hand_tone5": "8.0",
"thumbsup": "6.0",
"+1": "6.0",
"thumbup": "6.0",
"thumbsup_tone1": "8.0",
"+1_tone1": "8.0",
"thumbup_tone1": "8.0",
"thumbsup_tone2": "8.0",
"+1_tone2": "8.0",
"thumbup_tone2": "8.0",
"thumbsup_tone3": "8.0",
"+1_tone3": "8.0",
"thumbup_tone3": "8.0",
"thumbsup_tone4": "8.0",
"+1_tone4": "8.0",
"thumbup_tone4": "8.0",
"thumbsup_tone5": "8.0",
"+1_tone5": "8.0",
"thumbup_tone5": "8.0",
"thumbsdown": "6.0",
"-1": "6.0",
"thumbdown": "6.0",
"thumbsdown_tone1": "8.0",
"-1_tone1": "8.0",
"thumbdown_tone1": "8.0",
"thumbsdown_tone2": "8.0",
"-1_tone2": "8.0",
"thumbdown_tone2": "8.0",
"thumbsdown_tone3": "8.0",
"-1_tone3": "8.0",
"thumbdown_tone3": "8.0",
"thumbsdown_tone4": "8.0",
"-1_tone4": "8.0",
"thumbdown_tone4": "8.0",
"thumbsdown_tone5": "8.0",
"-1_tone5": "8.0",
"thumbdown_tone5": "8.0",
"fist": "6.0",
"fist_tone1": "8.0",
"fist_tone2": "8.0",
"fist_tone3": "8.0",
"fist_tone4": "8.0",
"fist_tone5": "8.0",
"punch": "6.0",
"punch_tone1": "8.0",
"punch_tone2": "8.0",
"punch_tone3": "8.0",
"punch_tone4": "8.0",
"punch_tone5": "8.0",
"left_facing_fist": "9.0",
"left_fist": "9.0",
"left_facing_fist_tone1": "9.0",
"left_fist_tone1": "9.0",
"left_facing_fist_tone2": "9.0",
"left_fist_tone2": "9.0",
"left_facing_fist_tone3": "9.0",
"left_fist_tone3": "9.0",
"left_facing_fist_tone4": "9.0",
"left_fist_tone4": "9.0",
"left_facing_fist_tone5": "9.0",
"left_fist_tone5": "9.0",
"right_facing_fist": "9.0",
"right_fist": "9.0",
"right_facing_fist_tone1": "9.0",
"right_fist_tone1": "9.0",
"right_facing_fist_tone2": "9.0",
"right_fist_tone2": "9.0",
"right_facing_fist_tone3": "9.0",
"right_fist_tone3": "9.0",
"right_facing_fist_tone4": "9.0",
"right_fist_tone4": "9.0",
"right_facing_fist_tone5": "9.0",
"right_fist_tone5": "9.0",
"raised_back_of_hand": "9.0",
"back_of_hand": "9.0",
"raised_back_of_hand_tone1": "9.0",
"back_of_hand_tone1": "9.0",
"raised_back_of_hand_tone2": "9.0",
"back_of_hand_tone2": "9.0",
"raised_back_of_hand_tone3": "9.0",
"back_of_hand_tone3": "9.0",
"raised_back_of_hand_tone4": "9.0",
"back_of_hand_tone4": "9.0",
"raised_back_of_hand_tone5": "9.0",
"back_of_hand_tone5": "9.0",
"wave": "6.0",
"wave_tone1": "8.0",
"wave_tone2": "8.0",
"wave_tone3": "8.0",
"wave_tone4": "8.0",
"wave_tone5": "8.0",
"clap": "6.0",
"clap_tone1": "8.0",
"clap_tone2": "8.0",
"clap_tone3": "8.0",
"clap_tone4": "8.0",
"clap_tone5": "8.0",
"writing_hand": "1.1",
"writing_hand_tone1": "8.0",
"writing_hand_tone2": "8.0",
"writing_hand_tone3": "8.0",
"writing_hand_tone4": "8.0",
"writing_hand_tone5": "8.0",
"open_hands": "6.0",
"open_hands_tone1": "8.0",
"open_hands_tone2": "8.0",
"open_hands_tone3": "8.0",
"open_hands_tone4": "8.0",
"open_hands_tone5": "8.0",
"raised_hands": "6.0",
"raised_hands_tone1": "8.0",
"raised_hands_tone2": "8.0",
"raised_hands_tone3": "8.0",
"raised_hands_tone4": "8.0",
"raised_hands_tone5": "8.0",
"pray": "6.0",
"pray_tone1": "8.0",
"pray_tone2": "8.0",
"pray_tone3": "8.0",
"pray_tone4": "8.0",
"pray_tone5": "8.0",
"handshake": "9.0",
"shaking_hands": "9.0",
"handshake_tone1": "9.0",
"shaking_hands_tone1": "9.0",
"handshake_tone2": "9.0",
"shaking_hands_tone2": "9.0",
"handshake_tone3": "9.0",
"shaking_hands_tone3": "9.0",
"handshake_tone4": "9.0",
"shaking_hands_tone4": "9.0",
"handshake_tone5": "9.0",
"shaking_hands_tone5": "9.0",
"nail_care": "6.0",
"nail_care_tone1": "8.0",
"nail_care_tone2": "8.0",
"nail_care_tone3": "8.0",
"nail_care_tone4": "8.0",
"nail_care_tone5": "8.0",
"ear": "6.0",
"ear_tone1": "8.0",
"ear_tone2": "8.0",
"ear_tone3": "8.0",
"ear_tone4": "8.0",
"ear_tone5": "8.0",
"nose": "6.0",
"nose_tone1": "8.0",
"nose_tone2": "8.0",
"nose_tone3": "8.0",
"nose_tone4": "8.0",
"nose_tone5": "8.0",
"footprints": "6.0",
"eyes": "6.0",
"eye": "7.0",
"eye_in_speech_bubble": "7.0",
"tongue": "6.0",
"lips": "6.0",
"kiss": "6.0",
"cupid": "6.0",
"heart": "1.1",
"heartbeat": "6.0",
"broken_heart": "6.0",
"two_hearts": "6.0",
"sparkling_heart": "6.0",
"heartpulse": "6.0",
"blue_heart": "6.0",
"green_heart": "6.0",
"yellow_heart": "6.0",
"purple_heart": "6.0",
"black_heart": "9.0",
"gift_heart": "6.0",
"revolving_hearts": "6.0",
"heart_decoration": "6.0",
"heart_exclamation": "1.1",
"heavy_heart_exclamation_mark_ornament": "1.1",
"love_letter": "6.0",
"zzz": "6.0",
"anger": "6.0",
"bomb": "6.0",
"boom": "6.0",
"sweat_drops": "6.0",
"dash": "6.0",
"dizzy": "6.0",
"speech_balloon": "6.0",
"speech_left": "7.0",
"left_speech_bubble": "7.0",
"anger_right": "7.0",
"right_anger_bubble": "7.0",
"thought_balloon": "6.0",
"hole": "7.0",
"eyeglasses": "6.0",
"dark_sunglasses": "7.0",
"necktie": "6.0",
"shirt": "6.0",
"jeans": "6.0",
"dress": "6.0",
"kimono": "6.0",
"bikini": "6.0",
"womans_clothes": "6.0",
"purse": "6.0",
"handbag": "6.0",
"pouch": "6.0",
"shopping_bags": "7.0",
"school_satchel": "6.0",
"mans_shoe": "6.0",
"athletic_shoe": "6.0",
"high_heel": "6.0",
"sandal": "6.0",
"boot": "6.0",
"crown": "6.0",
"womans_hat": "6.0",
"tophat": "6.0",
"mortar_board": "6.0",
"helmet_with_cross": "5.2",
"helmet_with_white_cross": "5.2",
"prayer_beads": "8.0",
"lipstick": "6.0",
"ring": "6.0",
"gem": "6.0",
"monkey_face": "6.0",
"monkey": "6.0",
"gorilla": "9.0",
"dog": "6.0",
"dog2": "6.0",
"poodle": "6.0",
"wolf": "6.0",
"fox": "9.0",
"fox_face": "9.0",
"cat": "6.0",
"cat2": "6.0",
"lion_face": "8.0",
"lion": "8.0",
"tiger": "6.0",
"tiger2": "6.0",
"leopard": "6.0",
"horse": "6.0",
"racehorse": "6.0",
"deer": "9.0",
"unicorn": "8.0",
"unicorn_face": "8.0",
"cow": "6.0",
"ox": "6.0",
"water_buffalo": "6.0",
"cow2": "6.0",
"pig": "6.0",
"pig2": "6.0",
"boar": "6.0",
"pig_nose": "6.0",
"ram": "6.0",
"sheep": "6.0",
"goat": "6.0",
"dromedary_camel": "6.0",
"camel": "6.0",
"elephant": "6.0",
"rhino": "9.0",
"rhinoceros": "9.0",
"mouse": "6.0",
"mouse2": "6.0",
"rat": "6.0",
"hamster": "6.0",
"rabbit": "6.0",
"rabbit2": "6.0",
"chipmunk": "7.0",
"bat": "9.0",
"bear": "6.0",
"koala": "6.0",
"panda_face": "6.0",
"feet": "6.0",
"paw_prints": "6.0",
"turkey": "8.0",
"chicken": "6.0",
"rooster": "6.0",
"hatching_chick": "6.0",
"baby_chick": "6.0",
"hatched_chick": "6.0",
"bird": "6.0",
"penguin": "6.0",
"dove": "7.0",
"dove_of_peace": "7.0",
"eagle": "9.0",
"duck": "9.0",
"owl": "9.0",
"frog": "6.0",
"crocodile": "6.0",
"turtle": "6.0",
"lizard": "9.0",
"snake": "6.0",
"dragon_face": "6.0",
"dragon": "6.0",
"whale": "6.0",
"whale2": "6.0",
"dolphin": "6.0",
"fish": "6.0",
"tropical_fish": "6.0",
"blowfish": "6.0",
"shark": "9.0",
"octopus": "6.0",
"shell": "6.0",
"crab": "8.0",
"shrimp": "9.0",
"squid": "9.0",
"butterfly": "9.0",
"snail": "6.0",
"bug": "6.0",
"ant": "6.0",
"bee": "6.0",
"beetle": "6.0",
"spider": "7.0",
"spider_web": "7.0",
"scorpion": "8.0",
"bouquet": "6.0",
"cherry_blossom": "6.0",
"white_flower": "6.0",
"rosette": "7.0",
"rose": "6.0",
"wilted_rose": "9.0",
"wilted_flower": "9.0",
"hibiscus": "6.0",
"sunflower": "6.0",
"blossom": "6.0",
"tulip": "6.0",
"seedling": "6.0",
"evergreen_tree": "6.0",
"deciduous_tree": "6.0",
"palm_tree": "6.0",
"cactus": "6.0",
"ear_of_rice": "6.0",
"herb": "6.0",
"shamrock": "4.1",
"four_leaf_clover": "6.0",
"maple_leaf": "6.0",
"fallen_leaf": "6.0",
"leaves": "6.0",
"grapes": "6.0",
"melon": "6.0",
"watermelon": "6.0",
"tangerine": "6.0",
"lemon": "6.0",
"banana": "6.0",
"pineapple": "6.0",
"apple": "6.0",
"green_apple": "6.0",
"pear": "6.0",
"peach": "6.0",
"cherries": "6.0",
"strawberry": "6.0",
"kiwi": "9.0",
"kiwifruit": "9.0",
"tomato": "6.0",
"avocado": "9.0",
"eggplant": "6.0",
"potato": "9.0",
"carrot": "9.0",
"corn": "6.0",
"hot_pepper": "7.0",
"cucumber": "9.0",
"mushroom": "6.0",
"peanuts": "9.0",
"shelled_peanut": "9.0",
"chestnut": "6.0",
"bread": "6.0",
"croissant": "9.0",
"french_bread": "9.0",
"baguette_bread": "9.0",
"pancakes": "9.0",
"cheese": "8.0",
"cheese_wedge": "8.0",
"meat_on_bone": "6.0",
"poultry_leg": "6.0",
"bacon": "9.0",
"hamburger": "6.0",
"fries": "6.0",
"pizza": "6.0",
"hotdog": "8.0",
"hot_dog": "8.0",
"taco": "8.0",
"burrito": "8.0",
"stuffed_flatbread": "9.0",
"stuffed_pita": "9.0",
"egg": "9.0",
"cooking": "6.0",
"shallow_pan_of_food": "9.0",
"paella": "9.0",
"stew": "6.0",
"salad": "9.0",
"green_salad": "9.0",
"popcorn": "8.0",
"bento": "6.0",
"rice_cracker": "6.0",
"rice_ball": "6.0",
"rice": "6.0",
"curry": "6.0",
"ramen": "6.0",
"spaghetti": "6.0",
"sweet_potato": "6.0",
"oden": "6.0",
"sushi": "6.0",
"fried_shrimp": "6.0",
"fish_cake": "6.0",
"dango": "6.0",
"icecream": "6.0",
"shaved_ice": "6.0",
"ice_cream": "6.0",
"doughnut": "6.0",
"cookie": "6.0",
"birthday": "6.0",
"cake": "6.0",
"chocolate_bar": "6.0",
"candy": "6.0",
"lollipop": "6.0",
"custard": "6.0",
"pudding": "6.0",
"flan": "6.0",
"honey_pot": "6.0",
"baby_bottle": "6.0",
"milk": "9.0",
"glass_of_milk": "9.0",
"coffee": "4.0",
"tea": "6.0",
"sake": "6.0",
"champagne": "8.0",
"bottle_with_popping_cork": "8.0",
"wine_glass": "6.0",
"cocktail": "6.0",
"tropical_drink": "6.0",
"beer": "6.0",
"beers": "6.0",
"champagne_glass": "9.0",
"clinking_glass": "9.0",
"tumbler_glass": "9.0",
"whisky": "9.0",
"fork_knife_plate": "7.0",
"fork_and_knife_with_plate": "7.0",
"fork_and_knife": "6.0",
"spoon": "9.0",
"knife": "6.0",
"amphora": "8.0",
"earth_africa": "6.0",
"earth_americas": "6.0",
"earth_asia": "6.0",
"globe_with_meridians": "6.0",
"map": "7.0",
"world_map": "7.0",
"japan": "6.0",
"mountain_snow": "7.0",
"snow_capped_mountain": "7.0",
"mountain": "5.2",
"volcano": "6.0",
"mount_fuji": "6.0",
"camping": "7.0",
"beach": "7.0",
"beach_with_umbrella": "7.0",
"desert": "7.0",
"island": "7.0",
"desert_island": "7.0",
"park": "7.0",
"national_park": "7.0",
"stadium": "7.0",
"classical_building": "7.0",
"construction_site": "7.0",
"building_construction": "7.0",
"homes": "7.0",
"house_buildings": "7.0",
"cityscape": "7.0",
"house_abandoned": "7.0",
"derelict_house_building": "7.0",
"house": "6.0",
"house_with_garden": "6.0",
"office": "6.0",
"post_office": "6.0",
"european_post_office": "6.0",
"hospital": "6.0",
"bank": "6.0",
"hotel": "6.0",
"love_hotel": "6.0",
"convenience_store": "6.0",
"school": "6.0",
"department_store": "6.0",
"factory": "6.0",
"japanese_castle": "6.0",
"european_castle": "6.0",
"wedding": "6.0",
"tokyo_tower": "6.0",
"statue_of_liberty": "6.0",
"church": "5.2",
"mosque": "8.0",
"synagogue": "8.0",
"shinto_shrine": "5.2",
"kaaba": "8.0",
"fountain": "5.2",
"tent": "5.2",
"foggy": "6.0",
"night_with_stars": "6.0",
"sunrise_over_mountains": "6.0",
"sunrise": "6.0",
"city_dusk": "6.0",
"city_sunset": "6.0",
"city_sunrise": "6.0",
"bridge_at_night": "6.0",
"hotsprings": "1.1",
"milky_way": "6.0",
"carousel_horse": "6.0",
"ferris_wheel": "6.0",
"roller_coaster": "6.0",
"barber": "6.0",
"circus_tent": "6.0",
"performing_arts": "6.0",
"frame_photo": "7.0",
"frame_with_picture": "7.0",
"art": "6.0",
"slot_machine": "6.0",
"steam_locomotive": "6.0",
"railway_car": "6.0",
"bullettrain_side": "6.0",
"bullettrain_front": "6.0",
"train2": "6.0",
"metro": "6.0",
"light_rail": "6.0",
"station": "6.0",
"tram": "6.0",
"monorail": "6.0",
"mountain_railway": "6.0",
"train": "6.0",
"bus": "6.0",
"oncoming_bus": "6.0",
"trolleybus": "6.0",
"minibus": "6.0",
"ambulance": "6.0",
"fire_engine": "6.0",
"police_car": "6.0",
"oncoming_police_car": "6.0",
"taxi": "6.0",
"oncoming_taxi": "6.0",
"red_car": "6.0",
"oncoming_automobile": "6.0",
"blue_car": "6.0",
"truck": "6.0",
"articulated_lorry": "6.0",
"tractor": "6.0",
"bike": "6.0",
"scooter": "9.0",
"motor_scooter": "9.0",
"motorbike": "9.0",
"busstop": "6.0",
"motorway": "7.0",
"railway_track": "7.0",
"railroad_track": "7.0",
"fuelpump": "5.2",
"rotating_light": "6.0",
"traffic_light": "6.0",
"vertical_traffic_light": "6.0",
"construction": "6.0",
"octagonal_sign": "9.0",
"stop_sign": "9.0",
"anchor": "4.1",
"sailboat": "5.2",
"canoe": "9.0",
"kayak": "9.0",
"speedboat": "6.0",
"cruise_ship": "7.0",
"passenger_ship": "7.0",
"ferry": "5.2",
"motorboat": "7.0",
"ship": "6.0",
"airplane": "1.1",
"airplane_small": "7.0",
"small_airplane": "7.0",
"airplane_departure": "7.0",
"airplane_arriving": "7.0",
"seat": "6.0",
"helicopter": "6.0",
"suspension_railway": "6.0",
"mountain_cableway": "6.0",
"aerial_tramway": "6.0",
"rocket": "6.0",
"satellite_orbital": "7.0",
"bellhop": "7.0",
"bellhop_bell": "7.0",
"door": "6.0",
"sleeping_accommodation": "7.0",
"bed": "7.0",
"couch": "7.0",
"couch_and_lamp": "7.0",
"toilet": "6.0",
"shower": "6.0",
"bath": "6.0",
"bath_tone1": "8.0",
"bath_tone2": "8.0",
"bath_tone3": "8.0",
"bath_tone4": "8.0",
"bath_tone5": "8.0",
"bathtub": "6.0",
"hourglass": "1.1",
"hourglass_flowing_sand": "6.0",
"watch": "1.1",
"alarm_clock": "6.0",
"stopwatch": "6.0",
"timer": "6.0",
"timer_clock": "6.0",
"clock": "7.0",
"mantlepiece_clock": "7.0",
"clock12": "6.0",
"clock1230": "6.0",
"clock1": "6.0",
"clock130": "6.0",
"clock2": "6.0",
"clock230": "6.0",
"clock3": "6.0",
"clock330": "6.0",
"clock4": "6.0",
"clock430": "6.0",
"clock5": "6.0",
"clock530": "6.0",
"clock6": "6.0",
"clock630": "6.0",
"clock7": "6.0",
"clock730": "6.0",
"clock8": "6.0",
"clock830": "6.0",
"clock9": "6.0",
"clock930": "6.0",
"clock10": "6.0",
"clock1030": "6.0",
"clock11": "6.0",
"clock1130": "6.0",
"new_moon": "6.0",
"waxing_crescent_moon": "6.0",
"first_quarter_moon": "6.0",
"waxing_gibbous_moon": "6.0",
"full_moon": "6.0",
"waning_gibbous_moon": "6.0",
"last_quarter_moon": "6.0",
"waning_crescent_moon": "6.0",
"crescent_moon": "6.0",
"new_moon_with_face": "6.0",
"first_quarter_moon_with_face": "6.0",
"last_quarter_moon_with_face": "6.0",
"thermometer": "7.0",
"sunny": "1.1",
"full_moon_with_face": "6.0",
"sun_with_face": "6.0",
"star": "5.1",
"star2": "6.0",
"stars": "6.0",
"cloud": "1.1",
"partly_sunny": "5.2",
"thunder_cloud_rain": "5.2",
"thunder_cloud_and_rain": "5.2",
"white_sun_small_cloud": "7.0",
"white_sun_with_small_cloud": "7.0",
"white_sun_cloud": "7.0",
"white_sun_behind_cloud": "7.0",
"white_sun_rain_cloud": "7.0",
"white_sun_behind_cloud_with_rain": "7.0",
"cloud_rain": "7.0",
"cloud_with_rain": "7.0",
"cloud_snow": "7.0",
"cloud_with_snow": "7.0",
"cloud_lightning": "7.0",
"cloud_with_lightning": "7.0",
"cloud_tornado": "7.0",
"cloud_with_tornado": "7.0",
"fog": "7.0",
"wind_blowing_face": "7.0",
"cyclone": "6.0",
"rainbow": "6.0",
"closed_umbrella": "6.0",
"umbrella2": "1.1",
"umbrella": "4.0",
"beach_umbrella": "5.2",
"umbrella_on_ground": "5.2",
"zap": "4.0",
"snowflake": "1.1",
"snowman2": "1.1",
"snowman": "5.2",
"comet": "1.1",
"fire": "6.0",
"flame": "6.0",
"droplet": "6.0",
"ocean": "6.0",
"jack_o_lantern": "6.0",
"christmas_tree": "6.0",
"fireworks": "6.0",
"sparkler": "6.0",
"sparkles": "6.0",
"balloon": "6.0",
"tada": "6.0",
"confetti_ball": "6.0",
"tanabata_tree": "6.0",
"bamboo": "6.0",
"dolls": "6.0",
"flags": "6.0",
"wind_chime": "6.0",
"rice_scene": "6.0",
"ribbon": "6.0",
"gift": "6.0",
"reminder_ribbon": "7.0",
"tickets": "7.0",
"admission_tickets": "7.0",
"ticket": "6.0",
"military_medal": "7.0",
"trophy": "6.0",
"medal": "7.0",
"sports_medal": "7.0",
"first_place": "9.0",
"first_place_medal": "9.0",
"second_place": "9.0",
"second_place_medal": "9.0",
"third_place": "9.0",
"third_place_medal": "9.0",
"soccer": "5.2",
"baseball": "5.2",
"basketball": "6.0",
"volleyball": "8.0",
"football": "6.0",
"rugby_football": "6.0",
"tennis": "6.0",
"8ball": "6.0",
"bowling": "6.0",
"cricket": "8.0",
"cricket_bat_ball": "8.0",
"field_hockey": "8.0",
"hockey": "8.0",
"ping_pong": "8.0",
"table_tennis": "8.0",
"badminton": "8.0",
"boxing_glove": "9.0",
"boxing_gloves": "9.0",
"martial_arts_uniform": "9.0",
"karate_uniform": "9.0",
"goal": "9.0",
"goal_net": "9.0",
"dart": "6.0",
"golf": "5.2",
"ice_skate": "5.2",
"fishing_pole_and_fish": "6.0",
"running_shirt_with_sash": "6.0",
"ski": "6.0",
"video_game": "6.0",
"joystick": "7.0",
"game_die": "6.0",
"spades": "1.1",
"hearts": "1.1",
"diamonds": "1.1",
"clubs": "1.1",
"black_joker": "6.0",
"mahjong": "5.1",
"flower_playing_cards": "6.0",
"mute": "6.0",
"speaker": "6.0",
"sound": "6.0",
"loud_sound": "6.0",
"loudspeaker": "6.0",
"mega": "6.0",
"postal_horn": "6.0",
"bell": "6.0",
"no_bell": "6.0",
"musical_score": "6.0",
"musical_note": "6.0",
"notes": "6.0",
"microphone2": "7.0",
"studio_microphone": "7.0",
"level_slider": "7.0",
"control_knobs": "7.0",
"microphone": "6.0",
"headphones": "6.0",
"radio": "6.0",
"saxophone": "6.0",
"guitar": "6.0",
"musical_keyboard": "6.0",
"trumpet": "6.0",
"violin": "6.0",
"drum": "9.0",
"drum_with_drumsticks": "9.0",
"iphone": "6.0",
"calling": "6.0",
"telephone": "1.1",
"telephone_receiver": "6.0",
"pager": "6.0",
"fax": "6.0",
"battery": "6.0",
"electric_plug": "6.0",
"computer": "6.0",
"desktop": "7.0",
"desktop_computer": "7.0",
"printer": "7.0",
"keyboard": "1.1",
"mouse_three_button": "7.0",
"three_button_mouse": "7.0",
"trackball": "7.0",
"minidisc": "6.0",
"floppy_disk": "6.0",
"cd": "6.0",
"dvd": "6.0",
"movie_camera": "6.0",
"film_frames": "7.0",
"projector": "7.0",
"film_projector": "7.0",
"clapper": "6.0",
"tv": "6.0",
"camera": "6.0",
"camera_with_flash": "7.0",
"video_camera": "6.0",
"vhs": "6.0",
"mag": "6.0",
"mag_right": "6.0",
"microscope": "6.0",
"telescope": "6.0",
"satellite": "6.0",
"candle": "7.0",
"bulb": "6.0",
"flashlight": "6.0",
"izakaya_lantern": "6.0",
"notebook_with_decorative_cover": "6.0",
"closed_book": "6.0",
"book": "6.0",
"green_book": "6.0",
"blue_book": "6.0",
"orange_book": "6.0",
"books": "6.0",
"notebook": "6.0",
"ledger": "6.0",
"page_with_curl": "6.0",
"scroll": "6.0",
"page_facing_up": "6.0",
"newspaper": "6.0",
"newspaper2": "7.0",
"rolled_up_newspaper": "7.0",
"bookmark_tabs": "6.0",
"bookmark": "6.0",
"label": "7.0",
"moneybag": "6.0",
"yen": "6.0",
"dollar": "6.0",
"euro": "6.0",
"pound": "6.0",
"money_with_wings": "6.0",
"credit_card": "6.0",
"chart": "6.0",
"currency_exchange": "6.0",
"heavy_dollar_sign": "6.0",
"envelope": "1.1",
"e-mail": "6.0",
"email": "6.0",
"incoming_envelope": "6.0",
"envelope_with_arrow": "6.0",
"outbox_tray": "6.0",
"inbox_tray": "6.0",
"package": "6.0",
"mailbox": "6.0",
"mailbox_closed": "6.0",
"mailbox_with_mail": "6.0",
"mailbox_with_no_mail": "6.0",
"postbox": "6.0",
"ballot_box": "7.0",
"ballot_box_with_ballot": "7.0",
"pencil2": "1.1",
"black_nib": "1.1",
"pen_fountain": "7.0",
"lower_left_fountain_pen": "7.0",
"pen_ballpoint": "7.0",
"lower_left_ballpoint_pen": "7.0",
"paintbrush": "7.0",
"lower_left_paintbrush": "7.0",
"crayon": "7.0",
"lower_left_crayon": "7.0",
"pencil": "6.0",
"briefcase": "6.0",
"file_folder": "6.0",
"open_file_folder": "6.0",
"dividers": "7.0",
"card_index_dividers": "7.0",
"date": "6.0",
"calendar": "6.0",
"notepad_spiral": "7.0",
"spiral_note_pad": "7.0",
"calendar_spiral": "7.0",
"spiral_calendar_pad": "7.0",
"card_index": "6.0",
"chart_with_upwards_trend": "6.0",
"chart_with_downwards_trend": "6.0",
"bar_chart": "6.0",
"clipboard": "6.0",
"pushpin": "6.0",
"round_pushpin": "6.0",
"paperclip": "6.0",
"paperclips": "7.0",
"linked_paperclips": "7.0",
"straight_ruler": "6.0",
"triangular_ruler": "6.0",
"scissors": "1.1",
"card_box": "7.0",
"card_file_box": "7.0",
"file_cabinet": "7.0",
"wastebasket": "7.0",
"lock": "6.0",
"unlock": "6.0",
"lock_with_ink_pen": "6.0",
"closed_lock_with_key": "6.0",
"key": "6.0",
"key2": "7.0",
"old_key": "7.0",
"hammer": "6.0",
"pick": "5.2",
"hammer_pick": "4.1",
"hammer_and_pick": "4.1",
"tools": "7.0",
"hammer_and_wrench": "7.0",
"dagger": "7.0",
"dagger_knife": "7.0",
"crossed_swords": "4.1",
"gun": "6.0",
"bow_and_arrow": "8.0",
"archery": "8.0",
"shield": "7.0",
"wrench": "6.0",
"nut_and_bolt": "6.0",
"gear": "4.1",
"compression": "7.0",
"alembic": "4.1",
"scales": "4.1",
"link": "6.0",
"chains": "5.2",
"syringe": "6.0",
"pill": "6.0",
"smoking": "6.0",
"coffin": "4.1",
"urn": "4.1",
"funeral_urn": "4.1",
"moyai": "6.0",
"oil": "7.0",
"oil_drum": "7.0",
"crystal_ball": "6.0",
"shopping_cart": "9.0",
"shopping_trolley": "9.0",
"atm": "6.0",
"put_litter_in_its_place": "6.0",
"potable_water": "6.0",
"wheelchair": "4.1",
"mens": "6.0",
"womens": "6.0",
"restroom": "6.0",
"baby_symbol": "6.0",
"wc": "6.0",
"passport_control": "6.0",
"customs": "6.0",
"baggage_claim": "6.0",
"left_luggage": "6.0",
"warning": "4.0",
"children_crossing": "6.0",
"no_entry": "5.2",
"no_entry_sign": "6.0",
"no_bicycles": "6.0",
"no_smoking": "6.0",
"do_not_litter": "6.0",
"non-potable_water": "6.0",
"no_pedestrians": "6.0",
"no_mobile_phones": "6.0",
"underage": "6.0",
"radioactive": "1.1",
"radioactive_sign": "1.1",
"biohazard": "1.1",
"biohazard_sign": "1.1",
"arrow_up": "4.0",
"arrow_upper_right": "1.1",
"arrow_right": "1.1",
"arrow_lower_right": "1.1",
"arrow_down": "4.0",
"arrow_lower_left": "1.1",
"arrow_left": "4.0",
"arrow_upper_left": "1.1",
"arrow_up_down": "1.1",
"left_right_arrow": "1.1",
"leftwards_arrow_with_hook": "1.1",
"arrow_right_hook": "1.1",
"arrow_heading_up": "3.2",
"arrow_heading_down": "3.2",
"arrows_clockwise": "6.0",
"arrows_counterclockwise": "6.0",
"back": "6.0",
"end": "6.0",
"on": "6.0",
"soon": "6.0",
"top": "6.0",
"place_of_worship": "8.0",
"worship_symbol": "8.0",
"atom": "4.1",
"atom_symbol": "4.1",
"om_symbol": "7.0",
"star_of_david": "1.1",
"wheel_of_dharma": "1.1",
"yin_yang": "1.1",
"cross": "1.1",
"latin_cross": "1.1",
"orthodox_cross": "1.1",
"star_and_crescent": "1.1",
"peace": "1.1",
"peace_symbol": "1.1",
"menorah": "8.0",
"six_pointed_star": "6.0",
"aries": "1.1",
"taurus": "1.1",
"gemini": "1.1",
"cancer": "1.1",
"leo": "1.1",
"virgo": "1.1",
"libra": "1.1",
"scorpius": "1.1",
"sagittarius": "1.1",
"capricorn": "1.1",
"aquarius": "1.1",
"pisces": "1.1",
"ophiuchus": "6.0",
"twisted_rightwards_arrows": "6.0",
"repeat": "6.0",
"repeat_one": "6.0",
"arrow_forward": "1.1",
"fast_forward": "6.0",
"track_next": "6.0",
"next_track": "6.0",
"play_pause": "6.0",
"arrow_backward": "1.1",
"rewind": "6.0",
"track_previous": "6.0",
"previous_track": "6.0",
"arrow_up_small": "6.0",
"arrow_double_up": "6.0",
"arrow_down_small": "6.0",
"arrow_double_down": "6.0",
"pause_button": "7.0",
"double_vertical_bar": "7.0",
"stop_button": "7.0",
"record_button": "7.0",
"eject": "4.0",
"eject_symbol": "4.0",
"cinema": "6.0",
"low_brightness": "6.0",
"high_brightness": "6.0",
"signal_strength": "6.0",
"vibration_mode": "6.0",
"mobile_phone_off": "6.0",
"recycle": "3.2",
"name_badge": "6.0",
"fleur-de-lis": "4.1",
"beginner": "6.0",
"trident": "6.0",
"o": "5.2",
"white_check_mark": "6.0",
"ballot_box_with_check": "1.1",
"heavy_check_mark": "1.1",
"heavy_multiplication_x": "1.1",
"x": "6.0",
"negative_squared_cross_mark": "6.0",
"heavy_plus_sign": "6.0",
"heavy_minus_sign": "6.0",
"heavy_division_sign": "6.0",
"curly_loop": "6.0",
"loop": "6.0",
"part_alternation_mark": "3.2",
"eight_spoked_asterisk": "1.1",
"eight_pointed_black_star": "1.1",
"sparkle": "1.1",
"bangbang": "1.1",
"interrobang": "3.0",
"question": "6.0",
"grey_question": "6.0",
"grey_exclamation": "6.0",
"exclamation": "5.2",
"wavy_dash": "1.1",
"copyright": "1.1",
"registered": "1.1",
"tm": "1.1",
"hash": "3.0",
"asterisk": "3.0",
"keycap_asterisk": "3.0",
"zero": "3.0",
"one": "3.0",
"two": "3.0",
"three": "3.0",
"four": "3.0",
"five": "3.0",
"six": "3.0",
"seven": "3.0",
"eight": "3.0",
"nine": "3.0",
"keycap_ten": "6.0",
"capital_abcd": "6.0",
"abcd": "6.0",
"symbols": "6.0",
"abc": "6.0",
"a": "6.0",
"ab": "6.0",
"b": "6.0",
"cl": "6.0",
"cool": "6.0",
"free": "6.0",
"information_source": "3.0",
"id": "6.0",
"m": "1.1",
"new": "6.0",
"ng": "6.0",
"o2": "6.0",
"ok": "6.0",
"parking": "5.2",
"sos": "6.0",
"up": "6.0",
"vs": "6.0",
"koko": "6.0",
"sa": "6.0",
"u6708": "6.0",
"u6709": "6.0",
"u6307": "5.2",
"ideograph_advantage": "6.0",
"u5272": "6.0",
"u7121": "5.2",
"u7981": "6.0",
"accept": "6.0",
"u7533": "6.0",
"u5408": "6.0",
"u7a7a": "6.0",
"congratulations": "1.1",
"secret": "1.1",
"u55b6": "6.0",
"u6e80": "6.0",
"black_small_square": "1.1",
"white_small_square": "1.1",
"white_medium_square": "3.2",
"black_medium_square": "3.2",
"white_medium_small_square": "3.2",
"black_medium_small_square": "3.2",
"black_large_square": "5.1",
"white_large_square": "5.1",
"large_orange_diamond": "6.0",
"large_blue_diamond": "6.0",
"small_orange_diamond": "6.0",
"small_blue_diamond": "6.0",
"small_red_triangle": "6.0",
"small_red_triangle_down": "6.0",
"diamond_shape_with_a_dot_inside": "6.0",
"radio_button": "6.0",
"black_square_button": "6.0",
"white_square_button": "6.0",
"white_circle": "4.1",
"black_circle": "4.1",
"red_circle": "6.0",
"blue_circle": "6.0",
"checkered_flag": "6.0",
"triangular_flag_on_post": "6.0",
"crossed_flags": "6.0",
"flag_black": "6.0",
"waving_black_flag": "6.0",
"flag_white": "6.0",
"waving_white_flag": "6.0",
"rainbow_flag": "6.0",
"gay_pride_flag": "6.0",
"flag_ac": "6.0",
"ac": "6.0",
"flag_ad": "6.0",
"ad": "6.0",
"flag_ae": "6.0",
"ae": "6.0",
"flag_af": "6.0",
"af": "6.0",
"flag_ag": "6.0",
"ag": "6.0",
"flag_ai": "6.0",
"ai": "6.0",
"flag_al": "6.0",
"al": "6.0",
"flag_am": "6.0",
"am": "6.0",
"flag_ao": "6.0",
"ao": "6.0",
"flag_aq": "6.0",
"aq": "6.0",
"flag_ar": "6.0",
"ar": "6.0",
"flag_as": "6.0",
"as": "6.0",
"flag_at": "6.0",
"at": "6.0",
"flag_au": "6.0",
"au": "6.0",
"flag_aw": "6.0",
"aw": "6.0",
"flag_ax": "6.0",
"ax": "6.0",
"flag_az": "6.0",
"az": "6.0",
"flag_ba": "6.0",
"ba": "6.0",
"flag_bb": "6.0",
"bb": "6.0",
"flag_bd": "6.0",
"bd": "6.0",
"flag_be": "6.0",
"be": "6.0",
"flag_bf": "6.0",
"bf": "6.0",
"flag_bg": "6.0",
"bg": "6.0",
"flag_bh": "6.0",
"bh": "6.0",
"flag_bi": "6.0",
"bi": "6.0",
"flag_bj": "6.0",
"bj": "6.0",
"flag_bl": "6.0",
"bl": "6.0",
"flag_bm": "6.0",
"bm": "6.0",
"flag_bn": "6.0",
"bn": "6.0",
"flag_bo": "6.0",
"bo": "6.0",
"flag_bq": "6.0",
"bq": "6.0",
"flag_br": "6.0",
"br": "6.0",
"flag_bs": "6.0",
"bs": "6.0",
"flag_bt": "6.0",
"bt": "6.0",
"flag_bv": "6.0",
"bv": "6.0",
"flag_bw": "6.0",
"bw": "6.0",
"flag_by": "6.0",
"by": "6.0",
"flag_bz": "6.0",
"bz": "6.0",
"flag_ca": "6.0",
"ca": "6.0",
"flag_cc": "6.0",
"cc": "6.0",
"flag_cd": "6.0",
"congo": "6.0",
"flag_cf": "6.0",
"cf": "6.0",
"flag_cg": "6.0",
"cg": "6.0",
"flag_ch": "6.0",
"ch": "6.0",
"flag_ci": "6.0",
"ci": "6.0",
"flag_ck": "6.0",
"ck": "6.0",
"flag_cl": "6.0",
"chile": "6.0",
"flag_cm": "6.0",
"cm": "6.0",
"flag_cn": "6.0",
"cn": "6.0",
"flag_co": "6.0",
"co": "6.0",
"flag_cp": "6.0",
"cp": "6.0",
"flag_cr": "6.0",
"cr": "6.0",
"flag_cu": "6.0",
"cu": "6.0",
"flag_cv": "6.0",
"cv": "6.0",
"flag_cw": "6.0",
"cw": "6.0",
"flag_cx": "6.0",
"cx": "6.0",
"flag_cy": "6.0",
"cy": "6.0",
"flag_cz": "6.0",
"cz": "6.0",
"flag_de": "6.0",
"de": "6.0",
"flag_dg": "6.0",
"dg": "6.0",
"flag_dj": "6.0",
"dj": "6.0",
"flag_dk": "6.0",
"dk": "6.0",
"flag_dm": "6.0",
"dm": "6.0",
"flag_do": "6.0",
"do": "6.0",
"flag_dz": "6.0",
"dz": "6.0",
"flag_ea": "6.0",
"ea": "6.0",
"flag_ec": "6.0",
"ec": "6.0",
"flag_ee": "6.0",
"ee": "6.0",
"flag_eg": "6.0",
"eg": "6.0",
"flag_eh": "6.0",
"eh": "6.0",
"flag_er": "6.0",
"er": "6.0",
"flag_es": "6.0",
"es": "6.0",
"flag_et": "6.0",
"et": "6.0",
"flag_eu": "6.0",
"eu": "6.0",
"flag_fi": "6.0",
"fi": "6.0",
"flag_fj": "6.0",
"fj": "6.0",
"flag_fk": "6.0",
"fk": "6.0",
"flag_fm": "6.0",
"fm": "6.0",
"flag_fo": "6.0",
"fo": "6.0",
"flag_fr": "6.0",
"fr": "6.0",
"flag_ga": "6.0",
"ga": "6.0",
"flag_gb": "6.0",
"gb": "6.0",
"flag_gd": "6.0",
"gd": "6.0",
"flag_ge": "6.0",
"ge": "6.0",
"flag_gf": "6.0",
"gf": "6.0",
"flag_gg": "6.0",
"gg": "6.0",
"flag_gh": "6.0",
"gh": "6.0",
"flag_gi": "6.0",
"gi": "6.0",
"flag_gl": "6.0",
"gl": "6.0",
"flag_gm": "6.0",
"gm": "6.0",
"flag_gn": "6.0",
"gn": "6.0",
"flag_gp": "6.0",
"gp": "6.0",
"flag_gq": "6.0",
"gq": "6.0",
"flag_gr": "6.0",
"gr": "6.0",
"flag_gs": "6.0",
"gs": "6.0",
"flag_gt": "6.0",
"gt": "6.0",
"flag_gu": "6.0",
"gu": "6.0",
"flag_gw": "6.0",
"gw": "6.0",
"flag_gy": "6.0",
"gy": "6.0",
"flag_hk": "6.0",
"hk": "6.0",
"flag_hm": "6.0",
"hm": "6.0",
"flag_hn": "6.0",
"hn": "6.0",
"flag_hr": "6.0",
"hr": "6.0",
"flag_ht": "6.0",
"ht": "6.0",
"flag_hu": "6.0",
"hu": "6.0",
"flag_ic": "6.0",
"ic": "6.0",
"flag_id": "6.0",
"indonesia": "6.0",
"flag_ie": "6.0",
"ie": "6.0",
"flag_il": "6.0",
"il": "6.0",
"flag_im": "6.0",
"im": "6.0",
"flag_in": "6.0",
"in": "6.0",
"flag_io": "6.0",
"io": "6.0",
"flag_iq": "6.0",
"iq": "6.0",
"flag_ir": "6.0",
"ir": "6.0",
"flag_is": "6.0",
"is": "6.0",
"flag_it": "6.0",
"it": "6.0",
"flag_je": "6.0",
"je": "6.0",
"flag_jm": "6.0",
"jm": "6.0",
"flag_jo": "6.0",
"jo": "6.0",
"flag_jp": "6.0",
"jp": "6.0",
"flag_ke": "6.0",
"ke": "6.0",
"flag_kg": "6.0",
"kg": "6.0",
"flag_kh": "6.0",
"kh": "6.0",
"flag_ki": "6.0",
"ki": "6.0",
"flag_km": "6.0",
"km": "6.0",
"flag_kn": "6.0",
"kn": "6.0",
"flag_kp": "6.0",
"kp": "6.0",
"flag_kr": "6.0",
"kr": "6.0",
"flag_kw": "6.0",
"kw": "6.0",
"flag_ky": "6.0",
"ky": "6.0",
"flag_kz": "6.0",
"kz": "6.0",
"flag_la": "6.0",
"la": "6.0",
"flag_lb": "6.0",
"lb": "6.0",
"flag_lc": "6.0",
"lc": "6.0",
"flag_li": "6.0",
"li": "6.0",
"flag_lk": "6.0",
"lk": "6.0",
"flag_lr": "6.0",
"lr": "6.0",
"flag_ls": "6.0",
"ls": "6.0",
"flag_lt": "6.0",
"lt": "6.0",
"flag_lu": "6.0",
"lu": "6.0",
"flag_lv": "6.0",
"lv": "6.0",
"flag_ly": "6.0",
"ly": "6.0",
"flag_ma": "6.0",
"ma": "6.0",
"flag_mc": "6.0",
"mc": "6.0",
"flag_md": "6.0",
"md": "6.0",
"flag_me": "6.0",
"me": "6.0",
"flag_mf": "6.0",
"mf": "6.0",
"flag_mg": "6.0",
"mg": "6.0",
"flag_mh": "6.0",
"mh": "6.0",
"flag_mk": "6.0",
"mk": "6.0",
"flag_ml": "6.0",
"ml": "6.0",
"flag_mm": "6.0",
"mm": "6.0",
"flag_mn": "6.0",
"mn": "6.0",
"flag_mo": "6.0",
"mo": "6.0",
"flag_mp": "6.0",
"mp": "6.0",
"flag_mq": "6.0",
"mq": "6.0",
"flag_mr": "6.0",
"mr": "6.0",
"flag_ms": "6.0",
"ms": "6.0",
"flag_mt": "6.0",
"mt": "6.0",
"flag_mu": "6.0",
"mu": "6.0",
"flag_mv": "6.0",
"mv": "6.0",
"flag_mw": "6.0",
"mw": "6.0",
"flag_mx": "6.0",
"mx": "6.0",
"flag_my": "6.0",
"my": "6.0",
"flag_mz": "6.0",
"mz": "6.0",
"flag_na": "6.0",
"na": "6.0",
"flag_nc": "6.0",
"nc": "6.0",
"flag_ne": "6.0",
"ne": "6.0",
"flag_nf": "6.0",
"nf": "6.0",
"flag_ng": "6.0",
"nigeria": "6.0",
"flag_ni": "6.0",
"ni": "6.0",
"flag_nl": "6.0",
"nl": "6.0",
"flag_no": "6.0",
"no": "6.0",
"flag_np": "6.0",
"np": "6.0",
"flag_nr": "6.0",
"nr": "6.0",
"flag_nu": "6.0",
"nu": "6.0",
"flag_nz": "6.0",
"nz": "6.0",
"flag_om": "6.0",
"om": "6.0",
"flag_pa": "6.0",
"pa": "6.0",
"flag_pe": "6.0",
"pe": "6.0",
"flag_pf": "6.0",
"pf": "6.0",
"flag_pg": "6.0",
"pg": "6.0",
"flag_ph": "6.0",
"ph": "6.0",
"flag_pk": "6.0",
"pk": "6.0",
"flag_pl": "6.0",
"pl": "6.0",
"flag_pm": "6.0",
"pm": "6.0",
"flag_pn": "6.0",
"pn": "6.0",
"flag_pr": "6.0",
"pr": "6.0",
"flag_ps": "6.0",
"ps": "6.0",
"flag_pt": "6.0",
"pt": "6.0",
"flag_pw": "6.0",
"pw": "6.0",
"flag_py": "6.0",
"py": "6.0",
"flag_qa": "6.0",
"qa": "6.0",
"flag_re": "6.0",
"re": "6.0",
"flag_ro": "6.0",
"ro": "6.0",
"flag_rs": "6.0",
"rs": "6.0",
"flag_ru": "6.0",
"ru": "6.0",
"flag_rw": "6.0",
"rw": "6.0",
"flag_sa": "6.0",
"saudiarabia": "6.0",
"saudi": "6.0",
"flag_sb": "6.0",
"sb": "6.0",
"flag_sc": "6.0",
"sc": "6.0",
"flag_sd": "6.0",
"sd": "6.0",
"flag_se": "6.0",
"se": "6.0",
"flag_sg": "6.0",
"sg": "6.0",
"flag_sh": "6.0",
"sh": "6.0",
"flag_si": "6.0",
"si": "6.0",
"flag_sj": "6.0",
"sj": "6.0",
"flag_sk": "6.0",
"sk": "6.0",
"flag_sl": "6.0",
"sl": "6.0",
"flag_sm": "6.0",
"sm": "6.0",
"flag_sn": "6.0",
"sn": "6.0",
"flag_so": "6.0",
"so": "6.0",
"flag_sr": "6.0",
"sr": "6.0",
"flag_ss": "6.0",
"ss": "6.0",
"flag_st": "6.0",
"st": "6.0",
"flag_sv": "6.0",
"sv": "6.0",
"flag_sx": "6.0",
"sx": "6.0",
"flag_sy": "6.0",
"sy": "6.0",
"flag_sz": "6.0",
"sz": "6.0",
"flag_ta": "6.0",
"ta": "6.0",
"flag_tc": "6.0",
"tc": "6.0",
"flag_td": "6.0",
"td": "6.0",
"flag_tf": "6.0",
"tf": "6.0",
"flag_tg": "6.0",
"tg": "6.0",
"flag_th": "6.0",
"th": "6.0",
"flag_tj": "6.0",
"tj": "6.0",
"flag_tk": "6.0",
"tk": "6.0",
"flag_tl": "6.0",
"tl": "6.0",
"flag_tm": "6.0",
"turkmenistan": "6.0",
"flag_tn": "6.0",
"tn": "6.0",
"flag_to": "6.0",
"to": "6.0",
"flag_tr": "6.0",
"tr": "6.0",
"flag_tt": "6.0",
"tt": "6.0",
"flag_tv": "6.0",
"tuvalu": "6.0",
"flag_tw": "6.0",
"tw": "6.0",
"flag_tz": "6.0",
"tz": "6.0",
"flag_ua": "6.0",
"ua": "6.0",
"flag_ug": "6.0",
"ug": "6.0",
"flag_um": "6.0",
"um": "6.0",
"flag_us": "6.0",
"us": "6.0",
"flag_uy": "6.0",
"uy": "6.0",
"flag_uz": "6.0",
"uz": "6.0",
"flag_va": "6.0",
"va": "6.0",
"flag_vc": "6.0",
"vc": "6.0",
"flag_ve": "6.0",
"ve": "6.0",
"flag_vg": "6.0",
"vg": "6.0",
"flag_vi": "6.0",
"vi": "6.0",
"flag_vn": "6.0",
"vn": "6.0",
"flag_vu": "6.0",
"vu": "6.0",
"flag_wf": "6.0",
"wf": "6.0",
"flag_ws": "6.0",
"ws": "6.0",
"flag_xk": "6.0",
"xk": "6.0",
"flag_ye": "6.0",
"ye": "6.0",
"flag_yt": "6.0",
"yt": "6.0",
"flag_za": "6.0",
"za": "6.0",
"flag_zm": "6.0",
"zm": "6.0",
"flag_zw": "6.0",
"zw": "6.0",
"regional_indicator_z": "6.0",
"regional_indicator_y": "6.0",
"regional_indicator_x": "6.0",
"regional_indicator_w": "6.0",
"regional_indicator_v": "6.0",
"regional_indicator_u": "6.0",
"regional_indicator_t": "6.0",
"regional_indicator_s": "6.0",
"regional_indicator_r": "6.0",
"regional_indicator_q": "6.0",
"regional_indicator_p": "6.0",
"regional_indicator_o": "6.0",
"regional_indicator_n": "6.0",
"regional_indicator_m": "6.0",
"regional_indicator_l": "6.0",
"regional_indicator_k": "6.0",
"regional_indicator_j": "6.0",
"regional_indicator_i": "6.0",
"regional_indicator_h": "6.0",
"regional_indicator_g": "6.0",
"regional_indicator_f": "6.0",
"regional_indicator_e": "6.0",
"regional_indicator_d": "6.0",
"regional_indicator_c": "6.0",
"regional_indicator_b": "6.0",
"regional_indicator_a": "6.0",
"large_blue_circle": "6.0",
"ten": "6.0"
}
\ No newline at end of file
...@@ -8,7 +8,6 @@ module Banzai ...@@ -8,7 +8,6 @@ module Banzai
# Based on HTML::Pipeline::EmojiFilter # Based on HTML::Pipeline::EmojiFilter
class EmojiFilter < HTML::Pipeline::Filter class EmojiFilter < HTML::Pipeline::Filter
IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
IGNORE_UNICODE_EMOJIS = %w(™ © ®).freeze
def call def call
doc.xpath('descendant-or-self::text()').each do |node| doc.xpath('descendant-or-self::text()').each do |node|
...@@ -35,7 +34,8 @@ module Banzai ...@@ -35,7 +34,8 @@ module Banzai
def emoji_name_element_unicode_filter(text) def emoji_name_element_unicode_filter(text)
text.gsub(emoji_pattern) do |match| text.gsub(emoji_pattern) do |match|
name = Regexp.last_match(1) name = Regexp.last_match(1)
Gitlab::Emoji.gl_emoji_tag(name) emoji = TanukiEmoji.find_by_alpha_code(name)
Gitlab::Emoji.gl_emoji_tag(emoji)
end end
end end
...@@ -46,26 +46,19 @@ module Banzai ...@@ -46,26 +46,19 @@ module Banzai
# Returns a String with unicode emoji replaced with gl-emoji unicode. # Returns a String with unicode emoji replaced with gl-emoji unicode.
def emoji_unicode_element_unicode_filter(text) def emoji_unicode_element_unicode_filter(text)
text.gsub(emoji_unicode_pattern) do |moji| text.gsub(emoji_unicode_pattern) do |moji|
emoji_info = Gitlab::Emoji.emojis_by_moji[moji] emoji = TanukiEmoji.find_by_codepoints(moji)
Gitlab::Emoji.gl_emoji_tag(emoji_info['name']) Gitlab::Emoji.gl_emoji_tag(emoji)
end end
end end
# Build a regexp that matches all valid :emoji: names. # Build a regexp that matches all valid :emoji: names.
def self.emoji_pattern def self.emoji_pattern
@emoji_pattern ||= @emoji_pattern ||= TanukiEmoji.index.alpha_code_pattern
%r{(?<=[^[:alnum:]:]|\n|^)
:(#{Gitlab::Emoji.emojis_names.map { |name| Regexp.escape(name) }.join('|')}):
(?=[^[:alnum:]:]|$)}x
end end
# Build a regexp that matches all valid unicode emojis names. # Build a regexp that matches all valid unicode emojis names.
def self.emoji_unicode_pattern def self.emoji_unicode_pattern
@emoji_unicode_pattern ||= @emoji_unicode_pattern ||= TanukiEmoji.index.codepoints_pattern
begin
filtered_emojis = Gitlab::Emoji.emojis_unicodes - IGNORE_UNICODE_EMOJIS
/(#{filtered_emojis.map { |moji| Regexp.escape(moji) }.join('|')})/
end
end end
private private
......
...@@ -4,40 +4,15 @@ module Gitlab ...@@ -4,40 +4,15 @@ module Gitlab
module Emoji module Emoji
extend self extend self
def emojis # When updating emoji assets increase the version below
Gemojione.index.instance_variable_get(:@emoji_by_name) # and update the version number in `app/assets/javascripts/emoji/index.js`
end EMOJI_VERSION = 1
def emojis_by_moji
Gemojione.index.instance_variable_get(:@emoji_by_moji)
end
def emojis_unicodes
emojis_by_moji.keys
end
def emojis_names
emojis.keys
end
def emojis_aliases
@emoji_aliases ||= Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json')))
end
def emoji_filename(name)
emojis[name]["unicode"]
end
def emoji_unicode_filename(moji)
emojis_by_moji[moji]["unicode"]
end
def emoji_unicode_version(name)
emoji_unicode_versions_by_name[name]
end
def normalize_emoji_name(name) # Return a Pathname to emoji's current versioned folder
emojis_aliases[name] || name #
# @return [Pathname] Absolute Path to versioned emojis folder in `public`
def emoji_public_absolute_path
Rails.root.join("public/-/emojis/#{EMOJI_VERSION}")
end end
def emoji_image_tag(name, src) def emoji_image_tag(name, src)
...@@ -54,23 +29,19 @@ module Gitlab ...@@ -54,23 +29,19 @@ module Gitlab
ActionController::Base.helpers.tag(:img, image_options) ActionController::Base.helpers.tag(:img, image_options)
end end
def emoji_exists?(name)
emojis.has_key?(name)
end
# CSS sprite fallback takes precedence over image fallback # CSS sprite fallback takes precedence over image fallback
def gl_emoji_tag(name, options = {}) # @param [TanukiEmoji::Character] emoji
emoji_name = emojis_aliases[name] || name # @param [Hash] options
emoji_info = emojis[emoji_name] def gl_emoji_tag(emoji, options = {})
return unless emoji_info return unless emoji
data = { data = {
name: emoji_name, name: emoji.name,
unicode_version: emoji_unicode_version(emoji_name) unicode_version: emoji.unicode_version
} }
options = { title: emoji_info['description'], data: data }.merge(options) options = { title: emoji.description, data: data }.merge(options)
ActionController::Base.helpers.content_tag('gl-emoji', emoji_info['moji'], options) ActionController::Base.helpers.content_tag('gl-emoji', emoji.codepoints, options)
end end
def custom_emoji_tag(name, image_source) def custom_emoji_tag(name, image_source)
...@@ -82,12 +53,5 @@ module Gitlab ...@@ -82,12 +53,5 @@ module Gitlab
emoji_image_tag(name, image_source).html_safe emoji_image_tag(name, image_source).html_safe
end end
end end
private
def emoji_unicode_versions_by_name
@emoji_unicode_versions_by_name ||=
Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json')))
end
end end
end end
# frozen_string_literal: true # frozen_string_literal: true
namespace :gemojione do namespace :tanuki_emoji do
desc 'Generates Emoji SHA256 digests' desc 'Generates Emoji aliases fixtures'
task aliases: :environment do
task aliases: ['yarn:check', 'environment'] do
require 'json'
aliases = {} aliases = {}
index_file = File.join(Rails.root, 'fixtures', 'emojis', 'index.json') TanukiEmoji.index.all.each do |emoji|
index = Gitlab::Json.parse(File.read(index_file)) emoji.aliases.each do |emoji_alias|
aliases[TanukiEmoji::Character.format_name(emoji_alias)] = emoji.name
index.each_pair do |key, data|
data['aliases'].each do |a|
a.tr!(':', '')
aliases[a] = key
end end
end end
out = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json') aliases_json_file = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
File.open(out, 'w') do |handle| File.open(aliases_json_file, 'w') do |handle|
handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: '')) handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: ''))
end end
end end
task digests: ['yarn:check', 'environment'] do desc 'Generates Emoji SHA256 digests'
task digests: :environment do
require 'digest/sha2' require 'digest/sha2'
require 'json'
# We don't have `node_modules` available in built versions of GitLab digest_emoji_map = {}
FileUtils.cp_r(Rails.root.join('node_modules', 'emoji-unicode-version', 'emoji-unicode-version-map.json'), File.join(Rails.root, 'fixtures', 'emojis')) emojis_map = {}
dir = Gemojione.images_path TanukiEmoji.index.all.each do |emoji|
resultant_emoji_map = {} emoji_path = Gitlab::Emoji.emoji_public_absolute_path.join("#{emoji.name}.png")
resultant_emoji_map_new = {}
Gitlab::Emoji.emojis.each do |name, emoji_hash| digest_entry = {
# Ignore aliases category: emoji.category,
unless Gitlab::Emoji.emojis_aliases.key?(name) moji: emoji.codepoints,
fpath = File.join(dir, "#{emoji_hash['unicode']}.png") description: emoji.description,
hash_digest = Digest::SHA256.file(fpath).hexdigest unicodeVersion: emoji.unicode_version,
digest: Digest::SHA256.file(emoji_path).hexdigest
}
category = emoji_hash['category'] digest_emoji_map[emoji.name] = digest_entry
if name == 'gay_pride_flag'
category = 'flags'
end
entry = {
category: category,
moji: emoji_hash['moji'],
description: emoji_hash['description'],
unicodeVersion: Gitlab::Emoji.emoji_unicode_version(name),
digest: hash_digest
}
resultant_emoji_map[name] = entry # Our new map is only characters to make the json substantially smaller
emoji_entry = {
c: emoji.category,
e: emoji.codepoints,
d: emoji.description,
u: emoji.unicode_version
}
# Our new map is only characters to make the json substantially smaller emojis_map[emoji.name] = emoji_entry
new_entry = { end
c: category,
e: emoji_hash['moji'],
d: emoji_hash['description'],
u: Gitlab::Emoji.emoji_unicode_version(name)
}
resultant_emoji_map_new[name] = new_entry digests_json = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
end File.open(digests_json, 'w') do |handle|
handle.write(Gitlab::Json.pretty_generate(digest_emoji_map))
end end
out = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json') emojis_json = Gitlab::Emoji.emoji_public_absolute_path.join('emojis.json')
File.open(out, 'w') do |handle| File.open(emojis_json, 'w') do |handle|
handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map)) handle.write(Gitlab::Json.pretty_generate(emojis_map))
end end
end
desc 'Import emoji assets from TanukiEmoji to versioned folder'
task import: :environment do
require 'mini_magick'
# Setting to the same size as previous gemojione images
EMOJI_SIZE = 64
emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
puts "Importing emojis into: #{emoji_dir} ..."
out_new = File.join(Rails.root, 'public', '-', 'emojis', '1', 'emojis.json') # Re-create the assets folder and copy emojis renaming them to use name instead of unicode hex
File.open(out_new, 'w') do |handle| FileUtils.rm_rf(emoji_dir) if Dir.exist?(emoji_dir)
handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map_new)) FileUtils.mkdir_p(emoji_dir, mode: 0700)
TanukiEmoji.index.all.each do |emoji|
source = File.join(TanukiEmoji.images_path, emoji.image_name)
destination = File.join(emoji_dir, "#{emoji.name}.png")
FileUtils.cp(source, destination)
resize!(destination, EMOJI_SIZE)
print emoji.codepoints
end end
puts
puts 'Done!'
end end
# This task will generate a standard and Retina sprite of all of the current # This task will generate a standard and Retina sprite of all of the current
# Gemojione Emojis, with the accompanying SCSS map. # TanukiEmoji Emojis, with the accompanying SCSS map.
# #
# It will not appear in `rake -T` output, and the dependent gems are not # It will not appear in `rake -T` output, and the dependent gems are not
# included in the Gemfile by default, because this task will only be needed # included in the Gemfile by default, because this task will only be needed
# occasionally, such as when new Emojis are added to Gemojione. # occasionally, such as when new Emojis are added to TanukiEmoji.
task sprite: :environment do task sprite: :environment do
begin begin
require 'sprite_factory' require 'sprite_factory'
# Sprite-Factory still requires rmagick, but maybe could be migrated to support minimagick
# Upstream issue: https://github.com/jakesgordon/sprite-factory/issues/47#issuecomment-929302890
require 'rmagick' require 'rmagick'
rescue LoadError rescue LoadError
# noop # noop
...@@ -104,24 +113,9 @@ namespace :gemojione do ...@@ -104,24 +113,9 @@ namespace :gemojione do
SPRITESHEET_WIDTH = 860 SPRITESHEET_WIDTH = 860
SPRITESHEET_HEIGHT = 840 SPRITESHEET_HEIGHT = 840
# Set up a map to rename image files emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
emoji_unicode_string_to_name_map = {}
Gitlab::Emoji.emojis.each do |name, emoji_hash|
# Ignore aliases
unless Gitlab::Emoji.emojis_aliases.key?(name)
emoji_unicode_string_to_name_map[emoji_hash['unicode']] = name
end
end
# Copy the Gemojione assets to the temporary folder for renaming puts "Preparing sprites for regular size: #{SIZE}px..."
emoji_dir = "app/assets/images/emoji"
FileUtils.rm_rf(emoji_dir)
FileUtils.mkdir_p(emoji_dir, mode: 0700)
FileUtils.cp_r(File.join(Gemojione.images_path, '.'), emoji_dir)
Dir[File.join(emoji_dir, "**/*.png")].each do |png|
image_path = png
rename_to_named_emoji_image!(emoji_unicode_string_to_name_map, image_path)
end
Dir.mktmpdir do |tmpdir| Dir.mktmpdir do |tmpdir|
FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir) FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
...@@ -130,10 +124,16 @@ namespace :gemojione do ...@@ -130,10 +124,16 @@ namespace :gemojione do
Dir["**/*.png"].each do |png| Dir["**/*.png"].each do |png|
tmp_image_path = File.join(tmpdir, png) tmp_image_path = File.join(tmpdir, png)
resize!(tmp_image_path, SIZE) resize!(tmp_image_path, SIZE)
print '.'
end end
end end
puts ' Done!'
style_path = Rails.root.join(*%w(app assets stylesheets framework emoji_sprites.scss)) puts "\n"
style_path = Rails.root.join(*%w(app assets stylesheets emoji_sprites.scss))
print 'Compiling sprites regular sprites... '
# Combine the resized assets into a packed sprite and re-generate the SCSS # Combine the resized assets into a packed sprite and re-generate the SCSS
SpriteFactory.cssurl = "image-url('$IMAGE')" SpriteFactory.cssurl = "image-url('$IMAGE')"
...@@ -165,31 +165,44 @@ namespace :gemojione do ...@@ -165,31 +165,44 @@ namespace :gemojione do
height: #{SIZE}px; height: #{SIZE}px;
width: #{SIZE}px; width: #{SIZE}px;
/* stylelint-disable media-feature-name-no-vendor-prefix */
@media only screen and (-webkit-min-device-pixel-ratio: 2), @media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min--moz-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2),
only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (-o-min-device-pixel-ratio: 2/1),
only screen and (min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2),
only screen and (min-resolution: 192dpi), only screen and (min-resolution: 192dpi),
only screen and (min-resolution: 2dppx) { only screen and (min-resolution: 2dppx) {
background-image: image-url('emoji@2x.png'); background-image: image-url('emoji@2x.png');
background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px; background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
} }
/* stylelint-enable media-feature-name-no-vendor-prefix */
} }
CSS CSS
end end
end end
puts 'Done!'
puts "\n"
puts "Preparing sprites for HiDPI size: #{RETINA}px..."
# Now do it again but for Retina # Now do it again but for Retina
Dir.mktmpdir do |tmpdir| Dir.mktmpdir do |tmpdir|
# Copy the Gemojione assets to the temporary folder for resizing # Copy the TanukiEmoji assets to the temporary folder for resizing
FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir) FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
Dir.chdir(tmpdir) do Dir.chdir(tmpdir) do
Dir["**/*.png"].each do |png| Dir["**/*.png"].each do |png|
tmp_image_path = File.join(tmpdir, png) tmp_image_path = File.join(tmpdir, png)
resize!(tmp_image_path, RETINA) resize!(tmp_image_path, RETINA)
print '.'
end end
end end
puts ' Done!'
puts "\n"
print 'Compiling HiDPI sprites...'
# Combine the resized assets into a packed sprite and re-generate the SCSS # Combine the resized assets into a packed sprite and re-generate the SCSS
SpriteFactory.run!(tmpdir, { SpriteFactory.run!(tmpdir, {
...@@ -200,20 +213,38 @@ namespace :gemojione do ...@@ -200,20 +213,38 @@ namespace :gemojione do
layout: :packed layout: :packed
}) })
end end
puts ' Done!'
end end
def check_requirements! def check_requirements!
return if defined?(SpriteFactory) && defined?(Magick) unless defined?(Magick)
puts <<~MSG
puts <<-MSG.strip_heredoc This task is disabled by default and should only be run when the TanukiEmoji
This task is disabled by default and should only be run when the Gemojione
gem is updated with new Emojis. gem is updated with new Emojis.
To enable this task, *temporarily* add the following lines to Gemfile and To enable this task, *temporarily* add the following lines to Gemfile and
re-bundle: re-bundle:
gem 'sprite-factory' gem 'rmagick', '~> 3.2'
gem 'rmagick'
It depends on ImageMagick 6, which can be installed via HomeBrew with:
brew unlink imagemagick
brew install imagemagick@6 && brew link imagemagick@6 --force
MSG
exit 1
end
return if Dir.exist? Gitlab::Emoji.emoji_public_absolute_path
puts <<~MSG
You first need to import the assets for Emoji version: #{Gitlab::Emoji::EMOJI_VERSION}
Run the following task:
rake tanuki_emoji:import
MSG MSG
exit 1 exit 1
...@@ -221,25 +252,9 @@ namespace :gemojione do ...@@ -221,25 +252,9 @@ namespace :gemojione do
def resize!(image_path, size) def resize!(image_path, size)
# Resize the image in-place, save it, and free the object # Resize the image in-place, save it, and free the object
image = Magick::Image.read(image_path).first image = MiniMagick::Image.open(image_path)
image.resize!(size, size) image.quality(100)
image.write(image_path) { self.quality = 100 } image.resize("#{size}x#{size}")
image.destroy! image.write(image_path)
end
EMOJI_IMAGE_PATH_RE = /(.*?)(([0-9a-f]-?)+)\.png$/i.freeze
def rename_to_named_emoji_image!(emoji_unicode_string_to_name_map, image_path)
# Rename file from unicode to emoji name
matches = EMOJI_IMAGE_PATH_RE.match(image_path)
preceding_path = matches[1]
unicode_string = matches[2]
name = emoji_unicode_string_to_name_map[unicode_string]
if name
new_png_path = File.join(preceding_path, "#{name}.png")
FileUtils.mv(image_path, new_png_path)
new_png_path
else
puts "Warning: emoji_unicode_string_to_name_map missing entry for #{unicode_string}. Full path: #{image_path}"
end
end end
end end
...@@ -56,13 +56,13 @@ describe('gl_emoji', () => { ...@@ -56,13 +56,13 @@ describe('gl_emoji', () => {
'bomb emoji just with name attribute', 'bomb emoji just with name attribute',
'<gl-emoji data-name="bomb"></gl-emoji>', '<gl-emoji data-name="bomb"></gl-emoji>',
'<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb">💣</gl-emoji>', '<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb">💣</gl-emoji>',
'<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/1/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>', `<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
], ],
[ [
'bomb emoji with name attribute and unicode version', 'bomb emoji with name attribute and unicode version',
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>', '<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>', '<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
'<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/1/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>', `<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
], ],
[ [
'bomb emoji with sprite fallback', 'bomb emoji with sprite fallback',
...@@ -80,7 +80,7 @@ describe('gl_emoji', () => { ...@@ -80,7 +80,7 @@ describe('gl_emoji', () => {
'invalid emoji', 'invalid emoji',
'<gl-emoji data-name="invalid_emoji"></gl-emoji>', '<gl-emoji data-name="invalid_emoji"></gl-emoji>',
'<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament">❔</gl-emoji>', '<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament">❔</gl-emoji>',
'<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/1/grey_question.png" width="20" height="20" align="absmiddle"></gl-emoji>', `<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/${EMOJI_VERSION}/grey_question.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
], ],
])('%s', (name, markup, withEmojiSupport, withoutEmojiSupport) => { ])('%s', (name, markup, withEmojiSupport, withoutEmojiSupport) => {
it(`renders correctly with emoji support`, async () => { it(`renders correctly with emoji support`, async () => {
......
...@@ -6,6 +6,7 @@ RSpec.describe EmojiHelper do ...@@ -6,6 +6,7 @@ RSpec.describe EmojiHelper do
describe '#emoji_icon' do describe '#emoji_icon' do
let(:options) { {} } let(:options) { {} }
let(:emoji_text) { 'rocket' } let(:emoji_text) { 'rocket' }
let(:unicode_version) { '6.0' }
let(:aria_hidden_option) { "aria-hidden=\"true\"" } let(:aria_hidden_option) { "aria-hidden=\"true\"" }
subject { helper.emoji_icon(emoji_text, options) } subject { helper.emoji_icon(emoji_text, options) }
...@@ -14,7 +15,7 @@ RSpec.describe EmojiHelper do ...@@ -14,7 +15,7 @@ RSpec.describe EmojiHelper do
is_expected.to include('<gl-emoji', is_expected.to include('<gl-emoji',
"title=\"#{emoji_text}\"", "title=\"#{emoji_text}\"",
"data-name=\"#{emoji_text}\"", "data-name=\"#{emoji_text}\"",
"data-unicode-version=\"#{::Gitlab::Emoji.emoji_unicode_version(emoji_text)}\"") "data-unicode-version=\"#{unicode_version}\"")
is_expected.not_to include(aria_hidden_option) is_expected.not_to include(aria_hidden_option)
end end
...@@ -25,7 +26,7 @@ RSpec.describe EmojiHelper do ...@@ -25,7 +26,7 @@ RSpec.describe EmojiHelper do
is_expected.to include('<gl-emoji', is_expected.to include('<gl-emoji',
"title=\"#{emoji_text}\"", "title=\"#{emoji_text}\"",
"data-name=\"#{emoji_text}\"", "data-name=\"#{emoji_text}\"",
"data-unicode-version=\"#{::Gitlab::Emoji.emoji_unicode_version(emoji_text)}\"", "data-unicode-version=\"#{unicode_version}\"",
aria_hidden_option) aria_hidden_option)
end end
end end
......
...@@ -28,9 +28,9 @@ RSpec.describe Banzai::Filter::EmojiFilter do ...@@ -28,9 +28,9 @@ RSpec.describe Banzai::Filter::EmojiFilter do
it 'replaces name versions of trademark, copyright, and registered trademark' do it 'replaces name versions of trademark, copyright, and registered trademark' do
doc = filter('<p>:tm: :copyright: :registered:</p>') doc = filter('<p>:tm: :copyright: :registered:</p>')
expect(doc.css('gl-emoji')[0].text).to eq '™' expect(doc.css('gl-emoji')[0].text).to eq '™'
expect(doc.css('gl-emoji')[1].text).to eq '©' expect(doc.css('gl-emoji')[1].text).to eq '
expect(doc.css('gl-emoji')[2].text).to eq '®' expect(doc.css('gl-emoji')[2].text).to eq '
end end
it 'correctly encodes the URL' do it 'correctly encodes the URL' do
......
...@@ -3,18 +3,20 @@ ...@@ -3,18 +3,20 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Banzai::Pipeline::EmojiPipeline do RSpec.describe Banzai::Pipeline::EmojiPipeline do
let(:emoji) { TanukiEmoji.find_by_alpha_code('100') }
def parse(text) def parse(text)
described_class.to_html(text, {}) described_class.to_html(text, {})
end end
it 'replaces emoji' do it 'replaces emoji' do
expected_result = "Hello world #{Gitlab::Emoji.gl_emoji_tag('100')}" expected_result = "Hello world #{Gitlab::Emoji.gl_emoji_tag(emoji)}"
expect(parse('Hello world :100:')).to eq(expected_result) expect(parse('Hello world :100:')).to eq(expected_result)
end end
it 'filters out HTML tags' do it 'filters out HTML tags' do
expected_result = "Hello &lt;b&gt;world&lt;/b&gt; #{Gitlab::Emoji.gl_emoji_tag('100')}" expected_result = "Hello &lt;b&gt;world&lt;/b&gt; #{Gitlab::Emoji.gl_emoji_tag(emoji)}"
expect(parse('Hello <b>world</b> :100:')).to eq(expected_result) expect(parse('Hello <b>world</b> :100:')).to eq(expected_result)
end end
......
...@@ -3,90 +3,6 @@ ...@@ -3,90 +3,6 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Emoji do RSpec.describe Gitlab::Emoji do
let_it_be(:emojis) { Gemojione.index.instance_variable_get(:@emoji_by_name) }
let_it_be(:emojis_by_moji) { Gemojione.index.instance_variable_get(:@emoji_by_moji) }
let_it_be(:emoji_unicode_versions_by_name) { Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json'))) }
let_it_be(:emojis_aliases) { Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json'))) }
describe '.emojis' do
it 'returns emojis' do
current_emojis = described_class.emojis
expect(current_emojis).to eq(emojis)
end
end
describe '.emojis_by_moji' do
it 'return emojis by moji' do
current_emojis_by_moji = described_class.emojis_by_moji
expect(current_emojis_by_moji).to eq(emojis_by_moji)
end
end
describe '.emojis_unicodes' do
it 'returns emoji unicodes' do
emoji_keys = described_class.emojis_unicodes
expect(emoji_keys).to eq(emojis_by_moji.keys)
end
end
describe '.emojis_names' do
it 'returns emoji names' do
emoji_names = described_class.emojis_names
expect(emoji_names).to eq(emojis.keys)
end
end
describe '.emojis_aliases' do
it 'returns emoji aliases' do
emoji_aliases = described_class.emojis_aliases
expect(emoji_aliases).to eq(emojis_aliases)
end
end
describe '.emoji_filename' do
it 'returns emoji filename' do
# "100" => {"unicode"=>"1F4AF"...}
emoji_filename = described_class.emoji_filename('100')
expect(emoji_filename).to eq(emojis['100']['unicode'])
end
end
describe '.emoji_unicode_filename' do
it 'returns emoji unicode filename' do
emoji_unicode_filename = described_class.emoji_unicode_filename('💯')
expect(emoji_unicode_filename).to eq(emojis_by_moji['💯']['unicode'])
end
end
describe '.emoji_unicode_version' do
it 'returns emoji unicode version by name' do
emoji_unicode_version = described_class.emoji_unicode_version('100')
expect(emoji_unicode_version).to eq(emoji_unicode_versions_by_name['100'])
end
end
describe '.normalize_emoji_name' do
it 'returns same name if not found in aliases' do
emoji_name = described_class.normalize_emoji_name('random')
expect(emoji_name).to eq('random')
end
it 'returns name if name found in aliases' do
emoji_name = described_class.normalize_emoji_name('small_airplane')
expect(emoji_name).to eq(emojis_aliases['small_airplane'])
end
end
describe '.emoji_image_tag' do describe '.emoji_image_tag' do
it 'returns emoji image tag' do it 'returns emoji image tag' do
emoji_image = described_class.emoji_image_tag('emoji_one', 'src_url') emoji_image = described_class.emoji_image_tag('emoji_one', 'src_url')
...@@ -104,29 +20,17 @@ RSpec.describe Gitlab::Emoji do ...@@ -104,29 +20,17 @@ RSpec.describe Gitlab::Emoji do
end end
end end
describe '.emoji_exists?' do
it 'returns true if the name exists' do
emoji_exists = described_class.emoji_exists?('100')
expect(emoji_exists).to be_truthy
end
it 'returns false if the name does not exist' do
emoji_exists = described_class.emoji_exists?('random')
expect(emoji_exists).to be_falsey
end
end
describe '.gl_emoji_tag' do describe '.gl_emoji_tag' do
it 'returns gl emoji tag if emoji is found' do it 'returns gl emoji tag if emoji is found' do
gl_tag = described_class.gl_emoji_tag('small_airplane') emoji = TanukiEmoji.find_by_alpha_code('small_airplane')
gl_tag = described_class.gl_emoji_tag(emoji)
expect(gl_tag).to eq('<gl-emoji title="small airplane" data-name="airplane_small" data-unicode-version="7.0">🛩</gl-emoji>') expect(gl_tag).to eq('<gl-emoji title="small airplane" data-name="airplane_small" data-unicode-version="7.0">🛩</gl-emoji>')
end end
it 'returns nil if emoji name is not found' do it 'returns nil if emoji is not found' do
gl_tag = described_class.gl_emoji_tag('random') emoji = TanukiEmoji.find_by_alpha_code('random')
gl_tag = described_class.gl_emoji_tag(emoji)
expect(gl_tag).to be_nil expect(gl_tag).to be_nil
end end
......
...@@ -14,7 +14,7 @@ RSpec.describe CustomEmoji do ...@@ -14,7 +14,7 @@ RSpec.describe CustomEmoji do
end end
describe 'exclusion of duplicated emoji' do describe 'exclusion of duplicated emoji' do
let(:emoji_name) { Gitlab::Emoji.emojis_names.sample } let(:emoji_name) { TanukiEmoji.index.all.sample.name }
let(:group) { create(:group, :private) } let(:group) { create(:group, :private) }
it 'disallows emoji names of built-in emoji' do it 'disallows emoji names of built-in emoji' do
......
...@@ -6,21 +6,22 @@ RSpec.describe AwardEmojiPresenter do ...@@ -6,21 +6,22 @@ RSpec.describe AwardEmojiPresenter do
let(:emoji_name) { 'thumbsup' } let(:emoji_name) { 'thumbsup' }
let(:award_emoji) { build(:award_emoji, name: emoji_name) } let(:award_emoji) { build(:award_emoji, name: emoji_name) }
let(:presenter) { described_class.new(award_emoji) } let(:presenter) { described_class.new(award_emoji) }
let(:emoji) { TanukiEmoji.find_by_alpha_code(emoji_name) }
describe '#description' do describe '#description' do
it { expect(presenter.description).to eq Gitlab::Emoji.emojis[emoji_name]['description'] } it { expect(presenter.description).to eq emoji.description }
end end
describe '#unicode' do describe '#unicode' do
it { expect(presenter.unicode).to eq Gitlab::Emoji.emojis[emoji_name]['unicode'] } it { expect(presenter.unicode).to eq emoji.hex }
end end
describe '#unicode_version' do describe '#unicode_version' do
it { expect(presenter.unicode_version).to eq Gitlab::Emoji.emoji_unicode_version(emoji_name) } it { expect(presenter.unicode_version).to eq('6.0') }
end end
describe '#emoji' do describe '#emoji' do
it { expect(presenter.emoji).to eq Gitlab::Emoji.emojis[emoji_name]['moji'] } it { expect(presenter.emoji).to eq emoji.codepoints }
end end
describe 'when presenting an award emoji with an invalid name' do describe 'when presenting an award emoji with an invalid name' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe AwardEmojis::BaseService do
let(:awardable) { build(:note) }
let(:current_user) { build(:user) }
describe '.initialize' do
subject { described_class }
it 'uses same emoji name if not an alias' do
emoji_name = 'horse'
expect(subject.new(awardable, emoji_name, current_user).name).to eq(emoji_name)
end
it 'uses emoji original name if its an alias' do
emoji_alias = 'small_airplane'
emoji_name = 'airplane_small'
expect(subject.new(awardable, emoji_alias, current_user).name).to eq(emoji_name)
end
end
end
...@@ -53,7 +53,7 @@ RSpec.describe Users::UpdateService do ...@@ -53,7 +53,7 @@ RSpec.describe Users::UpdateService do
result = update_user(user, status: { emoji: "Moo!" }) result = update_user(user, status: { emoji: "Moo!" })
expect(result[:status]).to eq(:error) expect(result[:status]).to eq(:error)
expect(result[:message]).to eq("Emoji is not included in the list") expect(result[:message]).to eq("Emoji is not a valid emoji name")
end end
it 'updates user detail with provided attributes' do it 'updates user detail with provided attributes' do
......
...@@ -4810,11 +4810,6 @@ emoji-regex@^8.0.0: ...@@ -4810,11 +4810,6 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
emoji-unicode-version@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc"
integrity sha1-Dr82ZrVBQJeXHTSZTimfznXNuvw=
emojis-list@^3.0.0: emojis-list@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment