Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/remarkablemark/html-react-parser
📝 HTML to React parser.
https://github.com/remarkablemark/html-react-parser
dom html html-react-parser javascript jsx library npm package parse parser react react-parser typescript
Last synced: about 23 hours ago
JSON representation
📝 HTML to React parser.
- Host: GitHub
- URL: https://github.com/remarkablemark/html-react-parser
- Owner: remarkablemark
- License: mit
- Created: 2016-08-20T00:22:07.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2024-10-29T04:15:30.000Z (3 months ago)
- Last Synced: 2024-10-29T10:17:47.612Z (3 months ago)
- Topics: dom, html, html-react-parser, javascript, jsx, library, npm, package, parse, parser, react, react-parser, typescript
- Language: TypeScript
- Homepage: https://b.remarkabl.org/html-react-parser
- Size: 5.65 MB
- Stars: 2,143
- Watchers: 7
- Forks: 129
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Codeowners: .github/CODEOWNERS
- Security: .github/SECURITY.md
Awesome Lists containing this project
- jimsghstars - remarkablemark/html-react-parser - 📝 HTML to React parser. (TypeScript)
README
# html-react-parser
[![NPM](https://nodei.co/npm/html-react-parser.png)](https://nodei.co/npm/html-react-parser/)
[![NPM version](https://badgen.net/npm/v/html-react-parser)](https://www.npmjs.com/package/html-react-parser)
[![Bundlephobia minified + gzip](https://badgen.net/bundlephobia/minzip/html-react-parser)](https://bundlephobia.com/package/html-react-parser)
[![Build Status](https://github.com/remarkablemark/html-react-parser/workflows/build/badge.svg?branch=master)](https://github.com/remarkablemark/html-react-parser/actions?query=workflow%3Abuild)
[![codecov](https://codecov.io/gh/remarkablemark/html-react-parser/branch/master/graph/badge.svg?token=wosFd1DBIR)](https://codecov.io/gh/remarkablemark/html-react-parser)
[![NPM downloads](https://badgen.net/npm/dm/html-react-parser)](https://www.npmjs.com/package/html-react-parser)
[![Discord](https://badgen.net/discord/online-members/zkS3QDV?cache=300&icon=discord)](https://b.remarkabl.org/discord)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://reactjs.org/docs/react-api.html#creating-react-elements).
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!')
```[Replit](https://replit.com/@remarkablemark/html-react-parser) | [JSFiddle](https://jsfiddle.net/remarkablemark/7v86d800/) | [StackBlitz](https://stackblitz.com/edit/html-react-parser) | [TypeScript](https://stackblitz.com/edit/html-react-parser-typescript) | [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)
- [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 `` tags parsed?](#are-script-tags-parsed)
- [Attributes aren't getting called](#attributes-arent-getting-called)
- [Parser throws an error](#parser-throws-an-error)
- [Is SSR supported?](#is-ssr-supported)
- [Elements aren't nested correctly](#elements-arent-nested-correctly)
- [Don't change case of tags](#dont-change-case-of-tags)
- [TS Error: Property 'attribs' does not exist on type 'DOMNode'](#ts-error-property-attribs-does-not-exist-on-type-domnode)
- [Can I enable `trim` for certain elements?](#can-i-enable-trim-for-certain-elements)
- [Webpack build warnings](#webpack-build-warnings)
- [TypeScript error](#typescript-error)
- [Performance](#performance)
- [Contributors](#contributors)
- [Code Contributors](#code-contributors)
- [Financial Contributors](#financial-contributors)
- [Individuals](#individuals)
- [Organizations](#organizations)
- [Support](#support)
- [License](#license)</details>
## Install
[NPM](https://www.npmjs.com/package/html-react-parser):
```sh
npm install html-react-parser --save
```[Yarn](https://yarnpkg.com/package/html-react-parser):
```sh
yarn add html-react-parser
```[CDN](https://unpkg.com/html-react-parser/):
```html
<!-- HTMLReactParser depends on React -->
<script src="https://unpkg.com/react@18/umd/react.production.min.js">window.HTMLReactParser(/* string */);
```
## 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('
```
Make sure to render parsed adjacent elements under a parent element:
```tsx
- Item 1
- Item 2
{parse(`
`)}
```
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 (see [demo](https://replit.com/@remarkablemark/html-react-parser-replace-example)):
```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
}
},
};
parse(html, options);
```
HTML output
```html
```
#### replace and remove element
[Exclude](https://replit.com/@remarkablemark/html-react-parser-56) 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 _**don't 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('\n'); // 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')
```
## Migration
### 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).
### 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/remarkablemark/html-react-parser/issues/141).
### Are `` tags parsed?
Although `<script>` tags and their contents are rendered on the server-side, they're not evaluated on the client-side. See [#98](https://github.com/remarkablemark/html-react-parser/issues/98).
### Attributes aren't getting called
The reason why your HTML attributes aren't getting called is because [inline event handlers](https://developer.mozilla.org/docs/Web/Guide/Events/Event_handlers) (e.g., `onclick`) are parsed as a _string_ rather than a _function_. See [#73](https://github.com/remarkablemark/html-react-parser/issues/73).
### Parser throws an error
If the parser throws an error, check if your arguments are valid. See ["Does invalid HTML get sanitized?"](#does-invalid-html-get-sanitized).
### Is SSR supported?
Yes, server-side rendering on Node.js is supported by this library. See [demo](https://replit.com/@remarkablemark/html-react-parser-SSR).
### Elements aren't nested correctly
If your elements are nested incorrectly, check to make sure your [HTML markup is valid](https://validator.w3.org/). The HTML to DOM parsing will be affected if you're using self-closing syntax (`/>`) on non-void elements:
```js
parse('<div /><div />'); // returns single element instead of array of elements
```
See [#158](https://github.com/remarkablemark/html-react-parser/issues/158).
### Don't change case of tags
Tags are lowercased by default. To prevent that from happening, pass the [htmlparser2 option](#htmlparser2):
```js
const options = {
htmlparser2: {
lowerCaseTags: false,
},
};
parse('<CustomElement>', options); // React.createElement('CustomElement')
```
> [!WARNING]
> By preserving case-sensitivity of the tags, you may get rendering warnings like:
>
> ```
> Warning: <CustomElement> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
> ```
See [#62](https://github.com/remarkablemark/html-react-parser/issues/62) and [example](https://replit.com/@remarkablemark/html-react-parser-62).
### TS Error: Property 'attribs' does not exist on type 'DOMNode'
The TypeScript error occurs because `DOMNode` needs to be an instance of domhandler's `Element`. See [migration](#migration) or [#199](https://github.com/remarkablemark/html-react-parser/issues/199).
### Can I enable `trim` for certain elements?
Yes, you can enable or disable [`trim`](#trim) for certain elements using the [`replace`](#replace) option. See [#205](https://github.com/remarkablemark/html-react-parser/issues/205).
### Webpack build warnings
If you see the Webpack build warning:
```
export 'default' (imported as 'parse') was not found in 'html-react-parser'
```
Then update your Webpack config to:
```js
// webpack.config.js
module.exports = {
// ...
resolve: {
mainFields: ['browser', 'main', 'module'],
},
};
```
See [#238](https://github.com/remarkablemark/html-react-parser/issues/238) and [#213](https://github.com/remarkablemark/html-react-parser/issues/213).
### TypeScript error
If you see the TypeScript error:
```
node_modules/htmlparser2/lib/index.d.ts:2:23 - error TS1005: ',' expected.
2 export { Parser, type ParserOptions };
~~~~~~~~~~~~~
```
Then upgrade to the latest version of [typescript](https://www.npmjs.com/package/typescript). See [#748](https://github.com/remarkablemark/html-react-parser/issues/748).
## Performance
Run benchmark:
```sh
npm run benchmark
```
Output of benchmark run on MacBook Pro 2021:
```
html-to-react - Single x 1,018,239 ops/sec ±0.43% (94 runs sampled)
html-to-react - Multiple x 380,037 ops/sec ±0.61% (97 runs sampled)
html-to-react - Complex x 35,091 ops/sec ±0.50% (96 runs sampled)
```
Run [Size Limit](https://github.com/ai/size-limit):
```sh
npx size-limit
```
## Contributors
### Code Contributors
This project exists thanks to all the people who contribute. [[Contribute](https://github.com/remarkablemark/html-react-parser/blob/master/.github/CONTRIBUTING.md)].
[![Code Contributors](https://contrib.rocks/image?repo=remarkablemark/html-react-parser)](https://github.com/remarkablemark/html-react-parser/graphs/contributors)
### Financial Contributors
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/html-react-parser/contribute)]
#### Individuals
[![Financial Contributors - Individuals](https://opencollective.com/html-react-parser/individuals.svg?width=890)](https://opencollective.com/html-react-parser)
#### Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/html-react-parser/contribute)]
[![Financial Contributors - Organization 0](https://opencollective.com/html-react-parser/organization/0/avatar.svg)](https://opencollective.com/html-react-parser/organization/0/website)
[![Financial Contributors - Organization 1](https://opencollective.com/html-react-parser/organization/1/avatar.svg)](https://opencollective.com/html-react-parser/organization/1/website)
[![Financial Contributors - Organization 2](https://opencollective.com/html-react-parser/organization/2/avatar.svg)](https://opencollective.com/html-react-parser/organization/2/website)
[![Financial Contributors - Organization 3](https://opencollective.com/html-react-parser/organization/3/avatar.svg)](https://opencollective.com/html-react-parser/organization/3/website)
[![Financial Contributors - Organization 4](https://opencollective.com/html-react-parser/organization/4/avatar.svg)](https://opencollective.com/html-react-parser/organization/4/website)
[![Financial Contributors - Organization 5](https://opencollective.com/html-react-parser/organization/5/avatar.svg)](https://opencollective.com/html-react-parser/organization/5/website)
[![Financial Contributors - Organization 6](https://opencollective.com/html-react-parser/organization/6/avatar.svg)](https://opencollective.com/html-react-parser/organization/6/website)
[![Financial Contributors - Organization 7](https://opencollective.com/html-react-parser/organization/7/avatar.svg)](https://opencollective.com/html-react-parser/organization/7/website)
[![Financial Contributors - Organization 8](https://opencollective.com/html-react-parser/organization/8/avatar.svg)](https://opencollective.com/html-react-parser/organization/8/website)
[![Financial Contributors - Organization 9](https://opencollective.com/html-react-parser/organization/9/avatar.svg)](https://opencollective.com/html-react-parser/organization/9/website)
## Support
- [GitHub Sponsors](https://b.remarkabl.org/github-sponsors)
- [Open Collective](https://b.remarkabl.org/open-collective-html-react-parser)
- [Tidelift](https://b.remarkabl.org/tidelift-html-react-parser)
- [Patreon](https://b.remarkabl.org/patreon)
- [Ko-fi](https://b.remarkabl.org/ko-fi)
- [Liberapay](https://b.remarkabl.org/liberapay)
- [Teespring](https://b.remarkabl.org/teespring)
## License
[MIT](https://github.com/remarkablemark/html-react-parser/blob/master/LICENSE)