@prairielearn/eslint-config 3.1.2 → 3.1.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @prairielearn/eslint-config
2
2
 
3
+ ## 3.1.4
4
+
5
+ ### Patch Changes
6
+
7
+ - e2ed7cd: Apply additional eslint unicorn rules
8
+
9
+ ## 3.1.3
10
+
11
+ ### Patch Changes
12
+
13
+ - b98ca1c: Update Unicorn overrides for v73 and address selected correctness-focused lint findings.
14
+
3
15
  ## 3.1.2
4
16
 
5
17
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"unicorn.d.ts","sourceRoot":"","sources":["../../src/configs/unicorn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGzD;;GAEG;AACH,wBAAgB,aAAa,IAAI,QAAQ,CAAC,UAAU,CAAC,WAAW,CA8E/D","sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport eslintPluginUnicorn from 'eslint-plugin-unicorn';\n\n/**\n * Unicorn plugin rules with PrairieLearn-specific overrides.\n */\nexport function unicornConfig(): TSESLint.FlatConfig.ConfigArray {\n return [\n {\n plugins: {\n unicorn: eslintPluginUnicorn,\n },\n\n rules: {\n ...eslintPluginUnicorn.configs.recommended.rules,\n\n // These rules don't align with our own style guidelines\n 'unicorn/filename-case': 'off', // We don't enforce specific styles for filenames\n 'unicorn/no-anonymous-default-export': 'off', // We use this for all of our pages\n 'unicorn/no-array-callback-reference': 'off',\n 'unicorn/no-array-method-this-argument': 'off',\n 'unicorn/no-array-reduce': 'off', // Sometimes, an array reduce is more readable\n 'unicorn/no-array-reverse': 'off', // `Array.prototype.toReversed` is not yet supported by our TypeScript config\n 'unicorn/no-array-sort': 'off', // Disabling for the time being to avoid unnecessary diffs\n 'unicorn/no-hex-escape': 'off',\n 'unicorn/no-lonely-if': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252261293\n 'unicorn/no-null': 'off',\n 'unicorn/no-useless-undefined': 'off', // Explicit undefined is more readable than implicit undefined\n 'unicorn/prefer-code-point': 'off',\n 'unicorn/prefer-dom-node-dataset': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2261095992\n 'unicorn/prefer-export-from': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252265000\n 'unicorn/prefer-string-raw': 'off', // We don't use `String.raw` in our codebase\n 'unicorn/prefer-ternary': 'off', // if/else can be more readable than a ternary\n 'unicorn/prefer-top-level-await': 'off', // we use this on a lot of pages\n 'unicorn/prefer-type-error': 'off',\n 'unicorn/prevent-abbreviations': 'off',\n\n // These rules have many violations. Decisions about enabling the rules have been deferred.\n 'unicorn/catch-error-name': 'off', // 200+ violations\n 'unicorn/no-array-for-each': 'off', // 300+ violations\n 'unicorn/no-await-expression-member': 'off', // 400+ violations\n 'unicorn/no-negated-condition': 'off', // 150+ violations\n 'unicorn/prefer-global-this': 'off', // 150+ violations\n 'unicorn/prefer-node-protocol': 'off', // 100+ violations\n 'unicorn/switch-case-braces': 'off', // 200+ violations\n\n // TODO: investigate, < 100 violations\n 'unicorn/consistent-assert': 'off',\n 'unicorn/consistent-function-scoping': 'off',\n 'unicorn/escape-case': 'off',\n 'unicorn/import-style': 'off',\n 'unicorn/numeric-separators-style': 'off',\n 'unicorn/prefer-query-selector': 'off',\n 'unicorn/prefer-spread': 'off',\n 'unicorn/prefer-switch': 'off',\n 'unicorn/text-encoding-identifier-case': 'off',\n\n // TODO: investigated and manual fixes are required\n 'unicorn/no-object-as-default-parameter': 'off',\n 'unicorn/prefer-add-event-listener': 'off',\n 'unicorn/prefer-dom-node-text-content': 'off',\n 'unicorn/prefer-event-target': 'off',\n\n // False positives\n 'unicorn/error-message': 'off',\n 'unicorn/prefer-array-find': ['error', { checkFromLast: false }], // findLast is unavailable in our target lib\n 'unicorn/prefer-at': 'off', // https://github.com/microsoft/TypeScript/issues/47660#issuecomment-3146907649\n 'unicorn/throw-new-error': 'off',\n\n // Duplicated from other lint rules\n 'unicorn/no-static-only-class': 'off',\n 'unicorn/no-this-assignment': 'off',\n 'unicorn/prefer-module': 'off',\n\n // https://github.com/PrairieLearn/PrairieLearn/pull/12545/files#r2252069292\n 'unicorn/no-for-loop': 'off',\n\n // Conflicts with prettier\n 'unicorn/no-nested-ternary': 'off',\n 'unicorn/number-literal-case': 'off',\n 'unicorn/template-indent': 'off',\n },\n },\n ];\n}\n"]}
1
+ {"version":3,"file":"unicorn.d.ts","sourceRoot":"","sources":["../../src/configs/unicorn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGzD;;GAEG;AACH,wBAAgB,aAAa,IAAI,QAAQ,CAAC,UAAU,CAAC,WAAW,CA4J/D","sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport eslintPluginUnicorn from 'eslint-plugin-unicorn';\n\n/**\n * Unicorn plugin rules with PrairieLearn-specific overrides.\n */\nexport function unicornConfig(): TSESLint.FlatConfig.ConfigArray {\n return [\n {\n plugins: {\n unicorn: eslintPluginUnicorn,\n },\n\n rules: {\n ...eslintPluginUnicorn.configs.recommended.rules,\n\n // These rules don't align with our own style guidelines\n 'unicorn/filename-case': 'off', // We don't enforce specific styles for filenames\n 'unicorn/no-anonymous-default-export': 'off', // We use this for all of our pages\n 'unicorn/no-array-callback-reference': 'off',\n 'unicorn/no-array-method-this-argument': 'off',\n 'unicorn/no-array-reduce': 'off', // Sometimes, an array reduce is more readable\n 'unicorn/no-array-reverse': 'off', // `Array.prototype.toReversed` is not yet supported by our TypeScript config\n 'unicorn/no-array-sort': 'off', // Disabling for the time being to avoid unnecessary diffs\n 'unicorn/prefer-unicode-code-point-escapes': 'off',\n 'unicorn/no-lonely-if': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252261293\n 'unicorn/no-null': 'off',\n 'unicorn/no-useless-undefined': 'off', // Explicit undefined is more readable than implicit undefined\n 'unicorn/prefer-code-point': 'off',\n 'unicorn/dom-node-dataset': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2261095992\n 'unicorn/prefer-export-from': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252265000\n 'unicorn/prefer-string-raw': 'off', // We don't use `String.raw` in our codebase\n 'unicorn/prefer-ternary': 'off', // if/else can be more readable than a ternary\n 'unicorn/prefer-top-level-await': 'off', // we use this on a lot of pages\n 'unicorn/prefer-type-error': 'off',\n 'unicorn/name-replacements': 'off',\n\n // These rules enforce conventions that we don't want to adopt.\n 'unicorn/consistent-boolean-name': 'off', // Boolean prefixes are too restrictive\n 'unicorn/consistent-class-member-order': 'off', // Existing class organization is readable\n 'unicorn/consistent-compound-words': 'off', // Would create unnecessary API naming churn\n 'unicorn/consistent-conditional-object-spread': 'off', // Both forms are readable\n 'unicorn/max-nested-calls': 'off', // An arbitrary nesting limit does not measure readability\n 'unicorn/no-break-in-nested-loop': 'off', // Extracting loops into functions is often less clear\n 'unicorn/no-computed-property-existence-check': 'off', // Dynamic property checks are valid\n 'unicorn/no-constant-zero-expression': 'off', // Explicit zero terms can document formulas and fixtures\n 'unicorn/no-declarations-before-early-exit': 'off', // Declaration placement is contextual\n 'unicorn/no-global-object-property-assignment': 'off', // Browser entry points intentionally expose globals\n 'unicorn/no-non-function-verb-prefix': 'off', // Verb prefixes are valid for values such as URLs and modals\n 'unicorn/no-this-outside-of-class': 'off', // We use function receivers and legacy callback APIs\n 'unicorn/no-top-level-assignment-in-function': 'off', // Modules intentionally maintain process state\n 'unicorn/no-top-level-side-effects': 'off', // Entry points and registration modules require side effects\n 'unicorn/no-unreadable-array-destructuring': 'off', // Property swaps are a readable destructuring use\n 'unicorn/no-unreadable-for-of-expression': 'off', // Temporary iterable variables are not always clearer\n 'unicorn/no-useless-else': 'off', // An explicit else can make control flow clearer\n 'unicorn/prefer-await': 'off', // Promise chains are sometimes clearer than try/catch\n 'unicorn/prefer-block-statement-over-iife': 'off', // IIFEs isolate legacy browser scripts\n 'unicorn/prefer-boolean-return': 'off', // Explicit branches can be clearer\n 'unicorn/prefer-continue': 'off', // Loop structure is contextual\n 'unicorn/prefer-early-return': 'off', // Guard clauses are not always clearer\n 'unicorn/prefer-else-if': 'off', // Separate conditions can better communicate intent\n 'unicorn/prefer-https': 'off', // HTTP is valid for local and test URLs\n 'unicorn/prefer-location-assign': 'off', // Assigning location.href is an established browser idiom\n 'unicorn/prefer-logical-operator-over-ternary': 'off', // Ternaries can make fallback behavior explicit\n 'unicorn/prefer-math-constants': 'off', // Approximate values are intentional in fixtures and examples\n 'unicorn/prefer-minimal-ternary': 'off', // The transformed expression is not always easier to read\n 'unicorn/prefer-number-coercion': 'off', // Number() differs from parseInt() and parseFloat()\n 'unicorn/prefer-number-is-safe-integer': 'off', // This changes the accepted numeric range\n 'unicorn/prefer-private-class-fields': 'off', // Underscore fields can be part of an external contract\n 'unicorn/prefer-queue-microtask': 'off', // queueMicrotask() and process.nextTick() have different ordering\n 'unicorn/prefer-split-limit': 'off', // Adding a limit is not clearer for most destructuring\n 'unicorn/prefer-then-catch': 'off', // Both Promise rejection styles are valid\n 'unicorn/single-line-block-comment-style': 'off', // Existing license and generated comments use both styles\n\n // These rules have many violations. Decisions about enabling the rules have been deferred.\n 'unicorn/catch-error-name': 'off', // 200+ violations\n 'unicorn/no-for-each': 'off', // 300+ violations\n 'unicorn/no-await-expression-member': 'off', // 400+ violations\n 'unicorn/no-negated-condition': 'off', // 150+ violations\n 'unicorn/prefer-global-this': 'off', // 150+ violations\n 'unicorn/prefer-node-protocol': 'off', // 100+ violations\n 'unicorn/prefer-simple-condition-first': 'off', // 100+ violations\n 'unicorn/switch-case-braces': 'off', // 200+ violations\n\n // These rules look valuable, but enabling them requires a focused manual migration.\n 'unicorn/better-dom-traversing': 'off', // 24 violations\n 'unicorn/isolated-functions': 'off', // 41 violations, including Playwright evaluation callbacks\n 'unicorn/no-array-sort-for-min-max': 'off', // 1 violation; empty-array behavior needs care\n 'unicorn/no-duplicate-loops': 'off', // 1 violation; requires an allocation/readability tradeoff\n 'unicorn/no-return-array-push': 'off', // 17 violations\n 'unicorn/no-undeclared-class-members': 'off', // 71 violations in a legacy browser class\n 'unicorn/no-unsafe-string-replacement': 'off', // 15 violations; replacements need semantic review\n 'unicorn/prefer-observer-apis': 'off', // 1 violation; requires an interaction behavior change\n 'unicorn/prefer-scoped-selector': 'off', // 12 violations\n 'unicorn/require-array-sort-compare': 'off', // 54 violations; string sorts need individual review\n\n // These rules can be considered in focused autofix or cleanup PRs.\n 'unicorn/logical-assignment-operators': 'off', // 40 violations\n 'unicorn/no-negated-array-predicate': 'off', // 26 violations\n 'unicorn/no-unnecessary-boolean-comparison': 'off', // 13 violations\n 'unicorn/no-useless-coercion': 'off', // 43 violations\n 'unicorn/no-useless-template-literals': 'off', // 32 violations\n 'unicorn/operator-assignment': 'off', // 10 violations\n 'unicorn/prefer-array-from-map': 'off', // 23 violations\n 'unicorn/prefer-direct-iteration': 'off', // 15 violations\n 'unicorn/prefer-includes-over-repeated-comparisons': 'off', // 10 violations\n 'unicorn/prefer-object-iterable-methods': 'off', // 19 violations\n 'unicorn/prefer-string-repeat': 'off', // 16 violations\n\n // These rules require confirming browser and runtime support before enabling them.\n 'unicorn/prefer-array-from-async': 'off', // 5 violations\n 'unicorn/prefer-dom-node-html-methods': 'off', // 2 violations\n 'unicorn/prefer-dom-node-replace-children': 'off', // 3 violations\n 'unicorn/prefer-iterator-helpers': 'off', // 3 violations\n 'unicorn/prefer-iterator-to-array': 'off', // 34 violations\n 'unicorn/prefer-iterator-to-array-at-end': 'off', // 5 violations\n 'unicorn/prefer-promise-with-resolvers': 'off', // 5 violations\n 'unicorn/prefer-set-methods': 'off', // 5 violations\n 'unicorn/prefer-toggle-attribute': 'off', // 2 violations\n\n // False positives for intentional source text or module structure.\n 'unicorn/no-exports-in-scripts': 'off', // The server entry point is an ES module\n 'unicorn/no-incorrect-template-string-interpolation': 'off', // We test and document literal ${...} text\n\n // TODO: investigate, < 100 violations\n 'unicorn/consistent-assert': 'off',\n 'unicorn/consistent-function-scoping': 'off',\n 'unicorn/escape-case': 'off',\n 'unicorn/import-style': 'off',\n 'unicorn/numeric-separators-style': 'off',\n 'unicorn/prefer-query-selector': 'off',\n 'unicorn/prefer-spread': 'off',\n 'unicorn/prefer-switch': 'off',\n 'unicorn/text-encoding-identifier-case': 'off',\n\n // TODO: investigated and manual fixes are required\n 'unicorn/no-object-as-default-parameter': 'off',\n 'unicorn/prefer-add-event-listener': 'off',\n 'unicorn/prefer-dom-node-text-content': 'off',\n 'unicorn/prefer-event-target': 'off',\n\n // False positives\n 'unicorn/error-message': 'off',\n 'unicorn/prefer-array-find': ['error', { checkFromLast: false }], // findLast is unavailable in our target lib\n 'unicorn/prefer-at': 'off', // https://github.com/microsoft/TypeScript/issues/47660#issuecomment-3146907649\n 'unicorn/throw-new-error': 'off',\n\n // Duplicated from other lint rules\n 'unicorn/no-static-only-class': 'off',\n 'unicorn/no-this-assignment': 'off',\n 'unicorn/prefer-module': 'off',\n\n // https://github.com/PrairieLearn/PrairieLearn/pull/12545/files#r2252069292\n 'unicorn/no-for-loop': 'off',\n\n // Conflicts with prettier\n 'unicorn/no-nested-ternary': 'off',\n 'unicorn/number-literal-case': 'off',\n 'unicorn/template-indent': 'off',\n },\n },\n ];\n}\n"]}
@@ -18,26 +18,99 @@ export function unicornConfig() {
18
18
  'unicorn/no-array-reduce': 'off', // Sometimes, an array reduce is more readable
19
19
  'unicorn/no-array-reverse': 'off', // `Array.prototype.toReversed` is not yet supported by our TypeScript config
20
20
  'unicorn/no-array-sort': 'off', // Disabling for the time being to avoid unnecessary diffs
21
- 'unicorn/no-hex-escape': 'off',
21
+ 'unicorn/prefer-unicode-code-point-escapes': 'off',
22
22
  'unicorn/no-lonely-if': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252261293
23
23
  'unicorn/no-null': 'off',
24
24
  'unicorn/no-useless-undefined': 'off', // Explicit undefined is more readable than implicit undefined
25
25
  'unicorn/prefer-code-point': 'off',
26
- 'unicorn/prefer-dom-node-dataset': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2261095992
26
+ 'unicorn/dom-node-dataset': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2261095992
27
27
  'unicorn/prefer-export-from': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252265000
28
28
  'unicorn/prefer-string-raw': 'off', // We don't use `String.raw` in our codebase
29
29
  'unicorn/prefer-ternary': 'off', // if/else can be more readable than a ternary
30
30
  'unicorn/prefer-top-level-await': 'off', // we use this on a lot of pages
31
31
  'unicorn/prefer-type-error': 'off',
32
- 'unicorn/prevent-abbreviations': 'off',
32
+ 'unicorn/name-replacements': 'off',
33
+ // These rules enforce conventions that we don't want to adopt.
34
+ 'unicorn/consistent-boolean-name': 'off', // Boolean prefixes are too restrictive
35
+ 'unicorn/consistent-class-member-order': 'off', // Existing class organization is readable
36
+ 'unicorn/consistent-compound-words': 'off', // Would create unnecessary API naming churn
37
+ 'unicorn/consistent-conditional-object-spread': 'off', // Both forms are readable
38
+ 'unicorn/max-nested-calls': 'off', // An arbitrary nesting limit does not measure readability
39
+ 'unicorn/no-break-in-nested-loop': 'off', // Extracting loops into functions is often less clear
40
+ 'unicorn/no-computed-property-existence-check': 'off', // Dynamic property checks are valid
41
+ 'unicorn/no-constant-zero-expression': 'off', // Explicit zero terms can document formulas and fixtures
42
+ 'unicorn/no-declarations-before-early-exit': 'off', // Declaration placement is contextual
43
+ 'unicorn/no-global-object-property-assignment': 'off', // Browser entry points intentionally expose globals
44
+ 'unicorn/no-non-function-verb-prefix': 'off', // Verb prefixes are valid for values such as URLs and modals
45
+ 'unicorn/no-this-outside-of-class': 'off', // We use function receivers and legacy callback APIs
46
+ 'unicorn/no-top-level-assignment-in-function': 'off', // Modules intentionally maintain process state
47
+ 'unicorn/no-top-level-side-effects': 'off', // Entry points and registration modules require side effects
48
+ 'unicorn/no-unreadable-array-destructuring': 'off', // Property swaps are a readable destructuring use
49
+ 'unicorn/no-unreadable-for-of-expression': 'off', // Temporary iterable variables are not always clearer
50
+ 'unicorn/no-useless-else': 'off', // An explicit else can make control flow clearer
51
+ 'unicorn/prefer-await': 'off', // Promise chains are sometimes clearer than try/catch
52
+ 'unicorn/prefer-block-statement-over-iife': 'off', // IIFEs isolate legacy browser scripts
53
+ 'unicorn/prefer-boolean-return': 'off', // Explicit branches can be clearer
54
+ 'unicorn/prefer-continue': 'off', // Loop structure is contextual
55
+ 'unicorn/prefer-early-return': 'off', // Guard clauses are not always clearer
56
+ 'unicorn/prefer-else-if': 'off', // Separate conditions can better communicate intent
57
+ 'unicorn/prefer-https': 'off', // HTTP is valid for local and test URLs
58
+ 'unicorn/prefer-location-assign': 'off', // Assigning location.href is an established browser idiom
59
+ 'unicorn/prefer-logical-operator-over-ternary': 'off', // Ternaries can make fallback behavior explicit
60
+ 'unicorn/prefer-math-constants': 'off', // Approximate values are intentional in fixtures and examples
61
+ 'unicorn/prefer-minimal-ternary': 'off', // The transformed expression is not always easier to read
62
+ 'unicorn/prefer-number-coercion': 'off', // Number() differs from parseInt() and parseFloat()
63
+ 'unicorn/prefer-number-is-safe-integer': 'off', // This changes the accepted numeric range
64
+ 'unicorn/prefer-private-class-fields': 'off', // Underscore fields can be part of an external contract
65
+ 'unicorn/prefer-queue-microtask': 'off', // queueMicrotask() and process.nextTick() have different ordering
66
+ 'unicorn/prefer-split-limit': 'off', // Adding a limit is not clearer for most destructuring
67
+ 'unicorn/prefer-then-catch': 'off', // Both Promise rejection styles are valid
68
+ 'unicorn/single-line-block-comment-style': 'off', // Existing license and generated comments use both styles
33
69
  // These rules have many violations. Decisions about enabling the rules have been deferred.
34
70
  'unicorn/catch-error-name': 'off', // 200+ violations
35
- 'unicorn/no-array-for-each': 'off', // 300+ violations
71
+ 'unicorn/no-for-each': 'off', // 300+ violations
36
72
  'unicorn/no-await-expression-member': 'off', // 400+ violations
37
73
  'unicorn/no-negated-condition': 'off', // 150+ violations
38
74
  'unicorn/prefer-global-this': 'off', // 150+ violations
39
75
  'unicorn/prefer-node-protocol': 'off', // 100+ violations
76
+ 'unicorn/prefer-simple-condition-first': 'off', // 100+ violations
40
77
  'unicorn/switch-case-braces': 'off', // 200+ violations
78
+ // These rules look valuable, but enabling them requires a focused manual migration.
79
+ 'unicorn/better-dom-traversing': 'off', // 24 violations
80
+ 'unicorn/isolated-functions': 'off', // 41 violations, including Playwright evaluation callbacks
81
+ 'unicorn/no-array-sort-for-min-max': 'off', // 1 violation; empty-array behavior needs care
82
+ 'unicorn/no-duplicate-loops': 'off', // 1 violation; requires an allocation/readability tradeoff
83
+ 'unicorn/no-return-array-push': 'off', // 17 violations
84
+ 'unicorn/no-undeclared-class-members': 'off', // 71 violations in a legacy browser class
85
+ 'unicorn/no-unsafe-string-replacement': 'off', // 15 violations; replacements need semantic review
86
+ 'unicorn/prefer-observer-apis': 'off', // 1 violation; requires an interaction behavior change
87
+ 'unicorn/prefer-scoped-selector': 'off', // 12 violations
88
+ 'unicorn/require-array-sort-compare': 'off', // 54 violations; string sorts need individual review
89
+ // These rules can be considered in focused autofix or cleanup PRs.
90
+ 'unicorn/logical-assignment-operators': 'off', // 40 violations
91
+ 'unicorn/no-negated-array-predicate': 'off', // 26 violations
92
+ 'unicorn/no-unnecessary-boolean-comparison': 'off', // 13 violations
93
+ 'unicorn/no-useless-coercion': 'off', // 43 violations
94
+ 'unicorn/no-useless-template-literals': 'off', // 32 violations
95
+ 'unicorn/operator-assignment': 'off', // 10 violations
96
+ 'unicorn/prefer-array-from-map': 'off', // 23 violations
97
+ 'unicorn/prefer-direct-iteration': 'off', // 15 violations
98
+ 'unicorn/prefer-includes-over-repeated-comparisons': 'off', // 10 violations
99
+ 'unicorn/prefer-object-iterable-methods': 'off', // 19 violations
100
+ 'unicorn/prefer-string-repeat': 'off', // 16 violations
101
+ // These rules require confirming browser and runtime support before enabling them.
102
+ 'unicorn/prefer-array-from-async': 'off', // 5 violations
103
+ 'unicorn/prefer-dom-node-html-methods': 'off', // 2 violations
104
+ 'unicorn/prefer-dom-node-replace-children': 'off', // 3 violations
105
+ 'unicorn/prefer-iterator-helpers': 'off', // 3 violations
106
+ 'unicorn/prefer-iterator-to-array': 'off', // 34 violations
107
+ 'unicorn/prefer-iterator-to-array-at-end': 'off', // 5 violations
108
+ 'unicorn/prefer-promise-with-resolvers': 'off', // 5 violations
109
+ 'unicorn/prefer-set-methods': 'off', // 5 violations
110
+ 'unicorn/prefer-toggle-attribute': 'off', // 2 violations
111
+ // False positives for intentional source text or module structure.
112
+ 'unicorn/no-exports-in-scripts': 'off', // The server entry point is an ES module
113
+ 'unicorn/no-incorrect-template-string-interpolation': 'off', // We test and document literal ${...} text
41
114
  // TODO: investigate, < 100 violations
42
115
  'unicorn/consistent-assert': 'off',
43
116
  'unicorn/consistent-function-scoping': 'off',
@@ -1 +1 @@
1
- {"version":3,"file":"unicorn.js","sourceRoot":"","sources":["../../src/configs/unicorn.ts"],"names":[],"mappings":"AACA,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AAExD;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL;YACE,OAAO,EAAE;gBACP,OAAO,EAAE,mBAAmB;aAC7B;YAED,KAAK,EAAE;gBACL,GAAG,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK;gBAEhD,wDAAwD;gBACxD,uBAAuB,EAAE,KAAK,EAAE,iDAAiD;gBACjF,qCAAqC,EAAE,KAAK,EAAE,mCAAmC;gBACjF,qCAAqC,EAAE,KAAK;gBAC5C,uCAAuC,EAAE,KAAK;gBAC9C,yBAAyB,EAAE,KAAK,EAAE,8CAA8C;gBAChF,0BAA0B,EAAE,KAAK,EAAE,6EAA6E;gBAChH,uBAAuB,EAAE,KAAK,EAAE,0DAA0D;gBAC1F,uBAAuB,EAAE,KAAK;gBAC9B,sBAAsB,EAAE,KAAK,EAAE,iFAAiF;gBAChH,iBAAiB,EAAE,KAAK;gBACxB,8BAA8B,EAAE,KAAK,EAAE,8DAA8D;gBACrG,2BAA2B,EAAE,KAAK;gBAClC,iCAAiC,EAAE,KAAK,EAAE,iFAAiF;gBAC3H,4BAA4B,EAAE,KAAK,EAAE,iFAAiF;gBACtH,2BAA2B,EAAE,KAAK,EAAE,4CAA4C;gBAChF,wBAAwB,EAAE,KAAK,EAAE,8CAA8C;gBAC/E,gCAAgC,EAAE,KAAK,EAAE,gCAAgC;gBACzE,2BAA2B,EAAE,KAAK;gBAClC,+BAA+B,EAAE,KAAK;gBAEtC,2FAA2F;gBAC3F,0BAA0B,EAAE,KAAK,EAAE,kBAAkB;gBACrD,2BAA2B,EAAE,KAAK,EAAE,kBAAkB;gBACtD,oCAAoC,EAAE,KAAK,EAAE,kBAAkB;gBAC/D,8BAA8B,EAAE,KAAK,EAAE,kBAAkB;gBACzD,4BAA4B,EAAE,KAAK,EAAE,kBAAkB;gBACvD,8BAA8B,EAAE,KAAK,EAAE,kBAAkB;gBACzD,4BAA4B,EAAE,KAAK,EAAE,kBAAkB;gBAEvD,sCAAsC;gBACtC,2BAA2B,EAAE,KAAK;gBAClC,qCAAqC,EAAE,KAAK;gBAC5C,qBAAqB,EAAE,KAAK;gBAC5B,sBAAsB,EAAE,KAAK;gBAC7B,kCAAkC,EAAE,KAAK;gBACzC,+BAA+B,EAAE,KAAK;gBACtC,uBAAuB,EAAE,KAAK;gBAC9B,uBAAuB,EAAE,KAAK;gBAC9B,uCAAuC,EAAE,KAAK;gBAE9C,mDAAmD;gBACnD,wCAAwC,EAAE,KAAK;gBAC/C,mCAAmC,EAAE,KAAK;gBAC1C,sCAAsC,EAAE,KAAK;gBAC7C,6BAA6B,EAAE,KAAK;gBAEpC,kBAAkB;gBAClB,uBAAuB,EAAE,KAAK;gBAC9B,2BAA2B,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,EAAE,4CAA4C;gBAC9G,mBAAmB,EAAE,KAAK,EAAE,+EAA+E;gBAC3G,yBAAyB,EAAE,KAAK;gBAEhC,mCAAmC;gBACnC,8BAA8B,EAAE,KAAK;gBACrC,4BAA4B,EAAE,KAAK;gBACnC,uBAAuB,EAAE,KAAK;gBAE9B,4EAA4E;gBAC5E,qBAAqB,EAAE,KAAK;gBAE5B,0BAA0B;gBAC1B,2BAA2B,EAAE,KAAK;gBAClC,6BAA6B,EAAE,KAAK;gBACpC,yBAAyB,EAAE,KAAK;aACjC;SACF;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport eslintPluginUnicorn from 'eslint-plugin-unicorn';\n\n/**\n * Unicorn plugin rules with PrairieLearn-specific overrides.\n */\nexport function unicornConfig(): TSESLint.FlatConfig.ConfigArray {\n return [\n {\n plugins: {\n unicorn: eslintPluginUnicorn,\n },\n\n rules: {\n ...eslintPluginUnicorn.configs.recommended.rules,\n\n // These rules don't align with our own style guidelines\n 'unicorn/filename-case': 'off', // We don't enforce specific styles for filenames\n 'unicorn/no-anonymous-default-export': 'off', // We use this for all of our pages\n 'unicorn/no-array-callback-reference': 'off',\n 'unicorn/no-array-method-this-argument': 'off',\n 'unicorn/no-array-reduce': 'off', // Sometimes, an array reduce is more readable\n 'unicorn/no-array-reverse': 'off', // `Array.prototype.toReversed` is not yet supported by our TypeScript config\n 'unicorn/no-array-sort': 'off', // Disabling for the time being to avoid unnecessary diffs\n 'unicorn/no-hex-escape': 'off',\n 'unicorn/no-lonely-if': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252261293\n 'unicorn/no-null': 'off',\n 'unicorn/no-useless-undefined': 'off', // Explicit undefined is more readable than implicit undefined\n 'unicorn/prefer-code-point': 'off',\n 'unicorn/prefer-dom-node-dataset': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2261095992\n 'unicorn/prefer-export-from': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252265000\n 'unicorn/prefer-string-raw': 'off', // We don't use `String.raw` in our codebase\n 'unicorn/prefer-ternary': 'off', // if/else can be more readable than a ternary\n 'unicorn/prefer-top-level-await': 'off', // we use this on a lot of pages\n 'unicorn/prefer-type-error': 'off',\n 'unicorn/prevent-abbreviations': 'off',\n\n // These rules have many violations. Decisions about enabling the rules have been deferred.\n 'unicorn/catch-error-name': 'off', // 200+ violations\n 'unicorn/no-array-for-each': 'off', // 300+ violations\n 'unicorn/no-await-expression-member': 'off', // 400+ violations\n 'unicorn/no-negated-condition': 'off', // 150+ violations\n 'unicorn/prefer-global-this': 'off', // 150+ violations\n 'unicorn/prefer-node-protocol': 'off', // 100+ violations\n 'unicorn/switch-case-braces': 'off', // 200+ violations\n\n // TODO: investigate, < 100 violations\n 'unicorn/consistent-assert': 'off',\n 'unicorn/consistent-function-scoping': 'off',\n 'unicorn/escape-case': 'off',\n 'unicorn/import-style': 'off',\n 'unicorn/numeric-separators-style': 'off',\n 'unicorn/prefer-query-selector': 'off',\n 'unicorn/prefer-spread': 'off',\n 'unicorn/prefer-switch': 'off',\n 'unicorn/text-encoding-identifier-case': 'off',\n\n // TODO: investigated and manual fixes are required\n 'unicorn/no-object-as-default-parameter': 'off',\n 'unicorn/prefer-add-event-listener': 'off',\n 'unicorn/prefer-dom-node-text-content': 'off',\n 'unicorn/prefer-event-target': 'off',\n\n // False positives\n 'unicorn/error-message': 'off',\n 'unicorn/prefer-array-find': ['error', { checkFromLast: false }], // findLast is unavailable in our target lib\n 'unicorn/prefer-at': 'off', // https://github.com/microsoft/TypeScript/issues/47660#issuecomment-3146907649\n 'unicorn/throw-new-error': 'off',\n\n // Duplicated from other lint rules\n 'unicorn/no-static-only-class': 'off',\n 'unicorn/no-this-assignment': 'off',\n 'unicorn/prefer-module': 'off',\n\n // https://github.com/PrairieLearn/PrairieLearn/pull/12545/files#r2252069292\n 'unicorn/no-for-loop': 'off',\n\n // Conflicts with prettier\n 'unicorn/no-nested-ternary': 'off',\n 'unicorn/number-literal-case': 'off',\n 'unicorn/template-indent': 'off',\n },\n },\n ];\n}\n"]}
1
+ {"version":3,"file":"unicorn.js","sourceRoot":"","sources":["../../src/configs/unicorn.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport eslintPluginUnicorn from 'eslint-plugin-unicorn';\n\n/**\n * Unicorn plugin rules with PrairieLearn-specific overrides.\n */\nexport function unicornConfig(): TSESLint.FlatConfig.ConfigArray {\n return [\n {\n plugins: {\n unicorn: eslintPluginUnicorn,\n },\n\n rules: {\n ...eslintPluginUnicorn.configs.recommended.rules,\n\n // These rules don't align with our own style guidelines\n 'unicorn/filename-case': 'off', // We don't enforce specific styles for filenames\n 'unicorn/no-anonymous-default-export': 'off', // We use this for all of our pages\n 'unicorn/no-array-callback-reference': 'off',\n 'unicorn/no-array-method-this-argument': 'off',\n 'unicorn/no-array-reduce': 'off', // Sometimes, an array reduce is more readable\n 'unicorn/no-array-reverse': 'off', // `Array.prototype.toReversed` is not yet supported by our TypeScript config\n 'unicorn/no-array-sort': 'off', // Disabling for the time being to avoid unnecessary diffs\n 'unicorn/prefer-unicode-code-point-escapes': 'off',\n 'unicorn/no-lonely-if': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252261293\n 'unicorn/no-null': 'off',\n 'unicorn/no-useless-undefined': 'off', // Explicit undefined is more readable than implicit undefined\n 'unicorn/prefer-code-point': 'off',\n 'unicorn/dom-node-dataset': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2261095992\n 'unicorn/prefer-export-from': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252265000\n 'unicorn/prefer-string-raw': 'off', // We don't use `String.raw` in our codebase\n 'unicorn/prefer-ternary': 'off', // if/else can be more readable than a ternary\n 'unicorn/prefer-top-level-await': 'off', // we use this on a lot of pages\n 'unicorn/prefer-type-error': 'off',\n 'unicorn/name-replacements': 'off',\n\n // These rules enforce conventions that we don't want to adopt.\n 'unicorn/consistent-boolean-name': 'off', // Boolean prefixes are too restrictive\n 'unicorn/consistent-class-member-order': 'off', // Existing class organization is readable\n 'unicorn/consistent-compound-words': 'off', // Would create unnecessary API naming churn\n 'unicorn/consistent-conditional-object-spread': 'off', // Both forms are readable\n 'unicorn/max-nested-calls': 'off', // An arbitrary nesting limit does not measure readability\n 'unicorn/no-break-in-nested-loop': 'off', // Extracting loops into functions is often less clear\n 'unicorn/no-computed-property-existence-check': 'off', // Dynamic property checks are valid\n 'unicorn/no-constant-zero-expression': 'off', // Explicit zero terms can document formulas and fixtures\n 'unicorn/no-declarations-before-early-exit': 'off', // Declaration placement is contextual\n 'unicorn/no-global-object-property-assignment': 'off', // Browser entry points intentionally expose globals\n 'unicorn/no-non-function-verb-prefix': 'off', // Verb prefixes are valid for values such as URLs and modals\n 'unicorn/no-this-outside-of-class': 'off', // We use function receivers and legacy callback APIs\n 'unicorn/no-top-level-assignment-in-function': 'off', // Modules intentionally maintain process state\n 'unicorn/no-top-level-side-effects': 'off', // Entry points and registration modules require side effects\n 'unicorn/no-unreadable-array-destructuring': 'off', // Property swaps are a readable destructuring use\n 'unicorn/no-unreadable-for-of-expression': 'off', // Temporary iterable variables are not always clearer\n 'unicorn/no-useless-else': 'off', // An explicit else can make control flow clearer\n 'unicorn/prefer-await': 'off', // Promise chains are sometimes clearer than try/catch\n 'unicorn/prefer-block-statement-over-iife': 'off', // IIFEs isolate legacy browser scripts\n 'unicorn/prefer-boolean-return': 'off', // Explicit branches can be clearer\n 'unicorn/prefer-continue': 'off', // Loop structure is contextual\n 'unicorn/prefer-early-return': 'off', // Guard clauses are not always clearer\n 'unicorn/prefer-else-if': 'off', // Separate conditions can better communicate intent\n 'unicorn/prefer-https': 'off', // HTTP is valid for local and test URLs\n 'unicorn/prefer-location-assign': 'off', // Assigning location.href is an established browser idiom\n 'unicorn/prefer-logical-operator-over-ternary': 'off', // Ternaries can make fallback behavior explicit\n 'unicorn/prefer-math-constants': 'off', // Approximate values are intentional in fixtures and examples\n 'unicorn/prefer-minimal-ternary': 'off', // The transformed expression is not always easier to read\n 'unicorn/prefer-number-coercion': 'off', // Number() differs from parseInt() and parseFloat()\n 'unicorn/prefer-number-is-safe-integer': 'off', // This changes the accepted numeric range\n 'unicorn/prefer-private-class-fields': 'off', // Underscore fields can be part of an external contract\n 'unicorn/prefer-queue-microtask': 'off', // queueMicrotask() and process.nextTick() have different ordering\n 'unicorn/prefer-split-limit': 'off', // Adding a limit is not clearer for most destructuring\n 'unicorn/prefer-then-catch': 'off', // Both Promise rejection styles are valid\n 'unicorn/single-line-block-comment-style': 'off', // Existing license and generated comments use both styles\n\n // These rules have many violations. Decisions about enabling the rules have been deferred.\n 'unicorn/catch-error-name': 'off', // 200+ violations\n 'unicorn/no-for-each': 'off', // 300+ violations\n 'unicorn/no-await-expression-member': 'off', // 400+ violations\n 'unicorn/no-negated-condition': 'off', // 150+ violations\n 'unicorn/prefer-global-this': 'off', // 150+ violations\n 'unicorn/prefer-node-protocol': 'off', // 100+ violations\n 'unicorn/prefer-simple-condition-first': 'off', // 100+ violations\n 'unicorn/switch-case-braces': 'off', // 200+ violations\n\n // These rules look valuable, but enabling them requires a focused manual migration.\n 'unicorn/better-dom-traversing': 'off', // 24 violations\n 'unicorn/isolated-functions': 'off', // 41 violations, including Playwright evaluation callbacks\n 'unicorn/no-array-sort-for-min-max': 'off', // 1 violation; empty-array behavior needs care\n 'unicorn/no-duplicate-loops': 'off', // 1 violation; requires an allocation/readability tradeoff\n 'unicorn/no-return-array-push': 'off', // 17 violations\n 'unicorn/no-undeclared-class-members': 'off', // 71 violations in a legacy browser class\n 'unicorn/no-unsafe-string-replacement': 'off', // 15 violations; replacements need semantic review\n 'unicorn/prefer-observer-apis': 'off', // 1 violation; requires an interaction behavior change\n 'unicorn/prefer-scoped-selector': 'off', // 12 violations\n 'unicorn/require-array-sort-compare': 'off', // 54 violations; string sorts need individual review\n\n // These rules can be considered in focused autofix or cleanup PRs.\n 'unicorn/logical-assignment-operators': 'off', // 40 violations\n 'unicorn/no-negated-array-predicate': 'off', // 26 violations\n 'unicorn/no-unnecessary-boolean-comparison': 'off', // 13 violations\n 'unicorn/no-useless-coercion': 'off', // 43 violations\n 'unicorn/no-useless-template-literals': 'off', // 32 violations\n 'unicorn/operator-assignment': 'off', // 10 violations\n 'unicorn/prefer-array-from-map': 'off', // 23 violations\n 'unicorn/prefer-direct-iteration': 'off', // 15 violations\n 'unicorn/prefer-includes-over-repeated-comparisons': 'off', // 10 violations\n 'unicorn/prefer-object-iterable-methods': 'off', // 19 violations\n 'unicorn/prefer-string-repeat': 'off', // 16 violations\n\n // These rules require confirming browser and runtime support before enabling them.\n 'unicorn/prefer-array-from-async': 'off', // 5 violations\n 'unicorn/prefer-dom-node-html-methods': 'off', // 2 violations\n 'unicorn/prefer-dom-node-replace-children': 'off', // 3 violations\n 'unicorn/prefer-iterator-helpers': 'off', // 3 violations\n 'unicorn/prefer-iterator-to-array': 'off', // 34 violations\n 'unicorn/prefer-iterator-to-array-at-end': 'off', // 5 violations\n 'unicorn/prefer-promise-with-resolvers': 'off', // 5 violations\n 'unicorn/prefer-set-methods': 'off', // 5 violations\n 'unicorn/prefer-toggle-attribute': 'off', // 2 violations\n\n // False positives for intentional source text or module structure.\n 'unicorn/no-exports-in-scripts': 'off', // The server entry point is an ES module\n 'unicorn/no-incorrect-template-string-interpolation': 'off', // We test and document literal ${...} text\n\n // TODO: investigate, < 100 violations\n 'unicorn/consistent-assert': 'off',\n 'unicorn/consistent-function-scoping': 'off',\n 'unicorn/escape-case': 'off',\n 'unicorn/import-style': 'off',\n 'unicorn/numeric-separators-style': 'off',\n 'unicorn/prefer-query-selector': 'off',\n 'unicorn/prefer-spread': 'off',\n 'unicorn/prefer-switch': 'off',\n 'unicorn/text-encoding-identifier-case': 'off',\n\n // TODO: investigated and manual fixes are required\n 'unicorn/no-object-as-default-parameter': 'off',\n 'unicorn/prefer-add-event-listener': 'off',\n 'unicorn/prefer-dom-node-text-content': 'off',\n 'unicorn/prefer-event-target': 'off',\n\n // False positives\n 'unicorn/error-message': 'off',\n 'unicorn/prefer-array-find': ['error', { checkFromLast: false }], // findLast is unavailable in our target lib\n 'unicorn/prefer-at': 'off', // https://github.com/microsoft/TypeScript/issues/47660#issuecomment-3146907649\n 'unicorn/throw-new-error': 'off',\n\n // Duplicated from other lint rules\n 'unicorn/no-static-only-class': 'off',\n 'unicorn/no-this-assignment': 'off',\n 'unicorn/prefer-module': 'off',\n\n // https://github.com/PrairieLearn/PrairieLearn/pull/12545/files#r2252069292\n 'unicorn/no-for-loop': 'off',\n\n // Conflicts with prettier\n 'unicorn/no-nested-ternary': 'off',\n 'unicorn/number-literal-case': 'off',\n 'unicorn/template-indent': 'off',\n },\n },\n ];\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prairielearn/eslint-config",
3
- "version": "3.1.2",
3
+ "version": "3.1.4",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,11 +34,11 @@
34
34
  "eslint-plugin-perfectionist": "^5.10.0",
35
35
  "eslint-plugin-react-hooks": "^7.1.1",
36
36
  "eslint-plugin-react-you-might-not-need-an-effect": "^0.11.1",
37
- "eslint-plugin-unicorn": "^64.0.0",
37
+ "eslint-plugin-unicorn": "^73.0.0",
38
38
  "eslint-plugin-you-dont-need-lodash-underscore": "^6.14.0",
39
39
  "globals": "^17.9.0",
40
40
  "typescript-eslint": "^8.66.0",
41
- "@prairielearn/eslint-plugin": "^4.3.5"
41
+ "@prairielearn/eslint-plugin": "^4.3.6"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^24.13.3",
@@ -22,28 +22,106 @@ export function unicornConfig(): TSESLint.FlatConfig.ConfigArray {
22
22
  'unicorn/no-array-reduce': 'off', // Sometimes, an array reduce is more readable
23
23
  'unicorn/no-array-reverse': 'off', // `Array.prototype.toReversed` is not yet supported by our TypeScript config
24
24
  'unicorn/no-array-sort': 'off', // Disabling for the time being to avoid unnecessary diffs
25
- 'unicorn/no-hex-escape': 'off',
25
+ 'unicorn/prefer-unicode-code-point-escapes': 'off',
26
26
  'unicorn/no-lonely-if': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252261293
27
27
  'unicorn/no-null': 'off',
28
28
  'unicorn/no-useless-undefined': 'off', // Explicit undefined is more readable than implicit undefined
29
29
  'unicorn/prefer-code-point': 'off',
30
- 'unicorn/prefer-dom-node-dataset': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2261095992
30
+ 'unicorn/dom-node-dataset': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2261095992
31
31
  'unicorn/prefer-export-from': 'off', // https://github.com/PrairieLearn/PrairieLearn/pull/12546#discussion_r2252265000
32
32
  'unicorn/prefer-string-raw': 'off', // We don't use `String.raw` in our codebase
33
33
  'unicorn/prefer-ternary': 'off', // if/else can be more readable than a ternary
34
34
  'unicorn/prefer-top-level-await': 'off', // we use this on a lot of pages
35
35
  'unicorn/prefer-type-error': 'off',
36
- 'unicorn/prevent-abbreviations': 'off',
36
+ 'unicorn/name-replacements': 'off',
37
+
38
+ // These rules enforce conventions that we don't want to adopt.
39
+ 'unicorn/consistent-boolean-name': 'off', // Boolean prefixes are too restrictive
40
+ 'unicorn/consistent-class-member-order': 'off', // Existing class organization is readable
41
+ 'unicorn/consistent-compound-words': 'off', // Would create unnecessary API naming churn
42
+ 'unicorn/consistent-conditional-object-spread': 'off', // Both forms are readable
43
+ 'unicorn/max-nested-calls': 'off', // An arbitrary nesting limit does not measure readability
44
+ 'unicorn/no-break-in-nested-loop': 'off', // Extracting loops into functions is often less clear
45
+ 'unicorn/no-computed-property-existence-check': 'off', // Dynamic property checks are valid
46
+ 'unicorn/no-constant-zero-expression': 'off', // Explicit zero terms can document formulas and fixtures
47
+ 'unicorn/no-declarations-before-early-exit': 'off', // Declaration placement is contextual
48
+ 'unicorn/no-global-object-property-assignment': 'off', // Browser entry points intentionally expose globals
49
+ 'unicorn/no-non-function-verb-prefix': 'off', // Verb prefixes are valid for values such as URLs and modals
50
+ 'unicorn/no-this-outside-of-class': 'off', // We use function receivers and legacy callback APIs
51
+ 'unicorn/no-top-level-assignment-in-function': 'off', // Modules intentionally maintain process state
52
+ 'unicorn/no-top-level-side-effects': 'off', // Entry points and registration modules require side effects
53
+ 'unicorn/no-unreadable-array-destructuring': 'off', // Property swaps are a readable destructuring use
54
+ 'unicorn/no-unreadable-for-of-expression': 'off', // Temporary iterable variables are not always clearer
55
+ 'unicorn/no-useless-else': 'off', // An explicit else can make control flow clearer
56
+ 'unicorn/prefer-await': 'off', // Promise chains are sometimes clearer than try/catch
57
+ 'unicorn/prefer-block-statement-over-iife': 'off', // IIFEs isolate legacy browser scripts
58
+ 'unicorn/prefer-boolean-return': 'off', // Explicit branches can be clearer
59
+ 'unicorn/prefer-continue': 'off', // Loop structure is contextual
60
+ 'unicorn/prefer-early-return': 'off', // Guard clauses are not always clearer
61
+ 'unicorn/prefer-else-if': 'off', // Separate conditions can better communicate intent
62
+ 'unicorn/prefer-https': 'off', // HTTP is valid for local and test URLs
63
+ 'unicorn/prefer-location-assign': 'off', // Assigning location.href is an established browser idiom
64
+ 'unicorn/prefer-logical-operator-over-ternary': 'off', // Ternaries can make fallback behavior explicit
65
+ 'unicorn/prefer-math-constants': 'off', // Approximate values are intentional in fixtures and examples
66
+ 'unicorn/prefer-minimal-ternary': 'off', // The transformed expression is not always easier to read
67
+ 'unicorn/prefer-number-coercion': 'off', // Number() differs from parseInt() and parseFloat()
68
+ 'unicorn/prefer-number-is-safe-integer': 'off', // This changes the accepted numeric range
69
+ 'unicorn/prefer-private-class-fields': 'off', // Underscore fields can be part of an external contract
70
+ 'unicorn/prefer-queue-microtask': 'off', // queueMicrotask() and process.nextTick() have different ordering
71
+ 'unicorn/prefer-split-limit': 'off', // Adding a limit is not clearer for most destructuring
72
+ 'unicorn/prefer-then-catch': 'off', // Both Promise rejection styles are valid
73
+ 'unicorn/single-line-block-comment-style': 'off', // Existing license and generated comments use both styles
37
74
 
38
75
  // These rules have many violations. Decisions about enabling the rules have been deferred.
39
76
  'unicorn/catch-error-name': 'off', // 200+ violations
40
- 'unicorn/no-array-for-each': 'off', // 300+ violations
77
+ 'unicorn/no-for-each': 'off', // 300+ violations
41
78
  'unicorn/no-await-expression-member': 'off', // 400+ violations
42
79
  'unicorn/no-negated-condition': 'off', // 150+ violations
43
80
  'unicorn/prefer-global-this': 'off', // 150+ violations
44
81
  'unicorn/prefer-node-protocol': 'off', // 100+ violations
82
+ 'unicorn/prefer-simple-condition-first': 'off', // 100+ violations
45
83
  'unicorn/switch-case-braces': 'off', // 200+ violations
46
84
 
85
+ // These rules look valuable, but enabling them requires a focused manual migration.
86
+ 'unicorn/better-dom-traversing': 'off', // 24 violations
87
+ 'unicorn/isolated-functions': 'off', // 41 violations, including Playwright evaluation callbacks
88
+ 'unicorn/no-array-sort-for-min-max': 'off', // 1 violation; empty-array behavior needs care
89
+ 'unicorn/no-duplicate-loops': 'off', // 1 violation; requires an allocation/readability tradeoff
90
+ 'unicorn/no-return-array-push': 'off', // 17 violations
91
+ 'unicorn/no-undeclared-class-members': 'off', // 71 violations in a legacy browser class
92
+ 'unicorn/no-unsafe-string-replacement': 'off', // 15 violations; replacements need semantic review
93
+ 'unicorn/prefer-observer-apis': 'off', // 1 violation; requires an interaction behavior change
94
+ 'unicorn/prefer-scoped-selector': 'off', // 12 violations
95
+ 'unicorn/require-array-sort-compare': 'off', // 54 violations; string sorts need individual review
96
+
97
+ // These rules can be considered in focused autofix or cleanup PRs.
98
+ 'unicorn/logical-assignment-operators': 'off', // 40 violations
99
+ 'unicorn/no-negated-array-predicate': 'off', // 26 violations
100
+ 'unicorn/no-unnecessary-boolean-comparison': 'off', // 13 violations
101
+ 'unicorn/no-useless-coercion': 'off', // 43 violations
102
+ 'unicorn/no-useless-template-literals': 'off', // 32 violations
103
+ 'unicorn/operator-assignment': 'off', // 10 violations
104
+ 'unicorn/prefer-array-from-map': 'off', // 23 violations
105
+ 'unicorn/prefer-direct-iteration': 'off', // 15 violations
106
+ 'unicorn/prefer-includes-over-repeated-comparisons': 'off', // 10 violations
107
+ 'unicorn/prefer-object-iterable-methods': 'off', // 19 violations
108
+ 'unicorn/prefer-string-repeat': 'off', // 16 violations
109
+
110
+ // These rules require confirming browser and runtime support before enabling them.
111
+ 'unicorn/prefer-array-from-async': 'off', // 5 violations
112
+ 'unicorn/prefer-dom-node-html-methods': 'off', // 2 violations
113
+ 'unicorn/prefer-dom-node-replace-children': 'off', // 3 violations
114
+ 'unicorn/prefer-iterator-helpers': 'off', // 3 violations
115
+ 'unicorn/prefer-iterator-to-array': 'off', // 34 violations
116
+ 'unicorn/prefer-iterator-to-array-at-end': 'off', // 5 violations
117
+ 'unicorn/prefer-promise-with-resolvers': 'off', // 5 violations
118
+ 'unicorn/prefer-set-methods': 'off', // 5 violations
119
+ 'unicorn/prefer-toggle-attribute': 'off', // 2 violations
120
+
121
+ // False positives for intentional source text or module structure.
122
+ 'unicorn/no-exports-in-scripts': 'off', // The server entry point is an ES module
123
+ 'unicorn/no-incorrect-template-string-interpolation': 'off', // We test and document literal ${...} text
124
+
47
125
  // TODO: investigate, < 100 violations
48
126
  'unicorn/consistent-assert': 'off',
49
127
  'unicorn/consistent-function-scoping': 'off',