Editor Component
Relevant source files
The following files were used as context for generating this wiki page:
The Editor Component is the primary interface for content creation and modification within the Augenblick application. It is built using the Tiptap framework (specifically migrated from Milkdown) and provides a specialized Markdown editing experience tailored for ephemeral note-taking. The editor maintains content as Markdown on disk while providing a rich, ProseMirror-powered WYSIWYG interface in the frontend.
The component supports two primary modes: an editable mode for active notes and a read-only mode for previewing notes in the trash. It integrates deeply with the Tauri environment for features like external link handling and file persistence.
Sources: plans/migration.editor.tiptap.md:5-9, src/features/editor/Editor.tsx:23-27
Architecture and Core Technologies
The editor follows a phased migration from a Milkdown-based stack to a Tiptap stack (MIT licensed). It leverages the useEditor hook from @tiptap/react to manage the lifecycle and state of the ProseMirror instance.
Technical Stack
| Package | Purpose |
|---|---|
@tiptap/react | Core React integration and component wrappers. |
@tiptap/starter-kit | Standard ProseMirror extensions (Bold, Italic, etc.). |
@tiptap/markdown | Adds contentType: 'markdown' and conversion capabilities. |
lowlight | Syntax highlighting for code blocks. |
@tauri-apps/plugin-opener | Securely opens links in the system's default browser. |
Sources: plans/migration.editor.tiptap.md:32-37, package.json:28-40, src/features/editor/Editor.tsx:4-15
Implementation Logic
The component uses useRef to maintain a stable reference to the latest Markdown content (lastMarkdownRef) to prevent infinite loop updates during prop synchronization. When external data changes, the editor uses editor.commands.setContent to refresh the view.
Component Features
Markdown Extensions
The editor implements several specialized extensions to handle Markdown-specific behaviors that aren't native to ProseMirror's default node structure.
- MarkdownImageText/TableText: Custom extensions that parse raw Markdown image and table tokens into text nodes or paragraph nodes respectively, ensuring raw Markdown structure is preserved if complex nodes aren't fully rendered.
- Task Lists: Implemented via
TaskListandTaskItem, allowing for interactive checkboxes. - Syntax Highlighting: Uses
CodeBlockLowlightwithlowlightfor GFM-compatible code blocks.
Sources: src/features/editor/Editor.tsx:32-51, src/features/editor/Editor.tsx:84-93
Specialized Input Handling
The component overrides default browser behaviors to align with the application's desktop nature.
| Feature | Implementation Detail |
|---|---|
| Link Opening | Overrides click events to require Meta or Ctrl key modifiers to open URLs via Tauri. |
| Markdown Paste | Intercepts paste events, parses text/plain as Markdown content, and inserts it as structured ProseMirror nodes. |
| Focus Management | Listens for the augenblick:focus-editor window event to programmatically focus the editor at the end of the content. |
Sources: src/features/editor/Editor.tsx:106-135, src/test/features/Editor.test.tsx:170-192
User Interface Elements
Bubble Menu
The BubbleMenu appears when text is selected or when a link mark is active. It provides quick access to formatting tools and a custom link management sub-interface.
Styling and Layout
The editor layout is optimized for readability with a maximum width of 720px and uses CSS variables for theme-aware colors.
- Outer Container:
h-full overflow-autowith backgroundvar(--bg-primary). - Inner Wrapper:
mx-auto max-w-[720px] px-10. - Titlebar Offset: Uses
var(--titlebar-inset, 0px)for padding-top to avoid overlapping with the custom Tauri titlebar drag region. - Placeholder: A "Start writing..." placeholder is displayed via the
@tiptap/extension-placeholderwhen the document is empty.
Sources: src/features/editor/Editor.tsx:205-212, src/App.css:220-235, plans/migration.editor.md:15-22
Data Flow and Persistence
The Editor Component acts as a bridge between the user's input and the application's state management.
- Initial Load:
App.tsxlazy-loads the Editor and passes theselectedContentfrom thenotesStore. - State Sync: Changes in the editor trigger the
onChangecallback, whichApp.tsxroutes tonotesStore.updateContent. - Autosave: The
notesStoremanages a debounce timer (500ms) to write the Markdown content to the filesystem via the Tauri Rust backend.
Sources: src/App.tsx:300-320, src/stores/notesStore.ts:200-215, plans/migration.inventory.md:120-125
Conclusion
The Editor Component is a robust Markdown editing solution that balances rich-text convenience with raw file-based storage requirements. By utilizing a modular Tiptap extension system and Tauri-specific event handling, it provides a performant interface that supports complex Markdown features like tables and tasks while adhering to the project's "no-hacks" architectural constraint. Its ability to switch between read-only and editable modes ensures consistent content rendering throughout the note lifecycle.