Emiliano
Emiliano

Reputation: 807

Render custom components in React Markdown

I'm building my website documentation and I need to render custom component and it's props, such as <Callout>Hi! I'm a callout</Callout>.

I'm using contentlayer for the directory and react-markdown to render the content.

Here's my code.

          <ReactMarkdown
            rehypePlugins={[rehypeRaw]}
            className={s.markdown}
            components={{
              code({ inline, children, ...props }) {
                if (!inline) {
                  return (
                    <SyntaxHighlighter
                      style={coldarkDark}
                      language={'typescript'}
                    >
                      {String(children).replace(/\n$/, '')}
                    </SyntaxHighlighter>
                  )
                }
                return <code {...props}>{children}</code>
              },
            }}
          >
            {currentDoc.body}
          </ReactMarkdown>

{currentDoc.body} is markdown. So, with this example, I'm passing this to <ReactMarkdown />:

Mollit nisi cillum exercitation minim officia velit laborum non Lorem
adipisicing dolore. Labore commodo consectetur commodo velit adipisicing irure
dolore dolor reprehenderit aliquip. Reprehenderit cillum mollit eiusmod
excepteur elit ipsum aute pariatur in. Cupidatat ex culpa velit culpa ad non
labore exercitation irure laborum.

<Callout>Hi! I'm a callout</Callout>

Hey! [link](https://github.com/rehypejs/rehype-react) right here

Upvotes: 0

Views: 2759

Answers (1)

dbuchet
dbuchet

Reputation: 1651

The idea is to catch your component Callout from your markdown and render it? If so, I think i would use a custom "code language" in your markdown, and then parse it in yourcomponents callback from react-markdown.

For example, your markdown would be

Mollit nisi cillum exercitation minim officia velit laborum non Lorem
adipisicing dolore. Labore commodo consectetur commodo velit adipisicing irure
dolore dolor reprehenderit aliquip. Reprehenderit cillum mollit eiusmod
excepteur elit ipsum aute pariatur in. Cupidatat ex culpa velit culpa ad non
labore exercitation irure laborum.

```callout
Hi! I'm a callout
```
Something else....

React-markdown then render anything as code with a particular className using language-{code} which means in this case language-callout. So you need to catch it and render your callout depending on the className

code({ inline, className, children, ...props }) {
  if (inline) return <code {...props}>{children}</code>

  const value = String(children).replace(/\n$/, '');

  if (className === "language-callout") return (
    <Callout>{value}</Callout>
  )

  return (
    <SyntaxHighlighter
      style={coldarkDark}
      language={'typescript'}
     > 
       {value}
     </SyntaxHighlighter>
   )
}

Upvotes: 4

Related Questions