Skip to content

Commit

Permalink
feat(pages): add LastUpdateAuthor & LastUpdateTime & editUrl (#10032)
Browse files Browse the repository at this point in the history
Co-authored-by: OzakIOne <[email protected]>
Co-authored-by: sebastien <[email protected]>
  • Loading branch information
3 people authored Apr 16, 2024
1 parent e4ecffe commit d1590e3
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = `
},
{
"description": "Markdown index page",
"editUrl": undefined,
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
},
"lastUpdatedAt": undefined,
"lastUpdatedBy": undefined,
"permalink": "/hello/",
"source": "@site/src/pages/hello/index.md",
"title": "Index",
Expand All @@ -25,11 +28,14 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = `
},
{
"description": "my MDX page",
"editUrl": undefined,
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
"description": "my MDX page",
"title": "MDX page",
},
"lastUpdatedAt": undefined,
"lastUpdatedBy": undefined,
"permalink": "/hello/mdxPage",
"source": "@site/src/pages/hello/mdxPage.mdx",
"title": "MDX page",
Expand All @@ -43,9 +49,12 @@ exports[`docusaurus-plugin-content-pages loads simple pages 1`] = `
},
{
"description": "translated Markdown page",
"editUrl": undefined,
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
},
"lastUpdatedAt": undefined,
"lastUpdatedBy": undefined,
"permalink": "/hello/translatedMd",
"source": "@site/src/pages/hello/translatedMd.md",
"title": undefined,
Expand Down Expand Up @@ -74,9 +83,12 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat
},
{
"description": "Markdown index page",
"editUrl": undefined,
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
},
"lastUpdatedAt": undefined,
"lastUpdatedBy": undefined,
"permalink": "/fr/hello/",
"source": "@site/src/pages/hello/index.md",
"title": "Index",
Expand All @@ -85,11 +97,14 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat
},
{
"description": "my MDX page",
"editUrl": undefined,
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
"description": "my MDX page",
"title": "MDX page",
},
"lastUpdatedAt": undefined,
"lastUpdatedBy": undefined,
"permalink": "/fr/hello/mdxPage",
"source": "@site/src/pages/hello/mdxPage.mdx",
"title": "MDX page",
Expand All @@ -103,9 +118,12 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat
},
{
"description": "translated Markdown page (fr)",
"editUrl": undefined,
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
},
"lastUpdatedAt": undefined,
"lastUpdatedBy": undefined,
"permalink": "/fr/hello/translatedMd",
"source": "@site/i18n/fr/docusaurus-plugin-content-pages/hello/translatedMd.md",
"title": undefined,
Expand All @@ -119,3 +137,72 @@ exports[`docusaurus-plugin-content-pages loads simple pages with french translat
},
]
`;

exports[`docusaurus-plugin-content-pages loads simple pages with last update 1`] = `
[
{
"permalink": "/",
"source": "@site/src/pages/index.js",
"type": "jsx",
},
{
"permalink": "/typescript",
"source": "@site/src/pages/typescript.tsx",
"type": "jsx",
},
{
"description": "Markdown index page",
"editUrl": "url placeholder",
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
},
"lastUpdatedAt": 1539502055000,
"lastUpdatedBy": "Author",
"permalink": "/hello/",
"source": "@site/src/pages/hello/index.md",
"title": "Index",
"type": "mdx",
"unlisted": false,
},
{
"description": "my MDX page",
"editUrl": "url placeholder",
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
"description": "my MDX page",
"title": "MDX page",
},
"lastUpdatedAt": 1539502055000,
"lastUpdatedBy": "Author",
"permalink": "/hello/mdxPage",
"source": "@site/src/pages/hello/mdxPage.mdx",
"title": "MDX page",
"type": "mdx",
"unlisted": false,
},
{
"permalink": "/hello/translatedJs",
"source": "@site/src/pages/hello/translatedJs.js",
"type": "jsx",
},
{
"description": "translated Markdown page",
"editUrl": "url placeholder",
"frontMatter": {
"custom_frontMatter": "added by parseFrontMatter",
},
"lastUpdatedAt": 1539502055000,
"lastUpdatedBy": "Author",
"permalink": "/hello/translatedMd",
"source": "@site/src/pages/hello/translatedMd.md",
"title": undefined,
"type": "mdx",
"unlisted": false,
},
{
"permalink": "/hello/world",
"source": "@site/src/pages/hello/world.js",
"type": "jsx",
},
]
`;
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,24 @@ describe('docusaurus-plugin-content-pages', () => {

expect(pagesMetadata).toMatchSnapshot();
});

it('loads simple pages with last update', async () => {
const siteDir = path.join(__dirname, '__fixtures__', 'website');
const context = await loadContext({siteDir});
const plugin = pluginContentPages(
context,
validateOptions({
validate: normalizePluginOptions,
options: {
path: 'src/pages',
editUrl: () => 'url placeholder',
showLastUpdateAuthor: true,
showLastUpdateTime: true,
},
}),
);
const pagesMetadata = await plugin.loadContent!();

expect(pagesMetadata).toMatchSnapshot();
});
});
2 changes: 2 additions & 0 deletions packages/docusaurus-plugin-content-pages/src/frontMatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
FrontMatterTOCHeadingLevels,
ContentVisibilitySchema,
URISchema,
FrontMatterLastUpdateSchema,
} from '@docusaurus/utils-validation';
import type {PageFrontMatter} from '@docusaurus/plugin-content-pages';

Expand All @@ -24,6 +25,7 @@ const PageFrontMatterSchema = Joi.object<PageFrontMatter>({
wrapperClassName: Joi.string(),
hide_table_of_contents: Joi.boolean(),
...FrontMatterTOCHeadingLevels,
last_update: FrontMatterLastUpdateSchema,
}).concat(ContentVisibilitySchema);

export function validatePageFrontMatter(frontMatter: {
Expand Down
63 changes: 57 additions & 6 deletions packages/docusaurus-plugin-content-pages/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import {
parseMarkdownFile,
isUnlisted,
isDraft,
readLastUpdateData,
getEditUrl,
posixPath,
} from '@docusaurus/utils';
import {validatePageFrontMatter} from './frontMatter';
import type {LoadContext, Plugin, RouteMetadata} from '@docusaurus/types';
Expand All @@ -45,7 +48,8 @@ export default function pluginContentPages(
context: LoadContext,
options: PluginOptions,
): Plugin<LoadedContent | null> {
const {siteConfig, siteDir, generatedFilesDir, localizationDir} = context;
const {siteConfig, siteDir, generatedFilesDir, localizationDir, i18n} =
context;

const contentPaths: PagesContentPaths = {
contentPath: path.resolve(siteDir, options.path),
Expand Down Expand Up @@ -73,7 +77,7 @@ export default function pluginContentPages(
},

async loadContent() {
const {include} = options;
const {include, editUrl} = options;

if (!(await fs.pathExists(contentPaths.contentPath))) {
return null;
Expand Down Expand Up @@ -120,6 +124,50 @@ export default function pluginContentPages(
});
const frontMatter = validatePageFrontMatter(unsafeFrontMatter);

const pagesDirPath = await getFolderContainingFile(
getContentPathList(contentPaths),
relativeSource,
);

const pagesSourceAbsolute = path.join(pagesDirPath, relativeSource);

function getPagesEditUrl() {
const pagesPathRelative = path.relative(
pagesDirPath,
path.resolve(pagesSourceAbsolute),
);

if (typeof editUrl === 'function') {
return editUrl({
pagesDirPath: posixPath(path.relative(siteDir, pagesDirPath)),
pagesPath: posixPath(pagesPathRelative),
permalink,
locale: i18n.currentLocale,
});
} else if (typeof editUrl === 'string') {
const isLocalized =
pagesDirPath === contentPaths.contentPathLocalized;
const fileContentPath =
isLocalized && options.editLocalizedFiles
? contentPaths.contentPathLocalized
: contentPaths.contentPath;

const contentPathEditUrl = normalizeUrl([
editUrl,
posixPath(path.relative(siteDir, fileContentPath)),
]);

return getEditUrl(pagesPathRelative, contentPathEditUrl);
}
return undefined;
}

const lastUpdatedData = await readLastUpdateData(
source,
options,
frontMatter.last_update,
);

if (isDraft({frontMatter})) {
return undefined;
}
Expand All @@ -132,6 +180,9 @@ export default function pluginContentPages(
title: frontMatter.title ?? contentTitle,
description: frontMatter.description ?? excerpt,
frontMatter,
lastUpdatedBy: lastUpdatedData.lastUpdatedBy,
lastUpdatedAt: lastUpdatedData.lastUpdatedAt,
editUrl: getPagesEditUrl(),
unlisted,
};
}
Expand Down Expand Up @@ -160,12 +211,12 @@ export default function pluginContentPages(
const {addRoute, createData} = actions;

function createPageRouteMetadata(metadata: Metadata): RouteMetadata {
const lastUpdatedAt =
metadata.type === 'mdx' ? metadata.lastUpdatedAt : undefined;

return {
sourceFilePath: aliasedSitePathToRelativePath(metadata.source),
// TODO add support for last updated date in the page plugin
// at least for Markdown files
// lastUpdatedAt: metadata.lastUpdatedAt,
lastUpdatedAt: undefined,
lastUpdatedAt,
};
}

Expand Down
10 changes: 10 additions & 0 deletions packages/docusaurus-plugin-content-pages/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
RehypePluginsSchema,
AdmonitionsSchema,
RouteBasePathSchema,
URISchema,
} from '@docusaurus/utils-validation';
import {GlobExcludeDefault} from '@docusaurus/utils';
import type {OptionValidationContext} from '@docusaurus/types';
Expand All @@ -27,6 +28,9 @@ export const DEFAULT_OPTIONS: PluginOptions = {
beforeDefaultRehypePlugins: [],
beforeDefaultRemarkPlugins: [],
admonitions: true,
showLastUpdateTime: false,
showLastUpdateAuthor: false,
editLocalizedFiles: false,
};

const PluginOptionSchema = Joi.object<PluginOptions>({
Expand All @@ -44,6 +48,12 @@ const PluginOptionSchema = Joi.object<PluginOptions>({
DEFAULT_OPTIONS.beforeDefaultRemarkPlugins,
),
admonitions: AdmonitionsSchema.default(DEFAULT_OPTIONS.admonitions),
showLastUpdateTime: Joi.bool().default(DEFAULT_OPTIONS.showLastUpdateTime),
showLastUpdateAuthor: Joi.bool().default(
DEFAULT_OPTIONS.showLastUpdateAuthor,
),
editUrl: Joi.alternatives().try(URISchema, Joi.function()),
editLocalizedFiles: Joi.boolean().default(DEFAULT_OPTIONS.editLocalizedFiles),
});

export function validateOptions({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
declare module '@docusaurus/plugin-content-pages' {
import type {MDXOptions} from '@docusaurus/mdx-loader';
import type {LoadContext, Plugin} from '@docusaurus/types';
import type {FrontMatterLastUpdate, LastUpdateData} from '@docusaurus/utils';

export type Assets = {
image?: string;
Expand All @@ -20,6 +21,10 @@ declare module '@docusaurus/plugin-content-pages' {
include: string[];
exclude: string[];
mdxPageComponent: string;
showLastUpdateTime: boolean;
showLastUpdateAuthor: boolean;
editUrl?: string | EditUrlFunction;
editLocalizedFiles?: boolean;
};

export type Options = Partial<PluginOptions>;
Expand All @@ -35,6 +40,7 @@ declare module '@docusaurus/plugin-content-pages' {
readonly toc_max_heading_level?: number;
readonly draft?: boolean;
readonly unlisted?: boolean;
readonly last_update?: FrontMatterLastUpdate;
};

export type JSXPageMetadata = {
Expand All @@ -43,16 +49,31 @@ declare module '@docusaurus/plugin-content-pages' {
source: string;
};

export type MDXPageMetadata = {
export type MDXPageMetadata = LastUpdateData & {
type: 'mdx';
permalink: string;
source: string;
frontMatter: PageFrontMatter & {[key: string]: unknown};
editUrl?: string;
title?: string;
description?: string;
unlisted: boolean;
};

export type EditUrlFunction = (editUrlParams: {
/**
* The root content directory containing this post file, relative to the
* site path. Usually the same as `options.path` but can be localized
*/
pagesDirPath: string;
/** Path to this pages file, relative to `pagesDirPath`. */
pagesPath: string;
/** @see {@link PagesPostMetadata.permalink} */
permalink: string;
/** Locale name. */
locale: string;
}) => string | undefined;

export type Metadata = JSXPageMetadata | MDXPageMetadata;

export type LoadedContent = Metadata[];
Expand Down
Loading

0 comments on commit d1590e3

Please sign in to comment.