diff --git a/src/docs/guide/usage/linter/generated-config.md b/src/docs/guide/usage/linter/generated-config.md
index bb7dacd3a6d..b129ddcd1de 100644
--- a/src/docs/guide/usage/linter/generated-config.md
+++ b/src/docs/guide/usage/linter/generated-config.md
@@ -143,6 +143,14 @@ default: `[]`
Globs to ignore during linting. These are resolved from the configuration file path.
+## jsPlugins
+
+type: `string[]`
+
+default: `null`
+
+JS plugins.
+
## overrides
type: `array`
@@ -157,6 +165,12 @@ type: `string[]`
A set of glob patterns.
+#### overrides[n].jsPlugins
+
+type: `string[]`
+
+JS plugins for this override.
+
#### overrides[n].rules
type: `object`
diff --git a/src/docs/guide/usage/linter/generated-rules.md b/src/docs/guide/usage/linter/generated-rules.md
index 6fcc728f1cb..1ff06592b00 100644
--- a/src/docs/guide/usage/linter/generated-rules.md
+++ b/src/docs/guide/usage/linter/generated-rules.md
@@ -2,8 +2,8 @@
The progress of all rule implementations is tracked [here](https://github.com/oxc-project/oxc/issues/481).
-- Total number of rules: 585
-- Rules turned on by default: 102
+- Total number of rules: 591
+- Rules turned on by default: 103
**Legend for 'Fixable?' column:**
@@ -13,7 +13,7 @@ The progress of all rule implementations is tracked [here](https://github.com/ox
- β οΈπ‘: a dangerous suggestion is available for this rule
- π§: an auto-fix or suggestion is possible, but currently not implemented
-## Correctness (194):
+## Correctness (195):
Code that is outright wrong or useless.
@@ -59,6 +59,7 @@ Code that is outright wrong or useless.
| [no-unsafe-finally](/docs/guide/usage/linter/rules/eslint/no-unsafe-finally.html) | eslint | β
| |
| [no-unsafe-negation](/docs/guide/usage/linter/rules/eslint/no-unsafe-negation.html) | eslint | β
| π οΈ |
| [no-unsafe-optional-chaining](/docs/guide/usage/linter/rules/eslint/no-unsafe-optional-chaining.html) | eslint | β
| |
+| [no-unused-expressions](/docs/guide/usage/linter/rules/eslint/no-unused-expressions.html) | eslint | β
| |
| [no-unused-labels](/docs/guide/usage/linter/rules/eslint/no-unused-labels.html) | eslint | β
| π οΈ |
| [no-unused-private-class-members](/docs/guide/usage/linter/rules/eslint/no-unused-private-class-members.html) | eslint | β
| |
| [no-unused-vars](/docs/guide/usage/linter/rules/eslint/no-unused-vars.html) | eslint | β
| β οΈπ‘ |
@@ -254,7 +255,6 @@ Lints which prevent the use of language and library features. Must not be enable
| [no-restricted-globals](/docs/guide/usage/linter/rules/eslint/no-restricted-globals.html) | eslint | | |
| [no-restricted-imports](/docs/guide/usage/linter/rules/eslint/no-restricted-imports.html) | eslint | | |
| [no-undefined](/docs/guide/usage/linter/rules/eslint/no-undefined.html) | eslint | | |
-| [no-unused-expressions](/docs/guide/usage/linter/rules/eslint/no-unused-expressions.html) | eslint | | |
| [no-var](/docs/guide/usage/linter/rules/eslint/no-var.html) | eslint | | π οΈ |
| [no-void](/docs/guide/usage/linter/rules/eslint/no-void.html) | eslint | | π‘ |
| [unicode-bom](/docs/guide/usage/linter/rules/eslint/unicode-bom.html) | eslint | | π οΈ |
@@ -309,9 +309,10 @@ Lints which prevent the use of language and library features. Must not be enable
| [prefer-modern-math-apis](/docs/guide/usage/linter/rules/unicorn/prefer-modern-math-apis.html) | unicorn | | π§ |
| [prefer-node-protocol](/docs/guide/usage/linter/rules/unicorn/prefer-node-protocol.html) | unicorn | | π οΈ |
| [prefer-number-properties](/docs/guide/usage/linter/rules/unicorn/prefer-number-properties.html) | unicorn | | β οΈπ οΈοΈ |
+| [max-props](/docs/guide/usage/linter/rules/vue/max-props.html) | vue | | |
| [no-multiple-slot-args](/docs/guide/usage/linter/rules/vue/no-multiple-slot-args.html) | vue | | π§ |
-## Suspicious (43):
+## Suspicious (45):
code that is most likely wrong or useless.
@@ -325,7 +326,7 @@ code that is most likely wrong or useless.
| [no-unneeded-ternary](/docs/guide/usage/linter/rules/eslint/no-unneeded-ternary.html) | eslint | | β οΈπ οΈοΈ |
| [no-useless-concat](/docs/guide/usage/linter/rules/eslint/no-useless-concat.html) | eslint | | |
| [no-useless-constructor](/docs/guide/usage/linter/rules/eslint/no-useless-constructor.html) | eslint | | π οΈ |
-| [preserve-caught-error](/docs/guide/usage/linter/rules/eslint/preserve-caught-error.html) | eslint | | π§ |
+| [preserve-caught-error](/docs/guide/usage/linter/rules/eslint/preserve-caught-error.html) | eslint | | π οΈ |
| [no-absolute-path](/docs/guide/usage/linter/rules/import/no-absolute-path.html) | import | | π§ |
| [no-empty-named-blocks](/docs/guide/usage/linter/rules/import/no-empty-named-blocks.html) | import | | π οΈ |
| [no-named-as-default](/docs/guide/usage/linter/rules/import/no-named-as-default.html) | import | | |
@@ -337,6 +338,7 @@ code that is most likely wrong or useless.
| [misrefactored-assign-op](/docs/guide/usage/linter/rules/oxc/misrefactored-assign-op.html) | oxc | | π§ |
| [no-async-endpoint-handlers](/docs/guide/usage/linter/rules/oxc/no-async-endpoint-handlers.html) | oxc | | |
| [always-return](/docs/guide/usage/linter/rules/promise/always-return.html) | promise | | |
+| [no-multiple-resolved](/docs/guide/usage/linter/rules/promise/no-multiple-resolved.html) | promise | | |
| [no-promise-in-callback](/docs/guide/usage/linter/rules/promise/no-promise-in-callback.html) | promise | | |
| [iframe-missing-sandbox](/docs/guide/usage/linter/rules/react/iframe-missing-sandbox.html) | react | | π§ |
| [jsx-no-comment-textnodes](/docs/guide/usage/linter/rules/react/jsx-no-comment-textnodes.html) | react | | |
@@ -356,12 +358,13 @@ code that is most likely wrong or useless.
| [consistent-function-scoping](/docs/guide/usage/linter/rules/unicorn/consistent-function-scoping.html) | unicorn | | π§ |
| [no-accessor-recursion](/docs/guide/usage/linter/rules/unicorn/no-accessor-recursion.html) | unicorn | | |
| [no-array-reverse](/docs/guide/usage/linter/rules/unicorn/no-array-reverse.html) | unicorn | | π οΈ |
+| [no-array-sort](/docs/guide/usage/linter/rules/unicorn/no-array-sort.html) | unicorn | | π οΈ |
| [no-instanceof-builtins](/docs/guide/usage/linter/rules/unicorn/no-instanceof-builtins.html) | unicorn | | π§ |
| [prefer-add-event-listener](/docs/guide/usage/linter/rules/unicorn/prefer-add-event-listener.html) | unicorn | | π§ |
| [require-post-message-target-origin](/docs/guide/usage/linter/rules/unicorn/require-post-message-target-origin.html) | unicorn | | π‘ |
| [no-required-prop-with-default](/docs/guide/usage/linter/rules/vue/no-required-prop-with-default.html) | vue | | π§ |
-## Pedantic (97):
+## Pedantic (98):
Lints which are rather strict or have occasional false positives.
@@ -430,6 +433,7 @@ Lints which are rather strict or have occasional false positives.
| [escape-case](/docs/guide/usage/linter/rules/unicorn/escape-case.html) | unicorn | | π οΈ |
| [explicit-length-check](/docs/guide/usage/linter/rules/unicorn/explicit-length-check.html) | unicorn | | π οΈ |
| [new-for-builtins](/docs/guide/usage/linter/rules/unicorn/new-for-builtins.html) | unicorn | | |
+| [no-array-callback-reference](/docs/guide/usage/linter/rules/unicorn/no-array-callback-reference.html) | unicorn | | π§ |
| [no-hex-escape](/docs/guide/usage/linter/rules/unicorn/no-hex-escape.html) | unicorn | | π οΈ |
| [no-instanceof-array](/docs/guide/usage/linter/rules/unicorn/no-instanceof-array.html) | unicorn | | π οΈ |
| [no-lonely-if](/docs/guide/usage/linter/rules/unicorn/no-lonely-if.html) | unicorn | | |
@@ -465,7 +469,7 @@ Lints which are rather strict or have occasional false positives.
| [prefer-type-error](/docs/guide/usage/linter/rules/unicorn/prefer-type-error.html) | unicorn | | π οΈ |
| [require-number-to-fixed-digits-argument](/docs/guide/usage/linter/rules/unicorn/require-number-to-fixed-digits-argument.html) | unicorn | | π οΈ |
-## Style (159):
+## Style (161):
Code that should be written in a more idiomatic way.
@@ -510,7 +514,7 @@ Code that should be written in a more idiomatic way.
| [prefer-spread](/docs/guide/usage/linter/rules/eslint/prefer-spread.html) | eslint | | |
| [prefer-template](/docs/guide/usage/linter/rules/eslint/prefer-template.html) | eslint | | π§ |
| [sort-imports](/docs/guide/usage/linter/rules/eslint/sort-imports.html) | eslint | | π οΈ |
-| [sort-keys](/docs/guide/usage/linter/rules/eslint/sort-keys.html) | eslint | | π§ |
+| [sort-keys](/docs/guide/usage/linter/rules/eslint/sort-keys.html) | eslint | | π οΈ |
| [vars-on-top](/docs/guide/usage/linter/rules/eslint/vars-on-top.html) | eslint | | |
| [yoda](/docs/guide/usage/linter/rules/eslint/yoda.html) | eslint | | π οΈ |
| [consistent-type-specifier-style](/docs/guide/usage/linter/rules/import/consistent-type-specifier-style.html) | import | | π οΈ |
@@ -521,6 +525,7 @@ Code that should be written in a more idiomatic way.
| [no-duplicates](/docs/guide/usage/linter/rules/import/no-duplicates.html) | import | | |
| [no-mutable-exports](/docs/guide/usage/linter/rules/import/no-mutable-exports.html) | import | | |
| [no-named-default](/docs/guide/usage/linter/rules/import/no-named-default.html) | import | | |
+| [no-named-export](/docs/guide/usage/linter/rules/import/no-named-export.html) | import | | |
| [no-namespace](/docs/guide/usage/linter/rules/import/no-namespace.html) | import | | π§ |
| [prefer-default-export](/docs/guide/usage/linter/rules/import/prefer-default-export.html) | import | | |
| [consistent-test-it](/docs/guide/usage/linter/rules/jest/consistent-test-it.html) | jest | | π οΈ |
@@ -573,6 +578,7 @@ Code that should be written in a more idiomatic way.
| [jsx-curly-brace-presence](/docs/guide/usage/linter/rules/react/jsx-curly-brace-presence.html) | react | | π οΈ |
| [jsx-fragments](/docs/guide/usage/linter/rules/react/jsx-fragments.html) | react | | π οΈ |
| [jsx-handler-names](/docs/guide/usage/linter/rules/react/jsx-handler-names.html) | react | | |
+| [jsx-pascal-case](/docs/guide/usage/linter/rules/react/jsx-pascal-case.html) | react | | |
| [no-set-state](/docs/guide/usage/linter/rules/react/no-set-state.html) | react | | |
| [prefer-es6-class](/docs/guide/usage/linter/rules/react/prefer-es6-class.html) | react | | |
| [self-closing-comp](/docs/guide/usage/linter/rules/react/self-closing-comp.html) | react | | π οΈ |
diff --git a/src/docs/guide/usage/linter/rules/eslint/curly.md b/src/docs/guide/usage/linter/rules/eslint/curly.md
index b8c8dd1272c..1e4626892f6 100644
--- a/src/docs/guide/usage/linter/rules/eslint/curly.md
+++ b/src/docs/guide/usage/linter/rules/eslint/curly.md
@@ -15,7 +15,8 @@ const source = `https://github.com/oxc-project/oxc/blob/${ data }/crates/oxc_lin
### What it does
-This rule enforces the use of curly braces `{}` for all control statements (`if`, `else`, `for`, `while`, `do`, etc.).
+This rule enforces the use of curly braces `{}` for all control statements
+(`if`, `else`, `for`, `while`, `do`, `with`).
It ensures that all blocks are enclosed in curly braces to improve code clarity and maintainability.
### Why is this bad?
@@ -24,31 +25,232 @@ Omitting curly braces can reduce code readability and increase the likelihood of
It can also lead to bugs if additional statements are added later without properly enclosing them in braces.
Using curly braces consistently makes the code safer and easier to modify.
+### Options
+
+First option:
+
+- Type: `string`
+- Default: `"all"`
+- Possible values:
+ - `"all"`: require braces in all cases
+ - `"multi"`: require braces only for multi-statement blocks
+ - `"multi-line"`: require braces only for multi-line blocks
+ - `"multi-or-nest"`: require braces for multi-line blocks or when nested
+
+Second option:
+
+- Type: `string`
+- Default: `undefined`
+- Possible values:
+- `"consistent"`: require braces if any other branch in the `if-else` chain has braces
+
+Note : The second option can only be used in conjunction with the first option.
+
+Example configuration:
+
+```json
+{
+ "curly": ["error", "multi-or-nest", "consistent"]
+}
+```
+
### Examples
+#### `"all"` (default)
+
Examples of **incorrect** code for this rule:
```js
+/* curly: ["error", "all"] */
+
if (foo) foo++;
+while (bar) bar--;
+do foo(); while (bar);
+```
+
+Examples of **correct** code for this rule:
-for (let i = 0; i < 10; i++) doSomething(i);
+```js
+/* curly: ["error", "all"] */
+if (foo) foo++;
while (bar) bar--;
+do {
+ foo();
+} while (bar);
```
-Examples of **correct** code for this rule:
+#### `"multi"`
+
+Examples of **incorrect** code for this rule with the `"multi"` option:
+
+```js
+/* curly: ["error", "multi"] */
+
+if (foo) foo();
+else {
+ bar();
+ baz();
+}
+```
+
+Examples of **correct** code for this rule with the `"multi"` option:
```js
+/* curly: ["error", "multi"] */
+
+if (foo) foo();
+else bar();
+```
+
+#### `"multi-line"`
+
+Examples of **incorrect** code for this rule with the `"multi-line"` option:
+
+```js
+/* curly: ["error", "multi-line"] */
+
+if (foo) foo();
+else {
+ bar();
+}
+
+while (foo) {
+ foo();
+}
+```
+
+Examples of **correct** code for this rule with the `"multi-line"` option:
+
+```js
+/* curly: ["error", "multi-line"] */
+
+if (foo) foo();
+else bar();
+
+while (foo) foo();
+
+while (true) {
+ doSomething();
+ doSomethingElse();
+}
+```
+
+#### `"multi-or-nest"`
+
+Examples of **incorrect** code for this rule with the `"multi-or-nest"` option:
+
+```js
+/* curly: ["error", "multi-or-nest"] */
+
if (foo) {
- foo++;
+ if (bar) bar();
}
-for (let i = 0; i < 10; i++) {
- doSomething(i);
+while (foo) {
+ while (bar) bar();
}
+```
+
+Examples of **correct** code for this rule with the `"multi-or-nest"` option:
-while (bar) {
- bar--;
+```js
+/* curly: ["error", "multi-or-nest"] */
+
+if (foo) {
+ if (bar) bar();
+}
+
+while (foo) {
+ while (bar) bar();
+}
+```
+
+#### `{ "consistent": true }`
+
+When enabled, `consistent: true` enforces consistent use of braces within an `if-else` chain.
+If one branch of the chain uses braces, then all branches must use braces, even if not strictly required by the first option.
+
+Examples of **incorrect** code with `"multi"` and `consistent: true`:
+
+```js
+/* curly: ["error", "multi", "consistent"] */
+
+if (foo) {
+ bar();
+ baz();
+} else qux();
+
+if (foo) bar();
+else {
+ baz();
+ qux();
+}
+```
+
+Examples of **correct** code with `"multi"` and `consistent: true`:
+
+```js
+/* curly: ["error", "multi", "consistent"] */
+
+if (foo) {
+ bar();
+ baz();
+} else {
+ qux();
+}
+
+if (foo) {
+ bar();
+} else {
+ baz();
+ qux();
+}
+```
+
+Examples of **incorrect** code with `"multi-line"` and `consistent: true`:
+
+```js
+/* curly: ["error", "multi-line", "consistent"] */
+
+if (foo) {
+ bar();
+} else {
+ baz();
+}
+```
+
+Examples of **correct** code with `"multi-line"` and `consistent: true`:
+
+```js
+/* curly: ["error", "multi-line", "consistent"] */
+
+if (foo) {
+ bar();
+} else {
+ baz();
+}
+```
+
+Examples of **incorrect** code with `"multi-or-nest"` and `consistent: true`:
+
+```js
+/* curly: ["error", "multi-or-nest", "consistent"] */
+
+if (foo) {
+ if (bar) baz();
+} else qux();
+```
+
+Examples of **correct** code with `"multi-or-nest"` and `consistent: true`:
+
+```js
+/* curly: ["error", "multi-or-nest", "consistent"] */
+
+if (foo) {
+ if (bar) baz();
+} else {
+ qux();
}
```
diff --git a/src/docs/guide/usage/linter/rules/eslint/eqeqeq.md b/src/docs/guide/usage/linter/rules/eslint/eqeqeq.md
index caad5664a44..88540d6d6a3 100644
--- a/src/docs/guide/usage/linter/rules/eslint/eqeqeq.md
+++ b/src/docs/guide/usage/linter/rules/eslint/eqeqeq.md
@@ -15,70 +15,149 @@ const source = `https://github.com/oxc-project/oxc/blob/${ data }/crates/oxc_lin
### What it does
-Requires the use of the `===` and `!==` operators.
+Requires the use of the `===` and `!==` operators, disallowing the use of `==` and `!=`.
### Why is this bad?
-Using non-strict equality operators leads to hard to track bugs due to type coercion.
+Using non-strict equality operators leads to unexpected behavior due to type coercion, which can cause hard-to-find bugs.
+
+### Options
+
+First option:
+
+- Type: `string`
+- Default: `"always"`
+
+Possible values:
+
+- `"always"` - always require `===`/`!==`
+- `"smart"` - allow safe comparisons (`typeof`, literals, nullish)
+
+Second option (only used with `"always"`):
+
+- Type: `object`
+- Properties:
+ - `null`: `string` (default: `"always"`) - `"ignore"` allows `== null` and `!= null`.
+
+Possible values for `null`:
+
+- `"always"` - always require `=== null`/`!== null`
+- `"never"` - always require `== null`/`!= null`
+- `"ignore"` - allow both `== null`/`!= null` and `=== null`/`!== null`
+
+Example JSON configuration:
+
+```json
+{
+ "eqeqeq": ["error", "always", { "null": "ignore" }]
+}
+```
### Examples
+#### `"always"` (default)
+
Examples of **incorrect** code for this rule:
```js
-const a = [];
-const b = true;
-a == b;
-```
+/* eslint eqeqeq: "error" */
-The above will evaluate to `true`, but that is almost surely not what you want.
+if (x == 42) {}
+if ("" == text) {}
+if (obj.getStuff() != undefined) {}
+```
Examples of **correct** code for this rule:
```js
-const a = [];
-const b = true;
-a === b;
+/* eslint eqeqeq: "error" */
+
+if (x === 42) {}
+if ("" === text) {}
+if (obj.getStuff() !== undefined) {}
```
-The above will evaluate to `false` (an array is not boolean true).
+#### `"smart"`
-### Options
+Examples of **incorrect** code for this rule with the `"smart"` option:
-#### null
+```js
+/* eslint eqeqeq: ["error", "smart"] */
-```json
-"eslint/eqeqeq": ["error", "always", {"null": "ignore"}]
+if (x == 42) {}
+if ("" == text) {}
```
-Allow nullish comparison (`foo == null`). The alternative (`foo === null || foo === undefined`) is verbose and has no other benefit.
+Examples of **correct** code for this rule with the `"smart"` option:
-#### smart
+```js
+/* eslint eqeqeq: ["error", "smart"] */
-```json
-"eslint/eqeqeq": ["error", "smart"]
+if (typeof foo == "undefined") {}
+if (foo == null) {}
+if (foo != null) {}
+```
+
+#### `{"null": "ignore"}` (with `"always"` first option)
+
+Examples of **incorrect** code for this rule with the `{ "null": "ignore" }` option:
+
+```js
+/* eslint eqeqeq: ["error", "always", { "null": "ignore" }] */
+if (x == 42) {}
+if ("" == text) {}
```
-Allow `==` when comparing:
+Examples of **correct** code for this rule with the `{ "null": "ignore" }` option:
+
+```js
+/* eslint eqeqeq: ["error", "always", { "null": "ignore" }] */
+if (foo == null) {}
+if (foo != null) {}
+```
-- the result from `typeof`
-- literal values
-- nullish
+#### `{"null": "always"}` (default - with `"always"` first option)
-Examples of **incorrect** code for this option:
+Examples of **incorrect** code for this rule with the `{ "null": "always" }` option:
```js
-a == b
-[] == true
+/* eslint eqeqeq: ["error", "always", { "null": "always" }] */
+
+if (foo == null) {}
+if (foo != null) {}
```
-Examples of **correct** code for this option:
+Examples of **correct** code for this rule with the `{ "null": "always" }` option:
```js
-typeof foo == "undefined";
-"foo" == "bar";
-42 == 42;
-foo == null;
+/* eslint eqeqeq: ["error", "always", { "null": "always" }] */
+
+if (foo === null) {}
+if (foo !== null) {}
+```
+
+#### `{"null": "never"}` (with `"always"` first option)
+
+Examples of **incorrect** code for this rule with the `{ "null": "never" }` option:
+
+```js
+/* eslint eqeqeq: ["error", "always", { "null": "never" }] */
+
+if (x == 42) {}
+if ("" == text) {}
+if (foo === null) {}
+if (foo !== null) {}
+```
+
+Examples of **correct** code for this rule with the `{ "null": "never" }` option:
+
+```js
+/* eslint eqeqeq: ["error", "always", { "null": "never" }] */
+
+if (x === 42) {}
+if ("" === text) {}
+if (foo == null) {}
+if (foo != null) {}
```
## Configuration
diff --git a/src/docs/guide/usage/linter/rules/eslint/no-unused-expressions.md b/src/docs/guide/usage/linter/rules/eslint/no-unused-expressions.md
index 2b855bf57c0..2dd7b1c0d8f 100644
--- a/src/docs/guide/usage/linter/rules/eslint/no-unused-expressions.md
+++ b/src/docs/guide/usage/linter/rules/eslint/no-unused-expressions.md
@@ -5,9 +5,12 @@ import { data } from '../version.data.js';
const source = `https://github.com/oxc-project/oxc/blob/${ data }/crates/oxc_linter/src/rules/eslint/no_unused_expressions.rs`;
-# eslint/no-unused-expressions