mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-09 23:27:28 +02:00
feat(v2): allow nested sidebar category shorthand syntax (#2444)
* feat(v2): allow sidebar category shorthand syntax also for nested elements * Update sidebars-category-shorthand.js * Update sidebars-category-shorthand.js Co-authored-by: Yangshun Tay <tay.yang.shun@gmail.com>
This commit is contained in:
parent
85c124e3f1
commit
201c663318
12 changed files with 116 additions and 52 deletions
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
docs: [
|
||||
{
|
||||
'level 1': [
|
||||
'a',
|
||||
{
|
||||
'level 2': [
|
||||
{
|
||||
'level 3': [
|
||||
'c',
|
||||
{
|
||||
'level 4': [
|
||||
'd',
|
||||
{
|
||||
'deeper more more': ['e'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
'f',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"docs": [
|
||||
{
|
||||
"a": "b",
|
||||
"c": "d"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -24,6 +24,17 @@ describe('loadSidebars', () => {
|
|||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('sidebars shortand and longform lead to exact same sidebar', async () => {
|
||||
const sidebarPath1 = path.join(fixtureDir, 'sidebars-category.js');
|
||||
const sidebarPath2 = path.join(
|
||||
fixtureDir,
|
||||
'sidebars-category-shorthand.js',
|
||||
);
|
||||
const sidebar1 = loadSidebars([sidebarPath1]);
|
||||
const sidebar2 = loadSidebars([sidebarPath2]);
|
||||
expect(sidebar1).toEqual(sidebar2);
|
||||
});
|
||||
|
||||
test('sidebars with category but category.items is not an array', async () => {
|
||||
const sidebarPath = path.join(
|
||||
fixtureDir,
|
||||
|
@ -93,15 +104,6 @@ describe('loadSidebars', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('sidebars with invalid sidebar item', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-invalid-item.json');
|
||||
expect(() =>
|
||||
loadSidebars([sidebarPath]),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unknown sidebar item \\"{\\"a\\":\\"b\\",\\"c\\":\\"d\\"}\\"."`,
|
||||
);
|
||||
});
|
||||
|
||||
test('sidebars with unknown sidebar item type', async () => {
|
||||
const sidebarPath = path.join(fixtureDir, 'sidebars-unknown-type.json');
|
||||
expect(() =>
|
||||
|
|
|
@ -15,8 +15,28 @@ import {
|
|||
SidebarItemRaw,
|
||||
SidebarItemLink,
|
||||
SidebarItemDoc,
|
||||
SidebarCategoryShorthandRaw,
|
||||
} from './types';
|
||||
|
||||
function isCategoryShorthand(
|
||||
item: SidebarItemRaw,
|
||||
): item is SidebarCategoryShorthandRaw {
|
||||
return typeof item !== 'string' && !item.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert {category1: [item1,item2]} shorthand syntax to long-form syntax
|
||||
*/
|
||||
function normalizeCategoryShorthand(
|
||||
sidebar: SidebarCategoryShorthandRaw,
|
||||
): SidebarItemCategoryRaw[] {
|
||||
return Object.entries(sidebar).map(([label, items]) => ({
|
||||
type: 'category',
|
||||
label,
|
||||
items,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that item contains only allowed keys.
|
||||
*/
|
||||
|
@ -75,27 +95,29 @@ function assertIsLink(item: any): asserts item is SidebarItemLink {
|
|||
* 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: SidebarItemRaw): SidebarItem {
|
||||
function normalizeItem(item: SidebarItemRaw): SidebarItem[] {
|
||||
if (typeof item === 'string') {
|
||||
return {
|
||||
type: 'doc',
|
||||
id: item,
|
||||
};
|
||||
return [
|
||||
{
|
||||
type: 'doc',
|
||||
id: item,
|
||||
},
|
||||
];
|
||||
}
|
||||
if (!item.type) {
|
||||
throw new Error(`Unknown sidebar item "${JSON.stringify(item)}".`);
|
||||
if (isCategoryShorthand(item)) {
|
||||
return normalizeCategoryShorthand(item).flatMap(normalizeItem);
|
||||
}
|
||||
switch (item.type) {
|
||||
case 'category':
|
||||
assertIsCategory(item);
|
||||
return {...item, items: item.items.map(normalizeItem)};
|
||||
return [{...item, items: item.items.flatMap(normalizeItem)}];
|
||||
case 'link':
|
||||
assertIsLink(item);
|
||||
return item;
|
||||
return [item];
|
||||
case 'ref':
|
||||
case 'doc':
|
||||
assertIsDoc(item);
|
||||
return item;
|
||||
return [item];
|
||||
default:
|
||||
throw new Error(`Unknown sidebar item type: ${item.type}`);
|
||||
}
|
||||
|
@ -107,20 +129,11 @@ function normalizeItem(item: SidebarItemRaw): SidebarItem {
|
|||
function normalizeSidebar(sidebars: SidebarRaw): Sidebar {
|
||||
return Object.entries(sidebars).reduce(
|
||||
(acc: Sidebar, [sidebarId, sidebar]) => {
|
||||
let normalizedSidebar: SidebarItemRaw[];
|
||||
const normalizedSidebar: SidebarItemRaw[] = Array.isArray(sidebar)
|
||||
? sidebar
|
||||
: normalizeCategoryShorthand(sidebar);
|
||||
|
||||
if (!Array.isArray(sidebar)) {
|
||||
// Convert sidebar to a more generic structure.
|
||||
normalizedSidebar = Object.entries(sidebar).map(([label, items]) => ({
|
||||
type: 'category',
|
||||
label,
|
||||
items,
|
||||
}));
|
||||
} else {
|
||||
normalizedSidebar = sidebar;
|
||||
}
|
||||
|
||||
acc[sidebarId] = normalizedSidebar.map(normalizeItem);
|
||||
acc[sidebarId] = normalizedSidebar.flatMap(normalizeItem);
|
||||
|
||||
return acc;
|
||||
},
|
||||
|
|
|
@ -55,6 +55,7 @@ export type SidebarItem =
|
|||
|
||||
export type SidebarItemRaw =
|
||||
| string
|
||||
| SidebarCategoryShorthandRaw
|
||||
| SidebarItemDoc
|
||||
| SidebarItemLink
|
||||
| SidebarItemCategoryRaw
|
||||
|
@ -63,13 +64,13 @@ export type SidebarItemRaw =
|
|||
[key: string]: any;
|
||||
};
|
||||
|
||||
export interface SidebarCategoryShorthandRaw {
|
||||
[sidebarCategory: string]: SidebarItemRaw[];
|
||||
}
|
||||
|
||||
// Sidebar given by user that is not normalized yet. e.g: sidebars.json
|
||||
export interface SidebarRaw {
|
||||
[sidebarId: string]:
|
||||
| {
|
||||
[sidebarCategory: string]: SidebarItemRaw[];
|
||||
}
|
||||
| SidebarItemRaw[];
|
||||
[sidebarId: string]: SidebarCategoryShorthandRaw | SidebarItemRaw[];
|
||||
}
|
||||
|
||||
export interface Sidebar {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue