diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index d7aaca98..023ba5d2 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -16,16 +16,16 @@ jobs: strategy: matrix: - node-version: [16.x, 18.x] + node-version: [16.x, 20.x] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: npm run lint - - run: npm run test-extensive + - run: npm run test env: CI: true diff --git a/INTERNALS.md b/INTERNALS.md index a7874076..4daf9659 100644 --- a/INTERNALS.md +++ b/INTERNALS.md @@ -149,8 +149,8 @@ concepts that can be used to create a custom network protocol: * `update`: The Yjs document can be encoded to an *update* object that can be parsed to reconstruct the document. Also every change on the document fires -an incremental document updates that allows clients to sync with each other. -The update object is an Uint8Array that efficiently encodes `Item` objects and +an incremental document update that allows clients to sync with each other. +The update object is a Uint8Array that efficiently encodes `Item` objects and the delete set. * `state vector`: A state vector defines the known state of each user (a set of tuples `(client, clock)`). This object is also efficiently encoded as a diff --git a/LICENSE b/LICENSE index c8c5c6da..f55e8b48 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ The MIT License (MIT) -Copyright (c) 2014 - - Kevin Jahns . +Copyright (c) 2023 + - Kevin Jahns . - Chair of Computer Science 5 (Databases & Information Systems), RWTH Aachen University, Germany Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/README.md b/README.md index 8e5fff2b..df66419a 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,30 @@ Otherwise you can find help on our community [discussion board](https://discuss. Please contribute to the project financially - especially if your company relies on Yjs. [![Become a Sponsor](https://img.shields.io/static/v1?label=Become%20a%20Sponsor&message=%E2%9D%A4&logo=GitHub&style=flat&color=d42f2d)](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 * [AFFiNE](https://affine.pro/) A local-first, privacy-first, open source knowledge base. 🏅 -* [Dynaboard](https://dynaboard.com/) Build web apps collaboratively. :star2: -* [Sana](https://sanalabs.com/) A learning platform with collaborative text - 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: +* [Dynaboard](https://dynaboard.com/) Build web apps collaboratively. :star: * [Relm](https://www.relm.us/) A collaborative gameworld for teamwork and community. :star: * [Room.sh](https://room.sh/) A meeting application with integrated @@ -47,6 +64,8 @@ on Yjs. [![Become a Sponsor](https://img.shields.io/static/v1?label=Become%20a%2 Nimbus Web. :star: * [Pluxbox RadioManager](https://getradiomanager.com/) A web-based app to collaboratively organize radio broadcasts. :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 collaborative notes app. * [PRSM](https://prsm.uk/) Collaborative mind-mapping and system visualisation. *[(source)](https://github.com/micrology/prsm)* @@ -56,16 +75,29 @@ on Yjs. [![Become a Sponsor](https://img.shields.io/static/v1?label=Become%20a%2 * [Slidebeamer](https://slidebeamer.com/) Presentation app. * [BlockSurvey](https://blocksurvey.io) End-to-end encryption for your forms/surveys. * [Skiff](https://skiff.org/) Private, decentralized workspace. +* [JupyterLab](https://jupyter.org/) Collaborative computational Notebooks +* [JupyterCad](https://jupytercad.readthedocs.io/en/latest/) Extension to + JupyterLab that enables collaborative editing of 3d FreeCAD Models. * [Hyperquery](https://hyperquery.ai/) A collaborative data workspace for sharing analyses, documentation, spreadsheets, and dashboards. * [Nosgestesclimat](https://nosgestesclimat.fr/groupe) The french carbon footprint calculator has a group P2P mode based on yjs +* [oorja.io](https://oorja.io) Online meeting spaces extensible with + collaborative apps, end-to-end encrypted. +* [LegendKeeper](https://legendkeeper.com) Collaborative campaign planner and + worldbuilding app for tabletop RPGs. +* [IllumiDesk](https://illumidesk.com/) Build courses and content with A.I. +* [btw](https://www.btw.so) Open-source Medium alternative +* [AWS SageMaker](https://aws.amazon.com/sagemaker/) Tools for building Machine + Learning Models +* [linear](https://linear.app) Streamline issues, projects, and product roadmaps. ## Table of Contents * [Overview](#Overview) * [Bindings](#Bindings) * [Providers](#Providers) + * [Ports](#Ports) * [Getting Started](#Getting-Started) * [API](#API) * [Shared Types](#Shared-Types) @@ -91,9 +123,11 @@ are implemented in separate modules. | [CodeMirror](https://codemirror.net/) | ✔ | [y-codemirror](https://github.com/yjs/y-codemirror) | [demo](https://demos.yjs.dev/codemirror/codemirror.html) | | [Monaco](https://microsoft.github.io/monaco-editor/) | ✔ | [y-monaco](https://github.com/yjs/y-monaco) | [demo](https://demos.yjs.dev/monaco/monaco.html) | | [Slate](https://github.com/ianstormtaylor/slate) | ✔ | [slate-yjs](https://github.com/bitphinix/slate-yjs) | [demo](https://bitphinix.github.io/slate-yjs-example) | +| [BlockSuite](https://github.com/toeverything/blocksuite) | ✔ | (native) | [demo](https://blocksuite-toeverything.vercel.app/?init) | | [valtio](https://github.com/pmndrs/valtio) | | [valtio-yjs](https://github.com/dai-shi/valtio-yjs) | [demo](https://codesandbox.io/s/valtio-yjs-demo-ox3iy) | | [immer](https://github.com/immerjs/immer) | | [immer-yjs](https://github.com/sep2/immer-yjs) | [demo](https://codesandbox.io/s/immer-yjs-demo-6e0znb) | | React / 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 @@ -102,7 +136,19 @@ and storing shared data for offline usage is quite a hassle. **Providers** manage all that for you and are the perfect starting point for your collaborative app. +> This list of providers is incomplete. Please open PRs to add your providers to +> this list! + +#### Connection Providers +
+
y-websocket
+
+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 +leveldb database. y-sweet and ypy-websocket (see below) are +compatible to the y-wesocket protocol. +
y-webrtc
Propagates document updates peer-to-peer using WebRTC. The peers exchange @@ -111,17 +157,22 @@ are available. Communication over the signaling servers can be encrypted by providing a shared secret, keeping the connection information and the shared document private.
-
y-websocket
+
@liveblocks/yjs
-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 -leveldb database. +Liveblocks Yjs provides a fully +hosted WebSocket infrastructure and persisted data store for Yjs +documents. No configuration or maintenance is required. It also features +Yjs webhook events, REST API to read and update Yjs documents, and a +browser DevTools extension.
-
y-indexeddb
+
y-sweet
-Efficiently persists document updates to the browsers indexeddb database. -The document is immediately available and only diffs need to be synced through the -network provider. +A standalone yjs server with persistence to S3 or filesystem. They offer a +cloud service as well. +
+
PartyKit
+
+Cloud service for building multiplayer apps.
y-libp2p
@@ -144,14 +195,59 @@ Use Matrix as transport and storage of Yjs updates, so you can focus building your client app and Matrix can provide powerful features like Authentication, Authorization, Federation, hosting (self-hosting or SaaS) and even End-to-End Encryption (E2EE). -
+ +
yrb-actioncable
+
+An ActionCable companion for Yjs clients. There is a fitting +redis extension as well. +
+
ypy-websocket
+
+Websocket backend, written in Python. +
+
+ +#### Persistence Providers + +
+
y-indexeddb
+
+Efficiently persists document updates to the browsers indexeddb database. +The document is immediately available and only diffs need to be synced through the +network provider. +
y-mongodb-provider
Adds persistent storage to a server with MongoDB. Can be used with the y-websocket provider. -
+ +
+@toeverything/y-indexeddb
+
+Like y-indexeddb, but with sub-documents support and fully TypeScript. +
+
y-fire
+
+A database and connection provider for Yjs based on Firestore. +
+# Ports + +There are several Yjs-compatible ports to other programming languages. + +* [y-octo](https://github.com/toeverything/y-octo) - Rust implementation by +[AFFiNE](https://affine.pro) +* [y-crdt](https://github.com/y-crdt/y-crdt) - Rust implementation with multiple +language bindings to other languages + * [yrs](https://github.com/y-crdt/y-crdt/tree/main/yrs) - Rust interface + * [ypy](https://github.com/y-crdt/ypy) - Python binding + * [yrb](https://github.com/y-crdt/yrb) - Ruby binding + * [yswift](https://github.com/y-crdt/yswift) - Swift binding + * [yffi](https://github.com/y-crdt/y-crdt/tree/main/yffi) - C-FFI + * [ywasm](https://github.com/y-crdt/y-crdt/tree/main/ywasm) - WASM binding +* [ycs](https://github.com/yjs/ycs) - .Net compatible C# implementation. + ## Getting Started Install Yjs and a provider with your favorite package manager: @@ -647,6 +743,8 @@ type. Doesn't log types that have not been defined (using
Define a shared Y.Map type. Is equivalent to y.get(string, Y.Map).
getText(string):Y.Text
Define a shared Y.Text type. Is equivalent to y.get(string, Y.Text).
+ getXmlElement(string, string):Y.XmlElement +
Define a shared Y.XmlElement type. Is equivalent to y.get(string, Y.XmlElement).
getXmlFragment(string):Y.XmlFragment
Define a shared Y.XmlFragment type. Is equivalent to y.get(string, Y.XmlFragment).
on(string, function) @@ -661,7 +759,8 @@ type. Doesn't log types that have not been defined (using on('update', function(updateMessage:Uint8Array, origin:any, Y.Doc):void)
Listen to document updates. Document updates must be transmitted to all other -peers. You can apply document updates in any order and multiple times. +peers. You can apply document updates in any order and multiple times. Use `updateV2` +to receive V2 events.
on('beforeTransaction', function(Y.Transaction, Y.Doc):void)
Emitted before each transaction.
@@ -753,7 +852,7 @@ const diff2 = Y.diffUpdate(currentState2, stateVector1) // sync clients currentState1 = Y.mergeUpdates([currentState1, diff2]) -currentState1 = Y.mergeUpdates([currentState1, diff1]) +currentState2 = Y.mergeUpdates([currentState2, diff1]) ``` #### Obfuscating Updates @@ -786,8 +885,10 @@ 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. 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 -suffix "V2". E.g. `Y.applyUpdate` ⇒ `Y.applyUpdateV2`. We also support conversion -functions between both formats: `Y.convertUpdateFormatV1ToV2` & `Y.convertUpdateFormatV2ToV1`. +suffix "V2". E.g. `Y.applyUpdate` ⇒ `Y.applyUpdateV2`. Also when listening to updates +you need to specifically need listen for V2 events e.g. `yDoc.on('updateV2', …)`. +We also support conversion functions between both formats: +`Y.convertUpdateFormatV1ToV2` & `Y.convertUpdateFormatV2ToV1`. #### Update API @@ -1032,7 +1133,7 @@ doc.transact(() => { ytext.insert(0, 'abc') }, 41) undoManager.undo() -ytext.toString() // => '' (not tracked because 41 is not an instance of +ytext.toString() // => 'abc' (not tracked because 41 is not an instance of // `trackedTransactionorigins`) ytext.delete(0, 3) // revert change diff --git a/package-lock.json b/package-lock.json index f479a8d1..e11d6c60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "yjs", - "version": "13.6.1", + "version": "13.6.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "yjs", - "version": "13.6.1", + "version": "13.6.12", "license": "MIT", "dependencies": { - "lib0": "^0.2.74" + "lib0": "^0.2.86" }, "devDependencies": { "@rollup/plugin-commonjs": "^24.0.1", @@ -34,35 +34,45 @@ "url": "https://github.com/sponsors/dmonad" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -70,9 +80,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -102,6 +112,16 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/@eslint/eslintrc/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -128,6 +148,18 @@ "node": ">= 4" } }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/eslintrc/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -135,15 +167,15 @@ "dev": true }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "node_modules/@rollup/plugin-commonjs": { - "version": "24.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.1.tgz", - "integrity": "sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow==", + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.1.0.tgz", + "integrity": "sha512-eSL45hjhCWI0jCCXcNtLVqM5N1JlBGvlFfY0m6oOYnLCJ6N0qEXoZql4sY2MOUArzhH4SA/qBpTxvvZp2Sc+DQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -165,56 +197,16 @@ } } }, - "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.1.tgz", - "integrity": "sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", + "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.0", + "is-builtin-module": "^3.2.1", "is-module": "^1.0.0", "resolve": "^1.22.1" }, @@ -222,7 +214,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.78.0||^3.0.0" + "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -231,9 +223,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dev": true, "dependencies": { "@types/estree": "^1.0.0", @@ -244,7 +236,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -253,9 +245,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/json5": { @@ -265,9 +257,9 @@ "dev": true }, "node_modules/@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", "dev": true }, "node_modules/@types/markdown-it": { @@ -281,16 +273,19 @@ } }, "node_modules/@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", "dev": true }, "node_modules/@types/node": { - "version": "18.15.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", - "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==", - "dev": true + "version": "18.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.15.tgz", + "integrity": "sha512-AMZ2UWx+woHNfM11PyAEQmfSxi05jm9OlkxczuHeEqmvwPkYj6MWv44gbzDPefYOLysTOFyI3ziiy2ONmUZfpA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/resolve": { "version": "1.20.2", @@ -372,28 +367,31 @@ "dev": true }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "is-string": "^1.0.7" }, "engines": { @@ -404,14 +402,14 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -422,14 +420,14 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -439,6 +437,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -458,9 +478,9 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", + "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", "dev": true, "engines": { "node": ">= 0.4" @@ -497,13 +517,12 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/builtin-modules": { @@ -519,13 +538,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.6.tgz", + "integrity": "sha512-Mj50FLHtlsoVfRfnHaZvyrooHcrlceNZdL/QBvJJVd9Ta55qCQK0gs4ss2oZDeV9zFCs6ewzYgVE5yfVmfFpVg==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "set-function-length": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -773,12 +797,28 @@ "node": ">=0.10.0" } }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "node_modules/define-data-property": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.2.tgz", + "integrity": "sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==", "dev": true, "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -865,12 +905,13 @@ "dev": true }, "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8.6" @@ -895,25 +936,26 @@ } }, "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", + "hasown": "^2.0.0", "internal-slot": "^1.0.5", "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", @@ -921,19 +963,23 @@ "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.12", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -942,27 +988,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -1096,20 +1151,20 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -1171,6 +1226,16 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" } }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1192,6 +1257,18 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-import/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1218,10 +1295,32 @@ "eslint": ">=5.16.0" } }, + "node_modules/eslint-plugin-node/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-node/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1266,6 +1365,16 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7" } }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -1278,13 +1387,25 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -1365,6 +1486,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1434,6 +1565,18 @@ "node": ">= 4" } }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1441,9 +1584,9 @@ "dev": true }, "node_modules/eslint/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1600,12 +1743,13 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -1613,15 +1757,15 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "dev": true, "funding": [ { @@ -1654,9 +1798,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -1668,21 +1812,24 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -1707,14 +1854,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1730,13 +1882,14 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -1746,20 +1899,19 @@ } }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -1832,13 +1984,10 @@ "dev": true }, "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, "engines": { "node": ">= 0.4.0" } @@ -1862,12 +2011,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.2.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1898,12 +2047,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -1912,6 +2061,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2043,13 +2204,13 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -2057,14 +2218,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2132,12 +2295,12 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2289,16 +2452,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -2319,6 +2478,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2409,6 +2574,12 @@ "node": ">=8" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -2446,18 +2617,29 @@ "dev": true }, "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" }, "engines": { "node": ">=4.0" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", @@ -2481,9 +2663,9 @@ } }, "node_modules/lib0": { - "version": "0.2.74", - "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.74.tgz", - "integrity": "sha512-roj9i46/JwG5ik5KNTkxP2IytlnrssAkD/OhlAVtE+GqectrdkfR+pttszVLrOzMDeXNs1MPt6yo66MUolWSiA==", + "version": "0.2.88", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.88.tgz", + "integrity": "sha512-KyroiEvCeZcZEMx5Ys+b4u4eEBbA1ch7XUaBhYpwa/nPMrzTjUhI4RfcytmQfYoTBPcdyx+FX6WFNIoNuJzJfQ==", "dependencies": { "isomorphic.js": "^0.2.4" }, @@ -2492,7 +2674,7 @@ "0serve": "bin/0serve.js" }, "engines": { - "node": ">=14" + "node": ">=16" }, "funding": { "type": "GitHub Sponsors ❤", @@ -2728,6 +2910,16 @@ "node": ">=10" } }, + "node_modules/markdownlint-cli/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/markdownlint-cli/node_modules/commander": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", @@ -2819,9 +3011,9 @@ } }, "node_modules/marked": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", - "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -2849,15 +3041,15 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=10" } }, "node_modules/minimist": { @@ -2924,9 +3116,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2942,13 +3134,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -2960,28 +3152,28 @@ } }, "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -2991,27 +3183,27 @@ } }, "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", + "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", "dev": true, "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -3039,17 +3231,17 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -3355,18 +3547,18 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz", - "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==", + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", "dev": true, "dependencies": { "side-channel": "^1.0.4" @@ -3459,14 +3651,14 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" }, "engines": { "node": ">= 0.4" @@ -3512,12 +3704,12 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -3552,10 +3744,52 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/rollup": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.0.tgz", - "integrity": "sha512-YsIfrk80NqUDrxrjWPXUa7PWvAfegZEXHuPsEZg58fGCdjL1I9C1i/NaG+L+27kxxwkrG/QEDEQc8s/ynXWWGQ==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -3574,6 +3808,24 @@ "integrity": "sha512-Ue4ZB7Dzbn2I9sIj8ws536nOP2S53uypyCkCz9q0vlYD5Kn6/pu4dE+wt2ZfFzd9m73hiYKnnCb1OyKqc+MRkg==", "dev": true }, + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3595,15 +3847,18 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3615,14 +3870,45 @@ "dev": true }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" } }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3645,14 +3931,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3725,9 +4015,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", + "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -3741,9 +4031,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, "node_modules/sprintf-js": { @@ -3853,18 +4143,19 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", "side-channel": "^1.0.4" }, "funding": { @@ -3872,14 +4163,14 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -3889,28 +4180,28 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4033,9 +4324,9 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", @@ -4074,6 +4365,57 @@ "node": ">=8" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.1.tgz", + "integrity": "sha512-RSqu1UEuSlrBhHTWC8O9FnPjOduNs4M7rJ4pRKoEjtx1zUNOPN2sSXHLDX+Y2WPbHIxbvg4JFo2DNAEfPIKWoQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", @@ -4128,6 +4470,12 @@ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "dev": true }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/union": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", @@ -4162,9 +4510,9 @@ "dev": true }, "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", "dev": true }, "node_modules/validate-npm-package-license": { @@ -4209,17 +4557,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -4228,15 +4575,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4259,16 +4597,23 @@ "dev": true }, "node_modules/y-protocols": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.5.tgz", - "integrity": "sha512-Wil92b7cGk712lRHDqS4T90IczF6RkcvCwAD0A2OPg+adKmOe+nOiT/N2hvpQIWS3zfjmtL4CPaH5sIW1Hkm/A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.6.tgz", + "integrity": "sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==", "dev": true, "dependencies": { - "lib0": "^0.2.42" + "lib0": "^0.2.85" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" }, "funding": { "type": "GitHub Sponsors ❤", "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" } }, "node_modules/yallist": { @@ -4276,6 +4621,24 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "node_modules/yjs": { + "version": "13.6.11", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.11.tgz", + "integrity": "sha512-FvRRJKX9u270dOLkllGF/UDCWwmIv2Z+ucM4v1QO1TuxdmoiMnSUXH1HAcOKOrkBEhQtPTkxep7tD2DrQB+l0g==", + "dev": true, + "peer": true, + "dependencies": { + "lib0": "^0.2.86" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } } } } diff --git a/package.json b/package.json index 3919dcda..d0133c49 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yjs", - "version": "13.6.1", + "version": "13.6.12", "description": "Shared Editing Library", "main": "./dist/yjs.cjs", "module": "./dist/yjs.mjs", @@ -75,7 +75,7 @@ }, "homepage": "https://docs.yjs.dev", "dependencies": { - "lib0": "^0.2.74" + "lib0": "^0.2.86" }, "devDependencies": { "@rollup/plugin-commonjs": "^24.0.1", diff --git a/src/index.js b/src/index.js index d23c37f5..ae96b747 100644 --- a/src/index.js +++ b/src/index.js @@ -18,8 +18,10 @@ export { Item, AbstractStruct, GC, + Skip, ContentBinary, ContentDeleted, + ContentDoc, ContentEmbed, ContentFormat, ContentJSON, @@ -50,6 +52,7 @@ export { getItem, typeListToArraySnapshot, typeMapGetSnapshot, + typeMapGetAllSnapshot, createDocFromSnapshot, iterateDeletedStructs, applyUpdate, @@ -92,7 +95,12 @@ export { convertUpdateFormatV2ToV1, obfuscateUpdate, obfuscateUpdateV2, - UpdateEncoderV1 + UpdateEncoderV1, + UpdateEncoderV2, + UpdateDecoderV1, + UpdateDecoderV2, + equalDeleteSets, + snapshotContainsUpdate } from './internals.js' const glo = /** @type {any} */ (typeof globalThis !== 'undefined' diff --git a/src/internals.js b/src/internals.js index bc386f0a..cb2fcac8 100644 --- a/src/internals.js +++ b/src/internals.js @@ -1,4 +1,3 @@ - export * from './utils/AbstractConnector.js' export * from './utils/DeleteSet.js' export * from './utils/Doc.js' diff --git a/src/structs/AbstractStruct.js b/src/structs/AbstractStruct.js index 38457aef..ad000053 100644 --- a/src/structs/AbstractStruct.js +++ b/src/structs/AbstractStruct.js @@ -1,4 +1,3 @@ - import { UpdateEncoderV1, UpdateEncoderV2, ID, Transaction // eslint-disable-line } from '../internals.js' diff --git a/src/structs/ContentDeleted.js b/src/structs/ContentDeleted.js index 7225e1f6..917ba247 100644 --- a/src/structs/ContentDeleted.js +++ b/src/structs/ContentDeleted.js @@ -1,4 +1,3 @@ - import { addToDeleteSet, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line diff --git a/src/structs/ContentDoc.js b/src/structs/ContentDoc.js index 2c3bf8a6..15836f51 100644 --- a/src/structs/ContentDoc.js +++ b/src/structs/ContentDoc.js @@ -1,4 +1,3 @@ - import { Doc, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, Item // eslint-disable-line } from '../internals.js' diff --git a/src/structs/ContentEmbed.js b/src/structs/ContentEmbed.js index a64c53fa..46fba375 100644 --- a/src/structs/ContentEmbed.js +++ b/src/structs/ContentEmbed.js @@ -1,4 +1,3 @@ - import { UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, StructStore, Item, Transaction // eslint-disable-line } from '../internals.js' diff --git a/src/structs/ContentFormat.js b/src/structs/ContentFormat.js index 6ac4c29c..eb2bd0ee 100644 --- a/src/structs/ContentFormat.js +++ b/src/structs/ContentFormat.js @@ -1,6 +1,5 @@ - import { - AbstractType, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Item, StructStore, Transaction // eslint-disable-line + YText, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Item, StructStore, Transaction // eslint-disable-line } from '../internals.js' import * as error from 'lib0/error' @@ -47,28 +46,30 @@ export class ContentFormat { } /** - * @param {number} offset + * @param {number} _offset * @return {ContentFormat} */ - splice (offset) { + splice (_offset) { throw error.methodUnimplemented() } /** - * @param {ContentFormat} right + * @param {ContentFormat} _right * @return {boolean} */ - mergeWith (right) { + mergeWith (_right) { return false } /** - * @param {Transaction} transaction + * @param {Transaction} _transaction * @param {Item} item */ - integrate (transaction, item) { + integrate (_transaction, item) { // @todo searchmarker are currently unsupported for rich text documents - /** @type {AbstractType} */ (item.parent)._searchMarker = null + const p = /** @type {YText} */ (item.parent) + p._searchMarker = null + p._hasFormatting = true } /** diff --git a/src/structs/ContentType.js b/src/structs/ContentType.js index 96a731de..630efeb3 100644 --- a/src/structs/ContentType.js +++ b/src/structs/ContentType.js @@ -1,4 +1,3 @@ - import { readYArray, readYMap, @@ -108,7 +107,7 @@ export class ContentType { while (item !== null) { if (!item.deleted) { item.delete(transaction) - } else { + } else if (item.id.clock < (transaction.beforeState.get(item.id.client) || 0)) { // This will be gc'd later and we want to merge it if possible // We try to merge all deleted items after each transaction, // but we have no knowledge about that this needs to be merged @@ -120,7 +119,7 @@ export class ContentType { this.type._map.forEach(item => { if (!item.deleted) { item.delete(transaction) - } else { + } else if (item.id.clock < (transaction.beforeState.get(item.id.client) || 0)) { // same as above transaction._mergeStructs.push(item) } diff --git a/src/structs/GC.js b/src/structs/GC.js index 42d71f73..3c7cec0c 100644 --- a/src/structs/GC.js +++ b/src/structs/GC.js @@ -1,4 +1,3 @@ - import { AbstractStruct, addStruct, diff --git a/src/structs/Item.js b/src/structs/Item.js index 7e1bc92c..1b7ba939 100644 --- a/src/structs/Item.js +++ b/src/structs/Item.js @@ -1,4 +1,3 @@ - import { GC, getState, @@ -389,9 +388,8 @@ export class Item extends AbstractStruct { } if ((this.left && this.left.constructor === GC) || (this.right && this.right.constructor === GC)) { this.parent = null - } - // only set parent if this shouldn't be garbage collected - if (!this.parent) { + } else if (!this.parent) { + // only set parent if this shouldn't be garbage collected if (this.left && this.left.constructor === Item) { this.parent = this.left.parent this.parentSub = this.left.parentSub diff --git a/src/structs/Skip.js b/src/structs/Skip.js index 3db2399d..3f7caafa 100644 --- a/src/structs/Skip.js +++ b/src/structs/Skip.js @@ -1,4 +1,3 @@ - import { AbstractStruct, UpdateEncoderV1, UpdateEncoderV2, StructStore, Transaction, ID // eslint-disable-line diff --git a/src/types/AbstractType.js b/src/types/AbstractType.js index 144cfc3c..4cc1bf8a 100644 --- a/src/types/AbstractType.js +++ b/src/types/AbstractType.js @@ -1,4 +1,3 @@ - import { removeEventHandlerListener, callEventHandlerListeners, @@ -683,7 +682,7 @@ export const typeListInsertGenericsAfter = (transaction, parent, referenceItem, packJsonContent() } -const lengthExceeded = error.create('Length exceeded!') +const lengthExceeded = () => error.create('Length exceeded!') /** * @param {Transaction} transaction @@ -696,7 +695,7 @@ const lengthExceeded = error.create('Length exceeded!') */ export const typeListInsertGenerics = (transaction, parent, index, content) => { if (index > parent._length) { - throw lengthExceeded + throw lengthExceeded() } if (index === 0) { if (parent._searchMarker) { @@ -798,7 +797,7 @@ export const typeListDelete = (transaction, parent, index, length) => { n = n.right } if (length > 0) { - throw lengthExceeded + throw lengthExceeded() } if (parent._searchMarker) { updateMarkerChanges(parent._searchMarker, startIndex, -startLength + length /* in case we remove the above exception */) @@ -925,6 +924,34 @@ export const typeMapGetSnapshot = (parent, key, snapshot) => { return v !== null && isVisible(v, snapshot) ? v.content.getContent()[v.length - 1] : undefined } +/** + * @param {AbstractType} parent + * @param {Snapshot} snapshot + * @return {Object|number|null|Array|string|Uint8Array|AbstractType|undefined>} + * + * @private + * @function + */ +export const typeMapGetAllSnapshot = (parent, snapshot) => { + /** + * @type {Object} + */ + const res = {} + parent._map.forEach((value, key) => { + /** + * @type {Item|null} + */ + let v = value + while (v !== null && (!snapshot.sv.has(v.id.client) || v.id.clock >= (snapshot.sv.get(v.id.client) || 0))) { + v = v.left + } + if (v !== null && isVisible(v, snapshot)) { + res[key] = v.content.getContent()[v.length - 1] + } + }) + return res +} + /** * @param {Map} map * @return {IterableIterator>} diff --git a/src/types/YMap.js b/src/types/YMap.js index 8dec01ee..16b07f2a 100644 --- a/src/types/YMap.js +++ b/src/types/YMap.js @@ -1,4 +1,3 @@ - /** * @module YMap */ @@ -66,7 +65,7 @@ export class YMapEvent extends YEvent { * A shared Map implementation. * * @extends AbstractType> - * @implements {Iterable} + * @implements {Iterable<[string, MapType]>} */ export class YMap extends AbstractType { /** @@ -177,7 +176,7 @@ export class YMap extends AbstractType { /** * Returns the values for each element in the YMap Type. * - * @return {IterableIterator} + * @return {IterableIterator} */ values () { return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => v[1].content.getContent()[v[1].length - 1]) @@ -186,10 +185,10 @@ export class YMap extends AbstractType { /** * Returns an Iterator of [key, value] pairs * - * @return {IterableIterator} + * @return {IterableIterator<[string, MapType]>} */ entries () { - return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => [v[0], v[1].content.getContent()[v[1].length - 1]]) + return iterator.iteratorMap(createMapIterator(this._map), /** @param {any} v */ v => /** @type {any} */ ([v[0], v[1].content.getContent()[v[1].length - 1]])) } /** @@ -208,7 +207,7 @@ export class YMap extends AbstractType { /** * Returns an Iterator of [key, value] pairs * - * @return {IterableIterator} + * @return {IterableIterator<[string, MapType]>} */ [Symbol.iterator] () { return this.entries() diff --git a/src/types/YText.js b/src/types/YText.js index 8f4f0b60..c02ae6e5 100644 --- a/src/types/YText.js +++ b/src/types/YText.js @@ -1,4 +1,3 @@ - /** * @module YText */ @@ -118,14 +117,15 @@ const findNextPosition = (transaction, pos, count) => { * @param {Transaction} transaction * @param {AbstractType} parent * @param {number} index + * @param {boolean} useSearchMarker * @return {ItemTextListPosition} * * @private * @function */ -const findPosition = (transaction, parent, index) => { +const findPosition = (transaction, parent, index, useSearchMarker) => { const currentAttributes = new Map() - const marker = findMarker(parent, index) + const marker = useSearchMarker ? findMarker(parent, index) : null if (marker) { const pos = new ItemTextListPosition(marker.p.left, marker.p, marker.index, currentAttributes) return findNextPosition(transaction, pos, index - marker.index) @@ -476,6 +476,56 @@ export const cleanupYTextFormatting = type => { return res } +/** + * This will be called by the transction once the event handlers are called to potentially cleanup + * formatting attributes. + * + * @param {Transaction} transaction + */ +export const cleanupYTextAfterTransaction = transaction => { + /** + * @type {Set} + */ + const needFullCleanup = new Set() + // check if another formatting item was inserted + const doc = transaction.doc + for (const [client, afterClock] of transaction.afterState.entries()) { + const clock = transaction.beforeState.get(client) || 0 + if (afterClock === clock) { + continue + } + iterateStructs(transaction, /** @type {Array} */ (doc.store.clients.get(client)), clock, afterClock, item => { + if ( + !item.deleted && /** @type {Item} */ (item).content.constructor === ContentFormat && item.constructor !== GC + ) { + needFullCleanup.add(/** @type {any} */ (item).parent) + } + }) + } + // cleanup in a new transaction + transact(doc, (t) => { + iterateDeletedStructs(transaction, transaction.deleteSet, item => { + if (item instanceof GC || !(/** @type {YText} */ (item.parent)._hasFormatting) || needFullCleanup.has(/** @type {YText} */ (item.parent))) { + return + } + const parent = /** @type {YText} */ (item.parent) + if (item.content.constructor === ContentFormat) { + needFullCleanup.add(parent) + } else { + // If no formatting attribute was inserted or deleted, we can make due with contextless + // formatting cleanups. + // Contextless: it is not necessary to compute currentAttributes for the affected position. + cleanupContextlessFormattingGap(t, item) + } + }) + // If a formatting item was inserted, we simply clean the whole type. + // We need to compute currentAttributes for the current position anyway. + for (const yText of needFullCleanup) { + cleanupYTextFormatting(yText) + } + }) +} + /** * @param {Transaction} transaction * @param {ItemTextListPosition} currPos @@ -809,9 +859,14 @@ export class YText extends AbstractType { */ this._pending = string !== undefined ? [() => this.insert(0, string)] : [] /** - * @type {Array} + * @type {Array|null} */ this._searchMarker = [] + /** + * Whether this YText contains formatting attributes. + * This flag is updated when a formatting item is integrated (see ContentFormat.integrate) + */ + this._hasFormatting = false } /** @@ -859,55 +914,10 @@ export class YText extends AbstractType { _callObserver (transaction, parentSubs) { super._callObserver(transaction, parentSubs) const event = new YTextEvent(this, transaction, parentSubs) - const doc = transaction.doc callTypeObservers(this, transaction, event) // If a remote change happened, we try to cleanup potential formatting duplicates. - if (!transaction.local) { - // check if another formatting item was inserted - let foundFormattingItem = false - for (const [client, afterClock] of transaction.afterState.entries()) { - const clock = transaction.beforeState.get(client) || 0 - if (afterClock === clock) { - continue - } - iterateStructs(transaction, /** @type {Array} */ (doc.store.clients.get(client)), clock, afterClock, item => { - if (!item.deleted && /** @type {Item} */ (item).content.constructor === ContentFormat) { - foundFormattingItem = true - } - }) - if (foundFormattingItem) { - break - } - } - if (!foundFormattingItem) { - iterateDeletedStructs(transaction, transaction.deleteSet, item => { - if (item instanceof GC || foundFormattingItem) { - return - } - if (item.parent === this && item.content.constructor === ContentFormat) { - foundFormattingItem = true - } - }) - } - transact(doc, (t) => { - if (foundFormattingItem) { - // If a formatting item was inserted, we simply clean the whole type. - // We need to compute currentAttributes for the current position anyway. - cleanupYTextFormatting(this) - } else { - // If no formatting attribute was inserted, we can make due with contextless - // formatting cleanups. - // Contextless: it is not necessary to compute currentAttributes for the affected position. - iterateDeletedStructs(t, t.deleteSet, item => { - if (item instanceof GC) { - return - } - if (item.parent === this) { - cleanupContextlessFormattingGap(t, item) - } - }) - } - }) + if (!transaction.local && this._hasFormatting) { + transaction._needFormattingCleanup = true } } @@ -1110,7 +1120,7 @@ export class YText extends AbstractType { const y = this.doc if (y !== null) { transact(y, transaction => { - const pos = findPosition(transaction, this, index) + const pos = findPosition(transaction, this, index, !attributes) if (!attributes) { attributes = {} // @ts-ignore @@ -1128,20 +1138,20 @@ export class YText extends AbstractType { * * @param {number} index The index to insert the embed at. * @param {Object | AbstractType} 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 * * @public */ - insertEmbed (index, embed, attributes = {}) { + insertEmbed (index, embed, attributes) { const y = this.doc if (y !== null) { transact(y, transaction => { - const pos = findPosition(transaction, this, index) - insertText(transaction, this, pos, embed, attributes) + const pos = findPosition(transaction, this, index, !attributes) + insertText(transaction, this, pos, embed, attributes || {}) }) } else { - /** @type {Array} */ (this._pending).push(() => this.insertEmbed(index, embed, attributes)) + /** @type {Array} */ (this._pending).push(() => this.insertEmbed(index, embed, attributes || {})) } } @@ -1160,7 +1170,7 @@ export class YText extends AbstractType { const y = this.doc if (y !== null) { transact(y, transaction => { - deleteText(transaction, findPosition(transaction, this, index), length) + deleteText(transaction, findPosition(transaction, this, index, true), length) }) } else { /** @type {Array} */ (this._pending).push(() => this.delete(index, length)) @@ -1184,7 +1194,7 @@ export class YText extends AbstractType { const y = this.doc if (y !== null) { transact(y, transaction => { - const pos = findPosition(transaction, this, index) + const pos = findPosition(transaction, this, index, false) if (pos.right === null) { return } diff --git a/src/types/YXmlElement.js b/src/types/YXmlElement.js index 92088cdd..1c1f3190 100644 --- a/src/types/YXmlElement.js +++ b/src/types/YXmlElement.js @@ -8,9 +8,10 @@ import { typeMapSet, typeMapGet, typeMapGetAll, + typeMapGetAllSnapshot, typeListForEach, YXmlElementRefID, - YXmlText, ContentType, AbstractType, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Item // eslint-disable-line + Snapshot, YXmlText, ContentType, AbstractType, UpdateDecoderV1, UpdateDecoderV2, UpdateEncoderV1, UpdateEncoderV2, Doc, Item // eslint-disable-line } from '../internals.js' /** @@ -19,7 +20,7 @@ import { /** * 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 childElements that must inherit from YXmlElement @@ -192,12 +193,13 @@ export class YXmlElement extends YXmlFragment { /** * Returns all attribute name/value pairs in a JSON Object. * + * @param {Snapshot} [snapshot] * @return {{ [Key in Extract]?: KV[Key]}} A JSON Object that describes the attributes. * * @public */ - getAttributes () { - return /** @type {any} */ (typeMapGetAll(this)) + getAttributes (snapshot) { + return /** @type {any} */ (snapshot ? typeMapGetAllSnapshot(this, snapshot) : typeMapGetAll(this)) } /** diff --git a/src/types/YXmlEvent.js b/src/types/YXmlEvent.js index 3c2566ed..022b72d5 100644 --- a/src/types/YXmlEvent.js +++ b/src/types/YXmlEvent.js @@ -1,4 +1,3 @@ - import { YEvent, YXmlText, YXmlElement, YXmlFragment, Transaction // eslint-disable-line diff --git a/src/types/YXmlHook.js b/src/types/YXmlHook.js index be8c759b..c5b5ed6d 100644 --- a/src/types/YXmlHook.js +++ b/src/types/YXmlHook.js @@ -1,4 +1,3 @@ - import { YMap, YXmlHookRefID, diff --git a/src/types/YXmlText.js b/src/types/YXmlText.js index 470ce70f..413b247c 100644 --- a/src/types/YXmlText.js +++ b/src/types/YXmlText.js @@ -1,4 +1,3 @@ - import { YText, YXmlTextRefID, diff --git a/src/utils/AbstractConnector.js b/src/utils/AbstractConnector.js index ecf76a3b..5f544684 100644 --- a/src/utils/AbstractConnector.js +++ b/src/utils/AbstractConnector.js @@ -1,4 +1,3 @@ - import { Observable } from 'lib0/observable' import { diff --git a/src/utils/DeleteSet.js b/src/utils/DeleteSet.js index 429c3b91..fe07b7ce 100644 --- a/src/utils/DeleteSet.js +++ b/src/utils/DeleteSet.js @@ -1,4 +1,3 @@ - import { findIndexSS, getState, @@ -328,3 +327,23 @@ export const readAndApplyDeleteSet = (decoder, transaction, store) => { } return null } + +/** + * @param {DeleteSet} ds1 + * @param {DeleteSet} ds2 + */ +export const equalDeleteSets = (ds1, ds2) => { + if (ds1.clients.size !== ds2.clients.size) return false + for (const [client, deleteItems1] of ds1.clients.entries()) { + const deleteItems2 = /** @type {Array} */ (ds2.clients.get(client)) + if (deleteItems2 === undefined || deleteItems1.length !== deleteItems2.length) return false + for (let i = 0; i < deleteItems1.length; i++) { + const di1 = deleteItems1[i] + const di2 = deleteItems2[i] + if (di1.clock !== di2.clock || di1.len !== di2.len) { + return false + } + } + } + return true +} diff --git a/src/utils/Doc.js b/src/utils/Doc.js index d07dd56e..0d8d471b 100644 --- a/src/utils/Doc.js +++ b/src/utils/Doc.js @@ -8,6 +8,7 @@ import { YArray, YText, YMap, + YXmlElement, YXmlFragment, transact, ContentDoc, Item, Transaction, YEvent // eslint-disable-line @@ -113,7 +114,7 @@ export class Doc extends Observable { this.whenSynced = provideSyncedPromise() } this.isSynced = isSynced === undefined || isSynced === true - if (!this.isLoaded) { + if (this.isSynced && !this.isLoaded) { this.emit('load', []) } }) @@ -180,6 +181,7 @@ export class Doc extends Observable { * Define all types right after the Yjs instance is created and store them in a separate object. * Also use the typed methods `getText(name)`, `getArray(name)`, .. * + * @template {typeof AbstractType} Type * @example * const y = new Y(..) * const appState = { @@ -188,12 +190,12 @@ export class Doc extends Observable { * } * * @param {string} name - * @param {Function} TypeConstructor The constructor of the type definition. E.g. Y.Text, Y.Array, Y.Map, ... - * @return {AbstractType} The created type. Constructed with TypeConstructor + * @param {Type} TypeConstructor The constructor of the type definition. E.g. Y.Text, Y.Array, Y.Map, ... + * @return {InstanceType} The created type. Constructed with TypeConstructor * * @public */ - get (name, TypeConstructor = AbstractType) { + get (name, TypeConstructor = /** @type {any} */ (AbstractType)) { const type = map.setIfUndefined(this.share, name, () => { // @ts-ignore const t = new TypeConstructor() @@ -219,12 +221,12 @@ export class Doc extends Observable { t._length = type._length this.share.set(name, t) t._integrate(this, null) - return t + return /** @type {InstanceType} */ (t) } else { throw new Error(`Type with the name ${name} has already been defined with a different constructor`) } } - return type + return /** @type {InstanceType} */ (type) } /** @@ -235,8 +237,7 @@ export class Doc extends Observable { * @public */ getArray (name = '') { - // @ts-ignore - return this.get(name, YArray) + return /** @type {YArray} */ (this.get(name, YArray)) } /** @@ -246,7 +247,6 @@ export class Doc extends Observable { * @public */ getText (name = '') { - // @ts-ignore return this.get(name, YText) } @@ -258,8 +258,17 @@ export class Doc extends Observable { * @public */ getMap (name = '') { - // @ts-ignore - return this.get(name, YMap) + return /** @type {YMap} */ (this.get(name, YMap)) + } + + /** + * @param {string} [name] + * @return {YXmlElement} + * + * @public + */ + getXmlElement (name = '') { + return /** @type {YXmlElement<{[key:string]:string}>} */ (this.get(name, YXmlElement)) } /** @@ -269,7 +278,6 @@ export class Doc extends Observable { * @public */ getXmlFragment (name = '') { - // @ts-ignore return this.get(name, YXmlFragment) } diff --git a/src/utils/ID.js b/src/utils/ID.js index 225ee5b4..b0cabd8f 100644 --- a/src/utils/ID.js +++ b/src/utils/ID.js @@ -1,4 +1,3 @@ - import { AbstractType } from '../internals.js' // eslint-disable-line import * as decoding from 'lib0/decoding' diff --git a/src/utils/PermanentUserData.js b/src/utils/PermanentUserData.js index d9e44f12..80b71259 100644 --- a/src/utils/PermanentUserData.js +++ b/src/utils/PermanentUserData.js @@ -1,4 +1,3 @@ - import { YArray, YMap, diff --git a/src/utils/RelativePosition.js b/src/utils/RelativePosition.js index 614c0bc5..a1b4356b 100644 --- a/src/utils/RelativePosition.js +++ b/src/utils/RelativePosition.js @@ -1,4 +1,3 @@ - import { writeID, readID, diff --git a/src/utils/Snapshot.js b/src/utils/Snapshot.js index a13bb559..777cd39d 100644 --- a/src/utils/Snapshot.js +++ b/src/utils/Snapshot.js @@ -1,4 +1,3 @@ - import { isDeleted, createDeleteSetFromStructStore, @@ -15,7 +14,10 @@ import { findIndexSS, UpdateEncoderV2, applyUpdateV2, - DSEncoderV1, DSEncoderV2, DSDecoderV1, DSDecoderV2, Transaction, Doc, DeleteSet, Item // eslint-disable-line + LazyStructReader, + equalDeleteSets, + UpdateDecoderV1, UpdateDecoderV2, DSEncoderV1, DSEncoderV2, DSDecoderV1, DSDecoderV2, Transaction, Doc, DeleteSet, Item, // eslint-disable-line + mergeDeleteSets } from '../internals.js' import * as map from 'lib0/map' @@ -147,7 +149,7 @@ export const splitSnapshotAffectedStructs = (transaction, snapshot) => { getItemCleanStart(transaction, createID(client, clock)) } }) - iterateDeletedStructs(transaction, snapshot.ds, item => {}) + iterateDeletedStructs(transaction, snapshot.ds, _item => {}) meta.add(snapshot) } } @@ -207,3 +209,28 @@ export const createDocFromSnapshot = (originDoc, snapshot, newDoc = new Doc()) = applyUpdateV2(newDoc, encoder.toUint8Array(), 'snapshot') return newDoc } + +/** + * @param {Snapshot} snapshot + * @param {Uint8Array} update + * @param {typeof UpdateDecoderV2 | typeof UpdateDecoderV1} [YDecoder] + */ +export const snapshotContainsUpdateV2 = (snapshot, update, YDecoder = UpdateDecoderV2) => { + const structs = [] + const updateDecoder = new YDecoder(decoding.createDecoder(update)) + const lazyDecoder = new LazyStructReader(updateDecoder, false) + for (let curr = lazyDecoder.curr; curr !== null; curr = lazyDecoder.next()) { + structs.push(curr) + if ((snapshot.sv.get(curr.id.client) || 0) < curr.id.clock + curr.length) { + return false + } + } + const mergedDS = mergeDeleteSets([snapshot.ds, readDeleteSet(updateDecoder)]) + return equalDeleteSets(snapshot.ds, mergedDS) +} + +/** + * @param {Snapshot} snapshot + * @param {Uint8Array} update + */ +export const snapshotContainsUpdate = (snapshot, update) => snapshotContainsUpdateV2(snapshot, update, UpdateDecoderV1) diff --git a/src/utils/StructStore.js b/src/utils/StructStore.js index 7a2e256c..55a85178 100644 --- a/src/utils/StructStore.js +++ b/src/utils/StructStore.js @@ -1,4 +1,3 @@ - import { GC, splitItem, diff --git a/src/utils/Transaction.js b/src/utils/Transaction.js index 1e553a90..c5931ab4 100644 --- a/src/utils/Transaction.js +++ b/src/utils/Transaction.js @@ -1,4 +1,3 @@ - import { getState, writeStructsFromTransaction, @@ -11,6 +10,7 @@ import { Item, generateNewClientId, createID, + cleanupYTextAfterTransaction, UpdateEncoderV1, UpdateEncoderV2, GC, StructStore, AbstractType, AbstractStruct, YEvent, Doc // eslint-disable-line } from '../internals.js' @@ -114,6 +114,10 @@ export class Transaction { * @type {Set} */ this.subdocsLoaded = new Set() + /** + * @type {boolean} + */ + this._needFormattingCleanup = false } } @@ -161,18 +165,29 @@ export const addChangedTypeToTransaction = (transaction, type, parentSub) => { /** * @param {Array} structs * @param {number} pos + * @return {number} # of merged structs */ -const tryToMergeWithLeft = (structs, pos) => { - const left = structs[pos - 1] - const right = structs[pos] - if (left.deleted === right.deleted && left.constructor === right.constructor) { - if (left.mergeWith(right)) { - structs.splice(pos, 1) - if (right instanceof Item && right.parentSub !== null && /** @type {AbstractType} */ (right.parent)._map.get(right.parentSub) === right) { - /** @type {AbstractType} */ (right.parent)._map.set(right.parentSub, /** @type {Item} */ (left)) +const tryToMergeWithLefts = (structs, pos) => { + let right = structs[pos] + let left = structs[pos - 1] + let i = pos + for (; i > 0; right = left, left = structs[--i - 1]) { + if (left.deleted === right.deleted && left.constructor === right.constructor) { + if (left.mergeWith(right)) { + if (right instanceof Item && right.parentSub !== null && /** @type {AbstractType} */ (right.parent)._map.get(right.parentSub) === right) { + /** @type {AbstractType} */ (right.parent)._map.set(right.parentSub, /** @type {Item} */ (left)) + } + continue } } + break } + const merged = pos - i + if (merged) { + // remove all merged structs from the array + structs.splice(pos + 1 - merged, merged) + } + return merged } /** @@ -219,9 +234,9 @@ const tryMergeDeleteSet = (ds, store) => { for ( let si = mostRightIndexToCheck, struct = structs[si]; si > 0 && struct.id.clock >= deleteItem.clock; - struct = structs[--si] + struct = structs[si] ) { - tryToMergeWithLeft(structs, si) + si -= 1 + tryToMergeWithLefts(structs, si) } } }) @@ -270,31 +285,34 @@ const cleanupTransactions = (transactionCleanups, i) => { ) fs.push(() => { // deep observe events - transaction.changedParentTypes.forEach((events, type) => - fs.push(() => { - // We need to think about the possibility that the user transforms the - // Y.Doc in the event. - if (type._item === null || !type._item.deleted) { - events = events - .filter(event => - event.target._item === null || !event.target._item.deleted - ) - events - .forEach(event => { - event.currentTarget = type - }) - // sort events by path length so that top-level events are fired first. - events - .sort((event1, event2) => event1.path.length - event2.path.length) - // We don't need to check for events.length - // because we know it has at least one element - callEventHandlerListeners(type._dEH, events, transaction) - } - }) - ) - fs.push(() => doc.emit('afterTransaction', [transaction, doc])) + transaction.changedParentTypes.forEach((events, type) => { + // We need to think about the possibility that the user transforms the + // Y.Doc in the event. + if (type._dEH.l.length > 0 && (type._item === null || !type._item.deleted)) { + events = events + .filter(event => + event.target._item === null || !event.target._item.deleted + ) + events + .forEach(event => { + event.currentTarget = type + // path is relative to the current target + event._path = null + }) + // sort events by path length so that top-level events are fired first. + events + .sort((event1, event2) => event1.path.length - event2.path.length) + // We don't need to check for events.length + // because we know it has at least one element + callEventHandlerListeners(type._dEH, events, transaction) + } + }) }) + fs.push(() => doc.emit('afterTransaction', [transaction, doc])) callAll(fs, []) + if (transaction._needFormattingCleanup) { + cleanupYTextAfterTransaction(transaction) + } } finally { // Replace deleted items with ItemDeleted / GC. // This is where content is actually remove from the Yjs Doc. @@ -310,23 +328,25 @@ const cleanupTransactions = (transactionCleanups, i) => { const structs = /** @type {Array} */ (store.clients.get(client)) // we iterate from right to left so we can safely remove entries const firstChangePos = math.max(findIndexSS(structs, beforeClock), 1) - for (let i = structs.length - 1; i >= firstChangePos; i--) { - tryToMergeWithLeft(structs, i) + for (let i = structs.length - 1; i >= firstChangePos;) { + i -= 1 + tryToMergeWithLefts(structs, i) } } }) // try to merge mergeStructs // @todo: it makes more sense to transform mergeStructs to a DS, sort it, and merge from right to left // but at the moment DS does not handle duplicates - for (let i = 0; i < mergeStructs.length; i++) { + for (let i = mergeStructs.length - 1; i >= 0; i--) { const { client, clock } = mergeStructs[i].id const structs = /** @type {Array} */ (store.clients.get(client)) const replacedStructPos = findIndexSS(structs, clock) if (replacedStructPos + 1 < structs.length) { - tryToMergeWithLeft(structs, replacedStructPos + 1) + if (tryToMergeWithLefts(structs, replacedStructPos + 1) > 1) { + continue // no need to perform next check, both are already merged + } } if (replacedStructPos > 0) { - tryToMergeWithLeft(structs, replacedStructPos) + tryToMergeWithLefts(structs, replacedStructPos) } } if (!transaction.local && transaction.afterState.get(doc.clientID) !== transaction.beforeState.get(doc.clientID)) { diff --git a/src/utils/UndoManager.js b/src/utils/UndoManager.js index 746d0f01..f6f13ee5 100644 --- a/src/utils/UndoManager.js +++ b/src/utils/UndoManager.js @@ -15,6 +15,7 @@ import { import * as time from 'lib0/time' import * as array from 'lib0/array' +import * as logging from 'lib0/logging' import { Observable } from 'lib0/observable' export class StackItem { @@ -169,6 +170,7 @@ export class UndoManager extends Observable { * @type {Array>} */ this.scope = [] + this.doc = doc this.addToScope(typeScope) this.deleteFilter = deleteFilter trackedOrigins.add(this) @@ -189,7 +191,6 @@ export class UndoManager extends Observable { */ this.undoing = false this.redoing = false - this.doc = doc this.lastChange = 0 this.ignoreRemoteMapChanges = ignoreRemoteMapChanges this.captureTimeout = captureTimeout @@ -263,6 +264,7 @@ export class UndoManager extends Observable { ytypes = array.isArray(ytypes) ? ytypes : [ytypes] ytypes.forEach(ytype => { if (this.scope.every(yt => yt !== ytype)) { + if (ytype.doc !== this.doc) logging.warn('[yjs#509] Not same Y.Doc') // use MultiDocUndoManager instead. also see https://github.com/yjs/yjs/issues/509 this.scope.push(ytype) } }) diff --git a/src/utils/UpdateEncoder.js b/src/utils/UpdateEncoder.js index e8c5d06c..8cf30381 100644 --- a/src/utils/UpdateEncoder.js +++ b/src/utils/UpdateEncoder.js @@ -1,4 +1,3 @@ - import * as error from 'lib0/error' import * as encoding from 'lib0/encoding' diff --git a/src/utils/YEvent.js b/src/utils/YEvent.js index ac877bc5..13174148 100644 --- a/src/utils/YEvent.js +++ b/src/utils/YEvent.js @@ -1,4 +1,3 @@ - import { isDeleted, Item, AbstractType, Transaction, AbstractStruct // eslint-disable-line @@ -6,6 +5,9 @@ import { import * as set from 'lib0/set' import * as array from 'lib0/array' +import * as error from 'lib0/error' + +const errorComputeChanges = 'You must not compute changes after the event-handler fired.' /** * @template {AbstractType} T @@ -44,6 +46,10 @@ export class YEvent { * @type {null | Array<{ insert?: string | Array | object | AbstractType, retain?: number, delete?: number, attributes?: Object }>} */ this._delta = null + /** + * @type {Array|null} + */ + this._path = null } /** @@ -60,8 +66,7 @@ export class YEvent { * type === event.target // => true */ get path () { - // @ts-ignore _item is defined because target is integrated - return getPathTo(this.currentTarget, this.target) + return this._path || (this._path = getPathTo(this.currentTarget, this.target)) } /** @@ -81,6 +86,9 @@ export class YEvent { */ get keys () { if (this._keys === null) { + if (this.transaction.doc._transactionCleanups.length === 0) { + throw error.create(errorComputeChanges) + } const keys = new Map() const target = this.target const changed = /** @type Set */ (this.transaction.changed.get(target)) @@ -164,6 +172,9 @@ export class YEvent { get changes () { let changes = this._changes if (changes === null) { + if (this.transaction.doc._transactionCleanups.length === 0) { + throw error.create(errorComputeChanges) + } const target = this.target const added = set.create() const deleted = set.create() diff --git a/src/utils/encoding.js b/src/utils/encoding.js index 56e5dac1..2277a140 100644 --- a/src/utils/encoding.js +++ b/src/utils/encoding.js @@ -1,4 +1,3 @@ - /** * @module encoding */ @@ -88,7 +87,7 @@ export const writeClientsStructs = (encoder, store, _sm) => { sm.set(client, clock) } }) - getStateVector(store).forEach((clock, client) => { + getStateVector(store).forEach((_clock, client) => { if (!_sm.has(client)) { sm.set(client, 0) } @@ -98,8 +97,7 @@ export const writeClientsStructs = (encoder, store, _sm) => { // Write items with higher client ids first // This heavily improves the conflict algorithm. array.from(sm.entries()).sort((a, b) => b[0] - a[0]).forEach(([client, clock]) => { - // @ts-ignore - writeStructs(encoder, store.clients.get(client), client, clock) + writeStructs(encoder, /** @type {Array} */ (store.clients.get(client)), client, clock) }) } @@ -252,7 +250,7 @@ const integrateStructs = (transaction, store, clientsStructRefs) => { return nextStructsTarget } let curStructsTarget = getNextStructTarget() - if (curStructsTarget === null && stack.length === 0) { + if (curStructsTarget === null) { return null } diff --git a/src/utils/isParentOf.js b/src/utils/isParentOf.js index d3012e24..d8f5a613 100644 --- a/src/utils/isParentOf.js +++ b/src/utils/isParentOf.js @@ -1,4 +1,3 @@ - import { AbstractType, Item } from '../internals.js' // eslint-disable-line /** diff --git a/src/utils/logging.js b/src/utils/logging.js index 37709763..989ac488 100644 --- a/src/utils/logging.js +++ b/src/utils/logging.js @@ -1,4 +1,3 @@ - import { AbstractType // eslint-disable-line } from '../internals.js' diff --git a/src/utils/updates.js b/src/utils/updates.js index c64ce355..fc40cd57 100644 --- a/src/utils/updates.js +++ b/src/utils/updates.js @@ -1,4 +1,3 @@ - import * as binary from 'lib0/binary' import * as decoding from 'lib0/decoding' import * as encoding from 'lib0/encoding' diff --git a/tests/compatibility.tests.js b/tests/compatibility.tests.js index 3a7ad4fe..fc71364c 100644 --- a/tests/compatibility.tests.js +++ b/tests/compatibility.tests.js @@ -1,4 +1,3 @@ - /** * 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. diff --git a/tests/doc.tests.js b/tests/doc.tests.js index 60524936..bb94819d 100644 --- a/tests/doc.tests.js +++ b/tests/doc.tests.js @@ -1,4 +1,3 @@ - import * as Y from '../src/index.js' import * as t from 'lib0/testing' diff --git a/tests/relativePositions.tests.js b/tests/relativePositions.tests.js index 817b9805..93fec230 100644 --- a/tests/relativePositions.tests.js +++ b/tests/relativePositions.tests.js @@ -1,4 +1,3 @@ - import * as Y from '../src/index.js' import * as t from 'lib0/testing' diff --git a/tests/snapshot.tests.js b/tests/snapshot.tests.js index cd3e4773..4f3ecd47 100644 --- a/tests/snapshot.tests.js +++ b/tests/snapshot.tests.js @@ -3,9 +3,9 @@ import * as t from 'lib0/testing' import { init } from './testHelper.js' /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testBasic = tc => { +export const testBasic = _tc => { const ydoc = new Y.Doc({ gc: false }) ydoc.getText().insert(0, 'world!') const snapshot = Y.snapshot(ydoc) @@ -15,9 +15,24 @@ export const testBasic = tc => { } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testBasicRestoreSnapshot = tc => { +export const testBasicXmlAttributes = _tc => { + const ydoc = new Y.Doc({ gc: false }) + const yxml = ydoc.getMap().set('el', new Y.XmlElement('div')) + const snapshot1 = Y.snapshot(ydoc) + yxml.setAttribute('a', '1') + const snapshot2 = Y.snapshot(ydoc) + yxml.setAttribute('a', '2') + t.compare(yxml.getAttributes(), { a: '2' }) + t.compare(yxml.getAttributes(snapshot2), { a: '1' }) + t.compare(yxml.getAttributes(snapshot1), {}) +} + +/** + * @param {t.TestCase} _tc + */ +export const testBasicRestoreSnapshot = _tc => { const doc = new Y.Doc({ gc: false }) doc.getArray('array').insert(0, ['hello']) const snap = Y.snapshot(doc) @@ -30,9 +45,9 @@ export const testBasicRestoreSnapshot = tc => { } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testEmptyRestoreSnapshot = tc => { +export const testEmptyRestoreSnapshot = _tc => { const doc = new Y.Doc({ gc: false }) const snap = Y.snapshot(doc) snap.sv.set(9999, 0) @@ -50,9 +65,9 @@ export const testEmptyRestoreSnapshot = tc => { } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testRestoreSnapshotWithSubType = tc => { +export const testRestoreSnapshotWithSubType = _tc => { const doc = new Y.Doc({ gc: false }) doc.getArray('array').insert(0, [new Y.Map()]) const subMap = doc.getArray('array').get(0) @@ -73,9 +88,9 @@ export const testRestoreSnapshotWithSubType = tc => { } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testRestoreDeletedItem1 = tc => { +export const testRestoreDeletedItem1 = _tc => { const doc = new Y.Doc({ gc: false }) doc.getArray('array').insert(0, ['item1', 'item2']) @@ -89,9 +104,9 @@ export const testRestoreDeletedItem1 = tc => { } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testRestoreLeftItem = tc => { +export const testRestoreLeftItem = _tc => { const doc = new Y.Doc({ gc: false }) doc.getArray('array').insert(0, ['item1']) doc.getMap('map').set('test', 1) @@ -107,9 +122,9 @@ export const testRestoreLeftItem = tc => { } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testDeletedItemsBase = tc => { +export const testDeletedItemsBase = _tc => { const doc = new Y.Doc({ gc: false }) doc.getArray('array').insert(0, ['item1']) doc.getArray('array').delete(0) @@ -123,9 +138,9 @@ export const testDeletedItemsBase = tc => { } /** - * @param {t.TestCase} tc + * @param {t.TestCase} _tc */ -export const testDeletedItems2 = tc => { +export const testDeletedItems2 = _tc => { const doc = new Y.Doc({ gc: false }) doc.getArray('array').insert(0, ['item1', 'item2', 'item3']) doc.getArray('array').delete(1) @@ -181,3 +196,28 @@ export const testDependentChanges = tc => { const docRestored1 = Y.createDocFromSnapshot(array1.doc, snap) t.compare(docRestored1.getArray('array').toArray(), ['user1item1', 'user2item1']) } + +/** + * @param {t.TestCase} _tc + */ +export const testContainsUpdate = _tc => { + const ydoc = new Y.Doc() + /** + * @type {Array} + */ + const updates = [] + ydoc.on('update', update => { + updates.push(update) + }) + const yarr = ydoc.getArray() + const snapshot1 = Y.snapshot(ydoc) + yarr.insert(0, [1]) + const snapshot2 = Y.snapshot(ydoc) + yarr.delete(0, 1) + const snapshotFinal = Y.snapshot(ydoc) + t.assert(!Y.snapshotContainsUpdate(snapshot1, updates[0])) + t.assert(!Y.snapshotContainsUpdate(snapshot2, updates[1])) + t.assert(Y.snapshotContainsUpdate(snapshot2, updates[0])) + t.assert(Y.snapshotContainsUpdate(snapshotFinal, updates[0])) + t.assert(Y.snapshotContainsUpdate(snapshotFinal, updates[1])) +} diff --git a/tests/testHelper.js b/tests/testHelper.js index 8c90a099..c74b7438 100644 --- a/tests/testHelper.js +++ b/tests/testHelper.js @@ -1,4 +1,3 @@ - import * as t from 'lib0/testing' import * as prng from 'lib0/prng' import * as encoding from 'lib0/encoding' @@ -356,8 +355,9 @@ export const compare = users => { return true }) t.compare(Y.encodeStateVector(users[i]), Y.encodeStateVector(users[i + 1])) - compareDS(Y.createDeleteSetFromStructStore(users[i].store), Y.createDeleteSetFromStructStore(users[i + 1].store)) + Y.equalDeleteSets(Y.createDeleteSetFromStructStore(users[i].store), Y.createDeleteSetFromStructStore(users[i + 1].store)) compareStructStores(users[i].store, users[i + 1].store) + t.compare(Y.encodeSnapshot(Y.snapshot(users[i])), Y.encodeSnapshot(Y.snapshot(users[i + 1]))) } users.map(u => u.destroy()) } @@ -412,25 +412,6 @@ export const compareStructStores = (ss1, ss2) => { } } -/** - * @param {import('../src/internals.js').DeleteSet} ds1 - * @param {import('../src/internals.js').DeleteSet} ds2 - */ -export const compareDS = (ds1, ds2) => { - t.assert(ds1.clients.size === ds2.clients.size) - ds1.clients.forEach((deleteItems1, client) => { - const deleteItems2 = /** @type {Array} */ (ds2.clients.get(client)) - t.assert(deleteItems2 !== undefined && deleteItems1.length === deleteItems2.length) - for (let i = 0; i < deleteItems1.length; i++) { - const di1 = deleteItems1[i] - const di2 = deleteItems2[i] - if (di1.clock !== di2.clock || di1.len !== di2.len) { - t.fail('DeleteSets dont match') - } - } - }) -} - /** * @template T * @callback InitTestObjectCallback diff --git a/tests/undo-redo.tests.js b/tests/undo-redo.tests.js index af7054d4..27636aff 100644 --- a/tests/undo-redo.tests.js +++ b/tests/undo-redo.tests.js @@ -3,6 +3,46 @@ import { init } from './testHelper.js' // eslint-disable-line import * as Y from '../src/index.js' 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 */ diff --git a/tests/y-map.tests.js b/tests/y-map.tests.js index 33221b64..92571c52 100644 --- a/tests/y-map.tests.js +++ b/tests/y-map.tests.js @@ -8,6 +8,54 @@ import * as Y from '../src/index.js' import * as t from 'lib0/testing' import * as prng from 'lib0/prng' +/** + * @param {t.TestCase} _tc + */ +export const testIterators = _tc => { + const ydoc = new Y.Doc() + /** + * @type {Y.Map} + */ + const ymap = ydoc.getMap() + // we are only checking if the type assumptions are correct + /** + * @type {Array} + */ + const vals = Array.from(ymap.values()) + /** + * @type {Array<[string,number]>} + */ + const entries = Array.from(ymap.entries()) + /** + * @type {Array} + */ + const keys = Array.from(ymap.keys()) + console.log(vals, entries, keys) +} + +/** + * Computing event changes after transaction should result in an error. See yjs#539 + * + * @param {t.TestCase} _tc + */ +export const testMapEventError = _tc => { + const doc = new Y.Doc() + const ymap = doc.getMap() + /** + * @type {any} + */ + let event = null + ymap.observe((e) => { + event = e + }) + t.fails(() => { + t.info(event.keys) + }) + t.fails(() => { + t.info(event.keys) + }) +} + /** * @param {t.TestCase} tc */ @@ -339,6 +387,34 @@ export const testObserversUsingObservedeep = tc => { compare(users) } +/** + * @param {t.TestCase} tc + */ +export const testPathsOfSiblingEvents = tc => { + const { users, map0 } = init(tc, { users: 2 }) + /** + * @type {Array>} + */ + const pathes = [] + let calls = 0 + const doc = users[0] + map0.set('map', new Y.Map()) + map0.get('map').set('text1', new Y.Text('initial')) + map0.observeDeep(events => { + events.forEach(event => { + pathes.push(event.path) + }) + calls++ + }) + doc.transact(() => { + map0.get('map').get('text1').insert(0, 'post-') + map0.get('map').set('text2', new Y.Text('new')) + }) + t.assert(calls === 1) + t.compare(pathes, [['map'], ['map', 'text1']]) + compare(users) +} + // TODO: Test events in Y.Map /** * @param {Object} is diff --git a/tests/y-xml.tests.js b/tests/y-xml.tests.js index 1ae2c813..a9395c2d 100644 --- a/tests/y-xml.tests.js +++ b/tests/y-xml.tests.js @@ -189,7 +189,6 @@ export const testClone = _tc => { const third = new Y.XmlElement('p') yxml.push([first, second, third]) t.compareArrays(yxml.toArray(), [first, second, third]) - const cloneYxml = yxml.clone() ydoc.getArray('copyarr').insert(0, [cloneYxml]) t.assert(cloneYxml.length === 3) @@ -210,3 +209,15 @@ export const testFormattingBug = _tc => { yxml.applyDelta(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]) +}