@zayne-labs/eslint-config 0.11.4 → 0.11.6
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 +204 -189
- package/dist/cli/index.js +4 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +1068 -614
- package/dist/index.js +151 -45
- package/dist/index.js.map +1 -1
- package/dist/src-BncWNtPe.js +671 -0
- package/dist/src-BncWNtPe.js.map +1 -0
- package/package.json +41 -40
- package/dist/src-MgbFTVE-.js +0 -1802
- package/dist/src-MgbFTVE-.js.map +0 -1
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
import globals from "globals";
|
|
2
|
+
|
|
3
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/util/ast.js
|
|
4
|
+
/**
|
|
5
|
+
* @import {Scope,Rule} from 'eslint'
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Get all references that ultimately flow into `ref`.
|
|
9
|
+
*
|
|
10
|
+
* @param {Rule.RuleContext} context
|
|
11
|
+
* @param {Scope.Reference} ref
|
|
12
|
+
* @param {"leaf" | "all"} [mode="all"]
|
|
13
|
+
* @param {Set<Scope.Reference>} visited
|
|
14
|
+
*
|
|
15
|
+
* @returns {Scope.Reference[]}
|
|
16
|
+
*/
|
|
17
|
+
const getUpstreamRefs = (context, ref, mode = "all", visited = /* @__PURE__ */ new Set()) => {
|
|
18
|
+
visited.add(ref);
|
|
19
|
+
const upstreamRefs = ref.resolved?.defs.filter((def) => def.type !== "ImportBinding").filter((def) => def.type !== "Parameter").map((def) => def.node.init ?? def.node.body).filter(Boolean).flatMap((node) => getDownstreamRefs(context, node)).filter((ref$1) => !visited.has(ref$1)).flatMap((ref$1) => getUpstreamRefs(context, ref$1, mode, visited));
|
|
20
|
+
const isLeafRef = upstreamRefs === void 0 || upstreamRefs.length === 0;
|
|
21
|
+
return mode === "leaf" ? isLeafRef ? [ref] : upstreamRefs : [ref].concat(upstreamRefs ?? []);
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Descend the AST from `node`, calling `visit` on each node.
|
|
25
|
+
*
|
|
26
|
+
* @param {Rule.RuleContext} context
|
|
27
|
+
* @param {Rule.Node} node
|
|
28
|
+
* @param {(node: Rule.Node) => void} visit
|
|
29
|
+
* @param {Set<Rule.Node>} visited
|
|
30
|
+
*/
|
|
31
|
+
const descend = (context, node, visit, visited = /* @__PURE__ */ new Set()) => {
|
|
32
|
+
if (visited.has(node)) return;
|
|
33
|
+
visit(node);
|
|
34
|
+
visited.add(node);
|
|
35
|
+
(context.sourceCode.visitorKeys[node.type] || []).map((key) => node[key]).filter(Boolean).flatMap((child) => Array.isArray(child) ? child : [child]).filter(Boolean).filter((child) => typeof child.type === "string").forEach((child) => descend(context, child, visit, visited));
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* @param {Rule.RuleContext} context
|
|
39
|
+
* @param {Rule.Node} topNode
|
|
40
|
+
* @param {string} type
|
|
41
|
+
*/
|
|
42
|
+
const findDownstreamNodes = (context, topNode, type) => {
|
|
43
|
+
const nodes = [];
|
|
44
|
+
descend(context, topNode, (node) => {
|
|
45
|
+
if (node.type === type) nodes.push(node);
|
|
46
|
+
});
|
|
47
|
+
return nodes;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* @param {Rule.RuleContext} context
|
|
51
|
+
* @param {Rule.Node} node
|
|
52
|
+
*/
|
|
53
|
+
const getDownstreamRefs = (context, node) => findDownstreamNodes(context, node, "Identifier").map((identifier) => getRef(context, identifier)).filter(Boolean);
|
|
54
|
+
/**
|
|
55
|
+
* @param {Scope.Reference} ref
|
|
56
|
+
* @param {Rule.Node} current
|
|
57
|
+
* @returns {Rule.Node | undefined}
|
|
58
|
+
*/
|
|
59
|
+
const getCallExpr = (ref, current = ref.identifier.parent) => {
|
|
60
|
+
if (current.type === "CallExpression") {
|
|
61
|
+
let node = ref.identifier;
|
|
62
|
+
while (node.parent.type === "MemberExpression") node = node.parent;
|
|
63
|
+
if (current.callee === node) return current;
|
|
64
|
+
}
|
|
65
|
+
if (current.type === "MemberExpression") return getCallExpr(ref, current.parent);
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* When using this, we assume that args passed to the derived function are always eventually passed to underlying functions.
|
|
69
|
+
* Which they may not be. Would be better to trace the actual flow of values, but that's complex. We'll start with this for now.
|
|
70
|
+
*
|
|
71
|
+
* @param {Rule.RuleContext} context
|
|
72
|
+
* @param {Scope.Reference} ref
|
|
73
|
+
* @param {"leaf" | "all"} [mode="all"] Whether to return all refs, or only leaf refs. Note that "all" includes `ref` itself.
|
|
74
|
+
* @returns {Rule.Node[]}
|
|
75
|
+
*/
|
|
76
|
+
const getArgsUpstreamRefs = (context, ref, mode) => getUpstreamRefs(context, ref, mode).map((ref$1) => getCallExpr(ref$1)).filter(Boolean).flatMap((callExpr) => callExpr.arguments).flatMap((arg) => getDownstreamRefs(context, arg)).flatMap((ref$1) => getUpstreamRefs(context, ref$1));
|
|
77
|
+
/**
|
|
78
|
+
* Walks up the AST until `within` (returns `true`) or finding any of (returns `false`):
|
|
79
|
+
* - An `async` function
|
|
80
|
+
* - A function declaration, which may be called at an arbitrary later time.
|
|
81
|
+
* - While we return false for *this* call, we may still return true for a call to a function containing this call. Combined with `getUpstreamRefs()`, it will still flag calls to the containing function.
|
|
82
|
+
* - A function passed as a callback to another function or `new` - event handler, `setTimeout`, `Promise.then()` `new ResizeObserver()`, etc.
|
|
83
|
+
*
|
|
84
|
+
* Inspired by https://eslint-react.xyz/docs/rules/hooks-extra-no-direct-set-state-in-use-effect
|
|
85
|
+
*
|
|
86
|
+
* @param {Rule.Node} node
|
|
87
|
+
* @param {Rule.Node} within
|
|
88
|
+
* @returns {boolean}
|
|
89
|
+
*/
|
|
90
|
+
const isSynchronous = (node, within) => {
|
|
91
|
+
if (node == within) return true;
|
|
92
|
+
else if (node.async || node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") return false;
|
|
93
|
+
else return isSynchronous(node.parent, within);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* @param {Rule.RuleContext} context
|
|
97
|
+
* @param {Rule.Node} identifier
|
|
98
|
+
*
|
|
99
|
+
* @returns {Scope.Reference | undefined}
|
|
100
|
+
*/
|
|
101
|
+
const getRef = (context, identifier) => context.sourceCode.getScope(identifier)?.references.find((ref) => ref.identifier == identifier);
|
|
102
|
+
/**
|
|
103
|
+
* @param {Rule.RuleContext} context
|
|
104
|
+
* @param {Scope.Reference} ref
|
|
105
|
+
* @param {(ref: Scope.Reference) => boolean} predicate
|
|
106
|
+
* @returns {boolean} Whether this reference eventually calls a function matching the given predicate.
|
|
107
|
+
*/
|
|
108
|
+
const isEventualCallTo = (context, ref, predicate) => getCallExpr(ref) !== void 0 && getUpstreamRefs(context, ref).some(predicate);
|
|
109
|
+
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/util/react.js
|
|
112
|
+
/**
|
|
113
|
+
* @import {Scope,Rule} from 'eslint'
|
|
114
|
+
*/
|
|
115
|
+
/**
|
|
116
|
+
* @param {Rule.Node} node
|
|
117
|
+
* @returns {boolean}
|
|
118
|
+
*/
|
|
119
|
+
const isReactFunctionalComponent = (node) => (node.type === "FunctionDeclaration" || node.type === "VariableDeclarator" && (node.init.type === "ArrowFunctionExpression" || node.init.type === "CallExpression")) && node.id.type === "Identifier" && node.id.name[0].toUpperCase() === node.id.name[0];
|
|
120
|
+
/**
|
|
121
|
+
* Excludes known pure HOCs like `memo` and `forwardRef`.
|
|
122
|
+
* Basically this is meant to detect custom HOCs that may have side effects, particularly when using their props.
|
|
123
|
+
*
|
|
124
|
+
* TODO: Will not detect when the component is defined normally and then exported wrapped in an HOC.
|
|
125
|
+
* e.g. `const MyComponent = (props) => {...}; export default memo(MyComponent);`
|
|
126
|
+
*
|
|
127
|
+
* @param {Rule.Node} node
|
|
128
|
+
* @returns {boolean}
|
|
129
|
+
*/
|
|
130
|
+
const isReactFunctionalHOC = (node) => node.type === "VariableDeclarator" && node.init && node.init.type === "CallExpression" && node.init.callee.type === "Identifier" && !["memo", "forwardRef"].includes(node.init.callee.name) && node.init.arguments.length > 0 && (node.init.arguments[0].type === "ArrowFunctionExpression" || node.init.arguments[0].type === "FunctionExpression") && node.id.type === "Identifier" && node.id.name[0].toUpperCase() === node.id.name[0];
|
|
131
|
+
/**
|
|
132
|
+
* @param {Rule.Node} node
|
|
133
|
+
* @returns {boolean}
|
|
134
|
+
*/
|
|
135
|
+
const isCustomHook = (node) => (node.type === "FunctionDeclaration" || node.type === "VariableDeclarator" && node.init && (node.init.type === "ArrowFunctionExpression" || node.init.type === "FunctionExpression")) && node.id.type === "Identifier" && node.id.name.startsWith("use") && node.id.name[3] === node.id.name[3].toUpperCase();
|
|
136
|
+
/**
|
|
137
|
+
* @param {Scope.Reference} ref
|
|
138
|
+
* @returns {boolean}
|
|
139
|
+
*/
|
|
140
|
+
const isUseState = (ref) => ref.identifier.type === "Identifier" && ref.identifier.name === "useState" || ref.identifier.parent.type === "MemberExpression" && ref.identifier.parent.object.name === "React" && ref.identifier.parent.property.name === "useState";
|
|
141
|
+
/**
|
|
142
|
+
* @param {Scope.Reference} ref
|
|
143
|
+
* @returns {boolean}
|
|
144
|
+
*/
|
|
145
|
+
const isState = (ref) => ref.resolved?.defs.some((def) => def.node.type === "VariableDeclarator" && def.node.id.type === "ArrayPattern" && (def.node.id.elements.length === 1 || def.node.id.elements.length === 2) && def.node.id.elements[0]?.type === "Identifier" && def.node.id.elements[0].name === ref.identifier.name);
|
|
146
|
+
/**
|
|
147
|
+
* @param {Scope.Reference} ref
|
|
148
|
+
* @returns {boolean}
|
|
149
|
+
*/
|
|
150
|
+
const isStateSetter = (ref) => ref.resolved?.defs.some((def) => def.node.type === "VariableDeclarator" && def.node.id.type === "ArrayPattern" && def.node.id.elements.length === 2 && def.node.id.elements[1]?.type === "Identifier" && def.node.id.elements[1].name === ref.identifier.name);
|
|
151
|
+
/**
|
|
152
|
+
* Returns false for props of HOCs (e.g. `withRouter`) because they usually have side effects.
|
|
153
|
+
*
|
|
154
|
+
* @param {Scope.Reference} ref
|
|
155
|
+
* @returns {boolean}
|
|
156
|
+
*/
|
|
157
|
+
const isProp = (ref) => ref.resolved?.defs.some((def) => {
|
|
158
|
+
const declaringNode = def.node.type === "ArrowFunctionExpression" ? def.node.parent.type === "CallExpression" ? def.node.parent.parent : def.node.parent : def.node;
|
|
159
|
+
return def.type === "Parameter" && (isReactFunctionalComponent(declaringNode) && !isReactFunctionalHOC(declaringNode) || isCustomHook(declaringNode));
|
|
160
|
+
});
|
|
161
|
+
/**
|
|
162
|
+
* @param {Scope.Reference} ref
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
165
|
+
const isConstant = (ref) => (ref.resolved?.defs ?? []).some((def) => def.node.type === "VariableDeclarator" && def.node.init?.type === "Literal" || def.node.init?.type === "TemplateLiteral" || def.node.init?.type === "ArrayExpression" || def.node.init?.type === "ObjectExpression");
|
|
166
|
+
/**
|
|
167
|
+
* @param {Scope.Reference} ref
|
|
168
|
+
* @returns {boolean}
|
|
169
|
+
*/
|
|
170
|
+
const isUseRef = (ref) => ref.identifier.type === "Identifier" && ref.identifier.name === "useRef" || ref.identifier.parent.type === "MemberExpression" && ref.identifier.parent.object.name === "React" && ref.identifier.parent.property.name === "useRef";
|
|
171
|
+
/**
|
|
172
|
+
* @param {Scope.Reference} ref
|
|
173
|
+
* @returns {boolean}
|
|
174
|
+
*/
|
|
175
|
+
const isRef = (ref) => ref.resolved?.defs.some((def) => def.node.type === "VariableDeclarator" && def.node.init?.type === "CallExpression" && (def.node.init.callee.type === "Identifier" && def.node.init.callee.name === "useRef" || def.node.init.callee.type === "MemberExpression" && def.node.init.callee.object.name === "React" && def.node.init.callee.property.name === "useRef"));
|
|
176
|
+
/**
|
|
177
|
+
* Whether the reference's `current` property is being accessed.
|
|
178
|
+
* Heuristic for whether the reference is a React ref object.
|
|
179
|
+
* Because we don't always have access to the `useRef` call itself.
|
|
180
|
+
* For example when receiving a ref from props.
|
|
181
|
+
*
|
|
182
|
+
* @param {Scope.Reference} ref
|
|
183
|
+
* @returns {boolean}
|
|
184
|
+
*/
|
|
185
|
+
const isRefCurrent = (ref) => ref.identifier.parent.type === "MemberExpression" && ref.identifier.parent.property.type === "Identifier" && ref.identifier.parent.property.name === "current";
|
|
186
|
+
/**
|
|
187
|
+
* Does not include `useLayoutEffect`.
|
|
188
|
+
* When used correctly, it interacts with the DOM = external system = (probably) valid effect.
|
|
189
|
+
* When used incorrectly, it's probably too difficult to accurately analyze anyway.
|
|
190
|
+
*
|
|
191
|
+
* @param {Rule.Node} node
|
|
192
|
+
* @returns {boolean}
|
|
193
|
+
*/
|
|
194
|
+
const isUseEffect = (node) => node.type === "CallExpression" && (node.callee.type === "Identifier" && node.callee.name === "useEffect" || node.callee.type === "MemberExpression" && node.callee.object.name === "React" && node.callee.property.name === "useEffect");
|
|
195
|
+
/**
|
|
196
|
+
* @param {Rule.Node} node - The `useEffect` `CallExpression` node
|
|
197
|
+
* @returns {Rule.Node | undefined}
|
|
198
|
+
*/
|
|
199
|
+
const getEffectFn = (node) => {
|
|
200
|
+
const effectFn = node.arguments[0];
|
|
201
|
+
if (effectFn?.type !== "ArrowFunctionExpression" && effectFn?.type !== "FunctionExpression") return;
|
|
202
|
+
return effectFn;
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* @param {Rule.RuleContext} context
|
|
206
|
+
* @param {Rule.Node} node - The `useEffect` `CallExpression` node
|
|
207
|
+
* @returns {Scope.Reference[] | undefined}
|
|
208
|
+
*/
|
|
209
|
+
const getEffectFnRefs = (context, node) => {
|
|
210
|
+
const effectFn = getEffectFn(node);
|
|
211
|
+
return effectFn ? getDownstreamRefs(context, effectFn) : void 0;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* @param {Rule.RuleContext} context
|
|
215
|
+
* @param {Rule.Node} node - The `useEffect` `CallExpression` node
|
|
216
|
+
* @returns {Scope.Reference[] | undefined}
|
|
217
|
+
*/
|
|
218
|
+
function getEffectDepsRefs(context, node) {
|
|
219
|
+
const depsArr = node.arguments[1];
|
|
220
|
+
if (depsArr?.type !== "ArrayExpression") return;
|
|
221
|
+
return getDownstreamRefs(context, depsArr);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* @param {Rule.RuleContext} context
|
|
225
|
+
* @param {Scope.Reference} ref
|
|
226
|
+
* @returns {boolean} Whether this reference eventually calls a state setter function or a method on state.
|
|
227
|
+
*/
|
|
228
|
+
const callsStateSetter = (context, ref) => isEventualCallTo(context, ref, isStateSetter);
|
|
229
|
+
/**
|
|
230
|
+
* @param {Rule.RuleContext} context
|
|
231
|
+
* @param {Scope.Reference} ref
|
|
232
|
+
* @returns {boolean} Whether this reference eventually calls a prop function or a method on a prop.
|
|
233
|
+
*/
|
|
234
|
+
const callsProp = (context, ref) => isEventualCallTo(context, ref, isProp);
|
|
235
|
+
/**
|
|
236
|
+
* @param {Rule.RuleContext} context
|
|
237
|
+
* @param {Scope.Reference} ref
|
|
238
|
+
* @returns {boolean} Whether this reference eventually calls a method on a ref.
|
|
239
|
+
*/
|
|
240
|
+
const callsRef = (context, ref) => isEventualCallTo(context, ref, (ref$1) => isRefCurrent(ref$1) || isRef(ref$1));
|
|
241
|
+
/**
|
|
242
|
+
* @param context {Rule.RuleContext}
|
|
243
|
+
* @param {Scope.Reference} ref
|
|
244
|
+
* @returns {Rule.Node | undefined} The `VariableDeclarator` node of the `useState` call.
|
|
245
|
+
*/
|
|
246
|
+
const getUseStateDecl = (context, ref) => {
|
|
247
|
+
let node = getUpstreamRefs(context, ref).find((ref$1) => isUseState(ref$1))?.identifier;
|
|
248
|
+
while (node && node.type !== "VariableDeclarator") node = node.parent;
|
|
249
|
+
return node;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* While it *could* be an anti-pattern or unnecessary, effects *are* meant to synchronize systems.
|
|
253
|
+
* So we presume that a "subscription effect" is usually valid, or at least may be more readable.
|
|
254
|
+
*
|
|
255
|
+
* TODO: We might be able to use this more granularly, e.g. ignore state setters inside a subscription effect,
|
|
256
|
+
* instead of ignoring the whole effect...? But it'd have to be more complicated, like also ignore the same state setters called in the body.
|
|
257
|
+
*
|
|
258
|
+
* @param {Rule.Node} node - The `useEffect` `CallExpression` node
|
|
259
|
+
* @returns {boolean}
|
|
260
|
+
*/
|
|
261
|
+
const hasCleanup = (node) => {
|
|
262
|
+
const effectFn = node.arguments[0];
|
|
263
|
+
return (effectFn.type === "ArrowFunctionExpression" || effectFn.type === "FunctionExpression") && effectFn.body.type === "BlockStatement" && effectFn.body.body.some((stmt) => stmt.type === "ReturnStatement" && stmt.argument);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
//#endregion
|
|
267
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-empty-effect.js
|
|
268
|
+
/**
|
|
269
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
270
|
+
*/
|
|
271
|
+
var no_empty_effect_default = {
|
|
272
|
+
meta: {
|
|
273
|
+
type: "suggestion",
|
|
274
|
+
docs: { description: "Disallow empty effects." },
|
|
275
|
+
schema: [],
|
|
276
|
+
messages: { avoidEmptyEffect: "This effect is empty and could be removed." }
|
|
277
|
+
},
|
|
278
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
279
|
+
if (!isUseEffect(node)) return;
|
|
280
|
+
if (node.arguments?.length === 0 || getEffectFnRefs(context, node)?.length === 0) context.report({
|
|
281
|
+
node,
|
|
282
|
+
messageId: "avoidEmptyEffect"
|
|
283
|
+
});
|
|
284
|
+
} })
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
//#endregion
|
|
288
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-adjust-state-on-prop-change.js
|
|
289
|
+
/**
|
|
290
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
291
|
+
*/
|
|
292
|
+
var no_adjust_state_on_prop_change_default = {
|
|
293
|
+
meta: {
|
|
294
|
+
type: "suggestion",
|
|
295
|
+
docs: {
|
|
296
|
+
description: "Disallow adjusting state in an effect when a prop changes.",
|
|
297
|
+
url: "https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes"
|
|
298
|
+
},
|
|
299
|
+
schema: [],
|
|
300
|
+
messages: { avoidAdjustingStateWhenAPropChanges: "Avoid adjusting state when a prop changes. Instead, adjust the state directly during render, or refactor your state to avoid this need entirely." }
|
|
301
|
+
},
|
|
302
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
303
|
+
if (!isUseEffect(node)) return;
|
|
304
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
305
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
306
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
307
|
+
const isSomeDepsProps = depsRefs.flatMap((ref) => getUpstreamRefs(context, ref)).some((ref) => isProp(ref));
|
|
308
|
+
effectFnRefs.filter((ref) => callsStateSetter(context, ref)).filter((ref) => isSynchronous(ref.identifier, getEffectFn(node))).forEach((ref) => {
|
|
309
|
+
const callExpr = getCallExpr(ref);
|
|
310
|
+
const isSomeArgsProps = getArgsUpstreamRefs(context, ref).some((ref$1) => isProp(ref$1));
|
|
311
|
+
if (isSomeDepsProps && !isSomeArgsProps) context.report({
|
|
312
|
+
node: callExpr,
|
|
313
|
+
messageId: "avoidAdjustingStateWhenAPropChanges"
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
} })
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-reset-all-state-on-prop-change.js
|
|
321
|
+
/**
|
|
322
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
323
|
+
*/
|
|
324
|
+
var no_reset_all_state_on_prop_change_default = {
|
|
325
|
+
meta: {
|
|
326
|
+
type: "suggestion",
|
|
327
|
+
docs: {
|
|
328
|
+
description: "Disallow resetting all state in an effect when a prop changes.",
|
|
329
|
+
url: "https://react.dev/learn/you-might-not-need-an-effect#resetting-all-state-when-a-prop-changes"
|
|
330
|
+
},
|
|
331
|
+
schema: [],
|
|
332
|
+
messages: { avoidResettingAllStateWhenAPropChanges: "Avoid resetting all state when a prop changes. If \"{{prop}}\" is a key, pass it as `key` instead so React will reset the component." }
|
|
333
|
+
},
|
|
334
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
335
|
+
if (!isUseEffect(node)) return;
|
|
336
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
337
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
338
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
339
|
+
const containingNode = findContainingNode(node);
|
|
340
|
+
if (containingNode && isCustomHook(containingNode)) return;
|
|
341
|
+
const propUsedToResetAllState = findPropUsedToResetAllState(context, effectFnRefs, depsRefs, node);
|
|
342
|
+
if (propUsedToResetAllState) context.report({
|
|
343
|
+
node,
|
|
344
|
+
messageId: "avoidResettingAllStateWhenAPropChanges",
|
|
345
|
+
data: { prop: propUsedToResetAllState.identifier.name }
|
|
346
|
+
});
|
|
347
|
+
} })
|
|
348
|
+
};
|
|
349
|
+
const findPropUsedToResetAllState = (context, effectFnRefs, depsRefs, useEffectNode) => {
|
|
350
|
+
const stateSetterRefs = effectFnRefs.filter((ref) => callsStateSetter(context, ref));
|
|
351
|
+
return stateSetterRefs.length > 0 && stateSetterRefs.every((ref) => isSetStateToInitialValue(context, ref)) && stateSetterRefs.length === countUseStates(context, findContainingNode(useEffectNode)) ? depsRefs.flatMap((ref) => getUpstreamRefs(context, ref)).find((ref) => isProp(ref)) : void 0;
|
|
352
|
+
};
|
|
353
|
+
const isSetStateToInitialValue = (context, setterRef) => {
|
|
354
|
+
const setStateToValue = getCallExpr(setterRef).arguments[0];
|
|
355
|
+
const stateInitialValue = getUseStateDecl(context, setterRef).init.arguments[0];
|
|
356
|
+
const isUndefined = (node) => node === void 0 || node.name === "undefined";
|
|
357
|
+
if (isUndefined(setStateToValue) && isUndefined(stateInitialValue)) return true;
|
|
358
|
+
if (setStateToValue === null && stateInitialValue === null) return true;
|
|
359
|
+
else if (setStateToValue && !stateInitialValue || !setStateToValue && stateInitialValue) return false;
|
|
360
|
+
return context.sourceCode.getText(setStateToValue) === context.sourceCode.getText(stateInitialValue);
|
|
361
|
+
};
|
|
362
|
+
const countUseStates = (context, componentNode) => {
|
|
363
|
+
if (!componentNode) return 0;
|
|
364
|
+
return getDownstreamRefs(context, componentNode).filter((ref) => isState(ref)).length;
|
|
365
|
+
};
|
|
366
|
+
const findContainingNode = (node) => {
|
|
367
|
+
if (!node) return;
|
|
368
|
+
else if (isReactFunctionalComponent(node) || isReactFunctionalHOC(node) || isCustomHook(node)) return node;
|
|
369
|
+
else return findContainingNode(node.parent);
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
//#endregion
|
|
373
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-event-handler.js
|
|
374
|
+
/**
|
|
375
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
376
|
+
*/
|
|
377
|
+
var no_event_handler_default = {
|
|
378
|
+
meta: {
|
|
379
|
+
type: "suggestion",
|
|
380
|
+
docs: {
|
|
381
|
+
description: "Disallow using state and an effect as an event handler.",
|
|
382
|
+
url: "https://react.dev/learn/you-might-not-need-an-effect#sharing-logic-between-event-handlers"
|
|
383
|
+
},
|
|
384
|
+
schema: [],
|
|
385
|
+
messages: { avoidEventHandler: "Avoid using state and effects as an event handler. Instead, call the event handling code directly when the event occurs." }
|
|
386
|
+
},
|
|
387
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
388
|
+
if (!isUseEffect(node) || hasCleanup(node)) return;
|
|
389
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
390
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
391
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
392
|
+
findDownstreamNodes(context, node, "IfStatement").filter((ifNode) => !ifNode.alternate).filter((ifNode) => getDownstreamRefs(context, ifNode.test).flatMap((ref) => getUpstreamRefs(context, ref)).some((ref) => isState(ref))).forEach((ifNode) => {
|
|
393
|
+
context.report({
|
|
394
|
+
node: ifNode.test,
|
|
395
|
+
messageId: "avoidEventHandler"
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
} })
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
//#endregion
|
|
402
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-pass-live-state-to-parent.js
|
|
403
|
+
/**
|
|
404
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
405
|
+
*/
|
|
406
|
+
var no_pass_live_state_to_parent_default = {
|
|
407
|
+
meta: {
|
|
408
|
+
type: "suggestion",
|
|
409
|
+
docs: {
|
|
410
|
+
description: "Disallow passing live state to parent components in an effect.",
|
|
411
|
+
url: "https://react.dev/learn/you-might-not-need-an-effect#notifying-parent-components-about-state-changes"
|
|
412
|
+
},
|
|
413
|
+
schema: [],
|
|
414
|
+
messages: { avoidPassingLiveStateToParent: "Avoid passing live state to parents in an effect. Instead, lift the state to the parent and pass it down to the child as a prop." }
|
|
415
|
+
},
|
|
416
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
417
|
+
if (!isUseEffect(node)) return;
|
|
418
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
419
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
420
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
421
|
+
effectFnRefs.filter((ref) => callsProp(context, ref)).filter((ref) => isSynchronous(ref.identifier, getEffectFn(node))).forEach((ref) => {
|
|
422
|
+
const callExpr = getCallExpr(ref);
|
|
423
|
+
if (getArgsUpstreamRefs(context, ref).some((ref$1) => isState(ref$1))) context.report({
|
|
424
|
+
node: callExpr,
|
|
425
|
+
messageId: "avoidPassingLiveStateToParent"
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
} })
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
//#endregion
|
|
432
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-initialize-state.js
|
|
433
|
+
/**
|
|
434
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
435
|
+
*/
|
|
436
|
+
var no_initialize_state_default = {
|
|
437
|
+
meta: {
|
|
438
|
+
type: "suggestion",
|
|
439
|
+
docs: {
|
|
440
|
+
description: "Disallow initializing state in an effect.",
|
|
441
|
+
url: "https://tkdodo.eu/blog/avoiding-hydration-mismatches-with-use-sync-external-store"
|
|
442
|
+
},
|
|
443
|
+
schema: [],
|
|
444
|
+
messages: { avoidInitializingState: "Avoid initializing state in an effect. Instead, initialize \"{{state}}\"'s `useState()` with \"{{arguments}}\". For SSR hydration, prefer `useSyncExternalStore()`." }
|
|
445
|
+
},
|
|
446
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
447
|
+
if (!isUseEffect(node)) return;
|
|
448
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
449
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
450
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
451
|
+
if (depsRefs.length > 0) return;
|
|
452
|
+
effectFnRefs.filter((ref) => callsStateSetter(context, ref)).filter((ref) => isSynchronous(ref.identifier, getEffectFn(node))).forEach((ref) => {
|
|
453
|
+
const callExpr = getCallExpr(ref);
|
|
454
|
+
const useStateNode = getUseStateDecl(context, ref);
|
|
455
|
+
const stateName = (useStateNode.id.elements[0] ?? useStateNode.id.elements[1])?.name;
|
|
456
|
+
const argumentText = callExpr.arguments[0] ? context.sourceCode.getText(callExpr.arguments[0]) : "undefined";
|
|
457
|
+
context.report({
|
|
458
|
+
node: getCallExpr(ref),
|
|
459
|
+
messageId: "avoidInitializingState",
|
|
460
|
+
data: {
|
|
461
|
+
state: stateName,
|
|
462
|
+
arguments: argumentText
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
} })
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
//#endregion
|
|
470
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-chain-state-updates.js
|
|
471
|
+
/**
|
|
472
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
473
|
+
*/
|
|
474
|
+
var no_chain_state_updates_default = {
|
|
475
|
+
meta: {
|
|
476
|
+
type: "suggestion",
|
|
477
|
+
docs: {
|
|
478
|
+
description: "Disallow chaining state changes in an effect.",
|
|
479
|
+
url: "https://react.dev/learn/you-might-not-need-an-effect#chains-of-computations"
|
|
480
|
+
},
|
|
481
|
+
schema: [],
|
|
482
|
+
messages: { avoidChainingStateUpdates: "Avoid chaining state changes. When possible, update all relevant state simultaneously." }
|
|
483
|
+
},
|
|
484
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
485
|
+
if (!isUseEffect(node) || hasCleanup(node)) return;
|
|
486
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
487
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
488
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
489
|
+
const isSomeDepsState = depsRefs.flatMap((ref) => getUpstreamRefs(context, ref)).some((ref) => isState(ref));
|
|
490
|
+
effectFnRefs.filter((ref) => callsStateSetter(context, ref)).filter((ref) => isSynchronous(ref.identifier, getEffectFn(node))).forEach((ref) => {
|
|
491
|
+
const callExpr = getCallExpr(ref);
|
|
492
|
+
const isSomeArgsState = getArgsUpstreamRefs(context, ref).some((ref$1) => isState(ref$1));
|
|
493
|
+
if (isSomeDepsState && !isSomeArgsState) context.report({
|
|
494
|
+
node: callExpr,
|
|
495
|
+
messageId: "avoidChainingStateUpdates"
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
} })
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
//#endregion
|
|
502
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-derived-state.js
|
|
503
|
+
/**
|
|
504
|
+
* @type {import('eslint').Rule.RuleModule}
|
|
505
|
+
*/
|
|
506
|
+
var no_derived_state_default = {
|
|
507
|
+
meta: {
|
|
508
|
+
type: "suggestion",
|
|
509
|
+
docs: {
|
|
510
|
+
description: "Disallow storing derived state in an effect.",
|
|
511
|
+
url: "https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state"
|
|
512
|
+
},
|
|
513
|
+
schema: [],
|
|
514
|
+
messages: {
|
|
515
|
+
avoidDerivedState: "Avoid storing derived state. Compute \"{{state}}\" directly during render, optionally with `useMemo` if it's expensive.",
|
|
516
|
+
avoidSingleSetter: "Avoid storing derived state. \"{{state}}\" is only set here, and thus could be computed directly during render."
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
520
|
+
if (!isUseEffect(node) || hasCleanup(node)) return;
|
|
521
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
522
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
523
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
524
|
+
effectFnRefs.filter((ref) => callsStateSetter(context, ref)).filter((ref) => isSynchronous(ref.identifier, getEffectFn(node))).forEach((ref) => {
|
|
525
|
+
const callExpr = getCallExpr(ref);
|
|
526
|
+
const useStateNode = getUseStateDecl(context, ref);
|
|
527
|
+
const stateName = (useStateNode?.id.elements[0] ?? useStateNode?.id.elements[1])?.name;
|
|
528
|
+
const argsUpstreamRefs = getArgsUpstreamRefs(context, ref);
|
|
529
|
+
const depsUpstreamRefs = depsRefs.flatMap((ref$1) => getUpstreamRefs(context, ref$1));
|
|
530
|
+
const isSomeArgsInternal = argsUpstreamRefs.some((ref$1) => isState(ref$1) || isProp(ref$1));
|
|
531
|
+
const isValueAlwaysInSync = argsUpstreamRefs.length && argsUpstreamRefs.every((argRef) => depsUpstreamRefs.some((depRef) => argRef.resolved == depRef.resolved)) && countCalls(ref) === 1;
|
|
532
|
+
if (isSomeArgsInternal) context.report({
|
|
533
|
+
node: callExpr,
|
|
534
|
+
messageId: "avoidDerivedState",
|
|
535
|
+
data: { state: stateName }
|
|
536
|
+
});
|
|
537
|
+
else if (isValueAlwaysInSync) context.report({
|
|
538
|
+
node: callExpr,
|
|
539
|
+
messageId: "avoidSingleSetter",
|
|
540
|
+
data: { state: stateName }
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
} })
|
|
544
|
+
};
|
|
545
|
+
const countCalls = (ref) => ref.resolved.references.filter((ref$1) => ref$1.identifier.parent.type === "CallExpression").length;
|
|
546
|
+
|
|
547
|
+
//#endregion
|
|
548
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-pass-data-to-parent.js
|
|
549
|
+
/**
|
|
550
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
551
|
+
*/
|
|
552
|
+
var no_pass_data_to_parent_default = {
|
|
553
|
+
meta: {
|
|
554
|
+
type: "suggestion",
|
|
555
|
+
docs: {
|
|
556
|
+
description: "Disallow passing data to parents in an effect.",
|
|
557
|
+
url: "https://react.dev/learn/you-might-not-need-an-effect#passing-data-to-the-parent"
|
|
558
|
+
},
|
|
559
|
+
schema: [],
|
|
560
|
+
messages: { avoidPassingDataToParent: "Avoid passing data to parents in an effect. Instead, let the parent fetch the data itself and pass it down to the child as a prop." }
|
|
561
|
+
},
|
|
562
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
563
|
+
if (!isUseEffect(node) || hasCleanup(node)) return;
|
|
564
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
565
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
566
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
567
|
+
effectFnRefs.filter((ref) => callsProp(context, ref)).filter((ref) => !callsRef(context, ref)).filter((ref) => isSynchronous(ref.identifier, getEffectFn(node))).forEach((ref) => {
|
|
568
|
+
const callExpr = getCallExpr(ref);
|
|
569
|
+
if (getUpstreamRefs(context, ref).map((ref$1) => getCallExpr(ref$1)).filter(Boolean).flatMap((callExpr$1) => callExpr$1.arguments).flatMap((arg) => getDownstreamRefs(context, arg)).flatMap((ref$1) => getUpstreamRefs(context, ref$1, "leaf")).some((ref$1) => !isUseState(ref$1) && !isProp(ref$1) && !isUseRef(ref$1) && !isRefCurrent(ref$1) && !isConstant(ref$1))) context.report({
|
|
570
|
+
node: callExpr,
|
|
571
|
+
messageId: "avoidPassingDataToParent"
|
|
572
|
+
});
|
|
573
|
+
});
|
|
574
|
+
} })
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
//#endregion
|
|
578
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/rules/no-pass-ref-to-parent.js
|
|
579
|
+
/**
|
|
580
|
+
* @type {import("eslint").Rule.RuleModule}
|
|
581
|
+
*/
|
|
582
|
+
var no_pass_ref_to_parent_default = {
|
|
583
|
+
meta: {
|
|
584
|
+
type: "suggestion",
|
|
585
|
+
docs: {
|
|
586
|
+
description: "Disallow passing refs, or data from callbacks registered on them, to parents in an effect. Use `forwardRef` instead.",
|
|
587
|
+
url: "https://react.dev/reference/react/forwardRef"
|
|
588
|
+
},
|
|
589
|
+
schema: [],
|
|
590
|
+
messages: {
|
|
591
|
+
avoidPassingRefToParent: "Avoid passing refs to parents in an effect. Use `forwardRef` instead.",
|
|
592
|
+
avoidPropCallbackInRefCallback: "Avoid calling props inside callbacks registered on refs in an effect. Use `forwardRef` to register the callback in the parent instead.",
|
|
593
|
+
avoidReceivingRefFromParent: "Avoid receiving refs from parents to use in an effect. Use `forwardRef` instead."
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
create: (context) => ({ CallExpression: (node) => {
|
|
597
|
+
if (!isUseEffect(node) || hasCleanup(node)) return;
|
|
598
|
+
const effectFnRefs = getEffectFnRefs(context, node);
|
|
599
|
+
const depsRefs = getEffectDepsRefs(context, node);
|
|
600
|
+
if (!effectFnRefs || !depsRefs) return;
|
|
601
|
+
effectFnRefs.filter((ref) => callsProp(context, ref)).forEach((ref) => {
|
|
602
|
+
const callExpr = getCallExpr(ref);
|
|
603
|
+
if (getArgsUpstreamRefs(context, ref).some((ref$1) => isRef(ref$1))) context.report({
|
|
604
|
+
node: callExpr,
|
|
605
|
+
messageId: "avoidPassingRefToParent"
|
|
606
|
+
});
|
|
607
|
+
});
|
|
608
|
+
effectFnRefs.filter((ref) => callsRef(context, ref)).forEach((ref) => {
|
|
609
|
+
const callExpr = getCallExpr(ref);
|
|
610
|
+
if (getArgsUpstreamRefs(context, ref).some((ref$1) => callsProp(context, ref$1))) context.report({
|
|
611
|
+
node: callExpr,
|
|
612
|
+
messageId: "avoidPropCallbackInRefCallback"
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
effectFnRefs.filter((ref) => callsProp(context, ref) && callsRef(context, ref)).forEach((ref) => {
|
|
616
|
+
const callExpr = getCallExpr(ref);
|
|
617
|
+
context.report({
|
|
618
|
+
node: callExpr,
|
|
619
|
+
messageId: "avoidReceivingRefFromParent"
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
} })
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
//#endregion
|
|
626
|
+
//#region ../../node_modules/.pnpm/eslint-plugin-react-you-might-not-need-an-effect@0.8.1_eslint@9.39.2_jiti@2.6.1_/node_modules/eslint-plugin-react-you-might-not-need-an-effect/src/index.js
|
|
627
|
+
/**
|
|
628
|
+
* @type {import("eslint").ESLint.Plugin}
|
|
629
|
+
*/
|
|
630
|
+
const plugin = {
|
|
631
|
+
meta: { name: "react-you-might-not-need-an-effect" },
|
|
632
|
+
configs: {},
|
|
633
|
+
rules: {
|
|
634
|
+
"no-empty-effect": no_empty_effect_default,
|
|
635
|
+
"no-adjust-state-on-prop-change": no_adjust_state_on_prop_change_default,
|
|
636
|
+
"no-reset-all-state-on-prop-change": no_reset_all_state_on_prop_change_default,
|
|
637
|
+
"no-event-handler": no_event_handler_default,
|
|
638
|
+
"no-pass-live-state-to-parent": no_pass_live_state_to_parent_default,
|
|
639
|
+
"no-pass-data-to-parent": no_pass_data_to_parent_default,
|
|
640
|
+
"no-pass-ref-to-parent": no_pass_ref_to_parent_default,
|
|
641
|
+
"no-initialize-state": no_initialize_state_default,
|
|
642
|
+
"no-chain-state-updates": no_chain_state_updates_default,
|
|
643
|
+
"no-derived-state": no_derived_state_default
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
const recommendedRules = Object.keys(plugin.rules).reduce((acc, ruleName) => {
|
|
647
|
+
acc[plugin.meta.name + "/" + ruleName] = "warn";
|
|
648
|
+
return acc;
|
|
649
|
+
}, {});
|
|
650
|
+
const languageOptions = {
|
|
651
|
+
globals: { ...globals.browser },
|
|
652
|
+
parserOptions: { ecmaFeatures: { jsx: true } }
|
|
653
|
+
};
|
|
654
|
+
Object.assign(plugin.configs, {
|
|
655
|
+
recommended: {
|
|
656
|
+
files: ["**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}"],
|
|
657
|
+
plugins: { [plugin.meta.name]: plugin },
|
|
658
|
+
rules: recommendedRules,
|
|
659
|
+
languageOptions
|
|
660
|
+
},
|
|
661
|
+
"legacy-recommended": {
|
|
662
|
+
plugins: [plugin.meta.name],
|
|
663
|
+
rules: recommendedRules,
|
|
664
|
+
...languageOptions
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
var src_default = plugin;
|
|
668
|
+
|
|
669
|
+
//#endregion
|
|
670
|
+
export { src_default as default };
|
|
671
|
+
//# sourceMappingURL=src-BncWNtPe.js.map
|