kamilrashid.dev
Menu

file_type_astro
Adding Table of Contents in Astro
TOC based on Headings generated by `.getEntry()` & its alt in NextJS
Jan 12, 2025

AstroJS

Fetch headings

  • from entry.rendered.metadata.headings generated in Content Collections
let toc = []
function buildToc(headings:[]){
	// console.log(headings);
	
	const parentHeading = new Map()
	headings.forEach ((h)=>{
		const heading = {...h, subheadings: []}
		parentHeading.set(heading.depth,heading)
		if (heading.depth === 2 ){
			toc.push(heading)
		} else {
			parentHeading.get(heading.depth-1)?.subheadings.push(heading)
		}
	})
}
if (entry.rendered.metadata?.headings){
    buildToc(entry.rendered.metadata.headings)
}

Generate Table of Contents

---
const {heading}  = Astro.props;
---
<li>
    <a href={'#' + heading.slug}>
      {heading.text}
    </a>
    {
        heading.subheadings.length > 0 && (
            <ul class="pl-3">
                {
                    heading.subheadings.map((subheading)=>(
                        <Astro.self heading={subheading} />
                    ))
                }
            </ul>
        )
    }
  </li>
  • Using Astro.self to loop until all the headings are generated.

NextJS

// ...existing code...
import React from 'react';

export default function TableOfContents({ heading }) {
  return (
    <ul>
      {heading.subheadings.map((subheading) => (
        <TableOfContents key={subheading.id} heading={subheading} />
      ))}
    </ul>
  );
}
// ...existing code...
  • Using TableOfContents to loop until all the headings are generated.