@tommy-mitchell/eslint-config-xo 2.0.0-beta.6 → 2.0.0-beta.8
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/package.json +37 -38
- package/readme.md +20 -6
- package/src/index.d.ts +1 -1
- package/src/index.js +0 -1
- package/src/react.js +39 -25
- package/src/tailwind.js +7 -7
- package/src/tanstack.js +1 -0
- package/src/xo.js +1 -0
package/package.json
CHANGED
|
@@ -1,60 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tommy-mitchell/eslint-config-xo",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.8",
|
|
4
4
|
"description": "Personal config for XO.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"nodejs",
|
|
7
|
-
"config",
|
|
8
|
-
"xo"
|
|
9
|
-
],
|
|
10
|
-
"repository": "tommy-mitchell/eslint-config-xo",
|
|
11
5
|
"license": "MIT",
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
"url": "https://tommymitchell.io"
|
|
15
|
-
},
|
|
16
|
-
"sideEffects": false,
|
|
6
|
+
"repository": "tommy-mitchell/eslint-config-xo",
|
|
7
|
+
"author": "Tommy Mitchell (https://tommymitchell.io)",
|
|
17
8
|
"type": "module",
|
|
18
|
-
"files": [
|
|
19
|
-
"src"
|
|
20
|
-
],
|
|
21
9
|
"exports": {
|
|
22
10
|
"types": "./src/index.d.ts",
|
|
23
11
|
"default": "./src/index.js"
|
|
24
12
|
},
|
|
13
|
+
"sideEffects": false,
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": "^22.22 || ^24.15 || >=26"
|
|
16
|
+
},
|
|
25
17
|
"scripts": {
|
|
26
|
-
"format": "dprint fmt && xo --fix",
|
|
27
18
|
"lint": "xo",
|
|
19
|
+
"format": "dprint fmt && xo --fix",
|
|
28
20
|
"test": "ava"
|
|
29
21
|
},
|
|
22
|
+
"files": [
|
|
23
|
+
"src"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"nodejs",
|
|
27
|
+
"config",
|
|
28
|
+
"xo"
|
|
29
|
+
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"
|
|
34
|
-
"eslint-plugin-
|
|
35
|
-
"eslint-plugin-
|
|
36
|
-
"eslint-plugin-
|
|
37
|
-
"eslint-plugin-react-refresh": "^0.5.2",
|
|
38
|
-
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
39
|
-
"eslint-plugin-sort-react-dependency-arrays": "^1.0.0"
|
|
31
|
+
"@next/eslint-plugin-next": "^16.3.7",
|
|
32
|
+
"@tanstack/eslint-plugin-router": "^1.162.0",
|
|
33
|
+
"eslint-plugin-better-tailwindcss": "^4.7.0",
|
|
34
|
+
"eslint-plugin-perfectionist": "^5.12.1",
|
|
35
|
+
"eslint-plugin-react-refresh": "^0.5.7",
|
|
36
|
+
"eslint-plugin-simple-import-sort": "^14.0.0"
|
|
40
37
|
},
|
|
41
38
|
"devDependencies": {
|
|
42
|
-
"@stylistic/eslint-plugin": "^5.
|
|
43
|
-
"@tommy-mitchell/dprint-config": "0.
|
|
44
|
-
"
|
|
39
|
+
"@stylistic/eslint-plugin": "^5.10.0",
|
|
40
|
+
"@tommy-mitchell/dprint-config": "^0.8.0",
|
|
41
|
+
"@tommy-mitchell/tsconfig": "^4.0.0",
|
|
42
|
+
"@types/node": "^22.20.4",
|
|
43
|
+
"@types/react": "^19.3.0",
|
|
44
|
+
"ava": "^8.0.1",
|
|
45
45
|
"dprint": "0.x",
|
|
46
|
-
"
|
|
47
|
-
"react": "^19.
|
|
48
|
-
"tailwindcss": "^4.
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"xo": "~2.0.2"
|
|
46
|
+
"eslint-config-xo-react": "^0.32.0",
|
|
47
|
+
"react": "^19.3.0",
|
|
48
|
+
"tailwindcss": "^4.3.3",
|
|
49
|
+
"typescript": "~6.0.3",
|
|
50
|
+
"xo": "~5.0.1"
|
|
52
51
|
},
|
|
53
52
|
"peerDependencies": {
|
|
54
53
|
"dprint": "0.x",
|
|
55
54
|
"react": "19.x",
|
|
56
55
|
"tailwindcss": "4.x",
|
|
57
|
-
"xo": "
|
|
56
|
+
"xo": "5.x"
|
|
58
57
|
},
|
|
59
58
|
"peerDependenciesMeta": {
|
|
60
59
|
"dprint": {
|
|
@@ -67,10 +66,10 @@
|
|
|
67
66
|
"optional": true
|
|
68
67
|
}
|
|
69
68
|
},
|
|
70
|
-
"engines": {
|
|
71
|
-
"node": ">=22"
|
|
72
|
-
},
|
|
73
69
|
"ava": {
|
|
70
|
+
"extensions": [
|
|
71
|
+
"ts"
|
|
72
|
+
],
|
|
74
73
|
"timeout": "30s"
|
|
75
74
|
}
|
|
76
75
|
}
|
package/readme.md
CHANGED
|
@@ -45,9 +45,9 @@ pnpm add --save-dev @tommy-mitchell/eslint-config-xo xo @tommy-mitchell/dprint-c
|
|
|
45
45
|
### Peer Dependencies
|
|
46
46
|
|
|
47
47
|
- [xo](https://github.com/xojs/xo) - JavaScript/TypeScript linter (ESLint wrapper) with great defaults.
|
|
48
|
-
- [dprint](https://github.com/dprint/dprint) (
|
|
49
|
-
- [react](https://react.dev) (
|
|
50
|
-
- [tailwindcss](https://tailwindcss.com) (
|
|
48
|
+
- [dprint](https://github.com/dprint/dprint) (_Optional_) - Pluggable and configurable code formatting platform written in Rust.
|
|
49
|
+
- [react](https://react.dev) (_Optional_) - The library for web and native user interfaces.
|
|
50
|
+
- [tailwindcss](https://tailwindcss.com) (_Optional_) - A utility-first CSS framework for rapid UI development.
|
|
51
51
|
|
|
52
52
|
## Usage (Flat Config)
|
|
53
53
|
|
|
@@ -58,13 +58,27 @@ import * as configs from "@tommy-mitchell/eslint-config-xo";
|
|
|
58
58
|
/** @type {import('xo').FlatXoConfig} */
|
|
59
59
|
export default [
|
|
60
60
|
...configs.xo,
|
|
61
|
-
...configs.react
|
|
61
|
+
...configs.react, // If using React
|
|
62
62
|
...configs.next, // If using Next.js
|
|
63
63
|
...configs.tanstack, // If using TanStack Start
|
|
64
64
|
...configs.tailwind({ config: "src/tailwind.css" }), // If using TailwindCSS
|
|
65
65
|
...configs.dprint, // If using dprint (must be last to override stylistic rules)
|
|
66
66
|
// Plus any overrides
|
|
67
|
-
]
|
|
67
|
+
];
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### TailwindCSS
|
|
71
|
+
|
|
72
|
+
Add the following to your `settings.json` to prevent duplicate lints:
|
|
73
|
+
|
|
74
|
+
```jsonc
|
|
75
|
+
"tailwindCSS.lint.suggestCanonicalClasses": "ignore",
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If using TailwindCSS v3:
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
configs.tailwind({ config: "tailwind.config.ts", version: "3" }),
|
|
68
82
|
```
|
|
69
83
|
|
|
70
84
|
### VS Code
|
|
@@ -81,7 +95,7 @@ Add the following to your `settings.json`:
|
|
|
81
95
|
If formatting with `dprint`:
|
|
82
96
|
|
|
83
97
|
```jsonc
|
|
84
|
-
"[javascript][javascriptreact][typescript][typescriptreact]": {
|
|
98
|
+
"[javascript][javascriptreact][typescript][typescriptreact][json][jsonc][yaml][markdown]": {
|
|
85
99
|
"editor.formatOnSave": true,
|
|
86
100
|
"editor.defaultFormatter": "dprint.dprint",
|
|
87
101
|
"editor.codeActionsOnSave": {
|
package/src/index.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ import type { FlatXoConfig } from "xo";
|
|
|
3
3
|
export declare const dprint: FlatXoConfig;
|
|
4
4
|
export declare const next: FlatXoConfig;
|
|
5
5
|
export declare const react: FlatXoConfig;
|
|
6
|
-
export declare const tailwind: (
|
|
6
|
+
export declare const tailwind: (options: { config: string; version?: "3" | "4"; }) => FlatXoConfig;
|
|
7
7
|
export declare const tanstack: FlatXoConfig;
|
|
8
8
|
export declare const xo: FlatXoConfig;
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { default as dprint } from "./dprint.js";
|
|
2
2
|
export { default as next } from "./next.js";
|
|
3
3
|
export { default as react } from "./react.js";
|
|
4
|
-
// TODO: only load if tailwind is installed
|
|
5
4
|
export { default as tailwind } from "./tailwind.js";
|
|
6
5
|
export { default as tanstack } from "./tanstack.js";
|
|
7
6
|
export { default as xo } from "./xo.js";
|
package/src/react.js
CHANGED
|
@@ -1,28 +1,48 @@
|
|
|
1
|
-
import
|
|
2
|
-
import jsxA11y from "eslint-plugin-jsx-a11y";
|
|
1
|
+
import eslintConfigXoReact from "eslint-config-xo-react";
|
|
3
2
|
import { reactRefresh } from "eslint-plugin-react-refresh";
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
const customGroups = [
|
|
5
|
+
{ elementNamePattern: "^on[A-Z].*", groupName: "callback" },
|
|
6
|
+
{ elementNamePattern: "^(children|dangerouslySetInnerHTML|key|ref)$", groupName: "reserved" },
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
const reactDependencyHooks = [
|
|
10
|
+
"useCallback",
|
|
11
|
+
"useEffect",
|
|
12
|
+
"useImperativeHandle",
|
|
13
|
+
"useInsertionEffect",
|
|
14
|
+
"useLayoutEffect",
|
|
15
|
+
"useMemo",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
// useX()
|
|
19
|
+
const reactHookCallees = reactDependencyHooks.map(hook => ([
|
|
20
|
+
"[callee.type=\"Identifier\"]",
|
|
21
|
+
`[callee.name="${hook}"]`,
|
|
22
|
+
].join(""))).join(", ");
|
|
23
|
+
|
|
24
|
+
// React.useX()
|
|
25
|
+
const reactHookMemberCallees = reactDependencyHooks.map(hook => ([
|
|
26
|
+
"[callee.type=\"MemberExpression\"]",
|
|
27
|
+
"[callee.object.type=\"Identifier\"]",
|
|
28
|
+
"[callee.object.name=\"React\"]",
|
|
29
|
+
"[callee.property.type=\"Identifier\"]",
|
|
30
|
+
`[callee.property.name="${hook}"]`,
|
|
31
|
+
].join(""))).join(", ");
|
|
5
32
|
|
|
6
33
|
/** @type {import('xo').FlatXoConfig} */
|
|
7
|
-
export default [
|
|
8
|
-
...eslintReact.configs.strict,
|
|
9
|
-
files: "**/*.{jsx}",
|
|
10
|
-
}, {
|
|
11
|
-
...eslintReact.configs["strict-type-checked"],
|
|
12
|
-
files: "**/*.{tsx}",
|
|
13
|
-
}, {
|
|
34
|
+
export default [...eslintConfigXoReact(), {
|
|
14
35
|
plugins: {
|
|
15
36
|
"react-refresh": reactRefresh.plugin,
|
|
16
|
-
"sort-react-dependency-arrays": sortReactDependencyArrays,
|
|
17
37
|
},
|
|
18
|
-
// TODO: boolean-prop-naming
|
|
19
38
|
rules: {
|
|
39
|
+
"perfectionist/sort-arrays": ["error", {
|
|
40
|
+
useConfigurationIf: {
|
|
41
|
+
matchesAstSelector: `CallExpression:is(${reactHookCallees}, ${reactHookMemberCallees}) > ArrayExpression`,
|
|
42
|
+
},
|
|
43
|
+
}],
|
|
20
44
|
"perfectionist/sort-jsx-props": ["error", {
|
|
21
|
-
customGroups
|
|
22
|
-
// TODO: move groups to a constant for reuse
|
|
23
|
-
{ elementNamePattern: "^on[A-Z].*", groupName: "callback" },
|
|
24
|
-
{ elementNamePattern: "^(children|dangerouslySetInnerHTML|key|ref)$", groupName: "reserved" },
|
|
25
|
-
],
|
|
45
|
+
customGroups,
|
|
26
46
|
groups: ["reserved", "shorthand-prop", "unknown", "callback"],
|
|
27
47
|
}],
|
|
28
48
|
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
|
|
@@ -38,7 +58,6 @@ export default [jsxA11y.flatConfigs.recommended, {
|
|
|
38
58
|
String.raw`^.+\.s?css$`,
|
|
39
59
|
]],
|
|
40
60
|
}],
|
|
41
|
-
"sort-react-dependency-arrays/sort": "error",
|
|
42
61
|
"unicorn/filename-case": ["error", {
|
|
43
62
|
cases: {
|
|
44
63
|
camelCase: true,
|
|
@@ -47,20 +66,15 @@ export default [jsxA11y.flatConfigs.recommended, {
|
|
|
47
66
|
},
|
|
48
67
|
}],
|
|
49
68
|
},
|
|
50
|
-
}, {
|
|
51
|
-
files: ["src/constants/**/*.{ts,cts,mts,tsx}", "**/constants.{ts,cts,mts,tsx}"],
|
|
52
|
-
rules: {
|
|
53
|
-
"@typescript-eslint/naming-convention": "off",
|
|
54
|
-
},
|
|
55
69
|
}, {
|
|
56
70
|
files: "**/*.{ts,cts,mts,tsx}",
|
|
57
71
|
rules: {
|
|
58
72
|
"perfectionist/sort-interfaces": ["error", {
|
|
59
|
-
customGroups
|
|
73
|
+
customGroups,
|
|
60
74
|
groups: ["unknown", "callback"],
|
|
61
75
|
}],
|
|
62
76
|
"perfectionist/sort-object-types": ["error", {
|
|
63
|
-
customGroups
|
|
77
|
+
customGroups,
|
|
64
78
|
groups: ["unknown", "callback"],
|
|
65
79
|
}],
|
|
66
80
|
},
|
package/src/tailwind.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import eslintPluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
},
|
|
3
|
+
// eslint-disable-next-line jsdoc/require-description
|
|
4
|
+
/** @type {(options: {config: string; version?: "3" | "4"}) => import('xo').FlatXoConfig} */
|
|
5
|
+
export default ({ config, version = "4" }) => [{
|
|
6
|
+
...eslintPluginBetterTailwindcss.configs.recommended,
|
|
8
7
|
rules: {
|
|
9
|
-
...eslintPluginBetterTailwindcss.configs.recommended.rules,
|
|
10
8
|
"better-tailwindcss/enforce-consistent-line-wrapping": ["warn", {
|
|
11
9
|
indent: "tab",
|
|
12
10
|
preferSingleLine: true,
|
|
13
11
|
printWidth: 120,
|
|
12
|
+
tabWidth: 2,
|
|
14
13
|
}],
|
|
14
|
+
"better-tailwindcss/enforce-logical-properties": ["warn"],
|
|
15
15
|
},
|
|
16
16
|
settings: {
|
|
17
17
|
"better-tailwindcss": {
|
|
18
18
|
callees: ["clsx", "cn", "cnx", "cva", "cx", "tv", "twJoin", "twMerge"],
|
|
19
19
|
detectComponentClasses: true,
|
|
20
|
-
|
|
20
|
+
...(version === "3" ? { tailwindConfig: config } : { entryPoint: config }),
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
23
|
}];
|
package/src/tanstack.js
CHANGED