diff --git a/app/app.vue b/app/app.vue index a508c15..6584301 100644 --- a/app/app.vue +++ b/app/app.vue @@ -25,10 +25,17 @@ onNuxtReady(() => loadSearchSections()) const nuxtApp = useNuxtApp() const navTree = computed(() => prefixNavigation(navigation.value ?? [], content.value.base)) -const navigationLayout = ref(findNavigationLayout(navTree.value, route.path)) +const resolveNavigationLayout = () => { + if (route.meta.layout === false) return undefined + if (route.meta.layout === 'docs' || route.meta.layout === 'page') return route.meta.layout + const layout = findNavigationLayout(navTree.value, route.path) + if (!layout && route.matched?.[0]?.name === 'slug') return 'docs' + return layout +} +const navigationLayout = ref(resolveNavigationLayout()) onNuxtReady(() => { nuxtApp.hook('page:finish', () => { - navigationLayout.value = findNavigationLayout(navTree.value, route.path) + navigationLayout.value = resolveNavigationLayout() }) }) const searchFiles = computed(() => @@ -99,9 +106,7 @@ defineShortcuts({ - - - + diff --git a/app/types/navigation-layout.d.ts b/app/types/navigation-layout.d.ts new file mode 100644 index 0000000..2654ab5 --- /dev/null +++ b/app/types/navigation-layout.d.ts @@ -0,0 +1,8 @@ +declare module 'nuxt/app' { + interface NuxtLayouts { + docs: Record + page: Record + } +} + +export {} diff --git a/app/utils/navigation.ts b/app/utils/navigation.ts index dc718d0..cff2c86 100644 --- a/app/utils/navigation.ts +++ b/app/utils/navigation.ts @@ -37,7 +37,7 @@ export function findNavigationLayout( navigation: NavigationItem[] | undefined | null, path: string | undefined ): NavigationLayout | undefined { - if (!navigation?.length || !path || path === '/') return undefined + if (!navigation?.length || !path) return undefined let layout: NavigationLayout | undefined const visit = (items: NavigationItem[]) => { @@ -56,7 +56,7 @@ export function findNavigationLayout( } visit(navigation) - return layout || 'docs' + return layout } /** Trail of navigation items leading to `path`, including the page itself. */ diff --git a/eslint.config.mjs b/eslint.config.mjs index 1181ca0..6f403e9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -36,7 +36,15 @@ export default createConfigForNuxt({ // `index.vue`, `docs.vue`, `[...slug].vue` are the framework's naming, not ours. // `Browser.vue` is exempt for a different reason: it's addressed from markdown // (`::browser`), so its name is part of the content API. - files: ['app/pages/**/*.vue', 'app/layouts/**/*.vue', 'app/error.vue', 'app/components/Browser.vue'], + files: [ + 'app/pages/**/*.vue', + 'playground/app/pages/**/*.vue', + 'app/layouts/**/*.vue', + 'playground/app/layouts/**/*.vue', + 'app/error.vue', + 'playground/app/error.vue', + 'app/components/Browser.vue', + ], rules: { 'vue/multi-word-component-names': 'off', }, diff --git a/playground/app/pages/full.vue b/playground/app/pages/full.vue new file mode 100644 index 0000000..b0fc791 --- /dev/null +++ b/playground/app/pages/full.vue @@ -0,0 +1,3 @@ + diff --git a/test/navigation.test.ts b/test/navigation.test.ts index da4aa0d..8110ef2 100644 --- a/test/navigation.test.ts +++ b/test/navigation.test.ts @@ -107,7 +107,7 @@ describe('findNavigationLayout', () => { }) it('does not inherit a layout from a partial path segment match', () => { - expect(findNavigationLayout(navigation, '/examples-extended/page')).toBe('docs') + expect(findNavigationLayout(navigation, '/examples-extended/page')).toBeUndefined() }) it('supports navigation paths prefixed for version previews', () => { @@ -122,12 +122,12 @@ describe('findNavigationLayout', () => { expect(findNavigationLayout(previewNavigation, '/tree/feature/examples/overview')).toBe('page') }) - it('falls back to docs without a matching supported layout', () => { - expect(findNavigationLayout(navigation, '/unknown')).toBe('docs') + it('returns undefined without a matching supported layout', () => { + expect(findNavigationLayout(navigation, '/unknown')).toBeUndefined() expect(findNavigationLayout( [{ title: 'Custom', path: '/custom', layout: 'custom' }] as unknown as NavigationItem[], '/custom' - )).toBe('docs') + )).toBeUndefined() }) it('returns undefined for the landing page or without enough navigation context', () => {