@exadev/eslint-config 2.10.2 → 2.10.4
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 +2 -0
- package/dist/index.cjs +24 -3
- package/dist/index.js +24 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,6 +113,8 @@ export default tseslint.config(
|
|
|
113
113
|
If none of these resolve, `@exadev/eslint-config`'s default export is byte-for-byte identical to the plain TypeScript ruleset -- nothing about the base package changes.
|
|
114
114
|
2. **For React specifically, the file must actually be `.jsx`/`.tsx`.** The React/hooks/a11y rule block is scoped to `files: ['**/*.jsx', '**/*.tsx']`, so even if `eslint-plugin-react` is resolvable only incidentally (e.g. hoisted as a transitive dependency of something unrelated in a monorepo, with zero real JSX anywhere in the linted project), its rules are never matched against a file that isn't JSX -- ESLint's flat-config `files` matching happens per linted file, at lint time, not at config-build time. `@next/eslint-plugin-next`'s block carries no such glob: its own presence is already an unambiguous signal on its own (nothing installs it except a real Next.js project).
|
|
115
115
|
|
|
116
|
+
React support pairs `eslint-plugin-react`'s `flat/recommended` with its own `flat/jsx-runtime` config, which turns `react/react-in-jsx-scope` and `react/jsx-uses-react` back off. `flat/recommended` alone assumes the classic runtime, where every file using JSX needs `import React` in scope; the automatic JSX runtime, the default since React 17 and the only mode Next.js's own compiler supports, needs no such import. Without this pairing, a consumer on the automatic runtime would see `react/react-in-jsx-scope` fire on every JSX file in the project.
|
|
117
|
+
|
|
116
118
|
### Explicit control
|
|
117
119
|
|
|
118
120
|
Two ways to override the automatic behaviour, for anyone who doesn't want to rely on it:
|
package/dist/index.cjs
CHANGED
|
@@ -89,16 +89,23 @@ function isFlatConfig(value) {
|
|
|
89
89
|
}
|
|
90
90
|
function buildReactConfig(options = {}) {
|
|
91
91
|
if (options.enabled === false) return [];
|
|
92
|
-
const
|
|
92
|
+
const reactModule = tryRequire("eslint-plugin-react", options.requireFn);
|
|
93
|
+
const reactConfig = readFlatConfig(reactModule, [
|
|
93
94
|
"configs",
|
|
94
95
|
"flat",
|
|
95
96
|
"recommended"
|
|
96
97
|
]);
|
|
97
98
|
if (options.enabled === true && reactConfig === void 0) throw new Error(`@exadev/eslint-config: React support was explicitly requested but 'eslint-plugin-react' could not be resolved. Install it with: ${INSTALL_COMMAND}`);
|
|
98
99
|
if (reactConfig === void 0) return [];
|
|
100
|
+
const jsxRuntimeConfig = readFlatConfig(reactModule, [
|
|
101
|
+
"configs",
|
|
102
|
+
"flat",
|
|
103
|
+
"jsx-runtime"
|
|
104
|
+
]);
|
|
99
105
|
const hooksModule = tryRequire("eslint-plugin-react-hooks", options.requireFn);
|
|
100
106
|
return [
|
|
101
107
|
reactConfig,
|
|
108
|
+
jsxRuntimeConfig,
|
|
102
109
|
readFlatConfig(hooksModule, [
|
|
103
110
|
"configs",
|
|
104
111
|
"flat",
|
|
@@ -112,7 +119,7 @@ function buildReactConfig(options = {}) {
|
|
|
112
119
|
}
|
|
113
120
|
//#endregion
|
|
114
121
|
//#region package.json
|
|
115
|
-
var version = "2.10.
|
|
122
|
+
var version = "2.10.4";
|
|
116
123
|
//#endregion
|
|
117
124
|
//#region src/rules/barrel-helpers.ts
|
|
118
125
|
const INDEX_BASENAME$1 = /^index\.[cm]?[tj]sx?$/;
|
|
@@ -144,6 +151,19 @@ function isPermittedBarrel(filename, mode) {
|
|
|
144
151
|
if (mode === "single") return isMainBarrel(filename);
|
|
145
152
|
return isIndexFile(filename);
|
|
146
153
|
}
|
|
154
|
+
function isAncestorNode(value) {
|
|
155
|
+
if (typeof value !== "object" || value === null) return false;
|
|
156
|
+
if (!("type" in value)) return false;
|
|
157
|
+
return typeof value.type === "string";
|
|
158
|
+
}
|
|
159
|
+
function isInsideAmbientModuleDeclaration(node) {
|
|
160
|
+
let current = node;
|
|
161
|
+
while (isAncestorNode(current)) {
|
|
162
|
+
if (current.type === "TSModuleDeclaration") return true;
|
|
163
|
+
current = current.parent;
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
147
167
|
function createSplitReexportDetector() {
|
|
148
168
|
const importsByName = /* @__PURE__ */ new Map();
|
|
149
169
|
const bareExportSpecifiers = [];
|
|
@@ -305,7 +325,7 @@ const barrelPolicy = {
|
|
|
305
325
|
},
|
|
306
326
|
ExportNamedDeclaration(node) {
|
|
307
327
|
detector.visitExportNamed(node);
|
|
308
|
-
if (hasSource(node)) {
|
|
328
|
+
if (hasSource(node) && !isInsideAmbientModuleDeclaration(node)) {
|
|
309
329
|
const source = node.source === null || node.source === void 0 ? void 0 : node.source.value;
|
|
310
330
|
if (!isPermittedBarrel(filename, mode)) context.report({
|
|
311
331
|
node,
|
|
@@ -319,6 +339,7 @@ const barrelPolicy = {
|
|
|
319
339
|
}
|
|
320
340
|
},
|
|
321
341
|
ExportAllDeclaration(node) {
|
|
342
|
+
if (isInsideAmbientModuleDeclaration(node)) return;
|
|
322
343
|
const source = node.source.value;
|
|
323
344
|
if (!isPermittedBarrel(filename, mode)) context.report({
|
|
324
345
|
node,
|
package/dist/index.js
CHANGED
|
@@ -60,16 +60,23 @@ function isFlatConfig(value) {
|
|
|
60
60
|
}
|
|
61
61
|
function buildReactConfig(options = {}) {
|
|
62
62
|
if (options.enabled === false) return [];
|
|
63
|
-
const
|
|
63
|
+
const reactModule = tryRequire("eslint-plugin-react", options.requireFn);
|
|
64
|
+
const reactConfig = readFlatConfig(reactModule, [
|
|
64
65
|
"configs",
|
|
65
66
|
"flat",
|
|
66
67
|
"recommended"
|
|
67
68
|
]);
|
|
68
69
|
if (options.enabled === true && reactConfig === void 0) throw new Error(`@exadev/eslint-config: React support was explicitly requested but 'eslint-plugin-react' could not be resolved. Install it with: ${INSTALL_COMMAND}`);
|
|
69
70
|
if (reactConfig === void 0) return [];
|
|
71
|
+
const jsxRuntimeConfig = readFlatConfig(reactModule, [
|
|
72
|
+
"configs",
|
|
73
|
+
"flat",
|
|
74
|
+
"jsx-runtime"
|
|
75
|
+
]);
|
|
70
76
|
const hooksModule = tryRequire("eslint-plugin-react-hooks", options.requireFn);
|
|
71
77
|
return [
|
|
72
78
|
reactConfig,
|
|
79
|
+
jsxRuntimeConfig,
|
|
73
80
|
readFlatConfig(hooksModule, [
|
|
74
81
|
"configs",
|
|
75
82
|
"flat",
|
|
@@ -83,7 +90,7 @@ function buildReactConfig(options = {}) {
|
|
|
83
90
|
}
|
|
84
91
|
//#endregion
|
|
85
92
|
//#region package.json
|
|
86
|
-
var version = "2.10.
|
|
93
|
+
var version = "2.10.4";
|
|
87
94
|
//#endregion
|
|
88
95
|
//#region src/rules/barrel-helpers.ts
|
|
89
96
|
const INDEX_BASENAME$1 = /^index\.[cm]?[tj]sx?$/;
|
|
@@ -115,6 +122,19 @@ function isPermittedBarrel(filename, mode) {
|
|
|
115
122
|
if (mode === "single") return isMainBarrel(filename);
|
|
116
123
|
return isIndexFile(filename);
|
|
117
124
|
}
|
|
125
|
+
function isAncestorNode(value) {
|
|
126
|
+
if (typeof value !== "object" || value === null) return false;
|
|
127
|
+
if (!("type" in value)) return false;
|
|
128
|
+
return typeof value.type === "string";
|
|
129
|
+
}
|
|
130
|
+
function isInsideAmbientModuleDeclaration(node) {
|
|
131
|
+
let current = node;
|
|
132
|
+
while (isAncestorNode(current)) {
|
|
133
|
+
if (current.type === "TSModuleDeclaration") return true;
|
|
134
|
+
current = current.parent;
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
118
138
|
function createSplitReexportDetector() {
|
|
119
139
|
const importsByName = /* @__PURE__ */ new Map();
|
|
120
140
|
const bareExportSpecifiers = [];
|
|
@@ -276,7 +296,7 @@ const barrelPolicy = {
|
|
|
276
296
|
},
|
|
277
297
|
ExportNamedDeclaration(node) {
|
|
278
298
|
detector.visitExportNamed(node);
|
|
279
|
-
if (hasSource(node)) {
|
|
299
|
+
if (hasSource(node) && !isInsideAmbientModuleDeclaration(node)) {
|
|
280
300
|
const source = node.source === null || node.source === void 0 ? void 0 : node.source.value;
|
|
281
301
|
if (!isPermittedBarrel(filename, mode)) context.report({
|
|
282
302
|
node,
|
|
@@ -290,6 +310,7 @@ const barrelPolicy = {
|
|
|
290
310
|
}
|
|
291
311
|
},
|
|
292
312
|
ExportAllDeclaration(node) {
|
|
313
|
+
if (isInsideAmbientModuleDeclaration(node)) return;
|
|
293
314
|
const source = node.source.value;
|
|
294
315
|
if (!isPermittedBarrel(filename, mode)) context.report({
|
|
295
316
|
node,
|