Răsfoiți Sursa

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

kosei-n 2 ani în urmă
părinte
comite
23c870b1a3

+ 24 - 2
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx

@@ -10,7 +10,8 @@ import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
 import { GlobalCodeMirrorEditorKey, AcceptedUploadFileType } from '../../consts';
 import { useFileDropzone, FileDropzoneOverlay, AllEditorTheme } from '../../services';
 import {
-  getStrFromBol, adjustPasteData,
+  getLineToCursor, adjustPasteData,
+  newlineAndIndentContinueMarkdownList,
 } from '../../services/list-util/markdown-list-util';
 import { useCodeMirrorEditorIsolated } from '../../stores';
 
@@ -55,6 +56,27 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
   }, [onChange]);
   const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(editorKey, containerRef.current, cmProps);
 
+  useEffect(() => {
+    const editor = codeMirrorEditor?.view;
+
+    const handleEnterKey = (event: KeyboardEvent) => {
+      if (event.key === 'Enter') {
+        event.preventDefault();
+        const editor = codeMirrorEditor?.view;
+        if (editor == null) {
+          return;
+        }
+        newlineAndIndentContinueMarkdownList(editor);
+      }
+    };
+
+    editor?.dom.addEventListener('keydown', handleEnterKey);
+
+    return () => {
+      editor?.dom.removeEventListener('keydown', handleEnterKey);
+    };
+  }, [codeMirrorEditor]);
+
   useEffect(() => {
     if (indentSize == null) {
       return;
@@ -88,7 +110,7 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
 
         const textData = event.clipboardData.getData('text/plain');
 
-        const strFromBol = getStrFromBol(editor);
+        const strFromBol = getLineToCursor(editor);
 
         const adjusted = adjustPasteData(strFromBol, textData);
 

+ 6 - 2
packages/editor/src/services/codemirror-editor/use-codemirror-editor/use-codemirror-editor.ts

@@ -1,10 +1,14 @@
 import { useMemo } from 'react';
 
 import { indentWithTab, defaultKeymap } from '@codemirror/commands';
-import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
+import {
+  markdown, markdownLanguage,
+} from '@codemirror/lang-markdown';
 import { syntaxHighlighting, HighlightStyle, defaultHighlightStyle } from '@codemirror/language';
 import { languages } from '@codemirror/language-data';
-import { EditorState, Prec, type Extension } from '@codemirror/state';
+import {
+  EditorState, Prec, type Extension,
+} from '@codemirror/state';
 import { keymap, EditorView } from '@codemirror/view';
 import { tags } from '@lezer/highlight';
 import { useCodeMirror, type UseCodeMirror } from '@uiw/react-codemirror';

+ 28 - 5
packages/editor/src/services/list-util/markdown-list-util.ts

@@ -3,15 +3,38 @@ import type { EditorView } from '@codemirror/view';
 // https://regex101.com/r/7BN2fR/5
 const indentAndMarkRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/;
 
-const getBol = (editor: EditorView) => {
+export const getLineToCursor = (editor: EditorView, lineNumBeforeCursor = 0): string => {
   const curPos = editor.state.selection.main.head;
-  const aboveLine = editor.state.doc.lineAt(curPos).number;
-  return editor.state.doc.line(aboveLine).from;
+  const firstLineNumToGet = editor.state.doc.lineAt(curPos).number - lineNumBeforeCursor;
+
+  const fixedFirstLineNumToGet = Math.max(firstLineNumToGet, 0);
+
+  const firstLineToGet = editor.state.doc.line(fixedFirstLineNumToGet).from;
+
+  return editor.state.sliceDoc(firstLineToGet, curPos);
 };
 
-export const getStrFromBol = (editor: EditorView): string => {
+const insertText = (editor: EditorView, text: string) => {
   const curPos = editor.state.selection.main.head;
-  return editor.state.sliceDoc(getBol(editor), curPos);
+  const line = editor.state.doc.lineAt(curPos).from;
+  editor.dispatch({
+    changes: {
+      from: line,
+      to: curPos,
+      insert: text,
+    },
+  });
+};
+
+export const newlineAndIndentContinueMarkdownList = (editor: EditorView): void => {
+  const getStrFromAboveLine = getLineToCursor(editor, 1);
+
+  const matchResult = getStrFromAboveLine.match(indentAndMarkRE);
+
+  if (matchResult != null) {
+    const indentAndMark = matchResult[0];
+    insertText(editor, indentAndMark);
+  }
 };
 
 export const adjustPasteData = (indentAndMark: string, text: string): string => {