Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(blog): slug/pathname aliases for blog posts #8356

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -197,6 +197,7 @@ describe('linkify', () => {
id: 'Happy 1st Birthday Slash!',
metadata: {
permalink: '/blog/2018/12/14/Happy-First-Birthday-Slash',
aliases: undefined,
source: path.posix.join(
'@site',
pluginDir,
Expand All @@ -214,6 +215,7 @@ describe('linkify', () => {
frontMatter: {},
authors: [],
formattedDate: '',
unlisted: false,
},
content: '',
},
Expand Down
Expand Up @@ -282,6 +282,23 @@ describe('validateBlogPostFrontMatter slug', () => {
});
});

describe('validateBlogPostFrontMatter aliases', () => {
testField({
prefix: 'aliases',
validFrontMatters: [
{aliases: ['blog/']},
{aliases: ['/blog']},
{aliases: ['/blog/']},
{aliases: ['./blog']},
{aliases: ['../blog']},
{aliases: ['../../blog']},
{aliases: ['/api/plugins/@docusaurus/plugin-debug']},
{aliases: ['@site/api/asset/image.png']},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should accept such value 😅

This code is unlikely to yield a great pathname

normalizeUrl([baseUrl, routeBasePath, alias])

and the tests do not cover these edge cases.


The question to me is: do we want to support relative aliases?

Is this really useful? I mean, you create a relative alias, then update the slug, and then you end up with a different alias. That might be a source of bug/confusion?

If we do want relative aliases, there's a resolvePathname util that could probably be applied to compute the final non-relative pathname of the alias.

But I would suggest to keep it simple for now and only accept absolute pathname aliases in validation? If someone wants a relative alias someday and has great reason to add it, we'll do an update.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question to me is: do we want to support relative aliases?

Probably not - will amend

],
invalidFrontMatters: [[{aliases: ['']}, 'not allowed to be empty']],
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
});
});

describe('validateBlogPostFrontMatter image', () => {
testField({
prefix: 'image',
Expand Down
Expand Up @@ -149,6 +149,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',
Expand All @@ -159,6 +160,7 @@ describe('blog plugin', () => {
frontMatter: {
date: new Date('2019-01-01'),
tags: ['date'],
aliases: ['/alias1', '/alias2'],
},
prevItem: undefined,
tags: [
Expand Down
6 changes: 6 additions & 0 deletions packages/docusaurus-plugin-content-blog/src/blogUtils.ts
Expand Up @@ -283,6 +283,11 @@ async function processBlogSourceFile(
const slug = frontMatter.slug ?? parsedBlogFileName.slug;

const permalink = normalizeUrl([baseUrl, routeBasePath, slug]);
const aliases = frontMatter.aliases
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
? frontMatter.aliases.map((alias) =>
normalizeUrl([baseUrl, routeBasePath, alias]),
)
: undefined;

function getBlogEditUrl() {
const blogPathRelative = path.relative(
Expand Down Expand Up @@ -325,6 +330,7 @@ async function processBlogSourceFile(
id: slug,
metadata: {
permalink,
aliases,
editUrl: getBlogEditUrl(),
source: aliasedSource,
title,
Expand Down
Expand Up @@ -64,6 +64,7 @@ const BlogFrontMatterSchema = Joi.object<BlogPostFrontMatter>({
// .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(),
Expand Down
14 changes: 14 additions & 0 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Expand Up @@ -274,6 +274,20 @@ export default async function pluginContentBlog(
},
});

if (metadata.aliases) {
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
metadata.aliases.forEach((alias) => {
addRoute({
path: alias,
component: blogPostComponent,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, this would create two pages with the same content? Isn't it simpler to set up redirects instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Josh-Cena,

The context for this is in @slorber's comment here: #8311 (reply in thread)

---
slug: /2022/11/17/azure-ad-claims-static-web-apps-azure-functions
aliases: ["/"] # NEW FEATURE
---

# Azure AD Claims with Static Web Apps and Azure Functions

Text

The aliasing feature would create extra pages for another slug (that can be /)

It gives the ability to keep a shared canonical URL for both pages and avoid SEO content being flagged as duplicate.

Does this make sense?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes that makes sense to me, and we'll likely want to add something similar to individual docs for consistency

exact: true,
modules: {
sidebar: aliasedSource(sidebarProp),
content: metadata.source,
},
});
});
}

blogItemsToMetadata[id] = metadata;
}),
);
Expand Down
Expand Up @@ -86,6 +86,11 @@ declare module '@docusaurus/plugin-content-blog' {
tags?: FrontMatterTag[];
/** Custom slug appended after `/<baseUrl>/<routeBasePath>/` */
slug?: string;
/**
* Alias URLs appended after `/<baseUrl>/<routeBasePath>/`
* If supplied these pages will point to the canonical URL.
*/
aliases?: string[];
/**
* Marks the post as draft and excludes it from the production build.
*/
Expand Down Expand Up @@ -190,6 +195,8 @@ declare module '@docusaurus/plugin-content-blog' {
readonly formattedDate: string;
/** Full link including base URL. */
readonly permalink: string;
/** Alias full links including base URL. */
readonly aliases: string[] | undefined;
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
/**
* Description used in the meta. Could be an empty string (empty content)
*/
Expand Down