2
0

insert-newline-continue-markup.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import type { ChangeSpec } from '@codemirror/state';
  2. import type { EditorView } from '@codemirror/view';
  3. // https://regex101.com/r/r9plEA/1
  4. const indentAndMarkRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]\s))(\s*)/;
  5. // https://regex101.com/r/HFYoFN/1
  6. const indentAndMarkOnlyRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/;
  7. export const insertNewlineContinueMarkup = (editor: EditorView): void => {
  8. const changes: ChangeSpec[] = [];
  9. let selection;
  10. const curPos = editor.state.selection.main.head;
  11. const aboveLine = editor.state.doc.lineAt(curPos).number;
  12. const bolPos = editor.state.doc.line(aboveLine).from;
  13. const strFromBol = editor.state.sliceDoc(bolPos, curPos);
  14. // If the text before the cursor is only markdown symbols
  15. if (indentAndMarkOnlyRE.test(strFromBol)) {
  16. const insert = editor.state.lineBreak;
  17. changes.push({
  18. from: bolPos,
  19. to: curPos,
  20. insert,
  21. });
  22. }
  23. // If the text before the cursor is markdown text
  24. else if (indentAndMarkRE.test(strFromBol)) {
  25. const indentAndMark = strFromBol.match(indentAndMarkRE)?.[0];
  26. if (indentAndMark == null) {
  27. return;
  28. }
  29. const insert = editor.state.lineBreak + indentAndMark;
  30. const nextCurPos = curPos + insert.length;
  31. selection = { anchor: nextCurPos };
  32. changes.push({
  33. from: curPos,
  34. insert,
  35. });
  36. }
  37. // If the text before the cursor is regular text
  38. else {
  39. const insert = editor.state.lineBreak;
  40. const nextCurPos = curPos + insert.length;
  41. selection = { anchor: nextCurPos };
  42. changes.push({
  43. from: curPos,
  44. insert,
  45. });
  46. }
  47. editor.dispatch({
  48. changes,
  49. selection,
  50. userEvent: 'input',
  51. });
  52. };