ギャツビーでTOCを加える方法


多くの人々は、私自身のブログを構築するためにギャツビーを使用しています.私が私のブログに加えたかったものの1つは、目次(TOC)でした📝. TOCは、記事のすべての見出しを表示されますときに直接その見出しにあなたを取る見出しをクリックします.それはあなたのブログには、それは簡単にユーザーがナビゲートし、彼らが探している情報を見つけることができます良いの機能です.

前提条件


だから私たちが始める前にsource code here . この記事では、私はgatsby-starter-blog .
# If you don't have the CLI installed, run this command.
npm -g install gatsby-cli

gatsby new my-gatsby-project https://github.com/gatsbyjs/gatsby-starter-blog
既に既存のギャツビーサイトがある場合は、このスターターを使用する代わりに直接変更を行うことができます.

プラグイン


適切に動作するようにTOC用にインストールされた余分なプラグインを入手する必要があります.
yarn add gatsby-remark-autolink-headers gatsby-plugin-emotion
プラグインgatsby-remark-autolink-headers すべてのヘッダをアンカーリンクにします.これはヘッダーにリンクできることを意味します.

Note: You only need to add the emotion plugin if you want to use emotionjs, which is a css-in-js solution. You will see this later when we look at the toc.js component.


`gatsby-plugin-emotion`,
`gatsby-plugin-smoothscroll`,
{
    resolve: `gatsby-transformer-remark`,
    options: {
        plugins: [
            // ...
            `gatsby-remark-autolink-headers`,
        ],
    },
},
// ...
とのヘッダー要素autolinks プラグインは次のようになります.
<h1 id="header-1" style="position:relative;">
  <a href="#header-1" aria-label="header 1 permalink" class="anchor before"
    >...</a
  >Header 1
</h1>

TOC


まず、TOC要素をデザインしましょう.このコンポーネントはプレゼンテーションコンポーネントだけです.
import styled from "@emotion/styled"
import React from "react"
import tw from "twin.macro"

const ToC = ({ headings }) => (
  <Toc>
    <Title>Table of contents</Title>
    <InnerScroll>
      {headings.map(heading => {
        if (heading.depth > 4) {
          return <div />
        }

        return (
          <ToCElement key={heading.value}>
            <ToCLink
              href={`#${heading.value.replace(/\s+/g, "-").toLowerCase()}`}
            >
              {heading.value}
            </ToCLink>
          </ToCElement>
        )
      })}
    </InnerScroll>
  </Toc>
)

const Toc = styled.ul`
  ${tw`bg-white fixed hidden lg:flex flex-col rounded p-3 my-3`};
  width: 20rem;
  left: calc(50% + 400px);
  top: 80px;
  max-height: 30vh;
`

const Title = tw.h2`text-2xl mb-2`

const ToCElement = tw.li`p-1 leading-5 ml-4 mb-4 mr-4 leading-3 list-none`

const ToCLink = tw.a`hover:text-black transition duration-300 no-underline`

const InnerScroll = styled.div`
  scrollbar-width: thin;
  scrollbar-color: #367ee9 rgba(48, 113, 209, 0.3);
  overflow: hidden auto;
`

export default ToC

この成分を壊しましょう.受信するheading 小道具のリストであるheadings マークダウンドキュメントから.見出しとは# , もっと# sは見出しを下ろします.
# Heading 1

## Heading 2

### Heading 3
我々はheading.map これは、headings リスト内.それが「見出し5」またはそれより低いならば、我々は単に空のdivを返します.heading.depth > 4 . これはTOCがあまり大きくなりません、そして、それは使用するのがより難しくなる/ナビゲートします.
const ToC = ({ headings }) => (
  <Toc>
    <Title>Table of contents</Title>
    <InnerScroll>
      {headings.map((heading) => {
        if (heading.depth > 4) {
          return <div />;
        }

        return (
          <ToCElement key={heading.value}>
            <ToCLink
              href={`#${heading.value.replace(/\s+/g, "-").toLowerCase()}`}
            >
              {heading.value}
            </ToCLink>
          </ToCElement>
        );
      })}
    </InnerScroll>
  </Toc>
);
見出し1 - 4の場合、リスト要素を作成します.<li> ) リンクで<a> ) その中に.これは私たちのTOC内の単一の見出しになります.以下はTOCの例です.

上記のTOCの見出しデータは次のようになります.
const headings = [
  {
    value: "Header 1",
    depth: 1,
  },
  {
    value: "Header 2",
    depth: 2,
  },
];
前に論じたように、我々はautolink ヘッダプラグイン.このプラグインは自動的にすべてのヘッダーのアンカーリンクを生成します.私たちはhref 属性は、我々のTOCでこれらのヘッダーにリンクします.

Note: The href link we replace all the whitespace with - so "Heading 1" becomes the anchor link #heading-1.


<ToCLink href={`#${heading.value.replace(/\s+/g, "-").toLowerCase()}`}>
  {heading.value}
</ToCLink>

ツインマクロ


上記でToC コンポーネントのように<ToCElement> , <InnerScroll> and <ToC> . これらのコンポーネントはどこから来ていますか?さて、これは私たちがgatsby感情プラグインを使用する必要があると言った理由です.これはJSコンポーネントのCSSです.上記のコンポーネントはツインです.マクロまたはemotionjsコンポーネント.コード内で使用するには、次のコマンドを実行します.
yarn add twin.macro @emotion/core @emotion/styled
npx tailwind init
vim package.json
"babelMacros": {
    "twin": {
        "config": "tailwind.config.js",
        "preset": "emotion",
        "debugProp": true,
        "debugPlugins": false,
        "debug": false
    }
}

Info: Gatsby have a good tutorial [here (https://www.gatsbyjs.com/docs/tailwind-css/), on how to integrate TailwindCSS with a Gatsby site.


The twin.macro ライブラリを使用することができます TailwindCSS . Tailwindは多くのプリジェネレーションクラスを提供します.ここでは、あなたはそれがどのように働くかについていくぶん熟知していると仮定しています.
const Toc = styled.ul`
  ${tw`bg-white fixed hidden lg:flex flex-col rounded p-3 my-3`};
  width: 20rem;
  left: calc(50% + 400px);
  top: 80px;
  max-height: 30vh;
`;

const Title = tw.h2`text-2xl mb-2`;

const ToCElement = tw.li`p-1 leading-5 ml-4 mb-4 mr-4 leading-3 list-none`;

const ToCLink = tw.a`hover:text-black transition duration-300 no-underline`;

const InnerScroll = styled.div`
  scrollbar-width: thin;
  scrollbar-color: #367ee9 rgba(48, 113, 209, 0.3);
  overflow: hidden auto;
`;
これはどのように我々はスクロールバーのスタイルです.最初の色はスクロールバーの色で、2番目の色はスクロールバーの背景色です.
const InnerScroll = styled.div`
  scrollbar-width: thin;
  scrollbar-color: #367ee9 rgba(48, 113, 209, 0.3);
  overflow: hidden auto;
`;
注:注意styled.div これはInnerScroll HTMLコードに翻訳すると<div> .
<div class="css-91zyin-InnerScroll eqpue8b4">
  <li class="css-12965kf-ToCElement eqpue8b2">
    <a href="#header-1" class="css-14n9u33-ToCLink eqpue8b3">Header 1</a>
  </li>
</div>
::
見ているもう一つの興味深いコンポーネントはToC . この組み合わせツイン.マクロと感情width CSSはEmotionJamを使用しています.マクロ{tw ... } . ここで我々はtw テイラー風のスタイルで我々は適用したい.下記の例ではfixed 要素の位置を固定します.
const Toc = styled.ul`
  ${tw`bg-white fixed hidden lg:flex flex-col rounded p-3 my-3`};
  width: 20rem;
  left: calc(50% + 400px);
  top: 80px;
  max-height: 30vh;
`;

グローバルスタイル


我々のスクロールがスムーズになるのを許すために必要とする1つの小さな変化は、それがCSSファイルでなければならないかどうか、または、JSのCSSでなければならないかどうかですstyle.css スタートに伴うファイル.次のプロパティーを追加する必要があります.
html {
  scroll-behavior: smooth;
  // ...
}
このCSSプロパティは、ジャーキー感じからスクロールを停止し、代わりにはるかにスムーズになります.そのため、ヘッダにジャンプする代わりに、ToC そして、それはスムーズにそのヘッダーにスクロールします.

ブログテンプレート


最後に、TOC要素をブログテンプレートに追加する必要があります.

ギャツビーノード


それを忘れずにgatsby-node.js ファイルを見つけることができます.ここでは、各マークダウンファイルのページを作成するロジックmarkdown-remark プラグイン.ご覧の通り、我々は使用しますblog-post.js 我々のブログ柱の各々のためのテンプレートとしてのファイル.
exports.createPages = async ({ graphql, actions, reporter }) => {
  const { createPage } = actions;

  // Define a template for blog post
  const blogPost = path.resolve(`./src/templates/blog-post.js`);

  // Get all markdown blog posts sorted by date
  const result = await graphql(
    `
      {
        allMarkdownRemark(
          sort: { fields: [frontmatter___date], order: ASC }
          limit: 1000
        ) {
          nodes {
            id
            fields {
              slug
            }
          }
        }
      }
    `
  );

  const posts = result.data.allMarkdownRemark.nodes;

  // Create blog posts pages
  // But only if there's at least one markdown file found at "content/blog" (defined in gatsby-config.js)
  // `context` is available in the template as a prop and as a variable in GraphQL

  if (posts.length > 0) {
    posts.forEach((post, index) => {
      createPage({
        path: post.fields.slug,
        component: blogPost,
      });
    });
  }
};

ギャツビー設定


マークダウンファイルを「見る」プラグインを許可するには、ソースを指定する必要があります.これを行うにはいくつかの方法がありますgit to source my plugins . この場合、すべてのマークダウンファイルをcontent/blog フォルダ.
{
    resolve: `gatsby-source-filesystem`,
    options: {
        path: `${__dirname}/content/blog`,
        name: `blog`,
    },
}

ブログ柱


だから今私たちにblog-post.js , 我々を加えましょうToC ブログ投稿テンプレートへのコンポーネント.
import ToC from "../components/toc";
// ...

const post = data.markdownRemark;
return (
    <Layout location={location} title={siteTitle}>
        <article className="blog-post" itemScope itemType="http://schema.org/Article">
            <ToC headings={post.headings} />
        </article>
    </Layout>;
)
また、TOCコンポーネントが必要とする見出しデータを取得できるように、GraphSQLクエリを調整しましょう.追加するheadings フィールドと値のフィールドを取得します.
markdownRemark(id: { eq: $id }) {
    id
    excerpt(pruneLength: 160)
    html
    headings {
        value
        depth
    }

    frontmatter {
        title
        date(formatString: "MMMM DD, YYYY")
        description
    }
}
それは、我々が我々のギャツビーサイトにTOCを加えたということです.我々はそれを改善するために他のものの束をすることができます.スタイリングなどの方が良く見えるように.私も、幅が減少するとき、私のTOCを隠します.それで、あなたはラップトップ/デスクトップでサイトを閲覧するとき、TOCを見るだけです.

付録

  • Source Code