mirror of
https://github.com/facebook/docusaurus.git
synced 2025-07-30 06:50:36 +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
|
@ -10,7 +10,7 @@
|
|||
import path from 'path';
|
||||
import {isMatch} from 'picomatch';
|
||||
import commander from 'commander';
|
||||
import {kebabCase} from 'lodash';
|
||||
import {kebabCase, orderBy} from 'lodash';
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import pluginContentDocs from '../index';
|
||||
|
@ -24,7 +24,7 @@ import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
|
|||
import * as cliDocs from '../cli';
|
||||
import {OptionsSchema} from '../options';
|
||||
import {normalizePluginOptions} from '@docusaurus/utils-validation';
|
||||
import {DocMetadata, LoadedVersion} from '../types';
|
||||
import {DocMetadata, LoadedVersion, SidebarItemsGenerator} from '../types';
|
||||
import {toSidebarsProp} from '../props';
|
||||
|
||||
// @ts-expect-error: TODO typedefs missing?
|
||||
|
@ -33,6 +33,17 @@ import {validate} from 'webpack';
|
|||
function findDocById(version: LoadedVersion, unversionedId: string) {
|
||||
return version.docs.find((item) => item.unversionedId === unversionedId);
|
||||
}
|
||||
function getDocById(version: LoadedVersion, unversionedId: string) {
|
||||
const doc = findDocById(version, unversionedId);
|
||||
if (!doc) {
|
||||
throw new Error(
|
||||
`No doc found with id=${unversionedId} in version ${version.versionName}.
|
||||
Available ids=\n- ${version.docs.map((d) => d.unversionedId).join('\n- ')}`,
|
||||
);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
const defaultDocMetadata: Partial<DocMetadata> = {
|
||||
next: undefined,
|
||||
previous: undefined,
|
||||
|
@ -40,6 +51,7 @@ const defaultDocMetadata: Partial<DocMetadata> = {
|
|||
lastUpdatedAt: undefined,
|
||||
lastUpdatedBy: undefined,
|
||||
sidebar_label: undefined,
|
||||
formattedLastUpdatedAt: undefined,
|
||||
};
|
||||
|
||||
const createFakeActions = (contentDir: string) => {
|
||||
|
@ -203,6 +215,7 @@ describe('simple website', () => {
|
|||
"sidebars.json",
|
||||
"i18n/en/docusaurus-plugin-content-docs/current/**/*.{md,mdx}",
|
||||
"docs/**/*.{md,mdx}",
|
||||
"docs/**/_category_.{json,yml,yaml}",
|
||||
]
|
||||
`);
|
||||
expect(isMatch('docs/hello.md', matchPattern)).toEqual(true);
|
||||
|
@ -247,6 +260,7 @@ describe('simple website', () => {
|
|||
version: 'current',
|
||||
id: 'hello',
|
||||
unversionedId: 'hello',
|
||||
sourceDirName: '.',
|
||||
isDocsHomePage: true,
|
||||
permalink: '/docs/',
|
||||
slug: '/',
|
||||
|
@ -268,11 +282,12 @@ describe('simple website', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(findDocById(currentVersion, 'foo/bar')).toEqual({
|
||||
expect(getDocById(currentVersion, 'foo/bar')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
version: 'current',
|
||||
id: 'foo/bar',
|
||||
unversionedId: 'foo/bar',
|
||||
sourceDirName: 'foo',
|
||||
isDocsHomePage: false,
|
||||
next: {
|
||||
title: 'baz',
|
||||
|
@ -368,15 +383,19 @@ describe('versioned website', () => {
|
|||
"sidebars.json",
|
||||
"i18n/en/docusaurus-plugin-content-docs/current/**/*.{md,mdx}",
|
||||
"docs/**/*.{md,mdx}",
|
||||
"docs/**/_category_.{json,yml,yaml}",
|
||||
"versioned_sidebars/version-1.0.1-sidebars.json",
|
||||
"i18n/en/docusaurus-plugin-content-docs/version-1.0.1/**/*.{md,mdx}",
|
||||
"versioned_docs/version-1.0.1/**/*.{md,mdx}",
|
||||
"versioned_docs/version-1.0.1/**/_category_.{json,yml,yaml}",
|
||||
"versioned_sidebars/version-1.0.0-sidebars.json",
|
||||
"i18n/en/docusaurus-plugin-content-docs/version-1.0.0/**/*.{md,mdx}",
|
||||
"versioned_docs/version-1.0.0/**/*.{md,mdx}",
|
||||
"versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}",
|
||||
"versioned_sidebars/version-withSlugs-sidebars.json",
|
||||
"i18n/en/docusaurus-plugin-content-docs/version-withSlugs/**/*.{md,mdx}",
|
||||
"versioned_docs/version-withSlugs/**/*.{md,mdx}",
|
||||
"versioned_docs/version-withSlugs/**/_category_.{json,yml,yaml}",
|
||||
]
|
||||
`);
|
||||
expect(isMatch('docs/hello.md', matchPattern)).toEqual(true);
|
||||
|
@ -427,10 +446,11 @@ describe('versioned website', () => {
|
|||
expect(findDocById(version101, 'foo/baz')).toBeUndefined();
|
||||
expect(findDocById(versionWithSlugs, 'foo/baz')).toBeUndefined();
|
||||
|
||||
expect(findDocById(currentVersion, 'foo/bar')).toEqual({
|
||||
expect(getDocById(currentVersion, 'foo/bar')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'foo/bar',
|
||||
unversionedId: 'foo/bar',
|
||||
sourceDirName: 'foo',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/next/foo/barSlug',
|
||||
slug: '/foo/barSlug',
|
||||
|
@ -452,10 +472,11 @@ describe('versioned website', () => {
|
|||
permalink: '/docs/next/',
|
||||
},
|
||||
});
|
||||
expect(findDocById(currentVersion, 'hello')).toEqual({
|
||||
expect(getDocById(currentVersion, 'hello')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'hello',
|
||||
unversionedId: 'hello',
|
||||
sourceDirName: '.',
|
||||
isDocsHomePage: true,
|
||||
permalink: '/docs/next/',
|
||||
slug: '/',
|
||||
|
@ -474,10 +495,11 @@ describe('versioned website', () => {
|
|||
permalink: '/docs/next/foo/barSlug',
|
||||
},
|
||||
});
|
||||
expect(findDocById(version101, 'hello')).toEqual({
|
||||
expect(getDocById(version101, 'hello')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'version-1.0.1/hello',
|
||||
unversionedId: 'hello',
|
||||
sourceDirName: '.',
|
||||
isDocsHomePage: true,
|
||||
permalink: '/docs/',
|
||||
slug: '/',
|
||||
|
@ -496,10 +518,11 @@ describe('versioned website', () => {
|
|||
permalink: '/docs/foo/bar',
|
||||
},
|
||||
});
|
||||
expect(findDocById(version100, 'foo/baz')).toEqual({
|
||||
expect(getDocById(version100, 'foo/baz')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'version-1.0.0/foo/baz',
|
||||
unversionedId: 'foo/baz',
|
||||
sourceDirName: 'foo',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/1.0.0/foo/baz',
|
||||
slug: '/foo/baz',
|
||||
|
@ -611,9 +634,11 @@ describe('versioned website (community)', () => {
|
|||
"community_sidebars.json",
|
||||
"i18n/en/docusaurus-plugin-content-docs-community/current/**/*.{md,mdx}",
|
||||
"community/**/*.{md,mdx}",
|
||||
"community/**/_category_.{json,yml,yaml}",
|
||||
"community_versioned_sidebars/version-1.0.0-sidebars.json",
|
||||
"i18n/en/docusaurus-plugin-content-docs-community/version-1.0.0/**/*.{md,mdx}",
|
||||
"community_versioned_docs/version-1.0.0/**/*.{md,mdx}",
|
||||
"community_versioned_docs/version-1.0.0/**/_category_.{json,yml,yaml}",
|
||||
]
|
||||
`);
|
||||
expect(isMatch('community/team.md', matchPattern)).toEqual(true);
|
||||
|
@ -644,10 +669,11 @@ describe('versioned website (community)', () => {
|
|||
expect(content.loadedVersions.length).toEqual(2);
|
||||
const [currentVersion, version100] = content.loadedVersions;
|
||||
|
||||
expect(findDocById(currentVersion, 'team')).toEqual({
|
||||
expect(getDocById(currentVersion, 'team')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'team',
|
||||
unversionedId: 'team',
|
||||
sourceDirName: '.',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/community/next/team',
|
||||
slug: '/team',
|
||||
|
@ -659,10 +685,11 @@ describe('versioned website (community)', () => {
|
|||
sidebar: 'community',
|
||||
frontMatter: {title: 'Team title translated'},
|
||||
});
|
||||
expect(findDocById(version100, 'team')).toEqual({
|
||||
expect(getDocById(version100, 'team')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'version-1.0.0/team',
|
||||
unversionedId: 'team',
|
||||
sourceDirName: '.',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/community/team',
|
||||
slug: '/team',
|
||||
|
@ -709,7 +736,7 @@ describe('site with doc label', () => {
|
|||
}),
|
||||
);
|
||||
|
||||
const content = await plugin.loadContent();
|
||||
const content = (await plugin.loadContent?.())!;
|
||||
|
||||
return {content};
|
||||
}
|
||||
|
@ -730,3 +757,807 @@ describe('site with doc label', () => {
|
|||
expect(sidebarProps.docs[1].label).toBe('Hello 2 From Doc');
|
||||
});
|
||||
});
|
||||
|
||||
describe('site with full autogenerated sidebar', () => {
|
||||
async function loadSite() {
|
||||
const siteDir = path.join(
|
||||
__dirname,
|
||||
'__fixtures__',
|
||||
'site-with-autogenerated-sidebar',
|
||||
);
|
||||
const context = await loadContext(siteDir);
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions(OptionsSchema, {
|
||||
path: 'docs',
|
||||
}),
|
||||
);
|
||||
|
||||
const content = (await plugin.loadContent?.())!;
|
||||
|
||||
return {content, siteDir};
|
||||
}
|
||||
|
||||
test('sidebar is fully autogenerated', async () => {
|
||||
const {content} = await loadSite();
|
||||
const version = content.loadedVersions[0];
|
||||
|
||||
expect(version.sidebars).toEqual({
|
||||
defaultSidebar: [
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'getting-started',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'installation',
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Guides',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'Guides/guide1',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'Guides/guide2',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'Guides/guide2.5',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'Guides/guide3',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'Guides/guide4',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'Guides/guide5',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'API (label from _category_.json)',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/api-overview',
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Core APIs',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
|
||||
id: 'API/Core APIs/Client API',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/Core APIs/Server API',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Extension APIs (label from _category_.yml)',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/Extension APIs/Plugin API',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/Extension APIs/Theme API',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/api-end',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('docs in fully generated sidebar have correct metadatas', async () => {
|
||||
const {content, siteDir} = await loadSite();
|
||||
const version = content.loadedVersions[0];
|
||||
|
||||
expect(getDocById(version, 'getting-started')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'getting-started',
|
||||
unversionedId: 'getting-started',
|
||||
sourceDirName: '.',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/getting-started',
|
||||
slug: '/getting-started',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'0-getting-started.md',
|
||||
),
|
||||
title: 'Getting Started',
|
||||
description: 'Getting started text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 0,
|
||||
previous: undefined,
|
||||
next: {
|
||||
permalink: '/docs/installation',
|
||||
title: 'Installation',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'installation')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'installation',
|
||||
unversionedId: 'installation',
|
||||
sourceDirName: '.',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/installation',
|
||||
slug: '/installation',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'1-installation.md',
|
||||
),
|
||||
title: 'Installation',
|
||||
description: 'Installation text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 1,
|
||||
previous: {
|
||||
permalink: '/docs/getting-started',
|
||||
title: 'Getting Started',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/Guides/guide1',
|
||||
title: 'Guide 1',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'Guides/guide1')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'Guides/guide1',
|
||||
unversionedId: 'Guides/guide1',
|
||||
sourceDirName: 'Guides',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/Guides/guide1',
|
||||
slug: '/Guides/guide1',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'Guides',
|
||||
'z-guide1.md',
|
||||
),
|
||||
title: 'Guide 1',
|
||||
description: 'Guide 1 text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {
|
||||
id: 'guide1',
|
||||
sidebar_position: 1,
|
||||
},
|
||||
sidebarPosition: 1,
|
||||
previous: {
|
||||
permalink: '/docs/installation',
|
||||
title: 'Installation',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/Guides/guide2',
|
||||
title: 'Guide 2',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'Guides/guide2')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'Guides/guide2',
|
||||
unversionedId: 'Guides/guide2',
|
||||
sourceDirName: 'Guides',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/Guides/guide2',
|
||||
slug: '/Guides/guide2',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'Guides',
|
||||
'02-guide2.md',
|
||||
),
|
||||
title: 'Guide 2',
|
||||
description: 'Guide 2 text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {
|
||||
id: 'guide2',
|
||||
},
|
||||
sidebarPosition: 2,
|
||||
previous: {
|
||||
permalink: '/docs/Guides/guide1',
|
||||
title: 'Guide 1',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/Guides/guide2.5',
|
||||
title: 'Guide 2.5',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'Guides/guide2.5')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'Guides/guide2.5',
|
||||
unversionedId: 'Guides/guide2.5',
|
||||
sourceDirName: 'Guides',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/Guides/guide2.5',
|
||||
slug: '/Guides/guide2.5',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'Guides',
|
||||
'0-guide2.5.md',
|
||||
),
|
||||
title: 'Guide 2.5',
|
||||
description: 'Guide 2.5 text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {
|
||||
id: 'guide2.5',
|
||||
sidebar_position: 2.5,
|
||||
},
|
||||
sidebarPosition: 2.5,
|
||||
previous: {
|
||||
permalink: '/docs/Guides/guide2',
|
||||
title: 'Guide 2',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/Guides/guide3',
|
||||
title: 'Guide 3',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'Guides/guide3')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'Guides/guide3',
|
||||
unversionedId: 'Guides/guide3',
|
||||
sourceDirName: 'Guides',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/Guides/guide3',
|
||||
slug: '/Guides/guide3',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'Guides',
|
||||
'guide3.md',
|
||||
),
|
||||
title: 'Guide 3',
|
||||
description: 'Guide 3 text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {
|
||||
id: 'guide3',
|
||||
sidebar_position: 3,
|
||||
},
|
||||
sidebarPosition: 3,
|
||||
previous: {
|
||||
permalink: '/docs/Guides/guide2.5',
|
||||
title: 'Guide 2.5',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/Guides/guide4',
|
||||
title: 'Guide 4',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'Guides/guide4')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'Guides/guide4',
|
||||
unversionedId: 'Guides/guide4',
|
||||
sourceDirName: 'Guides',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/Guides/guide4',
|
||||
slug: '/Guides/guide4',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'Guides',
|
||||
'a-guide4.md',
|
||||
),
|
||||
title: 'Guide 4',
|
||||
description: 'Guide 4 text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {
|
||||
id: 'guide4',
|
||||
},
|
||||
sidebarPosition: undefined,
|
||||
previous: {
|
||||
permalink: '/docs/Guides/guide3',
|
||||
title: 'Guide 3',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/Guides/guide5',
|
||||
title: 'Guide 5',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'Guides/guide5')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'Guides/guide5',
|
||||
unversionedId: 'Guides/guide5',
|
||||
sourceDirName: 'Guides',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/Guides/guide5',
|
||||
slug: '/Guides/guide5',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'Guides',
|
||||
'b-guide5.md',
|
||||
),
|
||||
title: 'Guide 5',
|
||||
description: 'Guide 5 text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {
|
||||
id: 'guide5',
|
||||
},
|
||||
sidebarPosition: undefined,
|
||||
previous: {
|
||||
permalink: '/docs/Guides/guide4',
|
||||
title: 'Guide 4',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/API/api-overview',
|
||||
title: 'API Overview',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/api-overview')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/api-overview',
|
||||
unversionedId: 'API/api-overview',
|
||||
sourceDirName: '3-API',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/api-overview',
|
||||
slug: '/API/api-overview',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'00_api-overview.md',
|
||||
),
|
||||
title: 'API Overview',
|
||||
description: 'API Overview text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 0,
|
||||
previous: {
|
||||
permalink: '/docs/Guides/guide5',
|
||||
title: 'Guide 5',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/API/Core APIs/Client API',
|
||||
title: 'Client API',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/Core APIs/Client API')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/Core APIs/Client API',
|
||||
unversionedId: 'API/Core APIs/Client API',
|
||||
sourceDirName: '3-API/01_Core APIs',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/Core APIs/Client API',
|
||||
slug: '/API/Core APIs/Client API',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'01_Core APIs',
|
||||
'0 --- Client API.md',
|
||||
),
|
||||
title: 'Client API',
|
||||
description: 'Client API text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 0,
|
||||
previous: {
|
||||
permalink: '/docs/API/api-overview',
|
||||
title: 'API Overview',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/API/Core APIs/Server API',
|
||||
title: 'Server API',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/Core APIs/Server API')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/Core APIs/Server API',
|
||||
unversionedId: 'API/Core APIs/Server API',
|
||||
sourceDirName: '3-API/01_Core APIs',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/Core APIs/Server API',
|
||||
slug: '/API/Core APIs/Server API',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'01_Core APIs',
|
||||
'1 --- Server API.md',
|
||||
),
|
||||
title: 'Server API',
|
||||
description: 'Server API text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 1,
|
||||
previous: {
|
||||
permalink: '/docs/API/Core APIs/Client API',
|
||||
title: 'Client API',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/API/Extension APIs/Plugin API',
|
||||
title: 'Plugin API',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/Extension APIs/Plugin API')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/Extension APIs/Plugin API',
|
||||
unversionedId: 'API/Extension APIs/Plugin API',
|
||||
sourceDirName: '3-API/02_Extension APIs',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/Extension APIs/Plugin API',
|
||||
slug: '/API/Extension APIs/Plugin API',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'02_Extension APIs',
|
||||
'0. Plugin API.md',
|
||||
),
|
||||
title: 'Plugin API',
|
||||
description: 'Plugin API text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 0,
|
||||
previous: {
|
||||
permalink: '/docs/API/Core APIs/Server API',
|
||||
title: 'Server API',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/API/Extension APIs/Theme API',
|
||||
title: 'Theme API',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/Extension APIs/Theme API')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/Extension APIs/Theme API',
|
||||
unversionedId: 'API/Extension APIs/Theme API',
|
||||
sourceDirName: '3-API/02_Extension APIs',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/Extension APIs/Theme API',
|
||||
slug: '/API/Extension APIs/Theme API',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'02_Extension APIs',
|
||||
'1. Theme API.md',
|
||||
),
|
||||
title: 'Theme API',
|
||||
description: 'Theme API text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 1,
|
||||
previous: {
|
||||
permalink: '/docs/API/Extension APIs/Plugin API',
|
||||
title: 'Plugin API',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/API/api-end',
|
||||
title: 'API End',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/api-end')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/api-end',
|
||||
unversionedId: 'API/api-end',
|
||||
sourceDirName: '3-API',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/api-end',
|
||||
slug: '/API/api-end',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'03_api-end.md',
|
||||
),
|
||||
title: 'API End',
|
||||
description: 'API End text',
|
||||
version: 'current',
|
||||
sidebar: 'defaultSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 3,
|
||||
previous: {
|
||||
permalink: '/docs/API/Extension APIs/Theme API',
|
||||
title: 'Theme API',
|
||||
},
|
||||
next: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('site with partial autogenerated sidebars', () => {
|
||||
async function loadSite() {
|
||||
const siteDir = path.join(
|
||||
__dirname,
|
||||
'__fixtures__',
|
||||
'site-with-autogenerated-sidebar',
|
||||
);
|
||||
const context = await loadContext(siteDir, {});
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions(OptionsSchema, {
|
||||
path: 'docs',
|
||||
sidebarPath: path.join(
|
||||
__dirname,
|
||||
'__fixtures__',
|
||||
'site-with-autogenerated-sidebar',
|
||||
'partialAutogeneratedSidebars.js',
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
const content = (await plugin.loadContent?.())!;
|
||||
|
||||
return {content, siteDir};
|
||||
}
|
||||
|
||||
test('sidebar is partially autogenerated', async () => {
|
||||
const {content} = await loadSite();
|
||||
const version = content.loadedVersions[0];
|
||||
|
||||
expect(version.sidebars).toEqual({
|
||||
someSidebar: [
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/api-end',
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Some category',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/api-overview',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/Extension APIs/Plugin API',
|
||||
},
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'API/Extension APIs/Theme API',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('docs in partially generated sidebar have correct metadatas', async () => {
|
||||
const {content, siteDir} = await loadSite();
|
||||
const version = content.loadedVersions[0];
|
||||
|
||||
// Only looking at the docs of the autogen sidebar, others metadatas should not be affected
|
||||
|
||||
expect(getDocById(version, 'API/api-end')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/api-end',
|
||||
unversionedId: 'API/api-end',
|
||||
sourceDirName: '3-API',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/api-end',
|
||||
slug: '/API/api-end',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'03_api-end.md',
|
||||
),
|
||||
title: 'API End',
|
||||
description: 'API End text',
|
||||
version: 'current',
|
||||
sidebar: 'someSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 3, // ignored (not part of the autogenerated sidebar slice)
|
||||
previous: undefined,
|
||||
next: {
|
||||
permalink: '/docs/API/api-overview',
|
||||
title: 'API Overview',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/api-overview')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/api-overview',
|
||||
unversionedId: 'API/api-overview',
|
||||
sourceDirName: '3-API',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/api-overview',
|
||||
slug: '/API/api-overview',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'00_api-overview.md',
|
||||
),
|
||||
title: 'API Overview',
|
||||
description: 'API Overview text',
|
||||
version: 'current',
|
||||
sidebar: 'someSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 0, // ignored (not part of the autogenerated sidebar slice)
|
||||
previous: {
|
||||
permalink: '/docs/API/api-end',
|
||||
title: 'API End',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/API/Extension APIs/Plugin API',
|
||||
title: 'Plugin API',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/Extension APIs/Plugin API')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/Extension APIs/Plugin API',
|
||||
unversionedId: 'API/Extension APIs/Plugin API',
|
||||
sourceDirName: '3-API/02_Extension APIs',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/Extension APIs/Plugin API',
|
||||
slug: '/API/Extension APIs/Plugin API',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'02_Extension APIs',
|
||||
'0. Plugin API.md',
|
||||
),
|
||||
title: 'Plugin API',
|
||||
description: 'Plugin API text',
|
||||
version: 'current',
|
||||
sidebar: 'someSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 0,
|
||||
previous: {
|
||||
permalink: '/docs/API/api-overview',
|
||||
title: 'API Overview',
|
||||
},
|
||||
next: {
|
||||
permalink: '/docs/API/Extension APIs/Theme API',
|
||||
title: 'Theme API',
|
||||
},
|
||||
});
|
||||
|
||||
expect(getDocById(version, 'API/Extension APIs/Theme API')).toEqual({
|
||||
...defaultDocMetadata,
|
||||
id: 'API/Extension APIs/Theme API',
|
||||
unversionedId: 'API/Extension APIs/Theme API',
|
||||
sourceDirName: '3-API/02_Extension APIs',
|
||||
isDocsHomePage: false,
|
||||
permalink: '/docs/API/Extension APIs/Theme API',
|
||||
slug: '/API/Extension APIs/Theme API',
|
||||
source: path.posix.join(
|
||||
'@site',
|
||||
posixPath(path.relative(siteDir, version.contentPath)),
|
||||
'3-API',
|
||||
'02_Extension APIs',
|
||||
'1. Theme API.md',
|
||||
),
|
||||
title: 'Theme API',
|
||||
description: 'Theme API text',
|
||||
version: 'current',
|
||||
sidebar: 'someSidebar',
|
||||
frontMatter: {},
|
||||
sidebarPosition: 1,
|
||||
previous: {
|
||||
permalink: '/docs/API/Extension APIs/Plugin API',
|
||||
title: 'Plugin API',
|
||||
},
|
||||
next: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('site with custom sidebar items generator', () => {
|
||||
async function loadSite(sidebarItemsGenerator: SidebarItemsGenerator) {
|
||||
const siteDir = path.join(
|
||||
__dirname,
|
||||
'__fixtures__',
|
||||
'site-with-autogenerated-sidebar',
|
||||
);
|
||||
const context = await loadContext(siteDir);
|
||||
const plugin = pluginContentDocs(
|
||||
context,
|
||||
normalizePluginOptions(OptionsSchema, {
|
||||
path: 'docs',
|
||||
sidebarItemsGenerator,
|
||||
}),
|
||||
);
|
||||
const content = (await plugin.loadContent?.())!;
|
||||
return {content, siteDir};
|
||||
}
|
||||
|
||||
test('sidebar is autogenerated according to custom sidebarItemsGenerator', async () => {
|
||||
const customSidebarItemsGenerator: SidebarItemsGenerator = async () => {
|
||||
return [
|
||||
{type: 'doc', id: 'API/api-overview'},
|
||||
{type: 'doc', id: 'API/api-end'},
|
||||
];
|
||||
};
|
||||
|
||||
const customSidebarItemsGeneratorMock: SidebarItemsGenerator = jest.fn(
|
||||
customSidebarItemsGenerator,
|
||||
);
|
||||
|
||||
const {content} = await loadSite(customSidebarItemsGeneratorMock);
|
||||
const version = content.loadedVersions[0];
|
||||
|
||||
expect(version.sidebars).toEqual({
|
||||
defaultSidebar: [
|
||||
{type: 'doc', id: 'API/api-overview'},
|
||||
{type: 'doc', id: 'API/api-end'},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('sidebarItemsGenerator is called with appropriate data', async () => {
|
||||
type GeneratorArg = Parameters<SidebarItemsGenerator>[0];
|
||||
|
||||
const customSidebarItemsGeneratorMock = jest.fn(
|
||||
async (_arg: GeneratorArg) => [],
|
||||
);
|
||||
const {siteDir} = await loadSite(customSidebarItemsGeneratorMock);
|
||||
|
||||
const generatorArg: GeneratorArg =
|
||||
customSidebarItemsGeneratorMock.mock.calls[0][0];
|
||||
|
||||
// Make test pass even if docs are in different order and paths are absolutes
|
||||
function makeDeterministic(arg: GeneratorArg): GeneratorArg {
|
||||
return {
|
||||
...arg,
|
||||
docs: orderBy(arg.docs, 'id'),
|
||||
version: {
|
||||
...arg.version,
|
||||
contentPath: path.relative(siteDir, arg.version.contentPath),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
expect(makeDeterministic(generatorArg)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue