diff --git a/pages/docs/api/js.mdx b/pages/docs/api/js.mdx index 83da9d3..60c51d0 100644 --- a/pages/docs/api/js.mdx +++ b/pages/docs/api/js.mdx @@ -71,6 +71,7 @@ Note: Under the hood, Loro combines a Fugue-based CRDT core with Eg-walker-inspi - **Create rich text**: [`getText`](#LoroDoc.getText) - Initialize a collaborative text container - **Edit text**: [`insert`](#LoroText.insert), [`delete`](#LoroText.delete), [`applyDelta`](#LoroText.applyDelta) - **Apply formatting**: [`mark`](#LoroText.mark) - Add bold, italic, links, custom styles +- **Copy styled snippets**: [`sliceDelta`](#LoroText.sliceDelta) - Get a Delta for a range (UTF-16; use `sliceDeltaUtf8` for byte offsets) - **Track cursor positions**: [`getCursor`](#LoroText.getCursor) + [`getCursorPos`](#LoroDoc.getCursorPos) - Stable positions across edits - **Configure styles**: [`configTextStyle`](#LoroDoc.configTextStyle) - Define expand behavior for marks @@ -2195,6 +2196,71 @@ const delta = text.toDelta(); ``` + +```typescript no_run +sliceDelta(start: number, end: number): Delta[] +``` + + +Returns a Quill-style Delta for a subsection of the text, using UTF-16 indices. Useful for copying a styled span. Use `sliceDeltaUtf8` if you need UTF-8 byte offsets instead. + +**Parameters:** +- `start` - Start UTF-16 code unit index (inclusive) +- `end` - End UTF-16 code unit index (exclusive) + +**Example:** +```ts threeslash +import { LoroDoc } from "loro-crdt"; +import { expect } from "expect"; +const doc = new LoroDoc(); +doc.configTextStyle({ + bold: { expand: "after" }, + comment: { expand: "none" }, +}); +const text = doc.getText("text"); + +text.insert(0, "Hello World!"); +text.mark({ start: 0, end: 5 }, "bold", true); +text.mark({ start: 6, end: 11 }, "comment", "greeting"); + +const snippet = text.sliceDelta(1, 8); +expect(snippet).toStrictEqual([ + { insert: "ello", attributes: { bold: true } }, + { insert: " " }, + { insert: "Wo", attributes: { comment: "greeting" } }, +]); +``` + + + +```typescript no_run +sliceDeltaUtf8(start: number, end: number): Delta[] +``` + + +Returns a Quill-style Delta for a subsection of the text using **UTF-8 byte offsets**. Choose this when your offsets come from UTF-8 encoded buffers. + +**Parameters:** +- `start` - Start byte offset (inclusive) +- `end` - End byte offset (exclusive) + +**Example:** +```ts threeslash +import { LoroDoc } from "loro-crdt"; +import { expect } from "expect"; +const doc = new LoroDoc(); +const text = doc.getText("text"); +text.insert(0, "Hi 👋"); + +const enc = new TextEncoder(); +const start = enc.encode("Hi ").length; // 3 bytes +const end = enc.encode("Hi 👋").length; // 7 bytes + +const delta = text.sliceDeltaUtf8(start, end); +expect(delta).toStrictEqual([{ insert: "👋" }]); +``` + + ```typescript no_run applyDelta(delta: Delta[]): void diff --git a/pages/docs/tutorial/text.mdx b/pages/docs/tutorial/text.mdx index d027b15..087c7c8 100644 --- a/pages/docs/tutorial/text.mdx +++ b/pages/docs/tutorial/text.mdx @@ -224,6 +224,15 @@ Delete text at the given range. Get a string slice. +### `sliceDelta(start: number, end: number): Delta[]` + +Get a Quill-style Delta slice for the given UTF-16 range. Use +`sliceDeltaUtf8` to slice by UTF-8 byte offsets instead. + +### `sliceDeltaUtf8(start: number, end: number): Delta[]` + +Get a Quill-style Delta slice for the given UTF-8 byte range. + ### `toString(): string` Get the plain text value. @@ -352,6 +361,33 @@ console.log(text.toDelta()); // ] ``` +### Slice a Delta snippet + +Use `sliceDelta(start, end)` when you only need a portion of the Delta (for example, to copy a styled snippet). It uses UTF-16 indices just like other text APIs; use `sliceDeltaUtf8` if you need to slice by UTF-8 byte offsets instead. + +```ts twoslash +import { LoroDoc } from "loro-crdt"; +import { expect } from "expect"; +// ---cut--- +const doc = new LoroDoc(); +doc.configTextStyle({ + bold: { expand: "after" }, + comment: { expand: "none" }, +}); +const text = doc.getText("text"); + +text.insert(0, "Hello World!"); +text.mark({ start: 0, end: 5 }, "bold", true); +text.mark({ start: 6, end: 11 }, "comment", "greeting"); + +const snippet = text.sliceDelta(1, 8); +expect(snippet).toStrictEqual([ + { insert: "ello", attributes: { bold: true } }, + { insert: " " }, + { insert: "Wo", attributes: { comment: "greeting" } }, +]); +``` + ### `mark(range: {start: number, end: number}, key: string, value: any): void` Mark the given range with a key-value pair.