// A nav item is visible (not off) when it is: current, ancestor of current,
// sibling of current (only when current is not a section-index node), or child of current.
// `inPath` = inSubtree(node, currentUrl), pre-computed by the caller to avoid double traversal.
+// `isAlias` = true for nav-only stub entries: isCurrent and isAncestor are suppressed so the
+// alias is hidden in Classic layout when its page is active (the canonical entry handles that).
function nodeOff(
nodeUrl: string,
parentUrl: string,
inPath: boolean,
currentParentUrl: string,
currentIsNode: boolean,
+ isAlias = false,
): boolean {
- const isCurrent = nodeUrl === currentUrl;
- const isAncestor = inPath && !isCurrent;
+ const isCurrent = !isAlias && nodeUrl === currentUrl;
+ const isAncestor = !isAlias && inPath && !isCurrent;
const isSibling = parentUrl === currentParentUrl && !currentIsNode;
const isChild = parentUrl === currentUrl;
return !(isCurrent || isAncestor || isSibling || isChild);
// Partial application of nodeOff bound to the Projects subtree's current-page context
const _projCurrentParentUrl = activeProjectCurrentParent?.url ?? '';
-const projNodeOff = (nodeUrl: string, parentUrl: string, inPath: boolean) =>
- nodeOff(nodeUrl, parentUrl, inPath, _projCurrentParentUrl, activeProjectCurrentIsNode);
+const projNodeOff = (nodeUrl: string, parentUrl: string, inPath: boolean, isAlias = false) =>
+ nodeOff(nodeUrl, parentUrl, inPath, _projCurrentParentUrl, activeProjectCurrentIsNode, isAlias);
// ── Blog URL classification ────────────────────────────────────────────────────
const mainSections = [
<ul class={`s${rootInPath ? ' active' : ''}`}>
{root.children.map(child => {
const childInPath = inSubtree(child, currentUrl);
- const childOff = projNodeOff(child.url, root.url, childInPath);
+ const childOff = projNodeOff(child.url, root.url, childInPath, child.isAlias);
const childIsNode = child.isNode;
return (
- <li class={`s${childIsNode ? ' sub' : ''}${childOff ? ' off' : ''}`}>
+ <li class={`s${childIsNode ? ' sub' : ''}${child.isAlias ? ' alias' : ''}${childOff ? ' off' : ''}`}>
{child.url === currentUrl
? <strong class="s">{child.title}</strong>
: <a href={child.url} class={childInPath ? 's selected' : 's'}>
<ul class={`s${childInPath ? ' active' : ''}`}>
{child.children.map(grand => {
const grandInPath = inSubtree(grand, currentUrl);
- const grandOff = projNodeOff(grand.url, child.url, grandInPath);
+ const grandOff = projNodeOff(grand.url, child.url, grandInPath, grand.isAlias);
const grandIsNode = grand.isNode;
return (
- <li class={`s${grandIsNode ? ' sub' : ''}${grandOff ? ' off' : ''}`}>
+ <li class={`s${grandIsNode ? ' sub' : ''}${grand.isAlias ? ' alias' : ''}${grandOff ? ' off' : ''}`}>
{grand.url === currentUrl
? <strong class="s">{grand.title}</strong>
: <a href={grand.url} class={grandInPath ? 's selected' : 's'}>
<ul class={`s${grandInPath ? ' active' : ''}`}>
{grand.children.map(ggrand => {
const ggInPath = ggrand.url === currentUrl;
- const ggOff = projNodeOff(ggrand.url, grand.url, ggInPath);
+ const ggOff = projNodeOff(ggrand.url, grand.url, ggInPath, ggrand.isAlias);
return (
- <li class={`s${ggOff ? ' off' : ''}`}>
+ <li class={`s${ggrand.isAlias ? ' alias' : ''}${ggOff ? ' off' : ''}`}>
{ggInPath
? <strong class="s">{ggrand.title}</strong>
: <a href={ggrand.url} class="s">{ggrand.title}</a>