From 9de3651bf072875a5addc6d70c4fc91dc215eaab Mon Sep 17 00:00:00 2001 From: Peter Newnham Date: Sun, 1 Oct 2017 23:25:17 +0100 Subject: [PATCH 1/3] Add preprocessNodes option --- README.md | 15 +++++++++++-- package-lock.json | 32 ++++++++++++++-------------- src/HtmlParser.js | 8 +++++-- test/integration/integration.spec.js | 17 ++++++++++++++- test/unit/HtmlParser.spec.js | 7 +++--- 5 files changed, 55 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 9187023..16ab6b4 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ yarn add react-html-parser ```javascript import React from 'react'; -import ReactHtmlParser from 'react-html-parser'; +import ReactHtmlParser, { processNodes, convertNodeToElement } from 'react-html-parser'; class HtmlComponent extends React.Component { render() { @@ -45,6 +45,7 @@ import ReactHtmlParser from 'react-html-parser'; - `options`: Options object - decodeEntities=true *(boolean)*: Whether to decode html entities (defaults to true) - transform *(function)*: Transform function that is applied to every node + - preprocessNodes *(function)*: Pre-process the nodes generated by `htmlparser2` #### Transform Function The transform function will be called for every node that is parsed by the library. @@ -86,6 +87,16 @@ function transform(node) { } ``` +#### preprocessNodes Function +Allows pre-processing the nodes generated from the html by `htmlparser2` before being passed to the library and converted to React elements. + +`function preprocessNodes(nodes)` +##### Arguments +- `nodes`: The entire node tree generated by `htmlparser2`. + +##### Return type +The `preprocessNodes` function should return a valid `htmlparser2` node tree. + ### `function convertNodeToElement(node, index, transform)` Processes a node and returns the React element to be rendered. This function can be used in conjunction with the previously described `transform` function to continue to process a node after modifying it. @@ -107,4 +118,4 @@ function transform(node, index) { return convertNodeToElement(node, index, transform); } } -``` +``` \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ad85724..4dc7fb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3178,14 +3178,6 @@ } } }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, "string-width": { "version": "1.0.2", "bundled": true, @@ -3196,6 +3188,14 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, "stringstream": { "version": "0.0.5", "bundled": true, @@ -5706,14 +5706,6 @@ "xtend": "4.0.1" } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -5725,6 +5717,14 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", diff --git a/src/HtmlParser.js b/src/HtmlParser.js index d72fdfb..d9db18f 100644 --- a/src/HtmlParser.js +++ b/src/HtmlParser.js @@ -8,7 +8,11 @@ import processNodes from './processNodes'; * @param {Object} options Options to pass * @returns {Array} List of top level React elements */ -export default function HtmlParser(html, { decodeEntities=true, transform }={}) { - const nodes = htmlparser2.parseDOM(html, { decodeEntities }); +export default function HtmlParser(html, { + decodeEntities = true, + transform, + preprocessNodes = nodes => nodes +}={}) { + const nodes = preprocessNodes(htmlparser2.parseDOM(html, { decodeEntities })); return processNodes(nodes, transform); } diff --git a/test/integration/integration.spec.js b/test/integration/integration.spec.js index 85e4680..0fe2180 100644 --- a/test/integration/integration.spec.js +++ b/test/integration/integration.spec.js @@ -1,6 +1,6 @@ import React from 'react'; import ReactDOMServer from 'react-dom/server'; -import HtmlParser, { convertNodeToElement } from 'index'; +import HtmlParser, { convertNodeToElement, htmlparser2 } from 'index'; const reactVersion = parseInt(require('react/package.json').version.match(/^(\d+)\./)[1], 10); @@ -170,4 +170,19 @@ describe('Integration tests: ', () => { ); }); + it('should preprocess nodes correctly', () => { + test( + '
preprocess test
', + '
preprocess test
preprocess test
', + { + preprocessNodes(nodes) { + return [ + ...nodes, + ...nodes + ]; + } + } + ); + }); + }); diff --git a/test/unit/HtmlParser.spec.js b/test/unit/HtmlParser.spec.js index 5140085..158a24d 100644 --- a/test/unit/HtmlParser.spec.js +++ b/test/unit/HtmlParser.spec.js @@ -22,10 +22,11 @@ describe('Testing: `HtmlParser`', () => { }); it('should apply the options', () => { - const transform = function() {}; - expect(HtmlParser('html', { decodeEntities:false, transform })).toBe('processed'); + const transform = jasmine.createSpy('transform'); + const preprocessNodes = jasmine.createSpy('preprocessNodes').and.callFake(v => `preprocessed ${v}`); + expect(HtmlParser('html', { decodeEntities:false, transform, preprocessNodes })).toBe('processed'); expect(htmlparser2.parseDOM).toHaveBeenCalledWith('html', {decodeEntities: false}); - expect(processNodes).toHaveBeenCalledWith('parsed', transform); + expect(processNodes).toHaveBeenCalledWith('preprocessed parsed', transform); }); }); From ddcdf9f69d3b1257d140533ba7e9f152b7072f90 Mon Sep 17 00:00:00 2001 From: Peter Newnham Date: Sun, 1 Oct 2017 23:26:00 +0100 Subject: [PATCH 2/3] Expose htmlparser2 --- README.md | 10 ++++++++-- src/index.js | 3 +++ test/integration/integration.spec.js | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 16ab6b4..c1c1a70 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ yarn add react-html-parser ```javascript import React from 'react'; -import ReactHtmlParser, { processNodes, convertNodeToElement } from 'react-html-parser'; +import ReactHtmlParser, { processNodes, convertNodeToElement, htmlparser2 } from 'react-html-parser'; class HtmlComponent extends React.Component { render() { @@ -118,4 +118,10 @@ function transform(node, index) { return convertNodeToElement(node, index, transform); } } -``` \ No newline at end of file +``` + +### `htmlparser2` +The library exposes the `htmlparser2` library it uses. This allows consumers +to use it without having to add it as a separate dependency. + +See https://github.com/fb55/htmlparser2 for full details. \ No newline at end of file diff --git a/src/index.js b/src/index.js index 862b9a8..0aa65ee 100644 --- a/src/index.js +++ b/src/index.js @@ -3,3 +3,6 @@ export default HtmlParser; export { default as processNodes } from './processNodes'; export { default as convertNodeToElement } from './convertNodeToElement'; + +// expose htmlparser2 so it can be used if required +export { default as htmlparser2 } from 'htmlparser2'; diff --git a/test/integration/integration.spec.js b/test/integration/integration.spec.js index 0fe2180..4f88464 100644 --- a/test/integration/integration.spec.js +++ b/test/integration/integration.spec.js @@ -185,4 +185,8 @@ describe('Integration tests: ', () => { ); }); + it('should expose htmlparser2', () => { + expect(htmlparser2).toBeDefined(); + }); + }); From 22bd74494c5220d9dadf884a700293a7347443b0 Mon Sep 17 00:00:00 2001 From: Peter Newnham Date: Sun, 1 Oct 2017 23:36:54 +0100 Subject: [PATCH 3/3] Add React 16 explicitely to travis config --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cdff517..0962076 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ node_js: - 8 env: - - REACT_VERSION=next # 16 beta + - REACT_VERSION=16 - REACT_VERSION=15 script: