Ivan Li
3932a2b612
Some checks failed
🚀 Build and deploy by ftp / 🎉 Deploy (push) Failing after 8m21s
139 lines
4.1 KiB
TypeScript
139 lines
4.1 KiB
TypeScript
import 'css/prism.css';
|
|
import 'katex/dist/katex.css';
|
|
|
|
import PageTitle from '@/components/PageTitle';
|
|
import { components } from '@/components/MDXComponents';
|
|
import { MDXLayoutRenderer } from 'pliny/mdx-components';
|
|
import { sortPosts, coreContent } from 'pliny/utils/contentlayer';
|
|
import { allBlogs, allAuthors } from 'contentlayer/generated';
|
|
import type { Authors, Blog } from 'contentlayer/generated';
|
|
import PostSimple from '@/layouts/PostSimple';
|
|
import PostLayout from '@/layouts/PostLayout';
|
|
import PostBanner from '@/layouts/PostBanner';
|
|
import { Metadata } from 'next';
|
|
import siteMetadata from '@/data/siteMetadata';
|
|
|
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
const defaultLayout = 'PostLayout';
|
|
const layouts = {
|
|
PostSimple,
|
|
PostLayout,
|
|
PostBanner,
|
|
};
|
|
|
|
export async function generateMetadata({
|
|
params,
|
|
}: {
|
|
params: { slug: string[] };
|
|
}): Promise<Metadata | undefined> {
|
|
const slug = decodeURI(params.slug.join('/'));
|
|
const post = allBlogs.find((p) => p.slug === slug);
|
|
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,
|
|
},
|
|
};
|
|
}
|
|
|
|
export const generateStaticParams = async () => {
|
|
const paths = allBlogs.map((p) => ({ slug: p.slug.split('/') }));
|
|
|
|
return paths;
|
|
};
|
|
|
|
export default async function Page({ params }: { params: { slug: string[] } }) {
|
|
const slug = decodeURI(params.slug.join('/'));
|
|
const sortedPosts = sortPosts(allBlogs) as Blog[];
|
|
const postIndex = sortedPosts.findIndex((p) => p.slug === slug);
|
|
const prev = coreContent(sortedPosts[postIndex + 1]);
|
|
const next = coreContent(sortedPosts[postIndex - 1]);
|
|
const post = sortedPosts.find((p) => p.slug === slug) as Blog;
|
|
const authorList = post?.authors || ['default'];
|
|
const authorDetails = authorList.map((author) => {
|
|
const authorResults = allAuthors.find((p) => p.slug === author);
|
|
return coreContent(authorResults as Authors);
|
|
});
|
|
const mainContent = coreContent(post);
|
|
const jsonLd = post.structuredData;
|
|
jsonLd['author'] = authorDetails.map((author) => {
|
|
return {
|
|
'@type': 'Person',
|
|
name: author.name,
|
|
};
|
|
});
|
|
|
|
const Layout = layouts[post.layout || defaultLayout];
|
|
|
|
return (
|
|
<>
|
|
{isProduction && 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>
|
|
) : (
|
|
<>
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
|
/>
|
|
<Layout
|
|
content={mainContent}
|
|
authorDetails={authorDetails}
|
|
next={next}
|
|
prev={prev}>
|
|
<MDXLayoutRenderer
|
|
code={post.body.code}
|
|
components={components}
|
|
toc={post.toc}
|
|
/>
|
|
</Layout>
|
|
</>
|
|
)}
|
|
</>
|
|
);
|
|
}
|