@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/docs.ts CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  import path from 'path';
9
9
  import fs from 'fs-extra';
10
+ import logger from '@docusaurus/logger';
10
11
  import {
11
12
  aliasedSitePath,
12
13
  getEditUrl,
@@ -14,24 +15,34 @@ import {
14
15
  normalizeUrl,
15
16
  parseMarkdownString,
16
17
  posixPath,
18
+ Globby,
19
+ normalizeFrontMatterTags,
17
20
  } from '@docusaurus/utils';
18
- import {LoadContext} from '@docusaurus/types';
21
+ import type {LoadContext} from '@docusaurus/types';
19
22
 
20
23
  import {getFileLastUpdate} from './lastUpdate';
21
- import {
24
+ import type {
22
25
  DocFile,
23
26
  DocMetadataBase,
27
+ DocMetadata,
28
+ DocNavLink,
24
29
  LastUpdateData,
25
- MetadataOptions,
26
- PluginOptions,
27
30
  VersionMetadata,
31
+ LoadedVersion,
28
32
  } from './types';
29
33
  import getSlug from './slug';
30
34
  import {CURRENT_VERSION_NAME} from './constants';
31
- import globby from 'globby';
32
35
  import {getDocsDirPaths} from './versions';
33
36
  import {stripPathNumberPrefixes} from './numberPrefix';
34
- import {validateDocFrontMatter} from './docFrontMatter';
37
+ import {validateDocFrontMatter} from './frontMatter';
38
+ import type {SidebarsUtils} from './sidebars/utils';
39
+ import {toDocNavigationLink, toNavigationLink} from './sidebars/utils';
40
+ import type {
41
+ MetadataOptions,
42
+ PluginOptions,
43
+ CategoryIndexMatcher,
44
+ CategoryIndexMatcherParam,
45
+ } from '@docusaurus/plugin-content-docs';
35
46
 
36
47
  type LastUpdateOptions = Pick<
37
48
  PluginOptions,
@@ -91,18 +102,19 @@ export async function readVersionDocs(
91
102
  versionMetadata: VersionMetadata,
92
103
  options: Pick<
93
104
  PluginOptions,
94
- 'include' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
105
+ 'include' | 'exclude' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
95
106
  >,
96
107
  ): Promise<DocFile[]> {
97
- const sources = await globby(options.include, {
108
+ const sources = await Globby(options.include, {
98
109
  cwd: versionMetadata.contentPath,
110
+ ignore: options.exclude,
99
111
  });
100
112
  return Promise.all(
101
113
  sources.map((source) => readDocFile(versionMetadata, source, options)),
102
114
  );
103
115
  }
104
116
 
105
- export function processDocMetadata({
117
+ function doProcessDocMetadata({
106
118
  docFile,
107
119
  versionMetadata,
108
120
  context,
@@ -114,7 +126,6 @@ export function processDocMetadata({
114
126
  options: MetadataOptions;
115
127
  }): DocMetadataBase {
116
128
  const {source, content, lastUpdate, contentPath, filePath} = docFile;
117
- const {homePageId} = options;
118
129
  const {siteDir, i18n} = context;
119
130
 
120
131
  const {
@@ -125,12 +136,12 @@ export function processDocMetadata({
125
136
  const frontMatter = validateDocFrontMatter(unsafeFrontMatter);
126
137
 
127
138
  const {
128
- sidebar_label: sidebarLabel,
129
139
  custom_edit_url: customEditURL,
130
140
 
131
- // Strip number prefixes by default (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc) by default,
132
- // but allow to disable this behavior with frontmatterr
133
- parse_number_prefixes = true,
141
+ // Strip number prefixes by default
142
+ // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
143
+ // but allow to disable this behavior with front matter
144
+ parse_number_prefixes: parseNumberPrefixes = true,
134
145
  } = frontMatter;
135
146
 
136
147
  // ex: api/plugins/myDoc -> myDoc
@@ -144,16 +155,17 @@ export function processDocMetadata({
144
155
  // ex: myDoc -> .
145
156
  const sourceDirName = path.dirname(source);
146
157
 
147
- const {filename: unprefixedFileName, numberPrefix} = parse_number_prefixes
158
+ const {filename: unprefixedFileName, numberPrefix} = parseNumberPrefixes
148
159
  ? options.numberPrefixParser(sourceFileNameWithoutExtension)
149
160
  : {filename: sourceFileNameWithoutExtension, numberPrefix: undefined};
150
161
 
151
162
  const baseID: string = frontMatter.id ?? unprefixedFileName;
152
163
  if (baseID.includes('/')) {
153
- throw new Error(`Document id [${baseID}] cannot include "/".`);
164
+ throw new Error(`Document id "${baseID}" cannot include slash.`);
154
165
  }
155
166
 
156
- // For autogenerated sidebars, sidebar position can come from filename number prefix or frontmatter
167
+ // For autogenerated sidebars, sidebar position can come from filename number
168
+ // prefix or front matter
157
169
  const sidebarPosition: number | undefined =
158
170
  frontMatter.sidebar_position ?? numberPrefix;
159
171
 
@@ -166,13 +178,13 @@ export function processDocMetadata({
166
178
  : `version-${versionMetadata.versionName}`;
167
179
 
168
180
  // TODO legacy retrocompatibility
169
- // I think it's bad to affect the frontmatter id with the dirname?
181
+ // I think it's bad to affect the front matter id with the dirname?
170
182
  function computeDirNameIdPrefix() {
171
183
  if (sourceDirName === '.') {
172
184
  return undefined;
173
185
  }
174
186
  // Eventually remove the number prefixes from intermediate directories
175
- return parse_number_prefixes
187
+ return parseNumberPrefixes
176
188
  ? stripPathNumberPrefixes(sourceDirName, options.numberPrefixParser)
177
189
  : sourceDirName;
178
190
  }
@@ -185,29 +197,19 @@ export function processDocMetadata({
185
197
  // legacy versioned id, requires a breaking change to modify this
186
198
  const id = [versionIdPrefix, unversionedId].filter(Boolean).join('/');
187
199
 
188
- // TODO remove soon, deprecated homePageId
189
- const isDocsHomePage = unversionedId === (homePageId ?? '_index');
190
- if (frontMatter.slug && isDocsHomePage) {
191
- throw new Error(
192
- `The docs homepage (homePageId=${homePageId}) is not allowed to have a frontmatter slug=${frontMatter.slug} => you have to choose either homePageId or slug, not both`,
193
- );
194
- }
195
-
196
- const docSlug = isDocsHomePage
197
- ? '/'
198
- : getSlug({
199
- baseID,
200
- dirName: sourceDirName,
201
- frontmatterSlug: frontMatter.slug,
202
- stripDirNumberPrefixes: parse_number_prefixes,
203
- numberPrefixParser: options.numberPrefixParser,
204
- });
200
+ const docSlug = getSlug({
201
+ baseID,
202
+ source,
203
+ sourceDirName,
204
+ frontMatterSlug: frontMatter.slug,
205
+ stripDirNumberPrefixes: parseNumberPrefixes,
206
+ numberPrefixParser: options.numberPrefixParser,
207
+ });
205
208
 
206
- // TODO expose both headingTitle+metaTitle to theme?
207
- // Different fallbacks order on purpose!
208
- // See https://github.com/facebook/docusaurus/issues/4665#issuecomment-825831367
209
- const headingTitle: string = contentTitle ?? frontMatter.title ?? baseID;
210
- // const metaTitle: string = frontMatter.title ?? contentTitle ?? baseID;
209
+ // Note: the title is used by default for page title, sidebar label,
210
+ // pagination buttons... frontMatter.title should be used in priority over
211
+ // contentTitle (because it can contain markdown/JSX syntax)
212
+ const title: string = frontMatter.title ?? contentTitle ?? baseID;
211
213
 
212
214
  const description: string = frontMatter.description ?? excerpt ?? '';
213
215
 
@@ -233,9 +235,8 @@ export function processDocMetadata({
233
235
  ? versionMetadata.versionEditUrlLocalized
234
236
  : versionMetadata.versionEditUrl;
235
237
  return getEditUrl(relativeFilePath, baseVersionEditUrl);
236
- } else {
237
- return undefined;
238
238
  }
239
+ return undefined;
239
240
  }
240
241
 
241
242
  // Assign all of object properties during instantiation (if possible) for
@@ -245,14 +246,14 @@ export function processDocMetadata({
245
246
  return {
246
247
  unversionedId,
247
248
  id,
248
- isDocsHomePage,
249
- title: headingTitle,
249
+ title,
250
250
  description,
251
251
  source: aliasedSitePath(filePath, siteDir),
252
252
  sourceDirName,
253
253
  slug: docSlug,
254
254
  permalink,
255
255
  editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
256
+ tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
256
257
  version: versionMetadata.versionName,
257
258
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
258
259
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
@@ -261,8 +262,173 @@ export function processDocMetadata({
261
262
  lastUpdate.lastUpdatedAt * 1000,
262
263
  )
263
264
  : undefined,
264
- sidebar_label: sidebarLabel,
265
265
  sidebarPosition,
266
266
  frontMatter,
267
267
  };
268
268
  }
269
+
270
+ export function processDocMetadata(args: {
271
+ docFile: DocFile;
272
+ versionMetadata: VersionMetadata;
273
+ context: LoadContext;
274
+ options: MetadataOptions;
275
+ }): DocMetadataBase {
276
+ try {
277
+ return doProcessDocMetadata(args);
278
+ } catch (err) {
279
+ logger.error`Can't process doc metadata for doc at path path=${args.docFile.filePath} in version name=${args.versionMetadata.versionName}`;
280
+ throw err;
281
+ }
282
+ }
283
+
284
+ export function addDocNavigation(
285
+ docsBase: DocMetadataBase[],
286
+ sidebarsUtils: SidebarsUtils,
287
+ sidebarFilePath: string,
288
+ ): LoadedVersion['docs'] {
289
+ const docsById = createDocsByIdIndex(docsBase);
290
+
291
+ sidebarsUtils.checkSidebarsDocIds(
292
+ docsBase.flatMap(getDocIds),
293
+ sidebarFilePath,
294
+ );
295
+
296
+ // Add sidebar/next/previous to the docs
297
+ function addNavData(doc: DocMetadataBase): DocMetadata {
298
+ const navigation = sidebarsUtils.getDocNavigation(
299
+ doc.unversionedId,
300
+ doc.id,
301
+ doc.frontMatter.displayed_sidebar,
302
+ );
303
+
304
+ const toNavigationLinkByDocId = (
305
+ docId: string | null | undefined,
306
+ type: 'prev' | 'next',
307
+ ): DocNavLink | undefined => {
308
+ if (!docId) {
309
+ return undefined;
310
+ }
311
+ const navDoc = docsById[docId];
312
+ if (!navDoc) {
313
+ // This could only happen if user provided the ID through front matter
314
+ throw new Error(
315
+ `Error when loading ${doc.id} in ${doc.sourceDirName}: the pagination_${type} front matter points to a non-existent ID ${docId}.`,
316
+ );
317
+ }
318
+ return toDocNavigationLink(navDoc);
319
+ };
320
+
321
+ const previous =
322
+ doc.frontMatter.pagination_prev !== undefined
323
+ ? toNavigationLinkByDocId(doc.frontMatter.pagination_prev, 'prev')
324
+ : toNavigationLink(navigation.previous, docsById);
325
+ const next =
326
+ doc.frontMatter.pagination_next !== undefined
327
+ ? toNavigationLinkByDocId(doc.frontMatter.pagination_next, 'next')
328
+ : toNavigationLink(navigation.next, docsById);
329
+
330
+ return {...doc, sidebar: navigation.sidebarName, previous, next};
331
+ }
332
+
333
+ const docsWithNavigation = docsBase.map(addNavData);
334
+ // sort to ensure consistent output for tests
335
+ docsWithNavigation.sort((a, b) => a.id.localeCompare(b.id));
336
+ return docsWithNavigation;
337
+ }
338
+
339
+ /**
340
+ * The "main doc" is the "version entry point"
341
+ * We browse this doc by clicking on a version:
342
+ * - the "home" doc (at '/docs/')
343
+ * - the first doc of the first sidebar
344
+ * - a random doc (if no docs are in any sidebar... edge case)
345
+ */
346
+ export function getMainDocId({
347
+ docs,
348
+ sidebarsUtils,
349
+ }: {
350
+ docs: DocMetadataBase[];
351
+ sidebarsUtils: SidebarsUtils;
352
+ }): string {
353
+ function getMainDoc(): DocMetadata {
354
+ const versionHomeDoc = docs.find((doc) => doc.slug === '/');
355
+ const firstDocIdOfFirstSidebar =
356
+ sidebarsUtils.getFirstDocIdOfFirstSidebar();
357
+ if (versionHomeDoc) {
358
+ return versionHomeDoc;
359
+ } else if (firstDocIdOfFirstSidebar) {
360
+ return docs.find(
361
+ (doc) =>
362
+ doc.id === firstDocIdOfFirstSidebar ||
363
+ doc.unversionedId === firstDocIdOfFirstSidebar,
364
+ )!;
365
+ }
366
+ return docs[0]!;
367
+ }
368
+
369
+ return getMainDoc().unversionedId;
370
+ }
371
+
372
+ // By convention, Docusaurus considers some docs are "indexes":
373
+ // - index.md
374
+ // - readme.md
375
+ // - <folder>/<folder>.md
376
+ //
377
+ // This function is the default implementation of this convention
378
+ //
379
+ // Those index docs produce a different behavior
380
+ // - Slugs do not end with a weird "/index" suffix
381
+ // - Auto-generated sidebar categories link to them as intro
382
+ export const isCategoryIndex: CategoryIndexMatcher = ({
383
+ fileName,
384
+ directories,
385
+ }): boolean => {
386
+ const eligibleDocIndexNames = [
387
+ 'index',
388
+ 'readme',
389
+ directories[0]?.toLowerCase(),
390
+ ];
391
+ return eligibleDocIndexNames.includes(fileName.toLowerCase());
392
+ };
393
+
394
+ /**
395
+ * `guides/sidebar/autogenerated.md` ->
396
+ * `'autogenerated', '.md', ['sidebar', 'guides']`
397
+ */
398
+ export function toCategoryIndexMatcherParam({
399
+ source,
400
+ sourceDirName,
401
+ }: Pick<
402
+ DocMetadataBase,
403
+ 'source' | 'sourceDirName'
404
+ >): CategoryIndexMatcherParam {
405
+ // source + sourceDirName are always posix-style
406
+ return {
407
+ fileName: path.posix.parse(source).name,
408
+ extension: path.posix.parse(source).ext,
409
+ directories: sourceDirName.split(path.posix.sep).reverse(),
410
+ };
411
+ }
412
+
413
+ // Return both doc ids
414
+ // TODO legacy retro-compatibility due to old versioned sidebars using
415
+ // versioned doc ids ("id" should be removed & "versionedId" should be renamed
416
+ // to "id")
417
+ export function getDocIds(doc: DocMetadataBase): [string, string] {
418
+ return [doc.unversionedId, doc.id];
419
+ }
420
+
421
+ // docs are indexed by both versioned and unversioned ids at the same time
422
+ // TODO legacy retro-compatibility due to old versioned sidebars using
423
+ // versioned doc ids ("id" should be removed & "versionedId" should be renamed
424
+ // to "id")
425
+ export function createDocsByIdIndex<
426
+ Doc extends {id: string; unversionedId: string},
427
+ >(docs: Doc[]): {[docId: string]: Doc} {
428
+ return Object.fromEntries(
429
+ docs.flatMap((doc) => [
430
+ [doc.unversionedId, doc],
431
+ [doc.id, doc],
432
+ ]),
433
+ );
434
+ }
@@ -5,30 +5,17 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- /* eslint-disable camelcase */
9
-
10
8
  import {
11
- JoiFrontMatter as Joi, // Custom instance for frontmatter
9
+ JoiFrontMatter as Joi, // Custom instance for front matter
10
+ URISchema,
11
+ FrontMatterTagsSchema,
12
+ FrontMatterTOCHeadingLevels,
12
13
  validateFrontMatter,
13
14
  } from '@docusaurus/utils-validation';
14
-
15
- export type DocFrontMatter = {
16
- id?: string;
17
- title?: string;
18
- hide_title?: boolean;
19
- hide_table_of_contents?: boolean;
20
- keywords?: string[];
21
- image?: string;
22
- description?: string;
23
- slug?: string;
24
- sidebar_label?: string;
25
- sidebar_position?: number;
26
- custom_edit_url?: string | null;
27
- parse_number_prefixes?: boolean;
28
- };
15
+ import type {DocFrontMatter} from './types';
29
16
 
30
17
  // NOTE: we don't add any default value on purpose here
31
- // We don't want default values to magically appear in doc metadatas and props
18
+ // We don't want default values to magically appear in doc metadata and props
32
19
  // While the user did not provide those values explicitly
33
20
  // We use default values in code instead
34
21
  const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
@@ -37,17 +24,25 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
37
24
  hide_title: Joi.boolean(),
38
25
  hide_table_of_contents: Joi.boolean(),
39
26
  keywords: Joi.array().items(Joi.string().required()),
40
- image: Joi.string().uri({allowRelative: false}),
41
- description: Joi.string().allow(''), // see https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
27
+ image: URISchema,
28
+ description: Joi.string().allow(''), // see https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
42
29
  slug: Joi.string(),
43
30
  sidebar_label: Joi.string(),
44
- sidebar_position: Joi.number().min(0),
45
- custom_edit_url: Joi.string().uri({allowRelative: true}).allow('', null),
31
+ sidebar_position: Joi.number(),
32
+ sidebar_class_name: Joi.string(),
33
+ sidebar_custom_props: Joi.object().unknown(),
34
+ displayed_sidebar: Joi.string().allow(null),
35
+ tags: FrontMatterTagsSchema,
36
+ pagination_label: Joi.string(),
37
+ custom_edit_url: URISchema.allow('', null),
46
38
  parse_number_prefixes: Joi.boolean(),
39
+ pagination_next: Joi.string().allow(null),
40
+ pagination_prev: Joi.string().allow(null),
41
+ ...FrontMatterTOCHeadingLevels,
47
42
  }).unknown();
48
43
 
49
- export function validateDocFrontMatter(
50
- frontMatter: Record<string, unknown>,
51
- ): DocFrontMatter {
44
+ export function validateDocFrontMatter(frontMatter: {
45
+ [key: string]: unknown;
46
+ }): DocFrontMatter {
52
47
  return validateFrontMatter(frontMatter, DocFrontMatterSchema);
53
48
  }
package/src/globalData.ts CHANGED
@@ -5,9 +5,21 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import {DocMetadata, GlobalDoc, LoadedVersion, GlobalVersion} from './types';
8
+ import _ from 'lodash';
9
+ import type {Sidebars} from './sidebars/types';
10
+ import {createSidebarsUtils} from './sidebars/utils';
11
+ import type {
12
+ CategoryGeneratedIndexMetadata,
13
+ DocMetadata,
14
+ LoadedVersion,
15
+ } from './types';
16
+ import type {
17
+ GlobalVersion,
18
+ GlobalSidebar,
19
+ GlobalDoc,
20
+ } from '@docusaurus/plugin-content-docs/client';
9
21
 
10
- export function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
22
+ function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
11
23
  return {
12
24
  id: doc.unversionedId,
13
25
  path: doc.permalink,
@@ -15,6 +27,41 @@ export function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
15
27
  };
16
28
  }
17
29
 
30
+ function toGlobalDataGeneratedIndex(
31
+ doc: CategoryGeneratedIndexMetadata,
32
+ ): GlobalDoc {
33
+ return {
34
+ id: doc.slug,
35
+ path: doc.permalink,
36
+ sidebar: doc.sidebar,
37
+ };
38
+ }
39
+
40
+ function toGlobalSidebars(
41
+ sidebars: Sidebars,
42
+ version: LoadedVersion,
43
+ ): {[sidebarId: string]: GlobalSidebar} {
44
+ const {getFirstLink} = createSidebarsUtils(sidebars);
45
+ return _.mapValues(sidebars, (sidebar, sidebarId) => {
46
+ const firstLink = getFirstLink(sidebarId);
47
+ if (!firstLink) {
48
+ return {};
49
+ }
50
+ return {
51
+ link: {
52
+ path:
53
+ firstLink.type === 'generated-index'
54
+ ? firstLink.permalink
55
+ : version.docs.find(
56
+ (doc) =>
57
+ doc.id === firstLink.id || doc.unversionedId === firstLink.id,
58
+ )!.permalink,
59
+ label: firstLink.label,
60
+ },
61
+ };
62
+ });
63
+ }
64
+
18
65
  export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
19
66
  return {
20
67
  name: version.versionName,
@@ -22,6 +69,9 @@ export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
22
69
  isLast: version.isLast,
23
70
  path: version.versionPath,
24
71
  mainDocId: version.mainDocId,
25
- docs: version.docs.map(toGlobalDataDoc),
72
+ docs: version.docs
73
+ .map(toGlobalDataDoc)
74
+ .concat(version.categoryGeneratedIndices.map(toGlobalDataGeneratedIndex)),
75
+ sidebars: toGlobalSidebars(version.sidebars, version),
26
76
  };
27
77
  }