diff --git a/packages/docusaurus-plugin-client-redirects/src/__tests__/collectRedirects.test.ts b/packages/docusaurus-plugin-client-redirects/src/__tests__/collectRedirects.test.ts index fc82c12a37fa..e9a200c98943 100644 --- a/packages/docusaurus-plugin-client-redirects/src/__tests__/collectRedirects.test.ts +++ b/packages/docusaurus-plugin-client-redirects/src/__tests__/collectRedirects.test.ts @@ -9,18 +9,21 @@ import {removeTrailingSlash} from '@docusaurus/utils'; import {normalizePluginOptions} from '@docusaurus/utils-validation'; import collectRedirects from '../collectRedirects'; import {validateOptions} from '../options'; +import type {DocusaurusConfig} from '@docusaurus/types'; import type {Options} from '../options'; import type {PluginContext} from '../types'; function createTestPluginContext( options?: Options, relativeRoutesPaths: string[] = [], + siteConfig: Partial = {}, ): PluginContext { return { outDir: '/tmp', baseUrl: 'https://docusaurus.io', relativeRoutesPaths, options: validateOptions({validate: normalizePluginOptions, options}), + siteConfig: {onDuplicateRoutes: 'warn', ...siteConfig} as DocusaurusConfig, }; } @@ -308,9 +311,10 @@ describe('collectRedirects', () => { collectRedirects( createTestPluginContext( { - createRedirects: (routePath) => { + // @ts-expect-error: for test + createRedirects(routePath) { if (routePath === '/') { - return [[`/fromPath`]] as unknown as string; + return [[`/fromPath`]]; } 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"}" + `); + }); }); diff --git a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts index 3cd0db4096cd..605a2b4af75f 100644 --- a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts +++ b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts @@ -102,8 +102,10 @@ function filterUnwantedRedirects( Object.entries(_.groupBy(redirects, (redirect) => redirect.from)).forEach( ([from, groupedFromRedirects]) => { if (groupedFromRedirects.length > 1) { - logger.error`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( + logger.report( + 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), )}`; } @@ -111,18 +113,18 @@ It is not possible to redirect the same pathname to multiple destinations: ${gro ); const collectedRedirects = _.uniqBy(redirects, (redirect) => redirect.from); - // We don't want to override an already existing route with a redirect file! - const redirectsOverridingExistingPath = collectedRedirects.filter( - (redirect) => pluginContext.relativeRoutesPaths.includes(redirect.from), - ); + const {false: newRedirects = [], true: redirectsOverridingExistingPath = []} = + _.groupBy(collectedRedirects, (redirect) => + pluginContext.relativeRoutesPaths.includes(redirect.from), + ); 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), )}`; } - return collectedRedirects.filter( - (redirect) => !pluginContext.relativeRoutesPaths.includes(redirect.from), - ); + return newRedirects; } function createRedirectsOptionRedirects( diff --git a/packages/docusaurus-plugin-client-redirects/src/index.ts b/packages/docusaurus-plugin-client-redirects/src/index.ts index fa96902d19e5..5b64560bac04 100644 --- a/packages/docusaurus-plugin-client-redirects/src/index.ts +++ b/packages/docusaurus-plugin-client-redirects/src/index.ts @@ -31,6 +31,7 @@ export default function pluginClientRedirectsPages( baseUrl: props.baseUrl, outDir: props.outDir, options, + siteConfig: props.siteConfig, }; const redirects: RedirectItem[] = collectRedirects( diff --git a/packages/docusaurus-plugin-client-redirects/src/types.ts b/packages/docusaurus-plugin-client-redirects/src/types.ts index 110e189c2f48..9492f0e3ecc0 100644 --- a/packages/docusaurus-plugin-client-redirects/src/types.ts +++ b/packages/docusaurus-plugin-client-redirects/src/types.ts @@ -11,7 +11,7 @@ import type {PluginOptions} from './options'; /** * The minimal infos the plugin needs to work */ -export type PluginContext = Pick & { +export type PluginContext = Pick & { options: PluginOptions; relativeRoutesPaths: string[]; }; diff --git a/website/docs/api/plugins/plugin-client-redirects.md b/website/docs/api/plugins/plugin-client-redirects.md index 8a1f161d1ccf..a24ac3e24b84 100644 --- a/website/docs/api/plugins/plugin-client-redirects.md +++ b/website/docs/api/plugins/plugin-client-redirects.md @@ -50,6 +50,12 @@ Accepted fields: ``` +:::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} #### `RedirectRule` {#RedirectRule}