-
-
Notifications
You must be signed in to change notification settings - Fork 135
/
Copy pathdom-to-react.js
93 lines (78 loc) · 2.59 KB
/
dom-to-react.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
'use strict';
/**
* Module dependencies.
*/
var React = require('react');
var attributesToProps = require('./attributes-to-props');
/**
* Convert 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, i); // i = key
if (React.isValidElement(replacement)) {
result.push(replacement);
continue;
}
}
if (node.type === 'text') {
result.push(node.data);
continue;
}
// update values
props = attributesToProps(node.attribs);
children = null;
// node type for script is "script" not "tag"
if (node.name === 'script' && node.children[0]) {
// prevent text in script tag from being escaped
// https://facebook.github.io/react/tips/dangerously-set-inner-html.html
props.dangerouslySetInnerHTML = {
__html: node.children[0].data
};
} else if (node.type === 'tag') {
// setting textarea value in children is an antipattern in React
// https://facebook.github.io/react/docs/forms.html#why-textarea-value
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)
);
}
if (result.length === 1) {
return result[0];
} else {
return result;
}
}
/**
* Export DOM to React parser.
*/
module.exports = domToReact;