Files
headquarter/openspec/changes/file-editor/design.md
T
Fusion 7261c75bb2 feat: implement file editor with syntax highlighting and editing
- Install react-simple-code-editor and prismjs dependencies
- Create language detection utility with 50+ file extensions
- Create SyntaxHighlighter component with Prism.js highlighting
- Create CodeEditor component with syntax-highlighted editing
- Create CommitDialog with diff preview and commit message
- Create FileEditor component integrating view/edit/commit flow
- Replace FileViewer with FileEditor in RepoWorkspace
- Add comprehensive CSS styles for editor, highlighter, and dialog
- Support keyboard shortcuts: Ctrl+E (toggle edit), Ctrl+S (save)
- Quality gates: typecheck ✓ lint ✓ build ✓
2026-05-19 16:04:48 +02:00

4.8 KiB

File Editor - Design

Architecture

RepoWorkspace
└── FileEditor (replaces FileViewer)
    ├── View Mode
    │   ├── Toolbar (Edit button, file info)
    │   ├── SyntaxHighlighter (Prism.js)
    │   └── Line numbers
    └── Edit Mode
        ├── Toolbar (Save, Cancel, file info)
        ├── Editor (react-simple-code-editor)
        └── Line numbers
            ↓ [Save clicked]
        CommitDialog
        ├── Diff preview
        ├── Commit message input
        └── Author info

Component Design

FileEditor

Props:

interface FileEditorProps {
  projectId: string;
  repoId: string;
  filePath: string;
  branch: string;
}

State:

interface FileEditorState {
  mode: 'view' | 'edit';
  content: string;
  originalContent: string;
  language: string;
  loading: boolean;
  error: string | null;
  showCommitDialog: boolean;
}

Flow:

  1. Load file content on mount/file change
  2. Detect language from file extension
  3. Display in view mode by default
  4. Click "Edit" → switch to edit mode
  5. Make changes → click "Save"
  6. Show commit dialog with diff
  7. Enter commit message → commit
  8. Return to view mode with updated content

SyntaxHighlighter (View Mode)

Implementation:

  • Use Prism.js for tokenization
  • Render highlighted tokens as HTML
  • Add line numbers via CSS counter
  • Copy-to-clipboard button

Language Detection:

const detectLanguage = (filename: string): string => {
  const ext = filename.split('.').pop()?.toLowerCase();
  const langMap: Record<string, string> = {
    'js': 'javascript',
    'ts': 'typescript',
    'tsx': 'tsx',
    'jsx': 'jsx',
    'py': 'python',
    'md': 'markdown',
    // ... more mappings
  };
  return langMap[ext || ''] || 'plaintext';
};

CodeEditor (Edit Mode)

Implementation:

  • react-simple-code-editor component
  • Prism.js highlighting via textarea overlay
  • Line numbers synchronized with content
  • Tab key support (inserts spaces)

Features:

  • Syntax highlighting while typing
  • Auto-indentation
  • Line numbers
  • Selection highlighting

CommitDialog

Props:

interface CommitDialogProps {
  isOpen: boolean;
  filePath: string;
  originalContent: string;
  newContent: string;
  onCommit: (message: string) => void;
  onCancel: () => void;
}

Features:

  • Diff preview (simple line-by-line comparison)
  • Commit message input (required)
  • Author info (from user profile)
  • Cancel button (returns to edit mode)

API Integration

Load File (existing)

GET /projects/{id}/repositories/{id}/files/content
Query: branch, path

Save File (existing)

POST /projects/{id}/repositories/{id}/files/content
Body: {
  path: string,
  branch: string,
  content: string,
  commit_message: string,
  author_name: string,
  author_email: string
}

Styling

Editor Layout

┌─────────────────────────────────────────┐
│ [file.txt]              [Edit] [Raw]   │ ← Toolbar
├─────────────────────────────────────────┤
│ 1 │ function hello() {                  │ ← Line numbers + content
│ 2 │   return "world";                   │
│ 3 │ }                                   │
└─────────────────────────────────────────┘

Colors

  • Match existing app theme (CSS variables)
  • Syntax colors:
    • Keywords: var(--brand)
    • Strings: #10b981
    • Comments: var(--muted)
    • Numbers: #f59e0b
    • Functions: #3b82f6

Responsive

  • Editor takes full width on mobile
  • Toolbar buttons shrink to icons
  • Line numbers hidden on very small screens

Implementation Order

  1. Install dependencies - react-simple-code-editor, prismjs
  2. Create SyntaxHighlighter component - Prism.js wrapper
  3. Create CodeEditor component - Edit mode with highlighting
  4. Create CommitDialog component - Commit flow
  5. Create FileEditor component - Main component orchestrating modes
  6. Replace FileViewer in RepoWorkspace
  7. Add CSS styles - Editor styling, syntax colors
  8. Test - Various file types, commit flow

Error Handling

  • Binary files: Show "Cannot edit binary files" message
  • Load errors: Show retry button
  • Save errors: Show error in commit dialog
  • Large files: Show warning, offer to download instead
  • Network errors: Show offline indicator

Performance

  • Lazy load Prism - Load language grammars on demand
  • Debounce edits - Don't re-highlight on every keystroke
  • Virtual scrolling - For files >1000 lines
  • Memoization - Cache highlighted output