aboutsummaryrefslogtreecommitdiffstats
path: root/web_src
diff options
context:
space:
mode:
Diffstat (limited to 'web_src')
-rw-r--r--web_src/js/features/contextpopup.js3
-rw-r--r--web_src/js/features/emoji.js38
-rw-r--r--web_src/js/features/tribute.js61
-rw-r--r--web_src/js/index.js29
-rw-r--r--web_src/less/_base.less36
-rw-r--r--web_src/less/_dashboard.less4
-rw-r--r--web_src/less/_emojify.less10
-rw-r--r--web_src/less/_repository.less19
-rw-r--r--web_src/less/_tribute.less9
-rw-r--r--web_src/less/index.less1
10 files changed, 163 insertions, 47 deletions
diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js
index 6feaa768c0..377a6a8f5a 100644
--- a/web_src/js/features/contextpopup.js
+++ b/web_src/js/features/contextpopup.js
@@ -24,7 +24,6 @@ function issuePopup(owner, repo, index, $element) {
let labels = '';
for (let i = 0; i < issue.labels.length; i++) {
const label = issue.labels[i];
- const labelName = emojify.replace(label.name);
const red = parseInt(label.color.substring(0, 2), 16);
const green = parseInt(label.color.substring(2, 4), 16);
const blue = parseInt(label.color.substring(4, 6), 16);
@@ -32,7 +31,7 @@ function issuePopup(owner, repo, index, $element) {
if ((red * 0.299 + green * 0.587 + blue * 0.114) > 125) {
color = '#000000';
}
- labels += `<div class="ui label" style="color: ${color}; background-color:#${label.color};">${labelName}</div>`;
+ labels += `<div class="ui label" style="color: ${color}; background-color:#${label.color};">${label.name}</div>`;
}
if (labels.length > 0) {
labels = `<p>${labels}</p>`;
diff --git a/web_src/js/features/emoji.js b/web_src/js/features/emoji.js
new file mode 100644
index 0000000000..3c24a165b9
--- /dev/null
+++ b/web_src/js/features/emoji.js
@@ -0,0 +1,38 @@
+import emojis from '../../../assets/emoji.json';
+
+const {StaticUrlPrefix} = window.config;
+
+const tempMap = {gitea: ':gitea:'};
+for (const {emoji, aliases} of emojis) {
+ for (const alias of aliases || []) {
+ tempMap[alias] = emoji;
+ }
+}
+
+export const emojiKeys = Object.keys(tempMap).sort((a, b) => {
+ if (a === '+1' || a === '-1') return -1;
+ if (b === '+1' || b === '-1') return 1;
+ return a.localeCompare(b);
+});
+
+export const emojiMap = {};
+for (const key of emojiKeys) {
+ emojiMap[key] = tempMap[key];
+}
+
+// retrieve HTML for given emoji name
+export function emojiHTML(name) {
+ let inner;
+ if (name === 'gitea') {
+ inner = `<img class="emoji" alt=":${name}:" src="${StaticUrlPrefix}/img/emoji/gitea.png" align="absmiddle">`;
+ } else {
+ inner = emojiString(name);
+ }
+
+ return `<span class="emoji" title=":${name}:">${inner}</span>`;
+}
+
+// retrieve string for given emoji name
+export function emojiString(name) {
+ return emojiMap[name] || `:${name}:`;
+}
diff --git a/web_src/js/features/tribute.js b/web_src/js/features/tribute.js
new file mode 100644
index 0000000000..30afb2b184
--- /dev/null
+++ b/web_src/js/features/tribute.js
@@ -0,0 +1,61 @@
+import {emojiKeys, emojiHTML, emojiString} from './emoji.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;
+ }
+ }
+ 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);
+ }
+
+ content = document.getElementById('content');
+ if (content !== null) {
+ emojiTribute.attach(document.getElementById('content'));
+ }
+}
diff --git a/web_src/js/index.js b/web_src/js/index.js
index 9e699c1a2e..992295addf 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -1,4 +1,4 @@
-/* globals wipPrefixes, issuesTribute, emojiTribute */
+/* globals wipPrefixes */
/* exported timeAddManual, toggleStopwatch, cancelStopwatch */
/* exported toggleDeadlineForm, setDeadline, updateDeadline, deleteDependencyModal, cancelCodeComment, onOAuthLoginClick */
@@ -15,6 +15,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 createDropzone from './features/dropzone.js';
import highlight from './features/highlight.js';
import ActivityTopAuthors from './components/ActivityTopAuthors.vue';
@@ -47,7 +48,6 @@ function initCommentPreviewTab($form) {
}, (data) => {
const $previewPanel = $form.find(`.tab.segment[data-tab="${$tabMenu.data('preview')}"]`);
$previewPanel.html(data);
- emojify.run($previewPanel[0]);
$('pre code', $previewPanel[0]).each(function () {
highlight(this);
});
@@ -79,7 +79,6 @@ function initEditPreviewTab($form) {
}, (data) => {
const $previewPanel = $form.find(`.tab.segment[data-tab="${$tabMenu.data('preview')}"]`);
$previewPanel.html(data);
- emojify.run($previewPanel[0]);
$('pre code', $previewPanel[0]).each(function () {
highlight(this);
});
@@ -100,7 +99,6 @@ function initEditDiffTab($form) {
}, (data) => {
const $diffPreviewPanel = $form.find(`.tab.segment[data-tab="${$tabMenu.data('diff')}"]`);
$diffPreviewPanel.html(data);
- emojify.run($diffPreviewPanel[0]);
});
});
}
@@ -256,10 +254,6 @@ function initReactionSelector(parent) {
react.appendTo(content);
}
react.html(resp.html);
- const hasEmoji = react.find('.has-emoji');
- for (let i = 0; i < hasEmoji.length; i++) {
- emojify.run(hasEmoji.get(i));
- }
react.find('.dropdown').dropdown();
initReactionSelector(react);
}
@@ -1006,7 +1000,6 @@ async function initRepository() {
$renderContent.html($('#no-content').html());
} else {
$renderContent.html(data.content);
- emojify.run($renderContent[0]);
$('pre code', $renderContent[0]).each(function () {
highlight(this);
});
@@ -1333,7 +1326,6 @@ function initWikiForm() {
text: plainText
}, (data) => {
preview.innerHTML = `<div class="markdown ui segment">${data}</div>`;
- emojify.run($('.editor-preview')[0]);
$(preview).find('pre code').each((_, e) => {
highlight(e);
});
@@ -1505,7 +1497,6 @@ function setSimpleMDE($editArea) {
text: plainText
}, (data) => {
preview.innerHTML = `<div class="markdown ui segment">${data}</div>`;
- emojify.run($('.editor-preview')[0]);
});
}, 0);
@@ -2474,21 +2465,6 @@ $(document).ready(async () => {
});
}
- // Emojify
- emojify.setConfig({
- img_dir: `${AppSubUrl}/vendor/plugins/emojify/images`,
- ignore_emoticons: true
- });
- const hasEmoji = document.getElementsByClassName('has-emoji');
- for (let i = 0; i < hasEmoji.length; i++) {
- emojify.run(hasEmoji[i]);
- for (let j = 0; j < hasEmoji[i].childNodes.length; j++) {
- if (hasEmoji[i].childNodes[j].nodeName === 'A') {
- emojify.run(hasEmoji[i].childNodes[j]);
- }
- }
- }
-
// Helpers.
$('.delete-button').on('click', showDeletePopup);
$('.add-all-button').on('click', showAddAllPopup);
@@ -2614,6 +2590,7 @@ $(document).ready(async () => {
initContextPopups();
initNotificationsTable();
initNotificationCount();
+ initTribute();
// Repo clone url.
if ($('#repo-clone-url').length > 0) {
diff --git a/web_src/less/_base.less b/web_src/less/_base.less
index ea0b8c5566..d2b1b6e66b 100644
--- a/web_src/less/_base.less
+++ b/web_src/less/_base.less
@@ -66,7 +66,15 @@
font-weight: 700;
}
-@default-fonts: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, Helvetica, Arial;
+@font-face {
+ font-family: 'Noto Color Emoji';
+ src:
+ local('Noto Color Emoji'),
+ local('Noto-Color-Emoji'),
+ url('../vendor/assets/noto-color-emoji/NotoColorEmoji.ttf') format('truetype');
+}
+
+@default-fonts: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
@monospaced-fonts: 'SF Mono', Consolas, Menlo, 'Liberation Mono', Monaco, 'Lucida Console';
.override-fonts(@fonts) {
@@ -1237,3 +1245,29 @@ i.icon.centerlock {
.text-label .color-icon {
position: static !important;
}
+
+.emoji,
+.reaction {
+ font-size: 1.5em;
+ line-height: 1.2;
+ font-weight: 400;
+ vertical-align: middle;
+ font-style: normal;
+}
+
+#issue-title > .emoji {
+ font-size: 1em;
+}
+
+.commit-summary > .emoji {
+ font-size: 1em;
+}
+
+.emoji img,
+.reaction img {
+ border-width: 0 !important;
+ margin: 0 !important;
+ width: 1em !important;
+ height: 1em !important;
+ vertical-align: middle !important;
+}
diff --git a/web_src/less/_dashboard.less b/web_src/less/_dashboard.less
index 9cfbb6db95..1a578d3fb0 100644
--- a/web_src/less/_dashboard.less
+++ b/web_src/less/_dashboard.less
@@ -79,6 +79,9 @@
&.feeds {
.news {
+
+ line-height: 1.2;
+
> .ui.grid {
margin-left: auto;
margin-right: auto;
@@ -97,6 +100,7 @@
}
.push.news .content ul {
+ line-height: initial;
font-size: 13px;
list-style: none;
padding-left: 10px;
diff --git a/web_src/less/_emojify.less b/web_src/less/_emojify.less
deleted file mode 100644
index 4cd9da3f21..0000000000
--- a/web_src/less/_emojify.less
+++ /dev/null
@@ -1,10 +0,0 @@
-.emoji {
- width: 1.5em;
- height: 1.5em;
- display: inline-block;
- background-size: contain;
-}
-
-.ui.label .emoji {
- height: 1.2em !important;
-}
diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less
index 979d2ab45b..863f2bad8e 100644
--- a/web_src/less/_repository.less
+++ b/web_src/less/_repository.less
@@ -2175,6 +2175,7 @@
&.dropdown .menu {
right: 0 !important;
left: auto !important;
+ min-width: 15em;
> .header {
margin: .75rem 0 .5rem;
@@ -2183,6 +2184,7 @@
> .item {
float: left;
padding: .5rem .5rem !important;
+ font-size: 1.5em;
img.emoji {
margin-right: 0;
@@ -2196,24 +2198,20 @@
display: flex;
.ui.label {
- padding: .4em;
- padding-right: 1em;
- padding-left: 1em;
+ max-height: 40px;
+ padding: 9px 15px 7px;
border: 0;
border-right: 1px solid;
border-radius: 0;
margin: 0;
font-size: 14px;
+ font-weight: 100;
border-color: inherit !important;
&.disabled {
cursor: default;
opacity: .5;
}
-
- > img {
- height: 1.5em !important;
- }
}
.ui.label.basic.blue {
@@ -2221,6 +2219,10 @@
border-color: inherit !important;
}
+ .reaction-count {
+ margin-left: 4px;
+ }
+
.select-reaction {
float: left;
padding: .4em;
@@ -2229,6 +2231,9 @@
&:not(.active) a {
display: none;
}
+ > svg {
+ vertical-align: middle;
+ }
}
&:hover .select-reaction a {
diff --git a/web_src/less/_tribute.less b/web_src/less/_tribute.less
index 82ae6ee73e..d0baaf51e1 100644
--- a/web_src/less/_tribute.less
+++ b/web_src/less/_tribute.less
@@ -30,3 +30,12 @@
color: #ffffff;
}
}
+
+.tribute-item {
+ display: flex;
+ align-items: center;
+}
+
+.tribute-item .emoji {
+ margin-right: .5rem;
+}
diff --git a/web_src/less/index.less b/web_src/less/index.less
index 12eb8cf8e5..968ef8dbfa 100644
--- a/web_src/less/index.less
+++ b/web_src/less/index.less
@@ -3,7 +3,6 @@
@import "_svg";
@import "_tribute";
-@import "_emojify";
@import "_base";
@import "_markdown";
@import "_home";