UNPKG

html-react-parser

Version:
122 lines 5.08 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = domToReact; var react_1 = require("react"); var attributes_to_props_1 = __importDefault(require("./attributes-to-props")); var utilities_1 = require("./utilities"); var React = { cloneElement: react_1.cloneElement, createElement: react_1.createElement, isValidElement: react_1.isValidElement, }; /** * Converts DOM nodes to JSX element(s). * * @param nodes - DOM nodes. * @param options - Options. * @returns - String or JSX element(s). */ function domToReact(nodes, options) { if (options === void 0) { options = {}; } var reactElements = []; var hasReplace = typeof options.replace === 'function'; var transform = options.transform || utilities_1.returnFirstArg; var _a = options.library || React, cloneElement = _a.cloneElement, createElement = _a.createElement, isValidElement = _a.isValidElement; var nodesLength = nodes.length; for (var index = 0; index < nodesLength; index++) { var node = nodes[index]; // replace with custom React element (if present) if (hasReplace) { var replaceElement = options.replace(node, index); if (isValidElement(replaceElement)) { // set "key" prop for sibling elements // https://react.dev/learn/rendering-lists#rules-of-keys if (nodesLength > 1) { replaceElement = cloneElement(replaceElement, { key: replaceElement.key || index, }); } reactElements.push(transform(replaceElement, node, index)); continue; } } if (node.type === 'text') { var isWhitespace = !node.data.trim().length; // We have a whitespace node that can't be nested in its parent // so skip it if (isWhitespace && node.parent && !(0, utilities_1.canTextBeChildOfNode)(node.parent)) { continue; } // Trim is enabled and we have a whitespace node // so skip it if (options.trim && isWhitespace) { continue; } // We have a text node that's not whitespace and it can be nested // in its parent so add it to the results reactElements.push(transform(node.data, node, index)); continue; } var element = node; var props = {}; if (skipAttributesToProps(element)) { (0, utilities_1.setStyleProp)(element.attribs.style, element.attribs); props = element.attribs; } else if (element.attribs) { props = (0, attributes_to_props_1.default)(element.attribs, element.name); } var children = void 0; switch (node.type) { case 'script': case 'style': // prevent text in <script> or <style> from being escaped // https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html if (node.children[0]) { props.dangerouslySetInnerHTML = { __html: node.children[0].data, }; } break; case 'tag': // setting textarea value in children is an antipattern in React // https://react.dev/reference/react-dom/components/textarea#caveats if (node.name === 'textarea' && node.children[0]) { props.defaultValue = node.children[0].data; } else if (node.children && node.children.length) { // continue recursion of creating React elements (if applicable) children = domToReact(node.children, options); } break; // skip all other cases (e.g., comment) default: continue; } // set "key" prop for sibling elements // https://react.dev/learn/rendering-lists#rules-of-keys if (nodesLength > 1) { props.key = index; } reactElements.push(transform(createElement(node.name, props, children), node, index)); } return reactElements.length === 1 ? reactElements[0] : reactElements; } /** * Determines whether DOM element attributes should be transformed to props. * Web Components should not have their attributes transformed except for `style`. * * @param node - Element node. * @returns - Whether the node attributes should be converted to props. */ function skipAttributesToProps(node) { return (utilities_1.PRESERVE_CUSTOM_ATTRIBUTES && node.type === 'tag' && (0, utilities_1.isCustomComponent)(node.name, node.attribs)); } //# sourceMappingURL=dom-to-react.js.map