@tony.ganchev/eslint-plugin-header 3.3.4 → 3.4.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 +287 -14
- package/lib/comment-parser.js +23 -9
- package/lib/rules/header.js +369 -220
- package/package.json +24 -9
- 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
|
@@ -7,13 +7,17 @@
|
|
|
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, Vue, 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
16
|
2. [Major Consumers](#major-consumers)
|
|
16
17
|
3. [Compatibility](#compatibility)
|
|
18
|
+
1. [Runtimes](#runtimes)
|
|
19
|
+
2. [Configuration Formats](#configuration-formats)
|
|
20
|
+
3. [Languages](#languages)
|
|
17
21
|
4. [Usage](#usage)
|
|
18
22
|
1. [File-based Configuration](#file-based-configuration)
|
|
19
23
|
2. [Inline Configuration](#inline-configuration)
|
|
@@ -24,10 +28,15 @@ and banner comments in JavaScript and TypeScript files. Supports _oxlint_.
|
|
|
24
28
|
3. [Support for Leading Comments](#support-for-leading-comments)
|
|
25
29
|
1. [Notes on Behavior](#notes-on-behavior)
|
|
26
30
|
4. [Examples](#examples)
|
|
31
|
+
5. [Linting CSS](#linting-css)
|
|
32
|
+
6. [Linting HTML](#linting-html)
|
|
33
|
+
7. [Linting Vue](#linting-vue)
|
|
34
|
+
8. [Linting Markdown](#linting-markdown)
|
|
27
35
|
5. [Comparison to Alternatives](#comparison-to-alternatives)
|
|
28
36
|
1. [Compared to eslint-plugin-headers](#compared-to-eslint-plugin-headers)
|
|
29
37
|
1. [Health Scans](#health-scans)
|
|
30
38
|
2. [Compared to eslint-plugin-license-header](#compared-to-eslint-plugin-license-header)
|
|
39
|
+
3. [Compared to eslint-plugin-notice](#compared-to-eslint-plugin-notice)
|
|
31
40
|
6. [Versioning](#versioning)
|
|
32
41
|
1. [What is a Feature?](#what-is-a-feature)
|
|
33
42
|
2. [What is Backward-compatibility?](#what-is-backward-compatibility)
|
|
@@ -88,6 +97,8 @@ consistent header structures. Notable adopters include:
|
|
|
88
97
|
|
|
89
98
|
[](./docs/consumers.md#mysten-labs)
|
|
90
99
|
|
|
100
|
+
[](./docs/consumers.md#suwayomi)
|
|
101
|
+
|
|
91
102
|
[](./docs/consumers.md#wire-swiss-gmbh)
|
|
92
103
|
|
|
93
104
|
[](./docs/consumers.md#wppconnect)
|
|
@@ -97,17 +108,46 @@ Learn more about how these organizations use the plugin on our
|
|
|
97
108
|
|
|
98
109
|
## Compatibility
|
|
99
110
|
|
|
111
|
+
### Runtimes
|
|
112
|
+
|
|
100
113
|
The plugin supports **ESLint 7 / 8 / 9 / 10**. Both **flat** config and legacy,
|
|
101
114
|
**hierarchical** config can be used. We have a smoke-test running to confirm the
|
|
102
|
-
plugin works with the latest version of ESLint.
|
|
115
|
+
plugin works with the latest version of ESLint. Certain features such as linting
|
|
116
|
+
copyright headers in CSS, HTML, or Markdown rely on APIs introduced with ESLint
|
|
117
|
+
9 and cannot be used with older ESLint versions.
|
|
103
118
|
|
|
104
119
|
The plugin works with latest version of **oxlint** too. We have a smoke-test
|
|
105
|
-
running to confirm the plugin works with the latest version of oxlint.
|
|
120
|
+
running to confirm the plugin works with the latest version of oxlint. Features
|
|
121
|
+
relying on the use of non-standard parsers such as linting headers in CSS, HTML,
|
|
122
|
+
Vue, or Markdown cannot be supported.
|
|
123
|
+
|
|
124
|
+
### Configuration Formats
|
|
125
|
+
|
|
126
|
+
The plugin supports hierarchical and flat configuration format for ESLint as
|
|
127
|
+
well as the configuration format for oxlint.
|
|
106
128
|
|
|
107
129
|
The NPM package provides TypeScript type definitions and can be used with
|
|
108
130
|
TypeScript-based ESLint flat configuration without the need for `@ts-ignore`
|
|
109
131
|
statements. Smoke tests cover this support as well.
|
|
110
132
|
|
|
133
|
+
### Languages
|
|
134
|
+
|
|
135
|
+
Currently the plugin supports linting copyright headers in JavaScript,
|
|
136
|
+
TypeScript and their JSX / TSX flavors; Vue, CSS, HTML, and Markdown files. As
|
|
137
|
+
mentioned in the previous sections, not all languages are supported for oxlint
|
|
138
|
+
or ESLint older than 9. Refer to the table below for more details.
|
|
139
|
+
|
|
140
|
+
| Language | ESLint 7 / 8 | ESLint 9 / 10 | oxlint |
|
|
141
|
+
|------------|---------------|---------------|--------|
|
|
142
|
+
| JavaScript | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
143
|
+
| TypeScript | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
144
|
+
| JSX | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
145
|
+
| TSX | ✅ Yes | ✅ Yes | ✅ Yes |
|
|
146
|
+
| Vue | ✅ Yes | ✅ Yes | ❌ No |
|
|
147
|
+
| CSS | ❌ No | ✅ Yes | ❌ No |
|
|
148
|
+
| HTML | ❌ No | ✅ Yes | ❌ No |
|
|
149
|
+
| Markdown | ❌ No | ✅ Yes | ❌ No |
|
|
150
|
+
|
|
111
151
|
## Usage
|
|
112
152
|
|
|
113
153
|
The plugin and its _header_ rule goes through evolution of its configuration in
|
|
@@ -1146,10 +1186,55 @@ export default defineConfig([
|
|
|
1146
1186
|
]);
|
|
1147
1187
|
```
|
|
1148
1188
|
|
|
1189
|
+
### Linting CSS
|
|
1190
|
+
|
|
1191
|
+
The rule supports validating and auto-fixing headers in CSS files. To
|
|
1192
|
+
use the plugin with these file types, you need to configure the official
|
|
1193
|
+
`@eslint/css` plugin.
|
|
1194
|
+
|
|
1195
|
+
**Note: the plugin does not support SCSS** as no current popular parser for
|
|
1196
|
+
ESLint supports SCSS / LESS that being a prerequisite for this plugin to be
|
|
1197
|
+
called. It is possible to rely on a dummy pass-through parser to ensure the SCSS
|
|
1198
|
+
/ LESS sources simply reach the rule but as of the time of the publisihng of
|
|
1199
|
+
this document we have not tested this approach.
|
|
1200
|
+
|
|
1201
|
+
Back to CSS, let us use the following configuration:
|
|
1202
|
+
|
|
1203
|
+
_eslint.config.js_:
|
|
1204
|
+
|
|
1149
1205
|
```js
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1206
|
+
import header from "@tony.ganchev/eslint-plugin-header";
|
|
1207
|
+
import css from "@eslint/css";
|
|
1208
|
+
|
|
1209
|
+
export default [
|
|
1210
|
+
{
|
|
1211
|
+
files: ["**/*.css"],
|
|
1212
|
+
plugins: {
|
|
1213
|
+
"@tony.ganchev": header,
|
|
1214
|
+
css
|
|
1215
|
+
},
|
|
1216
|
+
language: "css/css",
|
|
1217
|
+
rules: {
|
|
1218
|
+
"@tony.ganchev/header": [
|
|
1219
|
+
"error",
|
|
1220
|
+
{
|
|
1221
|
+
header: {
|
|
1222
|
+
commentType: "block",
|
|
1223
|
+
lines: [" Copyright 2025 "]
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
]
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
];
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
```css
|
|
1233
|
+
/* Copyright 2025 */
|
|
1234
|
+
|
|
1235
|
+
.foo {
|
|
1236
|
+
color: blue;
|
|
1237
|
+
}
|
|
1153
1238
|
```
|
|
1154
1239
|
|
|
1155
1240
|
With more decoration:
|
|
@@ -1184,14 +1269,174 @@ export default defineConfig([
|
|
|
1184
1269
|
]);
|
|
1185
1270
|
```
|
|
1186
1271
|
|
|
1187
|
-
```
|
|
1272
|
+
```css
|
|
1188
1273
|
/*************************
|
|
1189
1274
|
* Copyright 2015
|
|
1190
1275
|
* My Company
|
|
1191
1276
|
*************************/
|
|
1192
|
-
|
|
1277
|
+
|
|
1278
|
+
.foo {
|
|
1279
|
+
color: blue
|
|
1280
|
+
}
|
|
1281
|
+
```
|
|
1282
|
+
|
|
1283
|
+
As you can expect with CSS syntax, line comments and shebangs are not supported.
|
|
1284
|
+
All other features of the rule remain the same.
|
|
1285
|
+
|
|
1286
|
+
### Linting HTML
|
|
1287
|
+
|
|
1288
|
+
The rule supports linting copyright notices in HTML files. The rule works with
|
|
1289
|
+
the _@html-eslint/eslint-plugin_ plugin and its parser.
|
|
1290
|
+
|
|
1291
|
+
Similar to CSS, all you need to do to turn on header validation is to configure
|
|
1292
|
+
the _\@html-eslint/eslint-plugin_ plugin and the rule:
|
|
1293
|
+
|
|
1294
|
+
```ts
|
|
1295
|
+
import header from "@tony.ganchev/eslint-plugin-header";
|
|
1296
|
+
import html from "@html-eslint/eslint-plugin";
|
|
1297
|
+
|
|
1298
|
+
export default [
|
|
1299
|
+
{
|
|
1300
|
+
files: ["**/*.html"],
|
|
1301
|
+
plugins: {
|
|
1302
|
+
"@tony.ganchev": header,
|
|
1303
|
+
html
|
|
1304
|
+
},
|
|
1305
|
+
language: "html/html",
|
|
1306
|
+
rules: {
|
|
1307
|
+
"@tony.ganchev/header": [
|
|
1308
|
+
"error",
|
|
1309
|
+
{
|
|
1310
|
+
header: {
|
|
1311
|
+
commentType: "block",
|
|
1312
|
+
lines: [" Copyright 2025 "]
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
]
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
];
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
```html
|
|
1322
|
+
<!-- Copyright 2025 -->
|
|
1323
|
+
|
|
1324
|
+
<html>
|
|
1325
|
+
<body>
|
|
1326
|
+
<h1>Hello, world!</h1>
|
|
1327
|
+
<p>Lorem ipsum dolor.</p>
|
|
1328
|
+
</body>
|
|
1329
|
+
</html>
|
|
1330
|
+
```
|
|
1331
|
+
|
|
1332
|
+
As with CSS, only block comments are supported - no line- or shebang comments.
|
|
1333
|
+
|
|
1334
|
+
### Linting Vue
|
|
1335
|
+
|
|
1336
|
+
The rule supports linting copyright notices in Vue files. The rule works with
|
|
1337
|
+
the _eslint-plugin-vue_ plugin and its parser.
|
|
1338
|
+
|
|
1339
|
+
To turn on header validation for Vue files, configure the parser, the plugin,
|
|
1340
|
+
and the rule:
|
|
1341
|
+
|
|
1342
|
+
```ts
|
|
1343
|
+
import header from "@tony.ganchev/eslint-plugin-header";
|
|
1344
|
+
import vueParser from "vue-eslint-parser";
|
|
1345
|
+
import vuePlugin from "eslint-plugin-vue";
|
|
1346
|
+
|
|
1347
|
+
export default [
|
|
1348
|
+
{
|
|
1349
|
+
files: ["**/*.vue"],
|
|
1350
|
+
plugins: {
|
|
1351
|
+
"@tony.ganchev": header,
|
|
1352
|
+
vue: vuePlugin
|
|
1353
|
+
},
|
|
1354
|
+
languageOptions: {
|
|
1355
|
+
parser: vueParser
|
|
1356
|
+
},
|
|
1357
|
+
rules: {
|
|
1358
|
+
"@tony.ganchev/header": [
|
|
1359
|
+
"error",
|
|
1360
|
+
{
|
|
1361
|
+
header: {
|
|
1362
|
+
commentType: "block",
|
|
1363
|
+
lines: [" Copyright 2025 "]
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
]
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
];
|
|
1370
|
+
```
|
|
1371
|
+
|
|
1372
|
+
```vue
|
|
1373
|
+
<!-- Copyright 2025 -->
|
|
1374
|
+
<template>
|
|
1375
|
+
<div>Hello, world!</div>
|
|
1376
|
+
</template>
|
|
1377
|
+
```
|
|
1378
|
+
|
|
1379
|
+
As with HTML and CSS, only block comments are supported at the top of the file -
|
|
1380
|
+
no line- or shebang comments.
|
|
1381
|
+
|
|
1382
|
+
### Linting Markdown
|
|
1383
|
+
|
|
1384
|
+
The rule supports copyright comments in Markdown syntax in both _commonmark_ and
|
|
1385
|
+
_gfm_ flavors using the _\@eslint/markdown_ plugin and parser. Only HTML
|
|
1386
|
+
comments are supported - no anchor hacks or similar are accepted.
|
|
1387
|
+
|
|
1388
|
+
Similar to CSS, all you need to do to turn on header validation is to configure
|
|
1389
|
+
the _\@eslint/markdown_ plugin and the rule:
|
|
1390
|
+
|
|
1391
|
+
```ts
|
|
1392
|
+
import header from "@tony.ganchev/eslint-plugin-header";
|
|
1393
|
+
import markdown from "@eslint/markdown";
|
|
1394
|
+
|
|
1395
|
+
export default [
|
|
1396
|
+
{
|
|
1397
|
+
files: ["**/*.md"],
|
|
1398
|
+
plugins: {
|
|
1399
|
+
"@tony.ganchev": header,
|
|
1400
|
+
markdown
|
|
1401
|
+
},
|
|
1402
|
+
// ... or "markdown/gfm"
|
|
1403
|
+
language: "markdown/commonmark",
|
|
1404
|
+
rules: {
|
|
1405
|
+
"@tony.ganchev/header": [
|
|
1406
|
+
"error",
|
|
1407
|
+
{
|
|
1408
|
+
header: {
|
|
1409
|
+
commentType: "block",
|
|
1410
|
+
lines: [" Copyright 2025 "]
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
]
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
];
|
|
1193
1417
|
```
|
|
1194
1418
|
|
|
1419
|
+
```md
|
|
1420
|
+
<!-- Copyright 2025 -->
|
|
1421
|
+
|
|
1422
|
+
# Title
|
|
1423
|
+
|
|
1424
|
+
## Subtitle
|
|
1425
|
+
|
|
1426
|
+
## Code
|
|
1427
|
+
|
|
1428
|
+
```js
|
|
1429
|
+
console.log("Hello, world!");
|
|
1430
|
+
```
|
|
1431
|
+
```
|
|
1432
|
+
|
|
1433
|
+
Note that if you have configured header for `*.js` files, the linter would fail
|
|
1434
|
+
on the first line of the nested JavaScript snippet. Look up how to differentiate
|
|
1435
|
+
the configuration of JavaScript sources (`**/*.js`) from JavaScript snippets in
|
|
1436
|
+
Markdown (`**/*.md/*.js`). Same applies to `*.ts`, `*.jsx`, `*.tsx`, etc.
|
|
1437
|
+
|
|
1438
|
+
As with CSS, only block comments are supported - no line- or shebang comments.
|
|
1439
|
+
|
|
1195
1440
|
## Comparison to Alternatives
|
|
1196
1441
|
|
|
1197
1442
|
A number of projects have been aiming to solve problems similar to
|
|
@@ -1209,12 +1454,16 @@ _eslint-plugin-header_ and all plugins that already use the latter can migrate
|
|
|
1209
1454
|
to the fork right away. At the same time, it provides improved user experience
|
|
1210
1455
|
and windows support.
|
|
1211
1456
|
|
|
1212
|
-
|
|
1213
|
-
features
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1457
|
+
_eslint-plugin-headers_ is not a drop-in replacement. It offers additional
|
|
1458
|
+
features that are not first-level use-cases for
|
|
1459
|
+
_\@tony.ganchev/eslint-plugin-header_. One example is support for `{year}`
|
|
1460
|
+
variable placeholders which are redundant with ESLint's JavaScript-based
|
|
1461
|
+
configuration as [already pointed out in this document](#providing-to-year-in-auto-fix).
|
|
1462
|
+
JSDoc support can be achieved with regular expressions and the overall
|
|
1463
|
+
configuration capabilities of _\@tony.ganchev/eslint-plugin-header_. It is worth
|
|
1464
|
+
noting that the source code of _\@tony.ganchev/eslint-plugin-header_ already
|
|
1465
|
+
uses JSDoc-style comments for its own header which are in turn validated using
|
|
1466
|
+
_\@tony.ganchev/eslint-plugin-header/header_ rule.
|
|
1218
1467
|
|
|
1219
1468
|
The configuration format philosophy of the two plugin differs.
|
|
1220
1469
|
_\@tony.ganchev/eslint-plugin-header_ supports both the legacy model inherited
|
|
@@ -1281,6 +1530,30 @@ We have prepared a detailed
|
|
|
1281
1530
|
[migration guide](docs/migrate-from-license-header.md) for anyone eager to
|
|
1282
1531
|
migrate to _\@tony.ganchev/eslint-plugin-header_.
|
|
1283
1532
|
|
|
1533
|
+
### Compared to [eslint-plugin-notice](https://github.com/earl-man/eslint-plugin-notice)
|
|
1534
|
+
|
|
1535
|
+
_eslint-plugin-notice_ is another alternative that uses a template-based approach
|
|
1536
|
+
(powered by Lodash templates) to manage headers. This makes it quite powerful for
|
|
1537
|
+
dynamic content but also brings in more dependencies and a more complex
|
|
1538
|
+
configuration schema that doesn't always feel "native" to the new ESLint Flat
|
|
1539
|
+
Config era.
|
|
1540
|
+
|
|
1541
|
+
Key differences:
|
|
1542
|
+
|
|
1543
|
+
- **Philosophy**: _\@tony.ganchev/eslint-plugin-header_ focuses on a zero-bloat,
|
|
1544
|
+
native ESLint feel with first-class support for Flat Config and TypeScript.
|
|
1545
|
+
- **ESLint 9/10**: Our plugin is built from the ground up to support the latest
|
|
1546
|
+
ESLint versions and their core features.
|
|
1547
|
+
- **Languages**: We provide native support for linting headers in HTML, CSS,
|
|
1548
|
+
and Markdown via their respective ESLint ecosystem plugins.
|
|
1549
|
+
- **Simplicity**: No need for external template engines or complex variable
|
|
1550
|
+
mappings. Use standard JavaScript template literals in your `eslint.config.ts`
|
|
1551
|
+
to handle dynamic years or other variables.
|
|
1552
|
+
|
|
1553
|
+
We have prepared a detailed
|
|
1554
|
+
[migration guide](docs/migrate-from-notice.md) for anyone eager to
|
|
1555
|
+
migrate to _\@tony.ganchev/eslint-plugin-header_.
|
|
1556
|
+
|
|
1284
1557
|
## Versioning
|
|
1285
1558
|
|
|
1286
1559
|
The project follows standard [NPM semantic versioning policy](
|
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
|
};
|