remarkablemark / Html React Parser
Programming Languages
Projects that are alternatives of or similar to Html 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.
To replace an element with another element, check out the replace
option.
Example
const parse = require('html-react-parser');
parse('<p>Hello, World!</p>'); // React.createElement('p', {}, 'Hello, World!')
Repl.it | JSFiddle | CodeSandbox | TypeScript | Examples
Table of Contents
- Install
- Usage
- Migration
-
FAQ
- Is this XSS safe?
- Does invalid HTML get sanitized?
- Are
<script>
tags parsed? - Attributes aren't getting called
- Parser throws an error
- Is SSR supported?
- Elements aren't nested correctly
- Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of table
- Don't change case of tags
- TS Error: Property 'attribs' does not exist on type 'DOMNode'
- Can I enable
trim
for certain elements?
- Performance
- Contributors
- Support
- License
Install
NPM:
$ npm install html-react-parser --save
Yarn:
$ yarn add html-react-parser
CDN:
<!-- HTMLReactParser depends on React -->
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/html-react-parser.min.js"></script>
<script>
window.HTMLReactParser(/* string */);
</script>
Usage
Import or require the module:
// ES Modules
import parse from 'html-react-parser';
// CommonJS
const parse = require('html-react-parser');
Parse single element:
parse('<h1>single</h1>');
Parse multiple elements:
parse('<li>Item 1</li><li>Item 2</li>');
Make sure to render parsed adjacent elements under a parent element:
<ul>
{parse(`
<li>Item 1</li>
<li>Item 2</li>
`)}
</ul>
Parse nested elements:
parse('<body><p>Lorem ipsum</p></body>');
Parse element with attributes:
parse(
'<hr id="foo" class="bar" data-attr="baz" custom="qux" style="top:42px;">'
);
replace
The replace
option allows you to replace an element with another element.
The replace
callback's first argument is domhandler's node:
parse('<br>', {
replace: domNode => {
console.dir(domNode, { depth: null });
}
});
Console output:
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:
parse('<p id="replace">text</p>', {
replace: domNode => {
if (domNode.attribs && domNode.attribs.id === 'replace') {
return <span>replaced</span>;
}
}
});
For TypeScript projects, you may need to check that domNode
is an instance of domhandler's Element
:
import { HTMLReactParserOptions } from 'html-react-parser';
import { Element } from 'domhandler/lib/node';
const options: HTMLReactParserOptions = {
replace: domNode => {
if (domNode instanceof Element && domNode.attribs) {
// ...
}
}
};
The following example modifies the element along with its children:
import parse, { domToReact } from 'html-react-parser';
const html = `
<p id="main">
<span class="prettify">
keep me and make me pretty!
</span>
</p>
`;
const options = {
replace: ({ attribs, children }) => {
if (!attribs) {
return;
}
if (attribs.id === 'main') {
return <h1 style={{ fontSize: 42 }}>{domToReact(children, options)}</h1>;
}
if (attribs.class === 'prettify') {
return (
<span style={{ color: 'hotpink' }}>
{domToReact(children, options)}
</span>
);
}
}
};
parse(html, options);
HTML output:
<h1 style="font-size:42px">
<span style="color:hotpink">
keep me and make me pretty!
</span>
</h1>
Convert DOM attributes to React props with attributesToProps
:
import parse, { attributesToProps } from 'html-react-parser';
const html = `
<main class="prettify" style="background: #fff; text-align: center;" />
`;
const options = {
replace: domNode => {
if (domNode.attribs && domNode.name === 'main') {
const props = attributesToProps(domNode.attribs);
return <div {...props} />;
}
}
};
parse(html, options);
HTML output:
<div class="prettify" style="background:#fff;text-align:center"></div>
Exclude an element from rendering by replacing it with <React.Fragment>
:
parse('<p><br id="remove"></p>', {
replace: ({ attribs }) => attribs && attribs.id === 'remove' && <></>
});
HTML output:
<p></p>
library
This option specifies the library that creates elements. The default library is React.
To use Preact:
parse('<br>', {
library: require('preact')
});
Or a custom library:
parse('<br>', {
library: {
cloneElement: () => {
/* ... */
},
createElement: () => {
/* ... */
},
isValidElement: () => {
/* ... */
}
}
});
htmlparser2
Along with the default htmlparser2 options, the parser also sets:
{
"lowerCaseAttributeNames": false
}
Since v0.12.0, the htmlparser2 options can be overridden.
The following example enables xmlMode
but disables lowerCaseAttributeNames
:
parse('<p /><p />', {
htmlparser2: {
xmlMode: true
}
});
WARNING:
htmlparser2
options do not apply on the client-side (browser). The options only apply on the server-side (Node.js). By overridinghtmlparser2
options, universal rendering can break. Do this at your own risk.
trim
Normally, whitespace is preserved:
parse('<br>\n'); // [React.createElement('br'), '\n']
Enable the trim
option to remove whitespace:
parse('<br>\n', { trim: true }); // React.createElement('br')
This fixes the warning:
Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of <table>. Make sure you don't have any extra whitespace between tags on each line of your source code.
However, intentional whitespace may be stripped out:
parse('<p> </p>', { trim: true }); // React.createElement('p')
Migration
v1.0.0
TypeScript projects will need to update the types in v1.0.0.
For the replace
option, you may need to do the following:
import { Element } from 'domhandler/lib/node';
parse('<br class="remove">', {
replace: domNode => {
if (domNode instanceof Element && domNode.attribs.class === 'remove') {
return <></>;
}
}
});
Since 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) safe. See #94.
Does invalid HTML get sanitized?
No, this library does not sanitize HTML. See #124, #125, and #141.
<script>
tags parsed?
Are Although <script>
tags and their contents are rendered on the server-side, they're not evaluated on the client-side. See #98.
Attributes aren't getting called
The reason why your HTML attributes aren't getting called is because inline event handlers (e.g., onclick
) are parsed as a string rather than a function. See #73.
Parser throws an error
If the parser throws an erorr, check if your arguments are valid. See "Does invalid HTML get sanitized?".
Is SSR supported?
Yes, server-side rendering on Node.js is supported by this library. See demo.
Elements aren't nested correctly
If your elements are nested incorrectly, check to make sure your HTML markup is valid. The HTML to DOM parsing will be affected if you're using self-closing syntax (/>
) on non-void elements:
parse('<div /><div />'); // returns single element instead of array of elements
See #158.
Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a child of table
Enable the trim option. See #155.
Don't change case of tags
Tags are lowercased by default. To prevent that from happening, pass the htmlparser2 option:
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.
TS Error: Property 'attribs' does not exist on type 'DOMNode'
The TypeScript error occurs because DOMNode
needs be an instance of domhandler's Element
. See migration or #199.
trim
for certain elements?
Can I enable Yes, you can enable or disable trim
for certain elements using the replace
option. See #205.
Performance
Run benchmark:
$ npm run test:benchmark
Output of benchmark run on MacBook Pro 2017:
html-to-react - Single x 415,186 ops/sec ±0.92% (85 runs sampled)
html-to-react - Multiple x 139,780 ops/sec ±2.32% (87 runs sampled)
html-to-react - Complex x 8,118 ops/sec ±2.99% (82 runs sampled)
Run Size Limit:
$ npx size-limit
Contributors
Code Contributors
This project exists thanks to all the people who contribute. [Contribute].
Financial Contributors
Become a financial contributor and help us sustain our community. [Contribute]
Individuals
Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]