uiwjs / react-markdown-preview

React component preview markdown text in web browser. The minimal amount of CSS to replicate the GitHub Markdown style. Support dark-mode/night mode.
https://uiwjs.github.io/react-markdown-preview
MIT License
270 stars 48 forks source link

RehypeMermaid plugin not working #238

Open m-s-abeer opened 11 months ago

m-s-abeer commented 11 months ago

This is the code I'm rendering with:-

import React from 'react';
import MarkdownPreview from '@uiw/react-markdown-preview';
import rehypeMermaid from 'rehype-mermaidjs';

export default function MyMarkdownPreview({ data, setData }: { data: string; setData: (data: string) => void }) {
    return (
        <MarkdownPreview
            source={data}
            wrapperElement={{
                'data-color-mode': 'light',
            }}
            rehypePlugins={[rehypeMermaid]}
            rehypeRewrite={(node, index, parent) => {
                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
                if (node.tagName === 'a' && parent && /^h(1|2|3|4|5|6)/.test(parent.tagName as string)) {
                    parent.children = parent.children.slice(1);
                }
            }}
        />
    );
}

The md text I'm rendering with:-

```mermaid
  graph TD;
      A-->B;
      A-->C;
      B-->D;
      C-->D;
```

It just renders it like this:- image

jaywcjlove commented 11 months ago

@m-s-abeer https://codesandbox.io/embed/react-markdown-preview-https-github-com-uiwjs-react-markdown-preview-issues-238-lw6vr5?fontsize=14&hidenavigation=1&theme=dark

import React, { useState, useRef, useEffect, Fragment, useCallback } from "react";
import MarkdownPreview from '@uiw/react-markdown-preview';
import { getCodeString } from 'rehype-rewrite';
import mermaid from "mermaid";

const randomid = () => parseInt(String(Math.random() * 1e15), 10).toString(36);
const Code = ({ inline, children = [], className, ...props }) => {
  const demoid = useRef(`dome${randomid()}`);
  const [container, setContainer] = useState(null);
  const isMermaid = className && /^language-mermaid/.test(className.toLocaleLowerCase());
  const code = props.node && props.node.children ? getCodeString(props.node.children) : children[0] || '';

  const reRender = async () => {
    if (container && isMermaid) {
      try {
        const str = await mermaid.render(demoid.current, code);
        container.innerHTML = str.svg;
      } catch (error) {
        container.innerHTML = error;
      }
    }
  }

  useEffect(() => {
    reRender()
  }, [container, isMermaid, code, demoid]);

  const refElement = useCallback((node) => {
    if (node !== null) {
      setContainer(node);
    }
  }, []);

  if (isMermaid) {
    return (
      <Fragment>
        <code id={demoid.current} style={{ display: "none" }} />
        <code ref={refElement} data-name="mermaid" />
      </Fragment>
    );
  }
  return <code>{children}</code>;
};

const source = `
\`\`\`mermaid
graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;
\`\`\`
`;

export default function Demo() {
  return (
    <MarkdownPreview
      source={source}
      components={{
        code: Code
      }}
    />
  );
}