react-remark
react-remark offers a React hook and React component based way of rendering markdown into React using remark
Installation
npm
npm install --save react-remark
yarn
yarn add react-remark
Usage
As a hook
Render static content
import React, { useEffect } from 'react';
import { useRemark } from 'react-remark';
const ExampleComponent = () => {
const [reactContent, setMarkdownSource] = useRemark();
useEffect(() => {
setMarkdownSource('# markdown header');
}, []);
return reactContent;
};
export default ExampleComponent;
Using input and events to update
import React from 'react';
import { useRemark } from 'react-remark';
const ExampleComponent = () => {
const [reactContent, setMarkdownSource] = useRemark();
return (
<>
<input
type="text"
onChange={({ currentTarget }) => setMarkdownSource(currentTarget.value)}
/>
{reactContent}
</>
);
};
export default ExampleComponent;
Server side rendering
import React from 'react';
import { useRemarkSync } from 'react-remark';
const ExampleComponent = () => {
const reactContent = useRemarkSync('# markdown header');
return reactContent;
};
export default ExampleComponent;
📓 Note that some remark plugins are async, these plugins will error if used with useRemarkSync
.
More examples of usage as hook in storybook.
As a component
Render static content
import React, { useState } from 'react';
import { Remark } from 'react-remark';
const ExampleComponent = () => (
<Remark>{`
# header
1. ordered
2. list
`}</Remark>
);
export default ExampleComponent;
Using input and events to update
import React, { useState } from 'react';
import { Remark } from 'react-remark';
const ExampleComponent = () => {
const [markdownSource, setMarkdownSource] = useState('');
return (
<>
<input
type="text"
onChange={({ currentTarget }) => setMarkdownSource(currentTarget.value)}
/>
<Remark>{markdownSource}</Remark>
</>
);
};
export default ExampleComponent;
More examples of usage as component in storybook.
Examples
A set of runnable examples are provided through storybook at https://remarkjs.github.io/react-remark. The source for the story files can be found in /stories.
Architecture
react-remark
+---------------------------------------------------------------------------------------------------------------------------------------------+
| |
| +----------+ +----------------+ +---------------+ +----------------+ +--------------+ |
| | | | | | | | | | | |
| -markdown->+ remark +-mdast->+ remark plugins +-mdast->+ remark-rehype +-hast->+ rehype plugins +-hast->+ rehype-react +-react elements-> |
| | | | | | | | | | | |
| +----------+ +----------------+ +---------------+ +----------------+ +--------------+ |
| |
+---------------------------------------------------------------------------------------------------------------------------------------------+
relevant links: markdown, remark, mdast, remark plugins, remark-rehype, hast, rehype plugins, rehype-react
Options
remarkParseOptions
(Object) - configure how Markdown is parsed, same asremark-parse
optionsremarkPlugins
(Array) - remark plugins or custom plugins to transform markdown content before it is translated to HTML (hast)remarkToRehypeOptions
(Object) - configure how Markdown (mdast) is translated into HTML (hast), same asremark-rehype
optionsrehypePlugins
(Array) - rehype plugins or custom plugins to transform HTML (hast) before it is translated to React elements.rehypeReactOptions
(Object) - configure how HTML (hast) is translated into React elements, same asrehype-react
options
Pass options to hook
import React, { Fragment } from 'react';
import { useRemark } from 'react-remark';
import remarkGemoji from 'remark-gemoji';
import rehypeSlug from 'rehype-slug';
import rehypeAutoLinkHeadings from 'rehype-autolink-headings';
// ...
const [reactContent, setMarkdownSource] = useRemark({
remarkPlugins: [remarkGemoji],
remarkToRehypeOptions: { allowDangerousHtml: true },
rehypePlugins: [rehypeSlug, rehypeAutoLinkHeadings],
rehypeReactOptions: {
components: {
p: (props) => <p className="custom-paragraph" {...props} />,
},
},
});
Pass options to component
import React, { Fragment } from 'react';
import { Remark } from 'react-remark';
import remarkGemoji from 'remark-gemoji';
import rehypeSlug from 'rehype-slug';
import rehypeAutoLinkHeadings from 'rehype-autolink-headings';
// ...
<Remark
remarkPlugins={[remarkGemoji]}
remarkToRehypeOptions={{ allowDangerousHtml: true }}
rehypePlugins={[rehypeSlug, rehypeAutoLinkHeadings]}
rehypeReactOptions={{
components: {
p: (props) => <p className="custom-paragraph" {...props} />,
},
}}
>
{markdownSource}
</Remark>;