fix(utils): respect patterns within paths when sorting routes (#20669)

This commit is contained in:
Marcelo Botega Fontana 2023-05-22 18:15:44 +02:00 committed by GitHub
parent 10787e325b
commit 5e9942b007
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 245 additions and 51 deletions

View File

@ -97,7 +97,7 @@ function cleanChildrenRoutes (routes, isChild = false, routeNameSplitter = '-',
return routes
}
const DYNAMIC_ROUTE_REGEX = /^\/([:*])/
const DYNAMIC_ROUTE_REGEX = /[:*]/
export const sortRoutes = function sortRoutes (routes) {
routes.sort((a, b) => {
@ -126,13 +126,13 @@ export const sortRoutes = function sortRoutes (routes) {
if (res !== 0) {
break
}
y = _a[i] === '*' ? 2 : _a[i].includes(':') ? 1 : 0
z = _b[i] === '*' ? 2 : _b[i].includes(':') ? 1 : 0
y = _a[i] === '*' ? 3 : _a[i].includes(':') ? 2 : _a[i].includes('*') ? 1 : 0
z = _b[i] === '*' ? 3 : _b[i].includes(':') ? 2 : _b[i].includes('*') ? 1 : 0
res = y - z
// If a.length >= b.length
if (i === _b.length - 1 && res === 0) {
// unless * found sort by level, then alphabetically
res = _a[i] === '*'
res = _a[i].includes('*')
? -1
: (
_a.length === _b.length ? a.path.localeCompare(b.path) : (_a.length - _b.length)
@ -142,7 +142,7 @@ export const sortRoutes = function sortRoutes (routes) {
if (res === 0) {
// unless * found sort by level, then alphabetically
res = _a[i - 1] === '*' && _b[i]
res = _a[i - 1].includes('*') && _b[i]
? 1
: (
_a.length === _b.length ? a.path.localeCompare(b.path) : (_a.length - _b.length)
@ -248,7 +248,6 @@ const getRoutePathExtension = (key) => {
if (key.startsWith('_')) {
return `:${key.substr(1)}`
}
return key
}

View File

@ -26,6 +26,12 @@ exports[`util: route util: route create createRoutes should allow snake case rou
"name": "parent-child-test",
"path": "/parent/child/test",
},
{
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "/",
},
{
"chunkName": "pages/another_route/_id",
"component": "/some/nuxt/app/pages/another_route/_id.vue",
@ -44,12 +50,6 @@ exports[`util: route util: route create createRoutes should allow snake case rou
"name": "parent-all",
"path": "/parent/*",
},
{
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "/",
},
{
"chunkName": "pages/_param",
"component": "/some/nuxt/app/pages/_param.vue",
@ -85,6 +85,12 @@ exports[`util: route util: route create createRoutes should allow snake case rou
"name": "parent-child-test",
"path": "/parent/child/test",
},
{
"chunkName": "pages/index",
"component": "\\\\\\\\some\\\\nuxt\\\\app\\\\pages\\\\index.vue",
"name": "index",
"path": "/",
},
{
"chunkName": "pages/another_route/_id",
"component": "\\\\\\\\some\\\\nuxt\\\\app\\\\pages\\\\another_route\\\\_id.vue",
@ -103,12 +109,6 @@ exports[`util: route util: route create createRoutes should allow snake case rou
"name": "parent-all",
"path": "/parent/*",
},
{
"chunkName": "pages/index",
"component": "\\\\\\\\some\\\\nuxt\\\\app\\\\pages\\\\index.vue",
"name": "index",
"path": "/",
},
{
"chunkName": "pages/_param",
"component": "\\\\\\\\some\\\\nuxt\\\\app\\\\pages\\\\_param.vue",
@ -156,6 +156,15 @@ exports[`util: route util: route create createRoutes should enforce trailing sla
"strict": true,
},
},
{
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "/",
"pathToRegexpOptions": {
"strict": true,
},
},
{
"chunkName": "pages/another_route/_id",
"component": "/some/nuxt/app/pages/another_route/_id.vue",
@ -183,15 +192,6 @@ exports[`util: route util: route create createRoutes should enforce trailing sla
"strict": true,
},
},
{
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "/",
"pathToRegexpOptions": {
"strict": true,
},
},
{
"chunkName": "pages/_param",
"component": "/some/nuxt/app/pages/_param.vue",
@ -242,6 +242,15 @@ exports[`util: route util: route create createRoutes should remove trailing slas
"strict": true,
},
},
{
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "/",
"pathToRegexpOptions": {
"strict": true,
},
},
{
"chunkName": "pages/another_route/_id",
"component": "/some/nuxt/app/pages/another_route/_id.vue",
@ -269,15 +278,6 @@ exports[`util: route util: route create createRoutes should remove trailing slas
"strict": true,
},
},
{
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "/",
"pathToRegexpOptions": {
"strict": true,
},
},
{
"chunkName": "pages/_param",
"component": "/some/nuxt/app/pages/_param.vue",
@ -289,3 +289,93 @@ exports[`util: route util: route create createRoutes should remove trailing slas
},
]
`;
exports[`util: route util: route sortRoutes sortRoutes should sort routes 1`] = `
[
{
"chunkName": "pages/de/index",
"component": "/some/nuxt/app/pages/de/index.vue",
"name": "de",
"path": "/de",
},
{
"chunkName": "pages/de_",
"component": "/some/nuxt/app/pages/de_.vue",
"name": "de_",
"path": "/de_",
},
{
"chunkName": "pages/parent/index",
"component": "/some/nuxt/app/pages/parent/index.vue",
"name": "parent",
"path": "/parent",
},
{
"chunkName": "pages/snake_case_route",
"component": "/some/nuxt/app/pages/snake_case_route.vue",
"name": "snake_case_route",
"path": "/snake_case_route",
},
{
"children": [
{
"chunkName": "pages/another_route/rout_",
"component": "/some/nuxt/app/pages/another_route/rout_.vue",
"name": "another_route-rout_",
"path": "",
},
],
"chunkName": "pages/another_route/rout_",
"component": "/some/nuxt/app/pages/another_route/rout_.vue",
"path": "/another_route/rout_",
},
{
"chunkName": "pages/parent/child/index",
"component": "/some/nuxt/app/pages/parent/child/index.vue",
"name": "parent-child",
"path": "/parent/child",
},
{
"chunkName": "pages/parent/child/test",
"component": "/some/nuxt/app/pages/parent/child/test.vue",
"name": "parent-child-test",
"path": "/parent/child/test",
},
{
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "/",
},
{
"chunkName": "pages/another_route/_id",
"component": "/some/nuxt/app/pages/another_route/_id.vue",
"name": "another_route-id",
"path": "/another_route/:id?",
},
{
"chunkName": "pages/subpage/_param",
"component": "/some/nuxt/app/pages/subpage/_param.vue",
"name": "subpage-param",
"path": "/subpage/:param?",
},
{
"chunkName": "pages/parent/_",
"component": "/some/nuxt/app/pages/parent/_.vue",
"name": "parent-all",
"path": "/parent/*",
},
{
"chunkName": "pages/_param",
"component": "/some/nuxt/app/pages/_param.vue",
"name": "param",
"path": "/:param",
},
{
"chunkName": "pages/_",
"component": "/some/nuxt/app/pages/_.vue",
"name": "all",
"path": "/*",
},
]
`;

View File

@ -1,4 +1,4 @@
import { flatRoutes, createRoutes, guardDir, promisifyRoute } from '../src/route'
import { flatRoutes, createRoutes, guardDir, promisifyRoute, sortRoutes } from '../src/route'
describe('util: route', () => {
test('should flat route with path', () => {
@ -238,4 +238,109 @@ describe('util: route', () => {
expect(routesResult).toMatchSnapshot()
})
})
describe('util: route sortRoutes', () => {
const files = [
'pages/_param.vue',
'pages/de/index.vue',
'pages/index.vue',
'pages/_.vue',
'pages/another_route/rout_.vue',
'pages/snake_case_route.vue',
'pages/subpage/_param.vue',
'pages/de_.vue',
'pages/parent/index.vue',
'pages/parent/_.vue',
'pages/another_route/_id.vue',
'pages/another_route/rout_.vue',
'pages/parent/child/index.vue',
'pages/parent/child/test.vue'
]
const srcDir = '/some/nuxt/app'
const pagesDir = 'pages'
test.posix('sortRoutes should sort routes', () => {
const routesResult = createRoutes({ files, srcDir, pagesDir })
expect(routesResult).toMatchSnapshot()
})
test('Should sortRoutes with extendRoutes using *', () => {
const routes = [
{ path: '/poetry' },
{ path: '/reports' },
{ path: '*' },
{ path: '/de/about' },
{ path: '/' },
{ path: '/about' },
{ path: '/de' },
{ path: '/tech' },
{ path: '/de/tech' },
{ path: '/de*' },
{ path: '/:post' },
{ path: '/de/:post' },
{ path: '/de/reports' },
{ path: '/de/poetry' }
]
sortRoutes(routes)
expect(routes).toEqual(
[
{ path: '/about' },
{ path: '/de' },
{ path: '/poetry' },
{ path: '/reports' },
{ path: '/tech' },
{ path: '/de/about' },
{ path: '/de/poetry' },
{ path: '/de/reports' },
{ path: '/de/tech' },
{ path: '/' },
{ path: '/de/:post' },
{ path: '/de*' },
{ path: '/:post' },
{ path: '*' }
]
)
})
test('Should sortRoutes with extendRoutes using /*', () => {
const routes = [
{ path: '/poetry' },
{ path: '/reports' },
{ path: '/*' },
{ path: '/de/about' },
{ path: '/about' },
{ path: '/de' },
{ path: '/tech' },
{ path: '/de/tech' },
{ path: '/de/*' },
{ path: '/' },
{ path: '/:post' },
{ path: '/de/:post' },
{ path: '/de/reports' },
{ path: '/de/poetry' }
]
sortRoutes(routes)
expect(routes).toEqual(
[
{ path: '/about' },
{ path: '/de' },
{ path: '/poetry' },
{ path: '/reports' },
{ path: '/tech' },
{ path: '/de/about' },
{ path: '/de/poetry' },
{ path: '/de/reports' },
{ path: '/de/tech' },
{ path: '/' },
{ path: '/de/:post' },
{ path: '/de/*' },
{ path: '/:post' },
{ path: '/*' }
]
)
})
})
})

View File

@ -54,23 +54,23 @@ describe('dynamic routes', () => {
// pages/test/songs/toto.vue
expect(routes[5].path).toBe('/test/songs/toto')
expect(routes[5].name).toBe('test-songs-toto')
// pages/test/projects/_category.vue
expect(routes[6].path).toBe('/test/projects/:category')
expect(routes[6].name).toBe('test-projects-category')
// pages/test/songs/_id.vue
expect(routes[7].path).toBe('/test/songs/:id?')
expect(routes[7].name).toBe('test-songs-id')
// pages/users/_id.vue
expect(routes[8].path).toBe('/users/:id?')
expect(routes[8].name).toBe('users-id')
// pages/test/_.vue
expect(routes[9].path).toBe('/test/*')
expect(routes[9].name).toBe('test-all')
// pages/index.vue
expect(routes[10].path).toBe('/')
expect(routes[10].name).toBe('index')
expect(routes[6].path).toBe('/')
expect(routes[6].name).toBe('index')
// pages/test/projects/_category.vue
expect(routes[7].path).toBe('/test/projects/:category')
expect(routes[7].name).toBe('test-projects-category')
// pages/test/songs/_id.vue
expect(routes[8].path).toBe('/test/songs/:id?')
expect(routes[8].name).toBe('test-songs-id')
// pages/users/_id.vue
expect(routes[9].path).toBe('/users/:id?')
expect(routes[9].name).toBe('users-id')
// pages/test/_.vue
expect(routes[10].path).toBe('/test/*')
expect(routes[10].name).toBe('test-all')
// pages/_slug.vue
expect(routes[11].path).toBe('/:slug')
expect(routes[11].name).toBe('slug')