Hero img
Gatsby目次を追加する

Gatsby mdxに目次を追加しました。

Gatsby mdx目次機能を追加しました。gatsby-remark-autolink-headersのみを使用しています。


目次

  • Gatsbyに目次機能が欲しい
  • pluginを利用する
  • gatsby-remark-autolink-headers
  • gatsby-remark-table-of-contents
  • gatsby-remark-table-of-contentsを使わない理由
  • 目次機能を導入する
  • gatsby-remark-autolink-headers
  • gatsby-remark-autolink-headersのoptionについて
  • graphqlで確認する
  • mdxコンポーネントに追加
  • 値を利用し目次を作成する。
  • まとめ

Gatsbyに目次機能が欲しい

目次機能ってやっぱりほしいと思い追加しました。まずはどのようにすればいいのか調べた結果

  • gatsby-remark-autolink-headers
  • gatsby-remark-table-of-contents
    この二つがありました。 英語では目次機能は「TOC」だそうです。TOCで検索すると沢山の記事がヒットすると思います。

pluginを利用する

h1,h2,h3...等見出しタグに対して自動でidを付けてくれます。

gatsby-remark-table-of-contents

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-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は多少癖があり、記述の順番が違うとプラグインが反応しなかったりするから、始めて触るときややこしい。

gatsby-config.js
      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つについてもクリップマークに対して働く。

  • offsetY: 100x
  • icon: false
  • className: custom-class
    iconは今回不要なのでfalseで設定。
    今回重要なのはmaintainCaseです。idのアルファベットに対して大文字を使用するか小文字の身にするかを選択できます。 私の場合大文字を使用するとGraphQLで上手く機能しなかったのでfalseを指定しています。

graphqlで確認する

tableOfContentsというGraphiQLを追加機能、リンク見出しタグh1等にidを振ってくれる機能この二つを使用します。

query MyQuery {
  mdx {
    tableOfContents
  }
}

実際確認してみる tableOfContents-GraphiQL

mdxコンポーネントに追加

mdxブログ用のテンプレートにtableOfContents(maxDepth: 3)を追加します。h3までのタグを対象したいので(maxDepth: 3)を追加します。

blogcomponent.js
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を使用することで目次を追加できた。あとは目次をコンポーネント化すればどこでも使うことができる。色々なサイトを見ていったけどやはり目次は必須だと感じた。私自身も、初めにタイトルだけを見て判断するので目次機能はあったらとても助かる。 次回見出しの位置の調整

関連記事

コメント

コメントを書く

質問や、間違いがありましたら、お気軽にどうぞ

※お名前とコメントの内容を入力してください。
※全てこのブログ上に公表されます。
※許可なく管理者によって修正・削除する場合がございます。 詳しくはプライバシーポリシーを参照ください