import i18next from 'eslint-plugin-i18next' import react from 'eslint-plugin-react' import jsxA11y from 'eslint-plugin-jsx-a11y' /** * Enforces the CONVENTIONS.md rules: * - i18n keying (no-literal-string) * - strict jsx-a11y * - react hooks / components * * Custom rules that ship in Stage 3 (noted in CONVENTIONS.md): * - no-array-methods-in-widgets * - no-date-libraries-in-widgets */ export default [ { files: ['src/**/*.{ts,tsx}'], ignores: [ 'src/routeTree.gen.ts', '**/*.gen.ts', '**/*.gen.d.ts', 'dist/**', 'node_modules/**', ], plugins: { i18next, react, 'jsx-a11y': jsxA11y }, languageOptions: { ecmaVersion: 'latest', sourceType: 'module', parserOptions: { ecmaFeatures: { jsx: true }, }, }, rules: { // i18n keying — every visible string must go through t() 'i18next/no-literal-string': [ 'error', { markupOnly: true, onlyAttribute: ['label', 'placeholder', 'title', 'aria-label'], ignoreCallee: ['t', 'i18n.t', 'useTranslation'], ignoreComponent: ['Code', 'Kbd'], }, ], // A11y — Radix defaults stay; no escape hatch to
...jsxA11y.configs.strict.rules, }, }, ]