Editor state data structures for the CodeMirror code editor
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Immutable text document data structure with efficient operations for large documents and line-based access.
The abstract Text class provides an immutable representation of document content with efficient operations for large documents.
/**
* The data structure for documents. All instances are immutable.
*/
abstract class Text {
/** Create a Text instance from an array of lines */
static of(text: string[]): Text;
/** Create an empty text document */
static empty: Text;
/** The length of the string */
readonly length: number;
/** The number of lines in the string (always >= 1) */
readonly lines: number;
/** Get the line description around the given position */
lineAt(pos: number): Line;
/** Get the description for the given (1-based) line number */
line(n: number): Line;
/** Replace a range of the text with the given content */
replace(from: number, to: number, text: Text): Text;
/** Append another document to this one */
append(other: Text): Text;
/** Retrieve the text between the given points */
slice(from: number, to?: number): Text;
/** Retrieve a part of the document as a string */
sliceString(from: number, to?: number, lineSep?: string): string;
/** Test whether this text is equal to another instance */
eq(other: Text): boolean;
/** Iterate over the document content */
[Symbol.iterator](): Iterator<string>;
}
interface Line {
/** The start position of the line */
readonly from: number;
/** The end position of the line (excluding line break) */
readonly to: number;
/** The 1-based line number */
readonly number: number;
/** The text content of the line (excluding line break) */
readonly text: string;
}Usage Examples:
import { Text } from "@codemirror/state";
// Create text from lines
const doc = Text.of([
"First line",
"Second line",
"Third line"
]);
console.log(doc.length); // Total character count
console.log(doc.lines); // 3
// Access lines
const firstLine = doc.line(1);
console.log(firstLine.text); // "First line"
console.log(firstLine.from); // 0
console.log(firstLine.to); // 10
// Get line at position
const lineAtPos = doc.lineAt(15);
console.log(lineAtPos.number); // 2
console.log(lineAtPos.text); // "Second line"
// Extract text content
const substring = doc.sliceString(0, 10);
console.log(substring); // "First line"
// Replace content
const newDoc = doc.replace(0, 5, Text.of(["Hello"]));
console.log(newDoc.sliceString(0, 20)); // "Hello line\nSecond line"Methods for manipulating and querying text content.
/**
* Replace a range of the text with the given content
* @param from Start position
* @param to End position
* @param text Replacement text
*/
replace(from: number, to: number, text: Text): Text;
/**
* Append another document to this one
* @param other Text to append
*/
append(other: Text): Text;
/**
* Retrieve the text between the given points
* @param from Start position (default: 0)
* @param to End position (default: document length)
*/
slice(from: number, to?: number): Text;
/**
* Retrieve a part of the document as a string
* @param from Start position (default: 0)
* @param to End position (default: document length)
* @param lineSep Line separator to use in output
*/
sliceString(from: number, to?: number, lineSep?: string): string;
/**
* Test whether this text is equal to another instance
* @param other Text to compare with
*/
eq(other: Text): boolean;Usage Examples:
const doc = Text.of(["Hello", "world"]);
// Replace text
const replaced = doc.replace(0, 5, Text.of(["Hi"]));
console.log(replaced.toString()); // "Hi\nworld"
// Append text
const appended = doc.append(Text.of(["!", "More text"]));
console.log(appended.toString()); // "Hello\nworld\n!\nMore text"
// Slice text
const slice = doc.slice(2, 8);
console.log(slice.toString()); // "llo\nwo"
// Get string representation
const str = doc.sliceString(0, 5, " | ");
console.log(str); // "Hello"
// Compare texts
const doc2 = Text.of(["Hello", "world"]);
console.log(doc.eq(doc2)); // trueMethods for accessing line information within the document.
/**
* Get the line description around the given position
* @param pos Character position within the document
*/
lineAt(pos: number): Line;
/**
* Get the description for the given (1-based) line number
* @param n Line number (1-based)
*/
line(n: number): Line;Usage Examples:
const doc = Text.of([
"First line",
"Second line with more content",
"Third line"
]);
// Access by line number
const line2 = doc.line(2);
console.log(line2.text); // "Second line with more content"
console.log(line2.number); // 2
console.log(line2.from); // 11 (position after "First line\n")
console.log(line2.to); // 39 (end of second line)
// Access by position
const lineAtPos = doc.lineAt(15); // Position within second line
console.log(lineAtPos.number); // 2
console.log(lineAtPos.text); // "Second line with more content"
// First line
const firstLine = doc.lineAt(0);
console.log(firstLine.number); // 1
console.log(firstLine.from); // 0
console.log(firstLine.to); // 10The Text class implements the Iterable interface for iterating over document content.
/**
* Text iterator iterates over a sequence of strings. When iterating over a Text document,
* result values will either be lines or line breaks.
*/
interface TextIterator extends Iterator<string> {
/** Retrieve the next string */
next(skip?: number): this;
/** The current string */
value: string;
/** Whether the end of the iteration has been reached */
done: boolean;
/** Whether the current string represents a line break */
lineBreak: boolean;
}Usage Examples:
const doc = Text.of(["Line 1", "Line 2", "Line 3"]);
// Iterate using for...of
for (const chunk of doc) {
console.log(chunk); // "Line 1", "\n", "Line 2", "\n", "Line 3"
}
// Manual iteration
const iter = doc[Symbol.iterator]() as TextIterator;
let result = iter.next();
while (!result.done) {
console.log(`Content: "${result.value}", LineBreak: ${result.lineBreak}`);
result = iter.next();
}/**
* Information about a line in a document
*/
interface Line {
/** The start position of the line in the document */
readonly from: number;
/** The end position of the line (not including the line break) */
readonly to: number;
/** The 1-based line number */
readonly number: number;
/** The text content of the line (not including the line break) */
readonly text: string;
}
/**
* A text iterator for iterating over document content
*/
interface TextIterator extends Iterator<string>, Iterable<string> {
next(skip?: number): this;
value: string;
done: boolean;
lineBreak: boolean;
}