The Node.js® Website

Fix breadcrumbs not updating (#6431)

Co-authored-by: Claudio Wunder <cwunder@gnome.org>

authored by yanggggjie Claudio Wunder and committed by GitHub 2df76dca 507fc927

+38 -10
+1 -1
components/Common/Breadcrumbs/index.tsx
··· 8 import BreadcrumbTruncatedItem from '@/components/Common/Breadcrumbs/BreadcrumbTruncatedItem'; 9 import type { FormattedMessage } from '@/types'; 10 11 - type BreadcrumbLink = { 12 label: FormattedMessage; 13 href: string | undefined; 14 };
··· 8 import BreadcrumbTruncatedItem from '@/components/Common/Breadcrumbs/BreadcrumbTruncatedItem'; 9 import type { FormattedMessage } from '@/types'; 10 11 + export type BreadcrumbLink = { 12 label: FormattedMessage; 13 href: string | undefined; 14 };
+32 -9
components/withBreadcrumbs.tsx
··· 2 3 import type { FC } from 'react'; 4 5 import Breadcrumbs from '@/components/Common/Breadcrumbs'; 6 import { useClientContext, useMediaQuery, useSiteNavigation } from '@/hooks'; 7 import type { NavigationKeys } from '@/types'; 8 9 const WithBreadcrumbs: FC = () => { 10 const { navigationItems, getSideNavigation } = useSiteNavigation(); 11 const { pathname } = useClientContext(); 12 - 13 const isMobileScreen = useMediaQuery('(max-width: 639px)'); 14 15 const getBreadrumbs = () => { 16 const [navigationKey] = 17 navigationItems.find(([, item]) => pathname.includes(item.link)) || []; ··· 20 return []; 21 } 22 23 - return getSideNavigation([navigationKey as NavigationKeys]) 24 - .map(([, item]) => item.items) 25 - .flat() 26 - .filter(([, item]) => pathname.includes(item.link)) 27 - .map(([, item]) => ({ label: item.label, href: item.link })); 28 }; 29 30 - return ( 31 - <Breadcrumbs links={getBreadrumbs()} maxLength={isMobileScreen ? 2 : 4} /> 32 - ); 33 }; 34 35 export default WithBreadcrumbs;
··· 2 3 import type { FC } from 'react'; 4 5 + import type { BreadcrumbLink } from '@/components/Common/Breadcrumbs'; 6 import Breadcrumbs from '@/components/Common/Breadcrumbs'; 7 import { useClientContext, useMediaQuery, useSiteNavigation } from '@/hooks'; 8 import type { NavigationKeys } from '@/types'; 9 + import { dashToCamelCase } from '@/util/stringUtils'; 10 11 const WithBreadcrumbs: FC = () => { 12 const { navigationItems, getSideNavigation } = useSiteNavigation(); 13 const { pathname } = useClientContext(); 14 const isMobileScreen = useMediaQuery('(max-width: 639px)'); 15 16 + const maxLength = isMobileScreen ? 2 : 4; 17 + 18 const getBreadrumbs = () => { 19 const [navigationKey] = 20 navigationItems.find(([, item]) => pathname.includes(item.link)) || []; ··· 23 return []; 24 } 25 26 + const navigationTree = getSideNavigation([navigationKey as NavigationKeys]); 27 + 28 + const pathList = pathname 29 + .split('/') 30 + .filter(item => item !== '') 31 + .map(dashToCamelCase); 32 + 33 + let currentNode = navigationTree; 34 + 35 + // Reduce the pathList to a breadcrumbs array by finding each path in the current navigation layer, 36 + // updating the currentNode to the found node's items(next layer) for the next iteration. 37 + return pathList.reduce((breadcrumbs, path) => { 38 + const nodeWithCurrentPath = currentNode.find( 39 + ([nodePath]) => nodePath === path 40 + ); 41 + 42 + if (nodeWithCurrentPath) { 43 + const [, { label, link = '', items = [] }] = nodeWithCurrentPath; 44 + 45 + // Goes deeper on the tree of items if there are any. 46 + currentNode = items; 47 + 48 + return label ? [...breadcrumbs, { label, href: link }] : breadcrumbs; 49 + } 50 + 51 + return breadcrumbs; 52 + }, [] as Array<BreadcrumbLink>); 53 }; 54 55 + return <Breadcrumbs links={getBreadrumbs()} maxLength={maxLength} />; 56 }; 57 58 export default WithBreadcrumbs;
+5
util/stringUtils.ts
··· 21 .replace(/^[ ]+|[ ]+$/gm, '') 22 // replaces leading numbers and dots from each line with an empty string 23 .replace(/^\d+\.\s/gm, '');
··· 21 .replace(/^[ ]+|[ ]+$/gm, '') 22 // replaces leading numbers and dots from each line with an empty string 23 .replace(/^\d+\.\s/gm, ''); 24 + 25 + export const dashToCamelCase = (str: string) => 26 + str 27 + .replace(/-([a-z])/g, (match, chr) => chr.toUpperCase()) 28 + .replace(/^[A-Z]/, chr => chr.toLowerCase());