본문으로 건너뛰기

safe-html-react-parser

A secure wrapper for html-react-parser with DOMPurify that automatically sanitizes HTML before parsing.

What it does

  • 🛡️ Security: Automatically sanitizes malicious HTML using DOMPurify
  • ⚛️ React: Seamlessly integrates with html-react-parser
  • 🌐 Universal: Works in both browser and Node.js (SSR) environments
  • 🏷️ Custom Tags: Handles project-specific tags like <custom> safely
  • 🚀 Flexible: Choose your DOM implementation (jsdom, happy-dom, or linkedom)
  • Optimized: Built-in caching and memory management

Installation

npm install @naverpay/safe-html-react-parser

Choosing a DOM Implementation (Server-Side Only)

For server-side rendering, you need to install one of the following DOM implementations:

# Option 1: jsdom (most complete, heavier)
npm install jsdom

# Option 2: happy-dom (faster, lighter, recommended)
npm install happy-dom

# Option 3: linkedom (fastest, lightest)
npm install linkedom

The library will automatically detect and use the first available implementation in this order: jsdom → happy-dom → linkedom.

Basic Usage

import { safeParse } from '@naverpay/safe-html-react-parser'

// Basic usage - automatically sanitizes dangerous HTML
const Component = () => {
const maliciousHtml = '<p>Hello <script>alert("XSS")</script>World</p>'
return <div>{safeParse(maliciousHtml)}</div>
}
// Result: <div><p>Hello World</p></div>

API

safeParse(htmlString, options?)

Parses HTML string into React elements with automatic XSS protection.

Parameters

  • htmlString (string): The HTML string to parse
  • options (SafeParseOptions, optional): Configuration options

Options

interface SafeParseOptions extends HTMLReactParserOptions {
// DOMPurify configuration
sanitizeConfig?: DOMPurify.Config

// Custom tags to preserve during sanitization
preserveCustomTags?: string[]
}

Returns

React elements or array of React elements

Advanced Usage

Custom Sanitization Config

import { safeParse } from '@naverpay/safe-html-react-parser'

const html = '<div class="content"><style>body{color:red}</style><p>Text</p></div>'

const result = safeParse(html, {
sanitizeConfig: {
ALLOWED_TAGS: ['div', 'p', 'style'], // Allow style tags
ALLOWED_ATTR: ['class'],
ALLOW_ARIA_ATTR: true
}
})

Preserving Custom Tags

Use preserveCustomTags to preserve project-specific tags that would otherwise be removed:

import { safeParse } from '@naverpay/safe-html-react-parser'

// Preserve custom tags like <g>, <path>, etc.
const svgContent = '<g><path d="M10,10 L20,20"/></g>'

const result = safeParse(svgContent, {
preserveCustomTags: ['g', 'path'],
replace: (domNode) => {
if (domNode.name === 'g') {
return <g {...domNode.attribs}>{/* custom rendering */}</g>
}
if (domNode.name === 'path') {
return <path {...domNode.attribs} />
}
}
})

Using with html-react-parser Options

All html-react-parser options are supported:

import { safeParse } from '@naverpay/safe-html-react-parser'

const html = '<div id="content"><p>Hello</p><img src="image.jpg" alt="test"/></div>'

const result = safeParse(html, {
replace: (domNode) => {
if (domNode.name === 'img') {
return <img {...domNode.attribs} loading="lazy" />
}
},
trim: true
})

Configuring DOM Implementation (Server-Side)

You have two ways to configure the DOM implementation:

Pass domPurifyOptions directly to safeParse():

import { safeParse } from '@naverpay/safe-html-react-parser'
import { Window } from 'happy-dom'

const result = safeParse(htmlString, {
domPurifyOptions: {
domWindowFactory: () => new Window(),
enableCache: true,
maxCacheSize: 100
}
})

Method 2: Global configuration

Configure once at app initialization:

import { configureDOMPurify } from '@naverpay/safe-html-react-parser'

// Using jsdom
import { JSDOM } from 'jsdom'
configureDOMPurify({
domWindowFactory: () => new JSDOM('<!DOCTYPE html>'),
enableCache: true,
maxCacheSize: 100,
recreateInterval: 1000 // Recreate DOM instance every 1000 sanitizations
})

// Using happy-dom (recommended for better performance)
import { Window } from 'happy-dom'
configureDOMPurify({
domWindowFactory: () => new Window(),
enableCache: true,
recreateInterval: 500
})

// Using linkedom (fastest, minimal footprint)
import { parseHTML } from 'linkedom'
configureDOMPurify({
domWindowFactory: () => parseHTML('<!DOCTYPE html>'),
enableCache: true
})

[!NOTE]

If you don't configure anything, the library will automatically try jsdom → happy-dom → linkedom in that order.

Default Allowed Tags

By default, the following HTML tags are allowed:

ALLOWED_TAGS: [
'p', 'br', 'strong', 'em', 'b', 'i', 'u', 'span', 'div',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h',
'ul', 'ol', 'li', 'dl', 'dt', 'dd',
'a', 'img'
]

Performance Optimization

Caching

By default, caching is enabled to improve performance:

configureDOMPurify({
enableCache: true, // Default: true
maxCacheSize: 100, // Default: 100
})

Memory Management

The DOM instance is automatically recreated periodically to prevent memory leaks:

configureDOMPurify({
recreateInterval: 1000 // Default: 1000 sanitization calls
})

DOM Implementation Comparison

ImplementationSpeedMemoryCompletenessRecommended For
jsdomSlowerHigherMost completeMaximum compatibility
happy-domFastMediumGoodBalanced (Recommended)
linkedomFastestLowestBasicPerformance-critical apps

Security Notes

  • All HTML is sanitized by DOMPurify before parsing
  • Dangerous tags like <script>, <iframe>, <object> are automatically removed
  • Event handlers like onclick, onload are stripped out
  • Only safe attributes are preserved by default

Built with

License

MIT