Safe, GFM-friendly Markdown → React renderer with sanitation, link policy, and image allowlists.
Perfect for rendering AI / user-generated content without inviting XSS or layout chaos.
- ✅ No raw HTML from Markdown (by default)
- ✅ Sanitized output via
rehype-sanitize
(strict schema) - ✅ GFM support (tables, strikethrough, task lists)
- ✅ Link policy: adds
rel="nofollow noopener noreferrer"
andtarget="_blank"
- ✅ Image allowlist: blocks images unless host is allowed
- ✅ Heading depth guard: cap headings to a max level (e.g.,
h1..h3
only) - ✅ Override components: map tags to your React components
- ✅ TypeScript types, React 18+
npm i safe-markdown-react
# peer deps: react >= 18
import { SafeMarkdown } from 'safe-markdown-react';
export default function Article({ content }: { content: string }) {
return (
<SafeMarkdown
markdown={content}
allowedImageHosts={['images.example.com', 'cdn.jsdelivr.net']}
maxHeadingLevel={3}
linkTarget="_blank"
/>
);
}
import { SafeMarkdown } from 'safe-markdown-react';
const components = {
h2: (props) => <h2 className="text-2xl font-semibold" {...props} />,
code: (props) => <code className="rounded bg-zinc-950/90 px-1 py-0.5" {...props} />,
};
<SafeMarkdown markdown={md} components={components} />;
Props:
-
markdown: string
— the raw Markdown text -
allowedImageHosts?: string[]
— host allowlist for<img src>
. Defaults to[]
(block external images). -
allowedSchemes?: string[]
— URL schemes to permit inhref/src
. Defaults to['http', 'https', 'mailto']
. -
maxHeadingLevel?: 1|2|3|4|5|6
— cap headings to at most this level (default3
). -
linkRel?: string
— rel attribute for links (default'nofollow noopener noreferrer'
). -
linkTarget?: string
— target for links (default'_blank'
). -
components?: Record<string, React.ComponentType<any>>
— map element names to your components.
- Raw HTML in Markdown is ignored. If you need it, you must opt-in and extend the sanitizer schema carefully.
- Links always get safe
rel
andtarget
by default. - Images are blocked unless you allow a host explicitly.
- Only standard schemes (
http
,https
,mailto
) are allowed by default.
MIT