@soybeanjs/changelog 0.4.0-beta.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +35 -70
- package/package.json +14 -14
package/dist/index.js
CHANGED
|
@@ -11,8 +11,7 @@ import { convert } from "convert-gitmoji";
|
|
|
11
11
|
//#region src/shared.ts
|
|
12
12
|
async function execCommand(cmd, args, options) {
|
|
13
13
|
const { execa } = await import("execa");
|
|
14
|
-
|
|
15
|
-
return (res?.stdout)?.trim() || "";
|
|
14
|
+
return ((await execa(cmd, args, options))?.stdout)?.trim() || "";
|
|
16
15
|
}
|
|
17
16
|
function notNullish(v) {
|
|
18
17
|
return v !== null && v !== void 0;
|
|
@@ -60,14 +59,12 @@ const VERSION_WITH_RELEASE = /release\sv\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;
|
|
|
60
59
|
//#region src/git.ts
|
|
61
60
|
/** Get the total git tags */
|
|
62
61
|
async function getTotalGitTags() {
|
|
63
|
-
const
|
|
62
|
+
const filtered = (await execCommand("git", [
|
|
64
63
|
"--no-pager",
|
|
65
64
|
"tag",
|
|
66
65
|
"-l",
|
|
67
66
|
"--sort=v:refname"
|
|
68
|
-
]);
|
|
69
|
-
const tags = tagStr.split("\n");
|
|
70
|
-
const filtered = tags.filter((tag) => VERSION_REG.test(tag));
|
|
67
|
+
])).split("\n").filter((tag) => VERSION_REG.test(tag));
|
|
71
68
|
return semver.sort(filtered);
|
|
72
69
|
}
|
|
73
70
|
/** Get map of the git tag and date */
|
|
@@ -81,8 +78,7 @@ async function getTagDateMap() {
|
|
|
81
78
|
]);
|
|
82
79
|
const TAG_MARK = "tag: ";
|
|
83
80
|
const map = /* @__PURE__ */ new Map();
|
|
84
|
-
|
|
85
|
-
dates.forEach((item) => {
|
|
81
|
+
tagDateStr.split("\n").filter((item) => item.includes(TAG_MARK)).forEach((item) => {
|
|
86
82
|
const [dateStr, tagStr] = item.split(TAG_MARK);
|
|
87
83
|
const date = dayjs(dateStr).format("YYYY-MM-DD");
|
|
88
84
|
const tag = tagStr.match(VERSION_REG)?.[0];
|
|
@@ -104,10 +100,7 @@ function getFromToTags(tags) {
|
|
|
104
100
|
if (index < reversedTags.length - 1) {
|
|
105
101
|
const to = tag;
|
|
106
102
|
let from = reversedTags[index + 1];
|
|
107
|
-
if (!isPrerelease(to))
|
|
108
|
-
const toIndex = releaseTags.indexOf(to);
|
|
109
|
-
from = releaseTags[toIndex - 1];
|
|
110
|
-
}
|
|
103
|
+
if (!isPrerelease(to)) from = releaseTags[releaseTags.indexOf(to) - 1];
|
|
111
104
|
result.push({
|
|
112
105
|
from,
|
|
113
106
|
to
|
|
@@ -117,12 +110,11 @@ function getFromToTags(tags) {
|
|
|
117
110
|
return result.reverse();
|
|
118
111
|
}
|
|
119
112
|
async function getGitMainBranchName() {
|
|
120
|
-
|
|
113
|
+
return await execCommand("git", [
|
|
121
114
|
"rev-parse",
|
|
122
115
|
"--abbrev-ref",
|
|
123
116
|
"HEAD"
|
|
124
117
|
]);
|
|
125
|
-
return main;
|
|
126
118
|
}
|
|
127
119
|
async function getCurrentGitBranch() {
|
|
128
120
|
const tag = await execCommand("git", [
|
|
@@ -144,8 +136,7 @@ async function getGitHubRepo() {
|
|
|
144
136
|
return `${match[1]}/${match[2]}`;
|
|
145
137
|
}
|
|
146
138
|
function isPrerelease(version) {
|
|
147
|
-
|
|
148
|
-
return !REG.test(version);
|
|
139
|
+
return !/^[^.]*[\d.]+$/.test(version);
|
|
149
140
|
}
|
|
150
141
|
function getFirstGitCommit() {
|
|
151
142
|
return execCommand("git", [
|
|
@@ -155,18 +146,16 @@ function getFirstGitCommit() {
|
|
|
155
146
|
]);
|
|
156
147
|
}
|
|
157
148
|
async function getGitDiff(from, to = "HEAD") {
|
|
158
|
-
|
|
149
|
+
return (await execCommand("git", [
|
|
159
150
|
"--no-pager",
|
|
160
151
|
"log",
|
|
161
152
|
`${from ? `${from}...` : ""}${to}`,
|
|
162
153
|
"--pretty=\"----%n%s|%h|%an|%ae%n%b\"",
|
|
163
154
|
"--name-status"
|
|
164
|
-
])
|
|
165
|
-
const rwaGitLines = rawGit.split("----\n").splice(1);
|
|
166
|
-
const gitCommits = rwaGitLines.map((line) => {
|
|
155
|
+
])).split("----\n").splice(1).map((line) => {
|
|
167
156
|
const [firstLine, ...body] = line.split("\n");
|
|
168
157
|
const [message, shortHash, authorName, authorEmail] = firstLine.split("|");
|
|
169
|
-
|
|
158
|
+
return {
|
|
170
159
|
message,
|
|
171
160
|
shortHash,
|
|
172
161
|
author: {
|
|
@@ -175,9 +164,7 @@ async function getGitDiff(from, to = "HEAD") {
|
|
|
175
164
|
},
|
|
176
165
|
body: body.join("\n")
|
|
177
166
|
};
|
|
178
|
-
return gitCommit;
|
|
179
167
|
});
|
|
180
|
-
return gitCommits;
|
|
181
168
|
}
|
|
182
169
|
function parseGitCommit(commit) {
|
|
183
170
|
const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
|
@@ -226,9 +213,7 @@ function parseGitCommit(commit) {
|
|
|
226
213
|
};
|
|
227
214
|
}
|
|
228
215
|
async function getGitCommits(from, to = "HEAD") {
|
|
229
|
-
|
|
230
|
-
const commits = rwaGitCommits.map((commit) => parseGitCommit(commit)).filter(notNullish);
|
|
231
|
-
return commits;
|
|
216
|
+
return (await getGitDiff(from, to)).map((commit) => parseGitCommit(commit)).filter(notNullish);
|
|
232
217
|
}
|
|
233
218
|
function getHeaders(githubToken) {
|
|
234
219
|
return {
|
|
@@ -239,8 +224,7 @@ function getHeaders(githubToken) {
|
|
|
239
224
|
async function getResolvedAuthorLogin(github, commitHashes, email) {
|
|
240
225
|
let login = "";
|
|
241
226
|
try {
|
|
242
|
-
|
|
243
|
-
login = data?.user?.username || "";
|
|
227
|
+
login = (await ofetch(`https://ungh.cc/users/find/${email}`))?.user?.username || "";
|
|
244
228
|
} catch (e) {
|
|
245
229
|
consola.log("e: ", e);
|
|
246
230
|
}
|
|
@@ -248,15 +232,13 @@ async function getResolvedAuthorLogin(github, commitHashes, email) {
|
|
|
248
232
|
const { repo, token } = github;
|
|
249
233
|
if (!token) return login;
|
|
250
234
|
if (commitHashes.length) try {
|
|
251
|
-
|
|
252
|
-
login = data?.author?.login || "";
|
|
235
|
+
login = (await ofetch(`https://api.github.com/repos/${repo}/commits/${commitHashes[0]}`, { headers: getHeaders(token) }))?.author?.login || "";
|
|
253
236
|
} catch (e) {
|
|
254
237
|
consola.log("e: ", e);
|
|
255
238
|
}
|
|
256
239
|
if (login) return login;
|
|
257
240
|
try {
|
|
258
|
-
|
|
259
|
-
login = data.items[0].login;
|
|
241
|
+
login = (await ofetch(`https://api.github.com/search/users?q=${encodeURIComponent(email)}`, { headers: getHeaders(token) })).items[0].login;
|
|
260
242
|
} catch (e) {
|
|
261
243
|
consola.log("e: ", e);
|
|
262
244
|
}
|
|
@@ -282,10 +264,7 @@ async function getGitCommitsAndResolvedAuthors(commits, github, resolvedLogins)
|
|
|
282
264
|
const login = await getResolvedAuthorLogin(github, commitHashes, email);
|
|
283
265
|
resolvedAuthor.login = login;
|
|
284
266
|
resolvedLogins?.set(email, login);
|
|
285
|
-
} else
|
|
286
|
-
const login = resolvedLogins?.get(email) || "";
|
|
287
|
-
resolvedAuthor.login = login;
|
|
288
|
-
}
|
|
267
|
+
} else resolvedAuthor.login = resolvedLogins?.get(email) || "";
|
|
289
268
|
resolvedAuthors.push(resolvedAuthor);
|
|
290
269
|
if (!map.has(email)) map.set(email, resolvedAuthor);
|
|
291
270
|
}
|
|
@@ -305,9 +284,8 @@ async function getGitCommitsAndResolvedAuthors(commits, github, resolvedLogins)
|
|
|
305
284
|
//#endregion
|
|
306
285
|
//#region src/options.ts
|
|
307
286
|
function createDefaultOptions() {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
cwd,
|
|
287
|
+
return {
|
|
288
|
+
cwd: process.cwd(),
|
|
311
289
|
types: {
|
|
312
290
|
feat: "🚀 Features",
|
|
313
291
|
fix: "🐞 Bug Fixes",
|
|
@@ -337,14 +315,12 @@ function createDefaultOptions() {
|
|
|
337
315
|
output: "CHANGELOG.md",
|
|
338
316
|
regenerate: false
|
|
339
317
|
};
|
|
340
|
-
return options;
|
|
341
318
|
}
|
|
342
319
|
async function getVersionFromPkgJson(cwd) {
|
|
343
320
|
let newVersion = "";
|
|
344
321
|
try {
|
|
345
322
|
const pkgJson = await readFile(`${cwd}/package.json`, "utf-8");
|
|
346
|
-
|
|
347
|
-
newVersion = pkg?.version || "";
|
|
323
|
+
newVersion = JSON.parse(pkgJson)?.version || "";
|
|
348
324
|
} catch {}
|
|
349
325
|
return { newVersion };
|
|
350
326
|
}
|
|
@@ -375,15 +351,14 @@ async function createOptions(options) {
|
|
|
375
351
|
//#endregion
|
|
376
352
|
//#region src/markdown.ts
|
|
377
353
|
function formatReferences(references, githubRepo, type) {
|
|
378
|
-
const
|
|
354
|
+
const referencesString = join(references.filter((i) => {
|
|
379
355
|
if (type === "issues") return i.type === "issue" || i.type === "pull-request";
|
|
380
356
|
return i.type === "hash";
|
|
381
357
|
}).map((ref) => {
|
|
382
358
|
if (!githubRepo) return ref.value;
|
|
383
359
|
if (ref.type === "pull-request" || ref.type === "issue") return `https://github.com/${githubRepo}/issues/${ref.value.slice(1)}`;
|
|
384
360
|
return `[<samp>(${ref.value.slice(0, 5)})</samp>](https://github.com/${githubRepo}/commit/${ref.value})`;
|
|
385
|
-
});
|
|
386
|
-
const referencesString = join(refs).trim();
|
|
361
|
+
})).trim();
|
|
387
362
|
if (type === "issues") return referencesString && `in ${referencesString}`;
|
|
388
363
|
return referencesString;
|
|
389
364
|
}
|
|
@@ -398,8 +373,7 @@ function formatLine(commit, options) {
|
|
|
398
373
|
hashRefs
|
|
399
374
|
].filter((i) => i?.trim()).join(" ");
|
|
400
375
|
if (refs) refs = ` - ${refs}`;
|
|
401
|
-
|
|
402
|
-
return [description, refs].filter((i) => i?.trim()).join(" ");
|
|
376
|
+
return [options.capitalize ? capitalize(commit.description) : commit.description, refs].filter((i) => i?.trim()).join(" ");
|
|
403
377
|
}
|
|
404
378
|
function formatTitle(name, options) {
|
|
405
379
|
const emojisRE = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;
|
|
@@ -430,13 +404,10 @@ function formatSection(commits, sectionName, options) {
|
|
|
430
404
|
return lines;
|
|
431
405
|
}
|
|
432
406
|
function getUserGithub(userName) {
|
|
433
|
-
|
|
434
|
-
return githubUrl;
|
|
407
|
+
return `https://github.com/${userName}`;
|
|
435
408
|
}
|
|
436
409
|
function getGitUserAvatar(userName) {
|
|
437
|
-
|
|
438
|
-
const avatarUrl = `${githubUrl}.png?size=48`;
|
|
439
|
-
return avatarUrl;
|
|
410
|
+
return `${getUserGithub(userName)}.png?size=48`;
|
|
440
411
|
}
|
|
441
412
|
function createContributorLine(contributors) {
|
|
442
413
|
let loginLine = "";
|
|
@@ -445,8 +416,7 @@ function createContributorLine(contributors) {
|
|
|
445
416
|
contributors.forEach((contributor) => {
|
|
446
417
|
contributorMap.set(contributor.email, contributor);
|
|
447
418
|
});
|
|
448
|
-
|
|
449
|
-
filteredContributors.forEach((contributor, index) => {
|
|
419
|
+
Array.from(contributorMap.values()).forEach((contributor, index) => {
|
|
450
420
|
const { name, email, login } = contributor;
|
|
451
421
|
if (!login) {
|
|
452
422
|
let line = `[${name}](mailto:${email})`;
|
|
@@ -485,8 +455,7 @@ function generateMarkdown(params) {
|
|
|
485
455
|
const contributorLine = createContributorLine(contributors);
|
|
486
456
|
lines.push(contributorLine);
|
|
487
457
|
}
|
|
488
|
-
|
|
489
|
-
return md;
|
|
458
|
+
return convert(lines.join("\n").trim(), true);
|
|
490
459
|
}
|
|
491
460
|
async function isVersionInMarkdown(newVersion, mdPath) {
|
|
492
461
|
let isIn = false;
|
|
@@ -530,14 +499,13 @@ async function getChangelogMarkdown(options, showTitle = true) {
|
|
|
530
499
|
const gitCommits = await getGitCommits(opts.from, to);
|
|
531
500
|
const resolvedLogins = /* @__PURE__ */ new Map();
|
|
532
501
|
const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, opts.github, resolvedLogins);
|
|
533
|
-
const markdown = generateMarkdown({
|
|
534
|
-
commits,
|
|
535
|
-
options: opts,
|
|
536
|
-
showTitle,
|
|
537
|
-
contributors
|
|
538
|
-
});
|
|
539
502
|
return {
|
|
540
|
-
markdown
|
|
503
|
+
markdown: generateMarkdown({
|
|
504
|
+
commits,
|
|
505
|
+
options: opts,
|
|
506
|
+
showTitle,
|
|
507
|
+
contributors
|
|
508
|
+
}),
|
|
541
509
|
commits,
|
|
542
510
|
options: opts
|
|
543
511
|
};
|
|
@@ -562,9 +530,8 @@ async function getTotalChangelogMarkdown(options, showProgress = true) {
|
|
|
562
530
|
const resolvedLogins = /* @__PURE__ */ new Map();
|
|
563
531
|
for await (const [index, tag] of tags.entries()) {
|
|
564
532
|
const { from, to } = tag;
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
const nextMd = generateMarkdown({
|
|
533
|
+
const { commits, contributors } = await getGitCommitsAndResolvedAuthors(await getGitCommits(from, to), opts.github, resolvedLogins);
|
|
534
|
+
markdown = `${generateMarkdown({
|
|
568
535
|
commits,
|
|
569
536
|
options: {
|
|
570
537
|
...opts,
|
|
@@ -573,8 +540,7 @@ async function getTotalChangelogMarkdown(options, showProgress = true) {
|
|
|
573
540
|
},
|
|
574
541
|
showTitle: true,
|
|
575
542
|
contributors
|
|
576
|
-
})
|
|
577
|
-
markdown = `${nextMd}\n\n${markdown}`;
|
|
543
|
+
})}\n\n${markdown}`;
|
|
578
544
|
bar?.update(index + 1);
|
|
579
545
|
}
|
|
580
546
|
bar?.stop();
|
|
@@ -600,8 +566,7 @@ async function generateChangelog(options) {
|
|
|
600
566
|
*/
|
|
601
567
|
async function generateTotalChangelog(options, showProgress = true) {
|
|
602
568
|
const opts = await createOptions(options);
|
|
603
|
-
|
|
604
|
-
await writeMarkdown(markdown, opts.output, true);
|
|
569
|
+
await writeMarkdown(await getTotalChangelogMarkdown(opts, showProgress), opts.output, true);
|
|
605
570
|
}
|
|
606
571
|
|
|
607
572
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soybeanjs/changelog",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.4.0
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"description": "generate changelog form git tags and commits for github",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Soybean",
|
|
@@ -38,25 +38,25 @@
|
|
|
38
38
|
"pnpm": ">=9"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@soybeanjs/eslint-config": "1.7.
|
|
41
|
+
"@soybeanjs/eslint-config": "1.7.5",
|
|
42
42
|
"cli-progress": "3.12.0",
|
|
43
43
|
"convert-gitmoji": "0.1.5",
|
|
44
|
-
"dayjs": "1.11.
|
|
45
|
-
"execa": "9.6.
|
|
46
|
-
"ofetch": "1.
|
|
47
|
-
"semver": "7.7.
|
|
44
|
+
"dayjs": "1.11.19",
|
|
45
|
+
"execa": "9.6.1",
|
|
46
|
+
"ofetch": "1.5.1",
|
|
47
|
+
"semver": "7.7.3"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@soybeanjs/cli": "1.4.
|
|
50
|
+
"@soybeanjs/cli": "1.4.1",
|
|
51
51
|
"@types/cli-progress": "3.11.6",
|
|
52
|
-
"@types/node": "
|
|
53
|
-
"@types/semver": "7.7.
|
|
54
|
-
"eslint": "9.
|
|
55
|
-
"lint-staged": "16.
|
|
52
|
+
"@types/node": "25.0.3",
|
|
53
|
+
"@types/semver": "7.7.1",
|
|
54
|
+
"eslint": "9.39.2",
|
|
55
|
+
"lint-staged": "16.2.7",
|
|
56
56
|
"simple-git-hooks": "2.13.1",
|
|
57
|
-
"tsdown": "0.
|
|
58
|
-
"tsx": "4.
|
|
59
|
-
"typescript": "5.9.
|
|
57
|
+
"tsdown": "0.18.2",
|
|
58
|
+
"tsx": "4.21.0",
|
|
59
|
+
"typescript": "5.9.3"
|
|
60
60
|
},
|
|
61
61
|
"simple-git-hooks": {
|
|
62
62
|
"commit-msg": "pnpm soy git-commit-verify",
|