@wistia/oxlint-config 0.7.5 → 0.8.0
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 +15 -1
- package/package.json +11 -11
- package/rules/base.mjs +24 -0
- package/rules/import.mjs +9 -6
- package/rules/react-a11y.mjs +51 -0
- package/rules/react.mjs +12 -2
- package/rules/vitest.mjs +5 -0
package/README.md
CHANGED
|
@@ -12,9 +12,23 @@ Wistia's Oxlint configurations. This is a shared config package for [oxlint](htt
|
|
|
12
12
|
## How to install
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
yarn add -D @wistia/oxlint-config oxlint
|
|
15
|
+
yarn add -D @wistia/oxlint-config oxlint eslint
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
> **Why `eslint`?** This package uses oxlint's [jsPlugins](https://oxc.rs/docs/guide/usage/linter/js-plugins) feature to run ESLint plugins (e.g. `eslint-plugin-import-x`, `@eslint-react/eslint-plugin`, `eslint-plugin-testing-library`, etc.) natively inside oxlint. These plugins import utilities from the `eslint` package at runtime, so it must be installed even though you won't run `eslint` directly.
|
|
19
|
+
>
|
|
20
|
+
> **Note:** jsPlugins do not support rules that rely on TypeScript type information. Any type-aware rules in this config use native oxlint rules instead.
|
|
21
|
+
|
|
22
|
+
### Type-aware linting
|
|
23
|
+
|
|
24
|
+
The `typescriptConfig` enables [type-aware linting](https://oxc.rs/docs/guide/usage/linter/type-aware), which requires the `oxlint-tsgolint` package:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
yarn add -D oxlint-tsgolint
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`oxlint-tsgolint` is a separate Go-based tool that builds your TypeScript program using `typescript-go` and runs type-aware rules (e.g. detecting unhandled promises, unsafe assignments). Without it installed, type-aware rules will not run.
|
|
31
|
+
|
|
18
32
|
## Quick start
|
|
19
33
|
|
|
20
34
|
Create an `oxlint.config.ts` in your project root:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wistia/oxlint-config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Wistia's Oxlint configurations",
|
|
5
5
|
"packageManager": "yarn@4.14.1",
|
|
6
6
|
"type": "module",
|
|
@@ -55,16 +55,16 @@
|
|
|
55
55
|
"oxlint-tsgolint": ">= 1.0.0"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@eslint-react/eslint-plugin": "^5.
|
|
59
|
-
"@vitest/eslint-plugin": "^1.6.
|
|
58
|
+
"@eslint-react/eslint-plugin": "^5.8.3",
|
|
59
|
+
"@vitest/eslint-plugin": "^1.6.17",
|
|
60
60
|
"confusing-browser-globals": "^1.0.11",
|
|
61
61
|
"eslint-plugin-barrel-files": "^3.0.1",
|
|
62
62
|
"eslint-plugin-import-x": "^4.16.2",
|
|
63
63
|
"eslint-plugin-jest-dom": "^5.5.0",
|
|
64
64
|
"eslint-plugin-n": "^18.0.1",
|
|
65
65
|
"eslint-plugin-no-only-tests": "^3.4.0",
|
|
66
|
-
"eslint-plugin-playwright": "^2.10.
|
|
67
|
-
"eslint-plugin-storybook": "^10.
|
|
66
|
+
"eslint-plugin-playwright": "^2.10.4",
|
|
67
|
+
"eslint-plugin-storybook": "^10.4.0",
|
|
68
68
|
"eslint-plugin-styled-components": "^0.0.0",
|
|
69
69
|
"eslint-plugin-styled-components-a11y": "^2.2.1",
|
|
70
70
|
"eslint-plugin-testing-library": "^7.16.2",
|
|
@@ -73,12 +73,12 @@
|
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@changesets/changelog-github": "^0.7.0",
|
|
75
75
|
"@changesets/cli": "^2.31.0",
|
|
76
|
-
"eslint": "^10.
|
|
77
|
-
"oxfmt": "^0.
|
|
78
|
-
"oxlint": "^1.
|
|
79
|
-
"oxlint-tsgolint": "^0.
|
|
80
|
-
"storybook": "^10.
|
|
81
|
-
"vitest": "^4.1.
|
|
76
|
+
"eslint": "^10.4.0",
|
|
77
|
+
"oxfmt": "^0.51.0",
|
|
78
|
+
"oxlint": "^1.66.0",
|
|
79
|
+
"oxlint-tsgolint": "^0.23.0",
|
|
80
|
+
"storybook": "^10.4.0",
|
|
81
|
+
"vitest": "^4.1.7"
|
|
82
82
|
},
|
|
83
83
|
"engines": {
|
|
84
84
|
"node": "^20.19.0 || ^22.13.0 || >=24 || >=26"
|
package/rules/base.mjs
CHANGED
|
@@ -272,6 +272,11 @@ export const baseRules = {
|
|
|
272
272
|
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/grouped-accessor-pairs.html
|
|
273
273
|
'eslint/grouped-accessor-pairs': 'error',
|
|
274
274
|
|
|
275
|
+
// Require identifiers to match a specified regular expression
|
|
276
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/id-match.html
|
|
277
|
+
// Decision: too opinionated for general use
|
|
278
|
+
'eslint/id-match': 'off',
|
|
279
|
+
|
|
275
280
|
// Enforce minimum and maximum identifier lengths
|
|
276
281
|
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/id-length.html
|
|
277
282
|
'eslint/id-length': [
|
|
@@ -374,6 +379,14 @@ export const baseRules = {
|
|
|
374
379
|
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-implicit-coercion.html
|
|
375
380
|
'eslint/no-implicit-coercion': 'error',
|
|
376
381
|
|
|
382
|
+
// Disallow declarations in the global scope
|
|
383
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-implicit-globals.html
|
|
384
|
+
'eslint/no-implicit-globals': 'error',
|
|
385
|
+
|
|
386
|
+
// Disallow the use of eval()-like methods
|
|
387
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-implied-eval.html
|
|
388
|
+
'eslint/no-implied-eval': 'error',
|
|
389
|
+
|
|
377
390
|
// Disallow the use of the __iterator__ property
|
|
378
391
|
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-iterator.html
|
|
379
392
|
'eslint/no-iterator': 'error',
|
|
@@ -577,6 +590,13 @@ export const baseRules = {
|
|
|
577
590
|
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/operator-assignment.html
|
|
578
591
|
'eslint/operator-assignment': ['error', 'always'],
|
|
579
592
|
|
|
593
|
+
// Require using arrow functions for callbacks
|
|
594
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/prefer-arrow-callback.html
|
|
595
|
+
'eslint/prefer-arrow-callback': [
|
|
596
|
+
'error',
|
|
597
|
+
{ allowNamedFunctions: false, allowUnboundThis: true },
|
|
598
|
+
],
|
|
599
|
+
|
|
580
600
|
// Require const declarations for variables that are never reassigned after declared
|
|
581
601
|
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/prefer-const.html
|
|
582
602
|
'eslint/prefer-const': ['error', { destructuring: 'any', ignoreReadBeforeAssign: true }],
|
|
@@ -608,6 +628,10 @@ export const baseRules = {
|
|
|
608
628
|
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/prefer-object-spread.html
|
|
609
629
|
'eslint/prefer-object-spread': 'error',
|
|
610
630
|
|
|
631
|
+
// Disallow use of the RegExp constructor in favor of regular expression literals
|
|
632
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/prefer-regex-literals.html
|
|
633
|
+
'eslint/prefer-regex-literals': ['error', { disallowRedundantWrapping: true }],
|
|
634
|
+
|
|
611
635
|
// Require using Error objects as Promise rejection reasons
|
|
612
636
|
// https://oxc.rs/docs/guide/usage/linter/rules/eslint/prefer-promise-reject-errors.html
|
|
613
637
|
'eslint/prefer-promise-reject-errors': ['error', { allowEmptyReject: true }],
|
package/rules/import.mjs
CHANGED
|
@@ -115,6 +115,10 @@ export const importRules = {
|
|
|
115
115
|
// Decision: too opinionated for general use
|
|
116
116
|
'import/max-dependencies': 'off',
|
|
117
117
|
|
|
118
|
+
// Require a newline after the last import/require in a group
|
|
119
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/import/newline-after-import.html
|
|
120
|
+
'import/newline-after-import': 'error',
|
|
121
|
+
|
|
118
122
|
// Ensure named imports coupled with named exports
|
|
119
123
|
// https://oxc.rs/docs/guide/usage/linter/rules/import/named.html
|
|
120
124
|
// Decision: handled by TypeScript
|
|
@@ -175,19 +179,17 @@ export const importRules = {
|
|
|
175
179
|
'error',
|
|
176
180
|
{
|
|
177
181
|
devDependencies: [
|
|
178
|
-
'**/*{.,_}{test,vitest,spec}.{js,jsx,ts,tsx}',
|
|
182
|
+
'**/*{.,_}{test,vitest,spec,stories}.{js,jsx,ts,tsx}',
|
|
183
|
+
'**/oxfmt.config.*',
|
|
184
|
+
'**/.oxfmtrc.json*',
|
|
179
185
|
'**/vite.config.{ts,js,cjs,mjs,mts}',
|
|
180
186
|
'**/vitest.config.{ts,js,cjs,mjs,mts}',
|
|
181
|
-
'**/jest.config.{js,cjs,mjs,mts}',
|
|
182
|
-
'**/jest.setup.{js,cjs,mjs,mts}',
|
|
183
187
|
'**/eslint.config.{js,cjs,mjs,mts}',
|
|
184
188
|
'**/.eslintrc.{js,cjs}',
|
|
185
189
|
'**/.stylelintrc.{cjs,js,json,yaml,yml}',
|
|
186
190
|
'**/stylelint.config.{cjs,mjs,mts,js}',
|
|
187
191
|
'**/esbuild.config.{js,cjs,mjs,mts}',
|
|
188
192
|
'**/tsup.config.{js,cjs,mjs,mts}',
|
|
189
|
-
'**/webpack.config.{js,cjs,mjs,mts}',
|
|
190
|
-
'**/webpack.config.*.{js,cjs,mjs,mts}',
|
|
191
193
|
'**/rollup.config.{js,cjs,mjs,mts}',
|
|
192
194
|
'**/rollup.config.*.{js,cjs,mjs,mts}',
|
|
193
195
|
],
|
|
@@ -219,7 +221,8 @@ export const importRules = {
|
|
|
219
221
|
|
|
220
222
|
// Require a newline after the last import/require in a group
|
|
221
223
|
// https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/newline-after-import.md
|
|
222
|
-
|
|
224
|
+
// Decision: handled by native import/newline-after-import
|
|
225
|
+
'import-x-js/newline-after-import': 'off',
|
|
223
226
|
|
|
224
227
|
// Ensures that there are no useless path segments
|
|
225
228
|
// https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-useless-path-segments.md
|
package/rules/react-a11y.mjs
CHANGED
|
@@ -53,6 +53,30 @@ export const reactA11yRules = {
|
|
|
53
53
|
// Decision: too opinionated for general use
|
|
54
54
|
'jsx_a11y/autocomplete-valid': 'off',
|
|
55
55
|
|
|
56
|
+
// Enforce that a control (an interactive element) has a text label
|
|
57
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/jsx-a11y/control-has-associated-label.html
|
|
58
|
+
'jsx_a11y/control-has-associated-label': [
|
|
59
|
+
'error',
|
|
60
|
+
{
|
|
61
|
+
labelAttributes: ['label'],
|
|
62
|
+
controlComponents: [],
|
|
63
|
+
ignoreElements: ['audio', 'canvas', 'embed', 'input', 'textarea', 'tr', 'video'],
|
|
64
|
+
ignoreRoles: [
|
|
65
|
+
'grid',
|
|
66
|
+
'listbox',
|
|
67
|
+
'menu',
|
|
68
|
+
'menubar',
|
|
69
|
+
'radiogroup',
|
|
70
|
+
'row',
|
|
71
|
+
'tablist',
|
|
72
|
+
'toolbar',
|
|
73
|
+
'tree',
|
|
74
|
+
'treegrid',
|
|
75
|
+
],
|
|
76
|
+
depth: 5,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
|
|
56
80
|
// Enforce a clickable non-interactive element has at least one keyboard event listener
|
|
57
81
|
// https://oxc.rs/docs/guide/usage/linter/rules/jsx-a11y/click-events-have-key-events.html
|
|
58
82
|
'jsx_a11y/click-events-have-key-events': 'error',
|
|
@@ -128,6 +152,33 @@ export const reactA11yRules = {
|
|
|
128
152
|
},
|
|
129
153
|
],
|
|
130
154
|
|
|
155
|
+
// Ensure interactive elements are not assigned non-interactive roles
|
|
156
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/jsx-a11y/no-interactive-element-to-noninteractive-role.html
|
|
157
|
+
'jsx_a11y/no-interactive-element-to-noninteractive-role': [
|
|
158
|
+
'error',
|
|
159
|
+
{ tr: ['none', 'presentation'] },
|
|
160
|
+
],
|
|
161
|
+
|
|
162
|
+
// Enforce that non-interactive elements do not have interaction handlers
|
|
163
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/jsx-a11y/no-noninteractive-element-interactions.html
|
|
164
|
+
'jsx_a11y/no-noninteractive-element-interactions': [
|
|
165
|
+
'error',
|
|
166
|
+
{ handlers: ['onClick', 'onMouseDown', 'onMouseUp', 'onKeyPress', 'onKeyDown', 'onKeyUp'] },
|
|
167
|
+
],
|
|
168
|
+
|
|
169
|
+
// Enforce that non-interactive elements are not assigned interactive roles
|
|
170
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/jsx-a11y/no-noninteractive-element-to-interactive-role.html
|
|
171
|
+
'jsx_a11y/no-noninteractive-element-to-interactive-role': [
|
|
172
|
+
'error',
|
|
173
|
+
{
|
|
174
|
+
ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
|
|
175
|
+
ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'],
|
|
176
|
+
li: ['menuitem', 'option', 'row', 'tab', 'treeitem'],
|
|
177
|
+
table: ['grid'],
|
|
178
|
+
td: ['gridcell'],
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
|
|
131
182
|
// Enforce explicit role is not redundant with implicit role of the element
|
|
132
183
|
// https://oxc.rs/docs/guide/usage/linter/rules/jsx-a11y/no-redundant-roles.html
|
|
133
184
|
'jsx_a11y/no-redundant-roles': 'error',
|
package/rules/react.mjs
CHANGED
|
@@ -105,6 +105,14 @@ export const reactRules = {
|
|
|
105
105
|
// Decision: this is a decision best left to the implementer
|
|
106
106
|
'react/no-multi-comp': 'off',
|
|
107
107
|
|
|
108
|
+
// Disallow object types as default props
|
|
109
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/react/no-object-type-as-default-prop.html
|
|
110
|
+
'react/no-object-type-as-default-prop': 'error',
|
|
111
|
+
|
|
112
|
+
// Disallow creating unstable components inside components
|
|
113
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/react/no-unstable-nested-components.html
|
|
114
|
+
'react/no-unstable-nested-components': 'error',
|
|
115
|
+
|
|
108
116
|
// Disallow usage of the return value of ReactDOM.render
|
|
109
117
|
// https://oxc.rs/docs/guide/usage/linter/rules/react/no-render-return-value.html
|
|
110
118
|
'react/no-render-return-value': 'error',
|
|
@@ -430,7 +438,8 @@ export const reactRules = {
|
|
|
430
438
|
|
|
431
439
|
// Prevent creating unstable components inside components
|
|
432
440
|
// https://eslint-react.xyz/docs/rules/no-nested-component-definitions
|
|
433
|
-
|
|
441
|
+
// Decision: handled by native react/no-unstable-nested-components
|
|
442
|
+
'@eslint-react/no-nested-component-definitions': 'off',
|
|
434
443
|
|
|
435
444
|
// Prevent creating lazy components inside components
|
|
436
445
|
// https://eslint-react.xyz/docs/rules/no-nested-lazy-component-declarations
|
|
@@ -473,7 +482,8 @@ export const reactRules = {
|
|
|
473
482
|
|
|
474
483
|
// Disallow referential-type variables as default props
|
|
475
484
|
// https://eslint-react.xyz/docs/rules/no-unstable-default-props
|
|
476
|
-
|
|
485
|
+
// Decision: handled by native react/no-object-type-as-default-prop
|
|
486
|
+
'@eslint-react/no-unstable-default-props': 'off',
|
|
477
487
|
|
|
478
488
|
// Prevent declaring unused methods of component class
|
|
479
489
|
// https://eslint-react.xyz/docs/rules/no-unused-class-component-members
|
package/rules/vitest.mjs
CHANGED
|
@@ -30,6 +30,11 @@ export const vitestRules = {
|
|
|
30
30
|
// https://oxc.rs/docs/guide/usage/linter/rules/vitest/no-import-node-test.html
|
|
31
31
|
'vitest/no-import-node-test': 'error',
|
|
32
32
|
|
|
33
|
+
// Enforce padding around afterAll blocks
|
|
34
|
+
// https://oxc.rs/docs/guide/usage/linter/rules/vitest/padding-around-after-all-blocks.html
|
|
35
|
+
// Decision: stylistic formatting rule, left to formatter
|
|
36
|
+
'vitest/padding-around-after-all-blocks': 'off',
|
|
37
|
+
|
|
33
38
|
// Disallow conditional tests
|
|
34
39
|
// https://oxc.rs/docs/guide/usage/linter/rules/vitest/no-conditional-in-test.html
|
|
35
40
|
'vitest/no-conditional-in-test': 'error',
|