kawa.dev

BlogSlide
NextjsでSSGを適用する目次を生成する

SSGを適用したNextjsで目次を生成する

2020-12-29

Next.js

/

Javascript

SSGを適用したNext.jsで,目次(Table of Content)を生成する方法を紹介します.

h2タグを大目次,h3タグを小目次とし,こちらのような目次を生成することができます.

toc-result

こちらのブログはNext.jsで作成しており,目次を生成しています.具体的なコードを見たい方は,こちらのリポジトリを参考にしてください.

https://github.com/kawa1214/micro-cms-nextjs-blog-boiler-template

NextjsでSSGを適用する

Next.jsではgetStaticPropsを用いることで,静的なファイルを事前に生成することができます.

./pages/blogs/[id].tsx

export const getStaticProps: GetStaticProps = async context => { const id = context.params.id; const key = { headers: { 'X-API-KEY': process.env.API_KEY }, } const res = await fetch(process.env.ENDPOINT + '/blogs/' + id, key) const blog: BlogType = await res.json() return { props: { blog: blog, }, } }

目次を生成する

cheerioでhtmlを解析し,目次を生成します.

今回は,h2を大目次,h3を小目次としています.

./pages/blogs/[id].tsx

const Blog: React.FC<BlogProps> = ({ blog, toc }) => { return ( <> <div id="blog_toc" dangerouslySetInnerHTML={{ __html: toc, }} /> </> ) } export default Blog const generateTableOfContent = (body: string) => { const $ = cheerio.load(body,{ decodeEntities: false }) let generateHtml = '' generateHtml = generateHtml + '<ul>' $('h2, h3').each((index, elm) => { const text = $(elm).html() const tag = $(elm)[0].name const refId = $(elm)[0].attribs.id generateHtml = generateHtml + `<li class="toc_${tag}" key=${index}>`+ ` <a href="#${refId}">${text}</a>`+ '</li>' }) generateHtml = generateHtml + '</ul>' return generateHtml } export const getStaticProps: GetStaticProps = async context => { const id = context.params.id; const key = { headers: { 'X-API-KEY': process.env.API_KEY }, } const res = await fetch(process.env.ENDPOINT + '/blogs/' + id, key) const blog: BlogType = await res.json() const toc: string = generateTableOfContent(blog.body) return { props: { blog: blog, toc: toc, }, } }

生成したHTMLにCSSを適用します.こちらのサンプルコードはtailwind cssを使用しています.

./styles/Blog.module.css

/* blog table of content*/ #blog_toc ul { @apply bg-white rounded px-2 py-2; } #blog_toc li { @apply ml-4 my-1.5; } #blog_toc a:link { @apply text-gray-900; } #blog_toc a:visited { @apply text-gray-900; } #blog_toc a:hover { color: #4C74B9; } #blog_toc a:active { color: #4C74B9; } #blog_toc .toc_h3 { @apply pl-4 }