From bced5dceb1149ecb6d21830876bd4c5d2e071218 Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Fri, 12 Jun 2026 11:21:19 +0330 Subject: [PATCH] fix(blog): collapse inactive toc branches --- src/components/BlogTableOfContents.tsx | 30 +++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/components/BlogTableOfContents.tsx b/src/components/BlogTableOfContents.tsx index fd6113c..b32de0a 100644 --- a/src/components/BlogTableOfContents.tsx +++ b/src/components/BlogTableOfContents.tsx @@ -8,9 +8,37 @@ type Props = { headings: MarkdownHeading[]; }; +function getParentHeading(headings: MarkdownHeading[], index: number) { + const heading = headings[index]; + for (let cursor = index - 1; cursor >= 0; cursor -= 1) { + if (headings[cursor].level < heading.level) { + return headings[cursor]; + } + } + return null; +} + export default function BlogTableOfContents({ headings }: Props) { const [activeId, setActiveId] = useState(headings[0]?.id ?? ""); + const parentById = new Map(); + headings.forEach((heading, index) => { + parentById.set(heading.id, getParentHeading(headings, index)?.id ?? null); + }); + + const activeBranch = new Set(); + let cursor = activeId; + while (cursor) { + activeBranch.add(cursor); + cursor = parentById.get(cursor) ?? ""; + } + + const visibleHeadings = headings.filter((heading) => { + const parentId = parentById.get(heading.id); + if (!parentId) return true; + return activeBranch.has(parentId); + }); + useEffect(() => { if (!headings.length) return; @@ -51,7 +79,7 @@ export default function BlogTableOfContents({ headings }: Props) { return (