@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 CHANGED
@@ -2,18 +2,23 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@tony.ganchev/eslint-plugin-header.svg)](https://www.npmjs.com/package/@tony.ganchev/eslint-plugin-header)
4
4
  [![Downloads/month](https://img.shields.io/npm/dm/@tony.ganchev/eslint-plugin-header.svg)](http://www.npmtrends.com/@tony.ganchev/eslint-plugin-header)
5
- [![Build Status](https://github.com/tonyganchev/eslint-plugin-header/workflows/Test/badge.svg)](https://github.com/tonyganchev/eslint-plugin-header)
5
+ [![Build Status](https://github.com/tonyganchev/eslint-plugin-header/actions/workflows/test.yml/badge.svg)](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 TypeScript files.
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. [Compatibility](#compatibility)
16
- 3. [Usage](#usage)
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
- 4. [Comparison to Alternatives](#comparison-to-alternatives)
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
- 5. [Versioning](#versioning)
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
- 6. [License](#license)
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
+ [![Microsoft](https://github.com/microsoft.png?size=48)](./docs/consumers.md#microsoft)
73
+    
74
+ [![Microsoft Azure](https://github.com/azure.png?size=48)](./docs/consumers.md#azure)
75
+    
76
+ [![Salesforce](https://github.com/forcedotcom.png?size=48)](./docs/consumers.md#salesforce)
77
+    
78
+ [![Angular](https://github.com/angular.png?size=48)](./docs/consumers.md#angular)
79
+    
80
+ [![Amazon](https://github.com/aws.png?size=48)](./docs/consumers.md#amazon)
81
+    
82
+ [![Amazon Cloudscape Design System](https://github.com/cloudscape-design.png?size=48)](./docs/consumers.md#cloudscape-design-system)
83
+    
84
+ [![Eclipse GLSP](https://github.com/eclipse.png?size=48)](./docs/consumers.md#eclipse-foundation)
85
+    
86
+ [![Salto](https://github.com/salto-io.png?size=48)](./docs/consumers.md#salto)
87
+    
88
+ [![Dash0 OpenTelemetry JS Distribution](https://github.com/dash0hq.png?size=48)](./docs/consumers.md#dash0)
89
+    
90
+ [![IBM InspectorRAGet](https://github.com/ibm.png?size=48)](./docs/consumers.md#ibm)
91
+    
92
+ [![FlowCrypt Browser Extensions](https://github.com/flowcrypt.png?size=48)](./docs/consumers.md#flowcrypt)
93
+    
94
+ [![Cratis](https://github.com/Cratis.png?size=48)](./docs/consumers.md#cratis)
95
+    
96
+ [![Mysten Labs](https://github.com/MystenLabs.png?size=48)](./docs/consumers.md#mysten-labs)
97
+    
98
+ [![Suwayomi](https://github.com/Suwayomi.png?size=48)](./docs/consumers.md#suwayomi)
99
+    
100
+ [![Wire Swiss GmbH](https://github.com/wireapp.png?size=48)](./docs/consumers.md#wire-swiss-gmbh)
101
+    
102
+ [![WPPConnect](https://github.com/wppconnect-team.png?size=48)](./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
- //Copyright 2017
1053
- //My Company
1054
- console.log(1)
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
- ```js
1269
+ ```css
1090
1270
  /*************************
1091
1271
  * Copyright 2015
1092
1272
  * My Company
1093
1273
  *************************/
1094
- console.log(1);
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
@@ -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
- * @returns {[import("./rules/header").CommentType, string[]]} Comment type and
37
- * comment content broken into lines.
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(2))
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 either just line comments (//) or a single block " +
54
- "comment (/* ... */)");
66
+ "Could not parse comment file: the file must contain a comment " +
67
+ "that matches the supplied language delimiters."
68
+ );
55
69
  }
56
70
  };