-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmdx-components.tsx
122 lines (116 loc) · 3.11 KB
/
mdx-components.tsx
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import React, { ComponentPropsWithoutRef } from "react";
import Link from "@/components/link";
import { getHighlighter } from "shiki";
let highlighter: Awaited<ReturnType<typeof getHighlighter>> | null = null;
async function ensureHighlighter() {
if (!highlighter) {
highlighter = await getHighlighter({
themes: ["github-dark"],
langs: [
"typescript",
"javascript",
"jsx",
"tsx",
"css",
"json",
"markdown",
"bash",
"html",
],
});
}
return highlighter;
}
type HeadingProps = ComponentPropsWithoutRef<"h1">;
type ParagraphProps = ComponentPropsWithoutRef<"p">;
type ListProps = ComponentPropsWithoutRef<"ul">;
type ListItemProps = ComponentPropsWithoutRef<"li">;
type AnchorProps = ComponentPropsWithoutRef<"a">;
type BlockquoteProps = ComponentPropsWithoutRef<"blockquote">;
const components = {
h1: (props: HeadingProps) => (
<h1 className="font-bold text-2xl mb-3 fade-in" {...props} />
),
h2: (props: HeadingProps) => (
<h2 className="font-semibold text-xl mt-4 mb-3" {...props} />
),
h3: (props: HeadingProps) => (
<h3 className="font-medium mt-4 mb-3" {...props} />
),
h4: (props: HeadingProps) => <h4 className="font-medium" {...props} />,
p: (props: ParagraphProps) => (
<p className="text-justify leading-relaxed" {...props} />
),
ol: (props: ListProps) => (
<ol className="list-decimal pl-5 space-y-2" {...props} />
),
ul: (props: ListProps) => (
<ul className="list-disc pl-5 space-y-1" {...props} />
),
li: (props: ListItemProps) => <li className="pl-1" {...props} />,
em: (props: ComponentPropsWithoutRef<"em">) => (
<em className="font-medium" {...props} />
),
strong: (props: ComponentPropsWithoutRef<"strong">) => (
<strong className="font-medium" {...props} />
),
a: ({ href, children, ...props }: AnchorProps) => {
if (href?.startsWith("/") || href?.startsWith("#")) {
return (
<Link href={href} {...props}>
{children}
</Link>
);
}
return (
<Link href={href as string} external={true} {...props}>
{children}
</Link>
);
},
code: async ({
children,
className,
...props
}: ComponentPropsWithoutRef<"code">) => {
const highlighter = await ensureHighlighter();
const lang = className?.replace(/language-/, "") || "text";
const codeHTML = highlighter.codeToHtml(children as string, {
lang,
theme: "github-dark",
});
return <code dangerouslySetInnerHTML={{ __html: codeHTML }} {...props} />;
},
Table: ({ data }: { data: { headers: string[]; rows: string[][] } }) => (
<table>
<thead>
<tr>
{data.headers.map((header, index) => (
<th key={index}>{header}</th>
))}
</tr>
</thead>
<tbody>
{data.rows.map((row, index) => (
<tr key={index}>
{row.map((cell, cellIndex) => (
<td key={cellIndex}>{cell}</td>
))}
</tr>
))}
</tbody>
</table>
),
blockquote: (props: BlockquoteProps) => (
<blockquote
className="ml-[0.075em] border-l-3 border-gray-300 pl-4 text-gray-700"
{...props}
/>
),
};
declare global {
type MDXProvidedComponents = typeof components;
}
export function useMDXComponents(): MDXProvidedComponents {
return components;
}