From b54ec7238984c0dd65f27b56a28a732c59424f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Wed, 16 Jun 2021 19:04:28 +0200 Subject: [PATCH] fix(v2): redirect plugin: use siteConfig.trailingSlash (#4988) --- .../package.json | 1 + .../writeRedirectFiles.test.ts.snap | 78 +++++++++++++++- .../src/__tests__/collectRedirects.test.ts | 89 ++++++++++++++++++- .../src/__tests__/writeRedirectFiles.test.ts | 61 ++++++++++++- .../src/collectRedirects.ts | 21 ++++- .../src/index.ts | 23 ++++- .../src/writeRedirectFiles.ts | 7 +- .../src/__tests__/applyTrailingSlash.test.ts | 14 ++- .../src/applyTrailingSlash.tsx | 13 ++- .../__tests__/getFilePathForRoutePath.test.ts | 87 ++++++++++++++++++ .../src/__tests__/index.test.ts | 17 ---- .../src/getFilePathForRoutePath.ts | 43 +++++++++ packages/docusaurus-utils/src/index.ts | 7 +- .../server/plugins/applyRouteTrailingSlash.ts | 5 -- website/docusaurus.config.js | 50 +++++------ 15 files changed, 443 insertions(+), 73 deletions(-) create mode 100644 packages/docusaurus-utils/src/__tests__/getFilePathForRoutePath.test.ts create mode 100644 packages/docusaurus-utils/src/getFilePathForRoutePath.ts diff --git a/packages/docusaurus-plugin-client-redirects/package.json b/packages/docusaurus-plugin-client-redirects/package.json index 2315c30cf7da..d675d73a3530 100644 --- a/packages/docusaurus-plugin-client-redirects/package.json +++ b/packages/docusaurus-plugin-client-redirects/package.json @@ -20,6 +20,7 @@ "@docusaurus/core": "2.0.0-beta.0", "@docusaurus/types": "2.0.0-beta.0", "@docusaurus/utils": "2.0.0-beta.0", + "@docusaurus/utils-common": "2.0.0-beta.0", "@docusaurus/utils-validation": "2.0.0-beta.0", "chalk": "^4.1.1", "eta": "^1.11.0", diff --git a/packages/docusaurus-plugin-client-redirects/src/__tests__/__snapshots__/writeRedirectFiles.test.ts.snap b/packages/docusaurus-plugin-client-redirects/src/__tests__/__snapshots__/writeRedirectFiles.test.ts.snap index 09744baefa71..835742061507 100644 --- a/packages/docusaurus-plugin-client-redirects/src/__tests__/__snapshots__/writeRedirectFiles.test.ts.snap +++ b/packages/docusaurus-plugin-client-redirects/src/__tests__/__snapshots__/writeRedirectFiles.test.ts.snap @@ -32,7 +32,83 @@ Array [ ] `; -exports[`toRedirectFilesMetadata should create appropriate metadatas: fileContent 1`] = ` +exports[`toRedirectFilesMetadata should create appropriate metadatas trailingSlash=false: fileContent 1`] = ` +Array [ + " + + + + + + + +", + " + + + + + + + +", + " + + + + + + + +", +] +`; + +exports[`toRedirectFilesMetadata should create appropriate metadatas trailingSlash=true: fileContent 1`] = ` +Array [ + " + + + + + + + +", + " + + + + + + + +", + " + + + + + + + +", +] +`; + +exports[`toRedirectFilesMetadata should create appropriate metadatas trailingSlash=undefined: fileContent 1`] = ` Array [ " 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 8cf956a077c9..1e6f6b209f41 100644 --- a/packages/docusaurus-plugin-client-redirects/src/__tests__/collectRedirects.test.ts +++ b/packages/docusaurus-plugin-client-redirects/src/__tests__/collectRedirects.test.ts @@ -25,12 +25,17 @@ function createTestPluginContext( describe('collectRedirects', () => { test('should collect no redirect for undefined config', () => { expect( - collectRedirects(createTestPluginContext(undefined, ['/', '/path'])), + collectRedirects( + createTestPluginContext(undefined, ['/', '/path']), + undefined, + ), ).toEqual([]); }); test('should collect no redirect for empty config', () => { - expect(collectRedirects(createTestPluginContext({}))).toEqual([]); + expect(collectRedirects(createTestPluginContext({}), undefined)).toEqual( + [], + ); }); test('should collect redirects to html/exe extension', () => { @@ -42,6 +47,7 @@ describe('collectRedirects', () => { }, ['/', '/somePath', '/otherPath.html'], ), + undefined, ), ).toEqual([ { @@ -64,6 +70,7 @@ describe('collectRedirects', () => { }, ['/', '/somePath', '/otherPath.html'], ), + undefined, ), ).toEqual([ { @@ -91,6 +98,79 @@ describe('collectRedirects', () => { }, ['/', '/somePath'], ), + undefined, + ), + ).toEqual([ + { + from: '/someLegacyPath', + to: '/somePath', + }, + { + from: '/someLegacyPathArray1', + to: '/', + }, + { + from: '/someLegacyPathArray2', + to: '/', + }, + ]); + }); + + test('should collect redirects from plugin option redirects with trailingSlash=true', () => { + expect( + collectRedirects( + createTestPluginContext( + { + redirects: [ + { + from: '/someLegacyPath', + to: '/somePath', + }, + { + from: ['/someLegacyPathArray1', '/someLegacyPathArray2'], + to: '/', + }, + ], + }, + ['/', '/somePath/'], + ), + true, + ), + ).toEqual([ + { + from: '/someLegacyPath', + to: '/somePath/', + }, + { + from: '/someLegacyPathArray1', + to: '/', + }, + { + from: '/someLegacyPathArray2', + to: '/', + }, + ]); + }); + + test('should collect redirects from plugin option redirects with trailingSlash=false', () => { + expect( + collectRedirects( + createTestPluginContext( + { + redirects: [ + { + from: '/someLegacyPath', + to: '/somePath/', + }, + { + from: ['/someLegacyPathArray1', '/someLegacyPathArray2'], + to: '/', + }, + ], + }, + ['/', '/somePath'], + ), + false, ), ).toEqual([ { @@ -130,6 +210,7 @@ describe('collectRedirects', () => { }, ['/', '/someExistingPath', '/anotherExistingPath'], ), + undefined, ), ).toThrowErrorMatchingSnapshot(); }); @@ -148,6 +229,7 @@ describe('collectRedirects', () => { }, ['/', '/testpath', '/otherPath.html'], ), + undefined, ), ).toEqual([ { @@ -197,6 +279,7 @@ describe('collectRedirects', () => { }, ['/'], ), + undefined, ), ).toThrowErrorMatchingSnapshot(); }); @@ -215,6 +298,7 @@ describe('collectRedirects', () => { }, ['/'], ), + undefined, ), ).toThrowErrorMatchingSnapshot(); }); @@ -236,6 +320,7 @@ describe('collectRedirects', () => { '/toShouldWork', ], ), + undefined, ), ).toEqual([ { diff --git a/packages/docusaurus-plugin-client-redirects/src/__tests__/writeRedirectFiles.test.ts b/packages/docusaurus-plugin-client-redirects/src/__tests__/writeRedirectFiles.test.ts index 9c9aa007405d..26d33fd51f14 100644 --- a/packages/docusaurus-plugin-client-redirects/src/__tests__/writeRedirectFiles.test.ts +++ b/packages/docusaurus-plugin-client-redirects/src/__tests__/writeRedirectFiles.test.ts @@ -42,7 +42,7 @@ describe('createToUrl', () => { }); describe('toRedirectFilesMetadata', () => { - test('should create appropriate metadatas', async () => { + test('should create appropriate metadatas trailingSlash=undefined', async () => { const pluginContext = { outDir: '/tmp/someFixedOutDir', baseUrl: 'https://docusaurus.io', @@ -55,10 +55,11 @@ describe('toRedirectFilesMetadata', () => { {from: '/xyz', to: '/'}, ], pluginContext, + undefined, ); expect(redirectFiles.map((f) => f.fileAbsolutePath)).toEqual([ - path.join(pluginContext.outDir, '/abc.html/index.html'), + path.join(pluginContext.outDir, '/abc.html'), path.join(pluginContext.outDir, '/def/index.html'), path.join(pluginContext.outDir, '/xyz/index.html'), ]); @@ -68,6 +69,60 @@ describe('toRedirectFilesMetadata', () => { ); }); + test('should create appropriate metadatas trailingSlash=true', async () => { + const pluginContext = { + outDir: '/tmp/someFixedOutDir', + baseUrl: 'https://docusaurus.io', + }; + + const redirectFiles = toRedirectFilesMetadata( + [ + {from: '/abc.html', to: '/abc'}, + {from: '/def', to: '/def.html'}, + {from: '/xyz', to: '/'}, + ], + pluginContext, + true, + ); + + expect(redirectFiles.map((f) => f.fileAbsolutePath)).toEqual([ + path.join(pluginContext.outDir, '/abc.html'), + path.join(pluginContext.outDir, '/def/index.html'), + path.join(pluginContext.outDir, '/xyz/index.html'), + ]); + + expect(redirectFiles.map((f) => f.fileContent)).toMatchSnapshot( + 'fileContent', + ); + }); + + test('should create appropriate metadatas trailingSlash=false', async () => { + const pluginContext = { + outDir: '/tmp/someFixedOutDir', + baseUrl: 'https://docusaurus.io', + }; + + const redirectFiles = toRedirectFilesMetadata( + [ + {from: '/abc.html', to: '/abc'}, + {from: '/def', to: '/def.html'}, + {from: '/xyz', to: '/'}, + ], + pluginContext, + false, + ); + + expect(redirectFiles.map((f) => f.fileAbsolutePath)).toEqual([ + path.join(pluginContext.outDir, '/abc.html'), + path.join(pluginContext.outDir, '/def.html'), + path.join(pluginContext.outDir, '/xyz.html'), + ]); + + expect(redirectFiles.map((f) => f.fileContent)).toMatchSnapshot( + 'fileContent', + ); + }); + test('should create appropriate metadatas for root baseUrl', async () => { const pluginContext = { outDir: '/tmp/someFixedOutDir', @@ -76,6 +131,7 @@ describe('toRedirectFilesMetadata', () => { const redirectFiles = toRedirectFilesMetadata( [{from: '/abc.html', to: '/abc'}], pluginContext, + undefined, ); expect(redirectFiles.map((f) => f.fileContent)).toMatchSnapshot( 'fileContent baseUrl=/', @@ -90,6 +146,7 @@ describe('toRedirectFilesMetadata', () => { const redirectFiles = toRedirectFilesMetadata( [{from: '/abc.html', to: '/abc'}], pluginContext, + undefined, ); expect(redirectFiles.map((f) => f.fileContent)).toMatchSnapshot( 'fileContent baseUrl=empty', diff --git a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts index 599990b2a436..3d33d71cbc6c 100644 --- a/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts +++ b/packages/docusaurus-plugin-client-redirects/src/collectRedirects.ts @@ -17,17 +17,36 @@ import { createToExtensionsRedirects, } from './extensionRedirects'; import {validateRedirect} from './redirectValidation'; +import {applyTrailingSlash} from '@docusaurus/utils-common'; import chalk from 'chalk'; export default function collectRedirects( pluginContext: PluginContext, + trailingSlash: boolean | undefined, ): RedirectMetadata[] { - const redirects = doCollectRedirects(pluginContext); + let redirects = doCollectRedirects(pluginContext); + redirects = applyRedirectsTrailingSlash(redirects, trailingSlash); validateCollectedRedirects(redirects, pluginContext); return filterUnwantedRedirects(redirects, pluginContext); } +// If users wants to redirect to=/abc and they enable trailingSlash=true then +// => we don't want to reject the to=/abc (as only /abc/ is an existing/valid path now) +// => we want to redirect to=/abc/ without the user having to change all its redirect plugin options +// It should be easy to toggle siteConfig.trailingSlash option without having to change other configs +function applyRedirectsTrailingSlash( + redirects: RedirectMetadata[], + trailingSlash: boolean | undefined, +) { + return redirects.map((redirect) => { + return { + ...redirect, + to: applyTrailingSlash(redirect.to, trailingSlash), + }; + }); +} + function validateCollectedRedirects( redirects: RedirectMetadata[], pluginContext: PluginContext, diff --git a/packages/docusaurus-plugin-client-redirects/src/index.ts b/packages/docusaurus-plugin-client-redirects/src/index.ts index a58298162e4d..b399d9d56263 100644 --- a/packages/docusaurus-plugin-client-redirects/src/index.ts +++ b/packages/docusaurus-plugin-client-redirects/src/index.ts @@ -15,13 +15,28 @@ import writeRedirectFiles, { RedirectFileMetadata, } from './writeRedirectFiles'; import {removePrefix, addLeadingSlash} from '@docusaurus/utils'; +import chalk from 'chalk'; export default function pluginClientRedirectsPages( - _context: LoadContext, + context: LoadContext, opts: UserPluginOptions, ): Plugin { + const {trailingSlash} = context.siteConfig; + const options = normalizePluginOptions(opts); + // Special case, when using trailingSlash=false we output /xyz.html files instead of /xyz/index.html + // It makes no sense to use option fromExtensions=["html"]: the redirect files would be the same as the original files + if (options.fromExtensions.includes('html') && trailingSlash === false) { + console.warn( + chalk.yellow(`Using the Docusaurus redirect plugin with fromExtensions=['html'] and siteConfig.trailingSlash=false is prevented. +It would lead the redirect plugin to override all the page.html files created by Docusaurus.`), + ); + options.fromExtensions = options.fromExtensions.filter( + (ext) => ext !== 'html', + ); + } + return { name: 'docusaurus-plugin-client-redirects', async postBuild(props: Props) { @@ -34,11 +49,15 @@ export default function pluginClientRedirectsPages( options, }; - const redirects: RedirectMetadata[] = collectRedirects(pluginContext); + const redirects: RedirectMetadata[] = collectRedirects( + pluginContext, + trailingSlash, + ); const redirectFiles: RedirectFileMetadata[] = toRedirectFilesMetadata( redirects, pluginContext, + trailingSlash, ); // Write files only at the end: make code more easy to test without IO diff --git a/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts b/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts index 93ebf72b2a6e..0fe6db4ec002 100644 --- a/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts +++ b/packages/docusaurus-plugin-client-redirects/src/writeRedirectFiles.ts @@ -27,6 +27,7 @@ export function createToUrl(baseUrl: string, to: string): string { export function toRedirectFilesMetadata( redirects: RedirectMetadata[], pluginContext: WriteFilesPluginContext, + trailingSlash: boolean | undefined, ): RedirectFileMetadata[] { // Perf: avoid rendering the template twice with the exact same "props" // We might create multiple redirect pages for the same destination url @@ -36,10 +37,8 @@ export function toRedirectFilesMetadata( }); const createFileMetadata = (redirect: RedirectMetadata) => { - const fileAbsolutePath = path.join( - pluginContext.outDir, - getFilePathForRoutePath(redirect.from), - ); + const filePath = getFilePathForRoutePath(redirect.from, trailingSlash); + const fileAbsolutePath = path.join(pluginContext.outDir, filePath); const toUrl = createToUrl(pluginContext.baseUrl, redirect.to); const fileContent = createPageContentMemoized(toUrl); return { diff --git a/packages/docusaurus-utils-common/src/__tests__/applyTrailingSlash.test.ts b/packages/docusaurus-utils-common/src/__tests__/applyTrailingSlash.test.ts index 28e7ddac614f..1123bd4a4853 100644 --- a/packages/docusaurus-utils-common/src/__tests__/applyTrailingSlash.test.ts +++ b/packages/docusaurus-utils-common/src/__tests__/applyTrailingSlash.test.ts @@ -14,10 +14,20 @@ describe('applyTrailingSlash', () => { expect(applyTrailingSlash('', undefined)).toEqual(''); }); - test('should apply to /', () => { + test('should not apply to /', () => { expect(applyTrailingSlash('/', true)).toEqual('/'); - expect(applyTrailingSlash('/', false)).toEqual(''); + expect(applyTrailingSlash('/', false)).toEqual('/'); expect(applyTrailingSlash('/', undefined)).toEqual('/'); + + expect(applyTrailingSlash('/?query#anchor', true)).toEqual( + '/?query#anchor', + ); + expect(applyTrailingSlash('/?query#anchor', false)).toEqual( + '/?query#anchor', + ); + expect(applyTrailingSlash('/?query#anchor', undefined)).toEqual( + '/?query#anchor', + ); }); test('should not apply to #anchor links ', () => { diff --git a/packages/docusaurus-utils-common/src/applyTrailingSlash.tsx b/packages/docusaurus-utils-common/src/applyTrailingSlash.tsx index fb3fb9bf854e..6ae665064261 100644 --- a/packages/docusaurus-utils-common/src/applyTrailingSlash.tsx +++ b/packages/docusaurus-utils-common/src/applyTrailingSlash.tsx @@ -9,8 +9,8 @@ export default function applyTrailingSlash( path: string, trailingSlash: boolean | undefined, ): string { - // Never apply trailing slash to an anchor link if (path.startsWith('#')) { + // Never apply trailing slash to an anchor link return path; } @@ -29,8 +29,13 @@ export default function applyTrailingSlash( // The trailing slash should be handled before the ?search#hash ! const [pathname] = path.split(/[#?]/); - const newPathname = trailingSlash - ? addTrailingSlash(pathname) - : removeTrailingSlash(pathname); + + // Never transform '/' to '' + const newPathname = + pathname === '/' + ? '/' + : trailingSlash + ? addTrailingSlash(pathname) + : removeTrailingSlash(pathname); return path.replace(pathname, newPathname); } diff --git a/packages/docusaurus-utils/src/__tests__/getFilePathForRoutePath.test.ts b/packages/docusaurus-utils/src/__tests__/getFilePathForRoutePath.test.ts new file mode 100644 index 000000000000..a2225a2ce388 --- /dev/null +++ b/packages/docusaurus-utils/src/__tests__/getFilePathForRoutePath.test.ts @@ -0,0 +1,87 @@ +/** + * 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 {getFilePathForRoutePath} from '../getFilePathForRoutePath'; +import {posixPath} from '../posixPath'; + +describe('getFilePathForRoutePath trailingSlash=undefined', () => { + test('works for /', () => { + expect(posixPath(getFilePathForRoutePath('/', undefined))).toEqual( + '/index.html', + ); + }); + + test('works for /somePath', () => { + expect(posixPath(getFilePathForRoutePath('/somePath', undefined))).toEqual( + '/somePath/index.html', + ); + }); + + test('works for /somePath/', () => { + expect(posixPath(getFilePathForRoutePath('/somePath/', undefined))).toEqual( + '/somePath/index.html', + ); + }); + + test('works for /somePath/xyz.html', () => { + expect( + posixPath(getFilePathForRoutePath('/somePath/xyz.html', undefined)), + ).toEqual('/somePath/xyz.html'); + }); +}); + +describe('getFilePathForRoutePath trailingSlash=true', () => { + test('works for /', () => { + expect(posixPath(getFilePathForRoutePath('/', true))).toEqual( + '/index.html', + ); + }); + + test('works for /somePath', () => { + expect(posixPath(getFilePathForRoutePath('/somePath', true))).toEqual( + '/somePath/index.html', + ); + }); + + test('works for /somePath/', () => { + expect(posixPath(getFilePathForRoutePath('/somePath/', true))).toEqual( + '/somePath/index.html', + ); + }); + + test('works for /somePath/xyz.html', () => { + expect( + posixPath(getFilePathForRoutePath('/somePath/xyz.html', true)), + ).toEqual('/somePath/xyz.html'); + }); +}); + +describe('getFilePathForRoutePath trailingSlash=false', () => { + test('works for /', () => { + expect(posixPath(getFilePathForRoutePath('/', false))).toEqual( + '/index.html', + ); + }); + + test('works for /somePath', () => { + expect(posixPath(getFilePathForRoutePath('/somePath', false))).toEqual( + '/somePath.html', + ); + }); + + test('works for /somePath/', () => { + expect(posixPath(getFilePathForRoutePath('/somePath/', false))).toEqual( + '/somePath/index.html', + ); + }); + + test('works for /somePath/xyz.html', () => { + expect( + posixPath(getFilePathForRoutePath('/somePath/xyz.html', false)), + ).toEqual('/somePath/xyz.html'); + }); +}); diff --git a/packages/docusaurus-utils/src/__tests__/index.test.ts b/packages/docusaurus-utils/src/__tests__/index.test.ts index 17bf9e077a8d..f80cc2b796e5 100644 --- a/packages/docusaurus-utils/src/__tests__/index.test.ts +++ b/packages/docusaurus-utils/src/__tests__/index.test.ts @@ -21,7 +21,6 @@ import { removeTrailingSlash, removeSuffix, removePrefix, - getFilePathForRoutePath, addLeadingSlash, getElementsAround, mergeTranslations, @@ -401,22 +400,6 @@ describe('removePrefix', () => { }); }); -describe('getFilePathForRoutePath', () => { - test('works for /', () => { - expect(posixPath(getFilePathForRoutePath('/'))).toEqual('/index.html'); - }); - test('works for /somePath', () => { - expect(posixPath(getFilePathForRoutePath('/somePath'))).toEqual( - '/somePath/index.html', - ); - }); - test('works for /somePath/', () => { - expect(posixPath(getFilePathForRoutePath('/somePath/'))).toEqual( - '/somePath/index.html', - ); - }); -}); - describe('getElementsAround', () => { test('can return elements around', () => { expect(getElementsAround(['a', 'b', 'c', 'd'], 0)).toEqual({ diff --git a/packages/docusaurus-utils/src/getFilePathForRoutePath.ts b/packages/docusaurus-utils/src/getFilePathForRoutePath.ts new file mode 100644 index 000000000000..437ece69f535 --- /dev/null +++ b/packages/docusaurus-utils/src/getFilePathForRoutePath.ts @@ -0,0 +1,43 @@ +/** + * 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'; + +/* +export function getFilePathForRoutePath(routePath: string): string { + const fileName = path.basename(routePath); + const filePath = path.dirname(routePath); + return path.join(filePath, `${fileName}/index.html`); +} + */ + +// Almost exact copy of the behavior we implemented in our Docusaurus fork of the webpack static gen plugin +// See https://github.com/slorber/static-site-generator-webpack-plugin/blob/master/index.js#L167 +export function getFilePathForRoutePath( + routePath: string, + trailingSlash: boolean | undefined, +): string { + // const outputFileName = routePath.replace(/^(\/|\\)/, ''); // Remove leading slashes for webpack-dev-server + + // Paths ending with .html are left untouched + if (/\.(html?)$/i.test(routePath)) { + return routePath; + } + + // Legacy retro-compatible behavior + if (typeof trailingSlash === 'undefined') { + return path.join(routePath, 'index.html'); + } + + // New behavior: we can say if we prefer file/folder output + // Useful resource: https://github.com/slorber/trailing-slash-guide + if (routePath === '' || routePath.endsWith('/') || trailingSlash) { + return path.join(routePath, 'index.html'); + } else { + return `${routePath}.html`; + } +} diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index 638d0a34b0ec..376051f2d767 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -27,6 +27,7 @@ import {docuHash} from './docuHash'; export const posixPath = posixPathImport; +export * from './getFilePathForRoutePath'; export * from './codeTranslationsUtils'; export * from './markdownParser'; export * from './markdownLinks'; @@ -325,12 +326,6 @@ export function removePrefix(str: string, prefix: string): string { return str.startsWith(prefix) ? str.slice(prefix.length) : str; } -export function getFilePathForRoutePath(routePath: string): string { - const fileName = path.basename(routePath); - const filePath = path.dirname(routePath); - return path.join(filePath, `${fileName}/index.html`); -} - export function getElementsAround( array: T[], aroundIndex: number, diff --git a/packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts b/packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts index acac5aac53bf..b625a8e9e2a7 100644 --- a/packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts +++ b/packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts @@ -12,11 +12,6 @@ export default function applyRouteTrailingSlash( route: RouteConfig, trailingSlash: boolean | undefined, ) { - // Never transform "/" to "" => cause router issues ("" catch everything) - if (route.path === '/') { - return route; - } - return { ...route, path: applyTrailingSlash(route.path, trailingSlash), diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index d86669a94f32..b142d0109c0c 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -132,34 +132,30 @@ const isVersioningDisabled = !!process.env.DISABLE_VERSIONING || isI18nStaging; ], [ '@docusaurus/plugin-client-redirects', - isDeployPreview - ? // Plugin is disabled for deploy preview because we use trailing slashes on deploy previews - // This plugin is sensitive to trailing slashes, and we don't care much about making it work on deploy previews - {} - : { - fromExtensions: ['html'], - createRedirects: function (path) { - // redirect to /docs from /docs/introduction, - // as introduction has been made the home doc - if (allDocHomesPaths.includes(path)) { - return [`${path}/introduction`]; - } - }, - redirects: [ - { - from: ['/docs/support', '/docs/next/support'], - to: '/community/support', - }, - { - from: ['/docs/team', '/docs/next/team'], - to: '/community/team', - }, - { - from: ['/docs/resources', '/docs/next/resources'], - to: '/community/resources', - }, - ], + { + fromExtensions: ['html'], + createRedirects: function (path) { + // redirect to /docs from /docs/introduction, + // as introduction has been made the home doc + if (allDocHomesPaths.includes(path)) { + return [`${path}/introduction`]; + } + }, + redirects: [ + { + from: ['/docs/support', '/docs/next/support'], + to: '/community/support', }, + { + from: ['/docs/team', '/docs/next/team'], + to: '/community/team', + }, + { + from: ['/docs/resources', '/docs/next/resources'], + to: '/community/resources', + }, + ], + }, ], [ '@docusaurus/plugin-ideal-image',