diff options
Diffstat (limited to 'app/javascript/mastodon/features/emoji/emoji.js')
-rw-r--r-- | app/javascript/mastodon/features/emoji/emoji.js | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/app/javascript/mastodon/features/emoji/emoji.js b/app/javascript/mastodon/features/emoji/emoji.js index b70fc2b37..0f005dd50 100644 --- a/app/javascript/mastodon/features/emoji/emoji.js +++ b/app/javascript/mastodon/features/emoji/emoji.js @@ -1,3 +1,4 @@ +import { autoPlayGif } from '../../initial_state'; import unicodeMapping from './emoji_unicode_mapping_light'; import Trie from 'substring-trie'; @@ -5,13 +6,13 @@ const trie = new Trie(Object.keys(unicodeMapping)); const assetHost = process.env.CDN_HOST || ''; -let allowAnimations = false; - const emojify = (str, customEmojis = {}) => { - let rtn = ''; + const tagCharsWithoutEmojis = '<&'; + const tagCharsWithEmojis = Object.keys(customEmojis).length ? '<&:' : '<&'; + let rtn = '', tagChars = tagCharsWithEmojis, invisible = 0; for (;;) { let match, i = 0, tag; - while (i < str.length && (tag = '<&:'.indexOf(str[i])) === -1 && !(match = trie.search(str.slice(i)))) { + while (i < str.length && (tag = tagChars.indexOf(str[i])) === -1 && (invisible || !(match = trie.search(str.slice(i))))) { i += str.codePointAt(i) < 65536 ? 1 : 2; } let rend, replacement = ''; @@ -27,7 +28,7 @@ const emojify = (str, customEmojis = {}) => { // now got a replacee as ':shortname:' // if you want additional emoji handler, add statements below which set replacement and return true. if (shortname in customEmojis) { - const filename = allowAnimations ? customEmojis[shortname].url : customEmojis[shortname].static_url; + const filename = autoPlayGif ? customEmojis[shortname].url : customEmojis[shortname].static_url; replacement = `<img draggable="false" class="emojione" alt="${shortname}" title="${shortname}" src="${filename}" />`; return true; } @@ -35,7 +36,26 @@ const emojify = (str, customEmojis = {}) => { })()) rend = ++i; } else if (tag >= 0) { // <, & rend = str.indexOf('>;'[tag], i + 1) + 1; - if (!rend) break; + if (!rend) { + break; + } + if (tag === 0) { + if (invisible) { + if (str[i + 1] === '/') { // closing tag + if (!--invisible) { + tagChars = tagCharsWithEmojis; + } + } else if (str[rend - 2] !== '/') { // opening tag + invisible++; + } + } else { + if (str.startsWith('<span class="invisible">', i)) { + // avoid emojifying on invisible text + invisible = 1; + tagChars = tagCharsWithoutEmojis; + } + } + } i = rend; } else { // matched to unicode emoji const { filename, shortCode } = unicodeMapping[match]; @@ -51,14 +71,12 @@ const emojify = (str, customEmojis = {}) => { export default emojify; -export const buildCustomEmojis = (customEmojis, overrideAllowAnimations = false) => { +export const buildCustomEmojis = (customEmojis) => { const emojis = []; - allowAnimations = overrideAllowAnimations; - customEmojis.forEach(emoji => { const shortcode = emoji.get('shortcode'); - const url = allowAnimations ? emoji.get('url') : emoji.get('static_url'); + const url = autoPlayGif ? emoji.get('url') : emoji.get('static_url'); const name = shortcode.replace(':', ''); emojis.push({ |