fix(v2): fromExtensions and toExtensions translation with baseUrl (#2969)

This commit is contained in:
John Knox 2020-06-22 17:43:42 +01:00 committed by GitHub
parent 592dca9196
commit ee5e59f633
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 27 deletions

View File

@ -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([]);
});
});

View File

@ -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(

View File

@ -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;
}