@taiga-ui/auto-changelog-config 0.493.0 → 0.495.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taiga-ui/auto-changelog-config",
3
- "version": "0.493.0",
3
+ "version": "0.495.0",
4
4
  "description": "Taiga UI auto-changelog config",
5
5
  "keywords": [
6
6
  "auto-changelog"
@@ -7,15 +7,15 @@
7
7
  {{#commit-parser merges commits}}
8
8
 
9
9
  {{#commit-list this heading='### ⚠️ BREAKING CHANGES' message='^(feat|fix|perf)(\([^)]*\))!:' }}
10
- - {{#replaceCommit}}{{subject}}{{/replaceCommit}}{{#if pullRequest}}{{#if pullRequest.href}} ([#{{pullRequest.id}}]({{pullRequest.href}})){{else}} (#{{pullRequest.id}}){{/if}}{{/if}}{{#if shorthash}}{{#if href}} [({{shorthash}})]({{href}}){{else}} ({{shorthash}}){{/if}}{{/if}}
10
+ - {{changelogEntry}}
11
11
  {{/commit-list}}
12
12
 
13
13
  {{#commit-list this heading='### 🚀 Features' message='^feat:|^feat\(' exclude='^(feat|fix|perf)(\([^)]*\))!:'}}
14
- - {{#replaceCommit}}{{subject}}{{/replaceCommit}}{{#if pullRequest}}{{#if pullRequest.href}} ([#{{pullRequest.id}}]({{pullRequest.href}})){{else}} (#{{pullRequest.id}}){{/if}}{{/if}}{{#if shorthash}}{{#if href}} [({{shorthash}})]({{href}}){{else}} ({{shorthash}}){{/if}}{{/if}}
14
+ - {{changelogEntry}}
15
15
  {{/commit-list}}
16
16
 
17
17
  {{#commit-list this heading='### 🐞 Bug Fixes' message='^fix:|^fix\(' exclude='^(feat|fix|perf)(\([^)]*\))!:'}}
18
- - {{#replaceCommit}}{{subject}}{{/replaceCommit}}{{#if pullRequest}}{{#if pullRequest.href}} ([#{{pullRequest.id}}]({{pullRequest.href}})){{else}} (#{{pullRequest.id}}){{/if}}{{/if}}{{#if shorthash}}{{#if href}} [({{shorthash}})]({{href}}){{else}} ({{shorthash}}){{/if}}{{/if}}
18
+ - {{changelogEntry}}
19
19
  {{/commit-list}}
20
20
 
21
21
  {{/commit-parser}}
package/setup.js CHANGED
@@ -3,6 +3,15 @@ module.exports = function (Handlebars) {
3
3
  const firstNonEmptyString = (...values) =>
4
4
  values.map((value) => String(value ?? '').trim()).find(Boolean) ?? '';
5
5
 
6
+ const escape = (value) => Handlebars.escapeExpression(String(value ?? ''));
7
+
8
+ const createMarkdownLink = (text, href) => {
9
+ const safeText = escape(text);
10
+ const safeHref = escape(href);
11
+
12
+ return href ? `[${safeText}](${safeHref})` : safeText;
13
+ };
14
+
6
15
  const getPullRequestId = (href) => {
7
16
  const [, id = ''] =
8
17
  String(href ?? '').match(
@@ -12,14 +21,49 @@ module.exports = function (Handlebars) {
12
21
  return id;
13
22
  };
14
23
 
15
- const normalizePullRequest = (commit) => {
24
+ const getPullRequestIdFromText = (text) => {
25
+ const [, id = ''] = String(text ?? '').match(/\s\(#(\d+)\)\s*$/) ?? [];
26
+
27
+ return id;
28
+ };
29
+
30
+ const isPullRequestHref = (href) =>
31
+ /\/(?:pull|merge_requests|pull-requests)\/\d+(?:$|[/?#])/.test(
32
+ String(href ?? ''),
33
+ );
34
+
35
+ const isCommitHref = (href) =>
36
+ /\/commit\/[a-f\d]{7,40}(?:$|[/?#])/.test(String(href ?? ''));
37
+
38
+ const getCommitHashFromHref = (href) => {
39
+ const [, hash = ''] =
40
+ String(href ?? '').match(/\/commit\/([a-f\d]{7,40})(?:$|[/?#])/) ?? [];
41
+
42
+ return hash;
43
+ };
44
+
45
+ const getRepositoryHref = (href) => {
46
+ const [, repositoryHref = ''] =
47
+ String(href ?? '').match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)(?:\/|$)/) ?? [];
48
+
49
+ return repositoryHref;
50
+ };
51
+
52
+ const normalizePullRequest = (commit, subject) => {
16
53
  const pullRequest = commit.pullRequest ?? {};
17
- const href = firstNonEmptyString(pullRequest.href, commit.href);
54
+
55
+ const href =
56
+ [pullRequest.href, commit.pullRequestHref, commit.href]
57
+ .map((value) => firstNonEmptyString(value))
58
+ .find(isPullRequestHref) ?? '';
18
59
 
19
60
  const id = firstNonEmptyString(
20
61
  pullRequest.id,
21
62
  pullRequest.number,
22
63
  getPullRequestId(href),
64
+ getPullRequestIdFromText(subject),
65
+ getPullRequestIdFromText(commit.message),
66
+ getPullRequestIdFromText(commit.title),
23
67
  );
24
68
 
25
69
  if (!id) {
@@ -34,24 +78,145 @@ module.exports = function (Handlebars) {
34
78
  };
35
79
  };
36
80
 
81
+ const getCommitHref = (commit, pullRequest) => {
82
+ const href = firstNonEmptyString(commit.commitHref, commit.href);
83
+
84
+ if (isCommitHref(href)) {
85
+ return href;
86
+ }
87
+
88
+ const hash = firstNonEmptyString(
89
+ commit.hash,
90
+ commit.shorthash,
91
+ getCommitHashFromHref(href),
92
+ );
93
+
94
+ const repositoryHref = getRepositoryHref(
95
+ firstNonEmptyString(commit.repositoryHref, href, pullRequest?.href),
96
+ );
97
+
98
+ return hash && repositoryHref ? `${repositoryHref}/commit/${hash}` : '';
99
+ };
100
+
101
+ const getCommitHash = (commit, commitHref) =>
102
+ firstNonEmptyString(
103
+ commit.commitHash,
104
+ commit.shorthash,
105
+ getCommitHashFromHref(commitHref),
106
+ String(commit.hash ?? '').slice(0, 7),
107
+ ).slice(0, 7);
108
+
37
109
  const normalizeCommit = (commit) => {
38
110
  const subject = firstNonEmptyString(
39
111
  commit.subject,
40
- commit.message,
41
- commit.title,
42
112
  commit.pullRequest?.title,
113
+ commit.title,
114
+ commit.message,
43
115
  );
44
116
 
45
- const pullRequest = normalizePullRequest(commit);
117
+ const pullRequest = normalizePullRequest(commit, subject);
118
+ const commitHref = getCommitHref(commit, pullRequest);
119
+ const commitHash = getCommitHash(commit, commitHref);
46
120
 
47
121
  return {
48
122
  ...commit,
123
+ commitHash,
124
+ commitHref,
49
125
  message: firstNonEmptyString(commit.message, subject),
50
126
  pullRequest,
51
127
  subject,
52
128
  };
53
129
  };
54
130
 
131
+ const getCommitKey = (commit) =>
132
+ firstNonEmptyString(
133
+ commit.pullRequest?.id ? `pr:${commit.pullRequest.id}` : '',
134
+ commit.hash ? `hash:${commit.hash}` : '',
135
+ commit.commitHash ? `hash:${commit.commitHash}` : '',
136
+ commit.subject ? `subject:${commit.subject}` : '',
137
+ );
138
+
139
+ const mergePullRequests = (left, right) => {
140
+ if (!left && !right) {
141
+ return;
142
+ }
143
+
144
+ if (!left) {
145
+ return right;
146
+ }
147
+
148
+ if (!right) {
149
+ return left;
150
+ }
151
+
152
+ return {
153
+ ...left,
154
+ ...right,
155
+ id: firstNonEmptyString(left.id, right.id),
156
+ author: left.author ?? right.author,
157
+ href: firstNonEmptyString(left.href, right.href),
158
+ };
159
+ };
160
+
161
+ const mergeCommits = (left, right) => ({
162
+ ...left,
163
+ ...right,
164
+ commitHash: firstNonEmptyString(left.commitHash, right.commitHash),
165
+ commitHref: firstNonEmptyString(left.commitHref, right.commitHref),
166
+ hash: firstNonEmptyString(left.hash, right.hash),
167
+ href: firstNonEmptyString(left.href, right.href),
168
+ message: firstNonEmptyString(left.message, right.message),
169
+ pullRequest: mergePullRequests(left.pullRequest, right.pullRequest),
170
+ shorthash: firstNonEmptyString(left.shorthash, right.shorthash),
171
+ subject: firstNonEmptyString(left.subject, right.subject),
172
+ });
173
+
174
+ const formatCommitTitle = (subject) => {
175
+ const commit =
176
+ /^(?:build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)\s?(?:\((?<scope>[^)]*)\))?!?: (?<title>.*)$/;
177
+
178
+ const string = String(subject ?? '').trim();
179
+ const {scope = '', title = ''} = commit.exec(string)?.groups ?? {};
180
+ const cleanTitle = title.replace(/\s\(#\d+\)\s*$/, '');
181
+
182
+ if (!cleanTitle) {
183
+ return escape(string || 'empty commit name');
184
+ }
185
+
186
+ return scope
187
+ ? `**${escape(scope.toLowerCase())}**: ${escape(cleanTitle)}`
188
+ : escape(cleanTitle);
189
+ };
190
+
191
+ const formatPullRequestReference = (commit) => {
192
+ const pullRequest = commit.pullRequest;
193
+
194
+ if (!pullRequest?.id) {
195
+ return '';
196
+ }
197
+
198
+ const link = createMarkdownLink(`#${pullRequest.id}`, pullRequest.href);
199
+
200
+ return `(${link})`;
201
+ };
202
+
203
+ const formatCommitReference = (commit) => {
204
+ if (!commit.commitHash) {
205
+ return '';
206
+ }
207
+
208
+ return createMarkdownLink(`(${commit.commitHash})`, commit.commitHref);
209
+ };
210
+
211
+ const formatChangelogEntry = (commit) =>
212
+ [
213
+ formatCommitTitle(commit.subject),
214
+ formatPullRequestReference(commit),
215
+ formatCommitReference(commit),
216
+ ]
217
+ .filter(Boolean)
218
+ .join(' ');
219
+
55
220
  const getCommitAuthor = (commit) =>
56
221
  commit.pullRequest?.author?.login ??
57
222
  commit.pullRequest?.user?.login ??
@@ -102,33 +267,37 @@ module.exports = function (Handlebars) {
102
267
 
103
268
  const commits = args.flat().filter(Boolean).map(normalizeCommit);
104
269
 
105
- const unique = [
106
- ...new Map(
107
- commits.map((commit) => [
108
- firstNonEmptyString(
109
- commit.hash,
110
- commit.shorthash,
111
- commit.pullRequest?.href,
112
- commit.href,
113
- commit.subject,
114
- ),
115
- commit,
116
- ]),
117
- ).values(),
118
- ];
270
+ const unique = commits.reduce((map, commit) => {
271
+ const key = getCommitKey(commit);
272
+
273
+ if (!key) {
274
+ return map;
275
+ }
276
+
277
+ const previous = map.get(key);
119
278
 
120
- return options.fn(unique);
279
+ map.set(key, previous ? mergeCommits(previous, commit) : commit);
280
+
281
+ return map;
282
+ }, new Map());
283
+
284
+ return options.fn([...unique.values()]);
121
285
  });
122
286
 
123
287
  Handlebars.registerHelper('replaceCommit', function (context) {
124
- const commit =
125
- /^(?:build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)\s?(?:\((?<scope>[^)]*)\))?!?: (?<title>.*)$/;
288
+ return new Handlebars.SafeString(formatCommitTitle(context.fn(this)));
289
+ });
126
290
 
127
- const string = String(context.fn(this)).trim();
128
- const {scope = '', title = ''} = commit.exec(string)?.groups ?? {};
129
- const result = scope ? `**${scope.toLowerCase()}**: ${title}` : title;
291
+ Handlebars.registerHelper('pullRequestLink', function () {
292
+ return new Handlebars.SafeString(formatPullRequestReference(this));
293
+ });
294
+
295
+ Handlebars.registerHelper('commitLink', function () {
296
+ return new Handlebars.SafeString(formatCommitReference(this));
297
+ });
130
298
 
131
- return result || string || 'empty commit name';
299
+ Handlebars.registerHelper('changelogEntry', function () {
300
+ return new Handlebars.SafeString(formatChangelogEntry(this));
132
301
  });
133
302
 
134
303
  Handlebars.registerHelper('replaceTitle', function (context) {
package/template.hbs CHANGED
@@ -7,15 +7,15 @@
7
7
  {{#commit-parser merges commits}}
8
8
 
9
9
  {{#commit-list this heading='### ⚠️ BREAKING CHANGES' message='^(feat|fix|perf)(\([^)]*\))!:' }}
10
- - {{#replaceCommit}}{{subject}}{{/replaceCommit}}{{#if pullRequest}}{{#if pullRequest.href}} ([#{{pullRequest.id}}]({{pullRequest.href}})){{else}} (#{{pullRequest.id}}){{/if}}{{/if}}{{#if shorthash}}{{#if href}} [({{shorthash}})]({{href}}){{else}} ({{shorthash}}){{/if}}{{/if}}
10
+ - {{changelogEntry}}
11
11
  {{/commit-list}}
12
12
 
13
13
  {{#commit-list this heading='### 🚀 Features' message='^feat:|^feat\(' exclude='^(feat|fix|perf)(\([^)]*\))!:'}}
14
- - {{#replaceCommit}}{{subject}}{{/replaceCommit}}{{#if pullRequest}}{{#if pullRequest.href}} ([#{{pullRequest.id}}]({{pullRequest.href}})){{else}} (#{{pullRequest.id}}){{/if}}{{/if}}{{#if shorthash}}{{#if href}} [({{shorthash}})]({{href}}){{else}} ({{shorthash}}){{/if}}{{/if}}
14
+ - {{changelogEntry}}
15
15
  {{/commit-list}}
16
16
 
17
17
  {{#commit-list this heading='### 🐞 Bug Fixes' message='^fix:|^fix\(' exclude='^(feat|fix|perf)(\([^)]*\))!:'}}
18
- - {{#replaceCommit}}{{subject}}{{/replaceCommit}}{{#if pullRequest}}{{#if pullRequest.href}} ([#{{pullRequest.id}}]({{pullRequest.href}})){{else}} (#{{pullRequest.id}}){{/if}}{{/if}}{{#if shorthash}}{{#if href}} [({{shorthash}})]({{href}}){{else}} ({{shorthash}}){{/if}}{{/if}}
18
+ - {{changelogEntry}}
19
19
  {{/commit-list}}
20
20
 
21
21
  {{/commit-parser}}