- Add type-to-trigger Spotlight with keyboard (any character) - Add canvas click to open Spotlight - Implement keyboard navigation (↑↓ Enter Esc) - Add keyboard shortcut handlers and spotlight store - Create useSpotlight hook with fuzzy search - Create mock Kubernetes resources for initial testing - Implement krate creation with collision detection - Add Quick Actions (all pods, services, deployments, namespaces) - Create Spotlight with filter chips and result rendering - Add Spotlight state management with setQuery, setFilter, setSel - Include design specs (Krates.dc.html, server.js, support.js)
9631 lines
268 KiB
JavaScript
9631 lines
268 KiB
JavaScript
import {
|
||
__publicField
|
||
} from "./chunk-EQCVQC35.js";
|
||
|
||
// node_modules/lib0/map.js
|
||
var create = () => /* @__PURE__ */ new Map();
|
||
var copy = (m) => {
|
||
const r = create();
|
||
m.forEach((v, k) => {
|
||
r.set(k, v);
|
||
});
|
||
return r;
|
||
};
|
||
var setIfUndefined = (map3, key, createT) => {
|
||
let set = map3.get(key);
|
||
if (set === void 0) {
|
||
map3.set(key, set = createT());
|
||
}
|
||
return set;
|
||
};
|
||
var map = (m, f) => {
|
||
const res = [];
|
||
for (const [key, value] of m) {
|
||
res.push(f(value, key));
|
||
}
|
||
return res;
|
||
};
|
||
var any = (m, f) => {
|
||
for (const [key, value] of m) {
|
||
if (f(value, key)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
|
||
// node_modules/lib0/set.js
|
||
var create2 = () => /* @__PURE__ */ new Set();
|
||
|
||
// node_modules/lib0/array.js
|
||
var last = (arr) => arr[arr.length - 1];
|
||
var appendTo = (dest, src) => {
|
||
for (let i = 0; i < src.length; i++) {
|
||
dest.push(src[i]);
|
||
}
|
||
};
|
||
var from2 = Array.from;
|
||
var every = (arr, f) => {
|
||
for (let i = 0; i < arr.length; i++) {
|
||
if (!f(arr[i], i, arr)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
var some = (arr, f) => {
|
||
for (let i = 0; i < arr.length; i++) {
|
||
if (f(arr[i], i, arr)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
var unfold = (len, f) => {
|
||
const array = new Array(len);
|
||
for (let i = 0; i < len; i++) {
|
||
array[i] = f(i, array);
|
||
}
|
||
return array;
|
||
};
|
||
var isArray = Array.isArray;
|
||
|
||
// node_modules/lib0/observable.js
|
||
var ObservableV2 = class {
|
||
constructor() {
|
||
this._observers = create();
|
||
}
|
||
/**
|
||
* @template {keyof EVENTS & string} NAME
|
||
* @param {NAME} name
|
||
* @param {EVENTS[NAME]} f
|
||
*/
|
||
on(name, f) {
|
||
setIfUndefined(
|
||
this._observers,
|
||
/** @type {string} */
|
||
name,
|
||
create2
|
||
).add(f);
|
||
return f;
|
||
}
|
||
/**
|
||
* @template {keyof EVENTS & string} NAME
|
||
* @param {NAME} name
|
||
* @param {EVENTS[NAME]} f
|
||
*/
|
||
once(name, f) {
|
||
const _f = (...args2) => {
|
||
this.off(
|
||
name,
|
||
/** @type {any} */
|
||
_f
|
||
);
|
||
f(...args2);
|
||
};
|
||
this.on(
|
||
name,
|
||
/** @type {any} */
|
||
_f
|
||
);
|
||
}
|
||
/**
|
||
* @template {keyof EVENTS & string} NAME
|
||
* @param {NAME} name
|
||
* @param {EVENTS[NAME]} f
|
||
*/
|
||
off(name, f) {
|
||
const observers = this._observers.get(name);
|
||
if (observers !== void 0) {
|
||
observers.delete(f);
|
||
if (observers.size === 0) {
|
||
this._observers.delete(name);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Emit a named event. All registered event listeners that listen to the
|
||
* specified name will receive the event.
|
||
*
|
||
* @todo This should catch exceptions
|
||
*
|
||
* @template {keyof EVENTS & string} NAME
|
||
* @param {NAME} name The event name.
|
||
* @param {Parameters<EVENTS[NAME]>} args The arguments that are applied to the event listener.
|
||
*/
|
||
emit(name, args2) {
|
||
return from2((this._observers.get(name) || create()).values()).forEach((f) => f(...args2));
|
||
}
|
||
destroy() {
|
||
this._observers = create();
|
||
}
|
||
};
|
||
|
||
// node_modules/lib0/math.js
|
||
var floor = Math.floor;
|
||
var abs = Math.abs;
|
||
var min = (a, b) => a < b ? a : b;
|
||
var max = (a, b) => a > b ? a : b;
|
||
var isNaN = Number.isNaN;
|
||
var isNegativeZero = (n) => n !== 0 ? n < 0 : 1 / n < 0;
|
||
|
||
// node_modules/lib0/binary.js
|
||
var BIT1 = 1;
|
||
var BIT2 = 2;
|
||
var BIT3 = 4;
|
||
var BIT4 = 8;
|
||
var BIT6 = 32;
|
||
var BIT7 = 64;
|
||
var BIT8 = 128;
|
||
var BIT18 = 1 << 17;
|
||
var BIT19 = 1 << 18;
|
||
var BIT20 = 1 << 19;
|
||
var BIT21 = 1 << 20;
|
||
var BIT22 = 1 << 21;
|
||
var BIT23 = 1 << 22;
|
||
var BIT24 = 1 << 23;
|
||
var BIT25 = 1 << 24;
|
||
var BIT26 = 1 << 25;
|
||
var BIT27 = 1 << 26;
|
||
var BIT28 = 1 << 27;
|
||
var BIT29 = 1 << 28;
|
||
var BIT30 = 1 << 29;
|
||
var BIT31 = 1 << 30;
|
||
var BIT32 = 1 << 31;
|
||
var BITS5 = 31;
|
||
var BITS6 = 63;
|
||
var BITS7 = 127;
|
||
var BITS17 = BIT18 - 1;
|
||
var BITS18 = BIT19 - 1;
|
||
var BITS19 = BIT20 - 1;
|
||
var BITS20 = BIT21 - 1;
|
||
var BITS21 = BIT22 - 1;
|
||
var BITS22 = BIT23 - 1;
|
||
var BITS23 = BIT24 - 1;
|
||
var BITS24 = BIT25 - 1;
|
||
var BITS25 = BIT26 - 1;
|
||
var BITS26 = BIT27 - 1;
|
||
var BITS27 = BIT28 - 1;
|
||
var BITS28 = BIT29 - 1;
|
||
var BITS29 = BIT30 - 1;
|
||
var BITS30 = BIT31 - 1;
|
||
var BITS31 = 2147483647;
|
||
|
||
// node_modules/lib0/number.js
|
||
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
|
||
var MIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER;
|
||
var LOWEST_INT32 = 1 << 31;
|
||
var isInteger = Number.isInteger || ((num) => typeof num === "number" && isFinite(num) && floor(num) === num);
|
||
var isNaN2 = Number.isNaN;
|
||
var parseInt = Number.parseInt;
|
||
|
||
// node_modules/lib0/string.js
|
||
var fromCharCode = String.fromCharCode;
|
||
var fromCodePoint = String.fromCodePoint;
|
||
var MAX_UTF16_CHARACTER = fromCharCode(65535);
|
||
var toLowerCase = (s) => s.toLowerCase();
|
||
var trimLeftRegex = /^\s*/g;
|
||
var trimLeft = (s) => s.replace(trimLeftRegex, "");
|
||
var fromCamelCaseRegex = /([A-Z])/g;
|
||
var fromCamelCase = (s, separator) => trimLeft(s.replace(fromCamelCaseRegex, (match2) => `${separator}${toLowerCase(match2)}`));
|
||
var _encodeUtf8Polyfill = (str) => {
|
||
const encodedString = unescape(encodeURIComponent(str));
|
||
const len = encodedString.length;
|
||
const buf = new Uint8Array(len);
|
||
for (let i = 0; i < len; i++) {
|
||
buf[i] = /** @type {number} */
|
||
encodedString.codePointAt(i);
|
||
}
|
||
return buf;
|
||
};
|
||
var utf8TextEncoder = (
|
||
/** @type {TextEncoder} */
|
||
typeof TextEncoder !== "undefined" ? new TextEncoder() : null
|
||
);
|
||
var _encodeUtf8Native = (str) => utf8TextEncoder.encode(str);
|
||
var encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill;
|
||
var utf8TextDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
||
if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
|
||
utf8TextDecoder = null;
|
||
}
|
||
var repeat = (source, n) => unfold(n, () => source).join("");
|
||
|
||
// node_modules/lib0/encoding.js
|
||
var Encoder = class {
|
||
constructor() {
|
||
this.cpos = 0;
|
||
this.cbuf = new Uint8Array(100);
|
||
this.bufs = [];
|
||
}
|
||
};
|
||
var createEncoder = () => new Encoder();
|
||
var length = (encoder) => {
|
||
let len = encoder.cpos;
|
||
for (let i = 0; i < encoder.bufs.length; i++) {
|
||
len += encoder.bufs[i].length;
|
||
}
|
||
return len;
|
||
};
|
||
var toUint8Array = (encoder) => {
|
||
const uint8arr = new Uint8Array(length(encoder));
|
||
let curPos = 0;
|
||
for (let i = 0; i < encoder.bufs.length; i++) {
|
||
const d = encoder.bufs[i];
|
||
uint8arr.set(d, curPos);
|
||
curPos += d.length;
|
||
}
|
||
uint8arr.set(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
|
||
return uint8arr;
|
||
};
|
||
var verifyLen = (encoder, len) => {
|
||
const bufferLen = encoder.cbuf.length;
|
||
if (bufferLen - encoder.cpos < len) {
|
||
encoder.bufs.push(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos));
|
||
encoder.cbuf = new Uint8Array(max(bufferLen, len) * 2);
|
||
encoder.cpos = 0;
|
||
}
|
||
};
|
||
var write = (encoder, num) => {
|
||
const bufferLen = encoder.cbuf.length;
|
||
if (encoder.cpos === bufferLen) {
|
||
encoder.bufs.push(encoder.cbuf);
|
||
encoder.cbuf = new Uint8Array(bufferLen * 2);
|
||
encoder.cpos = 0;
|
||
}
|
||
encoder.cbuf[encoder.cpos++] = num;
|
||
};
|
||
var writeUint8 = write;
|
||
var writeVarUint = (encoder, num) => {
|
||
while (num > BITS7) {
|
||
write(encoder, BIT8 | BITS7 & num);
|
||
num = floor(num / 128);
|
||
}
|
||
write(encoder, BITS7 & num);
|
||
};
|
||
var writeVarInt = (encoder, num) => {
|
||
const isNegative = isNegativeZero(num);
|
||
if (isNegative) {
|
||
num = -num;
|
||
}
|
||
write(encoder, (num > BITS6 ? BIT8 : 0) | (isNegative ? BIT7 : 0) | BITS6 & num);
|
||
num = floor(num / 64);
|
||
while (num > 0) {
|
||
write(encoder, (num > BITS7 ? BIT8 : 0) | BITS7 & num);
|
||
num = floor(num / 128);
|
||
}
|
||
};
|
||
var _strBuffer = new Uint8Array(3e4);
|
||
var _maxStrBSize = _strBuffer.length / 3;
|
||
var _writeVarStringNative = (encoder, str) => {
|
||
if (str.length < _maxStrBSize) {
|
||
const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
|
||
writeVarUint(encoder, written);
|
||
for (let i = 0; i < written; i++) {
|
||
write(encoder, _strBuffer[i]);
|
||
}
|
||
} else {
|
||
writeVarUint8Array(encoder, encodeUtf8(str));
|
||
}
|
||
};
|
||
var _writeVarStringPolyfill = (encoder, str) => {
|
||
const encodedString = unescape(encodeURIComponent(str));
|
||
const len = encodedString.length;
|
||
writeVarUint(encoder, len);
|
||
for (let i = 0; i < len; i++) {
|
||
write(
|
||
encoder,
|
||
/** @type {number} */
|
||
encodedString.codePointAt(i)
|
||
);
|
||
}
|
||
};
|
||
var writeVarString = utf8TextEncoder && /** @type {any} */
|
||
utf8TextEncoder.encodeInto ? _writeVarStringNative : _writeVarStringPolyfill;
|
||
var writeBinaryEncoder = (encoder, append2) => writeUint8Array(encoder, toUint8Array(append2));
|
||
var writeUint8Array = (encoder, uint8Array) => {
|
||
const bufferLen = encoder.cbuf.length;
|
||
const cpos = encoder.cpos;
|
||
const leftCopyLen = min(bufferLen - cpos, uint8Array.length);
|
||
const rightCopyLen = uint8Array.length - leftCopyLen;
|
||
encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
|
||
encoder.cpos += leftCopyLen;
|
||
if (rightCopyLen > 0) {
|
||
encoder.bufs.push(encoder.cbuf);
|
||
encoder.cbuf = new Uint8Array(max(bufferLen * 2, rightCopyLen));
|
||
encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
|
||
encoder.cpos = rightCopyLen;
|
||
}
|
||
};
|
||
var writeVarUint8Array = (encoder, uint8Array) => {
|
||
writeVarUint(encoder, uint8Array.byteLength);
|
||
writeUint8Array(encoder, uint8Array);
|
||
};
|
||
var writeOnDataView = (encoder, len) => {
|
||
verifyLen(encoder, len);
|
||
const dview = new DataView(encoder.cbuf.buffer, encoder.cpos, len);
|
||
encoder.cpos += len;
|
||
return dview;
|
||
};
|
||
var writeFloat32 = (encoder, num) => writeOnDataView(encoder, 4).setFloat32(0, num, false);
|
||
var writeFloat64 = (encoder, num) => writeOnDataView(encoder, 8).setFloat64(0, num, false);
|
||
var writeBigInt64 = (encoder, num) => (
|
||
/** @type {any} */
|
||
writeOnDataView(encoder, 8).setBigInt64(0, num, false)
|
||
);
|
||
var floatTestBed = new DataView(new ArrayBuffer(4));
|
||
var isFloat32 = (num) => {
|
||
floatTestBed.setFloat32(0, num);
|
||
return floatTestBed.getFloat32(0) === num;
|
||
};
|
||
var writeAny = (encoder, data) => {
|
||
switch (typeof data) {
|
||
case "string":
|
||
write(encoder, 119);
|
||
writeVarString(encoder, data);
|
||
break;
|
||
case "number":
|
||
if (isInteger(data) && abs(data) <= BITS31) {
|
||
write(encoder, 125);
|
||
writeVarInt(encoder, data);
|
||
} else if (isFloat32(data)) {
|
||
write(encoder, 124);
|
||
writeFloat32(encoder, data);
|
||
} else {
|
||
write(encoder, 123);
|
||
writeFloat64(encoder, data);
|
||
}
|
||
break;
|
||
case "bigint":
|
||
write(encoder, 122);
|
||
writeBigInt64(encoder, data);
|
||
break;
|
||
case "object":
|
||
if (data === null) {
|
||
write(encoder, 126);
|
||
} else if (isArray(data)) {
|
||
write(encoder, 117);
|
||
writeVarUint(encoder, data.length);
|
||
for (let i = 0; i < data.length; i++) {
|
||
writeAny(encoder, data[i]);
|
||
}
|
||
} else if (data instanceof Uint8Array) {
|
||
write(encoder, 116);
|
||
writeVarUint8Array(encoder, data);
|
||
} else {
|
||
write(encoder, 118);
|
||
const keys2 = Object.keys(data);
|
||
writeVarUint(encoder, keys2.length);
|
||
for (let i = 0; i < keys2.length; i++) {
|
||
const key = keys2[i];
|
||
writeVarString(encoder, key);
|
||
writeAny(encoder, data[key]);
|
||
}
|
||
}
|
||
break;
|
||
case "boolean":
|
||
write(encoder, data ? 120 : 121);
|
||
break;
|
||
default:
|
||
write(encoder, 127);
|
||
}
|
||
};
|
||
var RleEncoder = class extends Encoder {
|
||
/**
|
||
* @param {function(Encoder, T):void} writer
|
||
*/
|
||
constructor(writer) {
|
||
super();
|
||
this.w = writer;
|
||
this.s = null;
|
||
this.count = 0;
|
||
}
|
||
/**
|
||
* @param {T} v
|
||
*/
|
||
write(v) {
|
||
if (this.s === v) {
|
||
this.count++;
|
||
} else {
|
||
if (this.count > 0) {
|
||
writeVarUint(this, this.count - 1);
|
||
}
|
||
this.count = 1;
|
||
this.w(this, v);
|
||
this.s = v;
|
||
}
|
||
}
|
||
};
|
||
var flushUintOptRleEncoder = (encoder) => {
|
||
if (encoder.count > 0) {
|
||
writeVarInt(encoder.encoder, encoder.count === 1 ? encoder.s : -encoder.s);
|
||
if (encoder.count > 1) {
|
||
writeVarUint(encoder.encoder, encoder.count - 2);
|
||
}
|
||
}
|
||
};
|
||
var UintOptRleEncoder = class {
|
||
constructor() {
|
||
this.encoder = new Encoder();
|
||
this.s = 0;
|
||
this.count = 0;
|
||
}
|
||
/**
|
||
* @param {number} v
|
||
*/
|
||
write(v) {
|
||
if (this.s === v) {
|
||
this.count++;
|
||
} else {
|
||
flushUintOptRleEncoder(this);
|
||
this.count = 1;
|
||
this.s = v;
|
||
}
|
||
}
|
||
/**
|
||
* Flush the encoded state and transform this to a Uint8Array.
|
||
*
|
||
* Note that this should only be called once.
|
||
*/
|
||
toUint8Array() {
|
||
flushUintOptRleEncoder(this);
|
||
return toUint8Array(this.encoder);
|
||
}
|
||
};
|
||
var flushIntDiffOptRleEncoder = (encoder) => {
|
||
if (encoder.count > 0) {
|
||
const encodedDiff = encoder.diff * 2 + (encoder.count === 1 ? 0 : 1);
|
||
writeVarInt(encoder.encoder, encodedDiff);
|
||
if (encoder.count > 1) {
|
||
writeVarUint(encoder.encoder, encoder.count - 2);
|
||
}
|
||
}
|
||
};
|
||
var IntDiffOptRleEncoder = class {
|
||
constructor() {
|
||
this.encoder = new Encoder();
|
||
this.s = 0;
|
||
this.count = 0;
|
||
this.diff = 0;
|
||
}
|
||
/**
|
||
* @param {number} v
|
||
*/
|
||
write(v) {
|
||
if (this.diff === v - this.s) {
|
||
this.s = v;
|
||
this.count++;
|
||
} else {
|
||
flushIntDiffOptRleEncoder(this);
|
||
this.count = 1;
|
||
this.diff = v - this.s;
|
||
this.s = v;
|
||
}
|
||
}
|
||
/**
|
||
* Flush the encoded state and transform this to a Uint8Array.
|
||
*
|
||
* Note that this should only be called once.
|
||
*/
|
||
toUint8Array() {
|
||
flushIntDiffOptRleEncoder(this);
|
||
return toUint8Array(this.encoder);
|
||
}
|
||
};
|
||
var StringEncoder = class {
|
||
constructor() {
|
||
this.sarr = [];
|
||
this.s = "";
|
||
this.lensE = new UintOptRleEncoder();
|
||
}
|
||
/**
|
||
* @param {string} string
|
||
*/
|
||
write(string) {
|
||
this.s += string;
|
||
if (this.s.length > 19) {
|
||
this.sarr.push(this.s);
|
||
this.s = "";
|
||
}
|
||
this.lensE.write(string.length);
|
||
}
|
||
toUint8Array() {
|
||
const encoder = new Encoder();
|
||
this.sarr.push(this.s);
|
||
this.s = "";
|
||
writeVarString(encoder, this.sarr.join(""));
|
||
writeUint8Array(encoder, this.lensE.toUint8Array());
|
||
return toUint8Array(encoder);
|
||
}
|
||
};
|
||
|
||
// node_modules/lib0/error.js
|
||
var create3 = (s) => new Error(s);
|
||
var methodUnimplemented = () => {
|
||
throw create3("Method unimplemented");
|
||
};
|
||
var unexpectedCase = () => {
|
||
throw create3("Unexpected case");
|
||
};
|
||
|
||
// node_modules/lib0/decoding.js
|
||
var errorUnexpectedEndOfArray = create3("Unexpected end of array");
|
||
var errorIntegerOutOfRange = create3("Integer out of Range");
|
||
var Decoder = class {
|
||
/**
|
||
* @param {Uint8Array<Buf>} uint8Array Binary data to decode
|
||
*/
|
||
constructor(uint8Array) {
|
||
this.arr = uint8Array;
|
||
this.pos = 0;
|
||
}
|
||
};
|
||
var createDecoder = (uint8Array) => new Decoder(uint8Array);
|
||
var hasContent = (decoder) => decoder.pos !== decoder.arr.length;
|
||
var readUint8Array = (decoder, len) => {
|
||
const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
|
||
decoder.pos += len;
|
||
return view;
|
||
};
|
||
var readVarUint8Array = (decoder) => readUint8Array(decoder, readVarUint(decoder));
|
||
var readUint8 = (decoder) => decoder.arr[decoder.pos++];
|
||
var readVarUint = (decoder) => {
|
||
let num = 0;
|
||
let mult = 1;
|
||
const len = decoder.arr.length;
|
||
while (decoder.pos < len) {
|
||
const r = decoder.arr[decoder.pos++];
|
||
num = num + (r & BITS7) * mult;
|
||
mult *= 128;
|
||
if (r < BIT8) {
|
||
return num;
|
||
}
|
||
if (num > MAX_SAFE_INTEGER) {
|
||
throw errorIntegerOutOfRange;
|
||
}
|
||
}
|
||
throw errorUnexpectedEndOfArray;
|
||
};
|
||
var readVarInt = (decoder) => {
|
||
let r = decoder.arr[decoder.pos++];
|
||
let num = r & BITS6;
|
||
let mult = 64;
|
||
const sign = (r & BIT7) > 0 ? -1 : 1;
|
||
if ((r & BIT8) === 0) {
|
||
return sign * num;
|
||
}
|
||
const len = decoder.arr.length;
|
||
while (decoder.pos < len) {
|
||
r = decoder.arr[decoder.pos++];
|
||
num = num + (r & BITS7) * mult;
|
||
mult *= 128;
|
||
if (r < BIT8) {
|
||
return sign * num;
|
||
}
|
||
if (num > MAX_SAFE_INTEGER) {
|
||
throw errorIntegerOutOfRange;
|
||
}
|
||
}
|
||
throw errorUnexpectedEndOfArray;
|
||
};
|
||
var _readVarStringPolyfill = (decoder) => {
|
||
let remainingLen = readVarUint(decoder);
|
||
if (remainingLen === 0) {
|
||
return "";
|
||
} else {
|
||
let encodedString = String.fromCodePoint(readUint8(decoder));
|
||
if (--remainingLen < 100) {
|
||
while (remainingLen--) {
|
||
encodedString += String.fromCodePoint(readUint8(decoder));
|
||
}
|
||
} else {
|
||
while (remainingLen > 0) {
|
||
const nextLen = remainingLen < 1e4 ? remainingLen : 1e4;
|
||
const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen);
|
||
decoder.pos += nextLen;
|
||
encodedString += String.fromCodePoint.apply(
|
||
null,
|
||
/** @type {any} */
|
||
bytes
|
||
);
|
||
remainingLen -= nextLen;
|
||
}
|
||
}
|
||
return decodeURIComponent(escape(encodedString));
|
||
}
|
||
};
|
||
var _readVarStringNative = (decoder) => (
|
||
/** @type any */
|
||
utf8TextDecoder.decode(readVarUint8Array(decoder))
|
||
);
|
||
var readVarString = utf8TextDecoder ? _readVarStringNative : _readVarStringPolyfill;
|
||
var readFromDataView = (decoder, len) => {
|
||
const dv = new DataView(decoder.arr.buffer, decoder.arr.byteOffset + decoder.pos, len);
|
||
decoder.pos += len;
|
||
return dv;
|
||
};
|
||
var readFloat32 = (decoder) => readFromDataView(decoder, 4).getFloat32(0, false);
|
||
var readFloat64 = (decoder) => readFromDataView(decoder, 8).getFloat64(0, false);
|
||
var readBigInt64 = (decoder) => (
|
||
/** @type {any} */
|
||
readFromDataView(decoder, 8).getBigInt64(0, false)
|
||
);
|
||
var readAnyLookupTable = [
|
||
(decoder) => void 0,
|
||
// CASE 127: undefined
|
||
(decoder) => null,
|
||
// CASE 126: null
|
||
readVarInt,
|
||
// CASE 125: integer
|
||
readFloat32,
|
||
// CASE 124: float32
|
||
readFloat64,
|
||
// CASE 123: float64
|
||
readBigInt64,
|
||
// CASE 122: bigint
|
||
(decoder) => false,
|
||
// CASE 121: boolean (false)
|
||
(decoder) => true,
|
||
// CASE 120: boolean (true)
|
||
readVarString,
|
||
// CASE 119: string
|
||
(decoder) => {
|
||
const len = readVarUint(decoder);
|
||
const obj = {};
|
||
for (let i = 0; i < len; i++) {
|
||
const key = readVarString(decoder);
|
||
obj[key] = readAny(decoder);
|
||
}
|
||
return obj;
|
||
},
|
||
(decoder) => {
|
||
const len = readVarUint(decoder);
|
||
const arr = [];
|
||
for (let i = 0; i < len; i++) {
|
||
arr.push(readAny(decoder));
|
||
}
|
||
return arr;
|
||
},
|
||
readVarUint8Array
|
||
// CASE 116: Uint8Array
|
||
];
|
||
var readAny = (decoder) => readAnyLookupTable[127 - readUint8(decoder)](decoder);
|
||
var RleDecoder = class extends Decoder {
|
||
/**
|
||
* @param {Uint8Array} uint8Array
|
||
* @param {function(Decoder):T} reader
|
||
*/
|
||
constructor(uint8Array, reader) {
|
||
super(uint8Array);
|
||
this.reader = reader;
|
||
this.s = null;
|
||
this.count = 0;
|
||
}
|
||
read() {
|
||
if (this.count === 0) {
|
||
this.s = this.reader(this);
|
||
if (hasContent(this)) {
|
||
this.count = readVarUint(this) + 1;
|
||
} else {
|
||
this.count = -1;
|
||
}
|
||
}
|
||
this.count--;
|
||
return (
|
||
/** @type {T} */
|
||
this.s
|
||
);
|
||
}
|
||
};
|
||
var UintOptRleDecoder = class extends Decoder {
|
||
/**
|
||
* @param {Uint8Array} uint8Array
|
||
*/
|
||
constructor(uint8Array) {
|
||
super(uint8Array);
|
||
this.s = 0;
|
||
this.count = 0;
|
||
}
|
||
read() {
|
||
if (this.count === 0) {
|
||
this.s = readVarInt(this);
|
||
const isNegative = isNegativeZero(this.s);
|
||
this.count = 1;
|
||
if (isNegative) {
|
||
this.s = -this.s;
|
||
this.count = readVarUint(this) + 2;
|
||
}
|
||
}
|
||
this.count--;
|
||
return (
|
||
/** @type {number} */
|
||
this.s
|
||
);
|
||
}
|
||
};
|
||
var IntDiffOptRleDecoder = class extends Decoder {
|
||
/**
|
||
* @param {Uint8Array} uint8Array
|
||
*/
|
||
constructor(uint8Array) {
|
||
super(uint8Array);
|
||
this.s = 0;
|
||
this.count = 0;
|
||
this.diff = 0;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
read() {
|
||
if (this.count === 0) {
|
||
const diff = readVarInt(this);
|
||
const hasCount = diff & 1;
|
||
this.diff = floor(diff / 2);
|
||
this.count = 1;
|
||
if (hasCount) {
|
||
this.count = readVarUint(this) + 2;
|
||
}
|
||
}
|
||
this.s += this.diff;
|
||
this.count--;
|
||
return this.s;
|
||
}
|
||
};
|
||
var StringDecoder = class {
|
||
/**
|
||
* @param {Uint8Array} uint8Array
|
||
*/
|
||
constructor(uint8Array) {
|
||
this.decoder = new UintOptRleDecoder(uint8Array);
|
||
this.str = readVarString(this.decoder);
|
||
this.spos = 0;
|
||
}
|
||
/**
|
||
* @return {string}
|
||
*/
|
||
read() {
|
||
const end = this.spos + this.decoder.read();
|
||
const res = this.str.slice(this.spos, end);
|
||
this.spos = end;
|
||
return res;
|
||
}
|
||
};
|
||
|
||
// node_modules/lib0/webcrypto.js
|
||
var subtle = crypto.subtle;
|
||
var getRandomValues = crypto.getRandomValues.bind(crypto);
|
||
|
||
// node_modules/lib0/random.js
|
||
var uint32 = () => getRandomValues(new Uint32Array(1))[0];
|
||
var uuidv4Template = "10000000-1000-4000-8000" + -1e11;
|
||
var uuidv4 = () => uuidv4Template.replace(
|
||
/[018]/g,
|
||
/** @param {number} c */
|
||
(c) => (c ^ uint32() & 15 >> c / 4).toString(16)
|
||
);
|
||
|
||
// node_modules/lib0/time.js
|
||
var getUnixTime = Date.now;
|
||
|
||
// node_modules/lib0/promise.js
|
||
var create4 = (f) => (
|
||
/** @type {Promise<T>} */
|
||
new Promise(f)
|
||
);
|
||
var all = Promise.all.bind(Promise);
|
||
|
||
// node_modules/lib0/conditions.js
|
||
var undefinedToNull = (v) => v === void 0 ? null : v;
|
||
|
||
// node_modules/lib0/storage.js
|
||
var VarStoragePolyfill = class {
|
||
constructor() {
|
||
this.map = /* @__PURE__ */ new Map();
|
||
}
|
||
/**
|
||
* @param {string} key
|
||
* @param {any} newValue
|
||
*/
|
||
setItem(key, newValue) {
|
||
this.map.set(key, newValue);
|
||
}
|
||
/**
|
||
* @param {string} key
|
||
*/
|
||
getItem(key) {
|
||
return this.map.get(key);
|
||
}
|
||
};
|
||
var _localStorage = new VarStoragePolyfill();
|
||
var usePolyfill = true;
|
||
try {
|
||
if (typeof localStorage !== "undefined" && localStorage) {
|
||
_localStorage = localStorage;
|
||
usePolyfill = false;
|
||
}
|
||
} catch (e) {
|
||
}
|
||
var varStorage = _localStorage;
|
||
|
||
// node_modules/lib0/trait/equality.js
|
||
var EqualityTraitSymbol = Symbol("Equality");
|
||
var equals = (a, b) => {
|
||
var _a;
|
||
return a === b || !!((_a = a == null ? void 0 : a[EqualityTraitSymbol]) == null ? void 0 : _a.call(a, b)) || false;
|
||
};
|
||
|
||
// node_modules/lib0/object.js
|
||
var isObject = (o) => typeof o === "object";
|
||
var assign = Object.assign;
|
||
var keys = Object.keys;
|
||
var forEach = (obj, f) => {
|
||
for (const key in obj) {
|
||
f(obj[key], key);
|
||
}
|
||
};
|
||
var size = (obj) => keys(obj).length;
|
||
var isEmpty = (obj) => {
|
||
for (const _k in obj) {
|
||
return false;
|
||
}
|
||
return true;
|
||
};
|
||
var every2 = (obj, f) => {
|
||
for (const key in obj) {
|
||
if (!f(obj[key], key)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
var hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
||
var equalFlat = (a, b) => a === b || size(a) === size(b) && every2(a, (val, key) => (val !== void 0 || hasProperty(b, key)) && equals(b[key], val));
|
||
var freeze = Object.freeze;
|
||
var deepFreeze = (o) => {
|
||
for (const key in o) {
|
||
const c = o[key];
|
||
if (typeof c === "object" || typeof c === "function") {
|
||
deepFreeze(o[key]);
|
||
}
|
||
}
|
||
return freeze(o);
|
||
};
|
||
|
||
// node_modules/lib0/function.js
|
||
var callAll = (fs, args2, i = 0) => {
|
||
try {
|
||
for (; i < fs.length; i++) {
|
||
fs[i](...args2);
|
||
}
|
||
} finally {
|
||
if (i < fs.length) {
|
||
callAll(fs, args2, i + 1);
|
||
}
|
||
}
|
||
};
|
||
var id = (a) => a;
|
||
var equalityDeep = (a, b) => {
|
||
if (a === b) {
|
||
return true;
|
||
}
|
||
if (a == null || b == null || a.constructor !== b.constructor && (a.constructor || Object) !== (b.constructor || Object)) {
|
||
return false;
|
||
}
|
||
if (a[EqualityTraitSymbol] != null) {
|
||
return a[EqualityTraitSymbol](b);
|
||
}
|
||
switch (a.constructor) {
|
||
case ArrayBuffer:
|
||
a = new Uint8Array(a);
|
||
b = new Uint8Array(b);
|
||
case Uint8Array: {
|
||
if (a.byteLength !== b.byteLength) {
|
||
return false;
|
||
}
|
||
for (let i = 0; i < a.length; i++) {
|
||
if (a[i] !== b[i]) {
|
||
return false;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case Set: {
|
||
if (a.size !== b.size) {
|
||
return false;
|
||
}
|
||
for (const value of a) {
|
||
if (!b.has(value)) {
|
||
return false;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case Map: {
|
||
if (a.size !== b.size) {
|
||
return false;
|
||
}
|
||
for (const key of a.keys()) {
|
||
if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
|
||
return false;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case void 0:
|
||
case Object:
|
||
if (size(a) !== size(b)) {
|
||
return false;
|
||
}
|
||
for (const key in a) {
|
||
if (!hasProperty(a, key) || !equalityDeep(a[key], b[key])) {
|
||
return false;
|
||
}
|
||
}
|
||
break;
|
||
case Array:
|
||
if (a.length !== b.length) {
|
||
return false;
|
||
}
|
||
for (let i = 0; i < a.length; i++) {
|
||
if (!equalityDeep(a[i], b[i])) {
|
||
return false;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
return false;
|
||
}
|
||
return true;
|
||
};
|
||
var isOneOf = (value, options) => options.includes(value);
|
||
|
||
// node_modules/lib0/environment.js
|
||
var isNode = typeof process !== "undefined" && process.release && /node|io\.js/.test(process.release.name) && Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]";
|
||
var isMac = typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
|
||
var params;
|
||
var args = [];
|
||
var computeParams = () => {
|
||
if (params === void 0) {
|
||
if (isNode) {
|
||
params = create();
|
||
const pargs = process.argv;
|
||
let currParamName = null;
|
||
for (let i = 0; i < pargs.length; i++) {
|
||
const parg = pargs[i];
|
||
if (parg[0] === "-") {
|
||
if (currParamName !== null) {
|
||
params.set(currParamName, "");
|
||
}
|
||
currParamName = parg;
|
||
} else {
|
||
if (currParamName !== null) {
|
||
params.set(currParamName, parg);
|
||
currParamName = null;
|
||
} else {
|
||
args.push(parg);
|
||
}
|
||
}
|
||
}
|
||
if (currParamName !== null) {
|
||
params.set(currParamName, "");
|
||
}
|
||
} else if (typeof location === "object") {
|
||
params = create();
|
||
(location.search || "?").slice(1).split("&").forEach((kv) => {
|
||
if (kv.length !== 0) {
|
||
const [key, value] = kv.split("=");
|
||
params.set(`--${fromCamelCase(key, "-")}`, value);
|
||
params.set(`-${fromCamelCase(key, "-")}`, value);
|
||
}
|
||
});
|
||
} else {
|
||
params = create();
|
||
}
|
||
}
|
||
return params;
|
||
};
|
||
var hasParam = (name) => computeParams().has(name);
|
||
var getVariable = (name) => isNode ? undefinedToNull(process.env[name.toUpperCase().replaceAll("-", "_")]) : undefinedToNull(varStorage.getItem(name));
|
||
var hasConf = (name) => hasParam("--" + name) || getVariable(name) !== null;
|
||
var production = hasConf("production");
|
||
var forceColor = isNode && isOneOf(process.env.FORCE_COLOR, ["true", "1", "2"]);
|
||
var supportsColor = forceColor || !hasParam("--no-colors") && // @todo deprecate --no-colors
|
||
!hasConf("no-color") && (!isNode || process.stdout.isTTY) && (!isNode || hasParam("--color") || getVariable("COLORTERM") !== null || (getVariable("TERM") || "").includes("color"));
|
||
|
||
// node_modules/lib0/buffer.js
|
||
var createUint8ArrayFromLen = (len) => new Uint8Array(len);
|
||
var copyUint8Array = (uint8Array) => {
|
||
const newBuf = createUint8ArrayFromLen(uint8Array.byteLength);
|
||
newBuf.set(uint8Array);
|
||
return newBuf;
|
||
};
|
||
|
||
// node_modules/lib0/pair.js
|
||
var Pair = class {
|
||
/**
|
||
* @param {L} left
|
||
* @param {R} right
|
||
*/
|
||
constructor(left, right) {
|
||
this.left = left;
|
||
this.right = right;
|
||
}
|
||
};
|
||
var create5 = (left, right) => new Pair(left, right);
|
||
|
||
// node_modules/lib0/prng.js
|
||
var bool = (gen) => gen.next() >= 0.5;
|
||
var int53 = (gen, min2, max2) => floor(gen.next() * (max2 + 1 - min2) + min2);
|
||
var int32 = (gen, min2, max2) => floor(gen.next() * (max2 + 1 - min2) + min2);
|
||
var int31 = (gen, min2, max2) => int32(gen, min2, max2);
|
||
var letter = (gen) => fromCharCode(int31(gen, 97, 122));
|
||
var word = (gen, minLen = 0, maxLen = 20) => {
|
||
const len = int31(gen, minLen, maxLen);
|
||
let str = "";
|
||
for (let i = 0; i < len; i++) {
|
||
str += letter(gen);
|
||
}
|
||
return str;
|
||
};
|
||
var oneOf = (gen, array) => array[int31(gen, 0, array.length - 1)];
|
||
|
||
// node_modules/lib0/schema.js
|
||
var schemaSymbol = Symbol("0schema");
|
||
var ValidationError = class {
|
||
constructor() {
|
||
this._rerrs = [];
|
||
}
|
||
/**
|
||
* @param {string?} path
|
||
* @param {string} expected
|
||
* @param {string} has
|
||
* @param {string?} message
|
||
*/
|
||
extend(path, expected, has, message = null) {
|
||
this._rerrs.push({ path, expected, has, message });
|
||
}
|
||
toString() {
|
||
const s = [];
|
||
for (let i = this._rerrs.length - 1; i > 0; i--) {
|
||
const r = this._rerrs[i];
|
||
s.push(repeat(" ", (this._rerrs.length - i) * 2) + `${r.path != null ? `[${r.path}] ` : ""}${r.has} doesn't match ${r.expected}. ${r.message}`);
|
||
}
|
||
return s.join("\n");
|
||
}
|
||
};
|
||
var shapeExtends = (a, b) => {
|
||
if (a === b) return true;
|
||
if (a == null || b == null || a.constructor !== b.constructor) return false;
|
||
if (a[EqualityTraitSymbol]) return equals(a, b);
|
||
if (isArray(a)) {
|
||
return every(
|
||
a,
|
||
(aitem) => some(b, (bitem) => shapeExtends(aitem, bitem))
|
||
);
|
||
} else if (isObject(a)) {
|
||
return every2(
|
||
a,
|
||
(aitem, akey) => shapeExtends(aitem, b[akey])
|
||
);
|
||
}
|
||
return false;
|
||
};
|
||
var Schema = class {
|
||
/**
|
||
* @param {Schema<any>} other
|
||
*/
|
||
extends(other) {
|
||
let [a, b] = [
|
||
/** @type {any} */
|
||
this.shape,
|
||
/** @type {any} */
|
||
other.shape
|
||
];
|
||
if (
|
||
/** @type {typeof Schema<any>} */
|
||
this.constructor._dilutes
|
||
) [b, a] = [a, b];
|
||
return shapeExtends(a, b);
|
||
}
|
||
/**
|
||
* Overwrite this when necessary. By default, we only check the `shape` property which every shape
|
||
* should have.
|
||
* @param {Schema<any>} other
|
||
*/
|
||
equals(other) {
|
||
return this.constructor === other.constructor && equalityDeep(this.shape, other.shape);
|
||
}
|
||
[schemaSymbol]() {
|
||
return true;
|
||
}
|
||
/**
|
||
* @param {object} other
|
||
*/
|
||
[EqualityTraitSymbol](other) {
|
||
return this.equals(
|
||
/** @type {any} */
|
||
other
|
||
);
|
||
}
|
||
/**
|
||
* Use `schema.validate(obj)` with a typed parameter that is already of typed to be an instance of
|
||
* Schema. Validate will check the structure of the parameter and return true iff the instance
|
||
* really is an instance of Schema.
|
||
*
|
||
* @param {T} o
|
||
* @return {boolean}
|
||
*/
|
||
validate(o) {
|
||
return this.check(o);
|
||
}
|
||
/* c8 ignore start */
|
||
/**
|
||
* Similar to validate, but this method accepts untyped parameters.
|
||
*
|
||
* @param {any} _o
|
||
* @param {ValidationError} [_err]
|
||
* @return {_o is T}
|
||
*/
|
||
check(_o, _err) {
|
||
methodUnimplemented();
|
||
}
|
||
/* c8 ignore stop */
|
||
/**
|
||
* @type {Schema<T?>}
|
||
*/
|
||
get nullable() {
|
||
return $union(this, $null);
|
||
}
|
||
/**
|
||
* @type {$Optional<Schema<T>>}
|
||
*/
|
||
get optional() {
|
||
return new $Optional(
|
||
/** @type {Schema<T>} */
|
||
this
|
||
);
|
||
}
|
||
/**
|
||
* Cast a variable to a specific type. Returns the casted value, or throws an exception otherwise.
|
||
* Use this if you know that the type is of a specific type and you just want to convince the type
|
||
* system.
|
||
*
|
||
* **Do not rely on these error messages!**
|
||
* Performs an assertion check only if not in a production environment.
|
||
*
|
||
* @template OO
|
||
* @param {OO} o
|
||
* @return {Extract<OO, T> extends never ? T : (OO extends Array<never> ? T : Extract<OO,T>)}
|
||
*/
|
||
cast(o) {
|
||
assert(o, this);
|
||
return (
|
||
/** @type {any} */
|
||
o
|
||
);
|
||
}
|
||
/**
|
||
* EXPECTO PATRONUM!! 🪄
|
||
* This function protects against type errors. Though it may not work in the real world.
|
||
*
|
||
* "After all this time?"
|
||
* "Always." - Snape, talking about type safety
|
||
*
|
||
* Ensures that a variable is a a specific type. Returns the value, or throws an exception if the assertion check failed.
|
||
* Use this if you know that the type is of a specific type and you just want to convince the type
|
||
* system.
|
||
*
|
||
* Can be useful when defining lambdas: `s.lambda(s.$number, s.$void).expect((n) => n + 1)`
|
||
*
|
||
* **Do not rely on these error messages!**
|
||
* Performs an assertion check if not in a production environment.
|
||
*
|
||
* @param {T} o
|
||
* @return {o extends T ? T : never}
|
||
*/
|
||
expect(o) {
|
||
assert(o, this);
|
||
return o;
|
||
}
|
||
};
|
||
// this.shape must not be defined on Schema. Otherwise typecheck on metatypes (e.g. $$object) won't work as expected anymore
|
||
/**
|
||
* If true, the more things are added to the shape the more objects this schema will accept (e.g.
|
||
* union). By default, the more objects are added, the the fewer objects this schema will accept.
|
||
* @protected
|
||
*/
|
||
__publicField(Schema, "_dilutes", false);
|
||
var $ConstructedBy = class extends Schema {
|
||
/**
|
||
* @param {C} c
|
||
* @param {((o:Instance<C>)=>boolean)|null} check
|
||
*/
|
||
constructor(c, check) {
|
||
super();
|
||
this.shape = c;
|
||
this._c = check;
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} [err]
|
||
* @return {o is C extends ((...args:any[]) => infer T) ? T : (C extends (new (...args:any[]) => any) ? InstanceType<C> : never)} o
|
||
*/
|
||
check(o, err = void 0) {
|
||
const c = (o == null ? void 0 : o.constructor) === this.shape && (this._c == null || this._c(o));
|
||
!c && (err == null ? void 0 : err.extend(null, this.shape.name, o == null ? void 0 : o.constructor.name, (o == null ? void 0 : o.constructor) !== this.shape ? "Constructor match failed" : "Check failed"));
|
||
return c;
|
||
}
|
||
};
|
||
var $constructedBy = (c, check = null) => new $ConstructedBy(c, check);
|
||
var $$constructedBy = $constructedBy($ConstructedBy);
|
||
var $Custom = class extends Schema {
|
||
/**
|
||
* @param {(o:any) => boolean} check
|
||
*/
|
||
constructor(check) {
|
||
super();
|
||
this.shape = check;
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} err
|
||
* @return {o is any}
|
||
*/
|
||
check(o, err) {
|
||
const c = this.shape(o);
|
||
!c && (err == null ? void 0 : err.extend(null, "custom prop", o == null ? void 0 : o.constructor.name, "failed to check custom prop"));
|
||
return c;
|
||
}
|
||
};
|
||
var $custom = (check) => new $Custom(check);
|
||
var $$custom = $constructedBy($Custom);
|
||
var $Literal = class extends Schema {
|
||
/**
|
||
* @param {Array<T>} literals
|
||
*/
|
||
constructor(literals) {
|
||
super();
|
||
this.shape = literals;
|
||
}
|
||
/**
|
||
*
|
||
* @param {any} o
|
||
* @param {ValidationError} [err]
|
||
* @return {o is T}
|
||
*/
|
||
check(o, err) {
|
||
const c = this.shape.some((a) => a === o);
|
||
!c && (err == null ? void 0 : err.extend(null, this.shape.join(" | "), o.toString()));
|
||
return c;
|
||
}
|
||
};
|
||
var $literal = (...literals) => new $Literal(literals);
|
||
var $$literal = $constructedBy($Literal);
|
||
var _regexEscape = (
|
||
/** @type {any} */
|
||
RegExp.escape || /** @type {(str:string) => string} */
|
||
((str) => str.replace(/[().|&,$^[\]]/g, (s) => "\\" + s))
|
||
);
|
||
var _schemaStringTemplateToRegex = (s) => {
|
||
if ($string.check(s)) {
|
||
return [_regexEscape(s)];
|
||
}
|
||
if ($$literal.check(s)) {
|
||
return (
|
||
/** @type {Array<string|number>} */
|
||
s.shape.map((v) => v + "")
|
||
);
|
||
}
|
||
if ($$number.check(s)) {
|
||
return ["[+-]?\\d+.?\\d*"];
|
||
}
|
||
if ($$string.check(s)) {
|
||
return [".*"];
|
||
}
|
||
if ($$union.check(s)) {
|
||
return s.shape.map(_schemaStringTemplateToRegex).flat(1);
|
||
}
|
||
unexpectedCase();
|
||
};
|
||
var $StringTemplate = class extends Schema {
|
||
/**
|
||
* @param {T} shape
|
||
*/
|
||
constructor(shape) {
|
||
super();
|
||
this.shape = shape;
|
||
this._r = new RegExp("^" + shape.map(_schemaStringTemplateToRegex).map((opts) => `(${opts.join("|")})`).join("") + "$");
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} [err]
|
||
* @return {o is CastStringTemplateArgsToTemplate<T>}
|
||
*/
|
||
check(o, err) {
|
||
const c = this._r.exec(o) != null;
|
||
!c && (err == null ? void 0 : err.extend(null, this._r.toString(), o.toString(), "String doesn't match string template."));
|
||
return c;
|
||
}
|
||
};
|
||
var $$stringTemplate = $constructedBy($StringTemplate);
|
||
var isOptionalSymbol = Symbol("optional");
|
||
var $Optional = class extends Schema {
|
||
/**
|
||
* @param {S} shape
|
||
*/
|
||
constructor(shape) {
|
||
super();
|
||
this.shape = shape;
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} [err]
|
||
* @return {o is (Unwrap<S>|undefined)}
|
||
*/
|
||
check(o, err) {
|
||
const c = o === void 0 || this.shape.check(o);
|
||
!c && (err == null ? void 0 : err.extend(null, "undefined (optional)", "()"));
|
||
return c;
|
||
}
|
||
get [isOptionalSymbol]() {
|
||
return true;
|
||
}
|
||
};
|
||
var $$optional = $constructedBy($Optional);
|
||
var $Never = class extends Schema {
|
||
/**
|
||
* @param {any} _o
|
||
* @param {ValidationError} [err]
|
||
* @return {_o is never}
|
||
*/
|
||
check(_o, err) {
|
||
err == null ? void 0 : err.extend(null, "never", typeof _o);
|
||
return false;
|
||
}
|
||
};
|
||
var $never = new $Never();
|
||
var $$never = $constructedBy($Never);
|
||
var _$Object = class _$Object extends Schema {
|
||
/**
|
||
* @param {S} shape
|
||
* @param {boolean} partial
|
||
*/
|
||
constructor(shape, partial = false) {
|
||
super();
|
||
this.shape = shape;
|
||
this._isPartial = partial;
|
||
}
|
||
/**
|
||
* @type {Schema<Partial<$ObjectToType<S>>>}
|
||
*/
|
||
get partial() {
|
||
return new _$Object(this.shape, true);
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} err
|
||
* @return {o is $ObjectToType<S>}
|
||
*/
|
||
check(o, err) {
|
||
if (o == null) {
|
||
err == null ? void 0 : err.extend(null, "object", "null");
|
||
return false;
|
||
}
|
||
return every2(this.shape, (vv, vk) => {
|
||
const c = this._isPartial && !hasProperty(o, vk) || vv.check(o[vk], err);
|
||
!c && (err == null ? void 0 : err.extend(vk.toString(), vv.toString(), typeof o[vk], "Object property does not match"));
|
||
return c;
|
||
});
|
||
}
|
||
};
|
||
__publicField(_$Object, "_dilutes", true);
|
||
var $Object = _$Object;
|
||
var $object = (def) => (
|
||
/** @type {any} */
|
||
new $Object(def)
|
||
);
|
||
var $$object = $constructedBy($Object);
|
||
var $objectAny = $custom((o) => o != null && (o.constructor === Object || o.constructor == null));
|
||
var $Record = class extends Schema {
|
||
/**
|
||
* @param {Keys} keys
|
||
* @param {Values} values
|
||
*/
|
||
constructor(keys2, values) {
|
||
super();
|
||
this.shape = {
|
||
keys: keys2,
|
||
values
|
||
};
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} err
|
||
* @return {o is { [key in Unwrap<Keys>]: Unwrap<Values> }}
|
||
*/
|
||
check(o, err) {
|
||
return o != null && every2(o, (vv, vk) => {
|
||
const ck = this.shape.keys.check(vk, err);
|
||
!ck && (err == null ? void 0 : err.extend(vk + "", "Record", typeof o, ck ? "Key doesn't match schema" : "Value doesn't match value"));
|
||
return ck && this.shape.values.check(vv, err);
|
||
});
|
||
}
|
||
};
|
||
var $record = (keys2, values) => new $Record(keys2, values);
|
||
var $$record = $constructedBy($Record);
|
||
var $Tuple = class extends Schema {
|
||
/**
|
||
* @param {S} shape
|
||
*/
|
||
constructor(shape) {
|
||
super();
|
||
this.shape = shape;
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} err
|
||
* @return {o is { [K in keyof S]: S[K] extends Schema<infer Type> ? Type : never }}
|
||
*/
|
||
check(o, err) {
|
||
return o != null && every2(this.shape, (vv, vk) => {
|
||
const c = (
|
||
/** @type {Schema<any>} */
|
||
vv.check(o[vk], err)
|
||
);
|
||
!c && (err == null ? void 0 : err.extend(vk.toString(), "Tuple", typeof vv));
|
||
return c;
|
||
});
|
||
}
|
||
};
|
||
var $tuple = (...def) => new $Tuple(def);
|
||
var $$tuple = $constructedBy($Tuple);
|
||
var $Array = class extends Schema {
|
||
/**
|
||
* @param {Array<S>} v
|
||
*/
|
||
constructor(v) {
|
||
super();
|
||
this.shape = v.length === 1 ? v[0] : new $Union(v);
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} [err]
|
||
* @return {o is Array<S extends Schema<infer T> ? T : never>} o
|
||
*/
|
||
check(o, err) {
|
||
const c = isArray(o) && every(o, (oi) => this.shape.check(oi));
|
||
!c && (err == null ? void 0 : err.extend(null, "Array", ""));
|
||
return c;
|
||
}
|
||
};
|
||
var $array = (...def) => new $Array(def);
|
||
var $$array = $constructedBy($Array);
|
||
var $arrayAny = $custom((o) => isArray(o));
|
||
var $InstanceOf = class extends Schema {
|
||
/**
|
||
* @param {new (...args:any) => T} constructor
|
||
* @param {((o:T) => boolean)|null} check
|
||
*/
|
||
constructor(constructor, check) {
|
||
super();
|
||
this.shape = constructor;
|
||
this._c = check;
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} err
|
||
* @return {o is T}
|
||
*/
|
||
check(o, err) {
|
||
const c = o instanceof this.shape && (this._c == null || this._c(o));
|
||
!c && (err == null ? void 0 : err.extend(null, this.shape.name, o == null ? void 0 : o.constructor.name));
|
||
return c;
|
||
}
|
||
};
|
||
var $instanceOf = (c, check = null) => new $InstanceOf(c, check);
|
||
var $$instanceOf = $constructedBy($InstanceOf);
|
||
var $$schema = $instanceOf(Schema);
|
||
var $Lambda = class extends Schema {
|
||
/**
|
||
* @param {Args} args
|
||
*/
|
||
constructor(args2) {
|
||
super();
|
||
this.len = args2.length - 1;
|
||
this.args = $tuple(...args2.slice(-1));
|
||
this.res = args2[this.len];
|
||
}
|
||
/**
|
||
* @param {any} f
|
||
* @param {ValidationError} err
|
||
* @return {f is _LArgsToLambdaDef<Args>}
|
||
*/
|
||
check(f, err) {
|
||
const c = f.constructor === Function && f.length <= this.len;
|
||
!c && (err == null ? void 0 : err.extend(null, "function", typeof f));
|
||
return c;
|
||
}
|
||
};
|
||
var $$lambda = $constructedBy($Lambda);
|
||
var $function = $custom((o) => typeof o === "function");
|
||
var $Intersection = class extends Schema {
|
||
/**
|
||
* @param {T} v
|
||
*/
|
||
constructor(v) {
|
||
super();
|
||
this.shape = v;
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} [err]
|
||
* @return {o is Intersect<UnwrapArray<T>>}
|
||
*/
|
||
check(o, err) {
|
||
const c = every(this.shape, (check) => check.check(o, err));
|
||
!c && (err == null ? void 0 : err.extend(null, "Intersectinon", typeof o));
|
||
return c;
|
||
}
|
||
};
|
||
var $$intersect = $constructedBy($Intersection, (o) => o.shape.length > 0);
|
||
var $Union = class extends Schema {
|
||
/**
|
||
* @param {Array<Schema<S>>} v
|
||
*/
|
||
constructor(v) {
|
||
super();
|
||
this.shape = v;
|
||
}
|
||
/**
|
||
* @param {any} o
|
||
* @param {ValidationError} [err]
|
||
* @return {o is S}
|
||
*/
|
||
check(o, err) {
|
||
const c = some(this.shape, (vv) => vv.check(o, err));
|
||
err == null ? void 0 : err.extend(null, "Union", typeof o);
|
||
return c;
|
||
}
|
||
};
|
||
__publicField($Union, "_dilutes", true);
|
||
var $union = (...schemas) => schemas.findIndex(($s) => $$union.check($s)) >= 0 ? $union(...schemas.map(($s) => $($s)).map(($s) => $$union.check($s) ? $s.shape : [$s]).flat(1)) : schemas.length === 1 ? schemas[0] : new $Union(schemas);
|
||
var $$union = (
|
||
/** @type {Schema<$Union<any>>} */
|
||
$constructedBy($Union)
|
||
);
|
||
var _t = () => true;
|
||
var $any = $custom(_t);
|
||
var $$any = (
|
||
/** @type {Schema<Schema<any>>} */
|
||
$constructedBy($Custom, (o) => o.shape === _t)
|
||
);
|
||
var $bigint = $custom((o) => typeof o === "bigint");
|
||
var $$bigint = (
|
||
/** @type {Schema<Schema<BigInt>>} */
|
||
$custom((o) => o === $bigint)
|
||
);
|
||
var $symbol = $custom((o) => typeof o === "symbol");
|
||
var $$symbol = (
|
||
/** @type {Schema<Schema<Symbol>>} */
|
||
$custom((o) => o === $symbol)
|
||
);
|
||
var $number = $custom((o) => typeof o === "number");
|
||
var $$number = (
|
||
/** @type {Schema<Schema<number>>} */
|
||
$custom((o) => o === $number)
|
||
);
|
||
var $string = $custom((o) => typeof o === "string");
|
||
var $$string = (
|
||
/** @type {Schema<Schema<string>>} */
|
||
$custom((o) => o === $string)
|
||
);
|
||
var $boolean = $custom((o) => typeof o === "boolean");
|
||
var $$boolean = (
|
||
/** @type {Schema<Schema<Boolean>>} */
|
||
$custom((o) => o === $boolean)
|
||
);
|
||
var $undefined = $literal(void 0);
|
||
var $$undefined = (
|
||
/** @type {Schema<Schema<undefined>>} */
|
||
$constructedBy($Literal, (o) => o.shape.length === 1 && o.shape[0] === void 0)
|
||
);
|
||
var $void = $literal(void 0);
|
||
var $null = $literal(null);
|
||
var $$null = (
|
||
/** @type {Schema<Schema<null>>} */
|
||
$constructedBy($Literal, (o) => o.shape.length === 1 && o.shape[0] === null)
|
||
);
|
||
var $uint8Array = $constructedBy(Uint8Array);
|
||
var $$uint8Array = (
|
||
/** @type {Schema<Schema<Uint8Array>>} */
|
||
$constructedBy($ConstructedBy, (o) => o.shape === Uint8Array)
|
||
);
|
||
var $primitive = $union($number, $string, $null, $undefined, $bigint, $boolean, $symbol);
|
||
var $json = (() => {
|
||
const $jsonArr = (
|
||
/** @type {$Array<$any>} */
|
||
$array($any)
|
||
);
|
||
const $jsonRecord = (
|
||
/** @type {$Record<$string,$any>} */
|
||
$record($string, $any)
|
||
);
|
||
const $json2 = $union($number, $string, $null, $boolean, $jsonArr, $jsonRecord);
|
||
$jsonArr.shape = $json2;
|
||
$jsonRecord.shape.values = $json2;
|
||
return $json2;
|
||
})();
|
||
var $ = (o) => {
|
||
if ($$schema.check(o)) {
|
||
return (
|
||
/** @type {any} */
|
||
o
|
||
);
|
||
} else if ($objectAny.check(o)) {
|
||
const o2 = {};
|
||
for (const k in o) {
|
||
o2[k] = $(o[k]);
|
||
}
|
||
return (
|
||
/** @type {any} */
|
||
$object(o2)
|
||
);
|
||
} else if ($arrayAny.check(o)) {
|
||
return (
|
||
/** @type {any} */
|
||
$union(...o.map($))
|
||
);
|
||
} else if ($primitive.check(o)) {
|
||
return (
|
||
/** @type {any} */
|
||
$literal(o)
|
||
);
|
||
} else if ($function.check(o)) {
|
||
return (
|
||
/** @type {any} */
|
||
$constructedBy(
|
||
/** @type {any} */
|
||
o
|
||
)
|
||
);
|
||
}
|
||
unexpectedCase();
|
||
};
|
||
var assert = production ? () => {
|
||
} : (o, schema) => {
|
||
const err = new ValidationError();
|
||
if (!schema.check(o, err)) {
|
||
throw create3(`Expected value to be of type ${schema.constructor.name}.
|
||
${err.toString()}`);
|
||
}
|
||
};
|
||
var PatternMatcher = class {
|
||
/**
|
||
* @param {Schema<State>} [$state]
|
||
*/
|
||
constructor($state) {
|
||
this.patterns = [];
|
||
this.$state = $state;
|
||
}
|
||
/**
|
||
* @template P
|
||
* @template R
|
||
* @param {P} pattern
|
||
* @param {(o:NoInfer<Unwrap<ReadSchema<P>>>,s:State)=>R} handler
|
||
* @return {PatternMatcher<State,Patterns|Pattern<Unwrap<ReadSchema<P>>,R>>}
|
||
*/
|
||
if(pattern, handler) {
|
||
this.patterns.push({ if: $(pattern), h: handler });
|
||
return this;
|
||
}
|
||
/**
|
||
* @template R
|
||
* @param {(o:any,s:State)=>R} h
|
||
*/
|
||
else(h) {
|
||
return this.if($any, h);
|
||
}
|
||
/**
|
||
* @return {State extends undefined
|
||
* ? <In extends Unwrap<Patterns['if']>>(o:In,state?:undefined)=>PatternMatchResult<Patterns,In>
|
||
* : <In extends Unwrap<Patterns['if']>>(o:In,state:State)=>PatternMatchResult<Patterns,In>}
|
||
*/
|
||
done() {
|
||
return (
|
||
/** @type {any} */
|
||
(o, s) => {
|
||
for (let i = 0; i < this.patterns.length; i++) {
|
||
const p = this.patterns[i];
|
||
if (p.if.check(o)) {
|
||
return p.h(o, s);
|
||
}
|
||
}
|
||
throw create3("Unhandled pattern");
|
||
}
|
||
);
|
||
}
|
||
};
|
||
var match = (state) => new PatternMatcher(
|
||
/** @type {any} */
|
||
state
|
||
);
|
||
var _random = (
|
||
/** @type {any} */
|
||
match(
|
||
/** @type {Schema<prng.PRNG>} */
|
||
$any
|
||
).if($$number, (_o, gen) => int53(gen, MIN_SAFE_INTEGER, MAX_SAFE_INTEGER)).if($$string, (_o, gen) => word(gen)).if($$boolean, (_o, gen) => bool(gen)).if($$bigint, (_o, gen) => BigInt(int53(gen, MIN_SAFE_INTEGER, MAX_SAFE_INTEGER))).if($$union, (o, gen) => random(gen, oneOf(gen, o.shape))).if($$object, (o, gen) => {
|
||
const res = {};
|
||
for (const k in o.shape) {
|
||
let prop = o.shape[k];
|
||
if ($$optional.check(prop)) {
|
||
if (bool(gen)) {
|
||
continue;
|
||
}
|
||
prop = prop.shape;
|
||
}
|
||
res[k] = _random(prop, gen);
|
||
}
|
||
return res;
|
||
}).if($$array, (o, gen) => {
|
||
const arr = [];
|
||
const n = int32(gen, 0, 42);
|
||
for (let i = 0; i < n; i++) {
|
||
arr.push(random(gen, o.shape));
|
||
}
|
||
return arr;
|
||
}).if($$literal, (o, gen) => {
|
||
return oneOf(gen, o.shape);
|
||
}).if($$null, (o, gen) => {
|
||
return null;
|
||
}).if($$lambda, (o, gen) => {
|
||
const res = random(gen, o.res);
|
||
return () => res;
|
||
}).if($$any, (o, gen) => random(gen, oneOf(gen, [
|
||
$number,
|
||
$string,
|
||
$null,
|
||
$undefined,
|
||
$bigint,
|
||
$boolean,
|
||
$array($number),
|
||
$record($union("a", "b", "c"), $number)
|
||
]))).if($$record, (o, gen) => {
|
||
const res = {};
|
||
const keysN = int53(gen, 0, 3);
|
||
for (let i = 0; i < keysN; i++) {
|
||
const key = random(gen, o.shape.keys);
|
||
const val = random(gen, o.shape.values);
|
||
res[key] = val;
|
||
}
|
||
return res;
|
||
}).done()
|
||
);
|
||
var random = (gen, schema) => (
|
||
/** @type {any} */
|
||
_random($(schema), gen)
|
||
);
|
||
|
||
// node_modules/lib0/dom.js
|
||
var doc = (
|
||
/** @type {Document} */
|
||
typeof document !== "undefined" ? document : {}
|
||
);
|
||
var $fragment = $custom((el) => el.nodeType === DOCUMENT_FRAGMENT_NODE);
|
||
var domParser = (
|
||
/** @type {DOMParser} */
|
||
typeof DOMParser !== "undefined" ? new DOMParser() : null
|
||
);
|
||
var $element = $custom((el) => el.nodeType === ELEMENT_NODE);
|
||
var $text = $custom((el) => el.nodeType === TEXT_NODE);
|
||
var mapToStyleString = (m) => map(m, (value, key) => `${key}:${value};`).join("");
|
||
var ELEMENT_NODE = doc.ELEMENT_NODE;
|
||
var TEXT_NODE = doc.TEXT_NODE;
|
||
var CDATA_SECTION_NODE = doc.CDATA_SECTION_NODE;
|
||
var COMMENT_NODE = doc.COMMENT_NODE;
|
||
var DOCUMENT_NODE = doc.DOCUMENT_NODE;
|
||
var DOCUMENT_TYPE_NODE = doc.DOCUMENT_TYPE_NODE;
|
||
var DOCUMENT_FRAGMENT_NODE = doc.DOCUMENT_FRAGMENT_NODE;
|
||
var $node = $custom((el) => el.nodeType === DOCUMENT_NODE);
|
||
|
||
// node_modules/lib0/eventloop.js
|
||
var createTimeoutClass = (clearFunction) => class TT {
|
||
/**
|
||
* @param {number} timeoutId
|
||
*/
|
||
constructor(timeoutId) {
|
||
this._ = timeoutId;
|
||
}
|
||
destroy() {
|
||
clearFunction(this._);
|
||
}
|
||
};
|
||
var Timeout = createTimeoutClass(clearTimeout);
|
||
var Interval = createTimeoutClass(clearInterval);
|
||
var Animation = createTimeoutClass((arg) => typeof requestAnimationFrame !== "undefined" && cancelAnimationFrame(arg));
|
||
var Idle = createTimeoutClass((arg) => typeof cancelIdleCallback !== "undefined" && cancelIdleCallback(arg));
|
||
|
||
// node_modules/lib0/symbol.js
|
||
var create6 = Symbol;
|
||
|
||
// node_modules/lib0/logging.common.js
|
||
var BOLD = create6();
|
||
var UNBOLD = create6();
|
||
var BLUE = create6();
|
||
var GREY = create6();
|
||
var GREEN = create6();
|
||
var RED = create6();
|
||
var PURPLE = create6();
|
||
var ORANGE = create6();
|
||
var UNCOLOR = create6();
|
||
var computeNoColorLoggingArgs = (args2) => {
|
||
var _a;
|
||
if (args2.length === 1 && ((_a = args2[0]) == null ? void 0 : _a.constructor) === Function) {
|
||
args2 = /** @type {Array<string|Symbol|Object|number>} */
|
||
/** @type {[function]} */
|
||
args2[0]();
|
||
}
|
||
const strBuilder = [];
|
||
const logArgs = [];
|
||
let i = 0;
|
||
for (; i < args2.length; i++) {
|
||
const arg = args2[i];
|
||
if (arg === void 0) {
|
||
break;
|
||
} else if (arg.constructor === String || arg.constructor === Number) {
|
||
strBuilder.push(arg);
|
||
} else if (arg.constructor === Object) {
|
||
break;
|
||
}
|
||
}
|
||
if (i > 0) {
|
||
logArgs.push(strBuilder.join(""));
|
||
}
|
||
for (; i < args2.length; i++) {
|
||
const arg = args2[i];
|
||
if (!(arg instanceof Symbol)) {
|
||
logArgs.push(arg);
|
||
}
|
||
}
|
||
return logArgs;
|
||
};
|
||
var lastLoggingTime = getUnixTime();
|
||
|
||
// node_modules/lib0/logging.js
|
||
var _browserStyleMap = {
|
||
[BOLD]: create5("font-weight", "bold"),
|
||
[UNBOLD]: create5("font-weight", "normal"),
|
||
[BLUE]: create5("color", "blue"),
|
||
[GREEN]: create5("color", "green"),
|
||
[GREY]: create5("color", "grey"),
|
||
[RED]: create5("color", "red"),
|
||
[PURPLE]: create5("color", "purple"),
|
||
[ORANGE]: create5("color", "orange"),
|
||
// not well supported in chrome when debugging node with inspector - TODO: deprecate
|
||
[UNCOLOR]: create5("color", "black")
|
||
};
|
||
var computeBrowserLoggingArgs = (args2) => {
|
||
var _a;
|
||
if (args2.length === 1 && ((_a = args2[0]) == null ? void 0 : _a.constructor) === Function) {
|
||
args2 = /** @type {Array<string|Symbol|Object|number>} */
|
||
/** @type {[function]} */
|
||
args2[0]();
|
||
}
|
||
const strBuilder = [];
|
||
const styles = [];
|
||
const currentStyle = create();
|
||
let logArgs = [];
|
||
let i = 0;
|
||
for (; i < args2.length; i++) {
|
||
const arg = args2[i];
|
||
const style = _browserStyleMap[arg];
|
||
if (style !== void 0) {
|
||
currentStyle.set(style.left, style.right);
|
||
} else {
|
||
if (arg === void 0) {
|
||
break;
|
||
}
|
||
if (arg.constructor === String || arg.constructor === Number) {
|
||
const style2 = mapToStyleString(currentStyle);
|
||
if (i > 0 || style2.length > 0) {
|
||
strBuilder.push("%c" + arg);
|
||
styles.push(style2);
|
||
} else {
|
||
strBuilder.push(arg);
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (i > 0) {
|
||
logArgs = styles;
|
||
logArgs.unshift(strBuilder.join(""));
|
||
}
|
||
for (; i < args2.length; i++) {
|
||
const arg = args2[i];
|
||
if (!(arg instanceof Symbol)) {
|
||
logArgs.push(arg);
|
||
}
|
||
}
|
||
return logArgs;
|
||
};
|
||
var computeLoggingArgs = supportsColor ? computeBrowserLoggingArgs : computeNoColorLoggingArgs;
|
||
var print = (...args2) => {
|
||
console.log(...computeLoggingArgs(args2));
|
||
vconsoles.forEach((vc) => vc.print(args2));
|
||
};
|
||
var warn = (...args2) => {
|
||
console.warn(...computeLoggingArgs(args2));
|
||
args2.unshift(ORANGE);
|
||
vconsoles.forEach((vc) => vc.print(args2));
|
||
};
|
||
var vconsoles = create2();
|
||
|
||
// node_modules/lib0/iterator.js
|
||
var createIterator = (next) => ({
|
||
/**
|
||
* @return {IterableIterator<T>}
|
||
*/
|
||
[Symbol.iterator]() {
|
||
return this;
|
||
},
|
||
// @ts-ignore
|
||
next
|
||
});
|
||
var iteratorFilter = (iterator, filter) => createIterator(() => {
|
||
let res;
|
||
do {
|
||
res = iterator.next();
|
||
} while (!res.done && !filter(res.value));
|
||
return res;
|
||
});
|
||
var iteratorMap = (iterator, fmap) => createIterator(() => {
|
||
const { done, value } = iterator.next();
|
||
return { done, value: done ? void 0 : fmap(value) };
|
||
});
|
||
|
||
// node_modules/yjs/dist/yjs.mjs
|
||
var AbstractConnector = class extends ObservableV2 {
|
||
/**
|
||
* @param {Doc} ydoc
|
||
* @param {any} awareness
|
||
*/
|
||
constructor(ydoc, awareness) {
|
||
super();
|
||
this.doc = ydoc;
|
||
this.awareness = awareness;
|
||
}
|
||
};
|
||
var DeleteItem = class {
|
||
/**
|
||
* @param {number} clock
|
||
* @param {number} len
|
||
*/
|
||
constructor(clock, len) {
|
||
this.clock = clock;
|
||
this.len = len;
|
||
}
|
||
};
|
||
var DeleteSet = class {
|
||
constructor() {
|
||
this.clients = /* @__PURE__ */ new Map();
|
||
}
|
||
};
|
||
var iterateDeletedStructs = (transaction, ds, f) => ds.clients.forEach((deletes, clientid) => {
|
||
const structs = (
|
||
/** @type {Array<GC|Item>} */
|
||
transaction.doc.store.clients.get(clientid)
|
||
);
|
||
if (structs != null) {
|
||
const lastStruct = structs[structs.length - 1];
|
||
const clockState = lastStruct.id.clock + lastStruct.length;
|
||
for (let i = 0, del = deletes[i]; i < deletes.length && del.clock < clockState; del = deletes[++i]) {
|
||
iterateStructs(transaction, structs, del.clock, del.len, f);
|
||
}
|
||
}
|
||
});
|
||
var findIndexDS = (dis, clock) => {
|
||
let left = 0;
|
||
let right = dis.length - 1;
|
||
while (left <= right) {
|
||
const midindex = floor((left + right) / 2);
|
||
const mid = dis[midindex];
|
||
const midclock = mid.clock;
|
||
if (midclock <= clock) {
|
||
if (clock < midclock + mid.len) {
|
||
return midindex;
|
||
}
|
||
left = midindex + 1;
|
||
} else {
|
||
right = midindex - 1;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
var isDeleted = (ds, id2) => {
|
||
const dis = ds.clients.get(id2.client);
|
||
return dis !== void 0 && findIndexDS(dis, id2.clock) !== null;
|
||
};
|
||
var sortAndMergeDeleteSet = (ds) => {
|
||
ds.clients.forEach((dels) => {
|
||
dels.sort((a, b) => a.clock - b.clock);
|
||
let i, j;
|
||
for (i = 1, j = 1; i < dels.length; i++) {
|
||
const left = dels[j - 1];
|
||
const right = dels[i];
|
||
if (left.clock + left.len >= right.clock) {
|
||
dels[j - 1] = new DeleteItem(left.clock, max(left.len, right.clock + right.len - left.clock));
|
||
} else {
|
||
if (j < i) {
|
||
dels[j] = right;
|
||
}
|
||
j++;
|
||
}
|
||
}
|
||
dels.length = j;
|
||
});
|
||
};
|
||
var mergeDeleteSets = (dss) => {
|
||
const merged = new DeleteSet();
|
||
for (let dssI = 0; dssI < dss.length; dssI++) {
|
||
dss[dssI].clients.forEach((delsLeft, client) => {
|
||
if (!merged.clients.has(client)) {
|
||
const dels = delsLeft.slice();
|
||
for (let i = dssI + 1; i < dss.length; i++) {
|
||
appendTo(dels, dss[i].clients.get(client) || []);
|
||
}
|
||
merged.clients.set(client, dels);
|
||
}
|
||
});
|
||
}
|
||
sortAndMergeDeleteSet(merged);
|
||
return merged;
|
||
};
|
||
var addToDeleteSet = (ds, client, clock, length2) => {
|
||
setIfUndefined(ds.clients, client, () => (
|
||
/** @type {Array<DeleteItem>} */
|
||
[]
|
||
)).push(new DeleteItem(clock, length2));
|
||
};
|
||
var createDeleteSet = () => new DeleteSet();
|
||
var createDeleteSetFromStructStore = (ss) => {
|
||
const ds = createDeleteSet();
|
||
ss.clients.forEach((structs, client) => {
|
||
const dsitems = [];
|
||
for (let i = 0; i < structs.length; i++) {
|
||
const struct = structs[i];
|
||
if (struct.deleted) {
|
||
const clock = struct.id.clock;
|
||
let len = struct.length;
|
||
if (i + 1 < structs.length) {
|
||
for (let next = structs[i + 1]; i + 1 < structs.length && next.deleted; next = structs[++i + 1]) {
|
||
len += next.length;
|
||
}
|
||
}
|
||
dsitems.push(new DeleteItem(clock, len));
|
||
}
|
||
}
|
||
if (dsitems.length > 0) {
|
||
ds.clients.set(client, dsitems);
|
||
}
|
||
});
|
||
return ds;
|
||
};
|
||
var writeDeleteSet = (encoder, ds) => {
|
||
writeVarUint(encoder.restEncoder, ds.clients.size);
|
||
from2(ds.clients.entries()).sort((a, b) => b[0] - a[0]).forEach(([client, dsitems]) => {
|
||
encoder.resetDsCurVal();
|
||
writeVarUint(encoder.restEncoder, client);
|
||
const len = dsitems.length;
|
||
writeVarUint(encoder.restEncoder, len);
|
||
for (let i = 0; i < len; i++) {
|
||
const item = dsitems[i];
|
||
encoder.writeDsClock(item.clock);
|
||
encoder.writeDsLen(item.len);
|
||
}
|
||
});
|
||
};
|
||
var readDeleteSet = (decoder) => {
|
||
const ds = new DeleteSet();
|
||
const numClients = readVarUint(decoder.restDecoder);
|
||
for (let i = 0; i < numClients; i++) {
|
||
decoder.resetDsCurVal();
|
||
const client = readVarUint(decoder.restDecoder);
|
||
const numberOfDeletes = readVarUint(decoder.restDecoder);
|
||
if (numberOfDeletes > 0) {
|
||
const dsField = setIfUndefined(ds.clients, client, () => (
|
||
/** @type {Array<DeleteItem>} */
|
||
[]
|
||
));
|
||
for (let i2 = 0; i2 < numberOfDeletes; i2++) {
|
||
dsField.push(new DeleteItem(decoder.readDsClock(), decoder.readDsLen()));
|
||
}
|
||
}
|
||
}
|
||
return ds;
|
||
};
|
||
var readAndApplyDeleteSet = (decoder, transaction, store) => {
|
||
const unappliedDS = new DeleteSet();
|
||
const numClients = readVarUint(decoder.restDecoder);
|
||
for (let i = 0; i < numClients; i++) {
|
||
decoder.resetDsCurVal();
|
||
const client = readVarUint(decoder.restDecoder);
|
||
const numberOfDeletes = readVarUint(decoder.restDecoder);
|
||
const structs = store.clients.get(client) || [];
|
||
const state = getState(store, client);
|
||
for (let i2 = 0; i2 < numberOfDeletes; i2++) {
|
||
const clock = decoder.readDsClock();
|
||
const clockEnd = clock + decoder.readDsLen();
|
||
if (clock < state) {
|
||
if (state < clockEnd) {
|
||
addToDeleteSet(unappliedDS, client, state, clockEnd - state);
|
||
}
|
||
let index = findIndexSS(structs, clock);
|
||
let struct = structs[index];
|
||
if (!struct.deleted && struct.id.clock < clock) {
|
||
structs.splice(index + 1, 0, splitItem(transaction, struct, clock - struct.id.clock));
|
||
index++;
|
||
}
|
||
while (index < structs.length) {
|
||
struct = structs[index++];
|
||
if (struct.id.clock < clockEnd) {
|
||
if (!struct.deleted) {
|
||
if (clockEnd < struct.id.clock + struct.length) {
|
||
structs.splice(index, 0, splitItem(transaction, struct, clockEnd - struct.id.clock));
|
||
}
|
||
struct.delete(transaction);
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
addToDeleteSet(unappliedDS, client, clock, clockEnd - clock);
|
||
}
|
||
}
|
||
}
|
||
if (unappliedDS.clients.size > 0) {
|
||
const ds = new UpdateEncoderV2();
|
||
writeVarUint(ds.restEncoder, 0);
|
||
writeDeleteSet(ds, unappliedDS);
|
||
return ds.toUint8Array();
|
||
}
|
||
return null;
|
||
};
|
||
var equalDeleteSets = (ds1, ds2) => {
|
||
if (ds1.clients.size !== ds2.clients.size) return false;
|
||
for (const [client, deleteItems1] of ds1.clients.entries()) {
|
||
const deleteItems2 = (
|
||
/** @type {Array<import('../internals.js').DeleteItem>} */
|
||
ds2.clients.get(client)
|
||
);
|
||
if (deleteItems2 === void 0 || deleteItems1.length !== deleteItems2.length) return false;
|
||
for (let i = 0; i < deleteItems1.length; i++) {
|
||
const di1 = deleteItems1[i];
|
||
const di2 = deleteItems2[i];
|
||
if (di1.clock !== di2.clock || di1.len !== di2.len) {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
var generateNewClientId = uint32;
|
||
var Doc = class _Doc extends ObservableV2 {
|
||
/**
|
||
* @param {DocOpts} opts configuration
|
||
*/
|
||
constructor({ guid = uuidv4(), collectionid = null, gc = true, gcFilter = () => true, meta = null, autoLoad = false, shouldLoad = true } = {}) {
|
||
super();
|
||
this.gc = gc;
|
||
this.gcFilter = gcFilter;
|
||
this.clientID = generateNewClientId();
|
||
this.guid = guid;
|
||
this.collectionid = collectionid;
|
||
this.share = /* @__PURE__ */ new Map();
|
||
this.store = new StructStore();
|
||
this._transaction = null;
|
||
this._transactionCleanups = [];
|
||
this.subdocs = /* @__PURE__ */ new Set();
|
||
this._item = null;
|
||
this.shouldLoad = shouldLoad;
|
||
this.autoLoad = autoLoad;
|
||
this.meta = meta;
|
||
this.isLoaded = false;
|
||
this.isSynced = false;
|
||
this.isDestroyed = false;
|
||
this.whenLoaded = create4((resolve) => {
|
||
this.on("load", () => {
|
||
this.isLoaded = true;
|
||
resolve(this);
|
||
});
|
||
});
|
||
const provideSyncedPromise = () => create4((resolve) => {
|
||
const eventHandler = (isSynced) => {
|
||
if (isSynced === void 0 || isSynced === true) {
|
||
this.off("sync", eventHandler);
|
||
resolve();
|
||
}
|
||
};
|
||
this.on("sync", eventHandler);
|
||
});
|
||
this.on("sync", (isSynced) => {
|
||
if (isSynced === false && this.isSynced) {
|
||
this.whenSynced = provideSyncedPromise();
|
||
}
|
||
this.isSynced = isSynced === void 0 || isSynced === true;
|
||
if (this.isSynced && !this.isLoaded) {
|
||
this.emit("load", [this]);
|
||
}
|
||
});
|
||
this.whenSynced = provideSyncedPromise();
|
||
}
|
||
/**
|
||
* Notify the parent document that you request to load data into this subdocument (if it is a subdocument).
|
||
*
|
||
* `load()` might be used in the future to request any provider to load the most current data.
|
||
*
|
||
* It is safe to call `load()` multiple times.
|
||
*/
|
||
load() {
|
||
const item = this._item;
|
||
if (item !== null && !this.shouldLoad) {
|
||
transact(
|
||
/** @type {any} */
|
||
item.parent.doc,
|
||
(transaction) => {
|
||
transaction.subdocsLoaded.add(this);
|
||
},
|
||
null,
|
||
true
|
||
);
|
||
}
|
||
this.shouldLoad = true;
|
||
}
|
||
getSubdocs() {
|
||
return this.subdocs;
|
||
}
|
||
getSubdocGuids() {
|
||
return new Set(from2(this.subdocs).map((doc2) => doc2.guid));
|
||
}
|
||
/**
|
||
* Changes that happen inside of a transaction are bundled. This means that
|
||
* the observer fires _after_ the transaction is finished and that all changes
|
||
* that happened inside of the transaction are sent as one message to the
|
||
* other peers.
|
||
*
|
||
* @template T
|
||
* @param {function(Transaction):T} f The function that should be executed as a transaction
|
||
* @param {any} [origin] Origin of who started the transaction. Will be stored on transaction.origin
|
||
* @return T
|
||
*
|
||
* @public
|
||
*/
|
||
transact(f, origin = null) {
|
||
return transact(this, f, origin);
|
||
}
|
||
/**
|
||
* Define a shared data type.
|
||
*
|
||
* Multiple calls of `ydoc.get(name, TypeConstructor)` yield the same result
|
||
* and do not overwrite each other. I.e.
|
||
* `ydoc.get(name, Y.Array) === ydoc.get(name, Y.Array)`
|
||
*
|
||
* After this method is called, the type is also available on `ydoc.share.get(name)`.
|
||
*
|
||
* *Best Practices:*
|
||
* Define all types right after the Y.Doc instance is created and store them in a separate object.
|
||
* Also use the typed methods `getText(name)`, `getArray(name)`, ..
|
||
*
|
||
* @template {typeof AbstractType<any>} Type
|
||
* @example
|
||
* const ydoc = new Y.Doc(..)
|
||
* const appState = {
|
||
* document: ydoc.getText('document')
|
||
* comments: ydoc.getArray('comments')
|
||
* }
|
||
*
|
||
* @param {string} name
|
||
* @param {Type} TypeConstructor The constructor of the type definition. E.g. Y.Text, Y.Array, Y.Map, ...
|
||
* @return {InstanceType<Type>} The created type. Constructed with TypeConstructor
|
||
*
|
||
* @public
|
||
*/
|
||
get(name, TypeConstructor = (
|
||
/** @type {any} */
|
||
AbstractType
|
||
)) {
|
||
const type = setIfUndefined(this.share, name, () => {
|
||
const t = new TypeConstructor();
|
||
t._integrate(this, null);
|
||
return t;
|
||
});
|
||
const Constr = type.constructor;
|
||
if (TypeConstructor !== AbstractType && Constr !== TypeConstructor) {
|
||
if (Constr === AbstractType) {
|
||
const t = new TypeConstructor();
|
||
t._map = type._map;
|
||
type._map.forEach(
|
||
/** @param {Item?} n */
|
||
(n) => {
|
||
for (; n !== null; n = n.left) {
|
||
n.parent = t;
|
||
}
|
||
}
|
||
);
|
||
t._start = type._start;
|
||
for (let n = t._start; n !== null; n = n.right) {
|
||
n.parent = t;
|
||
}
|
||
t._length = type._length;
|
||
this.share.set(name, t);
|
||
t._integrate(this, null);
|
||
return (
|
||
/** @type {InstanceType<Type>} */
|
||
t
|
||
);
|
||
} else {
|
||
throw new Error(`Type with the name ${name} has already been defined with a different constructor`);
|
||
}
|
||
}
|
||
return (
|
||
/** @type {InstanceType<Type>} */
|
||
type
|
||
);
|
||
}
|
||
/**
|
||
* @template T
|
||
* @param {string} [name]
|
||
* @return {YArray<T>}
|
||
*
|
||
* @public
|
||
*/
|
||
getArray(name = "") {
|
||
return (
|
||
/** @type {YArray<T>} */
|
||
this.get(name, YArray)
|
||
);
|
||
}
|
||
/**
|
||
* @param {string} [name]
|
||
* @return {YText}
|
||
*
|
||
* @public
|
||
*/
|
||
getText(name = "") {
|
||
return this.get(name, YText);
|
||
}
|
||
/**
|
||
* @template T
|
||
* @param {string} [name]
|
||
* @return {YMap<T>}
|
||
*
|
||
* @public
|
||
*/
|
||
getMap(name = "") {
|
||
return (
|
||
/** @type {YMap<T>} */
|
||
this.get(name, YMap)
|
||
);
|
||
}
|
||
/**
|
||
* @param {string} [name]
|
||
* @return {YXmlElement}
|
||
*
|
||
* @public
|
||
*/
|
||
getXmlElement(name = "") {
|
||
return (
|
||
/** @type {YXmlElement<{[key:string]:string}>} */
|
||
this.get(name, YXmlElement)
|
||
);
|
||
}
|
||
/**
|
||
* @param {string} [name]
|
||
* @return {YXmlFragment}
|
||
*
|
||
* @public
|
||
*/
|
||
getXmlFragment(name = "") {
|
||
return this.get(name, YXmlFragment);
|
||
}
|
||
/**
|
||
* Converts the entire document into a js object, recursively traversing each yjs type
|
||
* Doesn't log types that have not been defined (using ydoc.getType(..)).
|
||
*
|
||
* @deprecated Do not use this method and rather call toJSON directly on the shared types.
|
||
*
|
||
* @return {Object<string, any>}
|
||
*/
|
||
toJSON() {
|
||
const doc2 = {};
|
||
this.share.forEach((value, key) => {
|
||
doc2[key] = value.toJSON();
|
||
});
|
||
return doc2;
|
||
}
|
||
/**
|
||
* Emit `destroy` event and unregister all event handlers.
|
||
*/
|
||
destroy() {
|
||
this.isDestroyed = true;
|
||
from2(this.subdocs).forEach((subdoc) => subdoc.destroy());
|
||
const item = this._item;
|
||
if (item !== null) {
|
||
this._item = null;
|
||
const content = (
|
||
/** @type {ContentDoc} */
|
||
item.content
|
||
);
|
||
content.doc = new _Doc({ guid: this.guid, ...content.opts, shouldLoad: false });
|
||
content.doc._item = item;
|
||
transact(
|
||
/** @type {any} */
|
||
item.parent.doc,
|
||
(transaction) => {
|
||
const doc2 = content.doc;
|
||
if (!item.deleted) {
|
||
transaction.subdocsAdded.add(doc2);
|
||
}
|
||
transaction.subdocsRemoved.add(this);
|
||
},
|
||
null,
|
||
true
|
||
);
|
||
}
|
||
this.emit("destroyed", [true]);
|
||
this.emit("destroy", [this]);
|
||
super.destroy();
|
||
}
|
||
};
|
||
var DSDecoderV1 = class {
|
||
/**
|
||
* @param {decoding.Decoder} decoder
|
||
*/
|
||
constructor(decoder) {
|
||
this.restDecoder = decoder;
|
||
}
|
||
resetDsCurVal() {
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
readDsClock() {
|
||
return readVarUint(this.restDecoder);
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
readDsLen() {
|
||
return readVarUint(this.restDecoder);
|
||
}
|
||
};
|
||
var UpdateDecoderV1 = class extends DSDecoderV1 {
|
||
/**
|
||
* @return {ID}
|
||
*/
|
||
readLeftID() {
|
||
return createID(readVarUint(this.restDecoder), readVarUint(this.restDecoder));
|
||
}
|
||
/**
|
||
* @return {ID}
|
||
*/
|
||
readRightID() {
|
||
return createID(readVarUint(this.restDecoder), readVarUint(this.restDecoder));
|
||
}
|
||
/**
|
||
* Read the next client id.
|
||
* Use this in favor of readID whenever possible to reduce the number of objects created.
|
||
*/
|
||
readClient() {
|
||
return readVarUint(this.restDecoder);
|
||
}
|
||
/**
|
||
* @return {number} info An unsigned 8-bit integer
|
||
*/
|
||
readInfo() {
|
||
return readUint8(this.restDecoder);
|
||
}
|
||
/**
|
||
* @return {string}
|
||
*/
|
||
readString() {
|
||
return readVarString(this.restDecoder);
|
||
}
|
||
/**
|
||
* @return {boolean} isKey
|
||
*/
|
||
readParentInfo() {
|
||
return readVarUint(this.restDecoder) === 1;
|
||
}
|
||
/**
|
||
* @return {number} info An unsigned 8-bit integer
|
||
*/
|
||
readTypeRef() {
|
||
return readVarUint(this.restDecoder);
|
||
}
|
||
/**
|
||
* Write len of a struct - well suited for Opt RLE encoder.
|
||
*
|
||
* @return {number} len
|
||
*/
|
||
readLen() {
|
||
return readVarUint(this.restDecoder);
|
||
}
|
||
/**
|
||
* @return {any}
|
||
*/
|
||
readAny() {
|
||
return readAny(this.restDecoder);
|
||
}
|
||
/**
|
||
* @return {Uint8Array}
|
||
*/
|
||
readBuf() {
|
||
return copyUint8Array(readVarUint8Array(this.restDecoder));
|
||
}
|
||
/**
|
||
* Legacy implementation uses JSON parse. We use any-decoding in v2.
|
||
*
|
||
* @return {any}
|
||
*/
|
||
readJSON() {
|
||
return JSON.parse(readVarString(this.restDecoder));
|
||
}
|
||
/**
|
||
* @return {string}
|
||
*/
|
||
readKey() {
|
||
return readVarString(this.restDecoder);
|
||
}
|
||
};
|
||
var DSDecoderV2 = class {
|
||
/**
|
||
* @param {decoding.Decoder} decoder
|
||
*/
|
||
constructor(decoder) {
|
||
this.dsCurrVal = 0;
|
||
this.restDecoder = decoder;
|
||
}
|
||
resetDsCurVal() {
|
||
this.dsCurrVal = 0;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
readDsClock() {
|
||
this.dsCurrVal += readVarUint(this.restDecoder);
|
||
return this.dsCurrVal;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
readDsLen() {
|
||
const diff = readVarUint(this.restDecoder) + 1;
|
||
this.dsCurrVal += diff;
|
||
return diff;
|
||
}
|
||
};
|
||
var UpdateDecoderV2 = class extends DSDecoderV2 {
|
||
/**
|
||
* @param {decoding.Decoder} decoder
|
||
*/
|
||
constructor(decoder) {
|
||
super(decoder);
|
||
this.keys = [];
|
||
readVarUint(decoder);
|
||
this.keyClockDecoder = new IntDiffOptRleDecoder(readVarUint8Array(decoder));
|
||
this.clientDecoder = new UintOptRleDecoder(readVarUint8Array(decoder));
|
||
this.leftClockDecoder = new IntDiffOptRleDecoder(readVarUint8Array(decoder));
|
||
this.rightClockDecoder = new IntDiffOptRleDecoder(readVarUint8Array(decoder));
|
||
this.infoDecoder = new RleDecoder(readVarUint8Array(decoder), readUint8);
|
||
this.stringDecoder = new StringDecoder(readVarUint8Array(decoder));
|
||
this.parentInfoDecoder = new RleDecoder(readVarUint8Array(decoder), readUint8);
|
||
this.typeRefDecoder = new UintOptRleDecoder(readVarUint8Array(decoder));
|
||
this.lenDecoder = new UintOptRleDecoder(readVarUint8Array(decoder));
|
||
}
|
||
/**
|
||
* @return {ID}
|
||
*/
|
||
readLeftID() {
|
||
return new ID(this.clientDecoder.read(), this.leftClockDecoder.read());
|
||
}
|
||
/**
|
||
* @return {ID}
|
||
*/
|
||
readRightID() {
|
||
return new ID(this.clientDecoder.read(), this.rightClockDecoder.read());
|
||
}
|
||
/**
|
||
* Read the next client id.
|
||
* Use this in favor of readID whenever possible to reduce the number of objects created.
|
||
*/
|
||
readClient() {
|
||
return this.clientDecoder.read();
|
||
}
|
||
/**
|
||
* @return {number} info An unsigned 8-bit integer
|
||
*/
|
||
readInfo() {
|
||
return (
|
||
/** @type {number} */
|
||
this.infoDecoder.read()
|
||
);
|
||
}
|
||
/**
|
||
* @return {string}
|
||
*/
|
||
readString() {
|
||
return this.stringDecoder.read();
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
readParentInfo() {
|
||
return this.parentInfoDecoder.read() === 1;
|
||
}
|
||
/**
|
||
* @return {number} An unsigned 8-bit integer
|
||
*/
|
||
readTypeRef() {
|
||
return this.typeRefDecoder.read();
|
||
}
|
||
/**
|
||
* Write len of a struct - well suited for Opt RLE encoder.
|
||
*
|
||
* @return {number}
|
||
*/
|
||
readLen() {
|
||
return this.lenDecoder.read();
|
||
}
|
||
/**
|
||
* @return {any}
|
||
*/
|
||
readAny() {
|
||
return readAny(this.restDecoder);
|
||
}
|
||
/**
|
||
* @return {Uint8Array}
|
||
*/
|
||
readBuf() {
|
||
return readVarUint8Array(this.restDecoder);
|
||
}
|
||
/**
|
||
* This is mainly here for legacy purposes.
|
||
*
|
||
* Initial we incoded objects using JSON. Now we use the much faster lib0/any-encoder. This method mainly exists for legacy purposes for the v1 encoder.
|
||
*
|
||
* @return {any}
|
||
*/
|
||
readJSON() {
|
||
return readAny(this.restDecoder);
|
||
}
|
||
/**
|
||
* @return {string}
|
||
*/
|
||
readKey() {
|
||
const keyClock = this.keyClockDecoder.read();
|
||
if (keyClock < this.keys.length) {
|
||
return this.keys[keyClock];
|
||
} else {
|
||
const key = this.stringDecoder.read();
|
||
this.keys.push(key);
|
||
return key;
|
||
}
|
||
}
|
||
};
|
||
var DSEncoderV1 = class {
|
||
constructor() {
|
||
this.restEncoder = createEncoder();
|
||
}
|
||
toUint8Array() {
|
||
return toUint8Array(this.restEncoder);
|
||
}
|
||
resetDsCurVal() {
|
||
}
|
||
/**
|
||
* @param {number} clock
|
||
*/
|
||
writeDsClock(clock) {
|
||
writeVarUint(this.restEncoder, clock);
|
||
}
|
||
/**
|
||
* @param {number} len
|
||
*/
|
||
writeDsLen(len) {
|
||
writeVarUint(this.restEncoder, len);
|
||
}
|
||
};
|
||
var UpdateEncoderV1 = class extends DSEncoderV1 {
|
||
/**
|
||
* @param {ID} id
|
||
*/
|
||
writeLeftID(id2) {
|
||
writeVarUint(this.restEncoder, id2.client);
|
||
writeVarUint(this.restEncoder, id2.clock);
|
||
}
|
||
/**
|
||
* @param {ID} id
|
||
*/
|
||
writeRightID(id2) {
|
||
writeVarUint(this.restEncoder, id2.client);
|
||
writeVarUint(this.restEncoder, id2.clock);
|
||
}
|
||
/**
|
||
* Use writeClient and writeClock instead of writeID if possible.
|
||
* @param {number} client
|
||
*/
|
||
writeClient(client) {
|
||
writeVarUint(this.restEncoder, client);
|
||
}
|
||
/**
|
||
* @param {number} info An unsigned 8-bit integer
|
||
*/
|
||
writeInfo(info) {
|
||
writeUint8(this.restEncoder, info);
|
||
}
|
||
/**
|
||
* @param {string} s
|
||
*/
|
||
writeString(s) {
|
||
writeVarString(this.restEncoder, s);
|
||
}
|
||
/**
|
||
* @param {boolean} isYKey
|
||
*/
|
||
writeParentInfo(isYKey) {
|
||
writeVarUint(this.restEncoder, isYKey ? 1 : 0);
|
||
}
|
||
/**
|
||
* @param {number} info An unsigned 8-bit integer
|
||
*/
|
||
writeTypeRef(info) {
|
||
writeVarUint(this.restEncoder, info);
|
||
}
|
||
/**
|
||
* Write len of a struct - well suited for Opt RLE encoder.
|
||
*
|
||
* @param {number} len
|
||
*/
|
||
writeLen(len) {
|
||
writeVarUint(this.restEncoder, len);
|
||
}
|
||
/**
|
||
* @param {any} any
|
||
*/
|
||
writeAny(any2) {
|
||
writeAny(this.restEncoder, any2);
|
||
}
|
||
/**
|
||
* @param {Uint8Array} buf
|
||
*/
|
||
writeBuf(buf) {
|
||
writeVarUint8Array(this.restEncoder, buf);
|
||
}
|
||
/**
|
||
* @param {any} embed
|
||
*/
|
||
writeJSON(embed) {
|
||
writeVarString(this.restEncoder, JSON.stringify(embed));
|
||
}
|
||
/**
|
||
* @param {string} key
|
||
*/
|
||
writeKey(key) {
|
||
writeVarString(this.restEncoder, key);
|
||
}
|
||
};
|
||
var DSEncoderV2 = class {
|
||
constructor() {
|
||
this.restEncoder = createEncoder();
|
||
this.dsCurrVal = 0;
|
||
}
|
||
toUint8Array() {
|
||
return toUint8Array(this.restEncoder);
|
||
}
|
||
resetDsCurVal() {
|
||
this.dsCurrVal = 0;
|
||
}
|
||
/**
|
||
* @param {number} clock
|
||
*/
|
||
writeDsClock(clock) {
|
||
const diff = clock - this.dsCurrVal;
|
||
this.dsCurrVal = clock;
|
||
writeVarUint(this.restEncoder, diff);
|
||
}
|
||
/**
|
||
* @param {number} len
|
||
*/
|
||
writeDsLen(len) {
|
||
if (len === 0) {
|
||
unexpectedCase();
|
||
}
|
||
writeVarUint(this.restEncoder, len - 1);
|
||
this.dsCurrVal += len;
|
||
}
|
||
};
|
||
var UpdateEncoderV2 = class extends DSEncoderV2 {
|
||
constructor() {
|
||
super();
|
||
this.keyMap = /* @__PURE__ */ new Map();
|
||
this.keyClock = 0;
|
||
this.keyClockEncoder = new IntDiffOptRleEncoder();
|
||
this.clientEncoder = new UintOptRleEncoder();
|
||
this.leftClockEncoder = new IntDiffOptRleEncoder();
|
||
this.rightClockEncoder = new IntDiffOptRleEncoder();
|
||
this.infoEncoder = new RleEncoder(writeUint8);
|
||
this.stringEncoder = new StringEncoder();
|
||
this.parentInfoEncoder = new RleEncoder(writeUint8);
|
||
this.typeRefEncoder = new UintOptRleEncoder();
|
||
this.lenEncoder = new UintOptRleEncoder();
|
||
}
|
||
toUint8Array() {
|
||
const encoder = createEncoder();
|
||
writeVarUint(encoder, 0);
|
||
writeVarUint8Array(encoder, this.keyClockEncoder.toUint8Array());
|
||
writeVarUint8Array(encoder, this.clientEncoder.toUint8Array());
|
||
writeVarUint8Array(encoder, this.leftClockEncoder.toUint8Array());
|
||
writeVarUint8Array(encoder, this.rightClockEncoder.toUint8Array());
|
||
writeVarUint8Array(encoder, toUint8Array(this.infoEncoder));
|
||
writeVarUint8Array(encoder, this.stringEncoder.toUint8Array());
|
||
writeVarUint8Array(encoder, toUint8Array(this.parentInfoEncoder));
|
||
writeVarUint8Array(encoder, this.typeRefEncoder.toUint8Array());
|
||
writeVarUint8Array(encoder, this.lenEncoder.toUint8Array());
|
||
writeUint8Array(encoder, toUint8Array(this.restEncoder));
|
||
return toUint8Array(encoder);
|
||
}
|
||
/**
|
||
* @param {ID} id
|
||
*/
|
||
writeLeftID(id2) {
|
||
this.clientEncoder.write(id2.client);
|
||
this.leftClockEncoder.write(id2.clock);
|
||
}
|
||
/**
|
||
* @param {ID} id
|
||
*/
|
||
writeRightID(id2) {
|
||
this.clientEncoder.write(id2.client);
|
||
this.rightClockEncoder.write(id2.clock);
|
||
}
|
||
/**
|
||
* @param {number} client
|
||
*/
|
||
writeClient(client) {
|
||
this.clientEncoder.write(client);
|
||
}
|
||
/**
|
||
* @param {number} info An unsigned 8-bit integer
|
||
*/
|
||
writeInfo(info) {
|
||
this.infoEncoder.write(info);
|
||
}
|
||
/**
|
||
* @param {string} s
|
||
*/
|
||
writeString(s) {
|
||
this.stringEncoder.write(s);
|
||
}
|
||
/**
|
||
* @param {boolean} isYKey
|
||
*/
|
||
writeParentInfo(isYKey) {
|
||
this.parentInfoEncoder.write(isYKey ? 1 : 0);
|
||
}
|
||
/**
|
||
* @param {number} info An unsigned 8-bit integer
|
||
*/
|
||
writeTypeRef(info) {
|
||
this.typeRefEncoder.write(info);
|
||
}
|
||
/**
|
||
* Write len of a struct - well suited for Opt RLE encoder.
|
||
*
|
||
* @param {number} len
|
||
*/
|
||
writeLen(len) {
|
||
this.lenEncoder.write(len);
|
||
}
|
||
/**
|
||
* @param {any} any
|
||
*/
|
||
writeAny(any2) {
|
||
writeAny(this.restEncoder, any2);
|
||
}
|
||
/**
|
||
* @param {Uint8Array} buf
|
||
*/
|
||
writeBuf(buf) {
|
||
writeVarUint8Array(this.restEncoder, buf);
|
||
}
|
||
/**
|
||
* This is mainly here for legacy purposes.
|
||
*
|
||
* Initial we incoded objects using JSON. Now we use the much faster lib0/any-encoder. This method mainly exists for legacy purposes for the v1 encoder.
|
||
*
|
||
* @param {any} embed
|
||
*/
|
||
writeJSON(embed) {
|
||
writeAny(this.restEncoder, embed);
|
||
}
|
||
/**
|
||
* Property keys are often reused. For example, in y-prosemirror the key `bold` might
|
||
* occur very often. For a 3d application, the key `position` might occur very often.
|
||
*
|
||
* We cache these keys in a Map and refer to them via a unique number.
|
||
*
|
||
* @param {string} key
|
||
*/
|
||
writeKey(key) {
|
||
const clock = this.keyMap.get(key);
|
||
if (clock === void 0) {
|
||
this.keyClockEncoder.write(this.keyClock++);
|
||
this.stringEncoder.write(key);
|
||
} else {
|
||
this.keyClockEncoder.write(clock);
|
||
}
|
||
}
|
||
};
|
||
var writeStructs = (encoder, structs, client, clock) => {
|
||
clock = max(clock, structs[0].id.clock);
|
||
const startNewStructs = findIndexSS(structs, clock);
|
||
writeVarUint(encoder.restEncoder, structs.length - startNewStructs);
|
||
encoder.writeClient(client);
|
||
writeVarUint(encoder.restEncoder, clock);
|
||
const firstStruct = structs[startNewStructs];
|
||
firstStruct.write(encoder, clock - firstStruct.id.clock);
|
||
for (let i = startNewStructs + 1; i < structs.length; i++) {
|
||
structs[i].write(encoder, 0);
|
||
}
|
||
};
|
||
var writeClientsStructs = (encoder, store, _sm) => {
|
||
const sm = /* @__PURE__ */ new Map();
|
||
_sm.forEach((clock, client) => {
|
||
if (getState(store, client) > clock) {
|
||
sm.set(client, clock);
|
||
}
|
||
});
|
||
getStateVector(store).forEach((_clock, client) => {
|
||
if (!_sm.has(client)) {
|
||
sm.set(client, 0);
|
||
}
|
||
});
|
||
writeVarUint(encoder.restEncoder, sm.size);
|
||
from2(sm.entries()).sort((a, b) => b[0] - a[0]).forEach(([client, clock]) => {
|
||
writeStructs(
|
||
encoder,
|
||
/** @type {Array<GC|Item>} */
|
||
store.clients.get(client),
|
||
client,
|
||
clock
|
||
);
|
||
});
|
||
};
|
||
var readClientsStructRefs = (decoder, doc2) => {
|
||
const clientRefs = create();
|
||
const numOfStateUpdates = readVarUint(decoder.restDecoder);
|
||
for (let i = 0; i < numOfStateUpdates; i++) {
|
||
const numberOfStructs = readVarUint(decoder.restDecoder);
|
||
const refs = new Array(numberOfStructs);
|
||
const client = decoder.readClient();
|
||
let clock = readVarUint(decoder.restDecoder);
|
||
clientRefs.set(client, { i: 0, refs });
|
||
for (let i2 = 0; i2 < numberOfStructs; i2++) {
|
||
const info = decoder.readInfo();
|
||
switch (BITS5 & info) {
|
||
case 0: {
|
||
const len = decoder.readLen();
|
||
refs[i2] = new GC(createID(client, clock), len);
|
||
clock += len;
|
||
break;
|
||
}
|
||
case 10: {
|
||
const len = readVarUint(decoder.restDecoder);
|
||
refs[i2] = new Skip(createID(client, clock), len);
|
||
clock += len;
|
||
break;
|
||
}
|
||
default: {
|
||
const cantCopyParentInfo = (info & (BIT7 | BIT8)) === 0;
|
||
const struct = new Item(
|
||
createID(client, clock),
|
||
null,
|
||
// left
|
||
(info & BIT8) === BIT8 ? decoder.readLeftID() : null,
|
||
// origin
|
||
null,
|
||
// right
|
||
(info & BIT7) === BIT7 ? decoder.readRightID() : null,
|
||
// right origin
|
||
cantCopyParentInfo ? decoder.readParentInfo() ? doc2.get(decoder.readString()) : decoder.readLeftID() : null,
|
||
// parent
|
||
cantCopyParentInfo && (info & BIT6) === BIT6 ? decoder.readString() : null,
|
||
// parentSub
|
||
readItemContent(decoder, info)
|
||
// item content
|
||
);
|
||
refs[i2] = struct;
|
||
clock += struct.length;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return clientRefs;
|
||
};
|
||
var integrateStructs = (transaction, store, clientsStructRefs) => {
|
||
const stack = [];
|
||
let clientsStructRefsIds = from2(clientsStructRefs.keys()).sort((a, b) => a - b);
|
||
if (clientsStructRefsIds.length === 0) {
|
||
return null;
|
||
}
|
||
const getNextStructTarget = () => {
|
||
if (clientsStructRefsIds.length === 0) {
|
||
return null;
|
||
}
|
||
let nextStructsTarget = (
|
||
/** @type {{i:number,refs:Array<GC|Item>}} */
|
||
clientsStructRefs.get(clientsStructRefsIds[clientsStructRefsIds.length - 1])
|
||
);
|
||
while (nextStructsTarget.refs.length === nextStructsTarget.i) {
|
||
clientsStructRefsIds.pop();
|
||
if (clientsStructRefsIds.length > 0) {
|
||
nextStructsTarget = /** @type {{i:number,refs:Array<GC|Item>}} */
|
||
clientsStructRefs.get(clientsStructRefsIds[clientsStructRefsIds.length - 1]);
|
||
} else {
|
||
return null;
|
||
}
|
||
}
|
||
return nextStructsTarget;
|
||
};
|
||
let curStructsTarget = getNextStructTarget();
|
||
if (curStructsTarget === null) {
|
||
return null;
|
||
}
|
||
const restStructs = new StructStore();
|
||
const missingSV = /* @__PURE__ */ new Map();
|
||
const updateMissingSv = (client, clock) => {
|
||
const mclock = missingSV.get(client);
|
||
if (mclock == null || mclock > clock) {
|
||
missingSV.set(client, clock);
|
||
}
|
||
};
|
||
let stackHead = (
|
||
/** @type {any} */
|
||
curStructsTarget.refs[
|
||
/** @type {any} */
|
||
curStructsTarget.i++
|
||
]
|
||
);
|
||
const state = /* @__PURE__ */ new Map();
|
||
const addStackToRestSS = () => {
|
||
for (const item of stack) {
|
||
const client = item.id.client;
|
||
const inapplicableItems = clientsStructRefs.get(client);
|
||
if (inapplicableItems) {
|
||
inapplicableItems.i--;
|
||
restStructs.clients.set(client, inapplicableItems.refs.slice(inapplicableItems.i));
|
||
clientsStructRefs.delete(client);
|
||
inapplicableItems.i = 0;
|
||
inapplicableItems.refs = [];
|
||
} else {
|
||
restStructs.clients.set(client, [item]);
|
||
}
|
||
clientsStructRefsIds = clientsStructRefsIds.filter((c) => c !== client);
|
||
}
|
||
stack.length = 0;
|
||
};
|
||
while (true) {
|
||
if (stackHead.constructor !== Skip) {
|
||
const localClock = setIfUndefined(state, stackHead.id.client, () => getState(store, stackHead.id.client));
|
||
const offset = localClock - stackHead.id.clock;
|
||
if (offset < 0) {
|
||
stack.push(stackHead);
|
||
updateMissingSv(stackHead.id.client, stackHead.id.clock - 1);
|
||
addStackToRestSS();
|
||
} else {
|
||
const missing = stackHead.getMissing(transaction, store);
|
||
if (missing !== null) {
|
||
stack.push(stackHead);
|
||
const structRefs = clientsStructRefs.get(
|
||
/** @type {number} */
|
||
missing
|
||
) || { refs: [], i: 0 };
|
||
if (structRefs.refs.length === structRefs.i) {
|
||
updateMissingSv(
|
||
/** @type {number} */
|
||
missing,
|
||
getState(store, missing)
|
||
);
|
||
addStackToRestSS();
|
||
} else {
|
||
stackHead = structRefs.refs[structRefs.i++];
|
||
continue;
|
||
}
|
||
} else if (offset === 0 || offset < stackHead.length) {
|
||
stackHead.integrate(transaction, offset);
|
||
state.set(stackHead.id.client, stackHead.id.clock + stackHead.length);
|
||
}
|
||
}
|
||
}
|
||
if (stack.length > 0) {
|
||
stackHead = /** @type {GC|Item} */
|
||
stack.pop();
|
||
} else if (curStructsTarget !== null && curStructsTarget.i < curStructsTarget.refs.length) {
|
||
stackHead = /** @type {GC|Item} */
|
||
curStructsTarget.refs[curStructsTarget.i++];
|
||
} else {
|
||
curStructsTarget = getNextStructTarget();
|
||
if (curStructsTarget === null) {
|
||
break;
|
||
} else {
|
||
stackHead = /** @type {GC|Item} */
|
||
curStructsTarget.refs[curStructsTarget.i++];
|
||
}
|
||
}
|
||
}
|
||
if (restStructs.clients.size > 0) {
|
||
const encoder = new UpdateEncoderV2();
|
||
writeClientsStructs(encoder, restStructs, /* @__PURE__ */ new Map());
|
||
writeVarUint(encoder.restEncoder, 0);
|
||
return { missing: missingSV, update: encoder.toUint8Array() };
|
||
}
|
||
return null;
|
||
};
|
||
var writeStructsFromTransaction = (encoder, transaction) => writeClientsStructs(encoder, transaction.doc.store, transaction.beforeState);
|
||
var readUpdateV2 = (decoder, ydoc, transactionOrigin, structDecoder = new UpdateDecoderV2(decoder)) => transact(ydoc, (transaction) => {
|
||
transaction.local = false;
|
||
let retry = false;
|
||
const doc2 = transaction.doc;
|
||
const store = doc2.store;
|
||
const ss = readClientsStructRefs(structDecoder, doc2);
|
||
const restStructs = integrateStructs(transaction, store, ss);
|
||
const pending = store.pendingStructs;
|
||
if (pending) {
|
||
for (const [client, clock] of pending.missing) {
|
||
if (clock < getState(store, client)) {
|
||
retry = true;
|
||
break;
|
||
}
|
||
}
|
||
if (restStructs) {
|
||
for (const [client, clock] of restStructs.missing) {
|
||
const mclock = pending.missing.get(client);
|
||
if (mclock == null || mclock > clock) {
|
||
pending.missing.set(client, clock);
|
||
}
|
||
}
|
||
pending.update = mergeUpdatesV2([pending.update, restStructs.update]);
|
||
}
|
||
} else {
|
||
store.pendingStructs = restStructs;
|
||
}
|
||
const dsRest = readAndApplyDeleteSet(structDecoder, transaction, store);
|
||
if (store.pendingDs) {
|
||
const pendingDSUpdate = new UpdateDecoderV2(createDecoder(store.pendingDs));
|
||
readVarUint(pendingDSUpdate.restDecoder);
|
||
const dsRest2 = readAndApplyDeleteSet(pendingDSUpdate, transaction, store);
|
||
if (dsRest && dsRest2) {
|
||
store.pendingDs = mergeUpdatesV2([dsRest, dsRest2]);
|
||
} else {
|
||
store.pendingDs = dsRest || dsRest2;
|
||
}
|
||
} else {
|
||
store.pendingDs = dsRest;
|
||
}
|
||
if (retry) {
|
||
const update = (
|
||
/** @type {{update: Uint8Array}} */
|
||
store.pendingStructs.update
|
||
);
|
||
store.pendingStructs = null;
|
||
applyUpdateV2(transaction.doc, update);
|
||
}
|
||
}, transactionOrigin, false);
|
||
var readUpdate = (decoder, ydoc, transactionOrigin) => readUpdateV2(decoder, ydoc, transactionOrigin, new UpdateDecoderV1(decoder));
|
||
var applyUpdateV2 = (ydoc, update, transactionOrigin, YDecoder = UpdateDecoderV2) => {
|
||
const decoder = createDecoder(update);
|
||
readUpdateV2(decoder, ydoc, transactionOrigin, new YDecoder(decoder));
|
||
};
|
||
var applyUpdate = (ydoc, update, transactionOrigin) => applyUpdateV2(ydoc, update, transactionOrigin, UpdateDecoderV1);
|
||
var writeStateAsUpdate = (encoder, doc2, targetStateVector = /* @__PURE__ */ new Map()) => {
|
||
writeClientsStructs(encoder, doc2.store, targetStateVector);
|
||
writeDeleteSet(encoder, createDeleteSetFromStructStore(doc2.store));
|
||
};
|
||
var encodeStateAsUpdateV2 = (doc2, encodedTargetStateVector = new Uint8Array([0]), encoder = new UpdateEncoderV2()) => {
|
||
const targetStateVector = decodeStateVector(encodedTargetStateVector);
|
||
writeStateAsUpdate(encoder, doc2, targetStateVector);
|
||
const updates = [encoder.toUint8Array()];
|
||
if (doc2.store.pendingDs) {
|
||
updates.push(doc2.store.pendingDs);
|
||
}
|
||
if (doc2.store.pendingStructs) {
|
||
updates.push(diffUpdateV2(doc2.store.pendingStructs.update, encodedTargetStateVector));
|
||
}
|
||
if (updates.length > 1) {
|
||
if (encoder.constructor === UpdateEncoderV1) {
|
||
return mergeUpdates(updates.map((update, i) => i === 0 ? update : convertUpdateFormatV2ToV1(update)));
|
||
} else if (encoder.constructor === UpdateEncoderV2) {
|
||
return mergeUpdatesV2(updates);
|
||
}
|
||
}
|
||
return updates[0];
|
||
};
|
||
var encodeStateAsUpdate = (doc2, encodedTargetStateVector) => encodeStateAsUpdateV2(doc2, encodedTargetStateVector, new UpdateEncoderV1());
|
||
var readStateVector = (decoder) => {
|
||
const ss = /* @__PURE__ */ new Map();
|
||
const ssLength = readVarUint(decoder.restDecoder);
|
||
for (let i = 0; i < ssLength; i++) {
|
||
const client = readVarUint(decoder.restDecoder);
|
||
const clock = readVarUint(decoder.restDecoder);
|
||
ss.set(client, clock);
|
||
}
|
||
return ss;
|
||
};
|
||
var decodeStateVector = (decodedState) => readStateVector(new DSDecoderV1(createDecoder(decodedState)));
|
||
var writeStateVector = (encoder, sv) => {
|
||
writeVarUint(encoder.restEncoder, sv.size);
|
||
from2(sv.entries()).sort((a, b) => b[0] - a[0]).forEach(([client, clock]) => {
|
||
writeVarUint(encoder.restEncoder, client);
|
||
writeVarUint(encoder.restEncoder, clock);
|
||
});
|
||
return encoder;
|
||
};
|
||
var writeDocumentStateVector = (encoder, doc2) => writeStateVector(encoder, getStateVector(doc2.store));
|
||
var encodeStateVectorV2 = (doc2, encoder = new DSEncoderV2()) => {
|
||
if (doc2 instanceof Map) {
|
||
writeStateVector(encoder, doc2);
|
||
} else {
|
||
writeDocumentStateVector(encoder, doc2);
|
||
}
|
||
return encoder.toUint8Array();
|
||
};
|
||
var encodeStateVector = (doc2) => encodeStateVectorV2(doc2, new DSEncoderV1());
|
||
var EventHandler = class {
|
||
constructor() {
|
||
this.l = [];
|
||
}
|
||
};
|
||
var createEventHandler = () => new EventHandler();
|
||
var addEventHandlerListener = (eventHandler, f) => eventHandler.l.push(f);
|
||
var removeEventHandlerListener = (eventHandler, f) => {
|
||
const l = eventHandler.l;
|
||
const len = l.length;
|
||
eventHandler.l = l.filter((g) => f !== g);
|
||
if (len === eventHandler.l.length) {
|
||
console.error("[yjs] Tried to remove event handler that doesn't exist.");
|
||
}
|
||
};
|
||
var callEventHandlerListeners = (eventHandler, arg0, arg1) => callAll(eventHandler.l, [arg0, arg1]);
|
||
var ID = class {
|
||
/**
|
||
* @param {number} client client id
|
||
* @param {number} clock unique per client id, continuous number
|
||
*/
|
||
constructor(client, clock) {
|
||
this.client = client;
|
||
this.clock = clock;
|
||
}
|
||
};
|
||
var compareIDs = (a, b) => a === b || a !== null && b !== null && a.client === b.client && a.clock === b.clock;
|
||
var createID = (client, clock) => new ID(client, clock);
|
||
var writeID = (encoder, id2) => {
|
||
writeVarUint(encoder, id2.client);
|
||
writeVarUint(encoder, id2.clock);
|
||
};
|
||
var readID = (decoder) => createID(readVarUint(decoder), readVarUint(decoder));
|
||
var findRootTypeKey = (type) => {
|
||
for (const [key, value] of type.doc.share.entries()) {
|
||
if (value === type) {
|
||
return key;
|
||
}
|
||
}
|
||
throw unexpectedCase();
|
||
};
|
||
var isParentOf = (parent, child) => {
|
||
while (child !== null) {
|
||
if (child.parent === parent) {
|
||
return true;
|
||
}
|
||
child = /** @type {AbstractType<any>} */
|
||
child.parent._item;
|
||
}
|
||
return false;
|
||
};
|
||
var logType = (type) => {
|
||
const res = [];
|
||
let n = type._start;
|
||
while (n) {
|
||
res.push(n);
|
||
n = n.right;
|
||
}
|
||
console.log("Children: ", res);
|
||
console.log("Children content: ", res.filter((m) => !m.deleted).map((m) => m.content));
|
||
};
|
||
var PermanentUserData = class {
|
||
/**
|
||
* @param {Doc} doc
|
||
* @param {YMap<any>} [storeType]
|
||
*/
|
||
constructor(doc2, storeType = doc2.getMap("users")) {
|
||
const dss = /* @__PURE__ */ new Map();
|
||
this.yusers = storeType;
|
||
this.doc = doc2;
|
||
this.clients = /* @__PURE__ */ new Map();
|
||
this.dss = dss;
|
||
const initUser = (user, userDescription) => {
|
||
const ds = user.get("ds");
|
||
const ids = user.get("ids");
|
||
const addClientId = (
|
||
/** @param {number} clientid */
|
||
(clientid) => this.clients.set(clientid, userDescription)
|
||
);
|
||
ds.observe(
|
||
/** @param {YArrayEvent<any>} event */
|
||
(event) => {
|
||
event.changes.added.forEach((item) => {
|
||
item.content.getContent().forEach((encodedDs) => {
|
||
if (encodedDs instanceof Uint8Array) {
|
||
this.dss.set(userDescription, mergeDeleteSets([this.dss.get(userDescription) || createDeleteSet(), readDeleteSet(new DSDecoderV1(createDecoder(encodedDs)))]));
|
||
}
|
||
});
|
||
});
|
||
}
|
||
);
|
||
this.dss.set(userDescription, mergeDeleteSets(ds.map((encodedDs) => readDeleteSet(new DSDecoderV1(createDecoder(encodedDs))))));
|
||
ids.observe(
|
||
/** @param {YArrayEvent<any>} event */
|
||
(event) => event.changes.added.forEach((item) => item.content.getContent().forEach(addClientId))
|
||
);
|
||
ids.forEach(addClientId);
|
||
};
|
||
storeType.observe((event) => {
|
||
event.keysChanged.forEach(
|
||
(userDescription) => initUser(storeType.get(userDescription), userDescription)
|
||
);
|
||
});
|
||
storeType.forEach(initUser);
|
||
}
|
||
/**
|
||
* @param {Doc} doc
|
||
* @param {number} clientid
|
||
* @param {string} userDescription
|
||
* @param {Object} conf
|
||
* @param {function(Transaction, DeleteSet):boolean} [conf.filter]
|
||
*/
|
||
setUserMapping(doc2, clientid, userDescription, { filter = () => true } = {}) {
|
||
const users = this.yusers;
|
||
let user = users.get(userDescription);
|
||
if (!user) {
|
||
user = new YMap();
|
||
user.set("ids", new YArray());
|
||
user.set("ds", new YArray());
|
||
users.set(userDescription, user);
|
||
}
|
||
user.get("ids").push([clientid]);
|
||
users.observe((_event) => {
|
||
setTimeout(() => {
|
||
const userOverwrite = users.get(userDescription);
|
||
if (userOverwrite !== user) {
|
||
user = userOverwrite;
|
||
this.clients.forEach((_userDescription, clientid2) => {
|
||
if (userDescription === _userDescription) {
|
||
user.get("ids").push([clientid2]);
|
||
}
|
||
});
|
||
const encoder = new DSEncoderV1();
|
||
const ds = this.dss.get(userDescription);
|
||
if (ds) {
|
||
writeDeleteSet(encoder, ds);
|
||
user.get("ds").push([encoder.toUint8Array()]);
|
||
}
|
||
}
|
||
}, 0);
|
||
});
|
||
doc2.on(
|
||
"afterTransaction",
|
||
/** @param {Transaction} transaction */
|
||
(transaction) => {
|
||
setTimeout(() => {
|
||
const yds = user.get("ds");
|
||
const ds = transaction.deleteSet;
|
||
if (transaction.local && ds.clients.size > 0 && filter(transaction, ds)) {
|
||
const encoder = new DSEncoderV1();
|
||
writeDeleteSet(encoder, ds);
|
||
yds.push([encoder.toUint8Array()]);
|
||
}
|
||
});
|
||
}
|
||
);
|
||
}
|
||
/**
|
||
* @param {number} clientid
|
||
* @return {any}
|
||
*/
|
||
getUserByClientId(clientid) {
|
||
return this.clients.get(clientid) || null;
|
||
}
|
||
/**
|
||
* @param {ID} id
|
||
* @return {string | null}
|
||
*/
|
||
getUserByDeletedId(id2) {
|
||
for (const [userDescription, ds] of this.dss.entries()) {
|
||
if (isDeleted(ds, id2)) {
|
||
return userDescription;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
};
|
||
var RelativePosition = class {
|
||
/**
|
||
* @param {ID|null} type
|
||
* @param {string|null} tname
|
||
* @param {ID|null} item
|
||
* @param {number} assoc
|
||
*/
|
||
constructor(type, tname, item, assoc = 0) {
|
||
this.type = type;
|
||
this.tname = tname;
|
||
this.item = item;
|
||
this.assoc = assoc;
|
||
}
|
||
};
|
||
var relativePositionToJSON = (rpos) => {
|
||
const json = {};
|
||
if (rpos.type) {
|
||
json.type = rpos.type;
|
||
}
|
||
if (rpos.tname) {
|
||
json.tname = rpos.tname;
|
||
}
|
||
if (rpos.item) {
|
||
json.item = rpos.item;
|
||
}
|
||
if (rpos.assoc != null) {
|
||
json.assoc = rpos.assoc;
|
||
}
|
||
return json;
|
||
};
|
||
var createRelativePositionFromJSON = (json) => new RelativePosition(json.type == null ? null : createID(json.type.client, json.type.clock), json.tname ?? null, json.item == null ? null : createID(json.item.client, json.item.clock), json.assoc == null ? 0 : json.assoc);
|
||
var AbsolutePosition = class {
|
||
/**
|
||
* @param {AbstractType<any>} type
|
||
* @param {number} index
|
||
* @param {number} [assoc]
|
||
*/
|
||
constructor(type, index, assoc = 0) {
|
||
this.type = type;
|
||
this.index = index;
|
||
this.assoc = assoc;
|
||
}
|
||
};
|
||
var createAbsolutePosition = (type, index, assoc = 0) => new AbsolutePosition(type, index, assoc);
|
||
var createRelativePosition = (type, item, assoc) => {
|
||
let typeid = null;
|
||
let tname = null;
|
||
if (type._item === null) {
|
||
tname = findRootTypeKey(type);
|
||
} else {
|
||
typeid = createID(type._item.id.client, type._item.id.clock);
|
||
}
|
||
return new RelativePosition(typeid, tname, item, assoc);
|
||
};
|
||
var createRelativePositionFromTypeIndex = (type, index, assoc = 0) => {
|
||
let t = type._start;
|
||
if (assoc < 0) {
|
||
if (index === 0) {
|
||
return createRelativePosition(type, null, assoc);
|
||
}
|
||
index--;
|
||
}
|
||
while (t !== null) {
|
||
if (!t.deleted && t.countable) {
|
||
if (t.length > index) {
|
||
return createRelativePosition(type, createID(t.id.client, t.id.clock + index), assoc);
|
||
}
|
||
index -= t.length;
|
||
}
|
||
if (t.right === null && assoc < 0) {
|
||
return createRelativePosition(type, t.lastId, assoc);
|
||
}
|
||
t = t.right;
|
||
}
|
||
return createRelativePosition(type, null, assoc);
|
||
};
|
||
var writeRelativePosition = (encoder, rpos) => {
|
||
const { type, tname, item, assoc } = rpos;
|
||
if (item !== null) {
|
||
writeVarUint(encoder, 0);
|
||
writeID(encoder, item);
|
||
} else if (tname !== null) {
|
||
writeUint8(encoder, 1);
|
||
writeVarString(encoder, tname);
|
||
} else if (type !== null) {
|
||
writeUint8(encoder, 2);
|
||
writeID(encoder, type);
|
||
} else {
|
||
throw unexpectedCase();
|
||
}
|
||
writeVarInt(encoder, assoc);
|
||
return encoder;
|
||
};
|
||
var encodeRelativePosition = (rpos) => {
|
||
const encoder = createEncoder();
|
||
writeRelativePosition(encoder, rpos);
|
||
return toUint8Array(encoder);
|
||
};
|
||
var readRelativePosition = (decoder) => {
|
||
let type = null;
|
||
let tname = null;
|
||
let itemID = null;
|
||
switch (readVarUint(decoder)) {
|
||
case 0:
|
||
itemID = readID(decoder);
|
||
break;
|
||
case 1:
|
||
tname = readVarString(decoder);
|
||
break;
|
||
case 2: {
|
||
type = readID(decoder);
|
||
}
|
||
}
|
||
const assoc = hasContent(decoder) ? readVarInt(decoder) : 0;
|
||
return new RelativePosition(type, tname, itemID, assoc);
|
||
};
|
||
var decodeRelativePosition = (uint8Array) => readRelativePosition(createDecoder(uint8Array));
|
||
var getItemWithOffset = (store, id2) => {
|
||
const item = getItem(store, id2);
|
||
const diff = id2.clock - item.id.clock;
|
||
return {
|
||
item,
|
||
diff
|
||
};
|
||
};
|
||
var createAbsolutePositionFromRelativePosition = (rpos, doc2, followUndoneDeletions = true) => {
|
||
const store = doc2.store;
|
||
const rightID = rpos.item;
|
||
const typeID = rpos.type;
|
||
const tname = rpos.tname;
|
||
const assoc = rpos.assoc;
|
||
let type = null;
|
||
let index = 0;
|
||
if (rightID !== null) {
|
||
if (getState(store, rightID.client) <= rightID.clock) {
|
||
return null;
|
||
}
|
||
const res = followUndoneDeletions ? followRedone(store, rightID) : getItemWithOffset(store, rightID);
|
||
const right = res.item;
|
||
if (!(right instanceof Item)) {
|
||
return null;
|
||
}
|
||
type = /** @type {AbstractType<any>} */
|
||
right.parent;
|
||
if (type._item === null || !type._item.deleted) {
|
||
index = right.deleted || !right.countable ? 0 : res.diff + (assoc >= 0 ? 0 : 1);
|
||
let n = right.left;
|
||
while (n !== null) {
|
||
if (!n.deleted && n.countable) {
|
||
index += n.length;
|
||
}
|
||
n = n.left;
|
||
}
|
||
}
|
||
} else {
|
||
if (tname !== null) {
|
||
type = doc2.get(tname);
|
||
} else if (typeID !== null) {
|
||
if (getState(store, typeID.client) <= typeID.clock) {
|
||
return null;
|
||
}
|
||
const { item } = followUndoneDeletions ? followRedone(store, typeID) : { item: getItem(store, typeID) };
|
||
if (item instanceof Item && item.content instanceof ContentType) {
|
||
type = item.content.type;
|
||
} else {
|
||
return null;
|
||
}
|
||
} else {
|
||
throw unexpectedCase();
|
||
}
|
||
if (assoc >= 0) {
|
||
index = type._length;
|
||
} else {
|
||
index = 0;
|
||
}
|
||
}
|
||
return createAbsolutePosition(type, index, rpos.assoc);
|
||
};
|
||
var compareRelativePositions = (a, b) => a === b || a !== null && b !== null && a.tname === b.tname && compareIDs(a.item, b.item) && compareIDs(a.type, b.type) && a.assoc === b.assoc;
|
||
var Snapshot = class {
|
||
/**
|
||
* @param {DeleteSet} ds
|
||
* @param {Map<number,number>} sv state map
|
||
*/
|
||
constructor(ds, sv) {
|
||
this.ds = ds;
|
||
this.sv = sv;
|
||
}
|
||
};
|
||
var equalSnapshots = (snap1, snap2) => {
|
||
const ds1 = snap1.ds.clients;
|
||
const ds2 = snap2.ds.clients;
|
||
const sv1 = snap1.sv;
|
||
const sv2 = snap2.sv;
|
||
if (sv1.size !== sv2.size || ds1.size !== ds2.size) {
|
||
return false;
|
||
}
|
||
for (const [key, value] of sv1.entries()) {
|
||
if (sv2.get(key) !== value) {
|
||
return false;
|
||
}
|
||
}
|
||
for (const [client, dsitems1] of ds1.entries()) {
|
||
const dsitems2 = ds2.get(client) || [];
|
||
if (dsitems1.length !== dsitems2.length) {
|
||
return false;
|
||
}
|
||
for (let i = 0; i < dsitems1.length; i++) {
|
||
const dsitem1 = dsitems1[i];
|
||
const dsitem2 = dsitems2[i];
|
||
if (dsitem1.clock !== dsitem2.clock || dsitem1.len !== dsitem2.len) {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
var encodeSnapshotV2 = (snapshot2, encoder = new DSEncoderV2()) => {
|
||
writeDeleteSet(encoder, snapshot2.ds);
|
||
writeStateVector(encoder, snapshot2.sv);
|
||
return encoder.toUint8Array();
|
||
};
|
||
var encodeSnapshot = (snapshot2) => encodeSnapshotV2(snapshot2, new DSEncoderV1());
|
||
var decodeSnapshotV2 = (buf, decoder = new DSDecoderV2(createDecoder(buf))) => {
|
||
return new Snapshot(readDeleteSet(decoder), readStateVector(decoder));
|
||
};
|
||
var decodeSnapshot = (buf) => decodeSnapshotV2(buf, new DSDecoderV1(createDecoder(buf)));
|
||
var createSnapshot = (ds, sm) => new Snapshot(ds, sm);
|
||
var emptySnapshot = createSnapshot(createDeleteSet(), /* @__PURE__ */ new Map());
|
||
var snapshot = (doc2) => createSnapshot(createDeleteSetFromStructStore(doc2.store), getStateVector(doc2.store));
|
||
var isVisible = (item, snapshot2) => snapshot2 === void 0 ? !item.deleted : snapshot2.sv.has(item.id.client) && (snapshot2.sv.get(item.id.client) || 0) > item.id.clock && !isDeleted(snapshot2.ds, item.id);
|
||
var splitSnapshotAffectedStructs = (transaction, snapshot2) => {
|
||
const meta = setIfUndefined(transaction.meta, splitSnapshotAffectedStructs, create2);
|
||
const store = transaction.doc.store;
|
||
if (!meta.has(snapshot2)) {
|
||
snapshot2.sv.forEach((clock, client) => {
|
||
if (clock < getState(store, client)) {
|
||
getItemCleanStart(transaction, createID(client, clock));
|
||
}
|
||
});
|
||
iterateDeletedStructs(transaction, snapshot2.ds, (_item) => {
|
||
});
|
||
meta.add(snapshot2);
|
||
}
|
||
};
|
||
var createDocFromSnapshot = (originDoc, snapshot2, newDoc = new Doc()) => {
|
||
if (originDoc.gc) {
|
||
throw new Error("Garbage-collection must be disabled in `originDoc`!");
|
||
}
|
||
const { sv, ds } = snapshot2;
|
||
const encoder = new UpdateEncoderV2();
|
||
originDoc.transact((transaction) => {
|
||
let size2 = 0;
|
||
sv.forEach((clock) => {
|
||
if (clock > 0) {
|
||
size2++;
|
||
}
|
||
});
|
||
writeVarUint(encoder.restEncoder, size2);
|
||
for (const [client, clock] of sv) {
|
||
if (clock === 0) {
|
||
continue;
|
||
}
|
||
if (clock < getState(originDoc.store, client)) {
|
||
getItemCleanStart(transaction, createID(client, clock));
|
||
}
|
||
const structs = originDoc.store.clients.get(client) || [];
|
||
const lastStructIndex = findIndexSS(structs, clock - 1);
|
||
writeVarUint(encoder.restEncoder, lastStructIndex + 1);
|
||
encoder.writeClient(client);
|
||
writeVarUint(encoder.restEncoder, 0);
|
||
for (let i = 0; i <= lastStructIndex; i++) {
|
||
structs[i].write(encoder, 0);
|
||
}
|
||
}
|
||
writeDeleteSet(encoder, ds);
|
||
});
|
||
applyUpdateV2(newDoc, encoder.toUint8Array(), "snapshot");
|
||
return newDoc;
|
||
};
|
||
var snapshotContainsUpdateV2 = (snapshot2, update, YDecoder = UpdateDecoderV2) => {
|
||
const updateDecoder = new YDecoder(createDecoder(update));
|
||
const lazyDecoder = new LazyStructReader(updateDecoder, false);
|
||
for (let curr = lazyDecoder.curr; curr !== null; curr = lazyDecoder.next()) {
|
||
if ((snapshot2.sv.get(curr.id.client) || 0) < curr.id.clock + curr.length) {
|
||
return false;
|
||
}
|
||
}
|
||
const mergedDS = mergeDeleteSets([snapshot2.ds, readDeleteSet(updateDecoder)]);
|
||
return equalDeleteSets(snapshot2.ds, mergedDS);
|
||
};
|
||
var snapshotContainsUpdate = (snapshot2, update) => snapshotContainsUpdateV2(snapshot2, update, UpdateDecoderV1);
|
||
var StructStore = class {
|
||
constructor() {
|
||
this.clients = /* @__PURE__ */ new Map();
|
||
this.pendingStructs = null;
|
||
this.pendingDs = null;
|
||
}
|
||
};
|
||
var getStateVector = (store) => {
|
||
const sm = /* @__PURE__ */ new Map();
|
||
store.clients.forEach((structs, client) => {
|
||
const struct = structs[structs.length - 1];
|
||
sm.set(client, struct.id.clock + struct.length);
|
||
});
|
||
return sm;
|
||
};
|
||
var getState = (store, client) => {
|
||
const structs = store.clients.get(client);
|
||
if (structs === void 0) {
|
||
return 0;
|
||
}
|
||
const lastStruct = structs[structs.length - 1];
|
||
return lastStruct.id.clock + lastStruct.length;
|
||
};
|
||
var addStruct = (store, struct) => {
|
||
let structs = store.clients.get(struct.id.client);
|
||
if (structs === void 0) {
|
||
structs = [];
|
||
store.clients.set(struct.id.client, structs);
|
||
} else {
|
||
const lastStruct = structs[structs.length - 1];
|
||
if (lastStruct.id.clock + lastStruct.length !== struct.id.clock) {
|
||
throw unexpectedCase();
|
||
}
|
||
}
|
||
structs.push(struct);
|
||
};
|
||
var findIndexSS = (structs, clock) => {
|
||
let left = 0;
|
||
let right = structs.length - 1;
|
||
let mid = structs[right];
|
||
let midclock = mid.id.clock;
|
||
if (midclock === clock) {
|
||
return right;
|
||
}
|
||
let midindex = floor(clock / (midclock + mid.length - 1) * right);
|
||
while (left <= right) {
|
||
mid = structs[midindex];
|
||
midclock = mid.id.clock;
|
||
if (midclock <= clock) {
|
||
if (clock < midclock + mid.length) {
|
||
return midindex;
|
||
}
|
||
left = midindex + 1;
|
||
} else {
|
||
right = midindex - 1;
|
||
}
|
||
midindex = floor((left + right) / 2);
|
||
}
|
||
throw unexpectedCase();
|
||
};
|
||
var find = (store, id2) => {
|
||
const structs = store.clients.get(id2.client);
|
||
return structs[findIndexSS(structs, id2.clock)];
|
||
};
|
||
var getItem = (
|
||
/** @type {function(StructStore,ID):Item} */
|
||
find
|
||
);
|
||
var findIndexCleanStart = (transaction, structs, clock) => {
|
||
const index = findIndexSS(structs, clock);
|
||
const struct = structs[index];
|
||
if (struct.id.clock < clock && struct instanceof Item) {
|
||
structs.splice(index + 1, 0, splitItem(transaction, struct, clock - struct.id.clock));
|
||
return index + 1;
|
||
}
|
||
return index;
|
||
};
|
||
var getItemCleanStart = (transaction, id2) => {
|
||
const structs = (
|
||
/** @type {Array<Item>} */
|
||
transaction.doc.store.clients.get(id2.client)
|
||
);
|
||
return structs[findIndexCleanStart(transaction, structs, id2.clock)];
|
||
};
|
||
var getItemCleanEnd = (transaction, store, id2) => {
|
||
const structs = store.clients.get(id2.client);
|
||
const index = findIndexSS(structs, id2.clock);
|
||
const struct = structs[index];
|
||
if (id2.clock !== struct.id.clock + struct.length - 1 && struct.constructor !== GC) {
|
||
structs.splice(index + 1, 0, splitItem(transaction, struct, id2.clock - struct.id.clock + 1));
|
||
}
|
||
return struct;
|
||
};
|
||
var replaceStruct = (store, struct, newStruct) => {
|
||
const structs = (
|
||
/** @type {Array<GC|Item>} */
|
||
store.clients.get(struct.id.client)
|
||
);
|
||
structs[findIndexSS(structs, struct.id.clock)] = newStruct;
|
||
};
|
||
var iterateStructs = (transaction, structs, clockStart, len, f) => {
|
||
if (len === 0) {
|
||
return;
|
||
}
|
||
const clockEnd = clockStart + len;
|
||
let index = findIndexCleanStart(transaction, structs, clockStart);
|
||
let struct;
|
||
do {
|
||
struct = structs[index++];
|
||
if (clockEnd < struct.id.clock + struct.length) {
|
||
findIndexCleanStart(transaction, structs, clockEnd);
|
||
}
|
||
f(struct);
|
||
} while (index < structs.length && structs[index].id.clock < clockEnd);
|
||
};
|
||
var Transaction = class {
|
||
/**
|
||
* @param {Doc} doc
|
||
* @param {any} origin
|
||
* @param {boolean} local
|
||
*/
|
||
constructor(doc2, origin, local) {
|
||
this.doc = doc2;
|
||
this.deleteSet = new DeleteSet();
|
||
this.beforeState = getStateVector(doc2.store);
|
||
this.afterState = /* @__PURE__ */ new Map();
|
||
this.changed = /* @__PURE__ */ new Map();
|
||
this.changedParentTypes = /* @__PURE__ */ new Map();
|
||
this._mergeStructs = [];
|
||
this.origin = origin;
|
||
this.meta = /* @__PURE__ */ new Map();
|
||
this.local = local;
|
||
this.subdocsAdded = /* @__PURE__ */ new Set();
|
||
this.subdocsRemoved = /* @__PURE__ */ new Set();
|
||
this.subdocsLoaded = /* @__PURE__ */ new Set();
|
||
this._needFormattingCleanup = false;
|
||
}
|
||
};
|
||
var writeUpdateMessageFromTransaction = (encoder, transaction) => {
|
||
if (transaction.deleteSet.clients.size === 0 && !any(transaction.afterState, (clock, client) => transaction.beforeState.get(client) !== clock)) {
|
||
return false;
|
||
}
|
||
sortAndMergeDeleteSet(transaction.deleteSet);
|
||
writeStructsFromTransaction(encoder, transaction);
|
||
writeDeleteSet(encoder, transaction.deleteSet);
|
||
return true;
|
||
};
|
||
var addChangedTypeToTransaction = (transaction, type, parentSub) => {
|
||
const item = type._item;
|
||
if (item === null || item.id.clock < (transaction.beforeState.get(item.id.client) || 0) && !item.deleted) {
|
||
setIfUndefined(transaction.changed, type, create2).add(parentSub);
|
||
}
|
||
};
|
||
var tryToMergeWithLefts = (structs, pos) => {
|
||
let right = structs[pos];
|
||
let left = structs[pos - 1];
|
||
let i = pos;
|
||
for (; i > 0; right = left, left = structs[--i - 1]) {
|
||
if (left.deleted === right.deleted && left.constructor === right.constructor) {
|
||
if (left.mergeWith(right)) {
|
||
if (right instanceof Item && right.parentSub !== null && /** @type {AbstractType<any>} */
|
||
right.parent._map.get(right.parentSub) === right) {
|
||
right.parent._map.set(
|
||
right.parentSub,
|
||
/** @type {Item} */
|
||
left
|
||
);
|
||
}
|
||
continue;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
const merged = pos - i;
|
||
if (merged) {
|
||
structs.splice(pos + 1 - merged, merged);
|
||
}
|
||
return merged;
|
||
};
|
||
var tryGcDeleteSet = (ds, store, gcFilter) => {
|
||
for (const [client, deleteItems] of ds.clients.entries()) {
|
||
const structs = (
|
||
/** @type {Array<GC|Item>} */
|
||
store.clients.get(client)
|
||
);
|
||
for (let di = deleteItems.length - 1; di >= 0; di--) {
|
||
const deleteItem = deleteItems[di];
|
||
const endDeleteItemClock = deleteItem.clock + deleteItem.len;
|
||
for (let si = findIndexSS(structs, deleteItem.clock), struct = structs[si]; si < structs.length && struct.id.clock < endDeleteItemClock; struct = structs[++si]) {
|
||
const struct2 = structs[si];
|
||
if (deleteItem.clock + deleteItem.len <= struct2.id.clock) {
|
||
break;
|
||
}
|
||
if (struct2 instanceof Item && struct2.deleted && !struct2.keep && gcFilter(struct2)) {
|
||
struct2.gc(store, false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
var tryMergeDeleteSet = (ds, store) => {
|
||
ds.clients.forEach((deleteItems, client) => {
|
||
const structs = (
|
||
/** @type {Array<GC|Item>} */
|
||
store.clients.get(client)
|
||
);
|
||
for (let di = deleteItems.length - 1; di >= 0; di--) {
|
||
const deleteItem = deleteItems[di];
|
||
const mostRightIndexToCheck = min(structs.length - 1, 1 + findIndexSS(structs, deleteItem.clock + deleteItem.len - 1));
|
||
for (let si = mostRightIndexToCheck, struct = structs[si]; si > 0 && struct.id.clock >= deleteItem.clock; struct = structs[si]) {
|
||
si -= 1 + tryToMergeWithLefts(structs, si);
|
||
}
|
||
}
|
||
});
|
||
};
|
||
var tryGc = (ds, store, gcFilter) => {
|
||
tryGcDeleteSet(ds, store, gcFilter);
|
||
tryMergeDeleteSet(ds, store);
|
||
};
|
||
var cleanupTransactions = (transactionCleanups, i) => {
|
||
if (i < transactionCleanups.length) {
|
||
const transaction = transactionCleanups[i];
|
||
const doc2 = transaction.doc;
|
||
const store = doc2.store;
|
||
const ds = transaction.deleteSet;
|
||
const mergeStructs = transaction._mergeStructs;
|
||
try {
|
||
sortAndMergeDeleteSet(ds);
|
||
transaction.afterState = getStateVector(transaction.doc.store);
|
||
doc2.emit("beforeObserverCalls", [transaction, doc2]);
|
||
const fs = [];
|
||
transaction.changed.forEach(
|
||
(subs, itemtype) => fs.push(() => {
|
||
if (itemtype._item === null || !itemtype._item.deleted) {
|
||
itemtype._callObserver(transaction, subs);
|
||
}
|
||
})
|
||
);
|
||
fs.push(() => {
|
||
transaction.changedParentTypes.forEach((events, type) => {
|
||
if (type._dEH.l.length > 0 && (type._item === null || !type._item.deleted)) {
|
||
events = events.filter(
|
||
(event) => event.target._item === null || !event.target._item.deleted
|
||
);
|
||
events.forEach((event) => {
|
||
event.currentTarget = type;
|
||
event._path = null;
|
||
});
|
||
events.sort((event1, event2) => event1.path.length - event2.path.length);
|
||
fs.push(() => {
|
||
callEventHandlerListeners(type._dEH, events, transaction);
|
||
});
|
||
}
|
||
});
|
||
fs.push(() => doc2.emit("afterTransaction", [transaction, doc2]));
|
||
fs.push(() => {
|
||
if (transaction._needFormattingCleanup) {
|
||
cleanupYTextAfterTransaction(transaction);
|
||
}
|
||
});
|
||
});
|
||
callAll(fs, []);
|
||
} finally {
|
||
if (doc2.gc) {
|
||
tryGcDeleteSet(ds, store, doc2.gcFilter);
|
||
}
|
||
tryMergeDeleteSet(ds, store);
|
||
transaction.afterState.forEach((clock, client) => {
|
||
const beforeClock = transaction.beforeState.get(client) || 0;
|
||
if (beforeClock !== clock) {
|
||
const structs = (
|
||
/** @type {Array<GC|Item>} */
|
||
store.clients.get(client)
|
||
);
|
||
const firstChangePos = max(findIndexSS(structs, beforeClock), 1);
|
||
for (let i2 = structs.length - 1; i2 >= firstChangePos; ) {
|
||
i2 -= 1 + tryToMergeWithLefts(structs, i2);
|
||
}
|
||
}
|
||
});
|
||
for (let i2 = mergeStructs.length - 1; i2 >= 0; i2--) {
|
||
const { client, clock } = mergeStructs[i2].id;
|
||
const structs = (
|
||
/** @type {Array<GC|Item>} */
|
||
store.clients.get(client)
|
||
);
|
||
const replacedStructPos = findIndexSS(structs, clock);
|
||
if (replacedStructPos + 1 < structs.length) {
|
||
if (tryToMergeWithLefts(structs, replacedStructPos + 1) > 1) {
|
||
continue;
|
||
}
|
||
}
|
||
if (replacedStructPos > 0) {
|
||
tryToMergeWithLefts(structs, replacedStructPos);
|
||
}
|
||
}
|
||
if (!transaction.local && transaction.afterState.get(doc2.clientID) !== transaction.beforeState.get(doc2.clientID)) {
|
||
print(ORANGE, BOLD, "[yjs] ", UNBOLD, RED, "Changed the client-id because another client seems to be using it.");
|
||
doc2.clientID = generateNewClientId();
|
||
}
|
||
doc2.emit("afterTransactionCleanup", [transaction, doc2]);
|
||
if (doc2._observers.has("update")) {
|
||
const encoder = new UpdateEncoderV1();
|
||
const hasContent2 = writeUpdateMessageFromTransaction(encoder, transaction);
|
||
if (hasContent2) {
|
||
doc2.emit("update", [encoder.toUint8Array(), transaction.origin, doc2, transaction]);
|
||
}
|
||
}
|
||
if (doc2._observers.has("updateV2")) {
|
||
const encoder = new UpdateEncoderV2();
|
||
const hasContent2 = writeUpdateMessageFromTransaction(encoder, transaction);
|
||
if (hasContent2) {
|
||
doc2.emit("updateV2", [encoder.toUint8Array(), transaction.origin, doc2, transaction]);
|
||
}
|
||
}
|
||
const { subdocsAdded, subdocsLoaded, subdocsRemoved } = transaction;
|
||
if (subdocsAdded.size > 0 || subdocsRemoved.size > 0 || subdocsLoaded.size > 0) {
|
||
subdocsAdded.forEach((subdoc) => {
|
||
subdoc.clientID = doc2.clientID;
|
||
if (subdoc.collectionid == null) {
|
||
subdoc.collectionid = doc2.collectionid;
|
||
}
|
||
doc2.subdocs.add(subdoc);
|
||
});
|
||
subdocsRemoved.forEach((subdoc) => doc2.subdocs.delete(subdoc));
|
||
doc2.emit("subdocs", [{ loaded: subdocsLoaded, added: subdocsAdded, removed: subdocsRemoved }, doc2, transaction]);
|
||
subdocsRemoved.forEach((subdoc) => subdoc.destroy());
|
||
}
|
||
if (transactionCleanups.length <= i + 1) {
|
||
doc2._transactionCleanups = [];
|
||
doc2.emit("afterAllTransactions", [doc2, transactionCleanups]);
|
||
} else {
|
||
cleanupTransactions(transactionCleanups, i + 1);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
var transact = (doc2, f, origin = null, local = true) => {
|
||
const transactionCleanups = doc2._transactionCleanups;
|
||
let initialCall = false;
|
||
let result = null;
|
||
if (doc2._transaction === null) {
|
||
initialCall = true;
|
||
doc2._transaction = new Transaction(doc2, origin, local);
|
||
transactionCleanups.push(doc2._transaction);
|
||
if (transactionCleanups.length === 1) {
|
||
doc2.emit("beforeAllTransactions", [doc2]);
|
||
}
|
||
doc2.emit("beforeTransaction", [doc2._transaction, doc2]);
|
||
}
|
||
try {
|
||
result = f(doc2._transaction);
|
||
} finally {
|
||
if (initialCall) {
|
||
const finishCleanup = doc2._transaction === transactionCleanups[0];
|
||
doc2._transaction = null;
|
||
if (finishCleanup) {
|
||
cleanupTransactions(transactionCleanups, 0);
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
var StackItem = class {
|
||
/**
|
||
* @param {DeleteSet} deletions
|
||
* @param {DeleteSet} insertions
|
||
*/
|
||
constructor(deletions, insertions) {
|
||
this.insertions = insertions;
|
||
this.deletions = deletions;
|
||
this.meta = /* @__PURE__ */ new Map();
|
||
}
|
||
};
|
||
var clearUndoManagerStackItem = (tr, um, stackItem) => {
|
||
iterateDeletedStructs(tr, stackItem.deletions, (item) => {
|
||
if (item instanceof Item && um.scope.some((type) => type === tr.doc || isParentOf(
|
||
/** @type {AbstractType<any>} */
|
||
type,
|
||
item
|
||
))) {
|
||
keepItem(item, false);
|
||
}
|
||
});
|
||
};
|
||
var popStackItem = (undoManager, stack, eventType) => {
|
||
let _tr = null;
|
||
const doc2 = undoManager.doc;
|
||
const scope = undoManager.scope;
|
||
transact(doc2, (transaction) => {
|
||
while (stack.length > 0 && undoManager.currStackItem === null) {
|
||
const store = doc2.store;
|
||
const stackItem = (
|
||
/** @type {StackItem} */
|
||
stack.pop()
|
||
);
|
||
const itemsToRedo = /* @__PURE__ */ new Set();
|
||
const itemsToDelete = [];
|
||
let performedChange = false;
|
||
iterateDeletedStructs(transaction, stackItem.insertions, (struct) => {
|
||
if (struct instanceof Item) {
|
||
if (struct.redone !== null) {
|
||
let { item, diff } = followRedone(store, struct.id);
|
||
if (diff > 0) {
|
||
item = getItemCleanStart(transaction, createID(item.id.client, item.id.clock + diff));
|
||
}
|
||
struct = item;
|
||
}
|
||
if (!struct.deleted && scope.some((type) => type === transaction.doc || isParentOf(
|
||
/** @type {AbstractType<any>} */
|
||
type,
|
||
/** @type {Item} */
|
||
struct
|
||
))) {
|
||
itemsToDelete.push(struct);
|
||
}
|
||
}
|
||
});
|
||
iterateDeletedStructs(transaction, stackItem.deletions, (struct) => {
|
||
if (struct instanceof Item && scope.some((type) => type === transaction.doc || isParentOf(
|
||
/** @type {AbstractType<any>} */
|
||
type,
|
||
struct
|
||
)) && // Never redo structs in stackItem.insertions because they were created and deleted in the same capture interval.
|
||
!isDeleted(stackItem.insertions, struct.id)) {
|
||
itemsToRedo.add(struct);
|
||
}
|
||
});
|
||
itemsToRedo.forEach((struct) => {
|
||
performedChange = redoItem(transaction, struct, itemsToRedo, stackItem.insertions, undoManager.ignoreRemoteMapChanges, undoManager) !== null || performedChange;
|
||
});
|
||
for (let i = itemsToDelete.length - 1; i >= 0; i--) {
|
||
const item = itemsToDelete[i];
|
||
if (undoManager.deleteFilter(item)) {
|
||
item.delete(transaction);
|
||
performedChange = true;
|
||
}
|
||
}
|
||
undoManager.currStackItem = performedChange ? stackItem : null;
|
||
}
|
||
transaction.changed.forEach((subProps, type) => {
|
||
if (subProps.has(null) && type._searchMarker) {
|
||
type._searchMarker.length = 0;
|
||
}
|
||
});
|
||
_tr = transaction;
|
||
}, undoManager);
|
||
const res = undoManager.currStackItem;
|
||
if (res != null) {
|
||
const changedParentTypes = _tr.changedParentTypes;
|
||
undoManager.emit("stack-item-popped", [{ stackItem: res, type: eventType, changedParentTypes, origin: undoManager }, undoManager]);
|
||
undoManager.currStackItem = null;
|
||
}
|
||
return res;
|
||
};
|
||
var UndoManager = class extends ObservableV2 {
|
||
/**
|
||
* @param {Doc|AbstractType<any>|Array<AbstractType<any>>} typeScope Limits the scope of the UndoManager. If this is set to a ydoc instance, all changes on that ydoc will be undone. If set to a specific type, only changes on that type or its children will be undone. Also accepts an array of types.
|
||
* @param {UndoManagerOptions} options
|
||
*/
|
||
constructor(typeScope, {
|
||
captureTimeout = 500,
|
||
captureTransaction = (_tr) => true,
|
||
deleteFilter = () => true,
|
||
trackedOrigins = /* @__PURE__ */ new Set([null]),
|
||
ignoreRemoteMapChanges = false,
|
||
doc: doc2 = (
|
||
/** @type {Doc} */
|
||
isArray(typeScope) ? typeScope[0].doc : typeScope instanceof Doc ? typeScope : typeScope.doc
|
||
)
|
||
} = {}) {
|
||
super();
|
||
this.scope = [];
|
||
this.doc = doc2;
|
||
this.addToScope(typeScope);
|
||
this.deleteFilter = deleteFilter;
|
||
trackedOrigins.add(this);
|
||
this.trackedOrigins = trackedOrigins;
|
||
this.captureTransaction = captureTransaction;
|
||
this.undoStack = [];
|
||
this.redoStack = [];
|
||
this.undoing = false;
|
||
this.redoing = false;
|
||
this.currStackItem = null;
|
||
this.lastChange = 0;
|
||
this.ignoreRemoteMapChanges = ignoreRemoteMapChanges;
|
||
this.captureTimeout = captureTimeout;
|
||
this.afterTransactionHandler = (transaction) => {
|
||
if (!this.captureTransaction(transaction) || !this.scope.some((type) => transaction.changedParentTypes.has(
|
||
/** @type {AbstractType<any>} */
|
||
type
|
||
) || type === this.doc) || !this.trackedOrigins.has(transaction.origin) && (!transaction.origin || !this.trackedOrigins.has(transaction.origin.constructor))) {
|
||
return;
|
||
}
|
||
const undoing = this.undoing;
|
||
const redoing = this.redoing;
|
||
const stack = undoing ? this.redoStack : this.undoStack;
|
||
if (undoing) {
|
||
this.stopCapturing();
|
||
} else if (!redoing) {
|
||
this.clear(false, true);
|
||
}
|
||
const insertions = new DeleteSet();
|
||
transaction.afterState.forEach((endClock, client) => {
|
||
const startClock = transaction.beforeState.get(client) || 0;
|
||
const len = endClock - startClock;
|
||
if (len > 0) {
|
||
addToDeleteSet(insertions, client, startClock, len);
|
||
}
|
||
});
|
||
const now = getUnixTime();
|
||
let didAdd = false;
|
||
if (this.lastChange > 0 && now - this.lastChange < this.captureTimeout && stack.length > 0 && !undoing && !redoing) {
|
||
const lastOp = stack[stack.length - 1];
|
||
lastOp.deletions = mergeDeleteSets([lastOp.deletions, transaction.deleteSet]);
|
||
lastOp.insertions = mergeDeleteSets([lastOp.insertions, insertions]);
|
||
} else {
|
||
stack.push(new StackItem(transaction.deleteSet, insertions));
|
||
didAdd = true;
|
||
}
|
||
if (!undoing && !redoing) {
|
||
this.lastChange = now;
|
||
}
|
||
iterateDeletedStructs(
|
||
transaction,
|
||
transaction.deleteSet,
|
||
/** @param {Item|GC} item */
|
||
(item) => {
|
||
if (item instanceof Item && this.scope.some((type) => type === transaction.doc || isParentOf(
|
||
/** @type {AbstractType<any>} */
|
||
type,
|
||
item
|
||
))) {
|
||
keepItem(item, true);
|
||
}
|
||
}
|
||
);
|
||
const changeEvent = [{ stackItem: stack[stack.length - 1], origin: transaction.origin, type: undoing ? "redo" : "undo", changedParentTypes: transaction.changedParentTypes }, this];
|
||
if (didAdd) {
|
||
this.emit("stack-item-added", changeEvent);
|
||
} else {
|
||
this.emit("stack-item-updated", changeEvent);
|
||
}
|
||
};
|
||
this.doc.on("afterTransaction", this.afterTransactionHandler);
|
||
this.doc.on("destroy", () => {
|
||
this.destroy();
|
||
});
|
||
}
|
||
/**
|
||
* Extend the scope.
|
||
*
|
||
* @param {Array<AbstractType<any> | Doc> | AbstractType<any> | Doc} ytypes
|
||
*/
|
||
addToScope(ytypes) {
|
||
const tmpSet = new Set(this.scope);
|
||
ytypes = isArray(ytypes) ? ytypes : [ytypes];
|
||
ytypes.forEach((ytype) => {
|
||
if (!tmpSet.has(ytype)) {
|
||
tmpSet.add(ytype);
|
||
if (ytype instanceof AbstractType ? ytype.doc !== this.doc : ytype !== this.doc) warn("[yjs#509] Not same Y.Doc");
|
||
this.scope.push(ytype);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* @param {any} origin
|
||
*/
|
||
addTrackedOrigin(origin) {
|
||
this.trackedOrigins.add(origin);
|
||
}
|
||
/**
|
||
* @param {any} origin
|
||
*/
|
||
removeTrackedOrigin(origin) {
|
||
this.trackedOrigins.delete(origin);
|
||
}
|
||
clear(clearUndoStack = true, clearRedoStack = true) {
|
||
if (clearUndoStack && this.canUndo() || clearRedoStack && this.canRedo()) {
|
||
this.doc.transact((tr) => {
|
||
if (clearUndoStack) {
|
||
this.undoStack.forEach((item) => clearUndoManagerStackItem(tr, this, item));
|
||
this.undoStack = [];
|
||
}
|
||
if (clearRedoStack) {
|
||
this.redoStack.forEach((item) => clearUndoManagerStackItem(tr, this, item));
|
||
this.redoStack = [];
|
||
}
|
||
this.emit("stack-cleared", [{ undoStackCleared: clearUndoStack, redoStackCleared: clearRedoStack }]);
|
||
});
|
||
}
|
||
}
|
||
/**
|
||
* UndoManager merges Undo-StackItem if they are created within time-gap
|
||
* smaller than `options.captureTimeout`. Call `um.stopCapturing()` so that the next
|
||
* StackItem won't be merged.
|
||
*
|
||
*
|
||
* @example
|
||
* // without stopCapturing
|
||
* ytext.insert(0, 'a')
|
||
* ytext.insert(1, 'b')
|
||
* um.undo()
|
||
* ytext.toString() // => '' (note that 'ab' was removed)
|
||
* // with stopCapturing
|
||
* ytext.insert(0, 'a')
|
||
* um.stopCapturing()
|
||
* ytext.insert(0, 'b')
|
||
* um.undo()
|
||
* ytext.toString() // => 'a' (note that only 'b' was removed)
|
||
*
|
||
*/
|
||
stopCapturing() {
|
||
this.lastChange = 0;
|
||
}
|
||
/**
|
||
* Undo last changes on type.
|
||
*
|
||
* @return {StackItem?} Returns StackItem if a change was applied
|
||
*/
|
||
undo() {
|
||
this.undoing = true;
|
||
let res;
|
||
try {
|
||
res = popStackItem(this, this.undoStack, "undo");
|
||
} finally {
|
||
this.undoing = false;
|
||
}
|
||
return res;
|
||
}
|
||
/**
|
||
* Redo last undo operation.
|
||
*
|
||
* @return {StackItem?} Returns StackItem if a change was applied
|
||
*/
|
||
redo() {
|
||
this.redoing = true;
|
||
let res;
|
||
try {
|
||
res = popStackItem(this, this.redoStack, "redo");
|
||
} finally {
|
||
this.redoing = false;
|
||
}
|
||
return res;
|
||
}
|
||
/**
|
||
* Are undo steps available?
|
||
*
|
||
* @return {boolean} `true` if undo is possible
|
||
*/
|
||
canUndo() {
|
||
return this.undoStack.length > 0;
|
||
}
|
||
/**
|
||
* Are redo steps available?
|
||
*
|
||
* @return {boolean} `true` if redo is possible
|
||
*/
|
||
canRedo() {
|
||
return this.redoStack.length > 0;
|
||
}
|
||
destroy() {
|
||
this.trackedOrigins.delete(this);
|
||
this.doc.off("afterTransaction", this.afterTransactionHandler);
|
||
super.destroy();
|
||
}
|
||
};
|
||
function* lazyStructReaderGenerator(decoder) {
|
||
const numOfStateUpdates = readVarUint(decoder.restDecoder);
|
||
for (let i = 0; i < numOfStateUpdates; i++) {
|
||
const numberOfStructs = readVarUint(decoder.restDecoder);
|
||
const client = decoder.readClient();
|
||
let clock = readVarUint(decoder.restDecoder);
|
||
for (let i2 = 0; i2 < numberOfStructs; i2++) {
|
||
const info = decoder.readInfo();
|
||
if (info === 10) {
|
||
const len = readVarUint(decoder.restDecoder);
|
||
yield new Skip(createID(client, clock), len);
|
||
clock += len;
|
||
} else if ((BITS5 & info) !== 0) {
|
||
const cantCopyParentInfo = (info & (BIT7 | BIT8)) === 0;
|
||
const struct = new Item(
|
||
createID(client, clock),
|
||
null,
|
||
// left
|
||
(info & BIT8) === BIT8 ? decoder.readLeftID() : null,
|
||
// origin
|
||
null,
|
||
// right
|
||
(info & BIT7) === BIT7 ? decoder.readRightID() : null,
|
||
// right origin
|
||
// @ts-ignore Force writing a string here.
|
||
cantCopyParentInfo ? decoder.readParentInfo() ? decoder.readString() : decoder.readLeftID() : null,
|
||
// parent
|
||
cantCopyParentInfo && (info & BIT6) === BIT6 ? decoder.readString() : null,
|
||
// parentSub
|
||
readItemContent(decoder, info)
|
||
// item content
|
||
);
|
||
yield struct;
|
||
clock += struct.length;
|
||
} else {
|
||
const len = decoder.readLen();
|
||
yield new GC(createID(client, clock), len);
|
||
clock += len;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
var LazyStructReader = class {
|
||
/**
|
||
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder
|
||
* @param {boolean} filterSkips
|
||
*/
|
||
constructor(decoder, filterSkips) {
|
||
this.gen = lazyStructReaderGenerator(decoder);
|
||
this.curr = null;
|
||
this.done = false;
|
||
this.filterSkips = filterSkips;
|
||
this.next();
|
||
}
|
||
/**
|
||
* @return {Item | GC | Skip |null}
|
||
*/
|
||
next() {
|
||
do {
|
||
this.curr = this.gen.next().value || null;
|
||
} while (this.filterSkips && this.curr !== null && this.curr.constructor === Skip);
|
||
return this.curr;
|
||
}
|
||
};
|
||
var logUpdate = (update) => logUpdateV2(update, UpdateDecoderV1);
|
||
var logUpdateV2 = (update, YDecoder = UpdateDecoderV2) => {
|
||
const structs = [];
|
||
const updateDecoder = new YDecoder(createDecoder(update));
|
||
const lazyDecoder = new LazyStructReader(updateDecoder, false);
|
||
for (let curr = lazyDecoder.curr; curr !== null; curr = lazyDecoder.next()) {
|
||
structs.push(curr);
|
||
}
|
||
print("Structs: ", structs);
|
||
const ds = readDeleteSet(updateDecoder);
|
||
print("DeleteSet: ", ds);
|
||
};
|
||
var decodeUpdate = (update) => decodeUpdateV2(update, UpdateDecoderV1);
|
||
var decodeUpdateV2 = (update, YDecoder = UpdateDecoderV2) => {
|
||
const structs = [];
|
||
const updateDecoder = new YDecoder(createDecoder(update));
|
||
const lazyDecoder = new LazyStructReader(updateDecoder, false);
|
||
for (let curr = lazyDecoder.curr; curr !== null; curr = lazyDecoder.next()) {
|
||
structs.push(curr);
|
||
}
|
||
return {
|
||
structs,
|
||
ds: readDeleteSet(updateDecoder)
|
||
};
|
||
};
|
||
var LazyStructWriter = class {
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
*/
|
||
constructor(encoder) {
|
||
this.currClient = 0;
|
||
this.startClock = 0;
|
||
this.written = 0;
|
||
this.encoder = encoder;
|
||
this.clientStructs = [];
|
||
}
|
||
};
|
||
var mergeUpdates = (updates) => mergeUpdatesV2(updates, UpdateDecoderV1, UpdateEncoderV1);
|
||
var encodeStateVectorFromUpdateV2 = (update, YEncoder = DSEncoderV2, YDecoder = UpdateDecoderV2) => {
|
||
const encoder = new YEncoder();
|
||
const updateDecoder = new LazyStructReader(new YDecoder(createDecoder(update)), false);
|
||
let curr = updateDecoder.curr;
|
||
if (curr !== null) {
|
||
let size2 = 0;
|
||
let currClient = curr.id.client;
|
||
let stopCounting = curr.id.clock !== 0;
|
||
let currClock = stopCounting ? 0 : curr.id.clock + curr.length;
|
||
for (; curr !== null; curr = updateDecoder.next()) {
|
||
if (currClient !== curr.id.client) {
|
||
if (currClock !== 0) {
|
||
size2++;
|
||
writeVarUint(encoder.restEncoder, currClient);
|
||
writeVarUint(encoder.restEncoder, currClock);
|
||
}
|
||
currClient = curr.id.client;
|
||
currClock = 0;
|
||
stopCounting = curr.id.clock !== 0;
|
||
}
|
||
if (curr.constructor === Skip) {
|
||
stopCounting = true;
|
||
}
|
||
if (!stopCounting) {
|
||
currClock = curr.id.clock + curr.length;
|
||
}
|
||
}
|
||
if (currClock !== 0) {
|
||
size2++;
|
||
writeVarUint(encoder.restEncoder, currClient);
|
||
writeVarUint(encoder.restEncoder, currClock);
|
||
}
|
||
const enc = createEncoder();
|
||
writeVarUint(enc, size2);
|
||
writeBinaryEncoder(enc, encoder.restEncoder);
|
||
encoder.restEncoder = enc;
|
||
return encoder.toUint8Array();
|
||
} else {
|
||
writeVarUint(encoder.restEncoder, 0);
|
||
return encoder.toUint8Array();
|
||
}
|
||
};
|
||
var encodeStateVectorFromUpdate = (update) => encodeStateVectorFromUpdateV2(update, DSEncoderV1, UpdateDecoderV1);
|
||
var parseUpdateMetaV2 = (update, YDecoder = UpdateDecoderV2) => {
|
||
const from3 = /* @__PURE__ */ new Map();
|
||
const to = /* @__PURE__ */ new Map();
|
||
const updateDecoder = new LazyStructReader(new YDecoder(createDecoder(update)), false);
|
||
let curr = updateDecoder.curr;
|
||
if (curr !== null) {
|
||
let currClient = curr.id.client;
|
||
let currClock = curr.id.clock;
|
||
from3.set(currClient, currClock);
|
||
for (; curr !== null; curr = updateDecoder.next()) {
|
||
if (currClient !== curr.id.client) {
|
||
to.set(currClient, currClock);
|
||
from3.set(curr.id.client, curr.id.clock);
|
||
currClient = curr.id.client;
|
||
}
|
||
currClock = curr.id.clock + curr.length;
|
||
}
|
||
to.set(currClient, currClock);
|
||
}
|
||
return { from: from3, to };
|
||
};
|
||
var parseUpdateMeta = (update) => parseUpdateMetaV2(update, UpdateDecoderV1);
|
||
var sliceStruct = (left, diff) => {
|
||
if (left.constructor === GC) {
|
||
const { client, clock } = left.id;
|
||
return new GC(createID(client, clock + diff), left.length - diff);
|
||
} else if (left.constructor === Skip) {
|
||
const { client, clock } = left.id;
|
||
return new Skip(createID(client, clock + diff), left.length - diff);
|
||
} else {
|
||
const leftItem = (
|
||
/** @type {Item} */
|
||
left
|
||
);
|
||
const { client, clock } = leftItem.id;
|
||
return new Item(
|
||
createID(client, clock + diff),
|
||
null,
|
||
createID(client, clock + diff - 1),
|
||
null,
|
||
leftItem.rightOrigin,
|
||
leftItem.parent,
|
||
leftItem.parentSub,
|
||
leftItem.content.splice(diff)
|
||
);
|
||
}
|
||
};
|
||
var mergeUpdatesV2 = (updates, YDecoder = UpdateDecoderV2, YEncoder = UpdateEncoderV2) => {
|
||
if (updates.length === 1) {
|
||
return updates[0];
|
||
}
|
||
const updateDecoders = updates.map((update) => new YDecoder(createDecoder(update)));
|
||
let lazyStructDecoders = updateDecoders.map((decoder) => new LazyStructReader(decoder, true));
|
||
let currWrite = null;
|
||
const updateEncoder = new YEncoder();
|
||
const lazyStructEncoder = new LazyStructWriter(updateEncoder);
|
||
while (true) {
|
||
lazyStructDecoders = lazyStructDecoders.filter((dec) => dec.curr !== null);
|
||
lazyStructDecoders.sort(
|
||
/** @type {function(any,any):number} */
|
||
(dec1, dec2) => {
|
||
if (dec1.curr.id.client === dec2.curr.id.client) {
|
||
const clockDiff = dec1.curr.id.clock - dec2.curr.id.clock;
|
||
if (clockDiff === 0) {
|
||
return dec1.curr.constructor === dec2.curr.constructor ? 0 : dec1.curr.constructor === Skip ? 1 : -1;
|
||
} else {
|
||
return clockDiff;
|
||
}
|
||
} else {
|
||
return dec2.curr.id.client - dec1.curr.id.client;
|
||
}
|
||
}
|
||
);
|
||
if (lazyStructDecoders.length === 0) {
|
||
break;
|
||
}
|
||
const currDecoder = lazyStructDecoders[0];
|
||
const firstClient = (
|
||
/** @type {Item | GC} */
|
||
currDecoder.curr.id.client
|
||
);
|
||
if (currWrite !== null) {
|
||
let curr = (
|
||
/** @type {Item | GC | null} */
|
||
currDecoder.curr
|
||
);
|
||
let iterated = false;
|
||
while (curr !== null && curr.id.clock + curr.length <= currWrite.struct.id.clock + currWrite.struct.length && curr.id.client >= currWrite.struct.id.client) {
|
||
curr = currDecoder.next();
|
||
iterated = true;
|
||
}
|
||
if (curr === null || // current decoder is empty
|
||
curr.id.client !== firstClient || // check whether there is another decoder that has has updates from `firstClient`
|
||
iterated && curr.id.clock > currWrite.struct.id.clock + currWrite.struct.length) {
|
||
continue;
|
||
}
|
||
if (firstClient !== currWrite.struct.id.client) {
|
||
writeStructToLazyStructWriter(lazyStructEncoder, currWrite.struct, currWrite.offset);
|
||
currWrite = { struct: curr, offset: 0 };
|
||
currDecoder.next();
|
||
} else {
|
||
if (currWrite.struct.id.clock + currWrite.struct.length < curr.id.clock) {
|
||
if (currWrite.struct.constructor === Skip) {
|
||
currWrite.struct.length = curr.id.clock + curr.length - currWrite.struct.id.clock;
|
||
} else {
|
||
writeStructToLazyStructWriter(lazyStructEncoder, currWrite.struct, currWrite.offset);
|
||
const diff = curr.id.clock - currWrite.struct.id.clock - currWrite.struct.length;
|
||
const struct = new Skip(createID(firstClient, currWrite.struct.id.clock + currWrite.struct.length), diff);
|
||
currWrite = { struct, offset: 0 };
|
||
}
|
||
} else {
|
||
const diff = currWrite.struct.id.clock + currWrite.struct.length - curr.id.clock;
|
||
if (diff > 0) {
|
||
if (currWrite.struct.constructor === Skip) {
|
||
currWrite.struct.length -= diff;
|
||
} else {
|
||
curr = sliceStruct(curr, diff);
|
||
}
|
||
}
|
||
if (!currWrite.struct.mergeWith(
|
||
/** @type {any} */
|
||
curr
|
||
)) {
|
||
writeStructToLazyStructWriter(lazyStructEncoder, currWrite.struct, currWrite.offset);
|
||
currWrite = { struct: curr, offset: 0 };
|
||
currDecoder.next();
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
currWrite = { struct: (
|
||
/** @type {Item | GC} */
|
||
currDecoder.curr
|
||
), offset: 0 };
|
||
currDecoder.next();
|
||
}
|
||
for (let next = currDecoder.curr; next !== null && next.id.client === firstClient && next.id.clock === currWrite.struct.id.clock + currWrite.struct.length && next.constructor !== Skip; next = currDecoder.next()) {
|
||
writeStructToLazyStructWriter(lazyStructEncoder, currWrite.struct, currWrite.offset);
|
||
currWrite = { struct: next, offset: 0 };
|
||
}
|
||
}
|
||
if (currWrite !== null) {
|
||
writeStructToLazyStructWriter(lazyStructEncoder, currWrite.struct, currWrite.offset);
|
||
currWrite = null;
|
||
}
|
||
finishLazyStructWriting(lazyStructEncoder);
|
||
const dss = updateDecoders.map((decoder) => readDeleteSet(decoder));
|
||
const ds = mergeDeleteSets(dss);
|
||
writeDeleteSet(updateEncoder, ds);
|
||
return updateEncoder.toUint8Array();
|
||
};
|
||
var diffUpdateV2 = (update, sv, YDecoder = UpdateDecoderV2, YEncoder = UpdateEncoderV2) => {
|
||
const state = decodeStateVector(sv);
|
||
const encoder = new YEncoder();
|
||
const lazyStructWriter = new LazyStructWriter(encoder);
|
||
const decoder = new YDecoder(createDecoder(update));
|
||
const reader = new LazyStructReader(decoder, false);
|
||
while (reader.curr) {
|
||
const curr = reader.curr;
|
||
const currClient = curr.id.client;
|
||
const svClock = state.get(currClient) || 0;
|
||
if (reader.curr.constructor === Skip) {
|
||
reader.next();
|
||
continue;
|
||
}
|
||
if (curr.id.clock + curr.length > svClock) {
|
||
writeStructToLazyStructWriter(lazyStructWriter, curr, max(svClock - curr.id.clock, 0));
|
||
reader.next();
|
||
while (reader.curr && reader.curr.id.client === currClient) {
|
||
writeStructToLazyStructWriter(lazyStructWriter, reader.curr, 0);
|
||
reader.next();
|
||
}
|
||
} else {
|
||
while (reader.curr && reader.curr.id.client === currClient && reader.curr.id.clock + reader.curr.length <= svClock) {
|
||
reader.next();
|
||
}
|
||
}
|
||
}
|
||
finishLazyStructWriting(lazyStructWriter);
|
||
const ds = readDeleteSet(decoder);
|
||
writeDeleteSet(encoder, ds);
|
||
return encoder.toUint8Array();
|
||
};
|
||
var diffUpdate = (update, sv) => diffUpdateV2(update, sv, UpdateDecoderV1, UpdateEncoderV1);
|
||
var flushLazyStructWriter = (lazyWriter) => {
|
||
if (lazyWriter.written > 0) {
|
||
lazyWriter.clientStructs.push({ written: lazyWriter.written, restEncoder: toUint8Array(lazyWriter.encoder.restEncoder) });
|
||
lazyWriter.encoder.restEncoder = createEncoder();
|
||
lazyWriter.written = 0;
|
||
}
|
||
};
|
||
var writeStructToLazyStructWriter = (lazyWriter, struct, offset) => {
|
||
if (lazyWriter.written > 0 && lazyWriter.currClient !== struct.id.client) {
|
||
flushLazyStructWriter(lazyWriter);
|
||
}
|
||
if (lazyWriter.written === 0) {
|
||
lazyWriter.currClient = struct.id.client;
|
||
lazyWriter.encoder.writeClient(struct.id.client);
|
||
writeVarUint(lazyWriter.encoder.restEncoder, struct.id.clock + offset);
|
||
}
|
||
struct.write(lazyWriter.encoder, offset);
|
||
lazyWriter.written++;
|
||
};
|
||
var finishLazyStructWriting = (lazyWriter) => {
|
||
flushLazyStructWriter(lazyWriter);
|
||
const restEncoder = lazyWriter.encoder.restEncoder;
|
||
writeVarUint(restEncoder, lazyWriter.clientStructs.length);
|
||
for (let i = 0; i < lazyWriter.clientStructs.length; i++) {
|
||
const partStructs = lazyWriter.clientStructs[i];
|
||
writeVarUint(restEncoder, partStructs.written);
|
||
writeUint8Array(restEncoder, partStructs.restEncoder);
|
||
}
|
||
};
|
||
var convertUpdateFormat = (update, blockTransformer, YDecoder, YEncoder) => {
|
||
const updateDecoder = new YDecoder(createDecoder(update));
|
||
const lazyDecoder = new LazyStructReader(updateDecoder, false);
|
||
const updateEncoder = new YEncoder();
|
||
const lazyWriter = new LazyStructWriter(updateEncoder);
|
||
for (let curr = lazyDecoder.curr; curr !== null; curr = lazyDecoder.next()) {
|
||
writeStructToLazyStructWriter(lazyWriter, blockTransformer(curr), 0);
|
||
}
|
||
finishLazyStructWriting(lazyWriter);
|
||
const ds = readDeleteSet(updateDecoder);
|
||
writeDeleteSet(updateEncoder, ds);
|
||
return updateEncoder.toUint8Array();
|
||
};
|
||
var createObfuscator = ({ formatting = true, subdocs = true, yxml = true } = {}) => {
|
||
let i = 0;
|
||
const mapKeyCache = create();
|
||
const nodeNameCache = create();
|
||
const formattingKeyCache = create();
|
||
const formattingValueCache = create();
|
||
formattingValueCache.set(null, null);
|
||
return (block) => {
|
||
switch (block.constructor) {
|
||
case GC:
|
||
case Skip:
|
||
return block;
|
||
case Item: {
|
||
const item = (
|
||
/** @type {Item} */
|
||
block
|
||
);
|
||
const content = item.content;
|
||
switch (content.constructor) {
|
||
case ContentDeleted:
|
||
break;
|
||
case ContentType: {
|
||
if (yxml) {
|
||
const type = (
|
||
/** @type {ContentType} */
|
||
content.type
|
||
);
|
||
if (type instanceof YXmlElement) {
|
||
type.nodeName = setIfUndefined(nodeNameCache, type.nodeName, () => "node-" + i);
|
||
}
|
||
if (type instanceof YXmlHook) {
|
||
type.hookName = setIfUndefined(nodeNameCache, type.hookName, () => "hook-" + i);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case ContentAny: {
|
||
const c = (
|
||
/** @type {ContentAny} */
|
||
content
|
||
);
|
||
c.arr = c.arr.map(() => i);
|
||
break;
|
||
}
|
||
case ContentBinary: {
|
||
const c = (
|
||
/** @type {ContentBinary} */
|
||
content
|
||
);
|
||
c.content = new Uint8Array([i]);
|
||
break;
|
||
}
|
||
case ContentDoc: {
|
||
const c = (
|
||
/** @type {ContentDoc} */
|
||
content
|
||
);
|
||
if (subdocs) {
|
||
c.opts = {};
|
||
c.doc.guid = i + "";
|
||
}
|
||
break;
|
||
}
|
||
case ContentEmbed: {
|
||
const c = (
|
||
/** @type {ContentEmbed} */
|
||
content
|
||
);
|
||
c.embed = {};
|
||
break;
|
||
}
|
||
case ContentFormat: {
|
||
const c = (
|
||
/** @type {ContentFormat} */
|
||
content
|
||
);
|
||
if (formatting) {
|
||
c.key = setIfUndefined(formattingKeyCache, c.key, () => i + "");
|
||
c.value = setIfUndefined(formattingValueCache, c.value, () => ({ i }));
|
||
}
|
||
break;
|
||
}
|
||
case ContentJSON: {
|
||
const c = (
|
||
/** @type {ContentJSON} */
|
||
content
|
||
);
|
||
c.arr = c.arr.map(() => i);
|
||
break;
|
||
}
|
||
case ContentString: {
|
||
const c = (
|
||
/** @type {ContentString} */
|
||
content
|
||
);
|
||
c.str = repeat(i % 10 + "", c.str.length);
|
||
break;
|
||
}
|
||
default:
|
||
unexpectedCase();
|
||
}
|
||
if (item.parentSub) {
|
||
item.parentSub = setIfUndefined(mapKeyCache, item.parentSub, () => i + "");
|
||
}
|
||
i++;
|
||
return block;
|
||
}
|
||
default:
|
||
unexpectedCase();
|
||
}
|
||
};
|
||
};
|
||
var obfuscateUpdate = (update, opts) => convertUpdateFormat(update, createObfuscator(opts), UpdateDecoderV1, UpdateEncoderV1);
|
||
var obfuscateUpdateV2 = (update, opts) => convertUpdateFormat(update, createObfuscator(opts), UpdateDecoderV2, UpdateEncoderV2);
|
||
var convertUpdateFormatV1ToV2 = (update) => convertUpdateFormat(update, id, UpdateDecoderV1, UpdateEncoderV2);
|
||
var convertUpdateFormatV2ToV1 = (update) => convertUpdateFormat(update, id, UpdateDecoderV2, UpdateEncoderV1);
|
||
var errorComputeChanges = "You must not compute changes after the event-handler fired.";
|
||
var YEvent = class {
|
||
/**
|
||
* @param {T} target The changed type.
|
||
* @param {Transaction} transaction
|
||
*/
|
||
constructor(target, transaction) {
|
||
this.target = target;
|
||
this.currentTarget = target;
|
||
this.transaction = transaction;
|
||
this._changes = null;
|
||
this._keys = null;
|
||
this._delta = null;
|
||
this._path = null;
|
||
}
|
||
/**
|
||
* Computes the path from `y` to the changed type.
|
||
*
|
||
* @todo v14 should standardize on path: Array<{parent, index}> because that is easier to work with.
|
||
*
|
||
* The following property holds:
|
||
* @example
|
||
* let type = y
|
||
* event.path.forEach(dir => {
|
||
* type = type.get(dir)
|
||
* })
|
||
* type === event.target // => true
|
||
*/
|
||
get path() {
|
||
return this._path || (this._path = getPathTo(this.currentTarget, this.target));
|
||
}
|
||
/**
|
||
* Check if a struct is deleted by this event.
|
||
*
|
||
* In contrast to change.deleted, this method also returns true if the struct was added and then deleted.
|
||
*
|
||
* @param {AbstractStruct} struct
|
||
* @return {boolean}
|
||
*/
|
||
deletes(struct) {
|
||
return isDeleted(this.transaction.deleteSet, struct.id);
|
||
}
|
||
/**
|
||
* @type {Map<string, { action: 'add' | 'update' | 'delete', oldValue: any }>}
|
||
*/
|
||
get keys() {
|
||
if (this._keys === null) {
|
||
if (this.transaction.doc._transactionCleanups.length === 0) {
|
||
throw create3(errorComputeChanges);
|
||
}
|
||
const keys2 = /* @__PURE__ */ new Map();
|
||
const target = this.target;
|
||
const changed = (
|
||
/** @type Set<string|null> */
|
||
this.transaction.changed.get(target)
|
||
);
|
||
changed.forEach((key) => {
|
||
if (key !== null) {
|
||
const item = (
|
||
/** @type {Item} */
|
||
target._map.get(key)
|
||
);
|
||
let action;
|
||
let oldValue;
|
||
if (this.adds(item)) {
|
||
let prev = item.left;
|
||
while (prev !== null && this.adds(prev)) {
|
||
prev = prev.left;
|
||
}
|
||
if (this.deletes(item)) {
|
||
if (prev !== null && this.deletes(prev)) {
|
||
action = "delete";
|
||
oldValue = last(prev.content.getContent());
|
||
} else {
|
||
return;
|
||
}
|
||
} else {
|
||
if (prev !== null && this.deletes(prev)) {
|
||
action = "update";
|
||
oldValue = last(prev.content.getContent());
|
||
} else {
|
||
action = "add";
|
||
oldValue = void 0;
|
||
}
|
||
}
|
||
} else {
|
||
if (this.deletes(item)) {
|
||
action = "delete";
|
||
oldValue = last(
|
||
/** @type {Item} */
|
||
item.content.getContent()
|
||
);
|
||
} else {
|
||
return;
|
||
}
|
||
}
|
||
keys2.set(key, { action, oldValue });
|
||
}
|
||
});
|
||
this._keys = keys2;
|
||
}
|
||
return this._keys;
|
||
}
|
||
/**
|
||
* This is a computed property. Note that this can only be safely computed during the
|
||
* event call. Computing this property after other changes happened might result in
|
||
* unexpected behavior (incorrect computation of deltas). A safe way to collect changes
|
||
* is to store the `changes` or the `delta` object. Avoid storing the `transaction` object.
|
||
*
|
||
* @type {Array<{insert?: string | Array<any> | object | AbstractType<any>, retain?: number, delete?: number, attributes?: Object<string, any>}>}
|
||
*/
|
||
get delta() {
|
||
return this.changes.delta;
|
||
}
|
||
/**
|
||
* Check if a struct is added by this event.
|
||
*
|
||
* In contrast to change.deleted, this method also returns true if the struct was added and then deleted.
|
||
*
|
||
* @param {AbstractStruct} struct
|
||
* @return {boolean}
|
||
*/
|
||
adds(struct) {
|
||
return struct.id.clock >= (this.transaction.beforeState.get(struct.id.client) || 0);
|
||
}
|
||
/**
|
||
* This is a computed property. Note that this can only be safely computed during the
|
||
* event call. Computing this property after other changes happened might result in
|
||
* unexpected behavior (incorrect computation of deltas). A safe way to collect changes
|
||
* is to store the `changes` or the `delta` object. Avoid storing the `transaction` object.
|
||
*
|
||
* @type {{added:Set<Item>,deleted:Set<Item>,keys:Map<string,{action:'add'|'update'|'delete',oldValue:any}>,delta:Array<{insert?:Array<any>|string, delete?:number, retain?:number}>}}
|
||
*/
|
||
get changes() {
|
||
let changes = this._changes;
|
||
if (changes === null) {
|
||
if (this.transaction.doc._transactionCleanups.length === 0) {
|
||
throw create3(errorComputeChanges);
|
||
}
|
||
const target = this.target;
|
||
const added = create2();
|
||
const deleted = create2();
|
||
const delta = [];
|
||
changes = {
|
||
added,
|
||
deleted,
|
||
delta,
|
||
keys: this.keys
|
||
};
|
||
const changed = (
|
||
/** @type Set<string|null> */
|
||
this.transaction.changed.get(target)
|
||
);
|
||
if (changed.has(null)) {
|
||
let lastOp = null;
|
||
const packOp = () => {
|
||
if (lastOp) {
|
||
delta.push(lastOp);
|
||
}
|
||
};
|
||
for (let item = target._start; item !== null; item = item.right) {
|
||
if (item.deleted) {
|
||
if (this.deletes(item) && !this.adds(item)) {
|
||
if (lastOp === null || lastOp.delete === void 0) {
|
||
packOp();
|
||
lastOp = { delete: 0 };
|
||
}
|
||
lastOp.delete += item.length;
|
||
deleted.add(item);
|
||
}
|
||
} else {
|
||
if (this.adds(item)) {
|
||
if (lastOp === null || lastOp.insert === void 0) {
|
||
packOp();
|
||
lastOp = { insert: [] };
|
||
}
|
||
lastOp.insert = lastOp.insert.concat(item.content.getContent());
|
||
added.add(item);
|
||
} else {
|
||
if (lastOp === null || lastOp.retain === void 0) {
|
||
packOp();
|
||
lastOp = { retain: 0 };
|
||
}
|
||
lastOp.retain += item.length;
|
||
}
|
||
}
|
||
}
|
||
if (lastOp !== null && lastOp.retain === void 0) {
|
||
packOp();
|
||
}
|
||
}
|
||
this._changes = changes;
|
||
}
|
||
return (
|
||
/** @type {any} */
|
||
changes
|
||
);
|
||
}
|
||
};
|
||
var getPathTo = (parent, child) => {
|
||
const path = [];
|
||
while (child._item !== null && child !== parent) {
|
||
if (child._item.parentSub !== null) {
|
||
path.unshift(child._item.parentSub);
|
||
} else {
|
||
let i = 0;
|
||
let c = (
|
||
/** @type {AbstractType<any>} */
|
||
child._item.parent._start
|
||
);
|
||
while (c !== child._item && c !== null) {
|
||
if (!c.deleted && c.countable) {
|
||
i += c.length;
|
||
}
|
||
c = c.right;
|
||
}
|
||
path.unshift(i);
|
||
}
|
||
child = /** @type {AbstractType<any>} */
|
||
child._item.parent;
|
||
}
|
||
return path;
|
||
};
|
||
var warnPrematureAccess = () => {
|
||
warn("Invalid access: Add Yjs type to a document before reading data.");
|
||
};
|
||
var maxSearchMarker = 80;
|
||
var globalSearchMarkerTimestamp = 0;
|
||
var ArraySearchMarker = class {
|
||
/**
|
||
* @param {Item} p
|
||
* @param {number} index
|
||
*/
|
||
constructor(p, index) {
|
||
p.marker = true;
|
||
this.p = p;
|
||
this.index = index;
|
||
this.timestamp = globalSearchMarkerTimestamp++;
|
||
}
|
||
};
|
||
var refreshMarkerTimestamp = (marker) => {
|
||
marker.timestamp = globalSearchMarkerTimestamp++;
|
||
};
|
||
var overwriteMarker = (marker, p, index) => {
|
||
marker.p.marker = false;
|
||
marker.p = p;
|
||
p.marker = true;
|
||
marker.index = index;
|
||
marker.timestamp = globalSearchMarkerTimestamp++;
|
||
};
|
||
var markPosition = (searchMarker, p, index) => {
|
||
if (searchMarker.length >= maxSearchMarker) {
|
||
const marker = searchMarker.reduce((a, b) => a.timestamp < b.timestamp ? a : b);
|
||
overwriteMarker(marker, p, index);
|
||
return marker;
|
||
} else {
|
||
const pm = new ArraySearchMarker(p, index);
|
||
searchMarker.push(pm);
|
||
return pm;
|
||
}
|
||
};
|
||
var findMarker = (yarray, index) => {
|
||
if (yarray._start === null || index === 0 || yarray._searchMarker === null) {
|
||
return null;
|
||
}
|
||
const marker = yarray._searchMarker.length === 0 ? null : yarray._searchMarker.reduce((a, b) => abs(index - a.index) < abs(index - b.index) ? a : b);
|
||
let p = yarray._start;
|
||
let pindex = 0;
|
||
if (marker !== null) {
|
||
p = marker.p;
|
||
pindex = marker.index;
|
||
refreshMarkerTimestamp(marker);
|
||
}
|
||
while (p.right !== null && pindex < index) {
|
||
if (!p.deleted && p.countable) {
|
||
if (index < pindex + p.length) {
|
||
break;
|
||
}
|
||
pindex += p.length;
|
||
}
|
||
p = p.right;
|
||
}
|
||
while (p.left !== null && pindex > index) {
|
||
p = p.left;
|
||
if (!p.deleted && p.countable) {
|
||
pindex -= p.length;
|
||
}
|
||
}
|
||
while (p.left !== null && p.left.id.client === p.id.client && p.left.id.clock + p.left.length === p.id.clock) {
|
||
p = p.left;
|
||
if (!p.deleted && p.countable) {
|
||
pindex -= p.length;
|
||
}
|
||
}
|
||
if (marker !== null && abs(marker.index - pindex) < /** @type {YText|YArray<any>} */
|
||
p.parent.length / maxSearchMarker) {
|
||
overwriteMarker(marker, p, pindex);
|
||
return marker;
|
||
} else {
|
||
return markPosition(yarray._searchMarker, p, pindex);
|
||
}
|
||
};
|
||
var updateMarkerChanges = (searchMarker, index, len) => {
|
||
for (let i = searchMarker.length - 1; i >= 0; i--) {
|
||
const m = searchMarker[i];
|
||
if (len > 0) {
|
||
let p = m.p;
|
||
p.marker = false;
|
||
while (p && (p.deleted || !p.countable)) {
|
||
p = p.left;
|
||
if (p && !p.deleted && p.countable) {
|
||
m.index -= p.length;
|
||
}
|
||
}
|
||
if (p === null || p.marker === true) {
|
||
searchMarker.splice(i, 1);
|
||
continue;
|
||
}
|
||
m.p = p;
|
||
p.marker = true;
|
||
}
|
||
if (index < m.index || len > 0 && index === m.index) {
|
||
m.index = max(index, m.index + len);
|
||
}
|
||
}
|
||
};
|
||
var getTypeChildren = (t) => {
|
||
t.doc ?? warnPrematureAccess();
|
||
let s = t._start;
|
||
const arr = [];
|
||
while (s) {
|
||
arr.push(s);
|
||
s = s.right;
|
||
}
|
||
return arr;
|
||
};
|
||
var callTypeObservers = (type, transaction, event) => {
|
||
const changedType = type;
|
||
const changedParentTypes = transaction.changedParentTypes;
|
||
while (true) {
|
||
setIfUndefined(changedParentTypes, type, () => []).push(event);
|
||
if (type._item === null) {
|
||
break;
|
||
}
|
||
type = /** @type {AbstractType<any>} */
|
||
type._item.parent;
|
||
}
|
||
callEventHandlerListeners(changedType._eH, event, transaction);
|
||
};
|
||
var AbstractType = class {
|
||
constructor() {
|
||
this._item = null;
|
||
this._map = /* @__PURE__ */ new Map();
|
||
this._start = null;
|
||
this.doc = null;
|
||
this._length = 0;
|
||
this._eH = createEventHandler();
|
||
this._dEH = createEventHandler();
|
||
this._searchMarker = null;
|
||
}
|
||
/**
|
||
* @return {AbstractType<any>|null}
|
||
*/
|
||
get parent() {
|
||
return this._item ? (
|
||
/** @type {AbstractType<any>} */
|
||
this._item.parent
|
||
) : null;
|
||
}
|
||
/**
|
||
* Integrate this type into the Yjs instance.
|
||
*
|
||
* * Save this struct in the os
|
||
* * This type is sent to other client
|
||
* * Observer functions are fired
|
||
*
|
||
* @param {Doc} y The Yjs instance
|
||
* @param {Item|null} item
|
||
*/
|
||
_integrate(y, item) {
|
||
this.doc = y;
|
||
this._item = item;
|
||
}
|
||
/**
|
||
* @return {AbstractType<EventType>}
|
||
*/
|
||
_copy() {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* Makes a copy of this data type that can be included somewhere else.
|
||
*
|
||
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||
*
|
||
* @return {AbstractType<EventType>}
|
||
*/
|
||
clone() {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} _encoder
|
||
*/
|
||
_write(_encoder) {
|
||
}
|
||
/**
|
||
* The first non-deleted item
|
||
*/
|
||
get _first() {
|
||
let n = this._start;
|
||
while (n !== null && n.deleted) {
|
||
n = n.right;
|
||
}
|
||
return n;
|
||
}
|
||
/**
|
||
* Creates YEvent and calls all type observers.
|
||
* Must be implemented by each type.
|
||
*
|
||
* @param {Transaction} transaction
|
||
* @param {Set<null|string>} _parentSubs Keys changed on this type. `null` if list was modified.
|
||
*/
|
||
_callObserver(transaction, _parentSubs) {
|
||
if (!transaction.local && this._searchMarker) {
|
||
this._searchMarker.length = 0;
|
||
}
|
||
}
|
||
/**
|
||
* Observe all events that are created on this type.
|
||
*
|
||
* @param {function(EventType, Transaction):void} f Observer function
|
||
*/
|
||
observe(f) {
|
||
addEventHandlerListener(this._eH, f);
|
||
}
|
||
/**
|
||
* Observe all events that are created by this type and its children.
|
||
*
|
||
* @param {function(Array<YEvent<any>>,Transaction):void} f Observer function
|
||
*/
|
||
observeDeep(f) {
|
||
addEventHandlerListener(this._dEH, f);
|
||
}
|
||
/**
|
||
* Unregister an observer function.
|
||
*
|
||
* @param {function(EventType,Transaction):void} f Observer function
|
||
*/
|
||
unobserve(f) {
|
||
removeEventHandlerListener(this._eH, f);
|
||
}
|
||
/**
|
||
* Unregister an observer function.
|
||
*
|
||
* @param {function(Array<YEvent<any>>,Transaction):void} f Observer function
|
||
*/
|
||
unobserveDeep(f) {
|
||
removeEventHandlerListener(this._dEH, f);
|
||
}
|
||
/**
|
||
* @abstract
|
||
* @return {any}
|
||
*/
|
||
toJSON() {
|
||
}
|
||
};
|
||
var typeListSlice = (type, start, end) => {
|
||
type.doc ?? warnPrematureAccess();
|
||
if (start < 0) {
|
||
start = type._length + start;
|
||
}
|
||
if (end < 0) {
|
||
end = type._length + end;
|
||
}
|
||
let len = end - start;
|
||
const cs = [];
|
||
let n = type._start;
|
||
while (n !== null && len > 0) {
|
||
if (n.countable && !n.deleted) {
|
||
const c = n.content.getContent();
|
||
if (c.length <= start) {
|
||
start -= c.length;
|
||
} else {
|
||
for (let i = start; i < c.length && len > 0; i++) {
|
||
cs.push(c[i]);
|
||
len--;
|
||
}
|
||
start = 0;
|
||
}
|
||
}
|
||
n = n.right;
|
||
}
|
||
return cs;
|
||
};
|
||
var typeListToArray = (type) => {
|
||
type.doc ?? warnPrematureAccess();
|
||
const cs = [];
|
||
let n = type._start;
|
||
while (n !== null) {
|
||
if (n.countable && !n.deleted) {
|
||
const c = n.content.getContent();
|
||
for (let i = 0; i < c.length; i++) {
|
||
cs.push(c[i]);
|
||
}
|
||
}
|
||
n = n.right;
|
||
}
|
||
return cs;
|
||
};
|
||
var typeListToArraySnapshot = (type, snapshot2) => {
|
||
const cs = [];
|
||
let n = type._start;
|
||
while (n !== null) {
|
||
if (n.countable && isVisible(n, snapshot2)) {
|
||
const c = n.content.getContent();
|
||
for (let i = 0; i < c.length; i++) {
|
||
cs.push(c[i]);
|
||
}
|
||
}
|
||
n = n.right;
|
||
}
|
||
return cs;
|
||
};
|
||
var typeListForEach = (type, f) => {
|
||
let index = 0;
|
||
let n = type._start;
|
||
type.doc ?? warnPrematureAccess();
|
||
while (n !== null) {
|
||
if (n.countable && !n.deleted) {
|
||
const c = n.content.getContent();
|
||
for (let i = 0; i < c.length; i++) {
|
||
f(c[i], index++, type);
|
||
}
|
||
}
|
||
n = n.right;
|
||
}
|
||
};
|
||
var typeListMap = (type, f) => {
|
||
const result = [];
|
||
typeListForEach(type, (c, i) => {
|
||
result.push(f(c, i, type));
|
||
});
|
||
return result;
|
||
};
|
||
var typeListCreateIterator = (type) => {
|
||
let n = type._start;
|
||
let currentContent = null;
|
||
let currentContentIndex = 0;
|
||
return {
|
||
[Symbol.iterator]() {
|
||
return this;
|
||
},
|
||
next: () => {
|
||
if (currentContent === null) {
|
||
while (n !== null && n.deleted) {
|
||
n = n.right;
|
||
}
|
||
if (n === null) {
|
||
return {
|
||
done: true,
|
||
value: void 0
|
||
};
|
||
}
|
||
currentContent = n.content.getContent();
|
||
currentContentIndex = 0;
|
||
n = n.right;
|
||
}
|
||
const value = currentContent[currentContentIndex++];
|
||
if (currentContent.length <= currentContentIndex) {
|
||
currentContent = null;
|
||
}
|
||
return {
|
||
done: false,
|
||
value
|
||
};
|
||
}
|
||
};
|
||
};
|
||
var typeListGet = (type, index) => {
|
||
type.doc ?? warnPrematureAccess();
|
||
const marker = findMarker(type, index);
|
||
let n = type._start;
|
||
if (marker !== null) {
|
||
n = marker.p;
|
||
index -= marker.index;
|
||
}
|
||
for (; n !== null; n = n.right) {
|
||
if (!n.deleted && n.countable) {
|
||
if (index < n.length) {
|
||
return n.content.getContent()[index];
|
||
}
|
||
index -= n.length;
|
||
}
|
||
}
|
||
};
|
||
var typeListInsertGenericsAfter = (transaction, parent, referenceItem, content) => {
|
||
let left = referenceItem;
|
||
const doc2 = transaction.doc;
|
||
const ownClientId = doc2.clientID;
|
||
const store = doc2.store;
|
||
const right = referenceItem === null ? parent._start : referenceItem.right;
|
||
let jsonContent = [];
|
||
const packJsonContent = () => {
|
||
if (jsonContent.length > 0) {
|
||
left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentAny(jsonContent));
|
||
left.integrate(transaction, 0);
|
||
jsonContent = [];
|
||
}
|
||
};
|
||
content.forEach((c) => {
|
||
if (c === null) {
|
||
jsonContent.push(c);
|
||
} else {
|
||
switch (c.constructor) {
|
||
case Number:
|
||
case Object:
|
||
case Boolean:
|
||
case Array:
|
||
case String:
|
||
jsonContent.push(c);
|
||
break;
|
||
default:
|
||
packJsonContent();
|
||
switch (c.constructor) {
|
||
case Uint8Array:
|
||
case ArrayBuffer:
|
||
left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentBinary(new Uint8Array(
|
||
/** @type {Uint8Array} */
|
||
c
|
||
)));
|
||
left.integrate(transaction, 0);
|
||
break;
|
||
case Doc:
|
||
left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentDoc(
|
||
/** @type {Doc} */
|
||
c
|
||
));
|
||
left.integrate(transaction, 0);
|
||
break;
|
||
default:
|
||
if (c instanceof AbstractType) {
|
||
left = new Item(createID(ownClientId, getState(store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentType(c));
|
||
left.integrate(transaction, 0);
|
||
} else {
|
||
throw new Error("Unexpected content type in insert operation");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
packJsonContent();
|
||
};
|
||
var lengthExceeded = () => create3("Length exceeded!");
|
||
var typeListInsertGenerics = (transaction, parent, index, content) => {
|
||
if (index > parent._length) {
|
||
throw lengthExceeded();
|
||
}
|
||
if (index === 0) {
|
||
if (parent._searchMarker) {
|
||
updateMarkerChanges(parent._searchMarker, index, content.length);
|
||
}
|
||
return typeListInsertGenericsAfter(transaction, parent, null, content);
|
||
}
|
||
const startIndex = index;
|
||
const marker = findMarker(parent, index);
|
||
let n = parent._start;
|
||
if (marker !== null) {
|
||
n = marker.p;
|
||
index -= marker.index;
|
||
if (index === 0) {
|
||
n = n.prev;
|
||
index += n && n.countable && !n.deleted ? n.length : 0;
|
||
}
|
||
}
|
||
for (; n !== null; n = n.right) {
|
||
if (!n.deleted && n.countable) {
|
||
if (index <= n.length) {
|
||
if (index < n.length) {
|
||
getItemCleanStart(transaction, createID(n.id.client, n.id.clock + index));
|
||
}
|
||
break;
|
||
}
|
||
index -= n.length;
|
||
}
|
||
}
|
||
if (parent._searchMarker) {
|
||
updateMarkerChanges(parent._searchMarker, startIndex, content.length);
|
||
}
|
||
return typeListInsertGenericsAfter(transaction, parent, n, content);
|
||
};
|
||
var typeListPushGenerics = (transaction, parent, content) => {
|
||
const marker = (parent._searchMarker || []).reduce((maxMarker, currMarker) => currMarker.index > maxMarker.index ? currMarker : maxMarker, { index: 0, p: parent._start });
|
||
let n = marker.p;
|
||
if (n) {
|
||
while (n.right) {
|
||
n = n.right;
|
||
}
|
||
}
|
||
return typeListInsertGenericsAfter(transaction, parent, n, content);
|
||
};
|
||
var typeListDelete = (transaction, parent, index, length2) => {
|
||
if (length2 === 0) {
|
||
return;
|
||
}
|
||
const startIndex = index;
|
||
const startLength = length2;
|
||
const marker = findMarker(parent, index);
|
||
let n = parent._start;
|
||
if (marker !== null) {
|
||
n = marker.p;
|
||
index -= marker.index;
|
||
}
|
||
for (; n !== null && index > 0; n = n.right) {
|
||
if (!n.deleted && n.countable) {
|
||
if (index < n.length) {
|
||
getItemCleanStart(transaction, createID(n.id.client, n.id.clock + index));
|
||
}
|
||
index -= n.length;
|
||
}
|
||
}
|
||
while (length2 > 0 && n !== null) {
|
||
if (!n.deleted) {
|
||
if (length2 < n.length) {
|
||
getItemCleanStart(transaction, createID(n.id.client, n.id.clock + length2));
|
||
}
|
||
n.delete(transaction);
|
||
length2 -= n.length;
|
||
}
|
||
n = n.right;
|
||
}
|
||
if (length2 > 0) {
|
||
throw lengthExceeded();
|
||
}
|
||
if (parent._searchMarker) {
|
||
updateMarkerChanges(
|
||
parent._searchMarker,
|
||
startIndex,
|
||
-startLength + length2
|
||
/* in case we remove the above exception */
|
||
);
|
||
}
|
||
};
|
||
var typeMapDelete = (transaction, parent, key) => {
|
||
const c = parent._map.get(key);
|
||
if (c !== void 0) {
|
||
c.delete(transaction);
|
||
}
|
||
};
|
||
var typeMapSet = (transaction, parent, key, value) => {
|
||
const left = parent._map.get(key) || null;
|
||
const doc2 = transaction.doc;
|
||
const ownClientId = doc2.clientID;
|
||
let content;
|
||
if (value == null) {
|
||
content = new ContentAny([value]);
|
||
} else {
|
||
switch (value.constructor) {
|
||
case Number:
|
||
case Object:
|
||
case Boolean:
|
||
case Array:
|
||
case String:
|
||
case Date:
|
||
case BigInt:
|
||
content = new ContentAny([value]);
|
||
break;
|
||
case Uint8Array:
|
||
content = new ContentBinary(
|
||
/** @type {Uint8Array} */
|
||
value
|
||
);
|
||
break;
|
||
case Doc:
|
||
content = new ContentDoc(
|
||
/** @type {Doc} */
|
||
value
|
||
);
|
||
break;
|
||
default:
|
||
if (value instanceof AbstractType) {
|
||
content = new ContentType(value);
|
||
} else {
|
||
throw new Error("Unexpected content type");
|
||
}
|
||
}
|
||
}
|
||
new Item(createID(ownClientId, getState(doc2.store, ownClientId)), left, left && left.lastId, null, null, parent, key, content).integrate(transaction, 0);
|
||
};
|
||
var typeMapGet = (parent, key) => {
|
||
parent.doc ?? warnPrematureAccess();
|
||
const val = parent._map.get(key);
|
||
return val !== void 0 && !val.deleted ? val.content.getContent()[val.length - 1] : void 0;
|
||
};
|
||
var typeMapGetAll = (parent) => {
|
||
const res = {};
|
||
parent.doc ?? warnPrematureAccess();
|
||
parent._map.forEach((value, key) => {
|
||
if (!value.deleted) {
|
||
res[key] = value.content.getContent()[value.length - 1];
|
||
}
|
||
});
|
||
return res;
|
||
};
|
||
var typeMapHas = (parent, key) => {
|
||
parent.doc ?? warnPrematureAccess();
|
||
const val = parent._map.get(key);
|
||
return val !== void 0 && !val.deleted;
|
||
};
|
||
var typeMapGetSnapshot = (parent, key, snapshot2) => {
|
||
let v = parent._map.get(key) || null;
|
||
while (v !== null && (!snapshot2.sv.has(v.id.client) || v.id.clock >= (snapshot2.sv.get(v.id.client) || 0))) {
|
||
v = v.left;
|
||
}
|
||
return v !== null && isVisible(v, snapshot2) ? v.content.getContent()[v.length - 1] : void 0;
|
||
};
|
||
var typeMapGetAllSnapshot = (parent, snapshot2) => {
|
||
const res = {};
|
||
parent._map.forEach((value, key) => {
|
||
let v = value;
|
||
while (v !== null && (!snapshot2.sv.has(v.id.client) || v.id.clock >= (snapshot2.sv.get(v.id.client) || 0))) {
|
||
v = v.left;
|
||
}
|
||
if (v !== null && isVisible(v, snapshot2)) {
|
||
res[key] = v.content.getContent()[v.length - 1];
|
||
}
|
||
});
|
||
return res;
|
||
};
|
||
var createMapIterator = (type) => {
|
||
type.doc ?? warnPrematureAccess();
|
||
return iteratorFilter(
|
||
type._map.entries(),
|
||
/** @param {any} entry */
|
||
(entry) => !entry[1].deleted
|
||
);
|
||
};
|
||
var YArrayEvent = class extends YEvent {
|
||
};
|
||
var YArray = class _YArray extends AbstractType {
|
||
constructor() {
|
||
super();
|
||
this._prelimContent = [];
|
||
this._searchMarker = [];
|
||
}
|
||
/**
|
||
* Construct a new YArray containing the specified items.
|
||
* @template {Object<string,any>|Array<any>|number|null|string|Uint8Array} T
|
||
* @param {Array<T>} items
|
||
* @return {YArray<T>}
|
||
*/
|
||
static from(items) {
|
||
const a = new _YArray();
|
||
a.push(items);
|
||
return a;
|
||
}
|
||
/**
|
||
* Integrate this type into the Yjs instance.
|
||
*
|
||
* * Save this struct in the os
|
||
* * This type is sent to other client
|
||
* * Observer functions are fired
|
||
*
|
||
* @param {Doc} y The Yjs instance
|
||
* @param {Item} item
|
||
*/
|
||
_integrate(y, item) {
|
||
super._integrate(y, item);
|
||
this.insert(
|
||
0,
|
||
/** @type {Array<any>} */
|
||
this._prelimContent
|
||
);
|
||
this._prelimContent = null;
|
||
}
|
||
/**
|
||
* @return {YArray<T>}
|
||
*/
|
||
_copy() {
|
||
return new _YArray();
|
||
}
|
||
/**
|
||
* Makes a copy of this data type that can be included somewhere else.
|
||
*
|
||
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||
*
|
||
* @return {YArray<T>}
|
||
*/
|
||
clone() {
|
||
const arr = new _YArray();
|
||
arr.insert(0, this.toArray().map(
|
||
(el) => el instanceof AbstractType ? (
|
||
/** @type {typeof el} */
|
||
el.clone()
|
||
) : el
|
||
));
|
||
return arr;
|
||
}
|
||
get length() {
|
||
this.doc ?? warnPrematureAccess();
|
||
return this._length;
|
||
}
|
||
/**
|
||
* Creates YArrayEvent and calls observers.
|
||
*
|
||
* @param {Transaction} transaction
|
||
* @param {Set<null|string>} parentSubs Keys changed on this type. `null` if list was modified.
|
||
*/
|
||
_callObserver(transaction, parentSubs) {
|
||
super._callObserver(transaction, parentSubs);
|
||
callTypeObservers(this, transaction, new YArrayEvent(this, transaction));
|
||
}
|
||
/**
|
||
* Inserts new content at an index.
|
||
*
|
||
* Important: This function expects an array of content. Not just a content
|
||
* object. The reason for this "weirdness" is that inserting several elements
|
||
* is very efficient when it is done as a single operation.
|
||
*
|
||
* @example
|
||
* // Insert character 'a' at position 0
|
||
* yarray.insert(0, ['a'])
|
||
* // Insert numbers 1, 2 at position 1
|
||
* yarray.insert(1, [1, 2])
|
||
*
|
||
* @param {number} index The index to insert content at.
|
||
* @param {Array<T>} content The array of content
|
||
*/
|
||
insert(index, content) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeListInsertGenerics(
|
||
transaction,
|
||
this,
|
||
index,
|
||
/** @type {any} */
|
||
content
|
||
);
|
||
});
|
||
} else {
|
||
this._prelimContent.splice(index, 0, ...content);
|
||
}
|
||
}
|
||
/**
|
||
* Appends content to this YArray.
|
||
*
|
||
* @param {Array<T>} content Array of content to append.
|
||
*
|
||
* @todo Use the following implementation in all types.
|
||
*/
|
||
push(content) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeListPushGenerics(
|
||
transaction,
|
||
this,
|
||
/** @type {any} */
|
||
content
|
||
);
|
||
});
|
||
} else {
|
||
this._prelimContent.push(...content);
|
||
}
|
||
}
|
||
/**
|
||
* Prepends content to this YArray.
|
||
*
|
||
* @param {Array<T>} content Array of content to prepend.
|
||
*/
|
||
unshift(content) {
|
||
this.insert(0, content);
|
||
}
|
||
/**
|
||
* Deletes elements starting from an index.
|
||
*
|
||
* @param {number} index Index at which to start deleting elements
|
||
* @param {number} length The number of elements to remove. Defaults to 1.
|
||
*/
|
||
delete(index, length2 = 1) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeListDelete(transaction, this, index, length2);
|
||
});
|
||
} else {
|
||
this._prelimContent.splice(index, length2);
|
||
}
|
||
}
|
||
/**
|
||
* Returns the i-th element from a YArray.
|
||
*
|
||
* @param {number} index The index of the element to return from the YArray
|
||
* @return {T}
|
||
*/
|
||
get(index) {
|
||
return typeListGet(this, index);
|
||
}
|
||
/**
|
||
* Transforms this YArray to a JavaScript Array.
|
||
*
|
||
* @return {Array<T>}
|
||
*/
|
||
toArray() {
|
||
return typeListToArray(this);
|
||
}
|
||
/**
|
||
* Returns a portion of this YArray into a JavaScript Array selected
|
||
* from start to end (end not included).
|
||
*
|
||
* @param {number} [start]
|
||
* @param {number} [end]
|
||
* @return {Array<T>}
|
||
*/
|
||
slice(start = 0, end = this.length) {
|
||
return typeListSlice(this, start, end);
|
||
}
|
||
/**
|
||
* Transforms this Shared Type to a JSON object.
|
||
*
|
||
* @return {Array<any>}
|
||
*/
|
||
toJSON() {
|
||
return this.map((c) => c instanceof AbstractType ? c.toJSON() : c);
|
||
}
|
||
/**
|
||
* Returns an Array with the result of calling a provided function on every
|
||
* element of this YArray.
|
||
*
|
||
* @template M
|
||
* @param {function(T,number,YArray<T>):M} f Function that produces an element of the new Array
|
||
* @return {Array<M>} A new array with each element being the result of the
|
||
* callback function
|
||
*/
|
||
map(f) {
|
||
return typeListMap(
|
||
this,
|
||
/** @type {any} */
|
||
f
|
||
);
|
||
}
|
||
/**
|
||
* Executes a provided function once on every element of this YArray.
|
||
*
|
||
* @param {function(T,number,YArray<T>):void} f A function to execute on every element of this YArray.
|
||
*/
|
||
forEach(f) {
|
||
typeListForEach(this, f);
|
||
}
|
||
/**
|
||
* @return {IterableIterator<T>}
|
||
*/
|
||
[Symbol.iterator]() {
|
||
return typeListCreateIterator(this);
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
*/
|
||
_write(encoder) {
|
||
encoder.writeTypeRef(YArrayRefID);
|
||
}
|
||
};
|
||
var readYArray = (_decoder) => new YArray();
|
||
var YMapEvent = class extends YEvent {
|
||
/**
|
||
* @param {YMap<T>} ymap The YArray that changed.
|
||
* @param {Transaction} transaction
|
||
* @param {Set<any>} subs The keys that changed.
|
||
*/
|
||
constructor(ymap, transaction, subs) {
|
||
super(ymap, transaction);
|
||
this.keysChanged = subs;
|
||
}
|
||
};
|
||
var YMap = class _YMap extends AbstractType {
|
||
/**
|
||
*
|
||
* @param {Iterable<readonly [string, any]>=} entries - an optional iterable to initialize the YMap
|
||
*/
|
||
constructor(entries) {
|
||
super();
|
||
this._prelimContent = null;
|
||
if (entries === void 0) {
|
||
this._prelimContent = /* @__PURE__ */ new Map();
|
||
} else {
|
||
this._prelimContent = new Map(entries);
|
||
}
|
||
}
|
||
/**
|
||
* Integrate this type into the Yjs instance.
|
||
*
|
||
* * Save this struct in the os
|
||
* * This type is sent to other client
|
||
* * Observer functions are fired
|
||
*
|
||
* @param {Doc} y The Yjs instance
|
||
* @param {Item} item
|
||
*/
|
||
_integrate(y, item) {
|
||
super._integrate(y, item);
|
||
this._prelimContent.forEach((value, key) => {
|
||
this.set(key, value);
|
||
});
|
||
this._prelimContent = null;
|
||
}
|
||
/**
|
||
* @return {YMap<MapType>}
|
||
*/
|
||
_copy() {
|
||
return new _YMap();
|
||
}
|
||
/**
|
||
* Makes a copy of this data type that can be included somewhere else.
|
||
*
|
||
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||
*
|
||
* @return {YMap<MapType>}
|
||
*/
|
||
clone() {
|
||
const map3 = new _YMap();
|
||
this.forEach((value, key) => {
|
||
map3.set(key, value instanceof AbstractType ? (
|
||
/** @type {typeof value} */
|
||
value.clone()
|
||
) : value);
|
||
});
|
||
return map3;
|
||
}
|
||
/**
|
||
* Creates YMapEvent and calls observers.
|
||
*
|
||
* @param {Transaction} transaction
|
||
* @param {Set<null|string>} parentSubs Keys changed on this type. `null` if list was modified.
|
||
*/
|
||
_callObserver(transaction, parentSubs) {
|
||
callTypeObservers(this, transaction, new YMapEvent(this, transaction, parentSubs));
|
||
}
|
||
/**
|
||
* Transforms this Shared Type to a JSON object.
|
||
*
|
||
* @return {Object<string,any>}
|
||
*/
|
||
toJSON() {
|
||
this.doc ?? warnPrematureAccess();
|
||
const map3 = {};
|
||
this._map.forEach((item, key) => {
|
||
if (!item.deleted) {
|
||
const v = item.content.getContent()[item.length - 1];
|
||
map3[key] = v instanceof AbstractType ? v.toJSON() : v;
|
||
}
|
||
});
|
||
return map3;
|
||
}
|
||
/**
|
||
* Returns the size of the YMap (count of key/value pairs)
|
||
*
|
||
* @return {number}
|
||
*/
|
||
get size() {
|
||
return [...createMapIterator(this)].length;
|
||
}
|
||
/**
|
||
* Returns the keys for each element in the YMap Type.
|
||
*
|
||
* @return {IterableIterator<string>}
|
||
*/
|
||
keys() {
|
||
return iteratorMap(
|
||
createMapIterator(this),
|
||
/** @param {any} v */
|
||
(v) => v[0]
|
||
);
|
||
}
|
||
/**
|
||
* Returns the values for each element in the YMap Type.
|
||
*
|
||
* @return {IterableIterator<MapType>}
|
||
*/
|
||
values() {
|
||
return iteratorMap(
|
||
createMapIterator(this),
|
||
/** @param {any} v */
|
||
(v) => v[1].content.getContent()[v[1].length - 1]
|
||
);
|
||
}
|
||
/**
|
||
* Returns an Iterator of [key, value] pairs
|
||
*
|
||
* @return {IterableIterator<[string, MapType]>}
|
||
*/
|
||
entries() {
|
||
return iteratorMap(
|
||
createMapIterator(this),
|
||
/** @param {any} v */
|
||
(v) => (
|
||
/** @type {any} */
|
||
[v[0], v[1].content.getContent()[v[1].length - 1]]
|
||
)
|
||
);
|
||
}
|
||
/**
|
||
* Executes a provided function on once on every key-value pair.
|
||
*
|
||
* @param {function(MapType,string,YMap<MapType>):void} f A function to execute on every element of this YArray.
|
||
*/
|
||
forEach(f) {
|
||
this.doc ?? warnPrematureAccess();
|
||
this._map.forEach((item, key) => {
|
||
if (!item.deleted) {
|
||
f(item.content.getContent()[item.length - 1], key, this);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Returns an Iterator of [key, value] pairs
|
||
*
|
||
* @return {IterableIterator<[string, MapType]>}
|
||
*/
|
||
[Symbol.iterator]() {
|
||
return this.entries();
|
||
}
|
||
/**
|
||
* Remove a specified element from this YMap.
|
||
*
|
||
* @param {string} key The key of the element to remove.
|
||
*/
|
||
delete(key) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeMapDelete(transaction, this, key);
|
||
});
|
||
} else {
|
||
this._prelimContent.delete(key);
|
||
}
|
||
}
|
||
/**
|
||
* Adds or updates an element with a specified key and value.
|
||
* @template {MapType} VAL
|
||
*
|
||
* @param {string} key The key of the element to add to this YMap
|
||
* @param {VAL} value The value of the element to add
|
||
* @return {VAL}
|
||
*/
|
||
set(key, value) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeMapSet(
|
||
transaction,
|
||
this,
|
||
key,
|
||
/** @type {any} */
|
||
value
|
||
);
|
||
});
|
||
} else {
|
||
this._prelimContent.set(key, value);
|
||
}
|
||
return value;
|
||
}
|
||
/**
|
||
* Returns a specified element from this YMap.
|
||
*
|
||
* @param {string} key
|
||
* @return {MapType|undefined}
|
||
*/
|
||
get(key) {
|
||
return (
|
||
/** @type {any} */
|
||
typeMapGet(this, key)
|
||
);
|
||
}
|
||
/**
|
||
* Returns a boolean indicating whether the specified key exists or not.
|
||
*
|
||
* @param {string} key The key to test.
|
||
* @return {boolean}
|
||
*/
|
||
has(key) {
|
||
return typeMapHas(this, key);
|
||
}
|
||
/**
|
||
* Removes all elements from this YMap.
|
||
*/
|
||
clear() {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
this.forEach(function(_value, key, map3) {
|
||
typeMapDelete(transaction, map3, key);
|
||
});
|
||
});
|
||
} else {
|
||
this._prelimContent.clear();
|
||
}
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
*/
|
||
_write(encoder) {
|
||
encoder.writeTypeRef(YMapRefID);
|
||
}
|
||
};
|
||
var readYMap = (_decoder) => new YMap();
|
||
var equalAttrs = (a, b) => a === b || typeof a === "object" && typeof b === "object" && a && b && equalFlat(a, b);
|
||
var ItemTextListPosition = class {
|
||
/**
|
||
* @param {Item|null} left
|
||
* @param {Item|null} right
|
||
* @param {number} index
|
||
* @param {Map<string,any>} currentAttributes
|
||
*/
|
||
constructor(left, right, index, currentAttributes) {
|
||
this.left = left;
|
||
this.right = right;
|
||
this.index = index;
|
||
this.currentAttributes = currentAttributes;
|
||
}
|
||
/**
|
||
* Only call this if you know that this.right is defined
|
||
*/
|
||
forward() {
|
||
if (this.right === null) {
|
||
unexpectedCase();
|
||
}
|
||
switch (this.right.content.constructor) {
|
||
case ContentFormat:
|
||
if (!this.right.deleted) {
|
||
updateCurrentAttributes(
|
||
this.currentAttributes,
|
||
/** @type {ContentFormat} */
|
||
this.right.content
|
||
);
|
||
}
|
||
break;
|
||
default:
|
||
if (!this.right.deleted) {
|
||
this.index += this.right.length;
|
||
}
|
||
break;
|
||
}
|
||
this.left = this.right;
|
||
this.right = this.right.right;
|
||
}
|
||
};
|
||
var findNextPosition = (transaction, pos, count) => {
|
||
while (pos.right !== null && count > 0) {
|
||
switch (pos.right.content.constructor) {
|
||
case ContentFormat:
|
||
if (!pos.right.deleted) {
|
||
updateCurrentAttributes(
|
||
pos.currentAttributes,
|
||
/** @type {ContentFormat} */
|
||
pos.right.content
|
||
);
|
||
}
|
||
break;
|
||
default:
|
||
if (!pos.right.deleted) {
|
||
if (count < pos.right.length) {
|
||
getItemCleanStart(transaction, createID(pos.right.id.client, pos.right.id.clock + count));
|
||
}
|
||
pos.index += pos.right.length;
|
||
count -= pos.right.length;
|
||
}
|
||
break;
|
||
}
|
||
pos.left = pos.right;
|
||
pos.right = pos.right.right;
|
||
}
|
||
return pos;
|
||
};
|
||
var findPosition = (transaction, parent, index, useSearchMarker) => {
|
||
const currentAttributes = /* @__PURE__ */ new Map();
|
||
const marker = useSearchMarker ? findMarker(parent, index) : null;
|
||
if (marker) {
|
||
const pos = new ItemTextListPosition(marker.p.left, marker.p, marker.index, currentAttributes);
|
||
return findNextPosition(transaction, pos, index - marker.index);
|
||
} else {
|
||
const pos = new ItemTextListPosition(null, parent._start, 0, currentAttributes);
|
||
return findNextPosition(transaction, pos, index);
|
||
}
|
||
};
|
||
var insertNegatedAttributes = (transaction, parent, currPos, negatedAttributes) => {
|
||
while (currPos.right !== null && (currPos.right.deleted === true || currPos.right.content.constructor === ContentFormat && equalAttrs(
|
||
negatedAttributes.get(
|
||
/** @type {ContentFormat} */
|
||
currPos.right.content.key
|
||
),
|
||
/** @type {ContentFormat} */
|
||
currPos.right.content.value
|
||
))) {
|
||
if (!currPos.right.deleted) {
|
||
negatedAttributes.delete(
|
||
/** @type {ContentFormat} */
|
||
currPos.right.content.key
|
||
);
|
||
}
|
||
currPos.forward();
|
||
}
|
||
const doc2 = transaction.doc;
|
||
const ownClientId = doc2.clientID;
|
||
negatedAttributes.forEach((val, key) => {
|
||
const left = currPos.left;
|
||
const right = currPos.right;
|
||
const nextFormat = new Item(createID(ownClientId, getState(doc2.store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentFormat(key, val));
|
||
nextFormat.integrate(transaction, 0);
|
||
currPos.right = nextFormat;
|
||
currPos.forward();
|
||
});
|
||
};
|
||
var updateCurrentAttributes = (currentAttributes, format) => {
|
||
const { key, value } = format;
|
||
if (value === null) {
|
||
currentAttributes.delete(key);
|
||
} else {
|
||
currentAttributes.set(key, value);
|
||
}
|
||
};
|
||
var minimizeAttributeChanges = (currPos, attributes) => {
|
||
while (true) {
|
||
if (currPos.right === null) {
|
||
break;
|
||
} else if (currPos.right.deleted || currPos.right.content.constructor === ContentFormat && equalAttrs(
|
||
attributes[
|
||
/** @type {ContentFormat} */
|
||
currPos.right.content.key
|
||
] ?? null,
|
||
/** @type {ContentFormat} */
|
||
currPos.right.content.value
|
||
)) ;
|
||
else {
|
||
break;
|
||
}
|
||
currPos.forward();
|
||
}
|
||
};
|
||
var insertAttributes = (transaction, parent, currPos, attributes) => {
|
||
const doc2 = transaction.doc;
|
||
const ownClientId = doc2.clientID;
|
||
const negatedAttributes = /* @__PURE__ */ new Map();
|
||
for (const key in attributes) {
|
||
const val = attributes[key];
|
||
const currentVal = currPos.currentAttributes.get(key) ?? null;
|
||
if (!equalAttrs(currentVal, val)) {
|
||
negatedAttributes.set(key, currentVal);
|
||
const { left, right } = currPos;
|
||
currPos.right = new Item(createID(ownClientId, getState(doc2.store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentFormat(key, val));
|
||
currPos.right.integrate(transaction, 0);
|
||
currPos.forward();
|
||
}
|
||
}
|
||
return negatedAttributes;
|
||
};
|
||
var insertText = (transaction, parent, currPos, text2, attributes) => {
|
||
currPos.currentAttributes.forEach((_val, key) => {
|
||
if (attributes[key] === void 0) {
|
||
attributes[key] = null;
|
||
}
|
||
});
|
||
const doc2 = transaction.doc;
|
||
const ownClientId = doc2.clientID;
|
||
minimizeAttributeChanges(currPos, attributes);
|
||
const negatedAttributes = insertAttributes(transaction, parent, currPos, attributes);
|
||
const content = text2.constructor === String ? new ContentString(
|
||
/** @type {string} */
|
||
text2
|
||
) : text2 instanceof AbstractType ? new ContentType(text2) : new ContentEmbed(text2);
|
||
let { left, right, index } = currPos;
|
||
if (parent._searchMarker) {
|
||
updateMarkerChanges(parent._searchMarker, currPos.index, content.getLength());
|
||
}
|
||
right = new Item(createID(ownClientId, getState(doc2.store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, content);
|
||
right.integrate(transaction, 0);
|
||
currPos.right = right;
|
||
currPos.index = index;
|
||
currPos.forward();
|
||
insertNegatedAttributes(transaction, parent, currPos, negatedAttributes);
|
||
};
|
||
var formatText = (transaction, parent, currPos, length2, attributes) => {
|
||
const doc2 = transaction.doc;
|
||
const ownClientId = doc2.clientID;
|
||
minimizeAttributeChanges(currPos, attributes);
|
||
const negatedAttributes = insertAttributes(transaction, parent, currPos, attributes);
|
||
iterationLoop: while (currPos.right !== null && (length2 > 0 || negatedAttributes.size > 0 && (currPos.right.deleted || currPos.right.content.constructor === ContentFormat))) {
|
||
if (!currPos.right.deleted) {
|
||
switch (currPos.right.content.constructor) {
|
||
case ContentFormat: {
|
||
const { key, value } = (
|
||
/** @type {ContentFormat} */
|
||
currPos.right.content
|
||
);
|
||
const attr = attributes[key];
|
||
if (attr !== void 0) {
|
||
if (equalAttrs(attr, value)) {
|
||
negatedAttributes.delete(key);
|
||
} else {
|
||
if (length2 === 0) {
|
||
break iterationLoop;
|
||
}
|
||
negatedAttributes.set(key, value);
|
||
}
|
||
currPos.right.delete(transaction);
|
||
} else {
|
||
currPos.currentAttributes.set(key, value);
|
||
}
|
||
break;
|
||
}
|
||
default:
|
||
if (length2 < currPos.right.length) {
|
||
getItemCleanStart(transaction, createID(currPos.right.id.client, currPos.right.id.clock + length2));
|
||
}
|
||
length2 -= currPos.right.length;
|
||
break;
|
||
}
|
||
}
|
||
currPos.forward();
|
||
}
|
||
if (length2 > 0) {
|
||
let newlines = "";
|
||
for (; length2 > 0; length2--) {
|
||
newlines += "\n";
|
||
}
|
||
currPos.right = new Item(createID(ownClientId, getState(doc2.store, ownClientId)), currPos.left, currPos.left && currPos.left.lastId, currPos.right, currPos.right && currPos.right.id, parent, null, new ContentString(newlines));
|
||
currPos.right.integrate(transaction, 0);
|
||
currPos.forward();
|
||
}
|
||
insertNegatedAttributes(transaction, parent, currPos, negatedAttributes);
|
||
};
|
||
var cleanupFormattingGap = (transaction, start, curr, startAttributes, currAttributes) => {
|
||
let end = start;
|
||
const endFormats = create();
|
||
while (end && (!end.countable || end.deleted)) {
|
||
if (!end.deleted && end.content.constructor === ContentFormat) {
|
||
const cf = (
|
||
/** @type {ContentFormat} */
|
||
end.content
|
||
);
|
||
endFormats.set(cf.key, cf);
|
||
}
|
||
end = end.right;
|
||
}
|
||
let cleanups = 0;
|
||
let reachedCurr = false;
|
||
while (start !== end) {
|
||
if (curr === start) {
|
||
reachedCurr = true;
|
||
}
|
||
if (!start.deleted) {
|
||
const content = start.content;
|
||
switch (content.constructor) {
|
||
case ContentFormat: {
|
||
const { key, value } = (
|
||
/** @type {ContentFormat} */
|
||
content
|
||
);
|
||
const startAttrValue = startAttributes.get(key) ?? null;
|
||
if (endFormats.get(key) !== content || startAttrValue === value) {
|
||
start.delete(transaction);
|
||
cleanups++;
|
||
if (!reachedCurr && (currAttributes.get(key) ?? null) === value && startAttrValue !== value) {
|
||
if (startAttrValue === null) {
|
||
currAttributes.delete(key);
|
||
} else {
|
||
currAttributes.set(key, startAttrValue);
|
||
}
|
||
}
|
||
}
|
||
if (!reachedCurr && !start.deleted) {
|
||
updateCurrentAttributes(
|
||
currAttributes,
|
||
/** @type {ContentFormat} */
|
||
content
|
||
);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
start = /** @type {Item} */
|
||
start.right;
|
||
}
|
||
return cleanups;
|
||
};
|
||
var cleanupContextlessFormattingGap = (transaction, item) => {
|
||
while (item && item.right && (item.right.deleted || !item.right.countable)) {
|
||
item = item.right;
|
||
}
|
||
const attrs = /* @__PURE__ */ new Set();
|
||
while (item && (item.deleted || !item.countable)) {
|
||
if (!item.deleted && item.content.constructor === ContentFormat) {
|
||
const key = (
|
||
/** @type {ContentFormat} */
|
||
item.content.key
|
||
);
|
||
if (attrs.has(key)) {
|
||
item.delete(transaction);
|
||
} else {
|
||
attrs.add(key);
|
||
}
|
||
}
|
||
item = item.left;
|
||
}
|
||
};
|
||
var cleanupYTextFormatting = (type) => {
|
||
let res = 0;
|
||
transact(
|
||
/** @type {Doc} */
|
||
type.doc,
|
||
(transaction) => {
|
||
let start = (
|
||
/** @type {Item} */
|
||
type._start
|
||
);
|
||
let end = type._start;
|
||
let startAttributes = create();
|
||
const currentAttributes = copy(startAttributes);
|
||
while (end) {
|
||
if (end.deleted === false) {
|
||
switch (end.content.constructor) {
|
||
case ContentFormat:
|
||
updateCurrentAttributes(
|
||
currentAttributes,
|
||
/** @type {ContentFormat} */
|
||
end.content
|
||
);
|
||
break;
|
||
default:
|
||
res += cleanupFormattingGap(transaction, start, end, startAttributes, currentAttributes);
|
||
startAttributes = copy(currentAttributes);
|
||
start = end;
|
||
break;
|
||
}
|
||
}
|
||
end = end.right;
|
||
}
|
||
}
|
||
);
|
||
return res;
|
||
};
|
||
var cleanupYTextAfterTransaction = (transaction) => {
|
||
const needFullCleanup = /* @__PURE__ */ new Set();
|
||
const doc2 = transaction.doc;
|
||
for (const [client, afterClock] of transaction.afterState.entries()) {
|
||
const clock = transaction.beforeState.get(client) || 0;
|
||
if (afterClock === clock) {
|
||
continue;
|
||
}
|
||
iterateStructs(
|
||
transaction,
|
||
/** @type {Array<Item|GC>} */
|
||
doc2.store.clients.get(client),
|
||
clock,
|
||
afterClock,
|
||
(item) => {
|
||
if (!item.deleted && /** @type {Item} */
|
||
item.content.constructor === ContentFormat && item.constructor !== GC) {
|
||
needFullCleanup.add(
|
||
/** @type {any} */
|
||
item.parent
|
||
);
|
||
}
|
||
}
|
||
);
|
||
}
|
||
transact(doc2, (t) => {
|
||
iterateDeletedStructs(transaction, transaction.deleteSet, (item) => {
|
||
if (item instanceof GC || !/** @type {YText} */
|
||
item.parent._hasFormatting || needFullCleanup.has(
|
||
/** @type {YText} */
|
||
item.parent
|
||
)) {
|
||
return;
|
||
}
|
||
const parent = (
|
||
/** @type {YText} */
|
||
item.parent
|
||
);
|
||
if (item.content.constructor === ContentFormat) {
|
||
needFullCleanup.add(parent);
|
||
} else {
|
||
cleanupContextlessFormattingGap(t, item);
|
||
}
|
||
});
|
||
for (const yText of needFullCleanup) {
|
||
cleanupYTextFormatting(yText);
|
||
}
|
||
});
|
||
};
|
||
var deleteText = (transaction, currPos, length2) => {
|
||
const startLength = length2;
|
||
const startAttrs = copy(currPos.currentAttributes);
|
||
const start = currPos.right;
|
||
while (length2 > 0 && currPos.right !== null) {
|
||
if (currPos.right.deleted === false) {
|
||
switch (currPos.right.content.constructor) {
|
||
case ContentType:
|
||
case ContentEmbed:
|
||
case ContentString:
|
||
if (length2 < currPos.right.length) {
|
||
getItemCleanStart(transaction, createID(currPos.right.id.client, currPos.right.id.clock + length2));
|
||
}
|
||
length2 -= currPos.right.length;
|
||
currPos.right.delete(transaction);
|
||
break;
|
||
}
|
||
}
|
||
currPos.forward();
|
||
}
|
||
if (start) {
|
||
cleanupFormattingGap(transaction, start, currPos.right, startAttrs, currPos.currentAttributes);
|
||
}
|
||
const parent = (
|
||
/** @type {AbstractType<any>} */
|
||
/** @type {Item} */
|
||
(currPos.left || currPos.right).parent
|
||
);
|
||
if (parent._searchMarker) {
|
||
updateMarkerChanges(parent._searchMarker, currPos.index, -startLength + length2);
|
||
}
|
||
return currPos;
|
||
};
|
||
var YTextEvent = class extends YEvent {
|
||
/**
|
||
* @param {YText} ytext
|
||
* @param {Transaction} transaction
|
||
* @param {Set<any>} subs The keys that changed
|
||
*/
|
||
constructor(ytext, transaction, subs) {
|
||
super(ytext, transaction);
|
||
this.childListChanged = false;
|
||
this.keysChanged = /* @__PURE__ */ new Set();
|
||
subs.forEach((sub) => {
|
||
if (sub === null) {
|
||
this.childListChanged = true;
|
||
} else {
|
||
this.keysChanged.add(sub);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* @type {{added:Set<Item>,deleted:Set<Item>,keys:Map<string,{action:'add'|'update'|'delete',oldValue:any}>,delta:Array<{insert?:Array<any>|string, delete?:number, retain?:number}>}}
|
||
*/
|
||
get changes() {
|
||
if (this._changes === null) {
|
||
const changes = {
|
||
keys: this.keys,
|
||
delta: this.delta,
|
||
added: /* @__PURE__ */ new Set(),
|
||
deleted: /* @__PURE__ */ new Set()
|
||
};
|
||
this._changes = changes;
|
||
}
|
||
return (
|
||
/** @type {any} */
|
||
this._changes
|
||
);
|
||
}
|
||
/**
|
||
* Compute the changes in the delta format.
|
||
* A {@link https://quilljs.com/docs/delta/|Quill Delta}) that represents the changes on the document.
|
||
*
|
||
* @type {Array<{insert?:string|object|AbstractType<any>, delete?:number, retain?:number, attributes?: Object<string,any>}>}
|
||
*
|
||
* @public
|
||
*/
|
||
get delta() {
|
||
if (this._delta === null) {
|
||
const y = (
|
||
/** @type {Doc} */
|
||
this.target.doc
|
||
);
|
||
const delta = [];
|
||
transact(y, (transaction) => {
|
||
const currentAttributes = /* @__PURE__ */ new Map();
|
||
const oldAttributes = /* @__PURE__ */ new Map();
|
||
let item = this.target._start;
|
||
let action = null;
|
||
const attributes = {};
|
||
let insert = "";
|
||
let retain = 0;
|
||
let deleteLen = 0;
|
||
const addOp = () => {
|
||
if (action !== null) {
|
||
let op = null;
|
||
switch (action) {
|
||
case "delete":
|
||
if (deleteLen > 0) {
|
||
op = { delete: deleteLen };
|
||
}
|
||
deleteLen = 0;
|
||
break;
|
||
case "insert":
|
||
if (typeof insert === "object" || insert.length > 0) {
|
||
op = { insert };
|
||
if (currentAttributes.size > 0) {
|
||
op.attributes = {};
|
||
currentAttributes.forEach((value, key) => {
|
||
if (value !== null) {
|
||
op.attributes[key] = value;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
insert = "";
|
||
break;
|
||
case "retain":
|
||
if (retain > 0) {
|
||
op = { retain };
|
||
if (!isEmpty(attributes)) {
|
||
op.attributes = assign({}, attributes);
|
||
}
|
||
}
|
||
retain = 0;
|
||
break;
|
||
}
|
||
if (op) delta.push(op);
|
||
action = null;
|
||
}
|
||
};
|
||
while (item !== null) {
|
||
switch (item.content.constructor) {
|
||
case ContentType:
|
||
case ContentEmbed:
|
||
if (this.adds(item)) {
|
||
if (!this.deletes(item)) {
|
||
addOp();
|
||
action = "insert";
|
||
insert = item.content.getContent()[0];
|
||
addOp();
|
||
}
|
||
} else if (this.deletes(item)) {
|
||
if (action !== "delete") {
|
||
addOp();
|
||
action = "delete";
|
||
}
|
||
deleteLen += 1;
|
||
} else if (!item.deleted) {
|
||
if (action !== "retain") {
|
||
addOp();
|
||
action = "retain";
|
||
}
|
||
retain += 1;
|
||
}
|
||
break;
|
||
case ContentString:
|
||
if (this.adds(item)) {
|
||
if (!this.deletes(item)) {
|
||
if (action !== "insert") {
|
||
addOp();
|
||
action = "insert";
|
||
}
|
||
insert += /** @type {ContentString} */
|
||
item.content.str;
|
||
}
|
||
} else if (this.deletes(item)) {
|
||
if (action !== "delete") {
|
||
addOp();
|
||
action = "delete";
|
||
}
|
||
deleteLen += item.length;
|
||
} else if (!item.deleted) {
|
||
if (action !== "retain") {
|
||
addOp();
|
||
action = "retain";
|
||
}
|
||
retain += item.length;
|
||
}
|
||
break;
|
||
case ContentFormat: {
|
||
const { key, value } = (
|
||
/** @type {ContentFormat} */
|
||
item.content
|
||
);
|
||
if (this.adds(item)) {
|
||
if (!this.deletes(item)) {
|
||
const curVal = currentAttributes.get(key) ?? null;
|
||
if (!equalAttrs(curVal, value)) {
|
||
if (action === "retain") {
|
||
addOp();
|
||
}
|
||
if (equalAttrs(value, oldAttributes.get(key) ?? null)) {
|
||
delete attributes[key];
|
||
} else {
|
||
attributes[key] = value;
|
||
}
|
||
} else if (value !== null) {
|
||
item.delete(transaction);
|
||
}
|
||
}
|
||
} else if (this.deletes(item)) {
|
||
oldAttributes.set(key, value);
|
||
const curVal = currentAttributes.get(key) ?? null;
|
||
if (!equalAttrs(curVal, value)) {
|
||
if (action === "retain") {
|
||
addOp();
|
||
}
|
||
attributes[key] = curVal;
|
||
}
|
||
} else if (!item.deleted) {
|
||
oldAttributes.set(key, value);
|
||
const attr = attributes[key];
|
||
if (attr !== void 0) {
|
||
if (!equalAttrs(attr, value)) {
|
||
if (action === "retain") {
|
||
addOp();
|
||
}
|
||
if (value === null) {
|
||
delete attributes[key];
|
||
} else {
|
||
attributes[key] = value;
|
||
}
|
||
} else if (attr !== null) {
|
||
item.delete(transaction);
|
||
}
|
||
}
|
||
}
|
||
if (!item.deleted) {
|
||
if (action === "insert") {
|
||
addOp();
|
||
}
|
||
updateCurrentAttributes(
|
||
currentAttributes,
|
||
/** @type {ContentFormat} */
|
||
item.content
|
||
);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
item = item.right;
|
||
}
|
||
addOp();
|
||
while (delta.length > 0) {
|
||
const lastOp = delta[delta.length - 1];
|
||
if (lastOp.retain !== void 0 && lastOp.attributes === void 0) {
|
||
delta.pop();
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
});
|
||
this._delta = delta;
|
||
}
|
||
return (
|
||
/** @type {any} */
|
||
this._delta
|
||
);
|
||
}
|
||
};
|
||
var YText = class _YText extends AbstractType {
|
||
/**
|
||
* @param {String} [string] The initial value of the YText.
|
||
*/
|
||
constructor(string) {
|
||
super();
|
||
this._pending = string !== void 0 ? [() => this.insert(0, string)] : [];
|
||
this._searchMarker = [];
|
||
this._hasFormatting = false;
|
||
}
|
||
/**
|
||
* Number of characters of this text type.
|
||
*
|
||
* @type {number}
|
||
*/
|
||
get length() {
|
||
this.doc ?? warnPrematureAccess();
|
||
return this._length;
|
||
}
|
||
/**
|
||
* @param {Doc} y
|
||
* @param {Item} item
|
||
*/
|
||
_integrate(y, item) {
|
||
super._integrate(y, item);
|
||
try {
|
||
this._pending.forEach((f) => f());
|
||
} catch (e) {
|
||
console.error(e);
|
||
}
|
||
this._pending = null;
|
||
}
|
||
_copy() {
|
||
return new _YText();
|
||
}
|
||
/**
|
||
* Makes a copy of this data type that can be included somewhere else.
|
||
*
|
||
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||
*
|
||
* @return {YText}
|
||
*/
|
||
clone() {
|
||
const text2 = new _YText();
|
||
text2.applyDelta(this.toDelta());
|
||
return text2;
|
||
}
|
||
/**
|
||
* Creates YTextEvent and calls observers.
|
||
*
|
||
* @param {Transaction} transaction
|
||
* @param {Set<null|string>} parentSubs Keys changed on this type. `null` if list was modified.
|
||
*/
|
||
_callObserver(transaction, parentSubs) {
|
||
super._callObserver(transaction, parentSubs);
|
||
const event = new YTextEvent(this, transaction, parentSubs);
|
||
callTypeObservers(this, transaction, event);
|
||
if (!transaction.local && this._hasFormatting) {
|
||
transaction._needFormattingCleanup = true;
|
||
}
|
||
}
|
||
/**
|
||
* Returns the unformatted string representation of this YText type.
|
||
*
|
||
* @public
|
||
*/
|
||
toString() {
|
||
this.doc ?? warnPrematureAccess();
|
||
let str = "";
|
||
let n = this._start;
|
||
while (n !== null) {
|
||
if (!n.deleted && n.countable && n.content.constructor === ContentString) {
|
||
str += /** @type {ContentString} */
|
||
n.content.str;
|
||
}
|
||
n = n.right;
|
||
}
|
||
return str;
|
||
}
|
||
/**
|
||
* Returns the unformatted string representation of this YText type.
|
||
*
|
||
* @return {string}
|
||
* @public
|
||
*/
|
||
toJSON() {
|
||
return this.toString();
|
||
}
|
||
/**
|
||
* Apply a {@link Delta} on this shared YText type.
|
||
*
|
||
* @param {Array<any>} delta The changes to apply on this element.
|
||
* @param {object} opts
|
||
* @param {boolean} [opts.sanitize] Sanitize input delta. Removes ending newlines if set to true.
|
||
*
|
||
*
|
||
* @public
|
||
*/
|
||
applyDelta(delta, { sanitize = true } = {}) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
const currPos = new ItemTextListPosition(null, this._start, 0, /* @__PURE__ */ new Map());
|
||
for (let i = 0; i < delta.length; i++) {
|
||
const op = delta[i];
|
||
if (op.insert !== void 0) {
|
||
const ins = !sanitize && typeof op.insert === "string" && i === delta.length - 1 && currPos.right === null && op.insert.slice(-1) === "\n" ? op.insert.slice(0, -1) : op.insert;
|
||
if (typeof ins !== "string" || ins.length > 0) {
|
||
insertText(transaction, this, currPos, ins, op.attributes || {});
|
||
}
|
||
} else if (op.retain !== void 0) {
|
||
formatText(transaction, this, currPos, op.retain, op.attributes || {});
|
||
} else if (op.delete !== void 0) {
|
||
deleteText(transaction, currPos, op.delete);
|
||
}
|
||
}
|
||
});
|
||
} else {
|
||
this._pending.push(() => this.applyDelta(delta));
|
||
}
|
||
}
|
||
/**
|
||
* Returns the Delta representation of this YText type.
|
||
*
|
||
* @param {Snapshot} [snapshot]
|
||
* @param {Snapshot} [prevSnapshot]
|
||
* @param {function('removed' | 'added', ID):any} [computeYChange]
|
||
* @return {any} The Delta representation of this type.
|
||
*
|
||
* @public
|
||
*/
|
||
toDelta(snapshot2, prevSnapshot, computeYChange) {
|
||
this.doc ?? warnPrematureAccess();
|
||
const ops = [];
|
||
const currentAttributes = /* @__PURE__ */ new Map();
|
||
const doc2 = (
|
||
/** @type {Doc} */
|
||
this.doc
|
||
);
|
||
let str = "";
|
||
let n = this._start;
|
||
function packStr() {
|
||
if (str.length > 0) {
|
||
const attributes = {};
|
||
let addAttributes = false;
|
||
currentAttributes.forEach((value, key) => {
|
||
addAttributes = true;
|
||
attributes[key] = value;
|
||
});
|
||
const op = { insert: str };
|
||
if (addAttributes) {
|
||
op.attributes = attributes;
|
||
}
|
||
ops.push(op);
|
||
str = "";
|
||
}
|
||
}
|
||
const computeDelta = () => {
|
||
while (n !== null) {
|
||
if (isVisible(n, snapshot2) || prevSnapshot !== void 0 && isVisible(n, prevSnapshot)) {
|
||
switch (n.content.constructor) {
|
||
case ContentString: {
|
||
const cur = currentAttributes.get("ychange");
|
||
if (snapshot2 !== void 0 && !isVisible(n, snapshot2)) {
|
||
if (cur === void 0 || cur.user !== n.id.client || cur.type !== "removed") {
|
||
packStr();
|
||
currentAttributes.set("ychange", computeYChange ? computeYChange("removed", n.id) : { type: "removed" });
|
||
}
|
||
} else if (prevSnapshot !== void 0 && !isVisible(n, prevSnapshot)) {
|
||
if (cur === void 0 || cur.user !== n.id.client || cur.type !== "added") {
|
||
packStr();
|
||
currentAttributes.set("ychange", computeYChange ? computeYChange("added", n.id) : { type: "added" });
|
||
}
|
||
} else if (cur !== void 0) {
|
||
packStr();
|
||
currentAttributes.delete("ychange");
|
||
}
|
||
str += /** @type {ContentString} */
|
||
n.content.str;
|
||
break;
|
||
}
|
||
case ContentType:
|
||
case ContentEmbed: {
|
||
packStr();
|
||
const op = {
|
||
insert: n.content.getContent()[0]
|
||
};
|
||
if (currentAttributes.size > 0) {
|
||
const attrs = (
|
||
/** @type {Object<string,any>} */
|
||
{}
|
||
);
|
||
op.attributes = attrs;
|
||
currentAttributes.forEach((value, key) => {
|
||
attrs[key] = value;
|
||
});
|
||
}
|
||
ops.push(op);
|
||
break;
|
||
}
|
||
case ContentFormat:
|
||
if (isVisible(n, snapshot2)) {
|
||
packStr();
|
||
updateCurrentAttributes(
|
||
currentAttributes,
|
||
/** @type {ContentFormat} */
|
||
n.content
|
||
);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
n = n.right;
|
||
}
|
||
packStr();
|
||
};
|
||
if (snapshot2 || prevSnapshot) {
|
||
transact(doc2, (transaction) => {
|
||
if (snapshot2) {
|
||
splitSnapshotAffectedStructs(transaction, snapshot2);
|
||
}
|
||
if (prevSnapshot) {
|
||
splitSnapshotAffectedStructs(transaction, prevSnapshot);
|
||
}
|
||
computeDelta();
|
||
}, "cleanup");
|
||
} else {
|
||
computeDelta();
|
||
}
|
||
return ops;
|
||
}
|
||
/**
|
||
* Insert text at a given index.
|
||
*
|
||
* @param {number} index The index at which to start inserting.
|
||
* @param {String} text The text to insert at the specified position.
|
||
* @param {TextAttributes} [attributes] Optionally define some formatting
|
||
* information to apply on the inserted
|
||
* Text.
|
||
* @public
|
||
*/
|
||
insert(index, text2, attributes) {
|
||
if (text2.length <= 0) {
|
||
return;
|
||
}
|
||
const y = this.doc;
|
||
if (y !== null) {
|
||
transact(y, (transaction) => {
|
||
const pos = findPosition(transaction, this, index, !attributes);
|
||
if (!attributes) {
|
||
attributes = {};
|
||
pos.currentAttributes.forEach((v, k) => {
|
||
attributes[k] = v;
|
||
});
|
||
}
|
||
insertText(transaction, this, pos, text2, attributes);
|
||
});
|
||
} else {
|
||
this._pending.push(() => this.insert(index, text2, attributes));
|
||
}
|
||
}
|
||
/**
|
||
* Inserts an embed at a index.
|
||
*
|
||
* @param {number} index The index to insert the embed at.
|
||
* @param {Object | AbstractType<any>} embed The Object that represents the embed.
|
||
* @param {TextAttributes} [attributes] Attribute information to apply on the
|
||
* embed
|
||
*
|
||
* @public
|
||
*/
|
||
insertEmbed(index, embed, attributes) {
|
||
const y = this.doc;
|
||
if (y !== null) {
|
||
transact(y, (transaction) => {
|
||
const pos = findPosition(transaction, this, index, !attributes);
|
||
insertText(transaction, this, pos, embed, attributes || {});
|
||
});
|
||
} else {
|
||
this._pending.push(() => this.insertEmbed(index, embed, attributes || {}));
|
||
}
|
||
}
|
||
/**
|
||
* Deletes text starting from an index.
|
||
*
|
||
* @param {number} index Index at which to start deleting.
|
||
* @param {number} length The number of characters to remove. Defaults to 1.
|
||
*
|
||
* @public
|
||
*/
|
||
delete(index, length2) {
|
||
if (length2 === 0) {
|
||
return;
|
||
}
|
||
const y = this.doc;
|
||
if (y !== null) {
|
||
transact(y, (transaction) => {
|
||
deleteText(transaction, findPosition(transaction, this, index, true), length2);
|
||
});
|
||
} else {
|
||
this._pending.push(() => this.delete(index, length2));
|
||
}
|
||
}
|
||
/**
|
||
* Assigns properties to a range of text.
|
||
*
|
||
* @param {number} index The position where to start formatting.
|
||
* @param {number} length The amount of characters to assign properties to.
|
||
* @param {TextAttributes} attributes Attribute information to apply on the
|
||
* text.
|
||
*
|
||
* @public
|
||
*/
|
||
format(index, length2, attributes) {
|
||
if (length2 === 0) {
|
||
return;
|
||
}
|
||
const y = this.doc;
|
||
if (y !== null) {
|
||
transact(y, (transaction) => {
|
||
const pos = findPosition(transaction, this, index, false);
|
||
if (pos.right === null) {
|
||
return;
|
||
}
|
||
formatText(transaction, this, pos, length2, attributes);
|
||
});
|
||
} else {
|
||
this._pending.push(() => this.format(index, length2, attributes));
|
||
}
|
||
}
|
||
/**
|
||
* Removes an attribute.
|
||
*
|
||
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
|
||
*
|
||
* @param {String} attributeName The attribute name that is to be removed.
|
||
*
|
||
* @public
|
||
*/
|
||
removeAttribute(attributeName) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeMapDelete(transaction, this, attributeName);
|
||
});
|
||
} else {
|
||
this._pending.push(() => this.removeAttribute(attributeName));
|
||
}
|
||
}
|
||
/**
|
||
* Sets or updates an attribute.
|
||
*
|
||
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
|
||
*
|
||
* @param {String} attributeName The attribute name that is to be set.
|
||
* @param {any} attributeValue The attribute value that is to be set.
|
||
*
|
||
* @public
|
||
*/
|
||
setAttribute(attributeName, attributeValue) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeMapSet(transaction, this, attributeName, attributeValue);
|
||
});
|
||
} else {
|
||
this._pending.push(() => this.setAttribute(attributeName, attributeValue));
|
||
}
|
||
}
|
||
/**
|
||
* Returns an attribute value that belongs to the attribute name.
|
||
*
|
||
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
|
||
*
|
||
* @param {String} attributeName The attribute name that identifies the
|
||
* queried value.
|
||
* @return {any} The queried attribute value.
|
||
*
|
||
* @public
|
||
*/
|
||
getAttribute(attributeName) {
|
||
return (
|
||
/** @type {any} */
|
||
typeMapGet(this, attributeName)
|
||
);
|
||
}
|
||
/**
|
||
* Returns all attribute name/value pairs in a JSON Object.
|
||
*
|
||
* @note Xml-Text nodes don't have attributes. You can use this feature to assign properties to complete text-blocks.
|
||
*
|
||
* @return {Object<string, any>} A JSON Object that describes the attributes.
|
||
*
|
||
* @public
|
||
*/
|
||
getAttributes() {
|
||
return typeMapGetAll(this);
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
*/
|
||
_write(encoder) {
|
||
encoder.writeTypeRef(YTextRefID);
|
||
}
|
||
};
|
||
var readYText = (_decoder) => new YText();
|
||
var YXmlTreeWalker = class {
|
||
/**
|
||
* @param {YXmlFragment | YXmlElement} root
|
||
* @param {function(AbstractType<any>):boolean} [f]
|
||
*/
|
||
constructor(root, f = () => true) {
|
||
this._filter = f;
|
||
this._root = root;
|
||
this._currentNode = /** @type {Item} */
|
||
root._start;
|
||
this._firstCall = true;
|
||
root.doc ?? warnPrematureAccess();
|
||
}
|
||
[Symbol.iterator]() {
|
||
return this;
|
||
}
|
||
/**
|
||
* Get the next node.
|
||
*
|
||
* @return {IteratorResult<YXmlElement|YXmlText|YXmlHook>} The next node.
|
||
*
|
||
* @public
|
||
*/
|
||
next() {
|
||
let n = this._currentNode;
|
||
let type = n && n.content && /** @type {any} */
|
||
n.content.type;
|
||
if (n !== null && (!this._firstCall || n.deleted || !this._filter(type))) {
|
||
do {
|
||
type = /** @type {any} */
|
||
n.content.type;
|
||
if (!n.deleted && (type.constructor === YXmlElement || type.constructor === YXmlFragment) && type._start !== null) {
|
||
n = type._start;
|
||
} else {
|
||
while (n !== null) {
|
||
const nxt = n.next;
|
||
if (nxt !== null) {
|
||
n = nxt;
|
||
break;
|
||
} else if (n.parent === this._root) {
|
||
n = null;
|
||
} else {
|
||
n = /** @type {AbstractType<any>} */
|
||
n.parent._item;
|
||
}
|
||
}
|
||
}
|
||
} while (n !== null && (n.deleted || !this._filter(
|
||
/** @type {ContentType} */
|
||
n.content.type
|
||
)));
|
||
}
|
||
this._firstCall = false;
|
||
if (n === null) {
|
||
return { value: void 0, done: true };
|
||
}
|
||
this._currentNode = n;
|
||
return { value: (
|
||
/** @type {any} */
|
||
n.content.type
|
||
), done: false };
|
||
}
|
||
};
|
||
var YXmlFragment = class _YXmlFragment extends AbstractType {
|
||
constructor() {
|
||
super();
|
||
this._prelimContent = [];
|
||
}
|
||
/**
|
||
* @type {YXmlElement|YXmlText|null}
|
||
*/
|
||
get firstChild() {
|
||
const first = this._first;
|
||
return first ? first.content.getContent()[0] : null;
|
||
}
|
||
/**
|
||
* Integrate this type into the Yjs instance.
|
||
*
|
||
* * Save this struct in the os
|
||
* * This type is sent to other client
|
||
* * Observer functions are fired
|
||
*
|
||
* @param {Doc} y The Yjs instance
|
||
* @param {Item} item
|
||
*/
|
||
_integrate(y, item) {
|
||
super._integrate(y, item);
|
||
this.insert(
|
||
0,
|
||
/** @type {Array<any>} */
|
||
this._prelimContent
|
||
);
|
||
this._prelimContent = null;
|
||
}
|
||
_copy() {
|
||
return new _YXmlFragment();
|
||
}
|
||
/**
|
||
* Makes a copy of this data type that can be included somewhere else.
|
||
*
|
||
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||
*
|
||
* @return {YXmlFragment}
|
||
*/
|
||
clone() {
|
||
const el = new _YXmlFragment();
|
||
el.insert(0, this.toArray().map((item) => item instanceof AbstractType ? item.clone() : item));
|
||
return el;
|
||
}
|
||
get length() {
|
||
this.doc ?? warnPrematureAccess();
|
||
return this._prelimContent === null ? this._length : this._prelimContent.length;
|
||
}
|
||
/**
|
||
* Create a subtree of childNodes.
|
||
*
|
||
* @example
|
||
* const walker = elem.createTreeWalker(dom => dom.nodeName === 'div')
|
||
* for (let node in walker) {
|
||
* // `node` is a div node
|
||
* nop(node)
|
||
* }
|
||
*
|
||
* @param {function(AbstractType<any>):boolean} filter Function that is called on each child element and
|
||
* returns a Boolean indicating whether the child
|
||
* is to be included in the subtree.
|
||
* @return {YXmlTreeWalker} A subtree and a position within it.
|
||
*
|
||
* @public
|
||
*/
|
||
createTreeWalker(filter) {
|
||
return new YXmlTreeWalker(this, filter);
|
||
}
|
||
/**
|
||
* Returns the first YXmlElement that matches the query.
|
||
* Similar to DOM's {@link querySelector}.
|
||
*
|
||
* Query support:
|
||
* - tagname
|
||
* TODO:
|
||
* - id
|
||
* - attribute
|
||
*
|
||
* @param {CSS_Selector} query The query on the children.
|
||
* @return {YXmlElement|YXmlText|YXmlHook|null} The first element that matches the query or null.
|
||
*
|
||
* @public
|
||
*/
|
||
querySelector(query) {
|
||
query = query.toUpperCase();
|
||
const iterator = new YXmlTreeWalker(this, (element2) => element2.nodeName && element2.nodeName.toUpperCase() === query);
|
||
const next = iterator.next();
|
||
if (next.done) {
|
||
return null;
|
||
} else {
|
||
return next.value;
|
||
}
|
||
}
|
||
/**
|
||
* Returns all YXmlElements that match the query.
|
||
* Similar to Dom's {@link querySelectorAll}.
|
||
*
|
||
* @todo Does not yet support all queries. Currently only query by tagName.
|
||
*
|
||
* @param {CSS_Selector} query The query on the children
|
||
* @return {Array<YXmlElement|YXmlText|YXmlHook|null>} The elements that match this query.
|
||
*
|
||
* @public
|
||
*/
|
||
querySelectorAll(query) {
|
||
query = query.toUpperCase();
|
||
return from2(new YXmlTreeWalker(this, (element2) => element2.nodeName && element2.nodeName.toUpperCase() === query));
|
||
}
|
||
/**
|
||
* Creates YXmlEvent and calls observers.
|
||
*
|
||
* @param {Transaction} transaction
|
||
* @param {Set<null|string>} parentSubs Keys changed on this type. `null` if list was modified.
|
||
*/
|
||
_callObserver(transaction, parentSubs) {
|
||
callTypeObservers(this, transaction, new YXmlEvent(this, parentSubs, transaction));
|
||
}
|
||
/**
|
||
* Get the string representation of all the children of this YXmlFragment.
|
||
*
|
||
* @return {string} The string representation of all children.
|
||
*/
|
||
toString() {
|
||
return typeListMap(this, (xml) => xml.toString()).join("");
|
||
}
|
||
/**
|
||
* @return {string}
|
||
*/
|
||
toJSON() {
|
||
return this.toString();
|
||
}
|
||
/**
|
||
* Creates a Dom Element that mirrors this YXmlElement.
|
||
*
|
||
* @param {Document} [_document=document] The document object (you must define
|
||
* this when calling this method in
|
||
* nodejs)
|
||
* @param {Object<string, any>} [hooks={}] Optional property to customize how hooks
|
||
* are presented in the DOM
|
||
* @param {any} [binding] You should not set this property. This is
|
||
* used if DomBinding wants to create a
|
||
* association to the created DOM type.
|
||
* @return {Node} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
||
*
|
||
* @public
|
||
*/
|
||
toDOM(_document = document, hooks = {}, binding) {
|
||
const fragment = _document.createDocumentFragment();
|
||
if (binding !== void 0) {
|
||
binding._createAssociation(fragment, this);
|
||
}
|
||
typeListForEach(this, (xmlType) => {
|
||
fragment.insertBefore(xmlType.toDOM(_document, hooks, binding), null);
|
||
});
|
||
return fragment;
|
||
}
|
||
/**
|
||
* Inserts new content at an index.
|
||
*
|
||
* @example
|
||
* // Insert character 'a' at position 0
|
||
* xml.insert(0, [new Y.XmlText('text')])
|
||
*
|
||
* @param {number} index The index to insert content at
|
||
* @param {Array<YXmlElement|YXmlText>} content The array of content
|
||
*/
|
||
insert(index, content) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeListInsertGenerics(transaction, this, index, content);
|
||
});
|
||
} else {
|
||
this._prelimContent.splice(index, 0, ...content);
|
||
}
|
||
}
|
||
/**
|
||
* Inserts new content at an index.
|
||
*
|
||
* @example
|
||
* // Insert character 'a' at position 0
|
||
* xml.insert(0, [new Y.XmlText('text')])
|
||
*
|
||
* @param {null|Item|YXmlElement|YXmlText} ref The index to insert content at
|
||
* @param {Array<YXmlElement|YXmlText>} content The array of content
|
||
*/
|
||
insertAfter(ref, content) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
const refItem = ref && ref instanceof AbstractType ? ref._item : ref;
|
||
typeListInsertGenericsAfter(transaction, this, refItem, content);
|
||
});
|
||
} else {
|
||
const pc = (
|
||
/** @type {Array<any>} */
|
||
this._prelimContent
|
||
);
|
||
const index = ref === null ? 0 : pc.findIndex((el) => el === ref) + 1;
|
||
if (index === 0 && ref !== null) {
|
||
throw create3("Reference item not found");
|
||
}
|
||
pc.splice(index, 0, ...content);
|
||
}
|
||
}
|
||
/**
|
||
* Deletes elements starting from an index.
|
||
*
|
||
* @param {number} index Index at which to start deleting elements
|
||
* @param {number} [length=1] The number of elements to remove. Defaults to 1.
|
||
*/
|
||
delete(index, length2 = 1) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeListDelete(transaction, this, index, length2);
|
||
});
|
||
} else {
|
||
this._prelimContent.splice(index, length2);
|
||
}
|
||
}
|
||
/**
|
||
* Transforms this YArray to a JavaScript Array.
|
||
*
|
||
* @return {Array<YXmlElement|YXmlText|YXmlHook>}
|
||
*/
|
||
toArray() {
|
||
return typeListToArray(this);
|
||
}
|
||
/**
|
||
* Appends content to this YArray.
|
||
*
|
||
* @param {Array<YXmlElement|YXmlText>} content Array of content to append.
|
||
*/
|
||
push(content) {
|
||
this.insert(this.length, content);
|
||
}
|
||
/**
|
||
* Prepends content to this YArray.
|
||
*
|
||
* @param {Array<YXmlElement|YXmlText>} content Array of content to prepend.
|
||
*/
|
||
unshift(content) {
|
||
this.insert(0, content);
|
||
}
|
||
/**
|
||
* Returns the i-th element from a YArray.
|
||
*
|
||
* @param {number} index The index of the element to return from the YArray
|
||
* @return {YXmlElement|YXmlText}
|
||
*/
|
||
get(index) {
|
||
return typeListGet(this, index);
|
||
}
|
||
/**
|
||
* Returns a portion of this YXmlFragment into a JavaScript Array selected
|
||
* from start to end (end not included).
|
||
*
|
||
* @param {number} [start]
|
||
* @param {number} [end]
|
||
* @return {Array<YXmlElement|YXmlText>}
|
||
*/
|
||
slice(start = 0, end = this.length) {
|
||
return typeListSlice(this, start, end);
|
||
}
|
||
/**
|
||
* Executes a provided function on once on every child element.
|
||
*
|
||
* @param {function(YXmlElement|YXmlText,number, typeof self):void} f A function to execute on every element of this YArray.
|
||
*/
|
||
forEach(f) {
|
||
typeListForEach(this, f);
|
||
}
|
||
/**
|
||
* Transform the properties of this type to binary and write it to an
|
||
* BinaryEncoder.
|
||
*
|
||
* This is called when this Item is sent to a remote peer.
|
||
*
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to.
|
||
*/
|
||
_write(encoder) {
|
||
encoder.writeTypeRef(YXmlFragmentRefID);
|
||
}
|
||
};
|
||
var readYXmlFragment = (_decoder) => new YXmlFragment();
|
||
var YXmlElement = class _YXmlElement extends YXmlFragment {
|
||
constructor(nodeName = "UNDEFINED") {
|
||
super();
|
||
this.nodeName = nodeName;
|
||
this._prelimAttrs = /* @__PURE__ */ new Map();
|
||
}
|
||
/**
|
||
* @type {YXmlElement|YXmlText|null}
|
||
*/
|
||
get nextSibling() {
|
||
const n = this._item ? this._item.next : null;
|
||
return n ? (
|
||
/** @type {YXmlElement|YXmlText} */
|
||
/** @type {ContentType} */
|
||
n.content.type
|
||
) : null;
|
||
}
|
||
/**
|
||
* @type {YXmlElement|YXmlText|null}
|
||
*/
|
||
get prevSibling() {
|
||
const n = this._item ? this._item.prev : null;
|
||
return n ? (
|
||
/** @type {YXmlElement|YXmlText} */
|
||
/** @type {ContentType} */
|
||
n.content.type
|
||
) : null;
|
||
}
|
||
/**
|
||
* Integrate this type into the Yjs instance.
|
||
*
|
||
* * Save this struct in the os
|
||
* * This type is sent to other client
|
||
* * Observer functions are fired
|
||
*
|
||
* @param {Doc} y The Yjs instance
|
||
* @param {Item} item
|
||
*/
|
||
_integrate(y, item) {
|
||
super._integrate(y, item);
|
||
/** @type {Map<string, any>} */
|
||
this._prelimAttrs.forEach((value, key) => {
|
||
this.setAttribute(key, value);
|
||
});
|
||
this._prelimAttrs = null;
|
||
}
|
||
/**
|
||
* Creates an Item with the same effect as this Item (without position effect)
|
||
*
|
||
* @return {YXmlElement}
|
||
*/
|
||
_copy() {
|
||
return new _YXmlElement(this.nodeName);
|
||
}
|
||
/**
|
||
* Makes a copy of this data type that can be included somewhere else.
|
||
*
|
||
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||
*
|
||
* @return {YXmlElement<KV>}
|
||
*/
|
||
clone() {
|
||
const el = new _YXmlElement(this.nodeName);
|
||
const attrs = this.getAttributes();
|
||
forEach(attrs, (value, key) => {
|
||
el.setAttribute(
|
||
key,
|
||
/** @type {any} */
|
||
value
|
||
);
|
||
});
|
||
el.insert(0, this.toArray().map((v) => v instanceof AbstractType ? v.clone() : v));
|
||
return el;
|
||
}
|
||
/**
|
||
* Returns the XML serialization of this YXmlElement.
|
||
* The attributes are ordered by attribute-name, so you can easily use this
|
||
* method to compare YXmlElements
|
||
*
|
||
* @return {string} The string representation of this type.
|
||
*
|
||
* @public
|
||
*/
|
||
toString() {
|
||
const attrs = this.getAttributes();
|
||
const stringBuilder = [];
|
||
const keys2 = [];
|
||
for (const key in attrs) {
|
||
keys2.push(key);
|
||
}
|
||
keys2.sort();
|
||
const keysLen = keys2.length;
|
||
for (let i = 0; i < keysLen; i++) {
|
||
const key = keys2[i];
|
||
stringBuilder.push(key + '="' + attrs[key] + '"');
|
||
}
|
||
const nodeName = this.nodeName.toLocaleLowerCase();
|
||
const attrsString = stringBuilder.length > 0 ? " " + stringBuilder.join(" ") : "";
|
||
return `<${nodeName}${attrsString}>${super.toString()}</${nodeName}>`;
|
||
}
|
||
/**
|
||
* Removes an attribute from this YXmlElement.
|
||
*
|
||
* @param {string} attributeName The attribute name that is to be removed.
|
||
*
|
||
* @public
|
||
*/
|
||
removeAttribute(attributeName) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeMapDelete(transaction, this, attributeName);
|
||
});
|
||
} else {
|
||
this._prelimAttrs.delete(attributeName);
|
||
}
|
||
}
|
||
/**
|
||
* Sets or updates an attribute.
|
||
*
|
||
* @template {keyof KV & string} KEY
|
||
*
|
||
* @param {KEY} attributeName The attribute name that is to be set.
|
||
* @param {KV[KEY]} attributeValue The attribute value that is to be set.
|
||
*
|
||
* @public
|
||
*/
|
||
setAttribute(attributeName, attributeValue) {
|
||
if (this.doc !== null) {
|
||
transact(this.doc, (transaction) => {
|
||
typeMapSet(transaction, this, attributeName, attributeValue);
|
||
});
|
||
} else {
|
||
this._prelimAttrs.set(attributeName, attributeValue);
|
||
}
|
||
}
|
||
/**
|
||
* Returns an attribute value that belongs to the attribute name.
|
||
*
|
||
* @template {keyof KV & string} KEY
|
||
*
|
||
* @param {KEY} attributeName The attribute name that identifies the
|
||
* queried value.
|
||
* @return {KV[KEY]|undefined} The queried attribute value.
|
||
*
|
||
* @public
|
||
*/
|
||
getAttribute(attributeName) {
|
||
return (
|
||
/** @type {any} */
|
||
typeMapGet(this, attributeName)
|
||
);
|
||
}
|
||
/**
|
||
* Returns whether an attribute exists
|
||
*
|
||
* @param {string} attributeName The attribute name to check for existence.
|
||
* @return {boolean} whether the attribute exists.
|
||
*
|
||
* @public
|
||
*/
|
||
hasAttribute(attributeName) {
|
||
return (
|
||
/** @type {any} */
|
||
typeMapHas(this, attributeName)
|
||
);
|
||
}
|
||
/**
|
||
* Returns all attribute name/value pairs in a JSON Object.
|
||
*
|
||
* @param {Snapshot} [snapshot]
|
||
* @return {{ [Key in Extract<keyof KV,string>]?: KV[Key]}} A JSON Object that describes the attributes.
|
||
*
|
||
* @public
|
||
*/
|
||
getAttributes(snapshot2) {
|
||
return (
|
||
/** @type {any} */
|
||
snapshot2 ? typeMapGetAllSnapshot(this, snapshot2) : typeMapGetAll(this)
|
||
);
|
||
}
|
||
/**
|
||
* Creates a Dom Element that mirrors this YXmlElement.
|
||
*
|
||
* @param {Document} [_document=document] The document object (you must define
|
||
* this when calling this method in
|
||
* nodejs)
|
||
* @param {Object<string, any>} [hooks={}] Optional property to customize how hooks
|
||
* are presented in the DOM
|
||
* @param {any} [binding] You should not set this property. This is
|
||
* used if DomBinding wants to create a
|
||
* association to the created DOM type.
|
||
* @return {Node} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
||
*
|
||
* @public
|
||
*/
|
||
toDOM(_document = document, hooks = {}, binding) {
|
||
const dom = _document.createElement(this.nodeName);
|
||
const attrs = this.getAttributes();
|
||
for (const key in attrs) {
|
||
const value = attrs[key];
|
||
if (typeof value === "string") {
|
||
dom.setAttribute(key, value);
|
||
}
|
||
}
|
||
typeListForEach(this, (yxml) => {
|
||
dom.appendChild(yxml.toDOM(_document, hooks, binding));
|
||
});
|
||
if (binding !== void 0) {
|
||
binding._createAssociation(dom, this);
|
||
}
|
||
return dom;
|
||
}
|
||
/**
|
||
* Transform the properties of this type to binary and write it to an
|
||
* BinaryEncoder.
|
||
*
|
||
* This is called when this Item is sent to a remote peer.
|
||
*
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to.
|
||
*/
|
||
_write(encoder) {
|
||
encoder.writeTypeRef(YXmlElementRefID);
|
||
encoder.writeKey(this.nodeName);
|
||
}
|
||
};
|
||
var readYXmlElement = (decoder) => new YXmlElement(decoder.readKey());
|
||
var YXmlEvent = class extends YEvent {
|
||
/**
|
||
* @param {YXmlElement|YXmlText|YXmlFragment} target The target on which the event is created.
|
||
* @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
|
||
* child list changed.
|
||
* @param {Transaction} transaction The transaction instance with which the
|
||
* change was created.
|
||
*/
|
||
constructor(target, subs, transaction) {
|
||
super(target, transaction);
|
||
this.childListChanged = false;
|
||
this.attributesChanged = /* @__PURE__ */ new Set();
|
||
subs.forEach((sub) => {
|
||
if (sub === null) {
|
||
this.childListChanged = true;
|
||
} else {
|
||
this.attributesChanged.add(sub);
|
||
}
|
||
});
|
||
}
|
||
};
|
||
var YXmlHook = class _YXmlHook extends YMap {
|
||
/**
|
||
* @param {string} hookName nodeName of the Dom Node.
|
||
*/
|
||
constructor(hookName) {
|
||
super();
|
||
this.hookName = hookName;
|
||
}
|
||
/**
|
||
* Creates an Item with the same effect as this Item (without position effect)
|
||
*/
|
||
_copy() {
|
||
return new _YXmlHook(this.hookName);
|
||
}
|
||
/**
|
||
* Makes a copy of this data type that can be included somewhere else.
|
||
*
|
||
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||
*
|
||
* @return {YXmlHook}
|
||
*/
|
||
clone() {
|
||
const el = new _YXmlHook(this.hookName);
|
||
this.forEach((value, key) => {
|
||
el.set(key, value);
|
||
});
|
||
return el;
|
||
}
|
||
/**
|
||
* Creates a Dom Element that mirrors this YXmlElement.
|
||
*
|
||
* @param {Document} [_document=document] The document object (you must define
|
||
* this when calling this method in
|
||
* nodejs)
|
||
* @param {Object.<string, any>} [hooks] Optional property to customize how hooks
|
||
* are presented in the DOM
|
||
* @param {any} [binding] You should not set this property. This is
|
||
* used if DomBinding wants to create a
|
||
* association to the created DOM type
|
||
* @return {Element} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
||
*
|
||
* @public
|
||
*/
|
||
toDOM(_document = document, hooks = {}, binding) {
|
||
const hook = hooks[this.hookName];
|
||
let dom;
|
||
if (hook !== void 0) {
|
||
dom = hook.createDom(this);
|
||
} else {
|
||
dom = document.createElement(this.hookName);
|
||
}
|
||
dom.setAttribute("data-yjs-hook", this.hookName);
|
||
if (binding !== void 0) {
|
||
binding._createAssociation(dom, this);
|
||
}
|
||
return dom;
|
||
}
|
||
/**
|
||
* Transform the properties of this type to binary and write it to an
|
||
* BinaryEncoder.
|
||
*
|
||
* This is called when this Item is sent to a remote peer.
|
||
*
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to.
|
||
*/
|
||
_write(encoder) {
|
||
encoder.writeTypeRef(YXmlHookRefID);
|
||
encoder.writeKey(this.hookName);
|
||
}
|
||
};
|
||
var readYXmlHook = (decoder) => new YXmlHook(decoder.readKey());
|
||
var YXmlText = class _YXmlText extends YText {
|
||
/**
|
||
* @type {YXmlElement|YXmlText|null}
|
||
*/
|
||
get nextSibling() {
|
||
const n = this._item ? this._item.next : null;
|
||
return n ? (
|
||
/** @type {YXmlElement|YXmlText} */
|
||
/** @type {ContentType} */
|
||
n.content.type
|
||
) : null;
|
||
}
|
||
/**
|
||
* @type {YXmlElement|YXmlText|null}
|
||
*/
|
||
get prevSibling() {
|
||
const n = this._item ? this._item.prev : null;
|
||
return n ? (
|
||
/** @type {YXmlElement|YXmlText} */
|
||
/** @type {ContentType} */
|
||
n.content.type
|
||
) : null;
|
||
}
|
||
_copy() {
|
||
return new _YXmlText();
|
||
}
|
||
/**
|
||
* Makes a copy of this data type that can be included somewhere else.
|
||
*
|
||
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||
*
|
||
* @return {YXmlText}
|
||
*/
|
||
clone() {
|
||
const text2 = new _YXmlText();
|
||
text2.applyDelta(this.toDelta());
|
||
return text2;
|
||
}
|
||
/**
|
||
* Creates a Dom Element that mirrors this YXmlText.
|
||
*
|
||
* @param {Document} [_document=document] The document object (you must define
|
||
* this when calling this method in
|
||
* nodejs)
|
||
* @param {Object<string, any>} [hooks] Optional property to customize how hooks
|
||
* are presented in the DOM
|
||
* @param {any} [binding] You should not set this property. This is
|
||
* used if DomBinding wants to create a
|
||
* association to the created DOM type.
|
||
* @return {Text} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
||
*
|
||
* @public
|
||
*/
|
||
toDOM(_document = document, hooks, binding) {
|
||
const dom = _document.createTextNode(this.toString());
|
||
if (binding !== void 0) {
|
||
binding._createAssociation(dom, this);
|
||
}
|
||
return dom;
|
||
}
|
||
toString() {
|
||
return this.toDelta().map((delta) => {
|
||
const nestedNodes = [];
|
||
for (const nodeName in delta.attributes) {
|
||
const attrs = [];
|
||
for (const key in delta.attributes[nodeName]) {
|
||
attrs.push({ key, value: delta.attributes[nodeName][key] });
|
||
}
|
||
attrs.sort((a, b) => a.key < b.key ? -1 : 1);
|
||
nestedNodes.push({ nodeName, attrs });
|
||
}
|
||
nestedNodes.sort((a, b) => a.nodeName < b.nodeName ? -1 : 1);
|
||
let str = "";
|
||
for (let i = 0; i < nestedNodes.length; i++) {
|
||
const node = nestedNodes[i];
|
||
str += `<${node.nodeName}`;
|
||
for (let j = 0; j < node.attrs.length; j++) {
|
||
const attr = node.attrs[j];
|
||
str += ` ${attr.key}="${attr.value}"`;
|
||
}
|
||
str += ">";
|
||
}
|
||
str += delta.insert;
|
||
for (let i = nestedNodes.length - 1; i >= 0; i--) {
|
||
str += `</${nestedNodes[i].nodeName}>`;
|
||
}
|
||
return str;
|
||
}).join("");
|
||
}
|
||
/**
|
||
* @return {string}
|
||
*/
|
||
toJSON() {
|
||
return this.toString();
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
*/
|
||
_write(encoder) {
|
||
encoder.writeTypeRef(YXmlTextRefID);
|
||
}
|
||
};
|
||
var readYXmlText = (decoder) => new YXmlText();
|
||
var AbstractStruct = class {
|
||
/**
|
||
* @param {ID} id
|
||
* @param {number} length
|
||
*/
|
||
constructor(id2, length2) {
|
||
this.id = id2;
|
||
this.length = length2;
|
||
}
|
||
/**
|
||
* @type {boolean}
|
||
*/
|
||
get deleted() {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* Merge this struct with the item to the right.
|
||
* This method is already assuming that `this.id.clock + this.length === this.id.clock`.
|
||
* Also this method does *not* remove right from StructStore!
|
||
* @param {AbstractStruct} right
|
||
* @return {boolean} whether this merged with right
|
||
*/
|
||
mergeWith(right) {
|
||
return false;
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to.
|
||
* @param {number} offset
|
||
* @param {number} encodingRef
|
||
*/
|
||
write(encoder, offset, encodingRef) {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {number} offset
|
||
*/
|
||
integrate(transaction, offset) {
|
||
throw methodUnimplemented();
|
||
}
|
||
};
|
||
var structGCRefNumber = 0;
|
||
var GC = class extends AbstractStruct {
|
||
get deleted() {
|
||
return true;
|
||
}
|
||
delete() {
|
||
}
|
||
/**
|
||
* @param {GC} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
if (this.constructor !== right.constructor) {
|
||
return false;
|
||
}
|
||
this.length += right.length;
|
||
return true;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {number} offset
|
||
*/
|
||
integrate(transaction, offset) {
|
||
if (offset > 0) {
|
||
this.id.clock += offset;
|
||
this.length -= offset;
|
||
}
|
||
addStruct(transaction.doc.store, this);
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
encoder.writeInfo(structGCRefNumber);
|
||
encoder.writeLen(this.length - offset);
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {StructStore} store
|
||
* @return {null | number}
|
||
*/
|
||
getMissing(transaction, store) {
|
||
return null;
|
||
}
|
||
};
|
||
var ContentBinary = class _ContentBinary {
|
||
/**
|
||
* @param {Uint8Array} content
|
||
*/
|
||
constructor(content) {
|
||
this.content = content;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return 1;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return [this.content];
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return true;
|
||
}
|
||
/**
|
||
* @return {ContentBinary}
|
||
*/
|
||
copy() {
|
||
return new _ContentBinary(this.content);
|
||
}
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentBinary}
|
||
*/
|
||
splice(offset) {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* @param {ContentBinary} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
return false;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(transaction, item) {
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
encoder.writeBuf(this.content);
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 3;
|
||
}
|
||
};
|
||
var readContentBinary = (decoder) => new ContentBinary(decoder.readBuf());
|
||
var ContentDeleted = class _ContentDeleted {
|
||
/**
|
||
* @param {number} len
|
||
*/
|
||
constructor(len) {
|
||
this.len = len;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return this.len;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return [];
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return false;
|
||
}
|
||
/**
|
||
* @return {ContentDeleted}
|
||
*/
|
||
copy() {
|
||
return new _ContentDeleted(this.len);
|
||
}
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentDeleted}
|
||
*/
|
||
splice(offset) {
|
||
const right = new _ContentDeleted(this.len - offset);
|
||
this.len = offset;
|
||
return right;
|
||
}
|
||
/**
|
||
* @param {ContentDeleted} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
this.len += right.len;
|
||
return true;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(transaction, item) {
|
||
addToDeleteSet(transaction.deleteSet, item.id.client, item.id.clock, this.len);
|
||
item.markDeleted();
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
encoder.writeLen(this.len - offset);
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 1;
|
||
}
|
||
};
|
||
var readContentDeleted = (decoder) => new ContentDeleted(decoder.readLen());
|
||
var createDocFromOpts = (guid, opts) => new Doc({ guid, ...opts, shouldLoad: opts.shouldLoad || opts.autoLoad || false });
|
||
var ContentDoc = class _ContentDoc {
|
||
/**
|
||
* @param {Doc} doc
|
||
*/
|
||
constructor(doc2) {
|
||
if (doc2._item) {
|
||
console.error("This document was already integrated as a sub-document. You should create a second instance instead with the same guid.");
|
||
}
|
||
this.doc = doc2;
|
||
const opts = {};
|
||
this.opts = opts;
|
||
if (!doc2.gc) {
|
||
opts.gc = false;
|
||
}
|
||
if (doc2.autoLoad) {
|
||
opts.autoLoad = true;
|
||
}
|
||
if (doc2.meta !== null) {
|
||
opts.meta = doc2.meta;
|
||
}
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return 1;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return [this.doc];
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return true;
|
||
}
|
||
/**
|
||
* @return {ContentDoc}
|
||
*/
|
||
copy() {
|
||
return new _ContentDoc(createDocFromOpts(this.doc.guid, this.opts));
|
||
}
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentDoc}
|
||
*/
|
||
splice(offset) {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* @param {ContentDoc} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
return false;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(transaction, item) {
|
||
this.doc._item = item;
|
||
transaction.subdocsAdded.add(this.doc);
|
||
if (this.doc.shouldLoad) {
|
||
transaction.subdocsLoaded.add(this.doc);
|
||
}
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
if (transaction.subdocsAdded.has(this.doc)) {
|
||
transaction.subdocsAdded.delete(this.doc);
|
||
} else {
|
||
transaction.subdocsRemoved.add(this.doc);
|
||
}
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
encoder.writeString(this.doc.guid);
|
||
encoder.writeAny(this.opts);
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 9;
|
||
}
|
||
};
|
||
var readContentDoc = (decoder) => new ContentDoc(createDocFromOpts(decoder.readString(), decoder.readAny()));
|
||
var ContentEmbed = class _ContentEmbed {
|
||
/**
|
||
* @param {Object} embed
|
||
*/
|
||
constructor(embed) {
|
||
this.embed = embed;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return 1;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return [this.embed];
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return true;
|
||
}
|
||
/**
|
||
* @return {ContentEmbed}
|
||
*/
|
||
copy() {
|
||
return new _ContentEmbed(this.embed);
|
||
}
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentEmbed}
|
||
*/
|
||
splice(offset) {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* @param {ContentEmbed} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
return false;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(transaction, item) {
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
encoder.writeJSON(this.embed);
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 5;
|
||
}
|
||
};
|
||
var readContentEmbed = (decoder) => new ContentEmbed(decoder.readJSON());
|
||
var ContentFormat = class _ContentFormat {
|
||
/**
|
||
* @param {string} key
|
||
* @param {Object} value
|
||
*/
|
||
constructor(key, value) {
|
||
this.key = key;
|
||
this.value = value;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return 1;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return [];
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return false;
|
||
}
|
||
/**
|
||
* @return {ContentFormat}
|
||
*/
|
||
copy() {
|
||
return new _ContentFormat(this.key, this.value);
|
||
}
|
||
/**
|
||
* @param {number} _offset
|
||
* @return {ContentFormat}
|
||
*/
|
||
splice(_offset) {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* @param {ContentFormat} _right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(_right) {
|
||
return false;
|
||
}
|
||
/**
|
||
* @param {Transaction} _transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(_transaction, item) {
|
||
const p = (
|
||
/** @type {YText} */
|
||
item.parent
|
||
);
|
||
p._searchMarker = null;
|
||
p._hasFormatting = true;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
encoder.writeKey(this.key);
|
||
encoder.writeJSON(this.value);
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 6;
|
||
}
|
||
};
|
||
var readContentFormat = (decoder) => new ContentFormat(decoder.readKey(), decoder.readJSON());
|
||
var ContentJSON = class _ContentJSON {
|
||
/**
|
||
* @param {Array<any>} arr
|
||
*/
|
||
constructor(arr) {
|
||
this.arr = arr;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return this.arr.length;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return this.arr;
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return true;
|
||
}
|
||
/**
|
||
* @return {ContentJSON}
|
||
*/
|
||
copy() {
|
||
return new _ContentJSON(this.arr);
|
||
}
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentJSON}
|
||
*/
|
||
splice(offset) {
|
||
const right = new _ContentJSON(this.arr.slice(offset));
|
||
this.arr = this.arr.slice(0, offset);
|
||
return right;
|
||
}
|
||
/**
|
||
* @param {ContentJSON} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
this.arr = this.arr.concat(right.arr);
|
||
return true;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(transaction, item) {
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
const len = this.arr.length;
|
||
encoder.writeLen(len - offset);
|
||
for (let i = offset; i < len; i++) {
|
||
const c = this.arr[i];
|
||
encoder.writeString(c === void 0 ? "undefined" : JSON.stringify(c));
|
||
}
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 2;
|
||
}
|
||
};
|
||
var readContentJSON = (decoder) => {
|
||
const len = decoder.readLen();
|
||
const cs = [];
|
||
for (let i = 0; i < len; i++) {
|
||
const c = decoder.readString();
|
||
if (c === "undefined") {
|
||
cs.push(void 0);
|
||
} else {
|
||
cs.push(JSON.parse(c));
|
||
}
|
||
}
|
||
return new ContentJSON(cs);
|
||
};
|
||
var isDevMode = getVariable("node_env") === "development";
|
||
var ContentAny = class _ContentAny {
|
||
/**
|
||
* @param {Array<any>} arr
|
||
*/
|
||
constructor(arr) {
|
||
this.arr = arr;
|
||
isDevMode && deepFreeze(arr);
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return this.arr.length;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return this.arr;
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return true;
|
||
}
|
||
/**
|
||
* @return {ContentAny}
|
||
*/
|
||
copy() {
|
||
return new _ContentAny(this.arr);
|
||
}
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentAny}
|
||
*/
|
||
splice(offset) {
|
||
const right = new _ContentAny(this.arr.slice(offset));
|
||
this.arr = this.arr.slice(0, offset);
|
||
return right;
|
||
}
|
||
/**
|
||
* @param {ContentAny} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
this.arr = this.arr.concat(right.arr);
|
||
return true;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(transaction, item) {
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
const len = this.arr.length;
|
||
encoder.writeLen(len - offset);
|
||
for (let i = offset; i < len; i++) {
|
||
const c = this.arr[i];
|
||
encoder.writeAny(c);
|
||
}
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 8;
|
||
}
|
||
};
|
||
var readContentAny = (decoder) => {
|
||
const len = decoder.readLen();
|
||
const cs = [];
|
||
for (let i = 0; i < len; i++) {
|
||
cs.push(decoder.readAny());
|
||
}
|
||
return new ContentAny(cs);
|
||
};
|
||
var ContentString = class _ContentString {
|
||
/**
|
||
* @param {string} str
|
||
*/
|
||
constructor(str) {
|
||
this.str = str;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return this.str.length;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return this.str.split("");
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return true;
|
||
}
|
||
/**
|
||
* @return {ContentString}
|
||
*/
|
||
copy() {
|
||
return new _ContentString(this.str);
|
||
}
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentString}
|
||
*/
|
||
splice(offset) {
|
||
const right = new _ContentString(this.str.slice(offset));
|
||
this.str = this.str.slice(0, offset);
|
||
const firstCharCode = this.str.charCodeAt(offset - 1);
|
||
if (firstCharCode >= 55296 && firstCharCode <= 56319) {
|
||
this.str = this.str.slice(0, offset - 1) + "<22>";
|
||
right.str = "<22>" + right.str.slice(1);
|
||
}
|
||
return right;
|
||
}
|
||
/**
|
||
* @param {ContentString} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
this.str += right.str;
|
||
return true;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(transaction, item) {
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
encoder.writeString(offset === 0 ? this.str : this.str.slice(offset));
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 4;
|
||
}
|
||
};
|
||
var readContentString = (decoder) => new ContentString(decoder.readString());
|
||
var typeRefs = [
|
||
readYArray,
|
||
readYMap,
|
||
readYText,
|
||
readYXmlElement,
|
||
readYXmlFragment,
|
||
readYXmlHook,
|
||
readYXmlText
|
||
];
|
||
var YArrayRefID = 0;
|
||
var YMapRefID = 1;
|
||
var YTextRefID = 2;
|
||
var YXmlElementRefID = 3;
|
||
var YXmlFragmentRefID = 4;
|
||
var YXmlHookRefID = 5;
|
||
var YXmlTextRefID = 6;
|
||
var ContentType = class _ContentType {
|
||
/**
|
||
* @param {AbstractType<any>} type
|
||
*/
|
||
constructor(type) {
|
||
this.type = type;
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getLength() {
|
||
return 1;
|
||
}
|
||
/**
|
||
* @return {Array<any>}
|
||
*/
|
||
getContent() {
|
||
return [this.type];
|
||
}
|
||
/**
|
||
* @return {boolean}
|
||
*/
|
||
isCountable() {
|
||
return true;
|
||
}
|
||
/**
|
||
* @return {ContentType}
|
||
*/
|
||
copy() {
|
||
return new _ContentType(this.type._copy());
|
||
}
|
||
/**
|
||
* @param {number} offset
|
||
* @return {ContentType}
|
||
*/
|
||
splice(offset) {
|
||
throw methodUnimplemented();
|
||
}
|
||
/**
|
||
* @param {ContentType} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
return false;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {Item} item
|
||
*/
|
||
integrate(transaction, item) {
|
||
this.type._integrate(transaction.doc, item);
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
let item = this.type._start;
|
||
while (item !== null) {
|
||
if (!item.deleted) {
|
||
item.delete(transaction);
|
||
} else if (item.id.clock < (transaction.beforeState.get(item.id.client) || 0)) {
|
||
transaction._mergeStructs.push(item);
|
||
}
|
||
item = item.right;
|
||
}
|
||
this.type._map.forEach((item2) => {
|
||
if (!item2.deleted) {
|
||
item2.delete(transaction);
|
||
} else if (item2.id.clock < (transaction.beforeState.get(item2.id.client) || 0)) {
|
||
transaction._mergeStructs.push(item2);
|
||
}
|
||
});
|
||
transaction.changed.delete(this.type);
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
*/
|
||
gc(store) {
|
||
let item = this.type._start;
|
||
while (item !== null) {
|
||
item.gc(store, true);
|
||
item = item.right;
|
||
}
|
||
this.type._start = null;
|
||
this.type._map.forEach(
|
||
/** @param {Item | null} item */
|
||
(item2) => {
|
||
while (item2 !== null) {
|
||
item2.gc(store, true);
|
||
item2 = item2.left;
|
||
}
|
||
}
|
||
);
|
||
this.type._map = /* @__PURE__ */ new Map();
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
this.type._write(encoder);
|
||
}
|
||
/**
|
||
* @return {number}
|
||
*/
|
||
getRef() {
|
||
return 7;
|
||
}
|
||
};
|
||
var readContentType = (decoder) => new ContentType(typeRefs[decoder.readTypeRef()](decoder));
|
||
var followRedone = (store, id2) => {
|
||
let nextID = id2;
|
||
let diff = 0;
|
||
let item;
|
||
do {
|
||
if (diff > 0) {
|
||
nextID = createID(nextID.client, nextID.clock + diff);
|
||
}
|
||
item = getItem(store, nextID);
|
||
diff = nextID.clock - item.id.clock;
|
||
nextID = item.redone;
|
||
} while (nextID !== null && item instanceof Item);
|
||
return {
|
||
item,
|
||
diff
|
||
};
|
||
};
|
||
var keepItem = (item, keep) => {
|
||
while (item !== null && item.keep !== keep) {
|
||
item.keep = keep;
|
||
item = /** @type {AbstractType<any>} */
|
||
item.parent._item;
|
||
}
|
||
};
|
||
var splitItem = (transaction, leftItem, diff) => {
|
||
const { client, clock } = leftItem.id;
|
||
const rightItem = new Item(
|
||
createID(client, clock + diff),
|
||
leftItem,
|
||
createID(client, clock + diff - 1),
|
||
leftItem.right,
|
||
leftItem.rightOrigin,
|
||
leftItem.parent,
|
||
leftItem.parentSub,
|
||
leftItem.content.splice(diff)
|
||
);
|
||
if (leftItem.deleted) {
|
||
rightItem.markDeleted();
|
||
}
|
||
if (leftItem.keep) {
|
||
rightItem.keep = true;
|
||
}
|
||
if (leftItem.redone !== null) {
|
||
rightItem.redone = createID(leftItem.redone.client, leftItem.redone.clock + diff);
|
||
}
|
||
leftItem.right = rightItem;
|
||
if (rightItem.right !== null) {
|
||
rightItem.right.left = rightItem;
|
||
}
|
||
transaction._mergeStructs.push(rightItem);
|
||
if (rightItem.parentSub !== null && rightItem.right === null) {
|
||
rightItem.parent._map.set(rightItem.parentSub, rightItem);
|
||
}
|
||
leftItem.length = diff;
|
||
return rightItem;
|
||
};
|
||
var isDeletedByUndoStack = (stack, id2) => some(
|
||
stack,
|
||
/** @param {StackItem} s */
|
||
(s) => isDeleted(s.deletions, id2)
|
||
);
|
||
var redoItem = (transaction, item, redoitems, itemsToDelete, ignoreRemoteMapChanges, um) => {
|
||
const doc2 = transaction.doc;
|
||
const store = doc2.store;
|
||
const ownClientID = doc2.clientID;
|
||
const redone = item.redone;
|
||
if (redone !== null) {
|
||
return getItemCleanStart(transaction, redone);
|
||
}
|
||
let parentItem = (
|
||
/** @type {AbstractType<any>} */
|
||
item.parent._item
|
||
);
|
||
let left = null;
|
||
let right;
|
||
if (parentItem !== null && parentItem.deleted === true) {
|
||
if (parentItem.redone === null && (!redoitems.has(parentItem) || redoItem(transaction, parentItem, redoitems, itemsToDelete, ignoreRemoteMapChanges, um) === null)) {
|
||
return null;
|
||
}
|
||
while (parentItem.redone !== null) {
|
||
parentItem = getItemCleanStart(transaction, parentItem.redone);
|
||
}
|
||
}
|
||
const parentType = parentItem === null ? (
|
||
/** @type {AbstractType<any>} */
|
||
item.parent
|
||
) : (
|
||
/** @type {ContentType} */
|
||
parentItem.content.type
|
||
);
|
||
if (item.parentSub === null) {
|
||
left = item.left;
|
||
right = item;
|
||
while (left !== null) {
|
||
let leftTrace = left;
|
||
while (leftTrace !== null && /** @type {AbstractType<any>} */
|
||
leftTrace.parent._item !== parentItem) {
|
||
leftTrace = leftTrace.redone === null ? null : getItemCleanStart(transaction, leftTrace.redone);
|
||
}
|
||
if (leftTrace !== null && /** @type {AbstractType<any>} */
|
||
leftTrace.parent._item === parentItem) {
|
||
left = leftTrace;
|
||
break;
|
||
}
|
||
left = left.left;
|
||
}
|
||
while (right !== null) {
|
||
let rightTrace = right;
|
||
while (rightTrace !== null && /** @type {AbstractType<any>} */
|
||
rightTrace.parent._item !== parentItem) {
|
||
rightTrace = rightTrace.redone === null ? null : getItemCleanStart(transaction, rightTrace.redone);
|
||
}
|
||
if (rightTrace !== null && /** @type {AbstractType<any>} */
|
||
rightTrace.parent._item === parentItem) {
|
||
right = rightTrace;
|
||
break;
|
||
}
|
||
right = right.right;
|
||
}
|
||
} else {
|
||
right = null;
|
||
if (item.right && !ignoreRemoteMapChanges) {
|
||
left = item;
|
||
while (left !== null && left.right !== null && (left.right.redone || isDeleted(itemsToDelete, left.right.id) || isDeletedByUndoStack(um.undoStack, left.right.id) || isDeletedByUndoStack(um.redoStack, left.right.id))) {
|
||
left = left.right;
|
||
while (left.redone) left = getItemCleanStart(transaction, left.redone);
|
||
}
|
||
if (left && left.right !== null) {
|
||
return null;
|
||
}
|
||
} else {
|
||
left = parentType._map.get(item.parentSub) || null;
|
||
}
|
||
if (left !== null && /** @type {AbstractType<any>} */
|
||
left.parent._item !== parentItem) {
|
||
left = parentType._map.get(item.parentSub) || null;
|
||
}
|
||
}
|
||
const nextClock = getState(store, ownClientID);
|
||
const nextId = createID(ownClientID, nextClock);
|
||
const redoneItem = new Item(
|
||
nextId,
|
||
left,
|
||
left && left.lastId,
|
||
right,
|
||
right && right.id,
|
||
parentType,
|
||
item.parentSub,
|
||
item.content.copy()
|
||
);
|
||
item.redone = nextId;
|
||
keepItem(redoneItem, true);
|
||
redoneItem.integrate(transaction, 0);
|
||
return redoneItem;
|
||
};
|
||
var Item = class _Item extends AbstractStruct {
|
||
/**
|
||
* @param {ID} id
|
||
* @param {Item | null} left
|
||
* @param {ID | null} origin
|
||
* @param {Item | null} right
|
||
* @param {ID | null} rightOrigin
|
||
* @param {AbstractType<any>|ID|null} parent Is a type if integrated, is null if it is possible to copy parent from left or right, is ID before integration to search for it.
|
||
* @param {string | null} parentSub
|
||
* @param {AbstractContent} content
|
||
*/
|
||
constructor(id2, left, origin, right, rightOrigin, parent, parentSub, content) {
|
||
super(id2, content.getLength());
|
||
this.origin = origin;
|
||
this.left = left;
|
||
this.right = right;
|
||
this.rightOrigin = rightOrigin;
|
||
this.parent = parent;
|
||
this.parentSub = parentSub;
|
||
this.redone = null;
|
||
this.content = content;
|
||
this.info = this.content.isCountable() ? BIT2 : 0;
|
||
}
|
||
/**
|
||
* This is used to mark the item as an indexed fast-search marker
|
||
*
|
||
* @type {boolean}
|
||
*/
|
||
set marker(isMarked) {
|
||
if ((this.info & BIT4) > 0 !== isMarked) {
|
||
this.info ^= BIT4;
|
||
}
|
||
}
|
||
get marker() {
|
||
return (this.info & BIT4) > 0;
|
||
}
|
||
/**
|
||
* If true, do not garbage collect this Item.
|
||
*/
|
||
get keep() {
|
||
return (this.info & BIT1) > 0;
|
||
}
|
||
set keep(doKeep) {
|
||
if (this.keep !== doKeep) {
|
||
this.info ^= BIT1;
|
||
}
|
||
}
|
||
get countable() {
|
||
return (this.info & BIT2) > 0;
|
||
}
|
||
/**
|
||
* Whether this item was deleted or not.
|
||
* @type {Boolean}
|
||
*/
|
||
get deleted() {
|
||
return (this.info & BIT3) > 0;
|
||
}
|
||
set deleted(doDelete) {
|
||
if (this.deleted !== doDelete) {
|
||
this.info ^= BIT3;
|
||
}
|
||
}
|
||
markDeleted() {
|
||
this.info |= BIT3;
|
||
}
|
||
/**
|
||
* Return the creator clientID of the missing op or define missing items and return null.
|
||
*
|
||
* @param {Transaction} transaction
|
||
* @param {StructStore} store
|
||
* @return {null | number}
|
||
*/
|
||
getMissing(transaction, store) {
|
||
if (this.origin && this.origin.client !== this.id.client && this.origin.clock >= getState(store, this.origin.client)) {
|
||
return this.origin.client;
|
||
}
|
||
if (this.rightOrigin && this.rightOrigin.client !== this.id.client && this.rightOrigin.clock >= getState(store, this.rightOrigin.client)) {
|
||
return this.rightOrigin.client;
|
||
}
|
||
if (this.parent && this.parent.constructor === ID && this.id.client !== this.parent.client && this.parent.clock >= getState(store, this.parent.client)) {
|
||
return this.parent.client;
|
||
}
|
||
if (this.origin) {
|
||
this.left = getItemCleanEnd(transaction, store, this.origin);
|
||
this.origin = this.left.lastId;
|
||
}
|
||
if (this.rightOrigin) {
|
||
this.right = getItemCleanStart(transaction, this.rightOrigin);
|
||
this.rightOrigin = this.right.id;
|
||
}
|
||
if (this.left && this.left.constructor === GC || this.right && this.right.constructor === GC) {
|
||
this.parent = null;
|
||
} else if (!this.parent) {
|
||
if (this.left && this.left.constructor === _Item) {
|
||
this.parent = this.left.parent;
|
||
this.parentSub = this.left.parentSub;
|
||
} else if (this.right && this.right.constructor === _Item) {
|
||
this.parent = this.right.parent;
|
||
this.parentSub = this.right.parentSub;
|
||
}
|
||
} else if (this.parent.constructor === ID) {
|
||
const parentItem = getItem(store, this.parent);
|
||
if (parentItem.constructor === GC) {
|
||
this.parent = null;
|
||
} else {
|
||
this.parent = /** @type {ContentType} */
|
||
parentItem.content.type;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {number} offset
|
||
*/
|
||
integrate(transaction, offset) {
|
||
if (offset > 0) {
|
||
this.id.clock += offset;
|
||
this.left = getItemCleanEnd(transaction, transaction.doc.store, createID(this.id.client, this.id.clock - 1));
|
||
this.origin = this.left.lastId;
|
||
this.content = this.content.splice(offset);
|
||
this.length -= offset;
|
||
}
|
||
if (this.parent) {
|
||
if (!this.left && (!this.right || this.right.left !== null) || this.left && this.left.right !== this.right) {
|
||
let left = this.left;
|
||
let o;
|
||
if (left !== null) {
|
||
o = left.right;
|
||
} else if (this.parentSub !== null) {
|
||
o = /** @type {AbstractType<any>} */
|
||
this.parent._map.get(this.parentSub) || null;
|
||
while (o !== null && o.left !== null) {
|
||
o = o.left;
|
||
}
|
||
} else {
|
||
o = /** @type {AbstractType<any>} */
|
||
this.parent._start;
|
||
}
|
||
const conflictingItems = /* @__PURE__ */ new Set();
|
||
const itemsBeforeOrigin = /* @__PURE__ */ new Set();
|
||
while (o !== null && o !== this.right) {
|
||
itemsBeforeOrigin.add(o);
|
||
conflictingItems.add(o);
|
||
if (compareIDs(this.origin, o.origin)) {
|
||
if (o.id.client < this.id.client) {
|
||
left = o;
|
||
conflictingItems.clear();
|
||
} else if (compareIDs(this.rightOrigin, o.rightOrigin)) {
|
||
break;
|
||
}
|
||
} else if (o.origin !== null && itemsBeforeOrigin.has(getItem(transaction.doc.store, o.origin))) {
|
||
if (!conflictingItems.has(getItem(transaction.doc.store, o.origin))) {
|
||
left = o;
|
||
conflictingItems.clear();
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
o = o.right;
|
||
}
|
||
this.left = left;
|
||
}
|
||
if (this.left !== null) {
|
||
const right = this.left.right;
|
||
this.right = right;
|
||
this.left.right = this;
|
||
} else {
|
||
let r;
|
||
if (this.parentSub !== null) {
|
||
r = /** @type {AbstractType<any>} */
|
||
this.parent._map.get(this.parentSub) || null;
|
||
while (r !== null && r.left !== null) {
|
||
r = r.left;
|
||
}
|
||
} else {
|
||
r = /** @type {AbstractType<any>} */
|
||
this.parent._start;
|
||
this.parent._start = this;
|
||
}
|
||
this.right = r;
|
||
}
|
||
if (this.right !== null) {
|
||
this.right.left = this;
|
||
} else if (this.parentSub !== null) {
|
||
this.parent._map.set(this.parentSub, this);
|
||
if (this.left !== null) {
|
||
this.left.delete(transaction);
|
||
}
|
||
}
|
||
if (this.parentSub === null && this.countable && !this.deleted) {
|
||
this.parent._length += this.length;
|
||
}
|
||
addStruct(transaction.doc.store, this);
|
||
this.content.integrate(transaction, this);
|
||
addChangedTypeToTransaction(
|
||
transaction,
|
||
/** @type {AbstractType<any>} */
|
||
this.parent,
|
||
this.parentSub
|
||
);
|
||
if (
|
||
/** @type {AbstractType<any>} */
|
||
this.parent._item !== null && /** @type {AbstractType<any>} */
|
||
this.parent._item.deleted || this.parentSub !== null && this.right !== null
|
||
) {
|
||
this.delete(transaction);
|
||
}
|
||
} else {
|
||
new GC(this.id, this.length).integrate(transaction, 0);
|
||
}
|
||
}
|
||
/**
|
||
* Returns the next non-deleted item
|
||
*/
|
||
get next() {
|
||
let n = this.right;
|
||
while (n !== null && n.deleted) {
|
||
n = n.right;
|
||
}
|
||
return n;
|
||
}
|
||
/**
|
||
* Returns the previous non-deleted item
|
||
*/
|
||
get prev() {
|
||
let n = this.left;
|
||
while (n !== null && n.deleted) {
|
||
n = n.left;
|
||
}
|
||
return n;
|
||
}
|
||
/**
|
||
* Computes the last content address of this Item.
|
||
*/
|
||
get lastId() {
|
||
return this.length === 1 ? this.id : createID(this.id.client, this.id.clock + this.length - 1);
|
||
}
|
||
/**
|
||
* Try to merge two items
|
||
*
|
||
* @param {Item} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
if (this.constructor === right.constructor && compareIDs(right.origin, this.lastId) && this.right === right && compareIDs(this.rightOrigin, right.rightOrigin) && this.id.client === right.id.client && this.id.clock + this.length === right.id.clock && this.deleted === right.deleted && this.redone === null && right.redone === null && this.content.constructor === right.content.constructor && this.content.mergeWith(right.content)) {
|
||
const searchMarker = (
|
||
/** @type {AbstractType<any>} */
|
||
this.parent._searchMarker
|
||
);
|
||
if (searchMarker) {
|
||
searchMarker.forEach((marker) => {
|
||
if (marker.p === right) {
|
||
marker.p = this;
|
||
if (!this.deleted && this.countable) {
|
||
marker.index -= this.length;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
if (right.keep) {
|
||
this.keep = true;
|
||
}
|
||
this.right = right.right;
|
||
if (this.right !== null) {
|
||
this.right.left = this;
|
||
}
|
||
this.length += right.length;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Mark this Item as deleted.
|
||
*
|
||
* @param {Transaction} transaction
|
||
*/
|
||
delete(transaction) {
|
||
if (!this.deleted) {
|
||
const parent = (
|
||
/** @type {AbstractType<any>} */
|
||
this.parent
|
||
);
|
||
if (this.countable && this.parentSub === null) {
|
||
parent._length -= this.length;
|
||
}
|
||
this.markDeleted();
|
||
addToDeleteSet(transaction.deleteSet, this.id.client, this.id.clock, this.length);
|
||
addChangedTypeToTransaction(transaction, parent, this.parentSub);
|
||
this.content.delete(transaction);
|
||
}
|
||
}
|
||
/**
|
||
* @param {StructStore} store
|
||
* @param {boolean} parentGCd
|
||
*/
|
||
gc(store, parentGCd) {
|
||
if (!this.deleted) {
|
||
throw unexpectedCase();
|
||
}
|
||
this.content.gc(store);
|
||
if (parentGCd) {
|
||
replaceStruct(store, this, new GC(this.id, this.length));
|
||
} else {
|
||
this.content = new ContentDeleted(this.length);
|
||
}
|
||
}
|
||
/**
|
||
* Transform the properties of this type to binary and write it to an
|
||
* BinaryEncoder.
|
||
*
|
||
* This is called when this Item is sent to a remote peer.
|
||
*
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to.
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
const origin = offset > 0 ? createID(this.id.client, this.id.clock + offset - 1) : this.origin;
|
||
const rightOrigin = this.rightOrigin;
|
||
const parentSub = this.parentSub;
|
||
const info = this.content.getRef() & BITS5 | (origin === null ? 0 : BIT8) | // origin is defined
|
||
(rightOrigin === null ? 0 : BIT7) | // right origin is defined
|
||
(parentSub === null ? 0 : BIT6);
|
||
encoder.writeInfo(info);
|
||
if (origin !== null) {
|
||
encoder.writeLeftID(origin);
|
||
}
|
||
if (rightOrigin !== null) {
|
||
encoder.writeRightID(rightOrigin);
|
||
}
|
||
if (origin === null && rightOrigin === null) {
|
||
const parent = (
|
||
/** @type {AbstractType<any>} */
|
||
this.parent
|
||
);
|
||
if (parent._item !== void 0) {
|
||
const parentItem = parent._item;
|
||
if (parentItem === null) {
|
||
const ykey = findRootTypeKey(parent);
|
||
encoder.writeParentInfo(true);
|
||
encoder.writeString(ykey);
|
||
} else {
|
||
encoder.writeParentInfo(false);
|
||
encoder.writeLeftID(parentItem.id);
|
||
}
|
||
} else if (parent.constructor === String) {
|
||
encoder.writeParentInfo(true);
|
||
encoder.writeString(parent);
|
||
} else if (parent.constructor === ID) {
|
||
encoder.writeParentInfo(false);
|
||
encoder.writeLeftID(parent);
|
||
} else {
|
||
unexpectedCase();
|
||
}
|
||
if (parentSub !== null) {
|
||
encoder.writeString(parentSub);
|
||
}
|
||
}
|
||
this.content.write(encoder, offset);
|
||
}
|
||
};
|
||
var readItemContent = (decoder, info) => contentRefs[info & BITS5](decoder);
|
||
var contentRefs = [
|
||
() => {
|
||
unexpectedCase();
|
||
},
|
||
// GC is not ItemContent
|
||
readContentDeleted,
|
||
// 1
|
||
readContentJSON,
|
||
// 2
|
||
readContentBinary,
|
||
// 3
|
||
readContentString,
|
||
// 4
|
||
readContentEmbed,
|
||
// 5
|
||
readContentFormat,
|
||
// 6
|
||
readContentType,
|
||
// 7
|
||
readContentAny,
|
||
// 8
|
||
readContentDoc,
|
||
// 9
|
||
() => {
|
||
unexpectedCase();
|
||
}
|
||
// 10 - Skip is not ItemContent
|
||
];
|
||
var structSkipRefNumber = 10;
|
||
var Skip = class extends AbstractStruct {
|
||
get deleted() {
|
||
return true;
|
||
}
|
||
delete() {
|
||
}
|
||
/**
|
||
* @param {Skip} right
|
||
* @return {boolean}
|
||
*/
|
||
mergeWith(right) {
|
||
if (this.constructor !== right.constructor) {
|
||
return false;
|
||
}
|
||
this.length += right.length;
|
||
return true;
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {number} offset
|
||
*/
|
||
integrate(transaction, offset) {
|
||
unexpectedCase();
|
||
}
|
||
/**
|
||
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
|
||
* @param {number} offset
|
||
*/
|
||
write(encoder, offset) {
|
||
encoder.writeInfo(structSkipRefNumber);
|
||
writeVarUint(encoder.restEncoder, this.length - offset);
|
||
}
|
||
/**
|
||
* @param {Transaction} transaction
|
||
* @param {StructStore} store
|
||
* @return {null | number}
|
||
*/
|
||
getMissing(transaction, store) {
|
||
return null;
|
||
}
|
||
};
|
||
var glo = (
|
||
/** @type {any} */
|
||
typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}
|
||
);
|
||
var importIdentifier = "__ $YJS$ __";
|
||
if (glo[importIdentifier] === true) {
|
||
console.error("Yjs was already imported. This breaks constructor checks and will lead to issues! - https://github.com/yjs/yjs/issues/438");
|
||
}
|
||
glo[importIdentifier] = true;
|
||
export {
|
||
AbsolutePosition,
|
||
AbstractConnector,
|
||
AbstractStruct,
|
||
AbstractType,
|
||
YArray as Array,
|
||
ContentAny,
|
||
ContentBinary,
|
||
ContentDeleted,
|
||
ContentDoc,
|
||
ContentEmbed,
|
||
ContentFormat,
|
||
ContentJSON,
|
||
ContentString,
|
||
ContentType,
|
||
Doc,
|
||
GC,
|
||
ID,
|
||
Item,
|
||
YMap as Map,
|
||
PermanentUserData,
|
||
RelativePosition,
|
||
Skip,
|
||
Snapshot,
|
||
YText as Text,
|
||
Transaction,
|
||
UndoManager,
|
||
UpdateDecoderV1,
|
||
UpdateDecoderV2,
|
||
UpdateEncoderV1,
|
||
UpdateEncoderV2,
|
||
YXmlElement as XmlElement,
|
||
YXmlFragment as XmlFragment,
|
||
YXmlHook as XmlHook,
|
||
YXmlText as XmlText,
|
||
YArrayEvent,
|
||
YEvent,
|
||
YMapEvent,
|
||
YTextEvent,
|
||
YXmlEvent,
|
||
applyUpdate,
|
||
applyUpdateV2,
|
||
cleanupYTextFormatting,
|
||
compareIDs,
|
||
compareRelativePositions,
|
||
convertUpdateFormatV1ToV2,
|
||
convertUpdateFormatV2ToV1,
|
||
createAbsolutePositionFromRelativePosition,
|
||
createDeleteSet,
|
||
createDeleteSetFromStructStore,
|
||
createDocFromSnapshot,
|
||
createID,
|
||
createRelativePositionFromJSON,
|
||
createRelativePositionFromTypeIndex,
|
||
createSnapshot,
|
||
decodeRelativePosition,
|
||
decodeSnapshot,
|
||
decodeSnapshotV2,
|
||
decodeStateVector,
|
||
decodeUpdate,
|
||
decodeUpdateV2,
|
||
diffUpdate,
|
||
diffUpdateV2,
|
||
emptySnapshot,
|
||
encodeRelativePosition,
|
||
encodeSnapshot,
|
||
encodeSnapshotV2,
|
||
encodeStateAsUpdate,
|
||
encodeStateAsUpdateV2,
|
||
encodeStateVector,
|
||
encodeStateVectorFromUpdate,
|
||
encodeStateVectorFromUpdateV2,
|
||
equalDeleteSets,
|
||
equalSnapshots,
|
||
findIndexSS,
|
||
findRootTypeKey,
|
||
getItem,
|
||
getItemCleanEnd,
|
||
getItemCleanStart,
|
||
getState,
|
||
getTypeChildren,
|
||
isDeleted,
|
||
isParentOf,
|
||
iterateDeletedStructs,
|
||
logType,
|
||
logUpdate,
|
||
logUpdateV2,
|
||
mergeDeleteSets,
|
||
mergeUpdates,
|
||
mergeUpdatesV2,
|
||
obfuscateUpdate,
|
||
obfuscateUpdateV2,
|
||
parseUpdateMeta,
|
||
parseUpdateMetaV2,
|
||
readUpdate,
|
||
readUpdateV2,
|
||
relativePositionToJSON,
|
||
snapshot,
|
||
snapshotContainsUpdate,
|
||
transact,
|
||
tryGc,
|
||
typeListToArraySnapshot,
|
||
typeMapGetAllSnapshot,
|
||
typeMapGetSnapshot
|
||
};
|
||
//# sourceMappingURL=yjs.js.map
|