/** * Operational-transformation primitives for Rustpad's wire format. * * An operation is a flat array walked over the whole document: a positive * number retains that many characters, a string inserts it, a negative number * deletes that many characters. The retained/deleted counts MUST cover the * entire base document, and every index counts Unicode code points — not * UTF-16 units. `"👍".length` is 2, but Rustpad sees one character; mixing * the two corrupts every position after the first astral character. */ export type Op = number | string; /** * Rustpad rejects any edit whose resulting document exceeds this many * characters: `apply_edit` in rustpad-server compares * `operation.target_len()` against `256 * 1024`, and `target_len` counts * Unicode scalar values — code points, not bytes and not UTF-16 units. Checked * here first so the caller gets a readable error instead of a dropped * connection. The frame that carries the edit is never the tighter bound: a * 256 KiB insertion is at most 1.5 MB as escaped JSON, and the server's * WebSocket takes messages up to tungstenite's 64 MiB default. */ export declare const MAX_DOCUMENT_CODEPOINTS: number; /** * The number of Unicode code points in a string — exactly `[...text].length`, * which is what {@link applyOperation} slices by. * * The two have to agree on malformed input as well as on good: a high * surrogate counts as a pair only when a low surrogate actually follows it. * A lone `\ud800` — legal in JSON, and so something the instance can send — * used to swallow the character after it, and every operation built from * that count was one short of the document it was applied to. */ export declare function codepointLength(text: string): number; /** * Applies one operation to a document. Used to fold the server's History * messages into the current text, so a mismatch here means the local view has * diverged — better to fail loudly than to write on top of the wrong base. */ export declare function applyOperation(text: string, ops: readonly Op[]): string; /** Replaces the whole document. Returns `undefined` for a no-op. */ export declare function replaceOps(oldLength: number, text: string): Op[] | undefined; /** Appends to the end of the document. Returns `undefined` for a no-op. */ export declare function appendOps(oldLength: number, text: string): Op[] | undefined; export interface SearchReplaceResult { ops: Op[] | undefined; count: number; } /** * Builds the operation that replaces occurrences of `search` in `text`. * * Matches are literal and non-overlapping. Only the matched ranges are * deleted and re-inserted; everything else is retained, which is what lets a * concurrent edit elsewhere in the pad survive untouched — the whole point of * going through OT instead of rewriting the document. */ export declare function searchReplaceOps(text: string, search: string, replace: string, all: boolean): SearchReplaceResult;