react-doctor 0.2.0-beta.0 → 0.2.0-beta.2

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.
@@ -1,604 +0,0 @@
1
- import { u as reactDoctorOxlintRules } from "./rules-BfZ4Ujfv.js";
2
- import { createRequire } from "node:module";
3
- import path from "node:path";
4
- //#region src/core/rules/lint/config.ts
5
- const esmRequire = createRequire(import.meta.url);
6
- const REACT_DOCTOR_OXLINT_RULE_KEY_PREFIX = "react-doctor/";
7
- const REACT_HOOKS_JS_NAMESPACE = "react-hooks-js";
8
- const REACT_HOOKS_PLUGIN_SPECIFIER = "eslint-plugin-react-hooks";
9
- const UNCONSTRAINED_REACT_MAJOR = 99;
10
- const YOU_MIGHT_NOT_NEED_EFFECT_NAMESPACE = "effect";
11
- const YOU_MIGHT_NOT_NEED_EFFECT_PLUGIN_SPECIFIER = "eslint-plugin-react-you-might-not-need-an-effect";
12
- const DEFAULT_OXLINT_RULE_SEVERITY = "warn";
13
- const NEXTJS_RULE_NAME_PREFIX = "nextjs-";
14
- const TANSTACK_AI_RULE_NAME_PREFIX = "tanstack-ai-";
15
- const TANSTACK_START_RULE_NAME_PREFIX = "tanstack-start-";
16
- const TANSTACK_QUERY_RULE_NAME_PREFIX = "query-";
17
- const REACT_NATIVE_RULE_NAME_PREFIXES = ["expo-", "rn-"];
18
- const ECOSYSTEM_RULE_NAME_PREFIXES = [
19
- "tailwind-",
20
- "motion-",
21
- "swr-",
22
- "mobx-",
23
- "i18n-",
24
- "shadcn-",
25
- "radix-",
26
- "rhf-",
27
- "testing-",
28
- "storybook-",
29
- "r3f-"
30
- ];
31
- const REACT_DOCTOR_ERROR_RULE_NAMES = new Set([
32
- "nextjs-async-client-component",
33
- "nextjs-no-head-import",
34
- "nextjs-no-side-effect-in-get-handler",
35
- "rn-no-raw-text",
36
- "rn-no-deprecated-modules",
37
- "rn-no-scroll-state",
38
- "rn-animate-layout-property",
39
- "tanstack-start-route-property-order",
40
- "tanstack-start-server-fn-method-order",
41
- "tanstack-start-no-dynamic-server-fn-import",
42
- "tanstack-start-no-use-server-in-handler",
43
- "tanstack-start-no-secrets-in-loader",
44
- "query-no-unstable-query-key",
45
- "tailwind-oklch-alpha-syntax",
46
- "swr-no-unstable-key",
47
- "radix-aschild-single-child",
48
- "testing-await-user-event",
49
- "storybook-await-play-interactions",
50
- "r3f-no-new-in-frame",
51
- "r3f-no-clone-in-frame",
52
- "no-mutable-in-deps",
53
- "no-effect-event-in-deps",
54
- "rerender-dependencies",
55
- "effect-needs-cleanup",
56
- "no-random-key",
57
- "no-nested-component-definition",
58
- "no-legacy-class-lifecycles",
59
- "no-legacy-context-api",
60
- "no-layout-property-animation",
61
- "no-global-css-variable-animation",
62
- "no-eval",
63
- "server-auth-actions",
64
- "server-no-mutable-module-state",
65
- "no-disabled-zoom"
66
- ]);
67
- const YOU_MIGHT_NOT_NEED_EFFECT_OXLINT_RULES = {
68
- "effect/no-derived-state": "warn",
69
- "effect/no-chain-state-updates": "warn",
70
- "effect/no-event-handler": "warn",
71
- "effect/no-adjust-state-on-prop-change": "warn",
72
- "effect/no-reset-all-state-on-prop-change": "warn",
73
- "effect/no-pass-live-state-to-parent": "warn",
74
- "effect/no-pass-data-to-parent": "warn",
75
- "effect/no-initialize-state": "warn"
76
- };
77
- const REACT_COMPILER_OXLINT_RULES = {
78
- "react-hooks-js/set-state-in-render": "error",
79
- "react-hooks-js/immutability": "error",
80
- "react-hooks-js/refs": "error",
81
- "react-hooks-js/purity": "error",
82
- "react-hooks-js/hooks": "error",
83
- "react-hooks-js/set-state-in-effect": "error",
84
- "react-hooks-js/globals": "error",
85
- "react-hooks-js/error-boundaries": "error",
86
- "react-hooks-js/preserve-manual-memoization": "error",
87
- "react-hooks-js/unsupported-syntax": "error",
88
- "react-hooks-js/component-hook-factories": "error",
89
- "react-hooks-js/static-components": "error",
90
- "react-hooks-js/use-memo": "error",
91
- "react-hooks-js/void-use-memo": "error",
92
- "react-hooks-js/incompatible-library": "error",
93
- "react-hooks-js/todo": "error"
94
- };
95
- const BUILTIN_REACT_OXLINT_RULES = {
96
- "react/rules-of-hooks": "error",
97
- "react/exhaustive-deps": "warn",
98
- "react/no-direct-mutation-state": "error",
99
- "react/jsx-no-duplicate-props": "error",
100
- "react/jsx-key": "error",
101
- "react/no-children-prop": "warn",
102
- "react/no-danger": "warn",
103
- "react/jsx-no-script-url": "error",
104
- "react/no-render-return-value": "warn",
105
- "react/no-string-refs": "warn",
106
- "react/no-is-mounted": "warn",
107
- "react/require-render-return": "error",
108
- "react/no-unknown-property": "warn"
109
- };
110
- const BUILTIN_A11Y_OXLINT_RULES = {
111
- "jsx-a11y/alt-text": "error",
112
- "jsx-a11y/anchor-is-valid": "warn",
113
- "jsx-a11y/click-events-have-key-events": "warn",
114
- "jsx-a11y/no-static-element-interactions": "warn",
115
- "jsx-a11y/role-has-required-aria-props": "error",
116
- "jsx-a11y/no-autofocus": "warn",
117
- "jsx-a11y/heading-has-content": "warn",
118
- "jsx-a11y/html-has-lang": "warn",
119
- "jsx-a11y/no-redundant-roles": "warn",
120
- "jsx-a11y/scope": "warn",
121
- "jsx-a11y/tabindex-no-positive": "warn",
122
- "jsx-a11y/label-has-associated-control": "warn",
123
- "jsx-a11y/no-distracting-elements": "error",
124
- "jsx-a11y/iframe-has-title": "warn"
125
- };
126
- const BUILTIN_OXLINT_RULES = {
127
- ...BUILTIN_REACT_OXLINT_RULES,
128
- ...BUILTIN_A11Y_OXLINT_RULES
129
- };
130
- const startsWithAny = (value, prefixes) => prefixes.some((prefix) => value.startsWith(prefix));
131
- const toReactDoctorOxlintRuleKey = (ruleName) => `${REACT_DOCTOR_OXLINT_RULE_KEY_PREFIX}${ruleName}`;
132
- const getReactDoctorRuleSeverity = (ruleName) => REACT_DOCTOR_ERROR_RULE_NAMES.has(ruleName) ? "error" : DEFAULT_OXLINT_RULE_SEVERITY;
133
- const createReactDoctorRuleMap = (shouldIncludeRule) => {
134
- const rules = {};
135
- for (const ruleName of Object.keys(reactDoctorOxlintRules)) if (shouldIncludeRule(ruleName)) rules[toReactDoctorOxlintRuleKey(ruleName)] = getReactDoctorRuleSeverity(ruleName);
136
- return rules;
137
- };
138
- const isNextJsRuleName = (ruleName) => ruleName.startsWith(NEXTJS_RULE_NAME_PREFIX);
139
- const isReactNativeRuleName = (ruleName) => startsWithAny(ruleName, REACT_NATIVE_RULE_NAME_PREFIXES);
140
- const isTanStackAiRuleName = (ruleName) => ruleName.startsWith(TANSTACK_AI_RULE_NAME_PREFIX);
141
- const isTanStackStartRuleName = (ruleName) => ruleName.startsWith(TANSTACK_START_RULE_NAME_PREFIX);
142
- const isTanStackQueryRuleName = (ruleName) => ruleName.startsWith(TANSTACK_QUERY_RULE_NAME_PREFIX);
143
- const isEcosystemRuleName = (ruleName) => startsWithAny(ruleName, ECOSYSTEM_RULE_NAME_PREFIXES);
144
- const isFrameworkRuleName = (ruleName) => isNextJsRuleName(ruleName) || isReactNativeRuleName(ruleName) || isTanStackAiRuleName(ruleName) || isTanStackStartRuleName(ruleName) || isTanStackQueryRuleName(ruleName);
145
- const NEXTJS_OXLINT_RULES = createReactDoctorRuleMap(isNextJsRuleName);
146
- const REACT_NATIVE_OXLINT_RULES = createReactDoctorRuleMap(isReactNativeRuleName);
147
- const TANSTACK_START_OXLINT_RULES = createReactDoctorRuleMap(isTanStackStartRuleName);
148
- const TANSTACK_AI_OXLINT_RULES = createReactDoctorRuleMap(isTanStackAiRuleName);
149
- const TANSTACK_QUERY_OXLINT_RULES = createReactDoctorRuleMap(isTanStackQueryRuleName);
150
- const ECOSYSTEM_OXLINT_RULES = createReactDoctorRuleMap(isEcosystemRuleName);
151
- const GLOBAL_REACT_DOCTOR_OXLINT_RULES = createReactDoctorRuleMap((ruleName) => !isFrameworkRuleName(ruleName) && !isEcosystemRuleName(ruleName));
152
- const REACT_DOCTOR_CUSTOM_OXLINT_RULES = {
153
- ...GLOBAL_REACT_DOCTOR_OXLINT_RULES,
154
- ...NEXTJS_OXLINT_RULES,
155
- ...REACT_NATIVE_OXLINT_RULES,
156
- ...TANSTACK_AI_OXLINT_RULES,
157
- ...TANSTACK_START_OXLINT_RULES,
158
- ...TANSTACK_QUERY_OXLINT_RULES,
159
- ...ECOSYSTEM_OXLINT_RULES
160
- };
161
- const CURATED_OXLINT_RULES = {
162
- ...BUILTIN_REACT_OXLINT_RULES,
163
- ...BUILTIN_A11Y_OXLINT_RULES,
164
- ...REACT_DOCTOR_CUSTOM_OXLINT_RULES
165
- };
166
- const ALL_REACT_DOCTOR_OXLINT_RULE_KEYS = new Set(Object.keys(REACT_DOCTOR_CUSTOM_OXLINT_RULES));
167
- const DISABLED_OXLINT_CATEGORIES = {
168
- correctness: "off",
169
- nursery: "off",
170
- pedantic: "off",
171
- perf: "off",
172
- restriction: "off",
173
- style: "off",
174
- suspicious: "off"
175
- };
176
- const EMPTY_TAGS = /* @__PURE__ */ new Set();
177
- const DEFAULT_IGNORED_TAGS = new Set(["pedantic"]);
178
- const TEST_NOISE_TAGS = new Set(["test-noise"]);
179
- const PEDANTIC_TAGS = new Set(["pedantic"]);
180
- const DESIGN_AND_TEST_NOISE_TAGS = new Set(["design", "test-noise"]);
181
- const TAILWIND_VERSION_PATTERN = /(?:^|[^\d])(\d+)(?:\.(\d+))?/;
182
- const PEER_COMPARATOR_SEPARATOR = /[\s,|]+/;
183
- const PEER_WILDCARD_COMPARATOR = /^[*xX](?:\.[*xX])*$/;
184
- const withReactDoctorRuleKey = (ruleName, metadata) => [toReactDoctorOxlintRuleKey(ruleName), metadata];
185
- const RULE_METADATA = new Map([
186
- withReactDoctorRuleKey("no-react19-deprecated-apis", {
187
- requires: ["react:19"],
188
- tags: TEST_NOISE_TAGS
189
- }),
190
- withReactDoctorRuleKey("no-default-props", {
191
- requires: ["react:19"],
192
- tags: TEST_NOISE_TAGS
193
- }),
194
- withReactDoctorRuleKey("no-react-dom-deprecated-apis", {
195
- requires: ["react:18"],
196
- tags: TEST_NOISE_TAGS
197
- }),
198
- withReactDoctorRuleKey("prefer-use-effect-event", {
199
- requires: ["react:19"],
200
- tags: TEST_NOISE_TAGS
201
- }),
202
- withReactDoctorRuleKey("no-nested-component-definition", { tags: TEST_NOISE_TAGS }),
203
- withReactDoctorRuleKey("no-eval", { tags: TEST_NOISE_TAGS }),
204
- withReactDoctorRuleKey("design-no-bold-heading", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
205
- withReactDoctorRuleKey("tailwind-no-redundant-padding-axes", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
206
- withReactDoctorRuleKey("tailwind-no-redundant-size-axes", {
207
- requires: ["tailwind:3.4"],
208
- tags: DESIGN_AND_TEST_NOISE_TAGS
209
- }),
210
- withReactDoctorRuleKey("tailwind-no-space-on-flex-children", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
211
- withReactDoctorRuleKey("design-no-three-period-ellipsis", { tags: PEDANTIC_TAGS }),
212
- withReactDoctorRuleKey("i18n-no-literal-jsx-text", { tags: PEDANTIC_TAGS }),
213
- withReactDoctorRuleKey("rendering-content-visibility", { tags: PEDANTIC_TAGS }),
214
- withReactDoctorRuleKey("tailwind-no-default-palette", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
215
- withReactDoctorRuleKey("design-no-vague-button-label", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
216
- withReactDoctorRuleKey("no-side-tab-border", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
217
- withReactDoctorRuleKey("no-pure-black-background", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
218
- withReactDoctorRuleKey("no-gradient-text", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
219
- withReactDoctorRuleKey("no-dark-mode-glow", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
220
- withReactDoctorRuleKey("no-justified-text", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
221
- withReactDoctorRuleKey("no-tiny-text", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
222
- withReactDoctorRuleKey("no-wide-letter-spacing", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
223
- withReactDoctorRuleKey("no-gray-on-colored-background", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
224
- withReactDoctorRuleKey("no-layout-transition-inline", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
225
- withReactDoctorRuleKey("no-outline-none", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
226
- withReactDoctorRuleKey("no-long-transition-duration", { tags: DESIGN_AND_TEST_NOISE_TAGS }),
227
- withReactDoctorRuleKey("no-render-in-render", { tags: TEST_NOISE_TAGS }),
228
- withReactDoctorRuleKey("rerender-split-combined-hooks", { tags: PEDANTIC_TAGS })
229
- ]);
230
- const EMPTY_TAG_SET = /* @__PURE__ */ new Set();
231
- const getReactDoctorRuleTags = (ruleKey) => RULE_METADATA.get(ruleKey)?.tags ?? EMPTY_TAG_SET;
232
- const REACT_DOCTOR_FRAMEWORK_RULE_GROUPS = [
233
- {
234
- rules: NEXTJS_OXLINT_RULES,
235
- requires: ["nextjs"]
236
- },
237
- {
238
- rules: REACT_NATIVE_OXLINT_RULES,
239
- requires: ["react-native"]
240
- },
241
- {
242
- rules: TANSTACK_START_OXLINT_RULES,
243
- requires: ["tanstack-start"]
244
- },
245
- {
246
- rules: TANSTACK_AI_OXLINT_RULES,
247
- requires: ["tanstack-ai"]
248
- },
249
- {
250
- rules: TANSTACK_QUERY_OXLINT_RULES,
251
- requires: ["tanstack-query"]
252
- }
253
- ];
254
- const readPluginRuleNames = (pluginSpecifier, pluginRequire) => {
255
- try {
256
- const pluginModule = pluginRequire(pluginSpecifier);
257
- const rules = pluginModule.rules ?? pluginModule.default?.rules;
258
- return rules ? new Set(Object.keys(rules)) : /* @__PURE__ */ new Set();
259
- } catch {
260
- return /* @__PURE__ */ new Set();
261
- }
262
- };
263
- const resolveOptionalJsPlugin = (namespace, pluginSpecifier, projectRootDirectory) => {
264
- try {
265
- const pluginRequire = projectRootDirectory ? createRequire(path.join(projectRootDirectory, "package.json")) : esmRequire;
266
- const resolvedSpecifier = pluginRequire.resolve(pluginSpecifier);
267
- return {
268
- entry: {
269
- name: namespace,
270
- specifier: resolvedSpecifier
271
- },
272
- availableRuleNames: readPluginRuleNames(resolvedSpecifier, pluginRequire)
273
- };
274
- } catch {
275
- return null;
276
- }
277
- };
278
- const filterRulesToAvailable = (rules, pluginNamespace, availableRuleNames) => {
279
- if (availableRuleNames.size === 0) return rules;
280
- const ruleKeyPrefix = `${pluginNamespace}/`;
281
- const filteredRules = {};
282
- for (const [ruleKey, severity] of Object.entries(rules)) {
283
- if (!ruleKey.startsWith(ruleKeyPrefix)) {
284
- filteredRules[ruleKey] = severity;
285
- continue;
286
- }
287
- const ruleName = ruleKey.slice(ruleKeyPrefix.length);
288
- if (availableRuleNames.has(ruleName)) filteredRules[ruleKey] = severity;
289
- }
290
- return filteredRules;
291
- };
292
- const buildOptionalReactCompilerConfig = (customRulesOnly, hasReactCompiler, projectRootDirectory) => {
293
- if (customRulesOnly || !hasReactCompiler) return {
294
- jsPlugin: null,
295
- rules: {}
296
- };
297
- const plugin = resolveOptionalJsPlugin(REACT_HOOKS_JS_NAMESPACE, REACT_HOOKS_PLUGIN_SPECIFIER, projectRootDirectory);
298
- if (!plugin) return {
299
- jsPlugin: null,
300
- rules: {}
301
- };
302
- return {
303
- jsPlugin: plugin.entry,
304
- rules: filterRulesToAvailable(REACT_COMPILER_OXLINT_RULES, REACT_HOOKS_JS_NAMESPACE, plugin.availableRuleNames)
305
- };
306
- };
307
- const buildOptionalYouMightNotNeedEffectConfig = (customRulesOnly, projectRootDirectory) => {
308
- if (customRulesOnly) return {
309
- jsPlugin: null,
310
- rules: {}
311
- };
312
- const plugin = resolveOptionalJsPlugin(YOU_MIGHT_NOT_NEED_EFFECT_NAMESPACE, YOU_MIGHT_NOT_NEED_EFFECT_PLUGIN_SPECIFIER, projectRootDirectory);
313
- if (!plugin) return {
314
- jsPlugin: null,
315
- rules: {}
316
- };
317
- return {
318
- jsPlugin: plugin.entry,
319
- rules: filterRulesToAvailable(YOU_MIGHT_NOT_NEED_EFFECT_OXLINT_RULES, YOU_MIGHT_NOT_NEED_EFFECT_NAMESPACE, plugin.availableRuleNames)
320
- };
321
- };
322
- const parseMajorMinor = (version) => {
323
- if (!version) return null;
324
- const match = version.match(TAILWIND_VERSION_PATTERN);
325
- if (!match) return null;
326
- return {
327
- major: Number.parseInt(match[1], 10),
328
- minor: match[2] ? Number.parseInt(match[2], 10) : 0
329
- };
330
- };
331
- const isTailwindAtLeast = (version, minimum) => {
332
- if (!version) return true;
333
- if (version.major > minimum.major) return true;
334
- if (version.major < minimum.major) return false;
335
- return version.minor >= minimum.minor;
336
- };
337
- const comparatorMajor = (comparator) => {
338
- if (PEER_WILDCARD_COMPARATOR.test(comparator)) return null;
339
- const firstIntegerMatch = comparator.match(/\d+/);
340
- if (!firstIntegerMatch) return null;
341
- const major = Number.parseInt(firstIntegerMatch[0], 10);
342
- return major >= 1 ? major : null;
343
- };
344
- const reactPeerRangeMinMajor = (range) => {
345
- if (typeof range !== "string") return null;
346
- let lowestMajor = null;
347
- for (const comparator of range.trim().split(PEER_COMPARATOR_SEPARATOR).filter(Boolean)) {
348
- const major = comparatorMajor(comparator);
349
- if (major !== null && (lowestMajor === null || major < lowestMajor)) lowestMajor = major;
350
- }
351
- return lowestMajor;
352
- };
353
- const effectiveReactMajor = (project) => {
354
- const installedMajor = project.reactMajorVersion ?? null;
355
- const peerMajor = reactPeerRangeMinMajor(project.reactPeerDependencyRange);
356
- if (installedMajor !== null && peerMajor !== null) return Math.min(installedMajor, peerMajor);
357
- return installedMajor ?? peerMajor ?? UNCONSTRAINED_REACT_MAJOR;
358
- };
359
- const buildReactDoctorOxlintCapabilities = (project) => {
360
- const capabilities = /* @__PURE__ */ new Set();
361
- const framework = project.framework ?? "unknown";
362
- capabilities.add(framework);
363
- if (framework === "expo" || framework === "react-native") capabilities.add("react-native");
364
- const reactMajor = effectiveReactMajor(project);
365
- for (let major = 17; major <= reactMajor; major++) capabilities.add(`react:${major}`);
366
- if (project.tailwindVersion !== null) {
367
- capabilities.add("tailwind");
368
- if (isTailwindAtLeast(parseMajorMinor(project.tailwindVersion), {
369
- major: 3,
370
- minor: 4
371
- })) capabilities.add("tailwind:3.4");
372
- }
373
- if (project.hasReactCompiler) capabilities.add("react-compiler");
374
- if (project.hasTanStackAI) capabilities.add("tanstack-ai");
375
- if (project.hasTanStackQuery) capabilities.add("tanstack-query");
376
- if (project.hasTypeScript) capabilities.add("typescript");
377
- return capabilities;
378
- };
379
- const shouldEnableReactDoctorOxlintRule = (requires, tags, capabilities, ignoredTags) => {
380
- if (requires) {
381
- for (const capability of requires) if (!capabilities.has(capability)) return false;
382
- }
383
- for (const tag of tags) if (ignoredTags.has(tag)) return false;
384
- return true;
385
- };
386
- const addEnabledRules = (target, rules, capabilities, ignoredTags, defaultRequires) => {
387
- for (const [ruleKey, severity] of Object.entries(rules)) {
388
- const metadata = RULE_METADATA.get(ruleKey);
389
- if (shouldEnableReactDoctorOxlintRule(metadata?.requires ?? defaultRequires, metadata?.tags ?? EMPTY_TAGS, capabilities, ignoredTags)) target[ruleKey] = severity;
390
- }
391
- };
392
- const createReactDoctorOxlintConfig = ({ pluginPath, projectRootDirectory, project, framework = "unknown", customRulesOnly = false, hasReactCompiler = false, hasTanStackAI = false, hasTanStackQuery = false, includeEcosystemRules = true, extendsPaths = [], ignoredTags = DEFAULT_IGNORED_TAGS }) => {
393
- const projectInfo = project ?? {
394
- framework,
395
- hasReactCompiler,
396
- hasTanStackAI,
397
- hasTanStackQuery
398
- };
399
- const capabilities = buildReactDoctorOxlintCapabilities(projectInfo);
400
- const reactCompilerConfig = buildOptionalReactCompilerConfig(customRulesOnly, Boolean(projectInfo.hasReactCompiler), projectRootDirectory);
401
- const youMightNotNeedEffectConfig = buildOptionalYouMightNotNeedEffectConfig(customRulesOnly, projectRootDirectory);
402
- const jsPlugins = [];
403
- if (reactCompilerConfig.jsPlugin) jsPlugins.push(reactCompilerConfig.jsPlugin);
404
- if (youMightNotNeedEffectConfig.jsPlugin) jsPlugins.push(youMightNotNeedEffectConfig.jsPlugin);
405
- jsPlugins.push(pluginPath);
406
- const enabledReactDoctorRules = {};
407
- addEnabledRules(enabledReactDoctorRules, GLOBAL_REACT_DOCTOR_OXLINT_RULES, capabilities, ignoredTags);
408
- for (const ruleGroup of REACT_DOCTOR_FRAMEWORK_RULE_GROUPS) addEnabledRules(enabledReactDoctorRules, ruleGroup.rules, capabilities, ignoredTags, ruleGroup.requires);
409
- if (includeEcosystemRules) addEnabledRules(enabledReactDoctorRules, ECOSYSTEM_OXLINT_RULES, capabilities, ignoredTags);
410
- return {
411
- ...extendsPaths.length > 0 ? { extends: extendsPaths } : {},
412
- categories: { ...DISABLED_OXLINT_CATEGORIES },
413
- plugins: customRulesOnly ? [] : ["react", "jsx-a11y"],
414
- jsPlugins,
415
- rules: {
416
- ...customRulesOnly ? {} : BUILTIN_OXLINT_RULES,
417
- ...reactCompilerConfig.rules,
418
- ...youMightNotNeedEffectConfig.rules,
419
- ...enabledReactDoctorRules
420
- }
421
- };
422
- };
423
- //#endregion
424
- //#region src/core/rules/lint/metadata.ts
425
- const REACT_DOCTOR_OXLINT_PLUGIN_NAMESPACE = "react-doctor";
426
- const REACT_DOCTOR_OXLINT_RULE_ID_PREFIX = "oxlint/react-doctor/";
427
- const RULE_TITLE_WORD_UPPERCASE = /\b(css|html|url|svg|jsx|api|ua|rn)\b/gi;
428
- const toRuleDisplayName = (ruleName) => {
429
- const readable = ruleName.replace(/^(no|prefer|require|use)-/, "").replace(/^(nextjs|tanstack-start|tanstack-query|rn|js|server|client|query|effect|design|rendering|rerender|react-compiler|advanced)-/, "").replaceAll("-", " ");
430
- return (readable.charAt(0).toUpperCase() + readable.slice(1)).replace(RULE_TITLE_WORD_UPPERCASE, (match) => match.toUpperCase());
431
- };
432
- const REACT_DOCTOR_RULE_CATEGORY_MAP = {
433
- "no-derived-state-effect": "State & Effects",
434
- "no-fetch-in-effect": "State & Effects",
435
- "no-mirror-prop-effect": "State & Effects",
436
- "no-mutable-in-deps": "State & Effects",
437
- "no-cascading-set-state": "State & Effects",
438
- "no-effect-chain": "State & Effects",
439
- "no-effect-event-handler": "State & Effects",
440
- "no-effect-event-in-deps": "State & Effects",
441
- "no-event-trigger-state": "State & Effects",
442
- "no-prop-callback-in-effect": "State & Effects",
443
- "no-derived-useState": "State & Effects",
444
- "no-direct-state-mutation": "State & Effects",
445
- "no-set-state-in-render": "State & Effects",
446
- "prefer-use-effect-event": "State & Effects",
447
- "prefer-useReducer": "State & Effects",
448
- "prefer-use-sync-external-store": "State & Effects",
449
- "rerender-lazy-state-init": "Performance",
450
- "rerender-functional-setstate": "Performance",
451
- "rerender-dependencies": "State & Effects",
452
- "rerender-state-only-in-handlers": "Performance",
453
- "rerender-defer-reads-hook": "Performance",
454
- "advanced-event-handler-refs": "Performance",
455
- "effect-needs-cleanup": "State & Effects",
456
- "no-generic-handler-names": "Architecture",
457
- "no-giant-component": "Architecture",
458
- "no-many-boolean-props": "Architecture",
459
- "no-react19-deprecated-apis": "Architecture",
460
- "no-render-prop-children": "Architecture",
461
- "no-render-in-render": "Architecture",
462
- "no-nested-component-definition": "Correctness",
463
- "react-compiler-destructure-method": "Architecture",
464
- "no-legacy-class-lifecycles": "Correctness",
465
- "no-legacy-context-api": "Correctness",
466
- "no-default-props": "Architecture",
467
- "no-react-dom-deprecated-apis": "Architecture",
468
- "no-usememo-simple-expression": "Performance",
469
- "no-layout-property-animation": "Performance",
470
- "rerender-memo-with-default-value": "Performance",
471
- "rerender-memo-before-early-return": "Performance",
472
- "rerender-transitions-scroll": "Performance",
473
- "rerender-derived-state-from-hook": "Performance",
474
- "async-defer-await": "Performance",
475
- "async-await-in-loop": "Performance",
476
- "rendering-animate-svg-wrapper": "Performance",
477
- "rendering-hoist-jsx": "Performance",
478
- "rendering-hydration-mismatch-time": "Correctness",
479
- "rendering-usetransition-loading": "Performance",
480
- "rendering-hydration-no-flicker": "Performance",
481
- "rendering-script-defer-async": "Performance",
482
- "no-inline-prop-on-memo-component": "Performance",
483
- "no-transition-all": "Performance",
484
- "no-global-css-variable-animation": "Performance",
485
- "no-large-animated-blur": "Performance",
486
- "no-scale-from-zero": "Performance",
487
- "no-permanent-will-change": "Performance",
488
- "no-secrets-in-client-code": "Security",
489
- "no-barrel-import": "Bundle Size",
490
- "no-dynamic-import-path": "Bundle Size",
491
- "no-full-lodash-import": "Bundle Size",
492
- "no-moment": "Bundle Size",
493
- "prefer-dynamic-import": "Bundle Size",
494
- "use-lazy-motion": "Bundle Size",
495
- "no-undeferred-third-party": "Bundle Size",
496
- "no-array-index-as-key": "Correctness",
497
- "no-polymorphic-children": "Architecture",
498
- "rendering-conditional-render": "Correctness",
499
- "rendering-svg-precision": "Performance",
500
- "no-prevent-default": "Correctness",
501
- "no-uncontrolled-input": "Correctness",
502
- "no-document-start-view-transition": "Correctness",
503
- "no-flush-sync": "Performance",
504
- "no-justified-text": "Accessibility",
505
- "no-tiny-text": "Accessibility",
506
- "no-gray-on-colored-background": "Accessibility",
507
- "no-disabled-zoom": "Accessibility",
508
- "no-outline-none": "Accessibility",
509
- "design-no-vague-button-label": "Accessibility",
510
- "no-inline-bounce-easing": "Performance",
511
- "no-z-index-9999": "Architecture",
512
- "no-inline-exhaustive-style": "Architecture",
513
- "no-side-tab-border": "Architecture",
514
- "no-pure-black-background": "Architecture",
515
- "no-gradient-text": "Architecture",
516
- "no-dark-mode-glow": "Architecture",
517
- "no-wide-letter-spacing": "Architecture",
518
- "no-layout-transition-inline": "Performance",
519
- "no-long-transition-duration": "Performance",
520
- "design-no-bold-heading": "Architecture",
521
- "design-no-redundant-padding-axes": "Architecture",
522
- "design-no-redundant-size-axes": "Architecture",
523
- "design-no-space-on-flex-children": "Architecture",
524
- "design-no-three-period-ellipsis": "Architecture",
525
- "design-no-default-tailwind-palette": "Architecture",
526
- "js-flatmap-filter": "Performance",
527
- "js-combine-iterations": "Performance",
528
- "js-tosorted-immutable": "Performance",
529
- "js-hoist-regexp": "Performance",
530
- "js-hoist-intl": "Performance",
531
- "js-cache-property-access": "Performance",
532
- "js-length-check-first": "Performance",
533
- "js-min-max-loop": "Performance",
534
- "js-set-map-lookups": "Performance",
535
- "js-batch-dom-css": "Performance",
536
- "js-index-maps": "Performance",
537
- "js-cache-storage": "Performance",
538
- "js-early-exit": "Performance",
539
- "no-eval": "Security",
540
- "async-parallel": "Performance",
541
- "client-passive-event-listeners": "Performance",
542
- "client-localstorage-no-version": "Correctness",
543
- "query-stable-query-client": "TanStack Query",
544
- "query-no-rest-destructuring": "TanStack Query",
545
- "query-no-void-query-fn": "TanStack Query",
546
- "query-no-query-in-effect": "TanStack Query",
547
- "query-mutation-missing-invalidation": "TanStack Query",
548
- "query-no-usequery-for-mutation": "TanStack Query",
549
- "server-auth-actions": "Server",
550
- "server-after-nonblocking": "Server",
551
- "server-no-mutable-module-state": "Server",
552
- "server-cache-with-object-literal": "Server",
553
- "server-hoist-static-io": "Server",
554
- "server-dedup-props": "Server",
555
- "server-sequential-independent-await": "Server",
556
- "server-fetch-without-revalidate": "Server",
557
- "nextjs-no-side-effect-in-get-handler": "Security",
558
- "tanstack-start-no-secrets-in-loader": "Security",
559
- "tanstack-start-get-mutation": "Security",
560
- "tanstack-start-loader-parallel-fetch": "Performance"
561
- };
562
- const resolveReactDoctorRuleCategory = (ruleName) => {
563
- const mapped = REACT_DOCTOR_RULE_CATEGORY_MAP[ruleName];
564
- if (mapped) return mapped;
565
- if (ruleName.startsWith("nextjs-")) return "Next.js";
566
- if (ruleName.startsWith("rn-")) return "React Native";
567
- if (ruleName.startsWith("tanstack-start-")) return "TanStack Start";
568
- if (ruleName.startsWith("tanstack-query-") || ruleName.startsWith("query-")) return "TanStack Query";
569
- if (ruleName.startsWith("server-")) return "Server";
570
- if (ruleName.startsWith("js-")) return "Performance";
571
- if (ruleName.startsWith("design-")) return "Architecture";
572
- if (ruleName.startsWith("rendering-") || ruleName.startsWith("rerender-")) return "Performance";
573
- return "Other";
574
- };
575
- const toReactDoctorSeverity = (severity) => {
576
- if (severity === "error") return "error";
577
- if (severity === "off") return "info";
578
- return "warning";
579
- };
580
- const reactDoctorOxlintRuleMetadata = Object.entries(reactDoctorOxlintRules).sort(([ruleName], [nextRuleName]) => ruleName.localeCompare(nextRuleName)).map(([ruleName, rule]) => {
581
- const oxlintRuleKey = `${REACT_DOCTOR_OXLINT_PLUGIN_NAMESPACE}/${ruleName}`;
582
- const severity = REACT_DOCTOR_CUSTOM_OXLINT_RULES[oxlintRuleKey] ?? "warn";
583
- return {
584
- id: `${REACT_DOCTOR_OXLINT_RULE_ID_PREFIX}${ruleName}`,
585
- name: toRuleDisplayName(ruleName),
586
- description: `Runs the ${oxlintRuleKey} custom oxlint rule.`,
587
- recommendation: rule.recommendation,
588
- examples: rule.examples,
589
- category: resolveReactDoctorRuleCategory(ruleName),
590
- severity: toReactDoctorSeverity(severity),
591
- defaultEnabled: false,
592
- tags: [
593
- "oxlint",
594
- "custom",
595
- REACT_DOCTOR_OXLINT_PLUGIN_NAMESPACE
596
- ],
597
- oxlintRuleName: ruleName,
598
- oxlintRuleKey
599
- };
600
- });
601
- //#endregion
602
- export { createReactDoctorOxlintConfig as _, BUILTIN_A11Y_OXLINT_RULES as a, shouldEnableReactDoctorOxlintRule as b, CURATED_OXLINT_RULES as c, REACT_COMPILER_OXLINT_RULES as d, REACT_DOCTOR_CUSTOM_OXLINT_RULES as f, buildReactDoctorOxlintCapabilities as g, TANSTACK_START_OXLINT_RULES as h, ALL_REACT_DOCTOR_OXLINT_RULE_KEYS as i, GLOBAL_REACT_DOCTOR_OXLINT_RULES as l, TANSTACK_QUERY_OXLINT_RULES as m, REACT_DOCTOR_OXLINT_RULE_ID_PREFIX as n, BUILTIN_OXLINT_RULES as o, REACT_NATIVE_OXLINT_RULES as p, reactDoctorOxlintRuleMetadata as r, BUILTIN_REACT_OXLINT_RULES as s, REACT_DOCTOR_OXLINT_PLUGIN_NAMESPACE as t, NEXTJS_OXLINT_RULES as u, getReactDoctorRuleTags as v, reactPeerRangeMinMajor as y };
603
-
604
- //# sourceMappingURL=metadata-se470mRG.js.map
@@ -1,2 +0,0 @@
1
- import { t as reactDoctorOxlintPlugin } from "./rules-ebKa330H.js";
2
- export { reactDoctorOxlintPlugin as default, reactDoctorOxlintPlugin };
@@ -1,7 +0,0 @@
1
- import { l as reactDoctorOxlintPlugin } from "./rules-BfZ4Ujfv.js";
2
- //#region src/oxlint-plugin.ts
3
- var oxlint_plugin_default = reactDoctorOxlintPlugin;
4
- //#endregion
5
- export { oxlint_plugin_default as default, reactDoctorOxlintPlugin };
6
-
7
- //# sourceMappingURL=oxlint-plugin.js.map