A high-performance suggestion tracking system for CodeMirror 6 that enables real-time collaborative editing features, diff visualization, and change management with a clean, modular architecture.
- Intelligent Change Tracking: Automatically tracks additions, deletions, and replacements as users type
- Suggestion Mode: Toggle between normal editing and suggestion tracking mode
- Real-time Position Mapping: Maintains accurate positions as the document changes
- Smart Merging: Automatically merges adjacent deletions and additions into replacements
- Comments System: Add threaded comments to any text selection with optional author attribution
- Document Persistence: Save and load documents with suggestions and comments intact
- Additions: New text insertions with visual indicators
- Deletions: Text marked for removal with strikethrough styling
- Replacements: Combined deletion and addition for text substitution
- Text Selection Comments: Attach comments to specific text ranges
- Bidirectional Navigation: Click comments in editor to highlight in panel, and vice versa
- Edit & Delete: Full comment management capabilities
- Author Attribution: Optional author names for collaborative workflows
- Position Tracking: Comments maintain their positions as the document changes
- Non-intrusive Integration: Preserves normal editing behavior when suggestion mode is disabled
- Visual Feedback: Clear styling for different suggestion states (pending, accepted, rejected)
- Boundary Intelligence: Smart cursor handling at suggestion boundaries
- Bulk Operations: Accept or reject all suggestions with a single action
- Context Menus: Right-click popups for quick comment actions
npm install codemirror-suggestions-pluginimport { EditorState } from '@codemirror/state'
import { EditorView } from '@codemirror/view'
import {
suggestions,
toggleSuggestionMode,
applySuggestion,
rejectSuggestion
} from 'codemirror-suggestions-plugin'
// Initialize editor with suggestions extension
const state = EditorState.create({
doc: 'Your document content',
extensions: [
suggestions({
suggestionClass: 'cm-suggestion',
suggestionModeEnabled: false
})
]
})
const view = new EditorView({
state,
parent: document.body
})
// Enable suggestion tracking
toggleSuggestionMode(view, true)interface SuggestionsConfig {
suggestionClass?: string // Base CSS class (default: 'cm-suggestion')
acceptedClass?: string // Accepted state class
rejectedClass?: string // Rejected state class
pendingClass?: string // Pending state class
suggestionModeEnabled?: boolean // Initial mode state (default: false)
suggestionModeIndicator?: boolean // Show mode indicator (default: true)
}toggleSuggestionMode(view: EditorView, enabled?: boolean): void
getSuggestionMode(view: EditorView): booleanapplySuggestion(view: EditorView, id: string): boolean
rejectSuggestion(view: EditorView, id: string): booleanapplySuggestions(view: EditorView, ids: string[]): boolean
rejectSuggestions(view: EditorView, ids: string[]): boolean
applyAllSuggestions(view: EditorView): boolean
rejectAllSuggestions(view: EditorView): booleangetSuggestions(view: EditorView): Map<string, Suggestion>createCommentFromSelection(view: EditorView, text: string, author?: string): void
getComments(view: EditorView): Map<string, Comment>
updateComment(view: EditorView, id: string, text: string): void
deleteComment(view: EditorView, id: string): void
restoreComments(view: EditorView, comments: SerializedComment[]): voidinterface Suggestion {
from: number
to: number
insert: string
id: string
type?: 'addition' | 'deletion' | 'replacement'
insertFrom?: number
insertTo?: number
}
interface Comment {
id: string
from: number
to: number
text: string
author?: string
created: number
modified: number
}The plugin follows a modular architecture for maintainability and performance:
src/
├── types/ # TypeScript interfaces and types
├── api/ # Public API functions
├── core/
│ ├── state.ts # StateField with position mapping
│ ├── effects.ts # StateEffect definitions
│ ├── config.ts # Configuration management
│ ├── transaction-filter.ts # Transaction processing
│ ├── decorations.ts # Visual rendering
│ ├── comments-state.ts # Comment state management
│ ├── comments-effects.ts # Comment effects
│ └── comments-decorations.ts # Comment decorations
├── storage/ # Document persistence & export
│ ├── storage.ts # Storage interface
│ ├── localStorage.ts # Browser storage implementation
│ ├── export.ts # JSON/text export
│ ├── import.ts # Document import
│ └── types.ts # Storage type definitions
├── theme/ # Default styling
│ ├── index.ts # Main theme
│ └── comments.ts # Comment theme
└── suggestions.ts # Main plugin integration
demo/
├── ui/
│ ├── modals.js # Shared modal system
│ ├── suggestions-panel.js # Suggestions UI management
│ ├── comments-panel.js # Comments UI management
│ ├── comment-popup.js # Comment popup handlers
│ └── search-panel.js # Search & replace panel
├── editor/
│ ├── editor-init.js # Editor initialization
│ ├── autosave.js # Autosave functionality
│ └── import-export.js # Document import/export
└── main.js # Application entry point
dashboard/
├── ui/
│ ├── document-list.js # Document list management
│ └── import.js # Import functionality
└── main.js # Application entry point
// Get all current suggestions
const suggestions = getSuggestions(view)
// Process suggestions based on type
for (const [id, suggestion] of suggestions) {
switch(suggestion.type) {
case 'addition':
console.log(`New text: ${suggestion.insert}`)
break
case 'deletion':
const deletedText = view.state.doc.sliceString(
suggestion.from,
suggestion.to
)
console.log(`Deleted: ${deletedText}`)
break
case 'replacement':
console.log(`Replacement at ${suggestion.from}-${suggestion.to}`)
break
}
}.cm-suggestion-addition {
background-color: rgba(100, 255, 100, 0.2);
border-bottom: 2px solid #44ff44;
}
.cm-suggestion-deletion {
text-decoration: line-through;
background-color: rgba(255, 100, 100, 0.2);
}
.cm-suggestion-replacement-text {
background-color: rgba(100, 100, 255, 0.2);
border-bottom: 2px solid #4444ff;
}The project includes a full-featured demo application showcasing the plugin's capabilities:
- Document Management: Create, edit, delete, and organize documents
- Suggestion Mode: Track changes with visual diff indicators
- Comments System: Add, edit, and manage comments on text selections
- Search & Replace: Advanced find/replace with regex support
- Auto-save: Automatic persistence to browser localStorage
- Import/Export: Save and load documents as JSON
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run buildVisit http://localhost:5173 to access the dashboard and create/edit documents.
The React application follows a clean, modular architecture:
- Separation of Concerns: UI components separated from business logic
- Reusable Components: Shared components in
/app/src/shared - TypeScript: Full type safety across the application
- Modern Stack: React 18, Vite, Tailwind CSS
# Install dependencies
npm install
# Development server with hot reload
npm run dev
# Build production bundle (library + app)
npm run build
# Build library only
npm run build:lib
# Build app only
npm run build:app
# Type checking
npm run type-checkISC