64 lines
1.8 KiB
Text
64 lines
1.8 KiB
Text
---
|
|
import TableOfContentsHeading from './TableOfContentsHeading.astro'
|
|
|
|
// https://kld.dev/building-table-of-contents/
|
|
const { headings } = Astro.props
|
|
const toc = buildToc(headings)
|
|
|
|
export interface Heading {
|
|
depth: number
|
|
slug: string
|
|
text: string
|
|
}
|
|
|
|
function buildToc(headings: Heading[]) {
|
|
const toc: Heading[] = []
|
|
const parentHeadings = new Map()
|
|
headings.forEach((h) => {
|
|
const heading = { ...h, subheadings: [] }
|
|
parentHeadings.set(heading.depth, heading)
|
|
if (heading.depth === 2) {
|
|
toc.push(heading)
|
|
} else {
|
|
parentHeadings.get(heading.depth - 1).subheadings.push(heading)
|
|
}
|
|
})
|
|
return toc
|
|
}
|
|
---
|
|
|
|
<details open class="group block rounded-xl border p-4 xl:hidden">
|
|
<summary
|
|
class="flex cursor-pointer items-center justify-between text-xl font-semibold"
|
|
>
|
|
Table of Contents
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
class="size-5 transition-transform group-open:rotate-180"
|
|
viewBox="0 0 20 20"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
fill-rule="evenodd"
|
|
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
|
clip-rule="evenodd"></path>
|
|
</svg>
|
|
</summary>
|
|
<nav>
|
|
<ul class="pt-3">
|
|
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
|
|
</ul>
|
|
</nav>
|
|
</details>
|
|
<nav
|
|
class="overflow-wrap-break-word sticky top-16 hidden h-0 w-[calc(50vw-50%-4rem)] translate-x-[calc(-100%-2em)] text-xs leading-4 xl:block"
|
|
>
|
|
<div class="mr-6 flex justify-end">
|
|
<ul class="max-h-[calc(100vh-8rem)] space-y-2 overflow-y-auto">
|
|
<li>
|
|
<h2 class="mb-2 text-lg font-semibold">Table of Contents</h2>
|
|
</li>
|
|
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
|
|
</ul>
|
|
</div>
|
|
</nav>
|