mirror of
https://github.com/facebook/docusaurus.git
synced 2025-12-31 07:32:53 +00:00
split collectRedirects and writeRedirectFiles in separate files
This commit is contained in:
parent
2695548b93
commit
9579ac10fc
|
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import {flatten} from 'lodash';
|
||||
import {
|
||||
RedirectsCreator,
|
||||
PluginContext,
|
||||
RedirectMetadata,
|
||||
PluginOptions,
|
||||
} from './types';
|
||||
import createRedirectPageContent from './createRedirectPageContent';
|
||||
import {addTrailingSlash, getFilePathForRoutePath} from './utils';
|
||||
import {
|
||||
fromExtensionsRedirectCreator,
|
||||
toExtensionsRedirectCreator,
|
||||
} from './redirectCreators';
|
||||
|
||||
export default function collectRedirects(
|
||||
pluginContext: PluginContext,
|
||||
): RedirectMetadata[] {
|
||||
const redirectsCreators: RedirectsCreator[] = buildRedirectCreators(
|
||||
pluginContext.options,
|
||||
);
|
||||
|
||||
return flatten(
|
||||
redirectsCreators.map((redirectCreator) => {
|
||||
return createRoutesPathsRedirects(redirectCreator, pluginContext);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function buildRedirectCreators(options: PluginOptions): RedirectsCreator[] {
|
||||
const noopRedirectCreator: RedirectsCreator = (_routePath: string) => [];
|
||||
return [
|
||||
fromExtensionsRedirectCreator(options.fromExtensions),
|
||||
toExtensionsRedirectCreator(options.toExtensions),
|
||||
options.createRedirects ?? noopRedirectCreator,
|
||||
];
|
||||
}
|
||||
|
||||
// Create all redirects for a list of route path
|
||||
function createRoutesPathsRedirects(
|
||||
redirectCreator: RedirectsCreator,
|
||||
pluginContext: PluginContext,
|
||||
): RedirectMetadata[] {
|
||||
return flatten(
|
||||
pluginContext.routesPaths.map((routePath) =>
|
||||
createRoutePathRedirects(routePath, redirectCreator, pluginContext),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Create all redirects for a single route path
|
||||
function createRoutePathRedirects(
|
||||
routePath: string,
|
||||
redirectCreator: RedirectsCreator,
|
||||
{siteConfig, outDir}: PluginContext,
|
||||
): RedirectMetadata[] {
|
||||
// TODO do we receive absolute urls???
|
||||
if (!path.isAbsolute(routePath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// TODO addTrailingSlash ?
|
||||
const toUrl = addTrailingSlash(`${siteConfig.url}${routePath}`);
|
||||
|
||||
const redirectPageContent = createRedirectPageContent({toUrl});
|
||||
|
||||
const fromRoutePaths: string[] = redirectCreator(routePath) ?? [];
|
||||
|
||||
return fromRoutePaths.map((fromRoutePath) => {
|
||||
const redirectAbsoluteFilePath = path.join(
|
||||
outDir,
|
||||
getFilePathForRoutePath(fromRoutePath),
|
||||
);
|
||||
return {
|
||||
fromRoutePath,
|
||||
toRoutePath: routePath,
|
||||
toUrl,
|
||||
redirectPageContent,
|
||||
redirectAbsoluteFilePath,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
@ -5,137 +5,33 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import {flatten} from 'lodash';
|
||||
|
||||
import {LoadContext, Plugin, Props} from '@docusaurus/types';
|
||||
import {UserPluginOptions, PluginContext, RedirectMetadata} from './types';
|
||||
|
||||
import {PluginOptions, UserPluginOptions, RedirectsCreator} from './types';
|
||||
import createRedirectPageContent from './createRedirectPageContent';
|
||||
import normalizePluginOptions from './normalizePluginOptions';
|
||||
import {addTrailingSlash, getFilePathForRoutePath} from './utils';
|
||||
import {
|
||||
fromExtensionsRedirectCreator,
|
||||
toExtensionsRedirectCreator,
|
||||
} from './redirectCreators';
|
||||
|
||||
type RedirectMetadata = {
|
||||
fromRoutePath: string;
|
||||
toRoutePath: string;
|
||||
toUrl: string;
|
||||
redirectPageContent: string;
|
||||
redirectAbsoluteFilePath: string;
|
||||
};
|
||||
|
||||
type PluginContext = {
|
||||
props: Props;
|
||||
options: PluginOptions;
|
||||
redirectsCreators: RedirectsCreator[];
|
||||
};
|
||||
import collectRedirects from './collectRedirects';
|
||||
import writeRedirectFiles from './writeRedirectFiles';
|
||||
|
||||
export default function pluginClientRedirectsPages(
|
||||
_context: LoadContext,
|
||||
opts: UserPluginOptions,
|
||||
): Plugin<unknown> {
|
||||
const options = normalizePluginOptions(opts);
|
||||
|
||||
return {
|
||||
name: 'docusaurus-plugin-client-redirects',
|
||||
async postBuild(props: Props) {
|
||||
const redirectsCreators: RedirectsCreator[] = buildRedirectCreators(
|
||||
const pluginContext: PluginContext = {
|
||||
routesPaths: props.routesPaths,
|
||||
siteConfig: props.siteConfig,
|
||||
outDir: props.outDir,
|
||||
options,
|
||||
);
|
||||
};
|
||||
|
||||
const pluginContext: PluginContext = {props, options, redirectsCreators};
|
||||
|
||||
// Process in 2 steps, to make code more easy to test
|
||||
const redirects: RedirectMetadata[] = collectRoutePathRedirects(
|
||||
pluginContext,
|
||||
);
|
||||
|
||||
console.log('redirects=', redirects);
|
||||
const redirects: RedirectMetadata[] = collectRedirects(pluginContext);
|
||||
|
||||
// Write files only at the end: make code more easy to test without IO
|
||||
await writeRedirectFiles(redirects);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function buildRedirectCreators(options: PluginOptions): RedirectsCreator[] {
|
||||
const noopRedirectCreator: RedirectsCreator = (_routePath: string) => [];
|
||||
return [
|
||||
fromExtensionsRedirectCreator(options.fromExtensions),
|
||||
toExtensionsRedirectCreator(options.toExtensions),
|
||||
options.createRedirects ?? noopRedirectCreator,
|
||||
];
|
||||
}
|
||||
|
||||
function collectRoutePathRedirects(
|
||||
pluginContext: PluginContext,
|
||||
): RedirectMetadata[] {
|
||||
return flatten(
|
||||
pluginContext.redirectsCreators.map((redirectCreator) => {
|
||||
return createRoutesPathsRedirects(redirectCreator, pluginContext);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// Create all redirects for a list of route path
|
||||
function createRoutesPathsRedirects(
|
||||
redirectCreator: RedirectsCreator,
|
||||
pluginContext: PluginContext,
|
||||
): RedirectMetadata[] {
|
||||
return flatten(
|
||||
pluginContext.props.routesPaths.map((routePath) =>
|
||||
createRoutePathRedirects(routePath, redirectCreator, pluginContext),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Create all redirects for a single route path
|
||||
function createRoutePathRedirects(
|
||||
routePath: string,
|
||||
redirectCreator: RedirectsCreator,
|
||||
{props}: PluginContext,
|
||||
): RedirectMetadata[] {
|
||||
const {siteConfig, outDir} = props;
|
||||
|
||||
// TODO do we receive absolute urls???
|
||||
if (!path.isAbsolute(routePath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// TODO addTrailingSlash ?
|
||||
const toUrl = addTrailingSlash(`${siteConfig.url}${routePath}`);
|
||||
|
||||
const redirectPageContent = createRedirectPageContent({toUrl});
|
||||
|
||||
const fromRoutePaths: string[] = redirectCreator(routePath) ?? [];
|
||||
|
||||
return fromRoutePaths.map((fromRoutePath) => {
|
||||
const redirectAbsoluteFilePath = path.join(
|
||||
outDir,
|
||||
getFilePathForRoutePath(fromRoutePath),
|
||||
);
|
||||
return {
|
||||
fromRoutePath,
|
||||
toRoutePath: routePath,
|
||||
toUrl,
|
||||
redirectPageContent,
|
||||
redirectAbsoluteFilePath,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function writeRedirectFiles(redirects: RedirectMetadata[]) {
|
||||
async function writeRedirectFile(redirect: RedirectMetadata) {
|
||||
try {
|
||||
await fs.writeFile(
|
||||
redirect.redirectAbsoluteFilePath,
|
||||
redirect.redirectPageContent,
|
||||
);
|
||||
} catch (err) {
|
||||
throw new Error(`Redirect file creation error: ${err}`);
|
||||
}
|
||||
}
|
||||
await Promise.all(redirects.map(writeRedirectFile));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Props} from '@docusaurus/types';
|
||||
|
||||
export type PluginOptions = {
|
||||
fromExtensions: string[];
|
||||
toExtensions: string[];
|
||||
|
|
@ -18,3 +20,19 @@ export type UserPluginOptions = Partial<PluginOptions>;
|
|||
export type RedirectsCreator = (
|
||||
routePath: string,
|
||||
) => string[] | null | undefined;
|
||||
|
||||
// Having an in-memory representation of wanted redirects is easier to test
|
||||
export type RedirectMetadata = {
|
||||
fromRoutePath: string;
|
||||
toRoutePath: string;
|
||||
toUrl: string;
|
||||
redirectPageContent: string;
|
||||
redirectAbsoluteFilePath: string;
|
||||
};
|
||||
|
||||
export type PluginContext = Pick<
|
||||
Props,
|
||||
'routesPaths' | 'siteConfig' | 'outDir'
|
||||
> & {
|
||||
options: PluginOptions;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import {RedirectMetadata} from './types';
|
||||
|
||||
type RedirectFile = Pick<
|
||||
RedirectMetadata,
|
||||
'redirectAbsoluteFilePath' | 'redirectPageContent'
|
||||
>;
|
||||
|
||||
export default async function writeRedirectFiles(redirects: RedirectFile[]) {
|
||||
async function writeRedirectFile(redirect: RedirectFile) {
|
||||
try {
|
||||
await fs.writeFile(
|
||||
redirect.redirectAbsoluteFilePath,
|
||||
redirect.redirectPageContent,
|
||||
);
|
||||
} catch (err) {
|
||||
throw new Error(`Redirect file creation error: ${err}`);
|
||||
}
|
||||
}
|
||||
await Promise.all(redirects.map(writeRedirectFile));
|
||||
}
|
||||
Loading…
Reference in New Issue