Declarative, composable and secure HTML rendering for React.
Read the introduction article for the thoughts behind this lib.
Provide your html, your 'tag mapping', and you're done!
import HtmlMapper from 'react-html-map';
<HtmlMapper html={html}>
{{
p: Body,
h1: (props) => <Title variant="large" {...props} />,
h2: (props) => <Title variant="regular" {...props} />,
h3: (props) => <Title variant="small" {...props} />,
h4: (props) => <Title variant="micro" {...props} />,
h5: (props) => <Title variant="tiny" {...props} />,
a: ({ href, children, ...rest }) =>
href?.startsWith("/") ? (
// assume internal link
<Link to={href}>{children}</Link>
) : (
<a href={href} {...rest}>
{children}
</a>
),
}}
</HtmlMapper>
This pattern can become quite powerful when reusing a tag mapping and overriding it as you deem fit, for example, in a situation where you want your p
tags to be a tad bigger than the 'default':
const tagMap = { p: Body, h1: ... };
return (
<>
<HtmlMapper html={intro}>
{{
...tagMap,
p: ({ ...props }) => <Body variant="large" {...props} />,
}}
</HtmlMapper>
<HtmlMapper html={text}>{tagMap}</HtmlMapper>
</>
);
By default, react-html-map
will ignore any tags that are not provided in your tag map.
If you want to pass specific elements through 'as-is', you can define them with null
in your tag mapping:
<HtmlMapper html={html}>
{{
p: Body,
...
strong: null,
ul: null,
li: null,
br: null,
}}
</HtmlMapper>
If you wish to have react-html-map
pass through all tags it does not recognize, you can pass the acceptUnknown
prop:
<HtmlMapper
html={html}
// now we'll accept tags like strong by default,
// but at the cost of predictibility and security.
acceptUnknown
>
{{ p: Body }}
</HtmlMapper>
This is however NOT recommended, as it might leave you vulnerable to XSS attacks.
npm i react-html-map
- Library code
- Write README
- Basic tests (does it crash?)
- Snapshot tests (does it render what we expect it to render?)
- Example website (long term goal)
An example exists in theexample/
folder at the moment, but it's not quite finished just yet.