From 36b6a4551c9eae605ec951265980c913449e5a76 Mon Sep 17 00:00:00 2001 From: Ryan Kes Date: Fri, 4 Sep 2026 18:35:56 +0200 Subject: [PATCH] :bug: Fix smartTOC never highlighting on a page that can't scroll getActiveAnchorId derives the active entry from scroll position alone, so on a page short enough that scrollHeight never exceeds window.innerHeight, the answer can never change. Clicking a TOC entry still updates location.hash, but nothing ever picks it up as active. Falls back to the hash when the page can't scroll, honoured only if it names an entry the TOC actually lists. Pages that do scroll are unaffected - this only fires when scroll position can't answer the question at all. Fixes #3087 --- layouts/partials/toc.html | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/layouts/partials/toc.html b/layouts/partials/toc.html index a9859a7a..25e85d9f 100644 --- a/layouts/partials/toc.html +++ b/layouts/partials/toc.html @@ -36,6 +36,21 @@ let isJumpingToAnchor = false function getActiveAnchorId(anchors, offsetRatio) { + // On a page short enough that it never scrolls, scroll position can + // never change, so the loop below can never pick a different entry. + // Clicking a TOC entry still changes the hash, so fall back to that + // when scrolling can't answer the question at all - honoured only if + // it names an entry the TOC actually lists, so an unrelated hash + // doesn't fake a match. Pages that do scroll are unaffected. + const canScroll = + document.documentElement.scrollHeight > window.innerHeight + 1 + if (!canScroll) { + const fromHash = decodeURIComponent(window.location.hash.substring(1)) + const known = [...document.querySelectorAll('#TableOfContents a[href^="#"]')] + .map(link => decodeURIComponent(link.getAttribute('href').substring(1))) + if (fromHash && known.includes(fromHash)) return fromHash + } + const threshold = window.scrollY + window.innerHeight * offsetRatio const tocLinks = [...document.querySelectorAll('#TableOfContents a[href^="#"]')] const tocIds = new Set(tocLinks.map(link => link.getAttribute('href').substring(1)))