作成日:2022-08-30
Gatsby mdx目次機能を追加しました。gatsby-remark-autolink-headersのみを使用しています。
目次機能ってやっぱりほしいと思い追加しました。まずはどのようにすればいいのか調べた結果
h1,h2,h3...等見出しタグに対して自動でidを付けてくれます。
mdxに記述することでmdx記事内に目次を作成してくれます。 公式から引用
#```toc
# This code block gets replaced with the TOC
exclude: Table of Contents
tight: false
ordered: false
from-heading: 2
to-heading: 6
class-name: "table-of-contents"
#```
gatsby-remark-autolink-headersとgatsby-remark-table-of-contentsを使用することで簡単に追加できるようです。 しかし、gatsby-remark-table-of-contentsはmdxに記述するためカスタマイズがしづらい(できなくもない)。もっと柔軟に目次を追加したいと思ったので gatsby-remark-autolink-headersのみを使用して目次機能を追加することにしました。
gatsby-remark-autolink-headersのプラグインを入れて、後はgraphqlを利用して、自力で目次を作成していきます。
公式ページを確認。 インストール
npm install gatsby-remark-autolink-headers
gatsby-configに記述する。
gatsby-transformer-remarkのpluginsの中に記入する必要がある。公式ページではmdだが、私の場合mdxを使用しているので多少異なる。
また、他の記事でも紹介されている通りgatsby-remark-prismjsを導入しているため、gatsby-remark-autolink-headersをgatsby-remark-prismjsの前に記述した。
このgatsby-plugin-mdx->options->gatsbyRemarkPluginsは多少癖があり、記述の順番が違うとプラグインが反応しなかったりするから、始めて触るときややこしい。
resolve: `gatsby-plugin-mdx`,
options: {
gatsbyRemarkPlugins: [
{
resolve: `gatsby-remark-autolink-headers`,
options: {
offsetY: `100`,
icon: false,
className: `custom-class`,
maintainCase: false,
},
},
resolve: `gatsby-remark-prismjs`,
]
}
まず公式ページの見出しタグにカーソルを当ててみたらクリップマークが表示されることを確認してほしい。
このプラグインのoptionsはクリップマークに対してのオプションがほとんどなので正直不要である
上記のコード以下3つについてもクリップマークに対して働く。
tableOfContentsというGraphiQLを追加機能、リンク見出しタグh1等にidを振ってくれる機能この二つを使用します。
query MyQuery {
mdx {
tableOfContents
}
}
実際確認してみる
mdxブログ用のテンプレートにtableOfContents(maxDepth: 3)を追加します。h3までのタグを対象したいので(maxDepth: 3)を追加します。
import {graphql} from "gatsby"
const PostPagesMain = (props) => {
const list = props.data.mdx.tableOfcontents;
console.log(list);
}
export default PostPagesMain
export const pageQuery = graphql`
query BlogPostQuery($id: String) {
mdx(id: { eq: $id }) {
body
slug
tableOfContents(maxDepth: 3) <--追加
値が取得できオブジェクトが返ってきます。h1の下にh2タグがあると(imtes:array)があることが分かります。
{
"items": [
{
"url": "#h1-1",
"title": "h1-1",
"items": [
{
"items": [
{
"url": "#h2-1",
"title": "h2-1"
},
{
"url": "#h2-2",
"title": "h2-2"
}
]
},
]
},
{
"url": "#h1-2",
"title": "h1-2"
}
]
}
再帰処理を実行すると目次が作成できますね。再帰処理のロジックっていつも頭の中を整理でき無くて、書くのに時間がかかってしまいます。
const list = props.data.mdx.tableOfcontents;
function TOC(list) {
return <li>
<Link to={list.url}>
{list.title}
</Link>
<ul>
{list.items && list.items.map(index =>TOC(index))}
</ul>
</li>
}
export const PostPagesMain = (props) => {
const indexlist = props.data.mdx.tableOfContents;
function returnvalues(obj) {//再起関数
return <li>
{obj.title}
<ul>
{obj.items && obj.items.map(index =>
returnvalues(index))
}
</ul>
</li>
}
return (
<div>
<h4>目次</h4>
<ul>
{indexlist.items.map(items => returnvalues(items))
}
</ul>
</div>
)
}
export const pageQuery = graphql`
query BlogPostQuery($id: String) {
mdx(id: { eq: $id }) {
body
slug
tableOfContents(maxDepth: 3) <--追加
gatsby-remark-autolink-headersを使用することで目次を追加できた。あとは目次をコンポーネント化すればどこでも使うことができる。色々なサイトを見ていったけどやはり目次は必須だと感じた。私自身も、初めにタイトルだけを見て判断するので目次機能はあったらとても助かる。 次回見出しの位置の調整
質問や、間違いがありましたら、お気軽にどうぞ
※お名前とコメントの内容を入力してください。
※全てこのブログ上に公表されます。
※許可なく管理者によって修正・削除する場合がございます。 詳しくはプライバシーポリシーを参照ください