Fix EasyMDE toolbar (#24489)

Fixes https://github.com/go-gitea/gitea/issues/24486

The "clean block" button is gone because I could not find a matching
octicon. Order of buttons is roughly equal to textarea.

<img width="824" alt="Screenshot 2023-05-02 at 21 10 00"
src="https://user-images.githubusercontent.com/115237/235762593-ceccb260-e665-4932-ac8a-ef6fe8406a3c.png">

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind 2023-05-03 07:23:39 +02:00 committed by GitHub
parent 3ae997614a
commit a9ed87ce4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 217 additions and 81 deletions

View file

@ -8,7 +8,7 @@ import {handleGlobalEnterQuickSubmit} from './QuickSubmit.js';
import {emojiString} from '../emoji.js'; import {emojiString} from '../emoji.js';
import {renderPreviewPanelContent} from '../repo-editor.js'; import {renderPreviewPanelContent} from '../repo-editor.js';
import {matchEmoji, matchMention} from '../../utils/match.js'; import {matchEmoji, matchMention} from '../../utils/match.js';
import {svg} from '../../svg.js'; import {easyMDEToolbarActions} from './EasyMDEToolbarActions.js';
let elementIdCounter = 0; let elementIdCounter = 0;
@ -206,66 +206,20 @@ class ComboMarkdownEditor {
prepareEasyMDEToolbarActions() { prepareEasyMDEToolbarActions() {
this.easyMDEToolbarDefault = [ this.easyMDEToolbarDefault = [
'bold', 'italic', 'strikethrough', '|', 'heading-1', 'heading-2', 'heading-3', 'heading-bigger', 'heading-smaller', '|', 'bold', 'italic', 'strikethrough', '|', 'heading-1', 'heading-2', 'heading-3',
'code', 'quote', '|', 'gitea-checkbox-empty', 'gitea-checkbox-checked', '|', 'heading-bigger', 'heading-smaller', '|', 'code', 'quote', '|', 'gitea-checkbox-empty',
'unordered-list', 'ordered-list', '|', 'link', 'image', 'table', 'horizontal-rule', '|', 'clean-block', '|', 'gitea-checkbox-checked', '|', 'unordered-list', 'ordered-list', '|', 'link', 'image',
'gitea-switch-to-textarea', 'table', 'horizontal-rule', '|', 'gitea-switch-to-textarea',
]; ];
this.easyMDEToolbarActions = {
'gitea-checkbox-empty': {
action(e) {
const cm = e.codemirror;
cm.replaceSelection(`\n- [ ] ${cm.getSelection()}`);
cm.focus();
},
icon: svg('gitea-empty-checkbox'),
title: 'Add Checkbox (empty)',
},
'gitea-checkbox-checked': {
action(e) {
const cm = e.codemirror;
cm.replaceSelection(`\n- [x] ${cm.getSelection()}`);
cm.focus();
},
icon: svg('octicon-checkbox'),
title: 'Add Checkbox (checked)',
},
'gitea-switch-to-textarea': {
action: () => {
this.userPreferredEditor = 'textarea';
this.switchToTextarea();
},
icon: svg('octicon-file'),
title: 'Revert to simple textarea',
},
'gitea-code-inline': {
action(e) {
const cm = e.codemirror;
const selection = cm.getSelection();
cm.replaceSelection(`\`${selection}\``);
if (!selection) {
const cursorPos = cm.getCursor();
cm.setCursor(cursorPos.line, cursorPos.ch - 1);
}
cm.focus();
},
icon: svg('octicon-chevron-right'),
title: 'Add Inline Code',
}
};
} }
parseEasyMDEToolbar(actions) { parseEasyMDEToolbar(EasyMDE, actions) {
this.easyMDEToolbarActions = this.easyMDEToolbarActions || easyMDEToolbarActions(EasyMDE, this);
const processed = []; const processed = [];
for (const action of actions) { for (const action of actions) {
if (action.startsWith('gitea-')) { const actionButton = this.easyMDEToolbarActions[action];
const giteaAction = this.easyMDEToolbarActions[action]; if (!actionButton) throw new Error(`Unknown EasyMDE toolbar action ${action}`);
if (!giteaAction) throw new Error(`Unknown EasyMDE toolbar action ${action}`); processed.push(actionButton);
processed.push(giteaAction);
} else {
processed.push(action);
}
} }
return processed; return processed;
} }
@ -293,7 +247,7 @@ class ComboMarkdownEditor {
nativeSpellcheck: true, nativeSpellcheck: true,
...this.options.easyMDEOptions, ...this.options.easyMDEOptions,
}; };
easyMDEOpt.toolbar = this.parseEasyMDEToolbar(easyMDEOpt.toolbar ?? this.easyMDEToolbarDefault); easyMDEOpt.toolbar = this.parseEasyMDEToolbar(EasyMDE, easyMDEOpt.toolbar ?? this.easyMDEToolbarDefault);
this.easyMDE = new EasyMDE(easyMDEOpt); this.easyMDE = new EasyMDE(easyMDEOpt);
this.easyMDE.codemirror.on('change', (...args) => {this.options?.onContentChanged?.(this, ...args)}); this.easyMDE.codemirror.on('change', (...args) => {this.options?.onContentChanged?.(this, ...args)});

View file

@ -0,0 +1,152 @@
import {svg} from '../../svg.js';
export function easyMDEToolbarActions(EasyMDE, editor) {
const actions = {
'|': '|',
'heading-1': {
action: EasyMDE.toggleHeading1,
icon: svg('octicon-heading'),
title: 'Heading 1',
},
'heading-2': {
action: EasyMDE.toggleHeading2,
icon: svg('octicon-heading'),
title: 'Heading 2',
},
'heading-3': {
action: EasyMDE.toggleHeading3,
icon: svg('octicon-heading'),
title: 'Heading 3',
},
'heading-smaller': {
action: EasyMDE.toggleHeadingSmaller,
icon: svg('octicon-heading'),
title: 'Decrease Heading',
},
'heading-bigger': {
action: EasyMDE.toggleHeadingBigger,
icon: svg('octicon-heading'),
title: 'Increase Heading',
},
'bold': {
action: EasyMDE.toggleBold,
icon: svg('octicon-bold'),
title: 'Bold',
},
'italic': {
action: EasyMDE.toggleItalic,
icon: svg('octicon-italic'),
title: 'Italic',
},
'strikethrough': {
action: EasyMDE.toggleStrikethrough,
icon: svg('octicon-strikethrough'),
title: 'Strikethrough',
},
'quote': {
action: EasyMDE.toggleBlockquote,
icon: svg('octicon-quote'),
title: 'Quote',
},
'code': {
action: EasyMDE.toggleCodeBlock,
icon: svg('octicon-code'),
title: 'Code',
},
'link': {
action: EasyMDE.drawLink,
icon: svg('octicon-link'),
title: 'Link',
},
'unordered-list': {
action: EasyMDE.toggleUnorderedList,
icon: svg('octicon-list-unordered'),
title: 'Unordered List',
},
'ordered-list': {
action: EasyMDE.toggleOrderedList,
icon: svg('octicon-list-ordered'),
title: 'Ordered List',
},
'image': {
action: EasyMDE.drawImage,
icon: svg('octicon-image'),
title: 'Image',
},
'table': {
action: EasyMDE.drawTable,
icon: svg('octicon-table'),
title: 'Table',
},
'horizontal-rule': {
action: EasyMDE.drawHorizontalRule,
icon: svg('octicon-horizontal-rule'),
title: 'Horizontal Rule',
},
'preview': {
action: EasyMDE.togglePreview,
icon: svg('octicon-eye'),
title: 'Preview',
},
'fullscreen': {
action: EasyMDE.toggleFullScreen,
icon: svg('octicon-screen-full'),
title: 'Fullscreen',
},
'side-by-side': {
action: EasyMDE.toggleSideBySide,
icon: svg('octicon-columns'),
title: 'Side by Side',
},
// gitea's custom actions
'gitea-checkbox-empty': {
action(e) {
const cm = e.codemirror;
cm.replaceSelection(`\n- [ ] ${cm.getSelection()}`);
cm.focus();
},
icon: svg('gitea-empty-checkbox'),
title: 'Add Checkbox (empty)',
},
'gitea-checkbox-checked': {
action(e) {
const cm = e.codemirror;
cm.replaceSelection(`\n- [x] ${cm.getSelection()}`);
cm.focus();
},
icon: svg('octicon-checkbox'),
title: 'Add Checkbox (checked)',
},
'gitea-switch-to-textarea': {
action: () => {
editor.userPreferredEditor = 'textarea';
editor.switchToTextarea();
},
icon: svg('octicon-arrow-switch'),
title: 'Revert to simple textarea',
},
'gitea-code-inline': {
action(e) {
const cm = e.codemirror;
const selection = cm.getSelection();
cm.replaceSelection(`\`${selection}\``);
if (!selection) {
const cursorPos = cm.getCursor();
cm.setCursor(cursorPos.line, cursorPos.ch - 1);
}
cm.focus();
},
icon: svg('octicon-chevron-right'),
title: 'Add Inline Code',
}
};
for (const [key, value] of Object.entries(actions)) {
if (typeof value !== 'string') {
value.name = key;
}
}
return actions;
}

View file

@ -58,7 +58,7 @@ async function initRepoWikiFormEditor() {
'gitea-code-inline', 'code', 'quote', '|', 'gitea-checkbox-empty', 'gitea-checkbox-checked', '|', 'gitea-code-inline', 'code', 'quote', '|', 'gitea-checkbox-empty', 'gitea-checkbox-checked', '|',
'unordered-list', 'ordered-list', '|', 'unordered-list', 'ordered-list', '|',
'link', 'image', 'table', 'horizontal-rule', '|', 'link', 'image', 'table', 'horizontal-rule', '|',
'clean-block', 'preview', 'fullscreen', 'side-by-side', '|', 'gitea-switch-to-textarea' 'preview', 'fullscreen', 'side-by-side', '|', 'gitea-switch-to-textarea'
], ],
}, },
}); });

View file

@ -1,80 +1,106 @@
import {h} from 'vue'; import {h} from 'vue';
import giteaDoubleChevronLeft from '../../public/img/svg/gitea-double-chevron-left.svg';
import giteaDoubleChevronRight from '../../public/img/svg/gitea-double-chevron-right.svg';
import giteaEmptyCheckbox from '../../public/img/svg/gitea-empty-checkbox.svg';
import octiconArchive from '../../public/img/svg/octicon-archive.svg';
import octiconArrowSwitch from '../../public/img/svg/octicon-arrow-switch.svg';
import octiconBlocked from '../../public/img/svg/octicon-blocked.svg';
import octiconBold from '../../public/img/svg/octicon-bold.svg';
import octiconCheckbox from '../../public/img/svg/octicon-checkbox.svg';
import octiconCheckCircleFill from '../../public/img/svg/octicon-check-circle-fill.svg';
import octiconChevronDown from '../../public/img/svg/octicon-chevron-down.svg'; import octiconChevronDown from '../../public/img/svg/octicon-chevron-down.svg';
import octiconChevronLeft from '../../public/img/svg/octicon-chevron-left.svg';
import octiconChevronRight from '../../public/img/svg/octicon-chevron-right.svg'; import octiconChevronRight from '../../public/img/svg/octicon-chevron-right.svg';
import octiconClock from '../../public/img/svg/octicon-clock.svg'; import octiconClock from '../../public/img/svg/octicon-clock.svg';
import octiconCode from '../../public/img/svg/octicon-code.svg';
import octiconColumns from '../../public/img/svg/octicon-columns.svg';
import octiconCopy from '../../public/img/svg/octicon-copy.svg'; import octiconCopy from '../../public/img/svg/octicon-copy.svg';
import octiconDiffAdded from '../../public/img/svg/octicon-diff-added.svg'; import octiconDiffAdded from '../../public/img/svg/octicon-diff-added.svg';
import octiconDiffModified from '../../public/img/svg/octicon-diff-modified.svg'; import octiconDiffModified from '../../public/img/svg/octicon-diff-modified.svg';
import octiconDiffRemoved from '../../public/img/svg/octicon-diff-removed.svg'; import octiconDiffRemoved from '../../public/img/svg/octicon-diff-removed.svg';
import octiconDiffRenamed from '../../public/img/svg/octicon-diff-renamed.svg'; import octiconDiffRenamed from '../../public/img/svg/octicon-diff-renamed.svg';
import octiconEye from '../../public/img/svg/octicon-eye.svg';
import octiconFile from '../../public/img/svg/octicon-file.svg'; import octiconFile from '../../public/img/svg/octicon-file.svg';
import octiconFileDirectoryFill from '../../public/img/svg/octicon-file-directory-fill.svg'; import octiconFileDirectoryFill from '../../public/img/svg/octicon-file-directory-fill.svg';
import octiconFilter from '../../public/img/svg/octicon-filter.svg';
import octiconGitBranch from '../../public/img/svg/octicon-git-branch.svg';
import octiconGitMerge from '../../public/img/svg/octicon-git-merge.svg'; import octiconGitMerge from '../../public/img/svg/octicon-git-merge.svg';
import octiconGitPullRequest from '../../public/img/svg/octicon-git-pull-request.svg'; import octiconGitPullRequest from '../../public/img/svg/octicon-git-pull-request.svg';
import octiconHeading from '../../public/img/svg/octicon-heading.svg';
import octiconHorizontalRule from '../../public/img/svg/octicon-horizontal-rule.svg';
import octiconImage from '../../public/img/svg/octicon-image.svg';
import octiconIssueClosed from '../../public/img/svg/octicon-issue-closed.svg'; import octiconIssueClosed from '../../public/img/svg/octicon-issue-closed.svg';
import octiconIssueOpened from '../../public/img/svg/octicon-issue-opened.svg'; import octiconIssueOpened from '../../public/img/svg/octicon-issue-opened.svg';
import octiconItalic from '../../public/img/svg/octicon-italic.svg';
import octiconKebabHorizontal from '../../public/img/svg/octicon-kebab-horizontal.svg'; import octiconKebabHorizontal from '../../public/img/svg/octicon-kebab-horizontal.svg';
import octiconLink from '../../public/img/svg/octicon-link.svg'; import octiconLink from '../../public/img/svg/octicon-link.svg';
import octiconListOrdered from '../../public/img/svg/octicon-list-ordered.svg';
import octiconListUnordered from '../../public/img/svg/octicon-list-unordered.svg';
import octiconLock from '../../public/img/svg/octicon-lock.svg'; import octiconLock from '../../public/img/svg/octicon-lock.svg';
import octiconMeter from '../../public/img/svg/octicon-meter.svg';
import octiconMilestone from '../../public/img/svg/octicon-milestone.svg'; import octiconMilestone from '../../public/img/svg/octicon-milestone.svg';
import octiconMirror from '../../public/img/svg/octicon-mirror.svg'; import octiconMirror from '../../public/img/svg/octicon-mirror.svg';
import octiconOrganization from '../../public/img/svg/octicon-organization.svg';
import octiconPlay from '../../public/img/svg/octicon-play.svg'; import octiconPlay from '../../public/img/svg/octicon-play.svg';
import octiconPlus from '../../public/img/svg/octicon-plus.svg';
import octiconProject from '../../public/img/svg/octicon-project.svg'; import octiconProject from '../../public/img/svg/octicon-project.svg';
import octiconQuote from '../../public/img/svg/octicon-quote.svg';
import octiconRepo from '../../public/img/svg/octicon-repo.svg'; import octiconRepo from '../../public/img/svg/octicon-repo.svg';
import octiconRepoForked from '../../public/img/svg/octicon-repo-forked.svg'; import octiconRepoForked from '../../public/img/svg/octicon-repo-forked.svg';
import octiconRepoTemplate from '../../public/img/svg/octicon-repo-template.svg'; import octiconRepoTemplate from '../../public/img/svg/octicon-repo-template.svg';
import octiconRss from '../../public/img/svg/octicon-rss.svg';
import octiconScreenFull from '../../public/img/svg/octicon-screen-full.svg';
import octiconSearch from '../../public/img/svg/octicon-search.svg';
import octiconSidebarCollapse from '../../public/img/svg/octicon-sidebar-collapse.svg'; import octiconSidebarCollapse from '../../public/img/svg/octicon-sidebar-collapse.svg';
import octiconSidebarExpand from '../../public/img/svg/octicon-sidebar-expand.svg'; import octiconSidebarExpand from '../../public/img/svg/octicon-sidebar-expand.svg';
import octiconSkip from '../../public/img/svg/octicon-skip.svg';
import octiconStar from '../../public/img/svg/octicon-star.svg';
import octiconStrikethrough from '../../public/img/svg/octicon-strikethrough.svg';
import octiconSync from '../../public/img/svg/octicon-sync.svg';
import octiconTable from '../../public/img/svg/octicon-table.svg';
import octiconTag from '../../public/img/svg/octicon-tag.svg';
import octiconTriangleDown from '../../public/img/svg/octicon-triangle-down.svg'; import octiconTriangleDown from '../../public/img/svg/octicon-triangle-down.svg';
import octiconX from '../../public/img/svg/octicon-x.svg'; import octiconX from '../../public/img/svg/octicon-x.svg';
import octiconCheckCircleFill from '../../public/img/svg/octicon-check-circle-fill.svg';
import octiconXCircleFill from '../../public/img/svg/octicon-x-circle-fill.svg'; import octiconXCircleFill from '../../public/img/svg/octicon-x-circle-fill.svg';
import octiconSkip from '../../public/img/svg/octicon-skip.svg';
import octiconMeter from '../../public/img/svg/octicon-meter.svg';
import octiconBlocked from '../../public/img/svg/octicon-blocked.svg';
import octiconSync from '../../public/img/svg/octicon-sync.svg';
import octiconFilter from '../../public/img/svg/octicon-filter.svg';
import octiconPlus from '../../public/img/svg/octicon-plus.svg';
import octiconSearch from '../../public/img/svg/octicon-search.svg';
import octiconArchive from '../../public/img/svg/octicon-archive.svg';
import octiconStar from '../../public/img/svg/octicon-star.svg';
import giteaDoubleChevronLeft from '../../public/img/svg/gitea-double-chevron-left.svg';
import giteaDoubleChevronRight from '../../public/img/svg/gitea-double-chevron-right.svg';
import octiconChevronLeft from '../../public/img/svg/octicon-chevron-left.svg';
import octiconOrganization from '../../public/img/svg/octicon-organization.svg';
import octiconTag from '../../public/img/svg/octicon-tag.svg';
import octiconGitBranch from '../../public/img/svg/octicon-git-branch.svg';
import octiconRss from '../../public/img/svg/octicon-rss.svg';
import octiconCheckbox from '../../public/img/svg/octicon-checkbox.svg';
import giteaEmptyCheckbox from '../../public/img/svg/gitea-empty-checkbox.svg';
const svgs = { const svgs = {
'gitea-double-chevron-left': giteaDoubleChevronLeft,
'gitea-double-chevron-right': giteaDoubleChevronRight,
'gitea-empty-checkbox': giteaEmptyCheckbox,
'octicon-archive': octiconArchive, 'octicon-archive': octiconArchive,
'octicon-arrow-switch': octiconArrowSwitch,
'octicon-blocked': octiconBlocked, 'octicon-blocked': octiconBlocked,
'octicon-checkbox': octiconCheckbox, 'octicon-bold': octiconBold,
'octicon-check-circle-fill': octiconCheckCircleFill, 'octicon-check-circle-fill': octiconCheckCircleFill,
'octicon-checkbox': octiconCheckbox,
'octicon-chevron-down': octiconChevronDown, 'octicon-chevron-down': octiconChevronDown,
'octicon-chevron-left': octiconChevronLeft, 'octicon-chevron-left': octiconChevronLeft,
'octicon-chevron-right': octiconChevronRight, 'octicon-chevron-right': octiconChevronRight,
'octicon-clock': octiconClock, 'octicon-clock': octiconClock,
'octicon-code': octiconCode,
'octicon-columns': octiconColumns,
'octicon-copy': octiconCopy, 'octicon-copy': octiconCopy,
'octicon-diff-added': octiconDiffAdded, 'octicon-diff-added': octiconDiffAdded,
'octicon-diff-modified': octiconDiffModified, 'octicon-diff-modified': octiconDiffModified,
'octicon-diff-removed': octiconDiffRemoved, 'octicon-diff-removed': octiconDiffRemoved,
'octicon-diff-renamed': octiconDiffRenamed, 'octicon-diff-renamed': octiconDiffRenamed,
'gitea-double-chevron-left': giteaDoubleChevronLeft, 'octicon-eye': octiconEye,
'gitea-double-chevron-right': giteaDoubleChevronRight,
'gitea-empty-checkbox': giteaEmptyCheckbox,
'octicon-file': octiconFile, 'octicon-file': octiconFile,
'octicon-file-directory-fill': octiconFileDirectoryFill, 'octicon-file-directory-fill': octiconFileDirectoryFill,
'octicon-filter': octiconFilter, 'octicon-filter': octiconFilter,
'octicon-git-branch': octiconGitBranch, 'octicon-git-branch': octiconGitBranch,
'octicon-git-merge': octiconGitMerge, 'octicon-git-merge': octiconGitMerge,
'octicon-git-pull-request': octiconGitPullRequest, 'octicon-git-pull-request': octiconGitPullRequest,
'octicon-heading': octiconHeading,
'octicon-horizontal-rule': octiconHorizontalRule,
'octicon-image': octiconImage,
'octicon-issue-closed': octiconIssueClosed, 'octicon-issue-closed': octiconIssueClosed,
'octicon-issue-opened': octiconIssueOpened, 'octicon-issue-opened': octiconIssueOpened,
'octicon-italic': octiconItalic,
'octicon-kebab-horizontal': octiconKebabHorizontal, 'octicon-kebab-horizontal': octiconKebabHorizontal,
'octicon-link': octiconLink, 'octicon-link': octiconLink,
'octicon-list-ordered': octiconListOrdered,
'octicon-list-unordered': octiconListUnordered,
'octicon-lock': octiconLock, 'octicon-lock': octiconLock,
'octicon-meter': octiconMeter, 'octicon-meter': octiconMeter,
'octicon-milestone': octiconMilestone, 'octicon-milestone': octiconMilestone,
@ -83,16 +109,20 @@ const svgs = {
'octicon-play': octiconPlay, 'octicon-play': octiconPlay,
'octicon-plus': octiconPlus, 'octicon-plus': octiconPlus,
'octicon-project': octiconProject, 'octicon-project': octiconProject,
'octicon-quote': octiconQuote,
'octicon-repo': octiconRepo, 'octicon-repo': octiconRepo,
'octicon-repo-forked': octiconRepoForked, 'octicon-repo-forked': octiconRepoForked,
'octicon-repo-template': octiconRepoTemplate, 'octicon-repo-template': octiconRepoTemplate,
'octicon-rss': octiconRss, 'octicon-rss': octiconRss,
'octicon-screen-full': octiconScreenFull,
'octicon-search': octiconSearch, 'octicon-search': octiconSearch,
'octicon-sidebar-collapse': octiconSidebarCollapse, 'octicon-sidebar-collapse': octiconSidebarCollapse,
'octicon-sidebar-expand': octiconSidebarExpand, 'octicon-sidebar-expand': octiconSidebarExpand,
'octicon-skip': octiconSkip, 'octicon-skip': octiconSkip,
'octicon-star': octiconStar, 'octicon-star': octiconStar,
'octicon-strikethrough': octiconStrikethrough,
'octicon-sync': octiconSync, 'octicon-sync': octiconSync,
'octicon-table': octiconTable,
'octicon-tag': octiconTag, 'octicon-tag': octiconTag,
'octicon-triangle-down': octiconTriangleDown, 'octicon-triangle-down': octiconTriangleDown,
'octicon-x': octiconX, 'octicon-x': octiconX,