@icebreakers/changelog-github 0.1.0 → 0.2.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.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/index.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/index.ts
2
2
  var _getgithubinfo = require('@changesets/get-github-info');
3
3
  var _dotenv = require('dotenv');
4
4
  _dotenv.config.call(void 0, );
@@ -34,7 +34,7 @@ async function collectDependencyReferences(changesets, repo) {
34
34
  return links.commit;
35
35
  })
36
36
  );
37
- return references.filter((link) => Boolean(link));
37
+ return [...new Set(references.filter((link) => Boolean(link)))];
38
38
  }
39
39
  function formatDependencyLine(references, dependenciesUpdated) {
40
40
  const count = dependenciesUpdated.length;
@@ -42,16 +42,50 @@ function formatDependencyLine(references, dependenciesUpdated) {
42
42
  if (count === 0) {
43
43
  return firstCommit ? `- \u{1F4E6} **Dependencies** ${firstCommit}` : "- \u{1F4E6} **Dependencies**";
44
44
  }
45
+ const dependencySummaries = dependenciesUpdated.map(
46
+ (dependency) => `\`${dependency.name}@${dependency.newVersion}\``
47
+ );
45
48
  if (count <= 3) {
46
- const dependencySummaries = dependenciesUpdated.map(
47
- (dependency) => `\`${dependency.name}@${dependency.newVersion}\``
48
- );
49
- const header = firstCommit ? `- \u{1F4E6} **Dependencies** ${firstCommit}` : "- \u{1F4E6} **Dependencies**";
49
+ const header2 = firstCommit ? `- \u{1F4E6} **Dependencies** ${firstCommit}` : "- \u{1F4E6} **Dependencies**";
50
50
  const details = ` \u2192 ${dependencySummaries.join(", ")}`;
51
- return `${header}
51
+ return `${header2}
52
52
  ${details}`;
53
53
  }
54
- return firstCommit ? `- \u{1F4E6} Updated ${count} dependencies ${firstCommit}` : `- \u{1F4E6} Updated ${count} dependencies`;
54
+ const header = firstCommit ? `- \u{1F4E6} Updated ${count} dependencies ${firstCommit}` : `- \u{1F4E6} Updated ${count} dependencies`;
55
+ const detailBlock = [
56
+ " <details><summary>Details</summary>",
57
+ "",
58
+ ` ${dependencySummaries.join(", ")}`,
59
+ "",
60
+ " </details>"
61
+ ].join("\n");
62
+ return `${header}
63
+ ${detailBlock}`;
64
+ }
65
+ function parseConventionalHeadline(raw) {
66
+ const match = raw.match(
67
+ /^(\w+)(?:\(([^)]*)\))?(!?):\s(.+)$/
68
+ );
69
+ if (!match) {
70
+ return { breaking: false, description: raw };
71
+ }
72
+ return {
73
+ type: match[1],
74
+ scope: match[2] || void 0,
75
+ breaking: match[3] === "!",
76
+ description: match[4].trim()
77
+ };
78
+ }
79
+ function formatHeadline(raw) {
80
+ const parsed = parseConventionalHeadline(raw);
81
+ if (!parsed.type) {
82
+ return { text: raw, breaking: parsed.breaking };
83
+ }
84
+ const scopeTag = parsed.scope ? `${parsed.scope}: ` : "";
85
+ return {
86
+ text: `${scopeTag}${parsed.description}`,
87
+ breaking: parsed.breaking
88
+ };
55
89
  }
56
90
  function normalizeUserMentions(users) {
57
91
  const normalized = users.map((user) => user.trim()).filter(Boolean).map((user) => user.startsWith("@") ? user : `@${user}`);
@@ -69,6 +103,7 @@ function normalizeUserMentions(users) {
69
103
  function extractSummaryMeta(summary) {
70
104
  let prNumber;
71
105
  let commitRef;
106
+ let breaking = false;
72
107
  const users = [];
73
108
  const contentLines = summary.split(/\r?\n/).filter((line) => {
74
109
  const trimmed = line.trim();
@@ -93,13 +128,17 @@ function extractSummaryMeta(summary) {
93
128
  users.push(userMatch[1].replace(/^@/, ""));
94
129
  return false;
95
130
  }
131
+ if (/^BREAKING[\s-]CHANGE:/i.test(withoutListMarker)) {
132
+ breaking = true;
133
+ }
96
134
  return true;
97
- }).map((line) => line.trimRight());
135
+ }).map((line) => line.trimEnd());
98
136
  return {
99
137
  prNumber,
100
138
  commitRef,
101
139
  users,
102
- contentLines
140
+ contentLines,
141
+ breaking
103
142
  };
104
143
  }
105
144
  function parseSummary(summary) {
@@ -107,7 +146,8 @@ function parseSummary(summary) {
107
146
  prNumber,
108
147
  commitRef,
109
148
  users,
110
- contentLines
149
+ contentLines,
150
+ breaking: bodyBreaking
111
151
  } = extractSummaryMeta(summary);
112
152
  const nonEmptyIndex = contentLines.findIndex((line) => line.trim().length > 0);
113
153
  if (nonEmptyIndex === -1) {
@@ -116,7 +156,8 @@ function parseSummary(summary) {
116
156
  detailLines: [],
117
157
  prNumber,
118
158
  commitRef,
119
- users
159
+ users,
160
+ breaking: bodyBreaking
120
161
  };
121
162
  }
122
163
  const firstContentLine = contentLines[nonEmptyIndex].trim();
@@ -124,12 +165,15 @@ function parseSummary(summary) {
124
165
  const headline = startsWithList ? "" : firstContentLine;
125
166
  const restLines = startsWithList ? contentLines.slice(nonEmptyIndex) : contentLines.slice(nonEmptyIndex + 1);
126
167
  const detailLines = restLines;
168
+ const headlineParsed = headline ? parseConventionalHeadline(headline) : null;
169
+ const breaking = bodyBreaking || (_nullishCoalesce(_optionalChain([headlineParsed, 'optionalAccess', _ => _.breaking]), () => ( false)));
127
170
  return {
128
171
  headline,
129
172
  detailLines,
130
173
  prNumber,
131
174
  commitRef,
132
- users
175
+ users,
176
+ breaking
133
177
  };
134
178
  }
135
179
  async function resolveLinks(repo, parsed, changesetCommit) {
@@ -178,7 +222,7 @@ function indentMarkdownBlock(lines, spaces) {
178
222
  }).join("\n");
179
223
  }
180
224
  function formatDetailBlock(detailLines) {
181
- const trimmed = detailLines.join("\n").trim().split("\n").map((line) => line.trimRight());
225
+ const trimmed = detailLines.join("\n").trim().split("\n").map((line) => line.trimEnd());
182
226
  const hasFence = trimmed.some((line) => /^\s*```/.test(line));
183
227
  const isListLike = trimmed.some((line) => /^\s*(?:[-*+]\s+|\d+[.)]\s+)/.test(line));
184
228
  if (trimmed.length === 0) {
@@ -187,8 +231,11 @@ function formatDetailBlock(detailLines) {
187
231
  if (hasFence || isListLike) {
188
232
  return indentMarkdownBlock(trimmed, 2);
189
233
  }
190
- const paragraphs = trimmed.join("\n").split(/\n\s*\n/).map((chunk) => chunk.replace(/\s+/g, " ").trim()).filter(Boolean);
191
- return paragraphs.map((text) => ` - ${text}`).join("\n");
234
+ const paragraphs = trimmed.join("\n").split(/\n\s*\n/).filter((chunk) => chunk.trim().length > 0);
235
+ const lines = paragraphs.flatMap(
236
+ (chunk) => chunk.split("\n").map((line) => line.trim()).filter(Boolean)
237
+ );
238
+ return lines.map((text) => ` - ${text}`).join("\n");
192
239
  }
193
240
  var changelogFunctions = {
194
241
  async getDependencyReleaseLine(changesets, dependenciesUpdated, options) {
@@ -217,10 +264,13 @@ var changelogFunctions = {
217
264
  parsedSummary.users,
218
265
  links.user
219
266
  );
220
- const headlineText = parsedSummary.headline || "Miscellaneous improvements";
267
+ const { text: headlineText, breaking: headlineBreaking } = parsedSummary.headline ? formatHeadline(parsedSummary.headline) : { text: "Miscellaneous improvements", breaking: false };
268
+ const isBreaking = parsedSummary.breaking || headlineBreaking;
269
+ const breakingPrefix = isBreaking ? "\u26A0\uFE0F " : "";
270
+ const icon = isBreaking ? "\u{1F4A5}" : releaseTypeMap[resolvedType].icon;
221
271
  const mainLineParts = [
222
- `- ${releaseTypeMap[resolvedType].icon}`,
223
- `**${headlineText}**`
272
+ `- ${icon}`,
273
+ `${breakingPrefix}**${headlineText}**`
224
274
  ];
225
275
  if (links.pull) {
226
276
  mainLineParts.push(links.pull);
@@ -249,4 +299,6 @@ var { getDependencyReleaseLine, getReleaseLine } = changelogFunctions;
249
299
 
250
300
 
251
301
 
252
- exports.default = index_default; exports.getDependencyReleaseLine = getDependencyReleaseLine; exports.getReleaseLine = getReleaseLine;
302
+
303
+
304
+ exports.default = index_default; exports.formatHeadline = formatHeadline; exports.getDependencyReleaseLine = getDependencyReleaseLine; exports.getReleaseLine = getReleaseLine; exports.parseConventionalHeadline = parseConventionalHeadline;
package/dist/index.d.cts CHANGED
@@ -1,6 +1,17 @@
1
1
  import * as _changesets_types from '@changesets/types';
2
2
  import { ChangelogFunctions } from '@changesets/types';
3
3
 
4
+ interface ConventionalHeadline {
5
+ type?: string;
6
+ scope?: string;
7
+ breaking: boolean;
8
+ description: string;
9
+ }
10
+ declare function parseConventionalHeadline(raw: string): ConventionalHeadline;
11
+ declare function formatHeadline(raw: string): {
12
+ text: string;
13
+ breaking: boolean;
14
+ };
4
15
  declare const changelogFunctions: ChangelogFunctions;
5
16
 
6
17
  declare const getDependencyReleaseLine: _changesets_types.GetDependencyReleaseLine;
@@ -8,4 +19,4 @@ declare const getReleaseLine: _changesets_types.GetReleaseLine;
8
19
 
9
20
  // @ts-ignore
10
21
  export = changelogFunctions;
11
- export { getDependencyReleaseLine, getReleaseLine };
22
+ export { formatHeadline, getDependencyReleaseLine, getReleaseLine, parseConventionalHeadline };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,20 @@
1
1
  import * as _changesets_types from '@changesets/types';
2
2
  import { ChangelogFunctions } from '@changesets/types';
3
3
 
4
+ interface ConventionalHeadline {
5
+ type?: string;
6
+ scope?: string;
7
+ breaking: boolean;
8
+ description: string;
9
+ }
10
+ declare function parseConventionalHeadline(raw: string): ConventionalHeadline;
11
+ declare function formatHeadline(raw: string): {
12
+ text: string;
13
+ breaking: boolean;
14
+ };
4
15
  declare const changelogFunctions: ChangelogFunctions;
5
16
 
6
17
  declare const getDependencyReleaseLine: _changesets_types.GetDependencyReleaseLine;
7
18
  declare const getReleaseLine: _changesets_types.GetReleaseLine;
8
19
 
9
- export { changelogFunctions as default, getDependencyReleaseLine, getReleaseLine };
20
+ export { changelogFunctions as default, formatHeadline, getDependencyReleaseLine, getReleaseLine, parseConventionalHeadline };
package/dist/index.mjs CHANGED
@@ -34,7 +34,7 @@ async function collectDependencyReferences(changesets, repo) {
34
34
  return links.commit;
35
35
  })
36
36
  );
37
- return references.filter((link) => Boolean(link));
37
+ return [...new Set(references.filter((link) => Boolean(link)))];
38
38
  }
39
39
  function formatDependencyLine(references, dependenciesUpdated) {
40
40
  const count = dependenciesUpdated.length;
@@ -42,16 +42,50 @@ function formatDependencyLine(references, dependenciesUpdated) {
42
42
  if (count === 0) {
43
43
  return firstCommit ? `- \u{1F4E6} **Dependencies** ${firstCommit}` : "- \u{1F4E6} **Dependencies**";
44
44
  }
45
+ const dependencySummaries = dependenciesUpdated.map(
46
+ (dependency) => `\`${dependency.name}@${dependency.newVersion}\``
47
+ );
45
48
  if (count <= 3) {
46
- const dependencySummaries = dependenciesUpdated.map(
47
- (dependency) => `\`${dependency.name}@${dependency.newVersion}\``
48
- );
49
- const header = firstCommit ? `- \u{1F4E6} **Dependencies** ${firstCommit}` : "- \u{1F4E6} **Dependencies**";
49
+ const header2 = firstCommit ? `- \u{1F4E6} **Dependencies** ${firstCommit}` : "- \u{1F4E6} **Dependencies**";
50
50
  const details = ` \u2192 ${dependencySummaries.join(", ")}`;
51
- return `${header}
51
+ return `${header2}
52
52
  ${details}`;
53
53
  }
54
- return firstCommit ? `- \u{1F4E6} Updated ${count} dependencies ${firstCommit}` : `- \u{1F4E6} Updated ${count} dependencies`;
54
+ const header = firstCommit ? `- \u{1F4E6} Updated ${count} dependencies ${firstCommit}` : `- \u{1F4E6} Updated ${count} dependencies`;
55
+ const detailBlock = [
56
+ " <details><summary>Details</summary>",
57
+ "",
58
+ ` ${dependencySummaries.join(", ")}`,
59
+ "",
60
+ " </details>"
61
+ ].join("\n");
62
+ return `${header}
63
+ ${detailBlock}`;
64
+ }
65
+ function parseConventionalHeadline(raw) {
66
+ const match = raw.match(
67
+ /^(\w+)(?:\(([^)]*)\))?(!?):\s(.+)$/
68
+ );
69
+ if (!match) {
70
+ return { breaking: false, description: raw };
71
+ }
72
+ return {
73
+ type: match[1],
74
+ scope: match[2] || void 0,
75
+ breaking: match[3] === "!",
76
+ description: match[4].trim()
77
+ };
78
+ }
79
+ function formatHeadline(raw) {
80
+ const parsed = parseConventionalHeadline(raw);
81
+ if (!parsed.type) {
82
+ return { text: raw, breaking: parsed.breaking };
83
+ }
84
+ const scopeTag = parsed.scope ? `${parsed.scope}: ` : "";
85
+ return {
86
+ text: `${scopeTag}${parsed.description}`,
87
+ breaking: parsed.breaking
88
+ };
55
89
  }
56
90
  function normalizeUserMentions(users) {
57
91
  const normalized = users.map((user) => user.trim()).filter(Boolean).map((user) => user.startsWith("@") ? user : `@${user}`);
@@ -69,6 +103,7 @@ function normalizeUserMentions(users) {
69
103
  function extractSummaryMeta(summary) {
70
104
  let prNumber;
71
105
  let commitRef;
106
+ let breaking = false;
72
107
  const users = [];
73
108
  const contentLines = summary.split(/\r?\n/).filter((line) => {
74
109
  const trimmed = line.trim();
@@ -93,13 +128,17 @@ function extractSummaryMeta(summary) {
93
128
  users.push(userMatch[1].replace(/^@/, ""));
94
129
  return false;
95
130
  }
131
+ if (/^BREAKING[\s-]CHANGE:/i.test(withoutListMarker)) {
132
+ breaking = true;
133
+ }
96
134
  return true;
97
- }).map((line) => line.trimRight());
135
+ }).map((line) => line.trimEnd());
98
136
  return {
99
137
  prNumber,
100
138
  commitRef,
101
139
  users,
102
- contentLines
140
+ contentLines,
141
+ breaking
103
142
  };
104
143
  }
105
144
  function parseSummary(summary) {
@@ -107,7 +146,8 @@ function parseSummary(summary) {
107
146
  prNumber,
108
147
  commitRef,
109
148
  users,
110
- contentLines
149
+ contentLines,
150
+ breaking: bodyBreaking
111
151
  } = extractSummaryMeta(summary);
112
152
  const nonEmptyIndex = contentLines.findIndex((line) => line.trim().length > 0);
113
153
  if (nonEmptyIndex === -1) {
@@ -116,7 +156,8 @@ function parseSummary(summary) {
116
156
  detailLines: [],
117
157
  prNumber,
118
158
  commitRef,
119
- users
159
+ users,
160
+ breaking: bodyBreaking
120
161
  };
121
162
  }
122
163
  const firstContentLine = contentLines[nonEmptyIndex].trim();
@@ -124,12 +165,15 @@ function parseSummary(summary) {
124
165
  const headline = startsWithList ? "" : firstContentLine;
125
166
  const restLines = startsWithList ? contentLines.slice(nonEmptyIndex) : contentLines.slice(nonEmptyIndex + 1);
126
167
  const detailLines = restLines;
168
+ const headlineParsed = headline ? parseConventionalHeadline(headline) : null;
169
+ const breaking = bodyBreaking || (headlineParsed?.breaking ?? false);
127
170
  return {
128
171
  headline,
129
172
  detailLines,
130
173
  prNumber,
131
174
  commitRef,
132
- users
175
+ users,
176
+ breaking
133
177
  };
134
178
  }
135
179
  async function resolveLinks(repo, parsed, changesetCommit) {
@@ -178,7 +222,7 @@ function indentMarkdownBlock(lines, spaces) {
178
222
  }).join("\n");
179
223
  }
180
224
  function formatDetailBlock(detailLines) {
181
- const trimmed = detailLines.join("\n").trim().split("\n").map((line) => line.trimRight());
225
+ const trimmed = detailLines.join("\n").trim().split("\n").map((line) => line.trimEnd());
182
226
  const hasFence = trimmed.some((line) => /^\s*```/.test(line));
183
227
  const isListLike = trimmed.some((line) => /^\s*(?:[-*+]\s+|\d+[.)]\s+)/.test(line));
184
228
  if (trimmed.length === 0) {
@@ -187,8 +231,11 @@ function formatDetailBlock(detailLines) {
187
231
  if (hasFence || isListLike) {
188
232
  return indentMarkdownBlock(trimmed, 2);
189
233
  }
190
- const paragraphs = trimmed.join("\n").split(/\n\s*\n/).map((chunk) => chunk.replace(/\s+/g, " ").trim()).filter(Boolean);
191
- return paragraphs.map((text) => ` - ${text}`).join("\n");
234
+ const paragraphs = trimmed.join("\n").split(/\n\s*\n/).filter((chunk) => chunk.trim().length > 0);
235
+ const lines = paragraphs.flatMap(
236
+ (chunk) => chunk.split("\n").map((line) => line.trim()).filter(Boolean)
237
+ );
238
+ return lines.map((text) => ` - ${text}`).join("\n");
192
239
  }
193
240
  var changelogFunctions = {
194
241
  async getDependencyReleaseLine(changesets, dependenciesUpdated, options) {
@@ -217,10 +264,13 @@ var changelogFunctions = {
217
264
  parsedSummary.users,
218
265
  links.user
219
266
  );
220
- const headlineText = parsedSummary.headline || "Miscellaneous improvements";
267
+ const { text: headlineText, breaking: headlineBreaking } = parsedSummary.headline ? formatHeadline(parsedSummary.headline) : { text: "Miscellaneous improvements", breaking: false };
268
+ const isBreaking = parsedSummary.breaking || headlineBreaking;
269
+ const breakingPrefix = isBreaking ? "\u26A0\uFE0F " : "";
270
+ const icon = isBreaking ? "\u{1F4A5}" : releaseTypeMap[resolvedType].icon;
221
271
  const mainLineParts = [
222
- `- ${releaseTypeMap[resolvedType].icon}`,
223
- `**${headlineText}**`
272
+ `- ${icon}`,
273
+ `${breakingPrefix}**${headlineText}**`
224
274
  ];
225
275
  if (links.pull) {
226
276
  mainLineParts.push(links.pull);
@@ -247,6 +297,8 @@ var index_default = changelogFunctions;
247
297
  var { getDependencyReleaseLine, getReleaseLine } = changelogFunctions;
248
298
  export {
249
299
  index_default as default,
300
+ formatHeadline,
250
301
  getDependencyReleaseLine,
251
- getReleaseLine
302
+ getReleaseLine,
303
+ parseConventionalHeadline
252
304
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@icebreakers/changelog-github",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "description": "Changesets GitHub changelog formatter for Icebreaker's dev-configs",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -36,7 +36,7 @@
36
36
  "dependencies": {
37
37
  "@changesets/get-github-info": "^0.7.0",
38
38
  "@changesets/types": "^6.1.0",
39
- "dotenv": "^17.2.3"
39
+ "dotenv": "^17.2.4"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@changesets/parse": "^0.4.2"