@docusaurus/plugin-content-docs 3.1.1 → 3.2.0
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/client/index.js +10 -3
- package/lib/docs.js +3 -54
- package/lib/frontMatter.d.ts +1 -6
- package/lib/frontMatter.js +5 -14
- package/lib/routes.js +13 -6
- package/lib/sidebars/generator.js +3 -3
- package/lib/slug.js +2 -1
- package/package.json +10 -9
- package/src/client/index.ts +14 -4
- package/src/docs.ts +2 -75
- package/src/frontMatter.ts +3 -14
- package/src/plugin-content-docs.d.ts +5 -20
- package/src/routes.ts +27 -9
- package/src/sidebars/generator.ts +1 -1
- package/src/slug.ts +2 -6
- package/lib/lastUpdate.d.ts +0 -10
- package/lib/lastUpdate.js +0 -47
- package/src/lastUpdate.ts +0 -51
package/lib/client/index.js
CHANGED
|
@@ -13,9 +13,16 @@ const StableEmptyObject = {};
|
|
|
13
13
|
// In blog-only mode, docs hooks are still used by the theme. We need a fail-
|
|
14
14
|
// safe fallback when the docs plugin is not in use
|
|
15
15
|
export const useAllDocsData = () => useAllPluginInstancesData('docusaurus-plugin-content-docs') ?? StableEmptyObject;
|
|
16
|
-
export const useDocsData = (pluginId) =>
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
export const useDocsData = (pluginId) => {
|
|
17
|
+
try {
|
|
18
|
+
return usePluginData('docusaurus-plugin-content-docs', pluginId, {
|
|
19
|
+
failfast: true,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw new Error(`You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled${pluginId === 'Default' ? '' : ` (pluginId=${pluginId}`}`, { cause: error });
|
|
24
|
+
}
|
|
25
|
+
};
|
|
19
26
|
// TODO this feature should be provided by docusaurus core
|
|
20
27
|
export function useActivePlugin(options = {}) {
|
|
21
28
|
const data = useAllDocsData();
|
package/lib/docs.js
CHANGED
|
@@ -11,44 +11,11 @@ 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"));
|
|
13
13
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
14
|
-
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
15
14
|
const utils_1 = require("@docusaurus/utils");
|
|
16
|
-
const
|
|
15
|
+
const frontMatter_1 = require("./frontMatter");
|
|
17
16
|
const slug_1 = tslib_1.__importDefault(require("./slug"));
|
|
18
17
|
const numberPrefix_1 = require("./numberPrefix");
|
|
19
|
-
const frontMatter_1 = require("./frontMatter");
|
|
20
18
|
const utils_2 = require("./sidebars/utils");
|
|
21
|
-
async function readLastUpdateData(filePath, options, lastUpdateFrontMatter) {
|
|
22
|
-
const { showLastUpdateAuthor, showLastUpdateTime } = options;
|
|
23
|
-
if (showLastUpdateAuthor || showLastUpdateTime) {
|
|
24
|
-
const frontMatterTimestamp = lastUpdateFrontMatter?.date
|
|
25
|
-
? new Date(lastUpdateFrontMatter.date).getTime() / 1000
|
|
26
|
-
: undefined;
|
|
27
|
-
if (lastUpdateFrontMatter?.author && lastUpdateFrontMatter.date) {
|
|
28
|
-
return {
|
|
29
|
-
lastUpdatedAt: frontMatterTimestamp,
|
|
30
|
-
lastUpdatedBy: lastUpdateFrontMatter.author,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
// Use fake data in dev for faster development.
|
|
34
|
-
const fileLastUpdateData = process.env.NODE_ENV === 'production'
|
|
35
|
-
? await (0, lastUpdate_1.getFileLastUpdate)(filePath)
|
|
36
|
-
: {
|
|
37
|
-
author: 'Author',
|
|
38
|
-
timestamp: 1539502055,
|
|
39
|
-
};
|
|
40
|
-
const { author, timestamp } = fileLastUpdateData ?? {};
|
|
41
|
-
return {
|
|
42
|
-
lastUpdatedBy: showLastUpdateAuthor
|
|
43
|
-
? lastUpdateFrontMatter?.author ?? author
|
|
44
|
-
: undefined,
|
|
45
|
-
lastUpdatedAt: showLastUpdateTime
|
|
46
|
-
? frontMatterTimestamp ?? timestamp
|
|
47
|
-
: undefined,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
return {};
|
|
51
|
-
}
|
|
52
19
|
async function readDocFile(versionMetadata, source) {
|
|
53
20
|
const contentPath = await (0, utils_1.getFolderContainingFile)((0, utils_1.getContentPathList)(versionMetadata), source);
|
|
54
21
|
const filePath = path_1.default.join(contentPath, source);
|
|
@@ -66,7 +33,7 @@ async function readVersionDocs(versionMetadata, options) {
|
|
|
66
33
|
exports.readVersionDocs = readVersionDocs;
|
|
67
34
|
async function doProcessDocMetadata({ docFile, versionMetadata, context, options, env, }) {
|
|
68
35
|
const { source, content, contentPath, filePath } = docFile;
|
|
69
|
-
const { siteDir,
|
|
36
|
+
const { siteDir, siteConfig: { markdown: { parseFrontMatter }, }, } = context;
|
|
70
37
|
const { frontMatter: unsafeFrontMatter, contentTitle, excerpt, } = await (0, utils_1.parseMarkdownFile)({
|
|
71
38
|
filePath,
|
|
72
39
|
fileContent: content,
|
|
@@ -78,7 +45,7 @@ async function doProcessDocMetadata({ docFile, versionMetadata, context, options
|
|
|
78
45
|
// (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
|
|
79
46
|
// but allow to disable this behavior with front matter
|
|
80
47
|
parse_number_prefixes: parseNumberPrefixes = true, last_update: lastUpdateFrontMatter, } = frontMatter;
|
|
81
|
-
const lastUpdate = await readLastUpdateData(filePath, options, lastUpdateFrontMatter);
|
|
48
|
+
const lastUpdate = await (0, utils_1.readLastUpdateData)(filePath, options, lastUpdateFrontMatter);
|
|
82
49
|
// E.g. api/plugins/myDoc -> myDoc; myDoc -> myDoc
|
|
83
50
|
const sourceFileNameWithoutExtension = path_1.default.basename(source, path_1.default.extname(source));
|
|
84
51
|
// E.g. api/plugins/myDoc -> api/plugins; myDoc -> .
|
|
@@ -141,21 +108,6 @@ async function doProcessDocMetadata({ docFile, versionMetadata, context, options
|
|
|
141
108
|
}
|
|
142
109
|
const draft = (0, utils_1.isDraft)({ env, frontMatter });
|
|
143
110
|
const unlisted = (0, utils_1.isUnlisted)({ env, frontMatter });
|
|
144
|
-
const formatDate = (locale, date, calendar) => {
|
|
145
|
-
try {
|
|
146
|
-
return new Intl.DateTimeFormat(locale, {
|
|
147
|
-
day: 'numeric',
|
|
148
|
-
month: 'short',
|
|
149
|
-
year: 'numeric',
|
|
150
|
-
timeZone: 'UTC',
|
|
151
|
-
calendar,
|
|
152
|
-
}).format(date);
|
|
153
|
-
}
|
|
154
|
-
catch (err) {
|
|
155
|
-
logger_1.default.error `Can't format docs lastUpdatedAt date "${String(date)}"`;
|
|
156
|
-
throw err;
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
111
|
// Assign all of object properties during instantiation (if possible) for
|
|
160
112
|
// NodeJS optimization.
|
|
161
113
|
// Adding properties to object after instantiation will cause hidden
|
|
@@ -175,9 +127,6 @@ async function doProcessDocMetadata({ docFile, versionMetadata, context, options
|
|
|
175
127
|
version: versionMetadata.versionName,
|
|
176
128
|
lastUpdatedBy: lastUpdate.lastUpdatedBy,
|
|
177
129
|
lastUpdatedAt: lastUpdate.lastUpdatedAt,
|
|
178
|
-
formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
|
|
179
|
-
? formatDate(i18n.currentLocale, new Date(lastUpdate.lastUpdatedAt * 1000), i18n.localeConfigs[i18n.currentLocale].calendar)
|
|
180
|
-
: undefined,
|
|
181
130
|
sidebarPosition,
|
|
182
131
|
frontMatter,
|
|
183
132
|
};
|
package/lib/frontMatter.d.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
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
1
|
import type { DocFrontMatter } from '@docusaurus/plugin-content-docs';
|
|
2
|
+
export declare const DocFrontMatterSchema: import("joi").ObjectSchema<DocFrontMatter>;
|
|
8
3
|
export declare function validateDocFrontMatter(frontMatter: {
|
|
9
4
|
[key: string]: unknown;
|
|
10
5
|
}): DocFrontMatter;
|
package/lib/frontMatter.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateDocFrontMatter = exports.DocFrontMatterSchema = void 0;
|
|
2
4
|
/**
|
|
3
5
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
6
|
*
|
|
5
7
|
* This source code is licensed under the MIT license found in the
|
|
6
8
|
* LICENSE file in the root directory of this source tree.
|
|
7
9
|
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.validateDocFrontMatter = void 0;
|
|
10
10
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
|
-
const FrontMatterLastUpdateErrorMessage = '{{#label}} does not look like a valid front matter FileChange object. Please use a FileChange object (with an author and/or date).';
|
|
12
11
|
// NOTE: we don't add any default value on purpose here
|
|
13
12
|
// We don't want default values to magically appear in doc metadata and props
|
|
14
13
|
// While the user did not provide those values explicitly
|
|
15
14
|
// We use default values in code instead
|
|
16
|
-
|
|
15
|
+
exports.DocFrontMatterSchema = utils_validation_1.JoiFrontMatter.object({
|
|
17
16
|
id: utils_validation_1.JoiFrontMatter.string(),
|
|
18
17
|
// See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
|
|
19
18
|
title: utils_validation_1.JoiFrontMatter.string().allow(''),
|
|
@@ -36,19 +35,11 @@ const DocFrontMatterSchema = utils_validation_1.JoiFrontMatter.object({
|
|
|
36
35
|
pagination_next: utils_validation_1.JoiFrontMatter.string().allow(null),
|
|
37
36
|
pagination_prev: utils_validation_1.JoiFrontMatter.string().allow(null),
|
|
38
37
|
...utils_validation_1.FrontMatterTOCHeadingLevels,
|
|
39
|
-
last_update: utils_validation_1.
|
|
40
|
-
author: utils_validation_1.JoiFrontMatter.string(),
|
|
41
|
-
date: utils_validation_1.JoiFrontMatter.date().raw(),
|
|
42
|
-
})
|
|
43
|
-
.or('author', 'date')
|
|
44
|
-
.messages({
|
|
45
|
-
'object.missing': FrontMatterLastUpdateErrorMessage,
|
|
46
|
-
'object.base': FrontMatterLastUpdateErrorMessage,
|
|
47
|
-
}),
|
|
38
|
+
last_update: utils_validation_1.FrontMatterLastUpdateSchema,
|
|
48
39
|
})
|
|
49
40
|
.unknown()
|
|
50
41
|
.concat(utils_validation_1.ContentVisibilitySchema);
|
|
51
42
|
function validateDocFrontMatter(frontMatter) {
|
|
52
|
-
return (0, utils_validation_1.validateFrontMatter)(frontMatter, DocFrontMatterSchema);
|
|
43
|
+
return (0, utils_validation_1.validateFrontMatter)(frontMatter, exports.DocFrontMatterSchema);
|
|
53
44
|
}
|
|
54
45
|
exports.validateDocFrontMatter = validateDocFrontMatter;
|
package/lib/routes.js
CHANGED
|
@@ -13,6 +13,12 @@ const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
|
13
13
|
const utils_1 = require("@docusaurus/utils");
|
|
14
14
|
const props_1 = require("./props");
|
|
15
15
|
const tags_1 = require("./tags");
|
|
16
|
+
function createDocRouteMetadata(docMeta) {
|
|
17
|
+
return {
|
|
18
|
+
sourceFilePath: (0, utils_1.aliasedSitePathToRelativePath)(docMeta.source),
|
|
19
|
+
lastUpdatedAt: docMeta.lastUpdatedAt,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
16
22
|
async function buildVersionCategoryGeneratedIndexRoutes({ version, actions, options, aliasedSource, }) {
|
|
17
23
|
const slugs = (0, utils_1.createSlugger)();
|
|
18
24
|
async function buildCategoryGeneratedIndexRoute(categoryGeneratedIndex) {
|
|
@@ -34,23 +40,24 @@ async function buildVersionCategoryGeneratedIndexRoutes({ version, actions, opti
|
|
|
34
40
|
return Promise.all(version.categoryGeneratedIndices.map(buildCategoryGeneratedIndexRoute));
|
|
35
41
|
}
|
|
36
42
|
async function buildVersionDocRoutes({ version, actions, options, }) {
|
|
37
|
-
return Promise.all(version.docs.map(async (
|
|
43
|
+
return Promise.all(version.docs.map(async (doc) => {
|
|
38
44
|
await actions.createData(
|
|
39
45
|
// Note that this created data path must be in sync with
|
|
40
46
|
// metadataPath provided to mdx-loader.
|
|
41
|
-
`${(0, utils_1.docuHash)(
|
|
47
|
+
`${(0, utils_1.docuHash)(doc.source)}.json`, JSON.stringify(doc, null, 2));
|
|
42
48
|
const docRoute = {
|
|
43
|
-
path:
|
|
49
|
+
path: doc.permalink,
|
|
44
50
|
component: options.docItemComponent,
|
|
45
51
|
exact: true,
|
|
46
52
|
modules: {
|
|
47
|
-
content:
|
|
53
|
+
content: doc.source,
|
|
48
54
|
},
|
|
55
|
+
metadata: createDocRouteMetadata(doc),
|
|
49
56
|
// Because the parent (DocRoot) comp need to access it easily
|
|
50
57
|
// This permits to render the sidebar once without unmount/remount when
|
|
51
58
|
// navigating (and preserve sidebar state)
|
|
52
|
-
...(
|
|
53
|
-
sidebar:
|
|
59
|
+
...(doc.sidebar && {
|
|
60
|
+
sidebar: doc.sidebar,
|
|
54
61
|
}),
|
|
55
62
|
};
|
|
56
63
|
return docRoute;
|
|
@@ -11,7 +11,7 @@ const tslib_1 = require("tslib");
|
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
12
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
13
13
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
14
|
-
const
|
|
14
|
+
const utils_common_1 = require("@docusaurus/utils-common");
|
|
15
15
|
const docs_1 = require("../docs");
|
|
16
16
|
const BreadcrumbSeparator = '/';
|
|
17
17
|
// Just an alias to the make code more explicit
|
|
@@ -45,7 +45,7 @@ Available doc IDs:
|
|
|
45
45
|
autogenDir === '.' ||
|
|
46
46
|
// Autogen dir is not . and doc is in subfolder
|
|
47
47
|
// "api/myDoc" startsWith "api/" (note "api2/myDoc" is not included)
|
|
48
|
-
doc.sourceDirName.startsWith((0,
|
|
48
|
+
doc.sourceDirName.startsWith((0, utils_common_1.addTrailingSlash)(autogenDir)));
|
|
49
49
|
}
|
|
50
50
|
const docs = allDocs.filter(isInAutogeneratedDir);
|
|
51
51
|
if (docs.length === 0) {
|
|
@@ -66,7 +66,7 @@ Available doc IDs:
|
|
|
66
66
|
return autogenDir === doc.sourceDirName
|
|
67
67
|
? []
|
|
68
68
|
: doc.sourceDirName
|
|
69
|
-
.replace((0,
|
|
69
|
+
.replace((0, utils_common_1.addTrailingSlash)(autogenDir), '')
|
|
70
70
|
.split(BreadcrumbSeparator);
|
|
71
71
|
}
|
|
72
72
|
const treeRoot = {};
|
package/lib/slug.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
const utils_1 = require("@docusaurus/utils");
|
|
10
|
+
const utils_common_1 = require("@docusaurus/utils-common");
|
|
10
11
|
const numberPrefix_1 = require("./numberPrefix");
|
|
11
12
|
const docs_1 = require("./docs");
|
|
12
13
|
function getSlug({ baseID, frontMatterSlug, source, sourceDirName, stripDirNumberPrefixes = true, numberPrefixParser = numberPrefix_1.DefaultNumberPrefixParser, }) {
|
|
@@ -16,7 +17,7 @@ function getSlug({ baseID, frontMatterSlug, source, sourceDirName, stripDirNumbe
|
|
|
16
17
|
: sourceDirName;
|
|
17
18
|
const resolveDirname = sourceDirName === '.'
|
|
18
19
|
? '/'
|
|
19
|
-
: (0,
|
|
20
|
+
: (0, utils_common_1.addLeadingSlash)((0, utils_common_1.addTrailingSlash)(dirNameStripped));
|
|
20
21
|
return resolveDirname;
|
|
21
22
|
}
|
|
22
23
|
function computeSlug() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-docs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Docs plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -35,13 +35,14 @@
|
|
|
35
35
|
},
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@docusaurus/core": "3.
|
|
39
|
-
"@docusaurus/logger": "3.
|
|
40
|
-
"@docusaurus/mdx-loader": "3.
|
|
41
|
-
"@docusaurus/module-type-aliases": "3.
|
|
42
|
-
"@docusaurus/types": "3.
|
|
43
|
-
"@docusaurus/utils": "3.
|
|
44
|
-
"@docusaurus/utils-
|
|
38
|
+
"@docusaurus/core": "3.2.0",
|
|
39
|
+
"@docusaurus/logger": "3.2.0",
|
|
40
|
+
"@docusaurus/mdx-loader": "3.2.0",
|
|
41
|
+
"@docusaurus/module-type-aliases": "3.2.0",
|
|
42
|
+
"@docusaurus/types": "3.2.0",
|
|
43
|
+
"@docusaurus/utils": "3.2.0",
|
|
44
|
+
"@docusaurus/utils-common": "3.2.0",
|
|
45
|
+
"@docusaurus/utils-validation": "3.2.0",
|
|
45
46
|
"@types/react-router-config": "^5.0.7",
|
|
46
47
|
"combine-promises": "^1.1.0",
|
|
47
48
|
"fs-extra": "^11.1.1",
|
|
@@ -65,5 +66,5 @@
|
|
|
65
66
|
"engines": {
|
|
66
67
|
"node": ">=18.0"
|
|
67
68
|
},
|
|
68
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "5af143651b26b39761361acd96e9c5be7ba0cb25"
|
|
69
70
|
}
|
package/src/client/index.ts
CHANGED
|
@@ -86,10 +86,20 @@ export const useAllDocsData = (): {[pluginId: string]: GlobalPluginData} =>
|
|
|
86
86
|
}
|
|
87
87
|
| undefined) ?? StableEmptyObject;
|
|
88
88
|
|
|
89
|
-
export const useDocsData = (pluginId: string | undefined): GlobalPluginData =>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
export const useDocsData = (pluginId: string | undefined): GlobalPluginData => {
|
|
90
|
+
try {
|
|
91
|
+
return usePluginData('docusaurus-plugin-content-docs', pluginId, {
|
|
92
|
+
failfast: true,
|
|
93
|
+
}) as GlobalPluginData;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled${
|
|
97
|
+
pluginId === 'Default' ? '' : ` (pluginId=${pluginId}`
|
|
98
|
+
}`,
|
|
99
|
+
{cause: error as Error},
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
93
103
|
|
|
94
104
|
// TODO this feature should be provided by docusaurus core
|
|
95
105
|
export function useActivePlugin(
|
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 _ from 'lodash';
|
|
11
|
-
import logger from '@docusaurus/logger';
|
|
12
11
|
import {
|
|
13
12
|
aliasedSitePath,
|
|
14
13
|
getEditUrl,
|
|
@@ -21,12 +20,11 @@ import {
|
|
|
21
20
|
normalizeFrontMatterTags,
|
|
22
21
|
isUnlisted,
|
|
23
22
|
isDraft,
|
|
23
|
+
readLastUpdateData,
|
|
24
24
|
} from '@docusaurus/utils';
|
|
25
|
-
|
|
26
|
-
import {getFileLastUpdate} from './lastUpdate';
|
|
25
|
+
import {validateDocFrontMatter} from './frontMatter';
|
|
27
26
|
import getSlug from './slug';
|
|
28
27
|
import {stripPathNumberPrefixes} from './numberPrefix';
|
|
29
|
-
import {validateDocFrontMatter} from './frontMatter';
|
|
30
28
|
import {toDocNavigationLink, toNavigationLink} from './sidebars/utils';
|
|
31
29
|
import type {
|
|
32
30
|
MetadataOptions,
|
|
@@ -35,61 +33,13 @@ import type {
|
|
|
35
33
|
DocMetadataBase,
|
|
36
34
|
DocMetadata,
|
|
37
35
|
PropNavigationLink,
|
|
38
|
-
LastUpdateData,
|
|
39
36
|
VersionMetadata,
|
|
40
37
|
LoadedVersion,
|
|
41
|
-
FileChange,
|
|
42
38
|
} from '@docusaurus/plugin-content-docs';
|
|
43
39
|
import type {LoadContext} from '@docusaurus/types';
|
|
44
40
|
import type {SidebarsUtils} from './sidebars/utils';
|
|
45
41
|
import type {DocFile} from './types';
|
|
46
42
|
|
|
47
|
-
type LastUpdateOptions = Pick<
|
|
48
|
-
PluginOptions,
|
|
49
|
-
'showLastUpdateAuthor' | 'showLastUpdateTime'
|
|
50
|
-
>;
|
|
51
|
-
|
|
52
|
-
async function readLastUpdateData(
|
|
53
|
-
filePath: string,
|
|
54
|
-
options: LastUpdateOptions,
|
|
55
|
-
lastUpdateFrontMatter: FileChange | undefined,
|
|
56
|
-
): Promise<LastUpdateData> {
|
|
57
|
-
const {showLastUpdateAuthor, showLastUpdateTime} = options;
|
|
58
|
-
if (showLastUpdateAuthor || showLastUpdateTime) {
|
|
59
|
-
const frontMatterTimestamp = lastUpdateFrontMatter?.date
|
|
60
|
-
? new Date(lastUpdateFrontMatter.date).getTime() / 1000
|
|
61
|
-
: undefined;
|
|
62
|
-
|
|
63
|
-
if (lastUpdateFrontMatter?.author && lastUpdateFrontMatter.date) {
|
|
64
|
-
return {
|
|
65
|
-
lastUpdatedAt: frontMatterTimestamp,
|
|
66
|
-
lastUpdatedBy: lastUpdateFrontMatter.author,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Use fake data in dev for faster development.
|
|
71
|
-
const fileLastUpdateData =
|
|
72
|
-
process.env.NODE_ENV === 'production'
|
|
73
|
-
? await getFileLastUpdate(filePath)
|
|
74
|
-
: {
|
|
75
|
-
author: 'Author',
|
|
76
|
-
timestamp: 1539502055,
|
|
77
|
-
};
|
|
78
|
-
const {author, timestamp} = fileLastUpdateData ?? {};
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
lastUpdatedBy: showLastUpdateAuthor
|
|
82
|
-
? lastUpdateFrontMatter?.author ?? author
|
|
83
|
-
: undefined,
|
|
84
|
-
lastUpdatedAt: showLastUpdateTime
|
|
85
|
-
? frontMatterTimestamp ?? timestamp
|
|
86
|
-
: undefined,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return {};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
43
|
export async function readDocFile(
|
|
94
44
|
versionMetadata: Pick<
|
|
95
45
|
VersionMetadata,
|
|
@@ -142,7 +92,6 @@ async function doProcessDocMetadata({
|
|
|
142
92
|
const {source, content, contentPath, filePath} = docFile;
|
|
143
93
|
const {
|
|
144
94
|
siteDir,
|
|
145
|
-
i18n,
|
|
146
95
|
siteConfig: {
|
|
147
96
|
markdown: {parseFrontMatter},
|
|
148
97
|
},
|
|
@@ -257,21 +206,6 @@ async function doProcessDocMetadata({
|
|
|
257
206
|
const draft = isDraft({env, frontMatter});
|
|
258
207
|
const unlisted = isUnlisted({env, frontMatter});
|
|
259
208
|
|
|
260
|
-
const formatDate = (locale: string, date: Date, calendar: string): string => {
|
|
261
|
-
try {
|
|
262
|
-
return new Intl.DateTimeFormat(locale, {
|
|
263
|
-
day: 'numeric',
|
|
264
|
-
month: 'short',
|
|
265
|
-
year: 'numeric',
|
|
266
|
-
timeZone: 'UTC',
|
|
267
|
-
calendar,
|
|
268
|
-
}).format(date);
|
|
269
|
-
} catch (err) {
|
|
270
|
-
logger.error`Can't format docs lastUpdatedAt date "${String(date)}"`;
|
|
271
|
-
throw err;
|
|
272
|
-
}
|
|
273
|
-
};
|
|
274
|
-
|
|
275
209
|
// Assign all of object properties during instantiation (if possible) for
|
|
276
210
|
// NodeJS optimization.
|
|
277
211
|
// Adding properties to object after instantiation will cause hidden
|
|
@@ -291,13 +225,6 @@ async function doProcessDocMetadata({
|
|
|
291
225
|
version: versionMetadata.versionName,
|
|
292
226
|
lastUpdatedBy: lastUpdate.lastUpdatedBy,
|
|
293
227
|
lastUpdatedAt: lastUpdate.lastUpdatedAt,
|
|
294
|
-
formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
|
|
295
|
-
? formatDate(
|
|
296
|
-
i18n.currentLocale,
|
|
297
|
-
new Date(lastUpdate.lastUpdatedAt * 1000),
|
|
298
|
-
i18n.localeConfigs[i18n.currentLocale]!.calendar,
|
|
299
|
-
)
|
|
300
|
-
: undefined,
|
|
301
228
|
sidebarPosition,
|
|
302
229
|
frontMatter,
|
|
303
230
|
};
|
package/src/frontMatter.ts
CHANGED
|
@@ -4,7 +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
|
-
|
|
8
7
|
import {
|
|
9
8
|
JoiFrontMatter as Joi, // Custom instance for front matter
|
|
10
9
|
URISchema,
|
|
@@ -12,17 +11,15 @@ import {
|
|
|
12
11
|
FrontMatterTOCHeadingLevels,
|
|
13
12
|
validateFrontMatter,
|
|
14
13
|
ContentVisibilitySchema,
|
|
14
|
+
FrontMatterLastUpdateSchema,
|
|
15
15
|
} from '@docusaurus/utils-validation';
|
|
16
16
|
import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
|
|
17
17
|
|
|
18
|
-
const FrontMatterLastUpdateErrorMessage =
|
|
19
|
-
'{{#label}} does not look like a valid front matter FileChange object. Please use a FileChange object (with an author and/or date).';
|
|
20
|
-
|
|
21
18
|
// NOTE: we don't add any default value on purpose here
|
|
22
19
|
// We don't want default values to magically appear in doc metadata and props
|
|
23
20
|
// While the user did not provide those values explicitly
|
|
24
21
|
// We use default values in code instead
|
|
25
|
-
const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
|
|
22
|
+
export const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
|
|
26
23
|
id: Joi.string(),
|
|
27
24
|
// See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
|
|
28
25
|
title: Joi.string().allow(''),
|
|
@@ -45,15 +42,7 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
|
|
|
45
42
|
pagination_next: Joi.string().allow(null),
|
|
46
43
|
pagination_prev: Joi.string().allow(null),
|
|
47
44
|
...FrontMatterTOCHeadingLevels,
|
|
48
|
-
last_update:
|
|
49
|
-
author: Joi.string(),
|
|
50
|
-
date: Joi.date().raw(),
|
|
51
|
-
})
|
|
52
|
-
.or('author', 'date')
|
|
53
|
-
.messages({
|
|
54
|
-
'object.missing': FrontMatterLastUpdateErrorMessage,
|
|
55
|
-
'object.base': FrontMatterLastUpdateErrorMessage,
|
|
56
|
-
}),
|
|
45
|
+
last_update: FrontMatterLastUpdateSchema,
|
|
57
46
|
})
|
|
58
47
|
.unknown()
|
|
59
48
|
.concat(ContentVisibilitySchema);
|
|
@@ -16,6 +16,8 @@ declare module '@docusaurus/plugin-content-docs' {
|
|
|
16
16
|
TagsListItem,
|
|
17
17
|
TagModule,
|
|
18
18
|
Tag,
|
|
19
|
+
FrontMatterLastUpdate,
|
|
20
|
+
LastUpdateData,
|
|
19
21
|
} from '@docusaurus/utils';
|
|
20
22
|
import type {Plugin, LoadContext} from '@docusaurus/types';
|
|
21
23
|
import type {Overwrite, Required} from 'utility-types';
|
|
@@ -24,14 +26,6 @@ declare module '@docusaurus/plugin-content-docs' {
|
|
|
24
26
|
image?: string;
|
|
25
27
|
};
|
|
26
28
|
|
|
27
|
-
export type FileChange = {
|
|
28
|
-
author?: string;
|
|
29
|
-
/** Date can be any
|
|
30
|
-
* [parsable date string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
|
|
31
|
-
*/
|
|
32
|
-
date?: Date | string;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
29
|
/**
|
|
36
30
|
* Custom callback for parsing number prefixes from file/folder names.
|
|
37
31
|
*/
|
|
@@ -93,9 +87,9 @@ declare module '@docusaurus/plugin-content-docs' {
|
|
|
93
87
|
*/
|
|
94
88
|
editLocalizedFiles: boolean;
|
|
95
89
|
/** Whether to display the last date the doc was updated. */
|
|
96
|
-
showLastUpdateTime
|
|
90
|
+
showLastUpdateTime: boolean;
|
|
97
91
|
/** Whether to display the author who last updated the doc. */
|
|
98
|
-
showLastUpdateAuthor
|
|
92
|
+
showLastUpdateAuthor: boolean;
|
|
99
93
|
/**
|
|
100
94
|
* Custom parsing logic to extract number prefixes from file names. Use
|
|
101
95
|
* `false` to disable this behavior and leave the docs untouched, and `true`
|
|
@@ -401,16 +395,7 @@ declare module '@docusaurus/plugin-content-docs' {
|
|
|
401
395
|
/** Should this doc be accessible but hidden in production builds? */
|
|
402
396
|
unlisted?: boolean;
|
|
403
397
|
/** Allows overriding the last updated author and/or date. */
|
|
404
|
-
last_update?:
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
export type LastUpdateData = {
|
|
408
|
-
/** A timestamp in **seconds**, directly acquired from `git log`. */
|
|
409
|
-
lastUpdatedAt?: number;
|
|
410
|
-
/** `lastUpdatedAt` formatted as a date according to the current locale. */
|
|
411
|
-
formattedLastUpdatedAt?: string;
|
|
412
|
-
/** The author's name directly acquired from `git log`. */
|
|
413
|
-
lastUpdatedBy?: string;
|
|
398
|
+
last_update?: FrontMatterLastUpdate;
|
|
414
399
|
};
|
|
415
400
|
|
|
416
401
|
export type DocMetadataBase = LastUpdateData & {
|
package/src/routes.ts
CHANGED
|
@@ -7,21 +7,38 @@
|
|
|
7
7
|
|
|
8
8
|
import _ from 'lodash';
|
|
9
9
|
import logger from '@docusaurus/logger';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
docuHash,
|
|
12
|
+
createSlugger,
|
|
13
|
+
normalizeUrl,
|
|
14
|
+
aliasedSitePathToRelativePath,
|
|
15
|
+
} from '@docusaurus/utils';
|
|
11
16
|
import {
|
|
12
17
|
toTagDocListProp,
|
|
13
18
|
toTagsListTagsProp,
|
|
14
19
|
toVersionMetadataProp,
|
|
15
20
|
} from './props';
|
|
16
21
|
import {getVersionTags} from './tags';
|
|
17
|
-
import type {
|
|
22
|
+
import type {
|
|
23
|
+
PluginContentLoadedActions,
|
|
24
|
+
RouteConfig,
|
|
25
|
+
RouteMetadata,
|
|
26
|
+
} from '@docusaurus/types';
|
|
18
27
|
import type {FullVersion, VersionTag} from './types';
|
|
19
28
|
import type {
|
|
20
29
|
CategoryGeneratedIndexMetadata,
|
|
30
|
+
DocMetadata,
|
|
21
31
|
PluginOptions,
|
|
22
32
|
PropTagsListPage,
|
|
23
33
|
} from '@docusaurus/plugin-content-docs';
|
|
24
34
|
|
|
35
|
+
function createDocRouteMetadata(docMeta: DocMetadata): RouteMetadata {
|
|
36
|
+
return {
|
|
37
|
+
sourceFilePath: aliasedSitePathToRelativePath(docMeta.source),
|
|
38
|
+
lastUpdatedAt: docMeta.lastUpdatedAt,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
25
42
|
async function buildVersionCategoryGeneratedIndexRoutes({
|
|
26
43
|
version,
|
|
27
44
|
actions,
|
|
@@ -68,26 +85,27 @@ async function buildVersionDocRoutes({
|
|
|
68
85
|
options,
|
|
69
86
|
}: BuildVersionRoutesParam): Promise<RouteConfig[]> {
|
|
70
87
|
return Promise.all(
|
|
71
|
-
version.docs.map(async (
|
|
88
|
+
version.docs.map(async (doc) => {
|
|
72
89
|
await actions.createData(
|
|
73
90
|
// Note that this created data path must be in sync with
|
|
74
91
|
// metadataPath provided to mdx-loader.
|
|
75
|
-
`${docuHash(
|
|
76
|
-
JSON.stringify(
|
|
92
|
+
`${docuHash(doc.source)}.json`,
|
|
93
|
+
JSON.stringify(doc, null, 2),
|
|
77
94
|
);
|
|
78
95
|
|
|
79
96
|
const docRoute: RouteConfig = {
|
|
80
|
-
path:
|
|
97
|
+
path: doc.permalink,
|
|
81
98
|
component: options.docItemComponent,
|
|
82
99
|
exact: true,
|
|
83
100
|
modules: {
|
|
84
|
-
content:
|
|
101
|
+
content: doc.source,
|
|
85
102
|
},
|
|
103
|
+
metadata: createDocRouteMetadata(doc),
|
|
86
104
|
// Because the parent (DocRoot) comp need to access it easily
|
|
87
105
|
// This permits to render the sidebar once without unmount/remount when
|
|
88
106
|
// navigating (and preserve sidebar state)
|
|
89
|
-
...(
|
|
90
|
-
sidebar:
|
|
107
|
+
...(doc.sidebar && {
|
|
108
|
+
sidebar: doc.sidebar,
|
|
91
109
|
}),
|
|
92
110
|
};
|
|
93
111
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import _ from 'lodash';
|
|
10
10
|
import logger from '@docusaurus/logger';
|
|
11
|
-
import {addTrailingSlash} from '@docusaurus/utils';
|
|
11
|
+
import {addTrailingSlash} from '@docusaurus/utils-common';
|
|
12
12
|
import {createDocsByIdIndex, toCategoryIndexMatcherParam} from '../docs';
|
|
13
13
|
import type {
|
|
14
14
|
SidebarItemDoc,
|
package/src/slug.ts
CHANGED
|
@@ -5,12 +5,8 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
addTrailingSlash,
|
|
11
|
-
isValidPathname,
|
|
12
|
-
resolvePathname,
|
|
13
|
-
} from '@docusaurus/utils';
|
|
8
|
+
import {isValidPathname, resolvePathname} from '@docusaurus/utils';
|
|
9
|
+
import {addLeadingSlash, addTrailingSlash} from '@docusaurus/utils-common';
|
|
14
10
|
import {
|
|
15
11
|
DefaultNumberPrefixParser,
|
|
16
12
|
stripPathNumberPrefixes,
|
package/lib/lastUpdate.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
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
|
-
export declare function getFileLastUpdate(filePath: string): Promise<{
|
|
8
|
-
timestamp: number;
|
|
9
|
-
author: string;
|
|
10
|
-
} | null>;
|
package/lib/lastUpdate.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
-
*
|
|
5
|
-
* This source code is licensed under the MIT license found in the
|
|
6
|
-
* LICENSE file in the root directory of this source tree.
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.getFileLastUpdate = void 0;
|
|
10
|
-
const tslib_1 = require("tslib");
|
|
11
|
-
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
12
|
-
const utils_1 = require("@docusaurus/utils");
|
|
13
|
-
let showedGitRequirementError = false;
|
|
14
|
-
let showedFileNotTrackedError = false;
|
|
15
|
-
async function getFileLastUpdate(filePath) {
|
|
16
|
-
if (!filePath) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
// Wrap in try/catch in case the shell commands fail
|
|
20
|
-
// (e.g. project doesn't use Git, etc).
|
|
21
|
-
try {
|
|
22
|
-
const result = (0, utils_1.getFileCommitDate)(filePath, {
|
|
23
|
-
age: 'newest',
|
|
24
|
-
includeAuthor: true,
|
|
25
|
-
});
|
|
26
|
-
return { timestamp: result.timestamp, author: result.author };
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
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
|
-
}
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
logger_1.default.warn(err);
|
|
43
|
-
}
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
exports.getFileLastUpdate = getFileLastUpdate;
|
package/src/lastUpdate.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
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 logger from '@docusaurus/logger';
|
|
9
|
-
import {
|
|
10
|
-
getFileCommitDate,
|
|
11
|
-
FileNotTrackedError,
|
|
12
|
-
GitNotFoundError,
|
|
13
|
-
} from '@docusaurus/utils';
|
|
14
|
-
|
|
15
|
-
let showedGitRequirementError = false;
|
|
16
|
-
let showedFileNotTrackedError = false;
|
|
17
|
-
|
|
18
|
-
export async function getFileLastUpdate(
|
|
19
|
-
filePath: string,
|
|
20
|
-
): Promise<{timestamp: number; author: string} | null> {
|
|
21
|
-
if (!filePath) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Wrap in try/catch in case the shell commands fail
|
|
26
|
-
// (e.g. project doesn't use Git, etc).
|
|
27
|
-
try {
|
|
28
|
-
const result = getFileCommitDate(filePath, {
|
|
29
|
-
age: 'newest',
|
|
30
|
-
includeAuthor: true,
|
|
31
|
-
});
|
|
32
|
-
return {timestamp: result.timestamp, author: result.author};
|
|
33
|
-
} catch (err) {
|
|
34
|
-
if (err instanceof GitNotFoundError) {
|
|
35
|
-
if (!showedGitRequirementError) {
|
|
36
|
-
logger.warn('Sorry, the docs plugin last update options require Git.');
|
|
37
|
-
showedGitRequirementError = true;
|
|
38
|
-
}
|
|
39
|
-
} else if (err instanceof FileNotTrackedError) {
|
|
40
|
-
if (!showedFileNotTrackedError) {
|
|
41
|
-
logger.warn(
|
|
42
|
-
'Cannot infer the update date for some files, as they are not tracked by git.',
|
|
43
|
-
);
|
|
44
|
-
showedFileNotTrackedError = true;
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
logger.warn(err);
|
|
48
|
-
}
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|