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 ✓
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
# File Editor Specification
|
||||
|
||||
## Requirements
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
1. **File Display**: Show file contents with syntax highlighting for all text files
|
||||
2. **Language Detection**: Automatically detect language from file extension
|
||||
3. **View Mode**: Read-only display with line numbers and copy button
|
||||
4. **Edit Mode**: Rich text editing with syntax highlighting
|
||||
5. **Commit Flow**: Save changes via commit dialog with custom message
|
||||
6. **Diff Preview**: Show changes before committing
|
||||
7. **File Support**: All text-based files (source code, config, markdown, etc.)
|
||||
|
||||
### Non-Functional Requirements
|
||||
|
||||
1. **Performance**: Load files < 500ms, highlighting < 100ms
|
||||
2. **Responsiveness**: UI remains responsive during editing
|
||||
3. **Accessibility**: Keyboard navigation, screen reader support
|
||||
4. **Browser Support**: Modern browsers (Chrome, Firefox, Safari, Edge)
|
||||
|
||||
## API Specification
|
||||
|
||||
### GET /projects/{project_id}/repositories/{repo_id}/files/content
|
||||
Get file content (existing endpoint).
|
||||
|
||||
**Query Parameters:**
|
||||
- `branch` (required): Branch name
|
||||
- `path` (required): File path
|
||||
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"path": "src/main.py",
|
||||
"branch": "main",
|
||||
"content": "function hello() {\n return 'world';\n}",
|
||||
"size": 42,
|
||||
"encoding": "utf-8",
|
||||
"language": "python",
|
||||
"is_binary": false
|
||||
}
|
||||
```
|
||||
|
||||
### POST /projects/{project_id}/repositories/{repo_id}/files/content
|
||||
Update file content (existing endpoint).
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"path": "src/main.py",
|
||||
"branch": "main",
|
||||
"content": "new content",
|
||||
"commit_message": "Update greeting",
|
||||
"author_name": "User Name",
|
||||
"author_email": "user@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
## Frontend Specification
|
||||
|
||||
### Components
|
||||
|
||||
#### FileEditor
|
||||
Main component managing view/edit modes.
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface FileEditorProps {
|
||||
projectId: string;
|
||||
repoId: string;
|
||||
}
|
||||
```
|
||||
|
||||
**State:**
|
||||
```typescript
|
||||
interface FileEditorState {
|
||||
mode: 'view' | 'edit';
|
||||
content: string;
|
||||
originalContent: string;
|
||||
language: string;
|
||||
filePath: string | null;
|
||||
branch: string;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
showCommitDialog: boolean;
|
||||
isBinary: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
#### SyntaxHighlighter
|
||||
Read-only syntax highlighted display.
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface SyntaxHighlighterProps {
|
||||
code: string;
|
||||
language: string;
|
||||
showLineNumbers?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
#### CodeEditor
|
||||
Editable code with syntax highlighting.
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface CodeEditorProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
language: string;
|
||||
readOnly?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
#### CommitDialog
|
||||
Commit flow dialog.
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface CommitDialogProps {
|
||||
isOpen: boolean;
|
||||
filePath: string;
|
||||
originalContent: string;
|
||||
newContent: string;
|
||||
onCommit: (message: string) => Promise<void>;
|
||||
onCancel: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
### Language Support
|
||||
|
||||
Supported languages (from Prism.js):
|
||||
- JavaScript/TypeScript (js, ts, jsx, tsx)
|
||||
- Python (py)
|
||||
- HTML/XML (html, xml)
|
||||
- CSS/SCSS (css, scss)
|
||||
- JSON (json)
|
||||
- Markdown (md)
|
||||
- YAML (yaml, yml)
|
||||
- Shell/Bash (sh, bash)
|
||||
- Docker (dockerfile)
|
||||
- SQL (sql)
|
||||
- And 280+ more via Prism.js
|
||||
|
||||
### Keyboard Shortcuts
|
||||
|
||||
- `Ctrl/Cmd + E`: Toggle edit mode
|
||||
- `Ctrl/Cmd + S`: Save (shows commit dialog)
|
||||
- `Escape`: Cancel edit mode
|
||||
- `Tab`: Insert 2 spaces
|
||||
|
||||
### URL State
|
||||
|
||||
Editor state synced to URL:
|
||||
```
|
||||
/projects/:projectId?repo=:repoId&branch=:branch&file=:path&edit=true
|
||||
```
|
||||
|
||||
## Error Codes
|
||||
|
||||
| Error Code | Description | User Message |
|
||||
|------------|-------------|--------------|
|
||||
| BINARY_FILE | File is binary | "Binary files cannot be edited" |
|
||||
| FILE_TOO_LARGE | File > 1MB | "File too large to edit" |
|
||||
| LOAD_ERROR | Failed to load | "Failed to load file" |
|
||||
| SAVE_ERROR | Failed to save | "Failed to save changes" |
|
||||
| EMPTY_COMMIT | No changes | "No changes to commit" |
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
- Language detection
|
||||
- Syntax highlighting output
|
||||
- Diff generation
|
||||
- Commit validation
|
||||
|
||||
### Integration Tests
|
||||
- File loading
|
||||
- Mode switching
|
||||
- Commit flow
|
||||
- Error handling
|
||||
|
||||
### Manual Tests
|
||||
- Various file types
|
||||
- Large files
|
||||
- Binary files
|
||||
- Network failures
|
||||
Reference in New Issue
Block a user