Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a08e54c2fc | ||
|
|
2b377cd46d | ||
|
|
df9bfbe778 | ||
|
|
f1ab417570 | ||
|
|
371f2b6d55 | ||
|
|
85a7ad148f | ||
|
|
7ec1b3a19e | ||
|
|
633eb9033c | ||
|
|
4707fc46ac | ||
|
|
89b4320a8e | ||
|
|
0ea0a35521 | ||
|
|
15ea4ee805 | ||
|
|
5ddb7eefed |
@@ -100,6 +100,7 @@ are implemented in separate modules.
|
|||||||
| [CodeMirror](https://codemirror.net/) | ✔ | [y-codemirror](https://github.com/yjs/y-codemirror) | [demo](https://demos.yjs.dev/codemirror/codemirror.html) |
|
| [CodeMirror](https://codemirror.net/) | ✔ | [y-codemirror](https://github.com/yjs/y-codemirror) | [demo](https://demos.yjs.dev/codemirror/codemirror.html) |
|
||||||
| [Monaco](https://microsoft.github.io/monaco-editor/) | ✔ | [y-monaco](https://github.com/yjs/y-monaco) | [demo](https://demos.yjs.dev/monaco/monaco.html) |
|
| [Monaco](https://microsoft.github.io/monaco-editor/) | ✔ | [y-monaco](https://github.com/yjs/y-monaco) | [demo](https://demos.yjs.dev/monaco/monaco.html) |
|
||||||
| [Slate](https://github.com/ianstormtaylor/slate) | ✔ | [slate-yjs](https://github.com/bitphinix/slate-yjs) | [demo](https://bitphinix.github.io/slate-yjs-example) |
|
| [Slate](https://github.com/ianstormtaylor/slate) | ✔ | [slate-yjs](https://github.com/bitphinix/slate-yjs) | [demo](https://bitphinix.github.io/slate-yjs-example) |
|
||||||
|
| [valtio](https://github.com/pmndrs/valtio) | | [valtio-yjs](https://github.com/dai-shi/valtio-yjs) | [demo](https://codesandbox.io/s/valtio-yjs-demo-ox3iy) |
|
||||||
|
|
||||||
### Providers
|
### Providers
|
||||||
|
|
||||||
@@ -988,7 +989,7 @@ order of the structs anymore (e.g. if the parent was deleted).
|
|||||||
**Examples:**
|
**Examples:**
|
||||||
|
|
||||||
1. If a user inserts elements in sequence, the struct will be merged into a
|
1. If a user inserts elements in sequence, the struct will be merged into a
|
||||||
single struct. E.g. `array.insert(0, ['a']), array.insert(0, ['b']);` is
|
single struct. E.g. `text.insert(0, 'a'), text.insert(1, 'b');` is
|
||||||
first represented as two structs (`[{id: {client, clock: 0}, content: 'a'},
|
first represented as two structs (`[{id: {client, clock: 0}, content: 'a'},
|
||||||
{id: {client, clock: 1}, content: 'b'}`) and then merged into a single
|
{id: {client, clock: 1}, content: 'b'}`) and then merged into a single
|
||||||
struct: `[{id: {client, clock: 0}, content: 'ab'}]`.
|
struct: `[{id: {client, clock: 0}, content: 'ab'}]`.
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.5.11",
|
"version": "13.5.13",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.5.11",
|
"version": "13.5.13",
|
||||||
"description": "Shared Editing Library",
|
"description": "Shared Editing Library",
|
||||||
"main": "./dist/yjs.cjs",
|
"main": "./dist/yjs.cjs",
|
||||||
"module": "./dist/yjs.mjs",
|
"module": "./dist/yjs.mjs",
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export {
|
|||||||
snapshot,
|
snapshot,
|
||||||
emptySnapshot,
|
emptySnapshot,
|
||||||
findRootTypeKey,
|
findRootTypeKey,
|
||||||
|
findIndexSS,
|
||||||
getItem,
|
getItem,
|
||||||
typeListToArraySnapshot,
|
typeListToArraySnapshot,
|
||||||
typeMapGetSnapshot,
|
typeMapGetSnapshot,
|
||||||
|
|||||||
@@ -164,12 +164,13 @@ const insertNegatedAttributes = (transaction, parent, currPos, negatedAttributes
|
|||||||
}
|
}
|
||||||
const doc = transaction.doc
|
const doc = transaction.doc
|
||||||
const ownClientId = doc.clientID
|
const ownClientId = doc.clientID
|
||||||
let nextFormat = currPos.left
|
|
||||||
const right = currPos.right
|
|
||||||
negatedAttributes.forEach((val, key) => {
|
negatedAttributes.forEach((val, key) => {
|
||||||
nextFormat = new Item(createID(ownClientId, getState(doc.store, ownClientId)), nextFormat, nextFormat && nextFormat.lastId, right, right && right.id, parent, null, new ContentFormat(key, val))
|
const left = currPos.left
|
||||||
|
const right = currPos.right
|
||||||
|
const nextFormat = new Item(createID(ownClientId, getState(doc.store, ownClientId)), left, left && left.lastId, right, right && right.id, parent, null, new ContentFormat(key, val))
|
||||||
nextFormat.integrate(transaction, 0)
|
nextFormat.integrate(transaction, 0)
|
||||||
currPos.right = nextFormat
|
currPos.right = nextFormat
|
||||||
|
currPos.forward()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export class YXmlElement extends YXmlFragment {
|
|||||||
el.setAttribute(key, attrs[key])
|
el.setAttribute(key, attrs[key])
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
el.insert(0, el.toArray().map(item => item instanceof AbstractType ? item.clone() : item))
|
el.insert(0, this.toArray().map(item => item instanceof AbstractType ? item.clone() : item))
|
||||||
return el
|
return el
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ export class YXmlFragment extends AbstractType {
|
|||||||
clone () {
|
clone () {
|
||||||
const el = new YXmlFragment()
|
const el = new YXmlFragment()
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
el.insert(0, el.toArray().map(item => item instanceof AbstractType ? item.clone() : item))
|
el.insert(0, this.toArray().map(item => item instanceof AbstractType ? item.clone() : item))
|
||||||
return el
|
return el
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -287,6 +287,9 @@ const sliceStruct = (left, diff) => {
|
|||||||
* @return {Uint8Array}
|
* @return {Uint8Array}
|
||||||
*/
|
*/
|
||||||
export const mergeUpdatesV2 = (updates, YDecoder = UpdateDecoderV2, YEncoder = UpdateEncoderV2) => {
|
export const mergeUpdatesV2 = (updates, YDecoder = UpdateDecoderV2, YEncoder = UpdateEncoderV2) => {
|
||||||
|
if (updates.length === 1) {
|
||||||
|
return updates[0]
|
||||||
|
}
|
||||||
const updateDecoders = updates.map(update => new YDecoder(decoding.createDecoder(update)))
|
const updateDecoders = updates.map(update => new YDecoder(decoding.createDecoder(update)))
|
||||||
let lazyStructDecoders = updateDecoders.map(decoder => new LazyStructReader(decoder, true))
|
let lazyStructDecoders = updateDecoders.map(decoder => new LazyStructReader(decoder, true))
|
||||||
|
|
||||||
@@ -312,8 +315,9 @@ export const mergeUpdatesV2 = (updates, YDecoder = UpdateDecoderV2, YEncoder = U
|
|||||||
if (dec1.curr.id.client === dec2.curr.id.client) {
|
if (dec1.curr.id.client === dec2.curr.id.client) {
|
||||||
const clockDiff = dec1.curr.id.clock - dec2.curr.id.clock
|
const clockDiff = dec1.curr.id.clock - dec2.curr.id.clock
|
||||||
if (clockDiff === 0) {
|
if (clockDiff === 0) {
|
||||||
|
// @todo remove references to skip since the structDecoders must filter Skips.
|
||||||
return dec1.curr.constructor === dec2.curr.constructor ? 0 : (
|
return dec1.curr.constructor === dec2.curr.constructor ? 0 : (
|
||||||
dec1.curr.constructor === Skip ? 1 : -1
|
dec1.curr.constructor === Skip ? 1 : -1 // we are filtering skips anyway.
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return clockDiff
|
return clockDiff
|
||||||
|
|||||||
@@ -150,3 +150,36 @@ export const testInsertafter = tc => {
|
|||||||
el.insertAfter(deepsecond1, [new Y.XmlText()])
|
el.insertAfter(deepsecond1, [new Y.XmlText()])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
*/
|
||||||
|
export const testClone = tc => {
|
||||||
|
const ydoc = new Y.Doc()
|
||||||
|
const yxml = ydoc.getXmlFragment()
|
||||||
|
const first = new Y.XmlText('text')
|
||||||
|
const second = new Y.XmlElement('p')
|
||||||
|
const third = new Y.XmlElement('p')
|
||||||
|
yxml.push([first, second, third])
|
||||||
|
t.compareArrays(yxml.toArray(), [first, second, third])
|
||||||
|
|
||||||
|
const cloneYxml = yxml.clone()
|
||||||
|
ydoc.getArray('copyarr').insert(0, [cloneYxml])
|
||||||
|
t.assert(cloneYxml.length === 3)
|
||||||
|
t.compare(cloneYxml.toJSON(), yxml.toJSON())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
*/
|
||||||
|
export const testFormattingBug = tc => {
|
||||||
|
const ydoc = new Y.Doc()
|
||||||
|
const yxml = /** @type {Y.XmlText} */ (ydoc.get('', Y.XmlText))
|
||||||
|
const delta = [
|
||||||
|
{ insert: 'A', attributes: { em: {}, strong: {} } },
|
||||||
|
{ insert: 'B', attributes: { em: {} } },
|
||||||
|
{ insert: 'C', attributes: { em: {}, strong: {} } }
|
||||||
|
]
|
||||||
|
yxml.applyDelta(delta)
|
||||||
|
t.compare(yxml.toDelta(), delta)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user