mirror of
https://github.com/yjs/yjs.git
synced 2025-12-16 11:47:46 +01:00
fixed most tests for delta v2 migration
This commit is contained in:
@@ -233,7 +233,7 @@ export const updateMarkerChanges = (searchMarker, index, len) => {
|
|||||||
/**
|
/**
|
||||||
* Accumulate all (list) children of a type and return them as an Array.
|
* Accumulate all (list) children of a type and return them as an Array.
|
||||||
*
|
*
|
||||||
* @param {AbstractType} t
|
* @param {import('../utils/types.js').YType} t
|
||||||
* @return {Array<Item>}
|
* @return {Array<Item>}
|
||||||
*/
|
*/
|
||||||
export const getTypeChildren = t => {
|
export const getTypeChildren = t => {
|
||||||
@@ -272,7 +272,7 @@ export const callTypeObservers = (type, transaction, event) => {
|
|||||||
/**
|
/**
|
||||||
* Abstract Yjs Type class
|
* Abstract Yjs Type class
|
||||||
* @template {delta.Delta<any,any,any,any,any>} [EventDelta=delta.Delta<any,any,any,any,any>]
|
* @template {delta.Delta<any,any,any,any,any>} [EventDelta=delta.Delta<any,any,any,any,any>]
|
||||||
* @template {YType_} [Self=any]
|
* @template {AbstractType<any,any>} [Self=any]
|
||||||
*/
|
*/
|
||||||
export class AbstractType {
|
export class AbstractType {
|
||||||
constructor () {
|
constructor () {
|
||||||
@@ -442,18 +442,19 @@ export class AbstractType {
|
|||||||
* @param {import('../utils/IdSet.js').IdSet?} [opts.itemsToRender]
|
* @param {import('../utils/IdSet.js').IdSet?} [opts.itemsToRender]
|
||||||
* @param {boolean} [opts.retainInserts] - if true, retain rendered inserts with attributions
|
* @param {boolean} [opts.retainInserts] - if true, retain rendered inserts with attributions
|
||||||
* @param {boolean} [opts.retainDeletes] - if true, retain rendered+attributed deletes only
|
* @param {boolean} [opts.retainDeletes] - if true, retain rendered+attributed deletes only
|
||||||
* @param {Set<string>?} [opts.renderAttrs] - if true, retain rendered+attributed deletes only
|
* @param {Set<string>?} [opts.renderAttrs] - set of attrs to render. if null, render all attributes
|
||||||
* @param {boolean} [opts.renderChildren] - if true, retain rendered+attributed deletes only
|
* @param {boolean} [opts.renderChildren] - if true, retain rendered+attributed deletes only
|
||||||
|
* @param {import('../utils/IdSet.js').IdSet?} [opts.deletedItems] - used for computing prevItem in attributes
|
||||||
* @return {EventDelta} The Delta representation of this type.
|
* @return {EventDelta} The Delta representation of this type.
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
getContent (am = noAttributionsManager, { itemsToRender = null, retainInserts = false, retainDeletes = false, renderAttrs = null, renderChildren = true } = {}) {
|
getContent (am = noAttributionsManager, { itemsToRender = null, retainInserts = false, retainDeletes = false, renderAttrs = null, renderChildren = true, deletedItems = null } = {}) {
|
||||||
/**
|
/**
|
||||||
* @type {EventDelta}
|
* @type {EventDelta}
|
||||||
*/
|
*/
|
||||||
const d = /** @type {any} */ (delta.create())
|
const d = /** @type {any} */ (delta.create())
|
||||||
typeMapGetDelta(d, /** @type {any} */ (this), renderAttrs, am)
|
typeMapGetDelta(d, /** @type {any} */ (this), renderAttrs, am, deletedItems, itemsToRender)
|
||||||
if (renderChildren) {
|
if (renderChildren) {
|
||||||
/**
|
/**
|
||||||
* @type {delta.FormattingAttributes}
|
* @type {delta.FormattingAttributes}
|
||||||
@@ -625,7 +626,7 @@ export class AbstractType {
|
|||||||
* @type {import('../utils/AttributionManager.js').Attribution}
|
* @type {import('../utils/AttributionManager.js').Attribution}
|
||||||
*/
|
*/
|
||||||
const formattingAttribution = object.assign({}, d.usedAttribution)
|
const formattingAttribution = object.assign({}, d.usedAttribution)
|
||||||
const changedAttributedAttributes = /** @type {{ [key: string]: Array<any> }} */ (formattingAttribution.attributes = object.assign({}, formattingAttribution.attributes ?? {}))
|
const changedAttributedAttributes = /** @type {{ [key: string]: Array<any> }} */ (formattingAttribution.format = object.assign({}, formattingAttribution.format ?? {}))
|
||||||
if (attribution == null || equalAttrs(previousUnattributedAttributes[key], currentAttributes[key] ?? null)) {
|
if (attribution == null || equalAttrs(previousUnattributedAttributes[key], currentAttributes[key] ?? null)) {
|
||||||
// an unattributed formatting attribute was found or an attributed formatting
|
// an unattributed formatting attribute was found or an attributed formatting
|
||||||
// attribute was found that resets to the previous status
|
// attribute was found that resets to the previous status
|
||||||
@@ -635,13 +636,13 @@ export class AbstractType {
|
|||||||
const by = changedAttributedAttributes[key] = (changedAttributedAttributes[key]?.slice() ?? [])
|
const by = changedAttributedAttributes[key] = (changedAttributedAttributes[key]?.slice() ?? [])
|
||||||
by.push(...((c.deleted ? attribution.delete : attribution.insert) ?? []))
|
by.push(...((c.deleted ? attribution.delete : attribution.insert) ?? []))
|
||||||
const attributedAt = (c.deleted ? attribution.deletedAt : attribution.insertedAt)
|
const attributedAt = (c.deleted ? attribution.deletedAt : attribution.insertedAt)
|
||||||
if (attributedAt) formattingAttribution.attributedAt = attributedAt
|
if (attributedAt) formattingAttribution.formatAt = attributedAt
|
||||||
}
|
}
|
||||||
if (object.isEmpty(changedAttributedAttributes)) {
|
if (object.isEmpty(changedAttributedAttributes)) {
|
||||||
d.useAttribution(null)
|
d.useAttribution(null)
|
||||||
} else if (attribution != null) {
|
} else if (attribution != null) {
|
||||||
const attributedAt = (c.deleted ? attribution.deletedAt : attribution.insertedAt)
|
const attributedAt = (c.deleted ? attribution.deletedAt : attribution.insertedAt)
|
||||||
if (attributedAt != null) formattingAttribution.attributedAt = attributedAt
|
if (attributedAt != null) formattingAttribution.formatAt = attributedAt
|
||||||
d.useAttribution(formattingAttribution)
|
d.useAttribution(formattingAttribution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,7 +652,7 @@ export class AbstractType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return d
|
return /** @type {any} */ (d.done())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -678,7 +679,7 @@ export class AbstractType {
|
|||||||
op.value = op.value.getContentDeep(am)
|
op.value = op.value.getContentDeep(am)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return /** @type {any} */ (d)
|
return /** @type {any} */ (d.done())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,47 +769,6 @@ export const typeListToArray = type => {
|
|||||||
return cs
|
return cs
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo this can be removed as this can be replaced by a generic function
|
|
||||||
* Render the difference to another ydoc (which can be empty) and highlight the differences with
|
|
||||||
* attributions.
|
|
||||||
*
|
|
||||||
* Note that deleted content that was not deleted in prevYdoc is rendered as an insertion with the
|
|
||||||
* attribution `{ isDeleted: true, .. }`.
|
|
||||||
*
|
|
||||||
* @template {delta.Delta<any,any,any,any>} TypeDelta
|
|
||||||
* @param {TypeDelta} d
|
|
||||||
* @param {import('../utils/types.js').YType} type
|
|
||||||
* @param {import('../internals.js').AbstractAttributionManager} am
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @function
|
|
||||||
*/
|
|
||||||
export const typeListGetContent = (d, type, am) => {
|
|
||||||
type.doc ?? warnPrematureAccess()
|
|
||||||
/**
|
|
||||||
* @type {Array<import('../internals.js').AttributedContent<any>>}
|
|
||||||
*/
|
|
||||||
const cs = []
|
|
||||||
for (let item = type._start; item !== null; cs.length = 0) {
|
|
||||||
// populate cs
|
|
||||||
for (; item !== null && cs.length < 50; item = item.right) {
|
|
||||||
am.readContent(cs, item.id.client, item.id.clock, item.deleted, item.content, 1)
|
|
||||||
}
|
|
||||||
for (let i = 0; i < cs.length; i++) {
|
|
||||||
const c = cs[i]
|
|
||||||
const attribution = createAttributionFromAttributionItems(c.attrs, c.deleted)
|
|
||||||
if (c.content.isCountable()) {
|
|
||||||
if (c.render || attribution != null) {
|
|
||||||
d.insert(c.content.getContent(), null, attribution)
|
|
||||||
} else if (!c.deleted) {
|
|
||||||
d.retain(c.content.getLength())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {AbstractType<any>} type
|
* @param {AbstractType<any>} type
|
||||||
* @param {Snapshot} snapshot
|
* @param {Snapshot} snapshot
|
||||||
@@ -1270,13 +1230,13 @@ export const typeMapGetAll = (parent) => {
|
|||||||
* @param {YType_} parent
|
* @param {YType_} parent
|
||||||
* @param {Set<string>?} attrsToRender
|
* @param {Set<string>?} attrsToRender
|
||||||
* @param {import('../internals.js').AbstractAttributionManager} am
|
* @param {import('../internals.js').AbstractAttributionManager} am
|
||||||
|
* @param {import('../utils/IdSet.js').IdSet?} [deletedItems]
|
||||||
|
* @param {import('../utils/IdSet.js').IdSet?} [itemsToRender]
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const typeMapGetDelta = (d, parent, attrsToRender, am) => {
|
export const typeMapGetDelta = (d, parent, attrsToRender, am, deletedItems, itemsToRender) => {
|
||||||
parent.doc ?? warnPrematureAccess()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Item} item
|
* @param {Item} item
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
@@ -1291,28 +1251,17 @@ export const typeMapGetDelta = (d, parent, attrsToRender, am) => {
|
|||||||
const c = array.last(content.getContent())
|
const c = array.last(content.getContent())
|
||||||
const attribution = createAttributionFromAttributionItems(attrs, deleted)
|
const attribution = createAttributionFromAttributionItems(attrs, deleted)
|
||||||
if (deleted) {
|
if (deleted) {
|
||||||
d.unset(key, attribution, c)
|
if (itemsToRender == null || itemsToRender.hasId(item.lastId)) {
|
||||||
} else {
|
d.unset(key, attribution, c)
|
||||||
/**
|
|
||||||
* @type {Array<import('../internals.js').AttributedContent<any>>}
|
|
||||||
*/
|
|
||||||
let cs = []
|
|
||||||
for (let prevItem = item.left; prevItem != null; prevItem = prevItem.left) {
|
|
||||||
/**
|
|
||||||
* @type {Array<import('../internals.js').AttributedContent<any>>}
|
|
||||||
*/
|
|
||||||
const tmpcs = []
|
|
||||||
am.readContent(tmpcs, prevItem.id.client, prevItem.id.clock, prevItem.deleted, prevItem.content, 1)
|
|
||||||
cs = tmpcs.concat(cs)
|
|
||||||
if (cs.length === 0 || cs[0].attrs == null) {
|
|
||||||
cs.splice(0, cs.findIndex(c => c.attrs != null))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (cs.length > 0) {
|
|
||||||
cs.length = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const prevValue = cs.length > 0 ? array.last(cs[0].content.getContent()) : undefined
|
} else {
|
||||||
|
// find prev content
|
||||||
|
let prevContentItem = item
|
||||||
|
// this algorithm is problematic. should check all previous content using am.readcontent
|
||||||
|
for (; prevContentItem.left !== null && deletedItems?.hasId(prevContentItem.left.lastId); prevContentItem = prevContentItem.left) {
|
||||||
|
// nop
|
||||||
|
}
|
||||||
|
const prevValue = (prevContentItem !== item && itemsToRender?.hasId(prevContentItem.lastId)) ? array.last(prevContentItem.content.getContent()) : undefined
|
||||||
d.set(key, c, attribution, prevValue)
|
d.set(key, c, attribution, prevValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import {
|
|||||||
callTypeObservers,
|
callTypeObservers,
|
||||||
transact,
|
transact,
|
||||||
warnPrematureAccess,
|
warnPrematureAccess,
|
||||||
typeListGetContent,
|
|
||||||
typeListSlice,
|
typeListSlice,
|
||||||
noAttributionsManager,
|
noAttributionsManager,
|
||||||
AbstractAttributionManager, ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
|
AbstractAttributionManager, ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
|
||||||
@@ -108,7 +107,7 @@ export class YArray extends AbstractType {
|
|||||||
*/
|
*/
|
||||||
_callObserver (transaction, parentSubs) {
|
_callObserver (transaction, parentSubs) {
|
||||||
super._callObserver(transaction, parentSubs)
|
super._callObserver(transaction, parentSubs)
|
||||||
callTypeObservers(this, transaction, new YEvent(this, transaction, null))
|
callTypeObservers(this, transaction, new YEvent(this, transaction, parentSubs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,24 +213,6 @@ export class YArray extends AbstractType {
|
|||||||
return super.getContentDeep(am)
|
return super.getContentDeep(am)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Render the difference to another ydoc (which can be empty) and highlight the differences with
|
|
||||||
* attributions.
|
|
||||||
*
|
|
||||||
* Note that deleted content that was not deleted in prevYdoc is rendered as an insertion with the
|
|
||||||
* attribution `{ isDeleted: true, .. }`.
|
|
||||||
*
|
|
||||||
* @param {AbstractAttributionManager} am
|
|
||||||
* @return {delta.ArrayDelta<T>} The Delta representation of this type.
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
getContent (am = noAttributionsManager) {
|
|
||||||
const d = this.change
|
|
||||||
typeListGetContent(d, this, am)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a portion of this YArray into a JavaScript Array selected
|
* Returns a portion of this YArray into a JavaScript Array selected
|
||||||
* from start to end (end not included).
|
* from start to end (end not included).
|
||||||
|
|||||||
@@ -758,9 +758,11 @@ export class YText extends AbstractType {
|
|||||||
transact(this.doc, transaction => {
|
transact(this.doc, transaction => {
|
||||||
const currPos = new ItemTextListPosition(null, this._start, 0, new Map(), am)
|
const currPos = new ItemTextListPosition(null, this._start, 0, new Map(), am)
|
||||||
for (const op of d.children) {
|
for (const op of d.children) {
|
||||||
if (delta.$insertOp.check(op)) {
|
if (delta.$textOp.check(op)) {
|
||||||
if (op.insert.length > 0 || typeof op.insert !== 'string') {
|
insertText(transaction, this, currPos, op.insert, op.format || {})
|
||||||
insertText(transaction, this, currPos, op.insert, op.format || {})
|
} else if (delta.$insertOp.check(op)) {
|
||||||
|
for (let i = 0; i < op.insert.length; i++) {
|
||||||
|
insertText(transaction, this, currPos, op.insert[i], op.format || {})
|
||||||
}
|
}
|
||||||
} else if (delta.$retainOp.check(op)) {
|
} else if (delta.$retainOp.check(op)) {
|
||||||
currPos.formatText(transaction, this, op.retain, op.format || {})
|
currPos.formatText(transaction, this, op.retain, op.format || {})
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ export const attributionJsonSchema = s.$object({
|
|||||||
insertedAt: s.$number.optional,
|
insertedAt: s.$number.optional,
|
||||||
delete: s.$array(s.$string).optional,
|
delete: s.$array(s.$string).optional,
|
||||||
deletedAt: s.$number.optional,
|
deletedAt: s.$number.optional,
|
||||||
attributes: s.$record(s.$string, s.$array(s.$string)).optional,
|
format: s.$record(s.$string, s.$array(s.$string)).optional,
|
||||||
attributedAt: s.$number.optional
|
formatAt: s.$number.optional
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -41,10 +41,6 @@ export class YEvent {
|
|||||||
* @type {Transaction}
|
* @type {Transaction}
|
||||||
*/
|
*/
|
||||||
this.transaction = transaction
|
this.transaction = transaction
|
||||||
/**
|
|
||||||
* @type {Object|null}
|
|
||||||
*/
|
|
||||||
this._changes = null
|
|
||||||
/**
|
/**
|
||||||
* @type {null | Map<string, { action: 'add' | 'update' | 'delete', oldValue: any }>}
|
* @type {null | Map<string, { action: 'add' | 'update' | 'delete', oldValue: any }>}
|
||||||
*/
|
*/
|
||||||
@@ -183,7 +179,7 @@ export class YEvent {
|
|||||||
*/
|
*/
|
||||||
getDelta (am = noAttributionsManager) {
|
getDelta (am = noAttributionsManager) {
|
||||||
const itemsToRender = mergeIdSets([diffIdSet(this.transaction.insertSet, this.transaction.deleteSet), diffIdSet(this.transaction.deleteSet, this.transaction.insertSet)])
|
const itemsToRender = mergeIdSets([diffIdSet(this.transaction.insertSet, this.transaction.deleteSet), diffIdSet(this.transaction.deleteSet, this.transaction.insertSet)])
|
||||||
return /** @type {any} */ (this.target.getContent(am, { itemsToRender, retainDeletes: true, renderAttrs: this.keysChanged, renderChildren: this.childListChanged }))
|
return /** @type {any} */ (this.target.getContent(am, { itemsToRender, retainDeletes: true, renderAttrs: this.keysChanged, renderChildren: this.childListChanged, deletedItems: this.transaction.deleteSet }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,15 +1,4 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object<string,any>|Array<any>|number|null|string|Uint8Array|BigInt
|
|
||||||
* |import('../index.js').Array<any>
|
|
||||||
* |import('../index.js').Map<any>
|
|
||||||
* |import('../index.js').Text<any>
|
|
||||||
* |import('../index.js').XmlElement<any>
|
|
||||||
* |import('../index.js').XmlFragment<any>
|
|
||||||
* |import('../index.js').XmlText
|
|
||||||
* |import('../index.js').XmlHook} YValue
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../types/YArray.js').YArray<any>
|
* @typedef {import('../types/YArray.js').YArray<any>
|
||||||
* | import('../types/YMap.js').YMap<any>
|
* | import('../types/YMap.js').YMap<any>
|
||||||
@@ -17,15 +6,17 @@
|
|||||||
* | import('../types/YXmlFragment.js').YXmlFragment<any,any>
|
* | import('../types/YXmlFragment.js').YXmlFragment<any,any>
|
||||||
* | import('../types/YXmlElement.js').YXmlElement<any,any>
|
* | import('../types/YXmlElement.js').YXmlElement<any,any>
|
||||||
* | import('../types/YXmlHook.js').YXmlHook
|
* | import('../types/YXmlHook.js').YXmlHook
|
||||||
* | import('../types/YXmlText.js').YXmlText} YType
|
* | import('../types/YXmlText.js').YXmlText} YValueType
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {typeof import('../types/YArray.js').YArray<any>
|
* @typedef {Object<string,any>|Array<any>|number|null|string|Uint8Array|BigInt|YValueType} YValue
|
||||||
* | typeof import('../types/YMap.js').YMap<any>
|
*/
|
||||||
* | typeof import('../types/YText.js').YText<any>
|
|
||||||
* | typeof import('../types/YXmlFragment.js').YXmlFragment<any,any>
|
/**
|
||||||
* | typeof import('../types/YXmlElement.js').YXmlElement<any,any>
|
* @typedef {import('../types/AbstractType.js').AbstractType<any,any>} YType
|
||||||
* | typeof import('../types/YXmlHook.js').YXmlHook
|
*/
|
||||||
* | typeof import('../types/YXmlText.js').YXmlText} YTypeConstructors
|
|
||||||
|
/**
|
||||||
|
* @typedef {typeof import('../types/AbstractType.js').AbstractType<any,any>} YTypeConstructors
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
"lib0/conditions": "./node_modules/lib0/conditions.js",
|
"lib0/conditions": "./node_modules/lib0/conditions.js",
|
||||||
"lib0/crypto/jwt": "./node_modules/lib0/crypto/jwt.js",
|
"lib0/crypto/jwt": "./node_modules/lib0/crypto/jwt.js",
|
||||||
"lib0/crypto/aes-gcm": "./node_modules/lib0/crypto/aes-gcm.js",
|
"lib0/crypto/aes-gcm": "./node_modules/lib0/crypto/aes-gcm.js",
|
||||||
|
"lib0/delta": "./node_modules/lib0/delta/d2.js",
|
||||||
"lib0/crypto/ecdsa": "./node_modules/lib0/crypto/ecdsa.js",
|
"lib0/crypto/ecdsa": "./node_modules/lib0/crypto/ecdsa.js",
|
||||||
"lib0/crypto/rsa-oaep": "./node_modules/lib0/crypto/rsa-oaep.js",
|
"lib0/crypto/rsa-oaep": "./node_modules/lib0/crypto/rsa-oaep.js",
|
||||||
"lib0/hash/rabin": "./node_modules/lib0/hash/rabin.js",
|
"lib0/hash/rabin": "./node_modules/lib0/hash/rabin.js",
|
||||||
@@ -201,6 +202,7 @@
|
|||||||
"lib0/conditions": "./node_modules/lib0/conditions.js",
|
"lib0/conditions": "./node_modules/lib0/conditions.js",
|
||||||
"lib0/crypto/jwt": "./node_modules/lib0/crypto/jwt.js",
|
"lib0/crypto/jwt": "./node_modules/lib0/crypto/jwt.js",
|
||||||
"lib0/crypto/aes-gcm": "./node_modules/lib0/crypto/aes-gcm.js",
|
"lib0/crypto/aes-gcm": "./node_modules/lib0/crypto/aes-gcm.js",
|
||||||
|
"lib0/delta": "./node_modules/lib0/delta/d2.js",
|
||||||
"lib0/crypto/ecdsa": "./node_modules/lib0/crypto/ecdsa.js",
|
"lib0/crypto/ecdsa": "./node_modules/lib0/crypto/ecdsa.js",
|
||||||
"lib0/crypto/rsa-oaep": "./node_modules/lib0/crypto/rsa-oaep.js",
|
"lib0/crypto/rsa-oaep": "./node_modules/lib0/crypto/rsa-oaep.js",
|
||||||
"lib0/hash/rabin": "./node_modules/lib0/hash/rabin.js",
|
"lib0/hash/rabin": "./node_modules/lib0/hash/rabin.js",
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export const testFindTypeInOtherDoc = _tc => {
|
|||||||
const ydocClone = new Y.Doc()
|
const ydocClone = new Y.Doc()
|
||||||
Y.applyUpdate(ydocClone, Y.encodeStateAsUpdate(ydoc))
|
Y.applyUpdate(ydocClone, Y.encodeStateAsUpdate(ydoc))
|
||||||
/**
|
/**
|
||||||
* @template {Y.AbstractType<any>} Type
|
* @template {import('../src/utils/types.js').YType} Type
|
||||||
* @param {Type} ytype
|
* @param {Type} ytype
|
||||||
* @param {Y.Doc} otherYdoc
|
* @param {Y.Doc} otherYdoc
|
||||||
* @return {Type}
|
* @return {Type}
|
||||||
@@ -47,7 +47,7 @@ export const testFindTypeInOtherDoc = _tc => {
|
|||||||
if (rootKey == null) {
|
if (rootKey == null) {
|
||||||
throw new Error('type does not exist in other ydoc')
|
throw new Error('type does not exist in other ydoc')
|
||||||
}
|
}
|
||||||
return /** @type {Type} */ (otherYdoc.get(rootKey, /** @type {typeof Y.AbstractType<any>} */ (ytype.constructor)))
|
return /** @type {Type} */ (otherYdoc.get(rootKey, /** @type {import('../src/utils/types.js').YTypeConstructors} */ (ytype.constructor)))
|
||||||
} else {
|
} else {
|
||||||
/**
|
/**
|
||||||
* If it is a sub type, we use the item id to find the history type.
|
* If it is a sub type, we use the item id to find the history type.
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import * as object from 'lib0/object'
|
|||||||
import * as map from 'lib0/map'
|
import * as map from 'lib0/map'
|
||||||
import * as Y from '../src/index.js'
|
import * as Y from '../src/index.js'
|
||||||
import * as math from 'lib0/math'
|
import * as math from 'lib0/math'
|
||||||
|
import * as list from 'lib0/list'
|
||||||
|
import * as delta from 'lib0/delta'
|
||||||
import {
|
import {
|
||||||
createIdSet, createIdMap, addToIdSet, encodeIdMap
|
createIdSet, createIdMap, addToIdSet, encodeIdMap
|
||||||
} from '../src/internals.js'
|
} from '../src/internals.js'
|
||||||
@@ -484,7 +486,7 @@ export const compare = users => {
|
|||||||
t.compare(userArrayValues[i], userArrayValues[i + 1])
|
t.compare(userArrayValues[i], userArrayValues[i + 1])
|
||||||
t.compare(userMapValues[i], userMapValues[i + 1])
|
t.compare(userMapValues[i], userMapValues[i + 1])
|
||||||
t.compare(userXmlValues[i], userXmlValues[i + 1])
|
t.compare(userXmlValues[i], userXmlValues[i + 1])
|
||||||
t.compare(userTextValues[i].ops.map(/** @param {any} a */ a => typeof a.insert === 'string' ? a.insert : ' ').join('').length, users[i].getText('text').length)
|
t.compare(list.toArray(userTextValues[i].children).map(a => delta.$textOp.check(a) ? a.insert : ' ').join('').length, users[i].getText('text').length)
|
||||||
t.compare(userTextValues[i], userTextValues[i + 1], '', (_constructor, a, b) => {
|
t.compare(userTextValues[i], userTextValues[i + 1], '', (_constructor, a, b) => {
|
||||||
if (a instanceof Y.AbstractType) {
|
if (a instanceof Y.AbstractType) {
|
||||||
t.compare(a.toJSON(), b.toJSON())
|
t.compare(a.toJSON(), b.toJSON())
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as Y from '../src/index.js'
|
import * as Y from '../src/index.js'
|
||||||
import { init } from './testHelper.js' // eslint-disable-line
|
import { init } from './testHelper.js' // eslint-disable-line
|
||||||
import * as t from 'lib0/testing'
|
import * as t from 'lib0/testing'
|
||||||
import * as delta from '../src/utils/Delta.js'
|
import * as delta from 'lib0/delta'
|
||||||
|
|
||||||
export const testInconsistentFormat = () => {
|
export const testInconsistentFormat = () => {
|
||||||
/**
|
/**
|
||||||
@@ -11,7 +11,7 @@ export const testInconsistentFormat = () => {
|
|||||||
const content = /** @type {Y.XmlText} */ (ydoc.get('text', Y.XmlText))
|
const content = /** @type {Y.XmlText} */ (ydoc.get('text', Y.XmlText))
|
||||||
content.format(0, 6, { bold: null })
|
content.format(0, 6, { bold: null })
|
||||||
content.format(6, 4, { type: 'text' })
|
content.format(6, 4, { type: 'text' })
|
||||||
t.compare(content.getContent(), delta.createTextDelta().insert('Merge Test', { type: 'text' }).insert(' After', { type: 'text', italic: true }))
|
t.compare(content.getContent(), delta.create().insert('Merge Test', { type: 'text' }).insert(' After', { type: 'text', italic: true }))
|
||||||
}
|
}
|
||||||
const initializeYDoc = () => {
|
const initializeYDoc = () => {
|
||||||
const yDoc = new Y.Doc({ gc: false })
|
const yDoc = new Y.Doc({ gc: false })
|
||||||
@@ -85,11 +85,11 @@ export const testUndoText = tc => {
|
|||||||
t.assert(text0.toString() === 'bcxyz')
|
t.assert(text0.toString() === 'bcxyz')
|
||||||
// test marks
|
// test marks
|
||||||
text0.format(1, 3, { bold: true })
|
text0.format(1, 3, { bold: true })
|
||||||
t.compare(text0.getContent(), delta.fromJSON([{ insert: 'b' }, { insert: 'cxy', attributes: { bold: true } }, { insert: 'z' }]))
|
t.compare(text0.getContent(), delta.create().insert('b').insert('cxy', { bold: true }).insert('z'))
|
||||||
undoManager.undo()
|
undoManager.undo()
|
||||||
t.compare(text0.getContent(), delta.fromJSON([{ insert: 'bcxyz' }]))
|
t.compare(text0.getContent(), delta.create().insert('bcxyz'))
|
||||||
undoManager.redo()
|
undoManager.redo()
|
||||||
t.compare(text0.getContent(), delta.fromJSON([{ insert: 'b' }, { insert: 'cxy', attributes: { bold: true } }, { insert: 'z' }]))
|
t.compare(text0.getContent(), delta.create().insert('b').insert('cxy', { bold: true }).insert('z'))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -677,14 +677,10 @@ export const testUndoDeleteTextFormat = _tc => {
|
|||||||
undoManager.undo()
|
undoManager.undo()
|
||||||
Y.applyUpdate(doc2, Y.encodeStateAsUpdate(doc))
|
Y.applyUpdate(doc2, Y.encodeStateAsUpdate(doc))
|
||||||
|
|
||||||
const expect = delta.fromJSON([
|
const expect = delta.create()
|
||||||
{ insert: 'Attack ships ' },
|
.insert('Attack ships ')
|
||||||
{
|
.insert('on fire', { bold: true })
|
||||||
insert: 'on fire',
|
.insert(' off the shoulder of Orion.')
|
||||||
attributes: { bold: true }
|
|
||||||
},
|
|
||||||
{ insert: ' off the shoulder of Orion.' }
|
|
||||||
])
|
|
||||||
t.compare(text.getContent(), expect)
|
t.compare(text.getContent(), expect)
|
||||||
t.compare(text2.getContent(), expect)
|
t.compare(text2.getContent(), expect)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { readStructSet, readIdSet, UpdateDecoderV2, UpdateEncoderV2, writeIdSet
|
|||||||
import * as encoding from 'lib0/encoding'
|
import * as encoding from 'lib0/encoding'
|
||||||
import * as decoding from 'lib0/decoding'
|
import * as decoding from 'lib0/decoding'
|
||||||
import * as object from 'lib0/object'
|
import * as object from 'lib0/object'
|
||||||
|
import * as delta from 'lib0/delta'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} Enc
|
* @typedef {Object} Enc
|
||||||
@@ -126,7 +127,7 @@ export const testKeyEncoding = tc => {
|
|||||||
const update = Y.encodeStateAsUpdateV2(users[0])
|
const update = Y.encodeStateAsUpdateV2(users[0])
|
||||||
Y.applyUpdateV2(users[1], update)
|
Y.applyUpdateV2(users[1], update)
|
||||||
|
|
||||||
t.compare(text1.getContent().toJSON(), [{ insert: 'c', attributes: { italic: true } }, { insert: 'b' }, { insert: 'a', attributes: { italic: true } }])
|
t.compare(text1.getContent().toJSON().children, [{ insert: 'c', format: { italic: true } }, { insert: 'b' }, { insert: 'a', format: { italic: true } }])
|
||||||
|
|
||||||
compare(users)
|
compare(users)
|
||||||
}
|
}
|
||||||
@@ -207,7 +208,7 @@ const checkUpdateCases = (ydoc, updates, enc, hasDeletes) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const meta = enc.parseUpdateMeta(mergedUpdates)
|
const meta = enc.parseUpdateMeta(mergedUpdates)
|
||||||
meta.from.forEach((clock, client) => t.assert(clock === 0))
|
meta.from.forEach((clock, _client) => t.assert(clock === 0))
|
||||||
meta.to.forEach((clock, client) => {
|
meta.to.forEach((clock, client) => {
|
||||||
const structs = /** @type {Array<Y.Item>} */ (merged.store.clients.get(client))
|
const structs = /** @type {Array<Y.Item>} */ (merged.store.clients.get(client))
|
||||||
const lastStruct = structs[structs.length - 1]
|
const lastStruct = structs[structs.length - 1]
|
||||||
@@ -237,10 +238,10 @@ export const testMergeUpdates1 = _tc => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {t.TestCase} tc
|
* @param {t.TestCase} _tc
|
||||||
*/
|
*/
|
||||||
export const testMergeUpdates2 = tc => {
|
export const testMergeUpdates2 = _tc => {
|
||||||
encoders.forEach((enc, i) => {
|
encoders.forEach((enc, _i) => {
|
||||||
t.info(`Using encoder: ${enc.description}`)
|
t.info(`Using encoder: ${enc.description}`)
|
||||||
const ydoc = new Y.Doc({ gc: false })
|
const ydoc = new Y.Doc({ gc: false })
|
||||||
const updates = /** @type {Array<Uint8Array>} */ ([])
|
const updates = /** @type {Array<Uint8Array>} */ ([])
|
||||||
@@ -257,23 +258,23 @@ export const testMergeUpdates2 = tc => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {t.TestCase} tc
|
* @param {t.TestCase} _tc
|
||||||
*/
|
*/
|
||||||
export const testMergePendingUpdates = tc => {
|
export const testMergePendingUpdates = _tc => {
|
||||||
const yDoc = new Y.Doc()
|
const yDoc = new Y.Doc()
|
||||||
/**
|
/**
|
||||||
* @type {Array<Uint8Array>}
|
* @type {Array<Uint8Array>}
|
||||||
*/
|
*/
|
||||||
const serverUpdates = []
|
const serverUpdates = []
|
||||||
yDoc.on('update', (update, origin, c) => {
|
yDoc.on('update', (update, _origin, _c) => {
|
||||||
serverUpdates.splice(serverUpdates.length, 0, update)
|
serverUpdates.splice(serverUpdates.length, 0, update)
|
||||||
})
|
})
|
||||||
const yText = yDoc.getText('textBlock')
|
const yText = yDoc.getText('textBlock')
|
||||||
yText.applyDelta([{ insert: 'r' }])
|
yText.applyDelta(delta.create().insert('r'))
|
||||||
yText.applyDelta([{ insert: 'o' }])
|
yText.applyDelta(delta.create().insert('o'))
|
||||||
yText.applyDelta([{ insert: 'n' }])
|
yText.applyDelta(delta.create().insert('n'))
|
||||||
yText.applyDelta([{ insert: 'e' }])
|
yText.applyDelta(delta.create().insert('e'))
|
||||||
yText.applyDelta([{ insert: 'n' }])
|
yText.applyDelta(delta.create().insert('n'))
|
||||||
|
|
||||||
const yDoc1 = new Y.Doc()
|
const yDoc1 = new Y.Doc()
|
||||||
Y.applyUpdate(yDoc1, serverUpdates[0])
|
Y.applyUpdate(yDoc1, serverUpdates[0])
|
||||||
@@ -297,8 +298,7 @@ export const testMergePendingUpdates = tc => {
|
|||||||
const yDoc5 = new Y.Doc()
|
const yDoc5 = new Y.Doc()
|
||||||
Y.applyUpdate(yDoc5, update4)
|
Y.applyUpdate(yDoc5, update4)
|
||||||
Y.applyUpdate(yDoc5, serverUpdates[4])
|
Y.applyUpdate(yDoc5, serverUpdates[4])
|
||||||
// @ts-ignore
|
Y.encodeStateAsUpdate(yDoc5)
|
||||||
const _update5 = Y.encodeStateAsUpdate(yDoc5) // eslint-disable-line
|
|
||||||
|
|
||||||
const yText5 = yDoc5.getText('textBlock')
|
const yText5 = yDoc5.getText('textBlock')
|
||||||
t.compareStrings(yText5.toString(), 'nenor')
|
t.compareStrings(yText5.toString(), 'nenor')
|
||||||
@@ -313,7 +313,7 @@ export const testObfuscateUpdates = _tc => {
|
|||||||
const ymap = ydoc.getMap('map')
|
const ymap = ydoc.getMap('map')
|
||||||
const yarray = ydoc.getArray('array')
|
const yarray = ydoc.getArray('array')
|
||||||
// test ytext
|
// test ytext
|
||||||
ytext.applyDelta([{ insert: 'text', attributes: { bold: true } }, { insert: { href: 'supersecreturl' } }])
|
ytext.applyDelta(delta.create().insert('text', { bold: true }).insert([{ href: 'supersecreturl' }]))
|
||||||
// test ymap
|
// test ymap
|
||||||
ymap.set('key', 'secret1')
|
ymap.set('key', 'secret1')
|
||||||
ymap.set('key', 'secret2')
|
ymap.set('key', 'secret2')
|
||||||
@@ -330,13 +330,14 @@ export const testObfuscateUpdates = _tc => {
|
|||||||
const omap = odoc.getMap('map')
|
const omap = odoc.getMap('map')
|
||||||
const oarray = odoc.getArray('array')
|
const oarray = odoc.getArray('array')
|
||||||
// test ytext
|
// test ytext
|
||||||
const delta = /** @type {Array<any>} */ (otext.getContent().toJSON())
|
const d = /** @type {any} */ (otext.getContent().toJSON().children)
|
||||||
t.assert(delta.length === 2)
|
t.assert(d.length === 2)
|
||||||
t.assert(delta[0].insert !== 'text' && delta[0].insert.length === 4)
|
const q = d[0]
|
||||||
t.assert(object.length(delta[0].attributes) === 1)
|
t.assert(d[0].insert !== 'text' && d[0].insert.length === 4)
|
||||||
t.assert(!object.hasProperty(delta[0].attributes, 'bold'))
|
t.assert(object.length(d[0].format) === 1)
|
||||||
t.assert(object.length(delta[1]) === 1)
|
t.assert(!object.hasProperty(d[0].format, 'bold'))
|
||||||
t.assert(object.hasProperty(delta[1], 'insert'))
|
t.assert(object.length(d[1]) === 1)
|
||||||
|
t.assert(object.hasProperty(d[1], 'insert'))
|
||||||
// test ymap
|
// test ymap
|
||||||
t.assert(omap.size === 1)
|
t.assert(omap.size === 1)
|
||||||
t.assert(!omap.has('key'))
|
t.assert(!omap.has('key'))
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as t from 'lib0/testing'
|
|||||||
import * as prng from 'lib0/prng'
|
import * as prng from 'lib0/prng'
|
||||||
import * as math from 'lib0/math'
|
import * as math from 'lib0/math'
|
||||||
import * as env from 'lib0/environment'
|
import * as env from 'lib0/environment'
|
||||||
import * as delta from '../src/utils/Delta.js'
|
import * as delta from 'lib0/delta'
|
||||||
|
|
||||||
const isDevMode = env.getVariable('node_env') === 'development'
|
const isDevMode = env.getVariable('node_env') === 'development'
|
||||||
|
|
||||||
@@ -384,24 +384,22 @@ export const testObservedeepIndexes = _tc => {
|
|||||||
export const testChangeEvent = tc => {
|
export const testChangeEvent = tc => {
|
||||||
const { array0, users } = init(tc, { users: 2 })
|
const { array0, users } = init(tc, { users: 2 })
|
||||||
/**
|
/**
|
||||||
* @type {any}
|
* @type {delta.Delta<any,any,any,any,any>}
|
||||||
*/
|
*/
|
||||||
let changes = null
|
let d = delta.create()
|
||||||
array0.observe(e => {
|
array0.observe(e => {
|
||||||
changes = e.changes
|
d = e.delta
|
||||||
})
|
})
|
||||||
const newArr = new Y.Array()
|
const newArr = new Y.Array()
|
||||||
array0.insert(0, [newArr, 4, 'dtrn'])
|
array0.insert(0, [newArr, 4, 'dtrn'])
|
||||||
t.assert(changes !== null && changes.added.size === 2 && changes.deleted.size === 0)
|
t.assert(d !== null && d.children.len === 1)
|
||||||
t.compare(changes.delta, [{ insert: [newArr, 4, 'dtrn'] }])
|
t.compare(d.toJSON().children, [{ insert: [newArr, 4, 'dtrn'] }])
|
||||||
changes = null
|
|
||||||
array0.delete(0, 2)
|
array0.delete(0, 2)
|
||||||
t.assert(changes !== null && changes.added.size === 0 && changes.deleted.size === 2)
|
t.assert(d !== null && d.children.len === 1)
|
||||||
t.compare(changes.delta, [{ delete: 2 }])
|
t.compare(d.toJSON().children, [{ delete: 2 }])
|
||||||
changes = null
|
|
||||||
array0.insert(1, [0.1])
|
array0.insert(1, [0.1])
|
||||||
t.assert(changes !== null && changes.added.size === 1 && changes.deleted.size === 0)
|
t.assert(d !== null && d.children.len === 2)
|
||||||
t.compare(changes.delta, [{ retain: 1 }, { insert: [0.1] }])
|
t.compare(d.toJSON().children, [{ retain: 1 }, { insert: [0.1] }])
|
||||||
compare(users)
|
compare(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,7 +529,7 @@ export const testAttributedContent = _tc => {
|
|||||||
yarray.delete(0, 1)
|
yarray.delete(0, 1)
|
||||||
yarray.insert(1, [42])
|
yarray.insert(1, [42])
|
||||||
})
|
})
|
||||||
const expectedContent = delta.createArrayDelta().insert([1], null, { delete: [] }).insert([2]).insert([42], null, { insert: [] })
|
const expectedContent = delta.create().insert([1], null, { delete: [] }).insert([2]).insert([42], null, { insert: [] })
|
||||||
const attributedContent = yarray.getContent(attributionManager)
|
const attributedContent = yarray.getContent(attributionManager)
|
||||||
console.log(attributedContent.toJSON())
|
console.log(attributedContent.toJSON())
|
||||||
t.assert(attributedContent.equals(expectedContent))
|
t.assert(attributedContent.equals(expectedContent))
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import {
|
|||||||
compareIDs,
|
compareIDs,
|
||||||
noAttributionsManager,
|
noAttributionsManager,
|
||||||
TwosetAttributionManager,
|
TwosetAttributionManager,
|
||||||
createIdMapFromIdSet,
|
createIdMapFromIdSet
|
||||||
mapDeltaJsonSchema
|
|
||||||
} from '../src/internals.js'
|
} from '../src/internals.js'
|
||||||
import * as t from 'lib0/testing'
|
import * as t from 'lib0/testing'
|
||||||
import * as prng from 'lib0/prng'
|
import * as prng from 'lib0/prng'
|
||||||
|
import * as delta from 'lib0/delta'
|
||||||
|
import * as s from 'lib0/schema'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {t.TestCase} _tc
|
* @param {t.TestCase} _tc
|
||||||
@@ -490,45 +491,41 @@ export const testThrowsDeleteEventsOnClear = tc => {
|
|||||||
export const testChangeEvent = tc => {
|
export const testChangeEvent = tc => {
|
||||||
const { map0, users } = init(tc, { users: 2 })
|
const { map0, users } = init(tc, { users: 2 })
|
||||||
/**
|
/**
|
||||||
* @type {any}
|
* @type {delta.Delta<any,any,any,any>?}
|
||||||
*/
|
*/
|
||||||
let changes = null
|
let changes = delta.create()
|
||||||
/**
|
|
||||||
* @type {any}
|
|
||||||
*/
|
|
||||||
let keyChange = null
|
|
||||||
map0.observe(e => {
|
map0.observe(e => {
|
||||||
changes = e.changes
|
changes = e.delta
|
||||||
})
|
})
|
||||||
map0.set('a', 1)
|
map0.set('a', 1)
|
||||||
keyChange = changes.keys.get('a')
|
let keyChange = changes.attrs.get('a')
|
||||||
t.assert(changes !== null && keyChange.action === 'add' && keyChange.oldValue === undefined)
|
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === undefined)
|
||||||
map0.set('a', 2)
|
map0.set('a', 2)
|
||||||
keyChange = changes.keys.get('a')
|
keyChange = changes.attrs.get('a')
|
||||||
t.assert(changes !== null && keyChange.action === 'update' && keyChange.oldValue === 1)
|
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === 1)
|
||||||
users[0].transact(() => {
|
users[0].transact(() => {
|
||||||
map0.set('a', 3)
|
map0.set('a', 3)
|
||||||
map0.set('a', 4)
|
map0.set('a', 4)
|
||||||
})
|
})
|
||||||
keyChange = changes.keys.get('a')
|
keyChange = changes.attrs.get('a')
|
||||||
t.assert(changes !== null && keyChange.action === 'update' && keyChange.oldValue === 2)
|
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === 2)
|
||||||
users[0].transact(() => {
|
users[0].transact(() => {
|
||||||
map0.set('b', 1)
|
map0.set('b', 1)
|
||||||
map0.set('b', 2)
|
map0.set('b', 2)
|
||||||
})
|
})
|
||||||
keyChange = changes.keys.get('b')
|
keyChange = changes.attrs.get('b')
|
||||||
t.assert(changes !== null && keyChange.action === 'add' && keyChange.oldValue === undefined)
|
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === undefined)
|
||||||
users[0].transact(() => {
|
users[0].transact(() => {
|
||||||
map0.set('c', 1)
|
map0.set('c', 1)
|
||||||
map0.delete('c')
|
map0.delete('c')
|
||||||
})
|
})
|
||||||
t.assert(changes !== null && changes.keys.size === 0)
|
t.assert(changes !== null && changes.attrs.size === 0)
|
||||||
users[0].transact(() => {
|
users[0].transact(() => {
|
||||||
map0.set('d', 1)
|
map0.set('d', 1)
|
||||||
map0.set('d', 2)
|
map0.set('d', 2)
|
||||||
})
|
})
|
||||||
keyChange = changes.keys.get('d')
|
keyChange = changes.attrs.get('d')
|
||||||
t.assert(changes !== null && keyChange.action === 'add' && keyChange.oldValue === undefined)
|
t.assert(delta.$insertOpWith(s.$number).check(keyChange) && keyChange.prevValue === undefined)
|
||||||
compare(users)
|
compare(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,24 +628,24 @@ export const testAttributedContent = _tc => {
|
|||||||
})
|
})
|
||||||
t.group('initial value', () => {
|
t.group('initial value', () => {
|
||||||
ymap.set('test', 42)
|
ymap.set('test', 42)
|
||||||
const expectedContent = mapDeltaJsonSchema.ensure({ test: { type: 'insert', prevValue: undefined, value: 42, attribution: { insert: [] } } })
|
const expectedContent = { test: delta.$deltaMapChangeJson.expect({ type: 'insert', value: 42, attribution: { insert: [] } }) }
|
||||||
const attributedContent = ymap.getContent(attributionManager)
|
const attributedContent = ymap.getContent(attributionManager)
|
||||||
console.log(attributedContent.toJSON())
|
console.log(attributedContent.toJSON())
|
||||||
t.compare(expectedContent, attributedContent.toJSON())
|
t.compare(expectedContent, attributedContent.toJSON().attrs)
|
||||||
})
|
})
|
||||||
t.group('overwrite value', () => {
|
t.group('overwrite value', () => {
|
||||||
ymap.set('test', 'fourtytwo')
|
ymap.set('test', 'fourtytwo')
|
||||||
const expectedContent = mapDeltaJsonSchema.ensure({ test: { type: 'insert', prevValue: 42, value: 'fourtytwo', attribution: { insert: [] } } })
|
const expectedContent = { test: delta.$deltaMapChangeJson.expect({ type: 'insert', prevValue: 42, value: 'fourtytwo', attribution: { insert: [] } }) }
|
||||||
const attributedContent = ymap.getContent(attributionManager)
|
const attributedContent = ymap.getContent(attributionManager)
|
||||||
console.log(attributedContent)
|
console.log(attributedContent)
|
||||||
t.compare(expectedContent, attributedContent.toJSON())
|
t.compare(expectedContent, attributedContent.toJSON().attrs)
|
||||||
})
|
})
|
||||||
t.group('delete value', () => {
|
t.group('delete value', () => {
|
||||||
ymap.delete('test')
|
ymap.delete('test')
|
||||||
const expectedContent = mapDeltaJsonSchema.ensure({ test: { type: 'delete', prevValue: 'fourtytwo', attribution: { delete: [] } } })
|
const expectedContent = { test: delta.$deltaMapChangeJson.expect({ type: 'delete', prevValue: 'fourtytwo', attribution: { delete: [] } }) }
|
||||||
const attributedContent = ymap.getContent(attributionManager)
|
const attributedContent = ymap.getContent(attributionManager)
|
||||||
console.log(attributedContent)
|
console.log(attributedContent.toJSON())
|
||||||
t.compare(expectedContent, attributedContent.toJSON())
|
t.compare(expectedContent, attributedContent.toJSON().attrs)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,5 +20,5 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["./src/**/*.js", "./tests/**/*.js"],
|
"include": ["./src/**/*.js", "./tests/**/*.js"],
|
||||||
"exclude": ["../lib0/**"]
|
"exclude": ["./node_modules/**/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user