🐛 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
This commit is contained in:
Ryan Kes authored and Nuno C. committed 2026-09-13 22:12:55 +01:00
1 parent 1a5c232535
commit 36b6a4551c
1 file changed
+15
+15
View File
@@ -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)))