diff --git a/packages/bridge/package.json b/packages/bridge/package.json index 49f6a0b25f..b81eede170 100644 --- a/packages/bridge/package.json +++ b/packages/bridge/package.json @@ -27,7 +27,7 @@ "estree-walker": "^2.0.2", "fs-extra": "^10.0.0", "magic-string": "^0.25.7", - "mlly": "^0.2.10", + "mlly": "^0.3.0", "node-fetch": "^3.0.0", "nuxi": "3.0.0", "nuxt-vite": "^0.3.5", diff --git a/packages/kit/package.json b/packages/kit/package.json index 2f6688af56..1aee9602c7 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -28,7 +28,7 @@ "hookable": "^5.0.0", "jiti": "^1.12.9", "lodash.template": "^4.5.0", - "mlly": "^0.2.10", + "mlly": "^0.3.0", "pathe": "^0.2.0", "pkg-types": "^0.2.1", "rc9": "^1.2.0", diff --git a/packages/nitro/package.json b/packages/nitro/package.json index 1af48798ac..af3997a67a 100644 --- a/packages/nitro/package.json +++ b/packages/nitro/package.json @@ -50,7 +50,7 @@ "jiti": "^1.12.9", "listhen": "^0.2.5", "mime": "^2.5.2", - "mlly": "^0.2.10", + "mlly": "^0.3.0", "node-fetch": "^3.0.0", "ohmyfetch": "^0.3.1", "ora": "^6.0.1", diff --git a/packages/nuxi/package.json b/packages/nuxi/package.json index 909deac2e7..79a51020bf 100644 --- a/packages/nuxi/package.json +++ b/packages/nuxi/package.json @@ -39,7 +39,7 @@ "flat": "^5.0.2", "jiti": "^1.12.9", "listhen": "^0.2.5", - "mlly": "^0.2.10", + "mlly": "^0.3.0", "mri": "^1.2.0", "p-debounce": "^4.0.0", "pathe": "^0.2.0", diff --git a/packages/nuxt3/package.json b/packages/nuxt3/package.json index 14a7e3468e..149701f2a2 100644 --- a/packages/nuxt3/package.json +++ b/packages/nuxt3/package.json @@ -33,7 +33,7 @@ "hash-sum": "^2.0.0", "hookable": "^5.0.0", "ignore": "^5.1.8", - "mlly": "^0.2.10", + "mlly": "^0.3.0", "murmurhash-es": "^0.1.1", "nuxi": "3.0.0", "ohmyfetch": "^0.3.1", diff --git a/packages/nuxt3/src/pages/utils.ts b/packages/nuxt3/src/pages/utils.ts index 098691a2f6..0a5442644b 100644 --- a/packages/nuxt3/src/pages/utils.ts +++ b/packages/nuxt3/src/pages/utils.ts @@ -163,13 +163,17 @@ function parseSegment (segment: string) { state = SegmentParserState.catchall } if (c === ']') { - consumeBuffer() + if (!buffer) { + throw new Error('Empty param') + } else { + consumeBuffer() + } state = SegmentParserState.initial } else if (PARAM_CHAR_RE.test(c)) { buffer += c } else { // eslint-disable-next-line no-console - console.log(`Ignored character "${c}" while building param "${buffer}" from "segment"`) + // console.debug(`[pages]Ignored character "${c}" while building param "${buffer}" from "segment"`) } break } diff --git a/packages/nuxt3/test/pages.test.ts b/packages/nuxt3/test/pages.test.ts new file mode 100644 index 0000000000..91acecb07f --- /dev/null +++ b/packages/nuxt3/test/pages.test.ts @@ -0,0 +1,193 @@ +import { expect } from 'chai' +import { generateRoutesFromFiles } from '../src/pages/utils' + +describe('pages:generateRoutesFromFiles', () => { + const pagesDir = 'pages' + const tests = [ + { + description: 'should generate correct route for 404', + files: [`${pagesDir}/404.vue`], + output: [ + { + name: '404', + path: '/:catchAll(.*)*', + file: `${pagesDir}/404.vue`, + children: [] + } + ] + }, + { + description: 'should generate correct routes for index pages', + files: [ + `${pagesDir}/index.vue`, + `${pagesDir}/parent/index.vue`, + `${pagesDir}/parent/child/index.vue` + ], + output: [ + { + name: 'index', + path: '/', + file: `${pagesDir}/index.vue`, + children: [] + }, + { + name: 'parent', + path: '/parent', + file: `${pagesDir}/parent/index.vue`, + children: [] + }, + { + name: 'parent-child', + path: '/parent/child', + file: `${pagesDir}/parent/child/index.vue`, + children: [] + } + ] + }, + { + description: 'should generate correct routes for parent/child', + files: [ + `${pagesDir}/parent.vue`, + `${pagesDir}/parent/child.vue` + ], + output: [ + { + name: 'parent', + path: '/parent', + file: `${pagesDir}/parent.vue`, + children: [ + { + name: 'parent-child', + path: 'child', + file: `${pagesDir}/parent/child.vue`, + children: [] + } + ] + } + ] + }, + { + description: 'should generate correct route for snake_case file', + files: [ + `${pagesDir}/snake_case.vue` + ], + output: [ + { + name: 'snake_case', + path: '/snake_case', + file: `${pagesDir}/snake_case.vue`, + children: [] + } + ] + }, + { + description: 'should generate correct route for kebab-case file', + files: [`${pagesDir}/kebab-case.vue`], + output: [ + { + name: 'kebab-case', + path: '/kebab-case', + file: `${pagesDir}/kebab-case.vue`, + children: [] + } + ] + }, + { + description: 'should generate correct dynamic routes', + files: [ + `${pagesDir}/[slug].vue`, + `${pagesDir}/sub/[slug].vue`, + `${pagesDir}/[sub]/route-[slug].vue` + ], + output: [ + { + name: 'slug', + path: '/:slug?', + file: `${pagesDir}/[slug].vue`, + children: [] + }, + { + name: 'sub-slug', + path: '/sub/:slug?', + file: `${pagesDir}/sub/[slug].vue`, + children: [] + }, + { + name: 'sub-route-slug', + path: '/:sub/route-:slug', + file: `${pagesDir}/[sub]/route-[slug].vue`, + children: [] + } + ] + }, + { + description: 'should generate correct catch-all route', + files: [`${pagesDir}/[...slug].vue`], + output: [ + { + name: 'slug', + path: '/:slug(.*)*', + file: `${pagesDir}/[...slug].vue`, + children: [] + } + ] + }, + { + description: 'should throw unfinished param error for dynamic route', + files: [`${pagesDir}/[slug.vue`], + error: 'Unfinished param "slug"' + }, + { + description: 'should throw empty param error for dynamic route', + files: [ + `${pagesDir}/[].vue` + ], + error: 'Empty param' + }, + { + description: 'should only allow "_" & "." as special character for dynamic route', + files: [ + `${pagesDir}/[a1_1a].vue`, + `${pagesDir}/[b2.2b].vue`, + `${pagesDir}/[c3@3c].vue`, + `${pagesDir}/[d4-4d].vue` + ], + output: [ + { + name: 'a1_1a', + path: '/:a1_1a?', + file: `${pagesDir}/[a1_1a].vue`, + children: [] + }, + { + name: 'b2.2b', + path: '/:b2.2b?', + file: `${pagesDir}/[b2.2b].vue`, + children: [] + }, + { + name: 'c33c', + path: '/:c33c?', + file: `${pagesDir}/[c3@3c].vue`, + children: [] + }, + { + name: 'd44d', + path: '/:d44d?', + file: `${pagesDir}/[d4-4d].vue`, + children: [] + } + ] + } + ] + + for (const test of tests) { + it(test.description, async () => { + if (test.error) { + expect(() => generateRoutesFromFiles(test.files, pagesDir)).to.throws(test.error) + } else { + expect(await generateRoutesFromFiles(test.files, pagesDir)).to.deep.equal(test.output) + } + }) + } +}) diff --git a/packages/webpack/package.json b/packages/webpack/package.json index 8c252dc3dd..12a6b16055 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -34,7 +34,7 @@ "lodash-es": "^4.17.21", "memfs": "^3.3.0", "mini-css-extract-plugin": "^2.4.2", - "mlly": "^0.2.10", + "mlly": "^0.3.0", "pathe": "^0.2.0", "pify": "^5.0.0", "postcss": "^8.3.9", diff --git a/yarn.lock b/yarn.lock index c288f7c104..57fae1e122 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2401,7 +2401,7 @@ __metadata: estree-walker: ^2.0.2 fs-extra: ^10.0.0 magic-string: ^0.25.7 - mlly: ^0.2.10 + mlly: ^0.3.0 node-fetch: ^3.0.0 nuxi: 3.0.0 nuxt-vite: ^0.3.5 @@ -2591,7 +2591,7 @@ __metadata: hookable: ^5.0.0 jiti: ^1.12.9 lodash.template: ^4.5.0 - mlly: ^0.2.10 + mlly: ^0.3.0 pathe: ^0.2.0 pkg-types: ^0.2.1 rc9: ^1.2.0 @@ -2663,7 +2663,7 @@ __metadata: jiti: ^1.12.9 listhen: ^0.2.5 mime: ^2.5.2 - mlly: ^0.2.10 + mlly: ^0.3.0 node-fetch: ^3.0.0 ohmyfetch: ^0.3.1 ora: ^6.0.1 @@ -2887,7 +2887,7 @@ __metadata: lodash-es: ^4.17.21 memfs: ^3.3.0 mini-css-extract-plugin: ^2.4.2 - mlly: ^0.2.10 + mlly: ^0.3.0 pathe: ^0.2.0 pify: ^5.0.0 postcss: ^8.3.9 @@ -13031,15 +13031,6 @@ fsevents@~2.3.2: languageName: node linkType: hard -"mlly@npm:^0.2.10": - version: 0.2.10 - resolution: "mlly@npm:0.2.10" - dependencies: - import-meta-resolve: ^1.1.1 - checksum: a7b9f9e046389eb8263ae57bf6738084dd40319ce1608b31dd66a72baf15e35bfb9d8a7dcde33f4c6f3b5da4788b8e94c65e9fa519c508ab5b339f4e6de255bc - languageName: node - linkType: hard - "mlly@npm:^0.2.6": version: 0.2.9 resolution: "mlly@npm:0.2.9" @@ -13049,6 +13040,13 @@ fsevents@~2.3.2: languageName: node linkType: hard +"mlly@npm:^0.3.0": + version: 0.3.0 + resolution: "mlly@npm:0.3.0" + checksum: be9bf1fd8bd547425073462496e2bd6c7affab00bc7bb075d9ddb19f6c748ecbc1e691ed5ec3d2862aac987091b90113494a5d24109e10e5ac01ea2ac5ef3782 + languageName: node + linkType: hard + "mocha@npm:^9.1.3": version: 9.1.3 resolution: "mocha@npm:9.1.3" @@ -13806,7 +13804,7 @@ fsevents@~2.3.2: fsevents: ~2.3.2 jiti: ^1.12.9 listhen: ^0.2.5 - mlly: ^0.2.10 + mlly: ^0.3.0 mri: ^1.2.0 p-debounce: ^4.0.0 pathe: ^0.2.0 @@ -13904,7 +13902,7 @@ fsevents@~2.3.2: hash-sum: ^2.0.0 hookable: ^5.0.0 ignore: ^5.1.8 - mlly: ^0.2.10 + mlly: ^0.3.0 murmurhash-es: ^0.1.1 nuxi: 3.0.0 ohmyfetch: ^0.3.1