diff options
Diffstat (limited to 'app')
125 files changed, 3546 insertions, 1658 deletions
diff --git a/app/assets/images/emoji.png b/app/assets/images/emoji.png Binary files differindex a8ad7b6eab6..1e7cf79ea45 100644 --- a/app/assets/images/emoji.png +++ b/app/assets/images/emoji.png diff --git a/app/assets/images/emoji@2x.png b/app/assets/images/emoji@2x.png Binary files differnew file mode 100644 index 00000000000..74d67f7520d --- /dev/null +++ b/app/assets/images/emoji@2x.png diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index b17f8e51470..407005d8adf 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -91,7 +91,7 @@ class Dispatcher new TreeView() when 'projects:find_file:show' shortcut_handler = true - when 'projects:blob:show' + when 'projects:blob:show', 'projects:blame:show' new LineHighlighter() shortcut_handler = new ShortcutsNavigation() when 'projects:labels:new', 'projects:labels:edit' diff --git a/app/assets/javascripts/issuable_context.js.coffee b/app/assets/javascripts/issuable_context.js.coffee index d17b1123418..e52b73f94f6 100644 --- a/app/assets/javascripts/issuable_context.js.coffee +++ b/app/assets/javascripts/issuable_context.js.coffee @@ -15,3 +15,5 @@ class @IssuableContext block.find('.selectbox').show() block.find('.value').hide() block.find('.js-select2').select2("open") + + $(".right-sidebar").niceScroll() diff --git a/app/assets/javascripts/merge_request_tabs.js.coffee b/app/assets/javascripts/merge_request_tabs.js.coffee index b10e1db7f3f..6f569f9e1aa 100644 --- a/app/assets/javascripts/merge_request_tabs.js.coffee +++ b/app/assets/javascripts/merge_request_tabs.js.coffee @@ -146,6 +146,7 @@ class @MergeRequestTabs success: (data) => document.querySelector("div#diffs").innerHTML = data.html $('div#diffs .js-syntax-highlight').syntaxHighlight() + @expandViewContainer() if @diffViewType() is 'parallel' @diffsLoaded = true @scrollToElement("#diffs") @@ -177,3 +178,10 @@ class @MergeRequestTabs options = $.extend({}, defaults, options) $.ajax(options) + + # Returns diff view type + diffViewType: -> + $('.inline-parallel-buttons a.active').data('view-type') + + expandViewContainer: -> + $('.container-fluid').removeClass('container-limited') diff --git a/app/assets/javascripts/milestone.js.coffee b/app/assets/javascripts/milestone.js.coffee index d644d50b669..31f6c6d3d47 100644 --- a/app/assets/javascripts/milestone.js.coffee +++ b/app/assets/javascripts/milestone.js.coffee @@ -64,6 +64,7 @@ class @Milestone constructor: -> @bindIssuesSorting() @bindMergeRequestSorting() + @bindTabsSwitching bindIssuesSorting: -> $("#issues-list-unassigned, #issues-list-ongoing, #issues-list-closed").sortable( @@ -122,3 +123,12 @@ class @Milestone Milestone.updateMergeRequest(ui.item, merge_request_url, data) ).disableSelection() + + bindMergeRequestSorting: -> + $('a[data-toggle="tab"]').on 'show.bs.tab', (e) -> + currentTabClass = $(e.target).data('show') + previousTabClass = $(e.relatedTarget).data('show') + + $(previousTabClass).hide() + $(currentTabClass).removeClass('hidden') + $(currentTabClass).show() diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index ea56d9e12a0..0ddbf612543 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -377,7 +377,6 @@ table { } .project-item-select-holder { - display: inline-block; position: relative; .project-item-select { diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss index 8d9a0aae568..12cef6f8ea1 100644 --- a/app/assets/stylesheets/framework/gitlab-theme.scss +++ b/app/assets/stylesheets/framework/gitlab-theme.scss @@ -117,4 +117,4 @@ body { &.ui_violet { @include gitlab-theme(#9988CC, $theme-violet, #443366, #332255); } -} +}
\ No newline at end of file diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 93d74bf30f1..24e7d971768 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -77,6 +77,7 @@ header { line-height: $header-height; font-weight: normal; color: #4c4e54; + overflow: hidden; text-overflow: ellipsis; vertical-align: top; white-space: nowrap; diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss index 9854df4c45c..12e2f00fe89 100644 --- a/app/assets/stylesheets/framework/highlight.scss +++ b/app/assets/stylesheets/framework/highlight.scss @@ -44,8 +44,10 @@ white-space: nowrap; i { + float: left; + margin-top: 3px; + margin-right: 5px; visibility: hidden; - @extend .pull-left; } &:hover i { diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss index 08dcb563dce..5d7fd36be16 100644 --- a/app/assets/stylesheets/framework/issue_box.scss +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -6,31 +6,28 @@ .status-box { @include border-radius(3px); - display: block; float: left; padding: 0 $gl-btn-padding; - font-weight: normal; + margin-top: 5px; margin-right: 10px; + color: #FFF; font-size: $gl-font-size; + line-height: 25px; &.status-box-closed { background-color: $gl-danger; - color: #FFF; } &.status-box-merged { background-color: $gl-primary; - color: #FFF; } &.status-box-open { background-color: $green-light; - color: #FFF; } &.status-box-expired { background: #cea61b; - color: #FFF; } } diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss index 529a43548c8..d93b6ee6733 100644 --- a/app/assets/stylesheets/pages/detail_page.scss +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -12,6 +12,14 @@ .identifier { color: #5c5d5e; } + + .issue_created_ago, .author_link { + white-space: nowrap; + } + + .issue-meta { + margin-left: 65px + } } .detail-page-description { diff --git a/app/assets/stylesheets/pages/emojis.scss b/app/assets/stylesheets/pages/emojis.scss index 89a94c5a780..6c721b514f8 100644 --- a/app/assets/stylesheets/pages/emojis.scss +++ b/app/assets/stylesheets/pages/emojis.scss @@ -1,1272 +1,1736 @@ -/* -File is generated by https://github.com/jakesgordon/sprite-factory and midified manualy -The source: gemojione gem. -*/ +.emoji-0023-20E3 { background-position: 0px 0px; } +.emoji-002A-20E3 { background-position: -20px 0px; } +.emoji-0030-20E3 { background-position: 0px -20px; } +.emoji-0031-20E3 { background-position: -20px -20px; } +.emoji-0032-20E3 { background-position: -40px 0px; } +.emoji-0033-20E3 { background-position: -40px -20px; } +.emoji-0034-20E3 { background-position: 0px -40px; } +.emoji-0035-20E3 { background-position: -20px -40px; } +.emoji-0036-20E3 { background-position: -40px -40px; } +.emoji-0037-20E3 { background-position: -60px 0px; } +.emoji-0038-20E3 { background-position: -60px -20px; } +.emoji-0039-20E3 { background-position: -60px -40px; } +.emoji-00A9 { background-position: 0px -60px; } +.emoji-00AE { background-position: -20px -60px; } +.emoji-1F004 { background-position: -40px -60px; } +.emoji-1F0CF { background-position: -60px -60px; } +.emoji-1F170 { background-position: -80px 0px; } +.emoji-1F171 { background-position: -80px -20px; } +.emoji-1F17E { background-position: -80px -40px; } +.emoji-1F17F { background-position: -80px -60px; } +.emoji-1F18E { background-position: 0px -80px; } +.emoji-1F191 { background-position: -20px -80px; } +.emoji-1F192 { background-position: -40px -80px; } +.emoji-1F193 { background-position: -60px -80px; } +.emoji-1F194 { background-position: -80px -80px; } +.emoji-1F195 { background-position: -100px 0px; } +.emoji-1F196 { background-position: -100px -20px; } +.emoji-1F197 { background-position: -100px -40px; } +.emoji-1F198 { background-position: -100px -60px; } +.emoji-1F199 { background-position: -100px -80px; } +.emoji-1F19A { background-position: 0px -100px; } +.emoji-1F1E6-1F1E8 { background-position: -20px -100px; } +.emoji-1F1E6-1F1E9 { background-position: -40px -100px; } +.emoji-1F1E6-1F1EA { background-position: -60px -100px; } +.emoji-1F1E6-1F1EB { background-position: -80px -100px; } +.emoji-1F1E6-1F1EC { background-position: -100px -100px; } +.emoji-1F1E6-1F1EE { background-position: -120px 0px; } +.emoji-1F1E6-1F1F1 { background-position: -120px -20px; } +.emoji-1F1E6-1F1F2 { background-position: -120px -40px; } +.emoji-1F1E6-1F1F4 { background-position: -120px -60px; } +.emoji-1F1E6-1F1F6 { background-position: -120px -80px; } +.emoji-1F1E6-1F1F7 { background-position: -120px -100px; } +.emoji-1F1E6-1F1F8 { background-position: 0px -120px; } +.emoji-1F1E6-1F1F9 { background-position: -20px -120px; } +.emoji-1F1E6-1F1FA { background-position: -40px -120px; } +.emoji-1F1E6-1F1FC { background-position: -60px -120px; } +.emoji-1F1E6-1F1FD { background-position: -80px -120px; } +.emoji-1F1E6-1F1FF { background-position: -100px -120px; } +.emoji-1F1E7-1F1E6 { background-position: -120px -120px; } +.emoji-1F1E7-1F1E7 { background-position: -140px 0px; } +.emoji-1F1E7-1F1E9 { background-position: -140px -20px; } +.emoji-1F1E7-1F1EA { background-position: -140px -40px; } +.emoji-1F1E7-1F1EB { background-position: -140px -60px; } +.emoji-1F1E7-1F1EC { background-position: -140px -80px; } +.emoji-1F1E7-1F1ED { background-position: -140px -100px; } +.emoji-1F1E7-1F1EE { background-position: -140px -120px; } +.emoji-1F1E7-1F1EF { background-position: 0px -140px; } +.emoji-1F1E7-1F1F1 { background-position: -20px -140px; } +.emoji-1F1E7-1F1F2 { background-position: -40px -140px; } +.emoji-1F1E7-1F1F3 { background-position: -60px -140px; } +.emoji-1F1E7-1F1F4 { background-position: -80px -140px; } +.emoji-1F1E7-1F1F6 { background-position: -100px -140px; } +.emoji-1F1E7-1F1F7 { background-position: -120px -140px; } +.emoji-1F1E7-1F1F8 { background-position: -140px -140px; } +.emoji-1F1E7-1F1F9 { background-position: -160px 0px; } +.emoji-1F1E7-1F1FB { background-position: -160px -20px; } +.emoji-1F1E7-1F1FC { background-position: -160px -40px; } +.emoji-1F1E7-1F1FE { background-position: -160px -60px; } +.emoji-1F1E7-1F1FF { background-position: -160px -80px; } +.emoji-1F1E8-1F1E6 { background-position: -160px -100px; } +.emoji-1F1E8-1F1E8 { background-position: -160px -120px; } +.emoji-1F1E8-1F1E9 { background-position: -160px -140px; } +.emoji-1F1E8-1F1EB { background-position: 0px -160px; } +.emoji-1F1E8-1F1EC { background-position: -20px -160px; } +.emoji-1F1E8-1F1ED { background-position: -40px -160px; } +.emoji-1F1E8-1F1EE { background-position: -60px -160px; } +.emoji-1F1E8-1F1F0 { background-position: -80px -160px; } +.emoji-1F1E8-1F1F1 { background-position: -100px -160px; } +.emoji-1F1E8-1F1F2 { background-position: -120px -160px; } +.emoji-1F1E8-1F1F3 { background-position: -140px -160px; } +.emoji-1F1E8-1F1F4 { background-position: -160px -160px; } +.emoji-1F1E8-1F1F5 { background-position: -180px 0px; } +.emoji-1F1E8-1F1F7 { background-position: -180px -20px; } +.emoji-1F1E8-1F1FA { background-position: -180px -40px; } +.emoji-1F1E8-1F1FB { background-position: -180px -60px; } +.emoji-1F1E8-1F1FC { background-position: -180px -80px; } +.emoji-1F1E8-1F1FD { background-position: -180px -100px; } +.emoji-1F1E8-1F1FE { background-position: -180px -120px; } +.emoji-1F1E8-1F1FF { background-position: -180px -140px; } +.emoji-1F1E9-1F1EA { background-position: -180px -160px; } +.emoji-1F1E9-1F1EC { background-position: 0px -180px; } +.emoji-1F1E9-1F1EF { background-position: -20px -180px; } +.emoji-1F1E9-1F1F0 { background-position: -40px -180px; } +.emoji-1F1E9-1F1F2 { background-position: -60px -180px; } +.emoji-1F1E9-1F1F4 { background-position: -80px -180px; } +.emoji-1F1E9-1F1FF { background-position: -100px -180px; } +.emoji-1F1EA-1F1E6 { background-position: -120px -180px; } +.emoji-1F1EA-1F1E8 { background-position: -140px -180px; } +.emoji-1F1EA-1F1EA { background-position: -160px -180px; } +.emoji-1F1EA-1F1EC { background-position: -180px -180px; } +.emoji-1F1EA-1F1ED { background-position: -200px 0px; } +.emoji-1F1EA-1F1F7 { background-position: -200px -20px; } +.emoji-1F1EA-1F1F8 { background-position: -200px -40px; } +.emoji-1F1EA-1F1F9 { background-position: -200px -60px; } +.emoji-1F1EA-1F1FA { background-position: -200px -80px; } +.emoji-1F1EB-1F1EE { background-position: -200px -100px; } +.emoji-1F1EB-1F1EF { background-position: -200px -120px; } +.emoji-1F1EB-1F1F0 { background-position: -200px -140px; } +.emoji-1F1EB-1F1F2 { background-position: -200px -160px; } +.emoji-1F1EB-1F1F4 { background-position: -200px -180px; } +.emoji-1F1EB-1F1F7 { background-position: 0px -200px; } +.emoji-1F1EC-1F1E6 { background-position: -20px -200px; } +.emoji-1F1EC-1F1E7 { background-position: -40px -200px; } +.emoji-1F1EC-1F1E9 { background-position: -60px -200px; } +.emoji-1F1EC-1F1EA { background-position: -80px -200px; } +.emoji-1F1EC-1F1EB { background-position: -100px -200px; } +.emoji-1F1EC-1F1EC { background-position: -120px -200px; } +.emoji-1F1EC-1F1ED { background-position: -140px -200px; } +.emoji-1F1EC-1F1EE { background-position: -160px -200px; } +.emoji-1F1EC-1F1F1 { background-position: -180px -200px; } +.emoji-1F1EC-1F1F2 { background-position: -200px -200px; } +.emoji-1F1EC-1F1F3 { background-position: -220px 0px; } +.emoji-1F1EC-1F1F5 { background-position: -220px -20px; } +.emoji-1F1EC-1F1F6 { background-position: -220px -40px; } +.emoji-1F1EC-1F1F7 { background-position: -220px -60px; } +.emoji-1F1EC-1F1F8 { background-position: -220px -80px; } +.emoji-1F1EC-1F1F9 { background-position: -220px -100px; } +.emoji-1F1EC-1F1FA { background-position: -220px -120px; } +.emoji-1F1EC-1F1FC { background-position: -220px -140px; } +.emoji-1F1EC-1F1FE { background-position: -220px -160px; } +.emoji-1F1ED-1F1F0 { background-position: -220px -180px; } +.emoji-1F1ED-1F1F2 { background-position: -220px -200px; } +.emoji-1F1ED-1F1F3 { background-position: 0px -220px; } +.emoji-1F1ED-1F1F7 { background-position: -20px -220px; } +.emoji-1F1ED-1F1F9 { background-position: -40px -220px; } +.emoji-1F1ED-1F1FA { background-position: -60px -220px; } +.emoji-1F1EE-1F1E8 { background-position: -80px -220px; } +.emoji-1F1EE-1F1E9 { background-position: -100px -220px; } +.emoji-1F1EE-1F1EA { background-position: -120px -220px; } +.emoji-1F1EE-1F1F1 { background-position: -140px -220px; } +.emoji-1F1EE-1F1F2 { background-position: -160px -220px; } +.emoji-1F1EE-1F1F3 { background-position: -180px -220px; } +.emoji-1F1EE-1F1F4 { background-position: -200px -220px; } +.emoji-1F1EE-1F1F6 { background-position: -220px -220px; } +.emoji-1F1EE-1F1F7 { background-position: -240px 0px; } +.emoji-1F1EE-1F1F8 { background-position: -240px -20px; } +.emoji-1F1EE-1F1F9 { background-position: -240px -40px; } +.emoji-1F1EF-1F1EA { background-position: -240px -60px; } +.emoji-1F1EF-1F1F2 { background-position: -240px -80px; } +.emoji-1F1EF-1F1F4 { background-position: -240px -100px; } +.emoji-1F1EF-1F1F5 { background-position: -240px -120px; } +.emoji-1F1F0-1F1EA { background-position: -240px -140px; } +.emoji-1F1F0-1F1EC { background-position: -240px -160px; } +.emoji-1F1F0-1F1ED { background-position: -240px -180px; } +.emoji-1F1F0-1F1EE { background-position: -240px -200px; } +.emoji-1F1F0-1F1F2 { background-position: -240px -220px; } +.emoji-1F1F0-1F1F3 { background-position: 0px -240px; } +.emoji-1F1F0-1F1F5 { background-position: -20px -240px; } +.emoji-1F1F0-1F1F7 { background-position: -40px -240px; } +.emoji-1F1F0-1F1FC { background-position: -60px -240px; } +.emoji-1F1F0-1F1FE { background-position: -80px -240px; } +.emoji-1F1F0-1F1FF { background-position: -100px -240px; } +.emoji-1F1F1-1F1E6 { background-position: -120px -240px; } +.emoji-1F1F1-1F1E7 { background-position: -140px -240px; } +.emoji-1F1F1-1F1E8 { background-position: -160px -240px; } +.emoji-1F1F1-1F1EE { background-position: -180px -240px; } +.emoji-1F1F1-1F1F0 { background-position: -200px -240px; } +.emoji-1F1F1-1F1F7 { background-position: -220px -240px; } +.emoji-1F1F1-1F1F8 { background-position: -240px -240px; } +.emoji-1F1F1-1F1F9 { background-position: -260px 0px; } +.emoji-1F1F1-1F1FA { background-position: -260px -20px; } +.emoji-1F1F1-1F1FB { background-position: -260px -40px; } +.emoji-1F1F1-1F1FE { background-position: -260px -60px; } +.emoji-1F1F2-1F1E6 { background-position: -260px -80px; } +.emoji-1F1F2-1F1E8 { background-position: -260px -100px; } +.emoji-1F1F2-1F1E9 { background-position: -260px -120px; } +.emoji-1F1F2-1F1EA { background-position: -260px -140px; } +.emoji-1F1F2-1F1EB { background-position: -260px -160px; } +.emoji-1F1F2-1F1EC { background-position: -260px -180px; } +.emoji-1F1F2-1F1ED { background-position: -260px -200px; } +.emoji-1F1F2-1F1F0 { background-position: -260px -220px; } +.emoji-1F1F2-1F1F1 { background-position: -260px -240px; } +.emoji-1F1F2-1F1F2 { background-position: 0px -260px; } +.emoji-1F1F2-1F1F3 { background-position: -20px -260px; } +.emoji-1F1F2-1F1F4 { background-position: -40px -260px; } +.emoji-1F1F2-1F1F5 { background-position: -60px -260px; } +.emoji-1F1F2-1F1F6 { background-position: -80px -260px; } +.emoji-1F1F2-1F1F7 { background-position: -100px -260px; } +.emoji-1F1F2-1F1F8 { background-position: -120px -260px; } +.emoji-1F1F2-1F1F9 { background-position: -140px -260px; } +.emoji-1F1F2-1F1FA { background-position: -160px -260px; } +.emoji-1F1F2-1F1FB { background-position: -180px -260px; } +.emoji-1F1F2-1F1FC { background-position: -200px -260px; } +.emoji-1F1F2-1F1FD { background-position: -220px -260px; } +.emoji-1F1F2-1F1FE { background-position: -240px -260px; } +.emoji-1F1F2-1F1FF { background-position: -260px -260px; } +.emoji-1F1F3-1F1E6 { background-position: -280px 0px; } +.emoji-1F1F3-1F1E8 { background-position: -280px -20px; } +.emoji-1F1F3-1F1EA { background-position: -280px -40px; } +.emoji-1F1F3-1F1EB { background-position: -280px -60px; } +.emoji-1F1F3-1F1EC { background-position: -280px -80px; } +.emoji-1F1F3-1F1EE { background-position: -280px -100px; } +.emoji-1F1F3-1F1F1 { background-position: -280px -120px; } +.emoji-1F1F3-1F1F4 { background-position: -280px -140px; } +.emoji-1F1F3-1F1F5 { background-position: -280px -160px; } +.emoji-1F1F3-1F1F7 { background-position: -280px -180px; } +.emoji-1F1F3-1F1FA { background-position: -280px -200px; } +.emoji-1F1F3-1F1FF { background-position: -280px -220px; } +.emoji-1F1F4-1F1F2 { background-position: -280px -240px; } +.emoji-1F1F5-1F1E6 { background-position: -280px -260px; } +.emoji-1F1F5-1F1EA { background-position: 0px -280px; } +.emoji-1F1F5-1F1EB { background-position: -20px -280px; } +.emoji-1F1F5-1F1EC { background-position: -40px -280px; } +.emoji-1F1F5-1F1ED { background-position: -60px -280px; } +.emoji-1F1F5-1F1F0 { background-position: -80px -280px; } +.emoji-1F1F5-1F1F1 { background-position: -100px -280px; } +.emoji-1F1F5-1F1F2 { background-position: -120px -280px; } +.emoji-1F1F5-1F1F3 { background-position: -140px -280px; } +.emoji-1F1F5-1F1F7 { background-position: -160px -280px; } +.emoji-1F1F5-1F1F8 { background-position: -180px -280px; } +.emoji-1F1F5-1F1F9 { background-position: -200px -280px; } +.emoji-1F1F5-1F1FC { background-position: -220px -280px; } +.emoji-1F1F5-1F1FE { background-position: -240px -280px; } +.emoji-1F1F6-1F1E6 { background-position: -260px -280px; } +.emoji-1F1F7-1F1EA { background-position: -280px -280px; } +.emoji-1F1F7-1F1F4 { background-position: -300px 0px; } +.emoji-1F1F7-1F1F8 { background-position: -300px -20px; } +.emoji-1F1F7-1F1FA { background-position: -300px -40px; } +.emoji-1F1F7-1F1FC { background-position: -300px -60px; } +.emoji-1F1F8-1F1E6 { background-position: -300px -80px; } +.emoji-1F1F8-1F1E7 { background-position: -300px -100px; } +.emoji-1F1F8-1F1E8 { background-position: -300px -120px; } +.emoji-1F1F8-1F1E9 { background-position: -300px -140px; } +.emoji-1F1F8-1F1EA { background-position: -300px -160px; } +.emoji-1F1F8-1F1EC { background-position: -300px -180px; } +.emoji-1F1F8-1F1ED { background-position: -300px -200px; } +.emoji-1F1F8-1F1EE { background-position: -300px -220px; } +.emoji-1F1F8-1F1EF { background-position: -300px -240px; } +.emoji-1F1F8-1F1F0 { background-position: -300px -260px; } +.emoji-1F1F8-1F1F1 { background-position: -300px -280px; } +.emoji-1F1F8-1F1F2 { background-position: 0px -300px; } +.emoji-1F1F8-1F1F3 { background-position: -20px -300px; } +.emoji-1F1F8-1F1F4 { background-position: -40px -300px; } +.emoji-1F1F8-1F1F7 { background-position: -60px -300px; } +.emoji-1F1F8-1F1F8 { background-position: -80px -300px; } +.emoji-1F1F8-1F1F9 { background-position: -100px -300px; } +.emoji-1F1F8-1F1FB { background-position: -120px -300px; } +.emoji-1F1F8-1F1FD { background-position: -140px -300px; } +.emoji-1F1F8-1F1FE { background-position: -160px -300px; } +.emoji-1F1F8-1F1FF { background-position: -180px -300px; } +.emoji-1F1F9-1F1E6 { background-position: -200px -300px; } +.emoji-1F1F9-1F1E8 { background-position: -220px -300px; } +.emoji-1F1F9-1F1E9 { background-position: -240px -300px; } +.emoji-1F1F9-1F1EB { background-position: -260px -300px; } +.emoji-1F1F9-1F1EC { background-position: -280px -300px; } +.emoji-1F1F9-1F1ED { background-position: -300px -300px; } +.emoji-1F1F9-1F1EF { background-position: -320px 0px; } +.emoji-1F1F9-1F1F0 { background-position: -320px -20px; } +.emoji-1F1F9-1F1F1 { background-position: -320px -40px; } +.emoji-1F1F9-1F1F2 { background-position: -320px -60px; } +.emoji-1F1F9-1F1F3 { background-position: -320px -80px; } +.emoji-1F1F9-1F1F4 { background-position: -320px -100px; } +.emoji-1F1F9-1F1F7 { background-position: -320px -120px; } +.emoji-1F1F9-1F1F9 { background-position: -320px -140px; } +.emoji-1F1F9-1F1FB { background-position: -320px -160px; } +.emoji-1F1F9-1F1FC { background-position: -320px -180px; } +.emoji-1F1F9-1F1FF { background-position: -320px -200px; } +.emoji-1F1FA-1F1E6 { background-position: -320px -220px; } +.emoji-1F1FA-1F1EC { background-position: -320px -240px; } +.emoji-1F1FA-1F1F2 { background-position: -320px -260px; } +.emoji-1F1FA-1F1F8 { background-position: -320px -280px; } +.emoji-1F1FA-1F1FE { background-position: -320px -300px; } +.emoji-1F1FA-1F1FF { background-position: 0px -320px; } +.emoji-1F1FB-1F1E6 { background-position: -20px -320px; } +.emoji-1F1FB-1F1E8 { background-position: -40px -320px; } +.emoji-1F1FB-1F1EA { background-position: -60px -320px; } +.emoji-1F1FB-1F1EC { background-position: -80px -320px; } +.emoji-1F1FB-1F1EE { background-position: -100px -320px; } +.emoji-1F1FB-1F1F3 { background-position: -120px -320px; } +.emoji-1F1FB-1F1FA { background-position: -140px -320px; } +.emoji-1F1FC-1F1EB { background-position: -160px -320px; } +.emoji-1F1FC-1F1F8 { background-position: -180px -320px; } +.emoji-1F1FD-1F1F0 { background-position: -200px -320px; } +.emoji-1F1FE-1F1EA { background-position: -220px -320px; } +.emoji-1F1FE-1F1F9 { background-position: -240px -320px; } +.emoji-1F1FF-1F1E6 { background-position: -260px -320px; } +.emoji-1F1FF-1F1F2 { background-position: -280px -320px; } +.emoji-1F1FF-1F1FC { background-position: -300px -320px; } +.emoji-1F201 { background-position: -320px -320px; } +.emoji-1F202 { background-position: -340px 0px; } +.emoji-1F21A { background-position: -340px -20px; } +.emoji-1F22F { background-position: -340px -40px; } +.emoji-1F232 { background-position: -340px -60px; } +.emoji-1F233 { background-position: -340px -80px; } +.emoji-1F234 { background-position: -340px -100px; } +.emoji-1F235 { background-position: -340px -120px; } +.emoji-1F236 { background-position: -340px -140px; } +.emoji-1F237 { background-position: -340px -160px; } +.emoji-1F238 { background-position: -340px -180px; } +.emoji-1F239 { background-position: -340px -200px; } +.emoji-1F23A { background-position: -340px -220px; } +.emoji-1F250 { background-position: -340px -240px; } +.emoji-1F251 { background-position: -340px -260px; } +.emoji-1F300 { background-position: -340px -280px; } +.emoji-1F301 { background-position: -340px -300px; } +.emoji-1F302 { background-position: -340px -320px; } +.emoji-1F303 { background-position: 0px -340px; } +.emoji-1F304 { background-position: -20px -340px; } +.emoji-1F305 { background-position: -40px -340px; } +.emoji-1F306 { background-position: -60px -340px; } +.emoji-1F307 { background-position: -80px -340px; } +.emoji-1F308 { background-position: -100px -340px; } +.emoji-1F309 { background-position: -120px -340px; } +.emoji-1F30A { background-position: -140px -340px; } +.emoji-1F30B { background-position: -160px -340px; } +.emoji-1F30C { background-position: -180px -340px; } +.emoji-1F30D { background-position: -200px -340px; } +.emoji-1F30E { background-position: -220px -340px; } +.emoji-1F30F { background-position: -240px -340px; } +.emoji-1F310 { background-position: -260px -340px; } +.emoji-1F311 { background-position: -280px -340px; } +.emoji-1F312 { background-position: -300px -340px; } +.emoji-1F313 { background-position: -320px -340px; } +.emoji-1F314 { background-position: -340px -340px; } +.emoji-1F315 { background-position: -360px 0px; } +.emoji-1F316 { background-position: -360px -20px; } +.emoji-1F317 { background-position: -360px -40px; } +.emoji-1F318 { background-position: -360px -60px; } +.emoji-1F319 { background-position: -360px -80px; } +.emoji-1F31A { background-position: -360px -100px; } +.emoji-1F31B { background-position: -360px -120px; } +.emoji-1F31C { background-position: -360px -140px; } +.emoji-1F31D { background-position: -360px -160px; } +.emoji-1F31E { background-position: -360px -180px; } +.emoji-1F31F { background-position: -360px -200px; } +.emoji-1F320 { background-position: -360px -220px; } +.emoji-1F321 { background-position: -360px -240px; } +.emoji-1F324 { background-position: -360px -260px; } +.emoji-1F325 { background-position: -360px -280px; } +.emoji-1F326 { background-position: -360px -300px; } +.emoji-1F327 { background-position: -360px -320px; } +.emoji-1F328 { background-position: -360px -340px; } +.emoji-1F329 { background-position: 0px -360px; } +.emoji-1F32A { background-position: -20px -360px; } +.emoji-1F32B { background-position: -40px -360px; } +.emoji-1F32C { background-position: -60px -360px; } +.emoji-1F32D { background-position: -80px -360px; } +.emoji-1F32E { background-position: -100px -360px; } +.emoji-1F32F { background-position: -120px -360px; } +.emoji-1F330 { background-position: -140px -360px; } +.emoji-1F331 { background-position: -160px -360px; } +.emoji-1F332 { background-position: -180px -360px; } +.emoji-1F333 { background-position: -200px -360px; } +.emoji-1F334 { background-position: -220px -360px; } +.emoji-1F335 { background-position: -240px -360px; } +.emoji-1F336 { background-position: -260px -360px; } +.emoji-1F337 { background-position: -280px -360px; } +.emoji-1F338 { background-position: -300px -360px; } +.emoji-1F339 { background-position: -320px -360px; } +.emoji-1F33A { background-position: -340px -360px; } +.emoji-1F33B { background-position: -360px -360px; } +.emoji-1F33C { background-position: -380px 0px; } +.emoji-1F33D { background-position: -380px -20px; } +.emoji-1F33E { background-position: -380px -40px; } +.emoji-1F33F { background-position: -380px -60px; } +.emoji-1F340 { background-position: -380px -80px; } +.emoji-1F341 { background-position: -380px -100px; } +.emoji-1F342 { background-position: -380px -120px; } +.emoji-1F343 { background-position: -380px -140px; } +.emoji-1F344 { background-position: -380px -160px; } +.emoji-1F345 { background-position: -380px -180px; } +.emoji-1F346 { background-position: -380px -200px; } +.emoji-1F347 { background-position: -380px -220px; } +.emoji-1F348 { background-position: -380px -240px; } +.emoji-1F349 { background-position: -380px -260px; } +.emoji-1F34A { background-position: -380px -280px; } +.emoji-1F34B { background-position: -380px -300px; } +.emoji-1F34C { background-position: -380px -320px; } +.emoji-1F34D { background-position: -380px -340px; } +.emoji-1F34E { background-position: -380px -360px; } +.emoji-1F34F { background-position: 0px -380px; } +.emoji-1F350 { background-position: -20px -380px; } +.emoji-1F351 { background-position: -40px -380px; } +.emoji-1F352 { background-position: -60px -380px; } +.emoji-1F353 { background-position: -80px -380px; } +.emoji-1F354 { background-position: -100px -380px; } +.emoji-1F355 { background-position: -120px -380px; } +.emoji-1F356 { background-position: -140px -380px; } +.emoji-1F357 { background-position: -160px -380px; } +.emoji-1F358 { background-position: -180px -380px; } +.emoji-1F359 { background-position: -200px -380px; } +.emoji-1F35A { background-position: -220px -380px; } +.emoji-1F35B { background-position: -240px -380px; } +.emoji-1F35C { background-position: -260px -380px; } +.emoji-1F35D { background-position: -280px -380px; } +.emoji-1F35E { background-position: -300px -380px; } +.emoji-1F35F { background-position: -320px -380px; } +.emoji-1F360 { background-position: -340px -380px; } +.emoji-1F361 { background-position: -360px -380px; } +.emoji-1F362 { background-position: -380px -380px; } +.emoji-1F363 { background-position: -400px 0px; } +.emoji-1F364 { background-position: -400px -20px; } +.emoji-1F365 { background-position: -400px -40px; } +.emoji-1F366 { background-position: -400px -60px; } +.emoji-1F367 { background-position: -400px -80px; } +.emoji-1F368 { background-position: -400px -100px; } +.emoji-1F369 { background-position: -400px -120px; } +.emoji-1F36A { background-position: -400px -140px; } +.emoji-1F36B { background-position: -400px -160px; } +.emoji-1F36C { background-position: -400px -180px; } +.emoji-1F36D { background-position: -400px -200px; } +.emoji-1F36E { background-position: -400px -220px; } +.emoji-1F36F { background-position: -400px -240px; } +.emoji-1F370 { background-position: -400px -260px; } +.emoji-1F371 { background-position: -400px -280px; } +.emoji-1F372 { background-position: -400px -300px; } +.emoji-1F373 { background-position: -400px -320px; } +.emoji-1F374 { background-position: -400px -340px; } +.emoji-1F375 { background-position: -400px -360px; } +.emoji-1F376 { background-position: -400px -380px; } +.emoji-1F377 { background-position: 0px -400px; } +.emoji-1F378 { background-position: -20px -400px; } +.emoji-1F379 { background-position: -40px -400px; } +.emoji-1F37A { background-position: -60px -400px; } +.emoji-1F37B { background-position: -80px -400px; } +.emoji-1F37C { background-position: -100px -400px; } +.emoji-1F37D { background-position: -120px -400px; } +.emoji-1F37E { background-position: -140px -400px; } +.emoji-1F37F { background-position: -160px -400px; } +.emoji-1F380 { background-position: -180px -400px; } +.emoji-1F381 { background-position: -200px -400px; } +.emoji-1F382 { background-position: -220px -400px; } +.emoji-1F383 { background-position: -240px -400px; } +.emoji-1F384 { background-position: -260px -400px; } +.emoji-1F385 { background-position: -280px -400px; } +.emoji-1F385-1F3FB { background-position: -300px -400px; } +.emoji-1F385-1F3FC { background-position: -320px -400px; } +.emoji-1F385-1F3FD { background-position: -340px -400px; } +.emoji-1F385-1F3FE { background-position: -360px -400px; } +.emoji-1F385-1F3FF { background-position: -380px -400px; } +.emoji-1F386 { background-position: -400px -400px; } +.emoji-1F387 { background-position: -420px 0px; } +.emoji-1F388 { background-position: -420px -20px; } +.emoji-1F389 { background-position: -420px -40px; } +.emoji-1F38A { background-position: -420px -60px; } +.emoji-1F38B { background-position: -420px -80px; } +.emoji-1F38C { background-position: -420px -100px; } +.emoji-1F38D { background-position: -420px -120px; } +.emoji-1F38E { background-position: -420px -140px; } +.emoji-1F38F { background-position: -420px -160px; } +.emoji-1F390 { background-position: -420px -180px; } +.emoji-1F391 { background-position: -420px -200px; } +.emoji-1F392 { background-position: -420px -220px; } +.emoji-1F393 { background-position: -420px -240px; } +.emoji-1F394 { background-position: -420px -260px; } +.emoji-1F395 { background-position: -420px -280px; } +.emoji-1F396 { background-position: -420px -300px; } +.emoji-1F397 { background-position: -420px -320px; } +.emoji-1F398 { background-position: -420px -340px; } +.emoji-1F399 { background-position: -420px -360px; } +.emoji-1F39A { background-position: -420px -380px; } +.emoji-1F39B { background-position: -420px -400px; } +.emoji-1F39C { background-position: 0px -420px; } +.emoji-1F39D { background-position: -20px -420px; } +.emoji-1F39E { background-position: -40px -420px; } +.emoji-1F39F { background-position: -60px -420px; } +.emoji-1F3A0 { background-position: -80px -420px; } +.emoji-1F3A1 { background-position: -100px -420px; } +.emoji-1F3A2 { background-position: -120px -420px; } +.emoji-1F3A3 { background-position: -140px -420px; } +.emoji-1F3A4 { background-position: -160px -420px; } +.emoji-1F3A5 { background-position: -180px -420px; } +.emoji-1F3A6 { background-position: -200px -420px; } +.emoji-1F3A7 { background-position: -220px -420px; } +.emoji-1F3A8 { background-position: -240px -420px; } +.emoji-1F3A9 { background-position: -260px -420px; } +.emoji-1F3AA { background-position: -280px -420px; } +.emoji-1F3AB { background-position: -300px -420px; } +.emoji-1F3AC { background-position: -320px -420px; } +.emoji-1F3AD { background-position: -340px -420px; } +.emoji-1F3AE { background-position: -360px -420px; } +.emoji-1F3AF { background-position: -380px -420px; } +.emoji-1F3B0 { background-position: -400px -420px; } +.emoji-1F3B1 { background-position: -420px -420px; } +.emoji-1F3B2 { background-position: -440px 0px; } +.emoji-1F3B3 { background-position: -440px -20px; } +.emoji-1F3B4 { background-position: -440px -40px; } +.emoji-1F3B5 { background-position: -440px -60px; } +.emoji-1F3B6 { background-position: -440px -80px; } +.emoji-1F3B7 { background-position: -440px -100px; } +.emoji-1F3B8 { background-position: -440px -120px; } +.emoji-1F3B9 { background-position: -440px -140px; } +.emoji-1F3BA { background-position: -440px -160px; } +.emoji-1F3BB { background-position: -440px -180px; } +.emoji-1F3BC { background-position: -440px -200px; } +.emoji-1F3BD { background-position: -440px -220px; } +.emoji-1F3BE { background-position: -440px -240px; } +.emoji-1F3BF { background-position: -440px -260px; } +.emoji-1F3C0 { background-position: -440px -280px; } +.emoji-1F3C1 { background-position: -440px -300px; } +.emoji-1F3C2 { background-position: -440px -320px; } +.emoji-1F3C3 { background-position: -440px -340px; } +.emoji-1F3C3-1F3FB { background-position: -440px -360px; } +.emoji-1F3C3-1F3FC { background-position: -440px -380px; } +.emoji-1F3C3-1F3FD { background-position: -440px -400px; } +.emoji-1F3C3-1F3FE { background-position: -440px -420px; } +.emoji-1F3C3-1F3FF { background-position: 0px -440px; } +.emoji-1F3C4 { background-position: -20px -440px; } +.emoji-1F3C4-1F3FB { background-position: -40px -440px; } +.emoji-1F3C4-1F3FC { background-position: -60px -440px; } +.emoji-1F3C4-1F3FD { background-position: -80px -440px; } +.emoji-1F3C4-1F3FE { background-position: -100px -440px; } +.emoji-1F3C4-1F3FF { background-position: -120px -440px; } +.emoji-1F3C5 { background-position: -140px -440px; } +.emoji-1F3C6 { background-position: -160px -440px; } +.emoji-1F3C7 { background-position: -180px -440px; } +.emoji-1F3C7-1F3FB { background-position: -200px -440px; } +.emoji-1F3C7-1F3FC { background-position: -220px -440px; } +.emoji-1F3C7-1F3FD { background-position: -240px -440px; } +.emoji-1F3C7-1F3FE { background-position: -260px -440px; } +.emoji-1F3C7-1F3FF { background-position: -280px -440px; } +.emoji-1F3C8 { background-position: -300px -440px; } +.emoji-1F3C9 { background-position: -320px -440px; } +.emoji-1F3CA { background-position: -340px -440px; } +.emoji-1F3CA-1F3FB { background-position: -360px -440px; } +.emoji-1F3CA-1F3FC { background-position: -380px -440px; } +.emoji-1F3CA-1F3FD { background-position: -400px -440px; } +.emoji-1F3CA-1F3FE { background-position: -420px -440px; } +.emoji-1F3CA-1F3FF { background-position: -440px -440px; } +.emoji-1F3CB { background-position: -460px 0px; } +.emoji-1F3CB-1F3FB { background-position: -460px -20px; } +.emoji-1F3CB-1F3FC { background-position: -460px -40px; } +.emoji-1F3CB-1F3FD { background-position: -460px -60px; } +.emoji-1F3CB-1F3FE { background-position: -460px -80px; } +.emoji-1F3CB-1F3FF { background-position: -460px -100px; } +.emoji-1F3CC { background-position: -460px -120px; } +.emoji-1F3CD { background-position: -460px -140px; } +.emoji-1F3CE { background-position: -460px -160px; } +.emoji-1F3CF { background-position: -460px -180px; } +.emoji-1F3D0 { background-position: -460px -200px; } +.emoji-1F3D1 { background-position: -460px -220px; } +.emoji-1F3D2 { background-position: -460px -240px; } +.emoji-1F3D3 { background-position: -460px -260px; } +.emoji-1F3D4 { background-position: -460px -280px; } +.emoji-1F3D5 { background-position: -460px -300px; } +.emoji-1F3D6 { background-position: -460px -320px; } +.emoji-1F3D7 { background-position: -460px -340px; } +.emoji-1F3D8 { background-position: -460px -360px; } +.emoji-1F3D9 { background-position: -460px -380px; } +.emoji-1F3DA { background-position: -460px -400px; } +.emoji-1F3DB { background-position: -460px -420px; } +.emoji-1F3DC { background-position: -460px -440px; } +.emoji-1F3DD { background-position: 0px -460px; } +.emoji-1F3DE { background-position: -20px -460px; } +.emoji-1F3DF { background-position: -40px -460px; } +.emoji-1F3E0 { background-position: -60px -460px; } +.emoji-1F3E1 { background-position: -80px -460px; } +.emoji-1F3E2 { background-position: -100px -460px; } +.emoji-1F3E3 { background-position: -120px -460px; } +.emoji-1F3E4 { background-position: -140px -460px; } +.emoji-1F3E5 { background-position: -160px -460px; } +.emoji-1F3E6 { background-position: -180px -460px; } +.emoji-1F3E7 { background-position: -200px -460px; } +.emoji-1F3E8 { background-position: -220px -460px; } +.emoji-1F3E9 { background-position: -240px -460px; } +.emoji-1F3EA { background-position: -260px -460px; } +.emoji-1F3EB { background-position: -280px -460px; } +.emoji-1F3EC { background-position: -300px -460px; } +.emoji-1F3ED { background-position: -320px -460px; } +.emoji-1F3EE { background-position: -340px -460px; } +.emoji-1F3EF { background-position: -360px -460px; } +.emoji-1F3F0 { background-position: -380px -460px; } +.emoji-1F3F1 { background-position: -400px -460px; } +.emoji-1F3F2 { background-position: -420px -460px; } +.emoji-1F3F3 { background-position: -440px -460px; } +.emoji-1F3F4 { background-position: -460px -460px; } +.emoji-1F3F5 { background-position: -480px 0px; } +.emoji-1F3F6 { background-position: -480px -20px; } +.emoji-1F3F7 { background-position: -480px -40px; } +.emoji-1F3F8 { background-position: -480px -60px; } +.emoji-1F3F9 { background-position: -480px -80px; } +.emoji-1F3FA { background-position: -480px -100px; } +.emoji-1F3FB { background-position: -480px -120px; } +.emoji-1F3FC { background-position: -480px -140px; } +.emoji-1F3FD { background-position: -480px -160px; } +.emoji-1F3FE { background-position: -480px -180px; } +.emoji-1F3FF { background-position: -480px -200px; } +.emoji-1F400 { background-position: -480px -220px; } +.emoji-1F401 { background-position: -480px -240px; } +.emoji-1F402 { background-position: -480px -260px; } +.emoji-1F403 { background-position: -480px -280px; } +.emoji-1F404 { background-position: -480px -300px; } +.emoji-1F405 { background-position: -480px -320px; } +.emoji-1F406 { background-position: -480px -340px; } +.emoji-1F407 { background-position: -480px -360px; } +.emoji-1F408 { background-position: -480px -380px; } +.emoji-1F409 { background-position: -480px -400px; } +.emoji-1F40A { background-position: -480px -420px; } +.emoji-1F40B { background-position: -480px -440px; } +.emoji-1F40C { background-position: -480px -460px; } +.emoji-1F40D { background-position: 0px -480px; } +.emoji-1F40E { background-position: -20px -480px; } +.emoji-1F40F { background-position: -40px -480px; } +.emoji-1F410 { background-position: -60px -480px; } +.emoji-1F411 { background-position: -80px -480px; } +.emoji-1F412 { background-position: -100px -480px; } +.emoji-1F413 { background-position: -120px -480px; } +.emoji-1F414 { background-position: -140px -480px; } +.emoji-1F415 { background-position: -160px -480px; } +.emoji-1F416 { background-position: -180px -480px; } +.emoji-1F417 { background-position: -200px -480px; } +.emoji-1F418 { background-position: -220px -480px; } +.emoji-1F419 { background-position: -240px -480px; } +.emoji-1F41A { background-position: -260px -480px; } +.emoji-1F41B { background-position: -280px -480px; } +.emoji-1F41C { background-position: -300px -480px; } +.emoji-1F41D { background-position: -320px -480px; } +.emoji-1F41E { background-position: -340px -480px; } +.emoji-1F41F { background-position: -360px -480px; } +.emoji-1F420 { background-position: -380px -480px; } +.emoji-1F421 { background-position: -400px -480px; } +.emoji-1F422 { background-position: -420px -480px; } +.emoji-1F423 { background-position: -440px -480px; } +.emoji-1F424 { background-position: -460px -480px; } +.emoji-1F425 { background-position: -480px -480px; } +.emoji-1F426 { background-position: -500px 0px; } +.emoji-1F427 { background-position: -500px -20px; } +.emoji-1F428 { background-position: -500px -40px; } +.emoji-1F429 { background-position: -500px -60px; } +.emoji-1F42A { background-position: -500px -80px; } +.emoji-1F42B { background-position: -500px -100px; } +.emoji-1F42C { background-position: -500px -120px; } +.emoji-1F42D { background-position: -500px -140px; } +.emoji-1F42E { background-position: -500px -160px; } +.emoji-1F42F { background-position: -500px -180px; } +.emoji-1F430 { background-position: -500px -200px; } +.emoji-1F431 { background-position: -500px -220px; } +.emoji-1F432 { background-position: -500px -240px; } +.emoji-1F433 { background-position: -500px -260px; } +.emoji-1F434 { background-position: -500px -280px; } +.emoji-1F435 { background-position: -500px -300px; } +.emoji-1F436 { background-position: -500px -320px; } +.emoji-1F437 { background-position: -500px -340px; } +.emoji-1F438 { background-position: -500px -360px; } +.emoji-1F439 { background-position: -500px -380px; } +.emoji-1F43A { background-position: -500px -400px; } +.emoji-1F43B { background-position: -500px -420px; } +.emoji-1F43C { background-position: -500px -440px; } +.emoji-1F43D { background-position: -500px -460px; } +.emoji-1F43E { background-position: -500px -480px; } +.emoji-1F43F { background-position: 0px -500px; } +.emoji-1F440 { background-position: -20px -500px; } +.emoji-1F441 { background-position: -40px -500px; } +.emoji-1F441-1F5E8 { background-position: -60px -500px; } +.emoji-1F442 { background-position: -80px -500px; } +.emoji-1F442-1F3FB { background-position: -100px -500px; } +.emoji-1F442-1F3FC { background-position: -120px -500px; } +.emoji-1F442-1F3FD { background-position: -140px -500px; } +.emoji-1F442-1F3FE { background-position: -160px -500px; } +.emoji-1F442-1F3FF { background-position: -180px -500px; } +.emoji-1F443 { background-position: -200px -500px; } +.emoji-1F443-1F3FB { background-position: -220px -500px; } +.emoji-1F443-1F3FC { background-position: -240px -500px; } +.emoji-1F443-1F3FD { background-position: -260px -500px; } +.emoji-1F443-1F3FE { background-position: -280px -500px; } +.emoji-1F443-1F3FF { background-position: -300px -500px; } +.emoji-1F444 { background-position: -320px -500px; } +.emoji-1F445 { background-position: -340px -500px; } +.emoji-1F446 { background-position: -360px -500px; } +.emoji-1F446-1F3FB { background-position: -380px -500px; } +.emoji-1F446-1F3FC { background-position: -400px -500px; } +.emoji-1F446-1F3FD { background-position: -420px -500px; } +.emoji-1F446-1F3FE { background-position: -440px -500px; } +.emoji-1F446-1F3FF { background-position: -460px -500px; } +.emoji-1F447 { background-position: -480px -500px; } +.emoji-1F447-1F3FB { background-position: -500px -500px; } +.emoji-1F447-1F3FC { background-position: -520px 0px; } +.emoji-1F447-1F3FD { background-position: -520px -20px; } +.emoji-1F447-1F3FE { background-position: -520px -40px; } +.emoji-1F447-1F3FF { background-position: -520px -60px; } +.emoji-1F448 { background-position: -520px -80px; } +.emoji-1F448-1F3FB { background-position: -520px -100px; } +.emoji-1F448-1F3FC { background-position: -520px -120px; } +.emoji-1F448-1F3FD { background-position: -520px -140px; } +.emoji-1F448-1F3FE { background-position: -520px -160px; } +.emoji-1F448-1F3FF { background-position: -520px -180px; } +.emoji-1F449 { background-position: -520px -200px; } +.emoji-1F449-1F3FB { background-position: -520px -220px; } +.emoji-1F449-1F3FC { background-position: -520px -240px; } +.emoji-1F449-1F3FD { background-position: -520px -260px; } +.emoji-1F449-1F3FE { background-position: -520px -280px; } +.emoji-1F449-1F3FF { background-position: -520px -300px; } +.emoji-1F44A { background-position: -520px -320px; } +.emoji-1F44A-1F3FB { background-position: -520px -340px; } +.emoji-1F44A-1F3FC { background-position: -520px -360px; } +.emoji-1F44A-1F3FD { background-position: -520px -380px; } +.emoji-1F44A-1F3FE { background-position: -520px -400px; } +.emoji-1F44A-1F3FF { background-position: -520px -420px; } +.emoji-1F44B { background-position: -520px -440px; } +.emoji-1F44B-1F3FB { background-position: -520px -460px; } +.emoji-1F44B-1F3FC { background-position: -520px -480px; } +.emoji-1F44B-1F3FD { background-position: -520px -500px; } +.emoji-1F44B-1F3FE { background-position: 0px -520px; } +.emoji-1F44B-1F3FF { background-position: -20px -520px; } +.emoji-1F44C { background-position: -40px -520px; } +.emoji-1F44C-1F3FB { background-position: -60px -520px; } +.emoji-1F44C-1F3FC { background-position: -80px -520px; } +.emoji-1F44C-1F3FD { background-position: -100px -520px; } +.emoji-1F44C-1F3FE { background-position: -120px -520px; } +.emoji-1F44C-1F3FF { background-position: -140px -520px; } +.emoji-1F44D { background-position: -160px -520px; } +.emoji-1F44D-1F3FB { background-position: -180px -520px; } +.emoji-1F44D-1F3FC { background-position: -200px -520px; } +.emoji-1F44D-1F3FD { background-position: -220px -520px; } +.emoji-1F44D-1F3FE { background-position: -240px -520px; } +.emoji-1F44D-1F3FF { background-position: -260px -520px; } +.emoji-1F44E { background-position: -280px -520px; } +.emoji-1F44E-1F3FB { background-position: -300px -520px; } +.emoji-1F44E-1F3FC { background-position: -320px -520px; } +.emoji-1F44E-1F3FD { background-position: -340px -520px; } +.emoji-1F44E-1F3FE { background-position: -360px -520px; } +.emoji-1F44E-1F3FF { background-position: -380px -520px; } +.emoji-1F44F { background-position: -400px -520px; } +.emoji-1F44F-1F3FB { background-position: -420px -520px; } +.emoji-1F44F-1F3FC { background-position: -440px -520px; } +.emoji-1F44F-1F3FD { background-position: -460px -520px; } +.emoji-1F44F-1F3FE { background-position: -480px -520px; } +.emoji-1F44F-1F3FF { background-position: -500px -520px; } +.emoji-1F450 { background-position: -520px -520px; } +.emoji-1F450-1F3FB { background-position: -540px 0px; } +.emoji-1F450-1F3FC { background-position: -540px -20px; } +.emoji-1F450-1F3FD { background-position: -540px -40px; } +.emoji-1F450-1F3FE { background-position: -540px -60px; } +.emoji-1F450-1F3FF { background-position: -540px -80px; } +.emoji-1F451 { background-position: -540px -100px; } +.emoji-1F452 { background-position: -540px -120px; } +.emoji-1F453 { background-position: -540px -140px; } +.emoji-1F454 { background-position: -540px -160px; } +.emoji-1F455 { background-position: -540px -180px; } +.emoji-1F456 { background-position: -540px -200px; } +.emoji-1F457 { background-position: -540px -220px; } +.emoji-1F458 { background-position: -540px -240px; } +.emoji-1F459 { background-position: -540px -260px; } +.emoji-1F45A { background-position: -540px -280px; } +.emoji-1F45B { background-position: -540px -300px; } +.emoji-1F45C { background-position: -540px -320px; } +.emoji-1F45D { background-position: -540px -340px; } +.emoji-1F45E { background-position: -540px -360px; } +.emoji-1F45F { background-position: -540px -380px; } +.emoji-1F460 { background-position: -540px -400px; } +.emoji-1F461 { background-position: -540px -420px; } +.emoji-1F462 { background-position: -540px -440px; } +.emoji-1F463 { background-position: -540px -460px; } +.emoji-1F464 { background-position: -540px -480px; } +.emoji-1F465 { background-position: -540px -500px; } +.emoji-1F466 { background-position: -540px -520px; } +.emoji-1F466-1F3FB { background-position: 0px -540px; } +.emoji-1F466-1F3FC { background-position: -20px -540px; } +.emoji-1F466-1F3FD { background-position: -40px -540px; } +.emoji-1F466-1F3FE { background-position: -60px -540px; } +.emoji-1F466-1F3FF { background-position: -80px -540px; } +.emoji-1F467 { background-position: -100px -540px; } +.emoji-1F467-1F3FB { background-position: -120px -540px; } +.emoji-1F467-1F3FC { background-position: -140px -540px; } +.emoji-1F467-1F3FD { background-position: -160px -540px; } +.emoji-1F467-1F3FE { background-position: -180px -540px; } +.emoji-1F467-1F3FF { background-position: -200px -540px; } +.emoji-1F468 { background-position: -220px -540px; } +.emoji-1F468-1F3FB { background-position: -240px -540px; } +.emoji-1F468-1F3FC { background-position: -260px -540px; } +.emoji-1F468-1F3FD { background-position: -280px -540px; } +.emoji-1F468-1F3FE { background-position: -300px -540px; } +.emoji-1F468-1F3FF { background-position: -320px -540px; } +.emoji-1F468-1F468-1F466 { background-position: -340px -540px; } +.emoji-1F468-1F468-1F466-1F466 { background-position: -360px -540px; } +.emoji-1F468-1F468-1F467 { background-position: -380px -540px; } +.emoji-1F468-1F468-1F467-1F466 { background-position: -400px -540px; } +.emoji-1F468-1F468-1F467-1F467 { background-position: -420px -540px; } +.emoji-1F468-1F469-1F466-1F466 { background-position: -440px -540px; } +.emoji-1F468-1F469-1F467 { background-position: -460px -540px; } +.emoji-1F468-1F469-1F467-1F466 { background-position: -480px -540px; } +.emoji-1F468-1F469-1F467-1F467 { background-position: -500px -540px; } +.emoji-1F468-2764-1F468 { background-position: -520px -540px; } +.emoji-1F468-2764-1F48B-1F468 { background-position: -540px -540px; } +.emoji-1F469 { background-position: -560px 0px; } +.emoji-1F469-1F3FB { background-position: -560px -20px; } +.emoji-1F469-1F3FC { background-position: -560px -40px; } +.emoji-1F469-1F3FD { background-position: -560px -60px; } +.emoji-1F469-1F3FE { background-position: -560px -80px; } +.emoji-1F469-1F3FF { background-position: -560px -100px; } +.emoji-1F469-1F469-1F466 { background-position: -560px -120px; } +.emoji-1F469-1F469-1F466-1F466 { background-position: -560px -140px; } +.emoji-1F469-1F469-1F467 { background-position: -560px -160px; } +.emoji-1F469-1F469-1F467-1F466 { background-position: -560px -180px; } +.emoji-1F469-1F469-1F467-1F467 { background-position: -560px -200px; } +.emoji-1F469-2764-1F469 { background-position: -560px -220px; } +.emoji-1F469-2764-1F48B-1F469 { background-position: -560px -240px; } +.emoji-1F46A { background-position: -560px -260px; } +.emoji-1F46B { background-position: -560px -280px; } +.emoji-1F46C { background-position: -560px -300px; } +.emoji-1F46D { background-position: -560px -320px; } +.emoji-1F46E { background-position: -560px -340px; } +.emoji-1F46E-1F3FB { background-position: -560px -360px; } +.emoji-1F46E-1F3FC { background-position: -560px -380px; } +.emoji-1F46E-1F3FD { background-position: -560px -400px; } +.emoji-1F46E-1F3FE { background-position: -560px -420px; } +.emoji-1F46E-1F3FF { background-position: -560px -440px; } +.emoji-1F46F { background-position: -560px -460px; } +.emoji-1F470 { background-position: -560px -480px; } +.emoji-1F470-1F3FB { background-position: -560px -500px; } +.emoji-1F470-1F3FC { background-position: -560px -520px; } +.emoji-1F470-1F3FD { background-position: -560px -540px; } +.emoji-1F470-1F3FE { background-position: 0px -560px; } +.emoji-1F470-1F3FF { background-position: -20px -560px; } +.emoji-1F471 { background-position: -40px -560px; } +.emoji-1F471-1F3FB { background-position: -60px -560px; } +.emoji-1F471-1F3FC { background-position: -80px -560px; } +.emoji-1F471-1F3FD { background-position: -100px -560px; } +.emoji-1F471-1F3FE { background-position: -120px -560px; } +.emoji-1F471-1F3FF { background-position: -140px -560px; } +.emoji-1F472 { background-position: -160px -560px; } +.emoji-1F472-1F3FB { background-position: -180px -560px; } +.emoji-1F472-1F3FC { background-position: -200px -560px; } +.emoji-1F472-1F3FD { background-position: -220px -560px; } +.emoji-1F472-1F3FE { background-position: -240px -560px; } +.emoji-1F472-1F3FF { background-position: -260px -560px; } +.emoji-1F473 { background-position: -280px -560px; } +.emoji-1F473-1F3FB { background-position: -300px -560px; } +.emoji-1F473-1F3FC { background-position: -320px -560px; } +.emoji-1F473-1F3FD { background-position: -340px -560px; } +.emoji-1F473-1F3FE { background-position: -360px -560px; } +.emoji-1F473-1F3FF { background-position: -380px -560px; } +.emoji-1F474 { background-position: -400px -560px; } +.emoji-1F474-1F3FB { background-position: -420px -560px; } +.emoji-1F474-1F3FC { background-position: -440px -560px; } +.emoji-1F474-1F3FD { background-position: -460px -560px; } +.emoji-1F474-1F3FE { background-position: -480px -560px; } +.emoji-1F474-1F3FF { background-position: -500px -560px; } +.emoji-1F475 { background-position: -520px -560px; } +.emoji-1F475-1F3FB { background-position: -540px -560px; } +.emoji-1F475-1F3FC { background-position: -560px -560px; } +.emoji-1F475-1F3FD { background-position: -580px 0px; } +.emoji-1F475-1F3FE { background-position: -580px -20px; } +.emoji-1F475-1F3FF { background-position: -580px -40px; } +.emoji-1F476 { background-position: -580px -60px; } +.emoji-1F476-1F3FB { background-position: -580px -80px; } +.emoji-1F476-1F3FC { background-position: -580px -100px; } +.emoji-1F476-1F3FD { background-position: -580px -120px; } +.emoji-1F476-1F3FE { background-position: -580px -140px; } +.emoji-1F476-1F3FF { background-position: -580px -160px; } +.emoji-1F477 { background-position: -580px -180px; } +.emoji-1F477-1F3FB { background-position: -580px -200px; } +.emoji-1F477-1F3FC { background-position: -580px -220px; } +.emoji-1F477-1F3FD { background-position: -580px -240px; } +.emoji-1F477-1F3FE { background-position: -580px -260px; } +.emoji-1F477-1F3FF { background-position: -580px -280px; } +.emoji-1F478 { background-position: -580px -300px; } +.emoji-1F478-1F3FB { background-position: -580px -320px; } +.emoji-1F478-1F3FC { background-position: -580px -340px; } +.emoji-1F478-1F3FD { background-position: -580px -360px; } +.emoji-1F478-1F3FE { background-position: -580px -380px; } +.emoji-1F478-1F3FF { background-position: -580px -400px; } +.emoji-1F479 { background-position: -580px -420px; } +.emoji-1F47A { background-position: -580px -440px; } +.emoji-1F47B { background-position: -580px -460px; } +.emoji-1F47C { background-position: -580px -480px; } +.emoji-1F47C-1F3FB { background-position: -580px -500px; } +.emoji-1F47C-1F3FC { background-position: -580px -520px; } +.emoji-1F47C-1F3FD { background-position: -580px -540px; } +.emoji-1F47C-1F3FE { background-position: -580px -560px; } +.emoji-1F47C-1F3FF { background-position: 0px -580px; } +.emoji-1F47D { background-position: -20px -580px; } +.emoji-1F47E { background-position: -40px -580px; } +.emoji-1F47F { background-position: -60px -580px; } +.emoji-1F480 { background-position: -80px -580px; } +.emoji-1F481 { background-position: -100px -580px; } +.emoji-1F481-1F3FB { background-position: -120px -580px; } +.emoji-1F481-1F3FC { background-position: -140px -580px; } +.emoji-1F481-1F3FD { background-position: -160px -580px; } +.emoji-1F481-1F3FE { background-position: -180px -580px; } +.emoji-1F481-1F3FF { background-position: -200px -580px; } +.emoji-1F482 { background-position: -220px -580px; } +.emoji-1F482-1F3FB { background-position: -240px -580px; } +.emoji-1F482-1F3FC { background-position: -260px -580px; } +.emoji-1F482-1F3FD { background-position: -280px -580px; } +.emoji-1F482-1F3FE { background-position: -300px -580px; } +.emoji-1F482-1F3FF { background-position: -320px -580px; } +.emoji-1F483 { background-position: -340px -580px; } +.emoji-1F483-1F3FB { background-position: -360px -580px; } +.emoji-1F483-1F3FC { background-position: -380px -580px; } +.emoji-1F483-1F3FD { background-position: -400px -580px; } +.emoji-1F483-1F3FE { background-position: -420px -580px; } +.emoji-1F483-1F3FF { background-position: -440px -580px; } +.emoji-1F484 { background-position: -460px -580px; } +.emoji-1F485 { background-position: -480px -580px; } +.emoji-1F485-1F3FB { background-position: -500px -580px; } +.emoji-1F485-1F3FC { background-position: -520px -580px; } +.emoji-1F485-1F3FD { background-position: -540px -580px; } +.emoji-1F485-1F3FE { background-position: -560px -580px; } +.emoji-1F485-1F3FF { background-position: -580px -580px; } +.emoji-1F486 { background-position: -600px 0px; } +.emoji-1F486-1F3FB { background-position: -600px -20px; } +.emoji-1F486-1F3FC { background-position: -600px -40px; } +.emoji-1F486-1F3FD { background-position: -600px -60px; } +.emoji-1F486-1F3FE { background-position: -600px -80px; } +.emoji-1F486-1F3FF { background-position: -600px -100px; } +.emoji-1F487 { background-position: -600px -120px; } +.emoji-1F487-1F3FB { background-position: -600px -140px; } +.emoji-1F487-1F3FC { background-position: -600px -160px; } +.emoji-1F487-1F3FD { background-position: -600px -180px; } +.emoji-1F487-1F3FE { background-position: -600px -200px; } +.emoji-1F487-1F3FF { background-position: -600px -220px; } +.emoji-1F488 { background-position: -600px -240px; } +.emoji-1F489 { background-position: -600px -260px; } +.emoji-1F48A { background-position: -600px -280px; } +.emoji-1F48B { background-position: -600px -300px; } +.emoji-1F48C { background-position: -600px -320px; } +.emoji-1F48D { background-position: -600px -340px; } +.emoji-1F48E { background-position: -600px -360px; } +.emoji-1F48F { background-position: -600px -380px; } +.emoji-1F490 { background-position: -600px -400px; } +.emoji-1F491 { background-position: -600px -420px; } +.emoji-1F492 { background-position: -600px -440px; } +.emoji-1F493 { background-position: -600px -460px; } +.emoji-1F494 { background-position: -600px -480px; } +.emoji-1F495 { background-position: -600px -500px; } +.emoji-1F496 { background-position: -600px -520px; } +.emoji-1F497 { background-position: -600px -540px; } +.emoji-1F498 { background-position: -600px -560px; } +.emoji-1F499 { background-position: -600px -580px; } +.emoji-1F49A { background-position: 0px -600px; } +.emoji-1F49B { background-position: -20px -600px; } +.emoji-1F49C { background-position: -40px -600px; } +.emoji-1F49D { background-position: -60px -600px; } +.emoji-1F49E { background-position: -80px -600px; } +.emoji-1F49F { background-position: -100px -600px; } +.emoji-1F4A0 { background-position: -120px -600px; } +.emoji-1F4A1 { background-position: -140px -600px; } +.emoji-1F4A2 { background-position: -160px -600px; } +.emoji-1F4A3 { background-position: -180px -600px; } +.emoji-1F4A4 { background-position: -200px -600px; } +.emoji-1F4A5 { background-position: -220px -600px; } +.emoji-1F4A6 { background-position: -240px -600px; } +.emoji-1F4A7 { background-position: -260px -600px; } +.emoji-1F4A8 { background-position: -280px -600px; } +.emoji-1F4A9 { background-position: -300px -600px; } +.emoji-1F4AA { background-position: -320px -600px; } +.emoji-1F4AA-1F3FB { background-position: -340px -600px; } +.emoji-1F4AA-1F3FC { background-position: -360px -600px; } +.emoji-1F4AA-1F3FD { background-position: -380px -600px; } +.emoji-1F4AA-1F3FE { background-position: -400px -600px; } +.emoji-1F4AA-1F3FF { background-position: -420px -600px; } +.emoji-1F4AB { background-position: -440px -600px; } +.emoji-1F4AC { background-position: -460px -600px; } +.emoji-1F4AD { background-position: -480px -600px; } +.emoji-1F4AE { background-position: -500px -600px; } +.emoji-1F4AF { background-position: -520px -600px; } +.emoji-1F4B0 { background-position: -540px -600px; } +.emoji-1F4B1 { background-position: -560px -600px; } +.emoji-1F4B2 { background-position: -580px -600px; } +.emoji-1F4B3 { background-position: -600px -600px; } +.emoji-1F4B4 { background-position: -620px 0px; } +.emoji-1F4B5 { background-position: -620px -20px; } +.emoji-1F4B6 { background-position: -620px -40px; } +.emoji-1F4B7 { background-position: -620px -60px; } +.emoji-1F4B8 { background-position: -620px -80px; } +.emoji-1F4B9 { background-position: -620px -100px; } +.emoji-1F4BA { background-position: -620px -120px; } +.emoji-1F4BB { background-position: -620px -140px; } +.emoji-1F4BC { background-position: -620px -160px; } +.emoji-1F4BD { background-position: -620px -180px; } +.emoji-1F4BE { background-position: -620px -200px; } +.emoji-1F4BF { background-position: -620px -220px; } +.emoji-1F4C0 { background-position: -620px -240px; } +.emoji-1F4C1 { background-position: -620px -260px; } +.emoji-1F4C2 { background-position: -620px -280px; } +.emoji-1F4C3 { background-position: -620px -300px; } +.emoji-1F4C4 { background-position: -620px -320px; } +.emoji-1F4C5 { background-position: -620px -340px; } +.emoji-1F4C6 { background-position: -620px -360px; } +.emoji-1F4C7 { background-position: -620px -380px; } +.emoji-1F4C8 { background-position: -620px -400px; } +.emoji-1F4C9 { background-position: -620px -420px; } +.emoji-1F4CA { background-position: -620px -440px; } +.emoji-1F4CB { background-position: -620px -460px; } +.emoji-1F4CC { background-position: -620px -480px; } +.emoji-1F4CD { background-position: -620px -500px; } +.emoji-1F4CE { background-position: -620px -520px; } +.emoji-1F4CF { background-position: -620px -540px; } +.emoji-1F4D0 { background-position: -620px -560px; } +.emoji-1F4D1 { background-position: -620px -580px; } +.emoji-1F4D2 { background-position: -620px -600px; } +.emoji-1F4D3 { background-position: 0px -620px; } +.emoji-1F4D4 { background-position: -20px -620px; } +.emoji-1F4D5 { background-position: -40px -620px; } +.emoji-1F4D6 { background-position: -60px -620px; } +.emoji-1F4D7 { background-position: -80px -620px; } +.emoji-1F4D8 { background-position: -100px -620px; } +.emoji-1F4D9 { background-position: -120px -620px; } +.emoji-1F4DA { background-position: -140px -620px; } +.emoji-1F4DB { background-position: -160px -620px; } +.emoji-1F4DC { background-position: -180px -620px; } +.emoji-1F4DD { background-position: -200px -620px; } +.emoji-1F4DE { background-position: -220px -620px; } +.emoji-1F4DF { background-position: -240px -620px; } +.emoji-1F4E0 { background-position: -260px -620px; } +.emoji-1F4E1 { background-position: -280px -620px; } +.emoji-1F4E2 { background-position: -300px -620px; } +.emoji-1F4E3 { background-position: -320px -620px; } +.emoji-1F4E4 { background-position: -340px -620px; } +.emoji-1F4E5 { background-position: -360px -620px; } +.emoji-1F4E6 { background-position: -380px -620px; } +.emoji-1F4E7 { background-position: -400px -620px; } +.emoji-1F4E8 { background-position: -420px -620px; } +.emoji-1F4E9 { background-position: -440px -620px; } +.emoji-1F4EA { background-position: -460px -620px; } +.emoji-1F4EB { background-position: -480px -620px; } +.emoji-1F4EC { background-position: -500px -620px; } +.emoji-1F4ED { background-position: -520px -620px; } +.emoji-1F4EE { background-position: -540px -620px; } +.emoji-1F4EF { background-position: -560px -620px; } +.emoji-1F4F0 { background-position: -580px -620px; } +.emoji-1F4F1 { background-position: -600px -620px; } +.emoji-1F4F2 { background-position: -620px -620px; } +.emoji-1F4F3 { background-position: -640px 0px; } +.emoji-1F4F4 { background-position: -640px -20px; } +.emoji-1F4F5 { background-position: -640px -40px; } +.emoji-1F4F6 { background-position: -640px -60px; } +.emoji-1F4F7 { background-position: -640px -80px; } +.emoji-1F4F8 { background-position: -640px -100px; } +.emoji-1F4F9 { background-position: -640px -120px; } +.emoji-1F4FA { background-position: -640px -140px; } +.emoji-1F4FB { background-position: -640px -160px; } +.emoji-1F4FC { background-position: -640px -180px; } +.emoji-1F4FD { background-position: -640px -200px; } +.emoji-1F4FE { background-position: -640px -220px; } +.emoji-1F4FF { background-position: -640px -240px; } +.emoji-1F500 { background-position: -640px -260px; } +.emoji-1F501 { background-position: -640px -280px; } +.emoji-1F502 { background-position: -640px -300px; } +.emoji-1F503 { background-position: -640px -320px; } +.emoji-1F504 { background-position: -640px -340px; } +.emoji-1F505 { background-position: -640px -360px; } +.emoji-1F506 { background-position: -640px -380px; } +.emoji-1F507 { background-position: -640px -400px; } +.emoji-1F508 { background-position: -640px -420px; } +.emoji-1F509 { background-position: -640px -440px; } +.emoji-1F50A { background-position: -640px -460px; } +.emoji-1F50B { background-position: -640px -480px; } +.emoji-1F50C { background-position: -640px -500px; } +.emoji-1F50D { background-position: -640px -520px; } +.emoji-1F50E { background-position: -640px -540px; } +.emoji-1F50F { background-position: -640px -560px; } +.emoji-1F510 { background-position: -640px -580px; } +.emoji-1F511 { background-position: -640px -600px; } +.emoji-1F512 { background-position: -640px -620px; } +.emoji-1F513 { background-position: 0px -640px; } +.emoji-1F514 { background-position: -20px -640px; } +.emoji-1F515 { background-position: -40px -640px; } +.emoji-1F516 { background-position: -60px -640px; } +.emoji-1F517 { background-position: -80px -640px; } +.emoji-1F518 { background-position: -100px -640px; } +.emoji-1F519 { background-position: -120px -640px; } +.emoji-1F51A { background-position: -140px -640px; } +.emoji-1F51B { background-position: -160px -640px; } +.emoji-1F51C { background-position: -180px -640px; } +.emoji-1F51D { background-position: -200px -640px; } +.emoji-1F51E { background-position: -220px -640px; } +.emoji-1F51F { background-position: -240px -640px; } +.emoji-1F520 { background-position: -260px -640px; } +.emoji-1F521 { background-position: -280px -640px; } +.emoji-1F522 { background-position: -300px -640px; } +.emoji-1F523 { background-position: -320px -640px; } +.emoji-1F524 { background-position: -340px -640px; } +.emoji-1F525 { background-position: -360px -640px; } +.emoji-1F526 { background-position: -380px -640px; } +.emoji-1F527 { background-position: -400px -640px; } +.emoji-1F528 { background-position: -420px -640px; } +.emoji-1F529 { background-position: -440px -640px; } +.emoji-1F52A { background-position: -460px -640px; } +.emoji-1F52B { background-position: -480px -640px; } +.emoji-1F52C { background-position: -500px -640px; } +.emoji-1F52D { background-position: -520px -640px; } +.emoji-1F52E { background-position: -540px -640px; } +.emoji-1F52F { background-position: -560px -640px; } +.emoji-1F530 { background-position: -580px -640px; } +.emoji-1F531 { background-position: -600px -640px; } +.emoji-1F532 { background-position: -620px -640px; } +.emoji-1F533 { background-position: -640px -640px; } +.emoji-1F534 { background-position: -660px 0px; } +.emoji-1F535 { background-position: -660px -20px; } +.emoji-1F536 { background-position: -660px -40px; } +.emoji-1F537 { background-position: -660px -60px; } +.emoji-1F538 { background-position: -660px -80px; } +.emoji-1F539 { background-position: -660px -100px; } +.emoji-1F53A { background-position: -660px -120px; } +.emoji-1F53B { background-position: -660px -140px; } +.emoji-1F53C { background-position: -660px -160px; } +.emoji-1F53D { background-position: -660px -180px; } +.emoji-1F546 { background-position: -660px -200px; } +.emoji-1F547 { background-position: -660px -220px; } +.emoji-1F548 { background-position: -660px -240px; } +.emoji-1F549 { background-position: -660px -260px; } +.emoji-1F54A { background-position: -660px -280px; } +.emoji-1F54B { background-position: -660px -300px; } +.emoji-1F54C { background-position: -660px -320px; } +.emoji-1F54D { background-position: -660px -340px; } +.emoji-1F54E { background-position: -660px -360px; } +.emoji-1F550 { background-position: -660px -380px; } +.emoji-1F551 { background-position: -660px -400px; } +.emoji-1F552 { background-position: -660px -420px; } +.emoji-1F553 { background-position: -660px -440px; } +.emoji-1F554 { background-position: -660px -460px; } +.emoji-1F555 { background-position: -660px -480px; } +.emoji-1F556 { background-position: -660px -500px; } +.emoji-1F557 { background-position: -660px -520px; } +.emoji-1F558 { background-position: -660px -540px; } +.emoji-1F559 { background-position: -660px -560px; } +.emoji-1F55A { background-position: -660px -580px; } +.emoji-1F55B { background-position: -660px -600px; } +.emoji-1F55C { background-position: -660px -620px; } +.emoji-1F55D { background-position: -660px -640px; } +.emoji-1F55E { background-position: 0px -660px; } +.emoji-1F55F { background-position: -20px -660px; } +.emoji-1F560 { background-position: -40px -660px; } +.emoji-1F561 { background-position: -60px -660px; } +.emoji-1F562 { background-position: -80px -660px; } +.emoji-1F563 { background-position: -100px -660px; } +.emoji-1F564 { background-position: -120px -660px; } +.emoji-1F565 { background-position: -140px -660px; } +.emoji-1F566 { background-position: -160px -660px; } +.emoji-1F567 { background-position: -180px -660px; } +.emoji-1F568 { background-position: -200px -660px; } +.emoji-1F569 { background-position: -220px -660px; } +.emoji-1F56A { background-position: -240px -660px; } +.emoji-1F56B { background-position: -260px -660px; } +.emoji-1F56C { background-position: -280px -660px; } +.emoji-1F56D { background-position: -300px -660px; } +.emoji-1F56E { background-position: -320px -660px; } +.emoji-1F56F { background-position: -340px -660px; } +.emoji-1F570 { background-position: -360px -660px; } +.emoji-1F571 { background-position: -380px -660px; } +.emoji-1F572 { background-position: -400px -660px; } +.emoji-1F573 { background-position: -420px -660px; } +.emoji-1F574 { background-position: -440px -660px; } +.emoji-1F575 { background-position: -460px -660px; } +.emoji-1F575-1F3FB { background-position: -480px -660px; } +.emoji-1F575-1F3FC { background-position: -500px -660px; } +.emoji-1F575-1F3FD { background-position: -520px -660px; } +.emoji-1F575-1F3FE { background-position: -540px -660px; } +.emoji-1F575-1F3FF { background-position: -560px -660px; } +.emoji-1F576 { background-position: -580px -660px; } +.emoji-1F577 { background-position: -600px -660px; } +.emoji-1F578 { background-position: -620px -660px; } +.emoji-1F579 { background-position: -640px -660px; } +.emoji-1F57B { background-position: -660px -660px; } +.emoji-1F57E { background-position: -680px 0px; } +.emoji-1F57F { background-position: -680px -20px; } +.emoji-1F581 { background-position: -680px -40px; } +.emoji-1F582 { background-position: -680px -60px; } +.emoji-1F583 { background-position: -680px -80px; } +.emoji-1F585 { background-position: -680px -100px; } +.emoji-1F586 { background-position: -680px -120px; } +.emoji-1F587 { background-position: -680px -140px; } +.emoji-1F588 { background-position: -680px -160px; } +.emoji-1F589 { background-position: -680px -180px; } +.emoji-1F58A { background-position: -680px -200px; } +.emoji-1F58B { background-position: -680px -220px; } +.emoji-1F58C { background-position: -680px -240px; } +.emoji-1F58D { background-position: -680px -260px; } +.emoji-1F58E { background-position: -680px -280px; } +.emoji-1F58F { background-position: -680px -300px; } +.emoji-1F590 { background-position: -680px -320px; } +.emoji-1F590-1F3FB { background-position: -680px -340px; } +.emoji-1F590-1F3FC { background-position: -680px -360px; } +.emoji-1F590-1F3FD { background-position: -680px -380px; } +.emoji-1F590-1F3FE { background-position: -680px -400px; } +.emoji-1F590-1F3FF { background-position: -680px -420px; } +.emoji-1F591 { background-position: -680px -440px; } +.emoji-1F592 { background-position: -680px -460px; } +.emoji-1F593 { background-position: -680px -480px; } +.emoji-1F594 { background-position: -680px -500px; } +.emoji-1F595 { background-position: -680px -520px; } +.emoji-1F595-1F3FB { background-position: -680px -540px; } +.emoji-1F595-1F3FC { background-position: -680px -560px; } +.emoji-1F595-1F3FD { background-position: -680px -580px; } +.emoji-1F595-1F3FE { background-position: -680px -600px; } +.emoji-1F595-1F3FF { background-position: -680px -620px; } +.emoji-1F596 { background-position: -680px -640px; } +.emoji-1F596-1F3FB { background-position: -680px -660px; } +.emoji-1F596-1F3FC { background-position: 0px -680px; } +.emoji-1F596-1F3FD { background-position: -20px -680px; } +.emoji-1F596-1F3FE { background-position: -40px -680px; } +.emoji-1F596-1F3FF { background-position: -60px -680px; } +.emoji-1F597 { background-position: -80px -680px; } +.emoji-1F598 { background-position: -100px -680px; } +.emoji-1F599 { background-position: -120px -680px; } +.emoji-1F59E { background-position: -140px -680px; } +.emoji-1F59F { background-position: -160px -680px; } +.emoji-1F5A5 { background-position: -180px -680px; } +.emoji-1F5A6 { background-position: -200px -680px; } +.emoji-1F5A7 { background-position: -220px -680px; } +.emoji-1F5A8 { background-position: -240px -680px; } +.emoji-1F5A9 { background-position: -260px -680px; } +.emoji-1F5AA { background-position: -280px -680px; } +.emoji-1F5AB { background-position: -300px -680px; } +.emoji-1F5AD { background-position: -320px -680px; } +.emoji-1F5AE { background-position: -340px -680px; } +.emoji-1F5AF { background-position: -360px -680px; } +.emoji-1F5B1 { background-position: -380px -680px; } +.emoji-1F5B2 { background-position: -400px -680px; } +.emoji-1F5B3 { background-position: -420px -680px; } +.emoji-1F5B4 { background-position: -440px -680px; } +.emoji-1F5B8 { background-position: -460px -680px; } +.emoji-1F5B9 { background-position: -480px -680px; } +.emoji-1F5BC { background-position: -500px -680px; } +.emoji-1F5BD { background-position: -520px -680px; } +.emoji-1F5BE { background-position: -540px -680px; } +.emoji-1F5C0 { background-position: -560px -680px; } +.emoji-1F5C1 { background-position: -580px -680px; } +.emoji-1F5C2 { background-position: -600px -680px; } +.emoji-1F5C3 { background-position: -620px -680px; } +.emoji-1F5C4 { background-position: -640px -680px; } +.emoji-1F5C6 { background-position: -660px -680px; } +.emoji-1F5C7 { background-position: -680px -680px; } +.emoji-1F5C9 { background-position: -700px 0px; } +.emoji-1F5CA { background-position: -700px -20px; } +.emoji-1F5CE { background-position: -700px -40px; } +.emoji-1F5CF { background-position: -700px -60px; } +.emoji-1F5D0 { background-position: -700px -80px; } +.emoji-1F5D1 { background-position: -700px -100px; } +.emoji-1F5D2 { background-position: -700px -120px; } +.emoji-1F5D3 { background-position: -700px -140px; } +.emoji-1F5D4 { background-position: -700px -160px; } +.emoji-1F5D8 { background-position: -700px -180px; } +.emoji-1F5D9 { background-position: -700px -200px; } +.emoji-1F5DC { background-position: -700px -220px; } +.emoji-1F5DD { background-position: -700px -240px; } +.emoji-1F5DE { background-position: -700px -260px; } +.emoji-1F5E0 { background-position: -700px -280px; } +.emoji-1F5E1 { background-position: -700px -300px; } +.emoji-1F5E2 { background-position: -700px -320px; } +.emoji-1F5E3 { background-position: -700px -340px; } +.emoji-1F5E8 { background-position: -700px -360px; } +.emoji-1F5E9 { background-position: -700px -380px; } +.emoji-1F5EA { background-position: -700px -400px; } +.emoji-1F5EB { background-position: -700px -420px; } +.emoji-1F5EC { background-position: -700px -440px; } +.emoji-1F5ED { background-position: -700px -460px; } +.emoji-1F5EE { background-position: -700px -480px; } +.emoji-1F5EF { background-position: -700px -500px; } +.emoji-1F5F0 { background-position: -700px -520px; } +.emoji-1F5F1 { background-position: -700px -540px; } +.emoji-1F5F2 { background-position: -700px -560px; } +.emoji-1F5F3 { background-position: -700px -580px; } +.emoji-1F5F4 { background-position: -700px -600px; } +.emoji-1F5F5 { background-position: -700px -620px; } +.emoji-1F5F8 { background-position: -700px -640px; } +.emoji-1F5F9 { background-position: -700px -660px; } +.emoji-1F5FA { background-position: -700px -680px; } +.emoji-1F5FB { background-position: 0px -700px; } +.emoji-1F5FC { background-position: -20px -700px; } +.emoji-1F5FD { background-position: -40px -700px; } +.emoji-1F5FE { background-position: -60px -700px; } +.emoji-1F5FF { background-position: -80px -700px; } +.emoji-1F600 { background-position: -100px -700px; } +.emoji-1F601 { background-position: -120px -700px; } +.emoji-1F602 { background-position: -140px -700px; } +.emoji-1F603 { background-position: -160px -700px; } +.emoji-1F604 { background-position: -180px -700px; } +.emoji-1F605 { background-position: -200px -700px; } +.emoji-1F606 { background-position: -220px -700px; } +.emoji-1F607 { background-position: -240px -700px; } +.emoji-1F608 { background-position: -260px -700px; } +.emoji-1F609 { background-position: -280px -700px; } +.emoji-1F60A { background-position: -300px -700px; } +.emoji-1F60B { background-position: -320px -700px; } +.emoji-1F60C { background-position: -340px -700px; } +.emoji-1F60D { background-position: -360px -700px; } +.emoji-1F60E { background-position: -380px -700px; } +.emoji-1F60F { background-position: -400px -700px; } +.emoji-1F610 { background-position: -420px -700px; } +.emoji-1F611 { background-position: -440px -700px; } +.emoji-1F612 { background-position: -460px -700px; } +.emoji-1F613 { background-position: -480px -700px; } +.emoji-1F614 { background-position: -500px -700px; } +.emoji-1F615 { background-position: -520px -700px; } +.emoji-1F616 { background-position: -540px -700px; } +.emoji-1F617 { background-position: -560px -700px; } +.emoji-1F618 { background-position: -580px -700px; } +.emoji-1F619 { background-position: -600px -700px; } +.emoji-1F61A { background-position: -620px -700px; } +.emoji-1F61B { background-position: -640px -700px; } +.emoji-1F61C { background-position: -660px -700px; } +.emoji-1F61D { background-position: -680px -700px; } +.emoji-1F61E { background-position: -700px -700px; } +.emoji-1F61F { background-position: -720px 0px; } +.emoji-1F620 { background-position: -720px -20px; } +.emoji-1F621 { background-position: -720px -40px; } +.emoji-1F622 { background-position: -720px -60px; } +.emoji-1F623 { background-position: -720px -80px; } +.emoji-1F624 { background-position: -720px -100px; } +.emoji-1F625 { background-position: -720px -120px; } +.emoji-1F626 { background-position: -720px -140px; } +.emoji-1F627 { background-position: -720px -160px; } +.emoji-1F628 { background-position: -720px -180px; } +.emoji-1F629 { background-position: -720px -200px; } +.emoji-1F62A { background-position: -720px -220px; } +.emoji-1F62B { background-position: -720px -240px; } +.emoji-1F62C { background-position: -720px -260px; } +.emoji-1F62D { background-position: -720px -280px; } +.emoji-1F62E { background-position: -720px -300px; } +.emoji-1F62F { background-position: -720px -320px; } +.emoji-1F630 { background-position: -720px -340px; } +.emoji-1F631 { background-position: -720px -360px; } +.emoji-1F632 { background-position: -720px -380px; } +.emoji-1F633 { background-position: -720px -400px; } +.emoji-1F634 { background-position: -720px -420px; } +.emoji-1F635 { background-position: -720px -440px; } +.emoji-1F636 { background-position: -720px -460px; } +.emoji-1F637 { background-position: -720px -480px; } +.emoji-1F638 { background-position: -720px -500px; } +.emoji-1F639 { background-position: -720px -520px; } +.emoji-1F63A { background-position: -720px -540px; } +.emoji-1F63B { background-position: -720px -560px; } +.emoji-1F63C { background-position: -720px -580px; } +.emoji-1F63D { background-position: -720px -600px; } +.emoji-1F63E { background-position: -720px -620px; } +.emoji-1F63F { background-position: -720px -640px; } +.emoji-1F640 { background-position: -720px -660px; } +.emoji-1F641 { background-position: -720px -680px; } +.emoji-1F642 { background-position: -720px -700px; } +.emoji-1F643 { background-position: 0px -720px; } +.emoji-1F644 { background-position: -20px -720px; } +.emoji-1F645 { background-position: -40px -720px; } +.emoji-1F645-1F3FB { background-position: -60px -720px; } +.emoji-1F645-1F3FC { background-position: -80px -720px; } +.emoji-1F645-1F3FD { background-position: -100px -720px; } +.emoji-1F645-1F3FE { background-position: -120px -720px; } +.emoji-1F645-1F3FF { background-position: -140px -720px; } +.emoji-1F646 { background-position: -160px -720px; } +.emoji-1F646-1F3FB { background-position: -180px -720px; } +.emoji-1F646-1F3FC { background-position: -200px -720px; } +.emoji-1F646-1F3FD { background-position: -220px -720px; } +.emoji-1F646-1F3FE { background-position: -240px -720px; } +.emoji-1F646-1F3FF { background-position: -260px -720px; } +.emoji-1F647 { background-position: -280px -720px; } +.emoji-1F647-1F3FB { background-position: -300px -720px; } +.emoji-1F647-1F3FC { background-position: -320px -720px; } +.emoji-1F647-1F3FD { background-position: -340px -720px; } +.emoji-1F647-1F3FE { background-position: -360px -720px; } +.emoji-1F647-1F3FF { background-position: -380px -720px; } +.emoji-1F648 { background-position: -400px -720px; } +.emoji-1F649 { background-position: -420px -720px; } +.emoji-1F64A { background-position: -440px -720px; } +.emoji-1F64B { background-position: -460px -720px; } +.emoji-1F64B-1F3FB { background-position: -480px -720px; } +.emoji-1F64B-1F3FC { background-position: -500px -720px; } +.emoji-1F64B-1F3FD { background-position: -520px -720px; } +.emoji-1F64B-1F3FE { background-position: -540px -720px; } +.emoji-1F64B-1F3FF { background-position: -560px -720px; } +.emoji-1F64C { background-position: -580px -720px; } +.emoji-1F64C-1F3FB { background-position: -600px -720px; } +.emoji-1F64C-1F3FC { background-position: -620px -720px; } +.emoji-1F64C-1F3FD { background-position: -640px -720px; } +.emoji-1F64C-1F3FE { background-position: -660px -720px; } +.emoji-1F64C-1F3FF { background-position: -680px -720px; } +.emoji-1F64D { background-position: -700px -720px; } +.emoji-1F64D-1F3FB { background-position: -720px -720px; } +.emoji-1F64D-1F3FC { background-position: -740px 0px; } +.emoji-1F64D-1F3FD { background-position: -740px -20px; } +.emoji-1F64D-1F3FE { background-position: -740px -40px; } +.emoji-1F64D-1F3FF { background-position: -740px -60px; } +.emoji-1F64E { background-position: -740px -80px; } +.emoji-1F64E-1F3FB { background-position: -740px -100px; } +.emoji-1F64E-1F3FC { background-position: -740px -120px; } +.emoji-1F64E-1F3FD { background-position: -740px -140px; } +.emoji-1F64E-1F3FE { background-position: -740px -160px; } +.emoji-1F64E-1F3FF { background-position: -740px -180px; } +.emoji-1F64F { background-position: -740px -200px; } +.emoji-1F64F-1F3FB { background-position: -740px -220px; } +.emoji-1F64F-1F3FC { background-position: -740px -240px; } +.emoji-1F64F-1F3FD { background-position: -740px -260px; } +.emoji-1F64F-1F3FE { background-position: -740px -280px; } +.emoji-1F64F-1F3FF { background-position: -740px -300px; } +.emoji-1F680 { background-position: -740px -320px; } +.emoji-1F681 { background-position: -740px -340px; } +.emoji-1F682 { background-position: -740px -360px; } +.emoji-1F683 { background-position: -740px -380px; } +.emoji-1F684 { background-position: -740px -400px; } +.emoji-1F685 { background-position: -740px -420px; } +.emoji-1F686 { background-position: -740px -440px; } +.emoji-1F687 { background-position: -740px -460px; } +.emoji-1F688 { background-position: -740px -480px; } +.emoji-1F689 { background-position: -740px -500px; } +.emoji-1F68A { background-position: -740px -520px; } +.emoji-1F68B { background-position: -740px -540px; } +.emoji-1F68C { background-position: -740px -560px; } +.emoji-1F68D { background-position: -740px -580px; } +.emoji-1F68E { background-position: -740px -600px; } +.emoji-1F68F { background-position: -740px -620px; } +.emoji-1F690 { background-position: -740px -640px; } +.emoji-1F691 { background-position: -740px -660px; } +.emoji-1F692 { background-position: -740px -680px; } +.emoji-1F693 { background-position: -740px -700px; } +.emoji-1F694 { background-position: -740px -720px; } +.emoji-1F695 { background-position: 0px -740px; } +.emoji-1F696 { background-position: -20px -740px; } +.emoji-1F697 { background-position: -40px -740px; } +.emoji-1F698 { background-position: -60px -740px; } +.emoji-1F699 { background-position: -80px -740px; } +.emoji-1F69A { background-position: -100px -740px; } +.emoji-1F69B { background-position: -120px -740px; } +.emoji-1F69C { background-position: -140px -740px; } +.emoji-1F69D { background-position: -160px -740px; } +.emoji-1F69E { background-position: -180px -740px; } +.emoji-1F69F { background-position: -200px -740px; } +.emoji-1F6A0 { background-position: -220px -740px; } +.emoji-1F6A1 { background-position: -240px -740px; } +.emoji-1F6A2 { background-position: -260px -740px; } +.emoji-1F6A3 { background-position: -280px -740px; } +.emoji-1F6A3-1F3FB { background-position: -300px -740px; } +.emoji-1F6A3-1F3FC { background-position: -320px -740px; } +.emoji-1F6A3-1F3FD { background-position: -340px -740px; } +.emoji-1F6A3-1F3FE { background-position: -360px -740px; } +.emoji-1F6A3-1F3FF { background-position: -380px -740px; } +.emoji-1F6A4 { background-position: -400px -740px; } +.emoji-1F6A5 { background-position: -420px -740px; } +.emoji-1F6A6 { background-position: -440px -740px; } +.emoji-1F6A7 { background-position: -460px -740px; } +.emoji-1F6A8 { background-position: -480px -740px; } +.emoji-1F6A9 { background-position: -500px -740px; } +.emoji-1F6AA { background-position: -520px -740px; } +.emoji-1F6AB { background-position: -540px -740px; } +.emoji-1F6AC { background-position: -560px -740px; } +.emoji-1F6AD { background-position: -580px -740px; } +.emoji-1F6AE { background-position: -600px -740px; } +.emoji-1F6AF { background-position: -620px -740px; } +.emoji-1F6B0 { background-position: -640px -740px; } +.emoji-1F6B1 { background-position: -660px -740px; } +.emoji-1F6B2 { background-position: -680px -740px; } +.emoji-1F6B3 { background-position: -700px -740px; } +.emoji-1F6B4 { background-position: -720px -740px; } +.emoji-1F6B4-1F3FB { background-position: -740px -740px; } +.emoji-1F6B4-1F3FC { background-position: -760px 0px; } +.emoji-1F6B4-1F3FD { background-position: -760px -20px; } +.emoji-1F6B4-1F3FE { background-position: -760px -40px; } +.emoji-1F6B4-1F3FF { background-position: -760px -60px; } +.emoji-1F6B5 { background-position: -760px -80px; } +.emoji-1F6B5-1F3FB { background-position: -760px -100px; } +.emoji-1F6B5-1F3FC { background-position: -760px -120px; } +.emoji-1F6B5-1F3FD { background-position: -760px -140px; } +.emoji-1F6B5-1F3FE { background-position: -760px -160px; } +.emoji-1F6B5-1F3FF { background-position: -760px -180px; } +.emoji-1F6B6 { background-position: -760px -200px; } +.emoji-1F6B6-1F3FB { background-position: -760px -220px; } +.emoji-1F6B6-1F3FC { background-position: -760px -240px; } +.emoji-1F6B6-1F3FD { background-position: -760px -260px; } +.emoji-1F6B6-1F3FE { background-position: -760px -280px; } +.emoji-1F6B6-1F3FF { background-position: -760px -300px; } +.emoji-1F6B7 { background-position: -760px -320px; } +.emoji-1F6B8 { background-position: -760px -340px; } +.emoji-1F6B9 { background-position: -760px -360px; } +.emoji-1F6BA { background-position: -760px -380px; } +.emoji-1F6BB { background-position: -760px -400px; } +.emoji-1F6BC { background-position: -760px -420px; } +.emoji-1F6BD { background-position: -760px -440px; } +.emoji-1F6BE { background-position: -760px -460px; } +.emoji-1F6BF { background-position: -760px -480px; } +.emoji-1F6C0 { background-position: -760px -500px; } +.emoji-1F6C0-1F3FB { background-position: -760px -520px; } +.emoji-1F6C0-1F3FC { background-position: -760px -540px; } +.emoji-1F6C0-1F3FD { background-position: -760px -560px; } +.emoji-1F6C0-1F3FE { background-position: -760px -580px; } +.emoji-1F6C0-1F3FF { background-position: -760px -600px; } +.emoji-1F6C1 { background-position: -760px -620px; } +.emoji-1F6C2 { background-position: -760px -640px; } +.emoji-1F6C3 { background-position: -760px -660px; } +.emoji-1F6C4 { background-position: -760px -680px; } +.emoji-1F6C5 { background-position: -760px -700px; } +.emoji-1F6C6 { background-position: -760px -720px; } +.emoji-1F6C7 { background-position: -760px -740px; } +.emoji-1F6C8 { background-position: 0px -760px; } +.emoji-1F6C9 { background-position: -20px -760px; } +.emoji-1F6CA { background-position: -40px -760px; } +.emoji-1F6CB { background-position: -60px -760px; } +.emoji-1F6CC { background-position: -80px -760px; } +.emoji-1F6CD { background-position: -100px -760px; } +.emoji-1F6CE { background-position: -120px -760px; } +.emoji-1F6CF { background-position: -140px -760px; } +.emoji-1F6D0 { background-position: -160px -760px; } +.emoji-1F6E0 { background-position: -180px -760px; } +.emoji-1F6E1 { background-position: -200px -760px; } +.emoji-1F6E2 { background-position: -220px -760px; } +.emoji-1F6E3 { background-position: -240px -760px; } +.emoji-1F6E4 { background-position: -260px -760px; } +.emoji-1F6E5 { background-position: -280px -760px; } +.emoji-1F6E6 { background-position: -300px -760px; } +.emoji-1F6E7 { background-position: -320px -760px; } +.emoji-1F6E8 { background-position: -340px -760px; } +.emoji-1F6E9 { background-position: -360px -760px; } +.emoji-1F6EA { background-position: -380px -760px; } +.emoji-1F6EB { background-position: -400px -760px; } +.emoji-1F6EC { background-position: -420px -760px; } +.emoji-1F6F0 { background-position: -440px -760px; } +.emoji-1F6F1 { background-position: -460px -760px; } +.emoji-1F6F2 { background-position: -480px -760px; } +.emoji-1F6F3 { background-position: -500px -760px; } +.emoji-1F910 { background-position: -520px -760px; } +.emoji-1F911 { background-position: -540px -760px; } +.emoji-1F912 { background-position: -560px -760px; } +.emoji-1F913 { background-position: -580px -760px; } +.emoji-1F914 { background-position: -600px -760px; } +.emoji-1F915 { background-position: -620px -760px; } +.emoji-1F916 { background-position: -640px -760px; } +.emoji-1F917 { background-position: -660px -760px; } +.emoji-1F918 { background-position: -680px -760px; } +.emoji-1F918-1F3FB { background-position: -700px -760px; } +.emoji-1F918-1F3FC { background-position: -720px -760px; } +.emoji-1F918-1F3FD { background-position: -740px -760px; } +.emoji-1F918-1F3FE { background-position: -760px -760px; } +.emoji-1F918-1F3FF { background-position: -780px 0px; } +.emoji-1F980 { background-position: -780px -20px; } +.emoji-1F981 { background-position: -780px -40px; } +.emoji-1F982 { background-position: -780px -60px; } +.emoji-1F983 { background-position: -780px -80px; } +.emoji-1F984 { background-position: -780px -100px; } +.emoji-1F9C0 { background-position: -780px -120px; } +.emoji-203C { background-position: -780px -140px; } +.emoji-2049 { background-position: -780px -160px; } +.emoji-2122 { background-position: -780px -180px; } +.emoji-2139 { background-position: -780px -200px; } +.emoji-2194 { background-position: -780px -220px; } +.emoji-2195 { background-position: -780px -240px; } +.emoji-2196 { background-position: -780px -260px; } +.emoji-2197 { background-position: -780px -280px; } +.emoji-2198 { background-position: -780px -300px; } +.emoji-2199 { background-position: -780px -320px; } +.emoji-21A9 { background-position: -780px -340px; } +.emoji-21AA { background-position: -780px -360px; } +.emoji-231A { background-position: -780px -380px; } +.emoji-231B { background-position: -780px -400px; } +.emoji-2328 { background-position: -780px -420px; } +.emoji-23E9 { background-position: -780px -440px; } +.emoji-23EA { background-position: -780px -460px; } +.emoji-23EB { background-position: -780px -480px; } +.emoji-23EC { background-position: -780px -500px; } +.emoji-23ED { background-position: -780px -520px; } +.emoji-23EE { background-position: -780px -540px; } +.emoji-23EF { background-position: -780px -560px; } +.emoji-23F0 { background-position: -780px -580px; } +.emoji-23F1 { background-position: -780px -600px; } +.emoji-23F2 { background-position: -780px -620px; } +.emoji-23F3 { background-position: -780px -640px; } +.emoji-23F8 { background-position: -780px -660px; } +.emoji-23F9 { background-position: -780px -680px; } +.emoji-23FA { background-position: -780px -700px; } +.emoji-24C2 { background-position: -780px -720px; } +.emoji-25AA { background-position: -780px -740px; } +.emoji-25AB { background-position: -780px -760px; } +.emoji-25B6 { background-position: 0px -780px; } +.emoji-25C0 { background-position: -20px -780px; } +.emoji-25FB { background-position: -40px -780px; } +.emoji-25FC { background-position: -60px -780px; } +.emoji-25FD { background-position: -80px -780px; } +.emoji-25FE { background-position: -100px -780px; } +.emoji-2600 { background-position: -120px -780px; } +.emoji-2601 { background-position: -140px -780px; } +.emoji-2602 { background-position: -160px -780px; } +.emoji-2603 { background-position: -180px -780px; } +.emoji-2604 { background-position: -200px -780px; } +.emoji-260E { background-position: -220px -780px; } +.emoji-2611 { background-position: -240px -780px; } +.emoji-2614 { background-position: -260px -780px; } +.emoji-2615 { background-position: -280px -780px; } +.emoji-2618 { background-position: -300px -780px; } +.emoji-261D { background-position: -320px -780px; } +.emoji-261D-1F3FB { background-position: -340px -780px; } +.emoji-261D-1F3FC { background-position: -360px -780px; } +.emoji-261D-1F3FD { background-position: -380px -780px; } +.emoji-261D-1F3FE { background-position: -400px -780px; } +.emoji-261D-1F3FF { background-position: -420px -780px; } +.emoji-2620 { background-position: -440px -780px; } +.emoji-2622 { background-position: -460px -780px; } +.emoji-2623 { background-position: -480px -780px; } +.emoji-2626 { background-position: -500px -780px; } +.emoji-262A { background-position: -520px -780px; } +.emoji-262E { background-position: -540px -780px; } +.emoji-262F { background-position: -560px -780px; } +.emoji-2638 { background-position: -580px -780px; } +.emoji-2639 { background-position: -600px -780px; } +.emoji-263A { background-position: -620px -780px; } +.emoji-2648 { background-position: -640px -780px; } +.emoji-2649 { background-position: -660px -780px; } +.emoji-264A { background-position: -680px -780px; } +.emoji-264B { background-position: -700px -780px; } +.emoji-264C { background-position: -720px -780px; } +.emoji-264D { background-position: -740px -780px; } +.emoji-264E { background-position: -760px -780px; } +.emoji-264F { background-position: -780px -780px; } +.emoji-2650 { background-position: -800px 0px; } +.emoji-2651 { background-position: -800px -20px; } +.emoji-2652 { background-position: -800px -40px; } +.emoji-2653 { background-position: -800px -60px; } +.emoji-2660 { background-position: -800px -80px; } +.emoji-2663 { background-position: -800px -100px; } +.emoji-2665 { background-position: -800px -120px; } +.emoji-2666 { background-position: -800px -140px; } +.emoji-2668 { background-position: -800px -160px; } +.emoji-267B { background-position: -800px -180px; } +.emoji-267F { background-position: -800px -200px; } +.emoji-2692 { background-position: -800px -220px; } +.emoji-2693 { background-position: -800px -240px; } +.emoji-2694 { background-position: -800px -260px; } +.emoji-2696 { background-position: -800px -280px; } +.emoji-2697 { background-position: -800px -300px; } +.emoji-2699 { background-position: -800px -320px; } +.emoji-269B { background-position: -800px -340px; } +.emoji-269C { background-position: -800px -360px; } +.emoji-26A0 { background-position: -800px -380px; } +.emoji-26A1 { background-position: -800px -400px; } +.emoji-26AA { background-position: -800px -420px; } +.emoji-26AB { background-position: -800px -440px; } +.emoji-26B0 { background-position: -800px -460px; } +.emoji-26B1 { background-position: -800px -480px; } +.emoji-26BD { background-position: -800px -500px; } +.emoji-26BE { background-position: -800px -520px; } +.emoji-26C4 { background-position: -800px -540px; } +.emoji-26C5 { background-position: -800px -560px; } +.emoji-26C8 { background-position: -800px -580px; } +.emoji-26CE { background-position: -800px -600px; } +.emoji-26CF { background-position: -800px -620px; } +.emoji-26D1 { background-position: -800px -640px; } +.emoji-26D3 { background-position: -800px -660px; } +.emoji-26D4 { background-position: -800px -680px; } +.emoji-26E9 { background-position: -800px -700px; } +.emoji-26EA { background-position: -800px -720px; } +.emoji-26F0 { background-position: -800px -740px; } +.emoji-26F1 { background-position: -800px -760px; } +.emoji-26F2 { background-position: -800px -780px; } +.emoji-26F3 { background-position: 0px -800px; } +.emoji-26F4 { background-position: -20px -800px; } +.emoji-26F5 { background-position: -40px -800px; } +.emoji-26F7 { background-position: -60px -800px; } +.emoji-26F8 { background-position: -80px -800px; } +.emoji-26F9 { background-position: -100px -800px; } +.emoji-26F9-1F3FB { background-position: -120px -800px; } +.emoji-26F9-1F3FC { background-position: -140px -800px; } +.emoji-26F9-1F3FD { background-position: -160px -800px; } +.emoji-26F9-1F3FE { background-position: -180px -800px; } +.emoji-26F9-1F3FF { background-position: -200px -800px; } +.emoji-26FA { background-position: -220px -800px; } +.emoji-26FD { background-position: -240px -800px; } +.emoji-2702 { background-position: -260px -800px; } +.emoji-2705 { background-position: -280px -800px; } +.emoji-2708 { background-position: -300px -800px; } +.emoji-2709 { background-position: -320px -800px; } +.emoji-270A { background-position: -340px -800px; } +.emoji-270A-1F3FB { background-position: -360px -800px; } +.emoji-270A-1F3FC { background-position: -380px -800px; } +.emoji-270A-1F3FD { background-position: -400px -800px; } +.emoji-270A-1F3FE { background-position: -420px -800px; } +.emoji-270A-1F3FF { background-position: -440px -800px; } +.emoji-270B { background-position: -460px -800px; } +.emoji-270B-1F3FB { background-position: -480px -800px; } +.emoji-270B-1F3FC { background-position: -500px -800px; } +.emoji-270B-1F3FD { background-position: -520px -800px; } +.emoji-270B-1F3FE { background-position: -540px -800px; } +.emoji-270B-1F3FF { background-position: -560px -800px; } +.emoji-270C { background-position: -580px -800px; } +.emoji-270C-1F3FB { background-position: -600px -800px; } +.emoji-270C-1F3FC { background-position: -620px -800px; } +.emoji-270C-1F3FD { background-position: -640px -800px; } +.emoji-270C-1F3FE { background-position: -660px -800px; } +.emoji-270C-1F3FF { background-position: -680px -800px; } +.emoji-270D { background-position: -700px -800px; } +.emoji-270D-1F3FB { background-position: -720px -800px; } +.emoji-270D-1F3FC { background-position: -740px -800px; } +.emoji-270D-1F3FD { background-position: -760px -800px; } +.emoji-270D-1F3FE { background-position: -780px -800px; } +.emoji-270D-1F3FF { background-position: -800px -800px; } +.emoji-270F { background-position: -820px 0px; } +.emoji-2712 { background-position: -820px -20px; } +.emoji-2714 { background-position: -820px -40px; } +.emoji-2716 { background-position: -820px -60px; } +.emoji-271D { background-position: -820px -80px; } +.emoji-2721 { background-position: -820px -100px; } +.emoji-2728 { background-position: -820px -120px; } +.emoji-2733 { background-position: -820px -140px; } +.emoji-2734 { background-position: -820px -160px; } +.emoji-2744 { background-position: -820px -180px; } +.emoji-2747 { background-position: -820px -200px; } +.emoji-274C { background-position: -820px -220px; } +.emoji-274E { background-position: -820px -240px; } +.emoji-2753 { background-position: -820px -260px; } +.emoji-2754 { background-position: -820px -280px; } +.emoji-2755 { background-position: -820px -300px; } +.emoji-2757 { background-position: -820px -320px; } +.emoji-2763 { background-position: -820px -340px; } +.emoji-2764 { background-position: -820px -360px; } +.emoji-2795 { background-position: -820px -380px; } +.emoji-2796 { background-position: -820px -400px; } +.emoji-2797 { background-position: -820px -420px; } +.emoji-27A1 { background-position: -820px -440px; } +.emoji-27B0 { background-position: -820px -460px; } +.emoji-27BF { background-position: -820px -480px; } +.emoji-2934 { background-position: -820px -500px; } +.emoji-2935 { background-position: -820px -520px; } +.emoji-2B05 { background-position: -820px -540px; } +.emoji-2B06 { background-position: -820px -560px; } +.emoji-2B07 { background-position: -820px -580px; } +.emoji-2B1B { background-position: -820px -600px; } +.emoji-2B1C { background-position: -820px -620px; } +.emoji-2B50 { background-position: -820px -640px; } +.emoji-2B55 { background-position: -820px -660px; } +.emoji-3030 { background-position: -820px -680px; } +.emoji-303D { background-position: -820px -700px; } +.emoji-3297 { background-position: -820px -720px; } +.emoji-3299 { background-position: -820px -740px; } -.emoji-icon{ - background-image: image-url("emoji.png"); +.emoji-icon { + background-image: image-url('emoji.png'); background-repeat: no-repeat; -} + height: 20px; + width: 20px; -.emoji-0023-20E3 { background-position: 0px 0px; } -.emoji-0030-20E3 { background-position: -20px 0px; } -.emoji-0031-20E3 { background-position: -40px 0px; } -.emoji-0032-20E3 { background-position: -60px 0px; } -.emoji-0033-20E3 { background-position: -80px 0px; } -.emoji-0034-20E3 { background-position: -100px 0px; } -.emoji-0035-20E3 { background-position: -120px 0px; } -.emoji-0036-20E3 { background-position: -140px 0px; } -.emoji-0037-20E3 { background-position: -160px 0px; } -.emoji-0038-20E3 { background-position: -180px 0px; } -.emoji-0039-20E3 { background-position: -200px 0px; } -.emoji-00A9 { background-position: -220px 0px; } -.emoji-00AE { background-position: -240px 0px; } -.emoji-1F004 { background-position: -260px 0px; } -.emoji-1F0CF { background-position: -280px 0px; } -.emoji-1F170 { background-position: -300px 0px; } -.emoji-1F171 { background-position: -320px 0px; } -.emoji-1F17E { background-position: -340px 0px; } -.emoji-1F17F { background-position: -360px 0px; } -.emoji-1F18E { background-position: -380px 0px; } -.emoji-1F191 { background-position: -400px 0px; } -.emoji-1F192 { background-position: -420px 0px; } -.emoji-1F193 { background-position: -440px 0px; } -.emoji-1F194 { background-position: -460px 0px; } -.emoji-1F195 { background-position: -480px 0px; } -.emoji-1F196 { background-position: -500px 0px; } -.emoji-1F197 { background-position: -520px 0px; } -.emoji-1F198 { background-position: -540px 0px; } -.emoji-1F199 { background-position: -560px 0px; } -.emoji-1F19A { background-position: -580px 0px; } -.emoji-1F1E6-1F1E8 { background-position: -600px 0px; } -.emoji-1F1E6-1F1E9 { background-position: -620px 0px; } -.emoji-1F1E6-1F1EA { background-position: -640px 0px; } -.emoji-1F1E6-1F1EB { background-position: -660px 0px; } -.emoji-1F1E6-1F1EC { background-position: -680px 0px; } -.emoji-1F1E6-1F1EE { background-position: -700px 0px; } -.emoji-1F1E6-1F1F1 { background-position: -720px 0px; } -.emoji-1F1E6-1F1F2 { background-position: -740px 0px; } -.emoji-1F1E6-1F1F4 { background-position: -760px 0px; } -.emoji-1F1E6-1F1F7 { background-position: -780px 0px; } -.emoji-1F1E6-1F1F9 { background-position: -800px 0px; } -.emoji-1F1E6-1F1FA { background-position: -820px 0px; } -.emoji-1F1E6-1F1FC { background-position: -840px 0px; } -.emoji-1F1E6-1F1FF { background-position: -860px 0px; } -.emoji-1F1E7-1F1E6 { background-position: -880px 0px; } -.emoji-1F1E7-1F1E7 { background-position: -900px 0px; } -.emoji-1F1E7-1F1E9 { background-position: -920px 0px; } -.emoji-1F1E7-1F1EA { background-position: -940px 0px; } -.emoji-1F1E7-1F1EB { background-position: -960px 0px; } -.emoji-1F1E7-1F1EC { background-position: -980px 0px; } -.emoji-1F1E7-1F1ED { background-position: -1000px 0px; } -.emoji-1F1E7-1F1EE { background-position: -1020px 0px; } -.emoji-1F1E7-1F1EF { background-position: -1040px 0px; } -.emoji-1F1E7-1F1F2 { background-position: -1060px 0px; } -.emoji-1F1E7-1F1F3 { background-position: -1080px 0px; } -.emoji-1F1E7-1F1F4 { background-position: -1100px 0px; } -.emoji-1F1E7-1F1F7 { background-position: -1120px 0px; } -.emoji-1F1E7-1F1F8 { background-position: -1140px 0px; } -.emoji-1F1E7-1F1F9 { background-position: -1160px 0px; } -.emoji-1F1E7-1F1FC { background-position: -1180px 0px; } -.emoji-1F1E7-1F1FE { background-position: -1200px 0px; } -.emoji-1F1E7-1F1FF { background-position: -1220px 0px; } -.emoji-1F1E8-1F1E6 { background-position: -1240px 0px; } -.emoji-1F1E8-1F1E9 { background-position: -1260px 0px; } -.emoji-1F1E8-1F1EB { background-position: -1280px 0px; } -.emoji-1F1E8-1F1EC { background-position: -1300px 0px; } -.emoji-1F1E8-1F1ED { background-position: -1320px 0px; } -.emoji-1F1E8-1F1EE { background-position: -1340px 0px; } -.emoji-1F1E8-1F1F1 { background-position: -1360px 0px; } -.emoji-1F1E8-1F1F2 { background-position: -1380px 0px; } -.emoji-1F1E8-1F1F3 { background-position: -1400px 0px; } -.emoji-1F1E8-1F1F4 { background-position: -1420px 0px; } -.emoji-1F1E8-1F1F7 { background-position: -1440px 0px; } -.emoji-1F1E8-1F1FA { background-position: -1460px 0px; } -.emoji-1F1E8-1F1FB { background-position: -1480px 0px; } -.emoji-1F1E8-1F1FE { background-position: -1500px 0px; } -.emoji-1F1E8-1F1FF { background-position: -1520px 0px; } -.emoji-1F1E9-1F1EA { background-position: -1540px 0px; } -.emoji-1F1E9-1F1EF { background-position: -1560px 0px; } -.emoji-1F1E9-1F1F0 { background-position: -1580px 0px; } -.emoji-1F1E9-1F1F2 { background-position: -1600px 0px; } -.emoji-1F1E9-1F1F4 { background-position: -1620px 0px; } -.emoji-1F1E9-1F1FF { background-position: -1640px 0px; } -.emoji-1F1EA-1F1E8 { background-position: -1660px 0px; } -.emoji-1F1EA-1F1EA { background-position: -1680px 0px; } -.emoji-1F1EA-1F1EC { background-position: -1700px 0px; } -.emoji-1F1EA-1F1ED { background-position: -1720px 0px; } -.emoji-1F1EA-1F1F7 { background-position: -1740px 0px; } -.emoji-1F1EA-1F1F8 { background-position: -1760px 0px; } -.emoji-1F1EA-1F1F9 { background-position: -1780px 0px; } -.emoji-1F1EB-1F1EE { background-position: -1800px 0px; } -.emoji-1F1EB-1F1EF { background-position: -1820px 0px; } -.emoji-1F1EB-1F1F0 { background-position: -1840px 0px; } -.emoji-1F1EB-1F1F2 { background-position: -1860px 0px; } -.emoji-1F1EB-1F1F4 { background-position: -1880px 0px; } -.emoji-1F1EB-1F1F7 { background-position: -1900px 0px; } -.emoji-1F1EC-1F1E6 { background-position: -1920px 0px; } -.emoji-1F1EC-1F1E7 { background-position: -1940px 0px; } -.emoji-1F1EC-1F1E9 { background-position: -1960px 0px; } -.emoji-1F1EC-1F1EA { background-position: -1980px 0px; } -.emoji-1F1EC-1F1ED { background-position: -2000px 0px; } -.emoji-1F1EC-1F1EE { background-position: -2020px 0px; } -.emoji-1F1EC-1F1F1 { background-position: -2040px 0px; } -.emoji-1F1EC-1F1F2 { background-position: -2060px 0px; } -.emoji-1F1EC-1F1F3 { background-position: -2080px 0px; } -.emoji-1F1EC-1F1F6 { background-position: -2100px 0px; } -.emoji-1F1EC-1F1F7 { background-position: -2120px 0px; } -.emoji-1F1EC-1F1F9 { background-position: -2140px 0px; } -.emoji-1F1EC-1F1FA { background-position: -2160px 0px; } -.emoji-1F1EC-1F1FC { background-position: -2180px 0px; } -.emoji-1F1EC-1F1FE { background-position: -2200px 0px; } -.emoji-1F1ED-1F1F0 { background-position: -2220px 0px; } -.emoji-1F1ED-1F1F3 { background-position: -2240px 0px; } -.emoji-1F1ED-1F1F7 { background-position: -2260px 0px; } -.emoji-1F1ED-1F1F9 { background-position: -2280px 0px; } -.emoji-1F1ED-1F1FA { background-position: -2300px 0px; } -.emoji-1F1EE-1F1E9 { background-position: -2320px 0px; } -.emoji-1F1EE-1F1EA { background-position: -2340px 0px; } -.emoji-1F1EE-1F1F1 { background-position: -2360px 0px; } -.emoji-1F1EE-1F1F3 { background-position: -2380px 0px; } -.emoji-1F1EE-1F1F6 { background-position: -2400px 0px; } -.emoji-1F1EE-1F1F7 { background-position: -2420px 0px; } -.emoji-1F1EE-1F1F8 { background-position: -2440px 0px; } -.emoji-1F1EE-1F1F9 { background-position: -2460px 0px; } -.emoji-1F1EF-1F1EA { background-position: -2480px 0px; } -.emoji-1F1EF-1F1F2 { background-position: -2500px 0px; } -.emoji-1F1EF-1F1F4 { background-position: -2520px 0px; } -.emoji-1F1EF-1F1F5 { background-position: -2540px 0px; } -.emoji-1F1F0-1F1EA { background-position: -2560px 0px; } -.emoji-1F1F0-1F1EC { background-position: -2580px 0px; } -.emoji-1F1F0-1F1ED { background-position: -2600px 0px; } -.emoji-1F1F0-1F1EE { background-position: -2620px 0px; } -.emoji-1F1F0-1F1F2 { background-position: -2640px 0px; } -.emoji-1F1F0-1F1F3 { background-position: -2660px 0px; } -.emoji-1F1F0-1F1F5 { background-position: -2680px 0px; } -.emoji-1F1F0-1F1F7 { background-position: -2700px 0px; } -.emoji-1F1F0-1F1FC { background-position: -2720px 0px; } -.emoji-1F1F0-1F1FE { background-position: -2740px 0px; } -.emoji-1F1F0-1F1FF { background-position: -2760px 0px; } -.emoji-1F1F1-1F1E6 { background-position: -2780px 0px; } -.emoji-1F1F1-1F1E7 { background-position: -2800px 0px; } -.emoji-1F1F1-1F1E8 { background-position: -2820px 0px; } -.emoji-1F1F1-1F1EE { background-position: -2840px 0px; } -.emoji-1F1F1-1F1F0 { background-position: -2860px 0px; } -.emoji-1F1F1-1F1F7 { background-position: -2880px 0px; } -.emoji-1F1F1-1F1F8 { background-position: -2900px 0px; } -.emoji-1F1F1-1F1F9 { background-position: -2920px 0px; } -.emoji-1F1F1-1F1FA { background-position: -2940px 0px; } -.emoji-1F1F1-1F1FB { background-position: -2960px 0px; } -.emoji-1F1F1-1F1FE { background-position: -2980px 0px; } -.emoji-1F1F2-1F1E6 { background-position: -3000px 0px; } -.emoji-1F1F2-1F1E8 { background-position: -3020px 0px; } -.emoji-1F1F2-1F1E9 { background-position: -3040px 0px; } -.emoji-1F1F2-1F1EA { background-position: -3060px 0px; } -.emoji-1F1F2-1F1EC { background-position: -3080px 0px; } -.emoji-1F1F2-1F1ED { background-position: -3100px 0px; } -.emoji-1F1F2-1F1F0 { background-position: -3120px 0px; } -.emoji-1F1F2-1F1F1 { background-position: -3140px 0px; } -.emoji-1F1F2-1F1F2 { background-position: -3160px 0px; } -.emoji-1F1F2-1F1F3 { background-position: -3180px 0px; } -.emoji-1F1F2-1F1F4 { background-position: -3200px 0px; } -.emoji-1F1F2-1F1F7 { background-position: -3220px 0px; } -.emoji-1F1F2-1F1F8 { background-position: -3240px 0px; } -.emoji-1F1F2-1F1F9 { background-position: -3260px 0px; } -.emoji-1F1F2-1F1FA { background-position: -3280px 0px; } -.emoji-1F1F2-1F1FB { background-position: -3300px 0px; } -.emoji-1F1F2-1F1FC { background-position: -3320px 0px; } -.emoji-1F1F2-1F1FD { background-position: -3340px 0px; } -.emoji-1F1F2-1F1FE { background-position: -3360px 0px; } -.emoji-1F1F2-1F1FF { background-position: -3380px 0px; } -.emoji-1F1F3-1F1E6 { background-position: -3400px 0px; } -.emoji-1F1F3-1F1E8 { background-position: -3420px 0px; } -.emoji-1F1F3-1F1EA { background-position: -3440px 0px; } -.emoji-1F1F3-1F1EC { background-position: -3460px 0px; } -.emoji-1F1F3-1F1EE { background-position: -3480px 0px; } -.emoji-1F1F3-1F1F1 { background-position: -3500px 0px; } -.emoji-1F1F3-1F1F4 { background-position: -3520px 0px; } -.emoji-1F1F3-1F1F5 { background-position: -3540px 0px; } -.emoji-1F1F3-1F1F7 { background-position: -3560px 0px; } -.emoji-1F1F3-1F1FA { background-position: -3580px 0px; } -.emoji-1F1F3-1F1FF { background-position: -3600px 0px; } -.emoji-1F1F4-1F1F2 { background-position: -3620px 0px; } -.emoji-1F1F5-1F1E6 { background-position: -3640px 0px; } -.emoji-1F1F5-1F1EA { background-position: -3660px 0px; } -.emoji-1F1F5-1F1EB { background-position: -3680px 0px; } -.emoji-1F1F5-1F1EC { background-position: -3700px 0px; } -.emoji-1F1F5-1F1ED { background-position: -3720px 0px; } -.emoji-1F1F5-1F1F0 { background-position: -3740px 0px; } -.emoji-1F1F5-1F1F1 { background-position: -3760px 0px; } -.emoji-1F1F5-1F1F7 { background-position: -3780px 0px; } -.emoji-1F1F5-1F1F8 { background-position: -3800px 0px; } -.emoji-1F1F5-1F1F9 { background-position: -3820px 0px; } -.emoji-1F1F5-1F1FC { background-position: -3840px 0px; } -.emoji-1F1F5-1F1FE { background-position: -3860px 0px; } -.emoji-1F1F6-1F1E6 { background-position: -3880px 0px; } -.emoji-1F1F7-1F1F4 { background-position: -3900px 0px; } -.emoji-1F1F7-1F1F8 { background-position: -3920px 0px; } -.emoji-1F1F7-1F1FA { background-position: -3940px 0px; } -.emoji-1F1F7-1F1FC { background-position: -3960px 0px; } -.emoji-1F1F8-1F1E6 { background-position: -3980px 0px; } -.emoji-1F1F8-1F1E7 { background-position: -4000px 0px; } -.emoji-1F1F8-1F1E8 { background-position: -4020px 0px; } -.emoji-1F1F8-1F1E9 { background-position: -4040px 0px; } -.emoji-1F1F8-1F1EA { background-position: -4060px 0px; } -.emoji-1F1F8-1F1EC { background-position: -4080px 0px; } -.emoji-1F1F8-1F1ED { background-position: -4100px 0px; } -.emoji-1F1F8-1F1EE { background-position: -4120px 0px; } -.emoji-1F1F8-1F1F0 { background-position: -4140px 0px; } -.emoji-1F1F8-1F1F1 { background-position: -4160px 0px; } -.emoji-1F1F8-1F1F2 { background-position: -4180px 0px; } -.emoji-1F1F8-1F1F3 { background-position: -4200px 0px; } -.emoji-1F1F8-1F1F4 { background-position: -4220px 0px; } -.emoji-1F1F8-1F1F7 { background-position: -4240px 0px; } -.emoji-1F1F8-1F1F9 { background-position: -4260px 0px; } -.emoji-1F1F8-1F1FB { background-position: -4280px 0px; } -.emoji-1F1F8-1F1FE { background-position: -4300px 0px; } -.emoji-1F1F8-1F1FF { background-position: -4320px 0px; } -.emoji-1F1F9-1F1E9 { background-position: -4340px 0px; } -.emoji-1F1F9-1F1EC { background-position: -4360px 0px; } -.emoji-1F1F9-1F1ED { background-position: -4380px 0px; } -.emoji-1F1F9-1F1EF { background-position: -4400px 0px; } -.emoji-1F1F9-1F1F1 { background-position: -4420px 0px; } -.emoji-1F1F9-1F1F2 { background-position: -4440px 0px; } -.emoji-1F1F9-1F1F3 { background-position: -4460px 0px; } -.emoji-1F1F9-1F1F4 { background-position: -4480px 0px; } -.emoji-1F1F9-1F1F7 { background-position: -4500px 0px; } -.emoji-1F1F9-1F1F9 { background-position: -4520px 0px; } -.emoji-1F1F9-1F1FB { background-position: -4540px 0px; } -.emoji-1F1F9-1F1FC { background-position: -4560px 0px; } -.emoji-1F1F9-1F1FF { background-position: -4580px 0px; } -.emoji-1F1FA-1F1E6 { background-position: -4600px 0px; } -.emoji-1F1FA-1F1EC { background-position: -4620px 0px; } -.emoji-1F1FA-1F1F8 { background-position: -4640px 0px; } -.emoji-1F1FA-1F1FE { background-position: -4660px 0px; } -.emoji-1F1FA-1F1FF { background-position: -4680px 0px; } -.emoji-1F1FB-1F1E6 { background-position: -4700px 0px; } -.emoji-1F1FB-1F1E8 { background-position: -4720px 0px; } -.emoji-1F1FB-1F1EA { background-position: -4740px 0px; } -.emoji-1F1FB-1F1EE { background-position: -4760px 0px; } -.emoji-1F1FB-1F1F3 { background-position: -4780px 0px; } -.emoji-1F1FB-1F1FA { background-position: -4800px 0px; } -.emoji-1F1FC-1F1EB { background-position: -4820px 0px; } -.emoji-1F1FC-1F1F8 { background-position: -4840px 0px; } -.emoji-1F1FD-1F1F0 { background-position: -4860px 0px; } -.emoji-1F1FE-1F1EA { background-position: -4880px 0px; } -.emoji-1F1FF-1F1E6 { background-position: -4900px 0px; } -.emoji-1F1FF-1F1F2 { background-position: -4920px 0px; } -.emoji-1F1FF-1F1FC { background-position: -4940px 0px; } -.emoji-1F201 { background-position: -4960px 0px; } -.emoji-1F202 { background-position: -4980px 0px; } -.emoji-1F21A { background-position: -5000px 0px; } -.emoji-1F22F { background-position: -5020px 0px; } -.emoji-1F232 { background-position: -5040px 0px; } -.emoji-1F233 { background-position: -5060px 0px; } -.emoji-1F234 { background-position: -5080px 0px; } -.emoji-1F235 { background-position: -5100px 0px; } -.emoji-1F236 { background-position: -5120px 0px; } -.emoji-1F237 { background-position: -5140px 0px; } -.emoji-1F238 { background-position: -5160px 0px; } -.emoji-1F239 { background-position: -5180px 0px; } -.emoji-1F23A { background-position: -5200px 0px; } -.emoji-1F250 { background-position: -5220px 0px; } -.emoji-1F251 { background-position: -5240px 0px; } -.emoji-1F300 { background-position: -5260px 0px; } -.emoji-1F301 { background-position: -5280px 0px; } -.emoji-1F302 { background-position: -5300px 0px; } -.emoji-1F303 { background-position: -5320px 0px; } -.emoji-1F304 { background-position: -5340px 0px; } -.emoji-1F305 { background-position: -5360px 0px; } -.emoji-1F306 { background-position: -5380px 0px; } -.emoji-1F307 { background-position: -5400px 0px; } -.emoji-1F308 { background-position: -5420px 0px; } -.emoji-1F309 { background-position: -5440px 0px; } -.emoji-1F30A { background-position: -5460px 0px; } -.emoji-1F30B { background-position: -5480px 0px; } -.emoji-1F30C { background-position: -5500px 0px; } -.emoji-1F30D { background-position: -5520px 0px; } -.emoji-1F30E { background-position: -5540px 0px; } -.emoji-1F30F { background-position: -5560px 0px; } -.emoji-1F310 { background-position: -5580px 0px; } -.emoji-1F311 { background-position: -5600px 0px; } -.emoji-1F312 { background-position: -5620px 0px; } -.emoji-1F313 { background-position: -5640px 0px; } -.emoji-1F314 { background-position: -5660px 0px; } -.emoji-1F315 { background-position: -5680px 0px; } -.emoji-1F316 { background-position: -5700px 0px; } -.emoji-1F317 { background-position: -5720px 0px; } -.emoji-1F318 { background-position: -5740px 0px; } -.emoji-1F319 { background-position: -5760px 0px; } -.emoji-1F31A { background-position: -5780px 0px; } -.emoji-1F31B { background-position: -5800px 0px; } -.emoji-1F31C { background-position: -5820px 0px; } -.emoji-1F31D { background-position: -5840px 0px; } -.emoji-1F31E { background-position: -5860px 0px; } -.emoji-1F31F { background-position: -5880px 0px; } -.emoji-1F320 { background-position: -5900px 0px; } -.emoji-1F321 { background-position: -5920px 0px; } -.emoji-1F327 { background-position: -5940px 0px; } -.emoji-1F328 { background-position: -5960px 0px; } -.emoji-1F329 { background-position: -5980px 0px; } -.emoji-1F32A { background-position: -6000px 0px; } -.emoji-1F32B { background-position: -6020px 0px; } -.emoji-1F32C { background-position: -6040px 0px; } -.emoji-1F330 { background-position: -6060px 0px; } -.emoji-1F331 { background-position: -6080px 0px; } -.emoji-1F332 { background-position: -6100px 0px; } -.emoji-1F333 { background-position: -6120px 0px; } -.emoji-1F334 { background-position: -6140px 0px; } -.emoji-1F335 { background-position: -6160px 0px; } -.emoji-1F336 { background-position: -6180px 0px; } -.emoji-1F337 { background-position: -6200px 0px; } -.emoji-1F338 { background-position: -6220px 0px; } -.emoji-1F339 { background-position: -6240px 0px; } -.emoji-1F33A { background-position: -6260px 0px; } -.emoji-1F33B { background-position: -6280px 0px; } -.emoji-1F33C { background-position: -6300px 0px; } -.emoji-1F33D { background-position: -6320px 0px; } -.emoji-1F33E { background-position: -6340px 0px; } -.emoji-1F33F { background-position: -6360px 0px; } -.emoji-1F340 { background-position: -6380px 0px; } -.emoji-1F341 { background-position: -6400px 0px; } -.emoji-1F342 { background-position: -6420px 0px; } -.emoji-1F343 { background-position: -6440px 0px; } -.emoji-1F344 { background-position: -6460px 0px; } -.emoji-1F345 { background-position: -6480px 0px; } -.emoji-1F346 { background-position: -6500px 0px; } -.emoji-1F347 { background-position: -6520px 0px; } -.emoji-1F348 { background-position: -6540px 0px; } -.emoji-1F349 { background-position: -6560px 0px; } -.emoji-1F34A { background-position: -6580px 0px; } -.emoji-1F34B { background-position: -6600px 0px; } -.emoji-1F34C { background-position: -6620px 0px; } -.emoji-1F34D { background-position: -6640px 0px; } -.emoji-1F34E { background-position: -6660px 0px; } -.emoji-1F34F { background-position: -6680px 0px; } -.emoji-1F350 { background-position: -6700px 0px; } -.emoji-1F351 { background-position: -6720px 0px; } -.emoji-1F352 { background-position: -6740px 0px; } -.emoji-1F353 { background-position: -6760px 0px; } -.emoji-1F354 { background-position: -6780px 0px; } -.emoji-1F355 { background-position: -6800px 0px; } -.emoji-1F356 { background-position: -6820px 0px; } -.emoji-1F357 { background-position: -6840px 0px; } -.emoji-1F358 { background-position: -6860px 0px; } -.emoji-1F359 { background-position: -6880px 0px; } -.emoji-1F35A { background-position: -6900px 0px; } -.emoji-1F35B { background-position: -6920px 0px; } -.emoji-1F35C { background-position: -6940px 0px; } -.emoji-1F35D { background-position: -6960px 0px; } -.emoji-1F35E { background-position: -6980px 0px; } -.emoji-1F35F { background-position: -7000px 0px; } -.emoji-1F360 { background-position: -7020px 0px; } -.emoji-1F361 { background-position: -7040px 0px; } -.emoji-1F362 { background-position: -7060px 0px; } -.emoji-1F363 { background-position: -7080px 0px; } -.emoji-1F364 { background-position: -7100px 0px; } -.emoji-1F365 { background-position: -7120px 0px; } -.emoji-1F366 { background-position: -7140px 0px; } -.emoji-1F367 { background-position: -7160px 0px; } -.emoji-1F368 { background-position: -7180px 0px; } -.emoji-1F369 { background-position: -7200px 0px; } -.emoji-1F36A { background-position: -7220px 0px; } -.emoji-1F36B { background-position: -7240px 0px; } -.emoji-1F36C { background-position: -7260px 0px; } -.emoji-1F36D { background-position: -7280px 0px; } -.emoji-1F36E { background-position: -7300px 0px; } -.emoji-1F36F { background-position: -7320px 0px; } -.emoji-1F370 { background-position: -7340px 0px; } -.emoji-1F371 { background-position: -7360px 0px; } -.emoji-1F372 { background-position: -7380px 0px; } -.emoji-1F373 { background-position: -7400px 0px; } -.emoji-1F374 { background-position: -7420px 0px; } -.emoji-1F375 { background-position: -7440px 0px; } -.emoji-1F376 { background-position: -7460px 0px; } -.emoji-1F377 { background-position: -7480px 0px; } -.emoji-1F378 { background-position: -7500px 0px; } -.emoji-1F379 { background-position: -7520px 0px; } -.emoji-1F37A { background-position: -7540px 0px; } -.emoji-1F37B { background-position: -7560px 0px; } -.emoji-1F37C { background-position: -7580px 0px; } -.emoji-1F37D { background-position: -7600px 0px; } -.emoji-1F380 { background-position: -7620px 0px; } -.emoji-1F381 { background-position: -7640px 0px; } -.emoji-1F382 { background-position: -7660px 0px; } -.emoji-1F383 { background-position: -7680px 0px; } -.emoji-1F384 { background-position: -7700px 0px; } -.emoji-1F385 { background-position: -7720px 0px; } -.emoji-1F386 { background-position: -7740px 0px; } -.emoji-1F387 { background-position: -7760px 0px; } -.emoji-1F388 { background-position: -7780px 0px; } -.emoji-1F389 { background-position: -7800px 0px; } -.emoji-1F38A { background-position: -7820px 0px; } -.emoji-1F38B { background-position: -7840px 0px; } -.emoji-1F38C { background-position: -7860px 0px; } -.emoji-1F38D { background-position: -7880px 0px; } -.emoji-1F38E { background-position: -7900px 0px; } -.emoji-1F38F { background-position: -7920px 0px; } -.emoji-1F390 { background-position: -7940px 0px; } -.emoji-1F391 { background-position: -7960px 0px; } -.emoji-1F392 { background-position: -7980px 0px; } -.emoji-1F393 { background-position: -8000px 0px; } -.emoji-1F394 { background-position: -8020px 0px; } -.emoji-1F395 { background-position: -8040px 0px; } -.emoji-1F396 { background-position: -8060px 0px; } -.emoji-1F397 { background-position: -8080px 0px; } -.emoji-1F398 { background-position: -8100px 0px; } -.emoji-1F399 { background-position: -8120px 0px; } -.emoji-1F39A { background-position: -8140px 0px; } -.emoji-1F39B { background-position: -8160px 0px; } -.emoji-1F39C { background-position: -8180px 0px; } -.emoji-1F39D { background-position: -8200px 0px; } -.emoji-1F39E { background-position: -8220px 0px; } -.emoji-1F39F { background-position: -8240px 0px; } -.emoji-1F3A0 { background-position: -8260px 0px; } -.emoji-1F3A1 { background-position: -8280px 0px; } -.emoji-1F3A2 { background-position: -8300px 0px; } -.emoji-1F3A3 { background-position: -8320px 0px; } -.emoji-1F3A4 { background-position: -8340px 0px; } -.emoji-1F3A5 { background-position: -8360px 0px; } -.emoji-1F3A6 { background-position: -8380px 0px; } -.emoji-1F3A7 { background-position: -8400px 0px; } -.emoji-1F3A8 { background-position: -8420px 0px; } -.emoji-1F3A9 { background-position: -8440px 0px; } -.emoji-1F3AA { background-position: -8460px 0px; } -.emoji-1F3AB { background-position: -8480px 0px; } -.emoji-1F3AC { background-position: -8500px 0px; } -.emoji-1F3AD { background-position: -8520px 0px; } -.emoji-1F3AE { background-position: -8540px 0px; } -.emoji-1F3AF { background-position: -8560px 0px; } -.emoji-1F3B0 { background-position: -8580px 0px; } -.emoji-1F3B1 { background-position: -8600px 0px; } -.emoji-1F3B2 { background-position: -8620px 0px; } -.emoji-1F3B3 { background-position: -8640px 0px; } -.emoji-1F3B4 { background-position: -8660px 0px; } -.emoji-1F3B5 { background-position: -8680px 0px; } -.emoji-1F3B6 { background-position: -8700px 0px; } -.emoji-1F3B7 { background-position: -8720px 0px; } -.emoji-1F3B8 { background-position: -8740px 0px; } -.emoji-1F3B9 { background-position: -8760px 0px; } -.emoji-1F3BA { background-position: -8780px 0px; } -.emoji-1F3BB { background-position: -8800px 0px; } -.emoji-1F3BC { background-position: -8820px 0px; } -.emoji-1F3BD { background-position: -8840px 0px; } -.emoji-1F3BE { background-position: -8860px 0px; } -.emoji-1F3BF { background-position: -8880px 0px; } -.emoji-1F3C0 { background-position: -8900px 0px; } -.emoji-1F3C1 { background-position: -8920px 0px; } -.emoji-1F3C2 { background-position: -8940px 0px; } -.emoji-1F3C3 { background-position: -8960px 0px; } -.emoji-1F3C4 { background-position: -8980px 0px; } -.emoji-1F3C5 { background-position: -9000px 0px; } -.emoji-1F3C6 { background-position: -9020px 0px; } -.emoji-1F3C7 { background-position: -9040px 0px; } -.emoji-1F3C8 { background-position: -9060px 0px; } -.emoji-1F3C9 { background-position: -9080px 0px; } -.emoji-1F3CA { background-position: -9100px 0px; } -.emoji-1F3CB { background-position: -9120px 0px; } -.emoji-1F3CC { background-position: -9140px 0px; } -.emoji-1F3CD { background-position: -9160px 0px; } -.emoji-1F3CE { background-position: -9180px 0px; } -.emoji-1F3D4 { background-position: -9200px 0px; } -.emoji-1F3D5 { background-position: -9220px 0px; } -.emoji-1F3D6 { background-position: -9240px 0px; } -.emoji-1F3D7 { background-position: -9260px 0px; } -.emoji-1F3D8 { background-position: -9280px 0px; } -.emoji-1F3D9 { background-position: -9300px 0px; } -.emoji-1F3DA { background-position: -9320px 0px; } -.emoji-1F3DB { background-position: -9340px 0px; } -.emoji-1F3DC { background-position: -9360px 0px; } -.emoji-1F3DD { background-position: -9380px 0px; } -.emoji-1F3DE { background-position: -9400px 0px; } -.emoji-1F3DF { background-position: -9420px 0px; } -.emoji-1F3E0 { background-position: -9440px 0px; } -.emoji-1F3E1 { background-position: -9460px 0px; } -.emoji-1F3E2 { background-position: -9480px 0px; } -.emoji-1F3E3 { background-position: -9500px 0px; } -.emoji-1F3E4 { background-position: -9520px 0px; } -.emoji-1F3E5 { background-position: -9540px 0px; } -.emoji-1F3E6 { background-position: -9560px 0px; } -.emoji-1F3E7 { background-position: -9580px 0px; } -.emoji-1F3E8 { background-position: -9600px 0px; } -.emoji-1F3E9 { background-position: -9620px 0px; } -.emoji-1F3EA { background-position: -9640px 0px; } -.emoji-1F3EB { background-position: -9660px 0px; } -.emoji-1F3EC { background-position: -9680px 0px; } -.emoji-1F3ED { background-position: -9700px 0px; } -.emoji-1F3EE { background-position: -9720px 0px; } -.emoji-1F3EF { background-position: -9740px 0px; } -.emoji-1F3F0 { background-position: -9760px 0px; } -.emoji-1F3F1 { background-position: -9780px 0px; } -.emoji-1F3F2 { background-position: -9800px 0px; } -.emoji-1F3F3 { background-position: -9820px 0px; } -.emoji-1F3F4 { background-position: -9840px 0px; } -.emoji-1F3F5 { background-position: -9860px 0px; } -.emoji-1F3F6 { background-position: -9880px 0px; } -.emoji-1F3F7 { background-position: -9900px 0px; } -.emoji-1F400 { background-position: -9920px 0px; } -.emoji-1F401 { background-position: -9940px 0px; } -.emoji-1F402 { background-position: -9960px 0px; } -.emoji-1F403 { background-position: -9980px 0px; } -.emoji-1F404 { background-position: -10000px 0px; } -.emoji-1F405 { background-position: -10020px 0px; } -.emoji-1F406 { background-position: -10040px 0px; } -.emoji-1F407 { background-position: -10060px 0px; } -.emoji-1F408 { background-position: -10080px 0px; } -.emoji-1F409 { background-position: -10100px 0px; } -.emoji-1F40A { background-position: -10120px 0px; } -.emoji-1F40B { background-position: -10140px 0px; } -.emoji-1F40C { background-position: -10160px 0px; } -.emoji-1F40D { background-position: -10180px 0px; } -.emoji-1F40E { background-position: -10200px 0px; } -.emoji-1F40F { background-position: -10220px 0px; } -.emoji-1F410 { background-position: -10240px 0px; } -.emoji-1F411 { background-position: -10260px 0px; } -.emoji-1F412 { background-position: -10280px 0px; } -.emoji-1F413 { background-position: -10300px 0px; } -.emoji-1F414 { background-position: -10320px 0px; } -.emoji-1F415 { background-position: -10340px 0px; } -.emoji-1F416 { background-position: -10360px 0px; } -.emoji-1F417 { background-position: -10380px 0px; } -.emoji-1F418 { background-position: -10400px 0px; } -.emoji-1F419 { background-position: -10420px 0px; } -.emoji-1F41A { background-position: -10440px 0px; } -.emoji-1F41B { background-position: -10460px 0px; } -.emoji-1F41C { background-position: -10480px 0px; } -.emoji-1F41D { background-position: -10500px 0px; } -.emoji-1F41E { background-position: -10520px 0px; } -.emoji-1F41F { background-position: -10540px 0px; } -.emoji-1F420 { background-position: -10560px 0px; } -.emoji-1F421 { background-position: -10580px 0px; } -.emoji-1F422 { background-position: -10600px 0px; } -.emoji-1F423 { background-position: -10620px 0px; } -.emoji-1F424 { background-position: -10640px 0px; } -.emoji-1F425 { background-position: -10660px 0px; } -.emoji-1F426 { background-position: -10680px 0px; } -.emoji-1F427 { background-position: -10700px 0px; } -.emoji-1F428 { background-position: -10720px 0px; } -.emoji-1F429 { background-position: -10740px 0px; } -.emoji-1F42A { background-position: -10760px 0px; } -.emoji-1F42B { background-position: -10780px 0px; } -.emoji-1F42C { background-position: -10800px 0px; } -.emoji-1F42D { background-position: -10820px 0px; } -.emoji-1F42E { background-position: -10840px 0px; } -.emoji-1F42F { background-position: -10860px 0px; } -.emoji-1F430 { background-position: -10880px 0px; } -.emoji-1F431 { background-position: -10900px 0px; } -.emoji-1F432 { background-position: -10920px 0px; } -.emoji-1F433 { background-position: -10940px 0px; } -.emoji-1F434 { background-position: -10960px 0px; } -.emoji-1F435 { background-position: -10980px 0px; } -.emoji-1F436 { background-position: -11000px 0px; } -.emoji-1F437 { background-position: -11020px 0px; } -.emoji-1F438 { background-position: -11040px 0px; } -.emoji-1F439 { background-position: -11060px 0px; } -.emoji-1F43A { background-position: -11080px 0px; } -.emoji-1F43B { background-position: -11100px 0px; } -.emoji-1F43C { background-position: -11120px 0px; } -.emoji-1F43D { background-position: -11140px 0px; } -.emoji-1F43E { background-position: -11160px 0px; } -.emoji-1F43F { background-position: -11180px 0px; } -.emoji-1F440 { background-position: -11200px 0px; } -.emoji-1F441 { background-position: -11220px 0px; } -.emoji-1F442 { background-position: -11240px 0px; } -.emoji-1F443 { background-position: -11260px 0px; } -.emoji-1F444 { background-position: -11280px 0px; } -.emoji-1F445 { background-position: -11300px 0px; } -.emoji-1F446 { background-position: -11320px 0px; } -.emoji-1F447 { background-position: -11340px 0px; } -.emoji-1F448 { background-position: -11360px 0px; } -.emoji-1F449 { background-position: -11380px 0px; } -.emoji-1F44A { background-position: -11400px 0px; } -.emoji-1F44B { background-position: -11420px 0px; } -.emoji-1F44C { background-position: -11440px 0px; } -.emoji-1F44D { background-position: -11460px 0px; } -.emoji-1F44E { background-position: -11480px 0px; } -.emoji-1F44F { background-position: -11500px 0px; } -.emoji-1F450 { background-position: -11520px 0px; } -.emoji-1F451 { background-position: -11540px 0px; } -.emoji-1F452 { background-position: -11560px 0px; } -.emoji-1F453 { background-position: -11580px 0px; } -.emoji-1F454 { background-position: -11600px 0px; } -.emoji-1F455 { background-position: -11620px 0px; } -.emoji-1F456 { background-position: -11640px 0px; } -.emoji-1F457 { background-position: -11660px 0px; } -.emoji-1F458 { background-position: -11680px 0px; } -.emoji-1F459 { background-position: -11700px 0px; } -.emoji-1F45A { background-position: -11720px 0px; } -.emoji-1F45B { background-position: -11740px 0px; } -.emoji-1F45C { background-position: -11760px 0px; } -.emoji-1F45D { background-position: -11780px 0px; } -.emoji-1F45E { background-position: -11800px 0px; } -.emoji-1F45F { background-position: -11820px 0px; } -.emoji-1F460 { background-position: -11840px 0px; } -.emoji-1F461 { background-position: -11860px 0px; } -.emoji-1F462 { background-position: -11880px 0px; } -.emoji-1F463 { background-position: -11900px 0px; } -.emoji-1F464 { background-position: -11920px 0px; } -.emoji-1F465 { background-position: -11940px 0px; } -.emoji-1F466 { background-position: -11960px 0px; } -.emoji-1F467 { background-position: -11980px 0px; } -.emoji-1F468 { background-position: -12000px 0px; } -.emoji-1F468-1F468-1F466 { background-position: -12020px 0px; } -.emoji-1F468-1F468-1F466-1F466 { background-position: -12040px 0px; } -.emoji-1F468-1F468-1F467 { background-position: -12060px 0px; } -.emoji-1F468-1F468-1F467-1F466 { background-position: -12080px 0px; } -.emoji-1F468-1F468-1F467-1F467 { background-position: -12100px 0px; } -.emoji-1F468-1F469-1F466-1F466 { background-position: -12120px 0px; } -.emoji-1F468-1F469-1F467 { background-position: -12140px 0px; } -.emoji-1F468-1F469-1F467-1F466 { background-position: -12160px 0px; } -.emoji-1F468-1F469-1F467-1F467 { background-position: -12180px 0px; } -.emoji-1F468-2764-1F468 { background-position: -12200px 0px; } -.emoji-1F468-2764-1F48B-1F468 { background-position: -12220px 0px; } -.emoji-1F469 { background-position: -12240px 0px; } -.emoji-1F469-1F469-1F466 { background-position: -12260px 0px; } -.emoji-1F469-1F469-1F466-1F466 { background-position: -12280px 0px; } -.emoji-1F469-1F469-1F467 { background-position: -12300px 0px; } -.emoji-1F469-1F469-1F467-1F466 { background-position: -12320px 0px; } -.emoji-1F469-1F469-1F467-1F467 { background-position: -12340px 0px; } -.emoji-1F469-2764-1F469 { background-position: -12360px 0px; } -.emoji-1F469-2764-1F48B-1F469 { background-position: -12380px 0px; } -.emoji-1F46A { background-position: -12400px 0px; } -.emoji-1F46B { background-position: -12420px 0px; } -.emoji-1F46C { background-position: -12440px 0px; } -.emoji-1F46D { background-position: -12460px 0px; } -.emoji-1F46E { background-position: -12480px 0px; } -.emoji-1F46F { background-position: -12500px 0px; } -.emoji-1F470 { background-position: -12520px 0px; } -.emoji-1F471 { background-position: -12540px 0px; } -.emoji-1F472 { background-position: -12560px 0px; } -.emoji-1F473 { background-position: -12580px 0px; } -.emoji-1F474 { background-position: -12600px 0px; } -.emoji-1F475 { background-position: -12620px 0px; } -.emoji-1F476 { background-position: -12640px 0px; } -.emoji-1F477 { background-position: -12660px 0px; } -.emoji-1F478 { background-position: -12680px 0px; } -.emoji-1F479 { background-position: -12700px 0px; } -.emoji-1F47A { background-position: -12720px 0px; } -.emoji-1F47B { background-position: -12740px 0px; } -.emoji-1F47C { background-position: -12760px 0px; } -.emoji-1F47D { background-position: -12780px 0px; } -.emoji-1F47E { background-position: -12800px 0px; } -.emoji-1F47F { background-position: -12820px 0px; } -.emoji-1F480 { background-position: -12840px 0px; } -.emoji-1F481 { background-position: -12860px 0px; } -.emoji-1F482 { background-position: -12880px 0px; } -.emoji-1F483 { background-position: -12900px 0px; } -.emoji-1F484 { background-position: -12920px 0px; } -.emoji-1F485 { background-position: -12940px 0px; } -.emoji-1F486 { background-position: -12960px 0px; } -.emoji-1F487 { background-position: -12980px 0px; } -.emoji-1F488 { background-position: -13000px 0px; } -.emoji-1F489 { background-position: -13020px 0px; } -.emoji-1F48A { background-position: -13040px 0px; } -.emoji-1F48B { background-position: -13060px 0px; } -.emoji-1F48C { background-position: -13080px 0px; } -.emoji-1F48D { background-position: -13100px 0px; } -.emoji-1F48E { background-position: -13120px 0px; } -.emoji-1F48F { background-position: -13140px 0px; } -.emoji-1F490 { background-position: -13160px 0px; } -.emoji-1F491 { background-position: -13180px 0px; } -.emoji-1F492 { background-position: -13200px 0px; } -.emoji-1F493 { background-position: -13220px 0px; } -.emoji-1F494 { background-position: -13240px 0px; } -.emoji-1F495 { background-position: -13260px 0px; } -.emoji-1F496 { background-position: -13280px 0px; } -.emoji-1F497 { background-position: -13300px 0px; } -.emoji-1F498 { background-position: -13320px 0px; } -.emoji-1F499 { background-position: -13340px 0px; } -.emoji-1F49A { background-position: -13360px 0px; } -.emoji-1F49B { background-position: -13380px 0px; } -.emoji-1F49C { background-position: -13400px 0px; } -.emoji-1F49D { background-position: -13420px 0px; } -.emoji-1F49E { background-position: -13440px 0px; } -.emoji-1F49F { background-position: -13460px 0px; } -.emoji-1F4A0 { background-position: -13480px 0px; } -.emoji-1F4A1 { background-position: -13500px 0px; } -.emoji-1F4A2 { background-position: -13520px 0px; } -.emoji-1F4A3 { background-position: -13540px 0px; } -.emoji-1F4A4 { background-position: -13560px 0px; } -.emoji-1F4A5 { background-position: -13580px 0px; } -.emoji-1F4A6 { background-position: -13600px 0px; } -.emoji-1F4A7 { background-position: -13620px 0px; } -.emoji-1F4A8 { background-position: -13640px 0px; } -.emoji-1F4A9 { background-position: -13660px 0px; } -.emoji-1F4AA { background-position: -13680px 0px; } -.emoji-1F4AB { background-position: -13700px 0px; } -.emoji-1F4AC { background-position: -13720px 0px; } -.emoji-1F4AD { background-position: -13740px 0px; } -.emoji-1F4AE { background-position: -13760px 0px; } -.emoji-1F4AF { background-position: -13780px 0px; } -.emoji-1F4B0 { background-position: -13800px 0px; } -.emoji-1F4B1 { background-position: -13820px 0px; } -.emoji-1F4B2 { background-position: -13840px 0px; } -.emoji-1F4B3 { background-position: -13860px 0px; } -.emoji-1F4B4 { background-position: -13880px 0px; } -.emoji-1F4B5 { background-position: -13900px 0px; } -.emoji-1F4B6 { background-position: -13920px 0px; } -.emoji-1F4B7 { background-position: -13940px 0px; } -.emoji-1F4B8 { background-position: -13960px 0px; } -.emoji-1F4B9 { background-position: -13980px 0px; } -.emoji-1F4BA { background-position: -14000px 0px; } -.emoji-1F4BB { background-position: -14020px 0px; } -.emoji-1F4BC { background-position: -14040px 0px; } -.emoji-1F4BD { background-position: -14060px 0px; } -.emoji-1F4BE { background-position: -14080px 0px; } -.emoji-1F4BF { background-position: -14100px 0px; } -.emoji-1F4C0 { background-position: -14120px 0px; } -.emoji-1F4C1 { background-position: -14140px 0px; } -.emoji-1F4C2 { background-position: -14160px 0px; } -.emoji-1F4C3 { background-position: -14180px 0px; } -.emoji-1F4C4 { background-position: -14200px 0px; } -.emoji-1F4C5 { background-position: -14220px 0px; } -.emoji-1F4C6 { background-position: -14240px 0px; } -.emoji-1F4C7 { background-position: -14260px 0px; } -.emoji-1F4C8 { background-position: -14280px 0px; } -.emoji-1F4C9 { background-position: -14300px 0px; } -.emoji-1F4CA { background-position: -14320px 0px; } -.emoji-1F4CB { background-position: -14340px 0px; } -.emoji-1F4CC { background-position: -14360px 0px; } -.emoji-1F4CD { background-position: -14380px 0px; } -.emoji-1F4CE { background-position: -14400px 0px; } -.emoji-1F4CF { background-position: -14420px 0px; } -.emoji-1F4D0 { background-position: -14440px 0px; } -.emoji-1F4D1 { background-position: -14460px 0px; } -.emoji-1F4D2 { background-position: -14480px 0px; } -.emoji-1F4D3 { background-position: -14500px 0px; } -.emoji-1F4D4 { background-position: -14520px 0px; } -.emoji-1F4D5 { background-position: -14540px 0px; } -.emoji-1F4D6 { background-position: -14560px 0px; } -.emoji-1F4D7 { background-position: -14580px 0px; } -.emoji-1F4D8 { background-position: -14600px 0px; } -.emoji-1F4D9 { background-position: -14620px 0px; } -.emoji-1F4DA { background-position: -14640px 0px; } -.emoji-1F4DB { background-position: -14660px 0px; } -.emoji-1F4DC { background-position: -14680px 0px; } -.emoji-1F4DD { background-position: -14700px 0px; } -.emoji-1F4DE { background-position: -14720px 0px; } -.emoji-1F4DF { background-position: -14740px 0px; } -.emoji-1F4E0 { background-position: -14760px 0px; } -.emoji-1F4E1 { background-position: -14780px 0px; } -.emoji-1F4E2 { background-position: -14800px 0px; } -.emoji-1F4E3 { background-position: -14820px 0px; } -.emoji-1F4E4 { background-position: -14840px 0px; } -.emoji-1F4E5 { background-position: -14860px 0px; } -.emoji-1F4E6 { background-position: -14880px 0px; } -.emoji-1F4E7 { background-position: -14900px 0px; } -.emoji-1F4E8 { background-position: -14920px 0px; } -.emoji-1F4E9 { background-position: -14940px 0px; } -.emoji-1F4EA { background-position: -14960px 0px; } -.emoji-1F4EB { background-position: -14980px 0px; } -.emoji-1F4EC { background-position: -15000px 0px; } -.emoji-1F4ED { background-position: -15020px 0px; } -.emoji-1F4EE { background-position: -15040px 0px; } -.emoji-1F4EF { background-position: -15060px 0px; } -.emoji-1F4F0 { background-position: -15080px 0px; } -.emoji-1F4F1 { background-position: -15100px 0px; } -.emoji-1F4F2 { background-position: -15120px 0px; } -.emoji-1F4F3 { background-position: -15140px 0px; } -.emoji-1F4F4 { background-position: -15160px 0px; } -.emoji-1F4F5 { background-position: -15180px 0px; } -.emoji-1F4F6 { background-position: -15200px 0px; } -.emoji-1F4F7 { background-position: -15220px 0px; } -.emoji-1F4F8 { background-position: -15240px 0px; } -.emoji-1F4F9 { background-position: -15260px 0px; } -.emoji-1F4FA { background-position: -15280px 0px; } -.emoji-1F4FB { background-position: -15300px 0px; } -.emoji-1F4FC { background-position: -15320px 0px; } -.emoji-1F4FD { background-position: -15340px 0px; } -.emoji-1F4FE { background-position: -15360px 0px; } -.emoji-1F500 { background-position: -15380px 0px; } -.emoji-1F501 { background-position: -15400px 0px; } -.emoji-1F502 { background-position: -15420px 0px; } -.emoji-1F503 { background-position: -15440px 0px; } -.emoji-1F504 { background-position: -15460px 0px; } -.emoji-1F505 { background-position: -15480px 0px; } -.emoji-1F506 { background-position: -15500px 0px; } -.emoji-1F507 { background-position: -15520px 0px; } -.emoji-1F508 { background-position: -15540px 0px; } -.emoji-1F509 { background-position: -15560px 0px; } -.emoji-1F50A { background-position: -15580px 0px; } -.emoji-1F50B { background-position: -15600px 0px; } -.emoji-1F50C { background-position: -15620px 0px; } -.emoji-1F50D { background-position: -15640px 0px; } -.emoji-1F50E { background-position: -15660px 0px; } -.emoji-1F50F { background-position: -15680px 0px; } -.emoji-1F510 { background-position: -15700px 0px; } -.emoji-1F511 { background-position: -15720px 0px; } -.emoji-1F512 { background-position: -15740px 0px; } -.emoji-1F513 { background-position: -15760px 0px; } -.emoji-1F514 { background-position: -15780px 0px; } -.emoji-1F515 { background-position: -15800px 0px; } -.emoji-1F516 { background-position: -15820px 0px; } -.emoji-1F517 { background-position: -15840px 0px; } -.emoji-1F518 { background-position: -15860px 0px; } -.emoji-1F519 { background-position: -15880px 0px; } -.emoji-1F51A { background-position: -15900px 0px; } -.emoji-1F51B { background-position: -15920px 0px; } -.emoji-1F51C { background-position: -15940px 0px; } -.emoji-1F51D { background-position: -15960px 0px; } -.emoji-1F51E { background-position: -15980px 0px; } -.emoji-1F51F { background-position: -16000px 0px; } -.emoji-1F520 { background-position: -16020px 0px; } -.emoji-1F521 { background-position: -16040px 0px; } -.emoji-1F522 { background-position: -16060px 0px; } -.emoji-1F523 { background-position: -16080px 0px; } -.emoji-1F524 { background-position: -16100px 0px; } -.emoji-1F525 { background-position: -16120px 0px; } -.emoji-1F526 { background-position: -16140px 0px; } -.emoji-1F527 { background-position: -16160px 0px; } -.emoji-1F528 { background-position: -16180px 0px; } -.emoji-1F529 { background-position: -16200px 0px; } -.emoji-1F52A { background-position: -16220px 0px; } -.emoji-1F52B { background-position: -16240px 0px; } -.emoji-1F52C { background-position: -16260px 0px; } -.emoji-1F52D { background-position: -16280px 0px; } -.emoji-1F52E { background-position: -16300px 0px; } -.emoji-1F52F { background-position: -16320px 0px; } -.emoji-1F530 { background-position: -16340px 0px; } -.emoji-1F531 { background-position: -16360px 0px; } -.emoji-1F532 { background-position: -16380px 0px; } -.emoji-1F533 { background-position: -16400px 0px; } -.emoji-1F534 { background-position: -16420px 0px; } -.emoji-1F535 { background-position: -16440px 0px; } -.emoji-1F536 { background-position: -16460px 0px; } -.emoji-1F537 { background-position: -16480px 0px; } -.emoji-1F538 { background-position: -16500px 0px; } -.emoji-1F539 { background-position: -16520px 0px; } -.emoji-1F53A { background-position: -16540px 0px; } -.emoji-1F53B { background-position: -16560px 0px; } -.emoji-1F53C { background-position: -16580px 0px; } -.emoji-1F53D { background-position: -16600px 0px; } -.emoji-1F546 { background-position: -16620px 0px; } -.emoji-1F547 { background-position: -16640px 0px; } -.emoji-1F548 { background-position: -16660px 0px; } -.emoji-1F549 { background-position: -16680px 0px; } -.emoji-1F54A { background-position: -16700px 0px; } -.emoji-1F550 { background-position: -16720px 0px; } -.emoji-1F551 { background-position: -16740px 0px; } -.emoji-1F552 { background-position: -16760px 0px; } -.emoji-1F553 { background-position: -16780px 0px; } -.emoji-1F554 { background-position: -16800px 0px; } -.emoji-1F555 { background-position: -16820px 0px; } -.emoji-1F556 { background-position: -16840px 0px; } -.emoji-1F557 { background-position: -16860px 0px; } -.emoji-1F558 { background-position: -16880px 0px; } -.emoji-1F559 { background-position: -16900px 0px; } -.emoji-1F55A { background-position: -16920px 0px; } -.emoji-1F55B { background-position: -16940px 0px; } -.emoji-1F55C { background-position: -16960px 0px; } -.emoji-1F55D { background-position: -16980px 0px; } -.emoji-1F55E { background-position: -17000px 0px; } -.emoji-1F55F { background-position: -17020px 0px; } -.emoji-1F560 { background-position: -17040px 0px; } -.emoji-1F561 { background-position: -17060px 0px; } -.emoji-1F562 { background-position: -17080px 0px; } -.emoji-1F563 { background-position: -17100px 0px; } -.emoji-1F564 { background-position: -17120px 0px; } -.emoji-1F565 { background-position: -17140px 0px; } -.emoji-1F566 { background-position: -17160px 0px; } -.emoji-1F567 { background-position: -17180px 0px; } -.emoji-1F568 { background-position: -17200px 0px; } -.emoji-1F569 { background-position: -17220px 0px; } -.emoji-1F56A { background-position: -17240px 0px; } -.emoji-1F56B { background-position: -17260px 0px; } -.emoji-1F56C { background-position: -17280px 0px; } -.emoji-1F56D { background-position: -17300px 0px; } -.emoji-1F56E { background-position: -17320px 0px; } -.emoji-1F56F { background-position: -17340px 0px; } -.emoji-1F570 { background-position: -17360px 0px; } -.emoji-1F571 { background-position: -17380px 0px; } -.emoji-1F572 { background-position: -17400px 0px; } -.emoji-1F573 { background-position: -17420px 0px; } -.emoji-1F574 { background-position: -17440px 0px; } -.emoji-1F575 { background-position: -17460px 0px; } -.emoji-1F576 { background-position: -17480px 0px; } -.emoji-1F577 { background-position: -17500px 0px; } -.emoji-1F578 { background-position: -17520px 0px; } -.emoji-1F579 { background-position: -17540px 0px; } -.emoji-1F57B { background-position: -17560px 0px; } -.emoji-1F57E { background-position: -17580px 0px; } -.emoji-1F57F { background-position: -17600px 0px; } -.emoji-1F581 { background-position: -17620px 0px; } -.emoji-1F582 { background-position: -17640px 0px; } -.emoji-1F583 { background-position: -17660px 0px; } -.emoji-1F585 { background-position: -17680px 0px; } -.emoji-1F586 { background-position: -17700px 0px; } -.emoji-1F587 { background-position: -17720px 0px; } -.emoji-1F588 { background-position: -17740px 0px; } -.emoji-1F589 { background-position: -17760px 0px; } -.emoji-1F58A { background-position: -17780px 0px; } -.emoji-1F58B { background-position: -17800px 0px; } -.emoji-1F58C { background-position: -17820px 0px; } -.emoji-1F58D { background-position: -17840px 0px; } -.emoji-1F58E { background-position: -17860px 0px; } -.emoji-1F58F { background-position: -17880px 0px; } -.emoji-1F590 { background-position: -17900px 0px; } -.emoji-1F591 { background-position: -17920px 0px; } -.emoji-1F592 { background-position: -17940px 0px; } -.emoji-1F593 { background-position: -17960px 0px; } -.emoji-1F594 { background-position: -17980px 0px; } -.emoji-1F595 { background-position: -18000px 0px; } -.emoji-1F596 { background-position: -18020px 0px; } -.emoji-1F597 { background-position: -18040px 0px; } -.emoji-1F598 { background-position: -18060px 0px; } -.emoji-1F599 { background-position: -18080px 0px; } -.emoji-1F59E { background-position: -18100px 0px; } -.emoji-1F59F { background-position: -18120px 0px; } -.emoji-1F5A5 { background-position: -18140px 0px; } -.emoji-1F5A6 { background-position: -18160px 0px; } -.emoji-1F5A7 { background-position: -18180px 0px; } -.emoji-1F5A8 { background-position: -18200px 0px; } -.emoji-1F5A9 { background-position: -18220px 0px; } -.emoji-1F5AA { background-position: -18240px 0px; } -.emoji-1F5AB { background-position: -18260px 0px; } -.emoji-1F5AD { background-position: -18280px 0px; } -.emoji-1F5AE { background-position: -18300px 0px; } -.emoji-1F5AF { background-position: -18320px 0px; } -.emoji-1F5B2 { background-position: -18340px 0px; } -.emoji-1F5B3 { background-position: -18360px 0px; } -.emoji-1F5B4 { background-position: -18380px 0px; } -.emoji-1F5B8 { background-position: -18400px 0px; } -.emoji-1F5B9 { background-position: -18420px 0px; } -.emoji-1F5BC { background-position: -18440px 0px; } -.emoji-1F5BD { background-position: -18460px 0px; } -.emoji-1F5BE { background-position: -18480px 0px; } -.emoji-1F5C0 { background-position: -18500px 0px; } -.emoji-1F5C1 { background-position: -18520px 0px; } -.emoji-1F5C2 { background-position: -18540px 0px; } -.emoji-1F5C3 { background-position: -18560px 0px; } -.emoji-1F5C4 { background-position: -18580px 0px; } -.emoji-1F5C6 { background-position: -18600px 0px; } -.emoji-1F5C7 { background-position: -18620px 0px; } -.emoji-1F5C9 { background-position: -18640px 0px; } -.emoji-1F5CA { background-position: -18660px 0px; } -.emoji-1F5CE { background-position: -18680px 0px; } -.emoji-1F5CF { background-position: -18700px 0px; } -.emoji-1F5D0 { background-position: -18720px 0px; } -.emoji-1F5D1 { background-position: -18740px 0px; } -.emoji-1F5D2 { background-position: -18760px 0px; } -.emoji-1F5D3 { background-position: -18780px 0px; } -.emoji-1F5D4 { background-position: -18800px 0px; } -.emoji-1F5D8 { background-position: -18820px 0px; } -.emoji-1F5D9 { background-position: -18840px 0px; } -.emoji-1F5DC { background-position: -18860px 0px; } -.emoji-1F5DD { background-position: -18880px 0px; } -.emoji-1F5DE { background-position: -18900px 0px; } -.emoji-1F5E0 { background-position: -18920px 0px; } -.emoji-1F5E1 { background-position: -18940px 0px; } -.emoji-1F5E2 { background-position: -18960px 0px; } -.emoji-1F5E3 { background-position: -18980px 0px; } -.emoji-1F5E8 { background-position: -19000px 0px; } -.emoji-1F5E9 { background-position: -19020px 0px; } -.emoji-1F5EA { background-position: -19040px 0px; } -.emoji-1F5EB { background-position: -19060px 0px; } -.emoji-1F5EC { background-position: -19080px 0px; } -.emoji-1F5ED { background-position: -19100px 0px; } -.emoji-1F5EE { background-position: -19120px 0px; } -.emoji-1F5EF { background-position: -19140px 0px; } -.emoji-1F5F0 { background-position: -19160px 0px; } -.emoji-1F5F1 { background-position: -19180px 0px; } -.emoji-1F5F2 { background-position: -19200px 0px; } -.emoji-1F5F3 { background-position: -19220px 0px; } -.emoji-1F5F4 { background-position: -19240px 0px; } -.emoji-1F5F5 { background-position: -19260px 0px; } -.emoji-1F5F8 { background-position: -19280px 0px; } -.emoji-1F5F9 { background-position: -19300px 0px; } -.emoji-1F5FA { background-position: -19320px 0px; } -.emoji-1F5FB { background-position: -19340px 0px; } -.emoji-1F5FC { background-position: -19360px 0px; } -.emoji-1F5FD { background-position: -19380px 0px; } -.emoji-1F5FE { background-position: -19400px 0px; } -.emoji-1F5FF { background-position: -19420px 0px; } -.emoji-1F600 { background-position: -19440px 0px; } -.emoji-1F601 { background-position: -19460px 0px; } -.emoji-1F602 { background-position: -19480px 0px; } -.emoji-1F603 { background-position: -19500px 0px; } -.emoji-1F604 { background-position: -19520px 0px; } -.emoji-1F605 { background-position: -19540px 0px; } -.emoji-1F606 { background-position: -19560px 0px; } -.emoji-1F607 { background-position: -19580px 0px; } -.emoji-1F608 { background-position: -19600px 0px; } -.emoji-1F609 { background-position: -19620px 0px; } -.emoji-1F60A { background-position: -19640px 0px; } -.emoji-1F60B { background-position: -19660px 0px; } -.emoji-1F60C { background-position: -19680px 0px; } -.emoji-1F60D { background-position: -19700px 0px; } -.emoji-1F60E { background-position: -19720px 0px; } -.emoji-1F60F { background-position: -19740px 0px; } -.emoji-1F610 { background-position: -19760px 0px; } -.emoji-1F611 { background-position: -19780px 0px; } -.emoji-1F612 { background-position: -19800px 0px; } -.emoji-1F613 { background-position: -19820px 0px; } -.emoji-1F614 { background-position: -19840px 0px; } -.emoji-1F615 { background-position: -19860px 0px; } -.emoji-1F616 { background-position: -19880px 0px; } -.emoji-1F617 { background-position: -19900px 0px; } -.emoji-1F618 { background-position: -19920px 0px; } -.emoji-1F619 { background-position: -19940px 0px; } -.emoji-1F61A { background-position: -19960px 0px; } -.emoji-1F61B { background-position: -19980px 0px; } -.emoji-1F61C { background-position: -20000px 0px; } -.emoji-1F61D { background-position: -20020px 0px; } -.emoji-1F61E { background-position: -20040px 0px; } -.emoji-1F61F { background-position: -20060px 0px; } -.emoji-1F620 { background-position: -20080px 0px; } -.emoji-1F621 { background-position: -20100px 0px; } -.emoji-1F622 { background-position: -20120px 0px; } -.emoji-1F623 { background-position: -20140px 0px; } -.emoji-1F624 { background-position: -20160px 0px; } -.emoji-1F625 { background-position: -20180px 0px; } -.emoji-1F626 { background-position: -20200px 0px; } -.emoji-1F627 { background-position: -20220px 0px; } -.emoji-1F628 { background-position: -20240px 0px; } -.emoji-1F629 { background-position: -20260px 0px; } -.emoji-1F62A { background-position: -20280px 0px; } -.emoji-1F62B { background-position: -20300px 0px; } -.emoji-1F62C { background-position: -20320px 0px; } -.emoji-1F62D { background-position: -20340px 0px; } -.emoji-1F62E { background-position: -20360px 0px; } -.emoji-1F62F { background-position: -20380px 0px; } -.emoji-1F630 { background-position: -20400px 0px; } -.emoji-1F631 { background-position: -20420px 0px; } -.emoji-1F632 { background-position: -20440px 0px; } -.emoji-1F633 { background-position: -20460px 0px; } -.emoji-1F634 { background-position: -20480px 0px; } -.emoji-1F635 { background-position: -20500px 0px; } -.emoji-1F636 { background-position: -20520px 0px; } -.emoji-1F637 { background-position: -20540px 0px; } -.emoji-1F638 { background-position: -20560px 0px; } -.emoji-1F639 { background-position: -20580px 0px; } -.emoji-1F63A { background-position: -20600px 0px; } -.emoji-1F63B { background-position: -20620px 0px; } -.emoji-1F63C { background-position: -20640px 0px; } -.emoji-1F63D { background-position: -20660px 0px; } -.emoji-1F63E { background-position: -20680px 0px; } -.emoji-1F63F { background-position: -20700px 0px; } -.emoji-1F640 { background-position: -20720px 0px; } -.emoji-1F641 { background-position: -20740px 0px; } -.emoji-1F642 { background-position: -20760px 0px; } -.emoji-1F645 { background-position: -20780px 0px; } -.emoji-1F646 { background-position: -20800px 0px; } -.emoji-1F647 { background-position: -20820px 0px; } -.emoji-1F648 { background-position: -20840px 0px; } -.emoji-1F649 { background-position: -20860px 0px; } -.emoji-1F64A { background-position: -20880px 0px; } -.emoji-1F64B { background-position: -20900px 0px; } -.emoji-1F64C { background-position: -20920px 0px; } -.emoji-1F64D { background-position: -20940px 0px; } -.emoji-1F64E { background-position: -20960px 0px; } -.emoji-1F64F { background-position: -20980px 0px; } -.emoji-1F680 { background-position: -21000px 0px; } -.emoji-1F681 { background-position: -21020px 0px; } -.emoji-1F682 { background-position: -21040px 0px; } -.emoji-1F683 { background-position: -21060px 0px; } -.emoji-1F684 { background-position: -21080px 0px; } -.emoji-1F685 { background-position: -21100px 0px; } -.emoji-1F686 { background-position: -21120px 0px; } -.emoji-1F687 { background-position: -21140px 0px; } -.emoji-1F688 { background-position: -21160px 0px; } -.emoji-1F689 { background-position: -21180px 0px; } -.emoji-1F68A { background-position: -21200px 0px; } -.emoji-1F68B { background-position: -21220px 0px; } -.emoji-1F68C { background-position: -21240px 0px; } -.emoji-1F68D { background-position: -21260px 0px; } -.emoji-1F68E { background-position: -21280px 0px; } -.emoji-1F68F { background-position: -21300px 0px; } -.emoji-1F690 { background-position: -21320px 0px; } -.emoji-1F691 { background-position: -21340px 0px; } -.emoji-1F692 { background-position: -21360px 0px; } -.emoji-1F693 { background-position: -21380px 0px; } -.emoji-1F694 { background-position: -21400px 0px; } -.emoji-1F695 { background-position: -21420px 0px; } -.emoji-1F696 { background-position: -21440px 0px; } -.emoji-1F697 { background-position: -21460px 0px; } -.emoji-1F698 { background-position: -21480px 0px; } -.emoji-1F699 { background-position: -21500px 0px; } -.emoji-1F69A { background-position: -21520px 0px; } -.emoji-1F69B { background-position: -21540px 0px; } -.emoji-1F69C { background-position: -21560px 0px; } -.emoji-1F69D { background-position: -21580px 0px; } -.emoji-1F69E { background-position: -21600px 0px; } -.emoji-1F69F { background-position: -21620px 0px; } -.emoji-1F6A0 { background-position: -21640px 0px; } -.emoji-1F6A1 { background-position: -21660px 0px; } -.emoji-1F6A2 { background-position: -21680px 0px; } -.emoji-1F6A3 { background-position: -21700px 0px; } -.emoji-1F6A4 { background-position: -21720px 0px; } -.emoji-1F6A5 { background-position: -21740px 0px; } -.emoji-1F6A6 { background-position: -21760px 0px; } -.emoji-1F6A7 { background-position: -21780px 0px; } -.emoji-1F6A8 { background-position: -21800px 0px; } -.emoji-1F6A9 { background-position: -21820px 0px; } -.emoji-1F6AA { background-position: -21840px 0px; } -.emoji-1F6AB { background-position: -21860px 0px; } -.emoji-1F6AC { background-position: -21880px 0px; } -.emoji-1F6AD { background-position: -21900px 0px; } -.emoji-1F6AE { background-position: -21920px 0px; } -.emoji-1F6AF { background-position: -21940px 0px; } -.emoji-1F6B0 { background-position: -21960px 0px; } -.emoji-1F6B1 { background-position: -21980px 0px; } -.emoji-1F6B2 { background-position: -22000px 0px; } -.emoji-1F6B3 { background-position: -22020px 0px; } -.emoji-1F6B4 { background-position: -22040px 0px; } -.emoji-1F6B5 { background-position: -22060px 0px; } -.emoji-1F6B6 { background-position: -22080px 0px; } -.emoji-1F6B7 { background-position: -22100px 0px; } -.emoji-1F6B8 { background-position: -22120px 0px; } -.emoji-1F6B9 { background-position: -22140px 0px; } -.emoji-1F6BA { background-position: -22160px 0px; } -.emoji-1F6BB { background-position: -22180px 0px; } -.emoji-1F6BC { background-position: -22200px 0px; } -.emoji-1F6BD { background-position: -22220px 0px; } -.emoji-1F6BE { background-position: -22240px 0px; } -.emoji-1F6BF { background-position: -22260px 0px; } -.emoji-1F6C0 { background-position: -22280px 0px; } -.emoji-1F6C1 { background-position: -22300px 0px; } -.emoji-1F6C2 { background-position: -22320px 0px; } -.emoji-1F6C3 { background-position: -22340px 0px; } -.emoji-1F6C4 { background-position: -22360px 0px; } -.emoji-1F6C5 { background-position: -22380px 0px; } -.emoji-1F6C6 { background-position: -22400px 0px; } -.emoji-1F6C7 { background-position: -22420px 0px; } -.emoji-1F6C8 { background-position: -22440px 0px; } -.emoji-1F6C9 { background-position: -22460px 0px; } -.emoji-1F6CA { background-position: -22480px 0px; } -.emoji-1F6CB { background-position: -22500px 0px; } -.emoji-1F6CC { background-position: -22520px 0px; } -.emoji-1F6CD { background-position: -22540px 0px; } -.emoji-1F6CE { background-position: -22560px 0px; } -.emoji-1F6CF { background-position: -22580px 0px; } -.emoji-1F6E0 { background-position: -22600px 0px; } -.emoji-1F6E1 { background-position: -22620px 0px; } -.emoji-1F6E2 { background-position: -22640px 0px; } -.emoji-1F6E3 { background-position: -22660px 0px; } -.emoji-1F6E4 { background-position: -22680px 0px; } -.emoji-1F6E5 { background-position: -22700px 0px; } -.emoji-1F6E6 { background-position: -22720px 0px; } -.emoji-1F6E7 { background-position: -22740px 0px; } -.emoji-1F6E8 { background-position: -22760px 0px; } -.emoji-1F6E9 { background-position: -22780px 0px; } -.emoji-1F6EA { background-position: -22800px 0px; } -.emoji-1F6EB { background-position: -22820px 0px; } -.emoji-1F6EC { background-position: -22840px 0px; } -.emoji-1F6F0 { background-position: -22860px 0px; } -.emoji-1F6F1 { background-position: -22880px 0px; } -.emoji-1F6F2 { background-position: -22900px 0px; } -.emoji-1F6F3 { background-position: -22920px 0px; } -.emoji-203C { background-position: -22940px 0px; } -.emoji-2049 { background-position: -22960px 0px; } -.emoji-2122 { background-position: -22980px 0px; } -.emoji-2139 { background-position: -23000px 0px; } -.emoji-2194 { background-position: -23020px 0px; } -.emoji-2195 { background-position: -23040px 0px; } -.emoji-2196 { background-position: -23060px 0px; } -.emoji-2197 { background-position: -23080px 0px; } -.emoji-2198 { background-position: -23100px 0px; } -.emoji-2199 { background-position: -23120px 0px; } -.emoji-21A9 { background-position: -23140px 0px; } -.emoji-21AA { background-position: -23160px 0px; } -.emoji-231A { background-position: -23180px 0px; } -.emoji-231B { background-position: -23200px 0px; } -.emoji-23E9 { background-position: -23220px 0px; } -.emoji-23EA { background-position: -23240px 0px; } -.emoji-23EB { background-position: -23260px 0px; } -.emoji-23EC { background-position: -23280px 0px; } -.emoji-23F0 { background-position: -23300px 0px; } -.emoji-23F3 { background-position: -23320px 0px; } -.emoji-24C2 { background-position: -23340px 0px; } -.emoji-25AA { background-position: -23360px 0px; } -.emoji-25AB { background-position: -23380px 0px; } -.emoji-25B6 { background-position: -23400px 0px; } -.emoji-25C0 { background-position: -23420px 0px; } -.emoji-25FB { background-position: -23440px 0px; } -.emoji-25FC { background-position: -23460px 0px; } -.emoji-25FD { background-position: -23480px 0px; } -.emoji-25FE { background-position: -23500px 0px; } -.emoji-2600 { background-position: -23520px 0px; } -.emoji-2601 { background-position: -23540px 0px; } -.emoji-260E { background-position: -23560px 0px; } -.emoji-2611 { background-position: -23580px 0px; } -.emoji-2614 { background-position: -23600px 0px; } -.emoji-2615 { background-position: -23620px 0px; } -.emoji-261D { background-position: -23640px 0px; } -.emoji-263A { background-position: -23660px 0px; } -.emoji-2648 { background-position: -23680px 0px; } -.emoji-2649 { background-position: -23700px 0px; } -.emoji-264A { background-position: -23720px 0px; } -.emoji-264B { background-position: -23740px 0px; } -.emoji-264C { background-position: -23760px 0px; } -.emoji-264D { background-position: -23780px 0px; } -.emoji-264E { background-position: -23800px 0px; } -.emoji-264F { background-position: -23820px 0px; } -.emoji-2650 { background-position: -23840px 0px; } -.emoji-2651 { background-position: -23860px 0px; } -.emoji-2652 { background-position: -23880px 0px; } -.emoji-2653 { background-position: -23900px 0px; } -.emoji-2660 { background-position: -23920px 0px; } -.emoji-2663 { background-position: -23940px 0px; } -.emoji-2665 { background-position: -23960px 0px; } -.emoji-2666 { background-position: -23980px 0px; } -.emoji-2668 { background-position: -24000px 0px; } -.emoji-267B { background-position: -24020px 0px; } -.emoji-267F { background-position: -24040px 0px; } -.emoji-2693 { background-position: -24060px 0px; } -.emoji-26A0 { background-position: -24080px 0px; } -.emoji-26A1 { background-position: -24100px 0px; } -.emoji-26AA { background-position: -24120px 0px; } -.emoji-26AB { background-position: -24140px 0px; } -.emoji-26BD { background-position: -24160px 0px; } -.emoji-26BE { background-position: -24180px 0px; } -.emoji-26C4 { background-position: -24200px 0px; } -.emoji-26C5 { background-position: -24220px 0px; } -.emoji-26CE { background-position: -24240px 0px; } -.emoji-26D4 { background-position: -24260px 0px; } -.emoji-26EA { background-position: -24280px 0px; } -.emoji-26F2 { background-position: -24300px 0px; } -.emoji-26F3 { background-position: -24320px 0px; } -.emoji-26F5 { background-position: -24340px 0px; } -.emoji-26FA { background-position: -24360px 0px; } -.emoji-26FD { background-position: -24380px 0px; } -.emoji-2702 { background-position: -24400px 0px; } -.emoji-2705 { background-position: -24420px 0px; } -.emoji-2708 { background-position: -24440px 0px; } -.emoji-2709 { background-position: -24460px 0px; } -.emoji-270A { background-position: -24480px 0px; } -.emoji-270B { background-position: -24500px 0px; } -.emoji-270C { background-position: -24520px 0px; } -.emoji-270F { background-position: -24540px 0px; } -.emoji-2712 { background-position: -24560px 0px; } -.emoji-2714 { background-position: -24580px 0px; } -.emoji-2716 { background-position: -24600px 0px; } -.emoji-2728 { background-position: -24620px 0px; } -.emoji-2733 { background-position: -24640px 0px; } -.emoji-2734 { background-position: -24660px 0px; } -.emoji-2744 { background-position: -24680px 0px; } -.emoji-2747 { background-position: -24700px 0px; } -.emoji-274C { background-position: -24720px 0px; } -.emoji-274E { background-position: -24740px 0px; } -.emoji-2753 { background-position: -24760px 0px; } -.emoji-2754 { background-position: -24780px 0px; } -.emoji-2755 { background-position: -24800px 0px; } -.emoji-2757 { background-position: -24820px 0px; } -.emoji-2764 { background-position: -24840px 0px; } -.emoji-2795 { background-position: -24860px 0px; } -.emoji-2796 { background-position: -24880px 0px; } -.emoji-2797 { background-position: -24900px 0px; } -.emoji-27A1 { background-position: -24920px 0px; } -.emoji-27B0 { background-position: -24940px 0px; } -.emoji-27BF { background-position: -24960px 0px; } -.emoji-2934 { background-position: -24980px 0px; } -.emoji-2935 { background-position: -25000px 0px; } -.emoji-2B05 { background-position: -25020px 0px; } -.emoji-2B06 { background-position: -25040px 0px; } -.emoji-2B07 { background-position: -25060px 0px; } -.emoji-2B1B { background-position: -25080px 0px; } -.emoji-2B1C { background-position: -25100px 0px; } -.emoji-2B50 { background-position: -25120px 0px; } -.emoji-2B55 { background-position: -25140px 0px; } -.emoji-3030 { background-position: -25160px 0px; } -.emoji-303D { background-position: -25180px 0px; } -.emoji-3297 { background-position: -25200px 0px; } -.emoji-3299 { background-position: -25220px 0px; }
\ No newline at end of file + @media only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and (min--moz-device-pixel-ratio: 2), + only screen and (-o-min-device-pixel-ratio: 2/1), + only screen and (min-device-pixel-ratio: 2), + only screen and (min-resolution: 192dpi), + only screen and (min-resolution: 2dppx) { + background-image: image-url('emoji@2x.png'); + background-size: 840px 820px; + } +} diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index ef62f069dc2..374c66ef5af 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -64,7 +64,6 @@ // This prevents the mess when resizing the sidebar // of elements repositioning themselves.. width: $gutter_inner_width; - overflow-x: hidden; // -- &:first-child { @@ -90,7 +89,6 @@ .gutter-toggle { margin-left: 20px; - border-left: 1px solid $border-gray-light; padding-left: 10px; &:hover { @@ -157,11 +155,10 @@ .right-sidebar { position: fixed; top: 58px; + bottom: 0; right: 0; - height: 100%; - transition-duration: .3s; + transition: width .3s; background: $gray-light; - overflow: scroll; padding: 10px 20px; &.right-sidebar-expanded { @@ -170,6 +167,14 @@ hr { display: none; } + + .sidebar-collapsed-icon { + display: none; + } + + .gutter-toggle { + border-left: 1px solid $border-gray-light; + } } .subscribe-button { @@ -181,7 +186,6 @@ &.right-sidebar-collapsed { width: $sidebar_collapsed_width; padding-top: 0; - overflow-x: hidden; hr { margin: 0; @@ -192,21 +196,13 @@ } .block { - border-bottom: none; + width: $sidebar_collapsed_width - 1px; + margin-left: -19px; padding: 15px 0 0 0; + border-bottom: none; + overflow: hidden; } - } - - .btn { - background: $gray-normal; - border: 1px solid $border-gray-normal; - &:hover { - background: $gray-dark; - border: 1px solid $border-gray-dark; - } - } - &.right-sidebar-collapsed { .issuable-count, .issuable-nav, .assignee > *, @@ -219,15 +215,13 @@ } .gutter-toggle { - margin-left: -$gutter_inner_width + 4; + margin-left: -36px; } .sidebar-collapsed-icon { display: block; - float: left; - width: 62px; + width: 100%; text-align: center; - margin-left: -19px; padding-bottom: 10px; color: #999999; @@ -247,14 +241,15 @@ color: #999999; } } - } - } - &.right-sidebar-expanded { - .sidebar-collapsed-icon { - display: none; + .btn { + background: $gray-normal; + border: 1px solid $border-gray-normal; + &:hover { + background: $gray-dark; + border: 1px solid $border-gray-dark; } } } @@ -263,4 +258,4 @@ small { color: $gray-darkest; } -}
\ No newline at end of file +} diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index d1590e42fcb..1c78aafdb87 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -9,7 +9,7 @@ } } -.manage-labels-list { +.label-row { .label { padding: 9px; font-size: 14px; diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index f033ff15f88..9a2c4b83ffb 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -236,4 +236,4 @@ } } } -}
\ No newline at end of file +} diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss index e80dc9e84a1..9144a83647d 100644 --- a/app/assets/stylesheets/pages/milestone.scss +++ b/app/assets/stylesheets/pages/milestone.scss @@ -11,3 +11,60 @@ li.milestone { height: 6px; } } + +.milestone-content { + .issues-count { + margin-right: 17px; + float: right; + width: 105px; + } + + .issue-row { + .color-label { + border-radius: 2px; + padding: 3px !important; + } + + // Issue title + span a { + color: rgba(0,0,0,0.64); + } + } +} + +.milestone-summary { + margin-bottom: 25px; + + .milestone-stat { + margin-right: 10px; + } + + .time-elapsed { + color: $orange-light; + } +} + +.issues-sortable-list { + .issue-detail { + display: block; + + .issue-number{ + color: rgba(0,0,0,0.44); + margin-right: 5px; + } + .color-label { + padding: 6px 10px; + margin-right: 7px; + margin-top: 10px; + } + + .avatar { + float: none; + } + } +} + +.milestone-detail { + border-bottom: 1px solid $border-color; + padding: 20px 0; +} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 046bae672fc..542ac896f6b 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -73,24 +73,19 @@ font-weight: normal; } + .visibility-icon { + display: inline-block; + margin-left: 5px; + font-size: 18px; + color: $gray; + } + p { padding: 0 $gl-padding; color: #5c5d5e; } } - .visibility-level-label { - @extend .btn; - @extend .btn-gray; - - color: $gray; - cursor: default; - - i { - color: inherit; - } - } - .project-repo-buttons { margin-top: 20px; margin-bottom: 0px; diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss new file mode 100644 index 00000000000..2f57f21963d --- /dev/null +++ b/app/assets/stylesheets/pages/todos.scss @@ -0,0 +1,124 @@ +/** + * Dashboard Todos + * + */ + +.navbar-nav { + li { + .badge.todos-pending-count { + background-color: #7f8fa4; + margin-top: -5px; + } + } +} + +.todos { + .panel { + border-top: none; + margin-bottom: 0; + } +} + +.todo-item { + font-size: $gl-font-size; + padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top); + border-bottom: 1px solid $table-border-color; + color: #7f8fa4; + + &.todo-inline { + .avatar { + position: relative; + top: -2px; + } + + .todo-title { + line-height: 40px; + } + } + + a { + color: #4c4e54; + } + + .avatar { + margin-left: -($gl-avatar-size + $gl-padding-top); + } + + .todo-title { + @include str-truncated(calc(100% - 174px)); + font-weight: 600; + + .author_name { + color: #333; + } + } + + .todo-body { + margin-right: 174px; + + .todo-note { + word-wrap: break-word; + + .md { + color: #7f8fa4; + font-size: $gl-font-size; + + p { + color: #5c5d5e; + } + } + + pre { + border: none; + background: #f9f9f9; + border-radius: 0; + color: #777; + margin: 0 20px; + overflow: hidden; + } + + .note-image-attach { + margin-top: 4px; + margin-left: 0px; + max-width: 200px; + float: none; + } + + p:last-child { + margin-bottom: 0; + } + } + + .todo-note-icon { + color: #777; + float: left; + font-size: $gl-font-size; + line-height: 16px; + margin-right: 5px; + } + } + + &:last-child { border:none } +} + +@media (max-width: $screen-xs-max) { + .todo-item { + padding-left: $gl-padding; + + .todo-title { + white-space: normal; + overflow: visible; + max-width: 100%; + } + + .avatar { + display: none; + } + + .todo-body { + margin: 0; + border-left: 2px solid #DDD; + padding-left: 10px; + } + } +} diff --git a/app/controllers/admin/labels_controller.rb b/app/controllers/admin/labels_controller.rb index 3b070e65d0d..d79ce2b10fe 100644 --- a/app/controllers/admin/labels_controller.rb +++ b/app/controllers/admin/labels_controller.rb @@ -53,6 +53,6 @@ class Admin::LabelsController < Admin::ApplicationController end def label_params - params[:label].permit(:title, :color) + params[:label].permit(:title, :description, :color) end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2c329b60a19..fb74919ea23 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -25,7 +25,7 @@ class ApplicationController < ActionController::Base helper_method :abilities, :can?, :current_application_settings helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled? - helper_method :repository + helper_method :repository, :can_collaborate_with_project? rescue_from Encoding::CompatibilityError do |exception| log_exception(exception) @@ -410,6 +410,13 @@ class ApplicationController < ActionController::Base current_user.nil? && root_path == request.path end + def can_collaborate_with_project?(project = nil) + project ||= @project + + can?(current_user, :push_code, project) || + (current_user && current_user.already_forked?(project)) + end + private def set_default_sort diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index b9eb0a22f88..787416c17ab 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -13,17 +13,11 @@ module CreatesCommit result = service.new(@tree_edit_project, current_user, commit_params).execute if result[:status] == :success - flash[:notice] = success_notice || "Your changes have been successfully committed." - - if create_merge_request? - success_path = new_merge_request_path - target = different_project? ? "project" : "branch" - flash[:notice] << " You can now submit a merge request to get this change into the original #{target}." - end + update_flash_notice(success_notice) respond_to do |format| - format.html { redirect_to success_path } - format.json { render json: { message: "success", filePath: success_path } } + format.html { redirect_to final_success_path(success_path) } + format.json { render json: { message: "success", filePath: final_success_path(success_path) } } end else flash[:alert] = result[:message] @@ -41,14 +35,32 @@ module CreatesCommit end def authorize_edit_tree! - return if can?(current_user, :push_code, project) - return if current_user && current_user.already_forked?(project) + return if can_collaborate_with_project? access_denied! end private + def update_flash_notice(success_notice) + flash[:notice] = success_notice || "Your changes have been successfully committed." + + if create_merge_request? + if merge_request_exists? + flash[:notice] = nil + else + target = different_project? ? "project" : "branch" + flash[:notice] << " You can now submit a merge request to get this change into the original #{target}." + end + end + end + + def final_success_path(success_path) + return success_path unless create_merge_request? + + merge_request_exists? ? existing_merge_request_path : new_merge_request_path + end + def new_merge_request_path new_namespace_project_merge_request_path( @mr_source_project.namespace, @@ -62,6 +74,19 @@ module CreatesCommit ) end + def existing_merge_request_path + namespace_project_merge_request_path(@mr_target_project.namespace, @mr_target_project, @merge_request) + end + + def merge_request_exists? + return @merge_request if defined?(@merge_request) + + @merge_request = @mr_target_project.merge_requests.opened.find_by( + source_branch: @mr_source_branch, + target_branch: @mr_target_branch + ) + end + def different_project? @mr_source_project != @mr_target_project end @@ -75,7 +100,7 @@ module CreatesCommit end def set_commit_variables - @mr_source_branch = @target_branch + @mr_source_branch ||= @target_branch if can?(current_user, :push_code, @project) # Edit file in this project @@ -89,7 +114,7 @@ module CreatesCommit else # Merge request to this project @mr_target_project = @project - @mr_target_branch = @ref + @mr_target_branch ||= @ref end else # Edit file in fork @@ -97,7 +122,7 @@ module CreatesCommit # Merge request from fork to this project @mr_source_project = @tree_edit_project @mr_target_project = @project - @mr_target_branch = @ref + @mr_target_branch ||= @ref end end end diff --git a/app/controllers/concerns/issues_action.rb b/app/controllers/concerns/issues_action.rb index effd4721949..5b098628557 100644 --- a/app/controllers/concerns/issues_action.rb +++ b/app/controllers/concerns/issues_action.rb @@ -6,6 +6,8 @@ module IssuesAction @issues = @issues.page(params[:page]).per(ApplicationController::PER_PAGE) @issues = @issues.preload(:author, :project) + @label = @issuable_finder.labels.first + respond_to do |format| format.html format.atom { render layout: false } diff --git a/app/controllers/concerns/merge_requests_action.rb b/app/controllers/concerns/merge_requests_action.rb index f7a25111db9..f6de696e84d 100644 --- a/app/controllers/concerns/merge_requests_action.rb +++ b/app/controllers/concerns/merge_requests_action.rb @@ -5,5 +5,7 @@ module MergeRequestsAction @merge_requests = get_merge_requests_collection @merge_requests = @merge_requests.page(params[:page]).per(ApplicationController::PER_PAGE) @merge_requests = @merge_requests.preload(:author, :target_project) + + @label = @issuable_finder.labels.first end end diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb new file mode 100644 index 00000000000..9ee9039f004 --- /dev/null +++ b/app/controllers/dashboard/todos_controller.rb @@ -0,0 +1,35 @@ +class Dashboard::TodosController < Dashboard::ApplicationController + before_action :find_todos, only: [:index, :destroy_all] + + def index + @todos = @todos.page(params[:page]).per(PER_PAGE) + end + + def destroy + todo.done! + + respond_to do |format| + format.html { redirect_to dashboard_todos_path, notice: 'Todo was successfully marked as done.' } + format.js { render nothing: true } + end + end + + def destroy_all + @todos.each(&:done) + + respond_to do |format| + format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' } + format.js { render nothing: true } + end + end + + private + + def todo + @todo ||= current_user.todos.find(params[:id]) + end + + def find_todos + @todos = TodosFinder.new(current_user, params).execute + end +end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 9cf76521a0d..21135f7d607 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -42,6 +42,26 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController end end + def saml + if current_user + log_audit_event(current_user, with: :saml) + # Update SAML identity if data has changed. + identity = current_user.identities.find_by(extern_uid: oauth['uid'], provider: :saml) + if identity.nil? + current_user.identities.create(extern_uid: oauth['uid'], provider: :saml) + redirect_to profile_account_path, notice: 'Authentication method updated' + else + redirect_to after_sign_in_path_for(current_user) + end + else + saml_user = Gitlab::Saml::User.new(oauth) + saml_user.save + @user = saml_user.gl_user + + continue_login_process + end + end + def omniauth_error @provider = params[:provider] @error = params[:error] @@ -65,25 +85,11 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController log_audit_event(current_user, with: oauth['provider']) redirect_to profile_account_path, notice: 'Authentication method updated' else - @user = Gitlab::OAuth::User.new(oauth) - @user.save + oauth_user = Gitlab::OAuth::User.new(oauth) + oauth_user.save + @user = oauth_user.gl_user - # Only allow properly saved users to login. - if @user.persisted? && @user.valid? - log_audit_event(@user.gl_user, with: oauth['provider']) - sign_in_and_redirect(@user.gl_user) - else - error_message = - if @user.gl_user.errors.any? - @user.gl_user.errors.map do |attribute, message| - "#{attribute} #{message}" - end.join(", ") - else - '' - end - - redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return - end + continue_login_process end rescue Gitlab::OAuth::SignupDisabledError label = Gitlab::OAuth::Provider.label_for(oauth['provider']) @@ -104,6 +110,18 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController session[:service_tickets][provider] = ticket end + def continue_login_process + # Only allow properly saved users to login. + if @user.persisted? && @user.valid? + log_audit_event(@user, with: oauth['provider']) + sign_in_and_redirect(@user) + else + error_message = @user.errors.full_messages.to_sentence + + redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return + end + end + def oauth @oauth ||= request.env['omniauth.auth'] end diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 495a432347e..cd8b2911674 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -87,7 +87,7 @@ class Projects::BlobController < Projects::ApplicationController private def blob - @blob ||= @repository.blob_at(@commit.id, @path) + @blob ||= Blob.decorate(@repository.blob_at(@commit.id, @path)) if @blob @blob diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index ec379c53b8f..f159e169f6d 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -56,6 +56,12 @@ class Projects::BuildsController < Projects::ApplicationController render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha) end + def erase + @build.erase(erased_by: current_user) + redirect_to namespace_project_build_path(project.namespace, project, @build), + notice: "Build has been sucessfully erased!" + end + private def build diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 36951b91372..97d31a4229a 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -2,6 +2,8 @@ # # Not to be confused with CommitsController, plural. class Projects::CommitController < Projects::ApplicationController + include CreatesCommit + # Authorize before_action :require_non_empty_project before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds] @@ -9,6 +11,7 @@ class Projects::CommitController < Projects::ApplicationController before_action :authorize_read_commit_status!, only: [:builds] before_action :commit before_action :define_show_vars, only: [:show, :builds] + before_action :authorize_edit_tree!, only: [:revert] def show apply_diff_view_cookie! @@ -55,8 +58,37 @@ class Projects::CommitController < Projects::ApplicationController render layout: false end + def revert + assign_revert_commit_vars + + return render_404 if @target_branch.blank? + + create_commit(Commits::RevertService, success_notice: "The #{revert_type_title} has been successfully reverted.", + success_path: successful_revert_path, failure_path: failed_revert_path) + end + private + def revert_type_title + @commit.merged_merge_request ? 'merge request' : 'commit' + end + + def successful_revert_path + return referenced_merge_request_url if @commit.merged_merge_request + + namespace_project_commits_url(@project.namespace, @project, @target_branch) + end + + def failed_revert_path + return referenced_merge_request_url if @commit.merged_merge_request + + namespace_project_commit_url(@project.namespace, @project, params[:id]) + end + + def referenced_merge_request_url + namespace_project_merge_request_url(@project.namespace, @project, @commit.merged_merge_request) + end + def commit @commit ||= @project.commit(params[:id]) end @@ -79,4 +111,16 @@ class Projects::CommitController < Projects::ApplicationController @statuses = ci_commit.statuses if ci_commit end + + def assign_revert_commit_vars + @commit = project.commit(params[:id]) + @target_branch = params[:target_branch] + @mr_source_branch = @commit.revert_branch_name + @mr_target_branch = @target_branch + @commit_params = { + commit: @commit, + revert_type_title: revert_type_title, + create_merge_request: params[:create_merge_request].present? || different_project? + } + end end diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index e61e01c4a59..0c551501ca4 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -32,7 +32,7 @@ class Projects::ForksController < Projects::ApplicationController if continue_params redirect_to continue_params[:to], notice: continue_params[:notice] else - redirect_to namespace_project_path(@forked_project.namespace, @forked_project), notice: "The project was successfully forked." + redirect_to namespace_project_path(@forked_project.namespace, @forked_project), notice: "The project '#{@forked_project.name}' was successfully forked." end end else diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb index 07f355c35b1..196996f1752 100644 --- a/app/controllers/projects/imports_controller.rb +++ b/app/controllers/projects/imports_controller.rb @@ -3,6 +3,7 @@ class Projects::ImportsController < Projects::ApplicationController before_action :authorize_admin_project! before_action :require_no_repo, only: [:new, :create] before_action :redirect_if_progress, only: [:new, :create] + before_action :redirect_if_no_import, only: :show def new end @@ -63,14 +64,19 @@ class Projects::ImportsController < Projects::ApplicationController def require_no_repo if @project.repository_exists? - redirect_to(namespace_project_path(@project.namespace, @project)) + redirect_to namespace_project_path(@project.namespace, @project) end end def redirect_if_progress if @project.import_in_progress? - redirect_to namespace_project_import_path(@project.namespace, @project) && - return + redirect_to namespace_project_import_path(@project.namespace, @project) + end + end + + def redirect_if_no_import + if @project.repository_exists? && @project.no_import? + redirect_to namespace_project_path(@project.namespace, @project) end end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 68244883803..67faa1e4437 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -32,6 +32,7 @@ class Projects::IssuesController < Projects::ApplicationController end @issues = @issues.page(params[:page]).per(PER_PAGE) + @label = @project.labels.find_by(title: params[:label_name]) respond_to do |format| format.html diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 86d6e3e0f6b..ecac3c395ec 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -69,7 +69,7 @@ class Projects::LabelsController < Projects::ApplicationController end def label_params - params.require(:label).permit(:title, :color) + params.require(:label).permit(:title, :description, :color) end def label diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 9d588c370aa..5fe21694605 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -34,6 +34,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE) @merge_requests = @merge_requests.preload(:target_project) + @label = @project.labels.find_by(title: params[:label_name]) + respond_to do |format| format.html format.json do @@ -179,6 +181,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController return end + TodoService.new.merge_merge_request(merge_request, current_user) + @merge_request.update(merge_error: nil) if params[:merge_when_build_succeeds].present? && @merge_request.ci_commit && @merge_request.ci_commit.active? diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index a5c4ef1c7c7..21f30f278c8 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -35,6 +35,7 @@ class Projects::MilestonesController < Projects::ApplicationController @issues = @milestone.issues @users = @milestone.participants.uniq @merge_requests = @milestone.merge_requests + @labels = @milestone.labels end def create diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index ba9aea1c165..5c7614cfbaf 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -11,7 +11,9 @@ class Projects::RepositoriesController < Projects::ApplicationController end def archive - render json: ArchiveRepositoryService.new(@project, params[:ref], params[:format]).execute + RepositoryArchiveCacheWorker.perform_async + headers.store(*Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format])) + head :ok rescue => ex logger.error("#{self.class.name}: #{ex}") return git_not_found! diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 14ca7426c2f..aea08ecce3e 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -236,7 +236,7 @@ class ProjectsController < ApplicationController Emoji.emojis.map do |name, emoji| { name: name, - path: view_context.image_url("emoji/#{emoji["unicode"]}.png") + path: view_context.image_url("#{emoji["unicode"]}.png") } end end diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 0a4192e6bac..f7240edd618 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -119,6 +119,20 @@ class IssuableFinder labels? && params[:label_name] == Label::None.title end + def labels + return @labels if defined?(@labels) + + if labels? && !filter_by_no_label? + @labels = Label.where(title: label_names) + + if projects + @labels = @labels.where(project: projects) + end + else + @labels = Label.none + end + end + def assignee? params[:assignee_id].present? end @@ -253,8 +267,6 @@ class IssuableFinder joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{klass.name}' AND label_links.target_id = #{klass.table_name}.id"). where(label_links: { id: nil }) else - label_names = params[:label_name].split(",") - items = items.joins(:labels).where(labels: { title: label_names }) if projects @@ -266,6 +278,10 @@ class IssuableFinder items end + def label_names + params[:label_name].split(',') + end + def current_user_related? params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me' end diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb new file mode 100644 index 00000000000..3ba27c40504 --- /dev/null +++ b/app/finders/todos_finder.rb @@ -0,0 +1,129 @@ +# TodosFinder +# +# Used to filter Todos by set of params +# +# Arguments: +# current_user - which user use +# params: +# action_id: integer +# author_id: integer +# project_id; integer +# state: 'pending' or 'done' +# type: 'Issue' or 'MergeRequest' +# + +class TodosFinder + NONE = '0' + + attr_accessor :current_user, :params + + def initialize(current_user, params) + @current_user = current_user + @params = params + end + + def execute + items = current_user.todos + items = by_action_id(items) + items = by_author(items) + items = by_project(items) + items = by_state(items) + items = by_type(items) + + items + end + + private + + def action_id? + action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED].include?(action_id.to_i) + end + + def action_id + params[:action_id] + end + + def author? + params[:author_id].present? + end + + def author + return @author if defined?(@author) + + @author = + if author? && params[:author_id] != NONE + User.find(params[:author_id]) + else + nil + end + end + + def project? + params[:project_id].present? + end + + def project + return @project if defined?(@project) + + if project? + @project = Project.find(params[:project_id]) + + unless Ability.abilities.allowed?(current_user, :read_project, @project) + @project = nil + end + else + @project = nil + end + + @project + end + + def type? + type.present? && ['Issue', 'MergeRequest'].include?(type) + end + + def type + params[:type] + end + + def by_action_id(items) + if action_id? + items = items.where(action: action_id) + end + + items + end + + def by_author(items) + if author? + items = items.where(author_id: author.try(:id)) + end + + items + end + + def by_project(items) + if project? + items = items.where(project: project) + end + + items + end + + def by_state(items) + case params[:state] + when 'done' + items.done + else + items.pending + end + end + + def by_type(items) + if type? + items = items.where(target_type: type) + end + + items + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ecefa9b006d..f0aa2b57121 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -118,12 +118,6 @@ module ApplicationHelper grouped_options_for_select(options, @ref || @project.default_branch) end - def emoji_autocomplete_source - # should be an array of strings - # so to_s can be called, because it is sufficient and to_json is too slow - Emoji.names.to_s - end - # Define whenever show last push event # with suggestion to create MR def show_last_push_widget?(event) diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 16967927922..7143a744869 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -127,10 +127,6 @@ module BlobHelper end end - def blob_svg?(blob) - blob.language && blob.language.name == 'SVG' - end - # SVGs can contain malicious JavaScript; only include whitelisted # elements and attributes. Note that this whitelist is by no means complete # and may omit some elements. diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 1d14ee52cfc..a09e91578b6 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -123,6 +123,37 @@ module CommitsHelper ) end + def revert_commit_link(commit, continue_to_path, btn_class: nil) + return unless current_user + + tooltip = "Revert this #{revert_commit_type(commit)} in a new merge request" + + if can_collaborate_with_project? + content_tag :span, 'data-toggle' => 'modal', 'data-target' => '#modal-revert-commit' do + link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class}" + end + elsif can?(current_user, :fork_project, @project) + continue_params = { + to: continue_to_path, + notice: edit_in_new_fork_notice + ' Try to revert this commit again.', + notice_now: edit_in_new_fork_notice_now + } + fork_path = namespace_project_forks_path(@project.namespace, @project, + namespace_key: current_user.namespace.id, + continue: continue_params) + + link_to 'Revert', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip + end + end + + def revert_commit_type(commit) + if commit.merged_merge_request + 'merge request' + else + 'commit' + end + end + protected # Private: Returns a link to a person. If the person has a matching user and diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index f9bacc8ba45..d76db867c5a 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -69,7 +69,7 @@ module DiffHelper end def line_comments - @line_comments ||= @line_notes.select(&:active?).group_by(&:line_code) + @line_comments ||= @line_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code) end def organize_comments(type_left, type_right, line_code_left, line_code_right) @@ -137,7 +137,7 @@ module DiffHelper # Always use HTML to handle case where JSON diff rendered this button params_copy.delete(:format) - link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn active' : 'btn') do + link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn active' : 'btn'), data: { view_type: name } do title end end diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 29cb753e62c..5d86bd490a8 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -23,6 +23,7 @@ module NavHelper if current_path?('merge_requests#show') || current_path?('merge_requests#diffs') || current_path?('merge_requests#commits') || + current_path?('merge_requests#builds') || current_path?('issues#show') if cookies[:collapsed_gutter] == 'true' "page-gutter right-sidebar-collapsed" diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 241179b0212..f9026b887da 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -11,6 +11,8 @@ module SortingHelper sort_value_largest_repo => sort_title_largest_repo, sort_value_recently_signin => sort_title_recently_signin, sort_value_oldest_signin => sort_title_oldest_signin, + sort_value_downvotes => sort_title_downvotes, + sort_value_upvotes => sort_title_upvotes } end @@ -54,6 +56,14 @@ module SortingHelper 'Oldest sign in' end + def sort_title_downvotes + 'Least popular' + end + + def sort_title_upvotes + 'Most popular' + end + def sort_value_oldest_updated 'updated_asc' end @@ -93,4 +103,12 @@ module SortingHelper def sort_value_oldest_signin 'oldest_sign_in' end + + def sort_value_downvotes + 'downvotes_desc' + end + + def sort_value_upvotes + 'upvotes_desc' + end end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb new file mode 100644 index 00000000000..4b745a5b969 --- /dev/null +++ b/app/helpers/todos_helper.rb @@ -0,0 +1,87 @@ +module TodosHelper + def todos_pending_count + current_user.todos.pending.count + end + + def todos_done_count + current_user.todos.done.count + end + + def todo_action_name(todo) + case todo.action + when Todo::ASSIGNED then 'assigned you' + when Todo::MENTIONED then 'mentioned you on' + end + end + + def todo_target_link(todo) + target = todo.target_type.titleize.downcase + link_to "#{target} #{todo.target.to_reference}", todo_target_path(todo) + end + + def todo_target_path(todo) + anchor = dom_id(todo.note) if todo.note.present? + + polymorphic_path([todo.project.namespace.becomes(Namespace), + todo.project, todo.target], anchor: anchor) + end + + def todos_filter_params + { + state: params[:state], + project_id: params[:project_id], + author_id: params[:author_id], + type: params[:type], + action_id: params[:action_id], + } + end + + def todos_filter_path(options = {}) + without = options.delete(:without) + + options = todos_filter_params.merge(options) + + if without.present? + without.each do |key| + options.delete(key) + end + end + + path = request.path + path << "?#{options.to_param}" + path + end + + def todo_actions_options + actions = [ + OpenStruct.new(id: '', title: 'Any Action'), + OpenStruct.new(id: Todo::ASSIGNED, title: 'Assigned'), + OpenStruct.new(id: Todo::MENTIONED, title: 'Mentioned') + ] + + options_from_collection_for_select(actions, 'id', 'title', params[:action_id]) + end + + def todo_projects_options + projects = current_user.authorized_projects.sorted_by_activity.non_archived + projects = projects.includes(:namespace) + + projects = projects.map do |project| + OpenStruct.new(id: project.id, title: project.name_with_namespace) + end + + projects.unshift(OpenStruct.new(id: '', title: 'Any Project')) + + options_from_collection_for_select(projects, 'id', 'title', params[:project_id]) + end + + def todo_types_options + types = [ + OpenStruct.new(title: 'Any Type', name: ''), + OpenStruct.new(title: 'Issue', name: 'Issue'), + OpenStruct.new(title: 'Merge Request', name: 'MergeRequest') + ] + + options_from_collection_for_select(types, 'name', 'title', params[:type]) + end +end diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index 2ad7c80dae0..4920ca5af6e 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -56,8 +56,7 @@ module TreeHelper return false unless on_top_of_branch?(project, ref) - can?(current_user, :push_code, project) || - (current_user && current_user.already_forked?(project)) + can_collaborate_with_project?(project) end def tree_edit_branch(project = @project, ref = @ref) diff --git a/app/models/blob.rb b/app/models/blob.rb new file mode 100644 index 00000000000..8ee9f3006b2 --- /dev/null +++ b/app/models/blob.rb @@ -0,0 +1,34 @@ +# Blob is a Rails-specific wrapper around Gitlab::Git::Blob objects +class Blob < SimpleDelegator + # Wrap a Gitlab::Git::Blob object, or return nil when given nil + # + # This method prevents the decorated object from evaluating to "truthy" when + # given a nil value. For example: + # + # blob = Blob.new(nil) + # puts "truthy" if blob # => "truthy" + # + # blob = Blob.decorate(nil) + # puts "truthy" if blob # No output + def self.decorate(blob) + return if blob.nil? + + new(blob) + end + + def svg? + text? && language && language.name == 'SVG' + end + + def to_partial_path + if lfs_pointer? + 'download' + elsif image? || svg? + 'image' + elsif text? + 'text' + else + 'download' + end + end +end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 623edd8bc57..1227458e525 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -31,15 +31,19 @@ # artifacts_file :text # gl_project_id :integer # artifacts_metadata :text +# erased_by_id :integer +# erased_at :datetime # module Ci class Build < CommitStatus include Gitlab::Application.routes.url_helpers + LAZY_ATTRIBUTES = ['trace'] belongs_to :runner, class_name: 'Ci::Runner' belongs_to :trigger_request, class_name: 'Ci::TriggerRequest' + belongs_to :erased_by, class_name: 'User' serialize :options @@ -103,23 +107,22 @@ module Ci end state_machine :status, initial: :pending do - after_transition pending: :running do |build, transition| + after_transition pending: :running do |build| build.execute_hooks end - after_transition any => [:success, :failed, :canceled] do |build, transition| - return unless build.project + # We use around_transition to create builds for next stage as soon as possible, before the `after_*` is executed + around_transition any => [:success, :failed, :canceled] do |build, block| + block.call + build.commit.create_next_builds(build) if build.commit + end + after_transition any => [:success, :failed, :canceled] do |build| build.update_coverage - build.commit.create_next_builds(build) build.execute_hooks end end - def ignored? - failed? && allow_failure? - end - def retryable? project.builds_enabled? && commands.present? end @@ -179,6 +182,7 @@ module Ci end def update_coverage + return unless project coverage_regex = project.build_coverage_regex return unless coverage_regex coverage = extract_coverage(trace, coverage_regex) @@ -203,6 +207,10 @@ module Ci end end + def has_trace? + raw_trace.present? + end + def raw_trace if File.file?(path_to_trace) File.read(path_to_trace) @@ -330,6 +338,7 @@ module Ci end def execute_hooks + return unless project build_data = Gitlab::BuildDataBuilder.build(self) project.execute_hooks(build_data.dup, :build_hooks) project.execute_services(build_data.dup, :build_hooks) @@ -359,6 +368,33 @@ module Ci Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path, **options).to_entry end + def erase(opts = {}) + return false unless erasable? + + remove_artifacts_file! + remove_artifacts_metadata! + erase_trace! + update_erased!(opts[:erased_by]) + end + + def erasable? + complete? && (artifacts? || has_trace?) + end + + def erased? + !self.erased_at.nil? + end + + private + + def erase_trace! + self.trace = nil + end + + def update_erased!(user = nil) + self.update(erased_by: user, erased_at: Time.now) + end + private def yaml_variables diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 38b20cd7faa..e725a6d468c 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -22,6 +22,7 @@ module Ci extend Ci::Model LAST_CONTACT_TIME = 5.minutes.ago + AVAILABLE_SCOPES = ['specific', 'shared', 'active', 'paused', 'online'] has_many :builds, class_name: 'Ci::Build' has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject' @@ -38,6 +39,11 @@ module Ci scope :online, ->() { where('contacted_at > ?', LAST_CONTACT_TIME) } scope :ordered, ->() { order(id: :desc) } + scope :owned_or_shared, ->(project_id) do + joins('LEFT JOIN ci_runner_projects ON ci_runner_projects.runner_id = ci_runners.id') + .where("ci_runner_projects.gl_project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id) + end + acts_as_taggable def self.search(query) diff --git a/app/models/commit.rb b/app/models/commit.rb index 23b771aebb7..3224f5457f0 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -215,6 +215,44 @@ class Commit ci_commit.try(:status) || :not_found end + def revert_branch_name + "revert-#{short_id}" + end + + def revert_description + if merged_merge_request + "This reverts merge request #{merged_merge_request.to_reference}" + else + "This reverts commit #{sha}" + end + end + + def revert_message + %Q{Revert "#{title}"\n\n#{revert_description}} + end + + def reverts_commit?(commit) + description? && description.include?(commit.revert_description) + end + + def merge_commit? + parents.size > 1 + end + + def merged_merge_request + return @merged_merge_request if defined?(@merged_merge_request) + + @merged_merge_request = project.merge_requests.find_by(merge_commit_sha: id) if merge_commit? + end + + def has_been_reverted?(current_user = nil, noteable = self) + Gitlab::ReferenceExtractor.lazily do + noteable.notes.system.flat_map do |note| + note.all_references(current_user).commits + end + end.any? { |commit_ref| commit_ref.reverts_commit?(self) } + end + private def repo_changes diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 66e0502fc0c..7ef50836322 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -75,16 +75,16 @@ class CommitStatus < ActiveRecord::Base transition [:pending, :running] => :canceled end - after_transition pending: :running do |build, transition| - build.update_attributes started_at: Time.now + after_transition pending: :running do |commit_status| + commit_status.update_attributes started_at: Time.now end - after_transition any => [:success, :failed, :canceled] do |build, transition| - build.update_attributes finished_at: Time.now + after_transition any => [:success, :failed, :canceled] do |commit_status| + commit_status.update_attributes finished_at: Time.now end - after_transition [:pending, :running] => :success do |build, transition| - MergeRequests::MergeWhenBuildSucceedsService.new(build.commit.project, nil).trigger(build) + after_transition [:pending, :running] => :success do |commit_status| + MergeRequests::MergeWhenBuildSucceedsService.new(commit_status.commit.project, nil).trigger(commit_status) end state :pending, value: 'pending' @@ -113,6 +113,10 @@ class CommitStatus < ActiveRecord::Base canceled? || success? || failed? end + def ignored? + failed? && allow_failure? + end + def duration if started_at && finished_at finished_at - started_at diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 5136d0196a5..e5f089fb8a0 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -69,10 +69,35 @@ module Issuable case method.to_s when 'milestone_due_asc' then order_milestone_due_asc when 'milestone_due_desc' then order_milestone_due_desc + when 'downvotes_desc' then order_downvotes_desc + when 'upvotes_desc' then order_upvotes_desc else order_by(method) end end + + def order_downvotes_desc + order_votes_desc('thumbsdown') + end + + def order_upvotes_desc + order_votes_desc('thumbsup') + end + + def order_votes_desc(award_emoji_name) + issuable_table = self.arel_table + note_table = Note.arel_table + + join_clause = issuable_table.join(note_table, Arel::Nodes::OuterJoin).on( + note_table[:noteable_id].eq(issuable_table[:id]).and( + note_table[:noteable_type].eq(self.name).and( + note_table[:is_award].eq(true).and(note_table[:note].eq(award_emoji_name)) + ) + ) + ).join_sources + + joins(join_clause).group(issuable_table[:id]).reorder("COUNT(notes.id) DESC") + end end def today? diff --git a/app/models/label.rb b/app/models/label.rb index 220da10a6ab..07a1db4abe5 100644 --- a/app/models/label.rb +++ b/app/models/label.rb @@ -2,13 +2,14 @@ # # Table name: labels # -# id :integer not null, primary key -# title :string(255) -# color :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# template :boolean default(FALSE) +# id :integer not null, primary key +# title :string(255) +# color :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# template :boolean default(FALSE) +# description :string(255) # class Label < ActiveRecord::Base @@ -85,6 +86,10 @@ class Label < ActiveRecord::Base issues.opened.count end + def closed_issues_count + issues.closed.count + end + def template? template end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 1be8061e53d..1543ef311d7 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -24,6 +24,7 @@ # merge_params :text # merge_when_build_succeeds :boolean default(FALSE), not null # merge_user_id :integer +# merge_commit_sha :string # require Rails.root.join("app/models/commit") @@ -137,7 +138,7 @@ class MergeRequest < ActiveRecord::Base scope :by_milestone, ->(milestone) { where(milestone_id: milestone) } scope :in_projects, ->(project_ids) { where("source_project_id in (:project_ids) OR target_project_id in (:project_ids)", project_ids: project_ids) } scope :of_projects, ->(ids) { where(target_project_id: ids) } - scope :opened, -> { with_state(:opened) } + scope :opened, -> { with_states(:opened, :reopened) } scope :merged, -> { with_state(:merged) } scope :closed, -> { with_state(:closed) } scope :closed_and_merged, -> { with_states(:closed, :merged) } @@ -532,4 +533,12 @@ class MergeRequest < ActiveRecord::Base [diff_base_commit, last_commit] end + + def merge_commit + @merge_commit ||= project.commit(merge_commit_sha) if merge_commit_sha + end + + def can_be_reverted?(current_user = nil) + merge_commit && !merge_commit.has_been_reverted?(current_user, self) + end end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 9c4476c768e..cbe65d70997 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -27,6 +27,7 @@ class Milestone < ActiveRecord::Base belongs_to :project has_many :issues + has_many :labels, through: :issues has_many :merge_requests has_many :participants, through: :issues, source: :assignee @@ -109,6 +110,19 @@ class Milestone < ActiveRecord::Base 0 end + # Returns the elapsed time (in percent) since the Milestone creation date until today. + # If the Milestone doesn't have a due_date then returns 0 since we can't calculate the elapsed time. + # If the Milestone is overdue then it returns 100%. + def percent_time_used + return 0 unless due_date + return 100 if expired? + + duration = ((created_at - due_date.to_datetime) / 1.day) + days_elapsed = ((created_at - Time.now) / 1.day) + + ((days_elapsed.to_f / duration) * 100).floor + end + def expires_at if due_date if due_date.past? diff --git a/app/models/note.rb b/app/models/note.rb index 55255d22c2f..d287e0f3c6d 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -37,6 +37,8 @@ class Note < ActiveRecord::Base belongs_to :author, class_name: "User" belongs_to :updated_by, class_name: "User" + has_many :todos, dependent: :destroy + delegate :name, to: :project, prefix: true delegate :name, :email, to: :author, prefix: true @@ -375,6 +377,7 @@ class Note < ActiveRecord::Base # def set_award! return unless awards_supported? && contains_emoji_only? + self.is_award = true self.note = award_emoji_name end @@ -382,7 +385,7 @@ class Note < ActiveRecord::Base private def awards_supported? - noteable.kind_of?(Issue) || noteable.is_a?(MergeRequest) + (noteable.kind_of?(Issue) || noteable.is_a?(MergeRequest)) && !for_diff_line? end def contains_emoji_only? diff --git a/app/models/project.rb b/app/models/project.rb index a43878ebcad..95ad88c76ae 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -382,6 +382,10 @@ class Project < ActiveRecord::Base external_import? || forked? end + def no_import? + import_status == 'none' + end + def external_import? import_url.present? end diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 9f380a382cb..9629c7e1bb9 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -136,7 +136,7 @@ class ProjectTeam end def human_max_access(user_id) - Gitlab::Access.options.key max_member_access(user_id) + Gitlab::Access.options_with_owner.key(max_member_access(user_id)) end # This method assumes project and group members are eager loaded for optimal diff --git a/app/models/repository.rb b/app/models/repository.rb index ba275fd9803..e050bd45254 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -23,13 +23,11 @@ class Repository def raw_repository return nil unless path_with_namespace - @raw_repository ||= begin - repo = Gitlab::Git::Repository.new(path_to_repo) - repo.autocrlf = :input - repo - rescue Gitlab::Git::Repository::NoRepository - nil - end + @raw_repository ||= Gitlab::Git::Repository.new(path_to_repo) + end + + def update_autocrlf_option + raw_repository.autocrlf = :input if raw_repository.autocrlf != :input end # Return absolute path to repository @@ -40,7 +38,12 @@ class Repository end def exists? - raw_repository + return false unless raw_repository + + raw_repository.rugged + true + rescue Gitlab::Git::Repository::NoRepository + false end def empty? @@ -67,7 +70,7 @@ class Repository end def commit(id = 'HEAD') - return nil unless raw_repository + return nil unless exists? commit = Gitlab::Git::Commit.find(raw_repository, id) commit = Commit.new(commit, @project) if commit commit @@ -236,6 +239,19 @@ class Repository end expire_branch_cache(branch_name) + + # This ensures this particular cache is flushed after the first commit to a + # new repository. + expire_emptiness_caches if empty? + end + + # Expires _all_ caches, including those that would normally only be expired + # under specific conditions. + def expire_all_caches! + expire_cache + expire_root_ref_cache + expire_emptiness_caches + expire_has_visible_content_cache end def expire_branch_cache(branch_name = nil) @@ -258,6 +274,14 @@ class Repository @root_ref = nil end + # Expires the cache(s) used to determine if a repository is empty or not. + def expire_emptiness_caches + cache.expire(:empty?) + @empty = nil + + expire_has_visible_content_cache + end + def expire_has_visible_content_cache cache.expire(:has_visible_content?) @has_visible_content = nil @@ -599,6 +623,34 @@ class Repository end end + def revert(user, commit, base_branch, target_branch = nil) + source_sha = find_branch(base_branch).target + target_branch ||= base_branch + args = [commit.id, source_sha] + args << { mainline: 1 } if commit.merge_commit? + + revert_index = rugged.revert_commit(*args) + return false if revert_index.conflicts? + + tree_id = revert_index.write_tree(rugged) + return false unless diff_exists?(source_sha, tree_id) + + commit_with_hooks(user, target_branch) do |ref| + committer = user_to_committer(user) + source_sha = Rugged::Commit.create(rugged, + message: commit.revert_message, + author: committer, + committer: committer, + tree: tree_id, + parents: [rugged.lookup(source_sha)], + update_ref: ref) + end + end + + def diff_exists?(sha1, sha2) + rugged.diff(sha1, sha2).size > 0 + end + def merged_to_root_ref?(branch_name) branch_commit = commit(branch_name) root_ref_commit = commit(root_ref) @@ -611,6 +663,8 @@ class Repository end def merge_base(first_commit_id, second_commit_id) + first_commit_id = commit(first_commit_id).try(:id) || first_commit_id + second_commit_id = commit(second_commit_id).try(:id) || second_commit_id rugged.merge_base(first_commit_id, second_commit_id) rescue Rugged::ReferenceError nil @@ -674,12 +728,15 @@ class Repository end def commit_with_hooks(current_user, branch) + update_autocrlf_option + oldrev = Gitlab::Git::BLANK_SHA ref = Gitlab::Git::BRANCH_REF_PREFIX + branch + target_branch = find_branch(branch) was_empty = empty? - unless was_empty - oldrev = find_branch(branch).target + if !was_empty && target_branch + oldrev = target_branch.target end with_tmp_ref(oldrev) do |tmp_ref| @@ -691,7 +748,7 @@ class Repository end GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do - if was_empty + if was_empty || !target_branch # Create branch rugged.references.create(ref, newrev) else @@ -706,6 +763,8 @@ class Repository end end end + + newrev end end diff --git a/app/models/todo.rb b/app/models/todo.rb new file mode 100644 index 00000000000..34d71c1b0d3 --- /dev/null +++ b/app/models/todo.rb @@ -0,0 +1,53 @@ +# == Schema Information +# +# Table name: todos +# +# id :integer not null, primary key +# user_id :integer not null +# project_id :integer not null +# target_id :integer not null +# target_type :string not null +# author_id :integer +# note_id :integer +# action :integer not null +# state :string not null +# created_at :datetime +# updated_at :datetime +# + +class Todo < ActiveRecord::Base + ASSIGNED = 1 + MENTIONED = 2 + + belongs_to :author, class_name: "User" + belongs_to :note + belongs_to :project + belongs_to :target, polymorphic: true, touch: true + belongs_to :user + + delegate :name, :email, to: :author, prefix: true, allow_nil: true + + validates :action, :project, :target, :user, presence: true + + default_scope { reorder(id: :desc) } + + scope :pending, -> { with_state(:pending) } + scope :done, -> { with_state(:done) } + + state_machine :state, initial: :pending do + event :done do + transition pending: :done + end + + state :pending + state :done + end + + def body + if note.present? + note.note + else + target.title + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 9fe94b13e52..02ff2456f2b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -140,7 +140,7 @@ class User < ActiveRecord::Base has_one :abuse_report, dependent: :destroy has_many :spam_logs, dependent: :destroy has_many :builds, dependent: :nullify, class_name: 'Ci::Build' - + has_many :todos, dependent: :destroy # # Validations diff --git a/app/services/archive_repository_service.rb b/app/services/archive_repository_service.rb deleted file mode 100644 index 2160bf13e6d..00000000000 --- a/app/services/archive_repository_service.rb +++ /dev/null @@ -1,23 +0,0 @@ -class ArchiveRepositoryService - attr_reader :project, :ref, :format - - def initialize(project, ref, format) - format ||= 'tar.gz' - @project, @ref, @format = project, ref, format.downcase - end - - def execute(options = {}) - RepositoryArchiveCacheWorker.perform_async - - metadata = project.repository.archive_metadata(ref, storage_path, format) - raise "Repository or ref not found" if metadata.empty? - - metadata - end - - private - - def storage_path - Gitlab.config.gitlab.repository_downloads_path - end -end diff --git a/app/services/base_service.rb b/app/services/base_service.rb index b48ca67d4d2..8563633816c 100644 --- a/app/services/base_service.rb +++ b/app/services/base_service.rb @@ -23,6 +23,10 @@ class BaseService EventCreateService.new end + def todo_service + TodoService.new + end + def log_info(message) Gitlab::AppLogger.info message end diff --git a/app/services/ci/create_builds_service.rb b/app/services/ci/create_builds_service.rb index ad901f2da5d..002f7ba1278 100644 --- a/app/services/ci/create_builds_service.rb +++ b/app/services/ci/create_builds_service.rb @@ -34,6 +34,7 @@ module Ci build = commit.builds.create!(build_attrs) build.execute_hooks + build end end end diff --git a/app/services/commits/revert_service.rb b/app/services/commits/revert_service.rb new file mode 100644 index 00000000000..43d1c766e35 --- /dev/null +++ b/app/services/commits/revert_service.rb @@ -0,0 +1,58 @@ +module Commits + class RevertService < ::BaseService + class ValidationError < StandardError; end + class ReversionError < StandardError; end + + def execute + @source_project = params[:source_project] || @project + @target_branch = params[:target_branch] + @commit = params[:commit] + @create_merge_request = params[:create_merge_request].present? + + validate and commit + rescue Repository::CommitError, Gitlab::Git::Repository::InvalidBlobName, GitHooksService::PreReceiveError, + ValidationError, ReversionError => ex + error(ex.message) + end + + def commit + revert_into = @create_merge_request ? @commit.revert_branch_name : @target_branch + + if @create_merge_request + # Temporary branch exists and contains the revert commit + return success if repository.find_branch(revert_into) + + create_target_branch + end + + unless repository.revert(current_user, @commit, revert_into) + error_msg = "Sorry, we cannot revert this #{params[:revert_type_title]} automatically. + It may have already been reverted, or a more recent commit may have updated some of its content." + raise ReversionError, error_msg + end + + success + end + + private + + def create_target_branch + result = CreateBranchService.new(@project, current_user) + .execute(@commit.revert_branch_name, @target_branch, source_project: @source_project) + + if result[:status] == :error + raise ReversionError, "There was an error creating the source branch: #{result[:message]}" + end + end + + def validate + allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(@target_branch) + + unless allowed + raise_error('You are not allowed to push into this branch') + end + + true + end + end +end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index e3bf14966c8..a1711d234ff 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -1,10 +1,10 @@ -class GitPushService - attr_accessor :project, :user, :push_data, :push_commits +class GitPushService < BaseService + attr_accessor :push_data, :push_commits include Gitlab::CurrentSettings include Gitlab::Access # This method will be called after each git update - # and only if the provided user and project is present in GitLab. + # and only if the provided user and project are present in GitLab. # # All callbacks for post receive action should be placed here. # @@ -15,67 +15,67 @@ class GitPushService # 4. Executes the project's web hooks # 5. Executes the project's services # - def execute(project, user, oldrev, newrev, ref) - @project, @user = project, user - - branch_name = Gitlab::Git.ref_name(ref) - - project.repository.expire_cache(branch_name) - - if push_remove_branch?(ref, newrev) - project.repository.expire_has_visible_content_cache + def execute + @project.repository.expire_cache(branch_name) + if push_remove_branch? + @project.repository.expire_has_visible_content_cache @push_commits = [] - elsif push_to_new_branch?(ref, oldrev) - project.repository.expire_has_visible_content_cache + elsif push_to_new_branch? + @project.repository.expire_has_visible_content_cache # Re-find the pushed commits. - if is_default_branch?(ref) + if is_default_branch? # Initial push to the default branch. Take the full history of that branch as "newly pushed". - @push_commits = project.repository.commits(newrev) - - # Ensure HEAD points to the default branch in case it is not master - project.change_head(branch_name) - - # Set protection on the default branch if configured - if (current_application_settings.default_branch_protection != PROTECTION_NONE) - developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false - project.protected_branches.create({ name: project.default_branch, developers_can_push: developers_can_push }) - end + process_default_branch else # Use the pushed commits that aren't reachable by the default branch # as a heuristic. This may include more commits than are actually pushed, but # that shouldn't matter because we check for existing cross-references later. - @push_commits = project.repository.commits_between(project.default_branch, newrev) + @push_commits = @project.repository.commits_between(@project.default_branch, params[:newrev]) # don't process commits for the initial push to the default branch - process_commit_messages(ref) + process_commit_messages end - elsif push_to_existing_branch?(ref, oldrev) + elsif push_to_existing_branch? # Collect data for this git push - @push_commits = project.repository.commits_between(oldrev, newrev) - process_commit_messages(ref) + @push_commits = @project.repository.commits_between(params[:oldrev], params[:newrev]) + process_commit_messages end - # Update merge requests that may be affected by this push. A new branch # could cause the last commit of a merge request to change. - project.update_merge_requests(oldrev, newrev, ref, @user) + update_merge_requests + end - @push_data = build_push_data(oldrev, newrev, ref) + protected - EventCreateService.new.push(project, user, @push_data) - project.execute_hooks(@push_data.dup, :push_hooks) - project.execute_services(@push_data.dup, :push_hooks) - CreateCommitBuildsService.new.execute(project, @user, @push_data) - ProjectCacheWorker.perform_async(project.id) + def update_merge_requests + @project.update_merge_requests(params[:oldrev], params[:newrev], params[:ref], current_user) + + EventCreateService.new.push(@project, current_user, build_push_data) + @project.execute_hooks(build_push_data.dup, :push_hooks) + @project.execute_services(build_push_data.dup, :push_hooks) + CreateCommitBuildsService.new.execute(@project, current_user, build_push_data) + ProjectCacheWorker.perform_async(@project.id) end - protected + def process_default_branch + @push_commits = project.repository.commits(params[:newrev]) + + # Ensure HEAD points to the default branch in case it is not master + project.change_head(branch_name) + + # Set protection on the default branch if configured + if (current_application_settings.default_branch_protection != PROTECTION_NONE) + developers_can_push = current_application_settings.default_branch_protection == PROTECTION_DEV_CAN_PUSH ? true : false + @project.protected_branches.create({ name: @project.default_branch, developers_can_push: developers_can_push }) + end + end # Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched, # close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables. - def process_commit_messages(ref) - is_default_branch = is_default_branch?(ref) + def process_commit_messages + is_default_branch = is_default_branch? authors = Hash.new do |hash, commit| email = commit.author_email @@ -94,7 +94,7 @@ class GitPushService # Close issues if these commits were pushed to the project's default branch and the commit message matches the # closing regex. Exclude any mentioned Issues from cross-referencing even if the commits are being pushed to # a different branch. - closed_issues = commit.closes_issues(user) + closed_issues = commit.closes_issues(current_user) closed_issues.each do |issue| Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit) end @@ -104,34 +104,38 @@ class GitPushService end end - def build_push_data(oldrev, newrev, ref) - Gitlab::PushDataBuilder. - build(project, user, oldrev, newrev, ref, push_commits) + def build_push_data + @push_data ||= Gitlab::PushDataBuilder. + build(@project, current_user, params[:oldrev], params[:newrev], params[:ref], push_commits) end - def push_to_existing_branch?(ref, oldrev) + def push_to_existing_branch? # Return if this is not a push to a branch (e.g. new commits) - Gitlab::Git.branch_ref?(ref) && !Gitlab::Git.blank_ref?(oldrev) + Gitlab::Git.branch_ref?(params[:ref]) && !Gitlab::Git.blank_ref?(params[:oldrev]) end - def push_to_new_branch?(ref, oldrev) - Gitlab::Git.branch_ref?(ref) && Gitlab::Git.blank_ref?(oldrev) + def push_to_new_branch? + Gitlab::Git.branch_ref?(params[:ref]) && Gitlab::Git.blank_ref?(params[:oldrev]) end - def push_remove_branch?(ref, newrev) - Gitlab::Git.branch_ref?(ref) && Gitlab::Git.blank_ref?(newrev) + def push_remove_branch? + Gitlab::Git.branch_ref?(params[:ref]) && Gitlab::Git.blank_ref?(params[:newrev]) end - def push_to_branch?(ref) - Gitlab::Git.branch_ref?(ref) + def push_to_branch? + Gitlab::Git.branch_ref?(params[:ref]) end - def is_default_branch?(ref) - Gitlab::Git.branch_ref?(ref) && - (Gitlab::Git.ref_name(ref) == project.default_branch || project.default_branch.nil?) + def is_default_branch? + Gitlab::Git.branch_ref?(params[:ref]) && + (Gitlab::Git.ref_name(params[:ref]) == project.default_branch || project.default_branch.nil?) end def commit_user(commit) - commit.author || user + commit.author || current_user + end + + def branch_name + @branch_name ||= Gitlab::Git.ref_name(params[:ref]) end end diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index 2556f06e2d3..ca87dca4a70 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -54,7 +54,7 @@ class IssuableBaseService < BaseService if params.present? && issuable.update_attributes(params.merge(updated_by: current_user)) issuable.reset_events_cache handle_common_system_notes(issuable, old_labels: old_labels) - handle_changes(issuable) + handle_changes(issuable, old_labels: old_labels) issuable.create_new_cross_references!(current_user) execute_hooks(issuable, 'update') end @@ -71,6 +71,19 @@ class IssuableBaseService < BaseService end end + def has_changes?(issuable, options = {}) + valid_attrs = [:title, :description, :assignee_id, :milestone_id, :target_branch] + + attrs_changed = valid_attrs.any? do |attr| + issuable.previous_changes.include?(attr.to_s) + end + + old_labels = options[:old_labels] + labels_changed = old_labels && issuable.labels != old_labels + + attrs_changed || labels_changed + end + def handle_common_system_notes(issuable, options = {}) if issuable.previous_changes.include?('title') create_title_change_note(issuable, issuable.previous_changes['title'].first) diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb index a1a20e47681..78254b49af3 100644 --- a/app/services/issues/close_service.rb +++ b/app/services/issues/close_service.rb @@ -3,6 +3,7 @@ module Issues def execute(issue, commit = nil) if project.jira_tracker? && project.jira_service.active project.jira_service.execute(commit, issue) + todo_service.close_issue(issue, current_user) return issue end @@ -10,6 +11,7 @@ module Issues event_service.close_issue(issue, current_user) create_note(issue, commit) notification_service.close_issue(issue, current_user) + todo_service.close_issue(issue, current_user) execute_hooks(issue, 'close') end diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb index bcb380d3215..10787e8873c 100644 --- a/app/services/issues/create_service.rb +++ b/app/services/issues/create_service.rb @@ -9,6 +9,7 @@ module Issues if issue.save issue.update_attributes(label_ids: label_params) notification_service.new_issue(issue, current_user) + todo_service.new_issue(issue, current_user) event_service.open_issue(issue, current_user) issue.create_cross_references!(current_user) execute_hooks(issue, 'open') diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index a55a04dd5e0..51ef9dfe610 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -4,7 +4,16 @@ module Issues update(issue) end - def handle_changes(issue) + def handle_changes(issue, options = {}) + if has_changes?(issue, options) + todo_service.mark_pending_todos_as_done(issue, current_user) + end + + if issue.previous_changes.include?('title') || + issue.previous_changes.include?('description') + todo_service.update_issue(issue, current_user) + end + if issue.previous_changes.include?('milestone_id') create_milestone_note(issue) end @@ -12,6 +21,7 @@ module Issues if issue.previous_changes.include?('assignee_id') create_assignee_note(issue) notification_service.reassigned_issue(issue, current_user) + todo_service.reassigned_issue(issue, current_user) end end diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index a9b29f9654d..c0700d953dd 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -56,7 +56,7 @@ module MergeRequests if commits && commits.count == 1 commit = commits.first merge_request.title = commit.title - merge_request.description = commit.description.try(:strip) + merge_request.description ||= commit.description.try(:strip) else merge_request.title = merge_request.source_branch.titleize.humanize end diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb index 47454f9f0c2..27ee81fe3e7 100644 --- a/app/services/merge_requests/close_service.rb +++ b/app/services/merge_requests/close_service.rb @@ -9,6 +9,7 @@ module MergeRequests event_service.close_mr(merge_request, current_user) create_note(merge_request) notification_service.close_mr(merge_request, current_user) + todo_service.close_merge_request(merge_request, current_user) execute_hooks(merge_request, 'close') end diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index 009d5a6867e..33609d01f20 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -2,7 +2,7 @@ module MergeRequests class CreateService < MergeRequests::BaseService def execute # @project is used to determine whether the user can set the merge request's - # assignee, milestone and labels. Whether they can depends on their + # assignee, milestone and labels. Whether they can depends on their # permissions on the target project. source_project = @project @project = Project.find(params[:target_project_id]) if params[:target_project_id] @@ -18,6 +18,7 @@ module MergeRequests merge_request.update_attributes(label_ids: label_params) event_service.open_mr(merge_request, current_user) notification_service.new_merge_request(merge_request, current_user) + todo_service.new_merge_request(merge_request, current_user) merge_request.create_cross_references!(current_user) execute_hooks(merge_request) end diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb index e8bef250d8b..9a58383b398 100644 --- a/app/services/merge_requests/merge_service.rb +++ b/app/services/merge_requests/merge_service.rb @@ -34,7 +34,8 @@ module MergeRequests committer: committer } - repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options) + commit_id = repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options) + merge_request.update(merge_commit_sha: commit_id) rescue StandardError => e merge_request.update(merge_error: "Something went wrong during merge") Rails.logger.error(e.message) diff --git a/app/services/merge_requests/merge_when_build_succeeds_service.rb b/app/services/merge_requests/merge_when_build_succeeds_service.rb index 5cf7404a493..d6af12f9739 100644 --- a/app/services/merge_requests/merge_when_build_succeeds_service.rb +++ b/app/services/merge_requests/merge_when_build_succeeds_service.rb @@ -19,15 +19,19 @@ module MergeRequests end # Triggers the automatic merge of merge_request once the build succeeds - def trigger(build) - merge_requests = merge_request_from(build) + def trigger(commit_status) + merge_requests = merge_request_from(commit_status) merge_requests.each do |merge_request| next unless merge_request.merge_when_build_succeeds? + next unless merge_request.mergeable? - if merge_request.ci_commit && merge_request.ci_commit.success? && merge_request.mergeable? - MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params) - end + ci_commit = merge_request.ci_commit + next unless ci_commit + next unless ci_commit.sha == commit_status.sha + next unless ci_commit.success? + + MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params) end end @@ -45,9 +49,16 @@ module MergeRequests private - def merge_request_from(build) - merge_requests = @project.origin_merge_requests.opened.where(source_branch: build.ref).to_a - merge_requests += @project.fork_merge_requests.opened.where(source_branch: build.ref).to_a + def merge_request_from(commit_status) + branches = commit_status.ref + + # This is for ref-less builds + branches ||= @project.repository.branch_names_contains(commit_status.sha) + + return [] if branches.blank? + + merge_requests = @project.origin_merge_requests.opened.where(source_branch: branches).to_a + merge_requests += @project.fork_merge_requests.opened.where(source_branch: branches).to_a merge_requests.uniq.select(&:source_project) end diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index 5ff2cc03dda..6319ad805b6 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -14,7 +14,16 @@ module MergeRequests update(merge_request) end - def handle_changes(merge_request) + def handle_changes(merge_request, options = {}) + if has_changes?(merge_request, options) + todo_service.mark_pending_todos_as_done(merge_request, current_user) + end + + if merge_request.previous_changes.include?('title') || + merge_request.previous_changes.include?('description') + todo_service.update_merge_request(merge_request, current_user) + end + if merge_request.previous_changes.include?('target_branch') create_branch_change_note(merge_request, 'target', merge_request.previous_changes['target_branch'].first, @@ -28,6 +37,7 @@ module MergeRequests if merge_request.previous_changes.include?('assignee_id') create_assignee_note(merge_request) notification_service.reassigned_merge_request(merge_request, current_user) + todo_service.reassigned_merge_request(merge_request, current_user) end if merge_request.previous_changes.include?('target_branch') || diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index 8d9661167b5..b970439b921 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -8,6 +8,7 @@ module Notes if note.save # Finish the harder work in the background NewNoteWorker.perform_in(2.seconds, note.id, params) + TodoService.new.new_note(note, current_user) end note diff --git a/app/services/notes/post_process_service.rb b/app/services/notes/post_process_service.rb index f37d3c50cdd..e818f58d13c 100644 --- a/app/services/notes/post_process_service.rb +++ b/app/services/notes/post_process_service.rb @@ -1,6 +1,5 @@ module Notes class PostProcessService - attr_accessor :note def initialize(note) @@ -25,6 +24,5 @@ module Notes @note.project.execute_hooks(note_data, :note_hooks) @note.project.execute_services(note_data, :note_hooks) end - end end diff --git a/app/services/notes/update_service.rb b/app/services/notes/update_service.rb index 72e2f78008d..1361b1e0300 100644 --- a/app/services/notes/update_service.rb +++ b/app/services/notes/update_service.rb @@ -7,6 +7,10 @@ module Notes note.create_new_cross_references!(current_user) note.reset_events_cache + if note.previous_changes.include?('note') + TodoService.new.update_note(note, current_user) + end + note end end diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index 294157b4f0e..f4dcb142850 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -16,11 +16,15 @@ module Projects return false unless can?(current_user, :remove_project, project) project.team.truncate - project.repository.expire_cache unless project.empty_repo? repo_path = project.path_with_namespace wiki_path = repo_path + '.wiki' + # Flush the cache for both repositories. This has to be done _before_ + # removing the physical repositories as some expiration code depends on + # Git data (e.g. a list of branch names). + flush_caches(project, wiki_path) + Project.transaction do project.destroy! @@ -70,5 +74,13 @@ module Projects def removal_path(path) "#{path}+#{project.id}#{DELETED_FLAG}" end + + def flush_caches(project, wiki_path) + project.repository.expire_all_caches! if project.repository.exists? + + wiki_repo = Repository.new(wiki_path, project) + + wiki_repo.expire_all_caches! if wiki_repo.exists? + end end end diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb new file mode 100644 index 00000000000..dc270602ebc --- /dev/null +++ b/app/services/todo_service.rb @@ -0,0 +1,170 @@ +# TodoService class +# +# Used for creating todos after certain user actions +# +# Ex. +# TodoService.new.new_issue(issue, current_user) +# +class TodoService + # When create an issue we should: + # + # * create a todo for assignee if issue is assigned + # * create a todo for each mentioned user on issue + # + def new_issue(issue, current_user) + new_issuable(issue, current_user) + end + + # When update an issue we should: + # + # * mark all pending todos related to the issue for the current user as done + # + def update_issue(issue, current_user) + create_mention_todos(issue.project, issue, current_user) + end + + # When close an issue we should: + # + # * mark all pending todos related to the target for the current user as done + # + def close_issue(issue, current_user) + mark_pending_todos_as_done(issue, current_user) + end + + # When we reassign an issue we should: + # + # * create a pending todo for new assignee if issue is assigned + # + def reassigned_issue(issue, current_user) + create_assignment_todo(issue, current_user) + end + + # When create a merge request we should: + # + # * creates a pending todo for assignee if merge request is assigned + # * create a todo for each mentioned user on merge request + # + def new_merge_request(merge_request, current_user) + new_issuable(merge_request, current_user) + end + + # When update a merge request we should: + # + # * create a todo for each mentioned user on merge request + # + def update_merge_request(merge_request, current_user) + create_mention_todos(merge_request.project, merge_request, current_user) + end + + # When close a merge request we should: + # + # * mark all pending todos related to the target for the current user as done + # + def close_merge_request(merge_request, current_user) + mark_pending_todos_as_done(merge_request, current_user) + end + + # When we reassign a merge request we should: + # + # * creates a pending todo for new assignee if merge request is assigned + # + def reassigned_merge_request(merge_request, current_user) + create_assignment_todo(merge_request, current_user) + end + + # When merge a merge request we should: + # + # * mark all pending todos related to the target for the current user as done + # + def merge_merge_request(merge_request, current_user) + mark_pending_todos_as_done(merge_request, current_user) + end + + # When create a note we should: + # + # * mark all pending todos related to the noteable for the note author as done + # * create a todo for each mentioned user on note + # + def new_note(note, current_user) + handle_note(note, current_user) + end + + # When update a note we should: + # + # * mark all pending todos related to the noteable for the current user as done + # * create a todo for each new user mentioned on note + # + def update_note(note, current_user) + handle_note(note, current_user) + end + + # When marking pending todos as done we should: + # + # * mark all pending todos related to the target for the current user as done + # + def mark_pending_todos_as_done(target, user) + pending_todos(user, target.project, target).update_all(state: :done) + end + + private + + def create_todos(project, target, author, users, action, note = nil) + Array(users).each do |user| + next if pending_todos(user, project, target).exists? + + Todo.create( + project: project, + user_id: user.id, + author_id: author.id, + target_id: target.id, + target_type: target.class.name, + action: action, + note: note + ) + end + end + + def new_issuable(issuable, author) + create_assignment_todo(issuable, author) + create_mention_todos(issuable.project, issuable, author) + end + + def handle_note(note, author) + # Skip system notes, like status changes and cross-references + return if note.system + + project = note.project + target = note.noteable + + mark_pending_todos_as_done(target, author) + create_mention_todos(project, target, author, note) + end + + def create_assignment_todo(issuable, author) + if issuable.assignee && issuable.assignee != author + create_todos(issuable.project, issuable, author, issuable.assignee, Todo::ASSIGNED) + end + end + + def create_mention_todos(project, issuable, author, note = nil) + mentioned_users = filter_mentioned_users(project, note || issuable, author) + create_todos(project, issuable, author, mentioned_users, Todo::MENTIONED, note) + end + + def filter_mentioned_users(project, target, author) + mentioned_users = target.mentioned_users.select do |user| + user.can?(:read_project, project) + end + + mentioned_users.delete(author) + mentioned_users.uniq + end + + def pending_todos(user, project, target) + user.todos.pending.where( + project_id: project.id, + target_id: target.id, + target_type: target.class.name + ) + end +end diff --git a/app/views/admin/labels/_form.html.haml b/app/views/admin/labels/_form.html.haml index eaa94ed9e36..8c6b389bf15 100644 --- a/app/views/admin/labels/_form.html.haml +++ b/app/views/admin/labels/_form.html.haml @@ -12,6 +12,10 @@ .col-sm-10 = f.text_field :title, class: "form-control", required: true .form-group + = f.label :description, class: 'control-label' + .col-sm-10 + = f.text_field :description, class: "form-control js-quick-submit" + .form-group = f.label :color, "Background color", class: 'control-label' .col-sm-10 .input-group diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml index e3ccbf6c3a8..5736a301910 100644 --- a/app/views/admin/labels/_label.html.haml +++ b/app/views/admin/labels/_label.html.haml @@ -1,5 +1,7 @@ %li{id: dom_id(label)} - = render_colored_label(label) - .pull-right - = link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm' - = link_to 'Delete', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Delete this label? Are you sure?"} + .label-row + = render_colored_label(label) + = markdown(label.description, pipeline: :single_line) + .pull-right + = link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm' + = link_to 'Delete', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Delete this label? Are you sure?"} diff --git a/app/views/dashboard/projects/_zero_authorized_projects.html.haml b/app/views/dashboard/projects/_zero_authorized_projects.html.haml index 4e7d6639727..c3efa7727b1 100644 --- a/app/views/dashboard/projects/_zero_authorized_projects.html.haml +++ b/app/views/dashboard/projects/_zero_authorized_projects.html.haml @@ -11,7 +11,7 @@ %br - if current_user.can_create_project? You can create up to - %strong= pluralize(current_user.projects_limit, "project") + "." + %strong= pluralize(number_with_delimiter(current_user.projects_limit), "project") + "." - else If you are added to a project, it will be displayed here. @@ -44,7 +44,7 @@ .dashboard-intro-text %p.slead There are - %strong= publicish_project_count + %strong= number_with_delimiter(publicish_project_count) public projects on this server. %br Public projects are an easy way to allow everyone to have read-only access. diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml new file mode 100644 index 00000000000..6975f6ed0db --- /dev/null +++ b/app/views/dashboard/todos/_todo.html.haml @@ -0,0 +1,21 @@ +%li{class: "todo todo-#{todo.done? ? 'done' : 'pending'}", id: dom_id(todo) } + .todo-item{class: 'todo-block'} + = image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:'' + + .todo-title + %span.author_name + = link_to_author todo + %span.todo_label + = todo_action_name(todo) + = todo_target_link(todo) + + · #{time_ago_with_tooltip(todo.created_at)} + + - if todo.pending? + .todo-actions.pull-right + = link_to 'Done', [:dashboard, todo], method: :delete, class: 'btn' + + .todo-body + .todo-note + .md + = event_note(todo.body, project: todo.project) diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml new file mode 100644 index 00000000000..946d7df3933 --- /dev/null +++ b/app/views/dashboard/todos/index.html.haml @@ -0,0 +1,62 @@ +- page_title "Todos" +- header_title "Todos", dashboard_todos_path + +.top-area + %ul.nav-links + %li{class: ('active' if params[:state].blank? || params[:state] == 'pending')} + = link_to todos_filter_path(state: 'pending') do + %span + To do + %span{class: 'badge'} + = todos_pending_count + %li{class: ('active' if params[:state] == 'done')} + = link_to todos_filter_path(state: 'done') do + %span + Done + %span{class: 'badge'} + = todos_done_count + + .nav-controls + - if @todos.any?(&:pending?) + = link_to 'Mark all as done', destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn', method: :delete + +.todos-filters + .gray-content-block.second-block + = form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form' do + .filter-item.inline + = select_tag('project_id', todo_projects_options, + class: 'select2 trigger-submit', include_blank: true, + data: {placeholder: 'Project'}) + .filter-item.inline + = users_select_tag(:author_id, selected: params[:author_id], + placeholder: 'Author', class: 'trigger-submit', any_user: "Any Author", first_user: true, current_user: true) + .filter-item.inline + = select_tag('type', todo_types_options, + class: 'select2 trigger-submit', include_blank: true, + data: {placeholder: 'Type'}) + .filter-item.inline.actions-filter + = select_tag('action_id', todo_actions_options, + class: 'select2 trigger-submit', include_blank: true, + data: {placeholder: 'Action'}) + +.prepend-top-default + - if @todos.any? + - @todos.group_by(&:project).each do |group| + .panel.panel-default.panel-small + - project = group[0] + .panel-heading + = link_to project.name_with_namespace, namespace_project_path(project.namespace, project) + + %ul.well-list.todos-list + = render group[1] + = paginate @todos, theme: "gitlab" + - else + .nothing-here-block You're all done! + +:javascript + new UsersSelect(); + + $('form.filter-form').on('submit', function (event) { + event.preventDefault(); + Turbolinks.visit(this.action + '&' + $(this).serialize()); + }); diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 38ca4f91c4d..79cdbac1f37 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -44,6 +44,7 @@ = favicon_link_tag 'touch-icon-ipad.png', rel: 'apple-touch-icon', sizes: '76x76' = favicon_link_tag 'touch-icon-iphone-retina.png', rel: 'apple-touch-icon', sizes: '120x120' = favicon_link_tag 'touch-icon-ipad-retina.png', rel: 'apple-touch-icon', sizes: '152x152' + %link{rel: 'mask-icon', href: image_path('logo.svg'), color: 'rgb(226, 67, 41)'} -# Windows 8 pinned site tile %meta{name: 'msapplication-TileImage', content: image_path('msapplication-tile.png')} diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index fcb6b835a7e..4781ff23507 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -21,6 +21,10 @@ %li = link_to admin_root_path, title: 'Admin Area', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = icon('wrench fw') + %li + = link_to dashboard_todos_path, title: 'Todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do + %span.badge.todos-pending-count + = todos_pending_count - if current_user.can_create_project? %li = link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do @@ -39,4 +43,4 @@ = render 'shared/outdated_browser' - if @project && !@project.empty_repo? :javascript - var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}";
\ No newline at end of file + var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}"; diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index 106abd24a56..db0cf393922 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -4,6 +4,12 @@ = icon('home fw') %span Projects + = nav_link(controller: :todos) do + = link_to dashboard_todos_path, title: 'Todos' do + = icon('bell fw') + %span + Todos + %span.count= number_with_delimiter(todos_pending_count) = nav_link(path: 'dashboard#activity') do = link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do = icon('dashboard fw') @@ -25,12 +31,12 @@ %span Issues %span.count= number_with_delimiter(current_user.assigned_issues.opened.count) - = nav_link(path: 'dashboard#merge_requests') do - = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do - = icon('tasks fw') - %span - Merge Requests - %span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count) + = nav_link(path: 'dashboard#merge_requests') do + = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do + = icon('tasks fw') + %span + Merge Requests + %span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count) = nav_link(controller: :snippets) do = link_to dashboard_snippets_path, title: 'Snippets' do = icon('clipboard fw') diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 298c6664997..b45df44f270 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -3,7 +3,12 @@ .project-identicon-holder = project_icon(@project, alt: '', class: 'project-avatar avatar s90') .project-home-desc - %h1= @project.name + %h1 + = @project.name + %span.visibility-icon.has_tooltip{data: { container: 'body' }, + title: "#{visibility_level_label(@project.visibility_level)} - #{project_visibility_level_description(@project.visibility_level)}"} + = visibility_level_icon(@project.visibility_level, fw: false) + - if @project.description.present? = markdown(@project.description, pipeline: :description) @@ -12,10 +17,6 @@ Forked from = link_to project_path(forked_from_project) do = forked_from_project.namespace.try(:name) - .cover-controls.left - .visibility-level-label.has_tooltip{title: project_visibility_level_description(@project.visibility_level), data: { container: 'body' } } - = visibility_level_icon(@project.visibility_level, fw: false) - = visibility_level_label(@project.visibility_level) .cover-controls - if current_user diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index eb6fbfaffa0..5f9a92ff93f 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -3,7 +3,7 @@ %h3.page-title Blame view -#tree-holder.tree-holder +#blob-content-holder.tree-holder .file-holder .file-title = blob_icon @blob.mode, @blob.name @@ -33,7 +33,9 @@ %td.line-numbers - line_count = blame_group[:lines].count - (current_line...(current_line + line_count)).each do |i| - %a.diff-line-num= i + %a.diff-line-num{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i} + = icon("link") + = i \ - current_line += line_count %td.lines diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index 2c5b8dc4356..3ffc3fcb7ac 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -32,14 +32,4 @@ = number_to_human_size(blob_size(blob)) .file-actions.hidden-xs = render "actions" - - if blob.lfs_pointer? - = render "download", blob: blob - - elsif blob.text? - - if blob_svg?(blob) - = render "image", blob: sanitize_svg(blob) - - else - = render "text", blob: blob - - elsif blob.image? - = render "image", blob: blob - - else - = render "download", blob: blob + = render blob, blob: blob diff --git a/app/views/projects/blob/_image.html.haml b/app/views/projects/blob/_image.html.haml index 51fa91b08e4..3c11b97921f 100644 --- a/app/views/projects/blob/_image.html.haml +++ b/app/views/projects/blob/_image.html.haml @@ -1,2 +1,9 @@ .file-content.image_file - %img{ src: namespace_project_raw_path(@project.namespace, @project, @id)} + - if blob.svg? + - # We need to scrub SVG but we cannot do so in the RawController: it would + - # be wrong/strange if RawController modified the data. + - blob.load_all_data!(@repository) + - blob = sanitize_svg(blob) + %img{src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}"} + - else + %img{src: namespace_project_raw_path(@project.namespace, @project, @id)} diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index ca1441a20d8..8eec78a557c 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -76,10 +76,16 @@ = link_to '#down-build-trace', class: 'btn' do %i.fa.fa-angle-down - %pre.trace#build-trace - %code.bash - = preserve do - = raw @build.trace_html + - if @build.erased? + .erased.alert.alert-warning + - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by + Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)} + - else + %pre.trace#build-trace + %code.bash + = preserve do + = raw @build.trace_html + %div#down-build-trace .col-md-3 @@ -94,37 +100,55 @@ %h4.title Build artifacts .center .btn-group{ role: :group } - = link_to "Download", @build.artifacts_download_url, class: 'btn btn-sm btn-primary' + = link_to @build.artifacts_download_url, class: 'btn btn-sm btn-primary' do + = icon('download') + Download + - if @build.artifacts_metadata? - = link_to "Browse", @build.artifacts_browse_url, class: 'btn btn-sm btn-primary' + = link_to @build.artifacts_browse_url, class: 'btn btn-sm btn-primary' do + = icon('folder-open') + Browse .build-widget %h4.title Build ##{@build.id} - if can?(current_user, :update_build, @project) - .pull-right - - if @build.cancel_url - = link_to "Cancel", @build.cancel_url, class: 'btn btn-sm btn-danger', method: :post - - elsif @build.retry_url - = link_to "Retry", @build.retry_url, class: 'btn btn-sm btn-primary', method: :post - - - if @build.duration + .center + .btn-group{ role: :group } + - if @build.cancel_url + = link_to "Cancel", @build.cancel_url, class: 'btn btn-sm btn-danger', method: :post + - elsif @build.retry_url + = link_to "Retry", @build.retry_url, class: 'btn btn-sm btn-primary', method: :post + + - if @build.erasable? + = link_to erase_namespace_project_build_path(@project.namespace, @project, @build), + class: 'btn btn-sm btn-warning', method: :post, + data: { confirm: 'Are you sure you want to erase this build?' } do + = icon('eraser') + Erase + + .clearfix + - if @build.duration + %p + %span.attr-name Duration: + #{duration_in_words(@build.finished_at, @build.started_at)} %p - %span.attr-name Duration: - #{duration_in_words(@build.finished_at, @build.started_at)} - %p - %span.attr-name Created: - #{time_ago_with_tooltip(@build.created_at)} - - if @build.finished_at + %span.attr-name Created: + #{time_ago_with_tooltip(@build.created_at)} + - if @build.finished_at + %p + %span.attr-name Finished: + #{time_ago_with_tooltip(@build.finished_at)} + - if @build.erased_at + %p + %span.attr-name Erased: + #{time_ago_with_tooltip(@build.erased_at)} %p - %span.attr-name Finished: - #{time_ago_with_tooltip(@build.finished_at)} - %p - %span.attr-name Runner: - - if @build.runner && current_user && current_user.admin - = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id) - - elsif @build.runner - \##{@build.runner.id} + %span.attr-name Runner: + - if @build.runner && current_user && current_user.admin + = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id) + - elsif @build.runner + \##{@build.runner.id} - if @build.trigger_request .build-widget diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml index bbe820b8842..71995fcc487 100644 --- a/app/views/projects/commit/_commit_box.html.haml +++ b/app/views/projects/commit/_commit_box.html.haml @@ -16,6 +16,8 @@ = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-grouped" do = icon('files-o') Browse Files + - unless @commit.has_been_reverted?(current_user) + = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id)) %div %p diff --git a/app/views/projects/commit/_revert.html.haml b/app/views/projects/commit/_revert.html.haml new file mode 100644 index 00000000000..52ca3ed5b14 --- /dev/null +++ b/app/views/projects/commit/_revert.html.haml @@ -0,0 +1,31 @@ +#modal-revert-commit.modal + .modal-dialog + .modal-content + .modal-header + %a.close{href: "#", "data-dismiss" => "modal"} × + %h3.page-title== Revert this #{revert_commit_type(commit)} + .modal-body + = form_tag revert_namespace_project_commit_path(@project.namespace, @project, commit.id), method: :post, remote: false, class: 'form-horizontal js-create-dir-form js-requires-input' do + .form-group.branch + = label_tag 'target_branch', 'Revert in branch', class: 'control-label' + .col-sm-10 + = select_tag "target_branch", grouped_options_refs, class: "select2 select2-sm js-target-branch" + - if can?(current_user, :push_code, @project) + .js-create-merge-request-container + .checkbox + - nonce = SecureRandom.hex + = label_tag "create_merge_request-#{nonce}" do + = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}" + Start a <strong>new merge request</strong> with these changes + - else + = hidden_field_tag 'create_merge_request', 1 + .form-actions + = submit_tag "Revert", class: 'btn btn-create' + = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" + + - unless can?(current_user, :push_code, @project) + .inline.prepend-left-10 + = commit_in_fork_help + +:javascript + new NewCommitForm($('.js-create-dir-form')) diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 05dbe5ebea4..21e186120c3 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -12,3 +12,5 @@ = render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @diff_refs = render "projects/notes/notes_with_form" +- if can_collaborate_with_project? + = render "projects/commit/revert", commit: @commit, title: @commit.title diff --git a/app/views/projects/diffs/_image.html.haml b/app/views/projects/diffs/_image.html.haml index 4fcf7ea0b26..752e92e2e6b 100644 --- a/app/views/projects/diffs/_image.html.haml +++ b/app/views/projects/diffs/_image.html.haml @@ -1,19 +1,19 @@ - diff = diff_file.diff -- file.load_all_data!(@project.repository) +- file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.id, diff.new_path)) +- old_file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.parent_id, diff.old_path)) - if diff.renamed_file || diff.new_file || diff.deleted_file .image %span.wrap .frame{class: image_diff_class(diff)} - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} + %img{src: diff.deleted_file ? old_file_raw_path : file_raw_path} %p.image-info= "#{number_to_human_size file.size}" - else - - old_file.load_all_data!(@project.repository) .image %div.two-up.view %span.wrap .frame.deleted %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.parent_id, diff.old_path))} - %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"} + %img{src: old_file_raw_path} %p.image-info.hide %span.meta-filesize= "#{number_to_human_size old_file.size}" | @@ -25,7 +25,7 @@ %span.wrap .frame.added %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.id, diff.new_path))} - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} + %img{src: file_raw_path} %p.image-info.hide %span.meta-filesize= "#{number_to_human_size file.size}" | @@ -38,10 +38,10 @@ %div.swipe.view.hide .swipe-frame .frame.deleted - %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"} + %img{src: old_file_raw_path} .swipe-wrap .frame.added - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} + %img{src: file_raw_path} %span.swipe-bar %span.top-handle %span.bottom-handle @@ -49,9 +49,9 @@ %div.onion-skin.view.hide .onion-skin-frame .frame.deleted - %img{src: "data:#{old_file.mime_type};base64,#{Base64.encode64(old_file.data)}"} + %img{src: old_file_raw_path} .frame.added - %img{src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} + %img{src: file_raw_path} .controls .transparent .drag-track diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 5e835b10e1f..d75e9ef2a49 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -35,8 +35,8 @@ = render "projects/notes/diff_notes_with_reply", notes: comments, line: raw_diff_lines[index].text - if last_line > 0 - = render "projects/diffs/match_line", {line: "", - line_old: last_line, line_new: last_line, bottom: true, new_file: diff_file.new_file} + = render "projects/diffs/match_line", { line: "", + line_old: last_line, line_new: last_line, bottom: true, new_file: diff_file.new_file } - if diff_file.diff.blank? && diff_file.mode_changed? .file-mode-changed diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index fdcb6987471..042f660077e 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -119,13 +119,13 @@ .col-sm-offset-2.col-sm-10 %p Get recent application code using the following command: .radio - = f.label :build_allow_git_fetch do + = f.label :build_allow_git_fetch_false do = f.radio_button :build_allow_git_fetch, 'false' %strong git clone %br %span.descr Slower but makes sure you have a clean dir before every build .radio - = f.label :build_allow_git_fetch do + = f.label :build_allow_git_fetch_true do = f.radio_button :build_allow_git_fetch, 'true' %strong git fetch %br diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index f9cf4910df3..654d8cd5ed0 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -15,6 +15,17 @@ %li = link_to_member(@project, issue.assignee, name: false, title: "Assigned to :name") + - upvotes, downvotes = issue.upvotes, issue.downvotes + - if upvotes > 0 + %li + = icon('thumbs-up') + = upvotes + + - if downvotes > 0 + %li + = icon('thumbs-down') + = downvotes + - note_count = issue.notes.user.count - if note_count > 0 %li diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index fe977fd700c..69a0e2a0c4d 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -6,16 +6,6 @@ .issue .detail-page-header - .status-box{ class: "status-box-closed #{issue_button_visibility(@issue, false)}"} Closed - .status-box{ class: "status-box-open #{issue_button_visibility(@issue, true)}"} Open - %span.identifier - Issue ##{@issue.iid} - %span.creator - · - opened by #{link_to_member(@project, @issue.author, size: 24)} - · - = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') - .pull-right - if can?(current_user, :create_issue, @project) = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-nr btn-grouped new-issue-link btn-success', title: 'New Issue', id: 'new_issue_link' do @@ -29,6 +19,19 @@ = icon('pencil-square-o') Edit + .pull-left + .status-box{ class: "status-box-closed #{issue_button_visibility(@issue, false)}"} Closed + .status-box{ class: "status-box-open #{issue_button_visibility(@issue, true)}"} Open + + .issue-meta + %span.identifier + Issue ##{@issue.iid} + %span.creator + · + by #{link_to_member(@project, @issue.author, size: 24)} + · + = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') + .issue-details.issuable-details .detail-page-description.content-block %h2.title diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml index a54733883b4..986d8c220db 100644 --- a/app/views/projects/issues/update.js.haml +++ b/app/views/projects/issues/update.js.haml @@ -1,3 +1,3 @@ $('aside.right-sidebar')[0].outerHTML = "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"; $('aside.right-sidebar').effect('highlight'); -new Issue();
\ No newline at end of file +new IssuableContext(); diff --git a/app/views/projects/labels/_form.html.haml b/app/views/projects/labels/_form.html.haml index 5ce2a7b985d..d63d3a3ec20 100644 --- a/app/views/projects/labels/_form.html.haml +++ b/app/views/projects/labels/_form.html.haml @@ -12,6 +12,10 @@ .col-sm-10 = f.text_field :title, class: "form-control js-quick-submit", required: true, autofocus: true .form-group + = f.label :description, class: 'control-label' + .col-sm-10 + = f.text_field :description, class: "form-control js-quick-submit" + .form-group = f.label :color, "Background color", class: 'control-label' .col-sm-10 .input-group diff --git a/app/views/projects/labels/_label.html.haml b/app/views/projects/labels/_label.html.haml index b70a9fc9fe5..5b35acc66c0 100644 --- a/app/views/projects/labels/_label.html.haml +++ b/app/views/projects/labels/_label.html.haml @@ -1,5 +1,6 @@ %li{id: dom_id(label)} - = link_to_label(label) + = render "shared/label_row", label: label + .pull-right %strong.append-right-20 = link_to_label(label) do diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index e25bf917b43..b55f6a2d32a 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -24,6 +24,17 @@ %li = link_to_member(merge_request.source_project, merge_request.assignee, name: false, title: "Assigned to :name") + - upvotes, downvotes = merge_request.upvotes, merge_request.downvotes + - if upvotes > 0 + %li + = icon('thumbs-up') + = upvotes + + - if downvotes > 0 + %li + = icon('thumbs-down') + = downvotes + - note_count = merge_request.mr_and_commit_notes.user.count - if note_count > 0 %li diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index da67645bc2b..648512e5379 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -85,6 +85,8 @@ = spinner = render 'shared/issuable/sidebar', issuable: @merge_request +- if @merge_request.can_be_reverted? + = render "projects/commit/revert", commit: @merge_request.merge_commit, title: @merge_request.title :javascript var merge_request; diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml index 473fbff721b..14ea7b17786 100644 --- a/app/views/projects/merge_requests/show/_mr_title.html.haml +++ b/app/views/projects/merge_requests/show/_mr_title.html.haml @@ -5,7 +5,7 @@ Merge Request ##{@merge_request.iid} %span.creator · - opened by #{link_to_member(@project, @merge_request.author, size: 24)} + by #{link_to_member(@project, @merge_request.author, size: 24)} · = time_ago_with_tooltip(@merge_request.created_at) diff --git a/app/views/projects/merge_requests/update.js.haml b/app/views/projects/merge_requests/update.js.haml index ce5157d69a2..9cce5660e1c 100644 --- a/app/views/projects/merge_requests/update.js.haml +++ b/app/views/projects/merge_requests/update.js.haml @@ -1,3 +1,3 @@ -$('aside.right-sidebar')[0].outerHTML= "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"; -$('aside.right-sidebar').effect('highlight') -merge_request = new MergeRequest(); +$('aside.right-sidebar')[0].outerHTML = "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"; +$('aside.right-sidebar').effect('highlight'); +new IssuableContext(); diff --git a/app/views/projects/merge_requests/widget/_merged.html.haml b/app/views/projects/merge_requests/widget/_merged.html.haml index d1d602eecdc..3abae9f0bf6 100644 --- a/app/views/projects/merge_requests/widget/_merged.html.haml +++ b/app/views/projects/merge_requests/widget/_merged.html.haml @@ -8,20 +8,18 @@ #{time_ago_with_tooltip(@merge_request.merge_event.created_at)} %div - if !@merge_request.source_branch_exists? || (params[:delete_source] == 'true') - The changes were merged into - #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}. - The source branch has been removed. - + %p + The changes were merged into + #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}. + The source branch has been removed. + = render 'projects/merge_requests/widget/merged_buttons' - elsif @merge_request.can_remove_source_branch?(current_user) .remove_source_branch_widget %p The changes were merged into #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}. You can remove the source branch now. - = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-primary btn-sm remove_source_branch" do - %i.fa.fa-times - Remove Source Branch - + = render 'projects/merge_requests/widget/merged_buttons', source_branch_exists: true .remove_source_branch_widget.failed.hide %p Failed to remove source branch '#{@merge_request.source_branch}'. diff --git a/app/views/projects/merge_requests/widget/_merged_buttons.haml b/app/views/projects/merge_requests/widget/_merged_buttons.haml new file mode 100644 index 00000000000..85a3a6ba9e2 --- /dev/null +++ b/app/views/projects/merge_requests/widget/_merged_buttons.haml @@ -0,0 +1,11 @@ +- source_branch_exists = local_assigns.fetch(:source_branch_exists, false) +- mr_can_be_reverted = @merge_request.can_be_reverted? + +- if source_branch_exists || mr_can_be_reverted + .btn-group + - if source_branch_exists + = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-default btn-grouped btn-sm remove_source_branch" do + = icon('trash-o') + Remove Source Branch + - if mr_can_be_reverted + = revert_commit_link(@merge_request.merge_commit, namespace_project_merge_request_path(@project.namespace, @project, @merge_request), btn_class: 'sm') diff --git a/app/views/projects/milestones/_issue.html.haml b/app/views/projects/milestones/_issue.html.haml index 133d802aaca..ca51b8c745d 100644 --- a/app/views/projects/milestones/_issue.html.haml +++ b/app/views/projects/milestones/_issue.html.haml @@ -1,9 +1,10 @@ %li{ id: dom_id(issue, 'sortable'), class: 'issue-row', 'data-iid' => issue.iid, 'data-url' => issue_path(issue) } - .pull-right.assignee-icon - - if issue.assignee - = image_tag avatar_icon(issue.assignee, 16), class: "avatar s16", alt: '' %span - = link_to [@project.namespace.becomes(Namespace), @project, issue] do - %span.cgray ##{issue.iid} = link_to_gfm issue.title, [@project.namespace.becomes(Namespace), @project, issue], title: issue.title - + .issue-detail + = link_to [@project.namespace.becomes(Namespace), @project, issue] do + %span.issue-number ##{issue.iid} + - issue.labels.each do |label| + = render_colored_label(label) + - if issue.assignee + = image_tag avatar_icon(issue.assignee, 16), class: "avatar s24", alt: '' diff --git a/app/views/projects/milestones/_issues.html.haml b/app/views/projects/milestones/_issues.html.haml index 6e4df75a3df..6f8a341e478 100644 --- a/app/views/projects/milestones/_issues.html.haml +++ b/app/views/projects/milestones/_issues.html.haml @@ -1,6 +1,7 @@ .panel.panel-default - .panel-heading= title + .panel-heading + = title + .pull-right= issues.size %ul{ class: "well-list issues-sortable-list", id: "issues-list-#{id}", "data-state" => id } - issues.sort_by(&:position).each do |issue| = render 'issue', issue: issue - %li.light.ui-sort-disabled Drag and drop available diff --git a/app/views/projects/milestones/_merge_requests.html.haml b/app/views/projects/milestones/_merge_requests.html.haml index 00889a5eb24..9a5a02af215 100644 --- a/app/views/projects/milestones/_merge_requests.html.haml +++ b/app/views/projects/milestones/_merge_requests.html.haml @@ -3,4 +3,3 @@ %ul{ class: "well-list merge_requests-sortable-list", id: "merge_requests-list-#{id}", "data-state" => id } - merge_requests.sort_by(&:position).each do |merge_request| = render 'merge_request', merge_request: merge_request - %li.light.ui-sort-disabled Drag and drop available diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 528a4f9552f..631bc8c3e9d 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -24,7 +24,7 @@ - else = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-nr btn-grouped" - = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-nr btn-remove" do + = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-nr" do = icon('trash-o') Delete @@ -32,7 +32,7 @@ = icon('pencil-square-o') Edit -.detail-page-description.content-block +.detail-page-description.milestone-detail.second-block %h2.title = markdown escape_once(@milestone.title), pipeline: :single_line %div @@ -47,44 +47,55 @@ %span All issues for this milestone are closed. You may close milestone now. .context.prepend-top-default - %p.lead - Progress: - #{@milestone.closed_items_count} closed - – - #{@milestone.open_items_count} open - - %span.light #{@milestone.percent_complete}% complete - %span.pull-right= @milestone.expires_at + .milestone-summary + %h4 Progress + %strong= @milestone.issues.count + issues: + %span.milestone-stat + %strong= @milestone.open_items_count + open and + %strong= @milestone.closed_items_count + closed + %span.milestone-stat + %strong== #{@milestone.percent_complete}% + complete + %span.milestone-stat + %span.time-elapsed + %strong== #{@milestone.percent_time_used}% + time elapsed + %span.pull-right.tab-issues-buttons + - if can?(current_user, :create_issue, @project) + = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn btn-grouped", title: "New Issue" do + %i.fa.fa-plus + New Issue + - if can?(current_user, :read_issue, @project) + = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped" + %span.pull-right.tab-merge-requests-buttons.hidden + - if can?(current_user, :read_merge_request, @project) + = link_to 'Browse Merge Requests', namespace_project_merge_requests_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped" + = milestone_progress_bar(@milestone) %ul.nav-links.no-top.no-bottom %li.active - = link_to '#tab-issues', 'data-toggle' => 'tab' do + = link_to '#tab-issues', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do Issues %span.badge= @issues.count %li - = link_to '#tab-merge-requests', 'data-toggle' => 'tab' do + = link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do Merge Requests %span.badge= @merge_requests.count %li = link_to '#tab-participants', 'data-toggle' => 'tab' do Participants %span.badge= @users.count + %li + = link_to '#tab-labels', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do + Labels + %span.badge= @labels.count -.tab-content +.tab-content.milestone-content .tab-pane.active#tab-issues - .content-block.oneline-block - .controls - - if can?(current_user, :create_issue, @project) - = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn btn-grouped", title: "New Issue" do - %i.fa.fa-plus - New Issue - - if can?(current_user, :read_issue, @project) - = link_to 'Browse Issues', namespace_project_issues_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped" - - .oneline - All issues in this milestone - .row.prepend-top-default .col-md-4 = render('issues', title: 'Unstarted Issues (open and unassigned)', issues: @issues.opened.unassigned, id: 'unassigned') @@ -94,14 +105,6 @@ = render('issues', title: 'Completed Issues (closed)', issues: @issues.closed, id: 'closed') .tab-pane#tab-merge-requests - .content-block.oneline-block - .controls - - if can?(current_user, :read_merge_request, @project) - = link_to 'Browse Merge Requests', namespace_project_merge_requests_path(@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title), class: "btn btn-grouped" - - .oneline - All merge requests in this milestone - .row.prepend-top-default .col-md-3 = render('merge_requests', title: 'Work in progress (open and unassigned)', merge_requests: @merge_requests.opened.unassigned, id: 'unassigned') @@ -117,9 +120,6 @@ = render 'merge_request', merge_request: merge_request .tab-pane#tab-participants - .content-block.oneline-block - All participants to this milestone - %ul.bordered-list - @users.each do |user| %li @@ -128,3 +128,18 @@ %strong= truncate(user.name, lenght: 40) %br %small.cgray= user.username + + .tab-pane#tab-labels + %ul.bordered-list.manage-labels-list + - @labels.each do |label| + %li + = render_colored_label(label) + - args = [@milestone.project.namespace, @milestone.project, milestone_title: @milestone.title, label_name: label.title] + - options = args.extract_options! + + %span.issues-count + = link_to namespace_project_issues_path(*args, options.merge(state: 'opened')) do + = pluralize label.open_issues_count, 'open issue' + %span.issues-count + = link_to namespace_project_issues_path(*args, options.merge(state: 'closed')) do + = pluralize label.closed_issues_count, 'closed issue' diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml new file mode 100644 index 00000000000..8134b15d245 --- /dev/null +++ b/app/views/shared/_label_row.html.haml @@ -0,0 +1,4 @@ +%span.label-row + = link_to_label(label) + %span.prepend-left-10 + = markdown(label.description, pipeline: :single_line) diff --git a/app/views/shared/_project_limit.html.haml b/app/views/shared/_project_limit.html.haml index 960ff00b49d..f4eb8e491b9 100644 --- a/app/views/shared/_project_limit.html.haml +++ b/app/views/shared/_project_limit.html.haml @@ -1,4 +1,4 @@ -- if cookies[:hide_project_limit_message].blank? && !current_user.hide_project_limit && !current_user.can_create_project? +- if cookies[:hide_project_limit_message].blank? && !current_user.hide_project_limit && !current_user.can_create_project? && current_user.projects_limit > 0 .project-limit-message.alert.alert-warning.hidden-xs You won't be able to create new projects because you have reached your project limit. diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml index f09ab25276d..e3a6a5a68b6 100644 --- a/app/views/shared/_sort_dropdown.html.haml +++ b/app/views/shared/_sort_dropdown.html.haml @@ -20,3 +20,7 @@ = sort_title_milestone_soon = link_to page_filter_path(sort: sort_value_milestone_later) do = sort_title_milestone_later + = link_to page_filter_path(sort: sort_value_upvotes) do + = sort_title_upvotes + = link_to page_filter_path(sort: sort_value_downvotes) do + = sort_title_downvotes diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index b7e350d27af..e55159d996b 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -41,6 +41,10 @@ .filter-item.inline = button_tag "Update issues", class: "btn update_selected_issues btn-save" +- if @label + .gray-content-block.second-block + = render "shared/label_row", label: @label + :javascript new UsersSelect(); $('form.filter-form').on('submit', function (event) { diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 2aada5c9952..a45775f36b5 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -47,7 +47,7 @@ .block.milestone .sidebar-collapsed-icon - = icon('balance-scale') + = icon('clock-o') %span - if issuable.milestone = issuable.milestone.title diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index 00bf9dcd2d5..72061e272f1 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -4,7 +4,7 @@ - ci = false unless local_assigns[:ci] == true - skip_namespace = false unless local_assigns[:skip_namespace] == true - css_class = '' unless local_assigns[:css_class] -- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true +- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true && project.commit - css_class += " no-description" if project.description.blank? && !show_last_commit_as_description - ci_commit = project.ci_commit(project.commit.sha) if ci && !project.empty_repo? && project.commit - cache_key = [project.namespace, project, controller.controller_name, controller.action_name, current_application_settings, 'v2.2'] @@ -39,6 +39,9 @@ %span = icon('star') = project.star_count + %span.visibility-icon.has_tooltip{data: { container: 'body', placement: 'left' }, + title: "#{visibility_level_label(project.visibility_level)} - #{project_visibility_level_description(project.visibility_level)}"} + = visibility_level_icon(project.visibility_level, fw: false) - if show_last_commit_as_description .project-description = link_to_gfm project.commit.title, namespace_project_commit_path(project.namespace, project, project.commit), diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 994b8e8ed38..14d7813412e 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -38,7 +38,7 @@ class PostReceive if Gitlab::Git.tag_ref?(ref) GitTagPushService.new.execute(project, @user, oldrev, newrev, ref) else - GitPushService.new.execute(project, @user, oldrev, newrev, ref) + GitPushService.new(project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute end end end diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index 2f991c52339..2572b9d6d98 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -27,6 +27,7 @@ class RepositoryForkWorker return end + project.repository.expire_emptiness_caches project.import_finish end end diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index e295a9ddd14..0b6f746e118 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -18,6 +18,7 @@ class RepositoryImportWorker return end + project.repository.expire_emptiness_caches project.import_finish end end |