diff options
78 files changed, 1777 insertions, 1202 deletions
@@ -343,7 +343,7 @@ group :development, :test do gem 'benchmark-ips', '~> 2.3.0', require: false - gem 'license_finder', '~> 2.1.0', require: false + gem 'license_finder', '~> 3.1', require: false gem 'knapsack', '~> 1.11.0' gem 'activerecord_sane_schema_dumper', '0.2' diff --git a/Gemfile.lock b/Gemfile.lock index 43555a01037..dc56e6e8f82 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -83,6 +83,7 @@ GEM bindata (2.4.1) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) + blankslate (2.1.2.4) bootstrap-sass (3.3.6) autoprefixer-rails (>= 5.2.1) sass (>= 3.3.4) @@ -451,11 +452,13 @@ GEM actionmailer (>= 3.2) letter_opener (~> 1.0) railties (>= 3.2) - license_finder (2.1.0) + license_finder (3.1.1) bundler httparty rubyzip thor + toml (= 0.1.2) + with_env (> 1.0) xml-simple licensee (8.7.0) rugged (~> 0.24) @@ -571,6 +574,8 @@ GEM activerecord (>= 4.0, < 5.2) parser (2.4.0.0) ast (~> 2.2) + parslet (1.5.0) + blankslate (~> 2.0) path_expander (1.0.1) peek (1.0.1) concurrent-ruby (>= 0.9.0) @@ -898,6 +903,8 @@ GEM tilt (2.0.6) timecop (0.8.1) timfel-krb5-auth (0.8.3) + toml (0.1.2) + parslet (~> 1.5.0) toml-rb (0.3.15) citrus (~> 3.0, > 3.0) truncato (0.7.10) @@ -952,6 +959,7 @@ GEM builder expression_parser rinku + with_env (1.1.0) xml-simple (1.1.5) xpath (2.1.0) nokogiri (~> 1.3) @@ -1058,7 +1066,7 @@ DEPENDENCIES knapsack (~> 1.11.0) kubeclient (~> 2.2.0) letter_opener_web (~> 1.3.0) - license_finder (~> 2.1.0) + license_finder (~> 3.1) licensee (~> 8.7.0) lograge (~> 0.5) loofah (~> 2.0.3) diff --git a/app/assets/images/emoji.png b/app/assets/images/emoji.png Binary files differindex 5dcd9c09b70..723c2c3f4c8 100644 --- a/app/assets/images/emoji.png +++ b/app/assets/images/emoji.png diff --git a/app/assets/images/emoji/gay_pride_flag.png b/app/assets/images/emoji/gay_pride_flag.png Binary files differnew file mode 100644 index 00000000000..1bec5f2ffd7 --- /dev/null +++ b/app/assets/images/emoji/gay_pride_flag.png diff --git a/app/assets/images/emoji/mrs_claus.png b/app/assets/images/emoji/mrs_claus.png Binary files differindex 078f0657f95..9cf2458df1a 100644 --- a/app/assets/images/emoji/mrs_claus.png +++ b/app/assets/images/emoji/mrs_claus.png diff --git a/app/assets/images/emoji/speech_left.png b/app/assets/images/emoji/speech_left.png Binary files differnew file mode 100644 index 00000000000..00c05959bcd --- /dev/null +++ b/app/assets/images/emoji/speech_left.png diff --git a/app/assets/images/emoji@2x.png b/app/assets/images/emoji@2x.png Binary files differindex b0fa9e1139e..987279c13cc 100644 --- a/app/assets/images/emoji@2x.png +++ b/app/assets/images/emoji@2x.png diff --git a/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js b/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js index 3fd23efa9f8..e9defb62cf8 100644 --- a/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js +++ b/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js @@ -7,6 +7,17 @@ function isFlagEmoji(emojiUnicode) { return emojiUnicode.length === 4 && cp >= flagACodePoint && cp <= flagZCodePoint; } +// Tested on mac OS 10.12.6 and Windows 10 FCU, it renders as two separate characters +const baseFlagCodePoint = 127987; // parseInt('1F3F3', 16) +const rainbowCodePoint = 127752; // parseInt('1F308', 16) +function isRainbowFlagEmoji(emojiUnicode) { + const characters = Array.from(emojiUnicode); + // Length 4 because flags are made of 2 characters which are surrogate pairs + return emojiUnicode.length === 4 && + characters[0].codePointAt(0) === baseFlagCodePoint && + characters[1].codePointAt(0) === rainbowCodePoint; +} + // Chrome <57 renders keycaps oddly // See https://bugs.chromium.org/p/chromium/issues/detail?id=632294 // Same issue on Windows also fixed in Chrome 57, http://i.imgur.com/rQF7woO.png @@ -57,9 +68,11 @@ function isPersonZwjEmoji(emojiUnicode) { // in `isEmojiUnicodeSupported` logic function checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) { const isFlagResult = isFlagEmoji(emojiUnicode); + const isRainbowFlagResult = isRainbowFlagEmoji(emojiUnicode); return ( (unicodeSupportMap.flag && isFlagResult) || - !isFlagResult + (unicodeSupportMap.rainbowFlag && isRainbowFlagResult) || + (!isFlagResult && !isRainbowFlagResult) ); } @@ -113,6 +126,7 @@ function isEmojiUnicodeSupported(unicodeSupportMap = {}, emojiUnicode, unicodeVe export { isEmojiUnicodeSupported as default, isFlagEmoji, + isRainbowFlagEmoji, isKeycapEmoji, isSkinToneComboEmoji, isHorceRacingSkinToneComboEmoji, diff --git a/app/assets/javascripts/emoji/support/unicode_support_map.js b/app/assets/javascripts/emoji/support/unicode_support_map.js index 755381c2f95..c18d07dad43 100644 --- a/app/assets/javascripts/emoji/support/unicode_support_map.js +++ b/app/assets/javascripts/emoji/support/unicode_support_map.js @@ -1,5 +1,7 @@ import AccessorUtilities from '../../lib/utils/accessor'; +const GL_EMOJI_VERSION = '0.2.0'; + const unicodeSupportTestMap = { // man, student (emojione does not have any of these yet), http://emojipedia.org/emoji-zwj-sequences/ // occupationZwj: '\u{1F468}\u{200D}\u{1F393}', @@ -13,6 +15,7 @@ const unicodeSupportTestMap = { horseRacing: '\u{1F3C7}\u{1F3FF}', // US flag, http://emojipedia.org/flags/ flag: '\u{1F1FA}\u{1F1F8}', + rainbowFlag: '\u{1F3F3}\u{1F308}', // http://emojipedia.org/modifiers/ skinToneModifier: [ // spy_tone5 @@ -141,23 +144,31 @@ function generateUnicodeSupportMap(testMap) { } export default function getUnicodeSupportMap() { - let unicodeSupportMap; - let userAgentFromCache; - const isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe(); - if (isLocalStorageAvailable) userAgentFromCache = window.localStorage.getItem('gl-emoji-user-agent'); + let glEmojiVersionFromCache; + let userAgentFromCache; + if (isLocalStorageAvailable) { + glEmojiVersionFromCache = window.localStorage.getItem('gl-emoji-version'); + userAgentFromCache = window.localStorage.getItem('gl-emoji-user-agent'); + } + let unicodeSupportMap; try { unicodeSupportMap = JSON.parse(window.localStorage.getItem('gl-emoji-unicode-support-map')); } catch (err) { // swallow } - if (!unicodeSupportMap || userAgentFromCache !== navigator.userAgent) { + if ( + !unicodeSupportMap || + glEmojiVersionFromCache !== GL_EMOJI_VERSION || + userAgentFromCache !== navigator.userAgent + ) { unicodeSupportMap = generateUnicodeSupportMap(unicodeSupportTestMap); if (isLocalStorageAvailable) { + window.localStorage.setItem('gl-emoji-version', GL_EMOJI_VERSION); window.localStorage.setItem('gl-emoji-user-agent', navigator.userAgent); window.localStorage.setItem('gl-emoji-unicode-support-map', JSON.stringify(unicodeSupportMap)); } diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index d1aa83ea57f..e8ac8d3b5bb 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -29,6 +29,11 @@ export default { required: false, default: false, }, + showDeleteButton: { + type: Boolean, + required: false, + default: true, + }, issuableRef: { type: String, required: true, @@ -92,6 +97,11 @@ export default { type: String, required: true, }, + issuableType: { + type: String, + required: false, + default: 'issue', + }, }, data() { const store = new Store({ @@ -157,21 +167,21 @@ export default { }) .catch(() => { eventHub.$emit('close.form'); - window.Flash('Error updating issue'); + window.Flash(`Error updating ${this.issuableType}`); }); }, deleteIssuable() { this.service.deleteIssuable() .then(res => res.json()) .then((data) => { - // Stop the poll so we don't get 404's with the issue not existing + // Stop the poll so we don't get 404's with the issuable not existing this.poll.stop(); gl.utils.visitUrl(data.web_url); }) .catch(() => { eventHub.$emit('close.form'); - window.Flash('Error deleting issue'); + window.Flash(`Error deleting ${this.issuableType}`); }); }, }, @@ -223,6 +233,7 @@ export default { :markdown-preview-path="markdownPreviewPath" :project-path="projectPath" :project-namespace="projectNamespace" + :show-delete-button="showDeleteButton" /> <div v-else> <title-component diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue index 8c81575fe6f..a539506bce2 100644 --- a/app/assets/javascripts/issue_show/components/edit_actions.vue +++ b/app/assets/javascripts/issue_show/components/edit_actions.vue @@ -13,6 +13,11 @@ type: Object, required: true, }, + showDeleteButton: { + type: Boolean, + required: false, + default: true, + }, }, data() { return { @@ -23,6 +28,9 @@ isSubmitEnabled() { return this.formState.title.trim() !== ''; }, + shouldShowDeleteButton() { + return this.canDestroy && this.showDeleteButton; + }, }, methods: { closeForm() { @@ -62,7 +70,7 @@ Cancel </button> <button - v-if="canDestroy" + v-if="shouldShowDeleteButton" class="btn btn-danger pull-right append-right-default" :class="{ disabled: deleteLoading }" type="button" diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue index 28bf6c67ea5..8bb5c86d567 100644 --- a/app/assets/javascripts/issue_show/components/form.vue +++ b/app/assets/javascripts/issue_show/components/form.vue @@ -36,6 +36,11 @@ type: String, required: true, }, + showDeleteButton: { + type: Boolean, + required: false, + default: true, + }, }, components: { lockedWarning, @@ -81,6 +86,7 @@ :markdown-docs-path="markdownDocsPath" /> <edit-actions :form-state="formState" - :can-destroy="canDestroy" /> + :can-destroy="canDestroy" + :show-delete-button="showDeleteButton" /> </form> </template> diff --git a/app/assets/javascripts/vue_shared/components/loading_button.vue b/app/assets/javascripts/vue_shared/components/loading_button.vue index 0cc2653761c..247943f83e6 100644 --- a/app/assets/javascripts/vue_shared/components/loading_button.vue +++ b/app/assets/javascripts/vue_shared/components/loading_button.vue @@ -35,6 +35,11 @@ export default { type: String, required: false, }, + containerClass: { + type: String, + required: false, + default: 'btn btn-align-content', + }, }, components: { loadingIcon, @@ -49,9 +54,9 @@ export default { <template> <button - class="btn btn-align-content" @click="onClick" type="button" + :class="containerClass" :disabled="loading || disabled" > <transition name="fade"> diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 9c1439dfad5..91976ca1f56 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -353,3 +353,7 @@ display: -webkit-flex; display: flex; } + +.flex-right { + margin-left: auto; +} diff --git a/app/assets/stylesheets/framework/emoji-sprites.scss b/app/assets/stylesheets/framework/emoji-sprites.scss index 925415f84b1..0174e17b660 100644 --- a/app/assets/stylesheets/framework/emoji-sprites.scss +++ b/app/assets/stylesheets/framework/emoji-sprites.scss @@ -765,1031 +765,1033 @@ .emoji-full_moon { background-position: -160px -540px; } .emoji-full_moon_with_face { background-position: -180px -540px; } .emoji-game_die { background-position: -200px -540px; } -.emoji-gear { background-position: -220px -540px; } -.emoji-gem { background-position: -240px -540px; } -.emoji-gemini { background-position: -260px -540px; } -.emoji-ghost { background-position: -280px -540px; } -.emoji-gift { background-position: -300px -540px; } -.emoji-gift_heart { background-position: -320px -540px; } -.emoji-girl { background-position: -340px -540px; } -.emoji-girl_tone1 { background-position: -360px -540px; } -.emoji-girl_tone2 { background-position: -380px -540px; } -.emoji-girl_tone3 { background-position: -400px -540px; } -.emoji-girl_tone4 { background-position: -420px -540px; } -.emoji-girl_tone5 { background-position: -440px -540px; } -.emoji-globe_with_meridians { background-position: -460px -540px; } -.emoji-goal { background-position: -480px -540px; } -.emoji-goat { background-position: -500px -540px; } -.emoji-golf { background-position: -520px -540px; } -.emoji-golfer { background-position: -540px -540px; } -.emoji-gorilla { background-position: -560px 0; } -.emoji-grapes { background-position: -560px -20px; } -.emoji-green_apple { background-position: -560px -40px; } -.emoji-green_book { background-position: -560px -60px; } -.emoji-green_heart { background-position: -560px -80px; } -.emoji-grey_exclamation { background-position: -560px -100px; } -.emoji-grey_question { background-position: -560px -120px; } -.emoji-grimacing { background-position: -560px -140px; } -.emoji-grin { background-position: -560px -160px; } -.emoji-grinning { background-position: -560px -180px; } -.emoji-guardsman { background-position: -560px -200px; } -.emoji-guardsman_tone1 { background-position: -560px -220px; } -.emoji-guardsman_tone2 { background-position: -560px -240px; } -.emoji-guardsman_tone3 { background-position: -560px -260px; } -.emoji-guardsman_tone4 { background-position: -560px -280px; } -.emoji-guardsman_tone5 { background-position: -560px -300px; } -.emoji-guitar { background-position: -560px -320px; } -.emoji-gun { background-position: -560px -340px; } -.emoji-haircut { background-position: -560px -360px; } -.emoji-haircut_tone1 { background-position: -560px -380px; } -.emoji-haircut_tone2 { background-position: -560px -400px; } -.emoji-haircut_tone3 { background-position: -560px -420px; } -.emoji-haircut_tone4 { background-position: -560px -440px; } -.emoji-haircut_tone5 { background-position: -560px -460px; } -.emoji-hamburger { background-position: -560px -480px; } -.emoji-hammer { background-position: -560px -500px; } -.emoji-hammer_pick { background-position: -560px -520px; } -.emoji-hamster { background-position: -560px -540px; } -.emoji-hand_splayed { background-position: 0 -560px; } -.emoji-hand_splayed_tone1 { background-position: -20px -560px; } -.emoji-hand_splayed_tone2 { background-position: -40px -560px; } -.emoji-hand_splayed_tone3 { background-position: -60px -560px; } -.emoji-hand_splayed_tone4 { background-position: -80px -560px; } -.emoji-hand_splayed_tone5 { background-position: -100px -560px; } -.emoji-handbag { background-position: -120px -560px; } -.emoji-handball { background-position: -140px -560px; } -.emoji-handball_tone1 { background-position: -160px -560px; } -.emoji-handball_tone2 { background-position: -180px -560px; } -.emoji-handball_tone3 { background-position: -200px -560px; } -.emoji-handball_tone4 { background-position: -220px -560px; } -.emoji-handball_tone5 { background-position: -240px -560px; } -.emoji-handshake { background-position: -260px -560px; } -.emoji-handshake_tone1 { background-position: -280px -560px; } -.emoji-handshake_tone2 { background-position: -300px -560px; } -.emoji-handshake_tone3 { background-position: -320px -560px; } -.emoji-handshake_tone4 { background-position: -340px -560px; } -.emoji-handshake_tone5 { background-position: -360px -560px; } -.emoji-hash { background-position: -380px -560px; } -.emoji-hatched_chick { background-position: -400px -560px; } -.emoji-hatching_chick { background-position: -420px -560px; } -.emoji-head_bandage { background-position: -440px -560px; } -.emoji-headphones { background-position: -460px -560px; } -.emoji-hear_no_evil { background-position: -480px -560px; } -.emoji-heart { background-position: -500px -560px; } -.emoji-heart_decoration { background-position: -520px -560px; } -.emoji-heart_exclamation { background-position: -540px -560px; } -.emoji-heart_eyes { background-position: -560px -560px; } -.emoji-heart_eyes_cat { background-position: -580px 0; } -.emoji-heartbeat { background-position: -580px -20px; } -.emoji-heartpulse { background-position: -580px -40px; } -.emoji-hearts { background-position: -580px -60px; } -.emoji-heavy_check_mark { background-position: -580px -80px; } -.emoji-heavy_division_sign { background-position: -580px -100px; } -.emoji-heavy_dollar_sign { background-position: -580px -120px; } -.emoji-heavy_minus_sign { background-position: -580px -140px; } -.emoji-heavy_multiplication_x { background-position: -580px -160px; } -.emoji-heavy_plus_sign { background-position: -580px -180px; } -.emoji-helicopter { background-position: -580px -200px; } -.emoji-helmet_with_cross { background-position: -580px -220px; } -.emoji-herb { background-position: -580px -240px; } -.emoji-hibiscus { background-position: -580px -260px; } -.emoji-high_brightness { background-position: -580px -280px; } -.emoji-high_heel { background-position: -580px -300px; } -.emoji-hockey { background-position: -580px -320px; } -.emoji-hole { background-position: -580px -340px; } -.emoji-homes { background-position: -580px -360px; } -.emoji-honey_pot { background-position: -580px -380px; } -.emoji-horse { background-position: -580px -400px; } -.emoji-horse_racing { background-position: -580px -420px; } -.emoji-horse_racing_tone1 { background-position: -580px -440px; } -.emoji-horse_racing_tone2 { background-position: -580px -460px; } -.emoji-horse_racing_tone3 { background-position: -580px -480px; } -.emoji-horse_racing_tone4 { background-position: -580px -500px; } -.emoji-horse_racing_tone5 { background-position: -580px -520px; } -.emoji-hospital { background-position: -580px -540px; } -.emoji-hot_pepper { background-position: -580px -560px; } -.emoji-hotdog { background-position: 0 -580px; } -.emoji-hotel { background-position: -20px -580px; } -.emoji-hotsprings { background-position: -40px -580px; } -.emoji-hourglass { background-position: -60px -580px; } -.emoji-hourglass_flowing_sand { background-position: -80px -580px; } -.emoji-house { background-position: -100px -580px; } -.emoji-house_abandoned { background-position: -120px -580px; } -.emoji-house_with_garden { background-position: -140px -580px; } -.emoji-hugging { background-position: -160px -580px; } -.emoji-hushed { background-position: -180px -580px; } -.emoji-ice_cream { background-position: -200px -580px; } -.emoji-ice_skate { background-position: -220px -580px; } -.emoji-icecream { background-position: -240px -580px; } -.emoji-id { background-position: -260px -580px; } -.emoji-ideograph_advantage { background-position: -280px -580px; } -.emoji-imp { background-position: -300px -580px; } -.emoji-inbox_tray { background-position: -320px -580px; } -.emoji-incoming_envelope { background-position: -340px -580px; } -.emoji-information_desk_person { background-position: -360px -580px; } -.emoji-information_desk_person_tone1 { background-position: -380px -580px; } -.emoji-information_desk_person_tone2 { background-position: -400px -580px; } -.emoji-information_desk_person_tone3 { background-position: -420px -580px; } -.emoji-information_desk_person_tone4 { background-position: -440px -580px; } -.emoji-information_desk_person_tone5 { background-position: -460px -580px; } -.emoji-information_source { background-position: -480px -580px; } -.emoji-innocent { background-position: -500px -580px; } -.emoji-interrobang { background-position: -520px -580px; } -.emoji-iphone { background-position: -540px -580px; } -.emoji-island { background-position: -560px -580px; } -.emoji-izakaya_lantern { background-position: -580px -580px; } -.emoji-jack_o_lantern { background-position: -600px 0; } -.emoji-japan { background-position: -600px -20px; } -.emoji-japanese_castle { background-position: -600px -40px; } -.emoji-japanese_goblin { background-position: -600px -60px; } -.emoji-japanese_ogre { background-position: -600px -80px; } -.emoji-jeans { background-position: -600px -100px; } -.emoji-joy { background-position: -600px -120px; } -.emoji-joy_cat { background-position: -600px -140px; } -.emoji-joystick { background-position: -600px -160px; } -.emoji-juggling { background-position: -600px -180px; } -.emoji-juggling_tone1 { background-position: -600px -200px; } -.emoji-juggling_tone2 { background-position: -600px -220px; } -.emoji-juggling_tone3 { background-position: -600px -240px; } -.emoji-juggling_tone4 { background-position: -600px -260px; } -.emoji-juggling_tone5 { background-position: -600px -280px; } -.emoji-kaaba { background-position: -600px -300px; } -.emoji-key { background-position: -600px -320px; } -.emoji-key2 { background-position: -600px -340px; } -.emoji-keyboard { background-position: -600px -360px; } -.emoji-kimono { background-position: -600px -380px; } -.emoji-kiss { background-position: -600px -400px; } -.emoji-kiss_mm { background-position: -600px -420px; } -.emoji-kiss_ww { background-position: -600px -440px; } -.emoji-kissing { background-position: -600px -460px; } -.emoji-kissing_cat { background-position: -600px -480px; } -.emoji-kissing_closed_eyes { background-position: -600px -500px; } -.emoji-kissing_heart { background-position: -600px -520px; } -.emoji-kissing_smiling_eyes { background-position: -600px -540px; } -.emoji-kiwi { background-position: -600px -560px; } -.emoji-knife { background-position: -600px -580px; } -.emoji-koala { background-position: 0 -600px; } -.emoji-koko { background-position: -20px -600px; } -.emoji-label { background-position: -40px -600px; } -.emoji-large_blue_circle { background-position: -60px -600px; } -.emoji-large_blue_diamond { background-position: -80px -600px; } -.emoji-large_orange_diamond { background-position: -100px -600px; } -.emoji-last_quarter_moon { background-position: -120px -600px; } -.emoji-last_quarter_moon_with_face { background-position: -140px -600px; } -.emoji-laughing { background-position: -160px -600px; } -.emoji-leaves { background-position: -180px -600px; } -.emoji-ledger { background-position: -200px -600px; } -.emoji-left_facing_fist { background-position: -220px -600px; } -.emoji-left_facing_fist_tone1 { background-position: -240px -600px; } -.emoji-left_facing_fist_tone2 { background-position: -260px -600px; } -.emoji-left_facing_fist_tone3 { background-position: -280px -600px; } -.emoji-left_facing_fist_tone4 { background-position: -300px -600px; } -.emoji-left_facing_fist_tone5 { background-position: -320px -600px; } -.emoji-left_luggage { background-position: -340px -600px; } -.emoji-left_right_arrow { background-position: -360px -600px; } -.emoji-leftwards_arrow_with_hook { background-position: -380px -600px; } -.emoji-lemon { background-position: -400px -600px; } -.emoji-leo { background-position: -420px -600px; } -.emoji-leopard { background-position: -440px -600px; } -.emoji-level_slider { background-position: -460px -600px; } -.emoji-levitate { background-position: -480px -600px; } -.emoji-libra { background-position: -500px -600px; } -.emoji-lifter { background-position: -520px -600px; } -.emoji-lifter_tone1 { background-position: -540px -600px; } -.emoji-lifter_tone2 { background-position: -560px -600px; } -.emoji-lifter_tone3 { background-position: -580px -600px; } -.emoji-lifter_tone4 { background-position: -600px -600px; } -.emoji-lifter_tone5 { background-position: -620px 0; } -.emoji-light_rail { background-position: -620px -20px; } -.emoji-link { background-position: -620px -40px; } -.emoji-lion_face { background-position: -620px -60px; } -.emoji-lips { background-position: -620px -80px; } -.emoji-lipstick { background-position: -620px -100px; } -.emoji-lizard { background-position: -620px -120px; } -.emoji-lock { background-position: -620px -140px; } -.emoji-lock_with_ink_pen { background-position: -620px -160px; } -.emoji-lollipop { background-position: -620px -180px; } -.emoji-loop { background-position: -620px -200px; } -.emoji-loud_sound { background-position: -620px -220px; } -.emoji-loudspeaker { background-position: -620px -240px; } -.emoji-love_hotel { background-position: -620px -260px; } -.emoji-love_letter { background-position: -620px -280px; } -.emoji-low_brightness { background-position: -620px -300px; } -.emoji-lying_face { background-position: -620px -320px; } -.emoji-m { background-position: -620px -340px; } -.emoji-mag { background-position: -620px -360px; } -.emoji-mag_right { background-position: -620px -380px; } -.emoji-mahjong { background-position: -620px -400px; } -.emoji-mailbox { background-position: -620px -420px; } -.emoji-mailbox_closed { background-position: -620px -440px; } -.emoji-mailbox_with_mail { background-position: -620px -460px; } -.emoji-mailbox_with_no_mail { background-position: -620px -480px; } -.emoji-man { background-position: -620px -500px; } -.emoji-man_dancing { background-position: -620px -520px; } -.emoji-man_dancing_tone1 { background-position: -620px -540px; } -.emoji-man_dancing_tone2 { background-position: -620px -560px; } -.emoji-man_dancing_tone3 { background-position: -620px -580px; } -.emoji-man_dancing_tone4 { background-position: -620px -600px; } -.emoji-man_dancing_tone5 { background-position: 0 -620px; } -.emoji-man_in_tuxedo { background-position: -20px -620px; } -.emoji-man_in_tuxedo_tone1 { background-position: -40px -620px; } -.emoji-man_in_tuxedo_tone2 { background-position: -60px -620px; } -.emoji-man_in_tuxedo_tone3 { background-position: -80px -620px; } -.emoji-man_in_tuxedo_tone4 { background-position: -100px -620px; } -.emoji-man_in_tuxedo_tone5 { background-position: -120px -620px; } -.emoji-man_tone1 { background-position: -140px -620px; } -.emoji-man_tone2 { background-position: -160px -620px; } -.emoji-man_tone3 { background-position: -180px -620px; } -.emoji-man_tone4 { background-position: -200px -620px; } -.emoji-man_tone5 { background-position: -220px -620px; } -.emoji-man_with_gua_pi_mao { background-position: -240px -620px; } -.emoji-man_with_gua_pi_mao_tone1 { background-position: -260px -620px; } -.emoji-man_with_gua_pi_mao_tone2 { background-position: -280px -620px; } -.emoji-man_with_gua_pi_mao_tone3 { background-position: -300px -620px; } -.emoji-man_with_gua_pi_mao_tone4 { background-position: -320px -620px; } -.emoji-man_with_gua_pi_mao_tone5 { background-position: -340px -620px; } -.emoji-man_with_turban { background-position: -360px -620px; } -.emoji-man_with_turban_tone1 { background-position: -380px -620px; } -.emoji-man_with_turban_tone2 { background-position: -400px -620px; } -.emoji-man_with_turban_tone3 { background-position: -420px -620px; } -.emoji-man_with_turban_tone4 { background-position: -440px -620px; } -.emoji-man_with_turban_tone5 { background-position: -460px -620px; } -.emoji-mans_shoe { background-position: -480px -620px; } -.emoji-map { background-position: -500px -620px; } -.emoji-maple_leaf { background-position: -520px -620px; } -.emoji-martial_arts_uniform { background-position: -540px -620px; } -.emoji-mask { background-position: -560px -620px; } -.emoji-massage { background-position: -580px -620px; } -.emoji-massage_tone1 { background-position: -600px -620px; } -.emoji-massage_tone2 { background-position: -620px -620px; } -.emoji-massage_tone3 { background-position: -640px 0; } -.emoji-massage_tone4 { background-position: -640px -20px; } -.emoji-massage_tone5 { background-position: -640px -40px; } -.emoji-meat_on_bone { background-position: -640px -60px; } -.emoji-medal { background-position: -640px -80px; } -.emoji-mega { background-position: -640px -100px; } -.emoji-melon { background-position: -640px -120px; } -.emoji-menorah { background-position: -640px -140px; } -.emoji-mens { background-position: -640px -160px; } -.emoji-metal { background-position: -640px -180px; } -.emoji-metal_tone1 { background-position: -640px -200px; } -.emoji-metal_tone2 { background-position: -640px -220px; } -.emoji-metal_tone3 { background-position: -640px -240px; } -.emoji-metal_tone4 { background-position: -640px -260px; } -.emoji-metal_tone5 { background-position: -640px -280px; } -.emoji-metro { background-position: -640px -300px; } -.emoji-microphone { background-position: -640px -320px; } -.emoji-microphone2 { background-position: -640px -340px; } -.emoji-microscope { background-position: -640px -360px; } -.emoji-middle_finger { background-position: -640px -380px; } -.emoji-middle_finger_tone1 { background-position: -640px -400px; } -.emoji-middle_finger_tone2 { background-position: -640px -420px; } -.emoji-middle_finger_tone3 { background-position: -640px -440px; } -.emoji-middle_finger_tone4 { background-position: -640px -460px; } -.emoji-middle_finger_tone5 { background-position: -640px -480px; } -.emoji-military_medal { background-position: -640px -500px; } -.emoji-milk { background-position: -640px -520px; } -.emoji-milky_way { background-position: -640px -540px; } -.emoji-minibus { background-position: -640px -560px; } -.emoji-minidisc { background-position: -640px -580px; } -.emoji-mobile_phone_off { background-position: -640px -600px; } -.emoji-money_mouth { background-position: -640px -620px; } -.emoji-money_with_wings { background-position: 0 -640px; } -.emoji-moneybag { background-position: -20px -640px; } -.emoji-monkey { background-position: -40px -640px; } -.emoji-monkey_face { background-position: -60px -640px; } -.emoji-monorail { background-position: -80px -640px; } -.emoji-mortar_board { background-position: -100px -640px; } -.emoji-mosque { background-position: -120px -640px; } -.emoji-motor_scooter { background-position: -140px -640px; } -.emoji-motorboat { background-position: -160px -640px; } -.emoji-motorcycle { background-position: -180px -640px; } -.emoji-motorway { background-position: -200px -640px; } -.emoji-mount_fuji { background-position: -220px -640px; } -.emoji-mountain { background-position: -240px -640px; } -.emoji-mountain_bicyclist { background-position: -260px -640px; } -.emoji-mountain_bicyclist_tone1 { background-position: -280px -640px; } -.emoji-mountain_bicyclist_tone2 { background-position: -300px -640px; } -.emoji-mountain_bicyclist_tone3 { background-position: -320px -640px; } -.emoji-mountain_bicyclist_tone4 { background-position: -340px -640px; } -.emoji-mountain_bicyclist_tone5 { background-position: -360px -640px; } -.emoji-mountain_cableway { background-position: -380px -640px; } -.emoji-mountain_railway { background-position: -400px -640px; } -.emoji-mountain_snow { background-position: -420px -640px; } -.emoji-mouse { background-position: -440px -640px; } -.emoji-mouse2 { background-position: -460px -640px; } -.emoji-mouse_three_button { background-position: -480px -640px; } -.emoji-movie_camera { background-position: -500px -640px; } -.emoji-moyai { background-position: -520px -640px; } -.emoji-mrs_claus { background-position: -540px -640px; } -.emoji-mrs_claus_tone1 { background-position: -560px -640px; } -.emoji-mrs_claus_tone2 { background-position: -580px -640px; } -.emoji-mrs_claus_tone3 { background-position: -600px -640px; } -.emoji-mrs_claus_tone4 { background-position: -620px -640px; } -.emoji-mrs_claus_tone5 { background-position: -640px -640px; } -.emoji-muscle { background-position: -660px 0; } -.emoji-muscle_tone1 { background-position: -660px -20px; } -.emoji-muscle_tone2 { background-position: -660px -40px; } -.emoji-muscle_tone3 { background-position: -660px -60px; } -.emoji-muscle_tone4 { background-position: -660px -80px; } -.emoji-muscle_tone5 { background-position: -660px -100px; } -.emoji-mushroom { background-position: -660px -120px; } -.emoji-musical_keyboard { background-position: -660px -140px; } -.emoji-musical_note { background-position: -660px -160px; } -.emoji-musical_score { background-position: -660px -180px; } -.emoji-mute { background-position: -660px -200px; } -.emoji-nail_care { background-position: -660px -220px; } -.emoji-nail_care_tone1 { background-position: -660px -240px; } -.emoji-nail_care_tone2 { background-position: -660px -260px; } -.emoji-nail_care_tone3 { background-position: -660px -280px; } -.emoji-nail_care_tone4 { background-position: -660px -300px; } -.emoji-nail_care_tone5 { background-position: -660px -320px; } -.emoji-name_badge { background-position: -660px -340px; } -.emoji-nauseated_face { background-position: -660px -360px; } -.emoji-necktie { background-position: -660px -380px; } -.emoji-negative_squared_cross_mark { background-position: -660px -400px; } -.emoji-nerd { background-position: -660px -420px; } -.emoji-neutral_face { background-position: -660px -440px; } -.emoji-new { background-position: -660px -460px; } -.emoji-new_moon { background-position: -660px -480px; } -.emoji-new_moon_with_face { background-position: -660px -500px; } -.emoji-newspaper { background-position: -660px -520px; } -.emoji-newspaper2 { background-position: -660px -540px; } -.emoji-ng { background-position: -660px -560px; } -.emoji-night_with_stars { background-position: -660px -580px; } -.emoji-nine { background-position: -660px -600px; } -.emoji-no_bell { background-position: -660px -620px; } -.emoji-no_bicycles { background-position: -660px -640px; } -.emoji-no_entry { background-position: 0 -660px; } -.emoji-no_entry_sign { background-position: -20px -660px; } -.emoji-no_good { background-position: -40px -660px; } -.emoji-no_good_tone1 { background-position: -60px -660px; } -.emoji-no_good_tone2 { background-position: -80px -660px; } -.emoji-no_good_tone3 { background-position: -100px -660px; } -.emoji-no_good_tone4 { background-position: -120px -660px; } -.emoji-no_good_tone5 { background-position: -140px -660px; } -.emoji-no_mobile_phones { background-position: -160px -660px; } -.emoji-no_mouth { background-position: -180px -660px; } -.emoji-no_pedestrians { background-position: -200px -660px; } -.emoji-no_smoking { background-position: -220px -660px; } -.emoji-non-potable_water { background-position: -240px -660px; } -.emoji-nose { background-position: -260px -660px; } -.emoji-nose_tone1 { background-position: -280px -660px; } -.emoji-nose_tone2 { background-position: -300px -660px; } -.emoji-nose_tone3 { background-position: -320px -660px; } -.emoji-nose_tone4 { background-position: -340px -660px; } -.emoji-nose_tone5 { background-position: -360px -660px; } -.emoji-notebook { background-position: -380px -660px; } -.emoji-notebook_with_decorative_cover { background-position: -400px -660px; } -.emoji-notepad_spiral { background-position: -420px -660px; } -.emoji-notes { background-position: -440px -660px; } -.emoji-nut_and_bolt { background-position: -460px -660px; } -.emoji-o { background-position: -480px -660px; } -.emoji-o2 { background-position: -500px -660px; } -.emoji-ocean { background-position: -520px -660px; } -.emoji-octagonal_sign { background-position: -540px -660px; } -.emoji-octopus { background-position: -560px -660px; } -.emoji-oden { background-position: -580px -660px; } -.emoji-office { background-position: -600px -660px; } -.emoji-oil { background-position: -620px -660px; } -.emoji-ok { background-position: -640px -660px; } -.emoji-ok_hand { background-position: -660px -660px; } -.emoji-ok_hand_tone1 { background-position: -680px 0; } -.emoji-ok_hand_tone2 { background-position: -680px -20px; } -.emoji-ok_hand_tone3 { background-position: -680px -40px; } -.emoji-ok_hand_tone4 { background-position: -680px -60px; } -.emoji-ok_hand_tone5 { background-position: -680px -80px; } -.emoji-ok_woman { background-position: -680px -100px; } -.emoji-ok_woman_tone1 { background-position: -680px -120px; } -.emoji-ok_woman_tone2 { background-position: -680px -140px; } -.emoji-ok_woman_tone3 { background-position: -680px -160px; } -.emoji-ok_woman_tone4 { background-position: -680px -180px; } -.emoji-ok_woman_tone5 { background-position: -680px -200px; } -.emoji-older_man { background-position: -680px -220px; } -.emoji-older_man_tone1 { background-position: -680px -240px; } -.emoji-older_man_tone2 { background-position: -680px -260px; } -.emoji-older_man_tone3 { background-position: -680px -280px; } -.emoji-older_man_tone4 { background-position: -680px -300px; } -.emoji-older_man_tone5 { background-position: -680px -320px; } -.emoji-older_woman { background-position: -680px -340px; } -.emoji-older_woman_tone1 { background-position: -680px -360px; } -.emoji-older_woman_tone2 { background-position: -680px -380px; } -.emoji-older_woman_tone3 { background-position: -680px -400px; } -.emoji-older_woman_tone4 { background-position: -680px -420px; } -.emoji-older_woman_tone5 { background-position: -680px -440px; } -.emoji-om_symbol { background-position: -680px -460px; } -.emoji-on { background-position: -680px -480px; } -.emoji-oncoming_automobile { background-position: -680px -500px; } -.emoji-oncoming_bus { background-position: -680px -520px; } -.emoji-oncoming_police_car { background-position: -680px -540px; } -.emoji-oncoming_taxi { background-position: -680px -560px; } -.emoji-one { background-position: -680px -580px; } -.emoji-open_file_folder { background-position: -680px -600px; } -.emoji-open_hands { background-position: -680px -620px; } -.emoji-open_hands_tone1 { background-position: -680px -640px; } -.emoji-open_hands_tone2 { background-position: -680px -660px; } -.emoji-open_hands_tone3 { background-position: 0 -680px; } -.emoji-open_hands_tone4 { background-position: -20px -680px; } -.emoji-open_hands_tone5 { background-position: -40px -680px; } -.emoji-open_mouth { background-position: -60px -680px; } -.emoji-ophiuchus { background-position: -80px -680px; } -.emoji-orange_book { background-position: -100px -680px; } -.emoji-orthodox_cross { background-position: -120px -680px; } -.emoji-outbox_tray { background-position: -140px -680px; } -.emoji-owl { background-position: -160px -680px; } -.emoji-ox { background-position: -180px -680px; } -.emoji-package { background-position: -200px -680px; } -.emoji-page_facing_up { background-position: -220px -680px; } -.emoji-page_with_curl { background-position: -240px -680px; } -.emoji-pager { background-position: -260px -680px; } -.emoji-paintbrush { background-position: -280px -680px; } -.emoji-palm_tree { background-position: -300px -680px; } -.emoji-pancakes { background-position: -320px -680px; } -.emoji-panda_face { background-position: -340px -680px; } -.emoji-paperclip { background-position: -360px -680px; } -.emoji-paperclips { background-position: -380px -680px; } -.emoji-park { background-position: -400px -680px; } -.emoji-parking { background-position: -420px -680px; } -.emoji-part_alternation_mark { background-position: -440px -680px; } -.emoji-partly_sunny { background-position: -460px -680px; } -.emoji-passport_control { background-position: -480px -680px; } -.emoji-pause_button { background-position: -500px -680px; } -.emoji-peace { background-position: -520px -680px; } -.emoji-peach { background-position: -540px -680px; } -.emoji-peanuts { background-position: -560px -680px; } -.emoji-pear { background-position: -580px -680px; } -.emoji-pen_ballpoint { background-position: -600px -680px; } -.emoji-pen_fountain { background-position: -620px -680px; } -.emoji-pencil { background-position: -640px -680px; } -.emoji-pencil2 { background-position: -660px -680px; } -.emoji-penguin { background-position: -680px -680px; } -.emoji-pensive { background-position: -700px 0; } -.emoji-performing_arts { background-position: -700px -20px; } -.emoji-persevere { background-position: -700px -40px; } -.emoji-person_frowning { background-position: -700px -60px; } -.emoji-person_frowning_tone1 { background-position: -700px -80px; } -.emoji-person_frowning_tone2 { background-position: -700px -100px; } -.emoji-person_frowning_tone3 { background-position: -700px -120px; } -.emoji-person_frowning_tone4 { background-position: -700px -140px; } -.emoji-person_frowning_tone5 { background-position: -700px -160px; } -.emoji-person_with_blond_hair { background-position: -700px -180px; } -.emoji-person_with_blond_hair_tone1 { background-position: -700px -200px; } -.emoji-person_with_blond_hair_tone2 { background-position: -700px -220px; } -.emoji-person_with_blond_hair_tone3 { background-position: -700px -240px; } -.emoji-person_with_blond_hair_tone4 { background-position: -700px -260px; } -.emoji-person_with_blond_hair_tone5 { background-position: -700px -280px; } -.emoji-person_with_pouting_face { background-position: -700px -300px; } -.emoji-person_with_pouting_face_tone1 { background-position: -700px -320px; } -.emoji-person_with_pouting_face_tone2 { background-position: -700px -340px; } -.emoji-person_with_pouting_face_tone3 { background-position: -700px -360px; } -.emoji-person_with_pouting_face_tone4 { background-position: -700px -380px; } -.emoji-person_with_pouting_face_tone5 { background-position: -700px -400px; } -.emoji-pick { background-position: -700px -420px; } -.emoji-pig { background-position: -700px -440px; } -.emoji-pig2 { background-position: -700px -460px; } -.emoji-pig_nose { background-position: -700px -480px; } -.emoji-pill { background-position: -700px -500px; } -.emoji-pineapple { background-position: -700px -520px; } -.emoji-ping_pong { background-position: -700px -540px; } -.emoji-pisces { background-position: -700px -560px; } -.emoji-pizza { background-position: -700px -580px; } -.emoji-place_of_worship { background-position: -700px -600px; } -.emoji-play_pause { background-position: -700px -620px; } -.emoji-point_down { background-position: -700px -640px; } -.emoji-point_down_tone1 { background-position: -700px -660px; } -.emoji-point_down_tone2 { background-position: -700px -680px; } -.emoji-point_down_tone3 { background-position: 0 -700px; } -.emoji-point_down_tone4 { background-position: -20px -700px; } -.emoji-point_down_tone5 { background-position: -40px -700px; } -.emoji-point_left { background-position: -60px -700px; } -.emoji-point_left_tone1 { background-position: -80px -700px; } -.emoji-point_left_tone2 { background-position: -100px -700px; } -.emoji-point_left_tone3 { background-position: -120px -700px; } -.emoji-point_left_tone4 { background-position: -140px -700px; } -.emoji-point_left_tone5 { background-position: -160px -700px; } -.emoji-point_right { background-position: -180px -700px; } -.emoji-point_right_tone1 { background-position: -200px -700px; } -.emoji-point_right_tone2 { background-position: -220px -700px; } -.emoji-point_right_tone3 { background-position: -240px -700px; } -.emoji-point_right_tone4 { background-position: -260px -700px; } -.emoji-point_right_tone5 { background-position: -280px -700px; } -.emoji-point_up { background-position: -300px -700px; } -.emoji-point_up_2 { background-position: -320px -700px; } -.emoji-point_up_2_tone1 { background-position: -340px -700px; } -.emoji-point_up_2_tone2 { background-position: -360px -700px; } -.emoji-point_up_2_tone3 { background-position: -380px -700px; } -.emoji-point_up_2_tone4 { background-position: -400px -700px; } -.emoji-point_up_2_tone5 { background-position: -420px -700px; } -.emoji-point_up_tone1 { background-position: -440px -700px; } -.emoji-point_up_tone2 { background-position: -460px -700px; } -.emoji-point_up_tone3 { background-position: -480px -700px; } -.emoji-point_up_tone4 { background-position: -500px -700px; } -.emoji-point_up_tone5 { background-position: -520px -700px; } -.emoji-police_car { background-position: -540px -700px; } -.emoji-poodle { background-position: -560px -700px; } -.emoji-poop { background-position: -580px -700px; } -.emoji-popcorn { background-position: -600px -700px; } -.emoji-post_office { background-position: -620px -700px; } -.emoji-postal_horn { background-position: -640px -700px; } -.emoji-postbox { background-position: -660px -700px; } -.emoji-potable_water { background-position: -680px -700px; } -.emoji-potato { background-position: -700px -700px; } -.emoji-pouch { background-position: -720px 0; } -.emoji-poultry_leg { background-position: -720px -20px; } -.emoji-pound { background-position: -720px -40px; } -.emoji-pouting_cat { background-position: -720px -60px; } -.emoji-pray { background-position: -720px -80px; } -.emoji-pray_tone1 { background-position: -720px -100px; } -.emoji-pray_tone2 { background-position: -720px -120px; } -.emoji-pray_tone3 { background-position: -720px -140px; } -.emoji-pray_tone4 { background-position: -720px -160px; } -.emoji-pray_tone5 { background-position: -720px -180px; } -.emoji-prayer_beads { background-position: -720px -200px; } -.emoji-pregnant_woman { background-position: -720px -220px; } -.emoji-pregnant_woman_tone1 { background-position: -720px -240px; } -.emoji-pregnant_woman_tone2 { background-position: -720px -260px; } -.emoji-pregnant_woman_tone3 { background-position: -720px -280px; } -.emoji-pregnant_woman_tone4 { background-position: -720px -300px; } -.emoji-pregnant_woman_tone5 { background-position: -720px -320px; } -.emoji-prince { background-position: -720px -340px; } -.emoji-prince_tone1 { background-position: -720px -360px; } -.emoji-prince_tone2 { background-position: -720px -380px; } -.emoji-prince_tone3 { background-position: -720px -400px; } -.emoji-prince_tone4 { background-position: -720px -420px; } -.emoji-prince_tone5 { background-position: -720px -440px; } -.emoji-princess { background-position: -720px -460px; } -.emoji-princess_tone1 { background-position: -720px -480px; } -.emoji-princess_tone2 { background-position: -720px -500px; } -.emoji-princess_tone3 { background-position: -720px -520px; } -.emoji-princess_tone4 { background-position: -720px -540px; } -.emoji-princess_tone5 { background-position: -720px -560px; } -.emoji-printer { background-position: -720px -580px; } -.emoji-projector { background-position: -720px -600px; } -.emoji-punch { background-position: -720px -620px; } -.emoji-punch_tone1 { background-position: -720px -640px; } -.emoji-punch_tone2 { background-position: -720px -660px; } -.emoji-punch_tone3 { background-position: -720px -680px; } -.emoji-punch_tone4 { background-position: -720px -700px; } -.emoji-punch_tone5 { background-position: 0 -720px; } -.emoji-purple_heart { background-position: -20px -720px; } -.emoji-purse { background-position: -40px -720px; } -.emoji-pushpin { background-position: -60px -720px; } -.emoji-put_litter_in_its_place { background-position: -80px -720px; } -.emoji-question { background-position: -100px -720px; } -.emoji-rabbit { background-position: -120px -720px; } -.emoji-rabbit2 { background-position: -140px -720px; } -.emoji-race_car { background-position: -160px -720px; } -.emoji-racehorse { background-position: -180px -720px; } -.emoji-radio { background-position: -200px -720px; } -.emoji-radio_button { background-position: -220px -720px; } -.emoji-radioactive { background-position: -240px -720px; } -.emoji-rage { background-position: -260px -720px; } -.emoji-railway_car { background-position: -280px -720px; } -.emoji-railway_track { background-position: -300px -720px; } -.emoji-rainbow { background-position: -320px -720px; } -.emoji-raised_back_of_hand { background-position: -340px -720px; } -.emoji-raised_back_of_hand_tone1 { background-position: -360px -720px; } -.emoji-raised_back_of_hand_tone2 { background-position: -380px -720px; } -.emoji-raised_back_of_hand_tone3 { background-position: -400px -720px; } -.emoji-raised_back_of_hand_tone4 { background-position: -420px -720px; } -.emoji-raised_back_of_hand_tone5 { background-position: -440px -720px; } -.emoji-raised_hand { background-position: -460px -720px; } -.emoji-raised_hand_tone1 { background-position: -480px -720px; } -.emoji-raised_hand_tone2 { background-position: -500px -720px; } -.emoji-raised_hand_tone3 { background-position: -520px -720px; } -.emoji-raised_hand_tone4 { background-position: -540px -720px; } -.emoji-raised_hand_tone5 { background-position: -560px -720px; } -.emoji-raised_hands { background-position: -580px -720px; } -.emoji-raised_hands_tone1 { background-position: -600px -720px; } -.emoji-raised_hands_tone2 { background-position: -620px -720px; } -.emoji-raised_hands_tone3 { background-position: -640px -720px; } -.emoji-raised_hands_tone4 { background-position: -660px -720px; } -.emoji-raised_hands_tone5 { background-position: -680px -720px; } -.emoji-raising_hand { background-position: -700px -720px; } -.emoji-raising_hand_tone1 { background-position: -720px -720px; } -.emoji-raising_hand_tone2 { background-position: -740px 0; } -.emoji-raising_hand_tone3 { background-position: -740px -20px; } -.emoji-raising_hand_tone4 { background-position: -740px -40px; } -.emoji-raising_hand_tone5 { background-position: -740px -60px; } -.emoji-ram { background-position: -740px -80px; } -.emoji-ramen { background-position: -740px -100px; } -.emoji-rat { background-position: -740px -120px; } -.emoji-record_button { background-position: -740px -140px; } -.emoji-recycle { background-position: -740px -160px; } -.emoji-red_car { background-position: -740px -180px; } -.emoji-red_circle { background-position: -740px -200px; } -.emoji-registered { background-position: -740px -220px; } -.emoji-relaxed { background-position: -740px -240px; } -.emoji-relieved { background-position: -740px -260px; } -.emoji-reminder_ribbon { background-position: -740px -280px; } -.emoji-repeat { background-position: -740px -300px; } -.emoji-repeat_one { background-position: -740px -320px; } -.emoji-restroom { background-position: -740px -340px; } -.emoji-revolving_hearts { background-position: -740px -360px; } -.emoji-rewind { background-position: -740px -380px; } -.emoji-rhino { background-position: -740px -400px; } -.emoji-ribbon { background-position: -740px -420px; } -.emoji-rice { background-position: -740px -440px; } -.emoji-rice_ball { background-position: -740px -460px; } -.emoji-rice_cracker { background-position: -740px -480px; } -.emoji-rice_scene { background-position: -740px -500px; } -.emoji-right_facing_fist { background-position: -740px -520px; } -.emoji-right_facing_fist_tone1 { background-position: -740px -540px; } -.emoji-right_facing_fist_tone2 { background-position: -740px -560px; } -.emoji-right_facing_fist_tone3 { background-position: -740px -580px; } -.emoji-right_facing_fist_tone4 { background-position: -740px -600px; } -.emoji-right_facing_fist_tone5 { background-position: -740px -620px; } -.emoji-ring { background-position: -740px -640px; } -.emoji-robot { background-position: -740px -660px; } -.emoji-rocket { background-position: -740px -680px; } -.emoji-rofl { background-position: -740px -700px; } -.emoji-roller_coaster { background-position: -740px -720px; } -.emoji-rolling_eyes { background-position: 0 -740px; } -.emoji-rooster { background-position: -20px -740px; } -.emoji-rose { background-position: -40px -740px; } -.emoji-rosette { background-position: -60px -740px; } -.emoji-rotating_light { background-position: -80px -740px; } -.emoji-round_pushpin { background-position: -100px -740px; } -.emoji-rowboat { background-position: -120px -740px; } -.emoji-rowboat_tone1 { background-position: -140px -740px; } -.emoji-rowboat_tone2 { background-position: -160px -740px; } -.emoji-rowboat_tone3 { background-position: -180px -740px; } -.emoji-rowboat_tone4 { background-position: -200px -740px; } -.emoji-rowboat_tone5 { background-position: -220px -740px; } -.emoji-rugby_football { background-position: -240px -740px; } -.emoji-runner { background-position: -260px -740px; } -.emoji-runner_tone1 { background-position: -280px -740px; } -.emoji-runner_tone2 { background-position: -300px -740px; } -.emoji-runner_tone3 { background-position: -320px -740px; } -.emoji-runner_tone4 { background-position: -340px -740px; } -.emoji-runner_tone5 { background-position: -360px -740px; } -.emoji-running_shirt_with_sash { background-position: -380px -740px; } -.emoji-sa { background-position: -400px -740px; } -.emoji-sagittarius { background-position: -420px -740px; } -.emoji-sailboat { background-position: -440px -740px; } -.emoji-sake { background-position: -460px -740px; } -.emoji-salad { background-position: -480px -740px; } -.emoji-sandal { background-position: -500px -740px; } -.emoji-santa { background-position: -520px -740px; } -.emoji-santa_tone1 { background-position: -540px -740px; } -.emoji-santa_tone2 { background-position: -560px -740px; } -.emoji-santa_tone3 { background-position: -580px -740px; } -.emoji-santa_tone4 { background-position: -600px -740px; } -.emoji-santa_tone5 { background-position: -620px -740px; } -.emoji-satellite { background-position: -640px -740px; } -.emoji-satellite_orbital { background-position: -660px -740px; } -.emoji-saxophone { background-position: -680px -740px; } -.emoji-scales { background-position: -700px -740px; } -.emoji-school { background-position: -720px -740px; } -.emoji-school_satchel { background-position: -740px -740px; } -.emoji-scissors { background-position: -760px 0; } -.emoji-scooter { background-position: -760px -20px; } -.emoji-scorpion { background-position: -760px -40px; } -.emoji-scorpius { background-position: -760px -60px; } -.emoji-scream { background-position: -760px -80px; } -.emoji-scream_cat { background-position: -760px -100px; } -.emoji-scroll { background-position: -760px -120px; } -.emoji-seat { background-position: -760px -140px; } -.emoji-second_place { background-position: -760px -160px; } -.emoji-secret { background-position: -760px -180px; } -.emoji-see_no_evil { background-position: -760px -200px; } -.emoji-seedling { background-position: -760px -220px; } -.emoji-selfie { background-position: -760px -240px; } -.emoji-selfie_tone1 { background-position: -760px -260px; } -.emoji-selfie_tone2 { background-position: -760px -280px; } -.emoji-selfie_tone3 { background-position: -760px -300px; } -.emoji-selfie_tone4 { background-position: -760px -320px; } -.emoji-selfie_tone5 { background-position: -760px -340px; } -.emoji-seven { background-position: -760px -360px; } -.emoji-shallow_pan_of_food { background-position: -760px -380px; } -.emoji-shamrock { background-position: -760px -400px; } -.emoji-shark { background-position: -760px -420px; } -.emoji-shaved_ice { background-position: -760px -440px; } -.emoji-sheep { background-position: -760px -460px; } -.emoji-shell { background-position: -760px -480px; } -.emoji-shield { background-position: -760px -500px; } -.emoji-shinto_shrine { background-position: -760px -520px; } -.emoji-ship { background-position: -760px -540px; } -.emoji-shirt { background-position: -760px -560px; } -.emoji-shopping_bags { background-position: -760px -580px; } -.emoji-shopping_cart { background-position: -760px -600px; } -.emoji-shower { background-position: -760px -620px; } -.emoji-shrimp { background-position: -760px -640px; } -.emoji-shrug { background-position: -760px -660px; } -.emoji-shrug_tone1 { background-position: -760px -680px; } -.emoji-shrug_tone2 { background-position: -760px -700px; } -.emoji-shrug_tone3 { background-position: -760px -720px; } -.emoji-shrug_tone4 { background-position: -760px -740px; } -.emoji-shrug_tone5 { background-position: 0 -760px; } -.emoji-signal_strength { background-position: -20px -760px; } -.emoji-six { background-position: -40px -760px; } -.emoji-six_pointed_star { background-position: -60px -760px; } -.emoji-ski { background-position: -80px -760px; } -.emoji-skier { background-position: -100px -760px; } -.emoji-skull { background-position: -120px -760px; } -.emoji-skull_crossbones { background-position: -140px -760px; } -.emoji-sleeping { background-position: -160px -760px; } -.emoji-sleeping_accommodation { background-position: -180px -760px; } -.emoji-sleepy { background-position: -200px -760px; } -.emoji-slight_frown { background-position: -220px -760px; } -.emoji-slight_smile { background-position: -240px -760px; } -.emoji-slot_machine { background-position: -260px -760px; } -.emoji-small_blue_diamond { background-position: -280px -760px; } -.emoji-small_orange_diamond { background-position: -300px -760px; } -.emoji-small_red_triangle { background-position: -320px -760px; } -.emoji-small_red_triangle_down { background-position: -340px -760px; } -.emoji-smile { background-position: -360px -760px; } -.emoji-smile_cat { background-position: -380px -760px; } -.emoji-smiley { background-position: -400px -760px; } -.emoji-smiley_cat { background-position: -420px -760px; } -.emoji-smiling_imp { background-position: -440px -760px; } -.emoji-smirk { background-position: -460px -760px; } -.emoji-smirk_cat { background-position: -480px -760px; } -.emoji-smoking { background-position: -500px -760px; } -.emoji-snail { background-position: -520px -760px; } -.emoji-snake { background-position: -540px -760px; } -.emoji-sneezing_face { background-position: -560px -760px; } -.emoji-snowboarder { background-position: -580px -760px; } -.emoji-snowflake { background-position: -600px -760px; } -.emoji-snowman { background-position: -620px -760px; } -.emoji-snowman2 { background-position: -640px -760px; } -.emoji-sob { background-position: -660px -760px; } -.emoji-soccer { background-position: -680px -760px; } -.emoji-soon { background-position: -700px -760px; } -.emoji-sos { background-position: -720px -760px; } -.emoji-sound { background-position: -740px -760px; } -.emoji-space_invader { background-position: -760px -760px; } -.emoji-spades { background-position: -780px 0; } -.emoji-spaghetti { background-position: -780px -20px; } -.emoji-sparkle { background-position: -780px -40px; } -.emoji-sparkler { background-position: -780px -60px; } -.emoji-sparkles { background-position: -780px -80px; } -.emoji-sparkling_heart { background-position: -780px -100px; } -.emoji-speak_no_evil { background-position: -780px -120px; } -.emoji-speaker { background-position: -780px -140px; } -.emoji-speaking_head { background-position: -780px -160px; } -.emoji-speech_balloon { background-position: -780px -180px; } -.emoji-speedboat { background-position: -780px -200px; } -.emoji-spider { background-position: -780px -220px; } -.emoji-spider_web { background-position: -780px -240px; } -.emoji-spoon { background-position: -780px -260px; } -.emoji-spy { background-position: -780px -280px; } -.emoji-spy_tone1 { background-position: -780px -300px; } -.emoji-spy_tone2 { background-position: -780px -320px; } -.emoji-spy_tone3 { background-position: -780px -340px; } -.emoji-spy_tone4 { background-position: -780px -360px; } -.emoji-spy_tone5 { background-position: -780px -380px; } -.emoji-squid { background-position: -780px -400px; } -.emoji-stadium { background-position: -780px -420px; } -.emoji-star { background-position: -780px -440px; } -.emoji-star2 { background-position: -780px -460px; } -.emoji-star_and_crescent { background-position: -780px -480px; } -.emoji-star_of_david { background-position: -780px -500px; } -.emoji-stars { background-position: -780px -520px; } -.emoji-station { background-position: -780px -540px; } -.emoji-statue_of_liberty { background-position: -780px -560px; } -.emoji-steam_locomotive { background-position: -780px -580px; } -.emoji-stew { background-position: -780px -600px; } -.emoji-stop_button { background-position: -780px -620px; } -.emoji-stopwatch { background-position: -780px -640px; } -.emoji-straight_ruler { background-position: -780px -660px; } -.emoji-strawberry { background-position: -780px -680px; } -.emoji-stuck_out_tongue { background-position: -780px -700px; } -.emoji-stuck_out_tongue_closed_eyes { background-position: -780px -720px; } -.emoji-stuck_out_tongue_winking_eye { background-position: -780px -740px; } -.emoji-stuffed_flatbread { background-position: -780px -760px; } -.emoji-sun_with_face { background-position: 0 -780px; } -.emoji-sunflower { background-position: -20px -780px; } -.emoji-sunglasses { background-position: -40px -780px; } -.emoji-sunny { background-position: -60px -780px; } -.emoji-sunrise { background-position: -80px -780px; } -.emoji-sunrise_over_mountains { background-position: -100px -780px; } -.emoji-surfer { background-position: -120px -780px; } -.emoji-surfer_tone1 { background-position: -140px -780px; } -.emoji-surfer_tone2 { background-position: -160px -780px; } -.emoji-surfer_tone3 { background-position: -180px -780px; } -.emoji-surfer_tone4 { background-position: -200px -780px; } -.emoji-surfer_tone5 { background-position: -220px -780px; } -.emoji-sushi { background-position: -240px -780px; } -.emoji-suspension_railway { background-position: -260px -780px; } -.emoji-sweat { background-position: -280px -780px; } -.emoji-sweat_drops { background-position: -300px -780px; } -.emoji-sweat_smile { background-position: -320px -780px; } -.emoji-sweet_potato { background-position: -340px -780px; } -.emoji-swimmer { background-position: -360px -780px; } -.emoji-swimmer_tone1 { background-position: -380px -780px; } -.emoji-swimmer_tone2 { background-position: -400px -780px; } -.emoji-swimmer_tone3 { background-position: -420px -780px; } -.emoji-swimmer_tone4 { background-position: -440px -780px; } -.emoji-swimmer_tone5 { background-position: -460px -780px; } -.emoji-symbols { background-position: -480px -780px; } -.emoji-synagogue { background-position: -500px -780px; } -.emoji-syringe { background-position: -520px -780px; } -.emoji-taco { background-position: -540px -780px; } -.emoji-tada { background-position: -560px -780px; } -.emoji-tanabata_tree { background-position: -580px -780px; } -.emoji-tangerine { background-position: -600px -780px; } -.emoji-taurus { background-position: -620px -780px; } -.emoji-taxi { background-position: -640px -780px; } -.emoji-tea { background-position: -660px -780px; } -.emoji-telephone { background-position: -680px -780px; } -.emoji-telephone_receiver { background-position: -700px -780px; } -.emoji-telescope { background-position: -720px -780px; } -.emoji-ten { background-position: -740px -780px; } -.emoji-tennis { background-position: -760px -780px; } -.emoji-tent { background-position: -780px -780px; } -.emoji-thermometer { background-position: -800px 0; } -.emoji-thermometer_face { background-position: -800px -20px; } -.emoji-thinking { background-position: -800px -40px; } -.emoji-third_place { background-position: -800px -60px; } -.emoji-thought_balloon { background-position: -800px -80px; } -.emoji-three { background-position: -800px -100px; } -.emoji-thumbsdown { background-position: -800px -120px; } -.emoji-thumbsdown_tone1 { background-position: -800px -140px; } -.emoji-thumbsdown_tone2 { background-position: -800px -160px; } -.emoji-thumbsdown_tone3 { background-position: -800px -180px; } -.emoji-thumbsdown_tone4 { background-position: -800px -200px; } -.emoji-thumbsdown_tone5 { background-position: -800px -220px; } -.emoji-thumbsup { background-position: -800px -240px; } -.emoji-thumbsup_tone1 { background-position: -800px -260px; } -.emoji-thumbsup_tone2 { background-position: -800px -280px; } -.emoji-thumbsup_tone3 { background-position: -800px -300px; } -.emoji-thumbsup_tone4 { background-position: -800px -320px; } -.emoji-thumbsup_tone5 { background-position: -800px -340px; } -.emoji-thunder_cloud_rain { background-position: -800px -360px; } -.emoji-ticket { background-position: -800px -380px; } -.emoji-tickets { background-position: -800px -400px; } -.emoji-tiger { background-position: -800px -420px; } -.emoji-tiger2 { background-position: -800px -440px; } -.emoji-timer { background-position: -800px -460px; } -.emoji-tired_face { background-position: -800px -480px; } -.emoji-tm { background-position: -800px -500px; } -.emoji-toilet { background-position: -800px -520px; } -.emoji-tokyo_tower { background-position: -800px -540px; } -.emoji-tomato { background-position: -800px -560px; } -.emoji-tone1 { background-position: -800px -580px; } -.emoji-tone2 { background-position: -800px -600px; } -.emoji-tone3 { background-position: -800px -620px; } -.emoji-tone4 { background-position: -800px -640px; } -.emoji-tone5 { background-position: -800px -660px; } -.emoji-tongue { background-position: -800px -680px; } -.emoji-tools { background-position: -800px -700px; } -.emoji-top { background-position: -800px -720px; } -.emoji-tophat { background-position: -800px -740px; } -.emoji-track_next { background-position: -800px -760px; } -.emoji-track_previous { background-position: -800px -780px; } -.emoji-trackball { background-position: 0 -800px; } -.emoji-tractor { background-position: -20px -800px; } -.emoji-traffic_light { background-position: -40px -800px; } -.emoji-train { background-position: -60px -800px; } -.emoji-train2 { background-position: -80px -800px; } -.emoji-tram { background-position: -100px -800px; } -.emoji-triangular_flag_on_post { background-position: -120px -800px; } -.emoji-triangular_ruler { background-position: -140px -800px; } -.emoji-trident { background-position: -160px -800px; } -.emoji-triumph { background-position: -180px -800px; } -.emoji-trolleybus { background-position: -200px -800px; } -.emoji-trophy { background-position: -220px -800px; } -.emoji-tropical_drink { background-position: -240px -800px; } -.emoji-tropical_fish { background-position: -260px -800px; } -.emoji-truck { background-position: -280px -800px; } -.emoji-trumpet { background-position: -300px -800px; } -.emoji-tulip { background-position: -320px -800px; } -.emoji-tumbler_glass { background-position: -340px -800px; } -.emoji-turkey { background-position: -360px -800px; } -.emoji-turtle { background-position: -380px -800px; } -.emoji-tv { background-position: -400px -800px; } -.emoji-twisted_rightwards_arrows { background-position: -420px -800px; } -.emoji-two { background-position: -440px -800px; } -.emoji-two_hearts { background-position: -460px -800px; } -.emoji-two_men_holding_hands { background-position: -480px -800px; } -.emoji-two_women_holding_hands { background-position: -500px -800px; } -.emoji-u5272 { background-position: -520px -800px; } -.emoji-u5408 { background-position: -540px -800px; } -.emoji-u55b6 { background-position: -560px -800px; } -.emoji-u6307 { background-position: -580px -800px; } -.emoji-u6708 { background-position: -600px -800px; } -.emoji-u6709 { background-position: -620px -800px; } -.emoji-u6e80 { background-position: -640px -800px; } -.emoji-u7121 { background-position: -660px -800px; } -.emoji-u7533 { background-position: -680px -800px; } -.emoji-u7981 { background-position: -700px -800px; } -.emoji-u7a7a { background-position: -720px -800px; } -.emoji-umbrella { background-position: -740px -800px; } -.emoji-umbrella2 { background-position: -760px -800px; } -.emoji-unamused { background-position: -780px -800px; } -.emoji-underage { background-position: -800px -800px; } -.emoji-unicorn { background-position: -820px 0; } -.emoji-unlock { background-position: -820px -20px; } -.emoji-up { background-position: -820px -40px; } -.emoji-upside_down { background-position: -820px -60px; } -.emoji-urn { background-position: -820px -80px; } -.emoji-v { background-position: -820px -100px; } -.emoji-v_tone1 { background-position: -820px -120px; } -.emoji-v_tone2 { background-position: -820px -140px; } -.emoji-v_tone3 { background-position: -820px -160px; } -.emoji-v_tone4 { background-position: -820px -180px; } -.emoji-v_tone5 { background-position: -820px -200px; } -.emoji-vertical_traffic_light { background-position: -820px -220px; } -.emoji-vhs { background-position: -820px -240px; } -.emoji-vibration_mode { background-position: -820px -260px; } -.emoji-video_camera { background-position: -820px -280px; } -.emoji-video_game { background-position: -820px -300px; } -.emoji-violin { background-position: -820px -320px; } -.emoji-virgo { background-position: -820px -340px; } -.emoji-volcano { background-position: -820px -360px; } -.emoji-volleyball { background-position: -820px -380px; } -.emoji-vs { background-position: -820px -400px; } -.emoji-vulcan { background-position: -820px -420px; } -.emoji-vulcan_tone1 { background-position: -820px -440px; } -.emoji-vulcan_tone2 { background-position: -820px -460px; } -.emoji-vulcan_tone3 { background-position: -820px -480px; } -.emoji-vulcan_tone4 { background-position: -820px -500px; } -.emoji-vulcan_tone5 { background-position: -820px -520px; } -.emoji-walking { background-position: -820px -540px; } -.emoji-walking_tone1 { background-position: -820px -560px; } -.emoji-walking_tone2 { background-position: -820px -580px; } -.emoji-walking_tone3 { background-position: -820px -600px; } -.emoji-walking_tone4 { background-position: -820px -620px; } -.emoji-walking_tone5 { background-position: -820px -640px; } -.emoji-waning_crescent_moon { background-position: -820px -660px; } -.emoji-waning_gibbous_moon { background-position: -820px -680px; } -.emoji-warning { background-position: -820px -700px; } -.emoji-wastebasket { background-position: -820px -720px; } -.emoji-watch { background-position: -820px -740px; } -.emoji-water_buffalo { background-position: -820px -760px; } -.emoji-water_polo { background-position: -820px -780px; } -.emoji-water_polo_tone1 { background-position: -820px -800px; } -.emoji-water_polo_tone2 { background-position: 0 -820px; } -.emoji-water_polo_tone3 { background-position: -20px -820px; } -.emoji-water_polo_tone4 { background-position: -40px -820px; } -.emoji-water_polo_tone5 { background-position: -60px -820px; } -.emoji-watermelon { background-position: -80px -820px; } -.emoji-wave { background-position: -100px -820px; } -.emoji-wave_tone1 { background-position: -120px -820px; } -.emoji-wave_tone2 { background-position: -140px -820px; } -.emoji-wave_tone3 { background-position: -160px -820px; } -.emoji-wave_tone4 { background-position: -180px -820px; } -.emoji-wave_tone5 { background-position: -200px -820px; } -.emoji-wavy_dash { background-position: -220px -820px; } -.emoji-waxing_crescent_moon { background-position: -240px -820px; } -.emoji-waxing_gibbous_moon { background-position: -260px -820px; } -.emoji-wc { background-position: -280px -820px; } -.emoji-weary { background-position: -300px -820px; } -.emoji-wedding { background-position: -320px -820px; } -.emoji-whale { background-position: -340px -820px; } -.emoji-whale2 { background-position: -360px -820px; } -.emoji-wheel_of_dharma { background-position: -380px -820px; } -.emoji-wheelchair { background-position: -400px -820px; } -.emoji-white_check_mark { background-position: -420px -820px; } -.emoji-white_circle { background-position: -440px -820px; } -.emoji-white_flower { background-position: -460px -820px; } -.emoji-white_large_square { background-position: -480px -820px; } -.emoji-white_medium_small_square { background-position: -500px -820px; } -.emoji-white_medium_square { background-position: -520px -820px; } -.emoji-white_small_square { background-position: -540px -820px; } -.emoji-white_square_button { background-position: -560px -820px; } -.emoji-white_sun_cloud { background-position: -580px -820px; } -.emoji-white_sun_rain_cloud { background-position: -600px -820px; } -.emoji-white_sun_small_cloud { background-position: -620px -820px; } -.emoji-wilted_rose { background-position: -640px -820px; } -.emoji-wind_blowing_face { background-position: -660px -820px; } -.emoji-wind_chime { background-position: -680px -820px; } -.emoji-wine_glass { background-position: -700px -820px; } -.emoji-wink { background-position: -720px -820px; } -.emoji-wolf { background-position: -740px -820px; } -.emoji-woman { background-position: -760px -820px; } -.emoji-woman_tone1 { background-position: -780px -820px; } -.emoji-woman_tone2 { background-position: -800px -820px; } -.emoji-woman_tone3 { background-position: -820px -820px; } -.emoji-woman_tone4 { background-position: -840px 0; } -.emoji-woman_tone5 { background-position: -840px -20px; } -.emoji-womans_clothes { background-position: -840px -40px; } -.emoji-womans_hat { background-position: -840px -60px; } -.emoji-womens { background-position: -840px -80px; } -.emoji-worried { background-position: -840px -100px; } -.emoji-wrench { background-position: -840px -120px; } -.emoji-wrestlers { background-position: -840px -140px; } -.emoji-wrestlers_tone1 { background-position: -840px -160px; } -.emoji-wrestlers_tone2 { background-position: -840px -180px; } -.emoji-wrestlers_tone3 { background-position: -840px -200px; } -.emoji-wrestlers_tone4 { background-position: -840px -220px; } -.emoji-wrestlers_tone5 { background-position: -840px -240px; } -.emoji-writing_hand { background-position: -840px -260px; } -.emoji-writing_hand_tone1 { background-position: -840px -280px; } -.emoji-writing_hand_tone2 { background-position: -840px -300px; } -.emoji-writing_hand_tone3 { background-position: -840px -320px; } -.emoji-writing_hand_tone4 { background-position: -840px -340px; } -.emoji-writing_hand_tone5 { background-position: -840px -360px; } -.emoji-x { background-position: -840px -380px; } -.emoji-yellow_heart { background-position: -840px -400px; } -.emoji-yen { background-position: -840px -420px; } -.emoji-yin_yang { background-position: -840px -440px; } -.emoji-yum { background-position: -840px -460px; } -.emoji-zap { background-position: -840px -480px; } -.emoji-zero { background-position: -840px -500px; } -.emoji-zipper_mouth { background-position: -840px -520px; } -.emoji-100 { background-position: -840px -540px; } +.emoji-gay_pride_flag { background-position: -220px -540px; } +.emoji-gear { background-position: -240px -540px; } +.emoji-gem { background-position: -260px -540px; } +.emoji-gemini { background-position: -280px -540px; } +.emoji-ghost { background-position: -300px -540px; } +.emoji-gift { background-position: -320px -540px; } +.emoji-gift_heart { background-position: -340px -540px; } +.emoji-girl { background-position: -360px -540px; } +.emoji-girl_tone1 { background-position: -380px -540px; } +.emoji-girl_tone2 { background-position: -400px -540px; } +.emoji-girl_tone3 { background-position: -420px -540px; } +.emoji-girl_tone4 { background-position: -440px -540px; } +.emoji-girl_tone5 { background-position: -460px -540px; } +.emoji-globe_with_meridians { background-position: -480px -540px; } +.emoji-goal { background-position: -500px -540px; } +.emoji-goat { background-position: -520px -540px; } +.emoji-golf { background-position: -540px -540px; } +.emoji-golfer { background-position: -560px 0; } +.emoji-gorilla { background-position: -560px -20px; } +.emoji-grapes { background-position: -560px -40px; } +.emoji-green_apple { background-position: -560px -60px; } +.emoji-green_book { background-position: -560px -80px; } +.emoji-green_heart { background-position: -560px -100px; } +.emoji-grey_exclamation { background-position: -560px -120px; } +.emoji-grey_question { background-position: -560px -140px; } +.emoji-grimacing { background-position: -560px -160px; } +.emoji-grin { background-position: -560px -180px; } +.emoji-grinning { background-position: -560px -200px; } +.emoji-guardsman { background-position: -560px -220px; } +.emoji-guardsman_tone1 { background-position: -560px -240px; } +.emoji-guardsman_tone2 { background-position: -560px -260px; } +.emoji-guardsman_tone3 { background-position: -560px -280px; } +.emoji-guardsman_tone4 { background-position: -560px -300px; } +.emoji-guardsman_tone5 { background-position: -560px -320px; } +.emoji-guitar { background-position: -560px -340px; } +.emoji-gun { background-position: -560px -360px; } +.emoji-haircut { background-position: -560px -380px; } +.emoji-haircut_tone1 { background-position: -560px -400px; } +.emoji-haircut_tone2 { background-position: -560px -420px; } +.emoji-haircut_tone3 { background-position: -560px -440px; } +.emoji-haircut_tone4 { background-position: -560px -460px; } +.emoji-haircut_tone5 { background-position: -560px -480px; } +.emoji-hamburger { background-position: -560px -500px; } +.emoji-hammer { background-position: -560px -520px; } +.emoji-hammer_pick { background-position: -560px -540px; } +.emoji-hamster { background-position: 0 -560px; } +.emoji-hand_splayed { background-position: -20px -560px; } +.emoji-hand_splayed_tone1 { background-position: -40px -560px; } +.emoji-hand_splayed_tone2 { background-position: -60px -560px; } +.emoji-hand_splayed_tone3 { background-position: -80px -560px; } +.emoji-hand_splayed_tone4 { background-position: -100px -560px; } +.emoji-hand_splayed_tone5 { background-position: -120px -560px; } +.emoji-handbag { background-position: -140px -560px; } +.emoji-handball { background-position: -160px -560px; } +.emoji-handball_tone1 { background-position: -180px -560px; } +.emoji-handball_tone2 { background-position: -200px -560px; } +.emoji-handball_tone3 { background-position: -220px -560px; } +.emoji-handball_tone4 { background-position: -240px -560px; } +.emoji-handball_tone5 { background-position: -260px -560px; } +.emoji-handshake { background-position: -280px -560px; } +.emoji-handshake_tone1 { background-position: -300px -560px; } +.emoji-handshake_tone2 { background-position: -320px -560px; } +.emoji-handshake_tone3 { background-position: -340px -560px; } +.emoji-handshake_tone4 { background-position: -360px -560px; } +.emoji-handshake_tone5 { background-position: -380px -560px; } +.emoji-hash { background-position: -400px -560px; } +.emoji-hatched_chick { background-position: -420px -560px; } +.emoji-hatching_chick { background-position: -440px -560px; } +.emoji-head_bandage { background-position: -460px -560px; } +.emoji-headphones { background-position: -480px -560px; } +.emoji-hear_no_evil { background-position: -500px -560px; } +.emoji-heart { background-position: -520px -560px; } +.emoji-heart_decoration { background-position: -540px -560px; } +.emoji-heart_exclamation { background-position: -560px -560px; } +.emoji-heart_eyes { background-position: -580px 0; } +.emoji-heart_eyes_cat { background-position: -580px -20px; } +.emoji-heartbeat { background-position: -580px -40px; } +.emoji-heartpulse { background-position: -580px -60px; } +.emoji-hearts { background-position: -580px -80px; } +.emoji-heavy_check_mark { background-position: -580px -100px; } +.emoji-heavy_division_sign { background-position: -580px -120px; } +.emoji-heavy_dollar_sign { background-position: -580px -140px; } +.emoji-heavy_minus_sign { background-position: -580px -160px; } +.emoji-heavy_multiplication_x { background-position: -580px -180px; } +.emoji-heavy_plus_sign { background-position: -580px -200px; } +.emoji-helicopter { background-position: -580px -220px; } +.emoji-helmet_with_cross { background-position: -580px -240px; } +.emoji-herb { background-position: -580px -260px; } +.emoji-hibiscus { background-position: -580px -280px; } +.emoji-high_brightness { background-position: -580px -300px; } +.emoji-high_heel { background-position: -580px -320px; } +.emoji-hockey { background-position: -580px -340px; } +.emoji-hole { background-position: -580px -360px; } +.emoji-homes { background-position: -580px -380px; } +.emoji-honey_pot { background-position: -580px -400px; } +.emoji-horse { background-position: -580px -420px; } +.emoji-horse_racing { background-position: -580px -440px; } +.emoji-horse_racing_tone1 { background-position: -580px -460px; } +.emoji-horse_racing_tone2 { background-position: -580px -480px; } +.emoji-horse_racing_tone3 { background-position: -580px -500px; } +.emoji-horse_racing_tone4 { background-position: -580px -520px; } +.emoji-horse_racing_tone5 { background-position: -580px -540px; } +.emoji-hospital { background-position: -580px -560px; } +.emoji-hot_pepper { background-position: 0 -580px; } +.emoji-hotdog { background-position: -20px -580px; } +.emoji-hotel { background-position: -40px -580px; } +.emoji-hotsprings { background-position: -60px -580px; } +.emoji-hourglass { background-position: -80px -580px; } +.emoji-hourglass_flowing_sand { background-position: -100px -580px; } +.emoji-house { background-position: -120px -580px; } +.emoji-house_abandoned { background-position: -140px -580px; } +.emoji-house_with_garden { background-position: -160px -580px; } +.emoji-hugging { background-position: -180px -580px; } +.emoji-hushed { background-position: -200px -580px; } +.emoji-ice_cream { background-position: -220px -580px; } +.emoji-ice_skate { background-position: -240px -580px; } +.emoji-icecream { background-position: -260px -580px; } +.emoji-id { background-position: -280px -580px; } +.emoji-ideograph_advantage { background-position: -300px -580px; } +.emoji-imp { background-position: -320px -580px; } +.emoji-inbox_tray { background-position: -340px -580px; } +.emoji-incoming_envelope { background-position: -360px -580px; } +.emoji-information_desk_person { background-position: -380px -580px; } +.emoji-information_desk_person_tone1 { background-position: -400px -580px; } +.emoji-information_desk_person_tone2 { background-position: -420px -580px; } +.emoji-information_desk_person_tone3 { background-position: -440px -580px; } +.emoji-information_desk_person_tone4 { background-position: -460px -580px; } +.emoji-information_desk_person_tone5 { background-position: -480px -580px; } +.emoji-information_source { background-position: -500px -580px; } +.emoji-innocent { background-position: -520px -580px; } +.emoji-interrobang { background-position: -540px -580px; } +.emoji-iphone { background-position: -560px -580px; } +.emoji-island { background-position: -580px -580px; } +.emoji-izakaya_lantern { background-position: -600px 0; } +.emoji-jack_o_lantern { background-position: -600px -20px; } +.emoji-japan { background-position: -600px -40px; } +.emoji-japanese_castle { background-position: -600px -60px; } +.emoji-japanese_goblin { background-position: -600px -80px; } +.emoji-japanese_ogre { background-position: -600px -100px; } +.emoji-jeans { background-position: -600px -120px; } +.emoji-joy { background-position: -600px -140px; } +.emoji-joy_cat { background-position: -600px -160px; } +.emoji-joystick { background-position: -600px -180px; } +.emoji-juggling { background-position: -600px -200px; } +.emoji-juggling_tone1 { background-position: -600px -220px; } +.emoji-juggling_tone2 { background-position: -600px -240px; } +.emoji-juggling_tone3 { background-position: -600px -260px; } +.emoji-juggling_tone4 { background-position: -600px -280px; } +.emoji-juggling_tone5 { background-position: -600px -300px; } +.emoji-kaaba { background-position: -600px -320px; } +.emoji-key { background-position: -600px -340px; } +.emoji-key2 { background-position: -600px -360px; } +.emoji-keyboard { background-position: -600px -380px; } +.emoji-kimono { background-position: -600px -400px; } +.emoji-kiss { background-position: -600px -420px; } +.emoji-kiss_mm { background-position: -600px -440px; } +.emoji-kiss_ww { background-position: -600px -460px; } +.emoji-kissing { background-position: -600px -480px; } +.emoji-kissing_cat { background-position: -600px -500px; } +.emoji-kissing_closed_eyes { background-position: -600px -520px; } +.emoji-kissing_heart { background-position: -600px -540px; } +.emoji-kissing_smiling_eyes { background-position: -600px -560px; } +.emoji-kiwi { background-position: -600px -580px; } +.emoji-knife { background-position: 0 -600px; } +.emoji-koala { background-position: -20px -600px; } +.emoji-koko { background-position: -40px -600px; } +.emoji-label { background-position: -60px -600px; } +.emoji-large_blue_circle { background-position: -80px -600px; } +.emoji-large_blue_diamond { background-position: -100px -600px; } +.emoji-large_orange_diamond { background-position: -120px -600px; } +.emoji-last_quarter_moon { background-position: -140px -600px; } +.emoji-last_quarter_moon_with_face { background-position: -160px -600px; } +.emoji-laughing { background-position: -180px -600px; } +.emoji-leaves { background-position: -200px -600px; } +.emoji-ledger { background-position: -220px -600px; } +.emoji-left_facing_fist { background-position: -240px -600px; } +.emoji-left_facing_fist_tone1 { background-position: -260px -600px; } +.emoji-left_facing_fist_tone2 { background-position: -280px -600px; } +.emoji-left_facing_fist_tone3 { background-position: -300px -600px; } +.emoji-left_facing_fist_tone4 { background-position: -320px -600px; } +.emoji-left_facing_fist_tone5 { background-position: -340px -600px; } +.emoji-left_luggage { background-position: -360px -600px; } +.emoji-left_right_arrow { background-position: -380px -600px; } +.emoji-leftwards_arrow_with_hook { background-position: -400px -600px; } +.emoji-lemon { background-position: -420px -600px; } +.emoji-leo { background-position: -440px -600px; } +.emoji-leopard { background-position: -460px -600px; } +.emoji-level_slider { background-position: -480px -600px; } +.emoji-levitate { background-position: -500px -600px; } +.emoji-libra { background-position: -520px -600px; } +.emoji-lifter { background-position: -540px -600px; } +.emoji-lifter_tone1 { background-position: -560px -600px; } +.emoji-lifter_tone2 { background-position: -580px -600px; } +.emoji-lifter_tone3 { background-position: -600px -600px; } +.emoji-lifter_tone4 { background-position: -620px 0; } +.emoji-lifter_tone5 { background-position: -620px -20px; } +.emoji-light_rail { background-position: -620px -40px; } +.emoji-link { background-position: -620px -60px; } +.emoji-lion_face { background-position: -620px -80px; } +.emoji-lips { background-position: -620px -100px; } +.emoji-lipstick { background-position: -620px -120px; } +.emoji-lizard { background-position: -620px -140px; } +.emoji-lock { background-position: -620px -160px; } +.emoji-lock_with_ink_pen { background-position: -620px -180px; } +.emoji-lollipop { background-position: -620px -200px; } +.emoji-loop { background-position: -620px -220px; } +.emoji-loud_sound { background-position: -620px -240px; } +.emoji-loudspeaker { background-position: -620px -260px; } +.emoji-love_hotel { background-position: -620px -280px; } +.emoji-love_letter { background-position: -620px -300px; } +.emoji-low_brightness { background-position: -620px -320px; } +.emoji-lying_face { background-position: -620px -340px; } +.emoji-m { background-position: -620px -360px; } +.emoji-mag { background-position: -620px -380px; } +.emoji-mag_right { background-position: -620px -400px; } +.emoji-mahjong { background-position: -620px -420px; } +.emoji-mailbox { background-position: -620px -440px; } +.emoji-mailbox_closed { background-position: -620px -460px; } +.emoji-mailbox_with_mail { background-position: -620px -480px; } +.emoji-mailbox_with_no_mail { background-position: -620px -500px; } +.emoji-man { background-position: -620px -520px; } +.emoji-man_dancing { background-position: -620px -540px; } +.emoji-man_dancing_tone1 { background-position: -620px -560px; } +.emoji-man_dancing_tone2 { background-position: -620px -580px; } +.emoji-man_dancing_tone3 { background-position: -620px -600px; } +.emoji-man_dancing_tone4 { background-position: 0 -620px; } +.emoji-man_dancing_tone5 { background-position: -20px -620px; } +.emoji-man_in_tuxedo { background-position: -40px -620px; } +.emoji-man_in_tuxedo_tone1 { background-position: -60px -620px; } +.emoji-man_in_tuxedo_tone2 { background-position: -80px -620px; } +.emoji-man_in_tuxedo_tone3 { background-position: -100px -620px; } +.emoji-man_in_tuxedo_tone4 { background-position: -120px -620px; } +.emoji-man_in_tuxedo_tone5 { background-position: -140px -620px; } +.emoji-man_tone1 { background-position: -160px -620px; } +.emoji-man_tone2 { background-position: -180px -620px; } +.emoji-man_tone3 { background-position: -200px -620px; } +.emoji-man_tone4 { background-position: -220px -620px; } +.emoji-man_tone5 { background-position: -240px -620px; } +.emoji-man_with_gua_pi_mao { background-position: -260px -620px; } +.emoji-man_with_gua_pi_mao_tone1 { background-position: -280px -620px; } +.emoji-man_with_gua_pi_mao_tone2 { background-position: -300px -620px; } +.emoji-man_with_gua_pi_mao_tone3 { background-position: -320px -620px; } +.emoji-man_with_gua_pi_mao_tone4 { background-position: -340px -620px; } +.emoji-man_with_gua_pi_mao_tone5 { background-position: -360px -620px; } +.emoji-man_with_turban { background-position: -380px -620px; } +.emoji-man_with_turban_tone1 { background-position: -400px -620px; } +.emoji-man_with_turban_tone2 { background-position: -420px -620px; } +.emoji-man_with_turban_tone3 { background-position: -440px -620px; } +.emoji-man_with_turban_tone4 { background-position: -460px -620px; } +.emoji-man_with_turban_tone5 { background-position: -480px -620px; } +.emoji-mans_shoe { background-position: -500px -620px; } +.emoji-map { background-position: -520px -620px; } +.emoji-maple_leaf { background-position: -540px -620px; } +.emoji-martial_arts_uniform { background-position: -560px -620px; } +.emoji-mask { background-position: -580px -620px; } +.emoji-massage { background-position: -600px -620px; } +.emoji-massage_tone1 { background-position: -620px -620px; } +.emoji-massage_tone2 { background-position: -640px 0; } +.emoji-massage_tone3 { background-position: -640px -20px; } +.emoji-massage_tone4 { background-position: -640px -40px; } +.emoji-massage_tone5 { background-position: -640px -60px; } +.emoji-meat_on_bone { background-position: -640px -80px; } +.emoji-medal { background-position: -640px -100px; } +.emoji-mega { background-position: -640px -120px; } +.emoji-melon { background-position: -640px -140px; } +.emoji-menorah { background-position: -640px -160px; } +.emoji-mens { background-position: -640px -180px; } +.emoji-metal { background-position: -640px -200px; } +.emoji-metal_tone1 { background-position: -640px -220px; } +.emoji-metal_tone2 { background-position: -640px -240px; } +.emoji-metal_tone3 { background-position: -640px -260px; } +.emoji-metal_tone4 { background-position: -640px -280px; } +.emoji-metal_tone5 { background-position: -640px -300px; } +.emoji-metro { background-position: -640px -320px; } +.emoji-microphone { background-position: -640px -340px; } +.emoji-microphone2 { background-position: -640px -360px; } +.emoji-microscope { background-position: -640px -380px; } +.emoji-middle_finger { background-position: -640px -400px; } +.emoji-middle_finger_tone1 { background-position: -640px -420px; } +.emoji-middle_finger_tone2 { background-position: -640px -440px; } +.emoji-middle_finger_tone3 { background-position: -640px -460px; } +.emoji-middle_finger_tone4 { background-position: -640px -480px; } +.emoji-middle_finger_tone5 { background-position: -640px -500px; } +.emoji-military_medal { background-position: -640px -520px; } +.emoji-milk { background-position: -640px -540px; } +.emoji-milky_way { background-position: -640px -560px; } +.emoji-minibus { background-position: -640px -580px; } +.emoji-minidisc { background-position: -640px -600px; } +.emoji-mobile_phone_off { background-position: -640px -620px; } +.emoji-money_mouth { background-position: 0 -640px; } +.emoji-money_with_wings { background-position: -20px -640px; } +.emoji-moneybag { background-position: -40px -640px; } +.emoji-monkey { background-position: -60px -640px; } +.emoji-monkey_face { background-position: -80px -640px; } +.emoji-monorail { background-position: -100px -640px; } +.emoji-mortar_board { background-position: -120px -640px; } +.emoji-mosque { background-position: -140px -640px; } +.emoji-motor_scooter { background-position: -160px -640px; } +.emoji-motorboat { background-position: -180px -640px; } +.emoji-motorcycle { background-position: -200px -640px; } +.emoji-motorway { background-position: -220px -640px; } +.emoji-mount_fuji { background-position: -240px -640px; } +.emoji-mountain { background-position: -260px -640px; } +.emoji-mountain_bicyclist { background-position: -280px -640px; } +.emoji-mountain_bicyclist_tone1 { background-position: -300px -640px; } +.emoji-mountain_bicyclist_tone2 { background-position: -320px -640px; } +.emoji-mountain_bicyclist_tone3 { background-position: -340px -640px; } +.emoji-mountain_bicyclist_tone4 { background-position: -360px -640px; } +.emoji-mountain_bicyclist_tone5 { background-position: -380px -640px; } +.emoji-mountain_cableway { background-position: -400px -640px; } +.emoji-mountain_railway { background-position: -420px -640px; } +.emoji-mountain_snow { background-position: -440px -640px; } +.emoji-mouse { background-position: -460px -640px; } +.emoji-mouse2 { background-position: -480px -640px; } +.emoji-mouse_three_button { background-position: -500px -640px; } +.emoji-movie_camera { background-position: -520px -640px; } +.emoji-moyai { background-position: -540px -640px; } +.emoji-mrs_claus { background-position: -560px -640px; } +.emoji-mrs_claus_tone1 { background-position: -580px -640px; } +.emoji-mrs_claus_tone2 { background-position: -600px -640px; } +.emoji-mrs_claus_tone3 { background-position: -620px -640px; } +.emoji-mrs_claus_tone4 { background-position: -640px -640px; } +.emoji-mrs_claus_tone5 { background-position: -660px 0; } +.emoji-muscle { background-position: -660px -20px; } +.emoji-muscle_tone1 { background-position: -660px -40px; } +.emoji-muscle_tone2 { background-position: -660px -60px; } +.emoji-muscle_tone3 { background-position: -660px -80px; } +.emoji-muscle_tone4 { background-position: -660px -100px; } +.emoji-muscle_tone5 { background-position: -660px -120px; } +.emoji-mushroom { background-position: -660px -140px; } +.emoji-musical_keyboard { background-position: -660px -160px; } +.emoji-musical_note { background-position: -660px -180px; } +.emoji-musical_score { background-position: -660px -200px; } +.emoji-mute { background-position: -660px -220px; } +.emoji-nail_care { background-position: -660px -240px; } +.emoji-nail_care_tone1 { background-position: -660px -260px; } +.emoji-nail_care_tone2 { background-position: -660px -280px; } +.emoji-nail_care_tone3 { background-position: -660px -300px; } +.emoji-nail_care_tone4 { background-position: -660px -320px; } +.emoji-nail_care_tone5 { background-position: -660px -340px; } +.emoji-name_badge { background-position: -660px -360px; } +.emoji-nauseated_face { background-position: -660px -380px; } +.emoji-necktie { background-position: -660px -400px; } +.emoji-negative_squared_cross_mark { background-position: -660px -420px; } +.emoji-nerd { background-position: -660px -440px; } +.emoji-neutral_face { background-position: -660px -460px; } +.emoji-new { background-position: -660px -480px; } +.emoji-new_moon { background-position: -660px -500px; } +.emoji-new_moon_with_face { background-position: -660px -520px; } +.emoji-newspaper { background-position: -660px -540px; } +.emoji-newspaper2 { background-position: -660px -560px; } +.emoji-ng { background-position: -660px -580px; } +.emoji-night_with_stars { background-position: -660px -600px; } +.emoji-nine { background-position: -660px -620px; } +.emoji-no_bell { background-position: -660px -640px; } +.emoji-no_bicycles { background-position: 0 -660px; } +.emoji-no_entry { background-position: -20px -660px; } +.emoji-no_entry_sign { background-position: -40px -660px; } +.emoji-no_good { background-position: -60px -660px; } +.emoji-no_good_tone1 { background-position: -80px -660px; } +.emoji-no_good_tone2 { background-position: -100px -660px; } +.emoji-no_good_tone3 { background-position: -120px -660px; } +.emoji-no_good_tone4 { background-position: -140px -660px; } +.emoji-no_good_tone5 { background-position: -160px -660px; } +.emoji-no_mobile_phones { background-position: -180px -660px; } +.emoji-no_mouth { background-position: -200px -660px; } +.emoji-no_pedestrians { background-position: -220px -660px; } +.emoji-no_smoking { background-position: -240px -660px; } +.emoji-non-potable_water { background-position: -260px -660px; } +.emoji-nose { background-position: -280px -660px; } +.emoji-nose_tone1 { background-position: -300px -660px; } +.emoji-nose_tone2 { background-position: -320px -660px; } +.emoji-nose_tone3 { background-position: -340px -660px; } +.emoji-nose_tone4 { background-position: -360px -660px; } +.emoji-nose_tone5 { background-position: -380px -660px; } +.emoji-notebook { background-position: -400px -660px; } +.emoji-notebook_with_decorative_cover { background-position: -420px -660px; } +.emoji-notepad_spiral { background-position: -440px -660px; } +.emoji-notes { background-position: -460px -660px; } +.emoji-nut_and_bolt { background-position: -480px -660px; } +.emoji-o { background-position: -500px -660px; } +.emoji-o2 { background-position: -520px -660px; } +.emoji-ocean { background-position: -540px -660px; } +.emoji-octagonal_sign { background-position: -560px -660px; } +.emoji-octopus { background-position: -580px -660px; } +.emoji-oden { background-position: -600px -660px; } +.emoji-office { background-position: -620px -660px; } +.emoji-oil { background-position: -640px -660px; } +.emoji-ok { background-position: -660px -660px; } +.emoji-ok_hand { background-position: -680px 0; } +.emoji-ok_hand_tone1 { background-position: -680px -20px; } +.emoji-ok_hand_tone2 { background-position: -680px -40px; } +.emoji-ok_hand_tone3 { background-position: -680px -60px; } +.emoji-ok_hand_tone4 { background-position: -680px -80px; } +.emoji-ok_hand_tone5 { background-position: -680px -100px; } +.emoji-ok_woman { background-position: -680px -120px; } +.emoji-ok_woman_tone1 { background-position: -680px -140px; } +.emoji-ok_woman_tone2 { background-position: -680px -160px; } +.emoji-ok_woman_tone3 { background-position: -680px -180px; } +.emoji-ok_woman_tone4 { background-position: -680px -200px; } +.emoji-ok_woman_tone5 { background-position: -680px -220px; } +.emoji-older_man { background-position: -680px -240px; } +.emoji-older_man_tone1 { background-position: -680px -260px; } +.emoji-older_man_tone2 { background-position: -680px -280px; } +.emoji-older_man_tone3 { background-position: -680px -300px; } +.emoji-older_man_tone4 { background-position: -680px -320px; } +.emoji-older_man_tone5 { background-position: -680px -340px; } +.emoji-older_woman { background-position: -680px -360px; } +.emoji-older_woman_tone1 { background-position: -680px -380px; } +.emoji-older_woman_tone2 { background-position: -680px -400px; } +.emoji-older_woman_tone3 { background-position: -680px -420px; } +.emoji-older_woman_tone4 { background-position: -680px -440px; } +.emoji-older_woman_tone5 { background-position: -680px -460px; } +.emoji-om_symbol { background-position: -680px -480px; } +.emoji-on { background-position: -680px -500px; } +.emoji-oncoming_automobile { background-position: -680px -520px; } +.emoji-oncoming_bus { background-position: -680px -540px; } +.emoji-oncoming_police_car { background-position: -680px -560px; } +.emoji-oncoming_taxi { background-position: -680px -580px; } +.emoji-one { background-position: -680px -600px; } +.emoji-open_file_folder { background-position: -680px -620px; } +.emoji-open_hands { background-position: -680px -640px; } +.emoji-open_hands_tone1 { background-position: -680px -660px; } +.emoji-open_hands_tone2 { background-position: 0 -680px; } +.emoji-open_hands_tone3 { background-position: -20px -680px; } +.emoji-open_hands_tone4 { background-position: -40px -680px; } +.emoji-open_hands_tone5 { background-position: -60px -680px; } +.emoji-open_mouth { background-position: -80px -680px; } +.emoji-ophiuchus { background-position: -100px -680px; } +.emoji-orange_book { background-position: -120px -680px; } +.emoji-orthodox_cross { background-position: -140px -680px; } +.emoji-outbox_tray { background-position: -160px -680px; } +.emoji-owl { background-position: -180px -680px; } +.emoji-ox { background-position: -200px -680px; } +.emoji-package { background-position: -220px -680px; } +.emoji-page_facing_up { background-position: -240px -680px; } +.emoji-page_with_curl { background-position: -260px -680px; } +.emoji-pager { background-position: -280px -680px; } +.emoji-paintbrush { background-position: -300px -680px; } +.emoji-palm_tree { background-position: -320px -680px; } +.emoji-pancakes { background-position: -340px -680px; } +.emoji-panda_face { background-position: -360px -680px; } +.emoji-paperclip { background-position: -380px -680px; } +.emoji-paperclips { background-position: -400px -680px; } +.emoji-park { background-position: -420px -680px; } +.emoji-parking { background-position: -440px -680px; } +.emoji-part_alternation_mark { background-position: -460px -680px; } +.emoji-partly_sunny { background-position: -480px -680px; } +.emoji-passport_control { background-position: -500px -680px; } +.emoji-pause_button { background-position: -520px -680px; } +.emoji-peace { background-position: -540px -680px; } +.emoji-peach { background-position: -560px -680px; } +.emoji-peanuts { background-position: -580px -680px; } +.emoji-pear { background-position: -600px -680px; } +.emoji-pen_ballpoint { background-position: -620px -680px; } +.emoji-pen_fountain { background-position: -640px -680px; } +.emoji-pencil { background-position: -660px -680px; } +.emoji-pencil2 { background-position: -680px -680px; } +.emoji-penguin { background-position: -700px 0; } +.emoji-pensive { background-position: -700px -20px; } +.emoji-performing_arts { background-position: -700px -40px; } +.emoji-persevere { background-position: -700px -60px; } +.emoji-person_frowning { background-position: -700px -80px; } +.emoji-person_frowning_tone1 { background-position: -700px -100px; } +.emoji-person_frowning_tone2 { background-position: -700px -120px; } +.emoji-person_frowning_tone3 { background-position: -700px -140px; } +.emoji-person_frowning_tone4 { background-position: -700px -160px; } +.emoji-person_frowning_tone5 { background-position: -700px -180px; } +.emoji-person_with_blond_hair { background-position: -700px -200px; } +.emoji-person_with_blond_hair_tone1 { background-position: -700px -220px; } +.emoji-person_with_blond_hair_tone2 { background-position: -700px -240px; } +.emoji-person_with_blond_hair_tone3 { background-position: -700px -260px; } +.emoji-person_with_blond_hair_tone4 { background-position: -700px -280px; } +.emoji-person_with_blond_hair_tone5 { background-position: -700px -300px; } +.emoji-person_with_pouting_face { background-position: -700px -320px; } +.emoji-person_with_pouting_face_tone1 { background-position: -700px -340px; } +.emoji-person_with_pouting_face_tone2 { background-position: -700px -360px; } +.emoji-person_with_pouting_face_tone3 { background-position: -700px -380px; } +.emoji-person_with_pouting_face_tone4 { background-position: -700px -400px; } +.emoji-person_with_pouting_face_tone5 { background-position: -700px -420px; } +.emoji-pick { background-position: -700px -440px; } +.emoji-pig { background-position: -700px -460px; } +.emoji-pig2 { background-position: -700px -480px; } +.emoji-pig_nose { background-position: -700px -500px; } +.emoji-pill { background-position: -700px -520px; } +.emoji-pineapple { background-position: -700px -540px; } +.emoji-ping_pong { background-position: -700px -560px; } +.emoji-pisces { background-position: -700px -580px; } +.emoji-pizza { background-position: -700px -600px; } +.emoji-place_of_worship { background-position: -700px -620px; } +.emoji-play_pause { background-position: -700px -640px; } +.emoji-point_down { background-position: -700px -660px; } +.emoji-point_down_tone1 { background-position: -700px -680px; } +.emoji-point_down_tone2 { background-position: 0 -700px; } +.emoji-point_down_tone3 { background-position: -20px -700px; } +.emoji-point_down_tone4 { background-position: -40px -700px; } +.emoji-point_down_tone5 { background-position: -60px -700px; } +.emoji-point_left { background-position: -80px -700px; } +.emoji-point_left_tone1 { background-position: -100px -700px; } +.emoji-point_left_tone2 { background-position: -120px -700px; } +.emoji-point_left_tone3 { background-position: -140px -700px; } +.emoji-point_left_tone4 { background-position: -160px -700px; } +.emoji-point_left_tone5 { background-position: -180px -700px; } +.emoji-point_right { background-position: -200px -700px; } +.emoji-point_right_tone1 { background-position: -220px -700px; } +.emoji-point_right_tone2 { background-position: -240px -700px; } +.emoji-point_right_tone3 { background-position: -260px -700px; } +.emoji-point_right_tone4 { background-position: -280px -700px; } +.emoji-point_right_tone5 { background-position: -300px -700px; } +.emoji-point_up { background-position: -320px -700px; } +.emoji-point_up_2 { background-position: -340px -700px; } +.emoji-point_up_2_tone1 { background-position: -360px -700px; } +.emoji-point_up_2_tone2 { background-position: -380px -700px; } +.emoji-point_up_2_tone3 { background-position: -400px -700px; } +.emoji-point_up_2_tone4 { background-position: -420px -700px; } +.emoji-point_up_2_tone5 { background-position: -440px -700px; } +.emoji-point_up_tone1 { background-position: -460px -700px; } +.emoji-point_up_tone2 { background-position: -480px -700px; } +.emoji-point_up_tone3 { background-position: -500px -700px; } +.emoji-point_up_tone4 { background-position: -520px -700px; } +.emoji-point_up_tone5 { background-position: -540px -700px; } +.emoji-police_car { background-position: -560px -700px; } +.emoji-poodle { background-position: -580px -700px; } +.emoji-poop { background-position: -600px -700px; } +.emoji-popcorn { background-position: -620px -700px; } +.emoji-post_office { background-position: -640px -700px; } +.emoji-postal_horn { background-position: -660px -700px; } +.emoji-postbox { background-position: -680px -700px; } +.emoji-potable_water { background-position: -700px -700px; } +.emoji-potato { background-position: -720px 0; } +.emoji-pouch { background-position: -720px -20px; } +.emoji-poultry_leg { background-position: -720px -40px; } +.emoji-pound { background-position: -720px -60px; } +.emoji-pouting_cat { background-position: -720px -80px; } +.emoji-pray { background-position: -720px -100px; } +.emoji-pray_tone1 { background-position: -720px -120px; } +.emoji-pray_tone2 { background-position: -720px -140px; } +.emoji-pray_tone3 { background-position: -720px -160px; } +.emoji-pray_tone4 { background-position: -720px -180px; } +.emoji-pray_tone5 { background-position: -720px -200px; } +.emoji-prayer_beads { background-position: -720px -220px; } +.emoji-pregnant_woman { background-position: -720px -240px; } +.emoji-pregnant_woman_tone1 { background-position: -720px -260px; } +.emoji-pregnant_woman_tone2 { background-position: -720px -280px; } +.emoji-pregnant_woman_tone3 { background-position: -720px -300px; } +.emoji-pregnant_woman_tone4 { background-position: -720px -320px; } +.emoji-pregnant_woman_tone5 { background-position: -720px -340px; } +.emoji-prince { background-position: -720px -360px; } +.emoji-prince_tone1 { background-position: -720px -380px; } +.emoji-prince_tone2 { background-position: -720px -400px; } +.emoji-prince_tone3 { background-position: -720px -420px; } +.emoji-prince_tone4 { background-position: -720px -440px; } +.emoji-prince_tone5 { background-position: -720px -460px; } +.emoji-princess { background-position: -720px -480px; } +.emoji-princess_tone1 { background-position: -720px -500px; } +.emoji-princess_tone2 { background-position: -720px -520px; } +.emoji-princess_tone3 { background-position: -720px -540px; } +.emoji-princess_tone4 { background-position: -720px -560px; } +.emoji-princess_tone5 { background-position: -720px -580px; } +.emoji-printer { background-position: -720px -600px; } +.emoji-projector { background-position: -720px -620px; } +.emoji-punch { background-position: -720px -640px; } +.emoji-punch_tone1 { background-position: -720px -660px; } +.emoji-punch_tone2 { background-position: -720px -680px; } +.emoji-punch_tone3 { background-position: -720px -700px; } +.emoji-punch_tone4 { background-position: 0 -720px; } +.emoji-punch_tone5 { background-position: -20px -720px; } +.emoji-purple_heart { background-position: -40px -720px; } +.emoji-purse { background-position: -60px -720px; } +.emoji-pushpin { background-position: -80px -720px; } +.emoji-put_litter_in_its_place { background-position: -100px -720px; } +.emoji-question { background-position: -120px -720px; } +.emoji-rabbit { background-position: -140px -720px; } +.emoji-rabbit2 { background-position: -160px -720px; } +.emoji-race_car { background-position: -180px -720px; } +.emoji-racehorse { background-position: -200px -720px; } +.emoji-radio { background-position: -220px -720px; } +.emoji-radio_button { background-position: -240px -720px; } +.emoji-radioactive { background-position: -260px -720px; } +.emoji-rage { background-position: -280px -720px; } +.emoji-railway_car { background-position: -300px -720px; } +.emoji-railway_track { background-position: -320px -720px; } +.emoji-rainbow { background-position: -340px -720px; } +.emoji-raised_back_of_hand { background-position: -360px -720px; } +.emoji-raised_back_of_hand_tone1 { background-position: -380px -720px; } +.emoji-raised_back_of_hand_tone2 { background-position: -400px -720px; } +.emoji-raised_back_of_hand_tone3 { background-position: -420px -720px; } +.emoji-raised_back_of_hand_tone4 { background-position: -440px -720px; } +.emoji-raised_back_of_hand_tone5 { background-position: -460px -720px; } +.emoji-raised_hand { background-position: -480px -720px; } +.emoji-raised_hand_tone1 { background-position: -500px -720px; } +.emoji-raised_hand_tone2 { background-position: -520px -720px; } +.emoji-raised_hand_tone3 { background-position: -540px -720px; } +.emoji-raised_hand_tone4 { background-position: -560px -720px; } +.emoji-raised_hand_tone5 { background-position: -580px -720px; } +.emoji-raised_hands { background-position: -600px -720px; } +.emoji-raised_hands_tone1 { background-position: -620px -720px; } +.emoji-raised_hands_tone2 { background-position: -640px -720px; } +.emoji-raised_hands_tone3 { background-position: -660px -720px; } +.emoji-raised_hands_tone4 { background-position: -680px -720px; } +.emoji-raised_hands_tone5 { background-position: -700px -720px; } +.emoji-raising_hand { background-position: -720px -720px; } +.emoji-raising_hand_tone1 { background-position: -740px 0; } +.emoji-raising_hand_tone2 { background-position: -740px -20px; } +.emoji-raising_hand_tone3 { background-position: -740px -40px; } +.emoji-raising_hand_tone4 { background-position: -740px -60px; } +.emoji-raising_hand_tone5 { background-position: -740px -80px; } +.emoji-ram { background-position: -740px -100px; } +.emoji-ramen { background-position: -740px -120px; } +.emoji-rat { background-position: -740px -140px; } +.emoji-record_button { background-position: -740px -160px; } +.emoji-recycle { background-position: -740px -180px; } +.emoji-red_car { background-position: -740px -200px; } +.emoji-red_circle { background-position: -740px -220px; } +.emoji-registered { background-position: -740px -240px; } +.emoji-relaxed { background-position: -740px -260px; } +.emoji-relieved { background-position: -740px -280px; } +.emoji-reminder_ribbon { background-position: -740px -300px; } +.emoji-repeat { background-position: -740px -320px; } +.emoji-repeat_one { background-position: -740px -340px; } +.emoji-restroom { background-position: -740px -360px; } +.emoji-revolving_hearts { background-position: -740px -380px; } +.emoji-rewind { background-position: -740px -400px; } +.emoji-rhino { background-position: -740px -420px; } +.emoji-ribbon { background-position: -740px -440px; } +.emoji-rice { background-position: -740px -460px; } +.emoji-rice_ball { background-position: -740px -480px; } +.emoji-rice_cracker { background-position: -740px -500px; } +.emoji-rice_scene { background-position: -740px -520px; } +.emoji-right_facing_fist { background-position: -740px -540px; } +.emoji-right_facing_fist_tone1 { background-position: -740px -560px; } +.emoji-right_facing_fist_tone2 { background-position: -740px -580px; } +.emoji-right_facing_fist_tone3 { background-position: -740px -600px; } +.emoji-right_facing_fist_tone4 { background-position: -740px -620px; } +.emoji-right_facing_fist_tone5 { background-position: -740px -640px; } +.emoji-ring { background-position: -740px -660px; } +.emoji-robot { background-position: -740px -680px; } +.emoji-rocket { background-position: -740px -700px; } +.emoji-rofl { background-position: -740px -720px; } +.emoji-roller_coaster { background-position: 0 -740px; } +.emoji-rolling_eyes { background-position: -20px -740px; } +.emoji-rooster { background-position: -40px -740px; } +.emoji-rose { background-position: -60px -740px; } +.emoji-rosette { background-position: -80px -740px; } +.emoji-rotating_light { background-position: -100px -740px; } +.emoji-round_pushpin { background-position: -120px -740px; } +.emoji-rowboat { background-position: -140px -740px; } +.emoji-rowboat_tone1 { background-position: -160px -740px; } +.emoji-rowboat_tone2 { background-position: -180px -740px; } +.emoji-rowboat_tone3 { background-position: -200px -740px; } +.emoji-rowboat_tone4 { background-position: -220px -740px; } +.emoji-rowboat_tone5 { background-position: -240px -740px; } +.emoji-rugby_football { background-position: -260px -740px; } +.emoji-runner { background-position: -280px -740px; } +.emoji-runner_tone1 { background-position: -300px -740px; } +.emoji-runner_tone2 { background-position: -320px -740px; } +.emoji-runner_tone3 { background-position: -340px -740px; } +.emoji-runner_tone4 { background-position: -360px -740px; } +.emoji-runner_tone5 { background-position: -380px -740px; } +.emoji-running_shirt_with_sash { background-position: -400px -740px; } +.emoji-sa { background-position: -420px -740px; } +.emoji-sagittarius { background-position: -440px -740px; } +.emoji-sailboat { background-position: -460px -740px; } +.emoji-sake { background-position: -480px -740px; } +.emoji-salad { background-position: -500px -740px; } +.emoji-sandal { background-position: -520px -740px; } +.emoji-santa { background-position: -540px -740px; } +.emoji-santa_tone1 { background-position: -560px -740px; } +.emoji-santa_tone2 { background-position: -580px -740px; } +.emoji-santa_tone3 { background-position: -600px -740px; } +.emoji-santa_tone4 { background-position: -620px -740px; } +.emoji-santa_tone5 { background-position: -640px -740px; } +.emoji-satellite { background-position: -660px -740px; } +.emoji-satellite_orbital { background-position: -680px -740px; } +.emoji-saxophone { background-position: -700px -740px; } +.emoji-scales { background-position: -720px -740px; } +.emoji-school { background-position: -740px -740px; } +.emoji-school_satchel { background-position: -760px 0; } +.emoji-scissors { background-position: -760px -20px; } +.emoji-scooter { background-position: -760px -40px; } +.emoji-scorpion { background-position: -760px -60px; } +.emoji-scorpius { background-position: -760px -80px; } +.emoji-scream { background-position: -760px -100px; } +.emoji-scream_cat { background-position: -760px -120px; } +.emoji-scroll { background-position: -760px -140px; } +.emoji-seat { background-position: -760px -160px; } +.emoji-second_place { background-position: -760px -180px; } +.emoji-secret { background-position: -760px -200px; } +.emoji-see_no_evil { background-position: -760px -220px; } +.emoji-seedling { background-position: -760px -240px; } +.emoji-selfie { background-position: -760px -260px; } +.emoji-selfie_tone1 { background-position: -760px -280px; } +.emoji-selfie_tone2 { background-position: -760px -300px; } +.emoji-selfie_tone3 { background-position: -760px -320px; } +.emoji-selfie_tone4 { background-position: -760px -340px; } +.emoji-selfie_tone5 { background-position: -760px -360px; } +.emoji-seven { background-position: -760px -380px; } +.emoji-shallow_pan_of_food { background-position: -760px -400px; } +.emoji-shamrock { background-position: -760px -420px; } +.emoji-shark { background-position: -760px -440px; } +.emoji-shaved_ice { background-position: -760px -460px; } +.emoji-sheep { background-position: -760px -480px; } +.emoji-shell { background-position: -760px -500px; } +.emoji-shield { background-position: -760px -520px; } +.emoji-shinto_shrine { background-position: -760px -540px; } +.emoji-ship { background-position: -760px -560px; } +.emoji-shirt { background-position: -760px -580px; } +.emoji-shopping_bags { background-position: -760px -600px; } +.emoji-shopping_cart { background-position: -760px -620px; } +.emoji-shower { background-position: -760px -640px; } +.emoji-shrimp { background-position: -760px -660px; } +.emoji-shrug { background-position: -760px -680px; } +.emoji-shrug_tone1 { background-position: -760px -700px; } +.emoji-shrug_tone2 { background-position: -760px -720px; } +.emoji-shrug_tone3 { background-position: -760px -740px; } +.emoji-shrug_tone4 { background-position: 0 -760px; } +.emoji-shrug_tone5 { background-position: -20px -760px; } +.emoji-signal_strength { background-position: -40px -760px; } +.emoji-six { background-position: -60px -760px; } +.emoji-six_pointed_star { background-position: -80px -760px; } +.emoji-ski { background-position: -100px -760px; } +.emoji-skier { background-position: -120px -760px; } +.emoji-skull { background-position: -140px -760px; } +.emoji-skull_crossbones { background-position: -160px -760px; } +.emoji-sleeping { background-position: -180px -760px; } +.emoji-sleeping_accommodation { background-position: -200px -760px; } +.emoji-sleepy { background-position: -220px -760px; } +.emoji-slight_frown { background-position: -240px -760px; } +.emoji-slight_smile { background-position: -260px -760px; } +.emoji-slot_machine { background-position: -280px -760px; } +.emoji-small_blue_diamond { background-position: -300px -760px; } +.emoji-small_orange_diamond { background-position: -320px -760px; } +.emoji-small_red_triangle { background-position: -340px -760px; } +.emoji-small_red_triangle_down { background-position: -360px -760px; } +.emoji-smile { background-position: -380px -760px; } +.emoji-smile_cat { background-position: -400px -760px; } +.emoji-smiley { background-position: -420px -760px; } +.emoji-smiley_cat { background-position: -440px -760px; } +.emoji-smiling_imp { background-position: -460px -760px; } +.emoji-smirk { background-position: -480px -760px; } +.emoji-smirk_cat { background-position: -500px -760px; } +.emoji-smoking { background-position: -520px -760px; } +.emoji-snail { background-position: -540px -760px; } +.emoji-snake { background-position: -560px -760px; } +.emoji-sneezing_face { background-position: -580px -760px; } +.emoji-snowboarder { background-position: -600px -760px; } +.emoji-snowflake { background-position: -620px -760px; } +.emoji-snowman { background-position: -640px -760px; } +.emoji-snowman2 { background-position: -660px -760px; } +.emoji-sob { background-position: -680px -760px; } +.emoji-soccer { background-position: -700px -760px; } +.emoji-soon { background-position: -720px -760px; } +.emoji-sos { background-position: -740px -760px; } +.emoji-sound { background-position: -760px -760px; } +.emoji-space_invader { background-position: -780px 0; } +.emoji-spades { background-position: -780px -20px; } +.emoji-spaghetti { background-position: -780px -40px; } +.emoji-sparkle { background-position: -780px -60px; } +.emoji-sparkler { background-position: -780px -80px; } +.emoji-sparkles { background-position: -780px -100px; } +.emoji-sparkling_heart { background-position: -780px -120px; } +.emoji-speak_no_evil { background-position: -780px -140px; } +.emoji-speaker { background-position: -780px -160px; } +.emoji-speaking_head { background-position: -780px -180px; } +.emoji-speech_balloon { background-position: -780px -200px; } +.emoji-speech_left { background-position: -780px -220px; } +.emoji-speedboat { background-position: -780px -240px; } +.emoji-spider { background-position: -780px -260px; } +.emoji-spider_web { background-position: -780px -280px; } +.emoji-spoon { background-position: -780px -300px; } +.emoji-spy { background-position: -780px -320px; } +.emoji-spy_tone1 { background-position: -780px -340px; } +.emoji-spy_tone2 { background-position: -780px -360px; } +.emoji-spy_tone3 { background-position: -780px -380px; } +.emoji-spy_tone4 { background-position: -780px -400px; } +.emoji-spy_tone5 { background-position: -780px -420px; } +.emoji-squid { background-position: -780px -440px; } +.emoji-stadium { background-position: -780px -460px; } +.emoji-star { background-position: -780px -480px; } +.emoji-star2 { background-position: -780px -500px; } +.emoji-star_and_crescent { background-position: -780px -520px; } +.emoji-star_of_david { background-position: -780px -540px; } +.emoji-stars { background-position: -780px -560px; } +.emoji-station { background-position: -780px -580px; } +.emoji-statue_of_liberty { background-position: -780px -600px; } +.emoji-steam_locomotive { background-position: -780px -620px; } +.emoji-stew { background-position: -780px -640px; } +.emoji-stop_button { background-position: -780px -660px; } +.emoji-stopwatch { background-position: -780px -680px; } +.emoji-straight_ruler { background-position: -780px -700px; } +.emoji-strawberry { background-position: -780px -720px; } +.emoji-stuck_out_tongue { background-position: -780px -740px; } +.emoji-stuck_out_tongue_closed_eyes { background-position: -780px -760px; } +.emoji-stuck_out_tongue_winking_eye { background-position: 0 -780px; } +.emoji-stuffed_flatbread { background-position: -20px -780px; } +.emoji-sun_with_face { background-position: -40px -780px; } +.emoji-sunflower { background-position: -60px -780px; } +.emoji-sunglasses { background-position: -80px -780px; } +.emoji-sunny { background-position: -100px -780px; } +.emoji-sunrise { background-position: -120px -780px; } +.emoji-sunrise_over_mountains { background-position: -140px -780px; } +.emoji-surfer { background-position: -160px -780px; } +.emoji-surfer_tone1 { background-position: -180px -780px; } +.emoji-surfer_tone2 { background-position: -200px -780px; } +.emoji-surfer_tone3 { background-position: -220px -780px; } +.emoji-surfer_tone4 { background-position: -240px -780px; } +.emoji-surfer_tone5 { background-position: -260px -780px; } +.emoji-sushi { background-position: -280px -780px; } +.emoji-suspension_railway { background-position: -300px -780px; } +.emoji-sweat { background-position: -320px -780px; } +.emoji-sweat_drops { background-position: -340px -780px; } +.emoji-sweat_smile { background-position: -360px -780px; } +.emoji-sweet_potato { background-position: -380px -780px; } +.emoji-swimmer { background-position: -400px -780px; } +.emoji-swimmer_tone1 { background-position: -420px -780px; } +.emoji-swimmer_tone2 { background-position: -440px -780px; } +.emoji-swimmer_tone3 { background-position: -460px -780px; } +.emoji-swimmer_tone4 { background-position: -480px -780px; } +.emoji-swimmer_tone5 { background-position: -500px -780px; } +.emoji-symbols { background-position: -520px -780px; } +.emoji-synagogue { background-position: -540px -780px; } +.emoji-syringe { background-position: -560px -780px; } +.emoji-taco { background-position: -580px -780px; } +.emoji-tada { background-position: -600px -780px; } +.emoji-tanabata_tree { background-position: -620px -780px; } +.emoji-tangerine { background-position: -640px -780px; } +.emoji-taurus { background-position: -660px -780px; } +.emoji-taxi { background-position: -680px -780px; } +.emoji-tea { background-position: -700px -780px; } +.emoji-telephone { background-position: -720px -780px; } +.emoji-telephone_receiver { background-position: -740px -780px; } +.emoji-telescope { background-position: -760px -780px; } +.emoji-ten { background-position: -780px -780px; } +.emoji-tennis { background-position: -800px 0; } +.emoji-tent { background-position: -800px -20px; } +.emoji-thermometer { background-position: -800px -40px; } +.emoji-thermometer_face { background-position: -800px -60px; } +.emoji-thinking { background-position: -800px -80px; } +.emoji-third_place { background-position: -800px -100px; } +.emoji-thought_balloon { background-position: -800px -120px; } +.emoji-three { background-position: -800px -140px; } +.emoji-thumbsdown { background-position: -800px -160px; } +.emoji-thumbsdown_tone1 { background-position: -800px -180px; } +.emoji-thumbsdown_tone2 { background-position: -800px -200px; } +.emoji-thumbsdown_tone3 { background-position: -800px -220px; } +.emoji-thumbsdown_tone4 { background-position: -800px -240px; } +.emoji-thumbsdown_tone5 { background-position: -800px -260px; } +.emoji-thumbsup { background-position: -800px -280px; } +.emoji-thumbsup_tone1 { background-position: -800px -300px; } +.emoji-thumbsup_tone2 { background-position: -800px -320px; } +.emoji-thumbsup_tone3 { background-position: -800px -340px; } +.emoji-thumbsup_tone4 { background-position: -800px -360px; } +.emoji-thumbsup_tone5 { background-position: -800px -380px; } +.emoji-thunder_cloud_rain { background-position: -800px -400px; } +.emoji-ticket { background-position: -800px -420px; } +.emoji-tickets { background-position: -800px -440px; } +.emoji-tiger { background-position: -800px -460px; } +.emoji-tiger2 { background-position: -800px -480px; } +.emoji-timer { background-position: -800px -500px; } +.emoji-tired_face { background-position: -800px -520px; } +.emoji-tm { background-position: -800px -540px; } +.emoji-toilet { background-position: -800px -560px; } +.emoji-tokyo_tower { background-position: -800px -580px; } +.emoji-tomato { background-position: -800px -600px; } +.emoji-tone1 { background-position: -800px -620px; } +.emoji-tone2 { background-position: -800px -640px; } +.emoji-tone3 { background-position: -800px -660px; } +.emoji-tone4 { background-position: -800px -680px; } +.emoji-tone5 { background-position: -800px -700px; } +.emoji-tongue { background-position: -800px -720px; } +.emoji-tools { background-position: -800px -740px; } +.emoji-top { background-position: -800px -760px; } +.emoji-tophat { background-position: -800px -780px; } +.emoji-track_next { background-position: 0 -800px; } +.emoji-track_previous { background-position: -20px -800px; } +.emoji-trackball { background-position: -40px -800px; } +.emoji-tractor { background-position: -60px -800px; } +.emoji-traffic_light { background-position: -80px -800px; } +.emoji-train { background-position: -100px -800px; } +.emoji-train2 { background-position: -120px -800px; } +.emoji-tram { background-position: -140px -800px; } +.emoji-triangular_flag_on_post { background-position: -160px -800px; } +.emoji-triangular_ruler { background-position: -180px -800px; } +.emoji-trident { background-position: -200px -800px; } +.emoji-triumph { background-position: -220px -800px; } +.emoji-trolleybus { background-position: -240px -800px; } +.emoji-trophy { background-position: -260px -800px; } +.emoji-tropical_drink { background-position: -280px -800px; } +.emoji-tropical_fish { background-position: -300px -800px; } +.emoji-truck { background-position: -320px -800px; } +.emoji-trumpet { background-position: -340px -800px; } +.emoji-tulip { background-position: -360px -800px; } +.emoji-tumbler_glass { background-position: -380px -800px; } +.emoji-turkey { background-position: -400px -800px; } +.emoji-turtle { background-position: -420px -800px; } +.emoji-tv { background-position: -440px -800px; } +.emoji-twisted_rightwards_arrows { background-position: -460px -800px; } +.emoji-two { background-position: -480px -800px; } +.emoji-two_hearts { background-position: -500px -800px; } +.emoji-two_men_holding_hands { background-position: -520px -800px; } +.emoji-two_women_holding_hands { background-position: -540px -800px; } +.emoji-u5272 { background-position: -560px -800px; } +.emoji-u5408 { background-position: -580px -800px; } +.emoji-u55b6 { background-position: -600px -800px; } +.emoji-u6307 { background-position: -620px -800px; } +.emoji-u6708 { background-position: -640px -800px; } +.emoji-u6709 { background-position: -660px -800px; } +.emoji-u6e80 { background-position: -680px -800px; } +.emoji-u7121 { background-position: -700px -800px; } +.emoji-u7533 { background-position: -720px -800px; } +.emoji-u7981 { background-position: -740px -800px; } +.emoji-u7a7a { background-position: -760px -800px; } +.emoji-umbrella { background-position: -780px -800px; } +.emoji-umbrella2 { background-position: -800px -800px; } +.emoji-unamused { background-position: -820px 0; } +.emoji-underage { background-position: -820px -20px; } +.emoji-unicorn { background-position: -820px -40px; } +.emoji-unlock { background-position: -820px -60px; } +.emoji-up { background-position: -820px -80px; } +.emoji-upside_down { background-position: -820px -100px; } +.emoji-urn { background-position: -820px -120px; } +.emoji-v { background-position: -820px -140px; } +.emoji-v_tone1 { background-position: -820px -160px; } +.emoji-v_tone2 { background-position: -820px -180px; } +.emoji-v_tone3 { background-position: -820px -200px; } +.emoji-v_tone4 { background-position: -820px -220px; } +.emoji-v_tone5 { background-position: -820px -240px; } +.emoji-vertical_traffic_light { background-position: -820px -260px; } +.emoji-vhs { background-position: -820px -280px; } +.emoji-vibration_mode { background-position: -820px -300px; } +.emoji-video_camera { background-position: -820px -320px; } +.emoji-video_game { background-position: -820px -340px; } +.emoji-violin { background-position: -820px -360px; } +.emoji-virgo { background-position: -820px -380px; } +.emoji-volcano { background-position: -820px -400px; } +.emoji-volleyball { background-position: -820px -420px; } +.emoji-vs { background-position: -820px -440px; } +.emoji-vulcan { background-position: -820px -460px; } +.emoji-vulcan_tone1 { background-position: -820px -480px; } +.emoji-vulcan_tone2 { background-position: -820px -500px; } +.emoji-vulcan_tone3 { background-position: -820px -520px; } +.emoji-vulcan_tone4 { background-position: -820px -540px; } +.emoji-vulcan_tone5 { background-position: -820px -560px; } +.emoji-walking { background-position: -820px -580px; } +.emoji-walking_tone1 { background-position: -820px -600px; } +.emoji-walking_tone2 { background-position: -820px -620px; } +.emoji-walking_tone3 { background-position: -820px -640px; } +.emoji-walking_tone4 { background-position: -820px -660px; } +.emoji-walking_tone5 { background-position: -820px -680px; } +.emoji-waning_crescent_moon { background-position: -820px -700px; } +.emoji-waning_gibbous_moon { background-position: -820px -720px; } +.emoji-warning { background-position: -820px -740px; } +.emoji-wastebasket { background-position: -820px -760px; } +.emoji-watch { background-position: -820px -780px; } +.emoji-water_buffalo { background-position: -820px -800px; } +.emoji-water_polo { background-position: 0 -820px; } +.emoji-water_polo_tone1 { background-position: -20px -820px; } +.emoji-water_polo_tone2 { background-position: -40px -820px; } +.emoji-water_polo_tone3 { background-position: -60px -820px; } +.emoji-water_polo_tone4 { background-position: -80px -820px; } +.emoji-water_polo_tone5 { background-position: -100px -820px; } +.emoji-watermelon { background-position: -120px -820px; } +.emoji-wave { background-position: -140px -820px; } +.emoji-wave_tone1 { background-position: -160px -820px; } +.emoji-wave_tone2 { background-position: -180px -820px; } +.emoji-wave_tone3 { background-position: -200px -820px; } +.emoji-wave_tone4 { background-position: -220px -820px; } +.emoji-wave_tone5 { background-position: -240px -820px; } +.emoji-wavy_dash { background-position: -260px -820px; } +.emoji-waxing_crescent_moon { background-position: -280px -820px; } +.emoji-waxing_gibbous_moon { background-position: -300px -820px; } +.emoji-wc { background-position: -320px -820px; } +.emoji-weary { background-position: -340px -820px; } +.emoji-wedding { background-position: -360px -820px; } +.emoji-whale { background-position: -380px -820px; } +.emoji-whale2 { background-position: -400px -820px; } +.emoji-wheel_of_dharma { background-position: -420px -820px; } +.emoji-wheelchair { background-position: -440px -820px; } +.emoji-white_check_mark { background-position: -460px -820px; } +.emoji-white_circle { background-position: -480px -820px; } +.emoji-white_flower { background-position: -500px -820px; } +.emoji-white_large_square { background-position: -520px -820px; } +.emoji-white_medium_small_square { background-position: -540px -820px; } +.emoji-white_medium_square { background-position: -560px -820px; } +.emoji-white_small_square { background-position: -580px -820px; } +.emoji-white_square_button { background-position: -600px -820px; } +.emoji-white_sun_cloud { background-position: -620px -820px; } +.emoji-white_sun_rain_cloud { background-position: -640px -820px; } +.emoji-white_sun_small_cloud { background-position: -660px -820px; } +.emoji-wilted_rose { background-position: -680px -820px; } +.emoji-wind_blowing_face { background-position: -700px -820px; } +.emoji-wind_chime { background-position: -720px -820px; } +.emoji-wine_glass { background-position: -740px -820px; } +.emoji-wink { background-position: -760px -820px; } +.emoji-wolf { background-position: -780px -820px; } +.emoji-woman { background-position: -800px -820px; } +.emoji-woman_tone1 { background-position: -820px -820px; } +.emoji-woman_tone2 { background-position: -840px 0; } +.emoji-woman_tone3 { background-position: -840px -20px; } +.emoji-woman_tone4 { background-position: -840px -40px; } +.emoji-woman_tone5 { background-position: -840px -60px; } +.emoji-womans_clothes { background-position: -840px -80px; } +.emoji-womans_hat { background-position: -840px -100px; } +.emoji-womens { background-position: -840px -120px; } +.emoji-worried { background-position: -840px -140px; } +.emoji-wrench { background-position: -840px -160px; } +.emoji-wrestlers { background-position: -840px -180px; } +.emoji-wrestlers_tone1 { background-position: -840px -200px; } +.emoji-wrestlers_tone2 { background-position: -840px -220px; } +.emoji-wrestlers_tone3 { background-position: -840px -240px; } +.emoji-wrestlers_tone4 { background-position: -840px -260px; } +.emoji-wrestlers_tone5 { background-position: -840px -280px; } +.emoji-writing_hand { background-position: -840px -300px; } +.emoji-writing_hand_tone1 { background-position: -840px -320px; } +.emoji-writing_hand_tone2 { background-position: -840px -340px; } +.emoji-writing_hand_tone3 { background-position: -840px -360px; } +.emoji-writing_hand_tone4 { background-position: -840px -380px; } +.emoji-writing_hand_tone5 { background-position: -840px -400px; } +.emoji-x { background-position: -840px -420px; } +.emoji-yellow_heart { background-position: -840px -440px; } +.emoji-yen { background-position: -840px -460px; } +.emoji-yin_yang { background-position: -840px -480px; } +.emoji-yum { background-position: -840px -500px; } +.emoji-zap { background-position: -840px -520px; } +.emoji-zero { background-position: -840px -540px; } +.emoji-zipper_mouth { background-position: -840px -560px; } +.emoji-100 { background-position: -840px -580px; } .emoji-icon { background-image: image-url('emoji.png'); diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 50f0ef4414a..65b334662c2 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -125,7 +125,7 @@ color: $white-normal; } - &:hover { + &:hover:not(.tree-truncated-warning) { td { background-color: $row-hover; border-top: 1px solid $row-hover-border; @@ -198,6 +198,11 @@ } } + .tree-truncated-warning { + color: $orange-600; + background-color: $orange-100; + } + .tree-time-ago { min-width: 135px; color: $gl-text-color-secondary; diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index 3c64fd964ff..be2e1b47feb 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -4,7 +4,7 @@ module NotesActions included do before_action :set_polling_interval_header, only: [:index] - before_action :noteable, only: :index + before_action :require_noteable!, only: [:index, :create] before_action :authorize_admin_note!, only: [:update, :destroy] before_action :note_project, only: [:create] end @@ -90,7 +90,7 @@ module NotesActions if note.persisted? attrs[:valid] = true - if noteable.nil? || noteable.discussions_rendered_on_frontend? + if noteable.discussions_rendered_on_frontend? attrs.merge!(note_serializer.represent(note)) else attrs.merge!( @@ -191,7 +191,11 @@ module NotesActions end def noteable - @noteable ||= notes_finder.target || render_404 + @noteable ||= notes_finder.target || @note&.noteable + end + + def require_noteable! + render_404 unless noteable end def last_fetched_at diff --git a/app/controllers/snippets/notes_controller.rb b/app/controllers/snippets/notes_controller.rb index f9496787b15..c8b4682e6dc 100644 --- a/app/controllers/snippets/notes_controller.rb +++ b/app/controllers/snippets/notes_controller.rb @@ -20,6 +20,7 @@ class Snippets::NotesController < ApplicationController def snippet PersonalSnippet.find_by(id: params[:snippet_id]) end + alias_method :noteable, :snippet def note_params super.merge(noteable_id: params[:snippet_id]) diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index c4ea0f5ac53..0e106e2c85d 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -1,14 +1,23 @@ module TreeHelper + FILE_LIMIT = 1_000 + # Sorts a repository's tree so that folders are before files and renders # their corresponding partials # - # contents - A Grit::Tree object for the current tree + # tree - A `Tree` object for the current tree def render_tree(tree) # Sort submodules and folders together by name ahead of files folders, files, submodules = tree.trees, tree.blobs, tree.submodules - tree = "" + tree = '' items = (folders + submodules).sort_by(&:name) + files - tree << render(partial: "projects/tree/tree_row", collection: items) if items.present? + + if items.size > FILE_LIMIT + tree << render(partial: 'projects/tree/truncated_notice_tree_row', + locals: { limit: FILE_LIMIT, total: items.size }) + items = items.take(FILE_LIMIT) + end + + tree << render(partial: 'projects/tree/tree_row', collection: items) if items.present? tree.html_safe end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index c008fb91a16..35090181bd9 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -255,7 +255,7 @@ module Issuable participants(user).include?(user) end - def to_hook_data(user, old_labels: [], old_assignees: []) + def to_hook_data(user, old_labels: [], old_assignees: [], old_total_time_spent: nil) changes = previous_changes if old_labels != labels @@ -270,6 +270,10 @@ module Issuable end end + if old_total_time_spent != total_time_spent + changes[:total_time_spent] = [old_total_time_spent, total_time_spent] + end + Gitlab::HookData::IssuableBuilder.new(self).build(user: user, changes: changes) end diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb index 43de6809178..3eecbea8cbf 100644 --- a/app/models/project_wiki.rb +++ b/app/models/project_wiki.rb @@ -21,7 +21,7 @@ class ProjectWiki end delegate :empty?, to: :pages - delegate :repository_storage_path, to: :project + delegate :repository_storage_path, :hashed_storage?, to: :project def path @project.path + '.wiki' diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index 90865867ff0..39a7299ff60 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -172,6 +172,7 @@ class IssuableBaseService < BaseService old_labels = issuable.labels.to_a old_mentioned_users = issuable.mentioned_users.to_a old_assignees = issuable.assignees.to_a + old_total_time_spent = issuable.total_time_spent label_ids = process_label_ids(params, existing_label_ids: issuable.label_ids) params[:label_ids] = label_ids if labels_changing?(issuable.label_ids, label_ids) @@ -208,7 +209,12 @@ class IssuableBaseService < BaseService invalidate_cache_counts(issuable, users: affected_assignees.compact) after_update(issuable) issuable.create_new_cross_references!(current_user) - execute_hooks(issuable, 'update', old_labels: old_labels, old_assignees: old_assignees) + execute_hooks( + issuable, + 'update', + old_labels: old_labels, + old_assignees: old_assignees, + old_total_time_spent: old_total_time_spent) issuable.update_project_counter_caches if update_project_counters end diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index b680eaf5a49..0f711bcc3cf 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -1,7 +1,7 @@ module Issues class BaseService < ::IssuableBaseService - def hook_data(issue, action, old_labels: [], old_assignees: []) - hook_data = issue.to_hook_data(current_user, old_labels: old_labels, old_assignees: old_assignees) + def hook_data(issue, action, old_labels: [], old_assignees: [], old_total_time_spent: nil) + hook_data = issue.to_hook_data(current_user, old_labels: old_labels, old_assignees: old_assignees, old_total_time_spent: old_total_time_spent) hook_data[:object_attributes][:action] = action hook_data @@ -22,8 +22,8 @@ module Issues issue, issue.project, current_user, old_assignees) end - def execute_hooks(issue, action = 'open', old_labels: [], old_assignees: []) - issue_data = hook_data(issue, action, old_labels: old_labels, old_assignees: old_assignees) + def execute_hooks(issue, action = 'open', old_labels: [], old_assignees: [], old_total_time_spent: nil) + issue_data = hook_data(issue, action, old_labels: old_labels, old_assignees: old_assignees, old_total_time_spent: old_total_time_spent) hooks_scope = issue.confidential? ? :confidential_issue_hooks : :issue_hooks issue.project.execute_hooks(issue_data, hooks_scope) issue.project.execute_services(issue_data, hooks_scope) diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index 112606a82d7..d3938b065bc 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -18,8 +18,8 @@ module MergeRequests super if changed_title end - def hook_data(merge_request, action, old_rev: nil, old_labels: [], old_assignees: []) - hook_data = merge_request.to_hook_data(current_user, old_labels: old_labels, old_assignees: old_assignees) + def hook_data(merge_request, action, old_rev: nil, old_labels: [], old_assignees: [], old_total_time_spent: nil) + hook_data = merge_request.to_hook_data(current_user, old_labels: old_labels, old_assignees: old_assignees, old_total_time_spent: old_total_time_spent) hook_data[:object_attributes][:action] = action if old_rev && !Gitlab::Git.blank_ref?(old_rev) hook_data[:object_attributes][:oldrev] = old_rev @@ -28,9 +28,9 @@ module MergeRequests hook_data end - def execute_hooks(merge_request, action = 'open', old_rev: nil, old_labels: [], old_assignees: []) + def execute_hooks(merge_request, action = 'open', old_rev: nil, old_labels: [], old_assignees: [], old_total_time_spent: nil) if merge_request.project - merge_data = hook_data(merge_request, action, old_rev: old_rev, old_labels: old_labels, old_assignees: old_assignees) + merge_data = hook_data(merge_request, action, old_rev: old_rev, old_labels: old_labels, old_assignees: old_assignees, old_total_time_spent: old_total_time_spent) merge_request.project.execute_hooks(merge_data, :merge_request_hooks) merge_request.project.execute_services(merge_data, :merge_request_hooks) end diff --git a/app/views/projects/commit/_ajax_signature.html.haml b/app/views/projects/commit/_ajax_signature.html.haml index 1d6a0fa38ca..36b28c731a1 100644 --- a/app/views/projects/commit/_ajax_signature.html.haml +++ b/app/views/projects/commit/_ajax_signature.html.haml @@ -1,2 +1,2 @@ - if commit.has_signature? - %a{ href: '#', tabindex: 0, class: commit_signature_badge_classes('js-loading-gpg-badge'), data: { toggle: 'tooltip', placement: 'auto top', title: 'GPG signature (loading...)', 'commit-sha' => commit.sha } } + %a{ href: 'javascript:void(0)', tabindex: 0, class: commit_signature_badge_classes('js-loading-gpg-badge'), data: { toggle: 'tooltip', placement: 'auto top', title: 'GPG signature (loading...)', 'commit-sha' => commit.sha } } diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml index b6b7aae6f9a..44aa8002f12 100644 --- a/app/views/projects/commit/_signature_badge.html.haml +++ b/app/views/projects/commit/_signature_badge.html.haml @@ -24,5 +24,5 @@ = link_to('Learn more about signing commits', help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link') -%a{ href: '#', tabindex: 0, class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } } +%a{ href: 'javascript:void(0)', tabindex: 0, class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } } = label diff --git a/app/views/projects/tree/_truncated_notice_tree_row.html.haml b/app/views/projects/tree/_truncated_notice_tree_row.html.haml new file mode 100644 index 00000000000..693b641888b --- /dev/null +++ b/app/views/projects/tree/_truncated_notice_tree_row.html.haml @@ -0,0 +1,7 @@ +%tr.tree-truncated-warning + %td{ colspan: '3' } + = icon('exclamation-triangle fw') + %span + Too many items to show. To preserve performance only + %strong #{number_with_delimiter(limit)} of #{number_with_delimiter(total)} + items are displayed. diff --git a/changelogs/unreleased/39573-hashed-storage-backup.yml b/changelogs/unreleased/39573-hashed-storage-backup.yml new file mode 100644 index 00000000000..40ee589c8cc --- /dev/null +++ b/changelogs/unreleased/39573-hashed-storage-backup.yml @@ -0,0 +1,5 @@ +--- +title: Fix gitlab:backup rake for hashed storage based repositories +merge_request: 15400 +author: +type: fixed diff --git a/changelogs/unreleased/40122-only-one-note-webhook-is-triggered-when-a-comment-with-time-spent-is-added.yml b/changelogs/unreleased/40122-only-one-note-webhook-is-triggered-when-a-comment-with-time-spent-is-added.yml new file mode 100644 index 00000000000..a2ae2059c47 --- /dev/null +++ b/changelogs/unreleased/40122-only-one-note-webhook-is-triggered-when-a-comment-with-time-spent-is-added.yml @@ -0,0 +1,5 @@ +--- +title: Add total_time_spent to the `changes` hash in issuable Webhook payloads +merge_request: 15381 +author: +type: changed diff --git a/changelogs/unreleased/40198-fix-gpg-badge-links.yml b/changelogs/unreleased/40198-fix-gpg-badge-links.yml new file mode 100644 index 00000000000..62b962acefa --- /dev/null +++ b/changelogs/unreleased/40198-fix-gpg-badge-links.yml @@ -0,0 +1,6 @@ +--- +title: Fix issue where clicking a GPG verification badge would scroll to the top of + the page +merge_request: 15407 +author: +type: fixed diff --git a/changelogs/unreleased/dm-notes-actions-noteable-for-update.yml b/changelogs/unreleased/dm-notes-actions-noteable-for-update.yml new file mode 100644 index 00000000000..1d2f58bc765 --- /dev/null +++ b/changelogs/unreleased/dm-notes-actions-noteable-for-update.yml @@ -0,0 +1,5 @@ +--- +title: Make sure NotesActions#noteable returns a Noteable in the update action +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/fix-gb-update-registry-path-reference-regexp.yml b/changelogs/unreleased/fix-gb-update-registry-path-reference-regexp.yml new file mode 100644 index 00000000000..55c1089ade5 --- /dev/null +++ b/changelogs/unreleased/fix-gb-update-registry-path-reference-regexp.yml @@ -0,0 +1,5 @@ +--- +title: Update container repository path reference and allow using double underscore +merge_request: 15417 +author: +type: fixed diff --git a/changelogs/unreleased/tree_item_limit.yml b/changelogs/unreleased/tree_item_limit.yml new file mode 100644 index 00000000000..d95c5776075 --- /dev/null +++ b/changelogs/unreleased/tree_item_limit.yml @@ -0,0 +1,5 @@ +--- +title: Truncate tree to max 1,000 items and display notice to users +merge_request: +author: +type: performance diff --git a/changelogs/unreleased/update-emoji-digests-with-latest-from-gemojione.yml b/changelogs/unreleased/update-emoji-digests-with-latest-from-gemojione.yml new file mode 100644 index 00000000000..e509a8df6bc --- /dev/null +++ b/changelogs/unreleased/update-emoji-digests-with-latest-from-gemojione.yml @@ -0,0 +1,6 @@ +--- +title: 'Update emojis. Add :gay_pride_flag: and :speech_left:. Remove extraneous comma + in :cartwheel_tone4:' +merge_request: +author: +type: changed diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml index 3af7f7bd5c0..60df92a44fc 100644 --- a/config/dependency_decisions.yml +++ b/config/dependency_decisions.yml @@ -459,9 +459,9 @@ :versions: [] :when: 2017-09-13 17:31:16.425819400 Z - - :approve - - gitlab-svgs + - "@gitlab-org/gitlab-svgs" - :who: Tim Zallmann - :why: Our own library - https://gitlab.com/gitlab-org/gitlab-svgs + :why: Our own library - GitLab License https://gitlab.com/gitlab-org/gitlab-svgs :versions: [] :when: 2017-09-19 14:36:32.795496000 Z - - :license @@ -471,3 +471,35 @@ :why: :versions: [] :when: 2017-10-17 17:46:12.367554000 Z +- - :license + - component-emitter + - MIT + - :who: Winnie Hellmann + :why: package.json does not specify the license (README.md does) + :versions: + - 1.1.2 + :when: 2017-11-13 12:23:10.502463000 Z +- - :license + - json-schema + - BSD + - :who: Winnie Hellmann + :why: https://github.com/kriszyp/json-schema/blob/v0.2.3/package.json#L18-L19 + :versions: + - 0.2.3 + :when: 2017-11-16 12:52:18.286091000 Z +- - :license + - node-forge + - New BSD + - :who: Winnie Hellmann + :why: https://github.com/digitalbazaar/forge/blob/0.6.33/LICENSE + :versions: + - 0.6.33 + :when: 2017-11-16 12:56:17.974767000 Z +- - :license + - sntp + - BSD + - :who: Winnie Hellmann + :why: https://github.com/hueniverse/sntp/blob/v1.0.9/package.json#L28-L29 + :versions: + - 1.0.9 + :when: 2017-11-16 13:02:06.765282000 Z diff --git a/doc/api/environments.md b/doc/api/environments.md index e8deb3e07e9..6e20781f51a 100644 --- a/doc/api/environments.md +++ b/doc/api/environments.md @@ -36,7 +36,7 @@ Creates a new environment with the given name and external_url. It returns `201` if the environment was successfully created, `400` for wrong parameters. ``` -POST /projects/:id/environment +POST /projects/:id/environments ``` | Attribute | Type | Required | Description | diff --git a/doc/development/README.md b/doc/development/README.md index 5690ae68e00..6892838be7f 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -22,6 +22,7 @@ comments: false - [UX guide](ux_guide/index.md) for building GitLab with existing CSS styles and elements - [Frontend guidelines](fe_guide/index.md) +- [Emoji guide](fe_guide/emojis.md) ## Backend guides @@ -70,6 +71,7 @@ comments: false - [Iterating tables in batches](iterating_tables_in_batches.md) - [Ordering table columns](ordering_table_columns.md) - [Verifying database capabilities](verifying_database_capabilities.md) +- [Database Debugging and Troubleshooting](database_debugging.md) ## Testing guides diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md new file mode 100644 index 00000000000..4acfbef3020 --- /dev/null +++ b/doc/development/database_debugging.md @@ -0,0 +1,49 @@ +# Database Debugging and Troubleshooting + +This section is to help give some copy-pasta you can use as a reference when you +run into some head-banging database problems. + +An easy first step is to search for your error in Slack or google "GitLab <my error>". + +--- + +Available `RAILS_ENV` + + - `production` (not sure if in GDK) + - `development` (this is your main GDK db) + - `test` (used for tests like rspec and spinach) + + +## Nuke everything and start over + +If you just want to delete everything and start over, + + - `bundle exec rake db:drop RAILS_ENV=development` + - `bundle exec rake db:setup RAILS_ENV=development` + + +## Migration wrangling + + - `bundle exec rake db:migrate RAILS_ENV=development`: Execute any pending migrations that you may have picked up from a MR + - `bundle exec rake db:migrate:status RAILS_ENV=development`: Check if all migrations are `up` or `down` + - `bundle exec rake db:migrate:down VERSION=20170926203418 RAILS_ENV=development`: Tear down a migration + - `bundle exec rake db:migrate:up VERSION=20170926203418 RAILS_ENV=development`: Setup a migration + - `bundle exec rake db:migrate:redo VERSION=20170926203418 RAILS_ENV=development`: Re-run a specific migration + + +## Manually access the database + +Access the database via one of these commands (they all get you to the same place) + +``` +gdk psql -d gitlabhq_development +bundle exec rails dbconsole RAILS_ENV=development +bundle exec rails db RAILS_ENV=development +``` + + - `\q`: Quit/exit + - `\dt`: List all tables + - `\d+ issues`: List columns for `issues` table + - `CREATE TABLE board_labels();`: Create a table called `board_labels` + - `SELECT * FROM schema_migrations WHERE version = '20170926203418';`: Check if a migration was run + - `DELETE FROM schema_migrations WHERE version = '20170926203418';`: Manually remove a migration diff --git a/doc/development/fe_guide/emojis.md b/doc/development/fe_guide/emojis.md new file mode 100644 index 00000000000..38794c47965 --- /dev/null +++ b/doc/development/fe_guide/emojis.md @@ -0,0 +1,27 @@ +# Emojis + +GitLab supports native unicode emojis and fallsback to image-based emojis selectively +when your platform does not support it. + +# How to update Emojis + + 1. Update the `gemojione` gem + 1. Update `fixtures/emojis/index.json` from [Gemojione](https://github.com/jonathanwiesel/gemojione/blob/master/config/index.json). + In the future, we could grab the file directly from the gem. + We should probably make a PR on the Gemojione project to get access to + all emojis after being parsed or just a raw path to the `json` file itself. + 1. Ensure [`emoji-unicode-version`](https://www.npmjs.com/package/emoji-unicode-version) + is up to date with the latest version. + 1. Run `bundle exec rake gemojione:aliases` + 1. Run `bundle exec rake gemojione:digests` + 1. Run `bundle exec rake gemojione:sprite` + 1. Ensure new sprite sheets generated for 1x and 2x + - `app/assets/images/emoji.png` + - `app/assets/images/emoji@2x.png` + 1. Ensure you see new individual images copied into `app/assets/images/emoji/` + 1. Ensure you can see the new emojis and their aliases in the GFM Autocomplete + 1. Ensure you can see the new emojis and their aliases in the award emoji menu + 1. You might need to add new emoji unicode support checks and rules for platforms + that do not support a certain emoji and we need to fallback to an image. + See `app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js` + and `app/assets/javascripts/emoji/support/unicode_support_map.js` diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md index a76e978bd26..cef62618a3c 100644 --- a/doc/development/fe_guide/icons.md +++ b/doc/development/fe_guide/icons.md @@ -29,7 +29,7 @@ Please use the following function inside JS to render an icon : All Icons and Illustrations are managed in the [gitlab-svgs](https://gitlab.com/gitlab-org/gitlab-svgs) repository which is added as a dev-dependency. -To upgrade to a new SVG Sprite version run `yarn upgrade https://gitlab.com/gitlab-org/gitlab-svgs` and then run `yarn run svg`. This task will copy the svg sprite and all illustrations in the correct folders. +To upgrade to a new SVG Sprite version run `yarn upgrade @gitlab-org/gitlab-svgs` and then run `yarn run svg`. This task will copy the svg sprite and all illustrations in the correct folders. # SVG Illustrations diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md index bfd80aab6a4..4773b6773e8 100644 --- a/doc/development/rake_tasks.md +++ b/doc/development/rake_tasks.md @@ -122,6 +122,15 @@ they can be easily inspected. bundle exec rake services:doc ``` +## Updating Emoji Aliases + +To update the Emoji aliases file (used for Emoji autocomplete) you must run the +following: + +``` +bundle exec rake gemojione:aliases +``` + ## Updating Emoji Digests To update the Emoji digests file (used for Emoji autocomplete) you must run the @@ -131,6 +140,7 @@ following: bundle exec rake gemojione:digests ``` + This will update the file `fixtures/emojis/digests.json` based on the currently available Emoji. diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md index f2ad42f21fd..022d6317555 100644 --- a/doc/user/profile/preferences.md +++ b/doc/user/profile/preferences.md @@ -55,9 +55,10 @@ You have 6 options here that you can use for your default dashboard view: The project home page content setting allows you to choose what content you want to see on a project’s home page. -You can choose between 2 options: +You can choose between 3 options: - Show the files and the readme (default) +- Show the readme - Show the project’s activity [rouge]: http://rouge.jneen.net/ "Rouge website" diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md index 453e10184f0..1e19f422d94 100644 --- a/doc/user/project/pages/getting_started_part_one.md +++ b/doc/user/project/pages/getting_started_part_one.md @@ -62,7 +62,7 @@ which is highly recommendable and much faster than hardcoding. If you set up a GitLab Pages project on GitLab.com, it will automatically be accessible under a -[subdomain of `namespace.pages.io`](introduction.md#gitlab-pages-on-gitlab-com). +[subdomain of `namespace.gitlab.io`](introduction.md#gitlab-pages-on-gitlab-com). The `namespace` is defined by your username on GitLab.com, or the group name you created this project under. diff --git a/fixtures/emojis/aliases.json b/fixtures/emojis/aliases.json index e2f47db0de2..415dd5a54e0 100644 --- a/fixtures/emojis/aliases.json +++ b/fixtures/emojis/aliases.json @@ -339,6 +339,7 @@ "baguette_bread":"french_bread", "anguished":"frowning", "white_frowning_face":"frowning2", + "rainbow_flag":"gay_pride_flag", "goal_net":"goal", "hammer_and_pick":"hammer_pick", "raised_hand_with_fingers_splayed":"hand_splayed", @@ -488,6 +489,7 @@ "slightly_smiling_face":"slight_smile", "sneeze":"sneezing_face", "speaking_head_in_silhouette":"speaking_head", + "left_speech_bubble":"speech_left", "sleuth_or_spy":"spy", "sleuth_or_spy_tone1":"spy_tone1", "sleuth_or_spy_tone2":"spy_tone2", @@ -537,4 +539,4 @@ "wrestling_tone4":"wrestlers_tone4", "wrestling_tone5":"wrestlers_tone5", "zipper_mouth_face":"zipper_mouth" -} +}
\ No newline at end of file diff --git a/fixtures/emojis/digests.json b/fixtures/emojis/digests.json index 589cff165f3..3c8f6426f93 100644 --- a/fixtures/emojis/digests.json +++ b/fixtures/emojis/digests.json @@ -1478,7 +1478,7 @@ }, "cartwheel_tone4": { "category": "activity", - "moji": "🤸🏾,", + "moji": "🤸🏾", "description": "person doing cartwheel tone 4", "unicodeVersion": "9.0", "digest": "8253afb672431c84e498014c30babb00b9284bec773009e79f7f06aa7108643e" @@ -5375,6 +5375,13 @@ "unicodeVersion": "6.0", "digest": "180e66f19d9285e02d0a5e859722c608206826e80323942b9938fc49d44973b1" }, + "gay_pride_flag": { + "category": "flags", + "moji": "🏳🌈", + "description": "gay_pride_flag", + "unicodeVersion": "6.0", + "digest": "924e668c559db61b7f4724a661223081c2fc60d55169f3fe1ad6156934d1d37f" + }, "gemini": { "category": "symbols", "moji": "♊", @@ -7578,7 +7585,7 @@ "moji": "🤶", "description": "mother christmas", "unicodeVersion": "9.0", - "digest": "1f72f586ca75bd7ebb4150cdcc8199a930c32fa4b81510cb8d200f1b3ddd4076" + "digest": "357d769371305a8584f46d6087a962d647b6af22fab363a44702f38ab7814091" }, "mrs_claus_tone1": { "category": "people", @@ -10709,6 +10716,13 @@ "unicodeVersion": "6.0", "digest": "817100d9979456e7d2f253ac22e13b7a2302dc1590566214915b003e403c53ca" }, + "speech_left": { + "category": "symbols", + "moji": "🗨", + "description": "left speech bubble", + "unicodeVersion": "7.0", + "digest": "912797107d574f5665411498b6e349dbdec69846f085b6dc356548c4155e90b0" + }, "speedboat": { "category": "travel", "moji": "🚤", diff --git a/fixtures/emojis/generate_aliases.rb b/fixtures/emojis/generate_aliases.rb deleted file mode 100755 index 8838fb9a3af..00000000000 --- a/fixtures/emojis/generate_aliases.rb +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env ruby - -require 'json' - -aliases = {} - -index_file = File.expand_path("./index.json") -index = JSON.parse(File.read(index_file)) - -index.each_pair do |key, data| - data['aliases'].each do |a| - a.tr!(':', '') - - aliases[a] = key - end -end - -puts JSON.pretty_generate(aliases, indent: ' ', space: '', space_before: '') diff --git a/fixtures/emojis/index.json b/fixtures/emojis/index.json index 2a990913b9c..f55571d31fa 100644 --- a/fixtures/emojis/index.json +++ b/fixtures/emojis/index.json @@ -4023,7 +4023,7 @@ ], "aliases_ascii": [], "keywords": [], - "moji": "🤸🏾," + "moji": "🤸🏾" }, "cartwheel_tone5": { "unicode": "1F938-1F3FF", @@ -14475,6 +14475,19 @@ ], "moji": "💎" }, + "gay_pride_flag": { + "unicode": "1F3F3-1F308", + "unicode_alternates": [], + "name": "gay_pride_flag", + "shortname": ":gay_pride_flag:", + "category": "extras", + "aliases": [ + ":rainbow_flag:" + ], + "aliases_ascii": [], + "keywords": [], + "moji": "🏳🌈" + }, "gemini": { "unicode": "264A", "unicode_alternates": [ @@ -16830,7 +16843,6 @@ "0:-)", "0:)", "0;^)", - "O:-)", "O:)", "O;-)", "O=)", @@ -28506,6 +28518,21 @@ ], "moji": "💬" }, + "speech_left": { + "unicode": "1F5E8", + "unicode_alternates": [ + "1F5E8-FE0F" + ], + "name": "left speech bubble", + "shortname": ":speech_left:", + "category": "symbols", + "aliases": [ + ":left_speech_bubble:" + ], + "aliases_ascii": [], + "keywords": [], + "moji": "🗨" + }, "speedboat": { "unicode": "1F6A4", "unicode_alternates": [], @@ -33477,4 +33504,4 @@ ], "moji": "💤" } -} +}
\ No newline at end of file diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb index 4c0db4d42b1..4b3c473b0bb 100644 --- a/lib/api/helpers/internal_helpers.rb +++ b/lib/api/helpers/internal_helpers.rb @@ -36,6 +36,18 @@ module API {} end + def fix_git_env_repository_paths(env, repository_path) + if obj_dir_relative = env['GIT_OBJECT_DIRECTORY_RELATIVE'].presence + env['GIT_OBJECT_DIRECTORY'] = File.join(repository_path, obj_dir_relative) + end + + if alt_obj_dirs_relative = env['GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE'].presence + env['GIT_ALTERNATE_OBJECT_DIRECTORIES'] = alt_obj_dirs_relative.map { |dir| File.join(repository_path, dir) } + end + + env + end + def log_user_activity(actor) commands = Gitlab::GitAccess::DOWNLOAD_COMMANDS diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 6e78ac2c903..451121a4cea 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -19,7 +19,9 @@ module API status 200 # Stores some Git-specific env thread-safely - Gitlab::Git::Env.set(parse_env) + env = parse_env + env = fix_git_env_repository_paths(env, repository_path) if project + Gitlab::Git::Env.set(env) actor = if params[:key_id] diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index 3ad09a1b421..b6d273b98c2 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -7,12 +7,16 @@ module Backup prepare Project.find_each(batch_size: 1000) do |project| - progress.print " * #{project.full_path} ... " + progress.print " * #{display_repo_path(project)} ... " path_to_project_repo = path_to_repo(project) path_to_project_bundle = path_to_bundle(project) - # Create namespace dir if missing - FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace + # Create namespace dir or hashed path if missing + if project.hashed_storage?(:repository) + FileUtils.mkdir_p(File.dirname(File.join(backup_repos_path, project.disk_path))) + else + FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace + end if empty_repo?(project) progress.puts "[SKIPPED]".color(:cyan) @@ -42,7 +46,7 @@ module Backup path_to_wiki_bundle = path_to_bundle(wiki) if File.exist?(path_to_wiki_repo) - progress.print " * #{wiki.full_path} ... " + progress.print " * #{display_repo_path(wiki)} ... " if empty_repo?(wiki) progress.puts " [SKIPPED]".color(:cyan) else @@ -71,7 +75,7 @@ module Backup end Project.find_each(batch_size: 1000) do |project| - progress.print " * #{project.full_path} ... " + progress.print " * #{display_repo_path(project)} ... " path_to_project_repo = path_to_repo(project) path_to_project_bundle = path_to_bundle(project) @@ -104,7 +108,7 @@ module Backup path_to_wiki_bundle = path_to_bundle(wiki) if File.exist?(path_to_wiki_bundle) - progress.print " * #{wiki.full_path} ... " + progress.print " * #{display_repo_path(wiki)} ... " # If a wiki bundle exists, first remove the empty repo # that was initialized with ProjectWiki.new() and then @@ -185,14 +189,14 @@ module Backup def progress_warn(project, cmd, output) progress.puts "[WARNING] Executing #{cmd}".color(:orange) - progress.puts "Ignoring error on #{project.full_path} - #{output}".color(:orange) + progress.puts "Ignoring error on #{display_repo_path(project)} - #{output}".color(:orange) end def empty_repo?(project_or_wiki) project_or_wiki.repository.expire_exists_cache # protect backups from stale cache project_or_wiki.repository.empty_repo? rescue => e - progress.puts "Ignoring repository error and continuing backing up project: #{project_or_wiki.full_path} - #{e.message}".color(:orange) + progress.puts "Ignoring repository error and continuing backing up project: #{display_repo_path(project_or_wiki)} - #{e.message}".color(:orange) false end @@ -204,5 +208,9 @@ module Backup def progress $progress end + + def display_repo_path(project) + project.hashed_storage?(:repository) ? "#{project.full_path} (#{project.disk_path})" : project.full_path + end end end diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index 0ea534a5fd0..efc2e46d289 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -193,7 +193,7 @@ module Gitlab # Repository is initially cloned with a depth of 20 so we need to fetch # deeper in the case the branch has more than 20 commits on top of master fetch(branch: branch, depth: depth) - fetch(branch: 'master', depth: depth) + fetch(branch: 'master', depth: depth, remote: DEFAULT_CE_PROJECT_URL) merge_base_found? end @@ -201,10 +201,10 @@ module Gitlab raise "\n#{branch} is too far behind master, please rebase it!\n" unless success end - def fetch(branch:, depth:) + def fetch(branch:, depth:, remote: 'origin') step( "Fetching deeper...", - %W[git fetch --depth=#{depth} --prune origin +refs/heads/#{branch}:refs/remotes/origin/#{branch}] + %W[git fetch --depth=#{depth} --prune #{remote} +refs/heads/#{branch}:refs/remotes/origin/#{branch}] ) do |output, status| raise "Fetch failed: #{output}" unless status.zero? end diff --git a/lib/gitlab/gitaly_client/attributes_bag.rb b/lib/gitlab/gitaly_client/attributes_bag.rb new file mode 100644 index 00000000000..198a1de91c7 --- /dev/null +++ b/lib/gitlab/gitaly_client/attributes_bag.rb @@ -0,0 +1,31 @@ +module Gitlab + module GitalyClient + # This module expects an `ATTRS` const to be defined on the subclass + # See GitalyClient::WikiFile for an example + module AttributesBag + extend ActiveSupport::Concern + + included do + attr_accessor(*const_get(:ATTRS)) + end + + def initialize(params) + params = params.with_indifferent_access + + attributes.each do |attr| + instance_variable_set("@#{attr}", params[attr]) + end + end + + def ==(other) + attributes.all? do |field| + instance_variable_get("@#{field}") == other.instance_variable_get("@#{field}") + end + end + + def attributes + self.class.const_get(:ATTRS) + end + end + end +end diff --git a/lib/gitlab/gitaly_client/diff.rb b/lib/gitlab/gitaly_client/diff.rb index 54df6304865..d98a0ce988f 100644 --- a/lib/gitlab/gitaly_client/diff.rb +++ b/lib/gitlab/gitaly_client/diff.rb @@ -1,21 +1,9 @@ module Gitlab module GitalyClient class Diff - FIELDS = %i(from_path to_path old_mode new_mode from_id to_id patch overflow_marker collapsed).freeze + ATTRS = %i(from_path to_path old_mode new_mode from_id to_id patch overflow_marker collapsed).freeze - attr_accessor(*FIELDS) - - def initialize(params) - params.each do |key, val| - public_send(:"#{key}=", val) # rubocop:disable GitlabSecurity/PublicSend - end - end - - def ==(other) - FIELDS.all? do |field| - public_send(field) == other.public_send(field) # rubocop:disable GitlabSecurity/PublicSend - end - end + include AttributesBag end end end diff --git a/lib/gitlab/gitaly_client/diff_stitcher.rb b/lib/gitlab/gitaly_client/diff_stitcher.rb index 65d81dc5d46..da243ee2d1a 100644 --- a/lib/gitlab/gitaly_client/diff_stitcher.rb +++ b/lib/gitlab/gitaly_client/diff_stitcher.rb @@ -12,7 +12,7 @@ module Gitlab @rpc_response.each do |diff_msg| if current_diff.nil? - diff_params = diff_msg.to_h.slice(*GitalyClient::Diff::FIELDS) + diff_params = diff_msg.to_h.slice(*GitalyClient::Diff::ATTRS) # gRPC uses frozen strings by default, and we need to have an unfrozen string as it # gets processed further down the line. So we unfreeze the first chunk of the patch # in case it's the only chunk we receive for this diff. diff --git a/lib/gitlab/gitaly_client/wiki_file.rb b/lib/gitlab/gitaly_client/wiki_file.rb index a2e415864e6..47c60c92484 100644 --- a/lib/gitlab/gitaly_client/wiki_file.rb +++ b/lib/gitlab/gitaly_client/wiki_file.rb @@ -1,17 +1,9 @@ module Gitlab module GitalyClient class WikiFile - FIELDS = %i(name mime_type path raw_data).freeze + ATTRS = %i(name mime_type path raw_data).freeze - attr_accessor(*FIELDS) - - def initialize(params) - params = params.with_indifferent_access - - FIELDS.each do |field| - instance_variable_set("@#{field}", params[field]) - end - end + include AttributesBag end end end diff --git a/lib/gitlab/gitaly_client/wiki_page.rb b/lib/gitlab/gitaly_client/wiki_page.rb index 98d96fe6211..7339468e911 100644 --- a/lib/gitlab/gitaly_client/wiki_page.rb +++ b/lib/gitlab/gitaly_client/wiki_page.rb @@ -1,16 +1,12 @@ module Gitlab module GitalyClient class WikiPage - FIELDS = %i(title format url_path path name historical raw_data).freeze + ATTRS = %i(title format url_path path name historical raw_data).freeze - attr_accessor(*FIELDS) + include AttributesBag def initialize(params) - params = params.with_indifferent_access - - FIELDS.each do |field| - instance_variable_set("@#{field}", params[field]) - end + super # All gRPC strings in a response are frozen, so we get an unfrozen # version here so appending to `raw_data` doesn't blow up. diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb index 196f2b6b34c..e29dd0d5b0e 100644 --- a/lib/gitlab/hook_data/issue_builder.rb +++ b/lib/gitlab/hook_data/issue_builder.rb @@ -28,6 +28,7 @@ module Gitlab SAFE_HOOK_RELATIONS = %i[ assignees labels + total_time_spent ].freeze attr_accessor :issue diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb index 503452c8ff3..ae9b68eb648 100644 --- a/lib/gitlab/hook_data/merge_request_builder.rb +++ b/lib/gitlab/hook_data/merge_request_builder.rb @@ -33,6 +33,7 @@ module Gitlab SAFE_HOOK_RELATIONS = %i[ assignee labels + total_time_spent ].freeze attr_accessor :merge_request diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index bd677ec4bf3..2c7b8af83f2 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -25,7 +25,7 @@ module Gitlab # See https://github.com/docker/distribution/blob/master/reference/regexp.go. # def container_repository_name_regex - @container_repository_regex ||= %r{\A[a-z0-9]+(?:[-._/][a-z0-9]+)*\Z} + @container_repository_regex ||= %r{\A[a-z0-9]+((?:[._/]|__|[-])[a-z0-9]+)*\Z} end ## diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake index 87ca39b079b..c2d3a6b6950 100644 --- a/lib/tasks/gemojione.rake +++ b/lib/tasks/gemojione.rake @@ -1,5 +1,28 @@ namespace :gemojione do desc 'Generates Emoji SHA256 digests' + + task aliases: ['yarn:check', 'environment'] do + require 'json' + + aliases = {} + + index_file = File.join(Rails.root, 'fixtures', 'emojis', 'index.json') + index = JSON.parse(File.read(index_file)) + + index.each_pair do |key, data| + data['aliases'].each do |a| + a.tr!(':', '') + + aliases[a] = key + end + end + + out = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json') + File.open(out, 'w') do |handle| + handle.write(JSON.pretty_generate(aliases, indent: ' ', space: '', space_before: '')) + end + end + task digests: ['yarn:check', 'environment'] do require 'digest/sha2' require 'json' @@ -16,8 +39,13 @@ namespace :gemojione do fpath = File.join(dir, "#{emoji_hash['unicode']}.png") hash_digest = Digest::SHA256.file(fpath).hexdigest + category = emoji_hash['category'] + if name == 'gay_pride_flag' + category = 'flags' + end + entry = { - category: emoji_hash['category'], + category: category, moji: emoji_hash['moji'], description: emoji_hash['description'], unicodeVersion: Gitlab::Emoji.emoji_unicode_version(name), @@ -29,7 +57,6 @@ namespace :gemojione do end out = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json') - File.open(out, 'w') do |handle| handle.write(JSON.pretty_generate(resultant_emoji_map)) end diff --git a/package.json b/package.json index e607981143d..cbcce40ffb9 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "webpack-stats-plugin": "^0.1.5" }, "devDependencies": { + "@gitlab-org/gitlab-svgs": "^1.0.2", "babel-plugin-istanbul": "^4.0.0", "eslint": "^3.10.1", "eslint-config-airbnb-base": "^10.0.1", @@ -82,7 +83,6 @@ "eslint-plugin-import": "^2.2.0", "eslint-plugin-jasmine": "^2.1.0", "eslint-plugin-promise": "^3.5.0", - "gitlab-svgs": "https://gitlab.com/gitlab-org/gitlab-svgs.git", "istanbul": "^0.4.5", "jasmine-core": "^2.6.3", "jasmine-jquery": "^2.1.1", diff --git a/scripts/trigger-build-docs b/scripts/trigger-build-docs index d3a9f5ff4ea..89ad6a99467 100755 --- a/scripts/trigger-build-docs +++ b/scripts/trigger-build-docs @@ -31,13 +31,6 @@ def docs_branch end # -# Dummy way to find out in which repo we are, CE or EE -# -def ee? - File.exist?('CHANGELOG-EE.md') -end - -# # Create a remote branch in gitlab-docs # def create_remote_branch @@ -56,14 +49,34 @@ def remove_remote_branch end # +# Define suffix in review app URL based on project +# +def slug + case ENV["CI_PROJECT_NAME"] + when 'gitlab-ce' + 'ce' + when 'gitlab-ee' + 'ee' + when 'gitlab-runner' + 'runner' + when 'omnibus-gitlab' + 'omnibus' + end +end + +# +# Overriding vars in https://gitlab.com/gitlab-com/gitlab-docs/blob/master/.gitlab-ci.yml +# +def param_name + "BRANCH_#{slug.upcase}" +end + +# # Trigger a pipeline in gitlab-docs # def trigger_pipeline - # Overriding vars in https://gitlab.com/gitlab-com/gitlab-docs/blob/master/.gitlab-ci.yml - param_name = ee? ? 'BRANCH_EE' : 'BRANCH_CE' - # The review app URL - app_url = "http://#{docs_branch}.#{ENV["DOCS_REVIEW_APPS_DOMAIN"]}/#{ee? ? 'ee' : 'ce'}" + app_url = "http://#{docs_branch}.#{ENV["DOCS_REVIEW_APPS_DOMAIN"]}/#{slug}" # Create the pipeline puts "=> Triggering a pipeline..." diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index 5f5a789d5cc..37e9f863fc4 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -336,6 +336,29 @@ describe Projects::NotesController do end end + describe 'PUT update' do + let(:request_params) do + { + namespace_id: project.namespace, + project_id: project, + id: note, + format: :json, + note: { + note: "New comment" + } + } + end + + before do + sign_in(note.author) + project.team << [note.author, :developer] + end + + it "updates the note" do + expect { put :update, request_params }.to change { note.reload.note } + end + end + describe 'DELETE destroy' do let(:request_params) do { diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb index d7b66e6f078..c358ccae9c3 100644 --- a/spec/helpers/tree_helper_spec.rb +++ b/spec/helpers/tree_helper_spec.rb @@ -1,10 +1,36 @@ require 'spec_helper' describe TreeHelper do + let(:project) { create(:project, :repository) } + let(:repository) { project.repository } + let(:sha) { 'ce369011c189f62c815f5971d096b26759bab0d1' } + + describe '.render_tree' do + before do + @id = sha + @project = project + end + + it 'displays all entries without a warning' do + tree = repository.tree(sha, 'files') + + html = render_tree(tree) + + expect(html).not_to have_selector('.tree-truncated-warning') + end + + it 'truncates entries and adds a warning' do + stub_const('TreeHelper::FILE_LIMIT', 1) + tree = repository.tree(sha, 'files') + + html = render_tree(tree) + + expect(html).to have_selector('.tree-truncated-warning', count: 1) + expect(html).to have_selector('.tree-item-file-name', count: 1) + end + end + describe 'flatten_tree' do - let(:project) { create(:project, :repository) } - let(:repository) { project.repository } - let(:sha) { 'ce369011c189f62c815f5971d096b26759bab0d1' } let(:tree) { repository.tree(sha, 'files') } let(:root_path) { 'files' } let(:tree_item) { tree.entries.find { |entry| entry.path == path } } diff --git a/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js b/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js index ec2c549e032..f96f20ed4a5 100644 --- a/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js +++ b/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js @@ -21,13 +21,18 @@ describe('Unicode Support Map', () => { }); it('should call .getItem and .setItem', () => { - const allArgs = window.localStorage.setItem.calls.allArgs(); - - expect(window.localStorage.getItem).toHaveBeenCalledWith('gl-emoji-user-agent'); - expect(allArgs[0][0]).toBe('gl-emoji-user-agent'); - expect(allArgs[0][1]).toBe(navigator.userAgent); - expect(allArgs[1][0]).toBe('gl-emoji-unicode-support-map'); - expect(allArgs[1][1]).toBe(stringSupportMap); + const getArgs = window.localStorage.getItem.calls.allArgs(); + const setArgs = window.localStorage.setItem.calls.allArgs(); + + expect(getArgs[0][0]).toBe('gl-emoji-version'); + expect(getArgs[1][0]).toBe('gl-emoji-user-agent'); + + expect(setArgs[0][0]).toBe('gl-emoji-version'); + expect(setArgs[0][1]).toBe('0.2.0'); + expect(setArgs[1][0]).toBe('gl-emoji-user-agent'); + expect(setArgs[1][1]).toBe(navigator.userAgent); + expect(setArgs[2][0]).toBe('gl-emoji-unicode-support-map'); + expect(setArgs[2][1]).toBe(stringSupportMap); }); }); diff --git a/spec/javascripts/emoji_spec.js b/spec/javascripts/emoji_spec.js index fa11c602ec3..124d91f4477 100644 --- a/spec/javascripts/emoji_spec.js +++ b/spec/javascripts/emoji_spec.js @@ -1,6 +1,7 @@ import { glEmojiTag } from '~/emoji'; import isEmojiUnicodeSupported, { isFlagEmoji, + isRainbowFlagEmoji, isKeycapEmoji, isSkinToneComboEmoji, isHorceRacingSkinToneComboEmoji, @@ -217,6 +218,24 @@ describe('gl_emoji', () => { }); }); + describe('isRainbowFlagEmoji', () => { + it('should gracefully handle empty string', () => { + expect(isRainbowFlagEmoji('')).toBeFalsy(); + }); + it('should detect rainbow_flag', () => { + expect(isRainbowFlagEmoji('🏳🌈')).toBeTruthy(); + }); + it('should not detect flag_white on its\' own', () => { + expect(isRainbowFlagEmoji('🏳')).toBeFalsy(); + }); + it('should not detect rainbow on its\' own', () => { + expect(isRainbowFlagEmoji('🌈')).toBeFalsy(); + }); + it('should not detect flag_white with something else', () => { + expect(isRainbowFlagEmoji('🏳🔵')).toBeFalsy(); + }); + }); + describe('isKeycapEmoji', () => { it('should gracefully handle empty string', () => { expect(isKeycapEmoji('')).toBeFalsy(); diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js index 2ea290108a4..5662c7387fb 100644 --- a/spec/javascripts/issue_show/components/app_spec.js +++ b/spec/javascripts/issue_show/components/app_spec.js @@ -223,23 +223,46 @@ describe('Issuable output', () => { }); }); - it('closes form on error', (done) => { - spyOn(window, 'Flash').and.callThrough(); - spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve, reject) => { - reject(); - })); + describe('error when updating', () => { + beforeEach(() => { + spyOn(window, 'Flash').and.callThrough(); + spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve, reject) => { + reject(); + })); + }); - vm.updateIssuable(); + it('closes form on error', (done) => { + vm.updateIssuable(); - setTimeout(() => { - expect( - eventHub.$emit, - ).toHaveBeenCalledWith('close.form'); - expect( - window.Flash, - ).toHaveBeenCalledWith('Error updating issue'); + setTimeout(() => { + expect( + eventHub.$emit, + ).toHaveBeenCalledWith('close.form'); + expect( + window.Flash, + ).toHaveBeenCalledWith('Error updating issue'); - done(); + done(); + }); + }); + + it('returns the correct error message for issuableType', (done) => { + vm.issuableType = 'merge request'; + + Vue.nextTick(() => { + vm.updateIssuable(); + + setTimeout(() => { + expect( + eventHub.$emit, + ).toHaveBeenCalledWith('close.form'); + expect( + window.Flash, + ).toHaveBeenCalledWith('Error updating merge request'); + + done(); + }); + }); }); }); }); diff --git a/spec/javascripts/issue_show/components/edit_actions_spec.js b/spec/javascripts/issue_show/components/edit_actions_spec.js index f6625b748b6..d779ab7bb31 100644 --- a/spec/javascripts/issue_show/components/edit_actions_spec.js +++ b/spec/javascripts/issue_show/components/edit_actions_spec.js @@ -61,6 +61,15 @@ describe('Edit Actions components', () => { }); }); + it('should not show delete button if showDeleteButton is false', (done) => { + vm.showDeleteButton = false; + + Vue.nextTick(() => { + expect(vm.$el.querySelector('.btn-danger')).toBeNull(); + done(); + }); + }); + describe('updateIssuable', () => { it('sends update.issauble event when clicking save button', () => { vm.$el.querySelector('.btn-save').click(); diff --git a/spec/javascripts/monitoring/graph_path_spec.js b/spec/javascripts/monitoring/graph_path_spec.js index 8ece913ada8..c83bd19345f 100644 --- a/spec/javascripts/monitoring/graph_path_spec.js +++ b/spec/javascripts/monitoring/graph_path_spec.js @@ -32,4 +32,21 @@ describe('Monitoring Paths', () => { expect(metricLine.getAttribute('stroke')).toBe('#1f78d1'); expect(metricLine.getAttribute('d')).toBe(firstTimeSeries.linePath); }); + + describe('Computed properties', () => { + it('strokeDashArray', () => { + const component = createComponent({ + generatedLinePath: firstTimeSeries.linePath, + generatedAreaPath: firstTimeSeries.areaPath, + lineColor: firstTimeSeries.lineColor, + areaColor: firstTimeSeries.areaColor, + }); + + component.lineStyle = 'dashed'; + expect(component.strokeDashArray).toBe('3, 1'); + + component.lineStyle = 'dotted'; + expect(component.strokeDashArray).toBe('1, 1'); + }); + }); }); diff --git a/spec/javascripts/vue_shared/components/loading_button_spec.js b/spec/javascripts/vue_shared/components/loading_button_spec.js index 97c8a08fcdd..c1eabdede00 100644 --- a/spec/javascripts/vue_shared/components/loading_button_spec.js +++ b/spec/javascripts/vue_shared/components/loading_button_spec.js @@ -66,6 +66,23 @@ describe('LoadingButton', function () { }); }); + describe('container class', () => { + it('should default to btn btn-align-content', () => { + vm = mountComponent(LoadingButton, {}); + expect(vm.$el.classList.contains('btn')).toEqual(true); + expect(vm.$el.classList.contains('btn-align-content')).toEqual(true); + }); + + it('should be configurable through props', () => { + vm = mountComponent(LoadingButton, { + containerClass: 'test-class', + }); + expect(vm.$el.classList.contains('btn')).toEqual(false); + expect(vm.$el.classList.contains('btn-align-content')).toEqual(false); + expect(vm.$el.classList.contains('test-class')).toEqual(true); + }); + }); + describe('click callback prop', () => { it('calls given callback when normal', () => { vm = mountComponent(LoadingButton, { diff --git a/spec/lib/container_registry/path_spec.rb b/spec/lib/container_registry/path_spec.rb index 84cacdd3f0d..010deae822c 100644 --- a/spec/lib/container_registry/path_spec.rb +++ b/spec/lib/container_registry/path_spec.rb @@ -86,6 +86,24 @@ describe ContainerRegistry::Path do it { is_expected.to be_valid } end + + context 'when path contains double underscore' do + let(:path) { 'my/repository__name' } + + it { is_expected.to be_valid } + end + + context 'when path contains invalid separator with dot' do + let(:path) { 'some/registry-.name' } + + it { is_expected.not_to be_valid } + end + + context 'when path contains invalid separator with underscore' do + let(:path) { 'some/registry._name' } + + it { is_expected.not_to be_valid } + end end describe '#has_repository?' do diff --git a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb index 30da56bec16..26529c4759d 100644 --- a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb +++ b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb @@ -41,7 +41,8 @@ describe Gitlab::HookData::IssuableBuilder do labels: [ [{ id: 1, title: 'foo' }], [{ id: 1, title: 'foo' }, { id: 2, title: 'bar' }] - ] + ], + total_time_spent: [1, 2] } end let(:data) { builder.build(user: user, changes: changes) } @@ -53,6 +54,10 @@ describe Gitlab::HookData::IssuableBuilder do labels: { previous: [{ id: 1, title: 'foo' }], current: [{ id: 1, title: 'foo' }, { id: 2, title: 'bar' }] + }, + total_time_spent: { + previous: 1, + current: 2 } })) end diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index ba57301a3c9..4dfbb14952e 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -265,25 +265,44 @@ describe Issuable do end describe '#to_hook_data' do + let(:builder) { double } + context 'labels are updated' do let(:labels) { create_list(:label, 2) } before do issue.update(labels: [labels[1]]) + expect(Gitlab::HookData::IssuableBuilder) + .to receive(:new).with(issue).and_return(builder) end it 'delegates to Gitlab::HookData::IssuableBuilder#build' do - builder = double + expect(builder).to receive(:build).with( + user: user, + changes: hash_including( + 'labels' => [[labels[0].hook_attrs], [labels[1].hook_attrs]] + )) + issue.to_hook_data(user, old_labels: [labels[0]]) + end + end + + context 'total_time_spent is updated' do + before do + issue.spend_time(duration: 2, user: user, spent_at: Time.now) + issue.save expect(Gitlab::HookData::IssuableBuilder) .to receive(:new).with(issue).and_return(builder) + end + + it 'delegates to Gitlab::HookData::IssuableBuilder#build' do expect(builder).to receive(:build).with( user: user, changes: hash_including( - 'labels' => [[labels[0].hook_attrs], [labels[1].hook_attrs]] + 'total_time_spent' => [1, 2] )) - issue.to_hook_data(user, old_labels: [labels[0]]) + issue.to_hook_data(user, old_total_time_spent: 1) end end @@ -292,13 +311,11 @@ describe Issuable do before do issue.assignees << user << user2 + expect(Gitlab::HookData::IssuableBuilder) + .to receive(:new).with(issue).and_return(builder) end it 'delegates to Gitlab::HookData::IssuableBuilder#build' do - builder = double - - expect(Gitlab::HookData::IssuableBuilder) - .to receive(:new).with(issue).and_return(builder) expect(builder).to receive(:build).with( user: user, changes: hash_including( @@ -316,13 +333,11 @@ describe Issuable do before do merge_request.update(assignee: user) merge_request.update(assignee: user2) + expect(Gitlab::HookData::IssuableBuilder) + .to receive(:new).with(merge_request).and_return(builder) end it 'delegates to Gitlab::HookData::IssuableBuilder#build' do - builder = double - - expect(Gitlab::HookData::IssuableBuilder) - .to receive(:new).with(merge_request).and_return(builder) expect(builder).to receive(:build).with( user: user, changes: hash_including( diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 3d46434fc27..929086305ba 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -10,6 +10,10 @@ describe ProjectWiki do subject { project_wiki } + it { is_expected.to delegate_method(:empty?).to :pages } + it { is_expected.to delegate_method(:repository_storage_path).to :project } + it { is_expected.to delegate_method(:hashed_storage?).to :project } + describe "#path_with_namespace" do it "returns the project path with namespace with the .wiki extension" do expect(subject.path_with_namespace).to eq(project.full_path + '.wiki') diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index d919899282d..34ecdd1e164 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -203,18 +203,44 @@ describe API::Internal do end context 'with env passed as a JSON' do - it 'sets env in RequestStore' do - expect(Gitlab::Git::Env).to receive(:set).with({ - 'GIT_OBJECT_DIRECTORY' => 'foo', - 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => 'bar' - }) + context 'when relative path envs are not set' do + it 'sets env in RequestStore' do + expect(Gitlab::Git::Env).to receive(:set).with({ + 'GIT_OBJECT_DIRECTORY' => 'foo', + 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => 'bar' + }) + + push(key, project.wiki, env: { + GIT_OBJECT_DIRECTORY: 'foo', + GIT_ALTERNATE_OBJECT_DIRECTORIES: 'bar' + }.to_json) - push(key, project.wiki, env: { - GIT_OBJECT_DIRECTORY: 'foo', - GIT_ALTERNATE_OBJECT_DIRECTORIES: 'bar' - }.to_json) + expect(response).to have_gitlab_http_status(200) + end + end - expect(response).to have_gitlab_http_status(200) + context 'when relative path envs are set' do + it 'sets env in RequestStore' do + obj_dir_relative = './objects' + alt_obj_dirs_relative = ['./alt-objects-1', './alt-objects-2'] + repo_path = project.wiki.repository.path_to_repo + + expect(Gitlab::Git::Env).to receive(:set).with({ + 'GIT_OBJECT_DIRECTORY' => File.join(repo_path, obj_dir_relative), + 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => alt_obj_dirs_relative.map { |d| File.join(repo_path, d) }, + 'GIT_OBJECT_DIRECTORY_RELATIVE' => obj_dir_relative, + 'GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE' => alt_obj_dirs_relative + }) + + push(key, project.wiki, env: { + GIT_OBJECT_DIRECTORY: 'foo', + GIT_ALTERNATE_OBJECT_DIRECTORIES: 'bar', + GIT_OBJECT_DIRECTORY_RELATIVE: obj_dir_relative, + GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE: alt_obj_dirs_relative + }.to_json) + + expect(response).to have_gitlab_http_status(200) + end end end diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb index 0b1f8ce6f6d..1a5ad9b04e4 100644 --- a/spec/requests/openid_connect_spec.rb +++ b/spec/requests/openid_connect_spec.rb @@ -107,6 +107,15 @@ describe 'OpenID Connect requests' do end end + # These 2 calls shouldn't actually throw, they should be handled as an + # unauthorized request, so we should be able to check the response. + # + # This was not possible due to an issue with Warden: + # https://github.com/hassox/warden/pull/162 + # + # When the patch gets merged and we update Warden, these specs will need to + # updated to check the response instead of a raised exception. + # https://gitlab.com/gitlab-org/gitlab-ce/issues/40218 context 'when user is blocked' do it 'returns authentication error' do access_grant @@ -114,7 +123,7 @@ describe 'OpenID Connect requests' do expect do request_access_token - end.to throw_symbol :warden + end.to raise_error UncaughtThrowError end end @@ -125,7 +134,7 @@ describe 'OpenID Connect requests' do expect do request_access_token - end.to throw_symbol :warden + end.to raise_error UncaughtThrowError end end end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 98409be4236..5ce6ca70c83 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -80,7 +80,7 @@ describe MergeRequests::UpdateService, :mailer do it 'executes hooks with update action' do expect(service) .to have_received(:execute_hooks) - .with(@merge_request, 'update', old_labels: [], old_assignees: [user3]) + .with(@merge_request, 'update', old_labels: [], old_assignees: [user3], old_total_time_spent: 0) end it 'sends email to user2 about assign of new merge request and email to user3 about merge request unassignment' do diff --git a/yarn.lock b/yarn.lock index bf92370d44f..1271c8a1ee3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,10 @@ # yarn lockfile v1 +"@gitlab-org/gitlab-svgs@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.0.2.tgz#e4d29058e2bb438ba71ac525c6397ef15ae2877b" + abbrev@1, abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" @@ -2720,10 +2724,6 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -"gitlab-svgs@https://gitlab.com/gitlab-org/gitlab-svgs.git": - version "1.0.4" - resolved "https://gitlab.com/gitlab-org/gitlab-svgs.git#0442503549e6d74a4e22e1641e1d2ab0ae09884b" - glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" |