feat(client-redirects): make plugin respect onDuplicateRoutes config (#7649)

This commit is contained in:
Joshua Chen 2022-06-22 19:32:02 +08:00 committed by GitHub
parent 51d7899b0d
commit 4b5a47ba37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 13 deletions

View file

@ -9,18 +9,21 @@ import {removeTrailingSlash} from '@docusaurus/utils';
import {normalizePluginOptions} from '@docusaurus/utils-validation'; import {normalizePluginOptions} from '@docusaurus/utils-validation';
import collectRedirects from '../collectRedirects'; import collectRedirects from '../collectRedirects';
import {validateOptions} from '../options'; import {validateOptions} from '../options';
import type {DocusaurusConfig} from '@docusaurus/types';
import type {Options} from '../options'; import type {Options} from '../options';
import type {PluginContext} from '../types'; import type {PluginContext} from '../types';
function createTestPluginContext( function createTestPluginContext(
options?: Options, options?: Options,
relativeRoutesPaths: string[] = [], relativeRoutesPaths: string[] = [],
siteConfig: Partial<DocusaurusConfig> = {},
): PluginContext { ): PluginContext {
return { return {
outDir: '/tmp', outDir: '/tmp',
baseUrl: 'https://docusaurus.io', baseUrl: 'https://docusaurus.io',
relativeRoutesPaths, relativeRoutesPaths,
options: validateOptions({validate: normalizePluginOptions, options}), options: validateOptions({validate: normalizePluginOptions, options}),
siteConfig: {onDuplicateRoutes: 'warn', ...siteConfig} as DocusaurusConfig,
}; };
} }
@ -308,9 +311,10 @@ describe('collectRedirects', () => {
collectRedirects( collectRedirects(
createTestPluginContext( createTestPluginContext(
{ {
createRedirects: (routePath) => { // @ts-expect-error: for test
createRedirects(routePath) {
if (routePath === '/') { if (routePath === '/') {
return [[`/fromPath`]] as unknown as string; return [[`/fromPath`]];
} }
return undefined; return undefined;
}, },
@ -356,4 +360,44 @@ describe('collectRedirects', () => {
}, },
]); ]);
}); });
it('throws when creating duplicate redirect routes and onDuplicateRoutes=throw', () => {
expect(() =>
collectRedirects(
createTestPluginContext(
{
createRedirects() {
return '/random-path';
},
},
['/path-one', '/path-two'],
{onDuplicateRoutes: 'throw'},
),
undefined,
),
).toThrowErrorMatchingInlineSnapshot(`
"@docusaurus/plugin-client-redirects: multiple redirects are created with the same "from" pathname: "/random-path"
It is not possible to redirect the same pathname to multiple destinations:
- {"from":"/random-path","to":"/path-one"}
- {"from":"/random-path","to":"/path-two"}"
`);
expect(() =>
collectRedirects(
createTestPluginContext(
{
redirects: [
{from: '/path-three', to: '/path-one'},
{from: '/path-two', to: '/path-one'},
],
},
['/path-one', '/path-two'],
{onDuplicateRoutes: 'throw'},
),
undefined,
),
).toThrowErrorMatchingInlineSnapshot(`
"@docusaurus/plugin-client-redirects: some redirects would override existing paths, and will be ignored:
- {"from":"/path-two","to":"/path-one"}"
`);
});
}); });

View file

@ -102,8 +102,10 @@ function filterUnwantedRedirects(
Object.entries(_.groupBy(redirects, (redirect) => redirect.from)).forEach( Object.entries(_.groupBy(redirects, (redirect) => redirect.from)).forEach(
([from, groupedFromRedirects]) => { ([from, groupedFromRedirects]) => {
if (groupedFromRedirects.length > 1) { if (groupedFromRedirects.length > 1) {
logger.error`name=${'@docusaurus/plugin-client-redirects'}: multiple redirects are created with the same "from" pathname: path=${from} logger.report(
It is not possible to redirect the same pathname to multiple destinations: ${groupedFromRedirects.map( pluginContext.siteConfig.onDuplicateRoutes,
)`name=${'@docusaurus/plugin-client-redirects'}: multiple redirects are created with the same "from" pathname: path=${from}
It is not possible to redirect the same pathname to multiple destinations:${groupedFromRedirects.map(
(r) => JSON.stringify(r), (r) => JSON.stringify(r),
)}`; )}`;
} }
@ -111,18 +113,18 @@ It is not possible to redirect the same pathname to multiple destinations: ${gro
); );
const collectedRedirects = _.uniqBy(redirects, (redirect) => redirect.from); const collectedRedirects = _.uniqBy(redirects, (redirect) => redirect.from);
// We don't want to override an already existing route with a redirect file! const {false: newRedirects = [], true: redirectsOverridingExistingPath = []} =
const redirectsOverridingExistingPath = collectedRedirects.filter( _.groupBy(collectedRedirects, (redirect) =>
(redirect) => pluginContext.relativeRoutesPaths.includes(redirect.from), pluginContext.relativeRoutesPaths.includes(redirect.from),
); );
if (redirectsOverridingExistingPath.length > 0) { if (redirectsOverridingExistingPath.length > 0) {
logger.error`name=${'@docusaurus/plugin-client-redirects'}: some redirects would override existing paths, and will be ignored: ${redirectsOverridingExistingPath.map( logger.report(
pluginContext.siteConfig.onDuplicateRoutes,
)`name=${'@docusaurus/plugin-client-redirects'}: some redirects would override existing paths, and will be ignored:${redirectsOverridingExistingPath.map(
(r) => JSON.stringify(r), (r) => JSON.stringify(r),
)}`; )}`;
} }
return collectedRedirects.filter( return newRedirects;
(redirect) => !pluginContext.relativeRoutesPaths.includes(redirect.from),
);
} }
function createRedirectsOptionRedirects( function createRedirectsOptionRedirects(

View file

@ -31,6 +31,7 @@ export default function pluginClientRedirectsPages(
baseUrl: props.baseUrl, baseUrl: props.baseUrl,
outDir: props.outDir, outDir: props.outDir,
options, options,
siteConfig: props.siteConfig,
}; };
const redirects: RedirectItem[] = collectRedirects( const redirects: RedirectItem[] = collectRedirects(

View file

@ -11,7 +11,7 @@ import type {PluginOptions} from './options';
/** /**
* The minimal infos the plugin needs to work * The minimal infos the plugin needs to work
*/ */
export type PluginContext = Pick<Props, 'outDir' | 'baseUrl'> & { export type PluginContext = Pick<Props, 'outDir' | 'baseUrl' | 'siteConfig'> & {
options: PluginOptions; options: PluginOptions;
relativeRoutesPaths: string[]; relativeRoutesPaths: string[];
}; };

View file

@ -50,6 +50,12 @@ Accepted fields:
</APITable> </APITable>
``` ```
:::note
This plugin will also read the [`siteConfig.onDuplicateRoutes`](../docusaurus.config.js.md#onDuplicateRoutes) config to adjust its logging level when multiple files will be emitted to the same location.
:::
### Types {#types} ### Types {#types}
#### `RedirectRule` {#RedirectRule} #### `RedirectRule` {#RedirectRule}