@liveblocks/core 3.19.5-rc1 → 3.20.0-exp1
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 +792 -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 +722 -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-exp1";
|
|
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,581 @@ 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(applyTextOperationsToSegments(deltaToSegments(delta), ops));
|
|
8708
|
+
}
|
|
8709
|
+
function invertTextOperations(segments, ops) {
|
|
8710
|
+
let shadow = [...segments];
|
|
8711
|
+
const reverse = [];
|
|
8712
|
+
for (const op of ops) {
|
|
8713
|
+
if (op.type === "insert") {
|
|
8714
|
+
shadow = applyInsert(shadow, op.index, op.text, op.attributes);
|
|
8715
|
+
reverse.unshift({
|
|
8716
|
+
type: "delete",
|
|
8717
|
+
index: op.index,
|
|
8718
|
+
length: op.text.length
|
|
8719
|
+
});
|
|
8720
|
+
} else if (op.type === "delete") {
|
|
8721
|
+
const deletedSegments = extractDeletedSegments(
|
|
8722
|
+
shadow,
|
|
8723
|
+
op.index,
|
|
8724
|
+
op.length
|
|
8725
|
+
);
|
|
8726
|
+
shadow = applyDelete(shadow, op.index, op.length).segments;
|
|
8727
|
+
const inserts = [];
|
|
8728
|
+
let insertIndex = op.index;
|
|
8729
|
+
for (const segment of deletedSegments) {
|
|
8730
|
+
inserts.push({
|
|
8731
|
+
type: "insert",
|
|
8732
|
+
index: insertIndex,
|
|
8733
|
+
text: segment.text,
|
|
8734
|
+
attributes: segment.attributes
|
|
8735
|
+
});
|
|
8736
|
+
insertIndex += segment.text.length;
|
|
8737
|
+
}
|
|
8738
|
+
for (let index = inserts.length - 1; index >= 0; index--) {
|
|
8739
|
+
reverse.unshift(inserts[index]);
|
|
8740
|
+
}
|
|
8741
|
+
} else {
|
|
8742
|
+
const inverse = formatReverseOperations(
|
|
8743
|
+
shadow,
|
|
8744
|
+
op.index,
|
|
8745
|
+
op.length,
|
|
8746
|
+
op.attributes
|
|
8747
|
+
);
|
|
8748
|
+
shadow = applyFormat(shadow, op.index, op.length, op.attributes);
|
|
8749
|
+
reverse.unshift(...inverse.reverse());
|
|
8750
|
+
}
|
|
8751
|
+
}
|
|
8752
|
+
return reverse;
|
|
8753
|
+
}
|
|
8754
|
+
|
|
8755
|
+
// src/crdts/LiveText.ts
|
|
8756
|
+
var LiveText = class _LiveText extends AbstractCrdt {
|
|
8757
|
+
#segments;
|
|
8758
|
+
#version;
|
|
8759
|
+
#pendingOps;
|
|
8760
|
+
constructor(textOrDelta = "", version = 0) {
|
|
8761
|
+
super();
|
|
8762
|
+
this.#segments = typeof textOrDelta === "string" ? textOrDelta.length === 0 ? [] : [{ text: textOrDelta }] : deltaToSegments(textOrDelta);
|
|
8763
|
+
this.#version = version;
|
|
8764
|
+
this.#pendingOps = /* @__PURE__ */ new Map();
|
|
8765
|
+
}
|
|
8766
|
+
get version() {
|
|
8767
|
+
return this.#version;
|
|
8768
|
+
}
|
|
8769
|
+
get length() {
|
|
8770
|
+
return this.toString().length;
|
|
8771
|
+
}
|
|
8772
|
+
/** @internal */
|
|
8773
|
+
static _deserialize([id, item], _parentToChildren, pool) {
|
|
8774
|
+
const text = new _LiveText(item.data, item.version);
|
|
8775
|
+
text._attach(id, pool);
|
|
8776
|
+
return text;
|
|
8777
|
+
}
|
|
8778
|
+
/** @internal */
|
|
8779
|
+
_toOps(parentId, parentKey) {
|
|
8780
|
+
if (this._id === void 0) {
|
|
8781
|
+
throw new Error("Cannot serialize LiveText if it is not attached");
|
|
8782
|
+
}
|
|
8783
|
+
return [
|
|
8784
|
+
{
|
|
8785
|
+
type: OpCode.CREATE_TEXT,
|
|
8786
|
+
id: this._id,
|
|
8787
|
+
parentId,
|
|
8788
|
+
parentKey,
|
|
8789
|
+
data: this.toDelta(),
|
|
8790
|
+
version: this.#version
|
|
8791
|
+
}
|
|
8792
|
+
];
|
|
8793
|
+
}
|
|
8794
|
+
/** @internal */
|
|
8795
|
+
_serialize() {
|
|
8796
|
+
if (this.parent.type !== "HasParent") {
|
|
8797
|
+
throw new Error("Cannot serialize LiveText if parent is missing");
|
|
8798
|
+
}
|
|
8799
|
+
return {
|
|
8800
|
+
type: CrdtType.TEXT,
|
|
8801
|
+
parentId: nn(this.parent.node._id, "Parent node expected to have ID"),
|
|
8802
|
+
parentKey: this.parent.key,
|
|
8803
|
+
data: this.toDelta(),
|
|
8804
|
+
version: this.#version
|
|
8805
|
+
};
|
|
8806
|
+
}
|
|
8807
|
+
/** @internal */
|
|
8808
|
+
_attachChild(_op) {
|
|
8809
|
+
throw new Error("LiveText cannot contain child nodes");
|
|
8810
|
+
}
|
|
8811
|
+
/** @internal */
|
|
8812
|
+
_detachChild(_crdt) {
|
|
8813
|
+
throw new Error("LiveText cannot contain child nodes");
|
|
8814
|
+
}
|
|
8815
|
+
/** @internal */
|
|
8816
|
+
_apply(op, isLocal) {
|
|
8817
|
+
if (op.type !== OpCode.UPDATE_TEXT) {
|
|
8818
|
+
return super._apply(op, isLocal);
|
|
8819
|
+
}
|
|
8820
|
+
if (isLocal) {
|
|
8821
|
+
this.#pendingOps.set(nn(op.opId), op.ops);
|
|
8822
|
+
return this.#applyOperations(op.ops, op.version ?? this.#version);
|
|
8823
|
+
}
|
|
8824
|
+
if (op.opId !== void 0) {
|
|
8825
|
+
const pending2 = this.#pendingOps.get(op.opId);
|
|
8826
|
+
this.#pendingOps.delete(op.opId);
|
|
8827
|
+
const otherPending = Array.from(this.#pendingOps.values()).flat();
|
|
8828
|
+
if (pending2 !== void 0 && otherPending.length > 0) {
|
|
8829
|
+
this.#segments = applyTextOperationsToSegments(
|
|
8830
|
+
this.#segments,
|
|
8831
|
+
invertTextOperations(this.#segments, pending2)
|
|
8832
|
+
);
|
|
8833
|
+
const ops2 = rebaseTextOperations(op.ops, otherPending);
|
|
8834
|
+
return this.#applyOperations(
|
|
8835
|
+
ops2,
|
|
8836
|
+
op.version ?? Math.max(this.#version, op.baseVersion + 1)
|
|
8837
|
+
);
|
|
8838
|
+
}
|
|
8839
|
+
this.#version = op.version ?? Math.max(this.#version, op.baseVersion + 1);
|
|
8840
|
+
return { modified: false };
|
|
8841
|
+
}
|
|
8842
|
+
const pending = Array.from(this.#pendingOps.values()).flat();
|
|
8843
|
+
const ops = pending.length > 0 ? rebaseTextOperations(op.ops, pending) : op.ops;
|
|
8844
|
+
return this.#applyOperations(ops, op.version ?? this.#version + 1);
|
|
8845
|
+
}
|
|
8846
|
+
insert(index, text, attributes) {
|
|
8847
|
+
const clippedIndex = Math.max(0, Math.min(index, this.length));
|
|
8848
|
+
this.#dispatch([{ type: "insert", index: clippedIndex, text, attributes }]);
|
|
8849
|
+
}
|
|
8850
|
+
delete(index, length) {
|
|
8851
|
+
const clipped = clipRange(index, length, this.length);
|
|
8852
|
+
if (clipped.length === 0) {
|
|
8853
|
+
return;
|
|
8854
|
+
}
|
|
8855
|
+
this.#dispatch([
|
|
8856
|
+
{ type: "delete", index: clipped.index, length: clipped.length }
|
|
8857
|
+
]);
|
|
8858
|
+
}
|
|
8859
|
+
replace(index, length, text, attributes) {
|
|
8860
|
+
const clipped = clipRange(index, length, this.length);
|
|
8861
|
+
const ops = [];
|
|
8862
|
+
if (clipped.length > 0) {
|
|
8863
|
+
ops.push({
|
|
8864
|
+
type: "delete",
|
|
8865
|
+
index: clipped.index,
|
|
8866
|
+
length: clipped.length
|
|
8867
|
+
});
|
|
8868
|
+
}
|
|
8869
|
+
if (text.length > 0) {
|
|
8870
|
+
ops.push({ type: "insert", index: clipped.index, text, attributes });
|
|
8871
|
+
}
|
|
8872
|
+
this.#dispatch(ops);
|
|
8873
|
+
}
|
|
8874
|
+
format(index, length, attributes) {
|
|
8875
|
+
const clipped = clipRange(index, length, this.length);
|
|
8876
|
+
if (clipped.length === 0) {
|
|
8877
|
+
return;
|
|
8878
|
+
}
|
|
8879
|
+
this.#dispatch([
|
|
8880
|
+
{
|
|
8881
|
+
type: "format",
|
|
8882
|
+
index: clipped.index,
|
|
8883
|
+
length: clipped.length,
|
|
8884
|
+
attributes
|
|
8885
|
+
}
|
|
8886
|
+
]);
|
|
8887
|
+
}
|
|
8888
|
+
#dispatch(ops) {
|
|
8889
|
+
if (ops.length === 0) {
|
|
8890
|
+
return;
|
|
8891
|
+
}
|
|
8892
|
+
this._pool?.assertStorageIsWritable();
|
|
8893
|
+
const baseVersion = this.#version;
|
|
8894
|
+
const reverse = this._pool !== void 0 && this._id !== void 0 ? this.#invertOperations(ops) : [];
|
|
8895
|
+
const changes = this.#applyOperationsLocally(ops);
|
|
8896
|
+
if (this._pool !== void 0 && this._id !== void 0) {
|
|
8897
|
+
const opId = this._pool.generateOpId();
|
|
8898
|
+
this.#pendingOps.set(opId, ops);
|
|
8899
|
+
this._pool.dispatch(
|
|
8900
|
+
[
|
|
8901
|
+
{
|
|
8902
|
+
type: OpCode.UPDATE_TEXT,
|
|
8903
|
+
id: this._id,
|
|
8904
|
+
opId,
|
|
8905
|
+
baseVersion,
|
|
8906
|
+
ops: [...ops]
|
|
8907
|
+
}
|
|
8908
|
+
],
|
|
8909
|
+
reverse,
|
|
8910
|
+
/* @__PURE__ */ new Map([
|
|
8911
|
+
[
|
|
8912
|
+
this._id,
|
|
8913
|
+
{
|
|
8914
|
+
type: "LiveText",
|
|
8915
|
+
node: this,
|
|
8916
|
+
version: this.#version,
|
|
8917
|
+
updates: changes
|
|
8918
|
+
}
|
|
8919
|
+
]
|
|
8920
|
+
])
|
|
8921
|
+
);
|
|
8922
|
+
}
|
|
8923
|
+
}
|
|
8924
|
+
#applyOperations(ops, version) {
|
|
8925
|
+
const reverse = this.#invertOperations(ops);
|
|
8926
|
+
const changes = this.#applyOperationsLocally(ops);
|
|
8927
|
+
this.#version = Math.max(this.#version, version);
|
|
8928
|
+
return {
|
|
8929
|
+
reverse,
|
|
8930
|
+
modified: {
|
|
8931
|
+
type: "LiveText",
|
|
8932
|
+
node: this,
|
|
8933
|
+
version: this.#version,
|
|
8934
|
+
updates: changes
|
|
8935
|
+
}
|
|
8936
|
+
};
|
|
8937
|
+
}
|
|
8938
|
+
#applyOperationsLocally(ops) {
|
|
8939
|
+
const changes = [];
|
|
8940
|
+
for (const op of ops) {
|
|
8941
|
+
if (op.type === "insert") {
|
|
8942
|
+
this.#segments = applyInsert(
|
|
8943
|
+
this.#segments,
|
|
8944
|
+
op.index,
|
|
8945
|
+
op.text,
|
|
8946
|
+
op.attributes
|
|
8947
|
+
);
|
|
8948
|
+
changes.push({
|
|
8949
|
+
type: "insert",
|
|
8950
|
+
index: op.index,
|
|
8951
|
+
text: op.text,
|
|
8952
|
+
attributes: op.attributes
|
|
8953
|
+
});
|
|
8954
|
+
} else if (op.type === "delete") {
|
|
8955
|
+
const result = applyDelete(this.#segments, op.index, op.length);
|
|
8956
|
+
this.#segments = result.segments;
|
|
8957
|
+
changes.push({
|
|
8958
|
+
type: "delete",
|
|
8959
|
+
index: op.index,
|
|
8960
|
+
length: op.length,
|
|
8961
|
+
deletedText: result.deletedText
|
|
8962
|
+
});
|
|
8963
|
+
} else {
|
|
8964
|
+
this.#segments = applyFormat(
|
|
8965
|
+
this.#segments,
|
|
8966
|
+
op.index,
|
|
8967
|
+
op.length,
|
|
8968
|
+
op.attributes
|
|
8969
|
+
);
|
|
8970
|
+
changes.push({
|
|
8971
|
+
type: "format",
|
|
8972
|
+
index: op.index,
|
|
8973
|
+
length: op.length,
|
|
8974
|
+
attributes: op.attributes
|
|
8975
|
+
});
|
|
8976
|
+
}
|
|
8977
|
+
}
|
|
8978
|
+
this.invalidate();
|
|
8979
|
+
return changes;
|
|
8980
|
+
}
|
|
8981
|
+
#invertOperations(ops) {
|
|
8982
|
+
return [
|
|
8983
|
+
{
|
|
8984
|
+
type: OpCode.UPDATE_TEXT,
|
|
8985
|
+
id: nn(this._id),
|
|
8986
|
+
baseVersion: this.#version,
|
|
8987
|
+
ops: invertTextOperations(this.#segments, ops)
|
|
8988
|
+
}
|
|
8989
|
+
];
|
|
8990
|
+
}
|
|
8991
|
+
toString() {
|
|
8992
|
+
return this.#segments.map((segment) => segment.text).join("");
|
|
8993
|
+
}
|
|
8994
|
+
toDelta() {
|
|
8995
|
+
return segmentsToDelta(this.#segments);
|
|
8996
|
+
}
|
|
8997
|
+
toJSON() {
|
|
8998
|
+
return super.toJSON();
|
|
8999
|
+
}
|
|
9000
|
+
/** @internal */
|
|
9001
|
+
_toJSON() {
|
|
9002
|
+
return this.toDelta();
|
|
9003
|
+
}
|
|
9004
|
+
/** @internal */
|
|
9005
|
+
_toTreeNode(key) {
|
|
9006
|
+
return {
|
|
9007
|
+
type: "LiveText",
|
|
9008
|
+
id: this._id ?? nanoid(),
|
|
9009
|
+
key,
|
|
9010
|
+
payload: [
|
|
9011
|
+
{
|
|
9012
|
+
type: "Json",
|
|
9013
|
+
id: `${this._id ?? nanoid()}:text`,
|
|
9014
|
+
key: "text",
|
|
9015
|
+
payload: this.toString()
|
|
9016
|
+
}
|
|
9017
|
+
]
|
|
9018
|
+
};
|
|
9019
|
+
}
|
|
9020
|
+
clone() {
|
|
9021
|
+
return new _LiveText(this.toDelta(), this.#version);
|
|
9022
|
+
}
|
|
9023
|
+
};
|
|
9024
|
+
|
|
8429
9025
|
// src/crdts/liveblocks-helpers.ts
|
|
8430
9026
|
function creationOpToLiveNode(op) {
|
|
8431
9027
|
return lsonToLiveNode(creationOpToLson(op));
|
|
@@ -8440,6 +9036,8 @@ function creationOpToLson(op) {
|
|
|
8440
9036
|
return new LiveMap();
|
|
8441
9037
|
case OpCode.CREATE_LIST:
|
|
8442
9038
|
return new LiveList([]);
|
|
9039
|
+
case OpCode.CREATE_TEXT:
|
|
9040
|
+
return new LiveText(op.data, op.version);
|
|
8443
9041
|
default:
|
|
8444
9042
|
return assertNever(op, "Unknown creation Op");
|
|
8445
9043
|
}
|
|
@@ -8462,6 +9060,8 @@ function deserialize(node, parentToChildren, pool) {
|
|
|
8462
9060
|
return LiveMap._deserialize(node, parentToChildren, pool);
|
|
8463
9061
|
} else if (isRegisterStorageNode(node)) {
|
|
8464
9062
|
return LiveRegister._deserialize(node, parentToChildren, pool);
|
|
9063
|
+
} else if (isTextStorageNode(node)) {
|
|
9064
|
+
return LiveText._deserialize(node, parentToChildren, pool);
|
|
8465
9065
|
} else {
|
|
8466
9066
|
throw new Error("Unexpected CRDT type");
|
|
8467
9067
|
}
|
|
@@ -8475,12 +9075,14 @@ function deserializeToLson(node, parentToChildren, pool) {
|
|
|
8475
9075
|
return LiveMap._deserialize(node, parentToChildren, pool);
|
|
8476
9076
|
} else if (isRegisterStorageNode(node)) {
|
|
8477
9077
|
return node[1].data;
|
|
9078
|
+
} else if (isTextStorageNode(node)) {
|
|
9079
|
+
return LiveText._deserialize(node, parentToChildren, pool);
|
|
8478
9080
|
} else {
|
|
8479
9081
|
throw new Error("Unexpected CRDT type");
|
|
8480
9082
|
}
|
|
8481
9083
|
}
|
|
8482
9084
|
function isLiveStructure(value) {
|
|
8483
|
-
return isLiveList(value) || isLiveMap(value) || isLiveObject(value);
|
|
9085
|
+
return isLiveList(value) || isLiveMap(value) || isLiveObject(value) || isLiveText(value);
|
|
8484
9086
|
}
|
|
8485
9087
|
function isLiveNode(value) {
|
|
8486
9088
|
return isLiveStructure(value) || isLiveRegister(value);
|
|
@@ -8494,6 +9096,9 @@ function isLiveMap(value) {
|
|
|
8494
9096
|
function isLiveObject(value) {
|
|
8495
9097
|
return value instanceof LiveObject;
|
|
8496
9098
|
}
|
|
9099
|
+
function isLiveText(value) {
|
|
9100
|
+
return value instanceof LiveText;
|
|
9101
|
+
}
|
|
8497
9102
|
function isLiveRegister(value) {
|
|
8498
9103
|
return value instanceof LiveRegister;
|
|
8499
9104
|
}
|
|
@@ -8503,14 +9108,14 @@ function cloneLson(value) {
|
|
|
8503
9108
|
function liveNodeToLson(obj) {
|
|
8504
9109
|
if (obj instanceof LiveRegister) {
|
|
8505
9110
|
return obj.data;
|
|
8506
|
-
} else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject) {
|
|
9111
|
+
} else if (obj instanceof LiveList || obj instanceof LiveMap || obj instanceof LiveObject || obj instanceof LiveText) {
|
|
8507
9112
|
return obj;
|
|
8508
9113
|
} else {
|
|
8509
9114
|
return assertNever(obj, "Unknown AbstractCrdt");
|
|
8510
9115
|
}
|
|
8511
9116
|
}
|
|
8512
9117
|
function lsonToLiveNode(value) {
|
|
8513
|
-
if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList) {
|
|
9118
|
+
if (value instanceof LiveObject || value instanceof LiveMap || value instanceof LiveList || value instanceof LiveText) {
|
|
8514
9119
|
return value;
|
|
8515
9120
|
} else {
|
|
8516
9121
|
return new LiveRegister(value);
|
|
@@ -8541,6 +9146,35 @@ function dumpPool(pool) {
|
|
|
8541
9146
|
(r) => ` ${r.id} parent=${r.parentId} key=${r.key || "\u2014"} ${r.value}`
|
|
8542
9147
|
).join("\n");
|
|
8543
9148
|
}
|
|
9149
|
+
function isJsonEq(a, b) {
|
|
9150
|
+
if (a === b) {
|
|
9151
|
+
return true;
|
|
9152
|
+
}
|
|
9153
|
+
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
|
|
9154
|
+
return false;
|
|
9155
|
+
}
|
|
9156
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
9157
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
|
|
9158
|
+
return false;
|
|
9159
|
+
}
|
|
9160
|
+
for (let i = 0; i < a.length; i++) {
|
|
9161
|
+
if (!isJsonEq(a[i], b[i])) {
|
|
9162
|
+
return false;
|
|
9163
|
+
}
|
|
9164
|
+
}
|
|
9165
|
+
return true;
|
|
9166
|
+
}
|
|
9167
|
+
const aKeys = Object.keys(a);
|
|
9168
|
+
if (aKeys.length !== Object.keys(b).length) {
|
|
9169
|
+
return false;
|
|
9170
|
+
}
|
|
9171
|
+
for (const key of aKeys) {
|
|
9172
|
+
if (!isJsonEq(a[key], b[key])) {
|
|
9173
|
+
return false;
|
|
9174
|
+
}
|
|
9175
|
+
}
|
|
9176
|
+
return true;
|
|
9177
|
+
}
|
|
8544
9178
|
function getTreesDiffOperations(currentItems, newItems) {
|
|
8545
9179
|
const ops = [];
|
|
8546
9180
|
currentItems.forEach((_, id) => {
|
|
@@ -8552,11 +9186,59 @@ function getTreesDiffOperations(currentItems, newItems) {
|
|
|
8552
9186
|
const currentCrdt = currentItems.get(id);
|
|
8553
9187
|
if (currentCrdt) {
|
|
8554
9188
|
if (crdt.type === CrdtType.OBJECT) {
|
|
8555
|
-
if (currentCrdt.type !== CrdtType.OBJECT
|
|
9189
|
+
if (currentCrdt.type !== CrdtType.OBJECT) {
|
|
9190
|
+
ops.push({ type: OpCode.UPDATE_OBJECT, id, data: crdt.data });
|
|
9191
|
+
} else {
|
|
9192
|
+
const changed = /* @__PURE__ */ new Map();
|
|
9193
|
+
for (const key of Object.keys(crdt.data)) {
|
|
9194
|
+
const value = crdt.data[key];
|
|
9195
|
+
if (value !== void 0 && !isJsonEq(value, currentCrdt.data[key])) {
|
|
9196
|
+
changed.set(key, value);
|
|
9197
|
+
}
|
|
9198
|
+
}
|
|
9199
|
+
if (changed.size > 0) {
|
|
9200
|
+
ops.push({
|
|
9201
|
+
type: OpCode.UPDATE_OBJECT,
|
|
9202
|
+
id,
|
|
9203
|
+
data: Object.fromEntries(changed)
|
|
9204
|
+
});
|
|
9205
|
+
}
|
|
9206
|
+
for (const key of Object.keys(currentCrdt.data)) {
|
|
9207
|
+
if (!(key in crdt.data)) {
|
|
9208
|
+
ops.push({ type: OpCode.DELETE_OBJECT_KEY, id, key });
|
|
9209
|
+
}
|
|
9210
|
+
}
|
|
9211
|
+
}
|
|
9212
|
+
}
|
|
9213
|
+
if (crdt.type === CrdtType.TEXT) {
|
|
9214
|
+
if (currentCrdt.type !== CrdtType.TEXT || stringifyOrLog(crdt.data) !== stringifyOrLog(currentCrdt.data) || crdt.version !== currentCrdt.version) {
|
|
8556
9215
|
ops.push({
|
|
8557
|
-
type: OpCode.
|
|
9216
|
+
type: OpCode.UPDATE_TEXT,
|
|
8558
9217
|
id,
|
|
8559
|
-
|
|
9218
|
+
baseVersion: currentCrdt.type === CrdtType.TEXT ? currentCrdt.version : 0,
|
|
9219
|
+
version: crdt.version,
|
|
9220
|
+
ops: [
|
|
9221
|
+
{
|
|
9222
|
+
type: "delete",
|
|
9223
|
+
index: 0,
|
|
9224
|
+
length: currentCrdt.type === CrdtType.TEXT ? currentCrdt.data.reduce(
|
|
9225
|
+
(sum, item) => sum + item.text.length,
|
|
9226
|
+
0
|
|
9227
|
+
) : 0
|
|
9228
|
+
},
|
|
9229
|
+
...crdt.data.map(
|
|
9230
|
+
(item, index, items) => item.attributes === void 0 ? {
|
|
9231
|
+
type: "insert",
|
|
9232
|
+
index: items.slice(0, index).reduce((sum, item2) => sum + item2.text.length, 0),
|
|
9233
|
+
text: item.text
|
|
9234
|
+
} : {
|
|
9235
|
+
type: "insert",
|
|
9236
|
+
index: items.slice(0, index).reduce((sum, item2) => sum + item2.text.length, 0),
|
|
9237
|
+
text: item.text,
|
|
9238
|
+
attributes: item.attributes
|
|
9239
|
+
}
|
|
9240
|
+
)
|
|
9241
|
+
]
|
|
8560
9242
|
});
|
|
8561
9243
|
}
|
|
8562
9244
|
}
|
|
@@ -8608,6 +9290,16 @@ function getTreesDiffOperations(currentItems, newItems) {
|
|
|
8608
9290
|
parentKey: crdt.parentKey
|
|
8609
9291
|
});
|
|
8610
9292
|
break;
|
|
9293
|
+
case CrdtType.TEXT:
|
|
9294
|
+
ops.push({
|
|
9295
|
+
type: OpCode.CREATE_TEXT,
|
|
9296
|
+
id,
|
|
9297
|
+
parentId: crdt.parentId,
|
|
9298
|
+
parentKey: crdt.parentKey,
|
|
9299
|
+
data: crdt.data,
|
|
9300
|
+
version: crdt.version
|
|
9301
|
+
});
|
|
9302
|
+
break;
|
|
8611
9303
|
}
|
|
8612
9304
|
}
|
|
8613
9305
|
});
|
|
@@ -8640,6 +9332,12 @@ function mergeListStorageUpdates(first, second) {
|
|
|
8640
9332
|
updates: updates.concat(second.updates)
|
|
8641
9333
|
};
|
|
8642
9334
|
}
|
|
9335
|
+
function mergeTextStorageUpdates(first, second) {
|
|
9336
|
+
return {
|
|
9337
|
+
...second,
|
|
9338
|
+
updates: first.updates.concat(second.updates)
|
|
9339
|
+
};
|
|
9340
|
+
}
|
|
8643
9341
|
function mergeStorageUpdates(first, second) {
|
|
8644
9342
|
if (first === void 0) {
|
|
8645
9343
|
return second;
|
|
@@ -8650,6 +9348,8 @@ function mergeStorageUpdates(first, second) {
|
|
|
8650
9348
|
return mergeMapStorageUpdates(first, second);
|
|
8651
9349
|
} else if (first.type === "LiveList" && second.type === "LiveList") {
|
|
8652
9350
|
return mergeListStorageUpdates(first, second);
|
|
9351
|
+
} else if (first.type === "LiveText" && second.type === "LiveText") {
|
|
9352
|
+
return mergeTextStorageUpdates(first, second);
|
|
8653
9353
|
} else {
|
|
8654
9354
|
}
|
|
8655
9355
|
return second;
|
|
@@ -9938,7 +10638,7 @@ function createRoom(options, config) {
|
|
|
9938
10638
|
);
|
|
9939
10639
|
output.reverse.pushLeft(applyOpResult.reverse);
|
|
9940
10640
|
}
|
|
9941
|
-
if (op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_OBJECT) {
|
|
10641
|
+
if (op.type === OpCode.CREATE_LIST || op.type === OpCode.CREATE_MAP || op.type === OpCode.CREATE_OBJECT || op.type === OpCode.CREATE_TEXT) {
|
|
9942
10642
|
createdNodeIds.add(op.id);
|
|
9943
10643
|
}
|
|
9944
10644
|
}
|
|
@@ -9958,6 +10658,7 @@ function createRoom(options, config) {
|
|
|
9958
10658
|
switch (op.type) {
|
|
9959
10659
|
case OpCode.DELETE_OBJECT_KEY:
|
|
9960
10660
|
case OpCode.UPDATE_OBJECT:
|
|
10661
|
+
case OpCode.UPDATE_TEXT:
|
|
9961
10662
|
case OpCode.DELETE_CRDT: {
|
|
9962
10663
|
const node = context.pool.nodes.get(op.id);
|
|
9963
10664
|
if (node === void 0) {
|
|
@@ -9982,6 +10683,7 @@ function createRoom(options, config) {
|
|
|
9982
10683
|
case OpCode.CREATE_OBJECT:
|
|
9983
10684
|
case OpCode.CREATE_LIST:
|
|
9984
10685
|
case OpCode.CREATE_MAP:
|
|
10686
|
+
case OpCode.CREATE_TEXT:
|
|
9985
10687
|
case OpCode.CREATE_REGISTER: {
|
|
9986
10688
|
if (op.parentId === void 0) {
|
|
9987
10689
|
return { modified: false };
|
|
@@ -12141,6 +12843,12 @@ function toPlainLson(lson) {
|
|
|
12141
12843
|
liveblocksType: "LiveList",
|
|
12142
12844
|
data: [...lson].map((item) => toPlainLson(item))
|
|
12143
12845
|
};
|
|
12846
|
+
} else if (lson instanceof LiveText) {
|
|
12847
|
+
return {
|
|
12848
|
+
liveblocksType: "LiveText",
|
|
12849
|
+
data: lson.toDelta(),
|
|
12850
|
+
version: lson.version
|
|
12851
|
+
};
|
|
12144
12852
|
} else {
|
|
12145
12853
|
return lson;
|
|
12146
12854
|
}
|
|
@@ -12322,6 +13030,7 @@ export {
|
|
|
12322
13030
|
LiveList,
|
|
12323
13031
|
LiveMap,
|
|
12324
13032
|
LiveObject,
|
|
13033
|
+
LiveText,
|
|
12325
13034
|
LiveblocksError,
|
|
12326
13035
|
MENTION_CHARACTER,
|
|
12327
13036
|
MutableSignal,
|
|
@@ -12333,6 +13042,7 @@ export {
|
|
|
12333
13042
|
SortedList,
|
|
12334
13043
|
TextEditorType,
|
|
12335
13044
|
WebsocketCloseCodes,
|
|
13045
|
+
applyLiveTextOperations,
|
|
12336
13046
|
asPos,
|
|
12337
13047
|
assert,
|
|
12338
13048
|
assertNever,
|
|
@@ -12388,6 +13098,7 @@ export {
|
|
|
12388
13098
|
isRegisterStorageNode,
|
|
12389
13099
|
isRootStorageNode,
|
|
12390
13100
|
isStartsWithOperator,
|
|
13101
|
+
isTextStorageNode,
|
|
12391
13102
|
isUrl,
|
|
12392
13103
|
kInternal,
|
|
12393
13104
|
keys,
|