UNPKG

html-react-parser

Version:
102 lines (86 loc) 2.89 kB
var React = require('react'); var attributesToProps = require('./attributes-to-props'); var utilities = require('./utilities'); /** * Converts DOM nodes to React elements. * * @param {Array} nodes - The DOM nodes. * @param {Object} [options] - The additional options. * @param {Function} [options.replace] - The replace method. * @return {ReactElement|Array} */ function domToReact(nodes, options) { options = options || {}; var result = []; var node; var isReplacePresent = typeof options.replace === 'function'; var replacement; var props; var children; for (var i = 0, len = nodes.length; i < len; i++) { node = nodes[i]; // replace with custom React element (if applicable) if (isReplacePresent) { replacement = options.replace(node); if (React.isValidElement(replacement)) { // specify a "key" prop if element has siblings // https://fb.me/react-warning-keys if (len > 1) { replacement = React.cloneElement(replacement, { key: replacement.key || i }); } result.push(replacement); continue; } } if (node.type === 'text') { result.push(node.data); continue; } props = node.attribs; if (!shouldPassAttributesUnaltered(node)) { // update values props = attributesToProps(node.attribs); } children = null; // node type for <script> is "script" // node type for <style> is "style" if (node.type === 'script' || node.type === 'style') { // prevent text in <script> or <style> from being escaped // https://facebook.github.io/react/tips/dangerously-set-inner-html.html if (node.children[0]) { props.dangerouslySetInnerHTML = { __html: node.children[0].data }; } } else if (node.type === 'tag') { // setting textarea value in children is an antipattern in React // https://reactjs.org/docs/forms.html#the-textarea-tag if (node.name === 'textarea' && node.children[0]) { props.defaultValue = node.children[0].data; // continue recursion of creating React elements (if applicable) } else if (node.children && node.children.length) { children = domToReact(node.children, options); } // skip all other cases (e.g., comment) } else { continue; } // specify a "key" prop if element has siblings // https://fb.me/react-warning-keys if (len > 1) { props.key = i; } result.push(React.createElement(node.name, props, children)); } return result.length === 1 ? result[0] : result; } function shouldPassAttributesUnaltered(node) { return ( utilities.PRESERVE_CUSTOM_ATTRIBUTES && node.type === 'tag' && utilities.isCustomComponent(node.name, node.attribs) ); } module.exports = domToReact;