53 lines
2.1 KiB
JavaScript
53 lines
2.1 KiB
JavaScript
import React, { lazy, Suspense } from 'react';
|
|
|
|
// Load html-react-parser and sanitize-html in a single async chunk.
|
|
// Neither library ships in the main bundle — they are only fetched when a
|
|
// component that uses this wrapper actually renders.
|
|
const SanitizedHtmlContent = lazy(() =>
|
|
Promise.all([
|
|
import(/* webpackChunkName: "html-parser" */ 'html-react-parser'),
|
|
import(/* webpackChunkName: "html-parser" */ 'sanitize-html'),
|
|
]).then(([{ default: parse }, { default: sanitizeHtml }]) => ({
|
|
default: function SanitizedHtmlContent({ html, sanitizeOptions, parseOptions }) {
|
|
try {
|
|
// sanitizeOptions can be a plain object or a factory (fn) that receives
|
|
// the sanitizeHtml module so callers can reference sanitizeHtml.defaults.
|
|
const resolvedSanitizeOptions =
|
|
typeof sanitizeOptions === 'function'
|
|
? sanitizeOptions(sanitizeHtml)
|
|
: sanitizeOptions;
|
|
|
|
const sanitized = sanitizeHtml(html, resolvedSanitizeOptions);
|
|
return parse(sanitized, parseOptions);
|
|
} catch (error) {
|
|
console.warn('LazySanitizedHtml: failed to parse HTML', error);
|
|
return <span>{html}</span>;
|
|
}
|
|
},
|
|
}))
|
|
);
|
|
|
|
/**
|
|
* Renders sanitized and parsed HTML without including sanitize-html or
|
|
* html-react-parser in the initial JavaScript bundle.
|
|
*
|
|
* @param {string} html Raw HTML string to sanitize and render
|
|
* @param {object|function} sanitizeOptions sanitize-html options object, or a
|
|
* factory (sanitizeHtml) => options so
|
|
* callers can use sanitizeHtml.defaults
|
|
* @param {object} parseOptions html-react-parser options (e.g. replace)
|
|
* @param {React.ReactNode} fallback Shown while the libraries are loading
|
|
*/
|
|
export default function LazySanitizedHtml({ html, sanitizeOptions, parseOptions, fallback = null }) {
|
|
if (!html) return null;
|
|
return (
|
|
<Suspense fallback={fallback}>
|
|
<SanitizedHtmlContent
|
|
html={html}
|
|
sanitizeOptions={sanitizeOptions}
|
|
parseOptions={parseOptions}
|
|
/>
|
|
</Suspense>
|
|
);
|
|
}
|