diff --git a/Gemfile b/Gemfile
index 1e6648df48b..a2ed0fa9f26 100644
--- a/Gemfile
+++ b/Gemfile
@@ -129,7 +129,7 @@ gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.3'
-gem 'gitlab-fog-azure-rm', '~> 1.2.0', require: false
+gem 'gitlab-fog-azure-rm', '~> 1.2.0', require: 'fog/azurerm'
# for Google storage
gem 'google-api-client', '~> 0.33'
@@ -290,7 +290,7 @@ gem 'autoprefixer-rails', '10.2.5.1'
gem 'terser', '1.0.2'
gem 'addressable', '~> 2.8'
-gem 'gemojione', '~> 3.3'
+gem 'tanuki_emoji', '~> 0.5'
gem 'gon', '~> 6.4.0'
gem 'request_store', '~> 1.5'
gem 'base32', '~> 0.3.0'
@@ -348,6 +348,8 @@ group :development do
# thin instead webrick
gem 'thin', '~> 1.8.0'
+
+ gem 'sprite-factory', '~> 1.7'
end
group :development, :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index a6b7f598ec6..be5272e3e5d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -436,8 +436,6 @@ GEM
ruby-progressbar (~> 1.4)
fuzzyurl (0.9.0)
gemoji (3.0.1)
- gemojione (3.3.0)
- json
get_process_mem (0.2.5)
ffi (~> 1.0)
gettext (3.3.6)
@@ -1216,6 +1214,7 @@ GEM
spring (2.1.1)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
+ sprite-factory (1.7.1)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
@@ -1246,6 +1245,7 @@ GEM
sys-filesystem (1.1.9)
ffi
sysexits (1.2.0)
+ tanuki_emoji (0.5.0)
temple (0.8.2)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
@@ -1454,7 +1454,6 @@ DEPENDENCIES
fog-rackspace (~> 0.1.1)
fugit (~> 1.2.1)
fuubar (~> 2.2.0)
- gemojione (~> 3.3)
gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
@@ -1622,11 +1621,13 @@ DEPENDENCIES
spamcheck (~> 0.1.0)
spring (~> 2.1.0)
spring-commands-rspec (~> 1.0.4)
+ sprite-factory (~> 1.7)
sprockets (~> 3.7.0)
sshkey (~> 2.0)
stackprof (~> 0.2.15)
state_machines-activerecord (~> 0.8.0)
sys-filesystem (~> 1.1.6)
+ tanuki_emoji (~> 0.5)
terser (= 1.0.2)
test-prof (~> 1.0.7)
test_file_finder (~> 0.1.3)
diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js
index 7672151af2a..478e3f6aed9 100644
--- a/app/assets/javascripts/emoji/index.js
+++ b/app/assets/javascripts/emoji/index.js
@@ -9,6 +9,7 @@ let emojiMap = null;
let validEmojiNames = null;
export const FALLBACK_EMOJI_KEY = 'grey_question';
+// Keep the version in sync with `lib/gitlab/emoji.rb`
export const EMOJI_VERSION = '1';
const isLocalStorageAvailable = AccessorUtilities.canUseLocalStorage();
diff --git a/app/finders/award_emojis_finder.rb b/app/finders/award_emojis_finder.rb
index 9ff64637128..709d3f3e593 100644
--- a/app/finders/award_emojis_finder.rb
+++ b/app/finders/award_emojis_finder.rb
@@ -40,7 +40,7 @@ class AwardEmojisFinder
def validate_name_param
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
def validate_awarded_by_param
diff --git a/app/helpers/emoji_helper.rb b/app/helpers/emoji_helper.rb
index 51b7fd7f352..c390924f7e3 100644
--- a/app/helpers/emoji_helper.rb
+++ b/app/helpers/emoji_helper.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module EmojiHelper
- def emoji_icon(*args)
- raw Gitlab::Emoji.gl_emoji_tag(*args)
+ def emoji_icon(emoji_name, *options)
+ emoji = TanukiEmoji.find_by_alpha_code(emoji_name)
+ raw Gitlab::Emoji.gl_emoji_tag(emoji, *options)
end
end
diff --git a/app/helpers/reminder_emails_helper.rb b/app/helpers/reminder_emails_helper.rb
index bffb3cf7751..132fc3b784c 100644
--- a/app/helpers/reminder_emails_helper.rb
+++ b/app/helpers/reminder_emails_helper.rb
@@ -7,7 +7,8 @@ module ReminderEmailsHelper
s_('InviteReminderEmail|Invitation pending')
when 1
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
s_('InviteReminderEmail|Hey there!')
end
diff --git a/app/models/award_emoji.rb b/app/models/award_emoji.rb
index c8f6b9aaedb..b665f3d5d8c 100644
--- a/app/models/award_emoji.rb
+++ b/app/models/award_emoji.rb
@@ -14,7 +14,7 @@ class AwardEmoji < ApplicationRecord
validates :user, presence: true
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? }
participant :user
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 990ef71a457..f5f72250981 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -1214,7 +1214,19 @@ module Ci
end
def kubernetes_variables
- [] # Overridden in EE
+ ::Gitlab::Ci::Variables::Collection.new.tap do |collection|
+ # A cluster deployemnt may also define a KUBECONFIG variable, so to keep existing
+ # configurations working we shouldn't overwrite it here.
+ # This check will be removed when Cluster and Agent configurations are
+ # merged in https://gitlab.com/gitlab-org/gitlab/-/issues/335089
+ break collection if deployment&.deployment_cluster
+
+ template = ::Ci::GenerateKubeconfigService.new(self).execute # rubocop: disable CodeReuse/ServiceClass
+
+ if template.valid?
+ collection.append(key: 'KUBECONFIG', value: template.to_yaml, public: false, file: true)
+ end
+ end
end
def conditionally_allow_failure!(exit_code)
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index ef25ced8610..44652c7bdaa 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -1264,6 +1264,16 @@ module Ci
end
end
+ def authorized_cluster_agents
+ strong_memoize(:authorized_cluster_agents) do
+ if ::Feature.enabled?(:group_authorized_agents, project, default_enabled: :yaml)
+ ::Clusters::AgentAuthorizationsFinder.new(project).execute.map(&:agent)
+ else
+ ::Clusters::DeployableAgentsFinder.new(project).execute
+ end
+ end
+ end
+
private
def add_message(severity, content)
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index ecdac64b31b..173b38b2c63 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -31,7 +31,7 @@ class CustomEmoji < ApplicationRecord
private
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 })
end
end
diff --git a/app/models/user_status.rb b/app/models/user_status.rb
index 1c8634e47c3..5c446318dce 100644
--- a/app/models/user_status.rb
+++ b/app/models/user_status.rb
@@ -22,7 +22,7 @@ class UserStatus < ApplicationRecord
enum availability: { not_set: 0, busy: 1 }
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
scope :scheduled_for_cleanup, -> { where(arel_table[:clear_status_at].lteq(Time.current)) }
diff --git a/app/presenters/award_emoji_presenter.rb b/app/presenters/award_emoji_presenter.rb
index 8a7b58e0aba..9a1c8d6934d 100644
--- a/app/presenters/award_emoji_presenter.rb
+++ b/app/presenters/award_emoji_presenter.rb
@@ -4,24 +4,24 @@ class AwardEmojiPresenter < Gitlab::View::Presenter::Delegated
presents ::AwardEmoji, as: :award_emoji
def description
- as_emoji['description']
+ as_emoji&.description
end
def unicode
- as_emoji['unicode']
+ as_emoji&.hex
end
def emoji
- as_emoji['moji']
+ as_emoji&.codepoints
end
def unicode_version
- Gitlab::Emoji.emoji_unicode_version(award_emoji.name)
+ as_emoji&.unicode_version
end
private
def as_emoji
- @emoji ||= Gitlab::Emoji.emojis[award_emoji.name] || {}
+ @emoji ||= TanukiEmoji.find_by_alpha_code(award_emoji.name)
end
end
diff --git a/app/services/award_emojis/base_service.rb b/app/services/award_emojis/base_service.rb
index a677d03a221..626e26d63b5 100644
--- a/app/services/award_emojis/base_service.rb
+++ b/app/services/award_emojis/base_service.rb
@@ -14,7 +14,7 @@ module AwardEmojis
private
def normalize_name(name)
- Gitlab::Emoji.normalize_emoji_name(name)
+ TanukiEmoji.find_by_alpha_code(name)&.name || name
end
# Provide more error state data than what BaseService allows.
diff --git a/app/services/ci/generate_kubeconfig_service.rb b/app/services/ci/generate_kubeconfig_service.rb
new file mode 100644
index 00000000000..18f68c0ff09
--- /dev/null
+++ b/app/services/ci/generate_kubeconfig_service.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Ci
+ class GenerateKubeconfigService
+ def initialize(build)
+ @build = build
+ @template = Gitlab::Kubernetes::Kubeconfig::Template.new
+ end
+
+ def execute
+ template.add_cluster(
+ name: cluster_name,
+ url: Gitlab::Kas.tunnel_url
+ )
+
+ agents.each do |agent|
+ user = user_name(agent)
+
+ template.add_user(
+ name: user,
+ token: agent_token(agent)
+ )
+
+ template.add_context(
+ name: context_name(agent),
+ cluster: cluster_name,
+ user: user
+ )
+ end
+
+ template
+ end
+
+ private
+
+ attr_reader :build, :template
+
+ def agents
+ build.pipeline.authorized_cluster_agents
+ end
+
+ def cluster_name
+ 'gitlab'
+ end
+
+ def user_name(agent)
+ ['agent', agent.id].join(delimiter)
+ end
+
+ def context_name(agent)
+ [agent.project.full_path, agent.name].join(delimiter)
+ end
+
+ def agent_token(agent)
+ ['ci', agent.id, build.token].join(delimiter)
+ end
+
+ def delimiter
+ ':'
+ end
+ end
+end
diff --git a/app/validators/gitlab/emoji_name_validator.rb b/app/validators/gitlab/emoji_name_validator.rb
new file mode 100644
index 00000000000..a9092d0194f
--- /dev/null
+++ b/app/validators/gitlab/emoji_name_validator.rb
@@ -0,0 +1,19 @@
+# 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
diff --git a/config/application.rb b/config/application.rb
index dba9550a3dc..055a89efa6a 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -199,7 +199,7 @@ module Gitlab
config.assets.enabled = true
# 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.precompile << "application_utilities.css"
diff --git a/config/initializers/direct_upload_support.rb b/config/initializers/direct_upload_support.rb
index 880aea7d114..f57f0d7980d 100644
--- a/config/initializers/direct_upload_support.rb
+++ b/config/initializers/direct_upload_support.rb
@@ -17,7 +17,7 @@ class DirectUploadsValidator
raise ValidationError, "No provider configured for '#{uploader_type}'. #{supported_provider_text}" if provider.blank?
- return if provider_loaded?(provider)
+ return if provider_supported?(provider)
raise ValidationError, "Object storage provider '#{provider}' is not supported " \
"when 'direct_upload' is used for '#{uploader_type}'. #{supported_provider_text}"
@@ -25,12 +25,8 @@ class DirectUploadsValidator
private
- def provider_loaded?(provider)
- return false unless SUPPORTED_DIRECT_UPLOAD_PROVIDERS.include?(provider)
-
- require 'fog/azurerm' if provider == ObjectStorage::Config::AZURE_PROVIDER
-
- true
+ def provider_supported?(provider)
+ SUPPORTED_DIRECT_UPLOAD_PROVIDERS.include?(provider)
end
def supported_provider_text
diff --git a/db/fixtures/development/15_award_emoji.rb b/db/fixtures/development/15_award_emoji.rb
index 2b69a6c26ab..efad7e92bb0 100644
--- a/db/fixtures/development/15_award_emoji.rb
+++ b/db/fixtures/development/15_award_emoji.rb
@@ -1,15 +1,13 @@
require './spec/support/sidekiq_middleware'
Gitlab::Seeder.quiet do
- EMOJI = Gitlab::Emoji.emojis.keys
-
def seed_award_emoji(klass)
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|
- 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|
- AwardEmojis::AddService.new(note, EMOJI.sample, user).execute
+ AwardEmojis::AddService.new(note, TanukiEmoji.index.all.sample.name, user).execute
end
print '.'
diff --git a/doc/user/application_security/cluster_image_scanning/index.md b/doc/user/application_security/cluster_image_scanning/index.md
index abbe00a85ab..3a2ca47c82f 100644
--- a/doc/user/application_security/cluster_image_scanning/index.md
+++ b/doc/user/application_security/cluster_image_scanning/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Cluster Image Scanning **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 14.1.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/) in GitLab 14.1.
WARNING:
This analyzer is in [Alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha)
@@ -208,7 +208,7 @@ The cluster image scanning tool emits a JSON report file. For more information,
Here's an example cluster image scanning report:
```json-doc
-{{
+{
"version": "14.0.2",
"scan": {
"scanner": {
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 22b54bf019c..da2816ab6ed 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Container Scanning **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in GitLab 10.4.
Your application's Docker image may itself be based on Docker images that contain known
vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and
@@ -148,7 +148,7 @@ Support depends on the scanner:
#### UBI-based images
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 14.1.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5775) in GitLab 14.1.
GitLab also offers [Red Hat UBI](https://www.redhat.com/en/blog/introducing-red-hat-universal-base-image)
versions of the container-scanning images. You can therefore replace standard images with UBI-based
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
index 7cbbb9d520c..6b978d72748 100644
--- a/doc/user/application_security/policies/index.md
+++ b/doc/user/application_security/policies/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Policies **(ULTIMATE)**
-> - Introduced in GitLab Ultimate 13.10 [with a flag](https://gitlab.com/groups/gitlab-org/-/epics/5329) named `security_orchestration_policies_configuration`. Disabled by default.
-> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab Ultimate 14.3.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5329) in GitLab 13.10 with a flag named `security_orchestration_policies_configuration`. Disabled by default.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab 14.3.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab 14.4.
Policies in GitLab provide security teams a way to require scans of their choice to be run
@@ -49,7 +49,7 @@ users must make changes by following the
## Policy editor
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3403) in GitLab Ultimate 13.4.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3403) in GitLab 13.4.
You can use the policy editor to create, edit, and delete policies:
@@ -79,7 +79,7 @@ mode to fix your policy before Rule mode is available again.
## Container Network Policy
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in GitLab Ultimate 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in GitLab 12.9.
The **Container Network Policy** section provides packet flow metrics for
your application's Kubernetes namespace. This section has the following
@@ -154,7 +154,7 @@ at the bottom of the editor.
### Configure a Network Policy Alert
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab Ultimate 13.9.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab 13.9.
> - The feature flag was removed and the Threat Monitoring Alerts Project was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab 14.0.
You can use policy alerts to track your policy's impact. Alerts are only available if you've
diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md
index 977469e6844..ae5f6ba0fe1 100644
--- a/doc/user/application_security/threat_monitoring/index.md
+++ b/doc/user/application_security/threat_monitoring/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Threat Monitoring **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in GitLab 12.9.
The **Threat Monitoring** page provides alerts and metrics
for the GitLab application runtime security features. You can access
@@ -20,7 +20,7 @@ GitLab supports statistics for the following security features:
## Container Network Policy Alert list
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in GitLab 13.9.
The policy alert list displays your policy's alert activity. You can sort the list by these columns:
diff --git a/doc/user/project/repository/vscode.md b/doc/user/project/repository/vscode.md
new file mode 100644
index 00000000000..11dee1c78f4
--- /dev/null
+++ b/doc/user/project/repository/vscode.md
@@ -0,0 +1,47 @@
+---
+stage: Create
+group: Code Review
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GitLab Workflow VS Code extension **(FREE)**
+
+The [GitLab VS Code Extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
+integrates GitLab with Visual Studio Code. You can decrease context switching and
+do more day-to-day tasks in Visual Studio Code, such as:
+
+- [View issues](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-issues-review-mrs).
+- Run [common commands](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#commands)
+ from the Visual Studio Code [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
+- Create and [review](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#merge-request-reviews)
+ merge requests directly from Visual Studio Code.
+- [Validate your GitLab CI configuration](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#validate-gitlab-ci-configuration).
+- [View the status of your pipeline](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#information-about-your-branch-pipelines-mr-closing-issue).
+- [Create](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#create-snippet)
+ and paste snippets to, and from, your editor.
+- [Browse repositories](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-a-repository-without-cloning)
+ without cloning them.
+
+## Download the extension
+
+Download the extension from the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow).
+
+## Configure the extension
+
+After you [download the extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
+you can [configure](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#extension-settings):
+
+- [Features to display or hide](https://gitlab.com/gitlab-org/gitlab-vscode-extension#extension-settings).
+- [Self-signed certificate](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#self-signed-certificates) information.
+
+## Report issues with the extension
+
+Report any issues, bugs, or feature requests in the
+[`gitlab-vscode-extension` issue queue](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues).
+
+## Resources
+
+- [Download the extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
+- [Extension documentation](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md)
+- The extension source code is available in the
+ [`gitlab-vscode-extension`](https://gitlab.com/gitlab-org/gitlab-vscode-extension/) project.
diff --git a/fixtures/emojis/emoji-unicode-version-map.json b/fixtures/emojis/emoji-unicode-version-map.json
deleted file mode 100644
index 5164fe39426..00000000000
--- a/fixtures/emojis/emoji-unicode-version-map.json
+++ /dev/null
@@ -1,2377 +0,0 @@
-{
- "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
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 6c5350082e8..30b8084d293 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -210,9 +210,7 @@ module Backup
def object_storage_config
@object_storage_config ||= begin
- config = ObjectStorage::Config.new(Gitlab.config.backup.upload)
- config.load_provider
- config
+ ObjectStorage::Config.new(Gitlab.config.backup.upload)
end
end
diff --git a/lib/banzai/filter/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb
index 9d24bf028b6..d8c9fd0a7f0 100644
--- a/lib/banzai/filter/emoji_filter.rb
+++ b/lib/banzai/filter/emoji_filter.rb
@@ -8,7 +8,6 @@ module Banzai
# Based on HTML::Pipeline::EmojiFilter
class EmojiFilter < HTML::Pipeline::Filter
IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
- IGNORE_UNICODE_EMOJIS = %w(™ © ®).freeze
def call
doc.xpath('descendant-or-self::text()').each do |node|
@@ -35,7 +34,8 @@ module Banzai
def emoji_name_element_unicode_filter(text)
text.gsub(emoji_pattern) do |match|
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
@@ -46,26 +46,19 @@ module Banzai
# Returns a String with unicode emoji replaced with gl-emoji unicode.
def emoji_unicode_element_unicode_filter(text)
text.gsub(emoji_unicode_pattern) do |moji|
- emoji_info = Gitlab::Emoji.emojis_by_moji[moji]
- Gitlab::Emoji.gl_emoji_tag(emoji_info['name'])
+ emoji = TanukiEmoji.find_by_codepoints(moji)
+ Gitlab::Emoji.gl_emoji_tag(emoji)
end
end
# Build a regexp that matches all valid :emoji: names.
def self.emoji_pattern
- @emoji_pattern ||=
- %r{(?<=[^[:alnum:]:]|\n|^)
- :(#{Gitlab::Emoji.emojis_names.map { |name| Regexp.escape(name) }.join('|')}):
- (?=[^[:alnum:]:]|$)}x
+ @emoji_pattern ||= TanukiEmoji.index.alpha_code_pattern
end
# Build a regexp that matches all valid unicode emojis names.
def self.emoji_unicode_pattern
- @emoji_unicode_pattern ||=
- begin
- filtered_emojis = Gitlab::Emoji.emojis_unicodes - IGNORE_UNICODE_EMOJIS
- /(#{filtered_emojis.map { |moji| Regexp.escape(moji) }.join('|')})/
- end
+ @emoji_unicode_pattern ||= TanukiEmoji.index.codepoints_pattern
end
private
diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb
index 2b5f465d3c5..519b1d94bf5 100644
--- a/lib/gitlab/emoji.rb
+++ b/lib/gitlab/emoji.rb
@@ -4,40 +4,15 @@ module Gitlab
module Emoji
extend self
- def emojis
- Gemojione.index.instance_variable_get(:@emoji_by_name)
- end
+ # When updating emoji assets increase the version below
+ # and update the version number in `app/assets/javascripts/emoji/index.js`
+ 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)
- emojis_aliases[name] || name
+ # Return a Pathname to emoji's current versioned folder
+ #
+ # @return [Pathname] Absolute Path to versioned emojis folder in `public`
+ def emoji_public_absolute_path
+ Rails.root.join("public/-/emojis/#{EMOJI_VERSION}")
end
def emoji_image_tag(name, src)
@@ -54,23 +29,19 @@ module Gitlab
ActionController::Base.helpers.tag(:img, image_options)
end
- def emoji_exists?(name)
- emojis.has_key?(name)
- end
-
# CSS sprite fallback takes precedence over image fallback
- def gl_emoji_tag(name, options = {})
- emoji_name = emojis_aliases[name] || name
- emoji_info = emojis[emoji_name]
- return unless emoji_info
+ # @param [TanukiEmoji::Character] emoji
+ # @param [Hash] options
+ def gl_emoji_tag(emoji, options = {})
+ return unless emoji
data = {
- name: emoji_name,
- unicode_version: emoji_unicode_version(emoji_name)
+ name: 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
def custom_emoji_tag(name, image_source)
@@ -82,12 +53,5 @@ module Gitlab
emoji_image_tag(name, image_source).html_safe
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
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index 6d3b92afb53..fdc4c22001f 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -56,20 +56,10 @@ module Gitlab
end
def download(url, upload_path)
- File.open(upload_path, 'wb') do |file|
- Gitlab::HTTP.get(url, stream_body: true) do |fragment|
- if [301, 302, 307].include?(fragment.code)
- Gitlab::Import::Logger.warn(message: "received redirect fragment", fragment_code: fragment.code)
- elsif fragment.code == 200
- file.write(fragment)
- else
- raise Gitlab::ImportExport::Error, "unsupported response downloading fragment #{fragment.code}"
- end
- end
+ File.open(upload_path, 'w') do |file|
+ # Download (stream) file from the uploader's location
+ IO.copy_stream(URI.parse(url).open, file)
end
- rescue StandardError => e
- @shared.error(e) # rubocop:disable Gitlab/ModuleWithInstanceVariables
- raise e
end
def tar_with_options(archive:, dir:, options:)
diff --git a/lib/object_storage/config.rb b/lib/object_storage/config.rb
index 82d9fc07043..056e22278dd 100644
--- a/lib/object_storage/config.rb
+++ b/lib/object_storage/config.rb
@@ -12,16 +12,6 @@ module ObjectStorage
@options = options.to_hash.deep_symbolize_keys
end
- def load_provider
- if aws?
- require 'fog/aws'
- elsif google?
- require 'fog/google'
- elsif azure?
- require 'fog/azurerm'
- end
- end
-
def credentials
@credentials ||= options[:connection] || {}
end
diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake
deleted file mode 100644
index a4600a0ed16..00000000000
--- a/lib/tasks/gemojione.rake
+++ /dev/null
@@ -1,245 +0,0 @@
-# frozen_string_literal: true
-
-namespace :gemojione do
- desc 'Generates Emoji SHA256 digests'
-
- task aliases: ['yarn:check', 'environment'] do
- require 'json'
-
- aliases = {}
-
- index_file = File.join(Rails.root, 'fixtures', 'emojis', 'index.json')
- index = Gitlab::Json.parse(File.read(index_file))
-
- index.each_pair do |key, data|
- data['aliases'].each do |a|
- a.tr!(':', '')
-
- aliases[a] = key
- end
- end
-
- out = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
- File.open(out, 'w') do |handle|
- handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: ''))
- end
- end
-
- task digests: ['yarn:check', 'environment'] do
- require 'digest/sha2'
- require 'json'
-
- # We don't have `node_modules` available in built versions of GitLab
- FileUtils.cp_r(Rails.root.join('node_modules', 'emoji-unicode-version', 'emoji-unicode-version-map.json'), File.join(Rails.root, 'fixtures', 'emojis'))
-
- dir = Gemojione.images_path
- resultant_emoji_map = {}
- resultant_emoji_map_new = {}
-
- Gitlab::Emoji.emojis.each do |name, emoji_hash|
- # Ignore aliases
- unless Gitlab::Emoji.emojis_aliases.key?(name)
- fpath = File.join(dir, "#{emoji_hash['unicode']}.png")
- hash_digest = Digest::SHA256.file(fpath).hexdigest
-
- category = emoji_hash['category']
- 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
- new_entry = {
- c: category,
- e: emoji_hash['moji'],
- d: emoji_hash['description'],
- u: Gitlab::Emoji.emoji_unicode_version(name)
- }
-
- resultant_emoji_map_new[name] = new_entry
- end
- end
-
- out = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
- File.open(out, 'w') do |handle|
- handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map))
- end
-
- out_new = File.join(Rails.root, 'public', '-', 'emojis', '1', 'emojis.json')
- File.open(out_new, 'w') do |handle|
- handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map_new))
- end
- end
-
- # This task will generate a standard and Retina sprite of all of the current
- # Gemojione Emojis, with the accompanying SCSS map.
- #
- # 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
- # occasionally, such as when new Emojis are added to Gemojione.
- task sprite: :environment do
- begin
- require 'sprite_factory'
- require 'rmagick'
- rescue LoadError
- # noop
- end
-
- check_requirements!
-
- SIZE = 20
- RETINA = SIZE * 2
-
- # Update these values to the width and height of the spritesheet when
- # new emoji are added.
- SPRITESHEET_WIDTH = 860
- SPRITESHEET_HEIGHT = 840
-
- # Set up a map to rename image files
- 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
- 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|
- FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
-
- Dir.chdir(tmpdir) do
- Dir["**/*.png"].each do |png|
- tmp_image_path = File.join(tmpdir, png)
- resize!(tmp_image_path, SIZE)
- end
- end
-
- style_path = Rails.root.join(*%w(app assets stylesheets framework emoji_sprites.scss))
-
- # Combine the resized assets into a packed sprite and re-generate the SCSS
- SpriteFactory.cssurl = "image-url('$IMAGE')"
- SpriteFactory.run!(tmpdir, {
- output_style: style_path,
- output_image: "app/assets/images/emoji.png",
- selector: '.emoji-',
- style: :scss,
- nocomments: true,
- pngcrush: true,
- layout: :packed
- })
-
- # SpriteFactory's SCSS is a bit too verbose for our purposes here, so
- # let's simplify it
- system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
- system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
- system(%Q(sed -i '' "s/ 0px/ 0/g" #{style_path}))
-
- # Append a generic rule that applies to all Emojis
- File.open(style_path, 'a') do |f|
- f.puts
- f.puts <<-CSS.strip_heredoc
- .emoji-icon {
- background-image: image-url('emoji.png');
- background-repeat: no-repeat;
- color: transparent;
- text-indent: -99em;
- height: #{SIZE}px;
- width: #{SIZE}px;
-
- @media only screen and (-webkit-min-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 (min-device-pixel-ratio: 2),
- only screen and (min-resolution: 192dpi),
- only screen and (min-resolution: 2dppx) {
- background-image: image-url('emoji@2x.png');
- background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
- }
- }
- CSS
- end
- end
-
- # Now do it again but for Retina
- Dir.mktmpdir do |tmpdir|
- # Copy the Gemojione assets to the temporary folder for resizing
- FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
-
- Dir.chdir(tmpdir) do
- Dir["**/*.png"].each do |png|
- tmp_image_path = File.join(tmpdir, png)
- resize!(tmp_image_path, RETINA)
- end
- end
-
- # Combine the resized assets into a packed sprite and re-generate the SCSS
- SpriteFactory.run!(tmpdir, {
- output_image: "app/assets/images/emoji@2x.png",
- style: false,
- nocomments: true,
- pngcrush: true,
- layout: :packed
- })
- end
- end
-
- def check_requirements!
- return if defined?(SpriteFactory) && defined?(Magick)
-
- puts <<-MSG.strip_heredoc
- This task is disabled by default and should only be run when the Gemojione
- gem is updated with new Emojis.
-
- To enable this task, *temporarily* add the following lines to Gemfile and
- re-bundle:
-
- gem 'sprite-factory'
- gem 'rmagick'
- MSG
-
- exit 1
- end
-
- def resize!(image_path, size)
- # Resize the image in-place, save it, and free the object
- image = Magick::Image.read(image_path).first
- image.resize!(size, size)
- image.write(image_path) { self.quality = 100 }
- image.destroy!
- 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
diff --git a/lib/tasks/tanuki_emoji.rake b/lib/tasks/tanuki_emoji.rake
new file mode 100644
index 00000000000..98d3920c07f
--- /dev/null
+++ b/lib/tasks/tanuki_emoji.rake
@@ -0,0 +1,260 @@
+# frozen_string_literal: true
+
+namespace :tanuki_emoji do
+ desc 'Generates Emoji aliases fixtures'
+ task aliases: :environment do
+ aliases = {}
+
+ TanukiEmoji.index.all.each do |emoji|
+ emoji.aliases.each do |emoji_alias|
+ aliases[TanukiEmoji::Character.format_name(emoji_alias)] = emoji.name
+ end
+ end
+
+ aliases_json_file = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
+ File.open(aliases_json_file, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: ''))
+ end
+ end
+
+ desc 'Generates Emoji SHA256 digests'
+ task digests: :environment do
+ require 'digest/sha2'
+
+ digest_emoji_map = {}
+ emojis_map = {}
+
+ TanukiEmoji.index.all.each do |emoji|
+ emoji_path = Gitlab::Emoji.emoji_public_absolute_path.join("#{emoji.name}.png")
+
+ digest_entry = {
+ category: emoji.category,
+ moji: emoji.codepoints,
+ description: emoji.description,
+ unicodeVersion: emoji.unicode_version,
+ digest: Digest::SHA256.file(emoji_path).hexdigest
+ }
+
+ digest_emoji_map[emoji.name] = digest_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
+ }
+
+ emojis_map[emoji.name] = emoji_entry
+ end
+
+ digests_json = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
+ File.open(digests_json, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(digest_emoji_map))
+ end
+
+ emojis_json = Gitlab::Emoji.emoji_public_absolute_path.join('emojis.json')
+ File.open(emojis_json, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(emojis_map))
+ 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} ..."
+
+ # Re-create the assets folder and copy emojis renaming them to use name instead of unicode hex
+ FileUtils.rm_rf(emoji_dir) if Dir.exist?(emoji_dir)
+ 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
+
+ puts
+ puts 'Done!'
+ end
+
+ # This task will generate a standard and Retina sprite of all of the current
+ # TanukiEmoji Emojis, with the accompanying SCSS map.
+ #
+ # 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
+ # occasionally, such as when new Emojis are added to TanukiEmoji.
+ task sprite: :environment do
+ begin
+ 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'
+ rescue LoadError
+ # noop
+ end
+
+ check_requirements!
+
+ SIZE = 20
+ RETINA = SIZE * 2
+
+ # Update these values to the width and height of the spritesheet when
+ # new emoji are added.
+ SPRITESHEET_WIDTH = 860
+ SPRITESHEET_HEIGHT = 840
+
+ emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
+
+ puts "Preparing sprites for regular size: #{SIZE}px..."
+
+ Dir.mktmpdir do |tmpdir|
+ FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
+
+ Dir.chdir(tmpdir) do
+ Dir["**/*.png"].each do |png|
+ tmp_image_path = File.join(tmpdir, png)
+ resize!(tmp_image_path, SIZE)
+ print '.'
+ end
+ end
+ puts ' Done!'
+
+ 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
+ SpriteFactory.cssurl = "image-url('$IMAGE')"
+ SpriteFactory.run!(tmpdir, {
+ output_style: style_path,
+ output_image: "app/assets/images/emoji.png",
+ selector: '.emoji-',
+ style: :scss,
+ nocomments: true,
+ pngcrush: true,
+ layout: :packed
+ })
+
+ # SpriteFactory's SCSS is a bit too verbose for our purposes here, so
+ # let's simplify it
+ system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
+ system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
+ system(%Q(sed -i '' "s/ 0px/ 0/g" #{style_path}))
+
+ # Append a generic rule that applies to all Emojis
+ File.open(style_path, 'a') do |f|
+ f.puts
+ f.puts <<-CSS.strip_heredoc
+ .emoji-icon {
+ background-image: image-url('emoji.png');
+ background-repeat: no-repeat;
+ color: transparent;
+ text-indent: -99em;
+ height: #{SIZE}px;
+ width: #{SIZE}px;
+
+ /* stylelint-disable media-feature-name-no-vendor-prefix */
+ @media only screen and (-webkit-min-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 (min-device-pixel-ratio: 2),
+ only screen and (min-resolution: 192dpi),
+ only screen and (min-resolution: 2dppx) {
+ background-image: image-url('emoji@2x.png');
+ background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
+ }
+ /* stylelint-enable media-feature-name-no-vendor-prefix */
+ }
+ CSS
+ end
+ end
+ puts 'Done!'
+
+ puts "\n"
+
+ puts "Preparing sprites for HiDPI size: #{RETINA}px..."
+
+ # Now do it again but for Retina
+ Dir.mktmpdir do |tmpdir|
+ # Copy the TanukiEmoji assets to the temporary folder for resizing
+ FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
+
+ Dir.chdir(tmpdir) do
+ Dir["**/*.png"].each do |png|
+ tmp_image_path = File.join(tmpdir, png)
+ resize!(tmp_image_path, RETINA)
+ print '.'
+ end
+ end
+ puts ' Done!'
+
+ puts "\n"
+
+ print 'Compiling HiDPI sprites...'
+
+ # Combine the resized assets into a packed sprite and re-generate the SCSS
+ SpriteFactory.run!(tmpdir, {
+ output_image: "app/assets/images/emoji@2x.png",
+ style: false,
+ nocomments: true,
+ pngcrush: true,
+ layout: :packed
+ })
+ end
+
+ puts ' Done!'
+ end
+
+ def check_requirements!
+ unless defined?(Magick)
+ puts <<~MSG
+ This task is disabled by default and should only be run when the TanukiEmoji
+ gem is updated with new Emojis.
+
+ To enable this task, *temporarily* add the following lines to Gemfile and
+ re-bundle:
+
+ gem 'rmagick', '~> 3.2'
+
+ 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
+
+ exit 1
+ end
+
+ def resize!(image_path, size)
+ # Resize the image in-place, save it, and free the object
+ image = MiniMagick::Image.open(image_path)
+ image.quality(100)
+ image.resize("#{size}x#{size}")
+ image.write(image_path)
+ end
+end
diff --git a/package.json b/package.json
index b8ad3a5e84b..d6f25c86ae8 100644
--- a/package.json
+++ b/package.json
@@ -128,7 +128,6 @@
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^7.0.3",
- "emoji-unicode-version": "^0.2.1",
"fast-mersenne-twister": "1.0.2",
"file-loader": "^6.2.0",
"fuzzaldrin-plus": "^0.6.0",
diff --git a/spec/frontend/behaviors/gl_emoji_spec.js b/spec/frontend/behaviors/gl_emoji_spec.js
index 286ed269421..d23a0a84997 100644
--- a/spec/frontend/behaviors/gl_emoji_spec.js
+++ b/spec/frontend/behaviors/gl_emoji_spec.js
@@ -56,13 +56,13 @@ describe('gl_emoji', () => {
'bomb emoji just with name attribute',
'