gallery.badmanners.xyz/src/components/TocMdx.astro
2024-09-23 13:16:43 -03:00

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>