From bac5a7c3ebf365755067240f938aeae1dfeacb74 Mon Sep 17 00:00:00 2001 From: Plumbiu <3434909403@qq.com> Date: Tue, 6 May 2025 11:38:38 +0800 Subject: [PATCH 1/2] feat: Add scroll support for the TOC. --- .../theme-default/composables/outline.ts | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/client/theme-default/composables/outline.ts b/src/client/theme-default/composables/outline.ts index d9eda9c123be..3f4bf3fefaf9 100644 --- a/src/client/theme-default/composables/outline.ts +++ b/src/client/theme-default/composables/outline.ts @@ -8,6 +8,8 @@ const ignoreRE = /\b(?:VPBadge|header-anchor|footnote-ref|ignore-header)\b/ // cached list of anchor elements from resolveHeaders const resolvedHeaders: { element: HTMLHeadElement; link: string }[] = [] +let asideOutlineLinkDomList: NodeListOf | null = null +let asideContainerDom: HTMLDivElement | null = null export function resolveTitle(theme: DefaultTheme.Config): string { return ( @@ -87,6 +89,7 @@ export function useActiveAnchor( onMounted(() => { requestAnimationFrame(setActiveLink) + window.addEventListener('scroll', onScroll) }) @@ -99,6 +102,27 @@ export function useActiveAnchor( window.removeEventListener('scroll', onScroll) }) + function scrollToActiveLink(i: number) { + if (!asideContainerDom) { + asideContainerDom = document.querySelector('.aside-container')! + } + const containerClientHeight = container.value.clientHeight + const asideContainerClientHeight = asideContainerDom.clientHeight + if (containerClientHeight > asideContainerClientHeight) { + if (!asideOutlineLinkDomList) { + asideOutlineLinkDomList = document.querySelectorAll( + '.VPDocOutlineItem.root .outline-link' + ) + } + const height = asideOutlineLinkDomList[i]?.clientHeight + if (height) { + asideContainerDom.scrollTo({ + top: i * height + }) + } + } + } + function setActiveLink() { if (!isAsideEnabled.value) { return @@ -137,14 +161,18 @@ export function useActiveAnchor( } // find the last header above the top of viewport - let activeLink: string | null = null - for (const { link, top } of headers) { + let activeIndex: number | null = null + for (let i = 0; i < headers.length; i++) { + const { top } = headers[i] if (top > scrollY + getScrollOffset() + 4) { break } - activeLink = link + activeIndex = i + } + if (activeIndex !== null) { + scrollToActiveLink(activeIndex) + activateLink(headers[activeIndex].link) } - activateLink(activeLink) } function activateLink(hash: string | null) { From e1365e6cc9370dd5e75dd62cf9da396930eaf24d Mon Sep 17 00:00:00 2001 From: Plumbiu <3434909403@qq.com> Date: Tue, 6 May 2025 11:39:41 +0800 Subject: [PATCH 2/2] chore: remove whitespace --- src/client/theme-default/composables/outline.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/theme-default/composables/outline.ts b/src/client/theme-default/composables/outline.ts index 3f4bf3fefaf9..5cc916ca4581 100644 --- a/src/client/theme-default/composables/outline.ts +++ b/src/client/theme-default/composables/outline.ts @@ -89,7 +89,6 @@ export function useActiveAnchor( onMounted(() => { requestAnimationFrame(setActiveLink) - window.addEventListener('scroll', onScroll) })