-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMarkdownContent.jsx
More file actions
77 lines (69 loc) · 2.41 KB
/
MarkdownContent.jsx
File metadata and controls
77 lines (69 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import React, { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import rehypeRaw from 'rehype-raw';
import rehypeKatex from 'rehype-katex';
import { ImagesIcon } from '@phosphor-icons/react';
import ImageModal from './ImageModal';
import MermaidDiagram from './MermaidDiagram';
const MarkdownContent = ({ content, components = {}, className = '' }) => {
const [modalData, setModalData] = useState(null);
const CustomImage = ({ src, alt, ...props }) => {
return (
<figure className="my-8 group relative overflow-hidden rounded-lg">
<img
src={src}
alt={alt}
className="w-full h-auto transition-transform duration-500 group-hover:scale-105 cursor-pointer"
onClick={() => setModalData({ src, alt })}
{...props}
/>
{alt && (
<figcaption className="absolute bottom-0 left-0 w-full bg-black/60 backdrop-blur-md px-4 py-2 text-xs font-mono text-gray-300 border-t border-white/10 translate-y-full transition-transform duration-300 group-hover:translate-y-0">
{alt}
</figcaption>
)}
<div className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity bg-black/50 p-1.5 rounded-full backdrop-blur-sm border border-white/10 pointer-events-none">
<ImagesIcon size={16} className="text-white" />
</div>
</figure>
);
};
const CodeBlock = ({ node, inline, className, children, ...props }) => {
const match = /language-(\w+)/.exec(className || '');
const isMermaid = match && match[1] === 'mermaid';
if (!inline && isMermaid) {
return <MermaidDiagram chart={String(children).replace(/\n$/, '')} />;
}
return (
<code className={className} {...props}>
{children}
</code>
);
};
const defaultComponents = {
img: CustomImage,
code: CodeBlock,
...components,
};
return (
<>
<div className={className}>
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeRaw, rehypeKatex]}
components={defaultComponents}
>
{content}
</ReactMarkdown>
</div>
<ImageModal
src={modalData?.src}
alt={modalData?.alt}
onClose={() => setModalData(null)}
/>
</>
);
};
export default MarkdownContent;