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

Merge pull request #8396 from weseek/imprv/137433-improve-paste-operations-in-markdown

imprv: 137433 improve paste operations in markdown
Yuki Takei 2 лет назад
Родитель
Сommit
b53c2f58e6

+ 17 - 1
packages/editor/src/components/CodeMirrorEditor/CodeMirrorEditor.tsx

@@ -8,10 +8,14 @@ import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
 
 import { GlobalCodeMirrorEditorKey, AcceptedUploadFileType } from '../../consts';
 import { useFileDropzone, FileDropzoneOverlay } from '../../services';
+import {
+  getStrFromBol, adjustPasteData,
+} from '../../services/list-util/markdown-list-util';
 import { useCodeMirrorEditorIsolated } from '../../stores';
 
 import { Toolbar } from './Toolbar';
 
+
 import style from './CodeMirrorEditor.module.scss';
 
 const CodeMirrorEditorContainer = forwardRef<HTMLDivElement>((props, ref) => {
@@ -63,6 +67,12 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
     const handlePaste = (event: ClipboardEvent) => {
       event.preventDefault();
 
+      const editor = codeMirrorEditor?.view;
+
+      if (editor == null) {
+        return;
+      }
+
       if (event.clipboardData == null) {
         return;
       }
@@ -72,8 +82,14 @@ export const CodeMirrorEditor = (props: Props): JSX.Element => {
       }
 
       if (event.clipboardData.types.includes('text/plain')) {
+
         const textData = event.clipboardData.getData('text/plain');
-        codeMirrorEditor?.replaceText(textData);
+
+        const strFromBol = getStrFromBol(editor);
+
+        const adjusted = adjustPasteData(strFromBol, textData);
+
+        codeMirrorEditor?.replaceText(adjusted);
       }
     };
 

+ 46 - 0
packages/editor/src/services/list-util/markdown-list-util.ts

@@ -0,0 +1,46 @@
+import type { EditorView } from '@codemirror/view';
+
+// https://regex101.com/r/7BN2fR/5
+const indentAndMarkRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/;
+
+const getBol = (editor: EditorView) => {
+  const curPos = editor.state.selection.main.head;
+  const aboveLine = editor.state.doc.lineAt(curPos).number;
+  return editor.state.doc.line(aboveLine).from;
+};
+
+export const getStrFromBol = (editor: EditorView): string => {
+  const curPos = editor.state.selection.main.head;
+  return editor.state.sliceDoc(getBol(editor), curPos);
+};
+
+export const adjustPasteData = (indentAndMark: string, text: string): string => {
+
+  let adjusted;
+
+  if (text.match(indentAndMarkRE)) {
+    const matchResult = indentAndMark.match(indentAndMarkRE);
+    const indent = matchResult ? matchResult[1] : '';
+
+    const lines = text.match(/[^\r\n]+/g);
+
+    const replacedLines = lines?.map((line, index) => {
+
+      if (index === 0 && indentAndMark.match(indentAndMarkRE)) {
+        return line.replace(indentAndMarkRE, '');
+      }
+
+      return indent + line;
+    });
+
+    adjusted = replacedLines ? replacedLines.join('\n') : '';
+  }
+
+  else {
+    const replacedText = text.replace(/(\r\n|\r|\n)/g, `$1${indentAndMark}`);
+
+    adjusted = indentAndMark + replacedText;
+  }
+
+  return adjusted;
+};