@docusaurus/plugin-content-docs 0.0.0-4542 → 0.0.0-4547
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/sidebars/generator.d.ts +1 -9
- package/lib/sidebars/generator.js +2 -28
- package/lib/sidebars/index.d.ts +1 -1
- package/lib/sidebars/index.js +26 -1
- package/lib/sidebars/processor.d.ts +2 -1
- package/lib/sidebars/processor.js +2 -1
- package/lib/sidebars/types.d.ts +9 -0
- package/lib/sidebars/validation.d.ts +1 -2
- package/package.json +9 -9
- package/src/sidebars/generator.ts +4 -57
- package/src/sidebars/index.ts +38 -4
- package/src/sidebars/processor.ts +4 -0
- package/src/sidebars/types.ts +15 -0
- package/src/sidebars/validation.ts +1 -1
|
@@ -4,15 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import type { SidebarItemsGenerator
|
|
7
|
+
import type { SidebarItemsGenerator } from './types';
|
|
8
8
|
export declare const CategoryMetadataFilenameBase = "_category_";
|
|
9
9
|
export declare const CategoryMetadataFilenamePattern = "_category_.{json,yml,yaml}";
|
|
10
|
-
export declare type CategoryMetadataFile = {
|
|
11
|
-
label?: string;
|
|
12
|
-
position?: number;
|
|
13
|
-
collapsed?: boolean;
|
|
14
|
-
collapsible?: boolean;
|
|
15
|
-
className?: string;
|
|
16
|
-
link?: SidebarItemCategoryLinkConfig | null;
|
|
17
|
-
};
|
|
18
10
|
export declare const DefaultSidebarItemsGenerator: SidebarItemsGenerator;
|
|
@@ -12,9 +12,6 @@ const lodash_1 = require("lodash");
|
|
|
12
12
|
const utils_1 = require("@docusaurus/utils");
|
|
13
13
|
const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
|
|
14
14
|
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
15
|
-
const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
|
|
16
|
-
const js_yaml_1 = (0, tslib_1.__importDefault)(require("js-yaml"));
|
|
17
|
-
const validation_1 = require("./validation");
|
|
18
15
|
const docs_1 = require("../docs");
|
|
19
16
|
const BreadcrumbSeparator = '/';
|
|
20
17
|
// To avoid possible name clashes with a folder of the same name as the ID
|
|
@@ -25,30 +22,8 @@ function getLocalDocId(docId) {
|
|
|
25
22
|
}
|
|
26
23
|
exports.CategoryMetadataFilenameBase = '_category_';
|
|
27
24
|
exports.CategoryMetadataFilenamePattern = '_category_.{json,yml,yaml}';
|
|
28
|
-
// TODO I now believe we should read all the category metadata files ahead of
|
|
29
|
-
// time: we may need this metadata to customize docs metadata
|
|
30
|
-
// Example use-case being able to disable number prefix parsing at the folder
|
|
31
|
-
// level, or customize the default base slug for an intermediate directory
|
|
32
|
-
// TODO later if there is `CategoryFolder/with-category-name-doc.md`, we may
|
|
33
|
-
// want to read the metadata as yaml on it
|
|
34
|
-
// see https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
|
|
35
|
-
async function readCategoryMetadataFile(categoryDirPath) {
|
|
36
|
-
async function tryReadFile(filePath) {
|
|
37
|
-
const contentString = await fs_extra_1.default.readFile(filePath, { encoding: 'utf8' });
|
|
38
|
-
const unsafeContent = js_yaml_1.default.load(contentString);
|
|
39
|
-
try {
|
|
40
|
-
return (0, validation_1.validateCategoryMetadataFile)(unsafeContent);
|
|
41
|
-
}
|
|
42
|
-
catch (e) {
|
|
43
|
-
logger_1.default.error `The docs sidebar category metadata file path=${filePath} looks invalid!`;
|
|
44
|
-
throw e;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const filePath = await (0, utils_1.findAsyncSequential)(['.json', '.yml', '.yaml'].map((ext) => (0, utils_1.posixPath)(path_1.default.join(categoryDirPath, `${exports.CategoryMetadataFilenameBase}${ext}`))), fs_extra_1.default.pathExists);
|
|
48
|
-
return filePath ? tryReadFile(filePath) : null;
|
|
49
|
-
}
|
|
50
25
|
// Comment for this feature: https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
|
|
51
|
-
const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryIndex, docs: allDocs, options, item: { dirName: autogenDir },
|
|
26
|
+
const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryIndex, docs: allDocs, options, item: { dirName: autogenDir }, categoriesMetadata, }) => {
|
|
52
27
|
const docsById = (0, docs_1.createDocsByIdIndex)(allDocs);
|
|
53
28
|
const findDoc = (docId) => docsById[docId];
|
|
54
29
|
const getDoc = (docId) => {
|
|
@@ -127,8 +102,7 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
|
|
|
127
102
|
}
|
|
128
103
|
async function createCategoryItem(dir, fullPath, folderName) {
|
|
129
104
|
var _a, _b, _c, _d;
|
|
130
|
-
const
|
|
131
|
-
const categoryMetadata = await readCategoryMetadataFile(categoryPath);
|
|
105
|
+
const categoryMetadata = categoriesMetadata[(0, utils_1.posixPath)(path_1.default.join(autogenDir, fullPath))];
|
|
132
106
|
const className = categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.className;
|
|
133
107
|
const { filename, numberPrefix } = numberPrefixParser(folderName);
|
|
134
108
|
const allItems = await Promise.all(Object.entries(dir).map(([key, content]) => dirToItem(content, key, `${fullPath}/${key}`)));
|
package/lib/sidebars/index.d.ts
CHANGED
|
@@ -13,4 +13,4 @@ export declare const DisabledSidebars: SidebarsConfig;
|
|
|
13
13
|
export declare function resolveSidebarPathOption(siteDir: string, sidebarPathOption: PluginOptions['sidebarPath']): PluginOptions['sidebarPath'];
|
|
14
14
|
export declare function loadSidebarsFile(sidebarFilePath: string | false | undefined): Promise<SidebarsConfig>;
|
|
15
15
|
export declare function loadNormalizedSidebars(sidebarFilePath: string | false | undefined, params: NormalizeSidebarsParams): Promise<NormalizedSidebars>;
|
|
16
|
-
export declare function loadSidebars(sidebarFilePath: string | false | undefined, options: SidebarProcessorParams): Promise<Sidebars>;
|
|
16
|
+
export declare function loadSidebars(sidebarFilePath: string | false | undefined, options: Omit<SidebarProcessorParams, 'categoriesMetadata'>): Promise<Sidebars>;
|
package/lib/sidebars/index.js
CHANGED
|
@@ -15,6 +15,10 @@ const normalization_1 = require("./normalization");
|
|
|
15
15
|
const processor_1 = require("./processor");
|
|
16
16
|
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
17
17
|
const utils_1 = require("@docusaurus/utils");
|
|
18
|
+
const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
|
|
19
|
+
const js_yaml_1 = (0, tslib_1.__importDefault)(require("js-yaml"));
|
|
20
|
+
const lodash_1 = require("lodash");
|
|
21
|
+
const combine_promises_1 = (0, tslib_1.__importDefault)(require("combine-promises"));
|
|
18
22
|
exports.DefaultSidebars = {
|
|
19
23
|
defaultSidebar: [
|
|
20
24
|
{
|
|
@@ -32,6 +36,26 @@ function resolveSidebarPathOption(siteDir, sidebarPathOption) {
|
|
|
32
36
|
: sidebarPathOption;
|
|
33
37
|
}
|
|
34
38
|
exports.resolveSidebarPathOption = resolveSidebarPathOption;
|
|
39
|
+
async function readCategoriesMetadata(contentPath) {
|
|
40
|
+
const categoryFiles = await (0, utils_1.Globby)('**/_category_.{json,yml,yaml}', {
|
|
41
|
+
cwd: contentPath,
|
|
42
|
+
});
|
|
43
|
+
const categoryToFile = (0, lodash_1.groupBy)(categoryFiles, path_1.default.dirname);
|
|
44
|
+
return (0, combine_promises_1.default)((0, lodash_1.mapValues)(categoryToFile, async (files, folder) => {
|
|
45
|
+
const [filePath] = files;
|
|
46
|
+
if (files.length > 1) {
|
|
47
|
+
logger_1.default.warn `There are more than one category metadata files for path=${folder}: ${files.join(', ')}. The behavior is undetermined.`;
|
|
48
|
+
}
|
|
49
|
+
const content = await fs_extra_1.default.readFile(path_1.default.join(contentPath, filePath), 'utf-8');
|
|
50
|
+
try {
|
|
51
|
+
return (0, validation_1.validateCategoryMetadataFile)(js_yaml_1.default.load(content));
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
logger_1.default.error `The docs sidebar category metadata file path=${filePath} looks invalid!`;
|
|
55
|
+
throw e;
|
|
56
|
+
}
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
35
59
|
async function loadSidebarsFileUnsafe(sidebarFilePath) {
|
|
36
60
|
// false => no sidebars
|
|
37
61
|
if (sidebarFilePath === false) {
|
|
@@ -68,6 +92,7 @@ async function loadSidebars(sidebarFilePath, options) {
|
|
|
68
92
|
categoryLabelSlugger: (0, utils_1.createSlugger)(),
|
|
69
93
|
};
|
|
70
94
|
const normalizedSidebars = await loadNormalizedSidebars(sidebarFilePath, normalizeSidebarsParams);
|
|
71
|
-
|
|
95
|
+
const categoriesMetadata = await readCategoriesMetadata(options.version.contentPath);
|
|
96
|
+
return (0, processor_1.processSidebars)(normalizedSidebars, { ...options, categoriesMetadata });
|
|
72
97
|
}
|
|
73
98
|
exports.loadSidebars = loadSidebars;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { DocMetadataBase, VersionMetadata } from '../types';
|
|
8
|
-
import type { Sidebars, NormalizedSidebars, SidebarItemsGeneratorOption } from './types';
|
|
8
|
+
import type { Sidebars, NormalizedSidebars, SidebarItemsGeneratorOption, CategoryMetadataFile } from './types';
|
|
9
9
|
import type { Slugger } from '@docusaurus/utils';
|
|
10
10
|
import type { NumberPrefixParser, SidebarOptions } from '@docusaurus/plugin-content-docs';
|
|
11
11
|
export declare type SidebarProcessorParams = {
|
|
@@ -15,5 +15,6 @@ export declare type SidebarProcessorParams = {
|
|
|
15
15
|
version: VersionMetadata;
|
|
16
16
|
categoryLabelSlugger: Slugger;
|
|
17
17
|
sidebarOptions: SidebarOptions;
|
|
18
|
+
categoriesMetadata: Record<string, CategoryMetadataFile>;
|
|
18
19
|
};
|
|
19
20
|
export declare function processSidebars(unprocessedSidebars: NormalizedSidebars, params: SidebarProcessorParams): Promise<Sidebars>;
|
|
@@ -30,7 +30,7 @@ function toSidebarItemsGeneratorVersion(version) {
|
|
|
30
30
|
// Handle the generation of autogenerated sidebar items and other
|
|
31
31
|
// post-processing checks
|
|
32
32
|
async function processSidebar(unprocessedSidebar, params) {
|
|
33
|
-
const { sidebarItemsGenerator, numberPrefixParser, docs, version, sidebarOptions, } = params;
|
|
33
|
+
const { sidebarItemsGenerator, numberPrefixParser, docs, version, sidebarOptions, categoriesMetadata, } = params;
|
|
34
34
|
// Just a minor lazy transformation optimization
|
|
35
35
|
const getSidebarItemsGeneratorDocsAndVersion = (0, lodash_1.memoize)(() => ({
|
|
36
36
|
docs: docs.map(toSidebarItemsGeneratorDoc),
|
|
@@ -52,6 +52,7 @@ async function processSidebar(unprocessedSidebar, params) {
|
|
|
52
52
|
isCategoryIndex: docs_1.isCategoryIndex,
|
|
53
53
|
...getSidebarItemsGeneratorDocsAndVersion(),
|
|
54
54
|
options: sidebarOptions,
|
|
55
|
+
categoriesMetadata,
|
|
55
56
|
});
|
|
56
57
|
// TODO validate generated items: user can generate bad items
|
|
57
58
|
const generatedItemsNormalized = generatedItems.flatMap((generatedItem) => (0, normalization_1.normalizeItem)(generatedItem, { ...params, ...sidebarOptions }));
|
package/lib/sidebars/types.d.ts
CHANGED
|
@@ -120,6 +120,14 @@ export declare type PropVersionDoc = {
|
|
|
120
120
|
export declare type PropVersionDocs = {
|
|
121
121
|
[docId: string]: PropVersionDoc;
|
|
122
122
|
};
|
|
123
|
+
export declare type CategoryMetadataFile = {
|
|
124
|
+
label?: string;
|
|
125
|
+
position?: number;
|
|
126
|
+
collapsed?: boolean;
|
|
127
|
+
collapsible?: boolean;
|
|
128
|
+
className?: string;
|
|
129
|
+
link?: SidebarItemCategoryLinkConfig | null;
|
|
130
|
+
};
|
|
123
131
|
export declare type SidebarItemsGeneratorDoc = Pick<DocMetadataBase, 'id' | 'unversionedId' | 'frontMatter' | 'source' | 'sourceDirName' | 'sidebarPosition'>;
|
|
124
132
|
export declare type SidebarItemsGeneratorVersion = Pick<VersionMetadata, 'versionName' | 'contentPath'>;
|
|
125
133
|
export declare type SidebarItemsGeneratorArgs = {
|
|
@@ -128,6 +136,7 @@ export declare type SidebarItemsGeneratorArgs = {
|
|
|
128
136
|
docs: SidebarItemsGeneratorDoc[];
|
|
129
137
|
numberPrefixParser: NumberPrefixParser;
|
|
130
138
|
isCategoryIndex: CategoryIndexMatcher;
|
|
139
|
+
categoriesMetadata: Record<string, CategoryMetadataFile>;
|
|
131
140
|
options: SidebarOptions;
|
|
132
141
|
};
|
|
133
142
|
export declare type SidebarItemsGenerator = (generatorArgs: SidebarItemsGeneratorArgs) => Promise<SidebarItem[]>;
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import type { SidebarsConfig } from './types';
|
|
8
|
-
import type { CategoryMetadataFile } from './generator';
|
|
7
|
+
import type { SidebarsConfig, CategoryMetadataFile } from './types';
|
|
9
8
|
export declare function validateSidebars(sidebars: unknown): asserts sidebars is SidebarsConfig;
|
|
10
9
|
export declare function validateCategoryMetadataFile(unsafeContent: unknown): CategoryMetadataFile;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-docs",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-4547",
|
|
4
4
|
"description": "Docs plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@docusaurus/core": "0.0.0-
|
|
27
|
-
"@docusaurus/logger": "0.0.0-
|
|
28
|
-
"@docusaurus/mdx-loader": "0.0.0-
|
|
29
|
-
"@docusaurus/utils": "0.0.0-
|
|
30
|
-
"@docusaurus/utils-validation": "0.0.0-
|
|
26
|
+
"@docusaurus/core": "0.0.0-4547",
|
|
27
|
+
"@docusaurus/logger": "0.0.0-4547",
|
|
28
|
+
"@docusaurus/mdx-loader": "0.0.0-4547",
|
|
29
|
+
"@docusaurus/utils": "0.0.0-4547",
|
|
30
|
+
"@docusaurus/utils-validation": "0.0.0-4547",
|
|
31
31
|
"combine-promises": "^1.1.0",
|
|
32
32
|
"fs-extra": "^10.0.0",
|
|
33
33
|
"import-fresh": "^3.2.2",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"webpack": "^5.68.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@docusaurus/module-type-aliases": "0.0.0-
|
|
44
|
-
"@docusaurus/types": "0.0.0-
|
|
43
|
+
"@docusaurus/module-type-aliases": "0.0.0-4547",
|
|
44
|
+
"@docusaurus/types": "0.0.0-4547",
|
|
45
45
|
"@types/js-yaml": "^4.0.0",
|
|
46
46
|
"@types/picomatch": "^2.2.1",
|
|
47
47
|
"commander": "^5.1.0",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=14"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "17925a2f808cffa695698b1fe049d25524a48982"
|
|
61
61
|
}
|
|
@@ -12,19 +12,11 @@ import type {
|
|
|
12
12
|
SidebarItemsGenerator,
|
|
13
13
|
SidebarItemsGeneratorDoc,
|
|
14
14
|
SidebarItemCategoryLink,
|
|
15
|
-
SidebarItemCategoryLinkConfig,
|
|
16
15
|
} from './types';
|
|
17
16
|
import {sortBy, last} from 'lodash';
|
|
18
|
-
import {
|
|
19
|
-
addTrailingSlash,
|
|
20
|
-
posixPath,
|
|
21
|
-
findAsyncSequential,
|
|
22
|
-
} from '@docusaurus/utils';
|
|
17
|
+
import {addTrailingSlash, posixPath} from '@docusaurus/utils';
|
|
23
18
|
import logger from '@docusaurus/logger';
|
|
24
19
|
import path from 'path';
|
|
25
|
-
import fs from 'fs-extra';
|
|
26
|
-
import Yaml from 'js-yaml';
|
|
27
|
-
import {validateCategoryMetadataFile} from './validation';
|
|
28
20
|
import {createDocsByIdIndex, toCategoryIndexMatcherParam} from '../docs';
|
|
29
21
|
|
|
30
22
|
const BreadcrumbSeparator = '/';
|
|
@@ -39,20 +31,6 @@ function getLocalDocId(docId: string): string {
|
|
|
39
31
|
export const CategoryMetadataFilenameBase = '_category_';
|
|
40
32
|
export const CategoryMetadataFilenamePattern = '_category_.{json,yml,yaml}';
|
|
41
33
|
|
|
42
|
-
export type CategoryMetadataFile = {
|
|
43
|
-
label?: string;
|
|
44
|
-
position?: number;
|
|
45
|
-
collapsed?: boolean;
|
|
46
|
-
collapsible?: boolean;
|
|
47
|
-
className?: string;
|
|
48
|
-
link?: SidebarItemCategoryLinkConfig | null;
|
|
49
|
-
|
|
50
|
-
// TODO should we allow "items" here? how would this work? would an
|
|
51
|
-
// "autogenerated" type be allowed?
|
|
52
|
-
// This mkdocs plugin do something like that: https://github.com/lukasgeiter/mkdocs-awesome-pages-plugin/
|
|
53
|
-
// cf comment: https://github.com/facebook/docusaurus/issues/3464#issuecomment-784765199
|
|
54
|
-
};
|
|
55
|
-
|
|
56
34
|
type WithPosition<T> = T & {position?: number};
|
|
57
35
|
|
|
58
36
|
/**
|
|
@@ -65,37 +43,6 @@ type Dir = {
|
|
|
65
43
|
[item: string]: Dir | null;
|
|
66
44
|
};
|
|
67
45
|
|
|
68
|
-
// TODO I now believe we should read all the category metadata files ahead of
|
|
69
|
-
// time: we may need this metadata to customize docs metadata
|
|
70
|
-
// Example use-case being able to disable number prefix parsing at the folder
|
|
71
|
-
// level, or customize the default base slug for an intermediate directory
|
|
72
|
-
// TODO later if there is `CategoryFolder/with-category-name-doc.md`, we may
|
|
73
|
-
// want to read the metadata as yaml on it
|
|
74
|
-
// see https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
|
|
75
|
-
async function readCategoryMetadataFile(
|
|
76
|
-
categoryDirPath: string,
|
|
77
|
-
): Promise<CategoryMetadataFile | null> {
|
|
78
|
-
async function tryReadFile(filePath: string): Promise<CategoryMetadataFile> {
|
|
79
|
-
const contentString = await fs.readFile(filePath, {encoding: 'utf8'});
|
|
80
|
-
const unsafeContent = Yaml.load(contentString);
|
|
81
|
-
try {
|
|
82
|
-
return validateCategoryMetadataFile(unsafeContent);
|
|
83
|
-
} catch (e) {
|
|
84
|
-
logger.error`The docs sidebar category metadata file path=${filePath} looks invalid!`;
|
|
85
|
-
throw e;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const filePath = await findAsyncSequential(
|
|
89
|
-
['.json', '.yml', '.yaml'].map((ext) =>
|
|
90
|
-
posixPath(
|
|
91
|
-
path.join(categoryDirPath, `${CategoryMetadataFilenameBase}${ext}`),
|
|
92
|
-
),
|
|
93
|
-
),
|
|
94
|
-
fs.pathExists,
|
|
95
|
-
);
|
|
96
|
-
return filePath ? tryReadFile(filePath) : null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
46
|
// Comment for this feature: https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
|
|
100
47
|
export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
101
48
|
numberPrefixParser,
|
|
@@ -103,7 +50,7 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
103
50
|
docs: allDocs,
|
|
104
51
|
options,
|
|
105
52
|
item: {dirName: autogenDir},
|
|
106
|
-
|
|
53
|
+
categoriesMetadata,
|
|
107
54
|
}) => {
|
|
108
55
|
const docsById = createDocsByIdIndex(allDocs);
|
|
109
56
|
const findDoc = (docId: string): SidebarItemsGeneratorDoc | undefined =>
|
|
@@ -199,8 +146,8 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
199
146
|
fullPath: string,
|
|
200
147
|
folderName: string,
|
|
201
148
|
): Promise<WithPosition<SidebarItemCategory>> {
|
|
202
|
-
const
|
|
203
|
-
|
|
149
|
+
const categoryMetadata =
|
|
150
|
+
categoriesMetadata[posixPath(path.join(autogenDir, fullPath))];
|
|
204
151
|
const className = categoryMetadata?.className;
|
|
205
152
|
const {filename, numberPrefix} = numberPrefixParser(folderName);
|
|
206
153
|
const allItems = await Promise.all(
|
package/src/sidebars/index.ts
CHANGED
|
@@ -9,12 +9,16 @@ import fs from 'fs-extra';
|
|
|
9
9
|
import importFresh from 'import-fresh';
|
|
10
10
|
import type {SidebarsConfig, Sidebars, NormalizedSidebars} from './types';
|
|
11
11
|
import type {NormalizeSidebarsParams} from '../types';
|
|
12
|
-
import {validateSidebars} from './validation';
|
|
12
|
+
import {validateSidebars, validateCategoryMetadataFile} from './validation';
|
|
13
13
|
import {normalizeSidebars} from './normalization';
|
|
14
14
|
import {processSidebars, type SidebarProcessorParams} from './processor';
|
|
15
15
|
import path from 'path';
|
|
16
|
-
import {createSlugger} from '@docusaurus/utils';
|
|
16
|
+
import {createSlugger, Globby} from '@docusaurus/utils';
|
|
17
|
+
import logger from '@docusaurus/logger';
|
|
17
18
|
import type {PluginOptions} from '@docusaurus/plugin-content-docs';
|
|
19
|
+
import Yaml from 'js-yaml';
|
|
20
|
+
import {groupBy, mapValues} from 'lodash';
|
|
21
|
+
import combinePromises from 'combine-promises';
|
|
18
22
|
|
|
19
23
|
export const DefaultSidebars: SidebarsConfig = {
|
|
20
24
|
defaultSidebar: [
|
|
@@ -38,6 +42,33 @@ export function resolveSidebarPathOption(
|
|
|
38
42
|
: sidebarPathOption;
|
|
39
43
|
}
|
|
40
44
|
|
|
45
|
+
async function readCategoriesMetadata(contentPath: string) {
|
|
46
|
+
const categoryFiles = await Globby('**/_category_.{json,yml,yaml}', {
|
|
47
|
+
cwd: contentPath,
|
|
48
|
+
});
|
|
49
|
+
const categoryToFile = groupBy(categoryFiles, path.dirname);
|
|
50
|
+
return combinePromises(
|
|
51
|
+
mapValues(categoryToFile, async (files, folder) => {
|
|
52
|
+
const [filePath] = files;
|
|
53
|
+
if (files.length > 1) {
|
|
54
|
+
logger.warn`There are more than one category metadata files for path=${folder}: ${files.join(
|
|
55
|
+
', ',
|
|
56
|
+
)}. The behavior is undetermined.`;
|
|
57
|
+
}
|
|
58
|
+
const content = await fs.readFile(
|
|
59
|
+
path.join(contentPath, filePath),
|
|
60
|
+
'utf-8',
|
|
61
|
+
);
|
|
62
|
+
try {
|
|
63
|
+
return validateCategoryMetadataFile(Yaml.load(content));
|
|
64
|
+
} catch (e) {
|
|
65
|
+
logger.error`The docs sidebar category metadata file path=${filePath} looks invalid!`;
|
|
66
|
+
throw e;
|
|
67
|
+
}
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
41
72
|
async function loadSidebarsFileUnsafe(
|
|
42
73
|
sidebarFilePath: string | false | undefined,
|
|
43
74
|
): Promise<SidebarsConfig> {
|
|
@@ -80,7 +111,7 @@ export async function loadNormalizedSidebars(
|
|
|
80
111
|
// Note: sidebarFilePath must be absolute, use resolveSidebarPathOption
|
|
81
112
|
export async function loadSidebars(
|
|
82
113
|
sidebarFilePath: string | false | undefined,
|
|
83
|
-
options: SidebarProcessorParams,
|
|
114
|
+
options: Omit<SidebarProcessorParams, 'categoriesMetadata'>,
|
|
84
115
|
): Promise<Sidebars> {
|
|
85
116
|
const normalizeSidebarsParams: NormalizeSidebarsParams = {
|
|
86
117
|
...options.sidebarOptions,
|
|
@@ -91,5 +122,8 @@ export async function loadSidebars(
|
|
|
91
122
|
sidebarFilePath,
|
|
92
123
|
normalizeSidebarsParams,
|
|
93
124
|
);
|
|
94
|
-
|
|
125
|
+
const categoriesMetadata = await readCategoriesMetadata(
|
|
126
|
+
options.version.contentPath,
|
|
127
|
+
);
|
|
128
|
+
return processSidebars(normalizedSidebars, {...options, categoriesMetadata});
|
|
95
129
|
}
|
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
NormalizedSidebarItemCategory,
|
|
20
20
|
SidebarItemCategory,
|
|
21
21
|
SidebarItemAutogenerated,
|
|
22
|
+
CategoryMetadataFile,
|
|
22
23
|
} from './types';
|
|
23
24
|
import {transformSidebarItems} from './utils';
|
|
24
25
|
import {DefaultSidebarItemsGenerator} from './generator';
|
|
@@ -39,6 +40,7 @@ export type SidebarProcessorParams = {
|
|
|
39
40
|
version: VersionMetadata;
|
|
40
41
|
categoryLabelSlugger: Slugger;
|
|
41
42
|
sidebarOptions: SidebarOptions;
|
|
43
|
+
categoriesMetadata: Record<string, CategoryMetadataFile>;
|
|
42
44
|
};
|
|
43
45
|
|
|
44
46
|
function toSidebarItemsGeneratorDoc(
|
|
@@ -72,6 +74,7 @@ async function processSidebar(
|
|
|
72
74
|
docs,
|
|
73
75
|
version,
|
|
74
76
|
sidebarOptions,
|
|
77
|
+
categoriesMetadata,
|
|
75
78
|
} = params;
|
|
76
79
|
|
|
77
80
|
// Just a minor lazy transformation optimization
|
|
@@ -101,6 +104,7 @@ async function processSidebar(
|
|
|
101
104
|
isCategoryIndex,
|
|
102
105
|
...getSidebarItemsGeneratorDocsAndVersion(),
|
|
103
106
|
options: sidebarOptions,
|
|
107
|
+
categoriesMetadata,
|
|
104
108
|
});
|
|
105
109
|
// TODO validate generated items: user can generate bad items
|
|
106
110
|
|
package/src/sidebars/types.ts
CHANGED
|
@@ -188,6 +188,20 @@ export type PropVersionDocs = {
|
|
|
188
188
|
[docId: string]: PropVersionDoc;
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
+
export type CategoryMetadataFile = {
|
|
192
|
+
label?: string;
|
|
193
|
+
position?: number;
|
|
194
|
+
collapsed?: boolean;
|
|
195
|
+
collapsible?: boolean;
|
|
196
|
+
className?: string;
|
|
197
|
+
link?: SidebarItemCategoryLinkConfig | null;
|
|
198
|
+
|
|
199
|
+
// TODO should we allow "items" here? how would this work? would an
|
|
200
|
+
// "autogenerated" type be allowed?
|
|
201
|
+
// This mkdocs plugin do something like that: https://github.com/lukasgeiter/mkdocs-awesome-pages-plugin/
|
|
202
|
+
// cf comment: https://github.com/facebook/docusaurus/issues/3464#issuecomment-784765199
|
|
203
|
+
};
|
|
204
|
+
|
|
191
205
|
// Reduce API surface for options.sidebarItemsGenerator
|
|
192
206
|
// The user-provided generator fn should receive only a subset of metadata
|
|
193
207
|
// A change to any of these metadata can be considered as a breaking change
|
|
@@ -211,6 +225,7 @@ export type SidebarItemsGeneratorArgs = {
|
|
|
211
225
|
docs: SidebarItemsGeneratorDoc[];
|
|
212
226
|
numberPrefixParser: NumberPrefixParser;
|
|
213
227
|
isCategoryIndex: CategoryIndexMatcher;
|
|
228
|
+
categoriesMetadata: Record<string, CategoryMetadataFile>;
|
|
214
229
|
options: SidebarOptions;
|
|
215
230
|
};
|
|
216
231
|
export type SidebarItemsGenerator = (
|
|
@@ -19,9 +19,9 @@ import type {
|
|
|
19
19
|
SidebarsConfig,
|
|
20
20
|
SidebarItemCategoryLinkDoc,
|
|
21
21
|
SidebarItemCategoryLinkGeneratedIndex,
|
|
22
|
+
CategoryMetadataFile,
|
|
22
23
|
} from './types';
|
|
23
24
|
import {isCategoriesShorthand} from './utils';
|
|
24
|
-
import type {CategoryMetadataFile} from './generator';
|
|
25
25
|
|
|
26
26
|
// NOTE: we don't add any default values during validation on purpose!
|
|
27
27
|
// Config types are exposed to users for typechecking and we use the same type
|