Browse Source

Merge pull request #8355 from weseek/imprv/137432-make-markdown-list-util

imprv: Insert number list only 1 in editor when enter line
Yuki Takei 2 years ago
parent
commit
4bbb4f0f1b

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

@@ -2,7 +2,7 @@ import { useMemo } from 'react';
 
 
 import { indentWithTab, defaultKeymap } from '@codemirror/commands';
 import { indentWithTab, defaultKeymap } from '@codemirror/commands';
 import {
 import {
-  markdown, markdownLanguage,
+  markdown, markdownLanguage, deleteMarkupBackward,
 } from '@codemirror/lang-markdown';
 } from '@codemirror/lang-markdown';
 import { syntaxHighlighting, HighlightStyle, defaultHighlightStyle } from '@codemirror/language';
 import { syntaxHighlighting, HighlightStyle, defaultHighlightStyle } from '@codemirror/language';
 import { languages } from '@codemirror/language-data';
 import { languages } from '@codemirror/language-data';
@@ -26,11 +26,19 @@ import { FoldDrawio, useFoldDrawio } from './utils/fold-drawio';
 import { useGetDoc, type GetDoc } from './utils/get-doc';
 import { useGetDoc, type GetDoc } from './utils/get-doc';
 import { useInitDoc, type InitDoc } from './utils/init-doc';
 import { useInitDoc, type InitDoc } from './utils/init-doc';
 import { useInsertMarkdownElements, type InsertMarkdowElements } from './utils/insert-markdown-elements';
 import { useInsertMarkdownElements, type InsertMarkdowElements } from './utils/insert-markdown-elements';
+import { insertNewlineContinueMarkup } from './utils/insert-newline-continue-markup';
 import { useInsertPrefix, type InsertPrefix } from './utils/insert-prefix';
 import { useInsertPrefix, type InsertPrefix } from './utils/insert-prefix';
 import { useInsertText, type InsertText } from './utils/insert-text';
 import { useInsertText, type InsertText } from './utils/insert-text';
 import { useReplaceText, type ReplaceText } from './utils/replace-text';
 import { useReplaceText, type ReplaceText } from './utils/replace-text';
 import { useSetCaretLine, type SetCaretLine } from './utils/set-caret-line';
 import { useSetCaretLine, type SetCaretLine } from './utils/set-caret-line';
 
 
+// set new markdownKeymap instead of default one
+// I also bound the deleteMarkupBackward to the backspace key to align with the existing keymap
+// https://github.com/codemirror/lang-markdown/blob/main/src/index.ts#L17
+const markdownKeymap = [
+  { key: 'Backspace', run: deleteMarkupBackward },
+  { key: 'Enter', run: insertNewlineContinueMarkup },
+];
 
 
 const markdownHighlighting = HighlightStyle.define([
 const markdownHighlighting = HighlightStyle.define([
   { tag: tags.heading1, class: 'cm-header-1 cm-header' },
   { tag: tags.heading1, class: 'cm-header-1 cm-header' },
@@ -61,7 +69,8 @@ export type UseCodeMirrorEditor = {
 
 
 const defaultExtensions: Extension[] = [
 const defaultExtensions: Extension[] = [
   EditorView.lineWrapping,
   EditorView.lineWrapping,
-  markdown({ base: markdownLanguage, codeLanguages: languages }),
+  markdown({ base: markdownLanguage, codeLanguages: languages, addKeymap: false }),
+  keymap.of(markdownKeymap),
   keymap.of([indentWithTab]),
   keymap.of([indentWithTab]),
   Prec.lowest(keymap.of(defaultKeymap)),
   Prec.lowest(keymap.of(defaultKeymap)),
   syntaxHighlighting(markdownHighlighting),
   syntaxHighlighting(markdownHighlighting),

+ 70 - 0
packages/editor/src/services/codemirror-editor/use-codemirror-editor/utils/insert-newline-continue-markup.ts

@@ -0,0 +1,70 @@
+import type { ChangeSpec, StateCommand } from '@codemirror/state';
+
+// https://regex101.com/r/7BN2fR/5
+const indentAndMarkRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/;
+const indentAndMarkOnlyRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/;
+
+export const insertNewlineContinueMarkup: StateCommand = ({ state, dispatch }) => {
+
+  const changes: ChangeSpec[] = [];
+
+  let selection;
+
+  const curPos = state.selection.main.head;
+
+  const aboveLine = state.doc.lineAt(curPos).number;
+  const bolPos = state.doc.line(aboveLine).from;
+
+  const strFromBol = state.sliceDoc(bolPos, curPos);
+
+  // If the text before the cursor is only markdown symbols
+  if (indentAndMarkOnlyRE.test(strFromBol)) {
+    const insert = state.lineBreak;
+
+    changes.push({
+      from: bolPos,
+      to: curPos,
+      insert,
+    });
+  }
+
+  // If the text before the cursor is markdown text
+  else if (indentAndMarkRE.test(strFromBol)) {
+    const indentAndMark = strFromBol.match(indentAndMarkRE)?.[0];
+
+    if (indentAndMark == null) {
+      return false;
+    }
+
+    const insert = state.lineBreak + indentAndMark;
+    const nextCurPos = curPos + insert.length;
+
+    selection = { anchor: nextCurPos };
+
+    changes.push({
+      from: curPos,
+      insert,
+    });
+  }
+
+  // If the text before the cursor is regular text
+  else {
+    const insert = state.lineBreak;
+    const nextCurPos = curPos + insert.length;
+
+    selection = { anchor: nextCurPos };
+
+    changes.push({
+      from: curPos,
+      insert,
+    });
+  }
+
+  dispatch(state.update({
+    changes,
+    selection,
+    userEvent: 'input',
+  }));
+
+  return true;
+};

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

@@ -1,4 +1,4 @@
-import { EditorView } from '@codemirror/view';
+import type { EditorView } from '@codemirror/view';
 
 
 // https://regex101.com/r/7BN2fR/5
 // https://regex101.com/r/7BN2fR/5
 const indentAndMarkRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/;
 const indentAndMarkRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/;