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

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 (197) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +2 -2
  2. package/lib/categoryGeneratedIndex.js +2 -0
  3. package/lib/cli.d.ts +1 -1
  4. package/lib/cli.js +2 -1
  5. package/lib/client/docsClientUtils.d.ts +3 -22
  6. package/lib/client/docsClientUtils.js +5 -1
  7. package/lib/{theme/hooks/useDocs.d.ts → client/globalDataHooks.d.ts} +1 -2
  8. package/lib/{theme/hooks/useDocs.js → client/globalDataHooks.js} +2 -1
  9. package/{src/__tests__/__fixtures__/simple-site/docusaurus.config.js → lib/client/index.d.ts} +1 -8
  10. package/{src/__tests__/__fixtures__/site-with-doc-label/docusaurus.config.js → lib/client/index.js} +4 -8
  11. package/lib/docFrontMatter.js +1 -0
  12. package/lib/docs.d.ts +19 -6
  13. package/lib/docs.js +43 -22
  14. package/lib/globalData.d.ts +5 -1
  15. package/lib/globalData.js +34 -2
  16. package/lib/index.d.ts +3 -2
  17. package/lib/index.js +4 -10
  18. package/lib/lastUpdate.js +6 -5
  19. package/lib/markdown/index.d.ts +1 -1
  20. package/lib/markdown/linkify.d.ts +1 -1
  21. package/lib/numberPrefix.d.ts +1 -1
  22. package/lib/options.d.ts +1 -1
  23. package/lib/options.js +2 -2
  24. package/lib/routes.d.ts +4 -3
  25. package/lib/routes.js +8 -5
  26. package/lib/sidebars/generator.js +15 -17
  27. package/lib/sidebars/index.d.ts +3 -2
  28. package/lib/sidebars/processor.d.ts +3 -2
  29. package/lib/sidebars/processor.js +2 -0
  30. package/lib/sidebars/types.d.ts +8 -3
  31. package/lib/sidebars/utils.d.ts +12 -4
  32. package/lib/sidebars/utils.js +48 -3
  33. package/lib/sidebars/validation.d.ts +1 -1
  34. package/lib/sidebars/validation.js +4 -0
  35. package/lib/slug.d.ts +5 -4
  36. package/lib/slug.js +8 -7
  37. package/lib/translations.js +1 -1
  38. package/lib/types.d.ts +7 -78
  39. package/lib/versions.d.ts +3 -2
  40. package/lib/versions.js +27 -32
  41. package/package.json +14 -12
  42. package/src/categoryGeneratedIndex.ts +5 -3
  43. package/src/cli.ts +6 -2
  44. package/src/client/docsClientUtils.ts +22 -35
  45. package/src/{theme/hooks/useDocs.ts → client/globalDataHooks.ts} +6 -2
  46. package/src/{__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars2.js → client/index.ts} +1 -9
  47. package/src/docFrontMatter.ts +2 -1
  48. package/src/docs.ts +77 -42
  49. package/src/globalData.ts +49 -3
  50. package/src/index.ts +11 -21
  51. package/src/lastUpdate.ts +6 -5
  52. package/src/markdown/index.ts +1 -1
  53. package/src/markdown/linkify.ts +1 -1
  54. package/src/numberPrefix.ts +1 -1
  55. package/src/options.ts +3 -7
  56. package/src/plugin-content-docs.d.ts +128 -18
  57. package/src/routes.ts +21 -11
  58. package/src/sidebars/generator.ts +28 -31
  59. package/src/sidebars/index.ts +3 -2
  60. package/src/sidebars/normalization.ts +2 -1
  61. package/src/sidebars/processor.ts +8 -7
  62. package/src/sidebars/types.ts +9 -5
  63. package/src/sidebars/utils.ts +76 -8
  64. package/src/sidebars/validation.ts +6 -1
  65. package/src/slug.ts +15 -11
  66. package/src/translations.ts +2 -2
  67. package/src/types.ts +12 -98
  68. package/src/versions.ts +51 -47
  69. package/lib/.tsbuildinfo +0 -1
  70. package/src/__tests__/__fixtures__/bad-id-site/docs/invalid-id.md +0 -5
  71. package/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md +0 -5
  72. package/src/__tests__/__fixtures__/empty-site/docusaurus.config.js +0 -16
  73. package/src/__tests__/__fixtures__/empty-site/sidebars.json +0 -1
  74. package/src/__tests__/__fixtures__/simple-site/docs/_partials/somePartial.md +0 -3
  75. package/src/__tests__/__fixtures__/simple-site/docs/_partials/subfolder/somePartial.md +0 -3
  76. package/src/__tests__/__fixtures__/simple-site/docs/_somePartial.md +0 -3
  77. package/src/__tests__/__fixtures__/simple-site/docs/foo/bar.md +0 -69
  78. package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +0 -75
  79. package/src/__tests__/__fixtures__/simple-site/docs/headingAsTitle.md +0 -1
  80. package/src/__tests__/__fixtures__/simple-site/docs/hello.md +0 -55
  81. package/src/__tests__/__fixtures__/simple-site/docs/ipsum.md +0 -5
  82. package/src/__tests__/__fixtures__/simple-site/docs/lorem.md +0 -6
  83. package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +0 -7
  84. package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +0 -7
  85. package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +0 -7
  86. package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +0 -7
  87. package/src/__tests__/__fixtures__/simple-site/docs/slugs/absoluteSlug.md +0 -5
  88. package/src/__tests__/__fixtures__/simple-site/docs/slugs/relativeSlug.md +0 -5
  89. package/src/__tests__/__fixtures__/simple-site/docs/slugs/resolvedSlug.md +0 -5
  90. package/src/__tests__/__fixtures__/simple-site/docs/slugs/tryToEscapeSlug.md +0 -5
  91. package/src/__tests__/__fixtures__/simple-site/sidebars.json +0 -37
  92. package/src/__tests__/__fixtures__/simple-site/wrong-sidebars.json +0 -7
  93. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/0-getting-started.md +0 -3
  94. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/1-installation.md +0 -3
  95. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/00_api-overview.md +0 -3
  96. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/0 --- Client API.md +0 -1
  97. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/1 --- Server API.md +0 -1
  98. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/0. Plugin API.md +0 -1
  99. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/1. Theme API.md +0 -1
  100. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/_category_.yml +0 -1
  101. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/03_api-end.md +0 -3
  102. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/_category_.json +0 -3
  103. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/0-guide2.5.md +0 -8
  104. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/02-guide2.md +0 -7
  105. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/_category_.json +0 -3
  106. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/a-guide4.md +0 -7
  107. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/b-guide5.md +0 -7
  108. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/guide3.md +0 -8
  109. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/z-guide1.md +0 -8
  110. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docusaurus.config.js +0 -14
  111. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars.js +0 -23
  112. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-1.md +0 -8
  113. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md +0 -8
  114. package/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json +0 -14
  115. package/src/__tests__/__fixtures__/versioned-site/community/team.md +0 -1
  116. package/src/__tests__/__fixtures__/versioned-site/community_sidebars.json +0 -3
  117. package/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md +0 -1
  118. package/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json +0 -3
  119. package/src/__tests__/__fixtures__/versioned-site/community_versions.json +0 -1
  120. package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +0 -10
  121. package/src/__tests__/__fixtures__/versioned-site/docs/hello.md +0 -4
  122. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/absoluteSlug.md +0 -5
  123. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/relativeSlug.md +0 -5
  124. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/resolvedSlug.md +0 -5
  125. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/tryToEscapeSlug.md +0 -5
  126. package/src/__tests__/__fixtures__/versioned-site/docusaurus.config.js +0 -18
  127. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -4
  128. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs-community/current/team.md +0 -5
  129. package/src/__tests__/__fixtures__/versioned-site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -4
  130. package/src/__tests__/__fixtures__/versioned-site/sidebars.json +0 -10
  131. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/bar.md +0 -4
  132. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/baz.md +0 -1
  133. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/hello.md +0 -4
  134. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_partials/somePartial.md +0 -3
  135. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_partials/subfolder/somePartial.md +0 -3
  136. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_somePartial.md +0 -3
  137. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/foo/bar.md +0 -1
  138. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/hello.md +0 -4
  139. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md +0 -5
  140. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootRelativeSlug.md +0 -5
  141. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootResolvedSlug.md +0 -5
  142. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md +0 -5
  143. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md +0 -5
  144. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/relativeSlug.md +0 -5
  145. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md +0 -5
  146. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md +0 -5
  147. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.0-sidebars.json +0 -11
  148. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.1-sidebars.json +0 -10
  149. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-withSlugs-sidebars.json +0 -5
  150. package/src/__tests__/__fixtures__/versioned-site/versions.json +0 -5
  151. package/src/__tests__/__snapshots__/cli.test.ts.snap +0 -65
  152. package/src/__tests__/__snapshots__/docs.test.ts.snap +0 -140
  153. package/src/__tests__/__snapshots__/index.test.ts.snap +0 -2550
  154. package/src/__tests__/__snapshots__/translations.test.ts.snap +0 -514
  155. package/src/__tests__/cli.test.ts +0 -337
  156. package/src/__tests__/docFrontMatter.test.ts +0 -359
  157. package/src/__tests__/docs.test.ts +0 -1039
  158. package/src/__tests__/index.test.ts +0 -1910
  159. package/src/__tests__/lastUpdate.test.ts +0 -69
  160. package/src/__tests__/numberPrefix.test.ts +0 -199
  161. package/src/__tests__/options.test.ts +0 -276
  162. package/src/__tests__/props.test.ts +0 -62
  163. package/src/__tests__/slug.test.ts +0 -216
  164. package/src/__tests__/translations.test.ts +0 -164
  165. package/src/__tests__/versions.test.ts +0 -744
  166. package/src/client/__tests__/docsClientUtils.test.ts +0 -371
  167. package/src/markdown/__tests__/__fixtures__/docs/doc-localized.md +0 -1
  168. package/src/markdown/__tests__/__fixtures__/docs/doc1.md +0 -13
  169. package/src/markdown/__tests__/__fixtures__/docs/doc2.md +0 -12
  170. package/src/markdown/__tests__/__fixtures__/docs/doc4.md +0 -19
  171. package/src/markdown/__tests__/__fixtures__/docs/doc5.md +0 -6
  172. package/src/markdown/__tests__/__fixtures__/docs/subdir/doc3.md +0 -3
  173. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/doc2.md +0 -7
  174. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/subdir/doc1.md +0 -3
  175. package/src/markdown/__tests__/__snapshots__/linkify.test.ts.snap +0 -82
  176. package/src/markdown/__tests__/linkify.test.ts +0 -190
  177. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -34
  178. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -11
  179. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -11
  180. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-category.js +0 -44
  181. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -20
  182. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-collapsed.json +0 -21
  183. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -10
  184. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-first-level-not-category.js +0 -20
  185. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -11
  186. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -11
  187. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-link.json +0 -11
  188. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-unknown-type.json +0 -14
  189. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars-wrong-field.json +0 -20
  190. package/src/sidebars/__tests__/__fixtures__/sidebars/sidebars.json +0 -20
  191. package/src/sidebars/__tests__/__snapshots__/index.test.ts.snap +0 -248
  192. package/src/sidebars/__tests__/generator.test.ts +0 -461
  193. package/src/sidebars/__tests__/index.test.ts +0 -204
  194. package/src/sidebars/__tests__/processor.test.ts +0 -237
  195. package/src/sidebars/__tests__/utils.test.ts +0 -695
  196. package/src/sidebars/__tests__/validation.test.ts +0 -105
  197. package/tsconfig.json +0 -9
@@ -5,14 +5,13 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import type {Optional} from 'utility-types';
8
+ import type {Optional, Required} from 'utility-types';
9
+ import type {DocMetadataBase, VersionMetadata} from '../types';
9
10
  import type {
10
- DocMetadataBase,
11
- VersionMetadata,
12
11
  NumberPrefixParser,
13
12
  SidebarOptions,
14
- } from '../types';
15
- import {Required} from 'utility-types';
13
+ CategoryIndexMatcher,
14
+ } from '@docusaurus/plugin-content-docs';
16
15
 
17
16
  // Makes all properties visible when hovering over the type
18
17
  type Expand<T extends Record<string, unknown>> = {[P in keyof T]: T[P]};
@@ -53,6 +52,8 @@ export type SidebarItemCategoryLinkGeneratedIndexConfig = {
53
52
  slug?: string;
54
53
  title?: string;
55
54
  description?: string;
55
+ image?: string;
56
+ keywords?: string | readonly string[];
56
57
  };
57
58
  export type SidebarItemCategoryLinkGeneratedIndex = {
58
59
  type: 'generated-index';
@@ -60,6 +61,8 @@ export type SidebarItemCategoryLinkGeneratedIndex = {
60
61
  permalink: string;
61
62
  title?: string;
62
63
  description?: string;
64
+ image?: string;
65
+ keywords?: string | readonly string[];
63
66
  };
64
67
 
65
68
  export type SidebarItemCategoryLinkConfig =
@@ -193,6 +196,7 @@ export type SidebarItemsGeneratorArgs = {
193
196
  version: SidebarItemsGeneratorVersion;
194
197
  docs: SidebarItemsGeneratorDoc[];
195
198
  numberPrefixParser: NumberPrefixParser;
199
+ isCategoryIndex: CategoryIndexMatcher;
196
200
  options: SidebarOptions;
197
201
  };
198
202
  export type SidebarItemsGenerator = (
@@ -15,17 +15,15 @@ import type {
15
15
  SidebarItemType,
16
16
  SidebarCategoriesShorthand,
17
17
  SidebarItemConfig,
18
- } from './types';
19
-
20
- import {mapValues, difference, uniq} from 'lodash';
21
- import {getElementsAround, toMessageRelativeFilePath} from '@docusaurus/utils';
22
- import {DocMetadataBase, DocNavLink} from '../types';
23
- import {
24
18
  SidebarItemCategoryWithGeneratedIndex,
25
19
  SidebarItemCategoryWithLink,
26
20
  SidebarNavigationItem,
27
21
  } from './types';
28
22
 
23
+ import {mapValues, difference, uniq} from 'lodash';
24
+ import {getElementsAround, toMessageRelativeFilePath} from '@docusaurus/utils';
25
+ import type {DocMetadataBase, DocNavLink} from '../types';
26
+
29
27
  export function isCategoriesShorthand(
30
28
  item: SidebarItemConfig,
31
29
  ): item is SidebarCategoriesShorthand {
@@ -133,11 +131,24 @@ export type SidebarsUtils = {
133
131
  getDocNavigation: (
134
132
  unversionedId: string,
135
133
  versionedId: string,
134
+ displayedSidebar: string | null | undefined,
136
135
  ) => SidebarNavigation;
137
136
  getCategoryGeneratedIndexList: () => SidebarItemCategoryWithGeneratedIndex[];
138
137
  getCategoryGeneratedIndexNavigation: (
139
138
  categoryGeneratedIndexPermalink: string,
140
139
  ) => SidebarNavigation;
140
+ getFirstLink: (sidebarId: string) =>
141
+ | {
142
+ type: 'doc';
143
+ id: string;
144
+ label: string;
145
+ }
146
+ | {
147
+ type: 'generated-index';
148
+ slug: string;
149
+ label: string;
150
+ }
151
+ | undefined;
141
152
 
142
153
  checkSidebarsDocIds: (validDocIds: string[], sidebarFilePath: string) => void;
143
154
  };
@@ -172,16 +183,25 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils {
172
183
  function getDocNavigation(
173
184
  unversionedId: string,
174
185
  versionedId: string,
186
+ displayedSidebar: string | null | undefined,
175
187
  ): SidebarNavigation {
176
188
  // TODO legacy id retro-compatibility!
177
189
  let docId = unversionedId;
178
- let sidebarName = getSidebarNameByDocId(docId);
179
- if (!sidebarName) {
190
+ let sidebarName =
191
+ displayedSidebar === undefined
192
+ ? getSidebarNameByDocId(docId)
193
+ : displayedSidebar;
194
+ if (sidebarName === undefined) {
180
195
  docId = versionedId;
181
196
  sidebarName = getSidebarNameByDocId(docId);
182
197
  }
183
198
 
184
199
  if (sidebarName) {
200
+ if (!sidebarNameToNavigationItems[sidebarName]) {
201
+ throw new Error(
202
+ `Doc with ID ${docId} wants to display sidebar ${sidebarName} but a sidebar with this name doesn't exist`,
203
+ );
204
+ }
185
205
  const navigationItems = sidebarNameToNavigationItems[sidebarName];
186
206
  const currentItemIndex = navigationItems.findIndex((item) => {
187
207
  if (item.type === 'doc') {
@@ -192,6 +212,9 @@ export function createSidebarsUtils(sidebars: Sidebars): SidebarsUtils {
192
212
  }
193
213
  return false;
194
214
  });
215
+ if (currentItemIndex === -1) {
216
+ return {sidebarName, next: undefined, previous: undefined};
217
+ }
195
218
 
196
219
  const {previous, next} = getElementsAround(
197
220
  navigationItems,
@@ -266,6 +289,50 @@ Available document ids are:
266
289
  }
267
290
  }
268
291
 
292
+ function getFirstLink(sidebar: Sidebar):
293
+ | {
294
+ type: 'doc';
295
+ id: string;
296
+ label: string;
297
+ }
298
+ | {
299
+ type: 'generated-index';
300
+ slug: string;
301
+ label: string;
302
+ }
303
+ | undefined {
304
+ // eslint-disable-next-line no-restricted-syntax
305
+ for (const item of sidebar) {
306
+ if (item.type === 'doc') {
307
+ return {
308
+ type: 'doc',
309
+ id: item.id,
310
+ label: item.label ?? item.id,
311
+ };
312
+ } else if (item.type === 'category') {
313
+ if (item.link?.type === 'doc') {
314
+ return {
315
+ type: 'doc',
316
+ id: item.link.id,
317
+ label: item.label,
318
+ };
319
+ } else if (item.link?.type === 'generated-index') {
320
+ return {
321
+ type: 'generated-index',
322
+ slug: item.link.slug,
323
+ label: item.label,
324
+ };
325
+ } else {
326
+ const firstSubItem = getFirstLink(item.items);
327
+ if (firstSubItem) {
328
+ return firstSubItem;
329
+ }
330
+ }
331
+ }
332
+ }
333
+ return undefined;
334
+ }
335
+
269
336
  return {
270
337
  sidebars,
271
338
  getFirstDocIdOfFirstSidebar,
@@ -274,6 +341,7 @@ Available document ids are:
274
341
  getCategoryGeneratedIndexList,
275
342
  getCategoryGeneratedIndexNavigation,
276
343
  checkSidebarsDocIds,
344
+ getFirstLink: (id) => getFirstLink(sidebars[id]),
277
345
  };
278
346
  }
279
347
 
@@ -20,7 +20,10 @@ import type {
20
20
  SidebarItemCategoryLinkGeneratedIndex,
21
21
  } from './types';
22
22
  import {isCategoriesShorthand} from './utils';
23
- import {CategoryMetadataFile} from './generator';
23
+ import type {CategoryMetadataFile} from './generator';
24
+
25
+ // NOTE: we don't add any default values during validation on purpose!
26
+ // Config types are exposed to users for typechecking and we use the same type in normalization
24
27
 
25
28
  const sidebarItemBaseSchema = Joi.object<SidebarItemBase>({
26
29
  className: Joi.string(),
@@ -70,6 +73,8 @@ const sidebarItemCategoryLinkSchema = Joi.object<SidebarItemCategoryLink>()
70
73
  // permalink: Joi.string().optional(), // No, this one is not in the user config, only in the normalized version
71
74
  title: Joi.string().optional(),
72
75
  description: Joi.string().optional(),
76
+ image: Joi.string().optional(),
77
+ keywords: [Joi.string(), Joi.array().items(Joi.string())],
73
78
  }),
74
79
  },
75
80
  {
package/src/slug.ts CHANGED
@@ -15,20 +15,21 @@ import {
15
15
  DefaultNumberPrefixParser,
16
16
  stripPathNumberPrefixes,
17
17
  } from './numberPrefix';
18
- import type {DocMetadataBase, NumberPrefixParser} from './types';
19
- import {isConventionalDocIndex} from './docs';
18
+ import type {DocMetadataBase} from './types';
19
+ import {isCategoryIndex, toCategoryIndexMatcherParam} from './docs';
20
+ import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs';
20
21
 
21
22
  export default function getSlug({
22
23
  baseID,
23
- frontmatterSlug,
24
+ frontMatterSlug,
24
25
  source,
25
26
  sourceDirName,
26
27
  stripDirNumberPrefixes = true,
27
28
  numberPrefixParser = DefaultNumberPrefixParser,
28
29
  }: {
29
30
  baseID: string;
30
- frontmatterSlug?: string;
31
- source: DocMetadataBase['slug'];
31
+ frontMatterSlug?: string;
32
+ source: DocMetadataBase['source'];
32
33
  sourceDirName: DocMetadataBase['sourceDirName'];
33
34
  stripDirNumberPrefixes?: boolean;
34
35
  numberPrefixParser?: NumberPrefixParser;
@@ -45,14 +46,17 @@ export default function getSlug({
45
46
  }
46
47
 
47
48
  function computeSlug(): string {
48
- if (frontmatterSlug?.startsWith('/')) {
49
- return frontmatterSlug;
49
+ if (frontMatterSlug?.startsWith('/')) {
50
+ return frontMatterSlug;
50
51
  } else {
51
52
  const dirNameSlug = getDirNameSlug();
52
- if (!frontmatterSlug && isConventionalDocIndex({source, sourceDirName})) {
53
+ if (
54
+ !frontMatterSlug &&
55
+ isCategoryIndex(toCategoryIndexMatcherParam({source, sourceDirName}))
56
+ ) {
53
57
  return dirNameSlug;
54
58
  }
55
- const baseSlug = frontmatterSlug || baseID;
59
+ const baseSlug = frontMatterSlug || baseID;
56
60
  return resolvePathname(baseSlug, getDirNameSlug());
57
61
  }
58
62
  }
@@ -62,8 +66,8 @@ export default function getSlug({
62
66
  throw new Error(
63
67
  `We couldn't compute a valid slug for document with id "${baseID}" in "${sourceDirName}" directory.
64
68
  The slug we computed looks invalid: ${slug}.
65
- Maybe your slug frontmatter is incorrect or you use weird chars in the file path?
66
- By using the slug frontmatter, you should be able to fix this error, by using the slug of your choice:
69
+ Maybe your slug front matter is incorrect or you use weird chars in the file path?
70
+ By using the slug front matter, you should be able to fix this error, by using the slug of your choice:
67
71
 
68
72
  Example =>
69
73
  ---
@@ -23,10 +23,10 @@ import type {
23
23
  TranslationFileContent,
24
24
  TranslationFile,
25
25
  TranslationFiles,
26
+ TranslationMessage,
26
27
  } from '@docusaurus/types';
27
28
  import {mergeTranslations} from '@docusaurus/utils';
28
29
  import {CURRENT_VERSION_NAME} from './constants';
29
- import {TranslationMessage} from '@docusaurus/types';
30
30
 
31
31
  function getVersionFileName(versionName: string): string {
32
32
  if (versionName === CURRENT_VERSION_NAME) {
@@ -57,7 +57,7 @@ function getNormalizedSidebarName({
57
57
 
58
58
  /*
59
59
  // Do we need to translate doc metadata?
60
- // It seems translating frontmatter labels is good enough
60
+ // It seems translating front matter labels is good enough
61
61
  function getDocTranslations(doc: DocMetadata): TranslationFileContent {
62
62
  return {
63
63
  [`${doc.unversionedId}.title`]: {
package/src/types.ts CHANGED
@@ -7,13 +7,16 @@
7
7
 
8
8
  /// <reference types="@docusaurus/module-type-aliases" />
9
9
 
10
- import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
10
+ import type {Sidebars} from './sidebars/types';
11
11
  import type {Tag, FrontMatterTag, Slugger} from '@docusaurus/utils';
12
12
  import type {
13
13
  BrokenMarkdownLink as IBrokenMarkdownLink,
14
14
  ContentPaths,
15
15
  } from '@docusaurus/utils/lib/markdownLinks';
16
- import type {SidebarItemsGeneratorOption, Sidebars} from './sidebars/types';
16
+ import type {
17
+ VersionBanner,
18
+ SidebarOptions,
19
+ } from '@docusaurus/plugin-content-docs';
17
20
 
18
21
  export type DocFile = {
19
22
  contentPath: string; // /!\ may be localized
@@ -23,10 +26,8 @@ export type DocFile = {
23
26
  lastUpdate: LastUpdateData;
24
27
  };
25
28
 
26
- export type VersionName = string;
27
-
28
29
  export type VersionMetadata = ContentPaths & {
29
- versionName: VersionName; // 1.0.0
30
+ versionName: string; // 1.0.0
30
31
  versionLabel: string; // Version 1.0.0
31
32
  versionPath: string; // /baseUrl/docs/1.0.0
32
33
  tagsPath: string;
@@ -40,76 +41,11 @@ export type VersionMetadata = ContentPaths & {
40
41
  routePriority: number | undefined; // -1 for the latest docs
41
42
  };
42
43
 
43
- export type EditUrlFunction = (editUrlParams: {
44
- version: string;
45
- versionDocsDirPath: string;
46
- docPath: string;
47
- permalink: string;
48
- locale: string;
49
- }) => string | undefined;
50
-
51
- export type MetadataOptions = {
52
- routeBasePath: string;
53
- editUrl?: string | EditUrlFunction;
54
- editCurrentVersion: boolean;
55
- editLocalizedFiles: boolean;
56
- showLastUpdateTime?: boolean;
57
- showLastUpdateAuthor?: boolean;
58
- numberPrefixParser: NumberPrefixParser;
59
- };
60
-
61
- export type PathOptions = {
62
- path: string;
63
- sidebarPath?: string | false | undefined;
64
- };
65
-
66
- // TODO support custom version banner? {type: "error", content: "html content"}
67
- export type VersionBanner = 'unreleased' | 'unmaintained';
68
-
69
- export type VersionOptions = {
70
- path?: string;
71
- label?: string;
72
- banner?: 'none' | VersionBanner;
73
- badge?: boolean;
74
- className?: string;
75
- };
76
-
77
- export type VersionsOptions = {
78
- lastVersion?: string;
79
- versions: Record<string, VersionOptions>;
80
- onlyIncludeVersions?: string[];
81
- };
82
-
83
- export type SidebarOptions = {
84
- sidebarCollapsible: boolean;
85
- sidebarCollapsed: boolean;
86
- };
87
-
88
44
  export type NormalizeSidebarsParams = SidebarOptions & {
89
45
  version: VersionMetadata;
90
46
  categoryLabelSlugger: Slugger;
91
47
  };
92
48
 
93
- export type PluginOptions = MetadataOptions &
94
- PathOptions &
95
- VersionsOptions &
96
- RemarkAndRehypePluginOptions &
97
- SidebarOptions & {
98
- id: string;
99
- include: string[];
100
- exclude: string[];
101
- docLayoutComponent: string;
102
- docItemComponent: string;
103
- docTagDocListComponent: string;
104
- docTagsListComponent: string;
105
- docCategoryGeneratedIndexComponent: string;
106
- admonitions: Record<string, unknown>;
107
- disableVersioning: boolean;
108
- includeCurrentVersion: boolean;
109
- sidebarItemsGenerator: SidebarItemsGeneratorOption;
110
- tagsBasePath: string;
111
- };
112
-
113
49
  export type LastUpdateData = {
114
50
  lastUpdatedAt?: number;
115
51
  formattedLastUpdatedAt?: string;
@@ -130,6 +66,7 @@ export type DocFrontMatter = {
130
66
  sidebar_label?: string;
131
67
  sidebar_position?: number;
132
68
  sidebar_class_name?: string;
69
+ displayed_sidebar?: string | null;
133
70
  pagination_label?: string;
134
71
  custom_edit_url?: string | null;
135
72
  parse_number_prefixes?: boolean;
@@ -142,11 +79,11 @@ export type DocFrontMatter = {
142
79
  export type DocMetadataBase = LastUpdateData & {
143
80
  id: string; // TODO legacy versioned id => try to remove
144
81
  unversionedId: string; // TODO new unversioned id => try to rename to "id"
145
- version: VersionName;
82
+ version: string;
146
83
  title: string;
147
84
  description: string;
148
- source: string; // @site aliased source => "@site/docs/folder/subFolder/subSubFolder/myDoc.md"
149
- sourceDirName: string; // relative to the versioned docs folder (can be ".") => "folder/subFolder/subSubFolder"
85
+ source: string; // @site aliased posix source => "@site/docs/folder/subFolder/subSubFolder/myDoc.md"
86
+ sourceDirName: string; // posix path relative to the versioned docs folder (can be ".") => "folder/subFolder/subSubFolder"
150
87
  slug: string;
151
88
  permalink: string;
152
89
  sidebarPosition?: number;
@@ -174,6 +111,8 @@ export type CategoryGeneratedIndexMetadata = {
174
111
  sidebar: string;
175
112
  previous?: DocNavLink;
176
113
  next?: DocNavLink;
114
+ image?: string;
115
+ keywords?: string | readonly string[];
177
116
  };
178
117
 
179
118
  export type SourceToPermalink = {
@@ -201,26 +140,6 @@ export type LoadedContent = {
201
140
  loadedVersions: LoadedVersion[];
202
141
  };
203
142
 
204
- export type GlobalDoc = {
205
- id: string;
206
- path: string;
207
- sidebar: string | undefined;
208
- };
209
-
210
- export type GlobalVersion = {
211
- name: VersionName;
212
- label: string;
213
- isLast: boolean;
214
- path: string;
215
- mainDocId: string; // home doc (if docs homepage configured), or first doc
216
- docs: GlobalDoc[];
217
- };
218
-
219
- export type GlobalPluginData = {
220
- path: string;
221
- versions: GlobalVersion[];
222
- };
223
-
224
143
  export type BrokenMarkdownLink = IBrokenMarkdownLink<VersionMetadata>;
225
144
 
226
145
  export type DocsMarkdownOption = {
@@ -229,8 +148,3 @@ export type DocsMarkdownOption = {
229
148
  sourceToPermalink: SourceToPermalink;
230
149
  onBrokenMarkdownLink: (brokenMarkdownLink: BrokenMarkdownLink) => void;
231
150
  };
232
-
233
- export type NumberPrefixParser = (filename: string) => {
234
- filename: string;
235
- numberPrefix?: number;
236
- };
package/src/versions.ts CHANGED
@@ -7,19 +7,19 @@
7
7
 
8
8
  import path from 'path';
9
9
  import fs from 'fs-extra';
10
- import type {
11
- PluginOptions,
12
- VersionBanner,
13
- VersionMetadata,
14
- VersionOptions,
15
- VersionsOptions,
16
- } from './types';
10
+ import type {VersionMetadata} from './types';
17
11
  import {
18
12
  VERSIONS_JSON_FILE,
19
13
  VERSIONED_DOCS_DIR,
20
14
  VERSIONED_SIDEBARS_DIR,
21
15
  CURRENT_VERSION_NAME,
22
16
  } from './constants';
17
+ import type {
18
+ PluginOptions,
19
+ VersionBanner,
20
+ VersionOptions,
21
+ VersionsOptions,
22
+ } from '@docusaurus/plugin-content-docs';
23
23
 
24
24
  import type {LoadContext} from '@docusaurus/types';
25
25
  import {
@@ -87,11 +87,13 @@ function ensureValidVersionArray(
87
87
  versionArray.forEach(ensureValidVersionString);
88
88
  }
89
89
 
90
- // TODO not easy to make async due to many deps
91
- function readVersionsFile(siteDir: string, pluginId: string): string[] | null {
90
+ async function readVersionsFile(
91
+ siteDir: string,
92
+ pluginId: string,
93
+ ): Promise<string[] | null> {
92
94
  const versionsFilePath = getVersionsFilePath(siteDir, pluginId);
93
- if (fs.existsSync(versionsFilePath)) {
94
- const content = JSON.parse(fs.readFileSync(versionsFilePath, 'utf8'));
95
+ if (await fs.pathExists(versionsFilePath)) {
96
+ const content = JSON.parse(await fs.readFile(versionsFilePath, 'utf8'));
95
97
  ensureValidVersionArray(content);
96
98
  return content;
97
99
  } else {
@@ -99,27 +101,26 @@ function readVersionsFile(siteDir: string, pluginId: string): string[] | null {
99
101
  }
100
102
  }
101
103
 
102
- // TODO not easy to make async due to many deps
103
- function readVersionNames(
104
+ async function readVersionNames(
104
105
  siteDir: string,
105
106
  options: Pick<
106
107
  PluginOptions,
107
108
  'id' | 'disableVersioning' | 'includeCurrentVersion'
108
109
  >,
109
- ): string[] {
110
- const versionFileContent = readVersionsFile(siteDir, options.id);
110
+ ): Promise<string[]> {
111
+ const versionFileContent = await readVersionsFile(siteDir, options.id);
111
112
 
112
113
  if (!versionFileContent && options.disableVersioning) {
113
114
  throw new Error(
114
- `Docs: using "disableVersioning=${options.disableVersioning}" option on a non-versioned site does not make sense.`,
115
+ `Docs: using "disableVersioning: ${options.disableVersioning}" option on a non-versioned site does not make sense.`,
115
116
  );
116
117
  }
117
118
 
118
119
  const versions = options.disableVersioning ? [] : versionFileContent ?? [];
119
120
 
120
- // We add the current version at the beginning, unless
121
- // - user don't want to
122
- // - it's been explicitly added to versions.json
121
+ // We add the current version at the beginning, unless:
122
+ // - user don't want to; or
123
+ // - it's already been explicitly added to versions.json
123
124
  if (
124
125
  options.includeCurrentVersion &&
125
126
  !versions.includes(CURRENT_VERSION_NAME)
@@ -129,7 +130,7 @@ function readVersionNames(
129
130
 
130
131
  if (versions.length === 0) {
131
132
  throw new Error(
132
- `It is not possible to use docs without any version. Please check the configuration of these options: "includeCurrentVersion=${options.includeCurrentVersion}", "disableVersioning=${options.disableVersioning}".`,
133
+ `It is not possible to use docs without any version. Please check the configuration of these options: "includeCurrentVersion: ${options.includeCurrentVersion}", "disableVersioning: ${options.disableVersioning}".`,
133
134
  );
134
135
  }
135
136
 
@@ -174,13 +175,6 @@ function getVersionMetadataPaths({
174
175
  > {
175
176
  const isCurrentVersion = versionName === CURRENT_VERSION_NAME;
176
177
 
177
- const contentPath = isCurrentVersion
178
- ? path.resolve(context.siteDir, options.path)
179
- : path.join(
180
- getVersionedDocsDirPath(context.siteDir, options.id),
181
- `version-${versionName}`,
182
- );
183
-
184
178
  const contentPathLocalized = getDocsDirPathLocalized({
185
179
  siteDir: context.siteDir,
186
180
  locale: context.i18n.currentLocale,
@@ -188,21 +182,27 @@ function getVersionMetadataPaths({
188
182
  versionName,
189
183
  });
190
184
 
191
- function getSidebarFilePath() {
192
- if (isCurrentVersion) {
193
- return resolveSidebarPathOption(context.siteDir, options.sidebarPath);
194
- } else {
195
- return path.join(
196
- getVersionedSidebarsDirPath(context.siteDir, options.id),
197
- `version-${versionName}-sidebars.json`,
198
- );
199
- }
185
+ if (isCurrentVersion) {
186
+ return {
187
+ contentPath: path.resolve(context.siteDir, options.path),
188
+ contentPathLocalized,
189
+ sidebarFilePath: resolveSidebarPathOption(
190
+ context.siteDir,
191
+ options.sidebarPath,
192
+ ),
193
+ };
200
194
  }
201
195
 
202
196
  return {
203
- contentPath,
197
+ contentPath: path.join(
198
+ getVersionedDocsDirPath(context.siteDir, options.id),
199
+ `version-${versionName}`,
200
+ ),
204
201
  contentPathLocalized,
205
- sidebarFilePath: getSidebarFilePath(),
202
+ sidebarFilePath: path.join(
203
+ getVersionedSidebarsDirPath(context.siteDir, options.id),
204
+ `version-${versionName}-sidebars.json`,
205
+ ),
206
206
  };
207
207
  }
208
208
 
@@ -459,7 +459,7 @@ function checkVersionMetadataPaths({
459
459
  Please set the docs "sidebarPath" field in your config file to:
460
460
  - a sidebars path that exists
461
461
  - false: to disable the sidebar
462
- - undefined: for Docusaurus generates it automatically`);
462
+ - undefined: for Docusaurus to generate it automatically`);
463
463
  }
464
464
  }
465
465
 
@@ -488,7 +488,7 @@ function checkVersionsOptions(
488
488
  !availableVersionNames.includes(options.lastVersion)
489
489
  ) {
490
490
  throw new Error(
491
- `Docs option lastVersion=${options.lastVersion} is invalid. ${availableVersionNamesMsg}`,
491
+ `Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`,
492
492
  );
493
493
  }
494
494
  const unknownVersionConfigNames = difference(
@@ -531,9 +531,11 @@ function checkVersionsOptions(
531
531
  }
532
532
  }
533
533
 
534
- // Filter versions according to provided options
535
- // Note: we preserve the order in which versions are provided
536
- // the order of the onlyIncludeVersions array does not matter
534
+ /**
535
+ * Filter versions according to provided options.
536
+ * Note: we preserve the order in which versions are provided;
537
+ * the order of the onlyIncludeVersions array does not matter
538
+ */
537
539
  function filterVersions(
538
540
  versionNamesUnfiltered: string[],
539
541
  options: Pick<PluginOptions, 'onlyIncludeVersions'>,
@@ -547,8 +549,7 @@ function filterVersions(
547
549
  }
548
550
  }
549
551
 
550
- // TODO make this async (requires plugin init to be async)
551
- export function readVersionsMetadata({
552
+ export async function readVersionsMetadata({
552
553
  context,
553
554
  options,
554
555
  }: {
@@ -568,8 +569,11 @@ export function readVersionsMetadata({
568
569
  | 'editUrl'
569
570
  | 'editCurrentVersion'
570
571
  >;
571
- }): VersionMetadata[] {
572
- const versionNamesUnfiltered = readVersionNames(context.siteDir, options);
572
+ }): Promise<VersionMetadata[]> {
573
+ const versionNamesUnfiltered = await readVersionNames(
574
+ context.siteDir,
575
+ options,
576
+ );
573
577
 
574
578
  checkVersionsOptions(versionNamesUnfiltered, options);
575
579