@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.
- package/lib/categoryGeneratedIndex.d.ts +1 -1
- package/lib/categoryGeneratedIndex.js +5 -7
- package/lib/cli.d.ts +3 -2
- package/lib/cli.js +49 -41
- package/lib/client/docsClientUtils.d.ts +8 -5
- package/lib/client/docsClientUtils.js +13 -15
- package/lib/client/index.d.ts +12 -9
- package/lib/client/index.js +30 -33
- package/lib/constants.d.ts +4 -0
- package/lib/constants.js +4 -1
- package/lib/docs.d.ts +8 -15
- package/lib/docs.js +34 -39
- package/lib/{docFrontMatter.d.ts → frontMatter.d.ts} +4 -2
- package/lib/{docFrontMatter.js → frontMatter.js} +3 -0
- package/lib/globalData.d.ts +3 -7
- package/lib/globalData.js +9 -13
- package/lib/index.d.ts +1 -2
- package/lib/index.js +33 -26
- package/lib/lastUpdate.d.ts +4 -6
- package/lib/lastUpdate.js +14 -5
- package/lib/markdown/index.js +1 -1
- package/lib/markdown/linkify.js +5 -2
- package/lib/numberPrefix.js +16 -22
- package/lib/options.d.ts +3 -5
- package/lib/options.js +6 -5
- package/lib/props.d.ts +3 -3
- package/lib/props.js +10 -10
- package/lib/routes.d.ts +5 -4
- package/lib/routes.js +10 -24
- package/lib/server-export.d.ts +2 -1
- package/lib/server-export.js +3 -4
- package/lib/sidebars/generator.js +63 -44
- package/lib/sidebars/index.js +20 -16
- package/lib/sidebars/normalization.js +3 -3
- package/lib/sidebars/postProcessor.js +18 -25
- package/lib/sidebars/processor.d.ts +3 -1
- package/lib/sidebars/processor.js +17 -6
- package/lib/sidebars/types.d.ts +31 -19
- package/lib/sidebars/utils.d.ts +17 -6
- package/lib/sidebars/utils.js +27 -37
- package/lib/sidebars/validation.d.ts +3 -1
- package/lib/sidebars/validation.js +1 -0
- package/lib/slug.d.ts +1 -2
- package/lib/slug.js +4 -5
- package/lib/tags.d.ts +2 -1
- package/lib/tags.js +2 -2
- package/lib/translations.d.ts +3 -3
- package/lib/translations.js +28 -81
- package/lib/types.d.ts +10 -95
- package/lib/versions/files.d.ts +44 -0
- package/lib/versions/files.js +142 -0
- package/lib/versions/index.d.ts +36 -0
- package/lib/versions/index.js +155 -0
- package/lib/versions/validation.d.ts +17 -0
- package/lib/versions/validation.js +71 -0
- package/package.json +14 -12
- package/src/categoryGeneratedIndex.ts +10 -9
- package/src/cli.ts +64 -69
- package/src/client/docsClientUtils.ts +14 -16
- package/src/client/index.ts +42 -43
- package/src/constants.ts +4 -2
- package/src/deps.d.ts +1 -1
- package/src/docs.ts +48 -51
- package/src/{docFrontMatter.ts → frontMatter.ts} +9 -6
- package/src/globalData.ts +15 -16
- package/src/index.ts +45 -40
- package/src/lastUpdate.ts +20 -8
- package/src/markdown/index.ts +1 -3
- package/src/markdown/linkify.ts +6 -3
- package/src/numberPrefix.ts +18 -28
- package/src/options.ts +6 -8
- package/src/plugin-content-docs.d.ts +457 -116
- package/src/props.ts +12 -9
- package/src/routes.ts +13 -39
- package/src/server-export.ts +1 -3
- package/src/sidebars/generator.ts +88 -59
- package/src/sidebars/index.ts +20 -15
- package/src/sidebars/normalization.ts +1 -1
- package/src/sidebars/postProcessor.ts +6 -11
- package/src/sidebars/processor.ts +27 -14
- package/src/sidebars/types.ts +25 -23
- package/src/sidebars/utils.ts +45 -46
- package/src/sidebars/validation.ts +4 -3
- package/src/slug.ts +7 -6
- package/src/tags.ts +3 -2
- package/src/translations.ts +32 -84
- package/src/types.ts +15 -107
- package/src/versions/files.ts +220 -0
- package/src/versions/index.ts +247 -0
- package/src/versions/validation.ts +113 -0
- package/lib/versions.d.ts +0 -41
- package/lib/versions.js +0 -329
- 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 './
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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.
|
|
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.
|
|
236
|
-
: versionMetadata.
|
|
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
|
|
262
|
-
|
|
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
|
-
):
|
|
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
|
-
//
|
|
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
|
-
>):
|
|
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
|
-
//
|
|
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[]):
|
|
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 '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
10
|
+
import {getMainDocId} from './docs';
|
|
11
|
+
import type {FullVersion} from './types';
|
|
12
12
|
import type {
|
|
13
13
|
CategoryGeneratedIndexMetadata,
|
|
14
14
|
DocMetadata,
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
40
|
+
function toGlobalSidebars(
|
|
42
41
|
sidebars: Sidebars,
|
|
43
|
-
version:
|
|
44
|
-
):
|
|
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
|
-
?
|
|
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:
|
|
64
|
+
export function toGlobalDataVersion(version: FullVersion): GlobalVersion {
|
|
67
65
|
return {
|
|
68
66
|
name: version.versionName,
|
|
69
|
-
label: version.
|
|
67
|
+
label: version.label,
|
|
70
68
|
isLast: version.isLast,
|
|
71
|
-
path: version.
|
|
72
|
-
mainDocId: version
|
|
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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
285
|
+
versions.map((version) =>
|
|
281
286
|
createVersionRoutes({
|
|
282
|
-
|
|
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(
|
|
299
|
+
await Promise.all(versions.map(createVersionTagsRoutes));
|
|
295
300
|
|
|
296
|
-
setGlobalData
|
|
301
|
+
setGlobalData({
|
|
297
302
|
path: normalizeUrl([baseUrl, options.routeBasePath]),
|
|
298
|
-
versions:
|
|
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(
|
|
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 {
|
|
10
|
-
|
|
11
|
-
|
|
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<
|
|
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
|
|
32
|
-
|
|
33
|
-
|
|
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.
|
|
47
|
+
logger.warn(err);
|
|
36
48
|
}
|
|
37
49
|
return null;
|
|
38
50
|
}
|
package/src/markdown/index.ts
CHANGED
|
@@ -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
|
}
|
package/src/markdown/linkify.ts
CHANGED
|
@@ -6,15 +6,18 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type {DocsMarkdownOption} from '../types';
|
|
9
|
-
import {
|
|
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
|
-
|
|
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!`,
|