-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommitlint.config.cjs
More file actions
91 lines (88 loc) · 2.35 KB
/
commitlint.config.cjs
File metadata and controls
91 lines (88 loc) · 2.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
const FORBIDDEN_VOCABULARY =
/\b(wip|fix stuff|misc|various|tmp|temp|quick fix|minor changes|small fix|tweaks|improvements|adjustments|stuff|things)\b/i;
const SUBJECT_PROCESS_LANGUAGE =
/\b(record|scope|apply changes|process|misc|tmp|temp|things|stuff)\b/i;
const GENERIC_TARGETS = new Set([
'change',
'changes',
'file',
'files',
'message',
'messages',
'scope',
'scopes',
'stuff',
'things',
'work',
]);
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'build',
'ci',
'chore',
'revert',
],
],
'type-case': [2, 'always', 'lower-case'],
'scope-case': [2, 'always', 'kebab-case'],
'scope-empty': [2, 'never'],
'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
'header-max-length': [2, 'always', 130],
'body-leading-blank': [2, 'always'],
'body-max-line-length': [2, 'always', 140],
'no-forbidden-vocabulary': [2, 'always'],
'subject-target-required': [2, 'always'],
'no-process-language': [2, 'always'],
},
plugins: [
{
rules: {
'no-forbidden-vocabulary': (parsed) => {
const match = `${parsed.subject || ''}\n${parsed.body || ''}`.match(
FORBIDDEN_VOCABULARY,
);
if (!match) return [true];
return [false, `commit message contains forbidden vocabulary: "${match[0]}"`];
},
'subject-target-required': (parsed) => {
const subject = String(parsed.subject || '').trim();
const [verb, ...targetWords] = subject
.toLowerCase()
.split(/\s+/)
.filter(Boolean);
if (!verb) return [false, 'subject must include a verb and target'];
if (targetWords.length < 2) {
return [false, 'subject must include a concrete target after the verb'];
}
const meaningfulWords = targetWords.filter(
(word) => !GENERIC_TARGETS.has(word),
);
return [
meaningfulWords.length > 0,
'subject target is too generic; name the concrete thing that changed',
];
},
'no-process-language': (parsed) => {
if (SUBJECT_PROCESS_LANGUAGE.test(parsed.subject || '')) {
return [false, 'subject must describe the change'];
}
return [true];
},
},
},
],
};