Skip to content

Commit 73f688c

Browse files
committed
feat(cz-git): support single item intelligent filter ouput of scope and issueprefix
if scope list or issueprefix list only one item And set allowCustom and allowEmpty is false will filter question and finally will output the item. link #12
1 parent 65a2086 commit 73f688c

9 files changed

Lines changed: 140 additions & 102 deletions

File tree

packages/cz-git/__tests__/buildCommit.test.ts renamed to packages/cz-git/__tests__/generateMessage.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { buildCommit } from "../lib/shared";
1+
import { generateMessage } from "../lib/generator";
22

33
/**
4-
* @description: buildCommit Test
4+
* @description: generateMessage Test
55
*/
6-
describe("buildCommit()", () => {
6+
describe("generateMessage()", () => {
77
const answers = {
88
type: "feat",
99
scope: "app",
@@ -12,23 +12,23 @@ describe("buildCommit()", () => {
1212

1313
test("subject with default subject should be standard separator", () => {
1414
const options = {};
15-
expect(buildCommit(answers, options)).toEqual("feat(app): add a new feature");
15+
expect(generateMessage(answers, options)).toEqual("feat(app): add a new feature");
1616
});
1717

1818
test("subject with emoji options should be standard separator", () => {
1919
const options = {
2020
types: [{ value: "feat", name: "feat: A new feature", emoji: ":sparkles:" }],
2121
useEmoji: true
2222
};
23-
expect(buildCommit(answers, options)).toEqual("feat(app): :sparkles: add a new feature");
23+
expect(generateMessage(answers, options)).toEqual("feat(app): :sparkles: add a new feature");
2424
});
2525

2626
test("subject with emoji options and lost type should be standard separator", () => {
2727
const options = {
2828
types: [{ value: "feat", name: "feat: A new feature" }],
2929
useEmoji: true
3030
};
31-
expect(buildCommit(answers, options)).toEqual("feat(app): add a new feature");
31+
expect(generateMessage(answers, options)).toEqual("feat(app): add a new feature");
3232
});
3333

3434
test("body breaking line should be with breaklineNumber", () => {
@@ -42,7 +42,7 @@ describe("buildCommit()", () => {
4242
subject: "add a new feature",
4343
body: "test breaklineNumber test breaklineNumber"
4444
};
45-
expect(buildCommit(answers, options)).toEqual(
45+
expect(generateMessage(answers, options)).toEqual(
4646
`feat(app): add a new feature
4747
4848
test breaklineNumber
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/**
2+
* @description: generate commit message(generateMessage)
3+
* @author: @Zhengqbbb (zhengqbbb@gmail.com)
4+
* @license: MIT
5+
*/
6+
7+
import {
8+
Answers,
9+
CommitizenGitOptions,
10+
getCurrentScopes,
11+
handleStandardScopes,
12+
isSingleItem
13+
} from "../shared";
14+
import { wrap } from "../shared";
15+
16+
const getSingleParams = (answers: Answers, options: CommitizenGitOptions) => {
17+
const singleIndex = 0;
18+
const mapping = {
19+
singleScope: "",
20+
singeIssuePrefix: ""
21+
};
22+
const scopeList = handleStandardScopes(
23+
getCurrentScopes(options.scopes, options.scopeOverrides, answers.type)
24+
);
25+
if (isSingleItem(options.allowCustomScopes, options.allowCustomIssuePrefixs, scopeList)) {
26+
mapping.singleScope = scopeList[singleIndex].value;
27+
}
28+
// eslint-disable-next-line prettier/prettier
29+
if (isSingleItem(options.allowCustomIssuePrefixs, options.allowEmptyIssuePrefixs, options.issuePrefixs)) {
30+
mapping.singeIssuePrefix = options.issuePrefixs?.[singleIndex].value || "";
31+
}
32+
return mapping;
33+
};
34+
35+
const addType = (type: string, colorize?: boolean) =>
36+
colorize ? `\u001B[32m${type}\u001B[0m` : type;
37+
38+
const addScope = (scope?: string, colorize?: boolean) => {
39+
const separator = ":";
40+
if (!scope) return separator;
41+
scope = colorize ? `\u001B[33m${scope}\u001B[0m` : scope;
42+
return `(${scope.trim()})${separator}`;
43+
};
44+
45+
const addEmoji = (type: string, options: CommitizenGitOptions): string => {
46+
if (options.useEmoji && type !== "") {
47+
const itemSource = options.types?.concat(options.typesAppend || []) || [];
48+
const item = itemSource.find((i) => i.value === type);
49+
return item?.emoji ? ` ${item.emoji} ` : " ";
50+
} else {
51+
return " ";
52+
}
53+
};
54+
55+
const addSubject = (subject?: string, colorize?: boolean) => {
56+
if (!subject) return "";
57+
subject = colorize ? `\u001B[36m${subject}\u001B[0m` : subject;
58+
return subject.trim();
59+
};
60+
61+
const addBreaklinesIfNeeded = (value: string, breaklineChar = "|") =>
62+
value.split(breaklineChar).join("\n").valueOf();
63+
64+
const addFooter = (footer: string, footerPrefix = "", colorize?: boolean) => {
65+
if (footerPrefix === "") {
66+
return colorize ? `\n\n\u001B[32m${footer}\u001B[0m` : `\n\n${footer}`;
67+
}
68+
return colorize
69+
? `\n\n\u001B[32m${footerPrefix} ${footer}\u001B[0m`
70+
: `\n\n${footerPrefix} ${footer}`;
71+
};
72+
73+
export const generateMessage = (
74+
answers: Answers,
75+
options: CommitizenGitOptions,
76+
colorize = false
77+
) => {
78+
const wrapOptions = {
79+
trim: true,
80+
newLine: "\n",
81+
indent: "",
82+
width: options.breaklineNumber
83+
};
84+
const { singleScope, singeIssuePrefix } = getSingleParams(answers, options);
85+
const head =
86+
addType(answers.type ?? "", colorize) +
87+
addScope(singleScope || answers.scope, colorize) +
88+
addEmoji(answers.type ?? "", options) +
89+
addSubject(answers.subject, colorize);
90+
const body = wrap(answers.body ?? "", wrapOptions);
91+
const breaking = wrap(answers.breaking ?? "", wrapOptions);
92+
const footer = wrap(answers.footer ?? "", wrapOptions);
93+
94+
let result = head;
95+
if (body) {
96+
result += `\n\n${addBreaklinesIfNeeded(body, options.breaklineChar)}`;
97+
}
98+
if (breaking) {
99+
result += `\n\nBREAKING CHANGE :\n${addBreaklinesIfNeeded(breaking, options.breaklineChar)}`;
100+
}
101+
if (footer) {
102+
result += addFooter(footer, answers.footerPrefix || singeIssuePrefix, colorize);
103+
}
104+
return result;
105+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from "./build";
12
export * from "./option";
23
export * from "./question";

‎packages/cz-git/src/generator/option.ts‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@
44
* @license: MIT
55
*/
66

7-
/**
8-
* @description: generate commitizen config option(generateOptions) | generate commitizen questions(generateQuestions)
9-
* @author: @Zhengqbbb (zhengqbbb@gmail.com)
10-
* @license: MIT
11-
*/
12-
137
import { commitizenConfigLoader } from "@cz-git/loader";
148
import type { Config, CommitizenGitOptions, UserConfig } from "../shared";
159
import {

‎packages/cz-git/src/generator/question.ts‎

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import {
1010
getMaxSubjectLength,
1111
handleStandardScopes,
1212
handleCustomTemplate,
13-
buildCommit,
1413
log,
1514
isSingleItem,
1615
getCurrentScopes
1716
} from "../shared";
17+
import { generateMessage } from "./build";
1818

1919
export const generateQuestions = (options: CommitizenGitOptions, cz: any) => {
2020
if (!Array.isArray(options.types) || options.types.length === 0) {
@@ -53,7 +53,7 @@ export const generateQuestions = (options: CommitizenGitOptions, cz: any) => {
5353
);
5454
return scopes?.filter((item) => (input ? item.name?.includes(input) : true)) || true;
5555
},
56-
when(answer: Answers) {
56+
when: (answer: Answers) => {
5757
return !isSingleItem(
5858
options.allowCustomScopes,
5959
options.allowEmptyScopes,
@@ -68,19 +68,19 @@ export const generateQuestions = (options: CommitizenGitOptions, cz: any) => {
6868
name: "scope",
6969
message: options.messages?.customScope,
7070
default: options.defaultScope || undefined,
71-
validate(input: string) {
71+
validate: (input: string) => {
7272
if (options.allowEmptyScopes) return true;
7373
return input.length ? true : "\u001B[1;31m[ERROR] scope is required\u001B[0m";
7474
},
75-
when(answers: Answers) {
75+
when: (answers: Answers) => {
7676
return answers.scope === "___CUSTOM___";
7777
}
7878
},
7979
{
8080
type: "input",
8181
name: "subject",
8282
message: options.messages?.subject,
83-
validate(subject: string, answers: Answers) {
83+
validate: (subject: string, answers: Answers) => {
8484
const processedSubject = getProcessSubject(subject);
8585
if (processedSubject.length === 0)
8686
return "\u001B[1;31m[ERROR] subject is required\u001B[0m";
@@ -120,7 +120,7 @@ export const generateQuestions = (options: CommitizenGitOptions, cz: any) => {
120120

121121
return `${tooltipColor}[${tooltip}]\u001B[0m\n ${subjectColor}${subject}\u001B[0m`;
122122
},
123-
filter(subject: string) {
123+
filter: (subject: string) => {
124124
const upperCaseSubject = options.upperCaseSubject || false;
125125

126126
return (
@@ -141,7 +141,7 @@ export const generateQuestions = (options: CommitizenGitOptions, cz: any) => {
141141
name: "breaking",
142142
message: options.messages?.breaking,
143143
default: options.defaultBody || undefined,
144-
when(answers: Answers) {
144+
when: (answers: Answers) => {
145145
if (
146146
options.allowBreakingChanges &&
147147
answers.type &&
@@ -168,14 +168,20 @@ export const generateQuestions = (options: CommitizenGitOptions, cz: any) => {
168168
options.allowEmptyIssuePrefixs
169169
);
170170
return issues?.filter((item) => (input ? item.name?.includes(input) : true)) || true;
171-
}
171+
},
172+
when: () =>
173+
!isSingleItem(
174+
options.allowCustomIssuePrefixs,
175+
options.allowEmptyIssuePrefixs,
176+
options.issuePrefixs
177+
)
172178
},
173179
{
174180
type: "input",
175181
name: "footerPrefix",
176182
message: options.messages?.customFooterPrefixs,
177183
default: options.defaultIssues || undefined,
178-
when(answers: Answers) {
184+
when: (answers: Answers) => {
179185
return answers.footerPrefix === "___CUSTOM___";
180186
}
181187
},
@@ -202,7 +208,7 @@ export const generateQuestions = (options: CommitizenGitOptions, cz: any) => {
202208
? "\u001B[1;90m###--------------------------------------------------------###\u001B[0m"
203209
: "###--------------------------------------------------------###";
204210
console.info(
205-
`\n${SEP}\n${buildCommit(answers, options, options.confirmColorize)}\n${SEP}\n`
211+
`\n${SEP}\n${generateMessage(answers, options, options.confirmColorize)}\n${SEP}\n`
206212
);
207213
return options.messages?.confirmCommit;
208214
}

‎packages/cz-git/src/index.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
// @ts-ignore
1010
import autocompletePrompt from "inquirer-autocomplete-prompt";
1111
import { commitilintConfigLoader } from "@cz-git/loader";
12-
import { generateOptions, generateQuestions } from "./generator";
13-
import { buildCommit, editCommit, log } from "./shared";
12+
import { generateOptions, generateQuestions, generateMessage } from "./generator";
13+
import { editCommit, log } from "./shared";
1414
import type { CommitizenType, QualifiedConfig, UserConfig } from "./shared/types";
1515

1616
export * from "./shared/types";
@@ -27,7 +27,7 @@ export const prompter = (cz: CommitizenType, commit: (message: string) => void)
2727
break;
2828

2929
case "yes":
30-
commit(buildCommit(answers, options));
30+
commit(generateMessage(answers, options));
3131
break;
3232

3333
default:

‎packages/cz-git/src/shared/utils/editor.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import cnst from "constants";
55
import rimraf from "rimraf";
66
import { spawn } from "child_process";
77
import { Answers, CommitizenGitOptions } from "../types";
8-
import { buildCommit, log } from "./util";
8+
import { log } from "./util";
9+
import { generateMessage } from "../../generator";
910

1011
/**
1112
* @description: fork by "temp/open" v0.9.4
@@ -201,7 +202,7 @@ export const editCommit = (
201202
) => {
202203
tempOpen(undefined, (err, info) => {
203204
if (!err) {
204-
fs.writeSync(info.fd, buildCommit(answers, options));
205+
fs.writeSync(info.fd, generateMessage(answers, options));
205206
fs.close(info.fd, () => {
206207
editor(info.path, (code: number) => {
207208
if (code === 0) {
@@ -212,7 +213,7 @@ export const editCommit = (
212213
} else {
213214
log(
214215
"warm",
215-
`Editor exit non zero. Commit message was:\n${buildCommit(answers, options)}`
216+
`Editor exit non zero. Commit message was:\n${generateMessage(answers, options)}`
216217
);
217218
}
218219
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from "./editor";
22
export * from "./util";
33
export * from "./rule";
4+
export * from "./wrap";

0 commit comments

Comments
 (0)