From 413eaa0608b218b8729c0eed81d33e40f4358454 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 5 Jun 2020 19:32:07 -0400 Subject: [PATCH 1/7] feat(dom-to-react): add option `trim` that skips whitespace nodes --- lib/dom-to-react.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/dom-to-react.js b/lib/dom-to-react.js index 695dd2de..e1a5cf8a 100644 --- a/lib/dom-to-react.js +++ b/lib/dom-to-react.js @@ -24,6 +24,8 @@ function domToReact(nodes, options) { var replaceElement; var props; var children; + var data; + var trim = options.trim; for (var i = 0, len = nodes.length; i < len; i++) { node = nodes[i]; @@ -46,7 +48,15 @@ function domToReact(nodes, options) { } if (node.type === 'text') { - result.push(node.data); + // if trim option is enabled, skip whitespace text nodes + if (trim) { + data = node.data.trim(); + if (data) { + result.push(node.data); + } + } else { + result.push(node.data); + } continue; } From 984133f7a10c76b4a285af78dab6c0861cac5193 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 5 Jun 2020 19:35:11 -0400 Subject: [PATCH 2/7] test(html-to-react): add tests for `trim` option enabled & disabled --- test/html-to-react.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/html-to-react.js b/test/html-to-react.js index 15bf7085..3683fd92 100644 --- a/test/html-to-react.js +++ b/test/html-to-react.js @@ -152,5 +152,27 @@ describe('HTML to React', () => { ); }); }); + + describe('trim', () => { + it('preserves whitespace text nodes when disabled (default)', () => { + const html = ` + + +
`; + const reactElement = parse(html); + assert.strictEqual(render(reactElement), html); + }); + + it('removes whitespace text nodes when enabled', () => { + const html = ` + \t\r\n
text
`; + const options = { trim: true }; + const reactElement = parse(html, options); + assert.strictEqual( + render(reactElement), + '
text
' + ); + }); + }); }); }); From be71b13d4e93792373824e59800950b30d5589bc Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 5 Jun 2020 19:38:05 -0400 Subject: [PATCH 3/7] feat(index): type `trim` in HTMLReactParserOptions --- index.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.d.ts b/index.d.ts index 28b40dc3..c67d6aaf 100644 --- a/index.d.ts +++ b/index.d.ts @@ -21,6 +21,8 @@ export interface HTMLReactParserOptions { replace?: ( domNode: DomElement ) => JSX.Element | object | void | undefined | null | false; + + trim?: boolean; } /** From d2964e87904f8c0e9f9b3c3cd99d2e6d9b816af5 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 5 Jun 2020 19:40:13 -0400 Subject: [PATCH 4/7] test(types): add dtslint tests for `trim` option --- test/types/index.test.tsx | 3 +++ test/types/lib/dom-to-react.test.tsx | 3 +++ 2 files changed, 6 insertions(+) diff --git a/test/types/index.test.tsx b/test/types/index.test.tsx index 9fbef9b4..0bb19a48 100644 --- a/test/types/index.test.tsx +++ b/test/types/index.test.tsx @@ -72,6 +72,9 @@ parse('

', { } }); +// $ExpectType Element | Element[] +parse('\t

text \r

\n', { trim: true }); + // $ExpectType DomElement[] const domNodes = htmlToDOM('
text
'); diff --git a/test/types/lib/dom-to-react.test.tsx b/test/types/lib/dom-to-react.test.tsx index 54a38941..1d124fb1 100644 --- a/test/types/lib/dom-to-react.test.tsx +++ b/test/types/lib/dom-to-react.test.tsx @@ -38,3 +38,6 @@ domToReact(htmlToDOM('Heading'), { } } }); + +// $ExpectType Element | Element[] +domToReact(htmlToDOM('\t

text \r

\n'), { trim: true }); From 759b7a92f95f8895bf275f7e024d771920b6d1e8 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 5 Jun 2020 19:43:07 -0400 Subject: [PATCH 5/7] docs(readme): document `trim` option under Options and FAQ --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index a242442d..144b4c1f 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,32 @@ See [htmlparser2 options](https://github.com/fb55/htmlparser2/wiki/Parser-option > **Warning**: By overriding htmlparser2 options, there's a chance of breaking universal rendering. Do this at your own risk. +### trim + +Normally, whitespace is preserved: + +```js +parse('
\n'); // [React.createElement('br'), '\n'] +``` + +By enabling the `trim` option, whitespace text nodes will be skipped: + +```js +parse('
\n', { trim: true }); // React.createElement('br') +``` + +This addresses the warning: + +``` +Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of . Make sure you don't have any extra whitespace between tags on each line of your source code. +``` + +However, this option may strip out intentional whitespace: + +```js +parse('

', { trim: true }); // React.createElement('p') +``` + ## FAQ #### Is this library XSS safe? @@ -288,6 +314,10 @@ parse('
'); // returns single element instead of array of elements See [#158](https://github.com/remarkablemark/html-react-parser/issues/158). +#### I get "Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of table." + +Enable the [trim](https://github.com/remarkablemark/html-react-parser#trim) option. See [#155](https://github.com/remarkablemark/html-react-parser/issues/155). + ## Benchmarks ```sh From 507ad1ca301b508c19ec8dc81867ea68fe73d63a Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 5 Jun 2020 19:45:46 -0400 Subject: [PATCH 6/7] docs(dom-to-react): tidy comments and update JSDoc --- lib/dom-to-react.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/dom-to-react.js b/lib/dom-to-react.js index e1a5cf8a..1acba723 100644 --- a/lib/dom-to-react.js +++ b/lib/dom-to-react.js @@ -35,7 +35,7 @@ function domToReact(nodes, options) { replaceElement = options.replace(node); if (isValidElement(replaceElement)) { - // specify a "key" prop if element has siblings + // set "key" prop for sibling elements // https://fb.me/react-warning-keys if (len > 1) { replaceElement = cloneElement(replaceElement, { @@ -62,14 +62,11 @@ function domToReact(nodes, options) { props = node.attribs; if (!shouldPassAttributesUnaltered(node)) { - // update values props = attributesToProps(node.attribs); } children = null; - // node type for