diff --git a/.babelrc b/.babelrc index 008d06b..3085ce7 100644 --- a/.babelrc +++ b/.babelrc @@ -4,6 +4,7 @@ "es2015" ], "plugins": [ - "transform-object-assign" + "transform-object-assign", + "transform-object-rest-spread" ] } \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index d01c6ee..0ce95b7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -5,7 +5,7 @@ "sourceType": "module", "ecmaFeatures": { "jsx": true, - "spread": true + "experimentalObjectRestSpread": true } }, "env": { diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1ca8473 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Change Log + +## v2.0.0 +### Breaking Changes +- ReactHtmlParser now decodes html entities by default +### Updates +- Add React v16 as a peer dependency +- Added options parameter to ReactHtmlParser function with `decodeEntities` option (default true) + +## v1.0.3 +### Updates +- Added React v15 as a peer dependency +### Bug Fixes +- Match boolean attributes when defined with upper or lower case characters (#5) + +## v1.0.2 +### Bug Fixes +- Don't add children to void elements such as img or br (#1) +- Correctly render boolean attributes - disabled, checked, etc (#3) + +## v1.0.0 +### Initial Release +- Render HTML elements and text +- Map HTML attribute names to React HTML prop names +- Convert inline style strings to React style object format \ No newline at end of file diff --git a/README.md b/README.md index 1024725..e8bc10d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,20 @@ import ReactHtmlParser from 'react-html-parser'; class HtmlComponent extends React.Component { render() { const html = '
Example HTML string
'; - return
{ ReactHtmlParser(html) }
; + const options = { + decodeEntities: true + }; + return
{ ReactHtmlParser(html, options) }
; } } -``` \ No newline at end of file +``` + +## API + +### `ReactHtmlParser(html, [options])` +Takes an HTML string and returns equivalent React elements + +**Arguments** +- html: The HTML string to parse +- options: Options object + - decodeEntities=true *(boolean)*: Whether to decode html entities (defaults to true) diff --git a/package-lock.json b/package-lock.json index 274babe..10e8e2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -474,6 +474,12 @@ "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", "dev": true }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", @@ -727,6 +733,16 @@ "babel-runtime": "6.25.0" } }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz", + "integrity": "sha1-h11ryb52HFiirj/u5dxIldjH+SE=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.25.0" + } + }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", diff --git a/package.json b/package.json index e368b7c..c528dc4 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "babel-core": "^6.8.0", "babel-loader": "^6.2.4", "babel-plugin-transform-object-assign": "^6.8.0", + "babel-plugin-transform-object-rest-spread": "^6.23.0", "babel-preset-es2015": "^6.6.0", "babel-preset-react": "^6.5.0", "coveralls": "^2.11.9", diff --git a/src/HtmlParser.js b/src/HtmlParser.js index bda1c44..11690c0 100644 --- a/src/HtmlParser.js +++ b/src/HtmlParser.js @@ -4,10 +4,15 @@ import ProcessNodes from './utils/ProcessNodes'; /** * Parses a HTML string and returns a list of React components generated from it * - * @param {String} html The HTML to convert into React components + * @param {String} html The HTML to convert into React component + * @param {Object} options Options to pass * @returns {Array} List of top level React elements */ -export default function HtmlParser(html) { - const nodes = htmlparser2.parseDOM(html, {decodeEntities: true}); +export default function HtmlParser(html, options={}) { + options = { + decodeEntities: true, + ...options + }; + const nodes = htmlparser2.parseDOM(html, options); return ProcessNodes(nodes); } diff --git a/test/integration/integration.spec.js b/test/integration/integration.spec.js index 2d77ece..301096b 100644 --- a/test/integration/integration.spec.js +++ b/test/integration/integration.spec.js @@ -6,12 +6,12 @@ const reactVersion = parseInt(require('react/package.json').version.match(/^(\d+ class HtmlParserComponent extends React.Component { render() { - return
{HtmlParser(this.props.html)}
; + return
{HtmlParser(this.props.html, this.props.options)}
; } } -const test = function(html, override=null) { - const actual = ReactDOMServer.renderToStaticMarkup(); +const test = function(html, override=null, options={}) { + const actual = ReactDOMServer.renderToStaticMarkup(); const expected = `
${override === null && html || override}
`; expect(actual).toBe(expected); }; @@ -90,4 +90,18 @@ describe('Integration tests: ', () => { test('', ''); }); + it('should decode html entities by default', () => { + test('!', '!'); + }); + + it('should not decode html entities when the option is disabled', () => { + test( + '!', + '!', + { + decodeEntities: false + } + ); + }); + }); diff --git a/test/unit/HtmlParser.spec.js b/test/unit/HtmlParser.spec.js index 3bc4d18..475a89d 100644 --- a/test/unit/HtmlParser.spec.js +++ b/test/unit/HtmlParser.spec.js @@ -15,10 +15,16 @@ describe('Testing: `HtmlParser`', () => { htmlparser2.parseDOM.calls.reset(); }); - it('should parse the html string and process the resulting nodes', () => { + it('should parse the html string and process the resulting nodes with default options', () => { expect(HtmlParser('html')).toBe('processed'); expect(htmlparser2.parseDOM).toHaveBeenCalledWith('html', {decodeEntities: true}); expect(ProcessNodes).toHaveBeenCalledWith('parsed'); }); + it('should allow decodeEntities option to be changed', () => { + expect(HtmlParser('html', { decodeEntities:false })).toBe('processed'); + expect(htmlparser2.parseDOM).toHaveBeenCalledWith('html', {decodeEntities: false}); + expect(ProcessNodes).toHaveBeenCalledWith('parsed'); + }); + });