Editor System
Hibiscus features a powerful Monaco-based editor with support for syntax highlighting, multiple files, markdown preview, and seamless theme integration.
Editor View
The EditorView component wraps Microsoft's Monaco Editor with Hibiscus-specific enhancements:
Core Features
- Syntax Highlighting: 50+ languages supported
- Auto-completion: IntelliSense for many languages
- Error Diagnostics: Real-time error highlighting
- Multiple Cursors: Alt+Click for multi-cursor editing
- Find & Replace: Ctrl+F / Ctrl+H
- Minimap: Code overview (toggle in settings)
- Line Numbers: Toggleable gutter display
- Word Wrap: Soft wrapping for long lines
Editor Layout
┌─────────────────────────────────────────────────────┐
│ Tab Bar (open files) │
├─────────────────────────────────────────────────────┤
│ │
│ 1 │ # Heading │ │
│ 2 │ Content here... │ ┌─────────┐ │
│ 3 │ - List item 1 │ │ Preview │ │
│ 4 │ - List item 2 │ │ Panel │ │
│ 5 │ │ │ (50%) │ │
│ 6 │ ## Section 2 │ │ │ │
│ 7 │ More content... │ │ │ │
│ │ │ └─────────┘ │
│ │ [Editor: 50%] [Preview: 50%] │
│ │
└─────────────────────────────────────────────────────┘
File Renderer
The FileRenderer component handles different file types:
Supported Formats
| Type | Extension | Rendering Mode |
|---|---|---|
| Markdown | .md, .markdown |
Editor + Live preview |
| Text | .txt |
Editor with syntax highlight |
| Code | .js, .ts, .py, .rs, etc. |
Editor with syntax highlight |
.pdf |
Paginated viewer (all pages) | |
| DOCX | .docx |
Styled document viewer |
| Images | .png, .jpg, .gif, .svg, etc. |
Native image preview |
Binary Document Viewers (PDF & DOCX)
PDF and DOCX files are read-only in Hibiscus — they open in a dedicated viewer rather than Monaco. A toolbar above each viewer shows a "Read-only" badge and an "Extract to Note" button.
PDF viewer:
- Renders all pages in a vertical scroll, each in its own framed canvas.
- Sized to the actual container width via ResizeObserver (previously used window.innerWidth, which broke in narrower layouts).
- Reloads automatically when the file changes on disk.
- Page labels (Page 1, Page 2, …) match the section headings used in the knowledge index, so search results and viewer stay in sync.
DOCX viewer:
- Converts the document to HTML using mammoth.js in the frontend.
- The raw mammoth output is sanitised through DOMParser before rendering: <script> tags, on* event attributes, and javascript: / data:text/html URIs are stripped. No external sanitiser library required.
- Styled as a page-column layout (max-width: 72ch) via FileRenderer.css CSS variables — fully themed with the rest of the app.
- Cache invalidated on fs-changed events: if you edit the file in Word and save, reopening or switching back to the tab shows the updated content.
Why binary files are read-only
Monaco is kept mounted and hidden at all times (it must never unmount, to avoid the persistent corruption bug). This means it is bound to whatever buffer is in memory for the active file, including the empty placeholder for PDFs and DOCX files. Multiple code paths in useEditorController could previously reach write_text_file with that empty buffer — silently zeroing the document:
- Auto-save (1 s debounce after any
onChangeevent, even from Monaco while hidden) - "Save As" (wrote the buffer instead of copying bytes)
- Unmount handler (flushed all dirty buffers)
- Session restore (reloaded all paths as text, discarding the binary file's tab)
Every one of these paths now checks isBinaryFile(path) and bails out early. copy_file is used for binary Save As. Regression tests in tests/binaryFileSafety.test.ts cover all failure modes.
Markdown Preview
Toggle markdown preview with Ctrl+Shift+V:
Features: - Live preview updates as you type - GitHub-flavored Markdown support - Syntax highlighting in code blocks - Task list checkboxes clickable - Links clickable (internal and external)
Preview Features: - Scroll sync (editor ↔ preview) (planned) - Export to HTML (planned) - Print-friendly styling
Extract to Note
The "Extract to Note" button in the document toolbar triggers the extract_document_to_note Tauri command. It runs the full knowledge parser (same one the indexer uses) and writes a structured Markdown file alongside the original document:
document.pdf → document-note.md (or document-note-2.md if that exists)
research.docx → research-note.md
The resulting note has YAML frontmatter recording the source path, and the body preserves the heading structure extracted from the document (page numbers for PDFs, Word heading styles for DOCX). The indexer picks it up immediately as a regular note, making it searchable, linkable, and visible in the graph. This is the recommended path if you need to add wiki-links or annotations to a PDF or DOCX — edit the note, not the original.
File Loading States
Loading... → Reading file from disk
Parsing... → Determining file type
Rendering... → Setting up editor model
Ready → Editor ready for input
Monaco Integration
Editor Configuration
The editor is configured via editorConfig.ts:
export const defaultEditorOptions = {
fontSize: 14,
fontFamily: "'JetBrains Mono', 'Fira Code', monospace",
minimap: { enabled: true },
wordWrap: "on",
lineNumbers: "on",
automaticLayout: true,
scrollBeyondLastLine: false,
renderWhitespace: "selection",
tabSize: 2,
insertSpaces: true,
}
Theme Adaptation
Monaco themes are dynamically generated from Hibiscus CSS variables:
Process:
1. Read CSS variables from :root
2. Convert to Monaco theme format
3. Apply via editor.defineTheme()
4. Update when Hibiscus theme changes
Example Adaptation:
// CSS variables → Monaco theme
const theme = {
base: "vs-dark",
inherit: true,
rules: [
{ token: "", foreground: css.textPrimary },
{ token: "comment", foreground: css.textMuted },
{ token: "keyword", foreground: css.accent },
],
colors: {
"editor.background": css.bgPrimary,
"editor.foreground": css.textPrimary,
"editor.lineHighlightBackground": css.bgSecondary,
}
}
Tab Bar Integration
The editor works seamlessly with the tab bar:
Tab States
- Clean: No unsaved changes
- Dirty: Unsaved modifications (dot indicator)
- Active: Currently visible tab
- Background: Open but not visible
Model Management
Monaco uses a model-per-file system:
- File Opened: Model created from file content
- Tab Switched: Editor swaps to new model (instant)
- File Closed: Model disposed to free memory
- File Saved: Model marked as clean
Performance
- No Remounting: Editor component persists across tab switches
- Lazy Loading: Models created only when files opened
- Memory Cleanup: Closed file models disposed
- Cursor Restoration: Position restored when reopening files
Auto-Save
Hibiscus features intelligent auto-save:
Save Behavior
- Auto-save: 1-second debounce after typing stops
- Manual Save: Ctrl+S for immediate save
- Save All: Ctrl+Shift+S for all dirty files
- Dirty Indicator: Dot in tab shows unsaved changes
Save Strategy
Files are saved atomically to prevent corruption:
1. Write to temp file: .filename.hibiscus-save~
2. Sync to disk
3. Delete original (Windows)
4. Rename temp to original
5. Cleanup on any failure
Keyboard Shortcuts
Editor Shortcuts
| Shortcut | Action |
|---|---|
Ctrl+S |
Save current file |
Ctrl+Shift+S |
Save all files |
Ctrl+F |
Find in file |
Ctrl+H |
Replace in file |
Ctrl+G |
Go to line |
Ctrl+/ |
Toggle line comment |
Ctrl+D |
Select next occurrence |
Ctrl+L |
Select current line |
Alt+↑/↓ |
Move line up/down |
Ctrl+Shift+K |
Delete current line |
Ctrl+Space |
Trigger autocomplete |
F1 |
Command palette |
Monaco Shortcuts
Standard Monaco shortcuts work:
- Multi-cursor: Alt+Click
- Column selection: Alt+Shift+Drag
- Expand selection: Shift+Alt+→
- Shrink selection: Shift+Alt+←
Cursor Position Tracking
The editor tracks cursor position for the status bar:
interface CursorPosition {
line: number // 1-indexed line number
column: number // 1-indexed column number
}
Status Bar Display:
File Change Detection
External Changes
When a file is modified outside Hibiscus:
- File watcher detects change
- Compare SHA-256 hash
- If different, mark as "modified externally"
- User chooses: Reload | Keep current | Merge (planned)
Conflict Resolution
For conflicts between disk and buffer:
┌─────────────────────────────────────────┐
│ File Changed on Disk │
├─────────────────────────────────────────┤
│ "notes.md" was modified by another │
│ program. What would you like to do? │
│ │
│ [Keep Current] [Reload from Disk] │
└─────────────────────────────────────────┘
Error Handling
File Read Errors
- Permission Denied: Show error notification
- File Not Found: Remove from tree/session
- Binary File: Open in hex viewer (planned)
- Too Large: Warn and offer read-only mode
Editor Errors
- Parse Errors: Highlight in editor
- Save Errors: Show error, keep dirty state
- Model Errors: Recreate model from file
Screenshots
[PHOTO PLACEHOLDER: Editor with Markdown Preview] Add screenshot showing split view with editor on left and markdown preview on right
[PHOTO PLACEHOLDER: Syntax Highlighting] Add screenshot showing code editor with syntax highlighting for a programming language
[PHOTO PLACEHOLDER: Editor in Focus Mode] Add screenshot showing editor taking full width in focus mode
Troubleshooting
Editor Not Loading
- Check Monaco loader initialized
- Verify no JavaScript errors in console
- Try restarting Hibiscus
Preview Not Showing
- Only works for markdown files
- Check
showMarkdownPreviewsetting - Toggle with
Ctrl+Shift+V
Slow Performance
- Disable minimap for large files
- Turn off word wrap for code files
- Close unused tabs to free memory
Theme Not Applied
- Editor themes sync with Hibiscus theme
- Restart may be needed after theme change
- Check CSS variables are properly defined
Related Documentation
- Multi-File Editor - Tab management
- Theming System - Editor color schemes
- Keyboard Shortcuts - Complete shortcut reference