diff --git a/src/client/theme-api/useNavData.ts b/src/client/theme-api/useNavData.ts index 0ff36339da..924fd3588f 100644 --- a/src/client/theme-api/useNavData.ts +++ b/src/client/theme-api/useNavData.ts @@ -6,7 +6,7 @@ import type { IUserNavItems, IUserNavMode, } from './types'; -import { getLocaleClearPath } from './useSidebarData'; +import { getLocaleClearPath, getRouteParentPath } from './useSidebarData'; import { getLocaleNav, pickRouteSortMeta, @@ -65,11 +65,11 @@ export const useNavData = () => { .sort(([a], [b]) => a.split('/').length - b.split('/').length) // convert sidebar data to nav data .reduce>((ret, [link, groups]) => { - const [, parentPath, restPath] = `/${getLocaleClearPath( - link.replace(/^\//, ''), - locale, - )}`.match(/^(\/[^/]+)([^]+)?$/)!; - const isNestedNav = Boolean(restPath) && is2LevelNav; + const clearPath = getLocaleClearPath(link.replace(/^\//, ''), locale); + const parentPath = link.replace(clearPath, (s) => + getRouteParentPath(s, { is2LevelNav, locale }), + ); + const isNestedNav = link.length > parentPath.length && is2LevelNav; const [firstMeta, secondMeta] = Object.values(routes).reduce< { title?: string; @@ -96,7 +96,8 @@ export const useNavData = () => { if (isNestedNav) { // fallback to use parent path as 1-level nav title firstMeta.title ??= parentPath - .slice(1) + .split('/') + .pop()! .replace(/^[a-z]/, (s) => s.toUpperCase()); // handle nested nav item as parent children @@ -107,7 +108,7 @@ export const useNavData = () => { )); second.children ??= []; - ret[parentPath].children!.push( + second.children!.push( genNavItem(secondMeta, groups, link, groups[0].children[0].link), ); } else { diff --git a/src/client/theme-api/useSidebarData.ts b/src/client/theme-api/useSidebarData.ts index 31e42db939..3e7d0e18d0 100644 --- a/src/client/theme-api/useSidebarData.ts +++ b/src/client/theme-api/useSidebarData.ts @@ -27,12 +27,18 @@ export const getLocaleClearPath = ( /** * get parent path from route path */ -function getRouteParentPath( +export function getRouteParentPath( path: string, - { meta, is2LevelNav }: { meta: IRouteMeta; is2LevelNav: boolean }, + { + meta, + is2LevelNav, + locale, + }: { meta?: IRouteMeta; is2LevelNav: boolean; locale: ILocalesConfig[0] }, ) { + const indexDocRegex = new RegExp(`/index(\\.${locale.id})?.md$`); const isIndexDocRoute = - meta.frontmatter.filename?.endsWith('index.md') && + meta?.frontmatter.filename && + indexDocRegex.test(meta.frontmatter.filename) && !meta._atom_route && is2LevelNav; const paths = path @@ -82,7 +88,7 @@ export const useFullSidebarData = () => { // a/b => /a/b (if route file is a/b/index.md) // a/b/c => /a/b const parentPath = `/${route.path!.replace(clearPath, (s) => - getRouteParentPath(s, { is2LevelNav, meta: route.meta! }), + getRouteParentPath(s, { is2LevelNav, meta: route.meta!, locale }), )}`; const { title, order } = pickRouteSortMeta( { order: 0 }, @@ -224,7 +230,7 @@ export const useSidebarData = () => { // /en-US/a/b/ => /en-US/a (also strip trailing /) const parentPath = clearPath ? pathname.replace(clearPath, (s) => - getRouteParentPath(s, { is2LevelNav, meta }), + getRouteParentPath(s, { is2LevelNav, meta, locale }), ) : pathname;