diff --git a/examples/unplugin-vue-router/src/pages/second.vue b/examples/unplugin-vue-router/src/pages/second.vue deleted file mode 100644 index b588dbd..0000000 --- a/examples/unplugin-vue-router/src/pages/second.vue +++ /dev/null @@ -1,10 +0,0 @@ - - -{ - meta: { - layout: false - } -} - diff --git a/examples/unplugin-vue-router/typed-router.d.ts b/examples/unplugin-vue-router/typed-router.d.ts index 9599dcb..d3f703e 100644 --- a/examples/unplugin-vue-router/typed-router.d.ts +++ b/examples/unplugin-vue-router/typed-router.d.ts @@ -51,7 +51,6 @@ declare module 'vue-router/auto/routes' { '/news/': RouteRecordInfo<'/news/', '/news', Record, Record>, 'named-news-page': RouteRecordInfo<'named-news-page', '/news/Today', Record, Record>, '/nolayout': RouteRecordInfo<'/nolayout', '/nolayout', Record, Record>, - '/second': RouteRecordInfo<'/second', '/second', Record, Record>, '/second/': RouteRecordInfo<'/second/', '/second', Record, Record>, '/sublayout': RouteRecordInfo<'/sublayout', '/sublayout', Record, Record>, } diff --git a/src/RouteLayout.ts b/src/RouteLayout.ts index c571262..9ed1766 100644 --- a/src/RouteLayout.ts +++ b/src/RouteLayout.ts @@ -1,4 +1,4 @@ -import { ResolvedOptions } from './types' +import type { ResolvedOptions } from './types' function getClientCode(importCode: string, options: ResolvedOptions) { const code = ` @@ -18,13 +18,22 @@ export function setupLayouts(routes) { route.children = deepSetupLayout(route.children, false) } - if (top && route.meta?.layout !== false) { - return { - path: route.path, - component: layouts[route.meta?.layout || '${options.defaultLayout}'], - children: [ {...route, path: ''} ], - meta: { - isLayout: true + if (top) { + // unplugin-vue-router adds a top-level route to the routing group, which we should skip. + const skipLayout = !route.component && route.children?.find(r => (r.path === '' || r.path === '/') && r.meta?.isLayout) + + if (skipLayout) { + return route + } + + if (route.meta?.layout !== false) { + return { + path: route.path, + component: layouts[route.meta?.layout || '${options.defaultLayout}'], + children: route.path === '/' ? [route] : [{...route, path: ''}], + meta: { + isLayout: true + } } } } diff --git a/src/clientSide.ts b/src/clientSide.ts index f4fd9ea..ea45721 100644 --- a/src/clientSide.ts +++ b/src/clientSide.ts @@ -1,4 +1,4 @@ -import { posix } from 'path' +import { posix } from 'node:path' function normalizePath(path: string) { path = path.startsWith('/') ? path : `/${path}` @@ -55,14 +55,23 @@ export async function createVirtualModuleCode( if (route.children?.length > 0) { route.children = deepSetupLayout(route.children, false) } - - if (top && route.meta?.layout !== false) { - return { - path: route.path, - component: layouts[route.meta?.layout || '${defaultLayout}'], - children: [ {...route, path: ''} ], - meta: { - isLayout: true + + if (top) { + // unplugin-vue-router adds a top-level route to the routing group, which we should skip. + const skipLayout = !route.component && route.children?.find(r => (r.path === '' || r.path === '/') && r.meta?.isLayout) + + if (skipLayout) { + return route + } + + if (route.meta?.layout !== false) { + return { + path: route.path, + component: layouts[route.meta?.layout || '${defaultLayout}'], + children: route.path === '/' ? [route] : [{...route, path: ''}], + meta: { + isLayout: true + } } } }