1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2024-11-05 04:51:30 +01:00
.profile/blog/BlogPostContent.tsx

122 lines
3.4 KiB
TypeScript

import Image from "next/image"
import Link from "next/link"
import { cookies } from "next/headers"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { faLink } from "@fortawesome/free-solid-svg-icons"
import { MDXRemote } from "next-mdx-remote/rsc"
import { nodeTypes } from "@mdx-js/mdx"
import rehypeRaw from "rehype-raw"
import remarkGfm from "remark-gfm"
import rehypeSlug from "rehype-slug"
import remarkMath from "remark-math"
import rehypeKatex from "rehype-katex"
import { getHighlighter } from "shiki"
import "katex/dist/katex.min.css"
import { getTheme } from "@/theme/theme.server"
import { remarkSyntaxHighlightingPlugin } from "@/blog/remarkSyntaxHighlightingPlugin"
import { BlogPostComments } from "@/blog/BlogPostComments"
const Heading = (
props: React.DetailedHTMLProps<
React.HTMLAttributes<HTMLHeadingElement>,
HTMLHeadingElement
>,
): JSX.Element => {
const { children, id = "" } = props
return (
<h2 {...props} className="group">
<Link
href={`#${id}`}
className="invisible !text-black group-hover:visible dark:!text-white"
>
<FontAwesomeIcon className="mr-2 inline h-4 w-4" icon={faLink} />
</Link>
{children}
</h2>
)
}
export interface BlogPostContentProps {
content: string
}
export const BlogPostContent = async (
props: BlogPostContentProps,
): Promise<JSX.Element> => {
const { content } = props
const cookiesStore = cookies()
const theme = getTheme()
const highlighter = await getHighlighter({
theme: `${theme}-plus`,
})
return (
<div className="prose mb-10">
<div className="px-8">
<MDXRemote
source={content}
options={{
mdxOptions: {
remarkPlugins: [
remarkGfm,
[remarkSyntaxHighlightingPlugin, { highlighter }],
remarkMath,
],
rehypePlugins: [
rehypeSlug,
[rehypeRaw, { passThrough: nodeTypes }],
rehypeKatex,
],
},
}}
components={{
h1: Heading,
h2: Heading,
h3: Heading,
h4: Heading,
h5: Heading,
h6: Heading,
img: (properties) => {
const { src = "", alt = "Blog Image" } = properties
const source = src.replace("../../public/", "/")
return (
<span className="flex flex-col items-center justify-center">
<Image
src={source}
alt={alt}
width={1000}
height={1000}
className="h-auto w-auto"
/>
</span>
)
},
a: (props) => {
const { href = "", ...rest } = props
if (href.startsWith("#")) {
return <a {...props} />
}
if (href.startsWith("../posts/")) {
return (
<a
href={href
.replace("../posts/", "/blog/")
.replace(".md", "")}
{...rest}
/>
)
}
return <a target="_blank" rel="noopener noreferrer" {...props} />
},
}}
/>
<BlogPostComments cookiesStore={cookiesStore.toString()} />
</div>
</div>
)
}