Skip to content

Commit

Permalink
fix(theme-classic): fix breadcrumb home link bug with new useHomePage…
Browse files Browse the repository at this point in the history
…Route() hook (#6749)
  • Loading branch information
slorber authored Feb 24, 2022
1 parent 0d14470 commit ece7399
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 4 deletions.
2 changes: 1 addition & 1 deletion packages/docusaurus-module-type-aliases/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ declare module '@generated/registry' {
declare module '@generated/routes' {
import type {RouteConfig} from 'react-router-config';

type Route = {
export type Route = {
readonly path: string;
readonly component: RouteConfig['component'];
readonly exact?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
*/

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 clsx from 'clsx';
import Link from '@docusaurus/Link';
Expand Down Expand Up @@ -59,6 +63,7 @@ function HomeBreadcrumbItem() {

export default function DocBreadcrumbs(): JSX.Element | null {
const breadcrumbs = useSidebarBreadcrumbs();
const homePageRoute = useHomePageRoute();

if (!breadcrumbs) {
return null;
Expand All @@ -72,7 +77,7 @@ export default function DocBreadcrumbs(): JSX.Element | null {
)}
aria-label="breadcrumbs">
<ul className="breadcrumbs">
<HomeBreadcrumbItem />
{homePageRoute && <HomeBreadcrumbItem />}
{breadcrumbs.map((item, idx) => (
<BreadcrumbsItem key={idx} active={idx === breadcrumbs.length - 1}>
<BreadcrumbsItemLink href={item.href}>
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus-theme-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
"license": "MIT",
"dependencies": {
"@docusaurus/module-type-aliases": "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-pages": "2.0.0-beta.15",
Expand All @@ -29,7 +30,6 @@
},
"devDependencies": {
"@docusaurus/core": "2.0.0-beta.15",
"@docusaurus/module-type-aliases": "2.0.0-beta.15",
"@docusaurus/types": "2.0.0-beta.15",
"@testing-library/react-hooks": "^7.0.2",
"fs-extra": "^10.0.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/docusaurus-theme-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ export {

export {isRegexpStringMatch} from './utils/regexpUtils';

export {useHomePageRoute} from './utils/routesUtils';

export {useColorMode, ColorModeProvider} from './utils/colorModeUtils';
export {
useTabGroupChoice,
Expand Down
Original file line number Diff line number Diff line change
@@ -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 changes: 39 additions & 0 deletions packages/docusaurus-theme-common/src/utils/routesUtils.ts
Original file line number Diff line number Diff line change
@@ -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(), []);
}

0 comments on commit ece7399

Please sign in to comment.