diff --git a/README.md b/README.md
index dd9a0d43..a242442d 100644
--- a/README.md
+++ b/README.md
@@ -106,7 +106,7 @@ parse(
The `replace` callback allows you to swap an element with another React element.
-The first argument is an object with the same output as [htmlparser2](https://github.com/fb55/htmlparser2)'s [domhandler](https://github.com/fb55/domhandler#example):
+The first argument is an object with the same output as [htmlparser2](https://github.com/fb55/htmlparser2/tree/v3.10.1)'s [domhandler](https://github.com/fb55/domhandler#example):
```js
parse('
', {
@@ -224,6 +224,34 @@ parse('
', {
});
```
+### htmlparser2
+
+This library passes the following options to [htmlparser2](https://github.com/fb55/htmlparser2/tree/v3.10.1) on the server-side:
+
+```js
+{
+ decodeEntities: true,
+ lowerCaseAttributeNames: false
+}
+```
+
+By passing your own options, the default library options will be **replaced** (not merged).
+
+As a result, to enable `decodeEntities` and `xmlMode`, you need to do the following:
+
+```js
+parse('
', {
+ htmlparser2: {
+ decodeEntities: true,
+ xmlMode: true
+ }
+});
+```
+
+See [htmlparser2 options](https://github.com/fb55/htmlparser2/wiki/Parser-options).
+
+> **Warning**: By overriding htmlparser2 options, there's a chance of breaking universal rendering. Do this at your own risk.
+
## FAQ
#### Is this library XSS safe?
diff --git a/index.d.ts b/index.d.ts
index 4bcc997d..28b40dc3 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -1,13 +1,12 @@
// TypeScript Version: 3.3
-import { DomElement } from 'domhandler';
+import { DomElement, ParserOptions } from 'htmlparser2';
import domToReact from './lib/dom-to-react';
import htmlToDOM from 'html-dom-parser';
export interface HTMLReactParserOptions {
- replace?: (
- domNode: DomElement
- ) => JSX.Element | object | void | undefined | null | false;
+ htmlparser2?: ParserOptions;
+
library?: {
cloneElement: (
element: JSX.Element,
@@ -18,20 +17,24 @@ export interface HTMLReactParserOptions {
isValidElement: (element: any) => boolean;
[key: string]: any;
};
+
+ replace?: (
+ domNode: DomElement
+ ) => JSX.Element | object | void | undefined | null | false;
}
/**
* Converts HTML string to JSX element(s).
*
- * @param html - HTML string to parse to JSX element(s).
+ * @param html - HTML string.
* @param options - Parser options.
- * @return - JSX element(s).
+ * @return - JSX element(s), empty array, or string.
*/
declare function HTMLReactParser(
html: string,
options?: HTMLReactParserOptions
): ReturnType;
-export { DomElement, domToReact, htmlToDOM };
+export { DomElement, ParserOptions, domToReact, htmlToDOM };
export default HTMLReactParser;
diff --git a/index.js b/index.js
index b6fb44b9..a4e859ca 100644
--- a/index.js
+++ b/index.js
@@ -7,10 +7,12 @@ var domParserOptions = { decodeEntities: true, lowerCaseAttributeNames: false };
/**
* Converts HTML string to React elements.
*
- * @param {String} html - The HTML string to parse to React.
- * @param {Object} [options] - The parser options.
- * @param {Function} [options.replace] - The replace method.
- * @return {JSX.Element|JSX.Element[]|String} - Returns React element(s), string, or empty array.
+ * @param {String} html - HTML string.
+ * @param {Object} [options] - Parser options.
+ * @param {Object} [options.htmlparser2] - htmlparser2 options.
+ * @param {Object} [options.library] - Library for React, Preact, etc.
+ * @param {Function} [options.replace] - Replace method.
+ * @return {JSX.Element|JSX.Element[]|String} - React element(s), empty array, or string.
*/
function HTMLReactParser(html, options) {
if (typeof html !== 'string') {
@@ -19,7 +21,11 @@ function HTMLReactParser(html, options) {
if (html === '') {
return [];
}
- return domToReact(htmlToDOM(html, domParserOptions), options);
+ options = options || {};
+ return domToReact(
+ htmlToDOM(html, options.htmlparser2 || domParserOptions),
+ options
+ );
}
HTMLReactParser.domToReact = domToReact;
diff --git a/package.json b/package.json
index aa28ec36..2b6a1d3e 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
"dom"
],
"dependencies": {
- "@types/domhandler": "2.4.1",
+ "@types/htmlparser2": "3.10.1",
"html-dom-parser": "0.3.0",
"react-property": "1.0.1",
"style-to-object": "0.3.0"
diff --git a/test/html-to-react.js b/test/html-to-react.js
index 31e59410..15bf7085 100644
--- a/test/html-to-react.js
+++ b/test/html-to-react.js
@@ -127,5 +127,30 @@ describe('HTML to React', () => {
);
});
});
+
+ describe('library', () => {
+ it('converts with Preact instead of React', () => {
+ const Preact = require('preact');
+ const html = data.html.single;
+ const options = { library: Preact };
+ const preactElement = parse(html, options);
+ assert.deepEqual(preactElement, Preact.createElement('p', {}, 'foo'));
+ });
+ });
+
+ describe('htmlparser2', () => {
+ it('parses XHTML with xmlMode enabled', () => {
+ // using self-closing syntax (`/>`) for non-void elements is invalid
+ // which causes elements to nest instead of being rendered correctly
+ // enabling htmlparser2 option xmlMode resolves this issue
+ const html = '';
+ const options = { htmlparser2: { xmlMode: true } };
+ const reactElements = parse(html, options);
+ assert.strictEqual(
+ render(reactElements),
+ ''
+ );
+ });
+ });
});
});
diff --git a/test/types/index.test.tsx b/test/types/index.test.tsx
index 30314694..9fbef9b4 100644
--- a/test/types/index.test.tsx
+++ b/test/types/index.test.tsx
@@ -60,6 +60,18 @@ parse('
', {
}
});
+// $ExpectType Element | Element[]
+parse('', {
+ htmlparser2: {
+ xmlMode: true,
+ decodeEntities: true,
+ lowerCaseTags: false,
+ lowerCaseAttributeNames: false,
+ recognizeCDATA: true,
+ recognizeSelfClosing: true
+ }
+});
+
// $ExpectType DomElement[]
const domNodes = htmlToDOM('text
');