ページ内目次(ToC)のレンダリング
Methanol はコンパイル時に見出しを自動的に抽出し、ctx.page.toc を通じて構造化されたデータを提供します。
目次データの各エントリは以下の構造を持ちます。
{
depth: 2,
id: 'my-heading',
value: 'My heading',
children: []
}
ToC レンダラーの実装
以下は、標準的な再帰的実装の例です。
const Toc = ({ toc }) => {
if (!toc || toc.length === 0) return null
return (
<nav aria-label="目次">
<div>このページの内容</div>
<ul>
{toc.map((item) => (
<li>
<a href={`#${item.id}`}>{item.value}</a>
{item.children?.length ? <Toc toc={item.children} /> : null}
</li>
))}
</ul>
</nav>
)
}
export default function PageTemplate({ PageContent, ExtraHead, ctx }) {
return (
<>
<html>
<head>
<ExtraHead />
</head>
<body>
<main>
<PageContent />
</main>
<aside>
<Toc toc={ctx.page.toc} />
</aside>
</body>
</html>
</>
)
}
実装のアドバイス
- 階層の制限: 読みやすさを維持するために、多くのテーマでは抽出する見出しレベルを制限しています(例: H2〜H4)。
- スクロール同期: 「アクティブなセクションの強調表示」などの機能を実装する場合は、クライアントコンポーネントの使用を推奨します。Methanol のデフォルトテーマにある
ThemeToCContainer.client.jsxが非常に参考になります。