@docusaurus/plugin-content-docs 2.0.0-beta.15 → 2.0.0-beta.16
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 +18 -14
- package/lib/client/docsClientUtils.js +2 -2
- package/lib/client/index.d.ts +13 -1
- package/lib/client/index.js +66 -1
- package/lib/docFrontMatter.js +1 -0
- package/lib/docs.d.ts +2 -1
- package/lib/docs.js +23 -22
- package/lib/globalData.js +3 -2
- package/lib/index.js +11 -6
- package/lib/lastUpdate.js +14 -27
- package/lib/numberPrefix.js +7 -6
- package/lib/options.js +5 -2
- package/lib/props.js +15 -10
- package/lib/routes.js +6 -4
- package/lib/server-export.d.ts +8 -0
- package/lib/server-export.js +23 -0
- package/lib/sidebars/generator.d.ts +1 -9
- package/lib/sidebars/generator.js +26 -50
- package/lib/sidebars/index.d.ts +2 -5
- package/lib/sidebars/index.js +35 -20
- package/lib/sidebars/normalization.d.ts +2 -3
- package/lib/sidebars/normalization.js +17 -39
- package/lib/sidebars/postProcessor.d.ts +8 -0
- package/lib/sidebars/postProcessor.js +72 -0
- package/lib/sidebars/processor.d.ts +2 -13
- package/lib/sidebars/processor.js +25 -33
- package/lib/sidebars/types.d.ts +44 -10
- package/lib/sidebars/utils.js +53 -61
- package/lib/sidebars/validation.d.ts +2 -3
- package/lib/sidebars/validation.js +25 -30
- package/lib/slug.js +6 -8
- package/lib/tags.js +3 -2
- package/lib/translations.js +18 -17
- package/lib/types.d.ts +3 -6
- package/lib/versions.d.ts +25 -1
- package/lib/versions.js +25 -29
- package/package.json +19 -18
- package/src/cli.ts +25 -16
- package/src/client/docsClientUtils.ts +2 -2
- package/src/client/index.ts +97 -1
- package/src/docFrontMatter.ts +1 -0
- package/src/docs.ts +25 -20
- package/src/globalData.ts +2 -2
- package/src/index.ts +17 -7
- package/src/lastUpdate.ts +12 -33
- package/src/numberPrefix.ts +7 -6
- package/src/options.ts +5 -2
- package/src/plugin-content-docs.d.ts +16 -60
- package/src/props.ts +17 -12
- package/src/routes.ts +6 -4
- package/src/server-export.ts +24 -0
- package/src/sidebars/README.md +9 -0
- package/src/sidebars/generator.ts +50 -94
- package/src/sidebars/index.ts +50 -32
- package/src/sidebars/normalization.ts +22 -50
- package/src/sidebars/postProcessor.ts +94 -0
- package/src/sidebars/processor.ts +37 -66
- package/src/sidebars/types.ts +68 -10
- package/src/sidebars/utils.ts +63 -68
- package/src/sidebars/validation.ts +53 -53
- package/src/slug.ts +9 -10
- package/src/tags.ts +2 -2
- package/src/translations.ts +19 -16
- package/src/types.ts +3 -10
- package/src/versions.ts +30 -34
- package/lib/client/globalDataHooks.d.ts +0 -19
- package/lib/client/globalDataHooks.js +0 -76
- package/src/client/globalDataHooks.ts +0 -107
package/lib/versions.js
CHANGED
|
@@ -6,22 +6,19 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.getDocsDirPaths = exports.readVersionsMetadata = exports.getVersionsFilePath = exports.getVersionedSidebarsDirPath = exports.getVersionedDocsDirPath = void 0;
|
|
9
|
+
exports.getDocsDirPaths = exports.readVersionsMetadata = exports.filterVersions = exports.getVersionBadge = exports.getVersionBanner = exports.getDefaultVersionBanner = exports.readVersionNames = exports.readVersionsFile = exports.getVersionsFilePath = exports.getVersionedSidebarsDirPath = exports.getVersionedDocsDirPath = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
12
12
|
const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
|
|
13
13
|
const constants_1 = require("./constants");
|
|
14
14
|
const utils_1 = require("@docusaurus/utils");
|
|
15
|
-
const lodash_1 = require("lodash");
|
|
15
|
+
const lodash_1 = (0, tslib_1.__importDefault)(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,10 +54,9 @@ 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
|
}
|
|
59
|
+
exports.readVersionsFile = readVersionsFile;
|
|
64
60
|
async function readVersionNames(siteDir, options) {
|
|
65
61
|
const versionFileContent = await readVersionsFile(siteDir, options.id);
|
|
66
62
|
if (!versionFileContent && options.disableVersioning) {
|
|
@@ -79,6 +75,7 @@ async function readVersionNames(siteDir, options) {
|
|
|
79
75
|
}
|
|
80
76
|
return versions;
|
|
81
77
|
}
|
|
78
|
+
exports.readVersionNames = readVersionNames;
|
|
82
79
|
function getDocsDirPathLocalized({ siteDir, locale, pluginId, versionName, }) {
|
|
83
80
|
return (0, utils_1.getPluginI18nPath)({
|
|
84
81
|
siteDir,
|
|
@@ -149,14 +146,13 @@ function getDefaultVersionBanner({ versionName, versionNames, lastVersionName, }
|
|
|
149
146
|
return null;
|
|
150
147
|
}
|
|
151
148
|
// Upcoming versions: unreleased banner
|
|
152
|
-
|
|
149
|
+
if (versionNames.indexOf(versionName) < versionNames.indexOf(lastVersionName)) {
|
|
153
150
|
return 'unreleased';
|
|
154
151
|
}
|
|
155
152
|
// Older versions: display unmaintained banner
|
|
156
|
-
|
|
157
|
-
return 'unmaintained';
|
|
158
|
-
}
|
|
153
|
+
return 'unmaintained';
|
|
159
154
|
}
|
|
155
|
+
exports.getDefaultVersionBanner = getDefaultVersionBanner;
|
|
160
156
|
function getVersionBanner({ versionName, versionNames, lastVersionName, options, }) {
|
|
161
157
|
var _a;
|
|
162
158
|
const versionBannerOption = (_a = options.versions[versionName]) === null || _a === void 0 ? void 0 : _a.banner;
|
|
@@ -169,6 +165,7 @@ function getVersionBanner({ versionName, versionNames, lastVersionName, options,
|
|
|
169
165
|
lastVersionName,
|
|
170
166
|
});
|
|
171
167
|
}
|
|
168
|
+
exports.getVersionBanner = getVersionBanner;
|
|
172
169
|
function getVersionBadge({ versionName, versionNames, options, }) {
|
|
173
170
|
var _a;
|
|
174
171
|
const versionBadgeOption = (_a = options.versions[versionName]) === null || _a === void 0 ? void 0 : _a.badge;
|
|
@@ -178,6 +175,7 @@ function getVersionBadge({ versionName, versionNames, options, }) {
|
|
|
178
175
|
const versionBadgeDefault = versionNames.length !== 1;
|
|
179
176
|
return versionBadgeOption !== null && versionBadgeOption !== void 0 ? versionBadgeOption : versionBadgeDefault;
|
|
180
177
|
}
|
|
178
|
+
exports.getVersionBadge = getVersionBadge;
|
|
181
179
|
function getVersionClassName({ versionName, options, }) {
|
|
182
180
|
var _a;
|
|
183
181
|
const versionClassNameOption = (_a = options.versions[versionName]) === null || _a === void 0 ? void 0 : _a.className;
|
|
@@ -238,20 +236,21 @@ function createVersionMetadata({ versionName, versionNames, lastVersionName, con
|
|
|
238
236
|
contentPathLocalized,
|
|
239
237
|
};
|
|
240
238
|
}
|
|
241
|
-
function checkVersionMetadataPaths({ versionMetadata, context, }) {
|
|
239
|
+
async function checkVersionMetadataPaths({ versionMetadata, context, }) {
|
|
242
240
|
const { versionName, contentPath, sidebarFilePath } = versionMetadata;
|
|
243
241
|
const { siteDir } = context;
|
|
244
242
|
const isCurrentVersion = versionName === constants_1.CURRENT_VERSION_NAME;
|
|
245
|
-
if (!fs_extra_1.default.
|
|
243
|
+
if (!(await fs_extra_1.default.pathExists(contentPath))) {
|
|
246
244
|
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
245
|
}
|
|
248
|
-
// If the current version defines a path to a sidebar file
|
|
249
|
-
// Note: for versioned sidebars, the file may not exist (as
|
|
246
|
+
// If the current version defines a path to a sidebar file that does not
|
|
247
|
+
// exist, we throw! Note: for versioned sidebars, the file may not exist (as
|
|
248
|
+
// we prefer to not create it rather than to create an empty file)
|
|
250
249
|
// See https://github.com/facebook/docusaurus/issues/3366
|
|
251
250
|
// See https://github.com/facebook/docusaurus/pull/4775
|
|
252
251
|
if (isCurrentVersion &&
|
|
253
252
|
typeof sidebarFilePath === 'string' &&
|
|
254
|
-
!fs_extra_1.default.
|
|
253
|
+
!(await fs_extra_1.default.pathExists(sidebarFilePath))) {
|
|
255
254
|
throw new Error(`The path to the sidebar file does not exist at "${path_1.default.relative(siteDir, sidebarFilePath)}".
|
|
256
255
|
Please set the docs "sidebarPath" field in your config file to:
|
|
257
256
|
- a sidebars path that exists
|
|
@@ -266,9 +265,7 @@ function getDefaultLastVersionName(versionNames) {
|
|
|
266
265
|
if (versionNames.length === 1) {
|
|
267
266
|
return versionNames[0];
|
|
268
267
|
}
|
|
269
|
-
|
|
270
|
-
return versionNames.filter((versionName) => versionName !== constants_1.CURRENT_VERSION_NAME)[0];
|
|
271
|
-
}
|
|
268
|
+
return versionNames.filter((versionName) => versionName !== constants_1.CURRENT_VERSION_NAME)[0];
|
|
272
269
|
}
|
|
273
270
|
function checkVersionsOptions(availableVersionNames, options) {
|
|
274
271
|
const availableVersionNamesMsg = `Available version names are: ${availableVersionNames.join(', ')}`;
|
|
@@ -276,7 +273,7 @@ function checkVersionsOptions(availableVersionNames, options) {
|
|
|
276
273
|
!availableVersionNames.includes(options.lastVersion)) {
|
|
277
274
|
throw new Error(`Docs option lastVersion: ${options.lastVersion} is invalid. ${availableVersionNamesMsg}`);
|
|
278
275
|
}
|
|
279
|
-
const unknownVersionConfigNames =
|
|
276
|
+
const unknownVersionConfigNames = lodash_1.default.difference(Object.keys(options.versions), availableVersionNames);
|
|
280
277
|
if (unknownVersionConfigNames.length > 0) {
|
|
281
278
|
throw new Error(`Invalid docs option "versions": unknown versions (${unknownVersionConfigNames.join(',')}) found. ${availableVersionNamesMsg}`);
|
|
282
279
|
}
|
|
@@ -284,7 +281,7 @@ function checkVersionsOptions(availableVersionNames, options) {
|
|
|
284
281
|
if (options.onlyIncludeVersions.length === 0) {
|
|
285
282
|
throw new Error(`Invalid docs option "onlyIncludeVersions": an empty array is not allowed, at least one version is needed.`);
|
|
286
283
|
}
|
|
287
|
-
const unknownOnlyIncludeVersionNames =
|
|
284
|
+
const unknownOnlyIncludeVersionNames = lodash_1.default.difference(options.onlyIncludeVersions, availableVersionNames);
|
|
288
285
|
if (unknownOnlyIncludeVersionNames.length > 0) {
|
|
289
286
|
throw new Error(`Invalid docs option "onlyIncludeVersions": unknown versions (${unknownOnlyIncludeVersionNames.join(',')}) found. ${availableVersionNamesMsg}`);
|
|
290
287
|
}
|
|
@@ -303,10 +300,9 @@ function filterVersions(versionNamesUnfiltered, options) {
|
|
|
303
300
|
if (options.onlyIncludeVersions) {
|
|
304
301
|
return versionNamesUnfiltered.filter((name) => (options.onlyIncludeVersions || []).includes(name));
|
|
305
302
|
}
|
|
306
|
-
|
|
307
|
-
return versionNamesUnfiltered;
|
|
308
|
-
}
|
|
303
|
+
return versionNamesUnfiltered;
|
|
309
304
|
}
|
|
305
|
+
exports.filterVersions = filterVersions;
|
|
310
306
|
async function readVersionsMetadata({ context, options, }) {
|
|
311
307
|
var _a;
|
|
312
308
|
const versionNamesUnfiltered = await readVersionNames(context.siteDir, options);
|
|
@@ -320,7 +316,7 @@ async function readVersionsMetadata({ context, options, }) {
|
|
|
320
316
|
context,
|
|
321
317
|
options,
|
|
322
318
|
}));
|
|
323
|
-
versionsMetadata.
|
|
319
|
+
await Promise.all(versionsMetadata.map((versionMetadata) => checkVersionMetadataPaths({ versionMetadata, context })));
|
|
324
320
|
return versionsMetadata;
|
|
325
321
|
}
|
|
326
322
|
exports.readVersionsMetadata = readVersionsMetadata;
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-docs",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.16",
|
|
4
4
|
"description": "Docs plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./client": "./lib/client/index.js",
|
|
8
|
+
"./server": "./lib/server-export.js",
|
|
8
9
|
".": "./lib/index.js"
|
|
9
10
|
},
|
|
10
11
|
"types": "src/plugin-content-docs.d.ts",
|
|
@@ -22,30 +23,30 @@
|
|
|
22
23
|
},
|
|
23
24
|
"license": "MIT",
|
|
24
25
|
"dependencies": {
|
|
25
|
-
"@docusaurus/core": "2.0.0-beta.
|
|
26
|
-
"@docusaurus/logger": "2.0.0-beta.
|
|
27
|
-
"@docusaurus/mdx-loader": "2.0.0-beta.
|
|
28
|
-
"@docusaurus/utils": "2.0.0-beta.
|
|
29
|
-
"@docusaurus/utils-validation": "2.0.0-beta.
|
|
26
|
+
"@docusaurus/core": "2.0.0-beta.16",
|
|
27
|
+
"@docusaurus/logger": "2.0.0-beta.16",
|
|
28
|
+
"@docusaurus/mdx-loader": "2.0.0-beta.16",
|
|
29
|
+
"@docusaurus/utils": "2.0.0-beta.16",
|
|
30
|
+
"@docusaurus/utils-validation": "2.0.0-beta.16",
|
|
30
31
|
"combine-promises": "^1.1.0",
|
|
31
|
-
"fs-extra": "^10.0.
|
|
32
|
-
"import-fresh": "^3.
|
|
33
|
-
"js-yaml": "^4.
|
|
34
|
-
"lodash": "^4.17.
|
|
32
|
+
"fs-extra": "^10.0.1",
|
|
33
|
+
"import-fresh": "^3.3.0",
|
|
34
|
+
"js-yaml": "^4.1.0",
|
|
35
|
+
"lodash": "^4.17.21",
|
|
35
36
|
"remark-admonitions": "^1.2.1",
|
|
36
|
-
"shelljs": "^0.8.4",
|
|
37
37
|
"tslib": "^2.3.1",
|
|
38
38
|
"utility-types": "^3.10.0",
|
|
39
|
-
"webpack": "^5.
|
|
39
|
+
"webpack": "^5.69.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@docusaurus/module-type-aliases": "2.0.0-beta.
|
|
43
|
-
"@docusaurus/types": "2.0.0-beta.
|
|
44
|
-
"@types/js-yaml": "^4.0.
|
|
45
|
-
"@types/picomatch": "^2.
|
|
42
|
+
"@docusaurus/module-type-aliases": "2.0.0-beta.16",
|
|
43
|
+
"@docusaurus/types": "2.0.0-beta.16",
|
|
44
|
+
"@types/js-yaml": "^4.0.5",
|
|
45
|
+
"@types/picomatch": "^2.3.0",
|
|
46
46
|
"commander": "^5.1.0",
|
|
47
47
|
"escape-string-regexp": "^4.0.0",
|
|
48
|
-
"picomatch": "^2.
|
|
48
|
+
"picomatch": "^2.3.1",
|
|
49
|
+
"shelljs": "^0.8.5",
|
|
49
50
|
"utility-types": "^3.10.0"
|
|
50
51
|
},
|
|
51
52
|
"peerDependencies": {
|
|
@@ -55,5 +56,5 @@
|
|
|
55
56
|
"engines": {
|
|
56
57
|
"node": ">=14"
|
|
57
58
|
},
|
|
58
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "eb43c4d4f95a4fb97dc9bb9dc615413e0dc2e1e7"
|
|
59
60
|
}
|
package/src/cli.ts
CHANGED
|
@@ -16,11 +16,11 @@ import type {
|
|
|
16
16
|
PathOptions,
|
|
17
17
|
SidebarOptions,
|
|
18
18
|
} from '@docusaurus/plugin-content-docs';
|
|
19
|
-
import {
|
|
19
|
+
import {loadSidebarsFileUnsafe, 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,13 @@ 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
|
+
// We don't validate here, assuming the user has already built the version
|
|
38
|
+
const sidebars = await loadSidebarsFileUnsafe(sidebarPath);
|
|
37
39
|
|
|
38
|
-
// Do not create a useless versioned sidebars file if sidebars file is empty
|
|
40
|
+
// Do not create a useless versioned sidebars file if sidebars file is empty
|
|
41
|
+
// or sidebars are disabled/false)
|
|
39
42
|
const shouldCreateVersionedSidebarFile = Object.keys(sidebars).length > 0;
|
|
40
43
|
|
|
41
44
|
if (shouldCreateVersionedSidebarFile) {
|
|
@@ -44,8 +47,8 @@ function createVersionedSidebarFile({
|
|
|
44
47
|
versionedSidebarsDir,
|
|
45
48
|
`version-${version}-sidebars.json`,
|
|
46
49
|
);
|
|
47
|
-
fs.
|
|
48
|
-
fs.
|
|
50
|
+
await fs.ensureDir(path.dirname(newSidebarFile));
|
|
51
|
+
await fs.writeFile(
|
|
49
52
|
newSidebarFile,
|
|
50
53
|
`${JSON.stringify(sidebars, null, 2)}\n`,
|
|
51
54
|
'utf8',
|
|
@@ -54,12 +57,12 @@ function createVersionedSidebarFile({
|
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
// Tests depend on non-default export for mocking.
|
|
57
|
-
export function cliDocsVersionCommand(
|
|
60
|
+
export async function cliDocsVersionCommand(
|
|
58
61
|
version: string | null | undefined,
|
|
59
62
|
siteDir: string,
|
|
60
63
|
pluginId: string,
|
|
61
64
|
options: PathOptions & SidebarOptions,
|
|
62
|
-
): void {
|
|
65
|
+
): Promise<void> {
|
|
63
66
|
// It wouldn't be very user-friendly to show a [default] log prefix,
|
|
64
67
|
// so we use [docs] instead of [default]
|
|
65
68
|
const pluginIdLogPrefix =
|
|
@@ -101,8 +104,8 @@ export function cliDocsVersionCommand(
|
|
|
101
104
|
// Load existing versions.
|
|
102
105
|
let versions = [];
|
|
103
106
|
const versionsJSONFile = getVersionsFilePath(siteDir, pluginId);
|
|
104
|
-
if (fs.
|
|
105
|
-
versions = JSON.parse(fs.
|
|
107
|
+
if (await fs.pathExists(versionsJSONFile)) {
|
|
108
|
+
versions = JSON.parse(await fs.readFile(versionsJSONFile, 'utf8'));
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
// Check if version already exists.
|
|
@@ -117,15 +120,18 @@ export function cliDocsVersionCommand(
|
|
|
117
120
|
// Copy docs files.
|
|
118
121
|
const docsDir = path.join(siteDir, docsPath);
|
|
119
122
|
|
|
120
|
-
if (
|
|
123
|
+
if (
|
|
124
|
+
(await fs.pathExists(docsDir)) &&
|
|
125
|
+
(await fs.readdir(docsDir)).length > 0
|
|
126
|
+
) {
|
|
121
127
|
const versionedDir = getVersionedDocsDirPath(siteDir, pluginId);
|
|
122
128
|
const newVersionDir = path.join(versionedDir, `version-${version}`);
|
|
123
|
-
fs.
|
|
129
|
+
await fs.copy(docsDir, newVersionDir);
|
|
124
130
|
} else {
|
|
125
131
|
throw new Error(`${pluginIdLogPrefix}: there is no docs to version!`);
|
|
126
132
|
}
|
|
127
133
|
|
|
128
|
-
createVersionedSidebarFile({
|
|
134
|
+
await createVersionedSidebarFile({
|
|
129
135
|
siteDir,
|
|
130
136
|
pluginId,
|
|
131
137
|
version,
|
|
@@ -134,8 +140,11 @@ export function cliDocsVersionCommand(
|
|
|
134
140
|
|
|
135
141
|
// Update versions.json file.
|
|
136
142
|
versions.unshift(version);
|
|
137
|
-
fs.
|
|
138
|
-
fs.
|
|
143
|
+
await fs.ensureDir(path.dirname(versionsJSONFile));
|
|
144
|
+
await fs.writeFile(
|
|
145
|
+
versionsJSONFile,
|
|
146
|
+
`${JSON.stringify(versions, null, 2)}\n`,
|
|
147
|
+
);
|
|
139
148
|
|
|
140
149
|
logger.success`name=${pluginIdLogPrefix}: version name=${version} created!`;
|
|
141
150
|
}
|
|
@@ -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,
|
package/src/client/index.ts
CHANGED
|
@@ -5,4 +5,100 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import {useLocation} from '@docusaurus/router';
|
|
9
|
+
import useGlobalData, {usePluginData} from '@docusaurus/useGlobalData';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
getActivePlugin,
|
|
13
|
+
getLatestVersion,
|
|
14
|
+
getActiveVersion,
|
|
15
|
+
getActiveDocContext,
|
|
16
|
+
getDocVersionSuggestions,
|
|
17
|
+
} from './docsClientUtils';
|
|
18
|
+
import type {
|
|
19
|
+
GlobalPluginData,
|
|
20
|
+
GlobalVersion,
|
|
21
|
+
ActivePlugin,
|
|
22
|
+
ActiveDocContext,
|
|
23
|
+
DocVersionSuggestions,
|
|
24
|
+
GetActivePluginOptions,
|
|
25
|
+
} from '@docusaurus/plugin-content-docs/client';
|
|
26
|
+
|
|
27
|
+
// Important to use a constant object to avoid React useEffect executions etc.
|
|
28
|
+
// see https://github.com/facebook/docusaurus/issues/5089
|
|
29
|
+
const StableEmptyObject = {};
|
|
30
|
+
|
|
31
|
+
// Not using useAllPluginInstancesData() because in blog-only mode, docs hooks
|
|
32
|
+
// are still used by the theme. We need a fail-safe fallback when the docs
|
|
33
|
+
// plugin is not in use
|
|
34
|
+
export const useAllDocsData = (): Record<string, GlobalPluginData> =>
|
|
35
|
+
useGlobalData()['docusaurus-plugin-content-docs'] ?? StableEmptyObject;
|
|
36
|
+
|
|
37
|
+
export const useDocsData = (pluginId: string | undefined): GlobalPluginData =>
|
|
38
|
+
usePluginData('docusaurus-plugin-content-docs', pluginId) as GlobalPluginData;
|
|
39
|
+
|
|
40
|
+
// TODO this feature should be provided by docusaurus core
|
|
41
|
+
export const useActivePlugin = (
|
|
42
|
+
options: GetActivePluginOptions = {},
|
|
43
|
+
): ActivePlugin | undefined => {
|
|
44
|
+
const data = useAllDocsData();
|
|
45
|
+
const {pathname} = useLocation();
|
|
46
|
+
return getActivePlugin(data, pathname, options);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const useActivePluginAndVersion = (
|
|
50
|
+
options: GetActivePluginOptions = {},
|
|
51
|
+
):
|
|
52
|
+
| undefined
|
|
53
|
+
| {activePlugin: ActivePlugin; activeVersion: GlobalVersion | undefined} => {
|
|
54
|
+
const activePlugin = useActivePlugin(options);
|
|
55
|
+
const {pathname} = useLocation();
|
|
56
|
+
if (activePlugin) {
|
|
57
|
+
const activeVersion = getActiveVersion(activePlugin.pluginData, pathname);
|
|
58
|
+
return {
|
|
59
|
+
activePlugin,
|
|
60
|
+
activeVersion,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// versions are returned ordered (most recent first)
|
|
67
|
+
export const useVersions = (pluginId: string | undefined): GlobalVersion[] => {
|
|
68
|
+
const data = useDocsData(pluginId);
|
|
69
|
+
return data.versions;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export const useLatestVersion = (
|
|
73
|
+
pluginId: string | undefined,
|
|
74
|
+
): GlobalVersion => {
|
|
75
|
+
const data = useDocsData(pluginId);
|
|
76
|
+
return getLatestVersion(data);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Note: return undefined on doc-unrelated pages,
|
|
80
|
+
// because there's no version currently considered as active
|
|
81
|
+
export const useActiveVersion = (
|
|
82
|
+
pluginId: string | undefined,
|
|
83
|
+
): GlobalVersion | undefined => {
|
|
84
|
+
const data = useDocsData(pluginId);
|
|
85
|
+
const {pathname} = useLocation();
|
|
86
|
+
return getActiveVersion(data, pathname);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const useActiveDocContext = (
|
|
90
|
+
pluginId: string | undefined,
|
|
91
|
+
): ActiveDocContext => {
|
|
92
|
+
const data = useDocsData(pluginId);
|
|
93
|
+
const {pathname} = useLocation();
|
|
94
|
+
return getActiveDocContext(data, pathname);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Useful to say "hey, you are not on the latest docs version, please switch"
|
|
98
|
+
export const useDocVersionSuggestions = (
|
|
99
|
+
pluginId: string | undefined,
|
|
100
|
+
): DocVersionSuggestions => {
|
|
101
|
+
const data = useDocsData(pluginId);
|
|
102
|
+
const {pathname} = useLocation();
|
|
103
|
+
return getDocVersionSuggestions(data, pathname);
|
|
104
|
+
};
|
package/src/docFrontMatter.ts
CHANGED
|
@@ -30,6 +30,7 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
|
|
|
30
30
|
sidebar_label: Joi.string(),
|
|
31
31
|
sidebar_position: Joi.number(),
|
|
32
32
|
sidebar_class_name: Joi.string(),
|
|
33
|
+
sidebar_custom_props: Joi.object().unknown(),
|
|
33
34
|
displayed_sidebar: Joi.string().allow(null),
|
|
34
35
|
tags: FrontMatterTagsSchema,
|
|
35
36
|
pagination_label: Joi.string(),
|
package/src/docs.ts
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import fs from 'fs-extra';
|
|
10
10
|
import logger from '@docusaurus/logger';
|
|
11
|
-
import {keyBy} from 'lodash';
|
|
12
11
|
import {
|
|
13
12
|
aliasedSitePath,
|
|
14
13
|
getEditUrl,
|
|
@@ -139,7 +138,8 @@ function doProcessDocMetadata({
|
|
|
139
138
|
const {
|
|
140
139
|
custom_edit_url: customEditURL,
|
|
141
140
|
|
|
142
|
-
// Strip number prefixes by default
|
|
141
|
+
// Strip number prefixes by default
|
|
142
|
+
// (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
|
|
143
143
|
// but allow to disable this behavior with front matter
|
|
144
144
|
parse_number_prefixes: parseNumberPrefixes = true,
|
|
145
145
|
} = frontMatter;
|
|
@@ -164,7 +164,8 @@ function doProcessDocMetadata({
|
|
|
164
164
|
throw new Error(`Document id "${baseID}" cannot include slash.`);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
// For autogenerated sidebars, sidebar position can come from filename number
|
|
167
|
+
// For autogenerated sidebars, sidebar position can come from filename number
|
|
168
|
+
// prefix or front matter
|
|
168
169
|
const sidebarPosition: number | undefined =
|
|
169
170
|
frontMatter.sidebar_position ?? numberPrefix;
|
|
170
171
|
|
|
@@ -205,8 +206,9 @@ function doProcessDocMetadata({
|
|
|
205
206
|
numberPrefixParser: options.numberPrefixParser,
|
|
206
207
|
});
|
|
207
208
|
|
|
208
|
-
// Note: the title is used by default for page title, sidebar label,
|
|
209
|
-
// frontMatter.title should be used in priority over
|
|
209
|
+
// Note: the title is used by default for page title, sidebar label,
|
|
210
|
+
// pagination buttons... frontMatter.title should be used in priority over
|
|
211
|
+
// contentTitle (because it can contain markdown/JSX syntax)
|
|
210
212
|
const title: string = frontMatter.title ?? contentTitle ?? baseID;
|
|
211
213
|
|
|
212
214
|
const description: string = frontMatter.description ?? excerpt ?? '';
|
|
@@ -233,9 +235,8 @@ function doProcessDocMetadata({
|
|
|
233
235
|
? versionMetadata.versionEditUrlLocalized
|
|
234
236
|
: versionMetadata.versionEditUrl;
|
|
235
237
|
return getEditUrl(relativeFilePath, baseVersionEditUrl);
|
|
236
|
-
} else {
|
|
237
|
-
return undefined;
|
|
238
238
|
}
|
|
239
|
+
return undefined;
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
// Assign all of object properties during instantiation (if possible) for
|
|
@@ -274,9 +275,9 @@ export function processDocMetadata(args: {
|
|
|
274
275
|
}): DocMetadataBase {
|
|
275
276
|
try {
|
|
276
277
|
return doProcessDocMetadata(args);
|
|
277
|
-
} catch (
|
|
278
|
+
} catch (err) {
|
|
278
279
|
logger.error`Can't process doc metadata for doc at path path=${args.docFile.filePath} in version name=${args.versionMetadata.versionName}`;
|
|
279
|
-
throw
|
|
280
|
+
throw err;
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
283
|
|
|
@@ -361,9 +362,8 @@ export function getMainDocId({
|
|
|
361
362
|
doc.id === firstDocIdOfFirstSidebar ||
|
|
362
363
|
doc.unversionedId === firstDocIdOfFirstSidebar,
|
|
363
364
|
)!;
|
|
364
|
-
} else {
|
|
365
|
-
return docs[0];
|
|
366
365
|
}
|
|
366
|
+
return docs[0];
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
return getMainDoc().unversionedId;
|
|
@@ -407,7 +407,8 @@ export function toCategoryIndexMatcherParam({
|
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
/**
|
|
410
|
-
* guides/sidebar/autogenerated.md ->
|
|
410
|
+
* `guides/sidebar/autogenerated.md` ->
|
|
411
|
+
* `'autogenerated', '.md', ['sidebar', 'guides']`
|
|
411
412
|
*/
|
|
412
413
|
export function splitPath(str: string): {
|
|
413
414
|
/**
|
|
@@ -428,20 +429,24 @@ export function splitPath(str: string): {
|
|
|
428
429
|
}
|
|
429
430
|
|
|
430
431
|
// Return both doc ids
|
|
431
|
-
// TODO legacy retro-compatibility due to old versioned sidebars using
|
|
432
|
-
// ("id" should be removed & "versionedId" should be renamed
|
|
432
|
+
// TODO legacy retro-compatibility due to old versioned sidebars using
|
|
433
|
+
// versioned doc ids ("id" should be removed & "versionedId" should be renamed
|
|
434
|
+
// to "id")
|
|
433
435
|
export function getDocIds(doc: DocMetadataBase): [string, string] {
|
|
434
436
|
return [doc.unversionedId, doc.id];
|
|
435
437
|
}
|
|
436
438
|
|
|
437
439
|
// 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
|
|
440
|
+
// TODO legacy retro-compatibility due to old versioned sidebars using
|
|
441
|
+
// versioned doc ids ("id" should be removed & "versionedId" should be renamed
|
|
442
|
+
// to "id")
|
|
440
443
|
export function createDocsByIdIndex<
|
|
441
444
|
Doc extends {id: string; unversionedId: string},
|
|
442
445
|
>(docs: Doc[]): Record<string, Doc> {
|
|
443
|
-
return
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
446
|
+
return Object.fromEntries(
|
|
447
|
+
docs.flatMap((doc) => [
|
|
448
|
+
[doc.unversionedId, doc],
|
|
449
|
+
[doc.id, doc],
|
|
450
|
+
]),
|
|
451
|
+
);
|
|
447
452
|
}
|
package/src/globalData.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import _ from 'lodash';
|
|
9
9
|
import {normalizeUrl} from '@docusaurus/utils';
|
|
10
10
|
import type {Sidebars} from './sidebars/types';
|
|
11
11
|
import {createSidebarsUtils} from './sidebars/utils';
|
|
@@ -43,7 +43,7 @@ export function toGlobalSidebars(
|
|
|
43
43
|
version: LoadedVersion,
|
|
44
44
|
): Record<string, GlobalSidebar> {
|
|
45
45
|
const {getFirstLink} = createSidebarsUtils(sidebars);
|
|
46
|
-
return mapValues(sidebars, (sidebar, sidebarId) => {
|
|
46
|
+
return _.mapValues(sidebars, (sidebar, sidebarId) => {
|
|
47
47
|
const firstLink = getFirstLink(sidebarId);
|
|
48
48
|
if (!firstLink) {
|
|
49
49
|
return {};
|
package/src/index.ts
CHANGED
|
@@ -38,11 +38,11 @@ import type {
|
|
|
38
38
|
DocFile,
|
|
39
39
|
DocsMarkdownOption,
|
|
40
40
|
VersionTag,
|
|
41
|
+
DocFrontMatter,
|
|
41
42
|
} from './types';
|
|
42
43
|
import type {RuleSetRule} from 'webpack';
|
|
43
44
|
import {cliDocsVersionCommand} from './cli';
|
|
44
45
|
import {VERSIONS_JSON_FILE} from './constants';
|
|
45
|
-
import {keyBy, mapValues} from 'lodash';
|
|
46
46
|
import {toGlobalDataVersion} from './globalData';
|
|
47
47
|
import {toTagDocListProp} from './props';
|
|
48
48
|
import {
|
|
@@ -196,9 +196,9 @@ export default async function pluginContentDocs(
|
|
|
196
196
|
async function loadVersion(versionMetadata: VersionMetadata) {
|
|
197
197
|
try {
|
|
198
198
|
return await doLoadVersion(versionMetadata);
|
|
199
|
-
} catch (
|
|
199
|
+
} catch (err) {
|
|
200
200
|
logger.error`Loading of version failed for version name=${versionMetadata.versionName}`;
|
|
201
|
-
throw
|
|
201
|
+
throw err;
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
|
|
@@ -217,6 +217,7 @@ export default async function pluginContentDocs(
|
|
|
217
217
|
docLayoutComponent,
|
|
218
218
|
docItemComponent,
|
|
219
219
|
docCategoryGeneratedIndexComponent,
|
|
220
|
+
breadcrumbs,
|
|
220
221
|
} = options;
|
|
221
222
|
const {addRoute, createData, setGlobalData} = actions;
|
|
222
223
|
|
|
@@ -295,6 +296,7 @@ export default async function pluginContentDocs(
|
|
|
295
296
|
setGlobalData<GlobalPluginData>({
|
|
296
297
|
path: normalizeUrl([baseUrl, options.routeBasePath]),
|
|
297
298
|
versions: loadedVersions.map(toGlobalDataVersion),
|
|
299
|
+
breadcrumbs,
|
|
298
300
|
});
|
|
299
301
|
},
|
|
300
302
|
|
|
@@ -309,9 +311,8 @@ export default async function pluginContentDocs(
|
|
|
309
311
|
|
|
310
312
|
function getSourceToPermalink(): SourceToPermalink {
|
|
311
313
|
const allDocs = content.loadedVersions.flatMap((v) => v.docs);
|
|
312
|
-
return
|
|
313
|
-
|
|
314
|
-
(d) => d.permalink,
|
|
314
|
+
return Object.fromEntries(
|
|
315
|
+
allDocs.map(({source, permalink}) => [source, permalink]),
|
|
315
316
|
);
|
|
316
317
|
}
|
|
317
318
|
|
|
@@ -333,7 +334,7 @@ export default async function pluginContentDocs(
|
|
|
333
334
|
function createMDXLoaderRule(): RuleSetRule {
|
|
334
335
|
const contentDirs = versionsMetadata.flatMap(getDocsDirPaths);
|
|
335
336
|
return {
|
|
336
|
-
test:
|
|
337
|
+
test: /\.mdx?$/i,
|
|
337
338
|
include: contentDirs
|
|
338
339
|
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
339
340
|
.map(addTrailingPathSeparator),
|
|
@@ -360,6 +361,15 @@ export default async function pluginContentDocs(
|
|
|
360
361
|
const aliasedPath = aliasedSitePath(mdxPath, siteDir);
|
|
361
362
|
return path.join(dataDir, `${docuHash(aliasedPath)}.json`);
|
|
362
363
|
},
|
|
364
|
+
// Assets allow to convert some relative images paths to
|
|
365
|
+
// require(...) calls
|
|
366
|
+
createAssets: ({
|
|
367
|
+
frontMatter,
|
|
368
|
+
}: {
|
|
369
|
+
frontMatter: DocFrontMatter;
|
|
370
|
+
}) => ({
|
|
371
|
+
image: frontMatter.image,
|
|
372
|
+
}),
|
|
363
373
|
},
|
|
364
374
|
},
|
|
365
375
|
{
|