From 840c85c174e4f134bdce103b8226d5a2a7bcd4ac Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 19 Oct 2021 21:12:08 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- Gemfile | 6 +- Gemfile.lock | 7 +- app/assets/javascripts/emoji/index.js | 1 + app/finders/award_emojis_finder.rb | 2 +- app/helpers/emoji_helper.rb | 5 +- app/helpers/reminder_emails_helper.rb | 3 +- app/models/award_emoji.rb | 2 +- app/models/ci/build.rb | 14 +- app/models/ci/pipeline.rb | 10 + app/models/custom_emoji.rb | 2 +- app/models/user_status.rb | 2 +- app/presenters/award_emoji_presenter.rb | 10 +- app/services/award_emojis/base_service.rb | 2 +- .../ci/generate_kubeconfig_service.rb | 62 + app/validators/gitlab/emoji_name_validator.rb | 19 + config/application.rb | 2 +- config/initializers/direct_upload_support.rb | 10 +- db/fixtures/development/15_award_emoji.rb | 6 +- .../cluster_image_scanning/index.md | 4 +- .../container_scanning/index.md | 4 +- .../application_security/policies/index.md | 10 +- .../threat_monitoring/index.md | 4 +- doc/user/project/repository/vscode.md | 47 + .../emojis/emoji-unicode-version-map.json | 2377 ----------------- lib/backup/manager.rb | 4 +- lib/banzai/filter/emoji_filter.rb | 19 +- lib/gitlab/emoji.rb | 68 +- lib/gitlab/import_export/command_line_util.rb | 16 +- lib/object_storage/config.rb | 10 - lib/tasks/gemojione.rake | 245 -- lib/tasks/tanuki_emoji.rake | 260 ++ package.json | 1 - spec/frontend/behaviors/gl_emoji_spec.js | 6 +- spec/helpers/emoji_helper_spec.rb | 5 +- spec/initializers/carrierwave_patch_spec.rb | 3 - spec/lib/banzai/filter/emoji_filter_spec.rb | 6 +- .../banzai/pipeline/emoji_pipeline_spec.rb | 6 +- spec/lib/gitlab/emoji_spec.rb | 106 +- .../import_export/command_line_util_spec.rb | 44 - spec/lib/object_storage/config_spec.rb | 40 - spec/lib/object_storage/direct_upload_spec.rb | 4 - spec/models/ci/build_spec.rb | 25 + spec/models/ci/pipeline_spec.rb | 33 + spec/models/custom_emoji_spec.rb | 2 +- spec/presenters/award_emoji_presenter_spec.rb | 9 +- .../award_emojis/base_service_spec.rb | 25 + .../ci/generate_kubeconfig_service_spec.rb | 50 + spec/services/users/update_service_spec.rb | 2 +- yarn.lock | 5 - 49 files changed, 636 insertions(+), 2969 deletions(-) create mode 100644 app/services/ci/generate_kubeconfig_service.rb create mode 100644 app/validators/gitlab/emoji_name_validator.rb create mode 100644 doc/user/project/repository/vscode.md delete mode 100644 fixtures/emojis/emoji-unicode-version-map.json delete mode 100644 lib/tasks/gemojione.rake create mode 100644 lib/tasks/tanuki_emoji.rake create mode 100644 spec/services/award_emojis/base_service_spec.rb create mode 100644 spec/services/ci/generate_kubeconfig_service_spec.rb 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', '', '💣', - ':bomb:', + `:bomb:`, ], [ 'bomb emoji with name attribute and unicode version', '💣', '💣', - ':bomb:', + `:bomb:`, ], [ 'bomb emoji with sprite fallback', @@ -80,7 +80,7 @@ describe('gl_emoji', () => { 'invalid emoji', '', '', - ':grey_question:', + `:grey_question:`, ], ])('%s', (name, markup, withEmojiSupport, withoutEmojiSupport) => { it(`renders correctly with emoji support`, async () => { diff --git a/spec/helpers/emoji_helper_spec.rb b/spec/helpers/emoji_helper_spec.rb index 15e4ce03960..6f4c962c0fb 100644 --- a/spec/helpers/emoji_helper_spec.rb +++ b/spec/helpers/emoji_helper_spec.rb @@ -6,6 +6,7 @@ RSpec.describe EmojiHelper do describe '#emoji_icon' do let(:options) { {} } let(:emoji_text) { 'rocket' } + let(:unicode_version) { '6.0' } let(:aria_hidden_option) { "aria-hidden=\"true\"" } subject { helper.emoji_icon(emoji_text, options) } @@ -14,7 +15,7 @@ RSpec.describe EmojiHelper do is_expected.to include(':tm: :copyright: :registered:

') - expect(doc.css('gl-emoji')[0].text).to eq '™' - expect(doc.css('gl-emoji')[1].text).to eq '©' - expect(doc.css('gl-emoji')[2].text).to eq '®' + expect(doc.css('gl-emoji')[0].text).to eq '™️' + expect(doc.css('gl-emoji')[1].text).to eq '©️' + expect(doc.css('gl-emoji')[2].text).to eq '®️' end it 'correctly encodes the URL' do diff --git a/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb b/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb index 6de9d65f1b2..8103846d4f7 100644 --- a/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/emoji_pipeline_spec.rb @@ -3,18 +3,20 @@ require 'spec_helper' RSpec.describe Banzai::Pipeline::EmojiPipeline do + let(:emoji) { TanukiEmoji.find_by_alpha_code('100') } + def parse(text) described_class.to_html(text, {}) end it 'replaces emoji' do - expected_result = "Hello world #{Gitlab::Emoji.gl_emoji_tag('100')}" + expected_result = "Hello world #{Gitlab::Emoji.gl_emoji_tag(emoji)}" expect(parse('Hello world :100:')).to eq(expected_result) end it 'filters out HTML tags' do - expected_result = "Hello <b>world</b> #{Gitlab::Emoji.gl_emoji_tag('100')}" + expected_result = "Hello <b>world</b> #{Gitlab::Emoji.gl_emoji_tag(emoji)}" expect(parse('Hello world :100:')).to eq(expected_result) end diff --git a/spec/lib/gitlab/emoji_spec.rb b/spec/lib/gitlab/emoji_spec.rb index 8f855489c12..0db3b5f3b11 100644 --- a/spec/lib/gitlab/emoji_spec.rb +++ b/spec/lib/gitlab/emoji_spec.rb @@ -3,90 +3,6 @@ require 'spec_helper' RSpec.describe Gitlab::Emoji do - let_it_be(:emojis) { Gemojione.index.instance_variable_get(:@emoji_by_name) } - let_it_be(:emojis_by_moji) { Gemojione.index.instance_variable_get(:@emoji_by_moji) } - let_it_be(:emoji_unicode_versions_by_name) { Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json'))) } - let_it_be(:emojis_aliases) { Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json'))) } - - describe '.emojis' do - it 'returns emojis' do - current_emojis = described_class.emojis - - expect(current_emojis).to eq(emojis) - end - end - - describe '.emojis_by_moji' do - it 'return emojis by moji' do - current_emojis_by_moji = described_class.emojis_by_moji - - expect(current_emojis_by_moji).to eq(emojis_by_moji) - end - end - - describe '.emojis_unicodes' do - it 'returns emoji unicodes' do - emoji_keys = described_class.emojis_unicodes - - expect(emoji_keys).to eq(emojis_by_moji.keys) - end - end - - describe '.emojis_names' do - it 'returns emoji names' do - emoji_names = described_class.emojis_names - - expect(emoji_names).to eq(emojis.keys) - end - end - - describe '.emojis_aliases' do - it 'returns emoji aliases' do - emoji_aliases = described_class.emojis_aliases - - expect(emoji_aliases).to eq(emojis_aliases) - end - end - - describe '.emoji_filename' do - it 'returns emoji filename' do - # "100" => {"unicode"=>"1F4AF"...} - emoji_filename = described_class.emoji_filename('100') - - expect(emoji_filename).to eq(emojis['100']['unicode']) - end - end - - describe '.emoji_unicode_filename' do - it 'returns emoji unicode filename' do - emoji_unicode_filename = described_class.emoji_unicode_filename('💯') - - expect(emoji_unicode_filename).to eq(emojis_by_moji['💯']['unicode']) - end - end - - describe '.emoji_unicode_version' do - it 'returns emoji unicode version by name' do - emoji_unicode_version = described_class.emoji_unicode_version('100') - - expect(emoji_unicode_version).to eq(emoji_unicode_versions_by_name['100']) - end - end - - describe '.normalize_emoji_name' do - it 'returns same name if not found in aliases' do - emoji_name = described_class.normalize_emoji_name('random') - - expect(emoji_name).to eq('random') - end - - it 'returns name if name found in aliases' do - emoji_name = described_class.normalize_emoji_name('small_airplane') - - expect(emoji_name).to eq(emojis_aliases['small_airplane']) - end - end - describe '.emoji_image_tag' do it 'returns emoji image tag' do emoji_image = described_class.emoji_image_tag('emoji_one', 'src_url') @@ -104,29 +20,17 @@ RSpec.describe Gitlab::Emoji do end end - describe '.emoji_exists?' do - it 'returns true if the name exists' do - emoji_exists = described_class.emoji_exists?('100') - - expect(emoji_exists).to be_truthy - end - - it 'returns false if the name does not exist' do - emoji_exists = described_class.emoji_exists?('random') - - expect(emoji_exists).to be_falsey - end - end - describe '.gl_emoji_tag' do it 'returns gl emoji tag if emoji is found' do - gl_tag = described_class.gl_emoji_tag('small_airplane') + emoji = TanukiEmoji.find_by_alpha_code('small_airplane') + gl_tag = described_class.gl_emoji_tag(emoji) expect(gl_tag).to eq('🛩') end - it 'returns nil if emoji name is not found' do - gl_tag = described_class.gl_emoji_tag('random') + it 'returns nil if emoji is not found' do + emoji = TanukiEmoji.find_by_alpha_code('random') + gl_tag = described_class.gl_emoji_tag(emoji) expect(gl_tag).to be_nil end diff --git a/spec/lib/gitlab/import_export/command_line_util_spec.rb b/spec/lib/gitlab/import_export/command_line_util_spec.rb index 0d4c0545ae2..59c4e1083ae 100644 --- a/spec/lib/gitlab/import_export/command_line_util_spec.rb +++ b/spec/lib/gitlab/import_export/command_line_util_spec.rb @@ -17,10 +17,6 @@ RSpec.describe Gitlab::ImportExport::CommandLineUtil do def initialize @shared = Gitlab::ImportExport::Shared.new(nil) end - - def download(url, upload_path) - super(url, upload_path) - end end.new end @@ -105,44 +101,4 @@ RSpec.describe Gitlab::ImportExport::CommandLineUtil do end end end - - describe '#download' do - before do - stub_request(:get, loc) - .to_return( - status: 200, - body: content - ) - end - - context 'a non-localhost uri' do - let(:loc) { 'https://gitlab.com' } - let(:content) { File.open('spec/fixtures/rails_sample.tif') } - - it 'gets the contents' do - Tempfile.create("foo") do |f| - subject.download(loc, f.path) - expect(f.read).to eq(File.open('spec/fixtures/rails_sample.tif').read) - end - end - - it 'streams the contents' do - expect(Gitlab::HTTP).to receive(:get).with(loc, hash_including(stream_body: true)) - Tempfile.create("foo") do |f| - subject.download(loc, f.path) - end - end - end - - context 'a localhost uri' do - let(:loc) { 'https://localhost:8081/foo/bar' } - let(:content) { 'foo' } - - it 'throws a blocked url error' do - Tempfile.create("foo") do |f| - expect { subject.download(loc, f.path) }.to raise_error(Gitlab::HTTP::BlockedUrlError) - end - end - end - end end diff --git a/spec/lib/object_storage/config_spec.rb b/spec/lib/object_storage/config_spec.rb index 21b8a44b3d6..9a0e83bfd5e 100644 --- a/spec/lib/object_storage/config_spec.rb +++ b/spec/lib/object_storage/config_spec.rb @@ -36,46 +36,6 @@ RSpec.describe ObjectStorage::Config do subject { described_class.new(raw_config.as_json) } - describe '#load_provider' do - before do - subject.load_provider - end - - context 'with AWS' do - it 'registers AWS as a provider' do - expect(Fog.providers.keys).to include(:aws) - end - end - - context 'with Google' do - let(:credentials) do - { - provider: 'Google', - google_storage_access_key_id: 'GOOGLE_ACCESS_KEY_ID', - google_storage_secret_access_key: 'GOOGLE_SECRET_ACCESS_KEY' - } - end - - it 'registers Google as a provider' do - expect(Fog.providers.keys).to include(:google) - end - end - - context 'with Azure' do - let(:credentials) do - { - provider: 'AzureRM', - azure_storage_account_name: 'azuretest', - azure_storage_access_key: 'ABCD1234' - } - end - - it 'registers AzureRM as a provider' do - expect(Fog.providers.keys).to include(:azurerm) - end - end - end - describe '#credentials' do it { expect(subject.credentials).to eq(credentials) } end diff --git a/spec/lib/object_storage/direct_upload_spec.rb b/spec/lib/object_storage/direct_upload_spec.rb index 006f4f603b6..1629aec89f5 100644 --- a/spec/lib/object_storage/direct_upload_spec.rb +++ b/spec/lib/object_storage/direct_upload_spec.rb @@ -201,10 +201,6 @@ RSpec.describe ObjectStorage::DirectUpload do end shared_examples 'a valid AzureRM upload' do - before do - require 'fog/azurerm' - end - it_behaves_like 'a valid upload' it 'enables the Workhorse client' do diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index cbf73cdb8b2..e5ab00e1013 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -3411,6 +3411,31 @@ RSpec.describe Ci::Build do it { is_expected.to include(key: job_variable.key, value: job_variable.value, public: false, masked: false) } end + + describe 'kubernetes variables' do + let(:service) { double(execute: template) } + let(:template) { double(to_yaml: 'example-kubeconfig', valid?: template_valid) } + let(:template_valid) { true } + + before do + allow(Ci::GenerateKubeconfigService).to receive(:new).with(build).and_return(service) + end + + it { is_expected.to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) } + + context 'job is deploying to a cluster' do + let(:deployment) { create(:deployment, deployment_cluster: create(:deployment_cluster)) } + let(:build) { create(:ci_build, pipeline: pipeline, deployment: deployment) } + + it { is_expected.not_to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) } + end + + context 'generated config is invalid' do + let(:template_valid) { false } + + it { is_expected.not_to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) } + end + end end describe '#scoped_variables' do diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 98b55ccb76b..62e2639e518 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -4595,4 +4595,37 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end end + + describe '#authorized_cluster_agents' do + let(:pipeline) { create(:ci_empty_pipeline, :created) } + let(:agent) { instance_double(Clusters::Agent) } + let(:authorization) { instance_double(Clusters::Agents::GroupAuthorization, agent: agent) } + let(:finder) { double(execute: [authorization]) } + + it 'retrieves agent records from the finder and caches the result' do + expect(Clusters::AgentAuthorizationsFinder).to receive(:new).once + .with(pipeline.project) + .and_return(finder) + + expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) + expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) # cached + end + + context 'group_authorized_agents feature flag is disabled' do + let(:finder) { double(execute: [agent]) } + + before do + stub_feature_flags(group_authorized_agents: false) + end + + it 'retrieves agent records from the legacy finder and caches the result' do + expect(Clusters::DeployableAgentsFinder).to receive(:new).once + .with(pipeline.project) + .and_return(finder) + + expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) + expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) # cached + end + end + end end diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb index 4a8b671bab7..01252a58681 100644 --- a/spec/models/custom_emoji_spec.rb +++ b/spec/models/custom_emoji_spec.rb @@ -14,7 +14,7 @@ RSpec.describe CustomEmoji do end describe 'exclusion of duplicated emoji' do - let(:emoji_name) { Gitlab::Emoji.emojis_names.sample } + let(:emoji_name) { TanukiEmoji.index.all.sample.name } let(:group) { create(:group, :private) } it 'disallows emoji names of built-in emoji' do diff --git a/spec/presenters/award_emoji_presenter_spec.rb b/spec/presenters/award_emoji_presenter_spec.rb index 58ee985f165..a23196282a2 100644 --- a/spec/presenters/award_emoji_presenter_spec.rb +++ b/spec/presenters/award_emoji_presenter_spec.rb @@ -6,21 +6,22 @@ RSpec.describe AwardEmojiPresenter do let(:emoji_name) { 'thumbsup' } let(:award_emoji) { build(:award_emoji, name: emoji_name) } let(:presenter) { described_class.new(award_emoji) } + let(:emoji) { TanukiEmoji.find_by_alpha_code(emoji_name) } describe '#description' do - it { expect(presenter.description).to eq Gitlab::Emoji.emojis[emoji_name]['description'] } + it { expect(presenter.description).to eq emoji.description } end describe '#unicode' do - it { expect(presenter.unicode).to eq Gitlab::Emoji.emojis[emoji_name]['unicode'] } + it { expect(presenter.unicode).to eq emoji.hex } end describe '#unicode_version' do - it { expect(presenter.unicode_version).to eq Gitlab::Emoji.emoji_unicode_version(emoji_name) } + it { expect(presenter.unicode_version).to eq('6.0') } end describe '#emoji' do - it { expect(presenter.emoji).to eq Gitlab::Emoji.emojis[emoji_name]['moji'] } + it { expect(presenter.emoji).to eq emoji.codepoints } end describe 'when presenting an award emoji with an invalid name' do diff --git a/spec/services/award_emojis/base_service_spec.rb b/spec/services/award_emojis/base_service_spec.rb new file mode 100644 index 00000000000..e0c8fd39ad9 --- /dev/null +++ b/spec/services/award_emojis/base_service_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe AwardEmojis::BaseService do + let(:awardable) { build(:note) } + let(:current_user) { build(:user) } + + describe '.initialize' do + subject { described_class } + + it 'uses same emoji name if not an alias' do + emoji_name = 'horse' + + expect(subject.new(awardable, emoji_name, current_user).name).to eq(emoji_name) + end + + it 'uses emoji original name if its an alias' do + emoji_alias = 'small_airplane' + emoji_name = 'airplane_small' + + expect(subject.new(awardable, emoji_alias, current_user).name).to eq(emoji_name) + end + end +end diff --git a/spec/services/ci/generate_kubeconfig_service_spec.rb b/spec/services/ci/generate_kubeconfig_service_spec.rb new file mode 100644 index 00000000000..b0673d16158 --- /dev/null +++ b/spec/services/ci/generate_kubeconfig_service_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::GenerateKubeconfigService do + describe '#execute' do + let(:project) { create(:project) } + let(:build) { create(:ci_build, project: project) } + let(:agent1) { create(:cluster_agent, project: project) } + let(:agent2) { create(:cluster_agent) } + + let(:template) { instance_double(Gitlab::Kubernetes::Kubeconfig::Template) } + + subject { described_class.new(build).execute } + + before do + expect(Gitlab::Kubernetes::Kubeconfig::Template).to receive(:new).and_return(template) + expect(build.pipeline).to receive(:authorized_cluster_agents).and_return([agent1, agent2]) + end + + it 'adds a cluster, and a user and context for each available agent' do + expect(template).to receive(:add_cluster).with( + name: 'gitlab', + url: Gitlab::Kas.tunnel_url + ).once + + expect(template).to receive(:add_user).with( + name: "agent:#{agent1.id}", + token: "ci:#{agent1.id}:#{build.token}" + ) + expect(template).to receive(:add_user).with( + name: "agent:#{agent2.id}", + token: "ci:#{agent2.id}:#{build.token}" + ) + + expect(template).to receive(:add_context).with( + name: "#{project.full_path}:#{agent1.name}", + cluster: 'gitlab', + user: "agent:#{agent1.id}" + ) + expect(template).to receive(:add_context).with( + name: "#{agent2.project.full_path}:#{agent2.name}", + cluster: 'gitlab', + user: "agent:#{agent2.id}" + ) + + expect(subject).to eq(template) + end + end +end diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb index 3244db4c1fb..52c7b54ed72 100644 --- a/spec/services/users/update_service_spec.rb +++ b/spec/services/users/update_service_spec.rb @@ -53,7 +53,7 @@ RSpec.describe Users::UpdateService do result = update_user(user, status: { emoji: "Moo!" }) expect(result[:status]).to eq(:error) - expect(result[:message]).to eq("Emoji is not included in the list") + expect(result[:message]).to eq("Emoji is not a valid emoji name") end it 'updates user detail with provided attributes' do diff --git a/yarn.lock b/yarn.lock index 6746a1d71f8..7b1be03d597 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4810,11 +4810,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-unicode-version@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc" - integrity sha1-Dr82ZrVBQJeXHTSZTimfznXNuvw= - emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"