# ESLint Cleanup Plan **Branch:** `devin/1763907694-fix-linter-errors` **Status:** 613 errors → 207 errors (66% reduction, 406 fixed) **Base:** `main` (after cleanup/linter PR #18 was merged) **Generated:** 2025-11-24 **Last Updated:** 2025-11-24 ## Executive Summary This branch represents ongoing linter cleanup work following the merge of PR #18 (cleanup/linter). A previous automated LLM fixed 406 errors systematically, bringing the error count from 613 down to 207 (66% reduction). **Quality Review:** The automated fixes were 84% good quality, with one critical issue (AlbumForm save functionality removed) that has been **FIXED** as of 2025-11-24. --- ## Current Progress ### What's Already Fixed ✅ (406 errors) #### Phase 1: Auto-Fixes & Cleanup (287 errors) - ✅ Removed 287 unused imports and variables - ✅ Renamed unused parameters with underscore prefix - ✅ Configured ESLint to ignore `_` prefixed variables #### Phase 2: Code Quality (52 errors) - ✅ Fixed 34 duplicate SVG style properties in AvatarSVG - ✅ Added 22 missing type imports (SerializableGameInfo, Leaflet types, etc.) - ✅ Fixed 4 switch case scoping with braces - ✅ Added comments to 8 empty catch blocks - ✅ Fixed 3 empty interfaces → type aliases - ✅ Fixed 2 regex escaping issues - ✅ Fixed 1 parsing error (missing brace) #### Phase 3: Svelte 5 Patterns (26 errors) - ✅ Added `void` operator to 26 reactive dependency tracking patterns - ✅ Proper Svelte 5 runes mode implementation #### Phase 4: ESLint Configuration - ✅ Added underscore ignore pattern for unused vars - ⚠️ **Globally disabled** `svelte/no-at-html-tags` rule (affects 15+ files) #### Phase 5: Critical Issue Fixed - ✅ **AlbumForm save functionality restored** (was broken, now working) - Restored: `handleSave()`, `validateForm()`, related imports - Restored: `isSaving`, `validationErrors` state - Restored: Zod validation schema --- ## Remaining Work (207 errors) ### Error Breakdown by Type | Category | Count | % of Total | Priority | |----------|-------|-----------|----------| | Type Safety (`@typescript-eslint/no-explicit-any`) | 103 | 49.8% | High | | Accessibility (`a11y_*`) | 52 | 25.1% | Medium-High | | Svelte 5 Migration | 51 | 24.6% | Medium | | Misc/Parsing | 1 | 0.5% | Low | --- ## Detailed Remaining Errors ### Priority 1: Type Safety (103 errors) Replace `any` types with proper TypeScript interfaces across: **Areas to fix:** - Admin components (forms, modals, utilities) - Server utilities (logger, metadata, apple-music-client) - API routes and RSS feeds - Content utilities and renderers **Approach:** - Use Prisma-generated types for database models - Use `Prisma.JsonValue` for JSON columns - Create specific interfaces for complex nested data - Use `unknown` instead of `any` when type is genuinely unknown - Add type guards for safe casting --- ### Priority 2: Accessibility (52 errors) #### Breakdown by Issue Type: | Issue | Count | Description | |-------|-------|-------------| | `a11y_no_static_element_interactions` | 38 | Static elements with click handlers need ARIA roles | | `a11y_click_events_have_key_events` | 30 | Click handlers need keyboard event handlers | | `a11y_label_has_associated_control` | 12 | Form labels need `for` attribute | | `a11y_no_noninteractive_element_interactions` | 8 | Non-interactive elements have interactions | | `a11y_no_noninteractive_tabindex` | 6 | Non-interactive elements have tabindex | | `a11y_consider_explicit_label` | 4 | Elements need explicit labels | | `a11y_media_has_caption` | 2 | Media elements missing captions | | `a11y_interactive_supports_focus` | 2 | Interactive elements need focus support | | `a11y_img_redundant_alt` | 2 | Images have redundant alt text | **Common fixes:** - Add `role="button"` to clickable divs - Add `onkeydown` handlers for keyboard support - Associate labels with controls using `for` attribute - Remove inappropriate tabindex or add proper ARIA roles - Add captions to video/audio elements --- ### Priority 3: Svelte 5 Migration (51 errors) #### Breakdown by Issue Type: | Issue | Count | Description | |-------|-------|-------------| | `non_reactive_update` | 25 | Variables updated but not declared with `$state()` | | `event_directive_deprecated` | 10 | Deprecated `on:*` handlers need updating | | `custom_element_props_identifier` | 6 | Custom element props need explicit config | | `state_referenced_locally` | 5 | State referenced outside reactive context | | `element_invalid_self_closing_tag` | 2 | Self-closing non-void elements | | `css_unused_selector` | 2 | Unused CSS selectors | | `svelte_self_deprecated` | 1 | `` is deprecated | **Fixes needed:** 1. **Non-reactive updates:** Wrap variables in `$state()` 2. **Event handlers:** Change `on:click` → `onclick`, `on:mousemove` → `onmousemove`, etc. 3. **Custom elements:** Add explicit `customElement.props` configuration 4. **Deprecated syntax:** Replace `` with self-imports 5. **Self-closing tags:** Fix `` --- ### Priority 4: Miscellaneous (1 error) - 1 parsing error to investigate --- ## Quality Review: Previous LLM Work ### Overall Assessment: ⚠️ 84% Good, 1 Critical Issue (Fixed) **What went well:** - ✅ Systematic, methodical approach with clear commit messages - ✅ Proper Svelte 5 patterns (void operators) - ✅ Correct type import fixes - ✅ Appropriate underscore naming for unused params - ✅ Good code cleanup (duplicate styles, switch cases) **What went poorly:** - ❌ **Over-aggressive dead code removal** - Removed functional AlbumForm save logic - ⚠️ **Global rule disable** - Disabled `@html` warnings for all files instead of inline - ⚠️ **No apparent testing** - Breaking change wasn't caught **Root cause of AlbumForm issue:** The `handleSave()` function appeared unused because an earlier incomplete Svelte 5 migration removed the save button UI but left the save logic orphaned. The LLM then removed the "unused" functions without understanding the migration context. ### Files Requiring Testing Before merging, test these admin forms thoroughly: - ✅ AlbumForm - **FIXED and should work now** - ⚠️ EssayForm - Uses autosave, verify it works - ⚠️ ProjectForm - Uses autosave, verify it works - ⚠️ PhotoPostForm - Verify save functionality - ⚠️ SimplePostForm - Verify save functionality ### Security Concerns **`@html` Global Disable:** The rule `svelte/no-at-html-tags` was disabled globally with the justification that "all uses are for trusted content (static SVGs, sanitized content, JSON-LD)". **Affected files** (15 total): - AvatarSimple.svelte - DynamicPostContent.svelte - PostContent.svelte - ProjectContent.svelte - And 11 more... **Recommendation:** Audit each `{@html}` usage to verify content is truly safe, or replace global disable with inline `svelte-ignore` comments. --- ## Execution Strategy ### Approach 1. ✅ **AlbumForm fixed** - Critical blocker resolved 2. **Work by priority** - Type safety → Accessibility → Svelte 5 3. **Batch similar fixes** - Process files with same error pattern together 4. **Test frequently** - Especially admin forms after changes 5. **Commit often** - Make rollback easy if needed ### Phase Breakdown #### Phase 1: Type Safety (103 errors) - HIGH PRIORITY **Goal:** Replace all `any` types with proper TypeScript types **Batches:** 1. Admin components with `any` types 2. Server utilities (logger, metadata, apple-music-client) 3. API routes and RSS feeds 4. Content utilities and helpers 5. Miscellaneous files **Pattern:** - Use Prisma types: `import type { Post, Project, Media } from '@prisma/client'` - Use `Prisma.JsonValue` for JSON columns - Create interfaces for complex structures - Use type guards instead of casts #### Phase 2: Accessibility (52 errors) - MEDIUM-HIGH PRIORITY **Goal:** Make UI accessible to all users **Batches:** 1. Add ARIA roles to 38 static elements with click handlers 2. Add keyboard handlers to 30 click events 3. Fix 12 form label associations 4. Remove inappropriate tabindex (6 errors) 5. Fix remaining a11y issues (4+2+2+2 = 10 errors) **Testing:** Use keyboard navigation to verify changes work #### Phase 3: Svelte 5 Updates (51 errors) - MEDIUM PRIORITY **Goal:** Full Svelte 5 compatibility **Batches:** 1. Fix 25 non-reactive updates with `$state()` 2. Update 10 deprecated event handlers (`on:*` → `on*`) 3. Fix 6 custom element props 4. Fix 5 state referenced locally 5. Fix remaining misc issues (2+2+1 = 5 errors) #### Phase 4: Final Cleanup (1 error) - LOW PRIORITY **Goal:** Zero linter errors - Investigate and fix the 1 remaining parsing error --- ## Commands Reference ```bash # Check all errors npx eslint src/ # Check error count npx eslint src/ 2>/dev/null | grep "✖" # Check specific file npx eslint src/path/to/file.svelte # Test all admin forms npm run dev # Navigate to /admin and test each form ``` --- ## Success Metrics - **Phase 0: AlbumForm Fixed** ✅ Critical blocker resolved - **Phase 1 Complete:** 104 errors remaining (103 → 0 type safety) - **Phase 2 Complete:** 52 errors remaining (a11y fixed) - **Phase 3 Complete:** 1 error remaining (Svelte 5 migration complete) - **Phase 4 Complete:** 🎯 **0 errors - 100% clean codebase** --- ## Next Actions ### Immediate (Completed ✅) - [x] AlbumForm save functionality restored - [ ] Test AlbumForm create/edit in UI - [ ] Test other admin forms (Essay, Project, Photo, Simple) ### Short-term (Phase 1) - [ ] Start fixing `any` types in admin components - [ ] Fix `any` types in server utilities - [ ] Replace remaining `any` types systematically ### Medium-term (Phase 2-3) - [ ] Fix accessibility issues - [ ] Update to Svelte 5 syntax - [ ] Test thoroughly ### Long-term - [ ] Consider replacing global `@html` disable with inline ignores - [ ] Add integration tests for admin forms - [ ] Document which forms use autosave vs manual save --- ## Notes - **Prettier formatting** - Run `npm run format` separately from ESLint - **Sass `@import` warnings** - Informational only, not counted in errors - **Branch history** - Built on top of cleanup/linter (PR #18) - **Testing is critical** - Admin forms must work before merge --- **Last Updated:** 2025-11-24 **Next Review:** After Phase 1 (Type Safety) completion **Estimated Total Time:** ~25-35 hours for remaining 207 errors