@docusaurus/plugin-content-docs 0.0.0-4847 → 0.0.0-4850
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 +14 -26
- package/lib/constants.d.ts +4 -0
- package/lib/constants.js +4 -1
- package/lib/index.js +2 -0
- package/lib/server-export.d.ts +2 -1
- package/lib/server-export.js +3 -4
- package/lib/sidebars/index.js +0 -2
- 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 +10 -10
- package/src/cli.ts +15 -48
- package/src/constants.ts +4 -2
- package/src/index.ts +3 -1
- package/src/server-export.ts +1 -3
- package/src/sidebars/index.ts +0 -2
- 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 -45
- package/lib/versions.js +0 -314
- package/src/versions.ts +0 -593
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-4850",
|
|
4
4
|
"description": "Docs plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
},
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@docusaurus/core": "0.0.0-
|
|
28
|
-
"@docusaurus/logger": "0.0.0-
|
|
29
|
-
"@docusaurus/mdx-loader": "0.0.0-
|
|
30
|
-
"@docusaurus/utils": "0.0.0-
|
|
31
|
-
"@docusaurus/utils-validation": "0.0.0-
|
|
27
|
+
"@docusaurus/core": "0.0.0-4850",
|
|
28
|
+
"@docusaurus/logger": "0.0.0-4850",
|
|
29
|
+
"@docusaurus/mdx-loader": "0.0.0-4850",
|
|
30
|
+
"@docusaurus/utils": "0.0.0-4850",
|
|
31
|
+
"@docusaurus/utils-validation": "0.0.0-4850",
|
|
32
32
|
"combine-promises": "^1.1.0",
|
|
33
33
|
"fs-extra": "^10.0.1",
|
|
34
34
|
"import-fresh": "^3.3.0",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"remark-admonitions": "^1.2.1",
|
|
38
38
|
"tslib": "^2.3.1",
|
|
39
39
|
"utility-types": "^3.10.0",
|
|
40
|
-
"webpack": "^5.
|
|
40
|
+
"webpack": "^5.72.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@docusaurus/module-type-aliases": "0.0.0-
|
|
44
|
-
"@docusaurus/types": "0.0.0-
|
|
43
|
+
"@docusaurus/module-type-aliases": "0.0.0-4850",
|
|
44
|
+
"@docusaurus/types": "0.0.0-4850",
|
|
45
45
|
"@types/js-yaml": "^4.0.5",
|
|
46
46
|
"@types/picomatch": "^2.3.0",
|
|
47
47
|
"commander": "^5.1.0",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=14"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "fdcbca6d6e4861538bfdbb590b770ca0238632ab"
|
|
61
61
|
}
|
package/src/cli.ts
CHANGED
|
@@ -7,14 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
getVersionsFilePath,
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
getVersionDocsDirPath,
|
|
11
|
+
getVersionSidebarsPath,
|
|
12
12
|
getDocsDirPathLocalized,
|
|
13
|
-
} from './versions';
|
|
13
|
+
} from './versions/files';
|
|
14
|
+
import {validateVersionName} from './versions/validation';
|
|
14
15
|
import fs from 'fs-extra';
|
|
15
16
|
import path from 'path';
|
|
16
17
|
import type {PluginOptions} from '@docusaurus/plugin-content-docs';
|
|
17
|
-
import {loadSidebarsFileUnsafe
|
|
18
|
+
import {loadSidebarsFileUnsafe} from './sidebars';
|
|
18
19
|
import {CURRENT_VERSION_NAME} from './constants';
|
|
19
20
|
import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
|
|
20
21
|
import logger from '@docusaurus/logger';
|
|
@@ -42,13 +43,8 @@ async function createVersionedSidebarFile({
|
|
|
42
43
|
const shouldCreateVersionedSidebarFile = Object.keys(sidebars).length > 0;
|
|
43
44
|
|
|
44
45
|
if (shouldCreateVersionedSidebarFile) {
|
|
45
|
-
const versionedSidebarsDir = getVersionedSidebarsDirPath(siteDir, pluginId);
|
|
46
|
-
const newSidebarFile = path.join(
|
|
47
|
-
versionedSidebarsDir,
|
|
48
|
-
`version-${version}-sidebars.json`,
|
|
49
|
-
);
|
|
50
46
|
await fs.outputFile(
|
|
51
|
-
|
|
47
|
+
getVersionSidebarsPath(siteDir, pluginId, version),
|
|
52
48
|
`${JSON.stringify(sidebars, null, 2)}\n`,
|
|
53
49
|
'utf8',
|
|
54
50
|
);
|
|
@@ -57,7 +53,7 @@ async function createVersionedSidebarFile({
|
|
|
57
53
|
|
|
58
54
|
// Tests depend on non-default export for mocking.
|
|
59
55
|
export async function cliDocsVersionCommand(
|
|
60
|
-
version: string
|
|
56
|
+
version: string,
|
|
61
57
|
{id: pluginId, path: docsPath, sidebarPath}: PluginOptions,
|
|
62
58
|
{siteDir, i18n}: LoadContext,
|
|
63
59
|
): Promise<void> {
|
|
@@ -66,44 +62,18 @@ export async function cliDocsVersionCommand(
|
|
|
66
62
|
const pluginIdLogPrefix =
|
|
67
63
|
pluginId === DEFAULT_PLUGIN_ID ? '[docs]' : `[${pluginId}]`;
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (version.includes('/') || version.includes('\\')) {
|
|
76
|
-
throw new Error(
|
|
77
|
-
`${pluginIdLogPrefix}: invalid version tag specified! Do not include slash (/) or backslash (\\). Try something like: 1.0.0.`,
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (version.length > 32) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
`${pluginIdLogPrefix}: invalid version tag specified! Length cannot exceed 32 characters. Try something like: 1.0.0.`,
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Since we are going to create `version-${version}` folder, we need to make
|
|
88
|
-
// sure it's a valid pathname.
|
|
89
|
-
// eslint-disable-next-line no-control-regex
|
|
90
|
-
if (/[<>:"|?*\x00-\x1F]/.test(version)) {
|
|
91
|
-
throw new Error(
|
|
92
|
-
`${pluginIdLogPrefix}: invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0.`,
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (/^\.\.?$/.test(version)) {
|
|
97
|
-
throw new Error(
|
|
98
|
-
`${pluginIdLogPrefix}: invalid version tag specified! Do not name your version "." or "..". Try something like: 1.0.0.`,
|
|
99
|
-
);
|
|
65
|
+
try {
|
|
66
|
+
validateVersionName(version);
|
|
67
|
+
} catch (e) {
|
|
68
|
+
logger.info`${pluginIdLogPrefix}: Invalid version name provided. Try something like: 1.0.0`;
|
|
69
|
+
throw e;
|
|
100
70
|
}
|
|
101
71
|
|
|
102
72
|
// Load existing versions.
|
|
103
73
|
let versions = [];
|
|
104
74
|
const versionsJSONFile = getVersionsFilePath(siteDir, pluginId);
|
|
105
75
|
if (await fs.pathExists(versionsJSONFile)) {
|
|
106
|
-
versions =
|
|
76
|
+
versions = await fs.readJSON(versionsJSONFile);
|
|
107
77
|
}
|
|
108
78
|
|
|
109
79
|
// Check if version already exists.
|
|
@@ -146,10 +116,7 @@ export async function cliDocsVersionCommand(
|
|
|
146
116
|
|
|
147
117
|
const newVersionDir =
|
|
148
118
|
locale === i18n.defaultLocale
|
|
149
|
-
?
|
|
150
|
-
getVersionedDocsDirPath(siteDir, pluginId),
|
|
151
|
-
`version-${version}`,
|
|
152
|
-
)
|
|
119
|
+
? getVersionDocsDirPath(siteDir, pluginId, version)
|
|
153
120
|
: getDocsDirPathLocalized({
|
|
154
121
|
siteDir,
|
|
155
122
|
locale,
|
|
@@ -164,7 +131,7 @@ export async function cliDocsVersionCommand(
|
|
|
164
131
|
siteDir,
|
|
165
132
|
pluginId,
|
|
166
133
|
version,
|
|
167
|
-
sidebarPath
|
|
134
|
+
sidebarPath,
|
|
168
135
|
});
|
|
169
136
|
|
|
170
137
|
// Update versions.json file.
|
package/src/constants.ts
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
/** The name of the version that's actively worked on (e.g. `website/docs`) */
|
|
9
9
|
export const CURRENT_VERSION_NAME = 'current';
|
|
10
|
-
|
|
10
|
+
/** All doc versions are stored here by version names */
|
|
11
11
|
export const VERSIONED_DOCS_DIR = 'versioned_docs';
|
|
12
|
+
/** All doc versioned sidebars are stored here by version names */
|
|
12
13
|
export const VERSIONED_SIDEBARS_DIR = 'versioned_sidebars';
|
|
14
|
+
/** The version names. Should 1-1 map to the content of versioned docs dir. */
|
|
13
15
|
export const VERSIONS_JSON_FILE = 'versions.json';
|
package/src/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
DEFAULT_PLUGIN_ID,
|
|
21
21
|
} from '@docusaurus/utils';
|
|
22
22
|
import type {LoadContext, Plugin} from '@docusaurus/types';
|
|
23
|
-
import {loadSidebars} from './sidebars';
|
|
23
|
+
import {loadSidebars, resolveSidebarPathOption} from './sidebars';
|
|
24
24
|
import {CategoryMetadataFilenamePattern} from './sidebars/generator';
|
|
25
25
|
import {
|
|
26
26
|
readVersionDocs,
|
|
@@ -64,6 +64,8 @@ export default async function pluginContentDocs(
|
|
|
64
64
|
options: PluginOptions,
|
|
65
65
|
): Promise<Plugin<LoadedContent>> {
|
|
66
66
|
const {siteDir, generatedFilesDir, baseUrl, siteConfig} = context;
|
|
67
|
+
// Mutate options to resolve sidebar path according to siteDir
|
|
68
|
+
options.sidebarPath = resolveSidebarPathOption(siteDir, options.sidebarPath);
|
|
67
69
|
|
|
68
70
|
const versionsMetadata = await readVersionsMetadata({context, options});
|
|
69
71
|
|
package/src/server-export.ts
CHANGED
package/src/sidebars/index.ts
CHANGED
|
@@ -32,7 +32,6 @@ export const DefaultSidebars: SidebarsConfig = {
|
|
|
32
32
|
export const DisabledSidebars: SidebarsConfig = {};
|
|
33
33
|
|
|
34
34
|
// If a path is provided, make it absolute
|
|
35
|
-
// use this before loadSidebars()
|
|
36
35
|
export function resolveSidebarPathOption(
|
|
37
36
|
siteDir: string,
|
|
38
37
|
sidebarPathOption: PluginOptions['sidebarPath'],
|
|
@@ -93,7 +92,6 @@ export async function loadSidebarsFileUnsafe(
|
|
|
93
92
|
return importFresh(sidebarFilePath);
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
// Note: sidebarFilePath must be absolute, use resolveSidebarPathOption
|
|
97
95
|
export async function loadSidebars(
|
|
98
96
|
sidebarFilePath: string | false | undefined,
|
|
99
97
|
options: SidebarProcessorParams,
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import fs from 'fs-extra';
|
|
10
|
+
import {
|
|
11
|
+
VERSIONS_JSON_FILE,
|
|
12
|
+
VERSIONED_DOCS_DIR,
|
|
13
|
+
VERSIONED_SIDEBARS_DIR,
|
|
14
|
+
CURRENT_VERSION_NAME,
|
|
15
|
+
} from '../constants';
|
|
16
|
+
import {validateVersionNames} from './validation';
|
|
17
|
+
import {getPluginI18nPath, DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
|
|
18
|
+
import type {
|
|
19
|
+
PluginOptions,
|
|
20
|
+
VersionMetadata,
|
|
21
|
+
} from '@docusaurus/plugin-content-docs';
|
|
22
|
+
import type {VersionContext} from './index';
|
|
23
|
+
|
|
24
|
+
/** Add a prefix like `community_version-1.0.0`. No-op for default instance. */
|
|
25
|
+
function addPluginIdPrefix(fileOrDir: string, pluginId: string): string {
|
|
26
|
+
return pluginId === DEFAULT_PLUGIN_ID
|
|
27
|
+
? fileOrDir
|
|
28
|
+
: `${pluginId}_${fileOrDir}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** `[siteDir]/community_versioned_docs/version-1.0.0` */
|
|
32
|
+
export function getVersionDocsDirPath(
|
|
33
|
+
siteDir: string,
|
|
34
|
+
pluginId: string,
|
|
35
|
+
versionName: string,
|
|
36
|
+
): string {
|
|
37
|
+
return path.join(
|
|
38
|
+
siteDir,
|
|
39
|
+
addPluginIdPrefix(VERSIONED_DOCS_DIR, pluginId),
|
|
40
|
+
`version-${versionName}`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** `[siteDir]/community_versioned_sidebars/version-1.0.0-sidebars.json` */
|
|
45
|
+
export function getVersionSidebarsPath(
|
|
46
|
+
siteDir: string,
|
|
47
|
+
pluginId: string,
|
|
48
|
+
versionName: string,
|
|
49
|
+
): string {
|
|
50
|
+
return path.join(
|
|
51
|
+
siteDir,
|
|
52
|
+
addPluginIdPrefix(VERSIONED_SIDEBARS_DIR, pluginId),
|
|
53
|
+
`version-${versionName}-sidebars.json`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function getDocsDirPathLocalized({
|
|
58
|
+
siteDir,
|
|
59
|
+
locale,
|
|
60
|
+
pluginId,
|
|
61
|
+
versionName,
|
|
62
|
+
}: {
|
|
63
|
+
siteDir: string;
|
|
64
|
+
locale: string;
|
|
65
|
+
pluginId: string;
|
|
66
|
+
versionName: string;
|
|
67
|
+
}): string {
|
|
68
|
+
return getPluginI18nPath({
|
|
69
|
+
siteDir,
|
|
70
|
+
locale,
|
|
71
|
+
pluginName: 'docusaurus-plugin-content-docs',
|
|
72
|
+
pluginId,
|
|
73
|
+
subPaths: [
|
|
74
|
+
versionName === CURRENT_VERSION_NAME
|
|
75
|
+
? CURRENT_VERSION_NAME
|
|
76
|
+
: `version-${versionName}`,
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** `community` => `[siteDir]/community_versions.json` */
|
|
82
|
+
export function getVersionsFilePath(siteDir: string, pluginId: string): string {
|
|
83
|
+
return path.join(siteDir, addPluginIdPrefix(VERSIONS_JSON_FILE, pluginId));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Reads the plugin's respective `versions.json` file, and returns its content.
|
|
88
|
+
*
|
|
89
|
+
* @throws Throws if validation fails, i.e. `versions.json` doesn't contain an
|
|
90
|
+
* array of valid version names.
|
|
91
|
+
*/
|
|
92
|
+
async function readVersionsFile(
|
|
93
|
+
siteDir: string,
|
|
94
|
+
pluginId: string,
|
|
95
|
+
): Promise<string[] | null> {
|
|
96
|
+
const versionsFilePath = getVersionsFilePath(siteDir, pluginId);
|
|
97
|
+
if (await fs.pathExists(versionsFilePath)) {
|
|
98
|
+
const content = await fs.readJSON(versionsFilePath);
|
|
99
|
+
validateVersionNames(content);
|
|
100
|
+
return content;
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Reads the `versions.json` file, and returns an ordered list of version names.
|
|
107
|
+
*
|
|
108
|
+
* - If `disableVersioning` is turned on, it will return `["current"]` (requires
|
|
109
|
+
* `includeCurrentVersion` to be true);
|
|
110
|
+
* - If `includeCurrentVersion` is turned on, "current" will be inserted at the
|
|
111
|
+
* beginning, if not already there.
|
|
112
|
+
*
|
|
113
|
+
* You need to use {@link filterVersions} after this.
|
|
114
|
+
*
|
|
115
|
+
* @throws Throws an error if `disableVersioning: true` but `versions.json`
|
|
116
|
+
* doesn't exist (i.e. site is not versioned)
|
|
117
|
+
* @throws Throws an error if versions list is empty (empty `versions.json` or
|
|
118
|
+
* `disableVersioning` is true, and not including current version)
|
|
119
|
+
*/
|
|
120
|
+
export async function readVersionNames(
|
|
121
|
+
siteDir: string,
|
|
122
|
+
options: PluginOptions,
|
|
123
|
+
): Promise<string[]> {
|
|
124
|
+
const versionFileContent = await readVersionsFile(siteDir, options.id);
|
|
125
|
+
|
|
126
|
+
if (!versionFileContent && options.disableVersioning) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Docs: using "disableVersioning: true" option on a non-versioned site does not make sense.`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const versions = options.disableVersioning ? [] : versionFileContent ?? [];
|
|
133
|
+
|
|
134
|
+
// We add the current version at the beginning, unless:
|
|
135
|
+
// - user don't want to; or
|
|
136
|
+
// - it's already been explicitly added to versions.json
|
|
137
|
+
if (
|
|
138
|
+
options.includeCurrentVersion &&
|
|
139
|
+
!versions.includes(CURRENT_VERSION_NAME)
|
|
140
|
+
) {
|
|
141
|
+
versions.unshift(CURRENT_VERSION_NAME);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (versions.length === 0) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`It is not possible to use docs without any version. No version is included because you have requested to not include ${path.resolve(
|
|
147
|
+
options.path,
|
|
148
|
+
)} through "includeCurrentVersion: false", while ${
|
|
149
|
+
options.disableVersioning
|
|
150
|
+
? 'versioning is disabled with "disableVersioning: true"'
|
|
151
|
+
: `the versions file is empty/non-existent`
|
|
152
|
+
}.`,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return versions;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Gets the path-related version metadata.
|
|
161
|
+
*
|
|
162
|
+
* @throws Throws if the resolved docs folder or sidebars file doesn't exist.
|
|
163
|
+
* Does not throw if a versioned sidebar is missing (since we don't create empty
|
|
164
|
+
* files).
|
|
165
|
+
*/
|
|
166
|
+
export async function getVersionMetadataPaths({
|
|
167
|
+
versionName,
|
|
168
|
+
context,
|
|
169
|
+
options,
|
|
170
|
+
}: VersionContext): Promise<
|
|
171
|
+
Pick<
|
|
172
|
+
VersionMetadata,
|
|
173
|
+
'contentPath' | 'contentPathLocalized' | 'sidebarFilePath'
|
|
174
|
+
>
|
|
175
|
+
> {
|
|
176
|
+
const isCurrent = versionName === CURRENT_VERSION_NAME;
|
|
177
|
+
const contentPathLocalized = getDocsDirPathLocalized({
|
|
178
|
+
siteDir: context.siteDir,
|
|
179
|
+
locale: context.i18n.currentLocale,
|
|
180
|
+
pluginId: options.id,
|
|
181
|
+
versionName,
|
|
182
|
+
});
|
|
183
|
+
const contentPath = isCurrent
|
|
184
|
+
? path.resolve(context.siteDir, options.path)
|
|
185
|
+
: getVersionDocsDirPath(context.siteDir, options.id, versionName);
|
|
186
|
+
const sidebarFilePath = isCurrent
|
|
187
|
+
? options.sidebarPath
|
|
188
|
+
: getVersionSidebarsPath(context.siteDir, options.id, versionName);
|
|
189
|
+
|
|
190
|
+
if (!(await fs.pathExists(contentPath))) {
|
|
191
|
+
throw new Error(
|
|
192
|
+
`The docs folder does not exist for version "${versionName}". A docs folder is expected to be found at ${path.relative(
|
|
193
|
+
context.siteDir,
|
|
194
|
+
contentPath,
|
|
195
|
+
)}.`,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// If the current version defines a path to a sidebar file that does not
|
|
200
|
+
// exist, we throw! Note: for versioned sidebars, the file may not exist (as
|
|
201
|
+
// we prefer to not create it rather than to create an empty file)
|
|
202
|
+
// See https://github.com/facebook/docusaurus/issues/3366
|
|
203
|
+
// See https://github.com/facebook/docusaurus/pull/4775
|
|
204
|
+
if (
|
|
205
|
+
versionName === CURRENT_VERSION_NAME &&
|
|
206
|
+
typeof sidebarFilePath === 'string' &&
|
|
207
|
+
!(await fs.pathExists(sidebarFilePath))
|
|
208
|
+
) {
|
|
209
|
+
throw new Error(`The path to the sidebar file does not exist at "${path.relative(
|
|
210
|
+
context.siteDir,
|
|
211
|
+
sidebarFilePath,
|
|
212
|
+
)}".
|
|
213
|
+
Please set the docs "sidebarPath" field in your config file to:
|
|
214
|
+
- a sidebars path that exists
|
|
215
|
+
- false: to disable the sidebar
|
|
216
|
+
- undefined: for Docusaurus to generate it automatically`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return {contentPath, contentPathLocalized, sidebarFilePath};
|
|
220
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import {CURRENT_VERSION_NAME} from '../constants';
|
|
10
|
+
import {normalizeUrl, posixPath} from '@docusaurus/utils';
|
|
11
|
+
import {validateVersionsOptions} from './validation';
|
|
12
|
+
import {
|
|
13
|
+
getDocsDirPathLocalized,
|
|
14
|
+
getVersionMetadataPaths,
|
|
15
|
+
readVersionNames,
|
|
16
|
+
} from './files';
|
|
17
|
+
import type {
|
|
18
|
+
PluginOptions,
|
|
19
|
+
VersionBanner,
|
|
20
|
+
VersionMetadata,
|
|
21
|
+
} from '@docusaurus/plugin-content-docs';
|
|
22
|
+
import type {LoadContext} from '@docusaurus/types';
|
|
23
|
+
|
|
24
|
+
export type VersionContext = {
|
|
25
|
+
/** The version name to get banner of. */
|
|
26
|
+
versionName: string;
|
|
27
|
+
/** All versions, ordered from newest to oldest. */
|
|
28
|
+
versionNames: string[];
|
|
29
|
+
lastVersionName: string;
|
|
30
|
+
context: LoadContext;
|
|
31
|
+
options: PluginOptions;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function getVersionEditUrls({
|
|
35
|
+
contentPath,
|
|
36
|
+
contentPathLocalized,
|
|
37
|
+
context,
|
|
38
|
+
options,
|
|
39
|
+
}: Pick<VersionMetadata, 'contentPath' | 'contentPathLocalized'> & {
|
|
40
|
+
context: LoadContext;
|
|
41
|
+
options: PluginOptions;
|
|
42
|
+
}): Pick<VersionMetadata, 'editUrl' | 'editUrlLocalized'> {
|
|
43
|
+
// If the user is using the functional form of editUrl,
|
|
44
|
+
// she has total freedom and we can't compute a "version edit url"
|
|
45
|
+
if (!options.editUrl || typeof options.editUrl === 'function') {
|
|
46
|
+
return {editUrl: undefined, editUrlLocalized: undefined};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const editDirPath = options.editCurrentVersion ? options.path : contentPath;
|
|
50
|
+
const editDirPathLocalized = options.editCurrentVersion
|
|
51
|
+
? getDocsDirPathLocalized({
|
|
52
|
+
siteDir: context.siteDir,
|
|
53
|
+
locale: context.i18n.currentLocale,
|
|
54
|
+
versionName: CURRENT_VERSION_NAME,
|
|
55
|
+
pluginId: options.id,
|
|
56
|
+
})
|
|
57
|
+
: contentPathLocalized;
|
|
58
|
+
|
|
59
|
+
const versionPathSegment = posixPath(
|
|
60
|
+
path.relative(context.siteDir, path.resolve(context.siteDir, editDirPath)),
|
|
61
|
+
);
|
|
62
|
+
const versionPathSegmentLocalized = posixPath(
|
|
63
|
+
path.relative(
|
|
64
|
+
context.siteDir,
|
|
65
|
+
path.resolve(context.siteDir, editDirPathLocalized),
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const editUrl = normalizeUrl([options.editUrl, versionPathSegment]);
|
|
70
|
+
|
|
71
|
+
const editUrlLocalized = normalizeUrl([
|
|
72
|
+
options.editUrl,
|
|
73
|
+
versionPathSegmentLocalized,
|
|
74
|
+
]);
|
|
75
|
+
|
|
76
|
+
return {editUrl, editUrlLocalized};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The default version banner depends on the version's relative position to the
|
|
81
|
+
* latest version. More recent ones are "unreleased", and older ones are
|
|
82
|
+
* "unmaintained".
|
|
83
|
+
*/
|
|
84
|
+
export function getDefaultVersionBanner({
|
|
85
|
+
versionName,
|
|
86
|
+
versionNames,
|
|
87
|
+
lastVersionName,
|
|
88
|
+
}: VersionContext): VersionBanner | null {
|
|
89
|
+
// Current version: good, no banner
|
|
90
|
+
if (versionName === lastVersionName) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
// Upcoming versions: unreleased banner
|
|
94
|
+
if (
|
|
95
|
+
versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName)
|
|
96
|
+
) {
|
|
97
|
+
return 'unreleased';
|
|
98
|
+
}
|
|
99
|
+
// Older versions: display unmaintained banner
|
|
100
|
+
return 'unmaintained';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function getVersionBanner(
|
|
104
|
+
context: VersionContext,
|
|
105
|
+
): VersionMetadata['banner'] {
|
|
106
|
+
const {versionName, options} = context;
|
|
107
|
+
const versionBannerOption = options.versions[versionName]?.banner;
|
|
108
|
+
if (versionBannerOption) {
|
|
109
|
+
return versionBannerOption === 'none' ? null : versionBannerOption;
|
|
110
|
+
}
|
|
111
|
+
return getDefaultVersionBanner(context);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function getVersionBadge({
|
|
115
|
+
versionName,
|
|
116
|
+
versionNames,
|
|
117
|
+
options,
|
|
118
|
+
}: VersionContext): VersionMetadata['badge'] {
|
|
119
|
+
// If site is not versioned or only one version is included
|
|
120
|
+
// we don't show the version badge by default
|
|
121
|
+
// See https://github.com/facebook/docusaurus/issues/3362
|
|
122
|
+
const defaultVersionBadge = versionNames.length !== 1;
|
|
123
|
+
return options.versions[versionName]?.badge ?? defaultVersionBadge;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function getVersionClassName({
|
|
127
|
+
versionName,
|
|
128
|
+
options,
|
|
129
|
+
}: VersionContext): VersionMetadata['className'] {
|
|
130
|
+
const defaultVersionClassName = `docs-version-${versionName}`;
|
|
131
|
+
return options.versions[versionName]?.className ?? defaultVersionClassName;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getVersionLabel({
|
|
135
|
+
versionName,
|
|
136
|
+
options,
|
|
137
|
+
}: VersionContext): VersionMetadata['label'] {
|
|
138
|
+
const defaultVersionLabel =
|
|
139
|
+
versionName === CURRENT_VERSION_NAME ? 'Next' : versionName;
|
|
140
|
+
return options.versions[versionName]?.label ?? defaultVersionLabel;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function getVersionPathPart({
|
|
144
|
+
versionName,
|
|
145
|
+
options,
|
|
146
|
+
lastVersionName,
|
|
147
|
+
}: VersionContext): string {
|
|
148
|
+
function getDefaultVersionPathPart() {
|
|
149
|
+
if (versionName === lastVersionName) {
|
|
150
|
+
return '';
|
|
151
|
+
}
|
|
152
|
+
return versionName === CURRENT_VERSION_NAME ? 'next' : versionName;
|
|
153
|
+
}
|
|
154
|
+
return options.versions[versionName]?.path ?? getDefaultVersionPathPart();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function createVersionMetadata(
|
|
158
|
+
context: VersionContext,
|
|
159
|
+
): Promise<VersionMetadata> {
|
|
160
|
+
const {versionName, lastVersionName, options, context: loadContext} = context;
|
|
161
|
+
const {sidebarFilePath, contentPath, contentPathLocalized} =
|
|
162
|
+
await getVersionMetadataPaths(context);
|
|
163
|
+
const versionPathPart = getVersionPathPart(context);
|
|
164
|
+
|
|
165
|
+
const routePath = normalizeUrl([
|
|
166
|
+
loadContext.baseUrl,
|
|
167
|
+
options.routeBasePath,
|
|
168
|
+
versionPathPart,
|
|
169
|
+
]);
|
|
170
|
+
|
|
171
|
+
const versionEditUrls = getVersionEditUrls({
|
|
172
|
+
contentPath,
|
|
173
|
+
contentPathLocalized,
|
|
174
|
+
context: loadContext,
|
|
175
|
+
options,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
versionName,
|
|
180
|
+
label: getVersionLabel(context),
|
|
181
|
+
banner: getVersionBanner(context),
|
|
182
|
+
badge: getVersionBadge(context),
|
|
183
|
+
className: getVersionClassName(context),
|
|
184
|
+
path: routePath,
|
|
185
|
+
tagsPath: normalizeUrl([routePath, options.tagsBasePath]),
|
|
186
|
+
...versionEditUrls,
|
|
187
|
+
isLast: versionName === lastVersionName,
|
|
188
|
+
routePriority: versionPathPart === '' ? -1 : undefined,
|
|
189
|
+
sidebarFilePath,
|
|
190
|
+
contentPath,
|
|
191
|
+
contentPathLocalized,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Filter versions according to provided options (i.e. `onlyIncludeVersions`).
|
|
197
|
+
*
|
|
198
|
+
* Note: we preserve the order in which versions are provided; the order of the
|
|
199
|
+
* `onlyIncludeVersions` array does not matter
|
|
200
|
+
*/
|
|
201
|
+
export function filterVersions(
|
|
202
|
+
versionNamesUnfiltered: string[],
|
|
203
|
+
options: PluginOptions,
|
|
204
|
+
): string[] {
|
|
205
|
+
if (options.onlyIncludeVersions) {
|
|
206
|
+
return versionNamesUnfiltered.filter((name) =>
|
|
207
|
+
options.onlyIncludeVersions!.includes(name),
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
return versionNamesUnfiltered;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function getLastVersionName({
|
|
214
|
+
versionNames,
|
|
215
|
+
options,
|
|
216
|
+
}: Pick<VersionContext, 'versionNames' | 'options'>) {
|
|
217
|
+
return (
|
|
218
|
+
options.lastVersion ??
|
|
219
|
+
versionNames.find((name) => name !== CURRENT_VERSION_NAME) ??
|
|
220
|
+
CURRENT_VERSION_NAME
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export async function readVersionsMetadata({
|
|
225
|
+
context,
|
|
226
|
+
options,
|
|
227
|
+
}: {
|
|
228
|
+
context: LoadContext;
|
|
229
|
+
options: PluginOptions;
|
|
230
|
+
}): Promise<VersionMetadata[]> {
|
|
231
|
+
const allVersionNames = await readVersionNames(context.siteDir, options);
|
|
232
|
+
validateVersionsOptions(allVersionNames, options);
|
|
233
|
+
const versionNames = filterVersions(allVersionNames, options);
|
|
234
|
+
const lastVersionName = getLastVersionName({versionNames, options});
|
|
235
|
+
const versionsMetadata = await Promise.all(
|
|
236
|
+
versionNames.map((versionName) =>
|
|
237
|
+
createVersionMetadata({
|
|
238
|
+
versionName,
|
|
239
|
+
versionNames,
|
|
240
|
+
lastVersionName,
|
|
241
|
+
context,
|
|
242
|
+
options,
|
|
243
|
+
}),
|
|
244
|
+
),
|
|
245
|
+
);
|
|
246
|
+
return versionsMetadata;
|
|
247
|
+
}
|