本記事ではNext.jsで目次機能を実装していきます。以前に書いたmicroCMS + Next.jsでJamstackブログを作ってみようの拡張版になります。本記事はこのチュートリアルを終えてる前提で話を進めていきます。
今回の作成イメージはmicroCMSブログの記事内部にある目次です。リッチエディタの見出しに連動して目次が作成されます。さらにmicroCMS内部で目次の表示有無を判定するフィールドも追加してみましょう。
microCMSで目次を作る でも目次機能の作成方法が紹介されています。ぜひ一読してください。
目次コンポーネントを作成する
まずは、リッチエディタで取得したデータを目次のデータに整形する必要があります。cheerioというライブラリをインストールしましょう。
npm install --save cheerio
そして、libs配下にrender-toc.jsを作成します。これはbody(リッチエディタのデータ)を渡すと、h1、h2、h3のタグを抽出してくれます。そして、抽出したデータを元に配列を作成します。
import * as cheerio from 'cheerio';
export const renderToc = (body) => {
const $ = cheerio.load(body);
const headings = $('h1, h2, h3').toArray();
const toc = headings.map((data) => ({
text: data.children[0].data,
id: data.attribs.id
}));
return toc;
};
上記のメソッドを呼んで実際にどんなデータが配列として帰ってくるか確認してみましょう。pages/blog/[id].jsにインポートして、renderTocにblog.bodyを渡して検証してみましょう。
// pages/blog/[id].js
import { client } from "../../libs/client";
import { renderToc } from '../../libs/render-toc'; // 追加
import styles from '../../styles/Home.module.scss';
export default function BlogId({ blog }) {
const toc = renderToc(blog.body);
console.log(toc); // 検証用にconsole.logでデバッグ
return (
//more
);
}
すると、下記のような配列データが返されることが確認できます。このデータを元に目次機能を実装していきます。
[
{text: 'これは見出し1です', id: 'h1de74680b0'}
{text: 'これは見出し2です', id: 'h21ba5eb01f'}
{text: 'これは見出し3です', id: 'ha3e9327eec'}
]
componentsフォルダの中にTalbleOfContent.jsファイルを作成します。中身は単純で、上記で作成したtoc(配列のデータ)をTableOfContentsコンポーネントでpropsとして受け取ってmapしているだけです。
export const TableOfContents = ({ toc }) => {
return (
<div>
<p className="TableOfContentsHead">目次</p>
<ul>
{toc.map(data => (
<li key={data.id}>
<a href={`#${data.text}`}>
{data.text}
</a>
</li>
))}
</ul>
</div>
);
};
このコンポーネントをブログの詳細画面でインポートしてみましょう。
// pages/blog/[id].js
import { client } from "../../libs/client";
import { renderToc } from '../../libs/render-toc';
import styles from '../../styles/Home.module.scss';
import { TableOfContents } from '../../components/TableOfContents'; // TableOfContentsをインポートする
export default function BlogId({ blog }) {
const toc = renderToc(blog.body);
return (
<main className={styles.main}>
<h1 className={styles.title}>{blog.title}</h1>
<p className={styles.publishedAt}>{blog.publishedAt}</p>
<TableOfContents toc={toc} />
// more
</main>
);
}
ブラウザで確認するとこのようになります。タイトルの下に目次を作成することができました。
以上を踏まえて、目次の表示有無をmicroCMSの管理画面で制御してみましょう。
目次フィールドを追加
microCMSの管理画面にアクセスしてブログのAPIスキーマに追加します。API名に目次、エンドポイントにtoc_visibleを入力してください。
するとコンテンツ詳細画面でスイッチとして設定できます。値はbooleanで返します。
コードとしては以下になります。論理積(&&)を使って表示の有無を制御します。
{blog.toc_visible && (
<TableOfContents toc={toc} />
)}
おわりに
今回はNext.jsで目次機能の実装について解説しました。目次機能は読者にとって分かりやすくコンテンツの詳細を明示できます。今回の記事が役立てば嬉しいです。
-----
microCMSは日々改善を進めています。
ご意見・ご要望は管理画面右下のチャット、公式Twitter、メールからお気軽にご連絡ください!
引き続きmicroCMSをよろしくお願いいたします!