I have my documentation written in markdown and I would like to render those files from my JSX (ES6+CommonJS) code into React components. How can I achieve this?
For example I have styles.markdown and I would like to render it into a <p> tag.
You can use React-Markdown:
const React = require('react')
const ReactDOM = require('react-dom')
const ReactMarkdown = require('react-markdown')
const input = '# This is a header\n\nAnd this is a paragraph'
ReactDOM.render(<ReactMarkdown source={input} />, document.getElementById('container'))
Or... You can just create a simple React component that wraps a call to a Markdown parser. There are two very good ones for JavaScript:
Now, you can create a component like this:
var MarkdownViewer = React.createClass({
render: function() {
// pseudo code here, depends on the parser
var markdown = markdown.parse(this.props.markdown);
return <div dangerouslySetInnerHTML={{__html:markdown}} />;
}
});
There used to have one already, but it doesn't seem to be maintained anymore: https://github.com/tcoopman/markdown-react
Also, if you need a React Markdown Editor, check out: react-mde. Disclaimer: I am the author.
dangerouslySetInnerHTML={{__html: markdown}}). Also, even though it might not be relevant to the question asked here, it is worth noting that one is well advised to have the markdown library sanitize the input to avoid XSS, if any of it is potentially untrusted (e.g. var markdown = marked.parse(this.props.markdown, {sanitize: true});).dangerouslySetInnerHTML inefficient when the component re-renders?source={...} is obsolete. In the current version it is - <ReactMarkdown children={ ... }/>The package react-markdown with Markdown component will be good choice:
import React from 'react'
import Markdown from 'react-markdown'
var src = "# This is markdown document"
React.render(
<Markdown children={src} />,
document.getElementById('root')
)
You can write inplace here-docs like this:
<Markdown>
# Header
* dotted lists
* [url](/doc)
</Markdown>
It is possible to specify transformers for link-urls and image-urls and much more.
.md file in javascript unless you have the proper loader, but you can easily put the markdown into a string and import it that way.I'm a little late to the party, but I wrote a competitor library to the ones mentioned above that has an added benefit of not needing the dangerouslySetInnerHtml hack: https://github.com/probablyup/markdown-to-jsx
react-markdown and markdown-to-jsx today. Long story short: markdown-to-jsx is 5 times lighter, and it was much easier to configure it to open _blank links with safe noopener defaults. See github.com/probablyup/markdown-to-jsx/issues/… (I basically didn't success at doing that with react-markdown)Example of Markdown component that renders html from markdown text, the logic of loading data should be implemented in separate store/parent component/whatever. I am using marked package for converting markdown to html.
import React from 'react';
import marked from 'marked';
export default class MarkdownElement extends React.Component {
constructor(props) {
super(props);
marked.setOptions({
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: true,
smartLists: true,
smartypants: false
});
}
render() {
const { text } = this.props,
html = marked(text || '');
return (<div>
<div dangerouslySetInnerHTML={{__html: html}} />
</div>);
}
}
MarkdownElement.propTypes = {
text: React.PropTypes.string.isRequired
};
MarkdownElement.defaultProps = {
text: ''
};
Try something like this:
import fs from 'fs';
import React, { Component, PropTypes } from 'react';
class Markdown extends Component {
constructor() {
super(props);
this.state = { contents: '' };
this.componentDidMount = this.componentDidMount.bind(this);
}
componentDidMount() {
const contents = fs.readFileSync(this.props.path, 'utf8');
this.setState({ contents });
}
render()
return (
<div>
{this.state.contents.split('\n').map((line, i) =>
line ? <p key={i}>{line}</p> : <br key={i} />)}
</div>
);
}
}
Markdown.propTypes = { path: PropTypes.string.isRequired };
React.render(<Markdown path='./README.md' />, document.body);
Or if you're using ES7+ features:
import fs from 'fs';
import React, { Component, PropTypes } from 'react';
class Markdown extends Component {
static propTypes = { path: PropTypes.string.isRequired };
state = { contents: '' };
componentDidMount = () => {
const contents = fs.readFileSync(this.props.path, 'utf8');
this.setState({ contents });
};
render() {
return (
<div>
{this.state.contents.split('\n').map((line, i) =>
line ? <p key={i}>{line}</p> : <br key={i} />)}
</div>
);
}
}
React.render(<Markdown path='./README.md' />, document.body);
You'll need to use the brfs transform to be able to use fs.readFileSync if this is running client-side.
styles.markdown?