Files
fast-next-template/frontend/src/components/docs/MarkdownContent.tsx

221 lines
6.5 KiB
TypeScript

/* istanbul ignore file */
/**
* MarkdownContent Component
* Renders markdown content with syntax highlighting and design system styling
* This file is excluded from coverage as it's a documentation component
*/
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeHighlight from 'rehype-highlight';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import { cn } from '@/lib/utils';
import 'highlight.js/styles/github-dark.css';
interface MarkdownContentProps {
content: string;
className?: string;
}
export function MarkdownContent({ content, className }: MarkdownContentProps) {
return (
<div className={cn('prose prose-neutral dark:prose-invert max-w-none', className)}>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[
rehypeHighlight,
rehypeSlug,
[rehypeAutolinkHeadings, { behavior: 'wrap' }],
]}
components={{
// Headings
h1: ({ children, ...props }) => (
<h1
className="scroll-mt-20 text-4xl font-bold tracking-tight mb-6 mt-8 first:mt-0 border-b pb-3"
{...props}
>
{children}
</h1>
),
h2: ({ children, ...props }) => (
<h2
className="scroll-mt-20 text-3xl font-semibold tracking-tight mb-4 mt-10 first:mt-0 border-b pb-2"
{...props}
>
{children}
</h2>
),
h3: ({ children, ...props }) => (
<h3
className="scroll-mt-20 text-2xl font-semibold tracking-tight mb-3 mt-8 first:mt-0"
{...props}
>
{children}
</h3>
),
h4: ({ children, ...props }) => (
<h4
className="scroll-mt-20 text-xl font-semibold tracking-tight mb-2 mt-6 first:mt-0"
{...props}
>
{children}
</h4>
),
// Paragraphs and text
p: ({ children, ...props }) => (
<p className="leading-7 mb-4 text-foreground" {...props}>
{children}
</p>
),
strong: ({ children, ...props }) => (
<strong className="font-semibold text-foreground" {...props}>
{children}
</strong>
),
em: ({ children, ...props }) => (
<em className="italic" {...props}>
{children}
</em>
),
// Links
a: ({ children, href, ...props }) => (
<a
href={href}
className="font-medium text-primary underline underline-offset-4 hover:text-primary/80 transition-colors"
{...props}
>
{children}
</a>
),
// Lists
ul: ({ children, ...props }) => (
<ul className="my-4 ml-6 list-disc space-y-2" {...props}>
{children}
</ul>
),
ol: ({ children, ...props }) => (
<ol className="my-4 ml-6 list-decimal space-y-2" {...props}>
{children}
</ol>
),
li: ({ children, ...props }) => (
<li className="leading-7 text-foreground" {...props}>
{children}
</li>
),
// Code blocks
code: ({ inline, className, children, ...props }: {
inline?: boolean;
className?: string;
children?: React.ReactNode;
}) => {
if (inline) {
return (
<code
className="relative rounded bg-muted px-[0.4rem] py-[0.2rem] font-mono text-sm font-medium text-foreground border"
{...props}
>
{children}
</code>
);
}
return (
<code
className={cn(
'block font-mono text-sm',
className
)}
{...props}
>
{children}
</code>
);
},
pre: ({ children, ...props }) => (
<pre
className="mb-4 mt-4 overflow-x-auto rounded-lg border bg-muted/30 p-4 font-mono text-sm"
{...props}
>
{children}
</pre>
),
// Blockquotes
blockquote: ({ children, ...props }) => (
<blockquote
className="mt-6 border-l-4 border-primary pl-4 italic text-muted-foreground"
{...props}
>
{children}
</blockquote>
),
// Tables
table: ({ children, ...props }) => (
<div className="my-6 w-full overflow-x-auto">
<table
className="w-full border-collapse text-sm"
{...props}
>
{children}
</table>
</div>
),
thead: ({ children, ...props }) => (
<thead className="border-b bg-muted/50" {...props}>
{children}
</thead>
),
tbody: ({ children, ...props }) => (
<tbody {...props}>{children}</tbody>
),
tr: ({ children, ...props }) => (
<tr className="border-b transition-colors hover:bg-muted/30" {...props}>
{children}
</tr>
),
th: ({ children, ...props }) => (
<th
className="px-4 py-3 text-left font-semibold [&[align=center]]:text-center [&[align=right]]:text-right"
{...props}
>
{children}
</th>
),
td: ({ children, ...props }) => (
<td
className="px-4 py-3 [&[align=center]]:text-center [&[align=right]]:text-right"
{...props}
>
{children}
</td>
),
// Horizontal rule
hr: ({ ...props }) => (
<hr className="my-8 border-t border-border" {...props} />
),
// Images
img: ({ src, alt, ...props }) => (
<img
src={src}
alt={alt}
className="rounded-lg border my-6"
{...props}
/>
),
}}
>
{content}
</ReactMarkdown>
</div>
);
}