From a0241c4292fc7580c2a5a755d44d7f5df0050e54 Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Wed, 27 Nov 2024 16:32:36 +0800 Subject: [PATCH] feat(plugin-git): improve commits parsing and optimize plugins (#292) --- docs/plugins/development/git.md | 13 ++++++++++++- docs/zh/plugins/development/git.md | 12 +++++++++++- .../plugin-git/src/node/gitPlugin.ts | 5 ++++- .../development/plugin-git/src/node/options.ts | 13 ++++++++++++- .../plugin-git/src/node/resolveChangelog.ts | 2 +- .../plugin-git/src/node/resolveContributors.ts | 7 +++++++ .../development/plugin-git/src/node/typings.ts | 7 ++++++- .../plugin-git/src/node/utils/digestSHA256.ts | 3 +-- .../plugin-git/src/node/utils/getCommits.ts | 18 +++++++++++++++--- 9 files changed, 69 insertions(+), 11 deletions(-) diff --git a/docs/plugins/development/git.md b/docs/plugins/development/git.md index d5a6f3cbc..31e6a1023 100644 --- a/docs/plugins/development/git.md +++ b/docs/plugins/development/git.md @@ -107,6 +107,14 @@ This plugin will significantly slow down the speed of data preparation, especial */ avatar?: boolean + /** + * Avatar url pattern + * - `:username` - Contributor's username + * + * @example 'https://github.com/:username' + */ + avatarPattern?: string + /** * Functions to transform contributors, e.g. remove duplicates ones and sort them. * The input is the contributors collected by this plugin, and the output should be the transformed contributors. @@ -123,7 +131,7 @@ This plugin will significantly slow down the speed of data preparation, especial ### changelog -- Type: `false | ChangelogOptions` +- Type: `boolean | ChangelogOptions` ```ts interface ChangelogOptions { @@ -264,8 +272,11 @@ export default { ```ts interface GitContributor { + // display name name: string email: string + // username on the git hosting service + username: string commits: number avatar?: string url?: string diff --git a/docs/zh/plugins/development/git.md b/docs/zh/plugins/development/git.md index 15f28e9b4..8fedeb4be 100644 --- a/docs/zh/plugins/development/git.md +++ b/docs/zh/plugins/development/git.md @@ -82,6 +82,13 @@ export default { * 如果 git 托管服务为 `github`,则可以忽略不填,由插件自动填充 */ avatar?: string + /** + * 头像访问地址模式 + * - `:username` - 贡献者的用户名 + * + * @example 'https://github.com/:username' + */ + avatarPattern?: string /** * 贡献者访问地址 * 如果 git 托管服务为 `github`,则可以忽略不填,由插件自动填充 @@ -117,7 +124,7 @@ export default { ### changelog -- 类型: `false | ChangelogOptions` +- 类型: `boolean | ChangelogOptions` ```ts interface ChangelogOptions { @@ -258,8 +265,11 @@ export default { ```ts interface GitContributor { + // 在页面中显示的贡献者名称 name: string email: string + // 在 git 托管服务中的用户名 + username: string commits: number avatar?: string url?: string diff --git a/plugins/development/plugin-git/src/node/gitPlugin.ts b/plugins/development/plugin-git/src/node/gitPlugin.ts index ff82e6ea9..6fb4c1e80 100644 --- a/plugins/development/plugin-git/src/node/gitPlugin.ts +++ b/plugins/development/plugin-git/src/node/gitPlugin.ts @@ -58,7 +58,10 @@ export const gitPlugin = ), ] - const commits = await getCommits(filePaths, cwd) + const commits = await getCommits(filePaths, cwd, { + contributors: (frontmatter.contributors ?? contributors) !== false, + changelog: frontmatter.changelog ?? changelog, + }) if (commits.length === 0) return diff --git a/plugins/development/plugin-git/src/node/options.ts b/plugins/development/plugin-git/src/node/options.ts index 32ac94001..091ee244d 100644 --- a/plugins/development/plugin-git/src/node/options.ts +++ b/plugins/development/plugin-git/src/node/options.ts @@ -70,6 +70,17 @@ export interface ContributorsOptions { */ avatar?: boolean + /** + * Avatar url pattern + * - `:username` - Contributor's username + * + * 头像访问地址模式 + * - `:username` - 贡献者的用户名 + * + * @example 'https://github.com/:username' + */ + avatarPattern?: string + /** * Functions to transform contributors, e.g. remove duplicates ones and sort them * @@ -173,7 +184,7 @@ export interface GitPluginOptions { * * 是否收集页面的变更历史记录 */ - changelog?: ChangelogOptions | false + changelog?: ChangelogOptions | boolean /** * @deprecated use `contributors.transform` instead diff --git a/plugins/development/plugin-git/src/node/resolveChangelog.ts b/plugins/development/plugin-git/src/node/resolveChangelog.ts index 874d1e20a..009befe06 100644 --- a/plugins/development/plugin-git/src/node/resolveChangelog.ts +++ b/plugins/development/plugin-git/src/node/resolveChangelog.ts @@ -63,7 +63,7 @@ const parseTagName = (refs: string): string | undefined => { .split(',') .map((tag) => tag.trim()) - return tags[0]?.replace('tag:', '').trim() + return tags[0]?.includes('tag:') ? tags[0].replace('tag:', '').trim() : '' } export const resolveChangelog = ( diff --git a/plugins/development/plugin-git/src/node/resolveContributors.ts b/plugins/development/plugin-git/src/node/resolveContributors.ts index 05e8fe5b3..43827546a 100644 --- a/plugins/development/plugin-git/src/node/resolveContributors.ts +++ b/plugins/development/plugin-git/src/node/resolveContributors.ts @@ -38,6 +38,7 @@ export const getRawContributors = ( } else { const item: GitContributor = { name, + username, email, commits: 1, } @@ -45,6 +46,7 @@ export const getRawContributors = ( if (options.avatar) item.avatar = config?.avatar ?? + options.avatarPattern?.replace(':username', username) ?? (gitProvider === 'github' ? `https://avatars.githubusercontent.com/${username}?v=4` : `https://gravatar.com/avatar/${digestSHA256(email || username)}?d=retro`) @@ -97,6 +99,7 @@ export const resolveContributors = ( const result: GitContributor = { name: contributorInfo.name ?? extraContributor, + username: contributorInfo.name ?? extraContributor, email: '', commits: 0, } @@ -110,6 +113,10 @@ export const resolveContributors = ( if (options.avatar) result.avatar = contributorInfo.avatar ?? + options.avatarPattern?.replace( + ':username', + contributorInfo.username, + ) ?? (gitProvider === 'github' ? `https://avatars.githubusercontent.com/${contributorInfo.username}?v=4` : `https://gravatar.com/avatar/${digestSHA256(contributorInfo.username)}?d=retro`) diff --git a/plugins/development/plugin-git/src/node/typings.ts b/plugins/development/plugin-git/src/node/typings.ts index 166365f9b..3eda84df0 100644 --- a/plugins/development/plugin-git/src/node/typings.ts +++ b/plugins/development/plugin-git/src/node/typings.ts @@ -57,13 +57,18 @@ export interface MergedRawCommit extends Omit { export interface GitContributor { /** - * Contributor name + * Contributor display name */ name: string /** * Contributor email */ email: string + + /** + * Contributor username on the git hosting service + */ + username: string /** * Number of commits */ diff --git a/plugins/development/plugin-git/src/node/utils/digestSHA256.ts b/plugins/development/plugin-git/src/node/utils/digestSHA256.ts index 662aec642..4ba2a6e53 100644 --- a/plugins/development/plugin-git/src/node/utils/digestSHA256.ts +++ b/plugins/development/plugin-git/src/node/utils/digestSHA256.ts @@ -1,8 +1,7 @@ import { createHash } from 'node:crypto' -const hash = createHash('sha256') - export const digestSHA256 = (message: string): string => { + const hash = createHash('sha256') hash.update(message) return hash.digest('hex') diff --git a/plugins/development/plugin-git/src/node/utils/getCommits.ts b/plugins/development/plugin-git/src/node/utils/getCommits.ts index e0452c20a..195bd830e 100644 --- a/plugins/development/plugin-git/src/node/utils/getCommits.ts +++ b/plugins/development/plugin-git/src/node/utils/getCommits.ts @@ -1,7 +1,7 @@ import { execa } from 'execa' +import type { GitPluginOptions } from '../options.js' import type { GitContributor, MergedRawCommit, RawCommit } from '../typings.js' -const FORMAT = '%H|%an|%ae|%ad|%s|%d|%b' const SPLIT_CHAR = '[GIT_LOG_COMMIT_END]' const RE_SPLIT = /\[GIT_LOG_COMMIT_END\]$/ @@ -20,6 +20,15 @@ const getCoAuthors = ( .filter(Boolean) } +const getFormat = ({ contributors, changelog }: GitPluginOptions): string => { + // hash | _ | _ | author_date | _ | _ | _ + if (!contributors && !changelog) return '%H|||%ad|||' + // hash | author_name | author_email | author_date | _ | _ | body + if (contributors && !changelog) return '%H|%an|%ae|%ad|||%b' + // hash | author_name | author_email | author_date | subject | ref | body + return '%H|%an|%ae|%ad|%s|%d|%b' +} + /** * Get raw commits * @@ -30,14 +39,16 @@ const getCoAuthors = ( export const getRawCommits = async ( filepath: string, cwd: string, + options: GitPluginOptions, ): Promise => { + const format = getFormat(options) try { const { stdout } = await execa( 'git', [ 'log', '--max-count=-1', - `--format=${FORMAT}${SPLIT_CHAR}`, + `--format=${format}${SPLIT_CHAR}`, '--date=unix', '--follow', '--', @@ -87,9 +98,10 @@ export const mergeRawCommits = (commits: RawCommit[]): MergedRawCommit[] => { export const getCommits = async ( filepaths: string[], cwd: string, + options: GitPluginOptions, ): Promise => { const rawCommits = await Promise.all( - filepaths.map((filepath) => getRawCommits(filepath, cwd)), + filepaths.map((filepath) => getRawCommits(filepath, cwd, options)), ) return mergeRawCommits(rawCommits.flat()).sort((a, b) =>