loro-crdt 1.8.9 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +225 -0
- package/base64/index.js +2863 -2751
- package/base64/loro_wasm.d.ts +1159 -1179
- package/bundler/loro_wasm.d.ts +1159 -1179
- package/bundler/loro_wasm.js +85 -23
- package/bundler/loro_wasm_bg.js +2796 -2759
- package/bundler/loro_wasm_bg.wasm +0 -0
- package/bundler/loro_wasm_bg.wasm.d.ts +257 -257
- package/nodejs/loro_wasm.d.ts +1159 -1179
- package/nodejs/loro_wasm.js +2796 -2759
- package/nodejs/loro_wasm_bg.wasm +0 -0
- package/nodejs/loro_wasm_bg.wasm.d.ts +257 -257
- package/package.json +1 -2
- package/web/loro_wasm.d.ts +1453 -1473
- package/web/loro_wasm.js +2762 -2726
- package/web/loro_wasm_bg.wasm +0 -0
- package/web/loro_wasm_bg.wasm.d.ts +257 -257
package/base64/loro_wasm.d.ts
CHANGED
|
@@ -4,27 +4,12 @@
|
|
|
4
4
|
* Get the version of Loro
|
|
5
5
|
*/
|
|
6
6
|
export function LORO_VERSION(): string;
|
|
7
|
-
export function run(): void;
|
|
8
|
-
export function encodeFrontiers(frontiers: ({ peer: PeerID, counter: number })[]): Uint8Array;
|
|
9
|
-
export function decodeFrontiers(bytes: Uint8Array): { peer: PeerID, counter: number }[];
|
|
10
7
|
/**
|
|
11
8
|
* Enable debug info of Loro
|
|
12
9
|
*/
|
|
13
10
|
export function setDebug(): void;
|
|
14
|
-
export function
|
|
15
|
-
|
|
16
|
-
* Decode the metadata of the import blob.
|
|
17
|
-
*
|
|
18
|
-
* This method is useful to get the following metadata of the import blob:
|
|
19
|
-
*
|
|
20
|
-
* - startVersionVector
|
|
21
|
-
* - endVersionVector
|
|
22
|
-
* - startTimestamp
|
|
23
|
-
* - endTimestamp
|
|
24
|
-
* - mode
|
|
25
|
-
* - changeNum
|
|
26
|
-
*/
|
|
27
|
-
export function decodeImportBlobMeta(blob: Uint8Array, check_checksum: boolean): ImportBlobMetadata;
|
|
11
|
+
export function run(): void;
|
|
12
|
+
export function decodeFrontiers(bytes: Uint8Array): { peer: PeerID, counter: number }[];
|
|
28
13
|
/**
|
|
29
14
|
* Redacts sensitive content in JSON updates within the specified version range.
|
|
30
15
|
*
|
|
@@ -45,6 +30,21 @@ export function decodeImportBlobMeta(blob: Uint8Array, check_checksum: boolean):
|
|
|
45
30
|
* @returns {Object} The redacted JSON updates
|
|
46
31
|
*/
|
|
47
32
|
export function redactJsonUpdates(json_updates: string | JsonSchema, version_range: any): JsonSchema;
|
|
33
|
+
/**
|
|
34
|
+
* Decode the metadata of the import blob.
|
|
35
|
+
*
|
|
36
|
+
* This method is useful to get the following metadata of the import blob:
|
|
37
|
+
*
|
|
38
|
+
* - startVersionVector
|
|
39
|
+
* - endVersionVector
|
|
40
|
+
* - startTimestamp
|
|
41
|
+
* - endTimestamp
|
|
42
|
+
* - mode
|
|
43
|
+
* - changeNum
|
|
44
|
+
*/
|
|
45
|
+
export function decodeImportBlobMeta(blob: Uint8Array, check_checksum: boolean): ImportBlobMetadata;
|
|
46
|
+
export function encodeFrontiers(frontiers: ({ peer: PeerID, counter: number })[]): Uint8Array;
|
|
47
|
+
export function callPendingEvents(): void;
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Container types supported by loro.
|
|
@@ -85,27 +85,6 @@ export type ContainerID =
|
|
|
85
85
|
export type TreeID = `${number}@${PeerID}`;
|
|
86
86
|
|
|
87
87
|
interface LoroDoc {
|
|
88
|
-
/**
|
|
89
|
-
* Export updates from the specific version to the current version
|
|
90
|
-
*
|
|
91
|
-
* @deprecated Use `export({mode: "update", from: version})` instead
|
|
92
|
-
*
|
|
93
|
-
* @example
|
|
94
|
-
* ```ts
|
|
95
|
-
* import { LoroDoc } from "loro-crdt";
|
|
96
|
-
*
|
|
97
|
-
* const doc = new LoroDoc();
|
|
98
|
-
* const text = doc.getText("text");
|
|
99
|
-
* text.insert(0, "Hello");
|
|
100
|
-
* // get all updates of the doc
|
|
101
|
-
* const updates = doc.exportFrom();
|
|
102
|
-
* const version = doc.oplogVersion();
|
|
103
|
-
* text.insert(5, " World");
|
|
104
|
-
* // get updates from specific version to the latest version
|
|
105
|
-
* const updates2 = doc.exportFrom(version);
|
|
106
|
-
* ```
|
|
107
|
-
*/
|
|
108
|
-
exportFrom(version?: VersionVector): Uint8Array;
|
|
109
88
|
/**
|
|
110
89
|
*
|
|
111
90
|
* Get the container corresponding to the container id
|
|
@@ -1451,6 +1430,14 @@ interface EphemeralStoreEvent {
|
|
|
1451
1430
|
*/
|
|
1452
1431
|
export class AwarenessWasm {
|
|
1453
1432
|
free(): void;
|
|
1433
|
+
/**
|
|
1434
|
+
* Get the timestamp of the state of a given peer.
|
|
1435
|
+
*/
|
|
1436
|
+
getTimestamp(peer: number | bigint | `${number}`): number | undefined;
|
|
1437
|
+
/**
|
|
1438
|
+
* Remove the states of outdated peers.
|
|
1439
|
+
*/
|
|
1440
|
+
removeOutdated(): PeerID[];
|
|
1454
1441
|
/**
|
|
1455
1442
|
* Creates a new `Awareness` instance.
|
|
1456
1443
|
*
|
|
@@ -1460,13 +1447,9 @@ export class AwarenessWasm {
|
|
|
1460
1447
|
*/
|
|
1461
1448
|
constructor(peer: number | bigint | `${number}`, timeout: number);
|
|
1462
1449
|
/**
|
|
1463
|
-
*
|
|
1464
|
-
*/
|
|
1465
|
-
encode(peers: Array<any>): Uint8Array;
|
|
1466
|
-
/**
|
|
1467
|
-
* Encodes the state of all peers.
|
|
1450
|
+
* Get the PeerID of the local peer.
|
|
1468
1451
|
*/
|
|
1469
|
-
|
|
1452
|
+
peer(): PeerID;
|
|
1470
1453
|
/**
|
|
1471
1454
|
* Applies the encoded state of peers.
|
|
1472
1455
|
*
|
|
@@ -1475,17 +1458,13 @@ export class AwarenessWasm {
|
|
|
1475
1458
|
*/
|
|
1476
1459
|
apply(encoded_peers_info: Uint8Array): { updated: PeerID[], added: PeerID[] };
|
|
1477
1460
|
/**
|
|
1478
|
-
* Get
|
|
1479
|
-
*/
|
|
1480
|
-
peer(): PeerID;
|
|
1481
|
-
/**
|
|
1482
|
-
* Get the timestamp of the state of a given peer.
|
|
1461
|
+
* Get all the peers
|
|
1483
1462
|
*/
|
|
1484
|
-
|
|
1463
|
+
peers(): PeerID[];
|
|
1485
1464
|
/**
|
|
1486
|
-
*
|
|
1465
|
+
* Encodes the state of the given peers.
|
|
1487
1466
|
*/
|
|
1488
|
-
|
|
1467
|
+
encode(peers: Array<any>): Uint8Array;
|
|
1489
1468
|
/**
|
|
1490
1469
|
* Get the number of peers.
|
|
1491
1470
|
*/
|
|
@@ -1495,9 +1474,9 @@ export class AwarenessWasm {
|
|
|
1495
1474
|
*/
|
|
1496
1475
|
isEmpty(): boolean;
|
|
1497
1476
|
/**
|
|
1498
|
-
*
|
|
1477
|
+
* Encodes the state of all peers.
|
|
1499
1478
|
*/
|
|
1500
|
-
|
|
1479
|
+
encodeAll(): Uint8Array;
|
|
1501
1480
|
}
|
|
1502
1481
|
export class ChangeModifier {
|
|
1503
1482
|
private constructor();
|
|
@@ -1552,24 +1531,27 @@ export class Cursor {
|
|
|
1552
1531
|
*/
|
|
1553
1532
|
pos(): { peer: PeerID, counter: number } | undefined;
|
|
1554
1533
|
/**
|
|
1555
|
-
*
|
|
1534
|
+
* "Cursor"
|
|
1556
1535
|
*/
|
|
1557
|
-
|
|
1536
|
+
kind(): any;
|
|
1558
1537
|
/**
|
|
1559
|
-
*
|
|
1538
|
+
* Get which side of the character/list item the cursor is on.
|
|
1560
1539
|
*/
|
|
1561
|
-
|
|
1540
|
+
side(): Side;
|
|
1562
1541
|
/**
|
|
1563
1542
|
* Decode the cursor from a Uint8Array.
|
|
1564
1543
|
*/
|
|
1565
1544
|
static decode(data: Uint8Array): Cursor;
|
|
1566
1545
|
/**
|
|
1567
|
-
*
|
|
1546
|
+
* Encode the cursor into a Uint8Array.
|
|
1568
1547
|
*/
|
|
1569
|
-
|
|
1548
|
+
encode(): Uint8Array;
|
|
1570
1549
|
}
|
|
1571
1550
|
export class EphemeralStoreWasm {
|
|
1572
1551
|
free(): void;
|
|
1552
|
+
getAllStates(): any;
|
|
1553
|
+
removeOutdated(): void;
|
|
1554
|
+
get(key: string): any;
|
|
1573
1555
|
/**
|
|
1574
1556
|
* Creates a new `EphemeralStore` instance.
|
|
1575
1557
|
*
|
|
@@ -1579,18 +1561,15 @@ export class EphemeralStoreWasm {
|
|
|
1579
1561
|
*/
|
|
1580
1562
|
constructor(timeout: number);
|
|
1581
1563
|
set(key: string, value: any): void;
|
|
1564
|
+
keys(): string[];
|
|
1565
|
+
apply(data: Uint8Array): void;
|
|
1582
1566
|
delete(key: string): void;
|
|
1583
|
-
get(key: string): any;
|
|
1584
|
-
getAllStates(): any;
|
|
1585
1567
|
encode(key: string): Uint8Array;
|
|
1586
|
-
encodeAll(): Uint8Array;
|
|
1587
|
-
apply(data: Uint8Array): void;
|
|
1588
|
-
removeOutdated(): void;
|
|
1589
1568
|
/**
|
|
1590
1569
|
* If the state is empty.
|
|
1591
1570
|
*/
|
|
1592
1571
|
isEmpty(): boolean;
|
|
1593
|
-
|
|
1572
|
+
encodeAll(): Uint8Array;
|
|
1594
1573
|
}
|
|
1595
1574
|
/**
|
|
1596
1575
|
* The handler of a counter container.
|
|
@@ -1598,25 +1577,29 @@ export class EphemeralStoreWasm {
|
|
|
1598
1577
|
export class LoroCounter {
|
|
1599
1578
|
free(): void;
|
|
1600
1579
|
/**
|
|
1601
|
-
*
|
|
1580
|
+
* Whether the container is attached to a docuemnt.
|
|
1581
|
+
*
|
|
1582
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
1602
1583
|
*/
|
|
1603
|
-
|
|
1584
|
+
isAttached(): boolean;
|
|
1604
1585
|
/**
|
|
1605
|
-
*
|
|
1586
|
+
* Get the attached container associated with this.
|
|
1587
|
+
*
|
|
1588
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
1606
1589
|
*/
|
|
1607
|
-
|
|
1590
|
+
getAttached(): LoroTree | undefined;
|
|
1608
1591
|
/**
|
|
1609
|
-
*
|
|
1592
|
+
* Get the value of the counter.
|
|
1610
1593
|
*/
|
|
1611
|
-
|
|
1594
|
+
getShallowValue(): number;
|
|
1612
1595
|
/**
|
|
1613
|
-
*
|
|
1596
|
+
* Create a new LoroCounter.
|
|
1614
1597
|
*/
|
|
1615
|
-
|
|
1598
|
+
constructor();
|
|
1616
1599
|
/**
|
|
1617
|
-
*
|
|
1600
|
+
* "Counter"
|
|
1618
1601
|
*/
|
|
1619
|
-
|
|
1602
|
+
kind(): 'Counter';
|
|
1620
1603
|
/**
|
|
1621
1604
|
* Get the parent container of the counter container.
|
|
1622
1605
|
*
|
|
@@ -1625,23 +1608,19 @@ export class LoroCounter {
|
|
|
1625
1608
|
* the WASM boundary.
|
|
1626
1609
|
*/
|
|
1627
1610
|
parent(): Container | undefined;
|
|
1611
|
+
toJSON(): number;
|
|
1628
1612
|
/**
|
|
1629
|
-
*
|
|
1630
|
-
*
|
|
1631
|
-
* If it's detached, the operations on the container will not be persisted.
|
|
1613
|
+
* Decrement the counter by the given value.
|
|
1632
1614
|
*/
|
|
1633
|
-
|
|
1615
|
+
decrement(value: number): void;
|
|
1634
1616
|
/**
|
|
1635
|
-
*
|
|
1636
|
-
*
|
|
1637
|
-
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
1617
|
+
* Increment the counter by the given value.
|
|
1638
1618
|
*/
|
|
1639
|
-
|
|
1619
|
+
increment(value: number): void;
|
|
1640
1620
|
/**
|
|
1641
|
-
*
|
|
1621
|
+
* Subscribe to the changes of the counter.
|
|
1642
1622
|
*/
|
|
1643
|
-
|
|
1644
|
-
toJSON(): number;
|
|
1623
|
+
subscribe(f: Function): any;
|
|
1645
1624
|
/**
|
|
1646
1625
|
* The container id of this handler.
|
|
1647
1626
|
*/
|
|
@@ -1674,132 +1653,85 @@ export class LoroCounter {
|
|
|
1674
1653
|
export class LoroDoc {
|
|
1675
1654
|
free(): void;
|
|
1676
1655
|
/**
|
|
1677
|
-
*
|
|
1678
|
-
*
|
|
1679
|
-
* New document will have a random peer id.
|
|
1680
|
-
*/
|
|
1681
|
-
constructor();
|
|
1682
|
-
/**
|
|
1683
|
-
* Enables editing in detached mode, which is disabled by default.
|
|
1656
|
+
* Apply a batch of diff to the document
|
|
1684
1657
|
*
|
|
1685
|
-
*
|
|
1658
|
+
* A diff batch represents a set of changes between two versions of the document.
|
|
1659
|
+
* You can calculate a diff batch using `doc.diff()`.
|
|
1686
1660
|
*
|
|
1687
|
-
*
|
|
1661
|
+
* Changes are associated with container IDs. During diff application, if new containers were created in the source
|
|
1662
|
+
* document, they will be assigned fresh IDs in the target document. Loro automatically handles remapping these
|
|
1663
|
+
* container IDs from their original IDs to the new IDs as the diff is applied.
|
|
1688
1664
|
*
|
|
1689
|
-
*
|
|
1690
|
-
*
|
|
1691
|
-
*
|
|
1692
|
-
*
|
|
1693
|
-
*/
|
|
1694
|
-
setDetachedEditing(enable: boolean): void;
|
|
1695
|
-
/**
|
|
1696
|
-
* Whether the editing is enabled in detached mode.
|
|
1665
|
+
* @example
|
|
1666
|
+
* ```ts
|
|
1667
|
+
* const doc1 = new LoroDoc();
|
|
1668
|
+
* const doc2 = new LoroDoc();
|
|
1697
1669
|
*
|
|
1698
|
-
*
|
|
1670
|
+
* // Make some changes to doc1
|
|
1671
|
+
* const text = doc1.getText("text");
|
|
1672
|
+
* text.insert(0, "Hello");
|
|
1699
1673
|
*
|
|
1700
|
-
*
|
|
1674
|
+
* // Calculate diff between empty and current state
|
|
1675
|
+
* const diff = doc1.diff([], doc1.frontiers());
|
|
1701
1676
|
*
|
|
1702
|
-
*
|
|
1703
|
-
*
|
|
1704
|
-
*
|
|
1705
|
-
*
|
|
1677
|
+
* // Apply changes to doc2
|
|
1678
|
+
* doc2.applyDiff(diff);
|
|
1679
|
+
* console.log(doc2.getText("text").toString()); // "Hello"
|
|
1680
|
+
* ```
|
|
1706
1681
|
*/
|
|
1707
|
-
|
|
1682
|
+
applyDiff(diff: [ContainerID, Diff|JsonDiff][]): void;
|
|
1708
1683
|
/**
|
|
1709
|
-
*
|
|
1710
|
-
*
|
|
1711
|
-
* If enabled, the Unix timestamp (in seconds) will be recorded for each change automatically.
|
|
1712
|
-
*
|
|
1713
|
-
* You can also set each timestamp manually when you commit a change.
|
|
1714
|
-
* The timestamp manually set will override the automatic one.
|
|
1715
|
-
*
|
|
1716
|
-
* NOTE: Timestamps are forced to be in ascending order in the OpLog's history.
|
|
1717
|
-
* If you commit a new change with a timestamp that is less than the existing one,
|
|
1718
|
-
* the largest existing timestamp will be used instead.
|
|
1684
|
+
* Check if the doc contains the full history.
|
|
1719
1685
|
*/
|
|
1720
|
-
|
|
1686
|
+
isShallow(): boolean;
|
|
1721
1687
|
/**
|
|
1722
|
-
*
|
|
1723
|
-
*
|
|
1724
|
-
* The default value is 1_000 seconds.
|
|
1725
|
-
*
|
|
1726
|
-
* By default, we record timestamps in seconds for each change. So if the merge interval is 1, and changes A and B
|
|
1727
|
-
* have timestamps of 3 and 4 respectively, then they will be merged into one change
|
|
1688
|
+
* Get the number of changes in the oplog.
|
|
1728
1689
|
*/
|
|
1729
|
-
|
|
1690
|
+
changeCount(): number;
|
|
1730
1691
|
/**
|
|
1731
|
-
*
|
|
1692
|
+
* Get the value or container at the given path
|
|
1732
1693
|
*
|
|
1733
|
-
*
|
|
1734
|
-
* Specifically, you need to config the `expand` property of each style.
|
|
1694
|
+
* The path can be specified in different ways depending on the container type:
|
|
1735
1695
|
*
|
|
1736
|
-
*
|
|
1737
|
-
*
|
|
1696
|
+
* For Tree:
|
|
1697
|
+
* 1. Using node IDs: `tree/{node_id}/property`
|
|
1698
|
+
* 2. Using indices: `tree/0/1/property`
|
|
1738
1699
|
*
|
|
1739
|
-
*
|
|
1700
|
+
* For List and MovableList:
|
|
1701
|
+
* - Using indices: `list/0` or `list/1/property`
|
|
1740
1702
|
*
|
|
1741
|
-
*
|
|
1742
|
-
* -
|
|
1743
|
-
*
|
|
1744
|
-
*
|
|
1703
|
+
* For Map:
|
|
1704
|
+
* - Using keys: `map/key` or `map/nested/property`
|
|
1705
|
+
*
|
|
1706
|
+
* For tree structures, index-based paths follow depth-first traversal order.
|
|
1707
|
+
* The indices start from 0 and represent the position of a node among its siblings.
|
|
1745
1708
|
*
|
|
1746
1709
|
* @example
|
|
1747
1710
|
* ```ts
|
|
1711
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1712
|
+
*
|
|
1748
1713
|
* const doc = new LoroDoc();
|
|
1749
|
-
* doc.
|
|
1750
|
-
*
|
|
1751
|
-
*
|
|
1752
|
-
*
|
|
1753
|
-
* const text = doc.getText("text");
|
|
1754
|
-
* text.insert(0, "Hello World!");
|
|
1755
|
-
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
1756
|
-
* expect(text.toDelta()).toStrictEqual([
|
|
1757
|
-
* {
|
|
1758
|
-
* insert: "Hello",
|
|
1759
|
-
* attributes: {
|
|
1760
|
-
* bold: true,
|
|
1761
|
-
* },
|
|
1762
|
-
* },
|
|
1763
|
-
* {
|
|
1764
|
-
* insert: " World!",
|
|
1765
|
-
* },
|
|
1766
|
-
* ] as Delta<string>[]);
|
|
1714
|
+
* const map = doc.getMap("map");
|
|
1715
|
+
* map.set("key", 1);
|
|
1716
|
+
* console.log(doc.getByPath("map/key")); // 1
|
|
1717
|
+
* console.log(doc.getByPath("map")); // LoroMap
|
|
1767
1718
|
* ```
|
|
1768
1719
|
*/
|
|
1769
|
-
|
|
1770
|
-
/**
|
|
1771
|
-
* Configures the default text style for the document.
|
|
1772
|
-
*
|
|
1773
|
-
* This method sets the default text style configuration for the document when using LoroText.
|
|
1774
|
-
* If `None` is provided, the default style is reset.
|
|
1775
|
-
*/
|
|
1776
|
-
configDefaultTextStyle(style: { expand: 'before'|'after'|'none'|'both' } | undefined): void;
|
|
1720
|
+
getByPath(path: string): Value | Container | undefined;
|
|
1777
1721
|
/**
|
|
1778
|
-
*
|
|
1779
|
-
*
|
|
1780
|
-
* @see You can learn more [here](https://loro.dev/docs/tutorial/encoding).
|
|
1781
|
-
*
|
|
1782
|
-
* @example
|
|
1783
|
-
* ```ts
|
|
1784
|
-
* import { LoroDoc } from "loro-crdt"
|
|
1722
|
+
* Get a LoroCounter by container id
|
|
1785
1723
|
*
|
|
1786
|
-
*
|
|
1787
|
-
* // ...
|
|
1788
|
-
* const bytes = doc.export({ mode: "snapshot" });
|
|
1789
|
-
* const loro = LoroDoc.fromSnapshot(bytes);
|
|
1790
|
-
* ```
|
|
1724
|
+
* If the container does not exist, an error will be thrown.
|
|
1791
1725
|
*/
|
|
1792
|
-
|
|
1726
|
+
getCounter(cid: ContainerID | string): LoroCounter;
|
|
1793
1727
|
/**
|
|
1794
|
-
*
|
|
1728
|
+
* `detached` indicates that the `DocState` is not synchronized with the latest version of `OpLog`.
|
|
1795
1729
|
*
|
|
1796
1730
|
* > The document becomes detached during a `checkout` operation.
|
|
1797
1731
|
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
1798
|
-
* > In a detached state, the document is not editable, and any `import` operations will be
|
|
1732
|
+
* > In a detached state, the document is not editable by default, and any `import` operations will be
|
|
1799
1733
|
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
1800
1734
|
*
|
|
1801
|
-
* This method has the same effect as invoking `checkoutToLatest`.
|
|
1802
|
-
*
|
|
1803
1735
|
* @example
|
|
1804
1736
|
* ```ts
|
|
1805
1737
|
* import { LoroDoc } from "loro-crdt";
|
|
@@ -1808,210 +1740,327 @@ export class LoroDoc {
|
|
|
1808
1740
|
* const text = doc.getText("text");
|
|
1809
1741
|
* const frontiers = doc.frontiers();
|
|
1810
1742
|
* text.insert(0, "Hello World!");
|
|
1743
|
+
* console.log(doc.isDetached()); // false
|
|
1811
1744
|
* doc.checkout(frontiers);
|
|
1812
|
-
*
|
|
1745
|
+
* console.log(doc.isDetached()); // true
|
|
1813
1746
|
* doc.attach();
|
|
1814
|
-
*
|
|
1747
|
+
* console.log(doc.isDetached()); // false
|
|
1815
1748
|
* ```
|
|
1816
1749
|
*/
|
|
1817
|
-
|
|
1750
|
+
isDetached(): boolean;
|
|
1818
1751
|
/**
|
|
1819
|
-
*
|
|
1752
|
+
* Set the peer ID of the current writer.
|
|
1820
1753
|
*
|
|
1821
|
-
*
|
|
1822
|
-
*
|
|
1823
|
-
*
|
|
1824
|
-
*
|
|
1754
|
+
* It must be a number, a BigInt, or a decimal string that can be parsed to a unsigned 64-bit integer.
|
|
1755
|
+
*
|
|
1756
|
+
* Note: use it with caution. You need to make sure there is not chance that two peers
|
|
1757
|
+
* have the same peer ID. Otherwise, we cannot ensure the consistency of the document.
|
|
1758
|
+
*/
|
|
1759
|
+
setPeerId(peer_id: number | bigint | `${number}`): void;
|
|
1760
|
+
/**
|
|
1761
|
+
* Get the absolute position of the given Cursor
|
|
1825
1762
|
*
|
|
1826
1763
|
* @example
|
|
1827
1764
|
* ```ts
|
|
1828
|
-
* import { LoroDoc } from "loro-crdt";
|
|
1829
|
-
*
|
|
1830
1765
|
* const doc = new LoroDoc();
|
|
1831
1766
|
* const text = doc.getText("text");
|
|
1832
|
-
*
|
|
1833
|
-
* text.
|
|
1834
|
-
*
|
|
1835
|
-
* doc.
|
|
1836
|
-
*
|
|
1837
|
-
*
|
|
1838
|
-
*
|
|
1767
|
+
* text.insert(0, "123");
|
|
1768
|
+
* const pos0 = text.getCursor(0, 0);
|
|
1769
|
+
* {
|
|
1770
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
1771
|
+
* expect(ans.offset).toBe(0);
|
|
1772
|
+
* }
|
|
1773
|
+
* text.insert(0, "1");
|
|
1774
|
+
* {
|
|
1775
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
1776
|
+
* expect(ans.offset).toBe(1);
|
|
1777
|
+
* }
|
|
1839
1778
|
* ```
|
|
1840
1779
|
*/
|
|
1841
|
-
|
|
1780
|
+
getCursorPos(cursor: Cursor): { update?: Cursor, offset: number, side: Side } | undefined;
|
|
1842
1781
|
/**
|
|
1843
|
-
*
|
|
1782
|
+
* Check if the doc contains the target container.
|
|
1844
1783
|
*
|
|
1845
|
-
*
|
|
1846
|
-
*
|
|
1784
|
+
* A root container always exists, while a normal container exists
|
|
1785
|
+
* if it has ever been created on the doc.
|
|
1847
1786
|
*
|
|
1848
1787
|
* @example
|
|
1849
1788
|
* ```ts
|
|
1850
|
-
* import { LoroDoc } from "loro-crdt";
|
|
1789
|
+
* import { LoroDoc, LoroMap, LoroText, LoroList } from "loro-crdt";
|
|
1851
1790
|
*
|
|
1852
1791
|
* const doc = new LoroDoc();
|
|
1792
|
+
* doc.setPeerId("1");
|
|
1793
|
+
* const text = doc.getMap("map").setContainer("text", new LoroText());
|
|
1794
|
+
* const list = doc.getMap("map").setContainer("list", new LoroList());
|
|
1795
|
+
* expect(doc.isContainerExists("cid:root-map:Map")).toBe(true);
|
|
1796
|
+
* expect(doc.isContainerExists("cid:0@1:Text")).toBe(true);
|
|
1797
|
+
* expect(doc.isContainerExists("cid:1@1:List")).toBe(true);
|
|
1798
|
+
*
|
|
1799
|
+
* const doc2 = new LoroDoc();
|
|
1800
|
+
* // Containers exist, as long as the history or the doc state include it
|
|
1853
1801
|
* doc.detach();
|
|
1854
|
-
*
|
|
1802
|
+
* doc2.import(doc.export({ mode: "update" }));
|
|
1803
|
+
* expect(doc2.isContainerExists("cid:root-map:Map")).toBe(true);
|
|
1804
|
+
* expect(doc2.isContainerExists("cid:0@1:Text")).toBe(true);
|
|
1805
|
+
* expect(doc2.isContainerExists("cid:1@1:List")).toBe(true);
|
|
1855
1806
|
* ```
|
|
1856
1807
|
*/
|
|
1857
|
-
|
|
1808
|
+
hasContainer(container_id: ContainerID): boolean;
|
|
1858
1809
|
/**
|
|
1859
|
-
*
|
|
1810
|
+
* Import a batch of updates or snapshots.
|
|
1860
1811
|
*
|
|
1861
|
-
*
|
|
1812
|
+
* It's more efficient than importing updates one by one.
|
|
1862
1813
|
*
|
|
1863
|
-
*
|
|
1864
|
-
*
|
|
1814
|
+
* @example
|
|
1815
|
+
* ```ts
|
|
1816
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1817
|
+
*
|
|
1818
|
+
* const doc = new LoroDoc();
|
|
1819
|
+
* const text = doc.getText("text");
|
|
1820
|
+
* text.insert(0, "Hello");
|
|
1821
|
+
* const updates = doc.export({ mode: "update" });
|
|
1822
|
+
* const snapshot = doc.export({ mode: "snapshot" });
|
|
1823
|
+
* const doc2 = new LoroDoc();
|
|
1824
|
+
* doc2.importBatch([snapshot, updates]);
|
|
1825
|
+
* ```
|
|
1865
1826
|
*/
|
|
1866
|
-
|
|
1827
|
+
importBatch(data: Uint8Array[]): ImportStatus;
|
|
1867
1828
|
/**
|
|
1868
|
-
*
|
|
1829
|
+
* Compare the ordering of two Frontiers.
|
|
1869
1830
|
*
|
|
1870
|
-
*
|
|
1831
|
+
* It's assumed that both Frontiers are included by the doc. Otherwise, an error will be thrown.
|
|
1832
|
+
*
|
|
1833
|
+
* Return value:
|
|
1834
|
+
*
|
|
1835
|
+
* - -1: a < b
|
|
1836
|
+
* - 0: a == b
|
|
1837
|
+
* - 1: a > b
|
|
1838
|
+
* - undefined: a ∥ b: a and b are concurrent
|
|
1871
1839
|
*/
|
|
1872
|
-
|
|
1840
|
+
cmpFrontiers(a: ({ peer: PeerID, counter: number })[], b: ({ peer: PeerID, counter: number })[]): -1 | 1 | 0 | undefined;
|
|
1873
1841
|
/**
|
|
1874
|
-
*
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
*
|
|
1879
|
-
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
1842
|
+
* Debug the size of the history
|
|
1843
|
+
*/
|
|
1844
|
+
debugHistory(): void;
|
|
1845
|
+
/**
|
|
1846
|
+
* Create a loro document from the snapshot.
|
|
1880
1847
|
*
|
|
1881
|
-
*
|
|
1848
|
+
* @see You can learn more [here](https://loro.dev/docs/tutorial/encoding).
|
|
1882
1849
|
*
|
|
1883
1850
|
* @example
|
|
1884
1851
|
* ```ts
|
|
1885
|
-
* import { LoroDoc } from "loro-crdt"
|
|
1852
|
+
* import { LoroDoc } from "loro-crdt"
|
|
1886
1853
|
*
|
|
1887
1854
|
* const doc = new LoroDoc();
|
|
1888
|
-
*
|
|
1889
|
-
* const
|
|
1890
|
-
*
|
|
1891
|
-
* doc.checkout(frontiers);
|
|
1892
|
-
* // you need call `checkoutToLatest()` or `attach()` before changing the doc.
|
|
1893
|
-
* doc.checkoutToLatest();
|
|
1894
|
-
* text.insert(0, "Hi");
|
|
1855
|
+
* // ...
|
|
1856
|
+
* const bytes = doc.export({ mode: "snapshot" });
|
|
1857
|
+
* const loro = LoroDoc.fromSnapshot(bytes);
|
|
1895
1858
|
* ```
|
|
1896
1859
|
*/
|
|
1897
|
-
|
|
1860
|
+
static fromSnapshot(snapshot: Uint8Array): LoroDoc;
|
|
1898
1861
|
/**
|
|
1899
|
-
*
|
|
1900
|
-
*
|
|
1901
|
-
* @param ids - the changes to visit
|
|
1902
|
-
* @param f - the callback function, return `true` to continue visiting, return `false` to stop
|
|
1862
|
+
* Get the change that contains the specific ID
|
|
1903
1863
|
*/
|
|
1904
|
-
|
|
1864
|
+
getChangeAt(id: { peer: PeerID, counter: number }): Change;
|
|
1905
1865
|
/**
|
|
1906
|
-
*
|
|
1866
|
+
* Get the version vector of the latest known version in OpLog.
|
|
1907
1867
|
*
|
|
1908
|
-
*
|
|
1868
|
+
* If you checkout to a specific version, this version vector will not change.
|
|
1869
|
+
*/
|
|
1870
|
+
oplogVersion(): VersionVector;
|
|
1871
|
+
/**
|
|
1872
|
+
* Convert frontiers to a version vector
|
|
1909
1873
|
*
|
|
1910
|
-
*
|
|
1911
|
-
* and they can be concurrent to each other. You can use it to find all the changes related to an event:
|
|
1874
|
+
* Learn more about frontiers and version vector [here](https://loro.dev/docs/advanced/version_deep_dive)
|
|
1912
1875
|
*
|
|
1913
1876
|
* @example
|
|
1914
1877
|
* ```ts
|
|
1915
1878
|
* import { LoroDoc } from "loro-crdt";
|
|
1916
1879
|
*
|
|
1917
|
-
* const
|
|
1918
|
-
*
|
|
1919
|
-
*
|
|
1920
|
-
*
|
|
1921
|
-
*
|
|
1922
|
-
* docA.commit();
|
|
1923
|
-
* const snapshot = docA.export({ mode: "snapshot" });
|
|
1924
|
-
* let done = false;
|
|
1925
|
-
* docB.subscribe(e => {
|
|
1926
|
-
* const spans = docB.findIdSpansBetween(e.from, e.to);
|
|
1927
|
-
* const changes = docB.exportJsonInIdSpan(spans.forward[0]);
|
|
1928
|
-
* console.log(changes);
|
|
1929
|
-
* // [{
|
|
1930
|
-
* // id: "0@1",
|
|
1931
|
-
* // timestamp: expect.any(Number),
|
|
1932
|
-
* // deps: [],
|
|
1933
|
-
* // lamport: 0,
|
|
1934
|
-
* // msg: undefined,
|
|
1935
|
-
* // ops: [{
|
|
1936
|
-
* // container: "cid:root-text:Text",
|
|
1937
|
-
* // counter: 0,
|
|
1938
|
-
* // content: {
|
|
1939
|
-
* // type: "insert",
|
|
1940
|
-
* // pos: 0,
|
|
1941
|
-
* // text: "Hello"
|
|
1942
|
-
* // }
|
|
1943
|
-
* // }]
|
|
1944
|
-
* // }]
|
|
1945
|
-
* });
|
|
1946
|
-
* docB.import(snapshot);
|
|
1880
|
+
* const doc = new LoroDoc();
|
|
1881
|
+
* const text = doc.getText("text");
|
|
1882
|
+
* text.insert(0, "Hello");
|
|
1883
|
+
* const frontiers = doc.frontiers();
|
|
1884
|
+
* const version = doc.frontiersToVV(frontiers);
|
|
1947
1885
|
* ```
|
|
1948
1886
|
*/
|
|
1949
|
-
|
|
1887
|
+
frontiersToVV(frontiers: ({ peer: PeerID, counter: number })[]): VersionVector;
|
|
1950
1888
|
/**
|
|
1951
|
-
*
|
|
1952
|
-
*
|
|
1953
|
-
* > The document becomes detached during a `checkout` operation.
|
|
1954
|
-
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
1955
|
-
* > In a detached state, the document is not editable, and any `import` operations will be
|
|
1956
|
-
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
1957
|
-
*
|
|
1958
|
-
* You should call `attach` to attach the `DocState` to the latest version of `OpLog`.
|
|
1889
|
+
* Get all of changes in the oplog.
|
|
1959
1890
|
*
|
|
1960
|
-
*
|
|
1891
|
+
* Note: this method is expensive when the oplog is large. O(n)
|
|
1961
1892
|
*
|
|
1962
1893
|
* @example
|
|
1963
1894
|
* ```ts
|
|
1964
|
-
* import { LoroDoc } from "loro-crdt";
|
|
1895
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
1965
1896
|
*
|
|
1966
1897
|
* const doc = new LoroDoc();
|
|
1967
1898
|
* const text = doc.getText("text");
|
|
1968
|
-
*
|
|
1969
|
-
*
|
|
1970
|
-
*
|
|
1971
|
-
*
|
|
1899
|
+
* text.insert(0, "Hello");
|
|
1900
|
+
* const changes = doc.getAllChanges();
|
|
1901
|
+
*
|
|
1902
|
+
* for (let [peer, c] of changes.entries()){
|
|
1903
|
+
* console.log("peer: ", peer);
|
|
1904
|
+
* for (let change of c){
|
|
1905
|
+
* console.log("change: ", change);
|
|
1906
|
+
* }
|
|
1907
|
+
* }
|
|
1972
1908
|
* ```
|
|
1973
1909
|
*/
|
|
1974
|
-
|
|
1910
|
+
getAllChanges(): Map<PeerID, Change[]>;
|
|
1975
1911
|
/**
|
|
1976
|
-
*
|
|
1977
|
-
*
|
|
1978
|
-
* It must be a number, a BigInt, or a decimal string that can be parsed to a unsigned 64-bit integer.
|
|
1912
|
+
* Get the [frontiers](https://loro.dev/docs/advanced/version_deep_dive) of the latest version in OpLog.
|
|
1979
1913
|
*
|
|
1980
|
-
*
|
|
1981
|
-
* have the same peer ID. Otherwise, we cannot ensure the consistency of the document.
|
|
1914
|
+
* If you checkout to a specific version, this value will not change.
|
|
1982
1915
|
*/
|
|
1983
|
-
|
|
1916
|
+
oplogFrontiers(): { peer: PeerID, counter: number }[];
|
|
1984
1917
|
/**
|
|
1985
|
-
*
|
|
1918
|
+
* Convert a version vector to frontiers
|
|
1986
1919
|
*
|
|
1987
|
-
*
|
|
1920
|
+
* @example
|
|
1921
|
+
* ```ts
|
|
1922
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1988
1923
|
*
|
|
1989
|
-
*
|
|
1990
|
-
*
|
|
1991
|
-
*
|
|
1992
|
-
*
|
|
1924
|
+
* const doc = new LoroDoc();
|
|
1925
|
+
* const text = doc.getText("text");
|
|
1926
|
+
* text.insert(0, "Hello");
|
|
1927
|
+
* const version = doc.version();
|
|
1928
|
+
* const frontiers = doc.vvToFrontiers(version);
|
|
1929
|
+
* ```
|
|
1930
|
+
*/
|
|
1931
|
+
vvToFrontiers(vv: VersionVector): { peer: PeerID, counter: number }[];
|
|
1932
|
+
/**
|
|
1933
|
+
* The doc only contains the history since this version
|
|
1993
1934
|
*
|
|
1994
|
-
*
|
|
1935
|
+
* This is empty if the doc is not shallow.
|
|
1995
1936
|
*
|
|
1996
|
-
*
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
1937
|
+
* The ops included by the shallow history start version vector are not in the doc.
|
|
1938
|
+
*/
|
|
1939
|
+
shallowSinceVV(): VersionVector;
|
|
1940
|
+
/**
|
|
1941
|
+
* Set the rich text format configuration of the document.
|
|
2000
1942
|
*
|
|
2001
|
-
*
|
|
2002
|
-
*
|
|
2003
|
-
* the largest existing timestamp will be used instead.
|
|
1943
|
+
* You need to config it if you use rich text `mark` method.
|
|
1944
|
+
* Specifically, you need to config the `expand` property of each style.
|
|
2004
1945
|
*
|
|
2005
|
-
*
|
|
1946
|
+
* Expand is used to specify the behavior of expanding when new text is inserted at the
|
|
1947
|
+
* beginning or end of the style.
|
|
2006
1948
|
*
|
|
2007
|
-
*
|
|
2008
|
-
*
|
|
2009
|
-
*
|
|
2010
|
-
* -
|
|
2011
|
-
*
|
|
2012
|
-
*
|
|
1949
|
+
* You can specify the `expand` option to set the behavior when inserting text at the boundary of the range.
|
|
1950
|
+
*
|
|
1951
|
+
* - `after`(default): when inserting text right after the given range, the mark will be expanded to include the inserted text
|
|
1952
|
+
* - `before`: when inserting text right before the given range, the mark will be expanded to include the inserted text
|
|
1953
|
+
* - `none`: the mark will not be expanded to include the inserted text at the boundaries
|
|
1954
|
+
* - `both`: when inserting text either right before or right after the given range, the mark will be expanded to include the inserted text
|
|
1955
|
+
*
|
|
1956
|
+
* @example
|
|
1957
|
+
* ```ts
|
|
1958
|
+
* const doc = new LoroDoc();
|
|
1959
|
+
* doc.configTextStyle({
|
|
1960
|
+
* bold: { expand: "after" },
|
|
1961
|
+
* link: { expand: "before" }
|
|
1962
|
+
* });
|
|
1963
|
+
* const text = doc.getText("text");
|
|
1964
|
+
* text.insert(0, "Hello World!");
|
|
1965
|
+
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
1966
|
+
* expect(text.toDelta()).toStrictEqual([
|
|
1967
|
+
* {
|
|
1968
|
+
* insert: "Hello",
|
|
1969
|
+
* attributes: {
|
|
1970
|
+
* bold: true,
|
|
1971
|
+
* },
|
|
1972
|
+
* },
|
|
1973
|
+
* {
|
|
1974
|
+
* insert: " World!",
|
|
1975
|
+
* },
|
|
1976
|
+
* ] as Delta<string>[]);
|
|
1977
|
+
* ```
|
|
2013
1978
|
*/
|
|
2014
|
-
|
|
1979
|
+
configTextStyle(styles: {[key: string]: { expand: 'before'|'after'|'none'|'both' }}): void;
|
|
1980
|
+
/**
|
|
1981
|
+
* Get all ops of the change that contains the specific ID
|
|
1982
|
+
*/
|
|
1983
|
+
getOpsInChange(id: { peer: PeerID, counter: number }): any[];
|
|
1984
|
+
/**
|
|
1985
|
+
* Get the shallow json format of the document state.
|
|
1986
|
+
*
|
|
1987
|
+
* Unlike `toJSON()` which recursively resolves all containers to their values,
|
|
1988
|
+
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
1989
|
+
*
|
|
1990
|
+
* @example
|
|
1991
|
+
* ```ts
|
|
1992
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1993
|
+
*
|
|
1994
|
+
* const doc = new LoroDoc();
|
|
1995
|
+
* const list = doc.getList("list");
|
|
1996
|
+
* const tree = doc.getTree("tree");
|
|
1997
|
+
* const map = doc.getMap("map");
|
|
1998
|
+
* const shallowValue = doc.getShallowValue();
|
|
1999
|
+
* console.log(shallowValue);
|
|
2000
|
+
* // {
|
|
2001
|
+
* // list: 'cid:root-list:List',
|
|
2002
|
+
* // tree: 'cid:root-tree:Tree',
|
|
2003
|
+
* // map: 'cid:root-map:Map'
|
|
2004
|
+
* // }
|
|
2005
|
+
*
|
|
2006
|
+
* // It points to the same container as `list`
|
|
2007
|
+
* const listB = doc.getContainerById(shallowValue.list);
|
|
2008
|
+
* ```
|
|
2009
|
+
*/
|
|
2010
|
+
getShallowValue(): Record<string, ContainerID>;
|
|
2011
|
+
/**
|
|
2012
|
+
* Checkout the `DocState` to the latest version of `OpLog`.
|
|
2013
|
+
*
|
|
2014
|
+
* > The document becomes detached during a `checkout` operation.
|
|
2015
|
+
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
2016
|
+
* > In a detached state, the document is not editable by default, and any `import` operations will be
|
|
2017
|
+
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
2018
|
+
*
|
|
2019
|
+
* This has the same effect as `attach`.
|
|
2020
|
+
*
|
|
2021
|
+
* @example
|
|
2022
|
+
* ```ts
|
|
2023
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2024
|
+
*
|
|
2025
|
+
* const doc = new LoroDoc();
|
|
2026
|
+
* const text = doc.getText("text");
|
|
2027
|
+
* const frontiers = doc.frontiers();
|
|
2028
|
+
* text.insert(0, "Hello World!");
|
|
2029
|
+
* doc.checkout(frontiers);
|
|
2030
|
+
* // you need call `checkoutToLatest()` or `attach()` before changing the doc.
|
|
2031
|
+
* doc.checkoutToLatest();
|
|
2032
|
+
* text.insert(0, "Hi");
|
|
2033
|
+
* ```
|
|
2034
|
+
*/
|
|
2035
|
+
checkoutToLatest(): void;
|
|
2036
|
+
/**
|
|
2037
|
+
* Compare the version of the OpLog with the specified frontiers.
|
|
2038
|
+
*
|
|
2039
|
+
* This method is useful to compare the version by only a small amount of data.
|
|
2040
|
+
*
|
|
2041
|
+
* This method returns an integer indicating the relationship between the version of the OpLog (referred to as 'self')
|
|
2042
|
+
* and the provided 'frontiers' parameter:
|
|
2043
|
+
*
|
|
2044
|
+
* - -1: The version of 'self' is either less than 'frontiers' or is non-comparable (parallel) to 'frontiers',
|
|
2045
|
+
* indicating that it is not definitively less than 'frontiers'.
|
|
2046
|
+
* - 0: The version of 'self' is equal to 'frontiers'.
|
|
2047
|
+
* - 1: The version of 'self' is greater than 'frontiers'.
|
|
2048
|
+
*
|
|
2049
|
+
* # Internal
|
|
2050
|
+
*
|
|
2051
|
+
* Frontiers cannot be compared without the history of the OpLog.
|
|
2052
|
+
*/
|
|
2053
|
+
cmpWithFrontiers(frontiers: ({ peer: PeerID, counter: number })[]): number;
|
|
2054
|
+
/**
|
|
2055
|
+
* Delete all content from a root container and hide it from the document.
|
|
2056
|
+
*
|
|
2057
|
+
* When a root container is empty and hidden:
|
|
2058
|
+
* - It won't show up in `get_deep_value()` results
|
|
2059
|
+
* - It won't be included in document snapshots
|
|
2060
|
+
*
|
|
2061
|
+
* Only works on root containers (containers without parents).
|
|
2062
|
+
*/
|
|
2063
|
+
deleteRootContainer(cid: ContainerID): void;
|
|
2015
2064
|
/**
|
|
2016
2065
|
* Get the number of operations in the pending transaction.
|
|
2017
2066
|
*
|
|
@@ -2020,12 +2069,17 @@ export class LoroDoc {
|
|
|
2020
2069
|
*/
|
|
2021
2070
|
getPendingTxnLength(): number;
|
|
2022
2071
|
/**
|
|
2023
|
-
*
|
|
2072
|
+
* Import updates from the JSON format.
|
|
2024
2073
|
*
|
|
2025
|
-
*
|
|
2026
|
-
|
|
2074
|
+
* only supports backward compatibility but not forward compatibility.
|
|
2075
|
+
*/
|
|
2076
|
+
importJsonUpdates(json: string | JsonSchema): ImportStatus;
|
|
2077
|
+
/**
|
|
2078
|
+
* Import a batch of updates and snapshots.
|
|
2027
2079
|
*
|
|
2028
|
-
*
|
|
2080
|
+
* It's more efficient than importing updates one by one.
|
|
2081
|
+
*
|
|
2082
|
+
* @deprecated Use `importBatch` instead.
|
|
2029
2083
|
*
|
|
2030
2084
|
* @example
|
|
2031
2085
|
* ```ts
|
|
@@ -2033,157 +2087,295 @@ export class LoroDoc {
|
|
|
2033
2087
|
*
|
|
2034
2088
|
* const doc = new LoroDoc();
|
|
2035
2089
|
* const text = doc.getText("text");
|
|
2090
|
+
* text.insert(0, "Hello");
|
|
2091
|
+
* const updates = doc.export({ mode: "update" });
|
|
2092
|
+
* const snapshot = doc.export({ mode: "snapshot" });
|
|
2093
|
+
* const doc2 = new LoroDoc();
|
|
2094
|
+
* doc2.importBatch([snapshot, updates]);
|
|
2036
2095
|
* ```
|
|
2037
2096
|
*/
|
|
2038
|
-
|
|
2097
|
+
importUpdateBatch(data: Uint8Array[]): ImportStatus;
|
|
2039
2098
|
/**
|
|
2040
|
-
*
|
|
2099
|
+
* Enables editing in detached mode, which is disabled by default.
|
|
2041
2100
|
*
|
|
2042
|
-
*
|
|
2101
|
+
* The doc enter detached mode after calling `detach` or checking out a non-latest version.
|
|
2102
|
+
*
|
|
2103
|
+
* # Important Notes:
|
|
2104
|
+
*
|
|
2105
|
+
* - This mode uses a different PeerID for each checkout.
|
|
2106
|
+
* - Ensure no concurrent operations share the same PeerID if set manually.
|
|
2107
|
+
* - Importing does not affect the document's state or version; changes are
|
|
2108
|
+
* recorded in the [OpLog] only. Call `checkout` to apply changes.
|
|
2109
|
+
*/
|
|
2110
|
+
setDetachedEditing(enable: boolean): void;
|
|
2111
|
+
/**
|
|
2112
|
+
* Set whether to record the timestamp of each change. Default is `false`.
|
|
2113
|
+
*
|
|
2114
|
+
* If enabled, the Unix timestamp (in seconds) will be recorded for each change automatically.
|
|
2115
|
+
*
|
|
2116
|
+
* You can also set each timestamp manually when you commit a change.
|
|
2117
|
+
* The timestamp manually set will override the automatic one.
|
|
2118
|
+
*
|
|
2119
|
+
* NOTE: Timestamps are forced to be in ascending order in the OpLog's history.
|
|
2120
|
+
* If you commit a new change with a timestamp that is less than the existing one,
|
|
2121
|
+
* the largest existing timestamp will be used instead.
|
|
2122
|
+
*/
|
|
2123
|
+
setRecordTimestamp(auto_record: boolean): void;
|
|
2124
|
+
/**
|
|
2125
|
+
* Find the op id spans that between the `from` version and the `to` version.
|
|
2126
|
+
*
|
|
2127
|
+
* You can combine it with `exportJsonInIdSpan` to get the changes between two versions.
|
|
2128
|
+
*
|
|
2129
|
+
* You can use it to travel all the changes from `from` to `to`. `from` and `to` are frontiers,
|
|
2130
|
+
* and they can be concurrent to each other. You can use it to find all the changes related to an event:
|
|
2131
|
+
*
|
|
2132
|
+
* @example
|
|
2133
|
+
* ```ts
|
|
2134
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2135
|
+
*
|
|
2136
|
+
* const docA = new LoroDoc();
|
|
2137
|
+
* docA.setPeerId("1");
|
|
2138
|
+
* const docB = new LoroDoc();
|
|
2139
|
+
*
|
|
2140
|
+
* docA.getText("text").update("Hello");
|
|
2141
|
+
* docA.commit();
|
|
2142
|
+
* const snapshot = docA.export({ mode: "snapshot" });
|
|
2143
|
+
* let done = false;
|
|
2144
|
+
* docB.subscribe(e => {
|
|
2145
|
+
* const spans = docB.findIdSpansBetween(e.from, e.to);
|
|
2146
|
+
* const changes = docB.exportJsonInIdSpan(spans.forward[0]);
|
|
2147
|
+
* console.log(changes);
|
|
2148
|
+
* // [{
|
|
2149
|
+
* // id: "0@1",
|
|
2150
|
+
* // timestamp: expect.any(Number),
|
|
2151
|
+
* // deps: [],
|
|
2152
|
+
* // lamport: 0,
|
|
2153
|
+
* // msg: undefined,
|
|
2154
|
+
* // ops: [{
|
|
2155
|
+
* // container: "cid:root-text:Text",
|
|
2156
|
+
* // counter: 0,
|
|
2157
|
+
* // content: {
|
|
2158
|
+
* // type: "insert",
|
|
2159
|
+
* // pos: 0,
|
|
2160
|
+
* // text: "Hello"
|
|
2161
|
+
* // }
|
|
2162
|
+
* // }]
|
|
2163
|
+
* // }]
|
|
2164
|
+
* });
|
|
2165
|
+
* docB.import(snapshot);
|
|
2166
|
+
* ```
|
|
2167
|
+
*/
|
|
2168
|
+
findIdSpansBetween(from: ({ peer: PeerID, counter: number })[], to: ({ peer: PeerID, counter: number })[]): VersionVectorDiff;
|
|
2169
|
+
/**
|
|
2170
|
+
* Get the change of with specific peer_id and lamport <= given lamport
|
|
2171
|
+
*/
|
|
2172
|
+
getChangeAtLamport(peer_id: string, lamport: number): Change | undefined;
|
|
2173
|
+
/**
|
|
2174
|
+
* Get the path from the root to the container
|
|
2175
|
+
*/
|
|
2176
|
+
getPathToContainer(id: ContainerID): (string|number)[] | undefined;
|
|
2177
|
+
/**
|
|
2178
|
+
* Gets container IDs modified in the given ID range.
|
|
2179
|
+
*
|
|
2180
|
+
* **NOTE:** This method will implicitly commit.
|
|
2181
|
+
*
|
|
2182
|
+
* This method identifies which containers were affected by changes in a given range of operations.
|
|
2183
|
+
* It can be used together with `doc.travelChangeAncestors()` to analyze the history of changes
|
|
2184
|
+
* and determine which containers were modified by each change.
|
|
2185
|
+
*
|
|
2186
|
+
* @param id - The starting ID of the change range
|
|
2187
|
+
* @param len - The length of the change range to check
|
|
2188
|
+
* @returns An array of container IDs that were modified in the given range
|
|
2189
|
+
*/
|
|
2190
|
+
getChangedContainersIn(id: { peer: PeerID, counter: number }, len: number): ContainerID[];
|
|
2191
|
+
/**
|
|
2192
|
+
* Get deep value of the document with container id
|
|
2193
|
+
*/
|
|
2194
|
+
getDeepValueWithID(): any;
|
|
2195
|
+
/**
|
|
2196
|
+
* Set the origin of the next commit
|
|
2043
2197
|
*/
|
|
2044
|
-
|
|
2198
|
+
setNextCommitOrigin(origin: string): void;
|
|
2045
2199
|
/**
|
|
2046
|
-
*
|
|
2200
|
+
* Get the pending operations from the current transaction in JSON format
|
|
2047
2201
|
*
|
|
2048
|
-
*
|
|
2049
|
-
*
|
|
2202
|
+
* This method returns a JSON representation of operations that have been applied
|
|
2203
|
+
* but not yet committed in the current transaction.
|
|
2204
|
+
*
|
|
2205
|
+
* It will use the same data format as `doc.exportJsonUpdates()`
|
|
2050
2206
|
*
|
|
2051
2207
|
* @example
|
|
2052
2208
|
* ```ts
|
|
2053
|
-
* import { LoroDoc, LoroMap, LoroText, LoroList } from "loro-crdt";
|
|
2054
|
-
*
|
|
2055
2209
|
* const doc = new LoroDoc();
|
|
2056
|
-
* doc.
|
|
2057
|
-
*
|
|
2058
|
-
*
|
|
2059
|
-
*
|
|
2060
|
-
*
|
|
2061
|
-
*
|
|
2062
|
-
*
|
|
2063
|
-
* const doc2 = new LoroDoc();
|
|
2064
|
-
* // Containers exist, as long as the history or the doc state include it
|
|
2065
|
-
* doc.detach();
|
|
2066
|
-
* doc2.import(doc.export({ mode: "update" }));
|
|
2067
|
-
* expect(doc2.isContainerExists("cid:root-map:Map")).toBe(true);
|
|
2068
|
-
* expect(doc2.isContainerExists("cid:0@1:Text")).toBe(true);
|
|
2069
|
-
* expect(doc2.isContainerExists("cid:1@1:List")).toBe(true);
|
|
2210
|
+
* const text = doc.getText("text");
|
|
2211
|
+
* text.insert(0, "Hello");
|
|
2212
|
+
* // Get pending ops before commit
|
|
2213
|
+
* const pendingOps = doc.getPendingOpsFromCurrentTxnAsJson();
|
|
2214
|
+
* doc.commit();
|
|
2215
|
+
* const emptyOps = doc.getPendingOpsFromCurrentTxnAsJson(); // this is undefined
|
|
2070
2216
|
* ```
|
|
2071
2217
|
*/
|
|
2072
|
-
|
|
2218
|
+
getUncommittedOpsAsJson(): JsonSchema | undefined;
|
|
2073
2219
|
/**
|
|
2074
2220
|
* Set the commit message of the next commit
|
|
2075
2221
|
*/
|
|
2076
2222
|
setNextCommitMessage(msg: string): void;
|
|
2077
2223
|
/**
|
|
2078
|
-
* Set the
|
|
2224
|
+
* Set the options of the next commit
|
|
2079
2225
|
*/
|
|
2080
|
-
|
|
2226
|
+
setNextCommitOptions(options: { origin?: string, timestamp?: number, message?: string }): void;
|
|
2081
2227
|
/**
|
|
2082
|
-
*
|
|
2228
|
+
* The doc only contains the history since this version
|
|
2229
|
+
*
|
|
2230
|
+
* This is empty if the doc is not shallow.
|
|
2231
|
+
*
|
|
2232
|
+
* The ops included by the shallow history start frontiers are not in the doc.
|
|
2083
2233
|
*/
|
|
2084
|
-
|
|
2234
|
+
shallowSinceFrontiers(): { peer: PeerID, counter: number }[];
|
|
2085
2235
|
/**
|
|
2086
|
-
*
|
|
2236
|
+
* Visit all the ancestors of the changes in causal order.
|
|
2237
|
+
*
|
|
2238
|
+
* @param ids - the changes to visit
|
|
2239
|
+
* @param f - the callback function, return `true` to continue visiting, return `false` to stop
|
|
2087
2240
|
*/
|
|
2088
|
-
|
|
2241
|
+
travelChangeAncestors(ids: ({ peer: PeerID, counter: number })[], f: (change: Change) => boolean): void;
|
|
2089
2242
|
/**
|
|
2090
2243
|
* Clear the options of the next commit
|
|
2091
2244
|
*/
|
|
2092
2245
|
clearNextCommitOptions(): void;
|
|
2093
2246
|
/**
|
|
2094
|
-
*
|
|
2247
|
+
* Configures the default text style for the document.
|
|
2248
|
+
*
|
|
2249
|
+
* This method sets the default text style configuration for the document when using LoroText.
|
|
2250
|
+
* If `None` is provided, the default style is reset.
|
|
2095
2251
|
*/
|
|
2096
|
-
|
|
2252
|
+
configDefaultTextStyle(style: { expand: 'before'|'after'|'none'|'both' } | undefined): void;
|
|
2097
2253
|
/**
|
|
2098
|
-
*
|
|
2254
|
+
* If two continuous local changes are within (<=) the interval(**in seconds**), they will be merged into one change.
|
|
2255
|
+
*
|
|
2256
|
+
* The default value is 1_000 seconds.
|
|
2257
|
+
*
|
|
2258
|
+
* By default, we record timestamps in seconds for each change. So if the merge interval is 1, and changes A and B
|
|
2259
|
+
* have timestamps of 3 and 4 respectively, then they will be merged into one change
|
|
2099
2260
|
*/
|
|
2100
|
-
|
|
2261
|
+
setChangeMergeInterval(interval: number): void;
|
|
2101
2262
|
/**
|
|
2102
|
-
*
|
|
2263
|
+
* Set the timestamp of the next commit
|
|
2103
2264
|
*/
|
|
2104
|
-
|
|
2265
|
+
setNextCommitTimestamp(timestamp: number): void;
|
|
2105
2266
|
/**
|
|
2106
|
-
*
|
|
2267
|
+
* Set whether to hide empty root containers.
|
|
2107
2268
|
*
|
|
2108
|
-
*
|
|
2269
|
+
* @example
|
|
2270
|
+
* ```ts
|
|
2271
|
+
* const doc = new LoroDoc();
|
|
2272
|
+
* const map = doc.getMap("map");
|
|
2273
|
+
* console.log(doc.toJSON()); // { map: {} }
|
|
2274
|
+
* doc.setHideEmptyRootContainers(true);
|
|
2275
|
+
* console.log(doc.toJSON()); // {}
|
|
2276
|
+
* ```
|
|
2109
2277
|
*/
|
|
2110
|
-
|
|
2278
|
+
setHideEmptyRootContainers(hide: boolean): void;
|
|
2111
2279
|
/**
|
|
2112
|
-
*
|
|
2280
|
+
* Whether the editing is enabled in detached mode.
|
|
2113
2281
|
*
|
|
2114
|
-
*
|
|
2282
|
+
* The doc enter detached mode after calling `detach` or checking out a non-latest version.
|
|
2115
2283
|
*
|
|
2116
|
-
*
|
|
2284
|
+
* # Important Notes:
|
|
2285
|
+
*
|
|
2286
|
+
* - This mode uses a different PeerID for each checkout.
|
|
2287
|
+
* - Ensure no concurrent operations share the same PeerID if set manually.
|
|
2288
|
+
* - Importing does not affect the document's state or version; changes are
|
|
2289
|
+
* recorded in the [OpLog] only. Call `checkout` to apply changes.
|
|
2117
2290
|
*/
|
|
2118
|
-
|
|
2291
|
+
isDetachedEditingEnabled(): boolean;
|
|
2119
2292
|
/**
|
|
2120
|
-
*
|
|
2293
|
+
* Create a new loro document.
|
|
2294
|
+
*
|
|
2295
|
+
* New document will have a random peer id.
|
|
2121
2296
|
*/
|
|
2122
|
-
|
|
2297
|
+
constructor();
|
|
2123
2298
|
/**
|
|
2124
|
-
*
|
|
2299
|
+
* Duplicate the document with a different PeerID
|
|
2125
2300
|
*
|
|
2126
|
-
*
|
|
2301
|
+
* The time complexity and space complexity of this operation are both O(n),
|
|
2127
2302
|
*
|
|
2128
|
-
*
|
|
2303
|
+
* When called in detached mode, it will fork at the current state frontiers.
|
|
2304
|
+
* It will have the same effect as `forkAt(&self.frontiers())`.
|
|
2129
2305
|
*/
|
|
2130
|
-
|
|
2306
|
+
fork(): LoroDoc;
|
|
2131
2307
|
/**
|
|
2132
|
-
*
|
|
2308
|
+
* Attach the document state to the latest known version.
|
|
2133
2309
|
*
|
|
2134
|
-
*
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
* Get the [frontiers](https://loro.dev/docs/advanced/version_deep_dive) of the current document state.
|
|
2310
|
+
* > The document becomes detached during a `checkout` operation.
|
|
2311
|
+
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
2312
|
+
* > In a detached state, the document is not editable, and any `import` operations will be
|
|
2313
|
+
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
2139
2314
|
*
|
|
2140
|
-
*
|
|
2141
|
-
*/
|
|
2142
|
-
frontiers(): { peer: PeerID, counter: number }[];
|
|
2143
|
-
/**
|
|
2144
|
-
* Get the [frontiers](https://loro.dev/docs/advanced/version_deep_dive) of the latest version in OpLog.
|
|
2315
|
+
* This method has the same effect as invoking `checkoutToLatest`.
|
|
2145
2316
|
*
|
|
2146
|
-
*
|
|
2317
|
+
* @example
|
|
2318
|
+
* ```ts
|
|
2319
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2320
|
+
*
|
|
2321
|
+
* const doc = new LoroDoc();
|
|
2322
|
+
* const text = doc.getText("text");
|
|
2323
|
+
* const frontiers = doc.frontiers();
|
|
2324
|
+
* text.insert(0, "Hello World!");
|
|
2325
|
+
* doc.checkout(frontiers);
|
|
2326
|
+
* // you need call `attach()` or `checkoutToLatest()` before changing the doc.
|
|
2327
|
+
* doc.attach();
|
|
2328
|
+
* text.insert(0, "Hi");
|
|
2329
|
+
* ```
|
|
2147
2330
|
*/
|
|
2148
|
-
|
|
2331
|
+
attach(): void;
|
|
2149
2332
|
/**
|
|
2150
|
-
*
|
|
2151
|
-
*
|
|
2152
|
-
* This method is useful to compare the version by only a small amount of data.
|
|
2333
|
+
* Commit the cumulative auto-committed transaction.
|
|
2153
2334
|
*
|
|
2154
|
-
*
|
|
2155
|
-
* and the provided 'frontiers' parameter:
|
|
2335
|
+
* You can specify the `origin`, `timestamp`, and `message` of the commit.
|
|
2156
2336
|
*
|
|
2157
|
-
* -
|
|
2158
|
-
*
|
|
2159
|
-
* -
|
|
2160
|
-
*
|
|
2337
|
+
* - The `origin` is used to mark the event
|
|
2338
|
+
* - The `message` works like a git commit message, which will be recorded and synced to peers
|
|
2339
|
+
* - The `timestamp` is the number of seconds that have elapsed since 00:00:00 UTC on January 1, 1970.
|
|
2340
|
+
* It defaults to `Date.now() / 1000` when timestamp recording is enabled
|
|
2161
2341
|
*
|
|
2162
|
-
*
|
|
2342
|
+
* The events will be emitted after a transaction is committed. A transaction is committed when:
|
|
2163
2343
|
*
|
|
2164
|
-
*
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
* Compare the ordering of two Frontiers.
|
|
2344
|
+
* - `doc.commit()` is called.
|
|
2345
|
+
* - `doc.export(mode)` is called.
|
|
2346
|
+
* - `doc.import(data)` is called.
|
|
2347
|
+
* - `doc.checkout(version)` is called.
|
|
2169
2348
|
*
|
|
2170
|
-
*
|
|
2349
|
+
* NOTE: Timestamps are forced to be in ascending order.
|
|
2350
|
+
* If you commit a new change with a timestamp that is less than the existing one,
|
|
2351
|
+
* the largest existing timestamp will be used instead.
|
|
2171
2352
|
*
|
|
2172
|
-
*
|
|
2353
|
+
* NOTE: The `origin` will not be persisted, but the `message` will.
|
|
2173
2354
|
*
|
|
2174
|
-
*
|
|
2175
|
-
* -
|
|
2176
|
-
*
|
|
2177
|
-
* -
|
|
2355
|
+
* Behavior on empty commits:
|
|
2356
|
+
* - This method is an explicit commit. If the pending transaction is empty, any provided
|
|
2357
|
+
* options (message/timestamp/origin) are swallowed and will not carry over to the next commit.
|
|
2358
|
+
* - Implicit commits triggered by `export`/`checkout` act as processing barriers. If the
|
|
2359
|
+
* transaction is empty in those cases, `message`/`timestamp`/`origin` are preserved for the
|
|
2360
|
+
* next commit.
|
|
2178
2361
|
*/
|
|
2179
|
-
|
|
2362
|
+
commit(options?: { origin?: string, timestamp?: number, message?: string } | null): void;
|
|
2180
2363
|
/**
|
|
2181
|
-
*
|
|
2182
|
-
* It includes all the history and the document state
|
|
2364
|
+
* Detach the document state from the latest known version.
|
|
2183
2365
|
*
|
|
2184
|
-
*
|
|
2366
|
+
* After detaching, all import operations will be recorded in the `OpLog` without being applied to the `DocState`.
|
|
2367
|
+
* When `detached`, the document is not editable.
|
|
2368
|
+
*
|
|
2369
|
+
* @example
|
|
2370
|
+
* ```ts
|
|
2371
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2372
|
+
*
|
|
2373
|
+
* const doc = new LoroDoc();
|
|
2374
|
+
* doc.detach();
|
|
2375
|
+
* console.log(doc.isDetached()); // true
|
|
2376
|
+
* ```
|
|
2185
2377
|
*/
|
|
2186
|
-
|
|
2378
|
+
detach(): void;
|
|
2187
2379
|
/**
|
|
2188
2380
|
* Export the document based on the specified ExportMode.
|
|
2189
2381
|
*
|
|
@@ -2222,63 +2414,13 @@ export class LoroDoc {
|
|
|
2222
2414
|
* });
|
|
2223
2415
|
* ```
|
|
2224
2416
|
*/
|
|
2225
|
-
export(mode: ExportMode): Uint8Array;
|
|
2226
|
-
/**
|
|
2227
|
-
* Import updates from the JSON format.
|
|
2228
|
-
*
|
|
2229
|
-
* only supports backward compatibility but not forward compatibility.
|
|
2230
|
-
*/
|
|
2231
|
-
importJsonUpdates(json: string | JsonSchema): ImportStatus;
|
|
2232
|
-
/**
|
|
2233
|
-
* Import snapshot or updates into current doc.
|
|
2234
|
-
*
|
|
2235
|
-
* Note:
|
|
2236
|
-
* - Updates within the current version will be ignored
|
|
2237
|
-
* - Updates with missing dependencies will be pending until the dependencies are received
|
|
2238
|
-
*
|
|
2239
|
-
* @example
|
|
2240
|
-
* ```ts
|
|
2241
|
-
* import { LoroDoc } from "loro-crdt";
|
|
2242
|
-
*
|
|
2243
|
-
* const doc = new LoroDoc();
|
|
2244
|
-
* const text = doc.getText("text");
|
|
2245
|
-
* text.insert(0, "Hello");
|
|
2246
|
-
* // get all updates of the doc
|
|
2247
|
-
* const updates = doc.export({ mode: "update" });
|
|
2248
|
-
* const snapshot = doc.export({ mode: "snapshot" });
|
|
2249
|
-
* const doc2 = new LoroDoc();
|
|
2250
|
-
* // import snapshot
|
|
2251
|
-
* doc2.import(snapshot);
|
|
2252
|
-
* // or import updates
|
|
2253
|
-
* doc2.import(updates);
|
|
2254
|
-
* ```
|
|
2255
|
-
*/
|
|
2256
|
-
import(update_or_snapshot: Uint8Array): ImportStatus;
|
|
2257
|
-
/**
|
|
2258
|
-
* Import a batch of updates and snapshots.
|
|
2259
|
-
*
|
|
2260
|
-
* It's more efficient than importing updates one by one.
|
|
2261
|
-
*
|
|
2262
|
-
* @deprecated Use `importBatch` instead.
|
|
2263
|
-
*
|
|
2264
|
-
* @example
|
|
2265
|
-
* ```ts
|
|
2266
|
-
* import { LoroDoc } from "loro-crdt";
|
|
2267
|
-
*
|
|
2268
|
-
* const doc = new LoroDoc();
|
|
2269
|
-
* const text = doc.getText("text");
|
|
2270
|
-
* text.insert(0, "Hello");
|
|
2271
|
-
* const updates = doc.export({ mode: "update" });
|
|
2272
|
-
* const snapshot = doc.export({ mode: "snapshot" });
|
|
2273
|
-
* const doc2 = new LoroDoc();
|
|
2274
|
-
* doc2.importBatch([snapshot, updates]);
|
|
2275
|
-
* ```
|
|
2276
|
-
*/
|
|
2277
|
-
importUpdateBatch(data: Uint8Array[]): ImportStatus;
|
|
2417
|
+
export(mode: ExportMode): Uint8Array;
|
|
2278
2418
|
/**
|
|
2279
|
-
* Import
|
|
2419
|
+
* Import snapshot or updates into current doc.
|
|
2280
2420
|
*
|
|
2281
|
-
*
|
|
2421
|
+
* Note:
|
|
2422
|
+
* - Updates within the current version will be ignored
|
|
2423
|
+
* - Updates with missing dependencies will be pending until the dependencies are received
|
|
2282
2424
|
*
|
|
2283
2425
|
* @example
|
|
2284
2426
|
* ```ts
|
|
@@ -2287,40 +2429,27 @@ export class LoroDoc {
|
|
|
2287
2429
|
* const doc = new LoroDoc();
|
|
2288
2430
|
* const text = doc.getText("text");
|
|
2289
2431
|
* text.insert(0, "Hello");
|
|
2432
|
+
* // get all updates of the doc
|
|
2290
2433
|
* const updates = doc.export({ mode: "update" });
|
|
2291
2434
|
* const snapshot = doc.export({ mode: "snapshot" });
|
|
2292
2435
|
* const doc2 = new LoroDoc();
|
|
2293
|
-
*
|
|
2436
|
+
* // import snapshot
|
|
2437
|
+
* doc2.import(snapshot);
|
|
2438
|
+
* // or import updates
|
|
2439
|
+
* doc2.import(updates);
|
|
2294
2440
|
* ```
|
|
2295
2441
|
*/
|
|
2296
|
-
|
|
2442
|
+
import(update_or_snapshot: Uint8Array): ImportStatus;
|
|
2297
2443
|
/**
|
|
2298
|
-
*
|
|
2299
|
-
*
|
|
2300
|
-
* Unlike `toJSON()` which recursively resolves all containers to their values,
|
|
2301
|
-
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
2302
|
-
*
|
|
2303
|
-
* @example
|
|
2304
|
-
* ```ts
|
|
2305
|
-
* import { LoroDoc } from "loro-crdt";
|
|
2306
|
-
*
|
|
2307
|
-
* const doc = new LoroDoc();
|
|
2308
|
-
* const list = doc.getList("list");
|
|
2309
|
-
* const tree = doc.getTree("tree");
|
|
2310
|
-
* const map = doc.getMap("map");
|
|
2311
|
-
* const shallowValue = doc.getShallowValue();
|
|
2312
|
-
* console.log(shallowValue);
|
|
2313
|
-
* // {
|
|
2314
|
-
* // list: 'cid:root-list:List',
|
|
2315
|
-
* // tree: 'cid:root-tree:Tree',
|
|
2316
|
-
* // map: 'cid:root-map:Map'
|
|
2317
|
-
* // }
|
|
2444
|
+
* Creates a new LoroDoc at a specified version (Frontiers)
|
|
2318
2445
|
*
|
|
2319
|
-
*
|
|
2320
|
-
* const listB = doc.getContainerById(shallowValue.list);
|
|
2321
|
-
* ```
|
|
2446
|
+
* The created doc will only contain the history before the specified frontiers.
|
|
2322
2447
|
*/
|
|
2323
|
-
|
|
2448
|
+
forkAt(frontiers: ({ peer: PeerID, counter: number })[]): LoroDoc;
|
|
2449
|
+
/**
|
|
2450
|
+
* Get the number of ops in the oplog.
|
|
2451
|
+
*/
|
|
2452
|
+
opCount(): number;
|
|
2324
2453
|
/**
|
|
2325
2454
|
* Get the json format of the entire document state.
|
|
2326
2455
|
*
|
|
@@ -2344,71 +2473,22 @@ export class LoroDoc {
|
|
|
2344
2473
|
*/
|
|
2345
2474
|
toJSON(): any;
|
|
2346
2475
|
/**
|
|
2347
|
-
*
|
|
2348
|
-
*/
|
|
2349
|
-
debugHistory(): void;
|
|
2350
|
-
/**
|
|
2351
|
-
* Get the number of changes in the oplog.
|
|
2352
|
-
*/
|
|
2353
|
-
changeCount(): number;
|
|
2354
|
-
/**
|
|
2355
|
-
* Get the number of ops in the oplog.
|
|
2356
|
-
*/
|
|
2357
|
-
opCount(): number;
|
|
2358
|
-
/**
|
|
2359
|
-
* Get all of changes in the oplog.
|
|
2360
|
-
*
|
|
2361
|
-
* Note: this method is expensive when the oplog is large. O(n)
|
|
2362
|
-
*
|
|
2363
|
-
* @example
|
|
2364
|
-
* ```ts
|
|
2365
|
-
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
2366
|
-
*
|
|
2367
|
-
* const doc = new LoroDoc();
|
|
2368
|
-
* const text = doc.getText("text");
|
|
2369
|
-
* text.insert(0, "Hello");
|
|
2370
|
-
* const changes = doc.getAllChanges();
|
|
2476
|
+
* Get the version vector of the current document state.
|
|
2371
2477
|
*
|
|
2372
|
-
*
|
|
2373
|
-
* console.log("peer: ", peer);
|
|
2374
|
-
* for (let change of c){
|
|
2375
|
-
* console.log("change: ", change);
|
|
2376
|
-
* }
|
|
2377
|
-
* }
|
|
2378
|
-
* ```
|
|
2379
|
-
*/
|
|
2380
|
-
getAllChanges(): Map<PeerID, Change[]>;
|
|
2381
|
-
/**
|
|
2382
|
-
* Get the change that contains the specific ID
|
|
2383
|
-
*/
|
|
2384
|
-
getChangeAt(id: { peer: PeerID, counter: number }): Change;
|
|
2385
|
-
/**
|
|
2386
|
-
* Get the change of with specific peer_id and lamport <= given lamport
|
|
2387
|
-
*/
|
|
2388
|
-
getChangeAtLamport(peer_id: string, lamport: number): Change | undefined;
|
|
2389
|
-
/**
|
|
2390
|
-
* Get all ops of the change that contains the specific ID
|
|
2478
|
+
* If you checkout to a specific version, the version vector will change.
|
|
2391
2479
|
*/
|
|
2392
|
-
|
|
2480
|
+
version(): VersionVector;
|
|
2393
2481
|
/**
|
|
2394
|
-
*
|
|
2482
|
+
* Checkout the `DocState` to a specific version.
|
|
2395
2483
|
*
|
|
2396
|
-
*
|
|
2484
|
+
* > The document becomes detached during a `checkout` operation.
|
|
2485
|
+
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
2486
|
+
* > In a detached state, the document is not editable, and any `import` operations will be
|
|
2487
|
+
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
2397
2488
|
*
|
|
2398
|
-
*
|
|
2399
|
-
* ```ts
|
|
2400
|
-
* import { LoroDoc } from "loro-crdt";
|
|
2489
|
+
* You should call `attach` to attach the `DocState` to the latest version of `OpLog`.
|
|
2401
2490
|
*
|
|
2402
|
-
*
|
|
2403
|
-
* const text = doc.getText("text");
|
|
2404
|
-
* text.insert(0, "Hello");
|
|
2405
|
-
* const frontiers = doc.frontiers();
|
|
2406
|
-
* const version = doc.frontiersToVV(frontiers);
|
|
2407
|
-
* ```
|
|
2408
|
-
*/
|
|
2409
|
-
frontiersToVV(frontiers: ({ peer: PeerID, counter: number })[]): VersionVector;
|
|
2410
|
-
/**
|
|
2411
|
-
* Convert a version vector to frontiers
|
|
2491
|
+
* @param frontiers - the specific frontiers
|
|
2412
2492
|
*
|
|
2413
2493
|
* @example
|
|
2414
2494
|
* ```ts
|
|
@@ -2416,174 +2496,66 @@ export class LoroDoc {
|
|
|
2416
2496
|
*
|
|
2417
2497
|
* const doc = new LoroDoc();
|
|
2418
2498
|
* const text = doc.getText("text");
|
|
2419
|
-
*
|
|
2420
|
-
*
|
|
2421
|
-
*
|
|
2499
|
+
* const frontiers = doc.frontiers();
|
|
2500
|
+
* text.insert(0, "Hello World!");
|
|
2501
|
+
* doc.checkout(frontiers);
|
|
2502
|
+
* console.log(doc.toJSON()); // {"text": ""}
|
|
2422
2503
|
* ```
|
|
2423
2504
|
*/
|
|
2424
|
-
|
|
2505
|
+
checkout(frontiers: ({ peer: PeerID, counter: number })[]): void;
|
|
2425
2506
|
/**
|
|
2426
|
-
* Get
|
|
2427
|
-
*
|
|
2428
|
-
* The path can be specified in different ways depending on the container type:
|
|
2429
|
-
*
|
|
2430
|
-
* For Tree:
|
|
2431
|
-
* 1. Using node IDs: `tree/{node_id}/property`
|
|
2432
|
-
* 2. Using indices: `tree/0/1/property`
|
|
2433
|
-
*
|
|
2434
|
-
* For List and MovableList:
|
|
2435
|
-
* - Using indices: `list/0` or `list/1/property`
|
|
2507
|
+
* Get a LoroText by container id.
|
|
2436
2508
|
*
|
|
2437
|
-
*
|
|
2438
|
-
*
|
|
2509
|
+
* The object returned is a new js object each time because it need to cross
|
|
2510
|
+
* the WASM boundary.
|
|
2439
2511
|
*
|
|
2440
|
-
*
|
|
2441
|
-
* The indices start from 0 and represent the position of a node among its siblings.
|
|
2512
|
+
* If the container does not exist, an error will be thrown.
|
|
2442
2513
|
*
|
|
2443
2514
|
* @example
|
|
2444
2515
|
* ```ts
|
|
2445
2516
|
* import { LoroDoc } from "loro-crdt";
|
|
2446
2517
|
*
|
|
2447
2518
|
* const doc = new LoroDoc();
|
|
2448
|
-
* const map = doc.getMap("map");
|
|
2449
|
-
* map.set("key", 1);
|
|
2450
|
-
* console.log(doc.getByPath("map/key")); // 1
|
|
2451
|
-
* console.log(doc.getByPath("map")); // LoroMap
|
|
2452
|
-
* ```
|
|
2453
|
-
*/
|
|
2454
|
-
getByPath(path: string): Value | Container | undefined;
|
|
2455
|
-
/**
|
|
2456
|
-
* Get the absolute position of the given Cursor
|
|
2457
|
-
*
|
|
2458
|
-
* @example
|
|
2459
|
-
* ```ts
|
|
2460
|
-
* const doc = new LoroDoc();
|
|
2461
|
-
* const text = doc.getText("text");
|
|
2462
|
-
* text.insert(0, "123");
|
|
2463
|
-
* const pos0 = text.getCursor(0, 0);
|
|
2464
|
-
* {
|
|
2465
|
-
* const ans = doc.getCursorPos(pos0!);
|
|
2466
|
-
* expect(ans.offset).toBe(0);
|
|
2467
|
-
* }
|
|
2468
|
-
* text.insert(0, "1");
|
|
2469
|
-
* {
|
|
2470
|
-
* const ans = doc.getCursorPos(pos0!);
|
|
2471
|
-
* expect(ans.offset).toBe(1);
|
|
2472
|
-
* }
|
|
2473
|
-
* ```
|
|
2474
|
-
*/
|
|
2475
|
-
getCursorPos(cursor: Cursor): { update?: Cursor, offset: number, side: Side } | undefined;
|
|
2476
|
-
/**
|
|
2477
|
-
* Gets container IDs modified in the given ID range.
|
|
2478
|
-
*
|
|
2479
|
-
* **NOTE:** This method will implicitly commit.
|
|
2480
|
-
*
|
|
2481
|
-
* This method identifies which containers were affected by changes in a given range of operations.
|
|
2482
|
-
* It can be used together with `doc.travelChangeAncestors()` to analyze the history of changes
|
|
2483
|
-
* and determine which containers were modified by each change.
|
|
2484
|
-
*
|
|
2485
|
-
* @param id - The starting ID of the change range
|
|
2486
|
-
* @param len - The length of the change range to check
|
|
2487
|
-
* @returns An array of container IDs that were modified in the given range
|
|
2488
|
-
*/
|
|
2489
|
-
getChangedContainersIn(id: { peer: PeerID, counter: number }, len: number): ContainerID[];
|
|
2490
|
-
/**
|
|
2491
|
-
* Revert the document to the given frontiers.
|
|
2492
|
-
*
|
|
2493
|
-
* The doc will not become detached when using this method. Instead, it will generate a series
|
|
2494
|
-
* of operations to revert the document to the given version.
|
|
2495
|
-
*
|
|
2496
|
-
* @example
|
|
2497
|
-
* ```ts
|
|
2498
|
-
* const doc = new LoroDoc();
|
|
2499
|
-
* doc.setPeerId("1");
|
|
2500
2519
|
* const text = doc.getText("text");
|
|
2501
|
-
* text.insert(0, "Hello");
|
|
2502
|
-
* doc.commit();
|
|
2503
|
-
* doc.revertTo([{ peer: "1", counter: 1 }]);
|
|
2504
|
-
* expect(doc.getText("text").toString()).toBe("He");
|
|
2505
|
-
* ```
|
|
2506
|
-
*/
|
|
2507
|
-
revertTo(frontiers: ({ peer: PeerID, counter: number })[]): void;
|
|
2508
|
-
/**
|
|
2509
|
-
* Apply a batch of diff to the document
|
|
2510
|
-
*
|
|
2511
|
-
* A diff batch represents a set of changes between two versions of the document.
|
|
2512
|
-
* You can calculate a diff batch using `doc.diff()`.
|
|
2513
|
-
*
|
|
2514
|
-
* Changes are associated with container IDs. During diff application, if new containers were created in the source
|
|
2515
|
-
* document, they will be assigned fresh IDs in the target document. Loro automatically handles remapping these
|
|
2516
|
-
* container IDs from their original IDs to the new IDs as the diff is applied.
|
|
2517
|
-
*
|
|
2518
|
-
* @example
|
|
2519
|
-
* ```ts
|
|
2520
|
-
* const doc1 = new LoroDoc();
|
|
2521
|
-
* const doc2 = new LoroDoc();
|
|
2522
|
-
*
|
|
2523
|
-
* // Make some changes to doc1
|
|
2524
|
-
* const text = doc1.getText("text");
|
|
2525
|
-
* text.insert(0, "Hello");
|
|
2526
|
-
*
|
|
2527
|
-
* // Calculate diff between empty and current state
|
|
2528
|
-
* const diff = doc1.diff([], doc1.frontiers());
|
|
2529
|
-
*
|
|
2530
|
-
* // Apply changes to doc2
|
|
2531
|
-
* doc2.applyDiff(diff);
|
|
2532
|
-
* console.log(doc2.getText("text").toString()); // "Hello"
|
|
2533
2520
|
* ```
|
|
2534
2521
|
*/
|
|
2535
|
-
|
|
2522
|
+
getText(cid: ContainerID | string): LoroText;
|
|
2536
2523
|
/**
|
|
2537
|
-
* Get the
|
|
2538
|
-
*
|
|
2539
|
-
* This method returns a JSON representation of operations that have been applied
|
|
2540
|
-
* but not yet committed in the current transaction.
|
|
2541
|
-
*
|
|
2542
|
-
* It will use the same data format as `doc.exportJsonUpdates()`
|
|
2524
|
+
* Get the [frontiers](https://loro.dev/docs/advanced/version_deep_dive) of the current document state.
|
|
2543
2525
|
*
|
|
2544
|
-
*
|
|
2545
|
-
* ```ts
|
|
2546
|
-
* const doc = new LoroDoc();
|
|
2547
|
-
* const text = doc.getText("text");
|
|
2548
|
-
* text.insert(0, "Hello");
|
|
2549
|
-
* // Get pending ops before commit
|
|
2550
|
-
* const pendingOps = doc.getPendingOpsFromCurrentTxnAsJson();
|
|
2551
|
-
* doc.commit();
|
|
2552
|
-
* const emptyOps = doc.getPendingOpsFromCurrentTxnAsJson(); // this is undefined
|
|
2553
|
-
* ```
|
|
2526
|
+
* If you checkout to a specific version, this value will change.
|
|
2554
2527
|
*/
|
|
2555
|
-
|
|
2528
|
+
frontiers(): { peer: PeerID, counter: number }[];
|
|
2556
2529
|
/**
|
|
2557
|
-
*
|
|
2558
|
-
*
|
|
2559
|
-
* When a root container is empty and hidden:
|
|
2560
|
-
* - It won't show up in `get_deep_value()` results
|
|
2561
|
-
* - It won't be included in document snapshots
|
|
2562
|
-
*
|
|
2563
|
-
* Only works on root containers (containers without parents).
|
|
2530
|
+
* Evaluate JSONPath against a LoroDoc
|
|
2564
2531
|
*/
|
|
2565
|
-
|
|
2532
|
+
JSONPath(jsonpath: string): Array<any>;
|
|
2566
2533
|
/**
|
|
2567
|
-
*
|
|
2534
|
+
* Revert the document to the given frontiers.
|
|
2535
|
+
*
|
|
2536
|
+
* The doc will not become detached when using this method. Instead, it will generate a series
|
|
2537
|
+
* of operations to revert the document to the given version.
|
|
2568
2538
|
*
|
|
2569
2539
|
* @example
|
|
2570
2540
|
* ```ts
|
|
2571
2541
|
* const doc = new LoroDoc();
|
|
2572
|
-
*
|
|
2573
|
-
*
|
|
2574
|
-
*
|
|
2575
|
-
*
|
|
2542
|
+
* doc.setPeerId("1");
|
|
2543
|
+
* const text = doc.getText("text");
|
|
2544
|
+
* text.insert(0, "Hello");
|
|
2545
|
+
* doc.commit();
|
|
2546
|
+
* doc.revertTo([{ peer: "1", counter: 1 }]);
|
|
2547
|
+
* expect(doc.getText("text").toString()).toBe("He");
|
|
2576
2548
|
* ```
|
|
2577
2549
|
*/
|
|
2578
|
-
|
|
2579
|
-
/**
|
|
2580
|
-
* Peer ID of the current writer.
|
|
2581
|
-
*/
|
|
2582
|
-
readonly peerId: bigint;
|
|
2550
|
+
revertTo(frontiers: ({ peer: PeerID, counter: number })[]): void;
|
|
2583
2551
|
/**
|
|
2584
2552
|
* Get peer id in decimal string.
|
|
2585
2553
|
*/
|
|
2586
2554
|
readonly peerIdStr: PeerID;
|
|
2555
|
+
/**
|
|
2556
|
+
* Peer ID of the current writer.
|
|
2557
|
+
*/
|
|
2558
|
+
readonly peerId: bigint;
|
|
2587
2559
|
}
|
|
2588
2560
|
/**
|
|
2589
2561
|
* The handler of a list container.
|
|
@@ -2592,6 +2564,37 @@ export class LoroDoc {
|
|
|
2592
2564
|
*/
|
|
2593
2565
|
export class LoroList {
|
|
2594
2566
|
free(): void;
|
|
2567
|
+
/**
|
|
2568
|
+
* Whether the container is attached to a document.
|
|
2569
|
+
*
|
|
2570
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
2571
|
+
*/
|
|
2572
|
+
isAttached(): boolean;
|
|
2573
|
+
/**
|
|
2574
|
+
* Get the attached container associated with this.
|
|
2575
|
+
*
|
|
2576
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2577
|
+
*/
|
|
2578
|
+
getAttached(): LoroList | undefined;
|
|
2579
|
+
/**
|
|
2580
|
+
* Get the shallow value of the list.
|
|
2581
|
+
*
|
|
2582
|
+
* Unlike `toJSON()` which recursively resolves all containers to their values,
|
|
2583
|
+
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
2584
|
+
*
|
|
2585
|
+
* ```js
|
|
2586
|
+
* const doc = new LoroDoc();
|
|
2587
|
+
* doc.setPeerId("1");
|
|
2588
|
+
* const list = doc.getList("list");
|
|
2589
|
+
* list.insert(0, 1);
|
|
2590
|
+
* list.insert(1, "two");
|
|
2591
|
+
* const subList = list.insertContainer(2, new LoroList());
|
|
2592
|
+
* subList.insert(0, "sub");
|
|
2593
|
+
* list.getShallowValue(); // [1, "two", "cid:2@1:List"]
|
|
2594
|
+
* list.toJSON(); // [1, "two", ["sub"]]
|
|
2595
|
+
* ```
|
|
2596
|
+
*/
|
|
2597
|
+
getShallowValue(): Value[];
|
|
2595
2598
|
/**
|
|
2596
2599
|
* Create a new detached LoroList (not attached to any LoroDoc).
|
|
2597
2600
|
*
|
|
@@ -2599,10 +2602,18 @@ export class LoroList {
|
|
|
2599
2602
|
* To attach the container to the document, please insert it into an attached container.
|
|
2600
2603
|
*/
|
|
2601
2604
|
constructor();
|
|
2605
|
+
/**
|
|
2606
|
+
* Pop a value from the end of the list.
|
|
2607
|
+
*/
|
|
2608
|
+
pop(): Value | undefined;
|
|
2602
2609
|
/**
|
|
2603
2610
|
* "List"
|
|
2604
2611
|
*/
|
|
2605
2612
|
kind(): 'List';
|
|
2613
|
+
/**
|
|
2614
|
+
* Delete all elements in the list.
|
|
2615
|
+
*/
|
|
2616
|
+
clear(): void;
|
|
2606
2617
|
/**
|
|
2607
2618
|
* Delete elements from index to index + len.
|
|
2608
2619
|
*
|
|
@@ -2618,6 +2629,15 @@ export class LoroList {
|
|
|
2618
2629
|
* ```
|
|
2619
2630
|
*/
|
|
2620
2631
|
delete(index: number, len: number): void;
|
|
2632
|
+
/**
|
|
2633
|
+
* Get the parent container.
|
|
2634
|
+
*
|
|
2635
|
+
* - The parent container of the root tree is `undefined`.
|
|
2636
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2637
|
+
* the WASM boundary.
|
|
2638
|
+
*/
|
|
2639
|
+
parent(): Container | undefined;
|
|
2640
|
+
getIdAt(pos: number): { peer: PeerID, counter: number } | undefined;
|
|
2621
2641
|
/**
|
|
2622
2642
|
* Get elements of the list. If the type of a element is a container, it will be
|
|
2623
2643
|
* resolved recursively.
|
|
@@ -2635,58 +2655,10 @@ export class LoroList {
|
|
|
2635
2655
|
* ```
|
|
2636
2656
|
*/
|
|
2637
2657
|
toJSON(): any;
|
|
2638
|
-
/**
|
|
2639
|
-
* Get the parent container.
|
|
2640
|
-
*
|
|
2641
|
-
* - The parent container of the root tree is `undefined`.
|
|
2642
|
-
* - The object returned is a new js object each time because it need to cross
|
|
2643
|
-
* the WASM boundary.
|
|
2644
|
-
*/
|
|
2645
|
-
parent(): Container | undefined;
|
|
2646
|
-
/**
|
|
2647
|
-
* Whether the container is attached to a document.
|
|
2648
|
-
*
|
|
2649
|
-
* If it's detached, the operations on the container will not be persisted.
|
|
2650
|
-
*/
|
|
2651
|
-
isAttached(): boolean;
|
|
2652
|
-
/**
|
|
2653
|
-
* Get the attached container associated with this.
|
|
2654
|
-
*
|
|
2655
|
-
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2656
|
-
*/
|
|
2657
|
-
getAttached(): LoroList | undefined;
|
|
2658
|
-
/**
|
|
2659
|
-
* Pop a value from the end of the list.
|
|
2660
|
-
*/
|
|
2661
|
-
pop(): Value | undefined;
|
|
2662
|
-
/**
|
|
2663
|
-
* Delete all elements in the list.
|
|
2664
|
-
*/
|
|
2665
|
-
clear(): void;
|
|
2666
|
-
getIdAt(pos: number): { peer: PeerID, counter: number } | undefined;
|
|
2667
2658
|
/**
|
|
2668
2659
|
* Check if the container is deleted
|
|
2669
2660
|
*/
|
|
2670
2661
|
isDeleted(): boolean;
|
|
2671
|
-
/**
|
|
2672
|
-
* Get the shallow value of the list.
|
|
2673
|
-
*
|
|
2674
|
-
* Unlike `toJSON()` which recursively resolves all containers to their values,
|
|
2675
|
-
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
2676
|
-
*
|
|
2677
|
-
* ```js
|
|
2678
|
-
* const doc = new LoroDoc();
|
|
2679
|
-
* doc.setPeerId("1");
|
|
2680
|
-
* const list = doc.getList("list");
|
|
2681
|
-
* list.insert(0, 1);
|
|
2682
|
-
* list.insert(1, "two");
|
|
2683
|
-
* const subList = list.insertContainer(2, new LoroList());
|
|
2684
|
-
* subList.insert(0, "sub");
|
|
2685
|
-
* list.getShallowValue(); // [1, "two", "cid:2@1:List"]
|
|
2686
|
-
* list.toJSON(); // [1, "two", ["sub"]]
|
|
2687
|
-
* ```
|
|
2688
|
-
*/
|
|
2689
|
-
getShallowValue(): Value[];
|
|
2690
2662
|
/**
|
|
2691
2663
|
* Get the id of this container.
|
|
2692
2664
|
*/
|
|
@@ -2716,30 +2688,55 @@ export class LoroList {
|
|
|
2716
2688
|
export class LoroMap {
|
|
2717
2689
|
free(): void;
|
|
2718
2690
|
/**
|
|
2719
|
-
*
|
|
2691
|
+
* Whether the container is attached to a document.
|
|
2720
2692
|
*
|
|
2721
|
-
*
|
|
2722
|
-
* To attach the container to the document, please insert it into an attached container.
|
|
2693
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
2723
2694
|
*/
|
|
2724
|
-
|
|
2695
|
+
isAttached(): boolean;
|
|
2725
2696
|
/**
|
|
2726
|
-
*
|
|
2697
|
+
* Get the attached container associated with this.
|
|
2698
|
+
*
|
|
2699
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2727
2700
|
*/
|
|
2728
|
-
|
|
2701
|
+
getAttached(): LoroMap | undefined;
|
|
2729
2702
|
/**
|
|
2730
|
-
*
|
|
2703
|
+
* Get the peer id of the last editor on the given entry
|
|
2704
|
+
*/
|
|
2705
|
+
getLastEditor(key: string): PeerID | undefined;
|
|
2706
|
+
/**
|
|
2707
|
+
* Get the shallow value of the map.
|
|
2708
|
+
*
|
|
2709
|
+
* Unlike `toJSON()` which recursively resolves all containers to their values,
|
|
2710
|
+
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
2731
2711
|
*
|
|
2732
2712
|
* @example
|
|
2733
2713
|
* ```ts
|
|
2734
|
-
* import { LoroDoc } from "loro-crdt";
|
|
2714
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
2735
2715
|
*
|
|
2736
2716
|
* const doc = new LoroDoc();
|
|
2717
|
+
* doc.setPeerId("1");
|
|
2737
2718
|
* const map = doc.getMap("map");
|
|
2738
|
-
* map.set("
|
|
2739
|
-
* map.
|
|
2719
|
+
* map.set("key", "value");
|
|
2720
|
+
* const subText = map.setContainer("text", new LoroText());
|
|
2721
|
+
* subText.insert(0, "Hello");
|
|
2722
|
+
*
|
|
2723
|
+
* // Get shallow value - nested containers are represented by their IDs
|
|
2724
|
+
* console.log(map.getShallowValue());
|
|
2725
|
+
* // Output: { key: "value", text: "cid:1@1:Text" }
|
|
2726
|
+
*
|
|
2727
|
+
* // Get full value with nested containers resolved by `toJSON()`
|
|
2728
|
+
* console.log(map.toJSON());
|
|
2729
|
+
* // Output: { key: "value", text: "Hello" }
|
|
2740
2730
|
* ```
|
|
2741
2731
|
*/
|
|
2742
|
-
|
|
2732
|
+
getShallowValue(): Record<string, Value>;
|
|
2733
|
+
/**
|
|
2734
|
+
* Create a new detached LoroMap (not attached to any LoroDoc).
|
|
2735
|
+
*
|
|
2736
|
+
* The edits on a detached container will not be persisted.
|
|
2737
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
2738
|
+
*/
|
|
2739
|
+
constructor();
|
|
2743
2740
|
/**
|
|
2744
2741
|
* Get the keys of the map.
|
|
2745
2742
|
*
|
|
@@ -2755,6 +2752,36 @@ export class LoroMap {
|
|
|
2755
2752
|
* ```
|
|
2756
2753
|
*/
|
|
2757
2754
|
keys(): any[];
|
|
2755
|
+
/**
|
|
2756
|
+
* "Map"
|
|
2757
|
+
*/
|
|
2758
|
+
kind(): 'Map';
|
|
2759
|
+
/**
|
|
2760
|
+
* Delete all key-value pairs in the map.
|
|
2761
|
+
*/
|
|
2762
|
+
clear(): void;
|
|
2763
|
+
/**
|
|
2764
|
+
* Remove the key from the map.
|
|
2765
|
+
*
|
|
2766
|
+
* @example
|
|
2767
|
+
* ```ts
|
|
2768
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2769
|
+
*
|
|
2770
|
+
* const doc = new LoroDoc();
|
|
2771
|
+
* const map = doc.getMap("map");
|
|
2772
|
+
* map.set("foo", "bar");
|
|
2773
|
+
* map.delete("foo");
|
|
2774
|
+
* ```
|
|
2775
|
+
*/
|
|
2776
|
+
delete(key: string): void;
|
|
2777
|
+
/**
|
|
2778
|
+
* Get the parent container.
|
|
2779
|
+
*
|
|
2780
|
+
* - The parent container of the root tree is `undefined`.
|
|
2781
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2782
|
+
* the WASM boundary.
|
|
2783
|
+
*/
|
|
2784
|
+
parent(): Container | undefined;
|
|
2758
2785
|
/**
|
|
2759
2786
|
* Get the values of the map. If the value is a child container, the corresponding
|
|
2760
2787
|
* `Container` will be returned.
|
|
@@ -2804,65 +2831,10 @@ export class LoroMap {
|
|
|
2804
2831
|
* ```
|
|
2805
2832
|
*/
|
|
2806
2833
|
toJSON(): any;
|
|
2807
|
-
/**
|
|
2808
|
-
* Get the parent container.
|
|
2809
|
-
*
|
|
2810
|
-
* - The parent container of the root tree is `undefined`.
|
|
2811
|
-
* - The object returned is a new js object each time because it need to cross
|
|
2812
|
-
* the WASM boundary.
|
|
2813
|
-
*/
|
|
2814
|
-
parent(): Container | undefined;
|
|
2815
|
-
/**
|
|
2816
|
-
* Whether the container is attached to a document.
|
|
2817
|
-
*
|
|
2818
|
-
* If it's detached, the operations on the container will not be persisted.
|
|
2819
|
-
*/
|
|
2820
|
-
isAttached(): boolean;
|
|
2821
|
-
/**
|
|
2822
|
-
* Get the attached container associated with this.
|
|
2823
|
-
*
|
|
2824
|
-
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2825
|
-
*/
|
|
2826
|
-
getAttached(): LoroMap | undefined;
|
|
2827
|
-
/**
|
|
2828
|
-
* Delete all key-value pairs in the map.
|
|
2829
|
-
*/
|
|
2830
|
-
clear(): void;
|
|
2831
|
-
/**
|
|
2832
|
-
* Get the peer id of the last editor on the given entry
|
|
2833
|
-
*/
|
|
2834
|
-
getLastEditor(key: string): PeerID | undefined;
|
|
2835
2834
|
/**
|
|
2836
2835
|
* Check if the container is deleted
|
|
2837
2836
|
*/
|
|
2838
|
-
isDeleted(): boolean;
|
|
2839
|
-
/**
|
|
2840
|
-
* Get the shallow value of the map.
|
|
2841
|
-
*
|
|
2842
|
-
* Unlike `toJSON()` which recursively resolves all containers to their values,
|
|
2843
|
-
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
2844
|
-
*
|
|
2845
|
-
* @example
|
|
2846
|
-
* ```ts
|
|
2847
|
-
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
2848
|
-
*
|
|
2849
|
-
* const doc = new LoroDoc();
|
|
2850
|
-
* doc.setPeerId("1");
|
|
2851
|
-
* const map = doc.getMap("map");
|
|
2852
|
-
* map.set("key", "value");
|
|
2853
|
-
* const subText = map.setContainer("text", new LoroText());
|
|
2854
|
-
* subText.insert(0, "Hello");
|
|
2855
|
-
*
|
|
2856
|
-
* // Get shallow value - nested containers are represented by their IDs
|
|
2857
|
-
* console.log(map.getShallowValue());
|
|
2858
|
-
* // Output: { key: "value", text: "cid:1@1:Text" }
|
|
2859
|
-
*
|
|
2860
|
-
* // Get full value with nested containers resolved by `toJSON()`
|
|
2861
|
-
* console.log(map.toJSON());
|
|
2862
|
-
* // Output: { key: "value", text: "Hello" }
|
|
2863
|
-
* ```
|
|
2864
|
-
*/
|
|
2865
|
-
getShallowValue(): Record<string, Value>;
|
|
2837
|
+
isDeleted(): boolean;
|
|
2866
2838
|
/**
|
|
2867
2839
|
* The container id of this handler.
|
|
2868
2840
|
*/
|
|
@@ -2890,68 +2862,48 @@ export class LoroMap {
|
|
|
2890
2862
|
export class LoroMovableList {
|
|
2891
2863
|
free(): void;
|
|
2892
2864
|
/**
|
|
2893
|
-
*
|
|
2865
|
+
* Whether the container is attached to a document.
|
|
2894
2866
|
*
|
|
2895
|
-
*
|
|
2896
|
-
* To attach the container to the document, please insert it into an attached container.
|
|
2867
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
2897
2868
|
*/
|
|
2898
|
-
|
|
2869
|
+
isAttached(): boolean;
|
|
2899
2870
|
/**
|
|
2900
|
-
*
|
|
2871
|
+
* Get the creator of the list item at the given position.
|
|
2901
2872
|
*/
|
|
2902
|
-
|
|
2873
|
+
getCreatorAt(pos: number): PeerID | undefined;
|
|
2903
2874
|
/**
|
|
2904
|
-
*
|
|
2905
|
-
*
|
|
2906
|
-
* @example
|
|
2907
|
-
* ```ts
|
|
2908
|
-
* import { LoroDoc } from "loro-crdt";
|
|
2875
|
+
* Get the attached container associated with this.
|
|
2909
2876
|
*
|
|
2910
|
-
*
|
|
2911
|
-
* const list = doc.getList("list");
|
|
2912
|
-
* list.insert(0, 100);
|
|
2913
|
-
* list.delete(0, 1);
|
|
2914
|
-
* console.log(list.value); // []
|
|
2915
|
-
* ```
|
|
2877
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2916
2878
|
*/
|
|
2917
|
-
|
|
2879
|
+
getAttached(): LoroList | undefined;
|
|
2918
2880
|
/**
|
|
2919
|
-
* Get
|
|
2920
|
-
* resolved recursively.
|
|
2921
|
-
*
|
|
2922
|
-
* @example
|
|
2923
|
-
* ```ts
|
|
2924
|
-
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
2925
|
-
*
|
|
2926
|
-
* const doc = new LoroDoc();
|
|
2927
|
-
* const list = doc.getList("list");
|
|
2928
|
-
* list.insert(0, 100);
|
|
2929
|
-
* const text = list.insertContainer(1, new LoroText());
|
|
2930
|
-
* text.insert(0, "Hello");
|
|
2931
|
-
* console.log(list.toJSON()); // [100, "Hello"];
|
|
2932
|
-
* ```
|
|
2881
|
+
* Get the last mover of the list item at the given position.
|
|
2933
2882
|
*/
|
|
2934
|
-
|
|
2883
|
+
getLastMoverAt(pos: number): PeerID | undefined;
|
|
2935
2884
|
/**
|
|
2936
|
-
* Get the
|
|
2937
|
-
*
|
|
2938
|
-
* - The parent container of the root tree is `undefined`.
|
|
2939
|
-
* - The object returned is a new js object each time because it need to cross
|
|
2940
|
-
* the WASM boundary.
|
|
2885
|
+
* Get the last editor of the list item at the given position.
|
|
2941
2886
|
*/
|
|
2942
|
-
|
|
2887
|
+
getLastEditorAt(pos: number): PeerID | undefined;
|
|
2943
2888
|
/**
|
|
2944
|
-
*
|
|
2889
|
+
* Get the shallow value of the movable list.
|
|
2945
2890
|
*
|
|
2946
|
-
*
|
|
2947
|
-
|
|
2948
|
-
isAttached(): boolean;
|
|
2949
|
-
/**
|
|
2950
|
-
* Get the attached container associated with this.
|
|
2891
|
+
* Unlike `toJSON()` which recursively resolves all containers to their values,
|
|
2892
|
+
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
2951
2893
|
*
|
|
2952
|
-
*
|
|
2894
|
+
* ```js
|
|
2895
|
+
* const doc = new LoroDoc();
|
|
2896
|
+
* doc.setPeerId("1");
|
|
2897
|
+
* const list = doc.getMovableList("list");
|
|
2898
|
+
* list.insert(0, 1);
|
|
2899
|
+
* list.insert(1, "two");
|
|
2900
|
+
* const subList = list.insertContainer(2, new LoroList());
|
|
2901
|
+
* subList.insert(0, "sub");
|
|
2902
|
+
* list.getShallowValue(); // [1, "two", "cid:2@1:List"]
|
|
2903
|
+
* list.toJSON(); // [1, "two", ["sub"]]
|
|
2904
|
+
* ```
|
|
2953
2905
|
*/
|
|
2954
|
-
|
|
2906
|
+
getShallowValue(): Value[];
|
|
2955
2907
|
/**
|
|
2956
2908
|
* Move the element from `from` to `to`.
|
|
2957
2909
|
*
|
|
@@ -2966,48 +2918,68 @@ export class LoroMovableList {
|
|
|
2966
2918
|
*/
|
|
2967
2919
|
move(from: number, to: number): void;
|
|
2968
2920
|
/**
|
|
2969
|
-
*
|
|
2921
|
+
* Create a new detached LoroMovableList (not attached to any LoroDoc).
|
|
2922
|
+
*
|
|
2923
|
+
* The edits on a detached container will not be persisted.
|
|
2924
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
2970
2925
|
*/
|
|
2971
|
-
|
|
2926
|
+
constructor();
|
|
2972
2927
|
/**
|
|
2973
|
-
*
|
|
2928
|
+
* Pop a value from the end of the list.
|
|
2974
2929
|
*/
|
|
2975
|
-
|
|
2930
|
+
pop(): Value | undefined;
|
|
2976
2931
|
/**
|
|
2977
|
-
*
|
|
2932
|
+
* "MovableList"
|
|
2978
2933
|
*/
|
|
2979
|
-
|
|
2934
|
+
kind(): 'MovableList';
|
|
2980
2935
|
/**
|
|
2981
|
-
*
|
|
2936
|
+
* Delete all elements in the list.
|
|
2982
2937
|
*/
|
|
2983
|
-
|
|
2938
|
+
clear(): void;
|
|
2984
2939
|
/**
|
|
2985
|
-
*
|
|
2940
|
+
* Delete elements from index to index + len.
|
|
2941
|
+
*
|
|
2942
|
+
* @example
|
|
2943
|
+
* ```ts
|
|
2944
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2945
|
+
*
|
|
2946
|
+
* const doc = new LoroDoc();
|
|
2947
|
+
* const list = doc.getList("list");
|
|
2948
|
+
* list.insert(0, 100);
|
|
2949
|
+
* list.delete(0, 1);
|
|
2950
|
+
* console.log(list.value); // []
|
|
2951
|
+
* ```
|
|
2986
2952
|
*/
|
|
2987
|
-
|
|
2953
|
+
delete(index: number, len: number): void;
|
|
2988
2954
|
/**
|
|
2989
|
-
*
|
|
2955
|
+
* Get the parent container.
|
|
2956
|
+
*
|
|
2957
|
+
* - The parent container of the root tree is `undefined`.
|
|
2958
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2959
|
+
* the WASM boundary.
|
|
2990
2960
|
*/
|
|
2991
|
-
|
|
2961
|
+
parent(): Container | undefined;
|
|
2992
2962
|
/**
|
|
2993
|
-
* Get the
|
|
2963
|
+
* Get elements of the list. If the type of a element is a container, it will be
|
|
2964
|
+
* resolved recursively.
|
|
2994
2965
|
*
|
|
2995
|
-
*
|
|
2996
|
-
*
|
|
2966
|
+
* @example
|
|
2967
|
+
* ```ts
|
|
2968
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
2997
2969
|
*
|
|
2998
|
-
* ```js
|
|
2999
2970
|
* const doc = new LoroDoc();
|
|
3000
|
-
* doc.
|
|
3001
|
-
*
|
|
3002
|
-
* list.
|
|
3003
|
-
*
|
|
3004
|
-
*
|
|
3005
|
-
* subList.insert(0, "sub");
|
|
3006
|
-
* list.getShallowValue(); // [1, "two", "cid:2@1:List"]
|
|
3007
|
-
* list.toJSON(); // [1, "two", ["sub"]]
|
|
2971
|
+
* const list = doc.getList("list");
|
|
2972
|
+
* list.insert(0, 100);
|
|
2973
|
+
* const text = list.insertContainer(1, new LoroText());
|
|
2974
|
+
* text.insert(0, "Hello");
|
|
2975
|
+
* console.log(list.toJSON()); // [100, "Hello"];
|
|
3008
2976
|
* ```
|
|
3009
2977
|
*/
|
|
3010
|
-
|
|
2978
|
+
toJSON(): any;
|
|
2979
|
+
/**
|
|
2980
|
+
* Check if the container is deleted
|
|
2981
|
+
*/
|
|
2982
|
+
isDeleted(): boolean;
|
|
3011
2983
|
/**
|
|
3012
2984
|
* Get the id of this container.
|
|
3013
2985
|
*/
|
|
@@ -3037,38 +3009,34 @@ export class LoroMovableList {
|
|
|
3037
3009
|
export class LoroText {
|
|
3038
3010
|
free(): void;
|
|
3039
3011
|
/**
|
|
3040
|
-
*
|
|
3041
|
-
*
|
|
3042
|
-
* The edits on a detached container will not be persisted.
|
|
3043
|
-
* To attach the container to the document, please insert it into an attached container.
|
|
3044
|
-
*/
|
|
3045
|
-
constructor();
|
|
3046
|
-
/**
|
|
3047
|
-
* "Text"
|
|
3048
|
-
*/
|
|
3049
|
-
kind(): 'Text';
|
|
3050
|
-
/**
|
|
3051
|
-
* Iterate each text span(internal storage unit)
|
|
3012
|
+
* Change the state of this text by delta.
|
|
3052
3013
|
*
|
|
3053
|
-
*
|
|
3054
|
-
*
|
|
3014
|
+
* If a delta item is `insert`, it should include all the attributes of the inserted text.
|
|
3015
|
+
* Loro's rich text CRDT may make the inserted text inherit some styles when you use
|
|
3016
|
+
* `insert` method directly. However, when you use `applyDelta` if some attributes are
|
|
3017
|
+
* inherited from CRDT but not included in the delta, they will be removed.
|
|
3055
3018
|
*
|
|
3056
|
-
*
|
|
3057
|
-
*
|
|
3019
|
+
* Another special property of `applyDelta` is if you format an attribute for ranges out of
|
|
3020
|
+
* the text length, Loro will insert new lines to fill the gap first. It's useful when you
|
|
3021
|
+
* build the binding between Loro and rich text editors like Quill, which might assume there
|
|
3022
|
+
* is always a newline at the end of the text implicitly.
|
|
3058
3023
|
*
|
|
3059
3024
|
* @example
|
|
3060
3025
|
* ```ts
|
|
3061
|
-
* import { LoroDoc } from "loro-crdt";
|
|
3062
|
-
*
|
|
3063
3026
|
* const doc = new LoroDoc();
|
|
3064
3027
|
* const text = doc.getText("text");
|
|
3065
|
-
*
|
|
3066
|
-
* text.
|
|
3028
|
+
* doc.configTextStyle({bold: {expand: "after"}});
|
|
3029
|
+
* text.insert(0, "Hello World!");
|
|
3030
|
+
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
3031
|
+
* const delta = text.toDelta();
|
|
3032
|
+
* const text2 = doc.getText("text2");
|
|
3033
|
+
* text2.applyDelta(delta);
|
|
3034
|
+
* expect(text2.toDelta()).toStrictEqual(delta);
|
|
3067
3035
|
* ```
|
|
3068
3036
|
*/
|
|
3069
|
-
|
|
3037
|
+
applyDelta(delta: Delta<string>[]): void;
|
|
3070
3038
|
/**
|
|
3071
|
-
*
|
|
3039
|
+
* Delete elements from index to utf-8 index + len
|
|
3072
3040
|
*
|
|
3073
3041
|
* @example
|
|
3074
3042
|
* ```ts
|
|
@@ -3076,12 +3044,19 @@ export class LoroText {
|
|
|
3076
3044
|
*
|
|
3077
3045
|
* const doc = new LoroDoc();
|
|
3078
3046
|
* const text = doc.getText("text");
|
|
3079
|
-
* text.
|
|
3047
|
+
* text.insertUtf8(0, "Hello");
|
|
3048
|
+
* text.deleteUtf8(1, 3);
|
|
3049
|
+
* const s = text.toString();
|
|
3050
|
+
* console.log(s); // "Ho"
|
|
3080
3051
|
* ```
|
|
3081
3052
|
*/
|
|
3082
|
-
|
|
3053
|
+
deleteUtf8(index: number, len: number): void;
|
|
3083
3054
|
/**
|
|
3084
|
-
* Get
|
|
3055
|
+
* Get the editor of the text at the given position.
|
|
3056
|
+
*/
|
|
3057
|
+
getEditorOf(pos: number): PeerID | undefined;
|
|
3058
|
+
/**
|
|
3059
|
+
* Insert some string at utf-8 index.
|
|
3085
3060
|
*
|
|
3086
3061
|
* @example
|
|
3087
3062
|
* ```ts
|
|
@@ -3089,13 +3064,49 @@ export class LoroText {
|
|
|
3089
3064
|
*
|
|
3090
3065
|
* const doc = new LoroDoc();
|
|
3091
3066
|
* const text = doc.getText("text");
|
|
3092
|
-
* text.
|
|
3093
|
-
* text.slice(0, 2); // "He"
|
|
3067
|
+
* text.insertUtf8(0, "Hello");
|
|
3094
3068
|
* ```
|
|
3095
3069
|
*/
|
|
3096
|
-
|
|
3070
|
+
insertUtf8(index: number, content: string): void;
|
|
3097
3071
|
/**
|
|
3098
|
-
*
|
|
3072
|
+
* Whether the container is attached to a LoroDoc.
|
|
3073
|
+
*
|
|
3074
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
3075
|
+
*/
|
|
3076
|
+
isAttached(): boolean;
|
|
3077
|
+
/**
|
|
3078
|
+
* Get the rich text delta in the given range (utf-16 index).
|
|
3079
|
+
*/
|
|
3080
|
+
sliceDelta(start: number, end: number): Delta<string>[];
|
|
3081
|
+
/**
|
|
3082
|
+
* Get the attached container associated with this.
|
|
3083
|
+
*
|
|
3084
|
+
* Returns an attached `Container` that is equal to this or created by this; otherwise, it returns `undefined`.
|
|
3085
|
+
*/
|
|
3086
|
+
getAttached(): LoroText | undefined;
|
|
3087
|
+
/**
|
|
3088
|
+
* Get the rich text delta in the given range (utf-8 index).
|
|
3089
|
+
*/
|
|
3090
|
+
sliceDeltaUtf8(start: number, end: number): Delta<string>[];
|
|
3091
|
+
/**
|
|
3092
|
+
* Get the shallow value of the text. This equals to `text.toString()`.
|
|
3093
|
+
*/
|
|
3094
|
+
getShallowValue(): string;
|
|
3095
|
+
/**
|
|
3096
|
+
* Create a new detached LoroText (not attached to any LoroDoc).
|
|
3097
|
+
*
|
|
3098
|
+
* The edits on a detached container will not be persisted.
|
|
3099
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
3100
|
+
*/
|
|
3101
|
+
constructor();
|
|
3102
|
+
/**
|
|
3103
|
+
* Iterate each text span(internal storage unit)
|
|
3104
|
+
*
|
|
3105
|
+
* The callback function will be called for each span in the text.
|
|
3106
|
+
* If the callback returns `false`, the iteration will stop.
|
|
3107
|
+
*
|
|
3108
|
+
* Limitation: you cannot access or alter the doc state when iterating (this is for performance consideration).
|
|
3109
|
+
* If you need to access or alter the doc state, please use `toString` instead.
|
|
3099
3110
|
*
|
|
3100
3111
|
* @example
|
|
3101
3112
|
* ```ts
|
|
@@ -3104,26 +3115,39 @@ export class LoroText {
|
|
|
3104
3115
|
* const doc = new LoroDoc();
|
|
3105
3116
|
* const text = doc.getText("text");
|
|
3106
3117
|
* text.insert(0, "Hello");
|
|
3107
|
-
* text.
|
|
3118
|
+
* text.iter((str) => (console.log(str), true));
|
|
3108
3119
|
* ```
|
|
3109
3120
|
*/
|
|
3110
|
-
|
|
3121
|
+
iter(callback: (string) => boolean): void;
|
|
3111
3122
|
/**
|
|
3112
|
-
*
|
|
3123
|
+
* "Text"
|
|
3124
|
+
*/
|
|
3125
|
+
kind(): 'Text';
|
|
3126
|
+
/**
|
|
3127
|
+
* Mark a range of text with a key and a value (utf-16 index).
|
|
3128
|
+
*
|
|
3129
|
+
* > You should call `configTextStyle` before using `mark` and `unmark`.
|
|
3130
|
+
*
|
|
3131
|
+
* You can use it to create a highlight, make a range of text bold, or add a link to a range of text.
|
|
3113
3132
|
*
|
|
3114
3133
|
* @example
|
|
3115
3134
|
* ```ts
|
|
3116
3135
|
* import { LoroDoc } from "loro-crdt";
|
|
3117
3136
|
*
|
|
3118
3137
|
* const doc = new LoroDoc();
|
|
3138
|
+
* doc.configTextStyle({bold: {expand: "after"}});
|
|
3119
3139
|
* const text = doc.getText("text");
|
|
3120
|
-
* text.insert(0, "Hello");
|
|
3121
|
-
* text.
|
|
3140
|
+
* text.insert(0, "Hello World!");
|
|
3141
|
+
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
3122
3142
|
* ```
|
|
3123
3143
|
*/
|
|
3124
|
-
|
|
3144
|
+
mark(range: { start: number, end: number }, key: string, value: any): void;
|
|
3125
3145
|
/**
|
|
3126
|
-
*
|
|
3146
|
+
* Push a string to the end of the text.
|
|
3147
|
+
*/
|
|
3148
|
+
push(s: string): void;
|
|
3149
|
+
/**
|
|
3150
|
+
* Get a string slice (utf-16 index).
|
|
3127
3151
|
*
|
|
3128
3152
|
* @example
|
|
3129
3153
|
* ```ts
|
|
@@ -3131,10 +3155,11 @@ export class LoroText {
|
|
|
3131
3155
|
*
|
|
3132
3156
|
* const doc = new LoroDoc();
|
|
3133
3157
|
* const text = doc.getText("text");
|
|
3134
|
-
* text.
|
|
3158
|
+
* text.insert(0, "Hello");
|
|
3159
|
+
* text.slice(0, 2); // "He"
|
|
3135
3160
|
* ```
|
|
3136
3161
|
*/
|
|
3137
|
-
|
|
3162
|
+
slice(start_index: number, end_index: number): string;
|
|
3138
3163
|
/**
|
|
3139
3164
|
* Delete elements from index to index + len (utf-16 index).
|
|
3140
3165
|
*
|
|
@@ -3152,7 +3177,7 @@ export class LoroText {
|
|
|
3152
3177
|
*/
|
|
3153
3178
|
delete(index: number, len: number): void;
|
|
3154
3179
|
/**
|
|
3155
|
-
*
|
|
3180
|
+
* Insert the string at the given index (utf-16 index).
|
|
3156
3181
|
*
|
|
3157
3182
|
* @example
|
|
3158
3183
|
* ```ts
|
|
@@ -3160,32 +3185,32 @@ export class LoroText {
|
|
|
3160
3185
|
*
|
|
3161
3186
|
* const doc = new LoroDoc();
|
|
3162
3187
|
* const text = doc.getText("text");
|
|
3163
|
-
* text.
|
|
3164
|
-
* text.deleteUtf8(1, 3);
|
|
3165
|
-
* const s = text.toString();
|
|
3166
|
-
* console.log(s); // "Ho"
|
|
3188
|
+
* text.insert(0, "Hello");
|
|
3167
3189
|
* ```
|
|
3168
3190
|
*/
|
|
3169
|
-
|
|
3191
|
+
insert(index: number, content: string): void;
|
|
3170
3192
|
/**
|
|
3171
|
-
*
|
|
3172
|
-
*
|
|
3173
|
-
* > You should call `configTextStyle` before using `mark` and `unmark`.
|
|
3193
|
+
* Get the parent container.
|
|
3174
3194
|
*
|
|
3175
|
-
*
|
|
3195
|
+
* - The parent of the root is `undefined`.
|
|
3196
|
+
* - The object returned is a new js object each time because it need to cross
|
|
3197
|
+
* the WASM boundary.
|
|
3198
|
+
*/
|
|
3199
|
+
parent(): Container | undefined;
|
|
3200
|
+
/**
|
|
3201
|
+
* Delete and return the string at the given range and insert a string at the same position (utf-16 index).
|
|
3176
3202
|
*
|
|
3177
3203
|
* @example
|
|
3178
3204
|
* ```ts
|
|
3179
3205
|
* import { LoroDoc } from "loro-crdt";
|
|
3180
3206
|
*
|
|
3181
3207
|
* const doc = new LoroDoc();
|
|
3182
|
-
* doc.configTextStyle({bold: {expand: "after"}});
|
|
3183
3208
|
* const text = doc.getText("text");
|
|
3184
|
-
* text.insert(0, "Hello
|
|
3185
|
-
* text.
|
|
3209
|
+
* text.insert(0, "Hello");
|
|
3210
|
+
* text.splice(2, 3, "llo"); // "llo"
|
|
3186
3211
|
* ```
|
|
3187
3212
|
*/
|
|
3188
|
-
|
|
3213
|
+
splice(pos: number, len: number, s: string): string;
|
|
3189
3214
|
/**
|
|
3190
3215
|
* Unmark a range of text with a key and a value (utf-16 index).
|
|
3191
3216
|
*
|
|
@@ -3207,13 +3232,7 @@ export class LoroText {
|
|
|
3207
3232
|
*/
|
|
3208
3233
|
unmark(range: { start: number, end: number }, key: string): void;
|
|
3209
3234
|
/**
|
|
3210
|
-
*
|
|
3211
|
-
*/
|
|
3212
|
-
toString(): string;
|
|
3213
|
-
/**
|
|
3214
|
-
* Get the text in [Delta](https://quilljs.com/docs/delta/) format.
|
|
3215
|
-
*
|
|
3216
|
-
* The returned value will include the rich text information.
|
|
3235
|
+
* Get the character at the given position (utf-16 index).
|
|
3217
3236
|
*
|
|
3218
3237
|
* @example
|
|
3219
3238
|
* ```ts
|
|
@@ -3221,80 +3240,41 @@ export class LoroText {
|
|
|
3221
3240
|
*
|
|
3222
3241
|
* const doc = new LoroDoc();
|
|
3223
3242
|
* const text = doc.getText("text");
|
|
3224
|
-
*
|
|
3225
|
-
* text.
|
|
3226
|
-
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
3227
|
-
* console.log(text.toDelta()); // [ { insert: 'Hello', attributes: { bold: true } } ]
|
|
3243
|
+
* text.insert(0, "Hello");
|
|
3244
|
+
* text.charAt(0); // "H"
|
|
3228
3245
|
* ```
|
|
3229
3246
|
*/
|
|
3230
|
-
|
|
3247
|
+
charAt(pos: number): string;
|
|
3231
3248
|
/**
|
|
3232
|
-
*
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
*
|
|
3237
|
-
* inherited from CRDT but not included in the delta, they will be removed.
|
|
3249
|
+
* Get the JSON representation of the text.
|
|
3250
|
+
*/
|
|
3251
|
+
toJSON(): any;
|
|
3252
|
+
/**
|
|
3253
|
+
* Get the text in [Delta](https://quilljs.com/docs/delta/) format.
|
|
3238
3254
|
*
|
|
3239
|
-
*
|
|
3240
|
-
* the text length, Loro will insert new lines to fill the gap first. It's useful when you
|
|
3241
|
-
* build the binding between Loro and rich text editors like Quill, which might assume there
|
|
3242
|
-
* is always a newline at the end of the text implicitly.
|
|
3255
|
+
* The returned value will include the rich text information.
|
|
3243
3256
|
*
|
|
3244
3257
|
* @example
|
|
3245
3258
|
* ```ts
|
|
3259
|
+
* import { LoroDoc } from "loro-crdt";
|
|
3260
|
+
*
|
|
3246
3261
|
* const doc = new LoroDoc();
|
|
3247
3262
|
* const text = doc.getText("text");
|
|
3248
3263
|
* doc.configTextStyle({bold: {expand: "after"}});
|
|
3249
3264
|
* text.insert(0, "Hello World!");
|
|
3250
3265
|
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
3251
|
-
*
|
|
3252
|
-
* const text2 = doc.getText("text2");
|
|
3253
|
-
* text2.applyDelta(delta);
|
|
3254
|
-
* expect(text2.toDelta()).toStrictEqual(delta);
|
|
3266
|
+
* console.log(text.toDelta()); // [ { insert: 'Hello', attributes: { bold: true } } ]
|
|
3255
3267
|
* ```
|
|
3256
3268
|
*/
|
|
3257
|
-
|
|
3258
|
-
/**
|
|
3259
|
-
* Get the parent container.
|
|
3260
|
-
*
|
|
3261
|
-
* - The parent of the root is `undefined`.
|
|
3262
|
-
* - The object returned is a new js object each time because it need to cross
|
|
3263
|
-
* the WASM boundary.
|
|
3264
|
-
*/
|
|
3265
|
-
parent(): Container | undefined;
|
|
3266
|
-
/**
|
|
3267
|
-
* Whether the container is attached to a LoroDoc.
|
|
3268
|
-
*
|
|
3269
|
-
* If it's detached, the operations on the container will not be persisted.
|
|
3270
|
-
*/
|
|
3271
|
-
isAttached(): boolean;
|
|
3272
|
-
/**
|
|
3273
|
-
* Get the attached container associated with this.
|
|
3274
|
-
*
|
|
3275
|
-
* Returns an attached `Container` that is equal to this or created by this; otherwise, it returns `undefined`.
|
|
3276
|
-
*/
|
|
3277
|
-
getAttached(): LoroText | undefined;
|
|
3278
|
-
/**
|
|
3279
|
-
* Push a string to the end of the text.
|
|
3280
|
-
*/
|
|
3281
|
-
push(s: string): void;
|
|
3282
|
-
/**
|
|
3283
|
-
* Get the editor of the text at the given position.
|
|
3284
|
-
*/
|
|
3285
|
-
getEditorOf(pos: number): PeerID | undefined;
|
|
3269
|
+
toDelta(): Delta<string>[];
|
|
3286
3270
|
/**
|
|
3287
3271
|
* Check if the container is deleted
|
|
3288
3272
|
*/
|
|
3289
3273
|
isDeleted(): boolean;
|
|
3290
3274
|
/**
|
|
3291
|
-
*
|
|
3292
|
-
*/
|
|
3293
|
-
getShallowValue(): string;
|
|
3294
|
-
/**
|
|
3295
|
-
* Get the JSON representation of the text.
|
|
3275
|
+
* Convert the text to a string
|
|
3296
3276
|
*/
|
|
3297
|
-
|
|
3277
|
+
toString(): string;
|
|
3298
3278
|
/**
|
|
3299
3279
|
* Get the container id of the text.
|
|
3300
3280
|
*/
|
|
@@ -3312,61 +3292,90 @@ export class LoroText {
|
|
|
3312
3292
|
export class LoroTree {
|
|
3313
3293
|
free(): void;
|
|
3314
3294
|
/**
|
|
3315
|
-
*
|
|
3295
|
+
* Whether the container is attached to a document.
|
|
3316
3296
|
*
|
|
3317
|
-
*
|
|
3318
|
-
* To attach the container to the document, please insert it into an attached container.
|
|
3297
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
3319
3298
|
*/
|
|
3320
|
-
|
|
3299
|
+
isAttached(): boolean;
|
|
3321
3300
|
/**
|
|
3322
|
-
*
|
|
3301
|
+
* Get the attached container associated with this.
|
|
3302
|
+
*
|
|
3303
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
3323
3304
|
*/
|
|
3324
|
-
|
|
3305
|
+
getAttached(): LoroTree | undefined;
|
|
3325
3306
|
/**
|
|
3326
|
-
*
|
|
3327
|
-
|
|
3328
|
-
|
|
3307
|
+
* Return `None` if the node is not exist, otherwise return `Some(true)` if the node is deleted.
|
|
3308
|
+
*/
|
|
3309
|
+
isNodeDeleted(target: TreeID): boolean;
|
|
3310
|
+
/**
|
|
3311
|
+
* Get the shallow value of the tree.
|
|
3312
|
+
*
|
|
3313
|
+
* Unlike `toJSON()` which recursively resolves nested containers to their values,
|
|
3314
|
+
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
3329
3315
|
*
|
|
3330
3316
|
* @example
|
|
3331
3317
|
* ```ts
|
|
3332
|
-
* import { LoroDoc } from "loro-crdt";
|
|
3333
|
-
*
|
|
3334
3318
|
* const doc = new LoroDoc();
|
|
3319
|
+
* doc.setPeerId("1");
|
|
3335
3320
|
* const tree = doc.getTree("tree");
|
|
3336
3321
|
* const root = tree.createNode();
|
|
3337
|
-
*
|
|
3338
|
-
* const
|
|
3339
|
-
*
|
|
3340
|
-
*
|
|
3341
|
-
*
|
|
3322
|
+
* root.data.set("name", "root");
|
|
3323
|
+
* const text = root.data.setContainer("content", new LoroText());
|
|
3324
|
+
* text.insert(0, "Hello");
|
|
3325
|
+
*
|
|
3326
|
+
* console.log(tree.getShallowValue());
|
|
3327
|
+
* // [{
|
|
3328
|
+
* // id: "0@1",
|
|
3329
|
+
* // parent: null,
|
|
3330
|
+
* // index: 0,
|
|
3331
|
+
* // fractional_index: "80",
|
|
3332
|
+
* // meta: "cid:0@1:Map",
|
|
3333
|
+
* // children: []
|
|
3334
|
+
* // }]
|
|
3335
|
+
*
|
|
3336
|
+
* console.log(tree.toJSON());
|
|
3337
|
+
* // [{
|
|
3338
|
+
* // id: "0@1",
|
|
3339
|
+
* // parent: null,
|
|
3340
|
+
* // index: 0,
|
|
3341
|
+
* // fractional_index: "80",
|
|
3342
|
+
* // meta: {
|
|
3343
|
+
* // name: "root",
|
|
3344
|
+
* // content: "Hello"
|
|
3345
|
+
* // },
|
|
3346
|
+
* // children: []
|
|
3347
|
+
* // }]
|
|
3342
3348
|
* ```
|
|
3343
3349
|
*/
|
|
3344
|
-
|
|
3350
|
+
getShallowValue(): TreeNodeShallowValue[];
|
|
3345
3351
|
/**
|
|
3346
|
-
*
|
|
3352
|
+
* Set whether to generate a fractional index for moving and creating.
|
|
3347
3353
|
*
|
|
3348
|
-
*
|
|
3349
|
-
* ```ts
|
|
3350
|
-
* import { LoroDoc } from "loro-crdt";
|
|
3354
|
+
* A fractional index can be used to determine the position of tree nodes among their siblings.
|
|
3351
3355
|
*
|
|
3352
|
-
*
|
|
3353
|
-
*
|
|
3354
|
-
*
|
|
3355
|
-
*
|
|
3356
|
-
*
|
|
3357
|
-
* ```
|
|
3356
|
+
* The jitter is used to avoid conflicts when multiple users are creating a node at the same position.
|
|
3357
|
+
* A value of 0 is the default, which means no jitter; any value larger than 0 will enable jitter.
|
|
3358
|
+
*
|
|
3359
|
+
* Generally speaking, higher jitter value will increase the size of the operation
|
|
3360
|
+
* [Read more about it](https://www.loro.dev/blog/movable-tree#implementation-and-encoding-size)
|
|
3358
3361
|
*/
|
|
3359
|
-
|
|
3362
|
+
enableFractionalIndex(jitter: number): void;
|
|
3360
3363
|
/**
|
|
3361
|
-
*
|
|
3364
|
+
* Disable the fractional index generation when you don't need the Tree's siblings to be sorted.
|
|
3365
|
+
* The fractional index will always be set to the same default value 0.
|
|
3366
|
+
*
|
|
3367
|
+
* After calling this, you cannot use `tree.moveTo()`, `tree.moveBefore()`, `tree.moveAfter()`,
|
|
3368
|
+
* and `tree.createAt()`.
|
|
3362
3369
|
*/
|
|
3363
|
-
|
|
3370
|
+
disableFractionalIndex(): void;
|
|
3364
3371
|
/**
|
|
3365
|
-
*
|
|
3372
|
+
* Whether the tree enables the fractional index generation.
|
|
3366
3373
|
*/
|
|
3367
|
-
|
|
3374
|
+
isFractionalIndexEnabled(): boolean;
|
|
3368
3375
|
/**
|
|
3369
|
-
*
|
|
3376
|
+
* Move the target tree node to be a child of the parent.
|
|
3377
|
+
* It's not allowed that the target is an ancestor of the parent
|
|
3378
|
+
* or the target and the parent are the same node.
|
|
3370
3379
|
*
|
|
3371
3380
|
* @example
|
|
3372
3381
|
* ```ts
|
|
@@ -3375,12 +3384,25 @@ export class LoroTree {
|
|
|
3375
3384
|
* const doc = new LoroDoc();
|
|
3376
3385
|
* const tree = doc.getTree("tree");
|
|
3377
3386
|
* const root = tree.createNode();
|
|
3378
|
-
* root.
|
|
3379
|
-
*
|
|
3380
|
-
*
|
|
3387
|
+
* const node = root.createNode();
|
|
3388
|
+
* const node2 = node.createNode();
|
|
3389
|
+
* tree.move(node2.id, root.id);
|
|
3390
|
+
* // Error will be thrown if move operation creates a cycle
|
|
3391
|
+
* // tree.move(root.id, node.id);
|
|
3381
3392
|
* ```
|
|
3382
3393
|
*/
|
|
3383
|
-
|
|
3394
|
+
move(target: TreeID, parent: TreeID | undefined, index?: number | null): void;
|
|
3395
|
+
/**
|
|
3396
|
+
* Create a new detached LoroTree (not attached to any LoroDoc).
|
|
3397
|
+
*
|
|
3398
|
+
* The edits on a detached container will not be persisted.
|
|
3399
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
3400
|
+
*/
|
|
3401
|
+
constructor();
|
|
3402
|
+
/**
|
|
3403
|
+
* "Tree"
|
|
3404
|
+
*/
|
|
3405
|
+
kind(): 'Tree';
|
|
3384
3406
|
/**
|
|
3385
3407
|
* Get all tree nodes of the forest, including deleted nodes.
|
|
3386
3408
|
*
|
|
@@ -3393,103 +3415,61 @@ export class LoroTree {
|
|
|
3393
3415
|
* const root = tree.createNode();
|
|
3394
3416
|
* const node = root.createNode();
|
|
3395
3417
|
* const node2 = node.createNode();
|
|
3396
|
-
* console.log(tree.nodes());
|
|
3397
|
-
* ```
|
|
3398
|
-
*/
|
|
3399
|
-
nodes(): LoroTreeNode[];
|
|
3400
|
-
/**
|
|
3401
|
-
* Get the root nodes of the forest.
|
|
3402
|
-
*/
|
|
3403
|
-
roots(): LoroTreeNode[];
|
|
3404
|
-
/**
|
|
3405
|
-
* Get the parent container of the tree container.
|
|
3406
|
-
*
|
|
3407
|
-
* - The parent container of the root tree is `undefined`.
|
|
3408
|
-
* - The object returned is a new js object each time because it need to cross
|
|
3409
|
-
* the WASM boundary.
|
|
3410
|
-
*/
|
|
3411
|
-
parent(): Container | undefined;
|
|
3412
|
-
/**
|
|
3413
|
-
* Whether the container is attached to a document.
|
|
3414
|
-
*
|
|
3415
|
-
* If it's detached, the operations on the container will not be persisted.
|
|
3418
|
+
* console.log(tree.nodes());
|
|
3419
|
+
* ```
|
|
3416
3420
|
*/
|
|
3417
|
-
|
|
3421
|
+
nodes(): LoroTreeNode[];
|
|
3418
3422
|
/**
|
|
3419
|
-
* Get the
|
|
3420
|
-
*
|
|
3421
|
-
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
3423
|
+
* Get the root nodes of the forest.
|
|
3422
3424
|
*/
|
|
3423
|
-
|
|
3425
|
+
roots(): LoroTreeNode[];
|
|
3424
3426
|
/**
|
|
3425
|
-
*
|
|
3426
|
-
*
|
|
3427
|
-
* A fractional index can be used to determine the position of tree nodes among their siblings.
|
|
3427
|
+
* Delete a tree node from the forest.
|
|
3428
3428
|
*
|
|
3429
|
-
*
|
|
3430
|
-
*
|
|
3429
|
+
* @example
|
|
3430
|
+
* ```ts
|
|
3431
|
+
* import { LoroDoc } from "loro-crdt";
|
|
3431
3432
|
*
|
|
3432
|
-
*
|
|
3433
|
-
*
|
|
3433
|
+
* const doc = new LoroDoc();
|
|
3434
|
+
* const tree = doc.getTree("tree");
|
|
3435
|
+
* const root = tree.createNode();
|
|
3436
|
+
* const node = root.createNode();
|
|
3437
|
+
* tree.delete(node.id);
|
|
3438
|
+
* ```
|
|
3434
3439
|
*/
|
|
3435
|
-
|
|
3440
|
+
delete(target: TreeID): void;
|
|
3436
3441
|
/**
|
|
3437
|
-
*
|
|
3438
|
-
* The fractional index will always be set to the same default value 0.
|
|
3442
|
+
* Get the parent container of the tree container.
|
|
3439
3443
|
*
|
|
3440
|
-
*
|
|
3441
|
-
*
|
|
3442
|
-
|
|
3443
|
-
disableFractionalIndex(): void;
|
|
3444
|
-
/**
|
|
3445
|
-
* Whether the tree enables the fractional index generation.
|
|
3446
|
-
*/
|
|
3447
|
-
isFractionalIndexEnabled(): boolean;
|
|
3448
|
-
/**
|
|
3449
|
-
* Check if the container is deleted
|
|
3444
|
+
* - The parent container of the root tree is `undefined`.
|
|
3445
|
+
* - The object returned is a new js object each time because it need to cross
|
|
3446
|
+
* the WASM boundary.
|
|
3450
3447
|
*/
|
|
3451
|
-
|
|
3448
|
+
parent(): Container | undefined;
|
|
3452
3449
|
/**
|
|
3453
|
-
* Get the
|
|
3454
|
-
*
|
|
3455
|
-
* Unlike `toJSON()` which recursively resolves nested containers to their values,
|
|
3456
|
-
* `getShallowValue()` returns container IDs as strings for any nested containers.
|
|
3450
|
+
* Get the hierarchy array with metadata of the forest.
|
|
3457
3451
|
*
|
|
3458
3452
|
* @example
|
|
3459
3453
|
* ```ts
|
|
3454
|
+
* import { LoroDoc } from "loro-crdt";
|
|
3455
|
+
*
|
|
3460
3456
|
* const doc = new LoroDoc();
|
|
3461
|
-
* doc.setPeerId("1");
|
|
3462
3457
|
* const tree = doc.getTree("tree");
|
|
3463
3458
|
* const root = tree.createNode();
|
|
3464
|
-
* root.data.set("
|
|
3465
|
-
*
|
|
3466
|
-
* text.insert(0, "Hello");
|
|
3467
|
-
*
|
|
3468
|
-
* console.log(tree.getShallowValue());
|
|
3469
|
-
* // [{
|
|
3470
|
-
* // id: "0@1",
|
|
3471
|
-
* // parent: null,
|
|
3472
|
-
* // index: 0,
|
|
3473
|
-
* // fractional_index: "80",
|
|
3474
|
-
* // meta: "cid:0@1:Map",
|
|
3475
|
-
* // children: []
|
|
3476
|
-
* // }]
|
|
3477
|
-
*
|
|
3459
|
+
* root.data.set("color", "red");
|
|
3460
|
+
* // [ { id: '0@F2462C4159C4C8D1', parent: null, meta: { color: 'red' }, children: [] } ]
|
|
3478
3461
|
* console.log(tree.toJSON());
|
|
3479
|
-
* // [{
|
|
3480
|
-
* // id: "0@1",
|
|
3481
|
-
* // parent: null,
|
|
3482
|
-
* // index: 0,
|
|
3483
|
-
* // fractional_index: "80",
|
|
3484
|
-
* // meta: {
|
|
3485
|
-
* // name: "root",
|
|
3486
|
-
* // content: "Hello"
|
|
3487
|
-
* // },
|
|
3488
|
-
* // children: []
|
|
3489
|
-
* // }]
|
|
3490
3462
|
* ```
|
|
3491
3463
|
*/
|
|
3492
|
-
|
|
3464
|
+
toJSON(): any;
|
|
3465
|
+
/**
|
|
3466
|
+
* Return `true` if the tree contains the TreeID, include deleted node.
|
|
3467
|
+
*/
|
|
3468
|
+
has(target: TreeID): boolean;
|
|
3469
|
+
/**
|
|
3470
|
+
* Check if the container is deleted
|
|
3471
|
+
*/
|
|
3472
|
+
isDeleted(): boolean;
|
|
3493
3473
|
/**
|
|
3494
3474
|
* Get the id of the container.
|
|
3495
3475
|
*/
|
|
@@ -3501,26 +3481,14 @@ export class LoroTree {
|
|
|
3501
3481
|
export class LoroTreeNode {
|
|
3502
3482
|
private constructor();
|
|
3503
3483
|
free(): void;
|
|
3504
|
-
__getClassname(): string;
|
|
3505
3484
|
/**
|
|
3506
|
-
*
|
|
3507
|
-
*
|
|
3508
|
-
* @example
|
|
3509
|
-
* ```ts
|
|
3510
|
-
* import { LoroDoc } from "loro-crdt";
|
|
3511
|
-
*
|
|
3512
|
-
* const doc = new LoroDoc();
|
|
3513
|
-
* const tree = doc.getTree("tree");
|
|
3514
|
-
* const root = tree.createNode();
|
|
3515
|
-
* const node = root.createNode();
|
|
3516
|
-
* const node2 = root.createNode();
|
|
3517
|
-
* node2.moveAfter(node);
|
|
3518
|
-
* // root
|
|
3519
|
-
* // / \
|
|
3520
|
-
* // node node2
|
|
3521
|
-
* ```
|
|
3485
|
+
* Get the creation id of this node.
|
|
3522
3486
|
*/
|
|
3523
|
-
|
|
3487
|
+
creationId(): { peer: PeerID, counter: number };
|
|
3488
|
+
/**
|
|
3489
|
+
* Check if the node is deleted.
|
|
3490
|
+
*/
|
|
3491
|
+
isDeleted(): boolean;
|
|
3524
3492
|
/**
|
|
3525
3493
|
* Move the tree node to be before the target node.
|
|
3526
3494
|
*
|
|
@@ -3541,31 +3509,43 @@ export class LoroTreeNode {
|
|
|
3541
3509
|
*/
|
|
3542
3510
|
moveBefore(target: LoroTreeNode): void;
|
|
3543
3511
|
/**
|
|
3544
|
-
* Get the
|
|
3512
|
+
* Get the last mover of this node.
|
|
3545
3513
|
*/
|
|
3546
|
-
|
|
3514
|
+
getLastMoveId(): { peer: PeerID, counter: number } | undefined;
|
|
3547
3515
|
/**
|
|
3548
3516
|
* Get the `Fractional Index` of the node.
|
|
3549
3517
|
*
|
|
3550
3518
|
* Note: the tree container must be attached to the document.
|
|
3551
3519
|
*/
|
|
3552
3520
|
fractionalIndex(): string | undefined;
|
|
3521
|
+
__getClassname(): string;
|
|
3553
3522
|
/**
|
|
3554
|
-
*
|
|
3555
|
-
*/
|
|
3556
|
-
isDeleted(): boolean;
|
|
3557
|
-
/**
|
|
3558
|
-
* Get the last mover of this node.
|
|
3559
|
-
*/
|
|
3560
|
-
getLastMoveId(): { peer: PeerID, counter: number } | undefined;
|
|
3561
|
-
/**
|
|
3562
|
-
* Get the creation id of this node.
|
|
3523
|
+
* Get the index of the node in the parent's children.
|
|
3563
3524
|
*/
|
|
3564
|
-
|
|
3525
|
+
index(): number | undefined;
|
|
3565
3526
|
/**
|
|
3566
3527
|
* Get the creator of this node.
|
|
3567
3528
|
*/
|
|
3568
3529
|
creator(): PeerID;
|
|
3530
|
+
/**
|
|
3531
|
+
* Move the tree node to be after the target node.
|
|
3532
|
+
*
|
|
3533
|
+
* @example
|
|
3534
|
+
* ```ts
|
|
3535
|
+
* import { LoroDoc } from "loro-crdt";
|
|
3536
|
+
*
|
|
3537
|
+
* const doc = new LoroDoc();
|
|
3538
|
+
* const tree = doc.getTree("tree");
|
|
3539
|
+
* const root = tree.createNode();
|
|
3540
|
+
* const node = root.createNode();
|
|
3541
|
+
* const node2 = root.createNode();
|
|
3542
|
+
* node2.moveAfter(node);
|
|
3543
|
+
* // root
|
|
3544
|
+
* // / \
|
|
3545
|
+
* // node node2
|
|
3546
|
+
* ```
|
|
3547
|
+
*/
|
|
3548
|
+
moveAfter(target: LoroTreeNode): void;
|
|
3569
3549
|
/**
|
|
3570
3550
|
* The TreeID of the node.
|
|
3571
3551
|
*/
|
|
@@ -3587,6 +3567,33 @@ export class LoroTreeNode {
|
|
|
3587
3567
|
*/
|
|
3588
3568
|
export class UndoManager {
|
|
3589
3569
|
free(): void;
|
|
3570
|
+
/**
|
|
3571
|
+
* Get the value associated with the top redo stack item, if any.
|
|
3572
|
+
* Returns `undefined` if there is no redo item.
|
|
3573
|
+
*/
|
|
3574
|
+
topRedoValue(): Value | undefined;
|
|
3575
|
+
/**
|
|
3576
|
+
* Get the value associated with the top undo stack item, if any.
|
|
3577
|
+
* Returns `undefined` if there is no undo item.
|
|
3578
|
+
*/
|
|
3579
|
+
topUndoValue(): Value | undefined;
|
|
3580
|
+
/**
|
|
3581
|
+
* The number of max undo steps.
|
|
3582
|
+
* If the number of undo steps exceeds this number, the oldest undo step will be removed.
|
|
3583
|
+
*/
|
|
3584
|
+
setMaxUndoSteps(steps: number): void;
|
|
3585
|
+
/**
|
|
3586
|
+
* Set the merge interval (in ms).
|
|
3587
|
+
*
|
|
3588
|
+
* If the interval is set to 0, the undo steps will not be merged.
|
|
3589
|
+
* Otherwise, the undo steps will be merged if the interval between the two steps is less than the given interval.
|
|
3590
|
+
*/
|
|
3591
|
+
setMergeInterval(interval: number): void;
|
|
3592
|
+
/**
|
|
3593
|
+
* If a local event's origin matches the given prefix, it will not be recorded in the
|
|
3594
|
+
* undo stack.
|
|
3595
|
+
*/
|
|
3596
|
+
addExcludeOriginPrefix(prefix: string): void;
|
|
3590
3597
|
/**
|
|
3591
3598
|
* `UndoManager` is responsible for handling undo and redo operations.
|
|
3592
3599
|
*
|
|
@@ -3611,53 +3618,26 @@ export class UndoManager {
|
|
|
3611
3618
|
*/
|
|
3612
3619
|
constructor(doc: LoroDoc, config: UndoConfig);
|
|
3613
3620
|
/**
|
|
3614
|
-
*
|
|
3621
|
+
* Get the peer id of the undo manager.
|
|
3615
3622
|
*/
|
|
3616
|
-
|
|
3623
|
+
peer(): PeerID;
|
|
3617
3624
|
/**
|
|
3618
3625
|
* Redo the last undone operation.
|
|
3619
3626
|
*/
|
|
3620
3627
|
redo(): boolean;
|
|
3621
3628
|
/**
|
|
3622
|
-
*
|
|
3623
|
-
*/
|
|
3624
|
-
peer(): PeerID;
|
|
3625
|
-
/**
|
|
3626
|
-
* Can undo the last operation.
|
|
3629
|
+
* Undo the last operation.
|
|
3627
3630
|
*/
|
|
3628
|
-
|
|
3631
|
+
undo(): boolean;
|
|
3632
|
+
clear(): void;
|
|
3629
3633
|
/**
|
|
3630
3634
|
* Can redo the last operation.
|
|
3631
3635
|
*/
|
|
3632
3636
|
canRedo(): boolean;
|
|
3633
3637
|
/**
|
|
3634
|
-
*
|
|
3635
|
-
* Returns `undefined` if there is no undo item.
|
|
3636
|
-
*/
|
|
3637
|
-
topUndoValue(): Value | undefined;
|
|
3638
|
-
/**
|
|
3639
|
-
* Get the value associated with the top redo stack item, if any.
|
|
3640
|
-
* Returns `undefined` if there is no redo item.
|
|
3641
|
-
*/
|
|
3642
|
-
topRedoValue(): Value | undefined;
|
|
3643
|
-
/**
|
|
3644
|
-
* The number of max undo steps.
|
|
3645
|
-
* If the number of undo steps exceeds this number, the oldest undo step will be removed.
|
|
3646
|
-
*/
|
|
3647
|
-
setMaxUndoSteps(steps: number): void;
|
|
3648
|
-
/**
|
|
3649
|
-
* Set the merge interval (in ms).
|
|
3650
|
-
*
|
|
3651
|
-
* If the interval is set to 0, the undo steps will not be merged.
|
|
3652
|
-
* Otherwise, the undo steps will be merged if the interval between the two steps is less than the given interval.
|
|
3653
|
-
*/
|
|
3654
|
-
setMergeInterval(interval: number): void;
|
|
3655
|
-
/**
|
|
3656
|
-
* If a local event's origin matches the given prefix, it will not be recorded in the
|
|
3657
|
-
* undo stack.
|
|
3638
|
+
* Can undo the last operation.
|
|
3658
3639
|
*/
|
|
3659
|
-
|
|
3660
|
-
clear(): void;
|
|
3640
|
+
canUndo(): boolean;
|
|
3661
3641
|
}
|
|
3662
3642
|
/**
|
|
3663
3643
|
* [VersionVector](https://en.wikipedia.org/wiki/Version_vector)
|
|
@@ -3669,43 +3649,43 @@ export class UndoManager {
|
|
|
3669
3649
|
export class VersionVector {
|
|
3670
3650
|
free(): void;
|
|
3671
3651
|
/**
|
|
3672
|
-
*
|
|
3652
|
+
* Get the counter of a peer.
|
|
3673
3653
|
*/
|
|
3674
|
-
|
|
3654
|
+
get(peer_id: number | bigint | `${number}`): number | undefined;
|
|
3675
3655
|
/**
|
|
3676
|
-
* Create a new version vector
|
|
3656
|
+
* Create a new version vector.
|
|
3677
3657
|
*/
|
|
3678
|
-
|
|
3658
|
+
constructor(value: Map<PeerID, number> | Uint8Array | VersionVector | undefined | null);
|
|
3679
3659
|
/**
|
|
3680
|
-
*
|
|
3660
|
+
* Decode the version vector from a Uint8Array.
|
|
3681
3661
|
*/
|
|
3682
|
-
|
|
3662
|
+
static decode(bytes: Uint8Array): VersionVector;
|
|
3683
3663
|
/**
|
|
3684
3664
|
* Encode the version vector into a Uint8Array.
|
|
3685
3665
|
*/
|
|
3686
3666
|
encode(): Uint8Array;
|
|
3667
|
+
length(): number;
|
|
3668
|
+
remove(peer: PeerID): void;
|
|
3687
3669
|
/**
|
|
3688
|
-
*
|
|
3689
|
-
*/
|
|
3690
|
-
static decode(bytes: Uint8Array): VersionVector;
|
|
3691
|
-
/**
|
|
3692
|
-
* Get the counter of a peer.
|
|
3670
|
+
* set the exclusive ending point. target id will NOT be included by self
|
|
3693
3671
|
*/
|
|
3694
|
-
|
|
3672
|
+
setEnd(id: { peer: PeerID, counter: number }): void;
|
|
3695
3673
|
/**
|
|
3696
3674
|
* Compare the version vector with another version vector.
|
|
3697
3675
|
*
|
|
3698
3676
|
* If they are concurrent, return undefined.
|
|
3699
3677
|
*/
|
|
3700
3678
|
compare(other: VersionVector): number | undefined;
|
|
3701
|
-
/**
|
|
3702
|
-
* set the exclusive ending point. target id will NOT be included by self
|
|
3703
|
-
*/
|
|
3704
|
-
setEnd(id: { peer: PeerID, counter: number }): void;
|
|
3705
3679
|
/**
|
|
3706
3680
|
* set the inclusive ending point. target id will be included
|
|
3707
3681
|
*/
|
|
3708
3682
|
setLast(id: { peer: PeerID, counter: number }): void;
|
|
3709
|
-
|
|
3710
|
-
|
|
3683
|
+
/**
|
|
3684
|
+
* Convert the version vector to a Map
|
|
3685
|
+
*/
|
|
3686
|
+
toJSON(): Map<PeerID, number>;
|
|
3687
|
+
/**
|
|
3688
|
+
* Create a new version vector from a Map.
|
|
3689
|
+
*/
|
|
3690
|
+
static parseJSON(version: Map<PeerID, number>): VersionVector;
|
|
3711
3691
|
}
|