@tony.ganchev/eslint-plugin-header 3.3.3 → 3.4.0
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 +306 -14
- package/lib/comment-parser.js +23 -9
- package/lib/rules/header.js +366 -220
- package/package.json +34 -18
- package/types/lib/comment-parser.d.ts +3 -1
- package/types/lib/comment-parser.d.ts.map +1 -1
- package/types/lib/rules/header.d.ts +62 -1
- package/types/lib/rules/header.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@tony.ganchev/eslint-plugin-header)
|
|
4
4
|
[](http://www.npmtrends.com/@tony.ganchev/eslint-plugin-header)
|
|
5
|
-
[](https://github.com/tonyganchev/eslint-plugin-header/actions/workflows/test.yml?query=branch%3Amain)
|
|
6
6
|
|
|
7
7
|
The native ESLint 9/10 standard header-validating plugin. A zero-bloat, drop-in
|
|
8
8
|
replacement for [eslint-plugin-header](https://github.com/Stuk/eslint-plugin-header)
|
|
9
9
|
with first-class Flat Config & TypeScript support. Auto-fix copyright, license,
|
|
10
|
-
and banner comments in JavaScript and
|
|
10
|
+
and banner comments in JavaScript, TypeScript, CSS, HTML, and Markdown files.
|
|
11
|
+
Supports _oxlint_.
|
|
11
12
|
|
|
12
13
|
## Table of Contents
|
|
13
14
|
|
|
14
15
|
1. [Motivation and Acknowledgements](#motivation-and-acknowledgements)
|
|
15
|
-
2. [
|
|
16
|
-
3. [
|
|
16
|
+
2. [Major Consumers](#major-consumers)
|
|
17
|
+
3. [Compatibility](#compatibility)
|
|
18
|
+
1. [Runtimes](#runtimes)
|
|
19
|
+
2. [Configuration Formats](#configuration-formats)
|
|
20
|
+
3. [Languages](#languages)
|
|
21
|
+
4. [Usage](#usage)
|
|
17
22
|
1. [File-based Configuration](#file-based-configuration)
|
|
18
23
|
2. [Inline Configuration](#inline-configuration)
|
|
19
24
|
1. [Header Contents Configuration](#header-contents-configuration)
|
|
@@ -23,14 +28,17 @@ and banner comments in JavaScript and TypeScript files.
|
|
|
23
28
|
3. [Support for Leading Comments](#support-for-leading-comments)
|
|
24
29
|
1. [Notes on Behavior](#notes-on-behavior)
|
|
25
30
|
4. [Examples](#examples)
|
|
26
|
-
|
|
31
|
+
5. [Linting CSS](#linting-css)
|
|
32
|
+
6. [Linting HTML](#linting-html)
|
|
33
|
+
7. [Linting Markdown](#linting-markdown)
|
|
34
|
+
5. [Comparison to Alternatives](#comparison-to-alternatives)
|
|
27
35
|
1. [Compared to eslint-plugin-headers](#compared-to-eslint-plugin-headers)
|
|
28
36
|
1. [Health Scans](#health-scans)
|
|
29
37
|
2. [Compared to eslint-plugin-license-header](#compared-to-eslint-plugin-license-header)
|
|
30
|
-
|
|
38
|
+
6. [Versioning](#versioning)
|
|
31
39
|
1. [What is a Feature?](#what-is-a-feature)
|
|
32
40
|
2. [What is Backward-compatibility?](#what-is-backward-compatibility)
|
|
33
|
-
|
|
41
|
+
7. [License](#license)
|
|
34
42
|
|
|
35
43
|
## Motivation and Acknowledgements
|
|
36
44
|
|
|
@@ -56,19 +64,87 @@ Multiple other projects took from where _eslint-plugin-header_ left off. A
|
|
|
56
64
|
comparison of the current project to these alternatives is available in a
|
|
57
65
|
dedicated section.
|
|
58
66
|
|
|
67
|
+
## Major Consumers
|
|
68
|
+
|
|
69
|
+
The plugin is used by hundreds of projects to enforce license compliance and
|
|
70
|
+
consistent header structures. Notable adopters include:
|
|
71
|
+
|
|
72
|
+
[](./docs/consumers.md#microsoft)
|
|
73
|
+
|
|
74
|
+
[](./docs/consumers.md#azure)
|
|
75
|
+
|
|
76
|
+
[](./docs/consumers.md#salesforce)
|
|
77
|
+
|
|
78
|
+
[](./docs/consumers.md#angular)
|
|
79
|
+
|
|
80
|
+
[](./docs/consumers.md#amazon)
|
|
81
|
+
|
|
82
|
+
[](./docs/consumers.md#cloudscape-design-system)
|
|
83
|
+
|
|
84
|
+
[](./docs/consumers.md#eclipse-foundation)
|
|
85
|
+
|
|
86
|
+
[](./docs/consumers.md#salto)
|
|
87
|
+
|
|
88
|
+
[](./docs/consumers.md#dash0)
|
|
89
|
+
|
|
90
|
+
[](./docs/consumers.md#ibm)
|
|
91
|
+
|
|
92
|
+
[](./docs/consumers.md#flowcrypt)
|
|
93
|
+
|
|
94
|
+
[](./docs/consumers.md#cratis)
|
|
95
|
+
|
|
96
|
+
[](./docs/consumers.md#mysten-labs)
|
|
97
|
+
|
|
98
|
+
[](./docs/consumers.md#suwayomi)
|
|
99
|
+
|
|
100
|
+
[](./docs/consumers.md#wire-swiss-gmbh)
|
|
101
|
+
|
|
102
|
+
[](./docs/consumers.md#wppconnect)
|
|
103
|
+
|
|
104
|
+
Learn more about how these organizations use the plugin on our
|
|
105
|
+
[consumers list](./docs/consumers.md).
|
|
106
|
+
|
|
59
107
|
## Compatibility
|
|
60
108
|
|
|
109
|
+
### Runtimes
|
|
110
|
+
|
|
61
111
|
The plugin supports **ESLint 7 / 8 / 9 / 10**. Both **flat** config and legacy,
|
|
62
112
|
**hierarchical** config can be used. We have a smoke-test running to confirm the
|
|
63
|
-
plugin works with the latest version of ESLint.
|
|
113
|
+
plugin works with the latest version of ESLint. Certain features such as linting
|
|
114
|
+
copyright headers in CSS, HTML, or Markdown rely on APIs introduced with ESLint
|
|
115
|
+
9 and cannot be used with older ESLint versions.
|
|
64
116
|
|
|
65
117
|
The plugin works with latest version of **oxlint** too. We have a smoke-test
|
|
66
|
-
running to confirm the plugin works with the latest version of oxlint.
|
|
118
|
+
running to confirm the plugin works with the latest version of oxlint. Features
|
|
119
|
+
relying on the use of non-standard parsers such as linting headers in CSS, HTML,
|
|
120
|
+
or Markdown cannot be supported.
|
|
121
|
+
|
|
122
|
+
### Configuration Formats
|
|
123
|
+
|
|
124
|
+
The plugin supports hierarchical and flat configuration format for ESLint as
|
|
125
|
+
well as the configuration format for oxlint.
|
|
67
126
|
|
|
68
127
|
The NPM package provides TypeScript type definitions and can be used with
|
|
69
128
|
TypeScript-based ESLint flat configuration without the need for `@ts-ignore`
|
|
70
129
|
statements. Smoke tests cover this support as well.
|
|
71
130
|
|
|
131
|
+
### Languages
|
|
132
|
+
|
|
133
|
+
Currently the plugin supports linting copyright headers in JavaScript,
|
|
134
|
+
TypeScript and their JSX / TSX flavors; CSS, HTML, and Markdown files. As
|
|
135
|
+
mentioned in the previous sections, not all languages are supported for oxlint
|
|
136
|
+
or ESLint older than 9. Refer to the table below for more details.
|
|
137
|
+
|
|
138
|
+
| Language | ESLint 7 / 8 | ESLint 9 / 10 | oxlint |
|
|
139
|
+
|------------|---------------|---------------|--------|
|
|
140
|
+
| JavaScript | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
141
|
+
| TypeScript | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
142
|
+
| JSX | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
143
|
+
| TSX | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
144
|
+
| CSS | ❌ No | ✅ Yes | ❌ No |
|
|
145
|
+
| HTML | ❌ No | ✅ Yes | ❌ No |
|
|
146
|
+
| Markdown | ❌ No | ✅ Yes | ❌ No |
|
|
147
|
+
|
|
72
148
|
## Usage
|
|
73
149
|
|
|
74
150
|
The plugin and its _header_ rule goes through evolution of its configuration in
|
|
@@ -141,6 +217,34 @@ Due to limitations in ESLint plugins, the file is read relative to the working
|
|
|
141
217
|
directory that ESLint is executed in. If you run ESLint from elsewhere in your
|
|
142
218
|
tree then the header file will not be found.
|
|
143
219
|
|
|
220
|
+
The equivalent configuration for _oxlint_ is:
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
225
|
+
"overrides": [
|
|
226
|
+
{
|
|
227
|
+
"files": [
|
|
228
|
+
"**/*.js"
|
|
229
|
+
],
|
|
230
|
+
"rules": {
|
|
231
|
+
"@tony.ganchev/header/header": [
|
|
232
|
+
"error",
|
|
233
|
+
{
|
|
234
|
+
"header": {
|
|
235
|
+
"file": "config/header.js"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
},
|
|
240
|
+
"jsPlugins": [
|
|
241
|
+
"@tony.ganchev/eslint-plugin-header"
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
144
248
|
### Inline Configuration
|
|
145
249
|
|
|
146
250
|
In this configuration mode, the matching rules for the header are given inline.
|
|
@@ -194,6 +298,37 @@ All of the following configurations will match the header:
|
|
|
194
298
|
]);
|
|
195
299
|
```
|
|
196
300
|
|
|
301
|
+
Equivalent configuration for _oxlint_:
|
|
302
|
+
|
|
303
|
+
```json
|
|
304
|
+
{
|
|
305
|
+
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
306
|
+
"overrides": [
|
|
307
|
+
{
|
|
308
|
+
"files": [
|
|
309
|
+
"**/*.js"
|
|
310
|
+
],
|
|
311
|
+
"rules": {
|
|
312
|
+
"@tony.ganchev/header/header": [
|
|
313
|
+
"error",
|
|
314
|
+
{
|
|
315
|
+
"header": {
|
|
316
|
+
"commentType": "block",
|
|
317
|
+
"lines": [
|
|
318
|
+
"\n * Copyright (c) 2015\n * My Company\n "
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
"jsPlugins": [
|
|
325
|
+
"@tony.ganchev/eslint-plugin-header"
|
|
326
|
+
]
|
|
327
|
+
}
|
|
328
|
+
]
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
197
332
|
Note that the above would work for both Windows and POSIX systems even
|
|
198
333
|
though the EOL in the header content was specified as `\n`.
|
|
199
334
|
|
|
@@ -1048,10 +1183,55 @@ export default defineConfig([
|
|
|
1048
1183
|
]);
|
|
1049
1184
|
```
|
|
1050
1185
|
|
|
1186
|
+
### Linting CSS
|
|
1187
|
+
|
|
1188
|
+
The rule supports validating and auto-fixing headers in CSS files. To
|
|
1189
|
+
use the plugin with these file types, you need to configure the official
|
|
1190
|
+
`@eslint/css` plugin.
|
|
1191
|
+
|
|
1192
|
+
**Note: the plugin does not support SCSS** as no current popular parser for
|
|
1193
|
+
ESLint supports SCSS / LESS that being a prerequisite for this plugin to be
|
|
1194
|
+
called. It is possible to rely on a dummy pass-through parser to ensure the SCSS
|
|
1195
|
+
/ LESS sources simply reach the rule but as of the time of the publisihng of
|
|
1196
|
+
this document we have not tested this approach.
|
|
1197
|
+
|
|
1198
|
+
Back to CSS, let us use the following configuration:
|
|
1199
|
+
|
|
1200
|
+
_eslint.config.js_:
|
|
1201
|
+
|
|
1051
1202
|
```js
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1203
|
+
import header from "@tony.ganchev/eslint-plugin-header";
|
|
1204
|
+
import css from "@eslint/css";
|
|
1205
|
+
|
|
1206
|
+
export default [
|
|
1207
|
+
{
|
|
1208
|
+
files: ["**/*.css"],
|
|
1209
|
+
plugins: {
|
|
1210
|
+
"@tony.ganchev": header,
|
|
1211
|
+
css
|
|
1212
|
+
},
|
|
1213
|
+
language: "css/css",
|
|
1214
|
+
rules: {
|
|
1215
|
+
"@tony.ganchev/header": [
|
|
1216
|
+
"error",
|
|
1217
|
+
{
|
|
1218
|
+
header: {
|
|
1219
|
+
commentType: "block",
|
|
1220
|
+
lines: [" Copyright 2025 "]
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
]
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
];
|
|
1227
|
+
```
|
|
1228
|
+
|
|
1229
|
+
```css
|
|
1230
|
+
/* Copyright 2025 */
|
|
1231
|
+
|
|
1232
|
+
.foo {
|
|
1233
|
+
color: blue;
|
|
1234
|
+
}
|
|
1055
1235
|
```
|
|
1056
1236
|
|
|
1057
1237
|
With more decoration:
|
|
@@ -1086,14 +1266,126 @@ export default defineConfig([
|
|
|
1086
1266
|
]);
|
|
1087
1267
|
```
|
|
1088
1268
|
|
|
1089
|
-
```
|
|
1269
|
+
```css
|
|
1090
1270
|
/*************************
|
|
1091
1271
|
* Copyright 2015
|
|
1092
1272
|
* My Company
|
|
1093
1273
|
*************************/
|
|
1094
|
-
|
|
1274
|
+
|
|
1275
|
+
.foo {
|
|
1276
|
+
color: blue
|
|
1277
|
+
}
|
|
1278
|
+
```
|
|
1279
|
+
|
|
1280
|
+
As you can expect with CSS syntax, line comments and shebangs are not supported.
|
|
1281
|
+
All other features of the rule remain the same.
|
|
1282
|
+
|
|
1283
|
+
### Linting HTML
|
|
1284
|
+
|
|
1285
|
+
The rule supports linting copyright notices in HTML files. The rule works with
|
|
1286
|
+
the _@html-eslint/eslint-plugin_ plugin and its parser.
|
|
1287
|
+
|
|
1288
|
+
Similar to CSS, all you need to do to turn on header validation is to configure
|
|
1289
|
+
the _\@html-eslint/eslint-plugin_ plugin and the rule:
|
|
1290
|
+
|
|
1291
|
+
```ts
|
|
1292
|
+
import header from "@tony.ganchev/eslint-plugin-header";
|
|
1293
|
+
import html from "@html-eslint/eslint-plugin";
|
|
1294
|
+
|
|
1295
|
+
export default [
|
|
1296
|
+
{
|
|
1297
|
+
files: ["**/*.html"],
|
|
1298
|
+
plugins: {
|
|
1299
|
+
"@tony.ganchev": header,
|
|
1300
|
+
html
|
|
1301
|
+
},
|
|
1302
|
+
language: "html/html",
|
|
1303
|
+
rules: {
|
|
1304
|
+
"@tony.ganchev/header": [
|
|
1305
|
+
"error",
|
|
1306
|
+
{
|
|
1307
|
+
header: {
|
|
1308
|
+
commentType: "block",
|
|
1309
|
+
lines: [" Copyright 2025 "]
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
]
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
];
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
```html
|
|
1319
|
+
<!-- Copyright 2025 -->
|
|
1320
|
+
|
|
1321
|
+
<html>
|
|
1322
|
+
<body>
|
|
1323
|
+
<h1>Hello, world!</h1>
|
|
1324
|
+
<p>Lorem ipsum dolor.</p>
|
|
1325
|
+
</body>
|
|
1326
|
+
</html>
|
|
1095
1327
|
```
|
|
1096
1328
|
|
|
1329
|
+
As with CSS, only block comments are supported - no line- or shebang comments.
|
|
1330
|
+
|
|
1331
|
+
### Linting Markdown
|
|
1332
|
+
|
|
1333
|
+
The rule supports copyright comments in Markdown syntax in both _commonmark_ and
|
|
1334
|
+
_gfm_ flavors using the _\@eslint/markdown_ plugin and parser. Only HTML
|
|
1335
|
+
comments are supported - no anchor hacks or similar are accepted.
|
|
1336
|
+
|
|
1337
|
+
Similar to CSS, all you need to do to turn on header validation is to configure
|
|
1338
|
+
the _\@eslint/markdown_ plugin and the rule:
|
|
1339
|
+
|
|
1340
|
+
```ts
|
|
1341
|
+
import header from "@tony.ganchev/eslint-plugin-header";
|
|
1342
|
+
import markdown from "@eslint/markdown";
|
|
1343
|
+
|
|
1344
|
+
export default [
|
|
1345
|
+
{
|
|
1346
|
+
files: ["**/*.md"],
|
|
1347
|
+
plugins: {
|
|
1348
|
+
"@tony.ganchev": header,
|
|
1349
|
+
markdown
|
|
1350
|
+
},
|
|
1351
|
+
// ... or "markdown/gfm"
|
|
1352
|
+
language: "markdown/commonmark",
|
|
1353
|
+
rules: {
|
|
1354
|
+
"@tony.ganchev/header": [
|
|
1355
|
+
"error",
|
|
1356
|
+
{
|
|
1357
|
+
header: {
|
|
1358
|
+
commentType: "block",
|
|
1359
|
+
lines: [" Copyright 2025 "]
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
]
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
];
|
|
1366
|
+
```
|
|
1367
|
+
|
|
1368
|
+
```md
|
|
1369
|
+
<!-- Copyright 2025 -->
|
|
1370
|
+
|
|
1371
|
+
# Title
|
|
1372
|
+
|
|
1373
|
+
## Subtitle
|
|
1374
|
+
|
|
1375
|
+
## Code
|
|
1376
|
+
|
|
1377
|
+
```js
|
|
1378
|
+
console.log("Hello, world!");
|
|
1379
|
+
```
|
|
1380
|
+
```
|
|
1381
|
+
|
|
1382
|
+
Note that if you have configured header for `*.js` files, the linter would fail
|
|
1383
|
+
on the first line of the nested JavaScript snippet. Look up how to differentiate
|
|
1384
|
+
the configuration of JavaScript sources (`**/*.js`) from JavaScript snippets in
|
|
1385
|
+
Markdown (`**/*.md/*.js`). Same applies to `*.ts`, `*.jsx`, `*.tsx`, etc.
|
|
1386
|
+
|
|
1387
|
+
As with CSS, only block comments are supported - no line- or shebang comments.
|
|
1388
|
+
|
|
1097
1389
|
## Comparison to Alternatives
|
|
1098
1390
|
|
|
1099
1391
|
A number of projects have been aiming to solve problems similar to
|
package/lib/comment-parser.js
CHANGED
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
|
|
27
27
|
const assert = require("node:assert");
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @import { CommentType, Language } from './rules/header'
|
|
31
|
+
*/
|
|
32
|
+
|
|
29
33
|
/**
|
|
30
34
|
* Parses a line or block comment and returns the type of comment and an array
|
|
31
35
|
* of content lines.
|
|
@@ -33,24 +37,34 @@ const assert = require("node:assert");
|
|
|
33
37
|
* This is a really simple and dumb parser, that looks just for a
|
|
34
38
|
* single kind of comment. It won't detect multiple block comments.
|
|
35
39
|
* @param {string} commentText Content to parse.
|
|
36
|
-
* @
|
|
37
|
-
*
|
|
40
|
+
* @param {Language} language The language
|
|
41
|
+
* configuration.
|
|
42
|
+
* @returns {[CommentType, string[]]} Comment type and
|
|
43
|
+
* content.
|
|
38
44
|
* @throws {Error} If `commentText` starts with an unrecognized comment token.
|
|
39
45
|
*/
|
|
40
|
-
module.exports = function commentParser(commentText) {
|
|
46
|
+
module.exports = function commentParser(commentText, language) {
|
|
41
47
|
assert.strictEqual(typeof commentText, "string");
|
|
48
|
+
assert.ok(language);
|
|
49
|
+
|
|
42
50
|
const text = commentText.trim();
|
|
51
|
+
const lc = language.lineComment;
|
|
52
|
+
const bc = language.blockComment;
|
|
43
53
|
|
|
44
|
-
if (text.startsWith(
|
|
54
|
+
if (lc && text.startsWith(lc.startDelimiter)) {
|
|
45
55
|
return [
|
|
46
56
|
"line",
|
|
47
|
-
text.split(/\r?\n/).map((line) => line.substring(
|
|
57
|
+
text.split(/\r?\n/).map((line) => line.substring(lc.startDelimiter.length))
|
|
58
|
+
];
|
|
59
|
+
} else if (bc && text.startsWith(bc.startDelimiter) && text.endsWith(bc.endDelimiter)) {
|
|
60
|
+
return [
|
|
61
|
+
"block",
|
|
62
|
+
text.substring(bc.startDelimiter.length, text.length - bc.endDelimiter.length).split(/\r?\n/)
|
|
48
63
|
];
|
|
49
|
-
} else if (text.startsWith("/*") && text.endsWith("*/")) {
|
|
50
|
-
return ["block", text.substring(2, text.length - 2).split(/\r?\n/)];
|
|
51
64
|
} else {
|
|
52
65
|
throw new Error(
|
|
53
|
-
"Could not parse comment file: the file must contain
|
|
54
|
-
|
|
66
|
+
"Could not parse comment file: the file must contain a comment " +
|
|
67
|
+
"that matches the supplied language delimiters."
|
|
68
|
+
);
|
|
55
69
|
}
|
|
56
70
|
};
|