Create React components out of Remark.
More practically: render React components from Markdown formatted text, with emoji support ✨
Supports:
- Creating a React component – ready to be rendered – from an existing Remark processor pipeline.
- Optionally transforming emoji :shortcodes: to unicode.
- Sanitizing the Markdown text input.
- Setting a custom top-level class name.
npm install --save github:lookback/remark-react-component
import unified from 'unified';
import markdown from 'remark-parse';
import { createComponentFromProcessor } from 'remark-react-component';
import { emojis } from 'remark-react-component/emojis';
import React from 'react';
import { render } from 'react-dom';
const processor = unified()
// This is the Markdown parser
.use(markdown)
.use(emojis);
// You may use any other Unified plugins here..
const App = () => {
const MyMarkdownComponent = createComponentFromProcessor(processor);
return <MyMarkdownComponent text="# Hi there :smile:" />;
};
render(<App />, document.getElementbyId('app'));
We provide an ES6 style build in the es6
sub-directory:
import { createComponentFromProcessor } from 'remark-react-component/build/es6';
// Do stuff..
Factory function for creating a React component from a processor.
import { Node } from 'unist';
import { createComponentFromProcessor } from 'remark-react-component';
function createComponentFromProcessor(
processor: unified.Processor,
options?: Options): React.ComponentType<Props>;
interface Props {
text: string | null;
wrapIn?: string;
className?: string;
transformers?: ((node: Node) => void)[];
}
interface Options {
createElement?: CreateElement;
components?: {
[key: string]: React.ComponentType;
};
sanitizeSchema?: any;
}
You must hook on the remark-parse
function in the processor use()
function. This is because this module works off of the mdast produced by remark-parse
.
Provide a custom function for creating the component, based on the Remark processor output. Defaults to React.createElement
.
Override the default HTML elements. Example:
const processor = unified.use(markdown);
const MyH1 = (props) => <h1 className="my-h1">{props.children}</h1>;
const Markdown = createComponentFromProcessor(processor, {
components: {
// Overrides `h1` with `MyH1`
h1: MyH1
}
})
An object passed directly to the sanitize
function, configuring how to sanitize the incoming Markdown.
Defaults to GitHub's schema.
Required. The text to parse.
If specified, we'll wrap the parsed Markdown in this element.
If specified, we'll add this class to a wrapper div
around the parsed Markdown.
An optional array of Transformers on the parsed MDAST. Use this to walk the AST and modify it. See src/transformers/emoji-transformer.ts
for an example. You can use the unist-util-visit
to traverse the tree.
Read more in the Unified README.
We'll apply each transformer in the array (in order) to the newly parsed MDAST, from remark-parse
.
We don't provide emoji support as default, since we wanna keep the default bundle size low. But you can import the code needed from this module and plug it in yourself:
import unified from 'unified';
import markdown from 'remark-parse';
import { emojis, addEmojiClasses } from 'remark-react-component/emojis';
const processor = unified()
.use(markdown)
// Parses emojis from text
.use(emojis);
const MyMarkdownComponent = createComponentFromProcessor(processor, {
// The emoji transformer adds appropriate class names to the emojis
// so you can target them with CSS.
transformers: [addEmojiClasses()]
})
Adds support for finding emojis from text. Essentially a tokenizer plugin for Unified.
import { emojis } from 'remark-react-component/emojis';
function emojis(options?: TokenizerOptions): void;
Takes an options object as second parameter to the Unified use
function.
interface TokenizerOptions {
/** What HTML tag each emoji should be wrapped with. */
tag: string;
}
unified()
.use(markdown)
// Specify options as second argument to `use`:
.use(emojis, {
tag: 'strong'
});
Adds appropriate class names to the parsed emojis. It's essentially a transformer function which traverses the MDAST.
import { Node } from 'unist';
import { addEmojiClasses } from 'remark-react-component/emojis';
function addEmojiClasses(options?: Options): (tree: Node) => void;
interface Options {
/** Class name for each wrapped emoji. */
className?: string;
/**
* Class name for each wrapped emoji where the parent paragraph solely
* consists of emojis.
*/
classNameForOnlyEmojis?: string;
}
Provide a string class name to be added to each parsed emoji. Defaults to emoji
.
Provide a string class name to be added to each emoji when the parent paragraph only consists of emojis.
Example
This input text:
😏😄
would result in:
<span class="emoji emoji-large">😏</span>
<span class="emoji emoji-large">😄</span>
npm test
See tests
directory.