@liveblocks/core 3.19.5-rc1 → 3.20.0-exp2
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/dist/index.cjs +794 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +122 -10
- package/dist/index.d.ts +122 -10
- package/dist/index.js +724 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// src/version.ts
|
|
8
8
|
var PKG_NAME = "@liveblocks/core";
|
|
9
|
-
var PKG_VERSION = "3.
|
|
9
|
+
var PKG_VERSION = "3.20.0-exp2";
|
|
10
10
|
var PKG_FORMAT = "esm";
|
|
11
11
|
|
|
12
12
|
// src/dupe-detection.ts
|
|
@@ -5511,7 +5511,9 @@ var OpCode = Object.freeze({
|
|
|
5511
5511
|
DELETE_CRDT: 5,
|
|
5512
5512
|
DELETE_OBJECT_KEY: 6,
|
|
5513
5513
|
CREATE_MAP: 7,
|
|
5514
|
-
CREATE_REGISTER: 8
|
|
5514
|
+
CREATE_REGISTER: 8,
|
|
5515
|
+
CREATE_TEXT: 9,
|
|
5516
|
+
UPDATE_TEXT: 10
|
|
5515
5517
|
});
|
|
5516
5518
|
function isIgnoredOp(op) {
|
|
5517
5519
|
return op.type === OpCode.DELETE_CRDT && op.id === "ACK";
|
|
@@ -5525,7 +5527,8 @@ var CrdtType = Object.freeze({
|
|
|
5525
5527
|
OBJECT: 0,
|
|
5526
5528
|
LIST: 1,
|
|
5527
5529
|
MAP: 2,
|
|
5528
|
-
REGISTER: 3
|
|
5530
|
+
REGISTER: 3,
|
|
5531
|
+
TEXT: 4
|
|
5529
5532
|
});
|
|
5530
5533
|
function isRootStorageNode(node) {
|
|
5531
5534
|
return node[0] === "root";
|
|
@@ -5542,6 +5545,9 @@ function isMapStorageNode(node) {
|
|
|
5542
5545
|
function isRegisterStorageNode(node) {
|
|
5543
5546
|
return node[1].type === CrdtType.REGISTER;
|
|
5544
5547
|
}
|
|
5548
|
+
function isTextStorageNode(node) {
|
|
5549
|
+
return node[1].type === CrdtType.TEXT;
|
|
5550
|
+
}
|
|
5545
5551
|
function isCompactRootNode(node) {
|
|
5546
5552
|
return node[0] === "root";
|
|
5547
5553
|
}
|
|
@@ -5564,6 +5570,9 @@ function* compactNodesToNodeStream(compactNodes) {
|
|
|
5564
5570
|
case CrdtType.REGISTER:
|
|
5565
5571
|
yield [cnode[0], { type: CrdtType.REGISTER, parentId: cnode[2], parentKey: cnode[3], data: cnode[4] }];
|
|
5566
5572
|
break;
|
|
5573
|
+
case CrdtType.TEXT:
|
|
5574
|
+
yield [cnode[0], { type: CrdtType.TEXT, parentId: cnode[2], parentKey: cnode[3], data: cnode[4], version: cnode[5] }];
|
|
5575
|
+
break;
|
|
5567
5576
|
default:
|
|
5568
5577
|
}
|
|
5569
5578
|
}
|
|
@@ -5592,6 +5601,17 @@ function* nodeStreamToCompactNodes(nodes) {
|
|
|
5592
5601
|
const id = node[0];
|
|
5593
5602
|
const crdt = node[1];
|
|
5594
5603
|
yield [id, CrdtType.REGISTER, crdt.parentId, crdt.parentKey, crdt.data];
|
|
5604
|
+
} else if (isTextStorageNode(node)) {
|
|
5605
|
+
const id = node[0];
|
|
5606
|
+
const crdt = node[1];
|
|
5607
|
+
yield [
|
|
5608
|
+
id,
|
|
5609
|
+
CrdtType.TEXT,
|
|
5610
|
+
crdt.parentId,
|
|
5611
|
+
crdt.parentKey,
|
|
5612
|
+
crdt.data,
|
|
5613
|
+
crdt.version
|
|
5614
|
+
];
|
|
5595
5615
|
} else {
|
|
5596
5616
|
}
|
|
5597
5617
|
}
|
|
@@ -7928,6 +7948,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
7928
7948
|
const id = nn(this._id);
|
|
7929
7949
|
const parentKey = nn(child._parentKey);
|
|
7930
7950
|
const reverse = child._toOps(id, parentKey);
|
|
7951
|
+
const deletedItem = liveNodeToLson(child);
|
|
7931
7952
|
for (const [key, value] of this.#synced) {
|
|
7932
7953
|
if (value === child) {
|
|
7933
7954
|
this.#synced.delete(key);
|
|
@@ -7939,7 +7960,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
7939
7960
|
node: this,
|
|
7940
7961
|
type: "LiveObject",
|
|
7941
7962
|
updates: {
|
|
7942
|
-
[parentKey]: { type: "delete" }
|
|
7963
|
+
[parentKey]: { type: "delete", deletedItem }
|
|
7943
7964
|
}
|
|
7944
7965
|
};
|
|
7945
7966
|
return { modified: storageUpdate, reverse };
|
|
@@ -8426,6 +8447,583 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8426
8447
|
}
|
|
8427
8448
|
};
|
|
8428
8449
|
|
|
8450
|
+
// src/crdts/liveTextOps.ts
|
|
8451
|
+
function attributesEqual(left, right) {
|
|
8452
|
+
if (left === right) {
|
|
8453
|
+
return true;
|
|
8454
|
+
}
|
|
8455
|
+
if (left === void 0 || right === void 0) {
|
|
8456
|
+
return false;
|
|
8457
|
+
}
|
|
8458
|
+
const leftKeys = Object.keys(left);
|
|
8459
|
+
const rightKeys = Object.keys(right);
|
|
8460
|
+
if (leftKeys.length !== rightKeys.length) {
|
|
8461
|
+
return false;
|
|
8462
|
+
}
|
|
8463
|
+
for (const key of leftKeys) {
|
|
8464
|
+
if (left[key] !== right[key]) {
|
|
8465
|
+
return false;
|
|
8466
|
+
}
|
|
8467
|
+
}
|
|
8468
|
+
return true;
|
|
8469
|
+
}
|
|
8470
|
+
function cloneAttributes(attributes) {
|
|
8471
|
+
return attributes === void 0 ? void 0 : freeze({ ...attributes });
|
|
8472
|
+
}
|
|
8473
|
+
function normalizeSegments(segments) {
|
|
8474
|
+
const normalized = [];
|
|
8475
|
+
for (const segment of segments) {
|
|
8476
|
+
if (segment.text.length === 0) {
|
|
8477
|
+
continue;
|
|
8478
|
+
}
|
|
8479
|
+
const last = normalized.at(-1);
|
|
8480
|
+
const attributes = cloneAttributes(segment.attributes);
|
|
8481
|
+
if (last !== void 0 && attributesEqual(last.attributes, attributes)) {
|
|
8482
|
+
last.text += segment.text;
|
|
8483
|
+
} else {
|
|
8484
|
+
normalized.push({ text: segment.text, attributes });
|
|
8485
|
+
}
|
|
8486
|
+
}
|
|
8487
|
+
return normalized;
|
|
8488
|
+
}
|
|
8489
|
+
function deltaToSegments(delta) {
|
|
8490
|
+
return normalizeSegments(
|
|
8491
|
+
delta.map((item) => ({
|
|
8492
|
+
text: item.text,
|
|
8493
|
+
attributes: item.attributes
|
|
8494
|
+
}))
|
|
8495
|
+
);
|
|
8496
|
+
}
|
|
8497
|
+
function segmentsToDelta(segments) {
|
|
8498
|
+
return segments.map(
|
|
8499
|
+
(segment) => segment.attributes === void 0 ? { text: segment.text } : { text: segment.text, attributes: { ...segment.attributes } }
|
|
8500
|
+
);
|
|
8501
|
+
}
|
|
8502
|
+
function textLength(segments) {
|
|
8503
|
+
return segments.reduce((sum, segment) => sum + segment.text.length, 0);
|
|
8504
|
+
}
|
|
8505
|
+
function splitSegmentsAt(segments, index) {
|
|
8506
|
+
const result = [];
|
|
8507
|
+
let offset = 0;
|
|
8508
|
+
for (const segment of segments) {
|
|
8509
|
+
const end = offset + segment.text.length;
|
|
8510
|
+
if (index > offset && index < end) {
|
|
8511
|
+
const before2 = segment.text.slice(0, index - offset);
|
|
8512
|
+
const after2 = segment.text.slice(index - offset);
|
|
8513
|
+
result.push({ text: before2, attributes: segment.attributes });
|
|
8514
|
+
result.push({ text: after2, attributes: segment.attributes });
|
|
8515
|
+
} else {
|
|
8516
|
+
result.push({ text: segment.text, attributes: segment.attributes });
|
|
8517
|
+
}
|
|
8518
|
+
offset = end;
|
|
8519
|
+
}
|
|
8520
|
+
return result;
|
|
8521
|
+
}
|
|
8522
|
+
function clipRange(index, length, contentLength) {
|
|
8523
|
+
const clippedIndex = Math.max(0, Math.min(index, contentLength));
|
|
8524
|
+
const clippedEnd = Math.max(
|
|
8525
|
+
clippedIndex,
|
|
8526
|
+
Math.min(index + length, contentLength)
|
|
8527
|
+
);
|
|
8528
|
+
return { index: clippedIndex, length: clippedEnd - clippedIndex };
|
|
8529
|
+
}
|
|
8530
|
+
function applyInsert(segments, index, text, attributes) {
|
|
8531
|
+
if (text.length === 0) {
|
|
8532
|
+
return normalizeSegments(segments);
|
|
8533
|
+
}
|
|
8534
|
+
const split = splitSegmentsAt(segments, index);
|
|
8535
|
+
const result = [];
|
|
8536
|
+
let offset = 0;
|
|
8537
|
+
let inserted = false;
|
|
8538
|
+
for (const segment of split) {
|
|
8539
|
+
if (!inserted && offset === index) {
|
|
8540
|
+
result.push({ text, attributes });
|
|
8541
|
+
inserted = true;
|
|
8542
|
+
}
|
|
8543
|
+
result.push(segment);
|
|
8544
|
+
offset += segment.text.length;
|
|
8545
|
+
}
|
|
8546
|
+
if (!inserted) {
|
|
8547
|
+
result.push({ text, attributes });
|
|
8548
|
+
}
|
|
8549
|
+
return normalizeSegments(result);
|
|
8550
|
+
}
|
|
8551
|
+
function extractDeletedSegments(segments, index, length) {
|
|
8552
|
+
const split = splitSegmentsAt(
|
|
8553
|
+
splitSegmentsAt(segments, index),
|
|
8554
|
+
index + length
|
|
8555
|
+
);
|
|
8556
|
+
const deleted = [];
|
|
8557
|
+
let offset = 0;
|
|
8558
|
+
for (const segment of split) {
|
|
8559
|
+
const end = offset + segment.text.length;
|
|
8560
|
+
if (offset >= index && end <= index + length) {
|
|
8561
|
+
deleted.push({
|
|
8562
|
+
text: segment.text,
|
|
8563
|
+
attributes: segment.attributes
|
|
8564
|
+
});
|
|
8565
|
+
}
|
|
8566
|
+
offset = end;
|
|
8567
|
+
}
|
|
8568
|
+
return normalizeSegments(deleted);
|
|
8569
|
+
}
|
|
8570
|
+
function applyDelete(segments, index, length) {
|
|
8571
|
+
const deletedSegments = extractDeletedSegments(segments, index, length);
|
|
8572
|
+
const split = splitSegmentsAt(
|
|
8573
|
+
splitSegmentsAt(segments, index),
|
|
8574
|
+
index + length
|
|
8575
|
+
);
|
|
8576
|
+
const result = [];
|
|
8577
|
+
let offset = 0;
|
|
8578
|
+
let deletedText = "";
|
|
8579
|
+
for (const segment of split) {
|
|
8580
|
+
const end = offset + segment.text.length;
|
|
8581
|
+
if (offset >= index && end <= index + length) {
|
|
8582
|
+
deletedText += segment.text;
|
|
8583
|
+
} else {
|
|
8584
|
+
result.push(segment);
|
|
8585
|
+
}
|
|
8586
|
+
offset = end;
|
|
8587
|
+
}
|
|
8588
|
+
return {
|
|
8589
|
+
segments: normalizeSegments(result),
|
|
8590
|
+
deletedText,
|
|
8591
|
+
deletedSegments
|
|
8592
|
+
};
|
|
8593
|
+
}
|
|
8594
|
+
function applyFormat(segments, index, length, attributes) {
|
|
8595
|
+
const split = splitSegmentsAt(
|
|
8596
|
+
splitSegmentsAt(segments, index),
|
|
8597
|
+
index + length
|
|
8598
|
+
);
|
|
8599
|
+
const result = [];
|
|
8600
|
+
let offset = 0;
|
|
8601
|
+
for (const segment of split) {
|
|
8602
|
+
const end = offset + segment.text.length;
|
|
8603
|
+
if (offset >= index && end <= index + length) {
|
|
8604
|
+
const nextAttributes = {
|
|
8605
|
+
...segment.attributes ?? {}
|
|
8606
|
+
};
|
|
8607
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
8608
|
+
if (value === null) {
|
|
8609
|
+
delete nextAttributes[key];
|
|
8610
|
+
} else {
|
|
8611
|
+
nextAttributes[key] = value;
|
|
8612
|
+
}
|
|
8613
|
+
}
|
|
8614
|
+
result.push({
|
|
8615
|
+
text: segment.text,
|
|
8616
|
+
attributes: Object.keys(nextAttributes).length === 0 ? void 0 : freeze(nextAttributes)
|
|
8617
|
+
});
|
|
8618
|
+
} else {
|
|
8619
|
+
result.push(segment);
|
|
8620
|
+
}
|
|
8621
|
+
offset = end;
|
|
8622
|
+
}
|
|
8623
|
+
return normalizeSegments(result);
|
|
8624
|
+
}
|
|
8625
|
+
function formatReverseOperations(segments, index, length, patch) {
|
|
8626
|
+
const split = splitSegmentsAt(
|
|
8627
|
+
splitSegmentsAt(segments, index),
|
|
8628
|
+
index + length
|
|
8629
|
+
);
|
|
8630
|
+
const result = [];
|
|
8631
|
+
let offset = 0;
|
|
8632
|
+
for (const segment of split) {
|
|
8633
|
+
const end = offset + segment.text.length;
|
|
8634
|
+
if (offset >= index && end <= index + length) {
|
|
8635
|
+
const attributes = {};
|
|
8636
|
+
for (const key of Object.keys(patch)) {
|
|
8637
|
+
attributes[key] = segment.attributes?.[key] ?? null;
|
|
8638
|
+
}
|
|
8639
|
+
result.push({
|
|
8640
|
+
type: "format",
|
|
8641
|
+
index: offset,
|
|
8642
|
+
length: segment.text.length,
|
|
8643
|
+
attributes
|
|
8644
|
+
});
|
|
8645
|
+
}
|
|
8646
|
+
offset = end;
|
|
8647
|
+
}
|
|
8648
|
+
return result;
|
|
8649
|
+
}
|
|
8650
|
+
function mapIndexThroughOperation(index, op) {
|
|
8651
|
+
if (op.type === "insert") {
|
|
8652
|
+
return op.index <= index ? index + op.text.length : index;
|
|
8653
|
+
} else if (op.type === "delete") {
|
|
8654
|
+
if (op.index >= index) {
|
|
8655
|
+
return index;
|
|
8656
|
+
}
|
|
8657
|
+
return Math.max(op.index, index - op.length);
|
|
8658
|
+
} else {
|
|
8659
|
+
return index;
|
|
8660
|
+
}
|
|
8661
|
+
}
|
|
8662
|
+
function mapTextIndexThroughOperations(index, ops) {
|
|
8663
|
+
let mapped = index;
|
|
8664
|
+
for (const op of ops) {
|
|
8665
|
+
mapped = mapIndexThroughOperation(mapped, op);
|
|
8666
|
+
}
|
|
8667
|
+
return mapped;
|
|
8668
|
+
}
|
|
8669
|
+
function rebaseTextOperations(ops, acceptedOps) {
|
|
8670
|
+
return ops.map((op) => {
|
|
8671
|
+
if (op.type === "insert") {
|
|
8672
|
+
return {
|
|
8673
|
+
...op,
|
|
8674
|
+
index: mapTextIndexThroughOperations(op.index, acceptedOps)
|
|
8675
|
+
};
|
|
8676
|
+
} else if (op.type === "delete" || op.type === "format") {
|
|
8677
|
+
const start = mapTextIndexThroughOperations(op.index, acceptedOps);
|
|
8678
|
+
const end = mapTextIndexThroughOperations(
|
|
8679
|
+
op.index + op.length,
|
|
8680
|
+
acceptedOps
|
|
8681
|
+
);
|
|
8682
|
+
return { ...op, index: start, length: Math.max(0, end - start) };
|
|
8683
|
+
} else {
|
|
8684
|
+
return op;
|
|
8685
|
+
}
|
|
8686
|
+
});
|
|
8687
|
+
}
|
|
8688
|
+
function applyTextOperationsToSegments(segments, ops) {
|
|
8689
|
+
let next = [...segments];
|
|
8690
|
+
for (const op of ops) {
|
|
8691
|
+
if (op.type === "insert") {
|
|
8692
|
+
const index = Math.max(0, Math.min(op.index, textLength(next)));
|
|
8693
|
+
next = applyInsert(next, index, op.text, op.attributes);
|
|
8694
|
+
} else if (op.type === "delete") {
|
|
8695
|
+
const index = Math.max(0, Math.min(op.index, textLength(next)));
|
|
8696
|
+
const clipped = clipRange(index, op.length, textLength(next));
|
|
8697
|
+
next = applyDelete(next, clipped.index, clipped.length).segments;
|
|
8698
|
+
} else {
|
|
8699
|
+
const index = Math.max(0, Math.min(op.index, textLength(next)));
|
|
8700
|
+
const clipped = clipRange(index, op.length, textLength(next));
|
|
8701
|
+
next = applyFormat(next, clipped.index, clipped.length, op.attributes);
|
|
8702
|
+
}
|
|
8703
|
+
}
|
|
8704
|
+
return next;
|
|
8705
|
+
}
|
|
8706
|
+
function applyLiveTextOperations(delta, ops) {
|
|
8707
|
+
return segmentsToDelta(
|
|
8708
|
+
applyTextOperationsToSegments(deltaToSegments(delta), ops)
|
|
8709
|
+
);
|
|
8710
|
+
}
|
|
8711
|
+
function invertTextOperations(segments, ops) {
|
|
8712
|
+
let shadow = [...segments];
|
|
8713
|
+
const reverse = [];
|
|
8714
|
+
for (const op of ops) {
|
|
8715
|
+
if (op.type === "insert") {
|
|
8716
|
+
shadow = applyInsert(shadow, op.index, op.text, op.attributes);
|
|
8717
|
+
reverse.unshift({
|
|
8718
|
+
type: "delete",
|
|
8719
|
+
index: op.index,
|
|
8720
|
+
length: op.text.length
|
|
8721
|
+
});
|
|
8722
|
+
} else if (op.type === "delete") {
|
|
8723
|
+
const deletedSegments = extractDeletedSegments(
|
|
8724
|
+
shadow,
|
|
8725
|
+
op.index,
|
|
8726
|
+
op.length
|
|
8727
|
+
);
|
|
8728
|
+
shadow = applyDelete(shadow, op.index, op.length).segments;
|
|
8729
|
+
const inserts = [];
|
|
8730
|
+
let insertIndex = op.index;
|
|
8731
|
+
for (const segment of deletedSegments) {
|
|
8732
|
+
inserts.push({
|
|
8733
|
+
type: "insert",
|
|
8734
|
+
index: insertIndex,
|
|
8735
|
+
text: segment.text,
|
|
8736
|
+
attributes: segment.attributes
|
|
8737
|
+
});
|
|
8738
|
+
insertIndex += segment.text.length;
|
|
8739
|
+
}
|
|
8740
|
+
for (let index = inserts.length - 1; index >= 0; index--) {
|
|
8741
|
+
reverse.unshift(inserts[index]);
|
|
8742
|
+
}
|
|
8743
|
+
} else {
|
|
8744
|
+
const inverse = formatReverseOperations(
|
|
8745
|
+
shadow,
|
|
8746
|
+
op.index,
|
|
8747
|
+
op.length,
|
|
8748
|
+
op.attributes
|
|
8749
|
+
);
|
|
8750
|
+
shadow = applyFormat(shadow, op.index, op.length, op.attributes);
|
|
8751
|
+
reverse.unshift(...inverse.reverse());
|
|
8752
|
+
}
|
|
8753
|
+
}
|
|
8754
|
+
return reverse;
|
|
8755
|
+
}
|
|
8756
|
+
|
|
8757
|
+
// src/crdts/LiveText.ts
|
|
8758
|
+
var LiveText = class _LiveText extends AbstractCrdt {
|
|
8759
|
+
#segments;
|
|
8760
|
+
#version;
|
|
8761
|
+
#pendingOps;
|
|
8762
|
+
constructor(textOrDelta = "", version = 0) {
|
|
8763
|
+
super();
|
|
8764
|
+
this.#segments = typeof textOrDelta === "string" ? textOrDelta.length === 0 ? [] : [{ text: textOrDelta }] : deltaToSegments(textOrDelta);
|
|
8765
|
+
this.#version = version;
|
|
8766
|
+
this.#pendingOps = /* @__PURE__ */ new Map();
|
|
8767
|
+
}
|
|
8768
|
+
get version() {
|
|
8769
|
+
return this.#version;
|
|
8770
|
+
}
|
|
8771
|
+
get length() {
|
|
8772
|
+
return this.toString().length;
|
|
8773
|
+
}
|
|
8774
|
+
/** @internal */
|
|
8775
|
+
static _deserialize([id, item], _parentToChildren, pool) {
|
|
8776
|
+
const text = new _LiveText(item.data, item.version);
|
|
8777
|
+
text._attach(id, pool);
|
|
8778
|
+
return text;
|
|
8779
|
+
}
|
|
8780
|
+
/** @internal */
|
|
8781
|
+
_toOps(parentId, parentKey) {
|
|
8782
|
+
if (this._id === void 0) {
|
|
8783
|
+
throw new Error("Cannot serialize LiveText if it is not attached");
|
|
8784
|
+
}
|
|
8785
|
+
return [
|
|
8786
|
+
{
|
|
8787
|
+
type: OpCode.CREATE_TEXT,
|
|
8788
|
+
id: this._id,
|
|
8789
|
+
parentId,
|
|
8790
|
+
parentKey,
|
|
8791
|
+
data: this.toDelta(),
|
|
8792
|
+
version: this.#version
|
|
8793
|
+
}
|
|
8794
|
+
];
|
|
8795
|
+
}
|
|
8796
|
+
/** @internal */
|
|
8797
|
+
_serialize() {
|
|
8798
|
+
if (this.parent.type !== "HasParent") {
|
|
8799
|
+
throw new Error("Cannot serialize LiveText if parent is missing");
|
|
8800
|
+
}
|
|
8801
|
+
return {
|
|
8802
|
+
type: CrdtType.TEXT,
|
|
8803
|
+
parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
|
|
8804
|
+
parentKey: this.parent.key,
|
|
8805
|
+
data: this.toDelta(),
|
|
8806
|
+
version: this.#version
|
|
8807
|
+
};
|
|
8808
|
+
}
|
|
8809
|
+
/** @internal */
|
|
8810
|
+
_attachChild(_op) {
|
|
8811
|
+
throw new Error("LiveText cannot contain child nodes");
|
|
8812
|
+
}
|
|
8813
|
+
/** @internal */
|
|
8814
|
+
_detachChild(_crdt) {
|
|
8815
|
+
throw new Error("LiveText cannot contain child nodes");
|
|
8816
|
+
}
|
|
8817
|
+
/** @internal */
|
|
8818
|
+
_apply(op, isLocal) {
|
|
8819
|
+
if (op.type !== OpCode.UPDATE_TEXT) {
|
|
8820
|
+
return super._apply(op, isLocal);
|
|
8821
|
+
}
|
|
8822
|
+
if (isLocal) {
|
|
8823
|
+
this.#pendingOps.set(nn(op.opId), op.ops);
|
|
8824
|
+
return this.#applyOperations(op.ops, op.version ?? this.#version);
|
|
8825
|
+
}
|
|
8826
|
+
if (op.opId !== void 0) {
|
|
8827
|
+
const pending2 = this.#pendingOps.get(op.opId);
|
|
8828
|
+
this.#pendingOps.delete(op.opId);
|
|
8829
|
+
const otherPending = Array.from(this.#pendingOps.values()).flat();
|
|
8830
|
+
if (pending2 !== void 0 && otherPending.length > 0) {
|
|
8831
|
+
this.#segments = applyTextOperationsToSegments(
|
|
8832
|
+
this.#segments,
|
|
8833
|
+
invertTextOperations(this.#segments, pending2)
|
|
8834
|
+
);
|
|
8835
|
+
const ops2 = rebaseTextOperations(op.ops, otherPending);
|
|
8836
|
+
return this.#applyOperations(
|
|
8837
|
+
ops2,
|
|
8838
|
+
op.version ?? Math.max(this.#version, op.baseVersion + 1)
|
|
8839
|
+
);
|
|
8840
|
+
}
|
|
8841
|
+
this.#version = op.version ?? Math.max(this.#version, op.baseVersion + 1);
|
|
8842
|
+
return { modified: false };
|
|
8843
|
+
}
|
|
8844
|
+
const pending = Array.from(this.#pendingOps.values()).flat();
|
|
8845
|
+
const ops = pending.length > 0 ? rebaseTextOperations(op.ops, pending) : op.ops;
|
|
8846
|
+
return this.#applyOperations(ops, op.version ?? this.#version + 1);
|
|
8847
|
+
}
|
|
8848
|
+
insert(index, text, attributes) {
|
|
8849
|
+
const clippedIndex = Math.max(0, Math.min(index, this.length));
|
|
8850
|
+
this.#dispatch([{ type: "insert", index: clippedIndex, text, attributes }]);
|
|
8851
|
+
}
|
|
8852
|
+
delete(index, length) {
|
|
8853
|
+
const clipped = clipRange(index, length, this.length);
|
|
8854
|
+
if (clipped.length === 0) {
|
|
8855
|
+
return;
|
|
8856
|
+
}
|
|
8857
|
+
this.#dispatch([
|
|
8858
|
+
{ type: "delete", index: clipped.index, length: clipped.length }
|
|
8859
|
+
]);
|
|
8860
|
+
}
|
|
8861
|
+
replace(index, length, text, attributes) {
|
|
8862
|
+
const clipped = clipRange(index, length, this.length);
|
|
8863
|
+
const ops = [];
|
|
8864
|
+
if (clipped.length > 0) {
|
|
8865
|
+
ops.push({
|
|
8866
|
+
type: "delete",
|
|
8867
|
+
index: clipped.index,
|
|
8868
|
+
length: clipped.length
|
|
8869
|
+
});
|
|
8870
|
+
}
|
|
8871
|
+
if (text.length > 0) {
|
|
8872
|
+
ops.push({ type: "insert", index: clipped.index, text, attributes });
|
|
8873
|
+
}
|
|
8874
|
+
this.#dispatch(ops);
|
|
8875
|
+
}
|
|
8876
|
+
format(index, length, attributes) {
|
|
8877
|
+
const clipped = clipRange(index, length, this.length);
|
|
8878
|
+
if (clipped.length === 0) {
|
|
8879
|
+
return;
|
|
8880
|
+
}
|
|
8881
|
+
this.#dispatch([
|
|
8882
|
+
{
|
|
8883
|
+
type: "format",
|
|
8884
|
+
index: clipped.index,
|
|
8885
|
+
length: clipped.length,
|
|
8886
|
+
attributes
|
|
8887
|
+
}
|
|
8888
|
+
]);
|
|
8889
|
+
}
|
|
8890
|
+
#dispatch(ops) {
|
|
8891
|
+
if (ops.length === 0) {
|
|
8892
|
+
return;
|
|
8893
|
+
}
|
|
8894
|
+
this._pool?.assertStorageIsWritable();
|
|
8895
|
+
const baseVersion = this.#version;
|
|
8896
|
+
const reverse = this._pool !== void 0 && this._id !== void 0 ? this.#invertOperations(ops) : [];
|
|
8897
|
+
const changes = this.#applyOperationsLocally(ops);
|
|
8898
|
+
if (this._pool !== void 0 && this._id !== void 0) {
|
|
8899
|
+
const opId = this._pool.generateOpId();
|
|
8900
|
+
this.#pendingOps.set(opId, ops);
|
|
8901
|
+
this._pool.dispatch(
|
|
8902
|
+
[
|
|
8903
|
+
{
|
|
8904
|
+
type: OpCode.UPDATE_TEXT,
|
|
8905
|
+
id: this._id,
|
|
8906
|
+
opId,
|
|
8907
|
+
baseVersion,
|
|
8908
|
+
ops: [...ops]
|
|
8909
|
+
}
|
|
8910
|
+
],
|
|
8911
|
+
reverse,
|
|
8912
|
+
/* @__PURE__ */ new Map([
|
|
8913
|
+
[
|
|
8914
|
+
this._id,
|
|
8915
|
+
{
|
|
8916
|
+
type: "LiveText",
|
|
8917
|
+
node: this,
|
|
8918
|
+
version: this.#version,
|
|
8919
|
+
updates: changes
|
|
8920
|
+
}
|
|
8921
|
+
]
|
|
8922
|
+
])
|
|
8923
|
+
);
|
|
8924
|
+
}
|
|
8925
|
+
}
|
|
8926
|
+
#applyOperations(ops, version) {
|
|
8927
|
+
const reverse = this.#invertOperations(ops);
|
|
8928
|
+
const changes = this.#applyOperationsLocally(ops);
|
|
8929
|
+
this.#version = Math.max(this.#version, version);
|
|
8930
|
+
return {
|
|
8931
|
+
reverse,
|
|
8932
|
+
modified: {
|
|
8933
|
+
type: "LiveText",
|
|
8934
|
+
node: this,
|
|
8935
|
+
version: this.#version,
|
|
8936
|
+
updates: changes
|
|
8937
|
+
}
|
|
8938
|
+
};
|
|
8939
|
+
}
|
|
8940
|
+
#applyOperationsLocally(ops) {
|
|
8941
|
+
const changes = [];
|
|
8942
|
+
for (const op of ops) {
|
|
8943
|
+
if (op.type === "insert") {
|
|
8944
|
+
this.#segments = applyInsert(
|
|
8945
|
+
this.#segments,
|
|
8946
|
+
op.index,
|
|
8947
|
+
op.text,
|
|
8948
|
+
op.attributes
|
|
8949
|
+
);
|
|
8950
|
+
changes.push({
|
|
8951
|
+
type: "insert",
|
|
8952
|
+
index: op.index,
|
|
8953
|
+
text: op.text,
|
|
8954
|
+
attributes: op.attributes
|
|
8955
|
+
});
|
|
8956
|
+
} else if (op.type === "delete") {
|
|
8957
|
+
const result = applyDelete(this.#segments, op.index, op.length);
|
|
8958
|
+
this.#segments = result.segments;
|
|
8959
|
+
changes.push({
|
|
8960
|
+
type: "delete",
|
|
8961
|
+
index: op.index,
|
|
8962
|
+
length: op.length,
|
|
8963
|
+
deletedText: result.deletedText
|
|
8964
|
+
});
|
|
8965
|
+
} else {
|
|
8966
|
+
this.#segments = applyFormat(
|
|
8967
|
+
this.#segments,
|
|
8968
|
+
op.index,
|
|
8969
|
+
op.length,
|
|
8970
|
+
op.attributes
|
|
8971
|
+
);
|
|
8972
|
+
changes.push({
|
|
8973
|
+
type: "format",
|
|
8974
|
+
index: op.index,
|
|
8975
|
+
length: op.length,
|
|
8976
|
+
attributes: op.attributes
|
|
8977
|
+
});
|
|
8978
|
+
}
|
|
8979
|
+
}
|
|
8980
|
+
this.invalidate();
|
|
8981
|
+
return changes;
|
|
8982
|
+
}
|
|
8983
|
+
#invertOperations(ops) {
|
|
8984
|
+
return [
|
|
8985
|
+
{
|
|
8986
|
+
type: OpCode.UPDATE_TEXT,
|
|
8987
|
+
id: nn(this._id),
|
|
8988
|
+
baseVersion: this.#version,
|
|
8989
|
+
ops: invertTextOperations(this.#segments, ops)
|
|
8990
|
+
}
|
|
8991
|
+
];
|
|
8992
|
+
}
|
|
8993
|
+
toString() {
|
|
8994
|
+
return this.#segments.map((segment) => segment.text).join("");
|
|
8995
|
+
}
|
|
8996
|
+
toDelta() {
|
|
8997
|
+
return segmentsToDelta(this.#segments);
|
|
8998
|
+
}
|
|
8999
|
+
toJSON() {
|
|
9000
|
+
return super.toJSON();
|
|
9001
|
+
}
|
|
9002
|
+
/** @internal */
|
|
9003
|
+
_toJSON() {
|
|
9004
|
+
return this.toDelta();
|
|
9005
|
+
}
|
|
9006
|
+
/** @internal */
|
|
9007
|
+
_toTreeNode(key) {
|
|
9008
|
+
return {
|
|
9009
|
+
type: "LiveText",
|
|
9010
|
+
id: this._id ?? nanoid(),
|
|
9011
|
+
key,
|
|
9012
|
+
payload: [
|
|
9013
|
+
{
|
|
9014
|
+
type: "Json",
|
|
9015
|
+
id: `${this._id ?? nanoid()}:text`,
|
|
9016
|
+
key: "text",
|
|
9017
|
+
payload: this.toString()
|
|
9018
|
+
}
|
|
9019
|
+
]
|
|
9020
|
+
};
|
|
9021
|
+
}
|
|
9022
|
+
clone() {
|
|
9023
|
+
return new _LiveText(this.toDelta(), this.#version);
|
|
9024
|
+
}
|
|
9025
|
+
};
|
|
9026
|
+
|
|
8429
9027
|
// src/crdts/liveblocks-helpers.ts
|
|
8430
9028
|
function creationOpToLiveNode(op) {
|
|
8431
9029
|
return lsonToLiveNode(creationOpToLson(op));
|
|
@@ -8440,6 +9038,8 @@ function creationOpToLson(op) {
|
|
|
8440
9038
|
return new LiveMap();
|
|
8441
9039
|
case OpCode.CREATE_LIST:
|
|
8442
9040
|
return new LiveList([]);
|
|
9041
|
+
case OpCode.CREATE_TEXT:
|
|
9042
|
+
return new LiveText(op.data, op.version);
|
|
8443
9043
|
default:
|
|
8444
9044
|
return assertNever(op, "Unknown creation Op");
|
|
8445
9045
|
}
|
|
@@ -8462,6 +9062,8 @@ function deserialize(node, parentToChildren, pool) {
|
|
|
8462
9062
|
return LiveMap._deserialize(node, parentToChildren, pool);
|
|
8463
9063
|
} else if (isRegisterStorageNode(node)) {
|
|
8464
9064
|
return LiveRegister._deserialize(node, parentToChildren, pool);
|
|
9065
|
+
} else if (isTextStorageNode(node)) {
|
|
9066
|
+
return LiveText._deserialize(node, parentToChildren, pool);
|
|
8465
9067
|
} else {
|
|
8466
9068
|
throw new Error("Unexpected CRDT type");
|
|
8467
9069
|
}
|
|
@@ -8475,12 +9077,14 @@ function deserializeToLson(node, parentToChildren, pool) {
|
|
|
8475
9077
|
return LiveMap._deserialize(node, parentToChildren, pool);
|
|
8476
9078
|
} else if (isRegisterStorageNode(node)) {
|
|
8477
9079
|
return node[1].data;
|
|
9080
|
+
} else if (isTextStorageNode(node)) {
|
|
9081
|
+
return LiveText._deserialize(node, parentToChildren, pool);
|
|
8478
9082
|
} else {
|
|
8479
9083
|
throw new Error("Unexpected CRDT type");
|
|
8480
9084
|
}
|
|
8481
9085
|
}
|
|
8482
9086
|
function isLiveStructure(value) {
|
|
8483
|
-
return isLiveList(value) || isLiveMap(value) || isLiveObject(value);
|
|
9087
|
+
return isLiveList(value) || isLiveMap(value) || isLiveObject(value) || isLiveText(value);
|
|
8484
9088
|
}
|
|
8485
9089
|
function isLiveNode(value) {
|
|
8486
9090
|
return isLiveStructure(value) || isLiveRegister(value);
|
|
@@ -8494,6 +9098,9 @@ function isLiveMap(value) {
|
|
|
8494
9098
|
function isLiveObject(value) {
|
|
8495
9099
|
return value instanceof LiveObject;
|
|
8496
9100
|
}
|
|
9101
|
+
function isLiveText(value) {
|
|
9102
|
+
return value instanceof LiveText;
|
|
9103
|
+
}
|
|
8497
9104
|
function isLiveRegister(value) {
|
|
8498
9105
|
return value instanceof LiveRegister;
|
|
8499
9106
|
}
|
|
@@ -8503,14 +9110,14 @@ function cloneLson(value) {
|
|
|
8503
9110
|
function liveNodeToLson(obj) {
|
|
8504
9111
|
if (obj instanceof LiveRegister) {
|
|
8505
9112
|
return obj.data;
|
|
8506
|
-
} else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject) {
|
|
9113
|
+
} else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject || obj instanceof LiveText) {
|
|
8507
9114
|
return obj;
|
|
8508
9115
|
} else {
|
|
8509
9116
|
return assertNever(obj, "Unknown AbstractCrdt");
|
|
8510
9117
|
}
|
|
8511
9118
|
}
|
|
8512
9119
|
function lsonToLiveNode(value) {
|
|
8513
|
-
if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList) {
|
|
9120
|
+
if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList || value instanceof LiveText) {
|
|
8514
9121
|
return value;
|
|
8515
9122
|
} else {
|
|
8516
9123
|
return new LiveRegister(value);
|
|
@@ -8541,6 +9148,35 @@ function dumpPool(pool) {
|
|
|
8541
9148
|
(r) => ` ${r.id} parent=${r.parentId} key=${r.key || "\u2014"} ${r.value}`
|
|
8542
9149
|
).join("\n");
|
|
8543
9150
|
}
|
|
9151
|
+
function isJsonEq(a, b) {
|
|
9152
|
+
if (a === b) {
|
|
9153
|
+
return true;
|
|
9154
|
+
}
|
|
9155
|
+
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
|
|
9156
|
+
return false;
|
|
9157
|
+
}
|
|
9158
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
9159
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
|
|
9160
|
+
return false;
|
|
9161
|
+
}
|
|
9162
|
+
for (let i = 0; i < a.length; i++) {
|
|
9163
|
+
if (!isJsonEq(a[i], b[i])) {
|
|
9164
|
+
return false;
|
|
9165
|
+
}
|
|
9166
|
+
}
|
|
9167
|
+
return true;
|
|
9168
|
+
}
|
|
9169
|
+
const aKeys = Object.keys(a);
|
|
9170
|
+
if (aKeys.length !== Object.keys(b).length) {
|
|
9171
|
+
return false;
|
|
9172
|
+
}
|
|
9173
|
+
for (const key of aKeys) {
|
|
9174
|
+
if (!isJsonEq(a[key], b[key])) {
|
|
9175
|
+
return false;
|
|
9176
|
+
}
|
|
9177
|
+
}
|
|
9178
|
+
return true;
|
|
9179
|
+
}
|
|
8544
9180
|
function getTreesDiffOperations(currentItems, newItems) {
|
|
8545
9181
|
const ops = [];
|
|
8546
9182
|
currentItems.forEach((_, id) => {
|
|
@@ -8552,11 +9188,59 @@ function getTreesDiffOperations(currentItems, newItems) {
|
|
|
8552
9188
|
const currentCrdt = currentItems.get(id);
|
|
8553
9189
|
if (currentCrdt) {
|
|
8554
9190
|
if (crdt.type === CrdtType.OBJECT) {
|
|
8555
|
-
if (currentCrdt.type !== CrdtType.OBJECT
|
|
9191
|
+
if (currentCrdt.type !== CrdtType.OBJECT) {
|
|
9192
|
+
ops.push({ type: OpCode.UPDATE_OBJECT, id, data: crdt.data });
|
|
9193
|
+
} else {
|
|
9194
|
+
const changed = /* @__PURE__ */ new Map();
|
|
9195
|
+
for (const key of Object.keys(crdt.data)) {
|
|
9196
|
+
const value = crdt.data[key];
|
|
9197
|
+
if (value !== void 0 && !isJsonEq(value, currentCrdt.data[key])) {
|
|
9198
|
+
changed.set(key, value);
|
|
9199
|
+
}
|
|
9200
|
+
}
|
|
9201
|
+
if (changed.size > 0) {
|
|
9202
|
+
ops.push({
|
|
9203
|
+
type: OpCode.UPDATE_OBJECT,
|
|
9204
|
+
id,
|
|
9205
|
+
data: Object.fromEntries(changed)
|
|
9206
|
+
});
|
|
9207
|
+
}
|
|
9208
|
+
for (const key of Object.keys(currentCrdt.data)) {
|
|
9209
|
+
if (!(key in crdt.data)) {
|
|
9210
|
+
ops.push({ type: OpCode.DELETE_OBJECT_KEY, id, key });
|
|
9211
|
+
}
|
|
9212
|
+
}
|
|
9213
|
+
}
|
|
9214
|
+
}
|
|
9215
|
+
if (crdt.type === CrdtType.TEXT) {
|
|
9216
|
+
if (currentCrdt.type !== CrdtType.TEXT || stringifyOrLog(crdt.data) !== stringifyOrLog(currentCrdt.data) || crdt.version !== currentCrdt.version) {
|
|
8556
9217
|
ops.push({
|
|
8557
|
-
type: OpCode.
|
|
9218
|
+
type: OpCode.UPDATE_TEXT,
|
|
8558
9219
|
id,
|
|
8559
|
-
|
|
9220
|
+
baseVersion: currentCrdt.type === CrdtType.TEXT ? currentCrdt.version : 0,
|
|
9221
|
+
version: crdt.version,
|
|
9222
|
+
ops: [
|
|
9223
|
+
{
|
|
9224
|
+
type: "delete",
|
|
9225
|
+
index: 0,
|
|
9226
|
+
length: currentCrdt.type === CrdtType.TEXT ? currentCrdt.data.reduce(
|
|
9227
|
+
(sum, item) => sum + item.text.length,
|
|
9228
|
+
0
|
|
9229
|
+
) : 0
|
|
9230
|
+
},
|
|
9231
|
+
...crdt.data.map(
|
|
9232
|
+
(item, index, items) => item.attributes === void 0 ? {
|
|
9233
|
+
type: "insert",
|
|
9234
|
+
index: items.slice(0, index).reduce((sum, item2) => sum + item2.text.length, 0),
|
|
9235
|
+
text: item.text
|
|
9236
|
+
} : {
|
|
9237
|
+
type: "insert",
|
|
9238
|
+
index: items.slice(0, index).reduce((sum, item2) => sum + item2.text.length, 0),
|
|
9239
|
+
text: item.text,
|
|
9240
|
+
attributes: item.attributes
|
|
9241
|
+
}
|
|
9242
|
+
)
|
|
9243
|
+
]
|
|
8560
9244
|
});
|
|
8561
9245
|
}
|
|
8562
9246
|
}
|
|
@@ -8608,6 +9292,16 @@ function getTreesDiffOperations(currentItems, newItems) {
|
|
|
8608
9292
|
parentKey: crdt.parentKey
|
|
8609
9293
|
});
|
|
8610
9294
|
break;
|
|
9295
|
+
case CrdtType.TEXT:
|
|
9296
|
+
ops.push({
|
|
9297
|
+
type: OpCode.CREATE_TEXT,
|
|
9298
|
+
id,
|
|
9299
|
+
parentId: crdt.parentId,
|
|
9300
|
+
parentKey: crdt.parentKey,
|
|
9301
|
+
data: crdt.data,
|
|
9302
|
+
version: crdt.version
|
|
9303
|
+
});
|
|
9304
|
+
break;
|
|
8611
9305
|
}
|
|
8612
9306
|
}
|
|
8613
9307
|
});
|
|
@@ -8640,6 +9334,12 @@ function mergeListStorageUpdates(first, second) {
|
|
|
8640
9334
|
updates: updates.concat(second.updates)
|
|
8641
9335
|
};
|
|
8642
9336
|
}
|
|
9337
|
+
function mergeTextStorageUpdates(first, second) {
|
|
9338
|
+
return {
|
|
9339
|
+
...second,
|
|
9340
|
+
updates: first.updates.concat(second.updates)
|
|
9341
|
+
};
|
|
9342
|
+
}
|
|
8643
9343
|
function mergeStorageUpdates(first, second) {
|
|
8644
9344
|
if (first === void 0) {
|
|
8645
9345
|
return second;
|
|
@@ -8650,6 +9350,8 @@ function mergeStorageUpdates(first, second) {
|
|
|
8650
9350
|
return mergeMapStorageUpdates(first, second);
|
|
8651
9351
|
} else if (first.type === "LiveList" && second.type === "LiveList") {
|
|
8652
9352
|
return mergeListStorageUpdates(first, second);
|
|
9353
|
+
} else if (first.type === "LiveText" && second.type === "LiveText") {
|
|
9354
|
+
return mergeTextStorageUpdates(first, second);
|
|
8653
9355
|
} else {
|
|
8654
9356
|
}
|
|
8655
9357
|
return second;
|
|
@@ -9938,7 +10640,7 @@ function createRoom(options, config) {
|
|
|
9938
10640
|
);
|
|
9939
10641
|
output.reverse.pushLeft(applyOpResult.reverse);
|
|
9940
10642
|
}
|
|
9941
|
-
if (op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_OBJECT) {
|
|
10643
|
+
if (op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_OBJECT || op.type === OpCode.CREATE_TEXT) {
|
|
9942
10644
|
createdNodeIds.add(op.id);
|
|
9943
10645
|
}
|
|
9944
10646
|
}
|
|
@@ -9958,6 +10660,7 @@ function createRoom(options, config) {
|
|
|
9958
10660
|
switch (op.type) {
|
|
9959
10661
|
case OpCode.DELETE_OBJECT_KEY:
|
|
9960
10662
|
case OpCode.UPDATE_OBJECT:
|
|
10663
|
+
case OpCode.UPDATE_TEXT:
|
|
9961
10664
|
case OpCode.DELETE_CRDT: {
|
|
9962
10665
|
const node = context.pool.nodes.get(op.id);
|
|
9963
10666
|
if (node === void 0) {
|
|
@@ -9982,6 +10685,7 @@ function createRoom(options, config) {
|
|
|
9982
10685
|
case OpCode.CREATE_OBJECT:
|
|
9983
10686
|
case OpCode.CREATE_LIST:
|
|
9984
10687
|
case OpCode.CREATE_MAP:
|
|
10688
|
+
case OpCode.CREATE_TEXT:
|
|
9985
10689
|
case OpCode.CREATE_REGISTER: {
|
|
9986
10690
|
if (op.parentId === void 0) {
|
|
9987
10691
|
return { modified: false };
|
|
@@ -12141,6 +12845,12 @@ function toPlainLson(lson) {
|
|
|
12141
12845
|
liveblocksType: "LiveList",
|
|
12142
12846
|
data: [...lson].map((item) => toPlainLson(item))
|
|
12143
12847
|
};
|
|
12848
|
+
} else if (lson instanceof LiveText) {
|
|
12849
|
+
return {
|
|
12850
|
+
liveblocksType: "LiveText",
|
|
12851
|
+
data: lson.toDelta(),
|
|
12852
|
+
version: lson.version
|
|
12853
|
+
};
|
|
12144
12854
|
} else {
|
|
12145
12855
|
return lson;
|
|
12146
12856
|
}
|
|
@@ -12322,6 +13032,7 @@ export {
|
|
|
12322
13032
|
LiveList,
|
|
12323
13033
|
LiveMap,
|
|
12324
13034
|
LiveObject,
|
|
13035
|
+
LiveText,
|
|
12325
13036
|
LiveblocksError,
|
|
12326
13037
|
MENTION_CHARACTER,
|
|
12327
13038
|
MutableSignal,
|
|
@@ -12333,6 +13044,7 @@ export {
|
|
|
12333
13044
|
SortedList,
|
|
12334
13045
|
TextEditorType,
|
|
12335
13046
|
WebsocketCloseCodes,
|
|
13047
|
+
applyLiveTextOperations,
|
|
12336
13048
|
asPos,
|
|
12337
13049
|
assert,
|
|
12338
13050
|
assertNever,
|
|
@@ -12388,6 +13100,7 @@ export {
|
|
|
12388
13100
|
isRegisterStorageNode,
|
|
12389
13101
|
isRootStorageNode,
|
|
12390
13102
|
isStartsWithOperator,
|
|
13103
|
+
isTextStorageNode,
|
|
12391
13104
|
isUrl,
|
|
12392
13105
|
kInternal,
|
|
12393
13106
|
keys,
|