Class LoroText

The handler of a text container. It supports rich text CRDT.

Learn more at https://loro.dev/docs/tutorial/text

Constructors

  • Create a new detached LoroText (not attached to any LoroDoc).

    The edits on a detached container will not be persisted. To attach the container to the document, please insert it into an attached container.

    Returns LoroText

  • Returns LoroText

Properties

Get the container id of the text.

length: number

Get the length of text (utf-16 length).

Methods

  • Change the state of this text by delta.

    If a delta item is insert, it should include all the attributes of the inserted text. Loro's rich text CRDT may make the inserted text inherit some styles when you use insert method directly. However, when you use applyDelta if some attributes are inherited from CRDT but not included in the delta, they will be removed.

    Another special property of applyDelta is if you format an attribute for ranges out of the text length, Loro will insert new lines to fill the gap first. It's useful when you build the binding between Loro and rich text editors like Quill, which might assume there is always a newline at the end of the text implicitly.

    Parameters

    Returns void

    const doc = new LoroDoc();
    const text = doc.getText("text");
    doc.configTextStyle({bold: {expand: "after"}});
    text.insert(0, "Hello World!");
    text.mark({ start: 0, end: 5 }, "bold", true);
    const delta = text.toDelta();
    const text2 = doc.getText("text2");
    text2.applyDelta(delta);
    expect(text2.toDelta()).toStrictEqual(delta);
  • Get the character at the given position (utf-16 index).

    Parameters

    • pos: number

    Returns string

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insert(0, "Hello");
    text.charAt(0); // "H"
  • Parameters

    • pos: number
    • len: number

    Returns void

  • Delete elements from index to index + len (utf-16 index).

    Parameters

    • index: number
    • len: number

    Returns void

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insert(0, "Hello");
    text.delete(1, 3);
    const s = text.toString();
    console.log(s); // "Ho"
  • Delete elements from index to utf-8 index + len

    Parameters

    • index: number
    • len: number

    Returns void

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insertUtf8(0, "Hello");
    text.deleteUtf8(1, 3);
    const s = text.toString();
    console.log(s); // "Ho"
  • Returns void

  • Get the attached container associated with this.

    Returns an attached Container that is equal to this or created by this; otherwise, it returns undefined.

    Returns LoroText

  • Get the cursor position at the given pos.

    When expressing the position of a cursor, using "index" can be unstable because the cursor's position may change due to other deletions and insertions, requiring updates with each edit. To stably represent a position or range within a list structure, we can utilize the ID of each item/character on List CRDT or Text CRDT for expression.

    Loro optimizes State metadata by not storing the IDs of deleted elements. This approach complicates tracking cursors since they rely on these IDs. The solution recalculates position by replaying relevant history to update cursors accurately. To minimize the performance impact of history replay, the system updates cursor info to reference only the IDs of currently present elements, thereby reducing the need for replay.

    Parameters

    • pos: number
    • Optionalside: Side

    Returns Cursor


    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insert(0, "123");
    const pos0 = text.getCursor(0, 0);
    {
    const ans = doc.getCursorPos(pos0!);
    expect(ans.offset).toBe(0);
    }
    text.insert(0, "1");
    {
    const ans = doc.getCursorPos(pos0!);
    expect(ans.offset).toBe(1);
    }
  • Get the editor of the text at the given position.

    Parameters

    • pos: number

    Returns `${number}`

  • Get the shallow value of the text. This equals to text.toString().

    Returns string

  • Parameters

    • pos: number
    • text: string

    Returns void

  • Insert the string at the given index (utf-16 index).

    Parameters

    • index: number
    • content: string

    Returns void

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insert(0, "Hello");
  • Insert some string at utf-8 index.

    Parameters

    • index: number
    • content: string

    Returns void

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insertUtf8(0, "Hello");
  • Whether the container is attached to a LoroDoc.

    If it's detached, the operations on the container will not be persisted.

    Returns boolean

  • Check if the container is deleted

    Returns boolean

  • Iterate each text span(internal storage unit)

    The callback function will be called for each span in the text. If the callback returns false, the iteration will stop.

    Limitation: you cannot access or alter the doc state when iterating (this is for performance consideration). If you need to access or alter the doc state, please use toString instead.

    Parameters

    • callback: (string: any) => boolean

    Returns void

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insert(0, "Hello");
    text.iter((str) => (console.log(str), true));
  • "Text"

    Returns "Text"

  • Mark a range of text with a key and a value (utf-16 index).

    You should call configTextStyle before using mark and unmark.

    You can use it to create a highlight, make a range of text bold, or add a link to a range of text.

    Note: this is not suitable for unmergeable annotations like comments.

    Parameters

    • range: { end: number; start: number }
    • key: string
    • value: any

    Returns void

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    doc.configTextStyle({bold: {expand: "after"}});
    const text = doc.getText("text");
    text.insert(0, "Hello World!");
    text.mark({ start: 0, end: 5 }, "bold", true);
  • Get the parent container.

    • The parent of the root is undefined.
    • The object returned is a new js object each time because it need to cross the WASM boundary.

    Returns Container

  • Push a string to the end of the text.

    Parameters

    • s: string

    Returns void

  • Get a string slice (utf-16 index).

    Parameters

    • start_index: number
    • end_index: number

    Returns string

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insert(0, "Hello");
    text.slice(0, 2); // "He"
  • Delete and return the string at the given range and insert a string at the same position (utf-16 index).

    Parameters

    • pos: number
    • len: number
    • s: string

    Returns string

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insert(0, "Hello");
    text.splice(2, 3, "llo"); // "llo"
  • Get the text in Delta format.

    The returned value will include the rich text information.

    Returns Delta<string>[]

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    doc.configTextStyle({bold: {expand: "after"}});
    text.insert(0, "Hello World!");
    text.mark({ start: 0, end: 5 }, "bold", true);
    console.log(text.toDelta()); // [ { insert: 'Hello', attributes: { bold: true } } ]
  • Get the JSON representation of the text.

    Returns any

  • Convert the text to a string

    Returns string

  • Unmark a range of text with a key and a value (utf-16 index).

    You should call configTextStyle before using mark and unmark.

    You can use it to remove highlights, bolds or links

    Parameters

    • range: { end: number; start: number }
    • key: string

    Returns void

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    doc.configTextStyle({bold: {expand: "after"}});
    const text = doc.getText("text");
    text.insert(0, "Hello World!");
    text.mark({ start: 0, end: 5 }, "bold", true);
    text.unmark({ start: 0, end: 5 }, "bold");
  • Update the current text to the target text.

    It will calculate the minimal difference and apply it to the current text. It uses Myers' diff algorithm to compute the optimal difference.

    This could take a long time for large texts (e.g. > 50_000 characters). In that case, you should use updateByLine instead.

    Parameters

    Returns void

    import { LoroDoc } from "loro-crdt";

    const doc = new LoroDoc();
    const text = doc.getText("text");
    text.insert(0, "Hello");
    text.update("Hello World");
    console.log(text.toString()); // "Hello World"
  • Update the current text based on the provided text. This update calculation is line-based, which will be more efficient but less precise.

    Parameters

    Returns void