@docusaurus/plugin-content-docs 2.0.0-beta.16 → 2.0.0-beta.19

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 (93) hide show
  1. package/lib/categoryGeneratedIndex.d.ts +1 -1
  2. package/lib/categoryGeneratedIndex.js +5 -7
  3. package/lib/cli.d.ts +3 -2
  4. package/lib/cli.js +49 -41
  5. package/lib/client/docsClientUtils.d.ts +8 -5
  6. package/lib/client/docsClientUtils.js +13 -15
  7. package/lib/client/index.d.ts +12 -9
  8. package/lib/client/index.js +30 -33
  9. package/lib/constants.d.ts +4 -0
  10. package/lib/constants.js +4 -1
  11. package/lib/docs.d.ts +8 -15
  12. package/lib/docs.js +34 -39
  13. package/lib/{docFrontMatter.d.ts → frontMatter.d.ts} +4 -2
  14. package/lib/{docFrontMatter.js → frontMatter.js} +3 -0
  15. package/lib/globalData.d.ts +3 -7
  16. package/lib/globalData.js +9 -13
  17. package/lib/index.d.ts +1 -2
  18. package/lib/index.js +33 -26
  19. package/lib/lastUpdate.d.ts +4 -6
  20. package/lib/lastUpdate.js +14 -5
  21. package/lib/markdown/index.js +1 -1
  22. package/lib/markdown/linkify.js +5 -2
  23. package/lib/numberPrefix.js +16 -22
  24. package/lib/options.d.ts +3 -5
  25. package/lib/options.js +6 -5
  26. package/lib/props.d.ts +3 -3
  27. package/lib/props.js +10 -10
  28. package/lib/routes.d.ts +5 -4
  29. package/lib/routes.js +10 -24
  30. package/lib/server-export.d.ts +2 -1
  31. package/lib/server-export.js +3 -4
  32. package/lib/sidebars/generator.js +63 -44
  33. package/lib/sidebars/index.js +20 -16
  34. package/lib/sidebars/normalization.js +3 -3
  35. package/lib/sidebars/postProcessor.js +18 -25
  36. package/lib/sidebars/processor.d.ts +3 -1
  37. package/lib/sidebars/processor.js +17 -6
  38. package/lib/sidebars/types.d.ts +31 -19
  39. package/lib/sidebars/utils.d.ts +17 -6
  40. package/lib/sidebars/utils.js +27 -37
  41. package/lib/sidebars/validation.d.ts +3 -1
  42. package/lib/sidebars/validation.js +1 -0
  43. package/lib/slug.d.ts +1 -2
  44. package/lib/slug.js +4 -5
  45. package/lib/tags.d.ts +2 -1
  46. package/lib/tags.js +2 -2
  47. package/lib/translations.d.ts +3 -3
  48. package/lib/translations.js +28 -81
  49. package/lib/types.d.ts +10 -95
  50. package/lib/versions/files.d.ts +44 -0
  51. package/lib/versions/files.js +142 -0
  52. package/lib/versions/index.d.ts +36 -0
  53. package/lib/versions/index.js +155 -0
  54. package/lib/versions/validation.d.ts +17 -0
  55. package/lib/versions/validation.js +71 -0
  56. package/package.json +14 -12
  57. package/src/categoryGeneratedIndex.ts +10 -9
  58. package/src/cli.ts +64 -69
  59. package/src/client/docsClientUtils.ts +14 -16
  60. package/src/client/index.ts +42 -43
  61. package/src/constants.ts +4 -2
  62. package/src/deps.d.ts +1 -1
  63. package/src/docs.ts +48 -51
  64. package/src/{docFrontMatter.ts → frontMatter.ts} +9 -6
  65. package/src/globalData.ts +15 -16
  66. package/src/index.ts +45 -40
  67. package/src/lastUpdate.ts +20 -8
  68. package/src/markdown/index.ts +1 -3
  69. package/src/markdown/linkify.ts +6 -3
  70. package/src/numberPrefix.ts +18 -28
  71. package/src/options.ts +6 -8
  72. package/src/plugin-content-docs.d.ts +457 -116
  73. package/src/props.ts +12 -9
  74. package/src/routes.ts +13 -39
  75. package/src/server-export.ts +1 -3
  76. package/src/sidebars/generator.ts +88 -59
  77. package/src/sidebars/index.ts +20 -15
  78. package/src/sidebars/normalization.ts +1 -1
  79. package/src/sidebars/postProcessor.ts +6 -11
  80. package/src/sidebars/processor.ts +27 -14
  81. package/src/sidebars/types.ts +25 -23
  82. package/src/sidebars/utils.ts +45 -46
  83. package/src/sidebars/validation.ts +4 -3
  84. package/src/slug.ts +7 -6
  85. package/src/tags.ts +3 -2
  86. package/src/translations.ts +32 -84
  87. package/src/types.ts +15 -107
  88. package/src/versions/files.ts +220 -0
  89. package/src/versions/index.ts +247 -0
  90. package/src/versions/validation.ts +113 -0
  91. package/lib/versions.d.ts +0 -41
  92. package/lib/versions.js +0 -329
  93. package/src/versions.ts +0 -606
package/src/docs.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  aliasedSitePath,
13
13
  getEditUrl,
14
14
  getFolderContainingFile,
15
+ getContentPathList,
15
16
  normalizeUrl,
16
17
  parseMarkdownString,
17
18
  posixPath,
@@ -21,27 +22,24 @@ import {
21
22
  import type {LoadContext} from '@docusaurus/types';
22
23
 
23
24
  import {getFileLastUpdate} from './lastUpdate';
24
- import type {
25
- DocFile,
26
- DocMetadataBase,
27
- DocMetadata,
28
- DocNavLink,
29
- LastUpdateData,
30
- VersionMetadata,
31
- LoadedVersion,
32
- } from './types';
25
+ import type {DocFile} from './types';
33
26
  import getSlug from './slug';
34
27
  import {CURRENT_VERSION_NAME} from './constants';
35
- import {getDocsDirPaths} from './versions';
36
28
  import {stripPathNumberPrefixes} from './numberPrefix';
37
- import {validateDocFrontMatter} from './docFrontMatter';
29
+ import {validateDocFrontMatter} from './frontMatter';
38
30
  import type {SidebarsUtils} from './sidebars/utils';
39
31
  import {toDocNavigationLink, toNavigationLink} from './sidebars/utils';
40
32
  import type {
41
33
  MetadataOptions,
42
34
  PluginOptions,
43
35
  CategoryIndexMatcher,
44
- CategoryIndexMatcherParam,
36
+ DocMetadataBase,
37
+ DocMetadata,
38
+ PropNavigationLink,
39
+ LastUpdateData,
40
+ VersionMetadata,
41
+ DocFrontMatter,
42
+ LoadedVersion,
45
43
  } from '@docusaurus/plugin-content-docs';
46
44
 
47
45
  type LastUpdateOptions = Pick<
@@ -85,7 +83,7 @@ export async function readDocFile(
85
83
  options: LastUpdateOptions,
86
84
  ): Promise<DocFile> {
87
85
  const contentPath = await getFolderContainingFile(
88
- getDocsDirPaths(versionMetadata),
86
+ getContentPathList(versionMetadata),
89
87
  source,
90
88
  );
91
89
 
@@ -114,16 +112,31 @@ export async function readVersionDocs(
114
112
  );
115
113
  }
116
114
 
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
+
117
128
  function doProcessDocMetadata({
118
129
  docFile,
119
130
  versionMetadata,
120
131
  context,
121
132
  options,
133
+ env,
122
134
  }: {
123
135
  docFile: DocFile;
124
136
  versionMetadata: VersionMetadata;
125
137
  context: LoadContext;
126
138
  options: MetadataOptions;
139
+ env: DocEnv;
127
140
  }): DocMetadataBase {
128
141
  const {source, content, lastUpdate, contentPath, filePath} = docFile;
129
142
  const {siteDir, i18n} = context;
@@ -144,15 +157,13 @@ function doProcessDocMetadata({
144
157
  parse_number_prefixes: parseNumberPrefixes = true,
145
158
  } = frontMatter;
146
159
 
147
- // ex: api/plugins/myDoc -> myDoc
148
- // ex: myDoc -> myDoc
160
+ // E.g. api/plugins/myDoc -> myDoc; myDoc -> myDoc
149
161
  const sourceFileNameWithoutExtension = path.basename(
150
162
  source,
151
163
  path.extname(source),
152
164
  );
153
165
 
154
- // ex: api/plugins/myDoc -> api/plugins
155
- // ex: myDoc -> .
166
+ // E.g. api/plugins/myDoc -> api/plugins; myDoc -> .
156
167
  const sourceDirName = path.dirname(source);
157
168
 
158
169
  const {filename: unprefixedFileName, numberPrefix} = parseNumberPrefixes
@@ -213,7 +224,7 @@ function doProcessDocMetadata({
213
224
 
214
225
  const description: string = frontMatter.description ?? excerpt ?? '';
215
226
 
216
- const permalink = normalizeUrl([versionMetadata.versionPath, docSlug]);
227
+ const permalink = normalizeUrl([versionMetadata.path, docSlug]);
217
228
 
218
229
  function getDocEditUrl() {
219
230
  const relativeFilePath = path.relative(contentPath, filePath);
@@ -232,13 +243,15 @@ function doProcessDocMetadata({
232
243
  const isLocalized = contentPath === versionMetadata.contentPathLocalized;
233
244
  const baseVersionEditUrl =
234
245
  isLocalized && options.editLocalizedFiles
235
- ? versionMetadata.versionEditUrlLocalized
236
- : versionMetadata.versionEditUrl;
246
+ ? versionMetadata.editUrlLocalized
247
+ : versionMetadata.editUrl;
237
248
  return getEditUrl(relativeFilePath, baseVersionEditUrl);
238
249
  }
239
250
  return undefined;
240
251
  }
241
252
 
253
+ const draft = isDraftForEnvironment({env, frontMatter});
254
+
242
255
  // Assign all of object properties during instantiation (if possible) for
243
256
  // NodeJS optimization.
244
257
  // Adding properties to object after instantiation will cause hidden
@@ -252,15 +265,16 @@ function doProcessDocMetadata({
252
265
  sourceDirName,
253
266
  slug: docSlug,
254
267
  permalink,
268
+ draft,
255
269
  editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
256
270
  tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
257
271
  version: versionMetadata.versionName,
258
272
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
259
273
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
260
274
  formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
261
- ? new Intl.DateTimeFormat(i18n.currentLocale).format(
262
- lastUpdate.lastUpdatedAt * 1000,
263
- )
275
+ ? new Intl.DateTimeFormat(i18n.currentLocale, {
276
+ calendar: i18n.localeConfigs[i18n.currentLocale]!.calendar,
277
+ }).format(lastUpdate.lastUpdatedAt * 1000)
264
278
  : undefined,
265
279
  sidebarPosition,
266
280
  frontMatter,
@@ -272,6 +286,7 @@ export function processDocMetadata(args: {
272
286
  versionMetadata: VersionMetadata;
273
287
  context: LoadContext;
274
288
  options: MetadataOptions;
289
+ env: DocEnv;
275
290
  }): DocMetadataBase {
276
291
  try {
277
292
  return doProcessDocMetadata(args);
@@ -304,7 +319,7 @@ export function addDocNavigation(
304
319
  const toNavigationLinkByDocId = (
305
320
  docId: string | null | undefined,
306
321
  type: 'prev' | 'next',
307
- ): DocNavLink | undefined => {
322
+ ): PropNavigationLink | undefined => {
308
323
  if (!docId) {
309
324
  return undefined;
310
325
  }
@@ -331,7 +346,7 @@ export function addDocNavigation(
331
346
  }
332
347
 
333
348
  const docsWithNavigation = docsBase.map(addNavData);
334
- // sort to ensure consistent output for tests
349
+ // Sort to ensure consistent output for tests
335
350
  docsWithNavigation.sort((a, b) => a.id.localeCompare(b.id));
336
351
  return docsWithNavigation;
337
352
  }
@@ -363,7 +378,7 @@ export function getMainDocId({
363
378
  doc.unversionedId === firstDocIdOfFirstSidebar,
364
379
  )!;
365
380
  }
366
- return docs[0];
381
+ return docs[0]!;
367
382
  }
368
383
 
369
384
  return getMainDoc().unversionedId;
@@ -391,13 +406,17 @@ export const isCategoryIndex: CategoryIndexMatcher = ({
391
406
  return eligibleDocIndexNames.includes(fileName.toLowerCase());
392
407
  };
393
408
 
409
+ /**
410
+ * `guides/sidebar/autogenerated.md` ->
411
+ * `'autogenerated', '.md', ['sidebar', 'guides']`
412
+ */
394
413
  export function toCategoryIndexMatcherParam({
395
414
  source,
396
415
  sourceDirName,
397
416
  }: Pick<
398
417
  DocMetadataBase,
399
418
  'source' | 'sourceDirName'
400
- >): CategoryIndexMatcherParam {
419
+ >): Parameters<CategoryIndexMatcher>[0] {
401
420
  // source + sourceDirName are always posix-style
402
421
  return {
403
422
  fileName: path.posix.parse(source).name,
@@ -406,28 +425,6 @@ export function toCategoryIndexMatcherParam({
406
425
  };
407
426
  }
408
427
 
409
- /**
410
- * `guides/sidebar/autogenerated.md` ->
411
- * `'autogenerated', '.md', ['sidebar', 'guides']`
412
- */
413
- export function splitPath(str: string): {
414
- /**
415
- * The list of directories, from lowest level to highest.
416
- * If there's no dir name, directories is ['.']
417
- */
418
- directories: string[];
419
- /** The file name, without extension */
420
- fileName: string;
421
- /** The extension, with a leading dot */
422
- extension: string;
423
- } {
424
- return {
425
- fileName: path.parse(str).name,
426
- extension: path.parse(str).ext,
427
- directories: path.dirname(str).split(path.sep).reverse(),
428
- };
429
- }
430
-
431
428
  // Return both doc ids
432
429
  // TODO legacy retro-compatibility due to old versioned sidebars using
433
430
  // versioned doc ids ("id" should be removed & "versionedId" should be renamed
@@ -436,13 +433,13 @@ export function getDocIds(doc: DocMetadataBase): [string, string] {
436
433
  return [doc.unversionedId, doc.id];
437
434
  }
438
435
 
439
- // docs are indexed by both versioned and unversioned ids at the same time
436
+ // Docs are indexed by both versioned and unversioned ids at the same time
440
437
  // TODO legacy retro-compatibility due to old versioned sidebars using
441
438
  // versioned doc ids ("id" should be removed & "versionedId" should be renamed
442
439
  // to "id")
443
440
  export function createDocsByIdIndex<
444
441
  Doc extends {id: string; unversionedId: string},
445
- >(docs: Doc[]): Record<string, Doc> {
442
+ >(docs: Doc[]): {[docId: string]: Doc} {
446
443
  return Object.fromEntries(
447
444
  docs.flatMap((doc) => [
448
445
  [doc.unversionedId, doc],
@@ -12,7 +12,7 @@ import {
12
12
  FrontMatterTOCHeadingLevels,
13
13
  validateFrontMatter,
14
14
  } from '@docusaurus/utils-validation';
15
- import type {DocFrontMatter} from './types';
15
+ import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
16
16
 
17
17
  // NOTE: we don't add any default value on purpose here
18
18
  // We don't want default values to magically appear in doc metadata and props
@@ -20,12 +20,14 @@ import type {DocFrontMatter} from './types';
20
20
  // We use default values in code instead
21
21
  const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
22
22
  id: Joi.string(),
23
- title: Joi.string().allow(''), // see https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
23
+ // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
24
+ title: Joi.string().allow(''),
24
25
  hide_title: Joi.boolean(),
25
26
  hide_table_of_contents: Joi.boolean(),
26
27
  keywords: Joi.array().items(Joi.string().required()),
27
28
  image: URISchema,
28
- description: Joi.string().allow(''), // see https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
29
+ // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
30
+ description: Joi.string().allow(''),
29
31
  slug: Joi.string(),
30
32
  sidebar_label: Joi.string(),
31
33
  sidebar_position: Joi.number(),
@@ -38,11 +40,12 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
38
40
  parse_number_prefixes: Joi.boolean(),
39
41
  pagination_next: Joi.string().allow(null),
40
42
  pagination_prev: Joi.string().allow(null),
43
+ draft: Joi.boolean(),
41
44
  ...FrontMatterTOCHeadingLevels,
42
45
  }).unknown();
43
46
 
44
- export function validateDocFrontMatter(
45
- frontMatter: Record<string, unknown>,
46
- ): DocFrontMatter {
47
+ export function validateDocFrontMatter(frontMatter: {
48
+ [key: string]: unknown;
49
+ }): DocFrontMatter {
47
50
  return validateFrontMatter(frontMatter, DocFrontMatterSchema);
48
51
  }
package/src/globalData.ts CHANGED
@@ -6,21 +6,20 @@
6
6
  */
7
7
 
8
8
  import _ from 'lodash';
9
- import {normalizeUrl} from '@docusaurus/utils';
10
9
  import type {Sidebars} from './sidebars/types';
11
- import {createSidebarsUtils} from './sidebars/utils';
10
+ import {getMainDocId} from './docs';
11
+ import type {FullVersion} from './types';
12
12
  import type {
13
13
  CategoryGeneratedIndexMetadata,
14
14
  DocMetadata,
15
- LoadedVersion,
16
- } from './types';
15
+ } from '@docusaurus/plugin-content-docs';
17
16
  import type {
18
17
  GlobalVersion,
19
18
  GlobalSidebar,
20
19
  GlobalDoc,
21
20
  } from '@docusaurus/plugin-content-docs/client';
22
21
 
23
- export function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
22
+ function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
24
23
  return {
25
24
  id: doc.unversionedId,
26
25
  path: doc.permalink,
@@ -28,7 +27,7 @@ export function toGlobalDataDoc(doc: DocMetadata): GlobalDoc {
28
27
  };
29
28
  }
30
29
 
31
- export function toGlobalDataGeneratedIndex(
30
+ function toGlobalDataGeneratedIndex(
32
31
  doc: CategoryGeneratedIndexMetadata,
33
32
  ): GlobalDoc {
34
33
  return {
@@ -38,13 +37,12 @@ export function toGlobalDataGeneratedIndex(
38
37
  };
39
38
  }
40
39
 
41
- export function toGlobalSidebars(
40
+ function toGlobalSidebars(
42
41
  sidebars: Sidebars,
43
- version: LoadedVersion,
44
- ): Record<string, GlobalSidebar> {
45
- const {getFirstLink} = createSidebarsUtils(sidebars);
42
+ version: FullVersion,
43
+ ): {[sidebarId: string]: GlobalSidebar} {
46
44
  return _.mapValues(sidebars, (sidebar, sidebarId) => {
47
- const firstLink = getFirstLink(sidebarId);
45
+ const firstLink = version.sidebarsUtils.getFirstLink(sidebarId);
48
46
  if (!firstLink) {
49
47
  return {};
50
48
  }
@@ -52,7 +50,7 @@ export function toGlobalSidebars(
52
50
  link: {
53
51
  path:
54
52
  firstLink.type === 'generated-index'
55
- ? normalizeUrl([version.versionPath, firstLink.slug])
53
+ ? firstLink.permalink
56
54
  : version.docs.find(
57
55
  (doc) =>
58
56
  doc.id === firstLink.id || doc.unversionedId === firstLink.id,
@@ -63,16 +61,17 @@ export function toGlobalSidebars(
63
61
  });
64
62
  }
65
63
 
66
- export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion {
64
+ export function toGlobalDataVersion(version: FullVersion): GlobalVersion {
67
65
  return {
68
66
  name: version.versionName,
69
- label: version.versionLabel,
67
+ label: version.label,
70
68
  isLast: version.isLast,
71
- path: version.versionPath,
72
- mainDocId: version.mainDocId,
69
+ path: version.path,
70
+ mainDocId: getMainDocId(version),
73
71
  docs: version.docs
74
72
  .map(toGlobalDataDoc)
75
73
  .concat(version.categoryGeneratedIndices.map(toGlobalDataGeneratedIndex)),
74
+ draftIds: version.drafts.map((doc) => doc.unversionedId),
76
75
  sidebars: toGlobalSidebars(version.sidebars, version),
77
76
  };
78
77
  }
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  normalizeUrl,
12
12
  docuHash,
13
13
  aliasedSitePath,
14
+ getContentPathList,
14
15
  reportMessage,
15
16
  posixPath,
16
17
  addTrailingPathSeparator,
@@ -19,32 +20,24 @@ import {
19
20
  DEFAULT_PLUGIN_ID,
20
21
  } from '@docusaurus/utils';
21
22
  import type {LoadContext, Plugin} from '@docusaurus/types';
22
- import {loadSidebars} from './sidebars';
23
+ import {loadSidebars, resolveSidebarPathOption} from './sidebars';
23
24
  import {CategoryMetadataFilenamePattern} from './sidebars/generator';
24
- import {
25
- readVersionDocs,
26
- processDocMetadata,
27
- addDocNavigation,
28
- getMainDocId,
29
- } from './docs';
30
- import {getDocsDirPaths, readVersionsMetadata} from './versions';
31
-
25
+ import type {DocEnv} from './docs';
26
+ import {readVersionDocs, processDocMetadata, addDocNavigation} from './docs';
27
+ import {readVersionsMetadata} from './versions';
32
28
  import type {
33
- LoadedContent,
34
29
  SourceToPermalink,
35
- DocMetadataBase,
36
- VersionMetadata,
37
- LoadedVersion,
38
30
  DocFile,
39
31
  DocsMarkdownOption,
40
32
  VersionTag,
41
- DocFrontMatter,
33
+ FullVersion,
42
34
  } from './types';
43
35
  import type {RuleSetRule} from 'webpack';
44
36
  import {cliDocsVersionCommand} from './cli';
45
37
  import {VERSIONS_JSON_FILE} from './constants';
46
38
  import {toGlobalDataVersion} from './globalData';
47
39
  import {toTagDocListProp} from './props';
40
+ import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
48
41
  import {
49
42
  translateLoadedContent,
50
43
  getLoadedContentTranslationFiles,
@@ -55,20 +48,26 @@ import {createVersionRoutes} from './routes';
55
48
  import type {
56
49
  PropTagsListPage,
57
50
  PluginOptions,
51
+ DocMetadataBase,
52
+ VersionMetadata,
53
+ DocFrontMatter,
54
+ LoadedContent,
55
+ LoadedVersion,
58
56
  } from '@docusaurus/plugin-content-docs';
59
- import type {GlobalPluginData} from '@docusaurus/plugin-content-docs/client';
60
57
  import {createSidebarsUtils} from './sidebars/utils';
61
- import {getCategoryGeneratedIndexMetadataList} from './categoryGeneratedIndex';
58
+ import _ from 'lodash';
62
59
 
63
60
  export default async function pluginContentDocs(
64
61
  context: LoadContext,
65
62
  options: PluginOptions,
66
63
  ): Promise<Plugin<LoadedContent>> {
67
64
  const {siteDir, generatedFilesDir, baseUrl, siteConfig} = context;
65
+ // Mutate options to resolve sidebar path according to siteDir
66
+ options.sidebarPath = resolveSidebarPathOption(siteDir, options.sidebarPath);
68
67
 
69
68
  const versionsMetadata = await readVersionsMetadata({context, options});
70
69
 
71
- const pluginId = options.id ?? DEFAULT_PLUGIN_ID;
70
+ const pluginId = options.id;
72
71
 
73
72
  const pluginDataDirRoot = path.join(
74
73
  generatedFilesDir,
@@ -98,16 +97,11 @@ export default async function pluginContentDocs(
98
97
  .arguments('<version>')
99
98
  .description(commandDescription)
100
99
  .action((version) => {
101
- cliDocsVersionCommand(version, siteDir, pluginId, {
102
- path: options.path,
103
- sidebarPath: options.sidebarPath,
104
- sidebarCollapsed: options.sidebarCollapsed,
105
- sidebarCollapsible: options.sidebarCollapsible,
106
- });
100
+ cliDocsVersionCommand(version, options, context);
107
101
  });
108
102
  },
109
103
 
110
- async getTranslationFiles({content}) {
104
+ getTranslationFiles({content}) {
111
105
  return getLoadedContentTranslationFiles(content);
112
106
  },
113
107
 
@@ -115,7 +109,7 @@ export default async function pluginContentDocs(
115
109
  function getVersionPathsToWatch(version: VersionMetadata): string[] {
116
110
  const result = [
117
111
  ...options.include.flatMap((pattern) =>
118
- getDocsDirPaths(version).map(
112
+ getContentPathList(version).map(
119
113
  (docsDirPath) => `${docsDirPath}/${pattern}`,
120
114
  ),
121
115
  ),
@@ -151,6 +145,7 @@ export default async function pluginContentDocs(
151
145
  versionMetadata,
152
146
  context,
153
147
  options,
148
+ env: process.env.NODE_ENV as DocEnv,
154
149
  });
155
150
  }
156
151
  return Promise.all(docFiles.map(processVersionDoc));
@@ -159,14 +154,17 @@ export default async function pluginContentDocs(
159
154
  async function doLoadVersion(
160
155
  versionMetadata: VersionMetadata,
161
156
  ): Promise<LoadedVersion> {
162
- const docs: DocMetadataBase[] = await loadVersionDocsBase(
157
+ const docsBase: DocMetadataBase[] = await loadVersionDocsBase(
163
158
  versionMetadata,
164
159
  );
165
160
 
161
+ const [drafts, docs] = _.partition(docsBase, (doc) => doc.draft);
162
+
166
163
  const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, {
167
164
  sidebarItemsGenerator: options.sidebarItemsGenerator,
168
165
  numberPrefixParser: options.numberPrefixParser,
169
166
  docs,
167
+ drafts,
170
168
  version: versionMetadata,
171
169
  sidebarOptions: {
172
170
  sidebarCollapsed: options.sidebarCollapsed,
@@ -184,12 +182,8 @@ export default async function pluginContentDocs(
184
182
  sidebarsUtils,
185
183
  versionMetadata.sidebarFilePath as string,
186
184
  ),
185
+ drafts,
187
186
  sidebars,
188
- mainDocId: getMainDocId({docs, sidebarsUtils}),
189
- categoryGeneratedIndices: getCategoryGeneratedIndexMetadataList({
190
- docs,
191
- sidebarsUtils,
192
- }),
193
187
  };
194
188
  }
195
189
 
@@ -220,8 +214,19 @@ export default async function pluginContentDocs(
220
214
  breadcrumbs,
221
215
  } = options;
222
216
  const {addRoute, createData, setGlobalData} = actions;
217
+ const versions: FullVersion[] = loadedVersions.map((version) => {
218
+ const sidebarsUtils = createSidebarsUtils(version.sidebars);
219
+ return {
220
+ ...version,
221
+ sidebarsUtils,
222
+ categoryGeneratedIndices: getCategoryGeneratedIndexMetadataList({
223
+ docs: version.docs,
224
+ sidebarsUtils,
225
+ }),
226
+ };
227
+ });
223
228
 
224
- async function createVersionTagsRoutes(version: LoadedVersion) {
229
+ async function createVersionTagsRoutes(version: FullVersion) {
225
230
  const versionTags = getVersionTags(version.docs);
226
231
 
227
232
  // TODO tags should be a sub route of the version route
@@ -229,13 +234,13 @@ export default async function pluginContentDocs(
229
234
  const tagsProp: PropTagsListPage['tags'] = Object.values(
230
235
  versionTags,
231
236
  ).map((tagValue) => ({
232
- name: tagValue.name,
237
+ label: tagValue.label,
233
238
  permalink: tagValue.permalink,
234
239
  count: tagValue.docIds.length,
235
240
  }));
236
241
 
237
242
  // Only create /tags page if there are tags.
238
- if (Object.keys(tagsProp).length > 0) {
243
+ if (tagsProp.length > 0) {
239
244
  const tagsPropPath = await createData(
240
245
  `${docuHash(`tags-list-${version.versionName}-prop`)}.json`,
241
246
  JSON.stringify(tagsProp, null, 2),
@@ -277,9 +282,9 @@ export default async function pluginContentDocs(
277
282
  }
278
283
 
279
284
  await Promise.all(
280
- loadedVersions.map((loadedVersion) =>
285
+ versions.map((version) =>
281
286
  createVersionRoutes({
282
- loadedVersion,
287
+ version,
283
288
  docItemComponent,
284
289
  docLayoutComponent,
285
290
  docCategoryGeneratedIndexComponent,
@@ -291,11 +296,11 @@ export default async function pluginContentDocs(
291
296
  );
292
297
 
293
298
  // TODO tags should be a sub route of the version route
294
- await Promise.all(loadedVersions.map(createVersionTagsRoutes));
299
+ await Promise.all(versions.map(createVersionTagsRoutes));
295
300
 
296
- setGlobalData<GlobalPluginData>({
301
+ setGlobalData({
297
302
  path: normalizeUrl([baseUrl, options.routeBasePath]),
298
- versions: loadedVersions.map(toGlobalDataVersion),
303
+ versions: versions.map(toGlobalDataVersion),
299
304
  breadcrumbs,
300
305
  });
301
306
  },
@@ -332,7 +337,7 @@ export default async function pluginContentDocs(
332
337
  };
333
338
 
334
339
  function createMDXLoaderRule(): RuleSetRule {
335
- const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
340
+ const contentDirs = versionsMetadata.flatMap(getContentPathList);
336
341
  return {
337
342
  test: /\.mdx?$/i,
338
343
  include: contentDirs
package/src/lastUpdate.ts CHANGED
@@ -6,15 +6,18 @@
6
6
  */
7
7
 
8
8
  import logger from '@docusaurus/logger';
9
- import {getFileCommitDate, GitNotFoundError} from '@docusaurus/utils';
10
-
11
- type FileLastUpdateData = {timestamp?: number; author?: string};
9
+ import {
10
+ getFileCommitDate,
11
+ FileNotTrackedError,
12
+ GitNotFoundError,
13
+ } from '@docusaurus/utils';
12
14
 
13
15
  let showedGitRequirementError = false;
16
+ let showedFileNotTrackedError = false;
14
17
 
15
18
  export async function getFileLastUpdate(
16
19
  filePath?: string,
17
- ): Promise<FileLastUpdateData | null> {
20
+ ): Promise<{timestamp: number; author: string} | null> {
18
21
  if (!filePath) {
19
22
  return null;
20
23
  }
@@ -28,11 +31,20 @@ export async function getFileLastUpdate(
28
31
  });
29
32
  return {timestamp: result.timestamp, author: result.author};
30
33
  } catch (err) {
31
- if (err instanceof GitNotFoundError && !showedGitRequirementError) {
32
- logger.warn('Sorry, the docs plugin last update options require Git.');
33
- showedGitRequirementError = true;
34
+ if (err instanceof GitNotFoundError) {
35
+ if (!showedGitRequirementError) {
36
+ logger.warn('Sorry, the docs plugin last update options require Git.');
37
+ showedGitRequirementError = true;
38
+ }
39
+ } else if (err instanceof FileNotTrackedError) {
40
+ if (!showedFileNotTrackedError) {
41
+ logger.warn(
42
+ 'Cannot infer the update date for some files, as they are not tracked by git.',
43
+ );
44
+ showedFileNotTrackedError = true;
45
+ }
34
46
  } else {
35
- logger.error(err);
47
+ logger.warn(err);
36
48
  }
37
49
  return null;
38
50
  }
@@ -16,7 +16,5 @@ export default function markdownLoader(
16
16
  const fileString = source;
17
17
  const callback = this.async();
18
18
  const options = this.getOptions();
19
- return (
20
- callback && callback(null, linkify(fileString, this.resourcePath, options))
21
- );
19
+ return callback?.(null, linkify(fileString, this.resourcePath, options));
22
20
  }
@@ -6,15 +6,18 @@
6
6
  */
7
7
 
8
8
  import type {DocsMarkdownOption} from '../types';
9
- import {getDocsDirPaths} from '../versions';
10
- import {replaceMarkdownLinks} from '@docusaurus/utils';
9
+ import {replaceMarkdownLinks, getContentPathList} from '@docusaurus/utils';
11
10
 
12
11
  function getVersion(filePath: string, options: DocsMarkdownOption) {
13
12
  const versionFound = options.versionsMetadata.find((version) =>
14
- getDocsDirPaths(version).some((docsDirPath) =>
13
+ getContentPathList(version).some((docsDirPath) =>
15
14
  filePath.startsWith(docsDirPath),
16
15
  ),
17
16
  );
17
+ // At this point, this should never happen, because the MDX loaders' paths are
18
+ // literally using the version content paths; but if we allow sourcing content
19
+ // from outside the docs directory (through the `include` option, for example;
20
+ // is there a compelling use-case?), this would actually be testable
18
21
  if (!versionFound) {
19
22
  throw new Error(
20
23
  `Unexpected error: Markdown file at "${filePath}" does not belong to any docs version!`,