スマレジエンジニアyushiのブログ

スマレジエンジニアのブログ

【自作ブログ #4】メタ情報を表示する

自作ブログを作っています。

yushi-dev.hatenablog.com

技術スタック

  • TypeScript
  • React
  • Next.js
  • Styled Components
  • GitHub Pages

今回は、Markdownファイルにメタ情報を登録できるようにします。

メタ情報とは

メタ情報とは、Markdownファイルに下記のtitledateのように登録できる情報です。

---
title: サンプル2
date: 2022-09-25
---

(本文)
~~~

本文と違い、これらは単体で抜き出せるため、汎用的に利用することができます。

例えば、一覧画面に表示するタイトルとしたり、記事ページにおいても自由に配置・装飾できます。

dayjsの導入

メタ情報として作成日時を利用したいため、dayjsというライブラリを導入します。

day.js.org

dayjsは各ファイルから直接呼び出すのではなく、ラッパーを用意しておきます。

Pluginの導入などを一括で行うためなどです。

import dayjs from 'dayjs'

// Pluginの導入など

export default dayjs

gray-matter

メタ情報の活用には、gray-matterというライブラリを利用します。

github.com

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 }} />
    </>
  )
}

スクリーンショット

赤枠の箇所が画面表示できるようになりました。

Pull Request

https://github.com/nek0meshi/blog/pull/6