mirror of
https://github.com/facebook/docusaurus.git
synced 2025-08-02 08:19:07 +02:00
improve a bit collectRedirects
This commit is contained in:
parent
d8c163e76b
commit
26beb00476
6 changed files with 180 additions and 22 deletions
|
@ -0,0 +1,154 @@
|
|||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {PluginContext, UserPluginOptions} from '../types';
|
||||
import collectRedirects from '../collectRedirects';
|
||||
import normalizePluginOptions from '../normalizePluginOptions';
|
||||
import {removeTrailingSlash} from '../utils';
|
||||
|
||||
function createTestPluginContext(
|
||||
options?: UserPluginOptions,
|
||||
routesPaths: string[] = [],
|
||||
): PluginContext {
|
||||
return {
|
||||
outDir: '/tmp',
|
||||
baseUrl: 'https://docusaurus.io',
|
||||
routesPaths: routesPaths,
|
||||
options: normalizePluginOptions(options),
|
||||
};
|
||||
}
|
||||
|
||||
describe('collectRedirects', () => {
|
||||
test('should collect no redirect for undefined config', () => {
|
||||
expect(
|
||||
collectRedirects(createTestPluginContext(undefined, ['/', '/path'])),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
test('should collect no redirect for empty config', () => {
|
||||
expect(collectRedirects(createTestPluginContext({}))).toEqual([]);
|
||||
});
|
||||
|
||||
test('should collect redirects to html/exe extension', () => {
|
||||
expect(
|
||||
collectRedirects(
|
||||
createTestPluginContext(
|
||||
{
|
||||
fromExtensions: ['html', 'exe'],
|
||||
},
|
||||
['/', '/somePath', '/otherPath.html'],
|
||||
),
|
||||
),
|
||||
).toEqual([
|
||||
{
|
||||
fromRoutePath: '/somePath.html',
|
||||
toRoutePath: '/somePath',
|
||||
},
|
||||
{
|
||||
fromRoutePath: '/somePath.exe',
|
||||
toRoutePath: '/somePath',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('should collect redirects to html/exe extension', () => {
|
||||
expect(
|
||||
collectRedirects(
|
||||
createTestPluginContext(
|
||||
{
|
||||
toExtensions: ['html', 'exe'],
|
||||
},
|
||||
['/', '/somePath', '/otherPath.html'],
|
||||
),
|
||||
),
|
||||
).toEqual([
|
||||
{
|
||||
fromRoutePath: '/otherPath',
|
||||
toRoutePath: '/otherPath.html',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('should collect redirects with custom redirect creator', () => {
|
||||
expect(
|
||||
collectRedirects(
|
||||
createTestPluginContext(
|
||||
{
|
||||
createRedirects: (routePath) => {
|
||||
return [
|
||||
`${removeTrailingSlash(routePath)}/some/path/suffix1`,
|
||||
`${removeTrailingSlash(routePath)}/some/other/path/suffix2`,
|
||||
];
|
||||
},
|
||||
},
|
||||
['/', '/testpath', '/otherPath.html'],
|
||||
),
|
||||
),
|
||||
).toEqual([
|
||||
{
|
||||
fromRoutePath: '/some/path/suffix1',
|
||||
toRoutePath: '/',
|
||||
},
|
||||
{
|
||||
fromRoutePath: '/some/other/path/suffix2',
|
||||
toRoutePath: '/',
|
||||
},
|
||||
|
||||
{
|
||||
fromRoutePath: '/testpath/some/path/suffix1',
|
||||
toRoutePath: '/testpath',
|
||||
},
|
||||
{
|
||||
fromRoutePath: '/testpath/some/other/path/suffix2',
|
||||
toRoutePath: '/testpath',
|
||||
},
|
||||
|
||||
{
|
||||
fromRoutePath: '/otherPath.html/some/path/suffix1',
|
||||
toRoutePath: '/otherPath.html',
|
||||
},
|
||||
{
|
||||
fromRoutePath: '/otherPath.html/some/other/path/suffix2',
|
||||
toRoutePath: '/otherPath.html',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('should filter unwanted redirects', () => {
|
||||
expect(
|
||||
collectRedirects(
|
||||
createTestPluginContext(
|
||||
{
|
||||
fromExtensions: ['html', 'exe'],
|
||||
toExtensions: ['html', 'exe'],
|
||||
},
|
||||
[
|
||||
'/',
|
||||
'/somePath',
|
||||
'/somePath.html',
|
||||
'/somePath.exe',
|
||||
'/fromShouldWork.html',
|
||||
'/toShouldWork',
|
||||
],
|
||||
),
|
||||
),
|
||||
).toEqual([
|
||||
{
|
||||
fromRoutePath: '/toShouldWork.html',
|
||||
toRoutePath: '/toShouldWork',
|
||||
},
|
||||
{
|
||||
fromRoutePath: '/toShouldWork.exe',
|
||||
toRoutePath: '/toShouldWork',
|
||||
},
|
||||
{
|
||||
fromRoutePath: '/fromShouldWork',
|
||||
toRoutePath: '/fromShouldWork.html',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -44,11 +44,11 @@ const createExtensionValidationTests = (
|
|||
});
|
||||
};
|
||||
|
||||
describe('fromExtensionsRedirectCreator', () => {
|
||||
createExtensionValidationTests(fromExtensionsRedirectCreator);
|
||||
describe('toExtensionsRedirectCreator', () => {
|
||||
createExtensionValidationTests(toExtensionsRedirectCreator);
|
||||
|
||||
test('should create redirects from html/htm extensions', () => {
|
||||
const redirectCreator = fromExtensionsRedirectCreator(['html', 'htm']);
|
||||
const redirectCreator = toExtensionsRedirectCreator(['html', 'htm']);
|
||||
expect(redirectCreator('')).toEqual([]);
|
||||
expect(redirectCreator('/')).toEqual([]);
|
||||
expect(redirectCreator('/abc.html')).toEqual(['/abc']);
|
||||
|
@ -57,18 +57,18 @@ describe('fromExtensionsRedirectCreator', () => {
|
|||
});
|
||||
|
||||
test('should not create redirection for an empty extension array', () => {
|
||||
const redirectCreator = fromExtensionsRedirectCreator([]);
|
||||
const redirectCreator = toExtensionsRedirectCreator([]);
|
||||
expect(redirectCreator('')).toEqual([]);
|
||||
expect(redirectCreator('/')).toEqual([]);
|
||||
expect(redirectCreator('/abc.html')).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toExtensionsRedirectCreator', () => {
|
||||
createExtensionValidationTests(toExtensionsRedirectCreator);
|
||||
describe('fromExtensionsRedirectCreator', () => {
|
||||
createExtensionValidationTests(fromExtensionsRedirectCreator);
|
||||
|
||||
test('should create redirects to html/htm extensions', () => {
|
||||
const redirectCreator = toExtensionsRedirectCreator(['html', 'htm']);
|
||||
const redirectCreator = fromExtensionsRedirectCreator(['html', 'htm']);
|
||||
expect(redirectCreator('')).toEqual([]);
|
||||
expect(redirectCreator('/')).toEqual([]);
|
||||
expect(redirectCreator('/abc')).toEqual(['/abc.html', '/abc.htm']);
|
||||
|
@ -77,7 +77,7 @@ describe('toExtensionsRedirectCreator', () => {
|
|||
});
|
||||
|
||||
test('should not create redirection for an empty extension array', () => {
|
||||
const redirectCreator = toExtensionsRedirectCreator([]);
|
||||
const redirectCreator = fromExtensionsRedirectCreator([]);
|
||||
expect(redirectCreator('')).toEqual([]);
|
||||
expect(redirectCreator('/')).toEqual([]);
|
||||
expect(redirectCreator('/abc')).toEqual([]);
|
||||
|
|
|
@ -31,6 +31,8 @@ function filterUnwantedRedirects(
|
|||
redirects: RedirectMetadata[],
|
||||
pluginContext: PluginContext,
|
||||
): RedirectMetadata[] {
|
||||
// TODO how should we warn the user of filtered redirects?
|
||||
|
||||
// we don't want to create twice the same redirect
|
||||
redirects = uniqBy(redirects, (redirect) => redirect.fromRoutePath);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ export default function pluginClientRedirectsPages(
|
|||
async postBuild(props: Props) {
|
||||
const pluginContext: PluginContext = {
|
||||
routesPaths: props.routesPaths,
|
||||
siteConfig: props.siteConfig,
|
||||
baseUrl: props.baseUrl,
|
||||
outDir: props.outDir,
|
||||
options,
|
||||
};
|
||||
|
|
|
@ -38,7 +38,8 @@ const validateExtension = (ext: string) => {
|
|||
|
||||
const addLeadingDot = (extension: string) => `.${extension}`;
|
||||
|
||||
export function fromExtensionsRedirectCreator(
|
||||
// Create new /path that redirects to existing an /path.html
|
||||
export function toExtensionsRedirectCreator(
|
||||
extensions: string[],
|
||||
): RedirectsCreator {
|
||||
extensions.forEach(validateExtension);
|
||||
|
@ -60,7 +61,8 @@ export function fromExtensionsRedirectCreator(
|
|||
};
|
||||
}
|
||||
|
||||
export function toExtensionsRedirectCreator(
|
||||
// Create new /path.html that redirects to existing an /path
|
||||
export function fromExtensionsRedirectCreator(
|
||||
extensions: string[],
|
||||
): RedirectsCreator {
|
||||
extensions.forEach(validateExtension);
|
||||
|
|
|
@ -15,24 +15,24 @@ export type PluginOptions = {
|
|||
|
||||
export type UserPluginOptions = Partial<PluginOptions>;
|
||||
|
||||
// The minimal infos the plugin needs to work
|
||||
export type PluginContext = Pick<
|
||||
Props,
|
||||
'routesPaths' | 'outDir' | 'baseUrl'
|
||||
> & {
|
||||
options: PluginOptions;
|
||||
};
|
||||
|
||||
// For a given existing route path,
|
||||
// return all the paths from which we should redirect from
|
||||
export type RedirectsCreator = (
|
||||
routePath: string,
|
||||
) => string[] | null | undefined;
|
||||
|
||||
// Having an in-memory representation of wanted redirects is easier to test
|
||||
// In-memory representation of redirects we want: easier to test
|
||||
// /!\ easy to be confused: "fromRoutePath" is the new page we should create,
|
||||
// that redirects to "toRoutePath" the existing Docusaurus page
|
||||
export type RedirectMetadata = {
|
||||
fromRoutePath: string;
|
||||
toRoutePath: string;
|
||||
toUrl: string;
|
||||
redirectPageContent: string;
|
||||
redirectAbsoluteFilePath: string;
|
||||
};
|
||||
|
||||
export type PluginContext = Pick<
|
||||
Props,
|
||||
'routesPaths' | 'siteConfig' | 'outDir'
|
||||
> & {
|
||||
options: PluginOptions;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue