import React, { type JSX, ComponentType } from 'react'; import DomPurify from 'dompurify'; import parse, { domToReact, HTMLReactParserOptions, Element, DOMNode, attributesToProps, } from 'html-react-parser'; import { List, ListItem } from '@digigov/ui/content/List'; import { Link } from '@digigov/ui/navigation'; import { Heading } from '@digigov/ui/typography/Heading'; import { NormalText } from '@digigov/ui/typography/NormalText'; import { Paragraph } from '@digigov/ui/typography/Paragraph'; interface RegistryComponentProps { children?: React.ReactNode; [key: string]: any; } type ComponentsRegistry = Record>; export const componentsRegistry: ComponentsRegistry = { h1: (props) => {props.children}, h2: (props) => {props.children}, h3: (props) => {props.children}, h4: (props) => {props.children}, h5: (props) => {props.children}, a: (props) => {props.children}, p: (props) => {props.children}, span: (props) => {props.children}, ul: (props) => {props.children}, ol: (props) => {props.children}, li: (props) => {props.children}, br: () =>
, b: (props) => {props.children}, strong: (props) => {props.children}, i: (props) => {props.children}, sup: (props) => {props.children}, sub: (props) => {props.children}, img: (props) => , }; export interface SafeHTMLProps { content: string; Tag?: keyof JSX.IntrinsicElements; } export const SafeHTML = ({ content, Tag = 'span', ...props }: SafeHTMLProps) => { const purifiedHtmlString = DomPurify.sanitize(content, { ALLOWED_TAGS: [...Object.keys(componentsRegistry)], }); const options: HTMLReactParserOptions = { replace(domNode) { if (!(domNode instanceof Element && domNode.attribs)) return; const Component = componentsRegistry[domNode.name]; if (!Component) return; const reactProps = attributesToProps(domNode.attribs); if (domNode.children && domNode.children.length > 0) { return ( {domToReact(domNode.children as DOMNode[], options)} ); } return ; }, }; return {parse(purifiedHtmlString, options)}; }; export default SafeHTML;