@readme/markdown
Version:
ReadMe's React-based Markdown parser
70 lines (56 loc) • 1.68 kB
JSX
/* eslint-disable no-eval
*/
const escape = require('lodash.escape');
const PropTypes = require('prop-types');
const React = require('react');
const MATCH_SCRIPT_TAGS = /<script\b[^>]*>([\s\S]*?)<\/script *>\n?/gim;
const extractScripts = (html = '') => {
const scripts = [];
let match;
while ((match = MATCH_SCRIPT_TAGS.exec(html)) !== null) {
scripts.push(match[1]);
}
const cleaned = html.replace(MATCH_SCRIPT_TAGS, '');
return [cleaned, () => scripts.map(js => window.eval(js))];
};
class HTMLBlock extends React.PureComponent {
constructor(props) {
super(props);
[this.html, this.exec] = extractScripts(this.props.html);
}
componentDidMount() {
const { runScripts } = this.props;
if (typeof window !== 'undefined' && (runScripts === '' || runScripts)) this.exec();
}
render() {
const { html, safeMode } = this.props;
if (safeMode) {
return (
<pre className="html-unsafe">
<code dangerouslySetInnerHTML={{ __html: escape(html) }} />
</pre>
);
}
return <div className="rdmd-html" dangerouslySetInnerHTML={{ __html: this.html }} />;
}
}
HTMLBlock.defaultProps = {
runScripts: false,
safeMode: false,
};
HTMLBlock.propTypes = {
html: PropTypes.string,
runScripts: PropTypes.any,
safeMode: PropTypes.bool,
};
const CreateHtmlBlock =
({ safeMode }) =>
// eslint-disable-next-line react/display-name
props =>
<HTMLBlock {...props} safeMode={safeMode} />;
CreateHtmlBlock.sanitize = schema => {
schema.tagNames.push('html-block');
schema.attributes['html-block'] = ['html', 'runScripts'];
return schema;
};
module.exports = CreateHtmlBlock;