diff options
author | Tim Zallmann <tzallmann@gitlab.com> | 2019-03-07 12:33:03 +0300 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2019-03-07 12:33:03 +0300 |
commit | d07919de90e8212673adb47a4e60514c2573f2ce (patch) | |
tree | a45262773f31061182db9fe39700fea726b6cfc2 /app/assets/javascripts | |
parent | b7998f60f63a4b85db7b835ef152a9042db5e791 (diff) |
Moved all emojis to the public folder
Created new emojis map in public folder
Renamed folder to emojis
Loading now the emojis from Localstorage or from Server
Moved all emojis to the public folder
Loading the emojis.json file now through AJAX
Loads now the map in the web element instead when building the emoji tag
Updated the custom Element Setup to modern method
Fixed Emoji Karma Specs for async loading
Loading now the emojis from Localstorage or from Server
Loads now the map in the web element instead when building the emoji tag
Fixed problem with FIXTURE_PATH for emojis fixtures
Fixes Linting Error in gemojione.rake
Fixed Emoji Karma Specs
Fix static type check in gemojione and check if already registered
Testing if the Emoji Support Check is failing Rspec
Change of CLass Name, returning true on check to test
Fixes failing Emoji RSpec Tests
Moved Emojis into public/-/emojis/1/
Fixed Linting Errors in gl_emoji
Fix to fixtures creation for emojis
Fixed path spec for new subdirectory -/emojis
Optimized emojis.json output
Fix for Emoji Spec failure due to unicode dataset
Better catch handling for emojis
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r-- | app/assets/javascripts/awards_handler.js | 16 | ||||
-rw-r--r-- | app/assets/javascripts/behaviors/gl_emoji.js | 97 | ||||
-rw-r--r-- | app/assets/javascripts/emoji/index.js | 72 | ||||
-rw-r--r-- | app/assets/javascripts/emoji/support/index.js | 3 | ||||
-rw-r--r-- | app/assets/javascripts/filtered_search/visual_token_value.js | 23 | ||||
-rw-r--r-- | app/assets/javascripts/gfm_auto_complete.js | 12 | ||||
-rw-r--r-- | app/assets/javascripts/pages/profiles/show/index.js | 48 | ||||
-rw-r--r-- | app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue | 28 |
8 files changed, 200 insertions, 99 deletions
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 73ce3e760ab..aeb88715c11 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -615,10 +615,18 @@ export class AwardsHandler { let awardsHandlerPromise = null; export default function loadAwardsHandler(reload = false) { if (!awardsHandlerPromise || reload) { - awardsHandlerPromise = import(/* webpackChunkName: 'emoji' */ './emoji').then(Emoji => { - const awardsHandler = new AwardsHandler(Emoji); - awardsHandler.bindEvents(); - return awardsHandler; + awardsHandlerPromise = new Promise((resolve, reject) => { + import(/* webpackChunkName: 'emoji' */ './emoji') + .then(Emoji => { + Emoji.initEmojiMap() + .then(() => { + const awardsHandler = new AwardsHandler(Emoji); + awardsHandler.bindEvents(); + resolve(awardsHandler); + }) + .catch(() => reject); + }) + .catch(() => reject); }); } return awardsHandlerPromise; diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js index d1d75658181..9034563d9b3 100644 --- a/app/assets/javascripts/behaviors/gl_emoji.js +++ b/app/assets/javascripts/behaviors/gl_emoji.js @@ -1,47 +1,74 @@ import 'document-register-element'; import isEmojiUnicodeSupported from '../emoji/support'; +import { initEmojiMap, getEmojiInfo, emojiFallbackImageSrc, emojiImageTag } from '../emoji'; class GlEmoji extends HTMLElement { constructor() { super(); - const emojiUnicode = this.textContent.trim(); - const { name, unicodeVersion, fallbackSrc, fallbackSpriteClass } = this.dataset; - - const isEmojiUnicode = - this.childNodes && - Array.prototype.every.call(this.childNodes, childNode => childNode.nodeType === 3); - const hasImageFallback = fallbackSrc && fallbackSrc.length > 0; - const hasCssSpriteFalback = fallbackSpriteClass && fallbackSpriteClass.length > 0; - - if (emojiUnicode && isEmojiUnicode && !isEmojiUnicodeSupported(emojiUnicode, unicodeVersion)) { - // CSS sprite fallback takes precedence over image fallback - if (hasCssSpriteFalback) { - if (!gon.emoji_sprites_css_added && gon.emoji_sprites_css_path) { - const emojiSpriteLinkTag = document.createElement('link'); - emojiSpriteLinkTag.setAttribute('rel', 'stylesheet'); - emojiSpriteLinkTag.setAttribute('href', gon.emoji_sprites_css_path); - document.head.appendChild(emojiSpriteLinkTag); - gon.emoji_sprites_css_added = true; - } - // IE 11 doesn't like adding multiple at once :( - this.classList.add('emoji-icon'); - this.classList.add(fallbackSpriteClass); - } else { - import(/* webpackChunkName: 'emoji' */ '../emoji') - .then(({ emojiImageTag, emojiFallbackImageSrc }) => { - if (hasImageFallback) { - this.innerHTML = emojiImageTag(name, fallbackSrc); + let emojiUnicode = this.textContent.trim(); + const { fallbackSpriteClass, fallbackSrc, forceFallback } = this.dataset; + let { name, unicodeVersion } = this.dataset; + + initEmojiMap() + .then(() => { + if (!unicodeVersion) { + const emojiInfo = getEmojiInfo(name); + + if (emojiInfo) { + if (name !== emojiInfo.name) { + ({ name } = emojiInfo); + this.dataset.name = emojiInfo.name; + } + unicodeVersion = emojiInfo.u; + this.dataset.uni = unicodeVersion; + + if (forceFallback === 'true' && !fallbackSpriteClass) { + this.innerHTML = emojiImageTag(name, emojiFallbackImageSrc(name)); } else { - const src = emojiFallbackImageSrc(name); - this.innerHTML = emojiImageTag(name, src); + emojiUnicode = emojiInfo.e; + this.innerHTML = emojiInfo.e; } - }) - .catch(() => { - // do nothing - }); - } - } + + this.title = emojiInfo.d; + } + } + + const isEmojiUnicode = + this.childNodes && + Array.prototype.every.call(this.childNodes, childNode => childNode.nodeType === 3); + const hasImageFallback = fallbackSrc && fallbackSrc.length > 0; + const hasCssSpriteFalback = fallbackSpriteClass && fallbackSpriteClass.length > 0; + + if ( + emojiUnicode && + isEmojiUnicode && + !isEmojiUnicodeSupported(emojiUnicode, unicodeVersion) + ) { + // CSS sprite fallback takes precedence over image fallback + if (hasCssSpriteFalback) { + if (!gon.emoji_sprites_css_added && gon.emoji_sprites_css_path) { + const emojiSpriteLinkTag = document.createElement('link'); + emojiSpriteLinkTag.setAttribute('rel', 'stylesheet'); + emojiSpriteLinkTag.setAttribute('href', gon.emoji_sprites_css_path); + document.head.appendChild(emojiSpriteLinkTag); + gon.emoji_sprites_css_added = true; + } + // IE 11 doesn't like adding multiple at once :( + this.classList.add('emoji-icon'); + this.classList.add(fallbackSpriteClass); + } else if (hasImageFallback) { + this.innerHTML = emojiImageTag(name, fallbackSrc); + } else { + const src = emojiFallbackImageSrc(name); + this.innerHTML = emojiImageTag(name, src); + } + } + }) + .catch(error => { + // Only reject is already handled in initEmojiMap + throw error; + }); } } diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js index cd8dff40b88..36542315c4c 100644 --- a/app/assets/javascripts/emoji/index.js +++ b/app/assets/javascripts/emoji/index.js @@ -1,13 +1,58 @@ import _ from 'underscore'; -import emojiMap from 'emojis/digests.json'; +import createFlash from '~/flash'; +import { s__ } from '~/locale'; import emojiAliases from 'emojis/aliases.json'; +import axios from '../lib/utils/axios_utils'; -export const validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)]; +import AccessorUtilities from '../lib/utils/accessor'; + +let emojiMap = null; +let validEmojiNames = null; + +export const EMOJI_VERSION = '1'; +const EMOJI_VERSION_LOCALSTORAGE = `EMOJIS_${EMOJI_VERSION}`; + +const isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe(); + +export function initEmojiMap() { + return new Promise((resolve, reject) => { + if (emojiMap) { + resolve(emojiMap); + } else if (isLocalStorageAvailable && window.localStorage.getItem(EMOJI_VERSION_LOCALSTORAGE)) { + emojiMap = JSON.parse(window.localStorage.getItem(EMOJI_VERSION_LOCALSTORAGE)); + validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)]; + resolve(emojiMap); + } else { + // We load the JSON from server + axios + .get( + `${gon.asset_host || ''}${gon.relative_url_root || + ''}/-/emojis/${EMOJI_VERSION}/emojis.json`, + ) + .then(({ data }) => { + emojiMap = data; + validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)]; + resolve(emojiMap); + if (isLocalStorageAvailable) { + window.localStorage.setItem(EMOJI_VERSION_LOCALSTORAGE, JSON.stringify(emojiMap)); + } + }) + .catch(err => { + createFlash(s__('Emojis|Something went wrong while loading emojis.')); + reject(err); + }); + } + }); +} export function normalizeEmojiName(name) { return Object.prototype.hasOwnProperty.call(emojiAliases, name) ? emojiAliases[name] : name; } +export function getValidEmojiNames() { + return validEmojiNames; +} + export function isEmojiNameValid(name) { return validEmojiNames.indexOf(name) >= 0; } @@ -36,8 +81,8 @@ export function getEmojiCategoryMap() { }; Object.keys(emojiMap).forEach(name => { const emoji = emojiMap[name]; - if (emojiCategoryMap[emoji.category]) { - emojiCategoryMap[emoji.category].push(name); + if (emojiCategoryMap[emoji.c]) { + emojiCategoryMap[emoji.c].push(name); } }); } @@ -58,8 +103,9 @@ export function getEmojiInfo(query) { } export function emojiFallbackImageSrc(inputName) { - const { name, digest } = getEmojiInfo(inputName); - return `${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/emoji/${name}-${digest}.png`; + const { name } = getEmojiInfo(inputName); + return `${gon.asset_host || ''}${gon.relative_url_root || + ''}/-/emojis/${EMOJI_VERSION}/${name}.png`; } export function emojiImageTag(name, src) { @@ -68,9 +114,8 @@ export function emojiImageTag(name, src) { export function glEmojiTag(inputName, options) { const opts = { sprite: false, forceFallback: false, ...options }; - const { name, ...emojiInfo } = getEmojiInfo(inputName); + const name = normalizeEmojiName(inputName); - const fallbackImageSrc = emojiFallbackImageSrc(name); const fallbackSpriteClass = `emoji-${name}`; const classList = []; @@ -79,24 +124,19 @@ export function glEmojiTag(inputName, options) { classList.push(fallbackSpriteClass); } const classAttribute = classList.length > 0 ? `class="${classList.join(' ')}"` : ''; + const fallbackSpriteAttribute = opts.sprite ? `data-fallback-sprite-class="${fallbackSpriteClass}"` : ''; - let contents = emojiInfo.moji; - if (opts.forceFallback && !opts.sprite) { - contents = emojiImageTag(name, fallbackImageSrc); - } + const forceFallbackAttribute = opts.forceFallback ? 'data-force-fallback="true"' : ''; return ` <gl-emoji ${classAttribute} data-name="${name}" - data-fallback-src="${fallbackImageSrc}" ${fallbackSpriteAttribute} - data-unicode-version="${emojiInfo.unicodeVersion}" - title="${emojiInfo.description}" + ${forceFallbackAttribute} > - ${contents} </gl-emoji> `; } diff --git a/app/assets/javascripts/emoji/support/index.js b/app/assets/javascripts/emoji/support/index.js index 1f7852dd487..ed9bfb8bc78 100644 --- a/app/assets/javascripts/emoji/support/index.js +++ b/app/assets/javascripts/emoji/support/index.js @@ -5,6 +5,9 @@ import getUnicodeSupportMap from './unicode_support_map'; let browserUnicodeSupportMap; export default function isEmojiUnicodeSupportedByBrowser(emojiUnicode, unicodeVersion) { + // Our Spec browser would fail producing emoji maps + if (/\bHeadlessChrome\//.test(navigator.userAgent)) return true; + browserUnicodeSupportMap = browserUnicodeSupportMap || getUnicodeSupportMap(); return isEmojiUnicodeSupported(browserUnicodeSupportMap, emojiUnicode, unicodeVersion); } diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js index 99008a4c989..7f6f41c18f7 100644 --- a/app/assets/javascripts/filtered_search/visual_token_value.js +++ b/app/assets/javascripts/filtered_search/visual_token_value.js @@ -102,15 +102,24 @@ export default class VisualTokenValue { return ( import(/* webpackChunkName: 'emoji' */ '../emoji') .then(Emoji => { - if (!Emoji.isEmojiNameValid(value)) { - return; - } - - container.dataset.originalValue = value; - element.innerHTML = Emoji.glEmojiTag(value); + Emoji.initEmojiMap() + .then(() => { + if (!Emoji.isEmojiNameValid(value)) { + return; + } + + container.dataset.originalValue = value; + element.innerHTML = Emoji.glEmojiTag(value); + }) + // ignore error and leave emoji name in the search bar + .catch(err => { + throw err; + }); }) // ignore error and leave emoji name in the search bar - .catch(() => {}) + .catch(importError => { + throw importError; + }) ); } } diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index c81e754df4c..50ea13edf63 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -487,9 +487,15 @@ class GfmAutoComplete { this.loadData($input, at, this.cachedData[at]); } else if (GfmAutoComplete.atTypeMap[at] === 'emojis') { import(/* webpackChunkName: 'emoji' */ './emoji') - .then(({ validEmojiNames, glEmojiTag }) => { - this.loadData($input, at, validEmojiNames); - GfmAutoComplete.glEmojiTag = glEmojiTag; + .then(({ initEmojiMap, getValidEmojiNames, glEmojiTag }) => { + initEmojiMap() + .then(() => { + this.loadData($input, at, getValidEmojiNames()); + GfmAutoComplete.glEmojiTag = glEmojiTag; + }) + .catch(() => { + this.isLoadingData[at] = false; + }); }) .catch(() => { this.isLoadingData[at] = false; diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js index 0dd0d5336fc..c9d3bbc8c39 100644 --- a/app/assets/javascripts/pages/profiles/show/index.js +++ b/app/assets/javascripts/pages/profiles/show/index.js @@ -56,30 +56,34 @@ document.addEventListener('DOMContentLoaded', () => { import(/* webpackChunkName: 'emoji' */ '~/emoji') .then(Emoji => { - const emojiMenu = new EmojiMenu( - Emoji, - toggleEmojiMenuButtonSelector, - 'js-status-emoji-menu', - selectEmojiCallback, - ); - emojiMenu.bindEvents(); + Emoji.initEmojiMap() + .then(() => { + const emojiMenu = new EmojiMenu( + Emoji, + toggleEmojiMenuButtonSelector, + 'js-status-emoji-menu', + selectEmojiCallback, + ); + emojiMenu.bindEvents(); - const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji); - statusMessageField.addEventListener('input', () => { - const hasStatusMessage = statusMessageField.value.trim() !== ''; - const statusEmoji = findStatusEmoji(); - if (hasStatusMessage && statusEmoji) { - return; - } + const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji); + statusMessageField.addEventListener('input', () => { + const hasStatusMessage = statusMessageField.value.trim() !== ''; + const statusEmoji = findStatusEmoji(); + if (hasStatusMessage && statusEmoji) { + return; + } - if (hasStatusMessage) { - toggleNoEmojiPlaceholder(false); - toggleEmojiMenuButton.innerHTML += defaultEmojiTag; - } else if (statusEmoji.dataset.name === defaultStatusEmoji) { - toggleNoEmojiPlaceholder(true); - removeStatusEmoji(); - } - }); + if (hasStatusMessage) { + toggleNoEmojiPlaceholder(false); + toggleEmojiMenuButton.innerHTML += defaultEmojiTag; + } else if (statusEmoji.dataset.name === defaultStatusEmoji) { + toggleNoEmojiPlaceholder(true); + removeStatusEmoji(); + } + }); + }) + .catch(() => createFlash('Failed to load emoji list.')); }) .catch(() => createFlash('Failed to load emoji list.')); }); diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue index 7f86741ed29..e9ed05e30cd 100644 --- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue +++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue @@ -66,19 +66,23 @@ export default { import(/* webpackChunkName: 'emoji' */ '~/emoji') .then(Emoji => { - if (this.emoji) { - this.emojiTag = Emoji.glEmojiTag(this.emoji); - } - this.noEmoji = this.emoji === ''; - this.defaultEmojiTag = Emoji.glEmojiTag('speech_balloon'); + Emoji.initEmojiMap() + .then(() => { + if (this.emoji) { + this.emojiTag = Emoji.glEmojiTag(this.emoji); + } + this.noEmoji = this.emoji === ''; + this.defaultEmojiTag = Emoji.glEmojiTag('speech_balloon'); - this.emojiMenu = new EmojiMenuInModal( - Emoji, - toggleEmojiMenuButtonSelector, - emojiMenuClass, - this.setEmoji, - this.$refs.userStatusForm, - ); + this.emojiMenu = new EmojiMenuInModal( + Emoji, + toggleEmojiMenuButtonSelector, + emojiMenuClass, + this.setEmoji, + this.$refs.userStatusForm, + ); + }) + .catch(() => createFlash(__('Failed to load emoji list.'))); }) .catch(() => createFlash(__('Failed to load emoji list.'))); }, |