├── .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 = '

hey this is a paragraph

  • 1
  • 2
  • 3
'; 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 = '

hey this is a paragraph

  • 1
  • 2
  • 3
'; 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 | --------------------------------------------------------------------------------