48 lines
1.1 KiB
Text
48 lines
1.1 KiB
Text
---
|
|
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 (!parent.children) {
|
|
break;
|
|
}
|
|
nextParent = parent.children[parent.children.length - 1];
|
|
}
|
|
if (parent === null) {
|
|
acc.push({ ...heading });
|
|
} else {
|
|
if (parent.children) {
|
|
parent.children.push({ ...heading });
|
|
} else {
|
|
parent.children = [{ ...heading }];
|
|
}
|
|
}
|
|
}
|
|
return acc;
|
|
}, [] as NestedHeading[]);
|
|
---
|
|
|
|
<h2 id="table-of-contents">Table of contents</h2>
|
|
<nav>
|
|
<ul>
|
|
{nestedHeadings.map((heading) => <TocMdxHeading {...heading} />)}
|
|
</ul>
|
|
</nav>
|