Overview
Building a rich text editor is more than just working with contenteditable. It requires understanding document models, schema design, position management, and the separation between your internal data model and the DOM representation.
Modern editors like ProseMirror, Slate, and Lexical all follow similar architectural patterns that separate concerns and make editors maintainable and extensible.
Key Principle: Model-View Separation
The fundamental principle is separating the document model (your internal representation) from the view (the DOM). The model is your source of truth, and the view is just a projection.
- Model: Abstract, schema-validated, framework-agnostic
- View: HTML representation, handles user input, browser-specific
Core Concepts
Document Model
Your internal representation of the document. Tree structure with nodes (blocks, inlines, text) and marks (formatting).
Learn more →Schema
Defines what your document can contain: node types, content rules, attributes, and marks.
Learn more →Position Management
Representing positions in your model using paths (array of indices) instead of DOM references.
Learn more →HTML Mapping
Converting between your model and HTML: serialization (model → HTML) and deserialization (HTML → model).
Learn more →Detailed Guides
Editor Architecture
Model-view separation, document model structure, view layer responsibilities, and how they work together.
- Why separate model and view
- Document model structure
- View layer responsibilities
- State management patterns
Model & Schema
Designing your document model and schema: node types, document structure, mark system, and validation.
- Schema definition and validation
- Node type design
- Tree vs Flat Map structures
- Node ID vs Path addressing
Position & Selection Management
Managing positions and selections in your model: path-based positions, selection representation, and DOM conversion.
- Path-based position representation
- Model selection structure
- DOM to model conversion
- Model to DOM conversion
- Selection normalization
HTML Mapping
Converting between your model and HTML: serialization, deserialization, and incremental updates.
- Model to HTML serialization
- HTML to model deserialization
- Handling edge cases
- Incremental DOM updates
- Preserving marks and attributes
Model-DOM Synchronization
Keeping your model and DOM in sync: handling contenteditable=false, preserving selection, and managing updates.
- Bidirectional synchronization
- contenteditable=false handling
- Selection preservation
- Update strategies
History Management
Implementing undo/redo functionality: model-based history, conflict resolution, and DOM history handling.
- Model-based history
- DOM history conflicts
- Undo/redo implementation
- History state management
Input Handling & IME
Comprehensive guide to handling user input, IME composition, keyboard events, and text processing.
- IME composition handling
- Keyboard event processing
- Text input normalization
- Paste operation handling
- Mobile input support
Plugin Development
Guide to developing plugins that extend model-based contenteditable editors with custom functionality.
- Plugin architecture
- Plugin lifecycle
- Using hooks and commands
- Plugin examples
Testing Strategies
Comprehensive testing strategies for model-based contenteditable editors at different levels.
- Unit testing
- Integration testing
- IME testing
- End-to-end testing
- Mobile testing
Debugging Techniques
Debugging strategies and techniques for contenteditable editors, including tools and common issues.
- Debugging tools
- Event logging
- Common issues
- Performance debugging
Mobile Support
Guide to supporting mobile devices in contenteditable editors, including virtual keyboards and touch interactions.
- Virtual keyboard handling
- Touch selection
- Mobile input handling
- iOS/Android specific issues
Accessibility
Accessibility considerations and best practices for contenteditable editors, including screen reader support and ARIA attributes.
- Screen reader support
- ARIA attributes
- Keyboard navigation
- Focus management
- Live announcements
Transaction System
Using transactions to group operations into atomic units for consistent history management in model-based editors.
- Atomic history entries
- Transaction lifecycle
- History integration
- Transaction patterns
- Nested transactions
Operations
Comprehensive guide to operation types that can be combined in transactions for model-based editors.
- Insert operations
- Delete operations
- Format operations
- Replace and move operations
- Operation inversion
Getting Started
Recommended learning path:
- Start with Architecture: Understand model-view
separation and why it's important
→ Read Editor Architecture - Learn Model & Schema: Design your document structure
and validation rules
→ Read Model & Schema - Master Position & Selection: Understand how to
represent and manage positions in your model
→ Read Position & Selection - Implement HTML Mapping: Build serialization and
deserialization between model and HTML
→ Read HTML Mapping - Add contenteditable APIs: Use Selection API, Range
API, and events in your view layer
→ Browse Documentation
All Documentation
Editor Architecture
Model-view separation and architecture patterns
Model & Schema
Schema design and validation
Data Structures
Tree vs Flat Map strategies
Node ID System
ID vs Path addressing
Model-DOM Synchronization
Keeping model and DOM in sync
History Management
Undo/redo functionality
HTML Mapping
Serialization and parsing
Input Handling & IME
User input and IME composition
Plugin Development
Extending editor functionality
Testing Strategies
Testing editor functionality
Debugging Techniques
Debugging strategies and tools
Mobile Support
Mobile device support
Accessibility
Accessibility best practices
Transaction System
Atomic history management
Operations
Operation types and usage
CRDT Operations & Rendering
CRDT-based collaborative editing and rendering
History Management Optimization
Optimizing undo/redo performance
Error Handling & Recovery
Error handling and recovery strategies
Framework Integration
React, Vue, Svelte integration
Sanitization & Security
Security best practices
Markdown & Conversion
Import/Export guides
Advanced Features
Search, Collab, History
UI Patterns
Toolbars & Menus
Internationalization
i18n & RTL support
Related Resources
- Practical Patterns - Code examples for common patterns
- Tips - Framework integration and best practices
- Selection API - Working with browser selections
- Range API - Manipulating DOM ranges