Project 4: Browser-Based Code Editor
55 min read
Selection APICursor ManagementcontenteditableDebouncingFind & ReplaceTab Capture
📋 Project Brief
Build a lightweight, browser-based code editor with features like line numbering, bracket matching, auto-indentation, and a find-and-replace system. This project forces you to deeply understand cursor positioning, text selection ranges, and the debate between "DOM as source of truth" vs. "State as source of truth." You will handle rapid state changes efficiently using debouncing and virtual rendering techniques.
🎯 Learning Objectives
- Work with
contenteditableor hidden<textarea>overlay patterns - Manage cursor position and text selection using the Selection and Range APIs
- Implement efficient text diffing for syntax highlighting without re-rendering the entire document
- Handle the Tab key capture problem (preventing browser focus shift)
- Build a custom Find & Replace engine with regex support
✅ Feature Requirements
Feature 1: Line Numbering
Acceptance Criteria:
- A gutter column on the left displays line numbers
- Line numbers must stay perfectly aligned with the text, even when lines wrap
- The current line (where the cursor is) must be visually highlighted
- Line numbers must update dynamically as text is added or removed
- The gutter width must adapt (e.g., expand from 2 digits to 3 digits at line 100)
Feature 2: Bracket Matching
Acceptance Criteria:
- When the cursor is next to a bracket
( ) [ ] { }, its matching partner is highlighted - If no matching bracket is found, the current bracket is highlighted in red (error state)
- Must handle nested brackets correctly:
((a + b) * c) - Matching must work across multiple lines
Feature 3: Custom Snippets / Tab Completion
Acceptance Criteria:
- Typing
clg+ Tab expands toconsole.log();with the cursor inside the parentheses - Support at least 10 configurable snippets
- Snippets must be stored in a configuration object that users can extend
- Show a small tooltip preview of the snippet before expansion
Feature 4: Find & Replace
Acceptance Criteria:
- A modal/panel opens with Ctrl+F (or Cmd+F)
- Supports "Match Case" toggle
- Supports "Use Regex" toggle
- "Find Next" / "Find Previous" navigation with match count display ("3 of 17")
- "Replace" replaces the current match; "Replace All" replaces every occurrence
- All matches must be visually highlighted in the editor
Feature 5: Tab Capture
Acceptance Criteria:
- Pressing Tab inside the editor inserts spaces (configurable: 2 or 4) instead of moving focus
- Shift+Tab removes one level of indentation from the current line
- When multiple lines are selected, Tab indents all selected lines
- Pressing Escape must release focus back to normal browser tab navigation (no keyboard trap)
📊 Performance Benchmarks
| Metric | Target |
|---|---|
| Keystroke-to-render latency | < 16ms (one frame) |
| Opening a 5,000-line file | < 500ms |
| Find in a 10,000-line file | < 200ms |
| Memory usage for 10K lines | < 50MB heap |
🧪 Testing Checklist
- Unit test bracket matching algorithm with nested and edge cases
- Unit test snippet expansion logic
- Unit test regex find-and-replace
- Integration test: Tab key inserts spaces, Escape releases focus
- A11y: The editor must announce line/column position to screen readers
🚀 Stretch Goals
- Add basic syntax highlighting for one language (JavaScript)
- Implement multi-cursor editing (Ctrl+Click to add cursors)
- Add a minimap (code overview) on the right side
- Support multiple open files with a tab bar