@docusaurus/plugin-content-docs 2.0.0-beta.8bda3b2db → 2.0.0-beta.9
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/.tsbuildinfo +1 -1
- package/lib/cli.d.ts +2 -2
- package/lib/cli.js +20 -24
- package/lib/client/docsClientUtils.d.ts +1 -4
- package/lib/client/docsClientUtils.js +12 -16
- package/lib/docFrontMatter.js +7 -3
- package/lib/docs.d.ts +4 -2
- package/lib/docs.js +77 -23
- package/lib/index.js +88 -94
- package/lib/lastUpdate.js +8 -8
- package/lib/markdown/index.d.ts +3 -6
- package/lib/markdown/index.js +3 -3
- package/lib/markdown/linkify.js +2 -2
- package/lib/options.d.ts +1 -1
- package/lib/options.js +39 -11
- package/lib/props.d.ts +7 -2
- package/lib/props.js +27 -4
- package/lib/{sidebarItemsGenerator.d.ts → sidebars/generator.d.ts} +3 -1
- package/lib/sidebars/generator.js +174 -0
- package/lib/sidebars/index.d.ts +14 -0
- package/lib/sidebars/index.js +64 -0
- package/lib/sidebars/normalization.d.ts +9 -0
- package/lib/sidebars/normalization.js +58 -0
- package/lib/sidebars/processor.d.ts +16 -0
- package/lib/sidebars/processor.js +70 -0
- package/lib/sidebars/types.d.ts +87 -0
- package/lib/sidebars/types.js +13 -0
- package/lib/sidebars/utils.d.ts +22 -0
- package/lib/sidebars/utils.js +101 -0
- package/lib/sidebars/validation.d.ts +8 -0
- package/lib/sidebars/validation.js +102 -0
- package/lib/slug.js +4 -4
- package/lib/tags.d.ts +8 -0
- package/lib/tags.js +22 -0
- package/lib/theme/hooks/useDocs.js +24 -21
- package/lib/translations.d.ts +1 -1
- package/lib/translations.js +13 -13
- package/lib/types.d.ts +35 -58
- package/lib/versions.d.ts +1 -1
- package/lib/versions.js +75 -22
- package/package.json +15 -14
- package/src/__tests__/__fixtures__/simple-site/docs/_partials/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/simple-site/docs/_partials/subfolder/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/simple-site/docs/_somePartial.md +3 -0
- package/src/__tests__/__fixtures__/simple-site/docs/foo/baz.md +5 -0
- package/src/__tests__/__fixtures__/simple-site/docs/hello.md +1 -0
- package/src/__tests__/__fixtures__/simple-site/docs/rootAbsoluteSlug.md +2 -0
- package/src/__tests__/__fixtures__/simple-site/docs/rootRelativeSlug.md +2 -0
- package/src/__tests__/__fixtures__/simple-site/docs/rootResolvedSlug.md +2 -0
- package/src/__tests__/__fixtures__/simple-site/docs/rootTryToEscapeSlug.md +2 -0
- package/src/__tests__/__fixtures__/simple-site/sidebars.json +15 -1
- package/src/__tests__/__fixtures__/versioned-site/docs/foo/bar.md +6 -0
- package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_partials/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_partials/subfolder/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/versioned-site/versioned_docs/version-1.0.1/_somePartial.md +3 -0
- package/src/__tests__/__snapshots__/cli.test.ts.snap +33 -0
- package/src/__tests__/__snapshots__/docs.test.ts.snap +140 -0
- package/src/__tests__/__snapshots__/index.test.ts.snap +478 -60
- package/src/__tests__/__snapshots__/translations.test.ts.snap +0 -3
- package/src/__tests__/cli.test.ts +14 -10
- package/src/__tests__/docFrontMatter.test.ts +163 -48
- package/src/__tests__/docs.test.ts +167 -21
- package/src/__tests__/index.test.ts +74 -30
- package/src/__tests__/lastUpdate.test.ts +3 -2
- package/src/__tests__/options.test.ts +46 -3
- package/src/__tests__/props.test.ts +62 -0
- package/src/__tests__/translations.test.ts +0 -1
- package/src/__tests__/versions.test.ts +88 -60
- package/src/cli.ts +27 -30
- package/src/client/__tests__/docsClientUtils.test.ts +4 -5
- package/src/client/docsClientUtils.ts +6 -27
- package/src/docFrontMatter.ts +8 -3
- package/src/docs.ts +92 -9
- package/src/index.ts +114 -121
- package/src/lastUpdate.ts +10 -6
- package/src/markdown/index.ts +8 -12
- package/src/numberPrefix.ts +4 -2
- package/src/options.ts +47 -17
- package/src/plugin-content-docs.d.ts +121 -34
- package/src/props.ts +42 -6
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-shorthand.js +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-wrong-items.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category-wrong-label.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-category.js +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-collapsed-first-level.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-collapsed.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-doc-id-not-string.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-first-level-not-category.js +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link-wrong-href.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link-wrong-label.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-link.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-unknown-type.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars-wrong-field.json +0 -0
- package/src/{__tests__ → sidebars/__tests__}/__fixtures__/sidebars/sidebars.json +0 -0
- package/src/{__tests__/__snapshots__/sidebars.test.ts.snap → sidebars/__tests__/__snapshots__/index.test.ts.snap} +21 -6
- package/src/{__tests__/sidebarItemsGenerator.test.ts → sidebars/__tests__/generator.test.ts} +29 -7
- package/src/sidebars/__tests__/index.test.ts +202 -0
- package/src/sidebars/__tests__/processor.test.ts +148 -0
- package/src/sidebars/__tests__/utils.test.ts +395 -0
- package/src/sidebars/generator.ts +253 -0
- package/src/sidebars/index.ts +84 -0
- package/src/sidebars/normalization.ts +88 -0
- package/src/sidebars/processor.ts +124 -0
- package/src/sidebars/types.ts +156 -0
- package/src/sidebars/utils.ts +146 -0
- package/src/sidebars/validation.ts +124 -0
- package/src/tags.ts +21 -0
- package/src/theme/hooks/useDocs.ts +5 -1
- package/src/translations.ts +26 -36
- package/src/types.ts +48 -99
- package/src/versions.ts +109 -17
- package/lib/sidebarItemsGenerator.js +0 -211
- package/lib/sidebars.d.ts +0 -43
- package/lib/sidebars.js +0 -319
- package/src/__tests__/sidebars.test.ts +0 -639
- package/src/sidebarItemsGenerator.ts +0 -307
- package/src/sidebars.ts +0 -506
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} from 'lodash';
|
|
10
12
|
import {
|
|
11
13
|
aliasedSitePath,
|
|
12
14
|
getEditUrl,
|
|
@@ -14,6 +16,8 @@ import {
|
|
|
14
16
|
normalizeUrl,
|
|
15
17
|
parseMarkdownString,
|
|
16
18
|
posixPath,
|
|
19
|
+
Globby,
|
|
20
|
+
normalizeFrontMatterTags,
|
|
17
21
|
} from '@docusaurus/utils';
|
|
18
22
|
import {LoadContext} from '@docusaurus/types';
|
|
19
23
|
|
|
@@ -21,18 +25,21 @@ 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
|
|
41
|
+
import type {Sidebars} from './sidebars/types';
|
|
42
|
+
import {createSidebarsUtils} from './sidebars/utils';
|
|
36
43
|
|
|
37
44
|
type LastUpdateOptions = Pick<
|
|
38
45
|
PluginOptions,
|
|
@@ -92,11 +99,12 @@ export async function readVersionDocs(
|
|
|
92
99
|
versionMetadata: VersionMetadata,
|
|
93
100
|
options: Pick<
|
|
94
101
|
PluginOptions,
|
|
95
|
-
'include' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
|
|
102
|
+
'include' | 'exclude' | 'showLastUpdateAuthor' | 'showLastUpdateTime'
|
|
96
103
|
>,
|
|
97
104
|
): Promise<DocFile[]> {
|
|
98
|
-
const sources = await
|
|
105
|
+
const sources = await Globby(options.include, {
|
|
99
106
|
cwd: versionMetadata.contentPath,
|
|
107
|
+
ignore: options.exclude,
|
|
100
108
|
});
|
|
101
109
|
return Promise.all(
|
|
102
110
|
sources.map((source) => readDocFile(versionMetadata, source, options)),
|
|
@@ -129,8 +137,8 @@ function doProcessDocMetadata({
|
|
|
129
137
|
custom_edit_url: customEditURL,
|
|
130
138
|
|
|
131
139
|
// Strip number prefixes by default (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc) by default,
|
|
132
|
-
// but allow to disable this behavior with
|
|
133
|
-
parse_number_prefixes = true,
|
|
140
|
+
// but allow to disable this behavior with frontmatter
|
|
141
|
+
parse_number_prefixes: parseNumberPrefixes = true,
|
|
134
142
|
} = frontMatter;
|
|
135
143
|
|
|
136
144
|
// ex: api/plugins/myDoc -> myDoc
|
|
@@ -144,7 +152,7 @@ function doProcessDocMetadata({
|
|
|
144
152
|
// ex: myDoc -> .
|
|
145
153
|
const sourceDirName = path.dirname(source);
|
|
146
154
|
|
|
147
|
-
const {filename: unprefixedFileName, numberPrefix} =
|
|
155
|
+
const {filename: unprefixedFileName, numberPrefix} = parseNumberPrefixes
|
|
148
156
|
? options.numberPrefixParser(sourceFileNameWithoutExtension)
|
|
149
157
|
: {filename: sourceFileNameWithoutExtension, numberPrefix: undefined};
|
|
150
158
|
|
|
@@ -172,7 +180,7 @@ function doProcessDocMetadata({
|
|
|
172
180
|
return undefined;
|
|
173
181
|
}
|
|
174
182
|
// Eventually remove the number prefixes from intermediate directories
|
|
175
|
-
return
|
|
183
|
+
return parseNumberPrefixes
|
|
176
184
|
? stripPathNumberPrefixes(sourceDirName, options.numberPrefixParser)
|
|
177
185
|
: sourceDirName;
|
|
178
186
|
}
|
|
@@ -199,7 +207,7 @@ function doProcessDocMetadata({
|
|
|
199
207
|
baseID,
|
|
200
208
|
dirName: sourceDirName,
|
|
201
209
|
frontmatterSlug: frontMatter.slug,
|
|
202
|
-
stripDirNumberPrefixes:
|
|
210
|
+
stripDirNumberPrefixes: parseNumberPrefixes,
|
|
203
211
|
numberPrefixParser: options.numberPrefixParser,
|
|
204
212
|
});
|
|
205
213
|
|
|
@@ -251,6 +259,7 @@ function doProcessDocMetadata({
|
|
|
251
259
|
slug: docSlug,
|
|
252
260
|
permalink,
|
|
253
261
|
editUrl: customEditURL !== undefined ? customEditURL : getDocEditUrl(),
|
|
262
|
+
tags: normalizeFrontMatterTags(versionMetadata.tagsPath, frontMatter.tags),
|
|
254
263
|
version: versionMetadata.versionName,
|
|
255
264
|
lastUpdatedBy: lastUpdate.lastUpdatedBy,
|
|
256
265
|
lastUpdatedAt: lastUpdate.lastUpdatedAt,
|
|
@@ -281,3 +290,77 @@ export function processDocMetadata(args: {
|
|
|
281
290
|
throw e;
|
|
282
291
|
}
|
|
283
292
|
}
|
|
293
|
+
|
|
294
|
+
export function handleNavigation(
|
|
295
|
+
docsBase: DocMetadataBase[],
|
|
296
|
+
sidebars: Sidebars,
|
|
297
|
+
sidebarFilePath: string,
|
|
298
|
+
): Pick<LoadedVersion, 'mainDocId' | 'docs'> {
|
|
299
|
+
const docsBaseById = keyBy(docsBase, (doc) => doc.id);
|
|
300
|
+
const {checkSidebarsDocIds, getDocNavigation, getFirstDocIdOfFirstSidebar} =
|
|
301
|
+
createSidebarsUtils(sidebars);
|
|
302
|
+
|
|
303
|
+
const validDocIds = Object.keys(docsBaseById);
|
|
304
|
+
checkSidebarsDocIds(validDocIds, sidebarFilePath);
|
|
305
|
+
|
|
306
|
+
// Add sidebar/next/previous to the docs
|
|
307
|
+
function addNavData(doc: DocMetadataBase): DocMetadata {
|
|
308
|
+
const {sidebarName, previousId, nextId} = getDocNavigation(doc.id);
|
|
309
|
+
const toDocNavLink = (
|
|
310
|
+
docId: string | null | undefined,
|
|
311
|
+
type: 'prev' | 'next',
|
|
312
|
+
): DocNavLink | undefined => {
|
|
313
|
+
if (!docId) {
|
|
314
|
+
return undefined;
|
|
315
|
+
}
|
|
316
|
+
if (!docsBaseById[docId]) {
|
|
317
|
+
// This could only happen if user provided the ID through front matter
|
|
318
|
+
throw new Error(
|
|
319
|
+
`Error when loading ${doc.id} in ${doc.sourceDirName}: the pagination_${type} front matter points to a non-existent ID ${docId}.`,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
const {
|
|
323
|
+
title,
|
|
324
|
+
permalink,
|
|
325
|
+
frontMatter: {
|
|
326
|
+
pagination_label: paginationLabel,
|
|
327
|
+
sidebar_label: sidebarLabel,
|
|
328
|
+
},
|
|
329
|
+
} = docsBaseById[docId];
|
|
330
|
+
return {title: paginationLabel ?? sidebarLabel ?? title, permalink};
|
|
331
|
+
};
|
|
332
|
+
const {
|
|
333
|
+
frontMatter: {
|
|
334
|
+
pagination_next: paginationNext = nextId,
|
|
335
|
+
pagination_prev: paginationPrev = previousId,
|
|
336
|
+
},
|
|
337
|
+
} = doc;
|
|
338
|
+
const previous = toDocNavLink(paginationPrev, 'prev');
|
|
339
|
+
const next = toDocNavLink(paginationNext, 'next');
|
|
340
|
+
return {...doc, sidebar: sidebarName, previous, next};
|
|
341
|
+
}
|
|
342
|
+
const docs = docsBase.map(addNavData);
|
|
343
|
+
// sort to ensure consistent output for tests
|
|
344
|
+
docs.sort((a, b) => a.id.localeCompare(b.id));
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* The "main doc" is the "version entry point"
|
|
348
|
+
* We browse this doc by clicking on a version:
|
|
349
|
+
* - the "home" doc (at '/docs/')
|
|
350
|
+
* - the first doc of the first sidebar
|
|
351
|
+
* - a random doc (if no docs are in any sidebar... edge case)
|
|
352
|
+
*/
|
|
353
|
+
function getMainDoc(): DocMetadata {
|
|
354
|
+
const versionHomeDoc = docs.find((doc) => doc.slug === '/');
|
|
355
|
+
const firstDocIdOfFirstSidebar = 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 {mainDocId: getMainDoc().unversionedId, docs};
|
|
366
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -18,10 +18,12 @@ import {
|
|
|
18
18
|
reportMessage,
|
|
19
19
|
posixPath,
|
|
20
20
|
addTrailingPathSeparator,
|
|
21
|
+
createAbsoluteFilePathMatcher,
|
|
21
22
|
} from '@docusaurus/utils';
|
|
22
23
|
import {LoadContext, Plugin, RouteConfig} from '@docusaurus/types';
|
|
23
|
-
import {loadSidebars
|
|
24
|
-
import {
|
|
24
|
+
import {loadSidebars} from './sidebars';
|
|
25
|
+
import {CategoryMetadataFilenamePattern} from './sidebars/generator';
|
|
26
|
+
import {readVersionDocs, processDocMetadata, handleNavigation} from './docs';
|
|
25
27
|
import {getDocsDirPaths, readVersionsMetadata} from './versions';
|
|
26
28
|
|
|
27
29
|
import {
|
|
@@ -32,24 +34,24 @@ import {
|
|
|
32
34
|
DocMetadata,
|
|
33
35
|
GlobalPluginData,
|
|
34
36
|
VersionMetadata,
|
|
35
|
-
DocNavLink,
|
|
36
37
|
LoadedVersion,
|
|
37
38
|
DocFile,
|
|
38
39
|
DocsMarkdownOption,
|
|
40
|
+
VersionTag,
|
|
39
41
|
} from './types';
|
|
40
|
-
import {PermalinkToSidebar} from '@docusaurus/plugin-content-docs-types';
|
|
41
42
|
import {RuleSetRule} from 'webpack';
|
|
42
43
|
import {cliDocsVersionCommand} from './cli';
|
|
43
44
|
import {VERSIONS_JSON_FILE} from './constants';
|
|
44
|
-
import {
|
|
45
|
+
import {keyBy, mapValues} from 'lodash';
|
|
45
46
|
import {toGlobalDataVersion} from './globalData';
|
|
46
|
-
import {toVersionMetadataProp} from './props';
|
|
47
|
+
import {toTagDocListProp, toVersionMetadataProp} from './props';
|
|
47
48
|
import {
|
|
48
49
|
translateLoadedContent,
|
|
49
50
|
getLoadedContentTranslationFiles,
|
|
50
51
|
} from './translations';
|
|
51
|
-
import {CategoryMetadataFilenamePattern} from './sidebarItemsGenerator';
|
|
52
52
|
import chalk from 'chalk';
|
|
53
|
+
import {getVersionTags} from './tags';
|
|
54
|
+
import {PropTagsListPage} from '@docusaurus/plugin-content-docs-types';
|
|
53
55
|
|
|
54
56
|
export default function pluginContentDocs(
|
|
55
57
|
context: LoadContext,
|
|
@@ -59,7 +61,6 @@ export default function pluginContentDocs(
|
|
|
59
61
|
|
|
60
62
|
const versionsMetadata = readVersionsMetadata({context, options});
|
|
61
63
|
|
|
62
|
-
const sourceToPermalink: SourceToPermalink = {};
|
|
63
64
|
const pluginId = options.id ?? DEFAULT_PLUGIN_ID;
|
|
64
65
|
|
|
65
66
|
const pluginDataDirRoot = path.join(
|
|
@@ -101,6 +102,8 @@ export default function pluginContentDocs(
|
|
|
101
102
|
cliDocsVersionCommand(version, siteDir, pluginId, {
|
|
102
103
|
path: options.path,
|
|
103
104
|
sidebarPath: options.sidebarPath,
|
|
105
|
+
sidebarCollapsed: options.sidebarCollapsed,
|
|
106
|
+
sidebarCollapsible: options.sidebarCollapsible,
|
|
104
107
|
});
|
|
105
108
|
});
|
|
106
109
|
},
|
|
@@ -109,22 +112,12 @@ export default function pluginContentDocs(
|
|
|
109
112
|
return getLoadedContentTranslationFiles(content);
|
|
110
113
|
},
|
|
111
114
|
|
|
112
|
-
getClientModules() {
|
|
113
|
-
const modules = [];
|
|
114
|
-
if (options.admonitions) {
|
|
115
|
-
modules.push(require.resolve('remark-admonitions/styles/infima.css'));
|
|
116
|
-
}
|
|
117
|
-
return modules;
|
|
118
|
-
},
|
|
119
|
-
|
|
120
115
|
getPathsToWatch() {
|
|
121
116
|
function getVersionPathsToWatch(version: VersionMetadata): string[] {
|
|
122
117
|
const result = [
|
|
123
|
-
...
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
(docsDirPath) => `${docsDirPath}/${pattern}`,
|
|
127
|
-
),
|
|
118
|
+
...options.include.flatMap((pattern) =>
|
|
119
|
+
getDocsDirPaths(version).map(
|
|
120
|
+
(docsDirPath) => `${docsDirPath}/${pattern}`,
|
|
128
121
|
),
|
|
129
122
|
),
|
|
130
123
|
`${version.contentPath}/**/${CategoryMetadataFilenamePattern}`,
|
|
@@ -135,7 +128,7 @@ export default function pluginContentDocs(
|
|
|
135
128
|
return result;
|
|
136
129
|
}
|
|
137
130
|
|
|
138
|
-
return
|
|
131
|
+
return versionsMetadata.flatMap(getVersionPathsToWatch);
|
|
139
132
|
},
|
|
140
133
|
|
|
141
134
|
async loadContent() {
|
|
@@ -167,104 +160,28 @@ export default function pluginContentDocs(
|
|
|
167
160
|
async function doLoadVersion(
|
|
168
161
|
versionMetadata: VersionMetadata,
|
|
169
162
|
): Promise<LoadedVersion> {
|
|
170
|
-
const unprocessedSidebars = loadSidebars(
|
|
171
|
-
versionMetadata.sidebarFilePath,
|
|
172
|
-
);
|
|
173
|
-
|
|
174
163
|
const docsBase: DocMetadataBase[] = await loadVersionDocsBase(
|
|
175
164
|
versionMetadata,
|
|
176
165
|
);
|
|
177
|
-
const docsBaseById: Record<string, DocMetadataBase> = keyBy(
|
|
178
|
-
docsBase,
|
|
179
|
-
(doc) => doc.id,
|
|
180
|
-
);
|
|
181
166
|
|
|
182
|
-
const sidebars = await
|
|
167
|
+
const sidebars = await loadSidebars(versionMetadata.sidebarFilePath, {
|
|
183
168
|
sidebarItemsGenerator: options.sidebarItemsGenerator,
|
|
184
169
|
numberPrefixParser: options.numberPrefixParser,
|
|
185
|
-
unprocessedSidebars,
|
|
186
170
|
docs: docsBase,
|
|
187
171
|
version: versionMetadata,
|
|
172
|
+
options: {
|
|
173
|
+
sidebarCollapsed: options.sidebarCollapsed,
|
|
174
|
+
sidebarCollapsible: options.sidebarCollapsible,
|
|
175
|
+
},
|
|
188
176
|
});
|
|
189
|
-
|
|
190
|
-
const sidebarsUtils = createSidebarsUtils(sidebars);
|
|
191
|
-
|
|
192
|
-
const validDocIds = Object.keys(docsBaseById);
|
|
193
|
-
sidebarsUtils.checkSidebarsDocIds(
|
|
194
|
-
validDocIds,
|
|
195
|
-
versionMetadata.sidebarFilePath as string,
|
|
196
|
-
);
|
|
197
|
-
|
|
198
|
-
// Add sidebar/next/previous to the docs
|
|
199
|
-
function addNavData(doc: DocMetadataBase): DocMetadata {
|
|
200
|
-
const {
|
|
201
|
-
sidebarName,
|
|
202
|
-
previousId,
|
|
203
|
-
nextId,
|
|
204
|
-
} = sidebarsUtils.getDocNavigation(doc.id);
|
|
205
|
-
const toDocNavLink = (navDocId: string): DocNavLink => {
|
|
206
|
-
const {title, permalink, frontMatter} = docsBaseById[navDocId];
|
|
207
|
-
return {
|
|
208
|
-
title:
|
|
209
|
-
frontMatter.pagination_label ??
|
|
210
|
-
frontMatter.sidebar_label ??
|
|
211
|
-
title,
|
|
212
|
-
permalink,
|
|
213
|
-
};
|
|
214
|
-
};
|
|
215
|
-
return {
|
|
216
|
-
...doc,
|
|
217
|
-
sidebar: sidebarName,
|
|
218
|
-
previous: previousId ? toDocNavLink(previousId) : undefined,
|
|
219
|
-
next: nextId ? toDocNavLink(nextId) : undefined,
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const docs = docsBase.map(addNavData);
|
|
224
|
-
|
|
225
|
-
// sort to ensure consistent output for tests
|
|
226
|
-
docs.sort((a, b) => a.id.localeCompare(b.id));
|
|
227
|
-
|
|
228
|
-
// TODO annoying side effect!
|
|
229
|
-
Object.values(docs).forEach((loadedDoc) => {
|
|
230
|
-
const {source, permalink} = loadedDoc;
|
|
231
|
-
sourceToPermalink[source] = permalink;
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// TODO really useful? replace with global state logic?
|
|
235
|
-
const permalinkToSidebar: PermalinkToSidebar = {};
|
|
236
|
-
Object.values(docs).forEach((doc) => {
|
|
237
|
-
if (doc.sidebar) {
|
|
238
|
-
permalinkToSidebar[doc.permalink] = doc.sidebar;
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
// The "main doc" is the "version entry point"
|
|
243
|
-
// We browse this doc by clicking on a version:
|
|
244
|
-
// - the "home" doc (at '/docs/')
|
|
245
|
-
// - the first doc of the first sidebar
|
|
246
|
-
// - a random doc (if no docs are in any sidebar... edge case)
|
|
247
|
-
function getMainDoc(): DocMetadata {
|
|
248
|
-
const versionHomeDoc = docs.find(
|
|
249
|
-
(doc) =>
|
|
250
|
-
doc.unversionedId === options.homePageId || doc.slug === '/',
|
|
251
|
-
);
|
|
252
|
-
const firstDocIdOfFirstSidebar = sidebarsUtils.getFirstDocIdOfFirstSidebar();
|
|
253
|
-
if (versionHomeDoc) {
|
|
254
|
-
return versionHomeDoc;
|
|
255
|
-
} else if (firstDocIdOfFirstSidebar) {
|
|
256
|
-
return docs.find((doc) => doc.id === firstDocIdOfFirstSidebar)!;
|
|
257
|
-
} else {
|
|
258
|
-
return docs[0];
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
177
|
return {
|
|
263
178
|
...versionMetadata,
|
|
264
|
-
|
|
179
|
+
...handleNavigation(
|
|
180
|
+
docsBase,
|
|
181
|
+
sidebars,
|
|
182
|
+
versionMetadata.sidebarFilePath as string,
|
|
183
|
+
),
|
|
265
184
|
sidebars,
|
|
266
|
-
permalinkToSidebar,
|
|
267
|
-
docs: docs.map(addNavData),
|
|
268
185
|
};
|
|
269
186
|
}
|
|
270
187
|
|
|
@@ -307,30 +224,91 @@ export default function pluginContentDocs(
|
|
|
307
224
|
JSON.stringify(metadataItem, null, 2),
|
|
308
225
|
);
|
|
309
226
|
|
|
310
|
-
|
|
227
|
+
const docRoute: RouteConfig = {
|
|
311
228
|
path: metadataItem.permalink,
|
|
312
229
|
component: docItemComponent,
|
|
313
230
|
exact: true,
|
|
314
231
|
modules: {
|
|
315
232
|
content: metadataItem.source,
|
|
316
233
|
},
|
|
234
|
+
// Because the parent (DocPage) comp need to access it easily
|
|
235
|
+
// This permits to render the sidebar once without unmount/remount when navigating (and preserve sidebar state)
|
|
236
|
+
...(metadataItem.sidebar && {
|
|
237
|
+
sidebar: metadataItem.sidebar,
|
|
238
|
+
}),
|
|
317
239
|
};
|
|
240
|
+
|
|
241
|
+
return docRoute;
|
|
318
242
|
}),
|
|
319
243
|
);
|
|
320
244
|
|
|
321
245
|
return routes.sort((a, b) => a.path.localeCompare(b.path));
|
|
322
246
|
};
|
|
323
247
|
|
|
324
|
-
async function
|
|
248
|
+
async function createVersionTagsRoutes(loadedVersion: LoadedVersion) {
|
|
249
|
+
const versionTags = getVersionTags(loadedVersion.docs);
|
|
250
|
+
|
|
251
|
+
async function createTagsListPage() {
|
|
252
|
+
const tagsProp: PropTagsListPage['tags'] = Object.values(
|
|
253
|
+
versionTags,
|
|
254
|
+
).map((tagValue) => ({
|
|
255
|
+
name: tagValue.name,
|
|
256
|
+
permalink: tagValue.permalink,
|
|
257
|
+
count: tagValue.docIds.length,
|
|
258
|
+
}));
|
|
259
|
+
|
|
260
|
+
// Only create /tags page if there are tags.
|
|
261
|
+
if (Object.keys(tagsProp).length > 0) {
|
|
262
|
+
const tagsPropPath = await createData(
|
|
263
|
+
`${docuHash(`tags-list-${loadedVersion.versionName}-prop`)}.json`,
|
|
264
|
+
JSON.stringify(tagsProp, null, 2),
|
|
265
|
+
);
|
|
266
|
+
addRoute({
|
|
267
|
+
path: loadedVersion.tagsPath,
|
|
268
|
+
exact: true,
|
|
269
|
+
component: options.docTagsListComponent,
|
|
270
|
+
modules: {
|
|
271
|
+
tags: aliasedSource(tagsPropPath),
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async function createTagDocListPage(tag: VersionTag) {
|
|
278
|
+
const tagProps = toTagDocListProp({
|
|
279
|
+
allTagsPath: loadedVersion.tagsPath,
|
|
280
|
+
tag,
|
|
281
|
+
docs: loadedVersion.docs,
|
|
282
|
+
});
|
|
283
|
+
const tagPropPath = await createData(
|
|
284
|
+
`${docuHash(`tag-${tag.permalink}`)}.json`,
|
|
285
|
+
JSON.stringify(tagProps, null, 2),
|
|
286
|
+
);
|
|
287
|
+
addRoute({
|
|
288
|
+
path: tag.permalink,
|
|
289
|
+
component: options.docTagDocListComponent,
|
|
290
|
+
exact: true,
|
|
291
|
+
modules: {
|
|
292
|
+
tag: aliasedSource(tagPropPath),
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
await createTagsListPage();
|
|
298
|
+
await Promise.all(Object.values(versionTags).map(createTagDocListPage));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async function doCreateVersionRoutes(
|
|
302
|
+
loadedVersion: LoadedVersion,
|
|
303
|
+
): Promise<void> {
|
|
304
|
+
await createVersionTagsRoutes(loadedVersion);
|
|
305
|
+
|
|
306
|
+
const versionMetadata = toVersionMetadataProp(pluginId, loadedVersion);
|
|
325
307
|
const versionMetadataPropPath = await createData(
|
|
326
308
|
`${docuHash(
|
|
327
309
|
`version-${loadedVersion.versionName}-metadata-prop`,
|
|
328
310
|
)}.json`,
|
|
329
|
-
JSON.stringify(
|
|
330
|
-
toVersionMetadataProp(pluginId, loadedVersion),
|
|
331
|
-
null,
|
|
332
|
-
2,
|
|
333
|
-
),
|
|
311
|
+
JSON.stringify(versionMetadata, null, 2),
|
|
334
312
|
);
|
|
335
313
|
|
|
336
314
|
addRoute({
|
|
@@ -348,7 +326,9 @@ export default function pluginContentDocs(
|
|
|
348
326
|
});
|
|
349
327
|
}
|
|
350
328
|
|
|
351
|
-
async function createVersionRoutes(
|
|
329
|
+
async function createVersionRoutes(
|
|
330
|
+
loadedVersion: LoadedVersion,
|
|
331
|
+
): Promise<void> {
|
|
352
332
|
try {
|
|
353
333
|
return await doCreateVersionRoutes(loadedVersion);
|
|
354
334
|
} catch (e) {
|
|
@@ -369,7 +349,7 @@ export default function pluginContentDocs(
|
|
|
369
349
|
});
|
|
370
350
|
},
|
|
371
351
|
|
|
372
|
-
configureWebpack(_config, isServer, utils) {
|
|
352
|
+
configureWebpack(_config, isServer, utils, content) {
|
|
373
353
|
const {getJSLoader} = utils;
|
|
374
354
|
const {
|
|
375
355
|
rehypePlugins,
|
|
@@ -378,9 +358,17 @@ export default function pluginContentDocs(
|
|
|
378
358
|
beforeDefaultRemarkPlugins,
|
|
379
359
|
} = options;
|
|
380
360
|
|
|
361
|
+
function getSourceToPermalink(): SourceToPermalink {
|
|
362
|
+
const allDocs = content.loadedVersions.flatMap((v) => v.docs);
|
|
363
|
+
return mapValues(
|
|
364
|
+
keyBy(allDocs, (d) => d.source),
|
|
365
|
+
(d) => d.permalink,
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
381
369
|
const docsMarkdownOptions: DocsMarkdownOption = {
|
|
382
370
|
siteDir,
|
|
383
|
-
sourceToPermalink,
|
|
371
|
+
sourceToPermalink: getSourceToPermalink(),
|
|
384
372
|
versionsMetadata,
|
|
385
373
|
onBrokenMarkdownLink: (brokenMarkdownLink) => {
|
|
386
374
|
if (siteConfig.onBrokenMarkdownLinks === 'ignore') {
|
|
@@ -394,12 +382,13 @@ export default function pluginContentDocs(
|
|
|
394
382
|
};
|
|
395
383
|
|
|
396
384
|
function createMDXLoaderRule(): RuleSetRule {
|
|
385
|
+
const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
|
|
397
386
|
return {
|
|
398
387
|
test: /(\.mdx?)$/,
|
|
399
|
-
include:
|
|
388
|
+
include: contentDirs
|
|
400
389
|
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
401
390
|
.map(addTrailingPathSeparator),
|
|
402
|
-
use:
|
|
391
|
+
use: [
|
|
403
392
|
getJSLoader({isServer}),
|
|
404
393
|
{
|
|
405
394
|
loader: require.resolve('@docusaurus/mdx-loader'),
|
|
@@ -409,6 +398,10 @@ export default function pluginContentDocs(
|
|
|
409
398
|
beforeDefaultRehypePlugins,
|
|
410
399
|
beforeDefaultRemarkPlugins,
|
|
411
400
|
staticDir: path.join(siteDir, STATIC_DIR_NAME),
|
|
401
|
+
isMDXPartial: createAbsoluteFilePathMatcher(
|
|
402
|
+
options.exclude,
|
|
403
|
+
contentDirs,
|
|
404
|
+
),
|
|
412
405
|
metadataPath: (mdxPath: string) => {
|
|
413
406
|
// Note that metadataPath must be the same/in-sync as
|
|
414
407
|
// the path from createData for each MDX.
|
|
@@ -421,7 +414,7 @@ export default function pluginContentDocs(
|
|
|
421
414
|
loader: path.resolve(__dirname, './markdown/index.js'),
|
|
422
415
|
options: docsMarkdownOptions,
|
|
423
416
|
},
|
|
424
|
-
]),
|
|
417
|
+
].filter(Boolean),
|
|
425
418
|
};
|
|
426
419
|
}
|
|
427
420
|
|
package/src/lastUpdate.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import shell from 'shelljs';
|
|
9
9
|
import execa from 'execa';
|
|
10
|
+
import path from 'path';
|
|
10
11
|
|
|
11
12
|
type FileLastUpdateData = {timestamp?: number; author?: string};
|
|
12
13
|
|
|
@@ -43,12 +44,15 @@ export async function getFileLastUpdate(
|
|
|
43
44
|
return null;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
'
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
const fileBasename = path.basename(filePath);
|
|
48
|
+
const fileDirname = path.dirname(filePath);
|
|
49
|
+
const {stdout} = await execa(
|
|
50
|
+
'git',
|
|
51
|
+
['log', '-1', '--format=%ct, %an', fileBasename],
|
|
52
|
+
{
|
|
53
|
+
cwd: fileDirname,
|
|
54
|
+
},
|
|
55
|
+
);
|
|
52
56
|
return getTimestampAndAuthor(stdout);
|
|
53
57
|
} catch (error) {
|
|
54
58
|
console.error(error);
|
package/src/markdown/index.ts
CHANGED
|
@@ -7,20 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
import {linkify} from './linkify';
|
|
9
9
|
import {DocsMarkdownOption} from '../types';
|
|
10
|
+
import type {LoaderContext} from 'webpack';
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const markdownLoader: Loader = function (source) {
|
|
18
|
-
const fileString = source as string;
|
|
12
|
+
export default function markdownLoader(
|
|
13
|
+
this: LoaderContext<DocsMarkdownOption>,
|
|
14
|
+
source: string,
|
|
15
|
+
): void {
|
|
16
|
+
const fileString = source;
|
|
19
17
|
const callback = this.async();
|
|
20
|
-
const options = this.getOptions()
|
|
18
|
+
const options = this.getOptions();
|
|
21
19
|
return (
|
|
22
20
|
callback && callback(null, linkify(fileString, this.resourcePath, options))
|
|
23
21
|
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default markdownLoader;
|
|
22
|
+
}
|
package/src/numberPrefix.ts
CHANGED
|
@@ -10,7 +10,8 @@ import {NumberPrefixParser} from './types';
|
|
|
10
10
|
// Best-effort to avoid parsing some patterns as number prefix
|
|
11
11
|
const IgnoredPrefixPatterns = (function () {
|
|
12
12
|
// ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
|
|
13
|
-
const DateLikePrefixRegex =
|
|
13
|
+
const DateLikePrefixRegex =
|
|
14
|
+
/^((\d{2}|\d{4})[-_.]\d{2}([-_.](\d{2}|\d{4}))?)(.*)$/;
|
|
14
15
|
|
|
15
16
|
// ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
|
|
16
17
|
// note: we could try to parse float numbers in filenames but that is probably not worth it
|
|
@@ -23,7 +24,8 @@ const IgnoredPrefixPatterns = (function () {
|
|
|
23
24
|
);
|
|
24
25
|
})();
|
|
25
26
|
|
|
26
|
-
const NumberPrefixRegex =
|
|
27
|
+
const NumberPrefixRegex =
|
|
28
|
+
/^(?<numberPrefix>\d+)(?<separator>\s*[-_.]+\s*)(?<suffix>.*)$/;
|
|
27
29
|
|
|
28
30
|
// 0-myDoc => {filename: myDoc, numberPrefix: 0}
|
|
29
31
|
// 003 - myDoc => {filename: myDoc, numberPrefix: 3}
|