GatsbyJSでMarkdownを書くと,ファイル名がslug (URLの一部)になってしまいます.ファイル名は日本語にしたいが,slugは英語にしたい.また,slugを指定しない場合は通常通りファイル名から自動生成したい.これを実現する設定について説明します.
TL;DR
以下のように node.frontmatter.slug ||
を gatsby-node.js
の exports.onCreateNode
内で対応する箇所に追加する.
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
// If specified, `slug` field of frontmatter is prioritized
const value = node.frontmatter.slug || createFilePath({ node, getNode }) // highlight-line
createNodeField({
name: `slug`,
node,
value,
})
}
}
その上で, slug を指定したいポストには,frontmatter (---
で囲まれた部分) に slug: /SOME_SLUG
の形で slug を指定する.
ここで, slug として/
で始まらない文字列を指定すると,リンクが正しく表示されない場合が発生することがあります(対処法は後述).
解説
Gatsby でどのようにして Markdown から ページや slug が生成されているかについては,hththtさんの記事 Gatsbyノート3(slug/pageの生成) が分かりやすいです.
デフォルトでは createFilePath
関数によってファイル名をもとに slug を生成していますが,||
演算子を使って frontmatter 部分に slug
が定義されている場合はそれを用い,そうでなければデフォルト通り生成する,という処理を実現しています.
どんなときに便利か
ブログのポストにあたる Markdown のファイル名を日本語にしたいが,slug は英語を自分で設定したい,ということが可能になります.
また,Markdown を 2022/06/06/title.md
のように 年月日のフォルダで管理しているが,slug は https://example.com/title
にしたい,という場合にも,同じ部分をいじれば可能です.
この場合だと,createFilePath
の出力を適切に split
して取り出すことになると思います.
slug が/
から始まるよう強制する
上記のonCreateNode
内を修正しても良いですが,/
から始まらないような slug の指定が存在した場合コミットができないように,Git のフックを設定する方法を紹介します.
.git/hooks/pre-commit
(存在しなければ作成) に以下を記載すると,このチェックが実現できます.
#!/bin/sh
# Confirm every .md file which has a valid slug, if any, in its frontmatter.
# Slug should start with '/' and be longer than just '/'.
for file in `find content/blog -name '*.md'`; do
match=$(sed -n '/---/{p; :loop n; p; /---/q; b loop}' $file | grep 'slug:' | grep -E -v 'slug: /.+')
if [ "$match" != "" ]; then
echo "Error: Custom slug should start with / and include other character(s) after that."
echo "Check this file: " $file
exit 1
fi
done
find
によって/content/blog
以下の.md
で終わるファイルについてfor
ループを回しています.sed
によって frontmatter 部分 (---
で囲まれた最初の箇所) のみを取り出しています./
でパターンを区切っています.---
を見つけたら,{}
で囲まれた部分を実行します.p
は行を表示します.:loop
でラベルloop
をつけます.n;
で次の行に移ります./---/q;
は---
というパターンを見つけたら loop を quit します.b loop
でループラベルloop
にジャンプします.-n
は,その他の行は表示しない,というオプションです.
grep
によってslug:
を含む行のうち,slug の中身が/
で始まらない行や/
のみで終わっている行を取り出しています.- もしこれが
""
でない場合正しくないので,異常を報告しファイル名を表示してステータスコード1で終了します.
まとめ
今回は,Gatsby でスラッグ(slug)を指定する方法を紹介しました.
個人的には,Git のフックを利用する部分やsed
コマンドの使い方を学べ,勉強になりました.
本記事が少しでも参考になれば幸いです.