Open HerbertHe opened 2 weeks ago
That's probably an issue with Async plugins in react-markdown: https://github.com/remarkjs/react-markdown/issues/680
@HerbertHe Yesterday, I also got the same issue when using shiki with react-markdown. But it seems that no a solution yet on the react-markdown side. So, I referred to this article, and I think we only need a simple hook and don't necessarily need react-markdown, like below:
useRemark
import { useCallback, useState } from 'react'
import * as jsxRuntime from 'react/jsx-runtime'
import rehypeReact, { type Options as RehypeReactOptions } from 'rehype-react'
import remarkParse, { type Options as RemarkParseOptions } from 'remark-parse'
import remarkRehype, { type Options as RemarkRehypeOptions } from 'remark-rehype'
import { unified, type PluggableList } from 'unified'
export interface UseRemarkOptions {
remarkParseOptions?: RemarkParseOptions
remarkPlugins?: PluggableList
remarkRehypeOptions?: RemarkRehypeOptions
rehypePlugins?: PluggableList
rehypeReactOptions?: Pick<RehypeReactOptions, 'components'>
onError?: (err: Error) => void
}
export default function useRemark({
remarkParseOptions,
remarkPlugins = [],
remarkRehypeOptions,
rehypePlugins = [],
rehypeReactOptions,
onError = () => {},
}: UseRemarkOptions = {}): [React.ReactElement | null, (source: string) => void] {
const [content, setContent] = useState<React.ReactElement | null>(null)
const setMarkdown = useCallback((source: string) => {
unified()
.use(remarkParse, remarkParseOptions) // parse markdown
.use(remarkPlugins)
.use(remarkRehype, remarkRehypeOptions) // markdown to html
.use(rehypePlugins)
.use(rehypeReact, { // html to react elements
...rehypeReactOptions,
Fragment: jsxRuntime.Fragment,
jsx: jsxRuntime.jsx,
jsxs: jsxRuntime.jsxs,
} satisfies RehypeReactOptions)
.process(source)
.then(vfile => setContent(vfile.result)) // get react elements
.catch(onError)
}, [])
return [content, setMarkdown]
}
you just need to add the pkg of unified
, remark-parse
, remark-rehype
, rehype-react
const [markdown, setMarkdown] = useRemark({
rehypePlugins: [
[rehypeShiki, { theme: 'catppuccin-mocha' } satisfies RehypeShikiOptions]
],
})
if (markdown == null) {
setMarkdown(source) // markdown source string
}
return <article>{markdown}</article>
Hopefully, this will be useful to you.
@liuhq Thank you for the example, maybe I don't need to do that now🌚. I just need to render the markdown formatted content for AI Agent answers. It seems that I don't need to JUST highlight the code content, but to add more interactions🤣
Validations
Describe the bug
I tried to use @shikijs/rehype with react-markdown, but I got an error as followed:
Reproduction
follow the document with @shikijs/rehype
Contributes