@docusaurus/plugin-content-docs 2.0.0-beta.8bda3b2db → 2.0.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/.tsbuildinfo +1 -1
- package/lib/cli.d.ts +2 -2
- package/lib/cli.js +20 -24
- package/lib/client/docsClientUtils.d.ts +1 -4
- package/lib/client/docsClientUtils.js +12 -16
- package/lib/docFrontMatter.js +7 -3
- package/lib/docs.d.ts +4 -2
- package/lib/docs.js +77 -23
- package/lib/index.js +88 -94
- package/lib/lastUpdate.js +8 -8
- package/lib/markdown/index.d.ts +3 -6
- package/lib/markdown/index.js +3 -3
- package/lib/markdown/linkify.js +2 -2
- package/lib/options.d.ts +1 -1
- package/lib/options.js +39 -11
- package/lib/props.d.ts +7 -2
- package/lib/props.js +27 -4
- package/lib/{sidebarItemsGenerator.d.ts → sidebars/generator.d.ts} +3 -1
- package/lib/sidebars/generator.js +174 -0
- package/lib/sidebars/index.d.ts +14 -0
- package/lib/sidebars/index.js +64 -0
- package/lib/sidebars/normalization.d.ts +9 -0
- package/lib/sidebars/normalization.js +58 -0
- package/lib/sidebars/processor.d.ts +16 -0
- package/lib/sidebars/processor.js +70 -0
- package/lib/sidebars/types.d.ts +87 -0
- package/lib/sidebars/types.js +13 -0
- package/lib/sidebars/utils.d.ts +22 -0
- package/lib/sidebars/utils.js +101 -0
- package/lib/sidebars/validation.d.ts +8 -0
- package/lib/sidebars/validation.js +102 -0
- package/lib/slug.js +4 -4
- package/lib/tags.d.ts +8 -0
- package/lib/tags.js +22 -0
- package/lib/theme/hooks/useDocs.js +24 -21
- package/lib/translations.d.ts +1 -1
- package/lib/translations.js +13 -13
- package/lib/types.d.ts +35 -58
- package/lib/versions.d.ts +1 -1
- package/lib/versions.js +75 -22
- package/package.json +15 -14
- package/src/__tests__/__fixtures__/simple-site/docs/_partials/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/simple-site/docs/_partials/subfolder/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/simple-site/docs/_somePartial.md +3 -0
- package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +5 -0
- package/src/__tests__/__fixtures__/simple-site/docs/hello.md +1 -0
- package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +2 -0
- package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +2 -0
- package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +2 -0
- package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +2 -0
- package/src/__tests__/__fixtures__/simple-site/sidebars.json +15 -1
- package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +6 -0
- package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_partials/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_partials/subfolder/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_somePartial.md +3 -0
- package/src/__tests__/__snapshots__/cli.test.ts.snap +33 -0
- package/src/__tests__/__snapshots__/docs.test.ts.snap +140 -0
- package/src/__tests__/__snapshots__/index.test.ts.snap +478 -60
- package/src/__tests__/__snapshots__/translations.test.ts.snap +0 -3
- package/src/__tests__/cli.test.ts +14 -10
- package/src/__tests__/docFrontMatter.test.ts +163 -48
- package/src/__tests__/docs.test.ts +167 -21
- package/src/__tests__/index.test.ts +74 -30
- package/src/__tests__/lastUpdate.test.ts +3 -2
- package/src/__tests__/options.test.ts +46 -3
- package/src/__tests__/props.test.ts +62 -0
- package/src/__tests__/translations.test.ts +0 -1
- package/src/__tests__/versions.test.ts +88 -60
- package/src/cli.ts +27 -30
- package/src/client/__tests__/docsClientUtils.test.ts +4 -5
- package/src/client/docsClientUtils.ts +6 -27
- package/src/docFrontMatter.ts +8 -3
- package/src/docs.ts +92 -9
- package/src/index.ts +114 -121
- package/src/lastUpdate.ts +10 -6
- package/src/markdown/index.ts +8 -12
- package/src/numberPrefix.ts +4 -2
- package/src/options.ts +47 -17
- package/src/plugin-content-docs.d.ts +121 -34
- package/src/props.ts +42 -6
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category.js +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-collapsed.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-first-level-not-category.js +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-unknown-type.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-wrong-field.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars.json +0 -0
- package/src/{__tests__/__snapshots__/sidebars.test.ts.snap → sidebars/__tests__/__snapshots__/index.test.ts.snap} +21 -6
- package/src/{__tests__/sidebarItemsGenerator.test.ts → sidebars/__tests__/generator.test.ts} +29 -7
- package/src/sidebars/__tests__/index.test.ts +202 -0
- package/src/sidebars/__tests__/processor.test.ts +148 -0
- package/src/sidebars/__tests__/utils.test.ts +395 -0
- package/src/sidebars/generator.ts +253 -0
- package/src/sidebars/index.ts +84 -0
- package/src/sidebars/normalization.ts +88 -0
- package/src/sidebars/processor.ts +124 -0
- package/src/sidebars/types.ts +156 -0
- package/src/sidebars/utils.ts +146 -0
- package/src/sidebars/validation.ts +124 -0
- package/src/tags.ts +21 -0
- package/src/theme/hooks/useDocs.ts +5 -1
- package/src/translations.ts +26 -36
- package/src/types.ts +48 -99
- package/src/versions.ts +109 -17
- package/lib/sidebarItemsGenerator.js +0 -211
- package/lib/sidebars.d.ts +0 -43
- package/lib/sidebars.js +0 -319
- package/src/__tests__/sidebars.test.ts +0 -639
- package/src/sidebarItemsGenerator.ts +0 -307
- package/src/sidebars.ts +0 -506
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs-extra';
|
|
9
|
+
import importFresh from 'import-fresh';
|
|
10
|
+
import type {SidebarsConfig, Sidebars, NormalizedSidebars} from './types';
|
|
11
|
+
import type {PluginOptions} from '../types';
|
|
12
|
+
import {validateSidebars} from './validation';
|
|
13
|
+
import {normalizeSidebars} from './normalization';
|
|
14
|
+
import {processSidebars, SidebarProcessorProps} from './processor';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
|
|
17
|
+
export const DefaultSidebars: SidebarsConfig = {
|
|
18
|
+
defaultSidebar: [
|
|
19
|
+
{
|
|
20
|
+
type: 'autogenerated',
|
|
21
|
+
dirName: '.',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const DisabledSidebars: SidebarsConfig = {};
|
|
27
|
+
|
|
28
|
+
// If a path is provided, make it absolute
|
|
29
|
+
// use this before loadSidebars()
|
|
30
|
+
export function resolveSidebarPathOption(
|
|
31
|
+
siteDir: string,
|
|
32
|
+
sidebarPathOption: PluginOptions['sidebarPath'],
|
|
33
|
+
): PluginOptions['sidebarPath'] {
|
|
34
|
+
return sidebarPathOption
|
|
35
|
+
? path.resolve(siteDir, sidebarPathOption)
|
|
36
|
+
: sidebarPathOption;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function loadSidebarFile(
|
|
40
|
+
sidebarFilePath: string | false | undefined,
|
|
41
|
+
): SidebarsConfig {
|
|
42
|
+
// false => no sidebars
|
|
43
|
+
if (sidebarFilePath === false) {
|
|
44
|
+
return DisabledSidebars;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// undefined => defaults to autogenerated sidebars
|
|
48
|
+
if (typeof sidebarFilePath === 'undefined') {
|
|
49
|
+
return DefaultSidebars;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Non-existent sidebars file: no sidebars
|
|
53
|
+
// Note: this edge case can happen on versioned docs, not current version
|
|
54
|
+
// We avoid creating empty versioned sidebars file with the CLI
|
|
55
|
+
if (!fs.existsSync(sidebarFilePath)) {
|
|
56
|
+
return DisabledSidebars;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// We don't want sidebars to be cached because of hot reloading.
|
|
60
|
+
return importFresh(sidebarFilePath);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function loadUnprocessedSidebars(
|
|
64
|
+
sidebarFilePath: string | false | undefined,
|
|
65
|
+
options: SidebarProcessorProps['options'],
|
|
66
|
+
): NormalizedSidebars {
|
|
67
|
+
const sidebarsConfig = loadSidebarFile(sidebarFilePath);
|
|
68
|
+
validateSidebars(sidebarsConfig);
|
|
69
|
+
|
|
70
|
+
const normalizedSidebars = normalizeSidebars(sidebarsConfig, options);
|
|
71
|
+
return normalizedSidebars;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Note: sidebarFilePath must be absolute, use resolveSidebarPathOption
|
|
75
|
+
export async function loadSidebars(
|
|
76
|
+
sidebarFilePath: string | false | undefined,
|
|
77
|
+
options: SidebarProcessorProps,
|
|
78
|
+
): Promise<Sidebars> {
|
|
79
|
+
const unprocessedSidebars = loadUnprocessedSidebars(
|
|
80
|
+
sidebarFilePath,
|
|
81
|
+
options.options,
|
|
82
|
+
);
|
|
83
|
+
return processSidebars(unprocessedSidebars, options);
|
|
84
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {SidebarOptions} from '../types';
|
|
9
|
+
import {
|
|
10
|
+
NormalizedSidebarItem,
|
|
11
|
+
NormalizedSidebar,
|
|
12
|
+
NormalizedSidebars,
|
|
13
|
+
SidebarCategoriesShorthand,
|
|
14
|
+
SidebarItemCategoryConfig,
|
|
15
|
+
SidebarItemConfig,
|
|
16
|
+
SidebarConfig,
|
|
17
|
+
SidebarsConfig,
|
|
18
|
+
isCategoriesShorthand,
|
|
19
|
+
} from './types';
|
|
20
|
+
import {mapValues} from 'lodash';
|
|
21
|
+
|
|
22
|
+
function normalizeCategoriesShorthand(
|
|
23
|
+
sidebar: SidebarCategoriesShorthand,
|
|
24
|
+
options: SidebarOptions,
|
|
25
|
+
): SidebarItemCategoryConfig[] {
|
|
26
|
+
return Object.entries(sidebar).map(([label, items]) => ({
|
|
27
|
+
type: 'category',
|
|
28
|
+
collapsed: options.sidebarCollapsed,
|
|
29
|
+
collapsible: options.sidebarCollapsible,
|
|
30
|
+
label,
|
|
31
|
+
items,
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Normalizes recursively item and all its children. Ensures that at the end
|
|
37
|
+
* each item will be an object with the corresponding type.
|
|
38
|
+
*/
|
|
39
|
+
function normalizeItem(
|
|
40
|
+
item: SidebarItemConfig,
|
|
41
|
+
options: SidebarOptions,
|
|
42
|
+
): NormalizedSidebarItem[] {
|
|
43
|
+
if (typeof item === 'string') {
|
|
44
|
+
return [
|
|
45
|
+
{
|
|
46
|
+
type: 'doc',
|
|
47
|
+
id: item,
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
if (isCategoriesShorthand(item)) {
|
|
52
|
+
return normalizeCategoriesShorthand(item, options).flatMap((subitem) =>
|
|
53
|
+
normalizeItem(subitem, options),
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return item.type === 'category'
|
|
57
|
+
? [
|
|
58
|
+
{
|
|
59
|
+
...item,
|
|
60
|
+
items: item.items.flatMap((subItem) =>
|
|
61
|
+
normalizeItem(subItem, options),
|
|
62
|
+
),
|
|
63
|
+
collapsible: item.collapsible ?? options.sidebarCollapsible,
|
|
64
|
+
collapsed: item.collapsed ?? options.sidebarCollapsed,
|
|
65
|
+
},
|
|
66
|
+
]
|
|
67
|
+
: [item];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function normalizeSidebar(
|
|
71
|
+
sidebar: SidebarConfig,
|
|
72
|
+
options: SidebarOptions,
|
|
73
|
+
): NormalizedSidebar {
|
|
74
|
+
const normalizedSidebar = Array.isArray(sidebar)
|
|
75
|
+
? sidebar
|
|
76
|
+
: normalizeCategoriesShorthand(sidebar, options);
|
|
77
|
+
|
|
78
|
+
return normalizedSidebar.flatMap((subitem) =>
|
|
79
|
+
normalizeItem(subitem, options),
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function normalizeSidebars(
|
|
84
|
+
sidebars: SidebarsConfig,
|
|
85
|
+
options: SidebarOptions,
|
|
86
|
+
): NormalizedSidebars {
|
|
87
|
+
return mapValues(sidebars, (subitem) => normalizeSidebar(subitem, options));
|
|
88
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
NumberPrefixParser,
|
|
10
|
+
DocMetadataBase,
|
|
11
|
+
VersionMetadata,
|
|
12
|
+
SidebarOptions,
|
|
13
|
+
} from '../types';
|
|
14
|
+
import type {
|
|
15
|
+
Sidebars,
|
|
16
|
+
Sidebar,
|
|
17
|
+
SidebarItem,
|
|
18
|
+
NormalizedSidebarItem,
|
|
19
|
+
NormalizedSidebar,
|
|
20
|
+
NormalizedSidebars,
|
|
21
|
+
SidebarItemsGeneratorOption,
|
|
22
|
+
SidebarItemsGeneratorDoc,
|
|
23
|
+
SidebarItemsGeneratorVersion,
|
|
24
|
+
} from './types';
|
|
25
|
+
import {transformSidebarItems} from './utils';
|
|
26
|
+
import {DefaultSidebarItemsGenerator} from './generator';
|
|
27
|
+
import {mapValues, memoize, pick} from 'lodash';
|
|
28
|
+
import combinePromises from 'combine-promises';
|
|
29
|
+
|
|
30
|
+
export type SidebarProcessorProps = {
|
|
31
|
+
sidebarItemsGenerator: SidebarItemsGeneratorOption;
|
|
32
|
+
numberPrefixParser: NumberPrefixParser;
|
|
33
|
+
docs: DocMetadataBase[];
|
|
34
|
+
version: VersionMetadata;
|
|
35
|
+
options: SidebarOptions;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function toSidebarItemsGeneratorDoc(
|
|
39
|
+
doc: DocMetadataBase,
|
|
40
|
+
): SidebarItemsGeneratorDoc {
|
|
41
|
+
return pick(doc, [
|
|
42
|
+
'id',
|
|
43
|
+
'frontMatter',
|
|
44
|
+
'source',
|
|
45
|
+
'sourceDirName',
|
|
46
|
+
'sidebarPosition',
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function toSidebarItemsGeneratorVersion(
|
|
51
|
+
version: VersionMetadata,
|
|
52
|
+
): SidebarItemsGeneratorVersion {
|
|
53
|
+
return pick(version, ['versionName', 'contentPath']);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Handle the generation of autogenerated sidebar items and other post-processing checks
|
|
57
|
+
async function processSidebar(
|
|
58
|
+
unprocessedSidebar: NormalizedSidebar,
|
|
59
|
+
{
|
|
60
|
+
sidebarItemsGenerator,
|
|
61
|
+
numberPrefixParser,
|
|
62
|
+
docs,
|
|
63
|
+
version,
|
|
64
|
+
options,
|
|
65
|
+
}: SidebarProcessorProps,
|
|
66
|
+
): Promise<Sidebar> {
|
|
67
|
+
// Just a minor lazy transformation optimization
|
|
68
|
+
const getSidebarItemsGeneratorDocsAndVersion = memoize(() => ({
|
|
69
|
+
docs: docs.map(toSidebarItemsGeneratorDoc),
|
|
70
|
+
version: toSidebarItemsGeneratorVersion(version),
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
async function handleAutoGeneratedItems(
|
|
74
|
+
item: NormalizedSidebarItem,
|
|
75
|
+
): Promise<SidebarItem[]> {
|
|
76
|
+
if (item.type === 'category') {
|
|
77
|
+
return [
|
|
78
|
+
{
|
|
79
|
+
...item,
|
|
80
|
+
items: (
|
|
81
|
+
await Promise.all(item.items.map(handleAutoGeneratedItems))
|
|
82
|
+
).flat(),
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
if (item.type === 'autogenerated') {
|
|
87
|
+
return sidebarItemsGenerator({
|
|
88
|
+
item,
|
|
89
|
+
numberPrefixParser,
|
|
90
|
+
defaultSidebarItemsGenerator: DefaultSidebarItemsGenerator,
|
|
91
|
+
...getSidebarItemsGeneratorDocsAndVersion(),
|
|
92
|
+
options,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return [item];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const processedSidebar = (
|
|
99
|
+
await Promise.all(unprocessedSidebar.map(handleAutoGeneratedItems))
|
|
100
|
+
).flat();
|
|
101
|
+
|
|
102
|
+
const fixSidebarItemInconsistencies = (item: SidebarItem): SidebarItem => {
|
|
103
|
+
// A non-collapsible category can't be collapsed!
|
|
104
|
+
if (item.type === 'category' && !item.collapsible && item.collapsed) {
|
|
105
|
+
return {
|
|
106
|
+
...item,
|
|
107
|
+
collapsed: false,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return item;
|
|
111
|
+
};
|
|
112
|
+
return transformSidebarItems(processedSidebar, fixSidebarItemInconsistencies);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function processSidebars(
|
|
116
|
+
unprocessedSidebars: NormalizedSidebars,
|
|
117
|
+
props: SidebarProcessorProps,
|
|
118
|
+
): Promise<Sidebars> {
|
|
119
|
+
return combinePromises(
|
|
120
|
+
mapValues(unprocessedSidebars, (unprocessedSidebar) =>
|
|
121
|
+
processSidebar(unprocessedSidebar, props),
|
|
122
|
+
),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {Optional} from 'utility-types';
|
|
9
|
+
import type {
|
|
10
|
+
DocMetadataBase,
|
|
11
|
+
VersionMetadata,
|
|
12
|
+
NumberPrefixParser,
|
|
13
|
+
SidebarOptions,
|
|
14
|
+
} from '../types';
|
|
15
|
+
|
|
16
|
+
// Makes all properties visible when hovering over the type
|
|
17
|
+
type Expand<T extends Record<string, unknown>> = {[P in keyof T]: T[P]};
|
|
18
|
+
|
|
19
|
+
export type SidebarItemBase = {
|
|
20
|
+
className?: string;
|
|
21
|
+
customProps?: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type SidebarItemDoc = SidebarItemBase & {
|
|
25
|
+
type: 'doc' | 'ref';
|
|
26
|
+
label?: string;
|
|
27
|
+
id: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type SidebarItemLink = SidebarItemBase & {
|
|
31
|
+
type: 'link';
|
|
32
|
+
href: string;
|
|
33
|
+
label: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type SidebarItemAutogenerated = SidebarItemBase & {
|
|
37
|
+
type: 'autogenerated';
|
|
38
|
+
dirName: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
type SidebarItemCategoryBase = SidebarItemBase & {
|
|
42
|
+
type: 'category';
|
|
43
|
+
label: string;
|
|
44
|
+
collapsed: boolean;
|
|
45
|
+
collapsible: boolean;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// The user-given configuration in sidebars.js, before normalization
|
|
49
|
+
export type SidebarItemCategoryConfig = Expand<
|
|
50
|
+
Optional<SidebarItemCategoryBase, 'collapsed' | 'collapsible'> & {
|
|
51
|
+
items: SidebarItemConfig[];
|
|
52
|
+
}
|
|
53
|
+
>;
|
|
54
|
+
|
|
55
|
+
export type SidebarCategoriesShorthand = {
|
|
56
|
+
[sidebarCategory: string]: SidebarItemConfig[];
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export function isCategoriesShorthand(
|
|
60
|
+
item: SidebarItemConfig,
|
|
61
|
+
): item is SidebarCategoriesShorthand {
|
|
62
|
+
return typeof item !== 'string' && !item.type;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type SidebarItemConfig =
|
|
66
|
+
| SidebarItemDoc
|
|
67
|
+
| SidebarItemLink
|
|
68
|
+
| SidebarItemAutogenerated
|
|
69
|
+
| SidebarItemCategoryConfig
|
|
70
|
+
| string
|
|
71
|
+
| SidebarCategoriesShorthand;
|
|
72
|
+
|
|
73
|
+
export type SidebarConfig = SidebarCategoriesShorthand | SidebarItemConfig[];
|
|
74
|
+
export type SidebarsConfig = {
|
|
75
|
+
[sidebarId: string]: SidebarConfig;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Normalized but still has 'autogenerated', which will be handled in processing
|
|
79
|
+
export type NormalizedSidebarItemCategory = Expand<
|
|
80
|
+
SidebarItemCategoryBase & {
|
|
81
|
+
items: NormalizedSidebarItem[];
|
|
82
|
+
}
|
|
83
|
+
>;
|
|
84
|
+
|
|
85
|
+
export type NormalizedSidebarItem =
|
|
86
|
+
| SidebarItemDoc
|
|
87
|
+
| SidebarItemLink
|
|
88
|
+
| NormalizedSidebarItemCategory
|
|
89
|
+
| SidebarItemAutogenerated;
|
|
90
|
+
|
|
91
|
+
export type NormalizedSidebar = NormalizedSidebarItem[];
|
|
92
|
+
export type NormalizedSidebars = {
|
|
93
|
+
[sidebarId: string]: NormalizedSidebar;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type SidebarItemCategory = Expand<
|
|
97
|
+
SidebarItemCategoryBase & {
|
|
98
|
+
items: SidebarItem[];
|
|
99
|
+
}
|
|
100
|
+
>;
|
|
101
|
+
|
|
102
|
+
export type SidebarItem =
|
|
103
|
+
| SidebarItemDoc
|
|
104
|
+
| SidebarItemLink
|
|
105
|
+
| SidebarItemCategory;
|
|
106
|
+
|
|
107
|
+
export type Sidebar = SidebarItem[];
|
|
108
|
+
export type SidebarItemType = SidebarItem['type'];
|
|
109
|
+
export type Sidebars = {
|
|
110
|
+
[sidebarId: string]: Sidebar;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// Doc links have been resolved to URLs, ready to be passed to the theme
|
|
114
|
+
export type PropSidebarItemCategory = Expand<
|
|
115
|
+
SidebarItemCategoryBase & {
|
|
116
|
+
items: PropSidebarItem[];
|
|
117
|
+
}
|
|
118
|
+
>;
|
|
119
|
+
|
|
120
|
+
export type PropSidebarItem = SidebarItemLink | PropSidebarItemCategory;
|
|
121
|
+
export type PropSidebar = PropSidebarItem[];
|
|
122
|
+
export type PropSidebars = {
|
|
123
|
+
[sidebarId: string]: PropSidebar;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Reduce API surface for options.sidebarItemsGenerator
|
|
127
|
+
// The user-provided generator fn should receive only a subset of metadatas
|
|
128
|
+
// A change to any of these metadatas can be considered as a breaking change
|
|
129
|
+
export type SidebarItemsGeneratorDoc = Pick<
|
|
130
|
+
DocMetadataBase,
|
|
131
|
+
'id' | 'frontMatter' | 'source' | 'sourceDirName' | 'sidebarPosition'
|
|
132
|
+
>;
|
|
133
|
+
export type SidebarItemsGeneratorVersion = Pick<
|
|
134
|
+
VersionMetadata,
|
|
135
|
+
'versionName' | 'contentPath'
|
|
136
|
+
>;
|
|
137
|
+
|
|
138
|
+
export type SidebarItemsGeneratorArgs = {
|
|
139
|
+
item: SidebarItemAutogenerated;
|
|
140
|
+
version: SidebarItemsGeneratorVersion;
|
|
141
|
+
docs: SidebarItemsGeneratorDoc[];
|
|
142
|
+
numberPrefixParser: NumberPrefixParser;
|
|
143
|
+
options: SidebarOptions;
|
|
144
|
+
};
|
|
145
|
+
export type SidebarItemsGenerator = (
|
|
146
|
+
generatorArgs: SidebarItemsGeneratorArgs,
|
|
147
|
+
) => Promise<SidebarItem[]>;
|
|
148
|
+
|
|
149
|
+
// Also inject the default generator to conveniently wrap/enhance/sort the default sidebar gen logic
|
|
150
|
+
// see https://github.com/facebook/docusaurus/issues/4640#issuecomment-822292320
|
|
151
|
+
export type SidebarItemsGeneratorOptionArgs = {
|
|
152
|
+
defaultSidebarItemsGenerator: SidebarItemsGenerator;
|
|
153
|
+
} & SidebarItemsGeneratorArgs;
|
|
154
|
+
export type SidebarItemsGeneratorOption = (
|
|
155
|
+
generatorArgs: SidebarItemsGeneratorOptionArgs,
|
|
156
|
+
) => Promise<SidebarItem[]>;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
Sidebars,
|
|
10
|
+
Sidebar,
|
|
11
|
+
SidebarItem,
|
|
12
|
+
SidebarItemCategory,
|
|
13
|
+
SidebarItemLink,
|
|
14
|
+
SidebarItemDoc,
|
|
15
|
+
SidebarItemType,
|
|
16
|
+
} from './types';
|
|
17
|
+
import {mapValues, difference} from 'lodash';
|
|
18
|
+
import {getElementsAround, toMessageRelativeFilePath} from '@docusaurus/utils';
|
|
19
|
+
|
|
20
|
+
export function transformSidebarItems(
|
|
21
|
+
sidebar: Sidebar,
|
|
22
|
+
updateFn: (item: SidebarItem) => SidebarItem,
|
|
23
|
+
): Sidebar {
|
|
24
|
+
function transformRecursive(item: SidebarItem): SidebarItem {
|
|
25
|
+
if (item.type === 'category') {
|
|
26
|
+
return updateFn({
|
|
27
|
+
...item,
|
|
28
|
+
items: item.items.map(transformRecursive),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return updateFn(item);
|
|
32
|
+
}
|
|
33
|
+
return sidebar.map(transformRecursive);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function collectSidebarItemsOfType<
|
|
37
|
+
Type extends SidebarItemType,
|
|
38
|
+
Item extends SidebarItem & {type: SidebarItemType},
|
|
39
|
+
>(type: Type, sidebar: Sidebar): Item[] {
|
|
40
|
+
function collectRecursive(item: SidebarItem): Item[] {
|
|
41
|
+
const currentItemsCollected: Item[] =
|
|
42
|
+
item.type === type ? [item as Item] : [];
|
|
43
|
+
|
|
44
|
+
const childItemsCollected: Item[] =
|
|
45
|
+
item.type === 'category' ? item.items.flatMap(collectRecursive) : [];
|
|
46
|
+
|
|
47
|
+
return [...currentItemsCollected, ...childItemsCollected];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return sidebar.flatMap(collectRecursive);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function collectSidebarDocItems(sidebar: Sidebar): SidebarItemDoc[] {
|
|
54
|
+
return collectSidebarItemsOfType('doc', sidebar);
|
|
55
|
+
}
|
|
56
|
+
export function collectSidebarCategories(
|
|
57
|
+
sidebar: Sidebar,
|
|
58
|
+
): SidebarItemCategory[] {
|
|
59
|
+
return collectSidebarItemsOfType('category', sidebar);
|
|
60
|
+
}
|
|
61
|
+
export function collectSidebarLinks(sidebar: Sidebar): SidebarItemLink[] {
|
|
62
|
+
return collectSidebarItemsOfType('link', sidebar);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function collectSidebarsDocIds(
|
|
66
|
+
sidebars: Sidebars,
|
|
67
|
+
): Record<string, string[]> {
|
|
68
|
+
return mapValues(sidebars, (sidebar) => {
|
|
69
|
+
return collectSidebarDocItems(sidebar).map((docItem) => docItem.id);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function createSidebarsUtils(sidebars: Sidebars): {
|
|
74
|
+
getFirstDocIdOfFirstSidebar: () => string | undefined;
|
|
75
|
+
getSidebarNameByDocId: (docId: string) => string | undefined;
|
|
76
|
+
getDocNavigation: (docId: string) => {
|
|
77
|
+
sidebarName: string | undefined;
|
|
78
|
+
previousId: string | undefined;
|
|
79
|
+
nextId: string | undefined;
|
|
80
|
+
};
|
|
81
|
+
checkSidebarsDocIds: (validDocIds: string[], sidebarFilePath: string) => void;
|
|
82
|
+
} {
|
|
83
|
+
const sidebarNameToDocIds = collectSidebarsDocIds(sidebars);
|
|
84
|
+
// Reverse mapping
|
|
85
|
+
const docIdToSidebarName = Object.fromEntries(
|
|
86
|
+
Object.entries(sidebarNameToDocIds).flatMap(([sidebarName, docIds]) =>
|
|
87
|
+
docIds.map((docId) => [docId, sidebarName]),
|
|
88
|
+
),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
function getFirstDocIdOfFirstSidebar(): string | undefined {
|
|
92
|
+
return Object.values(sidebarNameToDocIds)[0]?.[0];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getSidebarNameByDocId(docId: string): string | undefined {
|
|
96
|
+
return docIdToSidebarName[docId];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function getDocNavigation(docId: string): {
|
|
100
|
+
sidebarName: string | undefined;
|
|
101
|
+
previousId: string | undefined;
|
|
102
|
+
nextId: string | undefined;
|
|
103
|
+
} {
|
|
104
|
+
const sidebarName = getSidebarNameByDocId(docId);
|
|
105
|
+
if (sidebarName) {
|
|
106
|
+
const docIds = sidebarNameToDocIds[sidebarName];
|
|
107
|
+
const currentIndex = docIds.indexOf(docId);
|
|
108
|
+
const {previous, next} = getElementsAround(docIds, currentIndex);
|
|
109
|
+
return {
|
|
110
|
+
sidebarName,
|
|
111
|
+
previousId: previous,
|
|
112
|
+
nextId: next,
|
|
113
|
+
};
|
|
114
|
+
} else {
|
|
115
|
+
return {
|
|
116
|
+
sidebarName: undefined,
|
|
117
|
+
previousId: undefined,
|
|
118
|
+
nextId: undefined,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function checkSidebarsDocIds(validDocIds: string[], sidebarFilePath: string) {
|
|
124
|
+
const allSidebarDocIds = Object.values(sidebarNameToDocIds).flat();
|
|
125
|
+
const invalidSidebarDocIds = difference(allSidebarDocIds, validDocIds);
|
|
126
|
+
if (invalidSidebarDocIds.length > 0) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Invalid sidebar file at "${toMessageRelativeFilePath(
|
|
129
|
+
sidebarFilePath,
|
|
130
|
+
)}".
|
|
131
|
+
These sidebar document ids do not exist:
|
|
132
|
+
- ${invalidSidebarDocIds.sort().join('\n- ')}
|
|
133
|
+
|
|
134
|
+
Available document ids are:
|
|
135
|
+
- ${validDocIds.sort().join('\n- ')}`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
getFirstDocIdOfFirstSidebar,
|
|
142
|
+
getSidebarNameByDocId,
|
|
143
|
+
getDocNavigation,
|
|
144
|
+
checkSidebarsDocIds,
|
|
145
|
+
};
|
|
146
|
+
}
|