From 42ff0ad035cf4590db894d199b1531990a7a4146 Mon Sep 17 00:00:00 2001 From: dannyandres Date: Tue, 12 Jul 2022 01:06:12 -0400 Subject: [PATCH] [feat] Adds support for folders in /layouts * added new util method to get the name from layout * added deep search on /layouts folder * added test cases for mobile and desktop layouts --- packages/nuxt/src/core/app.ts | 6 +++--- packages/nuxt/src/core/utils.ts | 16 ++++++++++++++- test/basic.test.ts | 20 +++++++++++++++++++ .../basic/layouts/desktop/default.vue | 6 ++++++ .../fixtures/basic/layouts/mobile/default.vue | 6 ++++++ .../basic/pages/with-desktop-layout.vue | 11 ++++++++++ .../basic/pages/with-mobile-layout.vue | 11 ++++++++++ 7 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/basic/layouts/desktop/default.vue create mode 100644 test/fixtures/basic/layouts/mobile/default.vue create mode 100644 test/fixtures/basic/pages/with-desktop-layout.vue create mode 100644 test/fixtures/basic/pages/with-mobile-layout.vue diff --git a/packages/nuxt/src/core/app.ts b/packages/nuxt/src/core/app.ts index 50524ca24ae..16818261410 100644 --- a/packages/nuxt/src/core/app.ts +++ b/packages/nuxt/src/core/app.ts @@ -5,7 +5,7 @@ import type { Nuxt, NuxtApp, NuxtPlugin } from '@nuxt/schema' import { findPath, resolveFiles, normalizePlugin, normalizeTemplate, compileTemplate, templateUtils, tryResolveModule } from '@nuxt/kit' import * as defaultTemplates from './templates' -import { getNameFromPath, hasSuffix, uniqueBy } from './utils' +import { getNameFromPath, getNameFromPathLocal, hasSuffix, uniqueBy } from './utils' export function createApp (nuxt: Nuxt, options: Partial = {}): NuxtApp { return defu(options, { @@ -76,9 +76,9 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) { // Resolve layouts/ from all config layers app.layouts = {} for (const config of nuxt.options._layers.map(layer => layer.config)) { - const layoutFiles = await resolveFiles(config.srcDir, `${config.dir?.layouts || 'layouts'}/*{${nuxt.options.extensions.join(',')}}`) + const layoutFiles = await resolveFiles(config.srcDir, `${config.dir?.layouts || 'layouts'}/**/*{${nuxt.options.extensions.join(',')}}`) for (const file of layoutFiles) { - const name = getNameFromPath(file) + const name = getNameFromPathLocal(file, config.srcDir + '/layouts') app.layouts[name] = app.layouts[name] || { name, file } } } diff --git a/packages/nuxt/src/core/utils.ts b/packages/nuxt/src/core/utils.ts index 46757ec20ba..94e4e63fee1 100644 --- a/packages/nuxt/src/core/utils.ts +++ b/packages/nuxt/src/core/utils.ts @@ -1,10 +1,24 @@ import { basename, extname } from 'pathe' -import { kebabCase, pascalCase } from 'scule' +import { kebabCase, pascalCase, snakeCase } from 'scule' export function getNameFromPath (path: string) { return kebabCase(basename(path).replace(extname(path), '')).replace(/["']/g, '') } +export function getNameFromPathLocal (path: string, src: string) { + const sourcePath = path + .replace(src + '/', '') + .split('/') + .slice(0, -1) + .map(e => snakeCase(e)) + .join('/') + return ( + sourcePath + + (sourcePath ? '/' : '') + + kebabCase(basename(path).replace(extname(path), '')).replace(/["']/g, '') + ) +} + export function uniqueBy (arr: T[], key: K) { const res: T[] = [] const seen = new Set() diff --git a/test/basic.test.ts b/test/basic.test.ts index b4fcb492bf6..cc64e2df80b 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -234,6 +234,26 @@ describe('layouts', () => { expect(html).toContain('with-layout.vue') expect(html).toContain('Custom Layout:') }) + + it('should apply desktop layout', async () => { + const html = await $fetch('/with-desktop-layout') + + // Snapshot + // expect(html).toMatchInlineSnapshot() + + expect(html).toContain('with-desktop-layout.vue') + expect(html).toContain('Desktop Layout:') + }) + + it('should apply mobile layout', async () => { + const html = await $fetch('/with-mobile-layout') + + // Snapshot + // expect(html).toMatchInlineSnapshot() + + expect(html).toContain('with-mobile-layout.vue') + expect(html).toContain('Mobile Layout:') + }) }) describe('reactivity transform', () => { diff --git a/test/fixtures/basic/layouts/desktop/default.vue b/test/fixtures/basic/layouts/desktop/default.vue new file mode 100644 index 00000000000..bca1fd61d2e --- /dev/null +++ b/test/fixtures/basic/layouts/desktop/default.vue @@ -0,0 +1,6 @@ + diff --git a/test/fixtures/basic/layouts/mobile/default.vue b/test/fixtures/basic/layouts/mobile/default.vue new file mode 100644 index 00000000000..b6926ca803b --- /dev/null +++ b/test/fixtures/basic/layouts/mobile/default.vue @@ -0,0 +1,6 @@ + diff --git a/test/fixtures/basic/pages/with-desktop-layout.vue b/test/fixtures/basic/pages/with-desktop-layout.vue new file mode 100644 index 00000000000..0e5c26d7aee --- /dev/null +++ b/test/fixtures/basic/pages/with-desktop-layout.vue @@ -0,0 +1,11 @@ + + + diff --git a/test/fixtures/basic/pages/with-mobile-layout.vue b/test/fixtures/basic/pages/with-mobile-layout.vue new file mode 100644 index 00000000000..c6aa723b6b4 --- /dev/null +++ b/test/fixtures/basic/pages/with-mobile-layout.vue @@ -0,0 +1,11 @@ + + +