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

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 (230) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +12 -0
  2. package/lib/categoryGeneratedIndex.js +37 -0
  3. package/lib/cli.d.ts +3 -2
  4. package/lib/cli.js +65 -69
  5. package/lib/client/docsClientUtils.d.ts +9 -28
  6. package/lib/client/docsClientUtils.js +34 -42
  7. package/lib/client/index.d.ts +22 -0
  8. package/lib/client/index.js +72 -0
  9. package/lib/constants.d.ts +4 -0
  10. package/lib/constants.js +4 -1
  11. package/lib/docs.d.ts +33 -4
  12. package/lib/docs.js +173 -62
  13. package/{src/__tests__/__fixtures__/site-with-doc-label/docusaurus.config.js → lib/frontMatter.d.ts} +4 -8
  14. package/lib/{docFrontMatter.js → frontMatter.js} +16 -6
  15. package/lib/globalData.d.ts +3 -3
  16. package/lib/globalData.js +35 -6
  17. package/lib/index.d.ts +3 -3
  18. package/lib/index.js +135 -140
  19. package/lib/lastUpdate.d.ts +4 -6
  20. package/lib/lastUpdate.js +22 -26
  21. package/lib/markdown/index.d.ts +3 -6
  22. package/lib/markdown/index.js +3 -3
  23. package/lib/markdown/linkify.d.ts +1 -1
  24. package/lib/markdown/linkify.js +7 -4
  25. package/lib/numberPrefix.d.ts +1 -1
  26. package/lib/numberPrefix.js +16 -21
  27. package/lib/options.d.ts +3 -5
  28. package/lib/options.js +55 -19
  29. package/lib/props.d.ts +7 -2
  30. package/lib/props.js +72 -15
  31. package/lib/routes.d.ts +29 -0
  32. package/lib/routes.js +96 -0
  33. package/lib/server-export.d.ts +9 -0
  34. package/lib/server-export.js +22 -0
  35. package/lib/{sidebarItemsGenerator.d.ts → sidebars/generator.d.ts} +1 -6
  36. package/lib/sidebars/generator.js +209 -0
  37. package/lib/sidebars/index.d.ts +13 -0
  38. package/lib/sidebars/index.js +92 -0
  39. package/lib/sidebars/normalization.d.ts +13 -0
  40. package/lib/sidebars/normalization.js +55 -0
  41. package/lib/sidebars/postProcessor.d.ts +8 -0
  42. package/lib/sidebars/postProcessor.js +65 -0
  43. package/lib/sidebars/processor.d.ts +10 -0
  44. package/lib/sidebars/processor.js +90 -0
  45. package/lib/sidebars/types.d.ts +178 -0
  46. package/{src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars2.js → lib/sidebars/types.js} +2 -10
  47. package/lib/sidebars/utils.d.ts +54 -0
  48. package/lib/sidebars/utils.js +255 -0
  49. package/lib/sidebars/validation.d.ts +11 -0
  50. package/lib/sidebars/validation.js +138 -0
  51. package/lib/slug.d.ts +5 -4
  52. package/lib/slug.js +29 -19
  53. package/{src/__tests__/__fixtures__/sidebars/sidebars-first-level-not-category.js → lib/tags.d.ts} +3 -14
  54. package/lib/tags.js +21 -0
  55. package/lib/translations.d.ts +3 -3
  56. package/lib/translations.js +84 -94
  57. package/lib/types.d.ts +13 -171
  58. package/lib/versions/files.d.ts +44 -0
  59. package/lib/versions/files.js +142 -0
  60. package/lib/versions/index.d.ts +36 -0
  61. package/lib/versions/index.js +155 -0
  62. package/lib/versions/validation.d.ts +17 -0
  63. package/lib/versions/validation.js +71 -0
  64. package/package.json +32 -26
  65. package/src/categoryGeneratedIndex.ts +60 -0
  66. package/src/cli.ts +90 -109
  67. package/src/client/docsClientUtils.ts +47 -84
  68. package/src/client/index.ts +103 -0
  69. package/src/constants.ts +4 -2
  70. package/{types.d.ts → src/deps.d.ts} +1 -1
  71. package/src/docs.ts +244 -63
  72. package/src/frontMatter.ts +51 -0
  73. package/src/globalData.ts +57 -7
  74. package/src/index.ts +186 -190
  75. package/src/lastUpdate.ts +26 -33
  76. package/src/markdown/index.ts +10 -16
  77. package/src/markdown/linkify.ts +8 -5
  78. package/src/numberPrefix.ts +19 -26
  79. package/src/options.ts +60 -32
  80. package/src/plugin-content-docs.d.ts +632 -75
  81. package/src/props.ts +109 -22
  82. package/src/routes.ts +159 -0
  83. package/src/server-export.ts +22 -0
  84. package/src/sidebars/README.md +9 -0
  85. package/src/sidebars/generator.ts +292 -0
  86. package/src/sidebars/index.ts +118 -0
  87. package/src/sidebars/normalization.ts +85 -0
  88. package/src/sidebars/postProcessor.ts +89 -0
  89. package/src/sidebars/processor.ts +139 -0
  90. package/src/sidebars/types.ts +275 -0
  91. package/src/sidebars/utils.ts +391 -0
  92. package/src/sidebars/validation.ts +174 -0
  93. package/src/slug.ts +42 -23
  94. package/src/tags.ts +20 -0
  95. package/src/translations.ts +124 -117
  96. package/src/types.ts +18 -231
  97. package/src/versions/files.ts +220 -0
  98. package/src/versions/index.ts +247 -0
  99. package/src/versions/validation.ts +113 -0
  100. package/lib/.tsbuildinfo +0 -4673
  101. package/lib/docFrontMatter.d.ts +0 -21
  102. package/lib/sidebarItemsGenerator.js +0 -211
  103. package/lib/sidebars.d.ts +0 -42
  104. package/lib/sidebars.js +0 -309
  105. package/lib/theme/hooks/useDocs.d.ts +0 -20
  106. package/lib/theme/hooks/useDocs.js +0 -72
  107. package/lib/versions.d.ts +0 -16
  108. package/lib/versions.js +0 -287
  109. package/src/__tests__/__fixtures__/bad-id-site/docs/invalid-id.md +0 -5
  110. package/src/__tests__/__fixtures__/bad-slug-on-doc-home-site/docs/docWithSlug.md +0 -5
  111. package/src/__tests__/__fixtures__/empty-site/docusaurus.config.js +0 -16
  112. package/src/__tests__/__fixtures__/empty-site/sidebars.json +0 -1
  113. package/src/__tests__/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -34
  114. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -11
  115. package/src/__tests__/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -11
  116. package/src/__tests__/__fixtures__/sidebars/sidebars-category.js +0 -44
  117. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -20
  118. package/src/__tests__/__fixtures__/sidebars/sidebars-collapsed.json +0 -21
  119. package/src/__tests__/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -10
  120. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -11
  121. package/src/__tests__/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -11
  122. package/src/__tests__/__fixtures__/sidebars/sidebars-link.json +0 -11
  123. package/src/__tests__/__fixtures__/sidebars/sidebars-unknown-type.json +0 -14
  124. package/src/__tests__/__fixtures__/sidebars/sidebars-wrong-field.json +0 -20
  125. package/src/__tests__/__fixtures__/sidebars/sidebars.json +0 -20
  126. package/src/__tests__/__fixtures__/simple-site/docs/foo/bar.md +0 -69
  127. package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +0 -67
  128. package/src/__tests__/__fixtures__/simple-site/docs/headingAsTitle.md +0 -1
  129. package/src/__tests__/__fixtures__/simple-site/docs/hello.md +0 -52
  130. package/src/__tests__/__fixtures__/simple-site/docs/ipsum.md +0 -5
  131. package/src/__tests__/__fixtures__/simple-site/docs/lorem.md +0 -6
  132. package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +0 -5
  133. package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +0 -5
  134. package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +0 -5
  135. package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +0 -5
  136. package/src/__tests__/__fixtures__/simple-site/docs/slugs/absoluteSlug.md +0 -5
  137. package/src/__tests__/__fixtures__/simple-site/docs/slugs/relativeSlug.md +0 -5
  138. package/src/__tests__/__fixtures__/simple-site/docs/slugs/resolvedSlug.md +0 -5
  139. package/src/__tests__/__fixtures__/simple-site/docs/slugs/tryToEscapeSlug.md +0 -5
  140. package/src/__tests__/__fixtures__/simple-site/docusaurus.config.js +0 -14
  141. package/src/__tests__/__fixtures__/simple-site/sidebars.json +0 -23
  142. package/src/__tests__/__fixtures__/simple-site/wrong-sidebars.json +0 -7
  143. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/0-getting-started.md +0 -3
  144. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/1-installation.md +0 -3
  145. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/00_api-overview.md +0 -3
  146. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/0 --- Client API.md +0 -1
  147. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/01_Core APIs/1 --- Server API.md +0 -1
  148. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/0. Plugin API.md +0 -1
  149. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/1. Theme API.md +0 -1
  150. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/02_Extension APIs/_category_.yml +0 -1
  151. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/03_api-end.md +0 -3
  152. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/3-API/_category_.json +0 -3
  153. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/0-guide2.5.md +0 -8
  154. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/02-guide2.md +0 -7
  155. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/_category_.json +0 -3
  156. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/a-guide4.md +0 -7
  157. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/b-guide5.md +0 -7
  158. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/guide3.md +0 -8
  159. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docs/Guides/z-guide1.md +0 -8
  160. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/docusaurus.config.js +0 -14
  161. package/src/__tests__/__fixtures__/site-with-autogenerated-sidebar/partialAutogeneratedSidebars.js +0 -23
  162. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-1.md +0 -7
  163. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-2.md +0 -8
  164. package/src/__tests__/__fixtures__/site-with-doc-label/sidebars.json +0 -14
  165. package/src/__tests__/__fixtures__/versioned-site/community/team.md +0 -1
  166. package/src/__tests__/__fixtures__/versioned-site/community_sidebars.json +0 -3
  167. package/src/__tests__/__fixtures__/versioned-site/community_versioned_docs/version-1.0.0/team.md +0 -1
  168. package/src/__tests__/__fixtures__/versioned-site/community_versioned_sidebars/version-1.0.0-sidebars.json +0 -3
  169. package/src/__tests__/__fixtures__/versioned-site/community_versions.json +0 -1
  170. package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +0 -4
  171. package/src/__tests__/__fixtures__/versioned-site/docs/hello.md +0 -1
  172. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/absoluteSlug.md +0 -5
  173. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/relativeSlug.md +0 -5
  174. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/resolvedSlug.md +0 -5
  175. package/src/__tests__/__fixtures__/versioned-site/docs/slugs/tryToEscapeSlug.md +0 -5
  176. package/src/__tests__/__fixtures__/versioned-site/docusaurus.config.js +0 -18
  177. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  178. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs-community/current/team.md +0 -5
  179. package/src/__tests__/__fixtures__/versioned-site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md +0 -1
  180. package/src/__tests__/__fixtures__/versioned-site/sidebars.json +0 -10
  181. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/bar.md +0 -4
  182. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/foo/baz.md +0 -1
  183. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/hello.md +0 -1
  184. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/foo/bar.md +0 -1
  185. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/hello.md +0 -1
  186. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootAbsoluteSlug.md +0 -5
  187. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootRelativeSlug.md +0 -5
  188. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootResolvedSlug.md +0 -5
  189. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/rootTryToEscapeSlug.md +0 -5
  190. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/absoluteSlug.md +0 -5
  191. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/relativeSlug.md +0 -5
  192. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/resolvedSlug.md +0 -5
  193. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-withSlugs/slugs/tryToEscapeSlug.md +0 -5
  194. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.0-sidebars.json +0 -11
  195. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.1-sidebars.json +0 -10
  196. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-withSlugs-sidebars.json +0 -5
  197. package/src/__tests__/__fixtures__/versioned-site/versions.json +0 -5
  198. package/src/__tests__/__snapshots__/cli.test.ts.snap +0 -90
  199. package/src/__tests__/__snapshots__/index.test.ts.snap +0 -1907
  200. package/src/__tests__/__snapshots__/sidebars.test.ts.snap +0 -218
  201. package/src/__tests__/__snapshots__/translations.test.ts.snap +0 -487
  202. package/src/__tests__/cli.test.ts +0 -333
  203. package/src/__tests__/docFrontMatter.test.ts +0 -204
  204. package/src/__tests__/docs.test.ts +0 -875
  205. package/src/__tests__/index.test.ts +0 -1831
  206. package/src/__tests__/lastUpdate.test.ts +0 -68
  207. package/src/__tests__/numberPrefix.test.ts +0 -199
  208. package/src/__tests__/options.test.ts +0 -232
  209. package/src/__tests__/sidebarItemsGenerator.test.ts +0 -336
  210. package/src/__tests__/sidebars.test.ts +0 -638
  211. package/src/__tests__/slug.test.ts +0 -109
  212. package/src/__tests__/translations.test.ts +0 -159
  213. package/src/__tests__/versions.test.ts +0 -718
  214. package/src/client/__tests__/docsClientUtils.test.ts +0 -372
  215. package/src/docFrontMatter.ts +0 -53
  216. package/src/markdown/__tests__/__fixtures__/docs/doc-localized.md +0 -1
  217. package/src/markdown/__tests__/__fixtures__/docs/doc1.md +0 -13
  218. package/src/markdown/__tests__/__fixtures__/docs/doc2.md +0 -12
  219. package/src/markdown/__tests__/__fixtures__/docs/doc4.md +0 -19
  220. package/src/markdown/__tests__/__fixtures__/docs/doc5.md +0 -6
  221. package/src/markdown/__tests__/__fixtures__/docs/subdir/doc3.md +0 -3
  222. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/doc2.md +0 -7
  223. package/src/markdown/__tests__/__fixtures__/versioned_docs/version-1.0.0/subdir/doc1.md +0 -3
  224. package/src/markdown/__tests__/__snapshots__/linkify.test.ts.snap +0 -82
  225. package/src/markdown/__tests__/linkify.test.ts +0 -190
  226. package/src/sidebarItemsGenerator.ts +0 -307
  227. package/src/sidebars.ts +0 -489
  228. package/src/theme/hooks/useDocs.ts +0 -99
  229. package/src/versions.ts +0 -511
  230. package/tsconfig.json +0 -9
package/src/docs.ts CHANGED
@@ -7,31 +7,40 @@
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,
13
14
  getFolderContainingFile,
15
+ getContentPathList,
14
16
  normalizeUrl,
15
17
  parseMarkdownString,
16
18
  posixPath,
19
+ Globby,
20
+ normalizeFrontMatterTags,
17
21
  } from '@docusaurus/utils';
18
- import {LoadContext} from '@docusaurus/types';
22
+ import type {LoadContext} from '@docusaurus/types';
19
23
 
20
24
  import {getFileLastUpdate} from './lastUpdate';
21
- import {
22
- DocFile,
23
- DocMetadataBase,
24
- LastUpdateData,
25
- MetadataOptions,
26
- PluginOptions,
27
- VersionMetadata,
28
- } from './types';
25
+ import type {DocFile} from './types';
29
26
  import getSlug from './slug';
30
27
  import {CURRENT_VERSION_NAME} from './constants';
31
- import globby from 'globby';
32
- import {getDocsDirPaths} from './versions';
33
28
  import {stripPathNumberPrefixes} from './numberPrefix';
34
- import {validateDocFrontMatter} from './docFrontMatter';
29
+ import {validateDocFrontMatter} from './frontMatter';
30
+ import type {SidebarsUtils} from './sidebars/utils';
31
+ import {toDocNavigationLink, toNavigationLink} from './sidebars/utils';
32
+ import type {
33
+ MetadataOptions,
34
+ PluginOptions,
35
+ CategoryIndexMatcher,
36
+ DocMetadataBase,
37
+ DocMetadata,
38
+ PropNavigationLink,
39
+ LastUpdateData,
40
+ VersionMetadata,
41
+ DocFrontMatter,
42
+ LoadedVersion,
43
+ } from '@docusaurus/plugin-content-docs';
35
44
 
36
45
  type LastUpdateOptions = Pick<
37
46
  PluginOptions,
@@ -74,7 +83,7 @@ export async function readDocFile(
74
83
  options: LastUpdateOptions,
75
84
  ): Promise<DocFile> {
76
85
  const contentPath = await getFolderContainingFile(
77
- getDocsDirPaths(versionMetadata),
86
+ getContentPathList(versionMetadata),
78
87
  source,
79
88
  );
80
89
 
@@ -91,30 +100,45 @@ export async function readVersionDocs(
91
100
  versionMetadata: VersionMetadata,
92
101
  options: Pick<
93
102
  PluginOptions,
94
- 'include' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
103
+ 'include' | 'exclude' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
95
104
  >,
96
105
  ): Promise<DocFile[]> {
97
- const sources = await globby(options.include, {
106
+ const sources = await Globby(options.include, {
98
107
  cwd: versionMetadata.contentPath,
108
+ ignore: options.exclude,
99
109
  });
100
110
  return Promise.all(
101
111
  sources.map((source) => readDocFile(versionMetadata, source, options)),
102
112
  );
103
113
  }
104
114
 
105
- export function processDocMetadata({
115
+ export type DocEnv = 'production' | 'development';
116
+
117
+ /** Docs with draft front matter are only considered draft in production. */
118
+ function isDraftForEnvironment({
119
+ env,
120
+ frontMatter,
121
+ }: {
122
+ frontMatter: DocFrontMatter;
123
+ env: DocEnv;
124
+ }): boolean {
125
+ return (env === 'production' && frontMatter.draft) ?? false;
126
+ }
127
+
128
+ function doProcessDocMetadata({
106
129
  docFile,
107
130
  versionMetadata,
108
131
  context,
109
132
  options,
133
+ env,
110
134
  }: {
111
135
  docFile: DocFile;
112
136
  versionMetadata: VersionMetadata;
113
137
  context: LoadContext;
114
138
  options: MetadataOptions;
139
+ env: DocEnv;
115
140
  }): DocMetadataBase {
116
141
  const {source, content, lastUpdate, contentPath, filePath} = docFile;
117
- const {homePageId} = options;
118
142
  const {siteDir, i18n} = context;
119
143
 
120
144
  const {
@@ -125,35 +149,34 @@ export function processDocMetadata({
125
149
  const frontMatter = validateDocFrontMatter(unsafeFrontMatter);
126
150
 
127
151
  const {
128
- sidebar_label: sidebarLabel,
129
152
  custom_edit_url: customEditURL,
130
153
 
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,
154
+ // Strip number prefixes by default
155
+ // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
156
+ // but allow to disable this behavior with front matter
157
+ parse_number_prefixes: parseNumberPrefixes = true,
134
158
  } = frontMatter;
135
159
 
136
- // ex: api/plugins/myDoc -> myDoc
137
- // ex: myDoc -> myDoc
160
+ // E.g. api/plugins/myDoc -> myDoc; myDoc -> myDoc
138
161
  const sourceFileNameWithoutExtension = path.basename(
139
162
  source,
140
163
  path.extname(source),
141
164
  );
142
165
 
143
- // ex: api/plugins/myDoc -> api/plugins
144
- // ex: myDoc -> .
166
+ // E.g. api/plugins/myDoc -> api/plugins; myDoc -> .
145
167
  const sourceDirName = path.dirname(source);
146
168
 
147
- const {filename: unprefixedFileName, numberPrefix} = parse_number_prefixes
169
+ const {filename: unprefixedFileName, numberPrefix} = parseNumberPrefixes
148
170
  ? options.numberPrefixParser(sourceFileNameWithoutExtension)
149
171
  : {filename: sourceFileNameWithoutExtension, numberPrefix: undefined};
150
172
 
151
173
  const baseID: string = frontMatter.id ?? unprefixedFileName;
152
174
  if (baseID.includes('/')) {
153
- throw new Error(`Document id [${baseID}] cannot include "/".`);
175
+ throw new Error(`Document id "${baseID}" cannot include slash.`);
154
176
  }
155
177
 
156
- // For autogenerated sidebars, sidebar position can come from filename number prefix or frontmatter
178
+ // For autogenerated sidebars, sidebar position can come from filename number
179
+ // prefix or front matter
157
180
  const sidebarPosition: number | undefined =
158
181
  frontMatter.sidebar_position ?? numberPrefix;
159
182
 
@@ -166,13 +189,13 @@ export function processDocMetadata({
166
189
  : `version-${versionMetadata.versionName}`;
167
190
 
168
191
  // TODO legacy retrocompatibility
169
- // I think it's bad to affect the frontmatter id with the dirname?
192
+ // I think it's bad to affect the front matter id with the dirname?
170
193
  function computeDirNameIdPrefix() {
171
194
  if (sourceDirName === '.') {
172
195
  return undefined;
173
196
  }
174
197
  // Eventually remove the number prefixes from intermediate directories
175
- return parse_number_prefixes
198
+ return parseNumberPrefixes
176
199
  ? stripPathNumberPrefixes(sourceDirName, options.numberPrefixParser)
177
200
  : sourceDirName;
178
201
  }
@@ -185,33 +208,23 @@ export function processDocMetadata({
185
208
  // legacy versioned id, requires a breaking change to modify this
186
209
  const id = [versionIdPrefix, unversionedId].filter(Boolean).join('/');
187
210
 
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
- });
211
+ const docSlug = getSlug({
212
+ baseID,
213
+ source,
214
+ sourceDirName,
215
+ frontMatterSlug: frontMatter.slug,
216
+ stripDirNumberPrefixes: parseNumberPrefixes,
217
+ numberPrefixParser: options.numberPrefixParser,
218
+ });
205
219
 
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;
220
+ // Note: the title is used by default for page title, sidebar label,
221
+ // pagination buttons... frontMatter.title should be used in priority over
222
+ // contentTitle (because it can contain markdown/JSX syntax)
223
+ const title: string = frontMatter.title ?? contentTitle ?? baseID;
211
224
 
212
225
  const description: string = frontMatter.description ?? excerpt ?? '';
213
226
 
214
- const permalink = normalizeUrl([versionMetadata.versionPath, docSlug]);
227
+ const permalink = normalizeUrl([versionMetadata.path, docSlug]);
215
228
 
216
229
  function getDocEditUrl() {
217
230
  const relativeFilePath = path.relative(contentPath, filePath);
@@ -230,14 +243,15 @@ export function processDocMetadata({
230
243
  const isLocalized = contentPath === versionMetadata.contentPathLocalized;
231
244
  const baseVersionEditUrl =
232
245
  isLocalized && options.editLocalizedFiles
233
- ? versionMetadata.versionEditUrlLocalized
234
- : versionMetadata.versionEditUrl;
246
+ ? versionMetadata.editUrlLocalized
247
+ : versionMetadata.editUrl;
235
248
  return getEditUrl(relativeFilePath, baseVersionEditUrl);
236
- } else {
237
- return undefined;
238
249
  }
250
+ return undefined;
239
251
  }
240
252
 
253
+ const draft = isDraftForEnvironment({env, frontMatter});
254
+
241
255
  // Assign all of object properties during instantiation (if possible) for
242
256
  // NodeJS optimization.
243
257
  // Adding properties to object after instantiation will cause hidden
@@ -245,24 +259,191 @@ export function processDocMetadata({
245
259
  return {
246
260
  unversionedId,
247
261
  id,
248
- isDocsHomePage,
249
- title: headingTitle,
262
+ title,
250
263
  description,
251
264
  source: aliasedSitePath(filePath, siteDir),
252
265
  sourceDirName,
253
266
  slug: docSlug,
254
267
  permalink,
268
+ draft,
255
269
  editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
270
+ tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
256
271
  version: versionMetadata.versionName,
257
272
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
258
273
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
259
274
  formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
260
- ? new Intl.DateTimeFormat(i18n.currentLocale).format(
261
- lastUpdate.lastUpdatedAt * 1000,
262
- )
275
+ ? new Intl.DateTimeFormat(i18n.currentLocale, {
276
+ calendar: i18n.localeConfigs[i18n.currentLocale]!.calendar,
277
+ }).format(lastUpdate.lastUpdatedAt * 1000)
263
278
  : undefined,
264
- sidebar_label: sidebarLabel,
265
279
  sidebarPosition,
266
280
  frontMatter,
267
281
  };
268
282
  }
283
+
284
+ export function processDocMetadata(args: {
285
+ docFile: DocFile;
286
+ versionMetadata: VersionMetadata;
287
+ context: LoadContext;
288
+ options: MetadataOptions;
289
+ env: DocEnv;
290
+ }): DocMetadataBase {
291
+ try {
292
+ return doProcessDocMetadata(args);
293
+ } catch (err) {
294
+ logger.error`Can't process doc metadata for doc at path path=${args.docFile.filePath} in version name=${args.versionMetadata.versionName}`;
295
+ throw err;
296
+ }
297
+ }
298
+
299
+ export function addDocNavigation(
300
+ docsBase: DocMetadataBase[],
301
+ sidebarsUtils: SidebarsUtils,
302
+ sidebarFilePath: string,
303
+ ): LoadedVersion['docs'] {
304
+ const docsById = createDocsByIdIndex(docsBase);
305
+
306
+ sidebarsUtils.checkSidebarsDocIds(
307
+ docsBase.flatMap(getDocIds),
308
+ sidebarFilePath,
309
+ );
310
+
311
+ // Add sidebar/next/previous to the docs
312
+ function addNavData(doc: DocMetadataBase): DocMetadata {
313
+ const navigation = sidebarsUtils.getDocNavigation(
314
+ doc.unversionedId,
315
+ doc.id,
316
+ doc.frontMatter.displayed_sidebar,
317
+ );
318
+
319
+ const toNavigationLinkByDocId = (
320
+ docId: string | null | undefined,
321
+ type: 'prev' | 'next',
322
+ ): PropNavigationLink | undefined => {
323
+ if (!docId) {
324
+ return undefined;
325
+ }
326
+ const navDoc = docsById[docId];
327
+ if (!navDoc) {
328
+ // This could only happen if user provided the ID through front matter
329
+ throw new Error(
330
+ `Error when loading ${doc.id} in ${doc.sourceDirName}: the pagination_${type} front matter points to a non-existent ID ${docId}.`,
331
+ );
332
+ }
333
+ return toDocNavigationLink(navDoc);
334
+ };
335
+
336
+ const previous =
337
+ doc.frontMatter.pagination_prev !== undefined
338
+ ? toNavigationLinkByDocId(doc.frontMatter.pagination_prev, 'prev')
339
+ : toNavigationLink(navigation.previous, docsById);
340
+ const next =
341
+ doc.frontMatter.pagination_next !== undefined
342
+ ? toNavigationLinkByDocId(doc.frontMatter.pagination_next, 'next')
343
+ : toNavigationLink(navigation.next, docsById);
344
+
345
+ return {...doc, sidebar: navigation.sidebarName, previous, next};
346
+ }
347
+
348
+ const docsWithNavigation = docsBase.map(addNavData);
349
+ // Sort to ensure consistent output for tests
350
+ docsWithNavigation.sort((a, b) => a.id.localeCompare(b.id));
351
+ return docsWithNavigation;
352
+ }
353
+
354
+ /**
355
+ * The "main doc" is the "version entry point"
356
+ * We browse this doc by clicking on a version:
357
+ * - the "home" doc (at '/docs/')
358
+ * - the first doc of the first sidebar
359
+ * - a random doc (if no docs are in any sidebar... edge case)
360
+ */
361
+ export function getMainDocId({
362
+ docs,
363
+ sidebarsUtils,
364
+ }: {
365
+ docs: DocMetadataBase[];
366
+ sidebarsUtils: SidebarsUtils;
367
+ }): string {
368
+ function getMainDoc(): DocMetadata {
369
+ const versionHomeDoc = docs.find((doc) => doc.slug === '/');
370
+ const firstDocIdOfFirstSidebar =
371
+ sidebarsUtils.getFirstDocIdOfFirstSidebar();
372
+ if (versionHomeDoc) {
373
+ return versionHomeDoc;
374
+ } else if (firstDocIdOfFirstSidebar) {
375
+ return docs.find(
376
+ (doc) =>
377
+ doc.id === firstDocIdOfFirstSidebar ||
378
+ doc.unversionedId === firstDocIdOfFirstSidebar,
379
+ )!;
380
+ }
381
+ return docs[0]!;
382
+ }
383
+
384
+ return getMainDoc().unversionedId;
385
+ }
386
+
387
+ // By convention, Docusaurus considers some docs are "indexes":
388
+ // - index.md
389
+ // - readme.md
390
+ // - <folder>/<folder>.md
391
+ //
392
+ // This function is the default implementation of this convention
393
+ //
394
+ // Those index docs produce a different behavior
395
+ // - Slugs do not end with a weird "/index" suffix
396
+ // - Auto-generated sidebar categories link to them as intro
397
+ export const isCategoryIndex: CategoryIndexMatcher = ({
398
+ fileName,
399
+ directories,
400
+ }): boolean => {
401
+ const eligibleDocIndexNames = [
402
+ 'index',
403
+ 'readme',
404
+ directories[0]?.toLowerCase(),
405
+ ];
406
+ return eligibleDocIndexNames.includes(fileName.toLowerCase());
407
+ };
408
+
409
+ /**
410
+ * `guides/sidebar/autogenerated.md` ->
411
+ * `'autogenerated', '.md', ['sidebar', 'guides']`
412
+ */
413
+ export function toCategoryIndexMatcherParam({
414
+ source,
415
+ sourceDirName,
416
+ }: Pick<
417
+ DocMetadataBase,
418
+ 'source' | 'sourceDirName'
419
+ >): Parameters<CategoryIndexMatcher>[0] {
420
+ // source + sourceDirName are always posix-style
421
+ return {
422
+ fileName: path.posix.parse(source).name,
423
+ extension: path.posix.parse(source).ext,
424
+ directories: sourceDirName.split(path.posix.sep).reverse(),
425
+ };
426
+ }
427
+
428
+ // Return both doc ids
429
+ // TODO legacy retro-compatibility due to old versioned sidebars using
430
+ // versioned doc ids ("id" should be removed & "versionedId" should be renamed
431
+ // to "id")
432
+ export function getDocIds(doc: DocMetadataBase): [string, string] {
433
+ return [doc.unversionedId, doc.id];
434
+ }
435
+
436
+ // Docs are indexed by both versioned and unversioned ids at the same time
437
+ // TODO legacy retro-compatibility due to old versioned sidebars using
438
+ // versioned doc ids ("id" should be removed & "versionedId" should be renamed
439
+ // to "id")
440
+ export function createDocsByIdIndex<
441
+ Doc extends {id: string; unversionedId: string},
442
+ >(docs: Doc[]): {[docId: string]: Doc} {
443
+ return Object.fromEntries(
444
+ docs.flatMap((doc) => [
445
+ [doc.unversionedId, doc],
446
+ [doc.id, doc],
447
+ ]),
448
+ );
449
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import {
9
+ JoiFrontMatter as Joi, // Custom instance for front matter
10
+ URISchema,
11
+ FrontMatterTagsSchema,
12
+ FrontMatterTOCHeadingLevels,
13
+ validateFrontMatter,
14
+ } from '@docusaurus/utils-validation';
15
+ import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
16
+
17
+ // NOTE: we don't add any default value on purpose here
18
+ // We don't want default values to magically appear in doc metadata and props
19
+ // While the user did not provide those values explicitly
20
+ // We use default values in code instead
21
+ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
22
+ id: Joi.string(),
23
+ // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
24
+ title: Joi.string().allow(''),
25
+ hide_title: Joi.boolean(),
26
+ hide_table_of_contents: Joi.boolean(),
27
+ keywords: Joi.array().items(Joi.string().required()),
28
+ image: URISchema,
29
+ // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
30
+ description: Joi.string().allow(''),
31
+ slug: Joi.string(),
32
+ sidebar_label: Joi.string(),
33
+ sidebar_position: Joi.number(),
34
+ sidebar_class_name: Joi.string(),
35
+ sidebar_custom_props: Joi.object().unknown(),
36
+ displayed_sidebar: Joi.string().allow(null),
37
+ tags: FrontMatterTagsSchema,
38
+ pagination_label: Joi.string(),
39
+ custom_edit_url: URISchema.allow('', null),
40
+ parse_number_prefixes: Joi.boolean(),
41
+ pagination_next: Joi.string().allow(null),
42
+ pagination_prev: Joi.string().allow(null),
43
+ draft: Joi.boolean(),
44
+ ...FrontMatterTOCHeadingLevels,
45
+ }).unknown();
46
+
47
+ export function validateDocFrontMatter(frontMatter: {
48
+ [key: string]: unknown;
49
+ }): DocFrontMatter {
50
+ return validateFrontMatter(frontMatter, DocFrontMatterSchema);
51
+ }
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 {getMainDocId} from './docs';
11
+ import type {FullVersion} from './types';
12
+ import type {
13
+ CategoryGeneratedIndexMetadata,
14
+ DocMetadata,
15
+ } from '@docusaurus/plugin-content-docs';
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,13 +27,51 @@ export function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
15
27
  };
16
28
  }
17
29
 
18
- export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
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: FullVersion,
43
+ ): {[sidebarId: string]: GlobalSidebar} {
44
+ return _.mapValues(sidebars, (sidebar, sidebarId) => {
45
+ const firstLink = version.sidebarsUtils.getFirstLink(sidebarId);
46
+ if (!firstLink) {
47
+ return {};
48
+ }
49
+ return {
50
+ link: {
51
+ path:
52
+ firstLink.type === 'generated-index'
53
+ ? firstLink.permalink
54
+ : version.docs.find(
55
+ (doc) =>
56
+ doc.id === firstLink.id || doc.unversionedId === firstLink.id,
57
+ )!.permalink,
58
+ label: firstLink.label,
59
+ },
60
+ };
61
+ });
62
+ }
63
+
64
+ export function toGlobalDataVersion(version: FullVersion): GlobalVersion {
19
65
  return {
20
66
  name: version.versionName,
21
- label: version.versionLabel,
67
+ label: version.label,
22
68
  isLast: version.isLast,
23
- path: version.versionPath,
24
- mainDocId: version.mainDocId,
25
- docs: version.docs.map(toGlobalDataDoc),
69
+ path: version.path,
70
+ mainDocId: getMainDocId(version),
71
+ docs: version.docs
72
+ .map(toGlobalDataDoc)
73
+ .concat(version.categoryGeneratedIndices.map(toGlobalDataGeneratedIndex)),
74
+ draftIds: version.drafts.map((doc) => doc.unversionedId),
75
+ sidebars: toGlobalSidebars(version.sidebars, version),
26
76
  };
27
77
  }