Compare commits

..

1 Commits

Author SHA1 Message Date
Kevin Jahns
cedcb118c8 v13.0.0-51 -- distribution files 2018-02-07 14:08:56 +01:00
17 changed files with 19650 additions and 208 deletions

View File

@@ -18,7 +18,7 @@ window.undoManager = new Y.utils.UndoManager(window.yXmlType, {
})
document.onkeydown = function interceptUndoRedo (e) {
if (e.keyCode === 90 && (e.metaKey || e.ctrlKey)) {
if (e.keyCode === 90 && e.metaKey) {
if (!e.shiftKey) {
window.undoManager.undo()
} else {

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "yjs",
"version": "13.0.0-55",
"version": "13.0.0-51",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "yjs",
"version": "13.0.0-55",
"version": "13.0.0-51",
"description": "A framework for real-time p2p shared editing on any data",
"main": "./y.node.js",
"browser": "./y.js",

View File

@@ -4,10 +4,8 @@ import { readDeleteSet, writeDeleteSet } from './deleteSet.js'
import BinaryEncoder from '../Binary/Encoder.js'
export function fromBinary (y, decoder) {
y.transact(function () {
integrateRemoteStructs(y, decoder)
readDeleteSet(y, decoder)
})
integrateRemoteStructs(y, decoder)
readDeleteSet(y, decoder)
}
export function toBinary (y) {

View File

@@ -51,57 +51,22 @@ export default class Item {
this._parent = null
this._parentSub = null
this._deleted = false
this._redone = null
}
/**
* Create a operation with the same effect (without position effect)
* Copy the effect of struct
*/
_copy () {
return new this.constructor()
}
/**
* Redo the effect of this operation.
*/
_redo (y) {
if (this._redone !== null) {
return this._redone
_copy (undeleteChildren, copyPosition) {
let struct = new this.constructor()
if (copyPosition) {
struct._origin = this._left
struct._left = this._left
struct._right = this
struct._right_origin = this
struct._parent = this._parent
struct._parentSub = this._parentSub
}
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) {
if (left._redone !== null && left._redone._parent === parent) {
left = left._redone
break
}
left = left._left
}
while (right !== null) {
if (right._redone !== null && right._redone._parent === parent) {
right = right._redone
}
right = right._right
}
}
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
}
get _lastId () {
return new ID(this._id.user, this._id.clock + this._length - 1)
}

View File

@@ -6,8 +6,8 @@ export default class ItemJSON extends Item {
super()
this._content = null
}
_copy () {
let struct = super._copy()
_copy (undeleteChildren, copyPosition) {
let struct = super._copy(undeleteChildren, copyPosition)
struct._content = this._content
return struct
}

View File

@@ -6,8 +6,8 @@ export default class ItemString extends Item {
super()
this._content = null
}
_copy () {
let struct = super._copy()
_copy (undeleteChildren, copyPosition) {
let struct = super._copy(undeleteChildren, copyPosition)
struct._content = this._content
return struct
}

View File

@@ -79,6 +79,40 @@ export default class Type extends Item {
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) {
const y = this._y
if (y !== null) {

View File

@@ -8,9 +8,6 @@ export default class YXmlElement extends YXmlFragment {
super()
this.nodeName = null
this._scrollElement = null
if (typeof arg2 === 'function') {
this._domFilter = arg2
}
if (typeof arg1 === 'string') {
this.nodeName = arg1.toUpperCase()
} else if (arg1 != null && arg1.nodeType != null && arg1.nodeType === arg1.ELEMENT_NODE) {
@@ -19,9 +16,12 @@ export default class YXmlElement extends YXmlFragment {
} else {
this.nodeName = 'UNDEFINED'
}
if (typeof arg2 === 'function') {
this._domFilter = arg2
}
}
_copy () {
let struct = super._copy()
_copy (undeleteChildren, copyPosition) {
let struct = super._copy(undeleteChildren, copyPosition)
struct.nodeName = this.nodeName
return struct
}
@@ -36,10 +36,9 @@ export default class YXmlElement extends YXmlFragment {
let attributes = new Map()
for (let i = 0; i < dom.attributes.length; i++) {
let attr = dom.attributes[i]
// get attribute via getAttribute for custom element support (some write something different in attr.value)
attributes.set(attr.name, dom.getAttribute(attr.name))
attributes.set(attr.name, attr.value)
}
attributes = this._domFilter(dom.nodeName, attributes)
attributes = this._domFilter(dom, attributes)
attributes.forEach((value, name) => {
this.setAttribute(name, value)
})

View File

@@ -14,8 +14,8 @@ export default class YXmlHook extends YMap {
getHook(hookName).fillType(dom, this)
}
}
_copy () {
const struct = super._copy()
_copy (undeleteChildren, copyPosition) {
const struct = super._copy(undeleteChildren, copyPosition)
struct.hookName = this.hookName
return struct
}

View File

@@ -4,12 +4,11 @@ class ReverseOperation {
constructor (y, transaction) {
this.created = new Date()
const beforeState = transaction.beforeState
this.toState = new ID(y.userID, y.ss.getState(y.userID) - 1)
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))
} else {
this.toState = null
this.fromState = null
this.fromState = this.toState
}
this.deletedStructs = transaction.deletedStructs
}
@@ -31,32 +30,28 @@ function applyReverseOperation (y, scope, reverseBuffer) {
while (!performedUndo && reverseBuffer.length > 0) {
let undoOp = reverseBuffer.pop()
// make sure that it is possible to iterate {from}-{to}
if (undoOp.fromState !== null) {
y.os.getItemCleanStart(undoOp.fromState)
y.os.getItemCleanEnd(undoOp.toState)
y.os.iterate(undoOp.fromState, undoOp.toState, op => {
while (op._deleted && op._redone !== null) {
op = op._redone
}
if (op._deleted === false && isStructInScope(y, op, scope)) {
performedUndo = true
op._delete(y)
}
})
}
y.os.getItemCleanStart(undoOp.fromState)
y.os.getItemCleanEnd(undoOp.toState)
y.os.iterate(undoOp.fromState, undoOp.toState, op => {
if (!op._deleted && isStructInScope(y, op, scope)) {
performedUndo = true
op._delete(y)
}
})
for (let op of undoOp.deletedStructs) {
if (
isStructInScope(y, op, scope) &&
op._parent !== y &&
!op._parent._deleted &&
(
op._id.user !== y.userID ||
undoOp.fromState === null ||
op._id.clock < undoOp.fromState.clock ||
op._id.clock > undoOp.toState.clock
op._parent._id.user !== y.userID ||
op._parent._id.clock < undoOp.fromState.clock ||
op._parent._id.clock > undoOp.fromState.clock
)
) {
performedUndo = true
op._redo(y)
op = op._copy(undoOp.deletedStructs, true)
op._integrate(y)
}
}
}
@@ -73,7 +68,6 @@ export default class UndoManager {
this._scope = scope
this._undoing = false
this._redoing = false
this._lastTransactionWasUndo = false
const y = scope._y
this.y = y
y.on('afterTransaction', (y, transaction, remote) => {
@@ -81,29 +75,17 @@ export default class UndoManager {
let reverseOperation = new ReverseOperation(y, transaction)
if (!this._undoing) {
let lastUndoOp = this._undoBuffer.length > 0 ? this._undoBuffer[this._undoBuffer.length - 1] : null
if (
this._redoing === false &&
this._lastTransactionWasUndo === false &&
lastUndoOp !== null &&
reverseOperation.created - lastUndoOp.created <= options.captureTimeout
) {
if (lastUndoOp !== null && reverseOperation.created - lastUndoOp.created <= options.captureTimeout) {
lastUndoOp.created = reverseOperation.created
if (reverseOperation.toState !== null) {
lastUndoOp.toState = reverseOperation.toState
if (lastUndoOp.fromState === null) {
lastUndoOp.fromState = reverseOperation.fromState
}
}
lastUndoOp.toState = reverseOperation.toState
reverseOperation.deletedStructs.forEach(lastUndoOp.deletedStructs.add, lastUndoOp.deletedStructs)
} else {
this._lastTransactionWasUndo = false
this._undoBuffer.push(reverseOperation)
}
if (!this._redoing) {
this._redoBuffer = []
}
} else {
this._lastTransactionWasUndo = true
this._redoBuffer.push(reverseOperation)
}
}

8
y.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

178
y.node.js
View File

@@ -1,7 +1,7 @@
/**
* yjs - A framework for real-time p2p shared editing on any data
* @version v13.0.0-55
* @version v13.0.0-51
* @license MIT
*/
@@ -1340,57 +1340,22 @@ class Item {
this._parent = null;
this._parentSub = null;
this._deleted = false;
this._redone = null;
}
/**
* Create a operation with the same effect (without position effect)
* Copy the effect of struct
*/
_copy () {
return new this.constructor()
}
/**
* Redo the effect of this operation.
*/
_redo (y) {
if (this._redone !== null) {
return this._redone
_copy (undeleteChildren, copyPosition) {
let struct = new this.constructor();
if (copyPosition) {
struct._origin = this._left;
struct._left = this._left;
struct._right = this;
struct._right_origin = this;
struct._parent = this._parent;
struct._parentSub = this._parentSub;
}
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) {
if (left._redone !== null && left._redone._parent === parent) {
left = left._redone;
break
}
left = left._left;
}
while (right !== null) {
if (right._redone !== null && right._redone._parent === parent) {
right = right._redone;
}
right = right._right;
}
}
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
}
get _lastId () {
return new ID(this._id.user, this._id.clock + this._length - 1)
}
@@ -1759,6 +1724,40 @@ class Type extends Item {
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) {
const y = this._y;
if (y !== null) {
@@ -1822,8 +1821,8 @@ class ItemJSON extends Item {
super();
this._content = null;
}
_copy () {
let struct = super._copy();
_copy (undeleteChildren, copyPosition) {
let struct = super._copy(undeleteChildren, copyPosition);
struct._content = this._content;
return struct
}
@@ -1884,8 +1883,8 @@ class ItemString extends Item {
super();
this._content = null;
}
_copy () {
let struct = super._copy();
_copy (undeleteChildren, copyPosition) {
let struct = super._copy(undeleteChildren, copyPosition);
struct._content = this._content;
return struct
}
@@ -3126,9 +3125,6 @@ class YXmlElement extends YXmlFragment {
super();
this.nodeName = null;
this._scrollElement = null;
if (typeof arg2 === 'function') {
this._domFilter = arg2;
}
if (typeof arg1 === 'string') {
this.nodeName = arg1.toUpperCase();
} else if (arg1 != null && arg1.nodeType != null && arg1.nodeType === arg1.ELEMENT_NODE) {
@@ -3137,9 +3133,12 @@ class YXmlElement extends YXmlFragment {
} else {
this.nodeName = 'UNDEFINED';
}
if (typeof arg2 === 'function') {
this._domFilter = arg2;
}
}
_copy () {
let struct = super._copy();
_copy (undeleteChildren, copyPosition) {
let struct = super._copy(undeleteChildren, copyPosition);
struct.nodeName = this.nodeName;
return struct
}
@@ -3154,10 +3153,9 @@ class YXmlElement extends YXmlFragment {
let attributes = new Map();
for (let i = 0; i < dom.attributes.length; i++) {
let attr = dom.attributes[i];
// get attribute via getAttribute for custom element support (some write something different in attr.value)
attributes.set(attr.name, dom.getAttribute(attr.name));
attributes.set(attr.name, attr.value);
}
attributes = this._domFilter(dom.nodeName, attributes);
attributes = this._domFilter(dom, attributes);
attributes.forEach((value, name) => {
this.setAttribute(name, value);
});
@@ -3278,8 +3276,8 @@ class YXmlHook extends YMap {
getHook(hookName).fillType(dom, this);
}
}
_copy () {
const struct = super._copy();
_copy (undeleteChildren, copyPosition) {
const struct = super._copy(undeleteChildren, copyPosition);
struct.hookName = this.hookName;
return struct
}
@@ -3677,12 +3675,11 @@ class ReverseOperation {
constructor (y, transaction) {
this.created = new Date();
const beforeState = transaction.beforeState;
this.toState = new ID(y.userID, y.ss.getState(y.userID) - 1);
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));
} else {
this.toState = null;
this.fromState = null;
this.fromState = this.toState;
}
this.deletedStructs = transaction.deletedStructs;
}
@@ -3704,32 +3701,28 @@ function applyReverseOperation (y, scope, reverseBuffer) {
while (!performedUndo && reverseBuffer.length > 0) {
let undoOp = reverseBuffer.pop();
// make sure that it is possible to iterate {from}-{to}
if (undoOp.fromState !== null) {
y.os.getItemCleanStart(undoOp.fromState);
y.os.getItemCleanEnd(undoOp.toState);
y.os.iterate(undoOp.fromState, undoOp.toState, op => {
while (op._deleted && op._redone !== null) {
op = op._redone;
}
if (op._deleted === false && isStructInScope(y, op, scope)) {
performedUndo = true;
op._delete(y);
}
});
}
y.os.getItemCleanStart(undoOp.fromState);
y.os.getItemCleanEnd(undoOp.toState);
y.os.iterate(undoOp.fromState, undoOp.toState, op => {
if (!op._deleted && isStructInScope(y, op, scope)) {
performedUndo = true;
op._delete(y);
}
});
for (let op of undoOp.deletedStructs) {
if (
isStructInScope(y, op, scope) &&
op._parent !== y &&
!op._parent._deleted &&
(
op._id.user !== y.userID ||
undoOp.fromState === null ||
op._id.clock < undoOp.fromState.clock ||
op._id.clock > undoOp.toState.clock
op._parent._id.user !== y.userID ||
op._parent._id.clock < undoOp.fromState.clock ||
op._parent._id.clock > undoOp.fromState.clock
)
) {
performedUndo = true;
op._redo(y);
op = op._copy(undoOp.deletedStructs, true);
op._integrate(y);
}
}
}
@@ -3746,7 +3739,6 @@ class UndoManager {
this._scope = scope;
this._undoing = false;
this._redoing = false;
this._lastTransactionWasUndo = false;
const y = scope._y;
this.y = y;
y.on('afterTransaction', (y, transaction, remote) => {
@@ -3754,29 +3746,17 @@ class UndoManager {
let reverseOperation = new ReverseOperation(y, transaction);
if (!this._undoing) {
let lastUndoOp = this._undoBuffer.length > 0 ? this._undoBuffer[this._undoBuffer.length - 1] : null;
if (
this._redoing === false &&
this._lastTransactionWasUndo === false &&
lastUndoOp !== null &&
reverseOperation.created - lastUndoOp.created <= options.captureTimeout
) {
if (lastUndoOp !== null && reverseOperation.created - lastUndoOp.created <= options.captureTimeout) {
lastUndoOp.created = reverseOperation.created;
if (reverseOperation.toState !== null) {
lastUndoOp.toState = reverseOperation.toState;
if (lastUndoOp.fromState === null) {
lastUndoOp.fromState = reverseOperation.fromState;
}
}
lastUndoOp.toState = reverseOperation.toState;
reverseOperation.deletedStructs.forEach(lastUndoOp.deletedStructs.add, lastUndoOp.deletedStructs);
} else {
this._lastTransactionWasUndo = false;
this._undoBuffer.push(reverseOperation);
}
if (!this._redoing) {
this._redoBuffer = [];
}
} else {
this._lastTransactionWasUndo = true;
this._redoBuffer.push(reverseOperation);
}
}
@@ -4650,10 +4630,8 @@ class AbstractConnector {
}
function fromBinary (y, decoder) {
y.transact(function () {
integrateRemoteStructs(y, decoder);
readDeleteSet(y, decoder);
});
integrateRemoteStructs(y, decoder);
readDeleteSet(y, decoder);
}
function toBinary (y) {

File diff suppressed because one or more lines are too long

19485
y.test.js Normal file

File diff suppressed because one or more lines are too long

1
y.test.js.map Normal file

File diff suppressed because one or more lines are too long