diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md new file mode 100644 index 000000000000..a3fa2f34fc9a --- /dev/null +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md @@ -0,0 +1,5 @@ +--- +slug: docWithSlug.html +--- + +Lorem diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap index e0b2dfecb78f..c96321e08fd9 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap @@ -29,7 +29,7 @@ Object { "type": "link", }, Object { - "href": "/docs", + "href": "/docs/", "label": "Hello, World !", "type": "link", }, @@ -41,7 +41,7 @@ Object { "collapsed": true, "items": Array [ Object { - "href": "/docs", + "href": "/docs/", "label": "Hello, World !", "type": "link", }, @@ -57,21 +57,21 @@ exports[`simple website content 2`] = ` Array [ Object { "component": "@theme/DocPage", - "exact": true, - "modules": Object { - "content": "@site/docs/hello.md", - "docsMetadata": "~docs/site-docs-hello-md-9df-base.json", - }, - "path": "/docs", - }, - Object { - "component": "@theme/DocPage", + "exact": false, "modules": Object { "docsMetadata": "~docs/docs-route-ff2.json", }, - "path": "/docs/:route", + "path": "/docs", "priority": undefined, "routes": Array [ + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/docs/hello.md", + }, + "path": "/docs/", + }, Object { "component": "@theme/DocItem", "exact": true, @@ -123,39 +123,21 @@ exports[`versioned website content 1`] = ` Array [ Object { "component": "@theme/DocPage", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-1.0.1/hello.md", - "docsMetadata": "~docs/site-versioned-docs-version-1-0-1-hello-md-0c7-base.json", - }, - "path": "/docs", - }, - Object { - "component": "@theme/DocPage", - "exact": true, - "modules": Object { - "content": "@site/versioned_docs/version-1.0.0/hello.md", - "docsMetadata": "~docs/site-versioned-docs-version-1-0-0-hello-md-3ef-base.json", - }, - "path": "/docs/1.0.0", - }, - Object { - "component": "@theme/DocPage", - "exact": true, - "modules": Object { - "content": "@site/docs/hello.md", - "docsMetadata": "~docs/site-docs-hello-md-9df-base.json", - }, - "path": "/docs/next", - }, - Object { - "component": "@theme/DocPage", + "exact": false, "modules": Object { "docsMetadata": "~docs/docs-1-0-0-route-660.json", }, - "path": "/docs/1.0.0/:route", + "path": "/docs/1.0.0", "priority": undefined, "routes": Array [ + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-1.0.0/hello.md", + }, + "path": "/docs/1.0.0/", + }, Object { "component": "@theme/DocItem", "exact": true, @@ -176,12 +158,21 @@ Array [ }, Object { "component": "@theme/DocPage", + "exact": false, "modules": Object { "docsMetadata": "~docs/docs-next-route-1c8.json", }, - "path": "/docs/next/:route", + "path": "/docs/next", "priority": undefined, "routes": Array [ + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/docs/hello.md", + }, + "path": "/docs/next/", + }, Object { "component": "@theme/DocItem", "exact": true, @@ -194,12 +185,21 @@ Array [ }, Object { "component": "@theme/DocPage", + "exact": false, "modules": Object { "docsMetadata": "~docs/docs-route-ff2.json", }, - "path": "/docs/:route", + "path": "/docs", "priority": -1, "routes": Array [ + Object { + "component": "@theme/DocItem", + "exact": true, + "modules": Object { + "content": "@site/versioned_docs/version-1.0.1/hello.md", + }, + "path": "/docs/", + }, Object { "component": "@theme/DocItem", "exact": true, @@ -232,7 +232,7 @@ Object { "collapsed": true, "items": Array [ Object { - "href": "/docs/next", + "href": "/docs/next/", "label": "hello", "type": "link", }, @@ -263,7 +263,7 @@ Object { "collapsed": true, "items": Array [ Object { - "href": "/docs/1.0.0", + "href": "/docs/1.0.0/", "label": "hello", "type": "link", }, @@ -289,7 +289,7 @@ Object { "collapsed": true, "items": Array [ Object { - "href": "/docs", + "href": "/docs/", "label": "hello", "type": "link", }, @@ -326,7 +326,7 @@ Object { "collapsed": true, "items": Array [ Object { - "href": "/docs/1.0.0", + "href": "/docs/1.0.0/", "label": "hello", "type": "link", }, @@ -337,9 +337,9 @@ Object { ], }, "permalinkToSidebar": Object { + "/docs/1.0.0/": "version-1.0.0/docs", "/docs/1.0.0/foo/barSlug": "version-1.0.0/docs", "/docs/1.0.0/foo/baz": "version-1.0.0/docs", - "/docs/1.0.0/hello": "version-1.0.0/docs", }, "version": "1.0.0", } @@ -365,7 +365,7 @@ Object { "collapsed": true, "items": Array [ Object { - "href": "/docs", + "href": "/docs/", "label": "hello", "type": "link", }, @@ -376,8 +376,8 @@ Object { ], }, "permalinkToSidebar": Object { + "/docs/": "version-1.0.1/docs", "/docs/foo/bar": "version-1.0.1/docs", - "/docs/hello": "version-1.0.1/docs", }, "version": "1.0.1", } @@ -403,7 +403,7 @@ Object { "collapsed": true, "items": Array [ Object { - "href": "/docs/next", + "href": "/docs/next/", "label": "hello", "type": "link", }, @@ -414,8 +414,8 @@ Object { ], }, "permalinkToSidebar": Object { + "/docs/next/": "docs", "/docs/next/foo/barSlug": "docs", - "/docs/next/hello": "docs", }, "version": "next", } diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index 2daea9fe1272..195cb8d12e99 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -154,7 +154,8 @@ describe('simple website', () => { expect(versionToSidebars).toEqual({}); expect(docsMetadata.hello).toEqual({ id: 'hello', - permalink: '/docs/hello', + isDocsHomePage: true, + permalink: '/docs/', previous: { title: 'baz', permalink: '/docs/foo/bazSlug.html', @@ -168,6 +169,7 @@ describe('simple website', () => { expect(docsMetadata['foo/bar']).toEqual({ id: 'foo/bar', + isDocsHomePage: false, next: { title: 'baz', permalink: '/docs/foo/bazSlug.html', @@ -296,6 +298,7 @@ describe('versioned website', () => { expect(docsMetadata['version-1.0.1/foo/baz']).toBeUndefined(); expect(docsMetadata['foo/bar']).toEqual({ id: 'foo/bar', + isDocsHomePage: false, permalink: '/docs/next/foo/barSlug', source: path.join('@site', routeBasePath, 'foo', 'bar.md'), title: 'bar', @@ -304,12 +307,13 @@ describe('versioned website', () => { sidebar: 'docs', next: { title: 'hello', - permalink: '/docs/next/hello', + permalink: '/docs/next/', }, }); expect(docsMetadata['hello']).toEqual({ id: 'hello', - permalink: '/docs/next/hello', + isDocsHomePage: true, + permalink: '/docs/next/', source: path.join('@site', routeBasePath, 'hello.md'), title: 'hello', description: 'Hello next !', @@ -322,7 +326,8 @@ describe('versioned website', () => { }); expect(docsMetadata['version-1.0.1/hello']).toEqual({ id: 'version-1.0.1/hello', - permalink: '/docs/hello', + isDocsHomePage: true, + permalink: '/docs/', source: path.join( '@site', path.relative(siteDir, versionedDir), @@ -341,6 +346,7 @@ describe('versioned website', () => { }); expect(docsMetadata['version-1.0.0/foo/baz']).toEqual({ id: 'version-1.0.0/foo/baz', + isDocsHomePage: false, permalink: '/docs/1.0.0/foo/baz', source: path.join( '@site', @@ -356,7 +362,7 @@ describe('versioned website', () => { sidebar: 'version-1.0.0/docs', next: { title: 'hello', - permalink: '/docs/1.0.0/hello', + permalink: '/docs/1.0.0/', }, previous: { title: 'bar', diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/metadata.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/metadata.test.ts index 17759bff68ab..9b4950b3d1cf 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/metadata.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/metadata.test.ts @@ -46,6 +46,7 @@ describe('simple site', () => { expect(dataA).toEqual({ id: 'foo/bar', + isDocsHomePage: false, permalink: '/docs/foo/bar', source: path.join('@site', routeBasePath, sourceA), title: 'Bar', @@ -54,6 +55,7 @@ describe('simple site', () => { }); expect(dataB).toEqual({ id: 'hello', + isDocsHomePage: false, permalink: '/docs/hello', source: path.join('@site', routeBasePath, sourceB), title: 'Hello, World !', @@ -62,6 +64,56 @@ describe('simple site', () => { }); }); + test('homePageId doc', async () => { + const source = path.join('hello.md'); + const options = { + routeBasePath, + homePageId: 'hello', + }; + + const data = await processMetadata({ + source, + refDir: docsDir, + context, + options, + env, + }); + + expect(data).toEqual({ + id: 'hello', + isDocsHomePage: true, + permalink: '/docs/', + source: path.join('@site', routeBasePath, source), + title: 'Hello, World !', + description: `Hi, Endilie here :)`, + }); + }); + + test('homePageId doc nested', async () => { + const source = path.join('foo', 'bar.md'); + const options = { + routeBasePath, + homePageId: 'foo/bar', + }; + + const data = await processMetadata({ + source, + refDir: docsDir, + context, + options, + env, + }); + + expect(data).toEqual({ + id: 'foo/bar', + isDocsHomePage: true, + permalink: '/docs/', + source: path.join('@site', routeBasePath, source), + title: 'Bar', + description: 'This is custom description', + }); + }); + test('docs with editUrl', async () => { const editUrl = 'https://github.com/facebook/docusaurus/edit/master/website'; @@ -81,6 +133,7 @@ describe('simple site', () => { expect(data).toEqual({ id: 'foo/baz', + isDocsHomePage: false, permalink: '/docs/foo/bazSlug.html', source: path.join('@site', routeBasePath, source), title: 'baz', @@ -107,6 +160,7 @@ describe('simple site', () => { expect(data).toEqual({ id: 'lorem', + isDocsHomePage: false, permalink: '/docs/lorem', source: path.join('@site', routeBasePath, source), title: 'lorem', @@ -137,6 +191,7 @@ describe('simple site', () => { expect(data).toEqual({ id: 'lorem', + isDocsHomePage: false, permalink: '/docs/lorem', source: path.join('@site', routeBasePath, source), title: 'lorem', @@ -166,6 +221,7 @@ describe('simple site', () => { expect(data).toEqual({ id: 'ipsum', + isDocsHomePage: false, permalink: '/docs/ipsum', source: path.join('@site', routeBasePath, source), title: 'ipsum', @@ -214,6 +270,26 @@ describe('simple site', () => { `"Document slug cannot include \\"/\\"."`, ); }); + + test('docs with slug on doc home', async () => { + const badSiteDir = path.join(fixtureDir, 'bad-slug-on-doc-home-site'); + const options = { + routeBasePath, + homePageId: 'docWithSlug', + }; + + await expect( + processMetadata({ + source: 'docWithSlug.md', + refDir: path.join(badSiteDir, 'docs'), + context, + options, + env, + }), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"The docs homepage (homePageId=docWithSlug) is not allowed to have a frontmatter slug=docWithSlug.html => you have to chooser either homePageId or slug, not both"`, + ); + }); }); describe('versioned site', () => { @@ -250,6 +326,7 @@ describe('versioned site', () => { expect(dataA).toEqual({ id: 'foo/bar', + isDocsHomePage: false, permalink: '/docs/next/foo/barSlug', source: path.join('@site', routeBasePath, sourceA), title: 'bar', @@ -258,6 +335,7 @@ describe('versioned site', () => { }); expect(dataB).toEqual({ id: 'hello', + isDocsHomePage: false, permalink: '/docs/next/hello', source: path.join('@site', routeBasePath, sourceB), title: 'hello', @@ -308,6 +386,7 @@ describe('versioned site', () => { expect(dataA).toEqual({ id: 'version-1.0.0/foo/bar', + isDocsHomePage: false, permalink: '/docs/1.0.0/foo/barSlug', source: path.join('@site', path.relative(siteDir, versionedDir), sourceA), title: 'bar', @@ -316,6 +395,7 @@ describe('versioned site', () => { }); expect(dataB).toEqual({ id: 'version-1.0.0/hello', + isDocsHomePage: false, permalink: '/docs/1.0.0/hello', source: path.join('@site', path.relative(siteDir, versionedDir), sourceB), title: 'hello', @@ -324,6 +404,7 @@ describe('versioned site', () => { }); expect(dataC).toEqual({ id: 'version-1.0.1/foo/bar', + isDocsHomePage: false, permalink: '/docs/foo/bar', source: path.join('@site', path.relative(siteDir, versionedDir), sourceC), title: 'bar', @@ -332,6 +413,7 @@ describe('versioned site', () => { }); expect(dataD).toEqual({ id: 'version-1.0.1/hello', + isDocsHomePage: false, permalink: '/docs/hello', source: path.join('@site', path.relative(siteDir, versionedDir), sourceD), title: 'hello', diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 614abda44bc9..6740c9e40715 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -85,7 +85,9 @@ export default function pluginContentDocs( context: LoadContext, opts: Partial, ): Plugin { - const options = {...DEFAULT_OPTIONS, ...opts}; + const options: PluginOptions = {...DEFAULT_OPTIONS, ...opts}; + const homePageDocsRoutePath = + options.routeBasePath === '' ? '/' : options.routeBasePath; if (options.admonitions) { options.remarkPlugins = options.remarkPlugins.concat([ @@ -112,24 +114,6 @@ export default function pluginContentDocs( } = versioning; const versionsNames = versions.map((version) => `version-${version}`); - // Docs home page. - const homePageDocsRoutePath = - options.routeBasePath === '' ? '/' : options.routeBasePath; - const isDocsHomePagePath = (permalink: string) => { - const documentIdMatch = new RegExp( - `^\/(?:${homePageDocsRoutePath}\/)?(?:(?:${versions.join( - '|', - )}|next)\/)?(.*)`, - 'i', - ).exec(permalink); - - if (documentIdMatch) { - return documentIdMatch[1] === options.homePageId; - } - - return false; - }; - return { name: 'docusaurus-plugin-content-docs', @@ -307,9 +291,7 @@ Available document ids= return { type: 'link', label: sidebar_label || title, - href: isDocsHomePagePath(permalink) - ? permalink.replace(`/${options.homePageId}`, '') - : permalink, + href: permalink, }; }; @@ -376,50 +358,8 @@ Available document ids= const genRoutes = async ( metadataItems: Metadata[], ): Promise => { - const versionsRegex = new RegExp(versionsNames.join('|'), 'i'); - const routes = await Promise.all( metadataItems.map(async (metadataItem) => { - const isDocsHomePage = - metadataItem.id.replace(versionsRegex, '').replace(/^\//, '') === - options.homePageId; - if (isDocsHomePage) { - const versionDocsPathPrefix = - (metadataItem?.version === versioning.latestVersion - ? '' - : metadataItem.version!) ?? ''; - - const docsBaseMetadata = createDocsBaseMetadata( - metadataItem.version!, - ); - docsBaseMetadata.isHomePage = true; - docsBaseMetadata.homePagePath = normalizeUrl([ - baseUrl, - homePageDocsRoutePath, - versionDocsPathPrefix, - ]); - - const docsBaseMetadataPath = await createData( - `${docuHash(metadataItem.source)}-base.json`, - JSON.stringify(docsBaseMetadata, null, 2), - ); - - // Add a route for docs home page. - addRoute({ - path: normalizeUrl([ - baseUrl, - homePageDocsRoutePath, - versionDocsPathPrefix, - ]), - component: docLayoutComponent, - exact: true, - modules: { - docsMetadata: aliasedSource(docsBaseMetadataPath), - content: metadataItem.source, - }, - }); - } - await createData( // Note that this created data path must be in sync with // metadataPath provided to mdx-loader. @@ -438,15 +378,14 @@ Available document ids= }), ); - return ( - routes - // Do not create a route for a document serve as docs home page. - // TODO: need way to do this filtering when generating routes for better perf. - .filter(({path}) => !isDocsHomePagePath(path)) - .sort((a, b) => (a.path > b.path ? 1 : b.path > a.path ? -1 : 0)) + return routes.sort((a, b) => + a.path > b.path ? 1 : b.path > a.path ? -1 : 0, ); }; + // This is the base route of the document root (for a doc given version) + // (/docs, /docs/next, /docs/1.0 etc...) + // The component applies the layout and renders the appropriate doc const addBaseRoute = async ( docsBaseRoute: string, docsBaseMetadata: DocsBaseMetadata, @@ -454,14 +393,20 @@ Available document ids= priority?: number, ) => { const docsBaseMetadataPath = await createData( - `${docuHash(docsBaseRoute)}.json`, + `${docuHash(normalizeUrl([docsBaseRoute, ':route']))}.json`, JSON.stringify(docsBaseMetadata, null, 2), ); + // Important: the layout component should not end with /, + // as it conflicts with the home doc + // Workaround fix for https://github.com/facebook/docusaurus/issues/2917 + const path = docsBaseRoute === '/' ? '' : docsBaseRoute; + addRoute({ - path: docsBaseRoute, - component: docLayoutComponent, - routes, + path, + exact: false, // allow matching /docs/* as well + component: docLayoutComponent, // main docs component (DocPage) + routes, // subroute for each doc modules: { docsMetadata: aliasedSource(docsBaseMetadataPath), }, @@ -499,21 +444,20 @@ Available document ids= ); const isLatestVersion = version === versioning.latestVersion; - const docsBasePermalink = normalizeUrl([ + const docsBaseRoute = normalizeUrl([ baseUrl, routeBasePath, isLatestVersion ? '' : version, ]); - const docsBaseRoute = normalizeUrl([docsBasePermalink, ':route']); const docsBaseMetadata = createDocsBaseMetadata(version); - // We want latest version route config to be placed last in the - // generated routeconfig. Otherwise, `/docs/next/foo` will match - // `/docs/:route` instead of `/docs/next/:route`. return addBaseRoute( docsBaseRoute, docsBaseMetadata, routes, + // We want latest version route config to be placed last in the + // generated routeconfig. Otherwise, `/docs/next/foo` will match + // `/docs/:route` instead of `/docs/next/:route`. isLatestVersion ? -1 : undefined, ); }), @@ -521,8 +465,7 @@ Available document ids= } else { const routes = await genRoutes(Object.values(content.docsMetadata)); const docsBaseMetadata = createDocsBaseMetadata(); - - const docsBaseRoute = normalizeUrl([baseUrl, routeBasePath, ':route']); + const docsBaseRoute = normalizeUrl([baseUrl, routeBasePath]); return addBaseRoute(docsBaseRoute, docsBaseMetadata, routes); } }, diff --git a/packages/docusaurus-plugin-content-docs/src/metadata.ts b/packages/docusaurus-plugin-content-docs/src/metadata.ts index 66225d8918aa..60ad3d959dd4 100644 --- a/packages/docusaurus-plugin-content-docs/src/metadata.ts +++ b/packages/docusaurus-plugin-content-docs/src/metadata.ts @@ -15,7 +15,43 @@ import { import {LoadContext} from '@docusaurus/types'; import lastUpdate from './lastUpdate'; -import {MetadataRaw, LastUpdateData, MetadataOptions, Env} from './types'; +import { + MetadataRaw, + LastUpdateData, + MetadataOptions, + Env, + VersioningEnv, +} from './types'; + +function removeVersionPrefix(str: string, version: string): string { + return str.replace(new RegExp(`^version-${version}/`), ''); +} + +function inferVersion( + dirName: string, + versioning: VersioningEnv, +): string | undefined { + if (!versioning.enabled) { + return undefined; + } + if (/^version-/.test(dirName)) { + const inferredVersion = dirName + .split('/', 1) + .shift()! + .replace(/^version-/, ''); + if (inferredVersion && versioning.versions.includes(inferredVersion)) { + return inferredVersion; + } else { + throw new Error( + `Can't infer version from folder=${dirName} +Expected versions: +- ${versioning.versions.join('- ')}`, + ); + } + } else { + return 'next'; + } +} type Args = { source: string; @@ -59,7 +95,7 @@ export default async function processMetadata({ options, env, }: Args): Promise { - const {routeBasePath, editUrl} = options; + const {routeBasePath, editUrl, homePageId} = options; const {siteDir, baseUrl} = context; const {versioning} = env; const filePath = path.join(refDir, source); @@ -67,21 +103,8 @@ export default async function processMetadata({ const fileMarkdownPromise = parseMarkdownFile(filePath); const lastUpdatedPromise = lastUpdated(filePath, options); - let version; const dirName = path.dirname(source); - if (versioning.enabled) { - if (/^version-/.test(dirName)) { - const inferredVersion = dirName - .split('/', 1) - .shift()! - .replace(/^version-/, ''); - if (inferredVersion && versioning.versions.includes(inferredVersion)) { - version = inferredVersion; - } - } else { - version = 'next'; - } - } + const version = inferVersion(dirName, versioning); // The version portion of the url path. Eg: 'next', '1.0.0', and ''. const versionPath = @@ -100,14 +123,20 @@ export default async function processMetadata({ if (baseID.includes('/')) { throw new Error('Document id cannot include "/".'); } + const id = dirName !== '.' ? `${dirName}/${baseID}` : baseID; + const idWithoutVersion = version ? removeVersionPrefix(id, version) : id; + + const isDocsHomePage = idWithoutVersion === homePageId; + if (frontMatter.slug && isDocsHomePage) { + throw new Error( + `The docs homepage (homePageId=${homePageId}) is not allowed to have a frontmatter slug=${frontMatter.slug} => you have to chooser either homePageId or slug, not both`, + ); + } const baseSlug: string = frontMatter.slug || baseID; if (baseSlug.includes('/')) { throw new Error('Document slug cannot include "/".'); } - - // Append subdirectory as part of id/slug. - const id = dirName !== '.' ? `${dirName}/${baseID}` : baseID; const slug = dirName !== '.' ? `${dirName}/${baseSlug}` : baseSlug; // Default title is the id. @@ -116,10 +145,16 @@ export default async function processMetadata({ const description: string = frontMatter.description || excerpt; // The last portion of the url path. Eg: 'foo/bar', 'bar'. - const routePath = - version && version !== 'next' - ? slug.replace(new RegExp(`^version-${version}/`), '') - : slug; + let routePath; + if (isDocsHomePage) { + // TODO can we remove this trailing / ? + // Seems it's not that easy... + // Related to https://github.com/facebook/docusaurus/issues/2917 + routePath = '/'; + } else { + routePath = + version && version !== 'next' ? removeVersionPrefix(slug, version) : slug; + } const permalink = normalizeUrl([ baseUrl, @@ -136,6 +171,7 @@ export default async function processMetadata({ // class transitions. const metadata: MetadataRaw = { id, + isDocsHomePage, title, description, source: aliasedSitePath(filePath, siteDir), diff --git a/packages/docusaurus-plugin-content-docs/src/types.ts b/packages/docusaurus-plugin-content-docs/src/types.ts index 2b7b8b89a295..1f37c318bcba 100644 --- a/packages/docusaurus-plugin-content-docs/src/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/types.ts @@ -7,6 +7,7 @@ export interface MetadataOptions { routeBasePath: string; + homePageId?: string; editUrl?: string; showLastUpdateTime?: boolean; showLastUpdateAuthor?: boolean; @@ -24,7 +25,6 @@ export interface PluginOptions extends MetadataOptions, PathOptions { remarkPlugins: ([Function, object] | Function)[]; rehypePlugins: string[]; admonitions: any; - homePageId: string; } export type SidebarItemDoc = { @@ -111,6 +111,7 @@ export interface LastUpdateData { export interface MetadataRaw extends LastUpdateData { id: string; + isDocsHomePage: boolean; title: string; description: string; source: string; @@ -165,8 +166,6 @@ export type DocsBaseMetadata = Pick< 'docsSidebars' | 'permalinkToSidebar' > & { version?: string; - isHomePage?: boolean; - homePagePath?: string; }; export type VersioningEnv = { diff --git a/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.js b/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.js index 93f92e5fc4a3..78c691a07cc6 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.js +++ b/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.js @@ -8,7 +8,6 @@ import React from 'react'; import renderRoutes from '@docusaurus/renderRoutes'; import NotFound from '@theme/NotFound'; -import DocItem from '@theme/DocItem'; import DocSidebar from '@theme/DocSidebar'; import MDXComponents from '@theme/MDXComponents'; import Layout from '@theme/Layout'; @@ -16,24 +15,16 @@ import {MDXProvider} from '@mdx-js/react'; import {matchPath} from '@docusaurus/router'; function DocPage(props) { - const {route: baseRoute, docsMetadata, location, content} = props; - const { - permalinkToSidebar, - docsSidebars, - isHomePage, - homePagePath, - } = docsMetadata; + const {route: baseRoute, docsMetadata, location} = props; // case-sensitive route such as it is defined in the sidebar - const currentRoute = !isHomePage - ? baseRoute.routes.find((route) => { - return matchPath(location.pathname, route); - }) || {} - : {}; - const sidebar = isHomePage - ? content.metadata.sidebar - : permalinkToSidebar[currentRoute.path]; + const currentRoute = + baseRoute.routes.find((route) => { + return matchPath(location.pathname, route); + }) || {}; + const {permalinkToSidebar, docsSidebars} = docsMetadata; + const sidebar = permalinkToSidebar[currentRoute.path]; - if (!isHomePage && Object.keys(currentRoute).length === 0) { + if (Object.keys(currentRoute).length === 0) { return ; } @@ -41,16 +32,12 @@ function DocPage(props) {
- {isHomePage ? ( - - ) : ( - renderRoutes(baseRoute.routes) - )} + {renderRoutes(baseRoute.routes)}
diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/index.js b/packages/docusaurus-theme-classic/src/theme/DocPage/index.js index fe3ef2767d16..adee2291b84c 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/index.js +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/index.js @@ -11,7 +11,6 @@ import {MDXProvider} from '@mdx-js/react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import renderRoutes from '@docusaurus/renderRoutes'; import Layout from '@theme/Layout'; -import DocItem from '@theme/DocItem'; import DocSidebar from '@theme/DocSidebar'; import MDXComponents from '@theme/MDXComponents'; import NotFound from '@theme/NotFound'; @@ -20,35 +19,22 @@ import {matchPath} from '@docusaurus/router'; import styles from './styles.module.css'; function DocPage(props) { - const {route: baseRoute, docsMetadata, location, content} = props; + const {route: baseRoute, docsMetadata, location} = props; + // case-sensitive route such as it is defined in the sidebar + const currentRoute = + baseRoute.routes.find((route) => { + return matchPath(location.pathname, route); + }) || {}; + const {permalinkToSidebar, docsSidebars, version} = docsMetadata; + const sidebar = permalinkToSidebar[currentRoute.path]; const { - permalinkToSidebar, - docsSidebars, - version, - isHomePage, - homePagePath, - } = docsMetadata; - - // Get case-sensitive route such as it is defined in the sidebar. - const currentRoute = !isHomePage - ? baseRoute.routes.find((route) => { - return matchPath(location.pathname, route); - }) || {} - : {}; - - const sidebar = isHomePage - ? content.metadata.sidebar - : permalinkToSidebar[currentRoute.path]; - const { - siteConfig: {themeConfig: {sidebarCollapsible = true} = {}} = {}, + siteConfig: {themeConfig = {}} = {}, isClient, } = useDocusaurusContext(); - if (isHomePage) { - content.metadata.permalink = homePagePath; - } + const {sidebarCollapsible = true} = themeConfig; - if (!isHomePage && Object.keys(currentRoute).length === 0) { + if (Object.keys(currentRoute).length === 0) { return ; } @@ -59,7 +45,7 @@ function DocPage(props) {
@@ -67,11 +53,7 @@ function DocPage(props) { )}
- {isHomePage ? ( - - ) : ( - renderRoutes(baseRoute.routes) - )} + {renderRoutes(baseRoute.routes)}
diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.js b/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.js index 68e710db040a..feb075b5fdbc 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.js +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.js @@ -27,9 +27,15 @@ function usePrevious(value) { return ref.current; } +// Compare the 2 paths, ignoring trailing / +const isSamePath = (path1, path2) => { + const normalize = (str) => (str.endsWith('/') ? str : `${str}/`); + return normalize(path1) === normalize(path2); +}; + const isActiveSidebarItem = (item, activePath) => { if (item.type === 'link') { - return item.href === activePath; + return isSamePath(item.href, activePath); } if (item.type === 'category') { return item.items.some((subItem) =>