mirror of
https://github.com/facebook/docusaurus.git
synced 2025-12-25 17:22:50 +00:00
fix(docs): breadcrumb APIs only return category/docs items, ignoring links (#11616)
Some checks failed
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Canary Release / Publish Canary (push) Has been cancelled
Some checks failed
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (24) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (25.1) (push) Waiting to run
E2E Tests / E2E — Yarn v1 Windows (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Canary Release / Publish Canary (push) Has been cancelled
Co-authored-by: sebastien <lorber.sebastien@gmail.com>
This commit is contained in:
parent
47a98a1d6e
commit
7f5d6122d2
|
|
@ -568,13 +568,28 @@ describe('useSidebarBreadcrumbs', () => {
|
||||||
|
|
||||||
it('returns first level link', () => {
|
it('returns first level link', () => {
|
||||||
const pathname = '/somePathName';
|
const pathname = '/somePathName';
|
||||||
const sidebar = [testCategory(), testLink({href: pathname})];
|
const sidebar = [testCategory(), testLink({href: pathname, docId: 'doc1'})];
|
||||||
|
|
||||||
expect(createUseSidebarBreadcrumbsMock(sidebar)(pathname)).toEqual([
|
expect(createUseSidebarBreadcrumbsMock(sidebar)(pathname)).toEqual([
|
||||||
sidebar[1],
|
sidebar[1],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns doc links only', () => {
|
||||||
|
const pathname = '/somePathName';
|
||||||
|
|
||||||
|
// A link that is not a doc link should not appear in the breadcrumbs
|
||||||
|
// See https://github.com/facebook/docusaurus/pull/11616
|
||||||
|
const nonDocLink = testLink({href: pathname});
|
||||||
|
const docLink = testLink({href: pathname, docId: 'doc1'});
|
||||||
|
|
||||||
|
const sidebar = [testCategory(), nonDocLink, docLink];
|
||||||
|
|
||||||
|
expect(createUseSidebarBreadcrumbsMock(sidebar)(pathname)).toEqual([
|
||||||
|
docLink,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it('returns nested category', () => {
|
it('returns nested category', () => {
|
||||||
const pathname = '/somePathName';
|
const pathname = '/somePathName';
|
||||||
|
|
||||||
|
|
@ -613,7 +628,7 @@ describe('useSidebarBreadcrumbs', () => {
|
||||||
it('returns nested link', () => {
|
it('returns nested link', () => {
|
||||||
const pathname = '/somePathName';
|
const pathname = '/somePathName';
|
||||||
|
|
||||||
const link = testLink({href: pathname});
|
const link = testLink({href: pathname, docId: 'docNested'});
|
||||||
|
|
||||||
const categoryLevel3 = testCategory({
|
const categoryLevel3 = testCategory({
|
||||||
items: [testLink(), link, testLink()],
|
items: [testLink(), link, testLink()],
|
||||||
|
|
@ -657,6 +672,35 @@ describe('useSidebarBreadcrumbs', () => {
|
||||||
createUseSidebarBreadcrumbsMock(undefined, false)('/foo'),
|
createUseSidebarBreadcrumbsMock(undefined, false)('/foo'),
|
||||||
).toBeNull();
|
).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/facebook/docusaurus/issues/11612
|
||||||
|
it('returns the category that owns the URL, not a category with a link pointing to it', () => {
|
||||||
|
const categoryA: PropSidebarItemCategory = testCategory({
|
||||||
|
label: 'Category A',
|
||||||
|
href: '/category-a',
|
||||||
|
items: [
|
||||||
|
testLink({href: '/category-a/doc1', label: 'Doc 1'}),
|
||||||
|
testLink({href: '/category-a/doc2', label: 'Doc 2'}),
|
||||||
|
// This link points to Category B's generated-index
|
||||||
|
testLink({href: '/category-b', label: 'Go to Category B'}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const categoryB: PropSidebarItemCategory = testCategory({
|
||||||
|
label: 'Category B',
|
||||||
|
href: '/category-b',
|
||||||
|
items: [
|
||||||
|
testLink({href: '/category-b/item1', label: 'Item 1'}),
|
||||||
|
testLink({href: '/category-b/item2', label: 'Item 2'}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const sidebar: PropSidebar = [categoryA, categoryB];
|
||||||
|
|
||||||
|
expect(createUseSidebarBreadcrumbsMock(sidebar)('/category-b')).toEqual([
|
||||||
|
categoryB,
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('useCurrentSidebarCategory', () => {
|
describe('useCurrentSidebarCategory', () => {
|
||||||
|
|
@ -708,12 +752,16 @@ describe('useCurrentSidebarCategory', () => {
|
||||||
expect(mockUseCurrentSidebarCategory('/cat2')).toEqual(category2);
|
expect(mockUseCurrentSidebarCategory('/cat2')).toEqual(category2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works for category link item', () => {
|
it('works for category doc link item', () => {
|
||||||
const link = testLink({href: '/my/link/path'});
|
const pathname = '/my/link/path';
|
||||||
|
const nonDocLink = testLink({href: pathname});
|
||||||
|
const docLink = testLink({href: pathname, docId: 'doc1'});
|
||||||
|
|
||||||
const category: PropSidebarItemCategory = testCategory({
|
const category: PropSidebarItemCategory = testCategory({
|
||||||
href: '/cat1',
|
href: '/cat1',
|
||||||
items: [testLink(), testLink(), link, testCategory()],
|
items: [testLink(), testLink(), nonDocLink, docLink, testCategory()],
|
||||||
});
|
});
|
||||||
|
|
||||||
const sidebar: PropSidebar = [
|
const sidebar: PropSidebar = [
|
||||||
testLink(),
|
testLink(),
|
||||||
testLink(),
|
testLink(),
|
||||||
|
|
@ -724,18 +772,28 @@ describe('useCurrentSidebarCategory', () => {
|
||||||
const mockUseCurrentSidebarCategory =
|
const mockUseCurrentSidebarCategory =
|
||||||
createUseCurrentSidebarCategoryMock(sidebar);
|
createUseCurrentSidebarCategoryMock(sidebar);
|
||||||
|
|
||||||
expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(category);
|
expect(mockUseCurrentSidebarCategory(pathname)).toEqual(category);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works for nested category link item', () => {
|
it('works for nested category link item', () => {
|
||||||
const link = testLink({href: '/my/link/path'});
|
const pathname = '/my/link/path';
|
||||||
|
const nonDocLink = testLink({href: pathname});
|
||||||
|
const docLink = testLink({href: pathname, docId: 'doc1'});
|
||||||
|
|
||||||
const category2: PropSidebarItemCategory = testCategory({
|
const category2: PropSidebarItemCategory = testCategory({
|
||||||
href: '/cat2',
|
href: '/cat2',
|
||||||
items: [testLink(), testLink(), link, testCategory()],
|
items: [
|
||||||
|
testLink(),
|
||||||
|
testLink(),
|
||||||
|
testCategory({items: [nonDocLink]}),
|
||||||
|
nonDocLink,
|
||||||
|
docLink,
|
||||||
|
testCategory(),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
const category1: PropSidebarItemCategory = testCategory({
|
const category1: PropSidebarItemCategory = testCategory({
|
||||||
href: '/cat1',
|
href: '/cat1',
|
||||||
items: [testLink(), testLink(), category2, testCategory()],
|
items: [testLink(), nonDocLink, testLink(), category2, testCategory()],
|
||||||
});
|
});
|
||||||
const sidebar: PropSidebar = [
|
const sidebar: PropSidebar = [
|
||||||
testLink(),
|
testLink(),
|
||||||
|
|
@ -780,6 +838,38 @@ describe('useCurrentSidebarCategory', () => {
|
||||||
`"Unexpected: cant find current sidebar in context"`,
|
`"Unexpected: cant find current sidebar in context"`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/facebook/docusaurus/issues/11612
|
||||||
|
it('returns the category that owns the URL, not a category with a link pointing to it', () => {
|
||||||
|
const categoryA: PropSidebarItemCategory = testCategory({
|
||||||
|
label: 'Category A',
|
||||||
|
href: '/category-a',
|
||||||
|
items: [
|
||||||
|
testLink({href: '/category-a/doc1', label: 'Doc 1'}),
|
||||||
|
testLink({href: '/category-a/doc2', label: 'Doc 2'}),
|
||||||
|
// This link points to Category B's generated-index
|
||||||
|
testLink({href: '/category-b', label: 'Go to Category B'}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const categoryB: PropSidebarItemCategory = testCategory({
|
||||||
|
label: 'Category B',
|
||||||
|
href: '/category-b',
|
||||||
|
items: [
|
||||||
|
testLink({href: '/category-b/item1', label: 'Item 1'}),
|
||||||
|
testLink({href: '/category-b/item2', label: 'Item 2'}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const sidebar: PropSidebar = [categoryA, categoryB];
|
||||||
|
|
||||||
|
const mockUseCurrentSidebarCategory =
|
||||||
|
createUseCurrentSidebarCategoryMock(sidebar);
|
||||||
|
|
||||||
|
// When visiting /category-b, we should get Category B (the owner),
|
||||||
|
// not Category A (which just has a link to it)
|
||||||
|
expect(mockUseCurrentSidebarCategory('/category-b')).toEqual(categoryB);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('useCurrentSidebarSiblings', () => {
|
describe('useCurrentSidebarSiblings', () => {
|
||||||
|
|
@ -805,10 +895,10 @@ describe('useCurrentSidebarSiblings', () => {
|
||||||
testCategory(),
|
testCategory(),
|
||||||
];
|
];
|
||||||
|
|
||||||
const mockUseCurrentSidebarCategory =
|
const mockUseCurrentSidebarSiblings =
|
||||||
createUseCurrentSidebarSiblingsMock(sidebar);
|
createUseCurrentSidebarSiblingsMock(sidebar);
|
||||||
|
|
||||||
expect(mockUseCurrentSidebarCategory('/cat')).toEqual(category.items);
|
expect(mockUseCurrentSidebarSiblings('/cat')).toEqual(category.items);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works for sidebar root', () => {
|
it('works for sidebar root', () => {
|
||||||
|
|
@ -823,10 +913,10 @@ describe('useCurrentSidebarSiblings', () => {
|
||||||
testCategory(),
|
testCategory(),
|
||||||
];
|
];
|
||||||
|
|
||||||
const mockUseCurrentSidebarCategory =
|
const mockUseCurrentSidebarSiblings =
|
||||||
createUseCurrentSidebarSiblingsMock(sidebar);
|
createUseCurrentSidebarSiblingsMock(sidebar);
|
||||||
|
|
||||||
expect(mockUseCurrentSidebarCategory('/rootLink')).toEqual(sidebar);
|
expect(mockUseCurrentSidebarSiblings('/rootLink')).toEqual(sidebar);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works for nested sidebar category', () => {
|
it('works for nested sidebar category', () => {
|
||||||
|
|
@ -852,10 +942,13 @@ describe('useCurrentSidebarSiblings', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works for category link item', () => {
|
it('works for category link item', () => {
|
||||||
const link = testLink({href: '/my/link/path'});
|
const pathname = '/my/link/path';
|
||||||
|
const nonDocLink = testLink({href: pathname});
|
||||||
|
const docLink = testLink({href: pathname, docId: 'doc1'});
|
||||||
|
|
||||||
const category: PropSidebarItemCategory = testCategory({
|
const category: PropSidebarItemCategory = testCategory({
|
||||||
href: '/cat1',
|
href: '/cat1',
|
||||||
items: [testLink(), testLink(), link, testCategory()],
|
items: [testLink(), testLink(), nonDocLink, docLink, testCategory()],
|
||||||
});
|
});
|
||||||
const sidebar: PropSidebar = [
|
const sidebar: PropSidebar = [
|
||||||
testLink(),
|
testLink(),
|
||||||
|
|
@ -864,23 +957,24 @@ describe('useCurrentSidebarSiblings', () => {
|
||||||
testCategory(),
|
testCategory(),
|
||||||
];
|
];
|
||||||
|
|
||||||
const mockUseCurrentSidebarCategory =
|
const mockUseCurrentSidebarSiblings =
|
||||||
createUseCurrentSidebarSiblingsMock(sidebar);
|
createUseCurrentSidebarSiblingsMock(sidebar);
|
||||||
|
|
||||||
expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(
|
expect(mockUseCurrentSidebarSiblings(pathname)).toEqual(category.items);
|
||||||
category.items,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('works for nested category link item', () => {
|
it('works for nested category link item', () => {
|
||||||
const link = testLink({href: '/my/link/path'});
|
const pathname = '/my/link/path';
|
||||||
|
const nonDocLink = testLink({href: pathname});
|
||||||
|
const docLink = testLink({href: pathname, docId: 'doc1'});
|
||||||
|
|
||||||
const category2: PropSidebarItemCategory = testCategory({
|
const category2: PropSidebarItemCategory = testCategory({
|
||||||
href: '/cat2',
|
href: '/cat2',
|
||||||
items: [testLink(), testLink(), link, testCategory()],
|
items: [testLink(), testLink(), nonDocLink, testCategory()],
|
||||||
});
|
});
|
||||||
const category1: PropSidebarItemCategory = testCategory({
|
const category1: PropSidebarItemCategory = testCategory({
|
||||||
href: '/cat1',
|
href: '/cat1',
|
||||||
items: [testLink(), testLink(), category2, testCategory()],
|
items: [testLink(), testLink(), category2, docLink, testCategory()],
|
||||||
});
|
});
|
||||||
const sidebar: PropSidebar = [
|
const sidebar: PropSidebar = [
|
||||||
testLink(),
|
testLink(),
|
||||||
|
|
@ -889,18 +983,16 @@ describe('useCurrentSidebarSiblings', () => {
|
||||||
testCategory(),
|
testCategory(),
|
||||||
];
|
];
|
||||||
|
|
||||||
const mockUseCurrentSidebarCategory =
|
const mockUseCurrentSidebarSiblings =
|
||||||
createUseCurrentSidebarSiblingsMock(sidebar);
|
createUseCurrentSidebarSiblingsMock(sidebar);
|
||||||
|
|
||||||
expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(
|
expect(mockUseCurrentSidebarSiblings(pathname)).toEqual(category1.items);
|
||||||
category2.items,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws when sidebar is missing', () => {
|
it('throws when sidebar is missing', () => {
|
||||||
const mockUseCurrentSidebarCategory = createUseCurrentSidebarSiblingsMock();
|
const mockUseCurrentSidebarSiblings = createUseCurrentSidebarSiblingsMock();
|
||||||
expect(() =>
|
expect(() =>
|
||||||
mockUseCurrentSidebarCategory('/cat'),
|
mockUseCurrentSidebarSiblings('/cat'),
|
||||||
).toThrowErrorMatchingInlineSnapshot(
|
).toThrowErrorMatchingInlineSnapshot(
|
||||||
`"Unexpected: cant find current sidebar in context"`,
|
`"Unexpected: cant find current sidebar in context"`,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -234,15 +234,22 @@ function getSidebarBreadcrumbs({
|
||||||
}): PropSidebarBreadcrumbsItem[] {
|
}): PropSidebarBreadcrumbsItem[] {
|
||||||
const breadcrumbs: PropSidebarBreadcrumbsItem[] = [];
|
const breadcrumbs: PropSidebarBreadcrumbsItem[] = [];
|
||||||
|
|
||||||
function extract(items: PropSidebarItem[]) {
|
function extract(items: PropSidebarItem[]): boolean {
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (
|
// Extract category item
|
||||||
(item.type === 'category' &&
|
if (item.type === 'category') {
|
||||||
(isSamePath(item.href, pathname) || extract(item.items))) ||
|
if (isSamePath(item.href, pathname) || extract(item.items)) {
|
||||||
(item.type === 'link' && isSamePath(item.href, pathname))
|
breadcrumbs.unshift(item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Extract doc item
|
||||||
|
else if (
|
||||||
|
item.type === 'link' &&
|
||||||
|
item.docId &&
|
||||||
|
isSamePath(item.href, pathname)
|
||||||
) {
|
) {
|
||||||
const filtered = onlyCategories && item.type !== 'category';
|
if (!onlyCategories) {
|
||||||
if (!filtered) {
|
|
||||||
breadcrumbs.unshift(item);
|
breadcrumbs.unshift(item);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue