import { Callout } from "@/components/mdx/Callout"; import MDXComponents from "@/components/mdx/MDXComponents"; import { Locale, LOCALES } from "@/i18n/routing"; import { getPosts } from "@/lib/getBlogs"; import { constructMetadata } from "@/lib/metadata"; import { BlogPost } from "@/types/blog"; import fs from "fs/promises"; import matter from 'gray-matter'; import { Metadata } from "next"; import { MDXRemote } from "next-mdx-remote-client/rsc"; import { notFound } from "next/navigation"; import path from "path"; type Params = Promise<{ locale: string; slug: string; }>; type MetadataProps = { params: Params; }; async function getMDXContent(locale: string, section: string): Promise { const filePath = path.join( process.cwd(), "blogs", locale, `${section}.mdx` ); try { const content = await fs.readFile(filePath, "utf-8"); // 解析MDX文件的frontmatter和内容 const { data: frontmatter, content: postContent } = matter(content); // 构建BlogPost对象 const blogPost: BlogPost = { locale, title: frontmatter.title || '', description: frontmatter.description, image: frontmatter.image, slug: frontmatter.slug || '', tags: frontmatter.tags, // 解析日期 date: frontmatter.date ? new Date(frontmatter.date) : new Date(), // 设置visible默认值为published visible: frontmatter.visible || 'published', // 处理pin字段 - 如果有pin标记则为true,否则为false pin: frontmatter.pin === 'pin', // 去除frontmatter后的内容 content: postContent.trim(), // 所有frontmatter作为metadata metadata: { ...frontmatter } }; return blogPost; } catch (error) { console.error(`Error reading MDX file: ${error}`); // 返回默认的BlogPost对象(符合类型要求) return { title: '', slug: '', date: new Date(), content: '', visible: 'published', pin: false, metadata: {}, locale }; } } export async function generateMetadata({ params, }: MetadataProps): Promise { const { locale, slug } = await params; let post = await getMDXContent(locale, slug); if (!post) { return constructMetadata({ title: "404", description: "Page not found", noIndex: true, locale: locale as Locale, path: `/blog/${slug}`, canonicalUrl: `/blog/${slug}`, }); } return constructMetadata({ page: "blog", title: post.title || '', description: post.description || '', images: [], locale: locale as Locale, path: `/blog/${slug}`, canonicalUrl: `/blog/${slug}`, }); } export default async function BlogPage({ params }: { params: Params }) { const { locale, slug } = await params; let post = await getMDXContent(locale, slug); if (!post) { return notFound(); } return (

{post.title}

{post.image && ( {post.title} )} {post.tags && post.tags.split(",").length ? (
{post.tags.split(",").map((tag) => { return (
{tag.trim()}
); })}
) : ( <> )} {post.description && {post.description}}
); } export async function generateStaticParams() { let posts = (await getPosts()).posts; // Filter out posts without a slug posts = posts.filter((post) => post.slug); return LOCALES.flatMap((locale) => posts.map((post) => { const slugPart = post.slug.replace(/^\//, "").replace(/^blog\//, ""); return { locale, slug: slugPart, }; }) ); }