diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/date-matter.md b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/date-matter.md index 139048ea4ebf..69482c95c689 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/date-matter.md +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/website/blog/date-matter.md @@ -1,6 +1,7 @@ --- date: 2019-01-01 tags: [date] +aliases: ['/alias1', '/alias2'] --- date inside front matter diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/blogUtils.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/blogUtils.test.ts index 3ec0e9d9f90a..54d31173de7c 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/blogUtils.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/blogUtils.test.ts @@ -197,6 +197,7 @@ describe('linkify', () => { id: 'Happy 1st Birthday Slash!', metadata: { permalink: '/blog/2018/12/14/Happy-First-Birthday-Slash', + aliases: [], source: path.posix.join( '@site', pluginDir, @@ -214,6 +215,7 @@ describe('linkify', () => { frontMatter: {}, authors: [], formattedDate: '', + unlisted: false, }, content: '', }, diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/frontMatter.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/frontMatter.test.ts index 9c05dcca944a..4d78a252687a 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/frontMatter.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/frontMatter.test.ts @@ -282,6 +282,21 @@ describe('validateBlogPostFrontMatter slug', () => { }); }); +describe('validateBlogPostFrontMatter aliases', () => { + testField({ + prefix: 'aliases', + validFrontMatters: [ + {aliases: ['another-blog-url']}, + {aliases: ['and-another']}, + ], + invalidFrontMatters: [ + [{aliases: ['']}, 'not allowed to be empty'], + [{aliases: null}, 'must be an array'], + [{aliases: [null]}, 'must be a string'], + ], + }); +}); + describe('validateBlogPostFrontMatter image', () => { testField({ prefix: 'image', diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index 51b2f63f2fe7..e94ffdc484bd 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -169,6 +169,7 @@ describe('blog plugin', () => { }).toEqual({ editUrl: `${BaseEditUrl}/blog/date-matter.md`, permalink: '/blog/date-matter', + aliases: ['/blog/alias1', '/blog/alias2'], readingTime: 0.02, source: path.posix.join('@site', PluginPath, 'date-matter.md'), title: 'date-matter', @@ -179,6 +180,7 @@ describe('blog plugin', () => { frontMatter: { date: new Date('2019-01-01'), tags: ['date'], + aliases: ['/alias1', '/alias2'], }, prevItem: undefined, tags: [ @@ -208,6 +210,7 @@ describe('blog plugin', () => { ), title: 'Happy 1st Birthday Slash! (translated)', description: `Happy birthday! (translated)`, + aliases: [], authors: [ { name: 'Yangshun Tay (translated)', @@ -249,6 +252,7 @@ describe('blog plugin', () => { source: path.posix.join('@site', PluginPath, 'complex-slug.md'), title: 'Complex Slug', description: `complex url slug`, + aliases: [], authors: [], prevItem: undefined, nextItem: { @@ -288,6 +292,7 @@ describe('blog plugin', () => { source: path.posix.join('@site', PluginPath, 'simple-slug.md'), title: 'Simple Slug', description: `simple url slug`, + aliases: [], authors: [ { name: 'Sébastien Lorber', @@ -326,6 +331,7 @@ describe('blog plugin', () => { source: path.posix.join('@site', PluginPath, 'heading-as-title.md'), title: 'some heading', description: '', + aliases: [], authors: [], date: new Date('2019-01-02'), formattedDate: 'January 2, 2019', @@ -492,6 +498,7 @@ describe('blog plugin', () => { source: noDateSource, title: 'no date', description: `no date`, + aliases: [], authors: [], date: noDateSourceTime, formattedDate, diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 3bbb5301bf92..ca6a7ac19941 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -298,6 +298,11 @@ async function processBlogSourceFile( const slug = frontMatter.slug ?? parsedBlogFileName.slug; const permalink = normalizeUrl([baseUrl, routeBasePath, slug]); + const aliases = frontMatter.aliases + ? frontMatter.aliases.map((alias) => + normalizeUrl([baseUrl, routeBasePath, alias]), + ) + : []; function getBlogEditUrl() { const blogPathRelative = path.relative( @@ -340,6 +345,7 @@ async function processBlogSourceFile( id: slug, metadata: { permalink, + aliases, editUrl: getBlogEditUrl(), source: aliasedSource, title, diff --git a/packages/docusaurus-plugin-content-blog/src/frontMatter.ts b/packages/docusaurus-plugin-content-blog/src/frontMatter.ts index 73b4d37d25ee..e063e0325cda 100644 --- a/packages/docusaurus-plugin-content-blog/src/frontMatter.ts +++ b/packages/docusaurus-plugin-content-blog/src/frontMatter.ts @@ -64,6 +64,7 @@ const BlogFrontMatterSchema = Joi.object({ // .warning('deprecate.error', { alternative: '"author_image_url"'}), slug: Joi.string(), + aliases: Joi.array().items(Joi.string().required()), image: URISchema, keywords: Joi.array().items(Joi.string().required()), hide_table_of_contents: Joi.boolean(), diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 4605877ed75b..abe0535f705d 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -276,6 +276,18 @@ export default async function pluginContentBlog( }, }); + metadata.aliases.forEach((alias) => { + addRoute({ + path: alias, + component: blogPostComponent, + exact: true, + modules: { + sidebar: aliasedSource(sidebarProp), + content: metadata.source, + }, + }); + }); + blogItemsToMetadata[id] = metadata; }), ); diff --git a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts index b1915f75196f..08511cb9106b 100644 --- a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts +++ b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts @@ -93,6 +93,11 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the tags?: FrontMatterTag[]; /** Custom slug appended after `///` */ slug?: string; + /** + * Alias URLs appended after `///` + * If supplied these pages will point to the canonical URL. + */ + aliases?: string[]; /** * Marks the post as draft and excludes it from the production build. */ @@ -197,6 +202,8 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the readonly formattedDate: string; /** Full link including base URL. */ readonly permalink: string; + /** Alias full links including base URL. */ + readonly aliases: string[]; /** * Description used in the meta. Could be an empty string (empty content) */