Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b56debef00 | ||
|
|
5b16071380 | ||
|
|
7ced59c847 | ||
|
|
3c98d97369 |
@@ -482,8 +482,6 @@ or any of its children.
|
|||||||
<dd>Clone this type into a fresh Yjs type.</dd>
|
<dd>Clone this type into a fresh Yjs type.</dd>
|
||||||
<b><code>toArray():Array<Y.XmlElement|Y.XmlText></code></b>
|
<b><code>toArray():Array<Y.XmlElement|Y.XmlText></code></b>
|
||||||
<dd>Copies the children to a new Array.</dd>
|
<dd>Copies the children to a new Array.</dd>
|
||||||
<b><code>toDOM():DocumentFragment</code></b>
|
|
||||||
<dd>Transforms this type and all children to new DOM elements.</dd>
|
|
||||||
<b><code>toString():string</code></b>
|
<b><code>toString():string</code></b>
|
||||||
<dd>Get the XML serialization of all descendants.</dd>
|
<dd>Get the XML serialization of all descendants.</dd>
|
||||||
<b><code>toJSON():string</code></b>
|
<b><code>toJSON():string</code></b>
|
||||||
@@ -557,8 +555,6 @@ content and be actually XML compliant.
|
|||||||
<dd>Clone this type into a fresh Yjs type.</dd>
|
<dd>Clone this type into a fresh Yjs type.</dd>
|
||||||
<b><code>toArray():Array<Y.XmlElement|Y.XmlText></code></b>
|
<b><code>toArray():Array<Y.XmlElement|Y.XmlText></code></b>
|
||||||
<dd>Copies the children to a new Array.</dd>
|
<dd>Copies the children to a new Array.</dd>
|
||||||
<b><code>toDOM():Element</code></b>
|
|
||||||
<dd>Transforms this type and all children to a new DOM element.</dd>
|
|
||||||
<b><code>toString():string</code></b>
|
<b><code>toString():string</code></b>
|
||||||
<dd>Get the XML serialization of all descendants.</dd>
|
<dd>Get the XML serialization of all descendants.</dd>
|
||||||
<b><code>toJSON():string</code></b>
|
<b><code>toJSON():string</code></b>
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "14.0.0-0",
|
"version": "14.0.0-1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "14.0.0-0",
|
"version": "14.0.0-1",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "14.0.0-0",
|
"version": "14.0.0-1",
|
||||||
"description": "Shared Editing Library",
|
"description": "Shared Editing Library",
|
||||||
"main": "./dist/yjs.cjs",
|
"main": "./dist/yjs.cjs",
|
||||||
"module": "./dist/yjs.mjs",
|
"module": "./dist/yjs.mjs",
|
||||||
|
|||||||
@@ -40,36 +40,6 @@ export class YXmlHook extends YMap {
|
|||||||
return el
|
return el
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Dom Element that mirrors this YXmlElement.
|
|
||||||
*
|
|
||||||
* @param {Document} [_document=document] The document object (you must define
|
|
||||||
* this when calling this method in
|
|
||||||
* nodejs)
|
|
||||||
* @param {Object.<string, any>} [hooks] Optional property to customize how hooks
|
|
||||||
* are presented in the DOM
|
|
||||||
* @param {any} [binding] You should not set this property. This is
|
|
||||||
* used if DomBinding wants to create a
|
|
||||||
* association to the created DOM type
|
|
||||||
* @return {Element} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
toDOM (_document = document, hooks = {}, binding) {
|
|
||||||
const hook = hooks[this.hookName]
|
|
||||||
let dom
|
|
||||||
if (hook !== undefined) {
|
|
||||||
dom = hook.createDom(this)
|
|
||||||
} else {
|
|
||||||
dom = document.createElement(this.hookName)
|
|
||||||
}
|
|
||||||
dom.setAttribute('data-yjs-hook', this.hookName)
|
|
||||||
if (binding !== undefined) {
|
|
||||||
binding._createAssociation(dom, this)
|
|
||||||
}
|
|
||||||
return dom
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform the properties of this type to binary and write it to an
|
* Transform the properties of this type to binary and write it to an
|
||||||
* BinaryEncoder.
|
* BinaryEncoder.
|
||||||
|
|||||||
@@ -39,29 +39,6 @@ export class YXmlText extends YText {
|
|||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a Dom Element that mirrors this YXmlText.
|
|
||||||
*
|
|
||||||
* @param {Document} [_document=document] The document object (you must define
|
|
||||||
* this when calling this method in
|
|
||||||
* nodejs)
|
|
||||||
* @param {Object<string, any>} [hooks] Optional property to customize how hooks
|
|
||||||
* are presented in the DOM
|
|
||||||
* @param {any} [binding] You should not set this property. This is
|
|
||||||
* used if DomBinding wants to create a
|
|
||||||
* association to the created DOM type.
|
|
||||||
* @return {Text} The {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}
|
|
||||||
*
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
toDOM (_document = document, hooks, binding) {
|
|
||||||
const dom = _document.createTextNode(this.toString())
|
|
||||||
if (binding !== undefined) {
|
|
||||||
binding._createAssociation(dom, this)
|
|
||||||
}
|
|
||||||
return dom
|
|
||||||
}
|
|
||||||
|
|
||||||
toString () {
|
toString () {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return this.toDelta().map(delta => {
|
return this.toDelta().map(delta => {
|
||||||
|
|||||||
@@ -522,7 +522,8 @@ export class ListCursor {
|
|||||||
*/
|
*/
|
||||||
forEach (tr, f) {
|
forEach (tr, f) {
|
||||||
for (const val of this.values(tr)) {
|
for (const val of this.values(tr)) {
|
||||||
f(val, this.index, this.type)
|
// decrease index because retrieving value will increase index
|
||||||
|
f(val, this.index - 1, this.type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +537,7 @@ export class ListCursor {
|
|||||||
const arr = new Array(this.type._length - this.index)
|
const arr = new Array(this.type._length - this.index)
|
||||||
let i = 0
|
let i = 0
|
||||||
for (const val of this.values(tr)) {
|
for (const val of this.values(tr)) {
|
||||||
arr[i++] = f(val, this.index, this.type)
|
arr[i++] = f(val, this.index - 1, this.type)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
import * as set from 'lib0/set'
|
import * as set from 'lib0/set'
|
||||||
import * as array from 'lib0/array'
|
import * as array from 'lib0/array'
|
||||||
import { addsStruct } from './Transaction.js'
|
import { addsStruct } from './Transaction.js'
|
||||||
|
import { ListCursor } from './ListCursor.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* YEvent describes the changes on a YType.
|
* YEvent describes the changes on a YType.
|
||||||
@@ -62,7 +63,7 @@ export class YEvent {
|
|||||||
*/
|
*/
|
||||||
get path () {
|
get path () {
|
||||||
// @ts-ignore _item is defined because target is integrated
|
// @ts-ignore _item is defined because target is integrated
|
||||||
return getPathTo(this.currentTarget, this.target)
|
return getPathTo(this.currentTarget, this.target, this.transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -297,12 +298,13 @@ export class YEvent {
|
|||||||
*
|
*
|
||||||
* @param {AbstractType<any>} parent
|
* @param {AbstractType<any>} parent
|
||||||
* @param {AbstractType<any>} child target
|
* @param {AbstractType<any>} child target
|
||||||
|
* @param {Transaction} tr
|
||||||
* @return {Array<string|number>} Path to the target
|
* @return {Array<string|number>} Path to the target
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
const getPathTo = (parent, child) => {
|
const getPathTo = (parent, child, tr) => {
|
||||||
const path = []
|
const path = []
|
||||||
while (child._item !== null && child !== parent) {
|
while (child._item !== null && child !== parent) {
|
||||||
if (child._item.parentSub !== null) {
|
if (child._item.parentSub !== null) {
|
||||||
@@ -310,15 +312,11 @@ const getPathTo = (parent, child) => {
|
|||||||
path.unshift(child._item.parentSub)
|
path.unshift(child._item.parentSub)
|
||||||
} else {
|
} else {
|
||||||
// parent is array-ish
|
// parent is array-ish
|
||||||
let i = 0
|
const c = new ListCursor(/** @type {AbstractType<any>} */ (child._item.parent))
|
||||||
let c = /** @type {AbstractType<any>} */ (child._item.parent)._start
|
while (c.nextItem != null && !c.reachedEnd && c.nextItem !== child._item) {
|
||||||
while (c !== child._item && c !== null) {
|
c.forward(tr, (c.nextItem.countable && !c.nextItem.deleted) ? c.nextItem.length : 0, true)
|
||||||
if (!c.deleted) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
c = c.right
|
|
||||||
}
|
}
|
||||||
path.unshift(i)
|
path.unshift(c.index)
|
||||||
}
|
}
|
||||||
child = /** @type {AbstractType<any>} */ (child._item.parent)
|
child = /** @type {AbstractType<any>} */ (child._item.parent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,71 @@
|
|||||||
import { init, compare, applyRandomTests, Doc, AbstractType, TestConnector, Item } from './testHelper.js' // eslint-disable-line
|
import { init, compare, applyRandomTests, Doc, Item } from './testHelper.js' // eslint-disable-line
|
||||||
|
|
||||||
import * as Y from '../src/index.js'
|
import * as Y from '../src/index.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 math from 'lib0/math'
|
import * as math from 'lib0/math'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* path should be correct when moving item - see yjs#481
|
||||||
|
*
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
*/
|
||||||
|
export const testArrayMovePathIssue481 = tc => {
|
||||||
|
const { users, testConnector, array0, array1 } = init(tc, { users: 2 })
|
||||||
|
array0.observeDeep(events => {
|
||||||
|
events.forEach(event => {
|
||||||
|
if (event.path.length > 0) {
|
||||||
|
/**
|
||||||
|
* @type {any}
|
||||||
|
*/
|
||||||
|
let target = event.currentTarget
|
||||||
|
event.path.forEach(p => {
|
||||||
|
target = target.get(p)
|
||||||
|
})
|
||||||
|
t.assert(target === event.target)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
array0.push([
|
||||||
|
['a', '1.1'],
|
||||||
|
['b', '2.2'],
|
||||||
|
['c', '3.1'],
|
||||||
|
['d', '4.1'],
|
||||||
|
['e', '5.1']
|
||||||
|
].map(e => Y.Array.from(e)))
|
||||||
|
testConnector.flushAllMessages()
|
||||||
|
users[1].transact(() => {
|
||||||
|
array1.get(1).insert(0, ['0'])
|
||||||
|
array1.move(1, 0)
|
||||||
|
})
|
||||||
|
testConnector.flushAllMessages()
|
||||||
|
users[1].transact(() => {
|
||||||
|
array1.get(3).insert(0, ['1'])
|
||||||
|
array1.move(3, 4)
|
||||||
|
})
|
||||||
|
testConnector.flushAllMessages()
|
||||||
|
users[1].transact(() => {
|
||||||
|
array1.get(2).insert(0, ['2'])
|
||||||
|
array1.move(2, array1.length)
|
||||||
|
})
|
||||||
|
testConnector.flushAllMessages()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* foreach has correct index - see yjs#485
|
||||||
|
*
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
*/
|
||||||
|
export const testArrayIndexIssue485 = tc => {
|
||||||
|
const doc = new Y.Doc()
|
||||||
|
const yarr = doc.getArray()
|
||||||
|
yarr.push([1, 2])
|
||||||
|
yarr.forEach((el, index) => {
|
||||||
|
t.info('index: ' + index)
|
||||||
|
t.assert(yarr.get(index) === el)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {t.TestCase} tc
|
* @param {t.TestCase} tc
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user