docs/wasm.md
This document analyzes each module in fresh-editor for WASM compatibility, identifying blocking dependencies and potential solutions.
Ratatui itself is WASM-compatible. The library is a rendering abstraction that writes to a Buffer of Cells. The platform-specific part is only the backend (like crossterm) that handles actual terminal I/O.
With default-features = false, ratatui provides:
Color, Style, Modifier - styling typesRect - layout rectanglesBuffer, Cell - terminal buffer abstractionFrame - rendering frame (backend-agnostic)crossterm backend - native terminal I/O (optional)Ratzilla provides a WASM backend for ratatui that renders to browser canvas/DOM.
| Layer | Total Files | WASM-Ready | Notes |
|---|---|---|---|
| model | 14 | 14 (100%) | ✅ Complete |
| primitives | 21 | 21 (100%) | ✅ Complete - all features have WASM fallbacks |
| input | 14 | 3 (21%) | Needs crossterm abstraction |
| view | 70+ | ~51 (72%) | Needs Ratzilla backend |
| services | 38 | ~5 (13%) | Gate async/tokio |
| app | 37 | 0 (0%) | Needs full refactor |
Key insights:
fancy-regex feature → syntax highlighting for 100+ languagesKeyEvent, MouseEvent, etc. are pure Rust data structuresRemaining blockers:
All model files are pure Rust. Already compilable to WASM.
| File | Status | Notes |
|---|---|---|
| buffer.rs | ✅ Ready | Uses anyhow, regex (WASM-compatible) |
| piece_tree.rs | ✅ Ready | Core data structure |
| piece_tree_diff.rs | ✅ Ready | Diff algorithms |
| cursor.rs | ✅ Ready | Cursor state |
| marker.rs | ✅ Ready | Marker types |
| marker_tree.rs | ✅ Ready | Interval tree |
| event.rs | ✅ Ready | Streaming gated behind runtime |
| edit.rs | ✅ Ready | Edit operations |
| document_model.rs | ✅ Ready | Document abstraction |
| control_event.rs | ✅ Ready | Control events |
| line_diff.rs | ✅ Ready | Line diffing |
| composite_buffer.rs | ✅ Ready | Composite buffer |
| filesystem.rs | ✅ Ready | libc gated behind runtime |
Status: ✅ Complete - no changes needed.
Every primitive feature now has a pure-Rust WASM-compatible implementation:
| Feature | WASM Module | Runtime Module | Notes |
|---|---|---|---|
| Syntax highlighting | textmate_engine.rs | highlight_engine.rs | Syntect with fancy-regex |
| Auto-indentation | indent_pattern.rs | indent.rs | Pattern-based heuristics |
| Reference highlighting | reference_highlight_text.rs | reference_highlighter.rs | Text matching |
| File | Status | Dependencies |
|---|---|---|
| display_width.rs | ✅ Ready | unicode-width |
| grapheme.rs | ✅ Ready | unicode-segmentation |
| snippet.rs | ✅ Ready | Pure Rust |
| text_property.rs | ✅ Ready | Pure Rust |
| path_utils.rs | ✅ Ready | std::path |
| line_wrapping.rs | ✅ Ready | display_width |
| line_iterator.rs | ✅ Ready | model::buffer |
| word_navigation.rs | ✅ Ready | model::buffer, grapheme |
| ansi.rs | ✅ Ready | ratatui::style |
| ansi_background.rs | ✅ Ready | ratatui::style |
| visual_layout.rs | ✅ Ready | ansi, display_width |
| grammar/types.rs | ✅ Ready | syntect with fancy-regex |
| highlight_types.rs | ✅ Ready | Common highlighting types |
| textmate_engine.rs | ✅ Ready | Syntect-only highlighting |
| indent_pattern.rs | ✅ Ready | Pattern-based indentation |
| reference_highlight_text.rs | ✅ Ready | Text-based word matching |
These modules provide enhanced features using tree-sitter AST analysis. WASM builds use the pure-Rust alternatives above.
| File | Enhancement | WASM Alternative |
|---|---|---|
| highlight_engine.rs | Unified engine with tree-sitter | textmate_engine.rs |
| highlighter.rs | Tree-sitter highlighting | textmate_engine.rs |
| indent.rs | AST-aware smart indentation | indent_pattern.rs |
| reference_highlighter.rs | Scope-aware semantic highlighting | reference_highlight_text.rs |
The input layer uses crossterm::event::{KeyCode, KeyEvent, KeyModifiers} for keyboard handling.
| File | Status | Notes |
|---|---|---|
| fuzzy.rs | ✅ Ready | Pure fuzzy matching algorithm |
| input_history.rs | ✅ Ready | Pure data structure |
| position_history.rs | ✅ Ready | Pure data structure |
| File | Blocker | Solution |
|---|---|---|
| handler.rs | KeyCode, KeyEvent | Abstract to platform-agnostic types |
| keybindings.rs | KeyCode, KeyModifiers | Use abstract types |
| key_translator.rs | KeyCode, KeyEvent | Conversion layer |
| buffer_mode.rs | KeyCode, KeyModifiers | Use abstract types |
| composite_router.rs | KeyCode, KeyEvent | Use abstract types |
| actions.rs | Indirect | Update when handler changes |
| commands.rs | Indirect | Update when handler changes |
| command_registry.rs | Indirect | Update when handler changes |
| multi_cursor.rs | Indirect | Update when handler changes |
| action.rs | Indirect | Update when handler changes |
| vim_mode.rs | KeyCode | Use abstract types |
Create abstract input types in fresh-core:
/// Platform-agnostic key code
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum KeyCode {
Char(char),
Enter, Esc, Backspace, Delete, Tab,
Left, Right, Up, Down,
Home, End, PageUp, PageDown,
F(u8),
}
/// Platform-agnostic modifiers
#[derive(Debug, Clone, Copy, Default)]
pub struct Modifiers {
pub ctrl: bool,
pub alt: bool,
pub shift: bool,
pub super_key: bool,
}
/// Platform-agnostic key event
#[derive(Debug, Clone)]
pub struct KeyEvent {
pub code: KeyCode,
pub modifiers: Modifiers,
}
// Conversions
#[cfg(feature = "runtime")]
impl From<crossterm::event::KeyEvent> for KeyEvent { ... }
#[cfg(feature = "wasm")]
impl From<web_sys::KeyboardEvent> for KeyEvent { ... }
Effort: 1-2 days to create abstraction and update input layer.
Most view files only use ratatui types (Color, Style, Rect, Buffer), which are WASM-compatible. The blockers are:
Files using only ratatui types (no crossterm):
| Category | Files | Status |
|---|---|---|
| Styling | color_support.rs, margin.rs, overlay.rs, stream.rs, virtual_text.rs | ✅ Ready |
| Layout | composite_view.rs, dimming.rs, split.rs, popup_mouse.rs | ✅ Ready |
| Rendering | markdown.rs, reference_highlight_overlay.rs | ✅ Ready |
| Theme | theme.rs, theme/*.rs (once filesystem abstracted) | ✅ Ready |
| UI Components | Most of view/ui/*.rs | ✅ Ready |
Files with crossterm input handling:
| File | Blocker | Solution |
|---|---|---|
| file_browser_input.rs | crossterm::event | Use abstract KeyEvent |
| popup_input.rs | crossterm::event | Use abstract KeyEvent |
| prompt_input.rs | crossterm::event | Use abstract KeyEvent |
| query_replace_input.rs | crossterm::event | Use abstract KeyEvent |
| File | Reason |
|---|---|
| calibration_wizard.rs | Interactive terminal calibration |
| terminal_view.rs | Terminal emulator display |
For WASM, use Ratzilla as the ratatui backend:
// Native (runtime feature)
#[cfg(feature = "runtime")]
use ratatui::backend::CrosstermBackend;
// WASM (wasm feature)
#[cfg(feature = "wasm")]
use ratzilla::backend::DomBackend;
This allows the same rendering code to work on both platforms.
| File | Status | Notes |
|---|---|---|
| log_dirs.rs | ✅ Ready | Path utilities |
| time_source.rs | ✅ Ready | Time abstraction |
| warning_log.rs | ✅ Ready | In-memory log |
| recovery/types.rs | ✅ Ready | Data types |
| styled_html.rs | ✅ Ready | HTML generation |
| File/Module | Blocker | Solution |
|---|---|---|
| clipboard.rs | arboard, crossterm OSC52 | Use browser Clipboard API |
| fs/manager.rs | tokio::sync | Gate behind runtime |
| lsp/*.rs | lsp_types, tokio | Gate (LSP not in browser) |
| plugins/*.rs | tokio, plugin runtime | Gate or WASM plugin runtime |
| recovery/*.rs | std::fs | Use FileSystem trait |
| release_checker.rs | ureq (HTTP) | Use fetch API |
| telemetry.rs | Network I/O | Gate |
| gpm/*.rs | GPM mouse protocol | Gate (native terminal only) |
| tracing_setup.rs | tracing-subscriber | Use web console |
| File | Reason |
|---|---|
| terminal/pty.rs | PTY requires OS process spawning |
| terminal/term.rs | alacritty_terminal is native-only |
| terminal/manager.rs | Depends on PTY |
| signal_handler.rs | Unix signals don't exist in browser |
| process_limits.rs | OS-level resource limits |
These are fundamentally incompatible with browsers and must remain runtime-only.
The app layer orchestrates all other layers. Key changes needed:
| Area | Change Needed |
|---|---|
| Input | Use abstract KeyEvent types |
| Rendering | Support both crossterm and Ratzilla backends |
| Services | Gate runtime-only services |
| Terminal | Gate PTY/terminal emulator features |
KeyCode, Modifiers, KeyEvent in fresh-coreRevised total effort: 3-4 weeks (down from 10-12 weeks)
Model layer: ✅ 100% WASM-compatible Primitives layer: ✅ 100% WASM-compatible
Completed:
fancy-regex feature (pure Rust regex)textmate_engine.rs (100+ languages)indent_pattern.rs (pattern-based)reference_highlight_text.rs (text matching)Next steps: