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

Changed files
+38 -10
components
Common
Breadcrumbs
util
+1 -1
components/Common/Breadcrumbs/index.tsx
··· 8 8 import BreadcrumbTruncatedItem from '@/components/Common/Breadcrumbs/BreadcrumbTruncatedItem'; 9 9 import type { FormattedMessage } from '@/types'; 10 10 11 - type BreadcrumbLink = { 11 + export type BreadcrumbLink = { 12 12 label: FormattedMessage; 13 13 href: string | undefined; 14 14 };
+32 -9
components/withBreadcrumbs.tsx
··· 2 2 3 3 import type { FC } from 'react'; 4 4 5 + import type { BreadcrumbLink } from '@/components/Common/Breadcrumbs'; 5 6 import Breadcrumbs from '@/components/Common/Breadcrumbs'; 6 7 import { useClientContext, useMediaQuery, useSiteNavigation } from '@/hooks'; 7 8 import type { NavigationKeys } from '@/types'; 9 + import { dashToCamelCase } from '@/util/stringUtils'; 8 10 9 11 const WithBreadcrumbs: FC = () => { 10 12 const { navigationItems, getSideNavigation } = useSiteNavigation(); 11 13 const { pathname } = useClientContext(); 12 - 13 14 const isMobileScreen = useMediaQuery('(max-width: 639px)'); 14 15 16 + const maxLength = isMobileScreen ? 2 : 4; 17 + 15 18 const getBreadrumbs = () => { 16 19 const [navigationKey] = 17 20 navigationItems.find(([, item]) => pathname.includes(item.link)) || []; ··· 20 23 return []; 21 24 } 22 25 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 })); 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>); 28 53 }; 29 54 30 - return ( 31 - <Breadcrumbs links={getBreadrumbs()} maxLength={isMobileScreen ? 2 : 4} /> 32 - ); 55 + return <Breadcrumbs links={getBreadrumbs()} maxLength={maxLength} />; 33 56 }; 34 57 35 58 export default WithBreadcrumbs;
+5
util/stringUtils.ts
··· 21 21 .replace(/^[ ]+|[ ]+$/gm, '') 22 22 // replaces leading numbers and dots from each line with an empty string 23 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());