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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +12 -0
  2. package/lib/categoryGeneratedIndex.js +35 -0
  3. package/lib/cli.d.ts +2 -2
  4. package/lib/cli.js +37 -51
  5. package/lib/client/docsClientUtils.d.ts +6 -26
  6. package/lib/client/docsClientUtils.js +28 -34
  7. package/lib/{theme/hooks/useDocs.d.ts → client/index.d.ts} +4 -3
  8. package/lib/{theme/hooks/useDocs.js → client/index.js} +28 -25
  9. package/lib/docs.d.ts +31 -4
  10. package/lib/docs.js +160 -54
  11. package/{src/__tests__/__fixtures__/simple-site/docusaurus.config.js → lib/frontMatter.d.ts} +4 -8
  12. package/lib/{docFrontMatter.js → frontMatter.js} +13 -6
  13. package/lib/globalData.d.ts +2 -2
  14. package/lib/globalData.js +32 -3
  15. package/lib/index.d.ts +4 -3
  16. package/lib/index.js +123 -136
  17. package/lib/lastUpdate.d.ts +4 -6
  18. package/lib/lastUpdate.js +22 -26
  19. package/lib/markdown/index.d.ts +3 -6
  20. package/lib/markdown/index.js +3 -3
  21. package/lib/markdown/linkify.d.ts +1 -1
  22. package/lib/markdown/linkify.js +7 -3
  23. package/lib/numberPrefix.d.ts +1 -1
  24. package/lib/numberPrefix.js +16 -21
  25. package/lib/options.d.ts +3 -5
  26. package/lib/options.js +55 -19
  27. package/lib/props.d.ts +7 -2
  28. package/lib/props.js +70 -14
  29. package/lib/routes.d.ts +28 -0
  30. package/lib/routes.js +110 -0
  31. package/lib/server-export.d.ts +8 -0
  32. package/lib/server-export.js +23 -0
  33. package/lib/{sidebarItemsGenerator.d.ts → sidebars/generator.d.ts} +1 -6
  34. package/lib/sidebars/generator.js +209 -0
  35. package/lib/sidebars/index.d.ts +13 -0
  36. package/lib/sidebars/index.js +94 -0
  37. package/lib/sidebars/normalization.d.ts +13 -0
  38. package/lib/sidebars/normalization.js +55 -0
  39. package/lib/sidebars/postProcessor.d.ts +8 -0
  40. package/lib/sidebars/postProcessor.js +65 -0
  41. package/lib/sidebars/processor.d.ts +10 -0
  42. package/lib/sidebars/processor.js +79 -0
  43. package/lib/sidebars/types.d.ts +174 -0
  44. package/{src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars2.js → lib/sidebars/types.js} +2 -10
  45. package/lib/sidebars/utils.d.ts +54 -0
  46. package/lib/sidebars/utils.js +255 -0
  47. package/lib/sidebars/validation.d.ts +11 -0
  48. package/lib/sidebars/validation.js +138 -0
  49. package/lib/slug.d.ts +6 -4
  50. package/lib/slug.js +29 -19
  51. package/{src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docusaurus.config.js → lib/tags.d.ts} +2 -8
  52. package/lib/tags.js +21 -0
  53. package/lib/translations.d.ts +2 -2
  54. package/lib/translations.js +89 -49
  55. package/lib/types.d.ts +60 -130
  56. package/lib/versions.d.ts +29 -4
  57. package/lib/versions.js +134 -97
  58. package/package.json +30 -26
  59. package/src/categoryGeneratedIndex.ts +55 -0
  60. package/src/cli.ts +47 -63
  61. package/src/client/docsClientUtils.ts +38 -73
  62. package/src/{theme/hooks/useDocs.ts → client/index.ts} +16 -11
  63. package/{types.d.ts → src/deps.d.ts} +1 -1
  64. package/src/docs.ts +212 -46
  65. package/src/{docFrontMatter.ts → frontMatter.ts} +21 -26
  66. package/src/globalData.ts +53 -3
  67. package/src/index.ts +168 -178
  68. package/src/lastUpdate.ts +26 -33
  69. package/src/markdown/index.ts +10 -16
  70. package/src/markdown/linkify.ts +6 -2
  71. package/src/numberPrefix.ts +19 -26
  72. package/src/options.ts +60 -32
  73. package/src/plugin-content-docs.d.ts +263 -40
  74. package/src/props.ts +105 -21
  75. package/src/routes.ts +185 -0
  76. package/src/server-export.ts +24 -0
  77. package/src/sidebars/README.md +9 -0
  78. package/src/sidebars/generator.ts +292 -0
  79. package/src/sidebars/index.ts +120 -0
  80. package/src/sidebars/normalization.ts +85 -0
  81. package/src/sidebars/postProcessor.ts +89 -0
  82. package/src/sidebars/processor.ts +120 -0
  83. package/src/sidebars/types.ts +274 -0
  84. package/src/sidebars/utils.ts +388 -0
  85. package/src/sidebars/validation.ts +174 -0
  86. package/src/slug.ts +40 -23
  87. package/src/tags.ts +19 -0
  88. package/src/translations.ts +124 -66
  89. package/src/types.ts +67 -187
  90. package/src/versions.ts +205 -110
  91. package/lib/.tsbuildinfo +0 -4717
  92. package/lib/docFrontMatter.d.ts +0 -21
  93. package/lib/sidebarItemsGenerator.js +0 -211
  94. package/lib/sidebars.d.ts +0 -42
  95. package/lib/sidebars.js +0 -309
  96. package/src/__tests__/__fixtures__/bad-id-site/docs/invalid-id.md +0 -5
  97. package/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md +0 -5
  98. package/src/__tests__/__fixtures__/empty-site/docusaurus.config.js +0 -16
  99. package/src/__tests__/__fixtures__/empty-site/sidebars.json +0 -1
  100. package/src/__tests__/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -34
  101. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -11
  102. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -11
  103. package/src/__tests__/__fixtures__/sidebars/sidebars-category.js +0 -44
  104. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -20
  105. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed.json +0 -21
  106. package/src/__tests__/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -10
  107. package/src/__tests__/__fixtures__/sidebars/sidebars-first-level-not-category.js +0 -20
  108. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -11
  109. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -11
  110. package/src/__tests__/__fixtures__/sidebars/sidebars-link.json +0 -11
  111. package/src/__tests__/__fixtures__/sidebars/sidebars-unknown-type.json +0 -14
  112. package/src/__tests__/__fixtures__/sidebars/sidebars-wrong-field.json +0 -20
  113. package/src/__tests__/__fixtures__/sidebars/sidebars.json +0 -20
  114. package/src/__tests__/__fixtures__/simple-site/docs/foo/bar.md +0 -69
  115. package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +0 -67
  116. package/src/__tests__/__fixtures__/simple-site/docs/headingAsTitle.md +0 -1
  117. package/src/__tests__/__fixtures__/simple-site/docs/hello.md +0 -52
  118. package/src/__tests__/__fixtures__/simple-site/docs/ipsum.md +0 -5
  119. package/src/__tests__/__fixtures__/simple-site/docs/lorem.md +0 -6
  120. package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +0 -5
  121. package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +0 -5
  122. package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +0 -5
  123. package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +0 -5
  124. package/src/__tests__/__fixtures__/simple-site/docs/slugs/absoluteSlug.md +0 -5
  125. package/src/__tests__/__fixtures__/simple-site/docs/slugs/relativeSlug.md +0 -5
  126. package/src/__tests__/__fixtures__/simple-site/docs/slugs/resolvedSlug.md +0 -5
  127. package/src/__tests__/__fixtures__/simple-site/docs/slugs/tryToEscapeSlug.md +0 -5
  128. package/src/__tests__/__fixtures__/simple-site/sidebars.json +0 -23
  129. package/src/__tests__/__fixtures__/simple-site/wrong-sidebars.json +0 -7
  130. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/0-getting-started.md +0 -3
  131. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/1-installation.md +0 -3
  132. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/00_api-overview.md +0 -3
  133. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/0 --- Client API.md +0 -1
  134. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/1 --- Server API.md +0 -1
  135. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/0. Plugin API.md +0 -1
  136. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/1. Theme API.md +0 -1
  137. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/_category_.yml +0 -1
  138. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/03_api-end.md +0 -3
  139. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/_category_.json +0 -3
  140. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/0-guide2.5.md +0 -8
  141. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/02-guide2.md +0 -7
  142. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/_category_.json +0 -3
  143. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/a-guide4.md +0 -7
  144. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/b-guide5.md +0 -7
  145. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/guide3.md +0 -8
  146. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/z-guide1.md +0 -8
  147. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars.js +0 -23
  148. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-1.md +0 -7
  149. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md +0 -8
  150. package/src/__tests__/__fixtures__/site-with-doc-label/docusaurus.config.js +0 -14
  151. package/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json +0 -14
  152. package/src/__tests__/__fixtures__/versioned-site/community/team.md +0 -1
  153. package/src/__tests__/__fixtures__/versioned-site/community_sidebars.json +0 -3
  154. package/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md +0 -1
  155. package/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json +0 -3
  156. package/src/__tests__/__fixtures__/versioned-site/community_versions.json +0 -1
  157. package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +0 -4
  158. package/src/__tests__/__fixtures__/versioned-site/docs/hello.md +0 -1
  159. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/absoluteSlug.md +0 -5
  160. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/relativeSlug.md +0 -5
  161. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/resolvedSlug.md +0 -5
  162. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/tryToEscapeSlug.md +0 -5
  163. package/src/__tests__/__fixtures__/versioned-site/docusaurus.config.js +0 -18
  164. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  165. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs-community/current/team.md +0 -5
  166. package/src/__tests__/__fixtures__/versioned-site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  167. package/src/__tests__/__fixtures__/versioned-site/sidebars.json +0 -10
  168. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/bar.md +0 -4
  169. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/baz.md +0 -1
  170. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/hello.md +0 -1
  171. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/foo/bar.md +0 -1
  172. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/hello.md +0 -1
  173. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md +0 -5
  174. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootRelativeSlug.md +0 -5
  175. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootResolvedSlug.md +0 -5
  176. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md +0 -5
  177. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md +0 -5
  178. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/relativeSlug.md +0 -5
  179. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md +0 -5
  180. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md +0 -5
  181. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.0-sidebars.json +0 -11
  182. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.1-sidebars.json +0 -10
  183. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-withSlugs-sidebars.json +0 -5
  184. package/src/__tests__/__fixtures__/versioned-site/versions.json +0 -5
  185. package/src/__tests__/__snapshots__/cli.test.ts.snap +0 -90
  186. package/src/__tests__/__snapshots__/index.test.ts.snap +0 -1907
  187. package/src/__tests__/__snapshots__/sidebars.test.ts.snap +0 -218
  188. package/src/__tests__/__snapshots__/translations.test.ts.snap +0 -487
  189. package/src/__tests__/cli.test.ts +0 -333
  190. package/src/__tests__/docFrontMatter.test.ts +0 -204
  191. package/src/__tests__/docs.test.ts +0 -875
  192. package/src/__tests__/index.test.ts +0 -1831
  193. package/src/__tests__/lastUpdate.test.ts +0 -68
  194. package/src/__tests__/numberPrefix.test.ts +0 -199
  195. package/src/__tests__/options.test.ts +0 -232
  196. package/src/__tests__/sidebarItemsGenerator.test.ts +0 -336
  197. package/src/__tests__/sidebars.test.ts +0 -638
  198. package/src/__tests__/slug.test.ts +0 -109
  199. package/src/__tests__/translations.test.ts +0 -159
  200. package/src/__tests__/versions.test.ts +0 -718
  201. package/src/client/__tests__/docsClientUtils.test.ts +0 -372
  202. package/src/markdown/__tests__/__fixtures__/docs/doc-localized.md +0 -1
  203. package/src/markdown/__tests__/__fixtures__/docs/doc1.md +0 -13
  204. package/src/markdown/__tests__/__fixtures__/docs/doc2.md +0 -12
  205. package/src/markdown/__tests__/__fixtures__/docs/doc4.md +0 -19
  206. package/src/markdown/__tests__/__fixtures__/docs/doc5.md +0 -6
  207. package/src/markdown/__tests__/__fixtures__/docs/subdir/doc3.md +0 -3
  208. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/doc2.md +0 -7
  209. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/subdir/doc1.md +0 -3
  210. package/src/markdown/__tests__/__snapshots__/linkify.test.ts.snap +0 -82
  211. package/src/markdown/__tests__/linkify.test.ts +0 -190
  212. package/src/sidebarItemsGenerator.ts +0 -307
  213. package/src/sidebars.ts +0 -489
  214. package/tsconfig.json +0 -9
package/src/versions.ts CHANGED
@@ -7,31 +7,35 @@
7
7
 
8
8
  import path from 'path';
9
9
  import fs from 'fs-extra';
10
- import {
11
- PluginOptions,
12
- VersionMetadata,
13
- VersionOptions,
14
- VersionsOptions,
15
- } from './types';
10
+ import type {VersionMetadata} from './types';
16
11
  import {
17
12
  VERSIONS_JSON_FILE,
18
13
  VERSIONED_DOCS_DIR,
19
14
  VERSIONED_SIDEBARS_DIR,
20
15
  CURRENT_VERSION_NAME,
21
16
  } from './constants';
17
+ import type {
18
+ PluginOptions,
19
+ VersionBanner,
20
+ VersionOptions,
21
+ VersionsOptions,
22
+ } from '@docusaurus/plugin-content-docs';
22
23
 
23
- import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
24
- import {LoadContext} from '@docusaurus/types';
25
- import {getPluginI18nPath, normalizeUrl, posixPath} from '@docusaurus/utils';
26
- import {difference} from 'lodash';
24
+ import type {LoadContext} from '@docusaurus/types';
25
+ import {
26
+ getPluginI18nPath,
27
+ normalizeUrl,
28
+ posixPath,
29
+ DEFAULT_PLUGIN_ID,
30
+ } from '@docusaurus/utils';
31
+ import _ from 'lodash';
32
+ import {resolveSidebarPathOption} from './sidebars';
27
33
 
28
34
  // retro-compatibility: no prefix for the default plugin id
29
35
  function addPluginIdPrefix(fileOrDir: string, pluginId: string): string {
30
- if (pluginId === DEFAULT_PLUGIN_ID) {
31
- return fileOrDir;
32
- } else {
33
- return `${pluginId}_${fileOrDir}`;
34
- }
36
+ return pluginId === DEFAULT_PLUGIN_ID
37
+ ? fileOrDir
38
+ : `${pluginId}_${fileOrDir}`;
35
39
  }
36
40
 
37
41
  export function getVersionedDocsDirPath(
@@ -58,21 +62,21 @@ export function getVersionsFilePath(siteDir: string, pluginId: string): string {
58
62
  function ensureValidVersionString(version: unknown): asserts version is string {
59
63
  if (typeof version !== 'string') {
60
64
  throw new Error(
61
- `versions should be strings. Found type=[${typeof version}] for version=[${version}]`,
65
+ `Versions should be strings. Found type "${typeof version}" for version "${version}".`,
62
66
  );
63
67
  }
64
68
  // Should we forbid versions with special chars like / ?
65
69
  if (version.trim().length === 0) {
66
- throw new Error(`Invalid version=[${version}]`);
70
+ throw new Error(`Invalid version "${version}".`);
67
71
  }
68
72
  }
69
73
 
70
74
  function ensureValidVersionArray(
71
75
  versionArray: unknown,
72
76
  ): asserts versionArray is string[] {
73
- if (!(versionArray instanceof Array)) {
77
+ if (!Array.isArray(versionArray)) {
74
78
  throw new Error(
75
- `The versions file should contain an array of versions! Found content=${JSON.stringify(
79
+ `The versions file should contain an array of version names! Found content: ${JSON.stringify(
76
80
  versionArray,
77
81
  )}`,
78
82
  );
@@ -81,39 +85,39 @@ function ensureValidVersionArray(
81
85
  versionArray.forEach(ensureValidVersionString);
82
86
  }
83
87
 
84
- // TODO not easy to make async due to many deps
85
- function readVersionsFile(siteDir: string, pluginId: string): string[] | null {
88
+ export async function readVersionsFile(
89
+ siteDir: string,
90
+ pluginId: string,
91
+ ): Promise<string[] | null> {
86
92
  const versionsFilePath = getVersionsFilePath(siteDir, pluginId);
87
- if (fs.existsSync(versionsFilePath)) {
88
- const content = JSON.parse(fs.readFileSync(versionsFilePath, 'utf8'));
93
+ if (await fs.pathExists(versionsFilePath)) {
94
+ const content = JSON.parse(await fs.readFile(versionsFilePath, 'utf8'));
89
95
  ensureValidVersionArray(content);
90
96
  return content;
91
- } else {
92
- return null;
93
97
  }
98
+ return null;
94
99
  }
95
100
 
96
- // TODO not easy to make async due to many deps
97
- function readVersionNames(
101
+ export async function readVersionNames(
98
102
  siteDir: string,
99
103
  options: Pick<
100
104
  PluginOptions,
101
105
  'id' | 'disableVersioning' | 'includeCurrentVersion'
102
106
  >,
103
- ): string[] {
104
- const versionFileContent = readVersionsFile(siteDir, options.id);
107
+ ): Promise<string[]> {
108
+ const versionFileContent = await readVersionsFile(siteDir, options.id);
105
109
 
106
110
  if (!versionFileContent && options.disableVersioning) {
107
111
  throw new Error(
108
- `Docs: using disableVersioning=${options.disableVersioning} option on a non-versioned site does not make sense`,
112
+ `Docs: using "disableVersioning: ${options.disableVersioning}" option on a non-versioned site does not make sense.`,
109
113
  );
110
114
  }
111
115
 
112
116
  const versions = options.disableVersioning ? [] : versionFileContent ?? [];
113
117
 
114
- // We add the current version at the beginning, unless
115
- // - user don't want to
116
- // - it's been explicitly added to versions.json
118
+ // We add the current version at the beginning, unless:
119
+ // - user don't want to; or
120
+ // - it's already been explicitly added to versions.json
117
121
  if (
118
122
  options.includeCurrentVersion &&
119
123
  !versions.includes(CURRENT_VERSION_NAME)
@@ -123,7 +127,7 @@ function readVersionNames(
123
127
 
124
128
  if (versions.length === 0) {
125
129
  throw new Error(
126
- `It is not possible to use docs without any version. Please check the configuration of these options: includeCurrentVersion=${options.includeCurrentVersion} disableVersioning=${options.disableVersioning}`,
130
+ `It is not possible to use docs without any version. Please check the configuration of these options: "includeCurrentVersion: ${options.includeCurrentVersion}", "disableVersioning: ${options.disableVersioning}".`,
127
131
  );
128
132
  }
129
133
 
@@ -168,13 +172,6 @@ function getVersionMetadataPaths({
168
172
  > {
169
173
  const isCurrentVersion = versionName === CURRENT_VERSION_NAME;
170
174
 
171
- const contentPath = isCurrentVersion
172
- ? path.resolve(context.siteDir, options.path)
173
- : path.join(
174
- getVersionedDocsDirPath(context.siteDir, options.id),
175
- `version-${versionName}`,
176
- );
177
-
178
175
  const contentPathLocalized = getDocsDirPathLocalized({
179
176
  siteDir: context.siteDir,
180
177
  locale: context.i18n.currentLocale,
@@ -182,23 +179,27 @@ function getVersionMetadataPaths({
182
179
  versionName,
183
180
  });
184
181
 
185
- function getSidebarFilePath() {
186
- if (isCurrentVersion) {
187
- return options.sidebarPath
188
- ? path.resolve(context.siteDir, options.sidebarPath)
189
- : options.sidebarPath;
190
- } else {
191
- return path.join(
192
- getVersionedSidebarsDirPath(context.siteDir, options.id),
193
- `version-${versionName}-sidebars.json`,
194
- );
195
- }
182
+ if (isCurrentVersion) {
183
+ return {
184
+ contentPath: path.resolve(context.siteDir, options.path),
185
+ contentPathLocalized,
186
+ sidebarFilePath: resolveSidebarPathOption(
187
+ context.siteDir,
188
+ options.sidebarPath,
189
+ ),
190
+ };
196
191
  }
197
192
 
198
193
  return {
199
- contentPath,
194
+ contentPath: path.join(
195
+ getVersionedDocsDirPath(context.siteDir, options.id),
196
+ `version-${versionName}`,
197
+ ),
200
198
  contentPathLocalized,
201
- sidebarFilePath: getSidebarFilePath(),
199
+ sidebarFilePath: path.join(
200
+ getVersionedSidebarsDirPath(context.siteDir, options.id),
201
+ `version-${versionName}-sidebars.json`,
202
+ ),
202
203
  };
203
204
  }
204
205
 
@@ -256,14 +257,90 @@ function getVersionEditUrls({
256
257
  };
257
258
  }
258
259
 
260
+ export function getDefaultVersionBanner({
261
+ versionName,
262
+ versionNames,
263
+ lastVersionName,
264
+ }: {
265
+ versionName: string;
266
+ versionNames: string[];
267
+ lastVersionName: string;
268
+ }): VersionBanner | null {
269
+ // Current version: good, no banner
270
+ if (versionName === lastVersionName) {
271
+ return null;
272
+ }
273
+ // Upcoming versions: unreleased banner
274
+ if (
275
+ versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName)
276
+ ) {
277
+ return 'unreleased';
278
+ }
279
+ // Older versions: display unmaintained banner
280
+ return 'unmaintained';
281
+ }
282
+
283
+ export function getVersionBanner({
284
+ versionName,
285
+ versionNames,
286
+ lastVersionName,
287
+ options,
288
+ }: {
289
+ versionName: string;
290
+ versionNames: string[];
291
+ lastVersionName: string;
292
+ options: Pick<PluginOptions, 'versions'>;
293
+ }): VersionBanner | null {
294
+ const versionBannerOption = options.versions[versionName]?.banner;
295
+ if (versionBannerOption) {
296
+ return versionBannerOption === 'none' ? null : versionBannerOption;
297
+ }
298
+ return getDefaultVersionBanner({
299
+ versionName,
300
+ versionNames,
301
+ lastVersionName,
302
+ });
303
+ }
304
+
305
+ export function getVersionBadge({
306
+ versionName,
307
+ versionNames,
308
+ options,
309
+ }: {
310
+ versionName: string;
311
+ versionNames: string[];
312
+ options: Pick<PluginOptions, 'versions'>;
313
+ }): boolean {
314
+ const versionBadgeOption = options.versions[versionName]?.badge;
315
+ // If site is not versioned or only one version is included
316
+ // we don't show the version badge by default
317
+ // See https://github.com/facebook/docusaurus/issues/3362
318
+ const versionBadgeDefault = versionNames.length !== 1;
319
+ return versionBadgeOption ?? versionBadgeDefault;
320
+ }
321
+
322
+ function getVersionClassName({
323
+ versionName,
324
+ options,
325
+ }: {
326
+ versionName: string;
327
+ options: Pick<PluginOptions, 'versions'>;
328
+ }): string {
329
+ const versionClassNameOption = options.versions[versionName]?.className;
330
+ const versionClassNameDefault = `docs-version-${versionName}`;
331
+ return versionClassNameOption ?? versionClassNameDefault;
332
+ }
333
+
259
334
  function createVersionMetadata({
260
335
  versionName,
261
- isLast,
336
+ versionNames,
337
+ lastVersionName,
262
338
  context,
263
339
  options,
264
340
  }: {
265
341
  versionName: string;
266
- isLast: boolean;
342
+ versionNames: string[];
343
+ lastVersionName: string;
267
344
  context: Pick<LoadContext, 'siteDir' | 'baseUrl' | 'i18n'>;
268
345
  options: Pick<
269
346
  PluginOptions,
@@ -271,29 +348,27 @@ function createVersionMetadata({
271
348
  | 'path'
272
349
  | 'sidebarPath'
273
350
  | 'routeBasePath'
351
+ | 'tagsBasePath'
274
352
  | 'versions'
275
353
  | 'editUrl'
276
354
  | 'editCurrentVersion'
277
355
  >;
278
356
  }): VersionMetadata {
279
- const {
280
- sidebarFilePath,
281
- contentPath,
282
- contentPathLocalized,
283
- } = getVersionMetadataPaths({
284
- versionName,
285
- context,
286
- options,
287
- });
357
+ const {sidebarFilePath, contentPath, contentPathLocalized} =
358
+ getVersionMetadataPaths({versionName, context, options});
359
+
360
+ const isLast = versionName === lastVersionName;
288
361
 
289
362
  // retro-compatible values
290
363
  const defaultVersionLabel =
291
364
  versionName === CURRENT_VERSION_NAME ? 'Next' : versionName;
292
- const defaultVersionPathPart = isLast
293
- ? ''
294
- : versionName === CURRENT_VERSION_NAME
295
- ? 'next'
296
- : versionName;
365
+ function getDefaultVersionPathPart() {
366
+ if (isLast) {
367
+ return '';
368
+ }
369
+ return versionName === CURRENT_VERSION_NAME ? 'next' : versionName;
370
+ }
371
+ const defaultVersionPathPart = getDefaultVersionPathPart();
297
372
 
298
373
  const versionOptions: VersionOptions = options.versions[versionName] ?? {};
299
374
 
@@ -316,12 +391,25 @@ function createVersionMetadata({
316
391
  // Because /docs/:route` should always be after `/docs/versionName/:route`.
317
392
  const routePriority = versionPathPart === '' ? -1 : undefined;
318
393
 
394
+ // the path that will be used to refer the docs tags
395
+ // example below will be using /docs/tags
396
+ const tagsPath = normalizeUrl([versionPath, options.tagsBasePath]);
397
+
319
398
  return {
320
399
  versionName,
321
400
  versionLabel,
322
401
  versionPath,
402
+ tagsPath,
323
403
  versionEditUrl: versionEditUrls?.versionEditUrl,
324
404
  versionEditUrlLocalized: versionEditUrls?.versionEditUrlLocalized,
405
+ versionBanner: getVersionBanner({
406
+ versionName,
407
+ versionNames,
408
+ lastVersionName,
409
+ options,
410
+ }),
411
+ versionBadge: getVersionBadge({versionName, versionNames, options}),
412
+ versionClassName: getVersionClassName({versionName, options}),
325
413
  isLast,
326
414
  routePriority,
327
415
  sidebarFilePath,
@@ -330,7 +418,7 @@ function createVersionMetadata({
330
418
  };
331
419
  }
332
420
 
333
- function checkVersionMetadataPaths({
421
+ async function checkVersionMetadataPaths({
334
422
  versionMetadata,
335
423
  context,
336
424
  }: {
@@ -341,32 +429,33 @@ function checkVersionMetadataPaths({
341
429
  const {siteDir} = context;
342
430
  const isCurrentVersion = versionName === CURRENT_VERSION_NAME;
343
431
 
344
- if (!fs.existsSync(contentPath)) {
432
+ if (!(await fs.pathExists(contentPath))) {
345
433
  throw new Error(
346
- `The docs folder does not exist for version [${versionName}]. A docs folder is expected to be found at ${path.relative(
434
+ `The docs folder does not exist for version "${versionName}". A docs folder is expected to be found at ${path.relative(
347
435
  siteDir,
348
436
  contentPath,
349
- )}`,
437
+ )}.`,
350
438
  );
351
439
  }
352
440
 
353
- // If the current version defines a path to a sidebar file that does not exist, we throw!
354
- // Note: for versioned sidebars, the file may not exist (as we prefer to not create it rather than to create an empty file)
441
+ // If the current version defines a path to a sidebar file that does not
442
+ // exist, we throw! Note: for versioned sidebars, the file may not exist (as
443
+ // we prefer to not create it rather than to create an empty file)
355
444
  // See https://github.com/facebook/docusaurus/issues/3366
356
445
  // See https://github.com/facebook/docusaurus/pull/4775
357
446
  if (
358
447
  isCurrentVersion &&
359
448
  typeof sidebarFilePath === 'string' &&
360
- !fs.existsSync(sidebarFilePath)
449
+ !(await fs.pathExists(sidebarFilePath))
361
450
  ) {
362
- throw new Error(`The path to the sidebar file does not exist at [${path.relative(
451
+ throw new Error(`The path to the sidebar file does not exist at "${path.relative(
363
452
  siteDir,
364
453
  sidebarFilePath,
365
- )}].
366
- Please set the docs [sidebarPath] field in your config file to:
454
+ )}".
455
+ Please set the docs "sidebarPath" field in your config file to:
367
456
  - a sidebars path that exists
368
457
  - false: to disable the sidebar
369
- - undefined: for Docusaurus generates it automatically`);
458
+ - undefined: for Docusaurus to generate it automatically`);
370
459
  }
371
460
  }
372
461
 
@@ -375,12 +464,11 @@ Please set the docs [sidebarPath] field in your config file to:
375
464
  // "last version" is not a very good concept nor api surface
376
465
  function getDefaultLastVersionName(versionNames: string[]) {
377
466
  if (versionNames.length === 1) {
378
- return versionNames[0];
379
- } else {
380
- return versionNames.filter(
381
- (versionName) => versionName !== CURRENT_VERSION_NAME,
382
- )[0];
467
+ return versionNames[0]!;
383
468
  }
469
+ return versionNames.filter(
470
+ (versionName) => versionName !== CURRENT_VERSION_NAME,
471
+ )[0]!;
384
472
  }
385
473
 
386
474
  function checkVersionsOptions(
@@ -395,36 +483,36 @@ function checkVersionsOptions(
395
483
  !availableVersionNames.includes(options.lastVersion)
396
484
  ) {
397
485
  throw new Error(
398
- `Docs option lastVersion=${options.lastVersion} is invalid. ${availableVersionNamesMsg}`,
486
+ `Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`,
399
487
  );
400
488
  }
401
- const unknownVersionConfigNames = difference(
489
+ const unknownVersionConfigNames = _.difference(
402
490
  Object.keys(options.versions),
403
491
  availableVersionNames,
404
492
  );
405
493
  if (unknownVersionConfigNames.length > 0) {
406
494
  throw new Error(
407
- `Bad docs options.versions: unknown versions found: ${unknownVersionConfigNames.join(
495
+ `Invalid docs option "versions": unknown versions (${unknownVersionConfigNames.join(
408
496
  ',',
409
- )}. ${availableVersionNamesMsg}`,
497
+ )}) found. ${availableVersionNamesMsg}`,
410
498
  );
411
499
  }
412
500
 
413
501
  if (options.onlyIncludeVersions) {
414
502
  if (options.onlyIncludeVersions.length === 0) {
415
503
  throw new Error(
416
- `Bad docs options.onlyIncludeVersions: an empty array is not allowed, at least one version is needed`,
504
+ `Invalid docs option "onlyIncludeVersions": an empty array is not allowed, at least one version is needed.`,
417
505
  );
418
506
  }
419
- const unknownOnlyIncludeVersionNames = difference(
507
+ const unknownOnlyIncludeVersionNames = _.difference(
420
508
  options.onlyIncludeVersions,
421
509
  availableVersionNames,
422
510
  );
423
511
  if (unknownOnlyIncludeVersionNames.length > 0) {
424
512
  throw new Error(
425
- `Bad docs options.onlyIncludeVersions: unknown versions found: ${unknownOnlyIncludeVersionNames.join(
513
+ `Invalid docs option "onlyIncludeVersions": unknown versions (${unknownOnlyIncludeVersionNames.join(
426
514
  ',',
427
- )}. ${availableVersionNamesMsg}`,
515
+ )}) found. ${availableVersionNamesMsg}`,
428
516
  );
429
517
  }
430
518
  if (
@@ -432,30 +520,30 @@ function checkVersionsOptions(
432
520
  !options.onlyIncludeVersions.includes(options.lastVersion)
433
521
  ) {
434
522
  throw new Error(
435
- `Bad docs options.lastVersion: if you use both the onlyIncludeVersions and lastVersion options, then lastVersion must be present in the provided onlyIncludeVersions array`,
523
+ `Invalid docs option "lastVersion": if you use both the "onlyIncludeVersions" and "lastVersion" options, then "lastVersion" must be present in the provided "onlyIncludeVersions" array.`,
436
524
  );
437
525
  }
438
526
  }
439
527
  }
440
528
 
441
- // Filter versions according to provided options
442
- // Note: we preserve the order in which versions are provided
443
- // the order of the onlyIncludeVersions array does not matter
444
- function filterVersions(
529
+ /**
530
+ * Filter versions according to provided options.
531
+ * Note: we preserve the order in which versions are provided;
532
+ * the order of the onlyIncludeVersions array does not matter
533
+ */
534
+ export function filterVersions(
445
535
  versionNamesUnfiltered: string[],
446
536
  options: Pick<PluginOptions, 'onlyIncludeVersions'>,
447
- ) {
537
+ ): string[] {
448
538
  if (options.onlyIncludeVersions) {
449
539
  return versionNamesUnfiltered.filter((name) =>
450
- (options.onlyIncludeVersions || []).includes(name),
540
+ options.onlyIncludeVersions!.includes(name),
451
541
  );
452
- } else {
453
- return versionNamesUnfiltered;
454
542
  }
543
+ return versionNamesUnfiltered;
455
544
  }
456
545
 
457
- // TODO make this async (requires plugin init to be async)
458
- export function readVersionsMetadata({
546
+ export async function readVersionsMetadata({
459
547
  context,
460
548
  options,
461
549
  }: {
@@ -466,6 +554,7 @@ export function readVersionsMetadata({
466
554
  | 'path'
467
555
  | 'sidebarPath'
468
556
  | 'routeBasePath'
557
+ | 'tagsBasePath'
469
558
  | 'includeCurrentVersion'
470
559
  | 'disableVersioning'
471
560
  | 'lastVersion'
@@ -474,8 +563,11 @@ export function readVersionsMetadata({
474
563
  | 'editUrl'
475
564
  | 'editCurrentVersion'
476
565
  >;
477
- }): VersionMetadata[] {
478
- const versionNamesUnfiltered = readVersionNames(context.siteDir, options);
566
+ }): Promise<VersionMetadata[]> {
567
+ const versionNamesUnfiltered = await readVersionNames(
568
+ context.siteDir,
569
+ options,
570
+ );
479
571
 
480
572
  checkVersionsOptions(versionNamesUnfiltered, options);
481
573
 
@@ -487,13 +579,16 @@ export function readVersionsMetadata({
487
579
  const versionsMetadata = versionNames.map((versionName) =>
488
580
  createVersionMetadata({
489
581
  versionName,
490
- isLast: versionName === lastVersionName,
582
+ versionNames,
583
+ lastVersionName,
491
584
  context,
492
585
  options,
493
586
  }),
494
587
  );
495
- versionsMetadata.forEach((versionMetadata) =>
496
- checkVersionMetadataPaths({versionMetadata, context}),
588
+ await Promise.all(
589
+ versionsMetadata.map((versionMetadata) =>
590
+ checkVersionMetadataPaths({versionMetadata, context}),
591
+ ),
497
592
  );
498
593
  return versionsMetadata;
499
594
  }