Nonviolent Pigeon Manifestation
    Have ideas to improve npm?Join in the discussion! »

    html-react-parser
    TypeScript icon, indicating that this package has built-in type declarations

    1.2.6 • Public • Published

    html-react-parser

    NPM

    NPM version Build Status Coverage Status Dependency status 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

    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

    NPM:

    $ npm install html-react-parser --save

    Yarn:

    $ yarn add html-react-parser

    CDN:

    <!-- HTMLReactParser depends on React -->
    <script src="https://unpkg.com/react@17/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 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>;
        }
      }
    });

    replace with TypeScript

    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) {
          // ...
        }
      }
    };

    If you're having issues with domNode instanceof Element, try this alternative solution.

    replace element and children

    Replace the element and its children (see demo):

    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 && attribs.id === 'remove' && <></>
    });

    HTML output:

    <p></p>

    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

    htmlparser2 options do not work on the client-side (browser) and only works on the server-side (Node.js). By overriding htmlparser2 options, universal rendering can break.

    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']

    To remove whitespace, enable the trim option:

    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.

    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 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.
    

    See #62 and example.

    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.

    Can I enable trim for certain elements?

    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].

    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

    License

    MIT

    Install

    npm i html-react-parser

    DownloadsWeekly Downloads

    396,077

    Version

    1.2.6

    License

    MIT

    Unpacked Size

    322 kB

    Total Files

    16

    Last publish

    Collaborators

    • avatar