feat: add mermaid support in codeblock (#2971)

This commit is contained in:
Kristián 2024-02-19 08:10:58 +01:00 committed by GitHub
parent a86117f613
commit 03d67d5a00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 911 additions and 7 deletions

View File

@ -62,6 +62,7 @@ services:
- pnpm-store:/work/web/.pnpm-store
- ../proto:/work/proto
- ../web:/work/web
- ../web/node_modules:/work/web/node_modules
healthcheck:
test: ["CMD", "wget", "-qO", "-", "http://localhost:3001"]
interval: 10s

View File

@ -23,6 +23,7 @@
"katex": "^0.16.9",
"lodash-es": "^4.17.21",
"lucide-react": "^0.309.0",
"mermaid": "^10.8.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
@ -38,6 +39,8 @@
"devDependencies": {
"@bufbuild/buf": "^1.29.0",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/d3": "^7.4.3",
"@types/dompurify": "^3.0.5",
"@types/katex": "^0.16.7",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.11.16",

876
web/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
import { useColorScheme } from "@mui/joy";
import mermaid from "mermaid";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Outlet } from "react-router-dom";
@ -18,6 +19,8 @@ const App = () => {
const { appearance, locale, systemStatus } = globalStore.state;
const userSetting = userStore.userSetting;
mermaid.initialize({ startOnLoad: false, theme: mode });
// Redirect to sign up page if no host.
useEffect(() => {
if (!systemStatus.host) {

View File

@ -3,8 +3,11 @@ import copy from "copy-to-clipboard";
import hljs from "highlight.js";
import toast from "react-hot-toast";
import Icon from "../Icon";
import MermaidBlock from "./MermaidBlock";
import { BaseProps } from "./types";
const MERMAID_LANGUAGE = "mermaid";
interface Props extends BaseProps {
language: string;
content: string;
@ -19,6 +22,10 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
return <div className="w-full overflow-auto !my-2" dangerouslySetInnerHTML={{ __html: content }} />;
}
if (formatedLanguage === MERMAID_LANGUAGE) {
return <MermaidBlock content={content} />;
}
try {
const temp = hljs.highlight(content, {
language: formatedLanguage,
@ -39,6 +46,7 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
<span className="text-sm font-mono">{formatedLanguage}</span>
<Icon.Copy className="w-4 h-auto cursor-pointer hover:opacity-80" onClick={handleCopyButtonClick} />
</div>
<pre className="w-full p-2 bg-amber-50 dark:bg-zinc-700 whitespace-pre-wrap relative">
<code
className={classNames(`language-${formatedLanguage}`, "block text-sm leading-5")}

View File

@ -0,0 +1,27 @@
import mermaid from "mermaid";
import { useEffect, useRef } from "react";
interface Props {
content: string;
}
const MermaidBlock: React.FC<Props> = ({ content }: Props) => {
const mermaidDockBlock = useRef<null>(null);
useEffect(() => {
if (!mermaidDockBlock.current) {
return;
}
// Render mermaid when mounted
mermaid.run({
nodes: [mermaidDockBlock.current],
});
});
return (
<pre ref={mermaidDockBlock} className="w-full p-2 whitespace-pre-wrap relative" dangerouslySetInnerHTML={{ __html: content }}></pre>
);
};
export default MermaidBlock;