soumaeda 2 лет назад
Родитель
Сommit
d8cf5c5126

+ 12 - 4
apps/app/src/components/PageEditor/DrawioModal.tsx

@@ -11,6 +11,7 @@ import {
 } from 'reactstrap';
 } from 'reactstrap';
 
 
 import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
 import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
+import mdu from '~/components/PageEditor/MarkdownDrawioUtil';
 import { useRendererConfig } from '~/stores/context';
 import { useRendererConfig } from '~/stores/context';
 import { useDrawioModal } from '~/stores/modal';
 import { useDrawioModal } from '~/stores/modal';
 import { usePersonalSettings } from '~/stores/personal-settings';
 import { usePersonalSettings } from '~/stores/personal-settings';
@@ -51,6 +52,7 @@ export const DrawioModal = (): JSX.Element => {
   const { data: drawioModalDataInEditor } = useDrawioModalForEditor();
   const { data: drawioModalDataInEditor } = useDrawioModalForEditor();
   const isOpened = drawioModalData?.isOpened ?? false;
   const isOpened = drawioModalData?.isOpened ?? false;
   const isOpendInEditor = drawioModalDataInEditor?.isOpened ?? false;
   const isOpendInEditor = drawioModalDataInEditor?.isOpened ?? false;
+  const editor = drawioModalDataInEditor?.editor;
 
 
   const drawioUriWithParams = useMemo(() => {
   const drawioUriWithParams = useMemo(() => {
     if (rendererConfig == null) {
     if (rendererConfig == null) {
@@ -81,20 +83,26 @@ export const DrawioModal = (): JSX.Element => {
       return undefined;
       return undefined;
     }
     }
 
 
+    const save = editor != null ? (drawioMxFile: string) => {
+      mdu.replaceFocusedDrawioWithEditor(editor, drawioMxFile);
+    } : drawioModalData?.onSave;
+    // TODO: Fold the section after the drawio section (```drawio) has been updated.
+
     return new DrawioCommunicationHelper(
     return new DrawioCommunicationHelper(
       rendererConfig.drawioUri,
       rendererConfig.drawioUri,
       drawioConfig,
       drawioConfig,
-      { onClose: closeDrawioModal, onSave: drawioModalData?.onSave },
+      { onClose: closeDrawioModal, onSave: save },
     );
     );
-  }, [closeDrawioModal, drawioModalData?.onSave, rendererConfig]);
+  }, [closeDrawioModal, drawioModalData?.onSave, editor, rendererConfig]);
 
 
   const receiveMessageHandler = useCallback((event: MessageEvent) => {
   const receiveMessageHandler = useCallback((event: MessageEvent) => {
     if (drawioModalData == null) {
     if (drawioModalData == null) {
       return;
       return;
     }
     }
 
 
-    drawioCommunicationHelper?.onReceiveMessage(event, drawioModalData.drawioMxFile);
-  }, [drawioCommunicationHelper, drawioModalData]);
+    const drawioMxFile = editor != null ? mdu.getMarkdownDrawioMxfile(editor) : drawioModalData.drawioMxFile;
+    drawioCommunicationHelper?.onReceiveMessage(event, drawioMxFile);
+  }, [drawioCommunicationHelper, drawioModalData, editor]);
 
 
   useEffect(() => {
   useEffect(() => {
     if (isOpened) {
     if (isOpened) {

+ 43 - 26
apps/app/src/components/PageEditor/MarkdownDrawioUtil.js

@@ -6,6 +6,18 @@ class MarkdownDrawioUtil {
   constructor() {
   constructor() {
     this.lineBeginPartOfDrawioRE = /^```(\s.*)drawio$/;
     this.lineBeginPartOfDrawioRE = /^```(\s.*)drawio$/;
     this.lineEndPartOfDrawioRE = /^```$/;
     this.lineEndPartOfDrawioRE = /^```$/;
+    this.curPos = this.curPos.bind(this);
+    this.doc = this.doc.bind(this);
+  }
+
+  // get cursor position from editor
+  curPos(editor) {
+    return editor.state.selection.main.head;
+  }
+
+  // get doc from editor
+  doc(editor) {
+    return editor.state.doc;
   }
   }
 
 
   /**
   /**
@@ -13,17 +25,17 @@ class MarkdownDrawioUtil {
    * (If the BOD is not found after the cursor or the EOD is found before the BOD, return null)
    * (If the BOD is not found after the cursor or the EOD is found before the BOD, return null)
    */
    */
   getBod(editor) {
   getBod(editor) {
-    const curPos = editor.getCursor();
-    const firstLine = editor.getDoc().firstLine();
+    const firstLine = 1;
 
 
-    if (this.lineBeginPartOfDrawioRE.test(editor.getDoc().getLine(curPos.line))) {
-      return { line: curPos.line, ch: 0 };
+    if (this.lineBeginPartOfDrawioRE.test(this.doc(editor).lineAt(this.curPos(editor))).text) {
+      // get the beginning of the line where the cursor is located
+      return this.doc(editor).lineAt(this.curPos(editor)).from;
     }
     }
 
 
-    let line = curPos.line - 1;
+    let line = this.doc(editor).lineAt(this.curPos(editor)).number - 1;
     let isFound = false;
     let isFound = false;
     for (; line >= firstLine; line--) {
     for (; line >= firstLine; line--) {
-      const strLine = editor.getDoc().getLine(line);
+      const strLine = this.doc(editor).line(line).text;
       if (this.lineBeginPartOfDrawioRE.test(strLine)) {
       if (this.lineBeginPartOfDrawioRE.test(strLine)) {
         isFound = true;
         isFound = true;
         break;
         break;
@@ -39,8 +51,8 @@ class MarkdownDrawioUtil {
       return null;
       return null;
     }
     }
 
 
-    const bodLine = Math.max(firstLine, line);
-    return { line: bodLine, ch: 0 };
+    const botLine = Math.max(firstLine, line);
+    return this.doc(editor).line(botLine).from;
   }
   }
 
 
   /**
   /**
@@ -48,17 +60,17 @@ class MarkdownDrawioUtil {
    * (If the EOD is not found after the cursor or the BOD is found before the EOD, return null)
    * (If the EOD is not found after the cursor or the BOD is found before the EOD, return null)
    */
    */
   getEod(editor) {
   getEod(editor) {
-    const curPos = editor.getCursor();
-    const lastLine = editor.getDoc().lastLine();
+    const lastLine = this.doc(editor).lines;
 
 
-    if (this.lineEndPartOfDrawioRE.test(editor.getDoc().getLine(curPos.line))) {
-      return { line: curPos.line, ch: editor.getDoc().getLine(curPos.line).length };
+    if (this.lineEndPartOfDrawioRE.test(this.doc(editor).lineAt(this.curPos(editor))).text) {
+      // get the end of the line where the cursor is located
+      return this.doc(editor).lineAt(this.curPos(editor)).to;
     }
     }
 
 
-    let line = curPos.line + 1;
+    let line = this.doc(editor).lineAt(this.curPos(editor)).number + 1;
     let isFound = false;
     let isFound = false;
     for (; line <= lastLine; line++) {
     for (; line <= lastLine; line++) {
-      const strLine = editor.getDoc().getLine(line);
+      const strLine = this.doc(editor).line(line).text;
       if (this.lineEndPartOfDrawioRE.test(strLine)) {
       if (this.lineEndPartOfDrawioRE.test(strLine)) {
         isFound = true;
         isFound = true;
         break;
         break;
@@ -75,8 +87,7 @@ class MarkdownDrawioUtil {
     }
     }
 
 
     const eodLine = Math.min(line, lastLine);
     const eodLine = Math.min(line, lastLine);
-    const lineLength = editor.getDoc().getLine(eodLine).length;
-    return { line: eodLine, ch: lineLength };
+    return this.doc(editor).line(eodLine).to;
   }
   }
 
 
   /**
   /**
@@ -101,18 +112,18 @@ class MarkdownDrawioUtil {
       const eod = this.getEod(editor);
       const eod = this.getEod(editor);
 
 
       // skip block begin sesion("``` drawio")
       // skip block begin sesion("``` drawio")
-      bod.line++;
+      const bodLineNum = this.doc(editor).lineAt(bod).number + 1;
+      const bodLine = this.doc(editor).line(bodLineNum);
       // skip block end sesion("```")
       // skip block end sesion("```")
-      eod.line--;
-      eod.ch = editor.getDoc().getLine(eod.line).length;
+      const eodLineNum = this.doc(editor).lineAt(eod).number - 1;
+      const eodLine = this.doc(editor).line(eodLineNum);
 
 
-      return editor.getDoc().getRange(bod, eod);
+      return editor.state.sliceDoc(bodLine.from, eodLine.to);
     }
     }
     return null;
     return null;
   }
   }
 
 
   replaceFocusedDrawioWithEditor(editor, drawioData) {
   replaceFocusedDrawioWithEditor(editor, drawioData) {
-    const curPos = editor.getCursor();
     const drawioBlock = ['``` drawio', drawioData.toString(), '```'].join('\n');
     const drawioBlock = ['``` drawio', drawioData.toString(), '```'].join('\n');
     let beginPos;
     let beginPos;
     let endPos;
     let endPos;
@@ -122,11 +133,17 @@ class MarkdownDrawioUtil {
       endPos = this.getEod(editor);
       endPos = this.getEod(editor);
     }
     }
     else {
     else {
-      beginPos = { line: curPos.line, ch: curPos.ch };
-      endPos = { line: curPos.line, ch: curPos.ch };
+      beginPos = this.doc(editor).lineAt(this.curPos(editor)).from;
+      endPos = this.doc(editor).lineAt(this.curPos(editor)).to;
     }
     }
 
 
-    editor.getDoc().replaceRange(drawioBlock, beginPos, endPos);
+    editor.dispatch({
+      changes: {
+        from: beginPos,
+        to: endPos,
+        insert: drawioBlock,
+      },
+    });
   }
   }
 
 
   /**
   /**
@@ -161,8 +178,8 @@ class MarkdownDrawioUtil {
   findAllDrawioSection(editor) {
   findAllDrawioSection(editor) {
     const lineNumbers = [];
     const lineNumbers = [];
     // refs: https://github.com/codemirror/CodeMirror/blob/5.64.0/addon/fold/foldcode.js#L106-L111
     // refs: https://github.com/codemirror/CodeMirror/blob/5.64.0/addon/fold/foldcode.js#L106-L111
-    for (let i = editor.firstLine(), e = editor.lastLine(); i <= e; i++) {
-      const line = editor.getLine(i);
+    for (let i = 1, e = this.doc(editor).lines; i <= e; i++) {
+      const line = this.doc(editor).line(i + 1).text;
       const match = this.lineBeginPartOfDrawioRE.exec(line);
       const match = this.lineBeginPartOfDrawioRE.exec(line);
       if (match) {
       if (match) {
         lineNumbers.push(i);
         lineNumbers.push(i);

+ 12 - 3
packages/editor/src/components/CodeMirrorEditor/Toolbar/DiagramButton.tsx

@@ -1,12 +1,21 @@
 import { useCallback } from 'react';
 import { useCallback } from 'react';
 
 
+import { useCodeMirrorEditorIsolated } from '../../../stores';
 import { useDrawioModalForEditor } from '../../../stores/use-drawio';
 import { useDrawioModalForEditor } from '../../../stores/use-drawio';
 
 
-export const DiagramButton = (): JSX.Element => {
+
+type Props = {
+  editorKey: string,
+}
+
+export const DiagramButton = (props: Props): JSX.Element => {
+  const { editorKey } = props;
+  const { data: codeMirrorEditor } = useCodeMirrorEditorIsolated(editorKey);
   const { open: openDrawioModal } = useDrawioModalForEditor();
   const { open: openDrawioModal } = useDrawioModalForEditor();
+  const editor = codeMirrorEditor?.view;
   const onClickDiagramButton = useCallback(() => {
   const onClickDiagramButton = useCallback(() => {
-    openDrawioModal();
-  }, [openDrawioModal]);
+    openDrawioModal(editor);
+  }, [editor, openDrawioModal]);
   return (
   return (
     <button type="button" className="btn btn-toolbar-button" onClick={onClickDiagramButton}>
     <button type="button" className="btn btn-toolbar-button" onClick={onClickDiagramButton}>
       <span className="material-symbols-outlined fs-5">lan</span>
       <span className="material-symbols-outlined fs-5">lan</span>

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

@@ -28,7 +28,7 @@ export const Toolbar = memo((props: Props): JSX.Element => {
         editorKey={editorKey}
         editorKey={editorKey}
       />
       />
       <TableButton editorKey={editorKey} />
       <TableButton editorKey={editorKey} />
-      <DiagramButton />
+      <DiagramButton editorKey={editorKey} />
       <TemplateButton />
       <TemplateButton />
     </div>
     </div>
   );
   );

+ 6 - 3
packages/editor/src/stores/use-drawio.ts

@@ -1,5 +1,6 @@
 import { useCallback } from 'react';
 import { useCallback } from 'react';
 
 
+import type { EditorView } from '@codemirror/view';
 import { useSWRStatic } from '@growi/core/dist/swr';
 import { useSWRStatic } from '@growi/core/dist/swr';
 import type { SWRResponse } from 'swr';
 import type { SWRResponse } from 'swr';
 
 
@@ -7,11 +8,13 @@ type DrawioModalSaveHandler = () => void;
 
 
 type DrawioModalStatus = {
 type DrawioModalStatus = {
   isOpened: boolean,
   isOpened: boolean,
+  editor?: EditorView,
   onSave?: DrawioModalSaveHandler,
   onSave?: DrawioModalSaveHandler,
 }
 }
 
 
 type DrawioModalStatusUtils = {
 type DrawioModalStatusUtils = {
   open(
   open(
+    editor?: EditorView,
     onSave?: DrawioModalSaveHandler,
     onSave?: DrawioModalSaveHandler,
   ): void,
   ): void,
   close(): void,
   close(): void,
@@ -25,12 +28,12 @@ export const useDrawioModalForEditor = (status?: DrawioModalStatus): SWRResponse
 
 
   const { mutate } = swrResponse;
   const { mutate } = swrResponse;
 
 
-  const open = useCallback((onSave?: DrawioModalSaveHandler): void => {
-    mutate({ isOpened: true, onSave });
+  const open = useCallback((editor?: EditorView, onSave?: DrawioModalSaveHandler): void => {
+    mutate({ isOpened: true, editor, onSave });
   }, [mutate]);
   }, [mutate]);
 
 
   const close = useCallback((): void => {
   const close = useCallback((): void => {
-    mutate({ isOpened: false, drawioMxFile: '', onSave: undefined });
+    mutate({ isOpened: false, editor: undefined, onSave: undefined });
   }, [mutate]);
   }, [mutate]);
 
 
   return {
   return {