Browse Source

Merge pull request #2056 from Yidadaa/bugfix-0620

fix: #2055 should render mermaid completely
Yifei Zhang 1 year ago
parent
commit
67f23d202a
2 changed files with 50 additions and 22 deletions
  1. 38 22
      app/components/markdown.tsx
  2. 12 0
      app/styles/markdown.scss

+ 38 - 22
app/components/markdown.tsx

@@ -11,19 +11,21 @@ import mermaid from "mermaid";
 
 import LoadingIcon from "../icons/three-dots.svg";
 import React from "react";
-import { useThrottledCallback } from "use-debounce";
+import { useDebouncedCallback, useThrottledCallback } from "use-debounce";
 
-export function Mermaid(props: { code: string; onError: () => void }) {
+export function Mermaid(props: { code: string }) {
   const ref = useRef<HTMLDivElement>(null);
+  const [hasError, setHasError] = useState(false);
 
   useEffect(() => {
     if (props.code && ref.current) {
       mermaid
         .run({
           nodes: [ref.current],
+          suppressErrors: true,
         })
         .catch((e) => {
-          props.onError();
+          setHasError(true);
           console.error("[Mermaid] ", e.message);
         });
     }
@@ -42,10 +44,17 @@ export function Mermaid(props: { code: string; onError: () => void }) {
     }
   }
 
+  if (hasError) {
+    return null;
+  }
+
   return (
     <div
-      className="no-dark"
-      style={{ cursor: "pointer", overflow: "auto" }}
+      className="no-dark mermaid"
+      style={{
+        cursor: "pointer",
+        overflow: "auto",
+      }}
       ref={ref}
       onClick={() => viewSvgInNewWindow()}
     >
@@ -56,33 +65,40 @@ export function Mermaid(props: { code: string; onError: () => void }) {
 
 export function PreCode(props: { children: any }) {
   const ref = useRef<HTMLPreElement>(null);
+  const refText = ref.current?.innerText;
   const [mermaidCode, setMermaidCode] = useState("");
 
-  useEffect(() => {
+  const renderMermaid = useDebouncedCallback(() => {
     if (!ref.current) return;
     const mermaidDom = ref.current.querySelector("code.language-mermaid");
     if (mermaidDom) {
       setMermaidCode((mermaidDom as HTMLElement).innerText);
     }
-  }, [props.children]);
+  }, 600);
 
-  if (mermaidCode) {
-    return <Mermaid code={mermaidCode} onError={() => setMermaidCode("")} />;
-  }
+  useEffect(() => {
+    setTimeout(renderMermaid, 1);
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [refText]);
 
   return (
-    <pre ref={ref}>
-      <span
-        className="copy-code-button"
-        onClick={() => {
-          if (ref.current) {
-            const code = ref.current.innerText;
-            copyToClipboard(code);
-          }
-        }}
-      ></span>
-      {props.children}
-    </pre>
+    <>
+      {mermaidCode.length > 0 && (
+        <Mermaid code={mermaidCode} key={mermaidCode} />
+      )}
+      <pre ref={ref}>
+        <span
+          className="copy-code-button"
+          onClick={() => {
+            if (ref.current) {
+              const code = ref.current.innerText;
+              copyToClipboard(code);
+            }
+          }}
+        ></span>
+        {props.children}
+      </pre>
+    </>
   );
 }
 

+ 12 - 0
app/styles/markdown.scss

@@ -1117,3 +1117,15 @@
 .markdown-body ::-webkit-calendar-picker-indicator {
   filter: invert(50%);
 }
+
+.markdown-body .mermaid {
+  border: var(--border-in-light);
+  margin-bottom: 10px;
+  border-radius: 4px;
+  padding: 10px;
+  background-color: var(--white);
+}
+
+#dmermaid {
+  display: none;
+}