自作ブログを作っています。
技術スタック
- TypeScript
- React
- Next.js
- Styled Components
- GitHub Pages
今回は、Markdownファイルにメタ情報を登録できるようにします。
メタ情報とは
メタ情報とは、Markdownファイルに下記のtitle
・date
のように登録できる情報です。
--- title: サンプル2 date: 2022-09-25 --- (本文) ~~~
本文と違い、これらは単体で抜き出せるため、汎用的に利用することができます。
例えば、一覧画面に表示するタイトルとしたり、記事ページにおいても自由に配置・装飾できます。
dayjsの導入
メタ情報として作成日時を利用したいため、dayjs
というライブラリを導入します。
dayjsは各ファイルから直接呼び出すのではなく、ラッパーを用意しておきます。
Pluginの導入などを一括で行うためなどです。
import dayjs from 'dayjs' // Pluginの導入など export default dayjs
gray-matter
メタ情報の活用には、gray-matter
というライブラリを利用します。
npm i gray-matter
既存のutilityを拡張します。
(markdown-utils.ts) export type FileContentBase = { content: string } export async function loadFile<MatterType>( rawContent: string ): Promise<FileContentBase & { matter: MatterType }> { const matterResult = matter(rawContent) const content = await convertToHtml(matterResult.content) return { content, matter: matterResult.data as MatterType, } }
これにより、ファイル読み込み時に本文(content)・メタ情報(matter)の2つに分けて返却するようにします。
メタ情報のデータ構造は、MatterType
として呼び出し元からデータ構造を指定できます。
ブログの拡張
作成中のブログにあった形式で、メタ情報を取り出せるようにします。
先ほど更新したmarkdown-utils.loadFile
を利用し、メタ情報としてタイトル(title
)・作成日時(date
)を取り出せるようにします。
(post-service.ts) export type PostMatter = { title: string date: string } export async function loadMarkdown(slug: string) { const fullPath = path.join(getPostDir(), `${slug}.md`) const rawContent = fs.readFileSync(fullPath, { encoding: 'utf8' }) const postData = await markdownUtils.loadFile<PostMatter>(rawContent) return { content: postData.content, matter: { title: postData.matter.title, date: dayjs(postData.matter.date).format('YYYY-MM-DD'), }, } }
最後に画面表示を更新します。
([slug].tsx) const Slug = ({ content, title, date }: Props) => { return ( <> <small>{dayjs(date).format('YYYY-MM-DD')}</small> <h1>{title}</h1> <div dangerouslySetInnerHTML={{ __html: content }} /> </> ) }
スクリーンショット
赤枠の箇所が画面表示できるようになりました。