@docusaurus/plugin-content-docs 0.0.0-4521 → 0.0.0-4526
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/cli.d.ts +1 -1
- package/lib/cli.js +8 -6
- package/lib/client/docsClientUtils.js +2 -2
- package/lib/client/globalDataHooks.js +4 -3
- package/lib/docs.d.ts +2 -1
- package/lib/docs.js +17 -15
- package/lib/index.js +1 -1
- package/lib/lastUpdate.js +6 -5
- package/lib/numberPrefix.js +7 -6
- package/lib/options.js +3 -2
- package/lib/routes.js +4 -2
- package/lib/sidebars/generator.js +20 -17
- package/lib/sidebars/index.d.ts +2 -2
- package/lib/sidebars/index.js +6 -6
- package/lib/sidebars/processor.js +6 -3
- package/lib/sidebars/utils.js +46 -54
- package/lib/sidebars/validation.js +7 -4
- package/lib/slug.js +6 -8
- package/lib/translations.js +7 -7
- package/lib/versions.js +11 -21
- package/package.json +9 -9
- package/src/cli.ts +9 -7
- package/src/client/docsClientUtils.ts +2 -2
- package/src/client/globalDataHooks.ts +4 -3
- package/src/docs.ts +17 -13
- package/src/index.ts +1 -1
- package/src/lastUpdate.ts +5 -5
- package/src/numberPrefix.ts +7 -6
- package/src/options.ts +3 -2
- package/src/plugin-content-docs.d.ts +2 -1
- package/src/routes.ts +4 -2
- package/src/sidebars/generator.ts +25 -19
- package/src/sidebars/index.ts +9 -9
- package/src/sidebars/processor.ts +6 -3
- package/src/sidebars/types.ts +2 -1
- package/src/sidebars/utils.ts +57 -61
- package/src/sidebars/validation.ts +7 -4
- package/src/slug.ts +9 -10
- package/src/translations.ts +7 -6
- package/src/versions.ts +13 -19
package/lib/slug.js
CHANGED
|
@@ -23,15 +23,13 @@ function getSlug({ baseID, frontMatterSlug, source, sourceDirName, stripDirNumbe
|
|
|
23
23
|
if (frontMatterSlug === null || frontMatterSlug === void 0 ? void 0 : frontMatterSlug.startsWith('/')) {
|
|
24
24
|
return frontMatterSlug;
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return dirNameSlug;
|
|
31
|
-
}
|
|
32
|
-
const baseSlug = frontMatterSlug || baseID;
|
|
33
|
-
return (0, utils_1.resolvePathname)(baseSlug, getDirNameSlug());
|
|
26
|
+
const dirNameSlug = getDirNameSlug();
|
|
27
|
+
if (!frontMatterSlug &&
|
|
28
|
+
(0, docs_1.isCategoryIndex)((0, docs_1.toCategoryIndexMatcherParam)({ source, sourceDirName }))) {
|
|
29
|
+
return dirNameSlug;
|
|
34
30
|
}
|
|
31
|
+
const baseSlug = frontMatterSlug || baseID;
|
|
32
|
+
return (0, utils_1.resolvePathname)(baseSlug, getDirNameSlug());
|
|
35
33
|
}
|
|
36
34
|
function ensureValidSlug(slug) {
|
|
37
35
|
if (!(0, utils_1.isValidPathname)(slug)) {
|
package/lib/translations.js
CHANGED
|
@@ -15,11 +15,9 @@ function getVersionFileName(versionName) {
|
|
|
15
15
|
if (versionName === constants_1.CURRENT_VERSION_NAME) {
|
|
16
16
|
return versionName;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return `version-${versionName}`;
|
|
22
|
-
}
|
|
18
|
+
// I don't like this "version-" prefix,
|
|
19
|
+
// but it's for consistency with site/versioned_docs
|
|
20
|
+
return `version-${versionName}`;
|
|
23
21
|
}
|
|
24
22
|
// TODO legacy, the sidebar name is like "version-2.0.0-alpha.66/docs"
|
|
25
23
|
// input: "version-2.0.0-alpha.66/docs"
|
|
@@ -44,7 +42,8 @@ function getDocTranslations(doc: DocMetadata): TranslationFileContent {
|
|
|
44
42
|
? {
|
|
45
43
|
[`${doc.unversionedId}.sidebar_label`]: {
|
|
46
44
|
message: doc.sidebar_label,
|
|
47
|
-
description:
|
|
45
|
+
description:
|
|
46
|
+
`The sidebar label for doc with id=${doc.unversionedId}`,
|
|
48
47
|
},
|
|
49
48
|
}
|
|
50
49
|
: undefined),
|
|
@@ -181,7 +180,8 @@ function getVersionTranslationFiles(version) {
|
|
|
181
180
|
},
|
|
182
181
|
};
|
|
183
182
|
const sidebarsTranslations = getSidebarsTranslations(version);
|
|
184
|
-
// const docsTranslations: TranslationFileContent =
|
|
183
|
+
// const docsTranslations: TranslationFileContent =
|
|
184
|
+
// getDocsTranslations(version);
|
|
185
185
|
return [
|
|
186
186
|
{
|
|
187
187
|
path: getVersionFileName(version.versionName),
|
package/lib/versions.js
CHANGED
|
@@ -16,12 +16,9 @@ const lodash_1 = require("lodash");
|
|
|
16
16
|
const sidebars_1 = require("./sidebars");
|
|
17
17
|
// retro-compatibility: no prefix for the default plugin id
|
|
18
18
|
function addPluginIdPrefix(fileOrDir, pluginId) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
else {
|
|
23
|
-
return `${pluginId}_${fileOrDir}`;
|
|
24
|
-
}
|
|
19
|
+
return pluginId === utils_1.DEFAULT_PLUGIN_ID
|
|
20
|
+
? fileOrDir
|
|
21
|
+
: `${pluginId}_${fileOrDir}`;
|
|
25
22
|
}
|
|
26
23
|
function getVersionedDocsDirPath(siteDir, pluginId) {
|
|
27
24
|
return path_1.default.join(siteDir, addPluginIdPrefix(constants_1.VERSIONED_DOCS_DIR, pluginId));
|
|
@@ -57,9 +54,7 @@ async function readVersionsFile(siteDir, pluginId) {
|
|
|
57
54
|
ensureValidVersionArray(content);
|
|
58
55
|
return content;
|
|
59
56
|
}
|
|
60
|
-
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
57
|
+
return null;
|
|
63
58
|
}
|
|
64
59
|
async function readVersionNames(siteDir, options) {
|
|
65
60
|
const versionFileContent = await readVersionsFile(siteDir, options.id);
|
|
@@ -149,13 +144,11 @@ function getDefaultVersionBanner({ versionName, versionNames, lastVersionName, }
|
|
|
149
144
|
return null;
|
|
150
145
|
}
|
|
151
146
|
// Upcoming versions: unreleased banner
|
|
152
|
-
|
|
147
|
+
if (versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName)) {
|
|
153
148
|
return 'unreleased';
|
|
154
149
|
}
|
|
155
150
|
// Older versions: display unmaintained banner
|
|
156
|
-
|
|
157
|
-
return 'unmaintained';
|
|
158
|
-
}
|
|
151
|
+
return 'unmaintained';
|
|
159
152
|
}
|
|
160
153
|
function getVersionBanner({ versionName, versionNames, lastVersionName, options, }) {
|
|
161
154
|
var _a;
|
|
@@ -245,8 +238,9 @@ function checkVersionMetadataPaths({ versionMetadata, context, }) {
|
|
|
245
238
|
if (!fs_extra_1.default.existsSync(contentPath)) {
|
|
246
239
|
throw new Error(`The docs folder does not exist for version "${versionName}". A docs folder is expected to be found at ${path_1.default.relative(siteDir, contentPath)}.`);
|
|
247
240
|
}
|
|
248
|
-
// If the current version defines a path to a sidebar file
|
|
249
|
-
// Note: for versioned sidebars, the file may not exist (as
|
|
241
|
+
// If the current version defines a path to a sidebar file that does not
|
|
242
|
+
// exist, we throw! Note: for versioned sidebars, the file may not exist (as
|
|
243
|
+
// we prefer to not create it rather than to create an empty file)
|
|
250
244
|
// See https://github.com/facebook/docusaurus/issues/3366
|
|
251
245
|
// See https://github.com/facebook/docusaurus/pull/4775
|
|
252
246
|
if (isCurrentVersion &&
|
|
@@ -266,9 +260,7 @@ function getDefaultLastVersionName(versionNames) {
|
|
|
266
260
|
if (versionNames.length === 1) {
|
|
267
261
|
return versionNames[0];
|
|
268
262
|
}
|
|
269
|
-
|
|
270
|
-
return versionNames.filter((versionName) => versionName !== constants_1.CURRENT_VERSION_NAME)[0];
|
|
271
|
-
}
|
|
263
|
+
return versionNames.filter((versionName) => versionName !== constants_1.CURRENT_VERSION_NAME)[0];
|
|
272
264
|
}
|
|
273
265
|
function checkVersionsOptions(availableVersionNames, options) {
|
|
274
266
|
const availableVersionNamesMsg = `Available version names are: ${availableVersionNames.join(', ')}`;
|
|
@@ -303,9 +295,7 @@ function filterVersions(versionNamesUnfiltered, options) {
|
|
|
303
295
|
if (options.onlyIncludeVersions) {
|
|
304
296
|
return versionNamesUnfiltered.filter((name) => (options.onlyIncludeVersions || []).includes(name));
|
|
305
297
|
}
|
|
306
|
-
|
|
307
|
-
return versionNamesUnfiltered;
|
|
308
|
-
}
|
|
298
|
+
return versionNamesUnfiltered;
|
|
309
299
|
}
|
|
310
300
|
async function readVersionsMetadata({ context, options, }) {
|
|
311
301
|
var _a;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-docs",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-4526",
|
|
4
4
|
"description": "Docs plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
},
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@docusaurus/core": "0.0.0-
|
|
26
|
-
"@docusaurus/logger": "0.0.0-
|
|
27
|
-
"@docusaurus/mdx-loader": "0.0.0-
|
|
28
|
-
"@docusaurus/utils": "0.0.0-
|
|
29
|
-
"@docusaurus/utils-validation": "0.0.0-
|
|
25
|
+
"@docusaurus/core": "0.0.0-4526",
|
|
26
|
+
"@docusaurus/logger": "0.0.0-4526",
|
|
27
|
+
"@docusaurus/mdx-loader": "0.0.0-4526",
|
|
28
|
+
"@docusaurus/utils": "0.0.0-4526",
|
|
29
|
+
"@docusaurus/utils-validation": "0.0.0-4526",
|
|
30
30
|
"combine-promises": "^1.1.0",
|
|
31
31
|
"fs-extra": "^10.0.0",
|
|
32
32
|
"import-fresh": "^3.2.2",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"webpack": "^5.61.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@docusaurus/module-type-aliases": "0.0.0-
|
|
43
|
-
"@docusaurus/types": "0.0.0-
|
|
42
|
+
"@docusaurus/module-type-aliases": "0.0.0-4526",
|
|
43
|
+
"@docusaurus/types": "0.0.0-4526",
|
|
44
44
|
"@types/js-yaml": "^4.0.0",
|
|
45
45
|
"@types/picomatch": "^2.2.1",
|
|
46
46
|
"commander": "^5.1.0",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"engines": {
|
|
57
57
|
"node": ">=14"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "3086e9e823783e306698097d959007f44de275b1"
|
|
60
60
|
}
|
package/src/cli.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {loadSidebarsFile, resolveSidebarPathOption} from './sidebars';
|
|
|
20
20
|
import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
|
|
21
21
|
import logger from '@docusaurus/logger';
|
|
22
22
|
|
|
23
|
-
function createVersionedSidebarFile({
|
|
23
|
+
async function createVersionedSidebarFile({
|
|
24
24
|
siteDir,
|
|
25
25
|
pluginId,
|
|
26
26
|
sidebarPath,
|
|
@@ -32,10 +32,12 @@ function createVersionedSidebarFile({
|
|
|
32
32
|
version: string;
|
|
33
33
|
}) {
|
|
34
34
|
// Load current sidebar and create a new versioned sidebars file (if needed).
|
|
35
|
-
// Note: we don't need the sidebars file to be normalized: it's ok to let
|
|
36
|
-
|
|
35
|
+
// Note: we don't need the sidebars file to be normalized: it's ok to let
|
|
36
|
+
// plugin option changes to impact older, versioned sidebars
|
|
37
|
+
const sidebars = await loadSidebarsFile(sidebarPath);
|
|
37
38
|
|
|
38
|
-
// Do not create a useless versioned sidebars file if sidebars file is empty
|
|
39
|
+
// Do not create a useless versioned sidebars file if sidebars file is empty
|
|
40
|
+
// or sidebars are disabled/false)
|
|
39
41
|
const shouldCreateVersionedSidebarFile = Object.keys(sidebars).length > 0;
|
|
40
42
|
|
|
41
43
|
if (shouldCreateVersionedSidebarFile) {
|
|
@@ -54,12 +56,12 @@ function createVersionedSidebarFile({
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
// Tests depend on non-default export for mocking.
|
|
57
|
-
export function cliDocsVersionCommand(
|
|
59
|
+
export async function cliDocsVersionCommand(
|
|
58
60
|
version: string | null | undefined,
|
|
59
61
|
siteDir: string,
|
|
60
62
|
pluginId: string,
|
|
61
63
|
options: PathOptions & SidebarOptions,
|
|
62
|
-
): void {
|
|
64
|
+
): Promise<void> {
|
|
63
65
|
// It wouldn't be very user-friendly to show a [default] log prefix,
|
|
64
66
|
// so we use [docs] instead of [default]
|
|
65
67
|
const pluginIdLogPrefix =
|
|
@@ -125,7 +127,7 @@ export function cliDocsVersionCommand(
|
|
|
125
127
|
throw new Error(`${pluginIdLogPrefix}: there is no docs to version!`);
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
createVersionedSidebarFile({
|
|
130
|
+
await createVersionedSidebarFile({
|
|
129
131
|
siteDir,
|
|
130
132
|
pluginId,
|
|
131
133
|
version,
|
|
@@ -28,7 +28,7 @@ export function getActivePlugin(
|
|
|
28
28
|
options: GetActivePluginOptions = {},
|
|
29
29
|
): ActivePlugin | undefined {
|
|
30
30
|
const activeEntry = Object.entries(allPluginDatas)
|
|
31
|
-
//
|
|
31
|
+
// Route sorting: '/android/foo' should match '/android' instead of '/'
|
|
32
32
|
.sort((a, b) => b[1].path.localeCompare(a[1].path))
|
|
33
33
|
.find(
|
|
34
34
|
([, pluginData]) =>
|
|
@@ -67,7 +67,7 @@ export const getActiveVersion = (
|
|
|
67
67
|
): GlobalVersion | undefined => {
|
|
68
68
|
const lastVersion = getLatestVersion(data);
|
|
69
69
|
// Last version is a route like /docs/*,
|
|
70
|
-
// we need to
|
|
70
|
+
// we need to match it last or it would match /docs/version-1.0/* as well
|
|
71
71
|
const orderedVersionsMetadata = [
|
|
72
72
|
...data.versions.filter((version) => version !== lastVersion),
|
|
73
73
|
lastVersion,
|
|
@@ -27,12 +27,13 @@ import type {
|
|
|
27
27
|
GetActivePluginOptions,
|
|
28
28
|
} from '@docusaurus/plugin-content-docs/client';
|
|
29
29
|
|
|
30
|
-
// Important to use a constant object to avoid React useEffect executions etc
|
|
30
|
+
// Important to use a constant object to avoid React useEffect executions etc.
|
|
31
31
|
// see https://github.com/facebook/docusaurus/issues/5089
|
|
32
32
|
const StableEmptyObject = {};
|
|
33
33
|
|
|
34
|
-
// Not using useAllPluginInstancesData() because in blog-only mode, docs hooks
|
|
35
|
-
// We need a fail-safe fallback when the docs
|
|
34
|
+
// Not using useAllPluginInstancesData() because in blog-only mode, docs hooks
|
|
35
|
+
// are still used by the theme. We need a fail-safe fallback when the docs
|
|
36
|
+
// plugin is not in use
|
|
36
37
|
export const useAllDocsData = (): Record<string, GlobalPluginData> =>
|
|
37
38
|
// useAllPluginInstancesData('docusaurus-plugin-content-docs');
|
|
38
39
|
useGlobalData()['docusaurus-plugin-content-docs'] ?? StableEmptyObject;
|
package/src/docs.ts
CHANGED
|
@@ -139,7 +139,8 @@ function doProcessDocMetadata({
|
|
|
139
139
|
const {
|
|
140
140
|
custom_edit_url: customEditURL,
|
|
141
141
|
|
|
142
|
-
// Strip number prefixes by default
|
|
142
|
+
// Strip number prefixes by default
|
|
143
|
+
// (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
|
|
143
144
|
// but allow to disable this behavior with front matter
|
|
144
145
|
parse_number_prefixes: parseNumberPrefixes = true,
|
|
145
146
|
} = frontMatter;
|
|
@@ -164,7 +165,8 @@ function doProcessDocMetadata({
|
|
|
164
165
|
throw new Error(`Document id "${baseID}" cannot include slash.`);
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
// For autogenerated sidebars, sidebar position can come from filename number
|
|
168
|
+
// For autogenerated sidebars, sidebar position can come from filename number
|
|
169
|
+
// prefix or front matter
|
|
168
170
|
const sidebarPosition: number | undefined =
|
|
169
171
|
frontMatter.sidebar_position ?? numberPrefix;
|
|
170
172
|
|
|
@@ -205,8 +207,9 @@ function doProcessDocMetadata({
|
|
|
205
207
|
numberPrefixParser: options.numberPrefixParser,
|
|
206
208
|
});
|
|
207
209
|
|
|
208
|
-
// Note: the title is used by default for page title, sidebar label,
|
|
209
|
-
// frontMatter.title should be used in priority over
|
|
210
|
+
// Note: the title is used by default for page title, sidebar label,
|
|
211
|
+
// pagination buttons... frontMatter.title should be used in priority over
|
|
212
|
+
// contentTitle (because it can contain markdown/JSX syntax)
|
|
210
213
|
const title: string = frontMatter.title ?? contentTitle ?? baseID;
|
|
211
214
|
|
|
212
215
|
const description: string = frontMatter.description ?? excerpt ?? '';
|
|
@@ -233,9 +236,8 @@ function doProcessDocMetadata({
|
|
|
233
236
|
? versionMetadata.versionEditUrlLocalized
|
|
234
237
|
: versionMetadata.versionEditUrl;
|
|
235
238
|
return getEditUrl(relativeFilePath, baseVersionEditUrl);
|
|
236
|
-
} else {
|
|
237
|
-
return undefined;
|
|
238
239
|
}
|
|
240
|
+
return undefined;
|
|
239
241
|
}
|
|
240
242
|
|
|
241
243
|
// Assign all of object properties during instantiation (if possible) for
|
|
@@ -361,9 +363,8 @@ export function getMainDocId({
|
|
|
361
363
|
doc.id === firstDocIdOfFirstSidebar ||
|
|
362
364
|
doc.unversionedId === firstDocIdOfFirstSidebar,
|
|
363
365
|
)!;
|
|
364
|
-
} else {
|
|
365
|
-
return docs[0];
|
|
366
366
|
}
|
|
367
|
+
return docs[0];
|
|
367
368
|
}
|
|
368
369
|
|
|
369
370
|
return getMainDoc().unversionedId;
|
|
@@ -407,7 +408,8 @@ export function toCategoryIndexMatcherParam({
|
|
|
407
408
|
}
|
|
408
409
|
|
|
409
410
|
/**
|
|
410
|
-
* guides/sidebar/autogenerated.md ->
|
|
411
|
+
* `guides/sidebar/autogenerated.md` ->
|
|
412
|
+
* `'autogenerated', '.md', ['sidebar', 'guides']`
|
|
411
413
|
*/
|
|
412
414
|
export function splitPath(str: string): {
|
|
413
415
|
/**
|
|
@@ -428,15 +430,17 @@ export function splitPath(str: string): {
|
|
|
428
430
|
}
|
|
429
431
|
|
|
430
432
|
// Return both doc ids
|
|
431
|
-
// TODO legacy retro-compatibility due to old versioned sidebars using
|
|
432
|
-
// ("id" should be removed & "versionedId" should be renamed
|
|
433
|
+
// TODO legacy retro-compatibility due to old versioned sidebars using
|
|
434
|
+
// versioned doc ids ("id" should be removed & "versionedId" should be renamed
|
|
435
|
+
// to "id")
|
|
433
436
|
export function getDocIds(doc: DocMetadataBase): [string, string] {
|
|
434
437
|
return [doc.unversionedId, doc.id];
|
|
435
438
|
}
|
|
436
439
|
|
|
437
440
|
// docs are indexed by both versioned and unversioned ids at the same time
|
|
438
|
-
// TODO legacy retro-compatibility due to old versioned sidebars using
|
|
439
|
-
// ("id" should be removed & "versionedId" should be renamed
|
|
441
|
+
// TODO legacy retro-compatibility due to old versioned sidebars using
|
|
442
|
+
// versioned doc ids ("id" should be removed & "versionedId" should be renamed
|
|
443
|
+
// to "id")
|
|
440
444
|
export function createDocsByIdIndex<
|
|
441
445
|
Doc extends {id: string; unversionedId: string},
|
|
442
446
|
>(docs: Doc[]): Record<string, Doc> {
|
package/src/index.ts
CHANGED
|
@@ -333,7 +333,7 @@ export default async function pluginContentDocs(
|
|
|
333
333
|
function createMDXLoaderRule(): RuleSetRule {
|
|
334
334
|
const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
|
|
335
335
|
return {
|
|
336
|
-
test:
|
|
336
|
+
test: /\.mdx?$/i,
|
|
337
337
|
include: contentDirs
|
|
338
338
|
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
339
339
|
.map(addTrailingPathSeparator),
|
package/src/lastUpdate.ts
CHANGED
|
@@ -10,7 +10,7 @@ import logger from '@docusaurus/logger';
|
|
|
10
10
|
|
|
11
11
|
type FileLastUpdateData = {timestamp?: number; author?: string};
|
|
12
12
|
|
|
13
|
-
const GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX = /^(
|
|
13
|
+
const GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX = /^(?<timestamp>\d+),(?<author>.+)$/;
|
|
14
14
|
|
|
15
15
|
let showedGitRequirementError = false;
|
|
16
16
|
|
|
@@ -25,10 +25,10 @@ export async function getFileLastUpdate(
|
|
|
25
25
|
return null;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const temp = str.match(GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX);
|
|
29
|
-
return
|
|
30
|
-
?
|
|
31
|
-
:
|
|
28
|
+
const temp = str.match(GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX)?.groups;
|
|
29
|
+
return temp
|
|
30
|
+
? {timestamp: Number(temp.timestamp), author: temp.author}
|
|
31
|
+
: null;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Wrap in try/catch in case the shell commands fail
|
package/src/numberPrefix.ts
CHANGED
|
@@ -8,16 +8,17 @@
|
|
|
8
8
|
import type {NumberPrefixParser} from '@docusaurus/plugin-content-docs';
|
|
9
9
|
|
|
10
10
|
// Best-effort to avoid parsing some patterns as number prefix
|
|
11
|
-
const IgnoredPrefixPatterns = (
|
|
11
|
+
const IgnoredPrefixPatterns = (() => {
|
|
12
12
|
// ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
|
|
13
13
|
const DateLikePrefixRegex =
|
|
14
|
-
/^(
|
|
14
|
+
/^(?:\d{2}|\d{4})[-_.]\d{2}(?:[-_.](?:\d{2}|\d{4}))?.*$/;
|
|
15
15
|
|
|
16
16
|
// ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
|
|
17
|
-
// note: we could try to parse float numbers in filenames but that is
|
|
18
|
-
// as a version such as "8.0" can be interpreted as both
|
|
19
|
-
// User can configure
|
|
20
|
-
|
|
17
|
+
// note: we could try to parse float numbers in filenames but that is
|
|
18
|
+
// probably not worth it as a version such as "8.0" can be interpreted as both
|
|
19
|
+
// a version and a float. User can configure her own NumberPrefixParser if
|
|
20
|
+
// she wants 8.0 to be interpreted as a float
|
|
21
|
+
const VersionLikePrefixRegex = /^\d+[-_.]\d+.*$/;
|
|
21
22
|
|
|
22
23
|
return new RegExp(
|
|
23
24
|
`${DateLikePrefixRegex.source}|${VersionLikePrefixRegex.source}`,
|
package/src/options.ts
CHANGED
|
@@ -148,8 +148,9 @@ export function validateOptions({
|
|
|
148
148
|
let options = userOptions;
|
|
149
149
|
|
|
150
150
|
if (options.sidebarCollapsible === false) {
|
|
151
|
-
// When sidebarCollapsible=false and sidebarCollapsed=undefined, we don't
|
|
152
|
-
//
|
|
151
|
+
// When sidebarCollapsible=false and sidebarCollapsed=undefined, we don't
|
|
152
|
+
// want to have the inconsistency warning. We let options.sidebarCollapsible
|
|
153
|
+
// become the default value for options.sidebarCollapsed
|
|
153
154
|
if (typeof options.sidebarCollapsed === 'undefined') {
|
|
154
155
|
options = {
|
|
155
156
|
...options,
|
|
@@ -45,7 +45,8 @@ declare module '@docusaurus/plugin-content-docs' {
|
|
|
45
45
|
sidebarPath?: string | false | undefined;
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
// TODO support custom version banner?
|
|
48
|
+
// TODO support custom version banner?
|
|
49
|
+
// {type: "error", content: "html content"}
|
|
49
50
|
export type VersionBanner = 'unreleased' | 'unmaintained';
|
|
50
51
|
export type VersionOptions = {
|
|
51
52
|
path?: string;
|
package/src/routes.ts
CHANGED
|
@@ -73,7 +73,8 @@ export async function createCategoryGeneratedIndexRoutes({
|
|
|
73
73
|
modules: {
|
|
74
74
|
categoryGeneratedIndex: aliasedSource(propData),
|
|
75
75
|
},
|
|
76
|
-
// Same as doc, this sidebar route attribute permits to associate this
|
|
76
|
+
// Same as doc, this sidebar route attribute permits to associate this
|
|
77
|
+
// subpage to the given sidebar
|
|
77
78
|
...(sidebar && {sidebar}),
|
|
78
79
|
};
|
|
79
80
|
}
|
|
@@ -109,7 +110,8 @@ export async function createDocRoutes({
|
|
|
109
110
|
content: metadataItem.source,
|
|
110
111
|
},
|
|
111
112
|
// Because the parent (DocPage) comp need to access it easily
|
|
112
|
-
// This permits to render the sidebar once without unmount/remount when
|
|
113
|
+
// This permits to render the sidebar once without unmount/remount when
|
|
114
|
+
// navigating (and preserve sidebar state)
|
|
113
115
|
...(metadataItem.sidebar && {
|
|
114
116
|
sidebar: metadataItem.sidebar,
|
|
115
117
|
}),
|
|
@@ -47,7 +47,8 @@ export type CategoryMetadataFile = {
|
|
|
47
47
|
className?: string;
|
|
48
48
|
link?: SidebarItemCategoryLinkConfig | null;
|
|
49
49
|
|
|
50
|
-
// TODO should we allow "items" here? how would this work? would an
|
|
50
|
+
// TODO should we allow "items" here? how would this work? would an
|
|
51
|
+
// "autogenerated" type be allowed?
|
|
51
52
|
// This mkdocs plugin do something like that: https://github.com/lukasgeiter/mkdocs-awesome-pages-plugin/
|
|
52
53
|
// cf comment: https://github.com/facebook/docusaurus/issues/3464#issuecomment-784765199
|
|
53
54
|
};
|
|
@@ -56,16 +57,20 @@ type WithPosition<T> = T & {position?: number};
|
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
* A representation of the fs structure. For each object entry:
|
|
59
|
-
* If it's a folder, the key is the directory name, and value is the directory
|
|
60
|
-
* If it's a doc file, the key is the doc id prefixed with '$doc$/',
|
|
60
|
+
* If it's a folder, the key is the directory name, and value is the directory
|
|
61
|
+
* content; If it's a doc file, the key is the doc id prefixed with '$doc$/',
|
|
62
|
+
* and value is null
|
|
61
63
|
*/
|
|
62
64
|
type Dir = {
|
|
63
65
|
[item: string]: Dir | null;
|
|
64
66
|
};
|
|
65
67
|
|
|
66
|
-
// TODO I now believe we should read all the category metadata files ahead of
|
|
67
|
-
//
|
|
68
|
-
//
|
|
68
|
+
// TODO I now believe we should read all the category metadata files ahead of
|
|
69
|
+
// time: we may need this metadata to customize docs metadata
|
|
70
|
+
// Example use-case being able to disable number prefix parsing at the folder
|
|
71
|
+
// level, or customize the default base slug for an intermediate directory
|
|
72
|
+
// TODO later if there is `CategoryFolder/with-category-name-doc.md`, we may
|
|
73
|
+
// want to read the metadata as yaml on it
|
|
69
74
|
// see https://github.com/facebook/docusaurus/issues/3464#issuecomment-818670449
|
|
70
75
|
async function readCategoryMetadataFile(
|
|
71
76
|
categoryDirPath: string,
|
|
@@ -142,7 +147,8 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
142
147
|
* Step 2. Turn the linear file list into a tree structure.
|
|
143
148
|
*/
|
|
144
149
|
function treeify(docs: SidebarItemsGeneratorDoc[]): Dir {
|
|
145
|
-
// Get the category breadcrumb of a doc (relative to the dir of the
|
|
150
|
+
// Get the category breadcrumb of a doc (relative to the dir of the
|
|
151
|
+
// autogenerated sidebar item)
|
|
146
152
|
// autogenDir=a/b and docDir=a/b/c/d => returns [c, d]
|
|
147
153
|
// autogenDir=a/b and docDir=a/b => returns []
|
|
148
154
|
// TODO: try to use path.relative()
|
|
@@ -169,7 +175,7 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
169
175
|
}
|
|
170
176
|
|
|
171
177
|
/**
|
|
172
|
-
* Step 3. Recursively transform the tree-like
|
|
178
|
+
* Step 3. Recursively transform the tree-like structure to sidebar items.
|
|
173
179
|
* (From a record to an array of items, akin to normalizing shorthand)
|
|
174
180
|
*/
|
|
175
181
|
function generateSidebar(fsModel: Dir): Promise<WithPosition<SidebarItem>[]> {
|
|
@@ -182,7 +188,8 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
182
188
|
type: 'doc',
|
|
183
189
|
id,
|
|
184
190
|
position,
|
|
185
|
-
// We don't want these fields to magically appear in the generated
|
|
191
|
+
// We don't want these fields to magically appear in the generated
|
|
192
|
+
// sidebar
|
|
186
193
|
...(label !== undefined && {label}),
|
|
187
194
|
...(className !== undefined && {className}),
|
|
188
195
|
};
|
|
@@ -225,13 +232,12 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
225
232
|
if (link !== undefined) {
|
|
226
233
|
if (link && link.type === 'doc') {
|
|
227
234
|
return findDocByLocalId(link.id)?.id || getDoc(link.id).id;
|
|
228
|
-
} else {
|
|
229
|
-
// We don't continue for other link types on purpose!
|
|
230
|
-
// IE if user decide to use type "generated-index", we should not pick a README.md file as the linked doc
|
|
231
|
-
return undefined;
|
|
232
235
|
}
|
|
236
|
+
// If a link is explicitly specified, we won't apply conventions
|
|
237
|
+
return undefined;
|
|
233
238
|
}
|
|
234
|
-
// Apply default convention to pick index.md, README.md or
|
|
239
|
+
// Apply default convention to pick index.md, README.md or
|
|
240
|
+
// <categoryName>.md as the category doc
|
|
235
241
|
return findConventionalCategoryDocLink()?.id;
|
|
236
242
|
}
|
|
237
243
|
|
|
@@ -279,10 +285,11 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
279
285
|
}
|
|
280
286
|
|
|
281
287
|
/**
|
|
282
|
-
* Step 4. Recursively sort the categories/docs + remove the "position"
|
|
283
|
-
* Note: the "position" is only used to sort
|
|
284
|
-
*
|
|
285
|
-
* composed of multiple
|
|
288
|
+
* Step 4. Recursively sort the categories/docs + remove the "position"
|
|
289
|
+
* attribute from final output. Note: the "position" is only used to sort
|
|
290
|
+
* "inside" a sidebar slice. It is not used to sort across multiple
|
|
291
|
+
* consecutive sidebar slices (i.e. a whole category composed of multiple
|
|
292
|
+
* autogenerated items)
|
|
286
293
|
*/
|
|
287
294
|
function sortItems(sidebarItems: WithPosition<SidebarItem>[]): SidebarItem[] {
|
|
288
295
|
const processedSidebarItems = sidebarItems.map((item) => {
|
|
@@ -298,7 +305,6 @@ export const DefaultSidebarItemsGenerator: SidebarItemsGenerator = async ({
|
|
|
298
305
|
return sortedSidebarItems.map(({position, ...item}) => item);
|
|
299
306
|
}
|
|
300
307
|
// TODO: the whole code is designed for pipeline operator
|
|
301
|
-
// return getAutogenDocs() |> treeify |> await generateSidebar(^) |> sortItems;
|
|
302
308
|
const docs = getAutogenDocs();
|
|
303
309
|
const fsModel = treeify(docs);
|
|
304
310
|
const sidebarWithPosition = await generateSidebar(fsModel);
|
package/src/sidebars/index.ts
CHANGED
|
@@ -38,9 +38,9 @@ export function resolveSidebarPathOption(
|
|
|
38
38
|
: sidebarPathOption;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function loadSidebarsFileUnsafe(
|
|
41
|
+
async function loadSidebarsFileUnsafe(
|
|
42
42
|
sidebarFilePath: string | false | undefined,
|
|
43
|
-
): SidebarsConfig {
|
|
43
|
+
): Promise<SidebarsConfig> {
|
|
44
44
|
// false => no sidebars
|
|
45
45
|
if (sidebarFilePath === false) {
|
|
46
46
|
return DisabledSidebars;
|
|
@@ -62,19 +62,19 @@ function loadSidebarsFileUnsafe(
|
|
|
62
62
|
return importFresh(sidebarFilePath);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
export function loadSidebarsFile(
|
|
65
|
+
export async function loadSidebarsFile(
|
|
66
66
|
sidebarFilePath: string | false | undefined,
|
|
67
|
-
): SidebarsConfig {
|
|
68
|
-
const sidebarsConfig = loadSidebarsFileUnsafe(sidebarFilePath);
|
|
67
|
+
): Promise<SidebarsConfig> {
|
|
68
|
+
const sidebarsConfig = await loadSidebarsFileUnsafe(sidebarFilePath);
|
|
69
69
|
validateSidebars(sidebarsConfig);
|
|
70
70
|
return sidebarsConfig;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export function loadNormalizedSidebars(
|
|
73
|
+
export async function loadNormalizedSidebars(
|
|
74
74
|
sidebarFilePath: string | false | undefined,
|
|
75
75
|
params: NormalizeSidebarsParams,
|
|
76
|
-
): NormalizedSidebars {
|
|
77
|
-
return normalizeSidebars(loadSidebarsFile(sidebarFilePath), params);
|
|
76
|
+
): Promise<NormalizedSidebars> {
|
|
77
|
+
return normalizeSidebars(await loadSidebarsFile(sidebarFilePath), params);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Note: sidebarFilePath must be absolute, use resolveSidebarPathOption
|
|
@@ -87,7 +87,7 @@ export async function loadSidebars(
|
|
|
87
87
|
version: options.version,
|
|
88
88
|
categoryLabelSlugger: createSlugger(),
|
|
89
89
|
};
|
|
90
|
-
const normalizedSidebars = loadNormalizedSidebars(
|
|
90
|
+
const normalizedSidebars = await loadNormalizedSidebars(
|
|
91
91
|
sidebarFilePath,
|
|
92
92
|
normalizeSidebarsParams,
|
|
93
93
|
);
|
|
@@ -60,7 +60,8 @@ function toSidebarItemsGeneratorVersion(
|
|
|
60
60
|
return pick(version, ['versionName', 'contentPath']);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// Handle the generation of autogenerated sidebar items and other
|
|
63
|
+
// Handle the generation of autogenerated sidebar items and other
|
|
64
|
+
// post-processing checks
|
|
64
65
|
async function processSidebar(
|
|
65
66
|
unprocessedSidebar: NormalizedSidebar,
|
|
66
67
|
params: SidebarProcessorParams,
|
|
@@ -91,7 +92,8 @@ async function processSidebar(
|
|
|
91
92
|
async function processAutoGeneratedItem(
|
|
92
93
|
item: SidebarItemAutogenerated,
|
|
93
94
|
): Promise<SidebarItem[]> {
|
|
94
|
-
// TODO the returned type can't be trusted in practice (generator can be
|
|
95
|
+
// TODO the returned type can't be trusted in practice (generator can be
|
|
96
|
+
// user-provided)
|
|
95
97
|
const generatedItems = await sidebarItemsGenerator({
|
|
96
98
|
item,
|
|
97
99
|
numberPrefixParser,
|
|
@@ -106,7 +108,8 @@ async function processSidebar(
|
|
|
106
108
|
normalizeItem(generatedItem, {...params, ...sidebarOptions}),
|
|
107
109
|
);
|
|
108
110
|
|
|
109
|
-
// Process again... weird but sidebar item generated might generate some
|
|
111
|
+
// Process again... weird but sidebar item generated might generate some
|
|
112
|
+
// auto-generated items?
|
|
110
113
|
return processItems(generatedItemsNormalized);
|
|
111
114
|
}
|
|
112
115
|
|
package/src/sidebars/types.ts
CHANGED
|
@@ -205,7 +205,8 @@ export type SidebarItemsGenerator = (
|
|
|
205
205
|
Promise<SidebarItem[]>;
|
|
206
206
|
// Promise<SidebarItemConfig[]>;
|
|
207
207
|
|
|
208
|
-
// Also inject the default generator to conveniently wrap/enhance/sort the
|
|
208
|
+
// Also inject the default generator to conveniently wrap/enhance/sort the
|
|
209
|
+
// default sidebar gen logic
|
|
209
210
|
// see https://github.com/facebook/docusaurus/issues/4640#issuecomment-822292320
|
|
210
211
|
export type SidebarItemsGeneratorOptionArgs = {
|
|
211
212
|
defaultSidebarItemsGenerator: SidebarItemsGenerator;
|