exadev-eslint-config 2.16.1 → 2.17.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 +12 -0
- package/dist/index.cjs +143 -3
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +141 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -160,6 +160,18 @@ export default tseslint.config(
|
|
|
160
160
|
|
|
161
161
|
Trailing arguments are arbitrary flat-config objects, appended in order after everything else -- `exadevConfig({}, { rules: { 'no-console': 'warn' } })` is equivalent to spreading the default export plus one more config object.
|
|
162
162
|
|
|
163
|
+
## Gitignore-derived ignores
|
|
164
|
+
|
|
165
|
+
`exadevConfig()`'s default output includes an `ignores` block derived directly from your project's own `.gitignore` (via [`@eslint/config-helpers`](https://www.npmjs.com/package/@eslint/config-helpers)'s `includeIgnoreFile`), so a generated directory your `.gitignore` already knows about (`dist/`, `coverage/`, a tool's own report output) is never linted, without hand-duplicating that list in `eslint.config.ts` too. This closes a real gap: a `.gitignore`d directory that nothing previously linted broadly enough to reach could still get linted the moment a wide-reaching rule (this package's own bundled RFC 8785 JSON canonicalization, say) started matching every file its glob covers.
|
|
166
|
+
|
|
167
|
+
| Value | `options.gitignore` |
|
|
168
|
+
| --- | --- |
|
|
169
|
+
| `true` | Force on -- throws if no `.gitignore` exists |
|
|
170
|
+
| `false` | Force off -- always `[]`, no resolution attempted |
|
|
171
|
+
| `undefined` / omitted | Auto-detect (the default): on if the project has a `.gitignore`, silently off if it doesn't (nothing to read from a project with no version control set up yet) |
|
|
172
|
+
|
|
173
|
+
Needs no peer to install -- `@eslint/config-helpers` is bundled into this package's own build.
|
|
174
|
+
|
|
163
175
|
## RFC 8785 canonical JSON formatting
|
|
164
176
|
|
|
165
177
|
Every JSON file is linted against [`eslint-plugin-json-canonical`](https://github.com/ExaDev/eslint-plugin-json-canonical) v2 -- plain UTF-16 code-unit key ordering, canonical number formatting, canonical string escaping, and (as of that plugin's own v2) pretty-printed layout (2-space indentation, one member/element per line, a trailing newline), per [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785). This is bundled unconditionally, the same way jsdoc/tsdoc support is: `eslint-plugin-json-canonical` is a plain dependency of this package, so every consumer already has it. There is no option to turn it off.
|
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
enumerable: true
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
//#endregion
|
|
27
|
+
let node_fs = require("node:fs");
|
|
28
|
+
node_fs = __toESM(node_fs, 1);
|
|
29
|
+
let node_path = require("node:path");
|
|
30
|
+
node_path = __toESM(node_path, 1);
|
|
27
31
|
let eslint_plugin_jsdoc = require("eslint-plugin-jsdoc");
|
|
28
32
|
eslint_plugin_jsdoc = __toESM(eslint_plugin_jsdoc, 1);
|
|
29
33
|
let eslint_plugin_tsdoc = require("eslint-plugin-tsdoc");
|
|
@@ -31,8 +35,6 @@ eslint_plugin_tsdoc = __toESM(eslint_plugin_tsdoc, 1);
|
|
|
31
35
|
let eslint_plugin_json_canonical = require("eslint-plugin-json-canonical");
|
|
32
36
|
eslint_plugin_json_canonical = __toESM(eslint_plugin_json_canonical, 1);
|
|
33
37
|
let node_module = require("node:module");
|
|
34
|
-
let node_fs = require("node:fs");
|
|
35
|
-
let node_path = require("node:path");
|
|
36
38
|
let _typescript_eslint_utils = require("@typescript-eslint/utils");
|
|
37
39
|
let typescript = require("typescript");
|
|
38
40
|
typescript = __toESM(typescript, 1);
|
|
@@ -41,6 +43,143 @@ let _eslint_js = require("@eslint/js");
|
|
|
41
43
|
_eslint_js = __toESM(_eslint_js, 1);
|
|
42
44
|
let typescript_eslint = require("typescript-eslint");
|
|
43
45
|
typescript_eslint = __toESM(typescript_eslint, 1);
|
|
46
|
+
//#region node_modules/.pnpm/@eslint+config-helpers@0.7.0/node_modules/@eslint/config-helpers/dist/esm/index.js
|
|
47
|
+
/**
|
|
48
|
+
* @fileoverview Ignore file utilities for the config-helpers package.
|
|
49
|
+
* This file was forked from the source code for the compat package.
|
|
50
|
+
*
|
|
51
|
+
* @author Nicholas C. Zakas
|
|
52
|
+
* @author Kirk Waiblinger
|
|
53
|
+
*/
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {object} IncludeIgnoreFileOptionsObject
|
|
56
|
+
* @property {boolean} [gitignoreResolution] Whether to interpret the contents of an ignore file relative to the config file or the ignore file.
|
|
57
|
+
* - gitignoreResolution: false (default): Interprets ignore patterns relative to the config file
|
|
58
|
+
* - gitignoreResolution: true: Interprets the ignore patterns in a file relative to the ignore file
|
|
59
|
+
* @property {string} [name] The name to give the output config object(s).
|
|
60
|
+
*/
|
|
61
|
+
/**
|
|
62
|
+
* Options for `includeIgnoreFile()`. May be provided as an object or, for
|
|
63
|
+
* legacy compatibility with `@eslint/compat`, as a string which is treated as
|
|
64
|
+
* the `name` option.
|
|
65
|
+
* @typedef {IncludeIgnoreFileOptionsObject | string} IncludeIgnoreFileOptions
|
|
66
|
+
*/
|
|
67
|
+
/**
|
|
68
|
+
* Converts an ESLint ignore pattern to a minimatch pattern.
|
|
69
|
+
* @param {string} pattern The .eslintignore or .gitignore pattern to convert.
|
|
70
|
+
* @returns {string} The converted pattern.
|
|
71
|
+
*/
|
|
72
|
+
function convertIgnorePatternToMinimatch(pattern) {
|
|
73
|
+
const isNegated = pattern.startsWith("!");
|
|
74
|
+
const negatedPrefix = isNegated ? "!" : "";
|
|
75
|
+
const patternToTest = (isNegated ? pattern.slice(1) : pattern).trimEnd();
|
|
76
|
+
if ([
|
|
77
|
+
"",
|
|
78
|
+
"**",
|
|
79
|
+
"/**",
|
|
80
|
+
"**/"
|
|
81
|
+
].includes(patternToTest)) return `${negatedPrefix}${patternToTest}`;
|
|
82
|
+
const firstIndexOfSlash = patternToTest.indexOf("/");
|
|
83
|
+
return `${negatedPrefix}${firstIndexOfSlash < 0 || firstIndexOfSlash === patternToTest.length - 1 ? "**/" : ""}${(firstIndexOfSlash === 0 ? patternToTest.slice(1) : patternToTest).replaceAll(/(?=((?:\\.|[^{(])*))\1([{(])/guy, "$1\\$2")}${patternToTest.endsWith("/**") ? "/*" : ""}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @param {string} ignoreFilePath
|
|
87
|
+
* @returns {string[]}
|
|
88
|
+
*/
|
|
89
|
+
function ignoreFilePathToPatterns(ignoreFilePath) {
|
|
90
|
+
return node_fs.default.readFileSync(ignoreFilePath, "utf8").split(/\r?\n/u).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map(convertIgnorePatternToMinimatch);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Helper to parse and validate the options to `includeIgnoreFile()`
|
|
94
|
+
*
|
|
95
|
+
* @param {string | { gitignoreResolution?: unknown, name?: unknown } | undefined} options
|
|
96
|
+
* @returns {{ gitignoreResolution: boolean, name: string }}
|
|
97
|
+
*/
|
|
98
|
+
function parseOptions(options) {
|
|
99
|
+
if (typeof options === "string") return {
|
|
100
|
+
gitignoreResolution: false,
|
|
101
|
+
name: options
|
|
102
|
+
};
|
|
103
|
+
const optionsObject = options ?? {};
|
|
104
|
+
if (typeof optionsObject !== "object" || Array.isArray(optionsObject)) throw new TypeError("The options argument to `includeIgnoreFile()` should be an object or a string.");
|
|
105
|
+
const gitignoreResolution = optionsObject.gitignoreResolution ?? false;
|
|
106
|
+
if (typeof gitignoreResolution !== "boolean") throw new TypeError("The `gitignoreResolution` option must be specified a boolean or omitted");
|
|
107
|
+
const name = optionsObject.name ?? `Imported .gitignore patterns`;
|
|
108
|
+
if (typeof name !== "string") throw new TypeError("The `name` option must be specified as a string or omitted.");
|
|
109
|
+
return {
|
|
110
|
+
gitignoreResolution,
|
|
111
|
+
name
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* @overload
|
|
116
|
+
*
|
|
117
|
+
* Reads ignore files and returns objects with the ignore patterns.
|
|
118
|
+
*
|
|
119
|
+
* @param {string[]} ignoreFilePathArg The paths of ignore files to include.
|
|
120
|
+
* @param {IncludeIgnoreFileOptions} [options]
|
|
121
|
+
* @returns {ConfigObject[]}
|
|
122
|
+
*/
|
|
123
|
+
/**
|
|
124
|
+
* @overload
|
|
125
|
+
*
|
|
126
|
+
* Reads an ignore file and returns an object with the ignore patterns.
|
|
127
|
+
*
|
|
128
|
+
* @param {string} ignoreFilePathArg The path of the ignore file to include.
|
|
129
|
+
* @param {IncludeIgnoreFileOptions} [options]
|
|
130
|
+
* @returns {ConfigObject}
|
|
131
|
+
*/
|
|
132
|
+
/**
|
|
133
|
+
* @overload
|
|
134
|
+
*
|
|
135
|
+
* Reads an ignore file(s) and returns an object(s) with the ignore patterns.
|
|
136
|
+
*
|
|
137
|
+
* @param {string[] | string} ignoreFilePathArg The path(s) of the ignore file(s) to include.
|
|
138
|
+
* @param {IncludeIgnoreFileOptions} [options]
|
|
139
|
+
* @returns {ConfigObject[] | ConfigObject}
|
|
140
|
+
*/
|
|
141
|
+
/**
|
|
142
|
+
* Reads an ignore file(s) and returns an object(s) with the ignore patterns.
|
|
143
|
+
*
|
|
144
|
+
* @param {string[] | string} ignoreFilePathArg The path(s) of the ignore file(s) to include.
|
|
145
|
+
* @param {IncludeIgnoreFileOptions} [options]
|
|
146
|
+
* @returns {ConfigObject[] | ConfigObject}
|
|
147
|
+
*/
|
|
148
|
+
function includeIgnoreFile(ignoreFilePathArg, options) {
|
|
149
|
+
const returnSingleObject = !Array.isArray(ignoreFilePathArg);
|
|
150
|
+
const ignoreFilePaths = Array.isArray(ignoreFilePathArg) ? ignoreFilePathArg : [ignoreFilePathArg];
|
|
151
|
+
for (const ignorePath of ignoreFilePaths) {
|
|
152
|
+
if (typeof ignorePath !== "string") throw new TypeError("The first argument to `includeIgnoreFile()` should be a string or array of strings");
|
|
153
|
+
if (!node_path.default.isAbsolute(ignorePath)) throw new Error(`The ignore file location must be an absolute path. Received ${ignorePath}`);
|
|
154
|
+
}
|
|
155
|
+
const { gitignoreResolution, name } = parseOptions(options);
|
|
156
|
+
if (returnSingleObject) return {
|
|
157
|
+
name,
|
|
158
|
+
ignores: ignoreFilePathToPatterns(ignoreFilePathArg),
|
|
159
|
+
...gitignoreResolution ? { basePath: node_path.default.dirname(ignoreFilePathArg) } : {}
|
|
160
|
+
};
|
|
161
|
+
return ignoreFilePaths.map((ignoreFilePath, i) => ({
|
|
162
|
+
name: `${name} (${i})`,
|
|
163
|
+
ignores: ignoreFilePathToPatterns(ignoreFilePath),
|
|
164
|
+
...gitignoreResolution ? { basePath: node_path.default.dirname(ignoreFilePath) } : {}
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
//#endregion
|
|
168
|
+
//#region src/gitignore.ts
|
|
169
|
+
/**
|
|
170
|
+
* A generated directory that's `.gitignore`d but not in this array's own `ignores` block was, until this feature existed, a real, confirmed gap: harmless while nothing linted broadly enough to reach it, then a real problem the moment a wide-reaching rule (this package's own bundled RFC 8785 JSON canonicalization, say) started matching every file its own glob covers, including a leftover build/report artifact nobody meant to lint at all. Deriving `ignores` from `.gitignore` itself, rather than a hand-maintained list every consumer would otherwise have to keep in sync by hand, means a project's own existing single source of truth for "what isn't source" is the one ESLint uses too.
|
|
171
|
+
*/
|
|
172
|
+
function buildGitignoreConfig(options = {}) {
|
|
173
|
+
const cwd = options.cwd ?? process.cwd();
|
|
174
|
+
if (options.enabled === false) return [];
|
|
175
|
+
const gitignorePath = (0, node_path.join)(cwd, ".gitignore");
|
|
176
|
+
if (!(0, node_fs.existsSync)(gitignorePath)) {
|
|
177
|
+
if (options.enabled === true) throw new Error(`@exadev/eslint-config: gitignore-based ignores were explicitly requested but no .gitignore was found at ${gitignorePath}`);
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
return [includeIgnoreFile(gitignorePath)];
|
|
181
|
+
}
|
|
182
|
+
//#endregion
|
|
44
183
|
//#region src/jsdoc.ts
|
|
45
184
|
const JS_TS_FILE_PATTERNS$1 = "**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}";
|
|
46
185
|
const jsdocConfig = eslint_plugin_jsdoc.default.configs["flat/recommended-tsdoc-error"];
|
|
@@ -160,7 +299,7 @@ function buildNextjsConfig(options = {}) {
|
|
|
160
299
|
}
|
|
161
300
|
//#endregion
|
|
162
301
|
//#region package.json
|
|
163
|
-
var version = "2.
|
|
302
|
+
var version = "2.17.0";
|
|
164
303
|
//#endregion
|
|
165
304
|
//#region src/react.ts
|
|
166
305
|
const JSX_FILE_PATTERNS = ["**/*.jsx", "**/*.tsx"];
|
|
@@ -1872,6 +2011,7 @@ function toPublicConfigArray(built) {
|
|
|
1872
2011
|
//#region src/create-config.ts
|
|
1873
2012
|
function exadevConfig(options = {}, ...userConfigs) {
|
|
1874
2013
|
return toPublicConfigArray([
|
|
2014
|
+
...buildGitignoreConfig({ enabled: options.gitignore }),
|
|
1875
2015
|
...recommendedTypeChecked,
|
|
1876
2016
|
...jsdocAndTsdoc,
|
|
1877
2017
|
...jsonCanonicalConfig,
|
package/dist/index.d.cts
CHANGED
|
@@ -8,6 +8,7 @@ interface ExadevConfigOptions {
|
|
|
8
8
|
readonly react?: boolean;
|
|
9
9
|
readonly nextjs?: boolean;
|
|
10
10
|
readonly packageJsonKeyOrder?: boolean;
|
|
11
|
+
readonly gitignore?: boolean;
|
|
11
12
|
}
|
|
12
13
|
declare function exadevConfig(options?: ExadevConfigOptions, ...userConfigs: readonly TSESLint.FlatConfig.Config[]): PublicConfigArray;
|
|
13
14
|
declare const defaultConfig: PublicConfigArray;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ interface ExadevConfigOptions {
|
|
|
8
8
|
readonly react?: boolean;
|
|
9
9
|
readonly nextjs?: boolean;
|
|
10
10
|
readonly packageJsonKeyOrder?: boolean;
|
|
11
|
+
readonly gitignore?: boolean;
|
|
11
12
|
}
|
|
12
13
|
declare function exadevConfig(options?: ExadevConfigOptions, ...userConfigs: readonly TSESLint.FlatConfig.Config[]): PublicConfigArray;
|
|
13
14
|
declare const defaultConfig: PublicConfigArray;
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,151 @@
|
|
|
1
|
+
import fs, { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import path, { join, posix } from "node:path";
|
|
1
3
|
import jsdoc from "eslint-plugin-jsdoc";
|
|
2
4
|
import tsdoc from "eslint-plugin-tsdoc";
|
|
3
5
|
import jsonCanonical from "eslint-plugin-json-canonical";
|
|
4
6
|
import { createRequire } from "node:module";
|
|
5
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
-
import { join, posix } from "node:path";
|
|
7
7
|
import { AST_NODE_TYPES, ESLintUtils, TSESLint } from "@typescript-eslint/utils";
|
|
8
8
|
import * as ts from "typescript";
|
|
9
9
|
import { isPropertyReadonlyInType, isTypeReference } from "ts-api-utils";
|
|
10
10
|
import js from "@eslint/js";
|
|
11
11
|
import tseslint from "typescript-eslint";
|
|
12
|
+
//#region node_modules/.pnpm/@eslint+config-helpers@0.7.0/node_modules/@eslint/config-helpers/dist/esm/index.js
|
|
13
|
+
/**
|
|
14
|
+
* @fileoverview Ignore file utilities for the config-helpers package.
|
|
15
|
+
* This file was forked from the source code for the compat package.
|
|
16
|
+
*
|
|
17
|
+
* @author Nicholas C. Zakas
|
|
18
|
+
* @author Kirk Waiblinger
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {object} IncludeIgnoreFileOptionsObject
|
|
22
|
+
* @property {boolean} [gitignoreResolution] Whether to interpret the contents of an ignore file relative to the config file or the ignore file.
|
|
23
|
+
* - gitignoreResolution: false (default): Interprets ignore patterns relative to the config file
|
|
24
|
+
* - gitignoreResolution: true: Interprets the ignore patterns in a file relative to the ignore file
|
|
25
|
+
* @property {string} [name] The name to give the output config object(s).
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Options for `includeIgnoreFile()`. May be provided as an object or, for
|
|
29
|
+
* legacy compatibility with `@eslint/compat`, as a string which is treated as
|
|
30
|
+
* the `name` option.
|
|
31
|
+
* @typedef {IncludeIgnoreFileOptionsObject | string} IncludeIgnoreFileOptions
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Converts an ESLint ignore pattern to a minimatch pattern.
|
|
35
|
+
* @param {string} pattern The .eslintignore or .gitignore pattern to convert.
|
|
36
|
+
* @returns {string} The converted pattern.
|
|
37
|
+
*/
|
|
38
|
+
function convertIgnorePatternToMinimatch(pattern) {
|
|
39
|
+
const isNegated = pattern.startsWith("!");
|
|
40
|
+
const negatedPrefix = isNegated ? "!" : "";
|
|
41
|
+
const patternToTest = (isNegated ? pattern.slice(1) : pattern).trimEnd();
|
|
42
|
+
if ([
|
|
43
|
+
"",
|
|
44
|
+
"**",
|
|
45
|
+
"/**",
|
|
46
|
+
"**/"
|
|
47
|
+
].includes(patternToTest)) return `${negatedPrefix}${patternToTest}`;
|
|
48
|
+
const firstIndexOfSlash = patternToTest.indexOf("/");
|
|
49
|
+
return `${negatedPrefix}${firstIndexOfSlash < 0 || firstIndexOfSlash === patternToTest.length - 1 ? "**/" : ""}${(firstIndexOfSlash === 0 ? patternToTest.slice(1) : patternToTest).replaceAll(/(?=((?:\\.|[^{(])*))\1([{(])/guy, "$1\\$2")}${patternToTest.endsWith("/**") ? "/*" : ""}`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @param {string} ignoreFilePath
|
|
53
|
+
* @returns {string[]}
|
|
54
|
+
*/
|
|
55
|
+
function ignoreFilePathToPatterns(ignoreFilePath) {
|
|
56
|
+
return fs.readFileSync(ignoreFilePath, "utf8").split(/\r?\n/u).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map(convertIgnorePatternToMinimatch);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Helper to parse and validate the options to `includeIgnoreFile()`
|
|
60
|
+
*
|
|
61
|
+
* @param {string | { gitignoreResolution?: unknown, name?: unknown } | undefined} options
|
|
62
|
+
* @returns {{ gitignoreResolution: boolean, name: string }}
|
|
63
|
+
*/
|
|
64
|
+
function parseOptions(options) {
|
|
65
|
+
if (typeof options === "string") return {
|
|
66
|
+
gitignoreResolution: false,
|
|
67
|
+
name: options
|
|
68
|
+
};
|
|
69
|
+
const optionsObject = options ?? {};
|
|
70
|
+
if (typeof optionsObject !== "object" || Array.isArray(optionsObject)) throw new TypeError("The options argument to `includeIgnoreFile()` should be an object or a string.");
|
|
71
|
+
const gitignoreResolution = optionsObject.gitignoreResolution ?? false;
|
|
72
|
+
if (typeof gitignoreResolution !== "boolean") throw new TypeError("The `gitignoreResolution` option must be specified a boolean or omitted");
|
|
73
|
+
const name = optionsObject.name ?? `Imported .gitignore patterns`;
|
|
74
|
+
if (typeof name !== "string") throw new TypeError("The `name` option must be specified as a string or omitted.");
|
|
75
|
+
return {
|
|
76
|
+
gitignoreResolution,
|
|
77
|
+
name
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* @overload
|
|
82
|
+
*
|
|
83
|
+
* Reads ignore files and returns objects with the ignore patterns.
|
|
84
|
+
*
|
|
85
|
+
* @param {string[]} ignoreFilePathArg The paths of ignore files to include.
|
|
86
|
+
* @param {IncludeIgnoreFileOptions} [options]
|
|
87
|
+
* @returns {ConfigObject[]}
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* @overload
|
|
91
|
+
*
|
|
92
|
+
* Reads an ignore file and returns an object with the ignore patterns.
|
|
93
|
+
*
|
|
94
|
+
* @param {string} ignoreFilePathArg The path of the ignore file to include.
|
|
95
|
+
* @param {IncludeIgnoreFileOptions} [options]
|
|
96
|
+
* @returns {ConfigObject}
|
|
97
|
+
*/
|
|
98
|
+
/**
|
|
99
|
+
* @overload
|
|
100
|
+
*
|
|
101
|
+
* Reads an ignore file(s) and returns an object(s) with the ignore patterns.
|
|
102
|
+
*
|
|
103
|
+
* @param {string[] | string} ignoreFilePathArg The path(s) of the ignore file(s) to include.
|
|
104
|
+
* @param {IncludeIgnoreFileOptions} [options]
|
|
105
|
+
* @returns {ConfigObject[] | ConfigObject}
|
|
106
|
+
*/
|
|
107
|
+
/**
|
|
108
|
+
* Reads an ignore file(s) and returns an object(s) with the ignore patterns.
|
|
109
|
+
*
|
|
110
|
+
* @param {string[] | string} ignoreFilePathArg The path(s) of the ignore file(s) to include.
|
|
111
|
+
* @param {IncludeIgnoreFileOptions} [options]
|
|
112
|
+
* @returns {ConfigObject[] | ConfigObject}
|
|
113
|
+
*/
|
|
114
|
+
function includeIgnoreFile(ignoreFilePathArg, options) {
|
|
115
|
+
const returnSingleObject = !Array.isArray(ignoreFilePathArg);
|
|
116
|
+
const ignoreFilePaths = Array.isArray(ignoreFilePathArg) ? ignoreFilePathArg : [ignoreFilePathArg];
|
|
117
|
+
for (const ignorePath of ignoreFilePaths) {
|
|
118
|
+
if (typeof ignorePath !== "string") throw new TypeError("The first argument to `includeIgnoreFile()` should be a string or array of strings");
|
|
119
|
+
if (!path.isAbsolute(ignorePath)) throw new Error(`The ignore file location must be an absolute path. Received ${ignorePath}`);
|
|
120
|
+
}
|
|
121
|
+
const { gitignoreResolution, name } = parseOptions(options);
|
|
122
|
+
if (returnSingleObject) return {
|
|
123
|
+
name,
|
|
124
|
+
ignores: ignoreFilePathToPatterns(ignoreFilePathArg),
|
|
125
|
+
...gitignoreResolution ? { basePath: path.dirname(ignoreFilePathArg) } : {}
|
|
126
|
+
};
|
|
127
|
+
return ignoreFilePaths.map((ignoreFilePath, i) => ({
|
|
128
|
+
name: `${name} (${i})`,
|
|
129
|
+
ignores: ignoreFilePathToPatterns(ignoreFilePath),
|
|
130
|
+
...gitignoreResolution ? { basePath: path.dirname(ignoreFilePath) } : {}
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/gitignore.ts
|
|
135
|
+
/**
|
|
136
|
+
* A generated directory that's `.gitignore`d but not in this array's own `ignores` block was, until this feature existed, a real, confirmed gap: harmless while nothing linted broadly enough to reach it, then a real problem the moment a wide-reaching rule (this package's own bundled RFC 8785 JSON canonicalization, say) started matching every file its own glob covers, including a leftover build/report artifact nobody meant to lint at all. Deriving `ignores` from `.gitignore` itself, rather than a hand-maintained list every consumer would otherwise have to keep in sync by hand, means a project's own existing single source of truth for "what isn't source" is the one ESLint uses too.
|
|
137
|
+
*/
|
|
138
|
+
function buildGitignoreConfig(options = {}) {
|
|
139
|
+
const cwd = options.cwd ?? process.cwd();
|
|
140
|
+
if (options.enabled === false) return [];
|
|
141
|
+
const gitignorePath = join(cwd, ".gitignore");
|
|
142
|
+
if (!existsSync(gitignorePath)) {
|
|
143
|
+
if (options.enabled === true) throw new Error(`@exadev/eslint-config: gitignore-based ignores were explicitly requested but no .gitignore was found at ${gitignorePath}`);
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
return [includeIgnoreFile(gitignorePath)];
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
12
149
|
//#region src/jsdoc.ts
|
|
13
150
|
const JS_TS_FILE_PATTERNS$1 = "**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}";
|
|
14
151
|
const jsdocConfig = jsdoc.configs["flat/recommended-tsdoc-error"];
|
|
@@ -128,7 +265,7 @@ function buildNextjsConfig(options = {}) {
|
|
|
128
265
|
}
|
|
129
266
|
//#endregion
|
|
130
267
|
//#region package.json
|
|
131
|
-
var version = "2.
|
|
268
|
+
var version = "2.17.0";
|
|
132
269
|
//#endregion
|
|
133
270
|
//#region src/react.ts
|
|
134
271
|
const JSX_FILE_PATTERNS = ["**/*.jsx", "**/*.tsx"];
|
|
@@ -1840,6 +1977,7 @@ function toPublicConfigArray(built) {
|
|
|
1840
1977
|
//#region src/create-config.ts
|
|
1841
1978
|
function exadevConfig(options = {}, ...userConfigs) {
|
|
1842
1979
|
return toPublicConfigArray([
|
|
1980
|
+
...buildGitignoreConfig({ enabled: options.gitignore }),
|
|
1843
1981
|
...recommendedTypeChecked,
|
|
1844
1982
|
...jsdocAndTsdoc,
|
|
1845
1983
|
...jsonCanonicalConfig,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "exadev-eslint-config",
|
|
3
3
|
"description": "Shared custom ESLint rules and plugin for ExaDev projects",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.17.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@eslint/js": "^10.0.1",
|
|
7
7
|
"@typescript-eslint/utils": "8.67.0",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
15
15
|
"@commitlint/cli": "^21.2.1",
|
|
16
16
|
"@commitlint/config-conventional": "^21.2.0",
|
|
17
|
+
"@eslint/config-helpers": "0.7.0",
|
|
17
18
|
"@eslint/json": "2.1.0",
|
|
18
19
|
"@humanwhocodes/momoa": "^3.3.13",
|
|
19
20
|
"@next/eslint-plugin-next": "^16.3.2",
|