Skip to content

Text โ€‹

Text is an explicit collaborative sequence. Its retain and delete lengths count Unicode scalar values, so Rust and JavaScript agree on positions.

Text values โ€‹

Use text(value) to distinguish collaborative text from an atomic string:

ts
import { text, ValueHandle } from 'colla-ot'

const value = ValueHandle.fromJS(text('A๐Ÿ˜€B'))

The constructor requires a string and rejects unpaired UTF-16 surrogates. The returned { type: 'text', value } record is immutable. Text is still stored as valid UTF-8; JavaScript UTF-16 is only a host representation.

Text changes โ€‹

Text changes are left-to-right streams of retain(length), insert(text), and delete(length) operations. Use Change.build for readable construction:

ts
import { Change, apply } from 'colla-ot'

const change = Change.build(change => {
  change.text(text => text.retain(1).delete(1).insert('๐Ÿ˜€'))
})
const next = apply(value, change)

For A๐Ÿ˜€B, the sequence length is 3: A, ๐Ÿ˜€, B. The emoji counts as one Unicode scalar, even though JavaScript reports two UTF-16 code units in 'A๐Ÿ˜€B'.length. A retain or delete that splits a scalar is invalid. An omitted tail is retained implicitly, and constructors merge adjacent compatible ops and remove zero-length operations.

Applying and inspecting edits โ€‹

apply() returns a new ValueHandle; it does not alter the base. To drive an editor, convertChangeToEditSteps(change, base) projects the recursive Change to path-relative text operations. inspectChange(change, base) returns a human-readable ChangeView, including text insertion positions and deletion ranges.

ts
import {
  Change, ValueHandle, apply, convertChangeToEditSteps, text,
} from 'colla-ot'

const base = ValueHandle.fromJS(text('Draft'))
const edit = Change.build(change => change.text(text => text.retain(5).insert(' v2')))
const steps = convertChangeToEditSteps(edit, base)
// [{ type: 'text', path: [], ops: [...]}]
const result = apply(base, edit)

The base is required for projection because a Change stores an operation, not the original content. Paths and editor offsets are views of that snapshot and are not part of the Change wire format. See Coordinates for conversion to and from UTF-16 offsets.

Limits and errors โ€‹

Change.fromJS and Change.build accept InputOptions to cap sequence length, operation count, string bytes, and recursive depth. Invalid types, out-of-range lengths, malformed strings, and oversized input raise CollaError with a stable error code. Use the JavaScript API reference for the complete builder and error surface.

Next: RichText.

Colla v0.3.0 ยท Released under the MIT License.