@docusaurus/plugin-content-docs 2.0.0-beta.15 → 2.0.0-beta.16

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.
Files changed (69) hide show
  1. package/lib/cli.d.ts +1 -1
  2. package/lib/cli.js +18 -14
  3. package/lib/client/docsClientUtils.js +2 -2
  4. package/lib/client/index.d.ts +13 -1
  5. package/lib/client/index.js +66 -1
  6. package/lib/docFrontMatter.js +1 -0
  7. package/lib/docs.d.ts +2 -1
  8. package/lib/docs.js +23 -22
  9. package/lib/globalData.js +3 -2
  10. package/lib/index.js +11 -6
  11. package/lib/lastUpdate.js +14 -27
  12. package/lib/numberPrefix.js +7 -6
  13. package/lib/options.js +5 -2
  14. package/lib/props.js +15 -10
  15. package/lib/routes.js +6 -4
  16. package/lib/server-export.d.ts +8 -0
  17. package/lib/server-export.js +23 -0
  18. package/lib/sidebars/generator.d.ts +1 -9
  19. package/lib/sidebars/generator.js +26 -50
  20. package/lib/sidebars/index.d.ts +2 -5
  21. package/lib/sidebars/index.js +35 -20
  22. package/lib/sidebars/normalization.d.ts +2 -3
  23. package/lib/sidebars/normalization.js +17 -39
  24. package/lib/sidebars/postProcessor.d.ts +8 -0
  25. package/lib/sidebars/postProcessor.js +72 -0
  26. package/lib/sidebars/processor.d.ts +2 -13
  27. package/lib/sidebars/processor.js +25 -33
  28. package/lib/sidebars/types.d.ts +44 -10
  29. package/lib/sidebars/utils.js +53 -61
  30. package/lib/sidebars/validation.d.ts +2 -3
  31. package/lib/sidebars/validation.js +25 -30
  32. package/lib/slug.js +6 -8
  33. package/lib/tags.js +3 -2
  34. package/lib/translations.js +18 -17
  35. package/lib/types.d.ts +3 -6
  36. package/lib/versions.d.ts +25 -1
  37. package/lib/versions.js +25 -29
  38. package/package.json +19 -18
  39. package/src/cli.ts +25 -16
  40. package/src/client/docsClientUtils.ts +2 -2
  41. package/src/client/index.ts +97 -1
  42. package/src/docFrontMatter.ts +1 -0
  43. package/src/docs.ts +25 -20
  44. package/src/globalData.ts +2 -2
  45. package/src/index.ts +17 -7
  46. package/src/lastUpdate.ts +12 -33
  47. package/src/numberPrefix.ts +7 -6
  48. package/src/options.ts +5 -2
  49. package/src/plugin-content-docs.d.ts +16 -60
  50. package/src/props.ts +17 -12
  51. package/src/routes.ts +6 -4
  52. package/src/server-export.ts +24 -0
  53. package/src/sidebars/README.md +9 -0
  54. package/src/sidebars/generator.ts +50 -94
  55. package/src/sidebars/index.ts +50 -32
  56. package/src/sidebars/normalization.ts +22 -50
  57. package/src/sidebars/postProcessor.ts +94 -0
  58. package/src/sidebars/processor.ts +37 -66
  59. package/src/sidebars/types.ts +68 -10
  60. package/src/sidebars/utils.ts +63 -68
  61. package/src/sidebars/validation.ts +53 -53
  62. package/src/slug.ts +9 -10
  63. package/src/tags.ts +2 -2
  64. package/src/translations.ts +19 -16
  65. package/src/types.ts +3 -10
  66. package/src/versions.ts +30 -34
  67. package/lib/client/globalDataHooks.d.ts +0 -19
  68. package/lib/client/globalDataHooks.js +0 -76
  69. package/src/client/globalDataHooks.ts +0 -107
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Facebook, Inc. and its affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.readVersionNames = exports.readVersionsFile = exports.getVersionsFilePath = exports.getVersionBanner = exports.getVersionBadge = exports.getDefaultVersionBanner = exports.filterVersions = exports.VERSIONS_JSON_FILE = exports.VERSIONED_SIDEBARS_DIR = exports.VERSIONED_DOCS_DIR = exports.CURRENT_VERSION_NAME = void 0;
10
+ // APIs available to Node.js
11
+ var constants_1 = require("./constants");
12
+ Object.defineProperty(exports, "CURRENT_VERSION_NAME", { enumerable: true, get: function () { return constants_1.CURRENT_VERSION_NAME; } });
13
+ Object.defineProperty(exports, "VERSIONED_DOCS_DIR", { enumerable: true, get: function () { return constants_1.VERSIONED_DOCS_DIR; } });
14
+ Object.defineProperty(exports, "VERSIONED_SIDEBARS_DIR", { enumerable: true, get: function () { return constants_1.VERSIONED_SIDEBARS_DIR; } });
15
+ Object.defineProperty(exports, "VERSIONS_JSON_FILE", { enumerable: true, get: function () { return constants_1.VERSIONS_JSON_FILE; } });
16
+ var versions_1 = require("./versions");
17
+ Object.defineProperty(exports, "filterVersions", { enumerable: true, get: function () { return versions_1.filterVersions; } });
18
+ Object.defineProperty(exports, "getDefaultVersionBanner", { enumerable: true, get: function () { return versions_1.getDefaultVersionBanner; } });
19
+ Object.defineProperty(exports, "getVersionBadge", { enumerable: true, get: function () { return versions_1.getVersionBadge; } });
20
+ Object.defineProperty(exports, "getVersionBanner", { enumerable: true, get: function () { return versions_1.getVersionBanner; } });
21
+ Object.defineProperty(exports, "getVersionsFilePath", { enumerable: true, get: function () { return versions_1.getVersionsFilePath; } });
22
+ Object.defineProperty(exports, "readVersionsFile", { enumerable: true, get: function () { return versions_1.readVersionsFile; } });
23
+ Object.defineProperty(exports, "readVersionNames", { enumerable: true, get: function () { return versions_1.readVersionNames; } });
@@ -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, SidebarItemCategoryLinkConfig } from './types';
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;
17
- };
18
10
  export declare const DefaultSidebarItemsGenerator: SidebarItemsGenerator;
@@ -8,44 +8,22 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.DefaultSidebarItemsGenerator = exports.CategoryMetadataFilenamePattern = exports.CategoryMetadataFilenameBase = void 0;
10
10
  const tslib_1 = require("tslib");
11
- const lodash_1 = require("lodash");
11
+ const lodash_1 = (0, tslib_1.__importDefault)(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
21
18
  const docIdPrefix = '$doc$/';
22
19
  // Just an alias to the make code more explicit
23
20
  function getLocalDocId(docId) {
24
- return (0, lodash_1.last)(docId.split('/'));
21
+ return lodash_1.default.last(docId.split('/'));
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 time: we may need this metadata to customize docs metadata
29
- // Example use-case being able to disable number prefix parsing at the folder level, or customize the default route path segment for an intermediate directory...
30
- // TODO later if there is `CategoryFolder/with-category-name-doc.md`, we may want to read the metadata as yaml on it
31
- // see https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
32
- async function readCategoryMetadataFile(categoryDirPath) {
33
- async function tryReadFile(filePath) {
34
- const contentString = await fs_extra_1.default.readFile(filePath, { encoding: 'utf8' });
35
- const unsafeContent = js_yaml_1.default.load(contentString);
36
- try {
37
- return (0, validation_1.validateCategoryMetadataFile)(unsafeContent);
38
- }
39
- catch (e) {
40
- logger_1.default.error `The docs sidebar category metadata file path=${filePath} looks invalid!`;
41
- throw e;
42
- }
43
- }
44
- 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);
45
- return filePath ? tryReadFile(filePath) : null;
46
- }
47
25
  // Comment for this feature: https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
48
- const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryIndex, docs: allDocs, options, item: { dirName: autogenDir }, version, }) => {
26
+ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryIndex, docs: allDocs, item: { dirName: autogenDir }, categoriesMetadata, }) => {
49
27
  const docsById = (0, docs_1.createDocsByIdIndex)(allDocs);
50
28
  const findDoc = (docId) => docsById[docId];
51
29
  const getDoc = (docId) => {
@@ -79,7 +57,8 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
79
57
  * Step 2. Turn the linear file list into a tree structure.
80
58
  */
81
59
  function treeify(docs) {
82
- // Get the category breadcrumb of a doc (relative to the dir of the autogenerated sidebar item)
60
+ // Get the category breadcrumb of a doc (relative to the dir of the
61
+ // autogenerated sidebar item)
83
62
  // autogenDir=a/b and docDir=a/b/c/d => returns [c, d]
84
63
  // autogenDir=a/b and docDir=a/b => returns []
85
64
  // TODO: try to use path.relative()
@@ -105,7 +84,7 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
105
84
  return treeRoot;
106
85
  }
107
86
  /**
108
- * Step 3. Recursively transform the tree-like file structure to sidebar items.
87
+ * Step 3. Recursively transform the tree-like structure to sidebar items.
109
88
  * (From a record to an array of items, akin to normalizing shorthand)
110
89
  */
111
90
  function generateSidebar(fsModel) {
@@ -115,15 +94,15 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
115
94
  type: 'doc',
116
95
  id,
117
96
  position,
118
- // We don't want these fields to magically appear in the generated sidebar
97
+ // We don't want these fields to magically appear in the generated
98
+ // sidebar
119
99
  ...(label !== undefined && { label }),
120
100
  ...(className !== undefined && { className }),
121
101
  };
122
102
  }
123
103
  async function createCategoryItem(dir, fullPath, folderName) {
124
- var _a, _b, _c, _d;
125
- const categoryPath = path_1.default.join(version.contentPath, autogenDir, fullPath);
126
- const categoryMetadata = await readCategoryMetadataFile(categoryPath);
104
+ var _a, _b;
105
+ const categoryMetadata = categoriesMetadata[(0, utils_1.posixPath)(path_1.default.join(autogenDir, fullPath))];
127
106
  const className = categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.className;
128
107
  const { filename, numberPrefix } = numberPrefixParser(folderName);
129
108
  const allItems = await Promise.all(Object.entries(dir).map(([key, content]) => dirToItem(content, key, `${fullPath}/${key}`)));
@@ -144,17 +123,15 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
144
123
  function getCategoryLinkedDocId() {
145
124
  var _a, _b;
146
125
  const link = categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.link;
147
- if (link) {
148
- if (link.type === 'doc') {
126
+ if (link !== undefined) {
127
+ if (link && link.type === 'doc') {
149
128
  return ((_a = findDocByLocalId(link.id)) === null || _a === void 0 ? void 0 : _a.id) || getDoc(link.id).id;
150
129
  }
151
- else {
152
- // We don't continue for other link types on purpose!
153
- // IE if user decide to use type "generated-index", we should not pick a README.md file as the linked doc
154
- return undefined;
155
- }
130
+ // If a link is explicitly specified, we won't apply conventions
131
+ return undefined;
156
132
  }
157
- // Apply default convention to pick index.md, README.md or <categoryName>.md as the category doc
133
+ // Apply default convention to pick index.md, README.md or
134
+ // <categoryName>.md as the category doc
158
135
  return (_b = findConventionalCategoryDocLink()) === null || _b === void 0 ? void 0 : _b.id;
159
136
  }
160
137
  const categoryLinkedDocId = getCategoryLinkedDocId();
@@ -163,16 +140,15 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
163
140
  type: 'doc',
164
141
  id: categoryLinkedDocId, // We "remap" a potentially "local id" to a "qualified id"
165
142
  }
166
- : // TODO typing issue
167
- categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.link;
143
+ : categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.link;
168
144
  // If a doc is linked, remove it from the category subItems
169
145
  const items = allItems.filter((item) => !(item.type === 'doc' && item.id === categoryLinkedDocId));
170
146
  return {
171
147
  type: 'category',
172
148
  label: (_a = categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.label) !== null && _a !== void 0 ? _a : filename,
173
- collapsible: (_b = categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.collapsible) !== null && _b !== void 0 ? _b : options.sidebarCollapsible,
174
- collapsed: (_c = categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.collapsed) !== null && _c !== void 0 ? _c : options.sidebarCollapsed,
175
- position: (_d = categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.position) !== null && _d !== void 0 ? _d : numberPrefix,
149
+ collapsible: categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.collapsible,
150
+ collapsed: categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.collapsed,
151
+ position: (_b = categoryMetadata === null || categoryMetadata === void 0 ? void 0 : categoryMetadata.position) !== null && _b !== void 0 ? _b : numberPrefix,
176
152
  ...(className !== undefined && { className }),
177
153
  items,
178
154
  ...(link && { link }),
@@ -188,10 +164,11 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
188
164
  return Promise.all(Object.entries(fsModel).map(([key, content]) => dirToItem(content, key, key)));
189
165
  }
190
166
  /**
191
- * Step 4. Recursively sort the categories/docs + remove the "position" attribute from final output.
192
- * Note: the "position" is only used to sort "inside" a sidebar slice. It is not
193
- * used to sort across multiple consecutive sidebar slices (ie a whole Category
194
- * composed of multiple autogenerated items)
167
+ * Step 4. Recursively sort the categories/docs + remove the "position"
168
+ * attribute from final output. Note: the "position" is only used to sort
169
+ * "inside" a sidebar slice. It is not used to sort across multiple
170
+ * consecutive sidebar slices (i.e. a whole category composed of multiple
171
+ * autogenerated items)
195
172
  */
196
173
  function sortItems(sidebarItems) {
197
174
  const processedSidebarItems = sidebarItems.map((item) => {
@@ -200,11 +177,10 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
200
177
  }
201
178
  return item;
202
179
  });
203
- const sortedSidebarItems = (0, lodash_1.sortBy)(processedSidebarItems, (item) => item.position);
180
+ const sortedSidebarItems = lodash_1.default.sortBy(processedSidebarItems, (item) => item.position);
204
181
  return sortedSidebarItems.map(({ position, ...item }) => item);
205
182
  }
206
183
  // TODO: the whole code is designed for pipeline operator
207
- // return getAutogenDocs() |> treeify |> await generateSidebar(^) |> sortItems;
208
184
  const docs = getAutogenDocs();
209
185
  const fsModel = treeify(docs);
210
186
  const sidebarWithPosition = await generateSidebar(fsModel);
@@ -4,13 +4,10 @@
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, Sidebars, NormalizedSidebars } from './types';
8
- import type { NormalizeSidebarsParams } from '../types';
9
- import { type SidebarProcessorParams } from './processor';
7
+ import type { SidebarsConfig, Sidebars, SidebarProcessorParams } from './types';
10
8
  import type { PluginOptions } from '@docusaurus/plugin-content-docs';
11
9
  export declare const DefaultSidebars: SidebarsConfig;
12
10
  export declare const DisabledSidebars: SidebarsConfig;
13
11
  export declare function resolveSidebarPathOption(siteDir: string, sidebarPathOption: PluginOptions['sidebarPath']): PluginOptions['sidebarPath'];
14
- export declare function loadSidebarsFile(sidebarFilePath: string | false | undefined): SidebarsConfig;
15
- export declare function loadNormalizedSidebars(sidebarFilePath: string | false | undefined, params: NormalizeSidebarsParams): NormalizedSidebars;
12
+ export declare function loadSidebarsFileUnsafe(sidebarFilePath: string | false | undefined): Promise<SidebarsConfig>;
16
13
  export declare function loadSidebars(sidebarFilePath: string | false | undefined, options: SidebarProcessorParams): Promise<Sidebars>;
@@ -6,15 +6,20 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.loadSidebars = exports.loadNormalizedSidebars = exports.loadSidebarsFile = exports.resolveSidebarPathOption = exports.DisabledSidebars = exports.DefaultSidebars = void 0;
9
+ exports.loadSidebars = exports.loadSidebarsFileUnsafe = exports.resolveSidebarPathOption = exports.DisabledSidebars = exports.DefaultSidebars = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
12
12
  const import_fresh_1 = (0, tslib_1.__importDefault)(require("import-fresh"));
13
13
  const validation_1 = require("./validation");
14
14
  const normalization_1 = require("./normalization");
15
15
  const processor_1 = require("./processor");
16
+ const postProcessor_1 = require("./postProcessor");
16
17
  const path_1 = (0, tslib_1.__importDefault)(require("path"));
17
18
  const utils_1 = require("@docusaurus/utils");
19
+ const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
20
+ const js_yaml_1 = (0, tslib_1.__importDefault)(require("js-yaml"));
21
+ const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
22
+ const combine_promises_1 = (0, tslib_1.__importDefault)(require("combine-promises"));
18
23
  exports.DefaultSidebars = {
19
24
  defaultSidebar: [
20
25
  {
@@ -32,7 +37,27 @@ function resolveSidebarPathOption(siteDir, sidebarPathOption) {
32
37
  : sidebarPathOption;
33
38
  }
34
39
  exports.resolveSidebarPathOption = resolveSidebarPathOption;
35
- function loadSidebarsFileUnsafe(sidebarFilePath) {
40
+ async function readCategoriesMetadata(contentPath) {
41
+ const categoryFiles = await (0, utils_1.Globby)('**/_category_.{json,yml,yaml}', {
42
+ cwd: contentPath,
43
+ });
44
+ const categoryToFile = lodash_1.default.groupBy(categoryFiles, path_1.default.dirname);
45
+ return (0, combine_promises_1.default)(lodash_1.default.mapValues(categoryToFile, async (files, folder) => {
46
+ const [filePath] = files;
47
+ if (files.length > 1) {
48
+ logger_1.default.warn `There are more than one category metadata files for path=${folder}: ${files.join(', ')}. The behavior is undetermined.`;
49
+ }
50
+ const content = await fs_extra_1.default.readFile(path_1.default.join(contentPath, filePath), 'utf-8');
51
+ try {
52
+ return (0, validation_1.validateCategoryMetadataFile)(js_yaml_1.default.load(content));
53
+ }
54
+ catch (err) {
55
+ logger_1.default.error `The docs sidebar category metadata file path=${filePath} looks invalid!`;
56
+ throw err;
57
+ }
58
+ }));
59
+ }
60
+ async function loadSidebarsFileUnsafe(sidebarFilePath) {
36
61
  // false => no sidebars
37
62
  if (sidebarFilePath === false) {
38
63
  return exports.DisabledSidebars;
@@ -44,30 +69,20 @@ function loadSidebarsFileUnsafe(sidebarFilePath) {
44
69
  // Non-existent sidebars file: no sidebars
45
70
  // Note: this edge case can happen on versioned docs, not current version
46
71
  // We avoid creating empty versioned sidebars file with the CLI
47
- if (!fs_extra_1.default.existsSync(sidebarFilePath)) {
72
+ if (!(await fs_extra_1.default.pathExists(sidebarFilePath))) {
48
73
  return exports.DisabledSidebars;
49
74
  }
50
75
  // We don't want sidebars to be cached because of hot reloading.
51
76
  return (0, import_fresh_1.default)(sidebarFilePath);
52
77
  }
53
- function loadSidebarsFile(sidebarFilePath) {
54
- const sidebarsConfig = loadSidebarsFileUnsafe(sidebarFilePath);
55
- (0, validation_1.validateSidebars)(sidebarsConfig);
56
- return sidebarsConfig;
57
- }
58
- exports.loadSidebarsFile = loadSidebarsFile;
59
- function loadNormalizedSidebars(sidebarFilePath, params) {
60
- return (0, normalization_1.normalizeSidebars)(loadSidebarsFile(sidebarFilePath), params);
61
- }
62
- exports.loadNormalizedSidebars = loadNormalizedSidebars;
78
+ exports.loadSidebarsFileUnsafe = loadSidebarsFileUnsafe;
63
79
  // Note: sidebarFilePath must be absolute, use resolveSidebarPathOption
64
80
  async function loadSidebars(sidebarFilePath, options) {
65
- const normalizeSidebarsParams = {
66
- ...options.sidebarOptions,
67
- version: options.version,
68
- categoryLabelSlugger: (0, utils_1.createSlugger)(),
69
- };
70
- const normalizedSidebars = loadNormalizedSidebars(sidebarFilePath, normalizeSidebarsParams);
71
- return (0, processor_1.processSidebars)(normalizedSidebars, options);
81
+ const sidebarsConfig = await loadSidebarsFileUnsafe(sidebarFilePath);
82
+ const normalizedSidebars = (0, normalization_1.normalizeSidebars)(sidebarsConfig);
83
+ (0, validation_1.validateSidebars)(normalizedSidebars);
84
+ const categoriesMetadata = await readCategoriesMetadata(options.version.contentPath);
85
+ const processedSidebars = await (0, processor_1.processSidebars)(normalizedSidebars, categoriesMetadata, options);
86
+ return (0, postProcessor_1.postProcessSidebars)(processedSidebars, options);
72
87
  }
73
88
  exports.loadSidebars = loadSidebars;
@@ -4,11 +4,10 @@
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 { NormalizeSidebarsParams } from '../types';
8
7
  import type { NormalizedSidebarItem, NormalizedSidebars, SidebarItemConfig, SidebarsConfig } from './types';
9
8
  /**
10
9
  * Normalizes recursively item and all its children. Ensures that at the end
11
10
  * each item will be an object with the corresponding type.
12
11
  */
13
- export declare function normalizeItem(item: SidebarItemConfig, options: NormalizeSidebarsParams): NormalizedSidebarItem[];
14
- export declare function normalizeSidebars(sidebars: SidebarsConfig, params: NormalizeSidebarsParams): NormalizedSidebars;
12
+ export declare function normalizeItem(item: SidebarItemConfig): NormalizedSidebarItem[];
13
+ export declare function normalizeSidebars(sidebars: SidebarsConfig): NormalizedSidebars;
@@ -7,29 +7,13 @@
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.normalizeSidebars = exports.normalizeItem = void 0;
10
+ const tslib_1 = require("tslib");
10
11
  const utils_1 = require("./utils");
11
- const lodash_1 = require("lodash");
12
- const utils_2 = require("@docusaurus/utils");
13
- function normalizeCategoryLink(category, params) {
14
- var _a, _b;
15
- if (((_a = category.link) === null || _a === void 0 ? void 0 : _a.type) === 'generated-index') {
16
- // default slug logic can be improved
17
- const getDefaultSlug = () => `/category/${params.categoryLabelSlugger.slug(category.label)}`;
18
- const slug = (_b = category.link.slug) !== null && _b !== void 0 ? _b : getDefaultSlug();
19
- const permalink = (0, utils_2.normalizeUrl)([params.version.versionPath, slug]);
20
- return {
21
- ...category.link,
22
- slug,
23
- permalink,
24
- };
25
- }
26
- return category.link;
27
- }
28
- function normalizeCategoriesShorthand(sidebar, options) {
12
+ const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
13
+ const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
14
+ function normalizeCategoriesShorthand(sidebar) {
29
15
  return Object.entries(sidebar).map(([label, items]) => ({
30
16
  type: 'category',
31
- collapsed: options.sidebarCollapsed,
32
- collapsible: options.sidebarCollapsible,
33
17
  label,
34
18
  items,
35
19
  }));
@@ -38,40 +22,34 @@ function normalizeCategoriesShorthand(sidebar, options) {
38
22
  * Normalizes recursively item and all its children. Ensures that at the end
39
23
  * each item will be an object with the corresponding type.
40
24
  */
41
- function normalizeItem(item, options) {
42
- var _a, _b, _c;
25
+ function normalizeItem(item) {
43
26
  if (typeof item === 'string') {
44
- return [
45
- {
46
- type: 'doc',
47
- id: item,
48
- },
49
- ];
27
+ return [{ type: 'doc', id: item }];
50
28
  }
51
29
  if ((0, utils_1.isCategoriesShorthand)(item)) {
52
- return normalizeCategoriesShorthand(item, options).flatMap((subItem) => normalizeItem(subItem, options));
30
+ // This will never throw anyways
31
+ return normalizeSidebar(item, 'sidebar items slice');
53
32
  }
54
33
  if (item.type === 'category') {
55
- const link = normalizeCategoryLink(item, options);
56
34
  const normalizedCategory = {
57
35
  ...item,
58
- link,
59
- items: ((_a = item.items) !== null && _a !== void 0 ? _a : []).flatMap((subItem) => normalizeItem(subItem, options)),
60
- collapsible: (_b = item.collapsible) !== null && _b !== void 0 ? _b : options.sidebarCollapsible,
61
- collapsed: (_c = item.collapsed) !== null && _c !== void 0 ? _c : options.sidebarCollapsed,
36
+ items: normalizeSidebar(item.items, logger_1.default.interpolate `code=${'items'} of the category name=${item.label}`),
62
37
  };
63
38
  return [normalizedCategory];
64
39
  }
65
40
  return [item];
66
41
  }
67
42
  exports.normalizeItem = normalizeItem;
68
- function normalizeSidebar(sidebar, options) {
43
+ function normalizeSidebar(sidebar, place) {
44
+ if (!Array.isArray(sidebar) && !(0, utils_1.isCategoriesShorthand)(sidebar)) {
45
+ throw new Error(logger_1.default.interpolate `Invalid sidebar items collection code=${JSON.stringify(sidebar)} in ${place}: it must either be an array of sidebar items or a shorthand notation (which doesn't contain a code=${'type'} property). See path=${'https://docusaurus.io/docs/sidebar/items'} for all valid syntaxes.`);
46
+ }
69
47
  const normalizedSidebar = Array.isArray(sidebar)
70
48
  ? sidebar
71
- : normalizeCategoriesShorthand(sidebar, options);
72
- return normalizedSidebar.flatMap((subItem) => normalizeItem(subItem, options));
49
+ : normalizeCategoriesShorthand(sidebar);
50
+ return normalizedSidebar.flatMap((subItem) => normalizeItem(subItem));
73
51
  }
74
- function normalizeSidebars(sidebars, params) {
75
- return (0, lodash_1.mapValues)(sidebars, (items) => normalizeSidebar(items, params));
52
+ function normalizeSidebars(sidebars) {
53
+ return lodash_1.default.mapValues(sidebars, (sidebar, id) => normalizeSidebar(sidebar, logger_1.default.interpolate `sidebar name=${id}`));
76
54
  }
77
55
  exports.normalizeSidebars = normalizeSidebars;
@@ -0,0 +1,8 @@
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
+ import type { Sidebars, SidebarProcessorParams, ProcessedSidebars } from './types';
8
+ export declare function postProcessSidebars(sidebars: ProcessedSidebars, params: SidebarProcessorParams): Sidebars;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Facebook, Inc. and its affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.postProcessSidebars = void 0;
10
+ const tslib_1 = require("tslib");
11
+ const utils_1 = require("@docusaurus/utils");
12
+ const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
13
+ function normalizeCategoryLink(category, params) {
14
+ var _a, _b;
15
+ if (((_a = category.link) === null || _a === void 0 ? void 0 : _a.type) === 'generated-index') {
16
+ // default slug logic can be improved
17
+ const getDefaultSlug = () => `/category/${params.categoryLabelSlugger.slug(category.label)}`;
18
+ const slug = (_b = category.link.slug) !== null && _b !== void 0 ? _b : getDefaultSlug();
19
+ const permalink = (0, utils_1.normalizeUrl)([params.version.versionPath, slug]);
20
+ return {
21
+ ...category.link,
22
+ slug,
23
+ permalink,
24
+ };
25
+ }
26
+ return category.link;
27
+ }
28
+ function postProcessSidebarItem(item, params) {
29
+ var _a, _b;
30
+ if (item.type === 'category') {
31
+ const category = {
32
+ ...item,
33
+ collapsed: (_a = item.collapsed) !== null && _a !== void 0 ? _a : params.sidebarOptions.sidebarCollapsed,
34
+ collapsible: (_b = item.collapsible) !== null && _b !== void 0 ? _b : params.sidebarOptions.sidebarCollapsible,
35
+ link: normalizeCategoryLink(item, params),
36
+ items: item.items.map((subItem) => postProcessSidebarItem(subItem, params)),
37
+ };
38
+ // If the current category doesn't have subitems, we render a normal link
39
+ // instead.
40
+ if (category.items.length === 0) {
41
+ if (!category.link) {
42
+ throw new Error(`Sidebar category ${item.label} has neither any subitem nor a link. This makes this item not able to link to anything.`);
43
+ }
44
+ switch (category.link.type) {
45
+ case 'doc':
46
+ return {
47
+ type: 'doc',
48
+ label: category.label,
49
+ id: category.link.id,
50
+ };
51
+ case 'generated-index':
52
+ return {
53
+ type: 'link',
54
+ label: category.label,
55
+ href: category.link.permalink,
56
+ };
57
+ default:
58
+ throw new Error('Unexpected sidebar category link type');
59
+ }
60
+ }
61
+ // A non-collapsible category can't be collapsed!
62
+ if (category.collapsible === false) {
63
+ category.collapsed = false;
64
+ }
65
+ return category;
66
+ }
67
+ return item;
68
+ }
69
+ function postProcessSidebars(sidebars, params) {
70
+ return lodash_1.default.mapValues(sidebars, (sidebar) => sidebar.map((item) => postProcessSidebarItem(item, params)));
71
+ }
72
+ exports.postProcessSidebars = postProcessSidebars;
@@ -4,16 +4,5 @@
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 { DocMetadataBase, VersionMetadata } from '../types';
8
- import type { Sidebars, NormalizedSidebars, SidebarItemsGeneratorOption } from './types';
9
- import type { Slugger } from '@docusaurus/utils';
10
- import type { NumberPrefixParser, SidebarOptions } from '@docusaurus/plugin-content-docs';
11
- export declare type SidebarProcessorParams = {
12
- sidebarItemsGenerator: SidebarItemsGeneratorOption;
13
- numberPrefixParser: NumberPrefixParser;
14
- docs: DocMetadataBase[];
15
- version: VersionMetadata;
16
- categoryLabelSlugger: Slugger;
17
- sidebarOptions: SidebarOptions;
18
- };
19
- export declare function processSidebars(unprocessedSidebars: NormalizedSidebars, params: SidebarProcessorParams): Promise<Sidebars>;
7
+ import type { NormalizedSidebars, ProcessedSidebars, SidebarProcessorParams, CategoryMetadataFile } from './types';
8
+ export declare function processSidebars(unprocessedSidebars: NormalizedSidebars, categoriesMetadata: Record<string, CategoryMetadataFile>, params: SidebarProcessorParams): Promise<ProcessedSidebars>;
@@ -8,14 +8,13 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.processSidebars = void 0;
10
10
  const tslib_1 = require("tslib");
11
- const utils_1 = require("./utils");
12
11
  const generator_1 = require("./generator");
13
- const lodash_1 = require("lodash");
12
+ const validation_1 = require("./validation");
13
+ const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
14
14
  const combine_promises_1 = (0, tslib_1.__importDefault)(require("combine-promises"));
15
- const normalization_1 = require("./normalization");
16
15
  const docs_1 = require("../docs");
17
16
  function toSidebarItemsGeneratorDoc(doc) {
18
- return (0, lodash_1.pick)(doc, [
17
+ return lodash_1.default.pick(doc, [
19
18
  'id',
20
19
  'unversionedId',
21
20
  'frontMatter',
@@ -25,24 +24,18 @@ function toSidebarItemsGeneratorDoc(doc) {
25
24
  ]);
26
25
  }
27
26
  function toSidebarItemsGeneratorVersion(version) {
28
- return (0, lodash_1.pick)(version, ['versionName', 'contentPath']);
27
+ return lodash_1.default.pick(version, ['versionName', 'contentPath']);
29
28
  }
30
- // Handle the generation of autogenerated sidebar items and other post-processing checks
31
- async function processSidebar(unprocessedSidebar, params) {
29
+ // Handle the generation of autogenerated sidebar items and other
30
+ // post-processing checks
31
+ async function processSidebar(unprocessedSidebar, categoriesMetadata, params) {
32
32
  const { sidebarItemsGenerator, numberPrefixParser, docs, version, sidebarOptions, } = params;
33
33
  // Just a minor lazy transformation optimization
34
- const getSidebarItemsGeneratorDocsAndVersion = (0, lodash_1.memoize)(() => ({
34
+ const getSidebarItemsGeneratorDocsAndVersion = lodash_1.default.memoize(() => ({
35
35
  docs: docs.map(toSidebarItemsGeneratorDoc),
36
36
  version: toSidebarItemsGeneratorVersion(version),
37
37
  }));
38
- async function processCategoryItem(item) {
39
- return {
40
- ...item,
41
- items: (await Promise.all(item.items.map(processItem))).flat(),
42
- };
43
- }
44
38
  async function processAutoGeneratedItem(item) {
45
- // TODO the returned type can't be trusted in practice (generator can be user-provided)
46
39
  const generatedItems = await sidebarItemsGenerator({
47
40
  item,
48
41
  numberPrefixParser,
@@ -50,15 +43,22 @@ async function processSidebar(unprocessedSidebar, params) {
50
43
  isCategoryIndex: docs_1.isCategoryIndex,
51
44
  ...getSidebarItemsGeneratorDocsAndVersion(),
52
45
  options: sidebarOptions,
46
+ categoriesMetadata,
53
47
  });
54
- // TODO validate generated items: user can generate bad items
55
- const generatedItemsNormalized = generatedItems.flatMap((generatedItem) => (0, normalization_1.normalizeItem)(generatedItem, { ...params, ...sidebarOptions }));
56
- // Process again... weird but sidebar item generated might generate some auto-generated items?
57
- return processItems(generatedItemsNormalized);
48
+ // Process again... weird but sidebar item generated might generate some
49
+ // auto-generated items?
50
+ // TODO repeatedly process & unwrap autogenerated items until there are no
51
+ // more autogenerated items, or when loop count (e.g. 10) is reached
52
+ return processItems(generatedItems);
58
53
  }
59
54
  async function processItem(item) {
60
55
  if (item.type === 'category') {
61
- return [await processCategoryItem(item)];
56
+ return [
57
+ {
58
+ ...item,
59
+ items: (await Promise.all(item.items.map(processItem))).flat(),
60
+ },
61
+ ];
62
62
  }
63
63
  if (item.type === 'autogenerated') {
64
64
  return processAutoGeneratedItem(item);
@@ -69,19 +69,11 @@ async function processSidebar(unprocessedSidebar, params) {
69
69
  return (await Promise.all(items.map(processItem))).flat();
70
70
  }
71
71
  const processedSidebar = await processItems(unprocessedSidebar);
72
- const fixSidebarItemInconsistencies = (item) => {
73
- // A non-collapsible category can't be collapsed!
74
- if (item.type === 'category' && !item.collapsible && item.collapsed) {
75
- return {
76
- ...item,
77
- collapsed: false,
78
- };
79
- }
80
- return item;
81
- };
82
- return (0, utils_1.transformSidebarItems)(processedSidebar, fixSidebarItemInconsistencies);
72
+ return processedSidebar;
83
73
  }
84
- async function processSidebars(unprocessedSidebars, params) {
85
- return (0, combine_promises_1.default)((0, lodash_1.mapValues)(unprocessedSidebars, (unprocessedSidebar) => processSidebar(unprocessedSidebar, params)));
74
+ async function processSidebars(unprocessedSidebars, categoriesMetadata, params) {
75
+ const processedSidebars = await (0, combine_promises_1.default)(lodash_1.default.mapValues(unprocessedSidebars, (unprocessedSidebar) => processSidebar(unprocessedSidebar, categoriesMetadata, params)));
76
+ (0, validation_1.validateSidebars)(processedSidebars);
77
+ return processedSidebars;
86
78
  }
87
79
  exports.processSidebars = processSidebars;