@tony.ganchev/eslint-plugin-header 3.1.13 → 3.2.1

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/README.md CHANGED
@@ -51,53 +51,66 @@ statements.
51
51
 
52
52
  ## Usage
53
53
 
54
- This rule takes between 1 and 4 arguments after the rule validation severity.
55
-
56
- The configuration can take any of the following forms:
57
-
58
- - File-based Configuration
59
- - `[<severity>, "<file>"]` - read the header template from a file.
60
- - `[<severity>, "<file>", {<settings>}]` - read the header template from a
61
- file with additional settings.
62
- - Inline Configuration
63
- - `"<severity>", "<comment-type>", <header-contents>` - define the header
64
- contents inline.
65
- - `[<severity>, "<comment-type>", <header-contents>, {<settings>}]` - define
66
- the header contents inline and pass additional settings.
67
- - `[<severity>, "<comment-type>", <header-contents>, <n-empty-lines>]` -
68
- define the header contents inline and an expected number of empty lines
69
- after the header.
70
- - `[<severity>, "<comment-type>", <header-contents>, <n-empty-lines>,
71
- {<settings>}]` - define the header contents inline and an expected number of
72
- empty lines after the header and pass additional settings.
73
-
74
- For TypesScript-based flat ESLint configuration, the following type is provided:
54
+ The plugin and its _header_ rule goes through evolution of its configuration in
55
+ the 3.2.x release. We introduced a new single object-based configuration format
56
+ that is easier to evolve in the future to add more capabilities.
57
+
58
+ The legacy configuration format inherited from
59
+ [eslint-plugin-header](https://github.com/Stuk/eslint-plugin-header) is still
60
+ supported and you can learn how to use it in a
61
+ [dedicated document](legacy-config.md). For information on how to switch from
62
+ the legacy configuration format to the new style, follow our
63
+ [migration guide](migrate-config.md). The current document from this point on
64
+ will cover only the new configuration format.
65
+
66
+ This _header_ rule takes a single object as configuration, after the severity
67
+ level. At the very least, the object should contain a `header` field describing
68
+ the expected header to match in the source files.
69
+
70
+ For TypesScript-based flat ESLint configuration, two types are provided:
75
71
 
76
72
  - `HeaderRuleConfig` defines the overall rule configuration for the `header`
77
73
  rule and includes severity level and supports both the modern object-based
78
74
  configuration and the legacy array-based configuration.
75
+ - `HeaderOptions` helper type that defines the structure of the configuration
76
+ object used in the modern configuration style that is used in this document.
77
+ It can be used to either simplify auto-completion since this type is not mixed
78
+ with a large number of named tuple types, or it can be used when the config
79
+ object is defined outside of the definition of a specific rule.
79
80
 
80
81
  ### File-based Configuration
81
82
 
82
- In this configuration mode, the first argument is a string pointing to a JS
83
- file containing the header contents. The rule would expect an exact match to be
84
- found in the source code.
83
+ In this configuration mode, the header template is read from a file.
84
+
85
+ _eslint.config.ts_:
85
86
 
86
- The second argument can be a settings object that will be covered later in this
87
- document.
87
+ ```ts
88
+ import header, {
89
+ HeaderOptions, HeaderRuleConfig
90
+ } from "@tony.ganchev/eslint-plugin-header";
91
+ import { defineConfig } from "eslint/config";
88
92
 
89
- ```json
90
- {
91
- "plugins": [
92
- "header"
93
- ],
94
- "rules": {
95
- "header/header": [2, "config/header.js"]
93
+ export default defineConfig([
94
+ {
95
+ files: ["**/*.js"],
96
+ plugins: {
97
+ "@tony.ganchev": header
98
+ },
99
+ rules: {
100
+ "@tony.ganchev/header": [
101
+ "error",
102
+ {
103
+ header: {
104
+ file: "config/header.js"
105
+ }
106
+ } as HeaderOptions
107
+ ] as HeaderRuleConfig
108
+ }
96
109
  }
97
- }
110
+ ]);
98
111
  ```
99
112
 
100
- config/header.js:
113
+ _config/header.js_:
101
114
 
102
115
  ```js
103
116
  // Copyright 2015
@@ -110,14 +123,16 @@ tree then the header file will not be found.
110
123
 
111
124
  ### Inline Configuration
112
125
 
113
- The inline configuration expects at least two arguments to be given:
126
+ In this configuration mode, the matching rules for the header are given inline.
127
+ The `header` field should contain the following nested properties:
114
128
 
115
- - _comment-type_ which is either `"block"` or `"line"` to indicate what style
129
+ - `commentType` which is either `"block"` or `"line"` to indicate what style
116
130
  of comment should be used.
117
- - _header-contents_ which defines the lines of the header. It can be either a
131
+ - `line` which defines the lines of the header. It can be either a
118
132
  single multiline string / regular expression with the full contents of the
119
133
  header comment or an array with comment lines or regular expressions matching
120
- each line.
134
+ each line. It can also include template replacement strings to enable ESLint's
135
+ auto-fix capabilities.
121
136
 
122
137
  #### Header Contents Configuration
123
138
 
@@ -134,16 +149,29 @@ All of the following configurations will match the header:
134
149
 
135
150
  - **Single string**:
136
151
 
137
- ```json
138
- {
139
- "rules": {
140
- "header/header": [
141
- 2,
142
- "block",
143
- "\n * Copyright (c) 2015\n * My Company\n "
144
- ]
152
+ ```ts
153
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
154
+ import { defineConfig } from "eslint/config";
155
+
156
+ export default defineConfig([
157
+ {
158
+ files: ["**/*.js"],
159
+ plugins: {
160
+ "@tony.ganchev": header
161
+ },
162
+ rules: {
163
+ "@tony.ganchev/header": [
164
+ "error",
165
+ {
166
+ header: {
167
+ commentType: "block",
168
+ lines: ["\n * Copyright (c) 2015\n * My Company\n "]
169
+ }
170
+ } as HeaderOptions
171
+ ]
172
+ }
145
173
  }
146
- }
174
+ ]);
147
175
  ```
148
176
 
149
177
  Note that the above would work for both Windows and POSIX systems even
@@ -159,61 +187,164 @@ All of the following configurations will match the header:
159
187
 
160
188
  - **Single regular expression**:
161
189
 
162
- ```json
163
- {
164
- "rules": {
165
- "header/header": [
166
- 2,
167
- "block",
168
- {
169
- "pattern":
170
- "\\n \\* Copyright \\(c\\) 2015\\n \\* My Company\\n "
171
- }
172
- ]
190
+ You can match the whole header with a regular expression. To do it, simply
191
+ pass a `RegExp` object in place of a string.
192
+
193
+ ```ts
194
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
195
+ import { defineConfig } from "eslint/config";
196
+
197
+ export default defineConfig([
198
+ {
199
+ files: ["**/*.js"],
200
+ plugins: {
201
+ "@tony.ganchev": header
202
+ },
203
+ rules: {
204
+ "@tony.ganchev/header": [
205
+ "error",
206
+ {
207
+ header: {
208
+ commentType: "block",
209
+ lines: [
210
+ /\n \* Copyright \(c\) 2015\n \* Company\n /
211
+ ]
212
+ }
213
+ } as HeaderOptions
214
+ ]
215
+ }
173
216
  }
174
- }
217
+ ]);
218
+ ```
219
+
220
+ If you still use hierarchical configuration, you can define the regular
221
+ expression as a string.
222
+
223
+ ```ts
224
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
225
+ import { defineConfig } from "eslint/config";
226
+
227
+ export default defineConfig([
228
+ {
229
+ files: ["**/*.js"],
230
+ plugins: {
231
+ "@tony.ganchev": header
232
+ },
233
+ rules: {
234
+ "@tony.ganchev/header": [
235
+ "error",
236
+ {
237
+ header: {
238
+ commentType: "block",
239
+ lines: [
240
+ { pattern: "\\n \\* Copyright \\(c\\) 2015"
241
+ + "\\n \\* My Company\\n "}
242
+ ]
243
+ }
244
+ } as HeaderOptions
245
+ ]
246
+ }
247
+ }
248
+ ]);
175
249
  ```
176
250
 
177
251
  Notice the double escaping of the braces. Since these pattern strings into
178
252
  `RegExp` objects, the backslashes need to be present in the string instead
179
253
  of disappear as escape characters.
180
254
 
255
+ You can pass a `RegExp` object to the `pattern` field. This is necessary if
256
+ you want to add an aut-fix for the line as we will explain further in this
257
+ document.
258
+
259
+ ```ts
260
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
261
+ import { defineConfig } from "eslint/config";
262
+
263
+ export default defineConfig([
264
+ {
265
+ files: ["**/*.js"],
266
+ plugins: {
267
+ "@tony.ganchev": header
268
+ },
269
+ rules: {
270
+ "@tony.ganchev/header": [
271
+ "error",
272
+ {
273
+ header: {
274
+ commentType: "block",
275
+ lines: [
276
+ { pattern: /Copyright \(c\) 20\d{2}/ }
277
+ ]
278
+ }
279
+ } as HeaderOptions
280
+ ]
281
+ }
282
+ }
283
+ ]);
284
+ ```
285
+
181
286
  - **Array of strings**:
182
287
 
183
- ```json
184
- {
185
- "rules": {
186
- "header/header": [
187
- 2,
188
- "block",
189
- [
190
- "",
191
- " * Copyright (c) 2015",
192
- " * My Company",
193
- " "
288
+ ```ts
289
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
290
+ import { defineConfig } from "eslint/config";
291
+
292
+ export default defineConfig([
293
+ {
294
+ files: ["**/*.js"],
295
+ plugins: {
296
+ "@tony.ganchev": header
297
+ },
298
+ rules: {
299
+ "@tony.ganchev/header": [
300
+ "error",
301
+ {
302
+ header: {
303
+ commentType: "block",
304
+ lines: [
305
+ "",
306
+ " * Copyright (c) 2015",
307
+ " * My Company",
308
+ " "
309
+ ]
310
+ }
311
+ } as HeaderOptions
194
312
  ]
195
- ]
313
+ }
196
314
  }
197
- }
315
+ ]);
198
316
  ```
199
317
 
200
318
  - **Array of strings and/or patterns**:
201
319
 
202
- ```json
203
- {
204
- "rules": {
205
- "header/header": [
206
- 2,
207
- "block",
208
- [
209
- "",
210
- { "pattern": " \\* Copyright \\(c\\) 2015" },
211
- " * My Company",
212
- " "
320
+ ```ts
321
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
322
+ import { defineConfig } from "eslint/config";
323
+
324
+ export default defineConfig([
325
+ {
326
+ files: ["**/*.js"],
327
+ plugins: {
328
+ "@tony.ganchev": header
329
+ },
330
+ rules: {
331
+ "@tony.ganchev/header": [
332
+ "error",
333
+ {
334
+ header: {
335
+ commentType: "block",
336
+ lines: [
337
+ "",
338
+ / \* Copyright \(c\) 2015/,
339
+ " * My Company",
340
+ " "
341
+ ]
342
+ }
343
+ } as HeaderOptions
213
344
  ]
214
- ]
345
+ }
215
346
  }
216
- }
347
+ ]);
217
348
  ```
218
349
 
219
350
  Regular expressions allow for a number of improvements in the maintainability
@@ -241,21 +372,34 @@ support:
241
372
 
242
373
  We can use a regular expression to support all of these cases for your header:
243
374
 
244
- ```json
245
- {
246
- "rules": {
247
- "header/header": [
248
- 2,
249
- "block",
250
- [
251
- "",
252
- { "pattern": " \\* Copyright \\(c\\) (\\d{4}-)?\\d{4}" },
253
- " * My Company",
254
- " "
375
+ ```ts
376
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
377
+ import { defineConfig } from "eslint/config";
378
+
379
+ export default defineConfig([
380
+ {
381
+ files: ["**/*.js"],
382
+ plugins: {
383
+ "@tony.ganchev": header
384
+ },
385
+ rules: {
386
+ "@tony.ganchev/header": [
387
+ "error",
388
+ {
389
+ header: {
390
+ commentType: "block",
391
+ lines: [
392
+ "",
393
+ / \* Copyright \(c\) (\d{4}-)?\d{4}/,
394
+ " * My Company",
395
+ " "
396
+ ]
397
+ }
398
+ } as HeaderOptions
255
399
  ]
256
- ]
400
+ }
257
401
  }
258
- }
402
+ ]);
259
403
  ```
260
404
 
261
405
  Note on auto-fixes i.e. `eslint --fix`: whenever strings are used to define the
@@ -264,22 +408,35 @@ to replace a header comment that did not pass validation. This is not possible
264
408
  with regular expressions. For regular expression pattern-objects, a second
265
409
  property `template` adds a replacement string.
266
410
 
267
- ```json
268
- {
269
- "rules": {
270
- "header/header": [
271
- 2,
272
- "line",
273
- [
411
+ ```ts
412
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
413
+ import { defineConfig } from "eslint/config";
414
+
415
+ export default defineConfig([
416
+ {
417
+ files: ["**/*.js"],
418
+ plugins: {
419
+ "@tony.ganchev": header
420
+ },
421
+ rules: {
422
+ "@tony.ganchev/header": [
423
+ "error",
274
424
  {
275
- "pattern": " Copyright \\(c\\) (\\d{4}-)?\\d{4}",
276
- "template": " Copyright 2025",
277
- },
278
- " My Company"
425
+ header: {
426
+ commentType: "line",
427
+ lines: [
428
+ {
429
+ pattern: / Copyright \(c\) (\d{4}-)?\d{4}/,
430
+ template: " Copyright 2025",
431
+ },
432
+ " My Company"
433
+ ]
434
+ }
435
+ } as HeaderOptions
279
436
  ]
280
- ]
437
+ }
281
438
  }
282
- }
439
+ ]);
283
440
  ```
284
441
 
285
442
  There are a number of things to consider:
@@ -297,23 +454,35 @@ number of newlines that are enforced after the header.
297
454
 
298
455
  Zero newlines:
299
456
 
300
- ```json
301
- {
302
- "plugins": [
303
- "header"
304
- ],
305
- "rules": {
306
- "header/header": [
307
- 2,
308
- "block",
309
- [
310
- " Copyright now",
311
- "My Company "
312
- ],
313
- 0
314
- ]
457
+ ```ts
458
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
459
+ import { defineConfig } from "eslint/config";
460
+
461
+ export default defineConfig([
462
+ {
463
+ files: ["**/*.js"],
464
+ plugins: {
465
+ "@tony.ganchev": header
466
+ },
467
+ rules: {
468
+ "@tony.ganchev/header": [
469
+ "error",
470
+ {
471
+ header: {
472
+ commentType: "block",
473
+ lines: [
474
+ " Copyright now",
475
+ "My Company "
476
+ ],
477
+ },
478
+ trailingEmptyLines: {
479
+ minimum: 0
480
+ }
481
+ } as HeaderOptions
482
+ ]
483
+ }
315
484
  }
316
- }
485
+ ]);
317
486
  ```
318
487
 
319
488
  ```js
@@ -323,23 +492,35 @@ My Company */ console.log(1)
323
492
 
324
493
  One newline (default):
325
494
 
326
- ```json
327
- {
328
- "plugins": [
329
- "header"
330
- ],
331
- "rules": {
332
- "header/header": [
333
- 2,
334
- "block",
335
- [
336
- " Copyright now",
337
- "My Company "
338
- ],
339
- 1
340
- ]
495
+ ```ts
496
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
497
+ import { defineConfig } from "eslint/config";
498
+
499
+ export default defineConfig([
500
+ {
501
+ files: ["**/*.js"],
502
+ plugins: {
503
+ "@tony.ganchev": header
504
+ },
505
+ rules: {
506
+ "@tony.ganchev/header": [
507
+ "error",
508
+ {
509
+ header: {
510
+ commentType: "block",
511
+ lines: [
512
+ " Copyright now",
513
+ "My Company "
514
+ ],
515
+ },
516
+ trailingEmptyLines: {
517
+ minimum: 1
518
+ }
519
+ } as HeaderOptions
520
+ ]
521
+ }
341
522
  }
342
- }
523
+ ]);
343
524
  ```
344
525
 
345
526
  ```js
@@ -350,23 +531,35 @@ console.log(1)
350
531
 
351
532
  Two newlines:
352
533
 
353
- ```json
354
- {
355
- "plugins": [
356
- "header"
357
- ],
358
- "rules": {
359
- "header/header": [
360
- 2,
361
- "block",
362
- [
363
- " Copyright now",
364
- "My Company "
365
- ],
366
- 2
367
- ]
534
+ ```ts
535
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
536
+ import { defineConfig } from "eslint/config";
537
+
538
+ export default defineConfig([
539
+ {
540
+ files: ["**/*.js"],
541
+ plugins: {
542
+ "@tony.ganchev": header
543
+ },
544
+ rules: {
545
+ "@tony.ganchev/header": [
546
+ "error",
547
+ {
548
+ header: {
549
+ commentType: "block",
550
+ lines: [
551
+ " Copyright now",
552
+ "My Company "
553
+ ]
554
+ },
555
+ trailingEmptyLines: {
556
+ minimum: 2
557
+ }
558
+ } as HeaderOptions
559
+ ]
560
+ }
368
561
  }
369
- }
562
+ ]);
370
563
  ```
371
564
 
372
565
  ```js
@@ -382,36 +575,99 @@ The rule works with both Unix/POSIX and Windows line endings. For ESLint
382
575
  `--fix`, the rule will use the line ending format of the current operating
383
576
  system (via Node's `os` package). This setting can be overwritten as follows:
384
577
 
385
- ```json
386
- "rules": {
387
- "header/header": [
388
- 2,
389
- "block",
390
- [
391
- "Copyright 2018",
392
- "My Company"
393
- ],
394
- {
395
- "lineEndings": "windows"
578
+ ```ts
579
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
580
+ import { defineConfig } from "eslint/config";
581
+
582
+ export default defineConfig([
583
+ {
584
+ files: ["**/*.js"],
585
+ plugins: {
586
+ "@tony.ganchev": header
587
+ },
588
+ rules: {
589
+ "@tony.ganchev/header": [
590
+ "error",
591
+ {
592
+ header: {
593
+ commentType: "block",
594
+ lines: [
595
+ "Copyright 2018",
596
+ "My Company"
597
+ ]
598
+ },
599
+ lineEndings: "windows"
600
+ } as HeaderOptions
601
+ ]
396
602
  }
397
- ]
398
- }
603
+ }
604
+ ]);
399
605
  ```
400
606
 
401
607
  Possible values are `"unix"` for `\n` and `"windows"` for `\r\n` line endings.
608
+ The default value is `"os"` which means assume the system-specific line endings.
402
609
 
403
610
  ## Examples
404
611
 
405
612
  The following examples are all valid.
406
613
 
407
- `"block", "Copyright 2015, My Company"`:
614
+ ```ts
615
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
616
+ import { defineConfig } from "eslint/config";
617
+
618
+ export default defineConfig([
619
+ {
620
+ files: ["**/*.js"],
621
+ plugins: {
622
+ "@tony.ganchev": header
623
+ },
624
+ rules: {
625
+ "@tony.ganchev/header": [
626
+ "error",
627
+ {
628
+ header: {
629
+ commentType: "block",
630
+ lines: ["Copyright 2015, My Company"]
631
+ }
632
+ } as HeaderOptions
633
+ ]
634
+ }
635
+ }
636
+ ]);
637
+ ```
408
638
 
409
639
  ```js
410
640
  /*Copyright 2015, My Company*/
411
641
  console.log(1);
412
642
  ```
413
643
 
414
- `"line", ["Copyright 2015", "My Company"]]`:
644
+ ```ts
645
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
646
+ import { defineConfig } from "eslint/config";
647
+
648
+ export default defineConfig([
649
+ {
650
+ files: ["**/*.js"],
651
+ plugins: {
652
+ "@tony.ganchev": header
653
+ },
654
+ rules: {
655
+ "@tony.ganchev/header": [
656
+ "error",
657
+ {
658
+ header: {
659
+ commentType: "line",
660
+ lines: [
661
+ "Copyright 2015",
662
+ "My Company"
663
+ ]
664
+ }
665
+ } as HeaderOptions
666
+ ]
667
+ }
668
+ }
669
+ ]);
670
+ ```
415
671
 
416
672
  ```js
417
673
  //Copyright 2015
@@ -419,7 +675,33 @@ console.log(1);
419
675
  console.log(1)
420
676
  ```
421
677
 
422
- `"line", [{pattern: "^Copyright \\d{4}$"}, {pattern: "^My Company$"}]]`:
678
+ ```ts
679
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
680
+ import { defineConfig } from "eslint/config";
681
+
682
+ export default defineConfig([
683
+ {
684
+ files: ["**/*.js"],
685
+ plugins: {
686
+ "@tony.ganchev": header
687
+ },
688
+ rules: {
689
+ "@tony.ganchev/header": [
690
+ "error",
691
+ {
692
+ header: {
693
+ commentType: "line",
694
+ lines: [
695
+ /^Copyright \d{4}$/,
696
+ /^My Company$/
697
+ ]
698
+ }
699
+ } as HeaderOptions
700
+ ]
701
+ }
702
+ }
703
+ ]);
704
+ ```
423
705
 
424
706
  ```js
425
707
  //Copyright 2017
@@ -429,13 +711,34 @@ console.log(1)
429
711
 
430
712
  With more decoration:
431
713
 
432
- ```json
433
- "header/header": [2, "block", [
434
- "************************",
435
- " * Copyright 2015",
436
- " * My Company",
437
- " ************************"
438
- ]]
714
+ ```ts
715
+ import header, { HeaderOptions } from "@tony.ganchev/eslint-plugin-header";
716
+ import { defineConfig } from "eslint/config";
717
+
718
+ export default defineConfig([
719
+ {
720
+ files: ["**/*.js"],
721
+ plugins: {
722
+ "@tony.ganchev": header
723
+ },
724
+ rules: {
725
+ "@tony.ganchev/header": [
726
+ "error",
727
+ {
728
+ header: {
729
+ commentType: "block",
730
+ lines: [
731
+ "************************",
732
+ " * Copyright 2015",
733
+ " * My Company",
734
+ " ************************"
735
+ ]
736
+ }
737
+ } as HeaderOptions
738
+ ]
739
+ }
740
+ }
741
+ ]);
439
742
  ```
440
743
 
441
744
  ```js