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-compatibleKeyEvent, 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 highlightingtextmate_engine.rshighlight_engine.rsSyntect with fancy-regex
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
textmate_engine.rs✅ ReadySyntect-only highlighting
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-sittertextmate_engine.rs
highlighter.rsTree-sitter highlightingtextmate_engine.rs
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)
  • Syntax highlighting: textmate_engine.rs (100+ languages)
  • 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