From b02d2c37728491caaf8af3384b8d3b25411e4679 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 21 May 2020 04:00:43 +0200 Subject: Move tributejs to npm/webpack (#11497) * Move tributejs to npm/webpack - Move vendored bundle to npm and webpack - Rewrote initialization to single function - Restyled it (made it a bit smaller) - Fixed it for arc-green * fix mention * also include emoji on #content * Update web_src/less/_tribute.less Co-authored-by: mrsdizzie * rewrite to only use one instance of Tribute * refactor * fix copy/paste error Co-authored-by: mrsdizzie Co-authored-by: techknowlogick --- web_src/js/features/tribute.js | 118 +++++++++++++++++++++++------------------ web_src/js/index.js | 13 +++-- web_src/js/utils.js | 5 ++ 3 files changed, 78 insertions(+), 58 deletions(-) (limited to 'web_src/js') diff --git a/web_src/js/features/tribute.js b/web_src/js/features/tribute.js index 30afb2b184..851ff74e57 100644 --- a/web_src/js/features/tribute.js +++ b/web_src/js/features/tribute.js @@ -1,61 +1,77 @@ import {emojiKeys, emojiHTML, emojiString} from './emoji.js'; +import {uniq} from '../utils.js'; -export const issuesTribute = window.config.Tribute ? new Tribute({ - values: window.config.tributeValues, - noMatchTemplate() { return null }, - menuItemTemplate(item) { - const div = $('
'); - div.append($('', {src: item.original.avatar})); - div.append($('', {class: 'name'}).text(item.original.name)); - if (item.original.fullname && item.original.fullname !== '') { - div.append($('', {class: 'fullname'}).text(item.original.fullname)); - } - return div.html(); - } -}) : null; - -export const emojiTribute = window.config.Tribute ? new Tribute({ - collection: [{ - trigger: ':', - requireLeadingSpace: true, - values(query, cb) { - const matches = []; - for (const name of emojiKeys) { - if (name.includes(query)) { - matches.push(name); - if (matches.length > 5) break; +function makeCollections({mentions, emoji}) { + const collections = []; + + if (mentions) { + collections.push({ + trigger: ':', + requireLeadingSpace: true, + values: (query, cb) => { + const matches = []; + for (const name of emojiKeys) { + if (name.includes(query)) { + matches.push(name); + if (matches.length > 5) break; + } } + cb(matches); + }, + lookup: (item) => item, + selectTemplate: (item) => { + if (typeof item === 'undefined') return null; + return emojiString(item.original); + }, + menuItemTemplate: (item) => { + return `
${emojiHTML(item.original)}${item.original}
`; } - cb(matches); - }, - lookup(item) { - return item; - }, - selectTemplate(item) { - if (typeof item === 'undefined') return null; - return emojiString(item.original); - }, - menuItemTemplate(item) { - return `
${emojiHTML(item.original)}${item.original}
`; - } - }] -}) : null; - -export function initTribute() { - if (!window.config.Tribute) return; - - let content = document.getElementById('content'); - if (content !== null) { - issuesTribute.attach(content); + }); } - const emojiInputs = document.querySelectorAll('.emoji-input'); - if (emojiInputs.length > 0) { - emojiTribute.attach(emojiInputs); + if (emoji) { + collections.push({ + values: window.config.tributeValues, + noMatchTemplate: () => null, + menuItemTemplate: (item) => { + return ` +
+ + ${item.original.name} + ${item.original.fullname && item.original.fullname !== '' ? `${item.original.fullname}` : ''} +
+ `; + } + }); } - content = document.getElementById('content'); - if (content !== null) { - emojiTribute.attach(document.getElementById('content')); + return collections; +} + +export default async function attachTribute(elementOrNodeList, {mentions, emoji} = {}) { + if (!window.config.Tribute || !elementOrNodeList) return; + const nodes = Array.from('length' in elementOrNodeList ? elementOrNodeList : [elementOrNodeList]); + if (!nodes.length) return; + + const mentionNodes = nodes.filter((node) => { + return mentions || node.id === 'content'; + }); + const emojiNodes = nodes.filter((node) => { + return emoji || node.id === 'content' || node.classList.contains('emoji-input'); + }); + const uniqueNodes = uniq([...mentionNodes, ...emojiNodes]); + if (!uniqueNodes.length) return; + + const {default: Tribute} = await import(/* webpackChunkName: "tribute" */'tributejs'); + + const collections = makeCollections({ + mentions: mentions || mentionNodes.length > 0, + emoji: emoji || emojiNodes.length > 0, + }); + + const tribute = new Tribute({collection: collections}); + for (const node of uniqueNodes) { + tribute.attach(node); } + return tribute; } diff --git a/web_src/js/index.js b/web_src/js/index.js index 4042924b6f..fdc5a926db 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -14,7 +14,7 @@ import initGitGraph from './features/gitgraph.js'; import initClipboard from './features/clipboard.js'; import initUserHeatmap from './features/userheatmap.js'; import initDateTimePicker from './features/datetimepicker.js'; -import {initTribute, issuesTribute, emojiTribute} from './features/tribute.js'; +import attachTribute from './features/tribute.js'; import createDropzone from './features/dropzone.js'; import highlight from './features/highlight.js'; import ActivityTopAuthors from './components/ActivityTopAuthors.vue'; @@ -891,8 +891,7 @@ async function initRepository() { if ($editContentZone.html().length === 0) { $editContentZone.html($('#edit-content-form').html()); $textarea = $editContentZone.find('textarea'); - issuesTribute.attach($textarea.get()); - emojiTribute.attach($textarea.get()); + attachTribute($textarea.get(), {mentions: true, emoji: true}); let dz; const $dropzone = $editContentZone.find('.dropzone'); @@ -1496,7 +1495,8 @@ function setCommentSimpleMDE($editArea) { $(simplemde.codemirror.getInputField()).addClass('js-quick-submit'); simplemde.codemirror.setOption('extraKeys', { Enter: () => { - if (!(issuesTribute.isActive || emojiTribute.isActive)) { + const tributeContainer = document.querySelector('.tribute-container'); + if (tributeContainer && tributeContainer.style.display !== 'none') { return CodeMirror.Pass; } }, @@ -1507,8 +1507,7 @@ function setCommentSimpleMDE($editArea) { cm.execCommand('delCharBefore'); } }); - issuesTribute.attach(simplemde.codemirror.getInputField()); - emojiTribute.attach(simplemde.codemirror.getInputField()); + attachTribute(simplemde.codemirror.getInputField(), {mentions: true, emoji: true}); return simplemde; } @@ -2431,7 +2430,6 @@ $(document).ready(async () => { initContextPopups(); initNotificationsTable(); initNotificationCount(); - initTribute(); // Repo clone url. if ($('#repo-clone-url').length > 0) { @@ -2473,6 +2471,7 @@ $(document).ready(async () => { // parallel init of lazy-loaded features await Promise.all([ highlight(document.querySelectorAll('pre code')), + attachTribute(document.querySelectorAll('#content, .emoji-input')), initGitGraph(), initClipboard(), initUserHeatmap(), diff --git a/web_src/js/utils.js b/web_src/js/utils.js index b511c9981d..b16b05a1b7 100644 --- a/web_src/js/utils.js +++ b/web_src/js/utils.js @@ -23,3 +23,8 @@ export function isObject(obj) { export function isDarkTheme() { return document.documentElement.classList.contains('theme-arc-green'); } + +// removes duplicate elements in an array +export function uniq(arr) { + return Array.from(new Set(arr)); +} -- cgit v1.2.3