diff --git a/assets/js/critical/sidebar-active.js b/assets/js/critical/sidebar-active.js index 42129a3e..b4227822 100644 --- a/assets/js/critical/sidebar-active.js +++ b/assets/js/critical/sidebar-active.js @@ -2,6 +2,20 @@ // (section, version, language, variant) and cached, so the server no longer emits per-page // `active` classes or an expanded collapse trail; this script applies them from the current // location. It runs in the critical bundle so the highlight lands before first paint. +// +// Matching is exact first, nearest-ancestor second: a link whose path equals the current +// path always wins, and only when no link matches exactly does the longest link that is a +// path ancestor of the current page take over (flagged `aria-current="true"` rather than +// "page"). The ancestor pass is what keeps the trail highlighted for pages the menu cannot +// contain - a page built with `build.list = never`, or one generated by a content adapter, +// is absent from the page collections the menu is built from, so it has no entry of its own. +// Without the fallback nothing matched at all and the sidebar rendered with no active item +// and every group collapsed. Ancestor matching compares against `path + "/"`, so +// `/docs/guides` never claims `/docs/guides-advanced/`, and it skips links to the site root, +// which would otherwise claim every page on the site. +// +// Ancestor matching is a property of the link's href, so it needs no opt-in marker in the +// markup: every link in the nav is a candidate. Do not reintroduce one. (function () { 'use strict' @@ -15,7 +29,10 @@ var best = null var bestLength = -1 var bestExact = false - nav.querySelectorAll('a[href]').forEach(function (link) { + // The brand logo is inside the