Merge branch 'main' into patch-1
This commit is contained in:
		
						commit
						0896ed42b2
					
				@ -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
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										82
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								README.md
									
									
									
									
									
								
							@ -32,13 +32,35 @@ Otherwise you can find help on our community [discussion board](https://discuss.
 | 
				
			|||||||
Please contribute to the project financially - especially if your company relies
 | 
					Please contribute to the project financially - especially if your company relies
 | 
				
			||||||
on Yjs. [](https://github.com/sponsors/dmonad)
 | 
					on Yjs. [](https://github.com/sponsors/dmonad)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Professional Support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Support Contract with the Maintainer](https://github.com/sponsors/dmonad) -
 | 
				
			||||||
 | 
					By contributing financially to the open-source Yjs project, you can receive
 | 
				
			||||||
 | 
					professional support directly from the author. This includes the opportunity for
 | 
				
			||||||
 | 
					weekly video calls to discuss your specific challenges.
 | 
				
			||||||
 | 
					* [Synergy Codes](https://synergycodes.com/yjs-services/) - Specializing in
 | 
				
			||||||
 | 
					consulting and developing real-time collaborative editing solutions for visual
 | 
				
			||||||
 | 
					apps, Synergy Codes focuses on interactive diagrams, complex graphs, charts, and
 | 
				
			||||||
 | 
					various data visualization types. Their expertise empowers developers to build
 | 
				
			||||||
 | 
					engaging and interactive visual experiences leveraging the power of Yjs. See
 | 
				
			||||||
 | 
					their work in action at [Visual Collaboration
 | 
				
			||||||
 | 
					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:
 | 
				
			||||||
* [Dynaboard](https://dynaboard.com/) Build web apps collaboratively. :star2:
 | 
					* [Huly](https://huly.io/) - Open Source All-in-One Project Management Platform
 | 
				
			||||||
* [Sana](https://sanalabs.com/) A learning platform with collaborative text
 | 
					  :star2:
 | 
				
			||||||
  editing powered by Yjs.
 | 
					* [Cargo](https://cargo.site/) Site builder for designers and artists :star2:
 | 
				
			||||||
 | 
					* [Gitbook](https://gitbook.com) Knowledge management for technical teams :star2:
 | 
				
			||||||
 | 
					* [Evernote](https://evernote.com) Note-taking app :star2:
 | 
				
			||||||
 | 
					* [Lessonspace](https://thelessonspace.com) Enterprise platform for virtual
 | 
				
			||||||
 | 
					  classrooms and online training :star2:
 | 
				
			||||||
 | 
					* [Ellipsus]{ellipsus.com} - Collaborative writing app for storytelling etc.
 | 
				
			||||||
 | 
					  Supports versioning, change attribution, and "blame". A solution for the whole
 | 
				
			||||||
 | 
					  publishing process (also selling) :star:
 | 
				
			||||||
 | 
					* [Dynaboard](https://dynaboard.com/) Build web apps collaboratively. :star:
 | 
				
			||||||
* [Relm](https://www.relm.us/) A collaborative gameworld for teamwork and
 | 
					* [Relm](https://www.relm.us/) A collaborative gameworld for teamwork and
 | 
				
			||||||
  community. :star:
 | 
					  community. :star:
 | 
				
			||||||
* [Room.sh](https://room.sh/) A meeting application with integrated
 | 
					* [Room.sh](https://room.sh/) A meeting application with integrated
 | 
				
			||||||
@ -47,9 +69,15 @@ on Yjs. [ 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
 | 
				
			||||||
 | 
					  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.
 | 
				
			||||||
@ -71,6 +99,21 @@ on Yjs. [ Open-source Medium alternative
 | 
					* [btw](https://www.btw.so) Open-source Medium alternative
 | 
				
			||||||
* [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.
 | 
				
			||||||
 | 
					* [btw](https://www.btw.so) - Personal website builder
 | 
				
			||||||
 | 
					* [AWS SageMaker](https://aws.amazon.com/sagemaker/) - Machine Learning Service
 | 
				
			||||||
 | 
					* [Arkiter](https://www.arkiter.com/) - Live interview software
 | 
				
			||||||
 | 
					* [Appflowy](https://www.appflowy.io/) - They use Yrs
 | 
				
			||||||
 | 
					* [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
 | 
				
			||||||
 | 
					  applicaiton
 | 
				
			||||||
 | 
					* [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.
 | 
					* [screen.garden](https://screen.garden) Collaborative backend for PKM apps.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Table of Contents
 | 
					## Table of Contents
 | 
				
			||||||
@ -108,6 +151,7 @@ are implemented in separate modules.
 | 
				
			|||||||
| [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 / 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) |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Providers
 | 
					### Providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -125,9 +169,10 @@ 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>
 | 
				
			||||||
@ -149,6 +194,10 @@ browser DevTools extension.
 | 
				
			|||||||
  <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>
 | 
				
			||||||
 | 
					  <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>
 | 
					  </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>
 | 
				
			||||||
@ -185,6 +234,15 @@ 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>
 | 
				
			||||||
</dl>
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Persistence Providers
 | 
					#### Persistence Providers
 | 
				
			||||||
@ -206,6 +264,10 @@ y-websocket provider.
 | 
				
			|||||||
  <dd>
 | 
					  <dd>
 | 
				
			||||||
Like y-indexeddb, but with sub-documents support and fully TypeScript.
 | 
					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>
 | 
				
			||||||
 | 
					  <dd>
 | 
				
			||||||
 | 
					A database and connection provider for Yjs based on Firestore.
 | 
				
			||||||
 | 
					  </dd>
 | 
				
			||||||
</dl>
 | 
					</dl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Ports
 | 
					# Ports
 | 
				
			||||||
@ -719,6 +781,8 @@ type. Doesn't log types that have not been defined (using
 | 
				
			|||||||
  <dd>Define a shared Y.Map type. Is equivalent to <code>y.get(string, Y.Map)</code>.</dd>
 | 
					  <dd>Define a shared Y.Map type. Is equivalent to <code>y.get(string, Y.Map)</code>.</dd>
 | 
				
			||||||
  <b><code>getText(string):Y.Text</code></b>
 | 
					  <b><code>getText(string):Y.Text</code></b>
 | 
				
			||||||
  <dd>Define a shared Y.Text type. Is equivalent to <code>y.get(string, Y.Text)</code>.</dd>
 | 
					  <dd>Define a shared Y.Text type. Is equivalent to <code>y.get(string, Y.Text)</code>.</dd>
 | 
				
			||||||
 | 
					  <b><code>getXmlElement(string, string):Y.XmlElement</code></b>
 | 
				
			||||||
 | 
					  <dd>Define a shared Y.XmlElement type. Is equivalent to <code>y.get(string, Y.XmlElement)</code>.</dd>
 | 
				
			||||||
  <b><code>getXmlFragment(string):Y.XmlFragment</code></b>
 | 
					  <b><code>getXmlFragment(string):Y.XmlFragment</code></b>
 | 
				
			||||||
  <dd>Define a shared Y.XmlFragment type. Is equivalent to <code>y.get(string, Y.XmlFragment)</code>.</dd>
 | 
					  <dd>Define a shared Y.XmlFragment type. Is equivalent to <code>y.get(string, Y.XmlFragment)</code>.</dd>
 | 
				
			||||||
  <b><code>on(string, function)</code></b>
 | 
					  <b><code>on(string, function)</code></b>
 | 
				
			||||||
@ -856,7 +920,7 @@ ydoc2.getText().toString() // => "00000000000"
 | 
				
			|||||||
#### Using V2 update format
 | 
					#### Using V2 update format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Yjs implements two update formats. By default you are using the V1 update format.
 | 
					Yjs implements two update formats. By default you are using the V1 update format.
 | 
				
			||||||
You can opt-in into the V2 update format wich provides much better compression.
 | 
					You can opt-in into the V2 update format which provides much better compression.
 | 
				
			||||||
It is not yet used by all providers. However, you can already use it if
 | 
					It is not yet used by all providers. However, you can already use it if
 | 
				
			||||||
you are building your own provider. All below functions are available with the
 | 
					you are building your own provider. All below functions are available with the
 | 
				
			||||||
suffix "V2". E.g. `Y.applyUpdate` ⇒ `Y.applyUpdateV2`. Also when listening to updates
 | 
					suffix "V2". E.g. `Y.applyUpdate` ⇒ `Y.applyUpdateV2`. Also when listening to updates
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1129
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1129
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "yjs",
 | 
					  "name": "yjs",
 | 
				
			||||||
  "version": "13.6.10",
 | 
					  "version": "13.6.15",
 | 
				
			||||||
  "description": "Shared Editing Library",
 | 
					  "description": "Shared Editing Library",
 | 
				
			||||||
  "main": "./dist/yjs.cjs",
 | 
					  "main": "./dist/yjs.cjs",
 | 
				
			||||||
  "module": "./dist/yjs.mjs",
 | 
					  "module": "./dist/yjs.mjs",
 | 
				
			||||||
@ -12,9 +12,10 @@
 | 
				
			|||||||
    "url": "https://github.com/sponsors/dmonad"
 | 
					    "url": "https://github.com/sponsors/dmonad"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "clean": "rm -rf dist docs",
 | 
				
			||||||
    "test": "npm run dist && node ./dist/tests.cjs --repetition-time 50",
 | 
					    "test": "npm run dist && node ./dist/tests.cjs --repetition-time 50",
 | 
				
			||||||
    "test-extensive": "npm run lint && npm run dist && node ./dist/tests.cjs --production --repetition-time 10000",
 | 
					    "test-extensive": "npm run lint && npm run dist && node ./dist/tests.cjs --production --repetition-time 10000",
 | 
				
			||||||
    "dist": "rm -rf dist && rollup -c && tsc",
 | 
					    "dist": "npm run clean && rollup -c && tsc",
 | 
				
			||||||
    "watch": "rollup -wc",
 | 
					    "watch": "rollup -wc",
 | 
				
			||||||
    "lint": "markdownlint README.md && standard && tsc",
 | 
					    "lint": "markdownlint README.md && standard && tsc",
 | 
				
			||||||
    "docs": "rm -rf docs; jsdoc --configure ./.jsdoc.json --verbose --readme ./README.md --package ./package.json || true",
 | 
					    "docs": "rm -rf docs; jsdoc --configure ./.jsdoc.json --verbose --readme ./README.md --package ./package.json || true",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
export * from './utils/AbstractConnector.js'
 | 
					export * from './utils/AbstractConnector.js'
 | 
				
			||||||
export * from './utils/DeleteSet.js'
 | 
					export * from './utils/DeleteSet.js'
 | 
				
			||||||
export * from './utils/Doc.js'
 | 
					export * from './utils/Doc.js'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  UpdateEncoderV1, UpdateEncoderV2, ID, Transaction // eslint-disable-line
 | 
					  UpdateEncoderV1, UpdateEncoderV2, ID, Transaction // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  addToDeleteSet,
 | 
					  addToDeleteSet,
 | 
				
			||||||
  UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line
 | 
					  UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Doc, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, Item // eslint-disable-line
 | 
					  Doc, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, Item // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line
 | 
					  UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  YText, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Item, StructStore, Transaction // eslint-disable-line
 | 
					  YText, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Item, StructStore, Transaction // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  readYArray,
 | 
					  readYArray,
 | 
				
			||||||
  readYMap,
 | 
					  readYMap,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  AbstractStruct,
 | 
					  AbstractStruct,
 | 
				
			||||||
  addStruct,
 | 
					  addStruct,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  GC,
 | 
					  GC,
 | 
				
			||||||
  getState,
 | 
					  getState,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  AbstractStruct,
 | 
					  AbstractStruct,
 | 
				
			||||||
  UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, ID // eslint-disable-line
 | 
					  UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, ID // eslint-disable-line
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  removeEventHandlerListener,
 | 
					  removeEventHandlerListener,
 | 
				
			||||||
  callEventHandlerListeners,
 | 
					  callEventHandlerListeners,
 | 
				
			||||||
@ -317,6 +316,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 () {
 | 
				
			||||||
@ -478,7 +481,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.
 | 
				
			||||||
@ -570,7 +573,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
 | 
				
			||||||
 | 
				
			|||||||
@ -25,16 +25,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 +86,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 () {
 | 
				
			||||||
@ -167,9 +162,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 +206,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 +240,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.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @module YMap
 | 
					 * @module YMap
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -89,6 +88,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 () {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @module YText
 | 
					 * @module YText
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -118,14 +117,15 @@ const findNextPosition = (transaction, pos, count) => {
 | 
				
			|||||||
 * @param {Transaction} transaction
 | 
					 * @param {Transaction} transaction
 | 
				
			||||||
 * @param {AbstractType<any>} parent
 | 
					 * @param {AbstractType<any>} parent
 | 
				
			||||||
 * @param {number} index
 | 
					 * @param {number} index
 | 
				
			||||||
 | 
					 * @param {boolean} useSearchMarker
 | 
				
			||||||
 * @return {ItemTextListPosition}
 | 
					 * @return {ItemTextListPosition}
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @private
 | 
					 * @private
 | 
				
			||||||
 * @function
 | 
					 * @function
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const findPosition = (transaction, parent, index) => {
 | 
					const findPosition = (transaction, parent, index, useSearchMarker) => {
 | 
				
			||||||
  const currentAttributes = new Map()
 | 
					  const currentAttributes = new Map()
 | 
				
			||||||
  const marker = findMarker(parent, index)
 | 
					  const marker = useSearchMarker ? findMarker(parent, index) : null
 | 
				
			||||||
  if (marker) {
 | 
					  if (marker) {
 | 
				
			||||||
    const pos = new ItemTextListPosition(marker.p.left, marker.p, marker.index, currentAttributes)
 | 
					    const pos = new ItemTextListPosition(marker.p.left, marker.p, marker.index, currentAttributes)
 | 
				
			||||||
    return findNextPosition(transaction, pos, index - marker.index)
 | 
					    return findNextPosition(transaction, pos, index - marker.index)
 | 
				
			||||||
@ -201,7 +201,7 @@ const minimizeAttributeChanges = (currPos, attributes) => {
 | 
				
			|||||||
  while (true) {
 | 
					  while (true) {
 | 
				
			||||||
    if (currPos.right === null) {
 | 
					    if (currPos.right === null) {
 | 
				
			||||||
      break
 | 
					      break
 | 
				
			||||||
    } else if (currPos.right.deleted || (currPos.right.content.constructor === ContentFormat && equalAttrs(attributes[(/** @type {ContentFormat} */ (currPos.right.content)).key] || null, /** @type {ContentFormat} */ (currPos.right.content).value))) {
 | 
					    } else if (currPos.right.deleted || (currPos.right.content.constructor === ContentFormat && equalAttrs(attributes[(/** @type {ContentFormat} */ (currPos.right.content)).key] ?? null, /** @type {ContentFormat} */ (currPos.right.content).value))) {
 | 
				
			||||||
      //
 | 
					      //
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      break
 | 
					      break
 | 
				
			||||||
@ -227,7 +227,7 @@ const insertAttributes = (transaction, parent, currPos, attributes) => {
 | 
				
			|||||||
  // insert format-start items
 | 
					  // insert format-start items
 | 
				
			||||||
  for (const key in attributes) {
 | 
					  for (const key in attributes) {
 | 
				
			||||||
    const val = attributes[key]
 | 
					    const val = attributes[key]
 | 
				
			||||||
    const currentVal = currPos.currentAttributes.get(key) || null
 | 
					    const currentVal = currPos.currentAttributes.get(key) ?? null
 | 
				
			||||||
    if (!equalAttrs(currentVal, val)) {
 | 
					    if (!equalAttrs(currentVal, val)) {
 | 
				
			||||||
      // save negated attribute (set null if currentVal undefined)
 | 
					      // save negated attribute (set null if currentVal undefined)
 | 
				
			||||||
      negatedAttributes.set(key, currentVal)
 | 
					      negatedAttributes.set(key, currentVal)
 | 
				
			||||||
@ -389,12 +389,12 @@ const cleanupFormattingGap = (transaction, start, curr, startAttributes, currAtt
 | 
				
			|||||||
      switch (content.constructor) {
 | 
					      switch (content.constructor) {
 | 
				
			||||||
        case ContentFormat: {
 | 
					        case ContentFormat: {
 | 
				
			||||||
          const { key, value } = /** @type {ContentFormat} */ (content)
 | 
					          const { key, value } = /** @type {ContentFormat} */ (content)
 | 
				
			||||||
          const startAttrValue = startAttributes.get(key) || null
 | 
					          const startAttrValue = startAttributes.get(key) ?? null
 | 
				
			||||||
          if (endFormats.get(key) !== content || startAttrValue === value) {
 | 
					          if (endFormats.get(key) !== content || startAttrValue === value) {
 | 
				
			||||||
            // Either this format is overwritten or it is not necessary because the attribute already existed.
 | 
					            // Either this format is overwritten or it is not necessary because the attribute already existed.
 | 
				
			||||||
            start.delete(transaction)
 | 
					            start.delete(transaction)
 | 
				
			||||||
            cleanups++
 | 
					            cleanups++
 | 
				
			||||||
            if (!reachedCurr && (currAttributes.get(key) || null) === value && startAttrValue !== value) {
 | 
					            if (!reachedCurr && (currAttributes.get(key) ?? null) === value && startAttrValue !== value) {
 | 
				
			||||||
              if (startAttrValue === null) {
 | 
					              if (startAttrValue === null) {
 | 
				
			||||||
                currAttributes.delete(key)
 | 
					                currAttributes.delete(key)
 | 
				
			||||||
              } else {
 | 
					              } else {
 | 
				
			||||||
@ -769,12 +769,12 @@ export class YTextEvent extends YEvent {
 | 
				
			|||||||
              const { key, value } = /** @type {ContentFormat} */ (item.content)
 | 
					              const { key, value } = /** @type {ContentFormat} */ (item.content)
 | 
				
			||||||
              if (this.adds(item)) {
 | 
					              if (this.adds(item)) {
 | 
				
			||||||
                if (!this.deletes(item)) {
 | 
					                if (!this.deletes(item)) {
 | 
				
			||||||
                  const curVal = currentAttributes.get(key) || null
 | 
					                  const curVal = currentAttributes.get(key) ?? null
 | 
				
			||||||
                  if (!equalAttrs(curVal, value)) {
 | 
					                  if (!equalAttrs(curVal, value)) {
 | 
				
			||||||
                    if (action === 'retain') {
 | 
					                    if (action === 'retain') {
 | 
				
			||||||
                      addOp()
 | 
					                      addOp()
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if (equalAttrs(value, (oldAttributes.get(key) || null))) {
 | 
					                    if (equalAttrs(value, (oldAttributes.get(key) ?? null))) {
 | 
				
			||||||
                      delete attributes[key]
 | 
					                      delete attributes[key]
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                      attributes[key] = value
 | 
					                      attributes[key] = value
 | 
				
			||||||
@ -785,7 +785,7 @@ export class YTextEvent extends YEvent {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
              } else if (this.deletes(item)) {
 | 
					              } else if (this.deletes(item)) {
 | 
				
			||||||
                oldAttributes.set(key, value)
 | 
					                oldAttributes.set(key, value)
 | 
				
			||||||
                const curVal = currentAttributes.get(key) || null
 | 
					                const curVal = currentAttributes.get(key) ?? null
 | 
				
			||||||
                if (!equalAttrs(curVal, value)) {
 | 
					                if (!equalAttrs(curVal, value)) {
 | 
				
			||||||
                  if (action === 'retain') {
 | 
					                  if (action === 'retain') {
 | 
				
			||||||
                    addOp()
 | 
					                    addOp()
 | 
				
			||||||
@ -897,6 +897,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 () {
 | 
				
			||||||
@ -1120,7 +1124,7 @@ export class YText extends AbstractType {
 | 
				
			|||||||
    const y = this.doc
 | 
					    const y = this.doc
 | 
				
			||||||
    if (y !== null) {
 | 
					    if (y !== null) {
 | 
				
			||||||
      transact(y, transaction => {
 | 
					      transact(y, transaction => {
 | 
				
			||||||
        const pos = findPosition(transaction, this, index)
 | 
					        const pos = findPosition(transaction, this, index, !attributes)
 | 
				
			||||||
        if (!attributes) {
 | 
					        if (!attributes) {
 | 
				
			||||||
          attributes = {}
 | 
					          attributes = {}
 | 
				
			||||||
          // @ts-ignore
 | 
					          // @ts-ignore
 | 
				
			||||||
@ -1138,20 +1142,20 @@ export class YText extends AbstractType {
 | 
				
			|||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param {number} index The index to insert the embed at.
 | 
					   * @param {number} index The index to insert the embed at.
 | 
				
			||||||
   * @param {Object | AbstractType<any>} embed The Object that represents the embed.
 | 
					   * @param {Object | AbstractType<any>} embed The Object that represents the embed.
 | 
				
			||||||
   * @param {TextAttributes} attributes Attribute information to apply on the
 | 
					   * @param {TextAttributes} [attributes] Attribute information to apply on the
 | 
				
			||||||
   *                                    embed
 | 
					   *                                    embed
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  insertEmbed (index, embed, attributes = {}) {
 | 
					  insertEmbed (index, embed, attributes) {
 | 
				
			||||||
    const y = this.doc
 | 
					    const y = this.doc
 | 
				
			||||||
    if (y !== null) {
 | 
					    if (y !== null) {
 | 
				
			||||||
      transact(y, transaction => {
 | 
					      transact(y, transaction => {
 | 
				
			||||||
        const pos = findPosition(transaction, this, index)
 | 
					        const pos = findPosition(transaction, this, index, !attributes)
 | 
				
			||||||
        insertText(transaction, this, pos, embed, attributes)
 | 
					        insertText(transaction, this, pos, embed, attributes || {})
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      /** @type {Array<function>} */ (this._pending).push(() => this.insertEmbed(index, embed, attributes))
 | 
					      /** @type {Array<function>} */ (this._pending).push(() => this.insertEmbed(index, embed, attributes || {}))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1170,7 +1174,7 @@ export class YText extends AbstractType {
 | 
				
			|||||||
    const y = this.doc
 | 
					    const y = this.doc
 | 
				
			||||||
    if (y !== null) {
 | 
					    if (y !== null) {
 | 
				
			||||||
      transact(y, transaction => {
 | 
					      transact(y, transaction => {
 | 
				
			||||||
        deleteText(transaction, findPosition(transaction, this, index), length)
 | 
					        deleteText(transaction, findPosition(transaction, this, index, true), length)
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      /** @type {Array<function>} */ (this._pending).push(() => this.delete(index, length))
 | 
					      /** @type {Array<function>} */ (this._pending).push(() => this.delete(index, length))
 | 
				
			||||||
@ -1194,7 +1198,7 @@ export class YText extends AbstractType {
 | 
				
			|||||||
    const y = this.doc
 | 
					    const y = this.doc
 | 
				
			||||||
    if (y !== null) {
 | 
					    if (y !== null) {
 | 
				
			||||||
      transact(y, transaction => {
 | 
					      transact(y, transaction => {
 | 
				
			||||||
        const pos = findPosition(transaction, this, index)
 | 
					        const pos = findPosition(transaction, this, index, false)
 | 
				
			||||||
        if (pos.right === null) {
 | 
					        if (pos.right === null) {
 | 
				
			||||||
          return
 | 
					          return
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ import {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * An YXmlElement imitates the behavior of a
 | 
					 * An YXmlElement imitates the behavior of a
 | 
				
			||||||
 * {@link https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element}.
 | 
					 * https://developer.mozilla.org/en-US/docs/Web/API/Element|Dom Element
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * * An YXmlElement has attributes (key value pairs)
 | 
					 * * An YXmlElement has attributes (key value pairs)
 | 
				
			||||||
 * * An YXmlElement has childElements that must inherit from YXmlElement
 | 
					 * * An YXmlElement has childElements that must inherit from YXmlElement
 | 
				
			||||||
@ -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 () {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  YEvent,
 | 
					  YEvent,
 | 
				
			||||||
  YXmlText, YXmlElement, YXmlFragment, Transaction // eslint-disable-line
 | 
					  YXmlText, YXmlElement, YXmlFragment, Transaction // eslint-disable-line
 | 
				
			||||||
 | 
				
			|||||||
@ -163,6 +163,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 () {
 | 
				
			||||||
@ -376,9 +380,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 +399,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 +411,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.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  YMap,
 | 
					  YMap,
 | 
				
			||||||
  YXmlHookRefID,
 | 
					  YXmlHookRefID,
 | 
				
			||||||
@ -30,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 () {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  YText,
 | 
					  YText,
 | 
				
			||||||
  YXmlTextRefID,
 | 
					  YXmlTextRefID,
 | 
				
			||||||
@ -31,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 () {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
 | 
					import { ObservableV2 } from 'lib0/observable'
 | 
				
			||||||
import { Observable } from 'lib0/observable'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Doc // eslint-disable-line
 | 
					  Doc // eslint-disable-line
 | 
				
			||||||
@ -11,9 +10,9 @@ import {
 | 
				
			|||||||
 * @note This interface is experimental and it is not advised to actually inherit this class.
 | 
					 * @note This interface is experimental and it is not advised to actually inherit this class.
 | 
				
			||||||
 *       It just serves as typing information.
 | 
					 *       It just serves as typing information.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @extends {Observable<any>}
 | 
					 * @extends {ObservableV2<any>}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class AbstractConnector extends Observable {
 | 
					export class AbstractConnector extends ObservableV2 {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {Doc} ydoc
 | 
					   * @param {Doc} ydoc
 | 
				
			||||||
   * @param {any} awareness
 | 
					   * @param {any} awareness
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  findIndexSS,
 | 
					  findIndexSS,
 | 
				
			||||||
  getState,
 | 
					  getState,
 | 
				
			||||||
 | 
				
			|||||||
@ -8,12 +8,13 @@ import {
 | 
				
			|||||||
  YArray,
 | 
					  YArray,
 | 
				
			||||||
  YText,
 | 
					  YText,
 | 
				
			||||||
  YMap,
 | 
					  YMap,
 | 
				
			||||||
 | 
					  YXmlElement,
 | 
				
			||||||
  YXmlFragment,
 | 
					  YXmlFragment,
 | 
				
			||||||
  transact,
 | 
					  transact,
 | 
				
			||||||
  ContentDoc, Item, Transaction, YEvent // eslint-disable-line
 | 
					  ContentDoc, Item, Transaction, YEvent // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Observable } from 'lib0/observable'
 | 
					import { ObservableV2 } from 'lib0/observable'
 | 
				
			||||||
import * as random from 'lib0/random'
 | 
					import * as random from 'lib0/random'
 | 
				
			||||||
import * as map from 'lib0/map'
 | 
					import * as map from 'lib0/map'
 | 
				
			||||||
import * as array from 'lib0/array'
 | 
					import * as array from 'lib0/array'
 | 
				
			||||||
@ -33,10 +34,26 @@ export const generateNewClientId = random.uint32
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A Yjs instance handles the state of shared data.
 | 
					 * @typedef {Object} DocEvents
 | 
				
			||||||
 * @extends Observable<string>
 | 
					 * @property {function(Doc):void} DocEvents.destroy
 | 
				
			||||||
 | 
					 * @property {function(Doc):void} DocEvents.load
 | 
				
			||||||
 | 
					 * @property {function(boolean, Doc):void} DocEvents.sync
 | 
				
			||||||
 | 
					 * @property {function(Uint8Array, any, Doc, Transaction):void} DocEvents.update
 | 
				
			||||||
 | 
					 * @property {function(Uint8Array, any, Doc, Transaction):void} DocEvents.updateV2
 | 
				
			||||||
 | 
					 * @property {function(Doc):void} DocEvents.beforeAllTransactions
 | 
				
			||||||
 | 
					 * @property {function(Transaction, Doc):void} DocEvents.beforeTransaction
 | 
				
			||||||
 | 
					 * @property {function(Transaction, Doc):void} DocEvents.beforeObserverCalls
 | 
				
			||||||
 | 
					 * @property {function(Transaction, Doc):void} DocEvents.afterTransaction
 | 
				
			||||||
 | 
					 * @property {function(Transaction, Doc):void} DocEvents.afterTransactionCleanup
 | 
				
			||||||
 | 
					 * @property {function(Doc, Array<Transaction>):void} DocEvents.afterAllTransactions
 | 
				
			||||||
 | 
					 * @property {function({ loaded: Set<Doc>, added: Set<Doc>, removed: Set<Doc> }, Doc, Transaction):void} DocEvents.subdocs
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class Doc extends Observable {
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A Yjs instance handles the state of shared data.
 | 
				
			||||||
 | 
					 * @extends ObservableV2<DocEvents>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export class Doc extends ObservableV2 {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {DocOpts} opts configuration
 | 
					   * @param {DocOpts} opts configuration
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
@ -114,7 +131,7 @@ export class Doc extends Observable {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      this.isSynced = isSynced === undefined || isSynced === true
 | 
					      this.isSynced = isSynced === undefined || isSynced === true
 | 
				
			||||||
      if (this.isSynced && !this.isLoaded) {
 | 
					      if (this.isSynced && !this.isLoaded) {
 | 
				
			||||||
        this.emit('load', [])
 | 
					        this.emit('load', [this])
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -170,30 +187,31 @@ export class Doc extends Observable {
 | 
				
			|||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 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
 | 
				
			||||||
   * @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
 | 
				
			||||||
   * @param {Function} TypeConstructor The constructor of the type definition. E.g. Y.Text, Y.Array, Y.Map, ...
 | 
					   * @param {Type} TypeConstructor The constructor of the type definition. E.g. Y.Text, Y.Array, Y.Map, ...
 | 
				
			||||||
   * @return {AbstractType<any>} The created type. Constructed with TypeConstructor
 | 
					   * @return {InstanceType<Type>} The created type. Constructed with TypeConstructor
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  get (name, TypeConstructor = AbstractType) {
 | 
					  get (name, TypeConstructor = /** @type {any} */ (AbstractType)) {
 | 
				
			||||||
    const type = map.setIfUndefined(this.share, name, () => {
 | 
					    const type = map.setIfUndefined(this.share, name, () => {
 | 
				
			||||||
      // @ts-ignore
 | 
					      // @ts-ignore
 | 
				
			||||||
      const t = new TypeConstructor()
 | 
					      const t = new TypeConstructor()
 | 
				
			||||||
@ -219,12 +237,12 @@ export class Doc extends Observable {
 | 
				
			|||||||
        t._length = type._length
 | 
					        t._length = type._length
 | 
				
			||||||
        this.share.set(name, t)
 | 
					        this.share.set(name, t)
 | 
				
			||||||
        t._integrate(this, null)
 | 
					        t._integrate(this, null)
 | 
				
			||||||
        return t
 | 
					        return /** @type {InstanceType<Type>} */ (t)
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        throw new Error(`Type with the name ${name} has already been defined with a different constructor`)
 | 
					        throw new Error(`Type with the name ${name} has already been defined with a different constructor`)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return type
 | 
					    return /** @type {InstanceType<Type>} */ (type)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@ -235,8 +253,7 @@ export class Doc extends Observable {
 | 
				
			|||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  getArray (name = '') {
 | 
					  getArray (name = '') {
 | 
				
			||||||
    // @ts-ignore
 | 
					    return /** @type {YArray<T>} */ (this.get(name, YArray))
 | 
				
			||||||
    return this.get(name, YArray)
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@ -246,7 +263,6 @@ export class Doc extends Observable {
 | 
				
			|||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  getText (name = '') {
 | 
					  getText (name = '') {
 | 
				
			||||||
    // @ts-ignore
 | 
					 | 
				
			||||||
    return this.get(name, YText)
 | 
					    return this.get(name, YText)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -258,8 +274,17 @@ export class Doc extends Observable {
 | 
				
			|||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  getMap (name = '') {
 | 
					  getMap (name = '') {
 | 
				
			||||||
    // @ts-ignore
 | 
					    return /** @type {YMap<T>} */ (this.get(name, YMap))
 | 
				
			||||||
    return this.get(name, YMap)
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @param {string} [name]
 | 
				
			||||||
 | 
					   * @return {YXmlElement}
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @public
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  getXmlElement (name = '') {
 | 
				
			||||||
 | 
					    return /** @type {YXmlElement<{[key:string]:string}>} */ (this.get(name, YXmlElement))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@ -269,7 +294,6 @@ export class Doc extends Observable {
 | 
				
			|||||||
   * @public
 | 
					   * @public
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  getXmlFragment (name = '') {
 | 
					  getXmlFragment (name = '') {
 | 
				
			||||||
    // @ts-ignore
 | 
					 | 
				
			||||||
    return this.get(name, YXmlFragment)
 | 
					    return this.get(name, YXmlFragment)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -313,24 +337,9 @@ export class Doc extends Observable {
 | 
				
			|||||||
        transaction.subdocsRemoved.add(this)
 | 
					        transaction.subdocsRemoved.add(this)
 | 
				
			||||||
      }, null, true)
 | 
					      }, null, true)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.emit('destroyed', [true])
 | 
					    // @ts-ignore
 | 
				
			||||||
 | 
					    this.emit('destroyed', [true]) // DEPRECATED!
 | 
				
			||||||
    this.emit('destroy', [this])
 | 
					    this.emit('destroy', [this])
 | 
				
			||||||
    super.destroy()
 | 
					    super.destroy()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * @param {string} eventName
 | 
					 | 
				
			||||||
   * @param {function(...any):any} f
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  on (eventName, f) {
 | 
					 | 
				
			||||||
    super.on(eventName, f)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * @param {string} eventName
 | 
					 | 
				
			||||||
   * @param {function} f
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  off (eventName, f) {
 | 
					 | 
				
			||||||
    super.off(eventName, f)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import { AbstractType } from '../internals.js' // eslint-disable-line
 | 
					import { AbstractType } from '../internals.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as decoding from 'lib0/decoding'
 | 
					import * as decoding from 'lib0/decoding'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  YArray,
 | 
					  YArray,
 | 
				
			||||||
  YMap,
 | 
					  YMap,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  writeID,
 | 
					  writeID,
 | 
				
			||||||
  readID,
 | 
					  readID,
 | 
				
			||||||
@ -9,6 +8,7 @@ import {
 | 
				
			|||||||
  createID,
 | 
					  createID,
 | 
				
			||||||
  ContentType,
 | 
					  ContentType,
 | 
				
			||||||
  followRedone,
 | 
					  followRedone,
 | 
				
			||||||
 | 
					  getItem,
 | 
				
			||||||
  ID, Doc, AbstractType // eslint-disable-line
 | 
					  ID, Doc, AbstractType // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -257,13 +257,24 @@ export const readRelativePosition = decoder => {
 | 
				
			|||||||
export const decodeRelativePosition = uint8Array => readRelativePosition(decoding.createDecoder(uint8Array))
 | 
					export const decodeRelativePosition = uint8Array => readRelativePosition(decoding.createDecoder(uint8Array))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
@ -275,7 +286,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) : { item: getItem(store, rightID), diff: 0 }
 | 
				
			||||||
    const right = res.item
 | 
					    const right = res.item
 | 
				
			||||||
    if (!(right instanceof Item)) {
 | 
					    if (!(right instanceof Item)) {
 | 
				
			||||||
      return null
 | 
					      return null
 | 
				
			||||||
@ -299,7 +310,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 {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  isDeleted,
 | 
					  isDeleted,
 | 
				
			||||||
  createDeleteSetFromStructStore,
 | 
					  createDeleteSetFromStructStore,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  GC,
 | 
					  GC,
 | 
				
			||||||
  splitItem,
 | 
					  splitItem,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  getState,
 | 
					  getState,
 | 
				
			||||||
  writeStructsFromTransaction,
 | 
					  writeStructsFromTransaction,
 | 
				
			||||||
@ -29,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')
 | 
				
			||||||
@ -38,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"
 | 
				
			||||||
@ -225,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--) {
 | 
				
			||||||
 | 
				
			|||||||
@ -10,13 +10,13 @@ import {
 | 
				
			|||||||
  getItemCleanStart,
 | 
					  getItemCleanStart,
 | 
				
			||||||
  isDeleted,
 | 
					  isDeleted,
 | 
				
			||||||
  addToDeleteSet,
 | 
					  addToDeleteSet,
 | 
				
			||||||
  Transaction, Doc, Item, GC, DeleteSet, AbstractType // eslint-disable-line
 | 
					  YEvent, Transaction, Doc, Item, GC, DeleteSet, AbstractType // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import * as time from 'lib0/time'
 | 
					import * as time from 'lib0/time'
 | 
				
			||||||
import * as array from 'lib0/array'
 | 
					import * as array from 'lib0/array'
 | 
				
			||||||
import * as logging from 'lib0/logging'
 | 
					import * as logging from 'lib0/logging'
 | 
				
			||||||
import { Observable } from 'lib0/observable'
 | 
					import { ObservableV2 } from 'lib0/observable'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class StackItem {
 | 
					export class StackItem {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@ -48,15 +48,10 @@ const clearUndoManagerStackItem = (tr, um, stackItem) => {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {UndoManager} undoManager
 | 
					 * @param {UndoManager} undoManager
 | 
				
			||||||
 * @param {Array<StackItem>} stack
 | 
					 * @param {Array<StackItem>} stack
 | 
				
			||||||
 * @param {string} eventType
 | 
					 * @param {'undo'|'redo'} eventType
 | 
				
			||||||
 * @return {StackItem?}
 | 
					 * @return {StackItem?}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const popStackItem = (undoManager, stack, eventType) => {
 | 
					const popStackItem = (undoManager, stack, eventType) => {
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Whether a change happened
 | 
					 | 
				
			||||||
   * @type {StackItem?}
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  let result = null
 | 
					 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Keep a reference to the transaction so we can fire the event with the changedParentTypes
 | 
					   * Keep a reference to the transaction so we can fire the event with the changedParentTypes
 | 
				
			||||||
   * @type {any}
 | 
					   * @type {any}
 | 
				
			||||||
@ -65,7 +60,7 @@ const popStackItem = (undoManager, stack, eventType) => {
 | 
				
			|||||||
  const doc = undoManager.doc
 | 
					  const doc = undoManager.doc
 | 
				
			||||||
  const scope = undoManager.scope
 | 
					  const scope = undoManager.scope
 | 
				
			||||||
  transact(doc, transaction => {
 | 
					  transact(doc, transaction => {
 | 
				
			||||||
    while (stack.length > 0 && result === null) {
 | 
					    while (stack.length > 0 && undoManager.currStackItem === null) {
 | 
				
			||||||
      const store = doc.store
 | 
					      const store = doc.store
 | 
				
			||||||
      const stackItem = /** @type {StackItem} */ (stack.pop())
 | 
					      const stackItem = /** @type {StackItem} */ (stack.pop())
 | 
				
			||||||
      /**
 | 
					      /**
 | 
				
			||||||
@ -113,7 +108,7 @@ const popStackItem = (undoManager, stack, eventType) => {
 | 
				
			|||||||
          performedChange = true
 | 
					          performedChange = true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      result = performedChange ? stackItem : null
 | 
					      undoManager.currStackItem = performedChange ? stackItem : null
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    transaction.changed.forEach((subProps, type) => {
 | 
					    transaction.changed.forEach((subProps, type) => {
 | 
				
			||||||
      // destroy search marker if necessary
 | 
					      // destroy search marker if necessary
 | 
				
			||||||
@ -123,11 +118,12 @@ const popStackItem = (undoManager, stack, eventType) => {
 | 
				
			|||||||
    })
 | 
					    })
 | 
				
			||||||
    _tr = transaction
 | 
					    _tr = transaction
 | 
				
			||||||
  }, undoManager)
 | 
					  }, undoManager)
 | 
				
			||||||
  if (result != null) {
 | 
					  if (undoManager.currStackItem != null) {
 | 
				
			||||||
    const changedParentTypes = _tr.changedParentTypes
 | 
					    const changedParentTypes = _tr.changedParentTypes
 | 
				
			||||||
    undoManager.emit('stack-item-popped', [{ stackItem: result, type: eventType, changedParentTypes }, undoManager])
 | 
					    undoManager.emit('stack-item-popped', [{ stackItem: undoManager.currStackItem, type: eventType, changedParentTypes, origin: undoManager }, undoManager])
 | 
				
			||||||
 | 
					    undoManager.currStackItem = null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return result
 | 
					  return undoManager.currStackItem
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -143,6 +139,14 @@ const popStackItem = (undoManager, stack, eventType) => {
 | 
				
			|||||||
 * @property {Doc} [doc] The document that this UndoManager operates on. Only needed if typeScope is empty.
 | 
					 * @property {Doc} [doc] The document that this UndoManager operates on. Only needed if typeScope is empty.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @typedef {Object} StackItemEvent
 | 
				
			||||||
 | 
					 * @property {StackItem} StackItemEvent.stackItem
 | 
				
			||||||
 | 
					 * @property {any} StackItemEvent.origin
 | 
				
			||||||
 | 
					 * @property {'undo'|'redo'} StackItemEvent.type
 | 
				
			||||||
 | 
					 * @property {Map<AbstractType<YEvent<any>>,Array<YEvent<any>>>} StackItemEvent.changedParentTypes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Fires 'stack-item-added' event when a stack item was added to either the undo- or
 | 
					 * Fires 'stack-item-added' event when a stack item was added to either the undo- or
 | 
				
			||||||
 * the redo-stack. You may store additional stack information via the
 | 
					 * the redo-stack. You may store additional stack information via the
 | 
				
			||||||
@ -150,9 +154,9 @@ const popStackItem = (undoManager, stack, eventType) => {
 | 
				
			|||||||
 * Fires 'stack-item-popped' event when a stack item was popped from either the
 | 
					 * Fires 'stack-item-popped' event when a stack item was popped from either the
 | 
				
			||||||
 * undo- or the redo-stack. You may restore the saved stack information from `event.stackItem.meta`.
 | 
					 * undo- or the redo-stack. You may restore the saved stack information from `event.stackItem.meta`.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @extends {Observable<'stack-item-added'|'stack-item-popped'|'stack-cleared'|'stack-item-updated'>}
 | 
					 * @extends {ObservableV2<{'stack-item-added':function(StackItemEvent, UndoManager):void, 'stack-item-popped': function(StackItemEvent, UndoManager):void, 'stack-cleared': function({ undoStackCleared: boolean, redoStackCleared: boolean }):void, 'stack-item-updated': function(StackItemEvent, UndoManager):void }>}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class UndoManager extends Observable {
 | 
					export class UndoManager extends ObservableV2 {
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * @param {AbstractType<any>|Array<AbstractType<any>>} typeScope Accepts either a single type, or an array of types
 | 
					   * @param {AbstractType<any>|Array<AbstractType<any>>} typeScope Accepts either a single type, or an array of types
 | 
				
			||||||
   * @param {UndoManagerOptions} options
 | 
					   * @param {UndoManagerOptions} options
 | 
				
			||||||
@ -191,6 +195,12 @@ export class UndoManager extends Observable {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    this.undoing = false
 | 
					    this.undoing = false
 | 
				
			||||||
    this.redoing = false
 | 
					    this.redoing = false
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The currently popped stack item if UndoManager.undoing or UndoManager.redoing
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @type {StackItem|null}
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    this.currStackItem = null
 | 
				
			||||||
    this.lastChange = 0
 | 
					    this.lastChange = 0
 | 
				
			||||||
    this.ignoreRemoteMapChanges = ignoreRemoteMapChanges
 | 
					    this.ignoreRemoteMapChanges = ignoreRemoteMapChanges
 | 
				
			||||||
    this.captureTimeout = captureTimeout
 | 
					    this.captureTimeout = captureTimeout
 | 
				
			||||||
@ -244,6 +254,9 @@ export class UndoManager extends Observable {
 | 
				
			|||||||
          keepItem(item, true)
 | 
					          keepItem(item, true)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					      /**
 | 
				
			||||||
 | 
					       * @type {[StackItemEvent, UndoManager]}
 | 
				
			||||||
 | 
					       */
 | 
				
			||||||
      const changeEvent = [{ stackItem: stack[stack.length - 1], origin: transaction.origin, type: undoing ? 'redo' : 'undo', changedParentTypes: transaction.changedParentTypes }, this]
 | 
					      const changeEvent = [{ stackItem: stack[stack.length - 1], origin: transaction.origin, type: undoing ? 'redo' : 'undo', changedParentTypes: transaction.changedParentTypes }, this]
 | 
				
			||||||
      if (didAdd) {
 | 
					      if (didAdd) {
 | 
				
			||||||
        this.emit('stack-item-added', changeEvent)
 | 
					        this.emit('stack-item-added', changeEvent)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import * as error from 'lib0/error'
 | 
					import * as error from 'lib0/error'
 | 
				
			||||||
import * as encoding from 'lib0/encoding'
 | 
					import * as encoding from 'lib0/encoding'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  isDeleted,
 | 
					  isDeleted,
 | 
				
			||||||
  Item, AbstractType, Transaction, AbstractStruct // eslint-disable-line
 | 
					  Item, AbstractType, Transaction, AbstractStruct // eslint-disable-line
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @module encoding
 | 
					 * @module encoding
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -155,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
 | 
				
			||||||
@ -179,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
 | 
				
			||||||
@ -371,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
 | 
				
			||||||
@ -452,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,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import { AbstractType, Item } from '../internals.js' // eslint-disable-line
 | 
					import { AbstractType, Item } from '../internals.js' // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  AbstractType // eslint-disable-line
 | 
					  AbstractType // eslint-disable-line
 | 
				
			||||||
} from '../internals.js'
 | 
					} from '../internals.js'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import * as binary from 'lib0/binary'
 | 
					import * as binary from 'lib0/binary'
 | 
				
			||||||
import * as decoding from 'lib0/decoding'
 | 
					import * as decoding from 'lib0/decoding'
 | 
				
			||||||
import * as encoding from 'lib0/encoding'
 | 
					import * as encoding from 'lib0/encoding'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Testing if encoding/decoding compatibility and integration compatiblity is given.
 | 
					 * Testing if encoding/decoding compatibility and integration compatiblity is given.
 | 
				
			||||||
 * We expect that the document always looks the same, even if we upgrade the integration algorithm, or add additional encoding approaches.
 | 
					 * We expect that the document always looks the same, even if we upgrade the integration algorithm, or add additional encoding approaches.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import * as Y from '../src/index.js'
 | 
					import * as Y from '../src/index.js'
 | 
				
			||||||
import * as t from 'lib0/testing'
 | 
					import * as t from 'lib0/testing'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import * as Y from '../src/index.js'
 | 
					import * as Y from '../src/index.js'
 | 
				
			||||||
import * as t from 'lib0/testing'
 | 
					import * as t from 'lib0/testing'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -102,3 +101,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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
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 encoding from 'lib0/encoding'
 | 
					import * as encoding from 'lib0/encoding'
 | 
				
			||||||
@ -35,7 +34,7 @@ export const encV1 = {
 | 
				
			|||||||
  mergeUpdates: Y.mergeUpdates,
 | 
					  mergeUpdates: Y.mergeUpdates,
 | 
				
			||||||
  applyUpdate: Y.applyUpdate,
 | 
					  applyUpdate: Y.applyUpdate,
 | 
				
			||||||
  logUpdate: Y.logUpdate,
 | 
					  logUpdate: Y.logUpdate,
 | 
				
			||||||
  updateEventName: 'update',
 | 
					  updateEventName: /** @type {'update'} */ ('update'),
 | 
				
			||||||
  diffUpdate: Y.diffUpdate
 | 
					  diffUpdate: Y.diffUpdate
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -44,7 +43,7 @@ export const encV2 = {
 | 
				
			|||||||
  mergeUpdates: Y.mergeUpdatesV2,
 | 
					  mergeUpdates: Y.mergeUpdatesV2,
 | 
				
			||||||
  applyUpdate: Y.applyUpdateV2,
 | 
					  applyUpdate: Y.applyUpdateV2,
 | 
				
			||||||
  logUpdate: Y.logUpdateV2,
 | 
					  logUpdate: Y.logUpdateV2,
 | 
				
			||||||
  updateEventName: 'updateV2',
 | 
					  updateEventName: /** @type {'updateV2'} */ ('updateV2'),
 | 
				
			||||||
  diffUpdate: Y.diffUpdateV2
 | 
					  diffUpdate: Y.diffUpdateV2
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,46 @@ import { init } from './testHelper.js' // eslint-disable-line
 | 
				
			|||||||
import * as Y from '../src/index.js'
 | 
					import * as Y from '../src/index.js'
 | 
				
			||||||
import * as t from 'lib0/testing'
 | 
					import * as t from 'lib0/testing'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const testInconsistentFormat = () => {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @param {Y.Doc} ydoc
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  const testYjsMerge = ydoc => {
 | 
				
			||||||
 | 
					    const content = /** @type {Y.XmlText} */ (ydoc.get('text', Y.XmlText))
 | 
				
			||||||
 | 
					    content.format(0, 6, { bold: null })
 | 
				
			||||||
 | 
					    content.format(6, 4, { type: 'text' })
 | 
				
			||||||
 | 
					    t.compare(content.toDelta(), [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        attributes: { type: 'text' },
 | 
				
			||||||
 | 
					        insert: 'Merge Test'
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        attributes: { type: 'text', italic: true },
 | 
				
			||||||
 | 
					        insert: ' After'
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ])
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  const initializeYDoc = () => {
 | 
				
			||||||
 | 
					    const yDoc = new Y.Doc({ gc: false })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const content = /** @type {Y.XmlText} */ (yDoc.get('text', Y.XmlText))
 | 
				
			||||||
 | 
					    content.insert(0, ' After', { type: 'text', italic: true })
 | 
				
			||||||
 | 
					    content.insert(0, 'Test', { type: 'text' })
 | 
				
			||||||
 | 
					    content.insert(0, 'Merge ', { type: 'text', bold: true })
 | 
				
			||||||
 | 
					    return yDoc
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    const yDoc = initializeYDoc()
 | 
				
			||||||
 | 
					    testYjsMerge(yDoc)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    const initialYDoc = initializeYDoc()
 | 
				
			||||||
 | 
					    const yDoc = new Y.Doc({ gc: false })
 | 
				
			||||||
 | 
					    Y.applyUpdate(yDoc, Y.encodeStateAsUpdate(initialYDoc))
 | 
				
			||||||
 | 
					    testYjsMerge(yDoc)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {t.TestCase} tc
 | 
					 * @param {t.TestCase} tc
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -675,3 +715,33 @@ export const testUndoDeleteInMap = (tc) => {
 | 
				
			|||||||
  undoManager.undo()
 | 
					  undoManager.undo()
 | 
				
			||||||
  t.compare(map0.toJSON(), { a: 'a' })
 | 
					  t.compare(map0.toJSON(), { a: 'a' })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * It should expose the StackItem being processed if undoing
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {t.TestCase} _tc
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const testUndoDoingStackItem = async (_tc) => {
 | 
				
			||||||
 | 
					  const doc = new Y.Doc()
 | 
				
			||||||
 | 
					  const text = doc.getText('text')
 | 
				
			||||||
 | 
					  const undoManager = new Y.UndoManager([text])
 | 
				
			||||||
 | 
					  undoManager.on('stack-item-added', /** @param {any} event */ event => {
 | 
				
			||||||
 | 
					    event.stackItem.meta.set('str', '42')
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  let metaUndo = /** @type {any} */ (null)
 | 
				
			||||||
 | 
					  let metaRedo = /** @type {any} */ (null)
 | 
				
			||||||
 | 
					  text.observe((event) => {
 | 
				
			||||||
 | 
					    const /** @type {Y.UndoManager} */ origin = event.transaction.origin
 | 
				
			||||||
 | 
					    if (origin === undoManager && origin.undoing) {
 | 
				
			||||||
 | 
					      metaUndo = origin.currStackItem?.meta.get('str')
 | 
				
			||||||
 | 
					    } else if (origin === undoManager && origin.redoing) {
 | 
				
			||||||
 | 
					      metaRedo = origin.currStackItem?.meta.get('str')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  text.insert(0, 'abc')
 | 
				
			||||||
 | 
					  undoManager.undo()
 | 
				
			||||||
 | 
					  undoManager.redo()
 | 
				
			||||||
 | 
					  t.compare(metaUndo, '42', 'currStackItem is accessible while undoing')
 | 
				
			||||||
 | 
					  t.compare(metaRedo, '42', 'currStackItem is accessible while redoing')
 | 
				
			||||||
 | 
					  t.compare(undoManager.currStackItem, null, 'currStackItem is null after observe/transaction')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ import * as object from 'lib0/object'
 | 
				
			|||||||
 * @property {function(Uint8Array):{from:Map<number,number>,to:Map<number,number>}} Enc.parseUpdateMeta
 | 
					 * @property {function(Uint8Array):{from:Map<number,number>,to:Map<number,number>}} Enc.parseUpdateMeta
 | 
				
			||||||
 * @property {function(Y.Doc):Uint8Array} Enc.encodeStateVector
 | 
					 * @property {function(Y.Doc):Uint8Array} Enc.encodeStateVector
 | 
				
			||||||
 * @property {function(Uint8Array):Uint8Array} Enc.encodeStateVectorFromUpdate
 | 
					 * @property {function(Uint8Array):Uint8Array} Enc.encodeStateVectorFromUpdate
 | 
				
			||||||
 * @property {string} Enc.updateEventName
 | 
					 * @property {'update'|'updateV2'} Enc.updateEventName
 | 
				
			||||||
 * @property {string} Enc.description
 | 
					 * @property {string} Enc.description
 | 
				
			||||||
 * @property {function(Uint8Array, Uint8Array):Uint8Array} Enc.diffUpdate
 | 
					 * @property {function(Uint8Array, Uint8Array):Uint8Array} Enc.diffUpdate
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -169,7 +169,7 @@ const checkUpdateCases = (ydoc, updates, enc, hasDeletes) => {
 | 
				
			|||||||
  // t.info('Target State: ')
 | 
					  // t.info('Target State: ')
 | 
				
			||||||
  // enc.logUpdate(targetState)
 | 
					  // enc.logUpdate(targetState)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cases.forEach((mergedUpdates, i) => {
 | 
					  cases.forEach((mergedUpdates) => {
 | 
				
			||||||
    // t.info('State Case $' + i + ':')
 | 
					    // t.info('State Case $' + i + ':')
 | 
				
			||||||
    // enc.logUpdate(updates)
 | 
					    // enc.logUpdate(updates)
 | 
				
			||||||
    const merged = new Y.Doc({ gc: false })
 | 
					    const merged = new Y.Doc({ gc: false })
 | 
				
			||||||
@ -218,10 +218,10 @@ const checkUpdateCases = (ydoc, updates, enc, hasDeletes) => {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {t.TestCase} tc
 | 
					 * @param {t.TestCase} _tc
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const testMergeUpdates1 = tc => {
 | 
					export const testMergeUpdates1 = _tc => {
 | 
				
			||||||
  encoders.forEach((enc, i) => {
 | 
					  encoders.forEach((enc) => {
 | 
				
			||||||
    t.info(`Using encoder: ${enc.description}`)
 | 
					    t.info(`Using encoder: ${enc.description}`)
 | 
				
			||||||
    const ydoc = new Y.Doc({ gc: false })
 | 
					    const ydoc = new Y.Doc({ gc: false })
 | 
				
			||||||
    const updates = /** @type {Array<Uint8Array>} */ ([])
 | 
					    const updates = /** @type {Array<Uint8Array>} */ ([])
 | 
				
			||||||
@ -299,16 +299,16 @@ export const testMergePendingUpdates = tc => {
 | 
				
			|||||||
  Y.applyUpdate(yDoc5, update4)
 | 
					  Y.applyUpdate(yDoc5, update4)
 | 
				
			||||||
  Y.applyUpdate(yDoc5, serverUpdates[4])
 | 
					  Y.applyUpdate(yDoc5, serverUpdates[4])
 | 
				
			||||||
  // @ts-ignore
 | 
					  // @ts-ignore
 | 
				
			||||||
  const update5 = Y.encodeStateAsUpdate(yDoc5) // eslint-disable-line
 | 
					  const _update5 = Y.encodeStateAsUpdate(yDoc5) // eslint-disable-line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const yText5 = yDoc5.getText('textBlock')
 | 
					  const yText5 = yDoc5.getText('textBlock')
 | 
				
			||||||
  t.compareStrings(yText5.toString(), 'nenor')
 | 
					  t.compareStrings(yText5.toString(), 'nenor')
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {t.TestCase} tc
 | 
					 * @param {t.TestCase} _tc
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const testObfuscateUpdates = tc => {
 | 
					export const testObfuscateUpdates = _tc => {
 | 
				
			||||||
  const ydoc = new Y.Doc()
 | 
					  const ydoc = new Y.Doc()
 | 
				
			||||||
  const ytext = ydoc.getText('text')
 | 
					  const ytext = ydoc.getText('text')
 | 
				
			||||||
  const ymap = ydoc.getMap('map')
 | 
					  const ymap = ydoc.getMap('map')
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
@ -189,7 +189,6 @@ export const testClone = _tc => {
 | 
				
			|||||||
  const third = new Y.XmlElement('p')
 | 
					  const third = new Y.XmlElement('p')
 | 
				
			||||||
  yxml.push([first, second, third])
 | 
					  yxml.push([first, second, third])
 | 
				
			||||||
  t.compareArrays(yxml.toArray(), [first, second, third])
 | 
					  t.compareArrays(yxml.toArray(), [first, second, third])
 | 
				
			||||||
 | 
					 | 
				
			||||||
  const cloneYxml = yxml.clone()
 | 
					  const cloneYxml = yxml.clone()
 | 
				
			||||||
  ydoc.getArray('copyarr').insert(0, [cloneYxml])
 | 
					  ydoc.getArray('copyarr').insert(0, [cloneYxml])
 | 
				
			||||||
  t.assert(cloneYxml.length === 3)
 | 
					  t.assert(cloneYxml.length === 3)
 | 
				
			||||||
@ -210,3 +209,15 @@ export const testFormattingBug = _tc => {
 | 
				
			|||||||
  yxml.applyDelta(delta)
 | 
					  yxml.applyDelta(delta)
 | 
				
			||||||
  t.compare(yxml.toDelta(), delta)
 | 
					  t.compare(yxml.toDelta(), delta)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @param {t.TestCase} _tc
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export const testElement = _tc => {
 | 
				
			||||||
 | 
					  const ydoc = new Y.Doc()
 | 
				
			||||||
 | 
					  const yxmlel = ydoc.getXmlElement()
 | 
				
			||||||
 | 
					  const text1 = new Y.XmlText('text1')
 | 
				
			||||||
 | 
					  const text2 = new Y.XmlText('text2')
 | 
				
			||||||
 | 
					  yxmlel.insert(0, [text1, text2])
 | 
				
			||||||
 | 
					  t.compareArrays(yxmlel.toArray(), [text1, text2])
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user