2026-03-18 18:50:26 +08:00
|
|
|
import ReactMarkdown from 'react-markdown'
|
|
|
|
|
import remarkGfm from 'remark-gfm'
|
|
|
|
|
import type { Components } from 'react-markdown'
|
2026-03-18 14:09:06 +08:00
|
|
|
|
|
|
|
|
interface DocContentProps {
|
2026-03-18 18:50:26 +08:00
|
|
|
content: string
|
2026-03-18 14:09:06 +08:00
|
|
|
onReferenceClick: (ref: string) => void
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-18 18:50:26 +08:00
|
|
|
export const DocContent = ({ content, onReferenceClick }: DocContentProps) => {
|
|
|
|
|
if (!content) {
|
2026-03-18 14:09:06 +08:00
|
|
|
return (
|
|
|
|
|
<div className="flex items-center justify-center h-full text-gray-500">
|
|
|
|
|
<p>Select a document from the sidebar</p>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-18 18:50:26 +08:00
|
|
|
const components: Components = {
|
|
|
|
|
a: ({ href, children }) => {
|
|
|
|
|
if (href && (href.startsWith('./') || href.startsWith('../'))) {
|
2026-03-18 14:09:06 +08:00
|
|
|
return (
|
|
|
|
|
<button
|
2026-03-18 18:50:26 +08:00
|
|
|
onClick={() => onReferenceClick(href)}
|
2026-03-18 14:09:06 +08:00
|
|
|
className="text-blue-400 hover:text-blue-300 hover:underline"
|
|
|
|
|
>
|
2026-03-18 18:50:26 +08:00
|
|
|
{children}
|
2026-03-18 14:09:06 +08:00
|
|
|
</button>
|
|
|
|
|
)
|
|
|
|
|
}
|
2026-03-18 18:50:26 +08:00
|
|
|
return (
|
|
|
|
|
<a href={href} className="text-blue-400 hover:text-blue-300 hover:underline">
|
|
|
|
|
{children}
|
|
|
|
|
</a>
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
code: ({ className, children, ...props }) => {
|
|
|
|
|
const match = /language-(\w+)/.exec(className || '')
|
|
|
|
|
if (match) {
|
|
|
|
|
return (
|
|
|
|
|
<code className={className} {...props}>
|
|
|
|
|
{children}
|
|
|
|
|
</code>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<code className="bg-gray-800 px-1.5 py-0.5 rounded text-blue-300 text-sm font-mono" {...props}>
|
|
|
|
|
{children}
|
|
|
|
|
</code>
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
pre: ({ children }) => (
|
|
|
|
|
<pre className="bg-gray-900 border border-gray-700 rounded-lg p-4 overflow-x-auto mb-4">
|
|
|
|
|
{children}
|
|
|
|
|
</pre>
|
|
|
|
|
),
|
|
|
|
|
table: ({ children }) => (
|
|
|
|
|
<div className="overflow-x-auto mb-4">
|
|
|
|
|
<table className="w-full border-collapse text-sm">
|
|
|
|
|
{children}
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
),
|
|
|
|
|
thead: ({ children }) => (
|
|
|
|
|
<thead className="bg-gray-800">
|
|
|
|
|
{children}
|
|
|
|
|
</thead>
|
|
|
|
|
),
|
|
|
|
|
th: ({ children }) => (
|
|
|
|
|
<th className="border border-gray-600 px-3 py-2 text-left text-gray-200 font-semibold">
|
|
|
|
|
{children}
|
|
|
|
|
</th>
|
|
|
|
|
),
|
|
|
|
|
td: ({ children }) => (
|
|
|
|
|
<td className="border border-gray-600 px-3 py-2 text-gray-300">
|
|
|
|
|
{children}
|
|
|
|
|
</td>
|
|
|
|
|
),
|
|
|
|
|
tr: ({ children }) => (
|
|
|
|
|
<tr className="hover:bg-gray-800/50">
|
|
|
|
|
{children}
|
|
|
|
|
</tr>
|
|
|
|
|
),
|
2026-03-18 14:09:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2026-03-18 18:50:26 +08:00
|
|
|
<div className="h-full overflow-auto p-6">
|
|
|
|
|
<div className="max-w-4xl mx-auto text-gray-200">
|
|
|
|
|
<ReactMarkdown
|
|
|
|
|
remarkPlugins={[remarkGfm]}
|
|
|
|
|
components={components}
|
|
|
|
|
>
|
|
|
|
|
{content}
|
|
|
|
|
</ReactMarkdown>
|
|
|
|
|
</div>
|
2026-03-18 14:09:06 +08:00
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|