Merge Nodes Operation

Merge two adjacent nodes into a single node.

Overview

The merge nodes operation combines two adjacent nodes into one. Commonly used when user presses Backspace at the start of a paragraph to merge with previous paragraph.

Interface

interface MergeNodesOperation extends Operation {
  type: 'mergeNodes';
  path: Path; // Path to first node
  targetPath: Path; // Path to second node (usually next sibling)
  position?: number; // Position in first node where to merge
}

Usage

// Merge current paragraph with previous
function mergeWithPrevious(editor: Editor, currentPath: Path) {
  const previousPath = [currentPath[0] - 1];
  
  const operation: MergeNodesOperation = {
    type: 'mergeNodes',
    path: previousPath,
    targetPath: currentPath
  };
  
  editor.applyOperation(operation);
}

// Merge at specific position
function mergeAtPosition(editor: Editor, firstPath: Path, secondPath: Path, position: number) {
  const operation: MergeNodesOperation = {
    type: 'mergeNodes',
    path: firstPath,
    targetPath: secondPath,
    position: position
  };
  
  editor.applyOperation(operation);
}

// In transaction (can be decomposed into operations)
function mergeInTransaction(editor: Editor, firstPath: Path, secondPath: Path) {
  const tx = editor.beginTransaction();
  const firstNode = editor.getNodeAtPath(firstPath);
  const secondNode = editor.getNodeAtPath(secondPath);
  
  // Combine content
  const mergedText = firstNode.text + secondNode.text;
  
  // Update first node
  tx.add({
    type: 'replace',
    path: firstPath,
    length: firstNode.text.length,
    content: mergedText
  });
  
  // Delete second node
  tx.add({
    type: 'deleteNode',
    path: secondPath
  });
  
  tx.commit();
}

Inverse Operation

The inverse of merge nodes is split node:

function getInverse(operation: MergeNodesOperation): SplitNodeOperation {
  return {
    type: 'splitNode',
    path: operation.path,
    position: operation.position || editor.getNodeAtPath(operation.path).text.length
  };
}