Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ✨ 兼容mdx文件直接渲染 & font #8

Merged
merged 2 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"framer-motion": "^11.3.29",
"lodash-es": "^4.17.21",
"lucide-react": "^0.429.0",
"lxgw-wenkai-lite-webfont": "^1.7.0",
"next": "^14.2.6",
"next-mdx-remote": "^5.0.0",
"next-themes": "^0.3.0",
Expand All @@ -34,11 +35,11 @@
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
"@next/bundle-analyzer": "^14.2.6",
"@mdx-js/loader": "^3.0.1",
"@next/bundle-analyzer": "^14.2.6",
"@next/mdx": "^14.2.6",
"@types/mdx": "^2.0.13",
"@types/lodash-es": "^4.17.12",
"@types/mdx": "^2.0.13",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
Expand Down
6 changes: 5 additions & 1 deletion src/app/blog/[id]/AnimatedBlogPost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ export default function AnimatedBlogPost({
transition={{ duration: 0.5, delay: 0.3 }}
>
<BlogHeader post={post} readingTime={readingTime} />
<BlogContent content={post.content} components={mdxComponents} />
<BlogContent
content={post.content}
contentFile={post?.contentFile}
components={mdxComponents}
/>
<BlogFooter post={post} />
<RelatedPosts posts={relatedPosts} />
<ShareButtons
Expand Down
44 changes: 28 additions & 16 deletions src/app/blog/[id]/BlogContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,40 @@ import remarkGfm from "remark-gfm";
import rehypeInlineCode from "@/lib/rehypeInlineCode";
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
import BlogPostMDXContent from "@/data/BlogPostMDXContent";

interface BlogContentProps {
content: string;
components: MDXComponents;
contentFile?: string;
}

export default function BlogContent({ content, components }: BlogContentProps) {
export default function BlogContent({
content,
components,
contentFile,
}: BlogContentProps) {
return (
<MDXRemote
source={content}
components={components}
options={{
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
[rehypeAutolinkHeadings, { behavior: "wrap" }],
rehypeInlineCode,
],
},
parseFrontmatter: true,
}}
/>
<>
{contentFile ? (
<BlogPostMDXContent contentFile={contentFile} components={components} />
) : (
<MDXRemote
source={content}
components={components}
options={{
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
[rehypeAutolinkHeadings, { behavior: "wrap" }],
rehypeInlineCode,
],
},
parseFrontmatter: true,
}}
/>
)}
</>
);
}
32 changes: 31 additions & 1 deletion src/app/blog/[id]/MdxComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ const CopyButton = dynamic(() => import("@/components/blog/id/CopyButton"), {
ssr: false,
});

const Table: React.FC<React.TableHTMLAttributes<HTMLTableElement>> = (
props
) => <table className="min-w-full divide-y divide-gray-200" {...props} />;

const Th: React.FC<React.ThHTMLAttributes<HTMLTableHeaderCellElement>> = (
props
) => (
<th
className="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
{...props}
/>
);

const Td: React.FC<React.TdHTMLAttributes<HTMLTableDataCellElement>> = (
props
) => (
<td
className="px-6 py-4 whitespace-nowrap text-sm text-gray-500"
{...props}
/>
);

const Tr: React.FC<React.HTMLAttributes<HTMLTableRowElement>> = (props) => (
<tr className="bg-white" {...props} />
);

export const mdxComponents: MDXComponents = {
h1: (props: any) => (
<h1
Expand Down Expand Up @@ -45,7 +71,7 @@ export const mdxComponents: MDXComponents = {
const match = /language-(\w+)/.exec(className || "");
const language = match ? match[1] : "text";
const isInline = className === "inline-code";
if (isInline) {
if (isInline || !className) {
return (
<code
className="bg-gray-100 dark:bg-gray-800 rounded px-1 py-0.5 font-mono text-sm"
Expand Down Expand Up @@ -74,4 +100,8 @@ export const mdxComponents: MDXComponents = {
);
},
pre: (props: any) => <div {...props} />,
table: Table,
th: Th,
td: Td,
tr: Tr,
};
11 changes: 1 addition & 10 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "@/style/globals.css";
import Header from "@/components/app/Header";
import Footer from "@/components/app/Footer";
Expand All @@ -11,8 +10,6 @@ import { ViewTransitions } from "next-view-transitions";
import { ThemeProvider } from "next-themes";
import AnimatedLayout from "@/components/app/AnimatedLayout";

const inter = Inter({ subsets: ["latin"], variable: "--font-sans" });

export const metadata: Metadata = {
title: "我的博客",
description: "欢迎来到我的博客",
Expand All @@ -29,13 +26,7 @@ export default function RootLayout({
<head>
<link rel="icon" href="/next.svg" type="image/svg+xml" />
</head>
<body
className={cn(
`${inter.className} flex flex-col bg-background font-sans antialiased h-full`,
inter.variable,
"font-['LXGW_WenKai',sans-serif]"
)}
>
<body className={cn(`flex flex-col bg-background antialiased h-full`)}>
<ThemeProvider attribute="class">
<Header />
<AnimatedLayout>{children}</AnimatedLayout>
Expand Down
25 changes: 25 additions & 0 deletions src/data/BlogPostMDXContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";
import { MDXProvider } from "@mdx-js/react";
import dynamic from "next/dynamic";
import { MDXComponents } from "@/app/blog/[id]/types";

interface BlogPostMDXContent {
contentFile: string;
components: MDXComponents;
}

const BlogPostMDXContent = ({
contentFile,
components,
}: BlogPostMDXContent) => {
const MDXContent = dynamic(() => import(`./content/${contentFile}`));

return (
<MDXProvider components={components}>
{/* @ts-ignore */}
<MDXContent components={components} />
</MDXProvider>
);
};

export default BlogPostMDXContent;
2 changes: 2 additions & 0 deletions src/data/blogPosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ export interface BlogPost {
tags: string[];
category?: string;
coverImage?: string;
contentFile?: string; // 新增字段,指向mdx文件
}

export const blogPosts: BlogPost[] = [
{
id: 1,
title: "深入理解React Hooks",
excerpt: "探索React Hooks的工作原理和最佳实践...",
contentFile: "1.mdx",
content: `
# 深入理解React Hooks

Expand Down
Loading