Skip to main content
The Editor component is the main code editing interface, built on top of CodeMirror 6. It provides syntax highlighting, language detection, theme support, and real-time content change handling.

Usage

import Editor from '@/components/Editor';

function App() {
  return (
    <EditorProvider>
      <Editor />
    </EditorProvider>
  );
}

Features

Syntax Highlighting

The Editor automatically detects file language based on file extension and applies appropriate syntax highlighting:
  • JavaScript/TypeScript (.js, .jsx, .ts, .tsx, .mjs, .cjs)
  • Python (.py)
  • HTML (.html, .htm)
  • CSS (.css)
  • JSON (.json)
  • Markdown (.md, .markdown)
  • Rust (.rs)

Language Detection

Language extensions are loaded dynamically using the getLanguageExtension() utility:
const langExt = getLanguageExtension(activeFile.name);
if (langExt) {
  extensions.push(langExt);
}

Content Change Handling

The editor tracks document changes and updates the file state:
EditorView.updateListener.of((update) => {
  if (update.docChanged) {
    handleContentChange(update.state.doc.toString());
  }
})

Theme Support

Custom themes are applied using CodeMirror extensions:
const extensions = [
  createThemeExtension(currentTheme.editor.bg, currentTheme.editor.fg),
  createSyntaxHighlighting(currentTheme.syntax),
];

CodeMirror Extensions

The Editor uses the following CodeMirror extensions:
basicSetup
Extension
Provides essential editor features (line numbers, bracket matching, etc.)
history()
Extension
Enables undo/redo functionality
keymap
Extension
Configures keyboard shortcuts using defaultKeymap and historyKeymap
createThemeExtension
(bg: string, fg: string) => Extension
Custom theme extension for background and foreground colors
createSyntaxHighlighting
(syntax: SyntaxConfig) => Extension
Applies syntax highlighting based on theme configuration
EditorView.updateListener
Extension
Listens for document changes and triggers content updates
getLanguageExtension
(filename: string) => Extension | null
Returns the appropriate language extension based on file extension

Context Integration

The Editor component relies on the useEditor hook from the EditorContext:

Consumed Properties

openFiles
OpenFile[]
Array of currently open files
interface OpenFile {
  path: string;
  name: string;
  content: string;
  modified: boolean;
}
activeFilePath
string | null
Path of the currently active file being edited
setActiveFilePath
(path: string | null) => void
Function to set the active file path
handleCloseTab
(path: string) => void
Function to close a file tab
handleContentChange
(content: string) => void
Function called when editor content changes. Updates the file’s content and marks it as modified
currentTheme
ThemeConfig
Current theme configuration object
interface ThemeConfig {
  editor: { bg: string; fg: string; };
  syntax: {
    keyword: string;
    string: string;
    comment: string;
    // ... more syntax colors
  };
}

State Management

The component uses React refs to maintain CodeMirror instances:
const editorRef = useRef<HTMLDivElement>(null);
const viewRef = useRef<EditorView | null>(null);
The editor view is recreated when:
  • Active file path changes
  • Active file name changes
  • Theme colors change

Empty State

When no file is open, the editor displays:
<p className="opacity-40 text-xl">
  Open a folder (File → Open Folder or Ctrl+O)
</p>

Example: Full Integration

import { EditorProvider } from '@/lib/editor-context';
import Editor from '@/components/Editor';

function CodeEditor() {
  return (
    <EditorProvider>
      <div className="flex">
        <Sidebar />
        <Editor />
      </div>
    </EditorProvider>
  );
}

Reference

Source: src/components/Editor.tsx Dependencies:
  • codemirror - CodeMirror 6 core
  • @codemirror/commands - Editor commands
  • @codemirror/state - Editor state management
  • @codemirror/view - Editor view
  • @codemirror/lang-* - Language support packages

Build docs developers (and LLMs) love