* 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 <info@mrsdizzie.com> * rewrite to only use one instance of Tribute * refactor * fix copy/paste error Co-authored-by: mrsdizzie <info@mrsdizzie.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>tags/v1.13.0-rc1
@@ -13574,6 +13574,11 @@ | |||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", | |||
"integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" | |||
}, | |||
"tributejs": { | |||
"version": "5.1.3", | |||
"resolved": "https://registry.npmjs.org/tributejs/-/tributejs-5.1.3.tgz", | |||
"integrity": "sha512-B5CXihaVzXw+1UHhNFyAwUTMDk1EfoLP5Tj1VhD9yybZ1I8DZJEv8tZ1l0RJo0t0tk9ZhR8eG5tEsaCvRigmdQ==" | |||
}, | |||
"trim": { | |||
"version": "0.0.1", | |||
"resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", |
@@ -39,6 +39,7 @@ | |||
"svgo-loader": "2.2.1", | |||
"swagger-ui": "3.25.3", | |||
"terser-webpack-plugin": "3.0.1", | |||
"tributejs": "5.1.3", | |||
"vue": "2.6.11", | |||
"vue-bar-graph": "1.2.0", | |||
"vue-calendar-heatmap": "0.8.4", |
@@ -1,27 +0,0 @@ | |||
.tribute-container { | |||
position: absolute; | |||
top: 0; | |||
left: 0; | |||
height: auto; | |||
max-height: 300px; | |||
max-width: 500px; | |||
overflow: auto; | |||
display: block; | |||
z-index: 999999; } | |||
.tribute-container ul { | |||
margin: 0; | |||
margin-top: 2px; | |||
padding: 0; | |||
list-style: none; | |||
background: #efefef; } | |||
.tribute-container li { | |||
padding: 5px 5px; | |||
cursor: pointer; } | |||
.tribute-container li.highlight, .tribute-container li:hover { | |||
background: #ddd; } | |||
.tribute-container li span { | |||
font-weight: bold; } | |||
.tribute-container li.no-match { | |||
cursor: default; } | |||
.tribute-container .menu-highlighted { | |||
font-weight: bold; } |
@@ -34,10 +34,6 @@ | |||
<script src='{{ URLJoin .RecaptchaURL "api.js"}}' async></script> | |||
{{end}} | |||
{{end}} | |||
{{if .RequireTribute}} | |||
<script src="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.min.js"></script> | |||
{{end}} | |||
<script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script> | |||
<script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script> | |||
{{template "custom/footer" .}} |
@@ -119,10 +119,6 @@ | |||
{{if .RequireSimpleMDE}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css"> | |||
{{end}} | |||
{{if .RequireTribute}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css"> | |||
{{end}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}"> | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}"> | |||
<noscript> |
@@ -10,6 +10,7 @@ var urlsToCache = [ | |||
'{{StaticUrlPrefix}}/js/swagger.js?v={{MD5 AppVer}}', | |||
'{{StaticUrlPrefix}}/js/dropzone.js', | |||
'{{StaticUrlPrefix}}/js/datetimepicker.js', | |||
'{{StaticUrlPrefix}}/js/tribute.js', | |||
'{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js', | |||
'{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js', | |||
'{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js', | |||
@@ -24,7 +25,6 @@ var urlsToCache = [ | |||
'{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css', | |||
'{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css', | |||
'{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css', | |||
'{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css', | |||
{{if .IsSigned }} | |||
{{ if ne .SignedUser.Theme "gitea" }} | |||
'{{StaticUrlPrefix}}/css/theme-{{.SignedUser.Theme}}.css?v={{MD5 AppVer}}', |
@@ -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/>'); | |||
div.append($('<img/>', {src: item.original.avatar})); | |||
div.append($('<span/>', {class: 'name'}).text(item.original.name)); | |||
if (item.original.fullname && item.original.fullname !== '') { | |||
div.append($('<span/>', {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 `<div class="tribute-item">${emojiHTML(item.original)}<span>${item.original}</span></div>`; | |||
} | |||
cb(matches); | |||
}, | |||
lookup(item) { | |||
return item; | |||
}, | |||
selectTemplate(item) { | |||
if (typeof item === 'undefined') return null; | |||
return emojiString(item.original); | |||
}, | |||
menuItemTemplate(item) { | |||
return `<div class="tribute-item">${emojiHTML(item.original)}<span>${item.original}</span></div>`; | |||
} | |||
}] | |||
}) : 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 ` | |||
<div class="tribute-item"> | |||
<img src="${item.original.avatar}"/> | |||
<span class="name">${item.original.name}</span> | |||
${item.original.fullname && item.original.fullname !== '' ? `<span class="fullname">${item.original.fullname}</span>` : ''} | |||
</div> | |||
`; | |||
} | |||
}); | |||
} | |||
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; | |||
} |
@@ -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(), |
@@ -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)); | |||
} |
@@ -1,34 +1,29 @@ | |||
@import "~tributejs/dist/tribute.css"; | |||
.tribute-container { | |||
box-shadow: 0 1px 3px 1px #c7c7c7; | |||
ul { | |||
background: #ffffff; | |||
} | |||
li { | |||
padding: 8px 12px; | |||
border-bottom: 1px solid #dcdcdc; | |||
img { | |||
display: inline-block; | |||
vertical-align: middle; | |||
width: 28px; | |||
height: 28px; | |||
margin-right: 5px; | |||
} | |||
span.fullname { | |||
font-weight: normal; | |||
font-size: .8rem; | |||
margin-left: 3px; | |||
} | |||
} | |||
li.highlight, | |||
li:hover { | |||
background: #2185d0; | |||
color: #ffffff; | |||
} | |||
box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .25); | |||
border-radius: .25rem; | |||
} | |||
.tribute-container ul { | |||
margin-top: 0 !important; | |||
background: #ffffff !important; | |||
} | |||
.tribute-container li { | |||
padding: 3px .5rem !important; | |||
} | |||
.tribute-container li span.fullname { | |||
font-weight: normal; | |||
font-size: .8rem; | |||
margin-left: 3px; | |||
} | |||
.tribute-container li.highlight, | |||
.tribute-container li:hover { | |||
background: #2185d0 !important; | |||
color: #ffffff !important; | |||
} | |||
.tribute-item { | |||
@@ -36,6 +31,12 @@ | |||
align-items: center; | |||
} | |||
.tribute-item .emoji { | |||
.tribute-item .emoji, | |||
.tribute-item img[src*="/avatar/"] { | |||
margin-right: .5rem; | |||
} | |||
.tribute-container img { | |||
width: 1.5rem !important; | |||
height: 1.5rem !important; | |||
} |
@@ -1625,3 +1625,16 @@ footer .container .links > * { | |||
.repository.release #release-list > li .detail .dot { | |||
background-color: #888; | |||
} | |||
.tribute-container { | |||
box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .6); | |||
} | |||
.tribute-container ul { | |||
background: #2d303b !important; | |||
} | |||
.tribute-container li.highlight, | |||
.tribute-container li:hover { | |||
background: #728e5e !important; | |||
} |