@docusaurus/plugin-content-docs 2.0.0-beta.20 → 2.0.0-beta.21

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 (60) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +1 -1
  2. package/lib/cli.d.ts +1 -1
  3. package/lib/cli.js +8 -13
  4. package/lib/client/docsClientUtils.js +12 -20
  5. package/lib/client/index.js +29 -42
  6. package/lib/docs.d.ts +2 -2
  7. package/lib/index.d.ts +1 -1
  8. package/lib/index.js +3 -3
  9. package/lib/markdown/index.js +1 -1
  10. package/lib/options.d.ts +1 -1
  11. package/lib/options.js +1 -1
  12. package/lib/props.js +1 -1
  13. package/lib/routes.js +1 -1
  14. package/lib/sidebars/generator.js +3 -3
  15. package/lib/sidebars/index.d.ts +1 -1
  16. package/lib/sidebars/index.js +6 -6
  17. package/lib/sidebars/normalization.js +1 -1
  18. package/lib/sidebars/postProcessor.d.ts +3 -0
  19. package/lib/sidebars/postProcessor.js +33 -17
  20. package/lib/sidebars/processor.js +5 -16
  21. package/lib/sidebars/types.d.ts +2 -2
  22. package/lib/sidebars/utils.js +1 -1
  23. package/lib/sidebars/validation.js +5 -1
  24. package/lib/slug.js +1 -1
  25. package/lib/tags.js +1 -1
  26. package/lib/translations.js +8 -8
  27. package/lib/versions/files.d.ts +7 -0
  28. package/lib/versions/files.js +3 -2
  29. package/lib/versions/index.js +1 -1
  30. package/lib/versions/validation.js +1 -1
  31. package/package.json +13 -13
  32. package/src/categoryGeneratedIndex.ts +2 -2
  33. package/src/cli.ts +11 -15
  34. package/src/client/docsClientUtils.ts +1 -1
  35. package/src/client/index.ts +5 -2
  36. package/src/docs.ts +3 -3
  37. package/src/globalData.ts +1 -1
  38. package/src/index.ts +21 -17
  39. package/src/markdown/index.ts +1 -1
  40. package/src/markdown/linkify.ts +1 -1
  41. package/src/options.ts +5 -6
  42. package/src/plugin-content-docs.d.ts +19 -2
  43. package/src/props.ts +3 -3
  44. package/src/routes.ts +3 -3
  45. package/src/sidebars/README.md +1 -0
  46. package/src/sidebars/generator.ts +6 -6
  47. package/src/sidebars/index.ts +7 -7
  48. package/src/sidebars/normalization.ts +3 -3
  49. package/src/sidebars/postProcessor.ts +47 -24
  50. package/src/sidebars/processor.ts +8 -24
  51. package/src/sidebars/types.ts +2 -2
  52. package/src/sidebars/utils.ts +3 -4
  53. package/src/sidebars/validation.ts +6 -2
  54. package/src/slug.ts +1 -1
  55. package/src/tags.ts +1 -1
  56. package/src/translations.ts +8 -9
  57. package/src/types.ts +0 -2
  58. package/src/versions/files.ts +3 -3
  59. package/src/versions/index.ts +1 -1
  60. package/src/versions/validation.ts +3 -1
@@ -5,6 +5,9 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import _ from 'lodash';
9
+ import logger from '@docusaurus/logger';
10
+ import {isCategoriesShorthand} from './utils';
8
11
  import type {
9
12
  NormalizedSidebarItem,
10
13
  NormalizedSidebar,
@@ -16,9 +19,6 @@ import type {
16
19
  SidebarsConfig,
17
20
  NormalizedSidebarItemCategory,
18
21
  } from './types';
19
- import {isCategoriesShorthand} from './utils';
20
- import _ from 'lodash';
21
- import logger from '@docusaurus/logger';
22
22
 
23
23
  function normalizeCategoriesShorthand(
24
24
  sidebar: SidebarCategoriesShorthand,
@@ -5,7 +5,9 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import _ from 'lodash';
8
9
  import {normalizeUrl} from '@docusaurus/utils';
10
+ import {getDocIds} from '../docs';
9
11
  import type {
10
12
  SidebarItem,
11
13
  Sidebars,
@@ -15,12 +17,18 @@ import type {
15
17
  ProcessedSidebars,
16
18
  SidebarItemCategoryLink,
17
19
  } from './types';
18
- import _ from 'lodash';
20
+
21
+ export type SidebarPostProcessorParams = SidebarProcessorParams & {
22
+ draftIds: Set<string>;
23
+ };
19
24
 
20
25
  function normalizeCategoryLink(
21
26
  category: ProcessedSidebarItemCategory,
22
- params: SidebarProcessorParams,
27
+ params: SidebarPostProcessorParams,
23
28
  ): SidebarItemCategoryLink | undefined {
29
+ if (category.link?.type === 'doc' && params.draftIds.has(category.link.id)) {
30
+ return undefined;
31
+ }
24
32
  if (category.link?.type === 'generated-index') {
25
33
  // Default slug logic can be improved
26
34
  const getDefaultSlug = () =>
@@ -38,44 +46,55 @@ function normalizeCategoryLink(
38
46
 
39
47
  function postProcessSidebarItem(
40
48
  item: ProcessedSidebarItem,
41
- params: SidebarProcessorParams,
42
- ): SidebarItem {
49
+ params: SidebarPostProcessorParams,
50
+ ): SidebarItem | null {
43
51
  if (item.type === 'category') {
52
+ // Fail-fast if there's actually no subitems, no because all subitems are
53
+ // drafts. This is likely a configuration mistake.
54
+ if (item.items.length === 0 && !item.link) {
55
+ throw new Error(
56
+ `Sidebar category ${item.label} has neither any subitem nor a link. This makes this item not able to link to anything.`,
57
+ );
58
+ }
44
59
  const category = {
45
60
  ...item,
46
61
  collapsed: item.collapsed ?? params.sidebarOptions.sidebarCollapsed,
47
62
  collapsible: item.collapsible ?? params.sidebarOptions.sidebarCollapsible,
48
63
  link: normalizeCategoryLink(item, params),
49
- items: item.items.map((subItem) =>
50
- postProcessSidebarItem(subItem, params),
51
- ),
64
+ items: item.items
65
+ .map((subItem) => postProcessSidebarItem(subItem, params))
66
+ .filter((v): v is SidebarItem => Boolean(v)),
52
67
  };
53
68
  // If the current category doesn't have subitems, we render a normal link
54
69
  // instead.
55
70
  if (category.items.length === 0) {
56
- if (!category.link) {
57
- throw new Error(
58
- `Sidebar category ${item.label} has neither any subitem nor a link. This makes this item not able to link to anything.`,
59
- );
71
+ // Doesn't make sense to render an empty generated index page, so we
72
+ // filter the entire category out as well.
73
+ if (
74
+ !category.link ||
75
+ category.link.type === 'generated-index' ||
76
+ params.draftIds.has(category.link.id)
77
+ ) {
78
+ return null;
60
79
  }
61
- return category.link.type === 'doc'
62
- ? {
63
- type: 'doc',
64
- label: category.label,
65
- id: category.link.id,
66
- }
67
- : {
68
- type: 'link',
69
- label: category.label,
70
- href: category.link.permalink,
71
- };
80
+ return {
81
+ type: 'doc',
82
+ label: category.label,
83
+ id: category.link.id,
84
+ };
72
85
  }
73
86
  // A non-collapsible category can't be collapsed!
74
- if (category.collapsible === false) {
87
+ if (!category.collapsible) {
75
88
  category.collapsed = false;
76
89
  }
77
90
  return category;
78
91
  }
92
+ if (
93
+ (item.type === 'doc' || item.type === 'ref') &&
94
+ params.draftIds.has(item.id)
95
+ ) {
96
+ return null;
97
+ }
79
98
  return item;
80
99
  }
81
100
 
@@ -83,7 +102,11 @@ export function postProcessSidebars(
83
102
  sidebars: ProcessedSidebars,
84
103
  params: SidebarProcessorParams,
85
104
  ): Sidebars {
105
+ const draftIds = new Set(params.drafts.flatMap(getDocIds));
106
+
86
107
  return _.mapValues(sidebars, (sidebar) =>
87
- sidebar.map((item) => postProcessSidebarItem(item, params)),
108
+ sidebar
109
+ .map((item) => postProcessSidebarItem(item, {...params, draftIds}))
110
+ .filter((v): v is SidebarItem => Boolean(v)),
88
111
  );
89
112
  }
@@ -5,6 +5,11 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import _ from 'lodash';
9
+ import combinePromises from 'combine-promises';
10
+ import {DefaultSidebarItemsGenerator} from './generator';
11
+ import {validateSidebars} from './validation';
12
+ import {isCategoryIndex} from '../docs';
8
13
  import type {
9
14
  DocMetadataBase,
10
15
  VersionMetadata,
@@ -22,11 +27,6 @@ import type {
22
27
  SidebarProcessorParams,
23
28
  CategoryMetadataFile,
24
29
  } from './types';
25
- import {DefaultSidebarItemsGenerator} from './generator';
26
- import {validateSidebars} from './validation';
27
- import _ from 'lodash';
28
- import combinePromises from 'combine-promises';
29
- import {getDocIds, isCategoryIndex} from '../docs';
30
30
 
31
31
  function toSidebarItemsGeneratorDoc(
32
32
  doc: DocMetadataBase,
@@ -55,8 +55,7 @@ async function processSidebar(
55
55
  categoriesMetadata: {[filePath: string]: CategoryMetadataFile},
56
56
  params: SidebarProcessorParams,
57
57
  ): Promise<ProcessedSidebar> {
58
- const {sidebarItemsGenerator, numberPrefixParser, docs, drafts, version} =
59
- params;
58
+ const {sidebarItemsGenerator, numberPrefixParser, docs, version} = params;
60
59
 
61
60
  // Just a minor lazy transformation optimization
62
61
  const getSidebarItemsGeneratorDocsAndVersion = _.memoize(() => ({
@@ -82,19 +81,6 @@ async function processSidebar(
82
81
  return processItems(generatedItems);
83
82
  }
84
83
 
85
- const draftIds = new Set(drafts.flatMap(getDocIds));
86
-
87
- const isDraftItem = (item: NormalizedSidebarItem): boolean => {
88
- if (item.type === 'doc' || item.type === 'ref') {
89
- return draftIds.has(item.id);
90
- }
91
- // If a category only contains draft items, it should be filtered entirely.
92
- if (item.type === 'category') {
93
- return item.items.every(isDraftItem);
94
- }
95
- return false;
96
- };
97
-
98
84
  async function processItem(
99
85
  item: NormalizedSidebarItem,
100
86
  ): Promise<ProcessedSidebarItem[]> {
@@ -102,7 +88,7 @@ async function processSidebar(
102
88
  return [
103
89
  {
104
90
  ...item,
105
- items: await processItems(item.items),
91
+ items: (await Promise.all(item.items.map(processItem))).flat(),
106
92
  },
107
93
  ];
108
94
  }
@@ -115,9 +101,7 @@ async function processSidebar(
115
101
  async function processItems(
116
102
  items: NormalizedSidebarItem[],
117
103
  ): Promise<ProcessedSidebarItem[]> {
118
- return (
119
- await Promise.all(items.filter((i) => !isDraftItem(i)).map(processItem))
120
- ).flat();
104
+ return (await Promise.all(items.map(processItem))).flat();
121
105
  }
122
106
 
123
107
  const processedSidebar = await processItems(unprocessedSidebar);
@@ -251,7 +251,7 @@ export type SidebarItemsGeneratorArgs = {
251
251
  };
252
252
  export type SidebarItemsGenerator = (
253
253
  generatorArgs: SidebarItemsGeneratorArgs,
254
- ) => Promise<NormalizedSidebar>;
254
+ ) => NormalizedSidebar | Promise<NormalizedSidebar>;
255
255
 
256
256
  export type SidebarItemsGeneratorOption = (
257
257
  generatorArgs: {
@@ -262,7 +262,7 @@ export type SidebarItemsGeneratorOption = (
262
262
  */
263
263
  defaultSidebarItemsGenerator: SidebarItemsGenerator;
264
264
  } & SidebarItemsGeneratorArgs,
265
- ) => Promise<NormalizedSidebarItem[]>;
265
+ ) => NormalizedSidebar | Promise<NormalizedSidebar>;
266
266
 
267
267
  export type SidebarProcessorParams = {
268
268
  sidebarItemsGenerator: SidebarItemsGeneratorOption;
@@ -5,6 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import _ from 'lodash';
9
+ import {toMessageRelativeFilePath} from '@docusaurus/utils';
8
10
  import type {
9
11
  Sidebars,
10
12
  Sidebar,
@@ -18,9 +20,6 @@ import type {
18
20
  SidebarItemCategoryWithGeneratedIndex,
19
21
  SidebarNavigationItem,
20
22
  } from './types';
21
-
22
- import _ from 'lodash';
23
- import {toMessageRelativeFilePath} from '@docusaurus/utils';
24
23
  import type {
25
24
  DocMetadataBase,
26
25
  PropNavigationLink,
@@ -258,7 +257,7 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils {
258
257
  ): boolean {
259
258
  return (
260
259
  item.type === 'category' &&
261
- item.link?.type === 'generated-index' &&
260
+ item.link.type === 'generated-index' &&
262
261
  item.link.permalink === categoryGeneratedIndexPermalink
263
262
  );
264
263
  }
@@ -144,7 +144,7 @@ function validateSidebarItem(
144
144
  // manually
145
145
  Joi.assert(item, sidebarItemSchema);
146
146
 
147
- if ((item as NormalizedSidebarItemCategory).type === 'category') {
147
+ if ((item as NormalizedSidebarItem).type === 'category') {
148
148
  (item as NormalizedSidebarItemCategory).items.forEach(validateSidebarItem);
149
149
  }
150
150
  }
@@ -170,5 +170,9 @@ const categoryMetadataFileSchema = Joi.object<CategoryMetadataFile>({
170
170
  export function validateCategoryMetadataFile(
171
171
  unsafeContent: unknown,
172
172
  ): CategoryMetadataFile {
173
- return Joi.attempt(unsafeContent, categoryMetadataFileSchema);
173
+ const {error, value} = categoryMetadataFileSchema.validate(unsafeContent);
174
+ if (error) {
175
+ throw error;
176
+ }
177
+ return value;
174
178
  }
package/src/slug.ts CHANGED
@@ -58,7 +58,7 @@ export default function getSlug({
58
58
  ) {
59
59
  return dirNameSlug;
60
60
  }
61
- const baseSlug = frontMatterSlug || baseID;
61
+ const baseSlug = frontMatterSlug ?? baseID;
62
62
  return resolvePathname(baseSlug, getDirNameSlug());
63
63
  }
64
64
 
package/src/tags.ts CHANGED
@@ -5,10 +5,10 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import _ from 'lodash';
8
9
  import {groupTaggedItems} from '@docusaurus/utils';
9
10
  import type {VersionTags} from './types';
10
11
  import type {DocMetadata} from '@docusaurus/plugin-content-docs';
11
- import _ from 'lodash';
12
12
 
13
13
  export function getVersionTags(docs: DocMetadata[]): VersionTags {
14
14
  const groups = groupTaggedItems(docs, (doc) => doc.tags);
@@ -5,6 +5,14 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import _ from 'lodash';
9
+ import {mergeTranslations} from '@docusaurus/utils';
10
+ import {CURRENT_VERSION_NAME} from './constants';
11
+ import {
12
+ collectSidebarCategories,
13
+ transformSidebarItems,
14
+ collectSidebarLinks,
15
+ } from './sidebars/utils';
8
16
  import type {
9
17
  LoadedVersion,
10
18
  LoadedContent,
@@ -15,20 +23,11 @@ import type {
15
23
  SidebarItemCategoryLink,
16
24
  Sidebars,
17
25
  } from './sidebars/types';
18
-
19
- import _ from 'lodash';
20
- import {
21
- collectSidebarCategories,
22
- transformSidebarItems,
23
- collectSidebarLinks,
24
- } from './sidebars/utils';
25
26
  import type {
26
27
  TranslationFileContent,
27
28
  TranslationFile,
28
29
  TranslationMessage,
29
30
  } from '@docusaurus/types';
30
- import {mergeTranslations} from '@docusaurus/utils';
31
- import {CURRENT_VERSION_NAME} from './constants';
32
31
 
33
32
  function getVersionFileName(versionName: string): string {
34
33
  if (versionName === CURRENT_VERSION_NAME) {
package/src/types.ts CHANGED
@@ -5,8 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- /// <reference types="@docusaurus/module-type-aliases" />
9
-
10
8
  import type {BrokenMarkdownLink, Tag} from '@docusaurus/utils';
11
9
  import type {
12
10
  VersionMetadata,
@@ -7,6 +7,7 @@
7
7
 
8
8
  import path from 'path';
9
9
  import fs from 'fs-extra';
10
+ import {getPluginI18nPath, DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
10
11
  import {
11
12
  VERSIONS_JSON_FILE,
12
13
  VERSIONED_DOCS_DIR,
@@ -14,7 +15,6 @@ import {
14
15
  CURRENT_VERSION_NAME,
15
16
  } from '../constants';
16
17
  import {validateVersionNames} from './validation';
17
- import {getPluginI18nPath, DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
18
18
  import type {
19
19
  PluginOptions,
20
20
  VersionMetadata,
@@ -89,13 +89,13 @@ export function getVersionsFilePath(siteDir: string, pluginId: string): string {
89
89
  * @throws Throws if validation fails, i.e. `versions.json` doesn't contain an
90
90
  * array of valid version names.
91
91
  */
92
- async function readVersionsFile(
92
+ export async function readVersionsFile(
93
93
  siteDir: string,
94
94
  pluginId: string,
95
95
  ): Promise<string[] | null> {
96
96
  const versionsFilePath = getVersionsFilePath(siteDir, pluginId);
97
97
  if (await fs.pathExists(versionsFilePath)) {
98
- const content = await fs.readJSON(versionsFilePath);
98
+ const content: unknown = await fs.readJSON(versionsFilePath);
99
99
  validateVersionNames(content);
100
100
  return content;
101
101
  }
@@ -6,8 +6,8 @@
6
6
  */
7
7
 
8
8
  import path from 'path';
9
- import {CURRENT_VERSION_NAME} from '../constants';
10
9
  import {normalizeUrl, posixPath} from '@docusaurus/utils';
10
+ import {CURRENT_VERSION_NAME} from '../constants';
11
11
  import {validateVersionsOptions} from './validation';
12
12
  import {
13
13
  getDocsDirPathLocalized,
@@ -11,7 +11,9 @@ import type {VersionsOptions} from '@docusaurus/plugin-content-docs';
11
11
  export function validateVersionName(name: unknown): asserts name is string {
12
12
  if (typeof name !== 'string') {
13
13
  throw new Error(
14
- `Versions should be strings. Found type "${typeof name}" for version "${name}".`,
14
+ `Versions should be strings. Found type "${typeof name}" for version ${JSON.stringify(
15
+ name,
16
+ )}.`,
15
17
  );
16
18
  }
17
19
  if (!name.trim()) {