@@ -7,12 +7,61 @@ import RemarkGfm from "remark-gfm";
7
7
import RehypeHighlight from "rehype-highlight" ;
8
8
import { useRef , useState , RefObject , useEffect } from "react" ;
9
9
import { copyToClipboard } from "../utils" ;
10
+ import mermaid from "mermaid" ;
10
11
11
12
import LoadingIcon from "../icons/three-dots.svg" ;
12
13
import React from "react" ;
13
14
15
+ export function Mermaid ( props : { code : string } ) {
16
+ const ref = useRef < HTMLDivElement > ( null ) ;
17
+
18
+ useEffect ( ( ) => {
19
+ if ( props . code && ref . current ) {
20
+ mermaid . run ( {
21
+ nodes : [ ref . current ] ,
22
+ } ) ;
23
+ }
24
+ } , [ props . code ] ) ;
25
+
26
+ function viewSvgInNewWindow ( ) {
27
+ const svg = ref . current ?. querySelector ( "svg" ) ;
28
+ if ( ! svg ) return ;
29
+ const text = new XMLSerializer ( ) . serializeToString ( svg ) ;
30
+ const blob = new Blob ( [ text ] , { type : "image/svg+xml" } ) ;
31
+ const url = URL . createObjectURL ( blob ) ;
32
+ const win = window . open ( url ) ;
33
+ if ( win ) {
34
+ win . onload = ( ) => URL . revokeObjectURL ( url ) ;
35
+ }
36
+ }
37
+
38
+ return (
39
+ < div
40
+ className = "no-dark"
41
+ style = { { cursor : "pointer" } }
42
+ ref = { ref }
43
+ onClick = { ( ) => viewSvgInNewWindow ( ) }
44
+ >
45
+ { props . code }
46
+ </ div >
47
+ ) ;
48
+ }
49
+
14
50
export function PreCode ( props : { children : any } ) {
15
51
const ref = useRef < HTMLPreElement > ( null ) ;
52
+ const [ mermaidCode , setMermaidCode ] = useState ( "" ) ;
53
+
54
+ useEffect ( ( ) => {
55
+ if ( ! ref . current ) return ;
56
+ const mermaidDom = ref . current . querySelector ( "code.language-mermaid" ) ;
57
+ if ( mermaidDom ) {
58
+ setMermaidCode ( ( mermaidDom as HTMLElement ) . innerText ) ;
59
+ }
60
+ } , [ props . children ] ) ;
61
+
62
+ if ( mermaidCode ) {
63
+ return < Mermaid code = { mermaidCode } /> ;
64
+ }
16
65
17
66
return (
18
67
< pre ref = { ref } >
0 commit comments