mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
fix(v2): fix docs homepage permalink issues (#2905)
* better fixes for docs homepage * fix tests * create special route for docs homepage + cleanup existing code * no need to create multiple docs parent paths * useful comment * add test for slug + doc home usage at the same time error * remove confusing variable name * fix tests by using same suffix as before for docs base metadata path * metadata: use homePageId correctly for nested docs: the full docId (including /) should be used to compare against homePageId * add folder/testNested test doc * refactor a bit processMetadata, the home should be handled correctly for all versions * Workaround to fix issue when parent layout route (DocPage) has same path as the child route (DocItem): see https://github.com/facebook/docusaurus/issues/2917 * revert homePageId * remove test doc * remove test doc * add useful comment
This commit is contained in:
parent
a3f54d747d
commit
f6b1c85b01
10 changed files with 264 additions and 218 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
slug: docWithSlug.html
|
||||||
|
---
|
||||||
|
|
||||||
|
Lorem
|
|
@ -29,7 +29,7 @@ Object {
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"href": "/docs",
|
"href": "/docs/",
|
||||||
"label": "Hello, World !",
|
"label": "Hello, World !",
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
|
@ -41,7 +41,7 @@ Object {
|
||||||
"collapsed": true,
|
"collapsed": true,
|
||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"href": "/docs",
|
"href": "/docs/",
|
||||||
"label": "Hello, World !",
|
"label": "Hello, World !",
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
|
@ -57,21 +57,21 @@ exports[`simple website content 2`] = `
|
||||||
Array [
|
Array [
|
||||||
Object {
|
Object {
|
||||||
"component": "@theme/DocPage",
|
"component": "@theme/DocPage",
|
||||||
"exact": true,
|
"exact": false,
|
||||||
"modules": Object {
|
|
||||||
"content": "@site/docs/hello.md",
|
|
||||||
"docsMetadata": "~docs/site-docs-hello-md-9df-base.json",
|
|
||||||
},
|
|
||||||
"path": "/docs",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"component": "@theme/DocPage",
|
|
||||||
"modules": Object {
|
"modules": Object {
|
||||||
"docsMetadata": "~docs/docs-route-ff2.json",
|
"docsMetadata": "~docs/docs-route-ff2.json",
|
||||||
},
|
},
|
||||||
"path": "/docs/:route",
|
"path": "/docs",
|
||||||
"priority": undefined,
|
"priority": undefined,
|
||||||
"routes": Array [
|
"routes": Array [
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocItem",
|
||||||
|
"exact": true,
|
||||||
|
"modules": Object {
|
||||||
|
"content": "@site/docs/hello.md",
|
||||||
|
},
|
||||||
|
"path": "/docs/",
|
||||||
|
},
|
||||||
Object {
|
Object {
|
||||||
"component": "@theme/DocItem",
|
"component": "@theme/DocItem",
|
||||||
"exact": true,
|
"exact": true,
|
||||||
|
@ -123,39 +123,21 @@ exports[`versioned website content 1`] = `
|
||||||
Array [
|
Array [
|
||||||
Object {
|
Object {
|
||||||
"component": "@theme/DocPage",
|
"component": "@theme/DocPage",
|
||||||
"exact": true,
|
"exact": false,
|
||||||
"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",
|
|
||||||
"modules": Object {
|
"modules": Object {
|
||||||
"docsMetadata": "~docs/docs-1-0-0-route-660.json",
|
"docsMetadata": "~docs/docs-1-0-0-route-660.json",
|
||||||
},
|
},
|
||||||
"path": "/docs/1.0.0/:route",
|
"path": "/docs/1.0.0",
|
||||||
"priority": undefined,
|
"priority": undefined,
|
||||||
"routes": Array [
|
"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 {
|
Object {
|
||||||
"component": "@theme/DocItem",
|
"component": "@theme/DocItem",
|
||||||
"exact": true,
|
"exact": true,
|
||||||
|
@ -176,12 +158,21 @@ Array [
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"component": "@theme/DocPage",
|
"component": "@theme/DocPage",
|
||||||
|
"exact": false,
|
||||||
"modules": Object {
|
"modules": Object {
|
||||||
"docsMetadata": "~docs/docs-next-route-1c8.json",
|
"docsMetadata": "~docs/docs-next-route-1c8.json",
|
||||||
},
|
},
|
||||||
"path": "/docs/next/:route",
|
"path": "/docs/next",
|
||||||
"priority": undefined,
|
"priority": undefined,
|
||||||
"routes": Array [
|
"routes": Array [
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocItem",
|
||||||
|
"exact": true,
|
||||||
|
"modules": Object {
|
||||||
|
"content": "@site/docs/hello.md",
|
||||||
|
},
|
||||||
|
"path": "/docs/next/",
|
||||||
|
},
|
||||||
Object {
|
Object {
|
||||||
"component": "@theme/DocItem",
|
"component": "@theme/DocItem",
|
||||||
"exact": true,
|
"exact": true,
|
||||||
|
@ -194,12 +185,21 @@ Array [
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"component": "@theme/DocPage",
|
"component": "@theme/DocPage",
|
||||||
|
"exact": false,
|
||||||
"modules": Object {
|
"modules": Object {
|
||||||
"docsMetadata": "~docs/docs-route-ff2.json",
|
"docsMetadata": "~docs/docs-route-ff2.json",
|
||||||
},
|
},
|
||||||
"path": "/docs/:route",
|
"path": "/docs",
|
||||||
"priority": -1,
|
"priority": -1,
|
||||||
"routes": Array [
|
"routes": Array [
|
||||||
|
Object {
|
||||||
|
"component": "@theme/DocItem",
|
||||||
|
"exact": true,
|
||||||
|
"modules": Object {
|
||||||
|
"content": "@site/versioned_docs/version-1.0.1/hello.md",
|
||||||
|
},
|
||||||
|
"path": "/docs/",
|
||||||
|
},
|
||||||
Object {
|
Object {
|
||||||
"component": "@theme/DocItem",
|
"component": "@theme/DocItem",
|
||||||
"exact": true,
|
"exact": true,
|
||||||
|
@ -232,7 +232,7 @@ Object {
|
||||||
"collapsed": true,
|
"collapsed": true,
|
||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"href": "/docs/next",
|
"href": "/docs/next/",
|
||||||
"label": "hello",
|
"label": "hello",
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
|
@ -263,7 +263,7 @@ Object {
|
||||||
"collapsed": true,
|
"collapsed": true,
|
||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"href": "/docs/1.0.0",
|
"href": "/docs/1.0.0/",
|
||||||
"label": "hello",
|
"label": "hello",
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
|
@ -289,7 +289,7 @@ Object {
|
||||||
"collapsed": true,
|
"collapsed": true,
|
||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"href": "/docs",
|
"href": "/docs/",
|
||||||
"label": "hello",
|
"label": "hello",
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
|
@ -326,7 +326,7 @@ Object {
|
||||||
"collapsed": true,
|
"collapsed": true,
|
||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"href": "/docs/1.0.0",
|
"href": "/docs/1.0.0/",
|
||||||
"label": "hello",
|
"label": "hello",
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
|
@ -337,9 +337,9 @@ Object {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"permalinkToSidebar": 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/barSlug": "version-1.0.0/docs",
|
||||||
"/docs/1.0.0/foo/baz": "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",
|
"version": "1.0.0",
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,7 @@ Object {
|
||||||
"collapsed": true,
|
"collapsed": true,
|
||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"href": "/docs",
|
"href": "/docs/",
|
||||||
"label": "hello",
|
"label": "hello",
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
|
@ -376,8 +376,8 @@ Object {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"permalinkToSidebar": Object {
|
"permalinkToSidebar": Object {
|
||||||
|
"/docs/": "version-1.0.1/docs",
|
||||||
"/docs/foo/bar": "version-1.0.1/docs",
|
"/docs/foo/bar": "version-1.0.1/docs",
|
||||||
"/docs/hello": "version-1.0.1/docs",
|
|
||||||
},
|
},
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
}
|
}
|
||||||
|
@ -403,7 +403,7 @@ Object {
|
||||||
"collapsed": true,
|
"collapsed": true,
|
||||||
"items": Array [
|
"items": Array [
|
||||||
Object {
|
Object {
|
||||||
"href": "/docs/next",
|
"href": "/docs/next/",
|
||||||
"label": "hello",
|
"label": "hello",
|
||||||
"type": "link",
|
"type": "link",
|
||||||
},
|
},
|
||||||
|
@ -414,8 +414,8 @@ Object {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"permalinkToSidebar": Object {
|
"permalinkToSidebar": Object {
|
||||||
|
"/docs/next/": "docs",
|
||||||
"/docs/next/foo/barSlug": "docs",
|
"/docs/next/foo/barSlug": "docs",
|
||||||
"/docs/next/hello": "docs",
|
|
||||||
},
|
},
|
||||||
"version": "next",
|
"version": "next",
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,8 @@ describe('simple website', () => {
|
||||||
expect(versionToSidebars).toEqual({});
|
expect(versionToSidebars).toEqual({});
|
||||||
expect(docsMetadata.hello).toEqual({
|
expect(docsMetadata.hello).toEqual({
|
||||||
id: 'hello',
|
id: 'hello',
|
||||||
permalink: '/docs/hello',
|
isDocsHomePage: true,
|
||||||
|
permalink: '/docs/',
|
||||||
previous: {
|
previous: {
|
||||||
title: 'baz',
|
title: 'baz',
|
||||||
permalink: '/docs/foo/bazSlug.html',
|
permalink: '/docs/foo/bazSlug.html',
|
||||||
|
@ -168,6 +169,7 @@ describe('simple website', () => {
|
||||||
|
|
||||||
expect(docsMetadata['foo/bar']).toEqual({
|
expect(docsMetadata['foo/bar']).toEqual({
|
||||||
id: 'foo/bar',
|
id: 'foo/bar',
|
||||||
|
isDocsHomePage: false,
|
||||||
next: {
|
next: {
|
||||||
title: 'baz',
|
title: 'baz',
|
||||||
permalink: '/docs/foo/bazSlug.html',
|
permalink: '/docs/foo/bazSlug.html',
|
||||||
|
@ -296,6 +298,7 @@ describe('versioned website', () => {
|
||||||
expect(docsMetadata['version-1.0.1/foo/baz']).toBeUndefined();
|
expect(docsMetadata['version-1.0.1/foo/baz']).toBeUndefined();
|
||||||
expect(docsMetadata['foo/bar']).toEqual({
|
expect(docsMetadata['foo/bar']).toEqual({
|
||||||
id: 'foo/bar',
|
id: 'foo/bar',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/next/foo/barSlug',
|
permalink: '/docs/next/foo/barSlug',
|
||||||
source: path.join('@site', routeBasePath, 'foo', 'bar.md'),
|
source: path.join('@site', routeBasePath, 'foo', 'bar.md'),
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
|
@ -304,12 +307,13 @@ describe('versioned website', () => {
|
||||||
sidebar: 'docs',
|
sidebar: 'docs',
|
||||||
next: {
|
next: {
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
permalink: '/docs/next/hello',
|
permalink: '/docs/next/',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(docsMetadata['hello']).toEqual({
|
expect(docsMetadata['hello']).toEqual({
|
||||||
id: 'hello',
|
id: 'hello',
|
||||||
permalink: '/docs/next/hello',
|
isDocsHomePage: true,
|
||||||
|
permalink: '/docs/next/',
|
||||||
source: path.join('@site', routeBasePath, 'hello.md'),
|
source: path.join('@site', routeBasePath, 'hello.md'),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
description: 'Hello next !',
|
description: 'Hello next !',
|
||||||
|
@ -322,7 +326,8 @@ describe('versioned website', () => {
|
||||||
});
|
});
|
||||||
expect(docsMetadata['version-1.0.1/hello']).toEqual({
|
expect(docsMetadata['version-1.0.1/hello']).toEqual({
|
||||||
id: 'version-1.0.1/hello',
|
id: 'version-1.0.1/hello',
|
||||||
permalink: '/docs/hello',
|
isDocsHomePage: true,
|
||||||
|
permalink: '/docs/',
|
||||||
source: path.join(
|
source: path.join(
|
||||||
'@site',
|
'@site',
|
||||||
path.relative(siteDir, versionedDir),
|
path.relative(siteDir, versionedDir),
|
||||||
|
@ -341,6 +346,7 @@ describe('versioned website', () => {
|
||||||
});
|
});
|
||||||
expect(docsMetadata['version-1.0.0/foo/baz']).toEqual({
|
expect(docsMetadata['version-1.0.0/foo/baz']).toEqual({
|
||||||
id: 'version-1.0.0/foo/baz',
|
id: 'version-1.0.0/foo/baz',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/1.0.0/foo/baz',
|
permalink: '/docs/1.0.0/foo/baz',
|
||||||
source: path.join(
|
source: path.join(
|
||||||
'@site',
|
'@site',
|
||||||
|
@ -356,7 +362,7 @@ describe('versioned website', () => {
|
||||||
sidebar: 'version-1.0.0/docs',
|
sidebar: 'version-1.0.0/docs',
|
||||||
next: {
|
next: {
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
permalink: '/docs/1.0.0/hello',
|
permalink: '/docs/1.0.0/',
|
||||||
},
|
},
|
||||||
previous: {
|
previous: {
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
|
|
|
@ -46,6 +46,7 @@ describe('simple site', () => {
|
||||||
|
|
||||||
expect(dataA).toEqual({
|
expect(dataA).toEqual({
|
||||||
id: 'foo/bar',
|
id: 'foo/bar',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/foo/bar',
|
permalink: '/docs/foo/bar',
|
||||||
source: path.join('@site', routeBasePath, sourceA),
|
source: path.join('@site', routeBasePath, sourceA),
|
||||||
title: 'Bar',
|
title: 'Bar',
|
||||||
|
@ -54,6 +55,7 @@ describe('simple site', () => {
|
||||||
});
|
});
|
||||||
expect(dataB).toEqual({
|
expect(dataB).toEqual({
|
||||||
id: 'hello',
|
id: 'hello',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/hello',
|
permalink: '/docs/hello',
|
||||||
source: path.join('@site', routeBasePath, sourceB),
|
source: path.join('@site', routeBasePath, sourceB),
|
||||||
title: 'Hello, World !',
|
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 () => {
|
test('docs with editUrl', async () => {
|
||||||
const editUrl =
|
const editUrl =
|
||||||
'https://github.com/facebook/docusaurus/edit/master/website';
|
'https://github.com/facebook/docusaurus/edit/master/website';
|
||||||
|
@ -81,6 +133,7 @@ describe('simple site', () => {
|
||||||
|
|
||||||
expect(data).toEqual({
|
expect(data).toEqual({
|
||||||
id: 'foo/baz',
|
id: 'foo/baz',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/foo/bazSlug.html',
|
permalink: '/docs/foo/bazSlug.html',
|
||||||
source: path.join('@site', routeBasePath, source),
|
source: path.join('@site', routeBasePath, source),
|
||||||
title: 'baz',
|
title: 'baz',
|
||||||
|
@ -107,6 +160,7 @@ describe('simple site', () => {
|
||||||
|
|
||||||
expect(data).toEqual({
|
expect(data).toEqual({
|
||||||
id: 'lorem',
|
id: 'lorem',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/lorem',
|
permalink: '/docs/lorem',
|
||||||
source: path.join('@site', routeBasePath, source),
|
source: path.join('@site', routeBasePath, source),
|
||||||
title: 'lorem',
|
title: 'lorem',
|
||||||
|
@ -137,6 +191,7 @@ describe('simple site', () => {
|
||||||
|
|
||||||
expect(data).toEqual({
|
expect(data).toEqual({
|
||||||
id: 'lorem',
|
id: 'lorem',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/lorem',
|
permalink: '/docs/lorem',
|
||||||
source: path.join('@site', routeBasePath, source),
|
source: path.join('@site', routeBasePath, source),
|
||||||
title: 'lorem',
|
title: 'lorem',
|
||||||
|
@ -166,6 +221,7 @@ describe('simple site', () => {
|
||||||
|
|
||||||
expect(data).toEqual({
|
expect(data).toEqual({
|
||||||
id: 'ipsum',
|
id: 'ipsum',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/ipsum',
|
permalink: '/docs/ipsum',
|
||||||
source: path.join('@site', routeBasePath, source),
|
source: path.join('@site', routeBasePath, source),
|
||||||
title: 'ipsum',
|
title: 'ipsum',
|
||||||
|
@ -214,6 +270,26 @@ describe('simple site', () => {
|
||||||
`"Document slug cannot include \\"/\\"."`,
|
`"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', () => {
|
describe('versioned site', () => {
|
||||||
|
@ -250,6 +326,7 @@ describe('versioned site', () => {
|
||||||
|
|
||||||
expect(dataA).toEqual({
|
expect(dataA).toEqual({
|
||||||
id: 'foo/bar',
|
id: 'foo/bar',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/next/foo/barSlug',
|
permalink: '/docs/next/foo/barSlug',
|
||||||
source: path.join('@site', routeBasePath, sourceA),
|
source: path.join('@site', routeBasePath, sourceA),
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
|
@ -258,6 +335,7 @@ describe('versioned site', () => {
|
||||||
});
|
});
|
||||||
expect(dataB).toEqual({
|
expect(dataB).toEqual({
|
||||||
id: 'hello',
|
id: 'hello',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/next/hello',
|
permalink: '/docs/next/hello',
|
||||||
source: path.join('@site', routeBasePath, sourceB),
|
source: path.join('@site', routeBasePath, sourceB),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
|
@ -308,6 +386,7 @@ describe('versioned site', () => {
|
||||||
|
|
||||||
expect(dataA).toEqual({
|
expect(dataA).toEqual({
|
||||||
id: 'version-1.0.0/foo/bar',
|
id: 'version-1.0.0/foo/bar',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/1.0.0/foo/barSlug',
|
permalink: '/docs/1.0.0/foo/barSlug',
|
||||||
source: path.join('@site', path.relative(siteDir, versionedDir), sourceA),
|
source: path.join('@site', path.relative(siteDir, versionedDir), sourceA),
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
|
@ -316,6 +395,7 @@ describe('versioned site', () => {
|
||||||
});
|
});
|
||||||
expect(dataB).toEqual({
|
expect(dataB).toEqual({
|
||||||
id: 'version-1.0.0/hello',
|
id: 'version-1.0.0/hello',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/1.0.0/hello',
|
permalink: '/docs/1.0.0/hello',
|
||||||
source: path.join('@site', path.relative(siteDir, versionedDir), sourceB),
|
source: path.join('@site', path.relative(siteDir, versionedDir), sourceB),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
|
@ -324,6 +404,7 @@ describe('versioned site', () => {
|
||||||
});
|
});
|
||||||
expect(dataC).toEqual({
|
expect(dataC).toEqual({
|
||||||
id: 'version-1.0.1/foo/bar',
|
id: 'version-1.0.1/foo/bar',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/foo/bar',
|
permalink: '/docs/foo/bar',
|
||||||
source: path.join('@site', path.relative(siteDir, versionedDir), sourceC),
|
source: path.join('@site', path.relative(siteDir, versionedDir), sourceC),
|
||||||
title: 'bar',
|
title: 'bar',
|
||||||
|
@ -332,6 +413,7 @@ describe('versioned site', () => {
|
||||||
});
|
});
|
||||||
expect(dataD).toEqual({
|
expect(dataD).toEqual({
|
||||||
id: 'version-1.0.1/hello',
|
id: 'version-1.0.1/hello',
|
||||||
|
isDocsHomePage: false,
|
||||||
permalink: '/docs/hello',
|
permalink: '/docs/hello',
|
||||||
source: path.join('@site', path.relative(siteDir, versionedDir), sourceD),
|
source: path.join('@site', path.relative(siteDir, versionedDir), sourceD),
|
||||||
title: 'hello',
|
title: 'hello',
|
||||||
|
|
|
@ -85,7 +85,9 @@ export default function pluginContentDocs(
|
||||||
context: LoadContext,
|
context: LoadContext,
|
||||||
opts: Partial<PluginOptions>,
|
opts: Partial<PluginOptions>,
|
||||||
): Plugin<LoadedContent | null> {
|
): Plugin<LoadedContent | null> {
|
||||||
const options = {...DEFAULT_OPTIONS, ...opts};
|
const options: PluginOptions = {...DEFAULT_OPTIONS, ...opts};
|
||||||
|
const homePageDocsRoutePath =
|
||||||
|
options.routeBasePath === '' ? '/' : options.routeBasePath;
|
||||||
|
|
||||||
if (options.admonitions) {
|
if (options.admonitions) {
|
||||||
options.remarkPlugins = options.remarkPlugins.concat([
|
options.remarkPlugins = options.remarkPlugins.concat([
|
||||||
|
@ -112,24 +114,6 @@ export default function pluginContentDocs(
|
||||||
} = versioning;
|
} = versioning;
|
||||||
const versionsNames = versions.map((version) => `version-${version}`);
|
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 {
|
return {
|
||||||
name: 'docusaurus-plugin-content-docs',
|
name: 'docusaurus-plugin-content-docs',
|
||||||
|
|
||||||
|
@ -307,9 +291,7 @@ Available document ids=
|
||||||
return {
|
return {
|
||||||
type: 'link',
|
type: 'link',
|
||||||
label: sidebar_label || title,
|
label: sidebar_label || title,
|
||||||
href: isDocsHomePagePath(permalink)
|
href: permalink,
|
||||||
? permalink.replace(`/${options.homePageId}`, '')
|
|
||||||
: permalink,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -376,50 +358,8 @@ Available document ids=
|
||||||
const genRoutes = async (
|
const genRoutes = async (
|
||||||
metadataItems: Metadata[],
|
metadataItems: Metadata[],
|
||||||
): Promise<RouteConfig[]> => {
|
): Promise<RouteConfig[]> => {
|
||||||
const versionsRegex = new RegExp(versionsNames.join('|'), 'i');
|
|
||||||
|
|
||||||
const routes = await Promise.all(
|
const routes = await Promise.all(
|
||||||
metadataItems.map(async (metadataItem) => {
|
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(
|
await createData(
|
||||||
// Note that this created data path must be in sync with
|
// Note that this created data path must be in sync with
|
||||||
// metadataPath provided to mdx-loader.
|
// metadataPath provided to mdx-loader.
|
||||||
|
@ -438,15 +378,14 @@ Available document ids=
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return routes.sort((a, b) =>
|
||||||
routes
|
a.path > b.path ? 1 : b.path > a.path ? -1 : 0,
|
||||||
// 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))
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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 (
|
const addBaseRoute = async (
|
||||||
docsBaseRoute: string,
|
docsBaseRoute: string,
|
||||||
docsBaseMetadata: DocsBaseMetadata,
|
docsBaseMetadata: DocsBaseMetadata,
|
||||||
|
@ -454,14 +393,20 @@ Available document ids=
|
||||||
priority?: number,
|
priority?: number,
|
||||||
) => {
|
) => {
|
||||||
const docsBaseMetadataPath = await createData(
|
const docsBaseMetadataPath = await createData(
|
||||||
`${docuHash(docsBaseRoute)}.json`,
|
`${docuHash(normalizeUrl([docsBaseRoute, ':route']))}.json`,
|
||||||
JSON.stringify(docsBaseMetadata, null, 2),
|
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({
|
addRoute({
|
||||||
path: docsBaseRoute,
|
path,
|
||||||
component: docLayoutComponent,
|
exact: false, // allow matching /docs/* as well
|
||||||
routes,
|
component: docLayoutComponent, // main docs component (DocPage)
|
||||||
|
routes, // subroute for each doc
|
||||||
modules: {
|
modules: {
|
||||||
docsMetadata: aliasedSource(docsBaseMetadataPath),
|
docsMetadata: aliasedSource(docsBaseMetadataPath),
|
||||||
},
|
},
|
||||||
|
@ -499,21 +444,20 @@ Available document ids=
|
||||||
);
|
);
|
||||||
|
|
||||||
const isLatestVersion = version === versioning.latestVersion;
|
const isLatestVersion = version === versioning.latestVersion;
|
||||||
const docsBasePermalink = normalizeUrl([
|
const docsBaseRoute = normalizeUrl([
|
||||||
baseUrl,
|
baseUrl,
|
||||||
routeBasePath,
|
routeBasePath,
|
||||||
isLatestVersion ? '' : version,
|
isLatestVersion ? '' : version,
|
||||||
]);
|
]);
|
||||||
const docsBaseRoute = normalizeUrl([docsBasePermalink, ':route']);
|
|
||||||
const docsBaseMetadata = createDocsBaseMetadata(version);
|
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(
|
return addBaseRoute(
|
||||||
docsBaseRoute,
|
docsBaseRoute,
|
||||||
docsBaseMetadata,
|
docsBaseMetadata,
|
||||||
routes,
|
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,
|
isLatestVersion ? -1 : undefined,
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
@ -521,8 +465,7 @@ Available document ids=
|
||||||
} else {
|
} else {
|
||||||
const routes = await genRoutes(Object.values(content.docsMetadata));
|
const routes = await genRoutes(Object.values(content.docsMetadata));
|
||||||
const docsBaseMetadata = createDocsBaseMetadata();
|
const docsBaseMetadata = createDocsBaseMetadata();
|
||||||
|
const docsBaseRoute = normalizeUrl([baseUrl, routeBasePath]);
|
||||||
const docsBaseRoute = normalizeUrl([baseUrl, routeBasePath, ':route']);
|
|
||||||
return addBaseRoute(docsBaseRoute, docsBaseMetadata, routes);
|
return addBaseRoute(docsBaseRoute, docsBaseMetadata, routes);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,7 +15,43 @@ import {
|
||||||
import {LoadContext} from '@docusaurus/types';
|
import {LoadContext} from '@docusaurus/types';
|
||||||
|
|
||||||
import lastUpdate from './lastUpdate';
|
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 = {
|
type Args = {
|
||||||
source: string;
|
source: string;
|
||||||
|
@ -59,7 +95,7 @@ export default async function processMetadata({
|
||||||
options,
|
options,
|
||||||
env,
|
env,
|
||||||
}: Args): Promise<MetadataRaw> {
|
}: Args): Promise<MetadataRaw> {
|
||||||
const {routeBasePath, editUrl} = options;
|
const {routeBasePath, editUrl, homePageId} = options;
|
||||||
const {siteDir, baseUrl} = context;
|
const {siteDir, baseUrl} = context;
|
||||||
const {versioning} = env;
|
const {versioning} = env;
|
||||||
const filePath = path.join(refDir, source);
|
const filePath = path.join(refDir, source);
|
||||||
|
@ -67,21 +103,8 @@ export default async function processMetadata({
|
||||||
const fileMarkdownPromise = parseMarkdownFile(filePath);
|
const fileMarkdownPromise = parseMarkdownFile(filePath);
|
||||||
const lastUpdatedPromise = lastUpdated(filePath, options);
|
const lastUpdatedPromise = lastUpdated(filePath, options);
|
||||||
|
|
||||||
let version;
|
|
||||||
const dirName = path.dirname(source);
|
const dirName = path.dirname(source);
|
||||||
if (versioning.enabled) {
|
const version = inferVersion(dirName, versioning);
|
||||||
if (/^version-/.test(dirName)) {
|
|
||||||
const inferredVersion = dirName
|
|
||||||
.split('/', 1)
|
|
||||||
.shift()!
|
|
||||||
.replace(/^version-/, '');
|
|
||||||
if (inferredVersion && versioning.versions.includes(inferredVersion)) {
|
|
||||||
version = inferredVersion;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
version = 'next';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The version portion of the url path. Eg: 'next', '1.0.0', and ''.
|
// The version portion of the url path. Eg: 'next', '1.0.0', and ''.
|
||||||
const versionPath =
|
const versionPath =
|
||||||
|
@ -100,14 +123,20 @@ export default async function processMetadata({
|
||||||
if (baseID.includes('/')) {
|
if (baseID.includes('/')) {
|
||||||
throw new Error('Document id cannot include "/".');
|
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;
|
const baseSlug: string = frontMatter.slug || baseID;
|
||||||
if (baseSlug.includes('/')) {
|
if (baseSlug.includes('/')) {
|
||||||
throw new Error('Document slug cannot include "/".');
|
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;
|
const slug = dirName !== '.' ? `${dirName}/${baseSlug}` : baseSlug;
|
||||||
|
|
||||||
// Default title is the id.
|
// Default title is the id.
|
||||||
|
@ -116,10 +145,16 @@ export default async function processMetadata({
|
||||||
const description: string = frontMatter.description || excerpt;
|
const description: string = frontMatter.description || excerpt;
|
||||||
|
|
||||||
// The last portion of the url path. Eg: 'foo/bar', 'bar'.
|
// The last portion of the url path. Eg: 'foo/bar', 'bar'.
|
||||||
const routePath =
|
let routePath;
|
||||||
version && version !== 'next'
|
if (isDocsHomePage) {
|
||||||
? slug.replace(new RegExp(`^version-${version}/`), '')
|
// TODO can we remove this trailing / ?
|
||||||
: slug;
|
// 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([
|
const permalink = normalizeUrl([
|
||||||
baseUrl,
|
baseUrl,
|
||||||
|
@ -136,6 +171,7 @@ export default async function processMetadata({
|
||||||
// class transitions.
|
// class transitions.
|
||||||
const metadata: MetadataRaw = {
|
const metadata: MetadataRaw = {
|
||||||
id,
|
id,
|
||||||
|
isDocsHomePage,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
source: aliasedSitePath(filePath, siteDir),
|
source: aliasedSitePath(filePath, siteDir),
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
export interface MetadataOptions {
|
export interface MetadataOptions {
|
||||||
routeBasePath: string;
|
routeBasePath: string;
|
||||||
|
homePageId?: string;
|
||||||
editUrl?: string;
|
editUrl?: string;
|
||||||
showLastUpdateTime?: boolean;
|
showLastUpdateTime?: boolean;
|
||||||
showLastUpdateAuthor?: boolean;
|
showLastUpdateAuthor?: boolean;
|
||||||
|
@ -24,7 +25,6 @@ export interface PluginOptions extends MetadataOptions, PathOptions {
|
||||||
remarkPlugins: ([Function, object] | Function)[];
|
remarkPlugins: ([Function, object] | Function)[];
|
||||||
rehypePlugins: string[];
|
rehypePlugins: string[];
|
||||||
admonitions: any;
|
admonitions: any;
|
||||||
homePageId: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SidebarItemDoc = {
|
export type SidebarItemDoc = {
|
||||||
|
@ -111,6 +111,7 @@ export interface LastUpdateData {
|
||||||
|
|
||||||
export interface MetadataRaw extends LastUpdateData {
|
export interface MetadataRaw extends LastUpdateData {
|
||||||
id: string;
|
id: string;
|
||||||
|
isDocsHomePage: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
source: string;
|
source: string;
|
||||||
|
@ -165,8 +166,6 @@ export type DocsBaseMetadata = Pick<
|
||||||
'docsSidebars' | 'permalinkToSidebar'
|
'docsSidebars' | 'permalinkToSidebar'
|
||||||
> & {
|
> & {
|
||||||
version?: string;
|
version?: string;
|
||||||
isHomePage?: boolean;
|
|
||||||
homePagePath?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VersioningEnv = {
|
export type VersioningEnv = {
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import renderRoutes from '@docusaurus/renderRoutes';
|
import renderRoutes from '@docusaurus/renderRoutes';
|
||||||
import NotFound from '@theme/NotFound';
|
import NotFound from '@theme/NotFound';
|
||||||
import DocItem from '@theme/DocItem';
|
|
||||||
import DocSidebar from '@theme/DocSidebar';
|
import DocSidebar from '@theme/DocSidebar';
|
||||||
import MDXComponents from '@theme/MDXComponents';
|
import MDXComponents from '@theme/MDXComponents';
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
|
@ -16,24 +15,16 @@ import {MDXProvider} from '@mdx-js/react';
|
||||||
import {matchPath} from '@docusaurus/router';
|
import {matchPath} from '@docusaurus/router';
|
||||||
|
|
||||||
function DocPage(props) {
|
function DocPage(props) {
|
||||||
const {route: baseRoute, docsMetadata, location, content} = props;
|
const {route: baseRoute, docsMetadata, location} = props;
|
||||||
const {
|
|
||||||
permalinkToSidebar,
|
|
||||||
docsSidebars,
|
|
||||||
isHomePage,
|
|
||||||
homePagePath,
|
|
||||||
} = docsMetadata;
|
|
||||||
// case-sensitive route such as it is defined in the sidebar
|
// case-sensitive route such as it is defined in the sidebar
|
||||||
const currentRoute = !isHomePage
|
const currentRoute =
|
||||||
? baseRoute.routes.find((route) => {
|
baseRoute.routes.find((route) => {
|
||||||
return matchPath(location.pathname, route);
|
return matchPath(location.pathname, route);
|
||||||
}) || {}
|
}) || {};
|
||||||
: {};
|
const {permalinkToSidebar, docsSidebars} = docsMetadata;
|
||||||
const sidebar = isHomePage
|
const sidebar = permalinkToSidebar[currentRoute.path];
|
||||||
? content.metadata.sidebar
|
|
||||||
: permalinkToSidebar[currentRoute.path];
|
|
||||||
|
|
||||||
if (!isHomePage && Object.keys(currentRoute).length === 0) {
|
if (Object.keys(currentRoute).length === 0) {
|
||||||
return <NotFound {...props} />;
|
return <NotFound {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,16 +32,12 @@ function DocPage(props) {
|
||||||
<Layout title="Doc page" description="My Doc page">
|
<Layout title="Doc page" description="My Doc page">
|
||||||
<DocSidebar
|
<DocSidebar
|
||||||
docsSidebars={docsSidebars}
|
docsSidebars={docsSidebars}
|
||||||
path={isHomePage ? homePagePath : currentRoute.path}
|
path={currentRoute.path}
|
||||||
sidebar={sidebar}
|
sidebar={sidebar}
|
||||||
/>
|
/>
|
||||||
<section className="offset-1 mr-4 mt-4 col-xl-6 offset-xl-4 p-0 justify-content-center align-self-center overflow-hidden">
|
<section className="offset-1 mr-4 mt-4 col-xl-6 offset-xl-4 p-0 justify-content-center align-self-center overflow-hidden">
|
||||||
<MDXProvider components={MDXComponents}>
|
<MDXProvider components={MDXComponents}>
|
||||||
{isHomePage ? (
|
{renderRoutes(baseRoute.routes)}
|
||||||
<DocItem content={content} />
|
|
||||||
) : (
|
|
||||||
renderRoutes(baseRoute.routes)
|
|
||||||
)}
|
|
||||||
</MDXProvider>
|
</MDXProvider>
|
||||||
</section>
|
</section>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -11,7 +11,6 @@ import {MDXProvider} from '@mdx-js/react';
|
||||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
import renderRoutes from '@docusaurus/renderRoutes';
|
import renderRoutes from '@docusaurus/renderRoutes';
|
||||||
import Layout from '@theme/Layout';
|
import Layout from '@theme/Layout';
|
||||||
import DocItem from '@theme/DocItem';
|
|
||||||
import DocSidebar from '@theme/DocSidebar';
|
import DocSidebar from '@theme/DocSidebar';
|
||||||
import MDXComponents from '@theme/MDXComponents';
|
import MDXComponents from '@theme/MDXComponents';
|
||||||
import NotFound from '@theme/NotFound';
|
import NotFound from '@theme/NotFound';
|
||||||
|
@ -20,35 +19,22 @@ import {matchPath} from '@docusaurus/router';
|
||||||
import styles from './styles.module.css';
|
import styles from './styles.module.css';
|
||||||
|
|
||||||
function DocPage(props) {
|
function DocPage(props) {
|
||||||
const {route: baseRoute, docsMetadata, location, content} = props;
|
const {route: baseRoute, docsMetadata, location} = props;
|
||||||
const {
|
// case-sensitive route such as it is defined in the sidebar
|
||||||
permalinkToSidebar,
|
const currentRoute =
|
||||||
docsSidebars,
|
baseRoute.routes.find((route) => {
|
||||||
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);
|
return matchPath(location.pathname, route);
|
||||||
}) || {}
|
}) || {};
|
||||||
: {};
|
const {permalinkToSidebar, docsSidebars, version} = docsMetadata;
|
||||||
|
const sidebar = permalinkToSidebar[currentRoute.path];
|
||||||
const sidebar = isHomePage
|
|
||||||
? content.metadata.sidebar
|
|
||||||
: permalinkToSidebar[currentRoute.path];
|
|
||||||
const {
|
const {
|
||||||
siteConfig: {themeConfig: {sidebarCollapsible = true} = {}} = {},
|
siteConfig: {themeConfig = {}} = {},
|
||||||
isClient,
|
isClient,
|
||||||
} = useDocusaurusContext();
|
} = useDocusaurusContext();
|
||||||
|
|
||||||
if (isHomePage) {
|
const {sidebarCollapsible = true} = themeConfig;
|
||||||
content.metadata.permalink = homePagePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isHomePage && Object.keys(currentRoute).length === 0) {
|
if (Object.keys(currentRoute).length === 0) {
|
||||||
return <NotFound {...props} />;
|
return <NotFound {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +45,7 @@ function DocPage(props) {
|
||||||
<div className={styles.docSidebarContainer} role="complementary">
|
<div className={styles.docSidebarContainer} role="complementary">
|
||||||
<DocSidebar
|
<DocSidebar
|
||||||
docsSidebars={docsSidebars}
|
docsSidebars={docsSidebars}
|
||||||
path={isHomePage ? homePagePath : currentRoute.path}
|
path={currentRoute.path}
|
||||||
sidebar={sidebar}
|
sidebar={sidebar}
|
||||||
sidebarCollapsible={sidebarCollapsible}
|
sidebarCollapsible={sidebarCollapsible}
|
||||||
/>
|
/>
|
||||||
|
@ -67,11 +53,7 @@ function DocPage(props) {
|
||||||
)}
|
)}
|
||||||
<main className={styles.docMainContainer}>
|
<main className={styles.docMainContainer}>
|
||||||
<MDXProvider components={MDXComponents}>
|
<MDXProvider components={MDXComponents}>
|
||||||
{isHomePage ? (
|
{renderRoutes(baseRoute.routes)}
|
||||||
<DocItem content={content} />
|
|
||||||
) : (
|
|
||||||
renderRoutes(baseRoute.routes)
|
|
||||||
)}
|
|
||||||
</MDXProvider>
|
</MDXProvider>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,9 +28,15 @@ function usePrevious(value) {
|
||||||
return ref.current;
|
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) => {
|
const isActiveSidebarItem = (item, activePath) => {
|
||||||
if (item.type === 'link') {
|
if (item.type === 'link') {
|
||||||
return item.href === activePath;
|
return isSamePath(item.href, activePath);
|
||||||
}
|
}
|
||||||
if (item.type === 'category') {
|
if (item.type === 'category') {
|
||||||
return item.items.some((subItem) =>
|
return item.items.some((subItem) =>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue