dad2b237d480ba64706fbb6c63d092b2738a2413 jnavarr5 Mon Aug 24 15:33:38 2026 -0700 Add ### headings as indented TOC sub-items and fix docs sidebar highlighting, refs #36320 diff --git docs/staticPage.html docs/staticPage.html index fb00a516517..7f08813bb12 100755 --- docs/staticPage.html +++ docs/staticPage.html @@ -1,61 +1,111 @@ <style> p + pre, p + div > pre { margin-top: 1em !important; } pre { margin-bottom: 1em !important; } </style> $for(include-before)$ $include-before$ $endfor$ $body$ $for(include-after)$ $include-after$ $endfor$ <script> // Scroll-spy: highlight the current section in the sidebar TOC (function() { var toc = document.getElementById('docs-toc'); if (!toc) return; var links = toc.querySelectorAll('a[href^="#"]'); if (!links.length) return; var sections = []; for (var i = 0; i < links.length; i++) { var id = links[i].getAttribute('href').slice(1); var el = document.getElementById(id); if (el) sections.push({link: links[i], target: el}); } if (!sections.length) return; + function setActive(link) { + for (var i = 0; i < sections.length; i++) { + sections[i].link.parentNode.classList.remove('active'); + } + link.parentNode.classList.add('active'); + } + + // Jumping to a section in the final screenful leaves the page at its + // maximum scroll, where the sweep below would hand the highlight to a + // later section. So a clicked link stays pinned until the reader scrolls. + var pinned = null; + function onScroll() { + if (pinned) { + setActive(pinned); + return; + } var scrollY = window.scrollY || window.pageYOffset; + var viewHeight = window.innerHeight; + var maxScroll = document.documentElement.scrollHeight - viewHeight; + // A section becomes current once it passes a reading line 80px below + // the top of the viewport. Sections in the final screenful never + // reach that line, because the page stops scrolling first, so once we + // enter the last screen the line sweeps down to the bottom of the + // viewport. That gives every trailing section its turn and leaves the + // last one current at the very bottom. + var sweepStart = Math.max(0, maxScroll - viewHeight); + var t = 0; + if (maxScroll > sweepStart) { + t = (scrollY - sweepStart) / (maxScroll - sweepStart); + t = Math.max(0, Math.min(1, t)); + } + var line = scrollY + 80 + t * (viewHeight - 80); var current = sections[0]; - // At the bottom of the page the last section is often too short to - // scroll within the 80px threshold, so highlight it explicitly. - if (window.innerHeight + scrollY >= document.documentElement.scrollHeight - 2) { - current = sections[sections.length - 1]; - } else { for (var i = 0; i < sections.length; i++) { - if (sections[i].target.offsetTop <= scrollY + 80) { + if (sections[i].target.offsetTop <= line) { current = sections[i]; } } + setActive(current.link); } + for (var i = 0; i < sections.length; i++) { - sections[i].link.parentNode.classList.remove('active'); + sections[i].link.addEventListener('click', function() { + pinned = this; + setActive(this); + }); } - current.link.parentNode.classList.add('active'); + + // Any genuine scroll input hands control back to the sweep. mousedown + // covers dragging the scrollbar, and fires before the click above, so + // clicking a TOC link still ends up pinned. + function release() { + pinned = null; } + window.addEventListener('wheel', release, {passive: true}); + window.addEventListener('touchmove', release, {passive: true}); + window.addEventListener('keydown', release); + window.addEventListener('mousedown', release); window.addEventListener('scroll', onScroll); + + // Landing on the page with a #section URL has the same problem as a click. + if (window.location.hash) { + for (var i = 0; i < sections.length; i++) { + if ('#' + sections[i].target.id === window.location.hash) { + pinned = sections[i].link; + break; + } + } + } onScroll(); })(); </script> <!--#include virtual="$$ROOT/inc/gbPageEnd.html" -->