@docusaurus/plugin-content-docs 2.0.0-beta.17 → 2.0.0-beta.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/categoryGeneratedIndex.js +0 -3
- package/lib/cli.js +3 -5
- package/lib/client/docsClientUtils.d.ts +3 -1
- package/lib/client/docsClientUtils.js +3 -3
- package/lib/client/index.d.ts +3 -1
- package/lib/docs.d.ts +4 -13
- package/lib/docs.js +7 -15
- package/lib/{docFrontMatter.d.ts → frontMatter.d.ts} +3 -1
- package/lib/{docFrontMatter.js → frontMatter.js} +0 -0
- package/lib/globalData.d.ts +2 -6
- package/lib/globalData.js +4 -8
- package/lib/lastUpdate.d.ts +4 -6
- package/lib/lastUpdate.js +13 -4
- package/lib/markdown/index.js +1 -1
- package/lib/markdown/linkify.js +4 -0
- package/lib/numberPrefix.js +16 -21
- package/lib/options.d.ts +3 -5
- package/lib/options.js +4 -3
- package/lib/sidebars/generator.js +33 -17
- package/lib/sidebars/index.js +13 -7
- package/lib/sidebars/postProcessor.js +11 -16
- package/lib/sidebars/processor.d.ts +3 -1
- package/lib/sidebars/processor.js +2 -2
- package/lib/sidebars/types.d.ts +13 -5
- package/lib/sidebars/utils.d.ts +15 -4
- package/lib/sidebars/utils.js +19 -23
- package/lib/sidebars/validation.d.ts +3 -1
- package/lib/sidebars/validation.js +1 -0
- package/lib/slug.js +3 -4
- package/lib/translations.js +19 -21
- package/lib/types.d.ts +9 -6
- package/lib/versions.js +3 -3
- package/package.json +10 -10
- package/src/categoryGeneratedIndex.ts +2 -6
- package/src/cli.ts +3 -5
- package/src/client/docsClientUtils.ts +3 -3
- package/src/client/index.ts +1 -1
- package/src/deps.d.ts +1 -1
- package/src/docs.ts +7 -25
- package/src/{docFrontMatter.ts → frontMatter.ts} +4 -4
- package/src/globalData.ts +5 -6
- package/src/index.ts +1 -2
- package/src/lastUpdate.ts +20 -8
- package/src/markdown/index.ts +1 -3
- package/src/markdown/linkify.ts +4 -0
- package/src/numberPrefix.ts +18 -28
- package/src/options.ts +6 -8
- package/src/plugin-content-docs.d.ts +12 -5
- package/src/sidebars/generator.ts +45 -22
- package/src/sidebars/index.ts +20 -13
- package/src/sidebars/postProcessor.ts +4 -9
- package/src/sidebars/processor.ts +4 -10
- package/src/sidebars/types.ts +5 -4
- package/src/sidebars/utils.ts +39 -43
- package/src/sidebars/validation.ts +4 -3
- package/src/slug.ts +3 -4
- package/src/translations.ts +24 -25
- package/src/types.ts +8 -7
- package/src/versions.ts +5 -5
|
@@ -11,9 +11,6 @@ const utils_1 = require("./sidebars/utils");
|
|
|
11
11
|
const docs_1 = require("./docs");
|
|
12
12
|
function getCategoryGeneratedIndexMetadata({ category, sidebarsUtils, docsById, }) {
|
|
13
13
|
const { sidebarName, previous, next } = sidebarsUtils.getCategoryGeneratedIndexNavigation(category.link.permalink);
|
|
14
|
-
if (!sidebarName) {
|
|
15
|
-
throw new Error('unexpected');
|
|
16
|
-
}
|
|
17
14
|
return {
|
|
18
15
|
title: category.link.title ?? category.label,
|
|
19
16
|
description: category.link.description,
|
package/lib/cli.js
CHANGED
|
@@ -26,8 +26,7 @@ async function createVersionedSidebarFile({ siteDir, pluginId, sidebarPath, vers
|
|
|
26
26
|
if (shouldCreateVersionedSidebarFile) {
|
|
27
27
|
const versionedSidebarsDir = (0, versions_1.getVersionedSidebarsDirPath)(siteDir, pluginId);
|
|
28
28
|
const newSidebarFile = path_1.default.join(versionedSidebarsDir, `version-${version}-sidebars.json`);
|
|
29
|
-
await fs_extra_1.default.
|
|
30
|
-
await fs_extra_1.default.writeFile(newSidebarFile, `${JSON.stringify(sidebars, null, 2)}\n`, 'utf8');
|
|
29
|
+
await fs_extra_1.default.outputFile(newSidebarFile, `${JSON.stringify(sidebars, null, 2)}\n`, 'utf8');
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
32
|
// Tests depend on non-default export for mocking.
|
|
@@ -47,7 +46,7 @@ async function cliDocsVersionCommand(version, siteDir, pluginId, options) {
|
|
|
47
46
|
// Since we are going to create `version-${version}` folder, we need to make
|
|
48
47
|
// sure it's a valid pathname.
|
|
49
48
|
// eslint-disable-next-line no-control-regex
|
|
50
|
-
if (/[<>:"|?*\x00-\x1F]
|
|
49
|
+
if (/[<>:"|?*\x00-\x1F]/.test(version)) {
|
|
51
50
|
throw new Error(`${pluginIdLogPrefix}: invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0.`);
|
|
52
51
|
}
|
|
53
52
|
if (/^\.\.?$/.test(version)) {
|
|
@@ -83,8 +82,7 @@ async function cliDocsVersionCommand(version, siteDir, pluginId, options) {
|
|
|
83
82
|
});
|
|
84
83
|
// Update versions.json file.
|
|
85
84
|
versions.unshift(version);
|
|
86
|
-
await fs_extra_1.default.
|
|
87
|
-
await fs_extra_1.default.writeFile(versionsJSONFile, `${JSON.stringify(versions, null, 2)}\n`);
|
|
85
|
+
await fs_extra_1.default.outputFile(versionsJSONFile, `${JSON.stringify(versions, null, 2)}\n`);
|
|
88
86
|
logger_1.default.success `name=${pluginIdLogPrefix}: version name=${version} created!`;
|
|
89
87
|
}
|
|
90
88
|
exports.cliDocsVersionCommand = cliDocsVersionCommand;
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { GlobalPluginData, GlobalVersion, GetActivePluginOptions, ActivePlugin, ActiveDocContext, DocVersionSuggestions } from '@docusaurus/plugin-content-docs/client';
|
|
8
|
-
export declare function getActivePlugin(
|
|
8
|
+
export declare function getActivePlugin(allPluginData: {
|
|
9
|
+
[pluginId: string]: GlobalPluginData;
|
|
10
|
+
}, pathname: string, options?: GetActivePluginOptions): ActivePlugin | undefined;
|
|
9
11
|
export declare const getLatestVersion: (data: GlobalPluginData) => GlobalVersion;
|
|
10
12
|
export declare const getActiveVersion: (data: GlobalPluginData, pathname: string) => GlobalVersion | undefined;
|
|
11
13
|
export declare const getActiveDocContext: (data: GlobalPluginData, pathname: string) => ActiveDocContext;
|
|
@@ -12,8 +12,8 @@ const router_1 = require("@docusaurus/router");
|
|
|
12
12
|
// get the data of the plugin that is currently "active"
|
|
13
13
|
// ie the docs of that plugin are currently browsed
|
|
14
14
|
// it is useful to support multiple docs plugin instances
|
|
15
|
-
function getActivePlugin(
|
|
16
|
-
const activeEntry = Object.entries(
|
|
15
|
+
function getActivePlugin(allPluginData, pathname, options = {}) {
|
|
16
|
+
const activeEntry = Object.entries(allPluginData)
|
|
17
17
|
// Route sorting: '/android/foo' should match '/android' instead of '/'
|
|
18
18
|
.sort((a, b) => b[1].path.localeCompare(a[1].path))
|
|
19
19
|
.find(([, pluginData]) => !!(0, router_1.matchPath)(pathname, {
|
|
@@ -25,7 +25,7 @@ function getActivePlugin(allPluginDatas, pathname, options = {}) {
|
|
|
25
25
|
? { pluginId: activeEntry[0], pluginData: activeEntry[1] }
|
|
26
26
|
: undefined;
|
|
27
27
|
if (!activePlugin && options.failfast) {
|
|
28
|
-
throw new Error(`Can't find active docs plugin for "${pathname}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(
|
|
28
|
+
throw new Error(`Can't find active docs plugin for "${pathname}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(allPluginData)
|
|
29
29
|
.map((plugin) => plugin.path)
|
|
30
30
|
.join(', ')}`);
|
|
31
31
|
}
|
package/lib/client/index.d.ts
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { GlobalPluginData, GlobalVersion, ActivePlugin, ActiveDocContext, DocVersionSuggestions, GetActivePluginOptions } from '@docusaurus/plugin-content-docs/client';
|
|
8
|
-
export declare const useAllDocsData: () =>
|
|
8
|
+
export declare const useAllDocsData: () => {
|
|
9
|
+
[pluginId: string]: GlobalPluginData;
|
|
10
|
+
};
|
|
9
11
|
export declare const useDocsData: (pluginId: string | undefined) => GlobalPluginData;
|
|
10
12
|
export declare const useActivePlugin: (options?: GetActivePluginOptions) => ActivePlugin | undefined;
|
|
11
13
|
export declare const useActivePluginAndVersion: (options?: GetActivePluginOptions) => {
|
package/lib/docs.d.ts
CHANGED
|
@@ -30,25 +30,16 @@ export declare function getMainDocId({ docs, sidebarsUtils, }: {
|
|
|
30
30
|
sidebarsUtils: SidebarsUtils;
|
|
31
31
|
}): string;
|
|
32
32
|
export declare const isCategoryIndex: CategoryIndexMatcher;
|
|
33
|
-
export declare function toCategoryIndexMatcherParam({ source, sourceDirName, }: Pick<DocMetadataBase, 'source' | 'sourceDirName'>): CategoryIndexMatcherParam;
|
|
34
33
|
/**
|
|
35
34
|
* `guides/sidebar/autogenerated.md` ->
|
|
36
35
|
* `'autogenerated', '.md', ['sidebar', 'guides']`
|
|
37
36
|
*/
|
|
38
|
-
export declare function
|
|
39
|
-
/**
|
|
40
|
-
* The list of directories, from lowest level to highest.
|
|
41
|
-
* If there's no dir name, directories is ['.']
|
|
42
|
-
*/
|
|
43
|
-
directories: string[];
|
|
44
|
-
/** The file name, without extension */
|
|
45
|
-
fileName: string;
|
|
46
|
-
/** The extension, with a leading dot */
|
|
47
|
-
extension: string;
|
|
48
|
-
};
|
|
37
|
+
export declare function toCategoryIndexMatcherParam({ source, sourceDirName, }: Pick<DocMetadataBase, 'source' | 'sourceDirName'>): CategoryIndexMatcherParam;
|
|
49
38
|
export declare function getDocIds(doc: DocMetadataBase): [string, string];
|
|
50
39
|
export declare function createDocsByIdIndex<Doc extends {
|
|
51
40
|
id: string;
|
|
52
41
|
unversionedId: string;
|
|
53
|
-
}>(docs: Doc[]):
|
|
42
|
+
}>(docs: Doc[]): {
|
|
43
|
+
[docId: string]: Doc;
|
|
44
|
+
};
|
|
54
45
|
export {};
|
package/lib/docs.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.createDocsByIdIndex = exports.getDocIds = exports.
|
|
9
|
+
exports.createDocsByIdIndex = exports.getDocIds = exports.toCategoryIndexMatcherParam = exports.isCategoryIndex = exports.getMainDocId = exports.addDocNavigation = exports.processDocMetadata = exports.readVersionDocs = exports.readDocFile = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
12
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
@@ -17,7 +17,7 @@ const slug_1 = tslib_1.__importDefault(require("./slug"));
|
|
|
17
17
|
const constants_1 = require("./constants");
|
|
18
18
|
const versions_1 = require("./versions");
|
|
19
19
|
const numberPrefix_1 = require("./numberPrefix");
|
|
20
|
-
const
|
|
20
|
+
const frontMatter_1 = require("./frontMatter");
|
|
21
21
|
const utils_2 = require("./sidebars/utils");
|
|
22
22
|
async function readLastUpdateData(filePath, options) {
|
|
23
23
|
const { showLastUpdateAuthor, showLastUpdateTime } = options;
|
|
@@ -61,7 +61,7 @@ function doProcessDocMetadata({ docFile, versionMetadata, context, options, }) {
|
|
|
61
61
|
const { source, content, lastUpdate, contentPath, filePath } = docFile;
|
|
62
62
|
const { siteDir, i18n } = context;
|
|
63
63
|
const { frontMatter: unsafeFrontMatter, contentTitle, excerpt, } = (0, utils_1.parseMarkdownString)(content);
|
|
64
|
-
const frontMatter = (0,
|
|
64
|
+
const frontMatter = (0, frontMatter_1.validateDocFrontMatter)(unsafeFrontMatter);
|
|
65
65
|
const { custom_edit_url: customEditURL,
|
|
66
66
|
// Strip number prefixes by default
|
|
67
67
|
// (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
|
|
@@ -248,6 +248,10 @@ const isCategoryIndex = ({ fileName, directories, }) => {
|
|
|
248
248
|
return eligibleDocIndexNames.includes(fileName.toLowerCase());
|
|
249
249
|
};
|
|
250
250
|
exports.isCategoryIndex = isCategoryIndex;
|
|
251
|
+
/**
|
|
252
|
+
* `guides/sidebar/autogenerated.md` ->
|
|
253
|
+
* `'autogenerated', '.md', ['sidebar', 'guides']`
|
|
254
|
+
*/
|
|
251
255
|
function toCategoryIndexMatcherParam({ source, sourceDirName, }) {
|
|
252
256
|
// source + sourceDirName are always posix-style
|
|
253
257
|
return {
|
|
@@ -257,18 +261,6 @@ function toCategoryIndexMatcherParam({ source, sourceDirName, }) {
|
|
|
257
261
|
};
|
|
258
262
|
}
|
|
259
263
|
exports.toCategoryIndexMatcherParam = toCategoryIndexMatcherParam;
|
|
260
|
-
/**
|
|
261
|
-
* `guides/sidebar/autogenerated.md` ->
|
|
262
|
-
* `'autogenerated', '.md', ['sidebar', 'guides']`
|
|
263
|
-
*/
|
|
264
|
-
function splitPath(str) {
|
|
265
|
-
return {
|
|
266
|
-
fileName: path_1.default.parse(str).name,
|
|
267
|
-
extension: path_1.default.parse(str).ext,
|
|
268
|
-
directories: path_1.default.dirname(str).split(path_1.default.sep).reverse(),
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
exports.splitPath = splitPath;
|
|
272
264
|
// Return both doc ids
|
|
273
265
|
// TODO legacy retro-compatibility due to old versioned sidebars using
|
|
274
266
|
// versioned doc ids ("id" should be removed & "versionedId" should be renamed
|
|
@@ -5,4 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { DocFrontMatter } from './types';
|
|
8
|
-
export declare function validateDocFrontMatter(frontMatter:
|
|
8
|
+
export declare function validateDocFrontMatter(frontMatter: {
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}): DocFrontMatter;
|
|
File without changes
|
package/lib/globalData.d.ts
CHANGED
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
8
|
-
import type {
|
|
9
|
-
import type { GlobalVersion, GlobalSidebar, GlobalDoc } from '@docusaurus/plugin-content-docs/client';
|
|
10
|
-
export declare function toGlobalDataDoc(doc: DocMetadata): GlobalDoc;
|
|
11
|
-
export declare function toGlobalDataGeneratedIndex(doc: CategoryGeneratedIndexMetadata): GlobalDoc;
|
|
12
|
-
export declare function toGlobalSidebars(sidebars: Sidebars, version: LoadedVersion): Record<string, GlobalSidebar>;
|
|
7
|
+
import type { LoadedVersion } from './types';
|
|
8
|
+
import type { GlobalVersion } from '@docusaurus/plugin-content-docs/client';
|
|
13
9
|
export declare function toGlobalDataVersion(version: LoadedVersion): GlobalVersion;
|
package/lib/globalData.js
CHANGED
|
@@ -6,11 +6,10 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.toGlobalDataVersion =
|
|
9
|
+
exports.toGlobalDataVersion = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
12
|
-
const utils_1 = require("
|
|
13
|
-
const utils_2 = require("./sidebars/utils");
|
|
12
|
+
const utils_1 = require("./sidebars/utils");
|
|
14
13
|
function toGlobalDataDoc(doc) {
|
|
15
14
|
return {
|
|
16
15
|
id: doc.unversionedId,
|
|
@@ -18,7 +17,6 @@ function toGlobalDataDoc(doc) {
|
|
|
18
17
|
sidebar: doc.sidebar,
|
|
19
18
|
};
|
|
20
19
|
}
|
|
21
|
-
exports.toGlobalDataDoc = toGlobalDataDoc;
|
|
22
20
|
function toGlobalDataGeneratedIndex(doc) {
|
|
23
21
|
return {
|
|
24
22
|
id: doc.slug,
|
|
@@ -26,9 +24,8 @@ function toGlobalDataGeneratedIndex(doc) {
|
|
|
26
24
|
sidebar: doc.sidebar,
|
|
27
25
|
};
|
|
28
26
|
}
|
|
29
|
-
exports.toGlobalDataGeneratedIndex = toGlobalDataGeneratedIndex;
|
|
30
27
|
function toGlobalSidebars(sidebars, version) {
|
|
31
|
-
const { getFirstLink } = (0,
|
|
28
|
+
const { getFirstLink } = (0, utils_1.createSidebarsUtils)(sidebars);
|
|
32
29
|
return lodash_1.default.mapValues(sidebars, (sidebar, sidebarId) => {
|
|
33
30
|
const firstLink = getFirstLink(sidebarId);
|
|
34
31
|
if (!firstLink) {
|
|
@@ -37,14 +34,13 @@ function toGlobalSidebars(sidebars, version) {
|
|
|
37
34
|
return {
|
|
38
35
|
link: {
|
|
39
36
|
path: firstLink.type === 'generated-index'
|
|
40
|
-
?
|
|
37
|
+
? firstLink.permalink
|
|
41
38
|
: version.docs.find((doc) => doc.id === firstLink.id || doc.unversionedId === firstLink.id).permalink,
|
|
42
39
|
label: firstLink.label,
|
|
43
40
|
},
|
|
44
41
|
};
|
|
45
42
|
});
|
|
46
43
|
}
|
|
47
|
-
exports.toGlobalSidebars = toGlobalSidebars;
|
|
48
44
|
function toGlobalDataVersion(version) {
|
|
49
45
|
return {
|
|
50
46
|
name: version.versionName,
|
package/lib/lastUpdate.d.ts
CHANGED
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
declare
|
|
8
|
-
timestamp
|
|
9
|
-
author
|
|
10
|
-
}
|
|
11
|
-
export declare function getFileLastUpdate(filePath?: string): Promise<FileLastUpdateData | null>;
|
|
12
|
-
export {};
|
|
7
|
+
export declare function getFileLastUpdate(filePath?: string): Promise<{
|
|
8
|
+
timestamp: number;
|
|
9
|
+
author: string;
|
|
10
|
+
} | null>;
|
package/lib/lastUpdate.js
CHANGED
|
@@ -11,6 +11,7 @@ const tslib_1 = require("tslib");
|
|
|
11
11
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
12
12
|
const utils_1 = require("@docusaurus/utils");
|
|
13
13
|
let showedGitRequirementError = false;
|
|
14
|
+
let showedFileNotTrackedError = false;
|
|
14
15
|
async function getFileLastUpdate(filePath) {
|
|
15
16
|
if (!filePath) {
|
|
16
17
|
return null;
|
|
@@ -25,12 +26,20 @@ async function getFileLastUpdate(filePath) {
|
|
|
25
26
|
return { timestamp: result.timestamp, author: result.author };
|
|
26
27
|
}
|
|
27
28
|
catch (err) {
|
|
28
|
-
if (err instanceof utils_1.GitNotFoundError
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
if (err instanceof utils_1.GitNotFoundError) {
|
|
30
|
+
if (!showedGitRequirementError) {
|
|
31
|
+
logger_1.default.warn('Sorry, the docs plugin last update options require Git.');
|
|
32
|
+
showedGitRequirementError = true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (err instanceof utils_1.FileNotTrackedError) {
|
|
36
|
+
if (!showedFileNotTrackedError) {
|
|
37
|
+
logger_1.default.warn('Cannot infer the update date for some files, as they are not tracked by git.');
|
|
38
|
+
showedFileNotTrackedError = true;
|
|
39
|
+
}
|
|
31
40
|
}
|
|
32
41
|
else {
|
|
33
|
-
logger_1.default.
|
|
42
|
+
logger_1.default.warn(err);
|
|
34
43
|
}
|
|
35
44
|
return null;
|
|
36
45
|
}
|
package/lib/markdown/index.js
CHANGED
|
@@ -11,6 +11,6 @@ function markdownLoader(source) {
|
|
|
11
11
|
const fileString = source;
|
|
12
12
|
const callback = this.async();
|
|
13
13
|
const options = this.getOptions();
|
|
14
|
-
return
|
|
14
|
+
return callback?.(null, (0, linkify_1.linkify)(fileString, this.resourcePath, options));
|
|
15
15
|
}
|
|
16
16
|
exports.default = markdownLoader;
|
package/lib/markdown/linkify.js
CHANGED
|
@@ -11,6 +11,10 @@ const versions_1 = require("../versions");
|
|
|
11
11
|
const utils_1 = require("@docusaurus/utils");
|
|
12
12
|
function getVersion(filePath, options) {
|
|
13
13
|
const versionFound = options.versionsMetadata.find((version) => (0, versions_1.getDocsDirPaths)(version).some((docsDirPath) => filePath.startsWith(docsDirPath)));
|
|
14
|
+
// At this point, this should never happen, because the MDX loaders' paths are
|
|
15
|
+
// literally using the version content paths; but if we allow sourcing content
|
|
16
|
+
// from outside the docs directory (through the `include` option, for example;
|
|
17
|
+
// is there a compelling use-case?), this would actually be testable
|
|
14
18
|
if (!versionFound) {
|
|
15
19
|
throw new Error(`Unexpected error: Markdown file at "${filePath}" does not belong to any docs version!`);
|
|
16
20
|
}
|
package/lib/numberPrefix.js
CHANGED
|
@@ -8,33 +8,28 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.stripPathNumberPrefixes = exports.stripNumberPrefix = exports.DisabledNumberPrefixParser = exports.DefaultNumberPrefixParser = void 0;
|
|
10
10
|
// Best-effort to avoid parsing some patterns as number prefix
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return new RegExp(`${DateLikePrefixRegex.source}|${VersionLikePrefixRegex.source}`);
|
|
21
|
-
})();
|
|
22
|
-
const NumberPrefixRegex = /^(?<numberPrefix>\d+)(?<separator>\s*[-_.]+\s*)(?<suffix>.*)$/;
|
|
11
|
+
// ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
|
|
12
|
+
// ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
|
|
13
|
+
// Both of them would look like 7.0-foo or 2021-11-foo
|
|
14
|
+
// note: we could try to parse float numbers in filenames, but that is probably
|
|
15
|
+
// not worth it, as a version such as "8.0" can be interpreted as either a
|
|
16
|
+
// version or a float. User can configure her own NumberPrefixParser if she
|
|
17
|
+
// wants 8.0 to be interpreted as a float
|
|
18
|
+
const ignoredPrefixPattern = /^\d+[-_.]\d+/;
|
|
19
|
+
const numberPrefixPattern = /^(?<numberPrefix>\d+)\s*[-_.]+\s*(?<suffix>[^-_.\s].*)$/;
|
|
23
20
|
// 0-myDoc => {filename: myDoc, numberPrefix: 0}
|
|
24
21
|
// 003 - myDoc => {filename: myDoc, numberPrefix: 3}
|
|
25
22
|
const DefaultNumberPrefixParser = (filename) => {
|
|
26
|
-
if (
|
|
23
|
+
if (ignoredPrefixPattern.test(filename)) {
|
|
24
|
+
return { filename, numberPrefix: undefined };
|
|
25
|
+
}
|
|
26
|
+
const match = numberPrefixPattern.exec(filename);
|
|
27
|
+
if (!match) {
|
|
27
28
|
return { filename, numberPrefix: undefined };
|
|
28
29
|
}
|
|
29
|
-
const match = NumberPrefixRegex.exec(filename);
|
|
30
|
-
const cleanFileName = match?.groups?.suffix ?? filename;
|
|
31
|
-
const numberPrefixString = match?.groups?.numberPrefix;
|
|
32
|
-
const numberPrefix = numberPrefixString
|
|
33
|
-
? parseInt(numberPrefixString, 10)
|
|
34
|
-
: undefined;
|
|
35
30
|
return {
|
|
36
|
-
filename:
|
|
37
|
-
numberPrefix,
|
|
31
|
+
filename: match.groups.suffix,
|
|
32
|
+
numberPrefix: parseInt(match.groups.numberPrefix, 10),
|
|
38
33
|
};
|
|
39
34
|
};
|
|
40
35
|
exports.DefaultNumberPrefixParser = DefaultNumberPrefixParser;
|
package/lib/options.d.ts
CHANGED
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import type { PluginOptions } from '@docusaurus/plugin-content-docs';
|
|
8
|
-
import {
|
|
9
|
-
import type { OptionValidationContext, ValidationResult } from '@docusaurus/types';
|
|
7
|
+
import type { PluginOptions, Options } from '@docusaurus/plugin-content-docs';
|
|
8
|
+
import type { OptionValidationContext } from '@docusaurus/types';
|
|
10
9
|
export declare const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'>;
|
|
11
|
-
export declare
|
|
12
|
-
export declare function validateOptions({ validate, options: userOptions, }: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions>;
|
|
10
|
+
export declare function validateOptions({ validate, options: userOptions, }: OptionValidationContext<Options, PluginOptions>): PluginOptions;
|
package/lib/options.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.validateOptions = exports.
|
|
9
|
+
exports.validateOptions = exports.DEFAULT_OPTIONS = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
12
12
|
const utils_1 = require("@docusaurus/utils");
|
|
@@ -54,7 +54,7 @@ const VersionOptionsSchema = utils_validation_1.Joi.object({
|
|
|
54
54
|
const VersionsOptionsSchema = utils_validation_1.Joi.object()
|
|
55
55
|
.pattern(utils_validation_1.Joi.string().required(), VersionOptionsSchema)
|
|
56
56
|
.default(exports.DEFAULT_OPTIONS.versions);
|
|
57
|
-
|
|
57
|
+
const OptionsSchema = utils_validation_1.Joi.object({
|
|
58
58
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
59
59
|
editUrl: utils_validation_1.Joi.alternatives().try(utils_validation_1.URISchema, utils_validation_1.Joi.function()),
|
|
60
60
|
editCurrentVersion: utils_validation_1.Joi.boolean().default(exports.DEFAULT_OPTIONS.editCurrentVersion),
|
|
@@ -64,6 +64,7 @@ exports.OptionsSchema = utils_validation_1.Joi.object({
|
|
|
64
64
|
// .allow('') ""
|
|
65
65
|
.default(exports.DEFAULT_OPTIONS.routeBasePath),
|
|
66
66
|
tagsBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.tagsBasePath),
|
|
67
|
+
// @ts-expect-error: deprecated
|
|
67
68
|
homePageId: utils_validation_1.Joi.any().forbidden().messages({
|
|
68
69
|
'any.unknown': 'The docs plugin option homePageId is not supported anymore. To make a doc the "home", please add "slug: /" in its front matter. See: https://docusaurus.io/docs/next/docs-introduction#home-page-docs',
|
|
69
70
|
}),
|
|
@@ -121,7 +122,7 @@ function validateOptions({ validate, options: userOptions, }) {
|
|
|
121
122
|
};
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
|
-
const normalizedOptions = validate(
|
|
125
|
+
const normalizedOptions = validate(OptionsSchema, options);
|
|
125
126
|
if (normalizedOptions.admonitions) {
|
|
126
127
|
normalizedOptions.remarkPlugins = normalizedOptions.remarkPlugins.concat([
|
|
127
128
|
[remark_admonitions_1.default, normalizedOptions.admonitions],
|
|
@@ -27,7 +27,9 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
|
|
|
27
27
|
const getDoc = (docId) => {
|
|
28
28
|
const doc = findDoc(docId);
|
|
29
29
|
if (!doc) {
|
|
30
|
-
throw new Error(`Can't find any doc with
|
|
30
|
+
throw new Error(`Can't find any doc with ID ${docId}.
|
|
31
|
+
Available doc IDs:
|
|
32
|
+
- ${Object.keys(docsById).join('\n- ')}`);
|
|
31
33
|
}
|
|
32
34
|
return doc;
|
|
33
35
|
};
|
|
@@ -103,8 +105,6 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
|
|
|
103
105
|
}
|
|
104
106
|
function createCategoryItem(dir, fullPath, folderName) {
|
|
105
107
|
const categoryMetadata = categoriesMetadata[(0, utils_1.posixPath)(path_1.default.join(autogenDir, fullPath))];
|
|
106
|
-
const className = categoryMetadata?.className;
|
|
107
|
-
const { filename, numberPrefix } = numberPrefixParser(folderName);
|
|
108
108
|
const allItems = Object.entries(dir).map(([key, content]) => dirToItem(content, key, `${fullPath}/${key}`));
|
|
109
109
|
// Try to match a doc inside the category folder,
|
|
110
110
|
// using the "local id" (myDoc) or "qualified id" (dirName/myDoc)
|
|
@@ -120,35 +120,51 @@ const DefaultSidebarItemsGenerator = async ({ numberPrefixParser, isCategoryInde
|
|
|
120
120
|
return isCategoryIndex((0, docs_1.toCategoryIndexMatcherParam)(doc));
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
|
-
function
|
|
123
|
+
// In addition to the ID, this function also retrieves metadata of the
|
|
124
|
+
// linked doc that could be used as fallback values for category metadata
|
|
125
|
+
function getCategoryLinkedDocMetadata() {
|
|
124
126
|
const link = categoryMetadata?.link;
|
|
125
|
-
if (link !== undefined) {
|
|
126
|
-
if (link && link.type === 'doc') {
|
|
127
|
-
return findDocByLocalId(link.id)?.id || getDoc(link.id).id;
|
|
128
|
-
}
|
|
127
|
+
if (link !== undefined && link?.type !== 'doc') {
|
|
129
128
|
// If a link is explicitly specified, we won't apply conventions
|
|
130
129
|
return undefined;
|
|
131
130
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
const id = link
|
|
132
|
+
? findDocByLocalId(link.id)?.id ?? getDoc(link.id).id
|
|
133
|
+
: findConventionalCategoryDocLink()?.id;
|
|
134
|
+
if (!id) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
const doc = getDoc(id);
|
|
138
|
+
return {
|
|
139
|
+
id,
|
|
140
|
+
position: doc.sidebarPosition,
|
|
141
|
+
label: doc.frontMatter.sidebar_label ?? doc.title,
|
|
142
|
+
customProps: doc.frontMatter.sidebar_custom_props,
|
|
143
|
+
className: doc.frontMatter.sidebar_class_name,
|
|
144
|
+
};
|
|
135
145
|
}
|
|
136
|
-
const
|
|
137
|
-
const link =
|
|
146
|
+
const categoryLinkedDoc = getCategoryLinkedDocMetadata();
|
|
147
|
+
const link = categoryLinkedDoc
|
|
138
148
|
? {
|
|
139
149
|
type: 'doc',
|
|
140
|
-
id:
|
|
150
|
+
id: categoryLinkedDoc.id, // We "remap" a potentially "local id" to a "qualified id"
|
|
141
151
|
}
|
|
142
152
|
: categoryMetadata?.link;
|
|
143
153
|
// If a doc is linked, remove it from the category subItems
|
|
144
|
-
const items = allItems.filter((item) => !(item.type === 'doc' && item.id ===
|
|
154
|
+
const items = allItems.filter((item) => !(item.type === 'doc' && item.id === categoryLinkedDoc?.id));
|
|
155
|
+
const className = categoryMetadata?.className ?? categoryLinkedDoc?.className;
|
|
156
|
+
const customProps = categoryMetadata?.customProps ?? categoryLinkedDoc?.customProps;
|
|
157
|
+
const { filename, numberPrefix } = numberPrefixParser(folderName);
|
|
145
158
|
return {
|
|
146
159
|
type: 'category',
|
|
147
|
-
label: categoryMetadata?.label ?? filename,
|
|
160
|
+
label: categoryMetadata?.label ?? categoryLinkedDoc?.label ?? filename,
|
|
148
161
|
collapsible: categoryMetadata?.collapsible,
|
|
149
162
|
collapsed: categoryMetadata?.collapsed,
|
|
150
|
-
position: categoryMetadata?.position ??
|
|
163
|
+
position: categoryMetadata?.position ??
|
|
164
|
+
categoryLinkedDoc?.position ??
|
|
165
|
+
numberPrefix,
|
|
151
166
|
source: folderName,
|
|
167
|
+
...(customProps !== undefined && { customProps }),
|
|
152
168
|
...(className !== undefined && { className }),
|
|
153
169
|
items,
|
|
154
170
|
...(link && { link }),
|
package/lib/sidebars/index.js
CHANGED
|
@@ -43,7 +43,7 @@ async function readCategoriesMetadata(contentPath) {
|
|
|
43
43
|
});
|
|
44
44
|
const categoryToFile = lodash_1.default.groupBy(categoryFiles, path_1.default.dirname);
|
|
45
45
|
return (0, combine_promises_1.default)(lodash_1.default.mapValues(categoryToFile, async (files, folder) => {
|
|
46
|
-
const
|
|
46
|
+
const filePath = files[0];
|
|
47
47
|
if (files.length > 1) {
|
|
48
48
|
logger_1.default.warn `There are more than one category metadata files for path=${folder}: ${files.join(', ')}. The behavior is undetermined.`;
|
|
49
49
|
}
|
|
@@ -78,11 +78,17 @@ async function loadSidebarsFileUnsafe(sidebarFilePath) {
|
|
|
78
78
|
exports.loadSidebarsFileUnsafe = loadSidebarsFileUnsafe;
|
|
79
79
|
// Note: sidebarFilePath must be absolute, use resolveSidebarPathOption
|
|
80
80
|
async function loadSidebars(sidebarFilePath, options) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
try {
|
|
82
|
+
const sidebarsConfig = await loadSidebarsFileUnsafe(sidebarFilePath);
|
|
83
|
+
const normalizedSidebars = (0, normalization_1.normalizeSidebars)(sidebarsConfig);
|
|
84
|
+
(0, validation_1.validateSidebars)(normalizedSidebars);
|
|
85
|
+
const categoriesMetadata = await readCategoriesMetadata(options.version.contentPath);
|
|
86
|
+
const processedSidebars = await (0, processor_1.processSidebars)(normalizedSidebars, categoriesMetadata, options);
|
|
87
|
+
return (0, postProcessor_1.postProcessSidebars)(processedSidebars, options);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
logger_1.default.error `Sidebars file at path=${sidebarFilePath} failed to be loaded.`;
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
87
93
|
}
|
|
88
94
|
exports.loadSidebars = loadSidebars;
|
|
@@ -39,22 +39,17 @@ function postProcessSidebarItem(item, params) {
|
|
|
39
39
|
if (!category.link) {
|
|
40
40
|
throw new Error(`Sidebar category ${item.label} has neither any subitem nor a link. This makes this item not able to link to anything.`);
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
href: category.link.permalink,
|
|
54
|
-
};
|
|
55
|
-
default:
|
|
56
|
-
throw new Error('Unexpected sidebar category link type');
|
|
57
|
-
}
|
|
42
|
+
return category.link.type === 'doc'
|
|
43
|
+
? {
|
|
44
|
+
type: 'doc',
|
|
45
|
+
label: category.label,
|
|
46
|
+
id: category.link.id,
|
|
47
|
+
}
|
|
48
|
+
: {
|
|
49
|
+
type: 'link',
|
|
50
|
+
label: category.label,
|
|
51
|
+
href: category.link.permalink,
|
|
52
|
+
};
|
|
58
53
|
}
|
|
59
54
|
// A non-collapsible category can't be collapsed!
|
|
60
55
|
if (category.collapsible === false) {
|
|
@@ -5,4 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { NormalizedSidebars, ProcessedSidebars, SidebarProcessorParams, CategoryMetadataFile } from './types';
|
|
8
|
-
export declare function processSidebars(unprocessedSidebars: NormalizedSidebars, categoriesMetadata:
|
|
8
|
+
export declare function processSidebars(unprocessedSidebars: NormalizedSidebars, categoriesMetadata: {
|
|
9
|
+
[filePath: string]: CategoryMetadataFile;
|
|
10
|
+
}, params: SidebarProcessorParams): Promise<ProcessedSidebars>;
|
|
@@ -17,6 +17,7 @@ function toSidebarItemsGeneratorDoc(doc) {
|
|
|
17
17
|
return lodash_1.default.pick(doc, [
|
|
18
18
|
'id',
|
|
19
19
|
'unversionedId',
|
|
20
|
+
'title',
|
|
20
21
|
'frontMatter',
|
|
21
22
|
'source',
|
|
22
23
|
'sourceDirName',
|
|
@@ -29,7 +30,7 @@ function toSidebarItemsGeneratorVersion(version) {
|
|
|
29
30
|
// Handle the generation of autogenerated sidebar items and other
|
|
30
31
|
// post-processing checks
|
|
31
32
|
async function processSidebar(unprocessedSidebar, categoriesMetadata, params) {
|
|
32
|
-
const { sidebarItemsGenerator, numberPrefixParser, docs, version
|
|
33
|
+
const { sidebarItemsGenerator, numberPrefixParser, docs, version } = params;
|
|
33
34
|
// Just a minor lazy transformation optimization
|
|
34
35
|
const getSidebarItemsGeneratorDocsAndVersion = lodash_1.default.memoize(() => ({
|
|
35
36
|
docs: docs.map(toSidebarItemsGeneratorDoc),
|
|
@@ -42,7 +43,6 @@ async function processSidebar(unprocessedSidebar, categoriesMetadata, params) {
|
|
|
42
43
|
defaultSidebarItemsGenerator: generator_1.DefaultSidebarItemsGenerator,
|
|
43
44
|
isCategoryIndex: docs_1.isCategoryIndex,
|
|
44
45
|
...getSidebarItemsGeneratorDocsAndVersion(),
|
|
45
|
-
options: sidebarOptions,
|
|
46
46
|
categoriesMetadata,
|
|
47
47
|
});
|
|
48
48
|
// Process again... weird but sidebar item generated might generate some
|