1 min read·Run it here

Design a Text Document Editor

Class state seeded by a constructor, edits applied through a public method, then undo/redo by storing inverse operations on stacks.

Pattern
Class state -> inverse operations -> stacks
Time
O(n) per edit
Space
O(history)

This is the class-mechanics rep. A TextDocument is just state plus a public API. EditorHistory is the wrapper that turns mutations into reversible operations.

The recipe

Say before you type: "The constructor seeds private state. apply mutates through slices. History stores the inverse."

For the document, do not overthink the string edit:

const before = value.slice(0, index);
const after = value.slice(index);
value = before + inserted + after;

Delete is the same shape, except after starts at index + length.

Undo/redo

Undo/redo is not magic. Every operation gets an inverse:

insert(index, text) -> delete(index, text.length)
delete(index, length) -> insert(index, deletedText)

The only gotcha is delete: you must read deletedText before mutating the document.

The stacks

undoStack receives every applied operation plus its inverse. redoStack receives entries popped by undo(). A new apply() clears redoStack, because you branched the timeline.

When history is bounded, shift() removes the oldest undo entry. That is FIFO trimming, not LRU.