Upgrade to CodeMirror 6 (#1787)

Upgrade to CodeMirror 6

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2022-02-13 12:14:01 +01:00 committed by GitHub
parent 1a09bfa5f1
commit 6a6f6105b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
103 changed files with 1906 additions and 2615 deletions

View file

@ -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>