CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-codemirror--state

Editor state data structures for the CodeMirror code editor

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

transactions.mddocs/

Transaction System

Transaction-based state updates that bundle document changes, selection updates, and side effects into atomic operations.

Capabilities

Transaction Class

Represents a state transition with document changes, selection updates, and side effects.

/**
 * A transaction represents a state change. It is the result of calling EditorState.update.
 */
class Transaction {
  /** The state this transaction was created from */
  readonly startState: EditorState;
  
  /** The state produced by this transaction (lazily computed) */
  readonly state: EditorState;
  
  /** The document changes made by this transaction */
  readonly changes: ChangeSet;
  
  /** The new selection produced by this transaction */
  readonly selection: EditorSelection;
  
  /** State effects attached to this transaction */
  readonly effects: readonly StateEffect<any>[];
  
  /** Annotations attached to this transaction */
  readonly annotations: readonly Annotation<any>[];
  
  /** Whether the document changed */
  readonly docChanged: boolean;
  
  /** Whether the configuration was reconfigured */
  readonly reconfigured: boolean;
  
  /** Whether this transaction should scroll the selection into view */
  readonly scrollIntoView: boolean;
  
  /** The new document produced by the transaction (computed on demand) */
  readonly newDoc: Text;
  
  /** The new selection produced by the transaction (computed on demand) */
  readonly newSelection: EditorSelection;
  
  /** Check whether this transaction has a given annotation */
  annotation<T>(type: AnnotationType<T>): T | undefined;
  
  /** Returns true if the transaction has a user event annotation matching the given event */
  isUserEvent(event: string): boolean;
}

Usage Examples:

import { EditorState, EditorSelection } from "@codemirror/state";

const state = EditorState.create({
  doc: "Hello, world!"
});

// Create a transaction with document changes
const transaction = state.update({
  changes: { from: 7, to: 12, insert: "CodeMirror" },
  selection: EditorSelection.single(18)
});

console.log(transaction.docChanged); // true
console.log(transaction.changes.length); // 13 (original doc length)
console.log(transaction.changes.newLength); // 18 (new doc length)
console.log(transaction.startState.doc.toString()); // "Hello, world!"
console.log(transaction.state.doc.toString()); // "Hello, CodeMirror!"

TransactionSpec Interface

Specification for creating transactions.

/**
 * Describes a Transaction when calling the EditorState.update method.
 */
interface TransactionSpec {
  /** The changes to the document made by this transaction */
  changes?: ChangeSpec;
  
  /** When set, this transaction explicitly updates the selection */
  selection?: EditorSelection | {anchor: number, head?: number};
  
  /** Attach state effects to this transaction */
  effects?: StateEffect<any> | readonly StateEffect<any>[];
  
  /** Set annotations for this transaction */
  annotations?: Annotation<any> | readonly Annotation<any>[];
  
  /** Shorthand for annotations: Transaction.userEvent.of(...) */
  userEvent?: string;
  
  /** When set to true, the transaction is marked as needing to scroll the current selection into view */
  scrollIntoView?: boolean;
  
  /** By default, transactions can be modified by change filters and transaction filters */
  filter?: boolean;
  
  /** When a spec has sequential set to true, its changes are mapped through previous specs */
  sequential?: boolean;
}

Usage Examples:

// Basic change transaction
const simpleChange: TransactionSpec = {
  changes: { from: 0, to: 5, insert: "Hi" }
};

// Transaction with selection update
const changeWithSelection: TransactionSpec = {
  changes: { from: 0, to: 5, insert: "Hello" },
  selection: EditorSelection.single(5),
  scrollIntoView: true
};

// Transaction with effects and annotations
const complexTransaction: TransactionSpec = {
  changes: { from: 0, insert: "// " },
  effects: [SomeStateEffect.of(someValue)],
  annotations: [Transaction.userEvent.of("input.comment")],
  userEvent: "input.type"
};

// Apply the transaction
const newState = state.update(simpleChange).state;

Annotation System

System for attaching metadata to transactions.

/**
 * Annotations are tagged values that are used to add metadata to transactions
 */
class Annotation<T> {
  /** Define a new type of annotation */
  static define<T>(): AnnotationType<T>;
  
  /** The annotation type */
  readonly type: AnnotationType<T>;
  
  /** The value of this annotation */
  readonly value: T;
}

/**
 * Marker that identifies a type of annotation
 */
class AnnotationType<T> {
  /** Create an instance of this annotation */
  of(value: T): Annotation<T>;
}

Usage Examples:

// Define custom annotation types
const MyAnnotation = Annotation.define<string>();
const CounterAnnotation = Annotation.define<number>();

// Create annotations
const myAnnotation = MyAnnotation.of("custom data");
const counterAnnotation = CounterAnnotation.of(42);

// Use in transaction
const transaction = state.update({
  changes: { from: 0, insert: "text" },
  annotations: [myAnnotation, counterAnnotation]
});

// Read annotations from transaction
const customData = transaction.annotation(MyAnnotation); // "custom data"
const counter = transaction.annotation(CounterAnnotation); // 42

State Effects

System for representing side effects that should be applied alongside document changes.

/**
 * State effects can be used to represent additional effects associated with a transaction
 */
class StateEffect<Value> {
  /** Define a new effect type */
  static define<Value = null>(spec?: StateEffectSpec<Value>): StateEffectType<Value>;
  
  /** Map an array of effects through a change set */
  static mapEffects(effects: readonly StateEffect<any>[], mapping: ChangeDesc): StateEffect<any>[];
  
  /** This effect can be used to reconfigure the root extensions of the editor */
  static reconfigure: StateEffectType<Extension>;
  
  /** Append extensions to the top-level configuration of the editor */
  static appendConfig: StateEffectType<Extension>;
  
  /** The effect type */
  readonly type: StateEffectType<Value>;
  
  /** The value of this effect */
  readonly value: Value;
  
  /** Map this effect through a position mapping */
  map(mapping: ChangeDesc): StateEffect<Value> | undefined;
  
  /** Tells you whether this effect object is of a given type */
  is<T>(type: StateEffectType<T>): this is StateEffect<T>;
}

/**
 * Representation of a type of state effect
 */
class StateEffectType<Value> {
  /** Create a state effect instance of this type */
  of(value: Value): StateEffect<Value>;
}

interface StateEffectSpec<Value> {
  /** Provides a way to map an effect through a position mapping */
  map?: (value: Value, mapping: ChangeDesc) => Value | undefined;
}

Usage Examples:

// Define custom effect types
const HighlightEffect = StateEffect.define<{from: number, to: number}>();
const LogEffect = StateEffect.define<string>();

// Create effects
const highlight = HighlightEffect.of({from: 5, to: 10});
const log = LogEffect.of("User performed action");

// Use effects in transaction
const transaction = state.update({
  changes: { from: 0, insert: "New " },
  effects: [highlight, log]
});

// Check for specific effects
for (const effect of transaction.effects) {
  if (effect.is(HighlightEffect)) {
    console.log("Highlight:", effect.value); // {from: 5, to: 10}
  }
  if (effect.is(LogEffect)) {
    console.log("Log:", effect.value); // "User performed action"  
  }
}

// Built-in reconfiguration effect
const reconfigureEffect = StateEffect.reconfigure.of([someExtension]);
const reconfigureTransaction = state.update({
  effects: reconfigureEffect
});

Built-in Annotations

Standard annotation types provided by the system.

/**
 * Built-in annotation types available on the Transaction class
 */
class Transaction {
  /** Annotation that stores a timestamp */
  static time: AnnotationType<number>;
  
  /** Annotation that holds a user event string */
  static userEvent: AnnotationType<string>;
  
  /** Annotation that indicates whether a transaction should be added to history */
  static addToHistory: AnnotationType<boolean>;
  
  /** Annotation that indicates whether a transaction is from a remote source */
  static remote: AnnotationType<boolean>;
}

Usage Examples:

// Add timestamp to transaction
const timedTransaction = state.update({
  changes: { from: 0, insert: "text" },
  annotations: Transaction.time.of(Date.now())
});

// Mark user event
const userTransaction = state.update({
  changes: { from: 0, to: 4, insert: "" },
  annotations: Transaction.userEvent.of("delete.selection")
});

// Control history behavior
const historyTransaction = state.update({
  changes: { from: 0, insert: "auto-save: " },
  annotations: [
    Transaction.addToHistory.of(false), // Don't add to undo history
    Transaction.userEvent.of("auto-save")
  ]
});

// Mark as remote transaction
const remoteTransaction = state.update({
  changes: { from: 0, insert: "remote change" },
  annotations: Transaction.remote.of(true)
});

Transaction Filtering

System for intercepting and modifying transactions before they are applied.

/**
 * Function type for change filters
 */
type ChangeFilter = (tr: Transaction) => boolean | readonly number[];

/**
 * Function type for transaction filters  
 */
type TransactionFilter = (tr: Transaction) => TransactionSpec | readonly TransactionSpec[];

/**
 * Function type for transaction extenders
 */
type TransactionExtender = (tr: Transaction) => Pick<TransactionSpec, "effects" | "annotations"> | null;

Usage Examples:

// Define a change filter that prevents certain changes
const preventDeleteFilter: ChangeFilter = (tr) => {
  // Return false to block the entire transaction
  if (tr.annotation(Transaction.userEvent) === "delete.dangerous") {
    return false;
  }
  // Return true to allow all changes
  return true;
};

// Define a transaction filter that modifies transactions
const addTimestampFilter: TransactionFilter = (tr) => {
  // Return modified transaction spec
  return {
    ...tr,
    annotations: [
      ...tr.annotations,
      Transaction.time.of(Date.now())
    ]
  };
};

// Define a transaction extender that adds effects
const logExtender: TransactionExtender = (tr) => {
  if (tr.docChanged) {
    return {
      effects: [LogEffect.of("Document changed")]
    };
  }
  return null;
};

// Register filters via facets (typically done in extensions)
const extension = [
  EditorState.changeFilter.of(preventDeleteFilter),
  EditorState.transactionFilter.of(addTimestampFilter),
  EditorState.transactionExtender.of(logExtender)
];

Types

/**
 * Options for resolving transactions
 */
interface TransactionOptions {
  sequential?: boolean;
}

/**
 * Interface for objects that can receive transactions
 */
interface TransactionReceiver {
  dispatch(transaction: Transaction): void;
}

docs

changes.md

character-utils.md

editor-state.md

extensions.md

index.md

range-sets.md

selection.md

text.md

transactions.md

tile.json