react-markdown
Version:
Renders Markdown as React components
135 lines (103 loc) • 4.42 kB
JavaScript
;
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
var xtend = require('xtend');
var unified = require('unified');
var parse = require('remark-parse');
var PropTypes = require('prop-types');
var addListMetadata = require('mdast-add-list-metadata');
var naiveHtml = require('./plugins/naive-html');
var disallowNode = require('./plugins/disallow-node');
var astToReact = require('./ast-to-react');
var wrapTableRows = require('./wrap-table-rows');
var getDefinitions = require('./get-definitions');
var uriTransformer = require('./uri-transformer');
var defaultRenderers = require('./renderers');
var symbols = require('./symbols');
var allTypes = Object.keys(defaultRenderers);
var ReactMarkdown = function ReactMarkdown(props) {
var src = props.source || props.children || '';
var parserOptions = props.parserOptions;
if (props.allowedTypes && props.disallowedTypes) {
throw new Error('Only one of `allowedTypes` and `disallowedTypes` should be defined');
}
var renderers = xtend(defaultRenderers, props.renderers);
var plugins = [[parse, parserOptions]].concat(props.plugins || []);
var parser = plugins.reduce(applyParserPlugin, unified());
var rawAst = parser.parse(src);
var renderProps = xtend(props, {
renderers: renderers,
definitions: getDefinitions(rawAst)
});
var astPlugins = determineAstPlugins(props); // eslint-disable-next-line no-sync
var transformedAst = parser.runSync(rawAst);
var ast = astPlugins.reduce(function (node, plugin) {
return plugin(node, renderProps);
}, transformedAst);
return astToReact(ast, renderProps);
};
function applyParserPlugin(parser, plugin) {
return Array.isArray(plugin) ? parser.use.apply(parser, _toConsumableArray(plugin)) : parser.use(plugin);
}
function determineAstPlugins(props) {
var plugins = [wrapTableRows, addListMetadata()];
var disallowedTypes = props.disallowedTypes;
if (props.allowedTypes) {
disallowedTypes = allTypes.filter(function (type) {
return type !== 'root' && props.allowedTypes.indexOf(type) === -1;
});
}
var removalMethod = props.unwrapDisallowed ? 'unwrap' : 'remove';
if (disallowedTypes && disallowedTypes.length > 0) {
plugins.push(disallowNode.ofType(disallowedTypes, removalMethod));
}
if (props.allowNode) {
plugins.push(disallowNode.ifNotMatch(props.allowNode, removalMethod));
}
var renderHtml = !props.escapeHtml && !props.skipHtml;
var hasHtmlParser = (props.astPlugins || []).some(function (item) {
var plugin = Array.isArray(item) ? item[0] : item;
return plugin.identity === symbols.HtmlParser;
});
if (renderHtml && !hasHtmlParser) {
plugins.push(naiveHtml);
}
return props.astPlugins ? plugins.concat(props.astPlugins) : plugins;
}
ReactMarkdown.defaultProps = {
renderers: {},
escapeHtml: true,
skipHtml: false,
sourcePos: false,
rawSourcePos: false,
transformLinkUri: uriTransformer,
astPlugins: [],
plugins: [],
parserOptions: {}
};
ReactMarkdown.propTypes = {
className: PropTypes.string,
source: PropTypes.string,
children: PropTypes.string,
sourcePos: PropTypes.bool,
rawSourcePos: PropTypes.bool,
escapeHtml: PropTypes.bool,
skipHtml: PropTypes.bool,
allowNode: PropTypes.func,
allowedTypes: PropTypes.arrayOf(PropTypes.oneOf(allTypes)),
disallowedTypes: PropTypes.arrayOf(PropTypes.oneOf(allTypes)),
transformLinkUri: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
linkTarget: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
transformImageUri: PropTypes.func,
astPlugins: PropTypes.arrayOf(PropTypes.func),
unwrapDisallowed: PropTypes.bool,
renderers: PropTypes.object,
plugins: PropTypes.array,
parserOptions: PropTypes.object
};
ReactMarkdown.types = allTypes;
ReactMarkdown.renderers = defaultRenderers;
ReactMarkdown.uriTransformer = uriTransformer;
module.exports = ReactMarkdown;