Compare commits

...

25 Commits

Author SHA1 Message Date
Kevin Jahns
1bec008862 13.6.22 2025-01-12 19:45:03 +01:00
Kevin Jahns
bb5410b6dd marginally better typings for applyDelta - #689 2025-01-12 19:41:19 +01:00
Kevin Jahns
2d2e662d4d Merge pull request #690 from yjs/revert-689-patch-1
Revert "fix(yText): applyDelta should support both Delta and Ops[]"
2025-01-12 19:33:12 +01:00
Kevin Jahns
80e83a84c6 Revert "fix(yText): applyDelta should support both Delta and Ops[]" 2025-01-12 19:32:51 +01:00
Kevin Jahns
3c9c0f17d1 Merge pull request #689 from ykou-clickup/patch-1
fix(yText): applyDelta should support both Delta and Ops[]
2025-01-12 19:26:30 +01:00
Yuxiang Kou
e67b1296a7 fix(yText): applyDelta should support both Delta and Ops[]
Fixed an issue that the yText.applyDelta() accepted only Ops[], but not Delta.
2025-01-09 14:58:47 -08:00
Kevin Jahns
1a0d4aa797 Merge pull request #685 from szepeviktor/typos
Fix typos
2025-01-07 12:36:44 +01:00
Viktor Szépe
f18eab2dfe Fix typos 2025-01-03 18:11:43 +00:00
Kevin Jahns
89dddc2a95 13.6.21 2024-12-21 00:55:05 +01:00
Kevin Jahns
f583d2a211 fix #657 - relative positions issue when using followUndoneDeletions=false 2024-12-21 00:52:48 +01:00
Kevin Jahns
1b0f2e5463 lint 2024-12-18 14:35:13 +01:00
Kevin Jahns
4404d090e4 add nodejs specific tests 2024-12-18 14:34:33 +01:00
Kevin Jahns
d4d4ae5f53 Merge pull request #679 from hoangqwe159/main
Add PSPDFKit binding to README.md
2024-12-14 21:24:57 +01:00
Viet Hoang Do
4ffd3709f8 Add PSPDFKit binding to README.md 2024-12-06 09:58:19 +10:00
Kevin Jahns
0419b74315 Merge pull request #676 from himself65/patch-1
docs: remove `@toeverything/y-indexeddb`
2024-12-04 22:37:32 +01:00
Kevin Jahns
c951f2b7ea add Open Collaboration Tools as a user 2024-11-28 01:08:37 +01:00
Alex Yang
4e2d3c8ac6 docs: remove @toeverything/y-indexeddb 2024-11-27 15:42:50 -08:00
Kevin Jahns
8dc1296a0b update readme 2024-10-24 18:07:52 +02:00
Kevin Jahns
4329997350 add stars to providers that sponsor yjs 2024-10-24 18:05:42 +02:00
Kevin Jahns
2b7ea8a2af Merge pull request #671 from carlossantos74/main
Added SuperViz Provider to the list of providers
2024-10-24 17:38:00 +02:00
Carlos
4f47355893 add SuperViz Provider in yjs README 2024-10-22 16:26:33 -03:00
Kevin Jahns
6074f80257 [funding.json] fix some validation issues 2024-10-19 17:43:48 +02:00
Kevin Jahns
42bbb44bfc fix errors in funding.json 2024-10-19 04:50:46 +02:00
Kevin Jahns
cc2d7320aa add funding.json 2024-10-19 04:40:13 +02:00
Kevin Jahns
e804dd7573 add y-crdt elexir bindings 2024-10-19 04:40:11 +02:00
21 changed files with 254 additions and 59 deletions

View File

@@ -60,7 +60,7 @@ characters have either been deleted or all characters are not deleted. The item
will be split if the run is interrupted for any reason (eg a character in the
middle of the run is deleted).
When an item is created, it stores a reference to the IDs of the preceeding and
When an item is created, it stores a reference to the IDs of the preceding and
succeeding item. These are stored in the item's `origin` and `originRight`
fields, respectively. These are used when peers concurrently insert at the same
location in a document. Though quite rare in practice, Yjs needs to make sure

View File

@@ -110,7 +110,7 @@ Showcase](https://yjs-diagram.synergy.codes/).
* [Synthesia](https://www.synthesia.io) - Collaborative Video Editor
* [thinkdeli](https://thinkdeli.com) - A fast and simple notes app powered by AI
* [ourboard](https://github.com/raimohanska/ourboard) - A collaborative whiteboard
applicaiton
application
* [Ellie.ai](https://ellie.ai) - Data Product Design and Collaboration
* [GoPeer](https://gopeer.org/) - Collaborative tutoring
* [screen.garden](https://screen.garden) - Collaborative backend for PKM apps.
@@ -121,6 +121,8 @@ Showcase](https://yjs-diagram.synergy.codes/).
* [Eclipse Theia](https://github.com/eclipse-theia/theia) - A cloud & desktop
IDE that runs in the browser.
* [ScienHub](https://scienhub.com) - Collaborative LaTeX editor in the browser.
* [Open Collaboration Tools](https://www.open-collab.tools/) - Collaborative
editing for your IDE or custom editor
## Table of Contents
@@ -161,6 +163,7 @@ are implemented in separate modules.
| React | | [react-yjs](https://github.com/nikgraf/react-yjs) | [demo](https://react-yjs-example.vercel.app/) |
| React / Vue / Svelte / MobX | | [SyncedStore](https://syncedstore.org) | [demo](https://syncedstore.org/docs/react) |
| [mobx-keystone](https://mobx-keystone.js.org/) | | [mobx-keystone-yjs](https://github.com/xaviergonz/mobx-keystone/tree/master/packages/mobx-keystone-yjs) | [demo](https://mobx-keystone.js.org/examples/yjs-binding) |
| [PSPDFKit](https://www.nutrient.io/) | | [yjs-pspdfkit](https://github.com/hoangqwe159/yjs-pspdfkit) | [demo](https://github.com/hoangqwe159/yjs-pspdfkit) |
### Providers
@@ -186,12 +189,12 @@ backends to y-websocket.
<dt><a href="https://github.com/yjs/y-webrtc">y-webrtc</a></dt>
<dd>
Propagates document updates peer-to-peer using WebRTC. The peers exchange
signaling data over signaling servers. Publically available signaling servers
signaling data over signaling servers. Publicly available signaling servers
are available. Communication over the signaling servers can be encrypted by
providing a shared secret, keeping the connection information and the shared
document private.
</dd>
<dt><a href="https://github.com/liveblocks/liveblocks">@liveblocks/yjs</a></dt>
<dt><a href="https://github.com/liveblocks/liveblocks">@liveblocks/yjs </a> 🌟</dt>
<dd>
<a href="https://liveblocks.io/document/yjs">Liveblocks Yjs</a> provides a fully
hosted WebSocket infrastructure and persisted data store for Yjs
@@ -199,15 +202,23 @@ documents. No configuration or maintenance is required. It also features
Yjs webhook events, REST API to read and update Yjs documents, and a
browser DevTools extension.
</dd>
<dt><a href="https://github.com/drifting-in-space/y-sweet">y-sweet</a></dt>
<dt><a href="https://github.com/drifting-in-space/y-sweet">y-sweet</a></dt>
<dd>
A standalone yjs server with persistence to S3 or filesystem. They offer a
<a href="https://y-sweet.cloud">cloud service</a> as well.
</dd>
<dt><a href="https://github.com/ueberdosis/hocuspocus">Hocuspocus</a></dt>
<dt><a href="https://github.com/ueberdosis/hocuspocus">Hocuspocus</a></dt>
<dd>
A standalone extensible yjs server with sqlite persistence, webhooks, auth and more.
</dd>
<dt><a href="https://docs.superviz.com/collaboration/integrations/YJS/overview">@superviz/yjs</a></dt>
<dd>
SuperViz Yjs Provider comes with a secure, scalable real-time infrastructure
for Yjs documents, fully compatible with a set of real-time
collaboration components offered by SuperViz. This solution ensures
synchronization, offline editing, and real-time updates, enabling
multiple users to collaborate effectively within shared workspaces.
</dd>
<dt><a href="https://docs.partykit.io/reference/y-partykit-api/">PartyKit</a></dt>
<dd>
Cloud service for building multiplayer apps.
@@ -272,11 +283,6 @@ network provider.
<dd>
Adds persistent storage to a server with MongoDB. Can be used with the
y-websocket provider.
</dd>
<dt><a href="https://github.com/toeverything/AFFiNE/tree/master/packages/y-indexeddb">
@toeverything/y-indexeddb</a></dt>
<dd>
Like y-indexeddb, but with sub-documents support and fully TypeScript.
</dd>
<dt><a href="https://github.com/podraven/y-fire">y-fire</a></dt>
<dd>
@@ -315,6 +321,7 @@ language bindings to other languages
* [yswift](https://github.com/y-crdt/yswift) - Swift binding
* [yffi](https://github.com/y-crdt/y-crdt/tree/main/yffi) - C-FFI
* [ywasm](https://github.com/y-crdt/y-crdt/tree/main/ywasm) - WASM binding
* [y_ex](https://github.com/satoren/y_ex) - Elixir bindings
* [ycs](https://github.com/yjs/ycs) - .Net compatible C# implementation.
## Getting Started
@@ -1090,7 +1097,7 @@ encoding format for document updates. If you prefer JSON encoding, you can
simply JSON.stringify / JSON.parse the relative position instead.
</dd>
<b><code>Y.decodeRelativePosition(Uint8Array):RelativePosition</code></b>
<dd>Decode a binary-encoded relative position to a RelativePositon object.</dd>
<dd>Decode a binary-encoded relative position to a RelativePosition object.</dd>
</dl>
### Y.UndoManager
@@ -1270,11 +1277,11 @@ More information about the specific implementation is available in
CRDTs that are suitable for shared text editing suffer from the fact that they
only grow in size. There are CRDTs that do not grow in size, but they do not
have the characteristics that are benificial for shared text editing (like
have the characteristics that are beneficial for shared text editing (like
intention preservation). Yjs implements many improvements to the original
algorithm that diminish the trade-off that the document only grows in size. We
can't garbage collect deleted structs (tombstones) while ensuring a unique
order of the structs. But we can 1. merge preceeding structs into a single
order of the structs. But we can 1. merge preceding structs into a single
struct to reduce the amount of meta information, 2. we can delete content from
the struct if it is deleted, and 3. we can garbage collect tombstones if we
don't care about the order of the structs anymore (e.g. if the parent was

143
funding.json Normal file
View File

@@ -0,0 +1,143 @@
{
"version": "v1.0.0",
"entity": {
"type": "group",
"role": "steward",
"name": "Kevin Jahns",
"email": "kevin.jahns@protonmail.com",
"phone": "",
"description": "OSS Developer",
"webpageUrl": {
"url": "https://github.com/yjs"
}
},
"projects": [
{
"guid": "yjs",
"name": "Yjs",
"description": "A library for building collaborative applications. #p2p #local-first #CRDT Funding this project will also enable me to maintain the other Yjs-related technologies.",
"webpageUrl": {
"url": "https://github.com/yjs/yjs"
},
"repositoryUrl": {
"url": "https://github.com/yjs/yjs"
},
"licenses": [
"spdx:MIT"
],
"tags": [
"collaboration",
"p2p",
"CRDT",
"rich-text",
"real-time"
]
},
{
"guid": "ystream",
"name": "Y/Stream",
"description": "A provider for syncing millions of docs efficiently with other peers. This will become the foundation for building real local-first apps with Yjs.",
"webpageUrl": {
"url": "https://github.com/yjs/ystream",
"wellKnown": "https://github.com/yjs/ystream/blob/main/.well-known/funding-manifest-urls"
},
"repositoryUrl": {
"url": "https://github.com/yjs/ystream",
"wellKnown": "https://github.com/yjs/ystream/blob/main/.well-known/funding-manifest-urls"
},
"licenses": [
"spdx:MIT",
"spdx:GPL-3.0"
],
"tags": [
"privacy",
"collaboration",
"p2p",
"CRDT",
"rich-text",
"real-time",
"web-development"
]
}
],
"funding": {
"channels": [
{
"guid": "github-sponsors",
"type": "payment-provider",
"address": "",
"description": "For funding of the Yjs project"
},
{
"guid": "y-collective",
"type": "payment-provider",
"address": "https://opencollective.com/y-collective",
"description": "For funding the Y-CRDT - the Rust implementation of Yjs and other listed projects."
}
],
"plans": [
{
"guid": "supporter",
"status": "active",
"name": "Supporter",
"description": "",
"amount": 0,
"currency": "USD",
"frequency": "monthly",
"channels": [
"github-sponsors",
"y-collective"
]
},
{
"guid": "ystream-funding",
"status": "active",
"name": "YStream Funding",
"description": "Fund the next generation of local-first providers.",
"amount": 30000,
"currency": "USD",
"frequency": "one-time",
"channels": [
"github-sponsors"
]
},
{
"guid": "bronze-sponsor",
"status": "active",
"name": "Bronze Sponsor",
"description": "This is the recommended plan for companies that use Yjs.",
"amount": 500,
"currency": "USD",
"frequency": "monthly",
"channels": [
"github-sponsors"
]
},
{
"guid": "silver-sponsor",
"status": "active",
"name": "Silver Sponsor",
"description": "This is the recommended plan for large/successfull companies that use Yjs.",
"amount": 1000,
"currency": "USD",
"frequency": "monthly",
"channels": [
"github-sponsors"
]
},
{
"guid": "gold-sponsor",
"status": "active",
"name": "Gold Sponsor",
"description": "This is the recommended plan for successful companies that build their entire product around Yjs-related technologies.",
"amount": 3000,
"currency": "USD",
"frequency": "monthly",
"channels": [
"github-sponsors"
]
}
],
"history": null
}
}

12
package-lock.json generated
View File

@@ -1,15 +1,15 @@
{
"name": "yjs",
"version": "13.6.20",
"version": "13.6.22",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "yjs",
"version": "13.6.20",
"version": "13.6.22",
"license": "MIT",
"dependencies": {
"lib0": "^0.2.98"
"lib0": "^0.2.99"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.1",
@@ -2785,9 +2785,9 @@
}
},
"node_modules/lib0": {
"version": "0.2.98",
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.98.tgz",
"integrity": "sha512-XteTiNO0qEXqqweWx+b21p/fBnNHUA1NwAtJNJek1oPrewEZs2uiT4gWivHKr9GqCjDPAhchz0UQO8NwU3bBNA==",
"version": "0.2.99",
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.99.tgz",
"integrity": "sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w==",
"dependencies": {
"isomorphic.js": "^0.2.4"
},

View File

@@ -1,6 +1,6 @@
{
"name": "yjs",
"version": "13.6.20",
"version": "13.6.22",
"description": "Shared Editing Library",
"main": "./dist/yjs.cjs",
"module": "./dist/yjs.mjs",
@@ -76,7 +76,7 @@
},
"homepage": "https://docs.yjs.dev",
"dependencies": {
"lib0": "^0.2.98"
"lib0": "^0.2.99"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.1",

View File

@@ -26,7 +26,7 @@ export class AbstractStruct {
* This method is already assuming that `this.id.clock + this.length === this.id.clock`.
* Also this method does *not* remove right from StructStore!
* @param {AbstractStruct} right
* @return {boolean} wether this merged with right
* @return {boolean} whether this merged with right
*/
mergeWith (right) {
return false

View File

@@ -155,11 +155,11 @@ export const findMarker = (yarray, index) => {
// }
// }
// if (marker) {
// if (window.lengthes == null) {
// window.lengthes = []
// window.getLengthes = () => window.lengthes.sort((a, b) => a - b)
// if (window.lengths == null) {
// window.lengths = []
// window.getLengths = () => window.lengths.sort((a, b) => a - b)
// }
// window.lengthes.push(marker.index - pindex)
// window.lengths.push(marker.index - pindex)
// console.log('distance', marker.index - pindex, 'len', p && p.parent.length)
// }
if (marker !== null && math.abs(marker.index - pindex) < /** @type {YText|YArray<any>} */ (p.parent).length / maxSearchMarker) {
@@ -751,7 +751,7 @@ export const typeListInsertGenerics = (transaction, parent, index, content) => {
/**
* Pushing content is special as we generally want to push after the last item. So we don't have to update
* the serach marker.
* the search marker.
*
* @param {Transaction} transaction
* @param {AbstractType<any>} parent

View File

@@ -478,7 +478,7 @@ export const cleanupYTextFormatting = type => {
}
/**
* This will be called by the transction once the event handlers are called to potentially cleanup
* This will be called by the transaction once the event handlers are called to potentially cleanup
* formatting attributes.
*
* @param {Transaction} transaction
@@ -568,7 +568,7 @@ const deleteText = (transaction, currPos, length) => {
/**
* The Quill Delta format represents changes on a text document with
* formatting information. For mor information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
* formatting information. For more information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
*
* @example
* {
@@ -961,7 +961,7 @@ export class YText extends AbstractType {
/**
* Apply a {@link Delta} on this shared YText type.
*
* @param {any} delta The changes to apply on this element.
* @param {Array<any>} delta The changes to apply on this element.
* @param {object} opts
* @param {boolean} [opts.sanitize] Sanitize input delta. Removes ending newlines if set to true.
*

View File

@@ -12,7 +12,7 @@ export class YXmlEvent extends YEvent {
* @param {YXmlElement|YXmlText|YXmlFragment} target The target on which the event is created.
* @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
* child list changed.
* @param {Transaction} transaction The transaction instance with wich the
* @param {Transaction} transaction The transaction instance with which the
* change was created.
*/
constructor (target, subs, transaction) {

View File

@@ -106,7 +106,7 @@ export class Doc extends ObservableV2 {
this.isSynced = false
this.isDestroyed = false
/**
* Promise that resolves once the document has been loaded from a presistence provider.
* Promise that resolves once the document has been loaded from a persistence provider.
*/
this.whenLoaded = promise.create(resolve => {
this.on('load', () => {

View File

@@ -62,7 +62,7 @@ export class PermanentUserData {
initUser(storeType.get(userDescription), userDescription)
)
})
// add intial data
// add initial data
storeType.forEach(initUser)
}

View File

@@ -9,7 +9,7 @@ import {
ContentType,
followRedone,
getItem,
ID, Doc, AbstractType // eslint-disable-line
StructStore, ID, Doc, AbstractType, // eslint-disable-line
} from '../internals.js'
import * as encoding from 'lib0/encoding'
@@ -66,7 +66,7 @@ export class RelativePosition {
* after the meant position.
* I.e. position 1 in 'ab' is associated to character 'b'.
*
* If assoc < 0, then the relative position is associated to the caharacter
* If assoc < 0, then the relative position is associated to the character
* before the meant position.
*
* @type {number}
@@ -256,6 +256,18 @@ export const readRelativePosition = decoder => {
*/
export const decodeRelativePosition = uint8Array => readRelativePosition(decoding.createDecoder(uint8Array))
/**
* @param {StructStore} store
* @param {ID} id
*/
const getItemWithOffset = (store, id) => {
const item = getItem(store, id)
const diff = id.clock - item.id.clock
return {
item, diff
}
}
/**
* Transform a relative position to an absolute position.
*
@@ -286,7 +298,7 @@ export const createAbsolutePositionFromRelativePosition = (rpos, doc, followUndo
if (getState(store, rightID.client) <= rightID.clock) {
return null
}
const res = followUndoneDeletions ? followRedone(store, rightID) : { item: getItem(store, rightID), diff: 0 }
const res = followUndoneDeletions ? followRedone(store, rightID) : getItemWithOffset(store, rightID)
const right = res.item
if (!(right instanceof Item)) {
return null

View File

@@ -66,13 +66,13 @@ export const getState = (store, client) => {
* @private
* @function
*/
export const integretyCheck = store => {
export const integrityCheck = store => {
store.clients.forEach(structs => {
for (let i = 1; i < structs.length; i++) {
const l = structs[i - 1]
const r = structs[i]
if (l.id.clock + l.length !== r.id.clock) {
throw new Error('StructStore failed integrety check')
throw new Error('StructStore failed integrity check')
}
}
})

View File

@@ -167,7 +167,7 @@ export class UpdateEncoderV2 extends DSEncoderV2 {
*/
this.keyMap = new Map()
/**
* Refers to the next uniqe key-identifier to me used.
* Refers to the next unique key-identifier to me used.
* See writeKey method for more information.
*
* @type {number}

View File

@@ -211,7 +211,7 @@ export const readClientsStructRefs = (decoder, doc) => {
* then we start emptying the stack.
*
* It is not possible to have circles: i.e. struct1 (from client1) depends on struct2 (from client2)
* depends on struct3 (from client1). Therefore the max stack size is eqaul to `structReaders.length`.
* depends on struct3 (from client1). Therefore the max stack size is equal to `structReaders.length`.
*
* This method is implemented in a way so that we can resume computation if this update
* causally depends on another update.
@@ -279,14 +279,14 @@ const integrateStructs = (transaction, store, clientsStructRefs) => {
const addStackToRestSS = () => {
for (const item of stack) {
const client = item.id.client
const unapplicableItems = clientsStructRefs.get(client)
if (unapplicableItems) {
const inapplicableItems = clientsStructRefs.get(client)
if (inapplicableItems) {
// decrement because we weren't able to apply previous operation
unapplicableItems.i--
restStructs.clients.set(client, unapplicableItems.refs.slice(unapplicableItems.i))
inapplicableItems.i--
restStructs.clients.set(client, inapplicableItems.refs.slice(inapplicableItems.i))
clientsStructRefs.delete(client)
unapplicableItems.i = 0
unapplicableItems.refs = []
inapplicableItems.i = 0
inapplicableItems.refs = []
} else {
// item was the last item on clientsStructRefs and the field was already cleared. Add item to restStructs and continue
restStructs.clients.set(client, [item])

View File

@@ -1,5 +1,5 @@
/**
* Testing if encoding/decoding compatibility and integration compatiblity is given.
* Testing if encoding/decoding compatibility and integration compatibility is given.
* We expect that the document always looks the same, even if we upgrade the integration algorithm, or add additional encoding approaches.
*
* The v1 documents were generated with Yjs v13.2.0 based on the randomisized tests.

View File

@@ -15,15 +15,28 @@ import * as relativePositions from './relativePositions.tests.js'
import { runTests } from 'lib0/testing'
import { isBrowser, isNode } from 'lib0/environment'
import * as log from 'lib0/logging'
import { environment } from 'lib0'
if (isBrowser) {
log.createVConsole(document.body)
}
runTests({
/**
* @type {any}
*/
const tests = {
doc, map, array, text, xml, encoding, undoredo, compatibility, snapshot, updates, relativePositions
}).then(success => {
}
const run = async () => {
if (environment.isNode) {
// tests.nodejs = await import('./node.tests.js')
}
const success = await runTests(tests)
/* istanbul ignore next */
if (isNode) {
process.exit(success ? 0 : 1)
}
})
}
run()

View File

@@ -85,6 +85,26 @@ export const testRelativePositionCase6 = tc => {
checkRelativePositions(ytext)
}
/**
* Testing https://github.com/yjs/yjs/issues/657
*
* @param {t.TestCase} tc
*/
export const testRelativePositionCase7 = tc => {
const docA = new Y.Doc()
const textA = docA.getText('text')
textA.insert(0, 'abcde')
// Create a relative position at index 2 in 'textA'
const relativePosition = Y.createRelativePositionFromTypeIndex(textA, 2)
// Verify that the absolutes positions on 'docA' are the same
const absolutePositionWithFollow =
Y.createAbsolutePositionFromRelativePosition(relativePosition, docA, true)
const absolutePositionWithoutFollow =
Y.createAbsolutePositionFromRelativePosition(relativePosition, docA, false)
t.assert(absolutePositionWithFollow?.index === 2)
t.assert(absolutePositionWithoutFollow?.index === 2)
}
/**
* @param {t.TestCase} tc
*/

View File

@@ -58,7 +58,7 @@ export const testEmptyRestoreSnapshot = _tc => {
t.compare(docRestored.getArray().toArray(), [])
t.compare(doc.getArray().toArray(), ['world'])
// now this snapshot reflects the latest state. It shoult still work.
// now this snapshot reflects the latest state. It should still work.
const snap2 = Y.snapshot(doc)
const docRestored2 = Y.createDocFromSnapshot(doc, snap2)
t.compare(docRestored2.getArray().toArray(), ['world'])

View File

@@ -369,11 +369,11 @@ export const testObserversUsingObservedeep = tc => {
/**
* @type {Array<Array<string|number>>}
*/
const pathes = []
const paths = []
let calls = 0
map0.observeDeep(events => {
events.forEach(event => {
pathes.push(event.path)
paths.push(event.path)
})
calls++
})
@@ -381,7 +381,7 @@ export const testObserversUsingObservedeep = tc => {
map0.get('map').set('array', new Y.Array())
map0.get('map').get('array').insert(0, ['content'])
t.assert(calls === 3)
t.compare(pathes, [[], ['map'], ['map', 'array']])
t.compare(paths, [[], ['map'], ['map', 'array']])
compare(users)
}
@@ -393,14 +393,14 @@ export const testPathsOfSiblingEvents = tc => {
/**
* @type {Array<Array<string|number>>}
*/
const pathes = []
const paths = []
let calls = 0
const doc = users[0]
map0.set('map', new Y.Map())
map0.get('map').set('text1', new Y.Text('initial'))
map0.observeDeep(events => {
events.forEach(event => {
pathes.push(event.path)
paths.push(event.path)
})
calls++
})
@@ -409,7 +409,7 @@ export const testPathsOfSiblingEvents = tc => {
map0.get('map').set('text2', new Y.Text('new'))
})
t.assert(calls === 1)
t.compare(pathes, [['map'], ['map', 'text1']])
t.compare(paths, [['map'], ['map', 'text1']])
compare(users)
}

View File

@@ -376,7 +376,7 @@ export const testDeltaBug = _tc => {
},
{
insert: '\n',
// This attibutes has only list and no table-cell-line
// This attributes has only list and no table-cell-line
attributes: {
list: {
rowspan: '1',