mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 18:27:56 +02:00
feat: docs plugin options sidebarCollapsible + sidebarCollapsed (#5203)
* Add prop Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * Add `collapsible` option to sidebar item Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * Add eslint-ignore Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * Move new page Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * Allow in autogenerated Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * Fix tests Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * Move config options to plugin-docs Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * Make non-collapsible items always expanded Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * docs versioning cli should receive a single options object * Update cli.test.ts * revert validateCategoryMetadataFile change * remove theme usage of themeConfig.sidebarCollapsible * better handling of sidebar item category inconsistencies + add warning message * Update snapshot Signed-off-by: Josh-Cena <sidachen2003@gmail.com> * Handle plugin option inconsistencies * improve doc for new sidebarCollapsible doc options * remove warning in fixSidebarItemInconsistencies as it will be annoyed for versioned sites, as "collapsed" is already persisted in sidebar json files Co-authored-by: slorber <lorber.sebastien@gmail.com>
This commit is contained in:
parent
b38c35a36d
commit
24156efcfb
27 changed files with 487 additions and 109 deletions
|
@ -5,9 +5,11 @@ Object {
|
|||
"version-1.0.0/docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-1.0.0/foo/bar",
|
||||
|
@ -36,6 +38,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-1.0.0/hello",
|
||||
|
@ -54,6 +57,7 @@ Object {
|
|||
"version-2.0.0/docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-2.0.0/foo/bar",
|
||||
|
@ -65,6 +69,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-2.0.0/hello",
|
||||
|
|
|
@ -27,9 +27,11 @@ Object {
|
|||
"docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "foo/bar",
|
||||
|
@ -58,6 +60,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "hello",
|
||||
|
@ -410,12 +413,12 @@ Object {
|
|||
\\"docsSidebars\\": {
|
||||
\\"docs\\": [
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Test\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"label\\": \\"foo\\",
|
||||
\\"items\\": [
|
||||
|
@ -429,7 +432,9 @@ Object {
|
|||
\\"label\\": \\"baz\\",
|
||||
\\"href\\": \\"/docs/foo/bazSlug.html\\"
|
||||
}
|
||||
]
|
||||
],
|
||||
\\"collapsible\\": true,
|
||||
\\"collapsed\\": true
|
||||
},
|
||||
{
|
||||
\\"type\\": \\"link\\",
|
||||
|
@ -444,8 +449,9 @@ Object {
|
|||
]
|
||||
},
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Guides\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
|
@ -806,6 +812,10 @@ Object {
|
|||
"type": "autogenerated",
|
||||
},
|
||||
"numberPrefixParser": [Function],
|
||||
"options": Object {
|
||||
"sidebarCollapsed": true,
|
||||
"sidebarCollapsible": true,
|
||||
},
|
||||
"version": Object {
|
||||
"contentPath": "docs",
|
||||
"versionName": "current",
|
||||
|
@ -992,6 +1002,7 @@ Object {
|
|||
"version-1.0.0/docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-1.0.0/foo/bar",
|
||||
|
@ -1007,6 +1018,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-1.0.0/hello",
|
||||
|
@ -1025,6 +1037,7 @@ Object {
|
|||
"version-1.0.1/docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-1.0.1/foo/bar",
|
||||
|
@ -1036,6 +1049,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-1.0.1/hello",
|
||||
|
@ -1054,6 +1068,7 @@ Object {
|
|||
"docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "foo/bar",
|
||||
|
@ -1065,6 +1080,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "hello",
|
||||
|
@ -1404,8 +1420,9 @@ Object {
|
|||
\\"docsSidebars\\": {
|
||||
\\"version-1.0.0/docs\\": [
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Test\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
|
@ -1421,8 +1438,9 @@ Object {
|
|||
]
|
||||
},
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Guides\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
|
@ -1444,8 +1462,9 @@ Object {
|
|||
\\"docsSidebars\\": {
|
||||
\\"version-1.0.1/docs\\": [
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Test\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
|
@ -1456,8 +1475,9 @@ Object {
|
|||
]
|
||||
},
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Guides\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
|
@ -1479,8 +1499,9 @@ Object {
|
|||
\\"docsSidebars\\": {
|
||||
\\"docs\\": [
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Test\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
|
@ -1491,8 +1512,9 @@ Object {
|
|||
]
|
||||
},
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Guides\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
|
@ -1514,8 +1536,9 @@ Object {
|
|||
\\"docsSidebars\\": {
|
||||
\\"version-1.0.1/docs\\": [
|
||||
{
|
||||
\\"collapsed\\": true,
|
||||
\\"type\\": \\"category\\",
|
||||
\\"collapsed\\": true,
|
||||
\\"collapsible\\": true,
|
||||
\\"label\\": \\"Test\\",
|
||||
\\"items\\": [
|
||||
{
|
||||
|
@ -1888,6 +1911,7 @@ Object {
|
|||
"version-1.0.1/docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "version-withSlugs/rootAbsoluteSlug",
|
||||
|
|
|
@ -5,6 +5,7 @@ Object {
|
|||
"docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"href": "https://github.com",
|
||||
|
@ -24,9 +25,11 @@ Object {
|
|||
"docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "doc1",
|
||||
|
@ -42,9 +45,11 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "doc2",
|
||||
|
@ -67,6 +72,7 @@ Object {
|
|||
"docs": Array [
|
||||
Object {
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "doc1",
|
||||
|
@ -78,6 +84,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": false,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "doc2",
|
||||
|
@ -96,6 +103,7 @@ Object {
|
|||
"docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "a",
|
||||
|
@ -103,9 +111,11 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "c",
|
||||
|
@ -113,6 +123,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "d",
|
||||
|
@ -120,6 +131,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "e",
|
||||
|
@ -158,6 +170,7 @@ Object {
|
|||
"docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "greeting",
|
||||
|
@ -180,6 +193,7 @@ Object {
|
|||
"docs": Array [
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "foo/bar",
|
||||
|
@ -204,6 +218,7 @@ Object {
|
|||
},
|
||||
Object {
|
||||
"collapsed": true,
|
||||
"collapsible": true,
|
||||
"items": Array [
|
||||
Object {
|
||||
"id": "hello",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import path from 'path';
|
||||
import {cliDocsVersionCommand} from '../cli';
|
||||
import {PathOptions} from '../types';
|
||||
import {PathOptions, SidebarOptions} from '../types';
|
||||
import fs from 'fs-extra';
|
||||
import {
|
||||
getVersionedDocsDirPath,
|
||||
|
@ -21,9 +21,12 @@ const fixtureDir = path.join(__dirname, '__fixtures__');
|
|||
describe('docsVersion', () => {
|
||||
const simpleSiteDir = path.join(fixtureDir, 'simple-site');
|
||||
const versionedSiteDir = path.join(fixtureDir, 'versioned-site');
|
||||
const DEFAULT_OPTIONS: PathOptions = {
|
||||
|
||||
const DEFAULT_OPTIONS: PathOptions & SidebarOptions = {
|
||||
path: 'docs',
|
||||
sidebarPath: '',
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
};
|
||||
|
||||
test('no version tag provided', () => {
|
||||
|
@ -186,17 +189,17 @@ describe('docsVersion', () => {
|
|||
let versionedSidebarPath;
|
||||
writeMock.mockImplementationOnce((filepath, content) => {
|
||||
versionedSidebarPath = filepath;
|
||||
versionedSidebar = JSON.parse(content);
|
||||
versionedSidebar = JSON.parse(content as string);
|
||||
});
|
||||
let versionsPath;
|
||||
let versions;
|
||||
writeMock.mockImplementationOnce((filepath, content) => {
|
||||
versionsPath = filepath;
|
||||
versions = JSON.parse(content);
|
||||
versions = JSON.parse(content as string);
|
||||
});
|
||||
const consoleMock = jest.spyOn(console, 'log').mockImplementation();
|
||||
const options = {
|
||||
path: 'docs',
|
||||
...DEFAULT_OPTIONS,
|
||||
sidebarPath: path.join(simpleSiteDir, 'sidebars.json'),
|
||||
};
|
||||
cliDocsVersionCommand('1.0.0', simpleSiteDir, DEFAULT_PLUGIN_ID, options);
|
||||
|
@ -234,17 +237,17 @@ describe('docsVersion', () => {
|
|||
let versionedSidebarPath;
|
||||
writeMock.mockImplementationOnce((filepath, content) => {
|
||||
versionedSidebarPath = filepath;
|
||||
versionedSidebar = JSON.parse(content);
|
||||
versionedSidebar = JSON.parse(content as string);
|
||||
});
|
||||
let versionsPath;
|
||||
let versions;
|
||||
writeMock.mockImplementationOnce((filepath, content) => {
|
||||
versionsPath = filepath;
|
||||
versions = JSON.parse(content);
|
||||
versions = JSON.parse(content as string);
|
||||
});
|
||||
const consoleMock = jest.spyOn(console, 'log').mockImplementation();
|
||||
const options = {
|
||||
path: 'docs',
|
||||
...DEFAULT_OPTIONS,
|
||||
sidebarPath: path.join(versionedSiteDir, 'sidebars.json'),
|
||||
};
|
||||
cliDocsVersionCommand(
|
||||
|
@ -289,16 +292,17 @@ describe('docsVersion', () => {
|
|||
let versionedSidebarPath;
|
||||
writeMock.mockImplementationOnce((filepath, content) => {
|
||||
versionedSidebarPath = filepath;
|
||||
versionedSidebar = JSON.parse(content);
|
||||
versionedSidebar = JSON.parse(content as string);
|
||||
});
|
||||
let versionsPath;
|
||||
let versions;
|
||||
writeMock.mockImplementationOnce((filepath, content) => {
|
||||
versionsPath = filepath;
|
||||
versions = JSON.parse(content);
|
||||
versions = JSON.parse(content as string);
|
||||
});
|
||||
const consoleMock = jest.spyOn(console, 'log').mockImplementation();
|
||||
const options = {
|
||||
...DEFAULT_OPTIONS,
|
||||
path: 'community',
|
||||
sidebarPath: path.join(versionedSiteDir, 'community_sidebars.json'),
|
||||
};
|
||||
|
|
|
@ -270,6 +270,8 @@ describe('simple website', () => {
|
|||
expect(mock).toHaveBeenCalledWith('1.0.0', siteDir, DEFAULT_PLUGIN_ID, {
|
||||
path: 'docs',
|
||||
sidebarPath,
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
});
|
||||
mock.mockRestore();
|
||||
});
|
||||
|
@ -478,6 +480,8 @@ describe('versioned website', () => {
|
|||
expect(mock).toHaveBeenCalledWith('2.0.0', siteDir, DEFAULT_PLUGIN_ID, {
|
||||
path: routeBasePath,
|
||||
sidebarPath,
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
});
|
||||
mock.mockRestore();
|
||||
});
|
||||
|
@ -729,6 +733,8 @@ describe('versioned website (community)', () => {
|
|||
expect(mock).toHaveBeenCalledWith('2.0.0', siteDir, pluginId, {
|
||||
path: routeBasePath,
|
||||
sidebarPath,
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
});
|
||||
mock.mockRestore();
|
||||
});
|
||||
|
@ -907,6 +913,7 @@ describe('site with full autogenerated sidebar', () => {
|
|||
type: 'category',
|
||||
label: 'Guides',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -938,6 +945,7 @@ describe('site with full autogenerated sidebar', () => {
|
|||
type: 'category',
|
||||
label: 'API (label from _category_.json)',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -947,6 +955,7 @@ describe('site with full autogenerated sidebar', () => {
|
|||
type: 'category',
|
||||
label: 'Core APIs',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -963,6 +972,7 @@ describe('site with full autogenerated sidebar', () => {
|
|||
type: 'category',
|
||||
label: 'Extension APIs (label from _category_.yml)',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -1461,6 +1471,7 @@ describe('site with partial autogenerated sidebars', () => {
|
|||
type: 'category',
|
||||
label: 'Some category',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -1650,6 +1661,7 @@ describe('site with partial autogenerated sidebars 2 (fix #4638)', () => {
|
|||
type: 'category',
|
||||
label: 'Core APIs',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -1666,6 +1678,7 @@ describe('site with partial autogenerated sidebars 2 (fix #4638)', () => {
|
|||
type: 'category',
|
||||
label: 'Extension APIs (label from _category_.yml)', // Fix #4638
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -1782,6 +1795,7 @@ describe('site with custom sidebar items generator', () => {
|
|||
type: 'category',
|
||||
label: 'API (label from _category_.json)',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -1791,6 +1805,7 @@ describe('site with custom sidebar items generator', () => {
|
|||
type: 'category',
|
||||
label: 'Extension APIs (label from _category_.yml)',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -1806,6 +1821,7 @@ describe('site with custom sidebar items generator', () => {
|
|||
type: 'category',
|
||||
label: 'Core APIs',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
@ -1827,6 +1843,7 @@ describe('site with custom sidebar items generator', () => {
|
|||
type: 'category',
|
||||
label: 'Guides',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {OptionsSchema, DEFAULT_OPTIONS} from '../options';
|
||||
import {OptionsSchema, DEFAULT_OPTIONS, validateOptions} from '../options';
|
||||
import {normalizePluginOptions} from '@docusaurus/utils-validation';
|
||||
import {DefaultSidebarItemsGenerator} from '../sidebarItemsGenerator';
|
||||
import {
|
||||
|
@ -13,11 +13,22 @@ import {
|
|||
DisabledNumberPrefixParser,
|
||||
} from '../numberPrefix';
|
||||
import {GlobExcludeDefault} from '@docusaurus/utils';
|
||||
import {PluginOptions} from '../types';
|
||||
|
||||
// the type of remark/rehype plugins is function
|
||||
const markdownPluginsFunctionStub = () => {};
|
||||
const markdownPluginsObjectStub = {};
|
||||
|
||||
function testValidateOptions(options: Partial<PluginOptions>) {
|
||||
return validateOptions({
|
||||
options: {
|
||||
...DEFAULT_OPTIONS,
|
||||
...options,
|
||||
},
|
||||
validate: normalizePluginOptions,
|
||||
});
|
||||
}
|
||||
|
||||
describe('normalizeDocsPluginOptions', () => {
|
||||
test('should return default options for undefined user options', async () => {
|
||||
const {value, error} = await OptionsSchema.validate({});
|
||||
|
@ -58,6 +69,8 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
label: 'world',
|
||||
},
|
||||
},
|
||||
sidebarCollapsible: false,
|
||||
sidebarCollapsed: false,
|
||||
};
|
||||
const {value, error} = await OptionsSchema.validate(userOptions);
|
||||
expect(value).toEqual(userOptions);
|
||||
|
@ -230,4 +243,30 @@ describe('normalizeDocsPluginOptions', () => {
|
|||
`"\\"versions.current.hey\\" is not allowed"`,
|
||||
);
|
||||
});
|
||||
|
||||
test('should handle sidebarCollapsed option inconsistencies', () => {
|
||||
expect(
|
||||
testValidateOptions({
|
||||
...DEFAULT_OPTIONS,
|
||||
sidebarCollapsible: true,
|
||||
sidebarCollapsed: undefined,
|
||||
}).sidebarCollapsed,
|
||||
).toEqual(true);
|
||||
|
||||
expect(
|
||||
testValidateOptions({
|
||||
...DEFAULT_OPTIONS,
|
||||
sidebarCollapsible: false,
|
||||
sidebarCollapsed: undefined,
|
||||
}).sidebarCollapsed,
|
||||
).toEqual(false);
|
||||
|
||||
expect(
|
||||
testValidateOptions({
|
||||
...DEFAULT_OPTIONS,
|
||||
sidebarCollapsible: false,
|
||||
sidebarCollapsed: true,
|
||||
}).sidebarCollapsed,
|
||||
).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,14 +9,13 @@ import {
|
|||
CategoryMetadatasFile,
|
||||
DefaultSidebarItemsGenerator,
|
||||
} from '../sidebarItemsGenerator';
|
||||
import {DefaultCategoryCollapsedValue} from '../sidebars';
|
||||
import {Sidebar, SidebarItemsGenerator} from '../types';
|
||||
import fs from 'fs-extra';
|
||||
import {DefaultNumberPrefixParser} from '../numberPrefix';
|
||||
|
||||
describe('DefaultSidebarItemsGenerator', () => {
|
||||
function testDefaultSidebarItemsGenerator(
|
||||
options: Partial<Parameters<SidebarItemsGenerator>[0]>,
|
||||
params: Partial<Parameters<SidebarItemsGenerator>[0]>,
|
||||
) {
|
||||
return DefaultSidebarItemsGenerator({
|
||||
numberPrefixParser: DefaultNumberPrefixParser,
|
||||
|
@ -29,7 +28,11 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
contentPath: 'docs',
|
||||
},
|
||||
docs: [],
|
||||
...options,
|
||||
options: {
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
},
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -110,6 +113,10 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
frontMatter: {},
|
||||
},
|
||||
],
|
||||
options: {
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
|
@ -190,6 +197,10 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
frontMatter: {},
|
||||
},
|
||||
],
|
||||
options: {
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
|
@ -197,7 +208,8 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
{
|
||||
type: 'category',
|
||||
label: 'Tutorials',
|
||||
collapsed: DefaultCategoryCollapsedValue,
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{type: 'doc', id: 'tutorial1'},
|
||||
{type: 'doc', id: 'tutorial2'},
|
||||
|
@ -207,12 +219,14 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
type: 'category',
|
||||
label: 'Guides',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{type: 'doc', id: 'guide1'},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'SubGuides (metadata file label)',
|
||||
collapsed: DefaultCategoryCollapsedValue,
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [{type: 'doc', id: 'nested-guide'}],
|
||||
},
|
||||
{type: 'doc', id: 'guide2'},
|
||||
|
@ -233,6 +247,7 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
'subfolder/subsubfolder/subsubsubfolder3/_category_.json': {
|
||||
position: 1,
|
||||
label: 'subsubsubfolder3 (_category_.json label)',
|
||||
collapsible: false,
|
||||
collapsed: false,
|
||||
},
|
||||
});
|
||||
|
@ -305,6 +320,10 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
frontMatter: {},
|
||||
},
|
||||
],
|
||||
options: {
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
|
@ -312,6 +331,7 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
type: 'category',
|
||||
label: 'subsubsubfolder3 (_category_.json label)',
|
||||
collapsed: false,
|
||||
collapsible: false,
|
||||
items: [
|
||||
{type: 'doc', id: 'doc8'},
|
||||
{type: 'doc', id: 'doc7'},
|
||||
|
@ -321,6 +341,7 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
type: 'category',
|
||||
label: 'subsubsubfolder2 (_category_.yml label)',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [{type: 'doc', id: 'doc6'}],
|
||||
},
|
||||
{type: 'doc', id: 'doc1'},
|
||||
|
@ -329,6 +350,7 @@ describe('DefaultSidebarItemsGenerator', () => {
|
|||
type: 'category',
|
||||
label: 'subsubsubfolder',
|
||||
collapsed: true,
|
||||
collapsible: true,
|
||||
items: [{type: 'doc', id: 'doc5'}],
|
||||
},
|
||||
] as Sidebar);
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
processSidebars,
|
||||
DefaultSidebars,
|
||||
DisabledSidebars,
|
||||
fixSidebarItemInconsistencies,
|
||||
} from '../sidebars';
|
||||
import {
|
||||
Sidebar,
|
||||
|
@ -24,6 +25,8 @@ import {
|
|||
SidebarItemsGenerator,
|
||||
Sidebars,
|
||||
UnprocessedSidebars,
|
||||
SidebarOptions,
|
||||
SidebarItemCategory,
|
||||
} from '../types';
|
||||
import {DefaultSidebarItemsGenerator} from '../sidebarItemsGenerator';
|
||||
|
||||
|
@ -31,15 +34,19 @@ import {DefaultSidebarItemsGenerator} from '../sidebarItemsGenerator';
|
|||
|
||||
describe('loadSidebars', () => {
|
||||
const fixtureDir = path.join(__dirname, '__fixtures__', 'sidebars');
|
||||
const options: SidebarOptions = {
|
||||
sidebarCollapsed: true,
|
||||
sidebarCollapsible: true,
|
||||
};
|
||||
test('sidebars with known sidebar item type', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars.json');
|
||||
const result = loadSidebars(sidebarPath);
|
||||
const result = loadSidebars(sidebarPath, options);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('sidebars with deep level of category', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-category.js');
|
||||
const result = loadSidebars(sidebarPath);
|
||||
const result = loadSidebars(sidebarPath, options);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -49,8 +56,8 @@ describe('loadSidebars', () => {
|
|||
fixtureDir,
|
||||
'sidebars-category-shorthand.js',
|
||||
);
|
||||
const sidebar1 = loadSidebars(sidebarPath1);
|
||||
const sidebar2 = loadSidebars(sidebarPath2);
|
||||
const sidebar1 = loadSidebars(sidebarPath1, options);
|
||||
const sidebar2 = loadSidebars(sidebarPath2, options);
|
||||
expect(sidebar1).toEqual(sidebar2);
|
||||
});
|
||||
|
||||
|
@ -59,7 +66,9 @@ describe('loadSidebars', () => {
|
|||
fixtureDir,
|
||||
'sidebars-category-wrong-items.json',
|
||||
);
|
||||
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||
expect(() =>
|
||||
loadSidebars(sidebarPath, options),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Error loading {\\"type\\":\\"category\\",\\"label\\":\\"Category Label\\",\\"items\\":\\"doc1\\"}: \\"items\\" must be an array."`,
|
||||
);
|
||||
});
|
||||
|
@ -69,7 +78,9 @@ describe('loadSidebars', () => {
|
|||
fixtureDir,
|
||||
'sidebars-category-wrong-label.json',
|
||||
);
|
||||
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||
expect(() =>
|
||||
loadSidebars(sidebarPath, options),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Error loading {\\"type\\":\\"category\\",\\"label\\":true,\\"items\\":[\\"doc1\\"]}: \\"label\\" must be a string."`,
|
||||
);
|
||||
});
|
||||
|
@ -79,7 +90,9 @@ describe('loadSidebars', () => {
|
|||
fixtureDir,
|
||||
'sidebars-doc-id-not-string.json',
|
||||
);
|
||||
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||
expect(() =>
|
||||
loadSidebars(sidebarPath, options),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Error loading {\\"type\\":\\"doc\\",\\"id\\":[\\"doc1\\"]}: \\"id\\" must be a string."`,
|
||||
);
|
||||
});
|
||||
|
@ -89,33 +102,38 @@ describe('loadSidebars', () => {
|
|||
fixtureDir,
|
||||
'sidebars-first-level-not-category.js',
|
||||
);
|
||||
const result = loadSidebars(sidebarPath);
|
||||
const result = loadSidebars(sidebarPath, options);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('sidebars link', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-link.json');
|
||||
const result = loadSidebars(sidebarPath);
|
||||
const result = loadSidebars(sidebarPath, options);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('sidebars link wrong label', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-link-wrong-label.json');
|
||||
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||
expect(() =>
|
||||
loadSidebars(sidebarPath, options),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Error loading {\\"type\\":\\"link\\",\\"label\\":false,\\"href\\":\\"https://github.com\\"}: \\"label\\" must be a string."`,
|
||||
);
|
||||
});
|
||||
|
||||
test('sidebars link wrong href', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-link-wrong-href.json');
|
||||
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||
expect(() =>
|
||||
loadSidebars(sidebarPath, options),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Error loading {\\"type\\":\\"link\\",\\"label\\":\\"GitHub\\",\\"href\\":[\\"example.com\\"]}: \\"href\\" must be a string."`,
|
||||
);
|
||||
});
|
||||
|
||||
test('sidebars with unknown sidebar item type', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-unknown-type.json');
|
||||
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(`
|
||||
expect(() => loadSidebars(sidebarPath, options))
|
||||
.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Unknown sidebar item type \\"superman\\". Sidebar item is {\\"type\\":\\"superman\\"}.
|
||||
"
|
||||
`);
|
||||
|
@ -123,26 +141,28 @@ describe('loadSidebars', () => {
|
|||
|
||||
test('sidebars with known sidebar item type but wrong field', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-wrong-field.json');
|
||||
expect(() => loadSidebars(sidebarPath)).toThrowErrorMatchingInlineSnapshot(
|
||||
expect(() =>
|
||||
loadSidebars(sidebarPath, options),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unknown sidebar item keys: href. Item: {\\"type\\":\\"category\\",\\"label\\":\\"category\\",\\"href\\":\\"https://github.com\\"}"`,
|
||||
);
|
||||
});
|
||||
|
||||
test('unexisting path', () => {
|
||||
expect(loadSidebars('badpath')).toEqual(DisabledSidebars);
|
||||
expect(loadSidebars('badpath', options)).toEqual(DisabledSidebars);
|
||||
});
|
||||
|
||||
test('undefined path', () => {
|
||||
expect(loadSidebars(undefined)).toEqual(DefaultSidebars);
|
||||
expect(loadSidebars(undefined, options)).toEqual(DefaultSidebars);
|
||||
});
|
||||
|
||||
test('literal false path', () => {
|
||||
expect(loadSidebars(false)).toEqual(DisabledSidebars);
|
||||
expect(loadSidebars(false, options)).toEqual(DisabledSidebars);
|
||||
});
|
||||
|
||||
test('sidebars with category.collapsed property', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-collapsed.json');
|
||||
const result = loadSidebars(sidebarPath);
|
||||
const result = loadSidebars(sidebarPath, options);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -151,7 +171,7 @@ describe('loadSidebars', () => {
|
|||
fixtureDir,
|
||||
'sidebars-collapsed-first-level.json',
|
||||
);
|
||||
const result = loadSidebars(sidebarPath);
|
||||
const result = loadSidebars(sidebarPath, options);
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -162,23 +182,27 @@ describe('collectSidebarDocItems', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category1',
|
||||
items: [
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 1',
|
||||
items: [{type: 'doc', id: 'doc1'}],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc2'},
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Sub sub category 1',
|
||||
items: [{type: 'doc', id: 'doc3'}],
|
||||
},
|
||||
|
@ -189,6 +213,7 @@ describe('collectSidebarDocItems', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc4'},
|
||||
|
@ -213,23 +238,27 @@ describe('collectSidebarCategories', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category1',
|
||||
items: [
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 1',
|
||||
items: [{type: 'doc', id: 'doc1'}],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc2'},
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Sub sub category 1',
|
||||
items: [{type: 'doc', id: 'doc3'}],
|
||||
},
|
||||
|
@ -240,6 +269,7 @@ describe('collectSidebarCategories', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc4'},
|
||||
|
@ -266,6 +296,7 @@ describe('collectSidebarLinks', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category1',
|
||||
items: [
|
||||
{
|
||||
|
@ -276,6 +307,7 @@ describe('collectSidebarLinks', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 2',
|
||||
items: [
|
||||
{
|
||||
|
@ -302,11 +334,13 @@ describe('collectSidebarsDocIds', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category1',
|
||||
items: [
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 1',
|
||||
items: [{type: 'doc', id: 'doc1'}],
|
||||
},
|
||||
|
@ -319,6 +353,7 @@ describe('collectSidebarsDocIds', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc3'},
|
||||
|
@ -345,11 +380,13 @@ describe('transformSidebarItems', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category1',
|
||||
items: [
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 1',
|
||||
items: [{type: 'doc', id: 'doc1'}],
|
||||
customProps: {fakeProp: false},
|
||||
|
@ -357,12 +394,14 @@ describe('transformSidebarItems', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc2'},
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Sub sub category 1',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc3', customProps: {lorem: 'ipsum'}},
|
||||
|
@ -375,6 +414,7 @@ describe('transformSidebarItems', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc4'},
|
||||
|
@ -394,11 +434,13 @@ describe('transformSidebarItems', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'MODIFIED LABEL: Category1',
|
||||
items: [
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'MODIFIED LABEL: Subcategory 1',
|
||||
items: [{type: 'doc', id: 'doc1'}],
|
||||
customProps: {fakeProp: false},
|
||||
|
@ -406,12 +448,14 @@ describe('transformSidebarItems', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'MODIFIED LABEL: Subcategory 2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc2'},
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'MODIFIED LABEL: Sub sub category 1',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc3', customProps: {lorem: 'ipsum'}},
|
||||
|
@ -424,6 +468,7 @@ describe('transformSidebarItems', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'MODIFIED LABEL: Category2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc4'},
|
||||
|
@ -463,6 +508,7 @@ describe('processSidebars', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
items: [{type: 'doc', id: 'doc2'}],
|
||||
label: 'Category',
|
||||
},
|
||||
|
@ -474,6 +520,7 @@ describe('processSidebars', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
items: [{type: 'doc', id: 'doc4'}],
|
||||
label: 'Category',
|
||||
},
|
||||
|
@ -491,6 +538,7 @@ describe('processSidebars', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
items: [
|
||||
{type: 'doc', id: 'doc2'},
|
||||
{type: 'autogenerated', dirName: 'dir1'},
|
||||
|
@ -507,6 +555,7 @@ describe('processSidebars', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
items: [{type: 'doc', id: 'doc4'}],
|
||||
label: 'Category',
|
||||
},
|
||||
|
@ -541,6 +590,7 @@ describe('processSidebars', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
items: [{type: 'doc', id: 'doc2'}, ...StaticGeneratedSidebarSlice],
|
||||
label: 'Category',
|
||||
},
|
||||
|
@ -554,6 +604,7 @@ describe('processSidebars', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
items: [{type: 'doc', id: 'doc4'}],
|
||||
label: 'Category',
|
||||
},
|
||||
|
@ -567,11 +618,13 @@ describe('createSidebarsUtils', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category1',
|
||||
items: [
|
||||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Subcategory 1',
|
||||
items: [{type: 'doc', id: 'doc1'}],
|
||||
},
|
||||
|
@ -584,6 +637,7 @@ describe('createSidebarsUtils', () => {
|
|||
{
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
collapsible: true,
|
||||
label: 'Category2',
|
||||
items: [
|
||||
{type: 'doc', id: 'doc3'},
|
||||
|
@ -637,3 +691,56 @@ describe('createSidebarsUtils', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('fixSidebarItemInconsistencies', () => {
|
||||
test('should not fix good category', () => {
|
||||
const category: SidebarItemCategory = {
|
||||
type: 'category',
|
||||
label: 'Cat',
|
||||
items: [],
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
};
|
||||
expect(fixSidebarItemInconsistencies(category)).toEqual(category);
|
||||
});
|
||||
|
||||
test('should fix bad category', () => {
|
||||
const category: SidebarItemCategory = {
|
||||
type: 'category',
|
||||
label: 'Cat',
|
||||
items: [],
|
||||
collapsible: false,
|
||||
collapsed: true, // Bad because collapsible=false
|
||||
};
|
||||
expect(fixSidebarItemInconsistencies(category)).toEqual({
|
||||
...category,
|
||||
collapsed: false,
|
||||
});
|
||||
});
|
||||
|
||||
test('should fix bad subcategory', () => {
|
||||
const subCategory: SidebarItemCategory = {
|
||||
type: 'category',
|
||||
label: 'SubCat',
|
||||
items: [],
|
||||
collapsible: false,
|
||||
collapsed: true, // Bad because collapsible=false
|
||||
};
|
||||
const category: SidebarItemCategory = {
|
||||
type: 'category',
|
||||
label: 'Cat',
|
||||
items: [subCategory],
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
};
|
||||
expect(fixSidebarItemInconsistencies(category)).toEqual({
|
||||
...category,
|
||||
items: [
|
||||
{
|
||||
...subCategory,
|
||||
collapsed: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
PathOptions,
|
||||
UnprocessedSidebarItem,
|
||||
UnprocessedSidebars,
|
||||
SidebarOptions,
|
||||
} from './types';
|
||||
import {loadSidebars, resolveSidebarPathOption} from './sidebars';
|
||||
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
||||
|
@ -25,14 +26,16 @@ function createVersionedSidebarFile({
|
|||
pluginId,
|
||||
sidebarPath,
|
||||
version,
|
||||
options,
|
||||
}: {
|
||||
siteDir: string;
|
||||
pluginId: string;
|
||||
sidebarPath: string | false | undefined;
|
||||
version: string;
|
||||
options: SidebarOptions;
|
||||
}) {
|
||||
// Load current sidebar and create a new versioned sidebars file (if needed).
|
||||
const loadedSidebars = loadSidebars(sidebarPath);
|
||||
const loadedSidebars = loadSidebars(sidebarPath, options);
|
||||
|
||||
// Do not create a useless versioned sidebars file if sidebars file is empty or sidebars are disabled/false)
|
||||
const shouldCreateVersionedSidebarFile =
|
||||
|
@ -87,7 +90,7 @@ export function cliDocsVersionCommand(
|
|||
version: string | null | undefined,
|
||||
siteDir: string,
|
||||
pluginId: string,
|
||||
options: PathOptions,
|
||||
options: PathOptions & SidebarOptions,
|
||||
): void {
|
||||
// It wouldn't be very user-friendly to show a [default] log prefix,
|
||||
// so we use [docs] instead of [default]
|
||||
|
@ -159,6 +162,7 @@ export function cliDocsVersionCommand(
|
|||
pluginId,
|
||||
version,
|
||||
sidebarPath: resolveSidebarPathOption(siteDir, sidebarPath),
|
||||
options,
|
||||
});
|
||||
|
||||
// Update versions.json file.
|
||||
|
|
|
@ -100,6 +100,8 @@ export default function pluginContentDocs(
|
|||
cliDocsVersionCommand(version, siteDir, pluginId, {
|
||||
path: options.path,
|
||||
sidebarPath: options.sidebarPath,
|
||||
sidebarCollapsed: options.sidebarCollapsed,
|
||||
sidebarCollapsible: options.sidebarCollapsible,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -168,6 +170,10 @@ export default function pluginContentDocs(
|
|||
): Promise<LoadedVersion> {
|
||||
const unprocessedSidebars = loadSidebars(
|
||||
versionMetadata.sidebarFilePath,
|
||||
{
|
||||
sidebarCollapsed: options.sidebarCollapsed,
|
||||
sidebarCollapsible: options.sidebarCollapsible,
|
||||
},
|
||||
);
|
||||
|
||||
const docsBase: DocMetadataBase[] = await loadVersionDocsBase(
|
||||
|
@ -184,6 +190,10 @@ export default function pluginContentDocs(
|
|||
unprocessedSidebars,
|
||||
docs: docsBase,
|
||||
version: versionMetadata,
|
||||
options: {
|
||||
sidebarCollapsed: options.sidebarCollapsed,
|
||||
sidebarCollapsible: options.sidebarCollapsible,
|
||||
},
|
||||
});
|
||||
|
||||
const sidebarsUtils = createSidebarsUtils(sidebars);
|
||||
|
|
|
@ -46,6 +46,8 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
|
|||
versions: {},
|
||||
editCurrentVersion: false,
|
||||
editLocalizedFiles: false,
|
||||
sidebarCollapsible: true,
|
||||
sidebarCollapsed: true,
|
||||
};
|
||||
|
||||
const VersionOptionsSchema = Joi.object({
|
||||
|
@ -77,6 +79,8 @@ export const OptionsSchema = Joi.object({
|
|||
sidebarItemsGenerator: Joi.function().default(
|
||||
() => DEFAULT_OPTIONS.sidebarItemsGenerator,
|
||||
),
|
||||
sidebarCollapsible: Joi.boolean().default(DEFAULT_OPTIONS.sidebarCollapsible),
|
||||
sidebarCollapsed: Joi.boolean().default(DEFAULT_OPTIONS.sidebarCollapsed),
|
||||
numberPrefixParser: Joi.alternatives()
|
||||
.try(
|
||||
Joi.function(),
|
||||
|
@ -116,8 +120,32 @@ export const OptionsSchema = Joi.object({
|
|||
|
||||
export function validateOptions({
|
||||
validate,
|
||||
options,
|
||||
options: userOptions,
|
||||
}: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions> {
|
||||
let options = userOptions;
|
||||
|
||||
if (options.sidebarCollapsible === false) {
|
||||
// When sidebarCollapsible=false and sidebarCollapsed=undefined, we don't want to have the inconsistency warning
|
||||
// We let options.sidebarCollapsible become the default value for options.sidebarCollapsed
|
||||
if (typeof options.sidebarCollapsed === 'undefined') {
|
||||
options = {
|
||||
...options,
|
||||
sidebarCollapsed: false,
|
||||
};
|
||||
}
|
||||
if (options.sidebarCollapsed) {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
'The docs plugin config is inconsistent. It does not make sense to use sidebarCollapsible=false and sidebarCollapsed=true at the same time. sidebarCollapsed=false will be ignored.',
|
||||
),
|
||||
);
|
||||
options = {
|
||||
...options,
|
||||
sidebarCollapsed: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// TODO remove homePageId before end of 2020
|
||||
// "slug: /" is better because the home doc can be different across versions
|
||||
if (options.homePageId) {
|
||||
|
|
|
@ -33,7 +33,8 @@ declare module '@docusaurus/plugin-content-docs-types' {
|
|||
type: 'category';
|
||||
label: string;
|
||||
items: PropSidebarItem[];
|
||||
collapsed?: boolean;
|
||||
collapsed: boolean;
|
||||
collapsible: boolean;
|
||||
};
|
||||
|
||||
export type PropSidebarItem = PropSidebarItemLink | PropSidebarItemCategory;
|
||||
|
|
|
@ -19,7 +19,6 @@ import chalk from 'chalk';
|
|||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import Yaml from 'js-yaml';
|
||||
import {DefaultCategoryCollapsedValue} from './sidebars';
|
||||
|
||||
const BreadcrumbSeparator = '/';
|
||||
|
||||
|
@ -30,6 +29,7 @@ export type CategoryMetadatasFile = {
|
|||
label?: string;
|
||||
position?: number;
|
||||
collapsed?: boolean;
|
||||
collapsible?: boolean;
|
||||
|
||||
// TODO should we allow "items" here? how would this work? would an "autogenerated" type be allowed?
|
||||
// This mkdocs plugin do something like that: https://github.com/lukasgeiter/mkdocs-awesome-pages-plugin/
|
||||
|
@ -43,6 +43,7 @@ const CategoryMetadatasFileSchema = Joi.object<CategoryMetadatasFile>({
|
|||
label: Joi.string(),
|
||||
position: Joi.number(),
|
||||
collapsed: Joi.boolean(),
|
||||
collapsible: Joi.boolean(),
|
||||
});
|
||||
|
||||
// TODO I now believe we should read all the category metadata files ahead of time: we may need this metadata to customize docs metadata
|
||||
|
@ -107,7 +108,8 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async functio
|
|||
docs: allDocs,
|
||||
version,
|
||||
numberPrefixParser,
|
||||
}): Promise<SidebarItem[]> {
|
||||
options,
|
||||
}) {
|
||||
// Doc at the root of the autogenerated sidebar dir
|
||||
function isRootDoc(doc: SidebarItemsGeneratorDoc) {
|
||||
return doc.sourceDirName === item.dirName;
|
||||
|
@ -199,11 +201,16 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async functio
|
|||
|
||||
const position = categoryMetadatas?.position ?? numberPrefix;
|
||||
|
||||
const collapsible =
|
||||
categoryMetadatas?.collapsible ?? options.sidebarCollapsible;
|
||||
const collapsed = categoryMetadatas?.collapsed ?? options.sidebarCollapsed;
|
||||
|
||||
return {
|
||||
type: 'category',
|
||||
label: categoryMetadatas?.label ?? filename,
|
||||
items: [],
|
||||
collapsed: categoryMetadatas?.collapsed ?? DefaultCategoryCollapsedValue,
|
||||
collapsed,
|
||||
collapsible,
|
||||
...(typeof position !== 'undefined' && {position}),
|
||||
};
|
||||
}
|
||||
|
@ -268,6 +275,7 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async functio
|
|||
}
|
||||
|
||||
// async process made sequential on purpose! order matters
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const doc of docs) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await handleDocItem(doc);
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
SidebarItemsGeneratorVersion,
|
||||
NumberPrefixParser,
|
||||
SidebarItemsGeneratorOption,
|
||||
SidebarOptions,
|
||||
PluginOptions,
|
||||
} from './types';
|
||||
import {mapValues, flatten, flatMap, difference, pick, memoize} from 'lodash';
|
||||
|
@ -38,6 +39,7 @@ type SidebarItemCategoryJSON = SidebarItemBase & {
|
|||
label: string;
|
||||
items: SidebarItemJSON[];
|
||||
collapsed?: boolean;
|
||||
collapsible?: boolean;
|
||||
};
|
||||
|
||||
type SidebarItemAutogeneratedJSON = SidebarItemBase & {
|
||||
|
@ -74,18 +76,17 @@ function isCategoryShorthand(
|
|||
return typeof item !== 'string' && !item.type;
|
||||
}
|
||||
|
||||
// categories are collapsed by default, unless user set collapsed = false
|
||||
export const DefaultCategoryCollapsedValue = true;
|
||||
|
||||
/**
|
||||
* Convert {category1: [item1,item2]} shorthand syntax to long-form syntax
|
||||
*/
|
||||
function normalizeCategoryShorthand(
|
||||
sidebar: SidebarCategoryShorthandJSON,
|
||||
options: SidebarOptions,
|
||||
): SidebarItemCategoryJSON[] {
|
||||
return Object.entries(sidebar).map(([label, items]) => ({
|
||||
type: 'category',
|
||||
collapsed: DefaultCategoryCollapsedValue,
|
||||
collapsed: options.sidebarCollapsed,
|
||||
collapsible: options.sidebarCollapsible,
|
||||
label,
|
||||
items,
|
||||
}));
|
||||
|
@ -115,7 +116,13 @@ function assertItem<K extends string>(
|
|||
function assertIsCategory(
|
||||
item: Record<string, unknown>,
|
||||
): asserts item is SidebarItemCategoryJSON {
|
||||
assertItem(item, ['items', 'label', 'collapsed', 'customProps']);
|
||||
assertItem(item, [
|
||||
'items',
|
||||
'label',
|
||||
'collapsed',
|
||||
'collapsible',
|
||||
'customProps',
|
||||
]);
|
||||
if (typeof item.label !== 'string') {
|
||||
throw new Error(
|
||||
`Error loading ${JSON.stringify(item)}: "label" must be a string.`,
|
||||
|
@ -135,6 +142,14 @@ function assertIsCategory(
|
|||
`Error loading ${JSON.stringify(item)}: "collapsed" must be a boolean.`,
|
||||
);
|
||||
}
|
||||
if (
|
||||
typeof item.collapsible !== 'undefined' &&
|
||||
typeof item.collapsible !== 'boolean'
|
||||
) {
|
||||
throw new Error(
|
||||
`Error loading ${JSON.stringify(item)}: "collapsible" must be a boolean.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function assertIsAutogenerated(
|
||||
|
@ -192,7 +207,10 @@ function assertIsLink(
|
|||
* Normalizes recursively item and all its children. Ensures that at the end
|
||||
* each item will be an object with the corresponding type.
|
||||
*/
|
||||
function normalizeItem(item: SidebarItemJSON): UnprocessedSidebarItem[] {
|
||||
function normalizeItem(
|
||||
item: SidebarItemJSON,
|
||||
options: SidebarOptions,
|
||||
): UnprocessedSidebarItem[] {
|
||||
if (typeof item === 'string') {
|
||||
return [
|
||||
{
|
||||
|
@ -202,16 +220,21 @@ function normalizeItem(item: SidebarItemJSON): UnprocessedSidebarItem[] {
|
|||
];
|
||||
}
|
||||
if (isCategoryShorthand(item)) {
|
||||
return flatMap(normalizeCategoryShorthand(item), normalizeItem);
|
||||
return flatMap(normalizeCategoryShorthand(item, options), (subitem) =>
|
||||
normalizeItem(subitem, options),
|
||||
);
|
||||
}
|
||||
switch (item.type) {
|
||||
case 'category':
|
||||
assertIsCategory(item);
|
||||
return [
|
||||
{
|
||||
collapsed: DefaultCategoryCollapsedValue,
|
||||
...item,
|
||||
items: flatMap(item.items, normalizeItem),
|
||||
items: flatMap(item.items, (subItem) =>
|
||||
normalizeItem(subItem, options),
|
||||
),
|
||||
collapsible: item.collapsible ?? options.sidebarCollapsible,
|
||||
collapsed: item.collapsed ?? options.sidebarCollapsed,
|
||||
},
|
||||
];
|
||||
case 'autogenerated':
|
||||
|
@ -238,16 +261,24 @@ function normalizeItem(item: SidebarItemJSON): UnprocessedSidebarItem[] {
|
|||
}
|
||||
}
|
||||
|
||||
function normalizeSidebar(sidebar: SidebarJSON): UnprocessedSidebar {
|
||||
function normalizeSidebar(
|
||||
sidebar: SidebarJSON,
|
||||
options: SidebarOptions,
|
||||
): UnprocessedSidebar {
|
||||
const normalizedSidebar: SidebarItemJSON[] = Array.isArray(sidebar)
|
||||
? sidebar
|
||||
: normalizeCategoryShorthand(sidebar);
|
||||
: normalizeCategoryShorthand(sidebar, options);
|
||||
|
||||
return flatMap(normalizedSidebar, normalizeItem);
|
||||
return flatMap(normalizedSidebar, (subitem) =>
|
||||
normalizeItem(subitem, options),
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeSidebars(sidebars: SidebarsJSON): UnprocessedSidebars {
|
||||
return mapValues(sidebars, normalizeSidebar);
|
||||
function normalizeSidebars(
|
||||
sidebars: SidebarsJSON,
|
||||
options: SidebarOptions,
|
||||
): UnprocessedSidebars {
|
||||
return mapValues(sidebars, (subitem) => normalizeSidebar(subitem, options));
|
||||
}
|
||||
|
||||
export const DefaultSidebars: UnprocessedSidebars = {
|
||||
|
@ -276,6 +307,7 @@ export function resolveSidebarPathOption(
|
|||
// Note: sidebarFilePath must be absolute, use resolveSidebarPathOption
|
||||
export function loadSidebars(
|
||||
sidebarFilePath: string | false | undefined,
|
||||
options: SidebarOptions,
|
||||
): UnprocessedSidebars {
|
||||
// false => no sidebars
|
||||
if (sidebarFilePath === false) {
|
||||
|
@ -297,7 +329,7 @@ export function loadSidebars(
|
|||
// We don't want sidebars to be cached because of hot reloading.
|
||||
const sidebarJson = importFresh(sidebarFilePath) as SidebarsJSON;
|
||||
|
||||
return normalizeSidebars(sidebarJson);
|
||||
return normalizeSidebars(sidebarJson, options);
|
||||
}
|
||||
|
||||
export function toSidebarItemsGeneratorDoc(
|
||||
|
@ -317,19 +349,44 @@ export function toSidebarItemsGeneratorVersion(
|
|||
return pick(version, ['versionName', 'contentPath']);
|
||||
}
|
||||
|
||||
// Handle the generation of autogenerated sidebar items
|
||||
export function fixSidebarItemInconsistencies(item: SidebarItem): SidebarItem {
|
||||
function fixCategoryInconsistencies(
|
||||
category: SidebarItemCategory,
|
||||
): SidebarItemCategory {
|
||||
// A non-collapsible category can't be collapsed!
|
||||
if (!category.collapsible && category.collapsed) {
|
||||
return {
|
||||
...category,
|
||||
collapsed: false,
|
||||
};
|
||||
}
|
||||
return category;
|
||||
}
|
||||
|
||||
if (item.type === 'category') {
|
||||
return {
|
||||
...fixCategoryInconsistencies(item),
|
||||
items: item.items.map(fixSidebarItemInconsistencies),
|
||||
};
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
// Handle the generation of autogenerated sidebar items and other post-processing checks
|
||||
export async function processSidebar({
|
||||
sidebarItemsGenerator,
|
||||
numberPrefixParser,
|
||||
unprocessedSidebar,
|
||||
docs,
|
||||
version,
|
||||
options,
|
||||
}: {
|
||||
sidebarItemsGenerator: SidebarItemsGeneratorOption;
|
||||
numberPrefixParser: NumberPrefixParser;
|
||||
unprocessedSidebar: UnprocessedSidebar;
|
||||
docs: DocMetadataBase[];
|
||||
version: VersionMetadata;
|
||||
options: SidebarOptions;
|
||||
}): Promise<Sidebar> {
|
||||
// Just a minor lazy transformation optimization
|
||||
const getSidebarItemsGeneratorDocsAndVersion = memoize(() => ({
|
||||
|
@ -337,14 +394,16 @@ export async function processSidebar({
|
|||
version: toSidebarItemsGeneratorVersion(version),
|
||||
}));
|
||||
|
||||
async function processRecursive(
|
||||
async function handleAutoGeneratedItems(
|
||||
item: UnprocessedSidebarItem,
|
||||
): Promise<SidebarItem[]> {
|
||||
if (item.type === 'category') {
|
||||
return [
|
||||
{
|
||||
...item,
|
||||
items: (await Promise.all(item.items.map(processRecursive))).flat(),
|
||||
items: (
|
||||
await Promise.all(item.items.map(handleAutoGeneratedItems))
|
||||
).flat(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -354,12 +413,17 @@ export async function processSidebar({
|
|||
numberPrefixParser,
|
||||
defaultSidebarItemsGenerator: DefaultSidebarItemsGenerator,
|
||||
...getSidebarItemsGeneratorDocsAndVersion(),
|
||||
options,
|
||||
});
|
||||
}
|
||||
return [item];
|
||||
}
|
||||
|
||||
return (await Promise.all(unprocessedSidebar.map(processRecursive))).flat();
|
||||
const processedSidebar = (
|
||||
await Promise.all(unprocessedSidebar.map(handleAutoGeneratedItems))
|
||||
).flat();
|
||||
|
||||
return processedSidebar.map(fixSidebarItemInconsistencies);
|
||||
}
|
||||
|
||||
export async function processSidebars({
|
||||
|
@ -368,12 +432,14 @@ export async function processSidebars({
|
|||
unprocessedSidebars,
|
||||
docs,
|
||||
version,
|
||||
options,
|
||||
}: {
|
||||
sidebarItemsGenerator: SidebarItemsGeneratorOption;
|
||||
numberPrefixParser: NumberPrefixParser;
|
||||
unprocessedSidebars: UnprocessedSidebars;
|
||||
docs: DocMetadataBase[];
|
||||
version: VersionMetadata;
|
||||
options: SidebarOptions;
|
||||
}): Promise<Sidebars> {
|
||||
return combinePromises(
|
||||
mapValues(unprocessedSidebars, (unprocessedSidebar) =>
|
||||
|
@ -383,6 +449,7 @@ export async function processSidebars({
|
|||
unprocessedSidebar,
|
||||
docs,
|
||||
version,
|
||||
options,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -75,10 +75,16 @@ export type VersionsOptions = {
|
|||
onlyIncludeVersions?: string[];
|
||||
};
|
||||
|
||||
export type SidebarOptions = {
|
||||
sidebarCollapsible: boolean;
|
||||
sidebarCollapsed: boolean;
|
||||
};
|
||||
|
||||
export type PluginOptions = MetadataOptions &
|
||||
PathOptions &
|
||||
VersionsOptions &
|
||||
RemarkAndRehypePluginOptions & {
|
||||
RemarkAndRehypePluginOptions &
|
||||
SidebarOptions & {
|
||||
id: string;
|
||||
include: string[];
|
||||
exclude: string[];
|
||||
|
@ -111,6 +117,7 @@ export type SidebarItemCategory = SidebarItemBase & {
|
|||
label: string;
|
||||
items: SidebarItem[];
|
||||
collapsed: boolean;
|
||||
collapsible: boolean;
|
||||
};
|
||||
|
||||
export type UnprocessedSidebarItemAutogenerated = {
|
||||
|
@ -123,6 +130,7 @@ export type UnprocessedSidebarItemCategory = SidebarItemBase & {
|
|||
label: string;
|
||||
items: UnprocessedSidebarItem[];
|
||||
collapsed: boolean;
|
||||
collapsible: boolean;
|
||||
};
|
||||
|
||||
export type UnprocessedSidebarItem =
|
||||
|
@ -160,6 +168,7 @@ export type SidebarItemsGeneratorArgs = {
|
|||
version: SidebarItemsGeneratorVersion;
|
||||
docs: SidebarItemsGeneratorDoc[];
|
||||
numberPrefixParser: NumberPrefixParser;
|
||||
options: SidebarOptions;
|
||||
};
|
||||
export type SidebarItemsGenerator = (
|
||||
generatorArgs: SidebarItemsGeneratorArgs,
|
||||
|
|
|
@ -36,7 +36,7 @@ function DocPageContent({
|
|||
versionMetadata,
|
||||
children,
|
||||
}: DocPageContentProps): JSX.Element {
|
||||
const {siteConfig, isClient} = useDocusaurusContext();
|
||||
const {isClient} = useDocusaurusContext();
|
||||
const {pluginId, version} = versionMetadata;
|
||||
|
||||
const sidebarName = currentDocRoute.sidebar;
|
||||
|
@ -88,7 +88,6 @@ function DocPageContent({
|
|||
}
|
||||
sidebar={sidebar}
|
||||
path={currentDocRoute.path}
|
||||
sidebarCollapsible={siteConfig.themeConfig.sidebarCollapsible}
|
||||
onCollapse={toggleSidebar}
|
||||
isHidden={hiddenSidebar}
|
||||
/>
|
||||
|
|
|
@ -58,13 +58,7 @@ function HideableSidebarButton({onClick}) {
|
|||
);
|
||||
}
|
||||
|
||||
function DocSidebarDesktop({
|
||||
path,
|
||||
sidebar,
|
||||
sidebarCollapsible,
|
||||
onCollapse,
|
||||
isHidden,
|
||||
}: Props) {
|
||||
function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}: Props) {
|
||||
const showAnnouncementBar = useShowAnnouncementBar();
|
||||
const {
|
||||
navbar: {hideOnScroll},
|
||||
|
@ -85,11 +79,7 @@ function DocSidebarDesktop({
|
|||
!isAnnouncementBarClosed && showAnnouncementBar,
|
||||
})}>
|
||||
<ul className="menu__list">
|
||||
<DocSidebarItems
|
||||
items={sidebar}
|
||||
collapsible={sidebarCollapsible}
|
||||
activePath={path}
|
||||
/>
|
||||
<DocSidebarItems items={sidebar} activePath={path} />
|
||||
</ul>
|
||||
</nav>
|
||||
{hideableSidebar && <HideableSidebarButton onClick={onCollapse} />}
|
||||
|
@ -100,14 +90,12 @@ function DocSidebarDesktop({
|
|||
const DocSidebarMobileSecondaryMenu: MobileSecondaryMenuComponent<Props> = ({
|
||||
toggleSidebar,
|
||||
sidebar,
|
||||
sidebarCollapsible,
|
||||
path,
|
||||
}) => {
|
||||
return (
|
||||
<ul className="menu__list">
|
||||
<DocSidebarItems
|
||||
items={sidebar}
|
||||
collapsible={sidebarCollapsible}
|
||||
activePath={path}
|
||||
onItemClick={() => toggleSidebar()}
|
||||
/>
|
||||
|
|
|
@ -95,11 +95,10 @@ function useAutoExpandActiveCategory({
|
|||
function DocSidebarItemCategory({
|
||||
item,
|
||||
onItemClick,
|
||||
collapsible = true,
|
||||
activePath,
|
||||
...props
|
||||
}: Props & {item: PropSidebarItemCategory}) {
|
||||
const {items, label} = item;
|
||||
const {items, label, collapsible} = item;
|
||||
|
||||
const isActive = isActiveSidebarItem(item, activePath);
|
||||
|
||||
|
@ -110,7 +109,7 @@ function DocSidebarItemCategory({
|
|||
if (!collapsible) {
|
||||
return false;
|
||||
}
|
||||
return isActive ? false : item.collapsed ?? true;
|
||||
return isActive ? false : item.collapsed;
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -146,7 +145,6 @@ function DocSidebarItemCategory({
|
|||
items={items}
|
||||
tabIndex={collapsed ? -1 : 0}
|
||||
onItemClick={onItemClick}
|
||||
collapsible={collapsible}
|
||||
activePath={activePath}
|
||||
/>
|
||||
</Collapsible>
|
||||
|
@ -158,7 +156,6 @@ function DocSidebarItemLink({
|
|||
item,
|
||||
onItemClick,
|
||||
activePath,
|
||||
collapsible: _collapsible,
|
||||
...props
|
||||
}: Props & {item: PropSidebarItemLink}) {
|
||||
const {href, label} = item;
|
||||
|
|
|
@ -93,7 +93,6 @@ declare module '@theme/DocSidebar' {
|
|||
export type Props = {
|
||||
readonly path: string;
|
||||
readonly sidebar: readonly PropSidebarItem[];
|
||||
readonly sidebarCollapsible?: boolean;
|
||||
readonly onCollapse: () => void;
|
||||
readonly isHidden: boolean;
|
||||
};
|
||||
|
@ -107,7 +106,6 @@ declare module '@theme/DocSidebarItem' {
|
|||
|
||||
type DocSidebarPropsBase = {
|
||||
readonly activePath: string;
|
||||
readonly collapsible?: boolean;
|
||||
readonly onItemClick?: () => void;
|
||||
readonly tabIndex?: number;
|
||||
};
|
||||
|
|
|
@ -40,7 +40,6 @@ const DEFAULT_CONFIG = {
|
|||
items: [],
|
||||
},
|
||||
hideableSidebar: false,
|
||||
sidebarCollapsible: true,
|
||||
};
|
||||
exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
|
||||
|
||||
|
@ -310,7 +309,10 @@ const ThemeConfigSchema = Joi.object({
|
|||
.default(DEFAULT_CONFIG.prism)
|
||||
.unknown(),
|
||||
hideableSidebar: Joi.bool().default(DEFAULT_CONFIG.hideableSidebar),
|
||||
sidebarCollapsible: Joi.bool().default(DEFAULT_CONFIG.sidebarCollapsible),
|
||||
sidebarCollapsible: Joi.forbidden().messages({
|
||||
'any.unknown':
|
||||
'The themeConfig.sidebarCollapsible has been moved to docs plugin options. See: https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-docs',
|
||||
}),
|
||||
});
|
||||
exports.ThemeConfigSchema = ThemeConfigSchema;
|
||||
|
||||
|
|
|
@ -46,7 +46,11 @@ type ContextValue = ReturnType<typeof useContextValue>;
|
|||
|
||||
const Context = createContext<ContextValue | null>(null);
|
||||
|
||||
export function MobileSecondaryMenuProvider({children}: {children: ReactNode}) {
|
||||
export function MobileSecondaryMenuProvider({
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<Context.Provider value={useContextValue()}>{children}</Context.Provider>
|
||||
);
|
||||
|
|
1
website/_dogfooding/_docs-tests/more-test.md
Normal file
1
website/_dogfooding/_docs-tests/more-test.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Another test page
|
|
@ -12,6 +12,12 @@ module.exports = {
|
|||
id: 'index',
|
||||
label: 'Index',
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'section',
|
||||
collapsible: false,
|
||||
items: ['index', 'more-test'],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Huge sidebar category',
|
||||
|
|
|
@ -82,6 +82,16 @@ module.exports = {
|
|||
* Path to sidebar configuration for showing a list of markdown pages.
|
||||
*/
|
||||
sidebarPath: 'sidebars.js',
|
||||
/**
|
||||
* By default, all sidebar categories will be collapsible.
|
||||
* This can be overriden per-category.
|
||||
*/
|
||||
sidebarCollapsible: true,
|
||||
/**
|
||||
* By default, all sidebar categories will be initialized in a collapsed state.
|
||||
* This can be overriden per-category.
|
||||
*/
|
||||
sidebarCollapsed: false,
|
||||
/**
|
||||
* Function used to replace the sidebar items of type "autogenerated"
|
||||
* by real sidebar items (docs, categories, links...)
|
||||
|
|
|
@ -285,7 +285,8 @@ type SidebarItemCategory = {
|
|||
items: SidebarItem[]; // Array of sidebar items.
|
||||
|
||||
// Category options:
|
||||
collapsed: boolean; // Set the category to be collapsed or open by default
|
||||
collapsible: boolean; // Set the category to be collapsible
|
||||
collapsed: boolean; // Set the category to be initially collapsed or open by default
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -297,6 +298,7 @@ module.exports = {
|
|||
{
|
||||
type: 'category',
|
||||
label: 'Guides',
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
items: [
|
||||
'creating-pages',
|
||||
|
@ -332,15 +334,25 @@ module.exports = {
|
|||
|
||||
#### Collapsible categories {#collapsible-categories}
|
||||
|
||||
For sites with a sizable amount of content, we support the option to expand/collapse a category to toggle the display of its contents. Categories are collapsible by default. If you want them to be always expanded, set `themeConfig.sidebarCollapsible` to `false`:
|
||||
By default, categories are collapsible and collapsed.
|
||||
|
||||
The docs plugin options allow to change these defaults globally:
|
||||
|
||||
```js title="docusaurus.config.js"
|
||||
module.exports = {
|
||||
themeConfig: {
|
||||
// highlight-start
|
||||
sidebarCollapsible: false,
|
||||
// highlight-end
|
||||
},
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
{
|
||||
docs: {
|
||||
// highlight-start
|
||||
sidebarCollapsible: true,
|
||||
sidebarCollapsed: false,
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -356,6 +368,7 @@ module.exports = {
|
|||
{
|
||||
type: 'category',
|
||||
label: 'Docs',
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
items: ['markdown-features', 'sidebar', 'versioning'],
|
||||
},
|
||||
|
@ -465,6 +478,7 @@ This is the easy tutorial!
|
|||
```yaml title="docs/tutorials/_category_.yml"
|
||||
label: 'Tutorial'
|
||||
position: 2.5 # float position is supported
|
||||
collapsible: true # make the category collapsible
|
||||
collapsed: false # keep the category open by default
|
||||
```
|
||||
|
||||
|
|
|
@ -229,8 +229,6 @@ module.exports = {
|
|||
copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`, // You can also put own HTML here.
|
||||
},
|
||||
image: 'img/docusaurus.png',
|
||||
// Equivalent to `docsSideNavCollapsible`.
|
||||
sidebarCollapsible: false,
|
||||
// ...
|
||||
},
|
||||
};
|
||||
|
@ -399,7 +397,7 @@ The following fields are all deprecated, you may remove from your configuration
|
|||
- `defaultVersionShown` - Versioning is not ported yet. You'd be unable to migration to Docusaurus 2 if you are using versioning. Stay tuned.
|
||||
- `disableHeaderTitle`
|
||||
- `disableTitleTagline`
|
||||
- `docsSideNavCollapsible` is available at `themeConfig.sidebarCollapsible`, and this is turned on by default now.
|
||||
- `docsSideNavCollapsible` is available at `docsPluginOptions.sidebarCollapsible`, and this is turned on by default now.
|
||||
- `facebookAppId`
|
||||
- `facebookComments`
|
||||
- `facebookPixelId`
|
||||
|
|
|
@ -227,6 +227,8 @@ const isVersioningDisabled = !!process.env.DISABLE_VERSIONING || isI18nStaging;
|
|||
// routeBasePath: '/',
|
||||
path: 'docs',
|
||||
sidebarPath: 'sidebars.js',
|
||||
// sidebarCollapsible: false,
|
||||
// sidebarCollapsed: true,
|
||||
editUrl: ({locale, docPath}) => {
|
||||
if (locale !== 'en') {
|
||||
return `https://crowdin.com/project/docusaurus-v2/${locale}`;
|
||||
|
@ -285,7 +287,6 @@ const isVersioningDisabled = !!process.env.DISABLE_VERSIONING || isI18nStaging;
|
|||
liveCodeBlock: {
|
||||
playgroundPosition: 'bottom',
|
||||
},
|
||||
sidebarCollapsible: true,
|
||||
hideableSidebar: true,
|
||||
colorMode: {
|
||||
defaultMode: 'light',
|
||||
|
|
Loading…
Add table
Reference in a new issue