From 885de38cdd4fd2f2dcb33723913e187548783449 Mon Sep 17 00:00:00 2001 From: Johnson Mao Date: Wed, 27 Sep 2023 13:29:49 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20add=20try-catch=20statement=20to=20?= =?UTF-8?q?handle=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/[lang]/posts/[postId]/page.tsx | 16 ++----- src/utils/__tests__/mdx.test.ts | 11 +++++ src/utils/mdx.ts | 66 ++++++++++++++------------ 3 files changed, 50 insertions(+), 43 deletions(-) diff --git a/src/app/[lang]/posts/[postId]/page.tsx b/src/app/[lang]/posts/[postId]/page.tsx index 54a027fb..e639ac83 100644 --- a/src/app/[lang]/posts/[postId]/page.tsx +++ b/src/app/[lang]/posts/[postId]/page.tsx @@ -21,27 +21,19 @@ export async function generateStaticParams() { export async function generateMetadata({ params: { postId }, }: PostParams): Promise { - const posts = await getAllDataFrontmatter('posts'); - const post = posts.find((post) => post.id === postId); + const post = await getDataById('posts', postId); if (!post) return notFound(); - return { - title: post.title, - description: post.excerpt, - }; + return post.frontmatter; } async function PostPage({ params: { postId } }: PostParams) { - const posts = await getAllDataFrontmatter('posts'); - const post = posts.find((post) => post.id === postId); + const post = await getDataById('posts', postId); if (!post) return notFound(); - const { content, frontmatter, source } = await getDataById( - 'posts', - postId - ); + const { content, frontmatter, source } = post; const formattedDate = formatDate(frontmatter.date); return ( diff --git a/src/utils/__tests__/mdx.test.ts b/src/utils/__tests__/mdx.test.ts index ef961df2..1602f0c8 100644 --- a/src/utils/__tests__/mdx.test.ts +++ b/src/utils/__tests__/mdx.test.ts @@ -91,6 +91,17 @@ describe('Get post data function', () => { source: '---\ndate: 2023/07/09\n---\n\n測試文章C', }); }); + + it('should return null when trying to get post data for a non-existing file', async () => { + mockExists.mockReturnValueOnce(false); + mockReadFile.mockImplementation(() => { + throw new Error('File not found'); + }); + + const postData = await getDataById('posts', 'not_found'); + + expect(postData).toBe(null); + }); }); const mockFileA = `--- diff --git a/src/utils/mdx.ts b/src/utils/mdx.ts index 18c51ffe..0da935e0 100644 --- a/src/utils/mdx.ts +++ b/src/utils/mdx.ts @@ -45,37 +45,41 @@ export async function getAllDataFrontmatter(dirType: DataDirType) { /** Retrieve data content and front matter for a specific data file by its id. */ export async function getDataById(dirType: DataDirType, id: string) { - const dirPath = path.join(ROOT_PATH, 'data', dirType); - const mdxPath = path.join(dirPath, `${id}.mdx`); - const mdPath = path.join(dirPath, `${id}.md`); - const fullPath = fs.existsSync(mdxPath) ? mdxPath : mdPath; - const source = fs.readFileSync(fullPath, 'utf8'); - const { content, frontmatter } = await compileMDX({ - source, - components: { - h1: H1, - h2: H2, - h3: H3, - h4: H4, - h5: H5, - h6: H6, - pre: CodeBox, - img: Image as () => JSX.Element, - a: Link as () => JSX.Element, - }, - options: { - parseFrontmatter: true, - mdxOptions: { - remarkPlugins: [remarkGfm], - rehypePlugins: [ - rehypeSlug, - rehypeCodeTitles, - rehypePrismPlus, - rehypeImageMetadata, - ], + try { + const dirPath = path.join(ROOT_PATH, 'data', dirType); + const mdxPath = path.join(dirPath, `${id}.mdx`); + const mdPath = path.join(dirPath, `${id}.md`); + const fullPath = fs.existsSync(mdxPath) ? mdxPath : mdPath; + const source = fs.readFileSync(fullPath, 'utf8'); + const { content, frontmatter } = await compileMDX({ + source, + components: { + h1: H1, + h2: H2, + h3: H3, + h4: H4, + h5: H5, + h6: H6, + pre: CodeBox, + img: Image as () => JSX.Element, + a: Link as () => JSX.Element, + }, + options: { + parseFrontmatter: true, + mdxOptions: { + remarkPlugins: [remarkGfm], + rehypePlugins: [ + rehypeSlug, + rehypeCodeTitles, + rehypePrismPlus, + rehypeImageMetadata, + ], + }, }, - }, - }); + }); - return { id, content, frontmatter, source }; + return { id, content, frontmatter, source }; + } catch { + return null; + } }