-
Notifications
You must be signed in to change notification settings - Fork 0
/
mdx-components.tsx
113 lines (100 loc) · 2.86 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
import type { MDXComponents } from "mdx/types";
import { Url } from "next/dist/shared/lib/router/router";
import Image, { ImageProps } from "next/image";
import Link, { LinkProps } from "next/link";
import { createElement, HTMLAttributes, Key, ReactNode } from "react";
import { highlight } from "sugar-high";
import { slugify } from "./app/(utils)/utils";
export function Table({ data }: any) {
let headers = data.headers.map((header: string, index: Key) => (
<th key={index}>{header}</th>
));
let rows = data.rows.map((row: string[], index: Key) => (
<tr key={index}>
{row.map((cell: string, cellIndex: Key) => (
<td key={cellIndex}>{cell}</td>
))}
</tr>
));
return (
<table>
<thead>
<tr>{headers}</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}
export function CustomLink({
href,
children,
...props
}: React.AnchorHTMLAttributes<HTMLAnchorElement> & LinkProps) {
const hrefString = typeof href === "string" ? href : (href as Url).toString(); // Convert Url to string
if (hrefString.startsWith("/")) {
// Internal link
return (
<Link {...props} href={href as Url}>
{children}
</Link>
);
}
if (hrefString.startsWith("#")) {
// Anchor link
return (
<a {...props} href={hrefString}>
{children}
</a>
);
}
// External link
return (
<a target="_blank" rel="noopener noreferrer" href={hrefString} {...props}>
{children}
</a>
);
}
export function RoundedImage(props: ImageProps) {
return <Image {...props} alt={props.alt} className="rounded-lg" />;
}
export function Code({ children, ...props }: any) {
let codeHTML = highlight(children);
return <code dangerouslySetInnerHTML={{ __html: codeHTML }} {...props} />;
}
export function createHeading(level: number) {
const Heading = ({
children,
...props
}: { children?: ReactNode } & HTMLAttributes<HTMLHeadingElement>) => {
const childText = typeof children === "string" ? children : ""; // Extract text for slug if children is a string
const slug = slugify(childText);
return createElement(
`h${level}`,
{ id: slug, ...props }, // Pass props to ensure compatibility
[
createElement("a", {
href: `#${slug}`,
key: `link-${slug}`,
className: "anchor",
}),
children, // Render children, even if it's undefined it will be safely handled
]
);
};
Heading.displayName = `Heading${level}`;
return Heading;
}
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
h1: createHeading(1),
h2: createHeading(2),
h3: createHeading(3),
h4: createHeading(4),
h5: createHeading(5),
Image: RoundedImage,
a: CustomLink as any, // Explicitly cast to any to bypass type mismatch
code: Code,
Table,
...components,
};
}