中野's workspace

  • Profile
  • Privacy
  • Contact

2019/07/15

GatsbyJSで目次を実装する

  • #Gatsby
  • #JavaScript

目次

はじめに

記事内に目次機能を導入したいと思い、実装してみました。

当初はgatsby-remark-tocを利用してサクッと作ろうとしたのですが、動かなかったのでGraphQLを使って導入しました。
大まかに、以下の工程で実装できます。

  1. GraphQLで目次取得
  2. gatsby-remark-autolink-headersで見出しにidを入れる

GraphQLで目次取得

GatsbyではtableOfContentsというクエリを投げることで目次一覧を取得することが出来ます。

  query {
    allMarkdownRemark {
      edges {
        node {
          tableOfContents(pathToSlugField: "frontmatter.slug")
          frontmatter {
            slug
          }
        }
      }
    }
  }

記事毎の目次の表示を実装したい場合はpathToSlugFieldでスラグを指定することで絞り込みを行うことができます。

結果は以下のようになります。

{
  "data": {
    "allMarkdownRemark": {
      "edges": [
        {
          "node": {
            "tableOfContents": "<ul>\n<li>
            <a href=\"/gatsby-toc/#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB\">はじめに</a>
            </li>\n<li><a href=\"/gatsby-toc/#graphql%E3%81%A7%E7%9
            B%AE%E6%AC%A1%E5%8F%96%E5%BE%97\">GraphQLで目次取得</a></li>\n<li>
            <a href=\"/gatsby-toc/#gatsby-remark-autolink-headers
            %E3%81%A7%E8%A6%8B%E5%87%BA%E3%81%97%E3%81%ABid%E3%82%92%E5%
            85%A5%E3%82%8C%E3%82%8B\">gatsby-remark-autolink-headersで見出しにidを入れる
            </a></li>\n<li>
            <a href=\"/gatsby-toc/#%E3%81%BE%E3%81%A8%E3%82%81\">まとめ</a>
            </li>\n</ul>",
            "frontmatter": {
              "slug": "gatsby-toc"
            }
          }
        }
      ]
    }
  }
}

これでテーブルタグが取得できたのであとは表示するだけだと嬉しいのですが、記事の各見出しにidを挿入する必要があります。

これに関してはgatsbyのプラグインを利用することで簡単に出来ます。

gatsby-remark-autolink-headersを利用することで簡単に記事の各見出しにidを挿入することが出来ます。

まずはインストール

yarn add gatsby-remark-autolink-headers1

あとは他のプラグインと同様にgatsby-config.js内に設定するだけです。

gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [`gatsby-remark-autolink-headers`],
      },
    },
  ],
}

注意点として、prismjsを設定している場合、それより上にgatsby-remark-autolink-headersを設定しなければいけません。

gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
            `gatsby-remark-autolink-headers`,
            `gatsby-remark-prismjs`
        ],
      },
    },
  ],
}

上記のような形ですね。

設定した後、gatsby developして各見出しの要素を見ると、idが挿入されています。

<h2 id="gatsby-remark-autolink-headersで見出しにidを入れる">
    gatsby-remark-autolink-headersで見出しにidを入れる
</h2>

これで目次の生成と各見出しにidの挿入が出来たので、あとは表示するだけです。 GraphQLで取得した目次をdangerouslySetInnerHTMLを使って表示します。

<div 
dangerouslySetInnerHTML=
    {{ 
        __html: query.data.allMarkdownRemark.edges[0].node.tableOfContents 
    }} 
/>

以下のようにリンクが表示されているはずです。

あとはcssでお好みのデザインを施してください。

まとめ

gatsbyで目次を作る方法のまとめとしては以下の通りです。

  1. GraphQLのtableOfContentsクエリで目次一覧を取得
  2. gatsby-remark-autolink-headersで記事見出しにidを自動挿入
  3. dangerouslySetInnerHTMLを使って目次一覧を表示

少し手順は複雑ですが、工程自体は少ないのでぜひ試してみてください!

このエントリーをはてなブックマークに追加