From d057d20c17a6900565c5b24da0987ec57f960f0b Mon Sep 17 00:00:00 2001
From: stakeswky <64798754+stakeswky@users.noreply.github.com>
Date: Sat, 10 Jun 2023 23:27:11 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0mermaid=E5=9B=BE=E8=A1=A8?=
=?UTF-8?q?=E6=8E=A5=E5=8F=A3=20(#85)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 添加mermaid图表接口
* 添加类型文件
* Update package.json
* Create next-env.d.ts
---
client/next-env.d.ts | 5 ++
client/package.json | 3 +-
.../components/Markdown/MermaidCodeBlock.tsx | 63 +++++++++++++++++++
client/src/components/Markdown/index.tsx | 50 ++++++++-------
client/src/types/mermaid.d.ts | 19 ++++++
5 files changed, 117 insertions(+), 23 deletions(-)
create mode 100644 client/next-env.d.ts
create mode 100644 client/src/components/Markdown/MermaidCodeBlock.tsx
create mode 100644 client/src/types/mermaid.d.ts
diff --git a/client/next-env.d.ts b/client/next-env.d.ts
new file mode 100644
index 000000000..4f11a03dc
--- /dev/null
+++ b/client/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/client/package.json b/client/package.json
index a681c4123..e5f3a99bd 100644
--- a/client/package.json
+++ b/client/package.json
@@ -55,7 +55,8 @@
"sass": "^1.58.3",
"tunnel": "^0.0.6",
"wxpay-v3": "^3.0.2",
- "zustand": "^4.3.5"
+ "zustand": "^4.3.5",
+ "mermaid": "^8.13.5"
},
"devDependencies": {
"@svgr/webpack": "^6.5.1",
diff --git a/client/src/components/Markdown/MermaidCodeBlock.tsx b/client/src/components/Markdown/MermaidCodeBlock.tsx
new file mode 100644
index 000000000..e312e2731
--- /dev/null
+++ b/client/src/components/Markdown/MermaidCodeBlock.tsx
@@ -0,0 +1,63 @@
+import React, { FC, useEffect, useState, useRef } from 'react';
+import mermaid from 'mermaid';
+import { Spinner } from '@chakra-ui/react';
+
+interface MermaidCodeBlockProps {
+ code: string;
+}
+
+const MermaidCodeBlock: FC = ({ code }) => {
+ const [svg, setSvg] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const codeTimeoutIdRef = useRef(null);
+
+ useEffect(() => {
+ if (codeTimeoutIdRef.current) {
+ clearTimeout(codeTimeoutIdRef.current);
+ }
+
+ codeTimeoutIdRef.current = window.setTimeout(() => {
+ setLoading(true);
+
+ const mermaidAPI = (mermaid as any).mermaidAPI as any;
+ mermaidAPI.initialize({ startOnLoad: false, theme: 'forest' });
+
+ try {
+ mermaidAPI.parse(code);
+ mermaidAPI.render('mermaid-svg', code, (svgCode: string) => {
+ setSvg(svgCode);
+ setLoading(false);
+ });
+ } catch (error) {
+ console.error('Error parsing Mermaid code:', '\n', error, '\n', 'Code:', code);
+ setLoading(false);
+ return;
+ }
+ }, 1000);
+ }, [code]);
+
+ useEffect(() => {
+ return () => {
+ if (codeTimeoutIdRef.current) {
+ clearTimeout(codeTimeoutIdRef.current);
+ }
+ };
+ }, []);
+
+ return (
+ <>
+ {loading ? (
+
+

+
+ ) : (
+
+ )}
+ >
+ );
+};
+
+export default MermaidCodeBlock;
diff --git a/client/src/components/Markdown/index.tsx b/client/src/components/Markdown/index.tsx
index fc25f7af3..1a2b43c5f 100644
--- a/client/src/components/Markdown/index.tsx
+++ b/client/src/components/Markdown/index.tsx
@@ -1,4 +1,4 @@
-import React, { memo, useMemo } from 'react';
+import React, { memo, useMemo, useEffect } from 'react';
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { Box, Flex, useColorModeValue } from '@chakra-ui/react';
@@ -7,6 +7,7 @@ import Icon from '@/components/Icon';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';
+import MermaidCodeBlock from './MermaidCodeBlock';
import 'katex/dist/katex.min.css';
import styles from './index.module.scss';
@@ -29,49 +30,54 @@ const Markdown = ({
return (
+ if (match && match[1] === "mermaid") {
+ return ;
+ }
+
+ return !inline && match ? (
+
{match?.[1]}
- copyData(code)} alignItems={'center'}>
-
+ copyData(code)} alignItems={"center"}>
+
复制代码
-
+
{code}
) : (
- {code}
+ {children}
);
- }
+ },
}}
linkTarget="_blank"
>
diff --git a/client/src/types/mermaid.d.ts b/client/src/types/mermaid.d.ts
new file mode 100644
index 000000000..a303d0259
--- /dev/null
+++ b/client/src/types/mermaid.d.ts
@@ -0,0 +1,19 @@
+declare module "mermaid" {
+ import mermaidAPI from "mermaid";
+ const mermaid: any;
+ export default mermaid;
+
+ // 扩展 mermaidAPI
+ interface MermaidAPI extends mermaidAPI.mermaidAPI {
+ contentLoaded: (
+ targetEl: Element,
+ options?: mermaidAPI.mermaidAPI.Config
+ ) => void;
+ }
+
+ const mermaidAPIInstance: MermaidAPI;
+ export default mermaidAPIInstance;
+ }
+type Dispatch = (action: Action) => void;
+
+
\ No newline at end of file