HTML to React parser.
# html-react-parser
HTML to React parser that works on both the server (Node.js) and the client (browser):
```
HTMLReactParser(string[, options])
```
The parser converts an HTML string to one or more [React elements](https://react.dev/reference/react/createElement).
To replace an element with another element, check out the [`replace`](#replace) option.
#### Example
```ts
import parse from 'html-react-parser';
parse('
Hello, World!
'); // React.createElement('p', {}, 'Hello, World!')
```
[StackBlitz](https://stackblitz.com/edit/html-react-parser) | [TypeScript](https://stackblitz.com/edit/html-react-parser-typescript) | [JSFiddle](https://jsfiddle.net/remarkablemark/7v86d800/) | [Examples](https://github.com/remarkablemark/html-react-parser/tree/master/examples)
Table of Contents
- [Install](#install)
- [Usage](#usage)
- [replace](#replace)
- [replace with TypeScript](#replace-with-typescript)
- [replace element and children](#replace-element-and-children)
- [replace element attributes](#replace-element-attributes)
- [replace and remove element](#replace-and-remove-element)
- [transform](#transform)
- [library](#library)
- [htmlparser2](#htmlparser2)
- [trim](#trim)
- [trustedTypePolicy](#trustedtypepolicy)
- [Migration](#migration)
- [v5](#v5)
- [v4](#v4)
- [v3](#v3)
- [v2](#v2)
- [v1](#v1)
- [FAQ](#faq)
- [Is this XSS safe?](#is-this-xss-safe)
- [Does invalid HTML get sanitized?](#does-invalid-html-get-sanitized)
- [Are `
```
## Usage
Import ES module:
```ts
import parse from 'html-react-parser';
```
Or require CommonJS module:
```ts
const parse = require('html-react-parser').default;
```
Parse single element:
```ts
parse('
single
');
```
Parse multiple elements:
```ts
parse('
Item 1Item 2');
```
Make sure to render parsed adjacent elements under a parent element:
```tsx
{parse(`
- Item 1
- Item 2
`)}
```
Parse nested elements:
```ts
parse('
Lorem ipsum
');
```
Parse element with attributes:
```ts
parse(
'
',
);
```
### replace
The `replace` option allows you to replace an element with another element.
The `replace` callback's first argument is [domhandler](https://github.com/fb55/domhandler#example)'s node:
```ts
parse('
', {
replace(domNode) {
console.dir(domNode, { depth: null });
},
});
```
Console output
```ts
Element {
type: 'tag',
parent: null,
prev: null,
next: null,
startIndex: null,
endIndex: null,
children: [],
name: 'br',
attribs: {}
}
```
The element is replaced if a **valid** React element is returned:
```tsx
parse('
text
', {
replace(domNode) {
if (domNode.attribs && domNode.attribs.id === 'replace') {
return replaced;
}
},
});
```
The second argument is the index:
```ts
parse('
', {
replace(domNode, index) {
console.assert(typeof index === 'number');
},
});
```
> [!NOTE]
>
> The index will restart at 0 when traversing the node's children so don't rely on index being a unique key (see [#1259](https://github.com/remarkablemark/html-react-parser/issues/1259#issuecomment-1889574133)).
#### replace with TypeScript
You need to check that `domNode` is an instance of domhandler's `Element`:
```tsx
import { HTMLReactParserOptions, Element } from 'html-react-parser';
const options: HTMLReactParserOptions = {
replace(domNode) {
if (domNode instanceof Element && domNode.attribs) {
// ...
}
},
};
```
Or use a type assertion:
```tsx
import { HTMLReactParserOptions, Element } from 'html-react-parser';
const options: HTMLReactParserOptions = {
replace(domNode) {
if ((domNode as Element).attribs) {
// ...
}
},
};
```
If you're having issues, take a look at our [Create React App example](./examples/create-react-app-typescript/src/App.tsx).
#### replace element and children
Replace the element and its children:
```tsx
import parse, { domToReact } from 'html-react-parser';
const html = `
keep me and make me pretty!
`;
const options = {
replace({ attribs, children }) {
if (!attribs) {
return;
}
if (attribs.id === 'main') {
return
{domToReact(children, options)}
;
}
if (attribs.class === 'prettify') {
return (
{domToReact(children, options)}
);
}
},
};
parse(html, options);
```
HTML output
```html
keep me and make me pretty!
```
#### replace element attributes
Convert DOM attributes to React props with `attributesToProps`:
```tsx
import parse, { attributesToProps } from 'html-react-parser';
const html = `
`;
const options = {
replace(domNode) {
if (domNode.attribs && domNode.name === 'main') {
const props = attributesToProps(domNode.attribs);
return
```
#### replace and remove element
Exclude an element from rendering by replacing it with ``:
```tsx
parse('
', {
replace: ({ attribs }) => attribs?.id === 'remove' && <></>,
});
```
HTML output
```html
```
### transform
The `transform` option allows you to transform each element individually after it's parsed.
The `transform` callback's first argument is the React element:
```tsx
parse('
', {
transform(reactNode, domNode, index) {
// this will wrap every element in a div
return
;
},
});
```
### library
The `library` option specifies the UI library. The default library is **React**.
To use Preact:
```ts
parse('
', {
library: require('preact'),
});
```
Or a custom library:
```ts
parse('
', {
library: {
cloneElement: () => {
/* ... */
},
createElement: () => {
/* ... */
},
isValidElement: () => {
/* ... */
},
},
});
```
### htmlparser2
> [!WARNING]
>
> `htmlparser2` options _**do not work** on the client-side_ (browser); they _**only work** on the server-side_ (Node.js). By overriding the options, it can break universal rendering.
Default [htmlparser2 options](https://github.com/fb55/htmlparser2/wiki/Parser-options#option-xmlmode) can be overridden in >=[0.12.0](https://github.com/remarkablemark/html-react-parser/tree/v0.12.0).
To enable [`xmlMode`](https://github.com/fb55/htmlparser2/wiki/Parser-options#option-xmlmode):
```ts
parse('
', {
htmlparser2: {
xmlMode: true,
},
});
```
### trim
By default, whitespace is preserved:
```ts
parse('
\n'); // [React.createElement('br'), '\n']
```
But certain elements like `
` will strip out invalid whitespace:
```ts
parse(''); // React.createElement('table')
```
To remove whitespace, enable the `trim` option:
```ts
parse('
\n', { trim: true }); // React.createElement('br')
```
However, intentional whitespace may be stripped out:
```ts
parse('
', { trim: true }); // React.createElement('p')
```
### trustedTypePolicy
When running in a browser, you can pass a [Trusted Types](https://developer.mozilla.org/docs/Web/API/Trusted_Types_API) policy so the parser calls `trustedTypePolicy.createHTML` before assigning content to `innerHTML`:
```ts
parse('
', {
trustedTypePolicy: window.trustedTypes?.createPolicy('my-policy', {
createHTML(input) {
// apply sanitization logic here
return DOMPurify.sanitize(input);
},
}),
});
```
## Migration
### v6
Changed build target from `es5` to `es2016`.
[html-dom-parser](https://github.com/remarkablemark/html-dom-parser) has been upgraded to [v7](https://github.com/remarkablemark/html-dom-parser/releases/tag/v7.0.0) and [domhandler](https://github.com/fb55/domhandler) has been upgraded to [v6](https://github.com/fb55/domhandler/releases/tag/v6.0.1).
### v5
Migrated to TypeScript. CommonJS imports require the `.default` key:
```ts
const parse = require('html-react-parser').default;
```
If you're getting the error:
```
Argument of type 'ChildNode[]' is not assignable to parameter of type 'DOMNode[]'.
```
Then use type assertion:
```ts
domToReact(domNode.children as DOMNode[], options);
```
See [#1126](https://github.com/remarkablemark/html-react-parser/issues/1126#issuecomment-1784188447).
### v4
[htmlparser2](https://github.com/fb55/htmlparser2) has been upgraded to [v9](https://github.com/fb55/htmlparser2/releases/tag/v9.0.0).
### v3
[domhandler](https://github.com/fb55/domhandler) has been upgraded to v5 so some [parser options](https://github.com/fb55/htmlparser2/wiki/Parser-options) like `normalizeWhitespace` have been removed.
Also, it's recommended to upgrade to the latest version of [TypeScript](https://www.npmjs.com/package/typescript).
### v2
Since [v2.0.0](https://github.com/remarkablemark/html-react-parser/releases/tag/v2.0.0), Internet Explorer (IE) is no longer supported.
### v1
TypeScript projects will need to update the types in [v1.0.0](https://github.com/remarkablemark/html-react-parser/releases/tag/v1.0.0).
For the `replace` option, you may need to do the following:
```tsx
import { Element } from 'domhandler/lib/node';
parse('
', {
replace(domNode) {
if (domNode instanceof Element && domNode.attribs.class === 'remove') {
return <></>;
}
},
});
```
Since [v1.1.1](https://github.com/remarkablemark/html-react-parser/releases/tag/v1.1.1), Internet Explorer 9 (IE9) is no longer supported.
## FAQ
### Is this XSS safe?
No, this library is **not** [XSS (cross-site scripting)](https://wikipedia.org/wiki/Cross-site_scripting) safe (see [#94](https://github.com/remarkablemark/html-react-parser/issues/94)). However, you can mitigate this risk by enforcing a Content Security Policy (CSP) with [Trusted Types](#trustedtypepolicy).
### Does invalid HTML get sanitized?
No, this library does **not** sanitize HTML (see [#124](https://github.com/remarkablemark/html-react-parser/issues/124), [#125](https://github.com/remarkablemark/html-react-parser/issues/125), and [#141](https://github.com/remarkable