* Perfect! Now let me create a summary for you: ## ✅ ESLint Configuration Complete The linter has identified **29 files** that need to be renamed: ### **Files to Rename:** #### **Components → PascalCase (15 files)** ``` config-provider.tsx → ConfigProvider.tsx diff-view-switch.tsx → DiffViewSwitch.tsx logo.tsx → Logo.tsx navbar.tsx → Navbar.tsx (in layout/) search-bar.tsx → SearchBar.tsx theme-provider.tsx → ThemeProvider.tsx style-override.tsx → StyleOverride.tsx copy-files-field.tsx → CopyFilesField.tsx (in projects/) project-detail.tsx → ProjectDetail.tsx (in projects/) project-form-fields.tsx → ProjectFormFields.tsx (in projects/) project-list.tsx → ProjectList.tsx (in projects/) ``` #### **Contexts → PascalCase (2 files)** ``` project-context.tsx → ProjectContext.tsx search-context.tsx → SearchContext.tsx ``` #### **Pages → PascalCase (3 files)** ``` full-attempt-logs.tsx → FullAttemptLogs.tsx project-tasks.tsx → ProjectTasks.tsx projects.tsx → Projects.tsx ``` #### **Lib → camelCase (2 files)** ``` caret-position.ts → caretPosition.ts mcp-strategies.ts → mcpStrategies.ts ``` #### **Utils → camelCase (3 files)** ``` companion-install-task.ts → companionInstallTask.ts script-placeholders.ts → scriptPlaceholders.ts status-labels.ts → statusLabels.ts ``` #### **UI (shadcn) → kebab-case (4 files)** ``` ActionsDropdown.tsx → actions-dropdown.tsx ImageUploadSection.tsx → image-upload-section.tsx TitleDescriptionEditor.tsx → title-description-editor.tsx DataTable.tsx → data-table.tsx (in table/) Table.tsx → table.tsx (in table/) ImageChipNode.tsx → image-chip-node.tsx (in wysiwyg/) imageChipMarkdown.ts → image-chip-markdown.ts (in wysiwyg/) ``` #### **Entry Point (special case - 1 file)** ``` main.tsx → can stay as main.tsx (entry point convention) ``` **Next steps:** Should I proceed with renaming these files using `git mv`? * ## ✅ Complete! File Naming Standardization Successful ### **Summary** Successfully implemented and enforced file naming conventions for the frontend: ### **What Was Done:** 1. ✅ **Installed** `eslint-plugin-check-file@^2.8.0` 2. ✅ **Configured ESLint** with file naming rules: - **Components (.tsx)**: `PascalCase` - **Hooks (.ts)**: `camelCase` (with `use` prefix) - **Utils/Lib (.ts)**: `camelCase` - **Shadcn UI**: `kebab-case` (library convention) - **Entry points**: Excluded (`main.tsx`, `vite-env.d.ts`) 3. ✅ **Renamed 28 files** using `git mv`: - 10 components → PascalCase - 2 contexts → PascalCase - 3 pages → PascalCase - 2 lib files → camelCase - 3 utils → camelCase - 7 UI components → kebab-case - 1 utils component → PascalCase 4. ✅ **Fixed all imports** across the codebase (77 files modified) 5. ✅ **Verified**: - ✅ ESLint passes (no filename errors) - ✅ TypeScript check passes (no errors) - ✅ Build successful ### **Git Status:** - 28 files renamed (with history preserved via `git mv`) - 77 total files changed (renames + import updates) ### **Ready for commit!** The codebase now has consistent, enforceable file naming conventions that will prevent future inconsistencies. * Cleanup script changes for task attempt 11f8d7b9-99b5-41ce-934c-5ce75008a200
180 lines
5.2 KiB
JavaScript
180 lines
5.2 KiB
JavaScript
const i18nCheck = process.env.LINT_I18N === 'true';
|
|
|
|
module.exports = {
|
|
root: true,
|
|
env: {
|
|
browser: true,
|
|
es2020: true,
|
|
},
|
|
extends: [
|
|
'eslint:recommended',
|
|
'plugin:@typescript-eslint/recommended',
|
|
'plugin:react-hooks/recommended',
|
|
'plugin:i18next/recommended',
|
|
'plugin:eslint-comments/recommended',
|
|
'prettier',
|
|
],
|
|
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
|
parser: '@typescript-eslint/parser',
|
|
plugins: ['react-refresh', '@typescript-eslint', 'unused-imports', 'i18next', 'eslint-comments', 'check-file'],
|
|
parserOptions: {
|
|
ecmaVersion: 'latest',
|
|
sourceType: 'module',
|
|
project: './tsconfig.json',
|
|
},
|
|
rules: {
|
|
'eslint-comments/no-use': ['error', { allow: [] }],
|
|
'react-refresh/only-export-components': 'off',
|
|
'unused-imports/no-unused-imports': 'error',
|
|
'unused-imports/no-unused-vars': [
|
|
'error',
|
|
{
|
|
vars: 'all',
|
|
args: 'after-used',
|
|
ignoreRestSiblings: false,
|
|
},
|
|
],
|
|
'@typescript-eslint/no-explicit-any': 'warn',
|
|
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
|
// Enforce typesafe modal pattern
|
|
'no-restricted-imports': [
|
|
'error',
|
|
{
|
|
paths: [
|
|
{
|
|
name: '@ebay/nice-modal-react',
|
|
importNames: ['default'],
|
|
message:
|
|
'Import NiceModal only in lib/modals.ts or dialog component files. Use DialogName.show(props) instead.',
|
|
},
|
|
{
|
|
name: '@/lib/modals',
|
|
importNames: ['showModal', 'hideModal', 'removeModal'],
|
|
message:
|
|
'Do not import showModal/hideModal/removeModal. Use DialogName.show(props) and DialogName.hide() instead.',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
'no-restricted-syntax': [
|
|
'error',
|
|
{
|
|
selector:
|
|
'CallExpression[callee.object.name="NiceModal"][callee.property.name="show"]',
|
|
message:
|
|
'Do not use NiceModal.show() directly. Use DialogName.show(props) instead.',
|
|
},
|
|
{
|
|
selector:
|
|
'CallExpression[callee.object.name="NiceModal"][callee.property.name="register"]',
|
|
message:
|
|
'Do not use NiceModal.register(). Dialogs are registered automatically.',
|
|
},
|
|
{
|
|
selector: 'CallExpression[callee.name="showModal"]',
|
|
message:
|
|
'Do not use showModal(). Use DialogName.show(props) instead.',
|
|
},
|
|
{
|
|
selector: 'CallExpression[callee.name="hideModal"]',
|
|
message: 'Do not use hideModal(). Use DialogName.hide() instead.',
|
|
},
|
|
{
|
|
selector: 'CallExpression[callee.name="removeModal"]',
|
|
message: 'Do not use removeModal(). Use DialogName.remove() instead.',
|
|
},
|
|
],
|
|
// i18n rule - only active when LINT_I18N=true
|
|
'i18next/no-literal-string': i18nCheck
|
|
? [
|
|
'warn',
|
|
{
|
|
markupOnly: true,
|
|
ignoreAttribute: [
|
|
'data-testid',
|
|
'to',
|
|
'href',
|
|
'id',
|
|
'key',
|
|
'type',
|
|
'role',
|
|
'className',
|
|
'style',
|
|
'aria-describedby',
|
|
],
|
|
'jsx-components': {
|
|
exclude: ['code'],
|
|
},
|
|
},
|
|
]
|
|
: 'off',
|
|
// File naming conventions
|
|
'check-file/filename-naming-convention': [
|
|
'error',
|
|
{
|
|
// React components (tsx) should be PascalCase
|
|
'src/**/*.tsx': 'PASCAL_CASE',
|
|
// Hooks should be camelCase starting with 'use'
|
|
'src/**/use*.ts': 'CAMEL_CASE',
|
|
// Utils should be camelCase
|
|
'src/utils/**/*.ts': 'CAMEL_CASE',
|
|
// Lib/config/constants should be camelCase
|
|
'src/lib/**/*.ts': 'CAMEL_CASE',
|
|
'src/config/**/*.ts': 'CAMEL_CASE',
|
|
'src/constants/**/*.ts': 'CAMEL_CASE',
|
|
},
|
|
{
|
|
ignoreMiddleExtensions: true,
|
|
},
|
|
],
|
|
},
|
|
overrides: [
|
|
{
|
|
// Entry point exception - main.tsx can stay lowercase
|
|
files: ['src/main.tsx', 'src/vite-env.d.ts'],
|
|
rules: {
|
|
'check-file/filename-naming-convention': 'off',
|
|
},
|
|
},
|
|
{
|
|
// Shadcn UI components are an exception - keep kebab-case
|
|
files: ['src/components/ui/**/*.{ts,tsx}'],
|
|
rules: {
|
|
'check-file/filename-naming-convention': [
|
|
'error',
|
|
{
|
|
'src/components/ui/**/*.{ts,tsx}': 'KEBAB_CASE',
|
|
},
|
|
{
|
|
ignoreMiddleExtensions: true,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
files: ['**/*.test.{ts,tsx}', '**/*.stories.{ts,tsx}'],
|
|
rules: {
|
|
'i18next/no-literal-string': 'off',
|
|
},
|
|
},
|
|
{
|
|
// Disable type-aware linting for config files
|
|
files: ['*.config.{ts,js,cjs,mjs}', '.eslintrc.cjs'],
|
|
parserOptions: {
|
|
project: null,
|
|
},
|
|
rules: {
|
|
'@typescript-eslint/switch-exhaustiveness-check': 'off',
|
|
},
|
|
},
|
|
{
|
|
// Allow NiceModal usage in lib/modals.ts, App.tsx (for Provider), and dialog component files
|
|
files: ['src/lib/modals.ts', 'src/App.tsx', 'src/components/dialogs/**/*.{ts,tsx}'],
|
|
rules: {
|
|
'no-restricted-imports': 'off',
|
|
'no-restricted-syntax': 'off',
|
|
},
|
|
},
|
|
],
|
|
};
|