fix(v2): fix redirect plugin when trailingSlash=false for .html extension (#5102)

* another redirect plugin fix when trailingSlash=false

* add comment
This commit is contained in:
Sébastien Lorber 2021-06-30 17:22:51 +02:00 committed by GitHub
parent 1ec2c95e3d
commit 15a2b59f9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 19 deletions

View file

@ -113,7 +113,8 @@ describe('toRedirectFilesMetadata', () => {
); );
expect(redirectFiles.map((f) => f.fileAbsolutePath)).toEqual([ expect(redirectFiles.map((f) => f.fileAbsolutePath)).toEqual([
path.join(pluginContext.outDir, '/abc.html/index.html'), // path.join(pluginContext.outDir, '/abc.html/index.html'), // Can't be used because /abc.html already exists, and file/folder can't share same name on Unix!
path.join(pluginContext.outDir, '/abc.html.html'), // Weird but on purpose!
path.join(pluginContext.outDir, '/def/index.html'), path.join(pluginContext.outDir, '/def/index.html'),
path.join(pluginContext.outDir, '/xyz/index.html'), path.join(pluginContext.outDir, '/xyz/index.html'),
]); ]);

View file

@ -24,22 +24,32 @@ export function createToUrl(baseUrl: string, to: string): string {
return normalizeUrl([baseUrl, to]); return normalizeUrl([baseUrl, to]);
} }
// if the target path is /xyz, with file /xyz/index.html // Create redirect file path
// we don't want the redirect file to be /xyz.html // Make sure this path has lower precedence over the original file path when served by host providers!
// otherwise it could be picked in priority and the redirect file would redirect to itself // Otherwise it can produce infinite redirect loops!
// This can potentially create an infinite loop (depends on host, like Netlify)
// //
// We prefer the redirect file to be /xyz.html/index.html, as it has lower serving priority for most static hosting tools // See https://github.com/facebook/docusaurus/issues/5055
// It is also the historical behavior of this plugin and nobody complained // See https://github.com/facebook/docusaurus/pull/5085
// See also https://github.com/facebook/docusaurus/issues/5055#issuecomment-870731207 // See https://github.com/facebook/docusaurus/pull/5102
// See also PR reverting to historical behavior: https://github.com/facebook/docusaurus/pull/5085 function getRedirectFilePath(
function getRedirectFilePathForRoutePath( fromPath: string,
routePath: string, trailingSlash: boolean | undefined, // Now unused, on purpose
_trailingSlash: boolean | undefined, // Now unused, on purpose
): string { ): string {
const fileName = path.basename(routePath); const fileName = path.basename(fromPath);
const filePath = path.dirname(routePath); const filePath = path.dirname(fromPath);
// Edge case for https://github.com/facebook/docusaurus/pull/5102
// If the redirect source path is /xyz, with file /xyz.html
// We can't write the redirect file at /xyz.html/index.html because for Unix FS, a file/folder can't have the same name "xyz.html"
// The only possible solution for a redirect file is thus /xyz.html.html (I know, looks suspicious)
if (trailingSlash === false && fileName.endsWith('.html')) {
return path.join(filePath, `${fileName}.html`);
}
// If the target path is /xyz, with file /xyz/index.html, we don't want the redirect file to be /xyz.html
// otherwise it would be picked in priority and the redirect file would redirect to itself
// We prefer the redirect file to be /xyz.html/index.html, served with lower priority for most static hosting tools
else {
return path.join(filePath, `${fileName}/index.html`); return path.join(filePath, `${fileName}/index.html`);
}
} }
export function toRedirectFilesMetadata( export function toRedirectFilesMetadata(
@ -55,10 +65,7 @@ export function toRedirectFilesMetadata(
}); });
const createFileMetadata = (redirect: RedirectMetadata) => { const createFileMetadata = (redirect: RedirectMetadata) => {
const fileRelativePath = getRedirectFilePathForRoutePath( const fileRelativePath = getRedirectFilePath(redirect.from, trailingSlash);
redirect.from,
trailingSlash,
);
const fileAbsolutePath = path.join(pluginContext.outDir, fileRelativePath); const fileAbsolutePath = path.join(pluginContext.outDir, fileRelativePath);
const toUrl = createToUrl(pluginContext.baseUrl, redirect.to); const toUrl = createToUrl(pluginContext.baseUrl, redirect.to);
const fileContent = createPageContentMemoized(toUrl); const fileContent = createPageContentMemoized(toUrl);