eslint-plugin-unicorn 68.0.0 → 70.0.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.
Files changed (88) hide show
  1. package/package.json +3 -1
  2. package/readme.md +22 -0
  3. package/rules/ast/is-empty-object-expression.js +2 -2
  4. package/rules/comment-content.js +136 -18
  5. package/rules/consistent-boolean-name.js +665 -37
  6. package/rules/consistent-conditional-object-spread.js +9 -3
  7. package/rules/consistent-tuple-labels.js +49 -0
  8. package/rules/custom-error-definition.js +26 -7
  9. package/rules/expiring-todo-comments.js +23 -0
  10. package/rules/fix/{add-parenthesizes-to-return-or-throw-expression.js → add-parentheses-to-return-or-throw-expression.js} +1 -1
  11. package/rules/fix/index.js +1 -1
  12. package/rules/fix/switch-new-expression-to-call-expression.js +2 -2
  13. package/rules/index.js +22 -0
  14. package/rules/isolated-functions.js +156 -12
  15. package/rules/no-async-promise-finally.js +111 -0
  16. package/rules/no-chained-comparison.js +1 -1
  17. package/rules/no-collection-bracket-access.js +27 -4
  18. package/rules/no-computed-property-existence-check.js +6 -0
  19. package/rules/no-incorrect-template-string-interpolation.js +82 -30
  20. package/rules/no-instanceof-builtins.js +59 -13
  21. package/rules/no-invalid-well-known-symbol-methods.js +205 -0
  22. package/rules/no-late-current-target-access.js +9 -71
  23. package/rules/no-late-event-control.js +127 -0
  24. package/rules/no-manually-wrapped-comments.js +5 -1
  25. package/rules/no-negated-array-predicate.js +2 -2
  26. package/rules/no-negated-comparison.js +24 -61
  27. package/rules/no-negated-condition.js +2 -2
  28. package/rules/no-negation-in-equality-check.js +2 -2
  29. package/rules/no-non-function-verb-prefix.js +25 -2
  30. package/rules/no-nonstandard-builtin-properties.js +2 -0
  31. package/rules/no-object-methods-with-collections.js +4 -289
  32. package/rules/no-return-array-push.js +28 -6
  33. package/rules/no-top-level-side-effects.js +8 -1
  34. package/rules/no-typeof-undefined.js +2 -2
  35. package/rules/no-unnecessary-array-flat-map.js +307 -0
  36. package/rules/no-unnecessary-await.js +2 -2
  37. package/rules/no-unnecessary-fetch-options.js +624 -0
  38. package/rules/no-unnecessary-global-this.js +36 -1
  39. package/rules/no-unreadable-object-destructuring.js +15 -0
  40. package/rules/no-unsafe-promise-all-settled-values.js +865 -0
  41. package/rules/no-unsafe-string-replacement.js +31 -0
  42. package/rules/no-unused-array-method-return.js +11 -2
  43. package/rules/no-useless-boolean-cast.js +58 -1
  44. package/rules/no-useless-concat.js +27 -3
  45. package/rules/no-useless-else.js +48 -3
  46. package/rules/no-useless-iterator-to-array.js +194 -118
  47. package/rules/no-useless-spread.js +2 -2
  48. package/rules/prefer-abort-signal-any.js +1391 -0
  49. package/rules/prefer-abort-signal-timeout.js +395 -0
  50. package/rules/prefer-aggregate-error.js +478 -0
  51. package/rules/prefer-array-flat-map.js +6 -11
  52. package/rules/prefer-array-from-range.js +98 -0
  53. package/rules/prefer-at.js +5 -6
  54. package/rules/prefer-block-statement-over-iife.js +159 -0
  55. package/rules/prefer-code-point.js +58 -8
  56. package/rules/prefer-continue.js +21 -1
  57. package/rules/prefer-dom-node-replace-children.js +353 -0
  58. package/rules/prefer-early-return.js +3 -1
  59. package/rules/prefer-error-is-error.js +181 -0
  60. package/rules/prefer-group-by.js +576 -0
  61. package/rules/prefer-has-check.js +1 -4
  62. package/rules/prefer-hoisting-branch-code.js +9 -7
  63. package/rules/prefer-iterator-concat.js +21 -1
  64. package/rules/prefer-iterator-helpers.js +196 -0
  65. package/rules/prefer-minimal-ternary.js +15 -11
  66. package/rules/prefer-modern-dom-apis.js +1 -45
  67. package/rules/prefer-number-coercion.js +1 -1
  68. package/rules/prefer-object-iterable-methods.js +57 -14
  69. package/rules/prefer-observer-apis.js +498 -0
  70. package/rules/prefer-promise-try.js +238 -0
  71. package/rules/prefer-set-methods.js +337 -0
  72. package/rules/prefer-simplified-conditions.js +584 -0
  73. package/rules/prefer-spread.js +3 -0
  74. package/rules/prefer-string-raw.js +2 -2
  75. package/rules/prefer-toggle-attribute.js +293 -0
  76. package/rules/prefer-url-search-parameters.js +411 -0
  77. package/rules/shared/array-range.js +66 -0
  78. package/rules/shared/iterator-helpers.js +43 -1
  79. package/rules/shared/late-event-handler.js +82 -0
  80. package/rules/shared/name-replacements.js +6 -0
  81. package/rules/utils/builtin-collection-type.js +267 -0
  82. package/rules/utils/comparison.js +65 -0
  83. package/rules/utils/index.js +6 -0
  84. package/rules/utils/is-boolean.js +24 -7
  85. package/rules/utils/is-event.js +127 -0
  86. package/rules/utils/should-report-replace-children-receiver.js +210 -0
  87. package/rules/utils/track-branch-exits.js +8 -7
  88. package/rules/utils/type-helpers.js +166 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-unicorn",
3
- "version": "68.0.0",
3
+ "version": "70.0.0",
4
4
  "description": "More than 300 powerful ESLint rules",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -113,6 +113,8 @@
113
113
  "open-editor": "^6.0.0",
114
114
  "outdent": "^0.8.0",
115
115
  "pretty-ms": "^9.3.0",
116
+ "svelte": "^5.56.3",
117
+ "svelte-eslint-parser": "^1.8.0",
116
118
  "typescript": "^6.0.3",
117
119
  "vue-eslint-parser": "^10.4.1",
118
120
  "yaml": "^2.9.0"
package/readme.md CHANGED
@@ -110,6 +110,7 @@ export default defineConfig([
110
110
  | [consistent-json-file-read](docs/rules/consistent-json-file-read.md) | Enforce consistent JSON file reads before `JSON.parse()`. | ✅ | 🔧 | | |
111
111
  | [consistent-optional-chaining](docs/rules/consistent-optional-chaining.md) | Enforce consistent optional chaining for same-base member access. | ✅ ☑️ | | 💡 | |
112
112
  | [consistent-template-literal-escape](docs/rules/consistent-template-literal-escape.md) | Enforce consistent style for escaping `${` in template literals. | ✅ | 🔧 | | |
113
+ | [consistent-tuple-labels](docs/rules/consistent-tuple-labels.md) | Enforce consistent labels on tuple type elements. | ✅ | | | |
113
114
  | [custom-error-definition](docs/rules/custom-error-definition.md) | Enforce correct `Error` subclassing. | | 🔧 | | |
114
115
  | [default-export-style](docs/rules/default-export-style.md) | Enforce consistent default export declarations. | ✅ | 🔧 | 💡 | |
115
116
  | [dom-node-dataset](docs/rules/dom-node-dataset.md) | Enforce consistent style for DOM element dataset access. | ✅ ☑️ | 🔧 | | |
@@ -143,6 +144,7 @@ export default defineConfig([
143
144
  | [no-array-sort-for-min-max](docs/rules/no-array-sort-for-min-max.md) | Disallow sorting arrays to get the minimum or maximum value. | ✅ ☑️ | | 💡 | |
144
145
  | [no-array-splice](docs/rules/no-array-splice.md) | Prefer `Array#toSpliced()` over `Array#splice()`. | ✅ | | 💡 | |
145
146
  | [no-asterisk-prefix-in-documentation-comments](docs/rules/no-asterisk-prefix-in-documentation-comments.md) | Disallow asterisk prefixes in documentation comments. | | 🔧 | | |
147
+ | [no-async-promise-finally](docs/rules/no-async-promise-finally.md) | Disallow async functions as `Promise#finally()` callbacks. | ✅ ☑️ | | | |
146
148
  | [no-await-expression-member](docs/rules/no-await-expression-member.md) | Disallow member access from await expression. | ✅ | 🔧 | | |
147
149
  | [no-await-in-promise-methods](docs/rules/no-await-in-promise-methods.md) | Disallow using `await` in `Promise` method parameters. | ✅ ☑️ | | 💡 | |
148
150
  | [no-blob-to-file](docs/rules/no-blob-to-file.md) | Disallow unnecessary `Blob` to `File` conversion. | ✅ ☑️ | | 💡 | |
@@ -179,8 +181,10 @@ export default defineConfig([
179
181
  | [no-invalid-fetch-options](docs/rules/no-invalid-fetch-options.md) | Disallow invalid options in `fetch()` and `new Request()`. | ✅ ☑️ | | | |
180
182
  | [no-invalid-file-input-accept](docs/rules/no-invalid-file-input-accept.md) | Disallow invalid `accept` values on file inputs. | | 🔧 | | |
181
183
  | [no-invalid-remove-event-listener](docs/rules/no-invalid-remove-event-listener.md) | Prevent calling `EventTarget#removeEventListener()` with the result of an expression. | ✅ ☑️ | | | |
184
+ | [no-invalid-well-known-symbol-methods](docs/rules/no-invalid-well-known-symbol-methods.md) | Disallow invalid implementations of well-known symbol methods. | ✅ ☑️ | 🔧 | 💡 | |
182
185
  | [no-keyword-prefix](docs/rules/no-keyword-prefix.md) | Disallow identifiers starting with `new` or `class`. | | | | |
183
186
  | [no-late-current-target-access](docs/rules/no-late-current-target-access.md) | Disallow accessing `event.currentTarget` after the synchronous event dispatch has finished. | ✅ | | | |
187
+ | [no-late-event-control](docs/rules/no-late-event-control.md) | Disallow event-control method calls after the synchronous event dispatch has finished. | ✅ | | | |
184
188
  | [no-lonely-if](docs/rules/no-lonely-if.md) | Disallow `if` statements as the only statement in `if` blocks without `else`. | ✅ ☑️ | 🔧 | | |
185
189
  | [no-loop-iterable-mutation](docs/rules/no-loop-iterable-mutation.md) | Disallow mutating a loop iterable during iteration. | ✅ | | | |
186
190
  | [no-magic-array-flat-depth](docs/rules/no-magic-array-flat-depth.md) | Disallow a magic number as the `depth` argument in `Array#flat(…).` | ✅ ☑️ | | | |
@@ -217,9 +221,11 @@ export default defineConfig([
217
221
  | [no-uncalled-method](docs/rules/no-uncalled-method.md) | Disallow referencing methods without calling them. | ✅ | | | |
218
222
  | [no-undeclared-class-members](docs/rules/no-undeclared-class-members.md) | Require class members to be declared. | ✅ | | 💡 | |
219
223
  | [no-unnecessary-array-flat-depth](docs/rules/no-unnecessary-array-flat-depth.md) | Disallow using `1` as the `depth` argument of `Array#flat()`. | ✅ ☑️ | 🔧 | | |
224
+ | [no-unnecessary-array-flat-map](docs/rules/no-unnecessary-array-flat-map.md) | Disallow `Array#flatMap()` callbacks that only wrap a single item. | ✅ | 🔧 | 💡 | |
220
225
  | [no-unnecessary-array-splice-count](docs/rules/no-unnecessary-array-splice-count.md) | Disallow using `.length` or `Infinity` as the `deleteCount` or `skipCount` argument of `Array#{splice,toSpliced}()`. | ✅ ☑️ | 🔧 | | |
221
226
  | [no-unnecessary-await](docs/rules/no-unnecessary-await.md) | Disallow awaiting non-promise values. | ✅ ☑️ | 🔧 | | |
222
227
  | [no-unnecessary-boolean-comparison](docs/rules/no-unnecessary-boolean-comparison.md) | Disallow unnecessary comparisons against boolean literals. | ✅ | 🔧 | | |
228
+ | [no-unnecessary-fetch-options](docs/rules/no-unnecessary-fetch-options.md) | Disallow unnecessary options in `fetch()` and `new Request()`. | ✅ ☑️ | 🔧 | | |
223
229
  | [no-unnecessary-global-this](docs/rules/no-unnecessary-global-this.md) | Disallow unnecessary `globalThis` references. | ✅ ☑️ | 🔧 | | |
224
230
  | [no-unnecessary-nested-ternary](docs/rules/no-unnecessary-nested-ternary.md) | Disallow unnecessary nested ternary expressions. | ✅ ☑️ | 🔧 | | |
225
231
  | [no-unnecessary-polyfills](docs/rules/no-unnecessary-polyfills.md) | Enforce the use of built-in methods instead of unnecessary polyfills. | ✅ ☑️ | | | |
@@ -232,6 +238,7 @@ export default defineConfig([
232
238
  | [no-unreadable-object-destructuring](docs/rules/no-unreadable-object-destructuring.md) | Disallow unreadable object destructuring. | ✅ ☑️ | | | |
233
239
  | [no-unsafe-buffer-conversion](docs/rules/no-unsafe-buffer-conversion.md) | Prevent unsafe use of ArrayBuffer view `.buffer`. | ✅ ☑️ | | 💡 | |
234
240
  | [no-unsafe-dom-html](docs/rules/no-unsafe-dom-html.md) | Disallow unsafe DOM HTML APIs. | | | | |
241
+ | [no-unsafe-promise-all-settled-values](docs/rules/no-unsafe-promise-all-settled-values.md) | Disallow reading `.value` from `Promise.allSettled()` results without a fulfilled status guard. | ✅ ☑️ | | | |
235
242
  | [no-unsafe-property-key](docs/rules/no-unsafe-property-key.md) | Disallow unsafe values as property keys. | ✅ | | | |
236
243
  | [no-unsafe-string-replacement](docs/rules/no-unsafe-string-replacement.md) | Disallow non-literal replacement values in `String#replace()` and `String#replaceAll()`. | ✅ | | | |
237
244
  | [no-unused-array-method-return](docs/rules/no-unused-array-method-return.md) | Disallow ignoring the return value of selected array methods. | ✅ ☑️ | | | |
@@ -261,13 +268,17 @@ export default defineConfig([
261
268
  | [number-literal-case](docs/rules/number-literal-case.md) | Enforce proper case for numeric literals. | ✅ ☑️ | 🔧 | | |
262
269
  | [numeric-separators-style](docs/rules/numeric-separators-style.md) | Enforce the style of numeric separators by correctly grouping digits. | ✅ ☑️ | 🔧 | | |
263
270
  | [operator-assignment](docs/rules/operator-assignment.md) | Require assignment operator shorthand where possible. | ✅ | 🔧 | 💡 | |
271
+ | [prefer-abort-signal-any](docs/rules/prefer-abort-signal-any.md) | Prefer `AbortSignal.any()` over manually forwarding abort events between signals. | ✅ | | 💡 | |
272
+ | [prefer-abort-signal-timeout](docs/rules/prefer-abort-signal-timeout.md) | Prefer `AbortSignal.timeout()` over manually aborting an `AbortController` with `setTimeout()`. | ✅ | | 💡 | |
264
273
  | [prefer-add-event-listener](docs/rules/prefer-add-event-listener.md) | Prefer `.addEventListener()` and `.removeEventListener()` over `on`-functions. | ✅ ☑️ | 🔧 | | |
265
274
  | [prefer-add-event-listener-options](docs/rules/prefer-add-event-listener-options.md) | Prefer an options object over a boolean in `.addEventListener()`. | ✅ ☑️ | 🔧 | | |
275
+ | [prefer-aggregate-error](docs/rules/prefer-aggregate-error.md) | Prefer `AggregateError` when throwing collected errors. | ✅ ☑️ | 🔧 | | |
266
276
  | [prefer-array-find](docs/rules/prefer-array-find.md) | Prefer `.find(…)` and `.findLast(…)` over the first or last element from `.filter(…)`. | ✅ ☑️ | 🔧 | 💡 | |
267
277
  | [prefer-array-flat](docs/rules/prefer-array-flat.md) | Prefer `Array#flat()` over legacy techniques to flatten arrays. | ✅ ☑️ | 🔧 | | |
268
278
  | [prefer-array-flat-map](docs/rules/prefer-array-flat-map.md) | Prefer `.flatMap(…)` over `.map(…).flat()` and `.filter(…).flatMap(…)`. | ✅ ☑️ | 🔧 | 💡 | |
269
279
  | [prefer-array-from-async](docs/rules/prefer-array-from-async.md) | Prefer `Array.fromAsync()` over `for await…of` array accumulation. | ✅ | 🔧 | | |
270
280
  | [prefer-array-from-map](docs/rules/prefer-array-from-map.md) | Prefer using the `Array.from()` mapping function argument. | ✅ ☑️ | 🔧 | 💡 | |
281
+ | [prefer-array-from-range](docs/rules/prefer-array-from-range.md) | Prefer `Array.from({length}, …)` when creating range arrays. | ✅ ☑️ | 🔧 | | |
271
282
  | [prefer-array-index-of](docs/rules/prefer-array-index-of.md) | Prefer `Array#{indexOf,lastIndexOf}()` over `Array#{findIndex,findLastIndex}()` when looking for the index of an item. | ✅ ☑️ | 🔧 | 💡 | |
272
283
  | [prefer-array-iterable-methods](docs/rules/prefer-array-iterable-methods.md) | Prefer iterating an array directly or with `Array#keys()` over `Array#entries()` when the index or value is unused. | ✅ | 🔧 | | |
273
284
  | [prefer-array-last-methods](docs/rules/prefer-array-last-methods.md) | Prefer last-oriented array methods over `Array#reverse()` or `Array#toReversed()` followed by a method. | ✅ ☑️ | | 💡 | |
@@ -277,6 +288,7 @@ export default defineConfig([
277
288
  | [prefer-await](docs/rules/prefer-await.md) | Prefer `await` over promise chaining. | ✅ ☑️ | | | |
278
289
  | [prefer-bigint-literals](docs/rules/prefer-bigint-literals.md) | Prefer `BigInt` literals over the constructor. | ✅ ☑️ | 🔧 | 💡 | |
279
290
  | [prefer-blob-reading-methods](docs/rules/prefer-blob-reading-methods.md) | Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(…)` and `Blob#text()` over `FileReader#readAsText(…)`. | ✅ ☑️ | | | |
291
+ | [prefer-block-statement-over-iife](docs/rules/prefer-block-statement-over-iife.md) | Prefer block statements over IIFEs used only for scoping. | ✅ ☑️ | 🔧 | | |
280
292
  | [prefer-boolean-return](docs/rules/prefer-boolean-return.md) | Prefer directly returning boolean expressions over `if` statements. | ✅ ☑️ | 🔧 | | |
281
293
  | [prefer-class-fields](docs/rules/prefer-class-fields.md) | Prefer class field declarations over `this` assignments in constructors. | ✅ ☑️ | 🔧 | 💡 | |
282
294
  | [prefer-classlist-toggle](docs/rules/prefer-classlist-toggle.md) | Prefer using `Element#classList.toggle()` to toggle class names. | ✅ ☑️ | 🔧 | 💡 | |
@@ -289,15 +301,18 @@ export default defineConfig([
289
301
  | [prefer-dom-node-append](docs/rules/prefer-dom-node-append.md) | Prefer `Element#append()` over `Node#appendChild()`. | ✅ ☑️ | 🔧 | | |
290
302
  | [prefer-dom-node-html-methods](docs/rules/prefer-dom-node-html-methods.md) | Prefer `.getHTML()` and `.setHTML()` over `.innerHTML`. | | 🔧 | 💡 | |
291
303
  | [prefer-dom-node-remove](docs/rules/prefer-dom-node-remove.md) | Prefer `childNode.remove()` over `parentNode.removeChild(childNode)`. | ✅ ☑️ | 🔧 | 💡 | |
304
+ | [prefer-dom-node-replace-children](docs/rules/prefer-dom-node-replace-children.md) | Prefer `.replaceChildren()` when emptying DOM children. | ✅ ☑️ | 🔧 | | |
292
305
  | [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | ✅ ☑️ | | 💡 | |
293
306
  | [prefer-early-return](docs/rules/prefer-early-return.md) | Prefer early returns over full-function conditional wrapping. | ✅ ☑️ | 🔧 | 💡 | |
294
307
  | [prefer-else-if](docs/rules/prefer-else-if.md) | Prefer `else if` over adjacent `if` statements with related conditions. | ✅ | 🔧 | 💡 | |
308
+ | [prefer-error-is-error](docs/rules/prefer-error-is-error.md) | Prefer `Error.isError()` when checking for errors. | | 🔧 | | |
295
309
  | [prefer-event-target](docs/rules/prefer-event-target.md) | Prefer `EventTarget` over `EventEmitter`. | ✅ ☑️ | | | |
296
310
  | [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` when re-exporting. | ✅ | 🔧 | 💡 | |
297
311
  | [prefer-flat-math-min-max](docs/rules/prefer-flat-math-min-max.md) | Prefer flat `Math.min()` and `Math.max()` calls over nested calls. | ✅ ☑️ | 🔧 | | |
298
312
  | [prefer-get-or-insert-computed](docs/rules/prefer-get-or-insert-computed.md) | Prefer `.getOrInsertComputed()` when the default value has side effects. | ✅ | 🔧 | | |
299
313
  | [prefer-global-number-constants](docs/rules/prefer-global-number-constants.md) | Prefer global numeric constants over `Number` static properties. | ✅ ☑️ | 🔧 | | |
300
314
  | [prefer-global-this](docs/rules/prefer-global-this.md) | Prefer `globalThis` over `window`, `self`, and `global`. | ✅ ☑️ | 🔧 | | |
315
+ | [prefer-group-by](docs/rules/prefer-group-by.md) | Prefer `Object.groupBy()` or `Map.groupBy()` over reduce-based grouping. | ✅ | 🔧 | | |
301
316
  | [prefer-has-check](docs/rules/prefer-has-check.md) | Prefer `.has()` when checking existence. | ✅ ☑️ | 🔧 | | |
302
317
  | [prefer-hoisting-branch-code](docs/rules/prefer-hoisting-branch-code.md) | Prefer moving code shared by all branches of an `if` statement out of the branches. | ✅ | 🔧 | 💡 | |
303
318
  | [prefer-https](docs/rules/prefer-https.md) | Prefer HTTPS over HTTP. | ✅ | 🔧 | | |
@@ -307,6 +322,7 @@ export default defineConfig([
307
322
  | [prefer-includes-over-repeated-comparisons](docs/rules/prefer-includes-over-repeated-comparisons.md) | Prefer `.includes()` over repeated equality comparisons. | ✅ | | | |
308
323
  | [prefer-iterable-in-constructor](docs/rules/prefer-iterable-in-constructor.md) | Prefer passing iterables directly to constructors instead of filling empty collections. | ✅ ☑️ | 🔧 | | |
309
324
  | [prefer-iterator-concat](docs/rules/prefer-iterator-concat.md) | Prefer `Iterator.concat(…)` over temporary spread arrays. | | 🔧 | 💡 | |
325
+ | [prefer-iterator-helpers](docs/rules/prefer-iterator-helpers.md) | Prefer iterator helpers over temporary arrays from iterators. | ✅ ☑️ | | 💡 | |
310
326
  | [prefer-iterator-to-array](docs/rules/prefer-iterator-to-array.md) | Prefer `Iterator#toArray()` over temporary arrays from iterator spreads. | ✅ | 🔧 | 💡 | |
311
327
  | [prefer-iterator-to-array-at-end](docs/rules/prefer-iterator-to-array-at-end.md) | Prefer moving `.toArray()` to the end of iterator helper chains. | ✅ ☑️ | | 💡 | |
312
328
  | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over deprecated keyboard event properties. | ✅ ☑️ | 🔧 | 💡 | |
@@ -331,9 +347,11 @@ export default defineConfig([
331
347
  | [prefer-object-destructuring-defaults](docs/rules/prefer-object-destructuring-defaults.md) | Prefer object destructuring defaults over default object literals with spread. | ✅ | | 💡 | |
332
348
  | [prefer-object-from-entries](docs/rules/prefer-object-from-entries.md) | Prefer using `Object.fromEntries(…)` to transform a list of key-value pairs into an object. | ✅ ☑️ | 🔧 | | |
333
349
  | [prefer-object-iterable-methods](docs/rules/prefer-object-iterable-methods.md) | Prefer the most specific `Object` iterable method. | ✅ ☑️ | 🔧 | | |
350
+ | [prefer-observer-apis](docs/rules/prefer-observer-apis.md) | Prefer observer APIs over resize and scroll listeners with layout reads. | ✅ | | | |
334
351
  | [prefer-optional-catch-binding](docs/rules/prefer-optional-catch-binding.md) | Prefer omitting the `catch` binding parameter. | ✅ ☑️ | 🔧 | | |
335
352
  | [prefer-path2d](docs/rules/prefer-path2d.md) | Prefer `Path2D` for repeatedly drawn canvas paths. | ✅ ☑️ | | | |
336
353
  | [prefer-private-class-fields](docs/rules/prefer-private-class-fields.md) | Prefer private class fields over the underscore-prefix convention. | ✅ | 🔧 | | |
354
+ | [prefer-promise-try](docs/rules/prefer-promise-try.md) | Prefer `Promise.try()` over promise-wrapping boilerplate. | ✅ | 🔧 | | |
337
355
  | [prefer-promise-with-resolvers](docs/rules/prefer-promise-with-resolvers.md) | Prefer `Promise.withResolvers()` when extracting resolver functions from `new Promise()`. | ✅ ☑️ | 🔧 | | |
338
356
  | [prefer-prototype-methods](docs/rules/prefer-prototype-methods.md) | Prefer borrowing methods from the prototype instead of the instance. | ✅ ☑️ | 🔧 | | |
339
357
  | [prefer-query-selector](docs/rules/prefer-query-selector.md) | Prefer `.querySelector()` and `.querySelectorAll()` over older DOM query methods. | ✅ | 🔧 | | |
@@ -344,10 +362,12 @@ export default defineConfig([
344
362
  | [prefer-response-static-json](docs/rules/prefer-response-static-json.md) | Prefer `Response.json()` over `new Response(JSON.stringify())`. | ✅ ☑️ | 🔧 | | |
345
363
  | [prefer-scoped-selector](docs/rules/prefer-scoped-selector.md) | Prefer `:scope` when using element query selector methods. | ✅ | | 💡 | |
346
364
  | [prefer-set-has](docs/rules/prefer-set-has.md) | Prefer `Set#has()` over `Array#includes()` when checking for existence or non-existence. | ✅ ☑️ | 🔧 | 💡 | |
365
+ | [prefer-set-methods](docs/rules/prefer-set-methods.md) | Prefer `Set` methods for Set operations. | ✅ | 🔧 | 💡 | |
347
366
  | [prefer-set-size](docs/rules/prefer-set-size.md) | Prefer using `Set#size` instead of `Array#length`. | ✅ ☑️ | 🔧 | | |
348
367
  | [prefer-short-arrow-method](docs/rules/prefer-short-arrow-method.md) | Prefer arrow function properties over methods with a single return. | | 🔧 | | |
349
368
  | [prefer-simple-condition-first](docs/rules/prefer-simple-condition-first.md) | Prefer simple conditions first in logical expressions. | ✅ ☑️ | 🔧 | 💡 | |
350
369
  | [prefer-simple-sort-comparator](docs/rules/prefer-simple-sort-comparator.md) | Prefer a simple comparison function for `Array#sort()`. | ✅ ☑️ | | 💡 | |
370
+ | [prefer-simplified-conditions](docs/rules/prefer-simplified-conditions.md) | Prefer simplified conditions. | ✅ ☑️ | 🔧 | | |
351
371
  | [prefer-single-array-predicate](docs/rules/prefer-single-array-predicate.md) | Prefer a single `Array#some()` or `Array#every()` with a combined predicate. | ✅ ☑️ | | 💡 | |
352
372
  | [prefer-single-call](docs/rules/prefer-single-call.md) | Enforce combining multiple `Array#{push,unshift}()`, `Element#classList.{add,remove}()`, and `importScripts()` into one call. | ✅ ☑️ | 🔧 | 💡 | |
353
373
  | [prefer-single-object-destructuring](docs/rules/prefer-single-object-destructuring.md) | Prefer a single object destructuring declaration per local const source. | ✅ | 🔧 | | |
@@ -367,6 +387,7 @@ export default defineConfig([
367
387
  | [prefer-switch](docs/rules/prefer-switch.md) | Prefer `switch` over multiple `else-if`. | ✅ ☑️ | 🔧 | | |
368
388
  | [prefer-temporal](docs/rules/prefer-temporal.md) | Prefer `Temporal` over `Date`. | | 🔧 | 💡 | |
369
389
  | [prefer-ternary](docs/rules/prefer-ternary.md) | Prefer ternary expressions over simple `if` statements that return or assign values. | ✅ ☑️ | 🔧 | 💡 | |
390
+ | [prefer-toggle-attribute](docs/rules/prefer-toggle-attribute.md) | Prefer using `Element#toggleAttribute()` to toggle attributes. | ✅ ☑️ | 🔧 | 💡 | |
370
391
  | [prefer-top-level-await](docs/rules/prefer-top-level-await.md) | Prefer top-level await over top-level promises and async function calls. | ✅ ☑️ | | 💡 | |
371
392
  | [prefer-type-error](docs/rules/prefer-type-error.md) | Enforce throwing `TypeError` in type checking conditions. | ✅ ☑️ | 🔧 | | |
372
393
  | [prefer-type-literal-last](docs/rules/prefer-type-literal-last.md) | Require type literals to be last in union types. | ✅ | 🔧 | | |
@@ -375,6 +396,7 @@ export default defineConfig([
375
396
  | [prefer-unicode-code-point-escapes](docs/rules/prefer-unicode-code-point-escapes.md) | Prefer Unicode code point escapes over legacy escape sequences. | ✅ ☑️ | 🔧 | 💡 | |
376
397
  | [prefer-url-can-parse](docs/rules/prefer-url-can-parse.md) | Prefer `URL.canParse()` over constructing a `URL` in a try/catch for validation. | ✅ ☑️ | 🔧 | | |
377
398
  | [prefer-url-href](docs/rules/prefer-url-href.md) | Prefer `URL#href` over stringifying a `URL`. | ✅ ☑️ | 🔧 | | |
399
+ | [prefer-url-search-parameters](docs/rules/prefer-url-search-parameters.md) | Prefer `URLSearchParams` over manually splitting query strings. | ✅ ☑️ | | 💡 | |
378
400
  | [prefer-while-loop-condition](docs/rules/prefer-while-loop-condition.md) | Prefer putting the condition in the while statement. | ✅ ☑️ | 🔧 | | |
379
401
  | [relative-url-style](docs/rules/relative-url-style.md) | Enforce consistent relative URL style. | ✅ ☑️ | 🔧 | 💡 | |
380
402
  | [require-array-join-separator](docs/rules/require-array-join-separator.md) | Enforce using the separator argument with `Array#join()`. | ✅ ☑️ | 🔧 | | |
@@ -1,5 +1,5 @@
1
- const isEmptyArrayExpression = node =>
1
+ const isEmptyObjectExpression = node =>
2
2
  node.type === 'ObjectExpression'
3
3
  && node.properties.length === 0;
4
4
 
5
- export default isEmptyArrayExpression;
5
+ export default isEmptyObjectExpression;
@@ -285,8 +285,11 @@ const listMarkerPatternSource = String.raw`(?:[*+\-]|\d+\.)`;
285
285
  const optionalListMarkerPrefixPatternSource = String.raw`${listMarkerPatternSource}?\s*`;
286
286
  const optionalLabelPrefixPatternSource = String.raw`(?:${identifierPatternSource}:\s*)?`;
287
287
  const bracketPropertyPatternSource = String.raw`\[[^\]]+\]`;
288
- const optionalAssignmentPrefixPatternSource = String.raw`(?:${identifierPatternSource}(?::|\s*=)\s*)?`;
289
288
  const memberCallPropertyPatternSource = String.raw`(?:(?:\?\.|\.)\s*${identifierPatternSource}|\??\.\s*${bracketPropertyPatternSource})`;
289
+ const memberAssignmentTargetPatternSource = String.raw`${identifierPatternSource}(?:\s*${memberCallPropertyPatternSource}|\s*${bracketPropertyPatternSource})+`;
290
+ const optionalDeclarationPrefixPatternSource = String.raw`(?:(?:const|let|var)\s+)?`;
291
+ const assignmentTargetPatternSource = `(?:${identifierPatternSource}|${memberAssignmentTargetPatternSource})`;
292
+ const optionalAssignmentPrefixPatternSource = String.raw`(?:(?:${identifierPatternSource}:|${optionalDeclarationPrefixPatternSource}${assignmentTargetPatternSource}\s*=)\s*)?`;
290
293
  const markdownLinkDestinationStartPatternSource = String.raw`(?:[A-Za-z][\d+\-.A-Za-z]*:\/\/|www\.|[\u{2D}0-9A-Za-z]+\.|[\w\-.]+\/|\/|#)`;
291
294
  const callArgumentsPatternSource = String.raw`\((?!\s*${markdownLinkDestinationStartPatternSource})[^\)]*\)`;
292
295
  const bracketMemberAccessLinePattern = new RegExp([
@@ -325,6 +328,14 @@ const memberCallLinePattern = new RegExp([
325
328
  String.raw`\s*${memberCallPropertyPatternSource}\s*(?:\?\.\s*)?\(`,
326
329
  String.raw`|${bracketPropertyPatternSource}\()`,
327
330
  ].join(''), 'v');
331
+ const bareCallLinePattern = new RegExp([
332
+ `^${optionalListMarkerPrefixPatternSource}`,
333
+ String.raw`(?:\(\s*)?`,
334
+ optionalAssignmentPrefixPatternSource,
335
+ String.raw`(?:new\s+)?`,
336
+ codeIdentifierPatternSource,
337
+ String.raw`(?:\(|\s+\(\s*$)`,
338
+ ].join(''), 'v');
328
339
  const shellPromptLinePattern = new RegExp(String.raw`^${optionalListMarkerPrefixPatternSource}\$\s+\S+`, 'v');
329
340
  const secondaryShellPromptLinePattern = new RegExp(String.raw`^${optionalListMarkerPrefixPatternSource}>\s*(?:bun|curl|deno|docker|git|node(?:js)?|npm|npx|pnpm|yarn)\b`, 'v');
330
341
  const listMarkerPattern = new RegExp(String.raw`^${listMarkerPatternSource}\s*`, 'v');
@@ -336,6 +347,55 @@ const packageSpecifierTerminatorCharacters = '"\'`()[]{}<>,';
336
347
  const domainLeadingPunctuation = '([{<';
337
348
  const domainTrailingPunctuation = '.,;:!?)]}>';
338
349
  const maskCharacter = '\uFFFF';
350
+ const openBrackets = '([{';
351
+ const closeBrackets = ')]}';
352
+ const quoteCharacters = '"\'`';
353
+
354
+ // Count the net change in unbalanced brackets across a line, ignoring brackets inside string literals so they do not miscount. Operates on raw text so it is independent of mask ordering.
355
+ function getBracketDepthDelta(text) {
356
+ let delta = 0;
357
+ let quote;
358
+
359
+ for (let index = 0; index < text.length; index++) {
360
+ const character = text[index];
361
+
362
+ if (quote) {
363
+ if (character === '\\') {
364
+ index++;
365
+ continue;
366
+ }
367
+
368
+ if (character === quote) {
369
+ quote = undefined;
370
+ }
371
+
372
+ continue;
373
+ }
374
+
375
+ if (character === '/' && text[index + 1] === '/') {
376
+ break;
377
+ }
378
+
379
+ if (character === '/' && text[index + 1] === '*') {
380
+ const endIndex = text.indexOf('*/', index + 2);
381
+ index = endIndex === -1 ? text.length : endIndex + 1;
382
+ continue;
383
+ }
384
+
385
+ if (quoteCharacters.includes(character)) {
386
+ quote = character;
387
+ continue;
388
+ }
389
+
390
+ if (openBrackets.includes(character)) {
391
+ delta++;
392
+ } else if (closeBrackets.includes(character)) {
393
+ delta--;
394
+ }
395
+ }
396
+
397
+ return delta;
398
+ }
339
399
 
340
400
  function isIdentifierLikeCharacter(character) {
341
401
  return Boolean(character) && /[\p{Letter}\p{Number}_]/v.test(character);
@@ -716,14 +776,48 @@ function isIgnoredCommentLine(line) {
716
776
  || memberCallLinePattern.test(removeMarkdownInlineLinks(line));
717
777
  }
718
778
 
779
+ function getBracketContinuationOpeningDepth(line) {
780
+ line = cleanCommentLine(line);
781
+ line = removeMarkdownInlineLinks(line);
782
+
783
+ if (!bareCallLinePattern.test(line) && !memberCallLinePattern.test(line)) {
784
+ return 0;
785
+ }
786
+
787
+ return Math.max(0, getBracketDepthDelta(line));
788
+ }
789
+
790
+ // Advance the running bracket depth for one line. A line counts as code if depth is already open (a continuation line) or it looks like code on its own; otherwise depth resets to zero.
791
+ function getNextBracketDepth(depth, line) {
792
+ if (depth > 0) {
793
+ return Math.max(0, depth + getBracketDepthDelta(line));
794
+ }
795
+
796
+ return getBracketContinuationOpeningDepth(line);
797
+ }
798
+
719
799
  function maskIgnoredLines(characters, text) {
720
800
  let start = 0;
801
+ let depth = 0;
721
802
 
722
803
  while (start < text.length) {
723
804
  const end = getLineEndIndex(text, start);
805
+ const line = text.slice(start, end);
806
+
807
+ if (characters.slice(start, end).includes(maskCharacter)) {
808
+ depth = 0;
809
+ start = end + 1;
810
+ continue;
811
+ }
724
812
 
725
- if (isIgnoredCommentLine(text.slice(start, end))) {
813
+ const openingDepth = getBracketContinuationOpeningDepth(line);
814
+
815
+ // A line is masked if it looks like code on its own, or if it is a continuation line inside brackets opened by an earlier code-like line.
816
+ if (depth > 0 || isIgnoredCommentLine(line) || openingDepth > 0) {
726
817
  maskRange(characters, start, end);
818
+ depth = depth > 0
819
+ ? Math.max(0, depth + getBracketDepthDelta(line))
820
+ : openingDepth;
727
821
  }
728
822
 
729
823
  start = end + 1;
@@ -980,29 +1074,53 @@ const create = context => {
980
1074
  const {sourceCode} = context;
981
1075
  const comments = getRuleComments(context);
982
1076
 
1077
+ // Carry bracket depth across adjacent line comments so that a commented-out multi-line code construct spanning several `//` comments is not rewritten on its continuation lines.
1078
+ let continuationDepth = 0;
1079
+ let previousLineCommentRangeEnd;
1080
+
983
1081
  for (const comment of comments) {
984
1082
  if (comment.type === 'Shebang' || isEslintDirective(context, comment)) {
1083
+ continuationDepth = 0;
1084
+ previousLineCommentRangeEnd = undefined;
985
1085
  continue;
986
1086
  }
987
1087
 
988
- const problem = getReplacementProblem(comment, sourceCode, replacements, checkUniformCase);
989
- if (!problem) {
990
- continue;
1088
+ const range = sourceCode.getRange(comment);
1089
+ const isAdjacentLineComment = comment.type === 'Line'
1090
+ && previousLineCommentRangeEnd !== undefined
1091
+ && /^[^\S\n]*\n[^\S\n]*$/v.test(sourceCode.text.slice(previousLineCommentRangeEnd, range[0]));
1092
+
1093
+ if (!isAdjacentLineComment) {
1094
+ continuationDepth = 0;
991
1095
  }
992
1096
 
993
- yield {
994
- node,
995
- loc: {
996
- start: sourceCode.getLocFromIndex(problem.replacementRange[0]),
997
- end: sourceCode.getLocFromIndex(problem.replacementRange[1]),
998
- },
999
- messageId: MESSAGE_ID,
1000
- data: {
1001
- value: problem.value,
1002
- replacement: problem.replacement,
1003
- },
1004
- fix: fixer => fixer.replaceTextRange(problem.replacementRange, problem.replacement),
1005
- };
1097
+ if (continuationDepth <= 0) {
1098
+ const problem = getReplacementProblem(comment, sourceCode, replacements, checkUniformCase);
1099
+ if (problem) {
1100
+ yield {
1101
+ node,
1102
+ loc: {
1103
+ start: sourceCode.getLocFromIndex(problem.replacementRange[0]),
1104
+ end: sourceCode.getLocFromIndex(problem.replacementRange[1]),
1105
+ },
1106
+ messageId: MESSAGE_ID,
1107
+ data: {
1108
+ value: problem.value,
1109
+ replacement: problem.replacement,
1110
+ },
1111
+ fix: fixer => fixer.replaceTextRange(problem.replacementRange, problem.replacement),
1112
+ };
1113
+ }
1114
+ }
1115
+
1116
+ // Update continuation state for the next adjacent line comment.
1117
+ if (comment.type === 'Line') {
1118
+ continuationDepth = getNextBracketDepth(continuationDepth, comment.value);
1119
+ previousLineCommentRangeEnd = range[1];
1120
+ } else {
1121
+ continuationDepth = 0;
1122
+ previousLineCommentRangeEnd = undefined;
1123
+ }
1006
1124
  }
1007
1125
  });
1008
1126
  };