1
- " format cjs" ;
1
+ ' format cjs' ;
2
2
3
3
var wrap = require ( 'word-wrap' ) ;
4
4
var map = require ( 'lodash.map' ) ;
5
5
var longest = require ( 'longest' ) ;
6
- var rightPad = require ( 'right-pad ' ) ;
6
+ var chalk = require ( 'chalk ' ) ;
7
7
8
8
var filter = function ( array ) {
9
9
return array . filter ( function ( x ) {
10
10
return x ;
11
11
} ) ;
12
12
} ;
13
13
14
+ var headerLength = function ( answers ) {
15
+ return (
16
+ answers . type . length + 2 + ( answers . scope ? answers . scope . length + 2 : 0 )
17
+ ) ;
18
+ } ;
19
+
20
+ var maxSummaryLength = function ( options , answers ) {
21
+ return options . maxHeaderWidth - headerLength ( answers ) ;
22
+ } ;
23
+
24
+ var filterSubject = function ( subject ) {
25
+ subject = subject . trim ( ) ;
26
+ if ( subject . charAt ( 0 ) . toLowerCase ( ) !== subject . charAt ( 0 ) ) {
27
+ subject =
28
+ subject . charAt ( 0 ) . toLowerCase ( ) + subject . slice ( 1 , subject . length ) ;
29
+ }
30
+ while ( subject . endsWith ( '.' ) ) {
31
+ subject = subject . slice ( 0 , subject . length - 1 ) ;
32
+ }
33
+ return subject ;
34
+ } ;
35
+
14
36
// This can be any kind of SystemJS compatible module.
15
37
// We use Commonjs here, but ES6 or AMD would do just
16
38
// fine.
17
- module . exports = function ( options ) {
18
-
39
+ module . exports = function ( options ) {
19
40
var types = options . types ;
20
41
21
42
var length = longest ( Object . keys ( types ) ) . length + 1 ;
22
- var choices = map ( types , function ( type , key ) {
43
+ var choices = map ( types , function ( type , key ) {
23
44
return {
24
- name : rightPad ( key + ':' , length ) + ' ' + type . description ,
45
+ name : ( key + ':' ) . padEnd ( length ) + ' ' + type . description ,
25
46
value : key
26
47
} ;
27
48
} ) ;
@@ -39,8 +60,6 @@ module.exports = function (options) {
39
60
// By default, we'll de-indent your commit
40
61
// template and will keep empty lines.
41
62
prompter : function ( cz , commit ) {
42
- console . log ( '\nLine 1 will be cropped at 100 characters. All other lines will be wrapped after 100 characters.\n' ) ;
43
-
44
63
// Let's ask some questions of the user
45
64
// so that we can populate our commit
46
65
// template.
@@ -52,60 +71,150 @@ module.exports = function (options) {
52
71
{
53
72
type : 'list' ,
54
73
name : 'type' ,
55
- message : 'Select the type of change that you\'re committing:' ,
56
- choices : choices
57
- } , {
74
+ message : "Select the type of change that you're committing:" ,
75
+ choices : choices ,
76
+ default : options . defaultType
77
+ } ,
78
+ {
58
79
type : 'input' ,
59
80
name : 'scope' ,
60
- message : 'Denote the scope of this change ($location, $browser, $compile, etc.):\n'
61
- } , {
81
+ message :
82
+ 'What is the scope of this change (e.g. component or file name): (press enter to skip)' ,
83
+ default : options . defaultScope ,
84
+ filter : function ( value ) {
85
+ return options . disableScopeLowerCase
86
+ ? value . trim ( )
87
+ : value . trim ( ) . toLowerCase ( ) ;
88
+ }
89
+ } ,
90
+ {
62
91
type : 'input' ,
63
92
name : 'subject' ,
64
- message : 'Write a short, imperative tense description of the change:\n'
65
- } , {
93
+ message : function ( answers ) {
94
+ return (
95
+ 'Write a short, imperative tense description of the change (max ' +
96
+ maxSummaryLength ( options , answers ) +
97
+ ' chars):\n'
98
+ ) ;
99
+ } ,
100
+ default : options . defaultSubject ,
101
+ validate : function ( subject , answers ) {
102
+ var filteredSubject = filterSubject ( subject ) ;
103
+ return filteredSubject . length == 0
104
+ ? 'subject is required'
105
+ : filteredSubject . length <= maxSummaryLength ( options , answers )
106
+ ? true
107
+ : 'Subject length must be less than or equal to ' +
108
+ maxSummaryLength ( options , answers ) +
109
+ ' characters. Current length is ' +
110
+ filteredSubject . length +
111
+ ' characters.' ;
112
+ } ,
113
+ transformer : function ( subject , answers ) {
114
+ var filteredSubject = filterSubject ( subject ) ;
115
+ var color =
116
+ filteredSubject . length <= maxSummaryLength ( options , answers )
117
+ ? chalk . green
118
+ : chalk . red ;
119
+ return color ( '(' + filteredSubject . length + ') ' + subject ) ;
120
+ } ,
121
+ filter : function ( subject ) {
122
+ return filterSubject ( subject ) ;
123
+ }
124
+ } ,
125
+ {
66
126
type : 'input' ,
67
127
name : 'body' ,
68
- message : 'Provide a longer description of the change:\n'
69
- } , {
128
+ message :
129
+ 'Provide a longer description of the change: (press enter to skip)\n' ,
130
+ default : options . defaultBody
131
+ } ,
132
+ {
133
+ type : 'confirm' ,
134
+ name : 'isBreaking' ,
135
+ message : 'Are there any breaking changes?' ,
136
+ default : false
137
+ } ,
138
+ {
139
+ type : 'input' ,
140
+ name : 'breakingBody' ,
141
+ default : '-' ,
142
+ message :
143
+ 'A BREAKING CHANGE commit requires a body. Please enter a longer description of the commit itself:\n' ,
144
+ when : function ( answers ) {
145
+ return answers . isBreaking && ! answers . body ;
146
+ } ,
147
+ validate : function ( breakingBody , answers ) {
148
+ return (
149
+ breakingBody . trim ( ) . length > 0 ||
150
+ 'Body is required for BREAKING CHANGE'
151
+ ) ;
152
+ }
153
+ } ,
154
+ {
70
155
type : 'input' ,
71
156
name : 'breaking' ,
72
- message : 'List any breaking changes:\n'
73
- } , {
157
+ message : 'Describe the breaking changes:\n' ,
158
+ when : function ( answers ) {
159
+ return answers . isBreaking ;
160
+ }
161
+ } ,
162
+
163
+ {
164
+ type : 'confirm' ,
165
+ name : 'isIssueAffected' ,
166
+ message : 'Does this change affect any open issues?' ,
167
+ default : options . defaultIssues ? true : false
168
+ } ,
169
+ {
170
+ type : 'input' ,
171
+ name : 'issuesBody' ,
172
+ default : '-' ,
173
+ message :
174
+ 'If issues are closed, the commit requires a body. Please enter a longer description of the commit itself:\n' ,
175
+ when : function ( answers ) {
176
+ return (
177
+ answers . isIssueAffected && ! answers . body && ! answers . breakingBody
178
+ ) ;
179
+ }
180
+ } ,
181
+ {
74
182
type : 'input' ,
75
183
name : 'issues' ,
76
- message : 'List any issues closed by this change:\n'
184
+ message : 'Add issue references (e.g. "fix #123", "re #123".):\n' ,
185
+ when : function ( answers ) {
186
+ return answers . isIssueAffected ;
187
+ } ,
188
+ default : options . defaultIssues ? options . defaultIssues : undefined
77
189
}
78
190
] ) . then ( function ( answers ) {
79
-
80
- var maxLineWidth = 100 ;
81
-
82
191
var wrapOptions = {
83
192
trim : true ,
193
+ cut : false ,
84
194
newline : '\n' ,
85
- indent :'' ,
86
- width : maxLineWidth
195
+ indent : '' ,
196
+ width : options . maxLineWidth
87
197
} ;
88
198
89
199
// parentheses are only needed when a scope is present
90
- var scope = answers . scope . trim ( ) ;
91
- scope = scope ? '(' + answers . scope . trim ( ) + ')' : '' ;
200
+ var scope = answers . scope ? '(' + answers . scope + ')' : '' ;
92
201
93
- // Hard limit this line
94
- var head = ( answers . type + scope + ': ' + answers . subject . trim ( ) ) . slice ( 0 , maxLineWidth ) ;
202
+ // Hard limit this line in the validate
203
+ var head = answers . type + scope + ': ' + answers . subject ;
95
204
96
- // Wrap these lines at 100 characters
97
- var body = wrap ( answers . body , wrapOptions ) ;
205
+ // Wrap these lines at options.maxLineWidth characters
206
+ var body = answers . body ? wrap ( answers . body , wrapOptions ) : false ;
98
207
99
208
// Apply breaking change prefix, removing it if already present
100
- var breaking = answers . breaking . trim ( ) ;
101
- breaking = breaking ? 'BREAKING CHANGE: ' + breaking . replace ( / ^ B R E A K I N G C H A N G E : / , '' ) : '' ;
102
- breaking = wrap ( breaking , wrapOptions ) ;
103
-
104
- var issues = wrap ( answers . issues , wrapOptions ) ;
209
+ var breaking = answers . breaking ? answers . breaking . trim ( ) : '' ;
210
+ breaking = breaking
211
+ ? 'BREAKING CHANGE: ' + breaking . replace ( / ^ B R E A K I N G C H A N G E : / , '' )
212
+ : '' ;
213
+ breaking = breaking ? wrap ( breaking , wrapOptions ) : false ;
105
214
106
- var footer = filter ( [ breaking , issues ] ) . join ( '\n\n' ) ;
215
+ var issues = answers . issues ? wrap ( answers . issues , wrapOptions ) : false ;
107
216
108
- commit ( head + '\n\n' + body + '\n\n' + footer ) ;
217
+ commit ( filter ( [ head , body , breaking , issues ] ) . join ( '\n\n' ) ) ;
109
218
} ) ;
110
219
}
111
220
} ;
0 commit comments