116 lines
3.7 KiB
TypeScript
Raw Normal View History

2023-07-07 11:17:22 +08:00
import PageTitle from '@/components/PageTitle'
2023-07-16 18:52:51 +08:00
import { components } from '@/components/MDXComponents'
import { MDXLayoutRenderer } from 'pliny/mdx-components'
2023-07-07 11:17:22 +08:00
import { sortedBlogPost, coreContent } from 'pliny/utils/contentlayer'
import { allBlogs, allAuthors } from 'contentlayer/generated'
import type { Authors, Blog } from 'contentlayer/generated'
2023-07-08 15:23:25 +08:00
import PostLayout from '@/layouts/PostLayout'
2023-07-08 21:03:46 +08:00
import { Metadata } from 'next'
import siteMetadata from '@/data/siteMetadata'
export async function generateMetadata({
params,
}: {
params: { slug: string[] }
}): Promise<Metadata | undefined> {
const slug = params.slug.join('/')
const post = allBlogs.find((p) => encodeURIComponent(p.slug) === slug)
2023-07-08 21:03:46 +08:00
const authorList = post?.authors || ['default']
const authorDetails = authorList.map((author) => {
const authorResults = allAuthors.find((p) => p.slug === author)
return coreContent(authorResults as Authors)
})
if (!post) {
return
}
const publishedAt = new Date(post.date).toISOString()
const modifiedAt = new Date(post.lastmod || post.date).toISOString()
const authors = authorDetails.map((author) => author.name)
let imageList = [siteMetadata.socialBanner]
if (post.images) {
imageList = typeof post.images === 'string' ? [post.images] : post.images
}
const ogImages = imageList.map((img) => {
return {
url: img.includes('http') ? img : siteMetadata.siteUrl + img,
}
})
return {
title: post.title,
description: post.summary,
openGraph: {
title: post.title,
description: post.summary,
siteName: siteMetadata.title,
locale: 'en_US',
type: 'article',
publishedTime: publishedAt,
modifiedTime: modifiedAt,
url: './',
images: ogImages,
authors: authors.length > 0 ? authors : [siteMetadata.author],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.summary,
images: imageList,
},
}
}
2023-07-07 11:17:22 +08:00
export const generateStaticParams = async () => {
const paths = allBlogs.map((p) => ({ slug: p.slug.split('/') }))
return paths
}
2023-07-08 15:23:25 +08:00
export default async function Page({ params }: { params: { slug: string[] } }) {
2023-07-07 11:17:22 +08:00
const slug = params.slug.join('/')
console.log('begin generate for slug: %o', slug)
2023-07-07 11:17:22 +08:00
const sortedPosts = sortedBlogPost(allBlogs) as Blog[]
const postIndex = sortedPosts.findIndex((p) => encodeURIComponent(p.slug) === slug)
2023-07-08 15:23:25 +08:00
const prev = coreContent(sortedPosts[postIndex + 1])
const next = coreContent(sortedPosts[postIndex - 1])
const post = sortedPosts.find((p) => encodeURIComponent(p.slug) === slug) as Blog
2023-07-07 11:17:22 +08:00
const authorList = post?.authors || ['default']
const authorDetails = authorList.map((author) => {
const authorResults = allAuthors.find((p) => p.slug === author)
return coreContent(authorResults as Authors)
})
2023-07-08 15:23:25 +08:00
const mainContent = coreContent(post)
2023-07-09 23:09:07 +08:00
const jsonLd = post.structuredData
jsonLd['author'] = authorDetails.map((author) => {
return {
'@type': 'Person',
name: author.name,
}
})
2023-07-07 11:17:22 +08:00
return (
<>
{post && 'draft' in post && post.draft === true ? (
<div className="mt-24 text-center">
<PageTitle>
Under Construction{' '}
<span role="img" aria-label="roadwork sign">
🚧
</span>
</PageTitle>
</div>
) : (
2023-07-09 23:09:07 +08:00
<>
<script type="application/ld+json" suppressHydrationWarning>
{JSON.stringify(jsonLd)}
</script>
<PostLayout content={mainContent} authorDetails={authorDetails} next={next} prev={prev}>
2023-07-16 18:52:51 +08:00
<MDXLayoutRenderer code={post.body.code} components={components} toc={post.toc} />
2023-07-09 23:09:07 +08:00
</PostLayout>
</>
2023-07-07 11:17:22 +08:00
)}
</>
)
}