@docusaurus/plugin-content-docs 0.0.0-5078 → 0.0.0-5085

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/docs.d.ts CHANGED
@@ -8,8 +8,7 @@ import type { MetadataOptions, PluginOptions, CategoryIndexMatcher, DocMetadataB
8
8
  import type { LoadContext } from '@docusaurus/types';
9
9
  import type { SidebarsUtils } from './sidebars/utils';
10
10
  import type { DocFile } from './types';
11
- declare type LastUpdateOptions = Pick<PluginOptions, 'showLastUpdateAuthor' | 'showLastUpdateTime'>;
12
- export declare function readDocFile(versionMetadata: Pick<VersionMetadata, 'contentPath' | 'contentPathLocalized'>, source: string, options: LastUpdateOptions): Promise<DocFile>;
11
+ export declare function readDocFile(versionMetadata: Pick<VersionMetadata, 'contentPath' | 'contentPathLocalized'>, source: string): Promise<DocFile>;
13
12
  export declare function readVersionDocs(versionMetadata: VersionMetadata, options: Pick<PluginOptions, 'include' | 'exclude' | 'showLastUpdateAuthor' | 'showLastUpdateTime'>): Promise<DocFile[]>;
14
13
  export declare type DocEnv = 'production' | 'development';
15
14
  export declare function processDocMetadata(args: {
@@ -18,7 +17,7 @@ export declare function processDocMetadata(args: {
18
17
  context: LoadContext;
19
18
  options: MetadataOptions;
20
19
  env: DocEnv;
21
- }): DocMetadataBase;
20
+ }): Promise<DocMetadataBase>;
22
21
  export declare function addDocNavigation(docsBase: DocMetadataBase[], sidebarsUtils: SidebarsUtils, sidebarFilePath: string): LoadedVersion['docs'];
23
22
  /**
24
23
  * The "main doc" is the "version entry point"
@@ -44,4 +43,3 @@ export declare function createDocsByIdIndex<Doc extends {
44
43
  }>(docs: Doc[]): {
45
44
  [docId: string]: Doc;
46
45
  };
47
- export {};
package/lib/docs.js CHANGED
@@ -18,9 +18,18 @@ const constants_1 = require("./constants");
18
18
  const numberPrefix_1 = require("./numberPrefix");
19
19
  const frontMatter_1 = require("./frontMatter");
20
20
  const utils_2 = require("./sidebars/utils");
21
- async function readLastUpdateData(filePath, options) {
21
+ async function readLastUpdateData(filePath, options, lastUpdateFrontMatter) {
22
22
  const { showLastUpdateAuthor, showLastUpdateTime } = options;
23
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
+ }
24
33
  // Use fake data in dev for faster development.
25
34
  const fileLastUpdateData = process.env.NODE_ENV === 'production'
26
35
  ? await (0, lastUpdate_1.getFileLastUpdate)(filePath)
@@ -28,24 +37,23 @@ async function readLastUpdateData(filePath, options) {
28
37
  author: 'Author',
29
38
  timestamp: 1539502055,
30
39
  };
31
- if (fileLastUpdateData) {
32
- const { author, timestamp } = fileLastUpdateData;
33
- return {
34
- lastUpdatedAt: showLastUpdateTime ? timestamp : undefined,
35
- lastUpdatedBy: showLastUpdateAuthor ? author : undefined,
36
- };
37
- }
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
+ };
38
49
  }
39
50
  return {};
40
51
  }
41
- async function readDocFile(versionMetadata, source, options) {
52
+ async function readDocFile(versionMetadata, source) {
42
53
  const contentPath = await (0, utils_1.getFolderContainingFile)((0, utils_1.getContentPathList)(versionMetadata), source);
43
54
  const filePath = path_1.default.join(contentPath, source);
44
- const [content, lastUpdate] = await Promise.all([
45
- fs_extra_1.default.readFile(filePath, 'utf-8'),
46
- readLastUpdateData(filePath, options),
47
- ]);
48
- return { source, content, lastUpdate, contentPath, filePath };
55
+ const content = await fs_extra_1.default.readFile(filePath, 'utf-8');
56
+ return { source, content, contentPath, filePath };
49
57
  }
50
58
  exports.readDocFile = readDocFile;
51
59
  async function readVersionDocs(versionMetadata, options) {
@@ -53,15 +61,15 @@ async function readVersionDocs(versionMetadata, options) {
53
61
  cwd: versionMetadata.contentPath,
54
62
  ignore: options.exclude,
55
63
  });
56
- return Promise.all(sources.map((source) => readDocFile(versionMetadata, source, options)));
64
+ return Promise.all(sources.map((source) => readDocFile(versionMetadata, source)));
57
65
  }
58
66
  exports.readVersionDocs = readVersionDocs;
59
67
  /** Docs with draft front matter are only considered draft in production. */
60
68
  function isDraftForEnvironment({ env, frontMatter, }) {
61
69
  return (env === 'production' && frontMatter.draft) ?? false;
62
70
  }
63
- function doProcessDocMetadata({ docFile, versionMetadata, context, options, env, }) {
64
- const { source, content, lastUpdate, contentPath, filePath } = docFile;
71
+ async function doProcessDocMetadata({ docFile, versionMetadata, context, options, env, }) {
72
+ const { source, content, contentPath, filePath } = docFile;
65
73
  const { siteDir, i18n } = context;
66
74
  const { frontMatter: unsafeFrontMatter, contentTitle, excerpt, } = (0, utils_1.parseMarkdownString)(content);
67
75
  const frontMatter = (0, frontMatter_1.validateDocFrontMatter)(unsafeFrontMatter);
@@ -69,7 +77,8 @@ function doProcessDocMetadata({ docFile, versionMetadata, context, options, env,
69
77
  // Strip number prefixes by default
70
78
  // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
71
79
  // but allow to disable this behavior with front matter
72
- parse_number_prefixes: parseNumberPrefixes = true, } = frontMatter;
80
+ parse_number_prefixes: parseNumberPrefixes = true, last_update: lastUpdateFrontMatter, } = frontMatter;
81
+ const lastUpdate = await readLastUpdateData(filePath, options, lastUpdateFrontMatter);
73
82
  // E.g. api/plugins/myDoc -> myDoc; myDoc -> myDoc
74
83
  const sourceFileNameWithoutExtension = path_1.default.basename(source, path_1.default.extname(source));
75
84
  // E.g. api/plugins/myDoc -> api/plugins; myDoc -> .
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
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).';
11
12
  // NOTE: we don't add any default value on purpose here
12
13
  // We don't want default values to magically appear in doc metadata and props
13
14
  // While the user did not provide those values explicitly
@@ -36,6 +37,15 @@ const DocFrontMatterSchema = utils_validation_1.JoiFrontMatter.object({
36
37
  pagination_prev: utils_validation_1.JoiFrontMatter.string().allow(null),
37
38
  draft: utils_validation_1.JoiFrontMatter.boolean(),
38
39
  ...utils_validation_1.FrontMatterTOCHeadingLevels,
40
+ last_update: utils_validation_1.JoiFrontMatter.object({
41
+ author: utils_validation_1.JoiFrontMatter.string(),
42
+ date: utils_validation_1.JoiFrontMatter.date().raw(),
43
+ })
44
+ .or('author', 'date')
45
+ .messages({
46
+ 'object.missing': FrontMatterLastUpdateErrorMessage,
47
+ 'object.base': FrontMatterLastUpdateErrorMessage,
48
+ }),
39
49
  }).unknown();
40
50
  function validateDocFrontMatter(frontMatter) {
41
51
  return (0, utils_validation_1.validateFrontMatter)(frontMatter, DocFrontMatterSchema);
package/lib/types.d.ts CHANGED
@@ -5,14 +5,13 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { BrokenMarkdownLink, Tag } from '@docusaurus/utils';
8
- import type { VersionMetadata, LastUpdateData, LoadedVersion, CategoryGeneratedIndexMetadata } from '@docusaurus/plugin-content-docs';
8
+ import type { VersionMetadata, LoadedVersion, CategoryGeneratedIndexMetadata } from '@docusaurus/plugin-content-docs';
9
9
  import type { SidebarsUtils } from './sidebars/utils';
10
10
  export declare type DocFile = {
11
11
  contentPath: string;
12
12
  filePath: string;
13
13
  source: string;
14
14
  content: string;
15
- lastUpdate: LastUpdateData;
16
15
  };
17
16
  export declare type SourceToPermalink = {
18
17
  [source: string]: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-docs",
3
- "version": "0.0.0-5078",
3
+ "version": "0.0.0-5085",
4
4
  "description": "Docs plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "sideEffects": false,
@@ -25,13 +25,13 @@
25
25
  },
26
26
  "license": "MIT",
27
27
  "dependencies": {
28
- "@docusaurus/core": "0.0.0-5078",
29
- "@docusaurus/logger": "0.0.0-5078",
30
- "@docusaurus/mdx-loader": "0.0.0-5078",
31
- "@docusaurus/module-type-aliases": "0.0.0-5078",
32
- "@docusaurus/types": "0.0.0-5078",
33
- "@docusaurus/utils": "0.0.0-5078",
34
- "@docusaurus/utils-validation": "0.0.0-5078",
28
+ "@docusaurus/core": "0.0.0-5085",
29
+ "@docusaurus/logger": "0.0.0-5085",
30
+ "@docusaurus/mdx-loader": "0.0.0-5085",
31
+ "@docusaurus/module-type-aliases": "0.0.0-5085",
32
+ "@docusaurus/types": "0.0.0-5085",
33
+ "@docusaurus/utils": "0.0.0-5085",
34
+ "@docusaurus/utils-validation": "0.0.0-5085",
35
35
  "@types/react-router-config": "^5.0.6",
36
36
  "combine-promises": "^1.1.0",
37
37
  "fs-extra": "^10.1.0",
@@ -59,5 +59,5 @@
59
59
  "engines": {
60
60
  "node": ">=16.14"
61
61
  },
62
- "gitHead": "b1ac010dc6c95b2a788eac5c9843b6a4b3852706"
62
+ "gitHead": "c752854fcbd457043a399f1184412ea6d912fe72"
63
63
  }
package/src/docs.ts CHANGED
@@ -37,6 +37,7 @@ import type {
37
37
  VersionMetadata,
38
38
  DocFrontMatter,
39
39
  LoadedVersion,
40
+ FileChange,
40
41
  } from '@docusaurus/plugin-content-docs';
41
42
  import type {LoadContext} from '@docusaurus/types';
42
43
  import type {SidebarsUtils} from './sidebars/utils';
@@ -50,9 +51,21 @@ type LastUpdateOptions = Pick<
50
51
  async function readLastUpdateData(
51
52
  filePath: string,
52
53
  options: LastUpdateOptions,
54
+ lastUpdateFrontMatter: FileChange | undefined,
53
55
  ): Promise<LastUpdateData> {
54
56
  const {showLastUpdateAuthor, showLastUpdateTime} = options;
55
57
  if (showLastUpdateAuthor || showLastUpdateTime) {
58
+ const frontMatterTimestamp = lastUpdateFrontMatter?.date
59
+ ? new Date(lastUpdateFrontMatter.date).getTime() / 1000
60
+ : undefined;
61
+
62
+ if (lastUpdateFrontMatter?.author && lastUpdateFrontMatter.date) {
63
+ return {
64
+ lastUpdatedAt: frontMatterTimestamp,
65
+ lastUpdatedBy: lastUpdateFrontMatter.author,
66
+ };
67
+ }
68
+
56
69
  // Use fake data in dev for faster development.
57
70
  const fileLastUpdateData =
58
71
  process.env.NODE_ENV === 'production'
@@ -61,14 +74,16 @@ async function readLastUpdateData(
61
74
  author: 'Author',
62
75
  timestamp: 1539502055,
63
76
  };
64
-
65
- if (fileLastUpdateData) {
66
- const {author, timestamp} = fileLastUpdateData;
67
- return {
68
- lastUpdatedAt: showLastUpdateTime ? timestamp : undefined,
69
- lastUpdatedBy: showLastUpdateAuthor ? author : undefined,
70
- };
71
- }
77
+ const {author, timestamp} = fileLastUpdateData ?? {};
78
+
79
+ return {
80
+ lastUpdatedBy: showLastUpdateAuthor
81
+ ? lastUpdateFrontMatter?.author ?? author
82
+ : undefined,
83
+ lastUpdatedAt: showLastUpdateTime
84
+ ? frontMatterTimestamp ?? timestamp
85
+ : undefined,
86
+ };
72
87
  }
73
88
 
74
89
  return {};
@@ -80,7 +95,6 @@ export async function readDocFile(
80
95
  'contentPath' | 'contentPathLocalized'
81
96
  >,
82
97
  source: string,
83
- options: LastUpdateOptions,
84
98
  ): Promise<DocFile> {
85
99
  const contentPath = await getFolderContainingFile(
86
100
  getContentPathList(versionMetadata),
@@ -89,11 +103,8 @@ export async function readDocFile(
89
103
 
90
104
  const filePath = path.join(contentPath, source);
91
105
 
92
- const [content, lastUpdate] = await Promise.all([
93
- fs.readFile(filePath, 'utf-8'),
94
- readLastUpdateData(filePath, options),
95
- ]);
96
- return {source, content, lastUpdate, contentPath, filePath};
106
+ const content = await fs.readFile(filePath, 'utf-8');
107
+ return {source, content, contentPath, filePath};
97
108
  }
98
109
 
99
110
  export async function readVersionDocs(
@@ -108,7 +119,7 @@ export async function readVersionDocs(
108
119
  ignore: options.exclude,
109
120
  });
110
121
  return Promise.all(
111
- sources.map((source) => readDocFile(versionMetadata, source, options)),
122
+ sources.map((source) => readDocFile(versionMetadata, source)),
112
123
  );
113
124
  }
114
125
 
@@ -125,7 +136,7 @@ function isDraftForEnvironment({
125
136
  return (env === 'production' && frontMatter.draft) ?? false;
126
137
  }
127
138
 
128
- function doProcessDocMetadata({
139
+ async function doProcessDocMetadata({
129
140
  docFile,
130
141
  versionMetadata,
131
142
  context,
@@ -137,8 +148,8 @@ function doProcessDocMetadata({
137
148
  context: LoadContext;
138
149
  options: MetadataOptions;
139
150
  env: DocEnv;
140
- }): DocMetadataBase {
141
- const {source, content, lastUpdate, contentPath, filePath} = docFile;
151
+ }): Promise<DocMetadataBase> {
152
+ const {source, content, contentPath, filePath} = docFile;
142
153
  const {siteDir, i18n} = context;
143
154
 
144
155
  const {
@@ -155,8 +166,15 @@ function doProcessDocMetadata({
155
166
  // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
156
167
  // but allow to disable this behavior with front matter
157
168
  parse_number_prefixes: parseNumberPrefixes = true,
169
+ last_update: lastUpdateFrontMatter,
158
170
  } = frontMatter;
159
171
 
172
+ const lastUpdate = await readLastUpdateData(
173
+ filePath,
174
+ options,
175
+ lastUpdateFrontMatter,
176
+ );
177
+
160
178
  // E.g. api/plugins/myDoc -> myDoc; myDoc -> myDoc
161
179
  const sourceFileNameWithoutExtension = path.basename(
162
180
  source,
@@ -287,7 +305,7 @@ export function processDocMetadata(args: {
287
305
  context: LoadContext;
288
306
  options: MetadataOptions;
289
307
  env: DocEnv;
290
- }): DocMetadataBase {
308
+ }): Promise<DocMetadataBase> {
291
309
  try {
292
310
  return doProcessDocMetadata(args);
293
311
  } catch (err) {
@@ -14,6 +14,9 @@ import {
14
14
  } from '@docusaurus/utils-validation';
15
15
  import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
16
16
 
17
+ const FrontMatterLastUpdateErrorMessage =
18
+ '{{#label}} does not look like a valid front matter FileChange object. Please use a FileChange object (with an author and/or date).';
19
+
17
20
  // NOTE: we don't add any default value on purpose here
18
21
  // We don't want default values to magically appear in doc metadata and props
19
22
  // While the user did not provide those values explicitly
@@ -42,6 +45,15 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
42
45
  pagination_prev: Joi.string().allow(null),
43
46
  draft: Joi.boolean(),
44
47
  ...FrontMatterTOCHeadingLevels,
48
+ last_update: Joi.object({
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
57
  }).unknown();
46
58
 
47
59
  export function validateDocFrontMatter(frontMatter: {
@@ -23,6 +23,14 @@ declare module '@docusaurus/plugin-content-docs' {
23
23
  image?: string;
24
24
  };
25
25
 
26
+ export type FileChange = {
27
+ author?: string;
28
+ /** Date can be any
29
+ * [parsable date string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
30
+ */
31
+ date?: Date | string;
32
+ };
33
+
26
34
  /**
27
35
  * Custom callback for parsing number prefixes from file/folder names.
28
36
  */
@@ -371,6 +379,8 @@ declare module '@docusaurus/plugin-content-docs' {
371
379
  pagination_prev?: string | null;
372
380
  /** Should this doc be excluded from production builds? */
373
381
  draft?: boolean;
382
+ /** Allows overriding the last updated author and/or date. */
383
+ last_update?: FileChange;
374
384
  };
375
385
 
376
386
  export type LastUpdateData = {
package/src/types.ts CHANGED
@@ -8,7 +8,6 @@
8
8
  import type {BrokenMarkdownLink, Tag} from '@docusaurus/utils';
9
9
  import type {
10
10
  VersionMetadata,
11
- LastUpdateData,
12
11
  LoadedVersion,
13
12
  CategoryGeneratedIndexMetadata,
14
13
  } from '@docusaurus/plugin-content-docs';
@@ -19,7 +18,6 @@ export type DocFile = {
19
18
  filePath: string; // /!\ may be localized
20
19
  source: string;
21
20
  content: string;
22
- lastUpdate: LastUpdateData;
23
21
  };
24
22
 
25
23
  export type SourceToPermalink = {