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

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 (138) hide show
  1. package/lib/.tsbuildinfo +1 -1
  2. package/lib/categoryGeneratedIndex.d.ts +12 -0
  3. package/lib/categoryGeneratedIndex.js +37 -0
  4. package/lib/cli.d.ts +2 -2
  5. package/lib/cli.js +12 -34
  6. package/lib/client/docsClientUtils.d.ts +0 -3
  7. package/lib/client/docsClientUtils.js +19 -22
  8. package/lib/docFrontMatter.d.ts +1 -1
  9. package/lib/docFrontMatter.js +7 -3
  10. package/lib/docs.d.ts +25 -3
  11. package/lib/docs.js +125 -41
  12. package/lib/globalData.d.ts +1 -1
  13. package/lib/index.d.ts +1 -1
  14. package/lib/index.js +100 -131
  15. package/lib/lastUpdate.js +8 -9
  16. package/lib/markdown/index.d.ts +3 -6
  17. package/lib/markdown/index.js +3 -3
  18. package/lib/markdown/linkify.js +2 -2
  19. package/lib/numberPrefix.d.ts +1 -1
  20. package/lib/options.d.ts +3 -3
  21. package/lib/options.js +48 -11
  22. package/lib/props.d.ts +7 -2
  23. package/lib/props.js +60 -8
  24. package/lib/routes.d.ts +27 -0
  25. package/lib/routes.js +105 -0
  26. package/lib/{sidebarItemsGenerator.d.ts → sidebars/generator.d.ts} +5 -2
  27. package/lib/sidebars/generator.js +216 -0
  28. package/lib/sidebars/index.d.ts +15 -0
  29. package/lib/sidebars/index.js +73 -0
  30. package/lib/sidebars/normalization.d.ts +14 -0
  31. package/lib/sidebars/normalization.js +77 -0
  32. package/lib/sidebars/processor.d.ts +18 -0
  33. package/lib/sidebars/processor.js +85 -0
  34. package/lib/sidebars/types.d.ts +127 -0
  35. package/lib/sidebars/types.js +8 -0
  36. package/lib/sidebars/utils.d.ts +35 -0
  37. package/lib/sidebars/utils.js +228 -0
  38. package/lib/sidebars/validation.d.ts +10 -0
  39. package/lib/sidebars/validation.js +138 -0
  40. package/lib/slug.d.ts +4 -3
  41. package/lib/slug.js +27 -15
  42. package/lib/tags.d.ts +8 -0
  43. package/lib/tags.js +20 -0
  44. package/lib/theme/hooks/useDocs.js +21 -21
  45. package/lib/translations.d.ts +2 -2
  46. package/lib/translations.js +71 -29
  47. package/lib/types.d.ts +52 -63
  48. package/lib/versions.d.ts +3 -3
  49. package/lib/versions.js +41 -22
  50. package/package.json +20 -20
  51. package/src/__tests__/__fixtures__/simple-site/docs/_partials/somePartial.md +3 -0
  52. package/src/__tests__/__fixtures__/simple-site/docs/_partials/subfolder/somePartial.md +3 -0
  53. package/src/__tests__/__fixtures__/simple-site/docs/_somePartial.md +3 -0
  54. package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +5 -0
  55. package/src/__tests__/__fixtures__/simple-site/docs/hello.md +2 -0
  56. package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +2 -0
  57. package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +2 -0
  58. package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +2 -0
  59. package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +2 -0
  60. package/src/__tests__/__fixtures__/simple-site/sidebars.json +15 -1
  61. package/src/__tests__/__fixtures__/site-with-doc-label/docs/hello-1.md +1 -0
  62. package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +6 -0
  63. package/src/__tests__/__fixtures__/versioned-site/docs/hello.md +3 -0
  64. package/src/__tests__/__fixtures__/versioned-site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md +3 -0
  65. package/src/__tests__/__fixtures__/versioned-site/i18n/fr/docusaurus-plugin-content-docs/version-1.0.0/hello.md +3 -0
  66. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.0/hello.md +3 -0
  67. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_partials/somePartial.md +3 -0
  68. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_partials/subfolder/somePartial.md +3 -0
  69. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_somePartial.md +3 -0
  70. package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/hello.md +3 -0
  71. package/src/__tests__/__fixtures__/versioned-site/versioned_sidebars/version-1.0.1-sidebars.json +2 -2
  72. package/src/__tests__/__snapshots__/cli.test.ts.snap +48 -73
  73. package/src/__tests__/__snapshots__/docs.test.ts.snap +140 -0
  74. package/src/__tests__/__snapshots__/index.test.ts.snap +745 -97
  75. package/src/__tests__/__snapshots__/translations.test.ts.snap +45 -15
  76. package/src/__tests__/cli.test.ts +15 -11
  77. package/src/__tests__/docFrontMatter.test.ts +160 -45
  78. package/src/__tests__/docs.test.ts +311 -150
  79. package/src/__tests__/index.test.ts +108 -66
  80. package/src/__tests__/lastUpdate.test.ts +1 -1
  81. package/src/__tests__/options.test.ts +48 -3
  82. package/src/__tests__/props.test.ts +62 -0
  83. package/src/__tests__/slug.test.ts +127 -20
  84. package/src/__tests__/translations.test.ts +7 -1
  85. package/src/__tests__/versions.test.ts +73 -70
  86. package/src/categoryGeneratedIndex.ts +57 -0
  87. package/src/cli.ts +8 -41
  88. package/src/client/docsClientUtils.ts +14 -26
  89. package/{types.d.ts → src/deps.d.ts} +0 -0
  90. package/src/docFrontMatter.ts +9 -4
  91. package/src/docs.ts +158 -32
  92. package/src/globalData.ts +6 -1
  93. package/src/index.ts +125 -169
  94. package/src/lastUpdate.ts +10 -13
  95. package/src/markdown/index.ts +8 -12
  96. package/src/numberPrefix.ts +5 -3
  97. package/src/options.ts +59 -14
  98. package/src/plugin-content-docs.d.ts +173 -40
  99. package/src/props.ts +90 -15
  100. package/src/routes.ts +173 -0
  101. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -0
  102. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -0
  103. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -0
  104. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category.js +0 -0
  105. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -0
  106. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-collapsed.json +0 -0
  107. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -0
  108. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-first-level-not-category.js +0 -0
  109. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -0
  110. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -0
  111. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link.json +0 -0
  112. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-unknown-type.json +0 -0
  113. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-wrong-field.json +0 -0
  114. package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars.json +0 -0
  115. package/src/{__tests__/__snapshots__/sidebars.test.ts.snap → sidebars/__tests__/__snapshots__/index.test.ts.snap} +36 -6
  116. package/src/{__tests__/sidebarItemsGenerator.test.ts → sidebars/__tests__/generator.test.ts} +143 -18
  117. package/src/sidebars/__tests__/index.test.ts +204 -0
  118. package/src/sidebars/__tests__/processor.test.ts +237 -0
  119. package/src/sidebars/__tests__/utils.test.ts +695 -0
  120. package/src/sidebars/__tests__/validation.test.ts +105 -0
  121. package/src/sidebars/generator.ts +310 -0
  122. package/src/sidebars/index.ts +94 -0
  123. package/src/sidebars/normalization.ts +112 -0
  124. package/src/sidebars/processor.ts +154 -0
  125. package/src/sidebars/types.ts +211 -0
  126. package/src/sidebars/utils.ts +329 -0
  127. package/src/sidebars/validation.ts +168 -0
  128. package/src/slug.ts +32 -17
  129. package/src/tags.ts +19 -0
  130. package/src/translations.ts +103 -47
  131. package/src/types.ts +64 -107
  132. package/src/versions.ts +59 -25
  133. package/lib/sidebarItemsGenerator.js +0 -211
  134. package/lib/sidebars.d.ts +0 -43
  135. package/lib/sidebars.js +0 -320
  136. package/src/__tests__/sidebars.test.ts +0 -639
  137. package/src/sidebarItemsGenerator.ts +0 -307
  138. package/src/sidebars.ts +0 -522
package/src/docs.ts CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  import path from 'path';
9
9
  import fs from 'fs-extra';
10
+ import chalk from 'chalk';
11
+ import {keyBy, last} from 'lodash';
10
12
  import {
11
13
  aliasedSitePath,
12
14
  getEditUrl,
@@ -14,25 +16,33 @@ import {
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
25
  import {
22
26
  DocFile,
23
27
  DocMetadataBase,
28
+ DocMetadata,
29
+ DocNavLink,
24
30
  LastUpdateData,
25
31
  MetadataOptions,
26
32
  PluginOptions,
27
33
  VersionMetadata,
34
+ LoadedVersion,
28
35
  } from './types';
29
36
  import getSlug from './slug';
30
37
  import {CURRENT_VERSION_NAME} from './constants';
31
- import globby from 'globby';
32
38
  import {getDocsDirPaths} from './versions';
33
39
  import {stripPathNumberPrefixes} from './numberPrefix';
34
40
  import {validateDocFrontMatter} from './docFrontMatter';
35
- import chalk from 'chalk';
41
+ import {
42
+ SidebarsUtils,
43
+ toDocNavigationLink,
44
+ toNavigationLink,
45
+ } from './sidebars/utils';
36
46
 
37
47
  type LastUpdateOptions = Pick<
38
48
  PluginOptions,
@@ -92,11 +102,12 @@ export async function readVersionDocs(
92
102
  versionMetadata: VersionMetadata,
93
103
  options: Pick<
94
104
  PluginOptions,
95
- 'include' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
105
+ 'include' | 'exclude' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
96
106
  >,
97
107
  ): Promise<DocFile[]> {
98
- const sources = await globby(options.include, {
108
+ const sources = await Globby(options.include, {
99
109
  cwd: versionMetadata.contentPath,
110
+ ignore: options.exclude,
100
111
  });
101
112
  return Promise.all(
102
113
  sources.map((source) => readDocFile(versionMetadata, source, options)),
@@ -115,7 +126,6 @@ function doProcessDocMetadata({
115
126
  options: MetadataOptions;
116
127
  }): DocMetadataBase {
117
128
  const {source, content, lastUpdate, contentPath, filePath} = docFile;
118
- const {homePageId} = options;
119
129
  const {siteDir, i18n} = context;
120
130
 
121
131
  const {
@@ -129,9 +139,8 @@ function doProcessDocMetadata({
129
139
  custom_edit_url: customEditURL,
130
140
 
131
141
  // Strip number prefixes by default (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc) by default,
132
- // but allow to disable this behavior with frontmatterr
133
- // eslint-disable-next-line camelcase
134
- parse_number_prefixes = true,
142
+ // but allow to disable this behavior with frontmatter
143
+ parse_number_prefixes: parseNumberPrefixes = true,
135
144
  } = frontMatter;
136
145
 
137
146
  // ex: api/plugins/myDoc -> myDoc
@@ -145,8 +154,7 @@ function doProcessDocMetadata({
145
154
  // ex: myDoc -> .
146
155
  const sourceDirName = path.dirname(source);
147
156
 
148
- // eslint-disable-next-line camelcase
149
- const {filename: unprefixedFileName, numberPrefix} = parse_number_prefixes
157
+ const {filename: unprefixedFileName, numberPrefix} = parseNumberPrefixes
150
158
  ? options.numberPrefixParser(sourceFileNameWithoutExtension)
151
159
  : {filename: sourceFileNameWithoutExtension, numberPrefix: undefined};
152
160
 
@@ -174,8 +182,7 @@ function doProcessDocMetadata({
174
182
  return undefined;
175
183
  }
176
184
  // Eventually remove the number prefixes from intermediate directories
177
- // eslint-disable-next-line camelcase
178
- return parse_number_prefixes
185
+ return parseNumberPrefixes
179
186
  ? stripPathNumberPrefixes(sourceDirName, options.numberPrefixParser)
180
187
  : sourceDirName;
181
188
  }
@@ -188,23 +195,14 @@ function doProcessDocMetadata({
188
195
  // legacy versioned id, requires a breaking change to modify this
189
196
  const id = [versionIdPrefix, unversionedId].filter(Boolean).join('/');
190
197
 
191
- // TODO remove soon, deprecated homePageId
192
- const isDocsHomePage = unversionedId === (homePageId ?? '_index');
193
- if (frontMatter.slug && isDocsHomePage) {
194
- throw new Error(
195
- `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`,
196
- );
197
- }
198
-
199
- const docSlug = isDocsHomePage
200
- ? '/'
201
- : getSlug({
202
- baseID,
203
- dirName: sourceDirName,
204
- frontmatterSlug: frontMatter.slug,
205
- stripDirNumberPrefixes: parse_number_prefixes,
206
- numberPrefixParser: options.numberPrefixParser,
207
- });
198
+ const docSlug = getSlug({
199
+ baseID,
200
+ source,
201
+ sourceDirName,
202
+ frontmatterSlug: frontMatter.slug,
203
+ stripDirNumberPrefixes: parseNumberPrefixes,
204
+ numberPrefixParser: options.numberPrefixParser,
205
+ });
208
206
 
209
207
  // Note: the title is used by default for page title, sidebar label, pagination buttons...
210
208
  // frontMatter.title should be used in priority over contentTitle (because it can contain markdown/JSX syntax)
@@ -246,7 +244,6 @@ function doProcessDocMetadata({
246
244
  return {
247
245
  unversionedId,
248
246
  id,
249
- isDocsHomePage,
250
247
  title,
251
248
  description,
252
249
  source: aliasedSitePath(filePath, siteDir),
@@ -254,6 +251,7 @@ function doProcessDocMetadata({
254
251
  slug: docSlug,
255
252
  permalink,
256
253
  editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
254
+ tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
257
255
  version: versionMetadata.versionName,
258
256
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
259
257
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
@@ -278,9 +276,137 @@ export function processDocMetadata(args: {
278
276
  } catch (e) {
279
277
  console.error(
280
278
  chalk.red(
281
- `Can't process doc metadatas for doc at path "${args.docFile.filePath}" in version "${args.versionMetadata.versionName}"`,
279
+ `Can't process doc metadata for doc at path "${args.docFile.filePath}" in version "${args.versionMetadata.versionName}"`,
282
280
  ),
283
281
  );
284
282
  throw e;
285
283
  }
286
284
  }
285
+
286
+ export function addDocNavigation(
287
+ docsBase: DocMetadataBase[],
288
+ sidebarsUtils: SidebarsUtils,
289
+ sidebarFilePath: string,
290
+ ): LoadedVersion['docs'] {
291
+ const docsById = createDocsByIdIndex(docsBase);
292
+
293
+ sidebarsUtils.checkSidebarsDocIds(
294
+ docsBase.flatMap(getDocIds),
295
+ sidebarFilePath,
296
+ );
297
+
298
+ // Add sidebar/next/previous to the docs
299
+ function addNavData(doc: DocMetadataBase): DocMetadata {
300
+ const navigation = sidebarsUtils.getDocNavigation(
301
+ doc.unversionedId,
302
+ doc.id,
303
+ );
304
+
305
+ const toNavigationLinkByDocId = (
306
+ docId: string | null | undefined,
307
+ type: 'prev' | 'next',
308
+ ): DocNavLink | undefined => {
309
+ if (!docId) {
310
+ return undefined;
311
+ }
312
+ const navDoc = docsById[docId];
313
+ if (!navDoc) {
314
+ // This could only happen if user provided the ID through front matter
315
+ throw new Error(
316
+ `Error when loading ${doc.id} in ${doc.sourceDirName}: the pagination_${type} front matter points to a non-existent ID ${docId}.`,
317
+ );
318
+ }
319
+ return toDocNavigationLink(navDoc);
320
+ };
321
+
322
+ const previous: DocNavLink | undefined = doc.frontMatter.pagination_prev
323
+ ? toNavigationLinkByDocId(doc.frontMatter.pagination_prev, 'prev')
324
+ : toNavigationLink(navigation.previous, docsById);
325
+ const next: DocNavLink | undefined = doc.frontMatter.pagination_next
326
+ ? toNavigationLinkByDocId(doc.frontMatter.pagination_next, 'next')
327
+ : toNavigationLink(navigation.next, docsById);
328
+
329
+ return {...doc, sidebar: navigation.sidebarName, previous, next};
330
+ }
331
+
332
+ const docsWithNavigation = docsBase.map(addNavData);
333
+ // sort to ensure consistent output for tests
334
+ docsWithNavigation.sort((a, b) => a.id.localeCompare(b.id));
335
+ return docsWithNavigation;
336
+ }
337
+
338
+ /**
339
+ * The "main doc" is the "version entry point"
340
+ * We browse this doc by clicking on a version:
341
+ * - the "home" doc (at '/docs/')
342
+ * - the first doc of the first sidebar
343
+ * - a random doc (if no docs are in any sidebar... edge case)
344
+ */
345
+ export function getMainDocId({
346
+ docs,
347
+ sidebarsUtils,
348
+ }: {
349
+ docs: DocMetadataBase[];
350
+ sidebarsUtils: SidebarsUtils;
351
+ }): string {
352
+ function getMainDoc(): DocMetadata {
353
+ const versionHomeDoc = docs.find((doc) => doc.slug === '/');
354
+ const firstDocIdOfFirstSidebar =
355
+ sidebarsUtils.getFirstDocIdOfFirstSidebar();
356
+ if (versionHomeDoc) {
357
+ return versionHomeDoc;
358
+ } else if (firstDocIdOfFirstSidebar) {
359
+ return docs.find((doc) => doc.id === firstDocIdOfFirstSidebar)!;
360
+ } else {
361
+ return docs[0];
362
+ }
363
+ }
364
+
365
+ return getMainDoc().unversionedId;
366
+ }
367
+
368
+ function getLastPathSegment(str: string): string {
369
+ return last(str.split('/'))!;
370
+ }
371
+
372
+ // By convention, Docusaurus considers some docs are "indexes":
373
+ // - index.md
374
+ // - readme.md
375
+ // - <folder>/<folder>.md
376
+ //
377
+ // Those index docs produce a different behavior
378
+ // - Slugs do not end with a weird "/index" suffix
379
+ // - Auto-generated sidebar categories link to them as intro
380
+ export function isConventionalDocIndex(doc: {
381
+ source: DocMetadataBase['slug'];
382
+ sourceDirName: DocMetadataBase['sourceDirName'];
383
+ }): boolean {
384
+ // "@site/docs/folder/subFolder/subSubFolder/myDoc.md" => "myDoc"
385
+ const docName = path.parse(doc.source).name;
386
+
387
+ // "folder/subFolder/subSubFolder" => "subSubFolder"
388
+ const lastDirName = getLastPathSegment(doc.sourceDirName);
389
+
390
+ const eligibleDocIndexNames = ['index', 'readme', lastDirName.toLowerCase()];
391
+
392
+ return eligibleDocIndexNames.includes(docName.toLowerCase());
393
+ }
394
+
395
+ // Return both doc ids
396
+ // TODO legacy retro-compatibility due to old versioned sidebars using versioned doc ids
397
+ // ("id" should be removed & "versionedId" should be renamed to "id")
398
+ export function getDocIds(doc: DocMetadataBase): [string, string] {
399
+ return [doc.unversionedId, doc.id];
400
+ }
401
+
402
+ // docs are indexed by both versioned and unversioned ids at the same time
403
+ // TODO legacy retro-compatibility due to old versioned sidebars using versioned doc ids
404
+ // ("id" should be removed & "versionedId" should be renamed to "id")
405
+ export function createDocsByIdIndex<
406
+ Doc extends {id: string; unversionedId: string},
407
+ >(docs: Doc[]): Record<string, Doc> {
408
+ return {
409
+ ...keyBy(docs, (doc) => doc.unversionedId),
410
+ ...keyBy(docs, (doc) => doc.id),
411
+ };
412
+ }
package/src/globalData.ts CHANGED
@@ -5,7 +5,12 @@
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 type {
9
+ DocMetadata,
10
+ GlobalDoc,
11
+ LoadedVersion,
12
+ GlobalVersion,
13
+ } from './types';
9
14
 
10
15
  export function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
11
16
  return {