diff options
96 files changed, 3791 insertions, 479 deletions
diff --git a/CHANGELOG b/CHANGELOG index 738162d983f..733c20df248 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.7.0 (unreleased) + - All service classes (those residing in app/services) are now instrumented (Yorick Peterse) - Enable gzip for assets, makes the page size significantly smaller. !3544 / !3632 (Connor Shea) - Load award emoji images separately unless opening the full picker. Saves several hundred KBs of data for most pages. (Connor Shea) - All images in discussions and wikis now link to their source files !3464 (Connor Shea). @@ -19,14 +20,20 @@ v 8.7.0 (unreleased) - Add endpoints to archive or unarchive a project !3372 - Add links to CI setup documentation from project settings and builds pages - Handle nil descriptions in Slack issue messages (Stan Hu) + - API: Expose open_issues_count, closed_issues_count, open_merge_requests_count for labels (Robert Schilling) - Add default scope to projects to exclude projects pending deletion - Ensure empty recipients are rejected in BuildsEmailService - API: Ability to filter milestones by state `active` and `closed` (Robert Schilling) + - API: Fix milestone filtering by `iid` (Robert Schilling) + - API: Delete notes of issues, snippets, and merge requests (Robert Schilling) - Implement 'Groups View' as an option for dashboard preferences !3379 (Elias W.) - Better errors handling when creating milestones inside groups + - Hide `Create a group` help block when creating a new project in a group - Implement 'TODOs View' as an option for dashboard preferences !3379 (Elias W.) - Gracefully handle notes on deleted commits in merge requests (Stan Hu) + - Decouple membership and notifications - Fix creation of merge requests for orphaned branches (Stan Hu) + - API: Ability to retrieve a single tag (Robert Schilling) - Fall back to `In-Reply-To` and `References` headers when sub-addressing is not available (David Padilla) - Remove "Congratulations!" tweet button on newly-created project. (Connor Shea) - Fix admin/projects when using visibility levels on search (PotHix) @@ -35,6 +42,12 @@ v 8.7.0 (unreleased) - ClosingIssueExtractor regex now also works with colons. e.g. "Fixes: #1234" !3591 - Update number of Todos in the sidebar when it's marked as "Done". !3600 - Sanitize branch names created for confidential issues + - API: Expose 'updated_at' for issue, snippet, and merge request notes (Robert Schilling) + - API: User can leave a project through the API when not master or owner. !3613 + +v 8.6.6 + - Fix error on language detection when repository has no HEAD (e.g., master branch). !3654 (Jeroen Bobbeldijk) + - Project switcher uses new dropdown styling v 8.6.5 - Fix importing from GitHub Enterprise. !3529 @@ -285,9 +285,9 @@ group :development, :test do gem 'teaspoon', '~> 1.1.0' gem 'teaspoon-jasmine', '~> 2.2.0' - gem 'spring', '~> 1.6.4' + gem 'spring', '~> 1.7.0' gem 'spring-commands-rspec', '~> 1.0.4' - gem 'spring-commands-spinach', '~> 1.0.0' + gem 'spring-commands-spinach', '~> 1.1.0' gem 'spring-commands-teaspoon', '~> 0.0.2' gem 'rubocop', '~> 0.38.0', require: false diff --git a/Gemfile.lock b/Gemfile.lock index 9da44a46583..ad7d7c18559 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -769,10 +769,10 @@ GEM spinach (>= 0.4) spinach-rerun-reporter (0.0.2) spinach (~> 0.8) - spring (1.6.4) + spring (1.7.1) spring-commands-rspec (1.0.4) spring (>= 0.9.1) - spring-commands-spinach (1.0.0) + spring-commands-spinach (1.1.0) spring (>= 0.9.1) spring-commands-teaspoon (0.0.2) spring (>= 0.9.1) @@ -1030,9 +1030,9 @@ DEPENDENCIES slack-notifier (~> 1.2.0) spinach-rails (~> 0.2.1) spinach-rerun-reporter (~> 0.0.2) - spring (~> 1.6.4) + spring (~> 1.7.0) spring-commands-rspec (~> 1.0.4) - spring-commands-spinach (~> 1.0.0) + spring-commands-spinach (~> 1.1.0) spring-commands-teaspoon (~> 0.0.2) sprockets (~> 3.6.0) state_machines-activerecord (~> 0.3.0) diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index f01c67e9474..b05138ac1ac 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -41,6 +41,7 @@ #= require shortcuts_issuable #= require shortcuts_network #= require jquery.nicescroll +#= require date.format #= require_tree . #= require fuzzaldrin-plus #= require cropper @@ -163,7 +164,7 @@ $ -> $('.trigger-submit').on 'change', -> $(@).parents('form').submit() - $('abbr.timeago, .js-timeago').timeago() + gl.utils.localTimeAgo($('abbr.timeago, .js-timeago'), false) # Flash if (flash = $(".flash-container")).length > 0 diff --git a/app/assets/javascripts/behaviors/requires_input.js.coffee b/app/assets/javascripts/behaviors/requires_input.js.coffee index 79d750d1847..0faa570ce13 100644 --- a/app/assets/javascripts/behaviors/requires_input.js.coffee +++ b/app/assets/javascripts/behaviors/requires_input.js.coffee @@ -35,4 +35,18 @@ $.fn.requiresInput = -> $form.on 'change input', fieldSelector, requireInput $ -> - $('form.js-requires-input').requiresInput() + $form = $('form.js-requires-input') + $form.requiresInput() + + # Hide or Show the help block when creating a new project + # based on the option selected + hideOrShowHelpBlock = (form) -> + selected = $('.js-select-namespace option:selected') + if selected.length and selected.data('options-parent') is 'groups' + return form.find('.help-block').hide() + else if selected.length + form.find('.help-block').show() + + hideOrShowHelpBlock($form) + + $('.select2.js-select-namespace').change -> hideOrShowHelpBlock($form) diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index ee1d0fad289..2dc37257e22 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -122,7 +122,9 @@ class GitLabDropdown FILTER_INPUT = '.dropdown-input .dropdown-input-field' constructor: (@el, @options) -> - @dropdown = $(@el).parent() + self = @ + selector = $(@el).data "target" + @dropdown = if selector? then $(selector) else $(@el).parent() # Set Defaults { diff --git a/app/assets/javascripts/lib/datetime_utility.js.coffee b/app/assets/javascripts/lib/datetime_utility.js.coffee new file mode 100644 index 00000000000..ad1d1c70481 --- /dev/null +++ b/app/assets/javascripts/lib/datetime_utility.js.coffee @@ -0,0 +1,17 @@ +((w) -> + + w.gl ?= {} + w.gl.utils ?= {} + + w.gl.utils.formatDate = (datetime) -> + dateFormat(datetime, 'mmm d, yyyy h:MMtt Z') + + w.gl.utils.localTimeAgo = ($timeagoEls, setTimeago = true) -> + $timeagoEls.each( -> + $el = $(@) + $el.attr('title', gl.utils.formatDate($el.attr('datetime'))) + ) + + $timeagoEls.timeago() if setTimeago + +) window diff --git a/app/assets/javascripts/lib/notify.js.coffee b/app/assets/javascripts/lib/notify.js.coffee index 3f9ca39912c..9e28353ac34 100644 --- a/app/assets/javascripts/lib/notify.js.coffee +++ b/app/assets/javascripts/lib/notify.js.coffee @@ -2,6 +2,11 @@ notificationGranted = (message, opts, onclick) -> notification = new Notification(message, opts) + # Hide the notification after X amount of seconds + setTimeout -> + notification.close() + , 8000 + if onclick notification.onclick = onclick diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee index 9946249adbf..ef0b534a709 100644 --- a/app/assets/javascripts/merge_request_tabs.js.coffee +++ b/app/assets/javascripts/merge_request_tabs.js.coffee @@ -142,7 +142,7 @@ class @MergeRequestTabs url: "#{source}.json" success: (data) => document.querySelector("div#commits").innerHTML = data.html - $('.js-timeago').timeago() + gl.utils.localTimeAgo($('.js-timeago', 'div#commits')) @commitsLoaded = true @scrollToElement("#commits") @@ -153,7 +153,7 @@ class @MergeRequestTabs url: "#{source}.json" + @_location.search success: (data) => document.querySelector("div#diffs").innerHTML = data.html - $('.js-timeago').timeago() + gl.utils.localTimeAgo($('.js-timeago', 'div#diffs')) $('div#diffs .js-syntax-highlight').syntaxHighlight() @expandViewContainer() if @diffViewType() is 'parallel' @diffsLoaded = true @@ -166,7 +166,7 @@ class @MergeRequestTabs url: "#{source}.json" success: (data) => document.querySelector("div#builds").innerHTML = data.html - $('.js-timeago').timeago() + gl.utils.localTimeAgo($('.js-timeago', 'div#builds')) @buildsLoaded = true @scrollToElement("#builds") diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee index 84a8887fbce..065626beeb8 100644 --- a/app/assets/javascripts/merge_request_widget.js.coffee +++ b/app/assets/javascripts/merge_request_widget.js.coffee @@ -12,10 +12,19 @@ class @MergeRequestWidget @readyForCICheck = true clearInterval @fetchBuildStatusInterval + @clearEventListeners() + @addEventListeners() @pollCIStatus() notifyPermissions() - setOpts: (@opts) -> + clearEventListeners: -> + $(document).off 'page:change.merge_request' + + addEventListeners: -> + $(document).on 'page:change.merge_request', => + if $('body').data('page') isnt 'projects:merge_requests:show' + clearInterval @fetchBuildStatusInterval + @clearEventListeners() mergeInProgress: (deleteSourceBranch = false)-> $.ajax @@ -38,7 +47,7 @@ class @MergeRequestWidget $('.mr-state-widget').replaceWith(data) ciLabelForStatus: (status) -> - if status == 'success' + if status is 'success' 'passed' else status @@ -67,18 +76,28 @@ class @MergeRequestWidget @opts.ci_status = data.status return - if data.status isnt @opts.ci_status + if data.status isnt @opts.ci_status and data.status? @showCIStatus data.status if data.coverage @showCICoverage data.coverage if showNotification - message = @opts.ci_message.replace('{{status}}', @ciLabelForStatus(data.status)) + status = @ciLabelForStatus(data.status) + + if status is "preparing" + title = @opts.ci_title.preparing + status = status.charAt(0).toUpperCase() + status.slice(1); + message = @opts.ci_message.preparing.replace('{{status}}', status) + else + title = @opts.ci_title.normal + message = @opts.ci_message.normal.replace('{{status}}', status) + + title = title.replace('{{status}}', status) message = message.replace('{{sha}}', data.sha) message = message.replace('{{title}}', data.title) notify( - "Build #{@ciLabelForStatus(data.status)}", + title, message, @opts.gitlab_icon, -> @@ -98,6 +117,8 @@ class @MergeRequestWidget @setMergeButtonClass('btn-danger') when "running", "pending" @setMergeButtonClass('btn-warning') + when "success" + @setMergeButtonClass('btn-create') else $('.ci_widget.ci-error').show() @setMergeButtonClass('btn-danger') @@ -107,4 +128,6 @@ class @MergeRequestWidget $('.ci_widget:visible .ci-coverage').text(text) setMergeButtonClass: (css_class) -> - $('.accept_merge_request').removeClass("btn-create").addClass(css_class) + $('.accept_merge_request') + .removeClass('btn-danger btn-warning btn-create') + .addClass(css_class) diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 86e3b860fcb..a67890200dd 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -163,9 +163,15 @@ class @Notes else if @isNewNote(note) @note_ids.push(note.id) - $('ul.main-notes-list') + $notesList = $('ul.main-notes-list') + + $notesList .append(note.html) .syntaxHighlight() + + # Update datetime format on the recent note + gl.utils.localTimeAgo($notesList.find("#note_#{note.id} .js-timeago"), false) + @initTaskList() @updateNotesCount(1) @@ -217,6 +223,8 @@ class @Notes # append new note to all matching discussions discussionContainer.append note_html + gl.utils.localTimeAgo($('.js-timeago', note_html), false) + @updateNotesCount(1) ### @@ -345,7 +353,9 @@ class @Notes updateNote: (_xhr, note, _status) => # Convert returned HTML to a jQuery object so we can modify it further $html = $(note.html) - $('.js-timeago', $html).timeago() + + gl.utils.localTimeAgo($('.js-timeago', $html)) + $html.syntaxHighlight() $html.find('.js-task-list-container').taskList('enable') diff --git a/app/assets/javascripts/profile.js.coffee b/app/assets/javascripts/profile.js.coffee index ae87c6c4e40..f4a2562885d 100644 --- a/app/assets/javascripts/profile.js.coffee +++ b/app/assets/javascripts/profile.js.coffee @@ -18,8 +18,11 @@ class @Profile $(this).find('.btn-save').enable() $(this).find('.loading-gif').hide() - $('.update-notifications').on 'ajax:complete', -> - $(this).find('.btn-save').enable() + $('.update-notifications').on 'ajax:success', (e, data) -> + if data.saved + new Flash("Notification settings saved", "notice") + else + new Flash("Failed to save new settings", "alert") @bindEvents() diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index 87d313ed67c..07be85a32a5 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -37,19 +37,20 @@ class @Project $('.update-notification').on 'click', (e) -> e.preventDefault() notification_level = $(@).data 'notification-level' - $('#notification_level').val(notification_level) + label = $(@).data 'notification-title' + $('#notification_setting_level').val(notification_level) $('#notification-form').submit() - label = null - switch notification_level - when 0 then label = ' Disabled ' - when 1 then label = ' Participating ' - when 2 then label = ' Watching ' - when 3 then label = ' Global ' - when 4 then label = ' On Mention ' $('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>") $(@).parents('ul').find('li.active').removeClass 'active' $(@).parent().addClass 'active' + $('#notification-form').on 'ajax:success', (e, data) -> + if data.saved + new Flash("Notification settings saved", "notice") + else + new Flash("Failed to save new settings", "alert") + + @projectSelectDropdown() projectSelectDropdown: -> diff --git a/app/assets/javascripts/project_select.js.coffee b/app/assets/javascripts/project_select.js.coffee index be8ab9b428d..704bd8dee53 100644 --- a/app/assets/javascripts/project_select.js.coffee +++ b/app/assets/javascripts/project_select.js.coffee @@ -1,5 +1,37 @@ class @ProjectSelect constructor: -> + $('.js-projects-dropdown-toggle').each (i, dropdown) -> + $dropdown = $(dropdown) + + $dropdown.glDropdown( + filterable: true + filterRemote: true + search: + fields: ['name_with_namespace'] + data: (term, callback) -> + finalCallback = (projects) -> + callback projects + + if @includeGroups + projectsCallback = (projects) -> + groupsCallback = (groups) -> + data = groups.concat(projects) + finalCallback(data) + + Api.groups term, false, groupsCallback + else + projectsCallback = finalCallback + + if @groupId + Api.groupProjects @groupId, term, projectsCallback + else + Api.projects term, @orderBy, projectsCallback + url: (project) -> + project.web_url + text: (project) -> + project.name_with_namespace + ) + $('.ajax-project-select').each (i, select) -> @groupId = $(select).data('group-id') @includeGroups = $(select).data('include-groups') diff --git a/app/assets/javascripts/todos.js.coffee b/app/assets/javascripts/todos.js.coffee index 886da72e261..00d2b641723 100644 --- a/app/assets/javascripts/todos.js.coffee +++ b/app/assets/javascripts/todos.js.coffee @@ -59,6 +59,8 @@ class @Todos goToTodoUrl: (e)-> todoLink = $(this).data('url') + return unless todoLink + if e.metaKey e.preventDefault() window.open(todoLink,'_blank') diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index b3397d16016..3f015427d07 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -69,6 +69,7 @@ header { } .header-content { + position: relative; height: $header-height; padding-right: 20px; @@ -76,6 +77,10 @@ header { padding-right: 0; } + .dropdown-menu { + margin-top: -5px; + } + .title { margin: 0; font-size: 19px; diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 94f5a12ff6a..192d53b048a 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -58,12 +58,12 @@ .nav-search { display: inline-block; - width: 50%; + width: 100%; padding: 11px 0; /* Small devices (phones, tablets, 768px and lower) */ - @media (max-width: $screen-sm-min) { - width: 100%; + @media (min-width: $screen-sm-min) { + width: 50%; } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 1ebbd9b0e57..0b6be86ce6a 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -28,6 +28,7 @@ $gl-link-color: #3084bb; $gl-dark-link-color: #333; $gl-placeholder-color: #8f8f8f; $gl-icon-color: $gl-placeholder-color; +$gl-grayish-blue: #7f8fa4; $gl-gray: $gl-text-color; $gl-header-color: $gl-title-color; diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss index c66efe978cd..6fe57c737b3 100644 --- a/app/assets/stylesheets/pages/events.scss +++ b/app/assets/stylesheets/pages/events.scss @@ -41,8 +41,17 @@ word-wrap: break-word; .md { - color: #7f8fa4; + color: $gl-grayish-blue; font-size: $gl-font-size; + + .label { + color: $gl-text-color; + font-size: inherit; + } + + iframe.twitter-share-button { + vertical-align: bottom; + } } pre { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 88c1b614c74..8b6f37f21b5 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -263,6 +263,12 @@ } } + .dropdown-content { + a:hover { + color: inherit; + } + } + .dropdown-menu-toggle { width: 100%; padding-top: 6px; diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index b79335eab91..4ef548ffbe7 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -142,6 +142,7 @@ overflow: hidden; font-size: 90%; margin: 0 3px; + word-break: break-all; } .mr-list { diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 4d4d508396d..f4da17fadaa 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -71,12 +71,24 @@ border-color: $focus-border-color; } } + + p { + code { + white-space: normal; + } + + pre { + code { + white-space: pre; + } + } + } } } .discussion-form { padding: $gl-padding-top $gl-padding; - background-color: #fff; + background-color: $white-light; } .note-edit-form { diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 7295fe51121..e421a31549a 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -81,9 +81,15 @@ ul.notes { @include md-typography; // On diffs code should wrap nicely and not overflow - pre { + p { code { - white-space: pre; + white-space: normal; + } + + pre { + code { + white-space: pre; + } } } @@ -112,6 +118,10 @@ ul.notes { margin: 10px 0; } } + + a { + word-break: break-all; + } } .note-header { @@ -127,7 +137,7 @@ ul.notes { margin-right: 10px; } .line_content { - white-space: pre-wrap; + white-space: pre; } } @@ -145,19 +155,27 @@ ul.notes { background: $background-color; color: $text-color; } + &.notes_line2 { text-align: center; padding: 10px 0; border-left: 1px solid #ddd !important; } + &.notes_content { - background-color: #fff; + background-color: $background-color; border-width: 1px 0; padding: 0; vertical-align: top; + white-space: normal; + &.parallel { border-width: 1px; } + + .notes { + background-color: $white-light; + } } } } diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss index e83fa9e3d52..75f78569e3c 100644 --- a/app/assets/stylesheets/pages/todos.scss +++ b/app/assets/stylesheets/pages/todos.scss @@ -34,6 +34,11 @@ color: #7f8fa4; font-size: $gl-font-size; + .label { + color: $gl-text-color; + font-size: inherit; + } + p { color: #5c5d5e; } diff --git a/app/controllers/groups/notification_settings_controller.rb b/app/controllers/groups/notification_settings_controller.rb new file mode 100644 index 00000000000..de13b16ccf2 --- /dev/null +++ b/app/controllers/groups/notification_settings_controller.rb @@ -0,0 +1,16 @@ +class Groups::NotificationSettingsController < Groups::ApplicationController + before_action :authenticate_user! + + def update + notification_setting = current_user.notification_settings_for(group) + saved = notification_setting.update_attributes(notification_setting_params) + + render json: { saved: saved } + end + + private + + def notification_setting_params + params.require(:notification_setting).permit(:level) + end +end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index d28e96c3f18..df98f56a1cd 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -60,6 +60,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController continue_login_process end + rescue Gitlab::OAuth::SignupDisabledError + handle_signup_error end def omniauth_error @@ -92,16 +94,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController continue_login_process end rescue Gitlab::OAuth::SignupDisabledError - label = Gitlab::OAuth::Provider.label_for(oauth['provider']) - message = "Signing in using your #{label} account without a pre-existing GitLab account is not allowed." - - if current_application_settings.signup_enabled? - message << " Create a GitLab account first, and then connect it to your #{label} account." - end - - flash[:notice] = message - - redirect_to new_user_session_path + handle_signup_error end def handle_service_ticket provider, ticket @@ -122,6 +115,19 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController end end + def handle_signup_error + label = Gitlab::OAuth::Provider.label_for(oauth['provider']) + message = "Signing in using your #{label} account without a pre-existing GitLab account is not allowed." + + if current_application_settings.signup_enabled? + message << " Create a GitLab account first, and then connect it to your #{label} account." + end + + flash[:notice] = message + + redirect_to new_user_session_path + end + def oauth @oauth ||= request.env['omniauth.auth'] end diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb index 1fd1d6882df..18ee55c839a 100644 --- a/app/controllers/profiles/notifications_controller.rb +++ b/app/controllers/profiles/notifications_controller.rb @@ -1,39 +1,18 @@ class Profiles::NotificationsController < Profiles::ApplicationController def show @user = current_user - @notification = current_user.notification - @project_members = current_user.project_members - @group_members = current_user.group_members + @group_notifications = current_user.notification_settings.for_groups + @project_notifications = current_user.notification_settings.for_projects end def update - type = params[:notification_type] - - @saved = if type == 'global' - current_user.update_attributes(user_params) - elsif type == 'group' - group_member = current_user.group_members.find(params[:notification_id]) - group_member.notification_level = params[:notification_level] - group_member.save - else - project_member = current_user.project_members.find(params[:notification_id]) - project_member.notification_level = params[:notification_level] - project_member.save - end - - respond_to do |format| - format.html do - if @saved - flash[:notice] = "Notification settings saved" - else - flash[:alert] = "Failed to save new settings" - end - - redirect_back_or_default(default: profile_notifications_path) - end - - format.js + if current_user.update_attributes(user_params) + flash[:notice] = "Notification settings saved" + else + flash[:alert] = "Failed to save new settings" end + + redirect_back_or_default(default: profile_notifications_path) end def user_params diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index ae613f5e093..3e0cfc6aa65 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -237,6 +237,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end + status = "preparing" if status.nil? + response = { title: merge_request.title, sha: merge_request.last_commit_short_sha, diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 1b9dd568043..707a0d0e5c6 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -39,8 +39,7 @@ class Projects::NotesController < Projects::ApplicationController def destroy if note.editable? - note.destroy - note.reset_events_cache + Notes::DeleteService.new(project, current_user).execute(note) end respond_to do |format| diff --git a/app/controllers/projects/notification_settings_controller.rb b/app/controllers/projects/notification_settings_controller.rb new file mode 100644 index 00000000000..7d81cc03c73 --- /dev/null +++ b/app/controllers/projects/notification_settings_controller.rb @@ -0,0 +1,16 @@ +class Projects::NotificationSettingsController < Projects::ApplicationController + before_action :authenticate_user! + + def update + notification_setting = current_user.notification_settings_for(project) + saved = notification_setting.update_attributes(notification_setting_params) + + render json: { saved: saved } + end + + private + + def notification_setting_params + params.require(:notification_setting).permit(:level) + end +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3cc37e59855..3768efe142a 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -101,14 +101,18 @@ class ProjectsController < Projects::ApplicationController respond_to do |format| format.html do + if current_user + @membership = @project.team.find_member(current_user.id) + + if @membership + @notification_setting = current_user.notification_settings_for(@project) + end + end + if @project.repository_exists? if @project.empty_repo? render 'projects/empty' else - if current_user - @membership = @project.team.find_member(current_user.id) - end - render :show end else diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e6ceb213532..16e5b8ac223 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -184,7 +184,7 @@ module ApplicationHelper element = content_tag :time, time.to_s, class: "#{html_class} js-timeago #{"js-timeago-pending" unless skip_js}", datetime: time.to_time.getutc.iso8601, - title: time.in_time_zone.to_s(:medium), + title: time.to_time.in_time_zone.to_s(:medium), data: { toggle: 'tooltip', placement: placement, container: 'body' } unless skip_js diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index faba418c4db..94c6b548ecd 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -3,8 +3,16 @@ module NamespacesHelper groups = current_user.owned_groups + current_user.masters_groups users = [current_user.namespace] - group_opts = ["Groups", groups.sort_by(&:human_name).map {|g| [display_path ? g.path : g.human_name, g.id]} ] - users_opts = [ "Users", users.sort_by(&:human_name).map {|u| [display_path ? u.path : u.human_name, u.id]} ] + data_attr_group = { 'data-options-parent' => 'groups' } + data_attr_users = { 'data-options-parent' => 'users' } + + group_opts = [ + "Groups", groups.sort_by(&:human_name).map { |g| [display_path ? g.path : g.human_name, g.id, data_attr_group] } + ] + + users_opts = [ + "Users", users.sort_by(&:human_name).map { |u| [display_path ? u.path : u.human_name, u.id, data_attr_users] } + ] options = [] options << group_opts diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 499c655d2bf..54ab9179efc 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -1,48 +1,48 @@ module NotificationsHelper include IconsHelper - def notification_icon(notification) - if notification.disabled? - icon('volume-off', class: 'ns-mute') - elsif notification.participating? - icon('volume-down', class: 'ns-part') - elsif notification.watch? - icon('volume-up', class: 'ns-watch') - else - icon('circle-o', class: 'ns-default') + def notification_icon_class(level) + case level.to_sym + when :disabled + 'microphone-slash' + when :participating + 'volume-up' + when :watch + 'eye' + when :mention + 'at' + when :global + 'globe' end end - def notification_list_item(notification_level, user_membership) - case notification_level - when Notification::N_DISABLED - update_notification_link(Notification::N_DISABLED, user_membership, 'Disabled', 'microphone-slash') - when Notification::N_PARTICIPATING - update_notification_link(Notification::N_PARTICIPATING, user_membership, 'Participate', 'volume-up') - when Notification::N_WATCH - update_notification_link(Notification::N_WATCH, user_membership, 'Watch', 'eye') - when Notification::N_MENTION - update_notification_link(Notification::N_MENTION, user_membership, 'On mention', 'at') - when Notification::N_GLOBAL - update_notification_link(Notification::N_GLOBAL, user_membership, 'Global', 'globe') - else - # do nothing - end + def notification_icon(level, text = nil) + icon("#{notification_icon_class(level)} fw", text: text) end - def update_notification_link(notification_level, user_membership, title, icon) - content_tag(:li, class: active_level_for(user_membership, notification_level)) do - link_to '#', class: 'update-notification', data: { notification_level: notification_level } do - icon("#{icon} fw", text: title) - end + def notification_title(level) + case level.to_sym + when :participating + 'Participate' + when :mention + 'On mention' + else + level.to_s.titlecase end end - def notification_label(user_membership) - Notification.new(user_membership).to_s - end + def notification_list_item(level, setting) + title = notification_title(level) + + data = { + notification_level: level, + notification_title: title + } - def active_level_for(user_membership, level) - 'active' if user_membership.notification_level == level + content_tag(:li, class: ('active' if setting.level == level)) do + link_to '#', class: 'update-notification', data: data do + notification_icon(level, title) + end + end end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 4e4c6e301d5..7e00aacceaa 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -65,21 +65,14 @@ module ProjectsHelper link_to(simple_sanitize(owner.name), user_path(owner)) end - project_link = link_to project_path(project), { class: "project-item-select-holder" } do - link_output = simple_sanitize(project.name) + project_link = link_to simple_sanitize(project.name), project_path(project), { class: "project-item-select-holder" } - if current_user - link_output += project_select_tag :project_path, - class: "project-item-select js-projects-dropdown", - data: { include_groups: false, order_by: 'last_activity_at' } - end - - link_output + if current_user + project_link << icon("chevron-down", class: "dropdown-toggle-caret js-projects-dropdown-toggle", data: { target: ".js-dropdown-menu-projects", toggle: "dropdown" }) end - project_link += icon "chevron-down", class: "dropdown-toggle-caret js-projects-dropdown-toggle" if current_user - full_title = namespace_link + ' / ' + project_link - full_title += ' · '.html_safe + link_to(simple_sanitize(name), url) if name + full_title = "#{namespace_link} / #{project_link}".html_safe + full_title << ' · '.html_safe << link_to(simple_sanitize(name), url) if name full_title end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index edc5686cf08..2f066682180 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -20,6 +20,8 @@ module TodosHelper end def todo_target_path(todo) + return unless todo.target.present? + anchor = dom_id(todo.note) if todo.note.present? if todo.for_commit? diff --git a/app/models/concerns/notifiable.rb b/app/models/concerns/notifiable.rb deleted file mode 100644 index d7dcd97911d..00000000000 --- a/app/models/concerns/notifiable.rb +++ /dev/null @@ -1,15 +0,0 @@ -# == Notifiable concern -# -# Contains notification functionality -# -module Notifiable - extend ActiveSupport::Concern - - included do - validates :notification_level, inclusion: { in: Notification.project_notification_levels }, presence: true - end - - def notification - @notification ||= Notification.new(self) - end -end diff --git a/app/models/group.rb b/app/models/group.rb index b332601c59b..9a04ac70d35 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -27,6 +27,7 @@ class Group < Namespace has_many :users, through: :group_members has_many :project_group_links, dependent: :destroy has_many :shared_projects, through: :project_group_links, source: :project + has_many :notification_settings, dependent: :destroy, as: :source validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } validate :visibility_level_allowed_by_projects diff --git a/app/models/member.rb b/app/models/member.rb index ca08007b7eb..60efafef211 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -19,7 +19,6 @@ class Member < ActiveRecord::Base include Sortable - include Notifiable include Gitlab::Access attr_accessor :raw_invite_token @@ -56,12 +55,15 @@ class Member < ActiveRecord::Base before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? } after_create :send_invite, if: :invite? + after_create :create_notification_setting, unless: :invite? after_create :post_create_hook, unless: :invite? after_update :post_update_hook, unless: :invite? after_destroy :post_destroy_hook, unless: :invite? delegate :name, :username, :email, to: :user, prefix: true + default_value_for :notification_level, NotificationSetting.levels[:global] + class << self def find_by_invite_token(invite_token) invite_token = Devise.token_generator.digest(self, :invite_token, invite_token) @@ -160,6 +162,14 @@ class Member < ActiveRecord::Base send_invite end + def create_notification_setting + user.notification_settings.find_or_create_for(source) + end + + def notification_setting + @notification_setting ||= user.notification_settings_for(source) + end + private def send_invite diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index 65d2ea00570..9fb474a1a93 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -24,7 +24,6 @@ class GroupMember < Member # Make sure group member points only to group as it source default_value_for :source_type, SOURCE_TYPE - default_value_for :notification_level, Notification::N_GLOBAL validates_format_of :source_type, with: /\ANamespace\z/ default_scope { where(source_type: SOURCE_TYPE) } diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index 560d1690e14..07ddb02ae9d 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -27,7 +27,6 @@ class ProjectMember < Member # Make sure project member points only to project as it source default_value_for :source_type, SOURCE_TYPE - default_value_for :notification_level, Notification::N_GLOBAL validates_format_of :source_type, with: /\AProject\z/ default_scope { where(source_type: SOURCE_TYPE) } diff --git a/app/models/notification.rb b/app/models/notification.rb deleted file mode 100644 index 171b8df45c2..00000000000 --- a/app/models/notification.rb +++ /dev/null @@ -1,77 +0,0 @@ -class Notification - # - # Notification levels - # - N_DISABLED = 0 - N_PARTICIPATING = 1 - N_WATCH = 2 - N_GLOBAL = 3 - N_MENTION = 4 - - attr_accessor :target - - class << self - def notification_levels - [N_DISABLED, N_MENTION, N_PARTICIPATING, N_WATCH] - end - - def options_with_labels - { - disabled: N_DISABLED, - participating: N_PARTICIPATING, - watch: N_WATCH, - mention: N_MENTION, - global: N_GLOBAL - } - end - - def project_notification_levels - [N_DISABLED, N_MENTION, N_PARTICIPATING, N_WATCH, N_GLOBAL] - end - end - - def initialize(target) - @target = target - end - - def disabled? - target.notification_level == N_DISABLED - end - - def participating? - target.notification_level == N_PARTICIPATING - end - - def watch? - target.notification_level == N_WATCH - end - - def global? - target.notification_level == N_GLOBAL - end - - def mention? - target.notification_level == N_MENTION - end - - def level - target.notification_level - end - - def to_s - case level - when N_DISABLED - 'Disabled' - when N_PARTICIPATING - 'Participating' - when N_WATCH - 'Watching' - when N_MENTION - 'On mention' - when N_GLOBAL - 'Global' - else - # do nothing - end - end -end diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb new file mode 100644 index 00000000000..5001738f411 --- /dev/null +++ b/app/models/notification_setting.rb @@ -0,0 +1,28 @@ +class NotificationSetting < ActiveRecord::Base + enum level: { disabled: 0, participating: 1, watch: 2, global: 3, mention: 4 } + + default_value_for :level, NotificationSetting.levels[:global] + + belongs_to :user + belongs_to :source, polymorphic: true + + validates :user, presence: true + validates :source, presence: true + validates :level, presence: true + validates :user_id, uniqueness: { scope: [:source_type, :source_id], + message: "already exists in source", + allow_nil: true } + + scope :for_groups, -> { where(source_type: 'Namespace') } + scope :for_projects, -> { where(source_type: 'Project') } + + def self.find_or_create_for(source) + setting = find_or_initialize_by(source: source) + + unless setting.persisted? + setting.save + end + + setting + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 3e1f04b4158..fadc8bb2c9e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -154,6 +154,7 @@ class Project < ActiveRecord::Base has_many :project_group_links, dependent: :destroy has_many :invited_groups, through: :project_group_links, source: :group has_many :todos, dependent: :destroy + has_many :notification_settings, dependent: :destroy, as: :source has_one :import_data, dependent: :destroy, class_name: "ProjectImportData" @@ -388,9 +389,15 @@ class Project < ActiveRecord::Base def add_import_job if forked? - RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path) + job_id = RepositoryForkWorker.perform_async(self.id, forked_from_project.path_with_namespace, self.namespace.path) else - RepositoryImportWorker.perform_async(self.id) + job_id = RepositoryImportWorker.perform_async(self.id) + end + + if job_id + Rails.logger.info "Import job started for #{path_with_namespace} with job ID #{job_id}" + else + Rails.logger.error "Import job failed to start for #{path_with_namespace}" end end diff --git a/app/models/repository.rb b/app/models/repository.rb index 8dead3a5884..462b48118ef 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -896,9 +896,9 @@ class Repository end def main_language - unless empty? - Linguist::Repository.new(rugged, rugged.head.target_id).language - end + return if empty? || rugged.head_unborn? + + Linguist::Repository.new(rugged, rugged.head.target_id).language end def avatar diff --git a/app/models/user.rb b/app/models/user.rb index 2b0bee2099f..031315debd7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -143,6 +143,7 @@ class User < ActiveRecord::Base has_many :spam_logs, dependent: :destroy has_many :builds, dependent: :nullify, class_name: 'Ci::Build' has_many :todos, dependent: :destroy + has_many :notification_settings, dependent: :destroy # # Validations @@ -157,7 +158,7 @@ class User < ActiveRecord::Base presence: true, uniqueness: { case_sensitive: false } - validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true + validates :notification_level, presence: true validate :namespace_uniq, if: ->(user) { user.username_changed? } validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } validate :unique_email, if: ->(user) { user.email_changed? } @@ -190,6 +191,13 @@ class User < ActiveRecord::Base # Note: When adding an option, it MUST go on the end of the array. enum project_view: [:readme, :activity, :files] + # Notification level + # Note: When adding an option, it MUST go on the end of the array. + # + # TODO: Add '_prefix: :notification' to enum when update to Rails 5. https://github.com/rails/rails/pull/19813 + # Because user.notification_disabled? is much better than user.disabled? + enum notification_level: [:disabled, :participating, :watch, :global, :mention] + alias_attribute :private_token, :authentication_token delegate :path, to: :namespace, allow_nil: true, prefix: true @@ -349,10 +357,6 @@ class User < ActiveRecord::Base "#{self.class.reference_prefix}#{username}" end - def notification - @notification ||= Notification.new(self) - end - def generate_password if self.force_random_password self.password = self.password_confirmation = Devise.friendly_token.first(8) @@ -827,6 +831,10 @@ class User < ActiveRecord::Base end end + def notification_settings_for(source) + notification_settings.find_or_initialize_by(source: source) + end + private def projects_union diff --git a/app/services/notes/delete_service.rb b/app/services/notes/delete_service.rb new file mode 100644 index 00000000000..7f1b30ec84e --- /dev/null +++ b/app/services/notes/delete_service.rb @@ -0,0 +1,8 @@ +module Notes + class DeleteService < BaseService + def execute(note) + note.destroy + note.reset_events_cache + end + end +end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index eff0d96f93d..42ec1ac9e1a 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -253,8 +253,8 @@ class NotificationService def project_watchers(project) project_members = project_member_notification(project) - users_with_project_level_global = project_member_notification(project, Notification::N_GLOBAL) - users_with_group_level_global = group_member_notification(project, Notification::N_GLOBAL) + users_with_project_level_global = project_member_notification(project, :global) + users_with_group_level_global = group_member_notification(project, :global) users = users_with_global_level_watch([users_with_project_level_global, users_with_group_level_global].flatten.uniq) users_with_project_setting = select_project_member_setting(project, users_with_project_level_global, users) @@ -264,18 +264,16 @@ class NotificationService end def project_member_notification(project, notification_level=nil) - project_members = project.project_members - if notification_level - project_members.where(notification_level: notification_level).pluck(:user_id) + project.notification_settings.where(level: NotificationSetting.levels[notification_level]).pluck(:user_id) else - project_members.pluck(:user_id) + project.notification_settings.pluck(:user_id) end end def group_member_notification(project, notification_level) if project.group - project.group.group_members.where(notification_level: notification_level).pluck(:user_id) + project.group.notification_settings.where(level: NotificationSetting.levels[notification_level]).pluck(:user_id) else [] end @@ -284,13 +282,13 @@ class NotificationService def users_with_global_level_watch(ids) User.where( id: ids, - notification_level: Notification::N_WATCH + notification_level: NotificationSetting.levels[:watch] ).pluck(:id) end # Build a list of users based on project notifcation settings def select_project_member_setting(project, global_setting, users_global_level_watch) - users = project_member_notification(project, Notification::N_WATCH) + users = project_member_notification(project, :watch) # If project setting is global, add to watch list if global setting is watch global_setting.each do |user_id| @@ -304,7 +302,7 @@ class NotificationService # Build a list of users based on group notification settings def select_group_member_setting(project, project_members, global_setting, users_global_level_watch) - uids = group_member_notification(project, Notification::N_WATCH) + uids = group_member_notification(project, :watch) # Group setting is watch, add to users list if user is not project member users = [] @@ -331,40 +329,46 @@ class NotificationService # Remove users with disabled notifications from array # Also remove duplications and nil recipients def reject_muted_users(users, project = nil) - reject_users(users, :disabled?, project) + reject_users(users, :disabled, project) end # Remove users with notification level 'Mentioned' def reject_mention_users(users, project = nil) - reject_users(users, :mention?, project) + reject_users(users, :mention, project) end - # Reject users which method_name from notification object returns true. + # Reject users which has certain notification level # # Example: - # reject_users(users, :watch?, project) + # reject_users(users, :watch, project) # - def reject_users(users, method_name, project = nil) + def reject_users(users, level, project = nil) + level = level.to_s + + unless NotificationSetting.levels.keys.include?(level) + raise 'Invalid notification level' + end + users = users.to_a.compact.uniq users = users.reject(&:blocked?) users.reject do |user| - next user.notification.send(method_name) unless project + next user.notification_level == level unless project - member = project.project_members.find_by(user_id: user.id) + setting = user.notification_settings_for(project) - if !member && project.group - member = project.group.group_members.find_by(user_id: user.id) + if !setting && project.group + setting = user.notification_settings_for(project.group) end - # reject users who globally set mention notification and has no membership - next user.notification.send(method_name) unless member + # reject users who globally set mention notification and has no setting per project/group + next user.notification_level == level unless setting # reject users who set mention notification in project - next true if member.notification.send(method_name) + next true if setting.level == level - # reject users who have N_MENTION in project and disabled in global settings - member.notification.global? && user.notification.send(method_name) + # reject users who have mention level in project and disabled in global settings + setting.global? && user.notification_level == level end end diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 0f3b8119379..44339293095 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -45,6 +45,8 @@ %h1.title= title + = yield :header_content + = render 'shared/outdated_browser' - if @project && !@project.empty_repo? diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index a7ef31acd3d..6dfe7fbdae8 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -17,4 +17,12 @@ - content_for :scripts_body do = render "layouts/init_auto_complete" if current_user +- content_for :header_content do + .js-dropdown-menu-projects + .dropdown-menu.dropdown-select.dropdown-menu-projects + = dropdown_title("Go to a project") + = dropdown_filter("Search your projects") + = dropdown_content + = dropdown_loading + = render template: "layouts/application" diff --git a/app/views/profiles/notifications/_group_settings.html.haml b/app/views/profiles/notifications/_group_settings.html.haml new file mode 100644 index 00000000000..89ae7ffda2b --- /dev/null +++ b/app/views/profiles/notifications/_group_settings.html.haml @@ -0,0 +1,13 @@ +%li.notification-list-item + %span.notification.fa.fa-holder.append-right-5 + - if setting.global? + = notification_icon(current_user.notification_level) + - else + = notification_icon(setting.level) + + %span.str-truncated + = link_to group.name, group_path(group) + + .pull-right + = form_for [group, setting], remote: true, html: { class: 'update-notifications' } do |f| + = f.select :level, NotificationSetting.levels.keys, {}, class: 'form-control trigger-submit' diff --git a/app/views/profiles/notifications/_project_settings.html.haml b/app/views/profiles/notifications/_project_settings.html.haml new file mode 100644 index 00000000000..17c097154da --- /dev/null +++ b/app/views/profiles/notifications/_project_settings.html.haml @@ -0,0 +1,13 @@ +%li.notification-list-item + %span.notification.fa.fa-holder.append-right-5 + - if setting.global? + = notification_icon(current_user.notification_level) + - else + = notification_icon(setting.level) + + %span.str-truncated + = link_to_project(project) + + .pull-right + = form_for [project.namespace.becomes(Namespace), project, setting], remote: true, html: { class: 'update-notifications' } do |f| + = f.select :level, NotificationSetting.levels.keys, {}, class: 'form-control trigger-submit' diff --git a/app/views/profiles/notifications/_settings.html.haml b/app/views/profiles/notifications/_settings.html.haml deleted file mode 100644 index d0d044136f6..00000000000 --- a/app/views/profiles/notifications/_settings.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -%li.notification-list-item - %span.notification.fa.fa-holder.append-right-5 - - if notification.global? - = notification_icon(@notification) - - else - = notification_icon(notification) - - %span.str-truncated - - if membership.kind_of? GroupMember - = link_to membership.group.name, membership.group - - else - = link_to_project(membership.project) - .pull-right - = form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do - = hidden_field_tag :notification_type, type, id: dom_id(membership, 'notification_type') - = hidden_field_tag :notification_id, membership.id, id: dom_id(membership, 'notification_id') - = select_tag :notification_level, options_for_select(Notification.options_with_labels, notification.level), class: 'form-control trigger-submit' diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml index 6609295a2a5..a2a505c082b 100644 --- a/app/views/profiles/notifications/show.html.haml +++ b/app/views/profiles/notifications/show.html.haml @@ -1,8 +1,12 @@ - page_title "Notifications" - header_title page_title, profile_notifications_path -= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications prepend-top-default' } do |f| - = form_errors(@user) +%div + - if @user.errors.any? + %div.alert.alert-danger + %ul + - @user.errors.full_messages.each do |msg| + %li= msg = hidden_field_tag :notification_type, 'global' .row @@ -16,56 +20,55 @@ .col-lg-9 %h5 Global notification settings - .form-group - = f.label :notification_email, class: "label-light" - = f.select :notification_email, @user.all_emails, { include_blank: false }, class: "select2" - .form-group - = f.label :notification_level, class: 'label-light' - .radio - = f.label :notification_level, value: Notification::N_DISABLED do - = f.radio_button :notification_level, Notification::N_DISABLED - .level-title - Disabled - %p You will not get any notifications via email - .radio - = f.label :notification_level, value: Notification::N_MENTION do - = f.radio_button :notification_level, Notification::N_MENTION - .level-title - On Mention - %p You will receive notifications only for comments in which you were @mentioned + = form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications prepend-top-default' } do |f| + .form-group + = f.label :notification_email, class: "label-light" + = f.select :notification_email, @user.all_emails, { include_blank: false }, class: "select2" + .form-group + = f.label :notification_level, class: 'label-light' + .radio + = f.label :notification_level, value: :disabled do + = f.radio_button :notification_level, :disabled + .level-title + Disabled + %p You will not get any notifications via email - .radio - = f.label :notification_level, value: Notification::N_PARTICIPATING do - = f.radio_button :notification_level, Notification::N_PARTICIPATING - .level-title - Participating - %p You will only receive notifications from related resources (e.g. from your commits or assigned issues) + .radio + = f.label :notification_level, value: :mention do + = f.radio_button :notification_level, :mention + .level-title + On Mention + %p You will receive notifications only for comments in which you were @mentioned - .radio - = f.label :notification_level, value: Notification::N_WATCH do - = f.radio_button :notification_level, Notification::N_WATCH - .level-title - Watch - %p You will receive notifications for any activity + .radio + = f.label :notification_level, value: :participating do + = f.radio_button :notification_level, :participating + .level-title + Participating + %p You will only receive notifications from related resources (e.g. from your commits or assigned issues) - .prepend-top-default - = f.submit 'Update settings', class: "btn btn-create" + .radio + = f.label :notification_level, value: :watch do + = f.radio_button :notification_level, :watch + .level-title + Watch + %p You will receive notifications for any activity + + .prepend-top-default + = f.submit 'Update settings', class: "btn btn-create" %hr -.col-lg-9.col-lg-push-3 - %h5 - Groups (#{@group_members.count}) - %div - %ul.bordered-list - - @group_members.each do |group_member| - - notification = Notification.new(group_member) - = render 'settings', type: 'group', membership: group_member, notification: notification - %h5 - Projects (#{@project_members.count}) - %p.account-well - To specify the notification level per project of a group you belong to, you need to be a member of the project itself, not only its group. - .append-bottom-default - %ul.bordered-list - - @project_members.each do |project_member| - - notification = Notification.new(project_member) - = render 'settings', type: 'project', membership: project_member, notification: notification + %h5 + Groups (#{@group_notifications.count}) + %div + %ul.bordered-list + - @group_notifications.each do |setting| + = render 'group_settings', setting: setting, group: setting.source + %h5 + Projects (#{@project_notifications.count}) + %p.account-well + To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there. + .append-bottom-default + %ul.bordered-list + - @project_notifications.each do |setting| + = render 'project_settings', setting: setting, project: setting.source diff --git a/app/views/profiles/notifications/update.js.haml b/app/views/profiles/notifications/update.js.haml deleted file mode 100644 index 84c6ab25599..00000000000 --- a/app/views/profiles/notifications/update.js.haml +++ /dev/null @@ -1,6 +0,0 @@ -- if @saved - :plain - new Flash("Notification settings saved", "notice") -- else - :plain - new Flash("Failed to save new settings", "alert") diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/projects/buttons/_notifications.html.haml index a3786c35a1f..c1e3e5b73a2 100644 --- a/app/views/projects/buttons/_notifications.html.haml +++ b/app/views/projects/buttons/_notifications.html.haml @@ -1,20 +1,11 @@ -- case @membership -- when ProjectMember - = form_tag profile_notifications_path, method: :put, remote: true, class: 'inline', id: 'notification-form' do - = hidden_field_tag :notification_type, 'project' - = hidden_field_tag :notification_id, @membership.id - = hidden_field_tag :notification_level +- if @notification_setting + = form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, remote: true, html: { class: 'inline', id: 'notification-form' } do |f| + = f.hidden_field :level %span.dropdown %a.dropdown-new.btn.notifications-btn#notifications-button{href: '#', "data-toggle" => "dropdown"} = icon('bell') - = notification_label(@membership) + = notification_title(@notification_setting.level) = icon('angle-down') %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown - - Notification.project_notification_levels.each do |level| - = notification_list_item(level, @membership) - -- when GroupMember - .btn.disabled.notifications-btn.has-tooltip{title: "To change the notification level, you need to be a member of the project itself, not only its group."} - = icon('bell') - = notification_label(@membership) - = icon('angle-down') + - NotificationSetting.levels.each do |level| + = notification_list_item(level.first, @notification_setting) diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml index 3e4ab09c6d4..1e6724fc92b 100644 --- a/app/views/projects/merge_requests/_form.html.haml +++ b/app/views/projects/merge_requests/_form.html.haml @@ -1,4 +1,4 @@ -= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: 'merge-request-form form-horizontal gfm-form js-requires-input' } do |f| += form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: 'merge-request-form form-horizontal gfm-form js-requires-input js-quick-submit' } do |f| = render 'shared/issuable/form', f: f, issuable: @merge_request :javascript diff --git a/app/views/projects/merge_requests/widget/_show.html.haml b/app/views/projects/merge_requests/widget/_show.html.haml index 92d95358937..3c68d61c4b5 100644 --- a/app/views/projects/merge_requests/widget/_show.html.haml +++ b/app/views/projects/merge_requests/widget/_show.html.haml @@ -8,20 +8,22 @@ = render 'projects/merge_requests/widget/locked' :javascript - var merge_request_widget; var opts = { merge_check_url: "#{merge_check_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", check_enable: #{@merge_request.unchecked? ? "true" : "false"}, ci_status_url: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", gitlab_icon: "#{asset_path 'gitlab_logo.png'}", ci_status: "", - ci_message: "Build {{status}} for \"{{title}}\"", + ci_message: { + normal: "Build {{status}} for \"{{title}}\"", + preparing: "{{status}} build for \"{{title}}\"" + }, ci_enable: #{@project.ci_service ? "true" : "false"}, + ci_title: { + preparing: "{{status}} build", + normal: "Build {{status}}" + }, builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}" }; - if(typeof merge_request_widget === 'undefined') { - merge_request_widget = new MergeRequestWidget(opts); - } else { - merge_request_widget.setOpts(opts); - } + merge_request_widget = new MergeRequestWidget(opts); diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 25233112132..a4c6094c69a 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -19,7 +19,7 @@ - if current_user.can_select_namespace? .input-group-addon = root_url - = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user, display_path: true), {}, {class: 'select2', tabindex: 1} + = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user, display_path: true), {}, {class: 'select2 js-select-namespace', tabindex: 1} .input-group-addon \/ - else diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index 5c42423541e..03a44ca99c0 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -10,12 +10,12 @@ = "#{note.author.to_reference} commented" %a{ href: "##{dom_id(note)}" } = time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago') - - if note_editable?(note) - .note-actions - - access = note.project.team.human_max_access(note.author.id) - - if access - %span.note-role - = access + .note-actions + - access = note.project.team.human_max_access(note.author.id) + - if access + %span.note-role + = access + - if note_editable?(note) = link_to '#', title: 'Edit comment', class: 'note-action-button js-note-edit' do = icon('pencil') = link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'note-action-button js-note-delete danger' do diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml index 7afbaeddee8..0a38327baa2 100644 --- a/app/views/shared/_commit_message_container.html.haml +++ b/app/views/shared/_commit_message_container.html.haml @@ -6,7 +6,7 @@ .commit-message-container .max-width-marker = text_area_tag 'commit_message', - (params[:commit_message] || local_assigns[:text]), + (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder]), class: 'form-control js-commit-message', placeholder: local_assigns[:placeholder], required: true, rows: (local_assigns[:rows] || 3), id: "commit_message-#{nonce}" diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb index 1b445bbbd10..22fe51a4534 100644 --- a/config/initializers/metrics.rb +++ b/config/initializers/metrics.rb @@ -1,4 +1,5 @@ if Gitlab::Metrics.enabled? + require 'pathname' require 'influxdb' require 'connection_pool' require 'method_source' @@ -85,9 +86,6 @@ if Gitlab::Metrics.enabled? config.instrument_instance_methods(const) end - config.instrument_methods(Banzai::ReferenceExtractor) - config.instrument_instance_methods(Banzai::ReferenceExtractor) - config.instrument_methods(Banzai::Renderer) config.instrument_methods(Banzai::Querying) @@ -98,6 +96,17 @@ if Gitlab::Metrics.enabled? config.instrument_methods(Gitlab::ReferenceExtractor) config.instrument_instance_methods(Gitlab::ReferenceExtractor) + + # Instrument all service classes + services = Rails.root.join('app', 'services') + + Dir[services.join('**', '*.rb')].each do |file_path| + path = Pathname.new(file_path).relative_path_from(services) + const = path.to_s.sub('.rb', '').camelize.constantize + + config.instrument_methods(const) + config.instrument_instance_methods(const) + end end GC::Profiler.enable diff --git a/config/routes.rb b/config/routes.rb index 842fbb99843..48601b7567b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -406,6 +406,7 @@ Rails.application.routes.draw do resource :avatar, only: [:destroy] resources :milestones, constraints: { id: /[^\/]+/ }, only: [:index, :show, :update, :new, :create] + resource :notification_setting, only: [:update] end end @@ -607,6 +608,7 @@ Rails.application.routes.draw do resources :forks, only: [:index, :new, :create] resource :import, only: [:new, :create, :show] + resource :notification_setting, only: [:update] resources :refs, only: [] do collection do diff --git a/db/migrate/20160328112808_create_notification_settings.rb b/db/migrate/20160328112808_create_notification_settings.rb new file mode 100644 index 00000000000..4755da8b806 --- /dev/null +++ b/db/migrate/20160328112808_create_notification_settings.rb @@ -0,0 +1,11 @@ +class CreateNotificationSettings < ActiveRecord::Migration + def change + create_table :notification_settings do |t| + t.references :user, null: false + t.references :source, polymorphic: true, null: false + t.integer :level, default: 0, null: false + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20160328115649_migrate_new_notification_setting.rb b/db/migrate/20160328115649_migrate_new_notification_setting.rb new file mode 100644 index 00000000000..0a110869027 --- /dev/null +++ b/db/migrate/20160328115649_migrate_new_notification_setting.rb @@ -0,0 +1,17 @@ +# This migration will create one row of NotificationSetting for each Member row +# It can take long time on big instances. +# +# This migration can be done online but with following effects: +# - during migration some users will receive notifications based on their global settings (project/group settings will be ignored) +# - its possible to get duplicate records for notification settings since we don't create uniq index yet +# +class MigrateNewNotificationSetting < ActiveRecord::Migration + def up + timestamp = Time.now + execute "INSERT INTO notification_settings ( user_id, source_id, source_type, level, created_at, updated_at ) SELECT user_id, source_id, source_type, notification_level, '#{timestamp}', '#{timestamp}' FROM members WHERE user_id IS NOT NULL" + end + + def down + execute "DELETE FROM notification_settings" + end +end diff --git a/db/migrate/20160328121138_add_notification_setting_index.rb b/db/migrate/20160328121138_add_notification_setting_index.rb new file mode 100644 index 00000000000..8aebce0244d --- /dev/null +++ b/db/migrate/20160328121138_add_notification_setting_index.rb @@ -0,0 +1,6 @@ +class AddNotificationSettingIndex < ActiveRecord::Migration + def change + add_index :notification_settings, :user_id + add_index :notification_settings, [:source_id, :source_type] + end +end diff --git a/db/schema.rb b/db/schema.rb index ec235c19131..44482de467e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -637,6 +637,18 @@ ActiveRecord::Schema.define(version: 20160331223143) do add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree + create_table "notification_settings", force: :cascade do |t| + t.integer "user_id", null: false + t.integer "source_id", null: false + t.string "source_type", null: false + t.integer "level", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "notification_settings", ["source_id", "source_type"], name: "index_notification_settings_on_source_id_and_source_type", using: :btree + add_index "notification_settings", ["user_id"], name: "index_notification_settings_on_user_id", using: :btree + create_table "oauth_access_grants", force: :cascade do |t| t.integer "resource_owner_id", null: false t.integer "application_id", null: false diff --git a/doc/api/labels.md b/doc/api/labels.md index 544e898b6aa..3730c07c5a7 100644 --- a/doc/api/labels.md +++ b/doc/api/labels.md @@ -23,42 +23,42 @@ Example response: { "name" : "bug", "color" : "#d9534f", - "description": "Bug reported by user" + "description": "Bug reported by user", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1 }, { "color" : "#d9534f", "name" : "confirmed", - "description": "Confirmed issue" + "description": "Confirmed issue", + "open_issues_count": 2, + "closed_issues_count": 5, + "open_merge_requests_count": 0 }, { "name" : "critical", "color" : "#d9534f", - "description": "Criticalissue. Need fix ASAP" - }, - { - "color" : "#428bca", - "name" : "discussion", - "description": "Issue that needs further discussion" + "description": "Criticalissue. Need fix ASAP", + "open_issues_count": 1, + "closed_issues_count": 3, + "open_merge_requests_count": 1 }, { "name" : "documentation", "color" : "#f0ad4e", - "description": "Issue about documentation" + "description": "Issue about documentation", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 2 }, { "color" : "#5cb85c", "name" : "enhancement", - "description": "Enhancement proposal" - }, - { - "color" : "#428bca", - "name" : "suggestion", - "description": "Suggestion" - }, - { - "color" : "#f0ad4e", - "name" : "support", - "description": "Support issue" + "description": "Enhancement proposal", + "open_issues_count": 1, + "closed_issues_count": 0, + "open_merge_requests_count": 1 } ] ``` diff --git a/doc/api/notes.md b/doc/api/notes.md index d4d63e825ab..2e0936f11b5 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -32,6 +32,7 @@ Parameters: "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:22:45Z", + "updated_at": "2013-10-02T10:22:45Z", "system": true, "upvote": false, "downvote": false, @@ -51,6 +52,7 @@ Parameters: "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T09:56:03Z", + "updated_at": "2013-10-02T09:56:03Z", "system": true, "upvote": false, "downvote": false, @@ -103,6 +105,53 @@ Parameters: - `note_id` (required) - The ID of a note - `body` (required) - The content of a note +### Delete an issue note + +Deletes an existing note of an issue. On success, this API method returns 200 +and the deleted note. If the note does not exist, the API returns 404. + +``` +DELETE /projects/:id/issues/:issue_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a project | +| `issue_id` | integer | yes | The ID of an issue | +| `note_id` | integer | yes | The ID of a note | + +```bash +curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/issues/11/notes/636 +``` + +Example Response: + +```json +{ + "id": 636, + "body": "This is a good idea.", + "attachment": null, + "author": { + "id": 1, + "username": "pipin", + "email": "admin@example.com", + "name": "Pip", + "state": "active", + "created_at": "2013-09-30T13:46:01Z", + "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/pipin" + }, + "created_at": "2016-04-05T22:10:44.164Z", + "system": false, + "noteable_id": 11, + "noteable_type": "Issue", + "upvote": false, + "downvote": false +} +``` + ## Snippets ### List all snippet notes @@ -180,6 +229,53 @@ Parameters: - `note_id` (required) - The ID of a note - `body` (required) - The content of a note +### Delete a snippet note + +Deletes an existing note of a snippet. On success, this API method returns 200 +and the deleted note. If the note does not exist, the API returns 404. + +``` +DELETE /projects/:id/snippets/:snippet_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a project | +| `snippet_id` | integer | yes | The ID of a snippet | +| `note_id` | integer | yes | The ID of a note | + +```bash +curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/snippets/52/notes/1659 +``` + +Example Response: + +```json +{ + "id": 1659, + "body": "This is a good idea.", + "attachment": null, + "author": { + "id": 1, + "username": "pipin", + "email": "admin@example.com", + "name": "Pip", + "state": "active", + "created_at": "2013-09-30T13:46:01Z", + "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/pipin" + }, + "created_at": "2016-04-06T16:51:53.239Z", + "system": false, + "noteable_id": 52, + "noteable_type": "Snippet", + "upvote": false, + "downvote": false +} +``` + ## Merge Requests ### List all merge request notes @@ -223,6 +319,7 @@ Parameters: "created_at": "2013-09-30T13:46:01Z" }, "created_at": "2013-10-02T08:57:14Z", + "updated_at": "2013-10-02T08:57:14Z", "system": false, "upvote": false, "downvote": false, @@ -259,3 +356,50 @@ Parameters: - `merge_request_id` (required) - The ID of a merge request - `note_id` (required) - The ID of a note - `body` (required) - The content of a note + +### Delete a merge request note + +Deletes an existing note of a merge request. On success, this API method returns +200 and the deleted note. If the note does not exist, the API returns 404. + +``` +DELETE /projects/:id/merge_requests/:merge_request_id/notes/:note_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a project | +| `merge_request_id` | integer | yes | The ID of a merge request | +| `note_id` | integer | yes | The ID of a note | + +```bash +curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/merge_requests/7/notes/1602 +``` + +Example Response: + +```json +{ + "id": 1602, + "body": "This is a good idea.", + "attachment": null, + "author": { + "id": 1, + "username": "pipin", + "email": "admin@example.com", + "name": "Pip", + "state": "active", + "created_at": "2013-09-30T13:46:01Z", + "avatar_url": "http://www.gravatar.com/avatar/5224fd70153710e92fb8bcf79ac29d67?s=80&d=identicon", + "web_url": "https://gitlab.example.com/u/pipin" + }, + "created_at": "2016-04-05T22:11:59.923Z", + "system": false, + "noteable_id": 7, + "noteable_type": "MergeRequest", + "upvote": false, + "downvote": false +} +``` diff --git a/doc/api/projects.md b/doc/api/projects.md index 3a909a2bc87..ab716c229dc 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -780,8 +780,10 @@ Parameters: - `id` (required) - The ID or NAMESPACE/PROJECT_NAME of a project - `user_id` (required) - The ID of a team member -This method is idempotent and can be called multiple times with the same parameters. -Revoking team membership for a user who is not currently a team member is considered success. +This method removes the project member if the user has the proper access rights to do so. +It returns a status code 403 if the member does not have the proper rights to perform this action. +In all other cases this method is idempotent and revoking team membership for a user who is not +currently a team member is considered success. Please note that the returned JSON currently differs slightly. Thus you should not rely on the returned JSON structure. diff --git a/doc/api/tags.md b/doc/api/tags.md index 17d12e9cc62..ac9fac92f4c 100644 --- a/doc/api/tags.md +++ b/doc/api/tags.md @@ -38,6 +38,50 @@ Parameters: ] ``` +## Get a single repository tag + +Get a specific repository tag determined by its name. It returns `200` together +with the tag information if the tag exists. It returns `404` if the tag does not +exist. + +``` +GET /projects/:id/repository/tags/:tag_name +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a project | +| `tag_name` | string | yes | The name of the tag | + +```bash +curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/repository/tags/v1.0.0 +``` + +Example Response: + +```json +{ + "name": "v5.0.0", + "message": null, + "commit": { + "id": "60a8ff033665e1207714d6670fcd7b65304ec02f", + "message": "v5.0.0\n", + "parent_ids": [ + "f61c062ff8bcbdb00e0a1b3317a91aed6ceee06b" + ], + "authored_date": "2015-02-01T21:56:31.000+01:00", + "author_name": "Arthur Verschaeve", + "author_email": "contact@arthurverschaeve.be", + "committed_date": "2015-02-01T21:56:31.000+01:00", + "committer_name": "Arthur Verschaeve", + "committer_email": "contact@arthurverschaeve.be" + }, + "release": null +} +``` + ## Create a new tag Creates a new tag in the repository that points to the supplied ref. @@ -148,4 +192,4 @@ Parameters: "tag_name": "1.0.0", "description": "Amazing release. Wow" } -```
\ No newline at end of file +``` diff --git a/features/profile/notifications.feature b/features/profile/notifications.feature index 55997d44dec..ef8743932f5 100644 --- a/features/profile/notifications.feature +++ b/features/profile/notifications.feature @@ -7,3 +7,9 @@ Feature: Profile Notifications Scenario: I visit notifications tab When I visit profile notifications page Then I should see global notifications settings + + @javascript + Scenario: I edit Project Notifications + Given I visit profile notifications page + When I select Mention setting from dropdown + Then I should see Notification saved message diff --git a/features/steps/profile/notifications.rb b/features/steps/profile/notifications.rb index 447ea6d9d10..a96f35ada51 100644 --- a/features/steps/profile/notifications.rb +++ b/features/steps/profile/notifications.rb @@ -9,4 +9,14 @@ class Spinach::Features::ProfileNotifications < Spinach::FeatureSteps step 'I should see global notifications settings' do expect(page).to have_content "Notifications" end + + step 'I select Mention setting from dropdown' do + select 'mention', from: 'notification_setting_level' + end + + step 'I should see Notification saved message' do + page.within '.flash-container' do + expect(page).to have_content 'Notification settings saved' + end + end end diff --git a/fixtures/emojis/digests.json b/fixtures/emojis/digests.json index 18d6e93e0f4..41ca617847e 100644 --- a/fixtures/emojis/digests.json +++ b/fixtures/emojis/digests.json @@ -65,21 +65,41 @@ "digest": "fdddc2cd3618ec6661612581b8b93553cb086b0bb197e96aedf1bee8055e7bb4" }, { + "name": "northeast_pointing_airplane", + "unicode": "1F6EA", + "digest": "fdddc2cd3618ec6661612581b8b93553cb086b0bb197e96aedf1bee8055e7bb4" + }, + { "name": "airplane_small", "unicode": "1F6E9", "digest": "f98b44422d6bf505b50330805ecf68013d035341f0b6487c3c05ad913eb5abd3" }, { + "name": "small_airplane", + "unicode": "1F6E9", + "digest": "f98b44422d6bf505b50330805ecf68013d035341f0b6487c3c05ad913eb5abd3" + }, + { "name": "airplane_small_up", "unicode": "1F6E8", "digest": "029752b29a757c087dec60f45ea242e974fc181129e20390d5d4a2f90442091a" }, { + "name": "up_pointing_small_airplane", + "unicode": "1F6E8", + "digest": "029752b29a757c087dec60f45ea242e974fc181129e20390d5d4a2f90442091a" + }, + { "name": "airplane_up", "unicode": "1F6E7", "digest": "ec45d4dbfce1f75dc59339417b1dcf5f1e1359cd9d04ff233babf359a3330e77" }, { + "name": "up_pointing_airplane", + "unicode": "1F6E7", + "digest": "ec45d4dbfce1f75dc59339417b1dcf5f1e1359cd9d04ff233babf359a3330e77" + }, + { "name": "alarm_clock", "unicode": "23F0", "digest": "84ddd7b3b857c165410b7b44863e5354ca0f3591c3bfe56231f12c9f7531a96f" @@ -150,11 +170,21 @@ "digest": "f2711991e8b386b2d5b12f296ce20a9b4b00ef91d6d67af2cf4e06abf2faa1dc" }, { + "name": "left_anger_bubble", + "unicode": "1F5EE", + "digest": "f2711991e8b386b2d5b12f296ce20a9b4b00ef91d6d67af2cf4e06abf2faa1dc" + }, + { "name": "anger_right", "unicode": "1F5EF", "digest": "24b572d64c519251a3ae8844e8d66fd6955752aff99aebe7dc20179505a466c4" }, { + "name": "right_anger_bubble", + "unicode": "1F5EF", + "digest": "24b572d64c519251a3ae8844e8d66fd6955752aff99aebe7dc20179505a466c4" + }, + { "name": "angry", "unicode": "1F620", "digest": "c4188ba70df99d8ccef5706d711176725d3dd50d62f065a177d68d85c7828107" @@ -305,6 +335,11 @@ "digest": "0b7f27f545b616677c83d40ff957337477b2881459b4d3c839ae55e23797419f" }, { + "name": "keycap_asterisk", + "unicode": "002A-20E3", + "digest": "0b7f27f545b616677c83d40ff957337477b2881459b4d3c839ae55e23797419f" + }, + { "name": "astonished", "unicode": "1F632", "digest": "58632b97e274ade5183752db2b3c5c4fe29effcd5a9720a8d01fa809b97023dc" @@ -325,6 +360,11 @@ "digest": "cbce1725602efbb77a935cfae5407e4d75489ee988910296c7f6140665afc669" }, { + "name": "atom_symbol", + "unicode": "269B", + "digest": "cbce1725602efbb77a935cfae5407e4d75489ee988910296c7f6140665afc669" + }, + { "name": "b", "unicode": "1F171", "digest": "9116256b3189977e37f6da7ddedf82bb29b0358829a4e8718fd59e51d9b86b3c" @@ -400,11 +440,21 @@ "digest": "0455ea75612efe78354315b4c345953d2d559bb471d5b01c1adc1d6b74ed693a" }, { + "name": "ballot_box_with_ballot", + "unicode": "1F5F3", + "digest": "0455ea75612efe78354315b4c345953d2d559bb471d5b01c1adc1d6b74ed693a" + }, + { "name": "ballot_box_check", "unicode": "1F5F9", "digest": "fc3ba16c009d963a4a0ea20a348ac98eee3c4c18c481df19a5ada0d1de7fcc15" }, { + "name": "ballot_box_with_bold_check", + "unicode": "1F5F9", + "digest": "fc3ba16c009d963a4a0ea20a348ac98eee3c4c18c481df19a5ada0d1de7fcc15" + }, + { "name": "ballot_box_with_check", "unicode": "2611", "digest": "5f5cec7fe462557d31e8d2b836534c1e76d546cc0061236fa2af3667972b84aa" @@ -415,11 +465,21 @@ "digest": "861dcfc2361298262587b5d0e163fed96a55c44636361f5b4a9ab1d6502b8928" }, { + "name": "ballot_box_with_script_x", + "unicode": "1F5F5", + "digest": "861dcfc2361298262587b5d0e163fed96a55c44636361f5b4a9ab1d6502b8928" + }, + { "name": "ballot_x", "unicode": "1F5F4", "digest": "0b73b89847eb82bcad5664644c8af237e0aef6c3d8c94b7a5df94e05d0ebf4e1" }, { + "name": "ballot_script_x", + "unicode": "1F5F4", + "digest": "0b73b89847eb82bcad5664644c8af237e0aef6c3d8c94b7a5df94e05d0ebf4e1" + }, + { "name": "bamboo", "unicode": "1F38D", "digest": "feb0cf2f1012a1c0649b8c66f7e96e2d8bcdefe879c5a52dab3e25c51009e3b2" @@ -465,31 +525,61 @@ "digest": "e94beb69f631667479a80095bf313ceb3aa109d6ebb80f182722360a6d2a214e" }, { + "name": "person_with_ball", + "unicode": "26F9", + "digest": "e94beb69f631667479a80095bf313ceb3aa109d6ebb80f182722360a6d2a214e" + }, + { "name": "basketball_player_tone1", "unicode": "26F9-1F3FB", "digest": "6fc77cf2f26ee18e9a3faea500d4277839f77633f31ee618a68c301f1ad32d90" }, { + "name": "person_with_ball_tone1", + "unicode": "26F9-1F3FB", + "digest": "6fc77cf2f26ee18e9a3faea500d4277839f77633f31ee618a68c301f1ad32d90" + }, + { "name": "basketball_player_tone2", "unicode": "26F9-1F3FC", "digest": "6ee9060c24d92708e12a854fb0bdf5c717c90b8c0350d8aa40c278b41bfa12fc" }, { + "name": "person_with_ball_tone2", + "unicode": "26F9-1F3FC", + "digest": "6ee9060c24d92708e12a854fb0bdf5c717c90b8c0350d8aa40c278b41bfa12fc" + }, + { "name": "basketball_player_tone3", "unicode": "26F9-1F3FD", "digest": "752e90dbfa7c7a9ae3f37de924e22f3c3d5a7e54dd41c8e8eb99cabb0dad73cf" }, { + "name": "person_with_ball_tone3", + "unicode": "26F9-1F3FD", + "digest": "752e90dbfa7c7a9ae3f37de924e22f3c3d5a7e54dd41c8e8eb99cabb0dad73cf" + }, + { "name": "basketball_player_tone4", "unicode": "26F9-1F3FE", "digest": "38bedc3074e6243454d568d9b665f5764f1a3d983875651ce7a1cdb53da9f6c8" }, { + "name": "person_with_ball_tone4", + "unicode": "26F9-1F3FE", + "digest": "38bedc3074e6243454d568d9b665f5764f1a3d983875651ce7a1cdb53da9f6c8" + }, + { "name": "basketball_player_tone5", "unicode": "26F9-1F3FF", "digest": "25ee1e84670d3db96d3ad098c859abd6b3448f55f668ce0c195ee2337a215de7" }, { + "name": "person_with_ball_tone5", + "unicode": "26F9-1F3FF", + "digest": "25ee1e84670d3db96d3ad098c859abd6b3448f55f668ce0c195ee2337a215de7" + }, + { "name": "bath", "unicode": "1F6C0", "digest": "ae6301a6354630cd9dc06a5137f23f826d019c8298b2b012b6ff31b773a910b6" @@ -535,11 +625,21 @@ "digest": "52855d75cfa4476ccc23c58b4afcb76ee48abb22a9a6081210c8accefdf33099" }, { + "name": "beach_with_umbrella", + "unicode": "1F3D6", + "digest": "52855d75cfa4476ccc23c58b4afcb76ee48abb22a9a6081210c8accefdf33099" + }, + { "name": "beach_umbrella", "unicode": "26F1", "digest": "cefe8e195d21d3e0769d3bfe15170db9e57c86db9d31cacb19fcdc8d2191b661" }, { + "name": "umbrella_on_ground", + "unicode": "26F1", + "digest": "cefe8e195d21d3e0769d3bfe15170db9e57c86db9d31cacb19fcdc8d2191b661" + }, + { "name": "bear", "unicode": "1F43B", "digest": "b5ac126875c20c82b9e3140b143233944a2e4132d781d0b575e83673988523cb" @@ -585,6 +685,11 @@ "digest": "c15455f1b52ac26404b5c13a0e1070212ed1830026422873f4f6335e26e31259" }, { + "name": "bellhop_bell", + "unicode": "1F6CE", + "digest": "c15455f1b52ac26404b5c13a0e1070212ed1830026422873f4f6335e26e31259" + }, + { "name": "bento", "unicode": "1F371", "digest": "d59314b17a8646d4a78fefb7b79f289f33d4aaea893fed4cad0b890df63395e7" @@ -635,6 +740,11 @@ "digest": "81f8309318051255ed4dc18855a3cd3f8657a6f3b2d368caa531a57ce0e34235" }, { + "name": "biohazard_sign", + "unicode": "2623", + "digest": "81f8309318051255ed4dc18855a3cd3f8657a6f3b2d368caa531a57ce0e34235" + }, + { "name": "bird", "unicode": "1F426", "digest": "3f219e5aa18e2f1febfd368ec133786cd2eab357db79984cb8ba07fed0eec7cd" @@ -770,6 +880,11 @@ "digest": "1643ec51ff26fc1ac0c67859e202386398650bf2a996c82b68e1b73fa52abf7d" }, { + "name": "bouquet_of_flowers", + "unicode": "1F395", + "digest": "1643ec51ff26fc1ac0c67859e202386398650bf2a996c82b68e1b73fa52abf7d" + }, + { "name": "bow", "unicode": "1F647", "digest": "5e260c38cfc80cd2f20ef78d982126dbf90934f7afa12c96d0b7b413beb6d4e0" @@ -780,6 +895,11 @@ "digest": "1c23469256331ea4ff03c036f89f0e63ad3228c51faecba50129da99b7eaddf3" }, { + "name": "archery", + "unicode": "1F3F9", + "digest": "1c23469256331ea4ff03c036f89f0e63ad3228c51faecba50129da99b7eaddf3" + }, + { "name": "bow_tone1", "unicode": "1F647-1F3FB", "digest": "d3ec7ef70b355ba310d6fae7130a4e4cd11526b6e219474b5678a2b3ba1077f0" @@ -925,6 +1045,11 @@ "digest": "92493636cf086205d1e12cc19e613b84152ef10b8cd0215619a0fc813bfc9a7c" }, { + "name": "bullhorn_with_sound_waves", + "unicode": "1F56C", + "digest": "92493636cf086205d1e12cc19e613b84152ef10b8cd0215619a0fc813bfc9a7c" + }, + { "name": "burrito", "unicode": "1F32F", "digest": "4babb1af1136ab2334d26495b0be779d0bcc9516fd956fc07ffde427d11122f0" @@ -965,6 +1090,11 @@ "digest": "01b47b5c69c12b65fa4f4c0d580f2a98280d6116f4ad2cf8be378759008bcc3c" }, { + "name": "pocket calculator", + "unicode": "1F5A9", + "digest": "01b47b5c69c12b65fa4f4c0d580f2a98280d6116f4ad2cf8be378759008bcc3c" + }, + { "name": "calendar", "unicode": "1F4C6", "digest": "00bb700dd88efbc43bc64263491cdf77965130b1dc23f31e682905c3dfe4040c" @@ -975,6 +1105,11 @@ "digest": "1dd5da98bb435c0c3f632bc0a5c9fdde694de7aee752bf4bb85def086e788a2a" }, { + "name": "spiral_calendar_pad", + "unicode": "1F5D3", + "digest": "1dd5da98bb435c0c3f632bc0a5c9fdde694de7aee752bf4bb85def086e788a2a" + }, + { "name": "calling", "unicode": "1F4F2", "digest": "2375828085f2efd17b8a5ebb3cfec1e420190913328a7a0dd9ff0f67c7249ffb" @@ -1035,6 +1170,11 @@ "digest": "7d760ae1d44e6f4b2aac00895ca86b5743f8b5ca157ec2bd21ce2665e50ad23a" }, { + "name": "card_file_box", + "unicode": "1F5C3", + "digest": "7d760ae1d44e6f4b2aac00895ca86b5743f8b5ca157ec2bd21ce2665e50ad23a" + }, + { "name": "card_index", "unicode": "1F4C7", "digest": "150950903eccb468981c58b87ed7c1ba44e17f52627d695f660ce96b3d9d6e8e" @@ -1050,6 +1190,11 @@ "digest": "0b1625eea118060b51a70905c1eb3313ed632e989f70943eca16aa29fe8a34f2" }, { + "name": "tape_cartridge", + "unicode": "1F5AD", + "digest": "0b1625eea118060b51a70905c1eb3313ed632e989f70943eca16aa29fe8a34f2" + }, + { "name": "cat", "unicode": "1F431", "digest": "002208c0c9165971853ee05cd05513175a913376a462a345a939d73401c6acb7" @@ -1080,6 +1225,11 @@ "digest": "77395d3afe5cc10bfdc381120bae2ae4aefdaa96c529536413873a696c5fa713" }, { + "name": "bottle_with_popping_cork", + "unicode": "1F37E", + "digest": "77395d3afe5cc10bfdc381120bae2ae4aefdaa96c529536413873a696c5fa713" + }, + { "name": "chart", "unicode": "1F4B9", "digest": "9fd5f8cd99988bbe0fabc89a0b23e28d1468641d2f9468e82b7148a1948d8236" @@ -1105,6 +1255,11 @@ "digest": "5897036ba97b557868bb314fcee83b9d8a609c8447b270a0b3d34a29ce7496d1" }, { + "name": "cheese_wedge", + "unicode": "1F9C0", + "digest": "5897036ba97b557868bb314fcee83b9d8a609c8447b270a0b3d34a29ce7496d1" + }, + { "name": "cherries", "unicode": "1F352", "digest": "5a0ba73039e4b56e3d16a1c70ad992f41af7a16f6d5ba4b5337bdf338276f0ff" @@ -1170,6 +1325,11 @@ "digest": "c2530d12204eb518c5a3c8d7deba11170b1412fdf406aea05a69d4c026210d1b" }, { + "name": "city_sunrise", + "unicode": "1F307", + "digest": "c2530d12204eb518c5a3c8d7deba11170b1412fdf406aea05a69d4c026210d1b" + }, + { "name": "cityscape", "unicode": "1F3D9", "digest": "15251a708d50fc721bd67d8abb2a517c0bade196df3b736e21d79191d749241f" @@ -1230,6 +1390,11 @@ "digest": "c48314ccde8bf01acc2b1bc9a6b5aa7d796fc0c8769f80398bc74545fcef31ed" }, { + "name": "mantlepiece_clock", + "unicode": "1F570", + "digest": "c48314ccde8bf01acc2b1bc9a6b5aa7d796fc0c8769f80398bc74545fcef31ed" + }, + { "name": "clock1", "unicode": "1F550", "digest": "c0550fa0c385920cbdb775bdaaa5e812097a484c4a32e35ebbafe3a364a4a438" @@ -1355,6 +1520,11 @@ "digest": "67027b7e1a4d800a3ce7d731c21c098d1109d217159a27665eebb7e080fc2622" }, { + "name": "clockwise_right_and_left_semicircle_arrows", + "unicode": "1F5D8", + "digest": "67027b7e1a4d800a3ce7d731c21c098d1109d217159a27665eebb7e080fc2622" + }, + { "name": "closed_book", "unicode": "1F4D5", "digest": "afd6dae5fa0f59330fc2adb922e92b3410a33a80a2667651718c7dac588010bc" @@ -1380,21 +1550,41 @@ "digest": "fc9c85cc95f9c456635692c974f72b6d40e14943824b8129a21c47265c3416f4" }, { + "name": "cloud_with_lightning", + "unicode": "1F329", + "digest": "fc9c85cc95f9c456635692c974f72b6d40e14943824b8129a21c47265c3416f4" + }, + { "name": "cloud_rain", "unicode": "1F327", "digest": "f4406e62ed98f6141ab70736f6d5c540023e805396db0346ee6b7082c3f5e8e2" }, { + "name": "cloud_with_rain", + "unicode": "1F327", + "digest": "f4406e62ed98f6141ab70736f6d5c540023e805396db0346ee6b7082c3f5e8e2" + }, + { "name": "cloud_snow", "unicode": "1F328", "digest": "948990cd13dd927917208c026089519fcf8e258a8a284684ace67c9a2f9a8149" }, { + "name": "cloud_with_snow", + "unicode": "1F328", + "digest": "948990cd13dd927917208c026089519fcf8e258a8a284684ace67c9a2f9a8149" + }, + { "name": "cloud_tornado", "unicode": "1F32A", "digest": "44753516d0bd05d47cfa6eb922aba570ba6a87f805f325772b2cff071460ead1" }, { + "name": "cloud_with_tornado", + "unicode": "1F32A", + "digest": "44753516d0bd05d47cfa6eb922aba570ba6a87f805f325772b2cff071460ead1" + }, + { "name": "clubs", "unicode": "2663", "digest": "5fd19fadd3b0887a6a59819ffbbe33a061055c043200700c31be30e14a5d36d5" @@ -1440,6 +1630,11 @@ "digest": "b27c30d74f205a8a3bd00a55ca17da7cf6ae3b65ae33e949755a4c6bd69a9fd3" }, { + "name": "old_personal_computer", + "unicode": "1F5B3", + "digest": "b27c30d74f205a8a3bd00a55ca17da7cf6ae3b65ae33e949755a4c6bd69a9fd3" + }, + { "name": "confetti_ball", "unicode": "1F38A", "digest": "e77d0c0970d3d12e123e548639fc0fa3ce41668667e4be55baefc09dfaa22cb0" @@ -1510,6 +1705,11 @@ "digest": "0ff52e6adf1927d356b27be5fef6bad2ad842be05e3a0bd16a17efe78e5676d9" }, { + "name": "building_construction", + "unicode": "1F3D7", + "digest": "0ff52e6adf1927d356b27be5fef6bad2ad842be05e3a0bd16a17efe78e5676d9" + }, + { "name": "convenience_store", "unicode": "1F3EA", "digest": "1ff4351e4a4503f58ed5d35074a2112c681337e35ffe55332187481685573606" @@ -1570,6 +1770,11 @@ "digest": "a93fffed194b404200495abda8772bb35539cfc8499eb0a9bf09c508afad6676" }, { + "name": "couch_and_lamp", + "unicode": "1F6CB", + "digest": "a93fffed194b404200495abda8772bb35539cfc8499eb0a9bf09c508afad6676" + }, + { "name": "couple", "unicode": "1F46B", "digest": "97fe611a613216a1788f9bd88a9deb4714ee123a66b5fd3d0ac916fbb4da7304" @@ -1580,6 +1785,11 @@ "digest": "3ae6fbf3ba168256ea85c756ac1e7b83fdb8b780d33f06128ed80706ff627eea" }, { + "name": "couple_with_heart_mm", + "unicode": "1F468-2764-1F468", + "digest": "3ae6fbf3ba168256ea85c756ac1e7b83fdb8b780d33f06128ed80706ff627eea" + }, + { "name": "couple_with_heart", "unicode": "1F491", "digest": "d9701173a5e8dff052ab6a15a42494dbb61dc7146d3734c82916abc9c05f76db" @@ -1590,6 +1800,11 @@ "digest": "d2a2ec29c1a1234ea0aa1d9fc6707cf8be8bb36ea8b92523ffa1c3071bcf0b06" }, { + "name": "couple_with_heart_ww", + "unicode": "1F469-2764-1F469", + "digest": "d2a2ec29c1a1234ea0aa1d9fc6707cf8be8bb36ea8b92523ffa1c3071bcf0b06" + }, + { "name": "couplekiss", "unicode": "1F48F", "digest": "e722730de82397da7c8f88d79319b391e8f01fbe4a9133850cc92ad34e77bd82" @@ -1615,6 +1830,11 @@ "digest": "0f3351c2e68a8d47d27b45a9901be6160de0f9a291bd8680df84d0fc679bcb31" }, { + "name": "lower_left_crayon", + "unicode": "1F58D", + "digest": "0f3351c2e68a8d47d27b45a9901be6160de0f9a291bd8680df84d0fc679bcb31" + }, + { "name": "credit_card", "unicode": "1F4B3", "digest": "708c0e7008e06e5d1b3b4e68a7e0ada9f4ae22ab6c28285d81a340f913fd9a84" @@ -1630,6 +1850,11 @@ "digest": "00eb11254e887c71db5e8945ad211e9e0280f1e02f4b77a4799b64bba2bbe9b3" }, { + "name": "cricket_bat_ball", + "unicode": "1F3CF", + "digest": "00eb11254e887c71db5e8945ad211e9e0280f1e02f4b77a4799b64bba2bbe9b3" + }, + { "name": "crocodile", "unicode": "1F40A", "digest": "99abcb42264d40d2450aaca8c3759a019bfd600a311cf3027243f1ca200d4639" @@ -1640,21 +1865,41 @@ "digest": "a6e3c345cf6aa2ce690b66454066b53ef5b1dab2ed635e21f1586b1dffc5df42" }, { + "name": "latin_cross", + "unicode": "271D", + "digest": "a6e3c345cf6aa2ce690b66454066b53ef5b1dab2ed635e21f1586b1dffc5df42" + }, + { "name": "cross_heavy", "unicode": "1F547", "digest": "2e37c26b9bad0beb019c7f3e7a3892352d0ad9ca1b90c4333d42e8d56680be70" }, { + "name": "heavy_latin_cross", + "unicode": "1F547", + "digest": "2e37c26b9bad0beb019c7f3e7a3892352d0ad9ca1b90c4333d42e8d56680be70" + }, + { "name": "cross_white", "unicode": "1F546", "digest": "3452e667010d7e49a51d7e1f4ba8ed4f303e33ed43255a051e9a18832a1efba6" }, { + "name": "white_latin_cross", + "unicode": "1F546", + "digest": "3452e667010d7e49a51d7e1f4ba8ed4f303e33ed43255a051e9a18832a1efba6" + }, + { "name": "crossbones", "unicode": "1F571", "digest": "f5e7ce293c1a3282711073e68f033a3876e8428d1218cb2f8294630f9124e584" }, { + "name": "black_skull_and_crossbones", + "unicode": "1F571", + "digest": "f5e7ce293c1a3282711073e68f033a3876e8428d1218cb2f8294630f9124e584" + }, + { "name": "crossed_flags", "unicode": "1F38C", "digest": "d4da057db289bec83f0106a94c89bd0cd9b52c7c7f8bc69bc8cbce480d53e12b" @@ -1675,6 +1920,11 @@ "digest": "90519c46ddfb63e71bc76661953da9041e5f0b97e9f8a7a8696518b4d529f3dd" }, { + "name": "passenger_ship", + "unicode": "1F6F3", + "digest": "90519c46ddfb63e71bc76661953da9041e5f0b97e9f8a7a8696518b4d529f3dd" + }, + { "name": "cry", "unicode": "1F622", "digest": "2d6a096796222c29b050f74db6b5aff9b9f61390c5eb56e45d1801918751002f" @@ -1730,6 +1980,11 @@ "digest": "377060a7ce930566a4732b361be98e8a193a546846dfbba2a00abeeef41d1976" }, { + "name": "dagger_knife", + "unicode": "1F5E1", + "digest": "377060a7ce930566a4732b361be98e8a193a546846dfbba2a00abeeef41d1976" + }, + { "name": "dancer", "unicode": "1F483", "digest": "e050db55afbb968e02219a58c7e82b824848d299a4df64f0d08d4e1872816203" @@ -1815,6 +2070,11 @@ "digest": "ba46323e695918e7253f1013cb991efb09790581c74c07c38bc5e10a20b8e8de" }, { + "name": "desktop_computer", + "unicode": "1F5A5", + "digest": "ba46323e695918e7253f1013cb991efb09790581c74c07c38bc5e10a20b8e8de" + }, + { "name": "desktop_window", "unicode": "1F5D4", "digest": "d5b6c4a847e2a96f97f50fd353a22cb121915cb1d7bbc0f02df38769819b6b7e" @@ -1845,6 +2105,11 @@ "digest": "bf4c303452a4c0b4986925041dbec5b7e478060d560630b7c5bc2f997fcad668" }, { + "name": "card_index_dividers", + "unicode": "1F5C2", + "digest": "bf4c303452a4c0b4986925041dbec5b7e478060d560630b7c5bc2f997fcad668" + }, + { "name": "dizzy", "unicode": "1F4AB", "digest": "d6fba9b906f0eabd46686e416273a2ca6634249374385f2abf7ed284f0eef995" @@ -1870,6 +2135,11 @@ "digest": "29407b12409c9673f3d89ef1f86ee50cbc7ed53b1870e33b4a29bbc609017f72" }, { + "name": "document_with_text", + "unicode": "1F5B9", + "digest": "29407b12409c9673f3d89ef1f86ee50cbc7ed53b1870e33b4a29bbc609017f72" + }, + { "name": "dog", "unicode": "1F436", "digest": "c7b729de8a0967b1f38c3fa5ded94e77e329588caeaaf43abfd1090f420e62bf" @@ -1910,6 +2180,11 @@ "digest": "4e2e9c47e5632efe6ccf945d61dbc2f1155a2e52905e17f307b502a2c951bdb8" }, { + "name": "dove_of_peace", + "unicode": "1F54A", + "digest": "4e2e9c47e5632efe6ccf945d61dbc2f1155a2e52905e17f307b502a2c951bdb8" + }, + { "name": "dragon", "unicode": "1F409", "digest": "d7d016568b54d67017681a075fb799d4a2a790ecfa2946d02dbcee629eb4975d" @@ -1945,6 +2220,11 @@ "digest": "12135310cfedc091d120426f5b132df82b538c5fcad458bf6b21588f353c3adb" }, { + "name": "email", + "unicode": "1F4E7", + "digest": "12135310cfedc091d120426f5b132df82b538c5fcad458bf6b21588f353c3adb" + }, + { "name": "ear", "unicode": "1F442", "digest": "70ba1103a34e68590d91a3b6f8acdbad3b1c65e46e31e26ee1cb855c1e21095e" @@ -2045,21 +2325,41 @@ "digest": "bc60b6d375feee00758a94a05b42eeb165f4084b20eb3e6012b72faa221f7e75" }, { + "name": "back_of_envelope", + "unicode": "1F582", + "digest": "bc60b6d375feee00758a94a05b42eeb165f4084b20eb3e6012b72faa221f7e75" + }, + { "name": "envelope_flying", "unicode": "1F585", "digest": "9d6b6ca4c08006062a6f11948de3e15b13cf5c458967e39a9358665a8e13e214" }, { + "name": "flying_envelope", + "unicode": "1F585", + "digest": "9d6b6ca4c08006062a6f11948de3e15b13cf5c458967e39a9358665a8e13e214" + }, + { "name": "envelope_stamped", "unicode": "1F583", "digest": "f6102aea7283ddc136bfeb09589573420b9279105045fc6b965c1633c1297468" }, { + "name": "stamped_envelope", + "unicode": "1F583", + "digest": "f6102aea7283ddc136bfeb09589573420b9279105045fc6b965c1633c1297468" + }, + { "name": "envelope_stamped_pen", "unicode": "1F586", "digest": "80ea471318d1e04f8e525ff236b3cd4a4c864e66c6246b6aad77d92f56895f33" }, { + "name": "pen_over_stamped_envelope", + "unicode": "1F586", + "digest": "80ea471318d1e04f8e525ff236b3cd4a4c864e66c6246b6aad77d92f56895f33" + }, + { "name": "envelope_with_arrow", "unicode": "1F4E9", "digest": "c1ba19b5e7cf64c547ac46eee139e6af70700d49ab511a96e6828c30feb116bc" @@ -2255,31 +2555,61 @@ "digest": "0c542ac3141e8f2e74767acd0eb399c2d68c779cb78bf16d437ad3b1f8134ad9" }, { + "name": "white_down_pointing_left_hand_index", + "unicode": "1F597", + "digest": "0c542ac3141e8f2e74767acd0eb399c2d68c779cb78bf16d437ad3b1f8134ad9" + }, + { "name": "finger_pointing_down2", "unicode": "1F59F", "digest": "c5b128a232cbf518544802a2ae1459368274297163721fa05d0103cf95b2b1ee" }, { + "name": "sideways_white_down_pointing_index", + "unicode": "1F59F", + "digest": "c5b128a232cbf518544802a2ae1459368274297163721fa05d0103cf95b2b1ee" + }, + { "name": "finger_pointing_left", "unicode": "1F598", "digest": "d178ece691e2091be08db77fda9cf05462934628557358a8cb6222587b291f7e" }, { + "name": "sideways_white_left_pointing_index", + "unicode": "1F598", + "digest": "d178ece691e2091be08db77fda9cf05462934628557358a8cb6222587b291f7e" + }, + { "name": "finger_pointing_right", "unicode": "1F599", "digest": "a412a47544d8f401f9181f8826c5fa3d6b42a1d76f6926963c2d9cd2a01be06d" }, { + "name": "sideways_white_right_pointing_index", + "unicode": "1F599", + "digest": "a412a47544d8f401f9181f8826c5fa3d6b42a1d76f6926963c2d9cd2a01be06d" + }, + { "name": "finger_pointing_up", "unicode": "1F59E", "digest": "32c2ccab52aa318a47c816d1bcf9c076e667c9ef3e64ce37d7ba7e827238690d" }, { + "name": "sideways_white_up_pointing_index", + "unicode": "1F59E", + "digest": "32c2ccab52aa318a47c816d1bcf9c076e667c9ef3e64ce37d7ba7e827238690d" + }, + { "name": "fire", "unicode": "1F525", "digest": "b44311874681135acbb5e7226febe4365c732da3a9617f10d7074a3b1ade1641" }, { + "name": "flame", + "unicode": "1F525", + "digest": "b44311874681135acbb5e7226febe4365c732da3a9617f10d7074a3b1ade1641" + }, + { "name": "fire_engine", "unicode": "1F692", "digest": "3ae03fa34a7088ada95458eb4ee3e97691b3489149f6bbc168086f0483ed3bb2" @@ -2290,6 +2620,11 @@ "digest": "e2482c450136d373f74dfafddf502e0b675eb5d2e1e1c645f163db0e4d15fbb6" }, { + "name": "oncoming_fire_engine", + "unicode": "1F6F1", + "digest": "e2482c450136d373f74dfafddf502e0b675eb5d2e1e1c645f163db0e4d15fbb6" + }, + { "name": "fireworks", "unicode": "1F386", "digest": "3dee83a27c406960253ca1460eb88a599c7b81506051b69605a421b17fe8282c" @@ -2360,1296 +2695,2596 @@ "digest": "d9db1edeb709824a1083c2bba79ca5f683ed0edded35918bb167d1ee7396c8da" }, { + "name": "ac", + "unicode": "1F1E6-1F1E8", + "digest": "d9db1edeb709824a1083c2bba79ca5f683ed0edded35918bb167d1ee7396c8da" + }, + { "name": "flag_ad", "unicode": "1F1E6-1F1E9", "digest": "04a8c1745d9b8b20e903302379f2557e8082f72e33878db4cb2cd6b33eb97952" }, { + "name": "ad", + "unicode": "1F1E6-1F1E9", + "digest": "04a8c1745d9b8b20e903302379f2557e8082f72e33878db4cb2cd6b33eb97952" + }, + { "name": "flag_ae", "unicode": "1F1E6-1F1EA", "digest": "868324ac2e7bea1547f5de95f39633b77b8d62f3b3433b3d1a4ee96d169a09cd" }, { + "name": "ae", + "unicode": "1F1E6-1F1EA", + "digest": "868324ac2e7bea1547f5de95f39633b77b8d62f3b3433b3d1a4ee96d169a09cd" + }, + { "name": "flag_af", "unicode": "1F1E6-1F1EB", "digest": "9a94458519e9db5d6cf1557e54fdf62d7e48aaf7de25744a093ec8f284656226" }, { + "name": "af", + "unicode": "1F1E6-1F1EB", + "digest": "9a94458519e9db5d6cf1557e54fdf62d7e48aaf7de25744a093ec8f284656226" + }, + { "name": "flag_ag", "unicode": "1F1E6-1F1EC", "digest": "ea59fabc2bd9024df06a59a34412f52bebfeb03eb6abd73d8fe153e3a68e28f4" }, { + "name": "ag", + "unicode": "1F1E6-1F1EC", + "digest": "ea59fabc2bd9024df06a59a34412f52bebfeb03eb6abd73d8fe153e3a68e28f4" + }, + { "name": "flag_ai", "unicode": "1F1E6-1F1EE", "digest": "75676ded736ad2ebb921e9fd8ebfef49819a35c3dcf005bbc3b7e8c6e75178f2" }, { + "name": "ai", + "unicode": "1F1E6-1F1EE", + "digest": "75676ded736ad2ebb921e9fd8ebfef49819a35c3dcf005bbc3b7e8c6e75178f2" + }, + { "name": "flag_al", "unicode": "1F1E6-1F1F1", "digest": "77b835dcff399b609e2479cbf10f08344c8fc277370ba8e4540165ca15563847" }, { + "name": "al", + "unicode": "1F1E6-1F1F1", + "digest": "77b835dcff399b609e2479cbf10f08344c8fc277370ba8e4540165ca15563847" + }, + { "name": "flag_am", "unicode": "1F1E6-1F1F2", "digest": "3b820c628dd5a93137f7288a43553778f60b0beea4c0a239d063893c0723e73d" }, { + "name": "am", + "unicode": "1F1E6-1F1F2", + "digest": "3b820c628dd5a93137f7288a43553778f60b0beea4c0a239d063893c0723e73d" + }, + { "name": "flag_ao", "unicode": "1F1E6-1F1F4", "digest": "d26439d4ecbe8b67bb1ae9753454505358ebb6b802624f19800471e53ee27187" }, { + "name": "ao", + "unicode": "1F1E6-1F1F4", + "digest": "d26439d4ecbe8b67bb1ae9753454505358ebb6b802624f19800471e53ee27187" + }, + { "name": "flag_aq", "unicode": "1F1E6-1F1F6", "digest": "6b0b4e800d88ab289ae4b6d449bfa115e92543958b477d13ad348468a74e4616" }, { + "name": "aq", + "unicode": "1F1E6-1F1F6", + "digest": "6b0b4e800d88ab289ae4b6d449bfa115e92543958b477d13ad348468a74e4616" + }, + { "name": "flag_ar", "unicode": "1F1E6-1F1F7", "digest": "ca76db601dd3f5794f1caace8ab5641fe3786b86e4ae030706162f0ce07d27b3" }, { + "name": "ar", + "unicode": "1F1E6-1F1F7", + "digest": "ca76db601dd3f5794f1caace8ab5641fe3786b86e4ae030706162f0ce07d27b3" + }, + { "name": "flag_as", "unicode": "1F1E6-1F1F8", "digest": "170e1dde0e3fd2e0f2149de5cc8845e15580cc0412e81a643d61bd387de16141" }, { + "name": "as", + "unicode": "1F1E6-1F1F8", + "digest": "170e1dde0e3fd2e0f2149de5cc8845e15580cc0412e81a643d61bd387de16141" + }, + { "name": "flag_at", "unicode": "1F1E6-1F1F9", "digest": "0ab3675a16b4988e87c81e87453c160d6616c7be76247f54c471dc63aa8b42ba" }, { + "name": "at", + "unicode": "1F1E6-1F1F9", + "digest": "0ab3675a16b4988e87c81e87453c160d6616c7be76247f54c471dc63aa8b42ba" + }, + { "name": "flag_au", "unicode": "1F1E6-1F1FA", "digest": "b6f17d3dfd3547c069a0b6cddd4cf44fb8ce1d1d300e24284fb292ac142537e3" }, { + "name": "au", + "unicode": "1F1E6-1F1FA", + "digest": "b6f17d3dfd3547c069a0b6cddd4cf44fb8ce1d1d300e24284fb292ac142537e3" + }, + { "name": "flag_aw", "unicode": "1F1E6-1F1FC", "digest": "7857bc907f04dfb7ccc4401c05034ad8afb6383a022db77973cfcafa4d6c16c8" }, { + "name": "aw", + "unicode": "1F1E6-1F1FC", + "digest": "7857bc907f04dfb7ccc4401c05034ad8afb6383a022db77973cfcafa4d6c16c8" + }, + { "name": "flag_ax", "unicode": "1F1E6-1F1FD", "digest": "ab8f1fd4af7c220a54d478cec5a9f7f3beb5fc83439c448f3ac9848af8391ac1" }, { + "name": "ax", + "unicode": "1F1E6-1F1FD", + "digest": "ab8f1fd4af7c220a54d478cec5a9f7f3beb5fc83439c448f3ac9848af8391ac1" + }, + { "name": "flag_az", "unicode": "1F1E6-1F1FF", "digest": "187cc7b6d39800c5910a34409db1e6b1d8aac808c72a93e922a419d9b054fd0b" }, { + "name": "az", + "unicode": "1F1E6-1F1FF", + "digest": "187cc7b6d39800c5910a34409db1e6b1d8aac808c72a93e922a419d9b054fd0b" + }, + { "name": "flag_ba", "unicode": "1F1E7-1F1E6", "digest": "cd22c744213087384cf79ed314742026787212c9ceb6999ed166534670f7864a" }, { + "name": "ba", + "unicode": "1F1E7-1F1E6", + "digest": "cd22c744213087384cf79ed314742026787212c9ceb6999ed166534670f7864a" + }, + { "name": "flag_bb", "unicode": "1F1E7-1F1E7", "digest": "44ff0a48ac2d2180374baa58b1b7c64f26d0d151a48811eb08ffa20758104512" }, { + "name": "bb", + "unicode": "1F1E7-1F1E7", + "digest": "44ff0a48ac2d2180374baa58b1b7c64f26d0d151a48811eb08ffa20758104512" + }, + { "name": "flag_bd", "unicode": "1F1E7-1F1E9", "digest": "c18793d2b963458607a0bab94c57e62c8278fce870e96fd8dda78067a8fbde18" }, { + "name": "bd", + "unicode": "1F1E7-1F1E9", + "digest": "c18793d2b963458607a0bab94c57e62c8278fce870e96fd8dda78067a8fbde18" + }, + { "name": "flag_be", "unicode": "1F1E7-1F1EA", "digest": "6e6ccfca064a43b93c8acc04a9425f95af204198022ca20b9ee6c491e99ad950" }, { + "name": "be", + "unicode": "1F1E7-1F1EA", + "digest": "6e6ccfca064a43b93c8acc04a9425f95af204198022ca20b9ee6c491e99ad950" + }, + { "name": "flag_bf", "unicode": "1F1E7-1F1EB", "digest": "d69c0394a1c7cb6323f54f024b7d740c728f229ca5e1b54ac374d5024f5470a5" }, { + "name": "bf", + "unicode": "1F1E7-1F1EB", + "digest": "d69c0394a1c7cb6323f54f024b7d740c728f229ca5e1b54ac374d5024f5470a5" + }, + { "name": "flag_bg", "unicode": "1F1E7-1F1EC", "digest": "413a270caf4a9155e84bdba6c9512277f5642246f6ba8d701383a5eeb02f7e95" }, { + "name": "bg", + "unicode": "1F1E7-1F1EC", + "digest": "413a270caf4a9155e84bdba6c9512277f5642246f6ba8d701383a5eeb02f7e95" + }, + { "name": "flag_bh", "unicode": "1F1E7-1F1ED", "digest": "9243ed65d7f24c824c2a3207335a2d4ad25251258547c16d0b7b7cbb9df6f8de" }, { + "name": "bh", + "unicode": "1F1E7-1F1ED", + "digest": "9243ed65d7f24c824c2a3207335a2d4ad25251258547c16d0b7b7cbb9df6f8de" + }, + { "name": "flag_bi", "unicode": "1F1E7-1F1EE", "digest": "63056519030524b2d2dcd47448267d817205dbd6b98075c97f011a8f1d4d1a4b" }, { + "name": "bi", + "unicode": "1F1E7-1F1EE", + "digest": "63056519030524b2d2dcd47448267d817205dbd6b98075c97f011a8f1d4d1a4b" + }, + { "name": "flag_bj", "unicode": "1F1E7-1F1EF", "digest": "93b245eed85d22260d27d1a8c77f51fb3439309e09b2aeca6cd504dbea77b509" }, { + "name": "bj", + "unicode": "1F1E7-1F1EF", + "digest": "93b245eed85d22260d27d1a8c77f51fb3439309e09b2aeca6cd504dbea77b509" + }, + { "name": "flag_bl", "unicode": "1F1E7-1F1F1", "digest": "5e1e478deaf02bbaa26595e4cefc5f5c9bec6105ce521b7b9ab4fa5e7a452c14" }, { + "name": "bl", + "unicode": "1F1E7-1F1F1", + "digest": "5e1e478deaf02bbaa26595e4cefc5f5c9bec6105ce521b7b9ab4fa5e7a452c14" + }, + { "name": "flag_black", "unicode": "1F3F4", "digest": "df131e5c28e9f51dea53fe7f33551f91d420f7d686b7a62980f0154c6b5357a6" }, { + "name": "waving_black_flag", + "unicode": "1F3F4", + "digest": "df131e5c28e9f51dea53fe7f33551f91d420f7d686b7a62980f0154c6b5357a6" + }, + { "name": "flag_bm", "unicode": "1F1E7-1F1F2", "digest": "9dcd9e60faebe7f93eb19157e99f2ad654a8145c61738de96e6ecd11a246764a" }, { + "name": "bm", + "unicode": "1F1E7-1F1F2", + "digest": "9dcd9e60faebe7f93eb19157e99f2ad654a8145c61738de96e6ecd11a246764a" + }, + { "name": "flag_bn", "unicode": "1F1E7-1F1F3", "digest": "078af6ca481a77871ba005e251a46ce63951c27b1b0cd33b9c1d0d31d349bc1a" }, { + "name": "bn", + "unicode": "1F1E7-1F1F3", + "digest": "078af6ca481a77871ba005e251a46ce63951c27b1b0cd33b9c1d0d31d349bc1a" + }, + { "name": "flag_bo", "unicode": "1F1E7-1F1F4", "digest": "92516d04e922a3bcbabe2e7619194bc972c09ba97576e8155f9829c397a71d8c" }, { + "name": "bo", + "unicode": "1F1E7-1F1F4", + "digest": "92516d04e922a3bcbabe2e7619194bc972c09ba97576e8155f9829c397a71d8c" + }, + { "name": "flag_bq", "unicode": "1F1E7-1F1F6", "digest": "7832df5267a2bb8dddb83aeb11162ce79aeebdb718f2ac0e54adcf3d87936171" }, { + "name": "bq", + "unicode": "1F1E7-1F1F6", + "digest": "7832df5267a2bb8dddb83aeb11162ce79aeebdb718f2ac0e54adcf3d87936171" + }, + { "name": "flag_br", "unicode": "1F1E7-1F1F7", "digest": "aabcc1c082124045ed214f7d9778d8e2ed791ebb8433defea91db458658abeec" }, { + "name": "br", + "unicode": "1F1E7-1F1F7", + "digest": "aabcc1c082124045ed214f7d9778d8e2ed791ebb8433defea91db458658abeec" + }, + { "name": "flag_bs", "unicode": "1F1E7-1F1F8", "digest": "f628f39003608e181696634929522884165e27ccef55270293f92eeef991635f" }, { + "name": "bs", + "unicode": "1F1E7-1F1F8", + "digest": "f628f39003608e181696634929522884165e27ccef55270293f92eeef991635f" + }, + { "name": "flag_bt", "unicode": "1F1E7-1F1F9", "digest": "af24a8ab34815da04c3e5af49a47449e0de93b068957cbda695816d0f830ca12" }, { + "name": "bt", + "unicode": "1F1E7-1F1F9", + "digest": "af24a8ab34815da04c3e5af49a47449e0de93b068957cbda695816d0f830ca12" + }, + { "name": "flag_bv", "unicode": "1F1E7-1F1FB", "digest": "ff0037f6eed95d4bb5f2b502902360e1ff41426e2896daf3e0730cef1f8f7e41" }, { + "name": "bv", + "unicode": "1F1E7-1F1FB", + "digest": "ff0037f6eed95d4bb5f2b502902360e1ff41426e2896daf3e0730cef1f8f7e41" + }, + { "name": "flag_bw", "unicode": "1F1E7-1F1FC", "digest": "3e3241ecb97946cc3e467b083d113a57dd305595e1512d4da18cc403e8689c1d" }, { + "name": "bw", + "unicode": "1F1E7-1F1FC", + "digest": "3e3241ecb97946cc3e467b083d113a57dd305595e1512d4da18cc403e8689c1d" + }, + { "name": "flag_by", "unicode": "1F1E7-1F1FE", "digest": "bdd21885c6fac475241884a44149b887297772e17617ee59dd9fe8518d52cf3d" }, { + "name": "by", + "unicode": "1F1E7-1F1FE", + "digest": "bdd21885c6fac475241884a44149b887297772e17617ee59dd9fe8518d52cf3d" + }, + { "name": "flag_bz", "unicode": "1F1E7-1F1FF", "digest": "21c16e1da641af004576000bf1db44b9a1e0fccfddc775e96022721c2f18eeea" }, { + "name": "bz", + "unicode": "1F1E7-1F1FF", + "digest": "21c16e1da641af004576000bf1db44b9a1e0fccfddc775e96022721c2f18eeea" + }, + { "name": "flag_ca", "unicode": "1F1E8-1F1E6", "digest": "0d00e459084d58d3ea9c60488a9e51bf45f71b77f1600f190225d5ca6ca6c796" }, { + "name": "ca", + "unicode": "1F1E8-1F1E6", + "digest": "0d00e459084d58d3ea9c60488a9e51bf45f71b77f1600f190225d5ca6ca6c796" + }, + { "name": "flag_cc", "unicode": "1F1E8-1F1E8", "digest": "86ab27164603ef0f1f83fe898eda6fbb7bc5709f2518f5577f00817860806a7b" }, { + "name": "cc", + "unicode": "1F1E8-1F1E8", + "digest": "86ab27164603ef0f1f83fe898eda6fbb7bc5709f2518f5577f00817860806a7b" + }, + { "name": "flag_cd", "unicode": "1F1E8-1F1E9", "digest": "fdc2796530ada4bd0bae37ace4bbe707b321b287dcd64568f8e01d3a9df56066" }, { + "name": "congo", + "unicode": "1F1E8-1F1E9", + "digest": "fdc2796530ada4bd0bae37ace4bbe707b321b287dcd64568f8e01d3a9df56066" + }, + { "name": "flag_cf", "unicode": "1F1E8-1F1EB", "digest": "5943bec02bede0931e21e7c34a68f375499f60a34883cc1edf2f21e9834b15ce" }, { + "name": "cf", + "unicode": "1F1E8-1F1EB", + "digest": "5943bec02bede0931e21e7c34a68f375499f60a34883cc1edf2f21e9834b15ce" + }, + { "name": "flag_cg", "unicode": "1F1E8-1F1EC", "digest": "54498482e2772371e148e05cfb7c5eb55f6a22cd528662abdea10bad47d157da" }, { + "name": "cg", + "unicode": "1F1E8-1F1EC", + "digest": "54498482e2772371e148e05cfb7c5eb55f6a22cd528662abdea10bad47d157da" + }, + { "name": "flag_ch", "unicode": "1F1E8-1F1ED", "digest": "53d6d35aeeebb0b4b1ad858dc3691e649ac73d30b3be76f96d5fe9605fa99386" }, { + "name": "ch", + "unicode": "1F1E8-1F1ED", + "digest": "53d6d35aeeebb0b4b1ad858dc3691e649ac73d30b3be76f96d5fe9605fa99386" + }, + { "name": "flag_ci", "unicode": "1F1E8-1F1EE", "digest": "3a173a3058a5c0174dc88750852cafec264e901ce82a6c69db122c8c0ea71a3a" }, { + "name": "ci", + "unicode": "1F1E8-1F1EE", + "digest": "3a173a3058a5c0174dc88750852cafec264e901ce82a6c69db122c8c0ea71a3a" + }, + { "name": "flag_ck", "unicode": "1F1E8-1F1F0", "digest": "42f395ff53c618b72b8a224cd4343d1a32f5ad82ced56bf590170a5ff0d5134c" }, { + "name": "ck", + "unicode": "1F1E8-1F1F0", + "digest": "42f395ff53c618b72b8a224cd4343d1a32f5ad82ced56bf590170a5ff0d5134c" + }, + { "name": "flag_cl", "unicode": "1F1E8-1F1F1", "digest": "9d6255feb690596904d800e72d5acdb5cda941c5a741b031ea39a3c7650ac46f" }, { + "name": "chile", + "unicode": "1F1E8-1F1F1", + "digest": "9d6255feb690596904d800e72d5acdb5cda941c5a741b031ea39a3c7650ac46f" + }, + { "name": "flag_cm", "unicode": "1F1E8-1F1F2", "digest": "ffc99d14e0a8b46a980331090ed9f36f31a87f1b0f8dd8c09007a31c6127c69e" }, { + "name": "cm", + "unicode": "1F1E8-1F1F2", + "digest": "ffc99d14e0a8b46a980331090ed9f36f31a87f1b0f8dd8c09007a31c6127c69e" + }, + { "name": "flag_cn", "unicode": "1F1E8-1F1F3", "digest": "869a98c52bdc33591f87e2aab6cb4f13e98bb19136250ff25805d0312a8b7c8a" }, { + "name": "cn", + "unicode": "1F1E8-1F1F3", + "digest": "869a98c52bdc33591f87e2aab6cb4f13e98bb19136250ff25805d0312a8b7c8a" + }, + { "name": "flag_co", "unicode": "1F1E8-1F1F4", "digest": "6aa458440eb2500ad307fea40fd8f1171a1506a6e32af144a4fd51545bb56151" }, { + "name": "co", + "unicode": "1F1E8-1F1F4", + "digest": "6aa458440eb2500ad307fea40fd8f1171a1506a6e32af144a4fd51545bb56151" + }, + { "name": "flag_cp", "unicode": "1F1E8-1F1F5", "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee" }, { + "name": "cp", + "unicode": "1F1E8-1F1F5", + "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee" + }, + { "name": "flag_cr", "unicode": "1F1E8-1F1F7", "digest": "0f3b54d8330c5bb136647547dafc598bda755697cfd6b7d872a2443ba7b5cad4" }, { + "name": "cr", + "unicode": "1F1E8-1F1F7", + "digest": "0f3b54d8330c5bb136647547dafc598bda755697cfd6b7d872a2443ba7b5cad4" + }, + { "name": "flag_cu", "unicode": "1F1E8-1F1FA", "digest": "69bc973002475bb3d9b54cb0ba9ec9cb85f144c1cf54689da0ee8f414ebb0d83" }, { + "name": "cu", + "unicode": "1F1E8-1F1FA", + "digest": "69bc973002475bb3d9b54cb0ba9ec9cb85f144c1cf54689da0ee8f414ebb0d83" + }, + { "name": "flag_cv", "unicode": "1F1E8-1F1FB", "digest": "af2e135cf3c1b03a5937c068a75061b5cd332e95902fd0f8dffb2ac2dc89692a" }, { + "name": "cv", + "unicode": "1F1E8-1F1FB", + "digest": "af2e135cf3c1b03a5937c068a75061b5cd332e95902fd0f8dffb2ac2dc89692a" + }, + { "name": "flag_cw", "unicode": "1F1E8-1F1FC", "digest": "df4b2228a82f766c5c64c13c1388482a68549e59dd843671ee0eb43506e33411" }, { + "name": "cw", + "unicode": "1F1E8-1F1FC", + "digest": "df4b2228a82f766c5c64c13c1388482a68549e59dd843671ee0eb43506e33411" + }, + { "name": "flag_cx", "unicode": "1F1E8-1F1FD", "digest": "db12e513345a7be53954167d359ede0b3effbfb292508ee4d726123e3a8f83d7" }, { + "name": "cx", + "unicode": "1F1E8-1F1FD", + "digest": "db12e513345a7be53954167d359ede0b3effbfb292508ee4d726123e3a8f83d7" + }, + { "name": "flag_cy", "unicode": "1F1E8-1F1FE", "digest": "0cea41d4820746e2c6eb408f7ec7419afba9f7396401d92e6c1d77382f721d0b" }, { + "name": "cy", + "unicode": "1F1E8-1F1FE", + "digest": "0cea41d4820746e2c6eb408f7ec7419afba9f7396401d92e6c1d77382f721d0b" + }, + { "name": "flag_cz", "unicode": "1F1E8-1F1FF", "digest": "a1c2405916963be306f761539123486a2845af53716c9dfe94ad5420e14d36c4" }, { + "name": "cz", + "unicode": "1F1E8-1F1FF", + "digest": "a1c2405916963be306f761539123486a2845af53716c9dfe94ad5420e14d36c4" + }, + { "name": "flag_de", "unicode": "1F1E9-1F1EA", "digest": "74a80b64437bc4e31bdd7cbb753ecd2d719bf34c506cbac535db83a644174cce" }, { + "name": "de", + "unicode": "1F1E9-1F1EA", + "digest": "74a80b64437bc4e31bdd7cbb753ecd2d719bf34c506cbac535db83a644174cce" + }, + { "name": "flag_dg", "unicode": "1F1E9-1F1EC", "digest": "13cb5ea872f94a9c3fb579cef417e2d1ed38e8cbe95059576380cacd59bc4b9d" }, { + "name": "dg", + "unicode": "1F1E9-1F1EC", + "digest": "13cb5ea872f94a9c3fb579cef417e2d1ed38e8cbe95059576380cacd59bc4b9d" + }, + { "name": "flag_dj", "unicode": "1F1E9-1F1EF", "digest": "5b479654c28d3eeb70055c5e25dc46ccaba9eeea7537cc45ca9dbb8186b743b6" }, { + "name": "dj", + "unicode": "1F1E9-1F1EF", + "digest": "5b479654c28d3eeb70055c5e25dc46ccaba9eeea7537cc45ca9dbb8186b743b6" + }, + { "name": "flag_dk", "unicode": "1F1E9-1F1F0", "digest": "dee7fa9644a9b447417518a353e7edcbb37b2af8bc7d13a6ed71d7210c43ca3c" }, { + "name": "dk", + "unicode": "1F1E9-1F1F0", + "digest": "dee7fa9644a9b447417518a353e7edcbb37b2af8bc7d13a6ed71d7210c43ca3c" + }, + { "name": "flag_dm", "unicode": "1F1E9-1F1F2", "digest": "2e339190a8a0a238140f42e329f6646af5be75763a787ea268488a2e0440dc4c" }, { + "name": "dm", + "unicode": "1F1E9-1F1F2", + "digest": "2e339190a8a0a238140f42e329f6646af5be75763a787ea268488a2e0440dc4c" + }, + { "name": "flag_do", "unicode": "1F1E9-1F1F4", "digest": "be5dafcd32d7197a96d37299a91835a8009299452f05a66d91c5fdec17448230" }, { + "name": "do", + "unicode": "1F1E9-1F1F4", + "digest": "be5dafcd32d7197a96d37299a91835a8009299452f05a66d91c5fdec17448230" + }, + { "name": "flag_dz", "unicode": "1F1E9-1F1FF", "digest": "cf525d56bac45fe689f92d441274fc0ecbed4f95591d2c066598f72b1ee8d618" }, { + "name": "dz", + "unicode": "1F1E9-1F1FF", + "digest": "cf525d56bac45fe689f92d441274fc0ecbed4f95591d2c066598f72b1ee8d618" + }, + { "name": "flag_ea", "unicode": "1F1EA-1F1E6", "digest": "1acb13950f7c3692f9a36e618d8ec10a73ead5d7fa80fb52b6b2a18e3d456002" }, { + "name": "ea", + "unicode": "1F1EA-1F1E6", + "digest": "1acb13950f7c3692f9a36e618d8ec10a73ead5d7fa80fb52b6b2a18e3d456002" + }, + { "name": "flag_ec", "unicode": "1F1EA-1F1E8", "digest": "4d9d35450efc6026651ccc2278e70fb90b001ca5e5eecd31361b1e4e23253dbd" }, { + "name": "ec", + "unicode": "1F1EA-1F1E8", + "digest": "4d9d35450efc6026651ccc2278e70fb90b001ca5e5eecd31361b1e4e23253dbd" + }, + { "name": "flag_ee", "unicode": "1F1EA-1F1EA", "digest": "86ec7b2f618fe71dddec3d5a621b56b878d683780f1e0ad446f965326d42df48" }, { + "name": "ee", + "unicode": "1F1EA-1F1EA", + "digest": "86ec7b2f618fe71dddec3d5a621b56b878d683780f1e0ad446f965326d42df48" + }, + { "name": "flag_eg", "unicode": "1F1EA-1F1EC", "digest": "f06d36a6fec15af4c1a76de30e8469847dde2728bb5a48956b4e466098b778a4" }, { + "name": "eg", + "unicode": "1F1EA-1F1EC", + "digest": "f06d36a6fec15af4c1a76de30e8469847dde2728bb5a48956b4e466098b778a4" + }, + { "name": "flag_eh", "unicode": "1F1EA-1F1ED", "digest": "eb63f5b92c62c98dc008dfa7ad8830aa17fa23964f812a28055bd8b6f5960c5b" }, { + "name": "eh", + "unicode": "1F1EA-1F1ED", + "digest": "eb63f5b92c62c98dc008dfa7ad8830aa17fa23964f812a28055bd8b6f5960c5b" + }, + { "name": "flag_er", "unicode": "1F1EA-1F1F7", "digest": "e901195f7b37b22a6872d36713de0ec176f6424c209e261e5c849ce318c772f6" }, { + "name": "er", + "unicode": "1F1EA-1F1F7", + "digest": "e901195f7b37b22a6872d36713de0ec176f6424c209e261e5c849ce318c772f6" + }, + { "name": "flag_es", "unicode": "1F1EA-1F1F8", "digest": "27ab5cc6c2e9f26ccdfa632887533eebcd9b514f80cec9e721cf8e5e2544339c" }, { + "name": "es", + "unicode": "1F1EA-1F1F8", + "digest": "27ab5cc6c2e9f26ccdfa632887533eebcd9b514f80cec9e721cf8e5e2544339c" + }, + { "name": "flag_et", "unicode": "1F1EA-1F1F9", "digest": "6cdb3718c9b3ec713258dd36781db58b7da53f3017445056c1a76233e3b4a7de" }, { + "name": "et", + "unicode": "1F1EA-1F1F9", + "digest": "6cdb3718c9b3ec713258dd36781db58b7da53f3017445056c1a76233e3b4a7de" + }, + { "name": "flag_eu", "unicode": "1F1EA-1F1FA", "digest": "363f60e8a747166d5cec8d70bfdf266411eec2ff07933b6187975075caadfd74" }, { + "name": "eu", + "unicode": "1F1EA-1F1FA", + "digest": "363f60e8a747166d5cec8d70bfdf266411eec2ff07933b6187975075caadfd74" + }, + { "name": "flag_fi", "unicode": "1F1EB-1F1EE", "digest": "1a1959cb551a0e8bdaee8c04657fb7387a4d83173f7759f89468da12e1818a9e" }, { + "name": "fi", + "unicode": "1F1EB-1F1EE", + "digest": "1a1959cb551a0e8bdaee8c04657fb7387a4d83173f7759f89468da12e1818a9e" + }, + { "name": "flag_fj", "unicode": "1F1EB-1F1EF", "digest": "f26dc36ea9c1f32d9bb54874ea384e7118b6e2585be69245fdd73acd8304ae78" }, { + "name": "fj", + "unicode": "1F1EB-1F1EF", + "digest": "f26dc36ea9c1f32d9bb54874ea384e7118b6e2585be69245fdd73acd8304ae78" + }, + { "name": "flag_fk", "unicode": "1F1EB-1F1F0", "digest": "0479e233499b704f91a9b13d083e66296efe2f28ed917ab1496b223bfb09adb8" }, { + "name": "fk", + "unicode": "1F1EB-1F1F0", + "digest": "0479e233499b704f91a9b13d083e66296efe2f28ed917ab1496b223bfb09adb8" + }, + { "name": "flag_fm", "unicode": "1F1EB-1F1F2", "digest": "142ea7b4b4a7004329925b495da43ab82351cbaac383c8da6e614b39ba58d05e" }, { + "name": "fm", + "unicode": "1F1EB-1F1F2", + "digest": "142ea7b4b4a7004329925b495da43ab82351cbaac383c8da6e614b39ba58d05e" + }, + { "name": "flag_fo", "unicode": "1F1EB-1F1F4", "digest": "f1c800d4f4d39e2aead9a11ed500f16108d6bc48bd24bd2a1af7b966d8e76752" }, { + "name": "fo", + "unicode": "1F1EB-1F1F4", + "digest": "f1c800d4f4d39e2aead9a11ed500f16108d6bc48bd24bd2a1af7b966d8e76752" + }, + { "name": "flag_fr", "unicode": "1F1EB-1F1F7", "digest": "6f52f36b5199c65ab1cad13ff4e77d2d8b48a8ff79b92166976674ffdc7829ee" }, { + "name": "fr", + "unicode": "1F1EB-1F1F7", + "digest": "6f52f36b5199c65ab1cad13ff4e77d2d8b48a8ff79b92166976674ffdc7829ee" + }, + { "name": "flag_ga", "unicode": "1F1EC-1F1E6", "digest": "50a0d5a07466e419b74a4d532738f7958de9baa37df6191be4f3755dccc3b326" }, { + "name": "ga", + "unicode": "1F1EC-1F1E6", + "digest": "50a0d5a07466e419b74a4d532738f7958de9baa37df6191be4f3755dccc3b326" + }, + { "name": "flag_gb", "unicode": "1F1EC-1F1E7", "digest": "220f7da6d5a231b766c79f2e1b7d3fdb74ec0c0c17558cc00a8a8ccdf2afc2e0" }, { + "name": "gb", + "unicode": "1F1EC-1F1E7", + "digest": "220f7da6d5a231b766c79f2e1b7d3fdb74ec0c0c17558cc00a8a8ccdf2afc2e0" + }, + { "name": "flag_gd", "unicode": "1F1EC-1F1E9", "digest": "3e162b0d13f4ceea7f663b1d425f13863d104e80df75a640f526e276bcd04081" }, { + "name": "gd", + "unicode": "1F1EC-1F1E9", + "digest": "3e162b0d13f4ceea7f663b1d425f13863d104e80df75a640f526e276bcd04081" + }, + { "name": "flag_ge", "unicode": "1F1EC-1F1EA", "digest": "35897f8254675d2efe9e3070c88af9ef214f08440e6ee75ebe81d28cdb57ea2b" }, { + "name": "ge", + "unicode": "1F1EC-1F1EA", + "digest": "35897f8254675d2efe9e3070c88af9ef214f08440e6ee75ebe81d28cdb57ea2b" + }, + { "name": "flag_gf", "unicode": "1F1EC-1F1EB", "digest": "3a34df321635f71a0f2cc4e1eda58d85c29230c77456362345196351bf56533d" }, { + "name": "gf", + "unicode": "1F1EC-1F1EB", + "digest": "3a34df321635f71a0f2cc4e1eda58d85c29230c77456362345196351bf56533d" + }, + { "name": "flag_gg", "unicode": "1F1EC-1F1EC", "digest": "c972f8d190b4e9ca8890df41503d202ffd73981833d3f3750f563302167bcd66" }, { + "name": "gg", + "unicode": "1F1EC-1F1EC", + "digest": "c972f8d190b4e9ca8890df41503d202ffd73981833d3f3750f563302167bcd66" + }, + { "name": "flag_gh", "unicode": "1F1EC-1F1ED", "digest": "9c3d3569bd411389fa0af7c6938d4325cedeb9c0e8f059dc1d5a74c6b8d6d01b" }, { + "name": "gh", + "unicode": "1F1EC-1F1ED", + "digest": "9c3d3569bd411389fa0af7c6938d4325cedeb9c0e8f059dc1d5a74c6b8d6d01b" + }, + { "name": "flag_gi", "unicode": "1F1EC-1F1EE", "digest": "ede638bc6fedc30a01821025d87ec19297500da9c04a7a155984fca186118649" }, { + "name": "gi", + "unicode": "1F1EC-1F1EE", + "digest": "ede638bc6fedc30a01821025d87ec19297500da9c04a7a155984fca186118649" + }, + { "name": "flag_gl", "unicode": "1F1EC-1F1F1", "digest": "a2ce3371eff1da8331671925f707232aa593ac7400d59555c9ca689729ce24ec" }, { + "name": "gl", + "unicode": "1F1EC-1F1F1", + "digest": "a2ce3371eff1da8331671925f707232aa593ac7400d59555c9ca689729ce24ec" + }, + { "name": "flag_gm", "unicode": "1F1EC-1F1F2", "digest": "932bf6eb75ddd4278268dd2f09d8fffcfef89f8fd6b6e86a08a414cd3ceec94d" }, { + "name": "gm", + "unicode": "1F1EC-1F1F2", + "digest": "932bf6eb75ddd4278268dd2f09d8fffcfef89f8fd6b6e86a08a414cd3ceec94d" + }, + { "name": "flag_gn", "unicode": "1F1EC-1F1F3", "digest": "ebf543713895adaa09d64897f24bd461191191b8fcbbcede52bdaf4bd2dc67a8" }, { + "name": "gn", + "unicode": "1F1EC-1F1F3", + "digest": "ebf543713895adaa09d64897f24bd461191191b8fcbbcede52bdaf4bd2dc67a8" + }, + { "name": "flag_gp", "unicode": "1F1EC-1F1F5", "digest": "2e6c48d80c571b34f31fa9b3622dcc51e1707c0118e991e9c177742ff02a8a96" }, { + "name": "gp", + "unicode": "1F1EC-1F1F5", + "digest": "2e6c48d80c571b34f31fa9b3622dcc51e1707c0118e991e9c177742ff02a8a96" + }, + { "name": "flag_gq", "unicode": "1F1EC-1F1F6", "digest": "b0f5810180d12fc48faf75e73f882dc59072d7bf957f8455bf7e1e336539dc41" }, { + "name": "gq", + "unicode": "1F1EC-1F1F6", + "digest": "b0f5810180d12fc48faf75e73f882dc59072d7bf957f8455bf7e1e336539dc41" + }, + { "name": "flag_gr", "unicode": "1F1EC-1F1F7", "digest": "8d60d6f8910f5179d851dbea0798b56a492c6be85f3d55e1a1126cd1d6663a3b" }, { + "name": "gr", + "unicode": "1F1EC-1F1F7", + "digest": "8d60d6f8910f5179d851dbea0798b56a492c6be85f3d55e1a1126cd1d6663a3b" + }, + { "name": "flag_gs", "unicode": "1F1EC-1F1F8", "digest": "7b07915af0e2364ebc386a162d44846f3a7986fdd24e20ad2bc56d64a103fe9c" }, { + "name": "gs", + "unicode": "1F1EC-1F1F8", + "digest": "7b07915af0e2364ebc386a162d44846f3a7986fdd24e20ad2bc56d64a103fe9c" + }, + { "name": "flag_gt", "unicode": "1F1EC-1F1F9", "digest": "0c78108ede45bf34917b409a0867f5ec8253c74b694beda083f3e8d04d7a10d8" }, { + "name": "gt", + "unicode": "1F1EC-1F1F9", + "digest": "0c78108ede45bf34917b409a0867f5ec8253c74b694beda083f3e8d04d7a10d8" + }, + { "name": "flag_gu", "unicode": "1F1EC-1F1FA", "digest": "909f1bc98fa1507adb787eb3875503b21ea937d6ae8bb152153916c2da5e13bb" }, { + "name": "gu", + "unicode": "1F1EC-1F1FA", + "digest": "909f1bc98fa1507adb787eb3875503b21ea937d6ae8bb152153916c2da5e13bb" + }, + { "name": "flag_gw", "unicode": "1F1EC-1F1FC", "digest": "f5f34410c7b22d5ed9994b47d0e7a9d9a6a1f05c4d3142f7fef3e4409725f5e6" }, { + "name": "gw", + "unicode": "1F1EC-1F1FC", + "digest": "f5f34410c7b22d5ed9994b47d0e7a9d9a6a1f05c4d3142f7fef3e4409725f5e6" + }, + { "name": "flag_gy", "unicode": "1F1EC-1F1FE", "digest": "4939cf52ab34a924a31032b42668960a2c7d8d4f998b16b065c247110df334be" }, { + "name": "gy", + "unicode": "1F1EC-1F1FE", + "digest": "4939cf52ab34a924a31032b42668960a2c7d8d4f998b16b065c247110df334be" + }, + { "name": "flag_hk", "unicode": "1F1ED-1F1F0", "digest": "bde0916df6d62f6b1cf8f85a8a39526c97fc6ef6fedb0b0cae2adb127a08eafe" }, { + "name": "hk", + "unicode": "1F1ED-1F1F0", + "digest": "bde0916df6d62f6b1cf8f85a8a39526c97fc6ef6fedb0b0cae2adb127a08eafe" + }, + { "name": "flag_hm", "unicode": "1F1ED-1F1F2", "digest": "603e6c9bff9a0dc941970a313fe98fbf53ff5a57028f1a2766420be4211711cc" }, { + "name": "hm", + "unicode": "1F1ED-1F1F2", + "digest": "603e6c9bff9a0dc941970a313fe98fbf53ff5a57028f1a2766420be4211711cc" + }, + { "name": "flag_hn", "unicode": "1F1ED-1F1F3", "digest": "2953ad0909bc32c02615f6ad5a4e5f331ba794a41632b1f0fc366e1c640cc2b9" }, { + "name": "hn", + "unicode": "1F1ED-1F1F3", + "digest": "2953ad0909bc32c02615f6ad5a4e5f331ba794a41632b1f0fc366e1c640cc2b9" + }, + { "name": "flag_hr", "unicode": "1F1ED-1F1F7", "digest": "41c9ffc4f0faaa2d77e5cffb781329e7d2489ce879bd8eb9c503621e834abc50" }, { + "name": "hr", + "unicode": "1F1ED-1F1F7", + "digest": "41c9ffc4f0faaa2d77e5cffb781329e7d2489ce879bd8eb9c503621e834abc50" + }, + { "name": "flag_ht", "unicode": "1F1ED-1F1F9", "digest": "6a56c3d71b4f858e1774aa2134a9f5584087fec968e9ee8bb1046d2ec93bf059" }, { + "name": "ht", + "unicode": "1F1ED-1F1F9", + "digest": "6a56c3d71b4f858e1774aa2134a9f5584087fec968e9ee8bb1046d2ec93bf059" + }, + { "name": "flag_hu", "unicode": "1F1ED-1F1FA", "digest": "72f5809818d4cab8c0cee73df7f67b820fb8471eea4199911a5917ac099795e8" }, { + "name": "hu", + "unicode": "1F1ED-1F1FA", + "digest": "72f5809818d4cab8c0cee73df7f67b820fb8471eea4199911a5917ac099795e8" + }, + { "name": "flag_ic", "unicode": "1F1EE-1F1E8", "digest": "7e2a7667fcd05f927af47e64c5790c104a9956dd9f1a45f03cb0fdcc85d866d3" }, { + "name": "ic", + "unicode": "1F1EE-1F1E8", + "digest": "7e2a7667fcd05f927af47e64c5790c104a9956dd9f1a45f03cb0fdcc85d866d3" + }, + { "name": "flag_id", "unicode": "1F1EE-1F1E9", "digest": "4721f616fae2e443e52f1e9cc96e4835bddca16a2d75d7d5afea57cdee866b7f" }, { + "name": "indonesia", + "unicode": "1F1EE-1F1E9", + "digest": "4721f616fae2e443e52f1e9cc96e4835bddca16a2d75d7d5afea57cdee866b7f" + }, + { "name": "flag_ie", "unicode": "1F1EE-1F1EA", "digest": "84b19833e6c9fb43187f8a28d85045a3df58816f20a07edab90474323174b1f3" }, { + "name": "ie", + "unicode": "1F1EE-1F1EA", + "digest": "84b19833e6c9fb43187f8a28d85045a3df58816f20a07edab90474323174b1f3" + }, + { "name": "flag_il", "unicode": "1F1EE-1F1F1", "digest": "c99d4bd8c2541cf3a7392c4faf4477d96bc47065dd1423b9e06450483e69b34f" }, { + "name": "il", + "unicode": "1F1EE-1F1F1", + "digest": "c99d4bd8c2541cf3a7392c4faf4477d96bc47065dd1423b9e06450483e69b34f" + }, + { "name": "flag_im", "unicode": "1F1EE-1F1F2", "digest": "5eeb12c0315b527ce61649a38b64d76af726a73b2d381d1a1ddd1366bafb1bfc" }, { + "name": "im", + "unicode": "1F1EE-1F1F2", + "digest": "5eeb12c0315b527ce61649a38b64d76af726a73b2d381d1a1ddd1366bafb1bfc" + }, + { "name": "flag_in", "unicode": "1F1EE-1F1F3", "digest": "ecc3cfcff3368fe0875a51a8be9f4dfd449a187e5beb41a2b34241736247f73b" }, { + "name": "in", + "unicode": "1F1EE-1F1F3", + "digest": "ecc3cfcff3368fe0875a51a8be9f4dfd449a187e5beb41a2b34241736247f73b" + }, + { "name": "flag_io", "unicode": "1F1EE-1F1F4", "digest": "26243d60e04ba3bc9eb8f008bfc77b2a64bcf1a3d0073eb0449a8c8121618c9c" }, { + "name": "io", + "unicode": "1F1EE-1F1F4", + "digest": "26243d60e04ba3bc9eb8f008bfc77b2a64bcf1a3d0073eb0449a8c8121618c9c" + }, + { "name": "flag_iq", "unicode": "1F1EE-1F1F6", "digest": "a1fb5e59575081920b3be5290f654d57a9be099deb56d4ed69eba81a2b531cb3" }, { + "name": "iq", + "unicode": "1F1EE-1F1F6", + "digest": "a1fb5e59575081920b3be5290f654d57a9be099deb56d4ed69eba81a2b531cb3" + }, + { "name": "flag_ir", "unicode": "1F1EE-1F1F7", "digest": "ab89488b934af1d4bdae7ed16dfc74fffe658bb8e95d5161b48cdd06de44ae85" }, { + "name": "ir", + "unicode": "1F1EE-1F1F7", + "digest": "ab89488b934af1d4bdae7ed16dfc74fffe658bb8e95d5161b48cdd06de44ae85" + }, + { "name": "flag_is", "unicode": "1F1EE-1F1F8", "digest": "55db1fc9e6c56d4c9bcb9a46e5e4300cf2a0c32fa91dc24b487a1d56c8097268" }, { + "name": "is", + "unicode": "1F1EE-1F1F8", + "digest": "55db1fc9e6c56d4c9bcb9a46e5e4300cf2a0c32fa91dc24b487a1d56c8097268" + }, + { "name": "flag_it", "unicode": "1F1EE-1F1F9", "digest": "36fc993fb00ab607578a4d0e573e988e17b9459a68a000a48de905a8238589d0" }, { + "name": "it", + "unicode": "1F1EE-1F1F9", + "digest": "36fc993fb00ab607578a4d0e573e988e17b9459a68a000a48de905a8238589d0" + }, + { "name": "flag_je", "unicode": "1F1EF-1F1EA", "digest": "c608dbfd1259330e2f8c40dc5d12ffd0489396f4fc5f3ca57bcb2f0d9d05c20c" }, { + "name": "je", + "unicode": "1F1EF-1F1EA", + "digest": "c608dbfd1259330e2f8c40dc5d12ffd0489396f4fc5f3ca57bcb2f0d9d05c20c" + }, + { "name": "flag_jm", "unicode": "1F1EF-1F1F2", "digest": "a8224b68b2d324f848d75e4376875ef76a8174e6ba32790d9ca622fe1eabfd5f" }, { + "name": "jm", + "unicode": "1F1EF-1F1F2", + "digest": "a8224b68b2d324f848d75e4376875ef76a8174e6ba32790d9ca622fe1eabfd5f" + }, + { "name": "flag_jo", "unicode": "1F1EF-1F1F4", "digest": "2403563dc2ab4ed0e7e3a0761cc09f96801550bba6b177b54d651d8804ad987d" }, { + "name": "jo", + "unicode": "1F1EF-1F1F4", + "digest": "2403563dc2ab4ed0e7e3a0761cc09f96801550bba6b177b54d651d8804ad987d" + }, + { "name": "flag_jp", "unicode": "1F1EF-1F1F5", "digest": "aea8eebd0a0139818cb7629d9c9a8e55160b458eb8ffeee2f36c5cff4b507fd3" }, { + "name": "jp", + "unicode": "1F1EF-1F1F5", + "digest": "aea8eebd0a0139818cb7629d9c9a8e55160b458eb8ffeee2f36c5cff4b507fd3" + }, + { "name": "flag_ke", "unicode": "1F1F0-1F1EA", "digest": "9c8365f74858743bcdce4a9cf6a6f4110faf2dc6433e5dc7d98c24bb3b32a36d" }, { + "name": "ke", + "unicode": "1F1F0-1F1EA", + "digest": "9c8365f74858743bcdce4a9cf6a6f4110faf2dc6433e5dc7d98c24bb3b32a36d" + }, + { "name": "flag_kg", "unicode": "1F1F0-1F1EC", "digest": "0c72bdb1d64b1e3be3d9516a50655a6162d8501851d2cf2fadb8c6ef7740df4e" }, { + "name": "kg", + "unicode": "1F1F0-1F1EC", + "digest": "0c72bdb1d64b1e3be3d9516a50655a6162d8501851d2cf2fadb8c6ef7740df4e" + }, + { "name": "flag_kh", "unicode": "1F1F0-1F1ED", "digest": "49e41e488732d789e395091e144cd6215c6818ba2073e5e22ea21203a737d03c" }, { + "name": "kh", + "unicode": "1F1F0-1F1ED", + "digest": "49e41e488732d789e395091e144cd6215c6818ba2073e5e22ea21203a737d03c" + }, + { "name": "flag_ki", "unicode": "1F1F0-1F1EE", "digest": "9d7f168adbcf5f4cfe28470addfdb0a8b231438d593edb70f633981bfa4c7638" }, { + "name": "ki", + "unicode": "1F1F0-1F1EE", + "digest": "9d7f168adbcf5f4cfe28470addfdb0a8b231438d593edb70f633981bfa4c7638" + }, + { "name": "flag_km", "unicode": "1F1F0-1F1F2", "digest": "9318c28957fa7a19eba5ec452c1cbce01a5a83d41d29d081614d3abb0585d478" }, { + "name": "km", + "unicode": "1F1F0-1F1F2", + "digest": "9318c28957fa7a19eba5ec452c1cbce01a5a83d41d29d081614d3abb0585d478" + }, + { "name": "flag_kn", "unicode": "1F1F0-1F1F3", "digest": "eac7e7d0f023dee5c0c8559bc2c9a96273adda54ce47598025120b30d8d6ebc1" }, { + "name": "kn", + "unicode": "1F1F0-1F1F3", + "digest": "eac7e7d0f023dee5c0c8559bc2c9a96273adda54ce47598025120b30d8d6ebc1" + }, + { "name": "flag_kp", "unicode": "1F1F0-1F1F5", "digest": "d4d53db6f8363174de6db864c056267ba8a7d7e87b5527f2f42bb9b8ac3f362b" }, { + "name": "kp", + "unicode": "1F1F0-1F1F5", + "digest": "d4d53db6f8363174de6db864c056267ba8a7d7e87b5527f2f42bb9b8ac3f362b" + }, + { "name": "flag_kr", "unicode": "1F1F0-1F1F7", "digest": "5c7e61ab4a2aae70cbe51f0ca4718516002bc943b35d870bd853a0c98c4e0ed5" }, { + "name": "kr", + "unicode": "1F1F0-1F1F7", + "digest": "5c7e61ab4a2aae70cbe51f0ca4718516002bc943b35d870bd853a0c98c4e0ed5" + }, + { "name": "flag_kw", "unicode": "1F1F0-1F1FC", "digest": "5d229cd99d25f4285bd30d98cfcc3cd8346648897476e2905a1811ceeef48d37" }, { + "name": "kw", + "unicode": "1F1F0-1F1FC", + "digest": "5d229cd99d25f4285bd30d98cfcc3cd8346648897476e2905a1811ceeef48d37" + }, + { "name": "flag_ky", "unicode": "1F1F0-1F1FE", "digest": "9ce3d8dfc273d3a400960876c434b702f93df92c6c00682dbed2ec8e3966d8a8" }, { + "name": "ky", + "unicode": "1F1F0-1F1FE", + "digest": "9ce3d8dfc273d3a400960876c434b702f93df92c6c00682dbed2ec8e3966d8a8" + }, + { "name": "flag_kz", "unicode": "1F1F0-1F1FF", "digest": "a6f0be0a767fa4824495d568d9fc2bd8d4c1a26f363873d3b65362e9383e2a50" }, { + "name": "kz", + "unicode": "1F1F0-1F1FF", + "digest": "a6f0be0a767fa4824495d568d9fc2bd8d4c1a26f363873d3b65362e9383e2a50" + }, + { "name": "flag_la", "unicode": "1F1F1-1F1E6", "digest": "ab2ae96da87f7b53ab212f8dcd897a591cff9ea6666270097a8e739ee0b8f8cb" }, { + "name": "la", + "unicode": "1F1F1-1F1E6", + "digest": "ab2ae96da87f7b53ab212f8dcd897a591cff9ea6666270097a8e739ee0b8f8cb" + }, + { "name": "flag_lb", "unicode": "1F1F1-1F1E7", "digest": "0c3fcab22e9fae1c78658290aff97de785d0b6adb5e3702d00073ce774b7ed54" }, { + "name": "lb", + "unicode": "1F1F1-1F1E7", + "digest": "0c3fcab22e9fae1c78658290aff97de785d0b6adb5e3702d00073ce774b7ed54" + }, + { "name": "flag_lc", "unicode": "1F1F1-1F1E8", "digest": "e154b0b3a1635a36e0d9ad518c0ea12259320e5f1ebbda982248486492065d28" }, { + "name": "lc", + "unicode": "1F1F1-1F1E8", + "digest": "e154b0b3a1635a36e0d9ad518c0ea12259320e5f1ebbda982248486492065d28" + }, + { "name": "flag_li", "unicode": "1F1F1-1F1EE", "digest": "bbc393a89e73cc8c29a0a9297428d07aa1d4717ea9b7d4dd9d69f21ac7d0605d" }, { + "name": "li", + "unicode": "1F1F1-1F1EE", + "digest": "bbc393a89e73cc8c29a0a9297428d07aa1d4717ea9b7d4dd9d69f21ac7d0605d" + }, + { "name": "flag_lk", "unicode": "1F1F1-1F1F0", "digest": "376bd501d113a844971ca1006ab31aa086cd55d74842ea5f3dedaba997b58693" }, { + "name": "lk", + "unicode": "1F1F1-1F1F0", + "digest": "376bd501d113a844971ca1006ab31aa086cd55d74842ea5f3dedaba997b58693" + }, + { "name": "flag_lr", "unicode": "1F1F1-1F1F7", "digest": "9a6ebe1c9d9a53079ee77292a5ad0965f96409b0417f92876a1c3bd463d6a9bc" }, { + "name": "lr", + "unicode": "1F1F1-1F1F7", + "digest": "9a6ebe1c9d9a53079ee77292a5ad0965f96409b0417f92876a1c3bd463d6a9bc" + }, + { "name": "flag_ls", "unicode": "1F1F1-1F1F8", "digest": "e2f4b05414f6e0c3d629a92b0534d4145475f0214a83a62c902fe0884c833c89" }, { + "name": "ls", + "unicode": "1F1F1-1F1F8", + "digest": "e2f4b05414f6e0c3d629a92b0534d4145475f0214a83a62c902fe0884c833c89" + }, + { "name": "flag_lt", "unicode": "1F1F1-1F1F9", "digest": "d5e2f8b2ffa820a33ea6d612fccd61e32467d25154342f5be134d3520e48387f" }, { + "name": "lt", + "unicode": "1F1F1-1F1F9", + "digest": "d5e2f8b2ffa820a33ea6d612fccd61e32467d25154342f5be134d3520e48387f" + }, + { "name": "flag_lu", "unicode": "1F1F1-1F1FA", "digest": "f43277103292195b51981d08e2dde68eab660a65c7875f510e09a8b2370f1b5c" }, { + "name": "lu", + "unicode": "1F1F1-1F1FA", + "digest": "f43277103292195b51981d08e2dde68eab660a65c7875f510e09a8b2370f1b5c" + }, + { "name": "flag_lv", "unicode": "1F1F1-1F1FB", "digest": "e1288ac5c80d6e9d577d652e34be247ca39bf9d3d7cfc8a6cae13c1f9ac9dc47" }, { + "name": "lv", + "unicode": "1F1F1-1F1FB", + "digest": "e1288ac5c80d6e9d577d652e34be247ca39bf9d3d7cfc8a6cae13c1f9ac9dc47" + }, + { "name": "flag_ly", "unicode": "1F1F1-1F1FE", "digest": "5122294b769a174e3b6e3d238bb846b3e760929f5bb3c1a708d8a429f3f32f68" }, { + "name": "ly", + "unicode": "1F1F1-1F1FE", + "digest": "5122294b769a174e3b6e3d238bb846b3e760929f5bb3c1a708d8a429f3f32f68" + }, + { "name": "flag_ma", "unicode": "1F1F2-1F1E6", "digest": "615a6447ff284de7689b4fd7b04fdda308f65dbbec958cfb96d2977514981d16" }, { + "name": "ma", + "unicode": "1F1F2-1F1E6", + "digest": "615a6447ff284de7689b4fd7b04fdda308f65dbbec958cfb96d2977514981d16" + }, + { "name": "flag_mc", "unicode": "1F1F2-1F1E8", "digest": "08b48b28938acbfc0fbc15c25ee14dbad7164c5165d03df2eee370755ee7b4cf" }, { + "name": "mc", + "unicode": "1F1F2-1F1E8", + "digest": "08b48b28938acbfc0fbc15c25ee14dbad7164c5165d03df2eee370755ee7b4cf" + }, + { "name": "flag_md", "unicode": "1F1F2-1F1E9", "digest": "93d61de68f821e1e08b30e63d91e8b4a657766475128538894cf9da9a3b4e3c0" }, { + "name": "md", + "unicode": "1F1F2-1F1E9", + "digest": "93d61de68f821e1e08b30e63d91e8b4a657766475128538894cf9da9a3b4e3c0" + }, + { "name": "flag_me", "unicode": "1F1F2-1F1EA", "digest": "ee55c0eb78241aec2baf1822a47fa46d63209ceae3db7617ae886b823ae229ff" }, { + "name": "me", + "unicode": "1F1F2-1F1EA", + "digest": "ee55c0eb78241aec2baf1822a47fa46d63209ceae3db7617ae886b823ae229ff" + }, + { "name": "flag_mf", "unicode": "1F1F2-1F1EB", "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee" }, { + "name": "mf", + "unicode": "1F1F2-1F1EB", + "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee" + }, + { "name": "flag_mg", "unicode": "1F1F2-1F1EC", "digest": "86ec8140e2c4854f52cff74757baf0cbb75a4aacca8be6af8c8f9c939a7b866c" }, { + "name": "mg", + "unicode": "1F1F2-1F1EC", + "digest": "86ec8140e2c4854f52cff74757baf0cbb75a4aacca8be6af8c8f9c939a7b866c" + }, + { "name": "flag_mh", "unicode": "1F1F2-1F1ED", "digest": "8311ea3422c9d5e94b55e19b03bedd6fe6e2a191b7657e15ac75a48932958a5b" }, { + "name": "mh", + "unicode": "1F1F2-1F1ED", + "digest": "8311ea3422c9d5e94b55e19b03bedd6fe6e2a191b7657e15ac75a48932958a5b" + }, + { "name": "flag_mk", "unicode": "1F1F2-1F1F0", "digest": "5c6f504f88c5a875c06ac8b26fa6e81a9d79c42a1c7d1fad9a5d4c8ad06ca502" }, { + "name": "mk", + "unicode": "1F1F2-1F1F0", + "digest": "5c6f504f88c5a875c06ac8b26fa6e81a9d79c42a1c7d1fad9a5d4c8ad06ca502" + }, + { "name": "flag_ml", "unicode": "1F1F2-1F1F1", "digest": "d08a4973db40cf28e58ca3c80e8bd4e50d68ba1080b31917aeefdb0e210b5c50" }, { + "name": "ml", + "unicode": "1F1F2-1F1F1", + "digest": "d08a4973db40cf28e58ca3c80e8bd4e50d68ba1080b31917aeefdb0e210b5c50" + }, + { "name": "flag_mm", "unicode": "1F1F2-1F1F2", "digest": "5e95089514ca09bb93afb481b317477c9d053adcf450e0b711d78ed1078c7470" }, { + "name": "mm", + "unicode": "1F1F2-1F1F2", + "digest": "5e95089514ca09bb93afb481b317477c9d053adcf450e0b711d78ed1078c7470" + }, + { "name": "flag_mn", "unicode": "1F1F2-1F1F3", "digest": "7a0ca72715dd2a36eeeed2f8c888497cb752f0000af8f07d6930743caf6e4273" }, { + "name": "mn", + "unicode": "1F1F2-1F1F3", + "digest": "7a0ca72715dd2a36eeeed2f8c888497cb752f0000af8f07d6930743caf6e4273" + }, + { "name": "flag_mo", "unicode": "1F1F2-1F1F4", "digest": "d2c7c2191bc1bc83d85f2270968cb4de5cf26a11f70e166a8b32c108287ef729" }, { + "name": "mo", + "unicode": "1F1F2-1F1F4", + "digest": "d2c7c2191bc1bc83d85f2270968cb4de5cf26a11f70e166a8b32c108287ef729" + }, + { "name": "flag_mp", "unicode": "1F1F2-1F1F5", "digest": "89ad06121fd7981338fe188464491bea371f85125bfb4fc01fb5cad606613b1e" }, { + "name": "mp", + "unicode": "1F1F2-1F1F5", + "digest": "89ad06121fd7981338fe188464491bea371f85125bfb4fc01fb5cad606613b1e" + }, + { "name": "flag_mq", "unicode": "1F1F2-1F1F6", "digest": "98176f3af823b26a3657a17c5073ee22367898b40bd3973de76329aa87ca5a2e" }, { + "name": "mq", + "unicode": "1F1F2-1F1F6", + "digest": "98176f3af823b26a3657a17c5073ee22367898b40bd3973de76329aa87ca5a2e" + }, + { "name": "flag_mr", "unicode": "1F1F2-1F1F7", "digest": "cc3e705ad84f83fe2d544385c39564743024dab26595d62469b35fdb791f6015" }, { + "name": "mr", + "unicode": "1F1F2-1F1F7", + "digest": "cc3e705ad84f83fe2d544385c39564743024dab26595d62469b35fdb791f6015" + }, + { "name": "flag_ms", "unicode": "1F1F2-1F1F8", "digest": "465e3d5700b557f2589bd6e34a0c6b12c634a6ed4dcfbee3c1c841c5de3413f0" }, { + "name": "ms", + "unicode": "1F1F2-1F1F8", + "digest": "465e3d5700b557f2589bd6e34a0c6b12c634a6ed4dcfbee3c1c841c5de3413f0" + }, + { "name": "flag_mt", "unicode": "1F1F2-1F1F9", "digest": "e610ba22d8d8ad750ed10dff8e1b4d89bc34f066c3424bfa77dbdc1a5d79743a" }, { + "name": "mt", + "unicode": "1F1F2-1F1F9", + "digest": "e610ba22d8d8ad750ed10dff8e1b4d89bc34f066c3424bfa77dbdc1a5d79743a" + }, + { "name": "flag_mu", "unicode": "1F1F2-1F1FA", "digest": "3daf015d3b95218677dafbb282b7804686aa68875a6bd1d70c165b7b149e19cb" }, { + "name": "mu", + "unicode": "1F1F2-1F1FA", + "digest": "3daf015d3b95218677dafbb282b7804686aa68875a6bd1d70c165b7b149e19cb" + }, + { "name": "flag_mv", "unicode": "1F1F2-1F1FB", "digest": "d30e4bfd04f08177de92f3c175600aaafa89b9668bbe2b83f35f07a74382065c" }, { + "name": "mv", + "unicode": "1F1F2-1F1FB", + "digest": "d30e4bfd04f08177de92f3c175600aaafa89b9668bbe2b83f35f07a74382065c" + }, + { "name": "flag_mw", "unicode": "1F1F2-1F1FC", "digest": "f364b1c8bfda3f86b5e26422eedc571ba11e312dcc634197631a6840cb22aede" }, { + "name": "mw", + "unicode": "1F1F2-1F1FC", + "digest": "f364b1c8bfda3f86b5e26422eedc571ba11e312dcc634197631a6840cb22aede" + }, + { "name": "flag_mx", "unicode": "1F1F2-1F1FD", "digest": "eafb02ec0be9cefab7cef7c426c7d860d98e4947f4da04054154dc86d8f487c4" }, { + "name": "mx", + "unicode": "1F1F2-1F1FD", + "digest": "eafb02ec0be9cefab7cef7c426c7d860d98e4947f4da04054154dc86d8f487c4" + }, + { "name": "flag_my", "unicode": "1F1F2-1F1FE", "digest": "9a690b357bc6b970781bd122c1e546ade3ccb73d930c2af1008b82027e36c7cf" }, { + "name": "my", + "unicode": "1F1F2-1F1FE", + "digest": "9a690b357bc6b970781bd122c1e546ade3ccb73d930c2af1008b82027e36c7cf" + }, + { "name": "flag_mz", "unicode": "1F1F2-1F1FF", "digest": "36d0548ebfef9e0443ec1d0597ebfa6e95c25b997381f30c8c74008820743bb9" }, { + "name": "mz", + "unicode": "1F1F2-1F1FF", + "digest": "36d0548ebfef9e0443ec1d0597ebfa6e95c25b997381f30c8c74008820743bb9" + }, + { "name": "flag_na", "unicode": "1F1F3-1F1E6", "digest": "4989dc9452b0bdfa101cfd3b7c83ef1195a7e45128b9ed00193fe712a6d02fca" }, { + "name": "na", + "unicode": "1F1F3-1F1E6", + "digest": "4989dc9452b0bdfa101cfd3b7c83ef1195a7e45128b9ed00193fe712a6d02fca" + }, + { "name": "flag_nc", "unicode": "1F1F3-1F1E8", "digest": "7fc9d865eebf729d5496c4cd7576476ec599f65b379d4a6df66b4e399553c2eb" }, { + "name": "nc", + "unicode": "1F1F3-1F1E8", + "digest": "7fc9d865eebf729d5496c4cd7576476ec599f65b379d4a6df66b4e399553c2eb" + }, + { "name": "flag_ne", "unicode": "1F1F3-1F1EA", "digest": "d3f10fb44ec44a04112bc66d05f0a44c6ec46dae73cfd3fe26cdc8b32ec06713" }, { + "name": "ne", + "unicode": "1F1F3-1F1EA", + "digest": "d3f10fb44ec44a04112bc66d05f0a44c6ec46dae73cfd3fe26cdc8b32ec06713" + }, + { "name": "flag_nf", "unicode": "1F1F3-1F1EB", "digest": "d390e0d52215a025380af221ba9e955e5886edbb4c9f4b124f2fb60a8e019e42" }, { + "name": "nf", + "unicode": "1F1F3-1F1EB", + "digest": "d390e0d52215a025380af221ba9e955e5886edbb4c9f4b124f2fb60a8e019e42" + }, + { "name": "flag_ng", "unicode": "1F1F3-1F1EC", "digest": "e69d1bb8f1db4a0c295c90dda23d8f97c2dea59f9a2da2ecb0e9a1dc4dbea101" }, { + "name": "nigeria", + "unicode": "1F1F3-1F1EC", + "digest": "e69d1bb8f1db4a0c295c90dda23d8f97c2dea59f9a2da2ecb0e9a1dc4dbea101" + }, + { "name": "flag_ni", "unicode": "1F1F3-1F1EE", "digest": "dbaccc942637469b0ee75bd5f956958c3c5a89d8f69b69c96f02ab6594124894" }, { + "name": "ni", + "unicode": "1F1F3-1F1EE", + "digest": "dbaccc942637469b0ee75bd5f956958c3c5a89d8f69b69c96f02ab6594124894" + }, + { "name": "flag_nl", "unicode": "1F1F3-1F1F1", "digest": "bda2eb0315763c3c19d37c664dab1ee4280f20888a0ca57677fd33cfa4240910" }, { + "name": "nl", + "unicode": "1F1F3-1F1F1", + "digest": "bda2eb0315763c3c19d37c664dab1ee4280f20888a0ca57677fd33cfa4240910" + }, + { "name": "flag_no", "unicode": "1F1F3-1F1F4", "digest": "42b49dec756a220781ea271ca8fbcaba524dc3b38d5d8f999bfaa40ef9ebd302" }, { + "name": "no", + "unicode": "1F1F3-1F1F4", + "digest": "42b49dec756a220781ea271ca8fbcaba524dc3b38d5d8f999bfaa40ef9ebd302" + }, + { "name": "flag_np", "unicode": "1F1F3-1F1F5", "digest": "b5259257db079235310d5d9537d2b5b61ae0326bc8920ba13084b009844e2957" }, { + "name": "np", + "unicode": "1F1F3-1F1F5", + "digest": "b5259257db079235310d5d9537d2b5b61ae0326bc8920ba13084b009844e2957" + }, + { "name": "flag_nr", "unicode": "1F1F3-1F1F7", "digest": "1bd7d1fe2c3a5e98cfd4dff6e8d6dd6d3c74f0051ad615587d77d2291a9784cc" }, { + "name": "nr", + "unicode": "1F1F3-1F1F7", + "digest": "1bd7d1fe2c3a5e98cfd4dff6e8d6dd6d3c74f0051ad615587d77d2291a9784cc" + }, + { "name": "flag_nu", "unicode": "1F1F3-1F1FA", "digest": "e2a7a398e07d2232147cc0917d72d18b519246d3d314e9f6f03dcf98d312d4ce" }, { + "name": "nu", + "unicode": "1F1F3-1F1FA", + "digest": "e2a7a398e07d2232147cc0917d72d18b519246d3d314e9f6f03dcf98d312d4ce" + }, + { "name": "flag_nz", "unicode": "1F1F3-1F1FF", "digest": "ce8b1cb87dae3a3ec865575b57a0b4987a7f4bd3f170e7b210dd764fc2588cd4" }, { + "name": "nz", + "unicode": "1F1F3-1F1FF", + "digest": "ce8b1cb87dae3a3ec865575b57a0b4987a7f4bd3f170e7b210dd764fc2588cd4" + }, + { "name": "flag_om", "unicode": "1F1F4-1F1F2", "digest": "29da72505a276a8a372a00c197388ebc5098c221cab26b3ff755bd62b10f740f" }, { + "name": "om", + "unicode": "1F1F4-1F1F2", + "digest": "29da72505a276a8a372a00c197388ebc5098c221cab26b3ff755bd62b10f740f" + }, + { "name": "flag_pa", "unicode": "1F1F5-1F1E6", "digest": "180b673c9aceea43a8b55823a82d80600257e4982d0757d129860e3d8a14f458" }, { + "name": "pa", + "unicode": "1F1F5-1F1E6", + "digest": "180b673c9aceea43a8b55823a82d80600257e4982d0757d129860e3d8a14f458" + }, + { "name": "flag_pe", "unicode": "1F1F5-1F1EA", "digest": "b61823ea2cd91e371e40832df5764558b81d44fac41030827a3f6d2564643c00" }, { + "name": "pe", + "unicode": "1F1F5-1F1EA", + "digest": "b61823ea2cd91e371e40832df5764558b81d44fac41030827a3f6d2564643c00" + }, + { "name": "flag_pf", "unicode": "1F1F5-1F1EB", "digest": "e560421911f4af90c73a0dbdf8f42e69316003799304c9394fb127e3b83326fa" }, { + "name": "pf", + "unicode": "1F1F5-1F1EB", + "digest": "e560421911f4af90c73a0dbdf8f42e69316003799304c9394fb127e3b83326fa" + }, + { "name": "flag_pg", "unicode": "1F1F5-1F1EC", "digest": "880e87db2ce0eac38db037683a5db46fd6ce30623cf56ae4a93a747103570044" }, { + "name": "pg", + "unicode": "1F1F5-1F1EC", + "digest": "880e87db2ce0eac38db037683a5db46fd6ce30623cf56ae4a93a747103570044" + }, + { "name": "flag_ph", "unicode": "1F1F5-1F1ED", "digest": "49aae2f56bfd1385741dc76857aa1f1459778b2d39a1c955e469c5367585bfd5" }, { + "name": "ph", + "unicode": "1F1F5-1F1ED", + "digest": "49aae2f56bfd1385741dc76857aa1f1459778b2d39a1c955e469c5367585bfd5" + }, + { "name": "flag_pk", "unicode": "1F1F5-1F1F0", "digest": "64379dbfc932df3a07935b5cfa11ca151f761d3728939e982604e12c663cd646" }, { + "name": "pk", + "unicode": "1F1F5-1F1F0", + "digest": "64379dbfc932df3a07935b5cfa11ca151f761d3728939e982604e12c663cd646" + }, + { "name": "flag_pl", "unicode": "1F1F5-1F1F1", "digest": "3b688b074c2735d3dea0b7ab74b80eba243ce50cb05d68e585c9d701c1f14617" }, { + "name": "pl", + "unicode": "1F1F5-1F1F1", + "digest": "3b688b074c2735d3dea0b7ab74b80eba243ce50cb05d68e585c9d701c1f14617" + }, + { "name": "flag_pm", "unicode": "1F1F5-1F1F2", "digest": "a13a69ee3131501dd8138173cfb669a35ee8039d84aa665e69dd7f0d0aa3e717" }, { + "name": "pm", + "unicode": "1F1F5-1F1F2", + "digest": "a13a69ee3131501dd8138173cfb669a35ee8039d84aa665e69dd7f0d0aa3e717" + }, + { "name": "flag_pn", "unicode": "1F1F5-1F1F3", "digest": "d7ae3985cf66024e4a3001e79a8efbb3e75571f2b0abbd0fb87fc1efc795a2b3" }, { + "name": "pn", + "unicode": "1F1F5-1F1F3", + "digest": "d7ae3985cf66024e4a3001e79a8efbb3e75571f2b0abbd0fb87fc1efc795a2b3" + }, + { "name": "flag_pr", "unicode": "1F1F5-1F1F7", "digest": "4910dc984bc908158506b770f28af56150cbb4509a4291947dfa2479b9e4b308" }, { + "name": "pr", + "unicode": "1F1F5-1F1F7", + "digest": "4910dc984bc908158506b770f28af56150cbb4509a4291947dfa2479b9e4b308" + }, + { "name": "flag_ps", "unicode": "1F1F5-1F1F8", "digest": "b2bca7619fced25de94d7bd398537857460348a552e7d73d189aef3f428e6a13" }, { + "name": "ps", + "unicode": "1F1F5-1F1F8", + "digest": "b2bca7619fced25de94d7bd398537857460348a552e7d73d189aef3f428e6a13" + }, + { "name": "flag_pt", "unicode": "1F1F5-1F1F9", "digest": "177282613b4b8b4d9551f1da6a1c3f66f1b96cf67c71c7d164213b26b3237395" }, { + "name": "pt", + "unicode": "1F1F5-1F1F9", + "digest": "177282613b4b8b4d9551f1da6a1c3f66f1b96cf67c71c7d164213b26b3237395" + }, + { "name": "flag_pw", "unicode": "1F1F5-1F1FC", "digest": "2ff42a14bdc7df76b5f989dca381f94765032b26ae47d47b97844abde458cefe" }, { + "name": "pw", + "unicode": "1F1F5-1F1FC", + "digest": "2ff42a14bdc7df76b5f989dca381f94765032b26ae47d47b97844abde458cefe" + }, + { "name": "flag_py", "unicode": "1F1F5-1F1FE", "digest": "80169b69a46c4c67d0090dc2c6bf05d1a14f133ac7ae56f811547e8e8f70d81b" }, { + "name": "py", + "unicode": "1F1F5-1F1FE", + "digest": "80169b69a46c4c67d0090dc2c6bf05d1a14f133ac7ae56f811547e8e8f70d81b" + }, + { "name": "flag_qa", "unicode": "1F1F6-1F1E6", "digest": "589b44b975aa97426afb8db7f8b355491fca246b693903485824bf0f5a6953a2" }, { + "name": "qa", + "unicode": "1F1F6-1F1E6", + "digest": "589b44b975aa97426afb8db7f8b355491fca246b693903485824bf0f5a6953a2" + }, + { "name": "flag_re", "unicode": "1F1F7-1F1EA", "digest": "77d242261742831a142c9ec74cd17d76b1e6d1af751ff3c6a356646744bc798a" }, { + "name": "re", + "unicode": "1F1F7-1F1EA", + "digest": "77d242261742831a142c9ec74cd17d76b1e6d1af751ff3c6a356646744bc798a" + }, + { "name": "flag_ro", "unicode": "1F1F7-1F1F4", "digest": "d7d17026ea81f27456983722540f9a23343a3a1b22e7697c4fba118ce8b4719e" }, { + "name": "ro", + "unicode": "1F1F7-1F1F4", + "digest": "d7d17026ea81f27456983722540f9a23343a3a1b22e7697c4fba118ce8b4719e" + }, + { "name": "flag_rs", "unicode": "1F1F7-1F1F8", "digest": "e466a18cc0368e623d3fe33a036c1e88db91ae24f7510e17caacc85c41f1bac8" }, { + "name": "rs", + "unicode": "1F1F7-1F1F8", + "digest": "e466a18cc0368e623d3fe33a036c1e88db91ae24f7510e17caacc85c41f1bac8" + }, + { "name": "flag_ru", "unicode": "1F1F7-1F1FA", "digest": "86bf53a62dfc4c434d910f43df70f430fc67c0070fe3fc466c4fbfd6a5d8e646" }, { + "name": "ru", + "unicode": "1F1F7-1F1FA", + "digest": "86bf53a62dfc4c434d910f43df70f430fc67c0070fe3fc466c4fbfd6a5d8e646" + }, + { "name": "flag_rw", "unicode": "1F1F7-1F1FC", "digest": "38ec5a01896c9747a8dbf865d5e8584770e587253b7af3d3b9c36cd993f67518" }, { + "name": "rw", + "unicode": "1F1F7-1F1FC", + "digest": "38ec5a01896c9747a8dbf865d5e8584770e587253b7af3d3b9c36cd993f67518" + }, + { "name": "flag_sa", "unicode": "1F1F8-1F1E6", "digest": "a44d0b145f2a0b68eace24ecfd27519e9525ec764836728bc9c1fe96ccb811a0" }, { + "name": "saudiarabia", + "unicode": "1F1F8-1F1E6", + "digest": "a44d0b145f2a0b68eace24ecfd27519e9525ec764836728bc9c1fe96ccb811a0" + }, + { + "name": "saudi", + "unicode": "1F1F8-1F1E6", + "digest": "a44d0b145f2a0b68eace24ecfd27519e9525ec764836728bc9c1fe96ccb811a0" + }, + { "name": "flag_sb", "unicode": "1F1F8-1F1E7", "digest": "8ffa24c5cb92be4dbe43f6cd85b61b9608a3101bd78ebccff4fe99c209b3e241" }, { + "name": "sb", + "unicode": "1F1F8-1F1E7", + "digest": "8ffa24c5cb92be4dbe43f6cd85b61b9608a3101bd78ebccff4fe99c209b3e241" + }, + { "name": "flag_sc", "unicode": "1F1F8-1F1E8", "digest": "227d090ac2cbf317e594567b6114b5063a13cfe33abf990d37b200debcfadabb" }, { + "name": "sc", + "unicode": "1F1F8-1F1E8", + "digest": "227d090ac2cbf317e594567b6114b5063a13cfe33abf990d37b200debcfadabb" + }, + { "name": "flag_sd", "unicode": "1F1F8-1F1E9", "digest": "350f3332e8ea1138e54facc870dd0fea5f2ab7d3fd4baa02ed8627ae79642f6c" }, { + "name": "sd", + "unicode": "1F1F8-1F1E9", + "digest": "350f3332e8ea1138e54facc870dd0fea5f2ab7d3fd4baa02ed8627ae79642f6c" + }, + { "name": "flag_se", "unicode": "1F1F8-1F1EA", "digest": "c1b09f36c263727de83b54376f05e083a17a61941af9a1640b826629256a280d" }, { + "name": "se", + "unicode": "1F1F8-1F1EA", + "digest": "c1b09f36c263727de83b54376f05e083a17a61941af9a1640b826629256a280d" + }, + { "name": "flag_sg", "unicode": "1F1F8-1F1EC", "digest": "e6fc26920dfc07e4fd3c8d897de9c607e0bf48a3b64a13630c858d707a8e7660" }, { + "name": "sg", + "unicode": "1F1F8-1F1EC", + "digest": "e6fc26920dfc07e4fd3c8d897de9c607e0bf48a3b64a13630c858d707a8e7660" + }, + { "name": "flag_sh", "unicode": "1F1F8-1F1ED", "digest": "f2c22ab0eb49e3104c35f1c0268b1e63c3a67f41b0cfa9861b189525988e53b6" }, { + "name": "sh", + "unicode": "1F1F8-1F1ED", + "digest": "f2c22ab0eb49e3104c35f1c0268b1e63c3a67f41b0cfa9861b189525988e53b6" + }, + { "name": "flag_si", "unicode": "1F1F8-1F1EE", "digest": "1ef0b10e498f71591322f9d8ec122d39838f479370cf7ee922560986ef6c4f2e" }, { + "name": "si", + "unicode": "1F1F8-1F1EE", + "digest": "1ef0b10e498f71591322f9d8ec122d39838f479370cf7ee922560986ef6c4f2e" + }, + { "name": "flag_sj", "unicode": "1F1F8-1F1EF", "digest": "ce913b007f84a9cba2add8d754aa791901624c60e4200de426dfa25271cb0f78" }, { + "name": "sj", + "unicode": "1F1F8-1F1EF", + "digest": "ce913b007f84a9cba2add8d754aa791901624c60e4200de426dfa25271cb0f78" + }, + { "name": "flag_sk", "unicode": "1F1F8-1F1F0", "digest": "d8f8fc4024c82f906effe98facbef9d543fb3708b1134dc502c74dc4a442b30a" }, { + "name": "sk", + "unicode": "1F1F8-1F1F0", + "digest": "d8f8fc4024c82f906effe98facbef9d543fb3708b1134dc502c74dc4a442b30a" + }, + { "name": "flag_sl", "unicode": "1F1F8-1F1F1", "digest": "dd7fd0452498d8d1c894cf0d5a662ddff9c5bcc02148bdc3dc7e6f25d0bb586e" }, { + "name": "sl", + "unicode": "1F1F8-1F1F1", + "digest": "dd7fd0452498d8d1c894cf0d5a662ddff9c5bcc02148bdc3dc7e6f25d0bb586e" + }, + { "name": "flag_sm", "unicode": "1F1F8-1F1F2", "digest": "2b499606aee2b5cbf4037338753c80a4c8f75f4abcef2c8657bd9337e602bbd3" }, { + "name": "sm", + "unicode": "1F1F8-1F1F2", + "digest": "2b499606aee2b5cbf4037338753c80a4c8f75f4abcef2c8657bd9337e602bbd3" + }, + { "name": "flag_sn", "unicode": "1F1F8-1F1F3", "digest": "03b46a9d8b129da13f60c23b820b04fba52050ca58a41b859ad57d5c3cc2515d" }, { + "name": "sn", + "unicode": "1F1F8-1F1F3", + "digest": "03b46a9d8b129da13f60c23b820b04fba52050ca58a41b859ad57d5c3cc2515d" + }, + { "name": "flag_so", "unicode": "1F1F8-1F1F4", "digest": "ea416b6a05ddc5b16291ebe5101735360b08c834d55ac82c663ac1dd3e459048" }, { + "name": "so", + "unicode": "1F1F8-1F1F4", + "digest": "ea416b6a05ddc5b16291ebe5101735360b08c834d55ac82c663ac1dd3e459048" + }, + { "name": "flag_sr", "unicode": "1F1F8-1F1F7", "digest": "012179fbcbcb7343e7b09d33e283fb63c7964a6eca35ccb9407d468e495a9874" }, { + "name": "sr", + "unicode": "1F1F8-1F1F7", + "digest": "012179fbcbcb7343e7b09d33e283fb63c7964a6eca35ccb9407d468e495a9874" + }, + { "name": "flag_ss", "unicode": "1F1F8-1F1F8", "digest": "6723150482c640643c9dd7e33ea749f4a8b46aceacbd4f5e11aa33b3ee13aab7" }, { + "name": "ss", + "unicode": "1F1F8-1F1F8", + "digest": "6723150482c640643c9dd7e33ea749f4a8b46aceacbd4f5e11aa33b3ee13aab7" + }, + { "name": "flag_st", "unicode": "1F1F8-1F1F9", "digest": "0947fcec2e3cb1b0e9943c3d00891e8ee226e8d0532e9b1fe807ddf2e8fbc49d" }, { + "name": "st", + "unicode": "1F1F8-1F1F9", + "digest": "0947fcec2e3cb1b0e9943c3d00891e8ee226e8d0532e9b1fe807ddf2e8fbc49d" + }, + { "name": "flag_sv", "unicode": "1F1F8-1F1FB", "digest": "ce7e583db833c4b10e2f7a2d09b97bb522c02e96ea0b3f3a48a955f7d8f970d8" }, { + "name": "sv", + "unicode": "1F1F8-1F1FB", + "digest": "ce7e583db833c4b10e2f7a2d09b97bb522c02e96ea0b3f3a48a955f7d8f970d8" + }, + { "name": "flag_sx", "unicode": "1F1F8-1F1FD", "digest": "c01fb238c7ba439f24a5ef821b6457f2a0fd0b99a1b2d02395bed87f0a4a88e5" }, { + "name": "sx", + "unicode": "1F1F8-1F1FD", + "digest": "c01fb238c7ba439f24a5ef821b6457f2a0fd0b99a1b2d02395bed87f0a4a88e5" + }, + { "name": "flag_sy", "unicode": "1F1F8-1F1FE", "digest": "a77d87ef98c96140c59998d10d94837e2a056dd3ac5c7522e89e5c62eac69e69" }, { + "name": "sy", + "unicode": "1F1F8-1F1FE", + "digest": "a77d87ef98c96140c59998d10d94837e2a056dd3ac5c7522e89e5c62eac69e69" + }, + { "name": "flag_sz", "unicode": "1F1F8-1F1FF", "digest": "2904ad01040a9107ad556ec4c2561781d96746005cca250babb1127b8ba21050" }, { + "name": "sz", + "unicode": "1F1F8-1F1FF", + "digest": "2904ad01040a9107ad556ec4c2561781d96746005cca250babb1127b8ba21050" + }, + { "name": "flag_ta", "unicode": "1F1F9-1F1E6", "digest": "eda84db90e1a8854e8ff3c15b3b38ee65f7d6532b76970a6fbac304c30d8c959" }, { + "name": "ta", + "unicode": "1F1F9-1F1E6", + "digest": "eda84db90e1a8854e8ff3c15b3b38ee65f7d6532b76970a6fbac304c30d8c959" + }, + { "name": "flag_tc", "unicode": "1F1F9-1F1E8", "digest": "4628fdf6dc598a2846beefe97f7d4c6812f4961394cec132924b44bbe79b3322" }, { + "name": "tc", + "unicode": "1F1F9-1F1E8", + "digest": "4628fdf6dc598a2846beefe97f7d4c6812f4961394cec132924b44bbe79b3322" + }, + { "name": "flag_td", "unicode": "1F1F9-1F1E9", "digest": "125ff31e4285cb2a5493a52a2703ebe8e7138b918ec4dae3d0f8693632372df6" }, { + "name": "td", + "unicode": "1F1F9-1F1E9", + "digest": "125ff31e4285cb2a5493a52a2703ebe8e7138b918ec4dae3d0f8693632372df6" + }, + { "name": "flag_tf", "unicode": "1F1F9-1F1EB", "digest": "489d591e11764ac341f2234020f7879db782b8f673fc9aae425fd713e4082334" }, { + "name": "tf", + "unicode": "1F1F9-1F1EB", + "digest": "489d591e11764ac341f2234020f7879db782b8f673fc9aae425fd713e4082334" + }, + { "name": "flag_tg", "unicode": "1F1F9-1F1EC", "digest": "4ceedfcfcc22cd14d9add9d86d6748447995f19f7095fa4be883e21eb1aa86bc" }, { + "name": "tg", + "unicode": "1F1F9-1F1EC", + "digest": "4ceedfcfcc22cd14d9add9d86d6748447995f19f7095fa4be883e21eb1aa86bc" + }, + { "name": "flag_th", "unicode": "1F1F9-1F1ED", "digest": "2798cc660af1c5dc4891c30aded3a53d7cfa0af128cc495df8141907b165902d" }, { + "name": "th", + "unicode": "1F1F9-1F1ED", + "digest": "2798cc660af1c5dc4891c30aded3a53d7cfa0af128cc495df8141907b165902d" + }, + { "name": "flag_tj", "unicode": "1F1F9-1F1EF", "digest": "0483506fc5b5f2d4fc18ea3cd2f8a5da985d68fe4bf90bd3fd05e67e38f32398" }, { + "name": "tj", + "unicode": "1F1F9-1F1EF", + "digest": "0483506fc5b5f2d4fc18ea3cd2f8a5da985d68fe4bf90bd3fd05e67e38f32398" + }, + { "name": "flag_tk", "unicode": "1F1F9-1F1F0", "digest": "d5d4a8c6ce3207731b7c154a9d8d8fa2af055a48f03b3cbbcfd3317d3b8a75f2" }, { + "name": "tk", + "unicode": "1F1F9-1F1F0", + "digest": "d5d4a8c6ce3207731b7c154a9d8d8fa2af055a48f03b3cbbcfd3317d3b8a75f2" + }, + { "name": "flag_tl", "unicode": "1F1F9-1F1F1", "digest": "7a2ba8f91a6b627c60c88244223a9b9d0c12707f50b174f9c2eca07dd3440df7" }, { + "name": "tl", + "unicode": "1F1F9-1F1F1", + "digest": "7a2ba8f91a6b627c60c88244223a9b9d0c12707f50b174f9c2eca07dd3440df7" + }, + { "name": "flag_tm", "unicode": "1F1F9-1F1F2", "digest": "adcf5f23adcf983ce626b44559482f8728251eab34b3ff5d8b125112f3a1010f" }, { + "name": "turkmenistan", + "unicode": "1F1F9-1F1F2", + "digest": "adcf5f23adcf983ce626b44559482f8728251eab34b3ff5d8b125112f3a1010f" + }, + { "name": "flag_tn", "unicode": "1F1F9-1F1F3", "digest": "5ee690ee1f3c3c0cba9b36efdef902894ec59cefbc60c4baa341efd3d7bb9ba2" }, { + "name": "tn", + "unicode": "1F1F9-1F1F3", + "digest": "5ee690ee1f3c3c0cba9b36efdef902894ec59cefbc60c4baa341efd3d7bb9ba2" + }, + { "name": "flag_to", "unicode": "1F1F9-1F1F4", "digest": "cde8672ca25b0e3a423865283fab9bc3ab10f472e04979b3b2f8032b71e96300" }, { + "name": "to", + "unicode": "1F1F9-1F1F4", + "digest": "cde8672ca25b0e3a423865283fab9bc3ab10f472e04979b3b2f8032b71e96300" + }, + { "name": "flag_tr", "unicode": "1F1F9-1F1F7", "digest": "3d83c03ed084cfc81fa633310382acd7213e1eaa19d0ed97d142e7824032b55d" }, { + "name": "tr", + "unicode": "1F1F9-1F1F7", + "digest": "3d83c03ed084cfc81fa633310382acd7213e1eaa19d0ed97d142e7824032b55d" + }, + { "name": "flag_tt", "unicode": "1F1F9-1F1F9", "digest": "d66d272ac27e2b398289d6b60128ccd3508aeb1f4a00a3920c5e6a21bfe357ed" }, { + "name": "tt", + "unicode": "1F1F9-1F1F9", + "digest": "d66d272ac27e2b398289d6b60128ccd3508aeb1f4a00a3920c5e6a21bfe357ed" + }, + { "name": "flag_tv", "unicode": "1F1F9-1F1FB", "digest": "8716527383854cf1569f737d0f0f9ad77b46747255f24e02f5b2fbc850c2e35c" }, { + "name": "tuvalu", + "unicode": "1F1F9-1F1FB", + "digest": "8716527383854cf1569f737d0f0f9ad77b46747255f24e02f5b2fbc850c2e35c" + }, + { "name": "flag_tw", "unicode": "1F1F9-1F1FC", "digest": "fb17b97e18e4423c5f60d60ec3ec60b917be579fc4dd9b5b23236786dcb35108" }, { + "name": "tw", + "unicode": "1F1F9-1F1FC", + "digest": "fb17b97e18e4423c5f60d60ec3ec60b917be579fc4dd9b5b23236786dcb35108" + }, + { "name": "flag_tz", "unicode": "1F1F9-1F1FF", "digest": "a8a8cf57ae5227cb54620bf31d2d6e154d2067d6d049b8db64bc4e538222948b" }, { + "name": "tz", + "unicode": "1F1F9-1F1FF", + "digest": "a8a8cf57ae5227cb54620bf31d2d6e154d2067d6d049b8db64bc4e538222948b" + }, + { "name": "flag_ua", "unicode": "1F1FA-1F1E6", "digest": "03aca4b3ffd60d944a5793eb7530f8d8ae527782f642f6606194e46ee314b12c" }, { + "name": "ua", + "unicode": "1F1FA-1F1E6", + "digest": "03aca4b3ffd60d944a5793eb7530f8d8ae527782f642f6606194e46ee314b12c" + }, + { "name": "flag_ug", "unicode": "1F1FA-1F1EC", "digest": "70226a1585e88390b3b815b8b79a0ddb36d2961c6b465c4ff72aa444abfe982e" }, { + "name": "ug", + "unicode": "1F1FA-1F1EC", + "digest": "70226a1585e88390b3b815b8b79a0ddb36d2961c6b465c4ff72aa444abfe982e" + }, + { "name": "flag_um", "unicode": "1F1FA-1F1F2", "digest": "aa83bf051149acf907140a860de5de1700710e4164ae5549ad1040b24d0a142b" }, { + "name": "um", + "unicode": "1F1FA-1F1F2", + "digest": "aa83bf051149acf907140a860de5de1700710e4164ae5549ad1040b24d0a142b" + }, + { "name": "flag_us", "unicode": "1F1FA-1F1F8", "digest": "32ba2aa09a30514247e91d60762791b582f547a37d9151f98b700dff50f355ea" }, { + "name": "us", + "unicode": "1F1FA-1F1F8", + "digest": "32ba2aa09a30514247e91d60762791b582f547a37d9151f98b700dff50f355ea" + }, + { "name": "flag_uy", "unicode": "1F1FA-1F1FE", "digest": "0e01b3f1df4bdf6d616dacc9c5825151b941bf074be750e8b24a07ea5d5bcacb" }, { + "name": "uy", + "unicode": "1F1FA-1F1FE", + "digest": "0e01b3f1df4bdf6d616dacc9c5825151b941bf074be750e8b24a07ea5d5bcacb" + }, + { "name": "flag_uz", "unicode": "1F1FA-1F1FF", "digest": "903029ce83812a2134f24b65db35b183443a440ea5fecaa6ef7dcaaf65b2519c" }, { + "name": "uz", + "unicode": "1F1FA-1F1FF", + "digest": "903029ce83812a2134f24b65db35b183443a440ea5fecaa6ef7dcaaf65b2519c" + }, + { "name": "flag_va", "unicode": "1F1FB-1F1E6", "digest": "fd3c1c5d0ac030e838f807288912c98a3e258f87901e252e46942a4dab9f8cb7" }, { + "name": "va", + "unicode": "1F1FB-1F1E6", + "digest": "fd3c1c5d0ac030e838f807288912c98a3e258f87901e252e46942a4dab9f8cb7" + }, + { "name": "flag_vc", "unicode": "1F1FB-1F1E8", "digest": "7cd554ea8ca817b5366701160274587ab44167ae5a89c430bbaf237ea18b7421" }, { + "name": "vc", + "unicode": "1F1FB-1F1E8", + "digest": "7cd554ea8ca817b5366701160274587ab44167ae5a89c430bbaf237ea18b7421" + }, + { "name": "flag_ve", "unicode": "1F1FB-1F1EA", "digest": "72930094fb088c1facabea07616035ec4771374358a90c3045219d087b350dd8" }, { + "name": "ve", + "unicode": "1F1FB-1F1EA", + "digest": "72930094fb088c1facabea07616035ec4771374358a90c3045219d087b350dd8" + }, + { "name": "flag_vg", "unicode": "1F1FB-1F1EC", "digest": "78a59afd368b7a8312bfdb2f49927ff09e6b8f46aab0136c0453e3319e81df49" }, { + "name": "vg", + "unicode": "1F1FB-1F1EC", + "digest": "78a59afd368b7a8312bfdb2f49927ff09e6b8f46aab0136c0453e3319e81df49" + }, + { "name": "flag_vi", "unicode": "1F1FB-1F1EE", "digest": "e070879f9605a9bae66bb84f2abf5a40c8b264baee65cd4f7a6720b826739f29" }, { + "name": "vi", + "unicode": "1F1FB-1F1EE", + "digest": "e070879f9605a9bae66bb84f2abf5a40c8b264baee65cd4f7a6720b826739f29" + }, + { "name": "flag_vn", "unicode": "1F1FB-1F1F3", "digest": "100ddf06e0f239b170f4d6cb459450bf4945281ee818f7d3c061828b80562219" }, { + "name": "vn", + "unicode": "1F1FB-1F1F3", + "digest": "100ddf06e0f239b170f4d6cb459450bf4945281ee818f7d3c061828b80562219" + }, + { "name": "flag_vu", "unicode": "1F1FB-1F1FA", "digest": "59fc9d16818295bba4f7f551598f85378cd07f2bd7e31a4eef2589aaa3847563" }, { + "name": "vu", + "unicode": "1F1FB-1F1FA", + "digest": "59fc9d16818295bba4f7f551598f85378cd07f2bd7e31a4eef2589aaa3847563" + }, + { "name": "flag_wf", "unicode": "1F1FC-1F1EB", "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee" }, { + "name": "wf", + "unicode": "1F1FC-1F1EB", + "digest": "62627702e3e3768808c12f153a527ffcc492ad74d8cdc1858cfde971efd0c8ee" + }, + { "name": "flag_white", "unicode": "1F3F3", "digest": "96307e3a28e92d1e7147a06f154ffc291ee3cd1765cf8b7bfb06412294112559" }, { + "name": "waving_white_flag", + "unicode": "1F3F3", + "digest": "96307e3a28e92d1e7147a06f154ffc291ee3cd1765cf8b7bfb06412294112559" + }, + { "name": "flag_ws", "unicode": "1F1FC-1F1F8", "digest": "0c95271d0f4b23f0d215ee0fba05cf08ecb70665d4c028e17463ecda2754b164" }, { + "name": "ws", + "unicode": "1F1FC-1F1F8", + "digest": "0c95271d0f4b23f0d215ee0fba05cf08ecb70665d4c028e17463ecda2754b164" + }, + { "name": "flag_xk", "unicode": "1F1FD-1F1F0", "digest": "713aa7d228e96f4a06d58d1fb8c2a55296c3e56842f8177ca936f3e09f50da1e" }, { + "name": "xk", + "unicode": "1F1FD-1F1F0", + "digest": "713aa7d228e96f4a06d58d1fb8c2a55296c3e56842f8177ca936f3e09f50da1e" + }, + { "name": "flag_ye", "unicode": "1F1FE-1F1EA", "digest": "3bb65bae9c913357bcae8b8b5878efc9e194ca308442ab69639c29716b49f078" }, { + "name": "ye", + "unicode": "1F1FE-1F1EA", + "digest": "3bb65bae9c913357bcae8b8b5878efc9e194ca308442ab69639c29716b49f078" + }, + { "name": "flag_yt", "unicode": "1F1FE-1F1F9", "digest": "f86c86f4c194610a3af78971fcf221ad97b9499d08f6d64476e417a2f52a611e" }, { + "name": "yt", + "unicode": "1F1FE-1F1F9", + "digest": "f86c86f4c194610a3af78971fcf221ad97b9499d08f6d64476e417a2f52a611e" + }, + { "name": "flag_za", "unicode": "1F1FF-1F1E6", "digest": "4dd4fa49a01fdcfc7c1c099a7869e0e9acba83a6a3debf6c8505ada4c796b872" }, { + "name": "za", + "unicode": "1F1FF-1F1E6", + "digest": "4dd4fa49a01fdcfc7c1c099a7869e0e9acba83a6a3debf6c8505ada4c796b872" + }, + { "name": "flag_zm", "unicode": "1F1FF-1F1F2", "digest": "ab6790d89875447de3d1c7f4713b102761bc3e9afdd714b818689e175ca03011" }, { + "name": "zm", + "unicode": "1F1FF-1F1F2", + "digest": "ab6790d89875447de3d1c7f4713b102761bc3e9afdd714b818689e175ca03011" + }, + { "name": "flag_zw", "unicode": "1F1FF-1F1FC", "digest": "9d39b934fe922174b2250f2cd1b174a548d2904091d3298f35b7cc59fbceb181" }, { + "name": "zw", + "unicode": "1F1FF-1F1FC", + "digest": "9d39b934fe922174b2250f2cd1b174a548d2904091d3298f35b7cc59fbceb181" + }, + { "name": "flags", "unicode": "1F38F", "digest": "c3f4a66786e524a5562919afcba9486113091ed205f1342e91d2f6439845ad61" @@ -3670,11 +5305,21 @@ "digest": "be59efba4bc0759af5a726c06619090ef5071bf2541611d71691dedecee6c697" }, { + "name": "clamshell_mobile_phone", + "unicode": "1F581", + "digest": "be59efba4bc0759af5a726c06619090ef5071bf2541611d71691dedecee6c697" + }, + { "name": "floppy_black", "unicode": "1F5AA", "digest": "9022f51bb09c5130c6d46bb2accb159bed6f54d6fbffda6ecad62965ebc958ea" }, { + "name": "black_hard_shell_floppy_disk", + "unicode": "1F5AA", + "digest": "9022f51bb09c5130c6d46bb2accb159bed6f54d6fbffda6ecad62965ebc958ea" + }, + { "name": "floppy_disk", "unicode": "1F4BE", "digest": "e987961ca516032a90942ef6c398836f2da68a5981714bd172acfe7b0e369d0a" @@ -3685,6 +5330,11 @@ "digest": "ec79c400117c4506ef8cf3eebef6c42dd37e60b3079d3e98b6ccd06e517e2af0" }, { + "name": "white_hard_shell_floppy_disk", + "unicode": "1F5AB", + "digest": "ec79c400117c4506ef8cf3eebef6c42dd37e60b3079d3e98b6ccd06e517e2af0" + }, + { "name": "flower_playing_cards", "unicode": "1F3B4", "digest": "451f361050b96ba9ed8dc5b64c8a90c1316fd9b83fb818152881a54e100eea6c" @@ -3715,6 +5365,11 @@ "digest": "74f3b484771c3d6ef61cf003de25c1a59b875afa46c057b5b1d92d9f99460685" }, { + "name": "open_folder", + "unicode": "1F5C1", + "digest": "74f3b484771c3d6ef61cf003de25c1a59b875afa46c057b5b1d92d9f99460685" + }, + { "name": "football", "unicode": "1F3C8", "digest": "834fe5f431d6aa8ef1186aa79e71f813393535d273483b6af4cc4bdb8380e5b4" @@ -3735,6 +5390,11 @@ "digest": "b4081b9edea6cdab5112fdd17535051ba17710953013f5020c7c40f84a1e3247" }, { + "name": "fork_and_knife_with_plate", + "unicode": "1F37D", + "digest": "b4081b9edea6cdab5112fdd17535051ba17710953013f5020c7c40f84a1e3247" + }, + { "name": "fountain", "unicode": "26F2", "digest": "0acdca5e8f6d745a8d582d96012ec8fc55b9f5447e657ebfd998a4e332d99322" @@ -3755,16 +5415,31 @@ "digest": "6ff21063063989c6ae7dd69f4d6a781c676f9dba380d8e6f1dbac5d53b24f349" }, { + "name": "frame_with_picture", + "unicode": "1F5BC", + "digest": "6ff21063063989c6ae7dd69f4d6a781c676f9dba380d8e6f1dbac5d53b24f349" + }, + { "name": "frame_tiles", "unicode": "1F5BD", "digest": "34a5bb044b4b3ad94b116ad106f7b6747fb8612dc0e9f8ccd4313c2920508df0" }, { + "name": "frame_with_tiles", + "unicode": "1F5BD", + "digest": "34a5bb044b4b3ad94b116ad106f7b6747fb8612dc0e9f8ccd4313c2920508df0" + }, + { "name": "frame_x", "unicode": "1F5BE", "digest": "2e427688fd70361c8c59787d0722ad68abe1c3f968258ee99c0c77ce4b8a8e15" }, { + "name": "frame_with_an_x", + "unicode": "1F5BE", + "digest": "2e427688fd70361c8c59787d0722ad68abe1c3f968258ee99c0c77ce4b8a8e15" + }, + { "name": "free", "unicode": "1F193", "digest": "c1d9172a656717f78d941303c5da8790c6cd9827838d8f7dc3719afb53bcab80" @@ -3790,11 +5465,21 @@ "digest": "fb39f5c2aea98054adb02a3a0ac34a2e38d83f32cd590e9d2449e06a9702f2f5" }, { + "name": "anguished", + "unicode": "1F626", + "digest": "fb39f5c2aea98054adb02a3a0ac34a2e38d83f32cd590e9d2449e06a9702f2f5" + }, + { "name": "frowning2", "unicode": "2639", "digest": "7bb6c682a6c9f98bf3a5ae986e317fd26d1af497c857500deec2f06b6a3af5da" }, { + "name": "white_frowning_face", + "unicode": "2639", + "digest": "7bb6c682a6c9f98bf3a5ae986e317fd26d1af497c857500deec2f06b6a3af5da" + }, + { "name": "fuelpump", "unicode": "26FD", "digest": "9cbb2646c93b255bd3de87dc01aa1193ab96e39a3013975d250472ab8aae61d6" @@ -4030,6 +5715,11 @@ "digest": "2e4fe33406ca03fbb0df1596d63e903d8ee6bd78ecc3ec38a67dd2cecbc584e2" }, { + "name": "hammer_and_pick", + "unicode": "2692", + "digest": "2e4fe33406ca03fbb0df1596d63e903d8ee6bd78ecc3ec38a67dd2cecbc584e2" + }, + { "name": "hamster", "unicode": "1F439", "digest": "f47da088ff5792532a382b6e3a47d2dd7c5e6fc19abd5ff6c5ba3ce420b4192e" @@ -4040,41 +5730,81 @@ "digest": "a43e52f7cdec5e9d51497888b0988d7bbd42846ad7e492b196293fbce576d197" }, { + "name": "raised_hand_with_fingers_splayed", + "unicode": "1F590", + "digest": "a43e52f7cdec5e9d51497888b0988d7bbd42846ad7e492b196293fbce576d197" + }, + { "name": "hand_splayed_reverse", "unicode": "1F591", "digest": "ff0af0fe9def7388adca6836e5958492282b1afae99f1b6e1e65d11ba68b96db" }, { + "name": "reversed_raised_hand_with_fingers_splayed", + "unicode": "1F591", + "digest": "ff0af0fe9def7388adca6836e5958492282b1afae99f1b6e1e65d11ba68b96db" + }, + { "name": "hand_splayed_tone1", "unicode": "1F590-1F3FB", "digest": "73cceec7117280d330f8a149979190f0f355dd8d0a92821be89fb70344bb8dfe" }, { + "name": "raised_hand_with_fingers_splayed_tone1", + "unicode": "1F590-1F3FB", + "digest": "73cceec7117280d330f8a149979190f0f355dd8d0a92821be89fb70344bb8dfe" + }, + { "name": "hand_splayed_tone2", "unicode": "1F590-1F3FC", "digest": "b06fac698128f4c3a7b8ea56e8bc4de088bb5461aa0f9c84553f16b43d347145" }, { + "name": "raised_hand_with_fingers_splayed_tone2", + "unicode": "1F590-1F3FC", + "digest": "b06fac698128f4c3a7b8ea56e8bc4de088bb5461aa0f9c84553f16b43d347145" + }, + { "name": "hand_splayed_tone3", "unicode": "1F590-1F3FD", "digest": "a94ee9a2f8cdec6d2f7dd6887d1c7b8e064fcad63030c2c7c001742d72b5603e" }, { + "name": "raised_hand_with_fingers_splayed_tone3", + "unicode": "1F590-1F3FD", + "digest": "a94ee9a2f8cdec6d2f7dd6887d1c7b8e064fcad63030c2c7c001742d72b5603e" + }, + { "name": "hand_splayed_tone4", "unicode": "1F590-1F3FE", "digest": "501792b4126c6f32e755accee0fc8b4d1915e1d36c4ceaa40f3bd0066efe76c3" }, { + "name": "raised_hand_with_fingers_splayed_tone4", + "unicode": "1F590-1F3FE", + "digest": "501792b4126c6f32e755accee0fc8b4d1915e1d36c4ceaa40f3bd0066efe76c3" + }, + { "name": "hand_splayed_tone5", "unicode": "1F590-1F3FF", "digest": "22ed533d587cf44f286e2d6ad77be20b4b5f133c422af4ca51e9af86a75002d8" }, { + "name": "raised_hand_with_fingers_splayed_tone5", + "unicode": "1F590-1F3FF", + "digest": "22ed533d587cf44f286e2d6ad77be20b4b5f133c422af4ca51e9af86a75002d8" + }, + { "name": "hand_victory", "unicode": "1F594", "digest": "2d512ced4e8a438f2a346aed67310d3080f9828c748ade1be95943c32ba1c735" }, { + "name": "reversed_victory_hand", + "unicode": "1F594", + "digest": "2d512ced4e8a438f2a346aed67310d3080f9828c748ade1be95943c32ba1c735" + }, + { "name": "handbag", "unicode": "1F45C", "digest": "f1e2822c67f659b52c76821dd9db001332215a8566fc1846c89b6019c9758038" @@ -4105,6 +5835,11 @@ "digest": "d690b740ff4f58e89dfc764c6411a4e84cfedffd7694eb5efa839a642dbabd08" }, { + "name": "face_with_head_bandage", + "unicode": "1F915", + "digest": "d690b740ff4f58e89dfc764c6411a4e84cfedffd7694eb5efa839a642dbabd08" + }, + { "name": "headphones", "unicode": "1F3A7", "digest": "219da138032c01c97a94f02b211049418191a3beb3d159804b9033f5916fd3c8" @@ -4130,6 +5865,11 @@ "digest": "9751c89dcf10805f2011949ff3ddcb6bcb13de8c32ae5de9e03955e8a4235df2" }, { + "name": "heavy_heart_exclamation_mark_ornament", + "unicode": "2763", + "digest": "9751c89dcf10805f2011949ff3ddcb6bcb13de8c32ae5de9e03955e8a4235df2" + }, + { "name": "heart_eyes", "unicode": "1F60D", "digest": "335ea73efca4824e623a5a51ccdb494c8b1f5f10b4139b39b250a2a771876b0d" @@ -4145,6 +5885,11 @@ "digest": "2178829e2c85accda55d2f685544587f6de5c8398a127ae1e08ff1c4ab282204" }, { + "name": "heart_with_tip_on_the_left", + "unicode": "1F394", + "digest": "2178829e2c85accda55d2f685544587f6de5c8398a127ae1e08ff1c4ab282204" + }, + { "name": "heartbeat", "unicode": "1F493", "digest": "cd6921ce55c155873220a09416d695c4bcca1556007066d6d185e93d6561e825" @@ -4200,6 +5945,11 @@ "digest": "affbe9dd87b87ff9235b4858c59c2a73e9ed30dd5221e5b666b8d7747378a9c4" }, { + "name": "helmet_with_white_cross", + "unicode": "26D1", + "digest": "affbe9dd87b87ff9235b4858c59c2a73e9ed30dd5221e5b666b8d7747378a9c4" + }, + { "name": "herb", "unicode": "1F33F", "digest": "3c452106b1966f643751bf161fa7d1762a33e6fff381b2109bb53b55c4fdd129" @@ -4235,6 +5985,11 @@ "digest": "9980d6dd6cbd23b820747ecac4cb10974dd24b0c94b4acfe21fa87793ad065c9" }, { + "name": "house_buildings", + "unicode": "1F3D8", + "digest": "9980d6dd6cbd23b820747ecac4cb10974dd24b0c94b4acfe21fa87793ad065c9" + }, + { "name": "honey_pot", "unicode": "1F36F", "digest": "94cb1624491076b5cb145e7a309f91a7be3d4c0bed712af6a51d641eb73edee7" @@ -4290,6 +6045,11 @@ "digest": "58b829e26b5c4642942898d9c7873cb08e048fd7deaacba8292899d5d895cb2b" }, { + "name": "hot_dog", + "unicode": "1F32D", + "digest": "58b829e26b5c4642942898d9c7873cb08e048fd7deaacba8292899d5d895cb2b" + }, + { "name": "hotel", "unicode": "1F3E8", "digest": "428120a35b38a217901e10d704751eb8fdbc9f805e6eccd8aab070f4311b2085" @@ -4320,6 +6080,11 @@ "digest": "e404631e3a296bdeae3de7510da8934c32327bc0fa0f7ae4e676b61932165668" }, { + "name": "derelict_house_building", + "unicode": "1F3DA", + "digest": "e404631e3a296bdeae3de7510da8934c32327bc0fa0f7ae4e676b61932165668" + }, + { "name": "house_with_garden", "unicode": "1F3E1", "digest": "22d0d911da96b7ae3bf6692d3cf3590afbca959fc99c13e7a088f7194f43a35d" @@ -4330,6 +6095,11 @@ "digest": "68ed6c4e0eae9071cf67770a39e07a2290b4f7763170f765b3cd3ac67ae43240" }, { + "name": "hugging_face", + "unicode": "1F917", + "digest": "68ed6c4e0eae9071cf67770a39e07a2290b4f7763170f765b3cd3ac67ae43240" + }, + { "name": "hushed", "unicode": "1F62F", "digest": "69faa8e0b170ee8cf41977ca4a5154406360ed9699d5c62ecdaa01f50e8e4276" @@ -4380,6 +6150,11 @@ "digest": "59c35e77d5ee663c5d56f7d8af845ce8aeb9935e526ae4a06e02ae70e71212ca" }, { + "name": "circled_information_source", + "unicode": "1F6C8", + "digest": "59c35e77d5ee663c5d56f7d8af845ce8aeb9935e526ae4a06e02ae70e71212ca" + }, + { "name": "information_desk_person", "unicode": "1F481", "digest": "acae6d272e348aee87dd60360f16ac58cea7cb4e1ea962cc1655005c7f4aed27" @@ -4435,6 +6210,11 @@ "digest": "17f02b309b62ed9542b1d8943168302846040e420f413e56d799bb5fba7064fa" }, { + "name": "desert_island", + "unicode": "1F3DD", + "digest": "17f02b309b62ed9542b1d8943168302846040e420f413e56d799bb5fba7064fa" + }, + { "name": "izakaya_lantern", "unicode": "1F3EE", "digest": "ddb20f475aa119c3a64a55dff40f7a9dbc3a14f7ffc6cfbac89210c652f10d02" @@ -4475,6 +6255,11 @@ "digest": "3708e5e034b1c64d1268d66527e13c369aa0f8903bce9172bef773b2d1940948" }, { + "name": "up_pointing_military_airplane", + "unicode": "1F6E6", + "digest": "3708e5e034b1c64d1268d66527e13c369aa0f8903bce9172bef773b2d1940948" + }, + { "name": "joy", "unicode": "1F602", "digest": "f90cfbcb14f906f8d786b61f022c978f381fc99ca422805f605631314e101805" @@ -4505,21 +6290,41 @@ "digest": "87a7d42531d7a11dcb11b0d6d1be611ee8cec35b5d22226a8ac6083fedef4f5d" }, { + "name": "old_key", + "unicode": "1F5DD", + "digest": "87a7d42531d7a11dcb11b0d6d1be611ee8cec35b5d22226a8ac6083fedef4f5d" + }, + { "name": "keyboard", "unicode": "1F5AE", "digest": "3b254cbf19946df3af05e501d11653d89fcda91684b7248d86186f842b83bf16" }, { + "name": "wired_keyboard", + "unicode": "1F5AE", + "digest": "3b254cbf19946df3af05e501d11653d89fcda91684b7248d86186f842b83bf16" + }, + { "name": "keyboard_mouse", "unicode": "1F5A6", "digest": "95b523e55d8afeaeb06442bbe20e47f49643bb0c32d89a8cdbbccdead20532b3" }, { + "name": "keyboard_and_mouse", + "unicode": "1F5A6", + "digest": "95b523e55d8afeaeb06442bbe20e47f49643bb0c32d89a8cdbbccdead20532b3" + }, + { "name": "keyboard_with_jacks", "unicode": "1F398", "digest": "e29a0d0b8018d13458469edca13c60a882a2817957c1aa11b050684c995a47ee" }, { + "name": "musical_keyboard_with_jacks", + "unicode": "1F398", + "digest": "e29a0d0b8018d13458469edca13c60a882a2817957c1aa11b050684c995a47ee" + }, + { "name": "keycap_ten", "unicode": "1F51F", "digest": "7593aa7ffe7192a2e35c6ccec76522f6243777783c9152c7c03419835ea58c03" @@ -4540,11 +6345,21 @@ "digest": "381364ad988ec07cc3708fd60f71838092224009088fff587069b4e8ab01ee63" }, { + "name": "couplekiss_mm", + "unicode": "1F468-2764-1F48B-1F468", + "digest": "381364ad988ec07cc3708fd60f71838092224009088fff587069b4e8ab01ee63" + }, + { "name": "kiss_ww", "unicode": "1F469-2764-1F48B-1F469", "digest": "7705ca707b73f44c856ea324bdfe30ed05244c8d192d1111f6e1d62ab3f2f8a5" }, { + "name": "couplekiss_ww", + "unicode": "1F469-2764-1F48B-1F469", + "digest": "7705ca707b73f44c856ea324bdfe30ed05244c8d192d1111f6e1d62ab3f2f8a5" + }, + { "name": "kissing", "unicode": "1F617", "digest": "3142617e8b9488689bd9efc67c0e4cc71a1870df8ffc308f949eedc5c3684051" @@ -4620,6 +6435,11 @@ "digest": "f22d3be77f1daf058d04c3cbc1fd7f76b4dc069d2d300b45e63e768b08d269c5" }, { + "name": "satisfied", + "unicode": "1F606", + "digest": "f22d3be77f1daf058d04c3cbc1fd7f76b4dc069d2d300b45e63e768b08d269c5" + }, + { "name": "leaves", "unicode": "1F343", "digest": "f65e2db125564eb04fc427a49fff175d6e2dae847bd12314d5e6a131610d5ccd" @@ -4640,6 +6460,11 @@ "digest": "8052e44951afee04c87296128744b5019ec783c9ed1a231f659af6c8ddaa50f3" }, { + "name": "left_hand_telephone_receiver", + "unicode": "1F57B", + "digest": "8052e44951afee04c87296128744b5019ec783c9ed1a231f659af6c8ddaa50f3" + }, + { "name": "left_right_arrow", "unicode": "2194", "digest": "28a6945972451b1f4dadec5c55310b8868ffd9f3b0a07803287bc4e07a56e7d4" @@ -4675,6 +6500,11 @@ "digest": "3e4e9a5ac6a8dbd7909c58a9d915f16f1a0fc59cc019714ae5935f18e4704044" }, { + "name": "man_in_business_suit_levitating", + "unicode": "1F574", + "digest": "3e4e9a5ac6a8dbd7909c58a9d915f16f1a0fc59cc019714ae5935f18e4704044" + }, + { "name": "libra", "unicode": "264E", "digest": "ec8e2e7a735abc9f2bddb115fc0e09f4bdc7a164679e2b57d127f58eee1155c2" @@ -4685,36 +6515,71 @@ "digest": "f64db037fd21e5918e5de35d6a561ef4b44668e307ed351338de00fcf3e771e3" }, { + "name": "weight_lifter", + "unicode": "1F3CB", + "digest": "f64db037fd21e5918e5de35d6a561ef4b44668e307ed351338de00fcf3e771e3" + }, + { "name": "lifter_tone1", "unicode": "1F3CB-1F3FB", "digest": "f9e0d161b12c4908ac3409b11c1a77ee38f33ba018f12416545876214bfb7c01" }, { + "name": "weight_lifter_tone1", + "unicode": "1F3CB-1F3FB", + "digest": "f9e0d161b12c4908ac3409b11c1a77ee38f33ba018f12416545876214bfb7c01" + }, + { "name": "lifter_tone2", "unicode": "1F3CB-1F3FC", "digest": "631eb6ed5bd147dc6f1f8b94149abe44d62a0f78e7809e37a4bfe127c40ed98f" }, { + "name": "weight_lifter_tone2", + "unicode": "1F3CB-1F3FC", + "digest": "631eb6ed5bd147dc6f1f8b94149abe44d62a0f78e7809e37a4bfe127c40ed98f" + }, + { "name": "lifter_tone3", "unicode": "1F3CB-1F3FD", "digest": "406b5707a47d9066f016acf0b64fa695e3505acc2453758a0428de21efd7eb6d" }, { + "name": "weight_lifter_tone3", + "unicode": "1F3CB-1F3FD", + "digest": "406b5707a47d9066f016acf0b64fa695e3505acc2453758a0428de21efd7eb6d" + }, + { "name": "lifter_tone4", "unicode": "1F3CB-1F3FE", "digest": "d917164ed8c4bb1ffcc887ca256ec329e7fa1b9516eaf8c159f8b43fdb071ed6" }, { + "name": "weight_lifter_tone4", + "unicode": "1F3CB-1F3FE", + "digest": "d917164ed8c4bb1ffcc887ca256ec329e7fa1b9516eaf8c159f8b43fdb071ed6" + }, + { "name": "lifter_tone5", "unicode": "1F3CB-1F3FF", "digest": "f79ea93e8a40b3c895b693bf49eb4ce6e7b3f4413595e5881ea44839fd7fe8e5" }, { + "name": "weight_lifter_tone5", + "unicode": "1F3CB-1F3FF", + "digest": "f79ea93e8a40b3c895b693bf49eb4ce6e7b3f4413595e5881ea44839fd7fe8e5" + }, + { "name": "light_check_mark", "unicode": "1F5F8", "digest": "7842b0df8c2b6703bed0cce5d2790d394eec7120b2a245a76f375528f2729a7b" }, { + "name": "light_mark", + "unicode": "1F5F8", + "digest": "7842b0df8c2b6703bed0cce5d2790d394eec7120b2a245a76f375528f2729a7b" + }, + { "name": "light_rail", "unicode": "1F688", "digest": "7c2be55456f1332e849ff6699a26dda2e1641c280f45c9ec88dedf6d9b7b7fe2" @@ -4730,6 +6595,11 @@ "digest": "935b1076815f51fafcd860a395d0a03c536acfcea61ffcf542a377da046fa7d9" }, { + "name": "lion", + "unicode": "1F981", + "digest": "935b1076815f51fafcd860a395d0a03c536acfcea61ffcf542a377da046fa7d9" + }, + { "name": "lips", "unicode": "1F444", "digest": "e3bc20f9e210fa1711271234fe61bf1c9ddf36dd6ffc5b832c6c3a769a1e59a8" @@ -4930,6 +6800,11 @@ "digest": "f56116d09996d6d08fb5cdfb46622b545253f2649008170fc2011a9713fa875b" }, { + "name": "world_map", + "unicode": "1F5FA", + "digest": "f56116d09996d6d08fb5cdfb46622b545253f2649008170fc2011a9713fa875b" + }, + { "name": "maple_leaf", "unicode": "1F341", "digest": "40c5ee93396301911391cf6e70454b6fa8020fe5c85d3364136bcedb5d052cdb" @@ -4980,6 +6855,11 @@ "digest": "270d438b6e2155e944dc734ea3e4d02409e51f59db2db636398fbf96e5edb0e6" }, { + "name": "sports_medal", + "unicode": "1F3C5", + "digest": "270d438b6e2155e944dc734ea3e4d02409e51f59db2db636398fbf96e5edb0e6" + }, + { "name": "mega", "unicode": "1F4E3", "digest": "540ab4fd5bab041a681749b85e6de598ebcbfc4fbf5c3cdbd9ca1e8256191733" @@ -5005,31 +6885,61 @@ "digest": "45e5fac0b9b019cf217dcfd1380cafb0d03063454612178278dac1ca5f8476a6" }, { + "name": "sign_of_the_horns", + "unicode": "1F918", + "digest": "45e5fac0b9b019cf217dcfd1380cafb0d03063454612178278dac1ca5f8476a6" + }, + { "name": "metal_tone1", "unicode": "1F918-1F3FB", "digest": "9b3596fe7c063df838f0a43fb680ce10fb88e2b73c5c3324abfa357a224c17aa" }, { + "name": "sign_of_the_horns_tone1", + "unicode": "1F918-1F3FB", + "digest": "9b3596fe7c063df838f0a43fb680ce10fb88e2b73c5c3324abfa357a224c17aa" + }, + { "name": "metal_tone2", "unicode": "1F918-1F3FC", "digest": "e15a4898a0efca4354ac48d6b01ff0618ce8b110b1246a4f5d78e19b54658be6" }, { + "name": "sign_of_the_horns_tone2", + "unicode": "1F918-1F3FC", + "digest": "e15a4898a0efca4354ac48d6b01ff0618ce8b110b1246a4f5d78e19b54658be6" + }, + { "name": "metal_tone3", "unicode": "1F918-1F3FD", "digest": "c159e8179cb1907c246b432d87c5253b914fd7cebb6ac05292c4e38eff4815b0" }, { + "name": "sign_of_the_horns_tone3", + "unicode": "1F918-1F3FD", + "digest": "c159e8179cb1907c246b432d87c5253b914fd7cebb6ac05292c4e38eff4815b0" + }, + { "name": "metal_tone4", "unicode": "1F918-1F3FE", "digest": "a8a43a88028c97074321e3da56df1045db41ede58bf286c21d7ae90f222f2011" }, { + "name": "sign_of_the_horns_tone4", + "unicode": "1F918-1F3FE", + "digest": "a8a43a88028c97074321e3da56df1045db41ede58bf286c21d7ae90f222f2011" + }, + { "name": "metal_tone5", "unicode": "1F918-1F3FF", "digest": "e6611e826e867e2c73a8cadb138e4aa6365e3583dd229ff24b3e8f161904bf56" }, { + "name": "sign_of_the_horns_tone5", + "unicode": "1F918-1F3FF", + "digest": "e6611e826e867e2c73a8cadb138e4aa6365e3583dd229ff24b3e8f161904bf56" + }, + { "name": "metro", "unicode": "1F687", "digest": "532378cf385f9a7fafe2f5c8203e675be6d38798871f4c8e2c50498a1529f956" @@ -5045,6 +6955,11 @@ "digest": "f9df32cd207808f67a895d3460a215d1ecc42e377907bcd64731c02b697d4f32" }, { + "name": "studio_microphone", + "unicode": "1F399", + "digest": "f9df32cd207808f67a895d3460a215d1ecc42e377907bcd64731c02b697d4f32" + }, + { "name": "microscope", "unicode": "1F52C", "digest": "79918f5fe0a39f31f270a481f4c6e00ea49fc09d64b1ae78770971293c2b1ed8" @@ -5055,31 +6970,61 @@ "digest": "c6320b236a4a9593aeade511b52dd3114207e947458cb3b818c78737a505fdf6" }, { + "name": "reversed_hand_with_middle_finger_extended", + "unicode": "1F595", + "digest": "c6320b236a4a9593aeade511b52dd3114207e947458cb3b818c78737a505fdf6" + }, + { "name": "middle_finger_tone1", "unicode": "1F595-1F3FB", "digest": "93c7aa994856185519d576cb779bdcff3a33f7077eef98e70968125f92f02448" }, { + "name": "reversed_hand_with_middle_finger_extended_tone1", + "unicode": "1F595-1F3FB", + "digest": "93c7aa994856185519d576cb779bdcff3a33f7077eef98e70968125f92f02448" + }, + { "name": "middle_finger_tone2", "unicode": "1F595-1F3FC", "digest": "a0de802294717b80e08d9d30f5fd64eacb90b5b3b9d7a0c27d6226a22822597f" }, { + "name": "reversed_hand_with_middle_finger_extended_tone2", + "unicode": "1F595-1F3FC", + "digest": "a0de802294717b80e08d9d30f5fd64eacb90b5b3b9d7a0c27d6226a22822597f" + }, + { "name": "middle_finger_tone3", "unicode": "1F595-1F3FD", "digest": "8bbbab07c838257416bbf8377904362c07019fca9d5abf9fd048ccf6370178da" }, { + "name": "reversed_hand_with_middle_finger_extended_tone3", + "unicode": "1F595-1F3FD", + "digest": "8bbbab07c838257416bbf8377904362c07019fca9d5abf9fd048ccf6370178da" + }, + { "name": "middle_finger_tone4", "unicode": "1F595-1F3FE", "digest": "d9eed8db540fdb669c6ae5ef168b77659660589f5ddd9b66062274d335a3ef04" }, { + "name": "reversed_hand_with_middle_finger_extended_tone4", + "unicode": "1F595-1F3FE", + "digest": "d9eed8db540fdb669c6ae5ef168b77659660589f5ddd9b66062274d335a3ef04" + }, + { "name": "middle_finger_tone5", "unicode": "1F595-1F3FF", "digest": "0519c3298040e57db202294476df239edb9b23b44848bab296bc45eda7cf8664" }, { + "name": "reversed_hand_with_middle_finger_extended_tone5", + "unicode": "1F595-1F3FF", + "digest": "0519c3298040e57db202294476df239edb9b23b44848bab296bc45eda7cf8664" + }, + { "name": "military_medal", "unicode": "1F396", "digest": "bd1da0004768f404c6bb4db85d4b748f766a77ab3edb74e709d0c0064509a043" @@ -5110,6 +7055,11 @@ "digest": "3ac2f9b5409e1426eef6966938ca04cf78aeffefd43f44b6c86af4af7836e22f" }, { + "name": "money_mouth_face", + "unicode": "1F911", + "digest": "3ac2f9b5409e1426eef6966938ca04cf78aeffefd43f44b6c86af4af7836e22f" + }, + { "name": "money_with_wings", "unicode": "1F4B8", "digest": "f7f1fa502d2f6804169869aeb5ca7f0ea64bc2d6a0204f08875d65da4f8cb332" @@ -5145,11 +7095,21 @@ "digest": "4af3e4e53eaa328b0d20542ab31705a74bf9fd368cd0673b706838ce1681d3c9" }, { + "name": "lightning_mood_bubble", + "unicode": "1F5F1", + "digest": "4af3e4e53eaa328b0d20542ab31705a74bf9fd368cd0673b706838ce1681d3c9" + }, + { "name": "mood_lightning", "unicode": "1F5F2", "digest": "6784635e81ec722fd50a1c2a23b0f9679e4bf1b5ae2b5a01eeb995bc1f7a426f" }, { + "name": "lightning_mood", + "unicode": "1F5F2", + "digest": "6784635e81ec722fd50a1c2a23b0f9679e4bf1b5ae2b5a01eeb995bc1f7a426f" + }, + { "name": "mortar_board", "unicode": "1F393", "digest": "cb59edb08f75c374088b65284e4d0f77b9bc9573de3e6a5127f865431011e54c" @@ -5170,6 +7130,11 @@ "digest": "8429fb6dfeb873abdffcc179c32d4f23e91c9e6b27b06cd204fd2e83cc11189e" }, { + "name": "racing_motorcycle", + "unicode": "1F3CD", + "digest": "8429fb6dfeb873abdffcc179c32d4f23e91c9e6b27b06cd204fd2e83cc11189e" + }, + { "name": "motorway", "unicode": "1F6E3", "digest": "fc05a36c917637c135b0a60db8afcd58cee2b335070fe3888697f8026c9d11a5" @@ -5230,6 +7195,11 @@ "digest": "9939aade3d4d972ba3af16fcc6cc2454978f5426e4c92838734a44db065ce0ff" }, { + "name": "snow_capped_mountain", + "unicode": "1F3D4", + "digest": "9939aade3d4d972ba3af16fcc6cc2454978f5426e4c92838734a44db065ce0ff" + }, + { "name": "mouse", "unicode": "1F42D", "digest": "fb20b3a82f407a6316bbbac68d58018c3d5b93a9a6ae968f44ace18d1c5698d9" @@ -5245,11 +7215,21 @@ "digest": "e0d2055ccba489d24e0c0b6d2f22793efe48a734b0fd50f5af88f721b40665c0" }, { + "name": "one_button_mouse", + "unicode": "1F5AF", + "digest": "e0d2055ccba489d24e0c0b6d2f22793efe48a734b0fd50f5af88f721b40665c0" + }, + { "name": "mouse_three_button", "unicode": "1F5B1", "digest": "6a5629fee01145211cc8f4e8f59c5f1e61affed38c650502213d76c7d8861b01" }, { + "name": "three_button_mouse", + "unicode": "1F5B1", + "digest": "6a5629fee01145211cc8f4e8f59c5f1e61affed38c650502213d76c7d8861b01" + }, + { "name": "movie_camera", "unicode": "1F3A5", "digest": "d6633b89a637b64d617c3032eed74bb82d3fa732dd9975486b2b5841b473808a" @@ -5365,11 +7345,21 @@ "digest": "94efd551700aae8909b8dd7a78a54a33e070d24b2e0a10534353645084614e98" }, { + "name": "nerd_face", + "unicode": "1F913", + "digest": "94efd551700aae8909b8dd7a78a54a33e070d24b2e0a10534353645084614e98" + }, + { "name": "network", "unicode": "1F5A7", "digest": "1dbaa54deeb2328fd8a3f044e450c97ac3ff39627c598bb2f4312d677482ee06" }, { + "name": "three_networked_computers", + "unicode": "1F5A7", + "digest": "1dbaa54deeb2328fd8a3f044e450c97ac3ff39627c598bb2f4312d677482ee06" + }, + { "name": "neutral_face", "unicode": "1F610", "digest": "df01da8501e1f588049c8ed66e504e9abcce83f74ce5790f4d3dc547408f77ee" @@ -5400,6 +7390,11 @@ "digest": "0ca6b5850091f23295c970815a8e64a52e3c3dae492029ecb1e0726c2693f9bf" }, { + "name": "rolled_up_newspaper", + "unicode": "1F5DE", + "digest": "0ca6b5850091f23295c970815a8e64a52e3c3dae492029ecb1e0726c2693f9bf" + }, + { "name": "ng", "unicode": "1F196", "digest": "4994c9b795033ed788e98c4af571a1dffe28c0a1479e3b42dcae21bb08381b5f" @@ -5525,11 +7520,21 @@ "digest": "073660fdaa02ecf98d04f61f8d65d6cc447ccae3825fccaff19a2c99ebba52af" }, { + "name": "note_page", + "unicode": "1F5C9", + "digest": "073660fdaa02ecf98d04f61f8d65d6cc447ccae3825fccaff19a2c99ebba52af" + }, + { "name": "note_empty", "unicode": "1F5C6", "digest": "06b56eeaca6349bbcf1020bea98f937450a7e086db65cd5d7497748e0fb607be" }, { + "name": "empty_note_page", + "unicode": "1F5C6", + "digest": "06b56eeaca6349bbcf1020bea98f937450a7e086db65cd5d7497748e0fb607be" + }, + { "name": "notebook", "unicode": "1F4D3", "digest": "64bd4a3e7ca7b22fc704c7b7bd4d13540c16bc69b9d8dd76e69e6ad573ab3823" @@ -5545,16 +7550,31 @@ "digest": "85069e2d13540886457368a57295072aec44c7137d9223bfcf908ce1f0e5124e" }, { + "name": "note_pad", + "unicode": "1F5CA", + "digest": "85069e2d13540886457368a57295072aec44c7137d9223bfcf908ce1f0e5124e" + }, + { "name": "notepad_empty", "unicode": "1F5C7", "digest": "8be5053e74c13d8220917c5aee1f4afdecb001612886438f283b0c2a0fecf6af" }, { + "name": "empty_note_pad", + "unicode": "1F5C7", + "digest": "8be5053e74c13d8220917c5aee1f4afdecb001612886438f283b0c2a0fecf6af" + }, + { "name": "notepad_spiral", "unicode": "1F5D2", "digest": "c181b6c1cc6063ec1848e46cbbf1d8b890c53b59cdc5218311ce06889570e727" }, { + "name": "spiral_note_pad", + "unicode": "1F5D2", + "digest": "c181b6c1cc6063ec1848e46cbbf1d8b890c53b59cdc5218311ce06889570e727" + }, + { "name": "notes", "unicode": "1F3B6", "digest": "bf3868386e17eac40ac7fbabea027042027ff061daafe406c869cdd8ce94641d" @@ -5600,6 +7620,11 @@ "digest": "f8b7626cb09e229203105b9c8c7f3fbb38c0650021092fc50115ad517248644a" }, { + "name": "oil_drum", + "unicode": "1F6E2", + "digest": "f8b7626cb09e229203105b9c8c7f3fbb38c0650021092fc50115ad517248644a" + }, + { "name": "ok", "unicode": "1F197", "digest": "6b05bbab4a7104541c2f4bce553884d17ae0ad07589b19d6b53b6949c14f2269" @@ -5700,31 +7725,61 @@ "digest": "3ed599443eed25399aac999fc234c9e97f8fb6ec567e37a553c26e01021b097c" }, { + "name": "grandma", + "unicode": "1F475", + "digest": "3ed599443eed25399aac999fc234c9e97f8fb6ec567e37a553c26e01021b097c" + }, + { "name": "older_woman_tone1", "unicode": "1F475-1F3FB", "digest": "7421c5dba67cfd1eeabb2fa8faf4aa0d615d23f191cf7d7c0ad9c1fa884edfda" }, { + "name": "grandma_tone1", + "unicode": "1F475-1F3FB", + "digest": "7421c5dba67cfd1eeabb2fa8faf4aa0d615d23f191cf7d7c0ad9c1fa884edfda" + }, + { "name": "older_woman_tone2", "unicode": "1F475-1F3FC", "digest": "65edeef25648ac7f8be535df06af1286441691fa15176e99a6e83fc779aa2cde" }, { + "name": "grandma_tone2", + "unicode": "1F475-1F3FC", + "digest": "65edeef25648ac7f8be535df06af1286441691fa15176e99a6e83fc779aa2cde" + }, + { "name": "older_woman_tone3", "unicode": "1F475-1F3FD", "digest": "5d27bbcc5796227a9caec1c7612d3f691055655b96f7303e420839463d76c269" }, { + "name": "grandma_tone3", + "unicode": "1F475-1F3FD", + "digest": "5d27bbcc5796227a9caec1c7612d3f691055655b96f7303e420839463d76c269" + }, + { "name": "older_woman_tone4", "unicode": "1F475-1F3FE", "digest": "75b858e910175fc0233503d672120fd43ac035ba3fd2052fbb44df39f6e3695c" }, { + "name": "grandma_tone4", + "unicode": "1F475-1F3FE", + "digest": "75b858e910175fc0233503d672120fd43ac035ba3fd2052fbb44df39f6e3695c" + }, + { "name": "older_woman_tone5", "unicode": "1F475-1F3FF", "digest": "9da1cf10a605c470877d7f4a840f99344b1ec2e7b1ec7db61e930cde77025e3b" }, { + "name": "grandma_tone5", + "unicode": "1F475-1F3FF", + "digest": "9da1cf10a605c470877d7f4a840f99344b1ec2e7b1ec7db61e930cde77025e3b" + }, + { "name": "om_symbol", "unicode": "1F549", "digest": "c8c1c9d445b1fc50a627b71bee21fba978e04532e4685ec032a0174f51fc12bb" @@ -5810,6 +7865,11 @@ "digest": "df8c10028d29d65f144a6b789d1c3294e7b3293554c4c30d28d72dc7ba8d9a5d" }, { + "name": "optical_disc_icon", + "unicode": "1F5B8", + "digest": "df8c10028d29d65f144a6b789d1c3294e7b3293554c4c30d28d72dc7ba8d9a5d" + }, + { "name": "orange_book", "unicode": "1F4D9", "digest": "86d150ea3d62183ab7dfe2851cf7f4d1ae769b7ecbb1987b0f463e639e429598" @@ -5865,6 +7925,11 @@ "digest": "73eb33184f5f495d6c2699fafc1a8680069f82a70fbe519290c3a2ce30d1aee9" }, { + "name": "lower_left_paintbrush", + "unicode": "1F58C", + "digest": "73eb33184f5f495d6c2699fafc1a8680069f82a70fbe519290c3a2ce30d1aee9" + }, + { "name": "palm_tree", "unicode": "1F334", "digest": "1589ff4b1b87296edc0118e4aa67b3b504ed85a5b8d47e7d0c3e309d0bbf8cd6" @@ -5885,11 +7950,21 @@ "digest": "7071e031f4a100c3cb3573fbfa375360043f0276289a0818f2ffaf71b3580040" }, { + "name": "linked_paperclips", + "unicode": "1F587", + "digest": "7071e031f4a100c3cb3573fbfa375360043f0276289a0818f2ffaf71b3580040" + }, + { "name": "park", "unicode": "1F3DE", "digest": "d257f0f1b1a0134573f80ba1a5f522a91c320ee7f93a1cb64877c077e7e19b50" }, { + "name": "national_park", + "unicode": "1F3DE", + "digest": "d257f0f1b1a0134573f80ba1a5f522a91c320ee7f93a1cb64877c077e7e19b50" + }, + { "name": "parking", "unicode": "1F17F", "digest": "e1d2cfd1c57ea85003ca4df066cbba4e506bf6c4d6c790e27b2f78ad8443fabf" @@ -5915,11 +7990,21 @@ "digest": "edd605ffaa39a7905ed0958b7cc69f00f5b271e579198d2df1746ad1b3648272" }, { + "name": "double_vertical_bar", + "unicode": "23F8", + "digest": "edd605ffaa39a7905ed0958b7cc69f00f5b271e579198d2df1746ad1b3648272" + }, + { "name": "peace", "unicode": "262E", "digest": "e0ee8a5c9fb18d5db6841b21527ed8fd955abdff9ffdb7b2684dca22107015fc" }, { + "name": "peace_symbol", + "unicode": "262E", + "digest": "e0ee8a5c9fb18d5db6841b21527ed8fd955abdff9ffdb7b2684dca22107015fc" + }, + { "name": "peach", "unicode": "1F351", "digest": "a3f4fd5ff02e0a03104ab54456ee1a7521858ee68443856ee10e0972e5b6aaa5" @@ -5935,16 +8020,31 @@ "digest": "6becdc6f622c774bb09b7e7592bba2123ecccc9de32a35f0b18b50d7d54109cb" }, { + "name": "lower_left_ballpoint_pen", + "unicode": "1F58A", + "digest": "6becdc6f622c774bb09b7e7592bba2123ecccc9de32a35f0b18b50d7d54109cb" + }, + { "name": "pen_fountain", "unicode": "1F58B", "digest": "8c78cf0c2bd1d5e309d2d3356ff207e3fc76ca18dd6b90762cb62f6afbc95c6a" }, { + "name": "lower_left_fountain_pen", + "unicode": "1F58B", + "digest": "8c78cf0c2bd1d5e309d2d3356ff207e3fc76ca18dd6b90762cb62f6afbc95c6a" + }, + { "name": "pencil", "unicode": "1F4DD", "digest": "62b7ee5d9352114d09ee6f2c9a4c5e8b79f775a6c509e82ddfcdd61e13716249" }, { + "name": "memo", + "unicode": "1F4DD", + "digest": "62b7ee5d9352114d09ee6f2c9a4c5e8b79f775a6c509e82ddfcdd61e13716249" + }, + { "name": "pencil2", "unicode": "270F", "digest": "aa2c572772187fee1f9125bb0950f5ce8a61f7dd2647258c40b4077ee5feb498" @@ -5955,6 +8055,11 @@ "digest": "52c1ba1228917eb491ac1745a495e0fdafba6b985a81caba250f71d1f94c725c" }, { + "name": "lower_left_pencil", + "unicode": "1F589", + "digest": "52c1ba1228917eb491ac1745a495e0fdafba6b985a81caba250f71d1f94c725c" + }, + { "name": "penguin", "unicode": "1F427", "digest": "095de34b3f6a2521a342c21f5f2551a0092bf47429801c15b7bbf0913924f412" @@ -5965,11 +8070,21 @@ "digest": "cd3c33bfc3c7fbe84b98d2d481d56a7bf5488ff94afadd8b5a0e454768b80269" }, { + "name": "black_pennant", + "unicode": "1F3F2", + "digest": "cd3c33bfc3c7fbe84b98d2d481d56a7bf5488ff94afadd8b5a0e454768b80269" + }, + { "name": "pennant_white", "unicode": "1F3F1", "digest": "818b1be73540f2cfeb1c514e1ee75d18715af317f0db817d9ae081b9ea33d4b0" }, { + "name": "white_pennant", + "unicode": "1F3F1", + "digest": "818b1be73540f2cfeb1c514e1ee75d18715af317f0db817d9ae081b9ea33d4b0" + }, + { "name": "pensive", "unicode": "1F614", "digest": "2d9e7f1eed14dcc86674cec78e992567a40d0f223fc67d722b91eebcd1251269" @@ -6110,11 +8225,21 @@ "digest": "dd2a84716c93410a285ff759bfbc2dc31a10f90b203c7a657b908e5949e89a39" }, { + "name": "table_tennis", + "unicode": "1F3D3", + "digest": "dd2a84716c93410a285ff759bfbc2dc31a10f90b203c7a657b908e5949e89a39" + }, + { "name": "piracy", "unicode": "1F572", "digest": "f42955ba75c598392e5e258be49968d858c876e0d6e7aa9dc795f7e8cff42be9" }, { + "name": "no_piracy", + "unicode": "1F572", + "digest": "f42955ba75c598392e5e258be49968d858c876e0d6e7aa9dc795f7e8cff42be9" + }, + { "name": "pisces", "unicode": "2653", "digest": "75f11b9a094196b54a242420362fa7c0aeba7cfc497b187e1aaaba96d93684a7" @@ -6130,6 +8255,11 @@ "digest": "4fabc307b7e35f94288f6d53985485662a4814b11a9a382f0a3873d41b1290d3" }, { + "name": "worship_symbol", + "unicode": "1F6D0", + "digest": "4fabc307b7e35f94288f6d53985485662a4814b11a9a382f0a3873d41b1290d3" + }, + { "name": "play_pause", "unicode": "23EF", "digest": "d69e8cdec33447283cf65d343b986115e27681d781b721db7894e5c587ca18ad" @@ -6300,6 +8430,21 @@ "digest": "140ce75a015ede5e764873e0ae9a56e7b2af333eddca0fe2796b14545c620258" }, { + "name": "shit", + "unicode": "1F4A9", + "digest": "140ce75a015ede5e764873e0ae9a56e7b2af333eddca0fe2796b14545c620258" + }, + { + "name": "hankey", + "unicode": "1F4A9", + "digest": "140ce75a015ede5e764873e0ae9a56e7b2af333eddca0fe2796b14545c620258" + }, + { + "name": "poo", + "unicode": "1F4A9", + "digest": "140ce75a015ede5e764873e0ae9a56e7b2af333eddca0fe2796b14545c620258" + }, + { "name": "popcorn", "unicode": "1F37F", "digest": "12264cb16fca9317e3ba8d5924a2c8f15f790e36d2f29e7b12aaaf77e1beb73d" @@ -6420,11 +8565,21 @@ "digest": "bc6cdea2269a0ec39576d98dc4cda2bd9efa4dc330dde870148c6a85ad9cc63f" }, { + "name": "prohibited_sign", + "unicode": "1F6C7", + "digest": "bc6cdea2269a0ec39576d98dc4cda2bd9efa4dc330dde870148c6a85ad9cc63f" + }, + { "name": "projector", "unicode": "1F4FD", "digest": "fc361282f367926254c08150b02cb8fda7fa8d2c9c939d9360c78bf19a4f982e" }, { + "name": "film_projector", + "unicode": "1F4FD", + "digest": "fc361282f367926254c08150b02cb8fda7fa8d2c9c939d9360c78bf19a4f982e" + }, + { "name": "punch", "unicode": "1F44A", "digest": "5759db1d7093744c74b840bbb4761fb025d6633f8fa539bcb35dcf54fc05ceb6" @@ -6500,6 +8655,11 @@ "digest": "2e9828e3884c79ad7e9e1173d3470790f3f56cfa08ef4e38deff45db0728c66c" }, { + "name": "racing_car", + "unicode": "1F3CE", + "digest": "2e9828e3884c79ad7e9e1173d3470790f3f56cfa08ef4e38deff45db0728c66c" + }, + { "name": "racehorse", "unicode": "1F40E", "digest": "36aa3c7123ee7e15600657166032b21b8edeb192cf6d3ada39b5c65001f7fc40" @@ -6520,6 +8680,11 @@ "digest": "5ad8e8594617c0153672a76421deb836e05c6098020c33af3f975f8fcfe216e4" }, { + "name": "radioactive_sign", + "unicode": "2622", + "digest": "5ad8e8594617c0153672a76421deb836e05c6098020c33af3f975f8fcfe216e4" + }, + { "name": "rage", "unicode": "1F621", "digest": "02ac70551fc51478884c133b29539cae58b463c760db38c0aeec1bdf5b282312" @@ -6535,6 +8700,11 @@ "digest": "63ee881cc775d5b2711082b6c96ab44d5204c5d390afd6d8ee97e52aeeaa5e5e" }, { + "name": "railroad_track", + "unicode": "1F6E4", + "digest": "63ee881cc775d5b2711082b6c96ab44d5204c5d390afd6d8ee97e52aeeaa5e5e" + }, + { "name": "rainbow", "unicode": "1F308", "digest": "bbd8ecc8d0737948969a3539d2d202e599404e509f1a21bdbb0a0c41c2540522" @@ -6745,11 +8915,21 @@ "digest": "5b92daa87bdf6ee15e798bec382a2ee885f4e6e77a68a3f626adcfe4c782b375" }, { + "name": "right_speaker_with_one_sound_wave", + "unicode": "1F569", + "digest": "5b92daa87bdf6ee15e798bec382a2ee885f4e6e77a68a3f626adcfe4c782b375" + }, + { "name": "right_speaker_three", "unicode": "1F56A", "digest": "4d00b720a65bd0f4c3682b290b1976ec2388d6ae61225398f4e70556ae9e5f80" }, { + "name": "right_speaker_with_three_sound_waves", + "unicode": "1F56A", + "digest": "4d00b720a65bd0f4c3682b290b1976ec2388d6ae61225398f4e70556ae9e5f80" + }, + { "name": "ring", "unicode": "1F48D", "digest": "ae2a93e7895b9b89f5a39f01d356ffed988f219ef8b658a56c55285826a4533b" @@ -6765,6 +8945,11 @@ "digest": "cc0e363774b86e21a5b2cea7f7af85bca9e92c124ebcd39c6067c125048baa60" }, { + "name": "robot_face", + "unicode": "1F916", + "digest": "cc0e363774b86e21a5b2cea7f7af85bca9e92c124ebcd39c6067c125048baa60" + }, + { "name": "rocket", "unicode": "1F680", "digest": "65d8bd005ceac41904237b7a8c5f55f16713a55d971522f0bbe63a1d548e515d" @@ -6780,6 +8965,11 @@ "digest": "f596f203030b6c9bd743848512aa3fc7919447020d35ae5c2bf13ccb16fa2dbe" }, { + "name": "face_with_rolling_eyes", + "unicode": "1F644", + "digest": "f596f203030b6c9bd743848512aa3fc7919447020d35ae5c2bf13ccb16fa2dbe" + }, + { "name": "rooster", "unicode": "1F413", "digest": "6cefdaa45631ed8c9480e15f578c793d95af81b42687164fd7900eee325ccf07" @@ -7100,11 +9290,21 @@ "digest": "dfd169764b192ac7c6e5101277dd9f1e010e86bdd32ad37e00ed4499fc0a5dd6" }, { + "name": "skeleton", + "unicode": "1F480", + "digest": "dfd169764b192ac7c6e5101277dd9f1e010e86bdd32ad37e00ed4499fc0a5dd6" + }, + { "name": "skull_crossbones", "unicode": "2620", "digest": "e2acf0f36b6a6800c1829a1c6551b5d0eb6dcdef4b7f02070cf69570aeab608c" }, { + "name": "skull_and_crossbones", + "unicode": "2620", + "digest": "e2acf0f36b6a6800c1829a1c6551b5d0eb6dcdef4b7f02070cf69570aeab608c" + }, + { "name": "sleeping", "unicode": "1F634", "digest": "4ead95079b1a542eedd0e5a0e93fddb318a002bdaffaa2fe5d8d7f20bf8143ed" @@ -7125,11 +9325,21 @@ "digest": "3ae82b38b58ffa50eddebd87153428d880ca181f4f4178a9ca3bd813ea15ccbc" }, { + "name": "slightly_frowning_face", + "unicode": "1F641", + "digest": "3ae82b38b58ffa50eddebd87153428d880ca181f4f4178a9ca3bd813ea15ccbc" + }, + { "name": "slight_smile", "unicode": "1F642", "digest": "5eee09f634a4e2031927d008a6530a258a00e611ead0c386dd5b7ebb5e75a306" }, { + "name": "slightly_smiling_face", + "unicode": "1F642", + "digest": "5eee09f634a4e2031927d008a6530a258a00e611ead0c386dd5b7ebb5e75a306" + }, + { "name": "slot_machine", "unicode": "1F3B0", "digest": "9d516b389299431b608c89d3f02ac68d28cb8df2a780f2048923bbcfbb49f416" @@ -7300,6 +9510,11 @@ "digest": "d92cfe1200887300b2f05f9576448a2f2a79d0accd51f323a65ce3db0aa5639b" }, { + "name": "speaking_head_in_silhouette", + "unicode": "1F5E3", + "digest": "d92cfe1200887300b2f05f9576448a2f2a79d0accd51f323a65ce3db0aa5639b" + }, + { "name": "speech_balloon", "unicode": "1F4AC", "digest": "5dccfda46fc984583bc9eaece66e7e884f2a9eb12a69dbd3493035e3c862edd0" @@ -7310,21 +9525,41 @@ "digest": "478b0b07460a9f54b7d0050f886da59fde5e428daa11e899fc31477fda1707ed" }, { + "name": "left_speech_bubble", + "unicode": "1F5E8", + "digest": "478b0b07460a9f54b7d0050f886da59fde5e428daa11e899fc31477fda1707ed" + }, + { "name": "speech_right", "unicode": "1F5E9", "digest": "8439b13779163c15e678a78b08ebeeb7d131632df21d2a7868de7fed38ca9d8a" }, { + "name": "right_speech_bubble", + "unicode": "1F5E9", + "digest": "8439b13779163c15e678a78b08ebeeb7d131632df21d2a7868de7fed38ca9d8a" + }, + { "name": "speech_three", "unicode": "1F5EB", "digest": "55a934f3659b6e75fdce0d0c4e2ea56dd34a43892c85a6666bd1882a0bfb92a9" }, { + "name": "three_speech_bubbles", + "unicode": "1F5EB", + "digest": "55a934f3659b6e75fdce0d0c4e2ea56dd34a43892c85a6666bd1882a0bfb92a9" + }, + { "name": "speech_two", "unicode": "1F5EA", "digest": "0563ef0591da243673cf877462acc5d8e1d980a56e81668ac627de74d0c33983" }, { + "name": "two_speech_bubbles", + "unicode": "1F5EA", + "digest": "0563ef0591da243673cf877462acc5d8e1d980a56e81668ac627de74d0c33983" + }, + { "name": "speedboat", "unicode": "1F6A4", "digest": "553a288ab8eeb3dee7b9d1c92eba38016caef7658beaa828136ba1d6ba8ed08a" @@ -7345,31 +9580,61 @@ "digest": "eaa570a36d83119d0a596228e74affe84d7355714ff6901d88a89410d26dec2a" }, { + "name": "sleuth_or_spy", + "unicode": "1F575", + "digest": "eaa570a36d83119d0a596228e74affe84d7355714ff6901d88a89410d26dec2a" + }, + { "name": "spy_tone1", "unicode": "1F575-1F3FB", "digest": "abdc066d4cad6a17047faf7806c45feb43ae1e2056cf500536f08f4173dbfa94" }, { + "name": "sleuth_or_spy_tone1", + "unicode": "1F575-1F3FB", + "digest": "abdc066d4cad6a17047faf7806c45feb43ae1e2056cf500536f08f4173dbfa94" + }, + { "name": "spy_tone2", "unicode": "1F575-1F3FC", "digest": "72a3313ef12364105e764cc3deabd47eb6bd086f261c435682ae1cd29dc8230b" }, { + "name": "sleuth_or_spy_tone2", + "unicode": "1F575-1F3FC", + "digest": "72a3313ef12364105e764cc3deabd47eb6bd086f261c435682ae1cd29dc8230b" + }, + { "name": "spy_tone3", "unicode": "1F575-1F3FD", "digest": "2a1108d3d2e778f88aa5b3ae36705c877b84d0bf6b421409582ba748aeb2aee7" }, { + "name": "sleuth_or_spy_tone3", + "unicode": "1F575-1F3FD", + "digest": "2a1108d3d2e778f88aa5b3ae36705c877b84d0bf6b421409582ba748aeb2aee7" + }, + { "name": "spy_tone4", "unicode": "1F575-1F3FE", "digest": "1d4fe62912384bc0d687bcf4565752caf0ed6146c903a156d1c6ba6ea239b154" }, { + "name": "sleuth_or_spy_tone4", + "unicode": "1F575-1F3FE", + "digest": "1d4fe62912384bc0d687bcf4565752caf0ed6146c903a156d1c6ba6ea239b154" + }, + { "name": "spy_tone5", "unicode": "1F575-1F3FF", "digest": "69c1baac73783edb9e2d0c951f922dc7dddac34d0a9c818fee8d1021bc17db0d" }, { + "name": "sleuth_or_spy_tone5", + "unicode": "1F575-1F3FF", + "digest": "69c1baac73783edb9e2d0c951f922dc7dddac34d0a9c818fee8d1021bc17db0d" + }, + { "name": "stadium", "unicode": "1F3DF", "digest": "4356db5d2cdef8c40830638debaf1f50831130c12ae8d8dc3d9a6bd28fdaa1f7" @@ -7420,6 +9685,11 @@ "digest": "1ce1f9a83867514b8351ad4fd80c46bba04ad67dfb9874e63d7296e1a21161a5" }, { + "name": "portable_stereo", + "unicode": "1F4FE", + "digest": "1ce1f9a83867514b8351ad4fd80c46bba04ad67dfb9874e63d7296e1a21161a5" + }, + { "name": "stew", "unicode": "1F372", "digest": "12e6e4bf48a7296700e07a053d831dd67b70c308ca9522ca96e933a4d1ef6c5e" @@ -7645,6 +9915,11 @@ "digest": "c3a42a653a91d90c6b668f678419d5438f2e546050914b841623e57107e805db" }, { + "name": "black_touchtone_telephone", + "unicode": "1F57F", + "digest": "c3a42a653a91d90c6b668f678419d5438f2e546050914b841623e57107e805db" + }, + { "name": "telephone_receiver", "unicode": "1F4DE", "digest": "e3bf6034de6cf2160893ba4990eba198185a6a3f9cd5767a63b048e41c297640" @@ -7655,6 +9930,11 @@ "digest": "62a7e0e50c53e9f85eba51a92882e6064be05997910d3f7700e1e957dbaf0581" }, { + "name": "white_touchtone_telephone", + "unicode": "1F57E", + "digest": "62a7e0e50c53e9f85eba51a92882e6064be05997910d3f7700e1e957dbaf0581" + }, + { "name": "telescope", "unicode": "1F52D", "digest": "abe0aca5f2c78105b0e9e4c8ee7a40adcd9bb013e7c49d568076459bade73556" @@ -7685,11 +9965,21 @@ "digest": "f19c489d89dd2d39770a6c8725a20f3e98f9e5216774af60c0665fd6a03a7687" }, { + "name": "face_with_thermometer", + "unicode": "1F912", + "digest": "f19c489d89dd2d39770a6c8725a20f3e98f9e5216774af60c0665fd6a03a7687" + }, + { "name": "thinking", "unicode": "1F914", "digest": "f64a9a18dca4c502b46f933838753a818b604a9d0268aa32eda26cbd31abc58c" }, { + "name": "thinking_face", + "unicode": "1F914", + "digest": "f64a9a18dca4c502b46f933838753a818b604a9d0268aa32eda26cbd31abc58c" + }, + { "name": "thought_balloon", "unicode": "1F4AD", "digest": "76c8513191641f0a79e878ccc0d83c4576984609810633f596db2f64cc684b7d" @@ -7700,11 +9990,21 @@ "digest": "4fd591bf4318df73d1b17f434a449d8e95f49cca53a3d8f4d1ca983f3809ef46" }, { + "name": "left_thought_bubble", + "unicode": "1F5EC", + "digest": "4fd591bf4318df73d1b17f434a449d8e95f49cca53a3d8f4d1ca983f3809ef46" + }, + { "name": "thought_right", "unicode": "1F5ED", "digest": "0e8c0ce26e2d0e30894f5394b0736456e8268f775e0e7eda4c7dc3c2ff9231ae" }, { + "name": "right_thought_bubble", + "unicode": "1F5ED", + "digest": "0e8c0ce26e2d0e30894f5394b0736456e8268f775e0e7eda4c7dc3c2ff9231ae" + }, + { "name": "three", "unicode": "0033-20E3", "digest": "ca0147a8f67cea3bc2516fa8deef4325188359559786c94ff0b27f90eef04b88" @@ -7715,76 +10015,151 @@ "digest": "a8b561e389bc4e4b07fba70994f6445e5ddc6afe68922fcb6e9e7282d19ad958" }, { + "name": "reversed_thumbs_down_sign", + "unicode": "1F593", + "digest": "a8b561e389bc4e4b07fba70994f6445e5ddc6afe68922fcb6e9e7282d19ad958" + }, + { "name": "thumbs_up_reverse", "unicode": "1F592", "digest": "b6e52715c5ce590bfd08f6e05058ec3765ea2da341b11f9825d100608b173837" }, { + "name": "reversed_thumbs_up_sign", + "unicode": "1F592", + "digest": "b6e52715c5ce590bfd08f6e05058ec3765ea2da341b11f9825d100608b173837" + }, + { "name": "thumbsdown", "unicode": "1F44E", "digest": "a98f742c9773e0d95c0de5e1c10d1ab373fa761378a205f27d095e85debe69a3" }, { + "name": "-1", + "unicode": "1F44E", + "digest": "a98f742c9773e0d95c0de5e1c10d1ab373fa761378a205f27d095e85debe69a3" + }, + { "name": "thumbsdown_tone1", "unicode": "1F44E-1F3FB", "digest": "5d0a7c63d52eafe6267c552168c5557a66622009d565c3cf7b5378c1f6e84bce" }, { + "name": "-1_tone1", + "unicode": "1F44E-1F3FB", + "digest": "5d0a7c63d52eafe6267c552168c5557a66622009d565c3cf7b5378c1f6e84bce" + }, + { "name": "thumbsdown_tone2", "unicode": "1F44E-1F3FC", "digest": "ca5c15dc516660b2989a1c717bf3745fdfb6964c7acf3b938285ff6c7caf2ca2" }, { + "name": "-1_tone2", + "unicode": "1F44E-1F3FC", + "digest": "ca5c15dc516660b2989a1c717bf3745fdfb6964c7acf3b938285ff6c7caf2ca2" + }, + { "name": "thumbsdown_tone3", "unicode": "1F44E-1F3FD", "digest": "05740e3568795270674dac9134198bf75b1b778c11daa71649c88c231859ec16" }, { + "name": "-1_tone3", + "unicode": "1F44E-1F3FD", + "digest": "05740e3568795270674dac9134198bf75b1b778c11daa71649c88c231859ec16" + }, + { "name": "thumbsdown_tone4", "unicode": "1F44E-1F3FE", "digest": "5ee93bcc2f515806462a7b303064beade2b22a3f43a8162e39fd65d15d772e27" }, { + "name": "-1_tone4", + "unicode": "1F44E-1F3FE", + "digest": "5ee93bcc2f515806462a7b303064beade2b22a3f43a8162e39fd65d15d772e27" + }, + { "name": "thumbsdown_tone5", "unicode": "1F44E-1F3FF", "digest": "5c9ef8d53cf6f755668ab6dabfbfcdfd4b95fd59db3b3dd60290efefe9c33994" }, { + "name": "-1_tone5", + "unicode": "1F44E-1F3FF", + "digest": "5c9ef8d53cf6f755668ab6dabfbfcdfd4b95fd59db3b3dd60290efefe9c33994" + }, + { "name": "thumbsup", "unicode": "1F44D", "digest": "28b31df963773ba42a1a089f43cd89d0ce1ab0981e5410f41242e9a125fc1aee" }, { + "name": "+1", + "unicode": "1F44D", + "digest": "28b31df963773ba42a1a089f43cd89d0ce1ab0981e5410f41242e9a125fc1aee" + }, + { "name": "thumbsup_tone1", "unicode": "1F44D-1F3FB", "digest": "f6365942738d2128b6959d6672b3d295757dc8240703cb84a2b014ad78d67de3" }, { + "name": "+1_tone1", + "unicode": "1F44D-1F3FB", + "digest": "f6365942738d2128b6959d6672b3d295757dc8240703cb84a2b014ad78d67de3" + }, + { "name": "thumbsup_tone2", "unicode": "1F44D-1F3FC", "digest": "771d30146e4dc947a69057b05d32c765c8457ab02b5342889c5489acf27ef356" }, { + "name": "+1_tone2", + "unicode": "1F44D-1F3FC", + "digest": "771d30146e4dc947a69057b05d32c765c8457ab02b5342889c5489acf27ef356" + }, + { "name": "thumbsup_tone3", "unicode": "1F44D-1F3FD", "digest": "0bb7bbfb654c6139260e1786e7ffa5a33f31e19410c1d4d15737fdf5dd4c721d" }, { + "name": "+1_tone3", + "unicode": "1F44D-1F3FD", + "digest": "0bb7bbfb654c6139260e1786e7ffa5a33f31e19410c1d4d15737fdf5dd4c721d" + }, + { "name": "thumbsup_tone4", "unicode": "1F44D-1F3FE", "digest": "df0927c5342f0075fbf4ea83b724e6f70c0466c54769c9ce4a5c2deb602b28aa" }, { + "name": "+1_tone4", + "unicode": "1F44D-1F3FE", + "digest": "df0927c5342f0075fbf4ea83b724e6f70c0466c54769c9ce4a5c2deb602b28aa" + }, + { "name": "thumbsup_tone5", "unicode": "1F44D-1F3FF", "digest": "0683ae08c50aaf186c6406680a60617679c7b4bccd0817f24b15911dbb06866f" }, { + "name": "+1_tone5", + "unicode": "1F44D-1F3FF", + "digest": "0683ae08c50aaf186c6406680a60617679c7b4bccd0817f24b15911dbb06866f" + }, + { "name": "thunder_cloud_rain", "unicode": "26C8", "digest": "dd836f06b41a10d6ed9bcbdae291d2886847ff66dc3ede2427382e469f60674c" }, { + "name": "thunder_cloud_and_rain", + "unicode": "26C8", + "digest": "dd836f06b41a10d6ed9bcbdae291d2886847ff66dc3ede2427382e469f60674c" + }, + { "name": "ticket", "unicode": "1F3AB", "digest": "a7654a5529535120da3c377e72cd1f7997bdc2dabf1d44b584f7df7852b158f9" @@ -7795,6 +10170,11 @@ "digest": "ccafcc9583a84e847ff1eaa3d53187c5ab150a7d27c6a19363e59b9bc046b567" }, { + "name": "admission_tickets", + "unicode": "1F39F", + "digest": "ccafcc9583a84e847ff1eaa3d53187c5ab150a7d27c6a19363e59b9bc046b567" + }, + { "name": "tiger", "unicode": "1F42F", "digest": "9ebe3117f5f1b589ff8164f8d87dcc275923e0db87121d2cee0fdb9b56dfc4ac" @@ -7810,6 +10190,11 @@ "digest": "c48199312ed42ff53a33bb2791db19e2e2521223cd49d8f758ea95b9b379c5ff" }, { + "name": "timer_clock", + "unicode": "23F2", + "digest": "c48199312ed42ff53a33bb2791db19e2e2521223cd49d8f758ea95b9b379c5ff" + }, + { "name": "tired_face", "unicode": "1F62B", "digest": "ad687a956388ec53ca1e301a0abe2f1e2cfb9f73cd543dd61a21c7335a42e332" @@ -7870,6 +10255,11 @@ "digest": "9b0a36dfdb475621d326359662b22cbdb80563c4f476aa5e7d7c00cdba605bd9" }, { + "name": "hammer_and_wrench", + "unicode": "1F6E0", + "digest": "9b0a36dfdb475621d326359662b22cbdb80563c4f476aa5e7d7c00cdba605bd9" + }, + { "name": "top", "unicode": "1F51D", "digest": "d645030099aeb433307569e8e1c4342c1c411a8fefe50fdca7a3207a1a0db671" @@ -7885,11 +10275,21 @@ "digest": "d5415ed140933f345fea8023a3d8fca30dcfcf7d19d9dc9771fa2cae9df62a3b" }, { + "name": "next_track", + "unicode": "23ED", + "digest": "d5415ed140933f345fea8023a3d8fca30dcfcf7d19d9dc9771fa2cae9df62a3b" + }, + { "name": "track_previous", "unicode": "23EE", "digest": "97ff4a59a236e5cf506fa3577b20715b3b0197e0f343a50615b36185d5b835f1" }, { + "name": "previous_track", + "unicode": "23EE", + "digest": "97ff4a59a236e5cf506fa3577b20715b3b0197e0f343a50615b36185d5b835f1" + }, + { "name": "trackball", "unicode": "1F5B2", "digest": "8332503454ce42059d720c285fe2b15eb0562a0a4b234dccb0f3159bb30a91aa" @@ -7920,6 +10320,11 @@ "digest": "621bb967cd93fa9f8fd4b155965cc7572d3f91f88d94938ba10c8626718b623c" }, { + "name": "diesel_locomotive", + "unicode": "1F6F2", + "digest": "621bb967cd93fa9f8fd4b155965cc7572d3f91f88d94938ba10c8626718b623c" + }, + { "name": "tram", "unicode": "1F68A", "digest": "5a86d31f7ab677d967fecd75babc900b5169766d0228961912314c4c4d1d64ee" @@ -7930,6 +10335,11 @@ "digest": "e24bb39ecfaaa746b03dc8418697d09ef327d5b077db39014f39d5fb87e23bd5" }, { + "name": "triangle_with_rounded_corners", + "unicode": "1F6C6", + "digest": "e24bb39ecfaaa746b03dc8418697d09ef327d5b077db39014f39d5fb87e23bd5" + }, + { "name": "triangular_flag_on_post", "unicode": "1F6A9", "digest": "d824c973d84cd62c845d64e546de87b094fda8f9972b6a33acd75e1a5ac19f75" @@ -7995,6 +10405,11 @@ "digest": "8a6c5b7d4c737866e7e32c6d9f7f447a48a0ac57a8909d43f87367d4a9b59246" }, { + "name": "turned_ok_hand_sign", + "unicode": "1F58F", + "digest": "8a6c5b7d4c737866e7e32c6d9f7f447a48a0ac57a8909d43f87367d4a9b59246" + }, + { "name": "turtle", "unicode": "1F422", "digest": "388b3e75b931638a09f65b842d26e2cc87b200ba782dec871f84cddd71aaeaf3" @@ -8110,6 +10525,11 @@ "digest": "1b1e9c209dabe619db76fd346c3fb51b28ace0e4102697fe0973fe2d46aa9f08" }, { + "name": "unicorn_face", + "unicode": "1F984", + "digest": "1b1e9c209dabe619db76fd346c3fb51b28ace0e4102697fe0973fe2d46aa9f08" + }, + { "name": "unlock", "unicode": "1F513", "digest": "63dbef0855399254ae01cf4ef0676adebc1432ae1ee260b569c23ae8152deaf8" @@ -8125,11 +10545,21 @@ "digest": "763fe2baf07a9b04f96958adf38a43c7dd2bc70d57398f49604307bd835cbb53" }, { + "name": "upside_down_face", + "unicode": "1F643", + "digest": "763fe2baf07a9b04f96958adf38a43c7dd2bc70d57398f49604307bd835cbb53" + }, + { "name": "urn", "unicode": "26B1", "digest": "dbfd5b90709d1b812d2fff71a5cfa10f84a4579866c2d7cd0e80759a22b2ba0e" }, { + "name": "funeral_urn", + "unicode": "26B1", + "digest": "dbfd5b90709d1b812d2fff71a5cfa10f84a4579866c2d7cd0e80759a22b2ba0e" + }, + { "name": "v", "unicode": "270C", "digest": "df85ad1a3ff365c3232a010701c9b25cd824d19fa2511422dee60ac231f457e3" @@ -8215,31 +10645,61 @@ "digest": "ca800fce797e652c5f47bf44992e8fbe19554688a36423fdf7c29ca6defae1e0" }, { + "name": "raised_hand_with_part_between_middle_and_ring_fingers", + "unicode": "1F596", + "digest": "ca800fce797e652c5f47bf44992e8fbe19554688a36423fdf7c29ca6defae1e0" + }, + { "name": "vulcan_tone1", "unicode": "1F596-1F3FB", "digest": "84bafdaca43426b053f5caa4e868ca109d99113a28ea9799db09d3c5d5f645c8" }, { + "name": "raised_hand_with_part_between_middle_and_ring_fingers_tone1", + "unicode": "1F596-1F3FB", + "digest": "84bafdaca43426b053f5caa4e868ca109d99113a28ea9799db09d3c5d5f645c8" + }, + { "name": "vulcan_tone2", "unicode": "1F596-1F3FC", "digest": "e7cedf63ead957ee5c287e4cb0828ba70673e17b604f92b529875c32d094e7e3" }, { + "name": "raised_hand_with_part_between_middle_and_ring_fingers_tone2", + "unicode": "1F596-1F3FC", + "digest": "e7cedf63ead957ee5c287e4cb0828ba70673e17b604f92b529875c32d094e7e3" + }, + { "name": "vulcan_tone3", "unicode": "1F596-1F3FD", "digest": "e124fef20f289921553274cf834f6dcc1a012889d30d9874dc5ad01afb8235b8" }, { + "name": "raised_hand_with_part_between_middle_and_ring_fingers_tone3", + "unicode": "1F596-1F3FD", + "digest": "e124fef20f289921553274cf834f6dcc1a012889d30d9874dc5ad01afb8235b8" + }, + { "name": "vulcan_tone4", "unicode": "1F596-1F3FE", "digest": "ea2115f549e4680467521bbf362b229f4a8f0fdadbfaf231378d801f9b369f08" }, { + "name": "raised_hand_with_part_between_middle_and_ring_fingers_tone4", + "unicode": "1F596-1F3FE", + "digest": "ea2115f549e4680467521bbf362b229f4a8f0fdadbfaf231378d801f9b369f08" + }, + { "name": "vulcan_tone5", "unicode": "1F596-1F3FF", "digest": "1b322e1252491f35ae02f0b279b6529dad867f2a6b3c2c3e77f981bed07e447d" }, { + "name": "raised_hand_with_part_between_middle_and_ring_fingers_tone5", + "unicode": "1F596-1F3FF", + "digest": "1b322e1252491f35ae02f0b279b6529dad867f2a6b3c2c3e77f981bed07e447d" + }, + { "name": "walking", "unicode": "1F6B6", "digest": "8ec0b2207d4368422261bc58944c17dff2554b2356becfb18f21dd87425cd67b" @@ -8430,16 +10890,31 @@ "digest": "d8ce416e6bdb0e59e06e2fceac3177dbe59fefc248fd8c6d76b80d1418141070" }, { + "name": "white_sun_behind_cloud", + "unicode": "1F325", + "digest": "d8ce416e6bdb0e59e06e2fceac3177dbe59fefc248fd8c6d76b80d1418141070" + }, + { "name": "white_sun_rain_cloud", "unicode": "1F326", "digest": "d2b132518261864ac4a95707eaeea335dd8351ed2b8ef4e2272ced456e309bf1" }, { + "name": "white_sun_behind_cloud_with_rain", + "unicode": "1F326", + "digest": "d2b132518261864ac4a95707eaeea335dd8351ed2b8ef4e2272ced456e309bf1" + }, + { "name": "white_sun_small_cloud", "unicode": "1F324", "digest": "b86a72f1cdb4d24fd3ab180aae9db012ca51fc01f3786aab596c2e330066b185" }, { + "name": "white_sun_with_small_cloud", + "unicode": "1F324", + "digest": "b86a72f1cdb4d24fd3ab180aae9db012ca51fc01f3786aab596c2e330066b185" + }, + { "name": "wind_blowing_face", "unicode": "1F32C", "digest": "20bdeb8e39dc637792ac9fbee031c5791889f3126e83556ba51f98809c19763c" @@ -8525,6 +11000,11 @@ "digest": "c4fc18ece6778339ebe14438aaf570e22385c3010c2d341824fa72ac6068cfeb" }, { + "name": "left_writing_hand", + "unicode": "1F58E", + "digest": "c4fc18ece6778339ebe14438aaf570e22385c3010c2d341824fa72ac6068cfeb" + }, + { "name": "writing_hand_tone1", "unicode": "270D-1F3FB", "digest": "38e64e6dca4847a12aef8a117c113b2025d841501c4bc8188c57d0c8a4f1e34d" @@ -8590,6 +11070,11 @@ "digest": "8396249161b6d865861b56aabd17cae2c821b0d814f4249bf8cab0bb21fa8ee9" }, { + "name": "zipper_mouth_face", + "unicode": "1F910", + "digest": "8396249161b6d865861b56aabd17cae2c821b0d814f4249bf8cab0bb21fa8ee9" + }, + { "name": "zzz", "unicode": "1F4A4", "digest": "f07c56d2d55c0a886c26a8e3d49a9adeab54cc1a0c0354ea8d3bf23aaed3176d" diff --git a/lib/api/entities.rb b/lib/api/entities.rb index d76b46b8836..60b9f5e0ece 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -212,7 +212,7 @@ module API expose :note, as: :body expose :attachment_identifier, as: :attachment expose :author, using: Entities::UserBasic - expose :created_at + expose :created_at, :updated_at expose :system?, as: :system expose :noteable_id, :noteable_type # upvote? and downvote? are deprecated, always return false @@ -263,14 +263,19 @@ module API expose :id, :path, :kind end - class ProjectAccess < Grape::Entity + class Member < Grape::Entity expose :access_level - expose :notification_level + expose :notification_level do |member, options| + if member.notification_setting + NotificationSetting.levels[member.notification_setting.level] + end + end end - class GroupAccess < Grape::Entity - expose :access_level - expose :notification_level + class ProjectAccess < Member + end + + class GroupAccess < Member end class ProjectService < Grape::Entity @@ -301,6 +306,7 @@ module API class Label < Grape::Entity expose :name, :color, :description + expose :open_issues_count, :closed_issues_count, :open_merge_requests_count end class Compare < Grape::Entity diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb index 0f3f505fa05..84b4d4cdd6d 100644 --- a/lib/api/milestones.rb +++ b/lib/api/milestones.rb @@ -21,6 +21,7 @@ module API # state (optional) - Return "active" or "closed" milestones # Example Request: # GET /projects/:id/milestones + # GET /projects/:id/milestones?iid=42 # GET /projects/:id/milestones?state=active # GET /projects/:id/milestones?state=closed get ":id/milestones" do @@ -28,6 +29,7 @@ module API milestones = user_project.milestones milestones = filter_milestones_state(milestones, params[:state]) + milestones = filter_by_iid(milestones, params[:iid]) if params[:iid].present? present paginate(milestones), with: Entities::Milestone end diff --git a/lib/api/notes.rb b/lib/api/notes.rb index 174473f5371..a1c98f5e8ff 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -112,6 +112,23 @@ module API end end + # Delete a +noteable+ note + # + # Parameters: + # id (required) - The ID of a project + # noteable_id (required) - The ID of an issue, MR, or snippet + # node_id (required) - The ID of a note + # Example Request: + # DELETE /projects/:id/issues/:noteable_id/notes/:note_id + # DELETE /projects/:id/snippets/:noteable_id/notes/:node_id + delete ":id/#{noteables_str}/:#{noteable_id_str}/notes/:note_id" do + note = user_project.notes.find(params[:note_id]) + authorize! :admin_note, note + + ::Notes::DeleteService.new(user_project, current_user).execute(note) + + present note, with: Entities::Note + end end end end diff --git a/lib/api/project_members.rb b/lib/api/project_members.rb index c756bb479fc..4aefdf319c6 100644 --- a/lib/api/project_members.rb +++ b/lib/api/project_members.rb @@ -93,12 +93,17 @@ module API # Example Request: # DELETE /projects/:id/members/:user_id delete ":id/members/:user_id" do - authorize! :admin_project, user_project project_member = user_project.project_members.find_by(user_id: params[:user_id]) - unless project_member.nil? - project_member.destroy - else + + unless current_user.can?(:admin_project, user_project) || + current_user.can?(:destroy_project_member, project_member) + forbidden! + end + + if project_member.nil? { message: "Access revoked", id: params[:user_id].to_i } + else + project_member.destroy end end end diff --git a/lib/api/tags.rb b/lib/api/tags.rb index 2d8a9e51bb9..d1a10479e44 100644 --- a/lib/api/tags.rb +++ b/lib/api/tags.rb @@ -16,6 +16,20 @@ module API with: Entities::RepoTag, project: user_project end + # Get a single repository tag + # + # Parameters: + # id (required) - The ID of a project + # tag_name (required) - The name of the tag + # Example Request: + # GET /projects/:id/repository/tags/:tag_name + get ":id/repository/tags/:tag_name", requirements: { tag_name: /.+/ } do + tag = user_project.repository.find_tag(params[:tag_name]) + not_found!('Tag') unless tag + + present tag, with: Entities::RepoTag, project: user_project + end + # Create tag # # Parameters: diff --git a/lib/gitlab/saml/user.rb b/lib/gitlab/saml/user.rb index c1072452abe..dba4bbfc899 100644 --- a/lib/gitlab/saml/user.rb +++ b/lib/gitlab/saml/user.rb @@ -26,7 +26,7 @@ module Gitlab @user ||= build_new_user end - if external_users_enabled? + if external_users_enabled? && @user # Check if there is overlap between the user's groups and the external groups # setting then set user as external or internal. if (auth_hash.groups & Gitlab::Saml::Config.external_groups).empty? @@ -48,6 +48,7 @@ module Gitlab end def changed? + return true unless gl_user gl_user.changed? || gl_user.identities.any?(&:changed?) end diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake index 7ec00a898fd..030ee8bafcb 100644 --- a/lib/tasks/gemojione.rake +++ b/lib/tasks/gemojione.rake @@ -5,12 +5,23 @@ namespace :gemojione do require 'json' dir = Gemojione.index.images_path + digests = [] + aliases = Hash.new { |hash, key| hash[key] = [] } + aliases_path = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json') - digests = AwardEmoji.emojis.map do |name, emoji_hash| + JSON.parse(File.read(aliases_path)).each do |alias_name, real_name| + aliases[real_name] << alias_name + end + + AwardEmoji.emojis.map do |name, emoji_hash| fpath = File.join(dir, "#{emoji_hash['unicode']}.png") digest = Digest::SHA256.file(fpath).hexdigest - { name: name, unicode: emoji_hash['unicode'], digest: digest } + digests << { name: name, unicode: emoji_hash['unicode'], digest: digest } + + aliases[name].each do |alias_name| + digests << { name: alias_name, unicode: emoji_hash['unicode'], digest: digest } + end end out = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json') diff --git a/spec/controllers/groups/notification_settings_controller_spec.rb b/spec/controllers/groups/notification_settings_controller_spec.rb new file mode 100644 index 00000000000..0786e45515a --- /dev/null +++ b/spec/controllers/groups/notification_settings_controller_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe Groups::NotificationSettingsController do + let(:group) { create(:group) } + let(:user) { create(:user) } + + describe '#update' do + context 'when not authorized' do + it 'redirects to sign in page' do + put :update, + group_id: group.to_param, + notification_setting: { level: :participating } + + expect(response).to redirect_to(new_user_session_path) + end + end + + context 'when authorized' do + before do + sign_in(user) + end + + it 'returns success' do + put :update, + group_id: group.to_param, + notification_setting: { level: :participating } + + expect(response.status).to eq 200 + end + end + end +end diff --git a/spec/controllers/projects/notification_settings_controller_spec.rb b/spec/controllers/projects/notification_settings_controller_spec.rb new file mode 100644 index 00000000000..4908b545648 --- /dev/null +++ b/spec/controllers/projects/notification_settings_controller_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Projects::NotificationSettingsController do + let(:project) { create(:empty_project) } + let(:user) { create(:user) } + + before do + project.team << [user, :developer] + end + + describe '#update' do + context 'when not authorized' do + it 'redirects to sign in page' do + put :update, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + notification_setting: { level: :participating } + + expect(response).to redirect_to(new_user_session_path) + end + end + + context 'when authorized' do + before do + sign_in(user) + end + + it 'returns success' do + put :update, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + notification_setting: { level: :participating } + + expect(response.status).to eq 200 + end + end + end +end diff --git a/spec/features/merge_requests/edit_mr_spec.rb b/spec/features/merge_requests/edit_mr_spec.rb new file mode 100644 index 00000000000..9e007ab7635 --- /dev/null +++ b/spec/features/merge_requests/edit_mr_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +feature 'Edit Merge Request', feature: true do + let(:user) { create(:user) } + let(:project) { create(:project, :public) } + let(:merge_request) { create(:merge_request, :with_diffs, source_project: project) } + + before do + project.team << [user, :master] + + login_as user + + visit edit_namespace_project_merge_request_path(project.namespace, project, merge_request) + end + + context 'editing a MR' do + it 'form should have class js-quick-submit' do + expect(page).to have_selector('.js-quick-submit') + end + end +end diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index ed97b6cb577..782c0bfe666 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -100,8 +100,7 @@ feature 'Project', feature: true do it 'click toggle and show dropdown', js: true do find('.js-projects-dropdown-toggle').click - wait_for_ajax - expect(page).to have_css('.select2-results li', count: 1) + expect(page).to have_css('.dropdown-menu-projects .dropdown-content li', count: 1) end end diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb index f1aba4cfdf3..9d5f009ebe1 100644 --- a/spec/helpers/notifications_helper_spec.rb +++ b/spec/helpers/notifications_helper_spec.rb @@ -2,34 +2,15 @@ require 'spec_helper' describe NotificationsHelper do describe 'notification_icon' do - let(:notification) { double(disabled?: false, participating?: false, watch?: false) } - - context "disabled notification" do - before { allow(notification).to receive(:disabled?).and_return(true) } - - it "has a red icon" do - expect(notification_icon(notification)).to match('class="fa fa-volume-off ns-mute"') - end - end - - context "participating notification" do - before { allow(notification).to receive(:participating?).and_return(true) } - - it "has a blue icon" do - expect(notification_icon(notification)).to match('class="fa fa-volume-down ns-part"') - end - end - - context "watched notification" do - before { allow(notification).to receive(:watch?).and_return(true) } - - it "has a green icon" do - expect(notification_icon(notification)).to match('class="fa fa-volume-up ns-watch"') - end - end + it { expect(notification_icon(:disabled)).to match('class="fa fa-microphone-slash fa-fw"') } + it { expect(notification_icon(:participating)).to match('class="fa fa-volume-up fa-fw"') } + it { expect(notification_icon(:mention)).to match('class="fa fa-at fa-fw"') } + it { expect(notification_icon(:global)).to match('class="fa fa-globe fa-fw"') } + it { expect(notification_icon(:watch)).to match('class="fa fa-eye fa-fw"') } + end - it "has a blue icon" do - expect(notification_icon(notification)).to match('class="fa fa-circle-o ns-default"') - end + describe 'notification_title' do + it { expect(notification_title(:watch)).to match('Watch') } + it { expect(notification_title(:mention)).to match('On mention') } end end diff --git a/spec/javascripts/fixtures/project_title.html.haml b/spec/javascripts/fixtures/project_title.html.haml index e5850b62659..4547feeb212 100644 --- a/spec/javascripts/fixtures/project_title.html.haml +++ b/spec/javascripts/fixtures/project_title.html.haml @@ -1,7 +1,20 @@ -%h1.title - %a - GitLab Org - %a.project-item-select-holder{href: "/gitlab-org/gitlab-test"} - GitLab Test - %input#project_path.project-item-select.js-projects-dropdown.ajax-project-select{type: "hidden", name: "project_path", "data-include-groups" => "false"} - %i.fa.chevron-down.dropdown-toggle-caret.js-projects-dropdown-toggle +.header-content + %h1.title + %a + GitLab Org + %a.project-item-select-holder{href: "/gitlab-org/gitlab-test"} + GitLab Test + %i.fa.chevron-down.dropdown-toggle-caret.js-projects-dropdown-toggle{ "data-toggle" => "dropdown", "data-target" => ".header-content" } + .js-dropdown-menu-projects + .dropdown-menu.dropdown-select.dropdown-menu-projects + .dropdown-title + %span Go to a project + %button.dropdown-title-button.dropdown-menu-close{"aria-label" => "Close", type: "button"} + %i.fa.fa-times.dropdown-menu-close-icon + .dropdown-input + %input.dropdown-input-field{id: "", placeholder: "Search your projects", type: "search", value: ""} + %i.fa.fa-search.dropdown-input-search + %i.fa.fa-times.dropdown-input-clear.js-dropdown-input-clear{role: "button"} + .dropdown-content + .dropdown-loading + %i.fa.fa-spinner.fa-spin diff --git a/spec/javascripts/project_title_spec.js.coffee b/spec/javascripts/project_title_spec.js.coffee index 47c7b7febe3..3d8de2ff989 100644 --- a/spec/javascripts/project_title_spec.js.coffee +++ b/spec/javascripts/project_title_spec.js.coffee @@ -1,4 +1,6 @@ +#= require bootstrap #= require select2 +#= require gl_dropdown #= require api #= require project_select #= require project @@ -14,9 +16,6 @@ describe 'Project Title', -> fixture.load('project_title.html') @project = new Project() - spyOn(@project, 'changeProject').and.callFake (url) -> - window.current_project_url = url - describe 'project list', -> beforeEach => @projects_data = fixture.load('projects.json')[0] @@ -29,18 +28,9 @@ describe 'Project Title', -> it 'to show on toggle click', => $('.js-projects-dropdown-toggle').click() - - expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(true) - expect($('.ajax-project-dropdown li').length).toBe(@projects_data.length) + expect($('.header-content').hasClass('open')).toBe(true) it 'hide dropdown', -> - $("#select2-drop-mask").click() - - expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(false) - - it 'change project when clicking item', -> - $('.js-projects-dropdown-toggle').click() - $('.ajax-project-dropdown li:nth-child(2)').trigger('mouseup') + $(".dropdown-menu-close-icon").click() - expect($('.title .select2-container').hasClass('select2-dropdown-open')).toBe(false) - expect(window.current_project_url).toBe('http://localhost:3000/h5bp/html5-boilerplate') + expect($('.header-content').hasClass('open')).toBe(false) diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb new file mode 100644 index 00000000000..295081e9da1 --- /dev/null +++ b/spec/models/notification_setting_spec.rb @@ -0,0 +1,17 @@ +require 'rails_helper' + +RSpec.describe NotificationSetting, type: :model do + describe "Associations" do + it { is_expected.to belong_to(:user) } + it { is_expected.to belong_to(:source) } + end + + describe "Validation" do + subject { NotificationSetting.new(source_id: 1, source_type: 'Project') } + + it { is_expected.to validate_presence_of(:user) } + it { is_expected.to validate_presence_of(:source) } + it { is_expected.to validate_presence_of(:level) } + it { is_expected.to validate_uniqueness_of(:user_id).scoped_to([:source_id, :source_type]).with_message(/already exists in source/) } + end +end diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index d97bf6d38ff..344f0fe0b7f 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -50,10 +50,12 @@ describe API::API, api: true do end it 'should return a project milestone by iid' do - get api("/projects/#{project.id}/milestones?iid=#{milestone.iid}", user) + get api("/projects/#{project.id}/milestones?iid=#{closed_milestone.iid}", user) + expect(response.status).to eq 200 - expect(json_response.first['title']).to eq milestone.title - expect(json_response.first['id']).to eq milestone.id + expect(json_response.size).to eq(1) + expect(json_response.first['title']).to eq closed_milestone.title + expect(json_response.first['id']).to eq closed_milestone.id end it 'should return 401 error if user not authenticated' do diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 39f9a06fe1b..a467bc935af 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -241,4 +241,65 @@ describe API::API, api: true do end end + describe 'DELETE /projects/:id/noteable/:noteable_id/notes/:note_id' do + context 'when noteable is an Issue' do + it 'deletes a note' do + delete api("/projects/#{project.id}/issues/#{issue.id}/"\ + "notes/#{issue_note.id}", user) + + expect(response.status).to eq(200) + # Check if note is really deleted + delete api("/projects/#{project.id}/issues/#{issue.id}/"\ + "notes/#{issue_note.id}", user) + expect(response.status).to eq(404) + end + + it 'returns a 404 error when note id not found' do + delete api("/projects/#{project.id}/issues/#{issue.id}/notes/123", user) + + expect(response.status).to eq(404) + end + end + + context 'when noteable is a Snippet' do + it 'deletes a note' do + delete api("/projects/#{project.id}/snippets/#{snippet.id}/"\ + "notes/#{snippet_note.id}", user) + + expect(response.status).to eq(200) + # Check if note is really deleted + delete api("/projects/#{project.id}/snippets/#{snippet.id}/"\ + "notes/#{snippet_note.id}", user) + expect(response.status).to eq(404) + end + + it 'returns a 404 error when note id not found' do + delete api("/projects/#{project.id}/snippets/#{snippet.id}/"\ + "notes/123", user) + + expect(response.status).to eq(404) + end + end + + context 'when noteable is a Merge Request' do + it 'deletes a note' do + delete api("/projects/#{project.id}/merge_requests/"\ + "#{merge_request.id}/notes/#{merge_request_note.id}", user) + + expect(response.status).to eq(200) + # Check if note is really deleted + delete api("/projects/#{project.id}/merge_requests/"\ + "#{merge_request.id}/notes/#{merge_request_note.id}", user) + expect(response.status).to eq(404) + end + + it 'returns a 404 error when note id not found' do + delete api("/projects/#{project.id}/merge_requests/"\ + "#{merge_request.id}/notes/123", user) + + expect(response.status).to eq(404) + end + end + end + end diff --git a/spec/requests/api/project_members_spec.rb b/spec/requests/api/project_members_spec.rb index 4301588b16a..c112ca5e3ca 100644 --- a/spec/requests/api/project_members_spec.rb +++ b/spec/requests/api/project_members_spec.rb @@ -118,8 +118,10 @@ describe API::API, api: true do end describe "DELETE /projects/:id/members/:user_id" do - before { project_member } - before { project_member2 } + before do + project_member + project_member2 + end it "should remove user from project team" do expect do @@ -132,6 +134,7 @@ describe API::API, api: true do expect do delete api("/projects/#{project.id}/members/#{user3.id}", user) end.to_not change { ProjectMember.count } + expect(response.status).to eq(200) end it "should return 200 if team member already removed" do @@ -145,8 +148,19 @@ describe API::API, api: true do delete api("/projects/#{project.id}/members/1000000", user) end.to change { ProjectMember.count }.by(0) expect(response.status).to eq(200) - expect(json_response['message']).to eq("Access revoked") expect(json_response['id']).to eq(1000000) + expect(json_response['message']).to eq('Access revoked') + end + + context 'when the user is not an admin or owner' do + it 'can leave the project' do + expect do + delete api("/projects/#{project.id}/members/#{user3.id}", user3) + end.to change { ProjectMember.count }.by(-1) + + expect(response.status).to eq(200) + expect(json_response['id']).to eq(project_member2.id) + end end end end diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb index a15be07ed57..9f9c3b1cf4c 100644 --- a/spec/requests/api/tags_spec.rb +++ b/spec/requests/api/tags_spec.rb @@ -40,6 +40,23 @@ describe API::API, api: true do end end + describe 'GET /projects/:id/repository/tags/:tag_name' do + let(:tag_name) { project.repository.tag_names.sort.reverse.first } + + it 'returns a specific tag' do + get api("/projects/#{project.id}/repository/tags/#{tag_name}", user) + + expect(response.status).to eq(200) + expect(json_response['name']).to eq(tag_name) + end + + it 'returns 404 for an invalid tag name' do + get api("/projects/#{project.id}/repository/tags/foobar", user) + + expect(response.status).to eq(404) + end + end + describe 'POST /projects/:id/repository/tags' do context 'lightweight tags' do it 'should create a new tag' do diff --git a/spec/services/notes/delete_service_spec.rb b/spec/services/notes/delete_service_spec.rb new file mode 100644 index 00000000000..1d0a747a480 --- /dev/null +++ b/spec/services/notes/delete_service_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe Notes::DeleteService, services: true do + describe '#execute' do + it 'deletes a note' do + project = create(:empty_project) + issue = create(:issue, project: project) + note = create(:note, project: project, noteable: issue) + + described_class.new(project, note.author).execute(note) + + expect(project.issues.find(issue.id).notes).not_to include(note) + end + end +end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 0f2aa3ae73c..d7c72dc0811 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -88,12 +88,9 @@ describe NotificationService, services: true do note.project.namespace_id = group.id note.project.group.add_user(@u_watcher, GroupMember::MASTER) note.project.save - user_project = note.project.project_members.find_by_user_id(@u_watcher.id) - user_project.notification_level = Notification::N_PARTICIPATING - user_project.save - group_member = note.project.group.group_members.find_by_user_id(@u_watcher.id) - group_member.notification_level = Notification::N_GLOBAL - group_member.save + + @u_watcher.notification_settings_for(note.project).participating! + @u_watcher.notification_settings_for(note.project.group).global! ActionMailer::Base.deliveries.clear end @@ -215,7 +212,7 @@ describe NotificationService, services: true do end it do - @u_committer.update_attributes(notification_level: Notification::N_MENTION) + @u_committer.update_attributes(notification_level: :mention) notification.new_note(note) should_not_email(@u_committer) end @@ -246,7 +243,7 @@ describe NotificationService, services: true do end it do - issue.assignee.update_attributes(notification_level: Notification::N_MENTION) + issue.assignee.update_attributes(notification_level: :mention) notification.new_issue(issue, @u_disabled) should_not_email(issue.assignee) @@ -596,13 +593,13 @@ describe NotificationService, services: true do end def build_team(project) - @u_watcher = create(:user, notification_level: Notification::N_WATCH) - @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING) - @u_participant_mentioned = create(:user, username: 'participant', notification_level: Notification::N_PARTICIPATING) - @u_disabled = create(:user, notification_level: Notification::N_DISABLED) - @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_MENTION) + @u_watcher = create(:user, notification_level: :watch) + @u_participating = create(:user, notification_level: :participating) + @u_participant_mentioned = create(:user, username: 'participant', notification_level: :participating) + @u_disabled = create(:user, notification_level: :disabled) + @u_mentioned = create(:user, username: 'mention', notification_level: :mention) @u_committer = create(:user, username: 'committer') - @u_not_mentioned = create(:user, username: 'regular', notification_level: Notification::N_PARTICIPATING) + @u_not_mentioned = create(:user, username: 'regular', notification_level: :participating) @u_outsider_mentioned = create(:user, username: 'outsider') project.team << [@u_watcher, :master] @@ -617,8 +614,8 @@ describe NotificationService, services: true do def add_users_with_subscription(project, issuable) @subscriber = create :user @unsubscriber = create :user - @subscribed_participant = create(:user, username: 'subscribed_participant', notification_level: Notification::N_PARTICIPATING) - @watcher_and_subscriber = create(:user, notification_level: Notification::N_WATCH) + @subscribed_participant = create(:user, username: 'subscribed_participant', notification_level: :participating) + @watcher_and_subscriber = create(:user, notification_level: :watch) project.team << [@subscribed_participant, :master] project.team << [@subscriber, :master] diff --git a/vendor/assets/javascripts/date.format.js b/vendor/assets/javascripts/date.format.js new file mode 100644 index 00000000000..f5dc4abcd80 --- /dev/null +++ b/vendor/assets/javascripts/date.format.js @@ -0,0 +1,125 @@ +/* + * Date Format 1.2.3 + * (c) 2007-2009 Steven Levithan <stevenlevithan.com> + * MIT license + * + * Includes enhancements by Scott Trenda <scott.trenda.net> + * and Kris Kowal <cixar.com/~kris.kowal/> + * + * Accepts a date, a mask, or a date and a mask. + * Returns a formatted version of the given date. + * The date defaults to the current date/time. + * The mask defaults to dateFormat.masks.default. + */ + +var dateFormat = function () { + var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, + timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, + timezoneClip = /[^-+\dA-Z]/g, + pad = function (val, len) { + val = String(val); + len = len || 2; + while (val.length < len) val = "0" + val; + return val; + }; + + // Regexes and supporting functions are cached through closure + return function (date, mask, utc) { + var dF = dateFormat; + + // You can't provide utc if you skip other args (use the "UTC:" mask prefix) + if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { + mask = date; + date = undefined; + } + + // Passing date through Date applies Date.parse, if necessary + date = date ? new Date(date) : new Date; + if (isNaN(date)) throw SyntaxError("invalid date"); + + mask = String(dF.masks[mask] || mask || dF.masks["default"]); + + // Allow setting the utc argument via the mask + if (mask.slice(0, 4) == "UTC:") { + mask = mask.slice(4); + utc = true; + } + + var _ = utc ? "getUTC" : "get", + d = date[_ + "Date"](), + D = date[_ + "Day"](), + m = date[_ + "Month"](), + y = date[_ + "FullYear"](), + H = date[_ + "Hours"](), + M = date[_ + "Minutes"](), + s = date[_ + "Seconds"](), + L = date[_ + "Milliseconds"](), + o = utc ? 0 : date.getTimezoneOffset(), + flags = { + d: d, + dd: pad(d), + ddd: dF.i18n.dayNames[D], + dddd: dF.i18n.dayNames[D + 7], + m: m + 1, + mm: pad(m + 1), + mmm: dF.i18n.monthNames[m], + mmmm: dF.i18n.monthNames[m + 12], + yy: String(y).slice(2), + yyyy: y, + h: H % 12 || 12, + hh: pad(H % 12 || 12), + H: H, + HH: pad(H), + M: M, + MM: pad(M), + s: s, + ss: pad(s), + l: pad(L, 3), + L: pad(L > 99 ? Math.round(L / 10) : L), + t: H < 12 ? "a" : "p", + tt: H < 12 ? "am" : "pm", + T: H < 12 ? "A" : "P", + TT: H < 12 ? "AM" : "PM", + Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), + o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), + S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] + }; + + return mask.replace(token, function ($0) { + return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); + }); + }; +}(); + +// Some common format strings +dateFormat.masks = { + "default": "ddd mmm dd yyyy HH:MM:ss", + shortDate: "m/d/yy", + mediumDate: "mmm d, yyyy", + longDate: "mmmm d, yyyy", + fullDate: "dddd, mmmm d, yyyy", + shortTime: "h:MM TT", + mediumTime: "h:MM:ss TT", + longTime: "h:MM:ss TT Z", + isoDate: "yyyy-mm-dd", + isoTime: "HH:MM:ss", + isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", + isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" +}; + +// Internationalization strings +dateFormat.i18n = { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ] +}; + +// For convenience... +Date.prototype.format = function (mask, utc) { + return dateFormat(this, mask, utc); +}; |