@@ -209,54 +209,66 @@ function generateToc() {
209209
210210function hookTocActiveHighlighting ( ) {
211211 var tocLinks = document . querySelectorAll ( '.toc-link' ) ;
212- if ( tocLinks . length === 0 ) return ;
212+ var targetHeadings = [ ] ;
213+ tocLinks . forEach ( function ( link ) {
214+ var targetId = link . getAttribute ( 'data-target' ) ;
215+ var heading = document . getElementById ( targetId ) ;
216+ if ( heading ) {
217+ targetHeadings . push ( heading ) ;
218+ }
219+ } ) ;
220+
221+ if ( targetHeadings . length === 0 ) return ;
213222
214223 var observerOptions = {
215224 root : null ,
216- rootMargin : '-20 % 0px -35% 0px' ,
225+ rootMargin : '0 % 0px -35% 0px' ,
217226 threshold : 0
218227 } ;
219228
220- var activeLink = null ;
229+ var intersectingHeadings = new Set ( ) ;
230+ function update ( ) {
231+ var firstIntersectingHeading = targetHeadings . find ( function ( heading ) {
232+ return intersectingHeadings . has ( heading ) ;
233+ } ) ;
234+ if ( ! firstIntersectingHeading ) return ;
235+ var correspondingLink = document . querySelector ( '.toc-link[data-target="' + firstIntersectingHeading . id + '"]' ) ;
236+ if ( ! correspondingLink ) return ;
237+
238+ // Remove active class from all links
239+ tocLinks . forEach ( function ( link ) {
240+ link . classList . remove ( 'active' ) ;
241+ } ) ;
242+
243+ // Add active class to current link
244+ correspondingLink . classList . add ( 'active' ) ;
245+ activeLink = correspondingLink ;
246+
247+ // Scroll link into view if needed
248+ var tocNav = document . querySelector ( '#toc-nav' ) ;
249+ if ( tocNav ) {
250+ var linkRect = correspondingLink . getBoundingClientRect ( ) ;
251+ var navRect = tocNav . getBoundingClientRect ( ) ;
221252
253+ if ( linkRect . top < navRect . top || linkRect . bottom > navRect . bottom ) {
254+ correspondingLink . scrollIntoView ( { behavior : 'smooth' , block : 'nearest' } ) ;
255+ }
256+ }
257+ }
222258 var observer = new IntersectionObserver ( function ( entries ) {
223259 entries . forEach ( function ( entry ) {
224260 if ( entry . isIntersecting ) {
225- var id = entry . target . id ;
226- var correspondingLink = document . querySelector ( '.toc-link[data-target="' + id + '"]' ) ;
227-
228- if ( correspondingLink ) {
229- // Remove active class from all links
230- tocLinks . forEach ( function ( link ) {
231- link . classList . remove ( 'active' ) ;
232- } ) ;
233-
234- // Add active class to current link
235- correspondingLink . classList . add ( 'active' ) ;
236- activeLink = correspondingLink ;
237-
238- // Scroll link into view if needed
239- var tocNav = document . querySelector ( '#toc-nav' ) ;
240- if ( tocNav ) {
241- var linkRect = correspondingLink . getBoundingClientRect ( ) ;
242- var navRect = tocNav . getBoundingClientRect ( ) ;
243-
244- if ( linkRect . top < navRect . top || linkRect . bottom > navRect . bottom ) {
245- correspondingLink . scrollIntoView ( { behavior : 'smooth' , block : 'nearest' } ) ;
246- }
247- }
248- }
261+ intersectingHeadings . add ( entry . target ) ;
262+ } else {
263+ intersectingHeadings . delete ( entry . target ) ;
249264 }
250265 } ) ;
266+ update ( ) ;
251267 } , observerOptions ) ;
252268
253269 // Observe all headings that have corresponding TOC links
254- tocLinks . forEach ( function ( link ) {
255- var targetId = link . getAttribute ( 'data-target' ) ;
256- var targetHeading = document . getElementById ( targetId ) ;
257- if ( targetHeading ) {
258- observer . observe ( targetHeading ) ;
259- }
270+ targetHeadings . forEach ( function ( heading ) {
271+ observer . observe ( heading ) ;
260272 } ) ;
261273
262274 // Smooth scroll when clicking TOC links
0 commit comments