Просмотр исходного кода

Merge branch 'imprv/137432-make-markdown-list-util' into fix/139350-fix-paste-operation-in-editor

kosei-n 2 лет назад
Родитель
Сommit
c6df2fdb28

+ 7 - 6
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx

@@ -11,7 +11,7 @@ import { GlobalCodeMirrorEditorKey, AcceptedUploadFileType } from '../../consts'
 import { useFileDropzone, FileDropzoneOverlay, AllEditorTheme } from '../../services';
 import {
   getLineToCursor, adjustPasteData,
-  newlineAndIndentContinueMarkdownList,
+  useNewlineAndIndentContinueMarkdownList,
 } from '../../services/list-util/markdown-list-util';
 import { useCodeMirrorEditorIsolated } from '../../stores';
 
@@ -56,17 +56,18 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
   }, [onChange]);
   const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(editorKey, containerRef.current, cmProps);
 
-  useEffect(() => {
-    const editor = codeMirrorEditor?.view;
+  const editor = codeMirrorEditor?.view;
+
+  const newlineAndIndentContinueMarkdownList = useNewlineAndIndentContinueMarkdownList(editor);
 
+  useEffect(() => {
     const handleEnterKey = (event: KeyboardEvent) => {
       if (event.key === 'Enter') {
         event.preventDefault();
-        const editor = codeMirrorEditor?.view;
         if (editor == null) {
           return;
         }
-        newlineAndIndentContinueMarkdownList(editor);
+        newlineAndIndentContinueMarkdownList?.(editor);
       }
     };
 
@@ -75,7 +76,7 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
     return () => {
       editor?.dom.removeEventListener('keydown', handleEnterKey);
     };
-  }, [codeMirrorEditor]);
+  }, [codeMirrorEditor, editor, newlineAndIndentContinueMarkdownList]);
 
   useEffect(() => {
     if (indentSize == null) {

+ 10 - 6
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/insert-text.ts

@@ -1,20 +1,24 @@
 import { useCallback } from 'react';
 
-import { EditorView } from '@codemirror/view';
+import { type EditorView } from '@codemirror/view';
 
-export type InsertText = (text: string) => void;
+export type InsertText = (text: string, from?: number, to?: number) => void;
 
-export const useInsertText = (view?: EditorView): InsertText => {
 
-  return useCallback((text) => {
+export const useInsertText = (view?: EditorView): InsertText => {
+  return useCallback((text, from?, to?) => {
     if (view == null) {
       return;
     }
     const insertPos = view.state.selection.main.head;
+
+    const fromPos = from ?? insertPos;
+    const toPos = to ?? insertPos;
+
     view.dispatch({
       changes: {
-        from: insertPos,
-        to: insertPos,
+        from: fromPos,
+        to: toPos,
         insert: text,
       },
       selection: { anchor: insertPos },

+ 27 - 18
packages/editor/src/services/list-util/markdown-list-util.ts

@@ -1,4 +1,11 @@
-import type { EditorView } from '@codemirror/view';
+import { useCallback } from 'react';
+
+import { EditorView } from '@codemirror/view';
+
+import { useInsertText } from '../codemirror-editor/use-codemirror-editor/utils/insert-text';
+
+
+export type NewlineAndIndentContinueMarkdownList = ((editor: EditorView) => void) | undefined;
 
 // https://regex101.com/r/7BN2fR/5
 const indentAndMarkRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/;
@@ -14,27 +21,29 @@ export const getLineToCursor = (editor: EditorView, lineNumBeforeCursor = 0): st
   return editor.state.sliceDoc(firstLineToGet, curPos);
 };
 
-const insertText = (editor: EditorView, text: string) => {
-  const curPos = editor.state.selection.main.head;
-  const line = editor.state.doc.lineAt(curPos).from;
-  editor.dispatch({
-    changes: {
-      from: line,
-      to: curPos,
-      insert: text,
-    },
-  });
-};
+export const useNewlineAndIndentContinueMarkdownList = (editor?: EditorView): NewlineAndIndentContinueMarkdownList => {
+  const insertText = useInsertText(editor);
+
+  const NewlineAndIndentContinueMarkdownList = useCallback((view: EditorView) => {
+
+    const curPos = view?.state.selection.main.head;
+    const lineStartPos = view?.state.doc.lineAt(curPos).from;
 
-export const newlineAndIndentContinueMarkdownList = (editor: EditorView): void => {
-  const getStrFromAboveLine = getLineToCursor(editor, 1);
+    const getStrFromAboveLine = getLineToCursor(view, 1);
 
-  const matchResult = getStrFromAboveLine.match(indentAndMarkRE);
+    const matchResult = getStrFromAboveLine.match(indentAndMarkRE);
 
-  if (matchResult != null) {
-    const indentAndMark = matchResult[0];
-    insertText(editor, indentAndMark);
+    if (matchResult != null) {
+      const indentAndMark = matchResult[0];
+      insertText(indentAndMark, lineStartPos, curPos);
+    }
+  }, [insertText]);
+
+  if (editor == null) {
+    return;
   }
+
+  return () => { NewlineAndIndentContinueMarkdownList(editor) };
 };
 
 export const adjustPasteData = (indentAndMark: string, text: string): string => {