├── .gitignore
├── README.md
├── example
└── parser.js
├── htmlparser2-react.js
├── lib
└── index.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | react-htmlparser2
2 | ================
3 |
4 | Parses raw html use htmlparser2 to a React DOM structure.
5 |
6 | This package is now agnostic, sort of tested in .13.3. If it doesn't work well fix it?
7 |
8 | So the process for now is
9 | ```
10 | npm install react-htmlparser2
11 | npm install react
12 | ```
13 |
14 | Quick example
15 | ```javascript
16 | var reactParser = require('htmlparser2-react'),
17 | React = require('react');
18 |
19 |
20 | var html = '
';
21 |
22 | var parsedComponent = reactParser(html, React);
23 |
24 |
25 | console.log(html == React.renderToStaticMarkup(parsedComponent));
26 | //logs true
27 | ```
28 |
29 |
30 | This by no means takes into account everything, like CData, no special cases for script tags, other stuff that I have no idea about.
31 |
32 | It can be browserified for ES5 compliant browsers.
33 |
34 | There are likely more elegant solutions, like actually hooking into htmlparser2 DOMHandler thus not parsing to an object then converting to React but I can do that later.
35 |
36 |
37 | Should you use this? No.
38 |
39 | Why would you use this? Maybe you don't want dangerously set innerhtml?
40 |
41 | Have fun
42 |
43 | Log issues if you find any, I'm sure there are
44 |
--------------------------------------------------------------------------------
/example/parser.js:
--------------------------------------------------------------------------------
1 | var React = require('react'),
2 | reactParser = require('./../lib/index');
3 |
4 |
5 | var html = '';
6 |
7 | var parsedComponent = reactParser(html, React);
8 |
9 | console.log('Original : ' + html);
10 | console.log('Converted: ' + React.renderToStaticMarkup(parsedComponent));
11 | console.log(html == React.renderToStaticMarkup(parsedComponent));
--------------------------------------------------------------------------------
/htmlparser2-react.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib/index');
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | var htmlparser = require('htmlparser2');
2 | var React;
3 |
4 | function parse(html, R) {
5 | React = R;
6 | return traverseToReact(parseHtmlToObj(html)[0]);
7 | }
8 |
9 | function traverseToReact(obj) {
10 | if (Array.isArray(obj)) {
11 | obj = obj[0];
12 | }
13 |
14 | var type = obj.type,
15 | tagName = obj.name,
16 | children = obj.children,
17 | comp,
18 | tagArray = [tagName];
19 |
20 | if (type == 'tag') {
21 | comp = React.createElement.apply(null, tagArray.concat(buildArgs(obj.attribs)).concat(children.map(traverseToReact)));
22 | } else if (type == 'text' ) {
23 | comp = obj.data;
24 | }
25 | return comp;
26 | }
27 |
28 | function buildArgs(obj) {
29 | if (isEmptyObject(obj)) {
30 | return null;
31 | }
32 | var key,
33 | attribObj = {},
34 | regularKeys = /(data-||aria-)?/;
35 |
36 | for (key in obj) {
37 | if (key == 'class') {
38 | attribObj.className = obj[key];
39 | } else if (key == 'style') {
40 | attribObj.style = parseStyle(obj[key].split(';'));
41 | } else if (key.match(regularKeys)[1]) {
42 | attribObj[key] = obj[key];
43 | } else if (key == 'for') {
44 | attribObj.htmlFor = obj[key];
45 | } else {
46 | attribObj[camelCase(key)] = obj[key];
47 | }
48 | }
49 | return attribObj;
50 | }
51 | function isEmptyObject(obj) {
52 | return Object.getOwnPropertyNames(obj).length === 0;
53 | }
54 | function parseStyle(styles) {
55 | var styleObj = {},
56 | styleSplit;
57 | if (!styles.length || !Array.isArray(styles)) {
58 | return {};
59 | }
60 |
61 | styles.forEach(function(style) {
62 | if (!style) {
63 | return;
64 | }
65 | styleSplit = style.split(':');
66 | styleObj[camelCase(styleSplit[0])] = styleSplit[1];
67 | });
68 | return styleObj;
69 | }
70 | function camelCase(input) {
71 | return input.toLowerCase().replace(/-(.)/g, function(match, group1) {
72 | return group1.toUpperCase();
73 | });
74 | }
75 |
76 | function parseHtmlToObj(html) {
77 | var handler = new htmlparser.DomHandler();
78 | var parser = new htmlparser.Parser(handler , { decodeEntities:true });
79 | parser.parseComplete(html);
80 | return handler.dom;
81 | }
82 |
83 | module.exports = parse;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-htmlparser2",
3 | "version": "0.1.0",
4 | "description": "Convert raw html to react DOM components",
5 | "keywords": [
6 | "react",
7 | "htmlparser2",
8 | "react-component"
9 | ],
10 | "main": "htmlparser2-react.js",
11 | "scripts": {
12 | "test": "echo \"Error: no test specified\" && exit 1"
13 | },
14 | "author": "Jason Brown",
15 | "license": "MIT",
16 | "dependencies": {
17 | "htmlparser2": "^3.8.3"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "https://github.com/browniefed/htmlparser2-react.git"
22 | },
23 | "homepage": "http://github.com/browniefed/htmlparser2-react",
24 | "github": "http://github.com/browniefed/htmlparser2-react",
25 | "bugs": "http://github.com/browniefed/htmlparser2-react/issues"
26 | }
27 |
--------------------------------------------------------------------------------