Skip to content

Commit

Permalink
Ensure author socials normalization is wired properly
Browse files Browse the repository at this point in the history
  • Loading branch information
slorber committed Jul 11, 2024
1 parent fd2b81a commit 8641bef
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 20 deletions.

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

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

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

Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,52 @@ describe('getBlogPostAuthors', () => {
]);
});

it('can normalize inline authors', () => {
expect(
getBlogPostAuthors({
frontMatter: {
authors: [
{
name: 'Seb1',
socials: {
x: 'https://x.com/sebastienlorber',
twitter: 'sebastienlorber',
github: 'slorber',
},
},
{
name: 'Seb2',
socials: {
x: 'sebastienlorber',
twitter: 'https://twitter.com/sebastienlorber',
github: 'https://github.com/slorber',
},
},
],
},
authorsMap: {},
baseUrl: '/',
}),
).toEqual([
{
name: 'Seb1',
socials: {
x: 'https://x.com/sebastienlorber',
twitter: 'https://twitter.com/sebastienlorber',
github: 'https://github.com/slorber',
},
},
{
name: 'Seb2',
socials: {
x: 'https://x.com/sebastienlorber',
twitter: 'https://twitter.com/sebastienlorber',
github: 'https://github.com/slorber',
},
},
]);
});

it('throw when using author key with no authorsMap', () => {
expect(() =>
getBlogPostAuthors({
Expand Down Expand Up @@ -412,6 +458,27 @@ describe('getAuthorsMap', () => {
}),
).resolves.toBeUndefined();
});

describe('getAuthorsMap returns normalized', () => {
it('socials', async () => {
const authorsMap = await getAuthorsMap({
contentPaths,
authorsMapPath: 'authors.yml',
});
expect(authorsMap.slorber.socials).toMatchInlineSnapshot(`
{
"twitter": "https://twitter.com/sebastienlorber",
"x": "https://x.com/sebastienlorber",
}
`);
expect(authorsMap.JMarcey.socials).toMatchInlineSnapshot(`
{
"twitter": "https://twitter.com/JoelMarcey",
"x": "https://x.com/JoelMarcey",
}
`);
});
});
});

describe('validateAuthorsMap', () => {
Expand Down
28 changes: 22 additions & 6 deletions packages/docusaurus-plugin-content-blog/src/authors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
* LICENSE file in the root directory of this source tree.
*/

import * as _ from 'lodash';
import {getDataFileData, normalizeUrl} from '@docusaurus/utils';
import {Joi, URISchema} from '@docusaurus/utils-validation';
import {normalizeSocials} from './authorsSocials';
import type {BlogContentPaths} from './types';
import type {
Author,
Expand Down Expand Up @@ -58,18 +60,32 @@ export function validateAuthorsMap(content: unknown): AuthorsMap {
return value;
}

function normalizeAuthor(author: Author): Author {
return {
...author,
socials: author.socials ? normalizeSocials(author.socials) : undefined,
};
}

function normalizeAuthorsMap(authorsMap: AuthorsMap): AuthorsMap {
return _.mapValues(authorsMap, normalizeAuthor);
}

export async function getAuthorsMap(params: {
authorsMapPath: string;
contentPaths: BlogContentPaths;
}): Promise<AuthorsMap | undefined> {
return getDataFileData(
const authorsMap = await getDataFileData(
{
filePath: params.authorsMapPath,
contentPaths: params.contentPaths,
fileType: 'authors map',
},
// TODO annoying to test: tightly coupled FS reads + validation...
validateAuthorsMap,
);

return authorsMap ? normalizeAuthorsMap(authorsMap) : undefined;
}

type AuthorsParam = {
Expand Down Expand Up @@ -122,7 +138,7 @@ function getFrontMatterAuthorLegacy({
function normalizeFrontMatterAuthors(
frontMatterAuthors: BlogPostFrontMatterAuthors = [],
): BlogPostFrontMatterAuthor[] {
function normalizeAuthor(
function normalizeFrontMatterAuthor(
authorInput: string | Author,
): BlogPostFrontMatterAuthor {
if (typeof authorInput === 'string') {
Expand All @@ -135,8 +151,8 @@ function normalizeFrontMatterAuthors(
}

return Array.isArray(frontMatterAuthors)
? frontMatterAuthors.map(normalizeAuthor)
: [normalizeAuthor(frontMatterAuthors)];
? frontMatterAuthors.map(normalizeFrontMatterAuthor)
: [normalizeFrontMatterAuthor(frontMatterAuthors)];
}

function getFrontMatterAuthors(params: AuthorsParam): Author[] {
Expand Down Expand Up @@ -165,11 +181,11 @@ ${Object.keys(authorsMap)
}

function toAuthor(frontMatterAuthor: BlogPostFrontMatterAuthor): Author {
return {
return normalizeAuthor({
// Author def from authorsMap can be locally overridden by front matter
...getAuthorsMapAuthor(frontMatterAuthor.key),
...frontMatterAuthor,
};
});
}

return frontMatterAuthors.map(toAuthor);
Expand Down
8 changes: 0 additions & 8 deletions packages/docusaurus-plugin-content-blog/src/blogUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import {getTagsFile} from '@docusaurus/utils-validation';
import {validateBlogPostFrontMatter} from './frontMatter';
import {type AuthorsMap, getAuthorsMap, getBlogPostAuthors} from './authors';
import {reportAuthorsProblems} from './authorsProblems';
import {normalizeSocials} from './authorsSocials';
import type {TagsFile} from '@docusaurus/utils';
import type {LoadContext, ParseFrontMatter} from '@docusaurus/types';
import type {
Expand Down Expand Up @@ -384,13 +383,6 @@ export async function generateBlogPosts(
authorsMapPath: options.authorsMapPath,
});

if (authorsMap) {
Object.entries(authorsMap).forEach(([, author]) => {
if (author.socials) {
author.socials = normalizeSocials(author.socials);
}
});
}
const tagsFile = await getTagsFile({contentPaths, tags: options.tags});

async function doProcessBlogSourceFile(blogSourceFile: string) {
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus-utils/src/dataFileUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export async function getDataFileData<T>(
try {
const contentString = await fs.readFile(filePath, {encoding: 'utf8'});
const unsafeContent = Yaml.load(contentString);
// TODO we shouldn't validate here: it makes validation harder to test
return validate(unsafeContent);
} catch (err) {
logger.error`The ${params.fileType} file at path=${filePath} looks invalid.`;
Expand Down
8 changes: 4 additions & 4 deletions website/_dogfooding/_blog tests/2024-07-03-dual-author.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ authors:
- name: Sébastien Lorber
imageURL: https://github.com/slorber.png
socials:
twitter: https://x.com/sebastienlorber
github: https://github.com/slorber
stackoverflow: https://stackoverflow.com/users/82609/sebastien-lorber
linkedin: https://www.linkedin.com/in/sebastienlorber/
twitter: sebastienlorber
github: slorber
stackoverflow: /users/82609/sebastien-lorber
linkedin: sebastienlorber
newsletter: https://thisweekinreact.com/newsletter
- name: Sébastien Lorber
imageURL: https://github.com/slorber.png
Expand Down

0 comments on commit 8641bef

Please sign in to comment.