[rehype] 記事冒頭に見出しリンク(目次)を追加する
MDXの記事本文に対して、記事冒頭の目次と見出しリンクを同時に付ける方法の記録。
next-mdx-remote で compileMDX している構成を前提にしている。
背景
長めの記事だと、冒頭で構成が分かった方が読みやすい。 そこで、rehypeで見出しを収集して目次を挿入し、各見出しにアンカーリンクも付ける。
環境
- Next.js 16.0.7 (App Router)
- TypeScript
- next-mdx-remote 5.0.0
- rehype-pretty-code 0.14.1
- rehype-slug / rehype-toc / rehype-autolink-headings
実装方針
rehype-slugで見出しにidを付与rehype-tocで見出し一覧を目次として挿入rehype-autolink-headingsで各見出しにリンクを付与
それぞれの役割(簡単に)
rehype-slug: 見出し要素(h2など)にidを自動付与して、リンク先を作るrehype-toc: 付与されたidを使って目次(リンク一覧)を生成し、本文に差し込むrehype-autolink-headings: 各見出しにアンカーリンクを追加し、見出し自体から移動できるようにする
実装手順
1. 依存パッケージを追加
yarn add rehype-slug rehype-toc rehype-autolink-headings2. MDXのrehype設定を追加
lib/note.ts の mdxOptions.rehypePlugins に追加する。
rehype-toc はデフォルトで記事先頭(afterbegin)に目次を挿入するため、
特別なオプション無しでも冒頭に出せる。
// lib/note.ts 抜粋
import rehypeSlug from "rehype-slug";
import rehypeToc from "rehype-toc";
import rehypeAutolinkHeadings from "rehype-autolink-headings";
mdxOptions: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeSlug,
rehypeToc,
[rehypeAutolinkHeadings, { behavior: "append" }],
[
rehypePrettyCode,
{
theme: {
light: "vitesse-light",
dark: "vitesse-dark",
},
transformers: [transformerNotationDiff()],
},
],
],
},3. TOCに含める見出しを絞る(任意)
h2/h3 だけを対象にしたい場合は headings を指定する。
[rehypeToc, { headings: ["h2", "h3"], position: "afterbegin" }]4. 見た目の調整(任意)
rehype-toc は .toc / .toc-level / .toc-item / .toc-link などのクラスを出力するので、
必要に応じてスタイルを足す。
.markdown-body .toc {
padding: 1rem 1.25rem;
border: 1px solid color-mix(in srgb, var(--color-text) 20%, transparent);
margin: 1rem 0 2rem;
border-radius: 8px;
}
.markdown-body .toc-link {
color: inherit;
text-decoration: none;
}
.markdown-body .toc-link:hover {
text-decoration: underline;
}見出しリンク側にクラスを付けたい場合は properties を追加する。
[rehypeAutolinkHeadings, {
behavior: "append",
properties: { className: ["heading-anchor"] },
}].markdown-body .heading-anchor {
margin-left: 0.4em;
opacity: 0.5;
text-decoration: none;
}
.markdown-body .heading-anchor:hover {
opacity: 1;
}まとめ
rehype-slugでidを付与rehype-tocで記事冒頭に目次を追加rehype-autolink-headingsで各見出しにリンクを付与
記事冒頭で構成が分かり、本文中の移動もしやすくなる。