1
0
Fork 0
forked from forgejo/forgejo

Introduce GitHub markdown editor, keep EasyMDE as fallback (#23876)

The first step of the plan

* #23290

Thanks to @silverwind for the first try in #15394 . Close #10729 and a
lot of related issues.

The EasyMDE is not removed, now it works as a fallback, users can switch
between these two editors.

Editor list:

* Issue / PR comment
* Issue / PR comment edit
* Issue / PR comment quote reply
* PR diff view, inline comment
* PR diff view, inline comment edit
* PR diff view, inline comment quote reply
* Release editor
* Wiki editor

Some editors have attached dropzone

Screenshots:

<details>


![image](https://user-images.githubusercontent.com/2114189/229363558-7e44dcd4-fb6d-48a0-92f8-bd12f57bb0a0.png)


![image](https://user-images.githubusercontent.com/2114189/229363566-781489c8-5306-4347-9714-d71af5d5b0b1.png)


![image](https://user-images.githubusercontent.com/2114189/229363771-1717bf5c-0f2a-4fc2-ba84-4f5b2a343a11.png)


![image](https://user-images.githubusercontent.com/2114189/229363793-ad362d0f-a045-47bd-8f9d-05a9a842bb39.png)

</details>

---------

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
wxiaoguang 2023-04-03 18:06:57 +08:00 committed by GitHub
parent d67e40684f
commit 5cc0801de9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 763 additions and 833 deletions

View file

@ -1,11 +1,10 @@
import {emojiKeys, emojiHTML, emojiString} from './emoji.js';
import {uniq} from '../utils.js';
import {htmlEscape} from 'escape-goat';
function makeCollections({mentions, emoji}) {
const collections = [];
if (mentions) {
if (emoji) {
collections.push({
trigger: ':',
requireLeadingSpace: true,
@ -30,14 +29,14 @@ function makeCollections({mentions, emoji}) {
});
}
if (emoji) {
if (mentions) {
collections.push({
values: window.config.tributeValues,
requireLeadingSpace: true,
menuItemTemplate: (item) => {
return `
<div class="tribute-item">
<img src="${htmlEscape(item.original.avatar)}"/>
<img src="${htmlEscape(item.original.avatar)}" class="gt-mr-3"/>
<span class="name">${htmlEscape(item.original.name)}</span>
${item.original.fullname && item.original.fullname !== '' ? `<span class="fullname">${htmlEscape(item.original.fullname)}</span>` : ''}
</div>
@ -49,30 +48,10 @@ function makeCollections({mentions, emoji}) {
return collections;
}
export async function attachTribute(elementOrNodeList, {mentions, emoji} = {}) {
if (!window.config.requireTribute || !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;
export async function attachTribute(element, {mentions, emoji} = {}) {
const {default: Tribute} = await import(/* webpackChunkName: "tribute" */'tributejs');
const collections = makeCollections({
mentions: mentions || mentionNodes.length > 0,
emoji: emoji || emojiNodes.length > 0,
});
const collections = makeCollections({mentions, emoji});
const tribute = new Tribute({collection: collections, noMatchTemplate: ''});
for (const node of uniqueNodes) {
tribute.attach(node);
}
tribute.attach(element);
return tribute;
}