React Marked Renderer
A low-level component wrapper for marked
that renders as React components instead of strings.
Check out the playground website to
see how markdown is rendered with the default renderers or custom renderers and
the
API Documentation.
Installation
npm install react react-marked-renderer
Or with yarn:
yarn add react react-marked-renderer
Features
- render almost everything that is available by GitHub flavored markdown out of
the box
- the only exception is rendering
html
code itself
- allow custom renderers to implement complex components if desired or custom
styles
- allows code highlighting
- allow code language aliases/resolution with
getLanguage
- in the browser with
highlightElement
(can be asynchronous) - in node environments with
highlightCode
(synchronous only)
Note: Since the marked.lexer does not
support custom extensions,
neither does this library. I would like to support this feature in the future.
Usage
The main component within this library is the Markdown
component.
Check out the Markdown tests and
Markdown snapshots to see
the default functionality.
Simple Example
import { render } from "react-dom";
import { Markdown } from "react-marked-renderer";
const markdown = `# Heading 1
This is some text that will be rendered as a paragraph.
Markdown defaults to the github-flavored markdown.
`;
render(<Markdown markdown={markdown} />, document.getElementById("root"));
Custom Renderers
Since the default renderers add no styles, you can define your own renderers to
add styles or additional functionality.
import { useState } from "react";
import { render } from "react-dom";
import {
DEFAULT_MARKDOWN_RENDERERS,
ListRenderer,
Markdown,
Renderers,
getTokensText,
} from "react-marked-renderer";
import { BrowserRouter as Router, Link } from "react-router-dom";
const renderers: Renderers = {
...DEFAULT_MARKDOWN_RENDERERS,
link: function CustomLink({ href, title, children }) {
return (
<Link to={href} title={title}>
{children}
</Link>
);
},
blockquote: function Blockquote({ children }) {
return <blockquote className="custom">{children}</blockquote>;
},
task: function Task({ defaultChecked, tokens, children }) {
const id = useSluggedId(`${getTokensText(tokens)}-task`);
const [checked, setChecked] = useState(defaultChecked);
return (
<li className="task-item">
<input
id={id}
checked={checked}
onChange={(event) => setChecked(event.currentTarget.checked)}
/>
<label htmlFor={d}>{children}</label>
</li>
);
},
list: function List(props) {
const renderers = useRenderers();
const { listitem: ListItem } = renderers;
const item = <ListItem>Content</ListItem>;
return <ListRenderer {...props} />;
},
};
render(
<Router>
<Markdown markdown={markdown} renderers={renderers} />
</Router>,
document.getElementById("root")
);
PrismJS Code Highlighting (Browser)
To be able to highlight code in the browser, provide a highlightElement
function that will modify a <code>
element to be highlighted:
import { render } from "react-dom";
import {
DEFAULT_MARKDOWN_RENDERERS,
Markdown,
Renderers,
} from "react-marked-renderer";
import Prism from "prismjs";
const renderers: Renderers = {
...DEFAULT_MARKDOWN_RENDERERS,
codespan: function CodeSpan({ children }) {
return <code className="language-none">{children}</code>;
},
};
render(
<Markdown
markdown={markdown}
renderers={renderers}
highlightElement={Prism.highlightElement}
/>,
document.getElementById("root")
);
PrismJS Code Highlighting (Node and Browser)
If you want to highlight code in a node environment or allow the code to be
highlighted for SSR and in the browser, provide a highlightCode
function:
import { render } from "react-dom";
import {
DEFAULT_MARKDOWN_RENDERERS,
DangerouslyHighlight,
GetCodeLanguage,
Markdown,
Renderers,
} from "react-marked-renderer";
import Prism from "prismjs";
const renderers: Renderers = {
...DEFAULT_MARKDOWN_RENDERERS,
codespan: function CodeSpan({ children }) {
return <code className="language-none">{children}</code>;
},
};
const getLanguage: GetCodeLanguage = (lang, _rawCode) => {
lang = lang === "sh" ? "shell" : lang;
if (!Prism.languages[lang]) {
return "none";
}
return lang;
};
const highlightCode: DangerouslyHighlightCode = (code, lang) =>
Prism.highlight(code, Prism.languages[lang], lang);
render(
<Markdown
markdown={markdown}
renderers={renderers}
getLanguage={getLanguage}
highlightCode={highlightCode}
/>,
document.getElementById("root")
);
What's the use-case?
This library mostly came up since I like to write documentation sites in
markdown, but also apply custom styles as well as linking to other documentation
pages using html5 history (no full page reloads).