diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6fd7e29382..b994543b90 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,12 +19,14 @@ updates: patterns: - 'tsdown' - '@tsdown/*' + oxlint: + patterns: + - 'oxlint' + - 'oxlint-tsgolint' vitest: patterns: - 'vitest' - '@vitest/*' - exclude-patterns: - - '@vitest/eslint-plugin' - package-ecosystem: 'github-actions' directory: '/' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3be5f75b59..3eb6a0a594 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,8 +23,11 @@ jobs: - name: Typecheck run: node --run typecheck - - name: ESLint - run: node --run eslint + - name: Oxlint + run: node --run lint + + - name: ESLint (markdown) + run: node --run lint:md - name: Oxfmt run: node --run format:check diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f840f2f395..9f74d42b6c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -33,8 +33,11 @@ jobs: - name: Typecheck run: node --run typecheck - - name: ESLint - run: node --run eslint + - name: Oxlint + run: node --run lint + + - name: ESLint (markdown) + run: node --run lint:md - name: Oxfmt run: node --run format:check diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000000..715433de23 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,955 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": [], + "categories": { + "correctness": "off" + }, + "options": { + "typeAware": true + }, + "env": { + "builtin": true + }, + "ignorePatterns": [ + ".cache", + ".claude", + ".nitro", + ".output", + ".tanstack", + "coverage", + "dist", + "lib" + ], + "overrides": [ + { + "files": ["**/*.{js,ts,tsx}"], + "rules": { + "array-callback-return": [ + "warn", + { + "checkForEach": true + } + ], + "constructor-super": "off", + "for-direction": "warn", + "getter-return": "warn", + "no-async-promise-executor": "warn", + "no-await-in-loop": "off", + "no-class-assign": "off", + "no-compare-neg-zero": "warn", + "no-cond-assign": "warn", + "no-const-assign": "off", + "no-constant-binary-expression": "warn", + "no-constant-condition": "warn", + "no-constructor-return": "warn", + "no-control-regex": "warn", + "no-debugger": "warn", + "no-dupe-class-members": "off", + "no-dupe-else-if": "warn", + "no-dupe-keys": "warn", + "no-duplicate-case": "warn", + "no-duplicate-imports": "off", + "no-empty-character-class": "warn", + "no-empty-pattern": "warn", + "no-ex-assign": "warn", + "no-fallthrough": [ + "warn", + { + "reportUnusedFallthroughComment": true + } + ], + "no-func-assign": "warn", + "no-import-assign": "warn", + "no-inner-declarations": "off", + "no-invalid-regexp": "warn", + "no-irregular-whitespace": "warn", + "no-loss-of-precision": "warn", + "no-misleading-character-class": "warn", + "no-new-native-nonconstructor": "warn", + "no-obj-calls": "warn", + "no-promise-executor-return": "warn", + "no-prototype-builtins": "warn", + "no-self-assign": [ + "warn", + { + "props": true + } + ], + "no-self-compare": "warn", + "no-setter-return": "warn", + "no-sparse-arrays": "warn", + "no-template-curly-in-string": "warn", + "no-this-before-super": "off", + "no-unassigned-vars": "warn", + "no-undef": "off", + "no-unexpected-multiline": "off", + "no-unmodified-loop-condition": "warn", + "no-unreachable": "warn", + "no-unreachable-loop": "warn", + "no-unsafe-finally": "warn", + "no-unsafe-negation": [ + "warn", + { + "enforceForOrderingRelations": true + } + ], + "no-unsafe-optional-chaining": [ + "warn", + { + "disallowArithmeticOperators": true + } + ], + "no-unused-private-class-members": "off", + "no-unused-vars": [ + "warn", + { + "enableAutofixRemoval": { + "imports": true + }, + "ignoreRestSiblings": true + } + ], + "no-use-before-define": "off", + "no-useless-backreference": "warn", + "use-isnan": [ + "warn", + { + "enforceForIndexOf": true + } + ], + "valid-typeof": [ + "warn", + { + "requireStringLiterals": true + } + ], + "accessor-pairs": "warn", + "arrow-body-style": "off", + "block-scoped-var": "warn", + "capitalized-comments": "off", + "class-methods-use-this": "warn", + "complexity": "off", + "curly": "off", + "default-case": "warn", + "default-case-last": "warn", + "default-param-last": "off", + "eqeqeq": [ + "warn", + "always", + { + "null": "ignore" + } + ], + "func-name-matching": "off", + "func-names": "off", + "func-style": "off", + "grouped-accessor-pairs": ["warn", "getBeforeSet"], + "guard-for-in": "off", + "id-denylist": "off", + "id-length": "off", + "id-match": "off", + "init-declarations": "off", + "logical-assignment-operators": [ + "warn", + "always", + { + "enforceForIfStatements": true + } + ], + "max-classes-per-file": "off", + "max-depth": "off", + "max-lines": "off", + "max-lines-per-function": "off", + "max-nested-callbacks": "off", + "max-params": "off", + "max-statements": "off", + "new-cap": "off", + "no-alert": "off", + "no-array-constructor": "warn", + "no-bitwise": "off", + "no-caller": "warn", + "no-case-declarations": "warn", + "no-console": "warn", + "no-continue": "off", + "no-delete-var": "warn", + "no-div-regex": "off", + "no-else-return": [ + "warn", + { + "allowElseIf": false + } + ], + "no-empty": [ + "warn", + { + "allowEmptyCatch": true + } + ], + "no-empty-function": "off", + "no-empty-static-block": "warn", + "no-eq-null": "off", + "no-eval": "warn", + "no-extend-native": "warn", + "no-extra-bind": "warn", + "no-extra-boolean-cast": [ + "warn", + { + "enforceForLogicalOperands": true + } + ], + "no-extra-label": "warn", + "no-global-assign": "warn", + "no-implicit-coercion": "off", + "no-implicit-globals": "off", + "no-implied-eval": "off", + "no-inline-comments": "off", + "no-iterator": "warn", + "no-label-var": "warn", + "no-labels": "warn", + "no-lone-blocks": "warn", + "no-lonely-if": "warn", + "no-loop-func": "off", + "no-magic-numbers": "off", + "no-multi-assign": "off", + "no-multi-str": "warn", + "no-negated-condition": "off", + "no-nested-ternary": "off", + "no-new": "warn", + "no-new-func": "warn", + "no-new-wrappers": "warn", + "no-nonoctal-decimal-escape": "warn", + "no-object-constructor": "warn", + "no-param-reassign": "off", + "no-plusplus": "off", + "no-proto": "warn", + "no-redeclare": "warn", + "no-regex-spaces": "warn", + "no-restricted-exports": "off", + "no-restricted-globals": [ + "warn", + { + "name": "Omit", + "message": "Use Omit from types instead." + } + ], + "no-restricted-imports": "off", + "no-restricted-properties": "off", + "no-return-assign": "off", + "no-script-url": "warn", + "no-sequences": [ + "warn", + { + "allowInParentheses": false + } + ], + "no-shadow": "off", + "no-shadow-restricted-names": "warn", + "no-ternary": "off", + "no-throw-literal": "off", + "no-undefined": "off", + "no-underscore-dangle": "off", + "no-unneeded-ternary": [ + "warn", + { + "defaultAssignment": false + } + ], + "no-unused-expressions": [ + "warn", + { + "enforceForJSX": true + } + ], + "no-unused-labels": "warn", + "no-useless-call": "warn", + "no-useless-catch": "warn", + "no-useless-computed-key": "warn", + "no-useless-concat": "warn", + "no-useless-constructor": "warn", + "no-useless-escape": "warn", + "no-useless-rename": "warn", + "no-useless-return": "warn", + "no-var": "warn", + "no-void": "warn", + "no-warning-comments": "off", + "no-with": "warn", + "object-shorthand": [ + "warn", + "always", + { + "avoidExplicitReturnArrows": true + } + ], + "operator-assignment": "warn", + "prefer-arrow-callback": [ + "warn", + { + "allowNamedFunctions": true + } + ], + "prefer-const": [ + "warn", + { + "destructuring": "all" + } + ], + "prefer-destructuring": "off", + "prefer-exponentiation-operator": "warn", + "prefer-named-capture-group": "off", + "prefer-numeric-literals": "warn", + "prefer-object-has-own": "warn", + "prefer-object-spread": "warn", + "prefer-promise-reject-errors": "off", + "prefer-regex-literals": [ + "warn", + { + "disallowRedundantWrapping": true + } + ], + "prefer-rest-params": "warn", + "prefer-spread": "warn", + "prefer-template": "warn", + "preserve-caught-error": "warn", + "radix": "warn", + "require-await": "off", + "require-unicode-regexp": "off", + "require-yield": "warn", + "sort-keys": "off", + "sort-vars": "off", + "symbol-description": "warn", + "vars-on-top": "off", + "yoda": "off", + "unicode-bom": "warn", + "@eslint-react/error-boundaries": "warn", + "@eslint-react/exhaustive-deps": "warn", + "@eslint-react/globals": "warn", + "@eslint-react/immutability": "warn", + "@eslint-react/no-access-state-in-setstate": "warn", + "@eslint-react/no-array-index-key": "off", + "@eslint-react/no-children-count": "warn", + "@eslint-react/no-children-for-each": "warn", + "@eslint-react/no-children-map": "warn", + "@eslint-react/no-children-only": "warn", + "@eslint-react/no-children-to-array": "warn", + "@eslint-react/no-class-component": "warn", + "@eslint-react/no-clone-element": "warn", + "@eslint-react/no-component-will-mount": "warn", + "@eslint-react/no-component-will-receive-props": "warn", + "@eslint-react/no-component-will-update": "warn", + "@eslint-react/no-context-provider": "warn", + "@eslint-react/no-create-ref": "warn", + "@eslint-react/no-direct-mutation-state": "warn", + "@eslint-react/no-duplicate-key": "warn", + "@eslint-react/no-forward-ref": "warn", + "@eslint-react/no-implicit-children": "off", + "@eslint-react/no-implicit-key": "off", + "@eslint-react/no-implicit-ref": "off", + "@eslint-react/no-leaked-conditional-rendering": "off", + "@eslint-react/no-missing-component-display-name": "warn", + "@eslint-react/no-missing-context-display-name": "warn", + "@eslint-react/no-missing-key": "warn", + "@eslint-react/no-misused-capture-owner-stack": "warn", + "@eslint-react/no-nested-component-definitions": "warn", + "@eslint-react/no-nested-lazy-component-declarations": "warn", + "@eslint-react/no-set-state-in-component-did-mount": "warn", + "@eslint-react/no-set-state-in-component-did-update": "warn", + "@eslint-react/no-set-state-in-component-will-update": "warn", + "@eslint-react/no-unnecessary-use-prefix": "warn", + "@eslint-react/no-unsafe-component-will-mount": "warn", + "@eslint-react/no-unsafe-component-will-receive-props": "warn", + "@eslint-react/no-unsafe-component-will-update": "warn", + "@eslint-react/no-unstable-context-value": "warn", + "@eslint-react/no-unstable-default-props": "warn", + "@eslint-react/no-unused-class-component-members": "warn", + "@eslint-react/no-unused-props": "off", + "@eslint-react/no-unused-state": "warn", + "@eslint-react/no-use-context": "warn", + "@eslint-react/purity": "warn", + "@eslint-react/refs": "warn", + "@eslint-react/rules-of-hooks": "warn", + "@eslint-react/set-state-in-effect": "off", + "@eslint-react/set-state-in-render": "warn", + "@eslint-react/static-components": "warn", + "@eslint-react/unsupported-syntax": "warn", + "@eslint-react/use-memo": "warn", + "@eslint-react/use-state": "warn", + "@eslint-react/jsx-no-children-prop": "warn", + "@eslint-react/jsx-no-children-prop-with-children": "warn", + "@eslint-react/jsx-no-comment-textnodes": "warn", + "@eslint-react/jsx-no-key-after-spread": "warn", + "@eslint-react/jsx-no-leaked-dollar": "warn", + "@eslint-react/jsx-no-leaked-semicolon": "warn", + "@eslint-react/jsx-no-namespace": "warn", + "@eslint-react/jsx-no-useless-fragment": [ + "warn", + { + "allowExpressions": false + } + ], + "@eslint-react/rsc-function-definition": "warn", + "@eslint-react/dom-no-dangerously-set-innerhtml": "warn", + "@eslint-react/dom-no-dangerously-set-innerhtml-with-children": "warn", + "@eslint-react/dom-no-find-dom-node": "warn", + "@eslint-react/dom-no-flush-sync": "off", + "@eslint-react/dom-no-hydrate": "warn", + "@eslint-react/dom-no-missing-button-type": "warn", + "@eslint-react/dom-no-missing-iframe-sandbox": "warn", + "@eslint-react/dom-no-render": "warn", + "@eslint-react/dom-no-render-return-value": "warn", + "@eslint-react/dom-no-script-url": "warn", + "@eslint-react/dom-no-string-style-prop": "warn", + "@eslint-react/dom-no-unknown-property": "warn", + "@eslint-react/dom-no-unsafe-iframe-sandbox": "warn", + "@eslint-react/dom-no-unsafe-target-blank": "warn", + "@eslint-react/dom-no-use-form-state": "warn", + "@eslint-react/dom-no-void-elements-with-children": "warn", + "@eslint-react/web-api-no-leaked-event-listener": "warn", + "@eslint-react/web-api-no-leaked-fetch": "warn", + "@eslint-react/web-api-no-leaked-intersection-observer": "warn", + "@eslint-react/web-api-no-leaked-interval": "warn", + "@eslint-react/web-api-no-leaked-resize-observer": "warn", + "@eslint-react/web-api-no-leaked-timeout": "warn", + "@eslint-react/naming-convention-context-name": "warn", + "@eslint-react/naming-convention-id-name": "warn", + "@eslint-react/naming-convention-ref-name": "warn", + "sonarjs/anchor-precedence": "warn", + "sonarjs/argument-type": "warn", + "sonarjs/arguments-order": "warn", + "sonarjs/arguments-usage": "warn", + "sonarjs/array-callback-without-return": "warn", + "sonarjs/array-constructor": "warn", + "sonarjs/arrow-function-convention": "off", + "sonarjs/assertions-in-tests": "warn", + "sonarjs/aws-apigateway-public-api": "off", + "sonarjs/aws-ec2-rds-dms-public": "off", + "sonarjs/aws-ec2-unencrypted-ebs-volume": "off", + "sonarjs/aws-efs-unencrypted": "off", + "sonarjs/aws-iam-all-privileges": "off", + "sonarjs/aws-iam-all-resources-accessible": "off", + "sonarjs/aws-iam-privilege-escalation": "off", + "sonarjs/aws-iam-public-access": "off", + "sonarjs/aws-opensearchservice-domain": "off", + "sonarjs/aws-rds-unencrypted-databases": "off", + "sonarjs/aws-restricted-ip-admin-access": "off", + "sonarjs/aws-s3-bucket-granted-access": "off", + "sonarjs/aws-s3-bucket-insecure-http": "off", + "sonarjs/aws-s3-bucket-public-access": "off", + "sonarjs/aws-s3-bucket-versioning": "off", + "sonarjs/aws-sagemaker-unencrypted-notebook": "off", + "sonarjs/aws-sns-unencrypted-topics": "off", + "sonarjs/aws-sqs-unencrypted-queue": "off", + "sonarjs/bitwise-operators": "warn", + "sonarjs/block-scoped-var": "warn", + "sonarjs/bool-param-default": "warn", + "sonarjs/call-argument-line": "warn", + "sonarjs/chai-determinate-assertion": "warn", + "sonarjs/class-name": "warn", + "sonarjs/class-prototype": "warn", + "sonarjs/code-eval": "warn", + "sonarjs/cognitive-complexity": "off", + "sonarjs/comma-or-logical-or-case": "warn", + "sonarjs/comment-regex": "warn", + "sonarjs/concise-regex": "warn", + "sonarjs/confidential-information-logging": "warn", + "sonarjs/constructor-for-side-effects": "warn", + "sonarjs/content-length": "warn", + "sonarjs/content-security-policy": "warn", + "sonarjs/cookie-no-httponly": "warn", + "sonarjs/cors": "warn", + "sonarjs/csrf": "warn", + "sonarjs/cyclomatic-complexity": "off", + "sonarjs/declarations-in-global-scope": "off", + "sonarjs/deprecation": "off", + "sonarjs/destructuring-assignment-syntax": "warn", + "sonarjs/different-types-comparison": "warn", + "sonarjs/disabled-auto-escaping": "warn", + "sonarjs/disabled-resource-integrity": "warn", + "sonarjs/disabled-timeout": "warn", + "sonarjs/dompurify-unsafe-config": "warn", + "sonarjs/duplicates-in-character-class": "warn", + "sonarjs/dynamically-constructed-templates": "warn", + "sonarjs/elseif-without-else": "off", + "sonarjs/empty-string-repetition": "warn", + "sonarjs/encryption-secure-mode": "warn", + "sonarjs/existing-groups": "warn", + "sonarjs/expression-complexity": "off", + "sonarjs/file-header": "off", + "sonarjs/file-name-differ-from-class": "warn", + "sonarjs/file-permissions": "warn", + "sonarjs/file-uploads": "warn", + "sonarjs/fixme-tag": "warn", + "sonarjs/for-in": "warn", + "sonarjs/for-loop-increment-sign": "warn", + "sonarjs/frame-ancestors": "warn", + "sonarjs/function-inside-loop": "warn", + "sonarjs/function-name": "off", + "sonarjs/function-return-type": "off", + "sonarjs/future-reserved-words": "warn", + "sonarjs/generator-without-yield": "warn", + "sonarjs/hardcoded-secret-signatures": "warn", + "sonarjs/hashing": "warn", + "sonarjs/hidden-files": "warn", + "sonarjs/in-operator-type-error": "warn", + "sonarjs/inconsistent-function-call": "warn", + "sonarjs/index-of-compare-to-positive-number": "warn", + "sonarjs/insecure-cookie": "warn", + "sonarjs/insecure-jwt-token": "warn", + "sonarjs/inverted-assertion-arguments": "warn", + "sonarjs/jsx-no-leaked-render": "warn", + "sonarjs/label-position": "warn", + "sonarjs/link-with-target-blank": "warn", + "sonarjs/max-lines": "off", + "sonarjs/max-lines-per-function": "off", + "sonarjs/max-switch-cases": "off", + "sonarjs/max-union-size": "off", + "sonarjs/misplaced-loop-counter": "warn", + "sonarjs/nested-control-flow": "off", + "sonarjs/new-operator-misuse": "warn", + "sonarjs/no-all-duplicated-branches": "warn", + "sonarjs/no-alphabetical-sort": "warn", + "sonarjs/no-angular-bypass-sanitization": "warn", + "sonarjs/no-array-delete": "warn", + "sonarjs/no-associative-arrays": "warn", + "sonarjs/no-async-constructor": "warn", + "sonarjs/no-built-in-override": "warn", + "sonarjs/no-case-label-in-switch": "warn", + "sonarjs/no-clear-text-protocols": "warn", + "sonarjs/no-code-after-done": "warn", + "sonarjs/no-collapsible-if": "warn", + "sonarjs/no-collection-size-mischeck": "warn", + "sonarjs/no-commented-code": "warn", + "sonarjs/no-control-regex": "warn", + "sonarjs/no-dead-store": "warn", + "sonarjs/no-delete-var": "warn", + "sonarjs/no-duplicate-in-composite": "warn", + "sonarjs/no-duplicate-string": "off", + "sonarjs/no-duplicated-branches": "warn", + "sonarjs/no-element-overwrite": "warn", + "sonarjs/no-empty-after-reluctant": "warn", + "sonarjs/no-empty-alternatives": "warn", + "sonarjs/no-empty-character-class": "warn", + "sonarjs/no-empty-collection": "warn", + "sonarjs/no-empty-group": "warn", + "sonarjs/no-empty-test-file": "warn", + "sonarjs/no-equals-in-for-termination": "warn", + "sonarjs/no-exclusive-tests": "warn", + "sonarjs/no-extra-arguments": "off", + "sonarjs/no-fallthrough": "warn", + "sonarjs/no-for-in-iterable": "warn", + "sonarjs/no-function-declaration-in-block": "warn", + "sonarjs/no-global-this": "warn", + "sonarjs/no-globals-shadowing": "warn", + "sonarjs/no-gratuitous-expressions": "warn", + "sonarjs/no-hardcoded-ip": "warn", + "sonarjs/no-hardcoded-passwords": "warn", + "sonarjs/no-hardcoded-secrets": "warn", + "sonarjs/no-hook-setter-in-body": "warn", + "sonarjs/no-identical-conditions": "warn", + "sonarjs/no-identical-expressions": "warn", + "sonarjs/no-identical-functions": "warn", + "sonarjs/no-ignored-exceptions": "warn", + "sonarjs/no-ignored-return": "warn", + "sonarjs/no-implicit-dependencies": "off", + "sonarjs/no-implicit-global": "warn", + "sonarjs/no-in-misuse": "warn", + "sonarjs/no-incomplete-assertions": "warn", + "sonarjs/no-inconsistent-returns": "off", + "sonarjs/no-incorrect-string-concat": "warn", + "sonarjs/no-internal-api-use": "warn", + "sonarjs/no-intrusive-permissions": "warn", + "sonarjs/no-invalid-regexp": "warn", + "sonarjs/no-invariant-returns": "warn", + "sonarjs/no-inverted-boolean-check": "warn", + "sonarjs/no-ip-forward": "warn", + "sonarjs/no-labels": "warn", + "sonarjs/no-literal-call": "warn", + "sonarjs/no-mime-sniff": "warn", + "sonarjs/no-misleading-array-reverse": "warn", + "sonarjs/no-misleading-character-class": "warn", + "sonarjs/no-mixed-content": "warn", + "sonarjs/no-nested-assignment": "warn", + "sonarjs/no-nested-conditional": "off", + "sonarjs/no-nested-functions": "off", + "sonarjs/no-nested-incdec": "warn", + "sonarjs/no-nested-switch": "warn", + "sonarjs/no-nested-template-literals": "warn", + "sonarjs/no-os-command-from-path": "warn", + "sonarjs/no-parameter-reassignment": "warn", + "sonarjs/no-primitive-wrappers": "warn", + "sonarjs/no-redundant-assignments": "warn", + "sonarjs/no-redundant-boolean": "warn", + "sonarjs/no-redundant-jump": "warn", + "sonarjs/no-redundant-optional": "warn", + "sonarjs/no-reference-error": "off", + "sonarjs/no-referrer-policy": "warn", + "sonarjs/no-regex-spaces": "warn", + "sonarjs/no-require-or-define": "warn", + "sonarjs/no-return-type-any": "warn", + "sonarjs/no-same-argument-assert": "warn", + "sonarjs/no-same-line-conditional": "warn", + "sonarjs/no-selector-parameter": "off", + "sonarjs/no-session-cookies-on-static-assets": "warn", + "sonarjs/no-skipped-tests": "warn", + "sonarjs/no-small-switch": "warn", + "sonarjs/no-sonar-comments": "warn", + "sonarjs/no-table-as-layout": "warn", + "sonarjs/no-try-promise": "warn", + "sonarjs/no-undefined-argument": "warn", + "sonarjs/no-undefined-assignment": "off", + "sonarjs/no-unenclosed-multiline-block": "warn", + "sonarjs/no-uniq-key": "warn", + "sonarjs/no-unthrown-error": "warn", + "sonarjs/no-unused-collection": "warn", + "sonarjs/no-unused-function-argument": "warn", + "sonarjs/no-unused-vars": "warn", + "sonarjs/no-use-of-empty-return-value": "warn", + "sonarjs/no-useless-catch": "warn", + "sonarjs/no-useless-increment": "warn", + "sonarjs/no-useless-intersection": "warn", + "sonarjs/no-useless-react-setstate": "warn", + "sonarjs/no-variable-usage-before-declaration": "warn", + "sonarjs/no-weak-cipher": "warn", + "sonarjs/no-weak-keys": "warn", + "sonarjs/no-wildcard-import": "off", + "sonarjs/non-existent-operator": "warn", + "sonarjs/non-number-in-arithmetic-expression": "warn", + "sonarjs/null-dereference": "warn", + "sonarjs/object-alt-content": "warn", + "sonarjs/operation-returning-nan": "warn", + "sonarjs/post-message": "warn", + "sonarjs/prefer-default-last": "warn", + "sonarjs/prefer-immediate-return": "warn", + "sonarjs/prefer-object-literal": "warn", + "sonarjs/prefer-promise-shorthand": "warn", + "sonarjs/prefer-read-only-props": "off", + "sonarjs/prefer-regexp-exec": "warn", + "sonarjs/prefer-single-boolean-return": "warn", + "sonarjs/prefer-type-guard": "warn", + "sonarjs/prefer-while": "warn", + "sonarjs/production-debug": "warn", + "sonarjs/pseudo-random": "off", + "sonarjs/public-static-readonly": "warn", + "sonarjs/publicly-writable-directories": "warn", + "sonarjs/reduce-initial-value": "warn", + "sonarjs/redundant-type-aliases": "off", + "sonarjs/regex-complexity": "warn", + "sonarjs/review-blockchain-mnemonic": "warn", + "sonarjs/session-regeneration": "warn", + "sonarjs/shorthand-property-grouping": "off", + "sonarjs/single-char-in-character-classes": "warn", + "sonarjs/single-character-alternation": "warn", + "sonarjs/slow-regex": "warn", + "sonarjs/sql-queries": "warn", + "sonarjs/stable-tests": "warn", + "sonarjs/stateful-regex": "warn", + "sonarjs/strict-transport-security": "warn", + "sonarjs/strings-comparison": "warn", + "sonarjs/table-header": "warn", + "sonarjs/table-header-reference": "warn", + "sonarjs/test-check-exception": "warn", + "sonarjs/todo-tag": "off", + "sonarjs/too-many-break-or-continue-in-loop": "off", + "sonarjs/unicode-aware-regex": "warn", + "sonarjs/unused-import": "warn", + "sonarjs/unused-named-groups": "warn", + "sonarjs/unverified-certificate": "warn", + "sonarjs/unverified-hostname": "warn", + "sonarjs/updated-const-var": "warn", + "sonarjs/updated-loop-counter": "off", + "sonarjs/use-type-alias": "warn", + "sonarjs/values-not-convertible-to-numbers": "warn", + "sonarjs/variable-name": "warn", + "sonarjs/void-use": "warn", + "sonarjs/weak-ssl": "warn", + "sonarjs/x-powered-by": "warn", + "sonarjs/xml-parser-xxe": "warn", + "react/rules-of-hooks": "warn", + "react/exhaustive-deps": "warn", + "typescript/consistent-return": "off", + "typescript/dot-notation": "warn", + "typescript/adjacent-overload-signatures": "warn", + "typescript/array-type": "warn", + "typescript/await-thenable": "warn", + "typescript/ban-ts-comment": [ + "warn", + { + "ts-expect-error": false + } + ], + "typescript/ban-tslint-comment": "off", + "typescript/class-literal-property-style": "off", + "typescript/consistent-generic-constructors": "warn", + "typescript/consistent-indexed-object-style": "warn", + "typescript/consistent-type-assertions": [ + "warn", + { + "arrayLiteralTypeAssertions": "never", + "objectLiteralTypeAssertions": "never" + } + ], + "typescript/consistent-type-definitions": "warn", + "typescript/consistent-type-exports": [ + "warn", + { + "fixMixedExportsWithInlineTypeSpecifier": true + } + ], + "typescript/consistent-type-imports": [ + "warn", + { + "fixStyle": "inline-type-imports" + } + ], + "typescript/explicit-function-return-type": "off", + "typescript/explicit-member-accessibility": "off", + "typescript/explicit-module-boundary-types": "off", + "typescript/method-signature-style": "warn", + "typescript/no-array-delete": "warn", + "typescript/no-base-to-string": "off", + "typescript/no-confusing-non-null-assertion": "off", + "typescript/no-confusing-void-expression": [ + "warn", + { + "ignoreArrowShorthand": true, + "ignoreVoidReturningFunctions": true + } + ], + "typescript/no-deprecated": "warn", + "typescript/no-duplicate-enum-values": "warn", + "typescript/no-duplicate-type-constituents": "warn", + "typescript/no-dynamic-delete": "off", + "typescript/no-empty-object-type": "warn", + "typescript/no-explicit-any": [ + "warn", + { + "fixToUnknown": true + } + ], + "typescript/no-extra-non-null-assertion": "warn", + "typescript/no-extraneous-class": "warn", + "typescript/no-floating-promises": "off", + "typescript/no-for-in-array": "warn", + "typescript/no-implied-eval": "warn", + "typescript/no-import-type-side-effects": "warn", + "typescript/no-inferrable-types": "warn", + "typescript/no-invalid-void-type": "warn", + "typescript/no-meaningless-void-operator": "warn", + "typescript/no-misused-new": "warn", + "typescript/no-misused-promises": "off", + "typescript/no-misused-spread": "warn", + "typescript/no-mixed-enums": "warn", + "typescript/no-namespace": "warn", + "typescript/no-non-null-asserted-nullish-coalescing": "warn", + "typescript/no-non-null-asserted-optional-chain": "warn", + "typescript/no-non-null-assertion": "off", + "typescript/no-redundant-type-constituents": "warn", + "typescript/no-require-imports": "warn", + "typescript/no-restricted-types": "off", + "typescript/no-this-alias": "warn", + "typescript/no-unnecessary-boolean-literal-compare": "warn", + "typescript/no-unnecessary-condition": [ + "warn", + { + "allowConstantLoopConditions": "only-allowed-literals", + "checkTypePredicates": true + } + ], + "typescript/no-unnecessary-parameter-property-assignment": "warn", + "typescript/no-unnecessary-qualifier": "off", + "typescript/no-unnecessary-template-expression": "warn", + "typescript/no-unnecessary-type-arguments": "warn", + "typescript/no-unnecessary-type-assertion": "warn", + "typescript/no-unnecessary-type-constraint": "warn", + "typescript/no-unnecessary-type-conversion": "warn", + "typescript/no-unnecessary-type-parameters": "warn", + "typescript/no-unsafe-argument": "off", + "typescript/no-unsafe-assignment": "off", + "typescript/no-unsafe-call": "off", + "typescript/no-unsafe-declaration-merging": "warn", + "typescript/no-unsafe-enum-comparison": "warn", + "typescript/no-unsafe-function-type": "warn", + "typescript/no-unsafe-member-access": "off", + "typescript/no-unsafe-return": "off", + "typescript/no-unsafe-type-assertion": "off", + "typescript/no-unsafe-unary-minus": "warn", + "typescript/no-useless-default-assignment": "warn", + "typescript/no-useless-empty-export": "warn", + "typescript/no-wrapper-object-types": "warn", + "typescript/non-nullable-type-assertion-style": "warn", + "typescript/only-throw-error": [ + "warn", + { + "allow": [ + { + "from": "package", + "package": "@tanstack/router-core", + "name": ["NotFoundError", "Redirect"] + } + ] + } + ], + "typescript/parameter-properties": "warn", + "typescript/prefer-as-const": "warn", + "typescript/prefer-enum-initializers": "warn", + "typescript/prefer-find": "warn", + "typescript/prefer-for-of": "warn", + "typescript/prefer-function-type": "warn", + "typescript/prefer-includes": "warn", + "typescript/prefer-literal-enum-member": "warn", + "typescript/prefer-namespace-keyword": "warn", + "typescript/prefer-nullish-coalescing": [ + "warn", + { + "ignoreConditionalTests": false, + "ignorePrimitives": true + } + ], + "typescript/prefer-optional-chain": "warn", + "typescript/prefer-promise-reject-errors": "warn", + "typescript/prefer-readonly": "warn", + "typescript/prefer-readonly-parameter-types": "off", + "typescript/prefer-reduce-type-parameter": "warn", + "typescript/prefer-regexp-exec": "warn", + "typescript/prefer-return-this-type": "warn", + "typescript/prefer-string-starts-ends-with": "warn", + "typescript/promise-function-async": "off", + "typescript/related-getter-setter-pairs": "off", + "typescript/require-array-sort-compare": "warn", + "typescript/require-await": "warn", + "typescript/restrict-plus-operands": [ + "warn", + { + "allowAny": false, + "allowBoolean": false, + "allowNullish": false, + "allowNumberAndString": false, + "allowRegExp": false + } + ], + "typescript/restrict-template-expressions": "off", + "typescript/return-await": "warn", + "typescript/strict-boolean-expressions": "off", + "typescript/strict-void-return": "off", + "typescript/switch-exhaustiveness-check": "warn", + "typescript/triple-slash-reference": [ + "warn", + { + "path": "never", + "types": "never", + "lib": "never" + } + ], + "typescript/unbound-method": "off", + "typescript/unified-signatures": "off", + "typescript/use-unknown-in-catch-callback-variable": "warn" + }, + "jsPlugins": ["@eslint-react/eslint-plugin", "eslint-plugin-sonarjs"], + "plugins": ["typescript", "react"] + }, + { + "files": ["test/**/*"], + "rules": { + "@eslint-react/no-create-ref": "off", + "vitest/consistent-each-for": "warn", + "vitest/consistent-test-filename": "off", + "vitest/consistent-test-it": "warn", + "vitest/consistent-vitest-vi": "warn", + "vitest/expect-expect": "off", + "vitest/hoisted-apis-on-top": "warn", + "vitest/max-expects": "off", + "vitest/max-nested-describe": "off", + "vitest/no-alias-methods": "warn", + "vitest/no-commented-out-tests": "warn", + "vitest/no-conditional-expect": "warn", + "vitest/no-conditional-in-test": "off", + "vitest/no-conditional-tests": "warn", + "vitest/no-disabled-tests": "off", + "vitest/no-duplicate-hooks": "warn", + "vitest/no-focused-tests": "warn", + "vitest/no-hooks": "off", + "vitest/no-identical-title": "warn", + "vitest/no-import-node-test": "warn", + "vitest/no-importing-vitest-globals": "warn", + "vitest/no-interpolation-in-snapshots": "off", + "vitest/no-large-snapshots": "off", + "vitest/no-mocks-import": "warn", + "vitest/no-restricted-matchers": "off", + "vitest/no-restricted-vi-methods": "off", + "vitest/no-standalone-expect": [ + "warn", + { + "additionalTestBlockFunctions": [ + "beforeAll", + "beforeEach", + "afterAll", + "afterEach", + "aroundAll", + "aroundEach" + ] + } + ], + "vitest/no-test-prefixes": "warn", + "vitest/no-test-return-statement": "warn", + "vitest/no-unneeded-async-expect-function": "warn", + "vitest/padding-around-after-all-blocks": "off", + "vitest/padding-around-test-blocks": "off", + "vitest/prefer-called-exactly-once-with": "warn", + "vitest/prefer-called-once": "warn", + "vitest/prefer-called-times": "off", + "vitest/prefer-called-with": "off", + "vitest/prefer-comparison-matcher": "warn", + "vitest/prefer-describe-function-title": "off", + "vitest/prefer-each": "warn", + "vitest/prefer-equality-matcher": "warn", + "vitest/prefer-expect-assertions": "off", + "vitest/prefer-expect-resolves": "warn", + "vitest/prefer-expect-type-of": "warn", + "vitest/prefer-hooks-in-order": "warn", + "vitest/prefer-hooks-on-top": "warn", + "vitest/prefer-import-in-mock": "warn", + "vitest/prefer-importing-vitest-globals": "off", + "vitest/prefer-lowercase-title": "off", + "vitest/prefer-mock-promise-shorthand": "warn", + "vitest/prefer-mock-return-shorthand": "warn", + "vitest/prefer-snapshot-hint": "off", + "vitest/prefer-spy-on": "warn", + "vitest/prefer-strict-boolean-matchers": "warn", + "vitest/prefer-strict-equal": "warn", + "vitest/prefer-to-be": "warn", + "vitest/prefer-to-be-falsy": "off", + "vitest/prefer-to-be-object": "warn", + "vitest/prefer-to-be-truthy": "off", + "vitest/prefer-to-contain": "warn", + "vitest/prefer-to-have-been-called-times": "warn", + "vitest/prefer-to-have-length": "warn", + "vitest/prefer-todo": "warn", + "vitest/require-awaited-expect-poll": "warn", + "vitest/require-hook": "off", + "vitest/require-local-test-context-for-concurrent-snapshots": "off", + "vitest/require-mock-type-parameters": "off", + "vitest/require-test-timeout": "off", + "vitest/require-to-throw-message": "warn", + "vitest/require-top-level-describe": "off", + "vitest/valid-describe-callback": "warn", + "vitest/valid-expect": [ + "warn", + { + "alwaysAwait": true + } + ], + "vitest/valid-expect-in-promise": "warn", + "vitest/valid-title": "warn", + "vitest/warn-todo": "warn", + "typescript/no-floating-promises": "warn" + }, + "jsPlugins": ["@eslint-react/eslint-plugin"], + "plugins": ["typescript", "vitest"] + }, + { + "files": ["test/failOnConsole.ts"], + "rules": { + "no-console": "off" + } + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 4a59117848..89ea30999a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,7 +10,11 @@ "eslint.options": { "flags": ["unstable_native_nodejs_ts_config"] }, + // ESLint is only used for markdown; JS/TS is linted by the oxc extension + "eslint.validate": ["markdown"], "eslint.problems.shortenToSingleLine": true, + "oxc.typeAware": true, + "oxc.unusedDisableDirectives": "warn", "files.readonlyInclude": { "**/routeTree.gen.ts": true }, diff --git a/AGENTS.md b/AGENTS.md index 008aa423b8..a76be47e82 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,8 +6,9 @@ npm ci # setup node --run build # library → lib/ node --run typecheck # tsc --build -node --run eslint # eslint --max-warnings 0 -node --run eslint:fix # eslint --fix +node --run lint # oxlint --max-warnings 0 --type-aware +node --run lint:fix # oxlint --fix +node --run lint:md # eslint --max-warnings 0 (markdown only) node --run format # oxfmt node --run test # vitest (browser + node) node --run test -- # single test, e.g. test/browser/rowHeight.test.ts @@ -59,4 +60,4 @@ website/ # demo site (Vite + TanStack Router) ## Validation -Run before submitting changes: `node --run typecheck`, `node --run eslint`, `node --run format`, `node --run test`. +Run before submitting changes: `node --run typecheck`, `node --run lint`, `node --run format`, `node --run test`. diff --git a/eslint.config.ts b/eslint.config.ts index 2e47a7ffae..0a0804925e 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -1,13 +1,21 @@ -import eslintReact from '@eslint-react/eslint-plugin'; import markdown from '@eslint/markdown'; -import vitest from '@vitest/eslint-plugin'; -import reactHooks from 'eslint-plugin-react-hooks'; -import sonarjs from 'eslint-plugin-sonarjs'; import { defineConfig, globalIgnores } from 'eslint/config'; -import tseslint from 'typescript-eslint'; +// ESLint is only kept for markdown linting. Everything else has moved to oxlint (`.oxlintrc.json`). +// `@eslint/markdown` is built on ESLint's language plugin API, which oxlint does not support. export default defineConfig([ - globalIgnores(['.cache', '.claude', '.nitro', '.output', '.tanstack', 'coverage', 'dist', 'lib']), + globalIgnores([ + '.cache', + '.claude', + '.nitro', + '.output', + '.tanstack', + 'coverage', + 'dist', + 'lib', + // linted by oxlint + '**/*.{js,ts,tsx}' + ]), { linterOptions: { @@ -15,1003 +23,6 @@ export default defineConfig([ } }, - { - name: 'common', - files: ['**/*.{js,ts,tsx}'], - - plugins: { - // @ts-expect-error - 'react-hooks': reactHooks, - '@eslint-react': eslintReact, - sonarjs, - '@typescript-eslint': tseslint.plugin - }, - - languageOptions: { - parser: tseslint.parser, - - parserOptions: { - ecmaVersion: 'latest', - jsxPragma: null, - projectService: true, - warnOnUnsupportedTypeScriptVersion: false - } - }, - - rules: { - // Possible Problems - // https://eslint.org/docs/latest/rules/#possible-problems - 'array-callback-return': [1, { checkForEach: true }], - 'constructor-super': 0, // covered by TS - 'for-direction': 1, - 'getter-return': 1, - 'no-async-promise-executor': 1, - 'no-await-in-loop': 0, - 'no-class-assign': 0, - 'no-compare-neg-zero': 1, - 'no-cond-assign': 1, - 'no-const-assign': 0, - 'no-constant-binary-expression': 1, - 'no-constant-condition': 1, - 'no-constructor-return': 1, - 'no-control-regex': 1, - 'no-debugger': 1, - 'no-dupe-args': 1, - 'no-dupe-class-members': 0, // replaced by @typescript-eslint/no-dupe-class-members - 'no-dupe-else-if': 1, - 'no-dupe-keys': 1, - 'no-duplicate-case': 1, - 'no-duplicate-imports': 0, - 'no-empty-character-class': 1, - 'no-empty-pattern': 1, - 'no-ex-assign': 1, - 'no-fallthrough': [1, { reportUnusedFallthroughComment: true }], - 'no-func-assign': 1, - 'no-import-assign': 1, - 'no-inner-declarations': 0, - 'no-invalid-regexp': 1, - 'no-irregular-whitespace': 1, - 'no-loss-of-precision': 1, - 'no-misleading-character-class': 1, - 'no-new-native-nonconstructor': 1, - 'no-obj-calls': 1, - 'no-promise-executor-return': 1, - 'no-prototype-builtins': 1, - 'no-self-assign': [1, { props: true }], - 'no-self-compare': 1, - 'no-setter-return': 1, - 'no-sparse-arrays': 1, - 'no-template-curly-in-string': 1, - 'no-this-before-super': 0, - 'no-unassigned-vars': 1, - 'no-undef': 0, - 'no-unexpected-multiline': 0, - 'no-unmodified-loop-condition': 1, - 'no-unreachable': 1, - 'no-unreachable-loop': 1, - 'no-unsafe-finally': 1, - 'no-unsafe-negation': [1, { enforceForOrderingRelations: true }], - 'no-unsafe-optional-chaining': [1, { disallowArithmeticOperators: true }], - 'no-unused-private-class-members': 0, // replaced by @typescript-eslint/no-unused-private-class-members - 'no-unused-vars': 0, // replaced by @typescript-eslint/no-unused-vars - 'no-use-before-define': 0, // replaced by @typescript-eslint/no-use-before-define - 'no-useless-backreference': 1, - 'require-atomic-updates': 1, - 'use-isnan': [1, { enforceForIndexOf: true }], - 'valid-typeof': [1, { requireStringLiterals: true }], - - // Suggestions - // https://eslint.org/docs/latest/rules/#suggestions - 'accessor-pairs': 1, - 'arrow-body-style': 0, - 'block-scoped-var': 1, - camelcase: 0, - 'capitalized-comments': 0, - 'class-methods-use-this': 0, // replaced by @typescript-eslint/class-methods-use-this - complexity: 0, - 'consistent-return': 0, // replaced by @typescript-eslint/consistent-return - 'consistent-this': 0, - curly: 0, - 'default-case': 1, - 'default-case-last': 1, - 'default-param-last': 0, // replaced by @typescript-eslint/default-param-last - 'dot-notation': 0, // replaced by @typescript-eslint/dot-notation - eqeqeq: [1, 'always', { null: 'ignore' }], - 'func-name-matching': 0, - 'func-names': 0, - 'func-style': 0, - 'grouped-accessor-pairs': [1, 'getBeforeSet'], - 'guard-for-in': 0, - 'id-denylist': 0, - 'id-length': 0, - 'id-match': 0, - 'init-declarations': 0, // replaced by @typescript-eslint/init-declarations - 'logical-assignment-operators': [1, 'always', { enforceForIfStatements: true }], - 'max-classes-per-file': 0, - 'max-depth': 0, - 'max-lines': 0, - 'max-lines-per-function': 0, - 'max-nested-callbacks': 0, - 'max-params': 0, // replaced by @typescript-eslint/max-params - 'max-statements': 0, - 'multiline-comment-style': 0, - 'new-cap': 0, - 'no-alert': 0, - 'no-array-constructor': 0, // replaced by @typescript-eslint/no-array-constructor - 'no-bitwise': 0, - 'no-caller': 1, - 'no-case-declarations': 1, - 'no-console': 1, - 'no-continue': 0, - 'no-delete-var': 1, - 'no-div-regex': 0, - 'no-else-return': [1, { allowElseIf: false }], - 'no-empty': [1, { allowEmptyCatch: true }], - 'no-empty-function': 0, // replaced by @typescript-eslint/no-empty-function - 'no-empty-static-block': 1, - 'no-eq-null': 0, - 'no-eval': 1, - 'no-extend-native': 1, - 'no-extra-bind': 1, - 'no-extra-boolean-cast': [1, { enforceForLogicalOperands: true }], - 'no-extra-label': 1, - 'no-global-assign': 1, - 'no-implicit-coercion': 0, - 'no-implicit-globals': 0, - 'no-implied-eval': 0, // replaced by @typescript-eslint/no-implied-eval - 'no-inline-comments': 0, - 'no-invalid-this': 0, // replaced by @typescript-eslint/no-invalid-this - 'no-iterator': 1, - 'no-label-var': 1, - 'no-labels': 1, - 'no-lone-blocks': 1, - 'no-lonely-if': 1, - 'no-loop-func': 0, // replaced by @typescript-eslint/no-loop-func - 'no-magic-numbers': 0, // replaced by @typescript-eslint/no-magic-numbers - 'no-multi-assign': 0, - 'no-multi-str': 1, - 'no-negated-condition': 0, - 'no-nested-ternary': 0, - 'no-new': 1, - 'no-new-func': 1, - 'no-new-wrappers': 1, - 'no-nonoctal-decimal-escape': 1, - 'no-object-constructor': 1, - 'no-octal': 1, - 'no-octal-escape': 1, - 'no-param-reassign': 0, - 'no-plusplus': 0, - 'no-proto': 1, - 'no-redeclare': 0, // replaced by @typescript-eslint/no-redeclare - 'no-regex-spaces': 1, - 'no-restricted-exports': 0, - 'no-restricted-globals': [ - 1, - { - name: 'Omit', - message: 'Use Omit from types instead.' - } - ], - 'no-restricted-imports': 0, // replaced by @typescript-eslint/no-restricted-imports - 'no-restricted-properties': 0, - 'no-restricted-syntax': 0, - 'no-return-assign': 0, - 'no-return-await': 0, // replaced by @typescript-eslint/return-await - 'no-script-url': 1, - 'no-sequences': [1, { allowInParentheses: false }], - 'no-shadow': 0, // replaced by @typescript-eslint/no-shadow - 'no-shadow-restricted-names': 1, - 'no-ternary': 0, - 'no-throw-literal': 0, // replaced by @typescript-eslint/only-throw-error - 'no-undef-init': 1, - 'no-undefined': 0, - 'no-underscore-dangle': 0, - 'no-unneeded-ternary': [1, { defaultAssignment: false }], - 'no-unused-expressions': 0, // replaced by @typescript-eslint/no-unused-expressions - 'no-unused-labels': 1, - 'no-useless-call': 1, - 'no-useless-catch': 1, - 'no-useless-computed-key': 1, - 'no-useless-concat': 1, - 'no-useless-constructor': 0, // replaced by @typescript-eslint/no-useless-constructor - 'no-useless-escape': 1, - 'no-useless-rename': 1, - 'no-useless-return': 1, - 'no-var': 1, - 'no-void': 1, - 'no-warning-comments': 0, - 'no-with': 1, - 'object-shorthand': [1, 'always', { avoidExplicitReturnArrows: true }], - 'one-var': [1, 'never'], - 'operator-assignment': 1, - 'prefer-arrow-callback': [1, { allowNamedFunctions: true }], - 'prefer-const': [1, { destructuring: 'all' }], - 'prefer-destructuring': 0, // replaced by @typescript-eslint/prefer-destructuring - 'prefer-exponentiation-operator': 1, - 'prefer-named-capture-group': 0, - 'prefer-numeric-literals': 1, - 'prefer-object-has-own': 1, - 'prefer-object-spread': 1, - 'prefer-promise-reject-errors': 0, // replaced by @typescript-eslint/prefer-promise-reject-errors - 'prefer-regex-literals': [1, { disallowRedundantWrapping: true }], - 'prefer-rest-params': 1, - 'prefer-spread': 1, - 'prefer-template': 1, - 'preserve-caught-error': 1, - radix: 1, - 'require-await': 0, // replaced by @typescript-eslint/require-await - 'require-unicode-regexp': 0, - 'require-yield': 1, - 'sort-imports': 0, - 'sort-keys': 0, - 'sort-vars': 0, - strict: 1, - 'symbol-description': 1, - 'vars-on-top': 0, - yoda: 0, - - // Layout & Formatting - // https://eslint.org/docs/latest/rules/#layout--formatting - 'unicode-bom': 1, - - // React Hooks - // https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks - // https://react.dev/reference/eslint-plugin-react-hooks - 'react-hooks/rules-of-hooks': 1, - 'react-hooks/exhaustive-deps': 1, - 'react-hooks/config': 1, - 'react-hooks/error-boundaries': 1, - 'react-hooks/gating': 1, - 'react-hooks/globals': 1, - 'react-hooks/immutability': 0, - 'react-hooks/incompatible-library': 1, - 'react-hooks/preserve-manual-memoization': 1, - 'react-hooks/purity': 1, - 'react-hooks/refs': 1, - 'react-hooks/set-state-in-effect': 1, - 'react-hooks/set-state-in-render': 1, - 'react-hooks/static-components': 1, - 'react-hooks/unsupported-syntax': 1, - 'react-hooks/use-memo': 1, - - // ESLint React - // https://eslint-react.xyz/docs/rules - /* -// copy all the rules from the rules table for easy pasting -copy( - Iterator.from( - document - // select all non-debug rule links - .querySelectorAll('tr a:not([href*="rules/debug"])') - ) - // map link to rule declaration - .map((a) => `'@eslint-react/${a.pathname.slice(a.pathname.lastIndexOf('/') + 1)}': 1,`) - .toArray() - .join('\n') -); - */ - '@eslint-react/error-boundaries': 1, - '@eslint-react/exhaustive-deps': 1, - '@eslint-react/globals': 1, - '@eslint-react/immutability': 1, - '@eslint-react/no-access-state-in-setstate': 1, - '@eslint-react/no-array-index-key': 0, - '@eslint-react/no-children-count': 1, - '@eslint-react/no-children-for-each': 1, - '@eslint-react/no-children-map': 1, - '@eslint-react/no-children-only': 1, - '@eslint-react/no-children-to-array': 1, - '@eslint-react/no-class-component': 1, - '@eslint-react/no-clone-element': 1, - '@eslint-react/no-component-will-mount': 1, - '@eslint-react/no-component-will-receive-props': 1, - '@eslint-react/no-component-will-update': 1, - '@eslint-react/no-context-provider': 1, - '@eslint-react/no-create-ref': 1, - '@eslint-react/no-direct-mutation-state': 1, - '@eslint-react/no-duplicate-key': 1, - '@eslint-react/no-forward-ref': 1, - '@eslint-react/no-implicit-children': 0, - '@eslint-react/no-implicit-key': 1, - '@eslint-react/no-implicit-ref': 0, - '@eslint-react/no-leaked-conditional-rendering': 1, - '@eslint-react/no-missing-component-display-name': 1, - '@eslint-react/no-missing-context-display-name': 1, - '@eslint-react/no-missing-key': 1, - '@eslint-react/no-misused-capture-owner-stack': 1, - '@eslint-react/no-nested-component-definitions': 1, - '@eslint-react/no-nested-lazy-component-declarations': 1, - '@eslint-react/no-set-state-in-component-did-mount': 1, - '@eslint-react/no-set-state-in-component-did-update': 1, - '@eslint-react/no-set-state-in-component-will-update': 1, - '@eslint-react/no-unnecessary-use-prefix': 1, - '@eslint-react/no-unsafe-component-will-mount': 1, - '@eslint-react/no-unsafe-component-will-receive-props': 1, - '@eslint-react/no-unsafe-component-will-update': 1, - '@eslint-react/no-unstable-context-value': 1, - '@eslint-react/no-unstable-default-props': 1, - '@eslint-react/no-unused-class-component-members': 1, - '@eslint-react/no-unused-props': 1, - '@eslint-react/no-unused-state': 1, - '@eslint-react/no-use-context': 1, - '@eslint-react/purity': 1, - '@eslint-react/refs': 1, - '@eslint-react/rules-of-hooks': 1, - '@eslint-react/set-state-in-effect': 0, - '@eslint-react/set-state-in-render': 1, - '@eslint-react/static-components': 1, - '@eslint-react/unsupported-syntax': 1, - '@eslint-react/use-memo': 1, - '@eslint-react/use-state': 1, - '@eslint-react/jsx-no-children-prop': 1, - '@eslint-react/jsx-no-children-prop-with-children': 1, - '@eslint-react/jsx-no-comment-textnodes': 1, - '@eslint-react/jsx-no-key-after-spread': 1, - '@eslint-react/jsx-no-leaked-dollar': 1, - '@eslint-react/jsx-no-leaked-semicolon': 1, - '@eslint-react/jsx-no-namespace': 1, - '@eslint-react/jsx-no-useless-fragment': [1, { allowExpressions: false }], - '@eslint-react/rsc-function-definition': 1, - '@eslint-react/dom-no-dangerously-set-innerhtml': 1, - '@eslint-react/dom-no-dangerously-set-innerhtml-with-children': 1, - '@eslint-react/dom-no-find-dom-node': 1, - '@eslint-react/dom-no-flush-sync': 0, - '@eslint-react/dom-no-hydrate': 1, - '@eslint-react/dom-no-missing-button-type': 1, - '@eslint-react/dom-no-missing-iframe-sandbox': 1, - '@eslint-react/dom-no-render': 1, - '@eslint-react/dom-no-render-return-value': 1, - '@eslint-react/dom-no-script-url': 1, - '@eslint-react/dom-no-string-style-prop': 1, - '@eslint-react/dom-no-unknown-property': 1, - '@eslint-react/dom-no-unsafe-iframe-sandbox': 1, - '@eslint-react/dom-no-unsafe-target-blank': 1, - '@eslint-react/dom-no-use-form-state': 1, - '@eslint-react/dom-no-void-elements-with-children': 1, - '@eslint-react/web-api-no-leaked-event-listener': 1, - '@eslint-react/web-api-no-leaked-fetch': 1, - '@eslint-react/web-api-no-leaked-intersection-observer': 1, - '@eslint-react/web-api-no-leaked-interval': 1, - '@eslint-react/web-api-no-leaked-resize-observer': 1, - '@eslint-react/web-api-no-leaked-timeout': 1, - '@eslint-react/naming-convention-context-name': 1, - '@eslint-react/naming-convention-id-name': 1, - '@eslint-react/naming-convention-ref-name': 1, - - // SonarJS rules - // https://github.com/SonarSource/SonarJS/blob/master/packages/analysis/src/jsts/rules/README.md#rules - /* -// copy all the rules from the rules table for easy pasting -copy( - Iterator.from( - document - // select rules table - .querySelector('.markdown-heading:has(> a[href="#rules"]) ~ markdown-accessiblity-table') - // select all rows with a rule - .querySelectorAll('tr:has(a)') - ) - // filter out deprecated rules - .filter((row) => row.lastElementChild.textContent === '') - // map row to rule declaration - .map((row) => `'sonarjs/${row.firstElementChild.textContent}': 1,`) - .toArray() - .join('\n') -); - */ - 'sonarjs/anchor-precedence': 1, - 'sonarjs/argument-type': 1, - 'sonarjs/arguments-order': 1, - 'sonarjs/arguments-usage': 1, - 'sonarjs/array-callback-without-return': 1, - 'sonarjs/array-constructor': 1, - 'sonarjs/arrow-function-convention': 0, - 'sonarjs/assertions-in-tests': 1, - 'sonarjs/aws-apigateway-public-api': 0, - 'sonarjs/aws-ec2-rds-dms-public': 0, - 'sonarjs/aws-ec2-unencrypted-ebs-volume': 0, - 'sonarjs/aws-efs-unencrypted': 0, - 'sonarjs/aws-iam-all-privileges': 0, - 'sonarjs/aws-iam-all-resources-accessible': 0, - 'sonarjs/aws-iam-privilege-escalation': 0, - 'sonarjs/aws-iam-public-access': 0, - 'sonarjs/aws-opensearchservice-domain': 0, - 'sonarjs/aws-rds-unencrypted-databases': 0, - 'sonarjs/aws-restricted-ip-admin-access': 0, - 'sonarjs/aws-s3-bucket-granted-access': 0, - 'sonarjs/aws-s3-bucket-insecure-http': 0, - 'sonarjs/aws-s3-bucket-public-access': 0, - 'sonarjs/aws-s3-bucket-versioning': 0, - 'sonarjs/aws-sagemaker-unencrypted-notebook': 0, - 'sonarjs/aws-sns-unencrypted-topics': 0, - 'sonarjs/aws-sqs-unencrypted-queue': 0, - 'sonarjs/bitwise-operators': 1, - 'sonarjs/block-scoped-var': 1, - 'sonarjs/bool-param-default': 1, - 'sonarjs/call-argument-line': 1, - 'sonarjs/chai-determinate-assertion': 1, - 'sonarjs/class-name': 1, - 'sonarjs/class-prototype': 1, - 'sonarjs/code-eval': 1, - 'sonarjs/cognitive-complexity': 0, - 'sonarjs/comma-or-logical-or-case': 1, - 'sonarjs/comment-regex': 1, - 'sonarjs/concise-regex': 1, - 'sonarjs/confidential-information-logging': 1, - 'sonarjs/constructor-for-side-effects': 1, - 'sonarjs/content-length': 1, - 'sonarjs/content-security-policy': 1, - 'sonarjs/cookie-no-httponly': 1, - 'sonarjs/cors': 1, - 'sonarjs/csrf': 1, - 'sonarjs/cyclomatic-complexity': 0, - 'sonarjs/declarations-in-global-scope': 0, - 'sonarjs/deprecation': 0, - 'sonarjs/destructuring-assignment-syntax': 1, - 'sonarjs/different-types-comparison': 1, - 'sonarjs/disabled-auto-escaping': 1, - 'sonarjs/disabled-resource-integrity': 1, - 'sonarjs/disabled-timeout': 1, - 'sonarjs/dompurify-unsafe-config': 1, - 'sonarjs/duplicates-in-character-class': 1, - 'sonarjs/dynamically-constructed-templates': 1, - 'sonarjs/elseif-without-else': 0, - 'sonarjs/empty-string-repetition': 1, - 'sonarjs/encryption-secure-mode': 1, - 'sonarjs/existing-groups': 1, - 'sonarjs/expression-complexity': 0, - 'sonarjs/file-header': 0, - 'sonarjs/file-name-differ-from-class': 1, - 'sonarjs/file-permissions': 1, - 'sonarjs/file-uploads': 1, - 'sonarjs/fixme-tag': 1, - 'sonarjs/for-in': 1, - 'sonarjs/for-loop-increment-sign': 1, - 'sonarjs/frame-ancestors': 1, - 'sonarjs/function-inside-loop': 1, - 'sonarjs/function-name': 0, - 'sonarjs/function-return-type': 0, - 'sonarjs/future-reserved-words': 1, - 'sonarjs/generator-without-yield': 1, - 'sonarjs/hardcoded-secret-signatures': 1, - 'sonarjs/hashing': 1, - 'sonarjs/hidden-files': 1, - 'sonarjs/in-operator-type-error': 1, - 'sonarjs/inconsistent-function-call': 1, - 'sonarjs/index-of-compare-to-positive-number': 1, - 'sonarjs/insecure-cookie': 1, - 'sonarjs/insecure-jwt-token': 1, - 'sonarjs/inverted-assertion-arguments': 1, - 'sonarjs/jsx-no-leaked-render': 1, - 'sonarjs/label-position': 1, - 'sonarjs/link-with-target-blank': 1, - 'sonarjs/max-lines': 0, - 'sonarjs/max-lines-per-function': 0, - 'sonarjs/max-switch-cases': 0, - 'sonarjs/max-union-size': 0, - 'sonarjs/misplaced-loop-counter': 1, - 'sonarjs/nested-control-flow': 0, - 'sonarjs/new-operator-misuse': 1, - 'sonarjs/no-all-duplicated-branches': 1, - 'sonarjs/no-alphabetical-sort': 1, - 'sonarjs/no-angular-bypass-sanitization': 1, - 'sonarjs/no-array-delete': 1, - 'sonarjs/no-associative-arrays': 1, - 'sonarjs/no-async-constructor': 1, - 'sonarjs/no-built-in-override': 1, - 'sonarjs/no-case-label-in-switch': 1, - 'sonarjs/no-clear-text-protocols': 1, - 'sonarjs/no-code-after-done': 1, - 'sonarjs/no-collapsible-if': 1, - 'sonarjs/no-collection-size-mischeck': 1, - 'sonarjs/no-commented-code': 1, - 'sonarjs/no-control-regex': 1, - 'sonarjs/no-dead-store': 1, - 'sonarjs/no-delete-var': 1, - 'sonarjs/no-duplicate-in-composite': 1, - 'sonarjs/no-duplicate-string': 0, - 'sonarjs/no-duplicated-branches': 1, - 'sonarjs/no-element-overwrite': 1, - 'sonarjs/no-empty-after-reluctant': 1, - 'sonarjs/no-empty-alternatives': 1, - 'sonarjs/no-empty-character-class': 1, - 'sonarjs/no-empty-collection': 1, - 'sonarjs/no-empty-group': 1, - 'sonarjs/no-empty-test-file': 1, - 'sonarjs/no-equals-in-for-termination': 1, - 'sonarjs/no-exclusive-tests': 1, - 'sonarjs/no-extra-arguments': 0, - 'sonarjs/no-fallthrough': 1, - 'sonarjs/no-for-in-iterable': 1, - 'sonarjs/no-function-declaration-in-block': 1, - 'sonarjs/no-global-this': 1, - 'sonarjs/no-globals-shadowing': 1, - 'sonarjs/no-gratuitous-expressions': 1, - 'sonarjs/no-hardcoded-ip': 1, - 'sonarjs/no-hardcoded-passwords': 1, - 'sonarjs/no-hardcoded-secrets': 1, - 'sonarjs/no-hook-setter-in-body': 1, - 'sonarjs/no-identical-conditions': 1, - 'sonarjs/no-identical-expressions': 1, - 'sonarjs/no-identical-functions': 1, - 'sonarjs/no-ignored-exceptions': 1, - 'sonarjs/no-ignored-return': 1, - 'sonarjs/no-implicit-dependencies': 0, - 'sonarjs/no-implicit-global': 1, - 'sonarjs/no-in-misuse': 1, - 'sonarjs/no-incomplete-assertions': 1, - 'sonarjs/no-inconsistent-returns': 0, - 'sonarjs/no-incorrect-string-concat': 1, - 'sonarjs/no-internal-api-use': 1, - 'sonarjs/no-intrusive-permissions': 1, - 'sonarjs/no-invalid-regexp': 1, - 'sonarjs/no-invariant-returns': 1, - 'sonarjs/no-inverted-boolean-check': 1, - 'sonarjs/no-ip-forward': 1, - 'sonarjs/no-labels': 1, - 'sonarjs/no-literal-call': 1, - 'sonarjs/no-mime-sniff': 1, - 'sonarjs/no-misleading-array-reverse': 1, - 'sonarjs/no-misleading-character-class': 1, - 'sonarjs/no-mixed-content': 1, - 'sonarjs/no-nested-assignment': 1, - 'sonarjs/no-nested-conditional': 0, - 'sonarjs/no-nested-functions': 0, - 'sonarjs/no-nested-incdec': 1, - 'sonarjs/no-nested-switch': 1, - 'sonarjs/no-nested-template-literals': 1, - 'sonarjs/no-os-command-from-path': 1, - 'sonarjs/no-parameter-reassignment': 1, - 'sonarjs/no-primitive-wrappers': 1, - 'sonarjs/no-redundant-assignments': 1, - 'sonarjs/no-redundant-boolean': 1, - 'sonarjs/no-redundant-jump': 1, - 'sonarjs/no-redundant-optional': 1, - 'sonarjs/no-reference-error': 0, - 'sonarjs/no-referrer-policy': 1, - 'sonarjs/no-regex-spaces': 1, - 'sonarjs/no-require-or-define': 1, - 'sonarjs/no-return-type-any': 1, - 'sonarjs/no-same-argument-assert': 1, - 'sonarjs/no-same-line-conditional': 1, - 'sonarjs/no-selector-parameter': 0, - 'sonarjs/no-session-cookies-on-static-assets': 1, - 'sonarjs/no-skipped-tests': 1, - 'sonarjs/no-small-switch': 1, - 'sonarjs/no-sonar-comments': 1, - 'sonarjs/no-table-as-layout': 1, - 'sonarjs/no-try-promise': 1, - 'sonarjs/no-undefined-argument': 1, - 'sonarjs/no-undefined-assignment': 0, - 'sonarjs/no-unenclosed-multiline-block': 1, - 'sonarjs/no-uniq-key': 1, - 'sonarjs/no-unthrown-error': 1, - 'sonarjs/no-unused-collection': 1, - 'sonarjs/no-unused-function-argument': 1, - 'sonarjs/no-unused-vars': 1, - 'sonarjs/no-use-of-empty-return-value': 1, - 'sonarjs/no-useless-catch': 1, - 'sonarjs/no-useless-increment': 1, - 'sonarjs/no-useless-intersection': 1, - 'sonarjs/no-useless-react-setstate': 1, - 'sonarjs/no-variable-usage-before-declaration': 1, - 'sonarjs/no-weak-cipher': 1, - 'sonarjs/no-weak-keys': 1, - 'sonarjs/no-wildcard-import': 0, - 'sonarjs/non-existent-operator': 1, - 'sonarjs/non-number-in-arithmetic-expression': 1, - 'sonarjs/null-dereference': 1, - 'sonarjs/object-alt-content': 1, - 'sonarjs/operation-returning-nan': 1, - 'sonarjs/post-message': 1, - 'sonarjs/prefer-default-last': 1, - 'sonarjs/prefer-immediate-return': 1, - 'sonarjs/prefer-object-literal': 1, - 'sonarjs/prefer-promise-shorthand': 1, - 'sonarjs/prefer-read-only-props': 0, - 'sonarjs/prefer-regexp-exec': 1, - 'sonarjs/prefer-single-boolean-return': 1, - 'sonarjs/prefer-type-guard': 1, - 'sonarjs/prefer-while': 1, - 'sonarjs/production-debug': 1, - 'sonarjs/pseudo-random': 0, - 'sonarjs/public-static-readonly': 1, - 'sonarjs/publicly-writable-directories': 1, - 'sonarjs/reduce-initial-value': 1, - 'sonarjs/redundant-type-aliases': 0, - 'sonarjs/regex-complexity': 1, - 'sonarjs/review-blockchain-mnemonic': 1, - 'sonarjs/session-regeneration': 1, - 'sonarjs/shorthand-property-grouping': 0, - 'sonarjs/single-char-in-character-classes': 1, - 'sonarjs/single-character-alternation': 1, - 'sonarjs/slow-regex': 1, - 'sonarjs/sql-queries': 1, - 'sonarjs/stable-tests': 1, - 'sonarjs/stateful-regex': 1, - 'sonarjs/strict-transport-security': 1, - 'sonarjs/strings-comparison': 1, - 'sonarjs/table-header': 1, - 'sonarjs/table-header-reference': 1, - 'sonarjs/test-check-exception': 1, - 'sonarjs/todo-tag': 0, - 'sonarjs/too-many-break-or-continue-in-loop': 0, - 'sonarjs/unicode-aware-regex': 1, - 'sonarjs/unused-import': 1, - 'sonarjs/unused-named-groups': 1, - 'sonarjs/unverified-certificate': 1, - 'sonarjs/unverified-hostname': 1, - 'sonarjs/updated-const-var': 1, - 'sonarjs/updated-loop-counter': 0, - 'sonarjs/use-type-alias': 1, - 'sonarjs/values-not-convertible-to-numbers': 1, - 'sonarjs/variable-name': 1, - 'sonarjs/void-use': 1, - 'sonarjs/weak-ssl': 1, - 'sonarjs/x-powered-by': 1, - 'sonarjs/xml-parser-xxe': 1, - - // @typescript-eslint/eslint-plugin rules - // https://typescript-eslint.io/rules/ - /* -// copy all the rules from the rules table for easy pasting -copy( - Iterator.from( - document - // select all rows with a rule - .querySelectorAll('tr:has(a)') - ) - // filter out deprecated rules - .filter((row) => row.lastElementChild.textContent === '') - // map row to rule declaration - .map((row) => `'${row.querySelector('a').textContent}': 1,`) - .toArray() - .join('\n') -); - */ - '@typescript-eslint/adjacent-overload-signatures': 1, - '@typescript-eslint/array-type': 1, - '@typescript-eslint/await-thenable': 1, - '@typescript-eslint/ban-ts-comment': [1, { 'ts-expect-error': false }], - '@typescript-eslint/ban-tslint-comment': 0, - '@typescript-eslint/class-literal-property-style': 0, - '@typescript-eslint/class-methods-use-this': 1, - '@typescript-eslint/consistent-generic-constructors': 1, - '@typescript-eslint/consistent-indexed-object-style': 1, - '@typescript-eslint/consistent-return': 0, - '@typescript-eslint/consistent-type-assertions': [ - 1, - { - arrayLiteralTypeAssertions: 'never', - objectLiteralTypeAssertions: 'never' - } - ], - '@typescript-eslint/consistent-type-definitions': 1, - '@typescript-eslint/consistent-type-exports': [ - 1, - { fixMixedExportsWithInlineTypeSpecifier: true } - ], - '@typescript-eslint/consistent-type-imports': [1, { fixStyle: 'inline-type-imports' }], - '@typescript-eslint/default-param-last': 0, - '@typescript-eslint/dot-notation': 1, - '@typescript-eslint/explicit-function-return-type': 0, - '@typescript-eslint/explicit-member-accessibility': 0, - '@typescript-eslint/explicit-module-boundary-types': 0, - '@typescript-eslint/init-declarations': 0, - '@typescript-eslint/max-params': 0, - '@typescript-eslint/member-ordering': 0, - '@typescript-eslint/method-signature-style': 1, - '@typescript-eslint/naming-convention': [ - 1, - { - selector: ['class', 'interface'], - format: ['PascalCase'] - } - ], - '@typescript-eslint/no-array-constructor': 1, - '@typescript-eslint/no-array-delete': 1, - '@typescript-eslint/no-base-to-string': 0, - '@typescript-eslint/no-confusing-non-null-assertion': 0, - '@typescript-eslint/no-confusing-void-expression': [ - 1, - { - ignoreArrowShorthand: true, - ignoreVoidReturningFunctions: true - } - ], - '@typescript-eslint/no-deprecated': 1, - '@typescript-eslint/no-dupe-class-members': 0, - '@typescript-eslint/no-duplicate-enum-values': 1, - '@typescript-eslint/no-duplicate-type-constituents': 1, - '@typescript-eslint/no-dynamic-delete': 0, - '@typescript-eslint/no-empty-function': 0, - '@typescript-eslint/no-empty-object-type': 1, - '@typescript-eslint/no-explicit-any': [1, { fixToUnknown: true }], - '@typescript-eslint/no-extra-non-null-assertion': 1, - '@typescript-eslint/no-extraneous-class': 1, - '@typescript-eslint/no-floating-promises': 0, - '@typescript-eslint/no-for-in-array': 1, - '@typescript-eslint/no-implied-eval': 1, - '@typescript-eslint/no-import-type-side-effects': 1, - '@typescript-eslint/no-inferrable-types': 1, - '@typescript-eslint/no-invalid-this': 0, - '@typescript-eslint/no-invalid-void-type': 1, - '@typescript-eslint/no-loop-func': 0, - '@typescript-eslint/no-magic-numbers': 0, - '@typescript-eslint/no-meaningless-void-operator': 1, - '@typescript-eslint/no-misused-new': 1, - '@typescript-eslint/no-misused-promises': 0, - '@typescript-eslint/no-misused-spread': 1, - '@typescript-eslint/no-mixed-enums': 1, - '@typescript-eslint/no-namespace': 1, - '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 1, - '@typescript-eslint/no-non-null-asserted-optional-chain': 1, - '@typescript-eslint/no-non-null-assertion': 0, - '@typescript-eslint/no-redeclare': 1, - '@typescript-eslint/no-redundant-type-constituents': 1, - '@typescript-eslint/no-require-imports': 1, - '@typescript-eslint/no-restricted-imports': 0, - '@typescript-eslint/no-restricted-types': 0, - '@typescript-eslint/no-shadow': 0, - '@typescript-eslint/no-this-alias': 1, - '@typescript-eslint/no-unnecessary-boolean-literal-compare': 1, - '@typescript-eslint/no-unnecessary-condition': [ - 1, - { - allowConstantLoopConditions: 'only-allowed-literals', - checkTypePredicates: true - } - ], - '@typescript-eslint/no-unnecessary-parameter-property-assignment': 1, - '@typescript-eslint/no-unnecessary-qualifier': 0, - '@typescript-eslint/no-unnecessary-template-expression': 1, - '@typescript-eslint/no-unnecessary-type-arguments': 1, - '@typescript-eslint/no-unnecessary-type-assertion': 1, - '@typescript-eslint/no-unnecessary-type-constraint': 1, - '@typescript-eslint/no-unnecessary-type-conversion': 1, - '@typescript-eslint/no-unnecessary-type-parameters': 1, - '@typescript-eslint/no-unsafe-argument': 0, - '@typescript-eslint/no-unsafe-assignment': 0, - '@typescript-eslint/no-unsafe-call': 0, - '@typescript-eslint/no-unsafe-declaration-merging': 1, - '@typescript-eslint/no-unsafe-enum-comparison': 1, - '@typescript-eslint/no-unsafe-function-type': 1, - '@typescript-eslint/no-unsafe-member-access': 0, - '@typescript-eslint/no-unsafe-return': 0, - '@typescript-eslint/no-unsafe-type-assertion': 0, - '@typescript-eslint/no-unsafe-unary-minus': 1, - '@typescript-eslint/no-unused-expressions': [1, { enforceForJSX: true }], - '@typescript-eslint/no-unused-private-class-members': 1, - '@typescript-eslint/no-unused-vars': [ - 1, - { - enableAutofixRemoval: { imports: true }, - ignoreRestSiblings: true - } - ], - '@typescript-eslint/no-use-before-define': 0, - '@typescript-eslint/no-useless-constructor': 1, - '@typescript-eslint/no-useless-default-assignment': 1, - '@typescript-eslint/no-useless-empty-export': 1, - '@typescript-eslint/no-wrapper-object-types': 1, - '@typescript-eslint/non-nullable-type-assertion-style': 1, - '@typescript-eslint/only-throw-error': [ - 1, - { - allow: [ - { - from: 'package', - package: '@tanstack/router-core', - name: ['NotFoundError', 'Redirect'] - } - ] - } - ], - '@typescript-eslint/parameter-properties': 1, - '@typescript-eslint/prefer-as-const': 1, - '@typescript-eslint/prefer-destructuring': [ - 1, - { - VariableDeclarator: { - array: false, - object: true - }, - AssignmentExpression: { - array: false, - object: false - } - } - ], - '@typescript-eslint/prefer-enum-initializers': 1, - '@typescript-eslint/prefer-find': 1, - '@typescript-eslint/prefer-for-of': 1, - '@typescript-eslint/prefer-function-type': 1, - '@typescript-eslint/prefer-includes': 1, - '@typescript-eslint/prefer-literal-enum-member': 1, - '@typescript-eslint/prefer-namespace-keyword': 1, - '@typescript-eslint/prefer-nullish-coalescing': [ - 1, - { - ignoreConditionalTests: false, - ignorePrimitives: true - } - ], - '@typescript-eslint/prefer-optional-chain': 1, - '@typescript-eslint/prefer-promise-reject-errors': 1, - '@typescript-eslint/prefer-readonly': 1, - '@typescript-eslint/prefer-readonly-parameter-types': 0, - '@typescript-eslint/prefer-reduce-type-parameter': 1, - '@typescript-eslint/prefer-regexp-exec': 1, - '@typescript-eslint/prefer-return-this-type': 1, - '@typescript-eslint/prefer-string-starts-ends-with': 1, - '@typescript-eslint/promise-function-async': 0, - '@typescript-eslint/related-getter-setter-pairs': 0, - '@typescript-eslint/require-array-sort-compare': 1, - '@typescript-eslint/require-await': 1, - '@typescript-eslint/restrict-plus-operands': [ - 1, - { - allowAny: false, - allowBoolean: false, - allowNullish: false, - allowNumberAndString: false, - allowRegExp: false - } - ], - '@typescript-eslint/restrict-template-expressions': 0, - '@typescript-eslint/return-await': 1, - '@typescript-eslint/strict-boolean-expressions': 0, - '@typescript-eslint/strict-void-return': 0, - '@typescript-eslint/switch-exhaustiveness-check': 1, - '@typescript-eslint/triple-slash-reference': [ - 1, - { path: 'never', types: 'never', lib: 'never' } - ], - '@typescript-eslint/unbound-method': 0, // replaced by vitest/unbound-method - '@typescript-eslint/unified-signatures': 0, - '@typescript-eslint/use-unknown-in-catch-callback-variable': 1 - } - }, - - { - name: 'test', - - files: ['test/**/*'], - - plugins: { - vitest - }, - - rules: { - '@typescript-eslint/no-floating-promises': 1, - - '@eslint-react/component-hook-factories': 0, - '@eslint-react/no-create-ref': 0, - - // https://github.com/vitest-dev/eslint-plugin-vitest#rules - /* -// copy all the rules from the rules table for easy pasting -copy( - Iterator.from( - document - // select rules table - .querySelector('.markdown-heading:has(> a[href="#rules"]) ~ markdown-accessiblity-table') - // select all rows with a rule - .querySelectorAll('tr:has(a)') - ) - // filter out deprecated rules - .filter((row) => row.lastElementChild.textContent === '') - // map row to rule declaration - .map((row) => `'vitest/${row.firstElementChild.textContent}': 1,`) - .toArray() - .join('\n') -); - */ - 'vitest/consistent-each-for': 1, - 'vitest/consistent-test-filename': 0, - 'vitest/consistent-test-it': 1, - 'vitest/consistent-vitest-vi': 1, - 'vitest/expect-expect': 0, - 'vitest/hoisted-apis-on-top': 1, - 'vitest/max-expects': 0, - 'vitest/max-nested-describe': 0, - 'vitest/no-alias-methods': 1, - 'vitest/no-commented-out-tests': 1, - 'vitest/no-conditional-expect': 1, - 'vitest/no-conditional-in-test': 0, - 'vitest/no-conditional-tests': 1, - 'vitest/no-disabled-tests': 0, - 'vitest/no-duplicate-hooks': 1, - 'vitest/no-focused-tests': [1, { fixable: false }], - 'vitest/no-hooks': 0, - 'vitest/no-identical-title': 1, - 'vitest/no-import-node-test': 1, - 'vitest/no-importing-vitest-globals': 1, - 'vitest/no-interpolation-in-snapshots': 0, - 'vitest/no-large-snapshots': 0, - 'vitest/no-mocks-import': 1, - 'vitest/no-restricted-matchers': 0, - 'vitest/no-restricted-vi-methods': 0, - 'vitest/no-standalone-expect': [ - 1, - { - additionalTestBlockFunctions: [ - 'beforeAll', - 'beforeEach', - 'afterAll', - 'afterEach', - 'aroundAll', - 'aroundEach' - ] - } - ], - 'vitest/no-test-prefixes': 1, - 'vitest/no-test-return-statement': 1, - 'vitest/no-unneeded-async-expect-function': 1, - 'vitest/padding-around-after-all-blocks': 0, - 'vitest/padding-around-after-each-blocks': 0, - 'vitest/padding-around-all': 0, - 'vitest/padding-around-before-all-blocks': 0, - 'vitest/padding-around-before-each-blocks': 0, - 'vitest/padding-around-describe-blocks': 0, - 'vitest/padding-around-expect-groups': 0, - 'vitest/padding-around-test-blocks': 0, - 'vitest/prefer-called-exactly-once-with': 1, - 'vitest/prefer-called-once': 1, - 'vitest/prefer-called-times': 0, - 'vitest/prefer-called-with': 0, - 'vitest/prefer-comparison-matcher': 1, - 'vitest/prefer-describe-function-title': 0, - 'vitest/prefer-each': 1, - 'vitest/prefer-equality-matcher': 1, - 'vitest/prefer-expect-assertions': 0, - 'vitest/prefer-expect-resolves': 1, - 'vitest/prefer-expect-type-of': 1, - 'vitest/prefer-hooks-in-order': 1, - 'vitest/prefer-hooks-on-top': 1, - 'vitest/prefer-import-in-mock': 1, - 'vitest/prefer-importing-vitest-globals': 0, - 'vitest/prefer-lowercase-title': 0, - 'vitest/prefer-mock-promise-shorthand': 1, - 'vitest/prefer-mock-return-shorthand': 1, - 'vitest/prefer-snapshot-hint': 0, - 'vitest/prefer-spy-on': 1, - 'vitest/prefer-strict-boolean-matchers': 1, - 'vitest/prefer-strict-equal': 1, - 'vitest/prefer-to-be': 1, - 'vitest/prefer-to-be-falsy': 0, - 'vitest/prefer-to-be-object': 1, - 'vitest/prefer-to-be-truthy': 0, - 'vitest/prefer-to-contain': 1, - 'vitest/prefer-to-have-been-called-times': 1, - 'vitest/prefer-to-have-length': 1, - 'vitest/prefer-todo': 1, - 'vitest/prefer-vi-mocked': 1, - 'vitest/require-awaited-expect-poll': 1, - 'vitest/require-hook': 0, - 'vitest/require-local-test-context-for-concurrent-snapshots': 0, - 'vitest/require-mock-type-parameters': 0, - 'vitest/require-test-timeout': 0, - 'vitest/require-to-throw-message': 1, - 'vitest/require-top-level-describe': 0, - 'vitest/unbound-method': 0, - 'vitest/valid-describe-callback': 1, - 'vitest/valid-expect': [1, { alwaysAwait: true }], - 'vitest/valid-expect-in-promise': 1, - 'vitest/valid-title': 1, - 'vitest/warn-todo': 1 - } - }, - - { - name: 'tools', - - files: ['test/failOnConsole.ts'], - - rules: { - 'no-console': 0 - } - }, - { name: 'markdown', files: ['**/*.md'], diff --git a/package-lock.json b/package-lock.json index 3cbccf9510..12ae67f571 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,21 +22,20 @@ "@vitejs/plugin-react": "^6.0.3", "@vitest/browser-playwright": "^4.1.5", "@vitest/coverage-istanbul": "^4.1.5", - "@vitest/eslint-plugin": "^1.6.16", "clsx": "^2.1.1", "ecij": "^0.4.1", "eslint": "^10.2.1", - "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-sonarjs": "^4.0.3", "jspdf": "^4.2.0", "jspdf-autotable": "^5.0.7", "oxfmt": "0.59.0", + "oxlint": "^1.76.0", + "oxlint-tsgolint": "^7.0.2001", "playwright": "~1.61.0", "react": "^19.2.7", "react-dom": "^19.2.7", "tsdown": "^0.22.7", "typescript": "npm:@typescript/typescript6@^6.0.2", - "typescript-eslint": "^8.59.0", "vite": "^8.1.0", "vitest": "^4.1.5", "vitest-browser-react": "^2.2.0" @@ -1125,6 +1124,437 @@ "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@oxlint-tsgolint/darwin-arm64": { + "version": "7.0.2001", + "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/darwin-arm64/-/darwin-arm64-7.0.2001.tgz", + "integrity": "sha512-CUJEdbSZ54+Xy9OXqOhWLTKZKV0BBiV7C2i/ygyVmXtkUNXx5YCzN8DpSSshTAKktoL7S+tnQ/ftFG/i7X896w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxlint-tsgolint/darwin-x64": { + "version": "7.0.2001", + "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/darwin-x64/-/darwin-x64-7.0.2001.tgz", + "integrity": "sha512-pXfBb5BqONCcgrXQNUZWXgiYmRSWJzd97S8i41VVOh6ut0tyo+cJ5FKFpczDHxiVNfj/3e7c9B4MtztNdpIVCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxlint-tsgolint/linux-arm64": { + "version": "7.0.2001", + "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/linux-arm64/-/linux-arm64-7.0.2001.tgz", + "integrity": "sha512-roP7zujb/QDPzDwEKsFFpzNHHy91/Y7oX9vQXk78ekyZtcQj1QXDIMH33gjDdHBfRl4K9pZ36xhRgrP4Zr+R8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint-tsgolint/linux-x64": { + "version": "7.0.2001", + "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/linux-x64/-/linux-x64-7.0.2001.tgz", + "integrity": "sha512-UDezNqdECVmngu2TPnjaS1YoAmcTaBoI5lV9vk3VahBxoi+I5r9k3iJTT7qZoYWOXTD/7T7bNcwRgrocR6BscQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint-tsgolint/win32-arm64": { + "version": "7.0.2001", + "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/win32-arm64/-/win32-arm64-7.0.2001.tgz", + "integrity": "sha512-uJZhqB6pdXLuN+AD1F5082byyQti/NPmJA77GtcFlmT2HzRelqbNls3SaIqxpjdFgvSBF9g0yOKGBkGFg7kX8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxlint-tsgolint/win32-x64": { + "version": "7.0.2001", + "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/win32-x64/-/win32-x64-7.0.2001.tgz", + "integrity": "sha512-FkDRm8hx9OwzGQqyWG1tO5QrTLRApff9DzSgpz9QZau37BR8d1VYKOxMLGf6shPZntJFoTwIIJYT68VndYDCog==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.76.0.tgz", + "integrity": "sha512-ZHIE5Zt9AsPDcY4nOlofXt0YfneEeo+QrKMPcPzLf2Z6Q8VtV2W73d7SFJ920WUwyik783u/doKCs3KXdwG+7w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-android-arm64": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.76.0.tgz", + "integrity": "sha512-shm/ngQilHK6bs+ElJWa4oHfNj5vL1Gl/iVEJldTQjpr0/67oSgr0KUpbmcnLig5Fo0v/l6j2567A7TOL89ONA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-arm64": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.76.0.tgz", + "integrity": "sha512-rvJmrAPKSQ9aWJ6wIS6CK2tJjwzfW0ApQH9qokq6sfDvmHwoyIHxHFMq7z7i7GiV6fdE6s8qvBqWKPTu8RmT6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-x64": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.76.0.tgz", + "integrity": "sha512-U/zYdb7VYKGY6pA9Vd2rYl9O/HlCylcOlb5PGPvVLtg+oLGsk6H3XGKEMHKyqD3nmmtmlmwb/8SwU2vfSAtvMw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-freebsd-x64": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.76.0.tgz", + "integrity": "sha512-WvKG9CAriuo0XNiFzpXjDngUZcRGFNpaK2kLyMUsnJlShxkT96u+BpJQ3KqdQwGOrvI14L6V8bAwXwAYNNY6Jg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-gnueabihf": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.76.0.tgz", + "integrity": "sha512-qJ5+RH99TqFRq3UCDxkW0zJJu9c+OAHFY72vGlxZLEpuO+MpKo3POgqb8sYipL9KYm8XY6ofb0HsOuvY6hQNqQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-musleabihf": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.76.0.tgz", + "integrity": "sha512-PvPCVptkgVARsucgIqFQQcSmJ6xc6GtnVB5bRBekRahTc9eObMtjHfMjy5M+C2tHt5UCMttWM9RuSk/H9NqYeg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-gnu": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.76.0.tgz", + "integrity": "sha512-3KeFDx8Bu4HPAXbuHZOr/oHvN+QT+JQhMw/NYPz7Z071xLSsG27Jfh9PIQVEY7hk1I+jr43ExqRIeJ6VKk2yLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.76.0.tgz", + "integrity": "sha512-oPFkkKTgl0K/EIg9fQ8oA3IGcI05/Mq1en04iFa41mmNPT+6KEiByVazTOZZJiHMBBrbsns1YJ2e1Scqwzesjw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.76.0.tgz", + "integrity": "sha512-gN7yZ0eqflA5Fhf1wvHxGUltIV3FsvmB1zhNMDEK9vSHhc7E6qg9CuPeBgPZab66Tjzq6w6kHAtNEvnTHf4cyw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.76.0.tgz", + "integrity": "sha512-S/HqMbn22mQrjtErUxEoS/a55u8kIeXvreIxiJu5G7Le3UecEd6SQZxrDIpuhtgaFnsY/nVra3ytP+pRljDilA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.76.0.tgz", + "integrity": "sha512-ZIga3097VJZolGZk6SrIAUokIGfRkxRlhiHDUznZptGBfwrhD7pNfD1rzEzsCwvk/1DX0A1bLz+liuNh5QKIVQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.76.0.tgz", + "integrity": "sha512-ZGiiA7pFzMJSyMWYZTVlPgbTsx+Vl8ihLGMIujPwaslUF7kIPPWAbVmAlTc+9lWDV+DCiB8Ikixu+lSHeOIIWQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.76.0.tgz", + "integrity": "sha512-JLiy5WuvEBFTT6ErIFV35SLzi0R7Iri6MKU6dZbTxfIx8pndbbPs3Mj780nMipBFcPkti+okAPOJ9POKkHFEgg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.76.0.tgz", + "integrity": "sha512-z7lgKQtbo/I1NIe8G5NHLesxJDv0tRSUWTpXKb9Pm3E9nKFKfO4IOSDtFroKgXtOYb0jQbcdH+0wzTyMXVes+A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.76.0.tgz", + "integrity": "sha512-JOjKymIpb9QcYfEhZsN6h4V9Ivd474W38cNIBRv6bg2TbIvogbMTH0Mg6YWW9TiRDqfcX+/Hyfsbo5vcSE5guQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-arm64-msvc": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.76.0.tgz", + "integrity": "sha512-pqDWZiwcmByWUEm1NFUBNiT6aentCcaoMWJv0HbXEmuYermJ4sg8ppVrshubYP2MZ6SHccJJcpr6x469PuDFIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-ia32-msvc": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.76.0.tgz", + "integrity": "sha512-Ba0O659kgMv6pwO3z9PdO+K3aMxQRaw9HnG+e6AtOfgwcKFvYilciQYBoUBmxfQvOCKZe1SwjMkuB542NkuDMQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-x64-msvc": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.76.0.tgz", + "integrity": "sha512-5qcirPHO8nKfkoowEVWtpAoVTcYDy6g0UT0NGic450Qv8J2NrOqg4uQ8QppRP4MDTC7Xx47lbZnmadTH03CGGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", @@ -1830,70 +2260,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.65.0.tgz", - "integrity": "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/type-utils": "8.65.0", - "@typescript-eslint/utils": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.65.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.65.0.tgz", - "integrity": "sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, "node_modules/@typescript-eslint/project-service": { "version": "8.65.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz", @@ -2575,37 +2941,6 @@ "vitest": "4.1.10" } }, - "node_modules/@vitest/eslint-plugin": { - "version": "1.6.23", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.23.tgz", - "integrity": "sha512-CbrXxQpIUMbeyylGlxaxTgnWYM44et4Nx58swl7+vrTyC9Ttx+hQoy8BGCregbbZ08K5qFhRHeoad1VvERUbkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "^8.58.0", - "@typescript-eslint/utils": "^8.58.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "*", - "eslint": ">=8.57.0", - "typescript": ">=5.0.0", - "vitest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "typescript": { - "optional": true - }, - "vitest": { - "optional": true - } - } - }, "node_modules/@vitest/expect": { "version": "4.1.10", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", @@ -3677,26 +4012,6 @@ "typescript": "*" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", - "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" - } - }, "node_modules/eslint-plugin-react-jsx": { "version": "5.18.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-jsx/-/eslint-plugin-react-jsx-5.18.0.tgz", @@ -4208,23 +4523,6 @@ "node": ">=8" } }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true, - "license": "MIT" - }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hermes-estree": "0.25.1" - } - }, "node_modules/hookable": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/hookable/-/hookable-6.1.1.tgz", @@ -5939,6 +6237,73 @@ } } }, + "node_modules/oxlint": { + "version": "1.76.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.76.0.tgz", + "integrity": "sha512-6QoFioEU4fNdiUx/2Eo6TRd6NG7H7njnRCz8rhB66cZmMHDTqcm1Rjvl8Wry+ZTQMBAmyb4Mlf62Mk5X+eHSOw==", + "dev": true, + "license": "MIT", + "bin": { + "oxlint": "bin/oxlint" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.76.0", + "@oxlint/binding-android-arm64": "1.76.0", + "@oxlint/binding-darwin-arm64": "1.76.0", + "@oxlint/binding-darwin-x64": "1.76.0", + "@oxlint/binding-freebsd-x64": "1.76.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.76.0", + "@oxlint/binding-linux-arm-musleabihf": "1.76.0", + "@oxlint/binding-linux-arm64-gnu": "1.76.0", + "@oxlint/binding-linux-arm64-musl": "1.76.0", + "@oxlint/binding-linux-ppc64-gnu": "1.76.0", + "@oxlint/binding-linux-riscv64-gnu": "1.76.0", + "@oxlint/binding-linux-riscv64-musl": "1.76.0", + "@oxlint/binding-linux-s390x-gnu": "1.76.0", + "@oxlint/binding-linux-x64-gnu": "1.76.0", + "@oxlint/binding-linux-x64-musl": "1.76.0", + "@oxlint/binding-openharmony-arm64": "1.76.0", + "@oxlint/binding-win32-arm64-msvc": "1.76.0", + "@oxlint/binding-win32-ia32-msvc": "1.76.0", + "@oxlint/binding-win32-x64-msvc": "1.76.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=7.0.2001", + "vite-plus": "*" + }, + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/oxlint-tsgolint": { + "version": "7.0.2001", + "resolved": "https://registry.npmjs.org/oxlint-tsgolint/-/oxlint-tsgolint-7.0.2001.tgz", + "integrity": "sha512-KjK/XLcXr1DSyonKhsuFqJRiuKqcyG9j3LJ8nkOsrLzGvodBPqzHOKauy10asLMDI0sUpvb+1sxlzff3udZvfg==", + "dev": true, + "license": "MIT", + "bin": { + "tsgolint": "bin/tsgolint.js" + }, + "optionalDependencies": { + "@oxlint-tsgolint/darwin-arm64": "7.0.2001", + "@oxlint-tsgolint/darwin-x64": "7.0.2001", + "@oxlint-tsgolint/linux-arm64": "7.0.2001", + "@oxlint-tsgolint/linux-x64": "7.0.2001", + "@oxlint-tsgolint/win32-arm64": "7.0.2001", + "@oxlint-tsgolint/win32-x64": "7.0.2001" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -6805,30 +7170,6 @@ "tsc6": "bin/tsc6" } }, - "node_modules/typescript-eslint": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.65.0.tgz", - "integrity": "sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.65.0", - "@typescript-eslint/parser": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/utils": "8.65.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, "node_modules/unconfig-core": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.5.0.tgz", @@ -7371,19 +7712,6 @@ "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/zod-validation-error": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", - "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - } - }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index be0a15d7ec..c2f850aefd 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,10 @@ "test:ci:update": "vitest run --project visual --update", "format": "oxfmt", "format:check": "oxfmt --check", - "eslint": "eslint --max-warnings 0 --cache --cache-location .cache/eslint --cache-strategy content --flag unstable_native_nodejs_ts_config", - "eslint:fix": "node --run eslint -- --fix", + "lint": "oxlint --max-warnings 0 --type-aware --report-unused-disable-directives", + "lint:fix": "node --run lint -- --fix", + "lint:md": "eslint --max-warnings 0 --cache --cache-location .cache/eslint --cache-strategy content --flag unstable_native_nodejs_ts_config", + "lint:md:fix": "node --run lint:md -- --fix", "typecheck": "tsc --build" }, "devDependencies": { @@ -60,21 +62,20 @@ "@vitejs/plugin-react": "^6.0.3", "@vitest/browser-playwright": "^4.1.5", "@vitest/coverage-istanbul": "^4.1.5", - "@vitest/eslint-plugin": "^1.6.16", "clsx": "^2.1.1", "ecij": "^0.4.1", "eslint": "^10.2.1", - "eslint-plugin-react-hooks": "^7.1.1", "eslint-plugin-sonarjs": "^4.0.3", "jspdf": "^4.2.0", "jspdf-autotable": "^5.0.7", "oxfmt": "0.59.0", + "oxlint": "^1.76.0", + "oxlint-tsgolint": "^7.0.2001", "playwright": "~1.61.0", "react": "^19.2.7", "react-dom": "^19.2.7", "tsdown": "^0.22.7", "typescript": "npm:@typescript/typescript6@^6.0.2", - "typescript-eslint": "^8.59.0", "vite": "^8.1.0", "vitest": "^4.1.5", "vitest-browser-react": "^2.2.0" diff --git a/src/globals.d.ts b/src/globals.d.ts index b8e33ced84..50b3a3a08f 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -1,6 +1,6 @@ declare module 'react' { - // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style interface CSSProperties { + // eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style [key: `--${string}`]: string | number | undefined; } } diff --git a/src/types.ts b/src/types.ts index fed440f9f3..8c8066b747 100644 --- a/src/types.ts +++ b/src/types.ts @@ -358,6 +358,8 @@ export interface RenderCheckboxProps extends Pick< React.ComponentProps<'input'>, 'aria-label' | 'aria-labelledby' | 'checked' | 'tabIndex' | 'disabled' > { + // `| undefined` is required by `exactOptionalPropertyTypes`, which oxlint's JS plugins cannot see + // eslint-disable-next-line sonarjs/no-redundant-optional indeterminate?: boolean | undefined; onChange: (checked: boolean, shift: boolean) => void; } diff --git a/test/browser/scrollToCell.test.tsx b/test/browser/scrollToCell.test.tsx index f983e7d92e..44c7e8aba8 100644 --- a/test/browser/scrollToCell.test.tsx +++ b/test/browser/scrollToCell.test.tsx @@ -118,6 +118,8 @@ function validateCellVisibility(name: string, isVisible: boolean) { const cell = page.getCell({ name }); if (isVisible) { + // this helper is not a test block, but oxlint's implementation flags it anyway + // eslint-disable-next-line vitest/no-conditional-expect return expect.element(cell).toBeVisible(); }