Skip to content

Commit 58e81cc

Browse files
Merge pull request #5 from remarkablemark/refactor-html-to-dom
Refactor HTML to DOM modules and environment detection logic
2 parents 22a3cc1 + cfeaea5 commit 58e81cc

File tree

7 files changed

+88
-80
lines changed

7 files changed

+88
-80
lines changed

index.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,21 @@
33
/**
44
* Module dependencies.
55
*/
6-
var htmlToDOM = require('./lib/html-to-dom');
76
var domToReact = require('./lib/dom-to-react');
7+
var htmlToDOM;
8+
9+
/**
10+
* Detect environment.
11+
*/
12+
13+
/** Client (Browser). */
14+
if (typeof window !== 'undefined' && this === window) {
15+
htmlToDOM = require('./html-to-dom-client');
16+
17+
/** Server (Node). */
18+
} else {
19+
htmlToDOM = require('./lib/html-to-dom-server');
20+
}
821

922
/**
1023
* Convert HTML to React.
@@ -14,11 +27,6 @@ var domToReact = require('./lib/dom-to-react');
1427
* @param {Function} [options.replace] - The replace method.
1528
* @return {ReactElement|Array}
1629
*/
17-
function htmlToReact(html, options) {
30+
module.exports = function(html, options) {
1831
return domToReact(htmlToDOM(html), options);
19-
}
20-
21-
/**
22-
* Export HTML to React parser.
23-
*/
24-
module.exports = htmlToReact;
32+
};

lib/html-to-dom-client.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,32 @@ function formatDOM(nodes, parentNode) {
9595
}
9696

9797
/**
98-
* Export HTML to DOM client helper.
98+
* Parse HTML string to DOM nodes.
99+
* This uses the browser DOM API.
100+
*
101+
* @param {String} html - The HTML.
102+
* @return {Object} - The DOM nodes.
103+
*/
104+
function htmlToDOMClient(html) {
105+
var root;
106+
107+
// `DOMParser` can parse full HTML
108+
// https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
109+
if (window.DOMParser) {
110+
var parser = new window.DOMParser();
111+
root = parser.parseFromString(html, 'text/html');
112+
113+
// otherwise, use `innerHTML`
114+
// but this will strip out tags like <html> and <body>
115+
} else {
116+
root = document.createElement('div');
117+
root.innerHTML = html;
118+
}
119+
120+
return formatDOM(root.childNodes);
121+
}
122+
123+
/**
124+
* Export HTML to DOM parser (client).
99125
*/
100-
module.exports = formatDOM;
126+
module.exports = htmlToDOMClient;

lib/html-to-dom-server.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
/**
4+
* Module dependencies.
5+
*/
6+
var Parser = require('htmlparser2/lib/Parser');
7+
var DomHandler = require('domhandler');
8+
9+
/**
10+
* Parse HTML string to DOM nodes.
11+
* This is the same method as `require('htmlparser2').parseDOM`.
12+
*
13+
* @param {String} html - The HTML.
14+
* @param {Object} options - The parser options.
15+
* @return {Object} - The DOM nodes.
16+
*/
17+
function htmlToDOMServer(html, options) {
18+
var handler = new DomHandler(options);
19+
new Parser(handler, options).end(html);
20+
return handler.dom;
21+
}
22+
23+
/**
24+
* Export HTML to DOM parser (server).
25+
*/
26+
module.exports = htmlToDOMServer;

lib/html-to-dom.js

Lines changed: 0 additions & 53 deletions
This file was deleted.

test/attributes-to-props.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('attributes to props helper', function() {
2626
{
2727
className: 'ic',
2828
htmlFor: 'tran',
29-
httpEquiv: 'refresh',
29+
httpEquiv: 'refresh'
3030
}
3131
);
3232
});

test/dom-to-react.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
var assert = require('assert');
77
var React = require('react');
8-
var htmlToDOM = require('../lib/html-to-dom');
8+
var htmlToDOMServer = require('../lib/html-to-dom-server');
99
var domToReact = require('../lib/dom-to-react');
1010
var data = require('./data');
1111

@@ -16,7 +16,7 @@ describe('dom-to-react parser', function() {
1616

1717
it('converts single DOM node to React', function() {
1818
var html = data.html.single;
19-
var reactElement = domToReact(htmlToDOM(html));
19+
var reactElement = domToReact(htmlToDOMServer(html));
2020
assert(React.isValidElement(reactElement));
2121
assert.deepEqual(
2222
reactElement,
@@ -26,7 +26,7 @@ describe('dom-to-react parser', function() {
2626

2727
it('converts multiple DOM nodes to React', function() {
2828
var html = data.html.multiple;
29-
var reactElements = domToReact(htmlToDOM(html));
29+
var reactElements = domToReact(htmlToDOMServer(html));
3030
reactElements.forEach(function(reactElement) {
3131
assert(React.isValidElement(reactElement));
3232
assert(reactElement.key);
@@ -43,7 +43,7 @@ describe('dom-to-react parser', function() {
4343
// https://facebook.github.io/react/docs/forms.html#why-textarea-value
4444
it('converts <textarea> correctly', function() {
4545
var html = data.html.textarea;
46-
var reactElement = domToReact(htmlToDOM(html));
46+
var reactElement = domToReact(htmlToDOMServer(html));
4747
assert(React.isValidElement(reactElement));
4848
assert.deepEqual(
4949
reactElement,
@@ -55,7 +55,7 @@ describe('dom-to-react parser', function() {
5555

5656
it('converts <script> correctly', function() {
5757
var html = data.html.script;
58-
var reactElement = domToReact(htmlToDOM(html));
58+
var reactElement = domToReact(htmlToDOMServer(html));
5959
assert(React.isValidElement(reactElement));
6060
assert.deepEqual(
6161
reactElement,
@@ -69,7 +69,7 @@ describe('dom-to-react parser', function() {
6969

7070
it('skips HTML comments', function() {
7171
var html = [data.html.single, data.html.comment, data.html.single].join('');
72-
var reactElements = domToReact(htmlToDOM(html));
72+
var reactElements = domToReact(htmlToDOMServer(html));
7373
reactElements.forEach(function(reactElement) {
7474
assert(React.isValidElement(reactElement));
7575
assert(reactElement.key);

test/html-to-dom.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ var assert = require('assert');
77
var util = require('util');
88
var jsdomify = require('jsdomify').default;
99
var htmlparser = require('htmlparser2');
10-
var parseDOM = require('../lib/html-to-dom');
11-
var formatDOM = require('../lib/html-to-dom-client');
10+
var htmlToDOMServer = require('../lib/html-to-dom-server');
11+
var htmlToDOMClient = require('../lib/html-to-dom-client');
1212
var helpers = require('./helpers/');
1313
var data = require('./data');
1414

@@ -26,7 +26,7 @@ describe('html-to-dom', function() {
2626
var html = data.html.complex;
2727
// use `util.inspect` to resolve circular references
2828
assert.equal(
29-
util.inspect(parseDOM(html), { showHidden: true, depth: null }),
29+
util.inspect(htmlToDOMServer(html), { showHidden: true, depth: null }),
3030
util.inspect(htmlparser.parseDOM(html), { showHidden: true, depth: null })
3131
);
3232
});
@@ -48,13 +48,14 @@ describe('html-to-dom', function() {
4848
jsdomify.destroy();
4949
});
5050

51-
it('formats the nodes like `htmlparser2.parseDOM`', function() {
52-
var html = data.html.attributes + data.html.nested + data.html.comment + data.html.script;
53-
var root = document.createElement('div');
54-
root.innerHTML = html;
55-
var clientNodes = formatDOM(root.childNodes);
56-
var serverNodes = parseDOM(html);
57-
helpers.deepEqualCircular(clientNodes, serverNodes);
51+
it('outputs the same result as the server parser', function() {
52+
var html = (
53+
data.html.attributes +
54+
data.html.nested +
55+
data.html.comment +
56+
data.html.script
57+
);
58+
helpers.deepEqualCircular(htmlToDOMClient(html), htmlToDOMServer(html));
5859
});
5960

6061
});

0 commit comments

Comments
 (0)