Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Operations & CRDT

All document mutations go through the Operation enum:

#![allow(unused)]
fn main() {
enum Operation {
    InsertNode { parent_id, index, node },
    DeleteNode { target_id },
    MoveNode { target_id, new_parent_id, new_index },
    InsertText { target_id, offset, text },
    DeleteText { target_id, offset, length },
    SetAttributes { target_id, attributes },
    RemoveAttributes { target_id, keys },
    SetMetadata { key, value },
    SetStyle { style },
    RemoveStyle { style_id },
}
}

Undo/Redo

Every operation produces an inverse. Applying the inverse undoes the change:

InsertNode → inverse: DeleteNode (with snapshot)
InsertText → inverse: DeleteText
SetAttributes → inverse: SetAttributes (with previous values)

Transactions

Multiple operations can be grouped into a Transaction for atomic undo:

#![allow(unused)]
fn main() {
let mut txn = Transaction::with_label("Bold selection");
txn.push(Operation::set_attributes(run1, bold_attrs));
txn.push(Operation::set_attributes(run2, bold_attrs));
doc.apply_transaction(&txn)?;
// Single undo reverts both
}

CRDT (Fugue)

The CRDT layer (s1-crdt) uses the Fugue algorithm for text:

  • Each character has a unique ID + origin references
  • Concurrent inserts produce deterministic interleaving
  • State vectors track what each replica has seen
  • Convergence guaranteed regardless of operation order