import { defineConfig } from 'vite-plus'; export default defineConfig({ fmt: { arrowParens: 'always', bracketSameLine: false, bracketSpacing: true, ignorePatterns: [ '.source', '**/.generated/entries.*', '**/.generated/icon-data.*', '**/*.hbs', 'packages/turbo-generators/templates/**', '**/dist/**', '**/routeTree.gen.ts', 'node_modules', ], jsxSingleQuote: false, overrides: [{ files: ['**/*.css.ts'], options: { sortImports: { sortSideEffects: false } } }], printWidth: 100, proseWrap: 'always', quoteProps: 'as-needed', semi: true, singleAttributePerLine: false, singleQuote: true, sortImports: { customGroups: [ { elementNamePattern: ['http://**', 'https://**'], groupName: 'url' }, { elementNamePattern: ['*:*'], groupName: 'protocol' }, ], groups: [ ['side_effect_style', 'side_effect'], 'url', 'protocol', ['builtin', 'external', 'type-builtin', 'type-external'], ['subpath', 'internal', 'type-subpath', 'type-internal'], ['parent', 'sibling', 'index', 'type-parent', 'type-sibling', 'type-index'], 'unknown', ], ignoreCase: false, internalPattern: ['@/', '#', '~'], newlinesBetween: false, sortSideEffects: true, }, tabWidth: 2, trailingComma: 'all', useTabs: true, }, lint: { categories: { correctness: 'deny', perf: 'deny', }, ignorePatterns: ['node_modules', '.source', '**/dist/**', '**/routeTree.gen.ts'], jsPlugins: [ { name: 'react-hooks-js', specifier: 'eslint-plugin-react-hooks', }, { name: 'vite-plus', specifier: 'vite-plus/oxlint-plugin', }, ], options: { typeAware: true, typeCheck: true, }, overrides: [ { excludeFiles: [ 'packages/@luke-ui/react/src/theme/**', 'packages/@luke-ui/react/src/core/styles/**', 'packages/@luke-ui/react/src/core/use-synchronize-animations/**', ], files: ['packages/@luke-ui/react/src/**/*.browser.test.tsx'], rules: { // Visual captures walk the appearance matrix one screenshot at a time: // each capture resizes the shared viewport, so they cannot be parallelised. 'no-await-in-loop': 'off', 'no-restricted-imports': [ 'error', { paths: [ { message: 'Mount components through src/core/test-utils/render.tsx.', name: 'react-dom/client', }, ], }, ], }, }, { excludeFiles: ['**/*.test.*', '**/__fixtures__/**'], files: ['packages/@luke-ui/react/src/core/**/*.{ts,tsx}'], rules: { 'no-restricted-imports': [ 'error', { patterns: [ { group: ['**/exports/**'], message: 'Core modules must not import public export modules.', }, ], }, ], }, }, { excludeFiles: ['**/*.test.*', '**/__fixtures__/**'], files: ['packages/@luke-ui/react/src/theme/**/*.{ts,tsx}'], rules: { 'no-restricted-imports': [ 'error', { patterns: [ { group: ['**/core/**', '**/exports/**'], message: 'Theme modules must not import from core or exports.', }, ], }, ], }, }, { excludeFiles: ['**/*.test.*', '**/__fixtures__/**'], files: ['packages/@luke-ui/react/src/shared/**/*.{ts,tsx}'], rules: { 'no-restricted-imports': [ 'error', { patterns: [ { group: ['**/core/**', '**/theme/**', '**/exports/**'], message: 'Shared modules must not import from core, theme, or exports.', }, ], }, ], }, }, ], plugins: ['import', 'jsx-a11y', 'react', 'typescript', 'vitest'], rules: { curly: 'off', 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], 'import/no-duplicates': 'error', 'jsdoc/check-access': 'error', 'jsdoc/check-property-names': 'error', 'jsdoc/check-tag-names': 'error', 'jsdoc/empty-tags': 'error', 'jsx-a11y/prefer-tag-over-role': 'off', 'no-console': 'warn', 'no-unused-vars': 'error', // Oxlint has no native equivalent for these two rules yet; keep them on the JS plugin. 'react-hooks-js/config': 'error', 'react-hooks-js/gating': 'error', 'react/error-boundaries': 'error', 'react/exhaustive-deps': 'warn', 'react/globals': 'error', 'react/immutability': 'error', 'react/incompatible-library': 'warn', 'react/no-array-index-key': 'off', 'react/preserve-manual-memoization': 'error', 'react/purity': 'error', 'react/refs': 'error', 'react/rules-of-hooks': 'error', 'react/set-state-in-effect': 'error', 'react/set-state-in-render': 'error', 'react/static-components': 'error', 'react/unsupported-syntax': 'warn', 'react/use-memo': 'error', 'sort-imports': 'off', 'typescript/array-type': ['error', { default: 'generic' }], 'typescript/consistent-type-exports': [ 'error', { fixMixedExportsWithInlineTypeSpecifier: false }, ], 'typescript/consistent-type-imports': [ 'error', { fixStyle: 'separate-type-imports', prefer: 'type-imports' }, ], // A method signature is bivariant in its parameters, so it accepts an argument the // declaration rules out. `strict` does not cover this: `strictFunctionTypes` exempts method // shorthand by design. It matters most where a hand-written interface models an external // API and a cast asserts the match, as the docs prop analysis does with ts-morph. 'typescript/method-signature-style': ['error', 'property'], 'vite-plus/prefer-vite-plus-imports': 'error', 'vitest/expect-expect': [ 'error', { // Type tests use these assertion helpers, which the rule does not recognise by default. assertFunctionNames: [ 'assertType', 'captureVisual', 'captureVisualAppearance', 'expect', 'expectForwardsDomProps', 'expectNoAxeViolations', 'expectTypeOf', ], }, ], }, }, });