Merge remote-tracking branch 'origin' into y-richtext-rewrite
This commit is contained in:
		
						commit
						250050e83b
					
				@ -18,7 +18,7 @@ window.undoManager = new Y.utils.UndoManager(window.yXmlType, {
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
document.onkeydown = function interceptUndoRedo (e) {
 | 
					document.onkeydown = function interceptUndoRedo (e) {
 | 
				
			||||||
  if (e.keyCode === 90 && e.metaKey) {
 | 
					  if (e.keyCode === 90 && (e.metaKey || e.ctrlKey)) {
 | 
				
			||||||
    if (!e.shiftKey) {
 | 
					    if (!e.shiftKey) {
 | 
				
			||||||
      window.undoManager.undo()
 | 
					      window.undoManager.undo()
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "yjs",
 | 
					  "name": "yjs",
 | 
				
			||||||
  "version": "13.0.0-50",
 | 
					  "version": "13.0.0-53",
 | 
				
			||||||
  "lockfileVersion": 1,
 | 
					  "lockfileVersion": 1,
 | 
				
			||||||
  "requires": true,
 | 
					  "requires": true,
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "yjs",
 | 
					  "name": "yjs",
 | 
				
			||||||
  "version": "13.0.0-50",
 | 
					  "version": "13.0.0-53",
 | 
				
			||||||
  "description": "A framework for real-time p2p shared editing on any data",
 | 
					  "description": "A framework for real-time p2p shared editing on any data",
 | 
				
			||||||
  "main": "./y.node.js",
 | 
					  "main": "./y.node.js",
 | 
				
			||||||
  "browser": "./y.js",
 | 
					  "browser": "./y.js",
 | 
				
			||||||
 | 
				
			|||||||
@ -4,8 +4,10 @@ import { readDeleteSet, writeDeleteSet } from './deleteSet.js'
 | 
				
			|||||||
import BinaryEncoder from '../Binary/Encoder.js'
 | 
					import BinaryEncoder from '../Binary/Encoder.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function fromBinary (y, decoder) {
 | 
					export function fromBinary (y, decoder) {
 | 
				
			||||||
  integrateRemoteStructs(y, decoder)
 | 
					  y.transact(function () {
 | 
				
			||||||
  readDeleteSet(y, decoder)
 | 
					    integrateRemoteStructs(y, decoder)
 | 
				
			||||||
 | 
					    readDeleteSet(y, decoder)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function toBinary (y) {
 | 
					export function toBinary (y) {
 | 
				
			||||||
 | 
				
			|||||||
@ -56,22 +56,56 @@ export default class Item {
 | 
				
			|||||||
    this._parent = null
 | 
					    this._parent = null
 | 
				
			||||||
    this._parentSub = null
 | 
					    this._parentSub = null
 | 
				
			||||||
    this._deleted = false
 | 
					    this._deleted = false
 | 
				
			||||||
 | 
					    this._redone = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Copy the effect of struct
 | 
					   * Create a operation with the same effect (without position effect)
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  _copy (undeleteChildren, copyPosition) {
 | 
					  _copy () {
 | 
				
			||||||
    let struct = new this.constructor()
 | 
					    return new this.constructor()
 | 
				
			||||||
    if (copyPosition) {
 | 
					  }
 | 
				
			||||||
      struct._origin = this._left
 | 
					  /**
 | 
				
			||||||
      struct._left = this._left
 | 
					   * Redo the effect of this operation.
 | 
				
			||||||
      struct._right = this
 | 
					   */
 | 
				
			||||||
      struct._right_origin = this
 | 
					  _redo (y) {
 | 
				
			||||||
      struct._parent = this._parent
 | 
					    if (this._redone !== null) {
 | 
				
			||||||
      struct._parentSub = this._parentSub
 | 
					      return this._redone
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    let struct = this._copy()
 | 
				
			||||||
 | 
					    let left = this._left
 | 
				
			||||||
 | 
					    let right = this
 | 
				
			||||||
 | 
					    let parent = this._parent
 | 
				
			||||||
 | 
					    // make sure that parent is redone
 | 
				
			||||||
 | 
					    if (parent._deleted === true && parent._redone === null) {
 | 
				
			||||||
 | 
					      parent._redo(y)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (parent._redone !== null) {
 | 
				
			||||||
 | 
					      parent = parent._redone
 | 
				
			||||||
 | 
					      // find next cloned items
 | 
				
			||||||
 | 
					      while (left !== null && left._redone === null) {
 | 
				
			||||||
 | 
					        left = left._left
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (left !== null) {
 | 
				
			||||||
 | 
					        left = left._redone
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      while (right !== null && right._redone === null) {
 | 
				
			||||||
 | 
					        right = right._right
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (right !== null) {
 | 
				
			||||||
 | 
					        right = right._redone
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    struct._origin = left
 | 
				
			||||||
 | 
					    struct._left = left
 | 
				
			||||||
 | 
					    struct._right = right
 | 
				
			||||||
 | 
					    struct._right_origin = right
 | 
				
			||||||
 | 
					    struct._parent = parent
 | 
				
			||||||
 | 
					    struct._parentSub = this._parentSub
 | 
				
			||||||
 | 
					    struct._integrate(y)
 | 
				
			||||||
 | 
					    this._redone = struct
 | 
				
			||||||
    return struct
 | 
					    return struct
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get _lastId () {
 | 
					  get _lastId () {
 | 
				
			||||||
    return new ID(this._id.user, this._id.clock + this._length - 1)
 | 
					    return new ID(this._id.user, this._id.clock + this._length - 1)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -104,11 +138,15 @@ export default class Item {
 | 
				
			|||||||
    if (!this._deleted) {
 | 
					    if (!this._deleted) {
 | 
				
			||||||
      this._deleted = true
 | 
					      this._deleted = true
 | 
				
			||||||
      y.ds.markDeleted(this._id, this._length)
 | 
					      y.ds.markDeleted(this._id, this._length)
 | 
				
			||||||
 | 
					      let del = new Delete()
 | 
				
			||||||
 | 
					      del._targetID = this._id
 | 
				
			||||||
 | 
					      del._length = this._length
 | 
				
			||||||
      if (createDelete) {
 | 
					      if (createDelete) {
 | 
				
			||||||
        let del = new Delete()
 | 
					        // broadcast and persists Delete
 | 
				
			||||||
        del._targetID = this._id
 | 
					 | 
				
			||||||
        del._length = this._length
 | 
					 | 
				
			||||||
        del._integrate(y, true)
 | 
					        del._integrate(y, true)
 | 
				
			||||||
 | 
					      } else if (y.persistence !== null) {
 | 
				
			||||||
 | 
					        // only persist Delete
 | 
				
			||||||
 | 
					        y.persistence.saveStruct(y, del)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      transactionTypeChanged(y, this._parent, this._parentSub)
 | 
					      transactionTypeChanged(y, this._parent, this._parentSub)
 | 
				
			||||||
      y._transaction.deletedStructs.add(this)
 | 
					      y._transaction.deletedStructs.add(this)
 | 
				
			||||||
 | 
				
			|||||||
@ -6,8 +6,8 @@ export default class ItemJSON extends Item {
 | 
				
			|||||||
    super()
 | 
					    super()
 | 
				
			||||||
    this._content = null
 | 
					    this._content = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _copy (undeleteChildren, copyPosition) {
 | 
					  _copy () {
 | 
				
			||||||
    let struct = super._copy(undeleteChildren, copyPosition)
 | 
					    let struct = super._copy()
 | 
				
			||||||
    struct._content = this._content
 | 
					    struct._content = this._content
 | 
				
			||||||
    return struct
 | 
					    return struct
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -6,8 +6,8 @@ export default class ItemString extends Item {
 | 
				
			|||||||
    super()
 | 
					    super()
 | 
				
			||||||
    this._content = null
 | 
					    this._content = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _copy (undeleteChildren, copyPosition) {
 | 
					  _copy () {
 | 
				
			||||||
    let struct = super._copy(undeleteChildren, copyPosition)
 | 
					    let struct = super._copy()
 | 
				
			||||||
    struct._content = this._content
 | 
					    struct._content = this._content
 | 
				
			||||||
    return struct
 | 
					    return struct
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -79,40 +79,6 @@ export default class Type extends Item {
 | 
				
			|||||||
      type = type._parent
 | 
					      type = type._parent
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _copy (undeleteChildren, copyPosition) {
 | 
					 | 
				
			||||||
    let copy = super._copy(undeleteChildren, copyPosition)
 | 
					 | 
				
			||||||
    let map = new Map()
 | 
					 | 
				
			||||||
    copy._map = map
 | 
					 | 
				
			||||||
    for (let [key, value] of this._map) {
 | 
					 | 
				
			||||||
      if (undeleteChildren.has(value) || !value.deleted) {
 | 
					 | 
				
			||||||
        let _item = value._copy(undeleteChildren, false)
 | 
					 | 
				
			||||||
        _item._parent = copy
 | 
					 | 
				
			||||||
        _item._parentSub = key
 | 
					 | 
				
			||||||
        map.set(key, _item)
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    let prevUndeleted = null
 | 
					 | 
				
			||||||
    copy._start = null
 | 
					 | 
				
			||||||
    let item = this._start
 | 
					 | 
				
			||||||
    while (item !== null) {
 | 
					 | 
				
			||||||
      if (undeleteChildren.has(item) || !item.deleted) {
 | 
					 | 
				
			||||||
        let _item = item._copy(undeleteChildren, false)
 | 
					 | 
				
			||||||
        _item._left = prevUndeleted
 | 
					 | 
				
			||||||
        _item._origin = prevUndeleted
 | 
					 | 
				
			||||||
        _item._right = null
 | 
					 | 
				
			||||||
        _item._right_origin = null
 | 
					 | 
				
			||||||
        _item._parent = copy
 | 
					 | 
				
			||||||
        if (prevUndeleted === null) {
 | 
					 | 
				
			||||||
          copy._start = _item
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          prevUndeleted._right = _item
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        prevUndeleted = _item
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      item = item._right
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return copy
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  _transact (f) {
 | 
					  _transact (f) {
 | 
				
			||||||
    const y = this._y
 | 
					    const y = this._y
 | 
				
			||||||
    if (y !== null) {
 | 
					    if (y !== null) {
 | 
				
			||||||
 | 
				
			|||||||
@ -20,8 +20,8 @@ export default class YXmlElement extends YXmlFragment {
 | 
				
			|||||||
      this._domFilter = arg2
 | 
					      this._domFilter = arg2
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _copy (undeleteChildren, copyPosition) {
 | 
					  _copy () {
 | 
				
			||||||
    let struct = super._copy(undeleteChildren, copyPosition)
 | 
					    let struct = super._copy()
 | 
				
			||||||
    struct.nodeName = this.nodeName
 | 
					    struct.nodeName = this.nodeName
 | 
				
			||||||
    return struct
 | 
					    return struct
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -36,7 +36,8 @@ export default class YXmlElement extends YXmlFragment {
 | 
				
			|||||||
      let attributes = new Map()
 | 
					      let attributes = new Map()
 | 
				
			||||||
      for (let i = 0; i < dom.attributes.length; i++) {
 | 
					      for (let i = 0; i < dom.attributes.length; i++) {
 | 
				
			||||||
        let attr = dom.attributes[i]
 | 
					        let attr = dom.attributes[i]
 | 
				
			||||||
        attributes.set(attr.name, attr.value)
 | 
					        // get attribute via getAttribute for custom element support (some write something different in attr.value)
 | 
				
			||||||
 | 
					        attributes.set(attr.name, dom.getAttribute(attr.name))
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      attributes = this._domFilter(dom, attributes)
 | 
					      attributes = this._domFilter(dom, attributes)
 | 
				
			||||||
      attributes.forEach((value, name) => {
 | 
					      attributes.forEach((value, name) => {
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,8 @@ export default class YXmlHook extends YMap {
 | 
				
			|||||||
      getHook(hookName).fillType(dom, this)
 | 
					      getHook(hookName).fillType(dom, this)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _copy (undeleteChildren, copyPosition) {
 | 
					  _copy () {
 | 
				
			||||||
    const struct = super._copy(undeleteChildren, copyPosition)
 | 
					    const struct = super._copy()
 | 
				
			||||||
    struct.hookName = this.hookName
 | 
					    struct.hookName = this.hookName
 | 
				
			||||||
    return struct
 | 
					    return struct
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -4,11 +4,12 @@ class ReverseOperation {
 | 
				
			|||||||
  constructor (y, transaction) {
 | 
					  constructor (y, transaction) {
 | 
				
			||||||
    this.created = new Date()
 | 
					    this.created = new Date()
 | 
				
			||||||
    const beforeState = transaction.beforeState
 | 
					    const beforeState = transaction.beforeState
 | 
				
			||||||
    this.toState = new ID(y.userID, y.ss.getState(y.userID) - 1)
 | 
					 | 
				
			||||||
    if (beforeState.has(y.userID)) {
 | 
					    if (beforeState.has(y.userID)) {
 | 
				
			||||||
 | 
					      this.toState = new ID(y.userID, y.ss.getState(y.userID) - 1)
 | 
				
			||||||
      this.fromState = new ID(y.userID, beforeState.get(y.userID))
 | 
					      this.fromState = new ID(y.userID, beforeState.get(y.userID))
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      this.fromState = this.toState
 | 
					      this.toState = null
 | 
				
			||||||
 | 
					      this.fromState = null
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.deletedStructs = transaction.deletedStructs
 | 
					    this.deletedStructs = transaction.deletedStructs
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -30,28 +31,32 @@ function applyReverseOperation (y, scope, reverseBuffer) {
 | 
				
			|||||||
    while (!performedUndo && reverseBuffer.length > 0) {
 | 
					    while (!performedUndo && reverseBuffer.length > 0) {
 | 
				
			||||||
      let undoOp = reverseBuffer.pop()
 | 
					      let undoOp = reverseBuffer.pop()
 | 
				
			||||||
      // make sure that it is possible to iterate {from}-{to}
 | 
					      // make sure that it is possible to iterate {from}-{to}
 | 
				
			||||||
      y.os.getItemCleanStart(undoOp.fromState)
 | 
					      if (undoOp.fromState !== null) {
 | 
				
			||||||
      y.os.getItemCleanEnd(undoOp.toState)
 | 
					        y.os.getItemCleanStart(undoOp.fromState)
 | 
				
			||||||
      y.os.iterate(undoOp.fromState, undoOp.toState, op => {
 | 
					        y.os.getItemCleanEnd(undoOp.toState)
 | 
				
			||||||
        if (!op._deleted && isStructInScope(y, op, scope)) {
 | 
					        y.os.iterate(undoOp.fromState, undoOp.toState, op => {
 | 
				
			||||||
          performedUndo = true
 | 
					          while (op._deleted && op._redone !== null) {
 | 
				
			||||||
          op._delete(y)
 | 
					            op = op._redone
 | 
				
			||||||
        }
 | 
					          }
 | 
				
			||||||
      })
 | 
					          if (op._deleted === false && isStructInScope(y, op, scope)) {
 | 
				
			||||||
 | 
					            performedUndo = true
 | 
				
			||||||
 | 
					            op._delete(y)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      for (let op of undoOp.deletedStructs) {
 | 
					      for (let op of undoOp.deletedStructs) {
 | 
				
			||||||
        if (
 | 
					        if (
 | 
				
			||||||
          isStructInScope(y, op, scope) &&
 | 
					          isStructInScope(y, op, scope) &&
 | 
				
			||||||
          op._parent !== y &&
 | 
					          op._parent !== y &&
 | 
				
			||||||
          !op._parent._deleted &&
 | 
					 | 
				
			||||||
          (
 | 
					          (
 | 
				
			||||||
            op._parent._id.user !== y.userID ||
 | 
					            op._id.user !== y.userID ||
 | 
				
			||||||
            op._parent._id.clock < undoOp.fromState.clock ||
 | 
					            undoOp.fromState === null ||
 | 
				
			||||||
            op._parent._id.clock > undoOp.fromState.clock
 | 
					            op._id.clock < undoOp.fromState.clock ||
 | 
				
			||||||
 | 
					            op._id.clock > undoOp.toState.clock
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
          performedUndo = true
 | 
					          performedUndo = true
 | 
				
			||||||
          op = op._copy(undoOp.deletedStructs, true)
 | 
					          op._redo(y)
 | 
				
			||||||
          op._integrate(y)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -77,7 +82,12 @@ export default class UndoManager {
 | 
				
			|||||||
          let lastUndoOp = this._undoBuffer.length > 0 ? this._undoBuffer[this._undoBuffer.length - 1] : null
 | 
					          let lastUndoOp = this._undoBuffer.length > 0 ? this._undoBuffer[this._undoBuffer.length - 1] : null
 | 
				
			||||||
          if (lastUndoOp !== null && reverseOperation.created - lastUndoOp.created <= options.captureTimeout) {
 | 
					          if (lastUndoOp !== null && reverseOperation.created - lastUndoOp.created <= options.captureTimeout) {
 | 
				
			||||||
            lastUndoOp.created = reverseOperation.created
 | 
					            lastUndoOp.created = reverseOperation.created
 | 
				
			||||||
            lastUndoOp.toState = reverseOperation.toState
 | 
					            if (reverseOperation.toState !== null) {
 | 
				
			||||||
 | 
					              lastUndoOp.toState = reverseOperation.toState
 | 
				
			||||||
 | 
					              if (lastUndoOp.fromState === null) {
 | 
				
			||||||
 | 
					                lastUndoOp.fromState = reverseOperation.fromState
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            reverseOperation.deletedStructs.forEach(lastUndoOp.deletedStructs.add, lastUndoOp.deletedStructs)
 | 
					            reverseOperation.deletedStructs.forEach(lastUndoOp.deletedStructs.add, lastUndoOp.deletedStructs)
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            this._undoBuffer.push(reverseOperation)
 | 
					            this._undoBuffer.push(reverseOperation)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user