markdown-drawio-util-for-editor.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { EditorView } from '@codemirror/view';
  2. const lineBeginPartOfDrawioRE = /^```(\s.*)drawio$/;
  3. const lineEndPartOfDrawioRE = /^```$/;
  4. const firstLineNum = 1;
  5. const curPos = (editor: EditorView) => {
  6. return editor.state.selection.main.head;
  7. };
  8. const doc = (editor: EditorView) => {
  9. return editor.state.doc;
  10. };
  11. const lastLineNum = (editor: EditorView) => {
  12. return doc(editor).lines;
  13. };
  14. const getCursorLine = (editor: EditorView) => {
  15. return doc(editor).lineAt(curPos(editor));
  16. };
  17. const getLine = (editor: EditorView, lineNum: number) => {
  18. return doc(editor).line(lineNum);
  19. };
  20. /**
  21. * return the postion of the BOD(beginning of drawio)
  22. * (If the BOD is not found after the cursor or the EOD is found before the BOD, return null)
  23. */
  24. const getBod = (editor: EditorView) => {
  25. const strLine = getCursorLine(editor).text;
  26. if (lineBeginPartOfDrawioRE.test(strLine)) {
  27. // get the beginning of the line where the cursor is located
  28. return getCursorLine(editor).from;
  29. }
  30. let line = getCursorLine(editor).number - 1;
  31. let isFound = false;
  32. for (; line >= firstLineNum; line--) {
  33. const strLine = getLine(editor, line).text;
  34. if (lineBeginPartOfDrawioRE.test(strLine)) {
  35. isFound = true;
  36. break;
  37. }
  38. if (lineEndPartOfDrawioRE.test(strLine)) {
  39. isFound = false;
  40. break;
  41. }
  42. }
  43. if (!isFound) {
  44. return null;
  45. }
  46. const botLine = Math.max(firstLineNum, line);
  47. return getLine(editor, botLine).from;
  48. };
  49. /**
  50. * return the postion of the EOD(end of drawio)
  51. * (If the EOD is not found after the cursor or the BOD is found before the EOD, return null)
  52. */
  53. const getEod = (editor: EditorView) => {
  54. const lastLine = lastLineNum(editor);
  55. const strLine = getCursorLine(editor).text;
  56. if (lineEndPartOfDrawioRE.test(strLine)) {
  57. // get the end of the line where the cursor is located
  58. return getCursorLine(editor).to;
  59. }
  60. let line = getCursorLine(editor).number + 1;
  61. let isFound = false;
  62. for (; line <= lastLine; line++) {
  63. const strLine = getLine(editor, line).text;
  64. if (lineEndPartOfDrawioRE.test(strLine)) {
  65. isFound = true;
  66. break;
  67. }
  68. if (lineBeginPartOfDrawioRE.test(strLine)) {
  69. isFound = false;
  70. break;
  71. }
  72. }
  73. if (!isFound) {
  74. return null;
  75. }
  76. const eodLine = Math.min(line, lastLine);
  77. return getLine(editor, eodLine).to;
  78. };
  79. /**
  80. * return drawioData instance where the cursor is
  81. * (If the cursor is not in a drawio block, return null)
  82. */
  83. export const getMarkdownDrawioMxfile = (editor: EditorView): string | null => {
  84. const bod = getBod(editor);
  85. const eod = getEod(editor);
  86. if (bod == null || eod == null || JSON.stringify(bod) === JSON.stringify(eod)) {
  87. return null;
  88. }
  89. // skip block begin sesion("``` drawio")
  90. const bodLineNum = doc(editor).lineAt(bod).number + 1;
  91. const bodLine = getLine(editor, bodLineNum).from;
  92. // skip block end sesion("```")
  93. const eodLineNum = doc(editor).lineAt(eod).number - 1;
  94. const eodLine = getLine(editor, eodLineNum).to;
  95. return editor.state.sliceDoc(bodLine, eodLine);
  96. };
  97. export const replaceFocusedDrawioWithEditor = (editor: EditorView, drawioData: string): void => {
  98. const drawioBlock = ['``` drawio', drawioData.toString(), '```'].join('\n');
  99. let bod = getBod(editor);
  100. let eod = getEod(editor);
  101. if (bod == null || eod == null || JSON.stringify(bod) === JSON.stringify(eod)) {
  102. bod = curPos(editor);
  103. eod = curPos(editor);
  104. }
  105. editor.dispatch({
  106. changes: {
  107. from: bod,
  108. to: eod,
  109. insert: drawioBlock,
  110. },
  111. });
  112. };