@docusaurus/plugin-content-docs 2.0.0-beta.17 → 2.0.0-beta.18
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/categoryGeneratedIndex.js +0 -3
- package/lib/cli.js +3 -5
- package/lib/client/docsClientUtils.d.ts +3 -1
- package/lib/client/docsClientUtils.js +3 -3
- package/lib/client/index.d.ts +3 -1
- package/lib/docs.d.ts +4 -13
- package/lib/docs.js +7 -15
- package/lib/{docFrontMatter.d.ts → frontMatter.d.ts} +3 -1
- package/lib/{docFrontMatter.js → frontMatter.js} +0 -0
- package/lib/globalData.d.ts +2 -6
- package/lib/globalData.js +4 -8
- package/lib/lastUpdate.d.ts +4 -6
- package/lib/lastUpdate.js +13 -4
- package/lib/markdown/index.js +1 -1
- package/lib/markdown/linkify.js +4 -0
- package/lib/numberPrefix.js +16 -21
- package/lib/options.d.ts +3 -5
- package/lib/options.js +4 -3
- package/lib/sidebars/generator.js +33 -17
- package/lib/sidebars/index.js +13 -7
- package/lib/sidebars/postProcessor.js +11 -16
- package/lib/sidebars/processor.d.ts +3 -1
- package/lib/sidebars/processor.js +2 -2
- package/lib/sidebars/types.d.ts +13 -5
- package/lib/sidebars/utils.d.ts +15 -4
- package/lib/sidebars/utils.js +19 -23
- package/lib/sidebars/validation.d.ts +3 -1
- package/lib/sidebars/validation.js +1 -0
- package/lib/slug.js +3 -4
- package/lib/translations.js +19 -21
- package/lib/types.d.ts +9 -6
- package/lib/versions.js +3 -3
- package/package.json +10 -10
- package/src/categoryGeneratedIndex.ts +2 -6
- package/src/cli.ts +3 -5
- package/src/client/docsClientUtils.ts +3 -3
- package/src/client/index.ts +1 -1
- package/src/deps.d.ts +1 -1
- package/src/docs.ts +7 -25
- package/src/{docFrontMatter.ts → frontMatter.ts} +4 -4
- package/src/globalData.ts +5 -6
- package/src/index.ts +1 -2
- package/src/lastUpdate.ts +20 -8
- package/src/markdown/index.ts +1 -3
- package/src/markdown/linkify.ts +4 -0
- package/src/numberPrefix.ts +18 -28
- package/src/options.ts +6 -8
- package/src/plugin-content-docs.d.ts +12 -5
- package/src/sidebars/generator.ts +45 -22
- package/src/sidebars/index.ts +20 -13
- package/src/sidebars/postProcessor.ts +4 -9
- package/src/sidebars/processor.ts +4 -10
- package/src/sidebars/types.ts +5 -4
- package/src/sidebars/utils.ts +39 -43
- package/src/sidebars/validation.ts +4 -3
- package/src/slug.ts +3 -4
- package/src/translations.ts +24 -25
- package/src/types.ts +8 -7
- package/src/versions.ts +5 -5
package/src/lastUpdate.ts
CHANGED
|
@@ -6,15 +6,18 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import logger from '@docusaurus/logger';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import {
|
|
10
|
+
getFileCommitDate,
|
|
11
|
+
FileNotTrackedError,
|
|
12
|
+
GitNotFoundError,
|
|
13
|
+
} from '@docusaurus/utils';
|
|
12
14
|
|
|
13
15
|
let showedGitRequirementError = false;
|
|
16
|
+
let showedFileNotTrackedError = false;
|
|
14
17
|
|
|
15
18
|
export async function getFileLastUpdate(
|
|
16
19
|
filePath?: string,
|
|
17
|
-
): Promise<
|
|
20
|
+
): Promise<{timestamp: number; author: string} | null> {
|
|
18
21
|
if (!filePath) {
|
|
19
22
|
return null;
|
|
20
23
|
}
|
|
@@ -28,11 +31,20 @@ export async function getFileLastUpdate(
|
|
|
28
31
|
});
|
|
29
32
|
return {timestamp: result.timestamp, author: result.author};
|
|
30
33
|
} catch (err) {
|
|
31
|
-
if (err instanceof GitNotFoundError
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
if (err instanceof GitNotFoundError) {
|
|
35
|
+
if (!showedGitRequirementError) {
|
|
36
|
+
logger.warn('Sorry, the docs plugin last update options require Git.');
|
|
37
|
+
showedGitRequirementError = true;
|
|
38
|
+
}
|
|
39
|
+
} else if (err instanceof FileNotTrackedError) {
|
|
40
|
+
if (!showedFileNotTrackedError) {
|
|
41
|
+
logger.warn(
|
|
42
|
+
'Cannot infer the update date for some files, as they are not tracked by git.',
|
|
43
|
+
);
|
|
44
|
+
showedFileNotTrackedError = true;
|
|
45
|
+
}
|
|
34
46
|
} else {
|
|
35
|
-
logger.
|
|
47
|
+
logger.warn(err);
|
|
36
48
|
}
|
|
37
49
|
return null;
|
|
38
50
|
}
|
package/src/markdown/index.ts
CHANGED
|
@@ -16,7 +16,5 @@ export default function markdownLoader(
|
|
|
16
16
|
const fileString = source;
|
|
17
17
|
const callback = this.async();
|
|
18
18
|
const options = this.getOptions();
|
|
19
|
-
return (
|
|
20
|
-
callback && callback(null, linkify(fileString, this.resourcePath, options))
|
|
21
|
-
);
|
|
19
|
+
return callback?.(null, linkify(fileString, this.resourcePath, options));
|
|
22
20
|
}
|
package/src/markdown/linkify.ts
CHANGED
|
@@ -15,6 +15,10 @@ function getVersion(filePath: string, options: DocsMarkdownOption) {
|
|
|
15
15
|
filePath.startsWith(docsDirPath),
|
|
16
16
|
),
|
|
17
17
|
);
|
|
18
|
+
// At this point, this should never happen, because the MDX loaders' paths are
|
|
19
|
+
// literally using the version content paths; but if we allow sourcing content
|
|
20
|
+
// from outside the docs directory (through the `include` option, for example;
|
|
21
|
+
// is there a compelling use-case?), this would actually be testable
|
|
18
22
|
if (!versionFound) {
|
|
19
23
|
throw new Error(
|
|
20
24
|
`Unexpected error: Markdown file at "${filePath}" does not belong to any docs version!`,
|
package/src/numberPrefix.ts
CHANGED
|
@@ -8,43 +8,33 @@
|
|
|
8
8
|
import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs';
|
|
9
9
|
|
|
10
10
|
// Best-effort to avoid parsing some patterns as number prefix
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return new RegExp(
|
|
24
|
-
`${DateLikePrefixRegex.source}|${VersionLikePrefixRegex.source}`,
|
|
25
|
-
);
|
|
26
|
-
})();
|
|
27
|
-
|
|
28
|
-
const NumberPrefixRegex =
|
|
29
|
-
/^(?<numberPrefix>\d+)(?<separator>\s*[-_.]+\s*)(?<suffix>.*)$/;
|
|
11
|
+
// ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
|
|
12
|
+
// ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
|
|
13
|
+
// Both of them would look like 7.0-foo or 2021-11-foo
|
|
14
|
+
// note: we could try to parse float numbers in filenames, but that is probably
|
|
15
|
+
// not worth it, as a version such as "8.0" can be interpreted as either a
|
|
16
|
+
// version or a float. User can configure her own NumberPrefixParser if she
|
|
17
|
+
// wants 8.0 to be interpreted as a float
|
|
18
|
+
const ignoredPrefixPattern = /^\d+[-_.]\d+/;
|
|
19
|
+
|
|
20
|
+
const numberPrefixPattern =
|
|
21
|
+
/^(?<numberPrefix>\d+)\s*[-_.]+\s*(?<suffix>[^-_.\s].*)$/;
|
|
30
22
|
|
|
31
23
|
// 0-myDoc => {filename: myDoc, numberPrefix: 0}
|
|
32
24
|
// 003 - myDoc => {filename: myDoc, numberPrefix: 3}
|
|
33
25
|
export const DefaultNumberPrefixParser: NumberPrefixParser = (
|
|
34
26
|
filename: string,
|
|
35
27
|
) => {
|
|
36
|
-
if (
|
|
28
|
+
if (ignoredPrefixPattern.test(filename)) {
|
|
29
|
+
return {filename, numberPrefix: undefined};
|
|
30
|
+
}
|
|
31
|
+
const match = numberPrefixPattern.exec(filename);
|
|
32
|
+
if (!match) {
|
|
37
33
|
return {filename, numberPrefix: undefined};
|
|
38
34
|
}
|
|
39
|
-
const match = NumberPrefixRegex.exec(filename);
|
|
40
|
-
const cleanFileName = match?.groups?.suffix ?? filename;
|
|
41
|
-
const numberPrefixString = match?.groups?.numberPrefix;
|
|
42
|
-
const numberPrefix = numberPrefixString
|
|
43
|
-
? parseInt(numberPrefixString, 10)
|
|
44
|
-
: undefined;
|
|
45
35
|
return {
|
|
46
|
-
filename:
|
|
47
|
-
numberPrefix,
|
|
36
|
+
filename: match.groups!.suffix!,
|
|
37
|
+
numberPrefix: parseInt(match.groups!.numberPrefix!, 10),
|
|
48
38
|
};
|
|
49
39
|
};
|
|
50
40
|
|
package/src/options.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {PluginOptions} from '@docusaurus/plugin-content-docs';
|
|
8
|
+
import type {PluginOptions, Options} from '@docusaurus/plugin-content-docs';
|
|
9
9
|
import {
|
|
10
10
|
Joi,
|
|
11
11
|
RemarkPluginsSchema,
|
|
@@ -15,10 +15,7 @@ import {
|
|
|
15
15
|
} from '@docusaurus/utils-validation';
|
|
16
16
|
import {GlobExcludeDefault} from '@docusaurus/utils';
|
|
17
17
|
|
|
18
|
-
import type {
|
|
19
|
-
OptionValidationContext,
|
|
20
|
-
ValidationResult,
|
|
21
|
-
} from '@docusaurus/types';
|
|
18
|
+
import type {OptionValidationContext} from '@docusaurus/types';
|
|
22
19
|
import logger from '@docusaurus/logger';
|
|
23
20
|
import admonitions from 'remark-admonitions';
|
|
24
21
|
import {DefaultSidebarItemsGenerator} from './sidebars/generator';
|
|
@@ -70,7 +67,7 @@ const VersionsOptionsSchema = Joi.object()
|
|
|
70
67
|
.pattern(Joi.string().required(), VersionOptionsSchema)
|
|
71
68
|
.default(DEFAULT_OPTIONS.versions);
|
|
72
69
|
|
|
73
|
-
|
|
70
|
+
const OptionsSchema = Joi.object<PluginOptions>({
|
|
74
71
|
path: Joi.string().default(DEFAULT_OPTIONS.path),
|
|
75
72
|
editUrl: Joi.alternatives().try(URISchema, Joi.function()),
|
|
76
73
|
editCurrentVersion: Joi.boolean().default(DEFAULT_OPTIONS.editCurrentVersion),
|
|
@@ -80,6 +77,7 @@ export const OptionsSchema = Joi.object({
|
|
|
80
77
|
// .allow('') ""
|
|
81
78
|
.default(DEFAULT_OPTIONS.routeBasePath),
|
|
82
79
|
tagsBasePath: Joi.string().default(DEFAULT_OPTIONS.tagsBasePath),
|
|
80
|
+
// @ts-expect-error: deprecated
|
|
83
81
|
homePageId: Joi.any().forbidden().messages({
|
|
84
82
|
'any.unknown':
|
|
85
83
|
'The docs plugin option homePageId is not supported anymore. To make a doc the "home", please add "slug: /" in its front matter. See: https://docusaurus.io/docs/next/docs-introduction#home-page-docs',
|
|
@@ -146,7 +144,7 @@ export const OptionsSchema = Joi.object({
|
|
|
146
144
|
export function validateOptions({
|
|
147
145
|
validate,
|
|
148
146
|
options: userOptions,
|
|
149
|
-
}: OptionValidationContext<PluginOptions>):
|
|
147
|
+
}: OptionValidationContext<Options, PluginOptions>): PluginOptions {
|
|
150
148
|
let options = userOptions;
|
|
151
149
|
|
|
152
150
|
if (options.sidebarCollapsible === false) {
|
|
@@ -168,7 +166,7 @@ export function validateOptions({
|
|
|
168
166
|
}
|
|
169
167
|
}
|
|
170
168
|
|
|
171
|
-
const normalizedOptions = validate(OptionsSchema, options);
|
|
169
|
+
const normalizedOptions = validate(OptionsSchema, options) as PluginOptions;
|
|
172
170
|
|
|
173
171
|
if (normalizedOptions.admonitions) {
|
|
174
172
|
normalizedOptions.remarkPlugins = normalizedOptions.remarkPlugins.concat([
|
|
@@ -18,8 +18,14 @@ declare module '@docusaurus/plugin-content-docs' {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export type CategoryIndexMatcherParam = {
|
|
21
|
+
/** The file name, without extension */
|
|
21
22
|
fileName: string;
|
|
23
|
+
/**
|
|
24
|
+
* The list of directories, from lowest level to highest.
|
|
25
|
+
* If there's no dir name, directories is ['.']
|
|
26
|
+
*/
|
|
22
27
|
directories: string[];
|
|
28
|
+
/** The extension, with a leading dot */
|
|
23
29
|
extension: string;
|
|
24
30
|
};
|
|
25
31
|
export type CategoryIndexMatcher = (
|
|
@@ -62,7 +68,7 @@ declare module '@docusaurus/plugin-content-docs' {
|
|
|
62
68
|
};
|
|
63
69
|
export type VersionsOptions = {
|
|
64
70
|
lastVersion?: string;
|
|
65
|
-
versions:
|
|
71
|
+
versions: {[versionName: string]: VersionOptions};
|
|
66
72
|
onlyIncludeVersions?: string[];
|
|
67
73
|
};
|
|
68
74
|
export type SidebarOptions = {
|
|
@@ -83,7 +89,7 @@ declare module '@docusaurus/plugin-content-docs' {
|
|
|
83
89
|
docTagDocListComponent: string;
|
|
84
90
|
docTagsListComponent: string;
|
|
85
91
|
docCategoryGeneratedIndexComponent: string;
|
|
86
|
-
admonitions:
|
|
92
|
+
admonitions: {[key: string]: unknown};
|
|
87
93
|
disableVersioning: boolean;
|
|
88
94
|
includeCurrentVersion: boolean;
|
|
89
95
|
sidebarItemsGenerator: import('./sidebars/types').SidebarItemsGeneratorOption;
|
|
@@ -185,6 +191,7 @@ declare module '@theme/DocItem' {
|
|
|
185
191
|
};
|
|
186
192
|
|
|
187
193
|
export type Metadata = {
|
|
194
|
+
readonly unversionedId?: string;
|
|
188
195
|
readonly description?: string;
|
|
189
196
|
readonly title?: string;
|
|
190
197
|
readonly permalink?: string;
|
|
@@ -275,7 +282,7 @@ declare module '@docusaurus/plugin-content-docs/client' {
|
|
|
275
282
|
export type ActiveDocContext = {
|
|
276
283
|
activeVersion?: GlobalVersion;
|
|
277
284
|
activeDoc?: GlobalDoc;
|
|
278
|
-
alternateDocVersions:
|
|
285
|
+
alternateDocVersions: {[versionName: string]: GlobalDoc};
|
|
279
286
|
};
|
|
280
287
|
export type GlobalDoc = {
|
|
281
288
|
id: string;
|
|
@@ -290,7 +297,7 @@ declare module '@docusaurus/plugin-content-docs/client' {
|
|
|
290
297
|
path: string;
|
|
291
298
|
mainDocId: string; // home doc (if docs homepage configured), or first doc
|
|
292
299
|
docs: GlobalDoc[];
|
|
293
|
-
sidebars?:
|
|
300
|
+
sidebars?: {[sidebarId: string]: GlobalSidebar};
|
|
294
301
|
};
|
|
295
302
|
|
|
296
303
|
export type GlobalSidebarLink = {
|
|
@@ -315,7 +322,7 @@ declare module '@docusaurus/plugin-content-docs/client' {
|
|
|
315
322
|
};
|
|
316
323
|
export type GetActivePluginOptions = {failfast?: boolean}; // use fail-fast option if you know for sure one plugin instance is active
|
|
317
324
|
|
|
318
|
-
export const useAllDocsData: () =>
|
|
325
|
+
export const useAllDocsData: () => {[pluginId: string]: GlobalPluginData};
|
|
319
326
|
export const useDocsData: (pluginId?: string) => GlobalPluginData;
|
|
320
327
|
export const useActivePlugin: (
|
|
321
328
|
options?: GetActivePluginOptions,
|
|
@@ -60,9 +60,9 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
60
60
|
const doc = findDoc(docId);
|
|
61
61
|
if (!doc) {
|
|
62
62
|
throw new Error(
|
|
63
|
-
`Can't find any doc with
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
`Can't find any doc with ID ${docId}.
|
|
64
|
+
Available doc IDs:
|
|
65
|
+
- ${Object.keys(docsById).join('\n- ')}`,
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
return doc;
|
|
@@ -158,8 +158,6 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
158
158
|
): WithPosition<NormalizedSidebarItemCategory> {
|
|
159
159
|
const categoryMetadata =
|
|
160
160
|
categoriesMetadata[posixPath(path.join(autogenDir, fullPath))];
|
|
161
|
-
const className = categoryMetadata?.className;
|
|
162
|
-
const {filename, numberPrefix} = numberPrefixParser(folderName);
|
|
163
161
|
const allItems = Object.entries(dir).map(([key, content]) =>
|
|
164
162
|
dirToItem(content, key, `${fullPath}/${key}`),
|
|
165
163
|
);
|
|
@@ -183,42 +181,67 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
183
181
|
});
|
|
184
182
|
}
|
|
185
183
|
|
|
186
|
-
function
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
184
|
+
// In addition to the ID, this function also retrieves metadata of the
|
|
185
|
+
// linked doc that could be used as fallback values for category metadata
|
|
186
|
+
function getCategoryLinkedDocMetadata():
|
|
187
|
+
| {
|
|
188
|
+
id: string;
|
|
189
|
+
position?: number;
|
|
190
|
+
label?: string;
|
|
191
|
+
customProps?: {[key: string]: unknown};
|
|
192
|
+
className?: string;
|
|
191
193
|
}
|
|
194
|
+
| undefined {
|
|
195
|
+
const link = categoryMetadata?.link;
|
|
196
|
+
if (link !== undefined && link?.type !== 'doc') {
|
|
192
197
|
// If a link is explicitly specified, we won't apply conventions
|
|
193
198
|
return undefined;
|
|
194
199
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
200
|
+
const id = link
|
|
201
|
+
? findDocByLocalId(link.id)?.id ?? getDoc(link.id).id
|
|
202
|
+
: findConventionalCategoryDocLink()?.id;
|
|
203
|
+
if (!id) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
const doc = getDoc(id);
|
|
207
|
+
return {
|
|
208
|
+
id,
|
|
209
|
+
position: doc.sidebarPosition,
|
|
210
|
+
label: doc.frontMatter.sidebar_label ?? doc.title,
|
|
211
|
+
customProps: doc.frontMatter.sidebar_custom_props,
|
|
212
|
+
className: doc.frontMatter.sidebar_class_name,
|
|
213
|
+
};
|
|
198
214
|
}
|
|
199
|
-
|
|
200
|
-
const categoryLinkedDocId = getCategoryLinkedDocId();
|
|
201
|
-
|
|
215
|
+
const categoryLinkedDoc = getCategoryLinkedDocMetadata();
|
|
202
216
|
const link: SidebarItemCategoryLinkConfig | null | undefined =
|
|
203
|
-
|
|
217
|
+
categoryLinkedDoc
|
|
204
218
|
? {
|
|
205
219
|
type: 'doc',
|
|
206
|
-
id:
|
|
220
|
+
id: categoryLinkedDoc.id, // We "remap" a potentially "local id" to a "qualified id"
|
|
207
221
|
}
|
|
208
222
|
: categoryMetadata?.link;
|
|
209
|
-
|
|
210
223
|
// If a doc is linked, remove it from the category subItems
|
|
211
224
|
const items = allItems.filter(
|
|
212
|
-
(item) => !(item.type === 'doc' && item.id ===
|
|
225
|
+
(item) => !(item.type === 'doc' && item.id === categoryLinkedDoc?.id),
|
|
213
226
|
);
|
|
214
227
|
|
|
228
|
+
const className =
|
|
229
|
+
categoryMetadata?.className ?? categoryLinkedDoc?.className;
|
|
230
|
+
const customProps =
|
|
231
|
+
categoryMetadata?.customProps ?? categoryLinkedDoc?.customProps;
|
|
232
|
+
const {filename, numberPrefix} = numberPrefixParser(folderName);
|
|
233
|
+
|
|
215
234
|
return {
|
|
216
235
|
type: 'category',
|
|
217
|
-
label: categoryMetadata?.label ?? filename,
|
|
236
|
+
label: categoryMetadata?.label ?? categoryLinkedDoc?.label ?? filename,
|
|
218
237
|
collapsible: categoryMetadata?.collapsible,
|
|
219
238
|
collapsed: categoryMetadata?.collapsed,
|
|
220
|
-
position:
|
|
239
|
+
position:
|
|
240
|
+
categoryMetadata?.position ??
|
|
241
|
+
categoryLinkedDoc?.position ??
|
|
242
|
+
numberPrefix,
|
|
221
243
|
source: folderName,
|
|
244
|
+
...(customProps !== undefined && {customProps}),
|
|
222
245
|
...(className !== undefined && {className}),
|
|
223
246
|
items,
|
|
224
247
|
...(link && {link}),
|
package/src/sidebars/index.ts
CHANGED
|
@@ -49,7 +49,7 @@ async function readCategoriesMetadata(contentPath: string) {
|
|
|
49
49
|
const categoryToFile = _.groupBy(categoryFiles, path.dirname);
|
|
50
50
|
return combinePromises(
|
|
51
51
|
_.mapValues(categoryToFile, async (files, folder) => {
|
|
52
|
-
const
|
|
52
|
+
const filePath = files[0]!;
|
|
53
53
|
if (files.length > 1) {
|
|
54
54
|
logger.warn`There are more than one category metadata files for path=${folder}: ${files.join(
|
|
55
55
|
', ',
|
|
@@ -98,16 +98,23 @@ export async function loadSidebars(
|
|
|
98
98
|
sidebarFilePath: string | false | undefined,
|
|
99
99
|
options: SidebarProcessorParams,
|
|
100
100
|
): Promise<Sidebars> {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
101
|
+
try {
|
|
102
|
+
const sidebarsConfig = await loadSidebarsFileUnsafe(sidebarFilePath);
|
|
103
|
+
const normalizedSidebars = normalizeSidebars(sidebarsConfig);
|
|
104
|
+
validateSidebars(normalizedSidebars);
|
|
105
|
+
const categoriesMetadata = await readCategoriesMetadata(
|
|
106
|
+
options.version.contentPath,
|
|
107
|
+
);
|
|
108
|
+
const processedSidebars = await processSidebars(
|
|
109
|
+
normalizedSidebars,
|
|
110
|
+
categoriesMetadata,
|
|
111
|
+
options,
|
|
112
|
+
);
|
|
113
|
+
return postProcessSidebars(processedSidebars, options);
|
|
114
|
+
} catch (err) {
|
|
115
|
+
logger.error`Sidebars file at path=${
|
|
116
|
+
sidebarFilePath as string
|
|
117
|
+
} failed to be loaded.`;
|
|
118
|
+
throw err;
|
|
119
|
+
}
|
|
113
120
|
}
|
|
@@ -58,22 +58,17 @@ function postProcessSidebarItem(
|
|
|
58
58
|
`Sidebar category ${item.label} has neither any subitem nor a link. This makes this item not able to link to anything.`,
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return {
|
|
61
|
+
return category.link.type === 'doc'
|
|
62
|
+
? {
|
|
64
63
|
type: 'doc',
|
|
65
64
|
label: category.label,
|
|
66
65
|
id: category.link.id,
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return {
|
|
66
|
+
}
|
|
67
|
+
: {
|
|
70
68
|
type: 'link',
|
|
71
69
|
label: category.label,
|
|
72
70
|
href: category.link.permalink,
|
|
73
71
|
};
|
|
74
|
-
default:
|
|
75
|
-
throw new Error('Unexpected sidebar category link type');
|
|
76
|
-
}
|
|
77
72
|
}
|
|
78
73
|
// A non-collapsible category can't be collapsed!
|
|
79
74
|
if (category.collapsible === false) {
|
|
@@ -31,6 +31,7 @@ function toSidebarItemsGeneratorDoc(
|
|
|
31
31
|
return _.pick(doc, [
|
|
32
32
|
'id',
|
|
33
33
|
'unversionedId',
|
|
34
|
+
'title',
|
|
34
35
|
'frontMatter',
|
|
35
36
|
'source',
|
|
36
37
|
'sourceDirName',
|
|
@@ -48,16 +49,10 @@ function toSidebarItemsGeneratorVersion(
|
|
|
48
49
|
// post-processing checks
|
|
49
50
|
async function processSidebar(
|
|
50
51
|
unprocessedSidebar: NormalizedSidebar,
|
|
51
|
-
categoriesMetadata:
|
|
52
|
+
categoriesMetadata: {[filePath: string]: CategoryMetadataFile},
|
|
52
53
|
params: SidebarProcessorParams,
|
|
53
54
|
): Promise<ProcessedSidebar> {
|
|
54
|
-
const {
|
|
55
|
-
sidebarItemsGenerator,
|
|
56
|
-
numberPrefixParser,
|
|
57
|
-
docs,
|
|
58
|
-
version,
|
|
59
|
-
sidebarOptions,
|
|
60
|
-
} = params;
|
|
55
|
+
const {sidebarItemsGenerator, numberPrefixParser, docs, version} = params;
|
|
61
56
|
|
|
62
57
|
// Just a minor lazy transformation optimization
|
|
63
58
|
const getSidebarItemsGeneratorDocsAndVersion = _.memoize(() => ({
|
|
@@ -74,7 +69,6 @@ async function processSidebar(
|
|
|
74
69
|
defaultSidebarItemsGenerator: DefaultSidebarItemsGenerator,
|
|
75
70
|
isCategoryIndex,
|
|
76
71
|
...getSidebarItemsGeneratorDocsAndVersion(),
|
|
77
|
-
options: sidebarOptions,
|
|
78
72
|
categoriesMetadata,
|
|
79
73
|
});
|
|
80
74
|
// Process again... weird but sidebar item generated might generate some
|
|
@@ -113,7 +107,7 @@ async function processSidebar(
|
|
|
113
107
|
|
|
114
108
|
export async function processSidebars(
|
|
115
109
|
unprocessedSidebars: NormalizedSidebars,
|
|
116
|
-
categoriesMetadata:
|
|
110
|
+
categoriesMetadata: {[filePath: string]: CategoryMetadataFile},
|
|
117
111
|
params: SidebarProcessorParams,
|
|
118
112
|
): Promise<ProcessedSidebars> {
|
|
119
113
|
const processedSidebars = await combinePromises(
|
package/src/sidebars/types.ts
CHANGED
|
@@ -15,11 +15,11 @@ import type {
|
|
|
15
15
|
import type {Slugger} from '@docusaurus/utils';
|
|
16
16
|
|
|
17
17
|
// Makes all properties visible when hovering over the type
|
|
18
|
-
type Expand<T extends
|
|
18
|
+
type Expand<T extends {[x: string]: unknown}> = {[P in keyof T]: T[P]};
|
|
19
19
|
|
|
20
20
|
export type SidebarItemBase = {
|
|
21
21
|
className?: string;
|
|
22
|
-
customProps?:
|
|
22
|
+
customProps?: {[key: string]: unknown};
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
export type SidebarItemDoc = SidebarItemBase & {
|
|
@@ -216,6 +216,7 @@ export type CategoryMetadataFile = {
|
|
|
216
216
|
collapsible?: boolean;
|
|
217
217
|
className?: string;
|
|
218
218
|
link?: SidebarItemCategoryLinkConfig | null;
|
|
219
|
+
customProps?: {[key: string]: unknown};
|
|
219
220
|
|
|
220
221
|
// TODO should we allow "items" here? how would this work? would an
|
|
221
222
|
// "autogenerated" type be allowed?
|
|
@@ -230,6 +231,7 @@ export type SidebarItemsGeneratorDoc = Pick<
|
|
|
230
231
|
DocMetadataBase,
|
|
231
232
|
| 'id'
|
|
232
233
|
| 'unversionedId'
|
|
234
|
+
| 'title'
|
|
233
235
|
| 'frontMatter'
|
|
234
236
|
| 'source'
|
|
235
237
|
| 'sourceDirName'
|
|
@@ -246,8 +248,7 @@ export type SidebarItemsGeneratorArgs = {
|
|
|
246
248
|
docs: SidebarItemsGeneratorDoc[];
|
|
247
249
|
numberPrefixParser: NumberPrefixParser;
|
|
248
250
|
isCategoryIndex: CategoryIndexMatcher;
|
|
249
|
-
categoriesMetadata:
|
|
250
|
-
options: SidebarOptions;
|
|
251
|
+
categoriesMetadata: {[filePath: string]: CategoryMetadataFile};
|
|
251
252
|
};
|
|
252
253
|
export type SidebarItemsGenerator = (
|
|
253
254
|
generatorArgs: SidebarItemsGeneratorArgs,
|