feat(builder, router): enforce uniform trailing slash handling (#6331)

This commit is contained in:
Alexander Lichter 2019-09-01 16:37:25 +02:00 committed by Pooya Parsa
parent e9c4bcfee2
commit 7c90310166
7 changed files with 203 additions and 5 deletions

View File

@ -337,12 +337,14 @@ export default class Builder {
async resolveRoutes ({ templateVars }) { async resolveRoutes ({ templateVars }) {
consola.debug('Generating routes...') consola.debug('Generating routes...')
const { routeNameSplitter, trailingSlash } = this.options.router
if (this._defaultPage) { if (this._defaultPage) {
templateVars.router.routes = createRoutes({ templateVars.router.routes = createRoutes({
files: ['index.vue'], files: ['index.vue'],
srcDir: this.template.dir + '/pages', srcDir: this.template.dir + '/pages',
routeNameSplitter: this.options.router.routeNameSplitter routeNameSplitter,
trailingSlash
}) })
} else if (this._nuxtPages) { } else if (this._nuxtPages) {
// Use nuxt.js createRoutes bases on pages/ // Use nuxt.js createRoutes bases on pages/
@ -359,8 +361,9 @@ export default class Builder {
files: Object.values(files), files: Object.values(files),
srcDir: this.options.srcDir, srcDir: this.options.srcDir,
pagesDir: this.options.dir.pages, pagesDir: this.options.dir.pages,
routeNameSplitter: this.options.router.routeNameSplitter, routeNameSplitter,
supportedExtensions: this.supportedExtensions supportedExtensions: this.supportedExtensions,
trailingSlash
}) })
} else { // If user defined a custom method to create routes } else { // If user defined a custom method to create routes
templateVars.router.routes = this.options.build.createRoutes( templateVars.router.routes = this.options.build.createRoutes(

View File

@ -12,5 +12,6 @@ export default () => ({
parseQuery: false, parseQuery: false,
stringifyQuery: false, stringifyQuery: false,
fallback: false, fallback: false,
prefetchLinks: true prefetchLinks: true,
trailingSlash: undefined
}) })

View File

@ -322,6 +322,7 @@ Object {
"routes": Array [], "routes": Array [],
"scrollBehavior": null, "scrollBehavior": null,
"stringifyQuery": false, "stringifyQuery": false,
"trailingSlash": undefined,
}, },
"server": Object { "server": Object {
"host": "localhost", "host": "localhost",

View File

@ -289,6 +289,7 @@ Object {
"routes": Array [], "routes": Array [],
"scrollBehavior": null, "scrollBehavior": null,
"stringifyQuery": false, "stringifyQuery": false,
"trailingSlash": undefined,
}, },
"server": Object { "server": Object {
"host": "localhost", "host": "localhost",
@ -618,6 +619,7 @@ Object {
"routes": Array [], "routes": Array [],
"scrollBehavior": null, "scrollBehavior": null,
"stringifyQuery": false, "stringifyQuery": false,
"trailingSlash": undefined,
}, },
"server": Object { "server": Object {
"host": "localhost", "host": "localhost",

View File

@ -136,7 +136,8 @@ export const createRoutes = function createRoutes ({
srcDir, srcDir,
pagesDir = '', pagesDir = '',
routeNameSplitter = '-', routeNameSplitter = '-',
supportedExtensions = ['vue', 'js'] supportedExtensions = ['vue', 'js'],
trailingSlash
}) { }) {
const routes = [] const routes = []
files.forEach((file) => { files.forEach((file) => {
@ -173,6 +174,11 @@ export const createRoutes = function createRoutes ({
} }
} }
}) })
if (trailingSlash !== undefined) {
route.pathToRegexpOptions = { ...route.pathToRegexpOptions, strict: true }
route.path = route.path.replace(/\/+$/, '') + (trailingSlash ? '/' : '')
}
parent.push(route) parent.push(route)
}) })

View File

@ -119,3 +119,178 @@ Array [
}, },
] ]
`; `;
exports[`util: route util: route create createRoutes should enforce trailing slashes when configured to 1`] = `
Array [
Object {
"chunkName": "pages/parent/index",
"component": "/some/nuxt/app/pages/parent/index.vue",
"name": "parent",
"path": "/parent/",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/snake_case_route",
"component": "/some/nuxt/app/pages/snake_case_route.vue",
"name": "snake_case_route",
"path": "/snake_case_route/",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/parent/child/index",
"component": "/some/nuxt/app/pages/parent/child/index.vue",
"name": "parent-child",
"path": "/parent/child/",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/parent/child/test",
"component": "/some/nuxt/app/pages/parent/child/test.vue",
"name": "parent-child-test",
"path": "/parent/child/test/",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"children": Array [
Object {
"chunkName": "pages/another_route/_id",
"component": "/some/nuxt/app/pages/another_route/_id.vue",
"name": "another_route-id",
"path": "",
"pathToRegexpOptions": Object {
"strict": true,
},
},
],
"chunkName": "pages/another_route/_id",
"component": "/some/nuxt/app/pages/another_route/_id.vue",
"name": "another_route-id",
"path": "/another_route/:id?/",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/subpage/_param",
"component": "/some/nuxt/app/pages/subpage/_param.vue",
"name": "subpage-param",
"path": "/subpage/:param?/",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "/",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/_param",
"component": "/some/nuxt/app/pages/_param.vue",
"name": "param",
"path": "/:param/",
"pathToRegexpOptions": Object {
"strict": true,
},
},
]
`;
exports[`util: route util: route create createRoutes should remove trailing slashes when configured to 1`] = `
Array [
Object {
"chunkName": "pages/index",
"component": "/some/nuxt/app/pages/index.vue",
"name": "index",
"path": "",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/parent/index",
"component": "/some/nuxt/app/pages/parent/index.vue",
"name": "parent",
"path": "/parent",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/snake_case_route",
"component": "/some/nuxt/app/pages/snake_case_route.vue",
"name": "snake_case_route",
"path": "/snake_case_route",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/parent/child/index",
"component": "/some/nuxt/app/pages/parent/child/index.vue",
"name": "parent-child",
"path": "/parent/child",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/parent/child/test",
"component": "/some/nuxt/app/pages/parent/child/test.vue",
"name": "parent-child-test",
"path": "/parent/child/test",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"children": Array [
Object {
"chunkName": "pages/another_route/_id",
"component": "/some/nuxt/app/pages/another_route/_id.vue",
"name": "another_route-id",
"path": "",
"pathToRegexpOptions": Object {
"strict": true,
},
},
],
"chunkName": "pages/another_route/_id",
"component": "/some/nuxt/app/pages/another_route/_id.vue",
"path": "/another_route/:id?",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/subpage/_param",
"component": "/some/nuxt/app/pages/subpage/_param.vue",
"name": "subpage-param",
"path": "/subpage/:param?",
"pathToRegexpOptions": Object {
"strict": true,
},
},
Object {
"chunkName": "pages/_param",
"component": "/some/nuxt/app/pages/_param.vue",
"name": "param",
"path": "/:param",
"pathToRegexpOptions": Object {
"strict": true,
},
},
]
`;

View File

@ -194,5 +194,15 @@ describe('util: route', () => {
const routesResult = createRoutes({ files, srcDir, pagesDir }) const routesResult = createRoutes({ files, srcDir, pagesDir })
expect(routesResult).toMatchSnapshot() expect(routesResult).toMatchSnapshot()
}) })
test.posix('createRoutes should enforce trailing slashes when configured to', () => {
const routesResult = createRoutes({ files, srcDir, pagesDir, trailingSlash: true })
expect(routesResult).toMatchSnapshot()
})
test.posix('createRoutes should remove trailing slashes when configured to', () => {
const routesResult = createRoutes({ files, srcDir, pagesDir, trailingSlash: false })
expect(routesResult).toMatchSnapshot()
})
}) })
}) })