diff --git a/lib/rdoc/generator/template/aliki/js/aliki.js b/lib/rdoc/generator/template/aliki/js/aliki.js index 599dc4a15d..5fcc3ac317 100644 --- a/lib/rdoc/generator/template/aliki/js/aliki.js +++ b/lib/rdoc/generator/template/aliki/js/aliki.js @@ -209,54 +209,65 @@ function generateToc() { function hookTocActiveHighlighting() { var tocLinks = document.querySelectorAll('.toc-link'); - if (tocLinks.length === 0) return; + var targetHeadings = []; + tocLinks.forEach(function(link) { + var targetId = link.getAttribute('data-target'); + var heading = document.getElementById(targetId); + if (heading) { + targetHeadings.push(heading); + } + }); + + if (targetHeadings.length === 0) return; var observerOptions = { root: null, - rootMargin: '-20% 0px -35% 0px', + rootMargin: '0% 0px -35% 0px', threshold: 0 }; - var activeLink = null; + var intersectingHeadings = new Set(); + function update() { + var firstIntersectingHeading = targetHeadings.find(function(heading) { + return intersectingHeadings.has(heading); + }); + if (!firstIntersectingHeading) return; + var correspondingLink = document.querySelector('.toc-link[data-target="' + firstIntersectingHeading.id + '"]'); + if (!correspondingLink) return; + + // Remove active class from all links + tocLinks.forEach(function(link) { + link.classList.remove('active'); + }); + + // Add active class to current link + correspondingLink.classList.add('active'); + + // Scroll link into view if needed + var tocNav = document.querySelector('#toc-nav'); + if (tocNav) { + var linkRect = correspondingLink.getBoundingClientRect(); + var navRect = tocNav.getBoundingClientRect(); + if (linkRect.top < navRect.top || linkRect.bottom > navRect.bottom) { + correspondingLink.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + } + } + } var observer = new IntersectionObserver(function(entries) { entries.forEach(function(entry) { if (entry.isIntersecting) { - var id = entry.target.id; - var correspondingLink = document.querySelector('.toc-link[data-target="' + id + '"]'); - - if (correspondingLink) { - // Remove active class from all links - tocLinks.forEach(function(link) { - link.classList.remove('active'); - }); - - // Add active class to current link - correspondingLink.classList.add('active'); - activeLink = correspondingLink; - - // Scroll link into view if needed - var tocNav = document.querySelector('#toc-nav'); - if (tocNav) { - var linkRect = correspondingLink.getBoundingClientRect(); - var navRect = tocNav.getBoundingClientRect(); - - if (linkRect.top < navRect.top || linkRect.bottom > navRect.bottom) { - correspondingLink.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); - } - } - } + intersectingHeadings.add(entry.target); + } else { + intersectingHeadings.delete(entry.target); } }); + update(); }, observerOptions); // Observe all headings that have corresponding TOC links - tocLinks.forEach(function(link) { - var targetId = link.getAttribute('data-target'); - var targetHeading = document.getElementById(targetId); - if (targetHeading) { - observer.observe(targetHeading); - } + targetHeadings.forEach(function(heading) { + observer.observe(heading); }); // Smooth scroll when clicking TOC links