Next.js を使用した MDX の目次


個人の Web サイトといくつかのドキュメントに Next.js と MDX を使用しています.各記事の見出しのリストである「目次」を表示したいと考えています.

プラグイン remark-toc を試しましたが、複雑すぎます (私には).何時間も費やして、まだ目次が機能しませんでした... それで、私は自分でそれを書こうとしました.

見出しのリストを取得する



見出しのリストを取得するためのコードは次のとおりです.

// ./components/PostLayout.js

import { renderToString } from "react-dom/server";
import { MDXProvider } from "@mdx-js/react";

import MDXComponents from "./MDXComponents";

const PostLayout = ({ children }) => {
  const contentString = renderToString(children);

  const getHeadings = (source) => {
    const regex = /<h2>(.*?)<\/h2>/g;

    if (source.match(regex)) {
      return source.match(regex).map((heading) => {
        const headingText = heading.replace("<h2>", "").replace("</h2>", "");

        const link = "#" + headingText.replace(/ /g, "_").toLowerCase();

        return {
          text: headingText,
          link,
        };
      });
    }

    return [];
  };

  const headings = getHeadings(contentString);

  return (
    <>
      {/* ... */}

      {headings.length > 0 ? (
        <ol>
          {headings.map((heading) => (
            <li key={heading.text}>
              <a href={heading.link}>{heading.text}</a>
            </li>
          ))}
        </ol>
      ) : null}

      <MDXProvider components={MDXComponents}>
        <Container>{children}</Container>
      </MDXProvider>
    </>
  );
};


ID を見出しに追加する


MDXProvider を使用して Markdown コンテンツをレンダリングし、別のファイルでコンポーネントをカスタマイズします.

カスタマイズされた h2 は次のとおりです.

// ./components/MDXComponents.js

const Heading2 = ({ children }) => {
  const idText = children.replace(/ /g, "_").toLowerCase();

  return <h2 id={idText}>{children}</h2>;
};

const MDXComponents = {
  h2: Heading2,
  // ...
};

export default MDXComponents;


これで、すべてが期待どおりに機能します. Next.js & MDX スターターを作成しました.click here to visit the repo でコード全体を見つけることができました.