|
|
@@ -1,29 +1,28 @@
|
|
|
import {
|
|
|
- forwardRef, useMemo, useRef, useEffect, useState, useCallback,
|
|
|
+ forwardRef, useMemo, useRef, useEffect,
|
|
|
} from 'react';
|
|
|
|
|
|
import { indentUnit } from '@codemirror/language';
|
|
|
-import { Prec, Extension } from '@codemirror/state';
|
|
|
import {
|
|
|
- keymap, type Command, EditorView, highlightActiveLine, highlightActiveLineGutter,
|
|
|
+ EditorView,
|
|
|
} from '@codemirror/view';
|
|
|
import { AcceptedUploadFileType } from '@growi/core';
|
|
|
import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
|
|
|
|
|
|
-import { GlobalCodeMirrorEditorKey } from '../../consts';
|
|
|
+import { EditorSettings, GlobalCodeMirrorEditorKey } from '../../consts';
|
|
|
import {
|
|
|
- useFileDropzone, FileDropzoneOverlay, getEditorTheme, type EditorTheme, getKeymap, type KeyMapMode,
|
|
|
+ useFileDropzone, FileDropzoneOverlay,
|
|
|
} from '../../services';
|
|
|
-import { insertNewlineContinueMarkup } from '../../services/list-util/insert-newline-continue-markup';
|
|
|
import {
|
|
|
adjustPasteData, getStrFromBol,
|
|
|
} from '../../services/paste-util/paste-markdown-util';
|
|
|
-import { insertNewRowToMarkdownTable, isInTable } from '../../services/table-util/insert-new-row-to-table-markdown';
|
|
|
import { useCodeMirrorEditorIsolated } from '../../stores';
|
|
|
|
|
|
import { Toolbar } from './Toolbar';
|
|
|
|
|
|
|
|
|
+import { useEditorSettings } from 'src/stores/use-editor-settings';
|
|
|
+
|
|
|
import style from './CodeMirrorEditor.module.scss';
|
|
|
|
|
|
const CodeMirrorEditorContainer = forwardRef<HTMLDivElement>((props, ref) => {
|
|
|
@@ -34,11 +33,8 @@ const CodeMirrorEditorContainer = forwardRef<HTMLDivElement>((props, ref) => {
|
|
|
|
|
|
export type CodeMirrorEditorProps = {
|
|
|
acceptedUploadFileType?: AcceptedUploadFileType,
|
|
|
- indentSize?: number,
|
|
|
- editorTheme?: EditorTheme,
|
|
|
- editorKeymap?: KeyMapMode,
|
|
|
- styleActiveLine?: boolean,
|
|
|
- autoFormatMarkdownTable?: boolean,
|
|
|
+ indentSize: number,
|
|
|
+ editorSettings?: EditorSettings,
|
|
|
onChange?: (value: string) => void,
|
|
|
onSave?: () => void,
|
|
|
onUpload?: (files: File[]) => void,
|
|
|
@@ -54,10 +50,7 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
|
|
|
editorKey,
|
|
|
acceptedUploadFileType = AcceptedUploadFileType.NONE,
|
|
|
indentSize,
|
|
|
- editorTheme,
|
|
|
- editorKeymap,
|
|
|
- styleActiveLine,
|
|
|
- autoFormatMarkdownTable,
|
|
|
+ editorSettings,
|
|
|
onChange,
|
|
|
onSave,
|
|
|
onUpload,
|
|
|
@@ -73,6 +66,8 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
|
|
|
}, [onChange]);
|
|
|
const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(editorKey, containerRef.current, cmProps);
|
|
|
|
|
|
+ useEditorSettings(codeMirrorEditor, editorSettings, onSave);
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
if (indentSize == null) {
|
|
|
return;
|
|
|
@@ -84,37 +79,6 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
|
|
|
|
|
|
}, [codeMirrorEditor, indentSize]);
|
|
|
|
|
|
- useEffect(() => {
|
|
|
- if (styleActiveLine == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
- const extensions = (styleActiveLine) ? [[highlightActiveLine(), highlightActiveLineGutter()]] : [[]];
|
|
|
-
|
|
|
- const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extensions);
|
|
|
- return cleanupFunction;
|
|
|
-
|
|
|
- }, [codeMirrorEditor, styleActiveLine]);
|
|
|
-
|
|
|
- const onPressEnter: Command = useCallback((editor) => {
|
|
|
- if (isInTable(editor) && autoFormatMarkdownTable) {
|
|
|
- insertNewRowToMarkdownTable(editor);
|
|
|
- return true;
|
|
|
- }
|
|
|
- insertNewlineContinueMarkup(editor);
|
|
|
- return true;
|
|
|
- }, [autoFormatMarkdownTable]);
|
|
|
-
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
-
|
|
|
- const extension = keymap.of([
|
|
|
- { key: 'Enter', run: onPressEnter },
|
|
|
- ]);
|
|
|
-
|
|
|
- const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extension);
|
|
|
- return cleanupFunction;
|
|
|
-
|
|
|
- }, [codeMirrorEditor, onPressEnter]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
const handlePaste = (event: ClipboardEvent) => {
|
|
|
@@ -190,45 +154,6 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
|
|
|
}, [onScroll, codeMirrorEditor]);
|
|
|
|
|
|
|
|
|
- const [themeExtension, setThemeExtension] = useState<Extension | undefined>(undefined);
|
|
|
- useEffect(() => {
|
|
|
- const settingTheme = async(name?: EditorTheme) => {
|
|
|
- setThemeExtension(await getEditorTheme(name ?? 'defaultlight'));
|
|
|
- };
|
|
|
- settingTheme(editorTheme);
|
|
|
- }, [codeMirrorEditor, editorTheme, setThemeExtension]);
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
- if (themeExtension == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
- // React CodeMirror has default theme which is default prec
|
|
|
- // and extension have to be higher prec here than default theme.
|
|
|
- const cleanupFunction = codeMirrorEditor?.appendExtensions(Prec.high(themeExtension));
|
|
|
- return cleanupFunction;
|
|
|
- }, [codeMirrorEditor, themeExtension]);
|
|
|
-
|
|
|
-
|
|
|
- const [keymapExtension, setKeymapExtension] = useState<Extension | undefined>(undefined);
|
|
|
- useEffect(() => {
|
|
|
- const settingKeyMap = async(name?: KeyMapMode) => {
|
|
|
- setKeymapExtension(await getKeymap(name ?? 'default'));
|
|
|
- };
|
|
|
- settingKeyMap(editorKeymap);
|
|
|
-
|
|
|
- }, [codeMirrorEditor, editorKeymap, setKeymapExtension]);
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
- if (keymapExtension == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Prevent these Keybind from overwriting the originally defined keymap.
|
|
|
- const cleanupFunction = codeMirrorEditor?.appendExtensions(Prec.low(keymapExtension));
|
|
|
- return cleanupFunction;
|
|
|
-
|
|
|
- }, [codeMirrorEditor, keymapExtension, onSave]);
|
|
|
-
|
|
|
const {
|
|
|
getRootProps,
|
|
|
getInputProps,
|