-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmarkdown-renderer.tsx
More file actions
73 lines (63 loc) · 1.93 KB
/
markdown-renderer.tsx
File metadata and controls
73 lines (63 loc) · 1.93 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
"use client";
import { useTheme } from "next-themes";
interface MarkdownRendererProps {
content: string;
}
export function MarkdownRenderer({ content }: MarkdownRendererProps) {
// Theme is used for styling in CSS variables, not directly in code
useTheme();
const formatMarkdown = (text: string) => {
// Replace headings
text = text.replace(
/^#\s+(.*$)/gm,
'<h1 class="text-2xl font-bold text-primary mb-4">$1</h1>'
);
text = text.replace(
/^##\s+(.*$)/gm,
'<h2 class="text-xl font-bold text-primary mb-3">$1</h2>'
);
text = text.replace(
/^###\s+(.*$)/gm,
'<h3 class="text-lg font-bold text-primary mb-2">$1</h3>'
);
text = text.replace(
/^####\s+(.*$)/gm,
'<h4 class="text-base font-bold text-primary mb-2">$1</h4>'
);
// Replace code blocks
text = text.replace(
/```(\w+)?\n([\s\S]*?)```/g,
(match, language, code) => {
return `<div class="my-4"><pre class="bg-muted p-4 rounded-md overflow-x-auto"><code class="text-foreground">${code.trim()}</code></pre></div>`;
}
);
// Replace inline code
text = text.replace(
/`([^`]+)`/g,
'<code class="bg-muted px-1 rounded">$1</code>'
);
// Replace lists
text = text.replace(/^\s*-\s+(.*$)/gm, '<li class="mb-1">$1</li>');
text = text.replace(
/<li/g,
'<ul class="list-disc pl-6 text-muted-foreground mb-2"><li'
);
text = text.replace(/<\/li>/g, "</li></ul>");
// Replace bold
text = text.replace(
/\*\*([^*]+)\*\*/g,
'<strong class="text-primary">$1</strong>'
);
// Replace paragraphs
text = text.replace(
/^(?!<[a-z])(.*$)/gm,
'<p class="text-muted-foreground mb-2">$1</p>'
);
return text;
};
return (
<div className="prose prose-sm dark:prose-invert max-w-none transition-colors">
<div dangerouslySetInnerHTML={{ __html: formatMarkdown(content) }} />
</div>
);
}