From d43d3b6a96f72f808f9acd6cb4ef8792dec57418 Mon Sep 17 00:00:00 2001 From: ULIVZ <472590061@qq.com> Date: Fri, 8 Feb 2019 22:13:26 +0800 Subject: [PATCH] feat($core): handle redirect for clean urls --- packages/@vuepress/core/lib/app/app.js | 12 +---- packages/@vuepress/core/lib/app/redirect.js | 57 +++++++++++++++++++++ 2 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 packages/@vuepress/core/lib/app/redirect.js diff --git a/packages/@vuepress/core/lib/app/app.js b/packages/@vuepress/core/lib/app/app.js index 1adc33e3f3..a0432331e6 100644 --- a/packages/@vuepress/core/lib/app/app.js +++ b/packages/@vuepress/core/lib/app/app.js @@ -8,6 +8,7 @@ import appEnhancers from '@internal/app-enhancers' import globalUIComponents from '@internal/global-ui' import ClientComputedMixin from '@transform/ClientComputedMixin' import VuePress from './plugins/VuePress' +import handleRedirect from './redirect.js' // built-in components import Content from './components/Content.js' @@ -74,16 +75,7 @@ export function createApp (isServer) { } }) - // redirect /foo to /foo/ - router.beforeEach((to, from, next) => { - if (!/(\/|\.html)$/.test(to.path)) { - next(Object.assign({}, to, { - path: to.path + '/' - })) - } else { - next() - } - }) + handleRedirect(router) const options = {} diff --git a/packages/@vuepress/core/lib/app/redirect.js b/packages/@vuepress/core/lib/app/redirect.js new file mode 100644 index 0000000000..1305771734 --- /dev/null +++ b/packages/@vuepress/core/lib/app/redirect.js @@ -0,0 +1,57 @@ +// In VuePress, we have following convention about routing: +// +// - `/foo/` means source file is `/foo/{README|index}.md` +// - `/foo.html` means your source file is `/foo.md` +// +// The original design of VuePress relied on above two styles +// of routing, especially the routing calculations involved in +// default theme. so we can't easily modify `/foo.html` directly +// to `/foo` (i.e. remove html suffix) +// +// This "temporary" utility handles redirect of clean urls, with +// this utility, you'll get: +// +// For unknown request `/foo` +// - redirect to `/foo.html` if it exists +// - redirect to `/foo/` if it exists +// +// For unknown request `/foo/` +// - redirect to `/foo.html` if it exists + +export default function handleRedirect (router) { + router.beforeEach((to, from, next) => { + if (isRouteExists(router, to.path)) { + next() + } else { + // For unknown request `/foo` + // redirect to /foo/ if exists + // redirect to /foo.html if exists + if (!/(\/|\.html)$/.test(to.path)) { + const endingSlashUrl = to.path + '/' + const endingHtmlUrl = to.path + '.html' + if (isRouteExists(router, endingHtmlUrl)) { + next(endingHtmlUrl) + } else if (isRouteExists(router, endingSlashUrl)) { + next(endingSlashUrl) + } else { + next() + } + // For unknown request `/foo/` + // redirect to /foo.html if exists + } else if (/\/$/.test(to.path)) { + const endingHtmlUrl = to.path.replace(/\/$/, '') + '.html' + if (isRouteExists(router, endingHtmlUrl)) { + next(endingHtmlUrl) + } else { + next() + } + } else { + next() + } + } + }) +} + +function isRouteExists (router, path) { + return router.options.routes.filter(route => route.path === path).length > 0 +}