From 456cf011b36de91c9936994b1fa45703adcd309b Mon Sep 17 00:00:00 2001 From: Dawid Rycerz Date: Thu, 3 Jul 2025 10:56:21 +0300 Subject: Initial fork of chrismwilliams/astro-theme-cactus theme --- src/utils/generateToc.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/utils/generateToc.ts (limited to 'src/utils/generateToc.ts') diff --git a/src/utils/generateToc.ts b/src/utils/generateToc.ts new file mode 100644 index 0000000..f63f0bf --- /dev/null +++ b/src/utils/generateToc.ts @@ -0,0 +1,37 @@ +// Heavy inspiration from starlight: https://github.com/withastro/starlight/blob/main/packages/starlight/utils/generateToC.ts +import type { MarkdownHeading } from "astro"; + +export interface TocItem extends MarkdownHeading { + children: TocItem[]; +} + +interface TocOpts { + maxHeadingLevel?: number | undefined; + minHeadingLevel?: number | undefined; +} + +/** Inject a ToC entry as deep in the tree as its `depth` property requires. */ +function injectChild(items: TocItem[], item: TocItem): void { + const lastItem = items.at(-1); + if (!lastItem || lastItem.depth >= item.depth) { + items.push(item); + } else { + injectChild(lastItem.children, item); + return; + } +} + +export function generateToc( + headings: ReadonlyArray, + { maxHeadingLevel = 4, minHeadingLevel = 2 }: TocOpts = {}, +) { + // by default this ignores/filters out h1 and h5 heading(s) + const bodyHeadings = headings.filter( + ({ depth }) => depth >= minHeadingLevel && depth <= maxHeadingLevel, + ); + const toc: Array = []; + + for (const heading of bodyHeadings) injectChild(toc, { ...heading, children: [] }); + + return toc; +} -- cgit v1.2.3