Compare commits
123 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
34b9343b2e | ||
|
d5b5e7a9a1 | ||
|
ad0d915794 | ||
|
2ef9ccd170 | ||
|
3ecfb4e898 | ||
|
35c030d834 | ||
|
e3739bce8e | ||
|
afa4c35866 | ||
|
09fbb62ba9 | ||
|
78e0527b46 | ||
|
69d4a5c821 | ||
|
cc9a857441 | ||
|
4b865764b8 | ||
|
40725e373b | ||
|
c05b815b4c | ||
|
e53c44e3a6 | ||
|
1bec008862 | ||
|
bb5410b6dd | ||
|
2d2e662d4d | ||
|
80e83a84c6 | ||
|
3c9c0f17d1 | ||
|
e67b1296a7 | ||
|
1a0d4aa797 | ||
|
f18eab2dfe | ||
|
89dddc2a95 | ||
|
f583d2a211 | ||
|
1b0f2e5463 | ||
|
4404d090e4 | ||
|
d4d4ae5f53 | ||
|
4ffd3709f8 | ||
|
0419b74315 | ||
|
c951f2b7ea | ||
|
4e2d3c8ac6 | ||
|
8dc1296a0b | ||
|
4329997350 | ||
|
2b7ea8a2af | ||
|
4f47355893 | ||
|
6074f80257 | ||
|
42bbb44bfc | ||
|
cc2d7320aa | ||
|
e804dd7573 | ||
|
a304024a76 | ||
|
487465d701 | ||
|
345fd31b10 | ||
|
4ff65b5dc3 | ||
|
8152cf81cb | ||
|
3bf44b9850 | ||
|
8cd1a482bb | ||
|
9e9f294009 | ||
|
9a993f81d4 | ||
|
f604250fc3 | ||
|
4fb7789cdd | ||
|
c1ef9a12b9 | ||
|
7422b18e87 | ||
|
95e2bc4429 | ||
|
f2ff8b9536 | ||
|
3f9bfe42f7 | ||
|
5b4d2a6bcf | ||
|
44e51080af | ||
|
dd17228a8f | ||
|
eeb4c9969d | ||
|
56d5e3287b | ||
|
294c6a15c5 | ||
|
c944a4553c | ||
|
f29cd2baf4 | ||
|
384ec4db78 | ||
|
5e19c35405 | ||
|
1bfa6dfb74 | ||
|
2e5abad773 | ||
|
3f1746f3a9 | ||
|
34b06b6cf9 | ||
|
d4dac558c0 | ||
|
a47a48b891 | ||
|
2e79d0369e | ||
|
88506f6d78 | ||
|
fbd088ee78 | ||
|
0678ed1eb5 | ||
|
0973e0acd4 | ||
|
6932696795 | ||
|
a4303f914d | ||
|
03593aeeb1 | ||
|
d67a951104 | ||
|
72205a688f | ||
|
edad668dbd | ||
|
c264b1c291 | ||
|
cdd8e4f5fc | ||
|
06e71f651d | ||
|
54594a2d75 | ||
|
13772bf891 | ||
|
0896ed42b2 | ||
|
656b7e7f6a | ||
|
0511b66346 | ||
|
91b718cde0 | ||
|
d56221b66a | ||
|
ce43124ad0 | ||
|
0af69cf6d6 | ||
|
3df335cb4c | ||
|
387be70ae9 | ||
|
927c2369aa | ||
|
8270373c9f | ||
|
43815d8292 | ||
|
f0dc53f53f | ||
|
25ae9f3236 | ||
|
5e712e39b1 | ||
|
4ffd23fd0b | ||
|
05d974cee1 | ||
|
f1532771b7 | ||
|
aee9e14d09 | ||
|
f5aa852054 | ||
|
b990ad9f86 | ||
|
43e17802a6 | ||
|
01c3668a0b | ||
|
52b906898f | ||
|
d119459fad | ||
|
d730abe594 | ||
|
ca24f1ee76 | ||
|
dc45a8d3cf | ||
|
2062f52a90 | ||
|
6e674ff5f7 | ||
|
2fba694cd4 | ||
|
b235c57d76 | ||
|
6beab79eb4 | ||
|
221cb81dbf |
@ -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
|
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
|
random 53-bit integer (53 bits because that fits in the javascript safe integer
|
||||||
range).
|
range \[JavaScript uses IEEE 754 floats\]).
|
||||||
|
|
||||||
## List items
|
## 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
|
will be split if the run is interrupted for any reason (eg a character in the
|
||||||
middle of the run is deleted).
|
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`
|
succeeding item. These are stored in the item's `origin` and `originRight`
|
||||||
fields, respectively. These are used when peers concurrently insert at the same
|
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
|
location in a document. Though quite rare in practice, Yjs needs to make sure
|
||||||
@ -88,7 +88,7 @@ When a local insert happens, Yjs needs to map the insert position in the
|
|||||||
document (eg position 1000) to an ID. With just the linked list, this would
|
document (eg position 1000) to an ID. With just the linked list, this would
|
||||||
require a slow O(n) linear scan of the list. But when editing a document, most
|
require a slow O(n) linear scan of the list. But when editing a document, most
|
||||||
inserts are either at the same position as the last insert, or nearby. To
|
inserts are either at the same position as the last insert, or nearby. To
|
||||||
improve performance, Yjs stores a cache of the 10 most recently looked up
|
improve performance, Yjs stores a cache of the 80 most recently looked up
|
||||||
insert positions in the document. This is consulted and updated when a position
|
insert positions in the document. This is consulted and updated when a position
|
||||||
is looked up to improve performance in the average case. The cache is updated
|
is looked up to improve performance in the average case. The cache is updated
|
||||||
using a heuristic that is still changing (currently, it is updated when a new
|
using a heuristic that is still changing (currently, it is updated when a new
|
||||||
|
159
README.md
159
README.md
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
> A CRDT framework with a powerful abstraction of shared data
|
> 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`
|
data structure as *shared types*. Shared types are common data types like `Map`
|
||||||
or `Array` with superpowers: changes are automatically distributed to other
|
or `Array` with superpowers: changes are automatically distributed to other
|
||||||
peers and merged without merge conflicts.
|
peers and merged without merge conflicts.
|
||||||
@ -49,12 +49,16 @@ Showcase](https://yjs-diagram.synergy.codes/).
|
|||||||
## Who is using Yjs
|
## Who is using Yjs
|
||||||
|
|
||||||
* [AFFiNE](https://affine.pro/) A local-first, privacy-first, open source
|
* [AFFiNE](https://affine.pro/) A local-first, privacy-first, open source
|
||||||
knowledge base. 🏅
|
knowledge base. :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:
|
* [Cargo](https://cargo.site/) Site builder for designers and artists :star2:
|
||||||
* [Gitbook](https://gitbook.com) Knowledge management for technical teams :star2:
|
* [Gitbook](https://gitbook.com) Knowledge management for technical teams :star2:
|
||||||
* [Evernote](https://evernote.com) Note-taking app :star2:
|
* [Evernote](https://evernote.com) Note-taking app :star2:
|
||||||
* [Lessonspace](https://thelessonspace.com) Enterprise platform for virtual
|
* [Lessonspace](https://thelessonspace.com) Enterprise platform for virtual
|
||||||
classrooms and online training :star2:
|
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:
|
* [Dynaboard](https://dynaboard.com/) Build web apps collaboratively. :star:
|
||||||
* [Relm](https://www.relm.us/) A collaborative gameworld for teamwork and
|
* [Relm](https://www.relm.us/) A collaborative gameworld for teamwork and
|
||||||
community. :star:
|
community. :star:
|
||||||
@ -64,11 +68,15 @@ Showcase](https://yjs-diagram.synergy.codes/).
|
|||||||
Nimbus Web. :star:
|
Nimbus Web. :star:
|
||||||
* [Pluxbox RadioManager](https://getradiomanager.com/) A web-based app to
|
* [Pluxbox RadioManager](https://getradiomanager.com/) A web-based app to
|
||||||
collaboratively organize radio broadcasts. :star:
|
collaboratively organize radio broadcasts. :star:
|
||||||
|
* [modyfi](https://www.modyfi.com) - Modyfi is the design platform built for
|
||||||
|
multidisciplinary designers. Design, generate, animate, and more — without
|
||||||
|
switching between apps. :star:
|
||||||
* [Sana](https://sanalabs.com/) A learning platform with collaborative text
|
* [Sana](https://sanalabs.com/) A learning platform with collaborative text
|
||||||
editing powered by Yjs.
|
editing powered by Yjs.
|
||||||
* [Serenity Notes](https://www.serenity.re/en/notes) End-to-end encrypted
|
* [Serenity Notes](https://www.serenity.re/en/notes) End-to-end encrypted
|
||||||
collaborative notes app.
|
collaborative notes app.
|
||||||
* [PRSM](https://prsm.uk/) Collaborative mind-mapping and system visualisation. *[(source)](https://github.com/micrology/prsm)*
|
* [PRSM](https://prsm.uk/) Collaborative mind-mapping and system visualisation.
|
||||||
|
*[(source)](https://github.com/micrology/prsm)*
|
||||||
* [Alldone](https://alldone.app/) A next-gen project management and
|
* [Alldone](https://alldone.app/) A next-gen project management and
|
||||||
collaboration platform.
|
collaboration platform.
|
||||||
* [Living Spec](https://livingspec.com/) A modern way for product teams to collaborate.
|
* [Living Spec](https://livingspec.com/) A modern way for product teams to collaborate.
|
||||||
@ -91,22 +99,47 @@ Showcase](https://yjs-diagram.synergy.codes/).
|
|||||||
* [AWS SageMaker](https://aws.amazon.com/sagemaker/) Tools for building Machine
|
* [AWS SageMaker](https://aws.amazon.com/sagemaker/) Tools for building Machine
|
||||||
Learning Models
|
Learning Models
|
||||||
* [linear](https://linear.app) Streamline issues, projects, and product roadmaps.
|
* [linear](https://linear.app) Streamline issues, projects, and product roadmaps.
|
||||||
|
* [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
|
||||||
|
* [Multi.app](https://multi.app) - Multiplayer app sharing: Point, draw and edit
|
||||||
|
in shared apps as if they're on your computer. They are using Yrs.
|
||||||
|
* [AppMaster](https://appmaster.io) A No-Code platform for creating
|
||||||
|
production-ready applications with source code generation.
|
||||||
|
* [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
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
* [Overview](#Overview)
|
* [Overview](#overview)
|
||||||
* [Bindings](#Bindings)
|
* [Bindings](#bindings)
|
||||||
* [Providers](#Providers)
|
* [Providers](#providers)
|
||||||
* [Ports](#Ports)
|
* [Tooling](#tooling)
|
||||||
* [Getting Started](#Getting-Started)
|
* [Ports](#ports)
|
||||||
* [API](#API)
|
* [Getting Started](#getting-started)
|
||||||
* [Shared Types](#Shared-Types)
|
* [API](#api)
|
||||||
* [Y.Doc](#YDoc)
|
* [Shared Types](#shared-types)
|
||||||
* [Document Updates](#Document-Updates)
|
* [Y.Doc](#ydoc)
|
||||||
* [Relative Positions](#Relative-Positions)
|
* [Document Updates](#document-updates)
|
||||||
* [Y.UndoManager](#YUndoManager)
|
* [Relative Positions](#relative-positions)
|
||||||
* [Yjs CRDT Algorithm](#Yjs-CRDT-Algorithm)
|
* [Y.UndoManager](#yundomanager)
|
||||||
* [License and Author](#License-and-Author)
|
* [Yjs CRDT Algorithm](#yjs-crdt-algorithm)
|
||||||
|
* [License and Author](#license-and-author)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@ -124,10 +157,14 @@ 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) |
|
| [Monaco](https://microsoft.github.io/monaco-editor/) | ✔ | [y-monaco](https://github.com/yjs/y-monaco) | [demo](https://demos.yjs.dev/monaco/monaco.html) |
|
||||||
| [Slate](https://github.com/ianstormtaylor/slate) | ✔ | [slate-yjs](https://github.com/bitphinix/slate-yjs) | [demo](https://bitphinix.github.io/slate-yjs-example) |
|
| [Slate](https://github.com/ianstormtaylor/slate) | ✔ | [slate-yjs](https://github.com/bitphinix/slate-yjs) | [demo](https://bitphinix.github.io/slate-yjs-example) |
|
||||||
| [BlockSuite](https://github.com/toeverything/blocksuite) | ✔ | (native) | [demo](https://blocksuite-toeverything.vercel.app/?init) |
|
| [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) |
|
| [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) |
|
| [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) |
|
| 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) |
|
| [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
|
### Providers
|
||||||
|
|
||||||
@ -145,19 +182,20 @@ collaborative app.
|
|||||||
<dt><a href="https://github.com/yjs/y-websocket">y-websocket</a></dt>
|
<dt><a href="https://github.com/yjs/y-websocket">y-websocket</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
A module that contains a simple websocket backend and a websocket client that
|
A module that contains a simple websocket backend and a websocket client that
|
||||||
connects to that backend. The backend can be extended to persist updates in a
|
connects to that backend. <a href="https://github.com/yjs/y-redis/"><b>y-redis</b></a>,
|
||||||
leveldb database. <b>y-sweet</b> and <b>ypy-websocket</b> (see below) are
|
<b>y-sweet</b>, <b>ypy-websocket</b> and <a href="https://tiptap.dev/docs/hocuspocus/introduction">
|
||||||
compatible to the y-wesocket protocol.
|
<b>Hocuspocus</b></a> (see below) are alternative
|
||||||
|
backends to y-websocket.
|
||||||
</dd>
|
</dd>
|
||||||
<dt><a href="https://github.com/yjs/y-webrtc">y-webrtc</a></dt>
|
<dt><a href="https://github.com/yjs/y-webrtc">y-webrtc</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
Propagates document updates peer-to-peer using WebRTC. The peers exchange
|
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
|
are available. Communication over the signaling servers can be encrypted by
|
||||||
providing a shared secret, keeping the connection information and the shared
|
providing a shared secret, keeping the connection information and the shared
|
||||||
document private.
|
document private.
|
||||||
</dd>
|
</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>
|
<dd>
|
||||||
<a href="https://liveblocks.io/document/yjs">Liveblocks Yjs</a> provides a fully
|
<a href="https://liveblocks.io/document/yjs">Liveblocks Yjs</a> provides a fully
|
||||||
hosted WebSocket infrastructure and persisted data store for Yjs
|
hosted WebSocket infrastructure and persisted data store for Yjs
|
||||||
@ -165,11 +203,23 @@ documents. No configuration or maintenance is required. It also features
|
|||||||
Yjs webhook events, REST API to read and update Yjs documents, and a
|
Yjs webhook events, REST API to read and update Yjs documents, and a
|
||||||
browser DevTools extension.
|
browser DevTools extension.
|
||||||
</dd>
|
</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>
|
<dd>
|
||||||
A standalone yjs server with persistence to S3 or filesystem. They offer a
|
A standalone yjs server with persistence to S3 or filesystem. They offer a
|
||||||
<a href="https://y-sweet.cloud">cloud service</a> as well.
|
<a href="https://y-sweet.cloud">cloud service</a> as well.
|
||||||
</dd>
|
</dd>
|
||||||
|
<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>
|
<dt><a href="https://docs.partykit.io/reference/y-partykit-api/">PartyKit</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
Cloud service for building multiplayer apps.
|
Cloud service for building multiplayer apps.
|
||||||
@ -205,6 +255,20 @@ An ActionCable companion for Yjs clients. There is a fitting
|
|||||||
<dd>
|
<dd>
|
||||||
Websocket backend, written in Python.
|
Websocket backend, written in Python.
|
||||||
</dd>
|
</dd>
|
||||||
|
<dt><a href="https://tinybase.org/">Tinybase</a></dt>
|
||||||
|
<dd>
|
||||||
|
The reactive data store for local-first apps. They support multiple CRDTs and
|
||||||
|
different network technologies.
|
||||||
|
</dd>
|
||||||
|
<dt><a href="https://codeberg.org/webxdc/y-webxdc">y-webxdc</a></dt>
|
||||||
|
<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>
|
</dl>
|
||||||
|
|
||||||
#### Persistence Providers
|
#### Persistence Providers
|
||||||
@ -220,19 +284,35 @@ network provider.
|
|||||||
<dd>
|
<dd>
|
||||||
Adds persistent storage to a server with MongoDB. Can be used with the
|
Adds persistent storage to a server with MongoDB. Can be used with the
|
||||||
y-websocket provider.
|
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>
|
</dd>
|
||||||
<dt><a href="https://github.com/podraven/y-fire">y-fire</a></dt>
|
<dt><a href="https://github.com/podraven/y-fire">y-fire</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
A database and connection provider for Yjs based on Firestore.
|
A database and connection provider for Yjs based on Firestore.
|
||||||
</dd>
|
</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>
|
</dl>
|
||||||
|
|
||||||
# Ports
|
### 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
|
||||||
|
|
||||||
There are several Yjs-compatible ports to other programming languages.
|
There are several Yjs-compatible ports to other programming languages.
|
||||||
|
|
||||||
@ -246,6 +326,7 @@ language bindings to other languages
|
|||||||
* [yswift](https://github.com/y-crdt/yswift) - Swift binding
|
* [yswift](https://github.com/y-crdt/yswift) - Swift binding
|
||||||
* [yffi](https://github.com/y-crdt/y-crdt/tree/main/yffi) - C-FFI
|
* [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
|
* [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.
|
* [ycs](https://github.com/yjs/ycs) - .Net compatible C# implementation.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
@ -259,7 +340,7 @@ npm i yjs y-websocket
|
|||||||
Start the y-websocket server:
|
Start the y-websocket server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
PORT=1234 node ./node_modules/y-websocket/bin/server.js
|
PORT=1234 node ./node_modules/y-websocket/bin/server.cjs
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example: Observe types
|
### Example: Observe types
|
||||||
@ -360,6 +441,11 @@ necessary.
|
|||||||
</p>
|
</p>
|
||||||
<pre>const yarray = new Y.Array()</pre>
|
<pre>const yarray = new Y.Array()</pre>
|
||||||
<dl>
|
<dl>
|
||||||
|
<b><code>
|
||||||
|
Y.Array.from(Array<object|boolean|Array|string|number|null|Uint8Array|Y.Type>):
|
||||||
|
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>
|
<b><code>parent:Y.AbstractType|null</code></b>
|
||||||
<dd></dd>
|
<dd></dd>
|
||||||
<b><code>insert(index:number, content:Array<object|boolean|Array|string|number|null|Uint8Array|Y.Type>)</code></b>
|
<b><code>insert(index:number, content:Array<object|boolean|Array|string|number|null|Uint8Array|Y.Type>)</code></b>
|
||||||
@ -389,6 +475,11 @@ forEach(function(value:object|boolean|Array|string|number|null|Uint8Array|Y.Type
|
|||||||
<dd></dd>
|
<dd></dd>
|
||||||
<b><code>map(function(T, number, YArray):M):Array<M></code></b>
|
<b><code>map(function(T, number, YArray):M):Array<M></code></b>
|
||||||
<dd></dd>
|
<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<object|boolean|Array|string|number|null|Uint8Array|Y.Type></code></b>
|
<b><code>toArray():Array<object|boolean|Array|string|number|null|Uint8Array|Y.Type></code></b>
|
||||||
<dd>Copies the content of this YArray to a new Array.</dd>
|
<dd>Copies the content of this YArray to a new Array.</dd>
|
||||||
<b><code>toJSON():Array<Object|boolean|Array|string|number|null></code></b>
|
<b><code>toJSON():Array<Object|boolean|Array|string|number|null></code></b>
|
||||||
@ -445,8 +536,6 @@ or any of its children.
|
|||||||
<dd></dd>
|
<dd></dd>
|
||||||
<b><code>has(key:string):boolean</code></b>
|
<b><code>has(key:string):boolean</code></b>
|
||||||
<dd></dd>
|
<dd></dd>
|
||||||
<b><code>get(index:number)</code></b>
|
|
||||||
<dd></dd>
|
|
||||||
<b><code>clear()</code></b>
|
<b><code>clear()</code></b>
|
||||||
<dd>Removes all elements from this YMap.</dd>
|
<dd>Removes all elements from this YMap.</dd>
|
||||||
<b><code>clone():Y.Map</code></b>
|
<b><code>clone():Y.Map</code></b>
|
||||||
@ -800,7 +889,7 @@ doc1.getArray('myarray').insert(0, ['Hello doc2, you got this?'])
|
|||||||
doc2.getArray('myarray').get(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
|
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
|
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
|
exchange the complete document structure or only the differences by sending the
|
||||||
@ -1013,7 +1102,7 @@ encoding format for document updates. If you prefer JSON encoding, you can
|
|||||||
simply JSON.stringify / JSON.parse the relative position instead.
|
simply JSON.stringify / JSON.parse the relative position instead.
|
||||||
</dd>
|
</dd>
|
||||||
<b><code>Y.decodeRelativePosition(Uint8Array):RelativePosition</code></b>
|
<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>
|
</dl>
|
||||||
|
|
||||||
### Y.UndoManager
|
### Y.UndoManager
|
||||||
@ -1193,11 +1282,11 @@ More information about the specific implementation is available in
|
|||||||
|
|
||||||
CRDTs that are suitable for shared text editing suffer from the fact that they
|
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
|
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
|
intention preservation). Yjs implements many improvements to the original
|
||||||
algorithm that diminish the trade-off that the document only grows in size. We
|
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
|
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
|
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
|
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
|
don't care about the order of the structs anymore (e.g. if the parent was
|
||||||
|
142
funding.json
Normal file
142
funding.json
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
657
package-lock.json
generated
657
package-lock.json
generated
@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.6.14",
|
"version": "13.6.24",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.6.14",
|
"version": "13.6.24",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lib0": "^0.2.86"
|
"lib0": "^0.2.99"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^24.0.1",
|
"@rollup/plugin-commonjs": "^24.0.1",
|
||||||
@ -18,7 +18,7 @@
|
|||||||
"concurrently": "^3.6.1",
|
"concurrently": "^3.6.1",
|
||||||
"http-server": "^0.12.3",
|
"http-server": "^0.12.3",
|
||||||
"jsdoc": "^3.6.7",
|
"jsdoc": "^3.6.7",
|
||||||
"markdownlint-cli": "^0.23.2",
|
"markdownlint-cli": "^0.41.0",
|
||||||
"rollup": "^3.20.0",
|
"rollup": "^3.20.0",
|
||||||
"standard": "^16.0.4",
|
"standard": "^16.0.4",
|
||||||
"tui-jsdoc-template": "^1.2.2",
|
"tui-jsdoc-template": "^1.2.2",
|
||||||
@ -166,12 +166,89 @@
|
|||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
"version": "1.4.15",
|
"version": "1.4.15",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/@rollup/plugin-commonjs": {
|
||||||
"version": "24.1.0",
|
"version": "24.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.1.0.tgz",
|
||||||
@ -773,13 +850,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/deep-extend": {
|
"node_modules/deep-extend": {
|
||||||
"version": "0.5.1",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||||
"integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==",
|
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"iojs": ">=1.0.0",
|
"node": ">=4.0.0"
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/deep-is": {
|
"node_modules/deep-is": {
|
||||||
@ -882,6 +958,12 @@
|
|||||||
"domelementtype": "1"
|
"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": {
|
"node_modules/ecstatic": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz",
|
||||||
@ -1791,6 +1873,22 @@
|
|||||||
"is-callable": "^1.1.3"
|
"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": {
|
"node_modules/fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
@ -1873,12 +1971,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/get-stdin": {
|
"node_modules/get-stdin": {
|
||||||
"version": "5.0.1",
|
"version": "9.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
|
||||||
"integrity": "sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA==",
|
"integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12.0"
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/get-symbol-description": {
|
"node_modules/get-symbol-description": {
|
||||||
@ -1977,12 +2078,6 @@
|
|||||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/has": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
|
||||||
@ -2148,9 +2243,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.1.9",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||||
"integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==",
|
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
@ -2198,10 +2293,13 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/ini": {
|
"node_modules/ini": {
|
||||||
"version": "1.3.8",
|
"version": "4.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz",
|
||||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
"integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/internal-slot": {
|
"node_modules/internal-slot": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
@ -2499,6 +2597,21 @@
|
|||||||
"url": "https://github.com/sponsors/dmonad"
|
"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": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@ -2611,11 +2724,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jsonc-parser": {
|
"node_modules/jsonc-parser": {
|
||||||
"version": "2.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
|
||||||
"integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==",
|
"integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/jsx-ast-utils": {
|
||||||
"version": "3.3.5",
|
"version": "3.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
||||||
@ -2663,13 +2785,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lib0": {
|
"node_modules/lib0": {
|
||||||
"version": "0.2.88",
|
"version": "0.2.99",
|
||||||
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.88.tgz",
|
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.99.tgz",
|
||||||
"integrity": "sha512-KyroiEvCeZcZEMx5Ys+b4u4eEBbA1ch7XUaBhYpwa/nPMrzTjUhI4RfcytmQfYoTBPcdyx+FX6WFNIoNuJzJfQ==",
|
"integrity": "sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"isomorphic.js": "^0.2.4"
|
"isomorphic.js": "^0.2.4"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
"0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js",
|
||||||
"0gentesthtml": "bin/gentesthtml.js",
|
"0gentesthtml": "bin/gentesthtml.js",
|
||||||
"0serve": "bin/0serve.js"
|
"0serve": "bin/0serve.js"
|
||||||
},
|
},
|
||||||
@ -2742,12 +2865,6 @@
|
|||||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/lodash.filter": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
|
||||||
@ -2871,145 +2988,164 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint": {
|
"node_modules/markdownlint": {
|
||||||
"version": "0.20.4",
|
"version": "0.34.0",
|
||||||
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.20.4.tgz",
|
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.34.0.tgz",
|
||||||
"integrity": "sha512-jpfaPgjT0OpeBbemjYNZbzGG3hCLcAIvrm/pEY3+q/szDScG6ZonDacqySVRJAv9glbo8y4wBPJ0wgW17+9GGA==",
|
"integrity": "sha512-qwGyuyKwjkEMOJ10XN6OTKNOVYvOIi35RNvDLNxTof5s8UmyGHlCdpngRHoRGNvQVGuxO3BJ7uNSgdeX166WXw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"markdown-it": "10.0.0"
|
"markdown-it": "14.1.0",
|
||||||
|
"markdownlint-micromark": "0.1.9"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/DavidAnson"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint-cli": {
|
"node_modules/markdownlint-cli": {
|
||||||
"version": "0.23.2",
|
"version": "0.41.0",
|
||||||
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.23.2.tgz",
|
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.41.0.tgz",
|
||||||
"integrity": "sha512-OSl5OZ8xzGN6z355cqRkiq67zPi3reJimklaF72p0554q85Dng5ToOjjSB9tDKZebSt85jX8cp+ruoQlPqOsPA==",
|
"integrity": "sha512-kp29tKrMKdn+xonfefjp3a/MsNzAd9c5ke0ydMEI9PR98bOjzglYN4nfMSaIs69msUf1DNkgevAIAPtK2SeX0Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "~2.9.0",
|
"commander": "~12.1.0",
|
||||||
"deep-extend": "~0.5.1",
|
"get-stdin": "~9.0.0",
|
||||||
"get-stdin": "~5.0.1",
|
"glob": "~10.4.1",
|
||||||
"glob": "~7.1.2",
|
"ignore": "~5.3.1",
|
||||||
"ignore": "~5.1.4",
|
"js-yaml": "^4.1.0",
|
||||||
"js-yaml": "~3.13.1",
|
"jsonc-parser": "~3.2.1",
|
||||||
"jsonc-parser": "~2.2.0",
|
"jsonpointer": "5.0.1",
|
||||||
"lodash.differencewith": "~4.5.0",
|
"markdownlint": "~0.34.0",
|
||||||
"lodash.flatten": "~4.4.0",
|
"minimatch": "~9.0.4",
|
||||||
"markdownlint": "~0.20.4",
|
"run-con": "~1.3.2",
|
||||||
"markdownlint-rule-helpers": "~0.11.0",
|
"smol-toml": "~1.2.0"
|
||||||
"minimatch": "~3.0.4",
|
|
||||||
"minimist": "~1.2.5",
|
|
||||||
"rc": "~1.2.7"
|
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"markdownlint": "markdownlint.js"
|
"markdownlint": "markdownlint.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=18"
|
||||||
}
|
|
||||||
},
|
|
||||||
"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": {
|
"node_modules/markdownlint-cli/node_modules/commander": {
|
||||||
"version": "2.9.0",
|
"version": "12.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||||
"integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==",
|
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
|
||||||
"graceful-readlink": ">= 1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6.x"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint-cli/node_modules/glob": {
|
"node_modules/markdownlint-cli/node_modules/glob": {
|
||||||
"version": "7.1.7",
|
"version": "10.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||||
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
|
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs.realpath": "^1.0.0",
|
"foreground-child": "^3.1.0",
|
||||||
"inflight": "^1.0.4",
|
"jackspeak": "^3.1.2",
|
||||||
"inherits": "2",
|
"minimatch": "^9.0.4",
|
||||||
"minimatch": "^3.0.4",
|
"minipass": "^7.1.2",
|
||||||
"once": "^1.3.0",
|
"package-json-from-dist": "^1.0.0",
|
||||||
"path-is-absolute": "^1.0.0"
|
"path-scurry": "^1.11.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"bin": {
|
||||||
"node": "*"
|
"glob": "dist/esm/bin.mjs"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint-cli/node_modules/minimatch": {
|
"node_modules/markdownlint-cli/node_modules/js-yaml": {
|
||||||
"version": "3.0.8",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
"integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==",
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"argparse": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"bin": {
|
||||||
"node": "*"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint-rule-helpers": {
|
"node_modules/markdownlint-cli/node_modules/minimatch": {
|
||||||
"version": "0.11.0",
|
"version": "9.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
"integrity": "sha512-PhGii9dOiDJDXxiRMpK8N0FM9powprvRPsXALgkjlSPTwLh6ymH+iF3iUe3nq8KGu26tclFBlLL5xAGy/zb7FA==",
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"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,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sprintf-js": "~1.0.2"
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/DavidAnson"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint/node_modules/entities": {
|
"node_modules/markdownlint/node_modules/entities": {
|
||||||
"version": "2.0.3",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint/node_modules/linkify-it": {
|
"node_modules/markdownlint/node_modules/linkify-it": {
|
||||||
"version": "2.2.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||||
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
|
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"uc.micro": "^1.0.1"
|
"uc.micro": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint/node_modules/markdown-it": {
|
"node_modules/markdownlint/node_modules/markdown-it": {
|
||||||
"version": "10.0.0",
|
"version": "14.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
||||||
"integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
|
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^2.0.1",
|
||||||
"entities": "~2.0.0",
|
"entities": "^4.4.0",
|
||||||
"linkify-it": "^2.0.0",
|
"linkify-it": "^5.0.0",
|
||||||
"mdurl": "^1.0.1",
|
"mdurl": "^2.0.0",
|
||||||
"uc.micro": "^1.0.5"
|
"punycode.js": "^2.3.1",
|
||||||
|
"uc.micro": "^2.1.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"markdown-it": "bin/markdown-it.js"
|
"markdown-it": "bin/markdown-it.mjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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": {
|
"node_modules/marked": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz",
|
||||||
@ -3061,6 +3197,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"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": {
|
"node_modules/mkdirp": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||||
@ -3280,6 +3425,12 @@
|
|||||||
"node": ">=4"
|
"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": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@ -3338,6 +3489,28 @@
|
|||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/path-type": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
||||||
@ -3555,6 +3728,15 @@
|
|||||||
"node": ">=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": {
|
"node_modules/qs": {
|
||||||
"version": "6.11.2",
|
"version": "6.11.2",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
|
||||||
@ -3570,39 +3752,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"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": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
@ -3802,6 +3951,21 @@
|
|||||||
"fsevents": "~2.3.2"
|
"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": {
|
"node_modules/rx": {
|
||||||
"version": "2.3.24",
|
"version": "2.3.24",
|
||||||
"resolved": "https://registry.npmjs.org/rx/-/rx-2.3.24.tgz",
|
"resolved": "https://registry.npmjs.org/rx/-/rx-2.3.24.tgz",
|
||||||
@ -3948,6 +4112,18 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"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": {
|
"node_modules/slice-ansi": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
|
||||||
@ -3998,6 +4174,15 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/spawn-command": {
|
||||||
"version": "0.0.2-1",
|
"version": "0.0.2-1",
|
||||||
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
|
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
|
||||||
@ -4142,6 +4327,21 @@
|
|||||||
"node": ">=8"
|
"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": {
|
"node_modules/string.prototype.matchall": {
|
||||||
"version": "4.0.10",
|
"version": "4.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
|
||||||
@ -4219,6 +4419,19 @@
|
|||||||
"node": ">=8"
|
"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": {
|
"node_modules/strip-bom": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||||
@ -4575,6 +4788,136 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"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": {
|
"node_modules/wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "13.6.14",
|
"version": "13.6.24",
|
||||||
"description": "Shared Editing Library",
|
"description": "Shared Editing Library",
|
||||||
"main": "./dist/yjs.cjs",
|
"main": "./dist/yjs.cjs",
|
||||||
"module": "./dist/yjs.mjs",
|
"module": "./dist/yjs.mjs",
|
||||||
@ -13,7 +13,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -rf dist docs",
|
"clean": "rm -rf dist docs",
|
||||||
"test": "npm run dist && node ./dist/tests.cjs --repetition-time 50",
|
"test": "npm run dist && NODE_ENV=development node ./dist/tests.cjs --repetition-time 50",
|
||||||
"test-extensive": "npm run lint && npm run dist && node ./dist/tests.cjs --production --repetition-time 10000",
|
"test-extensive": "npm run lint && npm run dist && node ./dist/tests.cjs --production --repetition-time 10000",
|
||||||
"dist": "npm run clean && rollup -c && tsc",
|
"dist": "npm run clean && rollup -c && tsc",
|
||||||
"watch": "rollup -wc",
|
"watch": "rollup -wc",
|
||||||
@ -76,7 +76,7 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://docs.yjs.dev",
|
"homepage": "https://docs.yjs.dev",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lib0": "^0.2.86"
|
"lib0": "^0.2.99"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^24.0.1",
|
"@rollup/plugin-commonjs": "^24.0.1",
|
||||||
@ -85,7 +85,7 @@
|
|||||||
"concurrently": "^3.6.1",
|
"concurrently": "^3.6.1",
|
||||||
"http-server": "^0.12.3",
|
"http-server": "^0.12.3",
|
||||||
"jsdoc": "^3.6.7",
|
"jsdoc": "^3.6.7",
|
||||||
"markdownlint-cli": "^0.23.2",
|
"markdownlint-cli": "^0.41.0",
|
||||||
"rollup": "^3.20.0",
|
"rollup": "^3.20.0",
|
||||||
"standard": "^16.0.4",
|
"standard": "^16.0.4",
|
||||||
"tui-jsdoc-template": "^1.2.2",
|
"tui-jsdoc-template": "^1.2.2",
|
||||||
|
@ -50,6 +50,8 @@ export {
|
|||||||
findRootTypeKey,
|
findRootTypeKey,
|
||||||
findIndexSS,
|
findIndexSS,
|
||||||
getItem,
|
getItem,
|
||||||
|
getItemCleanStart,
|
||||||
|
getItemCleanEnd,
|
||||||
typeListToArraySnapshot,
|
typeListToArraySnapshot,
|
||||||
typeMapGetSnapshot,
|
typeMapGetSnapshot,
|
||||||
typeMapGetAllSnapshot,
|
typeMapGetAllSnapshot,
|
||||||
@ -100,6 +102,7 @@ export {
|
|||||||
UpdateDecoderV1,
|
UpdateDecoderV1,
|
||||||
UpdateDecoderV2,
|
UpdateDecoderV2,
|
||||||
equalDeleteSets,
|
equalDeleteSets,
|
||||||
|
mergeDeleteSets,
|
||||||
snapshotContainsUpdate
|
snapshotContainsUpdate
|
||||||
} from './internals.js'
|
} from './internals.js'
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export class AbstractStruct {
|
|||||||
* This method is already assuming that `this.id.clock + this.length === this.id.clock`.
|
* This method is already assuming that `this.id.clock + this.length === this.id.clock`.
|
||||||
* Also this method does *not* remove right from StructStore!
|
* Also this method does *not* remove right from StructStore!
|
||||||
* @param {AbstractStruct} right
|
* @param {AbstractStruct} right
|
||||||
* @return {boolean} wether this merged with right
|
* @return {boolean} whether this merged with right
|
||||||
*/
|
*/
|
||||||
mergeWith (right) {
|
mergeWith (right) {
|
||||||
return false
|
return false
|
||||||
|
@ -2,6 +2,11 @@ import {
|
|||||||
UpdateEncoderV1, UpdateEncoderV2, UpdateDecoderV1, UpdateDecoderV2, Transaction, Item, StructStore // eslint-disable-line
|
UpdateEncoderV1, UpdateEncoderV2, UpdateDecoderV1, UpdateDecoderV2, Transaction, Item, StructStore // eslint-disable-line
|
||||||
} from '../internals.js'
|
} 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 {
|
export class ContentAny {
|
||||||
/**
|
/**
|
||||||
* @param {Array<any>} arr
|
* @param {Array<any>} arr
|
||||||
@ -11,6 +16,7 @@ export class ContentAny {
|
|||||||
* @type {Array<any>}
|
* @type {Array<any>}
|
||||||
*/
|
*/
|
||||||
this.arr = arr
|
this.arr = arr
|
||||||
|
isDevMode && object.deepFreeze(arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -393,8 +393,7 @@ export class Item extends AbstractStruct {
|
|||||||
if (this.left && this.left.constructor === Item) {
|
if (this.left && this.left.constructor === Item) {
|
||||||
this.parent = this.left.parent
|
this.parent = this.left.parent
|
||||||
this.parentSub = this.left.parentSub
|
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.parent = this.right.parent
|
||||||
this.parentSub = this.right.parentSub
|
this.parentSub = this.right.parentSub
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,12 @@ import * as map from 'lib0/map'
|
|||||||
import * as iterator from 'lib0/iterator'
|
import * as iterator from 'lib0/iterator'
|
||||||
import * as error from 'lib0/error'
|
import * as error from 'lib0/error'
|
||||||
import * as math from 'lib0/math'
|
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
|
const maxSearchMarker = 80
|
||||||
|
|
||||||
@ -149,11 +155,11 @@ export const findMarker = (yarray, index) => {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// if (marker) {
|
// if (marker) {
|
||||||
// if (window.lengthes == null) {
|
// if (window.lengths == null) {
|
||||||
// window.lengthes = []
|
// window.lengths = []
|
||||||
// window.getLengthes = () => window.lengthes.sort((a, b) => a - b)
|
// 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)
|
// 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) {
|
if (marker !== null && math.abs(marker.index - pindex) < /** @type {YText|YArray<any>} */ (p.parent).length / maxSearchMarker) {
|
||||||
@ -215,6 +221,7 @@ export const updateMarkerChanges = (searchMarker, index, len) => {
|
|||||||
* @return {Array<Item>}
|
* @return {Array<Item>}
|
||||||
*/
|
*/
|
||||||
export const getTypeChildren = t => {
|
export const getTypeChildren = t => {
|
||||||
|
t.doc ?? warnPrematureAccess()
|
||||||
let s = t._start
|
let s = t._start
|
||||||
const arr = []
|
const arr = []
|
||||||
while (s) {
|
while (s) {
|
||||||
@ -316,6 +323,10 @@ export class AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Makes a copy of this data type that can be included somewhere else.
|
||||||
|
*
|
||||||
|
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||||||
|
*
|
||||||
* @return {AbstractType<EventType>}
|
* @return {AbstractType<EventType>}
|
||||||
*/
|
*/
|
||||||
clone () {
|
clone () {
|
||||||
@ -404,6 +415,7 @@ export class AbstractType {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const typeListSlice = (type, start, end) => {
|
export const typeListSlice = (type, start, end) => {
|
||||||
|
type.doc ?? warnPrematureAccess()
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
start = type._length + start
|
start = type._length + start
|
||||||
}
|
}
|
||||||
@ -439,6 +451,7 @@ export const typeListSlice = (type, start, end) => {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const typeListToArray = type => {
|
export const typeListToArray = type => {
|
||||||
|
type.doc ?? warnPrematureAccess()
|
||||||
const cs = []
|
const cs = []
|
||||||
let n = type._start
|
let n = type._start
|
||||||
while (n !== null) {
|
while (n !== null) {
|
||||||
@ -477,7 +490,7 @@ export const typeListToArraySnapshot = (type, snapshot) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a provided function on once on overy element of this YArray.
|
* Executes a provided function on once on every element of this YArray.
|
||||||
*
|
*
|
||||||
* @param {AbstractType<any>} type
|
* @param {AbstractType<any>} type
|
||||||
* @param {function(any,number,any):void} f A function to execute on every element of this YArray.
|
* @param {function(any,number,any):void} f A function to execute on every element of this YArray.
|
||||||
@ -488,6 +501,7 @@ export const typeListToArraySnapshot = (type, snapshot) => {
|
|||||||
export const typeListForEach = (type, f) => {
|
export const typeListForEach = (type, f) => {
|
||||||
let index = 0
|
let index = 0
|
||||||
let n = type._start
|
let n = type._start
|
||||||
|
type.doc ?? warnPrematureAccess()
|
||||||
while (n !== null) {
|
while (n !== null) {
|
||||||
if (n.countable && !n.deleted) {
|
if (n.countable && !n.deleted) {
|
||||||
const c = n.content.getContent()
|
const c = n.content.getContent()
|
||||||
@ -569,7 +583,7 @@ export const typeListCreateIterator = type => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a provided function on once on overy element of this YArray.
|
* Executes a provided function on once on every element of this YArray.
|
||||||
* Operates on a snapshotted state of the document.
|
* Operates on a snapshotted state of the document.
|
||||||
*
|
*
|
||||||
* @param {AbstractType<any>} type
|
* @param {AbstractType<any>} type
|
||||||
@ -602,6 +616,7 @@ export const typeListForEachSnapshot = (type, f, snapshot) => {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const typeListGet = (type, index) => {
|
export const typeListGet = (type, index) => {
|
||||||
|
type.doc ?? warnPrematureAccess()
|
||||||
const marker = findMarker(type, index)
|
const marker = findMarker(type, index)
|
||||||
let n = type._start
|
let n = type._start
|
||||||
if (marker !== null) {
|
if (marker !== null) {
|
||||||
@ -736,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
|
* 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 {Transaction} transaction
|
||||||
* @param {AbstractType<any>} parent
|
* @param {AbstractType<any>} parent
|
||||||
@ -870,6 +885,7 @@ export const typeMapSet = (transaction, parent, key, value) => {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const typeMapGet = (parent, key) => {
|
export const typeMapGet = (parent, key) => {
|
||||||
|
parent.doc ?? warnPrematureAccess()
|
||||||
const val = parent._map.get(key)
|
const val = parent._map.get(key)
|
||||||
return val !== undefined && !val.deleted ? val.content.getContent()[val.length - 1] : undefined
|
return val !== undefined && !val.deleted ? val.content.getContent()[val.length - 1] : undefined
|
||||||
}
|
}
|
||||||
@ -886,6 +902,7 @@ export const typeMapGetAll = (parent) => {
|
|||||||
* @type {Object<string,any>}
|
* @type {Object<string,any>}
|
||||||
*/
|
*/
|
||||||
const res = {}
|
const res = {}
|
||||||
|
parent.doc ?? warnPrematureAccess()
|
||||||
parent._map.forEach((value, key) => {
|
parent._map.forEach((value, key) => {
|
||||||
if (!value.deleted) {
|
if (!value.deleted) {
|
||||||
res[key] = value.content.getContent()[value.length - 1]
|
res[key] = value.content.getContent()[value.length - 1]
|
||||||
@ -903,6 +920,7 @@ export const typeMapGetAll = (parent) => {
|
|||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const typeMapHas = (parent, key) => {
|
export const typeMapHas = (parent, key) => {
|
||||||
|
parent.doc ?? warnPrematureAccess()
|
||||||
const val = parent._map.get(key)
|
const val = parent._map.get(key)
|
||||||
return val !== undefined && !val.deleted
|
return val !== undefined && !val.deleted
|
||||||
}
|
}
|
||||||
@ -953,10 +971,13 @@ export const typeMapGetAllSnapshot = (parent, snapshot) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Map<string,Item>} map
|
* @param {AbstractType<any> & { _map: Map<string, Item> }} type
|
||||||
* @return {IterableIterator<Array<any>>}
|
* @return {IterableIterator<Array<any>>}
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const createMapIterator = map => iterator.iteratorFilter(map.entries(), /** @param {any} entry */ entry => !entry[1].deleted)
|
export const createMapIterator = type => {
|
||||||
|
type.doc ?? warnPrematureAccess()
|
||||||
|
return iterator.iteratorFilter(type._map.entries(), /** @param {any} entry */ entry => !entry[1].deleted)
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
YArrayRefID,
|
YArrayRefID,
|
||||||
callTypeObservers,
|
callTypeObservers,
|
||||||
transact,
|
transact,
|
||||||
|
warnPrematureAccess,
|
||||||
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
|
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
import { typeListSlice } from './AbstractType.js'
|
import { typeListSlice } from './AbstractType.js'
|
||||||
@ -25,16 +26,7 @@ import { typeListSlice } from './AbstractType.js'
|
|||||||
* @template T
|
* @template T
|
||||||
* @extends YEvent<YArray<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.
|
* A shared Array implementation.
|
||||||
@ -95,6 +87,10 @@ export class YArray extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Makes a copy of this data type that can be included somewhere else.
|
||||||
|
*
|
||||||
|
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||||||
|
*
|
||||||
* @return {YArray<T>}
|
* @return {YArray<T>}
|
||||||
*/
|
*/
|
||||||
clone () {
|
clone () {
|
||||||
@ -109,7 +105,8 @@ export class YArray extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get length () {
|
get length () {
|
||||||
return this._prelimContent === null ? this._length : this._prelimContent.length
|
this.doc ?? warnPrematureAccess()
|
||||||
|
return this._length
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,9 +164,9 @@ export class YArray extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preppends content to this YArray.
|
* Prepends content to this YArray.
|
||||||
*
|
*
|
||||||
* @param {Array<T>} content Array of content to preppend.
|
* @param {Array<T>} content Array of content to prepend.
|
||||||
*/
|
*/
|
||||||
unshift (content) {
|
unshift (content) {
|
||||||
this.insert(0, content)
|
this.insert(0, content)
|
||||||
@ -211,7 +208,8 @@ export class YArray extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms this YArray to a JavaScript Array.
|
* Returns a portion of this YArray into a JavaScript Array selected
|
||||||
|
* from start to end (end not included).
|
||||||
*
|
*
|
||||||
* @param {number} [start]
|
* @param {number} [start]
|
||||||
* @param {number} [end]
|
* @param {number} [end]
|
||||||
@ -244,7 +242,7 @@ export class YArray extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a provided function once on overy element of this YArray.
|
* Executes a provided function once on every element of this YArray.
|
||||||
*
|
*
|
||||||
* @param {function(T,number,YArray<T>):void} f A function to execute on every element of this YArray.
|
* @param {function(T,number,YArray<T>):void} f A function to execute on every element of this YArray.
|
||||||
*/
|
*/
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
YMapRefID,
|
YMapRefID,
|
||||||
callTypeObservers,
|
callTypeObservers,
|
||||||
transact,
|
transact,
|
||||||
|
warnPrematureAccess,
|
||||||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
|
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Transaction, Item // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
|
|
||||||
@ -88,6 +89,10 @@ export class YMap extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Makes a copy of this data type that can be included somewhere else.
|
||||||
|
*
|
||||||
|
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||||||
|
*
|
||||||
* @return {YMap<MapType>}
|
* @return {YMap<MapType>}
|
||||||
*/
|
*/
|
||||||
clone () {
|
clone () {
|
||||||
@ -117,6 +122,7 @@ export class YMap extends AbstractType {
|
|||||||
* @return {Object<string,any>}
|
* @return {Object<string,any>}
|
||||||
*/
|
*/
|
||||||
toJSON () {
|
toJSON () {
|
||||||
|
this.doc ?? warnPrematureAccess()
|
||||||
/**
|
/**
|
||||||
* @type {Object<string,MapType>}
|
* @type {Object<string,MapType>}
|
||||||
*/
|
*/
|
||||||
@ -136,7 +142,7 @@ export class YMap extends AbstractType {
|
|||||||
* @return {number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
get size () {
|
get size () {
|
||||||
return [...createMapIterator(this._map)].length
|
return [...createMapIterator(this)].length
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,7 +151,7 @@ export class YMap extends AbstractType {
|
|||||||
* @return {IterableIterator<string>}
|
* @return {IterableIterator<string>}
|
||||||
*/
|
*/
|
||||||
keys () {
|
keys () {
|
||||||
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => v[0])
|
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => v[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,7 +160,7 @@ export class YMap extends AbstractType {
|
|||||||
* @return {IterableIterator<MapType>}
|
* @return {IterableIterator<MapType>}
|
||||||
*/
|
*/
|
||||||
values () {
|
values () {
|
||||||
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => v[1].content.getContent()[v[1].length - 1])
|
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => v[1].content.getContent()[v[1].length - 1])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,7 +169,7 @@ export class YMap extends AbstractType {
|
|||||||
* @return {IterableIterator<[string, MapType]>}
|
* @return {IterableIterator<[string, MapType]>}
|
||||||
*/
|
*/
|
||||||
entries () {
|
entries () {
|
||||||
return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => /** @type {any} */ ([v[0], v[1].content.getContent()[v[1].length - 1]]))
|
return iterator.iteratorMap(createMapIterator(this), /** @param {any} v */ v => /** @type {any} */ ([v[0], v[1].content.getContent()[v[1].length - 1]]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,6 +178,7 @@ export class YMap extends AbstractType {
|
|||||||
* @param {function(MapType,string,YMap<MapType>):void} f A function to execute on every element of this YArray.
|
* @param {function(MapType,string,YMap<MapType>):void} f A function to execute on every element of this YArray.
|
||||||
*/
|
*/
|
||||||
forEach (f) {
|
forEach (f) {
|
||||||
|
this.doc ?? warnPrematureAccess()
|
||||||
this._map.forEach((item, key) => {
|
this._map.forEach((item, key) => {
|
||||||
if (!item.deleted) {
|
if (!item.deleted) {
|
||||||
f(item.content.getContent()[item.length - 1], key, this)
|
f(item.content.getContent()[item.length - 1], key, this)
|
||||||
|
@ -26,6 +26,7 @@ import {
|
|||||||
typeMapGetAll,
|
typeMapGetAll,
|
||||||
updateMarkerChanges,
|
updateMarkerChanges,
|
||||||
ContentType,
|
ContentType,
|
||||||
|
warnPrematureAccess,
|
||||||
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
|
ArraySearchMarker, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, ID, Doc, Item, Snapshot, Transaction // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
|
|
||||||
@ -477,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.
|
* formatting attributes.
|
||||||
*
|
*
|
||||||
* @param {Transaction} transaction
|
* @param {Transaction} transaction
|
||||||
@ -567,7 +568,7 @@ const deleteText = (transaction, currPos, length) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The Quill Delta format represents changes on a text document with
|
* 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
|
* @example
|
||||||
* {
|
* {
|
||||||
@ -875,6 +876,7 @@ export class YText extends AbstractType {
|
|||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
get length () {
|
get length () {
|
||||||
|
this.doc ?? warnPrematureAccess()
|
||||||
return this._length
|
return this._length
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,6 +899,10 @@ export class YText extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Makes a copy of this data type that can be included somewhere else.
|
||||||
|
*
|
||||||
|
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||||||
|
*
|
||||||
* @return {YText}
|
* @return {YText}
|
||||||
*/
|
*/
|
||||||
clone () {
|
clone () {
|
||||||
@ -927,6 +933,7 @@ export class YText extends AbstractType {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
toString () {
|
toString () {
|
||||||
|
this.doc ?? warnPrematureAccess()
|
||||||
let str = ''
|
let str = ''
|
||||||
/**
|
/**
|
||||||
* @type {Item|null}
|
* @type {Item|null}
|
||||||
@ -954,7 +961,7 @@ export class YText extends AbstractType {
|
|||||||
/**
|
/**
|
||||||
* Apply a {@link Delta} on this shared YText type.
|
* 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 {object} opts
|
||||||
* @param {boolean} [opts.sanitize] Sanitize input delta. Removes ending newlines if set to true.
|
* @param {boolean} [opts.sanitize] Sanitize input delta. Removes ending newlines if set to true.
|
||||||
*
|
*
|
||||||
@ -1000,6 +1007,7 @@ export class YText extends AbstractType {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
toDelta (snapshot, prevSnapshot, computeYChange) {
|
toDelta (snapshot, prevSnapshot, computeYChange) {
|
||||||
|
this.doc ?? warnPrematureAccess()
|
||||||
/**
|
/**
|
||||||
* @type{Array<any>}
|
* @type{Array<any>}
|
||||||
*/
|
*/
|
||||||
|
@ -81,6 +81,10 @@ export class YXmlElement extends YXmlFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Makes a copy of this data type that can be included somewhere else.
|
||||||
|
*
|
||||||
|
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||||||
|
*
|
||||||
* @return {YXmlElement<KV>}
|
* @return {YXmlElement<KV>}
|
||||||
*/
|
*/
|
||||||
clone () {
|
clone () {
|
||||||
|
@ -12,7 +12,7 @@ export class YXmlEvent extends YEvent {
|
|||||||
* @param {YXmlElement|YXmlText|YXmlFragment} target The target on which the event is created.
|
* @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
|
* @param {Set<string|null>} subs The set of changed attributes. `null` is included if the
|
||||||
* child list changed.
|
* child list changed.
|
||||||
* @param {Transaction} transaction The transaction instance with wich the
|
* @param {Transaction} transaction The transaction instance with which the
|
||||||
* change was created.
|
* change was created.
|
||||||
*/
|
*/
|
||||||
constructor (target, subs, transaction) {
|
constructor (target, subs, transaction) {
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
transact,
|
transact,
|
||||||
typeListGet,
|
typeListGet,
|
||||||
typeListSlice,
|
typeListSlice,
|
||||||
|
warnPrematureAccess,
|
||||||
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, ContentType, Transaction, Item, YXmlText, YXmlHook // eslint-disable-line
|
UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, ContentType, Transaction, Item, YXmlText, YXmlHook // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ export class YXmlTreeWalker {
|
|||||||
*/
|
*/
|
||||||
this._currentNode = /** @type {Item} */ (root._start)
|
this._currentNode = /** @type {Item} */ (root._start)
|
||||||
this._firstCall = true
|
this._firstCall = true
|
||||||
|
root.doc ?? warnPrematureAccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
[Symbol.iterator] () {
|
[Symbol.iterator] () {
|
||||||
@ -94,8 +96,12 @@ export class YXmlTreeWalker {
|
|||||||
} else {
|
} else {
|
||||||
// walk right or up in the tree
|
// walk right or up in the tree
|
||||||
while (n !== null) {
|
while (n !== null) {
|
||||||
if (n.right !== null) {
|
/**
|
||||||
n = n.right
|
* @type {Item | null}
|
||||||
|
*/
|
||||||
|
const nxt = n.next
|
||||||
|
if (nxt !== null) {
|
||||||
|
n = nxt
|
||||||
break
|
break
|
||||||
} else if (n.parent === this._root) {
|
} else if (n.parent === this._root) {
|
||||||
n = null
|
n = null
|
||||||
@ -163,6 +169,10 @@ export class YXmlFragment extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Makes a copy of this data type that can be included somewhere else.
|
||||||
|
*
|
||||||
|
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||||||
|
*
|
||||||
* @return {YXmlFragment}
|
* @return {YXmlFragment}
|
||||||
*/
|
*/
|
||||||
clone () {
|
clone () {
|
||||||
@ -173,6 +183,7 @@ export class YXmlFragment extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get length () {
|
get length () {
|
||||||
|
this.doc ?? warnPrematureAccess()
|
||||||
return this._prelimContent === null ? this._length : this._prelimContent.length
|
return this._prelimContent === null ? this._length : this._prelimContent.length
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,9 +387,9 @@ export class YXmlFragment extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preppends content to this YArray.
|
* Prepends content to this YArray.
|
||||||
*
|
*
|
||||||
* @param {Array<YXmlElement|YXmlText>} content Array of content to preppend.
|
* @param {Array<YXmlElement|YXmlText>} content Array of content to prepend.
|
||||||
*/
|
*/
|
||||||
unshift (content) {
|
unshift (content) {
|
||||||
this.insert(0, content)
|
this.insert(0, content)
|
||||||
@ -395,7 +406,8 @@ export class YXmlFragment extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms this YArray to a JavaScript Array.
|
* Returns a portion of this YXmlFragment into a JavaScript Array selected
|
||||||
|
* from start to end (end not included).
|
||||||
*
|
*
|
||||||
* @param {number} [start]
|
* @param {number} [start]
|
||||||
* @param {number} [end]
|
* @param {number} [end]
|
||||||
@ -406,7 +418,7 @@ export class YXmlFragment extends AbstractType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a provided function on once on overy child element.
|
* Executes a provided function on once on every child element.
|
||||||
*
|
*
|
||||||
* @param {function(YXmlElement|YXmlText,number, typeof self):void} f A function to execute on every element of this YArray.
|
* @param {function(YXmlElement|YXmlText,number, typeof self):void} f A function to execute on every element of this YArray.
|
||||||
*/
|
*/
|
||||||
|
@ -29,6 +29,10 @@ export class YXmlHook extends YMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Makes a copy of this data type that can be included somewhere else.
|
||||||
|
*
|
||||||
|
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||||||
|
*
|
||||||
* @return {YXmlHook}
|
* @return {YXmlHook}
|
||||||
*/
|
*/
|
||||||
clone () {
|
clone () {
|
||||||
|
@ -30,6 +30,10 @@ export class YXmlText extends YText {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Makes a copy of this data type that can be included somewhere else.
|
||||||
|
*
|
||||||
|
* Note that the content is only readable _after_ it has been included somewhere in the Ydoc.
|
||||||
|
*
|
||||||
* @return {YXmlText}
|
* @return {YXmlText}
|
||||||
*/
|
*/
|
||||||
clone () {
|
clone () {
|
||||||
|
@ -104,8 +104,9 @@ export class Doc extends ObservableV2 {
|
|||||||
* lost (with false as a parameter).
|
* lost (with false as a parameter).
|
||||||
*/
|
*/
|
||||||
this.isSynced = false
|
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.whenLoaded = promise.create(resolve => {
|
||||||
this.on('load', () => {
|
this.on('load', () => {
|
||||||
@ -187,22 +188,22 @@ export class Doc extends ObservableV2 {
|
|||||||
/**
|
/**
|
||||||
* Define a shared data type.
|
* Define a shared data type.
|
||||||
*
|
*
|
||||||
* Multiple calls of `y.get(name, TypeConstructor)` yield the same result
|
* Multiple calls of `ydoc.get(name, TypeConstructor)` yield the same result
|
||||||
* and do not overwrite each other. I.e.
|
* and do not overwrite each other. I.e.
|
||||||
* `y.define(name, Y.Array) === y.define(name, Y.Array)`
|
* `ydoc.get(name, Y.Array) === ydoc.get(name, Y.Array)`
|
||||||
*
|
*
|
||||||
* After this method is called, the type is also available on `y.share.get(name)`.
|
* After this method is called, the type is also available on `ydoc.share.get(name)`.
|
||||||
*
|
*
|
||||||
* *Best Practices:*
|
* *Best Practices:*
|
||||||
* Define all types right after the Yjs instance is created and store them in a separate object.
|
* Define all types right after the Y.Doc instance is created and store them in a separate object.
|
||||||
* Also use the typed methods `getText(name)`, `getArray(name)`, ..
|
* Also use the typed methods `getText(name)`, `getArray(name)`, ..
|
||||||
*
|
*
|
||||||
* @template {typeof AbstractType<any>} Type
|
* @template {typeof AbstractType<any>} Type
|
||||||
* @example
|
* @example
|
||||||
* const y = new Y(..)
|
* const ydoc = new Y.Doc(..)
|
||||||
* const appState = {
|
* const appState = {
|
||||||
* document: y.getText('document')
|
* document: ydoc.getText('document')
|
||||||
* comments: y.getArray('comments')
|
* comments: ydoc.getArray('comments')
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @param {string} name
|
* @param {string} name
|
||||||
@ -322,6 +323,7 @@ export class Doc extends ObservableV2 {
|
|||||||
* Emit `destroy` event and unregister all event handlers.
|
* Emit `destroy` event and unregister all event handlers.
|
||||||
*/
|
*/
|
||||||
destroy () {
|
destroy () {
|
||||||
|
this.isDestroyed = true
|
||||||
array.from(this.subdocs).forEach(subdoc => subdoc.destroy())
|
array.from(this.subdocs).forEach(subdoc => subdoc.destroy())
|
||||||
const item = this._item
|
const item = this._item
|
||||||
if (item !== null) {
|
if (item !== null) {
|
||||||
|
@ -62,7 +62,7 @@ export class PermanentUserData {
|
|||||||
initUser(storeType.get(userDescription), userDescription)
|
initUser(storeType.get(userDescription), userDescription)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
// add intial data
|
// add initial data
|
||||||
storeType.forEach(initUser)
|
storeType.forEach(initUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ import {
|
|||||||
createID,
|
createID,
|
||||||
ContentType,
|
ContentType,
|
||||||
followRedone,
|
followRedone,
|
||||||
ID, Doc, AbstractType // eslint-disable-line
|
getItem,
|
||||||
|
StructStore, ID, Doc, AbstractType, // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
|
|
||||||
import * as encoding from 'lib0/encoding'
|
import * as encoding from 'lib0/encoding'
|
||||||
@ -65,7 +66,7 @@ export class RelativePosition {
|
|||||||
* after the meant position.
|
* after the meant position.
|
||||||
* I.e. position 1 in 'ab' is associated to character 'b'.
|
* 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.
|
* before the meant position.
|
||||||
*
|
*
|
||||||
* @type {number}
|
* @type {number}
|
||||||
@ -101,7 +102,7 @@ export const relativePositionToJSON = rpos => {
|
|||||||
*
|
*
|
||||||
* @function
|
* @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 {
|
export class AbsolutePosition {
|
||||||
/**
|
/**
|
||||||
@ -256,13 +257,36 @@ export const readRelativePosition = decoder => {
|
|||||||
export const decodeRelativePosition = uint8Array => readRelativePosition(decoding.createDecoder(uint8Array))
|
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.
|
||||||
|
*
|
||||||
|
* If you want to share the relative position with other users, you should set
|
||||||
|
* `followUndoneDeletions` to false to get consistent results across all clients.
|
||||||
|
*
|
||||||
|
* When calculating the absolute position, we try to follow the "undone deletions". This yields
|
||||||
|
* better results for the user who performed undo. However, only the user who performed the undo
|
||||||
|
* will get the better results, the other users don't know which operations recreated a deleted
|
||||||
|
* range of content. There is more information in this ticket: https://github.com/yjs/yjs/issues/638
|
||||||
|
*
|
||||||
* @param {RelativePosition} rpos
|
* @param {RelativePosition} rpos
|
||||||
* @param {Doc} doc
|
* @param {Doc} doc
|
||||||
|
* @param {boolean} followUndoneDeletions - whether to follow undone deletions - see https://github.com/yjs/yjs/issues/638
|
||||||
* @return {AbsolutePosition|null}
|
* @return {AbsolutePosition|null}
|
||||||
*
|
*
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const createAbsolutePositionFromRelativePosition = (rpos, doc) => {
|
export const createAbsolutePositionFromRelativePosition = (rpos, doc, followUndoneDeletions = true) => {
|
||||||
const store = doc.store
|
const store = doc.store
|
||||||
const rightID = rpos.item
|
const rightID = rpos.item
|
||||||
const typeID = rpos.type
|
const typeID = rpos.type
|
||||||
@ -274,7 +298,7 @@ export const createAbsolutePositionFromRelativePosition = (rpos, doc) => {
|
|||||||
if (getState(store, rightID.client) <= rightID.clock) {
|
if (getState(store, rightID.client) <= rightID.clock) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const res = followRedone(store, rightID)
|
const res = followUndoneDeletions ? followRedone(store, rightID) : getItemWithOffset(store, rightID)
|
||||||
const right = res.item
|
const right = res.item
|
||||||
if (!(right instanceof Item)) {
|
if (!(right instanceof Item)) {
|
||||||
return null
|
return null
|
||||||
@ -298,7 +322,7 @@ export const createAbsolutePositionFromRelativePosition = (rpos, doc) => {
|
|||||||
// type does not exist yet
|
// type does not exist yet
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const { item } = followRedone(store, typeID)
|
const { item } = followUndoneDeletions ? followRedone(store, typeID) : { item: getItem(store, typeID) }
|
||||||
if (item instanceof Item && item.content instanceof ContentType) {
|
if (item instanceof Item && item.content instanceof ContentType) {
|
||||||
type = item.content.type
|
type = item.content.type
|
||||||
} else {
|
} else {
|
||||||
|
@ -66,13 +66,13 @@ export const getState = (store, client) => {
|
|||||||
* @private
|
* @private
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const integretyCheck = store => {
|
export const integrityCheck = store => {
|
||||||
store.clients.forEach(structs => {
|
store.clients.forEach(structs => {
|
||||||
for (let i = 1; i < structs.length; i++) {
|
for (let i = 1; i < structs.length; i++) {
|
||||||
const l = structs[i - 1]
|
const l = structs[i - 1]
|
||||||
const r = structs[i]
|
const r = structs[i]
|
||||||
if (l.id.clock + l.length !== r.id.clock) {
|
if (l.id.clock + l.length !== r.id.clock) {
|
||||||
throw new Error('StructStore failed integrety check')
|
throw new Error('StructStore failed integrity check')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -28,7 +28,8 @@ import { callAll } from 'lib0/function'
|
|||||||
* possible. Here is an example to illustrate the advantages of bundling:
|
* possible. Here is an example to illustrate the advantages of bundling:
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const map = y.define('map', YMap)
|
* const ydoc = new Y.Doc()
|
||||||
|
* const map = ydoc.getMap('map')
|
||||||
* // Log content when change is triggered
|
* // Log content when change is triggered
|
||||||
* map.observe(() => {
|
* map.observe(() => {
|
||||||
* console.log('change triggered')
|
* console.log('change triggered')
|
||||||
@ -37,7 +38,7 @@ import { callAll } from 'lib0/function'
|
|||||||
* map.set('a', 0) // => "change triggered"
|
* map.set('a', 0) // => "change triggered"
|
||||||
* map.set('b', 0) // => "change triggered"
|
* map.set('b', 0) // => "change triggered"
|
||||||
* // When put in a transaction, it will trigger the log after the transaction:
|
* // When put in a transaction, it will trigger the log after the transaction:
|
||||||
* y.transact(() => {
|
* ydoc.transact(() => {
|
||||||
* map.set('a', 1)
|
* map.set('a', 1)
|
||||||
* map.set('b', 1)
|
* map.set('b', 1)
|
||||||
* }) // => "change triggered"
|
* }) // => "change triggered"
|
||||||
@ -224,7 +225,7 @@ const tryGcDeleteSet = (ds, store, gcFilter) => {
|
|||||||
*/
|
*/
|
||||||
const tryMergeDeleteSet = (ds, store) => {
|
const tryMergeDeleteSet = (ds, store) => {
|
||||||
// try to merge deleted / gc'd items
|
// try to merge deleted / gc'd items
|
||||||
// merge from right to left for better efficiecy and so we don't miss any merge targets
|
// merge from right to left for better efficiency and so we don't miss any merge targets
|
||||||
ds.clients.forEach((deleteItems, client) => {
|
ds.clients.forEach((deleteItems, client) => {
|
||||||
const structs = /** @type {Array<GC|Item>} */ (store.clients.get(client))
|
const structs = /** @type {Array<GC|Item>} */ (store.clients.get(client))
|
||||||
for (let di = deleteItems.length - 1; di >= 0; di--) {
|
for (let di = deleteItems.length - 1; di >= 0; di--) {
|
||||||
|
@ -39,7 +39,7 @@ export class StackItem {
|
|||||||
*/
|
*/
|
||||||
const clearUndoManagerStackItem = (tr, um, stackItem) => {
|
const clearUndoManagerStackItem = (tr, um, stackItem) => {
|
||||||
iterateDeletedStructs(tr, stackItem.deletions, item => {
|
iterateDeletedStructs(tr, stackItem.deletions, item => {
|
||||||
if (item instanceof Item && um.scope.some(type => isParentOf(type, item))) {
|
if (item instanceof Item && um.scope.some(type => type === tr.doc || isParentOf(/** @type {AbstractType<any>} */ (type), item))) {
|
||||||
keepItem(item, false)
|
keepItem(item, false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -81,7 +81,7 @@ const popStackItem = (undoManager, stack, eventType) => {
|
|||||||
}
|
}
|
||||||
struct = item
|
struct = item
|
||||||
}
|
}
|
||||||
if (!struct.deleted && scope.some(type => isParentOf(type, /** @type {Item} */ (struct)))) {
|
if (!struct.deleted && scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), /** @type {Item} */ (struct)))) {
|
||||||
itemsToDelete.push(struct)
|
itemsToDelete.push(struct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +89,7 @@ const popStackItem = (undoManager, stack, eventType) => {
|
|||||||
iterateDeletedStructs(transaction, stackItem.deletions, struct => {
|
iterateDeletedStructs(transaction, stackItem.deletions, struct => {
|
||||||
if (
|
if (
|
||||||
struct instanceof Item &&
|
struct instanceof Item &&
|
||||||
scope.some(type => isParentOf(type, struct)) &&
|
scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), struct)) &&
|
||||||
// Never redo structs in stackItem.insertions because they were created and deleted in the same capture interval.
|
// Never redo structs in stackItem.insertions because they were created and deleted in the same capture interval.
|
||||||
!isDeleted(stackItem.insertions, struct.id)
|
!isDeleted(stackItem.insertions, struct.id)
|
||||||
) {
|
) {
|
||||||
@ -118,12 +118,13 @@ const popStackItem = (undoManager, stack, eventType) => {
|
|||||||
})
|
})
|
||||||
_tr = transaction
|
_tr = transaction
|
||||||
}, undoManager)
|
}, undoManager)
|
||||||
if (undoManager.currStackItem != null) {
|
const res = undoManager.currStackItem
|
||||||
|
if (res != null) {
|
||||||
const changedParentTypes = _tr.changedParentTypes
|
const changedParentTypes = _tr.changedParentTypes
|
||||||
undoManager.emit('stack-item-popped', [{ stackItem: undoManager.currStackItem, type: eventType, changedParentTypes, origin: undoManager }, undoManager])
|
undoManager.emit('stack-item-popped', [{ stackItem: res, type: eventType, changedParentTypes, origin: undoManager }, undoManager])
|
||||||
undoManager.currStackItem = null
|
undoManager.currStackItem = null
|
||||||
}
|
}
|
||||||
return undoManager.currStackItem
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,7 +159,7 @@ const popStackItem = (undoManager, stack, eventType) => {
|
|||||||
*/
|
*/
|
||||||
export class UndoManager extends ObservableV2 {
|
export class UndoManager extends ObservableV2 {
|
||||||
/**
|
/**
|
||||||
* @param {AbstractType<any>|Array<AbstractType<any>>} typeScope Accepts either a single type, or an array of types
|
* @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 {UndoManagerOptions} options
|
* @param {UndoManagerOptions} options
|
||||||
*/
|
*/
|
||||||
constructor (typeScope, {
|
constructor (typeScope, {
|
||||||
@ -167,11 +168,11 @@ export class UndoManager extends ObservableV2 {
|
|||||||
deleteFilter = () => true,
|
deleteFilter = () => true,
|
||||||
trackedOrigins = new Set([null]),
|
trackedOrigins = new Set([null]),
|
||||||
ignoreRemoteMapChanges = false,
|
ignoreRemoteMapChanges = false,
|
||||||
doc = /** @type {Doc} */ (array.isArray(typeScope) ? typeScope[0].doc : typeScope.doc)
|
doc = /** @type {Doc} */ (array.isArray(typeScope) ? typeScope[0].doc : typeScope instanceof Doc ? typeScope : typeScope.doc)
|
||||||
} = {}) {
|
} = {}) {
|
||||||
super()
|
super()
|
||||||
/**
|
/**
|
||||||
* @type {Array<AbstractType<any>>}
|
* @type {Array<AbstractType<any> | Doc>}
|
||||||
*/
|
*/
|
||||||
this.scope = []
|
this.scope = []
|
||||||
this.doc = doc
|
this.doc = doc
|
||||||
@ -211,7 +212,7 @@ export class UndoManager extends ObservableV2 {
|
|||||||
// Only track certain transactions
|
// Only track certain transactions
|
||||||
if (
|
if (
|
||||||
!this.captureTransaction(transaction) ||
|
!this.captureTransaction(transaction) ||
|
||||||
!this.scope.some(type => transaction.changedParentTypes.has(type)) ||
|
!this.scope.some(type => transaction.changedParentTypes.has(/** @type {AbstractType<any>} */ (type)) || type === this.doc) ||
|
||||||
(!this.trackedOrigins.has(transaction.origin) && (!transaction.origin || !this.trackedOrigins.has(transaction.origin.constructor)))
|
(!this.trackedOrigins.has(transaction.origin) && (!transaction.origin || !this.trackedOrigins.has(transaction.origin.constructor)))
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
@ -250,7 +251,7 @@ export class UndoManager extends ObservableV2 {
|
|||||||
}
|
}
|
||||||
// make sure that deleted structs are not gc'd
|
// make sure that deleted structs are not gc'd
|
||||||
iterateDeletedStructs(transaction, transaction.deleteSet, /** @param {Item|GC} item */ item => {
|
iterateDeletedStructs(transaction, transaction.deleteSet, /** @param {Item|GC} item */ item => {
|
||||||
if (item instanceof Item && this.scope.some(type => isParentOf(type, item))) {
|
if (item instanceof Item && this.scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), item))) {
|
||||||
keepItem(item, true)
|
keepItem(item, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -271,13 +272,17 @@ export class UndoManager extends ObservableV2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<AbstractType<any>> | AbstractType<any>} ytypes
|
* Extend the scope.
|
||||||
|
*
|
||||||
|
* @param {Array<AbstractType<any> | Doc> | AbstractType<any> | Doc} ytypes
|
||||||
*/
|
*/
|
||||||
addToScope (ytypes) {
|
addToScope (ytypes) {
|
||||||
|
const tmpSet = new Set(this.scope)
|
||||||
ytypes = array.isArray(ytypes) ? ytypes : [ytypes]
|
ytypes = array.isArray(ytypes) ? ytypes : [ytypes]
|
||||||
ytypes.forEach(ytype => {
|
ytypes.forEach(ytype => {
|
||||||
if (this.scope.every(yt => yt !== ytype)) {
|
if (!tmpSet.has(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
|
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
|
||||||
this.scope.push(ytype)
|
this.scope.push(ytype)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -167,7 +167,7 @@ export class UpdateEncoderV2 extends DSEncoderV2 {
|
|||||||
*/
|
*/
|
||||||
this.keyMap = new Map()
|
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.
|
* See writeKey method for more information.
|
||||||
*
|
*
|
||||||
* @type {number}
|
* @type {number}
|
||||||
|
@ -264,8 +264,8 @@ const getPathTo = (parent, child) => {
|
|||||||
let i = 0
|
let i = 0
|
||||||
let c = /** @type {AbstractType<any>} */ (child._item.parent)._start
|
let c = /** @type {AbstractType<any>} */ (child._item.parent)._start
|
||||||
while (c !== child._item && c !== null) {
|
while (c !== child._item && c !== null) {
|
||||||
if (!c.deleted) {
|
if (!c.deleted && c.countable) {
|
||||||
i++
|
i += c.length
|
||||||
}
|
}
|
||||||
c = c.right
|
c = c.right
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ export const readClientsStructRefs = (decoder, doc) => {
|
|||||||
// @type {string|null}
|
// @type {string|null}
|
||||||
const struct = new Item(
|
const struct = new Item(
|
||||||
createID(client, clock),
|
createID(client, clock),
|
||||||
null, // leftd
|
null, // left
|
||||||
(info & binary.BIT8) === binary.BIT8 ? decoder.readLeftID() : null, // origin
|
(info & binary.BIT8) === binary.BIT8 ? decoder.readLeftID() : null, // origin
|
||||||
null, // right
|
null, // right
|
||||||
(info & binary.BIT7) === binary.BIT7 ? decoder.readRightID() : null, // right origin
|
(info & binary.BIT7) === binary.BIT7 ? decoder.readRightID() : null, // right origin
|
||||||
@ -178,7 +178,7 @@ export const readClientsStructRefs = (decoder, doc) => {
|
|||||||
|
|
||||||
const struct = new Item(
|
const struct = new Item(
|
||||||
createID(client, clock),
|
createID(client, clock),
|
||||||
null, // leftd
|
null, // left
|
||||||
origin, // origin
|
origin, // origin
|
||||||
null, // right
|
null, // right
|
||||||
rightOrigin, // right origin
|
rightOrigin, // right origin
|
||||||
@ -211,7 +211,7 @@ export const readClientsStructRefs = (decoder, doc) => {
|
|||||||
* then we start emptying the stack.
|
* then we start emptying the stack.
|
||||||
*
|
*
|
||||||
* It is not possible to have circles: i.e. struct1 (from client1) depends on struct2 (from client2)
|
* 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
|
* This method is implemented in a way so that we can resume computation if this update
|
||||||
* causally depends on another update.
|
* causally depends on another update.
|
||||||
@ -279,14 +279,14 @@ const integrateStructs = (transaction, store, clientsStructRefs) => {
|
|||||||
const addStackToRestSS = () => {
|
const addStackToRestSS = () => {
|
||||||
for (const item of stack) {
|
for (const item of stack) {
|
||||||
const client = item.id.client
|
const client = item.id.client
|
||||||
const unapplicableItems = clientsStructRefs.get(client)
|
const inapplicableItems = clientsStructRefs.get(client)
|
||||||
if (unapplicableItems) {
|
if (inapplicableItems) {
|
||||||
// decrement because we weren't able to apply previous operation
|
// decrement because we weren't able to apply previous operation
|
||||||
unapplicableItems.i--
|
inapplicableItems.i--
|
||||||
restStructs.clients.set(client, unapplicableItems.refs.slice(unapplicableItems.i))
|
restStructs.clients.set(client, inapplicableItems.refs.slice(inapplicableItems.i))
|
||||||
clientsStructRefs.delete(client)
|
clientsStructRefs.delete(client)
|
||||||
unapplicableItems.i = 0
|
inapplicableItems.i = 0
|
||||||
unapplicableItems.refs = []
|
inapplicableItems.refs = []
|
||||||
} else {
|
} else {
|
||||||
// item was the last item on clientsStructRefs and the field was already cleared. Add item to restStructs and continue
|
// item was the last item on clientsStructRefs and the field was already cleared. Add item to restStructs and continue
|
||||||
restStructs.clients.set(client, [item])
|
restStructs.clients.set(client, [item])
|
||||||
@ -370,7 +370,7 @@ export const writeStructsFromTransaction = (encoder, transaction) => writeClient
|
|||||||
/**
|
/**
|
||||||
* Read and apply a document update.
|
* Read and apply a document update.
|
||||||
*
|
*
|
||||||
* This function has the same effect as `applyUpdate` but accepts an decoder.
|
* This function has the same effect as `applyUpdate` but accepts a decoder.
|
||||||
*
|
*
|
||||||
* @param {decoding.Decoder} decoder
|
* @param {decoding.Decoder} decoder
|
||||||
* @param {Doc} ydoc
|
* @param {Doc} ydoc
|
||||||
@ -451,7 +451,7 @@ export const readUpdateV2 = (decoder, ydoc, transactionOrigin, structDecoder = n
|
|||||||
/**
|
/**
|
||||||
* Read and apply a document update.
|
* Read and apply a document update.
|
||||||
*
|
*
|
||||||
* This function has the same effect as `applyUpdate` but accepts an decoder.
|
* This function has the same effect as `applyUpdate` but accepts a decoder.
|
||||||
*
|
*
|
||||||
* @param {decoding.Decoder} decoder
|
* @param {decoding.Decoder} decoder
|
||||||
* @param {Doc} ydoc
|
* @param {Doc} ydoc
|
||||||
|
@ -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.
|
* 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.
|
* The v1 documents were generated with Yjs v13.2.0 based on the randomisized tests.
|
||||||
|
@ -15,15 +15,28 @@ import * as relativePositions from './relativePositions.tests.js'
|
|||||||
import { runTests } from 'lib0/testing'
|
import { runTests } from 'lib0/testing'
|
||||||
import { isBrowser, isNode } from 'lib0/environment'
|
import { isBrowser, isNode } from 'lib0/environment'
|
||||||
import * as log from 'lib0/logging'
|
import * as log from 'lib0/logging'
|
||||||
|
import { environment } from 'lib0'
|
||||||
|
|
||||||
if (isBrowser) {
|
if (isBrowser) {
|
||||||
log.createVConsole(document.body)
|
log.createVConsole(document.body)
|
||||||
}
|
}
|
||||||
runTests({
|
|
||||||
|
/**
|
||||||
|
* @type {any}
|
||||||
|
*/
|
||||||
|
const tests = {
|
||||||
doc, map, array, text, xml, encoding, undoredo, compatibility, snapshot, updates, relativePositions
|
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 */
|
/* istanbul ignore next */
|
||||||
if (isNode) {
|
if (isNode) {
|
||||||
process.exit(success ? 0 : 1)
|
process.exit(success ? 0 : 1)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
run()
|
||||||
|
@ -85,6 +85,26 @@ export const testRelativePositionCase6 = tc => {
|
|||||||
checkRelativePositions(ytext)
|
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
|
* @param {t.TestCase} tc
|
||||||
*/
|
*/
|
||||||
@ -101,3 +121,25 @@ export const testRelativePositionAssociationDifference = tc => {
|
|||||||
t.assert(posRight != null && posRight.index === 2)
|
t.assert(posRight != null && posRight.index === 2)
|
||||||
t.assert(posLeft != null && posLeft.index === 1)
|
t.assert(posLeft != null && posLeft.index === 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
*/
|
||||||
|
export const testRelativePositionWithUndo = tc => {
|
||||||
|
const ydoc = new Y.Doc()
|
||||||
|
const ytext = ydoc.getText()
|
||||||
|
ytext.insert(0, 'hello world')
|
||||||
|
const rpos = Y.createRelativePositionFromTypeIndex(ytext, 1)
|
||||||
|
const um = new Y.UndoManager(ytext)
|
||||||
|
ytext.delete(0, 6)
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydoc)?.index === 0)
|
||||||
|
um.undo()
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydoc)?.index === 1)
|
||||||
|
const posWithoutFollow = Y.createAbsolutePositionFromRelativePosition(rpos, ydoc, false)
|
||||||
|
console.log({ posWithoutFollow })
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydoc, false)?.index === 6)
|
||||||
|
const ydocClone = new Y.Doc()
|
||||||
|
Y.applyUpdate(ydocClone, Y.encodeStateAsUpdate(ydoc))
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydocClone)?.index === 6)
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydocClone, false)?.index === 6)
|
||||||
|
}
|
||||||
|
@ -58,7 +58,7 @@ export const testEmptyRestoreSnapshot = _tc => {
|
|||||||
t.compare(docRestored.getArray().toArray(), [])
|
t.compare(docRestored.getArray().toArray(), [])
|
||||||
t.compare(doc.getArray().toArray(), ['world'])
|
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 snap2 = Y.snapshot(doc)
|
||||||
const docRestored2 = Y.createDocFromSnapshot(doc, snap2)
|
const docRestored2 = Y.createDocFromSnapshot(doc, snap2)
|
||||||
t.compare(docRestored2.getArray().toArray(), ['world'])
|
t.compare(docRestored2.getArray().toArray(), ['world'])
|
||||||
|
@ -116,6 +116,72 @@ export const testEmptyTypeScope = _tc => {
|
|||||||
t.assert(yarray.length === 0)
|
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
|
* Test case to fix #241
|
||||||
* @param {t.TestCase} _tc
|
* @param {t.TestCase} _tc
|
||||||
|
@ -4,6 +4,9 @@ import * as Y from '../src/index.js'
|
|||||||
import * as t from 'lib0/testing'
|
import * as t from 'lib0/testing'
|
||||||
import * as prng from 'lib0/prng'
|
import * as prng from 'lib0/prng'
|
||||||
import * as math from 'lib0/math'
|
import * as math from 'lib0/math'
|
||||||
|
import * as env from 'lib0/environment'
|
||||||
|
|
||||||
|
const isDevMode = env.getVariable('node_env') === 'development'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {t.TestCase} tc
|
* @param {t.TestCase} tc
|
||||||
@ -17,6 +20,28 @@ export const testBasicUpdate = tc => {
|
|||||||
t.compare(doc2.getArray('array').toArray(), ['hi'])
|
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
|
* @param {t.TestCase} tc
|
||||||
*/
|
*/
|
||||||
@ -330,6 +355,29 @@ 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
|
* @param {t.TestCase} tc
|
||||||
*/
|
*/
|
||||||
|
@ -369,11 +369,11 @@ export const testObserversUsingObservedeep = tc => {
|
|||||||
/**
|
/**
|
||||||
* @type {Array<Array<string|number>>}
|
* @type {Array<Array<string|number>>}
|
||||||
*/
|
*/
|
||||||
const pathes = []
|
const paths = []
|
||||||
let calls = 0
|
let calls = 0
|
||||||
map0.observeDeep(events => {
|
map0.observeDeep(events => {
|
||||||
events.forEach(event => {
|
events.forEach(event => {
|
||||||
pathes.push(event.path)
|
paths.push(event.path)
|
||||||
})
|
})
|
||||||
calls++
|
calls++
|
||||||
})
|
})
|
||||||
@ -381,7 +381,7 @@ export const testObserversUsingObservedeep = tc => {
|
|||||||
map0.get('map').set('array', new Y.Array())
|
map0.get('map').set('array', new Y.Array())
|
||||||
map0.get('map').get('array').insert(0, ['content'])
|
map0.get('map').get('array').insert(0, ['content'])
|
||||||
t.assert(calls === 3)
|
t.assert(calls === 3)
|
||||||
t.compare(pathes, [[], ['map'], ['map', 'array']])
|
t.compare(paths, [[], ['map'], ['map', 'array']])
|
||||||
compare(users)
|
compare(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,14 +393,14 @@ export const testPathsOfSiblingEvents = tc => {
|
|||||||
/**
|
/**
|
||||||
* @type {Array<Array<string|number>>}
|
* @type {Array<Array<string|number>>}
|
||||||
*/
|
*/
|
||||||
const pathes = []
|
const paths = []
|
||||||
let calls = 0
|
let calls = 0
|
||||||
const doc = users[0]
|
const doc = users[0]
|
||||||
map0.set('map', new Y.Map())
|
map0.set('map', new Y.Map())
|
||||||
map0.get('map').set('text1', new Y.Text('initial'))
|
map0.get('map').set('text1', new Y.Text('initial'))
|
||||||
map0.observeDeep(events => {
|
map0.observeDeep(events => {
|
||||||
events.forEach(event => {
|
events.forEach(event => {
|
||||||
pathes.push(event.path)
|
paths.push(event.path)
|
||||||
})
|
})
|
||||||
calls++
|
calls++
|
||||||
})
|
})
|
||||||
@ -409,7 +409,7 @@ export const testPathsOfSiblingEvents = tc => {
|
|||||||
map0.get('map').set('text2', new Y.Text('new'))
|
map0.get('map').set('text2', new Y.Text('new'))
|
||||||
})
|
})
|
||||||
t.assert(calls === 1)
|
t.assert(calls === 1)
|
||||||
t.compare(pathes, [['map'], ['map', 'text1']])
|
t.compare(paths, [['map'], ['map', 'text1']])
|
||||||
compare(users)
|
compare(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ export const testDeltaBug = _tc => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
insert: '\n',
|
insert: '\n',
|
||||||
// This attibutes has only list and no table-cell-line
|
// This attributes has only list and no table-cell-line
|
||||||
attributes: {
|
attributes: {
|
||||||
list: {
|
list: {
|
||||||
rowspan: '1',
|
rowspan: '1',
|
||||||
@ -1746,6 +1746,27 @@ export const testBasicFormat = tc => {
|
|||||||
compare(users)
|
compare(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
*/
|
||||||
|
export const testFalsyFormats = tc => {
|
||||||
|
const { users, text0 } = init(tc, { users: 2 })
|
||||||
|
let delta
|
||||||
|
text0.observe(event => {
|
||||||
|
delta = event.delta
|
||||||
|
})
|
||||||
|
text0.insert(0, 'abcde', { falsy: false })
|
||||||
|
t.compare(text0.toDelta(), [{ insert: 'abcde', attributes: { falsy: false } }])
|
||||||
|
t.compare(delta, [{ insert: 'abcde', attributes: { falsy: false } }])
|
||||||
|
text0.format(1, 3, { falsy: true })
|
||||||
|
t.compare(text0.toDelta(), [{ insert: 'a', attributes: { falsy: false } }, { insert: 'bcd', attributes: { falsy: true } }, { insert: 'e', attributes: { falsy: false } }])
|
||||||
|
t.compare(delta, [{ retain: 1 }, { retain: 3, attributes: { falsy: true } }])
|
||||||
|
text0.format(2, 1, { falsy: false })
|
||||||
|
t.compare(text0.toDelta(), [{ insert: 'a', attributes: { falsy: false } }, { insert: 'b', attributes: { falsy: true } }, { insert: 'c', attributes: { falsy: false } }, { insert: 'd', attributes: { falsy: true } }, { insert: 'e', attributes: { falsy: false } }])
|
||||||
|
t.compare(delta, [{ retain: 2 }, { retain: 1, attributes: { falsy: false } }])
|
||||||
|
compare(users)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {t.TestCase} _tc
|
* @param {t.TestCase} _tc
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user