ultracite 7.8.4 → 7.9.1
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 -3
- package/config/biome/core/biome.jsonc +65 -4
- package/config/biome/next/biome.jsonc +3 -1
- package/config/biome/react/biome.jsonc +1 -0
- package/config/biome/vue/biome.jsonc +22 -2
- package/config/eslint/astro/rules/astro.mjs +4 -1
- package/config/eslint/core/eslint.config.mjs +22 -2
- package/config/eslint/core/rules/eslint-typescript.mjs +0 -2
- package/config/eslint/core/rules/eslint.mjs +15 -1
- package/config/eslint/core/rules/github.mjs +7 -0
- package/config/eslint/core/rules/import.mjs +10 -1
- package/config/eslint/core/rules/jsdoc.mjs +31 -0
- package/config/eslint/core/rules/n.mjs +5 -0
- package/config/eslint/core/rules/promise.mjs +6 -1
- package/config/eslint/core/rules/sonarjs.mjs +24 -0
- package/config/eslint/core/rules/typescript.mjs +12 -1
- package/config/eslint/core/rules/unicorn.mjs +21 -5
- package/config/eslint/next/eslint.config.mjs +4 -0
- package/config/eslint/next/rules/react-doctor.mjs +27 -0
- package/config/eslint/react/eslint.config.mjs +20 -1
- package/config/eslint/react/rules/react-doctor.mjs +153 -0
- package/config/eslint/react/rules/react.mjs +7 -6
- package/config/eslint/svelte/rules/svelte.mjs +9 -2
- package/config/eslint/tanstack/eslint.config.mjs +4 -0
- package/config/eslint/tanstack/rules/react-doctor.mjs +25 -0
- package/config/eslint/vue/eslint.config.mjs +9 -0
- package/config/oxlint/core/index.mjs +251 -3
- package/config/oxlint/next/index.mjs +53 -1
- package/config/oxlint/react/index.mjs +245 -2
- package/config/oxlint/tanstack/index.mjs +26 -1
- package/config/oxlint/vue/index.mjs +3 -0
- package/dist/index.js +64 -100
- package/package.json +25 -21
|
@@ -10,12 +10,15 @@ const baseRules = Object.fromEntries(
|
|
|
10
10
|
availableKeys.map((key) => [`unicorn/${key}`, "error"])
|
|
11
11
|
);
|
|
12
12
|
|
|
13
|
+
// Overrides mirror the oxlint core config (config/oxlint/core/index.mjs),
|
|
14
|
+
// which is the benchmark for rule decisions across linters.
|
|
13
15
|
const overrideRules = {
|
|
14
|
-
|
|
15
|
-
"unicorn/
|
|
16
|
-
"unicorn/
|
|
17
|
-
"unicorn/
|
|
18
|
-
|
|
16
|
+
// Renamed from unicorn/prefer-dom-node-dataset in v65.
|
|
17
|
+
"unicorn/dom-node-dataset": "off",
|
|
18
|
+
"unicorn/explicit-length-check": "off",
|
|
19
|
+
"unicorn/max-nested-calls": "off",
|
|
20
|
+
// Renamed from unicorn/prevent-abbreviations in v68; same allowList option.
|
|
21
|
+
"unicorn/name-replacements": [
|
|
19
22
|
"error",
|
|
20
23
|
{
|
|
21
24
|
allowList: {
|
|
@@ -27,6 +30,19 @@ const overrideRules = {
|
|
|
27
30
|
},
|
|
28
31
|
},
|
|
29
32
|
],
|
|
33
|
+
"unicorn/no-array-callback-reference": "off",
|
|
34
|
+
// Strips the leading `*` from JSDoc lines, fighting the conventional
|
|
35
|
+
// documentation-comment style that the formatter preserves.
|
|
36
|
+
"unicorn/no-asterisk-prefix-in-documentation-comments": "off",
|
|
37
|
+
"unicorn/no-keyword-prefix": "off",
|
|
38
|
+
"unicorn/no-null": "off",
|
|
39
|
+
"unicorn/no-process-exit": "off",
|
|
40
|
+
"unicorn/prefer-global-this": "off",
|
|
41
|
+
"unicorn/prefer-string-raw": "off",
|
|
42
|
+
// Enforces Temporal over Date, but Temporal still lacks broad runtime
|
|
43
|
+
// support; unicorn ships it off by default. Premature to enforce.
|
|
44
|
+
"unicorn/prefer-temporal": "off",
|
|
45
|
+
"unicorn/prefer-top-level-await": "off",
|
|
30
46
|
"unicorn/text-encoding-identifier-case": ["error", { withDash: true }],
|
|
31
47
|
};
|
|
32
48
|
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
/* eslint-disable n/no-unpublished-import, n/no-extraneous-import, import/no-extraneous-dependencies, id-length */
|
|
2
2
|
|
|
3
3
|
import next from "@next/eslint-plugin-next";
|
|
4
|
+
import reactDoctor from "eslint-plugin-react-doctor";
|
|
4
5
|
|
|
5
6
|
import nextRules from "./rules/next.mjs";
|
|
7
|
+
import reactDoctorRules from "./rules/react-doctor.mjs";
|
|
6
8
|
|
|
7
9
|
const config = [
|
|
8
10
|
{
|
|
9
11
|
files: ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"],
|
|
10
12
|
plugins: {
|
|
11
13
|
"@next/next": next,
|
|
14
|
+
"react-doctor": reactDoctor,
|
|
12
15
|
},
|
|
13
16
|
rules: {
|
|
14
17
|
...nextRules,
|
|
18
|
+
...reactDoctorRules,
|
|
15
19
|
},
|
|
16
20
|
},
|
|
17
21
|
{
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const config = {
|
|
2
|
+
"react-doctor/nextjs-async-client-component": "error",
|
|
3
|
+
"react-doctor/nextjs-error-boundary-missing-use-client": "error",
|
|
4
|
+
"react-doctor/nextjs-global-error-missing-html-body": "error",
|
|
5
|
+
"react-doctor/nextjs-image-missing-sizes": "error",
|
|
6
|
+
"react-doctor/nextjs-inline-script-missing-id": "error",
|
|
7
|
+
"react-doctor/nextjs-missing-metadata": "error",
|
|
8
|
+
"react-doctor/nextjs-no-a-element": "error",
|
|
9
|
+
"react-doctor/nextjs-no-client-fetch-for-server-data": "error",
|
|
10
|
+
"react-doctor/nextjs-no-client-side-redirect": "error",
|
|
11
|
+
"react-doctor/nextjs-no-css-link": "error",
|
|
12
|
+
"react-doctor/nextjs-no-default-export-in-route-handler": "error",
|
|
13
|
+
"react-doctor/nextjs-no-edge-og-runtime": "error",
|
|
14
|
+
"react-doctor/nextjs-no-font-link": "error",
|
|
15
|
+
"react-doctor/nextjs-no-google-analytics-script": "error",
|
|
16
|
+
"react-doctor/nextjs-no-head-import": "error",
|
|
17
|
+
"react-doctor/nextjs-no-img-element": "error",
|
|
18
|
+
"react-doctor/nextjs-no-native-script": "error",
|
|
19
|
+
"react-doctor/nextjs-no-polyfill-script": "error",
|
|
20
|
+
"react-doctor/nextjs-no-redirect-in-try-catch": "error",
|
|
21
|
+
"react-doctor/nextjs-no-script-in-head": "error",
|
|
22
|
+
"react-doctor/nextjs-no-side-effect-in-get-handler": "error",
|
|
23
|
+
"react-doctor/nextjs-no-use-search-params-without-suspense": "error",
|
|
24
|
+
"react-doctor/nextjs-no-vercel-og-import": "error",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default config;
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
/* eslint-disable n/no-unpublished-import, n/no-extraneous-import, import/no-extraneous-dependencies, id-length */
|
|
2
2
|
|
|
3
|
+
import eslintPrettier from "eslint-config-prettier";
|
|
3
4
|
import jsxA11y from "eslint-plugin-jsx-a11y";
|
|
4
5
|
import react from "eslint-plugin-react";
|
|
6
|
+
import reactDoctor from "eslint-plugin-react-doctor";
|
|
5
7
|
import reactHooks from "eslint-plugin-react-hooks";
|
|
6
8
|
|
|
7
9
|
import jsxA11yRules from "./rules/jsx-a11y.mjs";
|
|
10
|
+
import reactDoctorRules from "./rules/react-doctor.mjs";
|
|
8
11
|
import reactHooksRules from "./rules/react-hooks.mjs";
|
|
9
12
|
import reactRules from "./rules/react.mjs";
|
|
10
13
|
|
|
14
|
+
// Only the react/ entries — this block merges after the core one, so the
|
|
15
|
+
// all-on react rules would otherwise re-enable the JSX formatting rules
|
|
16
|
+
// that eslint-config-prettier turns off (several crash under ESLint 10).
|
|
17
|
+
// Filtered to react/ so the spread can't clobber core-block decisions.
|
|
18
|
+
const reactPrettierOverrides = Object.fromEntries(
|
|
19
|
+
Object.entries(eslintPrettier.rules).filter(([key]) =>
|
|
20
|
+
key.startsWith("react/")
|
|
21
|
+
)
|
|
22
|
+
);
|
|
23
|
+
|
|
11
24
|
const config = [
|
|
12
25
|
{
|
|
13
26
|
files: ["**/*.jsx", "**/*.tsx"],
|
|
@@ -21,16 +34,22 @@ const config = [
|
|
|
21
34
|
plugins: {
|
|
22
35
|
"jsx-a11y": jsxA11y,
|
|
23
36
|
react,
|
|
37
|
+
"react-doctor": reactDoctor,
|
|
24
38
|
"react-hooks": reactHooks,
|
|
25
39
|
},
|
|
26
40
|
rules: {
|
|
27
41
|
...reactRules,
|
|
28
42
|
...reactHooksRules,
|
|
29
43
|
...jsxA11yRules,
|
|
44
|
+
...reactDoctorRules,
|
|
45
|
+
...reactPrettierOverrides,
|
|
30
46
|
},
|
|
31
47
|
settings: {
|
|
32
48
|
react: {
|
|
33
|
-
|
|
49
|
+
// "detect" calls the removed context.getFilename() under ESLint 10
|
|
50
|
+
// and crashes every version-aware rule. The preset targets React
|
|
51
|
+
// 19+ (see the react-doctor rules), so pin instead of detecting.
|
|
52
|
+
version: "19.0.0",
|
|
34
53
|
},
|
|
35
54
|
},
|
|
36
55
|
},
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const config = {
|
|
2
|
+
"react-doctor/activity-wraps-effect-heavy-subtree": "error",
|
|
3
|
+
"react-doctor/advanced-event-handler-refs": "error",
|
|
4
|
+
"react-doctor/async-await-in-loop": "error",
|
|
5
|
+
"react-doctor/async-defer-await": "error",
|
|
6
|
+
"react-doctor/async-parallel": "error",
|
|
7
|
+
"react-doctor/auth-token-in-web-storage": "error",
|
|
8
|
+
"react-doctor/client-localstorage-no-version": "error",
|
|
9
|
+
"react-doctor/client-passive-event-listeners": "error",
|
|
10
|
+
"react-doctor/dialog-has-accessible-name": "error",
|
|
11
|
+
"react-doctor/effect-needs-cleanup": "error",
|
|
12
|
+
"react-doctor/hooks-no-nan-in-deps": "error",
|
|
13
|
+
"react-doctor/html-no-invalid-paragraph-child": "error",
|
|
14
|
+
"react-doctor/html-no-invalid-table-nesting": "error",
|
|
15
|
+
"react-doctor/html-no-nested-interactive": "error",
|
|
16
|
+
"react-doctor/jotai-derived-atom-returns-fresh-object": "error",
|
|
17
|
+
"react-doctor/jotai-select-atom-in-render-body": "error",
|
|
18
|
+
"react-doctor/jotai-tq-use-raw-query-atom": "error",
|
|
19
|
+
"react-doctor/js-async-reduce-without-awaited-acc": "error",
|
|
20
|
+
"react-doctor/js-batch-dom-css": "error",
|
|
21
|
+
"react-doctor/js-cache-property-access": "error",
|
|
22
|
+
"react-doctor/js-cache-storage": "error",
|
|
23
|
+
"react-doctor/js-combine-iterations": "error",
|
|
24
|
+
"react-doctor/js-early-exit": "error",
|
|
25
|
+
"react-doctor/js-flatmap-filter": "error",
|
|
26
|
+
"react-doctor/js-hoist-intl": "error",
|
|
27
|
+
"react-doctor/js-hoist-regexp": "error",
|
|
28
|
+
"react-doctor/js-index-maps": "error",
|
|
29
|
+
"react-doctor/js-length-check-first": "error",
|
|
30
|
+
"react-doctor/js-min-max-loop": "error",
|
|
31
|
+
"react-doctor/js-set-map-lookups": "error",
|
|
32
|
+
"react-doctor/js-tosorted-immutable": "error",
|
|
33
|
+
"react-doctor/no-adjust-state-on-prop-change": "error",
|
|
34
|
+
"react-doctor/no-array-index-as-key": "error",
|
|
35
|
+
"react-doctor/no-async-effect-callback": "error",
|
|
36
|
+
"react-doctor/no-barrel-import": "error",
|
|
37
|
+
"react-doctor/no-call-component-as-function": "error",
|
|
38
|
+
"react-doctor/no-cascading-set-state": "error",
|
|
39
|
+
"react-doctor/no-chain-state-updates": "error",
|
|
40
|
+
"react-doctor/no-create-context-in-render": "error",
|
|
41
|
+
"react-doctor/no-create-ref-in-function-component": "error",
|
|
42
|
+
"react-doctor/no-create-store-in-render": "error",
|
|
43
|
+
"react-doctor/no-derived-state": "error",
|
|
44
|
+
"react-doctor/no-derived-state-effect": "error",
|
|
45
|
+
"react-doctor/no-derived-useState": "error",
|
|
46
|
+
"react-doctor/no-direct-state-mutation": "error",
|
|
47
|
+
"react-doctor/no-disabled-zoom": "error",
|
|
48
|
+
"react-doctor/no-document-start-view-transition": "error",
|
|
49
|
+
"react-doctor/no-document-write": "error",
|
|
50
|
+
"react-doctor/no-dynamic-import-path": "error",
|
|
51
|
+
"react-doctor/no-effect-chain": "error",
|
|
52
|
+
"react-doctor/no-effect-event-handler": "error",
|
|
53
|
+
"react-doctor/no-effect-event-in-deps": "error",
|
|
54
|
+
"react-doctor/no-effect-with-fresh-deps": "error",
|
|
55
|
+
"react-doctor/no-eval": "error",
|
|
56
|
+
"react-doctor/no-event-handler": "error",
|
|
57
|
+
"react-doctor/no-event-trigger-state": "error",
|
|
58
|
+
"react-doctor/no-fetch-in-effect": "error",
|
|
59
|
+
"react-doctor/no-flush-sync": "error",
|
|
60
|
+
"react-doctor/no-full-lodash-import": "error",
|
|
61
|
+
"react-doctor/no-giant-component": "error",
|
|
62
|
+
"react-doctor/no-global-css-variable-animation": "error",
|
|
63
|
+
"react-doctor/no-gray-on-colored-background": "error",
|
|
64
|
+
"react-doctor/no-img-lazy-with-high-fetchpriority": "error",
|
|
65
|
+
"react-doctor/no-initialize-state": "error",
|
|
66
|
+
"react-doctor/no-inline-bounce-easing": "error",
|
|
67
|
+
"react-doctor/no-inline-exhaustive-style": "error",
|
|
68
|
+
"react-doctor/no-inline-prop-on-memo-component": "error",
|
|
69
|
+
"react-doctor/no-json-parse-stringify-clone": "error",
|
|
70
|
+
"react-doctor/no-jsx-element-type": "error",
|
|
71
|
+
"react-doctor/no-large-animated-blur": "error",
|
|
72
|
+
"react-doctor/no-layout-property-animation": "error",
|
|
73
|
+
"react-doctor/no-layout-transition-inline": "error",
|
|
74
|
+
"react-doctor/no-legacy-class-lifecycles": "error",
|
|
75
|
+
"react-doctor/no-legacy-context-api": "error",
|
|
76
|
+
"react-doctor/no-long-transition-duration": "error",
|
|
77
|
+
"react-doctor/no-many-boolean-props": "error",
|
|
78
|
+
"react-doctor/no-mirror-prop-effect": "error",
|
|
79
|
+
"react-doctor/no-moment": "error",
|
|
80
|
+
"react-doctor/no-mutable-in-deps": "error",
|
|
81
|
+
"react-doctor/no-mutating-reducer-state": "error",
|
|
82
|
+
"react-doctor/no-nested-component-definition": "error",
|
|
83
|
+
"react-doctor/no-outline-none": "error",
|
|
84
|
+
"react-doctor/no-pass-data-to-parent": "error",
|
|
85
|
+
"react-doctor/no-pass-live-state-to-parent": "error",
|
|
86
|
+
"react-doctor/no-permanent-will-change": "error",
|
|
87
|
+
"react-doctor/no-polymorphic-children": "error",
|
|
88
|
+
"react-doctor/no-prevent-default": "error",
|
|
89
|
+
"react-doctor/no-prop-callback-in-effect": "error",
|
|
90
|
+
"react-doctor/no-random-key": "error",
|
|
91
|
+
"react-doctor/no-react-dom-deprecated-apis": "error",
|
|
92
|
+
"react-doctor/no-react19-deprecated-apis": "error",
|
|
93
|
+
"react-doctor/no-render-in-render": "error",
|
|
94
|
+
"react-doctor/no-render-prop-children": "error",
|
|
95
|
+
"react-doctor/no-reset-all-state-on-prop-change": "error",
|
|
96
|
+
"react-doctor/no-scale-from-zero": "error",
|
|
97
|
+
"react-doctor/no-secrets-in-client-code": "error",
|
|
98
|
+
"react-doctor/no-self-updating-effect": "error",
|
|
99
|
+
"react-doctor/no-set-state-in-render": "error",
|
|
100
|
+
"react-doctor/no-string-false-on-boolean-attribute": "error",
|
|
101
|
+
"react-doctor/no-sync-xhr": "error",
|
|
102
|
+
"react-doctor/no-tiny-text": "error",
|
|
103
|
+
"react-doctor/no-transition-all": "error",
|
|
104
|
+
"react-doctor/no-uncontrolled-input": "error",
|
|
105
|
+
"react-doctor/no-undeferred-third-party": "error",
|
|
106
|
+
"react-doctor/no-usememo-simple-expression": "error",
|
|
107
|
+
"react-doctor/only-export-components": "error",
|
|
108
|
+
"react-doctor/prefer-dynamic-import": "error",
|
|
109
|
+
"react-doctor/prefer-explicit-variants": "error",
|
|
110
|
+
"react-doctor/prefer-html-dialog": "error",
|
|
111
|
+
"react-doctor/prefer-module-scope-pure-function": "error",
|
|
112
|
+
"react-doctor/prefer-module-scope-static-value": "error",
|
|
113
|
+
"react-doctor/prefer-stable-empty-fallback": "error",
|
|
114
|
+
"react-doctor/prefer-use-effect-event": "error",
|
|
115
|
+
"react-doctor/prefer-use-sync-external-store": "error",
|
|
116
|
+
"react-doctor/prefer-useReducer": "error",
|
|
117
|
+
"react-doctor/react-compiler-no-manual-memoization": "error",
|
|
118
|
+
"react-doctor/redux-useselector-inline-derivation": "error",
|
|
119
|
+
"react-doctor/redux-useselector-returns-new-collection": "error",
|
|
120
|
+
"react-doctor/rendering-animate-svg-wrapper": "error",
|
|
121
|
+
"react-doctor/rendering-conditional-render": "error",
|
|
122
|
+
"react-doctor/rendering-hoist-jsx": "error",
|
|
123
|
+
"react-doctor/rendering-hydration-mismatch-time": "error",
|
|
124
|
+
"react-doctor/rendering-hydration-no-flicker": "error",
|
|
125
|
+
"react-doctor/rendering-script-defer-async": "error",
|
|
126
|
+
"react-doctor/rendering-svg-precision": "error",
|
|
127
|
+
"react-doctor/rendering-usetransition-loading": "error",
|
|
128
|
+
"react-doctor/rerender-defer-reads-hook": "error",
|
|
129
|
+
"react-doctor/rerender-dependencies": "error",
|
|
130
|
+
"react-doctor/rerender-derived-state-from-hook": "error",
|
|
131
|
+
"react-doctor/rerender-functional-setstate": "error",
|
|
132
|
+
"react-doctor/rerender-lazy-ref-init": "error",
|
|
133
|
+
"react-doctor/rerender-lazy-state-init": "error",
|
|
134
|
+
"react-doctor/rerender-memo-before-early-return": "error",
|
|
135
|
+
"react-doctor/rerender-memo-with-default-value": "error",
|
|
136
|
+
"react-doctor/rerender-state-only-in-handlers": "error",
|
|
137
|
+
"react-doctor/rerender-transitions-scroll": "error",
|
|
138
|
+
"react-doctor/server-after-nonblocking": "error",
|
|
139
|
+
"react-doctor/server-auth-actions": "error",
|
|
140
|
+
"react-doctor/server-cache-with-object-literal": "error",
|
|
141
|
+
"react-doctor/server-dedup-props": "error",
|
|
142
|
+
"react-doctor/server-fetch-without-revalidate": "error",
|
|
143
|
+
"react-doctor/server-hoist-static-io": "error",
|
|
144
|
+
"react-doctor/server-no-mutable-module-state": "error",
|
|
145
|
+
"react-doctor/server-sequential-independent-await": "error",
|
|
146
|
+
"react-doctor/use-lazy-motion": "error",
|
|
147
|
+
"react-doctor/zod-v4-no-deprecated-error-apis": "error",
|
|
148
|
+
"react-doctor/zod-v4-no-deprecated-error-customization": "error",
|
|
149
|
+
"react-doctor/zod-v4-no-deprecated-schema-apis": "error",
|
|
150
|
+
"react-doctor/zod-v4-prefer-top-level-string-formats": "error",
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default config;
|
|
@@ -12,6 +12,10 @@ const baseRules = Object.fromEntries(
|
|
|
12
12
|
|
|
13
13
|
const overrideRules = {
|
|
14
14
|
"react/forbid-component-props": "off",
|
|
15
|
+
// Crashes under ESLint 10 (uses the removed context.getSourceCode());
|
|
16
|
+
// forwardRef is deprecated in React 19 and
|
|
17
|
+
// react-doctor/no-react19-deprecated-apis covers it.
|
|
18
|
+
"react/forward-ref-uses-ref": "off",
|
|
15
19
|
"react/function-component-definition": [
|
|
16
20
|
"error",
|
|
17
21
|
{
|
|
@@ -19,12 +23,9 @@ const overrideRules = {
|
|
|
19
23
|
},
|
|
20
24
|
],
|
|
21
25
|
"react/jsx-boolean-value": "off",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
extensions: [".tsx"],
|
|
26
|
-
},
|
|
27
|
-
],
|
|
26
|
+
// Off in the oxlint react config, and its implementation uses the
|
|
27
|
+
// removed context.getFilename() under ESLint 10.
|
|
28
|
+
"react/jsx-filename-extension": "off",
|
|
28
29
|
"react/jsx-max-depth": "off",
|
|
29
30
|
"react/jsx-max-props-per-line": "off",
|
|
30
31
|
"react/jsx-newline": "off",
|
|
@@ -10,8 +10,15 @@ const baseRules = Object.fromEntries(
|
|
|
10
10
|
availableKeys.map((key) => [`svelte/${key}`, "error"])
|
|
11
11
|
);
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
// prettier-plugin-svelte owns formatting for .svelte files, so keep the
|
|
14
|
+
// formatting rules that the plugin's own prettier preset disables off.
|
|
15
|
+
const prettierConfig = plugin.configs["flat/prettier"];
|
|
16
|
+
const prettierOverrides = Object.fromEntries(
|
|
17
|
+
(Array.isArray(prettierConfig) ? prettierConfig : [prettierConfig])
|
|
18
|
+
.flatMap((entry) => Object.entries(entry.rules ?? {}))
|
|
19
|
+
.filter(([key]) => key.startsWith("svelte/"))
|
|
20
|
+
);
|
|
14
21
|
|
|
15
|
-
const config = Object.assign(baseRules,
|
|
22
|
+
const config = Object.assign(baseRules, prettierOverrides);
|
|
16
23
|
|
|
17
24
|
export default config;
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
import query from "@tanstack/eslint-plugin-query";
|
|
4
4
|
import router from "@tanstack/eslint-plugin-router";
|
|
5
5
|
import start from "@tanstack/eslint-plugin-start";
|
|
6
|
+
import reactDoctor from "eslint-plugin-react-doctor";
|
|
6
7
|
|
|
7
8
|
import queryRules from "./rules/query.mjs";
|
|
9
|
+
import reactDoctorRules from "./rules/react-doctor.mjs";
|
|
8
10
|
import routerRules from "./rules/router.mjs";
|
|
9
11
|
import startRules from "./rules/start.mjs";
|
|
10
12
|
|
|
@@ -22,11 +24,13 @@ const config = [
|
|
|
22
24
|
"@tanstack/query": query,
|
|
23
25
|
"@tanstack/router": router,
|
|
24
26
|
"@tanstack/start": start,
|
|
27
|
+
"react-doctor": reactDoctor,
|
|
25
28
|
},
|
|
26
29
|
rules: {
|
|
27
30
|
...queryRules,
|
|
28
31
|
...routerRules,
|
|
29
32
|
...startRules,
|
|
33
|
+
...reactDoctorRules,
|
|
30
34
|
},
|
|
31
35
|
},
|
|
32
36
|
];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const config = {
|
|
2
|
+
"react-doctor/query-destructure-result": "error",
|
|
3
|
+
"react-doctor/query-mutation-missing-invalidation": "error",
|
|
4
|
+
"react-doctor/query-no-query-in-effect": "error",
|
|
5
|
+
"react-doctor/query-no-rest-destructuring": "error",
|
|
6
|
+
"react-doctor/query-no-usequery-for-mutation": "error",
|
|
7
|
+
"react-doctor/query-no-void-query-fn": "error",
|
|
8
|
+
"react-doctor/query-stable-query-client": "error",
|
|
9
|
+
"react-doctor/tanstack-start-get-mutation": "error",
|
|
10
|
+
"react-doctor/tanstack-start-loader-parallel-fetch": "error",
|
|
11
|
+
"react-doctor/tanstack-start-missing-head-content": "error",
|
|
12
|
+
"react-doctor/tanstack-start-no-anchor-element": "error",
|
|
13
|
+
"react-doctor/tanstack-start-no-direct-fetch-in-loader": "error",
|
|
14
|
+
"react-doctor/tanstack-start-no-dynamic-server-fn-import": "error",
|
|
15
|
+
"react-doctor/tanstack-start-no-navigate-in-render": "error",
|
|
16
|
+
"react-doctor/tanstack-start-no-secrets-in-loader": "error",
|
|
17
|
+
"react-doctor/tanstack-start-no-use-server-in-handler": "error",
|
|
18
|
+
"react-doctor/tanstack-start-no-useeffect-fetch": "error",
|
|
19
|
+
"react-doctor/tanstack-start-redirect-in-try-catch": "error",
|
|
20
|
+
"react-doctor/tanstack-start-route-property-order": "error",
|
|
21
|
+
"react-doctor/tanstack-start-server-fn-method-order": "error",
|
|
22
|
+
"react-doctor/tanstack-start-server-fn-validate-input": "error",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default config;
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
/* eslint-disable n/no-unpublished-import, n/no-extraneous-import, import/no-extraneous-dependencies, id-length */
|
|
2
2
|
|
|
3
|
+
import eslintPrettier from "eslint-config-prettier";
|
|
3
4
|
import vue from "eslint-plugin-vue";
|
|
4
5
|
|
|
5
6
|
import vueRules from "./rules/vue.mjs";
|
|
6
7
|
|
|
8
|
+
// Only the vue/ entries — the all-on vue rules would otherwise re-enable
|
|
9
|
+
// the template formatting rules that eslint-config-prettier turns off.
|
|
10
|
+
// Prettier owns formatting for .vue files.
|
|
11
|
+
const vuePrettierOverrides = Object.fromEntries(
|
|
12
|
+
Object.entries(eslintPrettier.rules).filter(([key]) => key.startsWith("vue/"))
|
|
13
|
+
);
|
|
14
|
+
|
|
7
15
|
const config = [
|
|
8
16
|
{
|
|
9
17
|
files: ["**/*.vue"],
|
|
@@ -12,6 +20,7 @@ const config = [
|
|
|
12
20
|
},
|
|
13
21
|
rules: {
|
|
14
22
|
...vueRules,
|
|
23
|
+
...vuePrettierOverrides,
|
|
15
24
|
},
|
|
16
25
|
},
|
|
17
26
|
];
|