academic/src/components/Mdown.tsx
2025-09-04 20:51:12 +02:00

60 lines
2.1 KiB
TypeScript

import { Link } from '@tanstack/react-router'
import Markdown from 'react-markdown'
import rehypeRaw from 'rehype-raw'
import rehypeSanitize from 'rehype-sanitize'
import remarkGfm from 'remark-gfm'
interface Props {
children: string
}
export default function Mdown({ children }: Props) {
return (
<Markdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw, rehypeSanitize]}
components={{
ul(props) {
const { node, ...rest } = props
return <ul className="list-disc list-inside" {...rest} />
},
li(props) {
const { node, ...rest } = props
return <li className="pl-5" {...rest} />
},
a(props) {
const { node, ...rest } = props
const classes = 'text-sky-600 underline'
if (rest.href?.startsWith('dl:')) {
let parts = rest.href.split('/')
return (
<a
className={classes}
href={rest.href.replace('dl:', '')}
download={parts[parts.length - 1]}
{...rest}
/>
)
}
if (rest.href?.startsWith('/public')) {
return (
<a className={classes} target="_blank" {...rest} />
)
}
if (rest.href?.startsWith('/')) {
return (
<Link
className={classes}
to={rest.href}
{...rest}
/>
)
}
return <a className={classes} {...rest} />
},
}}
>
{children}
</Markdown>
)
}