Don't link page group breadcrumbs to their redirecting URL (#4686)

This commit is contained in:
Peter White
2026-10-14 12:31:26 +02:00
committed by GitHub
parent 0b515b0970
commit 0540ebc1b9
4 changed files with 26 additions and 9 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Stop page group breadcrumbs from linking to a URL that redirects to the group's first page.
@@ -222,9 +222,14 @@ export async function PageHeader(props: {
))}
{ancestors.map((breadcrumb, index) => {
const parentPages = ancestors[index - 1]?.pages ?? revision.pages;
// A group's own URL redirects to its first document, so link straight to it.
const target =
breadcrumb.type === 'group'
? (resolveFirstDocument([breadcrumb], [])?.page ?? breadcrumb)
: breadcrumb;
const href = linker.toPathForPage({
pages: revision.pages,
page: breadcrumb,
page: target,
});
return (
<li key={breadcrumb.id} className="inline">
@@ -483,15 +488,16 @@ function getPageSiblings(
if (page.hidden && page.id !== activeId) {
continue;
}
// A group whose subtree has no document resolves to no page — the sidebar renders it as a
// non-clickable label, so don't offer it as a navigable sibling (its path would 404).
if (page.type === 'group' && page.id !== activeId && !resolveFirstDocument([page], [])) {
// A group's own URL redirects to its first document, so link straight to it. A group whose
// subtree has no document resolves to no page, so don't offer it (its path would 404).
const target = page.type === 'group' ? resolveFirstDocument([page], [])?.page : page;
if (!target) {
continue;
}
result.push({
id: page.id,
title: page.linkTitle || page.title,
href: context.linker.toPathForPage({ pages: context.revision.pages, page }),
href: context.linker.toPathForPage({ pages: context.revision.pages, page: target }),
emoji: page.emoji,
icon: page.icon,
isActive: page.id === activeId,
+1 -2
View File
@@ -627,12 +627,11 @@ describe('resolveContentRef for direct space links', () => {
{ label: 'API guides' },
{ label: 'Authentification' },
{ label: 'Référence', href: targetSiteSpace.urls.published },
{ label: 'Getting started', icon: null, href: expect.any(String) },
{ label: 'Getting started', icon: null, href: result?.href },
]);
expect(result?.ancestors?.[0]?.href).toBeUndefined();
expect(result?.ancestors?.[1]?.href).toBeUndefined();
expect(result?.ancestors?.[2]?.href).toBeUndefined();
expect(result?.ancestors?.[4]?.href).toBeTruthy();
});
it('uses the first document as the target for a page-group reference', async () => {
+9 -2
View File
@@ -23,7 +23,7 @@ import {
findGitPageURLTarget,
findPageForGitPageURLTarget,
} from './gitPageURL';
import { resolvePageId } from './pages';
import { resolveFirstDocument, resolvePageId } from './pages';
import {
findSiteSpaceBy,
getFallbackSiteSpacePath,
@@ -276,7 +276,14 @@ export async function resolveContentRef(
style={iconStyle}
/>
) : null,
href: linker.toPathForPage({ page: ancestor, pages: revision.pages }),
// A group's own URL redirects to its first document, so link straight to it.
href: linker.toPathForPage({
page:
ancestor.type === 'group'
? (resolveFirstDocument([ancestor], [])?.page ?? ancestor)
: ancestor,
pages: revision.pages,
}),
})) ?? [];
if (!page) {
return null;