diff options
Diffstat (limited to 'web_src/js/features')
-rw-r--r-- | web_src/js/features/common-form.ts | 8 | ||||
-rw-r--r-- | web_src/js/features/comp/ComboMarkdownEditor.ts | 58 | ||||
-rw-r--r-- | web_src/js/features/repo-editor.ts | 8 | ||||
-rw-r--r-- | web_src/js/features/repo-issue.ts | 5 | ||||
-rw-r--r-- | web_src/js/features/repo-release.ts | 10 | ||||
-rw-r--r-- | web_src/js/features/repo-wiki.ts | 7 |
6 files changed, 48 insertions, 48 deletions
diff --git a/web_src/js/features/common-form.ts b/web_src/js/features/common-form.ts index 1aca93169d..86323e352e 100644 --- a/web_src/js/features/common-form.ts +++ b/web_src/js/features/common-form.ts @@ -1,5 +1,7 @@ import {applyAreYouSure, initAreYouSure} from '../vendor/jquery.are-you-sure.ts'; import {handleGlobalEnterQuickSubmit} from './comp/QuickSubmit.ts'; +import {queryElems} from '../utils/dom.ts'; +import {initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts'; export function initGlobalFormDirtyLeaveConfirm() { initAreYouSure(window.jQuery); @@ -11,7 +13,7 @@ export function initGlobalFormDirtyLeaveConfirm() { } export function initGlobalEnterQuickSubmit() { - document.addEventListener('keydown', (e) => { + document.addEventListener('keydown', (e: KeyboardEvent & {target: HTMLElement}) => { if (e.key !== 'Enter') return; const hasCtrlOrMeta = ((e.ctrlKey || e.metaKey) && !e.altKey); if (hasCtrlOrMeta && e.target.matches('textarea')) { @@ -27,3 +29,7 @@ export function initGlobalEnterQuickSubmit() { } }); } + +export function initGlobalComboMarkdownEditor() { + queryElems<HTMLElement>(document, '.combo-markdown-editor:not(.custom-init)', (el) => initComboMarkdownEditor(el)); +} diff --git a/web_src/js/features/comp/ComboMarkdownEditor.ts b/web_src/js/features/comp/ComboMarkdownEditor.ts index 7117952fa3..80eabaa37a 100644 --- a/web_src/js/features/comp/ComboMarkdownEditor.ts +++ b/web_src/js/features/comp/ComboMarkdownEditor.ts @@ -1,6 +1,5 @@ import '@github/markdown-toolbar-element'; import '@github/text-expander-element'; -import $ from 'jquery'; import {attachTribute} from '../tribute.ts'; import {hideElem, showElem, autosize, isElemVisible} from '../../utils/dom.ts'; import { @@ -23,6 +22,8 @@ import { } from './EditorMarkdown.ts'; import {DropzoneCustomEventReloadFiles, initDropzone} from '../dropzone.ts'; import {createTippy} from '../../modules/tippy.ts'; +import {fomanticQuery} from '../../modules/fomantic/base.ts'; +import type EasyMDE from 'easymde'; let elementIdCounter = 0; @@ -48,18 +49,23 @@ export function validateTextareaNonEmpty(textarea) { return true; } +type ComboMarkdownEditorOptions = { + editorHeights?: {minHeight?: string, height?: string, maxHeight?: string}, + easyMDEOptions?: EasyMDE.Options, +}; + export class ComboMarkdownEditor { static EventEditorContentChanged = EventEditorContentChanged; static EventUploadStateChanged = EventUploadStateChanged; public container : HTMLElement; - // TODO: use correct types to replace these "any" types - options: any; + options: ComboMarkdownEditorOptions; tabEditor: HTMLElement; tabPreviewer: HTMLElement; + supportEasyMDE: boolean; easyMDE: any; easyMDEToolbarActions: any; easyMDEToolbarDefault: any; @@ -71,11 +77,12 @@ export class ComboMarkdownEditor { dropzone: HTMLElement; attachedDropzoneInst: any; + previewMode: string; previewUrl: string; previewContext: string; - previewMode: string; - constructor(container, options = {}) { + constructor(container, options:ComboMarkdownEditorOptions = {}) { + if (container._giteaComboMarkdownEditor) throw new Error('ComboMarkdownEditor already initialized'); container._giteaComboMarkdownEditor = this; this.options = options; this.container = container; @@ -99,6 +106,10 @@ export class ComboMarkdownEditor { } setupContainer() { + this.supportEasyMDE = this.container.getAttribute('data-support-easy-mde') === 'true'; + this.previewMode = this.container.getAttribute('data-content-mode'); + this.previewUrl = this.container.getAttribute('data-preview-url'); + this.previewContext = this.container.getAttribute('data-preview-context'); initTextExpander(this.container.querySelector('text-expander')); } @@ -137,12 +148,14 @@ export class ComboMarkdownEditor { monospaceButton.setAttribute('aria-checked', String(enabled)); }); - const easymdeButton = this.container.querySelector('.markdown-switch-easymde'); - easymdeButton.addEventListener('click', async (e) => { - e.preventDefault(); - this.userPreferredEditor = 'easymde'; - await this.switchToEasyMDE(); - }); + if (this.supportEasyMDE) { + const easymdeButton = this.container.querySelector('.markdown-switch-easymde'); + easymdeButton.addEventListener('click', async (e) => { + e.preventDefault(); + this.userPreferredEditor = 'easymde'; + await this.switchToEasyMDE(); + }); + } this.initMarkdownButtonTableAdd(); @@ -187,6 +200,7 @@ export class ComboMarkdownEditor { setupTab() { const tabs = this.container.querySelectorAll<HTMLElement>('.tabular.menu > .item'); + if (!tabs.length) return; // Fomantic Tab requires the "data-tab" to be globally unique. // So here it uses our defined "data-tab-for" and "data-tab-panel" to generate the "data-tab" attribute for Fomantic. @@ -207,11 +221,8 @@ export class ComboMarkdownEditor { }); }); - $(tabs).tab(); + fomanticQuery(tabs).tab(); - this.previewUrl = this.tabPreviewer.getAttribute('data-preview-url'); - this.previewContext = this.tabPreviewer.getAttribute('data-preview-context'); - this.previewMode = this.options.previewMode ?? 'comment'; this.tabPreviewer.addEventListener('click', async () => { const formData = new FormData(); formData.append('mode', this.previewMode); @@ -219,7 +230,7 @@ export class ComboMarkdownEditor { formData.append('text', this.value()); const response = await POST(this.previewUrl, {data: formData}); const data = await response.text(); - renderPreviewPanelContent($(panelPreviewer), data); + renderPreviewPanelContent(panelPreviewer, data); }); } @@ -284,7 +295,7 @@ export class ComboMarkdownEditor { } async switchToUserPreference() { - if (this.userPreferredEditor === 'easymde') { + if (this.userPreferredEditor === 'easymde' && this.supportEasyMDE) { await this.switchToEasyMDE(); } else { this.switchToTextarea(); @@ -304,7 +315,7 @@ export class ComboMarkdownEditor { if (this.easyMDE) return; // EasyMDE's CSS should be loaded via webpack config, otherwise our own styles can not overwrite the default styles. const {default: EasyMDE} = await import(/* webpackChunkName: "easymde" */'easymde'); - const easyMDEOpt = { + const easyMDEOpt: EasyMDE.Options = { autoDownloadFontAwesome: false, element: this.textarea, forceSync: true, @@ -384,19 +395,20 @@ export class ComboMarkdownEditor { } get userPreferredEditor() { - return window.localStorage.getItem(`markdown-editor-${this.options.useScene ?? 'default'}`); + return window.localStorage.getItem(`markdown-editor-${this.previewMode ?? 'default'}`); } set userPreferredEditor(s) { - window.localStorage.setItem(`markdown-editor-${this.options.useScene ?? 'default'}`, s); + window.localStorage.setItem(`markdown-editor-${this.previewMode ?? 'default'}`, s); } } export function getComboMarkdownEditor(el) { - if (el instanceof $) el = el[0]; - return el?._giteaComboMarkdownEditor; + if (!el) return null; + if (el.length) el = el[0]; + return el._giteaComboMarkdownEditor; } -export async function initComboMarkdownEditor(container: HTMLElement, options = {}) { +export async function initComboMarkdownEditor(container: HTMLElement, options:ComboMarkdownEditorOptions = {}) { if (!container) { throw new Error('initComboMarkdownEditor: container is null'); } diff --git a/web_src/js/features/repo-editor.ts b/web_src/js/features/repo-editor.ts index 6ea9347eba..adae55f25c 100644 --- a/web_src/js/features/repo-editor.ts +++ b/web_src/js/features/repo-editor.ts @@ -201,10 +201,8 @@ export function initRepoEditor() { })(); } -export function renderPreviewPanelContent($previewPanel, data) { - $previewPanel.html(data); +export function renderPreviewPanelContent(previewPanel: Element, content: string) { + previewPanel.innerHTML = content; initMarkupContent(); - - const $refIssues = $previewPanel.find('p .ref-issue'); - attachRefIssueContextPopup($refIssues); + attachRefIssueContextPopup(previewPanel.querySelectorAll('p .ref-issue')); } diff --git a/web_src/js/features/repo-issue.ts b/web_src/js/features/repo-issue.ts index 9cc478712b..a59e4319ab 100644 --- a/web_src/js/features/repo-issue.ts +++ b/web_src/js/features/repo-issue.ts @@ -414,11 +414,6 @@ export function initRepoPullRequestReview() { await handleReply(this); }); - const elReviewBox = document.querySelector('.review-box-panel'); - if (elReviewBox) { - initComboMarkdownEditor(elReviewBox.querySelector('.combo-markdown-editor')); - } - // The following part is only for diff views if (!$('.repository.pull.diff').length) return; diff --git a/web_src/js/features/repo-release.ts b/web_src/js/features/repo-release.ts index 7589c77136..c59ab1f323 100644 --- a/web_src/js/features/repo-release.ts +++ b/web_src/js/features/repo-release.ts @@ -1,5 +1,4 @@ import {hideElem, showElem} from '../utils/dom.ts'; -import {initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts'; export function initRepoRelease() { document.addEventListener('click', (e) => { @@ -16,7 +15,6 @@ export function initRepoReleaseNew() { if (!document.querySelector('.repository.new.release')) return; initTagNameEditor(); - initRepoReleaseEditor(); } function initTagNameEditor() { @@ -48,11 +46,3 @@ function initTagNameEditor() { hideTargetInput(e.target); }); } - -function initRepoReleaseEditor() { - const editor = document.querySelector<HTMLElement>('.repository.new.release .combo-markdown-editor'); - if (!editor) { - return; - } - initComboMarkdownEditor(editor); -} diff --git a/web_src/js/features/repo-wiki.ts b/web_src/js/features/repo-wiki.ts index 0e72b87109..69188d6ae2 100644 --- a/web_src/js/features/repo-wiki.ts +++ b/web_src/js/features/repo-wiki.ts @@ -2,6 +2,7 @@ import {initMarkupContent} from '../markup/content.ts'; import {validateTextareaNonEmpty, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts'; import {fomanticMobileScreen} from '../modules/fomantic.ts'; import {POST} from '../modules/fetch.ts'; +import type {ComboMarkdownEditor} from './comp/ComboMarkdownEditor.ts'; async function initRepoWikiFormEditor() { const editArea = document.querySelector<HTMLTextAreaElement>('.repository.wiki .combo-markdown-editor textarea'); @@ -9,7 +10,7 @@ async function initRepoWikiFormEditor() { const form = document.querySelector('.repository.wiki.new .ui.form'); const editorContainer = form.querySelector<HTMLElement>('.combo-markdown-editor'); - let editor; + let editor: ComboMarkdownEditor; let renderRequesting = false; let lastContent; @@ -45,12 +46,10 @@ async function initRepoWikiFormEditor() { renderEasyMDEPreview(); editor = await initComboMarkdownEditor(editorContainer, { - useScene: 'wiki', // EasyMDE has some problems of height definition, it has inline style height 300px by default, so we also use inline styles to override it. // And another benefit is that we only need to write the style once for both editors. // TODO: Move height style to CSS after EasyMDE removal. editorHeights: {minHeight: '300px', height: 'calc(100vh - 600px)'}, - previewMode: 'wiki', easyMDEOptions: { previewRender: (_content, previewTarget) => previewTarget.innerHTML, // disable builtin preview render toolbar: ['bold', 'italic', 'strikethrough', '|', @@ -59,7 +58,7 @@ async function initRepoWikiFormEditor() { 'unordered-list', 'ordered-list', '|', 'link', 'image', 'table', 'horizontal-rule', '|', 'preview', 'fullscreen', 'side-by-side', '|', 'gitea-switch-to-textarea', - ], + ] as any, // to use custom toolbar buttons }, }); |