sendou.ink/app/components/Markdown.tsx
Kalle fef1ffc955
Design refresh + a bunch of stuff (#2864)
Co-authored-by: hfcRed <hfcred@gmx.net>
2026-03-19 17:51:42 +02:00

44 lines
1.3 KiB
TypeScript

import MarkdownToJsx from "markdown-to-jsx";
import * as React from "react";
// note: markdown-to-jsx also handles these, this is just to prevent them from appearing as plain text
const DANGEROUS_HTML_TAGS_REGEX =
/<(style|link|head|iframe|script|title|textarea|xmp|noembed|noframes|plaintext)[\s\S]*?<\/\1>|<(style|link|head|iframe|script|title|textarea|xmp|noembed|noframes|plaintext)[^>]*\/>/gi;
const CSS_URL_REGEX = /url\s*\([^)]*\)/gi;
export function Markdown({ children }: { children: string }) {
const sanitized = children
.replace(DANGEROUS_HTML_TAGS_REGEX, "")
.replace(/style\s*=\s*("[^"]*"|'[^']*')/gi, (_match, value) => {
const sanitized = value.replace(CSS_URL_REGEX, "");
return `style=${sanitized}`;
})
.replace(/ +$/gm, "");
return (
<MarkdownToJsx
options={{
wrapper: React.Fragment,
overrides: {
br: { component: () => <br /> },
hr: { component: () => <hr /> },
img: {
component: ({
children: _,
...props
}: React.ComponentProps<"img"> & {
children?: React.ReactNode;
}) => (
// biome-ignore lint/a11y/useAltText: parsed markdown, so we can't guarantee alt text is present
<img {...props} referrerPolicy="no-referrer" />
),
},
},
}}
>
{sanitized}
</MarkdownToJsx>
);
}