@varlet/release 1.0.0 → 1.0.2

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/cli.js CHANGED
@@ -3,7 +3,7 @@ import { changelog, commitLint, publish, release } from "./index.js";
3
3
  import { Command } from "commander";
4
4
 
5
5
  //#region package.json
6
- var version = "1.0.0";
6
+ var version = "1.0.2";
7
7
 
8
8
  //#endregion
9
9
  //#region src/cli.ts
package/dist/index.d.ts CHANGED
@@ -40,6 +40,7 @@ declare function changelog({
40
40
  }?: ChangelogCommandOptions): Promise<void>;
41
41
  //#endregion
42
42
  //#region src/commitLint.d.ts
43
+ declare const COMMIT_HEADER_RE: RegExp;
43
44
  declare const COMMIT_MESSAGE_RE: RegExp;
44
45
  declare function isVersionCommitMessage(message: string): boolean;
45
46
  declare function getCommitMessage(commitMessagePath: string): string;
@@ -51,4 +52,4 @@ interface CommitLintCommandOptions {
51
52
  }
52
53
  declare function commitLint(options: CommitLintCommandOptions): void;
53
54
  //#endregion
54
- export { COMMIT_MESSAGE_RE, ChangelogCommandOptions, CommitLintCommandOptions, PublishCommandOptions, ReleaseCommandOptions, changelog, commitLint, getAllPackageJsons, getCommitMessage, isSameVersion, isVersionCommitMessage, publish, release, updateVersion };
55
+ export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, ChangelogCommandOptions, CommitLintCommandOptions, PublishCommandOptions, ReleaseCommandOptions, changelog, commitLint, getAllPackageJsons, getCommitMessage, isSameVersion, isVersionCommitMessage, publish, release, updateVersion };
package/dist/index.js CHANGED
@@ -7,48 +7,194 @@ import semver from "semver";
7
7
  import { x } from "tinyexec";
8
8
  import conventionalChangelog from "conventional-changelog";
9
9
 
10
+ //#region src/commitLint.ts
11
+ const { readFileSync } = fse;
12
+ const COMMIT_HEADER_RE = /^(revert|fix|feat|docs|perf|test|types|style|build|chore|release|refactor|merge|wip)(?:\(([^)]+)\))?(!)?:\s(.+)$/;
13
+ const COMMIT_MESSAGE_RE = new RegExp(COMMIT_HEADER_RE.source.replace(/\$$/, "") + "(?:\\n[\\s\\S]+)?$");
14
+ const ERROR_MESSAGE = "Commit message invalid.";
15
+ const WARNING_MESSAGE = `\
16
+ The rules for commit messages are as follows
17
+
18
+ Example:
19
+
20
+ feat: add a new feature
21
+ feat(ui/button): add a new feature in the ui/button scope
22
+
23
+ fix: fix a bug
24
+ fix(ui/button): fix a bug in the ui/button scope
25
+
26
+ docs: fix an error in the documentation
27
+ docs(ui/button): fix a documentation error in the ui/button scope
28
+
29
+ Allowed types:
30
+ - fix
31
+ - feat
32
+ - docs
33
+ - perf
34
+ - test
35
+ - types
36
+ - style
37
+ - build
38
+ - chore
39
+ - release
40
+ - refactor
41
+ - revert
42
+ - merge
43
+ - wip
44
+
45
+ Commit message reference: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y
46
+ 参考阮一峰Commit message编写指南: https://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html`;
47
+ function isVersionCommitMessage(message) {
48
+ return Boolean(message.startsWith("v") && semver.valid(message.slice(1)));
49
+ }
50
+ function getCommitMessage(commitMessagePath) {
51
+ return readFileSync(commitMessagePath, "utf-8").trim();
52
+ }
53
+ function commitLint(options) {
54
+ const { commitMessagePath, commitMessageRe = COMMIT_MESSAGE_RE, errorMessage = ERROR_MESSAGE, warningMessage = WARNING_MESSAGE } = options;
55
+ if (!commitMessagePath) {
56
+ logger.error("commitMessagePath is required");
57
+ process.exit(1);
58
+ }
59
+ const commitMessage = getCommitMessage(commitMessagePath);
60
+ const isValidCommitMessage = new RegExp(commitMessageRe).test(commitMessage);
61
+ if (!isVersionCommitMessage(commitMessage) && !isValidCommitMessage) {
62
+ logger.error(errorMessage);
63
+ logger.warn(warningMessage);
64
+ process.exit(1);
65
+ }
66
+ }
67
+
68
+ //#endregion
10
69
  //#region src/changelog.ts
11
70
  const { createWriteStream } = fse;
12
- function changelog({ releaseCount = 0, file = "CHANGELOG.md", preset = "angular", writerOpts = { transform(commit, context) {
71
+ const COMMIT_TYPE_MAP = {
72
+ feat: "Features",
73
+ fix: "Bug Fixes",
74
+ perf: "Performance Improvements",
75
+ revert: "Reverts",
76
+ refactor: "Code Refactoring",
77
+ docs: "Documentation",
78
+ style: "Styles",
79
+ test: "Tests",
80
+ build: "Build System",
81
+ ci: "Continuous Integration"
82
+ };
83
+ const ALWAYS_SHOW_TYPES = new Set([
84
+ "feat",
85
+ "fix",
86
+ "perf",
87
+ "revert",
88
+ "refactor"
89
+ ]);
90
+ const BREAKING_CHANGE_RE = /BREAKING CHANGES?:\s*([\s\S]+)/;
91
+ const MAIN_TEMPLATE = `{{> header}}
92
+
93
+ {{> footer}}
94
+ {{#each commitGroups}}
95
+
96
+ {{#if title}}
97
+ ### {{title}}
98
+
99
+ {{/if}}
100
+ {{#each commits}}
101
+ {{> commit root=@root}}
102
+ {{/each}}
103
+
104
+ {{/each}}
105
+ `;
106
+ function linkify(text, context, issues) {
107
+ let result = text;
108
+ const repoUrl = context.repository ? `${context.host}/${context.owner}/${context.repository}` : context.repoUrl;
109
+ if (repoUrl) {
110
+ const issueBaseUrl = `${repoUrl}/issues/`;
111
+ result = result.replace(/#([0-9]+)/g, (_, issue) => {
112
+ issues.push(issue);
113
+ return `[#${issue}](${issueBaseUrl}${issue})`;
114
+ });
115
+ }
116
+ if (context.host) result = result.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => username.includes("/") ? `@${username}` : `[@${username}](${context.host}/${username})`);
117
+ return result;
118
+ }
119
+ function extractBreakingText(commit) {
120
+ const body = typeof commit.body === "string" ? commit.body : "";
121
+ const footer = typeof commit.footer === "string" ? commit.footer : "";
122
+ const match = BREAKING_CHANGE_RE.exec(`${footer}\n${body}`);
123
+ if (match?.[1]) return match[1].trim();
124
+ if (typeof commit.subject === "string" && commit.subject) return commit.subject;
125
+ if (typeof commit.header === "string" && commit.header) return commit.header;
126
+ return "";
127
+ }
128
+ function tryParseHeader(commit) {
129
+ if (typeof commit.header !== "string") return null;
130
+ const match = COMMIT_HEADER_RE.exec(commit.header.trim());
131
+ if (!match) return null;
132
+ return {
133
+ type: match[1],
134
+ scope: match[2] || void 0,
135
+ subject: match[4] || void 0,
136
+ isBreaking: Boolean(match[3])
137
+ };
138
+ }
139
+ function processBreakingChanges(commit, context, issues) {
13
140
  let discard = true;
14
- const issues = [];
15
141
  commit.notes.forEach((note) => {
16
142
  note.title = "BREAKING CHANGES";
17
143
  discard = false;
18
144
  });
19
- if (commit.type === "feat") commit.type = "Features";
20
- else if (commit.type === "fix") commit.type = "Bug Fixes";
21
- else if (commit.type === "perf") commit.type = "Performance Improvements";
22
- else if (commit.type === "revert" || commit.revert) commit.type = "Reverts";
23
- else if (commit.type === "refactor") commit.type = "Code Refactoring";
24
- else if (discard) return false;
25
- else if (commit.type === "docs") commit.type = "Documentation";
26
- else if (commit.type === "style") commit.type = "Styles";
27
- else if (commit.type === "test") commit.type = "Tests";
28
- else if (commit.type === "build") commit.type = "Build System";
29
- else if (commit.type === "ci") commit.type = "Continuous Integration";
30
- if (commit.scope === "*") commit.scope = "";
31
- if (typeof commit.hash === "string") commit.shortHash = commit.hash.substring(0, 7);
32
- if (typeof commit.subject === "string") {
33
- let url = context.repository ? `${context.host}/${context.owner}/${context.repository}` : context.repoUrl;
34
- if (url) {
35
- url = `${url}/issues/`;
36
- commit.subject = commit.subject.replace(/#([0-9]+)/g, (_, issue) => {
37
- issues.push(issue);
38
- return `[#${issue}](${url}${issue})`;
145
+ const hadBreakingNotes = commit.notes.length > 0;
146
+ const addBreakingNote = () => {
147
+ if (!hadBreakingNotes) {
148
+ const text = linkify(extractBreakingText(commit), context, issues);
149
+ commit.notes.push({
150
+ title: "BREAKING CHANGES",
151
+ text
39
152
  });
40
153
  }
41
- if (context.host) commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => {
42
- if (username.includes("/")) return `@${username}`;
43
- return `[@${username}](${context.host}/${username})`;
44
- });
154
+ discard = false;
155
+ };
156
+ const parsed = tryParseHeader(commit);
157
+ if (parsed) {
158
+ if (!commit.type) commit.type = parsed.type;
159
+ if (!commit.scope && parsed.scope) commit.scope = parsed.scope;
160
+ if (!commit.subject && parsed.subject) commit.subject = parsed.subject;
161
+ if (parsed.isBreaking) addBreakingNote();
45
162
  }
46
- commit.references = commit.references.filter((reference) => {
47
- if (issues.indexOf(reference.issue) === -1) return true;
48
- return false;
49
- });
50
- return commit;
51
- } } } = {}) {
163
+ if (typeof commit.type === "string" && commit.type.endsWith("!")) {
164
+ commit.type = commit.type.slice(0, -1);
165
+ addBreakingNote();
166
+ }
167
+ return discard;
168
+ }
169
+ function mapCommitType(commit, discard) {
170
+ if (commit.revert) {
171
+ commit.type = "Reverts";
172
+ return true;
173
+ }
174
+ const mapped = COMMIT_TYPE_MAP[commit.type];
175
+ if (mapped) {
176
+ if (ALWAYS_SHOW_TYPES.has(commit.type) || !discard) {
177
+ commit.type = mapped;
178
+ return true;
179
+ }
180
+ }
181
+ return !discard;
182
+ }
183
+ function createDefaultWriterOpts() {
184
+ return {
185
+ mainTemplate: MAIN_TEMPLATE,
186
+ transform(commit, context) {
187
+ const issues = [];
188
+ if (!mapCommitType(commit, processBreakingChanges(commit, context, issues))) return false;
189
+ if (commit.scope === "*") commit.scope = "";
190
+ if (typeof commit.hash === "string") commit.shortHash = commit.hash.substring(0, 7);
191
+ if (typeof commit.subject === "string") commit.subject = linkify(commit.subject, context, issues);
192
+ commit.references = commit.references.filter((ref) => !issues.includes(ref.issue));
193
+ return commit;
194
+ }
195
+ };
196
+ }
197
+ function changelog({ releaseCount = 0, file = "CHANGELOG.md", preset = "angular", writerOpts = createDefaultWriterOpts() } = {}) {
52
198
  const s = spinner();
53
199
  s.start("Generating changelog");
54
200
  return new Promise((resolve$1) => {
@@ -282,62 +428,4 @@ async function release(options) {
282
428
  }
283
429
 
284
430
  //#endregion
285
- //#region src/commitLint.ts
286
- const { readFileSync } = fse;
287
- const COMMIT_MESSAGE_RE = /^(revert|fix|feat|docs|perf|test|types|style|build|chore|release|refactor|merge|wip)(\(.+\))?!?: (.|\n)+/;
288
- const ERROR_MESSAGE = "Commit message invalid.";
289
- const WARNING_MESSAGE = `\
290
- The rules for commit messages are as follows
291
-
292
- Example:
293
-
294
- feat: add a new feature
295
- feat(ui/button): add a new feature in the ui/button scope
296
-
297
- fix: fix a bug
298
- fix(ui/button): fix a bug in the ui/button scope
299
-
300
- docs: fix an error in the documentation
301
- docs(ui/button): fix a documentation error in the ui/button scope
302
-
303
- Allowed types:
304
- - fix
305
- - feat
306
- - docs
307
- - perf
308
- - test
309
- - types
310
- - style
311
- - build
312
- - chore
313
- - release
314
- - refactor
315
- - revert
316
- - merge
317
- - wip
318
-
319
- Commit message reference: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y
320
- 参考阮一峰Commit message编写指南: https://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html`;
321
- function isVersionCommitMessage(message) {
322
- return Boolean(message.startsWith("v") && semver.valid(message.slice(1)));
323
- }
324
- function getCommitMessage(commitMessagePath) {
325
- return readFileSync(commitMessagePath, "utf-8").trim();
326
- }
327
- function commitLint(options) {
328
- const { commitMessagePath, commitMessageRe = COMMIT_MESSAGE_RE, errorMessage = ERROR_MESSAGE, warningMessage = WARNING_MESSAGE } = options;
329
- if (!commitMessagePath) {
330
- logger.error("commitMessagePath is required");
331
- process.exit(1);
332
- }
333
- const commitMessage = getCommitMessage(commitMessagePath);
334
- const isValidCommitMessage = new RegExp(commitMessageRe).test(commitMessage);
335
- if (!isVersionCommitMessage(commitMessage) && !isValidCommitMessage) {
336
- logger.error(errorMessage);
337
- logger.warn(warningMessage);
338
- process.exit(1);
339
- }
340
- }
341
-
342
- //#endregion
343
- export { COMMIT_MESSAGE_RE, changelog, commitLint, getAllPackageJsons, getCommitMessage, isSameVersion, isVersionCommitMessage, publish, release, updateVersion };
431
+ export { COMMIT_HEADER_RE, COMMIT_MESSAGE_RE, changelog, commitLint, getAllPackageJsons, getCommitMessage, isSameVersion, isVersionCommitMessage, publish, release, updateVersion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@varlet/release",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "publish all packages, generate changelogs and check commit messages",
5
5
  "keywords": [
6
6
  "changelog",
@@ -35,10 +35,11 @@
35
35
  },
36
36
  "lint-staged": {
37
37
  "*.{md}": "prettier --write",
38
- "*.{ts}": [
38
+ "*.{ts,js}": [
39
39
  "prettier --write",
40
40
  "eslint --fix"
41
- ]
41
+ ],
42
+ "package.json": "prettier --write"
42
43
  },
43
44
  "dependencies": {
44
45
  "@clack/prompts": "^1.0.0",