Skip to content

Commit d91fe78

Browse files
committed
Replace tribute with text-expander-element for textarea
1 parent 93eb914 commit d91fe78

File tree

5 files changed

+96
-4
lines changed

5 files changed

+96
-4
lines changed

package-lock.json

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@citation-js/plugin-software-formats": "0.6.1",
1414
"@claviska/jquery-minicolors": "2.3.6",
1515
"@github/markdown-toolbar-element": "2.1.1",
16+
"@github/text-expander-element": "2.3.0",
1617
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
1718
"@primer/octicons": "18.3.0",
1819
"@vue/compiler-sfc": "3.2.47",

templates/shared/combomarkdowneditor.tmpl

+3-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ Template Attributes:
3939
<span class="markdown-toolbar-button markdown-switch-easymde">{{svg "octicon-arrow-switch"}}</span>
4040
</div>
4141
</markdown-toolbar>
42-
<textarea class="markdown-text-editor js-quick-submit" name="{{.TextareaName}}" placeholder="{{.TextareaPlaceholder}}">{{.TextareaContent}}</textarea>
42+
<text-expander keys=": @">
43+
<textarea class="markdown-text-editor js-quick-submit" name="{{.TextareaName}}" placeholder="{{.TextareaPlaceholder}}">{{.TextareaContent}}</textarea>
44+
</text-expander>
4345
</div>
4446
<div class="ui tab markup" data-tab-panel="markdown-previewer">
4547
{{.locale.Tr "loading"}}

web_src/css/editor-markdown.css

+41
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,44 @@
3030
.combo-markdown-editor .CodeMirror-scroll {
3131
max-height: calc(100vh - 200px);
3232
}
33+
34+
text-expander {
35+
display: block;
36+
position: relative;
37+
}
38+
39+
text-expander .suggestions {
40+
position: absolute;
41+
min-width: 180px;
42+
padding: 0;
43+
margin-top: 24px;
44+
list-style: none;
45+
background: var(--color-box-body);
46+
border-radius: var(--border-radius);
47+
border: 1px solid var(--color-secondary);
48+
box-shadow: 0 .5rem 1rem var(--color-shadow);
49+
}
50+
51+
text-expander .suggestions li {
52+
display: block;
53+
cursor: pointer;
54+
padding: 4px 8px;
55+
font-weight: 500;
56+
}
57+
58+
text-expander .suggestions li + li {
59+
border-top: 1px solid var(--color-secondary);
60+
}
61+
62+
text-expander .suggestions li:first-child {
63+
border-radius: var(--border-radius) var(--border-radius) 0 0;
64+
}
65+
66+
text-expander .suggestions li:last-child {
67+
border-radius: 0 0 var(--border-radius) var(--border-radius);
68+
}
69+
70+
text-expander li[aria-selected="true"] {
71+
background: var(--color-primary);
72+
color: var(--color-primary-contrast);
73+
}

web_src/js/features/comp/ComboMarkdownEditor.js

+37-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import '@github/markdown-toolbar-element';
2+
import '@github/text-expander-element';
23
import $ from 'jquery';
34
import {attachTribute} from '../tribute.js';
45
import {hideElem, showElem, autosize} from '../../utils/dom.js';
56
import {initEasyMDEImagePaste, initTextareaImagePaste} from './ImagePaste.js';
67
import {initMarkupContent} from '../../markup/content.js';
78
import {handleGlobalEnterQuickSubmit} from './QuickSubmit.js';
89
import {attachRefIssueContextPopup} from '../contextpopup.js';
10+
import {emojiKeys, emojiString} from '../emoji.js';
911

1012
let elementIdCounter = 0;
1113

@@ -43,11 +45,9 @@ class ComboMarkdownEditor {
4345

4446
this.setupTab();
4547
this.setupDropzone();
46-
48+
this.setupExpander();
4749
this.setupTextarea();
4850

49-
await attachTribute(this.textarea, {mentions: true, emoji: true});
50-
5151
if (this.userPreferredEditor === 'easymde') {
5252
await this.switchToEasyMDE();
5353
}
@@ -83,6 +83,40 @@ class ComboMarkdownEditor {
8383
}
8484
}
8585

86+
setupExpander() {
87+
const expander = this.container.querySelector('text-expander');
88+
expander?.addEventListener('text-expander-change', ({detail: {key, provide, text}}) => {
89+
if (key === ':') {
90+
const ul = document.createElement('ul');
91+
ul.classList.add('suggestions');
92+
93+
const matches = [];
94+
for (const name of emojiKeys) {
95+
if (name.includes(text)) {
96+
matches.push(name);
97+
if (matches.length > 5) break;
98+
}
99+
}
100+
101+
for (const name of matches) {
102+
const emoji = emojiString(name);
103+
const li = document.createElement('li');
104+
li.setAttribute('role', 'option');
105+
li.setAttribute('data-value', emoji);
106+
li.textContent = `${emoji} :${name}:`;
107+
ul.append(li);
108+
}
109+
110+
provide(Promise.resolve({matched: true, fragment: ul}));
111+
}
112+
});
113+
expander?.addEventListener('text-expander-value', ({detail}) => {
114+
if (detail?.key === ':' && detail?.item) {
115+
detail.value = detail.item.getAttribute('data-value');
116+
}
117+
});
118+
}
119+
86120
setupDropzone() {
87121
const dropzoneParentContainer = this.container.getAttribute('data-dropzone-parent-container');
88122
if (dropzoneParentContainer) {

0 commit comments

Comments
 (0)