From c9d04f7d7ff3ede98c2bdd36f6b915bd22e720cf Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:02:06 +0200 Subject: [PATCH 1/7] fix: apply baseUrl to relative image --- .../__fixtures__/authorsMapFiles/authors.yml | 5 +++++ .../src/__tests__/authorsMap.test.ts | 14 ++++++++++++++ .../src/authorsMap.ts | 11 ++++++++++- .../docusaurus-plugin-content-blog/src/index.ts | 1 + 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml index 1d0cb11cd6ea..26338ad9fe8f 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml @@ -32,3 +32,8 @@ lex111: title: Open-source enthusiast url: https://github.com/lex111 image_url: https://github.com/lex111.png + +ozaki: + name: ozaki + title: ozaki + image_url: /img/ozaki.jpg diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts index b6393ede6854..4330dc5afcd1 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts @@ -80,6 +80,7 @@ describe('getAuthorsMap', () => { contentPaths, authorsMapPath: 'authors.yml', authorsBaseRoutePath: '/authors', + baseUrl: '/', }), ).resolves.toBeDefined(); }); @@ -90,6 +91,7 @@ describe('getAuthorsMap', () => { contentPaths, authorsMapPath: 'authors.json', authorsBaseRoutePath: '/authors', + baseUrl: '/', }), ).resolves.toBeDefined(); }); @@ -100,9 +102,21 @@ describe('getAuthorsMap', () => { contentPaths, authorsMapPath: 'authors_does_not_exist.yml', authorsBaseRoutePath: '/authors', + baseUrl: '/', }), ).resolves.toBeUndefined(); }); + + it('getAuthorsMap can return img with relative path if baseUrl is set', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/baseUrl', + }); + expect(authorsMap).toBeDefined(); + expect(authorsMap?.ozaki?.imageURL).toBe('/baseUrl/img/ozaki.jpg'); + }); }); describe('validateAuthorsMapInput', () => { diff --git a/packages/docusaurus-plugin-content-blog/src/authorsMap.ts b/packages/docusaurus-plugin-content-blog/src/authorsMap.ts index d1378aa3f26d..020845f9b975 100644 --- a/packages/docusaurus-plugin-content-blog/src/authorsMap.ts +++ b/packages/docusaurus-plugin-content-blog/src/authorsMap.ts @@ -93,10 +93,12 @@ export function checkAuthorsMapPermalinkCollisions( function normalizeAuthor({ authorsBaseRoutePath, authorKey, + baseUrl, author, }: { authorsBaseRoutePath: string; authorKey: string; + baseUrl: string; author: AuthorInput; }): Author & {key: string} { function getAuthorPage(): AuthorPage | null { @@ -109,11 +111,15 @@ function normalizeAuthor({ permalink: normalizeUrl([authorsBaseRoutePath, slug]), }; } + console.log('baseUrl:', baseUrl); return { ...author, key: authorKey, page: getAuthorPage(), + imageURL: author.imageURL?.startsWith('/') + ? normalizeUrl([baseUrl, author.imageURL]) + : author.imageURL, socials: author.socials ? normalizeSocials(author.socials) : undefined, }; } @@ -121,12 +127,14 @@ function normalizeAuthor({ function normalizeAuthorsMap({ authorsBaseRoutePath, authorsMapInput, + baseUrl, }: { authorsBaseRoutePath: string; authorsMapInput: AuthorsMapInput; + baseUrl: string; }): AuthorsMap { return _.mapValues(authorsMapInput, (author, authorKey) => { - return normalizeAuthor({authorsBaseRoutePath, authorKey, author}); + return normalizeAuthor({authorsBaseRoutePath, authorKey, author, baseUrl}); }); } @@ -153,6 +161,7 @@ export async function getAuthorsMap(params: { authorsMapPath: string; authorsBaseRoutePath: string; contentPaths: BlogContentPaths; + baseUrl: string; }): Promise { const authorsMapInput = await getAuthorsMapInput(params); if (!authorsMapInput) { diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts index 7ae3b5a54c79..e624afd0a750 100644 --- a/packages/docusaurus-plugin-content-blog/src/index.ts +++ b/packages/docusaurus-plugin-content-blog/src/index.ts @@ -177,6 +177,7 @@ export default async function pluginContentBlog( routeBasePath, authorsBasePath, ]), + baseUrl, }); checkAuthorsMapPermalinkCollisions(authorsMap); From 4f0214fd0b5d0b4ae52fd1a3d7bec9f9db0f92fd Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Fri, 23 Aug 2024 17:14:40 +0200 Subject: [PATCH 2/7] fix: baseUrl duplication --- packages/docusaurus-plugin-content-blog/src/authors.ts | 2 +- packages/docusaurus-plugin-content-blog/src/authorsMap.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts index 1fe0ef923815..242e6f52b8c6 100644 --- a/packages/docusaurus-plugin-content-blog/src/authors.ts +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -28,7 +28,7 @@ function normalizeImageUrl({ imageURL: string | undefined; baseUrl: string; }) { - return imageURL?.startsWith('/') + return imageURL?.startsWith('/') && !imageURL.startsWith(baseUrl) ? normalizeUrl([baseUrl, imageURL]) : imageURL; } diff --git a/packages/docusaurus-plugin-content-blog/src/authorsMap.ts b/packages/docusaurus-plugin-content-blog/src/authorsMap.ts index 020845f9b975..184d53720665 100644 --- a/packages/docusaurus-plugin-content-blog/src/authorsMap.ts +++ b/packages/docusaurus-plugin-content-blog/src/authorsMap.ts @@ -111,7 +111,6 @@ function normalizeAuthor({ permalink: normalizeUrl([authorsBaseRoutePath, slug]), }; } - console.log('baseUrl:', baseUrl); return { ...author, From df86b3b4d9eea9b09dfd47a1b18299e4ecc2de88 Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:57:56 +0200 Subject: [PATCH 3/7] add tests --- .../__fixtures__/authorsMapFiles/authors.yml | 8 +- .../src/__tests__/authors.test.ts | 192 +++++++++++++++++- .../src/__tests__/authorsMap.test.ts | 69 ++++++- .../src/authors.ts | 10 +- .../src/authorsMap.ts | 5 +- 5 files changed, 263 insertions(+), 21 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml index 26338ad9fe8f..0dffb1f16c8a 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__fixtures__/authorsMapFiles/authors.yml @@ -1,4 +1,3 @@ - JMarcey: name: Joel Marcey title: Technical Lead & Developer Advocate at Facebook @@ -36,4 +35,9 @@ lex111: ozaki: name: ozaki title: ozaki - image_url: /img/ozaki.jpg + image_url: /ozaki.png + +ozakione: + name: ozakione + title: ozakione + image_url: /img/ozaki.png diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts index 7072e8124caa..40b82502ca23 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts @@ -227,7 +227,7 @@ describe('getBlogPostAuthors', () => { { key: 'slorber', name: 'Sébastien Lorber', - imageURL: '/baseUrl/img/slorber.png', + imageURL: '/img/slorber.png', page: null, }, ]); @@ -522,3 +522,193 @@ describe('groupBlogPostsByAuthorKey', () => { }); }); }); + +describe('getBlogPostAuthors baseUrl', () => { + // Global author without baseUrl + it('getBlogPostAuthors do not modify global authors imageUrl without baseUrl', async () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: ['ozaki'], + }, + authorsMap: { + ozaki: { + name: 'ozaki', + key: 'ozaki', + imageURL: 'ozaki.png', + page: null, + }, + }, + baseUrl: '/', + }), + ).toEqual([ + { + imageURL: 'ozaki.png', + key: 'ozaki', + name: 'ozaki', + page: null, + }, + ]); + }); + + // Global author with baseUrl + it('getBlogPostAuthors do not modify global authors imageUrl with baseUrl', async () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: ['ozaki'], + }, + authorsMap: { + ozaki: { + name: 'ozaki', + key: 'ozaki', + imageURL: 'ozaki.png', + page: null, + }, + }, + baseUrl: '/img/', + }), + ).toEqual([ + { + imageURL: 'ozaki.png', + key: 'ozaki', + name: 'ozaki', + page: null, + }, + ]); + }); + + // Inline author without baseUrl + it('getBlogPostAuthors can return imageURL without baseUrl for inline authors', async () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: [{name: 'ozaki', imageURL: 'ozaki.png'}], + }, + authorsMap: undefined, + baseUrl: '/', + }), + ).toEqual([ + { + imageURL: 'ozaki.png', + key: null, + name: 'ozaki', + page: null, + }, + ]); + }); + + // Inline author with baseUrl + it('getBlogPostAuthors normalize imageURL with baseUrl for inline authors', async () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: [{name: 'ozaki', imageURL: '/ozaki.png'}], + }, + authorsMap: undefined, + baseUrl: '/img/', + }), + ).toEqual([ + { + imageURL: '/img/ozaki.png', + key: null, + name: 'ozaki', + page: null, + }, + ]); + }); + + // Global author without baseUrl with a subfolder in img + it('getBlogPostAuthors do not modify globalAuthor imageUrl with subfolder without baseUrl', async () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: ['ozaki'], + }, + authorsMap: { + ozaki: { + name: 'ozaki', + key: 'ozaki', + imageURL: 'img/ozaki.png', + page: null, + }, + }, + baseUrl: '/', + }), + ).toEqual([ + { + imageURL: 'img/ozaki.png', + key: 'ozaki', + name: 'ozaki', + page: null, + }, + ]); + }); + + // Global author with baseUrl with a subfolder in img + it('getBlogPostAuthors do not modify globalAuthor imageUrl with subfolder with baseUrl', async () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: ['ozaki'], + }, + authorsMap: { + ozaki: { + name: 'ozaki', + key: 'ozaki', + imageURL: 'img/ozaki.png', + page: null, + }, + }, + baseUrl: '/img/', + }), + ).toEqual([ + { + imageURL: 'img/ozaki.png', + key: 'ozaki', + name: 'ozaki', + page: null, + }, + ]); + }); + + // Inline author without baseUrl with a subfolder in img + it('getBlogPostAuthors normalize imageURL from subfolder without baseUrl for inline authors', async () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: [{name: 'ozaki', imageURL: 'img/ozaki.png'}], + }, + authorsMap: undefined, + baseUrl: '/', + }), + ).toEqual([ + { + imageURL: 'img/ozaki.png', + key: null, + name: 'ozaki', + page: null, + }, + ]); + }); + + // Inline author with baseUrl with a subfolder in img + it('getBlogPostAuthors normalize imageURL from subfolder with baseUrl for inline authors', async () => { + expect( + getBlogPostAuthors({ + frontMatter: { + authors: [{name: 'ozaki', imageURL: '/img/ozaki.png'}], + }, + authorsMap: undefined, + baseUrl: '/img/', + }), + ).toEqual([ + { + imageURL: '/img/img/ozaki.png', + key: null, + name: 'ozaki', + page: null, + }, + ]); + }); +}); diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts index 4330dc5afcd1..8ce98865ca35 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts @@ -106,17 +106,6 @@ describe('getAuthorsMap', () => { }), ).resolves.toBeUndefined(); }); - - it('getAuthorsMap can return img with relative path if baseUrl is set', async () => { - const authorsMap = await getAuthorsMap({ - contentPaths, - authorsMapPath: 'authors.yml', - authorsBaseRoutePath: '/authors', - baseUrl: '/baseUrl', - }); - expect(authorsMap).toBeDefined(); - expect(authorsMap?.ozaki?.imageURL).toBe('/baseUrl/img/ozaki.jpg'); - }); }); describe('validateAuthorsMapInput', () => { @@ -319,3 +308,61 @@ describe('authors socials', () => { expect(validateAuthorsMap(authorsMap)).toEqual(authorsMap); }); }); + +describe('getAuthorsMap global author baseUrl', () => { + const fixturesDir = path.join(__dirname, '__fixtures__/authorsMapFiles'); + const contentPaths = { + contentPathLocalized: fixturesDir, + contentPath: fixturesDir, + }; + + it('getAuthorsMap return imageURL with relative path', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/', + }); + expect(authorsMap?.ozaki?.imageURL).toBe('/ozaki.png'); + }); + + it('getAuthorsMap normalize imageURL with baseUrl', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/baseUrl/', + }); + expect(authorsMap?.ozaki?.imageURL).toBe('/baseUrl/ozaki.png'); + }); + + it('getAuthorsMap return imageURL with relative subdir path', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/', + }); + expect(authorsMap?.ozakione?.imageURL).toBe('/img/ozaki.png'); + }); + + it('getAuthorsMap normalize imageURL with baseUrl and subdir same value', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/img/', + }); + expect(authorsMap?.ozakione?.imageURL).toBe('/img/img/ozaki.png'); + }); + + it('getAuthorsMap normalize imageURL subdir with baseUrl', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/blog/', + }); + expect(authorsMap?.ozakione?.imageURL).toBe('/blog/img/ozaki.png'); + }); +}); diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts index 242e6f52b8c6..89b0938d61ee 100644 --- a/packages/docusaurus-plugin-content-blog/src/authors.ts +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -21,14 +21,14 @@ type AuthorsParam = { baseUrl: string; }; -function normalizeImageUrl({ +export function normalizeImageUrl({ imageURL, baseUrl, }: { imageURL: string | undefined; baseUrl: string; -}) { - return imageURL?.startsWith('/') && !imageURL.startsWith(baseUrl) +}): string | undefined { + return imageURL?.startsWith('/') ? normalizeUrl([baseUrl, imageURL]) : imageURL; } @@ -122,7 +122,9 @@ ${Object.keys(authorsMap) ...author, key: author.key ?? null, page: author.page ?? null, - imageURL: normalizeImageUrl({imageURL: author.imageURL, baseUrl}), + imageURL: author.key + ? author.imageURL + : normalizeImageUrl({imageURL: author.imageURL, baseUrl}), }; } } diff --git a/packages/docusaurus-plugin-content-blog/src/authorsMap.ts b/packages/docusaurus-plugin-content-blog/src/authorsMap.ts index 184d53720665..d195573ff42b 100644 --- a/packages/docusaurus-plugin-content-blog/src/authorsMap.ts +++ b/packages/docusaurus-plugin-content-blog/src/authorsMap.ts @@ -9,6 +9,7 @@ import _ from 'lodash'; import {readDataFile, normalizeUrl} from '@docusaurus/utils'; import {Joi, URISchema} from '@docusaurus/utils-validation'; import {AuthorSocialsSchema, normalizeSocials} from './authorsSocials'; +import {normalizeImageUrl} from './authors'; import type {BlogContentPaths} from './types'; import type { Author, @@ -116,9 +117,7 @@ function normalizeAuthor({ ...author, key: authorKey, page: getAuthorPage(), - imageURL: author.imageURL?.startsWith('/') - ? normalizeUrl([baseUrl, author.imageURL]) - : author.imageURL, + imageURL: normalizeImageUrl({imageURL: author.imageURL, baseUrl}), socials: author.socials ? normalizeSocials(author.socials) : undefined, }; } From f18f1247b8784d70d1424f0172013f45fcf69eee Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:00:42 +0200 Subject: [PATCH 4/7] move tests --- .../src/__tests__/authors.test.ts | 162 +++++++++--------- .../src/__tests__/authorsMap.test.ts | 108 ++++++------ .../src/authors.ts | 1 + .../src/authorsMap.ts | 4 +- 4 files changed, 133 insertions(+), 142 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts index 40b82502ca23..37ecd7106490 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts @@ -216,7 +216,7 @@ describe('getBlogPostAuthors', () => { authorsMap: { slorber: { name: 'Sébastien Lorber', - imageURL: '/img/slorber.png', + imageURL: '/baseUrl/img/slorber.png', key: 'slorber', page: null, }, @@ -227,7 +227,7 @@ describe('getBlogPostAuthors', () => { { key: 'slorber', name: 'Sébastien Lorber', - imageURL: '/img/slorber.png', + imageURL: '/baseUrl/img/slorber.png', page: null, }, ]); @@ -486,44 +486,7 @@ describe('getBlogPostAuthors', () => { Don't mix 'authors' with other existing 'author_*' front matter. Choose one or the other, not both at the same time." `); }); -}); - -describe('groupBlogPostsByAuthorKey', () => { - const authorsMap: AuthorsMap = fromPartial({ - ozaki: {}, - slorber: {}, - keyWithNoPost: {}, - }); - - it('can group blog posts', () => { - const post1 = post({metadata: {authors: [{key: 'ozaki'}]}}); - const post2 = post({ - metadata: {authors: [{key: 'slorber'}, {key: 'ozaki'}]}, - }); - const post3 = post({metadata: {authors: [{key: 'slorber'}]}}); - const post4 = post({ - metadata: {authors: [{name: 'Inline author 1'}, {key: 'slorber'}]}, - }); - const post5 = post({ - metadata: {authors: [{name: 'Inline author 2'}]}, - }); - const post6 = post({ - metadata: {authors: [{key: 'unknownKey'}]}, - }); - - const blogPosts = [post1, post2, post3, post4, post5, post6]; - expect(groupBlogPostsByAuthorKey({authorsMap, blogPosts})).toEqual({ - ozaki: [post1, post2], - slorber: [post2, post3, post4], - keyWithNoPost: [], - // We don't care about this edge case, it doesn't happen in practice - unknownKey: undefined, - }); - }); -}); - -describe('getBlogPostAuthors baseUrl', () => { // Global author without baseUrl it('getBlogPostAuthors do not modify global authors imageUrl without baseUrl', async () => { expect( @@ -535,7 +498,7 @@ describe('getBlogPostAuthors baseUrl', () => { ozaki: { name: 'ozaki', key: 'ozaki', - imageURL: 'ozaki.png', + imageURL: '/ozaki.png', page: null, }, }, @@ -543,7 +506,7 @@ describe('getBlogPostAuthors baseUrl', () => { }), ).toEqual([ { - imageURL: 'ozaki.png', + imageURL: '/ozaki.png', key: 'ozaki', name: 'ozaki', page: null, @@ -562,7 +525,7 @@ describe('getBlogPostAuthors baseUrl', () => { ozaki: { name: 'ozaki', key: 'ozaki', - imageURL: 'ozaki.png', + imageURL: '/img/ozaki.png', page: null, }, }, @@ -570,7 +533,7 @@ describe('getBlogPostAuthors baseUrl', () => { }), ).toEqual([ { - imageURL: 'ozaki.png', + imageURL: '/img/ozaki.png', key: 'ozaki', name: 'ozaki', page: null, @@ -578,94 +541,94 @@ describe('getBlogPostAuthors baseUrl', () => { ]); }); - // Inline author without baseUrl - it('getBlogPostAuthors can return imageURL without baseUrl for inline authors', async () => { + // Global author without baseUrl with a subfolder in img + it('getBlogPostAuthors do not modify globalAuthor imageUrl with subfolder without baseUrl', async () => { expect( getBlogPostAuthors({ frontMatter: { - authors: [{name: 'ozaki', imageURL: 'ozaki.png'}], + authors: ['ozaki'], + }, + authorsMap: { + ozaki: { + name: 'ozaki', + key: 'ozaki', + imageURL: '/img/ozaki.png', + page: null, + }, }, - authorsMap: undefined, baseUrl: '/', }), ).toEqual([ { - imageURL: 'ozaki.png', - key: null, + imageURL: '/img/ozaki.png', + key: 'ozaki', name: 'ozaki', page: null, }, ]); }); - // Inline author with baseUrl - it('getBlogPostAuthors normalize imageURL with baseUrl for inline authors', async () => { + // Global author with baseUrl with a subfolder in img + it('getBlogPostAuthors do not modify globalAuthor imageUrl with subfolder with baseUrl', async () => { expect( getBlogPostAuthors({ frontMatter: { - authors: [{name: 'ozaki', imageURL: '/ozaki.png'}], + authors: ['ozaki'], + }, + authorsMap: { + ozaki: { + name: 'ozaki', + key: 'ozaki', + imageURL: '/img/ozaki.png', + page: null, + }, }, - authorsMap: undefined, baseUrl: '/img/', }), ).toEqual([ { imageURL: '/img/ozaki.png', - key: null, + key: 'ozaki', name: 'ozaki', page: null, }, ]); }); - // Global author without baseUrl with a subfolder in img - it('getBlogPostAuthors do not modify globalAuthor imageUrl with subfolder without baseUrl', async () => { + // Inline author without baseUrl + it('getBlogPostAuthors can return imageURL without baseUrl for inline authors', async () => { expect( getBlogPostAuthors({ frontMatter: { - authors: ['ozaki'], - }, - authorsMap: { - ozaki: { - name: 'ozaki', - key: 'ozaki', - imageURL: 'img/ozaki.png', - page: null, - }, + authors: [{name: 'ozaki', imageURL: '/ozaki.png'}], }, + authorsMap: undefined, baseUrl: '/', }), ).toEqual([ { - imageURL: 'img/ozaki.png', - key: 'ozaki', + imageURL: '/ozaki.png', + key: null, name: 'ozaki', page: null, }, ]); }); - // Global author with baseUrl with a subfolder in img - it('getBlogPostAuthors do not modify globalAuthor imageUrl with subfolder with baseUrl', async () => { + // Inline author with baseUrl + it('getBlogPostAuthors normalize imageURL with baseUrl for inline authors', async () => { expect( getBlogPostAuthors({ frontMatter: { - authors: ['ozaki'], - }, - authorsMap: { - ozaki: { - name: 'ozaki', - key: 'ozaki', - imageURL: 'img/ozaki.png', - page: null, - }, + authors: [{name: 'ozaki', imageURL: '/ozaki.png'}], }, + authorsMap: undefined, baseUrl: '/img/', }), ).toEqual([ { - imageURL: 'img/ozaki.png', - key: 'ozaki', + imageURL: '/img/ozaki.png', + key: null, name: 'ozaki', page: null, }, @@ -677,14 +640,14 @@ describe('getBlogPostAuthors baseUrl', () => { expect( getBlogPostAuthors({ frontMatter: { - authors: [{name: 'ozaki', imageURL: 'img/ozaki.png'}], + authors: [{name: 'ozaki', imageURL: '/img/ozaki.png'}], }, authorsMap: undefined, baseUrl: '/', }), ).toEqual([ { - imageURL: 'img/ozaki.png', + imageURL: '/img/ozaki.png', key: null, name: 'ozaki', page: null, @@ -712,3 +675,38 @@ describe('getBlogPostAuthors baseUrl', () => { ]); }); }); + +describe('groupBlogPostsByAuthorKey', () => { + const authorsMap: AuthorsMap = fromPartial({ + ozaki: {}, + slorber: {}, + keyWithNoPost: {}, + }); + + it('can group blog posts', () => { + const post1 = post({metadata: {authors: [{key: 'ozaki'}]}}); + const post2 = post({ + metadata: {authors: [{key: 'slorber'}, {key: 'ozaki'}]}, + }); + const post3 = post({metadata: {authors: [{key: 'slorber'}]}}); + const post4 = post({ + metadata: {authors: [{name: 'Inline author 1'}, {key: 'slorber'}]}, + }); + const post5 = post({ + metadata: {authors: [{name: 'Inline author 2'}]}, + }); + const post6 = post({ + metadata: {authors: [{key: 'unknownKey'}]}, + }); + + const blogPosts = [post1, post2, post3, post4, post5, post6]; + + expect(groupBlogPostsByAuthorKey({authorsMap, blogPosts})).toEqual({ + ozaki: [post1, post2], + slorber: [post2, post3, post4], + keyWithNoPost: [], + // We don't care about this edge case, it doesn't happen in practice + unknownKey: undefined, + }); + }); +}); diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts index 8ce98865ca35..f9442ee82688 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authorsMap.test.ts @@ -106,6 +106,56 @@ describe('getAuthorsMap', () => { }), ).resolves.toBeUndefined(); }); + + it('getAuthorsMap return imageURL with relative path', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/', + }); + expect(authorsMap?.ozaki?.imageURL).toBe('/ozaki.png'); + }); + + it('getAuthorsMap normalize imageURL with baseUrl', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/baseUrl/', + }); + expect(authorsMap?.ozaki?.imageURL).toBe('/baseUrl/ozaki.png'); + }); + + it('getAuthorsMap return imageURL with relative subdir path', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/', + }); + expect(authorsMap?.ozakione?.imageURL).toBe('/img/ozaki.png'); + }); + + it('getAuthorsMap normalize imageURL with baseUrl and subdir same value', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/img/', + }); + expect(authorsMap?.ozakione?.imageURL).toBe('/img/img/ozaki.png'); + }); + + it('getAuthorsMap normalize imageURL subdir with baseUrl', async () => { + const authorsMap = await getAuthorsMap({ + contentPaths, + authorsMapPath: 'authors.yml', + authorsBaseRoutePath: '/authors', + baseUrl: '/blog/', + }); + expect(authorsMap?.ozakione?.imageURL).toBe('/blog/img/ozaki.png'); + }); }); describe('validateAuthorsMapInput', () => { @@ -308,61 +358,3 @@ describe('authors socials', () => { expect(validateAuthorsMap(authorsMap)).toEqual(authorsMap); }); }); - -describe('getAuthorsMap global author baseUrl', () => { - const fixturesDir = path.join(__dirname, '__fixtures__/authorsMapFiles'); - const contentPaths = { - contentPathLocalized: fixturesDir, - contentPath: fixturesDir, - }; - - it('getAuthorsMap return imageURL with relative path', async () => { - const authorsMap = await getAuthorsMap({ - contentPaths, - authorsMapPath: 'authors.yml', - authorsBaseRoutePath: '/authors', - baseUrl: '/', - }); - expect(authorsMap?.ozaki?.imageURL).toBe('/ozaki.png'); - }); - - it('getAuthorsMap normalize imageURL with baseUrl', async () => { - const authorsMap = await getAuthorsMap({ - contentPaths, - authorsMapPath: 'authors.yml', - authorsBaseRoutePath: '/authors', - baseUrl: '/baseUrl/', - }); - expect(authorsMap?.ozaki?.imageURL).toBe('/baseUrl/ozaki.png'); - }); - - it('getAuthorsMap return imageURL with relative subdir path', async () => { - const authorsMap = await getAuthorsMap({ - contentPaths, - authorsMapPath: 'authors.yml', - authorsBaseRoutePath: '/authors', - baseUrl: '/', - }); - expect(authorsMap?.ozakione?.imageURL).toBe('/img/ozaki.png'); - }); - - it('getAuthorsMap normalize imageURL with baseUrl and subdir same value', async () => { - const authorsMap = await getAuthorsMap({ - contentPaths, - authorsMapPath: 'authors.yml', - authorsBaseRoutePath: '/authors', - baseUrl: '/img/', - }); - expect(authorsMap?.ozakione?.imageURL).toBe('/img/img/ozaki.png'); - }); - - it('getAuthorsMap normalize imageURL subdir with baseUrl', async () => { - const authorsMap = await getAuthorsMap({ - contentPaths, - authorsMapPath: 'authors.yml', - authorsBaseRoutePath: '/authors', - baseUrl: '/blog/', - }); - expect(authorsMap?.ozakione?.imageURL).toBe('/blog/img/ozaki.png'); - }); -}); diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts index 89b0938d61ee..237d23a29968 100644 --- a/packages/docusaurus-plugin-content-blog/src/authors.ts +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -122,6 +122,7 @@ ${Object.keys(authorsMap) ...author, key: author.key ?? null, page: author.page ?? null, + // global author images have already been normalized imageURL: author.key ? author.imageURL : normalizeImageUrl({imageURL: author.imageURL, baseUrl}), diff --git a/packages/docusaurus-plugin-content-blog/src/authorsMap.ts b/packages/docusaurus-plugin-content-blog/src/authorsMap.ts index d195573ff42b..e5c358b422f5 100644 --- a/packages/docusaurus-plugin-content-blog/src/authorsMap.ts +++ b/packages/docusaurus-plugin-content-blog/src/authorsMap.ts @@ -12,10 +12,10 @@ import {AuthorSocialsSchema, normalizeSocials} from './authorsSocials'; import {normalizeImageUrl} from './authors'; import type {BlogContentPaths} from './types'; import type { - Author, AuthorAttributes, AuthorPage, AuthorsMap, + AuthorWithKey, } from '@docusaurus/plugin-content-blog'; type AuthorInput = AuthorAttributes & { @@ -101,7 +101,7 @@ function normalizeAuthor({ authorKey: string; baseUrl: string; author: AuthorInput; -}): Author & {key: string} { +}): AuthorWithKey { function getAuthorPage(): AuthorPage | null { if (!author.page) { return null; From 3a69dd05f8516093c0cecdaf0b3bdbc6e744c388 Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:06:25 +0200 Subject: [PATCH 5/7] add docusaurus bug detection --- .../src/__tests__/authors.test.ts | 29 +++++++++++++------ .../src/__tests__/feed.test.ts | 1 + .../src/authors.ts | 29 ++++++++++++++++--- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts index 37ecd7106490..973531f27fe5 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts @@ -419,7 +419,6 @@ describe('getBlogPostAuthors', () => { frontMatter: { authors: ['yangshun', 'jmarcey', 'slorber'], }, - authorsMap: { yangshun: {name: 'Yangshun Tay', key: 'yangshun', page: null}, jmarcey: {name: 'Joel Marcey', key: 'jmarcey', page: null}, @@ -496,7 +495,6 @@ describe('getBlogPostAuthors', () => { }, authorsMap: { ozaki: { - name: 'ozaki', key: 'ozaki', imageURL: '/ozaki.png', page: null, @@ -508,7 +506,6 @@ describe('getBlogPostAuthors', () => { { imageURL: '/ozaki.png', key: 'ozaki', - name: 'ozaki', page: null, }, ]); @@ -523,7 +520,6 @@ describe('getBlogPostAuthors', () => { }, authorsMap: { ozaki: { - name: 'ozaki', key: 'ozaki', imageURL: '/img/ozaki.png', page: null, @@ -535,7 +531,6 @@ describe('getBlogPostAuthors', () => { { imageURL: '/img/ozaki.png', key: 'ozaki', - name: 'ozaki', page: null, }, ]); @@ -550,7 +545,6 @@ describe('getBlogPostAuthors', () => { }, authorsMap: { ozaki: { - name: 'ozaki', key: 'ozaki', imageURL: '/img/ozaki.png', page: null, @@ -562,7 +556,6 @@ describe('getBlogPostAuthors', () => { { imageURL: '/img/ozaki.png', key: 'ozaki', - name: 'ozaki', page: null, }, ]); @@ -577,7 +570,6 @@ describe('getBlogPostAuthors', () => { }, authorsMap: { ozaki: { - name: 'ozaki', key: 'ozaki', imageURL: '/img/ozaki.png', page: null, @@ -589,12 +581,31 @@ describe('getBlogPostAuthors', () => { { imageURL: '/img/ozaki.png', key: 'ozaki', - name: 'ozaki', page: null, }, ]); }); + it('getBlogPostAuthors throws if global author does not have baseUrl', async () => { + expect(() => + getBlogPostAuthors({ + frontMatter: { + authors: ['ozaki'], + }, + authorsMap: { + ozaki: { + key: 'ozaki', + imageURL: '/ozaki.png', + page: null, + }, + }, + baseUrl: '/baseUrl/', + }), + ).toThrowErrorMatchingInlineSnapshot( + `"Docusaurus bug: global authors image /ozaki.png should start with the expected baseUrl=/baseUrl/"`, + ); + }); + // Inline author without baseUrl it('getBlogPostAuthors can return imageURL without baseUrl for inline authors', async () => { expect( diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts index 3cca6f94aaf9..96d0d857d706 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts @@ -67,6 +67,7 @@ async function testGenerateFeeds( contentPaths, authorsMapPath: options.authorsMapPath, authorsBaseRoutePath: '/authors', + baseUrl: '/', }); const blogPosts = await generateBlogPosts( diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts index 237d23a29968..2a11591255c3 100644 --- a/packages/docusaurus-plugin-content-blog/src/authors.ts +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -33,6 +33,29 @@ export function normalizeImageUrl({ : imageURL; } +function normalizeAuthorUrl({ + author, + baseUrl, +}: { + author: Author; + baseUrl: string; +}): string | undefined { + if (author.key) { + if ( + author.imageURL && + !author.imageURL.match(/^https?:\/\//) && + !author.imageURL.startsWith(baseUrl) + ) { + throw new Error( + `Docusaurus bug: global authors image ${author.imageURL} should start with the expected baseUrl=${baseUrl}`, + ); + } + + return author.imageURL; + } + return normalizeImageUrl({imageURL: author.imageURL, baseUrl}); +} + // Legacy v1/early-v2 front matter fields // We may want to deprecate those in favor of using only frontMatter.authors // TODO Docusaurus v4: remove this legacy front matter @@ -116,16 +139,14 @@ ${Object.keys(authorsMap) // Author def from authorsMap can be locally overridden by front matter ...getAuthorsMapAuthor(frontMatterAuthor.key), ...frontMatterAuthor, - }; + } as Author; return { ...author, key: author.key ?? null, page: author.page ?? null, // global author images have already been normalized - imageURL: author.key - ? author.imageURL - : normalizeImageUrl({imageURL: author.imageURL, baseUrl}), + imageURL: normalizeAuthorUrl({author, baseUrl}), }; } } From bbc86e8ae209d81248bc30e3d2d026558729f693 Mon Sep 17 00:00:00 2001 From: ozakione <29860391+OzakIOne@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:43:16 +0200 Subject: [PATCH 6/7] fix bug & add tests --- .../src/__tests__/authors.test.ts | 47 +++++++++++++++---- .../src/authors.ts | 3 +- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts index 973531f27fe5..9e1ae83b032c 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts @@ -586,7 +586,7 @@ describe('getBlogPostAuthors', () => { ]); }); - it('getBlogPostAuthors throws if global author does not have baseUrl', async () => { + it('getBlogPostAuthors throws if global author imageURL does not have baseUrl', async () => { expect(() => getBlogPostAuthors({ frontMatter: { @@ -606,12 +606,45 @@ describe('getBlogPostAuthors', () => { ); }); + it('getBlogPostAuthors do not throws if inline author imageURL is a link to a file', async () => { + const baseUrlTest = getBlogPostAuthors({ + frontMatter: { + authors: [{imageURL: './ozaki.png'}], + }, + authorsMap: undefined, + baseUrl: '/baseUrl/', + }); + const withoutBaseUrlTest = getBlogPostAuthors({ + frontMatter: { + authors: [{imageURL: './ozaki.png'}], + }, + authorsMap: undefined, + baseUrl: '/', + }); + expect(() => baseUrlTest).not.toThrow(); + expect(baseUrlTest).toEqual([ + { + imageURL: './ozaki.png', + key: null, + page: null, + }, + ]); + expect(() => withoutBaseUrlTest).not.toThrow(); + expect(withoutBaseUrlTest).toEqual([ + { + imageURL: './ozaki.png', + key: null, + page: null, + }, + ]); + }); + // Inline author without baseUrl it('getBlogPostAuthors can return imageURL without baseUrl for inline authors', async () => { expect( getBlogPostAuthors({ frontMatter: { - authors: [{name: 'ozaki', imageURL: '/ozaki.png'}], + authors: [{imageURL: '/ozaki.png'}], }, authorsMap: undefined, baseUrl: '/', @@ -620,7 +653,6 @@ describe('getBlogPostAuthors', () => { { imageURL: '/ozaki.png', key: null, - name: 'ozaki', page: null, }, ]); @@ -631,7 +663,7 @@ describe('getBlogPostAuthors', () => { expect( getBlogPostAuthors({ frontMatter: { - authors: [{name: 'ozaki', imageURL: '/ozaki.png'}], + authors: [{imageURL: '/ozaki.png'}], }, authorsMap: undefined, baseUrl: '/img/', @@ -640,7 +672,6 @@ describe('getBlogPostAuthors', () => { { imageURL: '/img/ozaki.png', key: null, - name: 'ozaki', page: null, }, ]); @@ -651,7 +682,7 @@ describe('getBlogPostAuthors', () => { expect( getBlogPostAuthors({ frontMatter: { - authors: [{name: 'ozaki', imageURL: '/img/ozaki.png'}], + authors: [{imageURL: '/img/ozaki.png'}], }, authorsMap: undefined, baseUrl: '/', @@ -660,7 +691,6 @@ describe('getBlogPostAuthors', () => { { imageURL: '/img/ozaki.png', key: null, - name: 'ozaki', page: null, }, ]); @@ -671,7 +701,7 @@ describe('getBlogPostAuthors', () => { expect( getBlogPostAuthors({ frontMatter: { - authors: [{name: 'ozaki', imageURL: '/img/ozaki.png'}], + authors: [{imageURL: '/img/ozaki.png'}], }, authorsMap: undefined, baseUrl: '/img/', @@ -680,7 +710,6 @@ describe('getBlogPostAuthors', () => { { imageURL: '/img/img/ozaki.png', key: null, - name: 'ozaki', page: null, }, ]); diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts index 2a11591255c3..eeda8019a37d 100644 --- a/packages/docusaurus-plugin-content-blog/src/authors.ts +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -44,7 +44,8 @@ function normalizeAuthorUrl({ if ( author.imageURL && !author.imageURL.match(/^https?:\/\//) && - !author.imageURL.startsWith(baseUrl) + !author.imageURL.startsWith(baseUrl) && + !author.imageURL.startsWith('./') ) { throw new Error( `Docusaurus bug: global authors image ${author.imageURL} should start with the expected baseUrl=${baseUrl}`, From 835afd481e2171694033c7406505ec194e73ad13 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 29 Aug 2024 14:14:48 +0200 Subject: [PATCH 7/7] Simplifies internal invariant check --- .../src/__tests__/authors.test.ts | 2 +- packages/docusaurus-plugin-content-blog/src/authors.ts | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts index 9e1ae83b032c..c1bf962c90ac 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/authors.test.ts @@ -602,7 +602,7 @@ describe('getBlogPostAuthors', () => { baseUrl: '/baseUrl/', }), ).toThrowErrorMatchingInlineSnapshot( - `"Docusaurus bug: global authors image /ozaki.png should start with the expected baseUrl=/baseUrl/"`, + `"Docusaurus internal bug: global authors image /ozaki.png should start with the expected baseUrl=/baseUrl/"`, ); }); diff --git a/packages/docusaurus-plugin-content-blog/src/authors.ts b/packages/docusaurus-plugin-content-blog/src/authors.ts index eeda8019a37d..bc6b152157b2 100644 --- a/packages/docusaurus-plugin-content-blog/src/authors.ts +++ b/packages/docusaurus-plugin-content-blog/src/authors.ts @@ -41,14 +41,13 @@ function normalizeAuthorUrl({ baseUrl: string; }): string | undefined { if (author.key) { + // Ensures invariant: global authors should have already been normalized if ( - author.imageURL && - !author.imageURL.match(/^https?:\/\//) && - !author.imageURL.startsWith(baseUrl) && - !author.imageURL.startsWith('./') + author.imageURL?.startsWith('/') && + !author.imageURL.startsWith(baseUrl) ) { throw new Error( - `Docusaurus bug: global authors image ${author.imageURL} should start with the expected baseUrl=${baseUrl}`, + `Docusaurus internal bug: global authors image ${author.imageURL} should start with the expected baseUrl=${baseUrl}`, ); }