@tony.ganchev/eslint-plugin-header 3.1.6 → 3.1.8
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/LICENSE.md +15 -4
- package/README.md +261 -64
- package/lib/rules/header.js +29 -9
- package/package.json +1 -1
package/LICENSE.md
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
Copyright (c) 2015-present Stuart Knightley and contributors
|
|
1
|
+
Copyright (c) 2015-present Stuart Knightley, Tony Ganchev and contributors
|
|
2
2
|
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
+
this software and associated documentation files (the “Software”), to deal in
|
|
5
|
+
the Software without restriction, including without limitation the rights to
|
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
+
subject to the following conditions:
|
|
4
9
|
|
|
5
|
-
The above copyright notice and this permission notice shall be included in all
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
6
12
|
|
|
7
|
-
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
13
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,19 +1,57 @@
|
|
|
1
|
-
This is a fork of https://github.com/Stuk/eslint-plugin-header
|
|
1
|
+
This is a fork of https://github.com/Stuk/eslint-plugin-header.
|
|
2
|
+
|
|
3
|
+
It addresses the following issus:
|
|
4
|
+
|
|
5
|
+
- Adds bugfixes where the original project has not been updated in the last
|
|
6
|
+
three years.
|
|
7
|
+
- Adds support for ESLint 9 with a fully-validated configuration schema.
|
|
8
|
+
- Addresses a number of bugs on Windows and adds significant amount of tests to
|
|
9
|
+
verify there are no future regressions.
|
|
10
|
+
- Fixes issues with she-bangs and empty lines before the header. See PR history
|
|
11
|
+
for more details.
|
|
12
|
+
- Provides the foundation to evolve the plugin to add more capabilities moving
|
|
13
|
+
forward. This would come at the expense of plugin compatibility and the
|
|
14
|
+
portability of fixes to the upstream repository.
|
|
2
15
|
|
|
3
16
|
eslint-plugin-header
|
|
4
17
|
====================
|
|
5
18
|
|
|
6
19
|
ESLint plugin to ensure that files begin with given comment.
|
|
7
20
|
|
|
8
|
-
Often you will want to have a copyright notice at the top of every file. This
|
|
21
|
+
Often you will want to have a copyright notice at the top of every file. This
|
|
22
|
+
ESLint plugin checks that the first comment in every file has the contents
|
|
23
|
+
defined in the rule settings.
|
|
9
24
|
|
|
10
25
|
## Usage
|
|
11
26
|
|
|
12
|
-
This rule takes 1
|
|
27
|
+
This rule takes between 1 and 4 arguments after the rule validation severity.
|
|
28
|
+
|
|
29
|
+
The configuration can take any of the following forms:
|
|
30
|
+
|
|
31
|
+
* File-based Configuration
|
|
32
|
+
* `[<severity>, "<file>"]` - read the header template from a file.
|
|
33
|
+
* `[<severity>, "<file>", {<settings>}]` - read the header template from a
|
|
34
|
+
file with additional settings.
|
|
35
|
+
* Inline Configuration
|
|
36
|
+
* `"<severity>", "<comment-type>", <header-contents>` - define the header
|
|
37
|
+
contents inline.
|
|
38
|
+
* `[<severity>, "<comment-type>", <header-contents>, {<settings>}]` - define
|
|
39
|
+
the header contents inline and pass additional settings.
|
|
40
|
+
* `[<severity>, "<comment-type>", <header-contents>, <n-empty-lines>]` -
|
|
41
|
+
define the header contents inline and an expected number of empty lines
|
|
42
|
+
after the header.
|
|
43
|
+
* `[<severity>, "<comment-type>", <header-contents>, <n-empty-lines>, {<settings>}]` -
|
|
44
|
+
define the header contents inline and an expected number of empty lines
|
|
45
|
+
after the header and pass additional settings.
|
|
13
46
|
|
|
14
|
-
###
|
|
47
|
+
### File-based Configuration
|
|
15
48
|
|
|
16
|
-
In
|
|
49
|
+
In this configuration mode, the first argument is a string pointing to a JS
|
|
50
|
+
file containing the header contents. The rule would expect an exact match to be
|
|
51
|
+
found in the source code.
|
|
52
|
+
|
|
53
|
+
The second argument can be a settings object that will be covered later in this
|
|
54
|
+
document.
|
|
17
55
|
|
|
18
56
|
```json
|
|
19
57
|
{
|
|
@@ -33,128 +71,287 @@ config/header.js:
|
|
|
33
71
|
// My company
|
|
34
72
|
```
|
|
35
73
|
|
|
36
|
-
Due to limitations in
|
|
74
|
+
Due to limitations in ESLint plugins, the file is read relative to the working
|
|
75
|
+
directory that ESLint is executed in. If you run ESLint from elsewhere in your
|
|
76
|
+
tree then the header file will not be found.
|
|
77
|
+
|
|
78
|
+
### Inline Configuration
|
|
37
79
|
|
|
38
|
-
|
|
80
|
+
The inline configuration expects at least two arguments to be given:
|
|
81
|
+
- _comment-type_ which is either `"block"` or `"line"` to indicate what style
|
|
82
|
+
of comment should be used.
|
|
83
|
+
- _header-contents_ which defines the lines of the header. It can be either a
|
|
84
|
+
single multiline string / regular expression with the full contents of the
|
|
85
|
+
header comment or an array with comment lines or regular expressions matching
|
|
86
|
+
each line.
|
|
39
87
|
|
|
40
|
-
|
|
88
|
+
#### Header Contents Configuration
|
|
89
|
+
|
|
90
|
+
Suppose we want our header to look like this:
|
|
91
|
+
```js
|
|
92
|
+
/*
|
|
93
|
+
* Copyright (c) 2015
|
|
94
|
+
* My Company
|
|
95
|
+
*/
|
|
96
|
+
...
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
All of the following configurations will match the header:
|
|
100
|
+
* **Single string**:
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
...
|
|
104
|
+
"rules": {
|
|
105
|
+
"header/header": [
|
|
106
|
+
2,
|
|
107
|
+
"block",
|
|
108
|
+
"\n * Copyright (c) 2015\n * My Company\n "
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
Note that the above would work for both Windows and POSIX systems even
|
|
114
|
+
though the EOL in the header content was specified as `\n`.
|
|
115
|
+
|
|
116
|
+
Also, notice how we have an empty space before each line. This is because
|
|
117
|
+
the plugin only strips the leading `//` characters from a line comment/
|
|
118
|
+
Similar for a block comment, only the opening `/*` and closing `*/` will be
|
|
119
|
+
preserved.
|
|
120
|
+
|
|
121
|
+
* **Single regular expression**:
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
...
|
|
125
|
+
"rules": {
|
|
126
|
+
"header/header": [
|
|
127
|
+
2,
|
|
128
|
+
"block",
|
|
129
|
+
{ "pattern": "\\n \\* Copyright \\(c\\) 2015\\n \\* My Company\\n " }
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Notice the double escaping of the braces. Since these pattern strings into
|
|
136
|
+
`RegExp` objects, the backslashes need to be present in the string instead
|
|
137
|
+
of disappear as escape characters.
|
|
138
|
+
|
|
139
|
+
For the comparable example using line comments we cannot use a single
|
|
140
|
+
expression as the second argument after the severity instead of a string or
|
|
141
|
+
an array. This is because the pattern will be matched against the first
|
|
142
|
+
single-line line comment and validation would fail. In general, using the
|
|
143
|
+
array form is preferable as it is easier to follow.
|
|
144
|
+
|
|
145
|
+
* **Array of strings**:
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
...
|
|
149
|
+
"rules": {
|
|
150
|
+
"header/header": [
|
|
151
|
+
2,
|
|
152
|
+
"block",
|
|
153
|
+
[
|
|
154
|
+
"",
|
|
155
|
+
" * Copyright (c) 2015",
|
|
156
|
+
" * My Company",
|
|
157
|
+
" "
|
|
158
|
+
]
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
* **Array of strings and/or patterns**:
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
...
|
|
167
|
+
"rules": {
|
|
168
|
+
"header/header": [
|
|
169
|
+
2,
|
|
170
|
+
"block",
|
|
171
|
+
[
|
|
172
|
+
"",
|
|
173
|
+
{ "pattern": " \\* Copyright \\(c\\) 2015" },
|
|
174
|
+
" * My Company",
|
|
175
|
+
" "
|
|
176
|
+
]
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Regular expressions allow for a number of improvements in the maintainability
|
|
183
|
+
of the headers. Given the example above, what is clear is that new sources may
|
|
184
|
+
have been created later than 2015 and a comment with a different year should be
|
|
185
|
+
perfectly valid such as:
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
/*
|
|
189
|
+
* Copyright 2020
|
|
190
|
+
* My company
|
|
191
|
+
*/
|
|
192
|
+
...
|
|
193
|
+
```
|
|
194
|
+
Moreover, suppose legal expects that the year of first and last change be added
|
|
195
|
+
except if all changes happen in the same year, we also need to support:
|
|
196
|
+
```js
|
|
197
|
+
/*
|
|
198
|
+
* Copyright 2017-2022
|
|
199
|
+
* My company
|
|
200
|
+
*/
|
|
201
|
+
...
|
|
202
|
+
```
|
|
203
|
+
We can use a regular expression to support all of these cases for your header:
|
|
41
204
|
|
|
42
205
|
```json
|
|
43
206
|
{
|
|
44
|
-
|
|
45
|
-
"header"
|
|
46
|
-
],
|
|
207
|
+
...
|
|
47
208
|
"rules": {
|
|
48
|
-
"header/header": [
|
|
209
|
+
"header/header": [
|
|
210
|
+
2,
|
|
211
|
+
"block",
|
|
212
|
+
[
|
|
213
|
+
"",
|
|
214
|
+
{ "pattern": " \\* Copyright \\(c\\) (\\d{4}-)?\\d{4}" },
|
|
215
|
+
" * My Company",
|
|
216
|
+
" "
|
|
217
|
+
]
|
|
218
|
+
]
|
|
49
219
|
}
|
|
50
220
|
}
|
|
51
221
|
```
|
|
52
222
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
223
|
+
Note on auto-fixes i.e. `eslint --fix`: whenever strings are used to define the
|
|
224
|
+
header - counting in file-based configuration - the same strings would be used
|
|
225
|
+
to replace a header comment that did not pass validation. This is not possible
|
|
226
|
+
with regular expressions. For regular expression pattern-objects, a second
|
|
227
|
+
property `template` adds a replacement string.
|
|
56
228
|
|
|
57
|
-
Zero newlines:
|
|
58
229
|
```json
|
|
59
230
|
{
|
|
60
|
-
|
|
61
|
-
"header"
|
|
62
|
-
],
|
|
231
|
+
...
|
|
63
232
|
"rules": {
|
|
64
|
-
"header/header": [
|
|
233
|
+
"header/header": [
|
|
234
|
+
2,
|
|
235
|
+
"line",
|
|
236
|
+
[
|
|
237
|
+
{
|
|
238
|
+
"pattern": " Copyright \\(c\\) (\\d{4}-)?\\d{4}",
|
|
239
|
+
"template": " Copyright 2025",
|
|
240
|
+
},
|
|
241
|
+
" My Company"
|
|
242
|
+
]
|
|
243
|
+
]
|
|
65
244
|
}
|
|
66
245
|
}
|
|
67
246
|
```
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
247
|
+
There are a number of things to consider:
|
|
248
|
+
- Templates need to be matched by the regular expression pattern or otherwise
|
|
249
|
+
an auto-fixed source would again fail linting. This needs to be validated
|
|
250
|
+
manually today as the plugin does not do it for you.
|
|
251
|
+
- Templates are hardcoded strings therefore it may be better to hand-fix a bad
|
|
252
|
+
header in order not to lose the from- and to-years in the copyright notice.
|
|
253
|
+
|
|
254
|
+
#### Trailing Empty Lines Configuration
|
|
72
255
|
|
|
73
|
-
|
|
256
|
+
The third argument of the rule configuration which defaults to 1 specifies the
|
|
257
|
+
number of newlines that are enforced after the header.
|
|
258
|
+
|
|
259
|
+
Zero newlines:
|
|
74
260
|
```json
|
|
75
261
|
{
|
|
76
262
|
"plugins": [
|
|
77
263
|
"header"
|
|
78
264
|
],
|
|
79
265
|
"rules": {
|
|
80
|
-
"header/header": [
|
|
266
|
+
"header/header": [
|
|
267
|
+
2,
|
|
268
|
+
"block",
|
|
269
|
+
[
|
|
270
|
+
" Copyright now",
|
|
271
|
+
"My Company "
|
|
272
|
+
],
|
|
273
|
+
0
|
|
274
|
+
]
|
|
81
275
|
}
|
|
82
276
|
}
|
|
83
277
|
```
|
|
84
278
|
```js
|
|
85
279
|
/* Copyright now
|
|
86
|
-
My Company */
|
|
87
|
-
console.log(1)
|
|
280
|
+
My Company */ console.log(1)
|
|
88
281
|
```
|
|
89
282
|
|
|
90
|
-
|
|
283
|
+
One newline (default):
|
|
91
284
|
```json
|
|
92
285
|
{
|
|
93
286
|
"plugins": [
|
|
94
287
|
"header"
|
|
95
288
|
],
|
|
96
289
|
"rules": {
|
|
97
|
-
"header/header": [
|
|
290
|
+
"header/header": [
|
|
291
|
+
2,
|
|
292
|
+
"block",
|
|
293
|
+
[
|
|
294
|
+
" Copyright now",
|
|
295
|
+
"My Company "
|
|
296
|
+
],
|
|
297
|
+
1
|
|
298
|
+
]
|
|
98
299
|
}
|
|
99
300
|
}
|
|
100
301
|
```
|
|
101
302
|
```js
|
|
102
303
|
/* Copyright now
|
|
103
304
|
My Company */
|
|
104
|
-
|
|
105
305
|
console.log(1)
|
|
106
306
|
```
|
|
107
307
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
Instead of a string to be checked for exact matching you can also supply a regular expression. Be aware that you have to escape backslashes:
|
|
111
|
-
|
|
308
|
+
Two newlines:
|
|
112
309
|
```json
|
|
113
310
|
{
|
|
114
311
|
"plugins": [
|
|
115
312
|
"header"
|
|
116
313
|
],
|
|
117
314
|
"rules": {
|
|
118
|
-
"header/header": [
|
|
119
|
-
|
|
120
|
-
"
|
|
121
|
-
|
|
315
|
+
"header/header": [
|
|
316
|
+
2,
|
|
317
|
+
"block",
|
|
318
|
+
[
|
|
319
|
+
" Copyright now",
|
|
320
|
+
"My Company "
|
|
321
|
+
],
|
|
322
|
+
2
|
|
323
|
+
]
|
|
122
324
|
}
|
|
123
325
|
}
|
|
124
326
|
```
|
|
125
|
-
|
|
126
|
-
This would match:
|
|
127
|
-
|
|
128
327
|
```js
|
|
129
|
-
/* Copyright
|
|
130
|
-
My Company*/
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
When you use a regular expression `pattern`, you can also provide a `template` property, to provide the comment value when using `eslint --fix`:
|
|
328
|
+
/* Copyright now
|
|
329
|
+
My Company */
|
|
134
330
|
|
|
135
|
-
|
|
136
|
-
{
|
|
137
|
-
"plugins": [
|
|
138
|
-
"header"
|
|
139
|
-
],
|
|
140
|
-
"rules": {
|
|
141
|
-
"header/header": [2, "block", [
|
|
142
|
-
{"pattern": " Copyright \\d{4}", "template": " Copyright 2019"},
|
|
143
|
-
"My Company"
|
|
144
|
-
]]
|
|
145
|
-
}
|
|
146
|
-
}
|
|
331
|
+
console.log(1)
|
|
147
332
|
```
|
|
148
333
|
|
|
149
|
-
|
|
334
|
+
#### Line Endings
|
|
150
335
|
|
|
151
|
-
The rule works with both
|
|
336
|
+
The rule works with both Unix/POSIX and Windows line endings. For ESLint
|
|
337
|
+
`--fix`, the rule will use the line ending format of the current operating
|
|
338
|
+
system (via Node's `os` package). This setting can be overwritten as follows:
|
|
152
339
|
```json
|
|
153
340
|
"rules": {
|
|
154
|
-
"header/header": [
|
|
341
|
+
"header/header": [
|
|
342
|
+
2,
|
|
343
|
+
"block",
|
|
344
|
+
[
|
|
345
|
+
"Copyright 2018",
|
|
346
|
+
"My Company"
|
|
347
|
+
],
|
|
348
|
+
{
|
|
349
|
+
"lineEndings": "windows"
|
|
350
|
+
}
|
|
351
|
+
]
|
|
155
352
|
}
|
|
156
353
|
```
|
|
157
|
-
Possible values are `unix` for `\n` and `windows` for `\r\n` line endings.
|
|
354
|
+
Possible values are `"unix"` for `\n` and `"windows"` for `\r\n` line endings.
|
|
158
355
|
|
|
159
356
|
## Examples
|
|
160
357
|
|
|
@@ -191,7 +388,7 @@ console.log(1)
|
|
|
191
388
|
" * Copyright 2015",
|
|
192
389
|
" * My Company",
|
|
193
390
|
" ************************"
|
|
194
|
-
]
|
|
391
|
+
]]
|
|
195
392
|
```
|
|
196
393
|
|
|
197
394
|
```js
|
package/lib/rules/header.js
CHANGED
|
@@ -160,19 +160,28 @@ function genCommentsRange(context, comments, eol) {
|
|
|
160
160
|
/**
|
|
161
161
|
* Factory for fixer that adds a missing header.
|
|
162
162
|
* @param {'block' | 'line'} commentType type of comment to use.
|
|
163
|
-
* @param {
|
|
163
|
+
* @param {RuleContext} context ESLint execution runtime.
|
|
164
164
|
* @param {string[]} headerLines lines of the header comment.
|
|
165
165
|
* @param {'\n' | '\r\n'} eol end-of-line characters
|
|
166
166
|
* @param {number} numNewlines number of trailing lines after the comment.
|
|
167
167
|
* @returns {ReportFixer} the fixer.
|
|
168
168
|
*/
|
|
169
|
-
function genPrependFixer(commentType,
|
|
169
|
+
function genPrependFixer(commentType, context, headerLines, eol, numNewlines) {
|
|
170
170
|
return function(fixer) {
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
const newHeader = genCommentBody(commentType, headerLines, eol, numNewlines);
|
|
172
|
+
if (context.sourceCode.text.substring(0, 2) === "#!") {
|
|
173
|
+
const firstNewLinePos = context.sourceCode.text.indexOf("\n");
|
|
174
|
+
const insertPos = firstNewLinePos === -1 ? context.sourceCode.text.length : firstNewLinePos + 1;
|
|
175
|
+
return fixer.insertTextBeforeRange(
|
|
176
|
+
[insertPos, insertPos /* don't care */],
|
|
177
|
+
(firstNewLinePos === -1 ? eol : "") + newHeader
|
|
178
|
+
);
|
|
179
|
+
} else {
|
|
180
|
+
return fixer.insertTextBeforeRange(
|
|
181
|
+
[0, 0 /* don't care */],
|
|
182
|
+
newHeader
|
|
183
|
+
);
|
|
184
|
+
}
|
|
176
185
|
};
|
|
177
186
|
}
|
|
178
187
|
|
|
@@ -403,11 +412,11 @@ module.exports = {
|
|
|
403
412
|
|
|
404
413
|
return {
|
|
405
414
|
Program: function(node) {
|
|
406
|
-
if (!hasHeader(context.
|
|
415
|
+
if (!hasHeader(context.sourceCode.getText())) {
|
|
407
416
|
context.report({
|
|
408
417
|
loc: node.loc,
|
|
409
418
|
message: "missing header",
|
|
410
|
-
fix: genPrependFixer(commentType,
|
|
419
|
+
fix: genPrependFixer(commentType, context, fixLines, eol, numNewlines)
|
|
411
420
|
});
|
|
412
421
|
} else {
|
|
413
422
|
var leadingComments = getLeadingComments(context, node);
|
|
@@ -437,6 +446,17 @@ module.exports = {
|
|
|
437
446
|
});
|
|
438
447
|
return;
|
|
439
448
|
}
|
|
449
|
+
if (headerLines.length === 1) {
|
|
450
|
+
const leadingCommentValues = leadingComments.map((c) => c.value);
|
|
451
|
+
if (!match(leadingCommentValues.join("\n"), headerLines[0]) && !match(leadingCommentValues.join("\r\n"), headerLines[0])) {
|
|
452
|
+
context.report({
|
|
453
|
+
loc: node.loc,
|
|
454
|
+
message: "incorrect header",
|
|
455
|
+
fix: canFix ? genReplaceFixer(commentType, context, leadingComments, fixLines, eol, numNewlines) : null
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
440
460
|
for (var i = 0; i < headerLines.length; i++) {
|
|
441
461
|
if (!match(leadingComments[i].value, headerLines[i])) {
|
|
442
462
|
context.report({
|
package/package.json
CHANGED