@docusaurus/plugin-content-pages 0.0.0-5894 → 0.0.0-5899

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.
@@ -18,6 +18,7 @@ const PageFrontMatterSchema = utils_validation_1.Joi.object({
18
18
  wrapperClassName: utils_validation_1.Joi.string(),
19
19
  hide_table_of_contents: utils_validation_1.Joi.boolean(),
20
20
  ...utils_validation_1.FrontMatterTOCHeadingLevels,
21
+ last_update: utils_validation_1.FrontMatterLastUpdateSchema,
21
22
  }).concat(utils_validation_1.ContentVisibilitySchema);
22
23
  function validatePageFrontMatter(frontMatter) {
23
24
  return (0, utils_validation_1.validateFrontMatter)(frontMatter, PageFrontMatterSchema);
package/lib/index.js CHANGED
@@ -18,7 +18,7 @@ function getContentPathList(contentPaths) {
18
18
  exports.getContentPathList = getContentPathList;
19
19
  const isMarkdownSource = (source) => source.endsWith('.md') || source.endsWith('.mdx');
20
20
  function pluginContentPages(context, options) {
21
- const { siteConfig, siteDir, generatedFilesDir, localizationDir } = context;
21
+ const { siteConfig, siteDir, generatedFilesDir, localizationDir, i18n } = context;
22
22
  const contentPaths = {
23
23
  contentPath: path_1.default.resolve(siteDir, options.path),
24
24
  contentPathLocalized: (0, utils_1.getPluginI18nPath)({
@@ -36,7 +36,7 @@ function pluginContentPages(context, options) {
36
36
  return getContentPathList(contentPaths).flatMap((contentPath) => include.map((pattern) => `${contentPath}/${pattern}`));
37
37
  },
38
38
  async loadContent() {
39
- const { include } = options;
39
+ const { include, editUrl } = options;
40
40
  if (!(await fs_extra_1.default.pathExists(contentPaths.contentPath))) {
41
41
  return null;
42
42
  }
@@ -69,6 +69,32 @@ function pluginContentPages(context, options) {
69
69
  parseFrontMatter: siteConfig.markdown.parseFrontMatter,
70
70
  });
71
71
  const frontMatter = (0, frontMatter_1.validatePageFrontMatter)(unsafeFrontMatter);
72
+ const pagesDirPath = await (0, utils_1.getFolderContainingFile)(getContentPathList(contentPaths), relativeSource);
73
+ const pagesSourceAbsolute = path_1.default.join(pagesDirPath, relativeSource);
74
+ function getPagesEditUrl() {
75
+ const pagesPathRelative = path_1.default.relative(pagesDirPath, path_1.default.resolve(pagesSourceAbsolute));
76
+ if (typeof editUrl === 'function') {
77
+ return editUrl({
78
+ pagesDirPath: (0, utils_1.posixPath)(path_1.default.relative(siteDir, pagesDirPath)),
79
+ pagesPath: (0, utils_1.posixPath)(pagesPathRelative),
80
+ permalink,
81
+ locale: i18n.currentLocale,
82
+ });
83
+ }
84
+ else if (typeof editUrl === 'string') {
85
+ const isLocalized = pagesDirPath === contentPaths.contentPathLocalized;
86
+ const fileContentPath = isLocalized && options.editLocalizedFiles
87
+ ? contentPaths.contentPathLocalized
88
+ : contentPaths.contentPath;
89
+ const contentPathEditUrl = (0, utils_1.normalizeUrl)([
90
+ editUrl,
91
+ (0, utils_1.posixPath)(path_1.default.relative(siteDir, fileContentPath)),
92
+ ]);
93
+ return (0, utils_1.getEditUrl)(pagesPathRelative, contentPathEditUrl);
94
+ }
95
+ return undefined;
96
+ }
97
+ const lastUpdatedData = await (0, utils_1.readLastUpdateData)(source, options, frontMatter.last_update);
72
98
  if ((0, utils_1.isDraft)({ frontMatter })) {
73
99
  return undefined;
74
100
  }
@@ -80,6 +106,9 @@ function pluginContentPages(context, options) {
80
106
  title: frontMatter.title ?? contentTitle,
81
107
  description: frontMatter.description ?? excerpt,
82
108
  frontMatter,
109
+ lastUpdatedBy: lastUpdatedData.lastUpdatedBy,
110
+ lastUpdatedAt: lastUpdatedData.lastUpdatedAt,
111
+ editUrl: getPagesEditUrl(),
83
112
  unlisted,
84
113
  };
85
114
  }
@@ -99,12 +128,10 @@ function pluginContentPages(context, options) {
99
128
  }
100
129
  const { addRoute, createData } = actions;
101
130
  function createPageRouteMetadata(metadata) {
131
+ const lastUpdatedAt = metadata.type === 'mdx' ? metadata.lastUpdatedAt : undefined;
102
132
  return {
103
133
  sourceFilePath: (0, utils_1.aliasedSitePathToRelativePath)(metadata.source),
104
- // TODO add support for last updated date in the page plugin
105
- // at least for Markdown files
106
- // lastUpdatedAt: metadata.lastUpdatedAt,
107
- lastUpdatedAt: undefined,
134
+ lastUpdatedAt,
108
135
  };
109
136
  }
110
137
  await Promise.all(content.map(async (metadata) => {
package/lib/options.js CHANGED
@@ -20,6 +20,9 @@ exports.DEFAULT_OPTIONS = {
20
20
  beforeDefaultRehypePlugins: [],
21
21
  beforeDefaultRemarkPlugins: [],
22
22
  admonitions: true,
23
+ showLastUpdateTime: false,
24
+ showLastUpdateAuthor: false,
25
+ editLocalizedFiles: false,
23
26
  };
24
27
  const PluginOptionSchema = utils_validation_1.Joi.object({
25
28
  path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
@@ -32,6 +35,10 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
32
35
  beforeDefaultRehypePlugins: utils_validation_1.RehypePluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRehypePlugins),
33
36
  beforeDefaultRemarkPlugins: utils_validation_1.RemarkPluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRemarkPlugins),
34
37
  admonitions: utils_validation_1.AdmonitionsSchema.default(exports.DEFAULT_OPTIONS.admonitions),
38
+ showLastUpdateTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showLastUpdateTime),
39
+ showLastUpdateAuthor: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showLastUpdateAuthor),
40
+ editUrl: utils_validation_1.Joi.alternatives().try(utils_validation_1.URISchema, utils_validation_1.Joi.function()),
41
+ editLocalizedFiles: utils_validation_1.Joi.boolean().default(exports.DEFAULT_OPTIONS.editLocalizedFiles),
35
42
  });
36
43
  function validateOptions({ validate, options, }) {
37
44
  const validatedOptions = validate(PluginOptionSchema, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-pages",
3
- "version": "0.0.0-5894",
3
+ "version": "0.0.0-5899",
4
4
  "description": "Pages plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/plugin-content-pages.d.ts",
@@ -18,11 +18,11 @@
18
18
  },
19
19
  "license": "MIT",
20
20
  "dependencies": {
21
- "@docusaurus/core": "0.0.0-5894",
22
- "@docusaurus/mdx-loader": "0.0.0-5894",
23
- "@docusaurus/types": "0.0.0-5894",
24
- "@docusaurus/utils": "0.0.0-5894",
25
- "@docusaurus/utils-validation": "0.0.0-5894",
21
+ "@docusaurus/core": "0.0.0-5899",
22
+ "@docusaurus/mdx-loader": "0.0.0-5899",
23
+ "@docusaurus/types": "0.0.0-5899",
24
+ "@docusaurus/utils": "0.0.0-5899",
25
+ "@docusaurus/utils-validation": "0.0.0-5899",
26
26
  "fs-extra": "^11.1.1",
27
27
  "tslib": "^2.6.0",
28
28
  "webpack": "^5.88.1"
@@ -34,5 +34,5 @@
34
34
  "engines": {
35
35
  "node": ">=18.0"
36
36
  },
37
- "gitHead": "002e325935f110e1f4142478b71b62ba21318bd5"
37
+ "gitHead": "e8e1f914293e8dade7f4e0907d9a00bd1df80470"
38
38
  }
@@ -11,6 +11,7 @@ import {
11
11
  FrontMatterTOCHeadingLevels,
12
12
  ContentVisibilitySchema,
13
13
  URISchema,
14
+ FrontMatterLastUpdateSchema,
14
15
  } from '@docusaurus/utils-validation';
15
16
  import type {PageFrontMatter} from '@docusaurus/plugin-content-pages';
16
17
 
@@ -24,6 +25,7 @@ const PageFrontMatterSchema = Joi.object<PageFrontMatter>({
24
25
  wrapperClassName: Joi.string(),
25
26
  hide_table_of_contents: Joi.boolean(),
26
27
  ...FrontMatterTOCHeadingLevels,
28
+ last_update: FrontMatterLastUpdateSchema,
27
29
  }).concat(ContentVisibilitySchema);
28
30
 
29
31
  export function validatePageFrontMatter(frontMatter: {
package/src/index.ts CHANGED
@@ -23,6 +23,9 @@ import {
23
23
  parseMarkdownFile,
24
24
  isUnlisted,
25
25
  isDraft,
26
+ readLastUpdateData,
27
+ getEditUrl,
28
+ posixPath,
26
29
  } from '@docusaurus/utils';
27
30
  import {validatePageFrontMatter} from './frontMatter';
28
31
  import type {LoadContext, Plugin, RouteMetadata} from '@docusaurus/types';
@@ -45,7 +48,8 @@ export default function pluginContentPages(
45
48
  context: LoadContext,
46
49
  options: PluginOptions,
47
50
  ): Plugin<LoadedContent | null> {
48
- const {siteConfig, siteDir, generatedFilesDir, localizationDir} = context;
51
+ const {siteConfig, siteDir, generatedFilesDir, localizationDir, i18n} =
52
+ context;
49
53
 
50
54
  const contentPaths: PagesContentPaths = {
51
55
  contentPath: path.resolve(siteDir, options.path),
@@ -73,7 +77,7 @@ export default function pluginContentPages(
73
77
  },
74
78
 
75
79
  async loadContent() {
76
- const {include} = options;
80
+ const {include, editUrl} = options;
77
81
 
78
82
  if (!(await fs.pathExists(contentPaths.contentPath))) {
79
83
  return null;
@@ -120,6 +124,50 @@ export default function pluginContentPages(
120
124
  });
121
125
  const frontMatter = validatePageFrontMatter(unsafeFrontMatter);
122
126
 
127
+ const pagesDirPath = await getFolderContainingFile(
128
+ getContentPathList(contentPaths),
129
+ relativeSource,
130
+ );
131
+
132
+ const pagesSourceAbsolute = path.join(pagesDirPath, relativeSource);
133
+
134
+ function getPagesEditUrl() {
135
+ const pagesPathRelative = path.relative(
136
+ pagesDirPath,
137
+ path.resolve(pagesSourceAbsolute),
138
+ );
139
+
140
+ if (typeof editUrl === 'function') {
141
+ return editUrl({
142
+ pagesDirPath: posixPath(path.relative(siteDir, pagesDirPath)),
143
+ pagesPath: posixPath(pagesPathRelative),
144
+ permalink,
145
+ locale: i18n.currentLocale,
146
+ });
147
+ } else if (typeof editUrl === 'string') {
148
+ const isLocalized =
149
+ pagesDirPath === contentPaths.contentPathLocalized;
150
+ const fileContentPath =
151
+ isLocalized && options.editLocalizedFiles
152
+ ? contentPaths.contentPathLocalized
153
+ : contentPaths.contentPath;
154
+
155
+ const contentPathEditUrl = normalizeUrl([
156
+ editUrl,
157
+ posixPath(path.relative(siteDir, fileContentPath)),
158
+ ]);
159
+
160
+ return getEditUrl(pagesPathRelative, contentPathEditUrl);
161
+ }
162
+ return undefined;
163
+ }
164
+
165
+ const lastUpdatedData = await readLastUpdateData(
166
+ source,
167
+ options,
168
+ frontMatter.last_update,
169
+ );
170
+
123
171
  if (isDraft({frontMatter})) {
124
172
  return undefined;
125
173
  }
@@ -132,6 +180,9 @@ export default function pluginContentPages(
132
180
  title: frontMatter.title ?? contentTitle,
133
181
  description: frontMatter.description ?? excerpt,
134
182
  frontMatter,
183
+ lastUpdatedBy: lastUpdatedData.lastUpdatedBy,
184
+ lastUpdatedAt: lastUpdatedData.lastUpdatedAt,
185
+ editUrl: getPagesEditUrl(),
135
186
  unlisted,
136
187
  };
137
188
  }
@@ -160,12 +211,12 @@ export default function pluginContentPages(
160
211
  const {addRoute, createData} = actions;
161
212
 
162
213
  function createPageRouteMetadata(metadata: Metadata): RouteMetadata {
214
+ const lastUpdatedAt =
215
+ metadata.type === 'mdx' ? metadata.lastUpdatedAt : undefined;
216
+
163
217
  return {
164
218
  sourceFilePath: aliasedSitePathToRelativePath(metadata.source),
165
- // TODO add support for last updated date in the page plugin
166
- // at least for Markdown files
167
- // lastUpdatedAt: metadata.lastUpdatedAt,
168
- lastUpdatedAt: undefined,
219
+ lastUpdatedAt,
169
220
  };
170
221
  }
171
222
 
package/src/options.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  RehypePluginsSchema,
12
12
  AdmonitionsSchema,
13
13
  RouteBasePathSchema,
14
+ URISchema,
14
15
  } from '@docusaurus/utils-validation';
15
16
  import {GlobExcludeDefault} from '@docusaurus/utils';
16
17
  import type {OptionValidationContext} from '@docusaurus/types';
@@ -27,6 +28,9 @@ export const DEFAULT_OPTIONS: PluginOptions = {
27
28
  beforeDefaultRehypePlugins: [],
28
29
  beforeDefaultRemarkPlugins: [],
29
30
  admonitions: true,
31
+ showLastUpdateTime: false,
32
+ showLastUpdateAuthor: false,
33
+ editLocalizedFiles: false,
30
34
  };
31
35
 
32
36
  const PluginOptionSchema = Joi.object<PluginOptions>({
@@ -44,6 +48,12 @@ const PluginOptionSchema = Joi.object<PluginOptions>({
44
48
  DEFAULT_OPTIONS.beforeDefaultRemarkPlugins,
45
49
  ),
46
50
  admonitions: AdmonitionsSchema.default(DEFAULT_OPTIONS.admonitions),
51
+ showLastUpdateTime: Joi.bool().default(DEFAULT_OPTIONS.showLastUpdateTime),
52
+ showLastUpdateAuthor: Joi.bool().default(
53
+ DEFAULT_OPTIONS.showLastUpdateAuthor,
54
+ ),
55
+ editUrl: Joi.alternatives().try(URISchema, Joi.function()),
56
+ editLocalizedFiles: Joi.boolean().default(DEFAULT_OPTIONS.editLocalizedFiles),
47
57
  });
48
58
 
49
59
  export function validateOptions({
@@ -8,6 +8,7 @@
8
8
  declare module '@docusaurus/plugin-content-pages' {
9
9
  import type {MDXOptions} from '@docusaurus/mdx-loader';
10
10
  import type {LoadContext, Plugin} from '@docusaurus/types';
11
+ import type {FrontMatterLastUpdate, LastUpdateData} from '@docusaurus/utils';
11
12
 
12
13
  export type Assets = {
13
14
  image?: string;
@@ -20,6 +21,10 @@ declare module '@docusaurus/plugin-content-pages' {
20
21
  include: string[];
21
22
  exclude: string[];
22
23
  mdxPageComponent: string;
24
+ showLastUpdateTime: boolean;
25
+ showLastUpdateAuthor: boolean;
26
+ editUrl?: string | EditUrlFunction;
27
+ editLocalizedFiles?: boolean;
23
28
  };
24
29
 
25
30
  export type Options = Partial<PluginOptions>;
@@ -35,6 +40,7 @@ declare module '@docusaurus/plugin-content-pages' {
35
40
  readonly toc_max_heading_level?: number;
36
41
  readonly draft?: boolean;
37
42
  readonly unlisted?: boolean;
43
+ readonly last_update?: FrontMatterLastUpdate;
38
44
  };
39
45
 
40
46
  export type JSXPageMetadata = {
@@ -43,16 +49,31 @@ declare module '@docusaurus/plugin-content-pages' {
43
49
  source: string;
44
50
  };
45
51
 
46
- export type MDXPageMetadata = {
52
+ export type MDXPageMetadata = LastUpdateData & {
47
53
  type: 'mdx';
48
54
  permalink: string;
49
55
  source: string;
50
56
  frontMatter: PageFrontMatter & {[key: string]: unknown};
57
+ editUrl?: string;
51
58
  title?: string;
52
59
  description?: string;
53
60
  unlisted: boolean;
54
61
  };
55
62
 
63
+ export type EditUrlFunction = (editUrlParams: {
64
+ /**
65
+ * The root content directory containing this post file, relative to the
66
+ * site path. Usually the same as `options.path` but can be localized
67
+ */
68
+ pagesDirPath: string;
69
+ /** Path to this pages file, relative to `pagesDirPath`. */
70
+ pagesPath: string;
71
+ /** @see {@link PagesPostMetadata.permalink} */
72
+ permalink: string;
73
+ /** Locale name. */
74
+ locale: string;
75
+ }) => string | undefined;
76
+
56
77
  export type Metadata = JSXPageMetadata | MDXPageMetadata;
57
78
 
58
79
  export type LoadedContent = Metadata[];