UNPKG

@spaced-out/ui-design-system

Version:
215 lines (199 loc) 6.64 kB
// ESLint 9 flat config for @spaced-out/ui-design-system // TypeScript-first config (Flow removed) import tseslint from 'typescript-eslint'; import ftFlowPlugin from 'eslint-plugin-ft-flow'; import reactPlugin from 'eslint-plugin-react'; import reactHooksPlugin from 'eslint-plugin-react-hooks'; import importPlugin from 'eslint-plugin-import'; import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort'; import unusedImportsPlugin from 'eslint-plugin-unused-imports'; import jestPlugin from 'eslint-plugin-jest'; import storybookPlugin from 'eslint-plugin-storybook'; import globals from 'globals'; export default [ // Global ignores (replaces .eslintignore) { ignores: [ 'node_modules/**', 'lib/**', 'dist/**', 'storybook-static/**', 'src/assets/fontawesome/**' ], }, // TypeScript rules for project source (non type-aware for now) //NOTE:(diwaker) make it type-aware later // Bring in TS-ESLint recommended (no type checking) scoped to TS files ...tseslint.configs.recommended.map((cfg) => ({ ...cfg, files: ['src/**/*.{ts,tsx}'], languageOptions: { ...(cfg.languageOptions ?? {}), parserOptions: { ...(cfg.languageOptions?.parserOptions ?? {}), ecmaVersion: 'latest', sourceType: 'module', ecmaFeatures: { jsx: true }, }, globals: { ...globals.browser, ...globals.node, Iterator: 'readonly', }, }, settings: { react: { version: 'detect' }, }, plugins: { '@typescript-eslint': tseslint.plugin, // Keep Flow plugin loaded so legacy inline directives don't error 'ft-flow': ftFlowPlugin, react: reactPlugin, 'react-hooks': reactHooksPlugin, import: importPlugin, 'simple-import-sort': simpleImportSortPlugin, 'unused-imports': unusedImportsPlugin, jest: jestPlugin, storybook: storybookPlugin, }, })), // Local project rule tweaks { files: ['src/**/*.{ts,tsx}'], rules: { // Core 'arrow-body-style': ['warn', 'as-needed'], curly: ['warn', 'all'], 'comma-spacing': ['warn', { before: false, after: true }], 'eol-last': 'warn', eqeqeq: ['error', 'always', { null: 'ignore' }], indent: 'off', 'max-params': ['warn', { max: 4 }], 'no-alert': 'warn', 'no-console': ['error', { allow: ['warn', 'error'] }], 'no-dupe-args': 'error', 'no-dupe-keys': 'error', 'no-duplicate-case': 'error', // Allow TS overloads 'no-dupe-class-members': 'off', 'no-empty-function': 'warn', 'no-empty-pattern': 'error', 'no-eval': 'error', 'no-extend-native': 'error', 'no-extra-boolean-cast': 'error', 'no-fallthrough': 'error', 'no-floating-decimal': 'error', 'no-inner-declarations': 'error', 'no-loop-func': 'error', 'no-mixed-requires': 'off', 'no-nested-ternary': 'off', 'no-new-symbol': 'error', 'no-redeclare': 'off', // use TS rule 'no-restricted-globals': ['error', 'event', 'location'], 'no-sparse-arrays': 'error', 'no-tabs': 'warn', 'no-this-before-super': 'error', 'no-trailing-spaces': 'warn', 'no-underscore-dangle': 'off', 'no-unmodified-loop-condition': 'warn', 'no-undef': 'off', // TS handles this 'no-unreachable': 'warn', 'no-useless-constructor': 'off', // use TS rule 'no-var': 'error', 'no-with': 'error', 'object-shorthand': 'error', 'prefer-arrow-callback': 'error', 'prefer-const': 'warn', 'prefer-spread': 'warn', quotes: ['warn', 'single', { allowTemplateLiterals: true }], 'require-yield': 'error', 'rest-spread-spacing': 'error', strict: ['warn', 'never'], // import 'import/newline-after-import': ['warn', { count: 2 }], 'import/no-duplicates': 'error', // react 'react/jsx-no-undef': 'error', 'react/jsx-pascal-case': 'warn', 'react/jsx-uses-react': 'off', 'react/jsx-uses-vars': 'error', 'react/no-array-index-key': 'warn', 'react/no-deprecated': 'error', 'react/no-direct-mutation-state': 'error', 'react/no-string-refs': 'warn', 'react/prop-types': 'off', 'react/react-in-jsx-scope': 'off', // hooks //NOTE:(diwaker) temp keep as warn during migration; tighten later 'react-hooks/rules-of-hooks': 'warn', // sorting 'simple-import-sort/imports': 'error', 'simple-import-sort/exports': 'error', // unused 'unused-imports/no-unused-imports': 'error', 'unused-imports/no-unused-vars': [ 'warn', { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_', }, ], // TS-specific replacements (non type-aware) '@typescript-eslint/no-redeclare': 'error', '@typescript-eslint/no-useless-constructor': 'error', '@typescript-eslint/consistent-type-imports': ['warn', { prefer: 'type-imports' }], //NOTE:(diwaker) temp disable for migration fix this later '@typescript-eslint/no-explicit-any': ['warn', { ignoreRestArgs: true }], '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' }], '@typescript-eslint/no-unused-expressions': ['warn', { allowShortCircuit: false, allowTaggedTemplates: false, allowTernary: false }], '@typescript-eslint/no-this-alias': 'warn', '@typescript-eslint/ban-ts-comment': 'warn', '@typescript-eslint/no-empty-object-type': 'warn', '@typescript-eslint/no-unnecessary-type-constraint': 'warn', }, }, // Tests (JS/TS) { files: ['**/__tests__/*.{js,jsx,ts,tsx}'], languageOptions: { globals: globals.jest, }, plugins: { jest: jestPlugin, }, }, // Storybook specifics { files: ['**/*.stories.{jsx,tsx}'], rules: { semi: ['warn', 'always'], }, }, // Project import sort groups (apply to JS and TS) { files: ['*.{js,jsx,ts,tsx}', '**/*.{js,jsx,ts,tsx}'], rules: { 'simple-import-sort/imports': [ 'error', { groups: [ ['^react', '^@?\\w'], ['^(@|components)(/.*|$)'], ['^\\u0000'], ['^\\.\\.(?!/?$)', '^\\.\\./?$'], ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'], ['^.+\\.?(css)$'], ], }, ], }, }, ];