diff --git a/web_src/js/features/comp/ComboMarkdownEditor.js b/web_src/js/features/comp/ComboMarkdownEditor.js index 42c10e664eaa6..90d1bcde5ab62 100644 --- a/web_src/js/features/comp/ComboMarkdownEditor.js +++ b/web_src/js/features/comp/ComboMarkdownEditor.js @@ -8,7 +8,7 @@ import {handleGlobalEnterQuickSubmit} from './QuickSubmit.js'; import {emojiString} from '../emoji.js'; import {renderPreviewPanelContent} from '../repo-editor.js'; import {matchEmoji, matchMention} from '../../utils/match.js'; -import {svg} from '../../svg.js'; +import {easyMDEToolbarActions} from './EasyMDEToolbarActions.js'; let elementIdCounter = 0; @@ -206,66 +206,20 @@ class ComboMarkdownEditor { prepareEasyMDEToolbarActions() { this.easyMDEToolbarDefault = [ - 'bold', 'italic', 'strikethrough', '|', 'heading-1', 'heading-2', 'heading-3', 'heading-bigger', 'heading-smaller', '|', - 'code', 'quote', '|', 'gitea-checkbox-empty', 'gitea-checkbox-checked', '|', - 'unordered-list', 'ordered-list', '|', 'link', 'image', 'table', 'horizontal-rule', '|', 'clean-block', '|', - 'gitea-switch-to-textarea', + 'bold', 'italic', 'strikethrough', '|', 'heading-1', 'heading-2', 'heading-3', + 'heading-bigger', 'heading-smaller', '|', 'code', 'quote', '|', 'gitea-checkbox-empty', + 'gitea-checkbox-checked', '|', 'unordered-list', 'ordered-list', '|', 'link', 'image', + '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 = []; for (const action of actions) { - if (action.startsWith('gitea-')) { - const giteaAction = this.easyMDEToolbarActions[action]; - if (!giteaAction) throw new Error(`Unknown EasyMDE toolbar action ${action}`); - processed.push(giteaAction); - } else { - processed.push(action); - } + const actionButton = this.easyMDEToolbarActions[action]; + if (!actionButton) throw new Error(`Unknown EasyMDE toolbar action ${action}`); + processed.push(actionButton); } return processed; } @@ -293,7 +247,7 @@ class ComboMarkdownEditor { nativeSpellcheck: true, ...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.codemirror.on('change', (...args) => {this.options?.onContentChanged?.(this, ...args)}); diff --git a/web_src/js/features/comp/EasyMDEToolbarActions.js b/web_src/js/features/comp/EasyMDEToolbarActions.js new file mode 100644 index 0000000000000..8286d5d871b53 --- /dev/null +++ b/web_src/js/features/comp/EasyMDEToolbarActions.js @@ -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; +} diff --git a/web_src/js/features/repo-wiki.js b/web_src/js/features/repo-wiki.js index 09202a303ce86..c37da45994f62 100644 --- a/web_src/js/features/repo-wiki.js +++ b/web_src/js/features/repo-wiki.js @@ -58,7 +58,7 @@ async function initRepoWikiFormEditor() { 'gitea-code-inline', 'code', 'quote', '|', 'gitea-checkbox-empty', 'gitea-checkbox-checked', '|', 'unordered-list', 'ordered-list', '|', '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' ], }, }); diff --git a/web_src/js/svg.js b/web_src/js/svg.js index 024b1fbc16c23..0894bbb169c25 100644 --- a/web_src/js/svg.js +++ b/web_src/js/svg.js @@ -1,80 +1,106 @@ 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 octiconChevronLeft from '../../public/img/svg/octicon-chevron-left.svg'; import octiconChevronRight from '../../public/img/svg/octicon-chevron-right.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 octiconDiffAdded from '../../public/img/svg/octicon-diff-added.svg'; import octiconDiffModified from '../../public/img/svg/octicon-diff-modified.svg'; import octiconDiffRemoved from '../../public/img/svg/octicon-diff-removed.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 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 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 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 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 octiconMeter from '../../public/img/svg/octicon-meter.svg'; import octiconMilestone from '../../public/img/svg/octicon-milestone.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 octiconPlus from '../../public/img/svg/octicon-plus.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 octiconRepoForked from '../../public/img/svg/octicon-repo-forked.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 octiconSidebarExpand from '../../public/img/svg/octicon-sidebar-expand.svg'; -import octiconTriangleDown from '../../public/img/svg/octicon-triangle-down.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 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 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 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'; +import octiconTriangleDown from '../../public/img/svg/octicon-triangle-down.svg'; +import octiconX from '../../public/img/svg/octicon-x.svg'; +import octiconXCircleFill from '../../public/img/svg/octicon-x-circle-fill.svg'; const svgs = { + 'gitea-double-chevron-left': giteaDoubleChevronLeft, + 'gitea-double-chevron-right': giteaDoubleChevronRight, + 'gitea-empty-checkbox': giteaEmptyCheckbox, 'octicon-archive': octiconArchive, + 'octicon-arrow-switch': octiconArrowSwitch, 'octicon-blocked': octiconBlocked, - 'octicon-checkbox': octiconCheckbox, + 'octicon-bold': octiconBold, 'octicon-check-circle-fill': octiconCheckCircleFill, + 'octicon-checkbox': octiconCheckbox, 'octicon-chevron-down': octiconChevronDown, 'octicon-chevron-left': octiconChevronLeft, 'octicon-chevron-right': octiconChevronRight, 'octicon-clock': octiconClock, + 'octicon-code': octiconCode, + 'octicon-columns': octiconColumns, 'octicon-copy': octiconCopy, 'octicon-diff-added': octiconDiffAdded, 'octicon-diff-modified': octiconDiffModified, 'octicon-diff-removed': octiconDiffRemoved, 'octicon-diff-renamed': octiconDiffRenamed, - 'gitea-double-chevron-left': giteaDoubleChevronLeft, - 'gitea-double-chevron-right': giteaDoubleChevronRight, - 'gitea-empty-checkbox': giteaEmptyCheckbox, + 'octicon-eye': octiconEye, 'octicon-file': octiconFile, 'octicon-file-directory-fill': octiconFileDirectoryFill, 'octicon-filter': octiconFilter, 'octicon-git-branch': octiconGitBranch, 'octicon-git-merge': octiconGitMerge, 'octicon-git-pull-request': octiconGitPullRequest, + 'octicon-heading': octiconHeading, + 'octicon-horizontal-rule': octiconHorizontalRule, + 'octicon-image': octiconImage, 'octicon-issue-closed': octiconIssueClosed, 'octicon-issue-opened': octiconIssueOpened, + 'octicon-italic': octiconItalic, 'octicon-kebab-horizontal': octiconKebabHorizontal, 'octicon-link': octiconLink, + 'octicon-list-ordered': octiconListOrdered, + 'octicon-list-unordered': octiconListUnordered, 'octicon-lock': octiconLock, 'octicon-meter': octiconMeter, 'octicon-milestone': octiconMilestone, @@ -83,16 +109,20 @@ const svgs = { 'octicon-play': octiconPlay, 'octicon-plus': octiconPlus, 'octicon-project': octiconProject, + 'octicon-quote': octiconQuote, 'octicon-repo': octiconRepo, 'octicon-repo-forked': octiconRepoForked, 'octicon-repo-template': octiconRepoTemplate, 'octicon-rss': octiconRss, + 'octicon-screen-full': octiconScreenFull, 'octicon-search': octiconSearch, 'octicon-sidebar-collapse': octiconSidebarCollapse, 'octicon-sidebar-expand': octiconSidebarExpand, 'octicon-skip': octiconSkip, 'octicon-star': octiconStar, + 'octicon-strikethrough': octiconStrikethrough, 'octicon-sync': octiconSync, + 'octicon-table': octiconTable, 'octicon-tag': octiconTag, 'octicon-triangle-down': octiconTriangleDown, 'octicon-x': octiconX,