mirror of
https://github.com/yjs/yjs.git
synced 2026-02-23 19:49:59 +01:00
[delta integration] fixed all tests
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
getItemCleanStart,
|
||||
intersectSets,
|
||||
ContentFormat,
|
||||
createAttributionItem,
|
||||
StructStore, Transaction, ID, IdSet, Item, Snapshot, Doc, AbstractContent, IdMap, // eslint-disable-line
|
||||
encodeStateAsUpdate
|
||||
} from '../internals.js'
|
||||
@@ -574,16 +575,16 @@ export class SnapshotAttributionManager extends ObservableV2 {
|
||||
* @param {Object} [options] - options for the attribution manager
|
||||
* @param {Array<import('./IdMap.js').AttributionItem<any>>} [options.attrs] - the attributes to apply to the diff
|
||||
*/
|
||||
constructor (prevSnapshot, nextSnapshot, { attrs = [] } = {}) {
|
||||
constructor (prevSnapshot, nextSnapshot) {
|
||||
super()
|
||||
this.prevSnapshot = prevSnapshot
|
||||
this.nextSnapshot = nextSnapshot
|
||||
const inserts = createIdMap()
|
||||
const deletes = createIdMapFromIdSet(diffIdSet(nextSnapshot.ds, prevSnapshot.ds), attrs)
|
||||
const deletes = createIdMapFromIdSet(diffIdSet(nextSnapshot.ds, prevSnapshot.ds), [createAttributionItem('change', '')])
|
||||
nextSnapshot.sv.forEach((clock, client) => {
|
||||
const prevClock = prevSnapshot.sv.get(client) || 0
|
||||
inserts.add(client, 0, prevClock, []) // content is included in prevSnapshot is rendered without attributes
|
||||
inserts.add(client, prevClock, clock - prevClock, attrs) // content is rendered as "inserted"
|
||||
inserts.add(client, prevClock, clock - prevClock, [createAttributionItem('change', '')]) // content is rendered as "inserted"
|
||||
})
|
||||
this.attrs = mergeIdMaps([diffIdMap(inserts, prevSnapshot.ds), deletes])
|
||||
}
|
||||
@@ -635,7 +636,5 @@ export class SnapshotAttributionManager extends ObservableV2 {
|
||||
/**
|
||||
* @param {Snapshot} prevSnapshot
|
||||
* @param {Snapshot} nextSnapshot
|
||||
* @param {Object} [options] - options for the attribution manager
|
||||
* @param {Array<import('./IdMap.js').AttributionItem<any>>} [options.attrs] - the attributes to apply to the diff
|
||||
*/
|
||||
export const createAttributionManagerFromSnapshots = (prevSnapshot, nextSnapshot = prevSnapshot, options) => new SnapshotAttributionManager(prevSnapshot, nextSnapshot, options)
|
||||
export const createAttributionManagerFromSnapshots = (prevSnapshot, nextSnapshot = prevSnapshot) => new SnapshotAttributionManager(prevSnapshot, nextSnapshot)
|
||||
|
||||
@@ -530,22 +530,6 @@ const cleanupTransactions = (transactionCleanups, i) => {
|
||||
// We need to think about the possibility that the user transforms the
|
||||
// Y.Doc in the event.
|
||||
if (type._dEH.l.length > 0 && (type._item === null || !type._item.deleted)) {
|
||||
events = events
|
||||
.filter(event =>
|
||||
event.target._item === null || !event.target._item.deleted
|
||||
)
|
||||
events
|
||||
.forEach(event => {
|
||||
event.currentTarget = type
|
||||
// path is relative to the current target
|
||||
event._path = null
|
||||
})
|
||||
// sort events by path length so that top-level events are fired first.
|
||||
events
|
||||
.sort((event1, event2) => event1.path.length - event2.path.length)
|
||||
// We don't need to check for events.length
|
||||
// because we know it has at least one element
|
||||
|
||||
/**
|
||||
* @type {YEvent<any>}
|
||||
*/
|
||||
|
||||
@@ -101,8 +101,6 @@ export class ItemTextListPosition {
|
||||
* @function
|
||||
*/
|
||||
formatText (transaction, parent, length, attributes) {
|
||||
const doc = transaction.doc
|
||||
const ownClientId = doc.clientID
|
||||
minimizeAttributeChanges(this, attributes)
|
||||
const negatedAttributes = insertAttributes(transaction, parent, this, attributes)
|
||||
// iterate until first non-format or null is found
|
||||
@@ -1312,7 +1310,7 @@ export class YType {
|
||||
* @type {{[K:string]:any}}
|
||||
*/
|
||||
const attrs = this.getAttrs()
|
||||
for (let k in attrs) {
|
||||
for (const k in attrs) {
|
||||
const attr = attrs[k]
|
||||
attrs[k] = attr instanceof YType ? attr.toJSON() : attr
|
||||
}
|
||||
@@ -1343,7 +1341,7 @@ export class YType {
|
||||
*/
|
||||
const attrs = []
|
||||
this.forEachAttr((attr, key) => {
|
||||
attrs.push([(key), attr.toString({ forceTag: true })])
|
||||
attrs.push([(key), /** @type {any} */ (attr) instanceof YType ? attr.toString({ forceTag: true }) : JSON.stringify(attr)])
|
||||
})
|
||||
const attrsString = (attrs.length > 0 ? ' ' : '') + attrs.sort((a, b) => a[0].toString() < b[0].toString() ? -1 : 1).map(attr => attr[0] + '=' + attr[1]).join(' ')
|
||||
/**
|
||||
@@ -1561,6 +1559,8 @@ export const typeListGet = (type, index) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo this is a duplicate. use the unified insert function and remove this.
|
||||
*
|
||||
* @param {Transaction} transaction
|
||||
* @param {YType} parent
|
||||
* @param {Item?} referenceItem
|
||||
|
||||
@@ -112,14 +112,16 @@ export const testToJSON = _tc => {
|
||||
map2.setAttr('m2k1', 'm2v1')
|
||||
t.compare(doc.toJSON(), {
|
||||
array: { children: ['test1'] },
|
||||
map: { attrs: {
|
||||
k1: 'v1',
|
||||
k2: {
|
||||
attrs: {
|
||||
m2k1: 'm2v1'
|
||||
map: {
|
||||
attrs: {
|
||||
k1: 'v1',
|
||||
k2: {
|
||||
attrs: {
|
||||
m2k1: 'm2v1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
}, 'doc.toJSON has array and recursive map')
|
||||
}
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ export const testUndoArray = tc => {
|
||||
t.compare(array0.toJSON().children, [{}])
|
||||
undoManager.stopCapturing()
|
||||
ymap.setAttr('a', 1)
|
||||
t.compare(array0.toJSON().children, [{ a: 1 }])
|
||||
t.compare(array0.toJSON().children, [{ attrs: { a: 1 } }])
|
||||
undoManager.undo()
|
||||
t.compare(array0.toJSON().children, [{}])
|
||||
undoManager.undo()
|
||||
@@ -270,19 +270,19 @@ export const testUndoArray = tc => {
|
||||
undoManager.redo()
|
||||
t.compare(array0.toJSON().children, [{}])
|
||||
undoManager.redo()
|
||||
t.compare(array0.toJSON().children, [{ a: 1 }])
|
||||
t.compare(array0.toJSON().children, [{ attrs: { a: 1 } }])
|
||||
testConnector.syncAll()
|
||||
array1.get(0).setAttr('b', 2)
|
||||
testConnector.syncAll()
|
||||
t.compare(array0.toJSON().children, [{ a: 1, b: 2 }])
|
||||
t.compare(array0.toJSON().children, [{ attrs: { a: 1, b: 2 } }])
|
||||
undoManager.undo()
|
||||
t.compare(array0.toJSON().children, [{ b: 2 }])
|
||||
t.compare(array0.toJSON().children, [{ attrs: { b: 2 } }])
|
||||
undoManager.undo()
|
||||
t.compare(array0.toJSON().children, [2, 3, 4, 5, 6])
|
||||
undoManager.redo()
|
||||
t.compare(array0.toJSON().children, [{ b: 2 }])
|
||||
t.compare(array0.toJSON().children, [{ attrs: { b: 2 } }])
|
||||
undoManager.redo()
|
||||
t.compare(array0.toJSON().children, [{ a: 1, b: 2 }])
|
||||
t.compare(array0.toJSON().children, [{ attrs: { a: 1, b: 2 } }])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,7 +311,6 @@ export const testUndoXml = tc => {
|
||||
t.compare(xml0.getContentDeep(), v1)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {t.TestCase} tc
|
||||
*/
|
||||
@@ -584,7 +583,7 @@ export const testUndoXmlBug = _tc => {
|
||||
undoManager.redo()
|
||||
undoManager.redo()
|
||||
undoManager.redo()
|
||||
t.compare(fragment.toString(), '<test-node a=180 b=50 />')
|
||||
t.compare(fragment.toString(), '<test-node a="180" b="50" />')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -643,7 +642,7 @@ export const testUndoBlockBug = _tc => {
|
||||
undoManager.redo() // {"text":{"blocks":{"text":"2"}}}
|
||||
undoManager.redo() // {"text":{"blocks":{"text":"3"}}}
|
||||
undoManager.redo() // {"text":{}}
|
||||
t.compare(design.toJSON().attrs, { text: { blocks: { text: '4' } } })
|
||||
t.compare(design.toJSON().attrs, { text: { attrs: { blocks: { attrs: { text: '4' } } } } })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -720,16 +719,16 @@ export const testSpecialDeletionCase = _tc => {
|
||||
e.setAttr('b', '2')
|
||||
fragment.insert(0, [e])
|
||||
})
|
||||
t.compareStrings(fragment.toString(), '<test a="1" b="2"></test>')
|
||||
t.compareStrings(fragment.toString(), '<test a="1" b="2" />')
|
||||
doc.transact(() => {
|
||||
// change attribute "b" and delete test-node
|
||||
const e = fragment.get(0)
|
||||
e.setAttribute('b', '3')
|
||||
e.setAttr('b', '3')
|
||||
fragment.delete(0)
|
||||
}, origin)
|
||||
t.compareStrings(fragment.toString(), '')
|
||||
undoManager.undo()
|
||||
t.compareStrings(fragment.toString(), '<test a="1" b="2"></test>')
|
||||
t.compareStrings(fragment.toString(), '<test a="1" b="2" />')
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -203,7 +203,7 @@ export const testYmapSetsYarray = tc => {
|
||||
t.assert(array === map0.getAttr('Array'))
|
||||
array.insert(0, [1, 2, 3])
|
||||
// @ts-ignore
|
||||
t.compare(map0.toJSON(), { Array: [1, 2, 3] })
|
||||
t.compare(map0.toJSON().attrs, { Array: { children: [1, 2, 3] } })
|
||||
compare(users)
|
||||
}
|
||||
|
||||
|
||||
@@ -2096,7 +2096,7 @@ const qChanges = [
|
||||
*/
|
||||
(y, gen) => { // delete text
|
||||
const ytext = y.get('text')
|
||||
const contentLen = ytext.toString().length
|
||||
const contentLen = ytext.length
|
||||
const insertPos = prng.int32(gen, 0, contentLen)
|
||||
const overwrite = math.min(prng.int32(gen, 0, contentLen - insertPos), 2)
|
||||
ytext.delete(insertPos, overwrite)
|
||||
@@ -2107,7 +2107,7 @@ const qChanges = [
|
||||
*/
|
||||
(y, gen) => { // format text
|
||||
const ytext = y.get('text')
|
||||
const contentLen = ytext.toString().length
|
||||
const contentLen = ytext.length
|
||||
const insertPos = prng.int32(gen, 0, contentLen)
|
||||
const overwrite = math.min(prng.int32(gen, 0, contentLen - insertPos), 2)
|
||||
const format = prng.oneOf(gen, marks)
|
||||
@@ -2119,7 +2119,7 @@ const qChanges = [
|
||||
*/
|
||||
(y, gen) => { // insert codeblock
|
||||
const ytext = y.get('text')
|
||||
const insertPos = prng.int32(gen, 0, ytext.toString().length)
|
||||
const insertPos = prng.int32(gen, 0, ytext.length)
|
||||
const text = charCounter++ + prng.word(gen)
|
||||
const d = delta.create()
|
||||
d.retain(insertPos).insert(text).insert('\n', { 'code-block': true })
|
||||
@@ -2131,7 +2131,7 @@ const qChanges = [
|
||||
*/
|
||||
(y, gen) => { // complex delta op
|
||||
const ytext = y.get('text')
|
||||
const contentLen = ytext.toString().length
|
||||
const contentLen = ytext.length
|
||||
let currentPos = math.max(0, prng.int32(gen, 0, contentLen - 1))
|
||||
const d = delta.create().retain(currentPos)
|
||||
// create max 3 ops
|
||||
|
||||
@@ -94,14 +94,12 @@ export const testInsertafter = _tc => {
|
||||
const first = new Y.Type()
|
||||
const second = new Y.Type('p')
|
||||
const third = new Y.Type('p')
|
||||
|
||||
const deepsecond1 = new Y.Type('span')
|
||||
const deepsecond2 = new Y.Type()
|
||||
second.insertAfter(null, [deepsecond1])
|
||||
second.insertAfter(deepsecond1, [deepsecond2])
|
||||
|
||||
yxml.insertAfter(null, [first, second])
|
||||
yxml.insertAfter(second, [third])
|
||||
second.insertAfter(null, [deepsecond1])
|
||||
second.insertAfter(deepsecond1, [deepsecond2])
|
||||
|
||||
t.assert(yxml.length === 3)
|
||||
t.assert(second.get(0) === deepsecond1)
|
||||
@@ -164,9 +162,9 @@ export const testElement = _tc => {
|
||||
export const testFragmentAttributedContent = _tc => {
|
||||
const ydoc = new Y.Doc({ gc: false })
|
||||
const yfragment = new Y.Type()
|
||||
const elem1 = new Y.Type('hello')
|
||||
const elem1 = Y.Type.from(delta.create().insert('hello'))
|
||||
const elem2 = new Y.Type()
|
||||
const elem3 = new Y.Type('world')
|
||||
const elem3 = Y.Type.from(delta.create().insert('world'))
|
||||
yfragment.insert(0, [elem1, elem2])
|
||||
ydoc.get().insert(0, [yfragment])
|
||||
let attributionManager = Y.noAttributionsManager
|
||||
@@ -230,7 +228,7 @@ export const testElementAttributedContentViaDiffer = _tc => {
|
||||
Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(ydocV1))
|
||||
const yelement = ydoc.get('p')
|
||||
const elem2 = yelement.get(1) // new Y.XmlElement('span')
|
||||
const elem3 = new Y.Type('world')
|
||||
const elem3 = Y.Type.from(delta.create().insert('world'))
|
||||
ydoc.transact(() => {
|
||||
yelement.delete(0, 1)
|
||||
yelement.insert(1, [elem3])
|
||||
|
||||
Reference in New Issue
Block a user