mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-30 06:45:47 -04:00
Upgrade to CodeMirror 6 (#1787)
Upgrade to CodeMirror 6 Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
1a09bfa5f1
commit
6a6f6105b9
103 changed files with 1906 additions and 2615 deletions
|
@ -1,89 +1,112 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import type { Editor, EditorChange } from 'codemirror'
|
||||
import React, { useCallback, useRef } from 'react'
|
||||
import React, { useCallback, useMemo, useRef } from 'react'
|
||||
import type { ScrollProps } from '../synced-scroll/scroll-props'
|
||||
import { StatusBar } from './status-bar/status-bar'
|
||||
import { ToolBar } from './tool-bar/tool-bar'
|
||||
import { useApplicationState } from '../../../hooks/common/use-application-state'
|
||||
import { setNoteContent } from '../../../redux/note-details/methods'
|
||||
import { useNoteMarkdownContent } from '../../../hooks/common/use-note-markdown-content'
|
||||
import { useCodeMirrorOptions } from './hooks/use-code-mirror-options'
|
||||
import { useOnEditorPasteCallback } from './hooks/use-on-editor-paste-callback'
|
||||
import { useOnEditorFileDrop } from './hooks/use-on-editor-file-drop'
|
||||
import { useOnEditorScroll } from './hooks/use-on-editor-scroll'
|
||||
import { useApplyScrollState } from './hooks/use-apply-scroll-state'
|
||||
import { MaxLengthWarning } from './max-length-warning/max-length-warning'
|
||||
import { useOnImageUploadFromRenderer } from './hooks/use-on-image-upload-from-renderer'
|
||||
import { ExtendedCodemirror } from './extended-codemirror/extended-codemirror'
|
||||
import type { ReactCodeMirrorRef } from '@uiw/react-codemirror'
|
||||
import ReactCodeMirror from '@uiw/react-codemirror'
|
||||
import { useCursorActivityCallback } from './hooks/use-cursor-activity-callback'
|
||||
import { useApplyScrollState } from './hooks/use-apply-scroll-state'
|
||||
import styles from './extended-codemirror/codemirror.module.scss'
|
||||
import { oneDark } from '@codemirror/theme-one-dark'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Logger } from '../../../utils/logger'
|
||||
import { useCodeMirrorScrollWatchExtension } from './hooks/code-mirror-extensions/use-code-mirror-scroll-watch-extension'
|
||||
import { useCodeMirrorPasteExtension } from './hooks/code-mirror-extensions/use-code-mirror-paste-extension'
|
||||
import { useCodeMirrorFileDropExtension } from './hooks/code-mirror-extensions/use-code-mirror-file-drop-extension'
|
||||
import { markdown, markdownLanguage } from '@codemirror/lang-markdown'
|
||||
import { languages } from '@codemirror/language-data'
|
||||
import { EditorView } from '@codemirror/view'
|
||||
import { autocompletion } from '@codemirror/autocomplete'
|
||||
import { useCodeMirrorFocusReference } from './hooks/use-code-mirror-focus-reference'
|
||||
import { useOffScreenScrollProtection } from './hooks/use-off-screen-scroll-protection'
|
||||
|
||||
const logger = new Logger('EditorPane')
|
||||
|
||||
export const EditorPane: React.FC<ScrollProps> = ({ scrollState, onScroll, onMakeScrollSource }) => {
|
||||
const markdownContent = useNoteMarkdownContent()
|
||||
|
||||
const editor = useRef<Editor>()
|
||||
const ligaturesEnabled = useApplicationState((state) => state.editorConfig.ligatures)
|
||||
const codeMirrorRef = useRef<ReactCodeMirrorRef | null>(null)
|
||||
|
||||
const onPaste = useOnEditorPasteCallback()
|
||||
const onEditorScroll = useOnEditorScroll(onScroll)
|
||||
useApplyScrollState(editor, scrollState)
|
||||
useApplyScrollState(codeMirrorRef, scrollState)
|
||||
|
||||
const onBeforeChange = useCallback((editor: Editor, data: EditorChange, value: string) => {
|
||||
setNoteContent(value)
|
||||
}, [])
|
||||
const editorScrollExtension = useCodeMirrorScrollWatchExtension(onScroll)
|
||||
const editorPasteExtension = useCodeMirrorPasteExtension()
|
||||
const dropExtension = useCodeMirrorFileDropExtension()
|
||||
const [focusExtension, editorFocused] = useCodeMirrorFocusReference()
|
||||
const saveOffFocusScrollStateExtensions = useOffScreenScrollProtection()
|
||||
const cursorActivityExtension = useCursorActivityCallback(editorFocused)
|
||||
|
||||
const onBeforeChange = useCallback(
|
||||
(value: string): void => {
|
||||
if (!editorFocused.current) {
|
||||
logger.debug("Don't post content change because editor isn't focused")
|
||||
} else {
|
||||
setNoteContent(value)
|
||||
}
|
||||
},
|
||||
[editorFocused]
|
||||
)
|
||||
|
||||
const extensions = useMemo(
|
||||
() => [
|
||||
markdown({ base: markdownLanguage, codeLanguages: languages }),
|
||||
...saveOffFocusScrollStateExtensions,
|
||||
focusExtension,
|
||||
EditorView.lineWrapping,
|
||||
editorScrollExtension,
|
||||
editorPasteExtension,
|
||||
dropExtension,
|
||||
autocompletion(),
|
||||
cursorActivityExtension
|
||||
],
|
||||
[
|
||||
cursorActivityExtension,
|
||||
dropExtension,
|
||||
editorPasteExtension,
|
||||
editorScrollExtension,
|
||||
focusExtension,
|
||||
saveOffFocusScrollStateExtensions
|
||||
]
|
||||
)
|
||||
|
||||
useOnImageUploadFromRenderer()
|
||||
|
||||
const onEditorDidMount = useCallback((mountedEditor: Editor) => {
|
||||
editor.current = mountedEditor
|
||||
}, [])
|
||||
|
||||
const onCursorActivity = useCursorActivityCallback()
|
||||
const onDrop = useOnEditorFileDrop()
|
||||
const codeMirrorOptions = useCodeMirrorOptions()
|
||||
|
||||
const editorFocus = useRef<boolean>(false)
|
||||
const onFocus = useCallback(() => {
|
||||
editorFocus.current = true
|
||||
if (editor.current) {
|
||||
onCursorActivity(editor.current)
|
||||
}
|
||||
}, [editor, onCursorActivity])
|
||||
|
||||
const onBlur = useCallback(() => {
|
||||
editorFocus.current = false
|
||||
}, [])
|
||||
|
||||
const cursorActivity = useCallback(
|
||||
(editor: Editor) => {
|
||||
if (editorFocus.current) {
|
||||
onCursorActivity(editor)
|
||||
}
|
||||
},
|
||||
[onCursorActivity]
|
||||
const codeMirrorClassName = useMemo(
|
||||
() => `overflow-hidden ${styles.extendedCodemirror} h-100 ${ligaturesEnabled ? '' : styles['no-ligatures']}`,
|
||||
[ligaturesEnabled]
|
||||
)
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={`d-flex flex-column h-100 position-relative`} onMouseEnter={onMakeScrollSource}>
|
||||
<MaxLengthWarning />
|
||||
<ToolBar />
|
||||
<ExtendedCodemirror
|
||||
className={`overflow-hidden w-100 flex-fill`}
|
||||
<ReactCodeMirror
|
||||
placeholder={t('editor.placeholder')}
|
||||
extensions={extensions}
|
||||
width={'100%'}
|
||||
height={'100%'}
|
||||
maxHeight={'100%'}
|
||||
maxWidth={'100%'}
|
||||
basicSetup={true}
|
||||
className={codeMirrorClassName}
|
||||
theme={oneDark}
|
||||
value={markdownContent}
|
||||
options={codeMirrorOptions}
|
||||
onPaste={onPaste}
|
||||
onDrop={onDrop}
|
||||
onCursorActivity={cursorActivity}
|
||||
editorDidMount={onEditorDidMount}
|
||||
onBeforeChange={onBeforeChange}
|
||||
onScroll={onEditorScroll}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
ligatures={ligaturesEnabled}
|
||||
onChange={onBeforeChange}
|
||||
ref={codeMirrorRef}
|
||||
/>
|
||||
<StatusBar />
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue