mirror of
https://github.com/facebook/docusaurus.git
synced 2025-12-26 01:33:02 +00:00
fix(blog): normalize inline authors socials (#10424)
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Some checks are pending
Argos CI / take-screenshots (push) Waiting to run
Build Hash Router / Build Hash Router (push) Waiting to run
Canary Release / Publish Canary (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
Continuous Releases / Continuous Releases (push) Waiting to run
E2E Tests / E2E — Yarn v1 (18.0) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (20) (push) Waiting to run
E2E Tests / E2E — Yarn v1 (22) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (node-modules, -st) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -s) (push) Waiting to run
E2E Tests / E2E — Yarn Berry (pnp, -st) (push) Waiting to run
E2E Tests / E2E — npm (push) Waiting to run
E2E Tests / E2E — pnpm (push) Waiting to run
Co-authored-by: OzakIOne <OzakIOne@users.noreply.github.com> Co-authored-by: Sébastien Lorber <slorber@users.noreply.github.com>
This commit is contained in:
parent
200b38b763
commit
2aef92cb9e
|
|
@ -7,7 +7,11 @@
|
|||
|
||||
import {fromPartial, type PartialDeep} from '@total-typescript/shoehorn';
|
||||
import {getBlogPostAuthors, groupBlogPostsByAuthorKey} from '../authors';
|
||||
import type {AuthorsMap, BlogPost} from '@docusaurus/plugin-content-blog';
|
||||
import type {
|
||||
AuthorAttributes,
|
||||
AuthorsMap,
|
||||
BlogPost,
|
||||
} from '@docusaurus/plugin-content-blog';
|
||||
|
||||
function post(partial: PartialDeep<BlogPost>): BlogPost {
|
||||
return fromPartial(partial);
|
||||
|
|
@ -268,11 +272,90 @@ describe('getBlogPostAuthors', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('can read authors Author', () => {
|
||||
it('read different values from socials', () => {
|
||||
function testSocials(socials: AuthorAttributes['socials'] | undefined) {
|
||||
return getBlogPostAuthors({
|
||||
frontMatter: {
|
||||
authors: {
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
socials,
|
||||
},
|
||||
},
|
||||
authorsMap: undefined,
|
||||
baseUrl: '/',
|
||||
});
|
||||
}
|
||||
|
||||
// @ts-expect-error test
|
||||
expect(() => testSocials(null)).not.toThrow();
|
||||
// @ts-expect-error test
|
||||
expect(testSocials(null)).toEqual([
|
||||
{
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
imageURL: undefined,
|
||||
socials: {},
|
||||
key: null,
|
||||
page: null,
|
||||
},
|
||||
]);
|
||||
expect(() => () => testSocials(undefined)).not.toThrow();
|
||||
// @ts-expect-error test
|
||||
expect(() => testSocials({twitter: undefined}))
|
||||
.toThrowErrorMatchingInlineSnapshot(`
|
||||
"Author socials should be usernames/userIds/handles, or fully qualified HTTP(s) absolute URLs.
|
||||
Social platform 'twitter' has illegal value 'undefined'"
|
||||
`);
|
||||
expect(
|
||||
// @ts-expect-error test
|
||||
() => testSocials({twitter: null}),
|
||||
).toThrowErrorMatchingInlineSnapshot(`
|
||||
"Author socials should be usernames/userIds/handles, or fully qualified HTTP(s) absolute URLs.
|
||||
Social platform 'twitter' has illegal value 'null'"
|
||||
`);
|
||||
});
|
||||
|
||||
it('can read empty socials', () => {
|
||||
expect(
|
||||
getBlogPostAuthors({
|
||||
frontMatter: {
|
||||
authors: {name: 'Sébastien Lorber', title: 'maintainer'},
|
||||
authors: {
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
socials: {},
|
||||
},
|
||||
},
|
||||
authorsMap: undefined,
|
||||
baseUrl: '/',
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
imageURL: undefined,
|
||||
socials: {},
|
||||
key: null,
|
||||
page: null,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('can normalize full socials from Author', () => {
|
||||
expect(
|
||||
getBlogPostAuthors({
|
||||
frontMatter: {
|
||||
authors: {
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
socials: {
|
||||
github: 'https://github.com/slorber',
|
||||
linkedin: 'https://www.linkedin.com/in/sebastienlorber/',
|
||||
stackoverflow: 'https://stackoverflow.com/users/82609',
|
||||
twitter: 'https://twitter.com/sebastienlorber',
|
||||
x: 'https://x.com/sebastienlorber',
|
||||
},
|
||||
},
|
||||
},
|
||||
authorsMap: undefined,
|
||||
baseUrl: '/',
|
||||
|
|
@ -283,18 +366,81 @@ describe('getBlogPostAuthors', () => {
|
|||
title: 'maintainer',
|
||||
imageURL: undefined,
|
||||
key: null,
|
||||
socials: {
|
||||
github: 'https://github.com/slorber',
|
||||
linkedin: 'https://www.linkedin.com/in/sebastienlorber/',
|
||||
stackoverflow: 'https://stackoverflow.com/users/82609',
|
||||
twitter: 'https://twitter.com/sebastienlorber',
|
||||
x: 'https://x.com/sebastienlorber',
|
||||
},
|
||||
page: null,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('can read authors Author[]', () => {
|
||||
it('can normalize handle socials from Author', () => {
|
||||
expect(
|
||||
getBlogPostAuthors({
|
||||
frontMatter: {
|
||||
authors: {
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
socials: {
|
||||
github: 'slorber',
|
||||
x: 'sebastienlorber',
|
||||
linkedin: 'sebastienlorber',
|
||||
stackoverflow: '82609',
|
||||
twitter: 'sebastienlorber',
|
||||
},
|
||||
},
|
||||
},
|
||||
authorsMap: undefined,
|
||||
baseUrl: '/',
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
imageURL: undefined,
|
||||
key: null,
|
||||
socials: {
|
||||
github: 'https://github.com/slorber',
|
||||
linkedin: 'https://www.linkedin.com/in/sebastienlorber/',
|
||||
stackoverflow: 'https://stackoverflow.com/users/82609',
|
||||
twitter: 'https://twitter.com/sebastienlorber',
|
||||
x: 'https://x.com/sebastienlorber',
|
||||
},
|
||||
page: null,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('can normalize socials from Author[]', () => {
|
||||
expect(
|
||||
getBlogPostAuthors({
|
||||
frontMatter: {
|
||||
authors: [
|
||||
{name: 'Sébastien Lorber', title: 'maintainer'},
|
||||
{name: 'Yangshun Tay'},
|
||||
{
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
socials: {
|
||||
github: 'slorber',
|
||||
x: 'sebastienlorber',
|
||||
linkedin: 'sebastienlorber',
|
||||
stackoverflow: '82609',
|
||||
twitter: 'sebastienlorber',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Seb',
|
||||
socials: {
|
||||
github: 'https://github.com/slorber',
|
||||
linkedin: 'https://www.linkedin.com/in/sebastienlorber/',
|
||||
stackoverflow: 'https://stackoverflow.com/users/82609',
|
||||
twitter: 'https://twitter.com/sebastienlorber',
|
||||
x: 'https://x.com/sebastienlorber',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
authorsMap: undefined,
|
||||
|
|
@ -306,9 +452,64 @@ describe('getBlogPostAuthors', () => {
|
|||
title: 'maintainer',
|
||||
imageURL: undefined,
|
||||
key: null,
|
||||
socials: {
|
||||
github: 'https://github.com/slorber',
|
||||
linkedin: 'https://www.linkedin.com/in/sebastienlorber/',
|
||||
stackoverflow: 'https://stackoverflow.com/users/82609',
|
||||
twitter: 'https://twitter.com/sebastienlorber',
|
||||
x: 'https://x.com/sebastienlorber',
|
||||
},
|
||||
page: null,
|
||||
},
|
||||
{
|
||||
name: 'Seb',
|
||||
imageURL: undefined,
|
||||
key: null,
|
||||
socials: {
|
||||
github: 'https://github.com/slorber',
|
||||
linkedin: 'https://www.linkedin.com/in/sebastienlorber/',
|
||||
stackoverflow: 'https://stackoverflow.com/users/82609',
|
||||
twitter: 'https://twitter.com/sebastienlorber',
|
||||
x: 'https://x.com/sebastienlorber',
|
||||
},
|
||||
page: null,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('can read authors Author[]', () => {
|
||||
expect(
|
||||
getBlogPostAuthors({
|
||||
frontMatter: {
|
||||
authors: [
|
||||
{
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
},
|
||||
{
|
||||
name: 'Yangshun Tay',
|
||||
},
|
||||
],
|
||||
},
|
||||
authorsMap: undefined,
|
||||
baseUrl: '/',
|
||||
}),
|
||||
).toEqual([
|
||||
{
|
||||
name: 'Sébastien Lorber',
|
||||
title: 'maintainer',
|
||||
imageURL: undefined,
|
||||
key: null,
|
||||
socials: {},
|
||||
page: null,
|
||||
},
|
||||
{
|
||||
name: 'Yangshun Tay',
|
||||
imageURL: undefined,
|
||||
socials: {},
|
||||
key: null,
|
||||
page: null,
|
||||
},
|
||||
{name: 'Yangshun Tay', imageURL: undefined, key: null, page: null},
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -323,7 +524,12 @@ describe('getBlogPostAuthors', () => {
|
|||
title: 'Yangshun title local override',
|
||||
extra: 42,
|
||||
},
|
||||
{name: 'Alexey'},
|
||||
{
|
||||
name: 'Alexey',
|
||||
socials: {
|
||||
github: 'lex111',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
authorsMap: {
|
||||
|
|
@ -355,10 +561,19 @@ describe('getBlogPostAuthors', () => {
|
|||
name: 'Yangshun Tay',
|
||||
title: 'Yangshun title local override',
|
||||
extra: 42,
|
||||
socials: {},
|
||||
imageURL: undefined,
|
||||
page: null,
|
||||
},
|
||||
{name: 'Alexey', imageURL: undefined, key: null, page: null},
|
||||
{
|
||||
name: 'Alexey',
|
||||
imageURL: undefined,
|
||||
key: null,
|
||||
page: null,
|
||||
socials: {
|
||||
github: 'https://github.com/lex111',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -627,6 +842,7 @@ describe('getBlogPostAuthors', () => {
|
|||
imageURL: './ozaki.png',
|
||||
key: null,
|
||||
page: null,
|
||||
socials: {},
|
||||
},
|
||||
]);
|
||||
expect(() => withoutBaseUrlTest).not.toThrow();
|
||||
|
|
@ -635,6 +851,7 @@ describe('getBlogPostAuthors', () => {
|
|||
imageURL: './ozaki.png',
|
||||
key: null,
|
||||
page: null,
|
||||
socials: {},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
@ -654,6 +871,7 @@ describe('getBlogPostAuthors', () => {
|
|||
imageURL: '/ozaki.png',
|
||||
key: null,
|
||||
page: null,
|
||||
socials: {},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
@ -673,6 +891,7 @@ describe('getBlogPostAuthors', () => {
|
|||
imageURL: '/img/ozaki.png',
|
||||
key: null,
|
||||
page: null,
|
||||
socials: {},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
@ -692,6 +911,7 @@ describe('getBlogPostAuthors', () => {
|
|||
imageURL: '/img/ozaki.png',
|
||||
key: null,
|
||||
page: null,
|
||||
socials: {},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
@ -711,6 +931,7 @@ describe('getBlogPostAuthors', () => {
|
|||
imageURL: '/img/img/ozaki.png',
|
||||
key: null,
|
||||
page: null,
|
||||
socials: {},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ describe('authors socials', () => {
|
|||
});
|
||||
|
||||
it('throw socials that are not strings', () => {
|
||||
const authorsMap: AuthorsMapInput = {
|
||||
const socialNumber: AuthorsMapInput = {
|
||||
ozaki: {
|
||||
name: 'ozaki',
|
||||
socials: {
|
||||
|
|
@ -318,11 +318,39 @@ describe('authors socials', () => {
|
|||
},
|
||||
};
|
||||
|
||||
const socialNull: AuthorsMapInput = {
|
||||
ozaki: {
|
||||
name: 'ozaki',
|
||||
socials: {
|
||||
// @ts-expect-error: for tests
|
||||
twitter: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const socialNull2: AuthorsMapInput = {
|
||||
ozaki: {
|
||||
name: 'ozaki',
|
||||
// @ts-expect-error: for tests
|
||||
socials: null,
|
||||
},
|
||||
};
|
||||
|
||||
expect(() =>
|
||||
validateAuthorsMap(authorsMap),
|
||||
validateAuthorsMap(socialNumber),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`""ozaki.socials.twitter" must be a string"`,
|
||||
);
|
||||
expect(() =>
|
||||
validateAuthorsMap(socialNull),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`""ozaki.socials.twitter" must be a string"`,
|
||||
);
|
||||
expect(() =>
|
||||
validateAuthorsMap(socialNull2),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`""ozaki.socials" should be an author object containing properties like name, title, and imageURL."`,
|
||||
);
|
||||
});
|
||||
|
||||
it('throw socials that are objects', () => {
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ describe('blog plugin', () => {
|
|||
imageURL: undefined,
|
||||
key: null,
|
||||
page: null,
|
||||
socials: {},
|
||||
},
|
||||
{
|
||||
email: 'lorber.sebastien@gmail.com',
|
||||
|
|
@ -231,6 +232,7 @@ describe('blog plugin', () => {
|
|||
name: 'Sébastien Lorber (translated)',
|
||||
title: 'Docusaurus maintainer (translated)',
|
||||
imageURL: undefined,
|
||||
socials: undefined,
|
||||
page: {permalink: '/blog/authors/slorber-custom-permalink-localized'},
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
import {normalizeUrl} from '@docusaurus/utils';
|
||||
import {normalizeSocials} from './authorsSocials';
|
||||
import type {
|
||||
Author,
|
||||
AuthorsMap,
|
||||
|
|
@ -107,7 +108,10 @@ function getFrontMatterAuthors(params: AuthorsParam): Author[] {
|
|||
// becoming a name and may end up unnoticed
|
||||
return {key: authorInput};
|
||||
}
|
||||
return authorInput;
|
||||
return {
|
||||
...authorInput,
|
||||
socials: normalizeSocials(authorInput.socials ?? {}),
|
||||
};
|
||||
}
|
||||
|
||||
return Array.isArray(frontMatter.authors)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@ type SocialEntry = [string, string];
|
|||
|
||||
function normalizeSocialEntry([platform, value]: SocialEntry): SocialEntry {
|
||||
const normalizer = PredefinedPlatformNormalizers[platform.toLowerCase()];
|
||||
if (typeof value !== 'string') {
|
||||
throw new Error(
|
||||
`Author socials should be usernames/userIds/handles, or fully qualified HTTP(s) absolute URLs.
|
||||
Social platform '${platform}' has illegal value '${value}'`,
|
||||
);
|
||||
}
|
||||
const isAbsoluteUrl =
|
||||
value.startsWith('http://') || value.startsWith('https://');
|
||||
if (isAbsoluteUrl) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue