{"id":13682343,"url":"https://github.com/remarkablemark/html-react-parser","last_synced_at":"2026-02-03T02:26:48.375Z","repository":{"id":37602165,"uuid":"66119977","full_name":"remarkablemark/html-react-parser","owner":"remarkablemark","description":"📝 HTML to React parser.","archived":false,"fork":false,"pushed_at":"2026-01-29T04:34:32.000Z","size":7001,"stargazers_count":2382,"open_issues_count":13,"forks_count":137,"subscribers_count":6,"default_branch":"master","last_synced_at":"2026-01-30T03:36:46.678Z","etag":null,"topics":["dom","html","html-react-parser","javascript","jsx","library","npm","package","parse","parser","react","react-parser","typescript"],"latest_commit_sha":null,"homepage":"https://b.remarkabl.org/html-react-parser","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/remarkablemark.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["remarkablemark"],"patreon":"remarkablemark","open_collective":null,"ko_fi":"remarkablemark","tidelift":null,"community_bridge":null,"liberapay":"remarkablemark","issuehunt":null,"otechie":null,"buy_me_a_coffee":"remarkablemark","thanks_dev":"u/gh/remarkablemark","custom":["https://b.remarkabl.org/teespring"]}},"created_at":"2016-08-20T00:22:07.000Z","updated_at":"2026-01-29T04:34:35.000Z","dependencies_parsed_at":"2025-12-25T23:03:50.956Z","dependency_job_id":null,"html_url":"https://github.com/remarkablemark/html-react-parser","commit_stats":{"total_commits":1925,"total_committers":39,"mean_commits":49.35897435897436,"dds":0.4701298701298702,"last_synced_commit":"26f30c3bf7f195241e7ac3bb8637b4c114fa0cf5"},"previous_names":[],"tags_count":159,"template":false,"template_full_name":null,"purl":"pkg:github/remarkablemark/html-react-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkablemark%2Fhtml-react-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkablemark%2Fhtml-react-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkablemark%2Fhtml-react-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkablemark%2Fhtml-react-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/remarkablemark","download_url":"https://codeload.github.com/remarkablemark/html-react-parser/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/remarkablemark%2Fhtml-react-parser/sbom","scorecard":{"id":352499,"data":{"date":"2025-08-18T06:50:49Z","repo":{"name":"github.com/remarkablemark/html-react-parser","commit":"ebdc0f954c032c3a3a5ba82ea869f7e788732a3f"},"scorecard":{"version":"v5.2.1","commit":"ab2f6e92482462fe66246d9e32f642855a691dc1"},"score":7.4,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/5 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#maintained"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: .github/SECURITY.md:1","Info: Found linked content: .github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: .github/SECURITY.md:1","Info: Found text in security policy: .github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#security-policy"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dependency-update-tool"}},{"name":"Token-Permissions","score":9,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release-please.yml:13","Info: jobLevel 'contents' permission set to 'read': .github/workflows/release-please.yml:29","Info: topLevel 'contents' permission set to 'read': .github/workflows/build.yml:5","Info: topLevel 'contents' permission set to 'read': .github/workflows/commitlint.yml:5","Warn: no topLevel permission defined: .github/workflows/release-please.yml:1","Info: topLevel permissions set to 'read-all': .github/workflows/scorecard.yml:14"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/build.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/commitlint.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/commitlint.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/commitlint.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/commitlint.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-please.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/release-please.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-please.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/release-please.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-please.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/release-please.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/scorecard.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/scorecard.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/scorecard.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/scorecard.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/scorecard.yml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/scorecard.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/scorecard.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/scorecard.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/size-limit.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/size-limit.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/size-limit.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/remarkablemark/html-react-parser/size-limit.yml/master?enable=pin","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned","Info:   3 out of   3 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#license"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#cii-best-practices"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#signed-releases"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: all commits (25) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#sast"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/release-please.yml:24"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#packaging"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#fuzzing"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'master'","Info: 'stale review dismissal' is required to merge on branch 'master'","Warn: branch 'master' does not require approvers","Warn: codeowners review is not required on branch 'master'","Warn: 'last push approval' is disabled on branch 'master'","Warn: 'up-to-date branches' is disabled on branch 'master'","Info: status check found to merge onto on branch 'master'","Info: PRs are required in order to make changes on branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#vulnerabilities"}},{"name":"CI-Tests","score":10,"reason":"23 out of 23 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#ci-tests"}},{"name":"Contributors","score":10,"reason":"project has 17 contributing companies or organizations","details":["Info: found contributions from: HackTheDeep, VidhuCraft, ai-action, aovim, bgzt, bitly-community, braze-community, corsmirror, encrypit, getvinch, klaviyo, lilboards, lit-io, onyxinsight, remarkablegames, silentsolutionsdigital, ☁️"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#contributors"}}]},"last_synced_at":"2025-08-18T08:41:23.912Z","repository_id":37602165,"created_at":"2025-08-18T08:41:23.912Z","updated_at":"2025-08-18T08:41:23.912Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28931094,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T04:05:25.756Z","status":"ssl_error","status_checked_at":"2026-01-31T04:02:35.005Z","response_time":128,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dom","html","html-react-parser","javascript","jsx","library","npm","package","parse","parser","react","react-parser","typescript"],"created_at":"2024-08-02T13:01:44.530Z","updated_at":"2026-01-31T06:05:57.877Z","avatar_url":"https://github.com/remarkablemark.png","language":"TypeScript","readme":"# html-react-parser\n\n[![NPM](https://nodei.co/npm/html-react-parser.svg)](https://b.remarkabl.org/html-react-parser)\n\n[![NPM version](https://img.shields.io/npm/v/html-react-parser)](https://b.remarkabl.org/html-react-parser)\n[![NPM bundle size](https://img.shields.io/bundlephobia/minzip/html-react-parser)](https://bundlephobia.com/package/html-react-parser)\n[![build](https://github.com/remarkablemark/html-react-parser/actions/workflows/build.yml/badge.svg)](https://github.com/remarkablemark/html-react-parser/actions/workflows/build.yml)\n[![codecov](https://codecov.io/gh/remarkablemark/html-react-parser/branch/master/graph/badge.svg?token=wosFd1DBIR)](https://codecov.io/gh/remarkablemark/html-react-parser)\n[![NPM downloads](https://img.shields.io/npm/dm/html-react-parser)](https://b.remarkabl.org/html-react-parser)\n[![Discord](https://img.shields.io/discord/422421589582282752?logo=discord\u0026logoColor=white\u0026color=%237289da\u0026cacheSeconds=300)](https://b.remarkabl.org/discord)\n\nHTML to React parser that works on both the server (Node.js) and the client (browser):\n\n```\nHTMLReactParser(string[, options])\n```\n\nThe parser converts an HTML string to one or more [React elements](https://react.dev/reference/react/createElement).\n\nTo replace an element with another element, check out the [`replace`](#replace) option.\n\n#### Example\n\n```ts\nimport parse from 'html-react-parser';\n\nparse('\u003cp\u003eHello, World!\u003c/p\u003e'); // React.createElement('p', {}, 'Hello, World!')\n```\n\n[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)\n\n\u003cdetails\u003e\n\u003csummary\u003eTable of Contents\u003c/summary\u003e\n\n- [Install](#install)\n- [Usage](#usage)\n  - [replace](#replace)\n    - [replace with TypeScript](#replace-with-typescript)\n    - [replace element and children](#replace-element-and-children)\n    - [replace element attributes](#replace-element-attributes)\n    - [replace and remove element](#replace-and-remove-element)\n  - [transform](#transform)\n  - [library](#library)\n  - [htmlparser2](#htmlparser2)\n  - [trim](#trim)\n- [Migration](#migration)\n  - [v5](#v5)\n  - [v4](#v4)\n  - [v3](#v3)\n  - [v2](#v2)\n  - [v1](#v1)\n- [FAQ](#faq)\n  - [Is this XSS safe?](#is-this-xss-safe)\n  - [Does invalid HTML get sanitized?](#does-invalid-html-get-sanitized)\n  - [Are `\u003cscript\u003e` tags parsed?](#are-script-tags-parsed)\n  - [Attributes aren't getting called](#attributes-arent-getting-called)\n  - [Parser throws an error](#parser-throws-an-error)\n  - [Is SSR supported?](#is-ssr-supported)\n  - [Elements aren't nested correctly](#elements-arent-nested-correctly)\n  - [Don't change case of tags](#dont-change-case-of-tags)\n  - [TS Error: Property 'attribs' does not exist on type 'DOMNode'](#ts-error-property-attribs-does-not-exist-on-type-domnode)\n  - [Can I enable `trim` for certain elements?](#can-i-enable-trim-for-certain-elements)\n  - [Webpack build warnings](#webpack-build-warnings)\n  - [TypeScript error](#typescript-error)\n- [Performance](#performance)\n- [Contributors](#contributors)\n  - [Code Contributors](#code-contributors)\n  - [Financial Contributors](#financial-contributors)\n    - [Individuals](#individuals)\n    - [Organizations](#organizations)\n- [Support](#support)\n- [License](#license)\n\n\u003c/details\u003e\n\n## Install\n\n[NPM](https://www.npmjs.com/package/html-react-parser):\n\n```sh\nnpm install html-react-parser --save\n```\n\n[Yarn](https://yarnpkg.com/package/html-react-parser):\n\n```sh\nyarn add html-react-parser\n```\n\n[CDN](https://unpkg.com/html-react-parser/):\n\n```html\n\u003c!-- HTMLReactParser depends on React --\u003e\n\u003cscript src=\"https://unpkg.com/react@18/umd/react.production.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/html-react-parser@latest/dist/html-react-parser.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  window.HTMLReactParser(/* string */);\n\u003c/script\u003e\n```\n\n## Usage\n\nImport ES module:\n\n```ts\nimport parse from 'html-react-parser';\n```\n\nOr require CommonJS module:\n\n```ts\nconst parse = require('html-react-parser').default;\n```\n\nParse single element:\n\n```ts\nparse('\u003ch1\u003esingle\u003c/h1\u003e');\n```\n\nParse multiple elements:\n\n```ts\nparse('\u003cli\u003eItem 1\u003c/li\u003e\u003cli\u003eItem 2\u003c/li\u003e');\n```\n\nMake sure to render parsed adjacent elements under a parent element:\n\n```tsx\n\u003cul\u003e\n  {parse(`\n    \u003cli\u003eItem 1\u003c/li\u003e\n    \u003cli\u003eItem 2\u003c/li\u003e\n  `)}\n\u003c/ul\u003e\n```\n\nParse nested elements:\n\n```ts\nparse('\u003cbody\u003e\u003cp\u003eLorem ipsum\u003c/p\u003e\u003c/body\u003e');\n```\n\nParse element with attributes:\n\n```ts\nparse(\n  '\u003chr id=\"foo\" class=\"bar\" data-attr=\"baz\" custom=\"qux\" style=\"top:42px;\"\u003e',\n);\n```\n\n### replace\n\nThe `replace` option allows you to replace an element with another element.\n\nThe `replace` callback's first argument is [domhandler](https://github.com/fb55/domhandler#example)'s node:\n\n```ts\nparse('\u003cbr\u003e', {\n  replace(domNode) {\n    console.dir(domNode, { depth: null });\n  },\n});\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eConsole output\u003c/summary\u003e\n\u003cp\u003e\n\n```ts\nElement {\n  type: 'tag',\n  parent: null,\n  prev: null,\n  next: null,\n  startIndex: null,\n  endIndex: null,\n  children: [],\n  name: 'br',\n  attribs: {}\n}\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\nThe element is replaced if a **valid** React element is returned:\n\n```tsx\nparse('\u003cp id=\"replace\"\u003etext\u003c/p\u003e', {\n  replace(domNode) {\n    if (domNode.attribs \u0026\u0026 domNode.attribs.id === 'replace') {\n      return \u003cspan\u003ereplaced\u003c/span\u003e;\n    }\n  },\n});\n```\n\nThe second argument is the index:\n\n```ts\nparse('\u003cbr\u003e', {\n  replace(domNode, index) {\n    console.assert(typeof index === 'number');\n  },\n});\n```\n\n\u003e [!NOTE]\n\u003e\n\u003e 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).\n\n#### replace with TypeScript\n\nYou need to check that `domNode` is an instance of domhandler's `Element`:\n\n```tsx\nimport { HTMLReactParserOptions, Element } from 'html-react-parser';\n\nconst options: HTMLReactParserOptions = {\n  replace(domNode) {\n    if (domNode instanceof Element \u0026\u0026 domNode.attribs) {\n      // ...\n    }\n  },\n};\n```\n\nOr use a type assertion:\n\n```tsx\nimport { HTMLReactParserOptions, Element } from 'html-react-parser';\n\nconst options: HTMLReactParserOptions = {\n  replace(domNode) {\n    if ((domNode as Element).attribs) {\n      // ...\n    }\n  },\n};\n```\n\nIf you're having issues, take a look at our [Create React App example](./examples/create-react-app-typescript/src/App.tsx).\n\n#### replace element and children\n\nReplace the element and its children (see [demo](https://replit.com/@remarkablemark/html-react-parser-replace-example)):\n\n```tsx\nimport parse, { domToReact } from 'html-react-parser';\n\nconst html = `\n  \u003cp id=\"main\"\u003e\n    \u003cspan class=\"prettify\"\u003e\n      keep me and make me pretty!\n    \u003c/span\u003e\n  \u003c/p\u003e\n`;\n\nconst options = {\n  replace({ attribs, children }) {\n    if (!attribs) {\n      return;\n    }\n\n    if (attribs.id === 'main') {\n      return \u003ch1 style={{ fontSize: 42 }}\u003e{domToReact(children, options)}\u003c/h1\u003e;\n    }\n\n    if (attribs.class === 'prettify') {\n      return (\n        \u003cspan style={{ color: 'hotpink' }}\u003e\n          {domToReact(children, options)}\n        \u003c/span\u003e\n      );\n    }\n  },\n};\n\nparse(html, options);\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eHTML output\u003c/summary\u003e\n\u003cp\u003e\n\n\u003c!-- prettier-ignore-start --\u003e\n\n```html\n\u003ch1 style=\"font-size:42px\"\u003e\n  \u003cspan style=\"color:hotpink\"\u003e\n    keep me and make me pretty!\n  \u003c/span\u003e\n\u003c/h1\u003e\n```\n\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n#### replace element attributes\n\nConvert DOM attributes to React props with `attributesToProps`:\n\n```tsx\nimport parse, { attributesToProps } from 'html-react-parser';\n\nconst html = `\n  \u003cmain class=\"prettify\" style=\"background: #fff; text-align: center;\" /\u003e\n`;\n\nconst options = {\n  replace(domNode) {\n    if (domNode.attribs \u0026\u0026 domNode.name === 'main') {\n      const props = attributesToProps(domNode.attribs);\n      return \u003cdiv {...props} /\u003e;\n    }\n  },\n};\n\nparse(html, options);\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eHTML output\u003c/summary\u003e\n\u003cp\u003e\n\n```html\n\u003cdiv class=\"prettify\" style=\"background:#fff;text-align:center\"\u003e\u003c/div\u003e\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n#### replace and remove element\n\n[Exclude](https://replit.com/@remarkablemark/html-react-parser-56) an element from rendering by replacing it with `\u003cReact.Fragment\u003e`:\n\n```tsx\nparse('\u003cp\u003e\u003cbr id=\"remove\"\u003e\u003c/p\u003e', {\n  replace: ({ attribs }) =\u003e attribs?.id === 'remove' \u0026\u0026 \u003c\u003e\u003c/\u003e,\n});\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eHTML output\u003c/summary\u003e\n\u003cp\u003e\n\n```html\n\u003cp\u003e\u003c/p\u003e\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n### transform\n\nThe `transform` option allows you to transform each element individually after it's parsed.\n\nThe `transform` callback's first argument is the React element:\n\n```tsx\nparse('\u003cbr\u003e', {\n  transform(reactNode, domNode, index) {\n    // this will wrap every element in a div\n    return \u003cdiv\u003e{reactNode}\u003c/div\u003e;\n  },\n});\n```\n\n### library\n\nThe `library` option specifies the UI library. The default library is **React**.\n\nTo use Preact:\n\n```ts\nparse('\u003cbr\u003e', {\n  library: require('preact'),\n});\n```\n\nOr a custom library:\n\n```ts\nparse('\u003cbr\u003e', {\n  library: {\n    cloneElement: () =\u003e {\n      /* ... */\n    },\n    createElement: () =\u003e {\n      /* ... */\n    },\n    isValidElement: () =\u003e {\n      /* ... */\n    },\n  },\n});\n```\n\n### htmlparser2\n\n\u003e [!WARNING]\n\u003e\n\u003e `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.\n\nDefault [htmlparser2 options](https://github.com/fb55/htmlparser2/wiki/Parser-options#option-xmlmode) can be overridden in \u003e=[0.12.0](https://github.com/remarkablemark/html-react-parser/tree/v0.12.0).\n\nTo enable [`xmlMode`](https://github.com/fb55/htmlparser2/wiki/Parser-options#option-xmlmode):\n\n```ts\nparse('\u003cp /\u003e\u003cp /\u003e', {\n  htmlparser2: {\n    xmlMode: true,\n  },\n});\n```\n\n### trim\n\nBy default, whitespace is preserved:\n\n```ts\nparse('\u003cbr\u003e\\n'); // [React.createElement('br'), '\\n']\n```\n\nBut certain elements like `\u003ctable\u003e` will strip out invalid whitespace:\n\n```ts\nparse('\u003ctable\u003e\\n\u003c/table\u003e'); // React.createElement('table')\n```\n\nTo remove whitespace, enable the `trim` option:\n\n```ts\nparse('\u003cbr\u003e\\n', { trim: true }); // React.createElement('br')\n```\n\nHowever, intentional whitespace may be stripped out:\n\n```ts\nparse('\u003cp\u003e \u003c/p\u003e', { trim: true }); // React.createElement('p')\n```\n\n## Migration\n\n### v5\n\nMigrated to TypeScript. CommonJS imports require the `.default` key:\n\n```ts\nconst parse = require('html-react-parser').default;\n```\n\nIf you're getting the error:\n\n```\nArgument of type 'ChildNode[]' is not assignable to parameter of type 'DOMNode[]'.\n```\n\nThen use type assertion:\n\n```ts\ndomToReact(domNode.children as DOMNode[], options);\n```\n\nSee [#1126](https://github.com/remarkablemark/html-react-parser/issues/1126#issuecomment-1784188447).\n\n### v4\n\n[htmlparser2](https://github.com/fb55/htmlparser2) has been upgraded to [v9](https://github.com/fb55/htmlparser2/releases/tag/v9.0.0).\n\n### v3\n\n[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.\n\nAlso, it's recommended to upgrade to the latest version of [TypeScript](https://www.npmjs.com/package/typescript).\n\n### v2\n\nSince [v2.0.0](https://github.com/remarkablemark/html-react-parser/releases/tag/v2.0.0), Internet Explorer (IE) is no longer supported.\n\n### v1\n\nTypeScript projects will need to update the types in [v1.0.0](https://github.com/remarkablemark/html-react-parser/releases/tag/v1.0.0).\n\nFor the `replace` option, you may need to do the following:\n\n```tsx\nimport { Element } from 'domhandler/lib/node';\n\nparse('\u003cbr class=\"remove\"\u003e', {\n  replace(domNode) {\n    if (domNode instanceof Element \u0026\u0026 domNode.attribs.class === 'remove') {\n      return \u003c\u003e\u003c/\u003e;\n    }\n  },\n});\n```\n\nSince [v1.1.1](https://github.com/remarkablemark/html-react-parser/releases/tag/v1.1.1), Internet Explorer 9 (IE9) is no longer supported.\n\n## FAQ\n\n### Is this XSS safe?\n\nNo, 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).\n\n### Does invalid HTML get sanitized?\n\nNo, 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).\n\n### Are `\u003cscript\u003e` tags parsed?\n\nAlthough `\u003cscript\u003e` 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).\n\n### Attributes aren't getting called\n\nThe 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).\n\n### Parser throws an error\n\nIf the parser throws an error, check if your arguments are valid. See [\"Does invalid HTML get sanitized?\"](#does-invalid-html-get-sanitized).\n\n### Is SSR supported?\n\nYes, server-side rendering on Node.js is supported by this library. See [demo](https://replit.com/@remarkablemark/html-react-parser-SSR).\n\n### Elements aren't nested correctly\n\nIf 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 (`/\u003e`) on non-void elements:\n\n```js\nparse('\u003cdiv /\u003e\u003cdiv /\u003e'); // returns single element instead of array of elements\n```\n\nSee [#158](https://github.com/remarkablemark/html-react-parser/issues/158).\n\n### Don't change case of tags\n\nTags are lowercased by default. To prevent that from happening, pass the [htmlparser2 option](#htmlparser2):\n\n```js\nconst options = {\n  htmlparser2: {\n    lowerCaseTags: false,\n  },\n};\nparse('\u003cCustomElement\u003e', options); // React.createElement('CustomElement')\n```\n\n\u003e [!WARNING]\n\u003e\n\u003e By preserving case-sensitivity of the tags, you may get rendering warnings like:\n\u003e\n\u003e ```\n\u003e Warning: \u003cCustomElement\u003e is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.\n\u003e ```\n\nSee [#62](https://github.com/remarkablemark/html-react-parser/issues/62) and [example](https://replit.com/@remarkablemark/html-react-parser-62).\n\n### TS Error: Property 'attribs' does not exist on type 'DOMNode'\n\nThe 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).\n\n### Can I enable `trim` for certain elements?\n\nYes, 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).\n\n### Webpack build warnings\n\nIf you see the Webpack build warning:\n\n```\nexport 'default' (imported as 'parse') was not found in 'html-react-parser'\n```\n\nThen update your Webpack config to:\n\n```js\n// webpack.config.js\nmodule.exports = {\n  // ...\n  resolve: {\n    mainFields: ['browser', 'main', 'module'],\n  },\n};\n```\n\nSee [#238](https://github.com/remarkablemark/html-react-parser/issues/238) and [#213](https://github.com/remarkablemark/html-react-parser/issues/213).\n\n### TypeScript error\n\nIf you see the TypeScript error:\n\n```\nnode_modules/htmlparser2/lib/index.d.ts:2:23 - error TS1005: ',' expected.\n\n2 export { Parser, type ParserOptions };\n                        ~~~~~~~~~~~~~\n```\n\nThen upgrade to the latest version of [typescript](https://www.npmjs.com/package/typescript). See [#748](https://github.com/remarkablemark/html-react-parser/issues/748).\n\n## Performance\n\nRun benchmark:\n\n```sh\nnpm run benchmark\n```\n\nOutput of benchmark run on MacBook Pro 2024:\n\n```\nhtml-to-react - Single x 1,230,874 ops/sec ±0.21% (97 runs sampled)\nhtml-to-react - Multiple x 502,028 ops/sec ±0.89% (94 runs sampled)\nhtml-to-react - Complex x 54,401 ops/sec ±0.76% (93 runs sampled)\n```\n\nRun [Size Limit](https://github.com/ai/size-limit):\n\n```sh\nnpx size-limit\n```\n\n## Contributors\n\n### Code Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](https://github.com/remarkablemark/html-react-parser/blob/master/.github/CONTRIBUTING.md)].\n\n[![Code Contributors](https://contrib.rocks/image?repo=remarkablemark/html-react-parser)](https://github.com/remarkablemark/html-react-parser/graphs/contributors)\n\n### Financial Contributors\n\nBecome a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/html-react-parser/contribute)]\n\n#### Individuals\n\n[![Financial Contributors - Individuals](https://opencollective.com/html-react-parser/individuals.svg?width=890)](https://opencollective.com/html-react-parser)\n\n#### Organizations\n\nSupport 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)]\n\n[![Financial Contributors - Organization 0](https://opencollective.com/html-react-parser/organization/0/avatar.svg)](https://opencollective.com/html-react-parser/organization/0/website)\n[![Financial Contributors - Organization 1](https://opencollective.com/html-react-parser/organization/1/avatar.svg)](https://opencollective.com/html-react-parser/organization/1/website)\n[![Financial Contributors - Organization 2](https://opencollective.com/html-react-parser/organization/2/avatar.svg)](https://opencollective.com/html-react-parser/organization/2/website)\n[![Financial Contributors - Organization 3](https://opencollective.com/html-react-parser/organization/3/avatar.svg)](https://opencollective.com/html-react-parser/organization/3/website)\n[![Financial Contributors - Organization 4](https://opencollective.com/html-react-parser/organization/4/avatar.svg)](https://opencollective.com/html-react-parser/organization/4/website)\n[![Financial Contributors - Organization 5](https://opencollective.com/html-react-parser/organization/5/avatar.svg)](https://opencollective.com/html-react-parser/organization/5/website)\n[![Financial Contributors - Organization 6](https://opencollective.com/html-react-parser/organization/6/avatar.svg)](https://opencollective.com/html-react-parser/organization/6/website)\n[![Financial Contributors - Organization 7](https://opencollective.com/html-react-parser/organization/7/avatar.svg)](https://opencollective.com/html-react-parser/organization/7/website)\n[![Financial Contributors - Organization 8](https://opencollective.com/html-react-parser/organization/8/avatar.svg)](https://opencollective.com/html-react-parser/organization/8/website)\n[![Financial Contributors - Organization 9](https://opencollective.com/html-react-parser/organization/9/avatar.svg)](https://opencollective.com/html-react-parser/organization/9/website)\n\n## Support\n\n- [GitHub Sponsors](https://b.remarkabl.org/github-sponsors)\n- [Open Collective](https://b.remarkabl.org/open-collective-html-react-parser)\n- [Tidelift](https://b.remarkabl.org/tidelift-html-react-parser)\n- [Patreon](https://b.remarkabl.org/patreon)\n- [Ko-fi](https://b.remarkabl.org/ko-fi)\n- [Liberapay](https://b.remarkabl.org/liberapay)\n- [Teespring](https://b.remarkabl.org/teespring)\n\n## License\n\n[MIT](https://github.com/remarkablemark/html-react-parser/blob/master/LICENSE)\n","funding_links":["https://github.com/sponsors/remarkablemark","https://patreon.com/remarkablemark","https://ko-fi.com/remarkablemark","https://liberapay.com/remarkablemark","https://buymeacoffee.com/remarkablemark","https://thanks.dev/u/gh/remarkablemark","https://b.remarkabl.org/teespring","https://opencollective.com/html-react-parser/contribute","https://opencollective.com/html-react-parser","https://opencollective.com/html-react-parser/organization/0/website","https://opencollective.com/html-react-parser/organization/1/website","https://opencollective.com/html-react-parser/organization/2/website","https://opencollective.com/html-react-parser/organization/3/website","https://opencollective.com/html-react-parser/organization/4/website","https://opencollective.com/html-react-parser/organization/5/website","https://opencollective.com/html-react-parser/organization/6/website","https://opencollective.com/html-react-parser/organization/7/website","https://opencollective.com/html-react-parser/organization/8/website","https://opencollective.com/html-react-parser/organization/9/website"],"categories":["JavaScript","TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremarkablemark%2Fhtml-react-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fremarkablemark%2Fhtml-react-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fremarkablemark%2Fhtml-react-parser/lists"}