Skip to content

WASM Compatibility Analysis ​

This document analyzes each module in fresh-editor for WASM compatibility, identifying blocking dependencies and potential solutions.

Key Insight: Ratatui is WASM-Compatible ​

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 types
  • ✅ Rect - layout rectangles
  • ✅ Buffer, Cell - terminal buffer abstraction
  • ✅ Frame - rendering frame (backend-agnostic)
  • ❌ crossterm backend - native terminal I/O (optional)

Ratzilla provides a WASM backend for ratatui that renders to browser canvas/DOM.


Summary ​

LayerTotal FilesWASM-ReadyNotes
model1414 (100%)✅ Complete
primitives2121 (100%)✅ Complete - all features have WASM fallbacks
input143 (21%)Needs crossterm abstraction
view70+~51 (72%)Needs Ratzilla backend
services38~5 (13%)Gate async/tokio
app370 (0%)Needs full refactor

Key insights:

  1. Syntect is WASM-compatible with fancy-regex feature → syntax highlighting for 100+ languages
  2. All tree-sitter features have WASM fallbacks → indentation, reference highlighting work without tree-sitter
  3. Crossterm event types are WASM-compatible → KeyEvent, MouseEvent, etc. are pure Rust data structures

Remaining blockers:

  1. crossterm terminal I/O - actual terminal read/write not available in WASM, use Ratzilla backend
  2. tokio/async in services - gate behind runtime
  3. PTY/signals - inherent platform limitations
  4. crate::input module - depends on crossterm I/O for event reading

Layer 1: MODEL (14 files) - 100% WASM-Ready ✅ ​

All model files are pure Rust. Already compilable to WASM.

FileStatusNotes
buffer.rs✅ ReadyUses anyhow, regex (WASM-compatible)
piece_tree.rs✅ ReadyCore data structure
piece_tree_diff.rs✅ ReadyDiff algorithms
cursor.rs✅ ReadyCursor state
marker.rs✅ ReadyMarker types
marker_tree.rs✅ ReadyInterval tree
event.rs✅ ReadyStreaming gated behind runtime
edit.rs✅ ReadyEdit operations
document_model.rs✅ ReadyDocument abstraction
control_event.rs✅ ReadyControl events
line_diff.rs✅ ReadyLine diffing
composite_buffer.rs✅ ReadyComposite buffer
filesystem.rs✅ Readylibc gated behind runtime

Status: ✅ Complete - no changes needed.


Layer 2: PRIMITIVES (21 files) - 100% WASM-Ready ✅ ​

All Features Have WASM-Compatible Implementations ​

Every primitive feature now has a pure-Rust WASM-compatible implementation:

FeatureWASM ModuleRuntime ModuleNotes
Syntax highlighting—highlight_engine.rsThe syntect-only textmate_engine.rs mirror was removed unused; a WASM build would need a syntect-only mode of highlight_engine.rs
Auto-indentationindent_pattern.rsindent.rsPattern-based heuristics
Reference highlightingreference_highlight_text.rsreference_highlighter.rsText matching

WASM-Ready (All 21 files) ​

FileStatusDependencies
display_width.rs✅ Readyunicode-width
grapheme.rs✅ Readyunicode-segmentation
snippet.rs✅ ReadyPure Rust
text_property.rs✅ ReadyPure Rust
path_utils.rs✅ Readystd::path
line_wrapping.rs✅ Readydisplay_width
line_iterator.rs✅ Readymodel::buffer
word_navigation.rs✅ Readymodel::buffer, grapheme
ansi.rs✅ Readyratatui::style
ansi_background.rs✅ Readyratatui::style
visual_layout.rs✅ Readyansi, display_width
grammar/types.rs✅ Readysyntect with fancy-regex
highlight_types.rs✅ ReadyCommon highlighting types
indent_pattern.rs✅ ReadyPattern-based indentation
reference_highlight_text.rs✅ ReadyText-based word matching

Runtime-Enhanced (4 files) ​

These modules provide enhanced features using tree-sitter AST analysis. WASM builds use the pure-Rust alternatives above.

FileEnhancementWASM Alternative
highlight_engine.rsUnified engine with tree-sitter—
highlighter.rsTree-sitter highlighting—
indent.rsAST-aware smart indentationindent_pattern.rs
reference_highlighter.rsScope-aware semantic highlightingreference_highlight_text.rs

Layer 3: INPUT (14 files) - 21% WASM-Ready ​

Blocker: crossterm::event types ​

The input layer uses crossterm::event::{KeyCode, KeyEvent, KeyModifiers} for keyboard handling.

WASM-Ready (3 files) ​

FileStatusNotes
fuzzy.rs✅ ReadyPure fuzzy matching algorithm
input_history.rs✅ ReadyPure data structure
position_history.rs✅ ReadyPure data structure

Needs Abstraction (11 files) ​

FileBlockerSolution
handler.rsKeyCode, KeyEventAbstract to platform-agnostic types
keybindings.rsKeyCode, KeyModifiersUse abstract types
key_translator.rsKeyCode, KeyEventConversion layer
buffer_mode.rsKeyCode, KeyModifiersUse abstract types
composite_router.rsKeyCode, KeyEventUse abstract types
actions.rsIndirectUpdate when handler changes
commands.rsIndirectUpdate when handler changes
command_registry.rsIndirectUpdate when handler changes
multi_cursor.rsIndirectUpdate when handler changes
action.rsIndirectUpdate when handler changes
vim_mode.rsKeyCodeUse abstract types

Create abstract input types in fresh-core:

rust
/// 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.


Layer 4: VIEW (70+ files) - 70% WASM-Ready ​

Key Insight ​

Most view files only use ratatui types (Color, Style, Rect, Buffer), which are WASM-compatible. The blockers are:

  1. crossterm::event - Input handling in some view files
  2. Terminal I/O - Actual rendering to terminal (use Ratzilla instead)

WASM-Ready (~50 files) ​

Files using only ratatui types (no crossterm):

CategoryFilesStatus
Stylingcolor_support.rs, margin.rs, overlay.rs, stream.rs, virtual_text.rs✅ Ready
Layoutcomposite_view.rs, dimming.rs, split.rs, popup_mouse.rs✅ Ready
Renderingmarkdown.rs, reference_highlight_overlay.rs✅ Ready
Themetheme.rs, theme/*.rs (once filesystem abstracted)✅ Ready
UI ComponentsMost of view/ui/*.rs✅ Ready

Needs Gating (~16 files) ​

Files with crossterm input handling:

FileBlockerSolution
file_browser_input.rscrossterm::eventUse abstract KeyEvent
popup_input.rscrossterm::eventUse abstract KeyEvent
prompt_input.rscrossterm::eventUse abstract KeyEvent
query_replace_input.rscrossterm::eventUse abstract KeyEvent

Inherent Blockers (~4 files) ​

FileReason
calibration_wizard.rsInteractive terminal calibration
terminal_view.rsTerminal emulator display

WASM Rendering Strategy ​

For WASM, use Ratzilla as the ratatui backend:

rust
// 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.


Layer 5: SERVICES (38 files) - Mixed ​

WASM-Ready (5 files) ​

FileStatusNotes
log_dirs.rs✅ ReadyPath utilities
time_source.rs✅ ReadyTime abstraction
warning_log.rs✅ ReadyIn-memory log
recovery/types.rs✅ ReadyData types
styled_html.rs✅ ReadyHTML generation

Needs Gating (28 files) ​

File/ModuleBlockerSolution
clipboard.rsarboard, crossterm OSC52Use browser Clipboard API
fs/manager.rstokio::syncGate behind runtime
lsp/*.rslsp_types, tokioGate (LSP not in browser)
plugins/*.rstokio, plugin runtimeGate or WASM plugin runtime
recovery/*.rsstd::fsUse FileSystem trait
release_checker.rsureq (HTTP)Use fetch API
telemetry.rsNetwork I/OGate
gpm/*.rsGPM mouse protocolGate (native terminal only)
tracing_setup.rstracing-subscriberUse web console

Inherent Blockers (5 files) ​

FileReason
terminal/pty.rsPTY requires OS process spawning
terminal/term.rsalacritty_terminal is native-only
terminal/manager.rsDepends on PTY
signal_handler.rsUnix signals don't exist in browser
process_limits.rsOS-level resource limits

These are fundamentally incompatible with browsers and must remain runtime-only.


Layer 6: APP (37 files) - Needs Refactoring ​

The app layer orchestrates all other layers. Key changes needed:

AreaChange Needed
InputUse abstract KeyEvent types
RenderingSupport both crossterm and Ratzilla backends
ServicesGate runtime-only services
TerminalGate PTY/terminal emulator features

Revised Refactoring Plan ​

Phase 1: Input Abstraction (3-5 days) ​

  1. Create KeyCode, Modifiers, KeyEvent in fresh-core
  2. Add conversion traits for crossterm (runtime) and web_sys (wasm)
  3. Update input layer to use abstract types
  4. Update view files with input handling

Phase 2: Backend Abstraction (1 week) ​

  1. Add Ratzilla dependency for WASM builds
  2. Create backend selection based on feature flags
  3. Update app layer to use selected backend
  4. Test with both backends

Phase 3: Service Gating (3-5 days) ​

  1. Gate LSP, plugins, terminal behind runtime
  2. Abstract clipboard with trait
  3. Update filesystem operations to use FileSystem trait
  4. Provide WASM stubs where needed

Phase 4: Integration & Testing (1 week) ​

  1. Build WASM target
  2. Create browser demo
  3. Performance testing
  4. Cross-browser compatibility

Revised total effort: 3-4 weeks (down from 10-12 weeks)


Current Status ​

Model layer: ✅ 100% WASM-compatible Primitives layer: ✅ 100% WASM-compatible

Completed:

  • ✅ Model layer WASM-compatible
  • ✅ FileSystem trait abstracted with NoopFileSystem for WASM
  • ✅ Event streaming gated behind runtime
  • ✅ Config runtime-specific functions gated
  • ✅ WASM feature flag added to Cargo.toml
  • ✅ Basic wasm module with WasmEditor wrapper
  • ✅ Syntect enabled for WASM with fancy-regex feature (pure Rust regex)
  • ✅ Grammar module WASM-compatible (TextMate grammar loading via syntect)
  • ✅ Theme types WASM-compatible (view/theme/types.rs)
  • ✅ Auto-indentation: indent_pattern.rs (pattern-based)
  • ✅ Reference highlighting: reference_highlight_text.rs (text matching)

Next steps:

  1. Input abstraction (biggest remaining blocker)
  2. Add Ratzilla for WASM rendering
  3. Gate remaining services

Released under the Apache 2.0 License