From d2846293d067cdf38d2816768e059d901a960a22 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 3 Nov 2015 16:37:39 +0100 Subject: Move visibility_level check for forked projects to Project model --- app/helpers/visibility_level_helper.rb | 3 +-- app/models/project.rb | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb index b52cd23aba2..bc594dc53c1 100644 --- a/app/helpers/visibility_level_helper.rb +++ b/app/helpers/visibility_level_helper.rb @@ -89,7 +89,6 @@ module VisibilityLevelHelper def skip_level?(form_model, level) form_model.is_a?(Project) && - form_model.forked? && - !Gitlab::VisibilityLevel.allowed_fork_levels(form_model.forked_from_project.visibility_level).include?(level) + !form_model.visibility_level_allowed?(level) end end diff --git a/app/models/project.rb b/app/models/project.rb index 74b89aad499..a4c634bdb5c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -783,4 +783,9 @@ class Project < ActiveRecord::Base service.active = true service.save end + + def visibility_level_allowed?(level) + return true unless forked? + Gitlab::VisibilityLevel.allowed_fork_levels(forked_from_project.visibility_level).include?(level) + end end -- cgit v1.2.1 From 9e1db139eb1387fa9658ed68592d93eca61efb6b Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 3 Nov 2015 17:23:19 +0100 Subject: Move level_name resolving to Gitlan::VisibilityLevel --- app/services/base_service.rb | 5 +---- lib/gitlab/visibility_level.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/services/base_service.rb b/app/services/base_service.rb index f00ec7408b6..b48ca67d4d2 100644 --- a/app/services/base_service.rb +++ b/app/services/base_service.rb @@ -39,10 +39,7 @@ class BaseService def deny_visibility_level(model, denied_visibility_level = nil) denied_visibility_level ||= model.visibility_level - level_name = 'Unknown' - Gitlab::VisibilityLevel.options.each do |name, level| - level_name = name if level == denied_visibility_level - end + level_name = Gitlab::VisibilityLevel.level_name(denied_visibility_level) model.errors.add( :visibility_level, diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb index 335dc44be19..d0ffe24f827 100644 --- a/lib/gitlab/visibility_level.rb +++ b/lib/gitlab/visibility_level.rb @@ -51,6 +51,15 @@ module Gitlab def allowed_fork_levels(origin_level) [PRIVATE, INTERNAL, PUBLIC].select{ |level| level <= origin_level } end + + def level_name(level) + level_name = 'Unknown' + options.each do |name, lvl| + level_name = name if lvl == level + end + + level_name + end end def private? -- cgit v1.2.1 From 7cb442eed4f488e378b3f20008ebe6ed3b53d31d Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 3 Nov 2015 18:23:48 +0100 Subject: Fix Project update service When project is updated and it is a fork, then visibility_level should not be less restrictive than in its parent project. --- app/models/project.rb | 2 +- app/services/projects/update_service.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index a4c634bdb5c..7f2dd37a3cc 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -786,6 +786,6 @@ class Project < ActiveRecord::Base def visibility_level_allowed?(level) return true unless forked? - Gitlab::VisibilityLevel.allowed_fork_levels(forked_from_project.visibility_level).include?(level) + Gitlab::VisibilityLevel.allowed_fork_levels(forked_from_project.visibility_level).include?(level.to_i) end end diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 69bdd045ddf..0a42f3e02aa 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -11,6 +11,15 @@ module Projects end end + unless project.visibility_level_allowed?(new_visibility) + level_name = Gitlab::VisibilityLevel.level_name(new_visibility) + project.errors.add( + :visibility_level, + "#{level_name} could not be set as visibility level of this project - parent project settings are more restrictive" + ) + return false + end + new_branch = params[:default_branch] if project.repository.exists? && new_branch && new_branch != project.default_branch -- cgit v1.2.1 From 3bc012db77e1b59986362d8de0660b97a15c9d1f Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 4 Nov 2015 22:13:40 +0100 Subject: Fix GitlabV::isibilityLevel::level_name method --- lib/gitlab/visibility_level.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb index d0ffe24f827..3160a3c7582 100644 --- a/lib/gitlab/visibility_level.rb +++ b/lib/gitlab/visibility_level.rb @@ -55,7 +55,7 @@ module Gitlab def level_name(level) level_name = 'Unknown' options.each do |name, lvl| - level_name = name if lvl == level + level_name = name if lvl == level.to_i end level_name -- cgit v1.2.1 From 89ecba5e6cec6632c2f8e3baef6604b1b8ea0d45 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 4 Nov 2015 23:40:43 +0100 Subject: Update forks visibility_level after parent project visibility_level change --- app/models/project.rb | 6 ++++- app/services/projects/update_service.rb | 48 ++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 7f2dd37a3cc..f287e59b6df 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -731,7 +731,11 @@ class Project < ActiveRecord::Base end def forks_count - ForkedProjectLink.where(forked_from_project_id: self.id).count + forks.count + end + + def forks + ForkedProjectLink.where(forked_from_project_id: self.id) end def find_label(name) diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 0a42f3e02aa..0d2665f298d 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -3,21 +3,17 @@ module Projects def execute # check that user is allowed to set specified visibility_level new_visibility = params[:visibility_level] - if new_visibility && new_visibility.to_i != project.visibility_level - unless can?(current_user, :change_visibility_level, project) && - Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) - deny_visibility_level(project, new_visibility) - return project + if new_visibility + if new_visibility.to_i != project.visibility_level + unless can?(current_user, :change_visibility_level, project) && + Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility) + deny_visibility_level(project, new_visibility) + return project + end end - end - unless project.visibility_level_allowed?(new_visibility) - level_name = Gitlab::VisibilityLevel.level_name(new_visibility) - project.errors.add( - :visibility_level, - "#{level_name} could not be set as visibility level of this project - parent project settings are more restrictive" - ) - return false + return false unless visibility_level_allowed?(new_visibility) + update_forks_visibility_level(new_visibility) end new_branch = params[:default_branch] @@ -32,5 +28,31 @@ module Projects end end end + + private + + def visibility_level_allowed?(level) + return true if project.visibility_level_allowed?(level) + + level_name = Gitlab::VisibilityLevel.level_name(level) + project.errors.add( + :visibility_level, + "#{level_name} could not be set as visibility level of this project - parent project settings are more restrictive" + ) + + false + end + + def update_forks_visibility_level(new_level) + project.forks.each do |forked_link| + forked_project = forked_link.forked_to_project + fork_level = forked_project.visibility_level + + if fork_level > new_level.to_i + forked_project.visibility_level = new_level.to_i + forked_project.save! + end + end + end end end -- cgit v1.2.1 From 6f41e3d9caa28b2a654fb775202be632673f2299 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 18 Nov 2015 22:11:15 +0100 Subject: Change forks method to has_many relation --- app/models/project.rb | 11 +++++------ app/services/projects/update_service.rb | 3 +-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index f287e59b6df..2562c441abe 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -97,9 +97,12 @@ class Project < ActiveRecord::Base has_one :gitlab_issue_tracker_service, dependent: :destroy has_one :external_wiki_service, dependent: :destroy - has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" + has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" + has_one :forked_from_project, through: :forked_project_link + + has_many :forked_project_links, foreign_key: "forked_from_project_id" + has_many :forks, through: :forked_project_links, source: :forked_to_project - has_one :forked_from_project, through: :forked_project_link # Merge Requests for target project should be removed with it has_many :merge_requests, dependent: :destroy, foreign_key: 'target_project_id' # Merge requests from source project should be kept when source project was removed @@ -734,10 +737,6 @@ class Project < ActiveRecord::Base forks.count end - def forks - ForkedProjectLink.where(forked_from_project_id: self.id) - end - def find_label(name) labels.find_by(name: name) end diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 0d2665f298d..67e3429c0bd 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -44,8 +44,7 @@ module Projects end def update_forks_visibility_level(new_level) - project.forks.each do |forked_link| - forked_project = forked_link.forked_to_project + project.forks.each do |forked_project| fork_level = forked_project.visibility_level if fork_level > new_level.to_i -- cgit v1.2.1 From 945e4293cb8f745b2e1a1aebdcf4df3eeba338cc Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 19 Nov 2015 23:40:29 +0100 Subject: Prevent unnecessary forks iteration at parent update --- app/services/projects/update_service.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index 67e3429c0bd..cd7a8b18218 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -13,7 +13,7 @@ module Projects end return false unless visibility_level_allowed?(new_visibility) - update_forks_visibility_level(new_visibility) + update_forks_visibility_level(new_visibility.to_i) end new_branch = params[:default_branch] @@ -44,11 +44,13 @@ module Projects end def update_forks_visibility_level(new_level) + return unless new_level < project.visibility_level + project.forks.each do |forked_project| fork_level = forked_project.visibility_level - if fork_level > new_level.to_i - forked_project.visibility_level = new_level.to_i + if fork_level > new_level + forked_project.visibility_level = new_level forked_project.save! end end -- cgit v1.2.1 From 1144b70ab624ee1c1e7f2de0c92de021a7b5ea8e Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Fri, 20 Nov 2015 00:13:56 +0100 Subject: Change update_forks_visibility_level into after_update hook in Project model --- app/models/project.rb | 13 +++++++++++++ app/services/projects/update_service.rb | 14 -------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 2562c441abe..b8495c6cd4f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -61,6 +61,19 @@ class Project < ActiveRecord::Base update_column(:last_activity_at, self.created_at) end + # update visibility_levet of forks + after_update :update_forks_visibility_level + def update_forks_visibility_level + return unless visibility_level < visibility_level_was + + forks.each do |forked_project| + if forked_project.visibility_level > visibility_level + forked_project.visibility_level = visibility_level + forked_project.save! + end + end + end + ActsAsTaggableOn.strict_case_match = true acts_as_taggable_on :tags diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb index cd7a8b18218..895e089bea3 100644 --- a/app/services/projects/update_service.rb +++ b/app/services/projects/update_service.rb @@ -13,7 +13,6 @@ module Projects end return false unless visibility_level_allowed?(new_visibility) - update_forks_visibility_level(new_visibility.to_i) end new_branch = params[:default_branch] @@ -42,18 +41,5 @@ module Projects false end - - def update_forks_visibility_level(new_level) - return unless new_level < project.visibility_level - - project.forks.each do |forked_project| - fork_level = forked_project.visibility_level - - if fork_level > new_level - forked_project.visibility_level = new_level - forked_project.save! - end - end - end end end -- cgit v1.2.1 From 03a40a7ee1262d5b68e5f7aba26077dc3bef6b33 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Wed, 16 Dec 2015 11:51:37 +0800 Subject: Avoid allocations in Ability class. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It won't change anything after they are first invoke, so add method cache to avoid allocations and avoid GC. Benchmarks: ``` Calculating ------------------------------------- project_guest_rules without method cache 79.352k i/100ms project_guest_rules with method cache 93.634k i/100ms ------------------------------------------------- project_guest_rules without method cache 2.865M (±32.5%) i/s - 11.982M project_guest_rules with method cache 4.419M (± 7.4%) i/s - 22.004M Comparison: project_guest_rules with method cache: 4418908.0 i/s project_guest_rules without method cache: 2864514.0 i/s - 1.54x slower Calculating ------------------------------------- project_report_rules without method cache 53.126k i/100ms project_report_rules with method cache 97.473k i/100ms ------------------------------------------------- project_report_rules without method cache 1.093M (±36.5%) i/s - 4.675M project_report_rules with method cache 4.420M (± 7.2%) i/s - 22.029M Comparison: project_report_rules with method cache: 4420054.3 i/s project_report_rules without method cache: 1092509.6 i/s - 4.05x slower ``` https://gist.github.com/huacnlee/b04788ae6df42fe769e4 --- app/models/ability.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index cd5ae0fb0fd..1b3ee757040 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -132,14 +132,14 @@ class Ability end def public_project_rules - project_guest_rules + [ + @public_project_rules ||= project_guest_rules + [ :download_code, :fork_project ] end def project_guest_rules - [ + @project_guest_rules ||= [ :read_project, :read_wiki, :read_issue, @@ -157,7 +157,7 @@ class Ability end def project_report_rules - project_guest_rules + [ + @project_report_rules ||= project_guest_rules + [ :create_commit_status, :read_commit_statuses, :download_code, @@ -170,7 +170,7 @@ class Ability end def project_dev_rules - project_report_rules + [ + @project_dev_rules ||= project_report_rules + [ :admin_merge_request, :create_merge_request, :create_wiki, @@ -181,7 +181,7 @@ class Ability end def project_archived_rules - [ + @project_archived_rules ||= [ :create_merge_request, :push_code, :push_code_to_protected_branches, @@ -191,7 +191,7 @@ class Ability end def project_master_rules - project_dev_rules + [ + @project_master_rules ||= project_dev_rules + [ :push_code_to_protected_branches, :update_project_snippet, :update_merge_request, @@ -206,7 +206,7 @@ class Ability end def project_admin_rules - project_master_rules + [ + @project_admin_rules ||= project_master_rules + [ :change_namespace, :change_visibility_level, :rename_project, @@ -332,7 +332,7 @@ class Ability end if snippet.public? || snippet.internal? - rules << :read_personal_snippet + rules << :read_personal_snippet end rules -- cgit v1.2.1 From 9c266d49354e9f7f86c76b00fbe800912f475153 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 16 Dec 2015 16:29:31 -0200 Subject: Add more descriptive error message when create branch with invalid name --- app/services/create_branch_service.rb | 2 +- app/views/projects/branches/new.html.haml | 1 + features/steps/project/commits/branches.rb | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb index de18f3bc556..6a77f51628e 100644 --- a/app/services/create_branch_service.rb +++ b/app/services/create_branch_service.rb @@ -4,7 +4,7 @@ class CreateBranchService < BaseService def execute(branch_name, ref) valid_branch = Gitlab::GitRefValidator.validate(branch_name) if valid_branch == false - return error('Branch name invalid') + return error("Branch name can't contains space, '~', '^', ':', '?', '*', '[', '\', '..', '@{', and consecutive slashes, start with '/' or '.' or end in '/' or '.' or '.lock'") end repository = project.repository diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index 31943a2407a..4e94f2a5ea2 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -14,6 +14,7 @@ = label_tag :branch_name, nil, class: 'control-label' .col-sm-10 = text_field_tag :branch_name, params[:branch_name], required: true, tabindex: 1, autofocus: true, class: 'form-control' + .help-block Can't contains space, '~', '^', ':', '?', '*', '[', '\', '..', '@{', and consecutive slashes, start with '/' or '.' or end in '/' or '.' or '.lock' .form-group = label_tag :ref, 'Create from', class: 'control-label' .col-sm-10 diff --git a/features/steps/project/commits/branches.rb b/features/steps/project/commits/branches.rb index 338f5e8d3ee..e9312e87637 100644 --- a/features/steps/project/commits/branches.rb +++ b/features/steps/project/commits/branches.rb @@ -61,7 +61,7 @@ class Spinach::Features::ProjectCommitsBranches < Spinach::FeatureSteps end step 'I should see new an error that branch is invalid' do - expect(page).to have_content 'Branch name invalid' + expect(page).to have_content "Branch name can't contains space, '~', '^', ':', '?', '*', '[', '\', '..', '@{', and consecutive slashes, start with '/' or '.' or end in '/' or '.' or '.lock'" end step 'I should see new an error that ref is invalid' do -- cgit v1.2.1 From c91cf1f66b3ed4329b313b7b75fca816fc5c6076 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 16 Dec 2015 16:48:14 -0200 Subject: Remove the hint on the branch name input --- app/views/projects/branches/new.html.haml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index 4e94f2a5ea2..31943a2407a 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -14,7 +14,6 @@ = label_tag :branch_name, nil, class: 'control-label' .col-sm-10 = text_field_tag :branch_name, params[:branch_name], required: true, tabindex: 1, autofocus: true, class: 'form-control' - .help-block Can't contains space, '~', '^', ':', '?', '*', '[', '\', '..', '@{', and consecutive slashes, start with '/' or '.' or end in '/' or '.' or '.lock' .form-group = label_tag :ref, 'Create from', class: 'control-label' .col-sm-10 -- cgit v1.2.1 From 1757e6ef65a1cedbfe5d5b5da894d6d0d3d5ef16 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 17 Dec 2015 16:59:15 -0200 Subject: Add JS validation for invalid characters in branch name More info about valid ref names: https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.ht ml --- app/assets/javascripts/new_branch_form.js.coffee | 73 ++++++++++++++++++++++++ app/services/create_branch_service.rb | 2 +- app/views/projects/branches/new.html.haml | 10 ++-- features/project/commits/branches.feature | 1 + features/steps/project/commits/branches.rb | 3 +- 5 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 app/assets/javascripts/new_branch_form.js.coffee diff --git a/app/assets/javascripts/new_branch_form.js.coffee b/app/assets/javascripts/new_branch_form.js.coffee new file mode 100644 index 00000000000..af531b3bf9f --- /dev/null +++ b/app/assets/javascripts/new_branch_form.js.coffee @@ -0,0 +1,73 @@ +class @NewBranchForm + constructor: (form, availableRefs) -> + @branchNameError = form.find('.js-branch-name-error') + @name = form.find('.js-branch-name') + @ref = form.find('#ref') + + @setupAvailableRefs(availableRefs) + @setupRestrictions() + @addBinding() + @init() + + addBinding: -> + @name.on 'blur', @validate + + init: -> + @name.trigger 'blur'if @name.val().length > 0 + + setupAvailableRefs: (availableRefs) -> + @ref.autocomplete { + source: availableRefs, + minLength: 1 + } + + setupRestrictions: -> + startsWith = { + pattern: /^(\/|\.)/g, + prefix: "can't start with ", + conjunction: "or" + } + + endsWith = { + pattern: /(\/|\.|\.lock)$/g, + prefix: "can't end in ", + conjunction: "or" + } + + characters = { + pattern: /(\s|~|\^|:|\?|\*|\[|\\|\.\.|@\{|\/{2,}){1}/g + prefix: "can't contains ", + conjunction: ", " + } + + @restrictions = [startsWith, characters, endsWith] + + validate: => + @branchNameError.empty() + + unique = (values, value) -> + values.push(value) unless value in values + values + + formatter = (values, restriction) -> + formatted = values.map (value) -> + switch + when /\s/.test value then 'spaces' + when /\/{2,}/g.test value then 'consecutive slashes' + else "'#{value}'" + + "#{restriction.prefix} #{formatted.join(restriction.conjunction)}" + + validator = (errors, restriction) => + matched = @name.val().match(restriction.pattern) + + if matched + errors.concat formatter(matched.reduce(unique, []), restriction) + else + errors + + errors = @restrictions.reduce validator, [] + + if errors.length > 0 + errorMessage = $("").text(errors.join(', ')) + @branchNameError.append(errorMessage) diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb index 6a77f51628e..a6844985c4e 100644 --- a/app/services/create_branch_service.rb +++ b/app/services/create_branch_service.rb @@ -4,7 +4,7 @@ class CreateBranchService < BaseService def execute(branch_name, ref) valid_branch = Gitlab::GitRefValidator.validate(branch_name) if valid_branch == false - return error("Branch name can't contains space, '~', '^', ':', '?', '*', '[', '\', '..', '@{', and consecutive slashes, start with '/' or '.' or end in '/' or '.' or '.lock'") + return error('Branch name is invalid') end repository = project.repository diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index 31943a2407a..c659af6338c 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -9,11 +9,12 @@ New Branch %hr -= form_tag namespace_project_branches_path, method: :post, id: "new-branch-form", class: "form-horizontal js-requires-input" do += form_tag namespace_project_branches_path, method: :post, id: "new-branch-form", class: "form-horizontal js-create-branch-form js-requires-input" do .form-group = label_tag :branch_name, nil, class: 'control-label' .col-sm-10 - = text_field_tag :branch_name, params[:branch_name], required: true, tabindex: 1, autofocus: true, class: 'form-control' + = text_field_tag :branch_name, params[:branch_name], required: true, tabindex: 1, autofocus: true, class: 'form-control js-branch-name' + .help-block.text-danger.js-branch-name-error .form-group = label_tag :ref, 'Create from', class: 'control-label' .col-sm-10 @@ -26,7 +27,4 @@ :javascript var availableRefs = #{@project.repository.ref_names.to_json}; - $("#ref").autocomplete({ - source: availableRefs, - minLength: 1 - }); + new NewBranchForm($('.js-create-branch-form'), availableRefs) diff --git a/features/project/commits/branches.feature b/features/project/commits/branches.feature index 5103ca12947..2c17d32154a 100644 --- a/features/project/commits/branches.feature +++ b/features/project/commits/branches.feature @@ -25,6 +25,7 @@ Feature: Project Commits Branches And I click branch 'improve/awesome' delete link Then I should not see branch 'improve/awesome' + @javascript Scenario: I create a branch with invalid name Given I visit project branches page And I click new branch link diff --git a/features/steps/project/commits/branches.rb b/features/steps/project/commits/branches.rb index e9312e87637..109d031d446 100644 --- a/features/steps/project/commits/branches.rb +++ b/features/steps/project/commits/branches.rb @@ -61,7 +61,8 @@ class Spinach::Features::ProjectCommitsBranches < Spinach::FeatureSteps end step 'I should see new an error that branch is invalid' do - expect(page).to have_content "Branch name can't contains space, '~', '^', ':', '?', '*', '[', '\', '..', '@{', and consecutive slashes, start with '/' or '.' or end in '/' or '.' or '.lock'" + expect(page).to have_content 'Branch name is invalid' + expect(page).to have_content "can't contains spaces" end step 'I should see new an error that ref is invalid' do -- cgit v1.2.1 From e26d1b47575646f15f1ab3a91878bbb695d3bc65 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 17 Dec 2015 19:44:28 -0200 Subject: Remove extra spaces in the error messages --- app/assets/javascripts/new_branch_form.js.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/new_branch_form.js.coffee b/app/assets/javascripts/new_branch_form.js.coffee index af531b3bf9f..6b01bb0ce21 100644 --- a/app/assets/javascripts/new_branch_form.js.coffee +++ b/app/assets/javascripts/new_branch_form.js.coffee @@ -24,19 +24,19 @@ class @NewBranchForm setupRestrictions: -> startsWith = { pattern: /^(\/|\.)/g, - prefix: "can't start with ", + prefix: "can't start with", conjunction: "or" } endsWith = { pattern: /(\/|\.|\.lock)$/g, - prefix: "can't end in ", + prefix: "can't end in", conjunction: "or" } characters = { pattern: /(\s|~|\^|:|\?|\*|\[|\\|\.\.|@\{|\/{2,}){1}/g - prefix: "can't contains ", + prefix: "can't contains", conjunction: ", " } -- cgit v1.2.1 From 05737f6c85619863f1ed15a8f6a6d0f1d72c1f22 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 17 Dec 2015 19:45:11 -0200 Subject: Add restriction for single characters in branch name --- app/assets/javascripts/new_branch_form.js.coffee | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/new_branch_form.js.coffee b/app/assets/javascripts/new_branch_form.js.coffee index 6b01bb0ce21..23a5b333b8a 100644 --- a/app/assets/javascripts/new_branch_form.js.coffee +++ b/app/assets/javascripts/new_branch_form.js.coffee @@ -34,13 +34,19 @@ class @NewBranchForm conjunction: "or" } - characters = { + invalid = { pattern: /(\s|~|\^|:|\?|\*|\[|\\|\.\.|@\{|\/{2,}){1}/g prefix: "can't contains", conjunction: ", " } - @restrictions = [startsWith, characters, endsWith] + single = { + pattern: /^@+$/g + prefix: "can't be", + conjunction: "or" + } + + @restrictions = [startsWith, invalid, endsWith, single] validate: => @branchNameError.empty() -- cgit v1.2.1 From 4163eb56d91f75f62d562034140b0b4debecb315 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 17 Dec 2015 19:45:43 -0200 Subject: Add specs for JS validation for invalid characters in branch name --- spec/javascripts/fixtures/new_branch.html.haml | 4 + spec/javascripts/new_branch_spec.js.coffee | 155 +++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 spec/javascripts/fixtures/new_branch.html.haml create mode 100644 spec/javascripts/new_branch_spec.js.coffee diff --git a/spec/javascripts/fixtures/new_branch.html.haml b/spec/javascripts/fixtures/new_branch.html.haml new file mode 100644 index 00000000000..f06629e5ecc --- /dev/null +++ b/spec/javascripts/fixtures/new_branch.html.haml @@ -0,0 +1,4 @@ +%form.js-create-branch-form + %input.js-branch-name + .js-branch-name-error + %input{id: "ref"} diff --git a/spec/javascripts/new_branch_spec.js.coffee b/spec/javascripts/new_branch_spec.js.coffee new file mode 100644 index 00000000000..1cba9546655 --- /dev/null +++ b/spec/javascripts/new_branch_spec.js.coffee @@ -0,0 +1,155 @@ +#= require jquery.ui.all +#= require new_branch_form + +describe 'Branch', -> + describe 'create a new branch', -> + fixture.preload('new_branch.html') + + beforeEach -> + fixture.load('new_branch.html') + $('form').on 'submit', (e) -> e.preventDefault() + + @form = new NewBranchForm($('.js-create-branch-form'), []) + @name = $('.js-branch-name') + + it "can't start with a dot", -> + @name.val('.foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't start with '.'") + + it "can't start with a slash", -> + @name.val('/foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't start with '/'") + + it "can't have two consecutive dots", -> + @name.val('foo..bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '..'") + + it "can't have spaces anywhere", -> + @name.val(' foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains spaces") + @name.val('foo bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains spaces") + @name.val('foo ').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains spaces") + + it "can't have ~ anywhere", -> + @name.val('~foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + @name.val('foo~bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + @name.val('foo~').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + + it "can't have tilde anwhere", -> + @name.val('~foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + @name.val('foo~bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + @name.val('foo~').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + + it "can't have caret anywhere", -> + @name.val('^foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '^'") + @name.val('foo^bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '^'") + @name.val('foo^').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '^'") + + it "can't have : anywhere", -> + @name.val(':foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains ':'") + @name.val('foo:bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains ':'") + @name.val(':foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains ':'") + + it "can't have question mark anywhere", -> + @name.val('?foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '?'") + @name.val('foo?bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '?'") + @name.val('foo?').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '?'") + + it "can't have asterisk anywhere", -> + @name.val('*foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '*'") + @name.val('foo*bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '*'") + @name.val('foo*').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '*'") + + it "can't have open bracket anywhere", -> + @name.val('[foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '['") + @name.val('foo[bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '['") + @name.val('foo[').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '['") + + it "can't have a backslash anywhere", -> + @name.val('\\foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '\\'") + @name.val('foo\\bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '\\'") + @name.val('foo\\').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '\\'") + + it "can't contain a sequence @{ anywhere", -> + @name.val('@{foo').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '@{'") + @name.val('foo@{bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '@{'") + @name.val('foo@{').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '@{'") + + it "can't have consecutive slashes", -> + @name.val('foo//bar').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains consecutive slashes") + + it "can't end with a slash", -> + @name.val('foo/').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't end in '/'") + + it "can't end with a dot", -> + @name.val('foo.').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't end in '.'") + + it "can't end with .lock", -> + @name.val('foo.lock').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't end in '.lock'") + + it "can't be the single character @", -> + @name.val('@').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't be '@'") + + it "concatenates all error messages", -> + @name.val('/foo bar?~.').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't start with '/', can't contains spaces, '?', '~', can't end in '.'") + + it "doesn't duplicate error messages", -> + @name.val('?foo?bar?zoo?').trigger('blur') + expect($('.js-branch-name-error span').text()).toEqual("can't contains '?'") + + it "removes the error message when is a valid name", -> + @name.val('foo?bar').trigger('blur') + expect($('.js-branch-name-error span').length).toEqual(1) + @name.val('foobar').trigger('blur') + expect($('.js-branch-name-error span').length).toEqual(0) + + it "can have dashes anywhere", -> + @name.val('-foo-bar-zoo-').trigger('blur') + expect($('.js-branch-name-error span').length).toEqual(0) + + it "can have underscores anywhere", -> + @name.val('_foo_bar_zoo_').trigger('blur') + expect($('.js-branch-name-error span').length).toEqual(0) + + it "can have numbers anywhere", -> + @name.val('1foo2bar3zoo4').trigger('blur') + expect($('.js-branch-name-error span').length).toEqual(0) + + it "can be only letters", -> + @name.val('foo').trigger('blur') + expect($('.js-branch-name-error span').length).toEqual(0) -- cgit v1.2.1 From d9c82d679fd622aead99aeb90369361a05e02a36 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 18 Dec 2015 10:03:34 +0100 Subject: Automatically fork a project when not allowed to edit a file. --- .../javascripts/blob/blob_file_dropzone.js.coffee | 2 +- app/assets/javascripts/new_commit_form.js.coffee | 2 +- app/controllers/concerns/creates_commit.rb | 103 +++++++++++++++++++++ .../concerns/creates_merge_request_for_commit.rb | 28 ------ app/controllers/projects/blob_controller.rb | 94 ++++--------------- app/controllers/projects/forks_controller.rb | 19 +++- app/controllers/projects/imports_controller.rb | 24 +++-- app/controllers/projects/tree_controller.rb | 38 ++------ app/helpers/blob_helper.rb | 102 +++++++++++++++----- app/helpers/tree_helper.rb | 41 ++++++-- app/models/repository.rb | 59 ++++++------ app/services/create_branch_service.rb | 17 +++- app/services/files/base_service.rb | 26 +++--- app/services/files/create_service.rb | 2 +- app/views/projects/_commit_button.html.haml | 4 + app/views/projects/blob/_actions.html.haml | 13 +-- app/views/projects/blob/_new_dir.html.haml | 4 + app/views/projects/blob/_upload.html.haml | 5 + app/views/projects/blob/edit.html.haml | 2 +- app/views/projects/blob/show.html.haml | 2 +- app/views/projects/buttons/_dropdown.html.haml | 20 +++- app/views/projects/diffs/_file.html.haml | 3 +- app/views/projects/forks/new.html.haml | 1 - app/views/projects/tree/_tree_content.html.haml | 2 +- app/views/projects/tree/_tree_header.html.haml | 76 ++++++++++----- app/views/shared/_new_commit_form.html.haml | 28 +++--- features/steps/project/source/browse_files.rb | 2 +- lib/api/files.rb | 2 +- spec/controllers/projects/tree_controller_spec.rb | 4 +- 29 files changed, 452 insertions(+), 273 deletions(-) create mode 100644 app/controllers/concerns/creates_commit.rb delete mode 100644 app/controllers/concerns/creates_merge_request_for_commit.rb diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee index 195f8b11e5d..9df932817f6 100644 --- a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee +++ b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee @@ -35,7 +35,7 @@ class @BlobFileDropzone return this.on 'sending', (file, xhr, formData) -> - formData.append('new_branch', form.find('.js-new-branch').val()) + formData.append('target_branch', form.find('.js-target-branch').val()) formData.append('create_merge_request', form.find('.js-create-merge-request').val()) formData.append('commit_message', form.find('.js-commit-message').val()) return diff --git a/app/assets/javascripts/new_commit_form.js.coffee b/app/assets/javascripts/new_commit_form.js.coffee index 3c7b776155f..03f0f51acfa 100644 --- a/app/assets/javascripts/new_commit_form.js.coffee +++ b/app/assets/javascripts/new_commit_form.js.coffee @@ -1,6 +1,6 @@ class @NewCommitForm constructor: (form) -> - @newBranch = form.find('.js-new-branch') + @newBranch = form.find('.js-target-branch') @originalBranch = form.find('.js-original-branch') @createMergeRequest = form.find('.js-create-merge-request') @createMergeRequestContainer = form.find('.js-create-merge-request-container') diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb new file mode 100644 index 00000000000..62127a09081 --- /dev/null +++ b/app/controllers/concerns/creates_commit.rb @@ -0,0 +1,103 @@ +module CreatesCommit + extend ActiveSupport::Concern + + def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil) + set_commit_variables + + commit_params = @commit_params.merge( + source_project: @project, + source_branch: @ref, + target_branch: @target_branch + ) + + result = service.new(@tree_edit_project, current_user, commit_params).execute + + if result[:status] == :success + flash[:notice] = success_notice || "Your changes have been successfully committed." + + if create_merge_request? + success_path = new_merge_request_path + target = different_project? ? "project" : "branch" + flash[:notice] << " You can now submit a merge request to get this change into the original #{target}." + end + + respond_to do |format| + format.html { redirect_to success_path } + format.json { render json: { message: "success", filePath: success_path } } + end + else + flash[:alert] = result[:message] + respond_to do |format| + format.html do + if failure_view + render failure_view + else + redirect_to failure_path + end + end + format.json { render json: { message: "failed", filePath: failure_path } } + end + end + end + + def authorize_edit_tree! + return if can?(current_user, :push_code, project) + return if current_user && current_user.already_forked?(project) + + access_denied! + end + + private + + def new_merge_request_path + new_namespace_project_merge_request_path( + @mr_source_project.namespace, + @mr_source_project, + merge_request: { + source_project_id: @mr_source_project.id, + target_project_id: @mr_target_project.id, + source_branch: @mr_source_branch, + target_branch: @mr_target_branch + } + ) + end + + def different_project? + @mr_source_project != @mr_target_project + end + + def different_branch? + @mr_source_branch != @mr_target_branch || different_project? + end + + def create_merge_request? + params[:create_merge_request].present? && different_branch? + end + + def set_commit_variables + @mr_source_branch = @target_branch + + if can?(current_user, :push_code, @project) + # Edit file in this project + @tree_edit_project = @project + @mr_source_project = @project + + if @project.forked? + # Merge request from this project to fork origin + @mr_target_project = @project.forked_from_project + @mr_target_branch = @mr_target_project.repository.root_ref + else + # Merge request to this project + @mr_target_project = @project + @mr_target_branch = @ref + end + else + # Edit file in fork + @tree_edit_project = current_user.fork_of(@project) + # Merge request from fork to this project + @mr_source_project = @tree_edit_project + @mr_target_project = @project + @mr_target_branch = @mr_target_project.repository.root_ref + end + end +end diff --git a/app/controllers/concerns/creates_merge_request_for_commit.rb b/app/controllers/concerns/creates_merge_request_for_commit.rb deleted file mode 100644 index c7527822158..00000000000 --- a/app/controllers/concerns/creates_merge_request_for_commit.rb +++ /dev/null @@ -1,28 +0,0 @@ -module CreatesMergeRequestForCommit - extend ActiveSupport::Concern - - def new_merge_request_path - if @project.forked? - target_project = @project.forked_from_project || @project - target_branch = target_project.repository.root_ref - else - target_project = @project - target_branch = @ref - end - - new_namespace_project_merge_request_path( - @project.namespace, - @project, - merge_request: { - source_project_id: @project.id, - target_project_id: target_project.id, - source_branch: @new_branch, - target_branch: target_branch - } - ) - end - - def create_merge_request? - params[:create_merge_request] && @new_branch != @ref - end -end diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 62163682936..c56a3497bb2 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -1,7 +1,7 @@ # Controller for viewing a file's blame class Projects::BlobController < Projects::ApplicationController include ExtractsPath - include CreatesMergeRequestForCommit + include CreatesCommit include ActionView::Helpers::SanitizeHelper # Raised when given an invalid file path @@ -9,21 +9,21 @@ class Projects::BlobController < Projects::ApplicationController before_action :require_non_empty_project, except: [:new, :create] before_action :authorize_download_code! - before_action :authorize_push_code!, only: [:destroy, :create] + before_action :authorize_edit_tree!, only: [:new, :create, :edit, :update, :destroy] before_action :assign_blob_vars before_action :commit, except: [:new, :create] before_action :blob, except: [:new, :create] before_action :from_merge_request, only: [:edit, :update] before_action :require_branch_head, only: [:edit, :update] before_action :editor_variables, except: [:show, :preview, :diff] - before_action :after_edit_path, only: [:edit, :update] def new commit unless @repository.empty? end def create - create_commit(Files::CreateService, success_path: after_create_path, + create_commit(Files::CreateService, success_notice: "The file has been successfully created.", + success_path: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)), failure_view: :new, failure_path: namespace_project_new_blob_path(@project.namespace, @project, @ref)) end @@ -36,6 +36,14 @@ class Projects::BlobController < Projects::ApplicationController end def update + after_edit_path = + if from_merge_request && @target_branch == @ref + diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) + + "#file-path-#{hexdigest(@path)}" + else + namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @path)) + end + create_commit(Files::UpdateService, success_path: after_edit_path, failure_view: :edit, failure_path: namespace_project_blob_path(@project.namespace, @project, @id)) @@ -50,15 +58,10 @@ class Projects::BlobController < Projects::ApplicationController end def destroy - result = Files::DeleteService.new(@project, current_user, @commit_params).execute - - if result[:status] == :success - flash[:notice] = "Your changes have been successfully committed" - redirect_to after_destroy_path - else - flash[:alert] = result[:message] - render :show - end + create_commit(Files::DeleteService, success_notice: "The file has been successfully deleted.", + success_path: namespace_project_tree_path(@project.namespace, @project, @target_branch), + failure_view: :show, + failure_path: namespace_project_blob_path(@project.namespace, @project, @id)) end def diff @@ -108,74 +111,13 @@ class Projects::BlobController < Projects::ApplicationController render_404 end - def create_commit(service, success_path:, failure_view:, failure_path:) - result = service.new(@project, current_user, @commit_params).execute - - if result[:status] == :success - flash[:notice] = "Your changes have been successfully committed" - respond_to do |format| - format.html { redirect_to success_path } - format.json { render json: { message: "success", filePath: success_path } } - end - else - flash[:alert] = result[:message] - respond_to do |format| - format.html { render failure_view } - format.json { render json: { message: "failed", filePath: failure_path } } - end - end - end - - def after_create_path - @after_create_path ||= - if create_merge_request? - new_merge_request_path - else - namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @file_path)) - end - end - - def after_edit_path - @after_edit_path ||= - if create_merge_request? - new_merge_request_path - elsif from_merge_request && @new_branch == @ref - diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) + - "#file-path-#{hexdigest(@path)}" - else - namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @path)) - end - end - - def after_destroy_path - @after_destroy_path ||= - if create_merge_request? - new_merge_request_path - else - namespace_project_tree_path(@project.namespace, @project, @new_branch) - end - end - def from_merge_request # If blob edit was initiated from merge request page @from_merge_request ||= MergeRequest.find_by(id: params[:from_merge_request_id]) end - def sanitized_new_branch_name - sanitize(strip_tags(params[:new_branch])) - end - def editor_variables - @current_branch = @ref - - @new_branch = - if params[:new_branch].present? - sanitized_new_branch_name - elsif ::Gitlab::GitAccess.new(current_user, @project).can_push_to_branch?(@ref) - @ref - else - @repository.next_patch_branch - end + @target_branch = params[:target_branch] @file_path = if action_name.to_s == 'create' @@ -194,8 +136,6 @@ class Projects::BlobController < Projects::ApplicationController @commit_params = { file_path: @file_path, - current_branch: @current_branch, - target_branch: @new_branch, commit_message: params[:commit_message], file_content: params[:content], file_content_encoding: params[:encoding] diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 8a785076bb7..51181b8042e 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -13,16 +13,25 @@ class Projects::ForksController < Projects::ApplicationController @forked_project = ::Projects::ForkService.new(project, current_user, namespace: namespace).execute if @forked_project.saved? && @forked_project.forked? + continue_params[:notice] ||= "The project was successfully forked." + if @forked_project.import_in_progress? - redirect_to namespace_project_import_path(@forked_project.namespace, @forked_project) + redirect_to namespace_project_import_path(@forked_project.namespace, @forked_project, continue: continue_params) else - redirect_to( - namespace_project_path(@forked_project.namespace, @forked_project), - notice: 'Project was successfully forked.' - ) + if continue_params + redirect_to continue_params[:to], notice: continue_params[:notice] + else + redirect_to namespace_project_path(@forked_project.namespace, @forked_project) + end end else render :error end end + + private + + def continue_params + params[:continue].permit(:to, :notice, :notice_now) + end end diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index fb8788f0818..e9c9edd3a3c 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -1,7 +1,7 @@ class Projects::ImportsController < Projects::ApplicationController # Authorize before_action :authorize_admin_project! - before_action :require_no_repo + before_action :require_no_repo, except: :show before_action :redirect_if_progress, except: :show def new @@ -24,21 +24,31 @@ class Projects::ImportsController < Projects::ApplicationController end def show - unless @project.import_in_progress? - if @project.import_finished? - redirect_to(project_path(@project)) and return + if @project.repository_exists? || @project.import_finished? + if continue_params + redirect_to continue_params[:to], notice: continue_params[:notice] else - redirect_to(new_namespace_project_import_path(@project.namespace, - @project)) and return + redirect_to project_path(@project) end + elsif @project.import_failed? + redirect_to new_namespace_project_import_path(@project.namespace, @project) + else + if continue_params && continue_params[:notice_now] + flash.now[:notice] = continue_params[:notice_now] + end + # Render end end private + def continue_params + @continue_params ||= params[:continue].permit(:to, :notice, :notice_now) + end + def require_no_repo if @project.repository_exists? && !@project.import_in_progress? - redirect_to(namespace_project_path(@project.namespace, @project)) and return + redirect_to(namespace_project_path(@project.namespace, @project)) end end diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 8f272ad1281..4f78bde2d2d 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -1,14 +1,14 @@ # Controller for viewing a repository's file structure class Projects::TreeController < Projects::ApplicationController include ExtractsPath - include CreatesMergeRequestForCommit + include CreatesCommit include ActionView::Helpers::SanitizeHelper before_action :require_non_empty_project, except: [:new, :create] before_action :assign_ref_vars before_action :assign_dir_vars, only: [:create_dir] before_action :authorize_download_code! - before_action :authorize_push_code!, only: [:create_dir] + before_action :authorize_edit_tree!, only: [:create_dir] def show return render_404 unless @repository.commit(@ref) @@ -34,44 +34,20 @@ class Projects::TreeController < Projects::ApplicationController def create_dir return render_404 unless @commit_params.values.all? - begin - result = Files::CreateDirService.new(@project, current_user, @commit_params).execute - message = result[:message] - rescue => e - message = e.to_s - end - - if result && result[:status] == :success - flash[:notice] = "The directory has been successfully created" - respond_to do |format| - format.html { redirect_to after_create_dir_path } - end - else - flash[:alert] = message - respond_to do |format| - format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, @new_branch) } - end - end + create_commit(Files::CreateDirService, success_notice: "The directory has been successfully created.", + success_path: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @dir_name)), + failure_path: namespace_project_tree_path(@project.namespace, @project, @ref)) end private def assign_dir_vars - @new_branch = params[:new_branch].present? ? sanitize(strip_tags(params[:new_branch])) : @ref + @target_branch = params[:target_branch] + @dir_name = File.join(@path, params[:dir_name]) @commit_params = { file_path: @dir_name, - current_branch: @ref, - target_branch: @new_branch, commit_message: params[:commit_message], } end - - def after_create_dir_path - if create_merge_request? - new_merge_request_path - else - namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @dir_name)) - end - end end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 68e5d5be600..81b1f34cdf8 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -22,32 +22,92 @@ module BlobHelper %w(credits changelog news copying copyright license authors) end - def edit_blob_link(project, ref, path, options = {}) - blob = - begin - project.repository.blob_at(ref, path) - rescue - nil - end - - return unless blob && blob.text? && blob_editable?(blob) - - text = 'Edit' - after = options[:after] || '' + def edit_blob_link(project = @project, ref = @ref, path = @path, options = {}) + return unless current_user + + blob = project.repository.blob_at(ref, path) rescue nil + + return unless blob && blob_text_editable?(blob) + from_mr = options[:from_merge_request_id] link_opts = {} link_opts[:from_merge_request_id] = from_mr if from_mr - cls = 'btn btn-small' - link_to(text, - namespace_project_edit_blob_path(project.namespace, project, - tree_join(ref, path), - link_opts), - class: cls - ) + after.html_safe + + edit_path = namespace_project_edit_blob_path(project.namespace, project, + tree_join(ref, path), + link_opts) + + if !on_top_of_branch? + button_tag "Edit", class: "btn btn-default disabled has_tooltip", title: "You can only edit files when you are on a branch", data: {container: 'body'} + elsif can_edit_blob?(blob) + link_to "Edit", edit_path, class: 'btn btn-small' + elsif can?(current_user, :fork_project, project) + continue_params = { + to: edit_path, + notice: edit_in_new_fork_notice, + notice_now: edit_in_new_fork_notice_now + } + fork_path = namespace_project_fork_path(project.namespace, project, namespace_key: current_user.namespace.id, + continue: continue_params) + + link_to "Edit", fork_path, class: 'btn btn-small', method: :post + end + end + + def modify_file_link(project = @project, ref = @ref, path = @path, label:, action:, btn_class:, modal_type:) + return unless current_user + + blob = project.repository.blob_at(ref, path) rescue nil + + return unless blob + + if !on_top_of_branch? + button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: {container: 'body'} + elsif can_edit_blob?(blob) + button_tag label, class: "btn btn-#{btn_class}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal' + elsif can?(current_user, :fork_project, project) + continue_params = { + to: request.fullpath, + notice: edit_in_new_fork_notice + " Try to #{action} this file again.", + notice_now: edit_in_new_fork_notice_now + } + fork_path = namespace_project_fork_path(project.namespace, project, namespace_key: current_user.namespace.id, + continue: continue_params) + + link_to label, fork_path, class: "btn btn-#{btn_class}", method: :post + end + end + + def replace_blob_link(project = @project, ref = @ref, path = @path) + modify_file_link( + project, + ref, + path, + label: "Replace", + action: "replace", + btn_class: "default", + modal_type: "upload" + ) + end + + def delete_blob_link(project = @project, ref = @ref, path = @path) + modify_file_link( + project, + ref, + path, + label: "Delete", + action: "delete", + btn_class: "remove", + modal_type: "remove" + ) + end + + def blob_text_editable?(blob) + blob.text? && !blob.lfs_pointer? end - def blob_editable?(blob, project = @project, ref = @ref) - !blob.lfs_pointer? && allowed_tree_edit?(project, ref) + def can_edit_blob?(blob, project = @project, ref = @ref) + !blob.lfs_pointer? && can_edit_tree?(project, ref) end def leave_edit_message diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index f448dd0ab61..2ad7c80dae0 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -50,24 +50,49 @@ module TreeHelper project.repository.branch_names.include?(ref) end - def allowed_tree_edit?(project = nil, ref = nil) + def can_edit_tree?(project = nil, ref = nil) project ||= @project ref ||= @ref + return false unless on_top_of_branch?(project, ref) - can?(current_user, :push_code, project) + can?(current_user, :push_code, project) || + (current_user && current_user.already_forked?(project)) end def tree_edit_branch(project = @project, ref = @ref) - if allowed_tree_edit?(project, ref) - if can_push_branch?(project, ref) - ref - else - project.repository.next_patch_branch - end + return unless can_edit_tree?(project, ref) + + if can_push_branch?(project, ref) + ref + else + project = tree_edit_project(project) + project.repository.next_patch_branch + end + end + + def tree_edit_project(project = @project) + if can?(current_user, :push_code, project) + project + elsif current_user && current_user.already_forked?(project) + current_user.fork_of(project) end end + def edit_in_new_fork_notice_now + "You're not allowed to make changes to this project directly." + + " A fork of this project is being created that you can make changes in, so you can submit a merge request." + end + + def edit_in_new_fork_notice + "You're not allowed to make changes to this project directly." + + " A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + + def commit_in_fork_help + "A new branch will be created in your fork and a new merge request will be started." + end + def tree_breadcrumbs(tree, max_links = 2) if @path.present? part_path = "" diff --git a/app/models/repository.rb b/app/models/repository.rb index 2c25f4ce451..9f688e3b45b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -592,47 +592,54 @@ class Repository Gitlab::Popen.popen(args, path_to_repo) end - def commit_with_hooks(current_user, branch) - oldrev = Gitlab::Git::BLANK_SHA - ref = Gitlab::Git::BRANCH_REF_PREFIX + branch - was_empty = empty? - - # Create temporary ref + def with_tmp_ref(oldrev = nil) random_string = SecureRandom.hex tmp_ref = "refs/tmp/#{random_string}/head" - unless was_empty - oldrev = find_branch(branch).target + if oldrev && !Gitlab::Git.blank_ref?(oldrev) rugged.references.create(tmp_ref, oldrev) end # Make commit in tmp ref - newrev = yield(tmp_ref) + yield(tmp_ref) + ensure + rugged.references.delete(tmp_ref) rescue nil + end + + def commit_with_hooks(current_user, branch) + oldrev = Gitlab::Git::BLANK_SHA + ref = Gitlab::Git::BRANCH_REF_PREFIX + branch + was_empty = empty? - unless newrev - raise CommitError.new('Failed to create commit') + unless was_empty + oldrev = find_branch(branch).target end - GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do - if was_empty - # Create branch - rugged.references.create(ref, newrev) - else - # Update head - current_head = find_branch(branch).target + with_tmp_ref(oldrev) do |tmp_ref| + # Make commit in tmp ref + newrev = yield(tmp_ref) + + unless newrev + raise CommitError.new('Failed to create commit') + end - # Make sure target branch was not changed during pre-receive hook - if current_head == oldrev - rugged.references.update(ref, newrev) + GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do + if was_empty + # Create branch + rugged.references.create(ref, newrev) else - raise CommitError.new('Commit was rejected because branch received new push') + # Update head + current_head = find_branch(branch).target + + # Make sure target branch was not changed during pre-receive hook + if current_head == oldrev + rugged.references.update(ref, newrev) + else + raise CommitError.new('Commit was rejected because branch received new push') + end end end end - rescue GitHooksService::PreReceiveError - # Remove tmp ref and return error to user - rugged.references.delete(tmp_ref) - raise end private diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb index de18f3bc556..84e141f5fd8 100644 --- a/app/services/create_branch_service.rb +++ b/app/services/create_branch_service.rb @@ -1,7 +1,7 @@ require_relative 'base_service' class CreateBranchService < BaseService - def execute(branch_name, ref) + def execute(branch_name, ref, source_project: @project) valid_branch = Gitlab::GitRefValidator.validate(branch_name) if valid_branch == false return error('Branch name invalid') @@ -13,7 +13,20 @@ class CreateBranchService < BaseService return error('Branch already exists') end - new_branch = repository.add_branch(current_user, branch_name, ref) + new_branch = nil + if source_project != @project + repository.with_tmp_ref do |tmp_ref| + repository.fetch_ref( + source_project.repository.path_to_repo, + "refs/heads/#{ref}", + tmp_ref + ) + + new_branch = repository.add_branch(current_user, branch_name, tmp_ref) + end + else + new_branch = repository.add_branch(current_user, branch_name, ref) + end if new_branch push_data = build_push_data(project, current_user, new_branch) diff --git a/app/services/files/base_service.rb b/app/services/files/base_service.rb index 9a67b160940..0326a8823e9 100644 --- a/app/services/files/base_service.rb +++ b/app/services/files/base_service.rb @@ -3,8 +3,10 @@ module Files class ValidationError < StandardError; end def execute - @current_branch = params[:current_branch] + @source_project = params[:source_project] || @project + @source_branch = params[:source_branch] @target_branch = params[:target_branch] + @commit_message = params[:commit_message] @file_path = params[:file_path] @file_content = if params[:file_content_encoding] == 'base64' @@ -16,8 +18,8 @@ module Files # Validate parameters validate - # Create new branch if it different from current_branch - if @target_branch != @current_branch + # Create new branch if it different from source_branch + if different_branch? create_target_branch end @@ -26,18 +28,14 @@ module Files else error("Something went wrong. Your changes were not committed") end - rescue Repository::CommitError, GitHooksService::PreReceiveError, ValidationError => ex + rescue Repository::CommitError, Gitlab::Git::Repository::InvalidBlobName, GitHooksService::PreReceiveError, ValidationError => ex error(ex.message) end private - def current_branch - @current_branch ||= params[:current_branch] - end - - def target_branch - @target_branch ||= params[:target_branch] + def different_branch? + @source_branch != @target_branch || @source_project != @project end def raise_error(message) @@ -52,11 +50,11 @@ module Files end unless project.empty_repo? - unless repository.branch_names.include?(@current_branch) + unless @source_project.repository.branch_names.include?(@source_branch) raise_error("You can only create or edit files when you are on a branch") end - if @current_branch != @target_branch + if different_branch? if repository.branch_names.include?(@target_branch) raise_error("Branch with such name already exists. You need to switch to this branch in order to make changes") end @@ -65,10 +63,10 @@ module Files end def create_target_branch - result = CreateBranchService.new(project, current_user).execute(@target_branch, @current_branch) + result = CreateBranchService.new(project, current_user).execute(@target_branch, @source_branch, source_project: @source_project) unless result[:status] == :success - raise_error("Something went wrong when we tried to create #{@target_branch} for you") + raise_error("Something went wrong when we tried to create #{@target_branch} for you: #{result[:message]}") end end end diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb index 2348920cc58..e4cde4a2fd8 100644 --- a/app/services/files/create_service.rb +++ b/app/services/files/create_service.rb @@ -26,7 +26,7 @@ module Files unless project.empty_repo? @file_path.slice!(0) if @file_path.start_with?('/') - blob = repository.blob_at_branch(@current_branch, @file_path) + blob = repository.blob_at_branch(@source_branch, @file_path) if blob raise_error("Your changes could not be committed because a file with the same name already exists") diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml index 2fd3d9e1be4..640612ca433 100644 --- a/app/views/projects/_commit_button.html.haml +++ b/app/views/projects/_commit_button.html.haml @@ -2,3 +2,7 @@ = button_tag 'Commit Changes', class: 'btn commit-btn js-commit-button btn-create' = link_to 'Cancel', cancel_path, class: 'btn btn-cancel', data: {confirm: leave_edit_message} + + - unless can?(current_user, :push_code, @project) + .inline.prepend-left-10 + = commit_in_fork_help diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml index b1df8d19938..caefd911a2a 100644 --- a/app/views/projects/blob/_actions.html.haml +++ b/app/views/projects/blob/_actions.html.haml @@ -14,13 +14,8 @@ = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.sha, @path)), class: 'btn btn-sm' -- if blob_editable?(@blob) +- if current_user .btn-group{ role: "group" } - = edit_blob_link(@project, @ref, @path) - %button.btn.btn-default{ 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } Replace - %button.btn.btn-remove{ 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal' } Delete -- elsif !on_top_of_branch? - .btn-group{ role: "group" } - %button.btn.btn-default.disabled.has_tooltip{title: "You can only edit files when you are on a branch.", data: {container: 'body'}} Edit - %button.btn.btn-default.disabled.has_tooltip{title: "You can only replace files when you are on a branch.", data: {container: 'body'}} Replace - %button.btn.btn-remove.disabled.has_tooltip{title: "You can only delete files when you are on a branch.", data: {container: 'body'}} Delete + = edit_blob_link + = replace_blob_link + = delete_blob_link diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml index fc6c9f5fd09..084608bbba3 100644 --- a/app/views/projects/blob/_new_dir.html.haml +++ b/app/views/projects/blob/_new_dir.html.haml @@ -17,5 +17,9 @@ = submit_tag "Create directory", class: 'btn btn-create' = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" + - unless can?(current_user, :push_code, @project) + .inline.prepend-left-10 + = commit_in_fork_help + :javascript new NewCommitForm($('.js-create-dir-form')) diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml index ecc90a30e78..676924dc6ca 100644 --- a/app/views/projects/blob/_upload.html.haml +++ b/app/views/projects/blob/_upload.html.haml @@ -20,6 +20,11 @@ = button_tag button_title, class: 'btn btn-small btn-create btn-upload-file', id: 'submit-all' = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" + - unless can?(current_user, :push_code, @project) + .inline.prepend-left-10 + = commit_in_fork_help + + :javascript disableButtonIfEmptyField($('.js-upload-blob-form').find('.js-commit-message'), '.btn-upload-file'); new BlobFileDropzone($('.js-upload-blob-form'), '#{method}'); diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index a47fe7ede80..09fa148b129 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -20,7 +20,7 @@ = hidden_field_tag 'last_commit', @last_commit = hidden_field_tag 'content', '', id: "file-content" = hidden_field_tag 'from_merge_request_id', params[:from_merge_request_id] - = render 'projects/commit_button', ref: @ref, cancel_path: @after_edit_path + = render 'projects/commit_button', ref: @ref, cancel_path: namespace_project_blob_path(@project.namespace, @project, @id) :javascript blob = new EditBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", "#{@blob.language.try(:ace_mode)}") diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index 3f8d11ed8c8..6988039b6c7 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -6,7 +6,7 @@ %div#tree-holder.tree-holder = render 'blob', blob: @blob -- if blob_editable?(@blob) +- if can_edit_blob?(@blob) = render 'projects/blob/remove' - title = "Replace #{@blob.name}" diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml index b277b765b6b..1f639fecc30 100644 --- a/app/views/projects/buttons/_dropdown.html.haml +++ b/app/views/projects/buttons/_dropdown.html.haml @@ -18,10 +18,11 @@ = link_to new_namespace_project_snippet_path(@project.namespace, @project) do = icon('file-text-o fw') New snippet + - if can?(current_user, :push_code, @project) %li.divider %li - = link_to namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master'), title: 'New file' do + = link_to namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master') do = icon('file fw') New file %li @@ -32,3 +33,20 @@ = link_to new_namespace_project_tag_path(@project.namespace, @project) do = icon('tags fw') New tag + - elsif current_user && current_user.already_forked?(@project) + %li.divider + %li + = link_to namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master') do + = icon('file fw') + New file + - elsif can?(current_user, :fork_project, @project) + %li.divider + %li + - continue_params = { to: namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master'), + notice: edit_in_new_fork_notice, + notice_now: edit_in_new_fork_notice_now } + - fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key: current_user.namespace.id, + continue: continue_params) + = link_to fork_path, method: :post do + = icon('file fw') + New file diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index 327e7d9245a..9c6d7b46429 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -32,7 +32,8 @@ - if editable_diff?(diff_file) = edit_blob_link(@merge_request.source_project, @merge_request.source_branch, diff_file.new_path, - after: ' ', from_merge_request_id: @merge_request.id) + from_merge_request_id: @merge_request.id) +   = view_file_btn(diff_commit.id, diff_file, project) diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml index f0b0a11c04a..8a2c027a455 100644 --- a/app/views/projects/forks/new.html.haml +++ b/app/views/projects/forks/new.html.haml @@ -43,4 +43,3 @@ %i.fa.fa-spinner.fa-spin Forking repository %p Please wait a moment, this page will automatically refresh when ready. - diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index 1bc90edd8f0..1927883513a 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -29,7 +29,7 @@ - if tree.readme = render "projects/tree/readme", readme: tree.readme -- if allowed_tree_edit? +- if can_edit_tree? = render 'projects/blob/upload', title: 'Upload New File', placeholder: 'Upload new file', button_title: 'Upload file', form_path: namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post = render 'projects/blob/new_dir' diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index cefe33e581f..6167006f947 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -11,26 +11,60 @@ = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path) - else = link_to title, '#' - - if allowed_tree_edit? + + - if current_user %li - %span.dropdown - %a.dropdown-toggle.btn.btn-sm.add-to-tree{href: '#', "data-toggle" => "dropdown"} + - if !on_top_of_branch? + %span.btn.btn-sm.add-to-tree.disabled.has_tooltip{title: "You can only add files when you are on a branch", data: {container: 'body'}} = icon('plus') - %ul.dropdown-menu - %li - = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'Create file', id: 'new-file-link' do - = icon('pencil fw') - Create file - %li - = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do - = icon('file fw') - Upload file - %li.divider - %li - = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do - = icon('folder fw') - New directory - - elsif !on_top_of_branch? - %li - %span.btn.btn-sm.add-to-tree.disabled.has_tooltip{title: "You can only add files when you are on a branch.", data: {container: 'body'}} - = icon('plus') + - elsif can_edit_tree? + %span.dropdown + %a.dropdown-toggle.btn.btn-sm.add-to-tree{href: '#', "data-toggle" => "dropdown"} + = icon('plus') + %ul.dropdown-menu + %li + = link_to namespace_project_new_blob_path(@project.namespace, @project, @id) do + = icon('pencil fw') + Create file + %li + = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do + = icon('file fw') + Upload file + %li.divider + %li + = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do + = icon('folder fw') + New directory + - elsif can?(current_user, :fork_project, @project) + %span.dropdown + %a.dropdown-toggle.btn.btn-sm.add-to-tree{href: '#', "data-toggle" => "dropdown"} + = icon('plus') + %ul.dropdown-menu + %li + - continue_params = { to: namespace_project_new_blob_path(@project.namespace, @project, @id), + notice: edit_in_new_fork_notice, + notice_now: edit_in_new_fork_notice_now } + - fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key: current_user.namespace.id, + continue: continue_params) + = link_to fork_path, method: :post do + = icon('pencil fw') + Create file + %li + - continue_params = { to: request.fullpath, + notice: edit_in_new_fork_notice + " Try to upload a file again.", + notice_now: edit_in_new_fork_notice_now } + - fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key: current_user.namespace.id, + continue: continue_params) + = link_to fork_path, method: :post do + = icon('file fw') + Upload file + %li.divider + %li + - continue_params = { to: request.fullpath, + notice: edit_in_new_fork_notice + " Try to create a new directory again.", + notice_now: edit_in_new_fork_notice_now } + - fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key: current_user.namespace.id, + continue: continue_params) + = link_to fork_path, method: :post do + = icon('folder fw') + New directory diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml index 111219f2064..0c8ac48bb58 100644 --- a/app/views/shared/_new_commit_form.html.haml +++ b/app/views/shared/_new_commit_form.html.haml @@ -1,16 +1,22 @@ = render 'shared/commit_message_container', placeholder: placeholder -- unless @project.empty_repo? - .form-group.branch - = label_tag 'new_branch', 'Target branch', class: 'control-label' - .col-sm-10 - = text_field_tag 'new_branch', @new_branch || tree_edit_branch, required: true, class: "form-control js-new-branch" +- if @project.empty_repo? + = hidden_field_tag 'target_branch', @ref +- else + - if can?(current_user, :push_code, @project) + .form-group.branch + = label_tag 'target_branch', 'Target branch', class: 'control-label' + .col-sm-10 + = text_field_tag 'target_branch', @target_branch || tree_edit_branch, required: true, class: "form-control js-target-branch" - .js-create-merge-request-container - .checkbox - - nonce = SecureRandom.hex - = label_tag "create_merge_request-#{nonce}" do - = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}" - Start a new merge request with these changes + .js-create-merge-request-container + .checkbox + - nonce = SecureRandom.hex + = label_tag "create_merge_request-#{nonce}" do + = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}" + Start a new merge request with these changes + - else + = hidden_field_tag 'target_branch', @target_branch || tree_edit_branch + = hidden_field_tag 'create_merge_request', 1 = hidden_field_tag 'original_branch', @ref, class: 'js-original-branch' diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index 0c6df18ce2e..da8a07c2b4a 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -75,7 +75,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I fill the new branch name' do - fill_in :new_branch, with: 'new_branch_name', visible: true + fill_in :target_branch, with: 'new_branch_name', visible: true end step 'I fill the new file name with an illegal name' do diff --git a/lib/api/files.rb b/lib/api/files.rb index a7a768f8895..8ad2c1883c7 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -7,7 +7,7 @@ module API def commit_params(attrs) { file_path: attrs[:file_path], - current_branch: attrs[:branch_name], + source_branch: attrs[:branch_name], target_branch: attrs[:branch_name], commit_message: attrs[:commit_message], file_content: attrs[:content], diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb index a474574c6e5..a4366e378c7 100644 --- a/spec/controllers/projects/tree_controller_spec.rb +++ b/spec/controllers/projects/tree_controller_spec.rb @@ -98,7 +98,7 @@ describe Projects::TreeController do project_id: project.to_param, id: 'master', dir_name: path, - new_branch: target_branch, + target_branch: target_branch, commit_message: 'Test commit message') end @@ -109,7 +109,7 @@ describe Projects::TreeController do it 'redirects to the new directory' do expect(subject). to redirect_to("/#{project.path_with_namespace}/blob/#{target_branch}/#{path}") - expect(flash[:notice]).to eq('The directory has been successfully created') + expect(flash[:notice]).to eq('The directory has been successfully created.') end end -- cgit v1.2.1 From 0ac57a540d245a24219519c4093d15b8ab2f536c Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 18 Dec 2015 11:19:08 +0100 Subject: Satisfy Rubocop --- app/helpers/blob_helper.rb | 4 ++-- app/views/projects/merge_requests/_merge_request.html.haml | 2 +- app/views/projects/tree/_tree_header.html.haml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 81b1f34cdf8..3368e77a0eb 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -38,7 +38,7 @@ module BlobHelper link_opts) if !on_top_of_branch? - button_tag "Edit", class: "btn btn-default disabled has_tooltip", title: "You can only edit files when you are on a branch", data: {container: 'body'} + button_tag "Edit", class: "btn btn-default disabled has_tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' } elsif can_edit_blob?(blob) link_to "Edit", edit_path, class: 'btn btn-small' elsif can?(current_user, :fork_project, project) @@ -62,7 +62,7 @@ module BlobHelper return unless blob if !on_top_of_branch? - button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: {container: 'body'} + button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' } elsif can_edit_blob?(blob) button_tag label, class: "btn btn-#{btn_class}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal' elsif can?(current_user, :fork_project, project) diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index 105c731c7e1..a051729dc32 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -17,7 +17,7 @@ - if merge_request.open? && merge_request.broken? %li - = link_to merge_request_path(merge_request), class: "has_tooltip", title: "Cannot be merged automatically", data: {container: 'body'} do + = link_to merge_request_path(merge_request), class: "has_tooltip", title: "Cannot be merged automatically", data: { container: 'body' } do = icon('exclamation-triangle') - if merge_request.assignee diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index 6167006f947..7453eb7a4a4 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -15,7 +15,7 @@ - if current_user %li - if !on_top_of_branch? - %span.btn.btn-sm.add-to-tree.disabled.has_tooltip{title: "You can only add files when you are on a branch", data: {container: 'body'}} + %span.btn.btn-sm.add-to-tree.disabled.has_tooltip{title: "You can only add files when you are on a branch", data: { container: 'body' }} = icon('plus') - elsif can_edit_tree? %span.dropdown -- cgit v1.2.1 From daa28d9fbd78415fd9e1d33deafdcaed56b10981 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 18 Dec 2015 12:43:53 -0200 Subject: Fix spec --- spec/requests/api/branches_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index 5c1b58535cc..36461e84c3a 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -118,7 +118,7 @@ describe API::API, api: true do branch_name: 'new design', ref: branch_sha expect(response.status).to eq(400) - expect(json_response['message']).to eq('Branch name invalid') + expect(json_response['message']).to eq('Branch name is invalid') end it 'should return 400 if branch already exists' do -- cgit v1.2.1 From f4f4a6b5303a0889f3fdb1bfe0bb014a6788c4d6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 18 Dec 2015 16:14:12 +0100 Subject: Fix specs and behavior for LFS files --- app/controllers/projects/forks_controller.rb | 11 +++++++---- app/controllers/projects/imports_controller.rb | 9 +++++++-- app/controllers/projects/tree_controller.rb | 2 +- app/helpers/blob_helper.rb | 10 ++++------ app/views/projects/blob/_actions.html.haml | 2 +- app/views/projects/diffs/_file.html.haml | 4 ++-- features/steps/project/source/browse_files.rb | 6 +++--- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 51181b8042e..1d599b6c427 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -13,15 +13,13 @@ class Projects::ForksController < Projects::ApplicationController @forked_project = ::Projects::ForkService.new(project, current_user, namespace: namespace).execute if @forked_project.saved? && @forked_project.forked? - continue_params[:notice] ||= "The project was successfully forked." - if @forked_project.import_in_progress? redirect_to namespace_project_import_path(@forked_project.namespace, @forked_project, continue: continue_params) else if continue_params redirect_to continue_params[:to], notice: continue_params[:notice] else - redirect_to namespace_project_path(@forked_project.namespace, @forked_project) + redirect_to namespace_project_path(@forked_project.namespace, @forked_project), notice: "The project was successfully forked." end end else @@ -32,6 +30,11 @@ class Projects::ForksController < Projects::ApplicationController private def continue_params - params[:continue].permit(:to, :notice, :notice_now) + continue_params = params[:continue] + if continue_params + continue_params.permit(:to, :notice, :notice_now) + else + nil + end end end diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index e9c9edd3a3c..8d8035ef5ff 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -28,7 +28,7 @@ class Projects::ImportsController < Projects::ApplicationController if continue_params redirect_to continue_params[:to], notice: continue_params[:notice] else - redirect_to project_path(@project) + redirect_to project_path(@project), notice: "The project was successfully forked." end elsif @project.import_failed? redirect_to new_namespace_project_import_path(@project.namespace, @project) @@ -43,7 +43,12 @@ class Projects::ImportsController < Projects::ApplicationController private def continue_params - @continue_params ||= params[:continue].permit(:to, :notice, :notice_now) + continue_params = params[:continue] + if continue_params + continue_params.permit(:to, :notice, :notice_now) + else + nil + end end def require_no_repo diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 4f78bde2d2d..cb3ed0f6f9c 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -35,7 +35,7 @@ class Projects::TreeController < Projects::ApplicationController return render_404 unless @commit_params.values.all? create_commit(Files::CreateDirService, success_notice: "The directory has been successfully created.", - success_path: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @dir_name)), + success_path: namespace_project_tree_path(@project.namespace, @project, File.join(@target_branch, @dir_name)), failure_path: namespace_project_tree_path(@project.namespace, @project, @ref)) end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 3368e77a0eb..d31d4cde08f 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -27,7 +27,7 @@ module BlobHelper blob = project.repository.blob_at(ref, path) rescue nil - return unless blob && blob_text_editable?(blob) + return unless blob && blob_text_viewable?(blob) from_mr = options[:from_merge_request_id] link_opts = {} @@ -63,6 +63,8 @@ module BlobHelper if !on_top_of_branch? button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' } + elsif blob.lfs_pointer? + button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "It is not possible to #{action} files that are stored in LFS using the web interface", data: { container: 'body' } elsif can_edit_blob?(blob) button_tag label, class: "btn btn-#{btn_class}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal' elsif can?(current_user, :fork_project, project) @@ -102,10 +104,6 @@ module BlobHelper ) end - def blob_text_editable?(blob) - blob.text? && !blob.lfs_pointer? - end - def can_edit_blob?(blob, project = @project, ref = @ref) !blob.lfs_pointer? && can_edit_tree?(project, ref) end @@ -130,7 +128,7 @@ module BlobHelper icon("#{file_type_icon_class('file', mode, name)} fw") end - def blob_viewable?(blob) + def blob_text_viewable?(blob) blob && blob.text? && !blob.lfs_pointer? end diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml index caefd911a2a..cdac50f7a8d 100644 --- a/app/views/projects/blob/_actions.html.haml +++ b/app/views/projects/blob/_actions.html.haml @@ -2,7 +2,7 @@ = link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id), class: 'btn btn-sm', target: '_blank' -# only show normal/blame view links for text files - - if blob_viewable?(@blob) + - if blob_text_viewable?(@blob) - if current_page? namespace_project_blame_path(@project.namespace, @project, @id) = link_to 'Normal View', namespace_project_blob_path(@project.namespace, @project, @id), class: 'btn btn-sm' diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index 9c6d7b46429..517f6aef7c5 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -24,7 +24,7 @@ = "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}" .diff-controls - - if blob_viewable?(blob) + - if blob_text_viewable?(blob) = link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do %i.fa.fa-comments   @@ -40,7 +40,7 @@ .diff-content.diff-wrap-lines -# Skipp all non non-supported blobs - return unless blob.respond_to?('text?') - - if blob_viewable?(blob) + - if blob_text_viewable?(blob) - if diff_view == 'parallel' = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i - else diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index da8a07c2b4a..4962b68b8f2 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -253,7 +253,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps step 'I am redirected to the root directory' do expect(current_path).to eq( - namespace_project_tree_path(@project.namespace, @project, 'master/')) + namespace_project_tree_path(@project.namespace, @project, 'master')) end step "I don't see the permalink link" do @@ -332,8 +332,8 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps expect(page).to have_content 'Permalink' expect(page).not_to have_content 'Edit' expect(page).not_to have_content 'Blame' - expect(page).not_to have_content 'Delete' - expect(page).not_to have_content 'Replace' + expect(page).to have_content 'Delete' + expect(page).to have_content 'Replace' end private -- cgit v1.2.1 From 3639ebd081a6f008c2d0824953dc37168cf59200 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 18 Dec 2015 17:09:58 +0100 Subject: Fix specs --- spec/controllers/projects/tree_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb index a4366e378c7..e74731c9ed8 100644 --- a/spec/controllers/projects/tree_controller_spec.rb +++ b/spec/controllers/projects/tree_controller_spec.rb @@ -108,7 +108,7 @@ describe Projects::TreeController do it 'redirects to the new directory' do expect(subject). - to redirect_to("/#{project.path_with_namespace}/blob/#{target_branch}/#{path}") + to redirect_to("/#{project.path_with_namespace}/tree/#{target_branch}/#{path}") expect(flash[:notice]).to eq('The directory has been successfully created.') end end @@ -119,7 +119,7 @@ describe Projects::TreeController do it 'does not allow overwriting of existing files' do expect(subject). - to redirect_to("/#{project.path_with_namespace}/blob/master") + to redirect_to("/#{project.path_with_namespace}/tree/master") expect(flash[:alert]).to eq('Directory already exists as a file') end end -- cgit v1.2.1 From 70eff78d8c875118ff22da5a3e8ecc45b730574e Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 18 Dec 2015 14:17:19 -0500 Subject: arrows for buttons --- app/assets/stylesheets/pages/projects.scss | 61 +++++++++++++++++++++++++++++- app/views/projects/_home_panel.html.haml | 2 +- app/views/projects/buttons/_fork.html.haml | 5 +++ app/views/projects/buttons/_star.html.haml | 6 +++ 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 2ded32dba12..31a093fadd5 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -101,11 +101,70 @@ margin-top: 12px; margin-bottom: 0px; + .count-buttons { + display: block; + } + .btn { @include btn-gray; - + text-transform: none; + } + .count-with-arrow { + display: inline-block; + position: relative; + margin-left: 4px; + + .arrow { + + &:before { + content: ''; + display: inline-block; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 50%; + left: 0; + margin-top: -6px; + border-width: 7px 5px 7px 0; + border-right-color: #dce0e5; + } + + &:after { + content: ''; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 50%; + left: 1px; + margin-top: -9px; + border-width: 10px 7px 10px 0; + border-right-color: #FFF; + } + } .count { + @include btn-gray; display: inline-block; + background: white; + border-radius: 2px; + border-width: 1px; + border-style: solid; + font-size: 13px; + font-weight: 600; + line-height: 20px; + padding: 11px 16px; + letter-spacing: .4px; + padding: 10px; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; + white-space: nowrap; + margin: 0 11px 0px 4px; } } } diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index c1669ac046b..4420861c9dc 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -27,7 +27,7 @@ = icon('rss') .project-repo-buttons - .split-one + .split-one.count-buttons = render 'projects/buttons/star' = render 'projects/buttons/fork' diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index 2d3abf09051..133531887a2 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -4,10 +4,15 @@ = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has_tooltip' do = icon('code-fork fw') Fork + %div.count-with-arrow + %span.arrow %span.count = @project.forks_count - else = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has_tooltip' do = icon('code-fork fw') + Fork + %div.count-with-arrow + %span.arrow %span.count = @project.forks_count diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 41a3ec6d90f..27d63cc4cec 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,6 +1,9 @@ - if current_user = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do = icon('star fw') + Star + %div.count-with-arrow + %span.arrow %span.count = @project.star_count @@ -15,5 +18,8 @@ - else = link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do = icon('star fw') + Star + %div.count-with-arrow + %span.arrow %span.count = @project.star_count -- cgit v1.2.1 From c82691b7b8c102ae8998ae8cff7facc6f720f5a8 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 18 Dec 2015 16:06:48 -0500 Subject: adds starring and unstarring text to star button, also adds partial new styles --- app/assets/stylesheets/pages/projects.scss | 5 ++++- app/controllers/projects_controller.rb | 2 +- app/views/projects/buttons/_star.html.haml | 19 +++++++++++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 31a093fadd5..32a66052659 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -115,7 +115,6 @@ margin-left: 4px; .arrow { - &:before { content: ''; display: inline-block; @@ -165,6 +164,10 @@ background-image: none; white-space: nowrap; margin: 0 11px 0px 4px; + + &:hover { + background: #FFF; + } } } } diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index bf5e25ff895..2dab04f2a7c 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -171,7 +171,7 @@ class ProjectsController < ApplicationController @project.reload render json: { - html: view_to_html_string("projects/buttons/_star") + star_count: @project.star_count } end diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 27d63cc4cec..4289d7afd26 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,7 +1,10 @@ - if current_user = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do = icon('star fw') - Star + - if current_user.starred?(@project) + %span.starred Unstar + - else + %span Star %div.count-with-arrow %span.arrow %span.count @@ -9,7 +12,19 @@ :javascript $('.project-home-panel .toggle-star').on('ajax:success', function (e, data, status, xhr) { - $(this).replaceWith(data.html); + var $this = $(this); + var $starSpan = $this.find('span'); + $this + .parent() + .find('span.count') + .text(data.star_count); + if($starSpan.hasClass('starred')){ + $starSpan.removeClass('starred'); + $starSpan.text('Star'); + } else { + $starSpan.addClass('starred'); + $starSpan.text('Unstar'); + } }) .on('ajax:error', function (e, xhr, status, error) { new Flash('Star toggle failed. Try again later.', 'alert'); -- cgit v1.2.1 From 67c623d8a28f1a3e2b8023f7e4c91947720218bb Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 18 Dec 2015 17:12:47 -0500 Subject: adds dropdown for cloning --- app/assets/stylesheets/pages/projects.scss | 11 ++++++++-- app/views/projects/buttons/_star.html.haml | 21 +++++++++++++++----- app/views/shared/_clone_panel.html.haml | 32 ++++++++++++++++++++++-------- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 32a66052659..7626bf113dc 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -91,10 +91,9 @@ } } - .input-group { + .git-clone-holder { display: inline-table; position: relative; - top: 17px; } .project-repo-buttons { @@ -103,6 +102,7 @@ .count-buttons { display: block; + margin-bottom: 12px; } .btn { @@ -187,6 +187,13 @@ margin-right: 45px; } + .clone-options { + display: table-cell; + a.btn { + width: 100%; + } + } + .form-control { cursor: auto; @extend .monospace; diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 4289d7afd26..aba959f991a 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,9 +1,10 @@ - if current_user = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do - = icon('star fw') - if current_user.starred?(@project) + = icon('star fw') %span.starred Unstar - else + = icon('star-o fw') %span Star %div.count-with-arrow %span.arrow @@ -14,16 +15,26 @@ $('.project-home-panel .toggle-star').on('ajax:success', function (e, data, status, xhr) { var $this = $(this); var $starSpan = $this.find('span'); + var $starIcon = $this.find('i'); $this .parent() .find('span.count') .text(data.star_count); if($starSpan.hasClass('starred')){ - $starSpan.removeClass('starred'); - $starSpan.text('Star'); + $starSpan + .removeClass('starred') + .text('Star'); + $starIcon + .removeClass('fa-star') + .addClass('fa-star-o'); + } else { - $starSpan.addClass('starred'); - $starSpan.text('Unstar'); + $starSpan + .addClass('starred') + .text('Unstar'); + $starIcon + .removeClass('fa-star-o') + .addClass('fa-star'); } }) .on('ajax:error', function (e, xhr, status, error) { diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index edb5778f424..d6fa2ea6a66 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -1,10 +1,26 @@ - project = project || @project -.git-clone-holder.input-group - .input-group-addon.git-protocols + +.git-clone-holder + .btn-group.clone-options + %a.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} + %span SSH + = icon('angle-down') + %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown + %li + %a{href: '#'} + SSH + %li + %a{href: '#'} + HTTPS + + = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true .input-group-btn - = ssh_clone_button(project) - .input-group-btn - = http_clone_button(project) - = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true - .input-group-btn - = clipboard_button(clipboard_target: '#project_clone') + = clipboard_button(clipboard_target: '#project_clone') + +:javascript + $('ul.clone-options-dropdown a').on('click',function(e){ + e.preventDefault(); + var $this = $(this); + $('a.clone-dropdown-btn span').text($this.text()); + console.log("got it",$(this).text()); + }); -- cgit v1.2.1 From f1d5f35936e11a27115b3f4e405d6af5fb850987 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 18 Dec 2015 17:24:43 -0500 Subject: dropdown chooses right default --- app/views/shared/_clone_panel.html.haml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index d6fa2ea6a66..74e82af48c8 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -3,14 +3,15 @@ .git-clone-holder .btn-group.clone-options %a.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} - %span SSH + %span + = default_clone_protocol.upcase = icon('angle-down') %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown %li - %a{href: '#'} + %a{href: '#', "data-url" => @project.ssh_url_to_repo} SSH %li - %a{href: '#'} + %a{href: '#', "data-url" => @project.http_url_to_repo} HTTPS = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true @@ -22,5 +23,5 @@ e.preventDefault(); var $this = $(this); $('a.clone-dropdown-btn span').text($this.text()); - console.log("got it",$(this).text()); + $('#project_clone').val($this.data('url')); }); -- cgit v1.2.1 From c65243427f4c940aab35cc86e039c89c6264cf00 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Sat, 19 Dec 2015 18:29:24 +0100 Subject: Fix specs --- features/steps/project/source/browse_files.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index 4962b68b8f2..898a8a0d0f6 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -124,7 +124,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps step 'I click on "New file" link in repo' do find('.add-to-tree').click - click_link 'Create file' + click_link 'New file' end step 'I click on "Upload file" link in repo' do -- cgit v1.2.1 From c910bca730561da3361faec56ef509e25a798c66 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 21 Dec 2015 11:57:51 +0100 Subject: Add tests for new functionality --- app/controllers/projects/forks_controller.rb | 6 +- features/project/source/browse_files.feature | 106 +++++++++++++++++++++++--- features/steps/project/source/browse_files.rb | 25 ++++-- 3 files changed, 122 insertions(+), 15 deletions(-) diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 1d599b6c427..750181f0c19 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -10,7 +10,11 @@ class Projects::ForksController < Projects::ApplicationController def create namespace = Namespace.find(params[:namespace_key]) - @forked_project = ::Projects::ForkService.new(project, current_user, namespace: namespace).execute + + @forked_project = namespace.projects.find_by(path: project.path) + @forked_project = nil unless @forked_project && @forked_project.forked_from_project == project + + @forked_project ||= ::Projects::ForkService.new(project, current_user, namespace: namespace).execute if @forked_project.saved? && @forked_project.forked? if @forked_project.import_in_progress? diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature index 02159ee3776..937db23d928 100644 --- a/features/project/source/browse_files.feature +++ b/features/project/source/browse_files.feature @@ -24,6 +24,12 @@ Feature: Project Source Browse Files Given I click on "New file" link in repo Then I can see new file page + Scenario: I can create file when I don't have write access + Given I don't have write access + And I click on "New file" link in repo + Then I should see a notice about a new fork having been created + Then I can see new file page + @javascript Scenario: I can create and commit file Given I click on "New file" link in repo @@ -34,6 +40,17 @@ Feature: Project Source Browse Files Then I am redirected to the new file And I should see its new content + @javascript + Scenario: I can create and commit file when I don't have write access + Given I don't have write access + And I click on "New file" link in repo + And I edit code + And I fill the new file name + And I fill the commit message + And I click on "Commit Changes" + Then I am redirected to the fork's new merge request page + And I can see the new commit message + @javascript Scenario: I can create and commit file with new lines at the end of file Given I click on "New file" link in repo @@ -45,6 +62,17 @@ Feature: Project Source Browse Files And I click button "Edit" And I should see its content with new lines preserved at end of file + @javascript + Scenario: I can create and commit file and specify new branch + Given I click on "New file" link in repo + And I edit code + And I fill the new file name + And I fill the commit message + And I fill the new branch name + And I click on "Commit Changes" + Then I am redirected to the fork's new merge request page + And I should see its new content + @javascript Scenario: I can upload file and commit Given I click on "Upload file" link in repo @@ -56,6 +84,19 @@ Feature: Project Source Browse Files And I am redirected to the new merge request page And I can see the new commit message + @javascript + Scenario: I can upload file and commit when I don't have write access + Given I don't have write access + And I click on "Upload file" link in repo + Then I should see a notice about a new fork having been created + When I click on "Upload file" link in repo + And I upload a new text file + And I fill the upload file commit message + And I click on "Upload file" + Then I can see the new text file + And I am redirected to the fork's new merge request page + And I can see the new commit message + @javascript Scenario: I can replace file and commit Given I click on ".gitignore" file in repo @@ -68,15 +109,19 @@ Feature: Project Source Browse Files And I can see the replacement commit message @javascript - Scenario: I can create and commit file and specify new branch - Given I click on "New file" link in repo - And I edit code - And I fill the new file name - And I fill the commit message - And I fill the new branch name - And I click on "Commit Changes" - Then I am redirected to the new merge request page - And I should see its new content + Scenario: I can replace file and commit when I don't have write access + Given I don't have write access + And I click on ".gitignore" file in repo + And I see the ".gitignore" + And I click on "Replace" + Then I should see a notice about a new fork having been created + When I click on "Replace" + And I replace it with a text file + And I fill the replace file commit message + And I click on "Replace file" + Then I can see the new text file + And I am redirected to the new merge request page + And I can see the replacement commit message @javascript Scenario: I can create file in empty repo @@ -117,6 +162,14 @@ Feature: Project Source Browse Files And I click button "Edit" Then I can edit code + @javascript + Scenario: I can edit file when I don't have write access + Given I don't have write access + And I click on ".gitignore" file in repo + And I click button "Edit" + Then I should see a notice about a new fork having been created + And I can edit code + Scenario: If the file is binary the edit link is hidden Given I visit a binary file in the repo Then I cannot see the edit button @@ -131,6 +184,17 @@ Feature: Project Source Browse Files Then I am redirected to the ".gitignore" And I should see its new content + @javascript + Scenario: I can edit and commit file when I don't have write access + Given I don't have write access + And I click on ".gitignore" file in repo + And I click button "Edit" + And I edit code + And I fill the commit message + And I click on "Commit Changes" + Then I am redirected to the fork's new merge request page + And I can see the new commit message + @javascript Scenario: I can edit and commit file to new branch Given I click on ".gitignore" file in repo @@ -161,6 +225,17 @@ Feature: Project Source Browse Files And I click on "Create directory" Then I am redirected to the new merge request page + @javascript + Scenario: I can create directory in repo when I don't have write access + Given I don't have write access + When I click on "New directory" link in repo + Then I should see a notice about a new fork having been created + When I click on "New directory" link in repo + And I fill the new directory name + And I fill the commit message + And I click on "Create directory" + Then I am redirected to the fork's new merge request page + @javascript Scenario: I attempt to create an existing directory When I click on "New directory" link in repo @@ -188,6 +263,19 @@ Feature: Project Source Browse Files Then I am redirected to the files URL And I don't see the ".gitignore" + @javascript + Scenario: I can delete file and commit when I don't have write access + Given I don't have write access + And I click on ".gitignore" file in repo + And I see the ".gitignore" + And I click on "Delete" + Then I should see a notice about a new fork having been created + When I click on "Delete" + And I fill the commit message + And I click on "Delete file" + Then I am redirected to the fork's new merge request page + And I can see the new commit message + Scenario: I can browse directory with Browse Dir Given I click on files directory And I click on History link diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index 898a8a0d0f6..d08935aa101 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -5,6 +5,12 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps include SharedPaths include RepoHelpers + step "I don't have write access" do + @project = create(:project, name: "Other Project", path: "other-project") + @project.team << [@user, :reporter] + visit namespace_project_tree_path(@project.namespace, @project, root_ref) + end + step 'I should see files from repository' do expect(page).to have_content "VERSION" expect(page).to have_content ".gitignore" @@ -87,7 +93,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I fill the commit message' do - fill_in :commit_message, with: 'Not yet a commit message.', visible: true + fill_in :commit_message, with: 'New commit message', visible: true end step 'I click link "Diff"' do @@ -103,7 +109,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I click on "Delete"' do - click_button 'Delete' + click_on 'Delete' end step 'I click on "Delete file"' do @@ -111,7 +117,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I click on "Replace"' do - click_button "Replace" + click_on "Replace" end step 'I click on "Replace file"' do @@ -155,7 +161,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps end step 'I can see the new commit message' do - expect(page).to have_content "New upload commit message" + expect(page).to have_content "New commit message" end step 'I upload a new text file' do @@ -164,7 +170,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps step 'I fill the upload file commit message' do page.within('#modal-upload-blob') do - fill_in :commit_message, with: 'New upload commit message' + fill_in :commit_message, with: 'New commit message' end end @@ -251,6 +257,11 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps expect(current_path).to eq(new_namespace_project_merge_request_path(@project.namespace, @project)) end + step "I am redirected to the fork's new merge request page" do + fork = @user.fork_of(@project) + expect(current_path).to eq(new_namespace_project_merge_request_path(fork.namespace, fork)) + end + step 'I am redirected to the root directory' do expect(current_path).to eq( namespace_project_tree_path(@project.namespace, @project, 'master')) @@ -336,6 +347,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps expect(page).to have_content 'Replace' end + step 'I should see a notice about a new fork having been created' do + expect(page).to have_content "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + private def set_new_content -- cgit v1.2.1 From cfa716ebe0f149fd3f152d90c4dcf32ea450b486 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 21 Dec 2015 12:14:09 +0100 Subject: Fix spec --- features/project/source/browse_files.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature index 937db23d928..a8c276b949e 100644 --- a/features/project/source/browse_files.feature +++ b/features/project/source/browse_files.feature @@ -70,7 +70,7 @@ Feature: Project Source Browse Files And I fill the commit message And I fill the new branch name And I click on "Commit Changes" - Then I am redirected to the fork's new merge request page + Then I am redirected to the new merge request page And I should see its new content @javascript @@ -120,7 +120,7 @@ Feature: Project Source Browse Files And I fill the replace file commit message And I click on "Replace file" Then I can see the new text file - And I am redirected to the new merge request page + And I am redirected to the fork's new merge request page And I can see the replacement commit message @javascript -- cgit v1.2.1 From 23b436dc9346275e9fbd6201317e09da63befc46 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 21 Dec 2015 21:44:34 -0200 Subject: Fix minor stylistic complaints --- app/assets/javascripts/new_branch_form.js.coffee | 7 ++- features/steps/project/commits/branches.rb | 2 +- spec/javascripts/new_branch_spec.js.coffee | 68 ++++++++++++------------ 3 files changed, 38 insertions(+), 39 deletions(-) diff --git a/app/assets/javascripts/new_branch_form.js.coffee b/app/assets/javascripts/new_branch_form.js.coffee index 23a5b333b8a..4b350854f78 100644 --- a/app/assets/javascripts/new_branch_form.js.coffee +++ b/app/assets/javascripts/new_branch_form.js.coffee @@ -13,13 +13,12 @@ class @NewBranchForm @name.on 'blur', @validate init: -> - @name.trigger 'blur'if @name.val().length > 0 + @name.trigger 'blur' if @name.val().length > 0 setupAvailableRefs: (availableRefs) -> - @ref.autocomplete { + @ref.autocomplete source: availableRefs, minLength: 1 - } setupRestrictions: -> startsWith = { @@ -36,7 +35,7 @@ class @NewBranchForm invalid = { pattern: /(\s|~|\^|:|\?|\*|\[|\\|\.\.|@\{|\/{2,}){1}/g - prefix: "can't contains", + prefix: "can't contain", conjunction: ", " } diff --git a/features/steps/project/commits/branches.rb b/features/steps/project/commits/branches.rb index 109d031d446..0a42931147d 100644 --- a/features/steps/project/commits/branches.rb +++ b/features/steps/project/commits/branches.rb @@ -62,7 +62,7 @@ class Spinach::Features::ProjectCommitsBranches < Spinach::FeatureSteps step 'I should see new an error that branch is invalid' do expect(page).to have_content 'Branch name is invalid' - expect(page).to have_content "can't contains spaces" + expect(page).to have_content "can't contain spaces" end step 'I should see new an error that ref is invalid' do diff --git a/spec/javascripts/new_branch_spec.js.coffee b/spec/javascripts/new_branch_spec.js.coffee index 1cba9546655..ea479239957 100644 --- a/spec/javascripts/new_branch_spec.js.coffee +++ b/spec/javascripts/new_branch_spec.js.coffee @@ -22,91 +22,91 @@ describe 'Branch', -> it "can't have two consecutive dots", -> @name.val('foo..bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '..'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '..'") it "can't have spaces anywhere", -> @name.val(' foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains spaces") + expect($('.js-branch-name-error span').text()).toEqual("can't contain spaces") @name.val('foo bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains spaces") + expect($('.js-branch-name-error span').text()).toEqual("can't contain spaces") @name.val('foo ').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains spaces") + expect($('.js-branch-name-error span').text()).toEqual("can't contain spaces") it "can't have ~ anywhere", -> @name.val('~foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") @name.val('foo~bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") @name.val('foo~').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") it "can't have tilde anwhere", -> @name.val('~foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") @name.val('foo~bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") @name.val('foo~').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '~'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") it "can't have caret anywhere", -> @name.val('^foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '^'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '^'") @name.val('foo^bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '^'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '^'") @name.val('foo^').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '^'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '^'") it "can't have : anywhere", -> @name.val(':foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains ':'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain ':'") @name.val('foo:bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains ':'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain ':'") @name.val(':foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains ':'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain ':'") it "can't have question mark anywhere", -> @name.val('?foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '?'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '?'") @name.val('foo?bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '?'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '?'") @name.val('foo?').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '?'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '?'") it "can't have asterisk anywhere", -> @name.val('*foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '*'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '*'") @name.val('foo*bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '*'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '*'") @name.val('foo*').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '*'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '*'") it "can't have open bracket anywhere", -> @name.val('[foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '['") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '['") @name.val('foo[bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '['") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '['") @name.val('foo[').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '['") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '['") it "can't have a backslash anywhere", -> @name.val('\\foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '\\'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '\\'") @name.val('foo\\bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '\\'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '\\'") @name.val('foo\\').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '\\'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '\\'") it "can't contain a sequence @{ anywhere", -> @name.val('@{foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '@{'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '@{'") @name.val('foo@{bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '@{'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '@{'") @name.val('foo@{').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '@{'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '@{'") it "can't have consecutive slashes", -> @name.val('foo//bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains consecutive slashes") + expect($('.js-branch-name-error span').text()).toEqual("can't contain consecutive slashes") it "can't end with a slash", -> @name.val('foo/').trigger('blur') @@ -126,11 +126,11 @@ describe 'Branch', -> it "concatenates all error messages", -> @name.val('/foo bar?~.').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't start with '/', can't contains spaces, '?', '~', can't end in '.'") + expect($('.js-branch-name-error span').text()).toEqual("can't start with '/', can't contain spaces, '?', '~', can't end in '.'") it "doesn't duplicate error messages", -> @name.val('?foo?bar?zoo?').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contains '?'") + expect($('.js-branch-name-error span').text()).toEqual("can't contain '?'") it "removes the error message when is a valid name", -> @name.val('foo?bar').trigger('blur') -- cgit v1.2.1 From 42da7cd375a615d0ba092495981682bafdb99b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Mon, 21 Dec 2015 22:59:15 -0500 Subject: Fix redirect to wrong URL when merging and MR detail URL has an anchor. #4189 --- app/assets/javascripts/merge_request_widget.js.coffee | 2 +- features/project/merge_requests/accept.feature | 8 ++++++++ features/steps/project/merge_requests/acceptance.rb | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee index c4b63966fe7..738ffc8343b 100644 --- a/app/assets/javascripts/merge_request_widget.js.coffee +++ b/app/assets/javascripts/merge_request_widget.js.coffee @@ -18,7 +18,7 @@ class @MergeRequestWidget if data.state == "merged" urlSuffix = if deleteSourceBranch then '?delete_source=true' else '' - window.location.href = window.location.href + urlSuffix + window.location.href = window.location.pathname + urlSuffix else if data.merge_error $('.mr-widget-body').html("

" + data.merge_error + "

") else diff --git a/features/project/merge_requests/accept.feature b/features/project/merge_requests/accept.feature index d5e4f2b0bd8..330ec8ae0fe 100644 --- a/features/project/merge_requests/accept.feature +++ b/features/project/merge_requests/accept.feature @@ -12,6 +12,14 @@ Feature: Project Merge Requests Acceptance Then I should see merge request merged And I should not see the Remove Source Branch button + @javascript + Scenario: Accepting the Merge Request when URL has an anchor + Given I am on the Merge Request detail with note anchor page + When I click on "Remove source branch" option + And I click on Accept Merge Request + Then I should see merge request merged + And I should not see the Remove Source Branch button + @javascript Scenario: Accepting the Merge Request without removing the source branch Given I am on the Merge Request detail page diff --git a/features/steps/project/merge_requests/acceptance.rb b/features/steps/project/merge_requests/acceptance.rb index 383c055c4ef..2685f5fd6b4 100644 --- a/features/steps/project/merge_requests/acceptance.rb +++ b/features/steps/project/merge_requests/acceptance.rb @@ -6,6 +6,10 @@ class Spinach::Features::ProjectMergeRequestsAcceptance < Spinach::FeatureSteps visit merge_request_path(@merge_request) end + step 'I am on the Merge Request detail with note anchor page' do + visit merge_request_path(@merge_request, anchor: 'note_123') + end + step 'I click on "Remove source branch" option' do check('Remove source branch') end -- cgit v1.2.1 From 2eed8007bf3f6759c4ebc7b4d303ae77c7f2a8e3 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 17 Dec 2015 14:29:55 +0200 Subject: base implementation of emoji picker [ci skip] --- app/assets/images/emoji.png | Bin 0 -> 832902 bytes app/assets/javascripts/awards_handler.coffee | 39 +- app/assets/javascripts/notes.js.coffee | 2 +- app/assets/stylesheets/pages/awards.scss | 75 +- app/assets/stylesheets/pages/emojis.scss | 1267 ++++++++++++++++++++++++++ app/controllers/projects/notes_controller.rb | 1 - app/helpers/issues_helper.rb | 14 +- app/views/votes/_votes_block.html.haml | 30 +- lib/award_emoji.rb | 49 +- spec/helpers/issues_helper_spec.rb | 6 - 10 files changed, 1412 insertions(+), 71 deletions(-) create mode 100644 app/assets/images/emoji.png create mode 100644 app/assets/stylesheets/pages/emojis.scss diff --git a/app/assets/images/emoji.png b/app/assets/images/emoji.png new file mode 100644 index 00000000000..a8ad7b6eab6 Binary files /dev/null and b/app/assets/images/emoji.png differ diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 3ff9ba77dfc..f3fdd46cf52 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -1,12 +1,23 @@ class @AwardsHandler constructor: (@post_emoji_url, @noteable_type, @noteable_id, @aliases) -> + $(".add-award").click (event)-> + event.stopPropagation() + event.preventDefault() + $(".emoji-menu").show() + + $("html").click -> + if !$(event.target).closest(".emoji-menu").length + if $(".emoji-menu").is(":visible") + $(".emoji-menu").hide() addAward: (emoji) -> emoji = @normilizeEmojiName(emoji) @postEmoji emoji, => @addAwardToEmojiBar(emoji) + + $(".emoji-menu").hide() - addAwardToEmojiBar: (emoji, custom_path = '') -> + addAwardToEmojiBar: (emoji) -> emoji = @normilizeEmojiName(emoji) if @exist(emoji) if @isActive(emoji) @@ -17,7 +28,7 @@ class @AwardsHandler counter.parent().addClass("active") @addMeToAuthorList(emoji) else - @createEmoji(emoji, custom_path) + @createEmoji(emoji) exist: (emoji) -> @findEmojiIcon(emoji).length > 0 @@ -54,31 +65,29 @@ class @AwardsHandler resetTooltip: (award) -> award.tooltip("destroy") - # "destroy" call is asynchronous, this is why we need to set timeout. + # "destroy" call is asynchronous and there is no appropriate callnack on it, this is why we need to set timeout. setTimeout (-> award.tooltip() ), 200 - createEmoji: (emoji, custom_path) -> + createEmoji: (emoji) -> + emojiCssClass = @resolveNameToCssClass(emoji) + nodes = [] nodes.push("
") - nodes.push("
") - nodes.push(@getImage(emoji, custom_path)) + nodes.push("
") + nodes.push("
1
") nodes.push("
") - nodes.push("
1") - nodes.push("
") - $(".awards-controls").before(nodes.join("\n")) + emoji_node = $(nodes.join("\n")).insertBefore(".awards-controls").find(".emoji-icon").data("emoji", emoji) $(".award").tooltip() - getImage: (emoji, custom_path) -> - if custom_path - $("").attr({src: custom_path, width: 20, height: 20}).wrap("
").parent().html() - else - $("li[data-emoji='" + emoji + "']").html() + resolveNameToCssClass: (emoji) -> + unicodeName = $(".emoji-menu-content [data-emoji='?']".replace("?", emoji)).data("unicode-name") + "emoji-" + unicodeName postEmoji: (emoji, callback) -> $.post @post_emoji_url, { note: { @@ -90,7 +99,7 @@ class @AwardsHandler callback.call() findEmojiIcon: (emoji) -> - $(".icon[data-emoji='" + emoji + "']") + $(".award [data-emoji='" + emoji + "']") scrollToAwards: -> $('body, html').animate({ diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 35dc7829da2..9e5204bfeeb 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -127,7 +127,7 @@ class @Notes @initTaskList() if note.award - awards_handler.addAwardToEmojiBar(note.note, note.emoji_path) + awards_handler.addAwardToEmojiBar(note.note) awards_handler.scrollToAwards() ### diff --git a/app/assets/stylesheets/pages/awards.scss b/app/assets/stylesheets/pages/awards.scss index 041b811a606..30fdf3f218d 100644 --- a/app/assets/stylesheets/pages/awards.scss +++ b/app/assets/stylesheets/pages/awards.scss @@ -2,6 +2,12 @@ @include clearfix; line-height: 34px; + .emoji-icon { + width: 20px; + height: 20px; + margin: 7px 0 0 5px; + } + .award { @include border-radius(5px); @@ -40,6 +46,7 @@ } .awards-controls { + position: relative; margin-left: 10px; float: left; @@ -55,32 +62,58 @@ } } - .awards-menu { - padding: $gl-padding; - min-width: 214px; - - > li { - cursor: pointer; - width: 30px; - height: 30px; - text-align: center; - @include border-radius(5px); + .emoji-menu{ + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0,0,0,.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175); + box-shadow: 0 6px 12px rgba(0,0,0,.175); + + .emoji-menu-content { + padding: $gl-padding; + width: 300px; + height: 300px; + overflow-y: scroll; + + h4 { + clear: left; + } - img { - margin-bottom: 2px; + ul { + list-style-type: none; + margin-left: -20px; } - &:hover { - background-color: #ccc; + li { + cursor: pointer; + width: 30px; + height: 30px; + text-align: center; + float: left; + margin: 3px; + list-decorate: none; + @include border-radius(5px); + + &:hover { + background-color: #ccc; + } } } } } - - .awards-menu{ - li { - float: left; - margin: 3px; - } - } } diff --git a/app/assets/stylesheets/pages/emojis.scss b/app/assets/stylesheets/pages/emojis.scss new file mode 100644 index 00000000000..d1a80b1ba48 --- /dev/null +++ b/app/assets/stylesheets/pages/emojis.scss @@ -0,0 +1,1267 @@ +/* +File is generated by https://github.com/jakesgordon/sprite-factory and midified manualy +The source: gemojione gem. +*/ + +.emoji-0023-20E3 { background: url(emoji.png) 0px 0px no-repeat; } +.emoji-0030-20E3 { background: url(emoji.png) -20px 0px no-repeat; } +.emoji-0031-20E3 { background: url(emoji.png) -40px 0px no-repeat; } +.emoji-0032-20E3 { background: url(emoji.png) -60px 0px no-repeat; } +.emoji-0033-20E3 { background: url(emoji.png) -80px 0px no-repeat; } +.emoji-0034-20E3 { background: url(emoji.png) -100px 0px no-repeat; } +.emoji-0035-20E3 { background: url(emoji.png) -120px 0px no-repeat; } +.emoji-0036-20E3 { background: url(emoji.png) -140px 0px no-repeat; } +.emoji-0037-20E3 { background: url(emoji.png) -160px 0px no-repeat; } +.emoji-0038-20E3 { background: url(emoji.png) -180px 0px no-repeat; } +.emoji-0039-20E3 { background: url(emoji.png) -200px 0px no-repeat; } +.emoji-00A9 { background: url(emoji.png) -220px 0px no-repeat; } +.emoji-00AE { background: url(emoji.png) -240px 0px no-repeat; } +.emoji-1F004 { background: url(emoji.png) -260px 0px no-repeat; } +.emoji-1F0CF { background: url(emoji.png) -280px 0px no-repeat; } +.emoji-1F170 { background: url(emoji.png) -300px 0px no-repeat; } +.emoji-1F171 { background: url(emoji.png) -320px 0px no-repeat; } +.emoji-1F17E { background: url(emoji.png) -340px 0px no-repeat; } +.emoji-1F17F { background: url(emoji.png) -360px 0px no-repeat; } +.emoji-1F18E { background: url(emoji.png) -380px 0px no-repeat; } +.emoji-1F191 { background: url(emoji.png) -400px 0px no-repeat; } +.emoji-1F192 { background: url(emoji.png) -420px 0px no-repeat; } +.emoji-1F193 { background: url(emoji.png) -440px 0px no-repeat; } +.emoji-1F194 { background: url(emoji.png) -460px 0px no-repeat; } +.emoji-1F195 { background: url(emoji.png) -480px 0px no-repeat; } +.emoji-1F196 { background: url(emoji.png) -500px 0px no-repeat; } +.emoji-1F197 { background: url(emoji.png) -520px 0px no-repeat; } +.emoji-1F198 { background: url(emoji.png) -540px 0px no-repeat; } +.emoji-1F199 { background: url(emoji.png) -560px 0px no-repeat; } +.emoji-1F19A { background: url(emoji.png) -580px 0px no-repeat; } +.emoji-1F1E6-1F1E8 { background: url(emoji.png) -600px 0px no-repeat; } +.emoji-1F1E6-1F1E9 { background: url(emoji.png) -620px 0px no-repeat; } +.emoji-1F1E6-1F1EA { background: url(emoji.png) -640px 0px no-repeat; } +.emoji-1F1E6-1F1EB { background: url(emoji.png) -660px 0px no-repeat; } +.emoji-1F1E6-1F1EC { background: url(emoji.png) -680px 0px no-repeat; } +.emoji-1F1E6-1F1EE { background: url(emoji.png) -700px 0px no-repeat; } +.emoji-1F1E6-1F1F1 { background: url(emoji.png) -720px 0px no-repeat; } +.emoji-1F1E6-1F1F2 { background: url(emoji.png) -740px 0px no-repeat; } +.emoji-1F1E6-1F1F4 { background: url(emoji.png) -760px 0px no-repeat; } +.emoji-1F1E6-1F1F7 { background: url(emoji.png) -780px 0px no-repeat; } +.emoji-1F1E6-1F1F9 { background: url(emoji.png) -800px 0px no-repeat; } +.emoji-1F1E6-1F1FA { background: url(emoji.png) -820px 0px no-repeat; } +.emoji-1F1E6-1F1FC { background: url(emoji.png) -840px 0px no-repeat; } +.emoji-1F1E6-1F1FF { background: url(emoji.png) -860px 0px no-repeat; } +.emoji-1F1E7-1F1E6 { background: url(emoji.png) -880px 0px no-repeat; } +.emoji-1F1E7-1F1E7 { background: url(emoji.png) -900px 0px no-repeat; } +.emoji-1F1E7-1F1E9 { background: url(emoji.png) -920px 0px no-repeat; } +.emoji-1F1E7-1F1EA { background: url(emoji.png) -940px 0px no-repeat; } +.emoji-1F1E7-1F1EB { background: url(emoji.png) -960px 0px no-repeat; } +.emoji-1F1E7-1F1EC { background: url(emoji.png) -980px 0px no-repeat; } +.emoji-1F1E7-1F1ED { background: url(emoji.png) -1000px 0px no-repeat; } +.emoji-1F1E7-1F1EE { background: url(emoji.png) -1020px 0px no-repeat; } +.emoji-1F1E7-1F1EF { background: url(emoji.png) -1040px 0px no-repeat; } +.emoji-1F1E7-1F1F2 { background: url(emoji.png) -1060px 0px no-repeat; } +.emoji-1F1E7-1F1F3 { background: url(emoji.png) -1080px 0px no-repeat; } +.emoji-1F1E7-1F1F4 { background: url(emoji.png) -1100px 0px no-repeat; } +.emoji-1F1E7-1F1F7 { background: url(emoji.png) -1120px 0px no-repeat; } +.emoji-1F1E7-1F1F8 { background: url(emoji.png) -1140px 0px no-repeat; } +.emoji-1F1E7-1F1F9 { background: url(emoji.png) -1160px 0px no-repeat; } +.emoji-1F1E7-1F1FC { background: url(emoji.png) -1180px 0px no-repeat; } +.emoji-1F1E7-1F1FE { background: url(emoji.png) -1200px 0px no-repeat; } +.emoji-1F1E7-1F1FF { background: url(emoji.png) -1220px 0px no-repeat; } +.emoji-1F1E8-1F1E6 { background: url(emoji.png) -1240px 0px no-repeat; } +.emoji-1F1E8-1F1E9 { background: url(emoji.png) -1260px 0px no-repeat; } +.emoji-1F1E8-1F1EB { background: url(emoji.png) -1280px 0px no-repeat; } +.emoji-1F1E8-1F1EC { background: url(emoji.png) -1300px 0px no-repeat; } +.emoji-1F1E8-1F1ED { background: url(emoji.png) -1320px 0px no-repeat; } +.emoji-1F1E8-1F1EE { background: url(emoji.png) -1340px 0px no-repeat; } +.emoji-1F1E8-1F1F1 { background: url(emoji.png) -1360px 0px no-repeat; } +.emoji-1F1E8-1F1F2 { background: url(emoji.png) -1380px 0px no-repeat; } +.emoji-1F1E8-1F1F3 { background: url(emoji.png) -1400px 0px no-repeat; } +.emoji-1F1E8-1F1F4 { background: url(emoji.png) -1420px 0px no-repeat; } +.emoji-1F1E8-1F1F7 { background: url(emoji.png) -1440px 0px no-repeat; } +.emoji-1F1E8-1F1FA { background: url(emoji.png) -1460px 0px no-repeat; } +.emoji-1F1E8-1F1FB { background: url(emoji.png) -1480px 0px no-repeat; } +.emoji-1F1E8-1F1FE { background: url(emoji.png) -1500px 0px no-repeat; } +.emoji-1F1E8-1F1FF { background: url(emoji.png) -1520px 0px no-repeat; } +.emoji-1F1E9-1F1EA { background: url(emoji.png) -1540px 0px no-repeat; } +.emoji-1F1E9-1F1EF { background: url(emoji.png) -1560px 0px no-repeat; } +.emoji-1F1E9-1F1F0 { background: url(emoji.png) -1580px 0px no-repeat; } +.emoji-1F1E9-1F1F2 { background: url(emoji.png) -1600px 0px no-repeat; } +.emoji-1F1E9-1F1F4 { background: url(emoji.png) -1620px 0px no-repeat; } +.emoji-1F1E9-1F1FF { background: url(emoji.png) -1640px 0px no-repeat; } +.emoji-1F1EA-1F1E8 { background: url(emoji.png) -1660px 0px no-repeat; } +.emoji-1F1EA-1F1EA { background: url(emoji.png) -1680px 0px no-repeat; } +.emoji-1F1EA-1F1EC { background: url(emoji.png) -1700px 0px no-repeat; } +.emoji-1F1EA-1F1ED { background: url(emoji.png) -1720px 0px no-repeat; } +.emoji-1F1EA-1F1F7 { background: url(emoji.png) -1740px 0px no-repeat; } +.emoji-1F1EA-1F1F8 { background: url(emoji.png) -1760px 0px no-repeat; } +.emoji-1F1EA-1F1F9 { background: url(emoji.png) -1780px 0px no-repeat; } +.emoji-1F1EB-1F1EE { background: url(emoji.png) -1800px 0px no-repeat; } +.emoji-1F1EB-1F1EF { background: url(emoji.png) -1820px 0px no-repeat; } +.emoji-1F1EB-1F1F0 { background: url(emoji.png) -1840px 0px no-repeat; } +.emoji-1F1EB-1F1F2 { background: url(emoji.png) -1860px 0px no-repeat; } +.emoji-1F1EB-1F1F4 { background: url(emoji.png) -1880px 0px no-repeat; } +.emoji-1F1EB-1F1F7 { background: url(emoji.png) -1900px 0px no-repeat; } +.emoji-1F1EC-1F1E6 { background: url(emoji.png) -1920px 0px no-repeat; } +.emoji-1F1EC-1F1E7 { background: url(emoji.png) -1940px 0px no-repeat; } +.emoji-1F1EC-1F1E9 { background: url(emoji.png) -1960px 0px no-repeat; } +.emoji-1F1EC-1F1EA { background: url(emoji.png) -1980px 0px no-repeat; } +.emoji-1F1EC-1F1ED { background: url(emoji.png) -2000px 0px no-repeat; } +.emoji-1F1EC-1F1EE { background: url(emoji.png) -2020px 0px no-repeat; } +.emoji-1F1EC-1F1F1 { background: url(emoji.png) -2040px 0px no-repeat; } +.emoji-1F1EC-1F1F2 { background: url(emoji.png) -2060px 0px no-repeat; } +.emoji-1F1EC-1F1F3 { background: url(emoji.png) -2080px 0px no-repeat; } +.emoji-1F1EC-1F1F6 { background: url(emoji.png) -2100px 0px no-repeat; } +.emoji-1F1EC-1F1F7 { background: url(emoji.png) -2120px 0px no-repeat; } +.emoji-1F1EC-1F1F9 { background: url(emoji.png) -2140px 0px no-repeat; } +.emoji-1F1EC-1F1FA { background: url(emoji.png) -2160px 0px no-repeat; } +.emoji-1F1EC-1F1FC { background: url(emoji.png) -2180px 0px no-repeat; } +.emoji-1F1EC-1F1FE { background: url(emoji.png) -2200px 0px no-repeat; } +.emoji-1F1ED-1F1F0 { background: url(emoji.png) -2220px 0px no-repeat; } +.emoji-1F1ED-1F1F3 { background: url(emoji.png) -2240px 0px no-repeat; } +.emoji-1F1ED-1F1F7 { background: url(emoji.png) -2260px 0px no-repeat; } +.emoji-1F1ED-1F1F9 { background: url(emoji.png) -2280px 0px no-repeat; } +.emoji-1F1ED-1F1FA { background: url(emoji.png) -2300px 0px no-repeat; } +.emoji-1F1EE-1F1E9 { background: url(emoji.png) -2320px 0px no-repeat; } +.emoji-1F1EE-1F1EA { background: url(emoji.png) -2340px 0px no-repeat; } +.emoji-1F1EE-1F1F1 { background: url(emoji.png) -2360px 0px no-repeat; } +.emoji-1F1EE-1F1F3 { background: url(emoji.png) -2380px 0px no-repeat; } +.emoji-1F1EE-1F1F6 { background: url(emoji.png) -2400px 0px no-repeat; } +.emoji-1F1EE-1F1F7 { background: url(emoji.png) -2420px 0px no-repeat; } +.emoji-1F1EE-1F1F8 { background: url(emoji.png) -2440px 0px no-repeat; } +.emoji-1F1EE-1F1F9 { background: url(emoji.png) -2460px 0px no-repeat; } +.emoji-1F1EF-1F1EA { background: url(emoji.png) -2480px 0px no-repeat; } +.emoji-1F1EF-1F1F2 { background: url(emoji.png) -2500px 0px no-repeat; } +.emoji-1F1EF-1F1F4 { background: url(emoji.png) -2520px 0px no-repeat; } +.emoji-1F1EF-1F1F5 { background: url(emoji.png) -2540px 0px no-repeat; } +.emoji-1F1F0-1F1EA { background: url(emoji.png) -2560px 0px no-repeat; } +.emoji-1F1F0-1F1EC { background: url(emoji.png) -2580px 0px no-repeat; } +.emoji-1F1F0-1F1ED { background: url(emoji.png) -2600px 0px no-repeat; } +.emoji-1F1F0-1F1EE { background: url(emoji.png) -2620px 0px no-repeat; } +.emoji-1F1F0-1F1F2 { background: url(emoji.png) -2640px 0px no-repeat; } +.emoji-1F1F0-1F1F3 { background: url(emoji.png) -2660px 0px no-repeat; } +.emoji-1F1F0-1F1F5 { background: url(emoji.png) -2680px 0px no-repeat; } +.emoji-1F1F0-1F1F7 { background: url(emoji.png) -2700px 0px no-repeat; } +.emoji-1F1F0-1F1FC { background: url(emoji.png) -2720px 0px no-repeat; } +.emoji-1F1F0-1F1FE { background: url(emoji.png) -2740px 0px no-repeat; } +.emoji-1F1F0-1F1FF { background: url(emoji.png) -2760px 0px no-repeat; } +.emoji-1F1F1-1F1E6 { background: url(emoji.png) -2780px 0px no-repeat; } +.emoji-1F1F1-1F1E7 { background: url(emoji.png) -2800px 0px no-repeat; } +.emoji-1F1F1-1F1E8 { background: url(emoji.png) -2820px 0px no-repeat; } +.emoji-1F1F1-1F1EE { background: url(emoji.png) -2840px 0px no-repeat; } +.emoji-1F1F1-1F1F0 { background: url(emoji.png) -2860px 0px no-repeat; } +.emoji-1F1F1-1F1F7 { background: url(emoji.png) -2880px 0px no-repeat; } +.emoji-1F1F1-1F1F8 { background: url(emoji.png) -2900px 0px no-repeat; } +.emoji-1F1F1-1F1F9 { background: url(emoji.png) -2920px 0px no-repeat; } +.emoji-1F1F1-1F1FA { background: url(emoji.png) -2940px 0px no-repeat; } +.emoji-1F1F1-1F1FB { background: url(emoji.png) -2960px 0px no-repeat; } +.emoji-1F1F1-1F1FE { background: url(emoji.png) -2980px 0px no-repeat; } +.emoji-1F1F2-1F1E6 { background: url(emoji.png) -3000px 0px no-repeat; } +.emoji-1F1F2-1F1E8 { background: url(emoji.png) -3020px 0px no-repeat; } +.emoji-1F1F2-1F1E9 { background: url(emoji.png) -3040px 0px no-repeat; } +.emoji-1F1F2-1F1EA { background: url(emoji.png) -3060px 0px no-repeat; } +.emoji-1F1F2-1F1EC { background: url(emoji.png) -3080px 0px no-repeat; } +.emoji-1F1F2-1F1ED { background: url(emoji.png) -3100px 0px no-repeat; } +.emoji-1F1F2-1F1F0 { background: url(emoji.png) -3120px 0px no-repeat; } +.emoji-1F1F2-1F1F1 { background: url(emoji.png) -3140px 0px no-repeat; } +.emoji-1F1F2-1F1F2 { background: url(emoji.png) -3160px 0px no-repeat; } +.emoji-1F1F2-1F1F3 { background: url(emoji.png) -3180px 0px no-repeat; } +.emoji-1F1F2-1F1F4 { background: url(emoji.png) -3200px 0px no-repeat; } +.emoji-1F1F2-1F1F7 { background: url(emoji.png) -3220px 0px no-repeat; } +.emoji-1F1F2-1F1F8 { background: url(emoji.png) -3240px 0px no-repeat; } +.emoji-1F1F2-1F1F9 { background: url(emoji.png) -3260px 0px no-repeat; } +.emoji-1F1F2-1F1FA { background: url(emoji.png) -3280px 0px no-repeat; } +.emoji-1F1F2-1F1FB { background: url(emoji.png) -3300px 0px no-repeat; } +.emoji-1F1F2-1F1FC { background: url(emoji.png) -3320px 0px no-repeat; } +.emoji-1F1F2-1F1FD { background: url(emoji.png) -3340px 0px no-repeat; } +.emoji-1F1F2-1F1FE { background: url(emoji.png) -3360px 0px no-repeat; } +.emoji-1F1F2-1F1FF { background: url(emoji.png) -3380px 0px no-repeat; } +.emoji-1F1F3-1F1E6 { background: url(emoji.png) -3400px 0px no-repeat; } +.emoji-1F1F3-1F1E8 { background: url(emoji.png) -3420px 0px no-repeat; } +.emoji-1F1F3-1F1EA { background: url(emoji.png) -3440px 0px no-repeat; } +.emoji-1F1F3-1F1EC { background: url(emoji.png) -3460px 0px no-repeat; } +.emoji-1F1F3-1F1EE { background: url(emoji.png) -3480px 0px no-repeat; } +.emoji-1F1F3-1F1F1 { background: url(emoji.png) -3500px 0px no-repeat; } +.emoji-1F1F3-1F1F4 { background: url(emoji.png) -3520px 0px no-repeat; } +.emoji-1F1F3-1F1F5 { background: url(emoji.png) -3540px 0px no-repeat; } +.emoji-1F1F3-1F1F7 { background: url(emoji.png) -3560px 0px no-repeat; } +.emoji-1F1F3-1F1FA { background: url(emoji.png) -3580px 0px no-repeat; } +.emoji-1F1F3-1F1FF { background: url(emoji.png) -3600px 0px no-repeat; } +.emoji-1F1F4-1F1F2 { background: url(emoji.png) -3620px 0px no-repeat; } +.emoji-1F1F5-1F1E6 { background: url(emoji.png) -3640px 0px no-repeat; } +.emoji-1F1F5-1F1EA { background: url(emoji.png) -3660px 0px no-repeat; } +.emoji-1F1F5-1F1EB { background: url(emoji.png) -3680px 0px no-repeat; } +.emoji-1F1F5-1F1EC { background: url(emoji.png) -3700px 0px no-repeat; } +.emoji-1F1F5-1F1ED { background: url(emoji.png) -3720px 0px no-repeat; } +.emoji-1F1F5-1F1F0 { background: url(emoji.png) -3740px 0px no-repeat; } +.emoji-1F1F5-1F1F1 { background: url(emoji.png) -3760px 0px no-repeat; } +.emoji-1F1F5-1F1F7 { background: url(emoji.png) -3780px 0px no-repeat; } +.emoji-1F1F5-1F1F8 { background: url(emoji.png) -3800px 0px no-repeat; } +.emoji-1F1F5-1F1F9 { background: url(emoji.png) -3820px 0px no-repeat; } +.emoji-1F1F5-1F1FC { background: url(emoji.png) -3840px 0px no-repeat; } +.emoji-1F1F5-1F1FE { background: url(emoji.png) -3860px 0px no-repeat; } +.emoji-1F1F6-1F1E6 { background: url(emoji.png) -3880px 0px no-repeat; } +.emoji-1F1F7-1F1F4 { background: url(emoji.png) -3900px 0px no-repeat; } +.emoji-1F1F7-1F1F8 { background: url(emoji.png) -3920px 0px no-repeat; } +.emoji-1F1F7-1F1FA { background: url(emoji.png) -3940px 0px no-repeat; } +.emoji-1F1F7-1F1FC { background: url(emoji.png) -3960px 0px no-repeat; } +.emoji-1F1F8-1F1E6 { background: url(emoji.png) -3980px 0px no-repeat; } +.emoji-1F1F8-1F1E7 { background: url(emoji.png) -4000px 0px no-repeat; } +.emoji-1F1F8-1F1E8 { background: url(emoji.png) -4020px 0px no-repeat; } +.emoji-1F1F8-1F1E9 { background: url(emoji.png) -4040px 0px no-repeat; } +.emoji-1F1F8-1F1EA { background: url(emoji.png) -4060px 0px no-repeat; } +.emoji-1F1F8-1F1EC { background: url(emoji.png) -4080px 0px no-repeat; } +.emoji-1F1F8-1F1ED { background: url(emoji.png) -4100px 0px no-repeat; } +.emoji-1F1F8-1F1EE { background: url(emoji.png) -4120px 0px no-repeat; } +.emoji-1F1F8-1F1F0 { background: url(emoji.png) -4140px 0px no-repeat; } +.emoji-1F1F8-1F1F1 { background: url(emoji.png) -4160px 0px no-repeat; } +.emoji-1F1F8-1F1F2 { background: url(emoji.png) -4180px 0px no-repeat; } +.emoji-1F1F8-1F1F3 { background: url(emoji.png) -4200px 0px no-repeat; } +.emoji-1F1F8-1F1F4 { background: url(emoji.png) -4220px 0px no-repeat; } +.emoji-1F1F8-1F1F7 { background: url(emoji.png) -4240px 0px no-repeat; } +.emoji-1F1F8-1F1F9 { background: url(emoji.png) -4260px 0px no-repeat; } +.emoji-1F1F8-1F1FB { background: url(emoji.png) -4280px 0px no-repeat; } +.emoji-1F1F8-1F1FE { background: url(emoji.png) -4300px 0px no-repeat; } +.emoji-1F1F8-1F1FF { background: url(emoji.png) -4320px 0px no-repeat; } +.emoji-1F1F9-1F1E9 { background: url(emoji.png) -4340px 0px no-repeat; } +.emoji-1F1F9-1F1EC { background: url(emoji.png) -4360px 0px no-repeat; } +.emoji-1F1F9-1F1ED { background: url(emoji.png) -4380px 0px no-repeat; } +.emoji-1F1F9-1F1EF { background: url(emoji.png) -4400px 0px no-repeat; } +.emoji-1F1F9-1F1F1 { background: url(emoji.png) -4420px 0px no-repeat; } +.emoji-1F1F9-1F1F2 { background: url(emoji.png) -4440px 0px no-repeat; } +.emoji-1F1F9-1F1F3 { background: url(emoji.png) -4460px 0px no-repeat; } +.emoji-1F1F9-1F1F4 { background: url(emoji.png) -4480px 0px no-repeat; } +.emoji-1F1F9-1F1F7 { background: url(emoji.png) -4500px 0px no-repeat; } +.emoji-1F1F9-1F1F9 { background: url(emoji.png) -4520px 0px no-repeat; } +.emoji-1F1F9-1F1FB { background: url(emoji.png) -4540px 0px no-repeat; } +.emoji-1F1F9-1F1FC { background: url(emoji.png) -4560px 0px no-repeat; } +.emoji-1F1F9-1F1FF { background: url(emoji.png) -4580px 0px no-repeat; } +.emoji-1F1FA-1F1E6 { background: url(emoji.png) -4600px 0px no-repeat; } +.emoji-1F1FA-1F1EC { background: url(emoji.png) -4620px 0px no-repeat; } +.emoji-1F1FA-1F1F8 { background: url(emoji.png) -4640px 0px no-repeat; } +.emoji-1F1FA-1F1FE { background: url(emoji.png) -4660px 0px no-repeat; } +.emoji-1F1FA-1F1FF { background: url(emoji.png) -4680px 0px no-repeat; } +.emoji-1F1FB-1F1E6 { background: url(emoji.png) -4700px 0px no-repeat; } +.emoji-1F1FB-1F1E8 { background: url(emoji.png) -4720px 0px no-repeat; } +.emoji-1F1FB-1F1EA { background: url(emoji.png) -4740px 0px no-repeat; } +.emoji-1F1FB-1F1EE { background: url(emoji.png) -4760px 0px no-repeat; } +.emoji-1F1FB-1F1F3 { background: url(emoji.png) -4780px 0px no-repeat; } +.emoji-1F1FB-1F1FA { background: url(emoji.png) -4800px 0px no-repeat; } +.emoji-1F1FC-1F1EB { background: url(emoji.png) -4820px 0px no-repeat; } +.emoji-1F1FC-1F1F8 { background: url(emoji.png) -4840px 0px no-repeat; } +.emoji-1F1FD-1F1F0 { background: url(emoji.png) -4860px 0px no-repeat; } +.emoji-1F1FE-1F1EA { background: url(emoji.png) -4880px 0px no-repeat; } +.emoji-1F1FF-1F1E6 { background: url(emoji.png) -4900px 0px no-repeat; } +.emoji-1F1FF-1F1F2 { background: url(emoji.png) -4920px 0px no-repeat; } +.emoji-1F1FF-1F1FC { background: url(emoji.png) -4940px 0px no-repeat; } +.emoji-1F201 { background: url(emoji.png) -4960px 0px no-repeat; } +.emoji-1F202 { background: url(emoji.png) -4980px 0px no-repeat; } +.emoji-1F21A { background: url(emoji.png) -5000px 0px no-repeat; } +.emoji-1F22F { background: url(emoji.png) -5020px 0px no-repeat; } +.emoji-1F232 { background: url(emoji.png) -5040px 0px no-repeat; } +.emoji-1F233 { background: url(emoji.png) -5060px 0px no-repeat; } +.emoji-1F234 { background: url(emoji.png) -5080px 0px no-repeat; } +.emoji-1F235 { background: url(emoji.png) -5100px 0px no-repeat; } +.emoji-1F236 { background: url(emoji.png) -5120px 0px no-repeat; } +.emoji-1F237 { background: url(emoji.png) -5140px 0px no-repeat; } +.emoji-1F238 { background: url(emoji.png) -5160px 0px no-repeat; } +.emoji-1F239 { background: url(emoji.png) -5180px 0px no-repeat; } +.emoji-1F23A { background: url(emoji.png) -5200px 0px no-repeat; } +.emoji-1F250 { background: url(emoji.png) -5220px 0px no-repeat; } +.emoji-1F251 { background: url(emoji.png) -5240px 0px no-repeat; } +.emoji-1F300 { background: url(emoji.png) -5260px 0px no-repeat; } +.emoji-1F301 { background: url(emoji.png) -5280px 0px no-repeat; } +.emoji-1F302 { background: url(emoji.png) -5300px 0px no-repeat; } +.emoji-1F303 { background: url(emoji.png) -5320px 0px no-repeat; } +.emoji-1F304 { background: url(emoji.png) -5340px 0px no-repeat; } +.emoji-1F305 { background: url(emoji.png) -5360px 0px no-repeat; } +.emoji-1F306 { background: url(emoji.png) -5380px 0px no-repeat; } +.emoji-1F307 { background: url(emoji.png) -5400px 0px no-repeat; } +.emoji-1F308 { background: url(emoji.png) -5420px 0px no-repeat; } +.emoji-1F309 { background: url(emoji.png) -5440px 0px no-repeat; } +.emoji-1F30A { background: url(emoji.png) -5460px 0px no-repeat; } +.emoji-1F30B { background: url(emoji.png) -5480px 0px no-repeat; } +.emoji-1F30C { background: url(emoji.png) -5500px 0px no-repeat; } +.emoji-1F30D { background: url(emoji.png) -5520px 0px no-repeat; } +.emoji-1F30E { background: url(emoji.png) -5540px 0px no-repeat; } +.emoji-1F30F { background: url(emoji.png) -5560px 0px no-repeat; } +.emoji-1F310 { background: url(emoji.png) -5580px 0px no-repeat; } +.emoji-1F311 { background: url(emoji.png) -5600px 0px no-repeat; } +.emoji-1F312 { background: url(emoji.png) -5620px 0px no-repeat; } +.emoji-1F313 { background: url(emoji.png) -5640px 0px no-repeat; } +.emoji-1F314 { background: url(emoji.png) -5660px 0px no-repeat; } +.emoji-1F315 { background: url(emoji.png) -5680px 0px no-repeat; } +.emoji-1F316 { background: url(emoji.png) -5700px 0px no-repeat; } +.emoji-1F317 { background: url(emoji.png) -5720px 0px no-repeat; } +.emoji-1F318 { background: url(emoji.png) -5740px 0px no-repeat; } +.emoji-1F319 { background: url(emoji.png) -5760px 0px no-repeat; } +.emoji-1F31A { background: url(emoji.png) -5780px 0px no-repeat; } +.emoji-1F31B { background: url(emoji.png) -5800px 0px no-repeat; } +.emoji-1F31C { background: url(emoji.png) -5820px 0px no-repeat; } +.emoji-1F31D { background: url(emoji.png) -5840px 0px no-repeat; } +.emoji-1F31E { background: url(emoji.png) -5860px 0px no-repeat; } +.emoji-1F31F { background: url(emoji.png) -5880px 0px no-repeat; } +.emoji-1F320 { background: url(emoji.png) -5900px 0px no-repeat; } +.emoji-1F321 { background: url(emoji.png) -5920px 0px no-repeat; } +.emoji-1F327 { background: url(emoji.png) -5940px 0px no-repeat; } +.emoji-1F328 { background: url(emoji.png) -5960px 0px no-repeat; } +.emoji-1F329 { background: url(emoji.png) -5980px 0px no-repeat; } +.emoji-1F32A { background: url(emoji.png) -6000px 0px no-repeat; } +.emoji-1F32B { background: url(emoji.png) -6020px 0px no-repeat; } +.emoji-1F32C { background: url(emoji.png) -6040px 0px no-repeat; } +.emoji-1F330 { background: url(emoji.png) -6060px 0px no-repeat; } +.emoji-1F331 { background: url(emoji.png) -6080px 0px no-repeat; } +.emoji-1F332 { background: url(emoji.png) -6100px 0px no-repeat; } +.emoji-1F333 { background: url(emoji.png) -6120px 0px no-repeat; } +.emoji-1F334 { background: url(emoji.png) -6140px 0px no-repeat; } +.emoji-1F335 { background: url(emoji.png) -6160px 0px no-repeat; } +.emoji-1F336 { background: url(emoji.png) -6180px 0px no-repeat; } +.emoji-1F337 { background: url(emoji.png) -6200px 0px no-repeat; } +.emoji-1F338 { background: url(emoji.png) -6220px 0px no-repeat; } +.emoji-1F339 { background: url(emoji.png) -6240px 0px no-repeat; } +.emoji-1F33A { background: url(emoji.png) -6260px 0px no-repeat; } +.emoji-1F33B { background: url(emoji.png) -6280px 0px no-repeat; } +.emoji-1F33C { background: url(emoji.png) -6300px 0px no-repeat; } +.emoji-1F33D { background: url(emoji.png) -6320px 0px no-repeat; } +.emoji-1F33E { background: url(emoji.png) -6340px 0px no-repeat; } +.emoji-1F33F { background: url(emoji.png) -6360px 0px no-repeat; } +.emoji-1F340 { background: url(emoji.png) -6380px 0px no-repeat; } +.emoji-1F341 { background: url(emoji.png) -6400px 0px no-repeat; } +.emoji-1F342 { background: url(emoji.png) -6420px 0px no-repeat; } +.emoji-1F343 { background: url(emoji.png) -6440px 0px no-repeat; } +.emoji-1F344 { background: url(emoji.png) -6460px 0px no-repeat; } +.emoji-1F345 { background: url(emoji.png) -6480px 0px no-repeat; } +.emoji-1F346 { background: url(emoji.png) -6500px 0px no-repeat; } +.emoji-1F347 { background: url(emoji.png) -6520px 0px no-repeat; } +.emoji-1F348 { background: url(emoji.png) -6540px 0px no-repeat; } +.emoji-1F349 { background: url(emoji.png) -6560px 0px no-repeat; } +.emoji-1F34A { background: url(emoji.png) -6580px 0px no-repeat; } +.emoji-1F34B { background: url(emoji.png) -6600px 0px no-repeat; } +.emoji-1F34C { background: url(emoji.png) -6620px 0px no-repeat; } +.emoji-1F34D { background: url(emoji.png) -6640px 0px no-repeat; } +.emoji-1F34E { background: url(emoji.png) -6660px 0px no-repeat; } +.emoji-1F34F { background: url(emoji.png) -6680px 0px no-repeat; } +.emoji-1F350 { background: url(emoji.png) -6700px 0px no-repeat; } +.emoji-1F351 { background: url(emoji.png) -6720px 0px no-repeat; } +.emoji-1F352 { background: url(emoji.png) -6740px 0px no-repeat; } +.emoji-1F353 { background: url(emoji.png) -6760px 0px no-repeat; } +.emoji-1F354 { background: url(emoji.png) -6780px 0px no-repeat; } +.emoji-1F355 { background: url(emoji.png) -6800px 0px no-repeat; } +.emoji-1F356 { background: url(emoji.png) -6820px 0px no-repeat; } +.emoji-1F357 { background: url(emoji.png) -6840px 0px no-repeat; } +.emoji-1F358 { background: url(emoji.png) -6860px 0px no-repeat; } +.emoji-1F359 { background: url(emoji.png) -6880px 0px no-repeat; } +.emoji-1F35A { background: url(emoji.png) -6900px 0px no-repeat; } +.emoji-1F35B { background: url(emoji.png) -6920px 0px no-repeat; } +.emoji-1F35C { background: url(emoji.png) -6940px 0px no-repeat; } +.emoji-1F35D { background: url(emoji.png) -6960px 0px no-repeat; } +.emoji-1F35E { background: url(emoji.png) -6980px 0px no-repeat; } +.emoji-1F35F { background: url(emoji.png) -7000px 0px no-repeat; } +.emoji-1F360 { background: url(emoji.png) -7020px 0px no-repeat; } +.emoji-1F361 { background: url(emoji.png) -7040px 0px no-repeat; } +.emoji-1F362 { background: url(emoji.png) -7060px 0px no-repeat; } +.emoji-1F363 { background: url(emoji.png) -7080px 0px no-repeat; } +.emoji-1F364 { background: url(emoji.png) -7100px 0px no-repeat; } +.emoji-1F365 { background: url(emoji.png) -7120px 0px no-repeat; } +.emoji-1F366 { background: url(emoji.png) -7140px 0px no-repeat; } +.emoji-1F367 { background: url(emoji.png) -7160px 0px no-repeat; } +.emoji-1F368 { background: url(emoji.png) -7180px 0px no-repeat; } +.emoji-1F369 { background: url(emoji.png) -7200px 0px no-repeat; } +.emoji-1F36A { background: url(emoji.png) -7220px 0px no-repeat; } +.emoji-1F36B { background: url(emoji.png) -7240px 0px no-repeat; } +.emoji-1F36C { background: url(emoji.png) -7260px 0px no-repeat; } +.emoji-1F36D { background: url(emoji.png) -7280px 0px no-repeat; } +.emoji-1F36E { background: url(emoji.png) -7300px 0px no-repeat; } +.emoji-1F36F { background: url(emoji.png) -7320px 0px no-repeat; } +.emoji-1F370 { background: url(emoji.png) -7340px 0px no-repeat; } +.emoji-1F371 { background: url(emoji.png) -7360px 0px no-repeat; } +.emoji-1F372 { background: url(emoji.png) -7380px 0px no-repeat; } +.emoji-1F373 { background: url(emoji.png) -7400px 0px no-repeat; } +.emoji-1F374 { background: url(emoji.png) -7420px 0px no-repeat; } +.emoji-1F375 { background: url(emoji.png) -7440px 0px no-repeat; } +.emoji-1F376 { background: url(emoji.png) -7460px 0px no-repeat; } +.emoji-1F377 { background: url(emoji.png) -7480px 0px no-repeat; } +.emoji-1F378 { background: url(emoji.png) -7500px 0px no-repeat; } +.emoji-1F379 { background: url(emoji.png) -7520px 0px no-repeat; } +.emoji-1F37A { background: url(emoji.png) -7540px 0px no-repeat; } +.emoji-1F37B { background: url(emoji.png) -7560px 0px no-repeat; } +.emoji-1F37C { background: url(emoji.png) -7580px 0px no-repeat; } +.emoji-1F37D { background: url(emoji.png) -7600px 0px no-repeat; } +.emoji-1F380 { background: url(emoji.png) -7620px 0px no-repeat; } +.emoji-1F381 { background: url(emoji.png) -7640px 0px no-repeat; } +.emoji-1F382 { background: url(emoji.png) -7660px 0px no-repeat; } +.emoji-1F383 { background: url(emoji.png) -7680px 0px no-repeat; } +.emoji-1F384 { background: url(emoji.png) -7700px 0px no-repeat; } +.emoji-1F385 { background: url(emoji.png) -7720px 0px no-repeat; } +.emoji-1F386 { background: url(emoji.png) -7740px 0px no-repeat; } +.emoji-1F387 { background: url(emoji.png) -7760px 0px no-repeat; } +.emoji-1F388 { background: url(emoji.png) -7780px 0px no-repeat; } +.emoji-1F389 { background: url(emoji.png) -7800px 0px no-repeat; } +.emoji-1F38A { background: url(emoji.png) -7820px 0px no-repeat; } +.emoji-1F38B { background: url(emoji.png) -7840px 0px no-repeat; } +.emoji-1F38C { background: url(emoji.png) -7860px 0px no-repeat; } +.emoji-1F38D { background: url(emoji.png) -7880px 0px no-repeat; } +.emoji-1F38E { background: url(emoji.png) -7900px 0px no-repeat; } +.emoji-1F38F { background: url(emoji.png) -7920px 0px no-repeat; } +.emoji-1F390 { background: url(emoji.png) -7940px 0px no-repeat; } +.emoji-1F391 { background: url(emoji.png) -7960px 0px no-repeat; } +.emoji-1F392 { background: url(emoji.png) -7980px 0px no-repeat; } +.emoji-1F393 { background: url(emoji.png) -8000px 0px no-repeat; } +.emoji-1F394 { background: url(emoji.png) -8020px 0px no-repeat; } +.emoji-1F395 { background: url(emoji.png) -8040px 0px no-repeat; } +.emoji-1F396 { background: url(emoji.png) -8060px 0px no-repeat; } +.emoji-1F397 { background: url(emoji.png) -8080px 0px no-repeat; } +.emoji-1F398 { background: url(emoji.png) -8100px 0px no-repeat; } +.emoji-1F399 { background: url(emoji.png) -8120px 0px no-repeat; } +.emoji-1F39A { background: url(emoji.png) -8140px 0px no-repeat; } +.emoji-1F39B { background: url(emoji.png) -8160px 0px no-repeat; } +.emoji-1F39C { background: url(emoji.png) -8180px 0px no-repeat; } +.emoji-1F39D { background: url(emoji.png) -8200px 0px no-repeat; } +.emoji-1F39E { background: url(emoji.png) -8220px 0px no-repeat; } +.emoji-1F39F { background: url(emoji.png) -8240px 0px no-repeat; } +.emoji-1F3A0 { background: url(emoji.png) -8260px 0px no-repeat; } +.emoji-1F3A1 { background: url(emoji.png) -8280px 0px no-repeat; } +.emoji-1F3A2 { background: url(emoji.png) -8300px 0px no-repeat; } +.emoji-1F3A3 { background: url(emoji.png) -8320px 0px no-repeat; } +.emoji-1F3A4 { background: url(emoji.png) -8340px 0px no-repeat; } +.emoji-1F3A5 { background: url(emoji.png) -8360px 0px no-repeat; } +.emoji-1F3A6 { background: url(emoji.png) -8380px 0px no-repeat; } +.emoji-1F3A7 { background: url(emoji.png) -8400px 0px no-repeat; } +.emoji-1F3A8 { background: url(emoji.png) -8420px 0px no-repeat; } +.emoji-1F3A9 { background: url(emoji.png) -8440px 0px no-repeat; } +.emoji-1F3AA { background: url(emoji.png) -8460px 0px no-repeat; } +.emoji-1F3AB { background: url(emoji.png) -8480px 0px no-repeat; } +.emoji-1F3AC { background: url(emoji.png) -8500px 0px no-repeat; } +.emoji-1F3AD { background: url(emoji.png) -8520px 0px no-repeat; } +.emoji-1F3AE { background: url(emoji.png) -8540px 0px no-repeat; } +.emoji-1F3AF { background: url(emoji.png) -8560px 0px no-repeat; } +.emoji-1F3B0 { background: url(emoji.png) -8580px 0px no-repeat; } +.emoji-1F3B1 { background: url(emoji.png) -8600px 0px no-repeat; } +.emoji-1F3B2 { background: url(emoji.png) -8620px 0px no-repeat; } +.emoji-1F3B3 { background: url(emoji.png) -8640px 0px no-repeat; } +.emoji-1F3B4 { background: url(emoji.png) -8660px 0px no-repeat; } +.emoji-1F3B5 { background: url(emoji.png) -8680px 0px no-repeat; } +.emoji-1F3B6 { background: url(emoji.png) -8700px 0px no-repeat; } +.emoji-1F3B7 { background: url(emoji.png) -8720px 0px no-repeat; } +.emoji-1F3B8 { background: url(emoji.png) -8740px 0px no-repeat; } +.emoji-1F3B9 { background: url(emoji.png) -8760px 0px no-repeat; } +.emoji-1F3BA { background: url(emoji.png) -8780px 0px no-repeat; } +.emoji-1F3BB { background: url(emoji.png) -8800px 0px no-repeat; } +.emoji-1F3BC { background: url(emoji.png) -8820px 0px no-repeat; } +.emoji-1F3BD { background: url(emoji.png) -8840px 0px no-repeat; } +.emoji-1F3BE { background: url(emoji.png) -8860px 0px no-repeat; } +.emoji-1F3BF { background: url(emoji.png) -8880px 0px no-repeat; } +.emoji-1F3C0 { background: url(emoji.png) -8900px 0px no-repeat; } +.emoji-1F3C1 { background: url(emoji.png) -8920px 0px no-repeat; } +.emoji-1F3C2 { background: url(emoji.png) -8940px 0px no-repeat; } +.emoji-1F3C3 { background: url(emoji.png) -8960px 0px no-repeat; } +.emoji-1F3C4 { background: url(emoji.png) -8980px 0px no-repeat; } +.emoji-1F3C5 { background: url(emoji.png) -9000px 0px no-repeat; } +.emoji-1F3C6 { background: url(emoji.png) -9020px 0px no-repeat; } +.emoji-1F3C7 { background: url(emoji.png) -9040px 0px no-repeat; } +.emoji-1F3C8 { background: url(emoji.png) -9060px 0px no-repeat; } +.emoji-1F3C9 { background: url(emoji.png) -9080px 0px no-repeat; } +.emoji-1F3CA { background: url(emoji.png) -9100px 0px no-repeat; } +.emoji-1F3CB { background: url(emoji.png) -9120px 0px no-repeat; } +.emoji-1F3CC { background: url(emoji.png) -9140px 0px no-repeat; } +.emoji-1F3CD { background: url(emoji.png) -9160px 0px no-repeat; } +.emoji-1F3CE { background: url(emoji.png) -9180px 0px no-repeat; } +.emoji-1F3D4 { background: url(emoji.png) -9200px 0px no-repeat; } +.emoji-1F3D5 { background: url(emoji.png) -9220px 0px no-repeat; } +.emoji-1F3D6 { background: url(emoji.png) -9240px 0px no-repeat; } +.emoji-1F3D7 { background: url(emoji.png) -9260px 0px no-repeat; } +.emoji-1F3D8 { background: url(emoji.png) -9280px 0px no-repeat; } +.emoji-1F3D9 { background: url(emoji.png) -9300px 0px no-repeat; } +.emoji-1F3DA { background: url(emoji.png) -9320px 0px no-repeat; } +.emoji-1F3DB { background: url(emoji.png) -9340px 0px no-repeat; } +.emoji-1F3DC { background: url(emoji.png) -9360px 0px no-repeat; } +.emoji-1F3DD { background: url(emoji.png) -9380px 0px no-repeat; } +.emoji-1F3DE { background: url(emoji.png) -9400px 0px no-repeat; } +.emoji-1F3DF { background: url(emoji.png) -9420px 0px no-repeat; } +.emoji-1F3E0 { background: url(emoji.png) -9440px 0px no-repeat; } +.emoji-1F3E1 { background: url(emoji.png) -9460px 0px no-repeat; } +.emoji-1F3E2 { background: url(emoji.png) -9480px 0px no-repeat; } +.emoji-1F3E3 { background: url(emoji.png) -9500px 0px no-repeat; } +.emoji-1F3E4 { background: url(emoji.png) -9520px 0px no-repeat; } +.emoji-1F3E5 { background: url(emoji.png) -9540px 0px no-repeat; } +.emoji-1F3E6 { background: url(emoji.png) -9560px 0px no-repeat; } +.emoji-1F3E7 { background: url(emoji.png) -9580px 0px no-repeat; } +.emoji-1F3E8 { background: url(emoji.png) -9600px 0px no-repeat; } +.emoji-1F3E9 { background: url(emoji.png) -9620px 0px no-repeat; } +.emoji-1F3EA { background: url(emoji.png) -9640px 0px no-repeat; } +.emoji-1F3EB { background: url(emoji.png) -9660px 0px no-repeat; } +.emoji-1F3EC { background: url(emoji.png) -9680px 0px no-repeat; } +.emoji-1F3ED { background: url(emoji.png) -9700px 0px no-repeat; } +.emoji-1F3EE { background: url(emoji.png) -9720px 0px no-repeat; } +.emoji-1F3EF { background: url(emoji.png) -9740px 0px no-repeat; } +.emoji-1F3F0 { background: url(emoji.png) -9760px 0px no-repeat; } +.emoji-1F3F1 { background: url(emoji.png) -9780px 0px no-repeat; } +.emoji-1F3F2 { background: url(emoji.png) -9800px 0px no-repeat; } +.emoji-1F3F3 { background: url(emoji.png) -9820px 0px no-repeat; } +.emoji-1F3F4 { background: url(emoji.png) -9840px 0px no-repeat; } +.emoji-1F3F5 { background: url(emoji.png) -9860px 0px no-repeat; } +.emoji-1F3F6 { background: url(emoji.png) -9880px 0px no-repeat; } +.emoji-1F3F7 { background: url(emoji.png) -9900px 0px no-repeat; } +.emoji-1F400 { background: url(emoji.png) -9920px 0px no-repeat; } +.emoji-1F401 { background: url(emoji.png) -9940px 0px no-repeat; } +.emoji-1F402 { background: url(emoji.png) -9960px 0px no-repeat; } +.emoji-1F403 { background: url(emoji.png) -9980px 0px no-repeat; } +.emoji-1F404 { background: url(emoji.png) -10000px 0px no-repeat; } +.emoji-1F405 { background: url(emoji.png) -10020px 0px no-repeat; } +.emoji-1F406 { background: url(emoji.png) -10040px 0px no-repeat; } +.emoji-1F407 { background: url(emoji.png) -10060px 0px no-repeat; } +.emoji-1F408 { background: url(emoji.png) -10080px 0px no-repeat; } +.emoji-1F409 { background: url(emoji.png) -10100px 0px no-repeat; } +.emoji-1F40A { background: url(emoji.png) -10120px 0px no-repeat; } +.emoji-1F40B { background: url(emoji.png) -10140px 0px no-repeat; } +.emoji-1F40C { background: url(emoji.png) -10160px 0px no-repeat; } +.emoji-1F40D { background: url(emoji.png) -10180px 0px no-repeat; } +.emoji-1F40E { background: url(emoji.png) -10200px 0px no-repeat; } +.emoji-1F40F { background: url(emoji.png) -10220px 0px no-repeat; } +.emoji-1F410 { background: url(emoji.png) -10240px 0px no-repeat; } +.emoji-1F411 { background: url(emoji.png) -10260px 0px no-repeat; } +.emoji-1F412 { background: url(emoji.png) -10280px 0px no-repeat; } +.emoji-1F413 { background: url(emoji.png) -10300px 0px no-repeat; } +.emoji-1F414 { background: url(emoji.png) -10320px 0px no-repeat; } +.emoji-1F415 { background: url(emoji.png) -10340px 0px no-repeat; } +.emoji-1F416 { background: url(emoji.png) -10360px 0px no-repeat; } +.emoji-1F417 { background: url(emoji.png) -10380px 0px no-repeat; } +.emoji-1F418 { background: url(emoji.png) -10400px 0px no-repeat; } +.emoji-1F419 { background: url(emoji.png) -10420px 0px no-repeat; } +.emoji-1F41A { background: url(emoji.png) -10440px 0px no-repeat; } +.emoji-1F41B { background: url(emoji.png) -10460px 0px no-repeat; } +.emoji-1F41C { background: url(emoji.png) -10480px 0px no-repeat; } +.emoji-1F41D { background: url(emoji.png) -10500px 0px no-repeat; } +.emoji-1F41E { background: url(emoji.png) -10520px 0px no-repeat; } +.emoji-1F41F { background: url(emoji.png) -10540px 0px no-repeat; } +.emoji-1F420 { background: url(emoji.png) -10560px 0px no-repeat; } +.emoji-1F421 { background: url(emoji.png) -10580px 0px no-repeat; } +.emoji-1F422 { background: url(emoji.png) -10600px 0px no-repeat; } +.emoji-1F423 { background: url(emoji.png) -10620px 0px no-repeat; } +.emoji-1F424 { background: url(emoji.png) -10640px 0px no-repeat; } +.emoji-1F425 { background: url(emoji.png) -10660px 0px no-repeat; } +.emoji-1F426 { background: url(emoji.png) -10680px 0px no-repeat; } +.emoji-1F427 { background: url(emoji.png) -10700px 0px no-repeat; } +.emoji-1F428 { background: url(emoji.png) -10720px 0px no-repeat; } +.emoji-1F429 { background: url(emoji.png) -10740px 0px no-repeat; } +.emoji-1F42A { background: url(emoji.png) -10760px 0px no-repeat; } +.emoji-1F42B { background: url(emoji.png) -10780px 0px no-repeat; } +.emoji-1F42C { background: url(emoji.png) -10800px 0px no-repeat; } +.emoji-1F42D { background: url(emoji.png) -10820px 0px no-repeat; } +.emoji-1F42E { background: url(emoji.png) -10840px 0px no-repeat; } +.emoji-1F42F { background: url(emoji.png) -10860px 0px no-repeat; } +.emoji-1F430 { background: url(emoji.png) -10880px 0px no-repeat; } +.emoji-1F431 { background: url(emoji.png) -10900px 0px no-repeat; } +.emoji-1F432 { background: url(emoji.png) -10920px 0px no-repeat; } +.emoji-1F433 { background: url(emoji.png) -10940px 0px no-repeat; } +.emoji-1F434 { background: url(emoji.png) -10960px 0px no-repeat; } +.emoji-1F435 { background: url(emoji.png) -10980px 0px no-repeat; } +.emoji-1F436 { background: url(emoji.png) -11000px 0px no-repeat; } +.emoji-1F437 { background: url(emoji.png) -11020px 0px no-repeat; } +.emoji-1F438 { background: url(emoji.png) -11040px 0px no-repeat; } +.emoji-1F439 { background: url(emoji.png) -11060px 0px no-repeat; } +.emoji-1F43A { background: url(emoji.png) -11080px 0px no-repeat; } +.emoji-1F43B { background: url(emoji.png) -11100px 0px no-repeat; } +.emoji-1F43C { background: url(emoji.png) -11120px 0px no-repeat; } +.emoji-1F43D { background: url(emoji.png) -11140px 0px no-repeat; } +.emoji-1F43E { background: url(emoji.png) -11160px 0px no-repeat; } +.emoji-1F43F { background: url(emoji.png) -11180px 0px no-repeat; } +.emoji-1F440 { background: url(emoji.png) -11200px 0px no-repeat; } +.emoji-1F441 { background: url(emoji.png) -11220px 0px no-repeat; } +.emoji-1F442 { background: url(emoji.png) -11240px 0px no-repeat; } +.emoji-1F443 { background: url(emoji.png) -11260px 0px no-repeat; } +.emoji-1F444 { background: url(emoji.png) -11280px 0px no-repeat; } +.emoji-1F445 { background: url(emoji.png) -11300px 0px no-repeat; } +.emoji-1F446 { background: url(emoji.png) -11320px 0px no-repeat; } +.emoji-1F447 { background: url(emoji.png) -11340px 0px no-repeat; } +.emoji-1F448 { background: url(emoji.png) -11360px 0px no-repeat; } +.emoji-1F449 { background: url(emoji.png) -11380px 0px no-repeat; } +.emoji-1F44A { background: url(emoji.png) -11400px 0px no-repeat; } +.emoji-1F44B { background: url(emoji.png) -11420px 0px no-repeat; } +.emoji-1F44C { background: url(emoji.png) -11440px 0px no-repeat; } +.emoji-1F44D { background: url(emoji.png) -11460px 0px no-repeat; } +.emoji-1F44E { background: url(emoji.png) -11480px 0px no-repeat; } +.emoji-1F44F { background: url(emoji.png) -11500px 0px no-repeat; } +.emoji-1F450 { background: url(emoji.png) -11520px 0px no-repeat; } +.emoji-1F451 { background: url(emoji.png) -11540px 0px no-repeat; } +.emoji-1F452 { background: url(emoji.png) -11560px 0px no-repeat; } +.emoji-1F453 { background: url(emoji.png) -11580px 0px no-repeat; } +.emoji-1F454 { background: url(emoji.png) -11600px 0px no-repeat; } +.emoji-1F455 { background: url(emoji.png) -11620px 0px no-repeat; } +.emoji-1F456 { background: url(emoji.png) -11640px 0px no-repeat; } +.emoji-1F457 { background: url(emoji.png) -11660px 0px no-repeat; } +.emoji-1F458 { background: url(emoji.png) -11680px 0px no-repeat; } +.emoji-1F459 { background: url(emoji.png) -11700px 0px no-repeat; } +.emoji-1F45A { background: url(emoji.png) -11720px 0px no-repeat; } +.emoji-1F45B { background: url(emoji.png) -11740px 0px no-repeat; } +.emoji-1F45C { background: url(emoji.png) -11760px 0px no-repeat; } +.emoji-1F45D { background: url(emoji.png) -11780px 0px no-repeat; } +.emoji-1F45E { background: url(emoji.png) -11800px 0px no-repeat; } +.emoji-1F45F { background: url(emoji.png) -11820px 0px no-repeat; } +.emoji-1F460 { background: url(emoji.png) -11840px 0px no-repeat; } +.emoji-1F461 { background: url(emoji.png) -11860px 0px no-repeat; } +.emoji-1F462 { background: url(emoji.png) -11880px 0px no-repeat; } +.emoji-1F463 { background: url(emoji.png) -11900px 0px no-repeat; } +.emoji-1F464 { background: url(emoji.png) -11920px 0px no-repeat; } +.emoji-1F465 { background: url(emoji.png) -11940px 0px no-repeat; } +.emoji-1F466 { background: url(emoji.png) -11960px 0px no-repeat; } +.emoji-1F467 { background: url(emoji.png) -11980px 0px no-repeat; } +.emoji-1F468 { background: url(emoji.png) -12000px 0px no-repeat; } +.emoji-1F468-1F468-1F466 { background: url(emoji.png) -12020px 0px no-repeat; } +.emoji-1F468-1F468-1F466-1F466 { background: url(emoji.png) -12040px 0px no-repeat; } +.emoji-1F468-1F468-1F467 { background: url(emoji.png) -12060px 0px no-repeat; } +.emoji-1F468-1F468-1F467-1F466 { background: url(emoji.png) -12080px 0px no-repeat; } +.emoji-1F468-1F468-1F467-1F467 { background: url(emoji.png) -12100px 0px no-repeat; } +.emoji-1F468-1F469-1F466-1F466 { background: url(emoji.png) -12120px 0px no-repeat; } +.emoji-1F468-1F469-1F467 { background: url(emoji.png) -12140px 0px no-repeat; } +.emoji-1F468-1F469-1F467-1F466 { background: url(emoji.png) -12160px 0px no-repeat; } +.emoji-1F468-1F469-1F467-1F467 { background: url(emoji.png) -12180px 0px no-repeat; } +.emoji-1F468-2764-1F468 { background: url(emoji.png) -12200px 0px no-repeat; } +.emoji-1F468-2764-1F48B-1F468 { background: url(emoji.png) -12220px 0px no-repeat; } +.emoji-1F469 { background: url(emoji.png) -12240px 0px no-repeat; } +.emoji-1F469-1F469-1F466 { background: url(emoji.png) -12260px 0px no-repeat; } +.emoji-1F469-1F469-1F466-1F466 { background: url(emoji.png) -12280px 0px no-repeat; } +.emoji-1F469-1F469-1F467 { background: url(emoji.png) -12300px 0px no-repeat; } +.emoji-1F469-1F469-1F467-1F466 { background: url(emoji.png) -12320px 0px no-repeat; } +.emoji-1F469-1F469-1F467-1F467 { background: url(emoji.png) -12340px 0px no-repeat; } +.emoji-1F469-2764-1F469 { background: url(emoji.png) -12360px 0px no-repeat; } +.emoji-1F469-2764-1F48B-1F469 { background: url(emoji.png) -12380px 0px no-repeat; } +.emoji-1F46A { background: url(emoji.png) -12400px 0px no-repeat; } +.emoji-1F46B { background: url(emoji.png) -12420px 0px no-repeat; } +.emoji-1F46C { background: url(emoji.png) -12440px 0px no-repeat; } +.emoji-1F46D { background: url(emoji.png) -12460px 0px no-repeat; } +.emoji-1F46E { background: url(emoji.png) -12480px 0px no-repeat; } +.emoji-1F46F { background: url(emoji.png) -12500px 0px no-repeat; } +.emoji-1F470 { background: url(emoji.png) -12520px 0px no-repeat; } +.emoji-1F471 { background: url(emoji.png) -12540px 0px no-repeat; } +.emoji-1F472 { background: url(emoji.png) -12560px 0px no-repeat; } +.emoji-1F473 { background: url(emoji.png) -12580px 0px no-repeat; } +.emoji-1F474 { background: url(emoji.png) -12600px 0px no-repeat; } +.emoji-1F475 { background: url(emoji.png) -12620px 0px no-repeat; } +.emoji-1F476 { background: url(emoji.png) -12640px 0px no-repeat; } +.emoji-1F477 { background: url(emoji.png) -12660px 0px no-repeat; } +.emoji-1F478 { background: url(emoji.png) -12680px 0px no-repeat; } +.emoji-1F479 { background: url(emoji.png) -12700px 0px no-repeat; } +.emoji-1F47A { background: url(emoji.png) -12720px 0px no-repeat; } +.emoji-1F47B { background: url(emoji.png) -12740px 0px no-repeat; } +.emoji-1F47C { background: url(emoji.png) -12760px 0px no-repeat; } +.emoji-1F47D { background: url(emoji.png) -12780px 0px no-repeat; } +.emoji-1F47E { background: url(emoji.png) -12800px 0px no-repeat; } +.emoji-1F47F { background: url(emoji.png) -12820px 0px no-repeat; } +.emoji-1F480 { background: url(emoji.png) -12840px 0px no-repeat; } +.emoji-1F481 { background: url(emoji.png) -12860px 0px no-repeat; } +.emoji-1F482 { background: url(emoji.png) -12880px 0px no-repeat; } +.emoji-1F483 { background: url(emoji.png) -12900px 0px no-repeat; } +.emoji-1F484 { background: url(emoji.png) -12920px 0px no-repeat; } +.emoji-1F485 { background: url(emoji.png) -12940px 0px no-repeat; } +.emoji-1F486 { background: url(emoji.png) -12960px 0px no-repeat; } +.emoji-1F487 { background: url(emoji.png) -12980px 0px no-repeat; } +.emoji-1F488 { background: url(emoji.png) -13000px 0px no-repeat; } +.emoji-1F489 { background: url(emoji.png) -13020px 0px no-repeat; } +.emoji-1F48A { background: url(emoji.png) -13040px 0px no-repeat; } +.emoji-1F48B { background: url(emoji.png) -13060px 0px no-repeat; } +.emoji-1F48C { background: url(emoji.png) -13080px 0px no-repeat; } +.emoji-1F48D { background: url(emoji.png) -13100px 0px no-repeat; } +.emoji-1F48E { background: url(emoji.png) -13120px 0px no-repeat; } +.emoji-1F48F { background: url(emoji.png) -13140px 0px no-repeat; } +.emoji-1F490 { background: url(emoji.png) -13160px 0px no-repeat; } +.emoji-1F491 { background: url(emoji.png) -13180px 0px no-repeat; } +.emoji-1F492 { background: url(emoji.png) -13200px 0px no-repeat; } +.emoji-1F493 { background: url(emoji.png) -13220px 0px no-repeat; } +.emoji-1F494 { background: url(emoji.png) -13240px 0px no-repeat; } +.emoji-1F495 { background: url(emoji.png) -13260px 0px no-repeat; } +.emoji-1F496 { background: url(emoji.png) -13280px 0px no-repeat; } +.emoji-1F497 { background: url(emoji.png) -13300px 0px no-repeat; } +.emoji-1F498 { background: url(emoji.png) -13320px 0px no-repeat; } +.emoji-1F499 { background: url(emoji.png) -13340px 0px no-repeat; } +.emoji-1F49A { background: url(emoji.png) -13360px 0px no-repeat; } +.emoji-1F49B { background: url(emoji.png) -13380px 0px no-repeat; } +.emoji-1F49C { background: url(emoji.png) -13400px 0px no-repeat; } +.emoji-1F49D { background: url(emoji.png) -13420px 0px no-repeat; } +.emoji-1F49E { background: url(emoji.png) -13440px 0px no-repeat; } +.emoji-1F49F { background: url(emoji.png) -13460px 0px no-repeat; } +.emoji-1F4A0 { background: url(emoji.png) -13480px 0px no-repeat; } +.emoji-1F4A1 { background: url(emoji.png) -13500px 0px no-repeat; } +.emoji-1F4A2 { background: url(emoji.png) -13520px 0px no-repeat; } +.emoji-1F4A3 { background: url(emoji.png) -13540px 0px no-repeat; } +.emoji-1F4A4 { background: url(emoji.png) -13560px 0px no-repeat; } +.emoji-1F4A5 { background: url(emoji.png) -13580px 0px no-repeat; } +.emoji-1F4A6 { background: url(emoji.png) -13600px 0px no-repeat; } +.emoji-1F4A7 { background: url(emoji.png) -13620px 0px no-repeat; } +.emoji-1F4A8 { background: url(emoji.png) -13640px 0px no-repeat; } +.emoji-1F4A9 { background: url(emoji.png) -13660px 0px no-repeat; } +.emoji-1F4AA { background: url(emoji.png) -13680px 0px no-repeat; } +.emoji-1F4AB { background: url(emoji.png) -13700px 0px no-repeat; } +.emoji-1F4AC { background: url(emoji.png) -13720px 0px no-repeat; } +.emoji-1F4AD { background: url(emoji.png) -13740px 0px no-repeat; } +.emoji-1F4AE { background: url(emoji.png) -13760px 0px no-repeat; } +.emoji-1F4AF { background: url(emoji.png) -13780px 0px no-repeat; } +.emoji-1F4B0 { background: url(emoji.png) -13800px 0px no-repeat; } +.emoji-1F4B1 { background: url(emoji.png) -13820px 0px no-repeat; } +.emoji-1F4B2 { background: url(emoji.png) -13840px 0px no-repeat; } +.emoji-1F4B3 { background: url(emoji.png) -13860px 0px no-repeat; } +.emoji-1F4B4 { background: url(emoji.png) -13880px 0px no-repeat; } +.emoji-1F4B5 { background: url(emoji.png) -13900px 0px no-repeat; } +.emoji-1F4B6 { background: url(emoji.png) -13920px 0px no-repeat; } +.emoji-1F4B7 { background: url(emoji.png) -13940px 0px no-repeat; } +.emoji-1F4B8 { background: url(emoji.png) -13960px 0px no-repeat; } +.emoji-1F4B9 { background: url(emoji.png) -13980px 0px no-repeat; } +.emoji-1F4BA { background: url(emoji.png) -14000px 0px no-repeat; } +.emoji-1F4BB { background: url(emoji.png) -14020px 0px no-repeat; } +.emoji-1F4BC { background: url(emoji.png) -14040px 0px no-repeat; } +.emoji-1F4BD { background: url(emoji.png) -14060px 0px no-repeat; } +.emoji-1F4BE { background: url(emoji.png) -14080px 0px no-repeat; } +.emoji-1F4BF { background: url(emoji.png) -14100px 0px no-repeat; } +.emoji-1F4C0 { background: url(emoji.png) -14120px 0px no-repeat; } +.emoji-1F4C1 { background: url(emoji.png) -14140px 0px no-repeat; } +.emoji-1F4C2 { background: url(emoji.png) -14160px 0px no-repeat; } +.emoji-1F4C3 { background: url(emoji.png) -14180px 0px no-repeat; } +.emoji-1F4C4 { background: url(emoji.png) -14200px 0px no-repeat; } +.emoji-1F4C5 { background: url(emoji.png) -14220px 0px no-repeat; } +.emoji-1F4C6 { background: url(emoji.png) -14240px 0px no-repeat; } +.emoji-1F4C7 { background: url(emoji.png) -14260px 0px no-repeat; } +.emoji-1F4C8 { background: url(emoji.png) -14280px 0px no-repeat; } +.emoji-1F4C9 { background: url(emoji.png) -14300px 0px no-repeat; } +.emoji-1F4CA { background: url(emoji.png) -14320px 0px no-repeat; } +.emoji-1F4CB { background: url(emoji.png) -14340px 0px no-repeat; } +.emoji-1F4CC { background: url(emoji.png) -14360px 0px no-repeat; } +.emoji-1F4CD { background: url(emoji.png) -14380px 0px no-repeat; } +.emoji-1F4CE { background: url(emoji.png) -14400px 0px no-repeat; } +.emoji-1F4CF { background: url(emoji.png) -14420px 0px no-repeat; } +.emoji-1F4D0 { background: url(emoji.png) -14440px 0px no-repeat; } +.emoji-1F4D1 { background: url(emoji.png) -14460px 0px no-repeat; } +.emoji-1F4D2 { background: url(emoji.png) -14480px 0px no-repeat; } +.emoji-1F4D3 { background: url(emoji.png) -14500px 0px no-repeat; } +.emoji-1F4D4 { background: url(emoji.png) -14520px 0px no-repeat; } +.emoji-1F4D5 { background: url(emoji.png) -14540px 0px no-repeat; } +.emoji-1F4D6 { background: url(emoji.png) -14560px 0px no-repeat; } +.emoji-1F4D7 { background: url(emoji.png) -14580px 0px no-repeat; } +.emoji-1F4D8 { background: url(emoji.png) -14600px 0px no-repeat; } +.emoji-1F4D9 { background: url(emoji.png) -14620px 0px no-repeat; } +.emoji-1F4DA { background: url(emoji.png) -14640px 0px no-repeat; } +.emoji-1F4DB { background: url(emoji.png) -14660px 0px no-repeat; } +.emoji-1F4DC { background: url(emoji.png) -14680px 0px no-repeat; } +.emoji-1F4DD { background: url(emoji.png) -14700px 0px no-repeat; } +.emoji-1F4DE { background: url(emoji.png) -14720px 0px no-repeat; } +.emoji-1F4DF { background: url(emoji.png) -14740px 0px no-repeat; } +.emoji-1F4E0 { background: url(emoji.png) -14760px 0px no-repeat; } +.emoji-1F4E1 { background: url(emoji.png) -14780px 0px no-repeat; } +.emoji-1F4E2 { background: url(emoji.png) -14800px 0px no-repeat; } +.emoji-1F4E3 { background: url(emoji.png) -14820px 0px no-repeat; } +.emoji-1F4E4 { background: url(emoji.png) -14840px 0px no-repeat; } +.emoji-1F4E5 { background: url(emoji.png) -14860px 0px no-repeat; } +.emoji-1F4E6 { background: url(emoji.png) -14880px 0px no-repeat; } +.emoji-1F4E7 { background: url(emoji.png) -14900px 0px no-repeat; } +.emoji-1F4E8 { background: url(emoji.png) -14920px 0px no-repeat; } +.emoji-1F4E9 { background: url(emoji.png) -14940px 0px no-repeat; } +.emoji-1F4EA { background: url(emoji.png) -14960px 0px no-repeat; } +.emoji-1F4EB { background: url(emoji.png) -14980px 0px no-repeat; } +.emoji-1F4EC { background: url(emoji.png) -15000px 0px no-repeat; } +.emoji-1F4ED { background: url(emoji.png) -15020px 0px no-repeat; } +.emoji-1F4EE { background: url(emoji.png) -15040px 0px no-repeat; } +.emoji-1F4EF { background: url(emoji.png) -15060px 0px no-repeat; } +.emoji-1F4F0 { background: url(emoji.png) -15080px 0px no-repeat; } +.emoji-1F4F1 { background: url(emoji.png) -15100px 0px no-repeat; } +.emoji-1F4F2 { background: url(emoji.png) -15120px 0px no-repeat; } +.emoji-1F4F3 { background: url(emoji.png) -15140px 0px no-repeat; } +.emoji-1F4F4 { background: url(emoji.png) -15160px 0px no-repeat; } +.emoji-1F4F5 { background: url(emoji.png) -15180px 0px no-repeat; } +.emoji-1F4F6 { background: url(emoji.png) -15200px 0px no-repeat; } +.emoji-1F4F7 { background: url(emoji.png) -15220px 0px no-repeat; } +.emoji-1F4F8 { background: url(emoji.png) -15240px 0px no-repeat; } +.emoji-1F4F9 { background: url(emoji.png) -15260px 0px no-repeat; } +.emoji-1F4FA { background: url(emoji.png) -15280px 0px no-repeat; } +.emoji-1F4FB { background: url(emoji.png) -15300px 0px no-repeat; } +.emoji-1F4FC { background: url(emoji.png) -15320px 0px no-repeat; } +.emoji-1F4FD { background: url(emoji.png) -15340px 0px no-repeat; } +.emoji-1F4FE { background: url(emoji.png) -15360px 0px no-repeat; } +.emoji-1F500 { background: url(emoji.png) -15380px 0px no-repeat; } +.emoji-1F501 { background: url(emoji.png) -15400px 0px no-repeat; } +.emoji-1F502 { background: url(emoji.png) -15420px 0px no-repeat; } +.emoji-1F503 { background: url(emoji.png) -15440px 0px no-repeat; } +.emoji-1F504 { background: url(emoji.png) -15460px 0px no-repeat; } +.emoji-1F505 { background: url(emoji.png) -15480px 0px no-repeat; } +.emoji-1F506 { background: url(emoji.png) -15500px 0px no-repeat; } +.emoji-1F507 { background: url(emoji.png) -15520px 0px no-repeat; } +.emoji-1F508 { background: url(emoji.png) -15540px 0px no-repeat; } +.emoji-1F509 { background: url(emoji.png) -15560px 0px no-repeat; } +.emoji-1F50A { background: url(emoji.png) -15580px 0px no-repeat; } +.emoji-1F50B { background: url(emoji.png) -15600px 0px no-repeat; } +.emoji-1F50C { background: url(emoji.png) -15620px 0px no-repeat; } +.emoji-1F50D { background: url(emoji.png) -15640px 0px no-repeat; } +.emoji-1F50E { background: url(emoji.png) -15660px 0px no-repeat; } +.emoji-1F50F { background: url(emoji.png) -15680px 0px no-repeat; } +.emoji-1F510 { background: url(emoji.png) -15700px 0px no-repeat; } +.emoji-1F511 { background: url(emoji.png) -15720px 0px no-repeat; } +.emoji-1F512 { background: url(emoji.png) -15740px 0px no-repeat; } +.emoji-1F513 { background: url(emoji.png) -15760px 0px no-repeat; } +.emoji-1F514 { background: url(emoji.png) -15780px 0px no-repeat; } +.emoji-1F515 { background: url(emoji.png) -15800px 0px no-repeat; } +.emoji-1F516 { background: url(emoji.png) -15820px 0px no-repeat; } +.emoji-1F517 { background: url(emoji.png) -15840px 0px no-repeat; } +.emoji-1F518 { background: url(emoji.png) -15860px 0px no-repeat; } +.emoji-1F519 { background: url(emoji.png) -15880px 0px no-repeat; } +.emoji-1F51A { background: url(emoji.png) -15900px 0px no-repeat; } +.emoji-1F51B { background: url(emoji.png) -15920px 0px no-repeat; } +.emoji-1F51C { background: url(emoji.png) -15940px 0px no-repeat; } +.emoji-1F51D { background: url(emoji.png) -15960px 0px no-repeat; } +.emoji-1F51E { background: url(emoji.png) -15980px 0px no-repeat; } +.emoji-1F51F { background: url(emoji.png) -16000px 0px no-repeat; } +.emoji-1F520 { background: url(emoji.png) -16020px 0px no-repeat; } +.emoji-1F521 { background: url(emoji.png) -16040px 0px no-repeat; } +.emoji-1F522 { background: url(emoji.png) -16060px 0px no-repeat; } +.emoji-1F523 { background: url(emoji.png) -16080px 0px no-repeat; } +.emoji-1F524 { background: url(emoji.png) -16100px 0px no-repeat; } +.emoji-1F525 { background: url(emoji.png) -16120px 0px no-repeat; } +.emoji-1F526 { background: url(emoji.png) -16140px 0px no-repeat; } +.emoji-1F527 { background: url(emoji.png) -16160px 0px no-repeat; } +.emoji-1F528 { background: url(emoji.png) -16180px 0px no-repeat; } +.emoji-1F529 { background: url(emoji.png) -16200px 0px no-repeat; } +.emoji-1F52A { background: url(emoji.png) -16220px 0px no-repeat; } +.emoji-1F52B { background: url(emoji.png) -16240px 0px no-repeat; } +.emoji-1F52C { background: url(emoji.png) -16260px 0px no-repeat; } +.emoji-1F52D { background: url(emoji.png) -16280px 0px no-repeat; } +.emoji-1F52E { background: url(emoji.png) -16300px 0px no-repeat; } +.emoji-1F52F { background: url(emoji.png) -16320px 0px no-repeat; } +.emoji-1F530 { background: url(emoji.png) -16340px 0px no-repeat; } +.emoji-1F531 { background: url(emoji.png) -16360px 0px no-repeat; } +.emoji-1F532 { background: url(emoji.png) -16380px 0px no-repeat; } +.emoji-1F533 { background: url(emoji.png) -16400px 0px no-repeat; } +.emoji-1F534 { background: url(emoji.png) -16420px 0px no-repeat; } +.emoji-1F535 { background: url(emoji.png) -16440px 0px no-repeat; } +.emoji-1F536 { background: url(emoji.png) -16460px 0px no-repeat; } +.emoji-1F537 { background: url(emoji.png) -16480px 0px no-repeat; } +.emoji-1F538 { background: url(emoji.png) -16500px 0px no-repeat; } +.emoji-1F539 { background: url(emoji.png) -16520px 0px no-repeat; } +.emoji-1F53A { background: url(emoji.png) -16540px 0px no-repeat; } +.emoji-1F53B { background: url(emoji.png) -16560px 0px no-repeat; } +.emoji-1F53C { background: url(emoji.png) -16580px 0px no-repeat; } +.emoji-1F53D { background: url(emoji.png) -16600px 0px no-repeat; } +.emoji-1F546 { background: url(emoji.png) -16620px 0px no-repeat; } +.emoji-1F547 { background: url(emoji.png) -16640px 0px no-repeat; } +.emoji-1F548 { background: url(emoji.png) -16660px 0px no-repeat; } +.emoji-1F549 { background: url(emoji.png) -16680px 0px no-repeat; } +.emoji-1F54A { background: url(emoji.png) -16700px 0px no-repeat; } +.emoji-1F550 { background: url(emoji.png) -16720px 0px no-repeat; } +.emoji-1F551 { background: url(emoji.png) -16740px 0px no-repeat; } +.emoji-1F552 { background: url(emoji.png) -16760px 0px no-repeat; } +.emoji-1F553 { background: url(emoji.png) -16780px 0px no-repeat; } +.emoji-1F554 { background: url(emoji.png) -16800px 0px no-repeat; } +.emoji-1F555 { background: url(emoji.png) -16820px 0px no-repeat; } +.emoji-1F556 { background: url(emoji.png) -16840px 0px no-repeat; } +.emoji-1F557 { background: url(emoji.png) -16860px 0px no-repeat; } +.emoji-1F558 { background: url(emoji.png) -16880px 0px no-repeat; } +.emoji-1F559 { background: url(emoji.png) -16900px 0px no-repeat; } +.emoji-1F55A { background: url(emoji.png) -16920px 0px no-repeat; } +.emoji-1F55B { background: url(emoji.png) -16940px 0px no-repeat; } +.emoji-1F55C { background: url(emoji.png) -16960px 0px no-repeat; } +.emoji-1F55D { background: url(emoji.png) -16980px 0px no-repeat; } +.emoji-1F55E { background: url(emoji.png) -17000px 0px no-repeat; } +.emoji-1F55F { background: url(emoji.png) -17020px 0px no-repeat; } +.emoji-1F560 { background: url(emoji.png) -17040px 0px no-repeat; } +.emoji-1F561 { background: url(emoji.png) -17060px 0px no-repeat; } +.emoji-1F562 { background: url(emoji.png) -17080px 0px no-repeat; } +.emoji-1F563 { background: url(emoji.png) -17100px 0px no-repeat; } +.emoji-1F564 { background: url(emoji.png) -17120px 0px no-repeat; } +.emoji-1F565 { background: url(emoji.png) -17140px 0px no-repeat; } +.emoji-1F566 { background: url(emoji.png) -17160px 0px no-repeat; } +.emoji-1F567 { background: url(emoji.png) -17180px 0px no-repeat; } +.emoji-1F568 { background: url(emoji.png) -17200px 0px no-repeat; } +.emoji-1F569 { background: url(emoji.png) -17220px 0px no-repeat; } +.emoji-1F56A { background: url(emoji.png) -17240px 0px no-repeat; } +.emoji-1F56B { background: url(emoji.png) -17260px 0px no-repeat; } +.emoji-1F56C { background: url(emoji.png) -17280px 0px no-repeat; } +.emoji-1F56D { background: url(emoji.png) -17300px 0px no-repeat; } +.emoji-1F56E { background: url(emoji.png) -17320px 0px no-repeat; } +.emoji-1F56F { background: url(emoji.png) -17340px 0px no-repeat; } +.emoji-1F570 { background: url(emoji.png) -17360px 0px no-repeat; } +.emoji-1F571 { background: url(emoji.png) -17380px 0px no-repeat; } +.emoji-1F572 { background: url(emoji.png) -17400px 0px no-repeat; } +.emoji-1F573 { background: url(emoji.png) -17420px 0px no-repeat; } +.emoji-1F574 { background: url(emoji.png) -17440px 0px no-repeat; } +.emoji-1F575 { background: url(emoji.png) -17460px 0px no-repeat; } +.emoji-1F576 { background: url(emoji.png) -17480px 0px no-repeat; } +.emoji-1F577 { background: url(emoji.png) -17500px 0px no-repeat; } +.emoji-1F578 { background: url(emoji.png) -17520px 0px no-repeat; } +.emoji-1F579 { background: url(emoji.png) -17540px 0px no-repeat; } +.emoji-1F57B { background: url(emoji.png) -17560px 0px no-repeat; } +.emoji-1F57E { background: url(emoji.png) -17580px 0px no-repeat; } +.emoji-1F57F { background: url(emoji.png) -17600px 0px no-repeat; } +.emoji-1F581 { background: url(emoji.png) -17620px 0px no-repeat; } +.emoji-1F582 { background: url(emoji.png) -17640px 0px no-repeat; } +.emoji-1F583 { background: url(emoji.png) -17660px 0px no-repeat; } +.emoji-1F585 { background: url(emoji.png) -17680px 0px no-repeat; } +.emoji-1F586 { background: url(emoji.png) -17700px 0px no-repeat; } +.emoji-1F587 { background: url(emoji.png) -17720px 0px no-repeat; } +.emoji-1F588 { background: url(emoji.png) -17740px 0px no-repeat; } +.emoji-1F589 { background: url(emoji.png) -17760px 0px no-repeat; } +.emoji-1F58A { background: url(emoji.png) -17780px 0px no-repeat; } +.emoji-1F58B { background: url(emoji.png) -17800px 0px no-repeat; } +.emoji-1F58C { background: url(emoji.png) -17820px 0px no-repeat; } +.emoji-1F58D { background: url(emoji.png) -17840px 0px no-repeat; } +.emoji-1F58E { background: url(emoji.png) -17860px 0px no-repeat; } +.emoji-1F58F { background: url(emoji.png) -17880px 0px no-repeat; } +.emoji-1F590 { background: url(emoji.png) -17900px 0px no-repeat; } +.emoji-1F591 { background: url(emoji.png) -17920px 0px no-repeat; } +.emoji-1F592 { background: url(emoji.png) -17940px 0px no-repeat; } +.emoji-1F593 { background: url(emoji.png) -17960px 0px no-repeat; } +.emoji-1F594 { background: url(emoji.png) -17980px 0px no-repeat; } +.emoji-1F595 { background: url(emoji.png) -18000px 0px no-repeat; } +.emoji-1F596 { background: url(emoji.png) -18020px 0px no-repeat; } +.emoji-1F597 { background: url(emoji.png) -18040px 0px no-repeat; } +.emoji-1F598 { background: url(emoji.png) -18060px 0px no-repeat; } +.emoji-1F599 { background: url(emoji.png) -18080px 0px no-repeat; } +.emoji-1F59E { background: url(emoji.png) -18100px 0px no-repeat; } +.emoji-1F59F { background: url(emoji.png) -18120px 0px no-repeat; } +.emoji-1F5A5 { background: url(emoji.png) -18140px 0px no-repeat; } +.emoji-1F5A6 { background: url(emoji.png) -18160px 0px no-repeat; } +.emoji-1F5A7 { background: url(emoji.png) -18180px 0px no-repeat; } +.emoji-1F5A8 { background: url(emoji.png) -18200px 0px no-repeat; } +.emoji-1F5A9 { background: url(emoji.png) -18220px 0px no-repeat; } +.emoji-1F5AA { background: url(emoji.png) -18240px 0px no-repeat; } +.emoji-1F5AB { background: url(emoji.png) -18260px 0px no-repeat; } +.emoji-1F5AD { background: url(emoji.png) -18280px 0px no-repeat; } +.emoji-1F5AE { background: url(emoji.png) -18300px 0px no-repeat; } +.emoji-1F5AF { background: url(emoji.png) -18320px 0px no-repeat; } +.emoji-1F5B2 { background: url(emoji.png) -18340px 0px no-repeat; } +.emoji-1F5B3 { background: url(emoji.png) -18360px 0px no-repeat; } +.emoji-1F5B4 { background: url(emoji.png) -18380px 0px no-repeat; } +.emoji-1F5B8 { background: url(emoji.png) -18400px 0px no-repeat; } +.emoji-1F5B9 { background: url(emoji.png) -18420px 0px no-repeat; } +.emoji-1F5BC { background: url(emoji.png) -18440px 0px no-repeat; } +.emoji-1F5BD { background: url(emoji.png) -18460px 0px no-repeat; } +.emoji-1F5BE { background: url(emoji.png) -18480px 0px no-repeat; } +.emoji-1F5C0 { background: url(emoji.png) -18500px 0px no-repeat; } +.emoji-1F5C1 { background: url(emoji.png) -18520px 0px no-repeat; } +.emoji-1F5C2 { background: url(emoji.png) -18540px 0px no-repeat; } +.emoji-1F5C3 { background: url(emoji.png) -18560px 0px no-repeat; } +.emoji-1F5C4 { background: url(emoji.png) -18580px 0px no-repeat; } +.emoji-1F5C6 { background: url(emoji.png) -18600px 0px no-repeat; } +.emoji-1F5C7 { background: url(emoji.png) -18620px 0px no-repeat; } +.emoji-1F5C9 { background: url(emoji.png) -18640px 0px no-repeat; } +.emoji-1F5CA { background: url(emoji.png) -18660px 0px no-repeat; } +.emoji-1F5CE { background: url(emoji.png) -18680px 0px no-repeat; } +.emoji-1F5CF { background: url(emoji.png) -18700px 0px no-repeat; } +.emoji-1F5D0 { background: url(emoji.png) -18720px 0px no-repeat; } +.emoji-1F5D1 { background: url(emoji.png) -18740px 0px no-repeat; } +.emoji-1F5D2 { background: url(emoji.png) -18760px 0px no-repeat; } +.emoji-1F5D3 { background: url(emoji.png) -18780px 0px no-repeat; } +.emoji-1F5D4 { background: url(emoji.png) -18800px 0px no-repeat; } +.emoji-1F5D8 { background: url(emoji.png) -18820px 0px no-repeat; } +.emoji-1F5D9 { background: url(emoji.png) -18840px 0px no-repeat; } +.emoji-1F5DC { background: url(emoji.png) -18860px 0px no-repeat; } +.emoji-1F5DD { background: url(emoji.png) -18880px 0px no-repeat; } +.emoji-1F5DE { background: url(emoji.png) -18900px 0px no-repeat; } +.emoji-1F5E0 { background: url(emoji.png) -18920px 0px no-repeat; } +.emoji-1F5E1 { background: url(emoji.png) -18940px 0px no-repeat; } +.emoji-1F5E2 { background: url(emoji.png) -18960px 0px no-repeat; } +.emoji-1F5E3 { background: url(emoji.png) -18980px 0px no-repeat; } +.emoji-1F5E8 { background: url(emoji.png) -19000px 0px no-repeat; } +.emoji-1F5E9 { background: url(emoji.png) -19020px 0px no-repeat; } +.emoji-1F5EA { background: url(emoji.png) -19040px 0px no-repeat; } +.emoji-1F5EB { background: url(emoji.png) -19060px 0px no-repeat; } +.emoji-1F5EC { background: url(emoji.png) -19080px 0px no-repeat; } +.emoji-1F5ED { background: url(emoji.png) -19100px 0px no-repeat; } +.emoji-1F5EE { background: url(emoji.png) -19120px 0px no-repeat; } +.emoji-1F5EF { background: url(emoji.png) -19140px 0px no-repeat; } +.emoji-1F5F0 { background: url(emoji.png) -19160px 0px no-repeat; } +.emoji-1F5F1 { background: url(emoji.png) -19180px 0px no-repeat; } +.emoji-1F5F2 { background: url(emoji.png) -19200px 0px no-repeat; } +.emoji-1F5F3 { background: url(emoji.png) -19220px 0px no-repeat; } +.emoji-1F5F4 { background: url(emoji.png) -19240px 0px no-repeat; } +.emoji-1F5F5 { background: url(emoji.png) -19260px 0px no-repeat; } +.emoji-1F5F8 { background: url(emoji.png) -19280px 0px no-repeat; } +.emoji-1F5F9 { background: url(emoji.png) -19300px 0px no-repeat; } +.emoji-1F5FA { background: url(emoji.png) -19320px 0px no-repeat; } +.emoji-1F5FB { background: url(emoji.png) -19340px 0px no-repeat; } +.emoji-1F5FC { background: url(emoji.png) -19360px 0px no-repeat; } +.emoji-1F5FD { background: url(emoji.png) -19380px 0px no-repeat; } +.emoji-1F5FE { background: url(emoji.png) -19400px 0px no-repeat; } +.emoji-1F5FF { background: url(emoji.png) -19420px 0px no-repeat; } +.emoji-1F600 { background: url(emoji.png) -19440px 0px no-repeat; } +.emoji-1F601 { background: url(emoji.png) -19460px 0px no-repeat; } +.emoji-1F602 { background: url(emoji.png) -19480px 0px no-repeat; } +.emoji-1F603 { background: url(emoji.png) -19500px 0px no-repeat; } +.emoji-1F604 { background: url(emoji.png) -19520px 0px no-repeat; } +.emoji-1F605 { background: url(emoji.png) -19540px 0px no-repeat; } +.emoji-1F606 { background: url(emoji.png) -19560px 0px no-repeat; } +.emoji-1F607 { background: url(emoji.png) -19580px 0px no-repeat; } +.emoji-1F608 { background: url(emoji.png) -19600px 0px no-repeat; } +.emoji-1F609 { background: url(emoji.png) -19620px 0px no-repeat; } +.emoji-1F60A { background: url(emoji.png) -19640px 0px no-repeat; } +.emoji-1F60B { background: url(emoji.png) -19660px 0px no-repeat; } +.emoji-1F60C { background: url(emoji.png) -19680px 0px no-repeat; } +.emoji-1F60D { background: url(emoji.png) -19700px 0px no-repeat; } +.emoji-1F60E { background: url(emoji.png) -19720px 0px no-repeat; } +.emoji-1F60F { background: url(emoji.png) -19740px 0px no-repeat; } +.emoji-1F610 { background: url(emoji.png) -19760px 0px no-repeat; } +.emoji-1F611 { background: url(emoji.png) -19780px 0px no-repeat; } +.emoji-1F612 { background: url(emoji.png) -19800px 0px no-repeat; } +.emoji-1F613 { background: url(emoji.png) -19820px 0px no-repeat; } +.emoji-1F614 { background: url(emoji.png) -19840px 0px no-repeat; } +.emoji-1F615 { background: url(emoji.png) -19860px 0px no-repeat; } +.emoji-1F616 { background: url(emoji.png) -19880px 0px no-repeat; } +.emoji-1F617 { background: url(emoji.png) -19900px 0px no-repeat; } +.emoji-1F618 { background: url(emoji.png) -19920px 0px no-repeat; } +.emoji-1F619 { background: url(emoji.png) -19940px 0px no-repeat; } +.emoji-1F61A { background: url(emoji.png) -19960px 0px no-repeat; } +.emoji-1F61B { background: url(emoji.png) -19980px 0px no-repeat; } +.emoji-1F61C { background: url(emoji.png) -20000px 0px no-repeat; } +.emoji-1F61D { background: url(emoji.png) -20020px 0px no-repeat; } +.emoji-1F61E { background: url(emoji.png) -20040px 0px no-repeat; } +.emoji-1F61F { background: url(emoji.png) -20060px 0px no-repeat; } +.emoji-1F620 { background: url(emoji.png) -20080px 0px no-repeat; } +.emoji-1F621 { background: url(emoji.png) -20100px 0px no-repeat; } +.emoji-1F622 { background: url(emoji.png) -20120px 0px no-repeat; } +.emoji-1F623 { background: url(emoji.png) -20140px 0px no-repeat; } +.emoji-1F624 { background: url(emoji.png) -20160px 0px no-repeat; } +.emoji-1F625 { background: url(emoji.png) -20180px 0px no-repeat; } +.emoji-1F626 { background: url(emoji.png) -20200px 0px no-repeat; } +.emoji-1F627 { background: url(emoji.png) -20220px 0px no-repeat; } +.emoji-1F628 { background: url(emoji.png) -20240px 0px no-repeat; } +.emoji-1F629 { background: url(emoji.png) -20260px 0px no-repeat; } +.emoji-1F62A { background: url(emoji.png) -20280px 0px no-repeat; } +.emoji-1F62B { background: url(emoji.png) -20300px 0px no-repeat; } +.emoji-1F62C { background: url(emoji.png) -20320px 0px no-repeat; } +.emoji-1F62D { background: url(emoji.png) -20340px 0px no-repeat; } +.emoji-1F62E { background: url(emoji.png) -20360px 0px no-repeat; } +.emoji-1F62F { background: url(emoji.png) -20380px 0px no-repeat; } +.emoji-1F630 { background: url(emoji.png) -20400px 0px no-repeat; } +.emoji-1F631 { background: url(emoji.png) -20420px 0px no-repeat; } +.emoji-1F632 { background: url(emoji.png) -20440px 0px no-repeat; } +.emoji-1F633 { background: url(emoji.png) -20460px 0px no-repeat; } +.emoji-1F634 { background: url(emoji.png) -20480px 0px no-repeat; } +.emoji-1F635 { background: url(emoji.png) -20500px 0px no-repeat; } +.emoji-1F636 { background: url(emoji.png) -20520px 0px no-repeat; } +.emoji-1F637 { background: url(emoji.png) -20540px 0px no-repeat; } +.emoji-1F638 { background: url(emoji.png) -20560px 0px no-repeat; } +.emoji-1F639 { background: url(emoji.png) -20580px 0px no-repeat; } +.emoji-1F63A { background: url(emoji.png) -20600px 0px no-repeat; } +.emoji-1F63B { background: url(emoji.png) -20620px 0px no-repeat; } +.emoji-1F63C { background: url(emoji.png) -20640px 0px no-repeat; } +.emoji-1F63D { background: url(emoji.png) -20660px 0px no-repeat; } +.emoji-1F63E { background: url(emoji.png) -20680px 0px no-repeat; } +.emoji-1F63F { background: url(emoji.png) -20700px 0px no-repeat; } +.emoji-1F640 { background: url(emoji.png) -20720px 0px no-repeat; } +.emoji-1F641 { background: url(emoji.png) -20740px 0px no-repeat; } +.emoji-1F642 { background: url(emoji.png) -20760px 0px no-repeat; } +.emoji-1F645 { background: url(emoji.png) -20780px 0px no-repeat; } +.emoji-1F646 { background: url(emoji.png) -20800px 0px no-repeat; } +.emoji-1F647 { background: url(emoji.png) -20820px 0px no-repeat; } +.emoji-1F648 { background: url(emoji.png) -20840px 0px no-repeat; } +.emoji-1F649 { background: url(emoji.png) -20860px 0px no-repeat; } +.emoji-1F64A { background: url(emoji.png) -20880px 0px no-repeat; } +.emoji-1F64B { background: url(emoji.png) -20900px 0px no-repeat; } +.emoji-1F64C { background: url(emoji.png) -20920px 0px no-repeat; } +.emoji-1F64D { background: url(emoji.png) -20940px 0px no-repeat; } +.emoji-1F64E { background: url(emoji.png) -20960px 0px no-repeat; } +.emoji-1F64F { background: url(emoji.png) -20980px 0px no-repeat; } +.emoji-1F680 { background: url(emoji.png) -21000px 0px no-repeat; } +.emoji-1F681 { background: url(emoji.png) -21020px 0px no-repeat; } +.emoji-1F682 { background: url(emoji.png) -21040px 0px no-repeat; } +.emoji-1F683 { background: url(emoji.png) -21060px 0px no-repeat; } +.emoji-1F684 { background: url(emoji.png) -21080px 0px no-repeat; } +.emoji-1F685 { background: url(emoji.png) -21100px 0px no-repeat; } +.emoji-1F686 { background: url(emoji.png) -21120px 0px no-repeat; } +.emoji-1F687 { background: url(emoji.png) -21140px 0px no-repeat; } +.emoji-1F688 { background: url(emoji.png) -21160px 0px no-repeat; } +.emoji-1F689 { background: url(emoji.png) -21180px 0px no-repeat; } +.emoji-1F68A { background: url(emoji.png) -21200px 0px no-repeat; } +.emoji-1F68B { background: url(emoji.png) -21220px 0px no-repeat; } +.emoji-1F68C { background: url(emoji.png) -21240px 0px no-repeat; } +.emoji-1F68D { background: url(emoji.png) -21260px 0px no-repeat; } +.emoji-1F68E { background: url(emoji.png) -21280px 0px no-repeat; } +.emoji-1F68F { background: url(emoji.png) -21300px 0px no-repeat; } +.emoji-1F690 { background: url(emoji.png) -21320px 0px no-repeat; } +.emoji-1F691 { background: url(emoji.png) -21340px 0px no-repeat; } +.emoji-1F692 { background: url(emoji.png) -21360px 0px no-repeat; } +.emoji-1F693 { background: url(emoji.png) -21380px 0px no-repeat; } +.emoji-1F694 { background: url(emoji.png) -21400px 0px no-repeat; } +.emoji-1F695 { background: url(emoji.png) -21420px 0px no-repeat; } +.emoji-1F696 { background: url(emoji.png) -21440px 0px no-repeat; } +.emoji-1F697 { background: url(emoji.png) -21460px 0px no-repeat; } +.emoji-1F698 { background: url(emoji.png) -21480px 0px no-repeat; } +.emoji-1F699 { background: url(emoji.png) -21500px 0px no-repeat; } +.emoji-1F69A { background: url(emoji.png) -21520px 0px no-repeat; } +.emoji-1F69B { background: url(emoji.png) -21540px 0px no-repeat; } +.emoji-1F69C { background: url(emoji.png) -21560px 0px no-repeat; } +.emoji-1F69D { background: url(emoji.png) -21580px 0px no-repeat; } +.emoji-1F69E { background: url(emoji.png) -21600px 0px no-repeat; } +.emoji-1F69F { background: url(emoji.png) -21620px 0px no-repeat; } +.emoji-1F6A0 { background: url(emoji.png) -21640px 0px no-repeat; } +.emoji-1F6A1 { background: url(emoji.png) -21660px 0px no-repeat; } +.emoji-1F6A2 { background: url(emoji.png) -21680px 0px no-repeat; } +.emoji-1F6A3 { background: url(emoji.png) -21700px 0px no-repeat; } +.emoji-1F6A4 { background: url(emoji.png) -21720px 0px no-repeat; } +.emoji-1F6A5 { background: url(emoji.png) -21740px 0px no-repeat; } +.emoji-1F6A6 { background: url(emoji.png) -21760px 0px no-repeat; } +.emoji-1F6A7 { background: url(emoji.png) -21780px 0px no-repeat; } +.emoji-1F6A8 { background: url(emoji.png) -21800px 0px no-repeat; } +.emoji-1F6A9 { background: url(emoji.png) -21820px 0px no-repeat; } +.emoji-1F6AA { background: url(emoji.png) -21840px 0px no-repeat; } +.emoji-1F6AB { background: url(emoji.png) -21860px 0px no-repeat; } +.emoji-1F6AC { background: url(emoji.png) -21880px 0px no-repeat; } +.emoji-1F6AD { background: url(emoji.png) -21900px 0px no-repeat; } +.emoji-1F6AE { background: url(emoji.png) -21920px 0px no-repeat; } +.emoji-1F6AF { background: url(emoji.png) -21940px 0px no-repeat; } +.emoji-1F6B0 { background: url(emoji.png) -21960px 0px no-repeat; } +.emoji-1F6B1 { background: url(emoji.png) -21980px 0px no-repeat; } +.emoji-1F6B2 { background: url(emoji.png) -22000px 0px no-repeat; } +.emoji-1F6B3 { background: url(emoji.png) -22020px 0px no-repeat; } +.emoji-1F6B4 { background: url(emoji.png) -22040px 0px no-repeat; } +.emoji-1F6B5 { background: url(emoji.png) -22060px 0px no-repeat; } +.emoji-1F6B6 { background: url(emoji.png) -22080px 0px no-repeat; } +.emoji-1F6B7 { background: url(emoji.png) -22100px 0px no-repeat; } +.emoji-1F6B8 { background: url(emoji.png) -22120px 0px no-repeat; } +.emoji-1F6B9 { background: url(emoji.png) -22140px 0px no-repeat; } +.emoji-1F6BA { background: url(emoji.png) -22160px 0px no-repeat; } +.emoji-1F6BB { background: url(emoji.png) -22180px 0px no-repeat; } +.emoji-1F6BC { background: url(emoji.png) -22200px 0px no-repeat; } +.emoji-1F6BD { background: url(emoji.png) -22220px 0px no-repeat; } +.emoji-1F6BE { background: url(emoji.png) -22240px 0px no-repeat; } +.emoji-1F6BF { background: url(emoji.png) -22260px 0px no-repeat; } +.emoji-1F6C0 { background: url(emoji.png) -22280px 0px no-repeat; } +.emoji-1F6C1 { background: url(emoji.png) -22300px 0px no-repeat; } +.emoji-1F6C2 { background: url(emoji.png) -22320px 0px no-repeat; } +.emoji-1F6C3 { background: url(emoji.png) -22340px 0px no-repeat; } +.emoji-1F6C4 { background: url(emoji.png) -22360px 0px no-repeat; } +.emoji-1F6C5 { background: url(emoji.png) -22380px 0px no-repeat; } +.emoji-1F6C6 { background: url(emoji.png) -22400px 0px no-repeat; } +.emoji-1F6C7 { background: url(emoji.png) -22420px 0px no-repeat; } +.emoji-1F6C8 { background: url(emoji.png) -22440px 0px no-repeat; } +.emoji-1F6C9 { background: url(emoji.png) -22460px 0px no-repeat; } +.emoji-1F6CA { background: url(emoji.png) -22480px 0px no-repeat; } +.emoji-1F6CB { background: url(emoji.png) -22500px 0px no-repeat; } +.emoji-1F6CC { background: url(emoji.png) -22520px 0px no-repeat; } +.emoji-1F6CD { background: url(emoji.png) -22540px 0px no-repeat; } +.emoji-1F6CE { background: url(emoji.png) -22560px 0px no-repeat; } +.emoji-1F6CF { background: url(emoji.png) -22580px 0px no-repeat; } +.emoji-1F6E0 { background: url(emoji.png) -22600px 0px no-repeat; } +.emoji-1F6E1 { background: url(emoji.png) -22620px 0px no-repeat; } +.emoji-1F6E2 { background: url(emoji.png) -22640px 0px no-repeat; } +.emoji-1F6E3 { background: url(emoji.png) -22660px 0px no-repeat; } +.emoji-1F6E4 { background: url(emoji.png) -22680px 0px no-repeat; } +.emoji-1F6E5 { background: url(emoji.png) -22700px 0px no-repeat; } +.emoji-1F6E6 { background: url(emoji.png) -22720px 0px no-repeat; } +.emoji-1F6E7 { background: url(emoji.png) -22740px 0px no-repeat; } +.emoji-1F6E8 { background: url(emoji.png) -22760px 0px no-repeat; } +.emoji-1F6E9 { background: url(emoji.png) -22780px 0px no-repeat; } +.emoji-1F6EA { background: url(emoji.png) -22800px 0px no-repeat; } +.emoji-1F6EB { background: url(emoji.png) -22820px 0px no-repeat; } +.emoji-1F6EC { background: url(emoji.png) -22840px 0px no-repeat; } +.emoji-1F6F0 { background: url(emoji.png) -22860px 0px no-repeat; } +.emoji-1F6F1 { background: url(emoji.png) -22880px 0px no-repeat; } +.emoji-1F6F2 { background: url(emoji.png) -22900px 0px no-repeat; } +.emoji-1F6F3 { background: url(emoji.png) -22920px 0px no-repeat; } +.emoji-203C { background: url(emoji.png) -22940px 0px no-repeat; } +.emoji-2049 { background: url(emoji.png) -22960px 0px no-repeat; } +.emoji-2122 { background: url(emoji.png) -22980px 0px no-repeat; } +.emoji-2139 { background: url(emoji.png) -23000px 0px no-repeat; } +.emoji-2194 { background: url(emoji.png) -23020px 0px no-repeat; } +.emoji-2195 { background: url(emoji.png) -23040px 0px no-repeat; } +.emoji-2196 { background: url(emoji.png) -23060px 0px no-repeat; } +.emoji-2197 { background: url(emoji.png) -23080px 0px no-repeat; } +.emoji-2198 { background: url(emoji.png) -23100px 0px no-repeat; } +.emoji-2199 { background: url(emoji.png) -23120px 0px no-repeat; } +.emoji-21A9 { background: url(emoji.png) -23140px 0px no-repeat; } +.emoji-21AA { background: url(emoji.png) -23160px 0px no-repeat; } +.emoji-231A { background: url(emoji.png) -23180px 0px no-repeat; } +.emoji-231B { background: url(emoji.png) -23200px 0px no-repeat; } +.emoji-23E9 { background: url(emoji.png) -23220px 0px no-repeat; } +.emoji-23EA { background: url(emoji.png) -23240px 0px no-repeat; } +.emoji-23EB { background: url(emoji.png) -23260px 0px no-repeat; } +.emoji-23EC { background: url(emoji.png) -23280px 0px no-repeat; } +.emoji-23F0 { background: url(emoji.png) -23300px 0px no-repeat; } +.emoji-23F3 { background: url(emoji.png) -23320px 0px no-repeat; } +.emoji-24C2 { background: url(emoji.png) -23340px 0px no-repeat; } +.emoji-25AA { background: url(emoji.png) -23360px 0px no-repeat; } +.emoji-25AB { background: url(emoji.png) -23380px 0px no-repeat; } +.emoji-25B6 { background: url(emoji.png) -23400px 0px no-repeat; } +.emoji-25C0 { background: url(emoji.png) -23420px 0px no-repeat; } +.emoji-25FB { background: url(emoji.png) -23440px 0px no-repeat; } +.emoji-25FC { background: url(emoji.png) -23460px 0px no-repeat; } +.emoji-25FD { background: url(emoji.png) -23480px 0px no-repeat; } +.emoji-25FE { background: url(emoji.png) -23500px 0px no-repeat; } +.emoji-2600 { background: url(emoji.png) -23520px 0px no-repeat; } +.emoji-2601 { background: url(emoji.png) -23540px 0px no-repeat; } +.emoji-260E { background: url(emoji.png) -23560px 0px no-repeat; } +.emoji-2611 { background: url(emoji.png) -23580px 0px no-repeat; } +.emoji-2614 { background: url(emoji.png) -23600px 0px no-repeat; } +.emoji-2615 { background: url(emoji.png) -23620px 0px no-repeat; } +.emoji-261D { background: url(emoji.png) -23640px 0px no-repeat; } +.emoji-263A { background: url(emoji.png) -23660px 0px no-repeat; } +.emoji-2648 { background: url(emoji.png) -23680px 0px no-repeat; } +.emoji-2649 { background: url(emoji.png) -23700px 0px no-repeat; } +.emoji-264A { background: url(emoji.png) -23720px 0px no-repeat; } +.emoji-264B { background: url(emoji.png) -23740px 0px no-repeat; } +.emoji-264C { background: url(emoji.png) -23760px 0px no-repeat; } +.emoji-264D { background: url(emoji.png) -23780px 0px no-repeat; } +.emoji-264E { background: url(emoji.png) -23800px 0px no-repeat; } +.emoji-264F { background: url(emoji.png) -23820px 0px no-repeat; } +.emoji-2650 { background: url(emoji.png) -23840px 0px no-repeat; } +.emoji-2651 { background: url(emoji.png) -23860px 0px no-repeat; } +.emoji-2652 { background: url(emoji.png) -23880px 0px no-repeat; } +.emoji-2653 { background: url(emoji.png) -23900px 0px no-repeat; } +.emoji-2660 { background: url(emoji.png) -23920px 0px no-repeat; } +.emoji-2663 { background: url(emoji.png) -23940px 0px no-repeat; } +.emoji-2665 { background: url(emoji.png) -23960px 0px no-repeat; } +.emoji-2666 { background: url(emoji.png) -23980px 0px no-repeat; } +.emoji-2668 { background: url(emoji.png) -24000px 0px no-repeat; } +.emoji-267B { background: url(emoji.png) -24020px 0px no-repeat; } +.emoji-267F { background: url(emoji.png) -24040px 0px no-repeat; } +.emoji-2693 { background: url(emoji.png) -24060px 0px no-repeat; } +.emoji-26A0 { background: url(emoji.png) -24080px 0px no-repeat; } +.emoji-26A1 { background: url(emoji.png) -24100px 0px no-repeat; } +.emoji-26AA { background: url(emoji.png) -24120px 0px no-repeat; } +.emoji-26AB { background: url(emoji.png) -24140px 0px no-repeat; } +.emoji-26BD { background: url(emoji.png) -24160px 0px no-repeat; } +.emoji-26BE { background: url(emoji.png) -24180px 0px no-repeat; } +.emoji-26C4 { background: url(emoji.png) -24200px 0px no-repeat; } +.emoji-26C5 { background: url(emoji.png) -24220px 0px no-repeat; } +.emoji-26CE { background: url(emoji.png) -24240px 0px no-repeat; } +.emoji-26D4 { background: url(emoji.png) -24260px 0px no-repeat; } +.emoji-26EA { background: url(emoji.png) -24280px 0px no-repeat; } +.emoji-26F2 { background: url(emoji.png) -24300px 0px no-repeat; } +.emoji-26F3 { background: url(emoji.png) -24320px 0px no-repeat; } +.emoji-26F5 { background: url(emoji.png) -24340px 0px no-repeat; } +.emoji-26FA { background: url(emoji.png) -24360px 0px no-repeat; } +.emoji-26FD { background: url(emoji.png) -24380px 0px no-repeat; } +.emoji-2702 { background: url(emoji.png) -24400px 0px no-repeat; } +.emoji-2705 { background: url(emoji.png) -24420px 0px no-repeat; } +.emoji-2708 { background: url(emoji.png) -24440px 0px no-repeat; } +.emoji-2709 { background: url(emoji.png) -24460px 0px no-repeat; } +.emoji-270A { background: url(emoji.png) -24480px 0px no-repeat; } +.emoji-270B { background: url(emoji.png) -24500px 0px no-repeat; } +.emoji-270C { background: url(emoji.png) -24520px 0px no-repeat; } +.emoji-270F { background: url(emoji.png) -24540px 0px no-repeat; } +.emoji-2712 { background: url(emoji.png) -24560px 0px no-repeat; } +.emoji-2714 { background: url(emoji.png) -24580px 0px no-repeat; } +.emoji-2716 { background: url(emoji.png) -24600px 0px no-repeat; } +.emoji-2728 { background: url(emoji.png) -24620px 0px no-repeat; } +.emoji-2733 { background: url(emoji.png) -24640px 0px no-repeat; } +.emoji-2734 { background: url(emoji.png) -24660px 0px no-repeat; } +.emoji-2744 { background: url(emoji.png) -24680px 0px no-repeat; } +.emoji-2747 { background: url(emoji.png) -24700px 0px no-repeat; } +.emoji-274C { background: url(emoji.png) -24720px 0px no-repeat; } +.emoji-274E { background: url(emoji.png) -24740px 0px no-repeat; } +.emoji-2753 { background: url(emoji.png) -24760px 0px no-repeat; } +.emoji-2754 { background: url(emoji.png) -24780px 0px no-repeat; } +.emoji-2755 { background: url(emoji.png) -24800px 0px no-repeat; } +.emoji-2757 { background: url(emoji.png) -24820px 0px no-repeat; } +.emoji-2764 { background: url(emoji.png) -24840px 0px no-repeat; } +.emoji-2795 { background: url(emoji.png) -24860px 0px no-repeat; } +.emoji-2796 { background: url(emoji.png) -24880px 0px no-repeat; } +.emoji-2797 { background: url(emoji.png) -24900px 0px no-repeat; } +.emoji-27A1 { background: url(emoji.png) -24920px 0px no-repeat; } +.emoji-27B0 { background: url(emoji.png) -24940px 0px no-repeat; } +.emoji-27BF { background: url(emoji.png) -24960px 0px no-repeat; } +.emoji-2934 { background: url(emoji.png) -24980px 0px no-repeat; } +.emoji-2935 { background: url(emoji.png) -25000px 0px no-repeat; } +.emoji-2B05 { background: url(emoji.png) -25020px 0px no-repeat; } +.emoji-2B06 { background: url(emoji.png) -25040px 0px no-repeat; } +.emoji-2B07 { background: url(emoji.png) -25060px 0px no-repeat; } +.emoji-2B1B { background: url(emoji.png) -25080px 0px no-repeat; } +.emoji-2B1C { background: url(emoji.png) -25100px 0px no-repeat; } +.emoji-2B50 { background: url(emoji.png) -25120px 0px no-repeat; } +.emoji-2B55 { background: url(emoji.png) -25140px 0px no-repeat; } +.emoji-3030 { background: url(emoji.png) -25160px 0px no-repeat; } +.emoji-303D { background: url(emoji.png) -25180px 0px no-repeat; } +.emoji-3297 { background: url(emoji.png) -25200px 0px no-repeat; } +.emoji-3299 { background: url(emoji.png) -25220px 0px no-repeat; } \ No newline at end of file diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 88b949a27ab..d560b3df17d 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -138,7 +138,6 @@ class Projects::NotesController < Projects::ApplicationController discussion_id: note.discussion_id, html: note_to_html(note), award: note.is_award, - emoji_path: note.is_award ? view_context.image_url(::AwardEmoji.path_to_emoji_image(note.note)) : "", note: note.note, discussion_html: note_to_discussion_html(note), discussion_with_diff_html: note_to_discussion_with_diff_html(note) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index e66b9c628c7..4373847ba7a 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -94,11 +94,11 @@ module IssuesHelper end.sort.to_sentence(last_word_connector: ', or ') end - def url_to_emoji(name) - emoji_path = ::AwardEmoji.path_to_emoji_image(name) - url_to_image(emoji_path) - rescue StandardError - "" + def emoji_icon(name, unicode = nil) + unicode ||= Emoji.emoji_filename(name) + + content_tag :div, "", class: "icon emoji-icon emoji-#{unicode}", + "data-emoji" => name, "data-unicode-name" => unicode end def emoji_author_list(notes, current_user) @@ -109,10 +109,6 @@ module IssuesHelper list.join(", ") end - def emoji_list - ::AwardEmoji::EMOJI_LIST - end - def note_active_class(notes, current_user) if current_user && notes.pluck(:author_id).include?(current_user.id) "active" diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml index 6071f1484c6..6c7f05c730c 100644 --- a/app/views/votes/_votes_block.html.haml +++ b/app/views/votes/_votes_block.html.haml @@ -1,18 +1,22 @@ .awards.votes-block - votable.notes.awards.grouped_awards.each do |emoji, notes| .award{class: (note_active_class(notes, current_user)), title: emoji_author_list(notes, current_user)} - .icon{"data-emoji" => "#{emoji}"} - = image_tag url_to_emoji(emoji), height: "20px", width: "20px" + = emoji_icon(emoji) .counter = notes.count - if current_user - .dropdown.awards-controls + .awards-controls %a.add-award{"data-toggle" => "dropdown", "data-target" => "#", "href" => "#"} = icon('smile-o') - %ul.dropdown-menu.awards-menu - - emoji_list.each do |emoji| - %li{"data-emoji" => "#{emoji}"}= image_tag url_to_emoji(emoji), height: "20px", width: "20px" + .emoji-menu + .emoji-menu-content + - AwardEmoji.emoji_by_category.each do |category, emojis| + %h4= AwardEmoji::CATEGORIES[category] + %ul + - emojis.each do |emoji| + %li + = emoji_icon(emoji["name"], emoji["unicode"]) - if current_user :coffeescript @@ -20,10 +24,16 @@ noteable_type = "#{votable.class.name.underscore}" noteable_id = "#{votable.id}" aliases = #{AwardEmoji::ALIASES.to_json} - window.awards_handler = new AwardsHandler(post_emoji_url, noteable_type, noteable_id, aliases) - $(".awards-menu li").click (e)-> - emoji = $(this).data("emoji") + window.awards_handler = new AwardsHandler( + post_emoji_url, + noteable_type, + noteable_id, + aliases + ) + + $(".emoji-menu-content li").click (e)-> + emoji = $(this).find(".emoji-icon").data("emoji") awards_handler.addAward(emoji) $(".awards").on "click", ".award", (e)-> @@ -31,3 +41,5 @@ awards_handler.addAward(emoji) $(".award").tooltip() + + $(".emoji-menu-content").niceScroll({cursorwidth: "7px"}) diff --git a/lib/award_emoji.rb b/lib/award_emoji.rb index 4d99164bc33..d3f98d2d7f0 100644 --- a/lib/award_emoji.rb +++ b/lib/award_emoji.rb @@ -1,11 +1,4 @@ class AwardEmoji - EMOJI_LIST = [ - "+1", "-1", "100", "blush", "heart", "smile", "rage", - "beers", "disappointed", "ok_hand", - "helicopter", "shit", "airplane", "alarm_clock", - "ambulance", "anguished", "two_hearts", "wink" - ] - ALIASES = { pout: "rage", satisfied: "laughing", @@ -37,11 +30,49 @@ class AwardEmoji squirrel: "shipit" }.with_indifferent_access - def self.path_to_emoji_image(name) - "emoji/#{Emoji.emoji_filename(name)}.png" + CATEGORIES = { + other: "Other", + objects: "Objects", + places: "Places", + travel_places: "Travel", + emoticons: "Emoticons", + objects_symbols: "Symbols", + nature: "Nature", + celebration: "Celebration", + people: "People", + activity: "Activity", + flags: "Flags", + food_drink: "Food" + }.with_indifferent_access + + def self.positions_by_name(name) + emoji = emojis_json.find do |emoji| + emoji["short_names"].include?(name) + end + + [emoji["sheet_x"], emoji["sheet_y"]] end def self.normilize_emoji_name(name) ALIASES[name] || name end + + def self.emoji_by_category + unless @emoji_by_category + @emoji_by_category = {} + emojis_added = [] + + Emoji.emojis.each do |emoji_name, data| + next if emojis_added.include?(data["name"]) + emojis_added << data["name"] + + @emoji_by_category[data["category"]] ||= [] + @emoji_by_category[data["category"]] << data + end + + @emoji_by_category = @emoji_by_category.sort.to_h + end + + @emoji_by_category + end end diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 1f2c4ee77b5..0fd96c7dc27 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -127,12 +127,6 @@ describe IssuesHelper do it { is_expected.to eq("!1, !2, or !3") } end - describe "#url_to_emoji" do - it "returns url" do - expect(url_to_emoji("smile")).to include("emoji/1F604.png") - end - end - describe "#emoji_list" do it "returns url" do expect(emoji_list).to be_kind_of(Array) -- cgit v1.2.1 From 4dd892b20b3bfd22a9dc69e095dfb1d2c141bcdb Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 22 Dec 2015 16:58:29 +0200 Subject: emoji css refactoring --- app/assets/stylesheets/pages/emojis.scss | 2529 +++++++++++++++--------------- 1 file changed, 1267 insertions(+), 1262 deletions(-) diff --git a/app/assets/stylesheets/pages/emojis.scss b/app/assets/stylesheets/pages/emojis.scss index d1a80b1ba48..819ec9a2f5f 100644 --- a/app/assets/stylesheets/pages/emojis.scss +++ b/app/assets/stylesheets/pages/emojis.scss @@ -3,1265 +3,1270 @@ File is generated by https://github.com/jakesgordon/sprite-factory and midified The source: gemojione gem. */ -.emoji-0023-20E3 { background: url(emoji.png) 0px 0px no-repeat; } -.emoji-0030-20E3 { background: url(emoji.png) -20px 0px no-repeat; } -.emoji-0031-20E3 { background: url(emoji.png) -40px 0px no-repeat; } -.emoji-0032-20E3 { background: url(emoji.png) -60px 0px no-repeat; } -.emoji-0033-20E3 { background: url(emoji.png) -80px 0px no-repeat; } -.emoji-0034-20E3 { background: url(emoji.png) -100px 0px no-repeat; } -.emoji-0035-20E3 { background: url(emoji.png) -120px 0px no-repeat; } -.emoji-0036-20E3 { background: url(emoji.png) -140px 0px no-repeat; } -.emoji-0037-20E3 { background: url(emoji.png) -160px 0px no-repeat; } -.emoji-0038-20E3 { background: url(emoji.png) -180px 0px no-repeat; } -.emoji-0039-20E3 { background: url(emoji.png) -200px 0px no-repeat; } -.emoji-00A9 { background: url(emoji.png) -220px 0px no-repeat; } -.emoji-00AE { background: url(emoji.png) -240px 0px no-repeat; } -.emoji-1F004 { background: url(emoji.png) -260px 0px no-repeat; } -.emoji-1F0CF { background: url(emoji.png) -280px 0px no-repeat; } -.emoji-1F170 { background: url(emoji.png) -300px 0px no-repeat; } -.emoji-1F171 { background: url(emoji.png) -320px 0px no-repeat; } -.emoji-1F17E { background: url(emoji.png) -340px 0px no-repeat; } -.emoji-1F17F { background: url(emoji.png) -360px 0px no-repeat; } -.emoji-1F18E { background: url(emoji.png) -380px 0px no-repeat; } -.emoji-1F191 { background: url(emoji.png) -400px 0px no-repeat; } -.emoji-1F192 { background: url(emoji.png) -420px 0px no-repeat; } -.emoji-1F193 { background: url(emoji.png) -440px 0px no-repeat; } -.emoji-1F194 { background: url(emoji.png) -460px 0px no-repeat; } -.emoji-1F195 { background: url(emoji.png) -480px 0px no-repeat; } -.emoji-1F196 { background: url(emoji.png) -500px 0px no-repeat; } -.emoji-1F197 { background: url(emoji.png) -520px 0px no-repeat; } -.emoji-1F198 { background: url(emoji.png) -540px 0px no-repeat; } -.emoji-1F199 { background: url(emoji.png) -560px 0px no-repeat; } -.emoji-1F19A { background: url(emoji.png) -580px 0px no-repeat; } -.emoji-1F1E6-1F1E8 { background: url(emoji.png) -600px 0px no-repeat; } -.emoji-1F1E6-1F1E9 { background: url(emoji.png) -620px 0px no-repeat; } -.emoji-1F1E6-1F1EA { background: url(emoji.png) -640px 0px no-repeat; } -.emoji-1F1E6-1F1EB { background: url(emoji.png) -660px 0px no-repeat; } -.emoji-1F1E6-1F1EC { background: url(emoji.png) -680px 0px no-repeat; } -.emoji-1F1E6-1F1EE { background: url(emoji.png) -700px 0px no-repeat; } -.emoji-1F1E6-1F1F1 { background: url(emoji.png) -720px 0px no-repeat; } -.emoji-1F1E6-1F1F2 { background: url(emoji.png) -740px 0px no-repeat; } -.emoji-1F1E6-1F1F4 { background: url(emoji.png) -760px 0px no-repeat; } -.emoji-1F1E6-1F1F7 { background: url(emoji.png) -780px 0px no-repeat; } -.emoji-1F1E6-1F1F9 { background: url(emoji.png) -800px 0px no-repeat; } -.emoji-1F1E6-1F1FA { background: url(emoji.png) -820px 0px no-repeat; } -.emoji-1F1E6-1F1FC { background: url(emoji.png) -840px 0px no-repeat; } -.emoji-1F1E6-1F1FF { background: url(emoji.png) -860px 0px no-repeat; } -.emoji-1F1E7-1F1E6 { background: url(emoji.png) -880px 0px no-repeat; } -.emoji-1F1E7-1F1E7 { background: url(emoji.png) -900px 0px no-repeat; } -.emoji-1F1E7-1F1E9 { background: url(emoji.png) -920px 0px no-repeat; } -.emoji-1F1E7-1F1EA { background: url(emoji.png) -940px 0px no-repeat; } -.emoji-1F1E7-1F1EB { background: url(emoji.png) -960px 0px no-repeat; } -.emoji-1F1E7-1F1EC { background: url(emoji.png) -980px 0px no-repeat; } -.emoji-1F1E7-1F1ED { background: url(emoji.png) -1000px 0px no-repeat; } -.emoji-1F1E7-1F1EE { background: url(emoji.png) -1020px 0px no-repeat; } -.emoji-1F1E7-1F1EF { background: url(emoji.png) -1040px 0px no-repeat; } -.emoji-1F1E7-1F1F2 { background: url(emoji.png) -1060px 0px no-repeat; } -.emoji-1F1E7-1F1F3 { background: url(emoji.png) -1080px 0px no-repeat; } -.emoji-1F1E7-1F1F4 { background: url(emoji.png) -1100px 0px no-repeat; } -.emoji-1F1E7-1F1F7 { background: url(emoji.png) -1120px 0px no-repeat; } -.emoji-1F1E7-1F1F8 { background: url(emoji.png) -1140px 0px no-repeat; } -.emoji-1F1E7-1F1F9 { background: url(emoji.png) -1160px 0px no-repeat; } -.emoji-1F1E7-1F1FC { background: url(emoji.png) -1180px 0px no-repeat; } -.emoji-1F1E7-1F1FE { background: url(emoji.png) -1200px 0px no-repeat; } -.emoji-1F1E7-1F1FF { background: url(emoji.png) -1220px 0px no-repeat; } -.emoji-1F1E8-1F1E6 { background: url(emoji.png) -1240px 0px no-repeat; } -.emoji-1F1E8-1F1E9 { background: url(emoji.png) -1260px 0px no-repeat; } -.emoji-1F1E8-1F1EB { background: url(emoji.png) -1280px 0px no-repeat; } -.emoji-1F1E8-1F1EC { background: url(emoji.png) -1300px 0px no-repeat; } -.emoji-1F1E8-1F1ED { background: url(emoji.png) -1320px 0px no-repeat; } -.emoji-1F1E8-1F1EE { background: url(emoji.png) -1340px 0px no-repeat; } -.emoji-1F1E8-1F1F1 { background: url(emoji.png) -1360px 0px no-repeat; } -.emoji-1F1E8-1F1F2 { background: url(emoji.png) -1380px 0px no-repeat; } -.emoji-1F1E8-1F1F3 { background: url(emoji.png) -1400px 0px no-repeat; } -.emoji-1F1E8-1F1F4 { background: url(emoji.png) -1420px 0px no-repeat; } -.emoji-1F1E8-1F1F7 { background: url(emoji.png) -1440px 0px no-repeat; } -.emoji-1F1E8-1F1FA { background: url(emoji.png) -1460px 0px no-repeat; } -.emoji-1F1E8-1F1FB { background: url(emoji.png) -1480px 0px no-repeat; } -.emoji-1F1E8-1F1FE { background: url(emoji.png) -1500px 0px no-repeat; } -.emoji-1F1E8-1F1FF { background: url(emoji.png) -1520px 0px no-repeat; } -.emoji-1F1E9-1F1EA { background: url(emoji.png) -1540px 0px no-repeat; } -.emoji-1F1E9-1F1EF { background: url(emoji.png) -1560px 0px no-repeat; } -.emoji-1F1E9-1F1F0 { background: url(emoji.png) -1580px 0px no-repeat; } -.emoji-1F1E9-1F1F2 { background: url(emoji.png) -1600px 0px no-repeat; } -.emoji-1F1E9-1F1F4 { background: url(emoji.png) -1620px 0px no-repeat; } -.emoji-1F1E9-1F1FF { background: url(emoji.png) -1640px 0px no-repeat; } -.emoji-1F1EA-1F1E8 { background: url(emoji.png) -1660px 0px no-repeat; } -.emoji-1F1EA-1F1EA { background: url(emoji.png) -1680px 0px no-repeat; } -.emoji-1F1EA-1F1EC { background: url(emoji.png) -1700px 0px no-repeat; } -.emoji-1F1EA-1F1ED { background: url(emoji.png) -1720px 0px no-repeat; } -.emoji-1F1EA-1F1F7 { background: url(emoji.png) -1740px 0px no-repeat; } -.emoji-1F1EA-1F1F8 { background: url(emoji.png) -1760px 0px no-repeat; } -.emoji-1F1EA-1F1F9 { background: url(emoji.png) -1780px 0px no-repeat; } -.emoji-1F1EB-1F1EE { background: url(emoji.png) -1800px 0px no-repeat; } -.emoji-1F1EB-1F1EF { background: url(emoji.png) -1820px 0px no-repeat; } -.emoji-1F1EB-1F1F0 { background: url(emoji.png) -1840px 0px no-repeat; } -.emoji-1F1EB-1F1F2 { background: url(emoji.png) -1860px 0px no-repeat; } -.emoji-1F1EB-1F1F4 { background: url(emoji.png) -1880px 0px no-repeat; } -.emoji-1F1EB-1F1F7 { background: url(emoji.png) -1900px 0px no-repeat; } -.emoji-1F1EC-1F1E6 { background: url(emoji.png) -1920px 0px no-repeat; } -.emoji-1F1EC-1F1E7 { background: url(emoji.png) -1940px 0px no-repeat; } -.emoji-1F1EC-1F1E9 { background: url(emoji.png) -1960px 0px no-repeat; } -.emoji-1F1EC-1F1EA { background: url(emoji.png) -1980px 0px no-repeat; } -.emoji-1F1EC-1F1ED { background: url(emoji.png) -2000px 0px no-repeat; } -.emoji-1F1EC-1F1EE { background: url(emoji.png) -2020px 0px no-repeat; } -.emoji-1F1EC-1F1F1 { background: url(emoji.png) -2040px 0px no-repeat; } -.emoji-1F1EC-1F1F2 { background: url(emoji.png) -2060px 0px no-repeat; } -.emoji-1F1EC-1F1F3 { background: url(emoji.png) -2080px 0px no-repeat; } -.emoji-1F1EC-1F1F6 { background: url(emoji.png) -2100px 0px no-repeat; } -.emoji-1F1EC-1F1F7 { background: url(emoji.png) -2120px 0px no-repeat; } -.emoji-1F1EC-1F1F9 { background: url(emoji.png) -2140px 0px no-repeat; } -.emoji-1F1EC-1F1FA { background: url(emoji.png) -2160px 0px no-repeat; } -.emoji-1F1EC-1F1FC { background: url(emoji.png) -2180px 0px no-repeat; } -.emoji-1F1EC-1F1FE { background: url(emoji.png) -2200px 0px no-repeat; } -.emoji-1F1ED-1F1F0 { background: url(emoji.png) -2220px 0px no-repeat; } -.emoji-1F1ED-1F1F3 { background: url(emoji.png) -2240px 0px no-repeat; } -.emoji-1F1ED-1F1F7 { background: url(emoji.png) -2260px 0px no-repeat; } -.emoji-1F1ED-1F1F9 { background: url(emoji.png) -2280px 0px no-repeat; } -.emoji-1F1ED-1F1FA { background: url(emoji.png) -2300px 0px no-repeat; } -.emoji-1F1EE-1F1E9 { background: url(emoji.png) -2320px 0px no-repeat; } -.emoji-1F1EE-1F1EA { background: url(emoji.png) -2340px 0px no-repeat; } -.emoji-1F1EE-1F1F1 { background: url(emoji.png) -2360px 0px no-repeat; } -.emoji-1F1EE-1F1F3 { background: url(emoji.png) -2380px 0px no-repeat; } -.emoji-1F1EE-1F1F6 { background: url(emoji.png) -2400px 0px no-repeat; } -.emoji-1F1EE-1F1F7 { background: url(emoji.png) -2420px 0px no-repeat; } -.emoji-1F1EE-1F1F8 { background: url(emoji.png) -2440px 0px no-repeat; } -.emoji-1F1EE-1F1F9 { background: url(emoji.png) -2460px 0px no-repeat; } -.emoji-1F1EF-1F1EA { background: url(emoji.png) -2480px 0px no-repeat; } -.emoji-1F1EF-1F1F2 { background: url(emoji.png) -2500px 0px no-repeat; } -.emoji-1F1EF-1F1F4 { background: url(emoji.png) -2520px 0px no-repeat; } -.emoji-1F1EF-1F1F5 { background: url(emoji.png) -2540px 0px no-repeat; } -.emoji-1F1F0-1F1EA { background: url(emoji.png) -2560px 0px no-repeat; } -.emoji-1F1F0-1F1EC { background: url(emoji.png) -2580px 0px no-repeat; } -.emoji-1F1F0-1F1ED { background: url(emoji.png) -2600px 0px no-repeat; } -.emoji-1F1F0-1F1EE { background: url(emoji.png) -2620px 0px no-repeat; } -.emoji-1F1F0-1F1F2 { background: url(emoji.png) -2640px 0px no-repeat; } -.emoji-1F1F0-1F1F3 { background: url(emoji.png) -2660px 0px no-repeat; } -.emoji-1F1F0-1F1F5 { background: url(emoji.png) -2680px 0px no-repeat; } -.emoji-1F1F0-1F1F7 { background: url(emoji.png) -2700px 0px no-repeat; } -.emoji-1F1F0-1F1FC { background: url(emoji.png) -2720px 0px no-repeat; } -.emoji-1F1F0-1F1FE { background: url(emoji.png) -2740px 0px no-repeat; } -.emoji-1F1F0-1F1FF { background: url(emoji.png) -2760px 0px no-repeat; } -.emoji-1F1F1-1F1E6 { background: url(emoji.png) -2780px 0px no-repeat; } -.emoji-1F1F1-1F1E7 { background: url(emoji.png) -2800px 0px no-repeat; } -.emoji-1F1F1-1F1E8 { background: url(emoji.png) -2820px 0px no-repeat; } -.emoji-1F1F1-1F1EE { background: url(emoji.png) -2840px 0px no-repeat; } -.emoji-1F1F1-1F1F0 { background: url(emoji.png) -2860px 0px no-repeat; } -.emoji-1F1F1-1F1F7 { background: url(emoji.png) -2880px 0px no-repeat; } -.emoji-1F1F1-1F1F8 { background: url(emoji.png) -2900px 0px no-repeat; } -.emoji-1F1F1-1F1F9 { background: url(emoji.png) -2920px 0px no-repeat; } -.emoji-1F1F1-1F1FA { background: url(emoji.png) -2940px 0px no-repeat; } -.emoji-1F1F1-1F1FB { background: url(emoji.png) -2960px 0px no-repeat; } -.emoji-1F1F1-1F1FE { background: url(emoji.png) -2980px 0px no-repeat; } -.emoji-1F1F2-1F1E6 { background: url(emoji.png) -3000px 0px no-repeat; } -.emoji-1F1F2-1F1E8 { background: url(emoji.png) -3020px 0px no-repeat; } -.emoji-1F1F2-1F1E9 { background: url(emoji.png) -3040px 0px no-repeat; } -.emoji-1F1F2-1F1EA { background: url(emoji.png) -3060px 0px no-repeat; } -.emoji-1F1F2-1F1EC { background: url(emoji.png) -3080px 0px no-repeat; } -.emoji-1F1F2-1F1ED { background: url(emoji.png) -3100px 0px no-repeat; } -.emoji-1F1F2-1F1F0 { background: url(emoji.png) -3120px 0px no-repeat; } -.emoji-1F1F2-1F1F1 { background: url(emoji.png) -3140px 0px no-repeat; } -.emoji-1F1F2-1F1F2 { background: url(emoji.png) -3160px 0px no-repeat; } -.emoji-1F1F2-1F1F3 { background: url(emoji.png) -3180px 0px no-repeat; } -.emoji-1F1F2-1F1F4 { background: url(emoji.png) -3200px 0px no-repeat; } -.emoji-1F1F2-1F1F7 { background: url(emoji.png) -3220px 0px no-repeat; } -.emoji-1F1F2-1F1F8 { background: url(emoji.png) -3240px 0px no-repeat; } -.emoji-1F1F2-1F1F9 { background: url(emoji.png) -3260px 0px no-repeat; } -.emoji-1F1F2-1F1FA { background: url(emoji.png) -3280px 0px no-repeat; } -.emoji-1F1F2-1F1FB { background: url(emoji.png) -3300px 0px no-repeat; } -.emoji-1F1F2-1F1FC { background: url(emoji.png) -3320px 0px no-repeat; } -.emoji-1F1F2-1F1FD { background: url(emoji.png) -3340px 0px no-repeat; } -.emoji-1F1F2-1F1FE { background: url(emoji.png) -3360px 0px no-repeat; } -.emoji-1F1F2-1F1FF { background: url(emoji.png) -3380px 0px no-repeat; } -.emoji-1F1F3-1F1E6 { background: url(emoji.png) -3400px 0px no-repeat; } -.emoji-1F1F3-1F1E8 { background: url(emoji.png) -3420px 0px no-repeat; } -.emoji-1F1F3-1F1EA { background: url(emoji.png) -3440px 0px no-repeat; } -.emoji-1F1F3-1F1EC { background: url(emoji.png) -3460px 0px no-repeat; } -.emoji-1F1F3-1F1EE { background: url(emoji.png) -3480px 0px no-repeat; } -.emoji-1F1F3-1F1F1 { background: url(emoji.png) -3500px 0px no-repeat; } -.emoji-1F1F3-1F1F4 { background: url(emoji.png) -3520px 0px no-repeat; } -.emoji-1F1F3-1F1F5 { background: url(emoji.png) -3540px 0px no-repeat; } -.emoji-1F1F3-1F1F7 { background: url(emoji.png) -3560px 0px no-repeat; } -.emoji-1F1F3-1F1FA { background: url(emoji.png) -3580px 0px no-repeat; } -.emoji-1F1F3-1F1FF { background: url(emoji.png) -3600px 0px no-repeat; } -.emoji-1F1F4-1F1F2 { background: url(emoji.png) -3620px 0px no-repeat; } -.emoji-1F1F5-1F1E6 { background: url(emoji.png) -3640px 0px no-repeat; } -.emoji-1F1F5-1F1EA { background: url(emoji.png) -3660px 0px no-repeat; } -.emoji-1F1F5-1F1EB { background: url(emoji.png) -3680px 0px no-repeat; } -.emoji-1F1F5-1F1EC { background: url(emoji.png) -3700px 0px no-repeat; } -.emoji-1F1F5-1F1ED { background: url(emoji.png) -3720px 0px no-repeat; } -.emoji-1F1F5-1F1F0 { background: url(emoji.png) -3740px 0px no-repeat; } -.emoji-1F1F5-1F1F1 { background: url(emoji.png) -3760px 0px no-repeat; } -.emoji-1F1F5-1F1F7 { background: url(emoji.png) -3780px 0px no-repeat; } -.emoji-1F1F5-1F1F8 { background: url(emoji.png) -3800px 0px no-repeat; } -.emoji-1F1F5-1F1F9 { background: url(emoji.png) -3820px 0px no-repeat; } -.emoji-1F1F5-1F1FC { background: url(emoji.png) -3840px 0px no-repeat; } -.emoji-1F1F5-1F1FE { background: url(emoji.png) -3860px 0px no-repeat; } -.emoji-1F1F6-1F1E6 { background: url(emoji.png) -3880px 0px no-repeat; } -.emoji-1F1F7-1F1F4 { background: url(emoji.png) -3900px 0px no-repeat; } -.emoji-1F1F7-1F1F8 { background: url(emoji.png) -3920px 0px no-repeat; } -.emoji-1F1F7-1F1FA { background: url(emoji.png) -3940px 0px no-repeat; } -.emoji-1F1F7-1F1FC { background: url(emoji.png) -3960px 0px no-repeat; } -.emoji-1F1F8-1F1E6 { background: url(emoji.png) -3980px 0px no-repeat; } -.emoji-1F1F8-1F1E7 { background: url(emoji.png) -4000px 0px no-repeat; } -.emoji-1F1F8-1F1E8 { background: url(emoji.png) -4020px 0px no-repeat; } -.emoji-1F1F8-1F1E9 { background: url(emoji.png) -4040px 0px no-repeat; } -.emoji-1F1F8-1F1EA { background: url(emoji.png) -4060px 0px no-repeat; } -.emoji-1F1F8-1F1EC { background: url(emoji.png) -4080px 0px no-repeat; } -.emoji-1F1F8-1F1ED { background: url(emoji.png) -4100px 0px no-repeat; } -.emoji-1F1F8-1F1EE { background: url(emoji.png) -4120px 0px no-repeat; } -.emoji-1F1F8-1F1F0 { background: url(emoji.png) -4140px 0px no-repeat; } -.emoji-1F1F8-1F1F1 { background: url(emoji.png) -4160px 0px no-repeat; } -.emoji-1F1F8-1F1F2 { background: url(emoji.png) -4180px 0px no-repeat; } -.emoji-1F1F8-1F1F3 { background: url(emoji.png) -4200px 0px no-repeat; } -.emoji-1F1F8-1F1F4 { background: url(emoji.png) -4220px 0px no-repeat; } -.emoji-1F1F8-1F1F7 { background: url(emoji.png) -4240px 0px no-repeat; } -.emoji-1F1F8-1F1F9 { background: url(emoji.png) -4260px 0px no-repeat; } -.emoji-1F1F8-1F1FB { background: url(emoji.png) -4280px 0px no-repeat; } -.emoji-1F1F8-1F1FE { background: url(emoji.png) -4300px 0px no-repeat; } -.emoji-1F1F8-1F1FF { background: url(emoji.png) -4320px 0px no-repeat; } -.emoji-1F1F9-1F1E9 { background: url(emoji.png) -4340px 0px no-repeat; } -.emoji-1F1F9-1F1EC { background: url(emoji.png) -4360px 0px no-repeat; } -.emoji-1F1F9-1F1ED { background: url(emoji.png) -4380px 0px no-repeat; } -.emoji-1F1F9-1F1EF { background: url(emoji.png) -4400px 0px no-repeat; } -.emoji-1F1F9-1F1F1 { background: url(emoji.png) -4420px 0px no-repeat; } -.emoji-1F1F9-1F1F2 { background: url(emoji.png) -4440px 0px no-repeat; } -.emoji-1F1F9-1F1F3 { background: url(emoji.png) -4460px 0px no-repeat; } -.emoji-1F1F9-1F1F4 { background: url(emoji.png) -4480px 0px no-repeat; } -.emoji-1F1F9-1F1F7 { background: url(emoji.png) -4500px 0px no-repeat; } -.emoji-1F1F9-1F1F9 { background: url(emoji.png) -4520px 0px no-repeat; } -.emoji-1F1F9-1F1FB { background: url(emoji.png) -4540px 0px no-repeat; } -.emoji-1F1F9-1F1FC { background: url(emoji.png) -4560px 0px no-repeat; } -.emoji-1F1F9-1F1FF { background: url(emoji.png) -4580px 0px no-repeat; } -.emoji-1F1FA-1F1E6 { background: url(emoji.png) -4600px 0px no-repeat; } -.emoji-1F1FA-1F1EC { background: url(emoji.png) -4620px 0px no-repeat; } -.emoji-1F1FA-1F1F8 { background: url(emoji.png) -4640px 0px no-repeat; } -.emoji-1F1FA-1F1FE { background: url(emoji.png) -4660px 0px no-repeat; } -.emoji-1F1FA-1F1FF { background: url(emoji.png) -4680px 0px no-repeat; } -.emoji-1F1FB-1F1E6 { background: url(emoji.png) -4700px 0px no-repeat; } -.emoji-1F1FB-1F1E8 { background: url(emoji.png) -4720px 0px no-repeat; } -.emoji-1F1FB-1F1EA { background: url(emoji.png) -4740px 0px no-repeat; } -.emoji-1F1FB-1F1EE { background: url(emoji.png) -4760px 0px no-repeat; } -.emoji-1F1FB-1F1F3 { background: url(emoji.png) -4780px 0px no-repeat; } -.emoji-1F1FB-1F1FA { background: url(emoji.png) -4800px 0px no-repeat; } -.emoji-1F1FC-1F1EB { background: url(emoji.png) -4820px 0px no-repeat; } -.emoji-1F1FC-1F1F8 { background: url(emoji.png) -4840px 0px no-repeat; } -.emoji-1F1FD-1F1F0 { background: url(emoji.png) -4860px 0px no-repeat; } -.emoji-1F1FE-1F1EA { background: url(emoji.png) -4880px 0px no-repeat; } -.emoji-1F1FF-1F1E6 { background: url(emoji.png) -4900px 0px no-repeat; } -.emoji-1F1FF-1F1F2 { background: url(emoji.png) -4920px 0px no-repeat; } -.emoji-1F1FF-1F1FC { background: url(emoji.png) -4940px 0px no-repeat; } -.emoji-1F201 { background: url(emoji.png) -4960px 0px no-repeat; } -.emoji-1F202 { background: url(emoji.png) -4980px 0px no-repeat; } -.emoji-1F21A { background: url(emoji.png) -5000px 0px no-repeat; } -.emoji-1F22F { background: url(emoji.png) -5020px 0px no-repeat; } -.emoji-1F232 { background: url(emoji.png) -5040px 0px no-repeat; } -.emoji-1F233 { background: url(emoji.png) -5060px 0px no-repeat; } -.emoji-1F234 { background: url(emoji.png) -5080px 0px no-repeat; } -.emoji-1F235 { background: url(emoji.png) -5100px 0px no-repeat; } -.emoji-1F236 { background: url(emoji.png) -5120px 0px no-repeat; } -.emoji-1F237 { background: url(emoji.png) -5140px 0px no-repeat; } -.emoji-1F238 { background: url(emoji.png) -5160px 0px no-repeat; } -.emoji-1F239 { background: url(emoji.png) -5180px 0px no-repeat; } -.emoji-1F23A { background: url(emoji.png) -5200px 0px no-repeat; } -.emoji-1F250 { background: url(emoji.png) -5220px 0px no-repeat; } -.emoji-1F251 { background: url(emoji.png) -5240px 0px no-repeat; } -.emoji-1F300 { background: url(emoji.png) -5260px 0px no-repeat; } -.emoji-1F301 { background: url(emoji.png) -5280px 0px no-repeat; } -.emoji-1F302 { background: url(emoji.png) -5300px 0px no-repeat; } -.emoji-1F303 { background: url(emoji.png) -5320px 0px no-repeat; } -.emoji-1F304 { background: url(emoji.png) -5340px 0px no-repeat; } -.emoji-1F305 { background: url(emoji.png) -5360px 0px no-repeat; } -.emoji-1F306 { background: url(emoji.png) -5380px 0px no-repeat; } -.emoji-1F307 { background: url(emoji.png) -5400px 0px no-repeat; } -.emoji-1F308 { background: url(emoji.png) -5420px 0px no-repeat; } -.emoji-1F309 { background: url(emoji.png) -5440px 0px no-repeat; } -.emoji-1F30A { background: url(emoji.png) -5460px 0px no-repeat; } -.emoji-1F30B { background: url(emoji.png) -5480px 0px no-repeat; } -.emoji-1F30C { background: url(emoji.png) -5500px 0px no-repeat; } -.emoji-1F30D { background: url(emoji.png) -5520px 0px no-repeat; } -.emoji-1F30E { background: url(emoji.png) -5540px 0px no-repeat; } -.emoji-1F30F { background: url(emoji.png) -5560px 0px no-repeat; } -.emoji-1F310 { background: url(emoji.png) -5580px 0px no-repeat; } -.emoji-1F311 { background: url(emoji.png) -5600px 0px no-repeat; } -.emoji-1F312 { background: url(emoji.png) -5620px 0px no-repeat; } -.emoji-1F313 { background: url(emoji.png) -5640px 0px no-repeat; } -.emoji-1F314 { background: url(emoji.png) -5660px 0px no-repeat; } -.emoji-1F315 { background: url(emoji.png) -5680px 0px no-repeat; } -.emoji-1F316 { background: url(emoji.png) -5700px 0px no-repeat; } -.emoji-1F317 { background: url(emoji.png) -5720px 0px no-repeat; } -.emoji-1F318 { background: url(emoji.png) -5740px 0px no-repeat; } -.emoji-1F319 { background: url(emoji.png) -5760px 0px no-repeat; } -.emoji-1F31A { background: url(emoji.png) -5780px 0px no-repeat; } -.emoji-1F31B { background: url(emoji.png) -5800px 0px no-repeat; } -.emoji-1F31C { background: url(emoji.png) -5820px 0px no-repeat; } -.emoji-1F31D { background: url(emoji.png) -5840px 0px no-repeat; } -.emoji-1F31E { background: url(emoji.png) -5860px 0px no-repeat; } -.emoji-1F31F { background: url(emoji.png) -5880px 0px no-repeat; } -.emoji-1F320 { background: url(emoji.png) -5900px 0px no-repeat; } -.emoji-1F321 { background: url(emoji.png) -5920px 0px no-repeat; } -.emoji-1F327 { background: url(emoji.png) -5940px 0px no-repeat; } -.emoji-1F328 { background: url(emoji.png) -5960px 0px no-repeat; } -.emoji-1F329 { background: url(emoji.png) -5980px 0px no-repeat; } -.emoji-1F32A { background: url(emoji.png) -6000px 0px no-repeat; } -.emoji-1F32B { background: url(emoji.png) -6020px 0px no-repeat; } -.emoji-1F32C { background: url(emoji.png) -6040px 0px no-repeat; } -.emoji-1F330 { background: url(emoji.png) -6060px 0px no-repeat; } -.emoji-1F331 { background: url(emoji.png) -6080px 0px no-repeat; } -.emoji-1F332 { background: url(emoji.png) -6100px 0px no-repeat; } -.emoji-1F333 { background: url(emoji.png) -6120px 0px no-repeat; } -.emoji-1F334 { background: url(emoji.png) -6140px 0px no-repeat; } -.emoji-1F335 { background: url(emoji.png) -6160px 0px no-repeat; } -.emoji-1F336 { background: url(emoji.png) -6180px 0px no-repeat; } -.emoji-1F337 { background: url(emoji.png) -6200px 0px no-repeat; } -.emoji-1F338 { background: url(emoji.png) -6220px 0px no-repeat; } -.emoji-1F339 { background: url(emoji.png) -6240px 0px no-repeat; } -.emoji-1F33A { background: url(emoji.png) -6260px 0px no-repeat; } -.emoji-1F33B { background: url(emoji.png) -6280px 0px no-repeat; } -.emoji-1F33C { background: url(emoji.png) -6300px 0px no-repeat; } -.emoji-1F33D { background: url(emoji.png) -6320px 0px no-repeat; } -.emoji-1F33E { background: url(emoji.png) -6340px 0px no-repeat; } -.emoji-1F33F { background: url(emoji.png) -6360px 0px no-repeat; } -.emoji-1F340 { background: url(emoji.png) -6380px 0px no-repeat; } -.emoji-1F341 { background: url(emoji.png) -6400px 0px no-repeat; } -.emoji-1F342 { background: url(emoji.png) -6420px 0px no-repeat; } -.emoji-1F343 { background: url(emoji.png) -6440px 0px no-repeat; } -.emoji-1F344 { background: url(emoji.png) -6460px 0px no-repeat; } -.emoji-1F345 { background: url(emoji.png) -6480px 0px no-repeat; } -.emoji-1F346 { background: url(emoji.png) -6500px 0px no-repeat; } -.emoji-1F347 { background: url(emoji.png) -6520px 0px no-repeat; } -.emoji-1F348 { background: url(emoji.png) -6540px 0px no-repeat; } -.emoji-1F349 { background: url(emoji.png) -6560px 0px no-repeat; } -.emoji-1F34A { background: url(emoji.png) -6580px 0px no-repeat; } -.emoji-1F34B { background: url(emoji.png) -6600px 0px no-repeat; } -.emoji-1F34C { background: url(emoji.png) -6620px 0px no-repeat; } -.emoji-1F34D { background: url(emoji.png) -6640px 0px no-repeat; } -.emoji-1F34E { background: url(emoji.png) -6660px 0px no-repeat; } -.emoji-1F34F { background: url(emoji.png) -6680px 0px no-repeat; } -.emoji-1F350 { background: url(emoji.png) -6700px 0px no-repeat; } -.emoji-1F351 { background: url(emoji.png) -6720px 0px no-repeat; } -.emoji-1F352 { background: url(emoji.png) -6740px 0px no-repeat; } -.emoji-1F353 { background: url(emoji.png) -6760px 0px no-repeat; } -.emoji-1F354 { background: url(emoji.png) -6780px 0px no-repeat; } -.emoji-1F355 { background: url(emoji.png) -6800px 0px no-repeat; } -.emoji-1F356 { background: url(emoji.png) -6820px 0px no-repeat; } -.emoji-1F357 { background: url(emoji.png) -6840px 0px no-repeat; } -.emoji-1F358 { background: url(emoji.png) -6860px 0px no-repeat; } -.emoji-1F359 { background: url(emoji.png) -6880px 0px no-repeat; } -.emoji-1F35A { background: url(emoji.png) -6900px 0px no-repeat; } -.emoji-1F35B { background: url(emoji.png) -6920px 0px no-repeat; } -.emoji-1F35C { background: url(emoji.png) -6940px 0px no-repeat; } -.emoji-1F35D { background: url(emoji.png) -6960px 0px no-repeat; } -.emoji-1F35E { background: url(emoji.png) -6980px 0px no-repeat; } -.emoji-1F35F { background: url(emoji.png) -7000px 0px no-repeat; } -.emoji-1F360 { background: url(emoji.png) -7020px 0px no-repeat; } -.emoji-1F361 { background: url(emoji.png) -7040px 0px no-repeat; } -.emoji-1F362 { background: url(emoji.png) -7060px 0px no-repeat; } -.emoji-1F363 { background: url(emoji.png) -7080px 0px no-repeat; } -.emoji-1F364 { background: url(emoji.png) -7100px 0px no-repeat; } -.emoji-1F365 { background: url(emoji.png) -7120px 0px no-repeat; } -.emoji-1F366 { background: url(emoji.png) -7140px 0px no-repeat; } -.emoji-1F367 { background: url(emoji.png) -7160px 0px no-repeat; } -.emoji-1F368 { background: url(emoji.png) -7180px 0px no-repeat; } -.emoji-1F369 { background: url(emoji.png) -7200px 0px no-repeat; } -.emoji-1F36A { background: url(emoji.png) -7220px 0px no-repeat; } -.emoji-1F36B { background: url(emoji.png) -7240px 0px no-repeat; } -.emoji-1F36C { background: url(emoji.png) -7260px 0px no-repeat; } -.emoji-1F36D { background: url(emoji.png) -7280px 0px no-repeat; } -.emoji-1F36E { background: url(emoji.png) -7300px 0px no-repeat; } -.emoji-1F36F { background: url(emoji.png) -7320px 0px no-repeat; } -.emoji-1F370 { background: url(emoji.png) -7340px 0px no-repeat; } -.emoji-1F371 { background: url(emoji.png) -7360px 0px no-repeat; } -.emoji-1F372 { background: url(emoji.png) -7380px 0px no-repeat; } -.emoji-1F373 { background: url(emoji.png) -7400px 0px no-repeat; } -.emoji-1F374 { background: url(emoji.png) -7420px 0px no-repeat; } -.emoji-1F375 { background: url(emoji.png) -7440px 0px no-repeat; } -.emoji-1F376 { background: url(emoji.png) -7460px 0px no-repeat; } -.emoji-1F377 { background: url(emoji.png) -7480px 0px no-repeat; } -.emoji-1F378 { background: url(emoji.png) -7500px 0px no-repeat; } -.emoji-1F379 { background: url(emoji.png) -7520px 0px no-repeat; } -.emoji-1F37A { background: url(emoji.png) -7540px 0px no-repeat; } -.emoji-1F37B { background: url(emoji.png) -7560px 0px no-repeat; } -.emoji-1F37C { background: url(emoji.png) -7580px 0px no-repeat; } -.emoji-1F37D { background: url(emoji.png) -7600px 0px no-repeat; } -.emoji-1F380 { background: url(emoji.png) -7620px 0px no-repeat; } -.emoji-1F381 { background: url(emoji.png) -7640px 0px no-repeat; } -.emoji-1F382 { background: url(emoji.png) -7660px 0px no-repeat; } -.emoji-1F383 { background: url(emoji.png) -7680px 0px no-repeat; } -.emoji-1F384 { background: url(emoji.png) -7700px 0px no-repeat; } -.emoji-1F385 { background: url(emoji.png) -7720px 0px no-repeat; } -.emoji-1F386 { background: url(emoji.png) -7740px 0px no-repeat; } -.emoji-1F387 { background: url(emoji.png) -7760px 0px no-repeat; } -.emoji-1F388 { background: url(emoji.png) -7780px 0px no-repeat; } -.emoji-1F389 { background: url(emoji.png) -7800px 0px no-repeat; } -.emoji-1F38A { background: url(emoji.png) -7820px 0px no-repeat; } -.emoji-1F38B { background: url(emoji.png) -7840px 0px no-repeat; } -.emoji-1F38C { background: url(emoji.png) -7860px 0px no-repeat; } -.emoji-1F38D { background: url(emoji.png) -7880px 0px no-repeat; } -.emoji-1F38E { background: url(emoji.png) -7900px 0px no-repeat; } -.emoji-1F38F { background: url(emoji.png) -7920px 0px no-repeat; } -.emoji-1F390 { background: url(emoji.png) -7940px 0px no-repeat; } -.emoji-1F391 { background: url(emoji.png) -7960px 0px no-repeat; } -.emoji-1F392 { background: url(emoji.png) -7980px 0px no-repeat; } -.emoji-1F393 { background: url(emoji.png) -8000px 0px no-repeat; } -.emoji-1F394 { background: url(emoji.png) -8020px 0px no-repeat; } -.emoji-1F395 { background: url(emoji.png) -8040px 0px no-repeat; } -.emoji-1F396 { background: url(emoji.png) -8060px 0px no-repeat; } -.emoji-1F397 { background: url(emoji.png) -8080px 0px no-repeat; } -.emoji-1F398 { background: url(emoji.png) -8100px 0px no-repeat; } -.emoji-1F399 { background: url(emoji.png) -8120px 0px no-repeat; } -.emoji-1F39A { background: url(emoji.png) -8140px 0px no-repeat; } -.emoji-1F39B { background: url(emoji.png) -8160px 0px no-repeat; } -.emoji-1F39C { background: url(emoji.png) -8180px 0px no-repeat; } -.emoji-1F39D { background: url(emoji.png) -8200px 0px no-repeat; } -.emoji-1F39E { background: url(emoji.png) -8220px 0px no-repeat; } -.emoji-1F39F { background: url(emoji.png) -8240px 0px no-repeat; } -.emoji-1F3A0 { background: url(emoji.png) -8260px 0px no-repeat; } -.emoji-1F3A1 { background: url(emoji.png) -8280px 0px no-repeat; } -.emoji-1F3A2 { background: url(emoji.png) -8300px 0px no-repeat; } -.emoji-1F3A3 { background: url(emoji.png) -8320px 0px no-repeat; } -.emoji-1F3A4 { background: url(emoji.png) -8340px 0px no-repeat; } -.emoji-1F3A5 { background: url(emoji.png) -8360px 0px no-repeat; } -.emoji-1F3A6 { background: url(emoji.png) -8380px 0px no-repeat; } -.emoji-1F3A7 { background: url(emoji.png) -8400px 0px no-repeat; } -.emoji-1F3A8 { background: url(emoji.png) -8420px 0px no-repeat; } -.emoji-1F3A9 { background: url(emoji.png) -8440px 0px no-repeat; } -.emoji-1F3AA { background: url(emoji.png) -8460px 0px no-repeat; } -.emoji-1F3AB { background: url(emoji.png) -8480px 0px no-repeat; } -.emoji-1F3AC { background: url(emoji.png) -8500px 0px no-repeat; } -.emoji-1F3AD { background: url(emoji.png) -8520px 0px no-repeat; } -.emoji-1F3AE { background: url(emoji.png) -8540px 0px no-repeat; } -.emoji-1F3AF { background: url(emoji.png) -8560px 0px no-repeat; } -.emoji-1F3B0 { background: url(emoji.png) -8580px 0px no-repeat; } -.emoji-1F3B1 { background: url(emoji.png) -8600px 0px no-repeat; } -.emoji-1F3B2 { background: url(emoji.png) -8620px 0px no-repeat; } -.emoji-1F3B3 { background: url(emoji.png) -8640px 0px no-repeat; } -.emoji-1F3B4 { background: url(emoji.png) -8660px 0px no-repeat; } -.emoji-1F3B5 { background: url(emoji.png) -8680px 0px no-repeat; } -.emoji-1F3B6 { background: url(emoji.png) -8700px 0px no-repeat; } -.emoji-1F3B7 { background: url(emoji.png) -8720px 0px no-repeat; } -.emoji-1F3B8 { background: url(emoji.png) -8740px 0px no-repeat; } -.emoji-1F3B9 { background: url(emoji.png) -8760px 0px no-repeat; } -.emoji-1F3BA { background: url(emoji.png) -8780px 0px no-repeat; } -.emoji-1F3BB { background: url(emoji.png) -8800px 0px no-repeat; } -.emoji-1F3BC { background: url(emoji.png) -8820px 0px no-repeat; } -.emoji-1F3BD { background: url(emoji.png) -8840px 0px no-repeat; } -.emoji-1F3BE { background: url(emoji.png) -8860px 0px no-repeat; } -.emoji-1F3BF { background: url(emoji.png) -8880px 0px no-repeat; } -.emoji-1F3C0 { background: url(emoji.png) -8900px 0px no-repeat; } -.emoji-1F3C1 { background: url(emoji.png) -8920px 0px no-repeat; } -.emoji-1F3C2 { background: url(emoji.png) -8940px 0px no-repeat; } -.emoji-1F3C3 { background: url(emoji.png) -8960px 0px no-repeat; } -.emoji-1F3C4 { background: url(emoji.png) -8980px 0px no-repeat; } -.emoji-1F3C5 { background: url(emoji.png) -9000px 0px no-repeat; } -.emoji-1F3C6 { background: url(emoji.png) -9020px 0px no-repeat; } -.emoji-1F3C7 { background: url(emoji.png) -9040px 0px no-repeat; } -.emoji-1F3C8 { background: url(emoji.png) -9060px 0px no-repeat; } -.emoji-1F3C9 { background: url(emoji.png) -9080px 0px no-repeat; } -.emoji-1F3CA { background: url(emoji.png) -9100px 0px no-repeat; } -.emoji-1F3CB { background: url(emoji.png) -9120px 0px no-repeat; } -.emoji-1F3CC { background: url(emoji.png) -9140px 0px no-repeat; } -.emoji-1F3CD { background: url(emoji.png) -9160px 0px no-repeat; } -.emoji-1F3CE { background: url(emoji.png) -9180px 0px no-repeat; } -.emoji-1F3D4 { background: url(emoji.png) -9200px 0px no-repeat; } -.emoji-1F3D5 { background: url(emoji.png) -9220px 0px no-repeat; } -.emoji-1F3D6 { background: url(emoji.png) -9240px 0px no-repeat; } -.emoji-1F3D7 { background: url(emoji.png) -9260px 0px no-repeat; } -.emoji-1F3D8 { background: url(emoji.png) -9280px 0px no-repeat; } -.emoji-1F3D9 { background: url(emoji.png) -9300px 0px no-repeat; } -.emoji-1F3DA { background: url(emoji.png) -9320px 0px no-repeat; } -.emoji-1F3DB { background: url(emoji.png) -9340px 0px no-repeat; } -.emoji-1F3DC { background: url(emoji.png) -9360px 0px no-repeat; } -.emoji-1F3DD { background: url(emoji.png) -9380px 0px no-repeat; } -.emoji-1F3DE { background: url(emoji.png) -9400px 0px no-repeat; } -.emoji-1F3DF { background: url(emoji.png) -9420px 0px no-repeat; } -.emoji-1F3E0 { background: url(emoji.png) -9440px 0px no-repeat; } -.emoji-1F3E1 { background: url(emoji.png) -9460px 0px no-repeat; } -.emoji-1F3E2 { background: url(emoji.png) -9480px 0px no-repeat; } -.emoji-1F3E3 { background: url(emoji.png) -9500px 0px no-repeat; } -.emoji-1F3E4 { background: url(emoji.png) -9520px 0px no-repeat; } -.emoji-1F3E5 { background: url(emoji.png) -9540px 0px no-repeat; } -.emoji-1F3E6 { background: url(emoji.png) -9560px 0px no-repeat; } -.emoji-1F3E7 { background: url(emoji.png) -9580px 0px no-repeat; } -.emoji-1F3E8 { background: url(emoji.png) -9600px 0px no-repeat; } -.emoji-1F3E9 { background: url(emoji.png) -9620px 0px no-repeat; } -.emoji-1F3EA { background: url(emoji.png) -9640px 0px no-repeat; } -.emoji-1F3EB { background: url(emoji.png) -9660px 0px no-repeat; } -.emoji-1F3EC { background: url(emoji.png) -9680px 0px no-repeat; } -.emoji-1F3ED { background: url(emoji.png) -9700px 0px no-repeat; } -.emoji-1F3EE { background: url(emoji.png) -9720px 0px no-repeat; } -.emoji-1F3EF { background: url(emoji.png) -9740px 0px no-repeat; } -.emoji-1F3F0 { background: url(emoji.png) -9760px 0px no-repeat; } -.emoji-1F3F1 { background: url(emoji.png) -9780px 0px no-repeat; } -.emoji-1F3F2 { background: url(emoji.png) -9800px 0px no-repeat; } -.emoji-1F3F3 { background: url(emoji.png) -9820px 0px no-repeat; } -.emoji-1F3F4 { background: url(emoji.png) -9840px 0px no-repeat; } -.emoji-1F3F5 { background: url(emoji.png) -9860px 0px no-repeat; } -.emoji-1F3F6 { background: url(emoji.png) -9880px 0px no-repeat; } -.emoji-1F3F7 { background: url(emoji.png) -9900px 0px no-repeat; } -.emoji-1F400 { background: url(emoji.png) -9920px 0px no-repeat; } -.emoji-1F401 { background: url(emoji.png) -9940px 0px no-repeat; } -.emoji-1F402 { background: url(emoji.png) -9960px 0px no-repeat; } -.emoji-1F403 { background: url(emoji.png) -9980px 0px no-repeat; } -.emoji-1F404 { background: url(emoji.png) -10000px 0px no-repeat; } -.emoji-1F405 { background: url(emoji.png) -10020px 0px no-repeat; } -.emoji-1F406 { background: url(emoji.png) -10040px 0px no-repeat; } -.emoji-1F407 { background: url(emoji.png) -10060px 0px no-repeat; } -.emoji-1F408 { background: url(emoji.png) -10080px 0px no-repeat; } -.emoji-1F409 { background: url(emoji.png) -10100px 0px no-repeat; } -.emoji-1F40A { background: url(emoji.png) -10120px 0px no-repeat; } -.emoji-1F40B { background: url(emoji.png) -10140px 0px no-repeat; } -.emoji-1F40C { background: url(emoji.png) -10160px 0px no-repeat; } -.emoji-1F40D { background: url(emoji.png) -10180px 0px no-repeat; } -.emoji-1F40E { background: url(emoji.png) -10200px 0px no-repeat; } -.emoji-1F40F { background: url(emoji.png) -10220px 0px no-repeat; } -.emoji-1F410 { background: url(emoji.png) -10240px 0px no-repeat; } -.emoji-1F411 { background: url(emoji.png) -10260px 0px no-repeat; } -.emoji-1F412 { background: url(emoji.png) -10280px 0px no-repeat; } -.emoji-1F413 { background: url(emoji.png) -10300px 0px no-repeat; } -.emoji-1F414 { background: url(emoji.png) -10320px 0px no-repeat; } -.emoji-1F415 { background: url(emoji.png) -10340px 0px no-repeat; } -.emoji-1F416 { background: url(emoji.png) -10360px 0px no-repeat; } -.emoji-1F417 { background: url(emoji.png) -10380px 0px no-repeat; } -.emoji-1F418 { background: url(emoji.png) -10400px 0px no-repeat; } -.emoji-1F419 { background: url(emoji.png) -10420px 0px no-repeat; } -.emoji-1F41A { background: url(emoji.png) -10440px 0px no-repeat; } -.emoji-1F41B { background: url(emoji.png) -10460px 0px no-repeat; } -.emoji-1F41C { background: url(emoji.png) -10480px 0px no-repeat; } -.emoji-1F41D { background: url(emoji.png) -10500px 0px no-repeat; } -.emoji-1F41E { background: url(emoji.png) -10520px 0px no-repeat; } -.emoji-1F41F { background: url(emoji.png) -10540px 0px no-repeat; } -.emoji-1F420 { background: url(emoji.png) -10560px 0px no-repeat; } -.emoji-1F421 { background: url(emoji.png) -10580px 0px no-repeat; } -.emoji-1F422 { background: url(emoji.png) -10600px 0px no-repeat; } -.emoji-1F423 { background: url(emoji.png) -10620px 0px no-repeat; } -.emoji-1F424 { background: url(emoji.png) -10640px 0px no-repeat; } -.emoji-1F425 { background: url(emoji.png) -10660px 0px no-repeat; } -.emoji-1F426 { background: url(emoji.png) -10680px 0px no-repeat; } -.emoji-1F427 { background: url(emoji.png) -10700px 0px no-repeat; } -.emoji-1F428 { background: url(emoji.png) -10720px 0px no-repeat; } -.emoji-1F429 { background: url(emoji.png) -10740px 0px no-repeat; } -.emoji-1F42A { background: url(emoji.png) -10760px 0px no-repeat; } -.emoji-1F42B { background: url(emoji.png) -10780px 0px no-repeat; } -.emoji-1F42C { background: url(emoji.png) -10800px 0px no-repeat; } -.emoji-1F42D { background: url(emoji.png) -10820px 0px no-repeat; } -.emoji-1F42E { background: url(emoji.png) -10840px 0px no-repeat; } -.emoji-1F42F { background: url(emoji.png) -10860px 0px no-repeat; } -.emoji-1F430 { background: url(emoji.png) -10880px 0px no-repeat; } -.emoji-1F431 { background: url(emoji.png) -10900px 0px no-repeat; } -.emoji-1F432 { background: url(emoji.png) -10920px 0px no-repeat; } -.emoji-1F433 { background: url(emoji.png) -10940px 0px no-repeat; } -.emoji-1F434 { background: url(emoji.png) -10960px 0px no-repeat; } -.emoji-1F435 { background: url(emoji.png) -10980px 0px no-repeat; } -.emoji-1F436 { background: url(emoji.png) -11000px 0px no-repeat; } -.emoji-1F437 { background: url(emoji.png) -11020px 0px no-repeat; } -.emoji-1F438 { background: url(emoji.png) -11040px 0px no-repeat; } -.emoji-1F439 { background: url(emoji.png) -11060px 0px no-repeat; } -.emoji-1F43A { background: url(emoji.png) -11080px 0px no-repeat; } -.emoji-1F43B { background: url(emoji.png) -11100px 0px no-repeat; } -.emoji-1F43C { background: url(emoji.png) -11120px 0px no-repeat; } -.emoji-1F43D { background: url(emoji.png) -11140px 0px no-repeat; } -.emoji-1F43E { background: url(emoji.png) -11160px 0px no-repeat; } -.emoji-1F43F { background: url(emoji.png) -11180px 0px no-repeat; } -.emoji-1F440 { background: url(emoji.png) -11200px 0px no-repeat; } -.emoji-1F441 { background: url(emoji.png) -11220px 0px no-repeat; } -.emoji-1F442 { background: url(emoji.png) -11240px 0px no-repeat; } -.emoji-1F443 { background: url(emoji.png) -11260px 0px no-repeat; } -.emoji-1F444 { background: url(emoji.png) -11280px 0px no-repeat; } -.emoji-1F445 { background: url(emoji.png) -11300px 0px no-repeat; } -.emoji-1F446 { background: url(emoji.png) -11320px 0px no-repeat; } -.emoji-1F447 { background: url(emoji.png) -11340px 0px no-repeat; } -.emoji-1F448 { background: url(emoji.png) -11360px 0px no-repeat; } -.emoji-1F449 { background: url(emoji.png) -11380px 0px no-repeat; } -.emoji-1F44A { background: url(emoji.png) -11400px 0px no-repeat; } -.emoji-1F44B { background: url(emoji.png) -11420px 0px no-repeat; } -.emoji-1F44C { background: url(emoji.png) -11440px 0px no-repeat; } -.emoji-1F44D { background: url(emoji.png) -11460px 0px no-repeat; } -.emoji-1F44E { background: url(emoji.png) -11480px 0px no-repeat; } -.emoji-1F44F { background: url(emoji.png) -11500px 0px no-repeat; } -.emoji-1F450 { background: url(emoji.png) -11520px 0px no-repeat; } -.emoji-1F451 { background: url(emoji.png) -11540px 0px no-repeat; } -.emoji-1F452 { background: url(emoji.png) -11560px 0px no-repeat; } -.emoji-1F453 { background: url(emoji.png) -11580px 0px no-repeat; } -.emoji-1F454 { background: url(emoji.png) -11600px 0px no-repeat; } -.emoji-1F455 { background: url(emoji.png) -11620px 0px no-repeat; } -.emoji-1F456 { background: url(emoji.png) -11640px 0px no-repeat; } -.emoji-1F457 { background: url(emoji.png) -11660px 0px no-repeat; } -.emoji-1F458 { background: url(emoji.png) -11680px 0px no-repeat; } -.emoji-1F459 { background: url(emoji.png) -11700px 0px no-repeat; } -.emoji-1F45A { background: url(emoji.png) -11720px 0px no-repeat; } -.emoji-1F45B { background: url(emoji.png) -11740px 0px no-repeat; } -.emoji-1F45C { background: url(emoji.png) -11760px 0px no-repeat; } -.emoji-1F45D { background: url(emoji.png) -11780px 0px no-repeat; } -.emoji-1F45E { background: url(emoji.png) -11800px 0px no-repeat; } -.emoji-1F45F { background: url(emoji.png) -11820px 0px no-repeat; } -.emoji-1F460 { background: url(emoji.png) -11840px 0px no-repeat; } -.emoji-1F461 { background: url(emoji.png) -11860px 0px no-repeat; } -.emoji-1F462 { background: url(emoji.png) -11880px 0px no-repeat; } -.emoji-1F463 { background: url(emoji.png) -11900px 0px no-repeat; } -.emoji-1F464 { background: url(emoji.png) -11920px 0px no-repeat; } -.emoji-1F465 { background: url(emoji.png) -11940px 0px no-repeat; } -.emoji-1F466 { background: url(emoji.png) -11960px 0px no-repeat; } -.emoji-1F467 { background: url(emoji.png) -11980px 0px no-repeat; } -.emoji-1F468 { background: url(emoji.png) -12000px 0px no-repeat; } -.emoji-1F468-1F468-1F466 { background: url(emoji.png) -12020px 0px no-repeat; } -.emoji-1F468-1F468-1F466-1F466 { background: url(emoji.png) -12040px 0px no-repeat; } -.emoji-1F468-1F468-1F467 { background: url(emoji.png) -12060px 0px no-repeat; } -.emoji-1F468-1F468-1F467-1F466 { background: url(emoji.png) -12080px 0px no-repeat; } -.emoji-1F468-1F468-1F467-1F467 { background: url(emoji.png) -12100px 0px no-repeat; } -.emoji-1F468-1F469-1F466-1F466 { background: url(emoji.png) -12120px 0px no-repeat; } -.emoji-1F468-1F469-1F467 { background: url(emoji.png) -12140px 0px no-repeat; } -.emoji-1F468-1F469-1F467-1F466 { background: url(emoji.png) -12160px 0px no-repeat; } -.emoji-1F468-1F469-1F467-1F467 { background: url(emoji.png) -12180px 0px no-repeat; } -.emoji-1F468-2764-1F468 { background: url(emoji.png) -12200px 0px no-repeat; } -.emoji-1F468-2764-1F48B-1F468 { background: url(emoji.png) -12220px 0px no-repeat; } -.emoji-1F469 { background: url(emoji.png) -12240px 0px no-repeat; } -.emoji-1F469-1F469-1F466 { background: url(emoji.png) -12260px 0px no-repeat; } -.emoji-1F469-1F469-1F466-1F466 { background: url(emoji.png) -12280px 0px no-repeat; } -.emoji-1F469-1F469-1F467 { background: url(emoji.png) -12300px 0px no-repeat; } -.emoji-1F469-1F469-1F467-1F466 { background: url(emoji.png) -12320px 0px no-repeat; } -.emoji-1F469-1F469-1F467-1F467 { background: url(emoji.png) -12340px 0px no-repeat; } -.emoji-1F469-2764-1F469 { background: url(emoji.png) -12360px 0px no-repeat; } -.emoji-1F469-2764-1F48B-1F469 { background: url(emoji.png) -12380px 0px no-repeat; } -.emoji-1F46A { background: url(emoji.png) -12400px 0px no-repeat; } -.emoji-1F46B { background: url(emoji.png) -12420px 0px no-repeat; } -.emoji-1F46C { background: url(emoji.png) -12440px 0px no-repeat; } -.emoji-1F46D { background: url(emoji.png) -12460px 0px no-repeat; } -.emoji-1F46E { background: url(emoji.png) -12480px 0px no-repeat; } -.emoji-1F46F { background: url(emoji.png) -12500px 0px no-repeat; } -.emoji-1F470 { background: url(emoji.png) -12520px 0px no-repeat; } -.emoji-1F471 { background: url(emoji.png) -12540px 0px no-repeat; } -.emoji-1F472 { background: url(emoji.png) -12560px 0px no-repeat; } -.emoji-1F473 { background: url(emoji.png) -12580px 0px no-repeat; } -.emoji-1F474 { background: url(emoji.png) -12600px 0px no-repeat; } -.emoji-1F475 { background: url(emoji.png) -12620px 0px no-repeat; } -.emoji-1F476 { background: url(emoji.png) -12640px 0px no-repeat; } -.emoji-1F477 { background: url(emoji.png) -12660px 0px no-repeat; } -.emoji-1F478 { background: url(emoji.png) -12680px 0px no-repeat; } -.emoji-1F479 { background: url(emoji.png) -12700px 0px no-repeat; } -.emoji-1F47A { background: url(emoji.png) -12720px 0px no-repeat; } -.emoji-1F47B { background: url(emoji.png) -12740px 0px no-repeat; } -.emoji-1F47C { background: url(emoji.png) -12760px 0px no-repeat; } -.emoji-1F47D { background: url(emoji.png) -12780px 0px no-repeat; } -.emoji-1F47E { background: url(emoji.png) -12800px 0px no-repeat; } -.emoji-1F47F { background: url(emoji.png) -12820px 0px no-repeat; } -.emoji-1F480 { background: url(emoji.png) -12840px 0px no-repeat; } -.emoji-1F481 { background: url(emoji.png) -12860px 0px no-repeat; } -.emoji-1F482 { background: url(emoji.png) -12880px 0px no-repeat; } -.emoji-1F483 { background: url(emoji.png) -12900px 0px no-repeat; } -.emoji-1F484 { background: url(emoji.png) -12920px 0px no-repeat; } -.emoji-1F485 { background: url(emoji.png) -12940px 0px no-repeat; } -.emoji-1F486 { background: url(emoji.png) -12960px 0px no-repeat; } -.emoji-1F487 { background: url(emoji.png) -12980px 0px no-repeat; } -.emoji-1F488 { background: url(emoji.png) -13000px 0px no-repeat; } -.emoji-1F489 { background: url(emoji.png) -13020px 0px no-repeat; } -.emoji-1F48A { background: url(emoji.png) -13040px 0px no-repeat; } -.emoji-1F48B { background: url(emoji.png) -13060px 0px no-repeat; } -.emoji-1F48C { background: url(emoji.png) -13080px 0px no-repeat; } -.emoji-1F48D { background: url(emoji.png) -13100px 0px no-repeat; } -.emoji-1F48E { background: url(emoji.png) -13120px 0px no-repeat; } -.emoji-1F48F { background: url(emoji.png) -13140px 0px no-repeat; } -.emoji-1F490 { background: url(emoji.png) -13160px 0px no-repeat; } -.emoji-1F491 { background: url(emoji.png) -13180px 0px no-repeat; } -.emoji-1F492 { background: url(emoji.png) -13200px 0px no-repeat; } -.emoji-1F493 { background: url(emoji.png) -13220px 0px no-repeat; } -.emoji-1F494 { background: url(emoji.png) -13240px 0px no-repeat; } -.emoji-1F495 { background: url(emoji.png) -13260px 0px no-repeat; } -.emoji-1F496 { background: url(emoji.png) -13280px 0px no-repeat; } -.emoji-1F497 { background: url(emoji.png) -13300px 0px no-repeat; } -.emoji-1F498 { background: url(emoji.png) -13320px 0px no-repeat; } -.emoji-1F499 { background: url(emoji.png) -13340px 0px no-repeat; } -.emoji-1F49A { background: url(emoji.png) -13360px 0px no-repeat; } -.emoji-1F49B { background: url(emoji.png) -13380px 0px no-repeat; } -.emoji-1F49C { background: url(emoji.png) -13400px 0px no-repeat; } -.emoji-1F49D { background: url(emoji.png) -13420px 0px no-repeat; } -.emoji-1F49E { background: url(emoji.png) -13440px 0px no-repeat; } -.emoji-1F49F { background: url(emoji.png) -13460px 0px no-repeat; } -.emoji-1F4A0 { background: url(emoji.png) -13480px 0px no-repeat; } -.emoji-1F4A1 { background: url(emoji.png) -13500px 0px no-repeat; } -.emoji-1F4A2 { background: url(emoji.png) -13520px 0px no-repeat; } -.emoji-1F4A3 { background: url(emoji.png) -13540px 0px no-repeat; } -.emoji-1F4A4 { background: url(emoji.png) -13560px 0px no-repeat; } -.emoji-1F4A5 { background: url(emoji.png) -13580px 0px no-repeat; } -.emoji-1F4A6 { background: url(emoji.png) -13600px 0px no-repeat; } -.emoji-1F4A7 { background: url(emoji.png) -13620px 0px no-repeat; } -.emoji-1F4A8 { background: url(emoji.png) -13640px 0px no-repeat; } -.emoji-1F4A9 { background: url(emoji.png) -13660px 0px no-repeat; } -.emoji-1F4AA { background: url(emoji.png) -13680px 0px no-repeat; } -.emoji-1F4AB { background: url(emoji.png) -13700px 0px no-repeat; } -.emoji-1F4AC { background: url(emoji.png) -13720px 0px no-repeat; } -.emoji-1F4AD { background: url(emoji.png) -13740px 0px no-repeat; } -.emoji-1F4AE { background: url(emoji.png) -13760px 0px no-repeat; } -.emoji-1F4AF { background: url(emoji.png) -13780px 0px no-repeat; } -.emoji-1F4B0 { background: url(emoji.png) -13800px 0px no-repeat; } -.emoji-1F4B1 { background: url(emoji.png) -13820px 0px no-repeat; } -.emoji-1F4B2 { background: url(emoji.png) -13840px 0px no-repeat; } -.emoji-1F4B3 { background: url(emoji.png) -13860px 0px no-repeat; } -.emoji-1F4B4 { background: url(emoji.png) -13880px 0px no-repeat; } -.emoji-1F4B5 { background: url(emoji.png) -13900px 0px no-repeat; } -.emoji-1F4B6 { background: url(emoji.png) -13920px 0px no-repeat; } -.emoji-1F4B7 { background: url(emoji.png) -13940px 0px no-repeat; } -.emoji-1F4B8 { background: url(emoji.png) -13960px 0px no-repeat; } -.emoji-1F4B9 { background: url(emoji.png) -13980px 0px no-repeat; } -.emoji-1F4BA { background: url(emoji.png) -14000px 0px no-repeat; } -.emoji-1F4BB { background: url(emoji.png) -14020px 0px no-repeat; } -.emoji-1F4BC { background: url(emoji.png) -14040px 0px no-repeat; } -.emoji-1F4BD { background: url(emoji.png) -14060px 0px no-repeat; } -.emoji-1F4BE { background: url(emoji.png) -14080px 0px no-repeat; } -.emoji-1F4BF { background: url(emoji.png) -14100px 0px no-repeat; } -.emoji-1F4C0 { background: url(emoji.png) -14120px 0px no-repeat; } -.emoji-1F4C1 { background: url(emoji.png) -14140px 0px no-repeat; } -.emoji-1F4C2 { background: url(emoji.png) -14160px 0px no-repeat; } -.emoji-1F4C3 { background: url(emoji.png) -14180px 0px no-repeat; } -.emoji-1F4C4 { background: url(emoji.png) -14200px 0px no-repeat; } -.emoji-1F4C5 { background: url(emoji.png) -14220px 0px no-repeat; } -.emoji-1F4C6 { background: url(emoji.png) -14240px 0px no-repeat; } -.emoji-1F4C7 { background: url(emoji.png) -14260px 0px no-repeat; } -.emoji-1F4C8 { background: url(emoji.png) -14280px 0px no-repeat; } -.emoji-1F4C9 { background: url(emoji.png) -14300px 0px no-repeat; } -.emoji-1F4CA { background: url(emoji.png) -14320px 0px no-repeat; } -.emoji-1F4CB { background: url(emoji.png) -14340px 0px no-repeat; } -.emoji-1F4CC { background: url(emoji.png) -14360px 0px no-repeat; } -.emoji-1F4CD { background: url(emoji.png) -14380px 0px no-repeat; } -.emoji-1F4CE { background: url(emoji.png) -14400px 0px no-repeat; } -.emoji-1F4CF { background: url(emoji.png) -14420px 0px no-repeat; } -.emoji-1F4D0 { background: url(emoji.png) -14440px 0px no-repeat; } -.emoji-1F4D1 { background: url(emoji.png) -14460px 0px no-repeat; } -.emoji-1F4D2 { background: url(emoji.png) -14480px 0px no-repeat; } -.emoji-1F4D3 { background: url(emoji.png) -14500px 0px no-repeat; } -.emoji-1F4D4 { background: url(emoji.png) -14520px 0px no-repeat; } -.emoji-1F4D5 { background: url(emoji.png) -14540px 0px no-repeat; } -.emoji-1F4D6 { background: url(emoji.png) -14560px 0px no-repeat; } -.emoji-1F4D7 { background: url(emoji.png) -14580px 0px no-repeat; } -.emoji-1F4D8 { background: url(emoji.png) -14600px 0px no-repeat; } -.emoji-1F4D9 { background: url(emoji.png) -14620px 0px no-repeat; } -.emoji-1F4DA { background: url(emoji.png) -14640px 0px no-repeat; } -.emoji-1F4DB { background: url(emoji.png) -14660px 0px no-repeat; } -.emoji-1F4DC { background: url(emoji.png) -14680px 0px no-repeat; } -.emoji-1F4DD { background: url(emoji.png) -14700px 0px no-repeat; } -.emoji-1F4DE { background: url(emoji.png) -14720px 0px no-repeat; } -.emoji-1F4DF { background: url(emoji.png) -14740px 0px no-repeat; } -.emoji-1F4E0 { background: url(emoji.png) -14760px 0px no-repeat; } -.emoji-1F4E1 { background: url(emoji.png) -14780px 0px no-repeat; } -.emoji-1F4E2 { background: url(emoji.png) -14800px 0px no-repeat; } -.emoji-1F4E3 { background: url(emoji.png) -14820px 0px no-repeat; } -.emoji-1F4E4 { background: url(emoji.png) -14840px 0px no-repeat; } -.emoji-1F4E5 { background: url(emoji.png) -14860px 0px no-repeat; } -.emoji-1F4E6 { background: url(emoji.png) -14880px 0px no-repeat; } -.emoji-1F4E7 { background: url(emoji.png) -14900px 0px no-repeat; } -.emoji-1F4E8 { background: url(emoji.png) -14920px 0px no-repeat; } -.emoji-1F4E9 { background: url(emoji.png) -14940px 0px no-repeat; } -.emoji-1F4EA { background: url(emoji.png) -14960px 0px no-repeat; } -.emoji-1F4EB { background: url(emoji.png) -14980px 0px no-repeat; } -.emoji-1F4EC { background: url(emoji.png) -15000px 0px no-repeat; } -.emoji-1F4ED { background: url(emoji.png) -15020px 0px no-repeat; } -.emoji-1F4EE { background: url(emoji.png) -15040px 0px no-repeat; } -.emoji-1F4EF { background: url(emoji.png) -15060px 0px no-repeat; } -.emoji-1F4F0 { background: url(emoji.png) -15080px 0px no-repeat; } -.emoji-1F4F1 { background: url(emoji.png) -15100px 0px no-repeat; } -.emoji-1F4F2 { background: url(emoji.png) -15120px 0px no-repeat; } -.emoji-1F4F3 { background: url(emoji.png) -15140px 0px no-repeat; } -.emoji-1F4F4 { background: url(emoji.png) -15160px 0px no-repeat; } -.emoji-1F4F5 { background: url(emoji.png) -15180px 0px no-repeat; } -.emoji-1F4F6 { background: url(emoji.png) -15200px 0px no-repeat; } -.emoji-1F4F7 { background: url(emoji.png) -15220px 0px no-repeat; } -.emoji-1F4F8 { background: url(emoji.png) -15240px 0px no-repeat; } -.emoji-1F4F9 { background: url(emoji.png) -15260px 0px no-repeat; } -.emoji-1F4FA { background: url(emoji.png) -15280px 0px no-repeat; } -.emoji-1F4FB { background: url(emoji.png) -15300px 0px no-repeat; } -.emoji-1F4FC { background: url(emoji.png) -15320px 0px no-repeat; } -.emoji-1F4FD { background: url(emoji.png) -15340px 0px no-repeat; } -.emoji-1F4FE { background: url(emoji.png) -15360px 0px no-repeat; } -.emoji-1F500 { background: url(emoji.png) -15380px 0px no-repeat; } -.emoji-1F501 { background: url(emoji.png) -15400px 0px no-repeat; } -.emoji-1F502 { background: url(emoji.png) -15420px 0px no-repeat; } -.emoji-1F503 { background: url(emoji.png) -15440px 0px no-repeat; } -.emoji-1F504 { background: url(emoji.png) -15460px 0px no-repeat; } -.emoji-1F505 { background: url(emoji.png) -15480px 0px no-repeat; } -.emoji-1F506 { background: url(emoji.png) -15500px 0px no-repeat; } -.emoji-1F507 { background: url(emoji.png) -15520px 0px no-repeat; } -.emoji-1F508 { background: url(emoji.png) -15540px 0px no-repeat; } -.emoji-1F509 { background: url(emoji.png) -15560px 0px no-repeat; } -.emoji-1F50A { background: url(emoji.png) -15580px 0px no-repeat; } -.emoji-1F50B { background: url(emoji.png) -15600px 0px no-repeat; } -.emoji-1F50C { background: url(emoji.png) -15620px 0px no-repeat; } -.emoji-1F50D { background: url(emoji.png) -15640px 0px no-repeat; } -.emoji-1F50E { background: url(emoji.png) -15660px 0px no-repeat; } -.emoji-1F50F { background: url(emoji.png) -15680px 0px no-repeat; } -.emoji-1F510 { background: url(emoji.png) -15700px 0px no-repeat; } -.emoji-1F511 { background: url(emoji.png) -15720px 0px no-repeat; } -.emoji-1F512 { background: url(emoji.png) -15740px 0px no-repeat; } -.emoji-1F513 { background: url(emoji.png) -15760px 0px no-repeat; } -.emoji-1F514 { background: url(emoji.png) -15780px 0px no-repeat; } -.emoji-1F515 { background: url(emoji.png) -15800px 0px no-repeat; } -.emoji-1F516 { background: url(emoji.png) -15820px 0px no-repeat; } -.emoji-1F517 { background: url(emoji.png) -15840px 0px no-repeat; } -.emoji-1F518 { background: url(emoji.png) -15860px 0px no-repeat; } -.emoji-1F519 { background: url(emoji.png) -15880px 0px no-repeat; } -.emoji-1F51A { background: url(emoji.png) -15900px 0px no-repeat; } -.emoji-1F51B { background: url(emoji.png) -15920px 0px no-repeat; } -.emoji-1F51C { background: url(emoji.png) -15940px 0px no-repeat; } -.emoji-1F51D { background: url(emoji.png) -15960px 0px no-repeat; } -.emoji-1F51E { background: url(emoji.png) -15980px 0px no-repeat; } -.emoji-1F51F { background: url(emoji.png) -16000px 0px no-repeat; } -.emoji-1F520 { background: url(emoji.png) -16020px 0px no-repeat; } -.emoji-1F521 { background: url(emoji.png) -16040px 0px no-repeat; } -.emoji-1F522 { background: url(emoji.png) -16060px 0px no-repeat; } -.emoji-1F523 { background: url(emoji.png) -16080px 0px no-repeat; } -.emoji-1F524 { background: url(emoji.png) -16100px 0px no-repeat; } -.emoji-1F525 { background: url(emoji.png) -16120px 0px no-repeat; } -.emoji-1F526 { background: url(emoji.png) -16140px 0px no-repeat; } -.emoji-1F527 { background: url(emoji.png) -16160px 0px no-repeat; } -.emoji-1F528 { background: url(emoji.png) -16180px 0px no-repeat; } -.emoji-1F529 { background: url(emoji.png) -16200px 0px no-repeat; } -.emoji-1F52A { background: url(emoji.png) -16220px 0px no-repeat; } -.emoji-1F52B { background: url(emoji.png) -16240px 0px no-repeat; } -.emoji-1F52C { background: url(emoji.png) -16260px 0px no-repeat; } -.emoji-1F52D { background: url(emoji.png) -16280px 0px no-repeat; } -.emoji-1F52E { background: url(emoji.png) -16300px 0px no-repeat; } -.emoji-1F52F { background: url(emoji.png) -16320px 0px no-repeat; } -.emoji-1F530 { background: url(emoji.png) -16340px 0px no-repeat; } -.emoji-1F531 { background: url(emoji.png) -16360px 0px no-repeat; } -.emoji-1F532 { background: url(emoji.png) -16380px 0px no-repeat; } -.emoji-1F533 { background: url(emoji.png) -16400px 0px no-repeat; } -.emoji-1F534 { background: url(emoji.png) -16420px 0px no-repeat; } -.emoji-1F535 { background: url(emoji.png) -16440px 0px no-repeat; } -.emoji-1F536 { background: url(emoji.png) -16460px 0px no-repeat; } -.emoji-1F537 { background: url(emoji.png) -16480px 0px no-repeat; } -.emoji-1F538 { background: url(emoji.png) -16500px 0px no-repeat; } -.emoji-1F539 { background: url(emoji.png) -16520px 0px no-repeat; } -.emoji-1F53A { background: url(emoji.png) -16540px 0px no-repeat; } -.emoji-1F53B { background: url(emoji.png) -16560px 0px no-repeat; } -.emoji-1F53C { background: url(emoji.png) -16580px 0px no-repeat; } -.emoji-1F53D { background: url(emoji.png) -16600px 0px no-repeat; } -.emoji-1F546 { background: url(emoji.png) -16620px 0px no-repeat; } -.emoji-1F547 { background: url(emoji.png) -16640px 0px no-repeat; } -.emoji-1F548 { background: url(emoji.png) -16660px 0px no-repeat; } -.emoji-1F549 { background: url(emoji.png) -16680px 0px no-repeat; } -.emoji-1F54A { background: url(emoji.png) -16700px 0px no-repeat; } -.emoji-1F550 { background: url(emoji.png) -16720px 0px no-repeat; } -.emoji-1F551 { background: url(emoji.png) -16740px 0px no-repeat; } -.emoji-1F552 { background: url(emoji.png) -16760px 0px no-repeat; } -.emoji-1F553 { background: url(emoji.png) -16780px 0px no-repeat; } -.emoji-1F554 { background: url(emoji.png) -16800px 0px no-repeat; } -.emoji-1F555 { background: url(emoji.png) -16820px 0px no-repeat; } -.emoji-1F556 { background: url(emoji.png) -16840px 0px no-repeat; } -.emoji-1F557 { background: url(emoji.png) -16860px 0px no-repeat; } -.emoji-1F558 { background: url(emoji.png) -16880px 0px no-repeat; } -.emoji-1F559 { background: url(emoji.png) -16900px 0px no-repeat; } -.emoji-1F55A { background: url(emoji.png) -16920px 0px no-repeat; } -.emoji-1F55B { background: url(emoji.png) -16940px 0px no-repeat; } -.emoji-1F55C { background: url(emoji.png) -16960px 0px no-repeat; } -.emoji-1F55D { background: url(emoji.png) -16980px 0px no-repeat; } -.emoji-1F55E { background: url(emoji.png) -17000px 0px no-repeat; } -.emoji-1F55F { background: url(emoji.png) -17020px 0px no-repeat; } -.emoji-1F560 { background: url(emoji.png) -17040px 0px no-repeat; } -.emoji-1F561 { background: url(emoji.png) -17060px 0px no-repeat; } -.emoji-1F562 { background: url(emoji.png) -17080px 0px no-repeat; } -.emoji-1F563 { background: url(emoji.png) -17100px 0px no-repeat; } -.emoji-1F564 { background: url(emoji.png) -17120px 0px no-repeat; } -.emoji-1F565 { background: url(emoji.png) -17140px 0px no-repeat; } -.emoji-1F566 { background: url(emoji.png) -17160px 0px no-repeat; } -.emoji-1F567 { background: url(emoji.png) -17180px 0px no-repeat; } -.emoji-1F568 { background: url(emoji.png) -17200px 0px no-repeat; } -.emoji-1F569 { background: url(emoji.png) -17220px 0px no-repeat; } -.emoji-1F56A { background: url(emoji.png) -17240px 0px no-repeat; } -.emoji-1F56B { background: url(emoji.png) -17260px 0px no-repeat; } -.emoji-1F56C { background: url(emoji.png) -17280px 0px no-repeat; } -.emoji-1F56D { background: url(emoji.png) -17300px 0px no-repeat; } -.emoji-1F56E { background: url(emoji.png) -17320px 0px no-repeat; } -.emoji-1F56F { background: url(emoji.png) -17340px 0px no-repeat; } -.emoji-1F570 { background: url(emoji.png) -17360px 0px no-repeat; } -.emoji-1F571 { background: url(emoji.png) -17380px 0px no-repeat; } -.emoji-1F572 { background: url(emoji.png) -17400px 0px no-repeat; } -.emoji-1F573 { background: url(emoji.png) -17420px 0px no-repeat; } -.emoji-1F574 { background: url(emoji.png) -17440px 0px no-repeat; } -.emoji-1F575 { background: url(emoji.png) -17460px 0px no-repeat; } -.emoji-1F576 { background: url(emoji.png) -17480px 0px no-repeat; } -.emoji-1F577 { background: url(emoji.png) -17500px 0px no-repeat; } -.emoji-1F578 { background: url(emoji.png) -17520px 0px no-repeat; } -.emoji-1F579 { background: url(emoji.png) -17540px 0px no-repeat; } -.emoji-1F57B { background: url(emoji.png) -17560px 0px no-repeat; } -.emoji-1F57E { background: url(emoji.png) -17580px 0px no-repeat; } -.emoji-1F57F { background: url(emoji.png) -17600px 0px no-repeat; } -.emoji-1F581 { background: url(emoji.png) -17620px 0px no-repeat; } -.emoji-1F582 { background: url(emoji.png) -17640px 0px no-repeat; } -.emoji-1F583 { background: url(emoji.png) -17660px 0px no-repeat; } -.emoji-1F585 { background: url(emoji.png) -17680px 0px no-repeat; } -.emoji-1F586 { background: url(emoji.png) -17700px 0px no-repeat; } -.emoji-1F587 { background: url(emoji.png) -17720px 0px no-repeat; } -.emoji-1F588 { background: url(emoji.png) -17740px 0px no-repeat; } -.emoji-1F589 { background: url(emoji.png) -17760px 0px no-repeat; } -.emoji-1F58A { background: url(emoji.png) -17780px 0px no-repeat; } -.emoji-1F58B { background: url(emoji.png) -17800px 0px no-repeat; } -.emoji-1F58C { background: url(emoji.png) -17820px 0px no-repeat; } -.emoji-1F58D { background: url(emoji.png) -17840px 0px no-repeat; } -.emoji-1F58E { background: url(emoji.png) -17860px 0px no-repeat; } -.emoji-1F58F { background: url(emoji.png) -17880px 0px no-repeat; } -.emoji-1F590 { background: url(emoji.png) -17900px 0px no-repeat; } -.emoji-1F591 { background: url(emoji.png) -17920px 0px no-repeat; } -.emoji-1F592 { background: url(emoji.png) -17940px 0px no-repeat; } -.emoji-1F593 { background: url(emoji.png) -17960px 0px no-repeat; } -.emoji-1F594 { background: url(emoji.png) -17980px 0px no-repeat; } -.emoji-1F595 { background: url(emoji.png) -18000px 0px no-repeat; } -.emoji-1F596 { background: url(emoji.png) -18020px 0px no-repeat; } -.emoji-1F597 { background: url(emoji.png) -18040px 0px no-repeat; } -.emoji-1F598 { background: url(emoji.png) -18060px 0px no-repeat; } -.emoji-1F599 { background: url(emoji.png) -18080px 0px no-repeat; } -.emoji-1F59E { background: url(emoji.png) -18100px 0px no-repeat; } -.emoji-1F59F { background: url(emoji.png) -18120px 0px no-repeat; } -.emoji-1F5A5 { background: url(emoji.png) -18140px 0px no-repeat; } -.emoji-1F5A6 { background: url(emoji.png) -18160px 0px no-repeat; } -.emoji-1F5A7 { background: url(emoji.png) -18180px 0px no-repeat; } -.emoji-1F5A8 { background: url(emoji.png) -18200px 0px no-repeat; } -.emoji-1F5A9 { background: url(emoji.png) -18220px 0px no-repeat; } -.emoji-1F5AA { background: url(emoji.png) -18240px 0px no-repeat; } -.emoji-1F5AB { background: url(emoji.png) -18260px 0px no-repeat; } -.emoji-1F5AD { background: url(emoji.png) -18280px 0px no-repeat; } -.emoji-1F5AE { background: url(emoji.png) -18300px 0px no-repeat; } -.emoji-1F5AF { background: url(emoji.png) -18320px 0px no-repeat; } -.emoji-1F5B2 { background: url(emoji.png) -18340px 0px no-repeat; } -.emoji-1F5B3 { background: url(emoji.png) -18360px 0px no-repeat; } -.emoji-1F5B4 { background: url(emoji.png) -18380px 0px no-repeat; } -.emoji-1F5B8 { background: url(emoji.png) -18400px 0px no-repeat; } -.emoji-1F5B9 { background: url(emoji.png) -18420px 0px no-repeat; } -.emoji-1F5BC { background: url(emoji.png) -18440px 0px no-repeat; } -.emoji-1F5BD { background: url(emoji.png) -18460px 0px no-repeat; } -.emoji-1F5BE { background: url(emoji.png) -18480px 0px no-repeat; } -.emoji-1F5C0 { background: url(emoji.png) -18500px 0px no-repeat; } -.emoji-1F5C1 { background: url(emoji.png) -18520px 0px no-repeat; } -.emoji-1F5C2 { background: url(emoji.png) -18540px 0px no-repeat; } -.emoji-1F5C3 { background: url(emoji.png) -18560px 0px no-repeat; } -.emoji-1F5C4 { background: url(emoji.png) -18580px 0px no-repeat; } -.emoji-1F5C6 { background: url(emoji.png) -18600px 0px no-repeat; } -.emoji-1F5C7 { background: url(emoji.png) -18620px 0px no-repeat; } -.emoji-1F5C9 { background: url(emoji.png) -18640px 0px no-repeat; } -.emoji-1F5CA { background: url(emoji.png) -18660px 0px no-repeat; } -.emoji-1F5CE { background: url(emoji.png) -18680px 0px no-repeat; } -.emoji-1F5CF { background: url(emoji.png) -18700px 0px no-repeat; } -.emoji-1F5D0 { background: url(emoji.png) -18720px 0px no-repeat; } -.emoji-1F5D1 { background: url(emoji.png) -18740px 0px no-repeat; } -.emoji-1F5D2 { background: url(emoji.png) -18760px 0px no-repeat; } -.emoji-1F5D3 { background: url(emoji.png) -18780px 0px no-repeat; } -.emoji-1F5D4 { background: url(emoji.png) -18800px 0px no-repeat; } -.emoji-1F5D8 { background: url(emoji.png) -18820px 0px no-repeat; } -.emoji-1F5D9 { background: url(emoji.png) -18840px 0px no-repeat; } -.emoji-1F5DC { background: url(emoji.png) -18860px 0px no-repeat; } -.emoji-1F5DD { background: url(emoji.png) -18880px 0px no-repeat; } -.emoji-1F5DE { background: url(emoji.png) -18900px 0px no-repeat; } -.emoji-1F5E0 { background: url(emoji.png) -18920px 0px no-repeat; } -.emoji-1F5E1 { background: url(emoji.png) -18940px 0px no-repeat; } -.emoji-1F5E2 { background: url(emoji.png) -18960px 0px no-repeat; } -.emoji-1F5E3 { background: url(emoji.png) -18980px 0px no-repeat; } -.emoji-1F5E8 { background: url(emoji.png) -19000px 0px no-repeat; } -.emoji-1F5E9 { background: url(emoji.png) -19020px 0px no-repeat; } -.emoji-1F5EA { background: url(emoji.png) -19040px 0px no-repeat; } -.emoji-1F5EB { background: url(emoji.png) -19060px 0px no-repeat; } -.emoji-1F5EC { background: url(emoji.png) -19080px 0px no-repeat; } -.emoji-1F5ED { background: url(emoji.png) -19100px 0px no-repeat; } -.emoji-1F5EE { background: url(emoji.png) -19120px 0px no-repeat; } -.emoji-1F5EF { background: url(emoji.png) -19140px 0px no-repeat; } -.emoji-1F5F0 { background: url(emoji.png) -19160px 0px no-repeat; } -.emoji-1F5F1 { background: url(emoji.png) -19180px 0px no-repeat; } -.emoji-1F5F2 { background: url(emoji.png) -19200px 0px no-repeat; } -.emoji-1F5F3 { background: url(emoji.png) -19220px 0px no-repeat; } -.emoji-1F5F4 { background: url(emoji.png) -19240px 0px no-repeat; } -.emoji-1F5F5 { background: url(emoji.png) -19260px 0px no-repeat; } -.emoji-1F5F8 { background: url(emoji.png) -19280px 0px no-repeat; } -.emoji-1F5F9 { background: url(emoji.png) -19300px 0px no-repeat; } -.emoji-1F5FA { background: url(emoji.png) -19320px 0px no-repeat; } -.emoji-1F5FB { background: url(emoji.png) -19340px 0px no-repeat; } -.emoji-1F5FC { background: url(emoji.png) -19360px 0px no-repeat; } -.emoji-1F5FD { background: url(emoji.png) -19380px 0px no-repeat; } -.emoji-1F5FE { background: url(emoji.png) -19400px 0px no-repeat; } -.emoji-1F5FF { background: url(emoji.png) -19420px 0px no-repeat; } -.emoji-1F600 { background: url(emoji.png) -19440px 0px no-repeat; } -.emoji-1F601 { background: url(emoji.png) -19460px 0px no-repeat; } -.emoji-1F602 { background: url(emoji.png) -19480px 0px no-repeat; } -.emoji-1F603 { background: url(emoji.png) -19500px 0px no-repeat; } -.emoji-1F604 { background: url(emoji.png) -19520px 0px no-repeat; } -.emoji-1F605 { background: url(emoji.png) -19540px 0px no-repeat; } -.emoji-1F606 { background: url(emoji.png) -19560px 0px no-repeat; } -.emoji-1F607 { background: url(emoji.png) -19580px 0px no-repeat; } -.emoji-1F608 { background: url(emoji.png) -19600px 0px no-repeat; } -.emoji-1F609 { background: url(emoji.png) -19620px 0px no-repeat; } -.emoji-1F60A { background: url(emoji.png) -19640px 0px no-repeat; } -.emoji-1F60B { background: url(emoji.png) -19660px 0px no-repeat; } -.emoji-1F60C { background: url(emoji.png) -19680px 0px no-repeat; } -.emoji-1F60D { background: url(emoji.png) -19700px 0px no-repeat; } -.emoji-1F60E { background: url(emoji.png) -19720px 0px no-repeat; } -.emoji-1F60F { background: url(emoji.png) -19740px 0px no-repeat; } -.emoji-1F610 { background: url(emoji.png) -19760px 0px no-repeat; } -.emoji-1F611 { background: url(emoji.png) -19780px 0px no-repeat; } -.emoji-1F612 { background: url(emoji.png) -19800px 0px no-repeat; } -.emoji-1F613 { background: url(emoji.png) -19820px 0px no-repeat; } -.emoji-1F614 { background: url(emoji.png) -19840px 0px no-repeat; } -.emoji-1F615 { background: url(emoji.png) -19860px 0px no-repeat; } -.emoji-1F616 { background: url(emoji.png) -19880px 0px no-repeat; } -.emoji-1F617 { background: url(emoji.png) -19900px 0px no-repeat; } -.emoji-1F618 { background: url(emoji.png) -19920px 0px no-repeat; } -.emoji-1F619 { background: url(emoji.png) -19940px 0px no-repeat; } -.emoji-1F61A { background: url(emoji.png) -19960px 0px no-repeat; } -.emoji-1F61B { background: url(emoji.png) -19980px 0px no-repeat; } -.emoji-1F61C { background: url(emoji.png) -20000px 0px no-repeat; } -.emoji-1F61D { background: url(emoji.png) -20020px 0px no-repeat; } -.emoji-1F61E { background: url(emoji.png) -20040px 0px no-repeat; } -.emoji-1F61F { background: url(emoji.png) -20060px 0px no-repeat; } -.emoji-1F620 { background: url(emoji.png) -20080px 0px no-repeat; } -.emoji-1F621 { background: url(emoji.png) -20100px 0px no-repeat; } -.emoji-1F622 { background: url(emoji.png) -20120px 0px no-repeat; } -.emoji-1F623 { background: url(emoji.png) -20140px 0px no-repeat; } -.emoji-1F624 { background: url(emoji.png) -20160px 0px no-repeat; } -.emoji-1F625 { background: url(emoji.png) -20180px 0px no-repeat; } -.emoji-1F626 { background: url(emoji.png) -20200px 0px no-repeat; } -.emoji-1F627 { background: url(emoji.png) -20220px 0px no-repeat; } -.emoji-1F628 { background: url(emoji.png) -20240px 0px no-repeat; } -.emoji-1F629 { background: url(emoji.png) -20260px 0px no-repeat; } -.emoji-1F62A { background: url(emoji.png) -20280px 0px no-repeat; } -.emoji-1F62B { background: url(emoji.png) -20300px 0px no-repeat; } -.emoji-1F62C { background: url(emoji.png) -20320px 0px no-repeat; } -.emoji-1F62D { background: url(emoji.png) -20340px 0px no-repeat; } -.emoji-1F62E { background: url(emoji.png) -20360px 0px no-repeat; } -.emoji-1F62F { background: url(emoji.png) -20380px 0px no-repeat; } -.emoji-1F630 { background: url(emoji.png) -20400px 0px no-repeat; } -.emoji-1F631 { background: url(emoji.png) -20420px 0px no-repeat; } -.emoji-1F632 { background: url(emoji.png) -20440px 0px no-repeat; } -.emoji-1F633 { background: url(emoji.png) -20460px 0px no-repeat; } -.emoji-1F634 { background: url(emoji.png) -20480px 0px no-repeat; } -.emoji-1F635 { background: url(emoji.png) -20500px 0px no-repeat; } -.emoji-1F636 { background: url(emoji.png) -20520px 0px no-repeat; } -.emoji-1F637 { background: url(emoji.png) -20540px 0px no-repeat; } -.emoji-1F638 { background: url(emoji.png) -20560px 0px no-repeat; } -.emoji-1F639 { background: url(emoji.png) -20580px 0px no-repeat; } -.emoji-1F63A { background: url(emoji.png) -20600px 0px no-repeat; } -.emoji-1F63B { background: url(emoji.png) -20620px 0px no-repeat; } -.emoji-1F63C { background: url(emoji.png) -20640px 0px no-repeat; } -.emoji-1F63D { background: url(emoji.png) -20660px 0px no-repeat; } -.emoji-1F63E { background: url(emoji.png) -20680px 0px no-repeat; } -.emoji-1F63F { background: url(emoji.png) -20700px 0px no-repeat; } -.emoji-1F640 { background: url(emoji.png) -20720px 0px no-repeat; } -.emoji-1F641 { background: url(emoji.png) -20740px 0px no-repeat; } -.emoji-1F642 { background: url(emoji.png) -20760px 0px no-repeat; } -.emoji-1F645 { background: url(emoji.png) -20780px 0px no-repeat; } -.emoji-1F646 { background: url(emoji.png) -20800px 0px no-repeat; } -.emoji-1F647 { background: url(emoji.png) -20820px 0px no-repeat; } -.emoji-1F648 { background: url(emoji.png) -20840px 0px no-repeat; } -.emoji-1F649 { background: url(emoji.png) -20860px 0px no-repeat; } -.emoji-1F64A { background: url(emoji.png) -20880px 0px no-repeat; } -.emoji-1F64B { background: url(emoji.png) -20900px 0px no-repeat; } -.emoji-1F64C { background: url(emoji.png) -20920px 0px no-repeat; } -.emoji-1F64D { background: url(emoji.png) -20940px 0px no-repeat; } -.emoji-1F64E { background: url(emoji.png) -20960px 0px no-repeat; } -.emoji-1F64F { background: url(emoji.png) -20980px 0px no-repeat; } -.emoji-1F680 { background: url(emoji.png) -21000px 0px no-repeat; } -.emoji-1F681 { background: url(emoji.png) -21020px 0px no-repeat; } -.emoji-1F682 { background: url(emoji.png) -21040px 0px no-repeat; } -.emoji-1F683 { background: url(emoji.png) -21060px 0px no-repeat; } -.emoji-1F684 { background: url(emoji.png) -21080px 0px no-repeat; } -.emoji-1F685 { background: url(emoji.png) -21100px 0px no-repeat; } -.emoji-1F686 { background: url(emoji.png) -21120px 0px no-repeat; } -.emoji-1F687 { background: url(emoji.png) -21140px 0px no-repeat; } -.emoji-1F688 { background: url(emoji.png) -21160px 0px no-repeat; } -.emoji-1F689 { background: url(emoji.png) -21180px 0px no-repeat; } -.emoji-1F68A { background: url(emoji.png) -21200px 0px no-repeat; } -.emoji-1F68B { background: url(emoji.png) -21220px 0px no-repeat; } -.emoji-1F68C { background: url(emoji.png) -21240px 0px no-repeat; } -.emoji-1F68D { background: url(emoji.png) -21260px 0px no-repeat; } -.emoji-1F68E { background: url(emoji.png) -21280px 0px no-repeat; } -.emoji-1F68F { background: url(emoji.png) -21300px 0px no-repeat; } -.emoji-1F690 { background: url(emoji.png) -21320px 0px no-repeat; } -.emoji-1F691 { background: url(emoji.png) -21340px 0px no-repeat; } -.emoji-1F692 { background: url(emoji.png) -21360px 0px no-repeat; } -.emoji-1F693 { background: url(emoji.png) -21380px 0px no-repeat; } -.emoji-1F694 { background: url(emoji.png) -21400px 0px no-repeat; } -.emoji-1F695 { background: url(emoji.png) -21420px 0px no-repeat; } -.emoji-1F696 { background: url(emoji.png) -21440px 0px no-repeat; } -.emoji-1F697 { background: url(emoji.png) -21460px 0px no-repeat; } -.emoji-1F698 { background: url(emoji.png) -21480px 0px no-repeat; } -.emoji-1F699 { background: url(emoji.png) -21500px 0px no-repeat; } -.emoji-1F69A { background: url(emoji.png) -21520px 0px no-repeat; } -.emoji-1F69B { background: url(emoji.png) -21540px 0px no-repeat; } -.emoji-1F69C { background: url(emoji.png) -21560px 0px no-repeat; } -.emoji-1F69D { background: url(emoji.png) -21580px 0px no-repeat; } -.emoji-1F69E { background: url(emoji.png) -21600px 0px no-repeat; } -.emoji-1F69F { background: url(emoji.png) -21620px 0px no-repeat; } -.emoji-1F6A0 { background: url(emoji.png) -21640px 0px no-repeat; } -.emoji-1F6A1 { background: url(emoji.png) -21660px 0px no-repeat; } -.emoji-1F6A2 { background: url(emoji.png) -21680px 0px no-repeat; } -.emoji-1F6A3 { background: url(emoji.png) -21700px 0px no-repeat; } -.emoji-1F6A4 { background: url(emoji.png) -21720px 0px no-repeat; } -.emoji-1F6A5 { background: url(emoji.png) -21740px 0px no-repeat; } -.emoji-1F6A6 { background: url(emoji.png) -21760px 0px no-repeat; } -.emoji-1F6A7 { background: url(emoji.png) -21780px 0px no-repeat; } -.emoji-1F6A8 { background: url(emoji.png) -21800px 0px no-repeat; } -.emoji-1F6A9 { background: url(emoji.png) -21820px 0px no-repeat; } -.emoji-1F6AA { background: url(emoji.png) -21840px 0px no-repeat; } -.emoji-1F6AB { background: url(emoji.png) -21860px 0px no-repeat; } -.emoji-1F6AC { background: url(emoji.png) -21880px 0px no-repeat; } -.emoji-1F6AD { background: url(emoji.png) -21900px 0px no-repeat; } -.emoji-1F6AE { background: url(emoji.png) -21920px 0px no-repeat; } -.emoji-1F6AF { background: url(emoji.png) -21940px 0px no-repeat; } -.emoji-1F6B0 { background: url(emoji.png) -21960px 0px no-repeat; } -.emoji-1F6B1 { background: url(emoji.png) -21980px 0px no-repeat; } -.emoji-1F6B2 { background: url(emoji.png) -22000px 0px no-repeat; } -.emoji-1F6B3 { background: url(emoji.png) -22020px 0px no-repeat; } -.emoji-1F6B4 { background: url(emoji.png) -22040px 0px no-repeat; } -.emoji-1F6B5 { background: url(emoji.png) -22060px 0px no-repeat; } -.emoji-1F6B6 { background: url(emoji.png) -22080px 0px no-repeat; } -.emoji-1F6B7 { background: url(emoji.png) -22100px 0px no-repeat; } -.emoji-1F6B8 { background: url(emoji.png) -22120px 0px no-repeat; } -.emoji-1F6B9 { background: url(emoji.png) -22140px 0px no-repeat; } -.emoji-1F6BA { background: url(emoji.png) -22160px 0px no-repeat; } -.emoji-1F6BB { background: url(emoji.png) -22180px 0px no-repeat; } -.emoji-1F6BC { background: url(emoji.png) -22200px 0px no-repeat; } -.emoji-1F6BD { background: url(emoji.png) -22220px 0px no-repeat; } -.emoji-1F6BE { background: url(emoji.png) -22240px 0px no-repeat; } -.emoji-1F6BF { background: url(emoji.png) -22260px 0px no-repeat; } -.emoji-1F6C0 { background: url(emoji.png) -22280px 0px no-repeat; } -.emoji-1F6C1 { background: url(emoji.png) -22300px 0px no-repeat; } -.emoji-1F6C2 { background: url(emoji.png) -22320px 0px no-repeat; } -.emoji-1F6C3 { background: url(emoji.png) -22340px 0px no-repeat; } -.emoji-1F6C4 { background: url(emoji.png) -22360px 0px no-repeat; } -.emoji-1F6C5 { background: url(emoji.png) -22380px 0px no-repeat; } -.emoji-1F6C6 { background: url(emoji.png) -22400px 0px no-repeat; } -.emoji-1F6C7 { background: url(emoji.png) -22420px 0px no-repeat; } -.emoji-1F6C8 { background: url(emoji.png) -22440px 0px no-repeat; } -.emoji-1F6C9 { background: url(emoji.png) -22460px 0px no-repeat; } -.emoji-1F6CA { background: url(emoji.png) -22480px 0px no-repeat; } -.emoji-1F6CB { background: url(emoji.png) -22500px 0px no-repeat; } -.emoji-1F6CC { background: url(emoji.png) -22520px 0px no-repeat; } -.emoji-1F6CD { background: url(emoji.png) -22540px 0px no-repeat; } -.emoji-1F6CE { background: url(emoji.png) -22560px 0px no-repeat; } -.emoji-1F6CF { background: url(emoji.png) -22580px 0px no-repeat; } -.emoji-1F6E0 { background: url(emoji.png) -22600px 0px no-repeat; } -.emoji-1F6E1 { background: url(emoji.png) -22620px 0px no-repeat; } -.emoji-1F6E2 { background: url(emoji.png) -22640px 0px no-repeat; } -.emoji-1F6E3 { background: url(emoji.png) -22660px 0px no-repeat; } -.emoji-1F6E4 { background: url(emoji.png) -22680px 0px no-repeat; } -.emoji-1F6E5 { background: url(emoji.png) -22700px 0px no-repeat; } -.emoji-1F6E6 { background: url(emoji.png) -22720px 0px no-repeat; } -.emoji-1F6E7 { background: url(emoji.png) -22740px 0px no-repeat; } -.emoji-1F6E8 { background: url(emoji.png) -22760px 0px no-repeat; } -.emoji-1F6E9 { background: url(emoji.png) -22780px 0px no-repeat; } -.emoji-1F6EA { background: url(emoji.png) -22800px 0px no-repeat; } -.emoji-1F6EB { background: url(emoji.png) -22820px 0px no-repeat; } -.emoji-1F6EC { background: url(emoji.png) -22840px 0px no-repeat; } -.emoji-1F6F0 { background: url(emoji.png) -22860px 0px no-repeat; } -.emoji-1F6F1 { background: url(emoji.png) -22880px 0px no-repeat; } -.emoji-1F6F2 { background: url(emoji.png) -22900px 0px no-repeat; } -.emoji-1F6F3 { background: url(emoji.png) -22920px 0px no-repeat; } -.emoji-203C { background: url(emoji.png) -22940px 0px no-repeat; } -.emoji-2049 { background: url(emoji.png) -22960px 0px no-repeat; } -.emoji-2122 { background: url(emoji.png) -22980px 0px no-repeat; } -.emoji-2139 { background: url(emoji.png) -23000px 0px no-repeat; } -.emoji-2194 { background: url(emoji.png) -23020px 0px no-repeat; } -.emoji-2195 { background: url(emoji.png) -23040px 0px no-repeat; } -.emoji-2196 { background: url(emoji.png) -23060px 0px no-repeat; } -.emoji-2197 { background: url(emoji.png) -23080px 0px no-repeat; } -.emoji-2198 { background: url(emoji.png) -23100px 0px no-repeat; } -.emoji-2199 { background: url(emoji.png) -23120px 0px no-repeat; } -.emoji-21A9 { background: url(emoji.png) -23140px 0px no-repeat; } -.emoji-21AA { background: url(emoji.png) -23160px 0px no-repeat; } -.emoji-231A { background: url(emoji.png) -23180px 0px no-repeat; } -.emoji-231B { background: url(emoji.png) -23200px 0px no-repeat; } -.emoji-23E9 { background: url(emoji.png) -23220px 0px no-repeat; } -.emoji-23EA { background: url(emoji.png) -23240px 0px no-repeat; } -.emoji-23EB { background: url(emoji.png) -23260px 0px no-repeat; } -.emoji-23EC { background: url(emoji.png) -23280px 0px no-repeat; } -.emoji-23F0 { background: url(emoji.png) -23300px 0px no-repeat; } -.emoji-23F3 { background: url(emoji.png) -23320px 0px no-repeat; } -.emoji-24C2 { background: url(emoji.png) -23340px 0px no-repeat; } -.emoji-25AA { background: url(emoji.png) -23360px 0px no-repeat; } -.emoji-25AB { background: url(emoji.png) -23380px 0px no-repeat; } -.emoji-25B6 { background: url(emoji.png) -23400px 0px no-repeat; } -.emoji-25C0 { background: url(emoji.png) -23420px 0px no-repeat; } -.emoji-25FB { background: url(emoji.png) -23440px 0px no-repeat; } -.emoji-25FC { background: url(emoji.png) -23460px 0px no-repeat; } -.emoji-25FD { background: url(emoji.png) -23480px 0px no-repeat; } -.emoji-25FE { background: url(emoji.png) -23500px 0px no-repeat; } -.emoji-2600 { background: url(emoji.png) -23520px 0px no-repeat; } -.emoji-2601 { background: url(emoji.png) -23540px 0px no-repeat; } -.emoji-260E { background: url(emoji.png) -23560px 0px no-repeat; } -.emoji-2611 { background: url(emoji.png) -23580px 0px no-repeat; } -.emoji-2614 { background: url(emoji.png) -23600px 0px no-repeat; } -.emoji-2615 { background: url(emoji.png) -23620px 0px no-repeat; } -.emoji-261D { background: url(emoji.png) -23640px 0px no-repeat; } -.emoji-263A { background: url(emoji.png) -23660px 0px no-repeat; } -.emoji-2648 { background: url(emoji.png) -23680px 0px no-repeat; } -.emoji-2649 { background: url(emoji.png) -23700px 0px no-repeat; } -.emoji-264A { background: url(emoji.png) -23720px 0px no-repeat; } -.emoji-264B { background: url(emoji.png) -23740px 0px no-repeat; } -.emoji-264C { background: url(emoji.png) -23760px 0px no-repeat; } -.emoji-264D { background: url(emoji.png) -23780px 0px no-repeat; } -.emoji-264E { background: url(emoji.png) -23800px 0px no-repeat; } -.emoji-264F { background: url(emoji.png) -23820px 0px no-repeat; } -.emoji-2650 { background: url(emoji.png) -23840px 0px no-repeat; } -.emoji-2651 { background: url(emoji.png) -23860px 0px no-repeat; } -.emoji-2652 { background: url(emoji.png) -23880px 0px no-repeat; } -.emoji-2653 { background: url(emoji.png) -23900px 0px no-repeat; } -.emoji-2660 { background: url(emoji.png) -23920px 0px no-repeat; } -.emoji-2663 { background: url(emoji.png) -23940px 0px no-repeat; } -.emoji-2665 { background: url(emoji.png) -23960px 0px no-repeat; } -.emoji-2666 { background: url(emoji.png) -23980px 0px no-repeat; } -.emoji-2668 { background: url(emoji.png) -24000px 0px no-repeat; } -.emoji-267B { background: url(emoji.png) -24020px 0px no-repeat; } -.emoji-267F { background: url(emoji.png) -24040px 0px no-repeat; } -.emoji-2693 { background: url(emoji.png) -24060px 0px no-repeat; } -.emoji-26A0 { background: url(emoji.png) -24080px 0px no-repeat; } -.emoji-26A1 { background: url(emoji.png) -24100px 0px no-repeat; } -.emoji-26AA { background: url(emoji.png) -24120px 0px no-repeat; } -.emoji-26AB { background: url(emoji.png) -24140px 0px no-repeat; } -.emoji-26BD { background: url(emoji.png) -24160px 0px no-repeat; } -.emoji-26BE { background: url(emoji.png) -24180px 0px no-repeat; } -.emoji-26C4 { background: url(emoji.png) -24200px 0px no-repeat; } -.emoji-26C5 { background: url(emoji.png) -24220px 0px no-repeat; } -.emoji-26CE { background: url(emoji.png) -24240px 0px no-repeat; } -.emoji-26D4 { background: url(emoji.png) -24260px 0px no-repeat; } -.emoji-26EA { background: url(emoji.png) -24280px 0px no-repeat; } -.emoji-26F2 { background: url(emoji.png) -24300px 0px no-repeat; } -.emoji-26F3 { background: url(emoji.png) -24320px 0px no-repeat; } -.emoji-26F5 { background: url(emoji.png) -24340px 0px no-repeat; } -.emoji-26FA { background: url(emoji.png) -24360px 0px no-repeat; } -.emoji-26FD { background: url(emoji.png) -24380px 0px no-repeat; } -.emoji-2702 { background: url(emoji.png) -24400px 0px no-repeat; } -.emoji-2705 { background: url(emoji.png) -24420px 0px no-repeat; } -.emoji-2708 { background: url(emoji.png) -24440px 0px no-repeat; } -.emoji-2709 { background: url(emoji.png) -24460px 0px no-repeat; } -.emoji-270A { background: url(emoji.png) -24480px 0px no-repeat; } -.emoji-270B { background: url(emoji.png) -24500px 0px no-repeat; } -.emoji-270C { background: url(emoji.png) -24520px 0px no-repeat; } -.emoji-270F { background: url(emoji.png) -24540px 0px no-repeat; } -.emoji-2712 { background: url(emoji.png) -24560px 0px no-repeat; } -.emoji-2714 { background: url(emoji.png) -24580px 0px no-repeat; } -.emoji-2716 { background: url(emoji.png) -24600px 0px no-repeat; } -.emoji-2728 { background: url(emoji.png) -24620px 0px no-repeat; } -.emoji-2733 { background: url(emoji.png) -24640px 0px no-repeat; } -.emoji-2734 { background: url(emoji.png) -24660px 0px no-repeat; } -.emoji-2744 { background: url(emoji.png) -24680px 0px no-repeat; } -.emoji-2747 { background: url(emoji.png) -24700px 0px no-repeat; } -.emoji-274C { background: url(emoji.png) -24720px 0px no-repeat; } -.emoji-274E { background: url(emoji.png) -24740px 0px no-repeat; } -.emoji-2753 { background: url(emoji.png) -24760px 0px no-repeat; } -.emoji-2754 { background: url(emoji.png) -24780px 0px no-repeat; } -.emoji-2755 { background: url(emoji.png) -24800px 0px no-repeat; } -.emoji-2757 { background: url(emoji.png) -24820px 0px no-repeat; } -.emoji-2764 { background: url(emoji.png) -24840px 0px no-repeat; } -.emoji-2795 { background: url(emoji.png) -24860px 0px no-repeat; } -.emoji-2796 { background: url(emoji.png) -24880px 0px no-repeat; } -.emoji-2797 { background: url(emoji.png) -24900px 0px no-repeat; } -.emoji-27A1 { background: url(emoji.png) -24920px 0px no-repeat; } -.emoji-27B0 { background: url(emoji.png) -24940px 0px no-repeat; } -.emoji-27BF { background: url(emoji.png) -24960px 0px no-repeat; } -.emoji-2934 { background: url(emoji.png) -24980px 0px no-repeat; } -.emoji-2935 { background: url(emoji.png) -25000px 0px no-repeat; } -.emoji-2B05 { background: url(emoji.png) -25020px 0px no-repeat; } -.emoji-2B06 { background: url(emoji.png) -25040px 0px no-repeat; } -.emoji-2B07 { background: url(emoji.png) -25060px 0px no-repeat; } -.emoji-2B1B { background: url(emoji.png) -25080px 0px no-repeat; } -.emoji-2B1C { background: url(emoji.png) -25100px 0px no-repeat; } -.emoji-2B50 { background: url(emoji.png) -25120px 0px no-repeat; } -.emoji-2B55 { background: url(emoji.png) -25140px 0px no-repeat; } -.emoji-3030 { background: url(emoji.png) -25160px 0px no-repeat; } -.emoji-303D { background: url(emoji.png) -25180px 0px no-repeat; } -.emoji-3297 { background: url(emoji.png) -25200px 0px no-repeat; } -.emoji-3299 { background: url(emoji.png) -25220px 0px no-repeat; } \ No newline at end of file +.emoji-icon{ + background-image: url(emoji.png); + background-repeat: no-repeat; +} + +.emoji-0023-20E3 { background-position: 0px 0px; } +.emoji-0030-20E3 { background-position: -20px 0px; } +.emoji-0031-20E3 { background-position: -40px 0px; } +.emoji-0032-20E3 { background-position: -60px 0px; } +.emoji-0033-20E3 { background-position: -80px 0px; } +.emoji-0034-20E3 { background-position: -100px 0px; } +.emoji-0035-20E3 { background-position: -120px 0px; } +.emoji-0036-20E3 { background-position: -140px 0px; } +.emoji-0037-20E3 { background-position: -160px 0px; } +.emoji-0038-20E3 { background-position: -180px 0px; } +.emoji-0039-20E3 { background-position: -200px 0px; } +.emoji-00A9 { background-position: -220px 0px; } +.emoji-00AE { background-position: -240px 0px; } +.emoji-1F004 { background-position: -260px 0px; } +.emoji-1F0CF { background-position: -280px 0px; } +.emoji-1F170 { background-position: -300px 0px; } +.emoji-1F171 { background-position: -320px 0px; } +.emoji-1F17E { background-position: -340px 0px; } +.emoji-1F17F { background-position: -360px 0px; } +.emoji-1F18E { background-position: -380px 0px; } +.emoji-1F191 { background-position: -400px 0px; } +.emoji-1F192 { background-position: -420px 0px; } +.emoji-1F193 { background-position: -440px 0px; } +.emoji-1F194 { background-position: -460px 0px; } +.emoji-1F195 { background-position: -480px 0px; } +.emoji-1F196 { background-position: -500px 0px; } +.emoji-1F197 { background-position: -520px 0px; } +.emoji-1F198 { background-position: -540px 0px; } +.emoji-1F199 { background-position: -560px 0px; } +.emoji-1F19A { background-position: -580px 0px; } +.emoji-1F1E6-1F1E8 { background-position: -600px 0px; } +.emoji-1F1E6-1F1E9 { background-position: -620px 0px; } +.emoji-1F1E6-1F1EA { background-position: -640px 0px; } +.emoji-1F1E6-1F1EB { background-position: -660px 0px; } +.emoji-1F1E6-1F1EC { background-position: -680px 0px; } +.emoji-1F1E6-1F1EE { background-position: -700px 0px; } +.emoji-1F1E6-1F1F1 { background-position: -720px 0px; } +.emoji-1F1E6-1F1F2 { background-position: -740px 0px; } +.emoji-1F1E6-1F1F4 { background-position: -760px 0px; } +.emoji-1F1E6-1F1F7 { background-position: -780px 0px; } +.emoji-1F1E6-1F1F9 { background-position: -800px 0px; } +.emoji-1F1E6-1F1FA { background-position: -820px 0px; } +.emoji-1F1E6-1F1FC { background-position: -840px 0px; } +.emoji-1F1E6-1F1FF { background-position: -860px 0px; } +.emoji-1F1E7-1F1E6 { background-position: -880px 0px; } +.emoji-1F1E7-1F1E7 { background-position: -900px 0px; } +.emoji-1F1E7-1F1E9 { background-position: -920px 0px; } +.emoji-1F1E7-1F1EA { background-position: -940px 0px; } +.emoji-1F1E7-1F1EB { background-position: -960px 0px; } +.emoji-1F1E7-1F1EC { background-position: -980px 0px; } +.emoji-1F1E7-1F1ED { background-position: -1000px 0px; } +.emoji-1F1E7-1F1EE { background-position: -1020px 0px; } +.emoji-1F1E7-1F1EF { background-position: -1040px 0px; } +.emoji-1F1E7-1F1F2 { background-position: -1060px 0px; } +.emoji-1F1E7-1F1F3 { background-position: -1080px 0px; } +.emoji-1F1E7-1F1F4 { background-position: -1100px 0px; } +.emoji-1F1E7-1F1F7 { background-position: -1120px 0px; } +.emoji-1F1E7-1F1F8 { background-position: -1140px 0px; } +.emoji-1F1E7-1F1F9 { background-position: -1160px 0px; } +.emoji-1F1E7-1F1FC { background-position: -1180px 0px; } +.emoji-1F1E7-1F1FE { background-position: -1200px 0px; } +.emoji-1F1E7-1F1FF { background-position: -1220px 0px; } +.emoji-1F1E8-1F1E6 { background-position: -1240px 0px; } +.emoji-1F1E8-1F1E9 { background-position: -1260px 0px; } +.emoji-1F1E8-1F1EB { background-position: -1280px 0px; } +.emoji-1F1E8-1F1EC { background-position: -1300px 0px; } +.emoji-1F1E8-1F1ED { background-position: -1320px 0px; } +.emoji-1F1E8-1F1EE { background-position: -1340px 0px; } +.emoji-1F1E8-1F1F1 { background-position: -1360px 0px; } +.emoji-1F1E8-1F1F2 { background-position: -1380px 0px; } +.emoji-1F1E8-1F1F3 { background-position: -1400px 0px; } +.emoji-1F1E8-1F1F4 { background-position: -1420px 0px; } +.emoji-1F1E8-1F1F7 { background-position: -1440px 0px; } +.emoji-1F1E8-1F1FA { background-position: -1460px 0px; } +.emoji-1F1E8-1F1FB { background-position: -1480px 0px; } +.emoji-1F1E8-1F1FE { background-position: -1500px 0px; } +.emoji-1F1E8-1F1FF { background-position: -1520px 0px; } +.emoji-1F1E9-1F1EA { background-position: -1540px 0px; } +.emoji-1F1E9-1F1EF { background-position: -1560px 0px; } +.emoji-1F1E9-1F1F0 { background-position: -1580px 0px; } +.emoji-1F1E9-1F1F2 { background-position: -1600px 0px; } +.emoji-1F1E9-1F1F4 { background-position: -1620px 0px; } +.emoji-1F1E9-1F1FF { background-position: -1640px 0px; } +.emoji-1F1EA-1F1E8 { background-position: -1660px 0px; } +.emoji-1F1EA-1F1EA { background-position: -1680px 0px; } +.emoji-1F1EA-1F1EC { background-position: -1700px 0px; } +.emoji-1F1EA-1F1ED { background-position: -1720px 0px; } +.emoji-1F1EA-1F1F7 { background-position: -1740px 0px; } +.emoji-1F1EA-1F1F8 { background-position: -1760px 0px; } +.emoji-1F1EA-1F1F9 { background-position: -1780px 0px; } +.emoji-1F1EB-1F1EE { background-position: -1800px 0px; } +.emoji-1F1EB-1F1EF { background-position: -1820px 0px; } +.emoji-1F1EB-1F1F0 { background-position: -1840px 0px; } +.emoji-1F1EB-1F1F2 { background-position: -1860px 0px; } +.emoji-1F1EB-1F1F4 { background-position: -1880px 0px; } +.emoji-1F1EB-1F1F7 { background-position: -1900px 0px; } +.emoji-1F1EC-1F1E6 { background-position: -1920px 0px; } +.emoji-1F1EC-1F1E7 { background-position: -1940px 0px; } +.emoji-1F1EC-1F1E9 { background-position: -1960px 0px; } +.emoji-1F1EC-1F1EA { background-position: -1980px 0px; } +.emoji-1F1EC-1F1ED { background-position: -2000px 0px; } +.emoji-1F1EC-1F1EE { background-position: -2020px 0px; } +.emoji-1F1EC-1F1F1 { background-position: -2040px 0px; } +.emoji-1F1EC-1F1F2 { background-position: -2060px 0px; } +.emoji-1F1EC-1F1F3 { background-position: -2080px 0px; } +.emoji-1F1EC-1F1F6 { background-position: -2100px 0px; } +.emoji-1F1EC-1F1F7 { background-position: -2120px 0px; } +.emoji-1F1EC-1F1F9 { background-position: -2140px 0px; } +.emoji-1F1EC-1F1FA { background-position: -2160px 0px; } +.emoji-1F1EC-1F1FC { background-position: -2180px 0px; } +.emoji-1F1EC-1F1FE { background-position: -2200px 0px; } +.emoji-1F1ED-1F1F0 { background-position: -2220px 0px; } +.emoji-1F1ED-1F1F3 { background-position: -2240px 0px; } +.emoji-1F1ED-1F1F7 { background-position: -2260px 0px; } +.emoji-1F1ED-1F1F9 { background-position: -2280px 0px; } +.emoji-1F1ED-1F1FA { background-position: -2300px 0px; } +.emoji-1F1EE-1F1E9 { background-position: -2320px 0px; } +.emoji-1F1EE-1F1EA { background-position: -2340px 0px; } +.emoji-1F1EE-1F1F1 { background-position: -2360px 0px; } +.emoji-1F1EE-1F1F3 { background-position: -2380px 0px; } +.emoji-1F1EE-1F1F6 { background-position: -2400px 0px; } +.emoji-1F1EE-1F1F7 { background-position: -2420px 0px; } +.emoji-1F1EE-1F1F8 { background-position: -2440px 0px; } +.emoji-1F1EE-1F1F9 { background-position: -2460px 0px; } +.emoji-1F1EF-1F1EA { background-position: -2480px 0px; } +.emoji-1F1EF-1F1F2 { background-position: -2500px 0px; } +.emoji-1F1EF-1F1F4 { background-position: -2520px 0px; } +.emoji-1F1EF-1F1F5 { background-position: -2540px 0px; } +.emoji-1F1F0-1F1EA { background-position: -2560px 0px; } +.emoji-1F1F0-1F1EC { background-position: -2580px 0px; } +.emoji-1F1F0-1F1ED { background-position: -2600px 0px; } +.emoji-1F1F0-1F1EE { background-position: -2620px 0px; } +.emoji-1F1F0-1F1F2 { background-position: -2640px 0px; } +.emoji-1F1F0-1F1F3 { background-position: -2660px 0px; } +.emoji-1F1F0-1F1F5 { background-position: -2680px 0px; } +.emoji-1F1F0-1F1F7 { background-position: -2700px 0px; } +.emoji-1F1F0-1F1FC { background-position: -2720px 0px; } +.emoji-1F1F0-1F1FE { background-position: -2740px 0px; } +.emoji-1F1F0-1F1FF { background-position: -2760px 0px; } +.emoji-1F1F1-1F1E6 { background-position: -2780px 0px; } +.emoji-1F1F1-1F1E7 { background-position: -2800px 0px; } +.emoji-1F1F1-1F1E8 { background-position: -2820px 0px; } +.emoji-1F1F1-1F1EE { background-position: -2840px 0px; } +.emoji-1F1F1-1F1F0 { background-position: -2860px 0px; } +.emoji-1F1F1-1F1F7 { background-position: -2880px 0px; } +.emoji-1F1F1-1F1F8 { background-position: -2900px 0px; } +.emoji-1F1F1-1F1F9 { background-position: -2920px 0px; } +.emoji-1F1F1-1F1FA { background-position: -2940px 0px; } +.emoji-1F1F1-1F1FB { background-position: -2960px 0px; } +.emoji-1F1F1-1F1FE { background-position: -2980px 0px; } +.emoji-1F1F2-1F1E6 { background-position: -3000px 0px; } +.emoji-1F1F2-1F1E8 { background-position: -3020px 0px; } +.emoji-1F1F2-1F1E9 { background-position: -3040px 0px; } +.emoji-1F1F2-1F1EA { background-position: -3060px 0px; } +.emoji-1F1F2-1F1EC { background-position: -3080px 0px; } +.emoji-1F1F2-1F1ED { background-position: -3100px 0px; } +.emoji-1F1F2-1F1F0 { background-position: -3120px 0px; } +.emoji-1F1F2-1F1F1 { background-position: -3140px 0px; } +.emoji-1F1F2-1F1F2 { background-position: -3160px 0px; } +.emoji-1F1F2-1F1F3 { background-position: -3180px 0px; } +.emoji-1F1F2-1F1F4 { background-position: -3200px 0px; } +.emoji-1F1F2-1F1F7 { background-position: -3220px 0px; } +.emoji-1F1F2-1F1F8 { background-position: -3240px 0px; } +.emoji-1F1F2-1F1F9 { background-position: -3260px 0px; } +.emoji-1F1F2-1F1FA { background-position: -3280px 0px; } +.emoji-1F1F2-1F1FB { background-position: -3300px 0px; } +.emoji-1F1F2-1F1FC { background-position: -3320px 0px; } +.emoji-1F1F2-1F1FD { background-position: -3340px 0px; } +.emoji-1F1F2-1F1FE { background-position: -3360px 0px; } +.emoji-1F1F2-1F1FF { background-position: -3380px 0px; } +.emoji-1F1F3-1F1E6 { background-position: -3400px 0px; } +.emoji-1F1F3-1F1E8 { background-position: -3420px 0px; } +.emoji-1F1F3-1F1EA { background-position: -3440px 0px; } +.emoji-1F1F3-1F1EC { background-position: -3460px 0px; } +.emoji-1F1F3-1F1EE { background-position: -3480px 0px; } +.emoji-1F1F3-1F1F1 { background-position: -3500px 0px; } +.emoji-1F1F3-1F1F4 { background-position: -3520px 0px; } +.emoji-1F1F3-1F1F5 { background-position: -3540px 0px; } +.emoji-1F1F3-1F1F7 { background-position: -3560px 0px; } +.emoji-1F1F3-1F1FA { background-position: -3580px 0px; } +.emoji-1F1F3-1F1FF { background-position: -3600px 0px; } +.emoji-1F1F4-1F1F2 { background-position: -3620px 0px; } +.emoji-1F1F5-1F1E6 { background-position: -3640px 0px; } +.emoji-1F1F5-1F1EA { background-position: -3660px 0px; } +.emoji-1F1F5-1F1EB { background-position: -3680px 0px; } +.emoji-1F1F5-1F1EC { background-position: -3700px 0px; } +.emoji-1F1F5-1F1ED { background-position: -3720px 0px; } +.emoji-1F1F5-1F1F0 { background-position: -3740px 0px; } +.emoji-1F1F5-1F1F1 { background-position: -3760px 0px; } +.emoji-1F1F5-1F1F7 { background-position: -3780px 0px; } +.emoji-1F1F5-1F1F8 { background-position: -3800px 0px; } +.emoji-1F1F5-1F1F9 { background-position: -3820px 0px; } +.emoji-1F1F5-1F1FC { background-position: -3840px 0px; } +.emoji-1F1F5-1F1FE { background-position: -3860px 0px; } +.emoji-1F1F6-1F1E6 { background-position: -3880px 0px; } +.emoji-1F1F7-1F1F4 { background-position: -3900px 0px; } +.emoji-1F1F7-1F1F8 { background-position: -3920px 0px; } +.emoji-1F1F7-1F1FA { background-position: -3940px 0px; } +.emoji-1F1F7-1F1FC { background-position: -3960px 0px; } +.emoji-1F1F8-1F1E6 { background-position: -3980px 0px; } +.emoji-1F1F8-1F1E7 { background-position: -4000px 0px; } +.emoji-1F1F8-1F1E8 { background-position: -4020px 0px; } +.emoji-1F1F8-1F1E9 { background-position: -4040px 0px; } +.emoji-1F1F8-1F1EA { background-position: -4060px 0px; } +.emoji-1F1F8-1F1EC { background-position: -4080px 0px; } +.emoji-1F1F8-1F1ED { background-position: -4100px 0px; } +.emoji-1F1F8-1F1EE { background-position: -4120px 0px; } +.emoji-1F1F8-1F1F0 { background-position: -4140px 0px; } +.emoji-1F1F8-1F1F1 { background-position: -4160px 0px; } +.emoji-1F1F8-1F1F2 { background-position: -4180px 0px; } +.emoji-1F1F8-1F1F3 { background-position: -4200px 0px; } +.emoji-1F1F8-1F1F4 { background-position: -4220px 0px; } +.emoji-1F1F8-1F1F7 { background-position: -4240px 0px; } +.emoji-1F1F8-1F1F9 { background-position: -4260px 0px; } +.emoji-1F1F8-1F1FB { background-position: -4280px 0px; } +.emoji-1F1F8-1F1FE { background-position: -4300px 0px; } +.emoji-1F1F8-1F1FF { background-position: -4320px 0px; } +.emoji-1F1F9-1F1E9 { background-position: -4340px 0px; } +.emoji-1F1F9-1F1EC { background-position: -4360px 0px; } +.emoji-1F1F9-1F1ED { background-position: -4380px 0px; } +.emoji-1F1F9-1F1EF { background-position: -4400px 0px; } +.emoji-1F1F9-1F1F1 { background-position: -4420px 0px; } +.emoji-1F1F9-1F1F2 { background-position: -4440px 0px; } +.emoji-1F1F9-1F1F3 { background-position: -4460px 0px; } +.emoji-1F1F9-1F1F4 { background-position: -4480px 0px; } +.emoji-1F1F9-1F1F7 { background-position: -4500px 0px; } +.emoji-1F1F9-1F1F9 { background-position: -4520px 0px; } +.emoji-1F1F9-1F1FB { background-position: -4540px 0px; } +.emoji-1F1F9-1F1FC { background-position: -4560px 0px; } +.emoji-1F1F9-1F1FF { background-position: -4580px 0px; } +.emoji-1F1FA-1F1E6 { background-position: -4600px 0px; } +.emoji-1F1FA-1F1EC { background-position: -4620px 0px; } +.emoji-1F1FA-1F1F8 { background-position: -4640px 0px; } +.emoji-1F1FA-1F1FE { background-position: -4660px 0px; } +.emoji-1F1FA-1F1FF { background-position: -4680px 0px; } +.emoji-1F1FB-1F1E6 { background-position: -4700px 0px; } +.emoji-1F1FB-1F1E8 { background-position: -4720px 0px; } +.emoji-1F1FB-1F1EA { background-position: -4740px 0px; } +.emoji-1F1FB-1F1EE { background-position: -4760px 0px; } +.emoji-1F1FB-1F1F3 { background-position: -4780px 0px; } +.emoji-1F1FB-1F1FA { background-position: -4800px 0px; } +.emoji-1F1FC-1F1EB { background-position: -4820px 0px; } +.emoji-1F1FC-1F1F8 { background-position: -4840px 0px; } +.emoji-1F1FD-1F1F0 { background-position: -4860px 0px; } +.emoji-1F1FE-1F1EA { background-position: -4880px 0px; } +.emoji-1F1FF-1F1E6 { background-position: -4900px 0px; } +.emoji-1F1FF-1F1F2 { background-position: -4920px 0px; } +.emoji-1F1FF-1F1FC { background-position: -4940px 0px; } +.emoji-1F201 { background-position: -4960px 0px; } +.emoji-1F202 { background-position: -4980px 0px; } +.emoji-1F21A { background-position: -5000px 0px; } +.emoji-1F22F { background-position: -5020px 0px; } +.emoji-1F232 { background-position: -5040px 0px; } +.emoji-1F233 { background-position: -5060px 0px; } +.emoji-1F234 { background-position: -5080px 0px; } +.emoji-1F235 { background-position: -5100px 0px; } +.emoji-1F236 { background-position: -5120px 0px; } +.emoji-1F237 { background-position: -5140px 0px; } +.emoji-1F238 { background-position: -5160px 0px; } +.emoji-1F239 { background-position: -5180px 0px; } +.emoji-1F23A { background-position: -5200px 0px; } +.emoji-1F250 { background-position: -5220px 0px; } +.emoji-1F251 { background-position: -5240px 0px; } +.emoji-1F300 { background-position: -5260px 0px; } +.emoji-1F301 { background-position: -5280px 0px; } +.emoji-1F302 { background-position: -5300px 0px; } +.emoji-1F303 { background-position: -5320px 0px; } +.emoji-1F304 { background-position: -5340px 0px; } +.emoji-1F305 { background-position: -5360px 0px; } +.emoji-1F306 { background-position: -5380px 0px; } +.emoji-1F307 { background-position: -5400px 0px; } +.emoji-1F308 { background-position: -5420px 0px; } +.emoji-1F309 { background-position: -5440px 0px; } +.emoji-1F30A { background-position: -5460px 0px; } +.emoji-1F30B { background-position: -5480px 0px; } +.emoji-1F30C { background-position: -5500px 0px; } +.emoji-1F30D { background-position: -5520px 0px; } +.emoji-1F30E { background-position: -5540px 0px; } +.emoji-1F30F { background-position: -5560px 0px; } +.emoji-1F310 { background-position: -5580px 0px; } +.emoji-1F311 { background-position: -5600px 0px; } +.emoji-1F312 { background-position: -5620px 0px; } +.emoji-1F313 { background-position: -5640px 0px; } +.emoji-1F314 { background-position: -5660px 0px; } +.emoji-1F315 { background-position: -5680px 0px; } +.emoji-1F316 { background-position: -5700px 0px; } +.emoji-1F317 { background-position: -5720px 0px; } +.emoji-1F318 { background-position: -5740px 0px; } +.emoji-1F319 { background-position: -5760px 0px; } +.emoji-1F31A { background-position: -5780px 0px; } +.emoji-1F31B { background-position: -5800px 0px; } +.emoji-1F31C { background-position: -5820px 0px; } +.emoji-1F31D { background-position: -5840px 0px; } +.emoji-1F31E { background-position: -5860px 0px; } +.emoji-1F31F { background-position: -5880px 0px; } +.emoji-1F320 { background-position: -5900px 0px; } +.emoji-1F321 { background-position: -5920px 0px; } +.emoji-1F327 { background-position: -5940px 0px; } +.emoji-1F328 { background-position: -5960px 0px; } +.emoji-1F329 { background-position: -5980px 0px; } +.emoji-1F32A { background-position: -6000px 0px; } +.emoji-1F32B { background-position: -6020px 0px; } +.emoji-1F32C { background-position: -6040px 0px; } +.emoji-1F330 { background-position: -6060px 0px; } +.emoji-1F331 { background-position: -6080px 0px; } +.emoji-1F332 { background-position: -6100px 0px; } +.emoji-1F333 { background-position: -6120px 0px; } +.emoji-1F334 { background-position: -6140px 0px; } +.emoji-1F335 { background-position: -6160px 0px; } +.emoji-1F336 { background-position: -6180px 0px; } +.emoji-1F337 { background-position: -6200px 0px; } +.emoji-1F338 { background-position: -6220px 0px; } +.emoji-1F339 { background-position: -6240px 0px; } +.emoji-1F33A { background-position: -6260px 0px; } +.emoji-1F33B { background-position: -6280px 0px; } +.emoji-1F33C { background-position: -6300px 0px; } +.emoji-1F33D { background-position: -6320px 0px; } +.emoji-1F33E { background-position: -6340px 0px; } +.emoji-1F33F { background-position: -6360px 0px; } +.emoji-1F340 { background-position: -6380px 0px; } +.emoji-1F341 { background-position: -6400px 0px; } +.emoji-1F342 { background-position: -6420px 0px; } +.emoji-1F343 { background-position: -6440px 0px; } +.emoji-1F344 { background-position: -6460px 0px; } +.emoji-1F345 { background-position: -6480px 0px; } +.emoji-1F346 { background-position: -6500px 0px; } +.emoji-1F347 { background-position: -6520px 0px; } +.emoji-1F348 { background-position: -6540px 0px; } +.emoji-1F349 { background-position: -6560px 0px; } +.emoji-1F34A { background-position: -6580px 0px; } +.emoji-1F34B { background-position: -6600px 0px; } +.emoji-1F34C { background-position: -6620px 0px; } +.emoji-1F34D { background-position: -6640px 0px; } +.emoji-1F34E { background-position: -6660px 0px; } +.emoji-1F34F { background-position: -6680px 0px; } +.emoji-1F350 { background-position: -6700px 0px; } +.emoji-1F351 { background-position: -6720px 0px; } +.emoji-1F352 { background-position: -6740px 0px; } +.emoji-1F353 { background-position: -6760px 0px; } +.emoji-1F354 { background-position: -6780px 0px; } +.emoji-1F355 { background-position: -6800px 0px; } +.emoji-1F356 { background-position: -6820px 0px; } +.emoji-1F357 { background-position: -6840px 0px; } +.emoji-1F358 { background-position: -6860px 0px; } +.emoji-1F359 { background-position: -6880px 0px; } +.emoji-1F35A { background-position: -6900px 0px; } +.emoji-1F35B { background-position: -6920px 0px; } +.emoji-1F35C { background-position: -6940px 0px; } +.emoji-1F35D { background-position: -6960px 0px; } +.emoji-1F35E { background-position: -6980px 0px; } +.emoji-1F35F { background-position: -7000px 0px; } +.emoji-1F360 { background-position: -7020px 0px; } +.emoji-1F361 { background-position: -7040px 0px; } +.emoji-1F362 { background-position: -7060px 0px; } +.emoji-1F363 { background-position: -7080px 0px; } +.emoji-1F364 { background-position: -7100px 0px; } +.emoji-1F365 { background-position: -7120px 0px; } +.emoji-1F366 { background-position: -7140px 0px; } +.emoji-1F367 { background-position: -7160px 0px; } +.emoji-1F368 { background-position: -7180px 0px; } +.emoji-1F369 { background-position: -7200px 0px; } +.emoji-1F36A { background-position: -7220px 0px; } +.emoji-1F36B { background-position: -7240px 0px; } +.emoji-1F36C { background-position: -7260px 0px; } +.emoji-1F36D { background-position: -7280px 0px; } +.emoji-1F36E { background-position: -7300px 0px; } +.emoji-1F36F { background-position: -7320px 0px; } +.emoji-1F370 { background-position: -7340px 0px; } +.emoji-1F371 { background-position: -7360px 0px; } +.emoji-1F372 { background-position: -7380px 0px; } +.emoji-1F373 { background-position: -7400px 0px; } +.emoji-1F374 { background-position: -7420px 0px; } +.emoji-1F375 { background-position: -7440px 0px; } +.emoji-1F376 { background-position: -7460px 0px; } +.emoji-1F377 { background-position: -7480px 0px; } +.emoji-1F378 { background-position: -7500px 0px; } +.emoji-1F379 { background-position: -7520px 0px; } +.emoji-1F37A { background-position: -7540px 0px; } +.emoji-1F37B { background-position: -7560px 0px; } +.emoji-1F37C { background-position: -7580px 0px; } +.emoji-1F37D { background-position: -7600px 0px; } +.emoji-1F380 { background-position: -7620px 0px; } +.emoji-1F381 { background-position: -7640px 0px; } +.emoji-1F382 { background-position: -7660px 0px; } +.emoji-1F383 { background-position: -7680px 0px; } +.emoji-1F384 { background-position: -7700px 0px; } +.emoji-1F385 { background-position: -7720px 0px; } +.emoji-1F386 { background-position: -7740px 0px; } +.emoji-1F387 { background-position: -7760px 0px; } +.emoji-1F388 { background-position: -7780px 0px; } +.emoji-1F389 { background-position: -7800px 0px; } +.emoji-1F38A { background-position: -7820px 0px; } +.emoji-1F38B { background-position: -7840px 0px; } +.emoji-1F38C { background-position: -7860px 0px; } +.emoji-1F38D { background-position: -7880px 0px; } +.emoji-1F38E { background-position: -7900px 0px; } +.emoji-1F38F { background-position: -7920px 0px; } +.emoji-1F390 { background-position: -7940px 0px; } +.emoji-1F391 { background-position: -7960px 0px; } +.emoji-1F392 { background-position: -7980px 0px; } +.emoji-1F393 { background-position: -8000px 0px; } +.emoji-1F394 { background-position: -8020px 0px; } +.emoji-1F395 { background-position: -8040px 0px; } +.emoji-1F396 { background-position: -8060px 0px; } +.emoji-1F397 { background-position: -8080px 0px; } +.emoji-1F398 { background-position: -8100px 0px; } +.emoji-1F399 { background-position: -8120px 0px; } +.emoji-1F39A { background-position: -8140px 0px; } +.emoji-1F39B { background-position: -8160px 0px; } +.emoji-1F39C { background-position: -8180px 0px; } +.emoji-1F39D { background-position: -8200px 0px; } +.emoji-1F39E { background-position: -8220px 0px; } +.emoji-1F39F { background-position: -8240px 0px; } +.emoji-1F3A0 { background-position: -8260px 0px; } +.emoji-1F3A1 { background-position: -8280px 0px; } +.emoji-1F3A2 { background-position: -8300px 0px; } +.emoji-1F3A3 { background-position: -8320px 0px; } +.emoji-1F3A4 { background-position: -8340px 0px; } +.emoji-1F3A5 { background-position: -8360px 0px; } +.emoji-1F3A6 { background-position: -8380px 0px; } +.emoji-1F3A7 { background-position: -8400px 0px; } +.emoji-1F3A8 { background-position: -8420px 0px; } +.emoji-1F3A9 { background-position: -8440px 0px; } +.emoji-1F3AA { background-position: -8460px 0px; } +.emoji-1F3AB { background-position: -8480px 0px; } +.emoji-1F3AC { background-position: -8500px 0px; } +.emoji-1F3AD { background-position: -8520px 0px; } +.emoji-1F3AE { background-position: -8540px 0px; } +.emoji-1F3AF { background-position: -8560px 0px; } +.emoji-1F3B0 { background-position: -8580px 0px; } +.emoji-1F3B1 { background-position: -8600px 0px; } +.emoji-1F3B2 { background-position: -8620px 0px; } +.emoji-1F3B3 { background-position: -8640px 0px; } +.emoji-1F3B4 { background-position: -8660px 0px; } +.emoji-1F3B5 { background-position: -8680px 0px; } +.emoji-1F3B6 { background-position: -8700px 0px; } +.emoji-1F3B7 { background-position: -8720px 0px; } +.emoji-1F3B8 { background-position: -8740px 0px; } +.emoji-1F3B9 { background-position: -8760px 0px; } +.emoji-1F3BA { background-position: -8780px 0px; } +.emoji-1F3BB { background-position: -8800px 0px; } +.emoji-1F3BC { background-position: -8820px 0px; } +.emoji-1F3BD { background-position: -8840px 0px; } +.emoji-1F3BE { background-position: -8860px 0px; } +.emoji-1F3BF { background-position: -8880px 0px; } +.emoji-1F3C0 { background-position: -8900px 0px; } +.emoji-1F3C1 { background-position: -8920px 0px; } +.emoji-1F3C2 { background-position: -8940px 0px; } +.emoji-1F3C3 { background-position: -8960px 0px; } +.emoji-1F3C4 { background-position: -8980px 0px; } +.emoji-1F3C5 { background-position: -9000px 0px; } +.emoji-1F3C6 { background-position: -9020px 0px; } +.emoji-1F3C7 { background-position: -9040px 0px; } +.emoji-1F3C8 { background-position: -9060px 0px; } +.emoji-1F3C9 { background-position: -9080px 0px; } +.emoji-1F3CA { background-position: -9100px 0px; } +.emoji-1F3CB { background-position: -9120px 0px; } +.emoji-1F3CC { background-position: -9140px 0px; } +.emoji-1F3CD { background-position: -9160px 0px; } +.emoji-1F3CE { background-position: -9180px 0px; } +.emoji-1F3D4 { background-position: -9200px 0px; } +.emoji-1F3D5 { background-position: -9220px 0px; } +.emoji-1F3D6 { background-position: -9240px 0px; } +.emoji-1F3D7 { background-position: -9260px 0px; } +.emoji-1F3D8 { background-position: -9280px 0px; } +.emoji-1F3D9 { background-position: -9300px 0px; } +.emoji-1F3DA { background-position: -9320px 0px; } +.emoji-1F3DB { background-position: -9340px 0px; } +.emoji-1F3DC { background-position: -9360px 0px; } +.emoji-1F3DD { background-position: -9380px 0px; } +.emoji-1F3DE { background-position: -9400px 0px; } +.emoji-1F3DF { background-position: -9420px 0px; } +.emoji-1F3E0 { background-position: -9440px 0px; } +.emoji-1F3E1 { background-position: -9460px 0px; } +.emoji-1F3E2 { background-position: -9480px 0px; } +.emoji-1F3E3 { background-position: -9500px 0px; } +.emoji-1F3E4 { background-position: -9520px 0px; } +.emoji-1F3E5 { background-position: -9540px 0px; } +.emoji-1F3E6 { background-position: -9560px 0px; } +.emoji-1F3E7 { background-position: -9580px 0px; } +.emoji-1F3E8 { background-position: -9600px 0px; } +.emoji-1F3E9 { background-position: -9620px 0px; } +.emoji-1F3EA { background-position: -9640px 0px; } +.emoji-1F3EB { background-position: -9660px 0px; } +.emoji-1F3EC { background-position: -9680px 0px; } +.emoji-1F3ED { background-position: -9700px 0px; } +.emoji-1F3EE { background-position: -9720px 0px; } +.emoji-1F3EF { background-position: -9740px 0px; } +.emoji-1F3F0 { background-position: -9760px 0px; } +.emoji-1F3F1 { background-position: -9780px 0px; } +.emoji-1F3F2 { background-position: -9800px 0px; } +.emoji-1F3F3 { background-position: -9820px 0px; } +.emoji-1F3F4 { background-position: -9840px 0px; } +.emoji-1F3F5 { background-position: -9860px 0px; } +.emoji-1F3F6 { background-position: -9880px 0px; } +.emoji-1F3F7 { background-position: -9900px 0px; } +.emoji-1F400 { background-position: -9920px 0px; } +.emoji-1F401 { background-position: -9940px 0px; } +.emoji-1F402 { background-position: -9960px 0px; } +.emoji-1F403 { background-position: -9980px 0px; } +.emoji-1F404 { background-position: -10000px 0px; } +.emoji-1F405 { background-position: -10020px 0px; } +.emoji-1F406 { background-position: -10040px 0px; } +.emoji-1F407 { background-position: -10060px 0px; } +.emoji-1F408 { background-position: -10080px 0px; } +.emoji-1F409 { background-position: -10100px 0px; } +.emoji-1F40A { background-position: -10120px 0px; } +.emoji-1F40B { background-position: -10140px 0px; } +.emoji-1F40C { background-position: -10160px 0px; } +.emoji-1F40D { background-position: -10180px 0px; } +.emoji-1F40E { background-position: -10200px 0px; } +.emoji-1F40F { background-position: -10220px 0px; } +.emoji-1F410 { background-position: -10240px 0px; } +.emoji-1F411 { background-position: -10260px 0px; } +.emoji-1F412 { background-position: -10280px 0px; } +.emoji-1F413 { background-position: -10300px 0px; } +.emoji-1F414 { background-position: -10320px 0px; } +.emoji-1F415 { background-position: -10340px 0px; } +.emoji-1F416 { background-position: -10360px 0px; } +.emoji-1F417 { background-position: -10380px 0px; } +.emoji-1F418 { background-position: -10400px 0px; } +.emoji-1F419 { background-position: -10420px 0px; } +.emoji-1F41A { background-position: -10440px 0px; } +.emoji-1F41B { background-position: -10460px 0px; } +.emoji-1F41C { background-position: -10480px 0px; } +.emoji-1F41D { background-position: -10500px 0px; } +.emoji-1F41E { background-position: -10520px 0px; } +.emoji-1F41F { background-position: -10540px 0px; } +.emoji-1F420 { background-position: -10560px 0px; } +.emoji-1F421 { background-position: -10580px 0px; } +.emoji-1F422 { background-position: -10600px 0px; } +.emoji-1F423 { background-position: -10620px 0px; } +.emoji-1F424 { background-position: -10640px 0px; } +.emoji-1F425 { background-position: -10660px 0px; } +.emoji-1F426 { background-position: -10680px 0px; } +.emoji-1F427 { background-position: -10700px 0px; } +.emoji-1F428 { background-position: -10720px 0px; } +.emoji-1F429 { background-position: -10740px 0px; } +.emoji-1F42A { background-position: -10760px 0px; } +.emoji-1F42B { background-position: -10780px 0px; } +.emoji-1F42C { background-position: -10800px 0px; } +.emoji-1F42D { background-position: -10820px 0px; } +.emoji-1F42E { background-position: -10840px 0px; } +.emoji-1F42F { background-position: -10860px 0px; } +.emoji-1F430 { background-position: -10880px 0px; } +.emoji-1F431 { background-position: -10900px 0px; } +.emoji-1F432 { background-position: -10920px 0px; } +.emoji-1F433 { background-position: -10940px 0px; } +.emoji-1F434 { background-position: -10960px 0px; } +.emoji-1F435 { background-position: -10980px 0px; } +.emoji-1F436 { background-position: -11000px 0px; } +.emoji-1F437 { background-position: -11020px 0px; } +.emoji-1F438 { background-position: -11040px 0px; } +.emoji-1F439 { background-position: -11060px 0px; } +.emoji-1F43A { background-position: -11080px 0px; } +.emoji-1F43B { background-position: -11100px 0px; } +.emoji-1F43C { background-position: -11120px 0px; } +.emoji-1F43D { background-position: -11140px 0px; } +.emoji-1F43E { background-position: -11160px 0px; } +.emoji-1F43F { background-position: -11180px 0px; } +.emoji-1F440 { background-position: -11200px 0px; } +.emoji-1F441 { background-position: -11220px 0px; } +.emoji-1F442 { background-position: -11240px 0px; } +.emoji-1F443 { background-position: -11260px 0px; } +.emoji-1F444 { background-position: -11280px 0px; } +.emoji-1F445 { background-position: -11300px 0px; } +.emoji-1F446 { background-position: -11320px 0px; } +.emoji-1F447 { background-position: -11340px 0px; } +.emoji-1F448 { background-position: -11360px 0px; } +.emoji-1F449 { background-position: -11380px 0px; } +.emoji-1F44A { background-position: -11400px 0px; } +.emoji-1F44B { background-position: -11420px 0px; } +.emoji-1F44C { background-position: -11440px 0px; } +.emoji-1F44D { background-position: -11460px 0px; } +.emoji-1F44E { background-position: -11480px 0px; } +.emoji-1F44F { background-position: -11500px 0px; } +.emoji-1F450 { background-position: -11520px 0px; } +.emoji-1F451 { background-position: -11540px 0px; } +.emoji-1F452 { background-position: -11560px 0px; } +.emoji-1F453 { background-position: -11580px 0px; } +.emoji-1F454 { background-position: -11600px 0px; } +.emoji-1F455 { background-position: -11620px 0px; } +.emoji-1F456 { background-position: -11640px 0px; } +.emoji-1F457 { background-position: -11660px 0px; } +.emoji-1F458 { background-position: -11680px 0px; } +.emoji-1F459 { background-position: -11700px 0px; } +.emoji-1F45A { background-position: -11720px 0px; } +.emoji-1F45B { background-position: -11740px 0px; } +.emoji-1F45C { background-position: -11760px 0px; } +.emoji-1F45D { background-position: -11780px 0px; } +.emoji-1F45E { background-position: -11800px 0px; } +.emoji-1F45F { background-position: -11820px 0px; } +.emoji-1F460 { background-position: -11840px 0px; } +.emoji-1F461 { background-position: -11860px 0px; } +.emoji-1F462 { background-position: -11880px 0px; } +.emoji-1F463 { background-position: -11900px 0px; } +.emoji-1F464 { background-position: -11920px 0px; } +.emoji-1F465 { background-position: -11940px 0px; } +.emoji-1F466 { background-position: -11960px 0px; } +.emoji-1F467 { background-position: -11980px 0px; } +.emoji-1F468 { background-position: -12000px 0px; } +.emoji-1F468-1F468-1F466 { background-position: -12020px 0px; } +.emoji-1F468-1F468-1F466-1F466 { background-position: -12040px 0px; } +.emoji-1F468-1F468-1F467 { background-position: -12060px 0px; } +.emoji-1F468-1F468-1F467-1F466 { background-position: -12080px 0px; } +.emoji-1F468-1F468-1F467-1F467 { background-position: -12100px 0px; } +.emoji-1F468-1F469-1F466-1F466 { background-position: -12120px 0px; } +.emoji-1F468-1F469-1F467 { background-position: -12140px 0px; } +.emoji-1F468-1F469-1F467-1F466 { background-position: -12160px 0px; } +.emoji-1F468-1F469-1F467-1F467 { background-position: -12180px 0px; } +.emoji-1F468-2764-1F468 { background-position: -12200px 0px; } +.emoji-1F468-2764-1F48B-1F468 { background-position: -12220px 0px; } +.emoji-1F469 { background-position: -12240px 0px; } +.emoji-1F469-1F469-1F466 { background-position: -12260px 0px; } +.emoji-1F469-1F469-1F466-1F466 { background-position: -12280px 0px; } +.emoji-1F469-1F469-1F467 { background-position: -12300px 0px; } +.emoji-1F469-1F469-1F467-1F466 { background-position: -12320px 0px; } +.emoji-1F469-1F469-1F467-1F467 { background-position: -12340px 0px; } +.emoji-1F469-2764-1F469 { background-position: -12360px 0px; } +.emoji-1F469-2764-1F48B-1F469 { background-position: -12380px 0px; } +.emoji-1F46A { background-position: -12400px 0px; } +.emoji-1F46B { background-position: -12420px 0px; } +.emoji-1F46C { background-position: -12440px 0px; } +.emoji-1F46D { background-position: -12460px 0px; } +.emoji-1F46E { background-position: -12480px 0px; } +.emoji-1F46F { background-position: -12500px 0px; } +.emoji-1F470 { background-position: -12520px 0px; } +.emoji-1F471 { background-position: -12540px 0px; } +.emoji-1F472 { background-position: -12560px 0px; } +.emoji-1F473 { background-position: -12580px 0px; } +.emoji-1F474 { background-position: -12600px 0px; } +.emoji-1F475 { background-position: -12620px 0px; } +.emoji-1F476 { background-position: -12640px 0px; } +.emoji-1F477 { background-position: -12660px 0px; } +.emoji-1F478 { background-position: -12680px 0px; } +.emoji-1F479 { background-position: -12700px 0px; } +.emoji-1F47A { background-position: -12720px 0px; } +.emoji-1F47B { background-position: -12740px 0px; } +.emoji-1F47C { background-position: -12760px 0px; } +.emoji-1F47D { background-position: -12780px 0px; } +.emoji-1F47E { background-position: -12800px 0px; } +.emoji-1F47F { background-position: -12820px 0px; } +.emoji-1F480 { background-position: -12840px 0px; } +.emoji-1F481 { background-position: -12860px 0px; } +.emoji-1F482 { background-position: -12880px 0px; } +.emoji-1F483 { background-position: -12900px 0px; } +.emoji-1F484 { background-position: -12920px 0px; } +.emoji-1F485 { background-position: -12940px 0px; } +.emoji-1F486 { background-position: -12960px 0px; } +.emoji-1F487 { background-position: -12980px 0px; } +.emoji-1F488 { background-position: -13000px 0px; } +.emoji-1F489 { background-position: -13020px 0px; } +.emoji-1F48A { background-position: -13040px 0px; } +.emoji-1F48B { background-position: -13060px 0px; } +.emoji-1F48C { background-position: -13080px 0px; } +.emoji-1F48D { background-position: -13100px 0px; } +.emoji-1F48E { background-position: -13120px 0px; } +.emoji-1F48F { background-position: -13140px 0px; } +.emoji-1F490 { background-position: -13160px 0px; } +.emoji-1F491 { background-position: -13180px 0px; } +.emoji-1F492 { background-position: -13200px 0px; } +.emoji-1F493 { background-position: -13220px 0px; } +.emoji-1F494 { background-position: -13240px 0px; } +.emoji-1F495 { background-position: -13260px 0px; } +.emoji-1F496 { background-position: -13280px 0px; } +.emoji-1F497 { background-position: -13300px 0px; } +.emoji-1F498 { background-position: -13320px 0px; } +.emoji-1F499 { background-position: -13340px 0px; } +.emoji-1F49A { background-position: -13360px 0px; } +.emoji-1F49B { background-position: -13380px 0px; } +.emoji-1F49C { background-position: -13400px 0px; } +.emoji-1F49D { background-position: -13420px 0px; } +.emoji-1F49E { background-position: -13440px 0px; } +.emoji-1F49F { background-position: -13460px 0px; } +.emoji-1F4A0 { background-position: -13480px 0px; } +.emoji-1F4A1 { background-position: -13500px 0px; } +.emoji-1F4A2 { background-position: -13520px 0px; } +.emoji-1F4A3 { background-position: -13540px 0px; } +.emoji-1F4A4 { background-position: -13560px 0px; } +.emoji-1F4A5 { background-position: -13580px 0px; } +.emoji-1F4A6 { background-position: -13600px 0px; } +.emoji-1F4A7 { background-position: -13620px 0px; } +.emoji-1F4A8 { background-position: -13640px 0px; } +.emoji-1F4A9 { background-position: -13660px 0px; } +.emoji-1F4AA { background-position: -13680px 0px; } +.emoji-1F4AB { background-position: -13700px 0px; } +.emoji-1F4AC { background-position: -13720px 0px; } +.emoji-1F4AD { background-position: -13740px 0px; } +.emoji-1F4AE { background-position: -13760px 0px; } +.emoji-1F4AF { background-position: -13780px 0px; } +.emoji-1F4B0 { background-position: -13800px 0px; } +.emoji-1F4B1 { background-position: -13820px 0px; } +.emoji-1F4B2 { background-position: -13840px 0px; } +.emoji-1F4B3 { background-position: -13860px 0px; } +.emoji-1F4B4 { background-position: -13880px 0px; } +.emoji-1F4B5 { background-position: -13900px 0px; } +.emoji-1F4B6 { background-position: -13920px 0px; } +.emoji-1F4B7 { background-position: -13940px 0px; } +.emoji-1F4B8 { background-position: -13960px 0px; } +.emoji-1F4B9 { background-position: -13980px 0px; } +.emoji-1F4BA { background-position: -14000px 0px; } +.emoji-1F4BB { background-position: -14020px 0px; } +.emoji-1F4BC { background-position: -14040px 0px; } +.emoji-1F4BD { background-position: -14060px 0px; } +.emoji-1F4BE { background-position: -14080px 0px; } +.emoji-1F4BF { background-position: -14100px 0px; } +.emoji-1F4C0 { background-position: -14120px 0px; } +.emoji-1F4C1 { background-position: -14140px 0px; } +.emoji-1F4C2 { background-position: -14160px 0px; } +.emoji-1F4C3 { background-position: -14180px 0px; } +.emoji-1F4C4 { background-position: -14200px 0px; } +.emoji-1F4C5 { background-position: -14220px 0px; } +.emoji-1F4C6 { background-position: -14240px 0px; } +.emoji-1F4C7 { background-position: -14260px 0px; } +.emoji-1F4C8 { background-position: -14280px 0px; } +.emoji-1F4C9 { background-position: -14300px 0px; } +.emoji-1F4CA { background-position: -14320px 0px; } +.emoji-1F4CB { background-position: -14340px 0px; } +.emoji-1F4CC { background-position: -14360px 0px; } +.emoji-1F4CD { background-position: -14380px 0px; } +.emoji-1F4CE { background-position: -14400px 0px; } +.emoji-1F4CF { background-position: -14420px 0px; } +.emoji-1F4D0 { background-position: -14440px 0px; } +.emoji-1F4D1 { background-position: -14460px 0px; } +.emoji-1F4D2 { background-position: -14480px 0px; } +.emoji-1F4D3 { background-position: -14500px 0px; } +.emoji-1F4D4 { background-position: -14520px 0px; } +.emoji-1F4D5 { background-position: -14540px 0px; } +.emoji-1F4D6 { background-position: -14560px 0px; } +.emoji-1F4D7 { background-position: -14580px 0px; } +.emoji-1F4D8 { background-position: -14600px 0px; } +.emoji-1F4D9 { background-position: -14620px 0px; } +.emoji-1F4DA { background-position: -14640px 0px; } +.emoji-1F4DB { background-position: -14660px 0px; } +.emoji-1F4DC { background-position: -14680px 0px; } +.emoji-1F4DD { background-position: -14700px 0px; } +.emoji-1F4DE { background-position: -14720px 0px; } +.emoji-1F4DF { background-position: -14740px 0px; } +.emoji-1F4E0 { background-position: -14760px 0px; } +.emoji-1F4E1 { background-position: -14780px 0px; } +.emoji-1F4E2 { background-position: -14800px 0px; } +.emoji-1F4E3 { background-position: -14820px 0px; } +.emoji-1F4E4 { background-position: -14840px 0px; } +.emoji-1F4E5 { background-position: -14860px 0px; } +.emoji-1F4E6 { background-position: -14880px 0px; } +.emoji-1F4E7 { background-position: -14900px 0px; } +.emoji-1F4E8 { background-position: -14920px 0px; } +.emoji-1F4E9 { background-position: -14940px 0px; } +.emoji-1F4EA { background-position: -14960px 0px; } +.emoji-1F4EB { background-position: -14980px 0px; } +.emoji-1F4EC { background-position: -15000px 0px; } +.emoji-1F4ED { background-position: -15020px 0px; } +.emoji-1F4EE { background-position: -15040px 0px; } +.emoji-1F4EF { background-position: -15060px 0px; } +.emoji-1F4F0 { background-position: -15080px 0px; } +.emoji-1F4F1 { background-position: -15100px 0px; } +.emoji-1F4F2 { background-position: -15120px 0px; } +.emoji-1F4F3 { background-position: -15140px 0px; } +.emoji-1F4F4 { background-position: -15160px 0px; } +.emoji-1F4F5 { background-position: -15180px 0px; } +.emoji-1F4F6 { background-position: -15200px 0px; } +.emoji-1F4F7 { background-position: -15220px 0px; } +.emoji-1F4F8 { background-position: -15240px 0px; } +.emoji-1F4F9 { background-position: -15260px 0px; } +.emoji-1F4FA { background-position: -15280px 0px; } +.emoji-1F4FB { background-position: -15300px 0px; } +.emoji-1F4FC { background-position: -15320px 0px; } +.emoji-1F4FD { background-position: -15340px 0px; } +.emoji-1F4FE { background-position: -15360px 0px; } +.emoji-1F500 { background-position: -15380px 0px; } +.emoji-1F501 { background-position: -15400px 0px; } +.emoji-1F502 { background-position: -15420px 0px; } +.emoji-1F503 { background-position: -15440px 0px; } +.emoji-1F504 { background-position: -15460px 0px; } +.emoji-1F505 { background-position: -15480px 0px; } +.emoji-1F506 { background-position: -15500px 0px; } +.emoji-1F507 { background-position: -15520px 0px; } +.emoji-1F508 { background-position: -15540px 0px; } +.emoji-1F509 { background-position: -15560px 0px; } +.emoji-1F50A { background-position: -15580px 0px; } +.emoji-1F50B { background-position: -15600px 0px; } +.emoji-1F50C { background-position: -15620px 0px; } +.emoji-1F50D { background-position: -15640px 0px; } +.emoji-1F50E { background-position: -15660px 0px; } +.emoji-1F50F { background-position: -15680px 0px; } +.emoji-1F510 { background-position: -15700px 0px; } +.emoji-1F511 { background-position: -15720px 0px; } +.emoji-1F512 { background-position: -15740px 0px; } +.emoji-1F513 { background-position: -15760px 0px; } +.emoji-1F514 { background-position: -15780px 0px; } +.emoji-1F515 { background-position: -15800px 0px; } +.emoji-1F516 { background-position: -15820px 0px; } +.emoji-1F517 { background-position: -15840px 0px; } +.emoji-1F518 { background-position: -15860px 0px; } +.emoji-1F519 { background-position: -15880px 0px; } +.emoji-1F51A { background-position: -15900px 0px; } +.emoji-1F51B { background-position: -15920px 0px; } +.emoji-1F51C { background-position: -15940px 0px; } +.emoji-1F51D { background-position: -15960px 0px; } +.emoji-1F51E { background-position: -15980px 0px; } +.emoji-1F51F { background-position: -16000px 0px; } +.emoji-1F520 { background-position: -16020px 0px; } +.emoji-1F521 { background-position: -16040px 0px; } +.emoji-1F522 { background-position: -16060px 0px; } +.emoji-1F523 { background-position: -16080px 0px; } +.emoji-1F524 { background-position: -16100px 0px; } +.emoji-1F525 { background-position: -16120px 0px; } +.emoji-1F526 { background-position: -16140px 0px; } +.emoji-1F527 { background-position: -16160px 0px; } +.emoji-1F528 { background-position: -16180px 0px; } +.emoji-1F529 { background-position: -16200px 0px; } +.emoji-1F52A { background-position: -16220px 0px; } +.emoji-1F52B { background-position: -16240px 0px; } +.emoji-1F52C { background-position: -16260px 0px; } +.emoji-1F52D { background-position: -16280px 0px; } +.emoji-1F52E { background-position: -16300px 0px; } +.emoji-1F52F { background-position: -16320px 0px; } +.emoji-1F530 { background-position: -16340px 0px; } +.emoji-1F531 { background-position: -16360px 0px; } +.emoji-1F532 { background-position: -16380px 0px; } +.emoji-1F533 { background-position: -16400px 0px; } +.emoji-1F534 { background-position: -16420px 0px; } +.emoji-1F535 { background-position: -16440px 0px; } +.emoji-1F536 { background-position: -16460px 0px; } +.emoji-1F537 { background-position: -16480px 0px; } +.emoji-1F538 { background-position: -16500px 0px; } +.emoji-1F539 { background-position: -16520px 0px; } +.emoji-1F53A { background-position: -16540px 0px; } +.emoji-1F53B { background-position: -16560px 0px; } +.emoji-1F53C { background-position: -16580px 0px; } +.emoji-1F53D { background-position: -16600px 0px; } +.emoji-1F546 { background-position: -16620px 0px; } +.emoji-1F547 { background-position: -16640px 0px; } +.emoji-1F548 { background-position: -16660px 0px; } +.emoji-1F549 { background-position: -16680px 0px; } +.emoji-1F54A { background-position: -16700px 0px; } +.emoji-1F550 { background-position: -16720px 0px; } +.emoji-1F551 { background-position: -16740px 0px; } +.emoji-1F552 { background-position: -16760px 0px; } +.emoji-1F553 { background-position: -16780px 0px; } +.emoji-1F554 { background-position: -16800px 0px; } +.emoji-1F555 { background-position: -16820px 0px; } +.emoji-1F556 { background-position: -16840px 0px; } +.emoji-1F557 { background-position: -16860px 0px; } +.emoji-1F558 { background-position: -16880px 0px; } +.emoji-1F559 { background-position: -16900px 0px; } +.emoji-1F55A { background-position: -16920px 0px; } +.emoji-1F55B { background-position: -16940px 0px; } +.emoji-1F55C { background-position: -16960px 0px; } +.emoji-1F55D { background-position: -16980px 0px; } +.emoji-1F55E { background-position: -17000px 0px; } +.emoji-1F55F { background-position: -17020px 0px; } +.emoji-1F560 { background-position: -17040px 0px; } +.emoji-1F561 { background-position: -17060px 0px; } +.emoji-1F562 { background-position: -17080px 0px; } +.emoji-1F563 { background-position: -17100px 0px; } +.emoji-1F564 { background-position: -17120px 0px; } +.emoji-1F565 { background-position: -17140px 0px; } +.emoji-1F566 { background-position: -17160px 0px; } +.emoji-1F567 { background-position: -17180px 0px; } +.emoji-1F568 { background-position: -17200px 0px; } +.emoji-1F569 { background-position: -17220px 0px; } +.emoji-1F56A { background-position: -17240px 0px; } +.emoji-1F56B { background-position: -17260px 0px; } +.emoji-1F56C { background-position: -17280px 0px; } +.emoji-1F56D { background-position: -17300px 0px; } +.emoji-1F56E { background-position: -17320px 0px; } +.emoji-1F56F { background-position: -17340px 0px; } +.emoji-1F570 { background-position: -17360px 0px; } +.emoji-1F571 { background-position: -17380px 0px; } +.emoji-1F572 { background-position: -17400px 0px; } +.emoji-1F573 { background-position: -17420px 0px; } +.emoji-1F574 { background-position: -17440px 0px; } +.emoji-1F575 { background-position: -17460px 0px; } +.emoji-1F576 { background-position: -17480px 0px; } +.emoji-1F577 { background-position: -17500px 0px; } +.emoji-1F578 { background-position: -17520px 0px; } +.emoji-1F579 { background-position: -17540px 0px; } +.emoji-1F57B { background-position: -17560px 0px; } +.emoji-1F57E { background-position: -17580px 0px; } +.emoji-1F57F { background-position: -17600px 0px; } +.emoji-1F581 { background-position: -17620px 0px; } +.emoji-1F582 { background-position: -17640px 0px; } +.emoji-1F583 { background-position: -17660px 0px; } +.emoji-1F585 { background-position: -17680px 0px; } +.emoji-1F586 { background-position: -17700px 0px; } +.emoji-1F587 { background-position: -17720px 0px; } +.emoji-1F588 { background-position: -17740px 0px; } +.emoji-1F589 { background-position: -17760px 0px; } +.emoji-1F58A { background-position: -17780px 0px; } +.emoji-1F58B { background-position: -17800px 0px; } +.emoji-1F58C { background-position: -17820px 0px; } +.emoji-1F58D { background-position: -17840px 0px; } +.emoji-1F58E { background-position: -17860px 0px; } +.emoji-1F58F { background-position: -17880px 0px; } +.emoji-1F590 { background-position: -17900px 0px; } +.emoji-1F591 { background-position: -17920px 0px; } +.emoji-1F592 { background-position: -17940px 0px; } +.emoji-1F593 { background-position: -17960px 0px; } +.emoji-1F594 { background-position: -17980px 0px; } +.emoji-1F595 { background-position: -18000px 0px; } +.emoji-1F596 { background-position: -18020px 0px; } +.emoji-1F597 { background-position: -18040px 0px; } +.emoji-1F598 { background-position: -18060px 0px; } +.emoji-1F599 { background-position: -18080px 0px; } +.emoji-1F59E { background-position: -18100px 0px; } +.emoji-1F59F { background-position: -18120px 0px; } +.emoji-1F5A5 { background-position: -18140px 0px; } +.emoji-1F5A6 { background-position: -18160px 0px; } +.emoji-1F5A7 { background-position: -18180px 0px; } +.emoji-1F5A8 { background-position: -18200px 0px; } +.emoji-1F5A9 { background-position: -18220px 0px; } +.emoji-1F5AA { background-position: -18240px 0px; } +.emoji-1F5AB { background-position: -18260px 0px; } +.emoji-1F5AD { background-position: -18280px 0px; } +.emoji-1F5AE { background-position: -18300px 0px; } +.emoji-1F5AF { background-position: -18320px 0px; } +.emoji-1F5B2 { background-position: -18340px 0px; } +.emoji-1F5B3 { background-position: -18360px 0px; } +.emoji-1F5B4 { background-position: -18380px 0px; } +.emoji-1F5B8 { background-position: -18400px 0px; } +.emoji-1F5B9 { background-position: -18420px 0px; } +.emoji-1F5BC { background-position: -18440px 0px; } +.emoji-1F5BD { background-position: -18460px 0px; } +.emoji-1F5BE { background-position: -18480px 0px; } +.emoji-1F5C0 { background-position: -18500px 0px; } +.emoji-1F5C1 { background-position: -18520px 0px; } +.emoji-1F5C2 { background-position: -18540px 0px; } +.emoji-1F5C3 { background-position: -18560px 0px; } +.emoji-1F5C4 { background-position: -18580px 0px; } +.emoji-1F5C6 { background-position: -18600px 0px; } +.emoji-1F5C7 { background-position: -18620px 0px; } +.emoji-1F5C9 { background-position: -18640px 0px; } +.emoji-1F5CA { background-position: -18660px 0px; } +.emoji-1F5CE { background-position: -18680px 0px; } +.emoji-1F5CF { background-position: -18700px 0px; } +.emoji-1F5D0 { background-position: -18720px 0px; } +.emoji-1F5D1 { background-position: -18740px 0px; } +.emoji-1F5D2 { background-position: -18760px 0px; } +.emoji-1F5D3 { background-position: -18780px 0px; } +.emoji-1F5D4 { background-position: -18800px 0px; } +.emoji-1F5D8 { background-position: -18820px 0px; } +.emoji-1F5D9 { background-position: -18840px 0px; } +.emoji-1F5DC { background-position: -18860px 0px; } +.emoji-1F5DD { background-position: -18880px 0px; } +.emoji-1F5DE { background-position: -18900px 0px; } +.emoji-1F5E0 { background-position: -18920px 0px; } +.emoji-1F5E1 { background-position: -18940px 0px; } +.emoji-1F5E2 { background-position: -18960px 0px; } +.emoji-1F5E3 { background-position: -18980px 0px; } +.emoji-1F5E8 { background-position: -19000px 0px; } +.emoji-1F5E9 { background-position: -19020px 0px; } +.emoji-1F5EA { background-position: -19040px 0px; } +.emoji-1F5EB { background-position: -19060px 0px; } +.emoji-1F5EC { background-position: -19080px 0px; } +.emoji-1F5ED { background-position: -19100px 0px; } +.emoji-1F5EE { background-position: -19120px 0px; } +.emoji-1F5EF { background-position: -19140px 0px; } +.emoji-1F5F0 { background-position: -19160px 0px; } +.emoji-1F5F1 { background-position: -19180px 0px; } +.emoji-1F5F2 { background-position: -19200px 0px; } +.emoji-1F5F3 { background-position: -19220px 0px; } +.emoji-1F5F4 { background-position: -19240px 0px; } +.emoji-1F5F5 { background-position: -19260px 0px; } +.emoji-1F5F8 { background-position: -19280px 0px; } +.emoji-1F5F9 { background-position: -19300px 0px; } +.emoji-1F5FA { background-position: -19320px 0px; } +.emoji-1F5FB { background-position: -19340px 0px; } +.emoji-1F5FC { background-position: -19360px 0px; } +.emoji-1F5FD { background-position: -19380px 0px; } +.emoji-1F5FE { background-position: -19400px 0px; } +.emoji-1F5FF { background-position: -19420px 0px; } +.emoji-1F600 { background-position: -19440px 0px; } +.emoji-1F601 { background-position: -19460px 0px; } +.emoji-1F602 { background-position: -19480px 0px; } +.emoji-1F603 { background-position: -19500px 0px; } +.emoji-1F604 { background-position: -19520px 0px; } +.emoji-1F605 { background-position: -19540px 0px; } +.emoji-1F606 { background-position: -19560px 0px; } +.emoji-1F607 { background-position: -19580px 0px; } +.emoji-1F608 { background-position: -19600px 0px; } +.emoji-1F609 { background-position: -19620px 0px; } +.emoji-1F60A { background-position: -19640px 0px; } +.emoji-1F60B { background-position: -19660px 0px; } +.emoji-1F60C { background-position: -19680px 0px; } +.emoji-1F60D { background-position: -19700px 0px; } +.emoji-1F60E { background-position: -19720px 0px; } +.emoji-1F60F { background-position: -19740px 0px; } +.emoji-1F610 { background-position: -19760px 0px; } +.emoji-1F611 { background-position: -19780px 0px; } +.emoji-1F612 { background-position: -19800px 0px; } +.emoji-1F613 { background-position: -19820px 0px; } +.emoji-1F614 { background-position: -19840px 0px; } +.emoji-1F615 { background-position: -19860px 0px; } +.emoji-1F616 { background-position: -19880px 0px; } +.emoji-1F617 { background-position: -19900px 0px; } +.emoji-1F618 { background-position: -19920px 0px; } +.emoji-1F619 { background-position: -19940px 0px; } +.emoji-1F61A { background-position: -19960px 0px; } +.emoji-1F61B { background-position: -19980px 0px; } +.emoji-1F61C { background-position: -20000px 0px; } +.emoji-1F61D { background-position: -20020px 0px; } +.emoji-1F61E { background-position: -20040px 0px; } +.emoji-1F61F { background-position: -20060px 0px; } +.emoji-1F620 { background-position: -20080px 0px; } +.emoji-1F621 { background-position: -20100px 0px; } +.emoji-1F622 { background-position: -20120px 0px; } +.emoji-1F623 { background-position: -20140px 0px; } +.emoji-1F624 { background-position: -20160px 0px; } +.emoji-1F625 { background-position: -20180px 0px; } +.emoji-1F626 { background-position: -20200px 0px; } +.emoji-1F627 { background-position: -20220px 0px; } +.emoji-1F628 { background-position: -20240px 0px; } +.emoji-1F629 { background-position: -20260px 0px; } +.emoji-1F62A { background-position: -20280px 0px; } +.emoji-1F62B { background-position: -20300px 0px; } +.emoji-1F62C { background-position: -20320px 0px; } +.emoji-1F62D { background-position: -20340px 0px; } +.emoji-1F62E { background-position: -20360px 0px; } +.emoji-1F62F { background-position: -20380px 0px; } +.emoji-1F630 { background-position: -20400px 0px; } +.emoji-1F631 { background-position: -20420px 0px; } +.emoji-1F632 { background-position: -20440px 0px; } +.emoji-1F633 { background-position: -20460px 0px; } +.emoji-1F634 { background-position: -20480px 0px; } +.emoji-1F635 { background-position: -20500px 0px; } +.emoji-1F636 { background-position: -20520px 0px; } +.emoji-1F637 { background-position: -20540px 0px; } +.emoji-1F638 { background-position: -20560px 0px; } +.emoji-1F639 { background-position: -20580px 0px; } +.emoji-1F63A { background-position: -20600px 0px; } +.emoji-1F63B { background-position: -20620px 0px; } +.emoji-1F63C { background-position: -20640px 0px; } +.emoji-1F63D { background-position: -20660px 0px; } +.emoji-1F63E { background-position: -20680px 0px; } +.emoji-1F63F { background-position: -20700px 0px; } +.emoji-1F640 { background-position: -20720px 0px; } +.emoji-1F641 { background-position: -20740px 0px; } +.emoji-1F642 { background-position: -20760px 0px; } +.emoji-1F645 { background-position: -20780px 0px; } +.emoji-1F646 { background-position: -20800px 0px; } +.emoji-1F647 { background-position: -20820px 0px; } +.emoji-1F648 { background-position: -20840px 0px; } +.emoji-1F649 { background-position: -20860px 0px; } +.emoji-1F64A { background-position: -20880px 0px; } +.emoji-1F64B { background-position: -20900px 0px; } +.emoji-1F64C { background-position: -20920px 0px; } +.emoji-1F64D { background-position: -20940px 0px; } +.emoji-1F64E { background-position: -20960px 0px; } +.emoji-1F64F { background-position: -20980px 0px; } +.emoji-1F680 { background-position: -21000px 0px; } +.emoji-1F681 { background-position: -21020px 0px; } +.emoji-1F682 { background-position: -21040px 0px; } +.emoji-1F683 { background-position: -21060px 0px; } +.emoji-1F684 { background-position: -21080px 0px; } +.emoji-1F685 { background-position: -21100px 0px; } +.emoji-1F686 { background-position: -21120px 0px; } +.emoji-1F687 { background-position: -21140px 0px; } +.emoji-1F688 { background-position: -21160px 0px; } +.emoji-1F689 { background-position: -21180px 0px; } +.emoji-1F68A { background-position: -21200px 0px; } +.emoji-1F68B { background-position: -21220px 0px; } +.emoji-1F68C { background-position: -21240px 0px; } +.emoji-1F68D { background-position: -21260px 0px; } +.emoji-1F68E { background-position: -21280px 0px; } +.emoji-1F68F { background-position: -21300px 0px; } +.emoji-1F690 { background-position: -21320px 0px; } +.emoji-1F691 { background-position: -21340px 0px; } +.emoji-1F692 { background-position: -21360px 0px; } +.emoji-1F693 { background-position: -21380px 0px; } +.emoji-1F694 { background-position: -21400px 0px; } +.emoji-1F695 { background-position: -21420px 0px; } +.emoji-1F696 { background-position: -21440px 0px; } +.emoji-1F697 { background-position: -21460px 0px; } +.emoji-1F698 { background-position: -21480px 0px; } +.emoji-1F699 { background-position: -21500px 0px; } +.emoji-1F69A { background-position: -21520px 0px; } +.emoji-1F69B { background-position: -21540px 0px; } +.emoji-1F69C { background-position: -21560px 0px; } +.emoji-1F69D { background-position: -21580px 0px; } +.emoji-1F69E { background-position: -21600px 0px; } +.emoji-1F69F { background-position: -21620px 0px; } +.emoji-1F6A0 { background-position: -21640px 0px; } +.emoji-1F6A1 { background-position: -21660px 0px; } +.emoji-1F6A2 { background-position: -21680px 0px; } +.emoji-1F6A3 { background-position: -21700px 0px; } +.emoji-1F6A4 { background-position: -21720px 0px; } +.emoji-1F6A5 { background-position: -21740px 0px; } +.emoji-1F6A6 { background-position: -21760px 0px; } +.emoji-1F6A7 { background-position: -21780px 0px; } +.emoji-1F6A8 { background-position: -21800px 0px; } +.emoji-1F6A9 { background-position: -21820px 0px; } +.emoji-1F6AA { background-position: -21840px 0px; } +.emoji-1F6AB { background-position: -21860px 0px; } +.emoji-1F6AC { background-position: -21880px 0px; } +.emoji-1F6AD { background-position: -21900px 0px; } +.emoji-1F6AE { background-position: -21920px 0px; } +.emoji-1F6AF { background-position: -21940px 0px; } +.emoji-1F6B0 { background-position: -21960px 0px; } +.emoji-1F6B1 { background-position: -21980px 0px; } +.emoji-1F6B2 { background-position: -22000px 0px; } +.emoji-1F6B3 { background-position: -22020px 0px; } +.emoji-1F6B4 { background-position: -22040px 0px; } +.emoji-1F6B5 { background-position: -22060px 0px; } +.emoji-1F6B6 { background-position: -22080px 0px; } +.emoji-1F6B7 { background-position: -22100px 0px; } +.emoji-1F6B8 { background-position: -22120px 0px; } +.emoji-1F6B9 { background-position: -22140px 0px; } +.emoji-1F6BA { background-position: -22160px 0px; } +.emoji-1F6BB { background-position: -22180px 0px; } +.emoji-1F6BC { background-position: -22200px 0px; } +.emoji-1F6BD { background-position: -22220px 0px; } +.emoji-1F6BE { background-position: -22240px 0px; } +.emoji-1F6BF { background-position: -22260px 0px; } +.emoji-1F6C0 { background-position: -22280px 0px; } +.emoji-1F6C1 { background-position: -22300px 0px; } +.emoji-1F6C2 { background-position: -22320px 0px; } +.emoji-1F6C3 { background-position: -22340px 0px; } +.emoji-1F6C4 { background-position: -22360px 0px; } +.emoji-1F6C5 { background-position: -22380px 0px; } +.emoji-1F6C6 { background-position: -22400px 0px; } +.emoji-1F6C7 { background-position: -22420px 0px; } +.emoji-1F6C8 { background-position: -22440px 0px; } +.emoji-1F6C9 { background-position: -22460px 0px; } +.emoji-1F6CA { background-position: -22480px 0px; } +.emoji-1F6CB { background-position: -22500px 0px; } +.emoji-1F6CC { background-position: -22520px 0px; } +.emoji-1F6CD { background-position: -22540px 0px; } +.emoji-1F6CE { background-position: -22560px 0px; } +.emoji-1F6CF { background-position: -22580px 0px; } +.emoji-1F6E0 { background-position: -22600px 0px; } +.emoji-1F6E1 { background-position: -22620px 0px; } +.emoji-1F6E2 { background-position: -22640px 0px; } +.emoji-1F6E3 { background-position: -22660px 0px; } +.emoji-1F6E4 { background-position: -22680px 0px; } +.emoji-1F6E5 { background-position: -22700px 0px; } +.emoji-1F6E6 { background-position: -22720px 0px; } +.emoji-1F6E7 { background-position: -22740px 0px; } +.emoji-1F6E8 { background-position: -22760px 0px; } +.emoji-1F6E9 { background-position: -22780px 0px; } +.emoji-1F6EA { background-position: -22800px 0px; } +.emoji-1F6EB { background-position: -22820px 0px; } +.emoji-1F6EC { background-position: -22840px 0px; } +.emoji-1F6F0 { background-position: -22860px 0px; } +.emoji-1F6F1 { background-position: -22880px 0px; } +.emoji-1F6F2 { background-position: -22900px 0px; } +.emoji-1F6F3 { background-position: -22920px 0px; } +.emoji-203C { background-position: -22940px 0px; } +.emoji-2049 { background-position: -22960px 0px; } +.emoji-2122 { background-position: -22980px 0px; } +.emoji-2139 { background-position: -23000px 0px; } +.emoji-2194 { background-position: -23020px 0px; } +.emoji-2195 { background-position: -23040px 0px; } +.emoji-2196 { background-position: -23060px 0px; } +.emoji-2197 { background-position: -23080px 0px; } +.emoji-2198 { background-position: -23100px 0px; } +.emoji-2199 { background-position: -23120px 0px; } +.emoji-21A9 { background-position: -23140px 0px; } +.emoji-21AA { background-position: -23160px 0px; } +.emoji-231A { background-position: -23180px 0px; } +.emoji-231B { background-position: -23200px 0px; } +.emoji-23E9 { background-position: -23220px 0px; } +.emoji-23EA { background-position: -23240px 0px; } +.emoji-23EB { background-position: -23260px 0px; } +.emoji-23EC { background-position: -23280px 0px; } +.emoji-23F0 { background-position: -23300px 0px; } +.emoji-23F3 { background-position: -23320px 0px; } +.emoji-24C2 { background-position: -23340px 0px; } +.emoji-25AA { background-position: -23360px 0px; } +.emoji-25AB { background-position: -23380px 0px; } +.emoji-25B6 { background-position: -23400px 0px; } +.emoji-25C0 { background-position: -23420px 0px; } +.emoji-25FB { background-position: -23440px 0px; } +.emoji-25FC { background-position: -23460px 0px; } +.emoji-25FD { background-position: -23480px 0px; } +.emoji-25FE { background-position: -23500px 0px; } +.emoji-2600 { background-position: -23520px 0px; } +.emoji-2601 { background-position: -23540px 0px; } +.emoji-260E { background-position: -23560px 0px; } +.emoji-2611 { background-position: -23580px 0px; } +.emoji-2614 { background-position: -23600px 0px; } +.emoji-2615 { background-position: -23620px 0px; } +.emoji-261D { background-position: -23640px 0px; } +.emoji-263A { background-position: -23660px 0px; } +.emoji-2648 { background-position: -23680px 0px; } +.emoji-2649 { background-position: -23700px 0px; } +.emoji-264A { background-position: -23720px 0px; } +.emoji-264B { background-position: -23740px 0px; } +.emoji-264C { background-position: -23760px 0px; } +.emoji-264D { background-position: -23780px 0px; } +.emoji-264E { background-position: -23800px 0px; } +.emoji-264F { background-position: -23820px 0px; } +.emoji-2650 { background-position: -23840px 0px; } +.emoji-2651 { background-position: -23860px 0px; } +.emoji-2652 { background-position: -23880px 0px; } +.emoji-2653 { background-position: -23900px 0px; } +.emoji-2660 { background-position: -23920px 0px; } +.emoji-2663 { background-position: -23940px 0px; } +.emoji-2665 { background-position: -23960px 0px; } +.emoji-2666 { background-position: -23980px 0px; } +.emoji-2668 { background-position: -24000px 0px; } +.emoji-267B { background-position: -24020px 0px; } +.emoji-267F { background-position: -24040px 0px; } +.emoji-2693 { background-position: -24060px 0px; } +.emoji-26A0 { background-position: -24080px 0px; } +.emoji-26A1 { background-position: -24100px 0px; } +.emoji-26AA { background-position: -24120px 0px; } +.emoji-26AB { background-position: -24140px 0px; } +.emoji-26BD { background-position: -24160px 0px; } +.emoji-26BE { background-position: -24180px 0px; } +.emoji-26C4 { background-position: -24200px 0px; } +.emoji-26C5 { background-position: -24220px 0px; } +.emoji-26CE { background-position: -24240px 0px; } +.emoji-26D4 { background-position: -24260px 0px; } +.emoji-26EA { background-position: -24280px 0px; } +.emoji-26F2 { background-position: -24300px 0px; } +.emoji-26F3 { background-position: -24320px 0px; } +.emoji-26F5 { background-position: -24340px 0px; } +.emoji-26FA { background-position: -24360px 0px; } +.emoji-26FD { background-position: -24380px 0px; } +.emoji-2702 { background-position: -24400px 0px; } +.emoji-2705 { background-position: -24420px 0px; } +.emoji-2708 { background-position: -24440px 0px; } +.emoji-2709 { background-position: -24460px 0px; } +.emoji-270A { background-position: -24480px 0px; } +.emoji-270B { background-position: -24500px 0px; } +.emoji-270C { background-position: -24520px 0px; } +.emoji-270F { background-position: -24540px 0px; } +.emoji-2712 { background-position: -24560px 0px; } +.emoji-2714 { background-position: -24580px 0px; } +.emoji-2716 { background-position: -24600px 0px; } +.emoji-2728 { background-position: -24620px 0px; } +.emoji-2733 { background-position: -24640px 0px; } +.emoji-2734 { background-position: -24660px 0px; } +.emoji-2744 { background-position: -24680px 0px; } +.emoji-2747 { background-position: -24700px 0px; } +.emoji-274C { background-position: -24720px 0px; } +.emoji-274E { background-position: -24740px 0px; } +.emoji-2753 { background-position: -24760px 0px; } +.emoji-2754 { background-position: -24780px 0px; } +.emoji-2755 { background-position: -24800px 0px; } +.emoji-2757 { background-position: -24820px 0px; } +.emoji-2764 { background-position: -24840px 0px; } +.emoji-2795 { background-position: -24860px 0px; } +.emoji-2796 { background-position: -24880px 0px; } +.emoji-2797 { background-position: -24900px 0px; } +.emoji-27A1 { background-position: -24920px 0px; } +.emoji-27B0 { background-position: -24940px 0px; } +.emoji-27BF { background-position: -24960px 0px; } +.emoji-2934 { background-position: -24980px 0px; } +.emoji-2935 { background-position: -25000px 0px; } +.emoji-2B05 { background-position: -25020px 0px; } +.emoji-2B06 { background-position: -25040px 0px; } +.emoji-2B07 { background-position: -25060px 0px; } +.emoji-2B1B { background-position: -25080px 0px; } +.emoji-2B1C { background-position: -25100px 0px; } +.emoji-2B50 { background-position: -25120px 0px; } +.emoji-2B55 { background-position: -25140px 0px; } +.emoji-3030 { background-position: -25160px 0px; } +.emoji-303D { background-position: -25180px 0px; } +.emoji-3297 { background-position: -25200px 0px; } +.emoji-3299 { background-position: -25220px 0px; } \ No newline at end of file -- cgit v1.2.1 From d361e1df818dfcdf48458a6f459e3efc12d8f64e Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 22 Dec 2015 17:15:25 +0200 Subject: emoji picker: minor fixes --- lib/award_emoji.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/award_emoji.rb b/lib/award_emoji.rb index d3f98d2d7f0..3825f4650be 100644 --- a/lib/award_emoji.rb +++ b/lib/award_emoji.rb @@ -45,14 +45,6 @@ class AwardEmoji food_drink: "Food" }.with_indifferent_access - def self.positions_by_name(name) - emoji = emojis_json.find do |emoji| - emoji["short_names"].include?(name) - end - - [emoji["sheet_x"], emoji["sheet_y"]] - end - def self.normilize_emoji_name(name) ALIASES[name] || name end -- cgit v1.2.1 From 3657eb76c265f4cf6c35c13c2e32bd2536df89ed Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 22 Dec 2015 15:32:57 -0200 Subject: Add helper methods to JS validation spec for invalid branch names --- spec/javascripts/new_branch_spec.js.coffee | 179 +++++++++++++++-------------- 1 file changed, 92 insertions(+), 87 deletions(-) diff --git a/spec/javascripts/new_branch_spec.js.coffee b/spec/javascripts/new_branch_spec.js.coffee index ea479239957..8889ce2e9b3 100644 --- a/spec/javascripts/new_branch_spec.js.coffee +++ b/spec/javascripts/new_branch_spec.js.coffee @@ -5,151 +5,156 @@ describe 'Branch', -> describe 'create a new branch', -> fixture.preload('new_branch.html') + fillNameWith = (value) -> + $('.js-branch-name').val(value).trigger('blur') + + expectToHaveError = (error) -> + expect($('.js-branch-name-error span').text()).toEqual(error) + beforeEach -> fixture.load('new_branch.html') $('form').on 'submit', (e) -> e.preventDefault() @form = new NewBranchForm($('.js-create-branch-form'), []) - @name = $('.js-branch-name') it "can't start with a dot", -> - @name.val('.foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't start with '.'") + fillNameWith '.foo' + expectToHaveError "can't start with '.'" it "can't start with a slash", -> - @name.val('/foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't start with '/'") + fillNameWith '/foo' + expectToHaveError "can't start with '/'" it "can't have two consecutive dots", -> - @name.val('foo..bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '..'") + fillNameWith 'foo..bar' + expectToHaveError "can't contain '..'" it "can't have spaces anywhere", -> - @name.val(' foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain spaces") - @name.val('foo bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain spaces") - @name.val('foo ').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain spaces") + fillNameWith ' foo' + expectToHaveError "can't contain spaces" + fillNameWith 'foo bar' + expectToHaveError "can't contain spaces" + fillNameWith 'foo ' + expectToHaveError "can't contain spaces" it "can't have ~ anywhere", -> - @name.val('~foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") - @name.val('foo~bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") - @name.val('foo~').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") + fillNameWith '~foo' + expectToHaveError "can't contain '~'" + fillNameWith 'foo~bar' + expectToHaveError "can't contain '~'" + fillNameWith 'foo~' + expectToHaveError "can't contain '~'" it "can't have tilde anwhere", -> - @name.val('~foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") - @name.val('foo~bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") - @name.val('foo~').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '~'") + fillNameWith '~foo' + expectToHaveError "can't contain '~'" + fillNameWith 'foo~bar' + expectToHaveError "can't contain '~'" + fillNameWith 'foo~' + expectToHaveError "can't contain '~'" it "can't have caret anywhere", -> - @name.val('^foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '^'") - @name.val('foo^bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '^'") - @name.val('foo^').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '^'") + fillNameWith '^foo' + expectToHaveError "can't contain '^'" + fillNameWith 'foo^bar' + expectToHaveError "can't contain '^'" + fillNameWith 'foo^' + expectToHaveError "can't contain '^'" it "can't have : anywhere", -> - @name.val(':foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain ':'") - @name.val('foo:bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain ':'") - @name.val(':foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain ':'") + fillNameWith ':foo' + expectToHaveError "can't contain ':'" + fillNameWith 'foo:bar' + expectToHaveError "can't contain ':'" + fillNameWith ':foo' + expectToHaveError "can't contain ':'" it "can't have question mark anywhere", -> - @name.val('?foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '?'") - @name.val('foo?bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '?'") - @name.val('foo?').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '?'") + fillNameWith '?foo' + expectToHaveError "can't contain '?'" + fillNameWith 'foo?bar' + expectToHaveError "can't contain '?'" + fillNameWith 'foo?' + expectToHaveError "can't contain '?'" it "can't have asterisk anywhere", -> - @name.val('*foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '*'") - @name.val('foo*bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '*'") - @name.val('foo*').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '*'") + fillNameWith '*foo' + expectToHaveError "can't contain '*'" + fillNameWith 'foo*bar' + expectToHaveError "can't contain '*'" + fillNameWith 'foo*' + expectToHaveError "can't contain '*'" it "can't have open bracket anywhere", -> - @name.val('[foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '['") - @name.val('foo[bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '['") - @name.val('foo[').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '['") + fillNameWith '[foo' + expectToHaveError "can't contain '['" + fillNameWith 'foo[bar' + expectToHaveError "can't contain '['" + fillNameWith 'foo[' + expectToHaveError "can't contain '['" it "can't have a backslash anywhere", -> - @name.val('\\foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '\\'") - @name.val('foo\\bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '\\'") - @name.val('foo\\').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '\\'") + fillNameWith '\\foo' + expectToHaveError "can't contain '\\'" + fillNameWith 'foo\\bar' + expectToHaveError "can't contain '\\'" + fillNameWith 'foo\\' + expectToHaveError "can't contain '\\'" it "can't contain a sequence @{ anywhere", -> - @name.val('@{foo').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '@{'") - @name.val('foo@{bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '@{'") - @name.val('foo@{').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '@{'") + fillNameWith '@{foo' + expectToHaveError "can't contain '@{'" + fillNameWith 'foo@{bar' + expectToHaveError "can't contain '@{'" + fillNameWith 'foo@{' + expectToHaveError "can't contain '@{'" it "can't have consecutive slashes", -> - @name.val('foo//bar').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain consecutive slashes") + fillNameWith 'foo//bar' + expectToHaveError "can't contain consecutive slashes" it "can't end with a slash", -> - @name.val('foo/').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't end in '/'") + fillNameWith 'foo/' + expectToHaveError "can't end in '/'" it "can't end with a dot", -> - @name.val('foo.').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't end in '.'") + fillNameWith 'foo.' + expectToHaveError "can't end in '.'" it "can't end with .lock", -> - @name.val('foo.lock').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't end in '.lock'") + fillNameWith 'foo.lock' + expectToHaveError "can't end in '.lock'" it "can't be the single character @", -> - @name.val('@').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't be '@'") + fillNameWith '@' + expectToHaveError "can't be '@'" it "concatenates all error messages", -> - @name.val('/foo bar?~.').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't start with '/', can't contain spaces, '?', '~', can't end in '.'") + fillNameWith '/foo bar?~.' + expectToHaveError "can't start with '/', can't contain spaces, '?', '~', can't end in '.'" it "doesn't duplicate error messages", -> - @name.val('?foo?bar?zoo?').trigger('blur') - expect($('.js-branch-name-error span').text()).toEqual("can't contain '?'") + fillNameWith '?foo?bar?zoo?' + expectToHaveError "can't contain '?'" it "removes the error message when is a valid name", -> - @name.val('foo?bar').trigger('blur') + fillNameWith 'foo?bar' expect($('.js-branch-name-error span').length).toEqual(1) - @name.val('foobar').trigger('blur') + fillNameWith 'foobar' expect($('.js-branch-name-error span').length).toEqual(0) it "can have dashes anywhere", -> - @name.val('-foo-bar-zoo-').trigger('blur') + fillNameWith '-foo-bar-zoo-' expect($('.js-branch-name-error span').length).toEqual(0) it "can have underscores anywhere", -> - @name.val('_foo_bar_zoo_').trigger('blur') + fillNameWith '_foo_bar_zoo_' expect($('.js-branch-name-error span').length).toEqual(0) it "can have numbers anywhere", -> - @name.val('1foo2bar3zoo4').trigger('blur') + fillNameWith '1foo2bar3zoo4' expect($('.js-branch-name-error span').length).toEqual(0) it "can be only letters", -> - @name.val('foo').trigger('blur') + fillNameWith 'foo' expect($('.js-branch-name-error span').length).toEqual(0) -- cgit v1.2.1 From bc9467cc0809fb7bb2b502ac99bd797461b1b7cc Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 22 Dec 2015 19:39:15 +0200 Subject: fix specs --- app/helpers/issues_helper.rb | 6 ++++-- features/steps/project/issues/award_emoji.rb | 4 ++-- spec/helpers/issues_helper_spec.rb | 6 ------ 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 4373847ba7a..bd568d64e4b 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -97,8 +97,10 @@ module IssuesHelper def emoji_icon(name, unicode = nil) unicode ||= Emoji.emoji_filename(name) - content_tag :div, "", class: "icon emoji-icon emoji-#{unicode}", - "data-emoji" => name, "data-unicode-name" => unicode + content_tag :div, "", + class: "icon emoji-icon emoji-#{unicode}", + "data-emoji" => name, + "data-unicode-name" => unicode end def emoji_author_list(notes, current_user) diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index 325eaf2ea6a..e367323f4a5 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -15,8 +15,8 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps end step 'I click to emoji in the picker' do - page.within '.awards-menu' do - page.first('img').click + page.within '.emoji-menu' do + page.first('.emoji-icon').click end end diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 0fd96c7dc27..04e795025d2 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -127,12 +127,6 @@ describe IssuesHelper do it { is_expected.to eq("!1, !2, or !3") } end - describe "#emoji_list" do - it "returns url" do - expect(emoji_list).to be_kind_of(Array) - end - end - describe "#note_active_class" do before do @note = create :note -- cgit v1.2.1 From 791c5bff7dd8c5eaf5d586e6c751b169923685d6 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 22 Dec 2015 19:47:38 +0200 Subject: add some spinach --- features/project/issues/award_emoji.feature | 5 +++++ features/steps/project/issues/award_emoji.rb | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/features/project/issues/award_emoji.feature b/features/project/issues/award_emoji.feature index 0ce99e855c6..cbf2e7104ab 100644 --- a/features/project/issues/award_emoji.feature +++ b/features/project/issues/award_emoji.feature @@ -13,6 +13,11 @@ Feature: Award Emoji Then I have award added And I can remove it by clicking to icon + @javascript + Scenario: I can see the list of emoji categories + Given I click to emoji-picker + Then I can see the activity and food categories + @javascript Scenario: I add award emoji using regular comment Given I leave comment with a single emoji diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index e367323f4a5..c94d0ba7306 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -27,6 +27,13 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps end end + step 'I can see the activity and food categories' do + page.within '.emoji-menu' do + expect(page).to_not have_selector 'Activity' + expect(page).to_not have_selector 'Food' + end + end + step 'I have award added' do page.within '.awards' do expect(page).to have_selector '.award' -- cgit v1.2.1 From 559318c85e23745f2feccce8b71784acbd4a0adb Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 22 Dec 2015 19:59:02 +0200 Subject: customize niceScroll --- app/views/votes/_votes_block.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml index 6c7f05c730c..65d3f4c7faf 100644 --- a/app/views/votes/_votes_block.html.haml +++ b/app/views/votes/_votes_block.html.haml @@ -42,4 +42,4 @@ $(".award").tooltip() - $(".emoji-menu-content").niceScroll({cursorwidth: "7px"}) + $(".emoji-menu-content").niceScroll({cursorwidth: "7px", autohidemode: false}) -- cgit v1.2.1 From f049b939653c9ff1be6ef9835682978d6db90196 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 22 Dec 2015 20:02:22 +0200 Subject: TYPO in the comment --- app/assets/javascripts/awards_handler.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index f3fdd46cf52..84e7287e48d 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -65,7 +65,7 @@ class @AwardsHandler resetTooltip: (award) -> award.tooltip("destroy") - # "destroy" call is asynchronous and there is no appropriate callnack on it, this is why we need to set timeout. + # "destroy" call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout. setTimeout (-> award.tooltip() ), 200 -- cgit v1.2.1 From 1d3889eb465655af5f7e3e6c3af9f3f529e6c9b5 Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Tue, 22 Dec 2015 13:00:41 -0500 Subject: Fix identity and user retrieval when special characters are used --- app/models/identity.rb | 1 + lib/gitlab/ldap/user.rb | 4 ++-- lib/gitlab/o_auth/user.rb | 2 +- spec/lib/gitlab/ldap/user_spec.rb | 15 +++++++++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/app/models/identity.rb b/app/models/identity.rb index ad60154be71..8bcdc194953 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -12,6 +12,7 @@ class Identity < ActiveRecord::Base include Sortable + include CaseSensitivity belongs_to :user validates :provider, presence: true diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index 4be99dd88c2..01bfe09cf07 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -14,7 +14,7 @@ module Gitlab # LDAP distinguished name is case-insensitive identity = ::Identity. where(provider: provider). - where('lower(extern_uid) = ?', uid.mb_chars.downcase.to_s).last + iwhere(extern_uid: uid.mb_chars.to_s).last identity && identity.user end end @@ -31,7 +31,7 @@ module Gitlab def find_by_uid_and_provider self.class.find_by_uid_and_provider( - auth_hash.uid.downcase, auth_hash.provider) + auth_hash.uid, auth_hash.provider) end def find_by_email diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb index 17ce4d4b174..f1a362f5303 100644 --- a/lib/gitlab/o_auth/user.rb +++ b/lib/gitlab/o_auth/user.rb @@ -64,7 +64,7 @@ module Gitlab # If a corresponding person exists with same uid in a LDAP server, # set up a Gitlab user with dual LDAP and Omniauth identities. - if user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn.downcase, ldap_person.provider) + if user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn, ldap_person.provider) # Case when a LDAP user already exists in Gitlab. Add the Omniauth identity to existing account. user.identities.build(extern_uid: auth_hash.uid, provider: auth_hash.provider) else diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb index 3bba5e2efa2..1e755259dae 100644 --- a/spec/lib/gitlab/ldap/user_spec.rb +++ b/spec/lib/gitlab/ldap/user_spec.rb @@ -42,6 +42,21 @@ describe Gitlab::LDAP::User, lib: true do end end + describe '.find_by_uid_and_provider' do + it 'retrieves the correct user' do + special_info = { + name: 'John Åström', + email: 'john@example.com', + nickname: 'jastrom' + } + special_hash = OmniAuth::AuthHash.new(uid: 'CN=John Åström,CN=Users,DC=Example,DC=com', provider: 'ldapmain', info: special_info) + special_chars_user = described_class.new(special_hash) + user = special_chars_user.save + + expect(described_class.find_by_uid_and_provider(special_hash.uid, special_hash.provider)).to eq user + end + end + describe :find_or_create do it "finds the user if already existing" do create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain') -- cgit v1.2.1 From d794ae8e1f6351282707d45df97ac0ec2a41eeb6 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 22 Dec 2015 23:04:19 +0200 Subject: add frequently used category to emoji picker --- CHANGELOG | 3 +++ app/assets/javascripts/awards_handler.coffee | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7f9dfd98cd7..d4b0e3ccf00 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ Please view this file on the master branch, on stable branches it's out of date. +v 8.4.0 (unreleased) + - Add "Frequently used" category to emoji picker + v 8.3.0 (unreleased) - Expand character set of usernames created by Omniauth (Corey Hinshaw) - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 84e7287e48d..0dc84b4c7ac 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -10,6 +10,8 @@ class @AwardsHandler if $(".emoji-menu").is(":visible") $(".emoji-menu").hide() + @renderFrequentlyUsedBlock() + addAward: (emoji) -> emoji = @normilizeEmojiName(emoji) @postEmoji emoji, => @@ -18,6 +20,8 @@ class @AwardsHandler $(".emoji-menu").hide() addAwardToEmojiBar: (emoji) -> + @addEmojiToFrequentlyUsedList(emoji) + emoji = @normilizeEmojiName(emoji) if @exist(emoji) if @isActive(emoji) @@ -108,3 +112,25 @@ class @AwardsHandler normilizeEmojiName: (emoji) -> @aliases[emoji] || emoji + + addEmojiToFrequentlyUsedList: (emoji) -> + frequently_used_emojis = @getFrequentlyUsedEmojis() + frequently_used_emojis.push(emoji) + $.cookie('frequently_used_emojis', frequently_used_emojis.join(","), { expires: 365 }) + + getFrequentlyUsedEmojis: -> + frequently_used_emojis = ($.cookie('frequently_used_emojis') || "").split(",") + _.compact(_.uniq(frequently_used_emojis)) + + renderFrequentlyUsedBlock: -> + if $.cookie('frequently_used_emojis') + frequently_used_emojis = @getFrequentlyUsedEmojis() + + ul = $("
    ") + + for emoji in frequently_used_emojis + do (emoji) -> + $(".emoji-menu-content [data-emoji='" + emoji + "']").closest("li").clone().appendTo(ul) + + $(".emoji-menu-content").prepend(ul).prepend($("

    ").text("Frequently used")) + -- cgit v1.2.1 From 34695569da0526cde82348286da0e68aaa6273e4 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 22 Dec 2015 13:15:32 -0800 Subject: Fix Error 500 when global milestones have slashes Closes #4226 --- CHANGELOG | 3 +++ app/models/global_milestone.rb | 2 +- spec/models/global_milestone_spec.rb | 10 ++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 851a8ed0145..cd70e83555a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,9 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.4.0 (unreleased) - Implement new UI for group page +v 8.3.1 (unreleased) + - Fix Error 500 when global milestones have slashes (Stan Hu) + v 8.3.0 - Add CAS support (tduehr) - Bump rack-attack to 4.3.1 for security fix (Stan Hu) diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index 8bfc79d88f8..af1d7562ebe 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -16,7 +16,7 @@ class GlobalMilestone end def safe_title - @title.to_slug.to_s + @title.to_slug.normalize.to_s end def expired? diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb index ba03e6aabd0..197c99cd007 100644 --- a/spec/models/global_milestone_spec.rb +++ b/spec/models/global_milestone_spec.rb @@ -62,4 +62,14 @@ describe GlobalMilestone, models: true do expect(@global_milestone.milestones.count).to eq(3) end end + + describe :safe_title do + let(:milestone) { create(:milestone, title: "git / test", project: project1) } + + it 'should strip out slashes and spaces' do + global_milestone = GlobalMilestone.new(milestone.title, [milestone]) + + expect(global_milestone.safe_title).to eq('git-test') + end + end end -- cgit v1.2.1 From efe98067da478a61a2d5e673b381c43eaace9d83 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 23 Dec 2015 12:01:31 +0200 Subject: emoji picker search --- CHANGELOG | 1 + app/assets/javascripts/awards_handler.coffee | 22 ++++++++++++++++++++++ app/assets/stylesheets/pages/awards.scss | 4 ++++ app/views/votes/_votes_block.html.haml | 3 ++- features/project/issues/award_emoji.feature | 6 ++++++ features/steps/project/issues/award_emoji.rb | 12 ++++++++++++ 6 files changed, 47 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 851a8ed0145..5ccf657445a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.4.0 (unreleased) - Implement new UI for group page + - Implement search inside emoji picker v 8.3.0 - Add CAS support (tduehr) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 84e7287e48d..99b9e281259 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -10,6 +10,8 @@ class @AwardsHandler if $(".emoji-menu").is(":visible") $(".emoji-menu").hide() + @setupSearch() + addAward: (emoji) -> emoji = @normilizeEmojiName(emoji) @postEmoji emoji, => @@ -108,3 +110,23 @@ class @AwardsHandler normilizeEmojiName: (emoji) -> @aliases[emoji] || emoji + + setupSearch: -> + $("input.emoji-search").keyup (ev)=> + term = $(ev.target).val() + + # Clean previous search results + $("ul.emoji-search,h5.emoji-search").remove() + + if term + # Generate search result block + h5 = $("
    ").text("Search results").addClass("emoji-search") + found_emojis = @searchEmojis(term).show() + ul = $("
      ").addClass("emoji-search").append(found_emojis) + $(".emoji-menu-content ul, .emoji-menu-content h5").hide() + $(".emoji-menu-content").append(h5).append(ul) + else + $(".emoji-menu-content").children().show() + + searchEmojis: (term)-> + $(".emoji-menu-content [data-emoji*='" + term + "']").closest("li").clone() diff --git a/app/assets/stylesheets/pages/awards.scss b/app/assets/stylesheets/pages/awards.scss index aa1a06b2fcc..842d73acaa6 100644 --- a/app/assets/stylesheets/pages/awards.scss +++ b/app/assets/stylesheets/pages/awards.scss @@ -101,6 +101,10 @@ overflow: auto; } + input.emoji-search{ + background: url(/assets/icon-search.png) 240px no-repeat; + } + li { cursor: pointer; width: 30px; diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml index 8c660ba16cc..5cd0c5f60f0 100644 --- a/app/views/votes/_votes_block.html.haml +++ b/app/views/votes/_votes_block.html.haml @@ -11,6 +11,7 @@ = icon('smile-o') .emoji-menu .emoji-menu-content + = text_field_tag :emoji_search, "", class: "emoji-search search-input form-control" - AwardEmoji.emoji_by_category.each do |category, emojis| %h5= AwardEmoji::CATEGORIES[category] %ul @@ -32,7 +33,7 @@ aliases ) - $(".emoji-menu-content li").click (e)-> + $(".awards").on "click", ".emoji-menu-content li", (e)-> emoji = $(this).find(".emoji-icon").data("emoji") awards_handler.addAward(emoji) diff --git a/features/project/issues/award_emoji.feature b/features/project/issues/award_emoji.feature index cbf2e7104ab..a996ae603fc 100644 --- a/features/project/issues/award_emoji.feature +++ b/features/project/issues/award_emoji.feature @@ -18,6 +18,12 @@ Feature: Award Emoji Given I click to emoji-picker Then I can see the activity and food categories + @javascript + Scenario: I can search emoji + Given I click to emoji-picker + And I search "hand" + Then I see search result for "hand" + @javascript Scenario: I add award emoji using regular comment Given I leave comment with a single emoji diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index c94d0ba7306..a7e15398819 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -52,4 +52,16 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps click_button 'Add Comment' end end + + step 'I search "hand"' do + page.within('.emoji-menu-content') do + fill_in 'emoji_search', with: 'hand' + end + end + + step 'I see search result for "hand"' do + page.within '.emoji-menu-content' do + expect(page).to have_selector '[data-emoji="raised_hand"]' + end + end end -- cgit v1.2.1 From 7b50ab5c1de71e8d2e9e959bfd1cbf68352c70ec Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 18 Dec 2015 14:17:19 -0500 Subject: arrows for buttons --- app/assets/stylesheets/pages/projects.scss | 61 +++++++++++++++++++++++++++++- app/views/projects/_home_panel.html.haml | 2 +- app/views/projects/buttons/_fork.html.haml | 5 +++ app/views/projects/buttons/_star.html.haml | 6 +++ 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 2ded32dba12..31a093fadd5 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -101,11 +101,70 @@ margin-top: 12px; margin-bottom: 0px; + .count-buttons { + display: block; + } + .btn { @include btn-gray; - + text-transform: none; + } + .count-with-arrow { + display: inline-block; + position: relative; + margin-left: 4px; + + .arrow { + + &:before { + content: ''; + display: inline-block; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 50%; + left: 0; + margin-top: -6px; + border-width: 7px 5px 7px 0; + border-right-color: #dce0e5; + } + + &:after { + content: ''; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 50%; + left: 1px; + margin-top: -9px; + border-width: 10px 7px 10px 0; + border-right-color: #FFF; + } + } .count { + @include btn-gray; display: inline-block; + background: white; + border-radius: 2px; + border-width: 1px; + border-style: solid; + font-size: 13px; + font-weight: 600; + line-height: 20px; + padding: 11px 16px; + letter-spacing: .4px; + padding: 10px; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; + white-space: nowrap; + margin: 0 11px 0px 4px; } } } diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index c1669ac046b..4420861c9dc 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -27,7 +27,7 @@ = icon('rss') .project-repo-buttons - .split-one + .split-one.count-buttons = render 'projects/buttons/star' = render 'projects/buttons/fork' diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index 2d3abf09051..133531887a2 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -4,10 +4,15 @@ = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has_tooltip' do = icon('code-fork fw') Fork + %div.count-with-arrow + %span.arrow %span.count = @project.forks_count - else = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has_tooltip' do = icon('code-fork fw') + Fork + %div.count-with-arrow + %span.arrow %span.count = @project.forks_count diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 41a3ec6d90f..27d63cc4cec 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,6 +1,9 @@ - if current_user = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do = icon('star fw') + Star + %div.count-with-arrow + %span.arrow %span.count = @project.star_count @@ -15,5 +18,8 @@ - else = link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do = icon('star fw') + Star + %div.count-with-arrow + %span.arrow %span.count = @project.star_count -- cgit v1.2.1 From 011a7a32978ea6cfc7857f9afa7f2f242a753634 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 18 Dec 2015 16:06:48 -0500 Subject: adds starring and unstarring text to star button, also adds partial new styles --- app/assets/stylesheets/pages/projects.scss | 5 ++++- app/controllers/projects_controller.rb | 2 +- app/views/projects/buttons/_star.html.haml | 19 +++++++++++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 31a093fadd5..32a66052659 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -115,7 +115,6 @@ margin-left: 4px; .arrow { - &:before { content: ''; display: inline-block; @@ -165,6 +164,10 @@ background-image: none; white-space: nowrap; margin: 0 11px 0px 4px; + + &:hover { + background: #FFF; + } } } } diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index bf5e25ff895..2dab04f2a7c 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -171,7 +171,7 @@ class ProjectsController < ApplicationController @project.reload render json: { - html: view_to_html_string("projects/buttons/_star") + star_count: @project.star_count } end diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 27d63cc4cec..4289d7afd26 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,7 +1,10 @@ - if current_user = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do = icon('star fw') - Star + - if current_user.starred?(@project) + %span.starred Unstar + - else + %span Star %div.count-with-arrow %span.arrow %span.count @@ -9,7 +12,19 @@ :javascript $('.project-home-panel .toggle-star').on('ajax:success', function (e, data, status, xhr) { - $(this).replaceWith(data.html); + var $this = $(this); + var $starSpan = $this.find('span'); + $this + .parent() + .find('span.count') + .text(data.star_count); + if($starSpan.hasClass('starred')){ + $starSpan.removeClass('starred'); + $starSpan.text('Star'); + } else { + $starSpan.addClass('starred'); + $starSpan.text('Unstar'); + } }) .on('ajax:error', function (e, xhr, status, error) { new Flash('Star toggle failed. Try again later.', 'alert'); -- cgit v1.2.1 From f56783e5244c8199dc30fb8374a96d8e5d96549c Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 18 Dec 2015 17:12:47 -0500 Subject: adds dropdown for cloning --- app/assets/stylesheets/pages/projects.scss | 11 ++++++++-- app/views/projects/buttons/_star.html.haml | 21 +++++++++++++++----- app/views/shared/_clone_panel.html.haml | 32 ++++++++++++++++++++++-------- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 32a66052659..7626bf113dc 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -91,10 +91,9 @@ } } - .input-group { + .git-clone-holder { display: inline-table; position: relative; - top: 17px; } .project-repo-buttons { @@ -103,6 +102,7 @@ .count-buttons { display: block; + margin-bottom: 12px; } .btn { @@ -187,6 +187,13 @@ margin-right: 45px; } + .clone-options { + display: table-cell; + a.btn { + width: 100%; + } + } + .form-control { cursor: auto; @extend .monospace; diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 4289d7afd26..aba959f991a 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,9 +1,10 @@ - if current_user = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do - = icon('star fw') - if current_user.starred?(@project) + = icon('star fw') %span.starred Unstar - else + = icon('star-o fw') %span Star %div.count-with-arrow %span.arrow @@ -14,16 +15,26 @@ $('.project-home-panel .toggle-star').on('ajax:success', function (e, data, status, xhr) { var $this = $(this); var $starSpan = $this.find('span'); + var $starIcon = $this.find('i'); $this .parent() .find('span.count') .text(data.star_count); if($starSpan.hasClass('starred')){ - $starSpan.removeClass('starred'); - $starSpan.text('Star'); + $starSpan + .removeClass('starred') + .text('Star'); + $starIcon + .removeClass('fa-star') + .addClass('fa-star-o'); + } else { - $starSpan.addClass('starred'); - $starSpan.text('Unstar'); + $starSpan + .addClass('starred') + .text('Unstar'); + $starIcon + .removeClass('fa-star-o') + .addClass('fa-star'); } }) .on('ajax:error', function (e, xhr, status, error) { diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index edb5778f424..d6fa2ea6a66 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -1,10 +1,26 @@ - project = project || @project -.git-clone-holder.input-group - .input-group-addon.git-protocols + +.git-clone-holder + .btn-group.clone-options + %a.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} + %span SSH + = icon('angle-down') + %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown + %li + %a{href: '#'} + SSH + %li + %a{href: '#'} + HTTPS + + = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true .input-group-btn - = ssh_clone_button(project) - .input-group-btn - = http_clone_button(project) - = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true - .input-group-btn - = clipboard_button(clipboard_target: '#project_clone') + = clipboard_button(clipboard_target: '#project_clone') + +:javascript + $('ul.clone-options-dropdown a').on('click',function(e){ + e.preventDefault(); + var $this = $(this); + $('a.clone-dropdown-btn span').text($this.text()); + console.log("got it",$(this).text()); + }); -- cgit v1.2.1 From ea5fa54b2d1949a21503661b3fd5a25401bf110e Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 18 Dec 2015 17:24:43 -0500 Subject: dropdown chooses right default --- app/views/shared/_clone_panel.html.haml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index d6fa2ea6a66..74e82af48c8 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -3,14 +3,15 @@ .git-clone-holder .btn-group.clone-options %a.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} - %span SSH + %span + = default_clone_protocol.upcase = icon('angle-down') %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown %li - %a{href: '#'} + %a{href: '#', "data-url" => @project.ssh_url_to_repo} SSH %li - %a{href: '#'} + %a{href: '#', "data-url" => @project.http_url_to_repo} HTTPS = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true @@ -22,5 +23,5 @@ e.preventDefault(); var $this = $(this); $('a.clone-dropdown-btn span').text($this.text()); - console.log("got it",$(this).text()); + $('#project_clone').val($this.data('url')); }); -- cgit v1.2.1 From 69f9bf77d4ad3fd6c690bf863337854f4347494d Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 23 Dec 2015 12:26:41 -0500 Subject: spinach tests will pass now --- app/views/projects/buttons/_star.html.haml | 2 +- features/project/star.feature | 1 + features/steps/project/star.rb | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index aba959f991a..0f2ee119871 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -8,7 +8,7 @@ %span Star %div.count-with-arrow %span.arrow - %span.count + %span.count.star-count = @project.star_count :javascript diff --git a/features/project/star.feature b/features/project/star.feature index a45f9c470ea..618f44fe6dc 100644 --- a/features/project/star.feature +++ b/features/project/star.feature @@ -1,3 +1,4 @@ +@project-stars Feature: Project Star Scenario: New projects have 0 stars Given public project "Community" diff --git a/features/steps/project/star.rb b/features/steps/project/star.rb index bd2e0619cdd..9f7c748a3b7 100644 --- a/features/steps/project/star.rb +++ b/features/steps/project/star.rb @@ -32,6 +32,6 @@ class Spinach::Features::ProjectStar < Spinach::FeatureSteps protected def has_n_stars(n) - expect(page).to have_css(".star-btn .count", text: n, visible: true) + expect(page).to have_css(".star-count", text: n, visible: true) end end -- cgit v1.2.1 From 8bbcbe78546beda04420e4403f7e6d42b38a55e4 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 23 Dec 2015 12:43:27 -0500 Subject: spacing changed from 4 to 2 in ` _clone_panel.html.haml`. --- app/views/shared/_clone_panel.html.haml | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 74e82af48c8..9edd1f0750e 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -1,27 +1,27 @@ - project = project || @project .git-clone-holder - .btn-group.clone-options - %a.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} - %span - = default_clone_protocol.upcase - = icon('angle-down') - %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown - %li - %a{href: '#', "data-url" => @project.ssh_url_to_repo} - SSH - %li - %a{href: '#', "data-url" => @project.http_url_to_repo} - HTTPS + .btn-group.clone-options + %a.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} + %span + = default_clone_protocol.upcase + = icon('angle-down') + %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown + %li + %a{href: '#', "data-url" => @project.ssh_url_to_repo} + SSH + %li + %a{href: '#', "data-url" => @project.http_url_to_repo} + HTTPS - = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true - .input-group-btn - = clipboard_button(clipboard_target: '#project_clone') + = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true + .input-group-btn + = clipboard_button(clipboard_target: '#project_clone') :javascript - $('ul.clone-options-dropdown a').on('click',function(e){ - e.preventDefault(); - var $this = $(this); - $('a.clone-dropdown-btn span').text($this.text()); - $('#project_clone').val($this.data('url')); - }); + $('ul.clone-options-dropdown a').on('click',function(e){ + e.preventDefault(); + var $this = $(this); + $('a.clone-dropdown-btn span').text($this.text()); + $('#project_clone').val($this.data('url')); + }); -- cgit v1.2.1 From 52293ccd65b1de8c2f70642d8146a09518258c47 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 23 Dec 2015 12:54:51 -0500 Subject: refactoring javascript to put starring functionality in a function --- app/views/projects/buttons/_star.html.haml | 43 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index 0f2ee119871..f92488fd88f 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -16,26 +16,31 @@ var $this = $(this); var $starSpan = $this.find('span'); var $starIcon = $this.find('i'); - $this - .parent() - .find('span.count') - .text(data.star_count); - if($starSpan.hasClass('starred')){ - $starSpan - .removeClass('starred') - .text('Star'); - $starIcon - .removeClass('fa-star') - .addClass('fa-star-o'); - } else { - $starSpan - .addClass('starred') - .text('Unstar'); - $starIcon - .removeClass('fa-star-o') - .addClass('fa-star'); - } + var toggleStar = function(isStarred) { + $this + .parent() + .find('span.count') + .text(data.star_count); + if(isStarred){ + $starSpan + .removeClass('starred') + .text('Star'); + $starIcon + .removeClass('fa-star') + .addClass('fa-star-o'); + + } else { + $starSpan + .addClass('starred') + .text('Unstar'); + $starIcon + .removeClass('fa-star-o') + .addClass('fa-star'); + } + }; + + toggleStar($starSpan.hasClass('starred')); }) .on('ajax:error', function (e, xhr, status, error) { new Flash('Star toggle failed. Try again later.', 'alert'); -- cgit v1.2.1 From 7ba4482fcf6faae162ceb920044f4ec07ef048af Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 23 Dec 2015 19:57:30 -0500 Subject: fixes failing test by updating project clone instructions --- app/assets/javascripts/project.js.coffee | 5 +++-- app/views/shared/_clone_panel.html.haml | 8 ++++---- features/project/create.feature | 1 + features/steps/project/create.rb | 10 ++++++---- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 1f221945c06..d7a658f8faa 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -1,7 +1,7 @@ class @Project constructor: -> # Git protocol switcher - $('.js-protocol-switch').click -> + $('ul.clone-options-dropdown a').click -> return if $(@).hasClass('active') @@ -10,7 +10,8 @@ class @Project # Add the active class for the clicked button $(@).toggleClass('active') - url = $(@).data('clone') + url = $("#project_clone").val() + console.log("url",url) # Update the input field $('#project_clone').val(url) diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml index 9edd1f0750e..687a59c270f 100644 --- a/app/views/shared/_clone_panel.html.haml +++ b/app/views/shared/_clone_panel.html.haml @@ -2,16 +2,16 @@ .git-clone-holder .btn-group.clone-options - %a.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} + %a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} %span = default_clone_protocol.upcase = icon('angle-down') %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown %li - %a{href: '#', "data-url" => @project.ssh_url_to_repo} + %a#ssh-selector{href: @project.ssh_url_to_repo} SSH %li - %a{href: '#', "data-url" => @project.http_url_to_repo} + %a#http-selector{href: @project.http_url_to_repo} HTTPS = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true @@ -23,5 +23,5 @@ e.preventDefault(); var $this = $(this); $('a.clone-dropdown-btn span').text($this.text()); - $('#project_clone').val($this.data('url')); + $('#project_clone').val($this.attr('href')); }); diff --git a/features/project/create.feature b/features/project/create.feature index a86079143e5..27136798e36 100644 --- a/features/project/create.feature +++ b/features/project/create.feature @@ -1,3 +1,4 @@ +@project-create Feature: Project Create In order to get access to project sections A user with ability to create a project diff --git a/features/steps/project/create.rb b/features/steps/project/create.rb index f90218f3791..0c247c83133 100644 --- a/features/steps/project/create.rb +++ b/features/steps/project/create.rb @@ -26,18 +26,20 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps end step 'I click on HTTP' do - click_button 'HTTP' + find('#clone-dropdown').click + find('#http-selector').click end step 'Remote url should update to http link' do - expect(page).to have_content "git remote add origin #{Project.last.http_url_to_repo}" + expect(page).to have_content Project.last.http_url_to_repo end step 'If I click on SSH' do - click_button 'SSH' + find('#clone-dropdown').click + find('#ssh-selector').click end step 'Remote url should update to ssh link' do - expect(page).to have_content "git remote add origin #{Project.last.url_to_repo}" + expect(page).to have_content Project.last.ssh_url_to_repo end end -- cgit v1.2.1 From 6592bfbb9ed37c348f257106c1da35692ef6a111 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 23 Dec 2015 20:36:29 -0500 Subject: Moves star code to a class --- app/assets/javascripts/star.js.coffee | 22 +++++++++++++++++++ app/views/projects/_home_panel.html.haml | 3 +++ app/views/projects/buttons/_star.html.haml | 35 ------------------------------ features/steps/project/create.rb | 4 ++-- 4 files changed, 27 insertions(+), 37 deletions(-) create mode 100644 app/assets/javascripts/star.js.coffee diff --git a/app/assets/javascripts/star.js.coffee b/app/assets/javascripts/star.js.coffee new file mode 100644 index 00000000000..d849b2e7950 --- /dev/null +++ b/app/assets/javascripts/star.js.coffee @@ -0,0 +1,22 @@ +class @Star + constructor: -> + $('.project-home-panel .toggle-star').on('ajax:success', (e, data, status, xhr) -> + $this = $(this) + $starSpan = $this.find('span') + $starIcon = $this.find('i') + + toggleStar = (isStarred) -> + $this.parent().find('span.count').text data.star_count + if isStarred + $starSpan.removeClass('starred').text 'Star' + $starIcon.removeClass('fa-star').addClass 'fa-star-o' + else + $starSpan.addClass('starred').text 'Unstar' + $starIcon.removeClass('fa-star-o').addClass 'fa-star' + return + + toggleStar $starSpan.hasClass('starred') + return + ).on 'ajax:error', (e, xhr, status, error) -> + new Flash('Star toggle failed. Try again later.', 'alert') + return \ No newline at end of file diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 4420861c9dc..e92115b9b98 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -38,3 +38,6 @@ = render 'projects/buttons/dropdown' = render 'projects/buttons/notifications' + +:coffeescript + new Star() \ No newline at end of file diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index f92488fd88f..21ba426aaa1 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -11,41 +11,6 @@ %span.count.star-count = @project.star_count - :javascript - $('.project-home-panel .toggle-star').on('ajax:success', function (e, data, status, xhr) { - var $this = $(this); - var $starSpan = $this.find('span'); - var $starIcon = $this.find('i'); - - var toggleStar = function(isStarred) { - $this - .parent() - .find('span.count') - .text(data.star_count); - if(isStarred){ - $starSpan - .removeClass('starred') - .text('Star'); - $starIcon - .removeClass('fa-star') - .addClass('fa-star-o'); - - } else { - $starSpan - .addClass('starred') - .text('Unstar'); - $starIcon - .removeClass('fa-star-o') - .addClass('fa-star'); - } - }; - - toggleStar($starSpan.hasClass('starred')); - }) - .on('ajax:error', function (e, xhr, status, error) { - new Flash('Star toggle failed. Try again later.', 'alert'); - }); - - else = link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do = icon('star fw') diff --git a/features/steps/project/create.rb b/features/steps/project/create.rb index 0c247c83133..8a0e8fc2b6c 100644 --- a/features/steps/project/create.rb +++ b/features/steps/project/create.rb @@ -31,7 +31,7 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps end step 'Remote url should update to http link' do - expect(page).to have_content Project.last.http_url_to_repo + expect(page).to have_content "git remote add origin #{Project.last.http_url_to_repo}" end step 'If I click on SSH' do @@ -40,6 +40,6 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps end step 'Remote url should update to ssh link' do - expect(page).to have_content Project.last.ssh_url_to_repo + expect(page).to have_content "git remote add origin #{Project.last.url_to_repo}" end end -- cgit v1.2.1 From a1294e5aabcfcc50423d78184b1bb34031754519 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 23 Dec 2015 20:39:42 -0500 Subject: fixes css spacing issues --- app/assets/stylesheets/pages/projects.scss | 54 +++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index c4275ef6c87..2894e935e8d 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -115,33 +115,33 @@ margin-left: 4px; .arrow { - &:before { - content: ''; - display: inline-block; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - top: 50%; - left: 0; - margin-top: -6px; - border-width: 7px 5px 7px 0; - border-right-color: #dce0e5; - } - - &:after { - content: ''; - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - top: 50%; - left: 1px; - margin-top: -9px; - border-width: 10px 7px 10px 0; - border-right-color: #FFF; + &:before { + content: ''; + display: inline-block; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 50%; + left: 0; + margin-top: -6px; + border-width: 7px 5px 7px 0; + border-right-color: #dce0e5; + } + + &:after { + content: ''; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 50%; + left: 1px; + margin-top: -9px; + border-width: 10px 7px 10px 0; + border-right-color: #FFF; } } .count { -- cgit v1.2.1 From c301ab0404229b0f3b0ff2cdd0482f1e0c0196ea Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 24 Dec 2015 10:33:26 +0100 Subject: Add some specs for forked project visibility_level cases --- spec/models/project_spec.rb | 24 +++++++++++++++++ spec/services/projects/update_service_spec.rb | 39 +++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index c4d3813e9c9..400bdf2d962 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -552,4 +552,28 @@ describe Project, models: true do end end end + + describe '#visibility_level_allowed?' do + let(:project) { create :project, visibility_level: Gitlab::VisibilityLevel::INTERNAL } + + context 'when checking on non-forked project' do + it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy } + it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_truthy } + it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PUBLIC)).to be_truthy } + end + + context 'when checking on forked project' do + let(:forked_project) { create :forked_project_with_submodules } + + before do + forked_project.build_forked_project_link(forked_to_project_id: forked_project.id, forked_from_project_id: project.id) + forked_project.save + end + + it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy } + it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_truthy } + it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::PUBLIC)).to be_falsey } + end + + end end diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index c36d4581989..3c06a890163 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -100,6 +100,45 @@ describe Projects::UpdateService, services: true do end end + describe :visibility_level do + let(:user) { create :user, admin: true } + let(:project) { create :project, visibility_level: Gitlab::VisibilityLevel::INTERNAL } + let(:forked_project) { create :forked_project_with_submodules, visibility_level: Gitlab::VisibilityLevel::INTERNAL } + let(:opts) { {} } + + before do + forked_project.build_forked_project_link(forked_to_project_id: forked_project.id, forked_from_project_id: project.id) + forked_project.save + + @created_internal = project.internal? + @fork_created_internal = forked_project.internal? + end + + context 'should update forks visibility level when parent set to more restrictive' do + before do + opts.merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) + update_project(project, user, opts).inspect + end + + it { expect(@created_internal).to be_truthy } + it { expect(@fork_created_internal).to be_truthy } + it { expect(project.private?).to be_truthy } + it { expect(project.forks.first.private?).to be_truthy } + end + + context 'should not update forks visibility level when parent set to less restrictive' do + before do + opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + update_project(project, user, opts).inspect + end + + it { expect(@created_internal).to be_truthy } + it { expect(@fork_created_internal).to be_truthy } + it { expect(project.public?).to be_truthy } + it { expect(project.forks.first.internal?).to be_truthy } + end + end + def update_project(project, user, opts) Projects::UpdateService.new(project, user, opts).execute end -- cgit v1.2.1 From 5da8c1f77a7a6f65366c02d17af763c0e19996bf Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 24 Dec 2015 11:57:46 +0200 Subject: fixes after review --- app/assets/javascripts/awards_handler.coffee | 4 ++-- app/assets/stylesheets/pages/awards.scss | 2 +- app/assets/stylesheets/pages/emojis.scss | 2 +- app/views/votes/_votes_block.html.haml | 4 ++-- features/project/issues/award_emoji.feature | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index fc49a1e7bf4..392440a2b00 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -118,7 +118,7 @@ class @AwardsHandler @aliases[emoji] || emoji setupSearch: -> - $("input.emoji-search").keyup (ev)=> + $("input.emoji-search").keyup (ev) => term = $(ev.target).val() # Clean previous search results @@ -135,4 +135,4 @@ class @AwardsHandler $(".emoji-menu-content").children().show() searchEmojis: (term)-> - $(".emoji-menu-content [data-emoji*='" + term + "']").closest("li").clone() + $(".emoji-menu-content [data-emoji*='#{term}']").closest("li").clone() diff --git a/app/assets/stylesheets/pages/awards.scss b/app/assets/stylesheets/pages/awards.scss index 842d73acaa6..19d0d361c79 100644 --- a/app/assets/stylesheets/pages/awards.scss +++ b/app/assets/stylesheets/pages/awards.scss @@ -102,7 +102,7 @@ } input.emoji-search{ - background: url(/assets/icon-search.png) 240px no-repeat; + background: image-url(/assets/icon-search.png) 240px no-repeat; } li { diff --git a/app/assets/stylesheets/pages/emojis.scss b/app/assets/stylesheets/pages/emojis.scss index 819ec9a2f5f..920d0e3d338 100644 --- a/app/assets/stylesheets/pages/emojis.scss +++ b/app/assets/stylesheets/pages/emojis.scss @@ -4,7 +4,7 @@ The source: gemojione gem. */ .emoji-icon{ - background-image: url(emoji.png); + background-image: image-url(emoji.png); background-repeat: no-repeat; } diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml index a344ac1a62e..e16187bb42f 100644 --- a/app/views/votes/_votes_block.html.haml +++ b/app/views/votes/_votes_block.html.haml @@ -33,11 +33,11 @@ aliases ) - $(".awards").on "click", ".emoji-menu-content li", (e)-> + $(".awards").on "click", ".emoji-menu-content li", (e) -> emoji = $(this).find(".emoji-icon").data("emoji") awards_handler.addAward(emoji) - $(".awards").on "click", ".award", (e)-> + $(".awards").on "click", ".award", (e) -> emoji = $(this).find(".icon").data("emoji") awards_handler.addAward(emoji) diff --git a/features/project/issues/award_emoji.feature b/features/project/issues/award_emoji.feature index a996ae603fc..2126e826ddc 100644 --- a/features/project/issues/award_emoji.feature +++ b/features/project/issues/award_emoji.feature @@ -18,7 +18,7 @@ Feature: Award Emoji Given I click to emoji-picker Then I can see the activity and food categories - @javascript + @javascript Scenario: I can search emoji Given I click to emoji-picker And I search "hand" -- cgit v1.2.1 From 5939d24756cddf77e1389fb6a3f52b160c007a3d Mon Sep 17 00:00:00 2001 From: Andriy Dyadyura Date: Thu, 24 Dec 2015 12:22:01 +0100 Subject: nav full width --- app/assets/stylesheets/pages/projects.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 99006b9f5d1..3917efeecdb 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -337,6 +337,8 @@ ul.nav.nav-projects-tabs { .top-area { border-bottom: 1px solid #EEE; + margin: 0 -16px; + padding: 0 $gl-padding; ul.left-top-menu { display: inline-block; -- cgit v1.2.1 From 662aa8ec35a2c1a898ade5be3a525591786cd9f5 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 24 Dec 2015 12:37:46 +0100 Subject: No mb_chars needed anymore --- lib/gitlab/ldap/user.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index 01bfe09cf07..aef08c97d1d 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -14,7 +14,7 @@ module Gitlab # LDAP distinguished name is case-insensitive identity = ::Identity. where(provider: provider). - iwhere(extern_uid: uid.mb_chars.to_s).last + iwhere(extern_uid: uid).last identity && identity.user end end @@ -47,7 +47,7 @@ module Gitlab # find_or_initialize_by doesn't update `gl_user.identities`, and isn't autosaved. identity = gl_user.identities.find { |identity| identity.provider == auth_hash.provider } identity ||= gl_user.identities.build(provider: auth_hash.provider) - + # For a new user set extern_uid to the LDAP DN # For an existing user with matching email but changed DN, update the DN. # For an existing user with no change in DN, this line changes nothing. -- cgit v1.2.1 From 7309b848e2e67e3206e986facc0104a11af18d88 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 24 Dec 2015 12:20:00 +0000 Subject: Move changelog items to their correct place. --- CHANGELOG | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0f9ae1e3b52..55e242cff50 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,12 +4,13 @@ v 8.4.0 (unreleased) - Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu) - Implement new UI for group page - Add project permissions to all project API endpoints (Stan Hu) + - Add CAS support (tduehr) + - Add link to merge request on build detail page. + - Expose Git's version in the admin area v 8.3.0 - - Add CAS support (tduehr) - Bump rack-attack to 4.3.1 for security fix (Stan Hu) - API support for starred projects for authorized user (Zeger-Jan van de Weg) - - Add link to merge request on build detail page. - Add open_issues_count to project API (Stan Hu) - Expand character set of usernames created by Omniauth (Corey Hinshaw) - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg) @@ -69,7 +70,6 @@ v 8.3.0 - Do not show build status unless builds are enabled and `.gitlab-ci.yml` is present - Persist runners registration token in database - Fix online editor should not remove newlines at the end of the file - - Expose Git's version in the admin area v 8.2.3 - Fix application settings cache not expiring after changes (Stan Hu) -- cgit v1.2.1 From 6d0705474791c2071153794e9be8df69375e1028 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 24 Dec 2015 14:54:02 +0200 Subject: fix specs --- app/assets/stylesheets/pages/awards.scss | 2 +- app/assets/stylesheets/pages/emojis.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pages/awards.scss b/app/assets/stylesheets/pages/awards.scss index 19d0d361c79..87dd30f4111 100644 --- a/app/assets/stylesheets/pages/awards.scss +++ b/app/assets/stylesheets/pages/awards.scss @@ -102,7 +102,7 @@ } input.emoji-search{ - background: image-url(/assets/icon-search.png) 240px no-repeat; + background: image-url("icon-search.png") 240px no-repeat; } li { diff --git a/app/assets/stylesheets/pages/emojis.scss b/app/assets/stylesheets/pages/emojis.scss index 920d0e3d338..89a94c5a780 100644 --- a/app/assets/stylesheets/pages/emojis.scss +++ b/app/assets/stylesheets/pages/emojis.scss @@ -4,7 +4,7 @@ The source: gemojione gem. */ .emoji-icon{ - background-image: image-url(emoji.png); + background-image: image-url("emoji.png"); background-repeat: no-repeat; } -- cgit v1.2.1 From 40a3845fab760a0600e06a2dc2fab4b942b5ffa3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 24 Dec 2015 14:11:51 +0100 Subject: Fix explore projects page UI Signed-off-by: Dmitriy Zaporozhets --- app/views/explore/projects/index.html.haml | 2 +- app/views/explore/projects/starred.html.haml | 2 +- app/views/explore/projects/trending.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index 76bdd68fd76..b9a958fbe7b 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -6,7 +6,7 @@ - else = render 'explore/head' -.gray-content-block.clearfix +.gray-content-block.clearfix.second-block = render 'filter' = render 'projects', projects: @projects = paginate @projects, theme: "gitlab" diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index e30c3633223..95d46e331f8 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -7,7 +7,7 @@ = render 'explore/head' .explore-trending-block - .gray-content-block + .gray-content-block.second-block .pull-right = render 'explore/projects/dropdown' .oneline diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index 1412b19acde..fa0b718e48b 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -7,7 +7,7 @@ = render 'explore/head' .explore-trending-block - .gray-content-block + .gray-content-block.second-block .pull-right = render 'explore/projects/dropdown' .oneline -- cgit v1.2.1 From a55b653d938e5ca5464c48174da3adce84cab275 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 24 Dec 2015 15:44:43 +0200 Subject: fix of frequently used emojis --- app/assets/javascripts/awards_handler.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 93860e3bbf3..bb17427852d 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -137,9 +137,9 @@ class @AwardsHandler for emoji in frequently_used_emojis do (emoji) -> - $(".emoji-menu-content [data-emoji='" + emoji + "']").closest("li").clone().appendTo(ul) + $(".emoji-menu-content [data-emoji='#{emoji}']").closest("li").clone().appendTo(ul) - $(".emoji-menu-content").prepend(ul).prepend($("

      ").text("Frequently used")) + $("input.emoji-search").after(ul).after($("

      ").text("Frequently used")) setupSearch: -> $("input.emoji-search").keyup (ev) => @@ -149,7 +149,7 @@ class @AwardsHandler $("ul.emoji-search,h5.emoji-search").remove() if term - # Generate search result block + # Generate a search result block h5 = $("
      ").text("Search results").addClass("emoji-search") found_emojis = @searchEmojis(term).show() ul = $("
        ").addClass("emoji-search").append(found_emojis) -- cgit v1.2.1 From 93b5ea6f0e9704df6bb1164e42dca987b9a285b3 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 24 Dec 2015 15:09:29 +0100 Subject: Fix NewBranchForm spec --- spec/javascripts/new_branch_spec.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/javascripts/new_branch_spec.js.coffee b/spec/javascripts/new_branch_spec.js.coffee index 8889ce2e9b3..f2ce85efcdc 100644 --- a/spec/javascripts/new_branch_spec.js.coffee +++ b/spec/javascripts/new_branch_spec.js.coffee @@ -1,4 +1,4 @@ -#= require jquery.ui.all +#= require jquery-ui #= require new_branch_form describe 'Branch', -> -- cgit v1.2.1 From 355e62eb498de90f91ac129af94d4a0f2ec6b129 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 24 Dec 2015 16:35:45 +0200 Subject: added default for frequently used emojis --- CHANGELOG | 5 ++--- app/assets/javascripts/awards_handler.coffee | 16 +++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 41e09f8b992..207b2bb1ba1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,13 +1,12 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.4.0 (unreleased) - - Add "Frequently used" category to emoji picker - -v 8.3.0 (unreleased) - Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu) - Implement new UI for group page - Implement search inside emoji picker - Add project permissions to all project API endpoints (Stan Hu) + - Add "Frequently used" category to emoji picker + v 8.3.0 - Add CAS support (tduehr) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index bb17427852d..04bf5cc7bb5 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -127,19 +127,21 @@ class @AwardsHandler getFrequentlyUsedEmojis: -> frequently_used_emojis = ($.cookie('frequently_used_emojis') || "").split(",") + + frequently_used_emojis = ["thumbsup", "thumbsdown"].concat(frequently_used_emojis) + _.compact(_.uniq(frequently_used_emojis)) renderFrequentlyUsedBlock: -> - if $.cookie('frequently_used_emojis') - frequently_used_emojis = @getFrequentlyUsedEmojis() + frequently_used_emojis = @getFrequentlyUsedEmojis() - ul = $("
          ") + ul = $("
            ") - for emoji in frequently_used_emojis - do (emoji) -> - $(".emoji-menu-content [data-emoji='#{emoji}']").closest("li").clone().appendTo(ul) + for emoji in frequently_used_emojis + do (emoji) -> + $(".emoji-menu-content [data-emoji='#{emoji}']").closest("li").clone().appendTo(ul) - $("input.emoji-search").after(ul).after($("
            ").text("Frequently used")) + $("input.emoji-search").after(ul).after($("
            ").text("Frequently used")) setupSearch: -> $("input.emoji-search").keyup (ev) => -- cgit v1.2.1 From e3befaed82f9aa52c79a1d4c437fe4fc63f8d07a Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 24 Dec 2015 14:05:30 -0500 Subject: Update CHANGELOG [ci skip] --- CHANGELOG | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 96d71331321..de8ac5161a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,6 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.4.0 (unreleased) - - Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu) - Implement new UI for group page - Implement search inside emoji picker - Add project permissions to all project API endpoints (Stan Hu) @@ -12,6 +11,9 @@ v 8.4.0 (unreleased) v 8.3.1 - Fix Error 500 when global milestones have slashes (Stan Hu) + - Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu) + - Fix LDAP identity and user retrieval when special characters are used + - Move Sidekiq-cron configuration to gitlab.yml v 8.3.0 - Bump rack-attack to 4.3.1 for security fix (Stan Hu) -- cgit v1.2.1