@soybeanjs/changelog 0.3.9-beta.0 → 0.3.9-beta.3

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 ADDED
@@ -0,0 +1,616 @@
1
+ import {
2
+ consola
3
+ } from "./chunk-DZRUSQMM.js";
4
+
5
+ // src/index.ts
6
+ import { Presets, SingleBar } from "cli-progress";
7
+
8
+ // src/options.ts
9
+ import process from "process";
10
+ import { readFile } from "fs/promises";
11
+
12
+ // src/git.ts
13
+ import { ofetch } from "ofetch";
14
+ import dayjs from "dayjs";
15
+
16
+ // src/shared.ts
17
+ async function execCommand(cmd, args, options) {
18
+ var _a;
19
+ const { execa } = await import("execa");
20
+ const res = await execa(cmd, args, options);
21
+ return ((_a = res == null ? void 0 : res.stdout) == null ? void 0 : _a.trim()) || "";
22
+ }
23
+ function notNullish(v) {
24
+ return v !== null && v !== void 0;
25
+ }
26
+ function partition(array, ...filters) {
27
+ const result = Array.from({ length: filters.length + 1 }).fill(null).map(() => []);
28
+ array.forEach((e, idx, arr) => {
29
+ let i = 0;
30
+ for (const filter of filters) {
31
+ if (filter(e, idx, arr)) {
32
+ result[i].push(e);
33
+ return;
34
+ }
35
+ i += 1;
36
+ }
37
+ result[i].push(e);
38
+ });
39
+ return result;
40
+ }
41
+ function groupBy(items, key, groups = {}) {
42
+ for (const item of items) {
43
+ const v = item[key];
44
+ groups[v] || (groups[v] = []);
45
+ groups[v].push(item);
46
+ }
47
+ return groups;
48
+ }
49
+ function capitalize(str) {
50
+ return str.charAt(0).toUpperCase() + str.slice(1);
51
+ }
52
+ function join(array, glue = ", ", finalGlue = " and ") {
53
+ if (!array || array.length === 0)
54
+ return "";
55
+ if (array.length === 1)
56
+ return array[0];
57
+ if (array.length === 2)
58
+ return array.join(finalGlue);
59
+ return `${array.slice(0, -1).join(glue)}${finalGlue}${array.slice(-1)}`;
60
+ }
61
+
62
+ // src/constant.ts
63
+ var VERSION_REG = /v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;
64
+ var VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g;
65
+ var VERSION_WITH_RELEASE = /release\sv\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;
66
+
67
+ // src/git.ts
68
+ async function getTotalGitTags() {
69
+ const tagStr = await execCommand("git", ["--no-pager", "tag", "-l", "--sort=creatordate"]);
70
+ const tags = tagStr.split("\n");
71
+ return tags;
72
+ }
73
+ async function getTagDateMap() {
74
+ const tagDateStr = await execCommand("git", [
75
+ "--no-pager",
76
+ "log",
77
+ "--tags",
78
+ "--simplify-by-decoration",
79
+ "--pretty=format:%ci %d"
80
+ ]);
81
+ const TAG_MARK = "tag: ";
82
+ const map = /* @__PURE__ */ new Map();
83
+ const dates = tagDateStr.split("\n").filter((item) => item.includes(TAG_MARK));
84
+ dates.forEach((item) => {
85
+ var _a;
86
+ const [dateStr, tagStr] = item.split(TAG_MARK);
87
+ const date = dayjs(dateStr).format("YYYY-MM-DD");
88
+ const tag = (_a = tagStr.match(VERSION_REG)) == null ? void 0 : _a[0];
89
+ if (tag && date) {
90
+ map.set(tag.trim(), date);
91
+ }
92
+ });
93
+ return map;
94
+ }
95
+ function getFromToTags(tags) {
96
+ const result = [];
97
+ tags.forEach((tag, index) => {
98
+ if (index < tags.length - 1) {
99
+ result.push({ from: tag, to: tags[index + 1] });
100
+ }
101
+ });
102
+ return result;
103
+ }
104
+ async function getLastGitTag(delta = 0) {
105
+ const tags = await getTotalGitTags();
106
+ return tags[tags.length + delta - 1];
107
+ }
108
+ async function getGitMainBranchName() {
109
+ const main = await execCommand("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
110
+ return main;
111
+ }
112
+ async function getCurrentGitBranch() {
113
+ const tag = await execCommand("git", ["tag", "--points-at", "HEAD"]);
114
+ const main = getGitMainBranchName();
115
+ return tag || main;
116
+ }
117
+ async function getGitHubRepo() {
118
+ const url = await execCommand("git", ["config", "--get", "remote.origin.url"]);
119
+ const match = url.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);
120
+ if (!match) {
121
+ throw new Error(`Can not parse GitHub repo from url ${url}`);
122
+ }
123
+ return `${match[1]}/${match[2]}`;
124
+ }
125
+ function isPrerelease(version) {
126
+ const REG = /^[^.]*[\d.]+$/;
127
+ return !REG.test(version);
128
+ }
129
+ function getFirstGitCommit() {
130
+ return execCommand("git", ["rev-list", "--max-parents=0", "HEAD"]);
131
+ }
132
+ async function getGitDiff(from, to = "HEAD") {
133
+ const rawGit = await execCommand("git", [
134
+ "--no-pager",
135
+ "log",
136
+ `${from ? `${from}...` : ""}${to}`,
137
+ '--pretty="----%n%s|%h|%an|%ae%n%b"',
138
+ "--name-status"
139
+ ]);
140
+ const rwaGitLines = rawGit.split("----\n").splice(1);
141
+ const gitCommits = rwaGitLines.map((line) => {
142
+ const [firstLine, ...body] = line.split("\n");
143
+ const [message, shortHash, authorName, authorEmail] = firstLine.split("|");
144
+ const gitCommit = {
145
+ message,
146
+ shortHash,
147
+ author: { name: authorName, email: authorEmail },
148
+ body: body.join("\n")
149
+ };
150
+ return gitCommit;
151
+ });
152
+ return gitCommits;
153
+ }
154
+ function parseGitCommit(commit) {
155
+ const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
156
+ const CoAuthoredByRegex = /co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim;
157
+ const PullRequestRE = /\([a-z]*(#\d+)\s*\)/gm;
158
+ const IssueRE = /(#\d+)/gm;
159
+ const match = commit.message.match(ConventionalCommitRegex);
160
+ if (!(match == null ? void 0 : match.groups)) {
161
+ return null;
162
+ }
163
+ const type = match.groups.type;
164
+ const scope = match.groups.scope || "";
165
+ const isBreaking = Boolean(match.groups.breaking);
166
+ let description = match.groups.description;
167
+ const references = [];
168
+ for (const m of description.matchAll(PullRequestRE)) {
169
+ references.push({ type: "pull-request", value: m[1] });
170
+ }
171
+ for (const m of description.matchAll(IssueRE)) {
172
+ if (!references.some((i) => i.value === m[1])) {
173
+ references.push({ type: "issue", value: m[1] });
174
+ }
175
+ }
176
+ references.push({ value: commit.shortHash, type: "hash" });
177
+ description = description.replace(PullRequestRE, "").trim();
178
+ const authors = [commit.author];
179
+ const matches = commit.body.matchAll(CoAuthoredByRegex);
180
+ for (const $match of matches) {
181
+ const { name = "", email = "" } = $match.groups || {};
182
+ const author = {
183
+ name: name.trim(),
184
+ email: email.trim()
185
+ };
186
+ authors.push(author);
187
+ }
188
+ return {
189
+ ...commit,
190
+ authors,
191
+ resolvedAuthors: [],
192
+ description,
193
+ type,
194
+ scope,
195
+ references,
196
+ isBreaking
197
+ };
198
+ }
199
+ async function getGitCommits(from, to = "HEAD") {
200
+ const rwaGitCommits = await getGitDiff(from, to);
201
+ const commits = rwaGitCommits.map((commit) => parseGitCommit(commit)).filter(notNullish);
202
+ return commits;
203
+ }
204
+ function getHeaders(githubToken) {
205
+ return {
206
+ accept: "application/vnd.github.v3+json",
207
+ authorization: `token ${githubToken}`
208
+ };
209
+ }
210
+ async function getResolvedAuthorLogin(github, commitHashes, email) {
211
+ var _a, _b;
212
+ let login = "";
213
+ try {
214
+ const data = await ofetch(`https://ungh.cc/users/find/${email}`);
215
+ login = ((_a = data == null ? void 0 : data.user) == null ? void 0 : _a.username) || "";
216
+ } catch (e) {
217
+ consola.log("e: ", e);
218
+ }
219
+ if (login) {
220
+ return login;
221
+ }
222
+ const { repo, token } = github;
223
+ if (!token) {
224
+ return login;
225
+ }
226
+ if (commitHashes.length) {
227
+ try {
228
+ const data = await ofetch(`https://api.github.com/repos/${repo}/commits/${commitHashes[0]}`, {
229
+ headers: getHeaders(token)
230
+ });
231
+ login = ((_b = data == null ? void 0 : data.author) == null ? void 0 : _b.login) || "";
232
+ } catch (e) {
233
+ consola.log("e: ", e);
234
+ }
235
+ }
236
+ if (login) {
237
+ return login;
238
+ }
239
+ try {
240
+ const data = await ofetch(`https://api.github.com/search/users?q=${encodeURIComponent(email)}`, {
241
+ headers: getHeaders(token)
242
+ });
243
+ login = data.items[0].login;
244
+ } catch (e) {
245
+ consola.log("e: ", e);
246
+ }
247
+ return login;
248
+ }
249
+ async function getGitCommitsAndResolvedAuthors(commits, github, resolvedLogins) {
250
+ const resultCommits = [];
251
+ const map = /* @__PURE__ */ new Map();
252
+ for await (const commit of commits) {
253
+ const resolvedAuthors = [];
254
+ for await (const [index, author] of commit.authors.entries()) {
255
+ const { email, name } = author;
256
+ if (email && name) {
257
+ const commitHashes = [];
258
+ if (index === 0) {
259
+ commitHashes.push(commit.shortHash);
260
+ }
261
+ const resolvedAuthor = {
262
+ name,
263
+ email,
264
+ commits: commitHashes,
265
+ login: ""
266
+ };
267
+ if (!(resolvedLogins == null ? void 0 : resolvedLogins.has(email))) {
268
+ const login = await getResolvedAuthorLogin(github, commitHashes, email);
269
+ resolvedAuthor.login = login;
270
+ resolvedLogins == null ? void 0 : resolvedLogins.set(email, login);
271
+ } else {
272
+ const login = (resolvedLogins == null ? void 0 : resolvedLogins.get(email)) || "";
273
+ resolvedAuthor.login = login;
274
+ }
275
+ resolvedAuthors.push(resolvedAuthor);
276
+ if (!map.has(email)) {
277
+ map.set(email, resolvedAuthor);
278
+ }
279
+ }
280
+ }
281
+ const resultCommit = { ...commit, resolvedAuthors };
282
+ resultCommits.push(resultCommit);
283
+ }
284
+ return {
285
+ commits: resultCommits,
286
+ contributors: Array.from(map.values())
287
+ };
288
+ }
289
+
290
+ // src/options.ts
291
+ function createDefaultOptions() {
292
+ const cwd = process.cwd();
293
+ const options = {
294
+ cwd,
295
+ types: {
296
+ feat: "\u{1F680} Features",
297
+ fix: "\u{1F41E} Bug Fixes",
298
+ perf: "\u{1F525} Performance",
299
+ refactor: "\u{1F485} Refactors",
300
+ docs: "\u{1F4D6} Documentation",
301
+ build: "\u{1F4E6} Build",
302
+ types: "\u{1F30A} Types",
303
+ chore: "\u{1F3E1} Chore",
304
+ examples: "\u{1F3C0} Examples",
305
+ test: "\u2705 Tests",
306
+ style: "\u{1F3A8} Styles",
307
+ ci: "\u{1F916} CI"
308
+ },
309
+ github: {
310
+ repo: "",
311
+ token: process.env.GITHUB_TOKEN || ""
312
+ },
313
+ from: "",
314
+ to: "",
315
+ tags: [],
316
+ tagDateMap: /* @__PURE__ */ new Map(),
317
+ capitalize: false,
318
+ emoji: true,
319
+ titles: {
320
+ breakingChanges: "\u{1F6A8} Breaking Changes"
321
+ },
322
+ output: "CHANGELOG.md",
323
+ regenerate: false,
324
+ newVersion: ""
325
+ };
326
+ return options;
327
+ }
328
+ async function getVersionFromPkgJson(cwd) {
329
+ let newVersion = "";
330
+ try {
331
+ const pkgJson = await readFile(`${cwd}/package.json`, "utf-8");
332
+ const pkg = JSON.parse(pkgJson);
333
+ newVersion = (pkg == null ? void 0 : pkg.version) || "";
334
+ } catch {
335
+ }
336
+ return {
337
+ newVersion
338
+ };
339
+ }
340
+ async function createOptions(options) {
341
+ var _a;
342
+ const opts = createDefaultOptions();
343
+ Object.assign(opts, options);
344
+ const { newVersion } = await getVersionFromPkgJson(opts.cwd);
345
+ (_a = opts.github).repo || (_a.repo = await getGitHubRepo());
346
+ opts.newVersion || (opts.newVersion = `v${newVersion}`);
347
+ opts.from || (opts.from = await getLastGitTag());
348
+ opts.to || (opts.to = await getCurrentGitBranch());
349
+ if (opts.to === opts.from) {
350
+ const lastTag = await getLastGitTag(-1);
351
+ const firstCommit = await getFirstGitCommit();
352
+ opts.from = lastTag || firstCommit;
353
+ }
354
+ opts.tags = await getTotalGitTags();
355
+ opts.tagDateMap = await getTagDateMap();
356
+ opts.prerelease || (opts.prerelease = isPrerelease(opts.to));
357
+ const isFromPrerelease = isPrerelease(opts.from);
358
+ if (!opts.prerelease && isFromPrerelease) {
359
+ const allReleaseTags = opts.tags.filter((tag) => !isPrerelease(tag));
360
+ opts.from = allReleaseTags[allReleaseTags.length - 2];
361
+ }
362
+ return opts;
363
+ }
364
+
365
+ // src/markdown.ts
366
+ import { existsSync } from "fs";
367
+ import { readFile as readFile2, writeFile } from "fs/promises";
368
+ import dayjs2 from "dayjs";
369
+ import { convert } from "convert-gitmoji";
370
+ function formatReferences(references, githubRepo, type) {
371
+ const refs = references.filter((i) => {
372
+ if (type === "issues")
373
+ return i.type === "issue" || i.type === "pull-request";
374
+ return i.type === "hash";
375
+ }).map((ref) => {
376
+ if (!githubRepo)
377
+ return ref.value;
378
+ if (ref.type === "pull-request" || ref.type === "issue")
379
+ return `https://github.com/${githubRepo}/issues/${ref.value.slice(1)}`;
380
+ return `[<samp>(${ref.value.slice(0, 5)})</samp>](https://github.com/${githubRepo}/commit/${ref.value})`;
381
+ });
382
+ const referencesString = join(refs).trim();
383
+ if (type === "issues")
384
+ return referencesString && `in ${referencesString}`;
385
+ return referencesString;
386
+ }
387
+ function formatLine(commit, options) {
388
+ const prRefs = formatReferences(commit.references, options.github.repo, "issues");
389
+ const hashRefs = formatReferences(commit.references, options.github.repo, "hash");
390
+ let authors = join([...new Set(commit.resolvedAuthors.map((i) => i.login ? `@${i.login}` : `**${i.name}**`))]).trim();
391
+ if (authors) {
392
+ authors = `by ${authors}`;
393
+ }
394
+ let refs = [authors, prRefs, hashRefs].filter((i) => i == null ? void 0 : i.trim()).join(" ");
395
+ if (refs) {
396
+ refs = `&nbsp;-&nbsp; ${refs}`;
397
+ }
398
+ const description = options.capitalize ? capitalize(commit.description) : commit.description;
399
+ return [description, refs].filter((i) => i == null ? void 0 : i.trim()).join(" ");
400
+ }
401
+ function formatTitle(name, options) {
402
+ const emojisRE = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;
403
+ let formatName = name.trim();
404
+ if (!options.emoji) {
405
+ formatName = name.replace(emojisRE, "").trim();
406
+ }
407
+ return `### &nbsp;&nbsp;&nbsp;${formatName}`;
408
+ }
409
+ function formatSection(commits, sectionName, options) {
410
+ if (!commits.length)
411
+ return [];
412
+ const lines = ["", formatTitle(sectionName, options), ""];
413
+ const scopes = groupBy(commits, "scope");
414
+ let useScopeGroup = true;
415
+ if (!Object.entries(scopes).some(([k, v]) => k && v.length > 1)) {
416
+ useScopeGroup = false;
417
+ }
418
+ Object.keys(scopes).sort().forEach((scope) => {
419
+ let padding = "";
420
+ let prefix = "";
421
+ const scopeText = `**${scope}**`;
422
+ if (scope && useScopeGroup) {
423
+ lines.push(`- ${scopeText}:`);
424
+ padding = " ";
425
+ } else if (scope) {
426
+ prefix = `${scopeText}: `;
427
+ }
428
+ lines.push(...scopes[scope].reverse().map((commit) => `${padding}- ${prefix}${formatLine(commit, options)}`));
429
+ });
430
+ return lines;
431
+ }
432
+ function getUserGithub(userName) {
433
+ const githubUrl = `https://github.com/${userName}`;
434
+ return githubUrl;
435
+ }
436
+ function getGitUserAvatar(userName) {
437
+ const githubUrl = getUserGithub(userName);
438
+ const avatarUrl = `${githubUrl}.png?size=48`;
439
+ return avatarUrl;
440
+ }
441
+ function createContributorLine(contributors) {
442
+ let loginLine = "";
443
+ let unLoginLine = "";
444
+ const contributorMap = /* @__PURE__ */ new Map();
445
+ contributors.forEach((contributor) => {
446
+ contributorMap.set(contributor.email, contributor);
447
+ });
448
+ const filteredContributors = Array.from(contributorMap.values());
449
+ filteredContributors.forEach((contributor, index) => {
450
+ const { name, email, login } = contributor;
451
+ if (!login) {
452
+ let line = `[${name}](mailto:${email})`;
453
+ if (index < contributors.length - 1) {
454
+ line += ",&nbsp;";
455
+ }
456
+ unLoginLine += line;
457
+ } else {
458
+ const githubUrl = getUserGithub(login);
459
+ const avatar = getGitUserAvatar(login);
460
+ loginLine += `[![${login}](${avatar})](${githubUrl})&nbsp;&nbsp;`;
461
+ }
462
+ });
463
+ return `${loginLine}
464
+ ${unLoginLine}`;
465
+ }
466
+ function generateMarkdown(params) {
467
+ const { options, showTitle, contributors } = params;
468
+ const commits = params.commits.filter((commit) => commit.description.match(VERSION_WITH_RELEASE) === null);
469
+ const lines = [];
470
+ const { version, isNewVersion } = getVersionInfo(options.to, options.newVersion);
471
+ const url = `https://github.com/${options.github.repo}/compare/${options.from}...${version}`;
472
+ if (showTitle) {
473
+ const date = isNewVersion ? dayjs2().format("YY-MM-DD") : options.tagDateMap.get(options.to);
474
+ let title = `## [${version}](${url})`;
475
+ if (date) {
476
+ title += ` (${date})`;
477
+ }
478
+ lines.push(title);
479
+ }
480
+ const [breaking, changes] = partition(commits, (c) => c.isBreaking);
481
+ const group = groupBy(changes, "type");
482
+ lines.push(...formatSection(breaking, options.titles.breakingChanges, options));
483
+ for (const type of Object.keys(options.types)) {
484
+ const items = group[type] || [];
485
+ lines.push(...formatSection(items, options.types[type], options));
486
+ }
487
+ if (!lines.length) {
488
+ lines.push("*No significant changes*");
489
+ }
490
+ if (!showTitle) {
491
+ lines.push("", `##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](${url})`);
492
+ }
493
+ if (showTitle) {
494
+ lines.push("", "### &nbsp;&nbsp;&nbsp;\u2764\uFE0F Contributors", "");
495
+ const contributorLine = createContributorLine(contributors);
496
+ lines.push(contributorLine);
497
+ }
498
+ const md = convert(lines.join("\n").trim(), true);
499
+ return md;
500
+ }
501
+ async function isVersionInMarkdown(to, newVersion, mdPath) {
502
+ let isIn = false;
503
+ let md = "";
504
+ try {
505
+ md = await readFile2(mdPath, "utf8");
506
+ } catch (error) {
507
+ }
508
+ if (md) {
509
+ const matches = md.match(VERSION_REG_OF_MARKDOWN);
510
+ if (matches == null ? void 0 : matches.length) {
511
+ const { version } = getVersionInfo(to, newVersion);
512
+ const versionInMarkdown = `## [${version}]`;
513
+ isIn = matches.includes(versionInMarkdown);
514
+ }
515
+ }
516
+ return isIn;
517
+ }
518
+ function getVersionInfo(to, newVersion) {
519
+ const isNewVersion = !VERSION_REG.test(to);
520
+ const version = isNewVersion ? newVersion : to;
521
+ return {
522
+ version,
523
+ isNewVersion
524
+ };
525
+ }
526
+ async function writeMarkdown(md, mdPath, regenerate = false) {
527
+ let changelogMD = "";
528
+ const changelogPrefix = "# Changelog";
529
+ if (!existsSync(mdPath)) {
530
+ await writeFile(mdPath, `${changelogPrefix}
531
+
532
+ `, "utf8");
533
+ }
534
+ if (!regenerate) {
535
+ changelogMD = await readFile2(mdPath, "utf8");
536
+ }
537
+ if (!changelogMD.startsWith(changelogPrefix)) {
538
+ changelogMD = `${changelogPrefix}
539
+
540
+ ${changelogMD}`;
541
+ }
542
+ const lastEntry = changelogMD.match(/^###?\s+.*$/m);
543
+ if (lastEntry) {
544
+ changelogMD = `${changelogMD.slice(0, lastEntry.index) + md}
545
+
546
+ ${changelogMD.slice(lastEntry.index)}`;
547
+ } else {
548
+ changelogMD += `
549
+ ${md}
550
+
551
+ `;
552
+ }
553
+ await writeFile(mdPath, changelogMD);
554
+ }
555
+
556
+ // src/index.ts
557
+ async function getChangelogMarkdown(options, showTitle = true) {
558
+ const opts = await createOptions(options);
559
+ const gitCommits = await getGitCommits(opts.from, opts.to);
560
+ const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, opts.github);
561
+ const markdown = generateMarkdown({ commits, options: opts, showTitle, contributors });
562
+ return {
563
+ markdown,
564
+ commits,
565
+ options: opts
566
+ };
567
+ }
568
+ async function getTotalChangelogMarkdown(options, showProgress = true) {
569
+ const opts = await createOptions(options);
570
+ let bar = null;
571
+ if (showProgress) {
572
+ bar = new SingleBar(
573
+ { format: "generate total changelog: [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}" },
574
+ Presets.shades_classic
575
+ );
576
+ }
577
+ const tags = getFromToTags(opts.tags);
578
+ if (tags.length === 0) {
579
+ const { markdown: markdown2 } = await getChangelogMarkdown(opts);
580
+ return markdown2;
581
+ }
582
+ bar == null ? void 0 : bar.start(tags.length, 0);
583
+ let markdown = "";
584
+ const resolvedLogins = /* @__PURE__ */ new Map();
585
+ for await (const [index, tag] of tags.entries()) {
586
+ const { from, to } = tag;
587
+ const gitCommits = await getGitCommits(from, to);
588
+ const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, opts.github, resolvedLogins);
589
+ const nextMd = generateMarkdown({ commits, options: { ...opts, from, to }, showTitle: true, contributors });
590
+ markdown = `${nextMd}
591
+
592
+ ${markdown}`;
593
+ bar == null ? void 0 : bar.update(index + 1);
594
+ }
595
+ bar == null ? void 0 : bar.stop();
596
+ return markdown;
597
+ }
598
+ async function generateChangelog(options) {
599
+ const opts = await createOptions(options);
600
+ const existContent = await isVersionInMarkdown(opts.to, opts.newVersion, opts.output);
601
+ if (!opts.regenerate && existContent)
602
+ return;
603
+ const { markdown } = await getChangelogMarkdown(opts);
604
+ await writeMarkdown(markdown, opts.output, opts.regenerate);
605
+ }
606
+ async function generateTotalChangelog(options, showProgress = true) {
607
+ const opts = await createOptions(options);
608
+ const markdown = await getTotalChangelogMarkdown(opts, showProgress);
609
+ await writeMarkdown(markdown, opts.output, true);
610
+ }
611
+ export {
612
+ generateChangelog,
613
+ generateTotalChangelog,
614
+ getChangelogMarkdown,
615
+ getTotalChangelogMarkdown
616
+ };