mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-11 16:17:25 +02:00
fix(v2): improve dx sidebar config, ability to have no sidebars file (#4775)
* Improve sidebar config * Edit message * fix some little issues in the way undefined/false sidebars are handled * remove old error message as it has been moved to a better place Co-authored-by: Nam Hoang Le <nam.hoang.le@mgm-tp.com> Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
e85ec1ab12
commit
1ab8aa0af8
10 changed files with 235 additions and 129 deletions
|
@ -1,5 +1,27 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`sidebar site with wrong sidebar content 1`] = `
|
||||||
|
"Bad sidebars file.
|
||||||
|
These sidebar document ids do not exist:
|
||||||
|
- goku,
|
||||||
|
|
||||||
|
Available document ids=
|
||||||
|
- foo/bar
|
||||||
|
- foo/baz
|
||||||
|
- headingAsTitle
|
||||||
|
- hello
|
||||||
|
- ipsum
|
||||||
|
- lorem
|
||||||
|
- rootAbsoluteSlug
|
||||||
|
- rootRelativeSlug
|
||||||
|
- rootResolvedSlug
|
||||||
|
- rootTryToEscapeSlug
|
||||||
|
- slugs/absoluteSlug
|
||||||
|
- slugs/relativeSlug
|
||||||
|
- slugs/resolvedSlug
|
||||||
|
- slugs/tryToEscapeSlug"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`simple website content 1`] = `
|
exports[`simple website content 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"docs": Array [
|
"docs": Array [
|
||||||
|
@ -790,28 +812,6 @@ Object {
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`site with wrong sidebar file 1`] = `
|
|
||||||
"Bad sidebars file.
|
|
||||||
These sidebar document ids do not exist:
|
|
||||||
- goku,
|
|
||||||
|
|
||||||
Available document ids=
|
|
||||||
- foo/bar
|
|
||||||
- foo/baz
|
|
||||||
- headingAsTitle
|
|
||||||
- hello
|
|
||||||
- ipsum
|
|
||||||
- lorem
|
|
||||||
- rootAbsoluteSlug
|
|
||||||
- rootRelativeSlug
|
|
||||||
- rootResolvedSlug
|
|
||||||
- rootTryToEscapeSlug
|
|
||||||
- slugs/absoluteSlug
|
|
||||||
- slugs/relativeSlug
|
|
||||||
- slugs/resolvedSlug
|
|
||||||
- slugs/tryToEscapeSlug"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`versioned website (community) content: 100 version sidebars 1`] = `
|
exports[`versioned website (community) content: 100 version sidebars 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"version-1.0.0/community": Array [
|
"version-1.0.0/community": Array [
|
||||||
|
|
|
@ -35,6 +35,7 @@ import {toSidebarsProp} from '../props';
|
||||||
|
|
||||||
import {validate} from 'webpack';
|
import {validate} from 'webpack';
|
||||||
import {DefaultSidebarItemsGenerator} from '../sidebarItemsGenerator';
|
import {DefaultSidebarItemsGenerator} from '../sidebarItemsGenerator';
|
||||||
|
import {DisabledSidebars} from '../sidebars';
|
||||||
|
|
||||||
function findDocById(version: LoadedVersion, unversionedId: string) {
|
function findDocById(version: LoadedVersion, unversionedId: string) {
|
||||||
return version.docs.find((item) => item.unversionedId === unversionedId);
|
return version.docs.find((item) => item.unversionedId === unversionedId);
|
||||||
|
@ -124,17 +125,84 @@ Entries created:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
test('site with wrong sidebar file', async () => {
|
describe('sidebar', () => {
|
||||||
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
test('site with wrong sidebar content', async () => {
|
||||||
const context = await loadContext(siteDir);
|
const siteDir = path.join(__dirname, '__fixtures__', 'simple-site');
|
||||||
const sidebarPath = path.join(siteDir, 'wrong-sidebars.json');
|
const context = await loadContext(siteDir);
|
||||||
const plugin = pluginContentDocs(
|
const sidebarPath = path.join(siteDir, 'wrong-sidebars.json');
|
||||||
context,
|
const plugin = pluginContentDocs(
|
||||||
normalizePluginOptions(OptionsSchema, {
|
context,
|
||||||
sidebarPath,
|
normalizePluginOptions(OptionsSchema, {
|
||||||
}),
|
sidebarPath,
|
||||||
);
|
}),
|
||||||
await expect(plugin.loadContent!()).rejects.toThrowErrorMatchingSnapshot();
|
);
|
||||||
|
await expect(plugin.loadContent!()).rejects.toThrowErrorMatchingSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('site with wrong sidebar file path', async () => {
|
||||||
|
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
||||||
|
const context = await loadContext(siteDir);
|
||||||
|
|
||||||
|
await expect(async () => {
|
||||||
|
const plugin = pluginContentDocs(
|
||||||
|
context,
|
||||||
|
normalizePluginOptions(OptionsSchema, {
|
||||||
|
sidebarPath: 'wrong-path-sidebar.json',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
await plugin.loadContent!();
|
||||||
|
}).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||||
|
"The path to the sidebar file does not exist at [wrong-path-sidebar.json].
|
||||||
|
Please set the docs [sidebarPath] field in your config file to:
|
||||||
|
- a sidebars path that exists
|
||||||
|
- false: to disable the sidebar
|
||||||
|
- undefined: for Docusaurus generates it automatically"
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('site with undefined sidebar', async () => {
|
||||||
|
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
||||||
|
const context = await loadContext(siteDir);
|
||||||
|
const plugin = pluginContentDocs(
|
||||||
|
context,
|
||||||
|
normalizePluginOptions(OptionsSchema, {
|
||||||
|
sidebarPath: undefined,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const result = await plugin.loadContent!();
|
||||||
|
|
||||||
|
expect(result.loadedVersions).toHaveLength(1);
|
||||||
|
expect(result.loadedVersions[0].sidebars).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"defaultSidebar": Array [
|
||||||
|
Object {
|
||||||
|
"id": "hello-1",
|
||||||
|
"type": "doc",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"id": "hello-2",
|
||||||
|
"label": "Hello 2 From Doc",
|
||||||
|
"type": "doc",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('site with disabled sidebar', async () => {
|
||||||
|
const siteDir = path.join(__dirname, '__fixtures__', 'site-with-doc-label');
|
||||||
|
const context = await loadContext(siteDir);
|
||||||
|
const plugin = pluginContentDocs(
|
||||||
|
context,
|
||||||
|
normalizePluginOptions(OptionsSchema, {
|
||||||
|
sidebarPath: false,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const result = await plugin.loadContent!();
|
||||||
|
|
||||||
|
expect(result.loadedVersions).toHaveLength(1);
|
||||||
|
expect(result.loadedVersions[0].sidebars).toEqual(DisabledSidebars);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('empty/no docs website', () => {
|
describe('empty/no docs website', () => {
|
||||||
|
|
|
@ -14,8 +14,9 @@ import {
|
||||||
collectSidebarCategories,
|
collectSidebarCategories,
|
||||||
collectSidebarLinks,
|
collectSidebarLinks,
|
||||||
transformSidebarItems,
|
transformSidebarItems,
|
||||||
DefaultSidebars,
|
|
||||||
processSidebars,
|
processSidebars,
|
||||||
|
DefaultSidebars,
|
||||||
|
DisabledSidebars,
|
||||||
} from '../sidebars';
|
} from '../sidebars';
|
||||||
import {
|
import {
|
||||||
Sidebar,
|
Sidebar,
|
||||||
|
@ -127,35 +128,15 @@ describe('loadSidebars', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('unexisting path', () => {
|
test('unexisting path', () => {
|
||||||
/*
|
expect(loadSidebars('badpath')).toEqual(DisabledSidebars);
|
||||||
expect(() => loadSidebars('badpath')).toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"No sidebar file exist at path: badpath"`,
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
// See https://github.com/facebook/docusaurus/issues/3366
|
|
||||||
expect(loadSidebars('badpath')).toEqual(DefaultSidebars);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('undefined path', () => {
|
test('undefined path', () => {
|
||||||
expect(() =>
|
expect(loadSidebars(undefined)).toEqual(DefaultSidebars);
|
||||||
loadSidebars(
|
|
||||||
// @ts-expect-error: bad arg
|
|
||||||
undefined,
|
|
||||||
),
|
|
||||||
).toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"sidebarFilePath not provided: undefined"`,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('null path', () => {
|
test('literal false path', () => {
|
||||||
expect(() =>
|
expect(loadSidebars(false)).toEqual(DisabledSidebars);
|
||||||
loadSidebars(
|
|
||||||
// @ts-expect-error: bad arg
|
|
||||||
null,
|
|
||||||
),
|
|
||||||
).toThrowErrorMatchingInlineSnapshot(
|
|
||||||
`"sidebarFilePath not provided: null"`,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('sidebars with category.collapsed property', async () => {
|
test('sidebars with category.collapsed property', async () => {
|
||||||
|
|
|
@ -75,7 +75,7 @@ describe('simple site', () => {
|
||||||
),
|
),
|
||||||
isLast: true,
|
isLast: true,
|
||||||
routePriority: -1,
|
routePriority: -1,
|
||||||
sidebarFilePath: path.join(simpleSiteDir, 'sidebars.json'),
|
sidebarFilePath: undefined,
|
||||||
versionLabel: 'Next',
|
versionLabel: 'Next',
|
||||||
versionName: 'current',
|
versionName: 'current',
|
||||||
versionPath: '/docs',
|
versionPath: '/docs',
|
||||||
|
@ -138,6 +138,9 @@ describe('simple site', () => {
|
||||||
versionPath: '/myBaseUrl/docs/current-path',
|
versionPath: '/myBaseUrl/docs/current-path',
|
||||||
versionLabel: 'current-label',
|
versionLabel: 'current-label',
|
||||||
routePriority: undefined,
|
routePriority: undefined,
|
||||||
|
sidebarFilePath: undefined,
|
||||||
|
versionEditUrl: undefined,
|
||||||
|
versionEditUrlLocalized: undefined,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -210,6 +213,7 @@ describe('versioned site, pluginId=default', () => {
|
||||||
const defaultOptions: PluginOptions = {
|
const defaultOptions: PluginOptions = {
|
||||||
id: DEFAULT_PLUGIN_ID,
|
id: DEFAULT_PLUGIN_ID,
|
||||||
...DEFAULT_OPTIONS,
|
...DEFAULT_OPTIONS,
|
||||||
|
sidebarPath: 'sidebars.json',
|
||||||
};
|
};
|
||||||
const defaultContext = {
|
const defaultContext = {
|
||||||
siteDir: versionedSiteDir,
|
siteDir: versionedSiteDir,
|
||||||
|
@ -607,6 +611,7 @@ describe('versioned site, pluginId=community', () => {
|
||||||
id: 'community',
|
id: 'community',
|
||||||
path: 'community',
|
path: 'community',
|
||||||
routeBasePath: 'communityBasePath',
|
routeBasePath: 'communityBasePath',
|
||||||
|
sidebarPath: 'sidebars.json',
|
||||||
};
|
};
|
||||||
const defaultContext = {
|
const defaultContext = {
|
||||||
siteDir: versionedSiteDir,
|
siteDir: versionedSiteDir,
|
||||||
|
|
|
@ -20,6 +20,67 @@ import {
|
||||||
import {loadSidebars} from './sidebars';
|
import {loadSidebars} from './sidebars';
|
||||||
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
||||||
|
|
||||||
|
function createVersionedSidebarFile({
|
||||||
|
siteDir,
|
||||||
|
pluginId,
|
||||||
|
sidebarPath,
|
||||||
|
version,
|
||||||
|
}: {
|
||||||
|
siteDir: string;
|
||||||
|
pluginId: string;
|
||||||
|
sidebarPath: string | false | undefined;
|
||||||
|
version: string;
|
||||||
|
}) {
|
||||||
|
// Load current sidebar and create a new versioned sidebars file (if needed).
|
||||||
|
const loadedSidebars = loadSidebars(sidebarPath);
|
||||||
|
|
||||||
|
// Do not create a useless versioned sidebars file if sidebars file is empty or sidebars are disabled/false)
|
||||||
|
const shouldCreateVersionedSidebarFile =
|
||||||
|
Object.keys(loadedSidebars).length > 0;
|
||||||
|
|
||||||
|
if (shouldCreateVersionedSidebarFile) {
|
||||||
|
// TODO @slorber: this "version prefix" in versioned sidebars looks like a bad idea to me
|
||||||
|
// TODO try to get rid of it
|
||||||
|
// Transform id in original sidebar to versioned id.
|
||||||
|
const normalizeItem = (
|
||||||
|
item: UnprocessedSidebarItem,
|
||||||
|
): UnprocessedSidebarItem => {
|
||||||
|
switch (item.type) {
|
||||||
|
case 'category':
|
||||||
|
return {...item, items: item.items.map(normalizeItem)};
|
||||||
|
case 'ref':
|
||||||
|
case 'doc':
|
||||||
|
return {
|
||||||
|
type: item.type,
|
||||||
|
id: `version-${version}/${item.id}`,
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const versionedSidebar: UnprocessedSidebars = Object.entries(
|
||||||
|
loadedSidebars,
|
||||||
|
).reduce((acc: UnprocessedSidebars, [sidebarId, sidebarItems]) => {
|
||||||
|
const newVersionedSidebarId = `version-${version}/${sidebarId}`;
|
||||||
|
acc[newVersionedSidebarId] = sidebarItems.map(normalizeItem);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const versionedSidebarsDir = getVersionedSidebarsDirPath(siteDir, pluginId);
|
||||||
|
const newSidebarFile = path.join(
|
||||||
|
versionedSidebarsDir,
|
||||||
|
`version-${version}-sidebars.json`,
|
||||||
|
);
|
||||||
|
fs.ensureDirSync(path.dirname(newSidebarFile));
|
||||||
|
fs.writeFileSync(
|
||||||
|
newSidebarFile,
|
||||||
|
`${JSON.stringify(versionedSidebar, null, 2)}\n`,
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests depend on non-default export for mocking.
|
// Tests depend on non-default export for mocking.
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export function cliDocsVersionCommand(
|
export function cliDocsVersionCommand(
|
||||||
|
@ -92,50 +153,7 @@ export function cliDocsVersionCommand(
|
||||||
throw new Error(`${pluginIdLogPrefix}There is no docs to version !`);
|
throw new Error(`${pluginIdLogPrefix}There is no docs to version !`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load current sidebar and create a new versioned sidebars file.
|
createVersionedSidebarFile({siteDir, pluginId, version, sidebarPath});
|
||||||
if (fs.existsSync(sidebarPath)) {
|
|
||||||
const loadedSidebars = loadSidebars(sidebarPath);
|
|
||||||
|
|
||||||
// TODO @slorber: this "version prefix" in versioned sidebars looks like a bad idea to me
|
|
||||||
// TODO try to get rid of it
|
|
||||||
// Transform id in original sidebar to versioned id.
|
|
||||||
const normalizeItem = (
|
|
||||||
item: UnprocessedSidebarItem,
|
|
||||||
): UnprocessedSidebarItem => {
|
|
||||||
switch (item.type) {
|
|
||||||
case 'category':
|
|
||||||
return {...item, items: item.items.map(normalizeItem)};
|
|
||||||
case 'ref':
|
|
||||||
case 'doc':
|
|
||||||
return {
|
|
||||||
type: item.type,
|
|
||||||
id: `version-${version}/${item.id}`,
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const versionedSidebar: UnprocessedSidebars = Object.entries(
|
|
||||||
loadedSidebars,
|
|
||||||
).reduce((acc: UnprocessedSidebars, [sidebarId, sidebarItems]) => {
|
|
||||||
const newVersionedSidebarId = `version-${version}/${sidebarId}`;
|
|
||||||
acc[newVersionedSidebarId] = sidebarItems.map(normalizeItem);
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const versionedSidebarsDir = getVersionedSidebarsDirPath(siteDir, pluginId);
|
|
||||||
const newSidebarFile = path.join(
|
|
||||||
versionedSidebarsDir,
|
|
||||||
`version-${version}-sidebars.json`,
|
|
||||||
);
|
|
||||||
fs.ensureDirSync(path.dirname(newSidebarFile));
|
|
||||||
fs.writeFileSync(
|
|
||||||
newSidebarFile,
|
|
||||||
`${JSON.stringify(versionedSidebar, null, 2)}\n`,
|
|
||||||
'utf8',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update versions.json file.
|
// Update versions.json file.
|
||||||
versions.unshift(version);
|
versions.unshift(version);
|
||||||
|
|
|
@ -118,8 +118,7 @@ export default function pluginContentDocs(
|
||||||
|
|
||||||
getPathsToWatch() {
|
getPathsToWatch() {
|
||||||
function getVersionPathsToWatch(version: VersionMetadata): string[] {
|
function getVersionPathsToWatch(version: VersionMetadata): string[] {
|
||||||
return [
|
const result = [
|
||||||
version.sidebarFilePath,
|
|
||||||
...flatten(
|
...flatten(
|
||||||
options.include.map((pattern) =>
|
options.include.map((pattern) =>
|
||||||
getDocsDirPaths(version).map(
|
getDocsDirPaths(version).map(
|
||||||
|
@ -129,6 +128,10 @@ export default function pluginContentDocs(
|
||||||
),
|
),
|
||||||
`${version.contentPath}/**/${CategoryMetadataFilenamePattern}`,
|
`${version.contentPath}/**/${CategoryMetadataFilenamePattern}`,
|
||||||
];
|
];
|
||||||
|
if (typeof version.sidebarFilePath === 'string') {
|
||||||
|
result.unshift(version.sidebarFilePath);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flatten(versionsMetadata.map(getVersionPathsToWatch));
|
return flatten(versionsMetadata.map(getVersionPathsToWatch));
|
||||||
|
|
|
@ -21,12 +21,11 @@ import {
|
||||||
DisabledNumberPrefixParser,
|
DisabledNumberPrefixParser,
|
||||||
} from './numberPrefix';
|
} from './numberPrefix';
|
||||||
|
|
||||||
export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id'> = {
|
export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
|
||||||
path: 'docs', // Path to data on filesystem, relative to site dir.
|
path: 'docs', // Path to data on filesystem, relative to site dir.
|
||||||
routeBasePath: 'docs', // URL Route.
|
routeBasePath: 'docs', // URL Route.
|
||||||
homePageId: undefined, // TODO remove soon, deprecated
|
homePageId: undefined, // TODO remove soon, deprecated
|
||||||
include: ['**/*.{md,mdx}'], // Extensions to include.
|
include: ['**/*.{md,mdx}'], // Extensions to include.
|
||||||
sidebarPath: 'sidebars.json', // Path to the sidebars configuration file
|
|
||||||
sidebarItemsGenerator: DefaultSidebarItemsGenerator,
|
sidebarItemsGenerator: DefaultSidebarItemsGenerator,
|
||||||
numberPrefixParser: DefaultNumberPrefixParser,
|
numberPrefixParser: DefaultNumberPrefixParser,
|
||||||
docLayoutComponent: '@theme/DocPage',
|
docLayoutComponent: '@theme/DocPage',
|
||||||
|
@ -67,7 +66,10 @@ export const OptionsSchema = Joi.object({
|
||||||
.default(DEFAULT_OPTIONS.routeBasePath),
|
.default(DEFAULT_OPTIONS.routeBasePath),
|
||||||
homePageId: Joi.string().optional(),
|
homePageId: Joi.string().optional(),
|
||||||
include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include),
|
include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include),
|
||||||
sidebarPath: Joi.string().allow('').default(DEFAULT_OPTIONS.sidebarPath),
|
sidebarPath: Joi.alternatives().try(
|
||||||
|
Joi.boolean().invalid(true),
|
||||||
|
Joi.string(),
|
||||||
|
),
|
||||||
sidebarItemsGenerator: Joi.function().default(
|
sidebarItemsGenerator: Joi.function().default(
|
||||||
() => DEFAULT_OPTIONS.sidebarItemsGenerator,
|
() => DEFAULT_OPTIONS.sidebarItemsGenerator,
|
||||||
),
|
),
|
||||||
|
|
|
@ -254,18 +254,29 @@ export const DefaultSidebars: UnprocessedSidebars = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DisabledSidebars: UnprocessedSidebars = {};
|
||||||
|
|
||||||
// TODO refactor: make async
|
// TODO refactor: make async
|
||||||
export function loadSidebars(sidebarFilePath: string): UnprocessedSidebars {
|
export function loadSidebars(
|
||||||
if (!sidebarFilePath) {
|
sidebarFilePath: string | false | undefined,
|
||||||
throw new Error(`sidebarFilePath not provided: ${sidebarFilePath}`);
|
): UnprocessedSidebars {
|
||||||
|
// false => no sidebars
|
||||||
|
if (sidebarFilePath === false) {
|
||||||
|
return DisabledSidebars;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No sidebars file: by default we use the file-system structure to generate the sidebar
|
// undefined => defaults to autogenerated sidebars
|
||||||
// See https://github.com/facebook/docusaurus/pull/4582
|
if (typeof sidebarFilePath === 'undefined') {
|
||||||
if (!fs.existsSync(sidebarFilePath)) {
|
|
||||||
return DefaultSidebars;
|
return DefaultSidebars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unexisting sidebars file: no sidebars
|
||||||
|
// Note: this edge case can happen on versioned docs, not current version
|
||||||
|
// We avoid creating empty versioned sidebars file with the CLI
|
||||||
|
if (!fs.existsSync(sidebarFilePath)) {
|
||||||
|
return DisabledSidebars;
|
||||||
|
}
|
||||||
|
|
||||||
// We don't want sidebars to be cached because of hot reloading.
|
// We don't want sidebars to be cached because of hot reloading.
|
||||||
const sidebarJson = importFresh(sidebarFilePath) as SidebarsJSON;
|
const sidebarJson = importFresh(sidebarFilePath) as SidebarsJSON;
|
||||||
return normalizeSidebars(sidebarJson);
|
return normalizeSidebars(sidebarJson);
|
||||||
|
|
|
@ -31,9 +31,7 @@ export type VersionMetadata = ContentPaths & {
|
||||||
versionEditUrl?: string | undefined;
|
versionEditUrl?: string | undefined;
|
||||||
versionEditUrlLocalized?: string | undefined;
|
versionEditUrlLocalized?: string | undefined;
|
||||||
isLast: boolean;
|
isLast: boolean;
|
||||||
// contentPath: string; // "versioned_docs/version-1.0.0"
|
sidebarFilePath: string | false | undefined; // versioned_sidebars/1.0.0.json
|
||||||
// contentPathLocalized: string; // "i18n/fr/version-1.0.0/default"
|
|
||||||
sidebarFilePath: string; // versioned_sidebars/1.0.0.json
|
|
||||||
routePriority: number | undefined; // -1 for the latest docs
|
routePriority: number | undefined; // -1 for the latest docs
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,7 +56,7 @@ export type MetadataOptions = {
|
||||||
|
|
||||||
export type PathOptions = {
|
export type PathOptions = {
|
||||||
path: string;
|
path: string;
|
||||||
sidebarPath: string;
|
sidebarPath?: string | false | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type VersionOptions = {
|
export type VersionOptions = {
|
||||||
|
|
|
@ -24,7 +24,6 @@ import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
||||||
import {LoadContext} from '@docusaurus/types';
|
import {LoadContext} from '@docusaurus/types';
|
||||||
import {getPluginI18nPath, normalizeUrl, posixPath} from '@docusaurus/utils';
|
import {getPluginI18nPath, normalizeUrl, posixPath} from '@docusaurus/utils';
|
||||||
import {difference} from 'lodash';
|
import {difference} from 'lodash';
|
||||||
import chalk from 'chalk';
|
|
||||||
|
|
||||||
// retro-compatibility: no prefix for the default plugin id
|
// retro-compatibility: no prefix for the default plugin id
|
||||||
function addPluginIdPrefix(fileOrDir: string, pluginId: string): string {
|
function addPluginIdPrefix(fileOrDir: string, pluginId: string): string {
|
||||||
|
@ -183,14 +182,24 @@ function getVersionMetadataPaths({
|
||||||
versionName,
|
versionName,
|
||||||
});
|
});
|
||||||
|
|
||||||
const sidebarFilePath = isCurrentVersion
|
function getSidebarFilePath() {
|
||||||
? path.resolve(context.siteDir, options.sidebarPath)
|
if (isCurrentVersion) {
|
||||||
: path.join(
|
return options.sidebarPath
|
||||||
|
? path.resolve(context.siteDir, options.sidebarPath)
|
||||||
|
: options.sidebarPath;
|
||||||
|
} else {
|
||||||
|
return path.join(
|
||||||
getVersionedSidebarsDirPath(context.siteDir, options.id),
|
getVersionedSidebarsDirPath(context.siteDir, options.id),
|
||||||
`version-${versionName}-sidebars.json`,
|
`version-${versionName}-sidebars.json`,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {contentPath, contentPathLocalized, sidebarFilePath};
|
return {
|
||||||
|
contentPath,
|
||||||
|
contentPathLocalized,
|
||||||
|
sidebarFilePath: getSidebarFilePath(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVersionEditUrls({
|
function getVersionEditUrls({
|
||||||
|
@ -330,6 +339,7 @@ function checkVersionMetadataPaths({
|
||||||
}) {
|
}) {
|
||||||
const {versionName, contentPath, sidebarFilePath} = versionMetadata;
|
const {versionName, contentPath, sidebarFilePath} = versionMetadata;
|
||||||
const {siteDir} = context;
|
const {siteDir} = context;
|
||||||
|
const isCurrentVersion = versionName === CURRENT_VERSION_NAME;
|
||||||
|
|
||||||
if (!fs.existsSync(contentPath)) {
|
if (!fs.existsSync(contentPath)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -340,13 +350,23 @@ function checkVersionMetadataPaths({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the current version defines a path to a sidebar file that does not exist, we throw!
|
||||||
|
// Note: for versioned sidebars, the file may not exist (as we prefer to not create it rather than to create an empty file)
|
||||||
// See https://github.com/facebook/docusaurus/issues/3366
|
// See https://github.com/facebook/docusaurus/issues/3366
|
||||||
if (!fs.existsSync(sidebarFilePath)) {
|
// See https://github.com/facebook/docusaurus/pull/4775
|
||||||
console.log(
|
if (
|
||||||
chalk.yellow(
|
isCurrentVersion &&
|
||||||
`The sidebar file of docs version [${versionName}] does not exist. It is optional, but should rather be provided at ${sidebarFilePath}`,
|
typeof sidebarFilePath === 'string' &&
|
||||||
),
|
!fs.existsSync(sidebarFilePath)
|
||||||
);
|
) {
|
||||||
|
throw new Error(`The path to the sidebar file does not exist at [${path.relative(
|
||||||
|
siteDir,
|
||||||
|
sidebarFilePath,
|
||||||
|
)}].
|
||||||
|
Please set the docs [sidebarPath] field in your config file to:
|
||||||
|
- a sidebars path that exists
|
||||||
|
- false: to disable the sidebar
|
||||||
|
- undefined: for Docusaurus generates it automatically`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue