import * as React from 'react' ; import { useRouter } from 'next/router' ; /**
 * While Next.js provides file-based routing, we still need to construct
 * a sidebar for navigation and provide each markdown page
 * previous/next links and titles. To do this, we construct a nested
 * route object that is infinitely nestable.
 */ export type RouteTag = 'foundation' | 'intermediate' | 'advanced' | 'experimental' | 'deprecated' ; export interface RouteItem { /** Page title (for the sidebar) */ title : string ; /** Optional page description for heading */ description ? : string ; tags ? : RouteTag [ ] ; /** Path to page */ path ? : string ; /** Whether the entry is a heading */ heading ? : boolean ; /** List of sub-routes */ routes ? : RouteItem [ ] ; } export interface Routes { /** List of routes */ routes : RouteItem [ ] ; } /** Routing metadata about a given route and it's siblings and parent */ export interface RouteMeta { /** The previous route */ prevRoute ? : RouteItem ; /** The next route */ nextRoute ? : RouteItem ; /** The current route */ route ? : RouteItem ; /** Trail of parent routes */ breadcrumbs ? : RouteItem [ ] ; } export function useRouteMeta ( rootRoute ? ) { const sidebarContext = React . useContext ( SidebarContext ) ; const routeTree = rootRoute || sidebarContext ; const router = useRouter ( ) ; const cleanedPath = router . pathname ; if ( cleanedPath === '/404' ) { return { breadcrumbs : [ ] , } ; } const breadcrumbs = getBreadcrumbs ( cleanedPath , routeTree ) ; return { ... getRouteMeta ( cleanedPath , routeTree ) , breadcrumbs : breadcrumbs . length > 0 ? breadcrumbs : [ routeTree ] , } ; } export const SidebarContext = React . createContext < RouteItem > ( { title : 'root' } ) ; function getRouteMeta ( searchPath , currentRoute , ctx = { } ) { const { routes } = currentRoute ; if ( ctx . route && ! ctx . nextRoute ) { ctx . nextRoute = currentRoute ; } if ( currentRoute . path === searchPath ) { ctx . route = currentRoute ; } if ( ! ctx . route ) { ctx . prevRoute = currentRoute ; } if ( ! routes ) { return ctx ; } for ( const route of routes ) { getRouteMeta ( searchPath , route , ctx ) ; } return ctx ; } function getBreadcrumbs ( path , currentRoute , breadcrumbs = [ ] ) { if ( currentRoute . path === path ) { return breadcrumbs ; } if ( ! currentRoute . routes ) { return [ ] ; } for ( const route of currentRoute . routes ) { const childRoute = getBreadcrumbs ( path , route , [ ... breadcrumbs , currentRoute , ] ) ; if ( childRoute ?. length ) { return childRoute ; } } return [ ] ; }