UNPKG

@shayanthenerd/eslint-config

Version:

A modern, flexible ESLint configuration for enforcing best practices and maintaining a consistent coding style

166 lines (165 loc) 7.96 kB
import { isEnabled } from "../utils/isEnabled.mjs"; import { defaultOptions } from "../helpers/options/defaultOptions.mjs"; //#region src/rules/react.ts const commonCallees = [ "classnames", "classNames", "clsx", "cx", "cva", "cn", "twMerge", "twJoin", "classcat", "ctl" ]; function getReactRules(options) { const { react, unicorn, tailwind, baseline, stylistic } = options.configs; const { imageComponents: userImageComponents, anchorComponents: userAnchorComponents, headingComponents: userHeadingComponents } = isEnabled(react) && isEnabled(react.accessibility) ? react.accessibility : defaultOptions.configs.react.accessibility; const jsxA11yRules = { "jsx-a11y/alt-text": ["error", { img: userImageComponents }], "jsx-a11y/anchor-ambiguous-text": "warn", "jsx-a11y/anchor-has-content": ["error", { components: userAnchorComponents }], "jsx-a11y/anchor-is-valid": ["error", { specialLink: ["to"], components: userAnchorComponents }], "jsx-a11y/aria-activedescendant-has-tabindex": "error", "jsx-a11y/aria-props": "error", "jsx-a11y/aria-proptypes": "error", "jsx-a11y/aria-role": "error", "jsx-a11y/aria-unsupported-elements": "error", "jsx-a11y/autocomplete-valid": "error", "jsx-a11y/click-events-have-key-events": "error", "jsx-a11y/control-has-associated-label": "error", "jsx-a11y/heading-has-content": ["error", { components: userHeadingComponents }], "jsx-a11y/html-has-lang": "error", "jsx-a11y/iframe-has-title": "error", "jsx-a11y/img-redundant-alt": ["error", { components: userImageComponents }], "jsx-a11y/interactive-supports-focus": "error", "jsx-a11y/label-has-associated-control": "error", "jsx-a11y/lang": "error", "jsx-a11y/media-has-caption": "error", "jsx-a11y/mouse-events-have-key-events": "error", "jsx-a11y/no-access-key": "warn", "jsx-a11y/no-aria-hidden-on-focusable": "error", "jsx-a11y/no-autofocus": "warn", "jsx-a11y/no-distracting-elements": "warn", "jsx-a11y/no-interactive-element-to-noninteractive-role": "error", "jsx-a11y/no-noninteractive-element-interactions": "error", "jsx-a11y/no-noninteractive-element-to-interactive-role": "error", "jsx-a11y/no-noninteractive-tabindex": "error", "jsx-a11y/no-redundant-roles": "warn", "jsx-a11y/no-static-element-interactions": "warn", "jsx-a11y/prefer-tag-over-role": "warn", "jsx-a11y/role-has-required-aria-props": "warn", "jsx-a11y/role-supports-aria-props": "warn", "jsx-a11y/scope": "error", "jsx-a11y/tabindex-no-positive": "error" }; const reactAndHtmlReactRules = { /*** @eslint/react ***/ "@eslint-react/error-boundaries": "error", "@eslint-react/exhaustive-deps": "error", "@eslint-react/globals": "error", "@eslint-react/immutability": "error", "@eslint-react/no-access-state-in-setstate": "error", "@eslint-react/no-array-index-key": "warn", "@eslint-react/no-children-count": "error", "@eslint-react/no-children-for-each": "error", "@eslint-react/no-children-map": "error", "@eslint-react/no-children-only": "error", "@eslint-react/no-children-to-array": "error", "@eslint-react/no-class-component": "warn", "@eslint-react/no-clone-element": "error", "@eslint-react/no-component-will-mount": "error", "@eslint-react/no-component-will-receive-props": "error", "@eslint-react/no-component-will-update": "error", "@eslint-react/no-context-provider": "error", "@eslint-react/no-create-ref": "error", "@eslint-react/no-direct-mutation-state": "error", "@eslint-react/no-duplicate-key": "error", "@eslint-react/no-forward-ref": "warn", "@eslint-react/no-implicit-children": "warn", "@eslint-react/no-implicit-key": "warn", "@eslint-react/no-implicit-ref": "warn", "@eslint-react/no-leaked-conditional-rendering": "error", "@eslint-react/no-missing-component-display-name": "warn", "@eslint-react/no-missing-context-display-name": "warn", "@eslint-react/no-missing-key": "error", "@eslint-react/no-misused-capture-owner-stack": "error", "@eslint-react/no-nested-component-definitions": "error", "@eslint-react/no-nested-lazy-component-declarations": "error", "@eslint-react/no-set-state-in-component-did-mount": "error", "@eslint-react/no-set-state-in-component-did-update": "error", "@eslint-react/no-set-state-in-component-will-update": "error", "@eslint-react/no-unnecessary-use-prefix": "warn", "@eslint-react/no-unsafe-component-will-mount": "error", "@eslint-react/no-unsafe-component-will-receive-props": "error", "@eslint-react/no-unsafe-component-will-update": "error", "@eslint-react/no-unstable-context-value": "error", "@eslint-react/no-unstable-default-props": "error", "@eslint-react/no-unused-class-component-members": "error", "@eslint-react/no-unused-props": "error", "@eslint-react/no-unused-state": "error", "@eslint-react/no-use-context": "warn", "@eslint-react/purity": "error", "@eslint-react/refs": "error", "@eslint-react/rules-of-hooks": "error", "@eslint-react/set-state-in-effect": "warn", "@eslint-react/set-state-in-render": "error", "@eslint-react/static-components": "warn", "@eslint-react/unsupported-syntax": "error", "@eslint-react/use-memo": "error", "@eslint-react/use-state": "warn", "@eslint-react/jsx-no-children-prop": "warn", "@eslint-react/jsx-no-children-prop-with-children": "error", "@eslint-react/jsx-no-comment-textnodes": "error", "@eslint-react/jsx-no-key-after-spread": "warn", "@eslint-react/jsx-no-namespace": "error", "@eslint-react/jsx-no-useless-fragment": "warn", "@eslint-react/rsc-function-definition": "error", "@eslint-react/dom-no-dangerously-set-innerhtml": "warn", "@eslint-react/dom-no-dangerously-set-innerhtml-with-children": "error", "@eslint-react/dom-no-find-dom-node": "error", "@eslint-react/dom-no-flush-sync": "warn", "@eslint-react/dom-no-hydrate": "error", "@eslint-react/dom-no-missing-button-type": "error", "@eslint-react/dom-no-missing-iframe-sandbox": "error", "@eslint-react/dom-no-render": "error", "@eslint-react/dom-no-render-return-value": "error", "@eslint-react/dom-no-script-url": "error", "@eslint-react/dom-no-string-style-prop": "error", "@eslint-react/dom-no-unknown-property": ["error", { requireDataLowercase: true }], "@eslint-react/dom-no-unsafe-iframe-sandbox": "error", "@eslint-react/dom-no-unsafe-target-blank": "warn", "@eslint-react/dom-no-use-form-state": "warn", "@eslint-react/dom-no-void-elements-with-children": "error", "@eslint-react/web-api-no-leaked-event-listener": "error", "@eslint-react/web-api-no-leaked-fetch": "error", "@eslint-react/web-api-no-leaked-intersection-observer": "error", "@eslint-react/web-api-no-leaked-interval": "error", "@eslint-react/web-api-no-leaked-resize-observer": "error", "@eslint-react/web-api-no-leaked-timeout": "error", "@eslint-react/naming-convention-context-name": "warn", "@eslint-react/naming-convention-id-name": "warn", "@eslint-react/naming-convention-ref-name": "warn", /*** @html-eslint/react ***/ "@html-eslint/react/no-invalid-attr-value": "error", "@html-eslint/react/use-baseline": isEnabled(baseline) ? ["warn", { available: baseline.baseline }] : "off", "@html-eslint/react/no-ineffective-attrs": "warn", "@html-eslint/react/no-obsolete-attrs": "error", "@html-eslint/react/no-obsolete-tags": "error", "@html-eslint/react/classname-spacing": isEnabled(stylistic) ? ["warn", { callees: commonCallees }] : "off", "@html-eslint/react/no-duplicate-classname": ["warn", { callees: commonCallees }] }; if (isEnabled(tailwind)) reactAndHtmlReactRules["better-tailwindcss/no-duplicate-classes"] = "off"; if (isEnabled(unicorn)) reactAndHtmlReactRules["unicorn/no-invalid-file-input-accept"] = "error"; const isReactAccessibilityEnabled = isEnabled(react) && isEnabled(react.accessibility); return { ...reactAndHtmlReactRules, ...isReactAccessibilityEnabled && jsxA11yRules }; } //#endregion export { getReactRules };