### Initialize Loro Document and Basic Text Operations Source: https://context7_llms Demonstrates how to initialize a new Loro document, create a collaborative text container, insert text, subscribe to changes, and export updates for synchronization. This is a fundamental example for getting started with Loro. ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const text = doc.getText("text"); text.insert(0, "Hello World"); // Subscribe to changes const unsubscribe = doc.subscribe((event) => { console.log("Document changed:", event); }); // Export updates for synchronization const updates = doc.export({ mode: "update" }); ``` -------------------------------- ### Basic Loro Mirror Setup and Usage in TypeScript Source: https://loro.dev/llms-full.txt Demonstrates the core setup and usage of Loro Mirror. It includes defining a schema for a movable list of todos, creating a Loro document and Mirror store, subscribing to state changes, and updating the state using both draft-mutation and immutable return styles. It also shows a basic example of syncing updates between two Loro documents. ```typescript /** * As an example, you can use `useState` from React to manage the state * * `const [appState, setAppState] = useState({});` */ function setAppState(state: any) {} // ---cut--- import { LoroDoc } from "loro-crdt"; import { schema, SyncDirection, Mirror } from "loro-mirror"; // 1) Declare state shape – a MovableList of todos with stable Container ID `$cid` type TodoStatus = "todo" | "inProgress" | "done"; const appSchema = schema({ todos: schema.LoroMovableList( schema.LoroMap({ text: schema.String(), status: schema.String(), }), // $cid is the container ID of LoroMap assigned by Loro (t) => t.$cid, ), }); // 2) Create a Loro document and a Mirror store const doc = new LoroDoc(); const store = new Mirror({ doc, schema: appSchema, // InitialState will not be written into LoroDoc initialState: { todos: [] }, }); // 3) Subscribe (optional) – know whether updates came from local or remote const unsubscribe = store.subscribe((state, { direction, tags }) => { if (direction === SyncDirection.FROM_LORO) { console.log("Remote update", { state, tags }); } else { console.log("Local update", { state, tags }); } // You can use `state` to render directly, it's a new immutable object that shares // the unchanged fields with the old state setAppState(state); }); // 4) Either draft‑mutate or return a new state // Draft‑style (mutate a draft) store.setState((s) => { s.todos.push({ text: "Draft add", status: "todo" }); }); // Immutable return (construct a new object) store.setState((s) => ({ ...s, todos: [...s.todos, { text: "Immutable add", status: "todo" }], })); // 5) Sync across peers with Loro updates (transport‑agnostic) // Example: two docs in memory – in real apps, send `bytes` over WS/HTTP/WebRTC const other = new LoroDoc(); other.import(doc.export({ mode: "snapshot" })); // Wire realtime sync (local updates → remote import) const stop = doc.subscribeLocalUpdates((bytes) => { other.import(bytes); }); // Any `store.setState(...)` on `doc` now appears in `other` as well ``` -------------------------------- ### Configure and Use Loro Rich Text Module in JavaScript Source: https://www.loro.dev/blog/loro-richtext Demonstrates how to initialize Loro, configure rich text styles with expand and overlap behaviors, insert text, and apply styles. It also shows how to convert the rich text state to a Delta format for verification. This example requires the Loro library to be installed. ```javascript const doc = new Loro(); doc.configTextStyle({ bold: { expand: "after" }, comment: { expand: "none", overlap: true }, link: { expand: "none" }, }); const text = doc.getText("text"); text.insert(0, "Hello world!"); text.mark({ start: 0, end: 5 }, "bold", true); // Expected output: [ // { insert: "Hello", attributes: { bold: true } }, // { insert: " world!" }, // ] as Delta[]; text.insert(5, "!"); // Expected output: [ // { insert: "Hello!", attributes: { bold: true } }, // { insert: " world!" }, // ] as Delta[]; ``` -------------------------------- ### Ephemeral Store Usage Example - JavaScript Source: https://loro.dev/docs/tutorial/ephemeral Demonstrates basic usage of the EphemeralStore, including setting and getting data, subscribing to changes, and encoding data for transmission. This example shows how to manage user presence and online status in a collaborative environment. ```javascript import { EphemeralStore, EphemeralStoreEvent } from "loro-crdt"; import { expect } from "expect"; const store = new EphemeralStore(); // Set ephemeral data store.set("loro-prosemirror", { anchor: { pos: 0 }, focus: { pos: 5 }, user: "Alice", }); store.set("online-users", ["Alice", "Bob"]); expect(store.get("online-users")).toEqual(["Alice", "Bob"]); // Encode only the data for `loro-prosemirror` const encoded = store.encode("loro-prosemirror"); store.subscribe((e: EphemeralStoreEvent) => { // Listen to changes from `local`, `remote`, or `timeout` events }); ``` -------------------------------- ### Install Loro CRDT Package Source: https://context7_llms Demonstrates how to install the loro-crdt NPM package using common package managers like npm, pnpm, and yarn. ```bash npm install loro-crdt # Or pnpm install loro-crdt # Or yarn add loro-crdt ``` -------------------------------- ### Complete Example of EphemeralStore Synchronization Source: https://context7_llms Demonstrates a complete example of synchronizing two EphemeralStore instances. It shows subscribing to local updates from one store and applying them to another, subscribing to all events, setting a value, encoding it, and applying the encoded value to the second store. ```typescript import { EphemeralStore } from "loro-crdt"; // Assume we have: declare const websocket: { send: (data: Uint8Array) => void; on: (event: string, handler: (data: any) => void) => void; }; const store = new EphemeralStore(30000); const store2 = new EphemeralStore(30000); // Subscribe to local updates store.subscribeLocalUpdates((data) => { store2.apply(data); }); // Subscribe to all updates store2.subscribe((event) => { console.log("event:", event); }); // Set a value store.set("key", "value"); // Encode the value const encoded = store.encode("key"); // Apply the encoded value store2.apply(encoded); ``` -------------------------------- ### Practical Example: Saving and Restoring Checkpoints with Frontiers Source: https://context7_llms Illustrates a practical application of frontiers for saving and restoring document states using a Map to store checkpoints. This example shows inserting text, saving a frontier as a checkpoint, making modifications, saving another checkpoint, and then restoring to an earlier state. ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const text = doc.getText("content"); const checkpoints = new Map(); // Save checkpoint with frontiers text.insert(0, "Draft version"); checkpoints.set("draft", doc.frontiers()); // Make changes text.delete(0, 5); text.insert(0, "Final"); checkpoints.set("final", doc.frontiers()); // Restore to any checkpoint doc.checkout(checkpoints.get("draft")); console.log(text.toString()); // "Draft version" ``` -------------------------------- ### Loro Text Insertion and Style Configuration Example Source: https://loro.dev/blog/loro-richtext Provides an example of configuring text styles in Loro and inserting text with overlapping comments. It showcases how Loro handles distinct comment styles for different users on the same text segment. ```javascript const doc = new Loro(); doc.configTextStyle({ comment: { expand: "none" } }); const text = doc.getText("text"); text.insert(0, "The fox jumped."); text.mark({ start: 0, end: 7 }, "comment:alice", "Hi"); text.mark({ start: 4, end: 14 }, "comment:bob", "Jump"); expect(text.toDelta()).toStrictEqual([ { insert: "The ", attributes: { "comment:alice": "Hi" } }, { insert: "fox", attributes: { "comment:alice": "Hi", "comment:bob": "Jump", }, }, { insert: " j ``` -------------------------------- ### Loro CRDT Browser Example with ESM Source: https://context7_llms Provides a minimal HTML example demonstrating how to use Loro CRDT directly in the browser using ECMAScript Modules (ESM) and CDN imports. It shows the basic initialization of a LoroDoc. ```html ESM Module Example
``` -------------------------------- ### Example of Inserting into a List and Creating a Text Container (TypeScript) Source: https://context7_llms Demonstrates how to use Loro's List and Text container types. It shows inserting an element into a list and then inserting a new Text container at a specific position within that list. This example highlights the creation and manipulation of different container types within a Loro document. ```typescript /** * Container types supported by loro. * * It is most commonly used to specify the type of sub-container to be created. * @example * ```ts * import { LoroDoc, LoroText } from "loro-crdt"; * * const doc = new LoroDoc(); * const list = doc.getList("list"); * list.insert(0, 100); * const text = list.insertContainer(1, new LoroText()); * ``` */ export type ContainerType = "Text" | "Map" | "List"| "Tree" | "MovableList" | "Counter"; export type PeerID = `${number}`; /** * The unique id of each container. * * @example * ```ts * import { LoroDoc } from "loro-crdt"; * * const doc = new LoroDoc(); * const list = doc.getList("list"); * const containerId = list.id; * ``` */ export type ContainerID = | `cid:root-${string}:${ContainerType}` | `cid:${number}@${PeerID}:${ContainerType}`; /** * The unique id of each tree node. */ export type TreeID = `${number}@${PeerID}`; interface LoroDoc { /** * Export updates from the specific version to the current version * * @deprecated Use `export({mode: "update", from: version})` instead * * @example * ```ts * import { LoroDoc } from "loro-crdt"; * * const doc = new LoroDoc(); * const text = doc.getText("text"); * text.insert(0, "Hello"); * // get all updates of the doc * const updates = doc.exportFrom(); * const version = doc.oplogVersion(); * text.insert(5, " World"); * // get updates from specific version to the latest version * const updates2 = doc.exportFrom(version); * ``` */ exportFrom(version?: VersionVector): Uint8Array; /** * * Get the container corresponding to the container id * * * @example * ```ts * import { LoroDoc } from "loro-crdt"; * * const doc = new LoroDoc(); * let text = doc.getText("text"); * const textId = text.id; * text = doc.getContainerById(textId); * ``` */ getContainerById(id: ContainerID): Container | undefined; /** * Subscribe to updates from local edits. * * This method allows you to listen for local changes made to the document. * It's useful for syncing changes with other instances or saving updates. * * @param f - A callback function that receives a Uint8Array containing the update data. * @returns A function to unsubscribe from the updates. * * @example * ```ts * const loro = new Loro(); * const text = loro.getText("text"); * * const unsubscribe = loro.subscribeLocalUpdates((update) => { * console.log("Local update received:", update); * // You can send this update to other Loro instances * }); * * text.insert(0, "Hello"); * loro.commit(); * * // Later, when you want to stop listening: * unsubscribe(); * ``` * * @example * ```ts * const loro1 = new Loro(); * const loro2 = new Loro(); * * // Set up two-way sync * loro1.subscribeLocalUpdates((updates) => { * loro2.import(updates); * }); * * loro2.subscribeLocalUpdates((updates) => { ``` -------------------------------- ### Vue State Management Example with Pinia Source: https://context7_llms This TypeScript example demonstrates how to define a state store using Pinia, a state management library for Vue.js. It includes state properties, getters for computed state, and actions for modifying the state, illustrating a typical pattern for managing application state. ```typescript export const useCartStore = defineStore({ id: "cart", state: () => ({ rawItems: [] as string[], }), getters: { items: (state): Array<{ name: string; amount: number }> => state.rawItems.reduce( (items, item) => { const existingItem = items.find((it) => it.name === item); if (!existingItem) { items.push({ name: item, amount: 1 }); } else { existingItem.amount++; } return items; }, [] as Array<{ name: string; amount: number }> ), }, actions: { addItem(name: string) { this.rawItems.push(name); }, removeItem(name: string) { const i = this.rawItems.lastIndexOf(name); if (i > -1) this.rawItems.splice(i, 1); }, async purchaseItems() { const user = useUserStore(); if (!user.name) return; console.log("Purchasing", this.items); const n = this.items.length; this.rawItems = []; return n; }, }, }); ``` -------------------------------- ### Loro Rich Text Implementation Example Source: https://context7_llms A TypeScript example demonstrating how to configure and use Loro's rich text features, specifically for handling overlapping comment styles. It shows inserting text, marking spans with styles, and verifying the resulting Delta format. ```typescript const doc = new Loro(); doc.configTextStyle({ comment: { expand: "none" }, }); const text = doc.getText("text"); text.insert(0, "The fox jumped."); text.mark({ start: 0, end: 7 }, "comment:alice", "Hi"); text.mark({ start: 4, end: 14 }, "comment:bob", "Jump"); expect(text.toDelta()).toStrictEqual([ { insert: "The ", attributes: { "comment:alice": "Hi" }, }, { insert: "fox", attributes: { "comment:alice": "Hi", "comment:bob": "Jump", }, }, { insert: " jumped", attributes: { "comment:bob": "Jump" }, }, { insert: ".", }, ]); ``` -------------------------------- ### Rich Text Expansion Configuration Example Source: https://loro.dev/docs/tutorial/text Shows how to configure rich text expansion behaviors ('after', 'before', 'none', 'both') for text formatting. This example demonstrates 'after' for bold and 'before' for links. ```typescript const doc = new LoroDoc(); doc.configTextStyle({ bold: { expand: "after" }, link: { expand: "before" }, }); const text = doc.getText("text"); text.insert(0, "Hello World!"); text.mark({ start: 0, end: 5 }, "bold", true); console.log(text.toDelta()); // " Test" will inherit the bold style because `bold` is configured to expand forward text.insert(5, " Test"); console.log(text.toDelta()); ``` -------------------------------- ### Text Editing with Undo/Redo Example in JavaScript Source: https://loro.dev/docs/advanced/undo Illustrates a practical example of using Loro's UndoManager for text editing, demonstrating how to group operations using `groupStart` and `groupEnd` to manage undo/redo actions effectively, including cursor restoration. ```javascript // Example: Text Editing with Undo/Redo // Assume 'doc' is an initialized Loro document and 'undoManager' is an instance of UndoManager. doc.groupStart(); // Start a group for undo/redo try { // Perform text editing operations, e.g., inserting or deleting text. // For example: // text.insert(0, "Hello"); // text.delete(0, 5); // Restore cursor or selection if needed. This would typically involve // interacting with the onPush/onPop callbacks of the UndoManager // to store and retrieve cursor positions. } finally { doc.groupEnd(); // End the group, making the operations a single undo/redo step } ``` -------------------------------- ### Initialize and Use LoroDoc Source: https://context7_llms Demonstrates the basic initialization of a LoroDoc, which is the entry point for using Loro. It shows how to create a document and interact with a LoroText container to insert text and view the document's JSON representation. ```typescript import { LoroDoc, LoroText } from "loro-crdt"; // ---cut--- const doc = new LoroDoc(); const text: LoroText = doc.getText("text"); text.insert(0, "Hello world!"); console.log(doc.toJSON()); // { "text": "Hello world!" } ``` -------------------------------- ### LoroText: Get String Slice (UTF-16 Index) (TypeScript) Source: https://context7_llms Retrieves a substring from the LoroText based on UTF-16 start and end indices. The end index is exclusive. ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const text = doc.getText("text"); text.insert(0, "Hello"); const slice = text.slice(0, 2); // slice will be "He" ``` -------------------------------- ### Counter System Example (JavaScript) Source: https://loro.dev/docs/concepts/peerid_management Shows the Loro counter system in action, where each peer maintains a monotonic counter starting at 0. Operations are identified by a combination of `(peerId, counter)`, ensuring uniqueness. ```javascript const doc = new LoroDoc(); doc.setPeerId("1"); const text = doc.getText("text"); text.insert(0, "H"); // Operation ("1", 0) text.insert(1, "i!"); // Operation ("1", 1) and Operation ("1", 2) are created console.log(doc.version()); // { "1": 2 } ``` -------------------------------- ### Get LoroDoc Version Vector (TypeScript) Source: https://context7_llms Provides code examples for retrieving the current version vector (`version()`) and the latest known version vector from the oplog (`oplogVersion()`) in LoroDoc. Version vectors are crucial for understanding the state of distributed data and detecting conflicts. ```typescript import { LoroDoc } from "loro-crdt"; // ---cut--- const doc = new LoroDoc(); // Get current version vector const vv = doc.version(); // Get oplog version vector (latest known version) const oplogVv = doc.oplogVersion(); ``` -------------------------------- ### Basic Snapshotting with LoroDoc Source: https://context7_llms Demonstrates how to create full and shallow snapshots of a Loro document. Full snapshots capture the entire history, while shallow snapshots trim history for efficiency. Useful for periodic backups or efficient client-side storage. ```ts import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); // ... extensive editing history ... // Regular snapshot - full history const full = doc.export({ mode: "snapshot" }); // Shallow snapshot - trimmed history const shallow = doc.export({ mode: "shallow-snapshot", frontiers: doc.frontiers(), }); // Typically 70-90% smaller console.log(`Size reduction: ${100 - (shallow.length / full.length * 100)}%`); ``` -------------------------------- ### Loro CRDT UndoManager Cursor Handling Example (TypeScript) Source: https://context7_llms Demonstrates how to use the Loro CRDT UndoManager to store and restore cursor positions during undo/redo operations. It shows the setup of the UndoManager with `onPush` and `onPop` callbacks, document modifications, and assertions to verify cursor restoration after undo. ```typescript import { LoroDoc, UndoManager, Cursor } from "loro-crdt"; import { expect } from "expect"; // ---cut--- const doc = new LoroDoc(); let cursors: Cursor[] = []; let poppedCursors: Cursor[] = []; const undo = new UndoManager(doc, { mergeInterval: 0, onPop: (isUndo, value, counterRange) => { poppedCursors = value.cursors; }, onPush: () => { return { value: null, cursors: cursors }; }, }); doc.getText("text").insert(0, "hello world"); doc.commit(); cursors = [ doc.getText("text").getCursor(0)!, doc.getText("text").getCursor(5)!, ]; // delete "hello ", the cursors should be transformed doc.getText("text").delete(0, 6); doc.commit(); expect(poppedCursors.length).toBe(0); undo.undo(); expect(poppedCursors.length).toBe(2); expect(doc.toJSON()).toStrictEqual({ text: "hello world", }); // expect the cursors to be transformed back expect(doc.getCursorPos(poppedCursors[0]).offset).toBe(0); expect(doc.getCursorPos(poppedCursors[1]).offset).toBe(5); ``` -------------------------------- ### Initialize and Populate LoroList Source: https://context7_llms Demonstrates the initialization of a LoroDoc and a LoroList, followed by pushing elements into the list and retrieving them as an array. ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const list = doc.getList("list"); list.push("a", "b", "c"); const array = list.toArray(); ``` -------------------------------- ### Example: LoroDoc Version Checkout Source: https://www.loro.dev/docs/advanced/version_deep_dive Demonstrates how to use Loro's time-travel capability by checking out a specific document version using Frontiers. It shows inserting text, committing, getting frontiers, and then checking out a previous version. ```typescript const doc = new LoroDoc(); doc.setPeerId(0n); const text = doc.getText("text"); text.insert(0, "H"); doc.commit(); const v = doc.frontiers(); text.insert(1, "i"); expect(doc.toJSON()).toStrictEqual({ text: "Hi", }); doc.checkout([{ peer: "0", counter: 0 }]); expect(doc.toJSON()).toStrictEqual({ text: "H", }); ``` -------------------------------- ### Fractional Index Encoding Example (JavaScript) Source: https://context7_llms Illustrates the growth of encoding size for Fractional Indexes as elements are inserted. Each insertion can potentially increase the byte size, demonstrating the base-256 nature of the implementation. ```javascript ab // [128] [129, 128] acb // [128] [129, 127, 128] [129, 128] acdb // [128] [129, 127, 128] [129, 127, 129, 128] [129, 128] acedb // [128] [129, 127, 128] [129, 127, 129, 127, 128] [129, 127, 129, 128] [129, 128] ``` -------------------------------- ### Debug and Metadata Access - TypeScript Source: https://context7_llms This example shows how to enable debug information globally in Loro and extract metadata from import blobs. It covers setting the debug mode and then exporting a document update blob. The `decodeImportBlobMeta` function is used to parse this blob and retrieve metadata such as start and end timestamps, the export mode, and the number of changes contained within the blob. ```typescript import { setDebug, LoroDoc, decodeImportBlobMeta } from "loro-crdt"; // ---cut--- const doc = new LoroDoc(); // Enable debug info setDebug(); const blob = doc.export({ mode: "update" }); // Get import blob metadata const metadata = decodeImportBlobMeta(blob, true); console.log({ startTimestamp: metadata.startTimestamp, endTimestamp: metadata.endTimestamp, mode: metadata.mode, changeNum: metadata.changeNum, }); ``` -------------------------------- ### Initialize LoroDoc and Create Containers Source: https://context7_llms Shows the basic setup for using LoroDoc, the main entry point for Loro CRDT functionality. It demonstrates creating a new document instance, setting a peer ID, and initializing various CRDT containers like Text, List, Map, Tree, and MovableList. ```typescript import { LoroDoc, LoroText, LoroList, LoroMap, LoroTree, LoroMovableList, } from "loro-crdt"; // ---cut--- // Create a new document with a random peer ID const doc = new LoroDoc(); // Or set a specific peer ID doc.setPeerId("1"); // Create containers const text = doc.getText("text"); const list = doc.getList("list"); const map = doc.getMap("map"); const tree = doc.getTree("tree"); const movableList = doc.getMovableList("tasks"); ``` -------------------------------- ### Get Size of LoroMap Source: https://context7_llms Gets the number of key-value pairs currently stored in the LoroMap. This provides a quick way to determine the map's current extent. ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const map = doc.getMap("map"); map.set("foo", "bar"); console.log(map.size); // 1 ``` -------------------------------- ### Synchronize Loro Documents with Initial Sync Source: https://context7_llms Demonstrates the initial synchronization between two Loro documents. It shows how one document can export its state and the other can import it, ensuring consistency. It also covers how to handle missing updates after an initial sync using version vectors. ```typescript import { LoroDoc, LoroList } from "loro-crdt"; import { expect } from "expect"; // ---cut--- const docA = new LoroDoc(); const docB = new LoroDoc(); const listA: LoroList = docA.getList("list"); listA.insert(0, "A"); listA.insert(1, "B"); listA.insert(2, "C"); // B import the ops from A const data: Uint8Array = docA.export({ mode: "update" }); // The data can be sent to B through the network docB.import(data); expect(docB.toJSON()).toStrictEqual({ list: ["A", "B", "C"], }); const listB: LoroList = docB.getList("list"); listB.delete(1, 1); // `doc.export({mode: "update", from: version})` can encode all the ops from the version to the latest version // `version` is the version vector of another document const missingOps = docB.export({ mode: "update", from: docA.oplogVersion(), }); docA.import(missingOps); expect(docA.toJSON()).toStrictEqual({ list: ["A", "C"], }); expect(docA.toJSON()).toStrictEqual(docB.toJSON()); ``` -------------------------------- ### Get LoroList Container ID Source: https://context7_llms Demonstrates how to access the `id` property to get the unique identifier for a LoroList container. This ID is immutable and assigned upon creation. ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const list = doc.getList("list"); const containerId = list.id; ``` -------------------------------- ### Get LoroMovableListItem Last Editor Source: https://loro.dev/llms-full.txt Get the peer ID of the last editor who modified the list item at a given position in a LoroMovableList. This helps identify the most recent changes to an item. ```typescript getLastEditorAt(pos: number): PeerID ``` -------------------------------- ### Establish Realtime Sync Between Loro Peers Source: https://context7_llms Demonstrates how two Loro peers can achieve realtime synchronization, even when one peer comes online with unapplied local changes. It covers exchanging version information, importing missing updates, and setting up real-time subscriptions. ```typescript import { LoroDoc } from "loro-crdt"; // ---cut--- const doc1 = new LoroDoc(); doc1.getText("text").insert(0, "Hello"); // Peer2 joins the network const doc2 = new LoroDoc(); // ... doc2 may import its local snapshot // 1. Exchange version information const peer2Version = doc2.oplogVersion(); const peer1Version = doc1.oplogVersion(); // 2. Request missing updates from existing peers const missingOps = doc1.export({ mode: "update", from: peer2Version, }); doc2.import(missingOps); const missingOps2 = doc2.export({ mode: "update", from: peer1Version, }); doc1.import(missingOps2); // 3. Establish realtime sync doc2.subscribeLocalUpdates((update) => { // websocket.send(update); }); doc1.subscribeLocalUpdates((update) => { // websocket.send(update); }); // Now both peers are in sync and can collaborate ``` -------------------------------- ### Use Loro Tree Container (TypeScript) Source: https://context7_llms Demonstrates the creation and basic usage of a LoroTree container for hierarchical data structures. It shows how to create a root node and child nodes, and how to set data on nodes. ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const tree = doc.getTree("tree"); const root = tree.createNode(); root.data.set("name", "Root"); const child1 = root.createNode(); child1.data.set("name", "Child 1"); const child2 = root.createNode(); child2.data.set("name", "Child 2"); ``` -------------------------------- ### ListDiff Type Definition and Example in TypeScript Source: https://context7_llms Defines the ListDiff type for tracking changes in list content using Delta operations. Includes an example of how to subscribe to list changes and process insert operations. ```typescript type ListDiff = { type: "list" diff: Delta<(Value | Container)[]>[] } // Example Usage: import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const list = doc.getList("list"); list.subscribe((e) => { for (const event of e.events) { if (event.diff.type === "list") { event.diff.diff.forEach(delta => { if (delta.insert) { console.log(`Inserted items:`, delta.insert); } }); } } }); ``` -------------------------------- ### MapDiff Type Definition and Example in TypeScript Source: https://context7_llms Defines the MapDiff type for tracking changes in map content, including updates and deletions. Provides an example of subscribing to map changes and logging key-value updates or deletions. ```typescript type MapDiff = { type: "map" updated: Record } // Example Usage: import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const map = doc.getMap("map"); map.subscribe((e) => { for (const event of e.events) { if (event.diff.type === "map") { Object.entries(event.diff.updated).forEach(([key, value]) => { if (value === undefined) { console.log(`Deleted key: ${key}`); } else { console.log(`Updated key: ${key} = ${value}`); } }); } } }); ``` -------------------------------- ### Basic Synchronization with Loro Source: https://context7_llms Demonstrates how to synchronize Loro documents between two peers by exporting updates from one document and importing them into another. This is useful for initial synchronization or periodic state sharing. ```typescript import { LoroDoc } from "loro-crdt"; // Peer A: Export updates const doc1 = new LoroDoc(); doc1.getText("text").insert(0, "Hello"); const updates = doc1.export({ mode: "update" }); // Peer B: Import updates const doc2 = new LoroDoc(); doc2.import(updates); // now doc2.getText("text").toString() === "Hello" ``` -------------------------------- ### TreeDiff Type Definition and Example in TypeScript Source: https://context7_llms Defines the TreeDiff type for tracking structural changes in a tree, including node creation, deletion, and movement. Includes an example of subscribing to tree changes and handling different action types. ```typescript type TreeDiff = { type: "tree" diff: TreeDiffItem[] } type TreeDiffItem = | { target: TreeID action: "create" parent: TreeID | undefined index: number fractionalIndex: string } | { target: TreeID action: "delete" oldParent: TreeID | undefined oldIndex: number } | { target: TreeID action: "move" parent: TreeID | undefined index: number fractionalIndex: string oldParent: TreeID | undefined oldIndex: number } // Example Usage: import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const tree = doc.getTree("tree"); tree.subscribe((e) => { for (const event of e.events) { if (event.diff.type === "tree") { event.diff.diff.forEach(item => { switch (item.action) { case "create": console.log(`Created node ${item.target}`); break; case "move": console.log(`Moved node ${item.target}`); break; case "delete": console.log(`Deleted node ${item.target}`); break; } }); } } }); ``` -------------------------------- ### Basic LoroDoc Initialization and Versioning (JavaScript) Source: https://loro.dev/docs/advanced/doc_state_and_oplog Demonstrates how to initialize a LoroDoc, perform edits, and query the OpLog version versus the current document state version. This is useful for understanding the immediate effects of operations on the document's state and history. ```javascript const doc = new LoroDoc(); // Edit updates both doc.getText("text").insert(0, "Hello"); console.log(doc.oplogVersion()); // Latest known version console.log(doc.version()); // The version of the current state of the document // If the document is attached, they are the same. ``` -------------------------------- ### Configure and Use Loro Rich Text Module in JavaScript Source: https://loro.dev/blog/loro-richtext Demonstrates how to configure text styles and use Loro's rich text module to insert text and apply styles. It shows the expected output after inserting text and applying a 'bold' attribute. ```javascript const doc = new Loro(); doc.configTextStyle({ bold: { expand: "after" }, comment: { expand: "none", overlap: true }, link: { expand: "none" }, }); const text = doc.getText("text"); text.insert(0, "Hello world!"); text.mark({ start: 0, end: 5 }, "bold", true); // Assertion for initial state // expect(text.toDelta()).toStrictEqual([ // { insert: "Hello", attributes: { bold: true } }, // { insert: " world!" }, // ] as Delta[]); text.insert(5, "!"); // Assertion for state after insertion // expect(text.toDelta()).toStrictEqual([ // { insert: "Hello!", attributes: { bold: true } }, // { insert: " world!" }, // ] as Delta[]); ``` -------------------------------- ### LoroTree.id Source: https://context7_llms Gets the unique identifier for the LoroTree container. ```APIDOC ## LoroTree.id ### Description Gets the unique identifier for the LoroTree container. ### Method GET ### Endpoint `/llmstxt/loro_dev-llms-full.txt/LoroTree/id` ### Parameters No parameters for this method. ### Request Example ```javascript // No request body for this method ``` ### Response #### Success Response (200) - **id** (ContainerID) - The unique identifier of the container. #### Response Example ```json { "id": "container-abc-123" } ``` ``` -------------------------------- ### LoroList.length Source: https://context7_llms Gets the number of elements currently in the list. ```APIDOC ## LoroList.length ### Description Gets the number of elements in the list. ### Method `length: number` ### Parameters None ### Request Example ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const list = doc.getList("list"); list.push("a"); list.push("b"); list.push("c"); console.log(`List has ${list.length} items`); ``` ### Response #### Success Response (number) Returns the current number of elements in the list. #### Response Example ```json 3 ``` ``` -------------------------------- ### Deep Subscription Example in TypeScript Source: https://context7_llms Demonstrates how to subscribe to changes within a Loro document, including subscribing to specific containers like text and using a deep observation method to track changes across the entire document with path information. ```typescript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); // Subscribe to specific container const text = doc.getText("text"); text.subscribe((event) => { console.log("Text changed:", event); }); // Subscribe with deep observation doc.subscribe((event) => { // Path shows the location of the change event.events.forEach(e => { console.log("Change path:", e.path); console.log("Container:", e.target); console.log("Diff:", e.diff); }); }); ``` -------------------------------- ### LoroText.getAttached Source: https://context7_llms Gets the attached version of this LoroText container. ```APIDOC ## GET /api/text/getAttached ### Description Gets the attached version of this container. ### Method GET ### Endpoint /api/text/getAttached ### Response #### Success Response (200) - **attachedContainerId** (string) - The ID of the attached container, or null if not attached. #### Response Example ```json { "attachedContainerId": "text-container-id" } ``` ``` -------------------------------- ### UndoManager.groupEnd Source: https://context7_llms Terminates a manually started group of operations. ```APIDOC ## UndoManager.groupEnd ### Description Ends the current manual grouping of operations started by `groupStart`. ### Method `groupEnd(): void` ### Behavior - Must be called after `groupStart` to finalize the grouped undo step. ### Request Example ```typescript import { LoroDoc, UndoManager } from "loro-crdt"; const doc = new LoroDoc(); const undo = new UndoManager(doc, {}); const text = doc.getText("text"); undo.groupStart(); text.insert(0, "First part"); doc.commit(); undo.groupEnd(); // Completes the group. ``` ``` -------------------------------- ### JavaScript: Get Document JSON Representation Source: https://loro.dev/llms-full.txt This snippet demonstrates how to get the JSON-like structure representing the complete state of a Loro document. This is equivalent to calling `doc.get_deep_value()` in other languages and represents the time spent on CRDT parsing before a user loads a document. ```javascript const doc = new LoroDocument(); // ... apply operations to the document ... const jsonState = doc.toJSON(); console.log(jsonState); ``` -------------------------------- ### Basic LoroDoc Initialization and Text Manipulation (TypeScript) Source: https://context7_llms Demonstrates how to initialize a LoroDoc and perform basic text insertions without explicit transactions. Each commit creates a new event, allowing for granular tracking of changes. ```typescript import { LoroDoc } from "loro-crdt"; // ---cut--- const doc = new LoroDoc(); // Without transaction - multiple events const text = doc.getText("text"); text.insert(0, "Hello"); doc.commit(); // Event emitted text.insert(5, " World"); doc.commit(); // Another event ``` -------------------------------- ### Initialize Loro UndoManager Source: https://context7_llms Demonstrates how to initialize the Loro UndoManager with a LoroDoc instance. It shows configuration options like maxUndoSteps, mergeInterval, excludeOriginPrefixes, and callback functions for push and pop operations. ```typescript import { UndoManager, LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); // ---cut--- const undoManager = new UndoManager(doc, { maxUndoSteps: 100, // default 100 mergeInterval: 1000, // default 1000ms excludeOriginPrefixes: ["sys:"], // default [] onPush: (isUndo, range, event) => { return { value: null, cursors: [] }; }, onPop: (isUndo, value, counterRange) => { return; }, }); ``` -------------------------------- ### JavaScript: Practical Example of Saving and Restoring Checkpoints Source: https://loro.dev/docs/concepts/frontiers Illustrates a practical use case of Frontiers for managing document states. This example shows how to save multiple checkpoints ('draft' and 'final') using frontiers and restore the document to a specific checkpoint. ```javascript import { LoroDoc } from "loro-crdt"; const doc = new LoroDoc(); const text = doc.getText("content"); const checkpoints = new Map(); // Save checkpoint with frontiers text.insert(0, "Draft version"); checkpoints.set("draft", doc.frontiers()); // Make changes text.delete(0, 5); text.insert(0, "Final"); checkpoints.set("final", doc.frontiers()); // Restore to any checkpoint doc.checkout(checkpoints.get("draft")); console.log(text.toString()); // Output: Draft version ``` -------------------------------- ### Run Loro Initialization (TypeScript) Source: https://context7_llms Initializes the Loro WASM runtime. This function is typically called once at the start of the application and has no input or output. ```typescript export function run(): void; ```