next.jsを使用して会社のHPを作成しています。
前回、remarkではなくzennのマークダウンファイルのパーサーを使用するように変更しました。
今回は、postに付随するyaml情報をいじってtagや関連記事を表示させるようにしていきます。
前回までの記事はこちら。
既存のyamlについて
既存のyamlには、title
やexcerpt
、coverImage
、date
、author
、ogImage
があります。
postのサンプルの先頭を見るとこのようになっているはずです。
---
title: 'Dynamic Routing and Static Generation'
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus.'
coverImage: '/assets/blog/dynamic-routing/cover.jpg'
date: '2020-03-16T05:35:07.322Z'
author:
name: JJ Kasper
picture: '/assets/blog/authors/jj.jpeg'
ogImage:
url: '/assets/blog/dynamic-routing/cover.jpg'
---
今回修正したいのは以下の項目です。
- coverImageやogImageに画像を指定していますが、今回は画像を使用しないので削除します。
- tagというキーを追加して、その中にタグを配列で指定します。
- relatedPostSlugsというキーを追加して、その中に関連記事のslugを配列で指定します。
- releasedというキーを追加して、その中に記事を公開するかどうかをbooleanで指定します。
---
title: '[React] Next.jsでブログ(会社HP)をつくるぞ!その4'
excerpt: 'next.jsを使用して会社のHPを作成しています。今回は、postに付随するyaml情報をいじってtagや関連記事を表示させるようにしていきます。'
date: '2022/12/03'
author:
name: Kenji
tags:
- 'Docker'
- 'React'
- 'Next.js'
relatedPostSlugs:
- 'next-create-blog-1'
- 'next-create-blog-2'
- 'next-create-blog-3'
released: true
---
それでは、これで対応できるようにlib/api.ts
を修正していきます。
lib/api.tsの修正
今回修正する関数は、getPostBySlug
です。
getAllPosts
は、getPostBySlug
を使用しているので、getPostBySlug
を修正するとgetAllPosts
も修正されます。
下記は、getPostBySlug
の修正後のコードです。
const relatedPosts = (relatedPostNeeded) ? data['relatedPostSlugs']?.map((slug: string) => getPostBySlug(slug, ['title', 'slug', 'image', 'date', 'tags'], false)) : []
export function getPostBySlug(slug: string, fields: string[] = [], relatedPostNeeded: boolean = false) {
const realSlug = slug.replace(/\.md$/, '')
const fullPath = join(postsDirectory, `${realSlug}.md`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
const image = `/assets/ogp/${realSlug}.webp`
const { data, content } = matter(fileContents)
const relatedPosts = (relatedPostNeeded) ? data['relatedPostSlugs']?.map((slug: string) => getPostBySlug(slug, ['title', 'slug', 'image', 'date', 'tags'], false)) : []
type Items = {
[key: string]: string
}
const items: Items = {}
// Ensure only the minimal needed data is exposed
fields.forEach((field) => {
if (field === 'slug') {
items[field] = realSlug
}
if (field === 'content') {
items[field] = content
}
if (field === 'image') {
items[field] = image
}
if (field === 'relatedPosts') {
items[field] = relatedPosts
}
if (typeof data[field] !== 'undefined') {
items[field] = data[field]
}
})
return items
}
新たな引数として、relatedPostNeeded
を追加しています。
これは、関連記事を取得するかどうかを指定するためのものですが、これを追加しておかないと、関連記事の取得が無限ループになってしまいます。
また、relatedPosts
の取得に関しては、relatedPostSlugs
のslugを元に、getPostBySlug
を再帰的に呼び出しています。
pages/posts/[slug].tsx
の修正
今回上記のように画像をimageに統合したので、pages/posts/[slug].tsx
を修正していきます。
<Head>
<title>
{post.title} | 合同会社irori
</title>
<meta property="og:image" content={post.image} />
</Head>
これで、OGP画像が表示されるようになりました。
タグの表示
次に、タグの表示を実装していきます。
タグの表示は以下のようにすれば大丈夫です。
{post.tags.map((tag) => (
<div className="pr-2 pb-2" key={tag}>
<Tag text={tag} />
</div>
))}
これで、タグが表示されるようになりました。
関連記事についても同様のやり方で実装できます。
今日はこのあたりで。