GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - remarkablemark/html-react-parser: 📝 HTML to React parser.

BranchesTags
Open more actions menu

Latest commit

 

History

3,678 Commits
3,678 Commits

Folders and files

NameName
Last commit message
Last commit date
.github
.github
 
 
.husky
.husky
 
 
__tests__
__tests__
 
 
benchmark
benchmark
 
 
esm
esm
 
 
examples
examples
 
 
src
src
 
 
umd
umd
 
 
.commitlintrc.json
.commitlintrc.json
 
 
.gitignore
.gitignore
 
 
.lintstagedrc.json
.lintstagedrc.json
 
 
.nvmrc
.nvmrc
 
 
.prettierrc.json
.prettierrc.json
 
 
.size-limit.json
.size-limit.json
 
 
CHANGELOG.md
CHANGELOG.md
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 
eslint.config.mts
eslint.config.mts
 
 
package-lock.json
package-lock.json
 
 
package.json
package.json
 
 
rollup.config.mjs
rollup.config.mjs
 
 
tsconfig.build.json
tsconfig.build.json
 
 
tsconfig.json
tsconfig.json
 
 
tsconfig.test.json
tsconfig.test.json
 
 
vitest.config.browser.mts
vitest.config.browser.mts
 
 
vitest.config.mts
vitest.config.mts
 
 

Repository files navigation

html-react-parser

NPM

NPM version NPM bundle size build codecov NPM downloads 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.

To replace an element with another element, check out the replace option.

Example

import parse from 'html-react-parser';

parse('<p>Hello, World!</p>'); // React.createElement('p', {}, 'Hello, World!')

StackBlitz | TypeScript | JSFiddle | Examples

Table of Contents
  • Install
  • Usage
    • replace
      • replace with TypeScript
      • replace element and children
      • replace element attributes
      • replace and remove element
    • transform
    • library
    • htmlparser2
    • trim
    • trustedTypePolicy
  • Migration
    • v5
    • v4
    • v3
    • v2
    • v1
  • 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
    • Don't change case of tags
    • TS Error: Property 'attribs' does not exist on type 'DOMNode'
    • Can I enable trim for certain elements?
    • Webpack build warnings
    • TypeScript error
  • Performance
  • Contributors
    • Code Contributors
    • Financial Contributors
      • Individuals
      • Organizations
  • 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/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/html-react-parser@latest/dist/html-react-parser.min.js"></script>
<script>
  window.HTMLReactParser(/* string */);
</script>

Usage

Import ES module:

import parse from 'html-react-parser';

Or require CommonJS module:

const parse = require('html-react-parser').default;

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>;
    }
  },
});

The second argument is the index:

parse('<br>', {
  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).

replace with TypeScript

You need to check that domNode is an instance of domhandler's Element:

import { HTMLReactParserOptions, Element } from 'html-react-parser';

const options: HTMLReactParserOptions = {
  replace(domNode) {
    if (domNode instanceof Element && domNode.attribs) {
      // ...
    }
  },
};

Or use a type assertion:

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.

replace element and children

Replace the element and 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>

replace element attributes

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>

replace and remove element

Exclude an element from rendering by replacing it with <React.Fragment>:

parse('<p><br id="remove"></p>', {
  replace: ({ attribs }) => attribs?.id === 'remove' && <></>,
});
HTML output

<p></p>

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:

parse('<br>', {
  transform(reactNode, domNode, index) {
    // this will wrap every element in a div
    return <div>{reactNode}</div>;
  },
});

library

The library option specifies the UI library. The default library is React.

To use Preact:

parse('<br>', {
  library: require('preact'),
});

Or a custom library:

parse('<br>', {
  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 can be overridden in >=0.12.0.

To enable xmlMode:

parse('<p /><p />', {
  htmlparser2: {
    xmlMode: true,
  },
});

trim

By default, whitespace is preserved:

parse('<br>\n'); // [React.createElement('br'), '\n']

But certain elements like <table> will strip out invalid whitespace:

parse('<table>\n</table>'); // React.createElement('table')

To remove whitespace, enable the trim option:

parse('<br>\n', { trim: true }); // React.createElement('br')

However, intentional whitespace may be stripped out:

parse('<p> </p>', { trim: true }); // React.createElement('p')

trustedTypePolicy

When running in a browser, you can pass a Trusted Types policy so the parser calls trustedTypePolicy.createHTML before assigning content to innerHTML:

parse('<div>Hello</div>', {
  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 has been upgraded to v7 and domhandler has been upgraded to v6.

v5

Migrated to TypeScript. CommonJS imports require the .default key:

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:

domToReact(domNode.children as DOMNode[], options);

See #1126.

v4

htmlparser2 has been upgraded to v9.

v3

domhandler has been upgraded to v5 so some parser options like normalizeWhitespace have been removed.

Also, it's recommended to upgrade to the latest version of TypeScript.

v2

Since v2.0.0, Internet Explorer (IE) is no longer supported.

v1

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). However, you can mitigate this risk by enforcing a Content Security Policy (CSP) with Trusted Types.

Does invalid HTML get sanitized?

No, this library does not sanitize HTML (see #124, #125, and #141).

Are <script> tags parsed?

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 error, 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:

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.

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.

See #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 or #199).

Can I enable trim for certain elements?

Yes, you can enable or disable trim for certain elements using the replace option (see #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:

// webpack.config.js
module.exports = {
  // ...
  resolve: {
    mainFields: ['browser', 'main', 'module'],
  },
};

See #238 and #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 (see #748).

Performance

Run benchmark:

npm run benchmark

Output of benchmark run on MacBook Pro 2024:

html-to-react - Single x 1,270,990 ops/sec ±0.21% (100 runs sampled)
html-to-react - Multiple x 522,472 ops/sec ±0.64% (94 runs sampled)
html-to-react - Complex x 54,028 ops/sec ±0.82% (98 runs sampled)

Run Size Limit:

npx size-limit

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Code Contributors

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Financial Contributors - Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

Financial Contributors - Organization 0 Financial Contributors - Organization 1 Financial Contributors - Organization 2 Financial Contributors - Organization 3 Financial Contributors - Organization 4 Financial Contributors - Organization 5 Financial Contributors - Organization 6 Financial Contributors - Organization 7 Financial Contributors - Organization 8 Financial Contributors - Organization 9

Support

  • GitHub Sponsors
  • Open Collective
  • Tidelift
  • Patreon
  • Ko-fi
  • Liberapay
  • Teespring

License

MIT

About

📝 HTML to React parser.

b.remarkabl.org/html-react-parser

Topics

domhtmlhtml-react-parserjavascriptjsxlibrarynpmpackageparseparserreactreact-parsertypescript

Resources

Readme
MIT license

Code of conduct

Code of conduct

Contributing

Contributing

Security policy

Security policy
Activity

Stars

2.4k stars

Watchers

6 watching

Forks

144 forks
Report repository

Releases

Sponsor this project

Packages

Used by

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.