* feat: delta rope support init
* perf: use generic-btree v0.9.0
* refactor: improve readability and maintainability
* fix: fix several issues about composing
* fix: a few more issue about composing deletions
* test: rich text
* fix: cover more edge cases
* refactor: use deltarope for list event
* refactor: replace text delta with DeltaRope
* fix: list fuzz err
* fix: safety issue on insert_many
* chore: refine impl of text delta
* refactor: use Replace instead of insert+del in DeltaItem (#330)
* refactor: use Replace instead of insert+del in DeltaItem
* fix: each deltaitem should have non-zero rle_len
Updated generic-btree dependency to version 0.10.3 and refactored DeltaItem and DeltaRope implementations in loro-delta. Refine compose impl
* fix: update generic-btree to fix the update leaf issue
* chore: lockfile
* chore: clippy fix
* refactor: make composing easier to understand
* refactor: simplify the impl of composing
This PR introduces support for retrieving and querying cursors.
## Motivation
Using "index" to denote cursor positions can be unstable, as positions may shift with document edits. To reliably represent a position or range within a document, it is more effective to leverage the unique ID of each item/character in a List CRDT or Text CRDT.
## Updating Cursors
Loro optimizes State metadata by not storing the IDs of deleted elements. This approach, while efficient, complicates tracking cursor positions since they rely on these IDs for precise locations within the document. The solution recalculates position by replaying relevant history to update stable positions 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.
Each position has a "Side" information, indicating the actual cursor position is on the left, right, or directly in the center of the target ID.
Note: In JavaScript, the offset returned when querying a Stable Position is based on the UTF-16 index.
# Example
```ts
const loro = new Loro();
const list = loro.getList("list");
list.insert(0, "a");
const pos0 = list.getStablePos(0);
list.insert(1, "b");
{
const ans = loro.queryStablePos(pos0!);
expect(ans.offset).toEqual(0);
expect(ans.side).toEqual(0);
expect(ans.update).toBeUndefined();
}
list.insert(0, "c");
{
const ans = loro.queryStablePos(pos0!);
expect(ans.offset).toEqual(1);
expect(ans.side).toEqual(0);
expect(ans.update).toBeUndefined();
}
list.delete(1, 1);
{
const ans = loro.queryStablePos(pos0!);
expect(ans.offset).toEqual(1);
expect(ans.side).toEqual(-1);
expect(ans.update).toBeDefined();
}
```
* feat: access elem by path
* fix: parse tree node index by str
* fix: reuse treeid try_from
* chore: rename methods on lib.rs
---------
Co-authored-by: Leon Zhao <leeeon233@gmail.com>
This PR includes a BREAKING CHANGE.
It enables you to create containers before attaching them to the document, making the API more intuitive and straightforward.
A container can be either attached to a document or detached. When it's detached, its history/state does not persist. You can attach a container to a document by inserting it into an attached container. Once a container is attached, its state, along with all of its descendants's states, will be recreated in the document. After attaching, the container and its descendants, will each have their corresponding "attached" version of themselves?
When a detached container x is attached to a document, you can use x.getAttached() to obtain the corresponding attached container.
* refactor: include start_id in seq delete span
* Add size benchmark example (#276)
* test: add size bench example
* chore: update lock file
* refactor: optimize encoding
* perf: make revert ops with the size of m O(m)
* fix: delete span with id merge rule
* fix: fix several bugs related to delete span id
* refactor: encoding container id
* fix: container indexing when merged ops in encoding
* chore: add compress encode size for draw example
* fix: do not need cids in encoding
* chore: change name containerIdx to containerType in encoding
* fix: avoid enter invalid richtext state
* fix: only include the style when the doc contains both style start and style end
* fix: iter_range err in richtext state
* fix: richtext state iter range
* fix: iter range err
* fix: iter range
* chore: rm log
* fix: iter range
* fix: get affected range
* fix: return err if given checkout target is invalid