From ee5e59f6338dfe229da15af39ff654e785589130 Mon Sep 17 00:00:00 2001 From: John Knox Date: Mon, 22 Jun 2020 17:43:42 +0100 Subject: [PATCH] fix(v2): fromExtensions and toExtensions translation with baseUrl (#2969) --- .../src/__tests__/extensionRedirects.test.ts | 57 +++++++++++++--------- .../src/collectRedirects.ts | 6 ++- .../src/extensionRedirects.ts | 14 ++++-- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/packages/docusaurus-plugin-client-redirects/src/__tests__/extensionRedirects.test.ts b/packages/docusaurus-plugin-client-redirects/src/__tests__/extensionRedirects.test.ts index e305aed7c0..ce327688a2 100644 --- a/packages/docusaurus-plugin-client-redirects/src/__tests__/extensionRedirects.test.ts +++ b/packages/docusaurus-plugin-client-redirects/src/__tests__/extensionRedirects.test.ts @@ -15,32 +15,33 @@ const createExtensionValidationTests = ( extensionRedirectCreatorFn: ( paths: string[], extensions: string[], + baseUrl: string, ) => RedirectMetadata[], ) => { test('should reject empty extensions', () => { expect(() => { - extensionRedirectCreatorFn(['/'], ['.html']); + extensionRedirectCreatorFn(['/'], ['.html'], '/'); }).toThrowErrorMatchingInlineSnapshot( `"Extension=['.html'] contains a . (dot) and is not allowed. If the redirect extension system is not good enough for your usecase, you can create redirects yourself with the 'createRedirects' plugin option."`, ); }); test('should reject extensions with .', () => { expect(() => { - extensionRedirectCreatorFn(['/'], ['.html']); + extensionRedirectCreatorFn(['/'], ['.html'], '/'); }).toThrowErrorMatchingInlineSnapshot( `"Extension=['.html'] contains a . (dot) and is not allowed. If the redirect extension system is not good enough for your usecase, you can create redirects yourself with the 'createRedirects' plugin option."`, ); }); test('should reject extensions with /', () => { expect(() => { - extensionRedirectCreatorFn(['/'], ['ht/ml']); + extensionRedirectCreatorFn(['/'], ['ht/ml'], '/'); }).toThrowErrorMatchingInlineSnapshot( `"Extension=['ht/ml'] contains a / and is not allowed. If the redirect extension system is not good enough for your usecase, you can create redirects yourself with the 'createRedirects' plugin option."`, ); }); test('should reject extensions with illegal url char', () => { expect(() => { - extensionRedirectCreatorFn(['/'], [',']); + extensionRedirectCreatorFn(['/'], [','], '/'); }).toThrowErrorMatchingInlineSnapshot( `"Extension=[','] contains invalid uri characters. If the redirect extension system is not good enough for your usecase, you can create redirects yourself with the 'createRedirects' plugin option."`, ); @@ -52,22 +53,28 @@ describe('createToExtensionsRedirects', () => { test('should create redirects from html/htm extensions', () => { const ext = ['html', 'htm']; - expect(createToExtensionsRedirects([''], ext)).toEqual([]); - expect(createToExtensionsRedirects(['/'], ext)).toEqual([]); - expect(createToExtensionsRedirects(['/abc.html'], ext)).toEqual([ + expect(createToExtensionsRedirects([''], ext, '/')).toEqual([]); + expect(createToExtensionsRedirects(['/'], ext, '/')).toEqual([]); + expect(createToExtensionsRedirects(['/abc.html'], ext, '/')).toEqual([ {from: '/abc', to: '/abc.html'}, ]); - expect(createToExtensionsRedirects(['/abc.htm'], ext)).toEqual([ + expect(createToExtensionsRedirects(['/abc.htm'], ext, '/')).toEqual([ {from: '/abc', to: '/abc.htm'}, ]); - expect(createToExtensionsRedirects(['/abc.xyz'], ext)).toEqual([]); + expect(createToExtensionsRedirects(['/abc.xyz'], ext, '/')).toEqual([]); + }); + + test('should create "to" redirects without baseUrl when baseUrl is used', () => { + expect( + createToExtensionsRedirects(['/prefix/file.html'], ['html'], '/prefix/'), + ).toEqual([{from: '/file', to: '/file.html'}]); }); test('should not create redirection for an empty extension array', () => { const ext: string[] = []; - expect(createToExtensionsRedirects([''], ext)).toEqual([]); - expect(createToExtensionsRedirects(['/'], ext)).toEqual([]); - expect(createToExtensionsRedirects(['/abc.html'], ext)).toEqual([]); + expect(createToExtensionsRedirects([''], ext, '/')).toEqual([]); + expect(createToExtensionsRedirects(['/'], ext, '/')).toEqual([]); + expect(createToExtensionsRedirects(['/abc.html'], ext, '/')).toEqual([]); }); }); @@ -76,22 +83,28 @@ describe('createFromExtensionsRedirects', () => { test('should create redirects to html/htm extensions', () => { const ext = ['html', 'htm']; - expect(createFromExtensionsRedirects([''], ext)).toEqual([]); - expect(createFromExtensionsRedirects(['/'], ext)).toEqual([]); - expect(createFromExtensionsRedirects(['/abc'], ext)).toEqual([ + expect(createFromExtensionsRedirects([''], ext, '/')).toEqual([]); + expect(createFromExtensionsRedirects(['/'], ext, '/')).toEqual([]); + expect(createFromExtensionsRedirects(['/abc'], ext, '/')).toEqual([ {from: '/abc.html', to: '/abc'}, {from: '/abc.htm', to: '/abc'}, ]); - expect(createFromExtensionsRedirects(['/def.html'], ext)).toEqual([]); - expect(createFromExtensionsRedirects(['/def/'], ext)).toEqual([]); + expect(createFromExtensionsRedirects(['/def.html'], ext, '/')).toEqual([]); + expect(createFromExtensionsRedirects(['/def/'], ext, '/')).toEqual([]); + }); + + test('should create "from" redirects without baseUrl when baseUrl is used', () => { + expect( + createFromExtensionsRedirects(['/prefix/file'], ['html'], '/prefix/'), + ).toEqual([{from: '/file.html', to: '/file'}]); }); test('should not create redirection for an empty extension array', () => { const ext: string[] = []; - expect(createFromExtensionsRedirects([''], ext)).toEqual([]); - expect(createFromExtensionsRedirects(['/'], ext)).toEqual([]); - expect(createFromExtensionsRedirects(['/abc'], ext)).toEqual([]); - expect(createFromExtensionsRedirects(['/def.html'], ext)).toEqual([]); - expect(createFromExtensionsRedirects(['/def/'], ext)).toEqual([]); + expect(createFromExtensionsRedirects([''], ext, '/')).toEqual([]); + expect(createFromExtensionsRedirects(['/'], ext, '/')).toEqual([]); + expect(createFromExtensionsRedirects(['/abc'], ext, '/')).toEqual([]); + expect(createFromExtensionsRedirects(['/def.html'], ext, '/')).toEqual([]); + expect(createFromExtensionsRedirects(['/def/'], ext, '/')).toEqual([]); }); }); diff --git a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts index 92d3275a39..73cf5f0983 100644 --- a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts +++ b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts @@ -50,7 +50,9 @@ function validateCollectedRedirects( ); } - const allowedToPaths = pluginContext.routesPaths; + const allowedToPaths = pluginContext.routesPaths.map((path) => + path.replace(pluginContext.baseUrl, '/'), + ); const toPaths = redirects.map((redirect) => redirect.to); const illegalToPaths = difference(toPaths, allowedToPaths); if (illegalToPaths.length > 0) { @@ -113,10 +115,12 @@ function doCollectRedirects(pluginContext: PluginContext): RedirectMetadata[] { ...createFromExtensionsRedirects( pluginContext.routesPaths, pluginContext.options.fromExtensions, + pluginContext.baseUrl, ), ...createToExtensionsRedirects( pluginContext.routesPaths, pluginContext.options.toExtensions, + pluginContext.baseUrl, ), ...createRedirectsOptionRedirects(pluginContext.options.redirects), ...createCreateRedirectsOptionRedirects( diff --git a/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts b/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts index 9adebf43b4..ee43f329d7 100644 --- a/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts +++ b/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts @@ -43,6 +43,7 @@ const addLeadingDot = (extension: string) => `.${extension}`; export function createToExtensionsRedirects( paths: string[], extensions: string[], + baseUrl: string, ): RedirectMetadata[] { extensions.forEach(validateExtension); @@ -53,8 +54,8 @@ export function createToExtensionsRedirects( if (extensionFound) { const routePathWithoutExtension = removeSuffix(path, extensionFound); return [routePathWithoutExtension].map((from) => ({ - from, - to: path, + from: trimBaseUrl(from, baseUrl), + to: trimBaseUrl(path, baseUrl), })); } return []; @@ -67,6 +68,7 @@ export function createToExtensionsRedirects( export function createFromExtensionsRedirects( paths: string[], extensions: string[], + baseUrl: string, ): RedirectMetadata[] { extensions.forEach(validateExtension); @@ -80,10 +82,14 @@ export function createFromExtensionsRedirects( return []; } return extensions.map((ext) => ({ - from: `${path}.${ext}`, - to: path, + from: `${trimBaseUrl(path, baseUrl)}.${ext}`, + to: trimBaseUrl(path, baseUrl), })); }; return flatten(paths.map(createPathRedirects)); } + +function trimBaseUrl(path: string, baseUrl: string) { + return path.startsWith(baseUrl) ? path.replace(baseUrl, '/') : path; +}