Compare commits

..

No commits in common. "main" and "v13.6.15" have entirely different histories.

32 changed files with 283 additions and 1025 deletions

View File

@ -26,7 +26,7 @@ article](https://blog.kevinjahns.de/are-crdts-suitable-for-shared-editing/).
Each client is assigned a unique *clientID* property on first insert. This is a
random 53-bit integer (53 bits because that fits in the javascript safe integer
range \[JavaScript uses IEEE 754 floats\]).
range).
## List items
@ -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 preceding and
When an item is created, it stores a reference to the IDs of the preceeding 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

127
README.md
View File

@ -3,7 +3,7 @@
> A CRDT framework with a powerful abstraction of shared data
Yjs is a [CRDT implementation](#yjs-crdt-algorithm) that exposes its internal
Yjs is a [CRDT implementation](#Yjs-CRDT-Algorithm) that exposes its internal
data structure as *shared types*. Shared types are common data types like `Map`
or `Array` with superpowers: changes are automatically distributed to other
peers and merged without merge conflicts.
@ -50,15 +50,13 @@ Showcase](https://yjs-diagram.synergy.codes/).
* [AFFiNE](https://affine.pro/) A local-first, privacy-first, open source
knowledge base. :star2:
* [Huly](https://huly.io/) - Open Source All-in-One Project Management Platform :star2:
* [Huly](https://huly.io/) - Open Source All-in-One Project Management Platform
:star2:
* [Cargo](https://cargo.site/) Site builder for designers and artists :star2:
* [Gitbook](https://gitbook.com) Knowledge management for technical teams :star2:
* [Evernote](https://evernote.com) Note-taking app :star2:
* [Lessonspace](https://thelessonspace.com) Enterprise platform for virtual
classrooms and online training :star2:
* [Ellipsus](ellipsus.com) - Collaborative writing app for storytelling etc.
Supports versioning, change attribution, and "blame". A solution for the whole
publishing process (also selling) :star:
* [Dynaboard](https://dynaboard.com/) Build web apps collaboratively. :star:
* [Relm](https://www.relm.us/) A collaborative gameworld for teamwork and
community. :star:
@ -99,6 +97,7 @@ Showcase](https://yjs-diagram.synergy.codes/).
* [AWS SageMaker](https://aws.amazon.com/sagemaker/) Tools for building Machine
Learning Models
* [linear](https://linear.app) Streamline issues, projects, and product roadmaps.
* [btw](https://www.btw.so) - Personal website builder
* [AWS SageMaker](https://aws.amazon.com/sagemaker/) - Machine Learning Service
* [Arkiter](https://www.arkiter.com/) - Live interview software
* [Appflowy](https://www.appflowy.io/) - They use Yrs
@ -109,37 +108,23 @@ 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
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.
* [NextCloud](https://nextcloud.com/) - Content Collaboration Platform
* [keystatic](https://github.com/Thinkmill/keystatic) - git-based CMS
* [QDAcity](https://qdacity.com) - Collaborative qualitative data analysis platform
* [Kanbert](https://kanbert.com) - Project management software
* [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
* [Typst](https://typst.app/) - Compose, edit, and automate technical documents
applicaiton
## Table of Contents
* [Overview](#overview)
* [Bindings](#bindings)
* [Providers](#providers)
* [Tooling](#tooling)
* [Ports](#ports)
* [Getting Started](#getting-started)
* [API](#api)
* [Shared Types](#shared-types)
* [Y.Doc](#ydoc)
* [Document Updates](#document-updates)
* [Relative Positions](#relative-positions)
* [Y.UndoManager](#yundomanager)
* [Yjs CRDT Algorithm](#yjs-crdt-algorithm)
* [License and Author](#license-and-author)
* [Overview](#Overview)
* [Bindings](#Bindings)
* [Providers](#Providers)
* [Ports](#Ports)
* [Getting Started](#Getting-Started)
* [API](#API)
* [Shared Types](#Shared-Types)
* [Y.Doc](#YDoc)
* [Document Updates](#Document-Updates)
* [Relative Positions](#Relative-Positions)
* [Y.UndoManager](#YUndoManager)
* [Yjs CRDT Algorithm](#Yjs-CRDT-Algorithm)
* [License and Author](#License-and-Author)
## Overview
@ -157,14 +142,10 @@ are implemented in separate modules.
| [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) |
| [BlockSuite](https://github.com/toeverything/blocksuite) | ✔ | (native) | [demo](https://blocksuite-toeverything.vercel.app/?init) |
| [Lexical](https://lexical.dev/) | ✔ | (native) | [demo](https://lexical.dev/docs/collaboration/react#see-it-in-action) |
| [valtio](https://github.com/pmndrs/valtio) | | [valtio-yjs](https://github.com/dai-shi/valtio-yjs) | [demo](https://codesandbox.io/s/valtio-yjs-demo-ox3iy) |
| [immer](https://github.com/immerjs/immer) | | [immer-yjs](https://github.com/sep2/immer-yjs) | [demo](https://codesandbox.io/s/immer-yjs-demo-6e0znb) |
| 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) |
| [Rows n'Columns](https://www.rowsncolumns.app/) | ✔ | [@rowsncolumns/y-spreadsheet](https://docs.rowsncolumns.app/collaboration/yjs-collaboration) | |
### Providers
@ -190,12 +171,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. Publicly available signaling servers
signaling data over signaling servers. Publically 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
@ -203,23 +184,15 @@ 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.
@ -264,11 +237,6 @@ The reactive data store for local-first apps. They support multiple CRDTs and
<dd>
Provider for sharing data in <a href="https://webxdc.org">webxdc chat apps</a>.
</dd>
<dt><a href="https://www.secsync.com/">secsync</a></dt>
<dd>
An architecture to relay end-to-end encrypted CRDTs over a central service.
</dd>
</dl>
#### Persistence Providers
@ -284,35 +252,19 @@ 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>
A database and connection provider for Yjs based on Firestore.
</dd>
<dt><a href="https://github.com/malte-j/y-op-sqlite">y-op-sqlite</a></dt>
<dd>
Persist YJS updates in your React Native app using
<a href="https://github.com/OP-Engineering/op-sqlite">op-sqlite</a>
, the fastest SQLite library for React Native.
</dd>
<dt><a href="https://github.com/MaxNoetzold/y-postgresql">y-postgresql</a></dt>
<dd>
Provides persistent storage for a web server using PostgreSQL and
is easily compatible with y-websocket.
</dd>
<dt><a href="https://github.com/kapv89/k_yrs_go">k_yrs_go</a></dt>
<dd>
Golang database server for YJS CRDT using Postgres + Redis
</dd>
</dl>
### Tooling
* [y-sweet debugger](https://docs.jamsocket.com/y-sweet/advanced/debugger)
* [liveblocks devtools](https://liveblocks.io/devtools)
* [Yjs inspector](https://inspector.yjs.dev)
### Ports
# Ports
There are several Yjs-compatible ports to other programming languages.
@ -326,7 +278,6 @@ 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
@ -340,7 +291,7 @@ npm i yjs y-websocket
Start the y-websocket server:
```sh
PORT=1234 node ./node_modules/y-websocket/bin/server.cjs
PORT=1234 node ./node_modules/y-websocket/bin/server.js
```
### Example: Observe types
@ -441,11 +392,6 @@ necessary.
</p>
<pre>const yarray = new Y.Array()</pre>
<dl>
<b><code>
Y.Array.from(Array&lt;object|boolean|Array|string|number|null|Uint8Array|Y.Type&gt;):
Y.Array
</code></b>
<dd>An alternative factory function to create a Y.Array based on existing content.</dd>
<b><code>parent:Y.AbstractType|null</code></b>
<dd></dd>
<b><code>insert(index:number, content:Array&lt;object|boolean|Array|string|number|null|Uint8Array|Y.Type&gt;)</code></b>
@ -475,11 +421,6 @@ forEach(function(value:object|boolean|Array|string|number|null|Uint8Array|Y.Type
<dd></dd>
<b><code>map(function(T, number, YArray):M):Array&lt;M&gt;</code></b>
<dd></dd>
<b><code>clone(): Y.Array</code></b>
<dd>
Clone all values into a fresh Y.Array instance. The returned type can be
included into the Yjs document.
</dd>
<b><code>toArray():Array&lt;object|boolean|Array|string|number|null|Uint8Array|Y.Type&gt;</code></b>
<dd>Copies the content of this YArray to a new Array.</dd>
<b><code>toJSON():Array&lt;Object|boolean|Array|string|number|null&gt;</code></b>
@ -536,6 +477,8 @@ or any of its children.
<dd></dd>
<b><code>has(key:string):boolean</code></b>
<dd></dd>
<b><code>get(index:number)</code></b>
<dd></dd>
<b><code>clear()</code></b>
<dd>Removes all elements from this YMap.</dd>
<b><code>clone():Y.Map</code></b>
@ -889,7 +832,7 @@ doc1.getArray('myarray').insert(0, ['Hello doc2, you got this?'])
doc2.getArray('myarray').get(0) // => 'Hello doc2, you got this?'
```
Yjs internally maintains a [state vector](#state-vector) that denotes the next
Yjs internally maintains a [state vector](#State-Vector) that denotes the next
expected clock from each client. In a different interpretation it holds the
number of structs created by each client. When two clients sync, you can either
exchange the complete document structure or only the differences by sending the
@ -1102,7 +1045,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 RelativePosition object.</dd>
<dd>Decode a binary-encoded relative position to a RelativePositon object.</dd>
</dl>
### Y.UndoManager
@ -1282,11 +1225,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 beneficial for shared text editing (like
have the characteristics that are benificial 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 preceding structs into a single
order of the structs. But we can 1. merge preceeding 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

View File

@ -1,142 +0,0 @@
{
"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": "Titanic",
"name": "Y/Titanic",
"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/titanic",
"wellKnown": "https://github.com/yjs/titanic/blob/main/.well-known/funding-manifest-urls"
},
"repositoryUrl": {
"url": "https://github.com/yjs/titanic",
"wellKnown": "https://github.com/yjs/titanic/blob/main/.well-known/funding-manifest-urls"
},
"licenses": [
"spdx:MIT"
],
"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": "titanic-funding",
"status": "active",
"name": "Titanic 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
}
}

655
package-lock.json generated
View File

@ -1,15 +1,15 @@
{
"name": "yjs",
"version": "13.6.24",
"version": "13.6.15",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "yjs",
"version": "13.6.24",
"version": "13.6.15",
"license": "MIT",
"dependencies": {
"lib0": "^0.2.99"
"lib0": "^0.2.86"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.1",
@ -18,7 +18,7 @@
"concurrently": "^3.6.1",
"http-server": "^0.12.3",
"jsdoc": "^3.6.7",
"markdownlint-cli": "^0.41.0",
"markdownlint-cli": "^0.23.2",
"rollup": "^3.20.0",
"standard": "^16.0.4",
"tui-jsdoc-template": "^1.2.2",
@ -166,89 +166,12 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@rollup/plugin-commonjs": {
"version": "24.1.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.1.0.tgz",
@ -850,12 +773,13 @@
}
},
"node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz",
"integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==",
"dev": true,
"engines": {
"node": ">=4.0.0"
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
"node_modules/deep-is": {
@ -958,12 +882,6 @@
"domelementtype": "1"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true
},
"node_modules/ecstatic": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz",
@ -1873,22 +1791,6 @@
"is-callable": "^1.1.3"
}
},
"node_modules/foreground-child": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
"integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -1971,15 +1873,12 @@
}
},
"node_modules/get-stdin": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
"integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
"integrity": "sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
"node": ">=0.12.0"
}
},
"node_modules/get-symbol-description": {
@ -2078,6 +1977,12 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true
},
"node_modules/graceful-readlink": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
"integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==",
"dev": true
},
"node_modules/has": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
@ -2243,9 +2148,9 @@
}
},
"node_modules/ignore": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
"version": "5.1.9",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz",
"integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==",
"dev": true,
"engines": {
"node": ">= 4"
@ -2293,13 +2198,10 @@
"dev": true
},
"node_modules/ini": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz",
"integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==",
"dev": true,
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"node_modules/internal-slot": {
"version": "1.0.7",
@ -2597,21 +2499,6 @@
"url": "https://github.com/sponsors/dmonad"
}
},
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"dev": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -2724,20 +2611,11 @@
}
},
"node_modules/jsonc-parser": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
"integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz",
"integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==",
"dev": true
},
"node_modules/jsonpointer": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
"integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@ -2785,14 +2663,13 @@
}
},
"node_modules/lib0": {
"version": "0.2.99",
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.99.tgz",
"integrity": "sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w==",
"version": "0.2.88",
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.88.tgz",
"integrity": "sha512-KyroiEvCeZcZEMx5Ys+b4u4eEBbA1ch7XUaBhYpwa/nPMrzTjUhI4RfcytmQfYoTBPcdyx+FX6WFNIoNuJzJfQ==",
"dependencies": {
"isomorphic.js": "^0.2.4"
},
"bin": {
"0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js",
"0gentesthtml": "bin/gentesthtml.js",
"0serve": "bin/0serve.js"
},
@ -2865,6 +2742,12 @@
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
"dev": true
},
"node_modules/lodash.differencewith": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz",
"integrity": "sha512-/8JFjydAS+4bQuo3CpLMBv7WxGFyk7/etOAsrQUCu0a9QVDemxv0YQ0rFyeZvqlUD314SERfNlgnlqqHmaQ0Cg==",
"dev": true
},
"node_modules/lodash.filter": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
@ -2988,164 +2871,145 @@
}
},
"node_modules/markdownlint": {
"version": "0.34.0",
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.34.0.tgz",
"integrity": "sha512-qwGyuyKwjkEMOJ10XN6OTKNOVYvOIi35RNvDLNxTof5s8UmyGHlCdpngRHoRGNvQVGuxO3BJ7uNSgdeX166WXw==",
"version": "0.20.4",
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.20.4.tgz",
"integrity": "sha512-jpfaPgjT0OpeBbemjYNZbzGG3hCLcAIvrm/pEY3+q/szDScG6ZonDacqySVRJAv9glbo8y4wBPJ0wgW17+9GGA==",
"dev": true,
"dependencies": {
"markdown-it": "14.1.0",
"markdownlint-micromark": "0.1.9"
"markdown-it": "10.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/DavidAnson"
"node": ">=10"
}
},
"node_modules/markdownlint-cli": {
"version": "0.41.0",
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.41.0.tgz",
"integrity": "sha512-kp29tKrMKdn+xonfefjp3a/MsNzAd9c5ke0ydMEI9PR98bOjzglYN4nfMSaIs69msUf1DNkgevAIAPtK2SeX0Q==",
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.23.2.tgz",
"integrity": "sha512-OSl5OZ8xzGN6z355cqRkiq67zPi3reJimklaF72p0554q85Dng5ToOjjSB9tDKZebSt85jX8cp+ruoQlPqOsPA==",
"dev": true,
"dependencies": {
"commander": "~12.1.0",
"get-stdin": "~9.0.0",
"glob": "~10.4.1",
"ignore": "~5.3.1",
"js-yaml": "^4.1.0",
"jsonc-parser": "~3.2.1",
"jsonpointer": "5.0.1",
"markdownlint": "~0.34.0",
"minimatch": "~9.0.4",
"run-con": "~1.3.2",
"smol-toml": "~1.2.0"
"commander": "~2.9.0",
"deep-extend": "~0.5.1",
"get-stdin": "~5.0.1",
"glob": "~7.1.2",
"ignore": "~5.1.4",
"js-yaml": "~3.13.1",
"jsonc-parser": "~2.2.0",
"lodash.differencewith": "~4.5.0",
"lodash.flatten": "~4.4.0",
"markdownlint": "~0.20.4",
"markdownlint-rule-helpers": "~0.11.0",
"minimatch": "~3.0.4",
"minimist": "~1.2.5",
"rc": "~1.2.7"
},
"bin": {
"markdownlint": "markdownlint.js"
},
"engines": {
"node": ">=18"
"node": ">=10"
}
},
"node_modules/markdownlint-cli/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/markdownlint-cli/node_modules/commander": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
"integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==",
"dev": true,
"dependencies": {
"graceful-readlink": ">= 1.0.0"
},
"engines": {
"node": ">=18"
"node": ">= 0.6.x"
}
},
"node_modules/markdownlint-cli/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/markdownlint-cli/node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/markdownlint-cli/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz",
"integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
"brace-expansion": "^1.1.7"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
"node": "*"
}
},
"node_modules/markdownlint-micromark": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.9.tgz",
"integrity": "sha512-5hVs/DzAFa8XqYosbEAEg6ok6MF2smDj89ztn9pKkCtdKHVdPQuGMH7frFfYL9mLkvfFe4pTyAMffLbjf3/EyA==",
"dev": true,
"engines": {
"node": ">=18"
"node_modules/markdownlint-rule-helpers": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.11.0.tgz",
"integrity": "sha512-PhGii9dOiDJDXxiRMpK8N0FM9powprvRPsXALgkjlSPTwLh6ymH+iF3iUe3nq8KGu26tclFBlLL5xAGy/zb7FA==",
"dev": true
},
"funding": {
"url": "https://github.com/sponsors/DavidAnson"
"node_modules/markdownlint/node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"dependencies": {
"sprintf-js": "~1.0.2"
}
},
"node_modules/markdownlint/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
"dev": true
},
"node_modules/markdownlint/node_modules/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
"dev": true,
"dependencies": {
"uc.micro": "^2.0.0"
"uc.micro": "^1.0.1"
}
},
"node_modules/markdownlint/node_modules/markdown-it": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.4.0",
"linkify-it": "^5.0.0",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
"argparse": "^1.0.7",
"entities": "~2.0.0",
"linkify-it": "^2.0.0",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"bin": {
"markdown-it": "bin/markdown-it.mjs"
"markdown-it": "bin/markdown-it.js"
}
},
"node_modules/markdownlint/node_modules/mdurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
"dev": true
},
"node_modules/markdownlint/node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"dev": true
},
"node_modules/marked": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
@ -3197,15 +3061,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@ -3425,12 +3280,6 @@
"node": ">=4"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
"integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
"dev": true
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -3489,28 +3338,6 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dev": true,
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true
},
"node_modules/path-type": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
@ -3728,15 +3555,6 @@
"node": ">=6"
}
},
"node_modules/punycode.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/qs": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
@ -3752,6 +3570,39 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"dev": true,
"dependencies": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
},
"bin": {
"rc": "cli.js"
}
},
"node_modules/rc/node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"dev": true,
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/rc/node_modules/strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@ -3951,21 +3802,6 @@
"fsevents": "~2.3.2"
}
},
"node_modules/run-con": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/run-con/-/run-con-1.3.2.tgz",
"integrity": "sha512-CcfE+mYiTcKEzg0IqS08+efdnH0oJ3zV0wSUFBNrMHMuxCtXvBCLzCJHatwuXDcu/RlhjTziTo/a1ruQik6/Yg==",
"dev": true,
"dependencies": {
"deep-extend": "^0.6.0",
"ini": "~4.1.0",
"minimist": "^1.2.8",
"strip-json-comments": "~3.1.1"
},
"bin": {
"run-con": "cli.js"
}
},
"node_modules/rx": {
"version": "2.3.24",
"resolved": "https://registry.npmjs.org/rx/-/rx-2.3.24.tgz",
@ -4112,18 +3948,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/slice-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
@ -4174,15 +3998,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/smol-toml": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.2.2.tgz",
"integrity": "sha512-fVEjX2ybKdJKzFL46VshQbj9PuA4IUKivalgp48/3zwS9vXzyykzQ6AX92UxHSvWJagziMRLeHMgEzoGO7A8hQ==",
"dev": true,
"engines": {
"node": ">= 18"
}
},
"node_modules/spawn-command": {
"version": "0.0.2-1",
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
@ -4327,21 +4142,6 @@
"node": ">=8"
}
},
"node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/string.prototype.matchall": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
@ -4419,19 +4219,6 @@
"node": ">=8"
}
},
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
@ -4788,136 +4575,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/wrap-ansi-cjs/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/wrap-ansi/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true
},
"node_modules/wrap-ansi/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/wrap-ansi/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",

View File

@ -1,6 +1,6 @@
{
"name": "yjs",
"version": "13.6.24",
"version": "13.6.15",
"description": "Shared Editing Library",
"main": "./dist/yjs.cjs",
"module": "./dist/yjs.mjs",
@ -13,7 +13,7 @@
},
"scripts": {
"clean": "rm -rf dist docs",
"test": "npm run dist && NODE_ENV=development node ./dist/tests.cjs --repetition-time 50",
"test": "npm run dist && node ./dist/tests.cjs --repetition-time 50",
"test-extensive": "npm run lint && npm run dist && node ./dist/tests.cjs --production --repetition-time 10000",
"dist": "npm run clean && rollup -c && tsc",
"watch": "rollup -wc",
@ -76,7 +76,7 @@
},
"homepage": "https://docs.yjs.dev",
"dependencies": {
"lib0": "^0.2.99"
"lib0": "^0.2.86"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^24.0.1",
@ -85,7 +85,7 @@
"concurrently": "^3.6.1",
"http-server": "^0.12.3",
"jsdoc": "^3.6.7",
"markdownlint-cli": "^0.41.0",
"markdownlint-cli": "^0.23.2",
"rollup": "^3.20.0",
"standard": "^16.0.4",
"tui-jsdoc-template": "^1.2.2",

View File

@ -50,8 +50,6 @@ export {
findRootTypeKey,
findIndexSS,
getItem,
getItemCleanStart,
getItemCleanEnd,
typeListToArraySnapshot,
typeMapGetSnapshot,
typeMapGetAllSnapshot,
@ -102,7 +100,6 @@ export {
UpdateDecoderV1,
UpdateDecoderV2,
equalDeleteSets,
mergeDeleteSets,
snapshotContainsUpdate
} from './internals.js'

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} whether this merged with right
* @return {boolean} wether this merged with right
*/
mergeWith (right) {
return false

View File

@ -2,11 +2,6 @@ import {
UpdateEncoderV1, UpdateEncoderV2, UpdateDecoderV1, UpdateDecoderV2, Transaction, Item, StructStore // eslint-disable-line
} from '../internals.js'
import * as env from 'lib0/environment'
import * as object from 'lib0/object'
const isDevMode = env.getVariable('node_env') === 'development'
export class ContentAny {
/**
* @param {Array<any>} arr
@ -16,7 +11,6 @@ export class ContentAny {
* @type {Array<any>}
*/
this.arr = arr
isDevMode && object.deepFreeze(arr)
}
/**

View File

@ -393,7 +393,8 @@ export class Item extends AbstractStruct {
if (this.left && this.left.constructor === Item) {
this.parent = this.left.parent
this.parentSub = this.left.parentSub
} else if (this.right && this.right.constructor === Item) {
}
if (this.right && this.right.constructor === Item) {
this.parent = this.right.parent
this.parentSub = this.right.parentSub
}

View File

@ -17,12 +17,6 @@ import * as map from 'lib0/map'
import * as iterator from 'lib0/iterator'
import * as error from 'lib0/error'
import * as math from 'lib0/math'
import * as log from 'lib0/logging'
/**
* https://docs.yjs.dev/getting-started/working-with-shared-types#caveats
*/
export const warnPrematureAccess = () => { log.warn('Invalid access: Add Yjs type to a document before reading data.') }
const maxSearchMarker = 80
@ -155,11 +149,11 @@ export const findMarker = (yarray, index) => {
// }
// }
// if (marker) {
// if (window.lengths == null) {
// window.lengths = []
// window.getLengths = () => window.lengths.sort((a, b) => a - b)
// if (window.lengthes == null) {
// window.lengthes = []
// window.getLengthes = () => window.lengthes.sort((a, b) => a - b)
// }
// window.lengths.push(marker.index - pindex)
// window.lengthes.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) {
@ -221,7 +215,6 @@ export const updateMarkerChanges = (searchMarker, index, len) => {
* @return {Array<Item>}
*/
export const getTypeChildren = t => {
t.doc ?? warnPrematureAccess()
let s = t._start
const arr = []
while (s) {
@ -415,7 +408,6 @@ export class AbstractType {
* @function
*/
export const typeListSlice = (type, start, end) => {
type.doc ?? warnPrematureAccess()
if (start < 0) {
start = type._length + start
}
@ -451,7 +443,6 @@ export const typeListSlice = (type, start, end) => {
* @function
*/
export const typeListToArray = type => {
type.doc ?? warnPrematureAccess()
const cs = []
let n = type._start
while (n !== null) {
@ -501,7 +492,6 @@ export const typeListToArraySnapshot = (type, snapshot) => {
export const typeListForEach = (type, f) => {
let index = 0
let n = type._start
type.doc ?? warnPrematureAccess()
while (n !== null) {
if (n.countable && !n.deleted) {
const c = n.content.getContent()
@ -616,7 +606,6 @@ export const typeListForEachSnapshot = (type, f, snapshot) => {
* @function
*/
export const typeListGet = (type, index) => {
type.doc ?? warnPrematureAccess()
const marker = findMarker(type, index)
let n = type._start
if (marker !== null) {
@ -751,7 +740,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 search marker.
* the serach marker.
*
* @param {Transaction} transaction
* @param {AbstractType<any>} parent
@ -885,7 +874,6 @@ export const typeMapSet = (transaction, parent, key, value) => {
* @function
*/
export const typeMapGet = (parent, key) => {
parent.doc ?? warnPrematureAccess()
const val = parent._map.get(key)
return val !== undefined && !val.deleted ? val.content.getContent()[val.length - 1] : undefined
}
@ -902,7 +890,6 @@ export const typeMapGetAll = (parent) => {
* @type {Object<string,any>}
*/
const res = {}
parent.doc ?? warnPrematureAccess()
parent._map.forEach((value, key) => {
if (!value.deleted) {
res[key] = value.content.getContent()[value.length - 1]
@ -920,7 +907,6 @@ export const typeMapGetAll = (parent) => {
* @function
*/
export const typeMapHas = (parent, key) => {
parent.doc ?? warnPrematureAccess()
const val = parent._map.get(key)
return val !== undefined && !val.deleted
}
@ -971,13 +957,10 @@ export const typeMapGetAllSnapshot = (parent, snapshot) => {
}
/**
* @param {AbstractType<any> & { _map: Map<string, Item> }} type
* @param {Map<string,Item>} map
* @return {IterableIterator<Array<any>>}
*
* @private
* @function
*/
export const createMapIterator = type => {
type.doc ?? warnPrematureAccess()
return iterator.iteratorFilter(type._map.entries(), /** @param {any} entry */ entry => !entry[1].deleted)
}
export const createMapIterator = map => iterator.iteratorFilter(map.entries(), /** @param {any} entry */ entry => !entry[1].deleted)

View File

@ -16,7 +16,6 @@ import {
YArrayRefID,
callTypeObservers,
transact,
warnPrematureAccess,
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
} from '../internals.js'
import { typeListSlice } from './AbstractType.js'
@ -26,7 +25,16 @@ import { typeListSlice } from './AbstractType.js'
* @template T
* @extends YEvent<YArray<T>>
*/
export class YArrayEvent extends YEvent {}
export class YArrayEvent extends YEvent {
/**
* @param {YArray<T>} yarray The changed type
* @param {Transaction} transaction The transaction object
*/
constructor (yarray, transaction) {
super(yarray, transaction)
this._transaction = transaction
}
}
/**
* A shared Array implementation.
@ -105,8 +113,7 @@ export class YArray extends AbstractType {
}
get length () {
this.doc ?? warnPrematureAccess()
return this._length
return this._prelimContent === null ? this._length : this._prelimContent.length
}
/**
@ -164,9 +171,9 @@ export class YArray extends AbstractType {
}
/**
* Prepends content to this YArray.
* Preppends content to this YArray.
*
* @param {Array<T>} content Array of content to prepend.
* @param {Array<T>} content Array of content to preppend.
*/
unshift (content) {
this.insert(0, content)
@ -208,8 +215,7 @@ export class YArray extends AbstractType {
}
/**
* Returns a portion of this YArray into a JavaScript Array selected
* from start to end (end not included).
* Transforms this YArray to a JavaScript Array.
*
* @param {number} [start]
* @param {number} [end]

View File

@ -13,7 +13,6 @@ import {
YMapRefID,
callTypeObservers,
transact,
warnPrematureAccess,
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
} from '../internals.js'
@ -122,7 +121,6 @@ export class YMap extends AbstractType {
* @return {Object<string,any>}
*/
toJSON () {
this.doc ?? warnPrematureAccess()
/**
* @type {Object<string,MapType>}
*/
@ -142,7 +140,7 @@ export class YMap extends AbstractType {
* @return {number}
*/
get size () {
return [...createMapIterator(this)].length
return [...createMapIterator(this._map)].length
}
/**
@ -151,7 +149,7 @@ export class YMap extends AbstractType {
* @return {IterableIterator<string>}
*/
keys () {
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => v[0])
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => v[0])
}
/**
@ -160,7 +158,7 @@ export class YMap extends AbstractType {
* @return {IterableIterator<MapType>}
*/
values () {
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => v[1].content.getContent()[v[1].length - 1])
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => v[1].content.getContent()[v[1].length - 1])
}
/**
@ -169,7 +167,7 @@ export class YMap extends AbstractType {
* @return {IterableIterator<[string, MapType]>}
*/
entries () {
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => /** @type {any} */ ([v[0], v[1].content.getContent()[v[1].length - 1]]))
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => /** @type {any} */ ([v[0], v[1].content.getContent()[v[1].length - 1]]))
}
/**
@ -178,7 +176,6 @@ export class YMap extends AbstractType {
* @param {function(MapType,string,YMap<MapType>):void} f A function to execute on every element of this YArray.
*/
forEach (f) {
this.doc ?? warnPrematureAccess()
this._map.forEach((item, key) => {
if (!item.deleted) {
f(item.content.getContent()[item.length - 1], key, this)

View File

@ -26,7 +26,6 @@ import {
typeMapGetAll,
updateMarkerChanges,
ContentType,
warnPrematureAccess,
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
} from '../internals.js'
@ -478,7 +477,7 @@ export const cleanupYTextFormatting = type => {
}
/**
* This will be called by the transaction once the event handlers are called to potentially cleanup
* This will be called by the transction once the event handlers are called to potentially cleanup
* formatting attributes.
*
* @param {Transaction} transaction
@ -568,7 +567,7 @@ const deleteText = (transaction, currPos, length) => {
/**
* The Quill Delta format represents changes on a text document with
* formatting information. For more information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
* formatting information. For mor information visit {@link https://quilljs.com/docs/delta/|Quill Delta}
*
* @example
* {
@ -876,7 +875,6 @@ export class YText extends AbstractType {
* @type {number}
*/
get length () {
this.doc ?? warnPrematureAccess()
return this._length
}
@ -933,7 +931,6 @@ export class YText extends AbstractType {
* @public
*/
toString () {
this.doc ?? warnPrematureAccess()
let str = ''
/**
* @type {Item|null}
@ -961,7 +958,7 @@ export class YText extends AbstractType {
/**
* Apply a {@link Delta} on this shared YText type.
*
* @param {Array<any>} delta The changes to apply on this element.
* @param {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.
*
@ -1007,7 +1004,6 @@ export class YText extends AbstractType {
* @public
*/
toDelta (snapshot, prevSnapshot, computeYChange) {
this.doc ?? warnPrematureAccess()
/**
* @type{Array<any>}
*/

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 which the
* @param {Transaction} transaction The transaction instance with wich the
* change was created.
*/
constructor (target, subs, transaction) {

View File

@ -17,7 +17,6 @@ import {
transact,
typeListGet,
typeListSlice,
warnPrematureAccess,
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, ContentType, Transaction, Item, YXmlText, YXmlHook // eslint-disable-line
} from '../internals.js'
@ -67,7 +66,6 @@ export class YXmlTreeWalker {
*/
this._currentNode = /** @type {Item} */ (root._start)
this._firstCall = true
root.doc ?? warnPrematureAccess()
}
[Symbol.iterator] () {
@ -96,12 +94,8 @@ export class YXmlTreeWalker {
} else {
// walk right or up in the tree
while (n !== null) {
/**
* @type {Item | null}
*/
const nxt = n.next
if (nxt !== null) {
n = nxt
if (n.right !== null) {
n = n.right
break
} else if (n.parent === this._root) {
n = null
@ -183,7 +177,6 @@ export class YXmlFragment extends AbstractType {
}
get length () {
this.doc ?? warnPrematureAccess()
return this._prelimContent === null ? this._length : this._prelimContent.length
}
@ -387,9 +380,9 @@ export class YXmlFragment extends AbstractType {
}
/**
* Prepends content to this YArray.
* Preppends content to this YArray.
*
* @param {Array<YXmlElement|YXmlText>} content Array of content to prepend.
* @param {Array<YXmlElement|YXmlText>} content Array of content to preppend.
*/
unshift (content) {
this.insert(0, content)
@ -406,8 +399,7 @@ export class YXmlFragment extends AbstractType {
}
/**
* Returns a portion of this YXmlFragment into a JavaScript Array selected
* from start to end (end not included).
* Transforms this YArray to a JavaScript Array.
*
* @param {number} [start]
* @param {number} [end]

View File

@ -104,9 +104,8 @@ export class Doc extends ObservableV2 {
* lost (with false as a parameter).
*/
this.isSynced = false
this.isDestroyed = false
/**
* Promise that resolves once the document has been loaded from a persistence provider.
* Promise that resolves once the document has been loaded from a presistence provider.
*/
this.whenLoaded = promise.create(resolve => {
this.on('load', () => {
@ -323,7 +322,6 @@ export class Doc extends ObservableV2 {
* Emit `destroy` event and unregister all event handlers.
*/
destroy () {
this.isDestroyed = true
array.from(this.subdocs).forEach(subdoc => subdoc.destroy())
const item = this._item
if (item !== null) {

View File

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

View File

@ -9,7 +9,7 @@ import {
ContentType,
followRedone,
getItem,
StructStore, ID, Doc, AbstractType, // eslint-disable-line
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 character
* If assoc < 0, then the relative position is associated to the caharacter
* before the meant position.
*
* @type {number}
@ -102,7 +102,7 @@ export const relativePositionToJSON = rpos => {
*
* @function
*/
export const createRelativePositionFromJSON = json => new RelativePosition(json.type == null ? null : createID(json.type.client, json.type.clock), json.tname ?? null, json.item == null ? null : createID(json.item.client, json.item.clock), json.assoc == null ? 0 : json.assoc)
export const createRelativePositionFromJSON = json => new RelativePosition(json.type == null ? null : createID(json.type.client, json.type.clock), json.tname || null, json.item == null ? null : createID(json.item.client, json.item.clock), json.assoc == null ? 0 : json.assoc)
export class AbsolutePosition {
/**
@ -256,18 +256,6 @@ 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.
*
@ -298,7 +286,7 @@ export const createAbsolutePositionFromRelativePosition = (rpos, doc, followUndo
if (getState(store, rightID.client) <= rightID.clock) {
return null
}
const res = followUndoneDeletions ? followRedone(store, rightID) : getItemWithOffset(store, rightID)
const res = followUndoneDeletions ? followRedone(store, rightID) : { item: getItem(store, rightID), diff: 0 }
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 integrityCheck = store => {
export const integretyCheck = 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 integrity check')
throw new Error('StructStore failed integrety check')
}
}
})

View File

@ -225,7 +225,7 @@ const tryGcDeleteSet = (ds, store, gcFilter) => {
*/
const tryMergeDeleteSet = (ds, store) => {
// try to merge deleted / gc'd items
// merge from right to left for better efficiency and so we don't miss any merge targets
// merge from right to left for better efficiecy and so we don't miss any merge targets
ds.clients.forEach((deleteItems, client) => {
const structs = /** @type {Array<GC|Item>} */ (store.clients.get(client))
for (let di = deleteItems.length - 1; di >= 0; di--) {

View File

@ -39,7 +39,7 @@ export class StackItem {
*/
const clearUndoManagerStackItem = (tr, um, stackItem) => {
iterateDeletedStructs(tr, stackItem.deletions, item => {
if (item instanceof Item && um.scope.some(type => type === tr.doc || isParentOf(/** @type {AbstractType<any>} */ (type), item))) {
if (item instanceof Item && um.scope.some(type => isParentOf(type, item))) {
keepItem(item, false)
}
})
@ -81,7 +81,7 @@ const popStackItem = (undoManager, stack, eventType) => {
}
struct = item
}
if (!struct.deleted && scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), /** @type {Item} */ (struct)))) {
if (!struct.deleted && scope.some(type => isParentOf(type, /** @type {Item} */ (struct)))) {
itemsToDelete.push(struct)
}
}
@ -89,7 +89,7 @@ const popStackItem = (undoManager, stack, eventType) => {
iterateDeletedStructs(transaction, stackItem.deletions, struct => {
if (
struct instanceof Item &&
scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), struct)) &&
scope.some(type => isParentOf(type, struct)) &&
// Never redo structs in stackItem.insertions because they were created and deleted in the same capture interval.
!isDeleted(stackItem.insertions, struct.id)
) {
@ -118,13 +118,12 @@ const popStackItem = (undoManager, stack, eventType) => {
})
_tr = transaction
}, undoManager)
const res = undoManager.currStackItem
if (res != null) {
if (undoManager.currStackItem != null) {
const changedParentTypes = _tr.changedParentTypes
undoManager.emit('stack-item-popped', [{ stackItem: res, type: eventType, changedParentTypes, origin: undoManager }, undoManager])
undoManager.emit('stack-item-popped', [{ stackItem: undoManager.currStackItem, type: eventType, changedParentTypes, origin: undoManager }, undoManager])
undoManager.currStackItem = null
}
return res
return undoManager.currStackItem
}
/**
@ -159,7 +158,7 @@ const popStackItem = (undoManager, stack, eventType) => {
*/
export class UndoManager extends ObservableV2 {
/**
* @param {Doc|AbstractType<any>|Array<AbstractType<any>>} typeScope Limits the scope of the UndoManager. If this is set to a ydoc instance, all changes on that ydoc will be undone. If set to a specific type, only changes on that type or its children will be undone. Also accepts an array of types.
* @param {AbstractType<any>|Array<AbstractType<any>>} typeScope Accepts either a single type, or an array of types
* @param {UndoManagerOptions} options
*/
constructor (typeScope, {
@ -168,11 +167,11 @@ export class UndoManager extends ObservableV2 {
deleteFilter = () => true,
trackedOrigins = new Set([null]),
ignoreRemoteMapChanges = false,
doc = /** @type {Doc} */ (array.isArray(typeScope) ? typeScope[0].doc : typeScope instanceof Doc ? typeScope : typeScope.doc)
doc = /** @type {Doc} */ (array.isArray(typeScope) ? typeScope[0].doc : typeScope.doc)
} = {}) {
super()
/**
* @type {Array<AbstractType<any> | Doc>}
* @type {Array<AbstractType<any>>}
*/
this.scope = []
this.doc = doc
@ -212,7 +211,7 @@ export class UndoManager extends ObservableV2 {
// Only track certain transactions
if (
!this.captureTransaction(transaction) ||
!this.scope.some(type => transaction.changedParentTypes.has(/** @type {AbstractType<any>} */ (type)) || type === this.doc) ||
!this.scope.some(type => transaction.changedParentTypes.has(type)) ||
(!this.trackedOrigins.has(transaction.origin) && (!transaction.origin || !this.trackedOrigins.has(transaction.origin.constructor)))
) {
return
@ -251,7 +250,7 @@ export class UndoManager extends ObservableV2 {
}
// make sure that deleted structs are not gc'd
iterateDeletedStructs(transaction, transaction.deleteSet, /** @param {Item|GC} item */ item => {
if (item instanceof Item && this.scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), item))) {
if (item instanceof Item && this.scope.some(type => isParentOf(type, item))) {
keepItem(item, true)
}
})
@ -272,17 +271,13 @@ export class UndoManager extends ObservableV2 {
}
/**
* Extend the scope.
*
* @param {Array<AbstractType<any> | Doc> | AbstractType<any> | Doc} ytypes
* @param {Array<AbstractType<any>> | AbstractType<any>} ytypes
*/
addToScope (ytypes) {
const tmpSet = new Set(this.scope)
ytypes = array.isArray(ytypes) ? ytypes : [ytypes]
ytypes.forEach(ytype => {
if (!tmpSet.has(ytype)) {
tmpSet.add(ytype)
if (ytype instanceof AbstractType ? ytype.doc !== this.doc : ytype !== this.doc) logging.warn('[yjs#509] Not same Y.Doc') // use MultiDocUndoManager instead. also see https://github.com/yjs/yjs/issues/509
if (this.scope.every(yt => yt !== ytype)) {
if (ytype.doc !== this.doc) logging.warn('[yjs#509] Not same Y.Doc') // use MultiDocUndoManager instead. also see https://github.com/yjs/yjs/issues/509
this.scope.push(ytype)
}
})

View File

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

View File

@ -264,8 +264,8 @@ const getPathTo = (parent, child) => {
let i = 0
let c = /** @type {AbstractType<any>} */ (child._item.parent)._start
while (c !== child._item && c !== null) {
if (!c.deleted && c.countable) {
i += c.length
if (!c.deleted) {
i++
}
c = c.right
}

View File

@ -154,7 +154,7 @@ export const readClientsStructRefs = (decoder, doc) => {
// @type {string|null}
const struct = new Item(
createID(client, clock),
null, // left
null, // leftd
(info & binary.BIT8) === binary.BIT8 ? decoder.readLeftID() : null, // origin
null, // right
(info & binary.BIT7) === binary.BIT7 ? decoder.readRightID() : null, // right origin
@ -178,7 +178,7 @@ export const readClientsStructRefs = (decoder, doc) => {
const struct = new Item(
createID(client, clock),
null, // left
null, // leftd
origin, // origin
null, // right
rightOrigin, // right origin
@ -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 equal to `structReaders.length`.
* depends on struct3 (from client1). Therefore the max stack size is eqaul 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 inapplicableItems = clientsStructRefs.get(client)
if (inapplicableItems) {
const unapplicableItems = clientsStructRefs.get(client)
if (unapplicableItems) {
// decrement because we weren't able to apply previous operation
inapplicableItems.i--
restStructs.clients.set(client, inapplicableItems.refs.slice(inapplicableItems.i))
unapplicableItems.i--
restStructs.clients.set(client, unapplicableItems.refs.slice(unapplicableItems.i))
clientsStructRefs.delete(client)
inapplicableItems.i = 0
inapplicableItems.refs = []
unapplicableItems.i = 0
unapplicableItems.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])
@ -370,7 +370,7 @@ export const writeStructsFromTransaction = (encoder, transaction) => writeClient
/**
* Read and apply a document update.
*
* This function has the same effect as `applyUpdate` but accepts a decoder.
* This function has the same effect as `applyUpdate` but accepts an decoder.
*
* @param {decoding.Decoder} decoder
* @param {Doc} ydoc
@ -451,7 +451,7 @@ export const readUpdateV2 = (decoder, ydoc, transactionOrigin, structDecoder = n
/**
* Read and apply a document update.
*
* This function has the same effect as `applyUpdate` but accepts a decoder.
* This function has the same effect as `applyUpdate` but accepts an decoder.
*
* @param {decoding.Decoder} decoder
* @param {Doc} ydoc

View File

@ -1,5 +1,5 @@
/**
* Testing if encoding/decoding compatibility and integration compatibility is given.
* Testing if encoding/decoding compatibility and integration compatiblity 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,28 +15,15 @@ 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)
}
/**
* @type {any}
*/
const tests = {
runTests({
doc, map, array, text, xml, encoding, undoredo, compatibility, snapshot, updates, relativePositions
}
const run = async () => {
if (environment.isNode) {
// tests.nodejs = await import('./node.tests.js')
}
const success = await runTests(tests)
}).then(success => {
/* istanbul ignore next */
if (isNode) {
process.exit(success ? 0 : 1)
}
}
run()
})

View File

@ -85,26 +85,6 @@ 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 should still work.
// now this snapshot reflects the latest state. It shoult still work.
const snap2 = Y.snapshot(doc)
const docRestored2 = Y.createDocFromSnapshot(doc, snap2)
t.compare(docRestored2.getArray().toArray(), ['world'])

View File

@ -116,72 +116,6 @@ export const testEmptyTypeScope = _tc => {
t.assert(yarray.length === 0)
}
/**
* @param {t.TestCase} _tc
*/
export const testRejectUpdateExample = _tc => {
const tmpydoc1 = new Y.Doc()
tmpydoc1.getArray('restricted').insert(0, [1])
tmpydoc1.getArray('public').insert(0, [1])
const update1 = Y.encodeStateAsUpdate(tmpydoc1)
const tmpydoc2 = new Y.Doc()
tmpydoc2.getArray('public').insert(0, [2])
const update2 = Y.encodeStateAsUpdate(tmpydoc2)
const ydoc = new Y.Doc()
const restrictedType = ydoc.getArray('restricted')
/**
* Assume this function handles incoming updates via a communication channel like websockets.
* Changes to the `ydoc.getMap('restricted')` type should be rejected.
*
* - set up undo manager on the restricted types
* - cache pending* updates from the Ydoc to avoid certain attacks
* - apply received update and check whether the restricted type (or any of its children) has been changed.
* - catch errors that might try to circumvent the restrictions
* - undo changes on restricted types
* - reapply pending* updates
*
* @param {Uint8Array} update
*/
const updateHandler = (update) => {
// don't handle changes of the local undo manager, which is used to undo invalid changes
const um = new Y.UndoManager(restrictedType, { trackedOrigins: new Set(['remote change']) })
const beforePendingDs = ydoc.store.pendingDs
const beforePendingStructs = ydoc.store.pendingStructs?.update
try {
Y.applyUpdate(ydoc, update, 'remote change')
} finally {
while (um.undoStack.length) {
um.undo()
}
um.destroy()
ydoc.store.pendingDs = beforePendingDs
ydoc.store.pendingStructs = null
if (beforePendingStructs) {
Y.applyUpdateV2(ydoc, beforePendingStructs)
}
}
}
updateHandler(update1)
updateHandler(update2)
t.assert(restrictedType.length === 0)
t.assert(ydoc.getArray('public').length === 2)
}
/**
* Test case to fix #241
* @param {t.TestCase} _tc
*/
export const testGlobalScope = _tc => {
const ydoc = new Y.Doc()
const um = new Y.UndoManager(ydoc)
const yarray = ydoc.getArray()
yarray.insert(0, [1])
um.undo()
t.assert(yarray.length === 0)
}
/**
* Test case to fix #241
* @param {t.TestCase} _tc

View File

@ -4,9 +4,6 @@ import * as Y from '../src/index.js'
import * as t from 'lib0/testing'
import * as prng from 'lib0/prng'
import * as math from 'lib0/math'
import * as env from 'lib0/environment'
const isDevMode = env.getVariable('node_env') === 'development'
/**
* @param {t.TestCase} tc
@ -20,28 +17,6 @@ export const testBasicUpdate = tc => {
t.compare(doc2.getArray('array').toArray(), ['hi'])
}
/**
* @param {t.TestCase} tc
*/
export const testFailsObjectManipulationInDevMode = tc => {
if (isDevMode) {
t.info('running in dev mode')
const doc = new Y.Doc()
const a = [1, 2, 3]
const b = { o: 1 }
doc.getArray('test').insert(0, [a])
doc.getMap('map').set('k', b)
t.fails(() => {
a[0] = 42
})
t.fails(() => {
b.o = 42
})
} else {
t.info('not in dev mode')
}
}
/**
* @param {t.TestCase} tc
*/
@ -355,29 +330,6 @@ export const testObserveDeepEventOrder = tc => {
}
}
/**
* Correct index when computing event.path in observeDeep - https://github.com/yjs/yjs/issues/457
*
* @param {t.TestCase} _tc
*/
export const testObservedeepIndexes = _tc => {
const doc = new Y.Doc()
const map = doc.getMap()
// Create a field with the array as value
map.set('my-array', new Y.Array())
// Fill the array with some strings and our Map
map.get('my-array').push(['a', 'b', 'c', new Y.Map()])
/**
* @type {Array<any>}
*/
let eventPath = []
map.observeDeep((events) => { eventPath = events[0].path })
// set a value on the map inside of our array
map.get('my-array').get(3).set('hello', 'world')
console.log(eventPath)
t.compare(eventPath, ['my-array', 3])
}
/**
* @param {t.TestCase} tc
*/

View File

@ -369,11 +369,11 @@ export const testObserversUsingObservedeep = tc => {
/**
* @type {Array<Array<string|number>>}
*/
const paths = []
const pathes = []
let calls = 0
map0.observeDeep(events => {
events.forEach(event => {
paths.push(event.path)
pathes.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(paths, [[], ['map'], ['map', 'array']])
t.compare(pathes, [[], ['map'], ['map', 'array']])
compare(users)
}
@ -393,14 +393,14 @@ export const testPathsOfSiblingEvents = tc => {
/**
* @type {Array<Array<string|number>>}
*/
const paths = []
const pathes = []
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 => {
paths.push(event.path)
pathes.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(paths, [['map'], ['map', 'text1']])
t.compare(pathes, [['map'], ['map', 'text1']])
compare(users)
}

View File

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