This commit is contained in:
jsingleton20 2023-01-30 15:11:09 -05:00
parent 370d0c138d
commit 100e051c5d
66 changed files with 50407 additions and 110 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
node_modules
dist
.vscode
docs

1
dist/src/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export { Doc, Transaction, YArray as Array, YMap as Map, YText as Text, YXmlText as XmlText, YXmlHook as XmlHook, YXmlElement as XmlElement, YXmlFragment as XmlFragment, YXmlEvent, YMapEvent, YArrayEvent, YTextEvent, YEvent, Item, AbstractStruct, GC, ContentBinary, ContentDeleted, ContentEmbed, ContentFormat, ContentJSON, ContentAny, ContentString, ContentType, AbstractType, getTypeChildren, createRelativePositionFromTypeIndex, createRelativePositionFromJSON, createAbsolutePositionFromRelativePosition, compareRelativePositions, AbsolutePosition, RelativePosition, ID, createID, compareIDs, getState, Snapshot, createSnapshot, createDeleteSet, createDeleteSetFromStructStore, cleanupYTextFormatting, snapshot, emptySnapshot, findRootTypeKey, findIndexSS, getItem, typeListToArraySnapshot, typeMapGetSnapshot, createDocFromSnapshot, iterateDeletedStructs, applyUpdate, applyUpdateV2, readUpdate, readUpdateV2, encodeStateAsUpdate, encodeStateAsUpdateV2, encodeStateVector, UndoManager, decodeSnapshot, encodeSnapshot, decodeSnapshotV2, encodeSnapshotV2, decodeStateVector, logUpdate, logUpdateV2, decodeUpdate, decodeUpdateV2, relativePositionToJSON, isDeleted, isParentOf, equalSnapshots, PermanentUserData, tryGc, transact, AbstractConnector, logType, mergeUpdates, mergeUpdatesV2, parseUpdateMeta, parseUpdateMetaV2, encodeStateVectorFromUpdate, encodeStateVectorFromUpdateV2, encodeRelativePosition, decodeRelativePosition, diffUpdate, diffUpdateV2, convertUpdateFormatV1ToV2, convertUpdateFormatV2ToV1, UpdateEncoderV1 } from "./internals.js";

40
dist/src/internals.d.ts vendored Normal file
View File

@ -0,0 +1,40 @@
export * from "./utils/AbstractConnector.js";
export * from "./utils/DeleteSet.js";
export * from "./utils/Doc.js";
export * from "./utils/UpdateDecoder.js";
export * from "./utils/UpdateEncoder.js";
export * from "./utils/encoding.js";
export * from "./utils/EventHandler.js";
export * from "./utils/ID.js";
export * from "./utils/isParentOf.js";
export * from "./utils/logging.js";
export * from "./utils/PermanentUserData.js";
export * from "./utils/RelativePosition.js";
export * from "./utils/Snapshot.js";
export * from "./utils/StructStore.js";
export * from "./utils/Transaction.js";
export * from "./utils/UndoManager.js";
export * from "./utils/updates.js";
export * from "./utils/YEvent.js";
export * from "./types/AbstractType.js";
export * from "./types/YArray.js";
export * from "./types/YMap.js";
export * from "./types/YText.js";
export * from "./types/YXmlFragment.js";
export * from "./types/YXmlElement.js";
export * from "./types/YXmlEvent.js";
export * from "./types/YXmlHook.js";
export * from "./types/YXmlText.js";
export * from "./structs/AbstractStruct.js";
export * from "./structs/GC.js";
export * from "./structs/ContentBinary.js";
export * from "./structs/ContentDeleted.js";
export * from "./structs/ContentDoc.js";
export * from "./structs/ContentEmbed.js";
export * from "./structs/ContentFormat.js";
export * from "./structs/ContentJSON.js";
export * from "./structs/ContentAny.js";
export * from "./structs/ContentString.js";
export * from "./structs/ContentType.js";
export * from "./structs/Item.js";
export * from "./structs/Skip.js";

36
dist/src/structs/AbstractStruct.d.ts vendored Normal file
View File

@ -0,0 +1,36 @@
export class AbstractStruct {
/**
* @param {ID} id
* @param {number} length
*/
constructor(id: ID, length: number);
id: ID;
length: number;
/**
* @type {boolean}
*/
get deleted(): boolean;
/**
* 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} wether this merged with right
*/
mergeWith(right: AbstractStruct): boolean;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder The encoder to write data to.
* @param {number} offset
* @param {number} encodingRef
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number, encodingRef: number): void;
/**
* @param {Transaction} transaction
* @param {number} offset
*/
integrate(transaction: Transaction, offset: number): void;
}
import { ID } from "../utils/ID.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { Transaction } from "../utils/Transaction.js";

66
dist/src/structs/ContentAny.d.ts vendored Normal file
View File

@ -0,0 +1,66 @@
export class ContentAny {
/**
* @param {Array<any>} arr
*/
constructor(arr: Array<any>);
/**
* @type {Array<any>}
*/
arr: Array<any>;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentAny}
*/
copy(): ContentAny;
/**
* @param {number} offset
* @return {ContentAny}
*/
splice(offset: number): ContentAny;
/**
* @param {ContentAny} right
* @return {boolean}
*/
mergeWith(right: ContentAny): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentAny(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentAny;
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

63
dist/src/structs/ContentBinary.d.ts vendored Normal file
View File

@ -0,0 +1,63 @@
export class ContentBinary {
/**
* @param {Uint8Array} content
*/
constructor(content: Uint8Array);
content: Uint8Array;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentBinary}
*/
copy(): ContentBinary;
/**
* @param {number} offset
* @return {ContentBinary}
*/
splice(offset: number): ContentBinary;
/**
* @param {ContentBinary} right
* @return {boolean}
*/
mergeWith(right: ContentBinary): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentBinary(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentBinary;
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

63
dist/src/structs/ContentDeleted.d.ts vendored Normal file
View File

@ -0,0 +1,63 @@
export class ContentDeleted {
/**
* @param {number} len
*/
constructor(len: number);
len: number;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentDeleted}
*/
copy(): ContentDeleted;
/**
* @param {number} offset
* @return {ContentDeleted}
*/
splice(offset: number): ContentDeleted;
/**
* @param {ContentDeleted} right
* @return {boolean}
*/
mergeWith(right: ContentDeleted): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentDeleted(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentDeleted;
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

71
dist/src/structs/ContentDoc.d.ts vendored Normal file
View File

@ -0,0 +1,71 @@
/**
* @private
*/
export class ContentDoc {
/**
* @param {Doc} doc
*/
constructor(doc: Doc);
/**
* @type {Doc}
*/
doc: Doc;
opts: any;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentDoc}
*/
copy(): ContentDoc;
/**
* @param {number} offset
* @return {ContentDoc}
*/
splice(offset: number): ContentDoc;
/**
* @param {ContentDoc} right
* @return {boolean}
*/
mergeWith(right: ContentDoc): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentDoc(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentDoc;
import { Doc } from "../utils/Doc.js";
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

66
dist/src/structs/ContentEmbed.d.ts vendored Normal file
View File

@ -0,0 +1,66 @@
/**
* @private
*/
export class ContentEmbed {
/**
* @param {Object} embed
*/
constructor(embed: Object);
embed: Object;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentEmbed}
*/
copy(): ContentEmbed;
/**
* @param {number} offset
* @return {ContentEmbed}
*/
splice(offset: number): ContentEmbed;
/**
* @param {ContentEmbed} right
* @return {boolean}
*/
mergeWith(right: ContentEmbed): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentEmbed(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentEmbed;
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

68
dist/src/structs/ContentFormat.d.ts vendored Normal file
View File

@ -0,0 +1,68 @@
/**
* @private
*/
export class ContentFormat {
/**
* @param {string} key
* @param {Object} value
*/
constructor(key: string, value: Object);
key: string;
value: Object;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentFormat}
*/
copy(): ContentFormat;
/**
* @param {number} offset
* @return {ContentFormat}
*/
splice(offset: number): ContentFormat;
/**
* @param {ContentFormat} right
* @return {boolean}
*/
mergeWith(right: ContentFormat): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentFormat(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentFormat;
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

69
dist/src/structs/ContentJSON.d.ts vendored Normal file
View File

@ -0,0 +1,69 @@
/**
* @private
*/
export class ContentJSON {
/**
* @param {Array<any>} arr
*/
constructor(arr: Array<any>);
/**
* @type {Array<any>}
*/
arr: Array<any>;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentJSON}
*/
copy(): ContentJSON;
/**
* @param {number} offset
* @return {ContentJSON}
*/
splice(offset: number): ContentJSON;
/**
* @param {ContentJSON} right
* @return {boolean}
*/
mergeWith(right: ContentJSON): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentJSON(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentJSON;
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

69
dist/src/structs/ContentString.d.ts vendored Normal file
View File

@ -0,0 +1,69 @@
/**
* @private
*/
export class ContentString {
/**
* @param {string} str
*/
constructor(str: string);
/**
* @type {string}
*/
str: string;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentString}
*/
copy(): ContentString;
/**
* @param {number} offset
* @return {ContentString}
*/
splice(offset: number): ContentString;
/**
* @param {ContentString} right
* @return {boolean}
*/
mergeWith(right: ContentString): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentString(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentString;
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

82
dist/src/structs/ContentType.d.ts vendored Normal file
View File

@ -0,0 +1,82 @@
/**
* @type {Array<function(UpdateDecoderV1 | UpdateDecoderV2):AbstractType<any>>}
* @private
*/
export const typeRefs: Array<(arg0: UpdateDecoderV1 | UpdateDecoderV2) => AbstractType<any>>;
export const YArrayRefID: 0;
export const YMapRefID: 1;
export const YTextRefID: 2;
export const YXmlElementRefID: 3;
export const YXmlFragmentRefID: 4;
export const YXmlHookRefID: 5;
export const YXmlTextRefID: 6;
/**
* @private
*/
export class ContentType {
/**
* @param {AbstractType<any>} type
*/
constructor(type: AbstractType<any>);
/**
* @type {AbstractType<any>}
*/
type: AbstractType<any>;
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {ContentType}
*/
copy(): ContentType;
/**
* @param {number} offset
* @return {ContentType}
*/
splice(offset: number): ContentType;
/**
* @param {ContentType} right
* @return {boolean}
*/
mergeWith(right: ContentType): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
export function readContentType(decoder: UpdateDecoderV1 | UpdateDecoderV2): ContentType;
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";
import { AbstractType } from "../types/AbstractType.js";
import { Transaction } from "../utils/Transaction.js";
import { Item } from "./Item.js";
import { StructStore } from "../utils/StructStore.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";

28
dist/src/structs/GC.d.ts vendored Normal file
View File

@ -0,0 +1,28 @@
export const structGCRefNumber: 0;
/**
* @private
*/
export class GC extends AbstractStruct {
delete(): void;
/**
* @param {GC} right
* @return {boolean}
*/
mergeWith(right: GC): boolean;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @param {Transaction} transaction
* @param {StructStore} store
* @return {null | number}
*/
getMissing(transaction: Transaction, store: StructStore): null | number;
}
import { AbstractStruct } from "./AbstractStruct.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { Transaction } from "../utils/Transaction.js";
import { StructStore } from "../utils/StructStore.js";

217
dist/src/structs/Item.d.ts vendored Normal file
View File

@ -0,0 +1,217 @@
export function followRedone(store: StructStore, id: ID): {
item: Item;
diff: number;
};
export function keepItem(item: Item | null, keep: boolean): void;
export function splitItem(transaction: Transaction, leftItem: Item, diff: number): Item;
export function redoItem(transaction: Transaction, item: Item, redoitems: Set<Item>, itemsToDelete: DeleteSet, ignoreRemoteMapChanges: boolean): Item | null;
/**
* Abstract class that represents any content.
*/
export 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(id: ID, left: Item | null, origin: ID | null, right: Item | null, rightOrigin: ID | null, parent: AbstractType<any> | ID | null, parentSub: string | null, content: AbstractContent);
/**
* The item that was originally to the left of this item.
* @type {ID | null}
*/
origin: ID | null;
/**
* The item that is currently to the left of this item.
* @type {Item | null}
*/
left: Item | null;
/**
* The item that is currently to the right of this item.
* @type {Item | null}
*/
right: Item | null;
/**
* The item that was originally to the right of this item.
* @type {ID | null}
*/
rightOrigin: ID | null;
/**
* @type {AbstractType<any>|ID|null}
*/
parent: AbstractType<any> | ID | null;
/**
* If the parent refers to this item with some kind of key (e.g. YMap, the
* key is specified here. The key is then used to refer to the list in which
* to insert this item. If `parentSub = null` type._start is the list in
* which to insert to. Otherwise it is `parent._map`.
* @type {String | null}
*/
parentSub: string | null;
/**
* If this type's effect is redone this type refers to the type that undid
* this operation.
* @type {ID | null}
*/
redone: ID | null;
/**
* @type {AbstractContent}
*/
content: AbstractContent;
/**
* bit1: keep
* bit2: countable
* bit3: deleted
* bit4: mark - mark node as fast-search-marker
* @type {number} byte
*/
info: number;
/**
* This is used to mark the item as an indexed fast-search marker
*
* @type {boolean}
*/
set marker(arg: boolean);
get marker(): boolean;
set keep(arg: boolean);
/**
* If true, do not garbage collect this Item.
*/
get keep(): boolean;
get countable(): boolean;
set deleted(arg: boolean);
/**
* Whether this item was deleted or not.
* @type {Boolean}
*/
get deleted(): boolean;
markDeleted(): void;
/**
* 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: Transaction, store: StructStore): null | number;
/**
* Returns the next non-deleted item
*/
get next(): Item | null;
/**
* Returns the previous non-deleted item
*/
get prev(): Item | null;
/**
* Computes the last content address of this Item.
*/
get lastId(): ID;
/**
* Try to merge two items
*
* @param {Item} right
* @return {boolean}
*/
mergeWith(right: Item): boolean;
/**
* Mark this Item as deleted.
*
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
* @param {boolean} parentGCd
*/
gc(store: StructStore, parentGCd: boolean): void;
/**
* 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: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
}
export function readItemContent(decoder: UpdateDecoderV1 | UpdateDecoderV2, info: number): AbstractContent;
/**
* A lookup map for reading Item content.
*
* @type {Array<function(UpdateDecoderV1 | UpdateDecoderV2):AbstractContent>}
*/
export const contentRefs: Array<(arg0: UpdateDecoderV1 | UpdateDecoderV2) => AbstractContent>;
/**
* Do not implement this class!
*/
export class AbstractContent {
/**
* @return {number}
*/
getLength(): number;
/**
* @return {Array<any>}
*/
getContent(): Array<any>;
/**
* Should return false if this Item is some kind of meta information
* (e.g. format information).
*
* * Whether this Item should be addressable via `yarray.get(i)`
* * Whether this Item should be counted when computing yarray.length
*
* @return {boolean}
*/
isCountable(): boolean;
/**
* @return {AbstractContent}
*/
copy(): AbstractContent;
/**
* @param {number} offset
* @return {AbstractContent}
*/
splice(offset: number): AbstractContent;
/**
* @param {AbstractContent} right
* @return {boolean}
*/
mergeWith(right: AbstractContent): boolean;
/**
* @param {Transaction} transaction
* @param {Item} item
*/
integrate(transaction: Transaction, item: Item): void;
/**
* @param {Transaction} transaction
*/
delete(transaction: Transaction): void;
/**
* @param {StructStore} store
*/
gc(store: StructStore): void;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @return {number}
*/
getRef(): number;
}
import { StructStore } from "../utils/StructStore.js";
import { ID } from "../utils/ID.js";
import { Transaction } from "../utils/Transaction.js";
import { DeleteSet } from "../utils/DeleteSet.js";
import { AbstractStruct } from "./AbstractStruct.js";
import { AbstractType } from "../types/AbstractType.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

28
dist/src/structs/Skip.d.ts vendored Normal file
View File

@ -0,0 +1,28 @@
export const structSkipRefNumber: 10;
/**
* @private
*/
export class Skip extends AbstractStruct {
delete(): void;
/**
* @param {Skip} right
* @return {boolean}
*/
mergeWith(right: Skip): boolean;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
* @param {number} offset
*/
write(encoder: UpdateEncoderV1 | UpdateEncoderV2, offset: number): void;
/**
* @param {Transaction} transaction
* @param {StructStore} store
* @return {null | number}
*/
getMissing(transaction: Transaction, store: StructStore): null | number;
}
import { AbstractStruct } from "./AbstractStruct.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { Transaction } from "../utils/Transaction.js";
import { StructStore } from "../utils/StructStore.js";

160
dist/src/types/AbstractType.d.ts vendored Normal file
View File

@ -0,0 +1,160 @@
export class ArraySearchMarker {
/**
* @param {Item} p
* @param {number} index
*/
constructor(p: Item, index: number);
p: Item;
index: number;
timestamp: number;
}
export function findMarker(yarray: AbstractType<any>, index: number): ArraySearchMarker | null;
export function updateMarkerChanges(searchMarker: Array<ArraySearchMarker>, index: number, len: number): void;
export function getTypeChildren(t: AbstractType<any>): Array<Item>;
export function callTypeObservers<EventType>(type: AbstractType<EventType>, transaction: Transaction, event: EventType): void;
/**
* @template EventType
* Abstract Yjs Type class
*/
export class AbstractType<EventType> {
/**
* @type {Item|null}
*/
_item: Item | null;
/**
* @type {Map<string,Item>}
*/
_map: Map<string, Item>;
/**
* @type {Item|null}
*/
_start: Item | null;
/**
* @type {Doc|null}
*/
doc: Doc | null;
_length: number;
/**
* Event handlers
* @type {EventHandler<EventType,Transaction>}
*/
_eH: EventHandler<EventType, Transaction>;
/**
* Deep event handlers
* @type {EventHandler<Array<YEvent<any>>,Transaction>}
*/
_dEH: EventHandler<Array<YEvent<any>>, Transaction>;
/**
* @type {null | Array<ArraySearchMarker>}
*/
_searchMarker: null | Array<ArraySearchMarker>;
/**
* @return {AbstractType<any>|null}
*/
get parent(): AbstractType<any> | 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: Doc, item: Item | null): void;
/**
* @return {AbstractType<EventType>}
*/
_copy(): AbstractType<EventType>;
/**
* @return {AbstractType<EventType>}
*/
clone(): AbstractType<EventType>;
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
*/
_write(encoder: UpdateEncoderV1 | UpdateEncoderV2): void;
/**
* The first non-deleted item
*/
get _first(): Item | null;
/**
* 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: Transaction, parentSubs: Set<null | string>): void;
/**
* Observe all events that are created on this type.
*
* @param {function(EventType, Transaction):void} f Observer function
*/
observe(f: (arg0: EventType, arg1: Transaction) => void): void;
/**
* Observe all events that are created by this type and its children.
*
* @param {function(Array<YEvent<any>>,Transaction):void} f Observer function
*/
observeDeep(f: (arg0: Array<YEvent<any>>, arg1: Transaction) => void): void;
/**
* Unregister an observer function.
*
* @param {function(EventType,Transaction):void} f Observer function
*/
unobserve(f: (arg0: EventType, arg1: Transaction) => void): void;
/**
* Unregister an observer function.
*
* @param {function(Array<YEvent<any>>,Transaction):void} f Observer function
*/
unobserveDeep(f: (arg0: Array<YEvent<any>>, arg1: Transaction) => void): void;
/**
* @abstract
* @return {any}
*/
toJSON(): any;
}
export function typeListSlice(type: AbstractType<any>, start: number, end: number): Array<any>;
export function typeListToArray(type: AbstractType<any>): Array<any>;
export function typeListToArraySnapshot(type: AbstractType<any>, snapshot: Snapshot): Array<any>;
export function typeListForEach(type: AbstractType<any>, f: (arg0: any, arg1: number, arg2: any) => void): void;
export function typeListMap<C, R>(type: AbstractType<any>, f: (arg0: C, arg1: number, arg2: AbstractType<any>) => R): R[];
export function typeListCreateIterator(type: AbstractType<any>): IterableIterator<any>;
export function typeListForEachSnapshot(type: AbstractType<any>, f: (arg0: any, arg1: number, arg2: AbstractType<any>) => void, snapshot: Snapshot): void;
export function typeListGet(type: AbstractType<any>, index: number): any;
export function typeListInsertGenericsAfter(transaction: Transaction, parent: AbstractType<any>, referenceItem: Item | null, content: Array<{
[x: string]: any;
} | Array<any> | boolean | number | null | string | Uint8Array>): void;
export function typeListInsertGenerics(transaction: Transaction, parent: AbstractType<any>, index: number, content: Array<{
[x: string]: any;
} | Array<any> | number | null | string | Uint8Array>): void;
export function typeListPushGenerics(transaction: Transaction, parent: AbstractType<any>, content: Array<{
[x: string]: any;
} | Array<any> | number | null | string | Uint8Array>): void;
export function typeListDelete(transaction: Transaction, parent: AbstractType<any>, index: number, length: number): void;
export function typeMapDelete(transaction: Transaction, parent: AbstractType<any>, key: string): void;
export function typeMapSet(transaction: Transaction, parent: AbstractType<any>, key: string, value: Object | number | null | Array<any> | string | Uint8Array | AbstractType<any>): void;
export function typeMapGet(parent: AbstractType<any>, key: string): {
[x: string]: any;
} | number | null | Array<any> | string | Uint8Array | AbstractType<any> | undefined;
export function typeMapGetAll(parent: AbstractType<any>): {
[x: string]: {
[x: string]: any;
} | number | null | Array<any> | string | Uint8Array | AbstractType<any> | undefined;
};
export function typeMapHas(parent: AbstractType<any>, key: string): boolean;
export function typeMapGetSnapshot(parent: AbstractType<any>, key: string, snapshot: Snapshot): {
[x: string]: any;
} | number | null | Array<any> | string | Uint8Array | AbstractType<any> | undefined;
export function createMapIterator(map: Map<string, Item>): IterableIterator<Array<any>>;
import { Item } from "../structs/Item.js";
import { Transaction } from "../utils/Transaction.js";
import { Doc } from "../utils/Doc.js";
import { EventHandler } from "../utils/EventHandler.js";
import { YEvent } from "../utils/YEvent.js";
import { UpdateEncoderV1 } from "../utils/UpdateEncoder.js";
import { UpdateEncoderV2 } from "../utils/UpdateEncoder.js";
import { Snapshot } from "../utils/Snapshot.js";

148
dist/src/types/YArray.d.ts vendored Normal file
View File

@ -0,0 +1,148 @@
/**
* Event that describes the changes on a YArray
* @template T
* @extends YEvent<YArray<T>>
*/
export class YArrayEvent<T> extends YEvent<YArray<T>> {
/**
* @param {YArray<T>} yarray The changed type
* @param {Transaction} transaction The transaction object
*/
constructor(yarray: YArray<T>, transaction: Transaction);
_transaction: Transaction;
}
/**
* A shared Array implementation.
* @template T
* @extends AbstractType<YArrayEvent<T>>
* @implements {Iterable<T>}
*/
export class YArray<T> extends AbstractType<YArrayEvent<T>> implements Iterable<T> {
/**
* Construct a new YArray containing the specified items.
* @template T
* @param {Array<T>} items
* @return {YArray<T>}
*/
static from<T_1>(items: T_1[]): YArray<T_1>;
/**
* @type {Array<any>?}
* @private
*/
private _prelimContent;
/**
* @type {Array<ArraySearchMarker>}
*/
_searchMarker: Array<ArraySearchMarker>;
/**
* 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: Doc, item: Item): void;
_copy(): YArray<any>;
/**
* @return {YArray<T>}
*/
clone(): YArray<T>;
get length(): number;
/**
* 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: number, content: Array<T>): void;
/**
* Appends content to this YArray.
*
* @param {Array<T>} content Array of content to append.
*
* @todo Use the following implementation in all types.
*/
push(content: Array<T>): void;
/**
* Preppends content to this YArray.
*
* @param {Array<T>} content Array of content to preppend.
*/
unshift(content: Array<T>): void;
/**
* 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: number, length?: number): void;
/**
* 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: number): T;
/**
* Transforms this YArray to a JavaScript Array.
*
* @return {Array<T>}
*/
toArray(): Array<T>;
/**
* Transforms this YArray to a JavaScript Array.
*
* @param {number} [start]
* @param {number} [end]
* @return {Array<T>}
*/
slice(start?: number | undefined, end?: number | undefined): Array<T>;
/**
* Transforms this Shared Type to a JSON object.
*
* @return {Array<any>}
*/
toJSON(): Array<any>;
/**
* 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<M>(f: (arg0: T, arg1: number, arg2: YArray<T>) => M): M[];
/**
* Executes a provided function on once on overy element of this YArray.
*
* @param {function(T,number,YArray<T>):void} f A function to execute on every element of this YArray.
*/
forEach(f: (arg0: T, arg1: number, arg2: YArray<T>) => void): void;
/**
* @return {IterableIterator<T>}
*/
[Symbol.iterator](): IterableIterator<T>;
}
export function readYArray(decoder: UpdateDecoderV1 | UpdateDecoderV2): YArray<any>;
import { YEvent } from "../utils/YEvent.js";
import { Transaction } from "../utils/Transaction.js";
import { AbstractType } from "./AbstractType.js";
import { ArraySearchMarker } from "./AbstractType.js";
import { Doc } from "../utils/Doc.js";
import { Item } from "../structs/Item.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

132
dist/src/types/YMap.d.ts vendored Normal file
View File

@ -0,0 +1,132 @@
/**
* @template T
* @extends YEvent<YMap<T>>
* Event that describes the changes on a YMap.
*/
export class YMapEvent<T> extends YEvent<YMap<T>> {
/**
* @param {YMap<T>} ymap The YArray that changed.
* @param {Transaction} transaction
* @param {Set<any>} subs The keys that changed.
*/
constructor(ymap: YMap<T>, transaction: Transaction, subs: Set<any>);
keysChanged: Set<any>;
}
/**
* @template MapType
* A shared Map implementation.
*
* @extends AbstractType<YMapEvent<MapType>>
* @implements {Iterable<MapType>}
*/
export class YMap<MapType> extends AbstractType<YMapEvent<MapType>> implements Iterable<MapType> {
/**
*
* @param {Iterable<readonly [string, any]>=} entries - an optional iterable to initialize the YMap
*/
constructor(entries?: Iterable<readonly [string, any]> | undefined);
/**
* @type {Map<string,any>?}
* @private
*/
private _prelimContent;
/**
* 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: Doc, item: Item): void;
_copy(): YMap<any>;
/**
* @return {YMap<MapType>}
*/
clone(): YMap<MapType>;
/**
* Transforms this Shared Type to a JSON object.
*
* @return {Object<string,any>}
*/
toJSON(): {
[x: string]: any;
};
/**
* Returns the size of the YMap (count of key/value pairs)
*
* @return {number}
*/
get size(): number;
/**
* Returns the keys for each element in the YMap Type.
*
* @return {IterableIterator<string>}
*/
keys(): IterableIterator<string>;
/**
* Returns the values for each element in the YMap Type.
*
* @return {IterableIterator<any>}
*/
values(): IterableIterator<any>;
/**
* Returns an Iterator of [key, value] pairs
*
* @return {IterableIterator<any>}
*/
entries(): IterableIterator<any>;
/**
* 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: (arg0: MapType, arg1: string, arg2: YMap<MapType>) => void): void;
/**
* Remove a specified element from this YMap.
*
* @param {string} key The key of the element to remove.
*/
delete(key: string): void;
/**
* Adds or updates an element with a specified key and value.
*
* @param {string} key The key of the element to add to this YMap
* @param {MapType} value The value of the element to add
*/
set(key: string, value: MapType): MapType;
/**
* Returns a specified element from this YMap.
*
* @param {string} key
* @return {MapType|undefined}
*/
get(key: string): MapType | undefined;
/**
* Returns a boolean indicating whether the specified key exists or not.
*
* @param {string} key The key to test.
* @return {boolean}
*/
has(key: string): boolean;
/**
* Removes all elements from this YMap.
*/
clear(): void;
/**
* Returns an Iterator of [key, value] pairs
*
* @return {IterableIterator<any>}
*/
[Symbol.iterator](): IterableIterator<any>;
}
export function readYMap(decoder: UpdateDecoderV1 | UpdateDecoderV2): YMap<any>;
import { YEvent } from "../utils/YEvent.js";
import { Transaction } from "../utils/Transaction.js";
import { AbstractType } from "./AbstractType.js";
import { Doc } from "../utils/Doc.js";
import { Item } from "../structs/Item.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

256
dist/src/types/YText.d.ts vendored Normal file
View File

@ -0,0 +1,256 @@
export class ItemTextListPosition {
/**
* @param {Item|null} left
* @param {Item|null} right
* @param {number} index
* @param {Map<string,any>} currentAttributes
*/
constructor(left: Item | null, right: Item | null, index: number, currentAttributes: Map<string, any>);
left: Item | null;
right: Item | null;
index: number;
currentAttributes: Map<string, any>;
/**
* Only call this if you know that this.right is defined
*/
forward(): void;
}
export function cleanupYTextFormatting(type: YText): number;
/**
* The Quill Delta format represents changes on a text document with
* formatting information. For mor information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
*
* @example
* {
* ops: [
* { insert: 'Gandalf', attributes: { bold: true } },
* { insert: ' the ' },
* { insert: 'Grey', attributes: { color: '#cccccc' } }
* ]
* }
*
*/
/**
* Attributes that can be assigned to a selection of text.
*
* @example
* {
* bold: true,
* font-size: '40px'
* }
*
* @typedef {Object} TextAttributes
*/
/**
* @extends YEvent<YText>
* Event that describes the changes on a YText type.
*/
export class YTextEvent extends YEvent<YText> {
/**
* @param {YText} ytext
* @param {Transaction} transaction
* @param {Set<any>} subs The keys that changed
*/
constructor(ytext: YText, transaction: Transaction, subs: Set<any>);
/**
* Whether the children changed.
* @type {Boolean}
* @private
*/
private childListChanged;
/**
* Set of all changed attributes.
* @type {Set<string>}
*/
keysChanged: Set<string>;
/**
* 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
*/
public get delta(): {
insert?: string | object | AbstractType<any> | undefined;
delete?: number | undefined;
retain?: number | undefined;
attributes?: {
[x: string]: any;
} | undefined;
}[];
}
/**
* Type that represents text with formatting information.
*
* This type replaces y-richtext as this implementation is able to handle
* block formats (format information on a paragraph), embeds (complex elements
* like pictures and videos), and text formats (**bold**, *italic*).
*
* @extends AbstractType<YTextEvent>
*/
export class YText extends AbstractType<YTextEvent> {
/**
* @param {String} [string] The initial value of the YText.
*/
constructor(string?: string | undefined);
/**
* Array of pending operations on this type
* @type {Array<function():void>?}
*/
_pending: (() => void)[] | null;
/**
* @type {Array<ArraySearchMarker>}
*/
_searchMarker: Array<ArraySearchMarker>;
/**
* Number of characters of this text type.
*
* @type {number}
*/
get length(): number;
/**
* @param {Doc} y
* @param {Item} item
*/
_integrate(y: Doc, item: Item): void;
_copy(): YText;
/**
* @return {YText}
*/
clone(): YText;
/**
* Returns the unformatted string representation of this YText type.
*
* @return {string}
* @public
*/
public toJSON(): string;
/**
* Apply a {@link Delta} on this shared YText type.
*
* @param {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
*/
public applyDelta(delta: any, { sanitize }?: {
sanitize?: boolean | undefined;
} | undefined): void;
/**
* 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
*/
public toDelta(snapshot?: Snapshot | undefined, prevSnapshot?: Snapshot | undefined, computeYChange?: ((arg0: 'removed' | 'added', arg1: ID) => any) | undefined): any;
/**
* 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
*/
public insert(index: number, text: string, attributes?: Object | undefined): void;
/**
* 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
*/
public insertEmbed(index: number, embed: Object | AbstractType<any>, attributes?: TextAttributes): void;
/**
* 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
*/
public delete(index: number, length: number): void;
/**
* 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
*/
public format(index: number, length: number, attributes: TextAttributes): void;
/**
* 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
*/
public removeAttribute(attributeName: string): void;
/**
* 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
*/
public setAttribute(attributeName: string, attributeValue: any): void;
/**
* 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
*/
public getAttribute(attributeName: string): any;
/**
* 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.
*
* @param {Snapshot} [snapshot]
* @return {Object<string, any>} A JSON Object that describes the attributes.
*
* @public
*/
public getAttributes(snapshot?: Snapshot | undefined): {
[x: string]: any;
};
}
export function readYText(decoder: UpdateDecoderV1 | UpdateDecoderV2): YText;
/**
* Attributes that can be assigned to a selection of text.
*/
export type TextAttributes = Object;
import { Item } from "../structs/Item.js";
import { YEvent } from "../utils/YEvent.js";
import { AbstractType } from "./AbstractType.js";
import { Transaction } from "../utils/Transaction.js";
import { ArraySearchMarker } from "./AbstractType.js";
import { Doc } from "../utils/Doc.js";
import { Snapshot } from "../utils/Snapshot.js";
import { ID } from "../utils/ID.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

84
dist/src/types/YXmlElement.d.ts vendored Normal file
View File

@ -0,0 +1,84 @@
/**
* An YXmlElement imitates the behavior of a
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}.
*
* * An YXmlElement has attributes (key value pairs)
* * An YXmlElement has childElements that must inherit from YXmlElement
*/
export class YXmlElement extends YXmlFragment {
constructor(nodeName?: string);
nodeName: string;
/**
* @type {Map<string, any>|null}
*/
_prelimAttrs: Map<string, any> | null;
/**
* @type {YXmlElement|YXmlText|null}
*/
get nextSibling(): YXmlElement | YXmlText | null;
/**
* @type {YXmlElement|YXmlText|null}
*/
get prevSibling(): YXmlElement | YXmlText | null;
/**
* Creates an Item with the same effect as this Item (without position effect)
*
* @return {YXmlElement}
*/
_copy(): YXmlElement;
/**
* @return {YXmlElement}
*/
clone(): YXmlElement;
/**
* Removes an attribute from this YXmlElement.
*
* @param {String} attributeName The attribute name that is to be removed.
*
* @public
*/
public removeAttribute(attributeName: string): void;
/**
* Sets or updates an attribute.
*
* @param {String} attributeName The attribute name that is to be set.
* @param {String} attributeValue The attribute value that is to be set.
*
* @public
*/
public setAttribute(attributeName: string, attributeValue: string): void;
/**
* Returns an attribute value that belongs to the attribute name.
*
* @param {String} attributeName The attribute name that identifies the
* queried value.
* @return {String} The queried attribute value.
*
* @public
*/
public getAttribute(attributeName: string): string;
/**
* Returns whether an attribute exists
*
* @param {String} attributeName The attribute name to check for existence.
* @return {boolean} whether the attribute exists.
*
* @public
*/
public hasAttribute(attributeName: string): boolean;
/**
* Returns all attribute name/value pairs in a JSON Object.
*
* @return {Object<string, any>} A JSON Object that describes the attributes.
*
* @public
*/
public getAttributes(): {
[x: string]: any;
};
}
export function readYXmlElement(decoder: UpdateDecoderV1 | UpdateDecoderV2): YXmlElement;
import { YXmlFragment } from "./YXmlFragment.js";
import { YXmlText } from "./YXmlText.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

30
dist/src/types/YXmlEvent.d.ts vendored Normal file
View File

@ -0,0 +1,30 @@
/**
* @extends YEvent<YXmlElement|YXmlText|YXmlFragment>
* An Event that describes changes on a YXml Element or Yxml Fragment
*/
export class YXmlEvent extends YEvent<YXmlFragment | YXmlElement | YXmlText> {
/**
* @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 wich the
* change was created.
*/
constructor(target: YXmlElement | YXmlText | YXmlFragment, subs: Set<string | null>, transaction: Transaction);
/**
* Whether the children changed.
* @type {Boolean}
* @private
*/
private childListChanged;
/**
* Set of all changed attributes.
* @type {Set<string>}
*/
attributesChanged: Set<string>;
}
import { YXmlFragment } from "./YXmlFragment.js";
import { YXmlElement } from "./YXmlElement.js";
import { YXmlText } from "./YXmlText.js";
import { YEvent } from "../utils/YEvent.js";
import { Transaction } from "../utils/Transaction.js";

243
dist/src/types/YXmlFragment.d.ts vendored Normal file
View File

@ -0,0 +1,243 @@
/**
* Define the elements to which a set of CSS queries apply.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|CSS_Selectors}
*
* @example
* query = '.classSelector'
* query = 'nodeSelector'
* query = '#idSelector'
*
* @typedef {string} CSS_Selector
*/
/**
* Dom filter function.
*
* @callback domFilter
* @param {string} nodeName The nodeName of the element
* @param {Map} attributes The map of attributes.
* @return {boolean} Whether to include the Dom node in the YXmlElement.
*/
/**
* Represents a subset of the nodes of a YXmlElement / YXmlFragment and a
* position within them.
*
* Can be created with {@link YXmlFragment#createTreeWalker}
*
* @public
* @implements {Iterable<YXmlElement|YXmlText|YXmlElement|YXmlHook>}
*/
export class YXmlTreeWalker implements Iterable<YXmlElement | YXmlText | YXmlElement | YXmlHook> {
/**
* @param {YXmlFragment | YXmlElement} root
* @param {function(AbstractType<any>):boolean} [f]
*/
constructor(root: YXmlFragment | YXmlElement, f?: ((arg0: AbstractType<any>) => boolean) | undefined);
_filter: (arg0: AbstractType<any>) => boolean;
_root: YXmlFragment | YXmlElement;
/**
* @type {Item}
*/
_currentNode: Item;
_firstCall: boolean;
/**
* Get the next node.
*
* @return {IteratorResult<YXmlElement|YXmlText|YXmlHook>} The next node.
*
* @public
*/
public next(): IteratorResult<YXmlElement | YXmlText | YXmlHook>;
[Symbol.iterator](): YXmlTreeWalker;
}
/**
* Represents a list of {@link YXmlElement}.and {@link YXmlText} types.
* A YxmlFragment is similar to a {@link YXmlElement}, but it does not have a
* nodeName and it does not have attributes. Though it can be bound to a DOM
* element - in this case the attributes and the nodeName are not shared.
*
* @public
* @extends AbstractType<YXmlEvent>
*/
export class YXmlFragment extends AbstractType<YXmlEvent> {
constructor();
/**
* @type {Array<any>|null}
*/
_prelimContent: Array<any> | null;
/**
* @type {YXmlElement|YXmlText|null}
*/
get firstChild(): YXmlElement | YXmlText | 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: Doc, item: Item): void;
_copy(): YXmlFragment;
/**
* @return {YXmlFragment}
*/
clone(): YXmlFragment;
get length(): number;
/**
* 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
*/
public createTreeWalker(filter: (arg0: AbstractType<any>) => boolean): YXmlTreeWalker;
/**
* 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
*/
public querySelector(query: CSS_Selector): YXmlElement | YXmlText | YXmlHook | null;
/**
* 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
*/
public querySelectorAll(query: CSS_Selector): Array<YXmlElement | YXmlText | YXmlHook | null>;
/**
* @return {string}
*/
toJSON(): string;
/**
* 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
*/
public toDOM(_document?: Document | undefined, hooks?: {
[x: string]: any;
} | undefined, binding?: any): Node;
/**
* 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: number, content: Array<YXmlElement | YXmlText>): void;
/**
* 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: null | Item | YXmlElement | YXmlText, content: Array<YXmlElement | YXmlText>): void;
/**
* 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: number, length?: number | undefined): void;
/**
* Transforms this YArray to a JavaScript Array.
*
* @return {Array<YXmlElement|YXmlText|YXmlHook>}
*/
toArray(): Array<YXmlElement | YXmlText | YXmlHook>;
/**
* Appends content to this YArray.
*
* @param {Array<YXmlElement|YXmlText>} content Array of content to append.
*/
push(content: Array<YXmlElement | YXmlText>): void;
/**
* Preppends content to this YArray.
*
* @param {Array<YXmlElement|YXmlText>} content Array of content to preppend.
*/
unshift(content: Array<YXmlElement | YXmlText>): void;
/**
* 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: number): YXmlElement | YXmlText;
/**
* Transforms this YArray to a JavaScript Array.
*
* @param {number} [start]
* @param {number} [end]
* @return {Array<YXmlElement|YXmlText>}
*/
slice(start?: number | undefined, end?: number | undefined): Array<YXmlElement | YXmlText>;
/**
* Executes a provided function on once on overy child element.
*
* @param {function(YXmlElement|YXmlText,number, typeof this):void} f A function to execute on every element of this YArray.
*/
forEach(f: (arg0: YXmlElement | YXmlText, arg1: number, arg2: YXmlFragment) => void): void;
}
export function readYXmlFragment(decoder: UpdateDecoderV1 | UpdateDecoderV2): YXmlFragment;
/**
* Define the elements to which a set of CSS queries apply.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|CSS_Selectors}
*/
export type CSS_Selector = string;
/**
* Dom filter function.
*/
export type domFilter = (nodeName: string, attributes: Map<any, any>) => boolean;
import { YXmlElement } from "./YXmlElement.js";
import { YXmlText } from "./YXmlText.js";
import { YXmlHook } from "./YXmlHook.js";
import { AbstractType } from "./AbstractType.js";
import { Item } from "../structs/Item.js";
import { YXmlEvent } from "./YXmlEvent.js";
import { Doc } from "../utils/Doc.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

45
dist/src/types/YXmlHook.d.ts vendored Normal file
View File

@ -0,0 +1,45 @@
/**
* You can manage binding to a custom type with YXmlHook.
*
* @extends {YMap<any>}
*/
export class YXmlHook extends YMap<any> {
/**
* @param {string} hookName nodeName of the Dom Node.
*/
constructor(hookName: string);
/**
* @type {string}
*/
hookName: string;
/**
* Creates an Item with the same effect as this Item (without position effect)
*/
_copy(): YXmlHook;
/**
* @return {YXmlHook}
*/
clone(): YXmlHook;
/**
* 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
*/
public toDOM(_document?: Document | undefined, hooks?: {
[x: string]: any;
} | undefined, binding?: any): Element;
}
export function readYXmlHook(decoder: UpdateDecoderV1 | UpdateDecoderV2): YXmlHook;
import { YMap } from "./YMap.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

43
dist/src/types/YXmlText.d.ts vendored Normal file
View File

@ -0,0 +1,43 @@
/**
* Represents text in a Dom Element. In the future this type will also handle
* simple formatting information like bold and italic.
*/
export class YXmlText extends YText {
/**
* @type {YXmlElement|YXmlText|null}
*/
get nextSibling(): YXmlElement | YXmlText | null;
/**
* @type {YXmlElement|YXmlText|null}
*/
get prevSibling(): YXmlElement | YXmlText | null;
_copy(): YXmlText;
/**
* @return {YXmlText}
*/
clone(): YXmlText;
/**
* 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
*/
public toDOM(_document?: Document | undefined, hooks?: {
[x: string]: any;
} | undefined, binding?: any): Text;
toString(): any;
}
export function readYXmlText(decoder: UpdateDecoderV1 | UpdateDecoderV2): YXmlText;
import { YText } from "./YText.js";
import { YXmlElement } from "./YXmlElement.js";
import { UpdateDecoderV1 } from "../utils/UpdateDecoder.js";
import { UpdateDecoderV2 } from "../utils/UpdateDecoder.js";

19
dist/src/utils/AbstractConnector.d.ts vendored Normal file
View File

@ -0,0 +1,19 @@
/**
* This is an abstract interface that all Connectors should implement to keep them interchangeable.
*
* @note This interface is experimental and it is not advised to actually inherit this class.
* It just serves as typing information.
*
* @extends {Observable<any>}
*/
export class AbstractConnector extends Observable<any> {
/**
* @param {Doc} ydoc
* @param {any} awareness
*/
constructor(ydoc: Doc, awareness: any);
doc: Doc;
awareness: any;
}
import { Observable } from "lib0/observable";
import { Doc } from "./Doc.js";

48
dist/src/utils/DeleteSet.d.ts vendored Normal file
View File

@ -0,0 +1,48 @@
export class DeleteItem {
/**
* @param {number} clock
* @param {number} len
*/
constructor(clock: number, len: number);
/**
* @type {number}
*/
clock: number;
/**
* @type {number}
*/
len: number;
}
/**
* We no longer maintain a DeleteStore. DeleteSet is a temporary object that is created when needed.
* - When created in a transaction, it must only be accessed after sorting, and merging
* - This DeleteSet is send to other clients
* - We do not create a DeleteSet when we send a sync message. The DeleteSet message is created directly from StructStore
* - We read a DeleteSet as part of a sync/update message. In this case the DeleteSet is already sorted and merged.
*/
export class DeleteSet {
/**
* @type {Map<number,Array<DeleteItem>>}
*/
clients: Map<number, Array<DeleteItem>>;
}
export function iterateDeletedStructs(transaction: Transaction, ds: DeleteSet, f: (arg0: GC | Item) => void): void;
export function findIndexDS(dis: Array<DeleteItem>, clock: number): number | null;
export function isDeleted(ds: DeleteSet, id: ID): boolean;
export function sortAndMergeDeleteSet(ds: DeleteSet): void;
export function mergeDeleteSets(dss: Array<DeleteSet>): DeleteSet;
export function addToDeleteSet(ds: DeleteSet, client: number, clock: number, length: number): void;
export function createDeleteSet(): DeleteSet;
export function createDeleteSetFromStructStore(ss: StructStore): DeleteSet;
export function writeDeleteSet(encoder: DSEncoderV1 | DSEncoderV2, ds: DeleteSet): void;
export function readDeleteSet(decoder: DSDecoderV1 | DSDecoderV2): DeleteSet;
export function readAndApplyDeleteSet(decoder: DSDecoderV1 | DSDecoderV2, transaction: Transaction, store: StructStore): Uint8Array | null;
import { Transaction } from "./Transaction.js";
import { GC } from "../structs/GC.js";
import { Item } from "../structs/Item.js";
import { ID } from "./ID.js";
import { StructStore } from "./StructStore.js";
import { DSEncoderV1 } from "./UpdateEncoder.js";
import { DSEncoderV2 } from "./UpdateEncoder.js";
import { DSDecoderV1 } from "./UpdateDecoder.js";
import { DSDecoderV2 } from "./UpdateDecoder.js";

189
dist/src/utils/Doc.d.ts vendored Normal file
View File

@ -0,0 +1,189 @@
export const generateNewClientId: typeof random.uint32;
/**
* @typedef {Object} DocOpts
* @property {boolean} [DocOpts.gc=true] Disable garbage collection (default: gc=true)
* @property {function(Item):boolean} [DocOpts.gcFilter] Will be called before an Item is garbage collected. Return false to keep the Item.
* @property {string} [DocOpts.guid] Define a globally unique identifier for this document
* @property {string | null} [DocOpts.collectionid] Associate this document with a collection. This only plays a role if your provider has a concept of collection.
* @property {any} [DocOpts.meta] Any kind of meta information you want to associate with this document. If this is a subdocument, remote peers will store the meta information as well.
* @property {boolean} [DocOpts.autoLoad] If a subdocument, automatically load document. If this is a subdocument, remote peers will load the document as well automatically.
* @property {boolean} [DocOpts.shouldLoad] Whether the document should be synced by the provider now. This is toggled to true when you call ydoc.load()
*/
/**
* A Yjs instance handles the state of shared data.
* @extends Observable<string>
*/
export class Doc extends Observable<string> {
/**
* @param {DocOpts} [opts] configuration
*/
constructor({ guid, collectionid, gc, gcFilter, meta, autoLoad, shouldLoad }?: DocOpts | undefined);
gc: boolean;
gcFilter: (arg0: Item) => boolean;
clientID: number;
guid: string;
collectionid: string | null;
/**
* @type {Map<string, AbstractType<YEvent<any>>>}
*/
share: Map<string, AbstractType<YEvent<any>>>;
store: StructStore;
/**
* @type {Transaction | null}
*/
_transaction: Transaction | null;
/**
* @type {Array<Transaction>}
*/
_transactionCleanups: Array<Transaction>;
/**
* @type {Set<Doc>}
*/
subdocs: Set<Doc>;
/**
* If this document is a subdocument - a document integrated into another document - then _item is defined.
* @type {Item?}
*/
_item: Item | null;
shouldLoad: boolean;
autoLoad: boolean;
meta: any;
isLoaded: boolean;
whenLoaded: Promise<any>;
/**
* 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(): void;
getSubdocs(): Set<Doc>;
getSubdocGuids(): Set<string>;
/**
* 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.
*
* @param {function(Transaction):void} 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
*
* @public
*/
public transact(f: (arg0: Transaction) => void, origin?: any): void;
/**
* Define a shared data type.
*
* Multiple calls of `y.get(name, TypeConstructor)` yield the same result
* and do not overwrite each other. I.e.
* `y.define(name, Y.Array) === y.define(name, Y.Array)`
*
* After this method is called, the type is also available on `y.share.get(name)`.
*
* *Best Practices:*
* Define all types right after the Yjs instance is created and store them in a separate object.
* Also use the typed methods `getText(name)`, `getArray(name)`, ..
*
* @example
* const y = new Y(..)
* const appState = {
* document: y.getText('document')
* comments: y.getArray('comments')
* }
*
* @param {string} name
* @param {Function} TypeConstructor The constructor of the type definition. E.g. Y.Text, Y.Array, Y.Map, ...
* @return {AbstractType<any>} The created type. Constructed with TypeConstructor
*
* @public
*/
public get(name: string, TypeConstructor?: Function): AbstractType<any>;
/**
* @template T
* @param {string} [name]
* @return {YArray<T>}
*
* @public
*/
public getArray<T>(name?: string | undefined): YArray<T>;
/**
* @param {string} [name]
* @return {YText}
*
* @public
*/
public getText(name?: string | undefined): YText;
/**
* @template T
* @param {string} [name]
* @return {YMap<T>}
*
* @public
*/
public getMap<T_1>(name?: string | undefined): YMap<T_1>;
/**
* @param {string} [name]
* @return {YXmlFragment}
*
* @public
*/
public getXmlFragment(name?: string | undefined): 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(): {
[x: string]: any;
};
/**
* @param {string} eventName
* @param {function(...any):any} f
*/
on(eventName: string, f: (...args: any[]) => any): void;
}
export type DocOpts = {
/**
* Disable garbage collection (default: gc=true)
*/
gc?: boolean | undefined;
/**
* Will be called before an Item is garbage collected. Return false to keep the Item.
*/
gcFilter?: ((arg0: Item) => boolean) | undefined;
/**
* Define a globally unique identifier for this document
*/
guid?: string | undefined;
/**
* Associate this document with a collection. This only plays a role if your provider has a concept of collection.
*/
collectionid?: string | null | undefined;
/**
* Any kind of meta information you want to associate with this document. If this is a subdocument, remote peers will store the meta information as well.
*/
meta?: any;
/**
* If a subdocument, automatically load document. If this is a subdocument, remote peers will load the document as well automatically.
*/
autoLoad?: boolean | undefined;
/**
* Whether the document should be synced by the provider now. This is toggled to true when you call ydoc.load()
*/
shouldLoad?: boolean | undefined;
};
import * as random from "lib0/random";
import { Observable } from "lib0/observable";
import { Item } from "../structs/Item.js";
import { AbstractType } from "../types/AbstractType.js";
import { YEvent } from "./YEvent.js";
import { StructStore } from "./StructStore.js";
import { Transaction } from "./Transaction.js";
import { YArray } from "../types/YArray.js";
import { YText } from "../types/YText.js";
import { YMap } from "../types/YMap.js";
import { YXmlFragment } from "../types/YXmlFragment.js";

18
dist/src/utils/EventHandler.d.ts vendored Normal file
View File

@ -0,0 +1,18 @@
/**
* General event handler implementation.
*
* @template ARG0, ARG1
*
* @private
*/
export class EventHandler<ARG0, ARG1> {
/**
* @type {Array<function(ARG0, ARG1):void>}
*/
l: ((arg0: ARG0, arg1: ARG1) => void)[];
}
export function createEventHandler<ARG0, ARG1>(): EventHandler<ARG0, ARG1>;
export function addEventHandlerListener<ARG0, ARG1>(eventHandler: EventHandler<ARG0, ARG1>, f: (arg0: ARG0, arg1: ARG1) => void): number;
export function removeEventHandlerListener<ARG0, ARG1>(eventHandler: EventHandler<ARG0, ARG1>, f: (arg0: ARG0, arg1: ARG1) => void): void;
export function removeAllEventHandlerListeners<ARG0, ARG1>(eventHandler: EventHandler<ARG0, ARG1>): void;
export function callEventHandlerListeners<ARG0, ARG1>(eventHandler: EventHandler<ARG0, ARG1>, arg0: ARG0, arg1: ARG1): void;

25
dist/src/utils/ID.d.ts vendored Normal file
View File

@ -0,0 +1,25 @@
export class ID {
/**
* @param {number} client client id
* @param {number} clock unique per client id, continuous number
*/
constructor(client: number, clock: number);
/**
* Client id
* @type {number}
*/
client: number;
/**
* unique per client id, continuous number
* @type {number}
*/
clock: number;
}
export function compareIDs(a: ID | null, b: ID | null): boolean;
export function createID(client: number, clock: number): ID;
export function writeID(encoder: encoding.Encoder, id: ID): void;
export function readID(decoder: decoding.Decoder): ID;
export function findRootTypeKey(type: AbstractType<any>): string;
import * as encoding from "lib0/encoding";
import * as decoding from "lib0/decoding";
import { AbstractType } from "../types/AbstractType.js";

41
dist/src/utils/PermanentUserData.d.ts vendored Normal file
View File

@ -0,0 +1,41 @@
export class PermanentUserData {
/**
* @param {Doc} doc
* @param {YMap<any>} [storeType]
*/
constructor(doc: Doc, storeType?: YMap<any> | undefined);
yusers: YMap<any>;
doc: Doc;
/**
* Maps from clientid to userDescription
*
* @type {Map<number,string>}
*/
clients: Map<number, string>;
dss: Map<string, DeleteSet>;
/**
* @param {Doc} doc
* @param {number} clientid
* @param {string} userDescription
* @param {Object} [conf]
* @param {function(Transaction, DeleteSet):boolean} [conf.filter]
*/
setUserMapping(doc: Doc, clientid: number, userDescription: string, { filter }?: {
filter?: ((arg0: Transaction, arg1: DeleteSet) => boolean) | undefined;
} | undefined): void;
/**
* @param {number} clientid
* @return {any}
*/
getUserByClientId(clientid: number): any;
/**
* @param {ID} id
* @return {string | null}
*/
getUserByDeletedId(id: ID): string | null;
}
import { YMap } from "../types/YMap.js";
import { Doc } from "./Doc.js";
import { DeleteSet } from "./DeleteSet.js";
import { Transaction } from "./Transaction.js";
import { ID } from "./ID.js";

90
dist/src/utils/RelativePosition.d.ts vendored Normal file
View File

@ -0,0 +1,90 @@
/**
* A relative position is based on the Yjs model and is not affected by document changes.
* E.g. If you place a relative position before a certain character, it will always point to this character.
* If you place a relative position at the end of a type, it will always point to the end of the type.
*
* A numeric position is often unsuited for user selections, because it does not change when content is inserted
* before or after.
*
* ```Insert(0, 'x')('a|bc') = 'xa|bc'``` Where | is the relative position.
*
* One of the properties must be defined.
*
* @example
* // Current cursor position is at position 10
* const relativePosition = createRelativePositionFromIndex(yText, 10)
* // modify yText
* yText.insert(0, 'abc')
* yText.delete(3, 10)
* // Compute the cursor position
* const absolutePosition = createAbsolutePositionFromRelativePosition(y, relativePosition)
* absolutePosition.type === yText // => true
* console.log('cursor location is ' + absolutePosition.index) // => cursor location is 3
*
*/
export class RelativePosition {
/**
* @param {ID|null} type
* @param {string|null} tname
* @param {ID|null} item
* @param {number} assoc
*/
constructor(type: ID | null, tname: string | null, item: ID | null, assoc?: number);
/**
* @type {ID|null}
*/
type: ID | null;
/**
* @type {string|null}
*/
tname: string | null;
/**
* @type {ID | null}
*/
item: ID | null;
/**
* A relative position is associated to a specific character. By default
* assoc >= 0, the relative position is associated to the character
* after the meant position.
* I.e. position 1 in 'ab' is associated to character 'b'.
*
* If assoc < 0, then the relative position is associated to the caharacter
* before the meant position.
*
* @type {number}
*/
assoc: number;
}
export function relativePositionToJSON(rpos: RelativePosition): any;
export function createRelativePositionFromJSON(json: any): RelativePosition;
export class AbsolutePosition {
/**
* @param {AbstractType<any>} type
* @param {number} index
* @param {number} [assoc]
*/
constructor(type: AbstractType<any>, index: number, assoc?: number | undefined);
/**
* @type {AbstractType<any>}
*/
type: AbstractType<any>;
/**
* @type {number}
*/
index: number;
assoc: number;
}
export function createAbsolutePosition(type: AbstractType<any>, index: number, assoc?: number | undefined): AbsolutePosition;
export function createRelativePosition(type: AbstractType<any>, item: ID | null, assoc?: number | undefined): RelativePosition;
export function createRelativePositionFromTypeIndex(type: AbstractType<any>, index: number, assoc?: number | undefined): RelativePosition;
export function writeRelativePosition(encoder: encoding.Encoder, rpos: RelativePosition): encoding.Encoder;
export function encodeRelativePosition(rpos: RelativePosition): Uint8Array;
export function readRelativePosition(decoder: decoding.Decoder): RelativePosition;
export function decodeRelativePosition(uint8Array: Uint8Array): RelativePosition;
export function createAbsolutePositionFromRelativePosition(rpos: RelativePosition, doc: Doc): AbsolutePosition | null;
export function compareRelativePositions(a: RelativePosition | null, b: RelativePosition | null): boolean;
import { ID } from "./ID.js";
import { AbstractType } from "../types/AbstractType.js";
import * as encoding from "lib0/encoding";
import * as decoding from "lib0/decoding";
import { Doc } from "./Doc.js";

35
dist/src/utils/Snapshot.d.ts vendored Normal file
View File

@ -0,0 +1,35 @@
export class Snapshot {
/**
* @param {DeleteSet} ds
* @param {Map<number,number>} sv state map
*/
constructor(ds: DeleteSet, sv: Map<number, number>);
/**
* @type {DeleteSet}
*/
ds: DeleteSet;
/**
* State Map
* @type {Map<number,number>}
*/
sv: Map<number, number>;
}
export function equalSnapshots(snap1: Snapshot, snap2: Snapshot): boolean;
export function encodeSnapshotV2(snapshot: Snapshot, encoder?: DSEncoderV1 | DSEncoderV2 | undefined): Uint8Array;
export function encodeSnapshot(snapshot: Snapshot): Uint8Array;
export function decodeSnapshotV2(buf: Uint8Array, decoder?: DSDecoderV1 | DSDecoderV2 | undefined): Snapshot;
export function decodeSnapshot(buf: Uint8Array): Snapshot;
export function createSnapshot(ds: DeleteSet, sm: Map<number, number>): Snapshot;
export const emptySnapshot: Snapshot;
export function snapshot(doc: Doc): Snapshot;
export function isVisible(item: Item, snapshot: Snapshot | undefined): boolean;
export function splitSnapshotAffectedStructs(transaction: Transaction, snapshot: Snapshot): void;
export function createDocFromSnapshot(originDoc: Doc, snapshot: Snapshot, newDoc?: Doc | undefined): Doc;
import { DeleteSet } from "./DeleteSet.js";
import { DSEncoderV1 } from "./UpdateEncoder.js";
import { DSEncoderV2 } from "./UpdateEncoder.js";
import { DSDecoderV1 } from "./UpdateDecoder.js";
import { DSDecoderV2 } from "./UpdateDecoder.js";
import { Doc } from "./Doc.js";
import { Item } from "../structs/Item.js";
import { Transaction } from "./Transaction.js";

33
dist/src/utils/StructStore.d.ts vendored Normal file
View File

@ -0,0 +1,33 @@
export class StructStore {
/**
* @type {Map<number,Array<GC|Item>>}
*/
clients: Map<number, Array<GC | Item>>;
/**
* @type {null | { missing: Map<number, number>, update: Uint8Array }}
*/
pendingStructs: {
missing: Map<number, number>;
update: Uint8Array;
} | null;
/**
* @type {null | Uint8Array}
*/
pendingDs: null | Uint8Array;
}
export function getStateVector(store: StructStore): Map<number, number>;
export function getState(store: StructStore, client: number): number;
export function integretyCheck(store: StructStore): void;
export function addStruct(store: StructStore, struct: GC | Item): void;
export function findIndexSS(structs: Array<Item | GC>, clock: number): number;
export function find(store: StructStore, id: ID): GC | Item;
export function getItem(arg0: StructStore, arg1: ID): Item;
export function findIndexCleanStart(transaction: Transaction, structs: Array<Item | GC>, clock: number): number;
export function getItemCleanStart(transaction: Transaction, id: ID): Item;
export function getItemCleanEnd(transaction: Transaction, store: StructStore, id: ID): Item;
export function replaceStruct(store: StructStore, struct: GC | Item, newStruct: GC | Item): void;
export function iterateStructs(transaction: Transaction, structs: Array<Item | GC>, clockStart: number, len: number, f: (arg0: GC | Item) => void): void;
import { GC } from "../structs/GC.js";
import { Item } from "../structs/Item.js";
import { ID } from "./ID.js";
import { Transaction } from "./Transaction.js";

109
dist/src/utils/Transaction.d.ts vendored Normal file
View File

@ -0,0 +1,109 @@
/**
* A transaction is created for every change on the Yjs model. It is possible
* to bundle changes on the Yjs model in a single transaction to
* minimize the number on messages sent and the number of observer calls.
* If possible the user of this library should bundle as many changes as
* possible. Here is an example to illustrate the advantages of bundling:
*
* @example
* const map = y.define('map', YMap)
* // Log content when change is triggered
* map.observe(() => {
* console.log('change triggered')
* })
* // Each change on the map type triggers a log message:
* map.set('a', 0) // => "change triggered"
* map.set('b', 0) // => "change triggered"
* // When put in a transaction, it will trigger the log after the transaction:
* y.transact(() => {
* map.set('a', 1)
* map.set('b', 1)
* }) // => "change triggered"
*
* @public
*/
export class Transaction {
/**
* @param {Doc} doc
* @param {any} origin
* @param {boolean} local
*/
constructor(doc: Doc, origin: any, local: boolean);
/**
* The Yjs instance.
* @type {Doc}
*/
doc: Doc;
/**
* Describes the set of deleted items by ids
* @type {DeleteSet}
*/
deleteSet: DeleteSet;
/**
* Holds the state before the transaction started.
* @type {Map<Number,Number>}
*/
beforeState: Map<number, number>;
/**
* Holds the state after the transaction.
* @type {Map<Number,Number>}
*/
afterState: Map<number, number>;
/**
* All types that were directly modified (property added or child
* inserted/deleted). New types are not included in this Set.
* Maps from type to parentSubs (`item.parentSub = null` for YArray)
* @type {Map<AbstractType<YEvent<any>>,Set<String|null>>}
*/
changed: Map<AbstractType<YEvent<any>>, Set<string | null>>;
/**
* Stores the events for the types that observe also child elements.
* It is mainly used by `observeDeep`.
* @type {Map<AbstractType<YEvent<any>>,Array<YEvent<any>>>}
*/
changedParentTypes: Map<AbstractType<YEvent<any>>, Array<YEvent<any>>>;
/**
* @type {Array<AbstractStruct>}
*/
_mergeStructs: Array<AbstractStruct>;
/**
* @type {any}
*/
origin: any;
/**
* Stores meta information on the transaction
* @type {Map<any,any>}
*/
meta: Map<any, any>;
/**
* Whether this change originates from this doc.
* @type {boolean}
*/
local: boolean;
/**
* @type {Set<Doc>}
*/
subdocsAdded: Set<Doc>;
/**
* @type {Set<Doc>}
*/
subdocsRemoved: Set<Doc>;
/**
* @type {Set<Doc>}
*/
subdocsLoaded: Set<Doc>;
}
export function writeUpdateMessageFromTransaction(encoder: UpdateEncoderV1 | UpdateEncoderV2, transaction: Transaction): boolean;
export function nextID(transaction: Transaction): import("./ID.js").ID;
export function addChangedTypeToTransaction(transaction: Transaction, type: AbstractType<YEvent<any>>, parentSub: string | null): void;
export function tryGc(ds: DeleteSet, store: StructStore, gcFilter: (arg0: Item) => boolean): void;
export function transact(doc: Doc, f: (arg0: Transaction) => void, origin?: any, local?: boolean): void;
import { Doc } from "./Doc.js";
import { DeleteSet } from "./DeleteSet.js";
import { AbstractType } from "../types/AbstractType.js";
import { YEvent } from "./YEvent.js";
import { AbstractStruct } from "../structs/AbstractStruct.js";
import { UpdateEncoderV1 } from "./UpdateEncoder.js";
import { UpdateEncoderV2 } from "./UpdateEncoder.js";
import { StructStore } from "./StructStore.js";
import { Item } from "../structs/Item.js";

159
dist/src/utils/UndoManager.d.ts vendored Normal file
View File

@ -0,0 +1,159 @@
/**
* @typedef {Object} UndoManagerOptions
* @property {number} [UndoManagerOptions.captureTimeout=500]
* @property {function(Transaction):boolean} [UndoManagerOptions.captureTransaction] Do not capture changes of a Transaction if result false.
* @property {function(Item):boolean} [UndoManagerOptions.deleteFilter=()=>true] Sometimes
* it is necessary to filter what an Undo/Redo operation can delete. If this
* filter returns false, the type/item won't be deleted even it is in the
* undo/redo scope.
* @property {Set<any>} [UndoManagerOptions.trackedOrigins=new Set([null])]
* @property {boolean} [ignoreRemoteMapChanges] Experimental. By default, the UndoManager will never overwrite remote changes. Enable this property to enable overwriting remote changes on key-value changes (Y.Map, properties on Y.Xml, etc..).
* @property {Doc} [doc] The document that this UndoManager operates on. Only needed if typeScope is empty.
*/
/**
* Fires 'stack-item-added' event when a stack item was added to either the undo- or
* the redo-stack. You may store additional stack information via the
* metadata property on `event.stackItem.meta` (it is a `Map` of metadata properties).
* Fires 'stack-item-popped' event when a stack item was popped from either the
* undo- or the redo-stack. You may restore the saved stack information from `event.stackItem.meta`.
*
* @extends {Observable<'stack-item-added'|'stack-item-popped'|'stack-cleared'|'stack-item-updated'>}
*/
export class UndoManager extends Observable<"stack-item-added" | "stack-item-popped" | "stack-cleared" | "stack-item-updated"> {
/**
* @param {AbstractType<any>|Array<AbstractType<any>>} typeScope Accepts either a single type, or an array of types
* @param {UndoManagerOptions} options
*/
constructor(typeScope: AbstractType<any> | Array<AbstractType<any>>, { captureTimeout, captureTransaction, deleteFilter, trackedOrigins, ignoreRemoteMapChanges, doc }?: UndoManagerOptions);
/**
* @type {Array<AbstractType<any>>}
*/
scope: Array<AbstractType<any>>;
deleteFilter: (arg0: Item) => boolean;
trackedOrigins: Set<any>;
captureTransaction: (arg0: Transaction) => boolean;
/**
* @type {Array<StackItem>}
*/
undoStack: Array<StackItem>;
/**
* @type {Array<StackItem>}
*/
redoStack: Array<StackItem>;
/**
* Whether the client is currently undoing (calling UndoManager.undo)
*
* @type {boolean}
*/
undoing: boolean;
redoing: boolean;
doc: Doc;
lastChange: number;
ignoreRemoteMapChanges: boolean;
captureTimeout: number;
/**
* @param {Transaction} transaction
*/
afterTransactionHandler: (transaction: Transaction) => void;
/**
* @param {Array<AbstractType<any>> | AbstractType<any>} ytypes
*/
addToScope(ytypes: Array<AbstractType<any>> | AbstractType<any>): void;
/**
* @param {any} origin
*/
addTrackedOrigin(origin: any): void;
/**
* @param {any} origin
*/
removeTrackedOrigin(origin: any): void;
clear(clearUndoStack?: boolean, clearRedoStack?: boolean): void;
/**
* 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(): void;
/**
* Undo last changes on type.
*
* @return {StackItem?} Returns StackItem if a change was applied
*/
undo(): StackItem | null;
/**
* Redo last undo operation.
*
* @return {StackItem?} Returns StackItem if a change was applied
*/
redo(): StackItem | null;
/**
* Are undo steps available?
*
* @return {boolean} `true` if undo is possible
*/
canUndo(): boolean;
/**
* Are redo steps available?
*
* @return {boolean} `true` if redo is possible
*/
canRedo(): boolean;
}
export type UndoManagerOptions = {
captureTimeout?: number | undefined;
/**
* Do not capture changes of a Transaction if result false.
*/
captureTransaction?: ((arg0: Transaction) => boolean) | undefined;
/**
* Sometimes
* it is necessary to filter what an Undo/Redo operation can delete. If this
* filter returns false, the type/item won't be deleted even it is in the
* undo/redo scope.
*/
deleteFilter?: ((arg0: Item) => boolean) | undefined;
trackedOrigins?: Set<any> | undefined;
/**
* Experimental. By default, the UndoManager will never overwrite remote changes. Enable this property to enable overwriting remote changes on key-value changes (Y.Map, properties on Y.Xml, etc..).
*/
ignoreRemoteMapChanges?: boolean | undefined;
/**
* The document that this UndoManager operates on. Only needed if typeScope is empty.
*/
doc?: Doc | undefined;
};
import { Observable } from "lib0/observable";
import { AbstractType } from "../types/AbstractType.js";
import { Item } from "../structs/Item.js";
import { Transaction } from "./Transaction.js";
declare class StackItem {
/**
* @param {DeleteSet} deletions
* @param {DeleteSet} insertions
*/
constructor(deletions: DeleteSet, insertions: DeleteSet);
insertions: DeleteSet;
deletions: DeleteSet;
/**
* Use this to save and restore metadata like selection range
*/
meta: Map<any, any>;
}
import { Doc } from "./Doc.js";
import { DeleteSet } from "./DeleteSet.js";
export {};

166
dist/src/utils/UpdateDecoder.d.ts vendored Normal file
View File

@ -0,0 +1,166 @@
export class DSDecoderV1 {
/**
* @param {decoding.Decoder} decoder
*/
constructor(decoder: decoding.Decoder);
restDecoder: decoding.Decoder;
resetDsCurVal(): void;
/**
* @return {number}
*/
readDsClock(): number;
/**
* @return {number}
*/
readDsLen(): number;
}
export class UpdateDecoderV1 extends DSDecoderV1 {
/**
* @return {ID}
*/
readLeftID(): ID;
/**
* @return {ID}
*/
readRightID(): ID;
/**
* Read the next client id.
* Use this in favor of readID whenever possible to reduce the number of objects created.
*/
readClient(): number;
/**
* @return {number} info An unsigned 8-bit integer
*/
readInfo(): number;
/**
* @return {string}
*/
readString(): string;
/**
* @return {boolean} isKey
*/
readParentInfo(): boolean;
/**
* @return {number} info An unsigned 8-bit integer
*/
readTypeRef(): number;
/**
* Write len of a struct - well suited for Opt RLE encoder.
*
* @return {number} len
*/
readLen(): number;
/**
* @return {any}
*/
readAny(): any;
/**
* @return {Uint8Array}
*/
readBuf(): Uint8Array;
/**
* Legacy implementation uses JSON parse. We use any-decoding in v2.
*
* @return {any}
*/
readJSON(): any;
/**
* @return {string}
*/
readKey(): string;
}
export class DSDecoderV2 {
/**
* @param {decoding.Decoder} decoder
*/
constructor(decoder: decoding.Decoder);
/**
* @private
*/
private dsCurrVal;
restDecoder: decoding.Decoder;
resetDsCurVal(): void;
/**
* @return {number}
*/
readDsClock(): number;
/**
* @return {number}
*/
readDsLen(): number;
}
export class UpdateDecoderV2 extends DSDecoderV2 {
/**
* List of cached keys. If the keys[id] does not exist, we read a new key
* from stringEncoder and push it to keys.
*
* @type {Array<string>}
*/
keys: Array<string>;
keyClockDecoder: decoding.IntDiffOptRleDecoder;
clientDecoder: decoding.UintOptRleDecoder;
leftClockDecoder: decoding.IntDiffOptRleDecoder;
rightClockDecoder: decoding.IntDiffOptRleDecoder;
infoDecoder: decoding.RleDecoder<number>;
stringDecoder: decoding.StringDecoder;
parentInfoDecoder: decoding.RleDecoder<number>;
typeRefDecoder: decoding.UintOptRleDecoder;
lenDecoder: decoding.UintOptRleDecoder;
/**
* @return {ID}
*/
readLeftID(): ID;
/**
* @return {ID}
*/
readRightID(): ID;
/**
* Read the next client id.
* Use this in favor of readID whenever possible to reduce the number of objects created.
*/
readClient(): number;
/**
* @return {number} info An unsigned 8-bit integer
*/
readInfo(): number;
/**
* @return {string}
*/
readString(): string;
/**
* @return {boolean}
*/
readParentInfo(): boolean;
/**
* @return {number} An unsigned 8-bit integer
*/
readTypeRef(): number;
/**
* Write len of a struct - well suited for Opt RLE encoder.
*
* @return {number}
*/
readLen(): number;
/**
* @return {any}
*/
readAny(): any;
/**
* @return {Uint8Array}
*/
readBuf(): Uint8Array;
/**
* 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(): any;
/**
* @return {string}
*/
readKey(): string;
}
import * as decoding from "lib0/decoding";
import { ID } from "./ID.js";

163
dist/src/utils/UpdateEncoder.d.ts vendored Normal file
View File

@ -0,0 +1,163 @@
export class DSEncoderV1 {
restEncoder: encoding.Encoder;
toUint8Array(): Uint8Array;
resetDsCurVal(): void;
/**
* @param {number} clock
*/
writeDsClock(clock: number): void;
/**
* @param {number} len
*/
writeDsLen(len: number): void;
}
export class UpdateEncoderV1 extends DSEncoderV1 {
/**
* @param {ID} id
*/
writeLeftID(id: ID): void;
/**
* @param {ID} id
*/
writeRightID(id: ID): void;
/**
* Use writeClient and writeClock instead of writeID if possible.
* @param {number} client
*/
writeClient(client: number): void;
/**
* @param {number} info An unsigned 8-bit integer
*/
writeInfo(info: number): void;
/**
* @param {string} s
*/
writeString(s: string): void;
/**
* @param {boolean} isYKey
*/
writeParentInfo(isYKey: boolean): void;
/**
* @param {number} info An unsigned 8-bit integer
*/
writeTypeRef(info: number): void;
/**
* Write len of a struct - well suited for Opt RLE encoder.
*
* @param {number} len
*/
writeLen(len: number): void;
/**
* @param {any} any
*/
writeAny(any: any): void;
/**
* @param {Uint8Array} buf
*/
writeBuf(buf: Uint8Array): void;
/**
* @param {any} embed
*/
writeJSON(embed: any): void;
/**
* @param {string} key
*/
writeKey(key: string): void;
}
export class DSEncoderV2 {
restEncoder: encoding.Encoder;
dsCurrVal: number;
toUint8Array(): Uint8Array;
resetDsCurVal(): void;
/**
* @param {number} clock
*/
writeDsClock(clock: number): void;
/**
* @param {number} len
*/
writeDsLen(len: number): void;
}
export class UpdateEncoderV2 extends DSEncoderV2 {
/**
* @type {Map<string,number>}
*/
keyMap: Map<string, number>;
/**
* Refers to the next uniqe key-identifier to me used.
* See writeKey method for more information.
*
* @type {number}
*/
keyClock: number;
keyClockEncoder: encoding.IntDiffOptRleEncoder;
clientEncoder: encoding.UintOptRleEncoder;
leftClockEncoder: encoding.IntDiffOptRleEncoder;
rightClockEncoder: encoding.IntDiffOptRleEncoder;
infoEncoder: encoding.RleEncoder<number>;
stringEncoder: encoding.StringEncoder;
parentInfoEncoder: encoding.RleEncoder<number>;
typeRefEncoder: encoding.UintOptRleEncoder;
lenEncoder: encoding.UintOptRleEncoder;
/**
* @param {ID} id
*/
writeLeftID(id: ID): void;
/**
* @param {ID} id
*/
writeRightID(id: ID): void;
/**
* @param {number} client
*/
writeClient(client: number): void;
/**
* @param {number} info An unsigned 8-bit integer
*/
writeInfo(info: number): void;
/**
* @param {string} s
*/
writeString(s: string): void;
/**
* @param {boolean} isYKey
*/
writeParentInfo(isYKey: boolean): void;
/**
* @param {number} info An unsigned 8-bit integer
*/
writeTypeRef(info: number): void;
/**
* Write len of a struct - well suited for Opt RLE encoder.
*
* @param {number} len
*/
writeLen(len: number): void;
/**
* @param {any} any
*/
writeAny(any: any): void;
/**
* @param {Uint8Array} buf
*/
writeBuf(buf: Uint8Array): void;
/**
* 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: any): void;
/**
* 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: string): void;
}
import * as encoding from "lib0/encoding";
import { ID } from "./ID.js";

120
dist/src/utils/YEvent.d.ts vendored Normal file
View File

@ -0,0 +1,120 @@
/**
* @template {AbstractType<any>} T
* YEvent describes the changes on a YType.
*/
export class YEvent<T extends AbstractType<any>> {
/**
* @param {T} target The changed type.
* @param {Transaction} transaction
*/
constructor(target: T, transaction: Transaction);
/**
* The type on which this event was created on.
* @type {T}
*/
target: T;
/**
* The current target on which the observe callback is called.
* @type {AbstractType<any>}
*/
currentTarget: AbstractType<any>;
/**
* The transaction that triggered this event.
* @type {Transaction}
*/
transaction: Transaction;
/**
* @type {Object|null}
*/
_changes: Object | null;
/**
* @type {null | Map<string, { action: 'add' | 'update' | 'delete', oldValue: any, newValue: any }>}
*/
_keys: Map<string, {
action: 'add' | 'update' | 'delete';
oldValue: any;
newValue: any;
}> | null;
/**
* @type {null | Array<{ insert?: string | Array<any> | object | AbstractType<any>, retain?: number, delete?: number, attributes?: Object<string, any> }>}
*/
_delta: {
insert?: string | object | any[] | AbstractType<any> | undefined;
retain?: number | undefined;
delete?: number | undefined;
attributes?: {
[x: string]: any;
} | undefined;
}[] | 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(): (string | number)[];
/**
* 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: AbstractStruct): boolean;
/**
* @type {Map<string, { action: 'add' | 'update' | 'delete', oldValue: any, newValue: any }>}
*/
get keys(): Map<string, {
action: 'add' | 'update' | 'delete';
oldValue: any;
newValue: any;
}>;
/**
* @type {Array<{insert?: string | Array<any> | object | AbstractType<any>, retain?: number, delete?: number, attributes?: Object<string, any>}>}
*/
get delta(): {
insert?: string | object | any[] | AbstractType<any> | undefined;
retain?: number | undefined;
delete?: number | undefined;
attributes?: {
[x: string]: any;
} | undefined;
}[];
/**
* 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: AbstractStruct): boolean;
/**
* @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(): {
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;
}>;
};
}
import { AbstractType } from "../types/AbstractType.js";
import { Transaction } from "./Transaction.js";
import { AbstractStruct } from "../structs/AbstractStruct.js";
import { Item } from "../structs/Item.js";

33
dist/src/utils/encoding.d.ts vendored Normal file
View File

@ -0,0 +1,33 @@
export function writeClientsStructs(encoder: UpdateEncoderV1 | UpdateEncoderV2, store: StructStore, _sm: Map<number, number>): void;
export function readClientsStructRefs(decoder: UpdateDecoderV1 | UpdateDecoderV2, doc: Doc): Map<number, {
i: number;
refs: Array<Item | GC>;
}>;
export function writeStructsFromTransaction(encoder: UpdateEncoderV1 | UpdateEncoderV2, transaction: Transaction): void;
export function readUpdateV2(decoder: decoding.Decoder, ydoc: Doc, transactionOrigin?: any, structDecoder?: UpdateDecoderV1 | UpdateDecoderV2 | undefined): void;
export function readUpdate(decoder: decoding.Decoder, ydoc: Doc, transactionOrigin?: any): void;
export function applyUpdateV2(ydoc: Doc, update: Uint8Array, transactionOrigin?: any, YDecoder?: typeof UpdateDecoderV1 | typeof UpdateDecoderV2 | undefined): void;
export function applyUpdate(ydoc: Doc, update: Uint8Array, transactionOrigin?: any): void;
export function writeStateAsUpdate(encoder: UpdateEncoderV1 | UpdateEncoderV2, doc: Doc, targetStateVector?: Map<number, number> | undefined): void;
export function encodeStateAsUpdateV2(doc: Doc, encodedTargetStateVector?: Uint8Array | undefined, encoder?: UpdateEncoderV2 | UpdateEncoderV1 | undefined): Uint8Array;
export function encodeStateAsUpdate(doc: Doc, encodedTargetStateVector?: Uint8Array | undefined): Uint8Array;
export function readStateVector(decoder: DSDecoderV1 | DSDecoderV2): Map<number, number>;
export function decodeStateVector(decodedState: Uint8Array): Map<number, number>;
export function writeStateVector(encoder: DSEncoderV1 | DSEncoderV2, sv: Map<number, number>): DSEncoderV1 | DSEncoderV2;
export function writeDocumentStateVector(encoder: DSEncoderV1 | DSEncoderV2, doc: Doc): DSEncoderV1 | DSEncoderV2;
export function encodeStateVectorV2(doc: Doc | Map<number, number>, encoder?: DSEncoderV1 | DSEncoderV2 | undefined): Uint8Array;
export function encodeStateVector(doc: Doc | Map<number, number>): Uint8Array;
import { UpdateEncoderV1 } from "./UpdateEncoder.js";
import { UpdateEncoderV2 } from "./UpdateEncoder.js";
import { StructStore } from "./StructStore.js";
import { UpdateDecoderV1 } from "./UpdateDecoder.js";
import { UpdateDecoderV2 } from "./UpdateDecoder.js";
import { Doc } from "./Doc.js";
import { Item } from "../structs/Item.js";
import { GC } from "../structs/GC.js";
import { Transaction } from "./Transaction.js";
import * as decoding from "lib0/decoding";
import { DSDecoderV1 } from "./UpdateDecoder.js";
import { DSDecoderV2 } from "./UpdateDecoder.js";
import { DSEncoderV1 } from "./UpdateEncoder.js";
import { DSEncoderV2 } from "./UpdateEncoder.js";

3
dist/src/utils/isParentOf.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
export function isParentOf(parent: AbstractType<any>, child: Item | null): boolean;
import { AbstractType } from "../types/AbstractType.js";
import { Item } from "../structs/Item.js";

2
dist/src/utils/logging.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
export function logType(type: AbstractType<any>): void;
import { AbstractType } from "../types/AbstractType.js";

78
dist/src/utils/updates.d.ts vendored Normal file
View File

@ -0,0 +1,78 @@
export class LazyStructReader {
/**
* @param {UpdateDecoderV1 | UpdateDecoderV2} decoder
* @param {boolean} filterSkips
*/
constructor(decoder: UpdateDecoderV1 | UpdateDecoderV2, filterSkips: boolean);
gen: Generator<GC | Item | Skip, void, unknown>;
/**
* @type {null | Item | Skip | GC}
*/
curr: null | Item | Skip | GC;
done: boolean;
filterSkips: boolean;
/**
* @return {Item | GC | Skip |null}
*/
next(): Item | GC | Skip | null;
}
export function logUpdate(update: Uint8Array): void;
export function logUpdateV2(update: Uint8Array, YDecoder?: typeof UpdateDecoderV1 | typeof UpdateDecoderV2 | undefined): void;
export function decodeUpdate(update: Uint8Array): {
structs: (GC | Item | Skip)[];
ds: import("./DeleteSet.js").DeleteSet;
};
export function decodeUpdateV2(update: Uint8Array, YDecoder?: typeof UpdateDecoderV1 | typeof UpdateDecoderV2 | undefined): {
structs: (GC | Item | Skip)[];
ds: import("./DeleteSet.js").DeleteSet;
};
export class LazyStructWriter {
/**
* @param {UpdateEncoderV1 | UpdateEncoderV2} encoder
*/
constructor(encoder: UpdateEncoderV1 | UpdateEncoderV2);
currClient: number;
startClock: number;
written: number;
encoder: UpdateEncoderV2 | UpdateEncoderV1;
/**
* We want to write operations lazily, but also we need to know beforehand how many operations we want to write for each client.
*
* This kind of meta-information (#clients, #structs-per-client-written) is written to the restEncoder.
*
* We fragment the restEncoder and store a slice of it per-client until we know how many clients there are.
* When we flush (toUint8Array) we write the restEncoder using the fragments and the meta-information.
*
* @type {Array<{ written: number, restEncoder: Uint8Array }>}
*/
clientStructs: {
written: number;
restEncoder: Uint8Array;
}[];
}
export function mergeUpdates(updates: Array<Uint8Array>): Uint8Array;
export function encodeStateVectorFromUpdateV2(update: Uint8Array, YEncoder?: typeof DSEncoderV1 | typeof DSEncoderV2, YDecoder?: typeof UpdateDecoderV1 | typeof UpdateDecoderV2): Uint8Array;
export function encodeStateVectorFromUpdate(update: Uint8Array): Uint8Array;
export function parseUpdateMetaV2(update: Uint8Array, YDecoder?: typeof UpdateDecoderV1 | typeof UpdateDecoderV2): {
from: Map<number, number>;
to: Map<number, number>;
};
export function parseUpdateMeta(update: Uint8Array): {
from: Map<number, number>;
to: Map<number, number>;
};
export function mergeUpdatesV2(updates: Array<Uint8Array>, YDecoder?: typeof UpdateDecoderV1 | typeof UpdateDecoderV2 | undefined, YEncoder?: typeof UpdateEncoderV2 | typeof UpdateEncoderV1 | undefined): Uint8Array;
export function diffUpdateV2(update: Uint8Array, sv: Uint8Array, YDecoder?: typeof UpdateDecoderV1 | typeof UpdateDecoderV2 | undefined, YEncoder?: typeof UpdateEncoderV2 | typeof UpdateEncoderV1 | undefined): Uint8Array;
export function diffUpdate(update: Uint8Array, sv: Uint8Array): Uint8Array;
export function convertUpdateFormat(update: Uint8Array, YDecoder: typeof UpdateDecoderV2 | typeof UpdateDecoderV1, YEncoder: typeof UpdateEncoderV2 | typeof UpdateEncoderV1): Uint8Array;
export function convertUpdateFormatV1ToV2(update: Uint8Array): Uint8Array;
export function convertUpdateFormatV2ToV1(update: Uint8Array): Uint8Array;
import { GC } from "../structs/GC.js";
import { Item } from "../structs/Item.js";
import { Skip } from "../structs/Skip.js";
import { UpdateDecoderV1 } from "./UpdateDecoder.js";
import { UpdateDecoderV2 } from "./UpdateDecoder.js";
import { UpdateEncoderV2 } from "./UpdateEncoder.js";
import { UpdateEncoderV1 } from "./UpdateEncoder.js";
import { DSEncoderV1 } from "./UpdateEncoder.js";
import { DSEncoderV2 } from "./UpdateEncoder.js";

475
dist/testHelper.mjs vendored Normal file
View File

@ -0,0 +1,475 @@
import * as t from 'lib0/testing';
import * as prng from 'lib0/prng';
import * as encoding from 'lib0/encoding';
import * as decoding from 'lib0/decoding';
import * as syncProtocol from 'y-protocols/sync';
import * as object from 'lib0/object';
import * as map from 'lib0/map';
import * as Y from 'yjs';
export * from 'yjs';
if (typeof window !== 'undefined') {
// @ts-ignore
window.Y = Y; // eslint-disable-line
}
/**
* @param {TestYInstance} y // publish message created by `y` to all other online clients
* @param {Uint8Array} m
*/
const broadcastMessage = (y, m) => {
if (y.tc.onlineConns.has(y)) {
y.tc.onlineConns.forEach(remoteYInstance => {
if (remoteYInstance !== y) {
remoteYInstance._receive(m, y);
}
});
}
};
let useV2 = false;
const encV1 = {
encodeStateAsUpdate: Y.encodeStateAsUpdate,
mergeUpdates: Y.mergeUpdates,
applyUpdate: Y.applyUpdate,
logUpdate: Y.logUpdate,
updateEventName: 'update',
diffUpdate: Y.diffUpdate
};
const encV2 = {
encodeStateAsUpdate: Y.encodeStateAsUpdateV2,
mergeUpdates: Y.mergeUpdatesV2,
applyUpdate: Y.applyUpdateV2,
logUpdate: Y.logUpdateV2,
updateEventName: 'updateV2',
diffUpdate: Y.diffUpdateV2
};
let enc = encV1;
const useV1Encoding = () => {
useV2 = false;
enc = encV1;
};
const useV2Encoding = () => {
console.error('sync protocol doesnt support v2 protocol yet, fallback to v1 encoding'); // @Todo
useV2 = false;
enc = encV1;
};
class TestYInstance extends Y.Doc {
/**
* @param {TestConnector} testConnector
* @param {number} clientID
*/
constructor (testConnector, clientID) {
super();
this.userID = clientID; // overwriting clientID
/**
* @type {TestConnector}
*/
this.tc = testConnector;
/**
* @type {Map<TestYInstance, Array<Uint8Array>>}
*/
this.receiving = new Map();
testConnector.allConns.add(this);
/**
* The list of received updates.
* We are going to merge them later using Y.mergeUpdates and check if the resulting document is correct.
* @type {Array<Uint8Array>}
*/
this.updates = [];
// set up observe on local model
this.on(enc.updateEventName, /** @param {Uint8Array} update @param {any} origin */ (update, origin) => {
if (origin !== testConnector) {
const encoder = encoding.createEncoder();
syncProtocol.writeUpdate(encoder, update);
broadcastMessage(this, encoding.toUint8Array(encoder));
}
this.updates.push(update);
});
this.connect();
}
/**
* Disconnect from TestConnector.
*/
disconnect () {
this.receiving = new Map();
this.tc.onlineConns.delete(this);
}
/**
* Append yourself to the list of known Y instances in testconnector.
* Also initiate sync with all clients.
*/
connect () {
if (!this.tc.onlineConns.has(this)) {
this.tc.onlineConns.add(this);
const encoder = encoding.createEncoder();
syncProtocol.writeSyncStep1(encoder, this);
// publish SyncStep1
broadcastMessage(this, encoding.toUint8Array(encoder));
this.tc.onlineConns.forEach(remoteYInstance => {
if (remoteYInstance !== this) {
// remote instance sends instance to this instance
const encoder = encoding.createEncoder();
syncProtocol.writeSyncStep1(encoder, remoteYInstance);
this._receive(encoding.toUint8Array(encoder), remoteYInstance);
}
});
}
}
/**
* Receive a message from another client. This message is only appended to the list of receiving messages.
* TestConnector decides when this client actually reads this message.
*
* @param {Uint8Array} message
* @param {TestYInstance} remoteClient
*/
_receive (message, remoteClient) {
map.setIfUndefined(this.receiving, remoteClient, () => []).push(message);
}
}
/**
* Keeps track of TestYInstances.
*
* The TestYInstances add/remove themselves from the list of connections maiained in this object.
* I think it makes sense. Deal with it.
*/
class TestConnector {
/**
* @param {prng.PRNG} gen
*/
constructor (gen) {
/**
* @type {Set<TestYInstance>}
*/
this.allConns = new Set();
/**
* @type {Set<TestYInstance>}
*/
this.onlineConns = new Set();
/**
* @type {prng.PRNG}
*/
this.prng = gen;
}
/**
* Create a new Y instance and add it to the list of connections
* @param {number} clientID
*/
createY (clientID) {
return new TestYInstance(this, clientID)
}
/**
* Choose random connection and flush a random message from a random sender.
*
* If this function was unable to flush a message, because there are no more messages to flush, it returns false. true otherwise.
* @return {boolean}
*/
flushRandomMessage () {
const gen = this.prng;
const conns = Array.from(this.onlineConns).filter(conn => conn.receiving.size > 0);
if (conns.length > 0) {
const receiver = prng.oneOf(gen, conns);
const [sender, messages] = prng.oneOf(gen, Array.from(receiver.receiving));
const m = messages.shift();
if (messages.length === 0) {
receiver.receiving.delete(sender);
}
if (m === undefined) {
return this.flushRandomMessage()
}
const encoder = encoding.createEncoder();
// console.log('receive (' + sender.userID + '->' + receiver.userID + '):\n', syncProtocol.stringifySyncMessage(decoding.createDecoder(m), receiver))
// do not publish data created when this function is executed (could be ss2 or update message)
syncProtocol.readSyncMessage(decoding.createDecoder(m), encoder, receiver, receiver.tc);
if (encoding.length(encoder) > 0) {
// send reply message
sender._receive(encoding.toUint8Array(encoder), receiver);
}
return true
}
return false
}
/**
* @return {boolean} True iff this function actually flushed something
*/
flushAllMessages () {
let didSomething = false;
while (this.flushRandomMessage()) {
didSomething = true;
}
return didSomething
}
reconnectAll () {
this.allConns.forEach(conn => conn.connect());
}
disconnectAll () {
this.allConns.forEach(conn => conn.disconnect());
}
syncAll () {
this.reconnectAll();
this.flushAllMessages();
}
/**
* @return {boolean} Whether it was possible to disconnect a randon connection.
*/
disconnectRandom () {
if (this.onlineConns.size === 0) {
return false
}
prng.oneOf(this.prng, Array.from(this.onlineConns)).disconnect();
return true
}
/**
* @return {boolean} Whether it was possible to reconnect a random connection.
*/
reconnectRandom () {
/**
* @type {Array<TestYInstance>}
*/
const reconnectable = [];
this.allConns.forEach(conn => {
if (!this.onlineConns.has(conn)) {
reconnectable.push(conn);
}
});
if (reconnectable.length === 0) {
return false
}
prng.oneOf(this.prng, reconnectable).connect();
return true
}
}
/**
* @template T
* @param {t.TestCase} tc
* @param {{users?:number}} conf
* @param {InitTestObjectCallback<T>} [initTestObject]
* @return {{testObjects:Array<any>,testConnector:TestConnector,users:Array<TestYInstance>,array0:Y.Array<any>,array1:Y.Array<any>,array2:Y.Array<any>,map0:Y.Map<any>,map1:Y.Map<any>,map2:Y.Map<any>,map3:Y.Map<any>,text0:Y.Text,text1:Y.Text,text2:Y.Text,xml0:Y.XmlElement,xml1:Y.XmlElement,xml2:Y.XmlElement}}
*/
const init = (tc, { users = 5 } = {}, initTestObject) => {
/**
* @type {Object<string,any>}
*/
const result = {
users: []
};
const gen = tc.prng;
// choose an encoding approach at random
if (prng.bool(gen)) {
useV2Encoding();
} else {
useV1Encoding();
}
const testConnector = new TestConnector(gen);
result.testConnector = testConnector;
for (let i = 0; i < users; i++) {
const y = testConnector.createY(i);
y.clientID = i;
result.users.push(y);
result['array' + i] = y.getArray('array');
result['map' + i] = y.getMap('map');
result['xml' + i] = y.get('xml', Y.XmlElement);
result['text' + i] = y.getText('text');
}
testConnector.syncAll();
result.testObjects = result.users.map(initTestObject || (() => null));
useV1Encoding();
return /** @type {any} */ (result)
};
/**
* 1. reconnect and flush all
* 2. user 0 gc
* 3. get type content
* 4. disconnect & reconnect all (so gc is propagated)
* 5. compare os, ds, ss
*
* @param {Array<TestYInstance>} users
*/
const compare = users => {
users.forEach(u => u.connect());
while (users[0].tc.flushAllMessages()) {} // eslint-disable-line
// For each document, merge all received document updates with Y.mergeUpdates and create a new document which will be added to the list of "users"
// This ensures that mergeUpdates works correctly
const mergedDocs = users.map(user => {
const ydoc = new Y.Doc();
enc.applyUpdate(ydoc, enc.mergeUpdates(user.updates));
return ydoc
});
users.push(.../** @type {any} */(mergedDocs));
const userArrayValues = users.map(u => u.getArray('array').toJSON());
const userMapValues = users.map(u => u.getMap('map').toJSON());
const userXmlValues = users.map(u => u.get('xml', Y.XmlElement).toString());
const userTextValues = users.map(u => u.getText('text').toDelta());
for (const u of users) {
t.assert(u.store.pendingDs === null);
t.assert(u.store.pendingStructs === null);
}
// Test Array iterator
t.compare(users[0].getArray('array').toArray(), Array.from(users[0].getArray('array')));
// Test Map iterator
const ymapkeys = Array.from(users[0].getMap('map').keys());
t.assert(ymapkeys.length === Object.keys(userMapValues[0]).length);
ymapkeys.forEach(key => t.assert(object.hasProperty(userMapValues[0], key)));
/**
* @type {Object<string,any>}
*/
const mapRes = {};
for (const [k, v] of users[0].getMap('map')) {
mapRes[k] = v instanceof Y.AbstractType ? v.toJSON() : v;
}
t.compare(userMapValues[0], mapRes);
// Compare all users
for (let i = 0; i < users.length - 1; i++) {
t.compare(userArrayValues[i].length, users[i].getArray('array').length);
t.compare(userArrayValues[i], userArrayValues[i + 1]);
t.compare(userMapValues[i], userMapValues[i + 1]);
t.compare(userXmlValues[i], userXmlValues[i + 1]);
t.compare(userTextValues[i].map(/** @param {any} a */ a => typeof a.insert === 'string' ? a.insert : ' ').join('').length, users[i].getText('text').length);
t.compare(userTextValues[i], userTextValues[i + 1], '', (constructor, a, b) => {
if (a instanceof Y.AbstractType) {
t.compare(a.toJSON(), b.toJSON());
} else if (a !== b) {
t.fail('Deltas dont match');
}
return true
});
t.compare(Y.encodeStateVector(users[i]), Y.encodeStateVector(users[i + 1]));
compareDS(Y.createDeleteSetFromStructStore(users[i].store), Y.createDeleteSetFromStructStore(users[i + 1].store));
compareStructStores(users[i].store, users[i + 1].store);
}
users.map(u => u.destroy());
};
/**
* @param {Y.Item?} a
* @param {Y.Item?} b
* @return {boolean}
*/
const compareItemIDs = (a, b) => a === b || (a !== null && b != null && Y.compareIDs(a.id, b.id));
/**
* @param {import('../src/internals').StructStore} ss1
* @param {import('../src/internals').StructStore} ss2
*/
const compareStructStores = (ss1, ss2) => {
t.assert(ss1.clients.size === ss2.clients.size);
for (const [client, structs1] of ss1.clients) {
const structs2 = /** @type {Array<Y.AbstractStruct>} */ (ss2.clients.get(client));
t.assert(structs2 !== undefined && structs1.length === structs2.length);
for (let i = 0; i < structs1.length; i++) {
const s1 = structs1[i];
const s2 = structs2[i];
// checks for abstract struct
if (
s1.constructor !== s2.constructor ||
!Y.compareIDs(s1.id, s2.id) ||
s1.deleted !== s2.deleted ||
// @ts-ignore
s1.length !== s2.length
) {
t.fail('Structs dont match');
}
if (s1 instanceof Y.Item) {
if (
!(s2 instanceof Y.Item) ||
!((s1.left === null && s2.left === null) || (s1.left !== null && s2.left !== null && Y.compareIDs(s1.left.lastId, s2.left.lastId))) ||
!compareItemIDs(s1.right, s2.right) ||
!Y.compareIDs(s1.origin, s2.origin) ||
!Y.compareIDs(s1.rightOrigin, s2.rightOrigin) ||
s1.parentSub !== s2.parentSub
) {
return t.fail('Items dont match')
}
// make sure that items are connected correctly
t.assert(s1.left === null || s1.left.right === s1);
t.assert(s1.right === null || s1.right.left === s1);
t.assert(s2.left === null || s2.left.right === s2);
t.assert(s2.right === null || s2.right.left === s2);
}
}
}
};
/**
* @param {import('../src/internals').DeleteSet} ds1
* @param {import('../src/internals').DeleteSet} ds2
*/
const compareDS = (ds1, ds2) => {
t.assert(ds1.clients.size === ds2.clients.size);
ds1.clients.forEach((deleteItems1, client) => {
const deleteItems2 = /** @type {Array<import('../src/internals').DeleteItem>} */ (ds2.clients.get(client));
t.assert(deleteItems2 !== undefined && deleteItems1.length === deleteItems2.length);
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) {
t.fail('DeleteSets dont match');
}
}
});
};
/**
* @template T
* @callback InitTestObjectCallback
* @param {TestYInstance} y
* @return {T}
*/
/**
* @template T
* @param {t.TestCase} tc
* @param {Array<function(Y.Doc,prng.PRNG,T):void>} mods
* @param {number} iterations
* @param {InitTestObjectCallback<T>} [initTestObject]
*/
const applyRandomTests = (tc, mods, iterations, initTestObject) => {
const gen = tc.prng;
const result = init(tc, { users: 5 }, initTestObject);
const { testConnector, users } = result;
for (let i = 0; i < iterations; i++) {
if (prng.int32(gen, 0, 100) <= 2) {
// 2% chance to disconnect/reconnect a random user
if (prng.bool(gen)) {
testConnector.disconnectRandom();
} else {
testConnector.reconnectRandom();
}
} else if (prng.int32(gen, 0, 100) <= 1) {
// 1% chance to flush all
testConnector.flushAllMessages();
} else if (prng.int32(gen, 0, 100) <= 50) {
// 50% chance to flush a random message
testConnector.flushRandomMessage();
}
const user = prng.int32(gen, 0, users.length - 1);
const test = prng.oneOf(gen, mods);
test(users[user], gen, result.testObjects[user]);
}
compare(users);
return result
};
export { TestConnector, TestYInstance, applyRandomTests, compare, compareDS, compareItemIDs, compareStructStores, enc, encV1, encV2, init, useV2 };
//# sourceMappingURL=testHelper.mjs.map

1
dist/testHelper.mjs.map vendored Normal file

File diff suppressed because one or more lines are too long

18048
dist/tests.cjs vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/tests.cjs.map vendored Normal file

File diff suppressed because one or more lines are too long

18075
dist/tests.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/tests.js.map vendored Normal file

File diff suppressed because one or more lines are too long

4
dist/tests/compatibility.tests.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
export function testArrayCompatibilityV1(tc: t.TestCase): void;
export function testMapDecodingCompatibilityV1(tc: t.TestCase): void;
export function testTextDecodingCompatibilityV1(tc: t.TestCase): void;
import * as t from "lib0/testing";

10
dist/tests/doc.tests.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
export function testOriginInTransaction(_tc: t.TestCase): void;
export function testClientIdDuplicateChange(tc: t.TestCase): void;
export function testGetTypeEmptyId(tc: t.TestCase): void;
export function testToJSON(tc: t.TestCase): void;
export function testSubdoc(tc: t.TestCase): void;
export function testSubdocLoadEdgeCases(tc: t.TestCase): void;
export function testSubdocLoadEdgeCasesAutoload(tc: t.TestCase): void;
export function testSubdocsUndo(tc: t.TestCase): void;
export function testLoadDocs(tc: t.TestCase): Promise<void>;
import * as t from "lib0/testing";

5
dist/tests/encoding.tests.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
export function testStructReferences(tc: t.TestCase): void;
export function testPermanentUserData(tc: t.TestCase): Promise<void>;
export function testDiffStateVectorOfUpdateIsEmpty(tc: t.TestCase): void;
export function testDiffStateVectorOfUpdateIgnoresSkips(tc: t.TestCase): void;
import * as t from "lib0/testing";

1
dist/tests/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,8 @@
export function testRelativePositionCase1(tc: t.TestCase): void;
export function testRelativePositionCase2(tc: t.TestCase): void;
export function testRelativePositionCase3(tc: t.TestCase): void;
export function testRelativePositionCase4(tc: t.TestCase): void;
export function testRelativePositionCase5(tc: t.TestCase): void;
export function testRelativePositionCase6(tc: t.TestCase): void;
export function testRelativePositionAssociationDifference(tc: t.TestCase): void;
import * as t from "lib0/testing";

9
dist/tests/snapshot.tests.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
export function testBasicRestoreSnapshot(tc: t.TestCase): void;
export function testEmptyRestoreSnapshot(tc: t.TestCase): void;
export function testRestoreSnapshotWithSubType(tc: t.TestCase): void;
export function testRestoreDeletedItem1(tc: t.TestCase): void;
export function testRestoreLeftItem(tc: t.TestCase): void;
export function testDeletedItemsBase(tc: t.TestCase): void;
export function testDeletedItems2(tc: t.TestCase): void;
export function testDependentChanges(tc: t.TestCase): void;
import * as t from "lib0/testing";

161
dist/tests/testHelper.d.ts vendored Normal file
View File

@ -0,0 +1,161 @@
export * from "../src/index.js";
export let useV2: boolean;
export namespace encV1 {
const encodeStateAsUpdate: (doc: Y.Doc, encodedTargetStateVector?: Uint8Array | undefined) => Uint8Array;
const mergeUpdates: (updates: Uint8Array[]) => Uint8Array;
const applyUpdate: (ydoc: Y.Doc, update: Uint8Array, transactionOrigin?: any) => void;
const logUpdate: (update: Uint8Array) => void;
const updateEventName: string;
const diffUpdate: (update: Uint8Array, sv: Uint8Array) => Uint8Array;
}
export namespace encV2 {
const encodeStateAsUpdate_1: (doc: Y.Doc, encodedTargetStateVector?: Uint8Array | undefined, encoder?: import("../src/internals").UpdateEncoderV2 | Y.UpdateEncoderV1 | undefined) => Uint8Array;
export { encodeStateAsUpdate_1 as encodeStateAsUpdate };
const mergeUpdates_1: (updates: Uint8Array[], YDecoder?: typeof import("../src/internals").UpdateDecoderV1 | typeof import("../src/internals").UpdateDecoderV2 | undefined, YEncoder?: typeof import("../src/internals").UpdateEncoderV2 | typeof Y.UpdateEncoderV1 | undefined) => Uint8Array;
export { mergeUpdates_1 as mergeUpdates };
const applyUpdate_1: (ydoc: Y.Doc, update: Uint8Array, transactionOrigin?: any, YDecoder?: typeof import("../src/internals").UpdateDecoderV1 | typeof import("../src/internals").UpdateDecoderV2 | undefined) => void;
export { applyUpdate_1 as applyUpdate };
const logUpdate_1: (update: Uint8Array, YDecoder?: typeof import("../src/internals").UpdateDecoderV1 | typeof import("../src/internals").UpdateDecoderV2 | undefined) => void;
export { logUpdate_1 as logUpdate };
const updateEventName_1: string;
export { updateEventName_1 as updateEventName };
const diffUpdate_1: (update: Uint8Array, sv: Uint8Array, YDecoder?: typeof import("../src/internals").UpdateDecoderV1 | typeof import("../src/internals").UpdateDecoderV2 | undefined, YEncoder?: typeof import("../src/internals").UpdateEncoderV2 | typeof Y.UpdateEncoderV1 | undefined) => Uint8Array;
export { diffUpdate_1 as diffUpdate };
}
export namespace enc { }
export class TestYInstance extends Y.Doc {
/**
* @param {TestConnector} testConnector
* @param {number} clientID
*/
constructor(testConnector: TestConnector, clientID: number);
userID: number;
/**
* @type {TestConnector}
*/
tc: TestConnector;
/**
* @type {Map<TestYInstance, Array<Uint8Array>>}
*/
receiving: Map<TestYInstance, Array<Uint8Array>>;
/**
* The list of received updates.
* We are going to merge them later using Y.mergeUpdates and check if the resulting document is correct.
* @type {Array<Uint8Array>}
*/
updates: Array<Uint8Array>;
/**
* Disconnect from TestConnector.
*/
disconnect(): void;
/**
* Append yourself to the list of known Y instances in testconnector.
* Also initiate sync with all clients.
*/
connect(): void;
/**
* Receive a message from another client. This message is only appended to the list of receiving messages.
* TestConnector decides when this client actually reads this message.
*
* @param {Uint8Array} message
* @param {TestYInstance} remoteClient
*/
_receive(message: Uint8Array, remoteClient: TestYInstance): void;
}
/**
* Keeps track of TestYInstances.
*
* The TestYInstances add/remove themselves from the list of connections maiained in this object.
* I think it makes sense. Deal with it.
*/
export class TestConnector {
/**
* @param {prng.PRNG} gen
*/
constructor(gen: prng.PRNG);
/**
* @type {Set<TestYInstance>}
*/
allConns: Set<TestYInstance>;
/**
* @type {Set<TestYInstance>}
*/
onlineConns: Set<TestYInstance>;
/**
* @type {prng.PRNG}
*/
prng: prng.PRNG;
/**
* Create a new Y instance and add it to the list of connections
* @param {number} clientID
*/
createY(clientID: number): TestYInstance;
/**
* Choose random connection and flush a random message from a random sender.
*
* If this function was unable to flush a message, because there are no more messages to flush, it returns false. true otherwise.
* @return {boolean}
*/
flushRandomMessage(): boolean;
/**
* @return {boolean} True iff this function actually flushed something
*/
flushAllMessages(): boolean;
reconnectAll(): void;
disconnectAll(): void;
syncAll(): void;
/**
* @return {boolean} Whether it was possible to disconnect a randon connection.
*/
disconnectRandom(): boolean;
/**
* @return {boolean} Whether it was possible to reconnect a random connection.
*/
reconnectRandom(): boolean;
}
export function init<T>(tc: t.TestCase, { users }?: {
users?: number;
}, initTestObject?: InitTestObjectCallback<T> | undefined): {
testObjects: Array<any>;
testConnector: TestConnector;
users: Array<TestYInstance>;
array0: Y.Array<any>;
array1: Y.Array<any>;
array2: Y.Array<any>;
map0: Y.Map<any>;
map1: Y.Map<any>;
map2: Y.Map<any>;
map3: Y.Map<any>;
text0: Y.Text;
text1: Y.Text;
text2: Y.Text;
xml0: Y.XmlElement;
xml1: Y.XmlElement;
xml2: Y.XmlElement;
};
export function compare(users: Array<TestYInstance>): void;
export function compareItemIDs(a: Y.Item | null, b: Y.Item | null): boolean;
export function compareStructStores(ss1: import('../src/internals').StructStore, ss2: import('../src/internals').StructStore): undefined;
export function compareDS(ds1: import('../src/internals').DeleteSet, ds2: import('../src/internals').DeleteSet): void;
export function applyRandomTests<T>(tc: t.TestCase, mods: ((arg0: Y.Doc, arg1: prng.PRNG, arg2: T) => void)[], iterations: number, initTestObject?: InitTestObjectCallback<T> | undefined): {
testObjects: Array<any>;
testConnector: TestConnector;
users: Array<TestYInstance>;
array0: Y.Array<any>;
array1: Y.Array<any>;
array2: Y.Array<any>;
map0: Y.Map<any>;
map1: Y.Map<any>;
map2: Y.Map<any>;
map3: Y.Map<any>;
text0: Y.Text;
text1: Y.Text;
text2: Y.Text;
xml0: Y.XmlElement;
xml1: Y.XmlElement;
xml2: Y.XmlElement;
};
export type InitTestObjectCallback<T> = (y: TestYInstance) => T;
import * as Y from "../src/index.js";
import * as prng from "lib0/prng";
import * as t from "lib0/testing";

21
dist/tests/undo-redo.tests.d.ts vendored Normal file
View File

@ -0,0 +1,21 @@
export function testInfiniteCaptureTimeout(tc: t.TestCase): void;
export function testUndoText(tc: t.TestCase): void;
export function testEmptyTypeScope(tc: t.TestCase): void;
export function testDoubleUndo(tc: t.TestCase): void;
export function testUndoMap(tc: t.TestCase): void;
export function testUndoArray(tc: t.TestCase): void;
export function testUndoXml(tc: t.TestCase): void;
export function testUndoEvents(tc: t.TestCase): void;
export function testTrackClass(tc: t.TestCase): void;
export function testTypeScope(tc: t.TestCase): void;
export function testUndoInEmbed(tc: t.TestCase): void;
export function testUndoDeleteFilter(tc: t.TestCase): void;
export function testUndoUntilChangePerformed(tc: t.TestCase): void;
export function testUndoNestedUndoIssue(tc: t.TestCase): void;
export function testConsecutiveRedoBug(tc: t.TestCase): void;
export function testUndoXmlBug(tc: t.TestCase): void;
export function testUndoBlockBug(tc: t.TestCase): void;
export function testUndoDeleteTextFormat(tc: t.TestCase): void;
export function testBehaviorOfIgnoreremotemapchangesProperty(tc: t.TestCase): void;
export function testSpecialDeletionCase(tc: t.TestCase): void;
import * as t from "lib0/testing";

22
dist/tests/updates.tests.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
export function testMergeUpdates(tc: t.TestCase): void;
export function testKeyEncoding(tc: t.TestCase): void;
export function testMergeUpdates1(tc: t.TestCase): void;
export function testMergeUpdates2(tc: t.TestCase): void;
export function testMergePendingUpdates(tc: t.TestCase): void;
export type Enc = {
mergeUpdates: (arg0: Array<Uint8Array>) => Uint8Array;
encodeStateAsUpdate: (arg0: Y.Doc) => Uint8Array;
applyUpdate: (arg0: Y.Doc, arg1: Uint8Array) => void;
logUpdate: (arg0: Uint8Array) => void;
parseUpdateMeta: (arg0: Uint8Array) => {
from: Map<number, number>;
to: Map<number, number>;
};
encodeStateVector: (arg0: Y.Doc) => Uint8Array;
encodeStateVectorFromUpdate: (arg0: Uint8Array) => Uint8Array;
updateEventName: string;
description: string;
diffUpdate: (arg0: Uint8Array, arg1: Uint8Array) => Uint8Array;
};
import * as t from "lib0/testing";
import * as Y from "../src/index.js";

41
dist/tests/y-array.tests.d.ts vendored Normal file
View File

@ -0,0 +1,41 @@
export function testBasicUpdate(tc: t.TestCase): void;
export function testSlice(tc: t.TestCase): void;
export function testArrayFrom(tc: t.TestCase): void;
export function testLengthIssue(tc: t.TestCase): void;
export function testLengthIssue2(tc: t.TestCase): void;
export function testDeleteInsert(tc: t.TestCase): void;
export function testInsertThreeElementsTryRegetProperty(tc: t.TestCase): void;
export function testConcurrentInsertWithThreeConflicts(tc: t.TestCase): void;
export function testConcurrentInsertDeleteWithThreeConflicts(tc: t.TestCase): void;
export function testInsertionsInLateSync(tc: t.TestCase): void;
export function testDisconnectReallyPreventsSendingMessages(tc: t.TestCase): void;
export function testDeletionsInLateSync(tc: t.TestCase): void;
export function testInsertThenMergeDeleteOnSync(tc: t.TestCase): void;
export function testInsertAndDeleteEvents(tc: t.TestCase): void;
export function testNestedObserverEvents(tc: t.TestCase): void;
export function testInsertAndDeleteEventsForTypes(tc: t.TestCase): void;
export function testObserveDeepEventOrder(tc: t.TestCase): void;
export function testChangeEvent(tc: t.TestCase): void;
export function testInsertAndDeleteEventsForTypes2(tc: t.TestCase): void;
export function testNewChildDoesNotEmitEventInTransaction(tc: t.TestCase): void;
export function testGarbageCollector(tc: t.TestCase): void;
export function testEventTargetIsSetCorrectlyOnLocal(tc: t.TestCase): void;
export function testEventTargetIsSetCorrectlyOnRemote(tc: t.TestCase): void;
export function testIteratingArrayContainingTypes(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests6(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests40(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests42(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests43(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests44(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests45(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests46(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests300(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests400(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests500(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests600(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests1000(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests1800(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests3000(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests5000(tc: t.TestCase): void;
export function testRepeatGeneratingYarrayTests30000(tc: t.TestCase): void;
import * as t from "lib0/testing";

38
dist/tests/y-map.tests.d.ts vendored Normal file
View File

@ -0,0 +1,38 @@
export function testMapHavingIterableAsConstructorParamTests(tc: t.TestCase): void;
export function testBasicMapTests(tc: t.TestCase): void;
export function testGetAndSetOfMapProperty(tc: t.TestCase): void;
export function testYmapSetsYmap(tc: t.TestCase): void;
export function testYmapSetsYarray(tc: t.TestCase): void;
export function testGetAndSetOfMapPropertySyncs(tc: t.TestCase): void;
export function testGetAndSetOfMapPropertyWithConflict(tc: t.TestCase): void;
export function testSizeAndDeleteOfMapProperty(tc: t.TestCase): void;
export function testGetAndSetAndDeleteOfMapProperty(tc: t.TestCase): void;
export function testSetAndClearOfMapProperties(tc: t.TestCase): void;
export function testSetAndClearOfMapPropertiesWithConflicts(tc: t.TestCase): void;
export function testGetAndSetOfMapPropertyWithThreeConflicts(tc: t.TestCase): void;
export function testGetAndSetAndDeleteOfMapPropertyWithThreeConflicts(tc: t.TestCase): void;
export function testObserveDeepProperties(tc: t.TestCase): void;
export function testObserversUsingObservedeep(tc: t.TestCase): void;
export function testThrowsAddAndUpdateAndDeleteEvents(tc: t.TestCase): void;
export function testThrowsDeleteEventsOnClear(tc: t.TestCase): void;
export function testChangeEvent(tc: t.TestCase): void;
export function testYmapEventExceptionsShouldCompleteTransaction(tc: t.TestCase): void;
export function testYmapEventHasCorrectValueWhenSettingAPrimitive(tc: t.TestCase): void;
export function testYmapEventHasCorrectValueWhenSettingAPrimitiveFromOtherUser(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests10(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests40(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests42(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests43(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests44(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests45(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests46(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests300(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests400(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests500(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests600(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests1000(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests1800(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests5000(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests10000(tc: t.TestCase): void;
export function testRepeatGeneratingYmapTests100000(tc: t.TestCase): void;
import * as t from "lib0/testing";

42
dist/tests/y-text.tests.d.ts vendored Normal file
View File

@ -0,0 +1,42 @@
export function testDeltaAfterConcurrentFormatting(tc: t.TestCase): void;
export function testBasicInsertAndDelete(tc: t.TestCase): void;
export function testBasicFormat(tc: t.TestCase): void;
export function testMultilineFormat(tc: t.TestCase): void;
export function testNotMergeEmptyLinesFormat(tc: t.TestCase): void;
export function testPreserveAttributesThroughDelete(tc: t.TestCase): void;
export function testGetDeltaWithEmbeds(tc: t.TestCase): void;
export function testTypesAsEmbed(tc: t.TestCase): void;
export function testSnapshot(tc: t.TestCase): void;
export function testSnapshotDeleteAfter(tc: t.TestCase): void;
export function testToJson(tc: t.TestCase): void;
export function testToDeltaEmbedAttributes(tc: t.TestCase): void;
export function testToDeltaEmbedNoAttributes(tc: t.TestCase): void;
export function testFormattingRemoved(tc: t.TestCase): void;
export function testFormattingRemovedInMidText(tc: t.TestCase): void;
export function testFormattingDeltaUnnecessaryAttributeChange(tc: t.TestCase): void;
export function testInsertAndDeleteAtRandomPositions(tc: t.TestCase): void;
export function testAppendChars(tc: t.TestCase): void;
export function testBestCase(tc: t.TestCase): void;
export function testLargeFragmentedDocument(tc: t.TestCase): void;
export function testIncrementalUpdatesPerformanceOnLargeFragmentedDocument(tc: t.TestCase): void;
export function testSplitSurrogateCharacter(tc: t.TestCase): void;
export function testSearchMarkerBug1(tc: t.TestCase): void;
export function testFormattingBug(tc: t.TestCase): Promise<void>;
export function testDeleteFormatting(tc: t.TestCase): void;
export function testRepeatGenerateTextChanges5(tc: t.TestCase): void;
export function testRepeatGenerateTextChanges30(tc: t.TestCase): void;
export function testRepeatGenerateTextChanges40(tc: t.TestCase): void;
export function testRepeatGenerateTextChanges50(tc: t.TestCase): void;
export function testRepeatGenerateTextChanges70(tc: t.TestCase): void;
export function testRepeatGenerateTextChanges90(tc: t.TestCase): void;
export function testRepeatGenerateTextChanges300(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges1(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges2(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges2Repeat(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges3(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges30(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges40(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges70(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges100(tc: t.TestCase): void;
export function testRepeatGenerateQuillChanges300(tc: t.TestCase): void;
import * as t from "lib0/testing";

10
dist/tests/y-xml.tests.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
export function testSetProperty(tc: t.TestCase): void;
export function testHasProperty(tc: t.TestCase): void;
export function testEvents(tc: t.TestCase): void;
export function testTreewalker(tc: t.TestCase): void;
export function testYtextAttributes(tc: t.TestCase): void;
export function testSiblings(tc: t.TestCase): void;
export function testInsertafter(tc: t.TestCase): void;
export function testClone(tc: t.TestCase): void;
export function testFormattingBug(tc: t.TestCase): void;
import * as t from "lib0/testing";

9901
dist/yjs.js vendored Normal file

File diff suppressed because it is too large Load Diff

1
dist/yjs.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -2,10 +2,9 @@
"name": "yjs",
"version": "13.5.44",
"description": "Shared Editing Library",
"main": "./dist/yjs.cjs",
"module": "./dist/yjs.mjs",
"main": "./dist/yjs.js",
"types": "./dist/src/index.d.ts",
"type": "module",
"type": "commonjs",
"sideEffects": false,
"funding": {
"type": "GitHub Sponsors ❤",
@ -24,18 +23,6 @@
"trace-deopt": "clear && rollup -c && node --trace-deopt dist/test.cjs",
"trace-opt": "clear && rollup -c && node --trace-opt dist/test.cjs"
},
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"module": "./dist/yjs.mjs",
"import": "./dist/yjs.mjs",
"require": "./dist/yjs.cjs"
},
"./src/index.js": "./src/index.js",
"./tests/testHelper.js": "./tests/testHelper.js",
"./testHelper": "./dist/testHelper.mjs",
"./package.json": "./package.json"
},
"files": [
"dist/yjs.*",
"dist/src",

View File

@ -1,111 +1,107 @@
import nodeResolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import nodeResolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
const localImports = process.env.LOCALIMPORTS
const localImports = process.env.LOCALIMPORTS;
const customModules = new Set([
'y-websocket',
'y-codemirror',
'y-ace',
'y-textarea',
'y-quill',
'y-dom',
'y-prosemirror'
])
"y-websocket",
"y-codemirror",
"y-ace",
"y-textarea",
"y-quill",
"y-dom",
"y-prosemirror",
]);
/**
* @type {Set<any>}
*/
const customLibModules = new Set([
'lib0',
'y-protocols'
])
const customLibModules = new Set(["lib0", "y-protocols"]);
const debugResolve = {
resolveId (importee) {
if (importee === 'yjs') {
return `${process.cwd()}/src/index.js`
resolveId(importee) {
if (importee === "yjs") {
return `${process.cwd()}/src/index.js`;
}
if (localImports) {
if (customModules.has(importee.split('/')[0])) {
return `${process.cwd()}/../${importee}/src/${importee}.js`
if (customModules.has(importee.split("/")[0])) {
return `${process.cwd()}/../${importee}/src/${importee}.js`;
}
if (customLibModules.has(importee.split('/')[0])) {
return `${process.cwd()}/../${importee}`
if (customLibModules.has(importee.split("/")[0])) {
return `${process.cwd()}/../${importee}`;
}
}
return null
}
}
return null;
},
};
export default [{
input: './src/index.js',
output: {
name: 'Y',
file: 'dist/yjs.cjs',
format: 'cjs',
sourcemap: true,
paths: path => {
if (/^lib0\//.test(path)) {
return `lib0/dist/${path.slice(5)}.cjs`
}
return path
}
export default [
{
input: "./src/index.js",
output: {
name: "Y",
file: "dist/yjs.js",
format: "cjs",
sourcemap: true,
paths: (path) => {
if (/^lib0\//.test(path)) {
return `lib0/dist/${path.slice(5)}.cjs`;
}
return path;
},
},
external: (id) => /^lib0\//.test(id),
},
external: id => /^lib0\//.test(id)
}, {
input: './src/index.js',
output: {
name: 'Y',
file: 'dist/yjs.mjs',
format: 'esm',
sourcemap: true
{
input: "./tests/testHelper.js",
output: {
name: "Y",
file: "dist/testHelper.mjs",
format: "esm",
sourcemap: true,
},
external: (id) => /^lib0\//.test(id) || id === "yjs",
plugins: [
{
resolveId(importee) {
if (importee === "../src/index.js") {
return "yjs";
}
return null;
},
},
],
},
external: id => /^lib0\//.test(id)
}, {
input: './tests/testHelper.js',
output: {
name: 'Y',
file: 'dist/testHelper.mjs',
format: 'esm',
sourcemap: true
{
input: "./tests/index.js",
output: {
name: "test",
file: "dist/tests.js",
format: "iife",
sourcemap: true,
},
plugins: [
debugResolve,
nodeResolve({
mainFields: ["module", "browser", "main"],
}),
commonjs(),
],
},
external: id => /^lib0\//.test(id) || id === 'yjs',
plugins: [{
resolveId (importee) {
if (importee === '../src/index.js') {
return 'yjs'
}
return null
}
}]
}, {
input: './tests/index.js',
output: {
name: 'test',
file: 'dist/tests.js',
format: 'iife',
sourcemap: true
{
input: "./tests/index.js",
output: {
name: "test",
file: "dist/tests.cjs",
format: "cjs",
sourcemap: true,
},
plugins: [
debugResolve,
nodeResolve({
mainFields: ["module", "main"],
}),
commonjs(),
],
external: ["isomorphic.js"],
},
plugins: [
debugResolve,
nodeResolve({
mainFields: ['module', 'browser', 'main']
}),
commonjs()
]
}, {
input: './tests/index.js',
output: {
name: 'test',
file: 'dist/tests.cjs',
format: 'cjs',
sourcemap: true
},
plugins: [
debugResolve,
nodeResolve({
mainFields: ['module', 'main']
}),
commonjs()
],
external: ['isomorphic.js']
}]
];