Gatsby製のブログ記事ページに目次を表示させたい
はじめに
ブログの記事の分量が大きくなってくると、記事を上から読むだけでは全体の構造の把握が難しくなってくる。また、記事ページに流入して来たユーザーが記事の内容を一目で把握できるようにすることで、記事の通読率を高めたかった。
そんなわけでこのブログにも記事の目次を作成することにした。このブログはGatsbyで作られているため、Gatsbyでの目次の作成を紹介する。
目次の作成方法
目次は英語でTable Of Contentsと言い、その頭文字をとってTOCと呼ばれたりする。目次を表示するにあたってTOC生成用のライブラリを導入する必要があるかと思ったが、Gatsbyではそれを入れることなく簡単に実現できた。
MarkdownRemark
のNodeにtableOfContents
というフィールドがある。以下のようにクエリ中で指定することで目次データを取得することができる。
query MyQuery {
markdownRemark(id: { eq: $id }) {
id
tableOfContents
frontmatter {
title
}
}
}
例えばMarkdownが以下のようなヘッダーを持つ構造だったとする。
## First
### FirstChild1
### FirstChild2
## Second
すると、tableOfContents
の値は以下のようなHTML構造の文字列を取得できる。ちなみにMarkdown内にヘッダーが存在しない場合は空文字が返ってくる。
"<ul>\n<li>\n<p><a href=\"#first\">First</a></p>\n<ul>\n<li><a href=\"#firstchild1\">FirstChild1</a></li>\n<li><a href=\"#firstchild2\">FirstChild2</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#second\">Second</a></p>\n</li>\n</ul>"
上記の文字列をHTMLとして整形したものが以下。
<ul>
<li>
<p><a href="#first">First</a></p>
<ul>
<li><a href="#firstchild1">FirstChild1</a></li>
<li><a href="#firstchild2">FirstChild2</a></li>
</ul>
</li>
<li><p><a href="#second">Second</a></p></li>
</ul>
以下のようにして目次をページ内に表示することができる。あとはCSS等でスタイルを与えてやると目次が出来上がる。
<nav dangerouslySetInnerHTML={{ __html: contentsOfTable }} />
おわり
TOC生成ライブラリを入れることなく簡単に目次の表示を実現でき、Gatsbyの便利さを改めて感じた。