--- import TocMdxHeading from "./TocMdxHeading.astro"; type Props = { headings: { depth: number; slug: string; text: string }[]; }; interface NestedHeading { depth: number; slug: string; text: string; children?: NestedHeading[]; } const { headings } = Astro.props; const nestedHeadings = headings.reduce((acc, heading) => { if (acc.length === 0) { acc.push({ ...heading }); } else { let parent: NestedHeading | null = null; let nextParent: NestedHeading = acc[acc.length - 1]; while (nextParent.depth < heading.depth) { parent = nextParent; if (!nextParent.children) { nextParent.children = []; break; } nextParent = nextParent.children[nextParent.children.length - 1]; } if (parent === null) { acc.push({ ...heading }); } else { parent.children!.push({ ...heading }); } } return acc; }, [] as NestedHeading[]); --- <h2 id="table-of-contents">Table of contents</h2> <nav> <ul> {nestedHeadings.map((heading) => <TocMdxHeading {...heading} />)} </ul> </nav>