Skip to content

Commit 97ce98a

Browse files
Prevent <script> from being escaped by React
Use `dangerouslySetInnerHTML` to prevent the text in the script tag from being escaped by React. Create test to check logic in DOM to React parser.
1 parent 115466b commit 97ce98a

File tree

3 files changed

+39
-16
lines changed

3 files changed

+39
-16
lines changed

lib/dom-to-react.js

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,15 @@ function domToReact(nodes) {
2626

2727
children = null;
2828

29-
if (node.type === 'tag') {
29+
// node type for script is "script" not "tag"
30+
if (node.name === 'script' && node.children[0]) {
31+
// prevent text in script tag from being escaped
32+
// https://facebook.github.io/react/tips/dangerously-set-inner-html.html
33+
node.attribs.dangerouslySetInnerHTML = {
34+
__html: node.children[0].data
35+
};
36+
37+
} else if (node.type === 'tag') {
3038
// setting textarea value in children is an antipattern in React
3139
// https://facebook.github.io/react/docs/forms.html#why-textarea-value
3240
if (node.name === 'textarea' && node.children[0]) {
@@ -36,21 +44,21 @@ function domToReact(nodes) {
3644
// continue recursion of creating React elements
3745
children = domToReact(node.children);
3846
}
47+
}
3948

40-
// specify a `key` prop if returning an array
41-
// https://fb.me/react-warning-keys
42-
if (len > 1) {
43-
node.attribs.key = i;
44-
}
45-
46-
result.push(
47-
React.createElement(
48-
node.name,
49-
node.attribs,
50-
children
51-
)
52-
);
49+
// specify a `key` prop if returning an array
50+
// https://fb.me/react-warning-keys
51+
if (len > 1) {
52+
node.attribs.key = i;
5353
}
54+
55+
result.push(
56+
React.createElement(
57+
node.name,
58+
node.attribs,
59+
children
60+
)
61+
);
5462
}
5563

5664
if (result.length === 1) {

test/data.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"single": "<p>foo</p>",
44
"multiple": "<p>foo</p><p>bar</p>",
55
"complex": "<html><head><title>Title</title></head><body><header id=\"header\">Header</header><h1>Heading</h1><p>Paragraph</p><div class=\"class1 class2\">Some <em>text</em>.</div><script>alert();</script></body></html>",
6-
"textarea": "<textarea>foo</textarea>"
6+
"textarea": "<textarea>foo</textarea>",
7+
"script": "<script>alert(1 < 2);</script>"
78
}
89
}

test/dom-to-react.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ describe('dom-to-react parser', function() {
4141
});
4242

4343
// https://facebook.github.io/react/docs/forms.html#why-textarea-value
44-
it('converts textarea correctly', function() {
44+
it('converts <textarea> correctly', function() {
4545
var html = data.html.textarea;
4646
var reactElement = domToReact(htmlToDOM(html));
4747
assert(React.isValidElement(reactElement));
@@ -53,4 +53,18 @@ describe('dom-to-react parser', function() {
5353
);
5454
});
5555

56+
it('converts <script> correctly', function() {
57+
var html = data.html.script;
58+
var reactElement = domToReact(htmlToDOM(html));
59+
assert(React.isValidElement(reactElement));
60+
assert.deepEqual(
61+
reactElement,
62+
React.createElement('script', {
63+
dangerouslySetInnerHTML: {
64+
__html: 'alert(1 < 2);'
65+
}
66+
}, null)
67+
);
68+
});
69+
5670
});

0 commit comments

Comments
 (0)