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

pref: reduce the count of regular matches #295

Merged
merged 2 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 44 additions & 44 deletions packages/vitepress-plugin-git-changelog/src/vite/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {
defaultReleaseTagURLHandler,
defaultReleaseTagsURLHandler,
findMapAuthorByEmail,
findMapAuthorByGitHub,
findMapAuthorByName,
findMapAuthorLink,
getAvatarFromGithubNoreplyAddress,
getCoAuthors,
getProfileUrlFromGithubNoreplyAddress,
getGitHubUserNameFromNoreplyAddress,
mergeRawCommits,
newAvatarForAuthor,
parseCommitAuthors,
Expand Down Expand Up @@ -333,7 +333,8 @@ describe('parseCommitAuthors', () => {
{
name: 'First Last',
email: 'user@users.noreply.github.com',
avatarUrl: 'https://avatars.githubusercontent.com/user?size=80',
i18n: undefined,
avatarUrl: 'https://github.com/user.png',
url: 'https://github.com/user',
},
])
Expand Down Expand Up @@ -385,6 +386,37 @@ describe('findMapAuthorByEmail', () => {
})
})

describe('findMapAuthorByGitHub', () => {
it('should return the commit author for GitHub noreply email with username in mapAuthors', async () => {
const creators: Contributor[] = [
{
name: 'John',
username: 'user',
},
]
const creator = await findMapAuthorByGitHub(creators, 'John', '123456+user@users.noreply.github.com')

expect(creator).toEqual(creators[0])
})

it('should return the commit author for GitHub noreply email without username in mapAuthors', async () => {
const creators: Contributor[] = [
{
name: 'user',
},
]
const creator = await findMapAuthorByGitHub(creators, 'user', '123456+user@users.noreply.github.com')

expect(creator).toEqual({ name: 'user', username: 'user' })
})

it('should return the commit author avatar for GitHub noreply email without mapAuthor', async () => {
const avatar = await findMapAuthorByGitHub(undefined, 'John', '123456+user@users.noreply.github.com')

expect(avatar).toEqual({ name: 'John', username: 'user' })
})
})

describe('findMapAuthorByName', () => {
it('should return the registered creator by name', () => {
const creators: Contributor[] = [
Expand Down Expand Up @@ -559,57 +591,25 @@ describe('newAvatarForAuthor', () => {

expect(avatar).toEqual('https://gravatar.com/avatar/b4c9a289323b21a01c3e940f150eb9b8c542587f1abfd8f0e1cc1ffc5e475514?d=retro')
})

it('should return the commit author avatar for GitHub noreply email without user ID', async () => {
const avatar = await newAvatarForAuthor(undefined, 'user@users.noreply.github.com')

expect(avatar).toEqual('https://avatars.githubusercontent.com/user?size=80')
})

it('should return the commit author avatar for GitHub noreply email with user ID', async () => {
const avatar = await newAvatarForAuthor(undefined, '123456+user@users.noreply.github.com')

expect(avatar).toEqual('https://avatars.githubusercontent.com/u/123456?size=80')
})
})

describe('getAvatarFromGithubNoreplyAddress', () => {
it('should return undefined for email it cannot handle', async () => {
const avatar = await getAvatarFromGithubNoreplyAddress('user@example.com')

expect(avatar).toEqual(undefined)
})

it('should return the commit author avatar for GitHub noreply email without user ID', async () => {
const avatar = await getAvatarFromGithubNoreplyAddress('user@users.noreply.github.com')

expect(avatar).toEqual('https://avatars.githubusercontent.com/user?size=80')
})

it('should return the commit author avatar for GitHub noreply email with user ID', async () => {
const avatar = await getAvatarFromGithubNoreplyAddress('123456+user@users.noreply.github.com')

expect(avatar).toEqual('https://avatars.githubusercontent.com/u/123456?size=80')
})
})

describe('getProfileUrlFromGithubNoreplyAddress', () => {
describe('getGitHubFromGithubNoreplyAddress', () => {
it('should return undefined for email it cannot handle', async () => {
const avatar = await getProfileUrlFromGithubNoreplyAddress('user@example.com')
const result = await getGitHubUserNameFromNoreplyAddress('user@example.com')

expect(avatar).toEqual(undefined)
expect(result).toEqual(undefined)
})

it('should return the GitHub profile URL for GitHub noreply email without user ID', async () => {
const avatar = await getProfileUrlFromGithubNoreplyAddress('user@users.noreply.github.com')
it('should return the commit author for GitHub noreply email without user ID', async () => {
const result = await getGitHubUserNameFromNoreplyAddress('user@users.noreply.github.com')

expect(avatar).toEqual('https://github.com/user')
expect(result).toEqual({ userId: undefined, userName: 'user' })
})

it('should return the GitHub profile URL for GitHub noreply email with user ID', async () => {
const avatar = await getProfileUrlFromGithubNoreplyAddress('123456+user@users.noreply.github.com')
it('should return the commit author for GitHub noreply email with user ID', async () => {
const result = await getGitHubUserNameFromNoreplyAddress('123456+user@users.noreply.github.com')

expect(avatar).toEqual('https://github.com/user')
expect(result).toEqual({ userId: '123456', userName: 'user' })
})
})

Expand Down
53 changes: 26 additions & 27 deletions packages/vitepress-plugin-git-changelog/src/vite/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,15 @@ export async function parseCommitAuthors(commit: MergedRawCommit, mapContributor
author.avatarUrl = await newAvatarForAuthor(targetCreatorByEmail, author.email!)
return author
}
const targetCreatorByGitHub = findMapAuthorByGitHub(mapContributors, author.name, author.email!)
if (targetCreatorByGitHub) {
author.name = targetCreatorByGitHub.name ?? author.name
author.i18n = findMapAuthorI18n(targetCreatorByGitHub)
author.url = findMapAuthorLink(targetCreatorByGitHub)
author.avatarUrl = await newAvatarForAuthor(targetCreatorByGitHub, author.email!)
return author
}
author.avatarUrl = await newAvatarForAuthor(undefined, author.email!)
author.url ||= getProfileUrlFromGithubNoreplyAddress(author.email)
return author
}))
}
Expand Down Expand Up @@ -410,7 +417,7 @@ export function getCoAuthors(body?: string): CommitAuthor[] {

export function findMapAuthorByName(mapContributors: Contributor[] | undefined, author_name: string) {
return mapContributors?.find((item) => {
const res = (item.mapByNameAliases && Array.isArray(item.mapByNameAliases) && item.mapByNameAliases.includes(author_name)) || item.name === author_name
const res = (item.mapByNameAliases && Array.isArray(item.mapByNameAliases) && item.mapByNameAliases.includes(author_name)) || item.name === author_name || item.username === author_name
if (res)
return true

Expand All @@ -430,6 +437,21 @@ export function findMapAuthorByEmail(mapContributors: Contributor[] | undefined,
})
}

export function findMapAuthorByGitHub(mapContributors: Contributor[] | undefined, author_name: string, author_email: string) {
const github = getGitHubUserNameFromNoreplyAddress(author_email)
if (github && github.userName) {
const mappedByName = findMapAuthorByName(mapContributors, github.userName)
if (mappedByName && mappedByName.username) {
mappedByName.username ||= github.userName
return mappedByName
}
return {
name: author_name,
username: github.userName,
}
}
}

export function findMapAuthorLink(creator: Contributor): string | undefined {
if (!creator.links && !!creator.username)
return `https://github.com/${creator.username}`
Expand Down Expand Up @@ -457,32 +479,13 @@ export function findMapAuthorI18n(mappedAuthor: Contributor): Record<string, str
}

// based on https://github.com/nolebase/integrations/issues/277#issuecomment-2254111802
export function getAvatarFromGithubNoreplyAddress(email: string | undefined, size: number = 80): string | undefined {
if (!email)
return undefined

export function getGitHubUserNameFromNoreplyAddress(email: string) {
const match = email.match(/^(?:(?<userId>\d+)\+)?(?<userName>[a-zA-Z\d-]{1,39})@users.noreply.github.com$/)
if (!match || !match.groups)
return undefined

const { userName, userId } = match.groups
return `https://avatars.githubusercontent.com/${userId ? `u/${userId}` : userName}?size=${size}`
}

export function getProfileUrlFromGithubNoreplyAddress(email: string | undefined): string | undefined {
if (!email)
return undefined

const match = email.match(/^(?:(?<userId>\d+)\+)?(?<userName>[a-zA-Z\d-]{1,39})@users.noreply.github.com$/)
if (!match || !match.groups)
return undefined

const { userName } = match.groups

if (!userName)
return undefined

return `https://github.com/${userName}`
return { userId, userName }
}

export async function newAvatarForAuthor(mappedAuthor: Contributor | undefined, email: string): Promise<string> {
Expand All @@ -493,9 +496,5 @@ export async function newAvatarForAuthor(mappedAuthor: Contributor | undefined,
return `https://github.com/${mappedAuthor.username}.png`
}

const githubProfilePicture = getAvatarFromGithubNoreplyAddress(email)
if (githubProfilePicture != null)
return githubProfilePicture

return `https://gravatar.com/avatar/${await digestStringAsSHA256(email)}?d=retro`
}
Loading