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

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
@@ -10,17 +10,18 @@ defined in the rule settings.
10
10
  ## Table of Contents
11
11
 
12
12
  1. [Scope and Acknowledgements](#scope-and-acknowledgements)
13
- 2. [Usage](#usage)
13
+ 2. [Compatibility](#compatibility)
14
+ 3. [Usage](#usage)
14
15
  1. [File-based Configuration](#file-based-configuration)
15
16
  2. [Inline Configuration](#inline-configuration)
16
17
  1. [Header Contents Configuration](#header-contents-configuration)
17
18
  2. [Trailing Empty Lines Configuration](#trailing-empty-lines-configuration)
18
19
  3. [Line Endings](#line-endings)
19
- 3. [Examples](#examples)
20
- 4. [Versioning](#versioning)
20
+ 4. [Examples](#examples)
21
+ 5. [Versioning](#versioning)
21
22
  1. [What is a Feature?](#what-is-a-feature)
22
23
  2. [What is Backward-compatibility?](#what-is-backward-compatibility)
23
- 5. [License](#license)
24
+ 6. [License](#license)
24
25
 
25
26
  ## Scope and Acknowledgements
26
27
 
@@ -39,6 +40,15 @@ It addresses the following issus:
39
40
  forward. This would come at the expense of plugin compatibility and the
40
41
  portability of fixes to the upstream repository.
41
42
 
43
+ ## Compatibility
44
+
45
+ The plugin supports ESLint 7 / 8 / 9 / 10rc0 (check package.json for details).
46
+ Both flat config and legacy, hierarchical config can be used.
47
+
48
+ The NPM package provides TypeScript type definitions and can be used with
49
+ TypeScript-based ESLint flat configuration without the need for `@ts-ignore`
50
+ statements.
51
+
42
52
  ## Usage
43
53
 
44
54
  This rule takes between 1 and 4 arguments after the rule validation severity.
@@ -61,6 +71,12 @@ The configuration can take any of the following forms:
61
71
  {<settings>}]` - define the header contents inline and an expected number of
62
72
  empty lines after the header and pass additional settings.
63
73
 
74
+ For TypesScript-based flat ESLint configuration, the following type is provided:
75
+
76
+ - `HeaderRuleConfig` defines the overall rule configuration for the `header`
77
+ rule and includes severity level and supports both the modern object-based
78
+ configuration and the legacy array-based configuration.
79
+
64
80
  ### File-based Configuration
65
81
 
66
82
  In this configuration mode, the first argument is a string pointing to a JS
@@ -440,7 +456,7 @@ The following guidelines apply:
440
456
  - **major versions** - new functionality that breaks compatibility.
441
457
  - **minor versions** - new features that do not break compatibility. For the
442
458
  most part we would aim to continue releasing new versions in the 3.x product
443
- line and have opt-in flags for changes in behavior of existign features.
459
+ line and have opt-in flags for changes in behavior of existing features.
444
460
  - **revisions** - bugfixes and minor non-feature improvements that do not break
445
461
  compatibility. Note that bug-fixes are allowed to break compatibility with
446
462
  previous version if the older version regressed previous expected behavior.
package/index.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /*
2
+ * MIT License
3
+ *
4
+ * Copyright (c) 2026-present Tony Ganchev and contributors
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the “Software”), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ * SOFTWARE.
23
+ */
24
+
25
+ export { HeaderOptions, HeaderRuleConfig } from "./types/lib/rules/header";
26
+
27
+ import plugin = require("./types");
28
+
29
+ export default plugin;
package/index.js CHANGED
@@ -24,11 +24,13 @@
24
24
 
25
25
  "use strict";
26
26
 
27
- module.exports = {
27
+ const { header } = require("./lib/rules/header");
28
+
29
+ /** @type {import('eslint').ESLint.Plugin} */
30
+ const pluginDefinition = {
28
31
  rules: {
29
- "header": require("./lib/rules/header")
30
- },
31
- rulesConfig: {
32
- "header": 0
32
+ header
33
33
  }
34
34
  };
35
+
36
+ module.exports = pluginDefinition;
@@ -24,7 +24,7 @@
24
24
 
25
25
  "use strict";
26
26
 
27
- const assert = require("assert");
27
+ const assert = require("node:assert");
28
28
 
29
29
  /**
30
30
  * Parses a line or block comment and returns the type of comment and an array
@@ -0,0 +1,42 @@
1
+ /*
2
+ * MIT License
3
+ *
4
+ * Copyright (c) 2025-present Tony Ganchev and contributors
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the “Software”), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ * SOFTWARE.
23
+ */
24
+
25
+ "use strict";
26
+
27
+ /**
28
+ * @typedef {import('eslint').Rule.RuleContext} RuleContext
29
+ * @typedef {import('eslint').SourceCode} SourceCode
30
+ */
31
+
32
+ module.exports = {
33
+ /**
34
+ * Provides compatibility wrapper for ESLint 7 through 10 for getting the
35
+ * full source code object from the execution context.
36
+ * @param {RuleContext} context ESLint execution context.
37
+ * @returns {SourceCode} the source-code object.
38
+ */
39
+ contextSourceCode: function(context) {
40
+ return context.sourceCode || context.getSourceCode();
41
+ }
42
+ };
@@ -29,11 +29,11 @@ const assert = require("node:assert");
29
29
  const fs = require("node:fs");
30
30
  const path = require("node:path");
31
31
 
32
- const packageJsonContent = fs.readFileSync(path.resolve(__dirname, "../../package.json"));
32
+ const packageJsonContent = fs.readFileSync(path.resolve(__dirname, "../../package.json"), "utf8");
33
33
  const packageJson = JSON.parse(packageJsonContent);
34
34
  assert.equal(Object.prototype.hasOwnProperty.call(packageJson, "version"), true,
35
35
  "The plugin's package.json should be available two directories above the rule.");
36
- const pluginVersion = packageJsonContent.version;
36
+ const pluginVersion = packageJson.version;
37
37
 
38
38
  exports.description = "";
39
39
  exports.recommended = true;
@@ -24,10 +24,11 @@
24
24
 
25
25
  "use strict";
26
26
 
27
- const assert = require("assert");
28
- const fs = require("fs");
29
- const os = require("os");
27
+ const assert = require("node:assert");
28
+ const fs = require("node:fs");
29
+ const os = require("node:os");
30
30
  const commentParser = require("../comment-parser");
31
+ const { contextSourceCode } = require("./eslint-utils");
31
32
  const { description, recommended, url } = require("./header.docs");
32
33
  const { commentTypeOptions, lineEndingOptions, schema } = require("./header.schema");
33
34
 
@@ -37,8 +38,6 @@ const { commentTypeOptions, lineEndingOptions, schema } = require("./header.sche
37
38
  * @typedef {import('eslint').Rule.NodeListener} NodeListener
38
39
  * @typedef {import('eslint').Rule.ReportFixer} ReportFixer
39
40
  * @typedef {import('eslint').Rule.RuleFixer} RuleFixer
40
- * @typedef {import('eslint').Rule.RuleTextEdit} RuleTextEdit
41
- * @typedef {import('eslint').Rule.RuleTextEditor} RuleTextEditor
42
41
  * @typedef {import('eslint').Rule.RuleContext} RuleContext
43
42
  * @typedef {import('estree').Comment} Comment
44
43
  * @typedef {import('estree').Program} Program
@@ -46,26 +45,36 @@ const { commentTypeOptions, lineEndingOptions, schema } = require("./header.sche
46
45
  */
47
46
 
48
47
  /**
49
- * Local type defintions.
50
- * @typedef {string | { pattern: string, template?: string }} HeaderLine
48
+ * Local type definitions.
49
+ * @typedef {{ pattern: string, template?: string }} HeaderLinePattern
50
+ * @typedef {string | HeaderLinePattern} HeaderLine
51
51
  * @typedef {(HeaderLine | HeaderLine[])} HeaderLines
52
- * @typedef {{ lineEndings: ('unix' | 'windows') }} HeaderSettings
53
- * @typedef {
54
- * [string]
55
- * | [string, HeaderSettings]
56
- * | [('block' | 'line') | HeaderLines ]
57
- * | [('block' | 'line') | HeaderLines | HeaderSettings]
58
- * | [('block' | 'line') | HeaderLines | number ]
59
- * | [('block' | 'line') | HeaderLines | number | HeaderSettings]
60
- * } HeaderOptions
52
+ * @typedef {'unix' | 'windows'} LineEndingOption
53
+ * @typedef {{ lineEndings?: LineEndingOption }} HeaderSettings
54
+ * @typedef {'block' | 'line'} CommentType
55
+ * @typedef {[template: string] |
56
+ * [template: string, settings: HeaderSettings] |
57
+ * [type: CommentType, lines: HeaderLines] |
58
+ * [type: CommentType, lines: HeaderLines, settings: HeaderSettings] |
59
+ * [type: CommentType, lines: HeaderLines, minLines: number] |
60
+ * [
61
+ * type: CommentType,
62
+ * lines: HeaderLines,
63
+ * minLines: number,
64
+ * settings: HeaderSettings
65
+ * ]
66
+ * } AllHeaderOptions
67
+ * @typedef {import('eslint').Linter.RuleEntry<AllHeaderOptions>
68
+ * } HeaderRuleConfig
61
69
  */
62
70
 
63
71
  /**
64
72
  * Tests if the passed line configuration string or object is a pattern
65
73
  * definition.
66
74
  * @param {HeaderLine} object line configuration object or string
67
- * @returns {boolean} `true` if the line configuration is a pattern-defining
68
- * object or `false` otherwise.
75
+ * @returns {object is HeaderLinePattern} `true` if the line configuration is a
76
+ * pattern-defining object or `false`
77
+ * otherwise.
69
78
  */
70
79
  function isPattern(object) {
71
80
  return typeof object === "object" && Object.prototype.hasOwnProperty.call(object, "pattern");
@@ -74,13 +83,13 @@ function isPattern(object) {
74
83
  /**
75
84
  * Utility over a line config argument to match an expected string either
76
85
  * against a regex or for full match against a string.
77
- * @param {HeaderLine} actual the string to test.
78
- * @param {string} expected The string or regex to test again.
86
+ * @param {string} actual the string to test.
87
+ * @param {string | RegExp} expected The string or regex to test again.
79
88
  * @returns {boolean} `true` if the passed string matches the expected line
80
89
  * config or `false` otherwise.
81
90
  */
82
91
  function match(actual, expected) {
83
- if (expected.test) {
92
+ if (expected instanceof RegExp) {
84
93
  return expected.test(actual);
85
94
  } else {
86
95
  return expected === actual;
@@ -89,34 +98,62 @@ function match(actual, expected) {
89
98
 
90
99
  /**
91
100
  * Remove Unix she-bangs from the list of comments.
92
- * @param {Comment[]} comments the list of comment lines.
93
- * @returns {Comment[]} the list of comments with containing all incomming
101
+ * @param {(Comment | { type: "Shebang" })[]} comments the list of comment
102
+ * lines.
103
+ * @returns {Comment[]} the list of comments with containing all incoming
94
104
  * comments from `comments` with the shebang comments
95
105
  * omitted.
96
106
  */
97
107
  function excludeShebangs(comments) {
108
+ /** @type {Comment[]} */
98
109
  return comments.filter(function(comment) {
99
110
  return comment.type !== "Shebang";
100
111
  });
101
112
  }
102
113
 
114
+ /**
115
+ * TypeScript helper to confirm defined type.
116
+ * @template T
117
+ * @param {T | undefined} val the value to validate.
118
+ * @returns {asserts val is T} validates defined type
119
+ */
120
+ function assertDefined(val) {
121
+ assert.strict.notEqual(typeof val, "undefined");
122
+ }
123
+
124
+ /**
125
+ * TypeScript helper to confirm non-null type.
126
+ * @template T
127
+ * @param {T | null} val the value to validate.
128
+ * @returns {asserts val is T} validates non-null type
129
+ */
130
+ function assertNotNull(val) {
131
+ assert.strict.notEqual(val, null);
132
+ }
133
+
103
134
  /**
104
135
  * Returns either the first block comment or the first set of line comments that
105
136
  * are ONLY separated by a single newline. Note that this does not actually
106
137
  * check if they are at the start of the file since that is already checked by
107
138
  * `hasHeader()`.
108
139
  * @param {RuleContext} context ESLint execution environment.
109
- * @param {Program} node ESLint AST treee node being processed.
110
140
  * @returns {Comment[]} lines that constitute the leading comment.
111
141
  */
112
- function getLeadingComments(context, node) {
113
- const all = excludeShebangs(context.sourceCode.getAllComments(node.body.length ? node.body[0] : node));
142
+ function getLeadingComments(context) {
143
+ const sourceCode = contextSourceCode(context);
144
+ const all = excludeShebangs(sourceCode.getAllComments());
145
+ assert.ok(all);
146
+ assert.ok(all.length);
114
147
  if (all[0].type.toLowerCase() === commentTypeOptions.block) {
115
148
  return [all[0]];
116
149
  }
117
150
  let i = 1;
118
151
  for (; i < all.length; ++i) {
119
- const txt = context.sourceCode.text.slice(all[i - 1].range[1], all[i].range[0]);
152
+ const previousRange = all[i - 1].range;
153
+ assertDefined(previousRange);
154
+ const currentRange = all[i].range;
155
+ assertDefined(currentRange);
156
+ const txt = sourceCode.text.slice(previousRange[1], currentRange[0]);
120
157
  if (!txt.match(/^(\r\n|\r|\n)$/)) {
121
158
  break;
122
159
  }
@@ -127,7 +164,7 @@ function getLeadingComments(context, node) {
127
164
  /**
128
165
  * Generate a comment including trailing spaces out of a number of comment body
129
166
  * lines.
130
- * @param {'block' | 'line'} commentType the type of comment to generate.
167
+ * @param {CommentType} commentType the type of comment to generate.
131
168
  * @param {string[]} textArray list of lines of the comment content.
132
169
  * @param {'\n' | '\r\n'} eol end-of-line characters.
133
170
  * @returns {string} resulting comment.
@@ -145,12 +182,21 @@ function genCommentBody(commentType, textArray, eol) {
145
182
  /**
146
183
  * Determines the start and end position in the source code of the leading
147
184
  * comment.
148
- * @param {string[]} comments list of comments.
185
+ * @param {Comment[]} comments list of comments.
149
186
  * @returns {[number, number]} resulting range.
150
187
  */
151
188
  function genCommentsRange(comments) {
152
- const start = comments[0].range[0];
153
- const end = comments.slice(-1)[0].range[1];
189
+ assert.ok(comments.length);
190
+ const firstComment = comments[0];
191
+ assertDefined(firstComment);
192
+ const firstCommentRange = firstComment.range;
193
+ assertDefined(firstCommentRange);
194
+ const start = firstCommentRange[0];
195
+ const lastComment = comments.slice(-1)[0];
196
+ assertDefined(lastComment);
197
+ const lastCommentRange = lastComment.range;
198
+ assertDefined(lastCommentRange);
199
+ const end = lastCommentRange[1];
154
200
  return [start, end];
155
201
  }
156
202
 
@@ -176,7 +222,7 @@ function leadingEmptyLines(src) {
176
222
 
177
223
  /**
178
224
  * Factory for fixer that adds a missing header.
179
- * @param {'block' | 'line'} commentType type of comment to use.
225
+ * @param {CommentType} commentType type of comment to use.
180
226
  * @param {RuleContext} context ESLint execution runtime.
181
227
  * @param {string[]} headerLines lines of the header comment.
182
228
  * @param {'\n' | '\r\n'} eol end-of-line characters
@@ -186,15 +232,16 @@ function leadingEmptyLines(src) {
186
232
  function genPrependFixer(commentType, context, headerLines, eol, numNewlines) {
187
233
  return function(fixer) {
188
234
  let insertPos = 0;
189
- let newHeader = genCommentBody(commentType, headerLines, eol, numNewlines);
190
- if (context.sourceCode.text.startsWith("#!")) {
191
- const firstNewLinePos = context.sourceCode.text.indexOf("\n");
192
- insertPos = firstNewLinePos === -1 ? context.sourceCode.text.length : firstNewLinePos + 1;
235
+ let newHeader = genCommentBody(commentType, headerLines, eol);
236
+ const sourceCode = contextSourceCode(context);
237
+ if (sourceCode.text.startsWith("#!")) {
238
+ const firstNewLinePos = sourceCode.text.indexOf("\n");
239
+ insertPos = firstNewLinePos === -1 ? sourceCode.text.length : firstNewLinePos + 1;
193
240
  if (firstNewLinePos === -1) {
194
241
  newHeader = eol + newHeader;
195
242
  }
196
243
  }
197
- const numEmptyLines = leadingEmptyLines(context.sourceCode.text.substring(insertPos));
244
+ const numEmptyLines = leadingEmptyLines(sourceCode.text.substring(insertPos));
198
245
  const additionalEmptyLines = Math.max(0, numNewlines - numEmptyLines);
199
246
  newHeader += eol.repeat(additionalEmptyLines);
200
247
  return fixer.insertTextBeforeRange(
@@ -206,25 +253,23 @@ function genPrependFixer(commentType, context, headerLines, eol, numNewlines) {
206
253
 
207
254
  /**
208
255
  * Factory for fixer that replaces an incorrect header.
209
- * @param {'block' | 'line'} commentType type of comment to use.
256
+ * @param {CommentType} commentType type of comment to use.
210
257
  * @param {RuleContext} context ESLint execution context.
211
258
  * @param {Comment[]} leadingComments comment elements to replace.
212
259
  * @param {string[]} headerLines lines of the header comment.
213
260
  * @param {'\n' | '\r\n'} eol end-of-line characters
214
261
  * @param {number} numNewlines number of trailing lines after the comment.
215
- * @returns {
216
- * (fixer: RuleTextEditor) => RuleTextEdit | RuleTextEdit[] | null
217
- * } the fixer.
262
+ * @returns {(fixer: RuleFixer) => Fix | Fix[] | null} the fixer.
218
263
  */
219
264
  function genReplaceFixer(commentType, context, leadingComments, headerLines, eol, numNewlines) {
220
265
  return function(fixer) {
221
266
  const commentRange = genCommentsRange(leadingComments);
222
- const emptyLines = leadingEmptyLines(context.sourceCode.text.substring(commentRange[1]));
267
+ const emptyLines = leadingEmptyLines(contextSourceCode(context).text.substring(commentRange[1]));
223
268
  const missingNewlines = Math.max(0, numNewlines - emptyLines);
224
269
  const eols = eol.repeat(missingNewlines);
225
270
  return fixer.replaceTextRange(
226
271
  commentRange,
227
- genCommentBody(commentType, headerLines, eol, numNewlines) + eols
272
+ genCommentBody(commentType, headerLines, eol) + eols
228
273
  );
229
274
  };
230
275
  }
@@ -235,9 +280,7 @@ function genReplaceFixer(commentType, context, leadingComments, headerLines, eol
235
280
  * @param {'\n' | '\r\n'} eol end-of-line characters
236
281
  * @param {number} missingEmptyLinesCount number of trailing lines after the
237
282
  * comment.
238
- * @returns {
239
- * (fixer: RuleTextEditor) => RuleTextEdit | RuleTextEdit[] | null
240
- * } the fixer.
283
+ * @returns {(fixer: RuleFixer) => Fix | Fix[] | null} the fixer.
241
284
  */
242
285
  function genEmptyLinesFixer(leadingComments, eol, missingEmptyLinesCount) {
243
286
  return function(fixer) {
@@ -250,7 +293,7 @@ function genEmptyLinesFixer(leadingComments, eol, missingEmptyLinesCount) {
250
293
 
251
294
  /**
252
295
  * Finds the option parameter within the list of rule config options.
253
- * @param {HeaderOptions} options the config options passed to the rule.
296
+ * @param {AllHeaderOptions} options the config options passed to the rule.
254
297
  * @returns {HeaderSettings | null} the settings parameter or `null` if no such
255
298
  * is defined.
256
299
  */
@@ -258,7 +301,7 @@ function findSettings(options) {
258
301
  const lastOption = options[options.length - 1];
259
302
  if (typeof lastOption === "object" && !Array.isArray(lastOption) && lastOption !== null
260
303
  && !Object.prototype.hasOwnProperty.call(lastOption, "pattern")) {
261
- return lastOption;
304
+ return /** @type {HeaderSettings} */ (lastOption);
262
305
  }
263
306
  return null;
264
307
  }
@@ -266,7 +309,7 @@ function findSettings(options) {
266
309
  /**
267
310
  * Returns the used line-termination characters per the rule's config if any or
268
311
  * else based on the runtime environments.
269
- * @param {HeaderOptions} options rule configuration.
312
+ * @param {AllHeaderOptions} options rule configuration.
270
313
  * @returns {'\n' | '\r\n'} the correct line ending characters for the
271
314
  * environment.
272
315
  */
@@ -280,7 +323,7 @@ function getEOL(options) {
280
323
  return "\r\n";
281
324
  }
282
325
  }
283
- return os.EOL;
326
+ return /** @type {'\n' | '\r\n'} */ (os.EOL);
284
327
  }
285
328
 
286
329
  /**
@@ -308,7 +351,11 @@ function hasHeader(src) {
308
351
  * @returns {SourceLocation} the location (line and column) of the violation.
309
352
  */
310
353
  function missingEmptyLinesViolationLoc(leadingComments, actualEmptyLines) {
311
- const lastCommentLineLocEnd = leadingComments[leadingComments.length - 1].loc.end;
354
+ assert.ok(leadingComments);
355
+ const loc = leadingComments[leadingComments.length - 1].loc;
356
+ assertDefined(loc);
357
+ assertNotNull(loc);
358
+ const lastCommentLineLocEnd = loc.end;
312
359
  return {
313
360
  start: lastCommentLineLocEnd,
314
361
  end: {
@@ -318,7 +365,8 @@ function missingEmptyLinesViolationLoc(leadingComments, actualEmptyLines) {
318
365
  };
319
366
  }
320
367
 
321
- module.exports = {
368
+ /** @type {import('eslint').Rule.RuleModule} */
369
+ const headerRule = {
322
370
  meta: {
323
371
  type: "layout",
324
372
  docs: {
@@ -348,7 +396,7 @@ module.exports = {
348
396
  * @returns {NodeListener} the rule definition.
349
397
  */
350
398
  create: function(context) {
351
- let options = context.options;
399
+ let options = /** @type {AllHeaderOptions} */ (context.options);
352
400
  const numNewlines = options.length > 2 && typeof options[2] === "number" ? options[2] : 1;
353
401
  const eol = getEOL(options);
354
402
 
@@ -358,9 +406,10 @@ module.exports = {
358
406
  options = commentParser(text);
359
407
  }
360
408
 
361
- const commentType = options[0].toLowerCase();
362
- /** @type {(string | RegExp)[]} */
409
+ const commentType = /** @type {CommentType} */ (options[0].toLowerCase());
410
+ /** @type {(string | RegExp)[] | string[]} */
363
411
  let headerLines;
412
+ /** @type {string[]} */
364
413
  let fixLines = [];
365
414
  // If any of the lines are regular expressions, then we can't
366
415
  // automatically fix them. We set this to true below once we
@@ -371,34 +420,42 @@ module.exports = {
371
420
  headerLines = options[1].map(function(line) {
372
421
  const isRegex = isPattern(line);
373
422
  // Can only fix regex option if a template is also provided
374
- if (isRegex && !line.template) {
375
- canFix = false;
423
+ if (isRegex) {
424
+ if (line.template) {
425
+ fixLines.push(line.template);
426
+ } else {
427
+ canFix = false;
428
+ }
429
+ return new RegExp(line.pattern);
430
+ } else {
431
+ fixLines.push(line);
432
+ return line;
376
433
  }
377
- fixLines.push(line.template || line);
378
- return isRegex ? new RegExp(line.pattern) : line;
379
434
  });
380
- } else if (isPattern(options[1])) {
381
- const line = options[1];
382
- headerLines = [new RegExp(line.pattern)];
383
- fixLines.push(line.template || line);
384
- // Same as above for regex and template
385
- canFix = !!line.template;
386
435
  } else {
387
- canFix = true;
388
- headerLines = options[1].split(/\r?\n/);
389
- fixLines = headerLines;
436
+ const line = /** @type {HeaderLine} */ (options[1]);
437
+ if (isPattern(line)) {
438
+ headerLines = [new RegExp(line.pattern)];
439
+ fixLines.push(line.template || "");
440
+ // Same as above for regex and template
441
+ canFix = !!line.template;
442
+ } else {
443
+ canFix = true;
444
+ headerLines = line.split(/\r?\n/);
445
+ fixLines = /** @type {string[]} */ (headerLines);
446
+ }
390
447
  }
391
448
 
392
449
  return {
393
450
  /**
394
451
  * Hooks into the processing of the overall script node to do the
395
452
  * header validation.
396
- * @param {Program} node the whole script node
397
453
  * @returns {void}
398
454
  */
399
- Program: function(node) {
400
- if (!hasHeader(context.sourceCode.text)) {
401
- const hasShebang = context.sourceCode.text.startsWith("#!");
455
+ Program: function() {
456
+ const sourceCode = contextSourceCode(context);
457
+ if (!hasHeader(sourceCode.text)) {
458
+ const hasShebang = sourceCode.text.startsWith("#!");
402
459
  const line = hasShebang ? 2 : 1;
403
460
  context.report({
404
461
  loc: {
@@ -416,13 +473,22 @@ module.exports = {
416
473
  });
417
474
  return;
418
475
  }
419
- const leadingComments = getLeadingComments(context, node);
476
+ const leadingComments = getLeadingComments(context);
477
+ const firstLeadingCommentLoc = leadingComments[0].loc;
478
+ const firstLeadingCommentRange = leadingComments[0].range;
479
+ assertDefined(firstLeadingCommentRange);
480
+
481
+ const lastLeadingCommentLoc = leadingComments[leadingComments.length - 1].loc;
420
482
 
421
483
  if (leadingComments[0].type.toLowerCase() !== commentType) {
484
+ assertDefined(firstLeadingCommentLoc);
485
+ assertNotNull(firstLeadingCommentLoc);
486
+ assertDefined(lastLeadingCommentLoc);
487
+ assertNotNull(lastLeadingCommentLoc);
422
488
  context.report({
423
489
  loc: {
424
- start: leadingComments[0].loc.start,
425
- end: leadingComments[leadingComments.length - 1].loc.end
490
+ start: firstLeadingCommentLoc.start,
491
+ end: lastLeadingCommentLoc.end
426
492
  },
427
493
  messageId: "incorrectCommentType",
428
494
  data: {
@@ -441,10 +507,14 @@ module.exports = {
441
507
  !match(leadingCommentValues.join("\n"), headerLines[0])
442
508
  && !match(leadingCommentValues.join("\r\n"), headerLines[0])
443
509
  ) {
510
+ assertDefined(firstLeadingCommentLoc);
511
+ assertNotNull(firstLeadingCommentLoc);
512
+ assertDefined(lastLeadingCommentLoc);
513
+ assertNotNull(lastLeadingCommentLoc);
444
514
  context.report({
445
515
  loc: {
446
- start: leadingComments[0].loc.start,
447
- end: leadingComments[leadingComments.length - 1].loc.end
516
+ start: firstLeadingCommentLoc.start,
517
+ end: lastLeadingCommentLoc.end
448
518
  },
449
519
  messageId: "incorrectHeader",
450
520
  fix: canFix
@@ -456,9 +526,12 @@ module.exports = {
456
526
  } else {
457
527
  for (let i = 0; i < headerLines.length; i++) {
458
528
  if (leadingComments.length - 1 < i) {
529
+ assertDefined(lastLeadingCommentLoc);
530
+ assertNotNull(lastLeadingCommentLoc);
459
531
  context.report({
460
532
  loc: {
461
- start: leadingComments[leadingComments.length - 1].loc.end
533
+ start: lastLeadingCommentLoc.end,
534
+ end: lastLeadingCommentLoc.end
462
535
  },
463
536
  messageId: "headerTooShort",
464
537
  data: {
@@ -476,22 +549,27 @@ module.exports = {
476
549
  });
477
550
  return;
478
551
  }
479
- if (typeof headerLines[i] === "string") {
480
- const leadingCommentLength = leadingComments[i].value.length;
481
- const headerLineLength = headerLines[i].length;
552
+ const headerLine = headerLines[i];
553
+ const comment = leadingComments[i];
554
+ const commentLoc = comment.loc;
555
+ assertDefined(commentLoc);
556
+ assertNotNull(commentLoc);
557
+ if (typeof headerLine === "string") {
558
+ const leadingCommentLength = comment.value.length;
559
+ const headerLineLength = headerLine.length;
482
560
  for (let j = 0; j < Math.min(leadingCommentLength, headerLineLength); j++) {
483
- if (leadingComments[i].value[j] !== headerLines[i][j]) {
561
+ if (comment.value[j] !== headerLine[j]) {
484
562
  context.report({
485
563
  loc: {
486
564
  start: {
487
565
  column: "//".length + j,
488
- line: leadingComments[i].loc.start.line
566
+ line: commentLoc.start.line
489
567
  },
490
- end: leadingComments[i].loc.end
568
+ end: commentLoc.end
491
569
  },
492
570
  messageId: "headerLineMismatchAtPos",
493
571
  data: {
494
- expected: headerLines[i].substring(j)
572
+ expected: headerLine.substring(j)
495
573
  },
496
574
  fix: genReplaceFixer(
497
575
  commentType,
@@ -507,11 +585,12 @@ module.exports = {
507
585
  if (leadingCommentLength < headerLineLength) {
508
586
  context.report({
509
587
  loc: {
510
- start: leadingComments[i].loc.end,
588
+ start: commentLoc.end,
589
+ end: commentLoc.end,
511
590
  },
512
591
  messageId: "headerLineTooShort",
513
592
  data: {
514
- remainder: headerLines[i].substring(leadingCommentLength)
593
+ remainder: headerLine.substring(leadingCommentLength)
515
594
  },
516
595
  fix: canFix
517
596
  ? genReplaceFixer(
@@ -530,9 +609,9 @@ module.exports = {
530
609
  loc: {
531
610
  start: {
532
611
  column: "//".length + headerLineLength,
533
- line: leadingComments[i].loc.start.line
612
+ line: commentLoc.start.line
534
613
  },
535
- end: leadingComments[i].loc.end,
614
+ end: commentLoc.end,
536
615
  },
537
616
  messageId: "headerLineTooLong",
538
617
  fix: canFix
@@ -548,18 +627,18 @@ module.exports = {
548
627
  return;
549
628
  }
550
629
  } else {
551
- if (!match(leadingComments[i].value, headerLines[i])) {
630
+ if (!match(comment.value, headerLine)) {
552
631
  context.report({
553
632
  loc: {
554
633
  start: {
555
634
  column: "//".length,
556
- line: leadingComments[i].loc.start.line,
635
+ line: commentLoc.start.line,
557
636
  },
558
- end: leadingComments[i].loc.end,
637
+ end: commentLoc.end,
559
638
  },
560
639
  messageId: "incorrectHeaderLine",
561
640
  data: {
562
- pattern: headerLines[i]
641
+ pattern: headerLine
563
642
  },
564
643
  fix: canFix
565
644
  ? genReplaceFixer(
@@ -577,8 +656,9 @@ module.exports = {
577
656
  }
578
657
  }
579
658
 
580
- const actualLeadingEmptyLines = leadingEmptyLines(
581
- context.sourceCode.text.substring(leadingComments[headerLines.length - 1].range[1]));
659
+ const commentRange = leadingComments[headerLines.length - 1].range;
660
+ assertDefined(commentRange);
661
+ const actualLeadingEmptyLines = leadingEmptyLines(sourceCode.text.substring(commentRange[1]));
582
662
  const missingEmptyLines = numNewlines - actualLeadingEmptyLines;
583
663
  if (missingEmptyLines > 0) {
584
664
  context.report({
@@ -602,8 +682,8 @@ module.exports = {
602
682
 
603
683
  /** @type {null | string} */
604
684
  let errorMessageId = null;
605
- /** @type {null | Record<string, string | RegExp>} */
606
- let errorMessageData = null;
685
+ /** @type {undefined | Record<string, string | RegExp>} */
686
+ let errorMessageData;
607
687
  /** @type {null | SourceLocation} */
608
688
  let errorMessageLoc = null;
609
689
  for (let i = 0; i < headerLines.length; i++) {
@@ -614,7 +694,9 @@ module.exports = {
614
694
  if (leadingLine[j] !== headerLine[j]) {
615
695
  errorMessageId = "headerLineMismatchAtPos";
616
696
  const columnOffset = i === 0 ? "/*".length : 0;
617
- const line = leadingComments[0].loc.start.line + i;
697
+ assertDefined(firstLeadingCommentLoc);
698
+ assertNotNull(firstLeadingCommentLoc);
699
+ const line = firstLeadingCommentLoc.start.line + i;
618
700
  errorMessageLoc = {
619
701
  start: {
620
702
  column: columnOffset + j,
@@ -637,31 +719,35 @@ module.exports = {
637
719
  if (leadingLine.length < headerLine.length) {
638
720
  errorMessageId = "headerLineTooShort";
639
721
  const startColumn = (i === 0 ? "/*".length : 0) + leadingLine.length;
722
+ assertDefined(firstLeadingCommentLoc);
723
+ assertNotNull(firstLeadingCommentLoc);
640
724
  errorMessageLoc = {
641
725
  start: {
642
726
  column: startColumn,
643
- line: leadingComments[0].loc.start.line + i
727
+ line: firstLeadingCommentLoc.start.line + i
644
728
  },
645
729
  end: {
646
730
  column: startColumn + 1,
647
- line: leadingComments[0].loc.start.line + i
731
+ line: firstLeadingCommentLoc.start.line + i
648
732
  }
649
733
  };
650
734
  errorMessageData = {
651
- remainder: headerLines[i].substring(leadingLine.length)
735
+ remainder: headerLine.substring(leadingLine.length)
652
736
  };
653
737
  break;
654
738
  }
655
739
  if (leadingLine.length > headerLine.length) {
740
+ assertDefined(firstLeadingCommentLoc);
741
+ assertNotNull(firstLeadingCommentLoc);
656
742
  errorMessageId = "headerLineTooLong";
657
743
  errorMessageLoc = {
658
744
  start: {
659
745
  column: (i === 0 ? "/*".length : 0) + headerLine.length,
660
- line: leadingComments[0].loc.start.line + i
746
+ line: firstLeadingCommentLoc.start.line + i
661
747
  },
662
748
  end: {
663
749
  column: (i === 0 ? "/*".length : 0) + leadingLine.length,
664
- line: leadingComments[0].loc.start.line + i
750
+ line: firstLeadingCommentLoc.start.line + i
665
751
  }
666
752
  };
667
753
  break;
@@ -673,14 +759,16 @@ module.exports = {
673
759
  pattern: headerLine
674
760
  };
675
761
  const columnOffset = i === 0 ? "/*".length : 0;
762
+ assertDefined(firstLeadingCommentLoc);
763
+ assertNotNull(firstLeadingCommentLoc);
676
764
  errorMessageLoc = {
677
765
  start: {
678
766
  column: columnOffset + 0,
679
- line: leadingComments[0].loc.start.line + i
767
+ line: firstLeadingCommentLoc.start.line + i
680
768
  },
681
769
  end: {
682
770
  column: columnOffset + leadingLine.length,
683
- line: leadingComments[0].loc.start.line + i
771
+ line: firstLeadingCommentLoc.start.line + i
684
772
  }
685
773
  };
686
774
  break;
@@ -690,14 +778,18 @@ module.exports = {
690
778
 
691
779
  if (!errorMessageId && leadingLines.length > headerLines.length) {
692
780
  errorMessageId = "headerTooLong";
781
+ assertDefined(firstLeadingCommentLoc);
782
+ assertNotNull(firstLeadingCommentLoc);
783
+ assertDefined(lastLeadingCommentLoc);
784
+ assertNotNull(lastLeadingCommentLoc);
693
785
  errorMessageLoc = {
694
786
  start: {
695
787
  column: (headerLines.length === 0 ? "/*".length : 0) + 0,
696
- line: leadingComments[0].loc.start.line + headerLines.length
788
+ line: firstLeadingCommentLoc.start.line + headerLines.length
697
789
  },
698
790
  end: {
699
- column: leadingComments[leadingComments.length - 1].loc.end.column - "*/".length,
700
- line: leadingComments[leadingComments.length - 1].loc.end.line
791
+ column: lastLeadingCommentLoc.end.column - "*/".length,
792
+ line: lastLeadingCommentLoc.end.line
701
793
  }
702
794
  };
703
795
  }
@@ -706,6 +798,7 @@ module.exports = {
706
798
  if (canFix && headerLines.length > 1) {
707
799
  fixLines = [fixLines.join(eol)];
708
800
  }
801
+ assertNotNull(errorMessageLoc);
709
802
  context.report({
710
803
  loc: errorMessageLoc,
711
804
  messageId: errorMessageId,
@@ -717,8 +810,8 @@ module.exports = {
717
810
  return;
718
811
  }
719
812
 
720
- const actualLeadingEmptyLines = leadingEmptyLines(
721
- context.sourceCode.text.substring(leadingComments[0].range[1]));
813
+ const actualLeadingEmptyLines =
814
+ leadingEmptyLines(sourceCode.text.substring(firstLeadingCommentRange[1]));
722
815
  const missingEmptyLines = numNewlines - actualLeadingEmptyLines;
723
816
  if (missingEmptyLines > 0) {
724
817
  context.report({
@@ -735,3 +828,5 @@ module.exports = {
735
828
  };
736
829
  }
737
830
  };
831
+
832
+ exports.header = headerRule;
@@ -41,6 +41,7 @@ const commentTypeOptions = Object.freeze({
41
41
  line: "line"
42
42
  });
43
43
 
44
+ /** @type {import('json-schema').JSONSchema4} */
44
45
  const schema = Object.freeze({
45
46
  $ref: "#/definitions/options",
46
47
  definitions: {
package/package.json CHANGED
@@ -1,31 +1,47 @@
1
1
  {
2
2
  "name": "@tony.ganchev/eslint-plugin-header",
3
- "version": "3.1.11",
3
+ "version": "3.1.13",
4
4
  "description": "ESLint plugin to ensure files begin with a given comment, usually a copyright or license notice.",
5
5
  "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./index.d.ts",
10
+ "import": "./index.js",
11
+ "require": "./index.js"
12
+ }
13
+ },
6
14
  "files": [
7
- "/lib/**/*.js",
8
- "!/lib/rules/test-utils.js"
15
+ "lib/**/*.js",
16
+ "index.d.ts*",
17
+ "types",
18
+ "!lib/rules/test-utils.js"
9
19
  ],
10
20
  "scripts": {
21
+ "build": "npx tsc",
22
+ "e2e": "npm run build && npx mocha --timeout 60000 tests/e2e/*.js",
11
23
  "eslint": "npx eslint .",
12
24
  "lint": "npm run eslint && npm run markdownlint",
13
25
  "markdownlint": "npx markdownlint-cli *.md",
14
- "test": "npm run lint && npm run unit",
26
+ "test": "npm run lint && npm run unit && npm run e2e",
15
27
  "unit": "npx nyc --reporter=html --reporter=text --reporter=text-summary --reporter=lcov --check-coverage=true --statements=100 --branches=100 --lines=100 --functions=100 mocha tests/lib/*.js tests/lib/**/*.js"
16
28
  },
17
29
  "devDependencies": {
18
- "@eslint/eslintrc": "^3.3.1",
19
- "@eslint/js": "^9.39.1",
30
+ "@eslint/eslintrc": "^3.3.3",
31
+ "@eslint/js": "^9.39.2",
20
32
  "@eslint/markdown": "^7.5.1",
21
- "@stylistic/eslint-plugin": "^5.5.0",
22
- "eslint": "^9.39.1",
23
- "eslint-plugin-eslint-plugin": "^7.2.0",
24
- "eslint-plugin-jsdoc": "^61.1.12",
25
- "eslint-plugin-n": "^17.23.1",
26
- "mocha": "^11.7.5",
33
+ "@stylistic/eslint-plugin": "^5.7.1",
34
+ "@types/node": "^25.2.1",
35
+ "eslint": "^9.39.2",
36
+ "eslint-plugin-eslint-plugin": "^7.3.0",
37
+ "eslint-plugin-jsdoc": "^62.5.2",
38
+ "eslint-plugin-n": "^17.23.2",
39
+ "markdownlint-cli": "^0.47.0",
40
+ "mocha": "^12.0.0-beta-6",
27
41
  "nyc": "^17.1.0",
28
- "testdouble": "^3.20.2"
42
+ "testdouble": "^3.20.2",
43
+ "typescript": "^5.9.3",
44
+ "typescript-eslint": "^8.54.0"
29
45
  },
30
46
  "peerDependencies": {
31
47
  "eslint": ">=7.7.0"
@@ -40,7 +56,7 @@
40
56
  },
41
57
  "author": "Stuart Knightley",
42
58
  "license": "MIT",
43
- "contributors": [
59
+ "maintainers": [
44
60
  "Tony Ganchev"
45
61
  ]
46
62
  }
@@ -0,0 +1,4 @@
1
+ export = pluginDefinition;
2
+ /** @type {import('eslint').ESLint.Plugin} */
3
+ declare const pluginDefinition: import("eslint").ESLint.Plugin;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.js"],"names":[],"mappings":";AA4BA,6CAA6C;AAC7C,gCADW,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,CAKvC"}
@@ -0,0 +1,3 @@
1
+ declare function _exports(commentText: string): ["block" | "line", string | string[]];
2
+ export = _exports;
3
+ //# sourceMappingURL=comment-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-parser.d.ts","sourceRoot":"","sources":["../../lib/comment-parser.js"],"names":[],"mappings":"AAsCiB,uCAJN,MAAM,GACJ,CAAC,OAAO,GAAG,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAmBjD"}
@@ -0,0 +1,10 @@
1
+ declare namespace _exports {
2
+ export { RuleContext, SourceCode };
3
+ }
4
+ declare namespace _exports {
5
+ function contextSourceCode(context: RuleContext): SourceCode;
6
+ }
7
+ export = _exports;
8
+ type RuleContext = import("eslint").Rule.RuleContext;
9
+ type SourceCode = import("eslint").SourceCode;
10
+ //# sourceMappingURL=eslint-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint-utils.d.ts","sourceRoot":"","sources":["../../../lib/rules/eslint-utils.js"],"names":[],"mappings":";;;;IAsCuB,oCAHR,WAAW,GACT,UAAU,CAItB;;;mBAbQ,OAAO,QAAQ,EAAE,IAAI,CAAC,WAAW;kBACjC,OAAO,QAAQ,EAAE,UAAU"}
@@ -0,0 +1,73 @@
1
+ export { headerRule as header };
2
+ /**
3
+ * Import type definitions.
4
+ */
5
+ export type Fix = import("eslint").Rule.Fix;
6
+ /**
7
+ * Import type definitions.
8
+ */
9
+ export type NodeListener = import("eslint").Rule.NodeListener;
10
+ /**
11
+ * Import type definitions.
12
+ */
13
+ export type ReportFixer = import("eslint").Rule.ReportFixer;
14
+ /**
15
+ * Import type definitions.
16
+ */
17
+ export type RuleFixer = import("eslint").Rule.RuleFixer;
18
+ /**
19
+ * Import type definitions.
20
+ */
21
+ export type RuleContext = import("eslint").Rule.RuleContext;
22
+ /**
23
+ * Import type definitions.
24
+ */
25
+ export type Comment = import("estree").Comment;
26
+ /**
27
+ * Import type definitions.
28
+ */
29
+ export type Program = import("estree").Program;
30
+ /**
31
+ * Import type definitions.
32
+ */
33
+ export type SourceLocation = import("estree").SourceLocation;
34
+ /**
35
+ * Local type definitions.
36
+ */
37
+ export type HeaderLinePattern = {
38
+ pattern: string;
39
+ template?: string;
40
+ };
41
+ /**
42
+ * Local type definitions.
43
+ */
44
+ export type HeaderLine = string | HeaderLinePattern;
45
+ /**
46
+ * Local type definitions.
47
+ */
48
+ export type HeaderLines = (HeaderLine | HeaderLine[]);
49
+ /**
50
+ * Local type definitions.
51
+ */
52
+ export type LineEndingOption = "unix" | "windows";
53
+ /**
54
+ * Local type definitions.
55
+ */
56
+ export type HeaderSettings = {
57
+ lineEndings?: LineEndingOption;
58
+ };
59
+ /**
60
+ * Local type definitions.
61
+ */
62
+ export type CommentType = "block" | "line";
63
+ /**
64
+ * Local type definitions.
65
+ */
66
+ export type AllHeaderOptions = [template: string] | [template: string, settings: HeaderSettings] | [type: CommentType, lines: HeaderLines] | [type: CommentType, lines: HeaderLines, settings: HeaderSettings] | [type: CommentType, lines: HeaderLines, minLines: number] | [type: CommentType, lines: HeaderLines, minLines: number, settings: HeaderSettings];
67
+ /**
68
+ * Local type definitions.
69
+ */
70
+ export type HeaderRuleConfig = import("eslint").Linter.RuleEntry<AllHeaderOptions>;
71
+ /** @type {import('eslint').Rule.RuleModule} */
72
+ declare const headerRule: import("eslint").Rule.RuleModule;
73
+ //# sourceMappingURL=header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../lib/rules/header.js"],"names":[],"mappings":";;;;kBAoCa,OAAO,QAAQ,EAAE,IAAI,CAAC,GAAG;;;;2BACzB,OAAO,QAAQ,EAAE,IAAI,CAAC,YAAY;;;;0BAClC,OAAO,QAAQ,EAAE,IAAI,CAAC,WAAW;;;;wBACjC,OAAO,QAAQ,EAAE,IAAI,CAAC,SAAS;;;;0BAC/B,OAAO,QAAQ,EAAE,IAAI,CAAC,WAAW;;;;sBACjC,OAAO,QAAQ,EAAE,OAAO;;;;sBACxB,OAAO,QAAQ,EAAE,OAAO;;;;6BACxB,OAAO,QAAQ,EAAE,cAAc;;;;gCAK/B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;;;;yBACtC,MAAM,GAAG,iBAAiB;;;;0BAC1B,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC;;;;+BAC3B,MAAM,GAAG,SAAS;;;;6BAClB;IAAE,WAAW,CAAC,EAAE,gBAAgB,CAAA;CAAE;;;;0BAClC,OAAO,GAAG,MAAM;;;;+BAChB,CAAC,QAAQ,EAAE,MAAM,CAAC,GAC9B,CAAI,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,GAC/C,CAAI,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,GAC1C,CAAI,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,CAAC,GACpE,CAAI,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,GAC5D,CACM,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,CAC1B;;;;+BAEQ,OAAO,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC;AA6ShE,+CAA+C;AAC/C,0BADW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU,CA8czC"}
@@ -0,0 +1,4 @@
1
+ export const description: "";
2
+ export const recommended: true;
3
+ export const url: string;
4
+ //# sourceMappingURL=header.docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header.docs.d.ts","sourceRoot":"","sources":["../../../lib/rules/header.docs.js"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ export type lineEndingOptions = string;
2
+ /**
3
+ * @enum {string}
4
+ */
5
+ export const lineEndingOptions: Readonly<{
6
+ os: "os";
7
+ unix: "unix";
8
+ windows: "windows";
9
+ }>;
10
+ export type commentTypeOptions = string;
11
+ /**
12
+ * @enum {string}
13
+ */
14
+ export const commentTypeOptions: Readonly<{
15
+ block: "block";
16
+ line: "line";
17
+ }>;
18
+ /** @type {import('json-schema').JSONSchema4} */
19
+ export const schema: import("json-schema").JSONSchema4;
20
+ //# sourceMappingURL=header.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header.schema.d.ts","sourceRoot":"","sources":["../../../lib/rules/header.schema.js"],"names":[],"mappings":"gCA2BU,MAAM;AADhB;;GAEG;AACH;;;;GAIG;iCAGO,MAAM;AADhB;;GAEG;AACH;;;GAGG;AAEH,gDAAgD;AAChD,qBADW,OAAO,aAAa,EAAE,WAAW,CA0FzC"}
@@ -0,0 +1,10 @@
1
+ declare namespace _exports {
2
+ export { InvalidTestCase, TestCaseError };
3
+ }
4
+ declare namespace _exports {
5
+ function generateInvalidTestCaseNames(invalidTests: InvalidTestCase[]): InvalidTestCase[];
6
+ }
7
+ export = _exports;
8
+ type InvalidTestCase = import("eslint").RuleTester.InvalidTestCase;
9
+ type TestCaseError = import("eslint").RuleTester.TestCaseError;
10
+ //# sourceMappingURL=test-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../lib/rules/test-utils.js"],"names":[],"mappings":";;;;IA4EkC,oDAJnB,eAAe,EAAE,GACf,eAAe,EAAE,CA4B7B;;;uBAxEQ,OAAO,QAAQ,EAAE,UAAU,CAAC,eAAe;qBAC3C,OAAO,QAAQ,EAAE,UAAU,CAAC,aAAa"}