Skip to content

Commit becc168

Browse files
Merge pull request #10 from remarkablemark/html-to-dom-client
Fix HTML to DOM client parser
2 parents 15cc84c + 8cd62a8 commit becc168

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
* @return {ReactElement|Array}
5252
*/
5353
function HTMLReactParser(html, options) {
54+
if (typeof html !== 'string') {
55+
throw new Error('`HTMLReactParser`: The first argument must be a string.');
56+
}
5457
return domToReact(htmlToDOM(html), options);
5558
}
5659

lib/html-to-dom-client.js

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,22 +102,45 @@ function formatDOM(nodes, parentNode) {
102102
* @return {Object} - The DOM nodes.
103103
*/
104104
function htmlToDOMClient(html) {
105-
var root;
105+
var match = typeof html === 'string' ? html.match(/<(.+?)>/) : null;
106+
var tagName;
107+
var parentNode;
108+
var nodes;
109+
110+
if (match && typeof match[1] === 'string') {
111+
tagName = match[1].toLowerCase();
112+
}
106113

107114
// `DOMParser` can parse full HTML
108115
// https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
109-
if (window.DOMParser) {
116+
if (tagName && window.DOMParser) {
110117
var parser = new window.DOMParser();
111-
root = parser.parseFromString(html, 'text/html');
118+
var doc = parser.parseFromString(html, 'text/html');
119+
120+
// <head> and <body> are siblings
121+
if (tagName === 'head' || tagName === 'body') {
122+
nodes = doc.getElementsByTagName(tagName);
123+
124+
// document's child nodes
125+
} else if (tagName === 'html') {
126+
nodes = doc.childNodes;
127+
128+
// get the element's parent's child nodes
129+
// do this in case of adjacent elements
130+
} else {
131+
parentNode = doc.getElementsByTagName(tagName)[0].parentNode;
132+
nodes = parentNode.childNodes;
133+
}
112134

113135
// otherwise, use `innerHTML`
114136
// but this will strip out tags like <html> and <body>
115137
} else {
116-
root = document.createElement('div');
117-
root.innerHTML = html;
138+
parentNode = document.createElement('div');
139+
parentNode.innerHTML = html;
140+
nodes = parentNode.childNodes;
118141
}
119142

120-
return formatDOM(root.childNodes);
143+
return formatDOM(nodes);
121144
}
122145

123146
/**

test/html-to-react.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ describe('html-to-react', function() {
2929
*/
3030
describe('parser', function() {
3131

32+
it('throws an error if first argument is not a string', function() {
33+
assert.throws(function() { Parser(); });
34+
35+
[undefined, null, {}, [], 42].forEach(function(arg) {
36+
assert.throws(function() { Parser(arg); });
37+
});
38+
});
39+
40+
it('returns string if cannot be parsed to HTML', function() {
41+
assert.equal(Parser('foo'), 'foo');
42+
});
43+
3244
it('converts single HTML element to React', function() {
3345
var html = data.html.single;
3446
var reactElement = Parser(html);

0 commit comments

Comments
 (0)