mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-12 08:37:25 +02:00
feat(v2): auto-generated sidebars, frontmatter-less sites (#4582)
* POC of autogenerated sidebars
* use combine-promises utility lib
* autogenerated sidebar poc working
* Revert "autogenerated sidebar poc working"
This reverts commit c81da980
* POC of auto-generated sidebars for community docs
* update tests
* add initial test suite for autogenerated sidebars + fix some edge cases
* Improve autogen sidebars: strip more number prefixes in folder breadcrumb + slugs
* fix typo!
* Add tests for partially generated sidebars + fix edge cases + extract sidebar generation code
* Ability to read category metadatas file from a file in the category
* fix tests
* change position of API
* ability to extract number prefix
* stable system to enable position frontmatter
* fix tests for autogen sidebar position
* renamings
* restore community sidebars
* rename frontmatter position -> sidebar_position
* make sidebarItemsGenerator fn configurable
* minor changes
* rename dirPath => dirName
* Make the init template use autogenerated sidebars
* fix options
* fix docusaurus site: remove test docs
* add _category_ file to docs pathsToWatch
* add _category_ file to docs pathsToWatch
* tutorial: use sidebar_position instead of file number prefixes
* Adapt Docusaurus tutorial for autogenerated sidebars
* remove slug: /
* polish the homepage template
* rename _category_ sidebar_position to just "position"
* test for custom sidebarItemsGenerator fn
* fix category metadata + add link to report tutorial issues
* fix absolute path breaking tests
* fix absolute path breaking tests
* Add test for floating number sidebar_position
* add sidebarItemsGenerator unit tests
* add processSidebars unit tests
* Fix init template broken links
* windows test
* increase code translations test timeout
* cleanup mockCategoryMetadataFiles after windows test fixed
* update init template positions
* fix windows tests
* fix comment
* Add autogenerated sidebar items documentation + rewrite the full sidebars page doc
* add useful comment
* fix code block title
This commit is contained in:
parent
836f92708a
commit
db79d462ab
67 changed files with 2887 additions and 306 deletions
|
@ -0,0 +1,268 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import {
|
||||
CategoryMetadatasFile,
|
||||
DefaultSidebarItemsGenerator,
|
||||
} from '../sidebarItemsGenerator';
|
||||
import {DefaultCategoryCollapsedValue} from '../sidebars';
|
||||
import {Sidebar, SidebarItemsGenerator} from '../types';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
describe('DefaultSidebarItemsGenerator', () => {
|
||||
function testDefaultSidebarItemsGenerator(
|
||||
options: Partial<Parameters<SidebarItemsGenerator>[0]>,
|
||||
) {
|
||||
return DefaultSidebarItemsGenerator({
|
||||
item: {
|
||||
type: 'autogenerated',
|
||||
dirName: '.',
|
||||
},
|
||||
version: {
|
||||
versionName: 'current',
|
||||
contentPath: 'docs',
|
||||
},
|
||||
docs: [],
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
function mockCategoryMetadataFiles(
|
||||
categoryMetadataFiles: Record<string, Partial<CategoryMetadatasFile>>,
|
||||
) {
|
||||
jest.spyOn(fs, 'pathExists').mockImplementation((metadataFilePath) => {
|
||||
return typeof categoryMetadataFiles[metadataFilePath] !== 'undefined';
|
||||
});
|
||||
jest.spyOn(fs, 'readFile').mockImplementation(
|
||||
// @ts-expect-error: annoying TS error due to overrides
|
||||
async (metadataFilePath: string) => {
|
||||
return JSON.stringify(categoryMetadataFiles[metadataFilePath]);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
test('generates empty sidebar slice when no docs and emit a warning', async () => {
|
||||
const consoleWarn = jest.spyOn(console, 'warn');
|
||||
const sidebarSlice = await testDefaultSidebarItemsGenerator({
|
||||
docs: [],
|
||||
});
|
||||
expect(sidebarSlice).toEqual([]);
|
||||
expect(consoleWarn).toHaveBeenCalledWith(
|
||||
expect.stringMatching(
|
||||
/No docs found in dir .: can't auto-generate a sidebar/,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('generates simple flat sidebar', async () => {
|
||||
const sidebarSlice = await DefaultSidebarItemsGenerator({
|
||||
item: {
|
||||
type: 'autogenerated',
|
||||
dirName: '.',
|
||||
},
|
||||
version: {
|
||||
versionName: 'current',
|
||||
contentPath: '',
|
||||
},
|
||||
docs: [
|
||||
{
|
||||
id: 'doc1',
|
||||
source: 'doc1.md',
|
||||
sourceDirName: '.',
|
||||
sidebarPosition: 2,
|
||||
frontMatter: {
|
||||
sidebar_label: 'doc1 sidebar label',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'doc2',
|
||||
source: 'doc2.md',
|
||||
sourceDirName: '.',
|
||||
sidebarPosition: 3,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'doc3',
|
||||
source: 'doc3.md',
|
||||
sourceDirName: '.',
|
||||
sidebarPosition: 1,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'doc4',
|
||||
source: 'doc4.md',
|
||||
sourceDirName: '.',
|
||||
sidebarPosition: 1.5,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'doc5',
|
||||
source: 'doc5.md',
|
||||
sourceDirName: '.',
|
||||
sidebarPosition: undefined,
|
||||
frontMatter: {},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
{type: 'doc', id: 'doc3'},
|
||||
{type: 'doc', id: 'doc4'},
|
||||
{type: 'doc', id: 'doc1', label: 'doc1 sidebar label'},
|
||||
{type: 'doc', id: 'doc2'},
|
||||
{type: 'doc', id: 'doc5'},
|
||||
] as Sidebar);
|
||||
});
|
||||
|
||||
test('generates complex nested sidebar', async () => {
|
||||
mockCategoryMetadataFiles({
|
||||
'02-Guides/_category_.json': {collapsed: false},
|
||||
'02-Guides/01-SubGuides/_category_.yml': {
|
||||
label: 'SubGuides (metadata file label)',
|
||||
},
|
||||
});
|
||||
|
||||
const sidebarSlice = await DefaultSidebarItemsGenerator({
|
||||
item: {
|
||||
type: 'autogenerated',
|
||||
dirName: '.',
|
||||
},
|
||||
version: {
|
||||
versionName: 'current',
|
||||
contentPath: '',
|
||||
},
|
||||
docs: [
|
||||
{
|
||||
id: 'intro',
|
||||
source: 'intro.md',
|
||||
sourceDirName: '.',
|
||||
sidebarPosition: 1,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'tutorial2',
|
||||
source: 'tutorial2.md',
|
||||
sourceDirName: '01-Tutorials',
|
||||
sidebarPosition: 2,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'tutorial1',
|
||||
source: 'tutorial1.md',
|
||||
sourceDirName: '01-Tutorials',
|
||||
sidebarPosition: 1,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'guide2',
|
||||
source: 'guide2.md',
|
||||
sourceDirName: '02-Guides',
|
||||
sidebarPosition: 2,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'guide1',
|
||||
source: 'guide1.md',
|
||||
sourceDirName: '02-Guides',
|
||||
sidebarPosition: 1,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'nested-guide',
|
||||
source: 'nested-guide.md',
|
||||
sourceDirName: '02-Guides/01-SubGuides',
|
||||
sidebarPosition: undefined,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'end',
|
||||
source: 'end.md',
|
||||
sourceDirName: '.',
|
||||
sidebarPosition: 3,
|
||||
frontMatter: {},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
{type: 'doc', id: 'intro'},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Tutorials',
|
||||
collapsed: DefaultCategoryCollapsedValue,
|
||||
items: [
|
||||
{type: 'doc', id: 'tutorial1'},
|
||||
{type: 'doc', id: 'tutorial2'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Guides',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{type: 'doc', id: 'guide1'},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'SubGuides (metadata file label)',
|
||||
collapsed: DefaultCategoryCollapsedValue,
|
||||
items: [{type: 'doc', id: 'nested-guide'}],
|
||||
},
|
||||
{type: 'doc', id: 'guide2'},
|
||||
],
|
||||
},
|
||||
{type: 'doc', id: 'end'},
|
||||
] as Sidebar);
|
||||
});
|
||||
|
||||
test('generates subfolder sidebar', async () => {
|
||||
const sidebarSlice = await DefaultSidebarItemsGenerator({
|
||||
item: {
|
||||
type: 'autogenerated',
|
||||
dirName: 'subfolder/subsubfolder',
|
||||
},
|
||||
version: {
|
||||
versionName: 'current',
|
||||
contentPath: '',
|
||||
},
|
||||
docs: [
|
||||
{
|
||||
id: 'doc1',
|
||||
source: 'doc1.md',
|
||||
sourceDirName: 'subfolder/subsubfolder',
|
||||
sidebarPosition: undefined,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'doc2',
|
||||
source: 'doc2.md',
|
||||
sourceDirName: 'subfolder',
|
||||
sidebarPosition: undefined,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'doc3',
|
||||
source: 'doc3.md',
|
||||
sourceDirName: '.',
|
||||
sidebarPosition: undefined,
|
||||
frontMatter: {},
|
||||
},
|
||||
{
|
||||
id: 'doc4',
|
||||
source: 'doc4.md',
|
||||
sourceDirName: 'subfolder/subsubfolder',
|
||||
sidebarPosition: undefined,
|
||||
frontMatter: {},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(sidebarSlice).toEqual([
|
||||
{type: 'doc', id: 'doc1'},
|
||||
{type: 'doc', id: 'doc4'},
|
||||
] as Sidebar);
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue