自作ブログを作っています。
技術スタック
- TypeScript
- React
- Next.js
- Styled Components
- GitHub Pages
remarkの導入
Next.jsの公式ドキュメントでは、Markdownをrenderする仕組みとしてremark
を紹介しています。
今回はこちらを利用します。
npm i remark remark-html remark-gfm
remark-gfmは、テーブルなどいくつかの拡張的な記述方法のためのプラグインです。
Markdownファイルのparser
ファイルの読み込みと、markdownをhtmlにparseする仕組みを合わせたutilityを用意します。
(markdown-utils.ts) import fs from 'fs' import { remark } from 'remark' import remarkGfm from 'remark-gfm' import html from 'remark-html' export async function convertToHtml(md: string) { const result = await remark().use(html).use(remarkGfm).process(md) return result.toString() } export async function loadFile(filePath: string) { const contents = await convertToHtml( fs.readFileSync(filePath, { encoding: 'utf8' }) ) return { contents } }
Markdownの色々な記述方法を含むサンプルファイルを用意します。
(sample.md) # Sample ## サブタイトル ### 文字装飾 サンプルです。 _イタリック_ **太文字** ### リスト - データ 1 - データ 2 1. 手順 1 2. 手順 2 ### テーブル | a | b | | --- | --- | | c | d | | e | f |
これを、/postsに配置します。
上記の/posts以下のファイルを読み込むためのメソッドを用意します。
先ほど作ったmarkdown-utils.ts
を利用しています。
(post-service.ts) import path from 'path' import * as markdownUtils from '@/utils/markdown-utils' export async function loadMarkdown(slug: string) { const postDir = path.join(process.cwd(), 'posts') const fullPath = path.join(postDir, `${slug}.md`) return markdownUtils.loadFile(fullPath) }
最後に、pages以下に先程用意したsample.mdに対応するページを表示するためのファイルを用意します。
(sample.tsx) import * as postService from '@/services/post-service' export async function getStaticProps() { const postData = await postService.loadMarkdown('sample') return { props: { contents: postData.contents, }, } } const Slug = ({ contents }) => { return ( <> <div dangerouslySetInnerHTML={{ __html: contents }} /> </> ) } export default Slug
スクリーンショット
画面が表示できるようになりました。
Markdownの各記述がうまくparseされています。
Pull Request
https://github.com/nek0meshi/blog/pull/3
あとがき
最近はハリポタを読んでいます。学生時代ぶりです。とても面白いです。