mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-02 19:57:25 +02:00
fix(theme-classic): fix breadcrumb home link bug with new useHomePageRoute() hook (#6749)
This commit is contained in:
parent
0d14470d54
commit
ece7399d2e
6 changed files with 123 additions and 4 deletions
|
@ -37,7 +37,7 @@ declare module '@generated/registry' {
|
||||||
declare module '@generated/routes' {
|
declare module '@generated/routes' {
|
||||||
import type {RouteConfig} from 'react-router-config';
|
import type {RouteConfig} from 'react-router-config';
|
||||||
|
|
||||||
type Route = {
|
export type Route = {
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
readonly component: RouteConfig['component'];
|
readonly component: RouteConfig['component'];
|
||||||
readonly exact?: boolean;
|
readonly exact?: boolean;
|
||||||
|
|
|
@ -6,7 +6,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {type ReactNode} from 'react';
|
import React, {type ReactNode} from 'react';
|
||||||
import {ThemeClassNames, useSidebarBreadcrumbs} from '@docusaurus/theme-common';
|
import {
|
||||||
|
ThemeClassNames,
|
||||||
|
useSidebarBreadcrumbs,
|
||||||
|
useHomePageRoute,
|
||||||
|
} from '@docusaurus/theme-common';
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
|
@ -59,6 +63,7 @@ function HomeBreadcrumbItem() {
|
||||||
|
|
||||||
export default function DocBreadcrumbs(): JSX.Element | null {
|
export default function DocBreadcrumbs(): JSX.Element | null {
|
||||||
const breadcrumbs = useSidebarBreadcrumbs();
|
const breadcrumbs = useSidebarBreadcrumbs();
|
||||||
|
const homePageRoute = useHomePageRoute();
|
||||||
|
|
||||||
if (!breadcrumbs) {
|
if (!breadcrumbs) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -72,7 +77,7 @@ export default function DocBreadcrumbs(): JSX.Element | null {
|
||||||
)}
|
)}
|
||||||
aria-label="breadcrumbs">
|
aria-label="breadcrumbs">
|
||||||
<ul className="breadcrumbs">
|
<ul className="breadcrumbs">
|
||||||
<HomeBreadcrumbItem />
|
{homePageRoute && <HomeBreadcrumbItem />}
|
||||||
{breadcrumbs.map((item, idx) => (
|
{breadcrumbs.map((item, idx) => (
|
||||||
<BreadcrumbsItem key={idx} active={idx === breadcrumbs.length - 1}>
|
<BreadcrumbsItem key={idx} active={idx === breadcrumbs.length - 1}>
|
||||||
<BreadcrumbsItemLink href={item.href}>
|
<BreadcrumbsItemLink href={item.href}>
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@docusaurus/module-type-aliases": "2.0.0-beta.15",
|
||||||
"@docusaurus/plugin-content-blog": "2.0.0-beta.15",
|
"@docusaurus/plugin-content-blog": "2.0.0-beta.15",
|
||||||
"@docusaurus/plugin-content-docs": "2.0.0-beta.15",
|
"@docusaurus/plugin-content-docs": "2.0.0-beta.15",
|
||||||
"@docusaurus/plugin-content-pages": "2.0.0-beta.15",
|
"@docusaurus/plugin-content-pages": "2.0.0-beta.15",
|
||||||
|
@ -29,7 +30,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@docusaurus/core": "2.0.0-beta.15",
|
"@docusaurus/core": "2.0.0-beta.15",
|
||||||
"@docusaurus/module-type-aliases": "2.0.0-beta.15",
|
|
||||||
"@docusaurus/types": "2.0.0-beta.15",
|
"@docusaurus/types": "2.0.0-beta.15",
|
||||||
"@testing-library/react-hooks": "^7.0.2",
|
"@testing-library/react-hooks": "^7.0.2",
|
||||||
"fs-extra": "^10.0.0",
|
"fs-extra": "^10.0.0",
|
||||||
|
|
|
@ -124,6 +124,8 @@ export {
|
||||||
|
|
||||||
export {isRegexpStringMatch} from './utils/regexpUtils';
|
export {isRegexpStringMatch} from './utils/regexpUtils';
|
||||||
|
|
||||||
|
export {useHomePageRoute} from './utils/routesUtils';
|
||||||
|
|
||||||
export {useColorMode, ColorModeProvider} from './utils/colorModeUtils';
|
export {useColorMode, ColorModeProvider} from './utils/colorModeUtils';
|
||||||
export {
|
export {
|
||||||
useTabGroupChoice,
|
useTabGroupChoice,
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {type Route} from '@generated/routes';
|
||||||
|
import {findHomePageRoute} from '../routesUtils';
|
||||||
|
|
||||||
|
describe('routesUtils findHomePageRoute', () => {
|
||||||
|
const homePage: Route = {
|
||||||
|
path: '/',
|
||||||
|
exact: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
test('should return undefined for no routes', () => {
|
||||||
|
expect(findHomePageRoute([])).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return undefined for no homepage', () => {
|
||||||
|
expect(
|
||||||
|
findHomePageRoute([
|
||||||
|
{path: '/a', exact: true},
|
||||||
|
{path: '/b', exact: false},
|
||||||
|
{path: '/c', exact: undefined},
|
||||||
|
{
|
||||||
|
path: '/d',
|
||||||
|
exact: false,
|
||||||
|
routes: [
|
||||||
|
{path: '/d/1', exact: true},
|
||||||
|
{path: '/d/2', exact: false},
|
||||||
|
{path: '/d/3', exact: undefined},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should find top-level homepage', () => {
|
||||||
|
expect(
|
||||||
|
findHomePageRoute([
|
||||||
|
{path: '/a', exact: true},
|
||||||
|
{path: '/b', exact: false},
|
||||||
|
{path: '/c', exact: undefined},
|
||||||
|
{...homePage, exact: false},
|
||||||
|
homePage,
|
||||||
|
{...homePage, exact: undefined},
|
||||||
|
]),
|
||||||
|
).toEqual(homePage);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should find nested homepage', () => {
|
||||||
|
expect(
|
||||||
|
findHomePageRoute([
|
||||||
|
{path: '/a', exact: true},
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
exact: false,
|
||||||
|
routes: [
|
||||||
|
{path: '/b', exact: true},
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
exact: false,
|
||||||
|
routes: [{path: '/c', exact: true}, homePage],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{path: '/d', exact: true},
|
||||||
|
]),
|
||||||
|
).toEqual(homePage);
|
||||||
|
});
|
||||||
|
});
|
39
packages/docusaurus-theme-common/src/utils/routesUtils.ts
Normal file
39
packages/docusaurus-theme-common/src/utils/routesUtils.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import GeneratedRoutes, {type Route} from '@generated/routes';
|
||||||
|
import {useMemo} from 'react';
|
||||||
|
|
||||||
|
function isHomePageRoute(route: Route): boolean {
|
||||||
|
return route.path === '/' && route.exact === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isHomeParentRoute(route: Route): boolean {
|
||||||
|
return route.path === '/' && route.exact === false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that all sites don't always have a homepage in practice
|
||||||
|
// See https://github.com/facebook/docusaurus/pull/6517#issuecomment-1048709116
|
||||||
|
export function findHomePageRoute(
|
||||||
|
routes: Route[] = GeneratedRoutes,
|
||||||
|
): Route | undefined {
|
||||||
|
if (routes.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const homePage = routes.find(isHomePageRoute);
|
||||||
|
if (homePage) {
|
||||||
|
return homePage;
|
||||||
|
}
|
||||||
|
const indexSubRoutes = routes
|
||||||
|
.filter(isHomeParentRoute)
|
||||||
|
.flatMap((route) => route.routes ?? []);
|
||||||
|
return findHomePageRoute(indexSubRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useHomePageRoute(): Route | undefined {
|
||||||
|
return useMemo(() => findHomePageRoute(), []);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue