edytor 2.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -4
- package/dist/block/block.svelte.js +2 -4
- package/dist/clipboard/htmlFlow.d.ts +20 -7
- package/dist/clipboard/htmlFlow.js +23 -15
- package/dist/clipboard/serializeClipboardFragment.d.ts +37 -4
- package/dist/clipboard/serializeClipboardFragment.js +6 -4
- package/dist/clipboard/textBlocks.d.ts +8 -0
- package/dist/clipboard/textBlocks.js +6 -2
- package/dist/cloudflare/DocumentRoom.d.ts +13 -9
- package/dist/cloudflare/DocumentRoom.js +10 -6
- package/dist/cloudflare/room/admission.js +3 -3
- package/dist/cloudflare/room/context.d.ts +28 -27
- package/dist/cloudflare/room/context.js +2 -2
- package/dist/cloudflare/room/purge.d.ts +6 -3
- package/dist/cloudflare/room/purge.js +44 -19
- package/dist/cloudflare/room/updates.d.ts +3 -4
- package/dist/cloudflare/room/updates.js +6 -8
- package/dist/cloudflare/routeDocumentSocket.d.ts +17 -0
- package/dist/cloudflare/routeDocumentSocket.js +53 -0
- package/dist/collaboration/comments/client.d.ts +1 -1
- package/dist/collaboration/comments/client.js +1 -1
- package/dist/collaboration/remoteSelection.js +3 -3
- package/dist/components/Edytor.svelte +2 -10
- package/dist/components/Edytor.svelte.d.ts +1 -3
- package/dist/crdt/admission.d.ts +5 -10
- package/dist/crdt/admission.js +5 -11
- package/dist/crdt/attribution/attribution.d.ts +31 -12
- package/dist/crdt/attribution/attribution.js +56 -18
- package/dist/crdt/attribution/block.d.ts +3 -3
- package/dist/crdt/attribution/block.js +7 -8
- package/dist/crdt/attribution/index.d.ts +1 -1
- package/dist/crdt/attribution/index.js +1 -1
- package/dist/crdt/data.d.ts +62 -31
- package/dist/crdt/data.js +211 -103
- package/dist/crdt/doc/delete.d.ts +1 -1
- package/dist/crdt/doc/delete.js +13 -30
- package/dist/crdt/doc/funnel.d.ts +7 -6
- package/dist/crdt/doc/funnel.js +39 -33
- package/dist/crdt/doc/gate.d.ts +3 -20
- package/dist/crdt/doc/gate.js +2 -41
- package/dist/crdt/doc/history.d.ts +25 -9
- package/dist/crdt/doc/history.js +152 -42
- package/dist/crdt/doc/layout.js +11 -22
- package/dist/crdt/doc/meta.js +12 -17
- package/dist/crdt/doc/moves.d.ts +1 -1
- package/dist/crdt/doc/moves.js +52 -32
- package/dist/crdt/doc/reads.js +2 -2
- package/dist/crdt/doc/seed.js +2 -2
- package/dist/crdt/doc/split-merge.js +12 -15
- package/dist/crdt/doc/steps.d.ts +25 -13
- package/dist/crdt/doc/steps.js +52 -122
- package/dist/crdt/doc/types.d.ts +21 -9
- package/dist/crdt/document.d.ts +21 -19
- package/dist/crdt/document.js +26 -23
- package/dist/crdt/edytor-doc.d.ts +66 -68
- package/dist/crdt/edytor-doc.js +21 -20
- package/dist/crdt/engine-api.d.ts +33 -1
- package/dist/crdt/engine.d.ts +0 -1
- package/dist/crdt/engine.js +1 -4
- package/dist/crdt/flow.d.ts +1 -1
- package/dist/crdt/flow.js +25 -27
- package/dist/crdt/index.d.ts +29 -28
- package/dist/crdt/index.js +3 -3
- package/dist/crdt/placement/display.d.ts +5 -30
- package/dist/crdt/placement/display.js +39 -144
- package/dist/crdt/placement/keys.d.ts +58 -0
- package/dist/crdt/placement/keys.js +90 -0
- package/dist/crdt/placement/model.d.ts +119 -118
- package/dist/crdt/placement/model.js +242 -142
- package/dist/crdt/placement/resolve.d.ts +123 -35
- package/dist/crdt/placement/resolve.js +187 -153
- package/dist/crdt/placement/slots.d.ts +134 -0
- package/dist/crdt/placement/slots.js +152 -0
- package/dist/crdt/protocol.d.ts +2 -2
- package/dist/crdt/protocol.js +2 -2
- package/dist/crdt/providers/index.d.ts +1 -1
- package/dist/crdt/providers/room.d.ts +26 -11
- package/dist/crdt/providers/room.js +77 -27
- package/dist/crdt/providers/websocket.d.ts +1 -1
- package/dist/crdt/providers/websocket.js +33 -32
- package/dist/crdt/purge.d.ts +17 -8
- package/dist/crdt/purge.js +236 -126
- package/dist/crdt/restore.d.ts +2 -2
- package/dist/crdt/restore.js +18 -34
- package/dist/crdt/schema.d.ts +22 -21
- package/dist/crdt/schema.js +29 -23
- package/dist/crdt/semantics.js +3 -1
- package/dist/crdt/storage.d.ts +1 -1
- package/dist/crdt/storage.js +1 -1
- package/dist/crdt/structs.d.ts +15 -15
- package/dist/crdt/structs.js +8 -22
- package/dist/crdt/text/index/cache.js +4 -0
- package/dist/crdt/text/index/claims.js +12 -0
- package/dist/crdt/text/index/fold.d.ts +2 -3
- package/dist/crdt/text/index/fold.js +194 -44
- package/dist/crdt/text/index/layout.js +5 -8
- package/dist/crdt/text/index/placement.d.ts +26 -18
- package/dist/crdt/text/index/placement.js +404 -138
- package/dist/crdt/text/index/records.d.ts +3 -3
- package/dist/crdt/text/index/records.js +24 -31
- package/dist/crdt/text/index/shared.d.ts +11 -3
- package/dist/crdt/text/index/shared.js +12 -3
- package/dist/crdt/text/index/state.d.ts +21 -17
- package/dist/crdt/text/index/state.js +15 -17
- package/dist/crdt/text/index/streams.d.ts +10 -5
- package/dist/crdt/text/index/streams.js +78 -27
- package/dist/crdt/text/items.d.ts +10 -3
- package/dist/crdt/text/items.js +7 -0
- package/dist/crdt/text/model.d.ts +77 -62
- package/dist/crdt/text/model.js +84 -169
- package/dist/crdt/text/ranges.d.ts +1 -1
- package/dist/crdt/text/ranges.js +3 -3
- package/dist/crdt/text/rows.d.ts +13 -7
- package/dist/crdt/text/rows.js +24 -7
- package/dist/crdt/text/runs.d.ts +17 -12
- package/dist/crdt/text/runs.js +24 -7
- package/dist/crdt/text/streams.d.ts +26 -13
- package/dist/crdt/text/streams.js +41 -14
- package/dist/crdt/vendor/yjs/UPSTREAM.md +568 -21
- package/dist/crdt/vendor/yjs/dts/global.d.ts +2 -0
- package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
- package/dist/crdt/vendor/yjs/dts/structs/AbstractStruct.d.ts +7 -0
- package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +194 -10
- package/dist/crdt/vendor/yjs/dts/utils/Doc.d.ts +6 -3
- package/dist/crdt/vendor/yjs/dts/utils/StructStore.d.ts +5 -18
- package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +15 -1
- package/dist/crdt/vendor/yjs/dts/utils/UpdateDecoder.d.ts +14 -6
- package/dist/crdt/vendor/yjs/dts/utils/UpdateEncoder.d.ts +33 -6
- package/dist/crdt/vendor/yjs/dts/utils/ids.d.ts +1 -65
- package/dist/crdt/vendor/yjs/dts/utils/marks.d.ts +6 -1
- package/dist/crdt/vendor/yjs/dts/ynode.d.ts +43 -7
- package/dist/crdt/vendor/yjs/global.d.ts +2 -0
- package/dist/crdt/vendor/yjs/src/index.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/AbstractStruct.js +10 -0
- package/dist/crdt/vendor/yjs/src/structs/Item.js +610 -51
- package/dist/crdt/vendor/yjs/src/utils/BlockSet.js +18 -9
- package/dist/crdt/vendor/yjs/src/utils/Doc.js +5 -3
- package/dist/crdt/vendor/yjs/src/utils/StructStore.js +5 -0
- package/dist/crdt/vendor/yjs/src/utils/Transaction.js +36 -13
- package/dist/crdt/vendor/yjs/src/utils/UpdateDecoder.js +88 -18
- package/dist/crdt/vendor/yjs/src/utils/UpdateEncoder.js +119 -32
- package/dist/crdt/vendor/yjs/src/utils/encoding.js +13 -1
- package/dist/crdt/vendor/yjs/src/utils/ids.js +7 -7
- package/dist/crdt/vendor/yjs/src/utils/marks.js +193 -8
- package/dist/crdt/vendor/yjs/src/utils/redo.js +1 -1
- package/dist/crdt/vendor/yjs/src/utils/transaction-helpers.js +1 -1
- package/dist/crdt/vendor/yjs/src/utils/updates.js +3 -3
- package/dist/crdt/vendor/yjs/src/ynode.js +177 -12
- package/dist/dnd/autoScroll.d.ts +15 -7
- package/dist/dnd/autoScroll.js +10 -15
- package/dist/dnd/dropIndicator.js +2 -5
- package/dist/dnd/external.d.ts +6 -0
- package/dist/dnd/external.js +17 -0
- package/dist/dnd/geometry.d.ts +2 -0
- package/dist/dnd/geometry.js +3 -4
- package/dist/dnd/placement.d.ts +1 -1
- package/dist/dnd/pragmatic.d.ts +3 -1
- package/dist/dnd/pragmatic.js +12 -2
- package/dist/dnd/vendor/pragmatic/UPSTREAM.md +51 -18
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.d.ts +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.d.ts +0 -2
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.js +4 -22
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter-types.d.ts +26 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.d.ts +30 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.js +203 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-items.js +13 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-types.js +9 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/is-an-available-type.js +19 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.d.ts +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.js +6 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/make-honey-pot-fix.js +4 -16
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/internal-types.d.ts +1 -8
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-drop-target.js +5 -6
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-monitor.js +2 -3
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.d.ts +1 -1
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +6 -24
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.d.ts +2 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js +5 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.d.ts +3 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js +12 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/native-types.d.ts +12 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window-in-safari.js +10 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window.js +55 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.d.ts +4 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.js +8 -0
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/internal-types.d.ts +0 -4
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/get-scroll-by.js +16 -72
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/try-scroll.js +1 -9
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/configuration.js +4 -29
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-scroll-change.js +2 -3
- package/dist/edytor.svelte.d.ts +2 -5
- package/dist/edytor.svelte.js +21 -32
- package/dist/events/beforeInputCommands.js +2 -2
- package/dist/events/onBeforeInput.js +1 -1
- package/dist/events/onDrop.d.ts +0 -6
- package/dist/events/onDrop.js +10 -23
- package/dist/events/onInput.d.ts +0 -12
- package/dist/events/onInput.js +1 -67
- package/dist/events/onPageHide.d.ts +3 -0
- package/dist/events/onPageHide.js +16 -0
- package/dist/export/forms.d.ts +627 -0
- package/dist/export/forms.js +749 -0
- package/dist/export/index.d.ts +170 -0
- package/dist/export/index.js +161 -0
- package/dist/export/markdown.d.ts +41 -0
- package/dist/export/markdown.js +585 -0
- package/dist/export/markdownWriter.d.ts +9 -0
- package/dist/export/markdownWriter.js +133 -0
- package/dist/export/mdx.d.ts +15 -0
- package/dist/export/mdx.js +33 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/kinds.js +1 -1
- package/dist/plugins/anchored.svelte.d.ts +21 -25
- package/dist/plugins/anchored.svelte.js +23 -39
- package/dist/plugins/blockHandles/BlockHandleController.svelte.js +24 -32
- package/dist/plugins/blockHandles/dragPreview.d.ts +26 -7
- package/dist/plugins/blockHandles/dragPreview.js +33 -0
- package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +5 -0
- package/dist/plugins/blockMenu/BlockMenuController.svelte.js +7 -2
- package/dist/plugins/blockMenu/blockMenuPlugin.js +5 -50
- package/dist/plugins/chrome.d.ts +27 -5
- package/dist/plugins/chrome.js +24 -9
- package/dist/plugins/code/CodePlugin.svelte +12 -9
- package/dist/plugins/code/header.svelte.js +7 -11
- package/dist/plugins/code/languageMenu.svelte.d.ts +5 -2
- package/dist/plugins/code/languageMenu.svelte.js +13 -20
- package/dist/plugins/columns/ColumnsPlugin.svelte +7 -20
- package/dist/plugins/columns/resize.svelte.d.ts +2 -3
- package/dist/plugins/columns/resize.svelte.js +2 -5
- package/dist/plugins/comments/CommentsController.svelte.d.ts +6 -0
- package/dist/plugins/comments/CommentsController.svelte.js +20 -0
- package/dist/plugins/equation/EquationPlugin.svelte +12 -22
- package/dist/plugins/equation/equation.svelte.d.ts +7 -15
- package/dist/plugins/equation/equation.svelte.js +13 -50
- package/dist/plugins/equation/tex.d.ts +17 -0
- package/dist/plugins/equation/tex.js +42 -0
- package/dist/plugins/fileDrop.d.ts +38 -23
- package/dist/plugins/fileDrop.js +82 -76
- package/dist/plugins/find/FindController.svelte.d.ts +5 -0
- package/dist/plugins/find/FindController.svelte.js +14 -14
- package/dist/plugins/find/findPlugin.js +1 -15
- package/dist/plugins/image/ImageChrome.svelte +8 -2
- package/dist/plugins/image/ImagePlugin.svelte +15 -52
- package/dist/plugins/image/controls.svelte.js +16 -2
- package/dist/plugins/image/toolbar.svelte.d.ts +5 -4
- package/dist/plugins/image/toolbar.svelte.js +21 -31
- package/dist/plugins/index.d.ts +1 -1
- package/dist/plugins/list.svelte.d.ts +9 -0
- package/dist/plugins/list.svelte.js +18 -0
- package/dist/plugins/marquee/marqueePlugin.js +0 -4
- package/dist/plugins/media/AudioPlugin.svelte +1 -1
- package/dist/plugins/media/BookmarkPlugin.svelte +6 -97
- package/dist/plugins/media/EmbedPlugin.svelte +5 -90
- package/dist/plugins/media/EmptySlot.svelte +36 -20
- package/dist/plugins/media/EmptySlot.svelte.d.ts +6 -15
- package/dist/plugins/media/FilePlugin.svelte +1 -19
- package/dist/plugins/media/MediaEmpty.svelte +2 -55
- package/dist/plugins/media/MediaEmpty.svelte.d.ts +18 -14
- package/dist/plugins/media/SourceBlock.svelte +142 -52
- package/dist/plugins/media/SourceBlock.svelte.d.ts +10 -4
- package/dist/plugins/media/VideoPlugin.svelte +1 -1
- package/dist/plugins/media/empty.svelte.js +2 -7
- package/dist/plugins/media/media.d.ts +2 -63
- package/dist/plugins/media/media.js +1 -194
- package/dist/plugins/media/sources.d.ts +60 -0
- package/dist/plugins/media/sources.js +165 -0
- package/dist/plugins/media/urlPaste.svelte.d.ts +2 -1
- package/dist/plugins/media/urlPaste.svelte.js +12 -21
- package/dist/plugins/mention/MentionPlugin.svelte +8 -35
- package/dist/plugins/page/PagePlugin.svelte +2 -9
- package/dist/plugins/page/page.js +1 -1
- package/dist/plugins/pageLink/PageLinkPlugin.svelte +6 -13
- package/dist/plugins/richtext/RichTextPlugin.svelte +85 -197
- package/dist/plugins/richtext/body.js +1 -1
- package/dist/plugins/richtext/calloutIcons.svelte.d.ts +2 -2
- package/dist/plugins/richtext/calloutIcons.svelte.js +5 -7
- package/dist/plugins/richtext/richTextOperations.d.ts +1 -19
- package/dist/plugins/richtext/richTextOperations.js +3 -49
- package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +2 -0
- package/dist/plugins/slashMenu/SlashMenuController.svelte.js +7 -0
- package/dist/plugins/slashMenu/slashMenuPlugin.js +5 -14
- package/dist/plugins/table/TableChrome.svelte +2 -3
- package/dist/plugins/table/TablePlugin.svelte +20 -54
- package/dist/plugins/table/chrome.svelte.d.ts +5 -2
- package/dist/plugins/table/chrome.svelte.js +30 -54
- package/dist/plugins/table/table.js +3 -3
- package/dist/plugins/toc/TocPlugin.svelte +2 -4
- package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +7 -0
- package/dist/plugins/toolbar/ToolbarController.svelte.js +20 -13
- package/dist/plugins/toolbar/toolbarPlugin.js +19 -53
- package/dist/plugins/triggers/TriggerController.svelte.d.ts +7 -2
- package/dist/plugins/triggers/TriggerController.svelte.js +11 -4
- package/dist/plugins/triggers/place.js +1 -2
- package/dist/plugins/triggers/triggers.d.ts +6 -1
- package/dist/plugins/triggers/triggers.js +12 -13
- package/dist/plugins/uploads.svelte.d.ts +5 -2
- package/dist/plugins/uploads.svelte.js +25 -15
- package/dist/plugins.d.ts +26 -0
- package/dist/plugins.js +0 -24
- package/dist/selection/replaceSelection.js +2 -2
- package/dist/selection/selection.svelte.d.ts +4 -10
- package/dist/selection/selection.svelte.js +7 -11
- package/dist/session/bindings.js +1 -1
- package/dist/session/commands.d.ts +7 -11
- package/dist/session/commands.js +13 -19
- package/dist/session/inputRules.js +1 -1
- package/dist/session/navigation.js +1 -1
- package/dist/session/suggestions.svelte.d.ts +0 -11
- package/dist/session/suggestions.svelte.js +15 -3
- package/dist/session/uploads.d.ts +8 -8
- package/dist/surface/lines.js +1 -3
- package/dist/surface/observer.svelte.d.ts +17 -1
- package/dist/surface/observer.svelte.js +74 -19
- package/dist/surface/overlay.d.ts +0 -14
- package/dist/surface/overlay.js +0 -25
- package/dist/surface/projector.svelte.d.ts +15 -3
- package/dist/surface/projector.svelte.js +60 -9
- package/dist/text/text.svelte.js +3 -13
- package/dist/utils/sanitize.d.ts +38 -0
- package/dist/utils/sanitize.js +82 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +5 -0
- package/package.json +19 -2
- package/dist/crdt/placement/rank.d.ts +0 -87
- package/dist/crdt/placement/rank.js +0 -332
- package/dist/crdt/placement/source.d.ts +0 -43
- package/dist/crdt/placement/source.js +0 -66
- package/dist/crdt/text/delete-index.d.ts +0 -129
- package/dist/crdt/text/delete-index.js +0 -365
- package/dist/crdt/text/deletes.d.ts +0 -76
- package/dist/crdt/text/deletes.js +0 -362
- package/dist/crdt/text/index/anchored.d.ts +0 -17
- package/dist/crdt/text/index/anchored.js +0 -197
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/max-z-index.js +0 -3
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/supports-popover.js +0 -16
- package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/is-axis-allowed.js +0 -3
- package/dist/plugins/code/LanguageMenu.svelte +0 -25
- package/dist/plugins/code/LanguageMenu.svelte.d.ts +0 -9
- package/dist/plugins/equation/EquationEditor.svelte +0 -27
- package/dist/plugins/equation/EquationEditor.svelte.d.ts +0 -9
- package/dist/plugins/image/ImageToolbarHost.svelte +0 -37
- package/dist/plugins/image/ImageToolbarHost.svelte.d.ts +0 -9
- package/dist/plugins/richtext/CalloutIconPicker.svelte +0 -26
- package/dist/plugins/richtext/CalloutIconPicker.svelte.d.ts +0 -9
package/dist/crdt/doc/funnel.js
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* frame's one attribution pass.
|
|
6
|
-
*/
|
|
7
|
-
import { blockNodeOf, buildInline, materializeSpec, ownText, view as modelView, writePlacement, writeSplit } from '../placement/model.js';
|
|
8
|
-
import { ENTRY_FACET } from '../text/runs.js';
|
|
9
|
-
import { AT, DEL_PREFIX, ID, LAST_CHANGED_ATTR, TYPE } from '../schema.js';
|
|
10
|
-
import { writeLeaves } from '../data.js';
|
|
1
|
+
import { blockNodeOf, buildInline, insertSpecsAt, moveBlocksTo, ownText, view as modelView, writeSplit } from '../placement/model.js';
|
|
2
|
+
import { ENTRY_FACET, SEQ_FACET } from '../text/runs.js';
|
|
3
|
+
import { DEL_PREFIX, ID, LAST_CHANGED_ATTR, TYPE } from '../schema.js';
|
|
4
|
+
import { writeData } from '../data.js';
|
|
11
5
|
import { NOOP } from './plan.js';
|
|
12
6
|
import { claimInto, deleteRange, formatRangeIn, insertIntoText } from '../text/model.js';
|
|
13
7
|
/**
|
|
14
|
-
* Raised when
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* bare `bindEdytorDoc` facade has no document
|
|
8
|
+
* Raised when an operation runs against a torn-down document: every attach
|
|
9
|
+
* reference released, or its facade disposed (terminal for writes; reads
|
|
10
|
+
* stay dead-safe: a stale handle may still be inspected). Distinct from
|
|
11
|
+
* `DocumentNotReadyError`: destroyed is terminal, pending may still resolve.
|
|
12
|
+
* Kept in this module because a bare `bindEdytorDoc` facade has no document
|
|
13
|
+
* layer above it.
|
|
19
14
|
*/
|
|
20
|
-
export class
|
|
15
|
+
export class DocumentDestroyedError extends Error {
|
|
21
16
|
constructor(service) {
|
|
22
|
-
super(
|
|
23
|
-
this.name = '
|
|
17
|
+
super(`${service ?? 'document'}: the document is destroyed`);
|
|
18
|
+
this.name = 'DocumentDestroyedError';
|
|
24
19
|
}
|
|
25
20
|
}
|
|
26
21
|
/** The write funnel of one facade. */
|
|
@@ -37,7 +32,7 @@ export const writeFunnel = (c) => {
|
|
|
37
32
|
/** Mutation boundary — every facade write funnels through `write`. */
|
|
38
33
|
const write = (fn) => {
|
|
39
34
|
if (disposed) {
|
|
40
|
-
throw new
|
|
35
|
+
throw new DocumentDestroyedError();
|
|
41
36
|
}
|
|
42
37
|
config.assertWritable?.();
|
|
43
38
|
return fn();
|
|
@@ -54,8 +49,8 @@ export const writeFunnel = (c) => {
|
|
|
54
49
|
// Each apply opens a frame that tracks the index's folds. When it
|
|
55
50
|
// closes, ONE pass over the facets the fold saw stamps attribution: a
|
|
56
51
|
// block whose registry entry was created gets its `createdBy` record; a block whose content, claims, type or data
|
|
57
|
-
// changed gets a contributor stamp; moves
|
|
58
|
-
// nothing. Two intents the effects cannot name are recorded by their
|
|
52
|
+
// changed gets a contributor stamp; moves (a record or a slot in a
|
|
53
|
+
// block's sequence) and delete marks stamp nothing. Two intents the effects cannot name are recorded by their
|
|
59
54
|
// steps: a split-born block inherits its source's contributors, and a
|
|
60
55
|
// merge survivor unions the absorbed block's. With no configured
|
|
61
56
|
// `actor` the funnel writes no attribution at all.
|
|
@@ -73,9 +68,12 @@ export const writeFunnel = (c) => {
|
|
|
73
68
|
else
|
|
74
69
|
for (const facet of facets)
|
|
75
70
|
if (!facet.startsWith(DEL_PREFIX) &&
|
|
76
|
-
![ENTRY_FACET,
|
|
71
|
+
![ENTRY_FACET, SEQ_FACET, ID, LAST_CHANGED_ATTR].includes(facet))
|
|
77
72
|
changed.add(id);
|
|
78
73
|
}
|
|
74
|
+
// A merge changed its survivor (its claim item, written quietly, is no edit of the text holding it).
|
|
75
|
+
for (const [into] of f.unions)
|
|
76
|
+
changed.add(into);
|
|
79
77
|
for (const id of created) {
|
|
80
78
|
const node = blockNodeOf(doc, id);
|
|
81
79
|
if (node !== null)
|
|
@@ -92,38 +90,46 @@ export const writeFunnel = (c) => {
|
|
|
92
90
|
/**
|
|
93
91
|
* A streamless block gets its own text before the first write that
|
|
94
92
|
* needs a stream (`ownText`: a writer derived from its dead
|
|
95
|
-
* incarnation); its attribution record follows the re-minted nonce.
|
|
93
|
+
* incarnation); its attribution record follows the re-minted nonce. A
|
|
94
|
+
* claim item needs the block's own stream (`claim`); text, any piece of
|
|
95
|
+
* its display.
|
|
96
96
|
*/
|
|
97
|
-
const needStream = (id) => {
|
|
98
|
-
|
|
97
|
+
const needStream = (id, claim = false) => {
|
|
98
|
+
const { own } = modelView(doc);
|
|
99
|
+
if (claim ? own.streamOf(id) !== undefined : (own.display(id) ?? []).length > 0)
|
|
99
100
|
return;
|
|
100
101
|
const { from, to } = ownText(doc, id);
|
|
101
102
|
BA.retarget(doc, id, from, to);
|
|
102
103
|
};
|
|
103
104
|
/** One planned step, written (the plan decided it; writers never refuse). */
|
|
104
105
|
const writeStep = (w, f) => {
|
|
105
|
-
//
|
|
106
|
+
// Delete marks need no view: they write one node.
|
|
106
107
|
if (w.op === 'deleteBlock')
|
|
107
108
|
return w.marks.forEach((id) => blockNodeOf(doc, id).setAttr(DEL_PREFIX + doc.clientID, true));
|
|
108
109
|
if (w.op === 'splitBlock' || w.op === 'insertText' || w.op === 'insertInline')
|
|
109
110
|
needStream(w.id);
|
|
110
|
-
|
|
111
|
+
// A claim item goes at the end of the stream of the block merged into.
|
|
112
|
+
if (w.op === 'mergeBlocks')
|
|
113
|
+
needStream(w.into, true);
|
|
114
|
+
const v = modelView(doc);
|
|
115
|
+
const { blocks, own } = v;
|
|
111
116
|
const node = (id) => blockNodeOf(doc, id);
|
|
112
117
|
switch (w.op) {
|
|
113
118
|
case 'insertBlocks':
|
|
114
|
-
return
|
|
119
|
+
return insertSpecsAt(doc, v, w.parent, w.index, w.specs, w.split === undefined ? null : (f.bounds.get(w.split) ?? null));
|
|
115
120
|
case 'moveBlocks':
|
|
116
|
-
return w.ids.
|
|
121
|
+
return moveBlocksTo(doc, v, w.ids, w.parent, w.index, w.side ?? 0, w.part ?? 0, w.at ?? null);
|
|
117
122
|
case 'splitBlock':
|
|
118
123
|
f.inherit.set(w.newId, w.id);
|
|
119
|
-
|
|
124
|
+
f.bounds.set(w.newId, writeSplit(doc, w.id, w.offset, w.newId, w.tail, w.parent, w.index));
|
|
125
|
+
return;
|
|
120
126
|
case 'mergeBlocks':
|
|
121
127
|
f.unions.push([w.into, w.from]);
|
|
122
|
-
return claimInto(
|
|
128
|
+
return f.quiet(() => claimInto(own, w.from, w.into));
|
|
123
129
|
case 'setBlockType':
|
|
124
130
|
return void node(w.id).setAttr(TYPE, w.type);
|
|
125
131
|
case 'patchData':
|
|
126
|
-
return
|
|
132
|
+
return writeData(dataNode(w.id, w.inlineId), w.writes);
|
|
127
133
|
case 'insertText':
|
|
128
134
|
return insertIntoText(doc, blocks, own, w.id, w.offset, w.text, w.marks);
|
|
129
135
|
case 'insertInline':
|
|
@@ -149,7 +155,7 @@ export const writeFunnel = (c) => {
|
|
|
149
155
|
}
|
|
150
156
|
return write(() => doc.transact(() => {
|
|
151
157
|
const frame = runsView.track();
|
|
152
|
-
const f = { inherit: new Map(), unions: [] };
|
|
158
|
+
const f = { inherit: new Map(), bounds: new Map(), unions: [], quiet: frame.quiet };
|
|
153
159
|
try {
|
|
154
160
|
for (const w of p.writes)
|
|
155
161
|
writeStep(w, f);
|
package/dist/crdt/doc/gate.d.ts
CHANGED
|
@@ -17,15 +17,15 @@
|
|
|
17
17
|
*
|
|
18
18
|
* ```
|
|
19
19
|
* doc.get('blocks') registry — flat map, blockId → node('block')
|
|
20
|
-
* └ <blockId>
|
|
21
|
-
* (n: incarnation nonce)
|
|
20
|
+
* └ <blockId> n/type/d/…/del./wd./l + content
|
|
21
|
+
* (n: incarnation nonce; the id is the key)
|
|
22
22
|
* doc.get('meta') version record root
|
|
23
23
|
* ├ v : number SCHEMA_VERSION (LWW attr — concurrent init converges)
|
|
24
24
|
* └ schema : 'edytor-doc' SCHEMA_NAME
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
import type { EngineDoc } from '../engine-api.js';
|
|
28
|
-
export declare const SCHEMA_VERSION:
|
|
28
|
+
export declare const SCHEMA_VERSION: 10;
|
|
29
29
|
export declare const SCHEMA_NAME: "edytor-doc";
|
|
30
30
|
export declare const META_KEY: "meta";
|
|
31
31
|
/**
|
|
@@ -86,20 +86,3 @@ export declare class SchemaMismatchError extends Error {
|
|
|
86
86
|
* mutating a synced document.
|
|
87
87
|
*/
|
|
88
88
|
export declare const assertSchema: (doc: EngineDoc, docName?: string) => void;
|
|
89
|
-
/**
|
|
90
|
-
* Error raised by {@link assertUsableDoc} — the doc cannot host a v14 facade:
|
|
91
|
-
* a foreign engine object (a v13 `yjs` Doc — a different CRDT implementation
|
|
92
|
-
* entirely).
|
|
93
|
-
*/
|
|
94
|
-
export declare class UnsupportedDocError extends Error {
|
|
95
|
-
readonly kind: 'foreign';
|
|
96
|
-
constructor(kind: 'foreign');
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Document-boundary guard run by {@link EdytorDocBinding.create} before the
|
|
100
|
-
* runs view attaches. The facade only speaks the v14 unified-node surface —
|
|
101
|
-
* without this gate a foreign doc dies obscurely inside `buildView`
|
|
102
|
-
* (`registry.forEachAttr is not a function`); it fails fast with an
|
|
103
|
-
* actionable error instead.
|
|
104
|
-
*/
|
|
105
|
-
export declare const assertUsableDoc: (doc: EngineDoc) => void;
|
package/dist/crdt/doc/gate.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SCHEMA } from '../schema.js';
|
|
2
2
|
export const SCHEMA_VERSION = SCHEMA.version;
|
|
3
3
|
export const SCHEMA_NAME = SCHEMA.name;
|
|
4
4
|
export const META_KEY = SCHEMA.roots.meta;
|
|
@@ -51,13 +51,7 @@ export class SchemaMismatchError extends Error {
|
|
|
51
51
|
docName;
|
|
52
52
|
problem;
|
|
53
53
|
constructor(docName, problem) {
|
|
54
|
-
super(problem.kind
|
|
55
|
-
? `Document "${docName}" carries replicated registry state but no meta.v schema version — refusing to treat it as initialized.`
|
|
56
|
-
: problem.kind === 'unsupported'
|
|
57
|
-
? `Document "${docName}" claims unsupported schema version ${problem.version} (this build speaks ${SCHEMA_VERSION}).`
|
|
58
|
-
: problem.schema === undefined
|
|
59
|
-
? `Document "${docName}" carries meta.v=${problem.version} but no meta.schema manifest name — refusing it as an "${SCHEMA_NAME}" document.`
|
|
60
|
-
: `Document "${docName}" claims foreign schema "${String(problem.schema)}" (this build speaks "${SCHEMA_NAME}").`);
|
|
54
|
+
super(`${docName}: ${problem.kind} schema version ${problem.version} "${String(problem.schema)}" (this build speaks ${SCHEMA_VERSION} "${SCHEMA_NAME}")`);
|
|
61
55
|
this.docName = docName;
|
|
62
56
|
this.problem = problem;
|
|
63
57
|
this.name = 'SchemaMismatchError';
|
|
@@ -73,36 +67,3 @@ export const assertSchema = (doc, docName = 'doc') => {
|
|
|
73
67
|
if (problem !== null)
|
|
74
68
|
throw new SchemaMismatchError(docName, problem);
|
|
75
69
|
};
|
|
76
|
-
/**
|
|
77
|
-
* Error raised by {@link assertUsableDoc} — the doc cannot host a v14 facade:
|
|
78
|
-
* a foreign engine object (a v13 `yjs` Doc — a different CRDT implementation
|
|
79
|
-
* entirely).
|
|
80
|
-
*/
|
|
81
|
-
export class UnsupportedDocError extends Error {
|
|
82
|
-
kind;
|
|
83
|
-
constructor(kind) {
|
|
84
|
-
super('Document is not a v14 engine doc — the `blocks` registry is not a ' +
|
|
85
|
-
'unified Y.Node. Use `crdt.createDoc()` (or `new Y.Doc()` from `edytor/crdt`).');
|
|
86
|
-
this.kind = kind;
|
|
87
|
-
this.name = 'UnsupportedDocError';
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Document-boundary guard run by {@link EdytorDocBinding.create} before the
|
|
92
|
-
* runs view attaches. The facade only speaks the v14 unified-node surface —
|
|
93
|
-
* without this gate a foreign doc dies obscurely inside `buildView`
|
|
94
|
-
* (`registry.forEachAttr is not a function`); it fails fast with an
|
|
95
|
-
* actionable error instead.
|
|
96
|
-
*/
|
|
97
|
-
export const assertUsableDoc = (doc) => {
|
|
98
|
-
let registry;
|
|
99
|
-
try {
|
|
100
|
-
registry = typeof doc?.get === 'function' ? doc.get(SCHEMA.roots.registry) : undefined;
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
registry = undefined;
|
|
104
|
-
}
|
|
105
|
-
if (!isNodeLike(registry) || typeof registry.forEachAttr !== 'function') {
|
|
106
|
-
throw new UnsupportedDocError('foreign');
|
|
107
|
-
}
|
|
108
|
-
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { EngineApi, EngineDoc, EngineNode } from '../engine-api.js';
|
|
2
|
-
import type { TextDeletes } from '../text/deletes.js';
|
|
3
2
|
import { type IdSetOf, type StoreStruct } from '../structs.js';
|
|
4
3
|
import { type WriteFunnel } from './funnel.js';
|
|
5
4
|
import type { DocBase } from './reads.js';
|
|
@@ -33,15 +32,12 @@ export type HistoryOptions = {
|
|
|
33
32
|
}) => boolean;
|
|
34
33
|
};
|
|
35
34
|
/** What a history is made over: the document and the rules of its replay. */
|
|
36
|
-
type Rules = {
|
|
35
|
+
export type Rules = {
|
|
37
36
|
Y: EngineApi;
|
|
38
37
|
doc: EngineDoc;
|
|
39
38
|
scope: EngineNode[];
|
|
40
|
-
/** The
|
|
41
|
-
|
|
42
|
-
restoreFilter(item: unknown): boolean;
|
|
43
|
-
onApply(tr: unknown, step: StackItem): void;
|
|
44
|
-
};
|
|
39
|
+
/** The records list a replay's text holds go to (fork patch YP20). */
|
|
40
|
+
records: EngineNode;
|
|
45
41
|
/** Whether an item a replay would delete is withdrawn instead (`hist.undo.withdraw`). */
|
|
46
42
|
withdraw(item: StoreStruct, step: StackItem): boolean;
|
|
47
43
|
/** Repair the attrs a replay left undefined. */
|
|
@@ -85,16 +81,36 @@ export declare class UndoManager {
|
|
|
85
81
|
redo(): StackItem | null;
|
|
86
82
|
/** Drop every step (undo and redo) and release what they kept for their replay. */
|
|
87
83
|
clear(): void;
|
|
84
|
+
/**
|
|
85
|
+
* The session ends: its page left for good (`hist.release.end`). Every
|
|
86
|
+
* step is dropped and released as a dropped step is (`#release`: what
|
|
87
|
+
* they kept is collected, the text this writer's records hold is
|
|
88
|
+
* deleted for good), in one transaction that, when a step marked a block
|
|
89
|
+
* deleted or withdrawn, also appends one release record (the
|
|
90
|
+
* {@link RELEASE_ROOT} list): its id names this writer and the clock the
|
|
91
|
+
* history ended at, so the room's purge removes what those marks hide at
|
|
92
|
+
* its next tick, past the horizon or not. Then the manager stops
|
|
93
|
+
* capturing (it is destroyed; the document attaches a fresh one if asked).
|
|
94
|
+
* A history that captured nothing writes nothing. Only for a page that
|
|
95
|
+
* cannot come back: a page the back/forward cache keeps, or one that
|
|
96
|
+
* only lost its connection, keeps its history.
|
|
97
|
+
*/
|
|
98
|
+
end(): void;
|
|
88
99
|
destroy: () => void;
|
|
89
100
|
}
|
|
90
101
|
/** What a facade's history is made over: its doc, the write funnel and the bound engine layers. */
|
|
91
102
|
export type HistoryContext = DocBase & Pick<WriteFunnel, 'write' | 'disposed'> & {
|
|
92
|
-
D: TextDeletes;
|
|
93
103
|
/** Stamp the version record before the history attaches. */
|
|
94
104
|
init: (doc: EngineDoc) => void;
|
|
95
105
|
};
|
|
106
|
+
/**
|
|
107
|
+
* The document's history rules over `doc` (the one set every history of an
|
|
108
|
+
* edytor document runs): its scope (the block registry, the text hold
|
|
109
|
+
* records, the document's data), the records a replay's text holds go to,
|
|
110
|
+
* the withdraw rule (`hist.undo.withdraw`) and the attr repair below.
|
|
111
|
+
*/
|
|
112
|
+
export declare const historyRules: (Y: EngineApi, doc: EngineDoc) => Rules;
|
|
96
113
|
/** The history factory of one facade. */
|
|
97
114
|
export declare const docHistory: (c: HistoryContext) => {
|
|
98
115
|
createUndoManager: (options?: HistoryOptions) => UndoManager;
|
|
99
116
|
};
|
|
100
|
-
export {};
|
package/dist/crdt/doc/history.js
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The document's history: the one undo manager (fork patch YP18 removed the
|
|
3
3
|
* engine's). It captures the tracked local transactions that write in its
|
|
4
|
-
* scope (the block registry, the text
|
|
4
|
+
* scope (the block registry, the text hold records, the document's data)
|
|
5
5
|
* into steps, and an undo or a redo replays a step in one transaction over
|
|
6
|
-
* the engine's struct primitives (`redoItem`, `keepItem`). Its rules: text
|
|
7
|
-
*
|
|
6
|
+
* the engine's struct primitives (`redoItem`, `keepItem`). Its rules: a text
|
|
7
|
+
* delete is a hold record (fork patch YP20), so undoing it deletes the record
|
|
8
|
+
* and the text shows again unless another writer's record holds it
|
|
9
|
+
* (`hist.undo.restore`); undoing typing holds the typed text; an undone
|
|
8
10
|
* creation is withdrawn (`hist.undo.withdraw`), an overwritten attr is
|
|
9
|
-
* repaired, the stack keeps `limit` steps,
|
|
10
|
-
* steps below it (`hist.purge.horizon`)
|
|
11
|
+
* repaired, the stack keeps `limit` steps, the purge horizon drops the
|
|
12
|
+
* steps below it (`hist.purge.horizon`), and a session's end releases them
|
|
13
|
+
* all (`hist.release.end`).
|
|
11
14
|
*/
|
|
12
15
|
import { getUnixTime } from 'lib0-v14/time';
|
|
13
|
-
import { ownTextIds } from '../text/model.js';
|
|
16
|
+
import { openSteps, ownTextIds } from '../text/model.js';
|
|
14
17
|
import { readHorizon } from '../purge.js';
|
|
15
|
-
import { BLOCK_NODE, DATA_LEAF_PREFIX, DOC_DATA_ROOT, HORIZON_ROOT, INLINE_NODE, LAST_CHANGED_ATTR, TYPE } from '../schema.js';
|
|
18
|
+
import { BLOCK_NODE, CONTENT_NODE, DATA_LEAF_PREFIX, DEL_PREFIX, DOC_DATA_ROOT, HORIZON_ROOT, INLINE_NODE, LAST_CHANGED_ATTR, RELEASE_ROOT, TEXT_DELETES_ROOT, TYPE, WITHDRAW_PREFIX } from '../schema.js';
|
|
16
19
|
import { changedUnder, collectable, collectNow, collects, dropSearchMarkers, engineOps, walkIdSet } from '../structs.js';
|
|
17
20
|
import { isInitialized } from './gate.js';
|
|
18
|
-
import {
|
|
21
|
+
import { DocumentDestroyedError } from './funnel.js';
|
|
19
22
|
import { registryOf, withdrawOnUndo } from '../placement/model.js';
|
|
20
23
|
/** The undo steps a document's history keeps by default: older ones are released. */
|
|
21
24
|
export const DEFAULT_HISTORY_LIMIT = 200;
|
|
@@ -37,6 +40,13 @@ const REPAIRED = {
|
|
|
37
40
|
[BLOCK_NODE]: [TYPE, LAST_CHANGED_ATTR],
|
|
38
41
|
[INLINE_NODE]: [TYPE]
|
|
39
42
|
};
|
|
43
|
+
/** A unit of a block's text: a character or an inline atom (what a hold record holds). */
|
|
44
|
+
const isUnit = (it) => {
|
|
45
|
+
const content = it.content;
|
|
46
|
+
return (it.parentSub === null &&
|
|
47
|
+
it.parent?.name === CONTENT_NODE &&
|
|
48
|
+
(typeof content?.str === 'string' || content?.type?.name === INLINE_NODE));
|
|
49
|
+
};
|
|
40
50
|
/**
|
|
41
51
|
* A document's undo manager: the undo and redo stacks of the tracked local
|
|
42
52
|
* transactions in its scope. `undo()`/`redo()` replay the top step and
|
|
@@ -64,6 +74,10 @@ export class UndoManager {
|
|
|
64
74
|
/** What dropped steps released (an item is released once every step that deleted it is gone). */
|
|
65
75
|
#released;
|
|
66
76
|
#horizon;
|
|
77
|
+
/** A captured step wrote a block's delete or withdraw mark: the session's end records its release. */
|
|
78
|
+
#marked = false;
|
|
79
|
+
/** The session ended (`end()`): nothing more is released. */
|
|
80
|
+
#ended = false;
|
|
67
81
|
constructor(rules, options = {}) {
|
|
68
82
|
this.#rules = rules;
|
|
69
83
|
this.#ops = engineOps(rules.Y);
|
|
@@ -78,7 +92,19 @@ export class UndoManager {
|
|
|
78
92
|
this.trackedOrigins.add(this);
|
|
79
93
|
this.#ops.on(rules.doc, 'afterTransaction', this.#afterTransaction);
|
|
80
94
|
this.#ops.on(rules.doc, 'destroy', this.destroy);
|
|
95
|
+
const open = openSteps.get(rules.doc) ?? new Set();
|
|
96
|
+
openSteps.set(rules.doc, open.add(this.#open));
|
|
81
97
|
}
|
|
98
|
+
/** What the step still capturing inserted (`null`: none is open): a text delete there removes. */
|
|
99
|
+
#open = () => {
|
|
100
|
+
const top = this.undoStack.at(-1);
|
|
101
|
+
const open = top !== undefined &&
|
|
102
|
+
!this.undoing &&
|
|
103
|
+
!this.redoing &&
|
|
104
|
+
this.lastChange > 0 &&
|
|
105
|
+
getUnixTime() - this.lastChange < this.captureTimeout;
|
|
106
|
+
return open ? top.inserts : null;
|
|
107
|
+
};
|
|
82
108
|
/** Be told of every step taken into a stack (added, or the open one updated). Returns the unsubscribe. */
|
|
83
109
|
observe(f) {
|
|
84
110
|
this.#observers.add(f);
|
|
@@ -118,8 +144,39 @@ export class UndoManager {
|
|
|
118
144
|
clear() {
|
|
119
145
|
this.#release([...this.undoStack.splice(0), ...this.redoStack.splice(0)]);
|
|
120
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* The session ends: its page left for good (`hist.release.end`). Every
|
|
149
|
+
* step is dropped and released as a dropped step is (`#release`: what
|
|
150
|
+
* they kept is collected, the text this writer's records hold is
|
|
151
|
+
* deleted for good), in one transaction that, when a step marked a block
|
|
152
|
+
* deleted or withdrawn, also appends one release record (the
|
|
153
|
+
* {@link RELEASE_ROOT} list): its id names this writer and the clock the
|
|
154
|
+
* history ended at, so the room's purge removes what those marks hide at
|
|
155
|
+
* its next tick, past the horizon or not. Then the manager stops
|
|
156
|
+
* capturing (it is destroyed; the document attaches a fresh one if asked).
|
|
157
|
+
* A history that captured nothing writes nothing. Only for a page that
|
|
158
|
+
* cannot come back: a page the back/forward cache keeps, or one that
|
|
159
|
+
* only lost its connection, keeps its history.
|
|
160
|
+
*/
|
|
161
|
+
end() {
|
|
162
|
+
if (this.#ended)
|
|
163
|
+
return;
|
|
164
|
+
this.#ended = true;
|
|
165
|
+
const dropped = [...this.undoStack.splice(0), ...this.redoStack.splice(0)];
|
|
166
|
+
const marked = this.#marked;
|
|
167
|
+
if (dropped.length > 0 || marked)
|
|
168
|
+
this.doc.transact(() => {
|
|
169
|
+
this.#release(dropped);
|
|
170
|
+
if (marked) {
|
|
171
|
+
const records = this.doc.get(RELEASE_ROOT);
|
|
172
|
+
records.insert(records.length, [true]);
|
|
173
|
+
}
|
|
174
|
+
}, HISTORY_TRIM);
|
|
175
|
+
this.destroy();
|
|
176
|
+
}
|
|
121
177
|
destroy = () => {
|
|
122
178
|
this.trackedOrigins.delete(this);
|
|
179
|
+
openSteps.get(this.doc)?.delete(this.#open);
|
|
123
180
|
this.#ops.off(this.doc, 'afterTransaction', this.#afterTransaction);
|
|
124
181
|
this.#ops.off(this.doc, 'destroy', this.destroy);
|
|
125
182
|
this.#observers.clear();
|
|
@@ -164,6 +221,14 @@ export class UndoManager {
|
|
|
164
221
|
stack.push(new StackItem(tr.insertSet, tr.deleteSet));
|
|
165
222
|
if (!undoing && !redoing)
|
|
166
223
|
this.lastChange = now;
|
|
224
|
+
// A block's delete or withdraw mark: what it hides waits for this
|
|
225
|
+
// history (its end releases it to the purge, `end()`).
|
|
226
|
+
if (!this.#marked)
|
|
227
|
+
for (const keys of tr.changed.values())
|
|
228
|
+
for (const key of keys)
|
|
229
|
+
if (typeof key === 'string' &&
|
|
230
|
+
(key.startsWith(DEL_PREFIX) || key.startsWith(WITHDRAW_PREFIX)))
|
|
231
|
+
this.#marked = true;
|
|
167
232
|
// What the step deleted is kept from collection while a step may bring it back.
|
|
168
233
|
ops.iterate(tr, tr.deleteSet, (item) => {
|
|
169
234
|
if (ops.isItem(item) && this.#inScope(item))
|
|
@@ -190,13 +255,14 @@ export class UndoManager {
|
|
|
190
255
|
}
|
|
191
256
|
/**
|
|
192
257
|
* Replay the top step of `stack` in one transaction (origin: this
|
|
193
|
-
* manager): what it inserted is deleted (
|
|
194
|
-
*
|
|
258
|
+
* manager): what it inserted is deleted (text: held by a record of this
|
|
259
|
+
* writer; a block: withdrawn), what it deleted comes back (a text delete
|
|
260
|
+
* was a record: deleting it shows the text), the overwritten attrs are
|
|
195
261
|
* repaired. A step that changes nothing is skipped for the one below.
|
|
196
262
|
*/
|
|
197
263
|
#pop(stack) {
|
|
198
264
|
const ops = this.#ops;
|
|
199
|
-
const {
|
|
265
|
+
const { records, withdraw, repair } = this.#rules;
|
|
200
266
|
const deletedByHistory = (id) => [this.undoStack, this.redoStack].some((s) => s.some((step) => step.deletes.has(id.client, id.clock)));
|
|
201
267
|
this.doc.transact((transaction) => {
|
|
202
268
|
const tr = transaction;
|
|
@@ -204,11 +270,18 @@ export class UndoManager {
|
|
|
204
270
|
const step = stack.pop();
|
|
205
271
|
const restore = new Set();
|
|
206
272
|
const remove = [];
|
|
273
|
+
const held = [];
|
|
207
274
|
let changed = false;
|
|
208
275
|
ops.iterate(tr, step.inserts, (struct) => {
|
|
209
276
|
if (!ops.isItem(struct))
|
|
210
277
|
return;
|
|
211
278
|
const item = ops.latest(tr, struct);
|
|
279
|
+
// An atom the step inserted is held whole: its attrs stay with it.
|
|
280
|
+
const atom = item.parent?._item;
|
|
281
|
+
if (atom?.id &&
|
|
282
|
+
isUnit(atom) &&
|
|
283
|
+
step.inserts.has(atom.id.client, atom.id.clock))
|
|
284
|
+
return;
|
|
212
285
|
if (!item.deleted && this.#inScope(item))
|
|
213
286
|
remove.push(item);
|
|
214
287
|
});
|
|
@@ -218,25 +291,27 @@ export class UndoManager {
|
|
|
218
291
|
// Created and deleted within the step: nothing to bring back.
|
|
219
292
|
if (step.inserts.has(struct.id.client, struct.id.clock))
|
|
220
293
|
return;
|
|
221
|
-
// Text
|
|
222
|
-
if (
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
restore.add(struct);
|
|
294
|
+
// Text a record holds stays hidden: the record decides (removed with its node).
|
|
295
|
+
if ((struct.holds ?? 0) > 0)
|
|
296
|
+
return;
|
|
297
|
+
restore.add(struct);
|
|
226
298
|
});
|
|
227
299
|
for (const item of restore)
|
|
228
300
|
changed = ops.redo(tr, item, restore, step.inserts, deletedByHistory) !== null || changed;
|
|
229
301
|
// Children before parents: more is known when an item is judged.
|
|
230
302
|
for (let i = remove.length - 1; i >= 0; i--) {
|
|
231
|
-
|
|
232
|
-
|
|
303
|
+
const item = remove[i];
|
|
304
|
+
// Text the step wrote is held, never removed: a redo shows it again where it was.
|
|
305
|
+
if (isUnit(item))
|
|
306
|
+
held.push(item.id.client, item.id.clock, item.length);
|
|
307
|
+
else if (!withdraw(item, step))
|
|
308
|
+
ops.remove(tr, item);
|
|
233
309
|
changed = true;
|
|
234
310
|
}
|
|
311
|
+
records.hold(held);
|
|
235
312
|
this.currStackItem = changed ? step : null;
|
|
236
|
-
if (changed)
|
|
237
|
-
marks.onApply(tr, step);
|
|
313
|
+
if (changed)
|
|
238
314
|
repair(step);
|
|
239
|
-
}
|
|
240
315
|
}
|
|
241
316
|
tr.changed.forEach((keys, node) => {
|
|
242
317
|
if (keys.has(null))
|
|
@@ -250,8 +325,8 @@ export class UndoManager {
|
|
|
250
325
|
/**
|
|
251
326
|
* Release what dropped steps kept for their replay: the engine collects
|
|
252
327
|
* that content now, as it would have at the delete without a history
|
|
253
|
-
* (the doc's `gcFilter` still decides
|
|
254
|
-
*
|
|
328
|
+
* (the doc's `gcFilter` still decides), and the text their hold records
|
|
329
|
+
* hold is deleted for good. An item is released only
|
|
255
330
|
* once every step that deleted part of it was dropped (the engine merges
|
|
256
331
|
* deleted items across steps): never split, so the store keeps its
|
|
257
332
|
* merged items. Only the items themselves are released: a kept
|
|
@@ -269,6 +344,8 @@ export class UndoManager {
|
|
|
269
344
|
return (released.clients.get(st.id.client)?.getIds() ?? []).some((r) => r.clock <= st.id.clock && end <= r.clock + r.len);
|
|
270
345
|
};
|
|
271
346
|
const gc = collects(doc);
|
|
347
|
+
const ops = this.#ops;
|
|
348
|
+
const { records } = this.#rules;
|
|
272
349
|
doc.transact((tr) => {
|
|
273
350
|
for (const step of dropped)
|
|
274
351
|
walkIdSet(Y, doc, step.deletes, (st) => {
|
|
@@ -279,6 +356,32 @@ export class UndoManager {
|
|
|
279
356
|
if (gc && it.deleted && collectable(doc, it))
|
|
280
357
|
collectNow(it, tr);
|
|
281
358
|
});
|
|
359
|
+
// A dropped step's text deletes can never be undone here: what this
|
|
360
|
+
// writer's live records hold is deleted for good, as the purge does,
|
|
361
|
+
// and the engine collects it (`hist.delete-marks.release`). A record
|
|
362
|
+
// a captured remote frame wrote (the room's validation) is its
|
|
363
|
+
// writer's to take back.
|
|
364
|
+
const own = ops.idSet();
|
|
365
|
+
for (const step of dropped)
|
|
366
|
+
walkIdSet(Y, doc, step.inserts, (st, from, to) => {
|
|
367
|
+
if (st.parent === records && !st.deleted && st.id.client === doc.clientID)
|
|
368
|
+
own.add(st.id.client, from, to - from);
|
|
369
|
+
});
|
|
370
|
+
const held = ops.idSet();
|
|
371
|
+
ops.iterate(tr, own, (st) => {
|
|
372
|
+
const ids = st.content?.ids;
|
|
373
|
+
if (st.deleted || ids === undefined)
|
|
374
|
+
return;
|
|
375
|
+
for (let i = 0; i < ids.length; i += 3)
|
|
376
|
+
held.add(ids[i], ids[i + 1], ids[i + 2]);
|
|
377
|
+
ops.remove(tr, st);
|
|
378
|
+
});
|
|
379
|
+
ops.iterate(tr, held, (it) => {
|
|
380
|
+
if (it.removed !== false)
|
|
381
|
+
return;
|
|
382
|
+
ops.remove(tr, it);
|
|
383
|
+
dropSearchMarkers(it.parent);
|
|
384
|
+
});
|
|
282
385
|
}, HISTORY_TRIM);
|
|
283
386
|
}
|
|
284
387
|
/**
|
|
@@ -310,9 +413,13 @@ export class UndoManager {
|
|
|
310
413
|
this.#release(dropped);
|
|
311
414
|
}
|
|
312
415
|
}
|
|
313
|
-
/**
|
|
314
|
-
|
|
315
|
-
|
|
416
|
+
/**
|
|
417
|
+
* The document's history rules over `doc` (the one set every history of an
|
|
418
|
+
* edytor document runs): its scope (the block registry, the text hold
|
|
419
|
+
* records, the document's data), the records a replay's text holds go to,
|
|
420
|
+
* the withdraw rule (`hist.undo.withdraw`) and the attr repair below.
|
|
421
|
+
*/
|
|
422
|
+
export const historyRules = (Y, doc) => {
|
|
316
423
|
/**
|
|
317
424
|
* Undo repair, inside the replay's transaction. A replayed step
|
|
318
425
|
* deletes its own attr write and re-creates the value that write
|
|
@@ -350,9 +457,25 @@ export const docHistory = (c) => {
|
|
|
350
457
|
node.setAttr(key, value);
|
|
351
458
|
}
|
|
352
459
|
};
|
|
460
|
+
// The text hold records are in scope (an undo deletes the undoer's
|
|
461
|
+
// own, fork patch YP20). An undone creation withdraws the block instead
|
|
462
|
+
// of deleting it (`hist.undo.withdraw`).
|
|
463
|
+
const records = doc.get(TEXT_DELETES_ROOT);
|
|
464
|
+
return {
|
|
465
|
+
Y,
|
|
466
|
+
doc,
|
|
467
|
+
scope: [registryOf(doc), records, doc.get(DOC_DATA_ROOT)],
|
|
468
|
+
records,
|
|
469
|
+
withdraw: withdrawOnUndo(doc),
|
|
470
|
+
repair: repairAttrs
|
|
471
|
+
};
|
|
472
|
+
};
|
|
473
|
+
/** The history factory of one facade. */
|
|
474
|
+
export const docHistory = (c) => {
|
|
475
|
+
const { Y, doc, init, write, disposed } = c;
|
|
353
476
|
/**
|
|
354
477
|
* The document's undo manager, SCOPED TO THE BLOCK REGISTRY (with the
|
|
355
|
-
* text
|
|
478
|
+
* text hold records and the document's data), attached only after the
|
|
356
479
|
* doc carries the schema version record:
|
|
357
480
|
*
|
|
358
481
|
* - the `meta` root (version stamp, schema name) is outside the scope,
|
|
@@ -367,26 +490,13 @@ export const docHistory = (c) => {
|
|
|
367
490
|
*/
|
|
368
491
|
const createUndoManager = (options = {}) => {
|
|
369
492
|
if (disposed()) {
|
|
370
|
-
throw new
|
|
493
|
+
throw new DocumentDestroyedError('createUndoManager');
|
|
371
494
|
}
|
|
372
495
|
write(() => {
|
|
373
496
|
if (!isInitialized(doc))
|
|
374
497
|
init(doc);
|
|
375
498
|
});
|
|
376
|
-
|
|
377
|
-
// removes the undoer's own), and the history restores text only as the
|
|
378
|
-
// marks allow. An undone creation withdraws the block instead of
|
|
379
|
-
// deleting it (`hist.undo.withdraw`).
|
|
380
|
-
const marks = D.history(doc, () => um);
|
|
381
|
-
const um = new UndoManager({
|
|
382
|
-
Y,
|
|
383
|
-
doc,
|
|
384
|
-
scope: [registryOf(doc), D.scope(doc), doc.get(DOC_DATA_ROOT)],
|
|
385
|
-
marks,
|
|
386
|
-
withdraw: withdrawOnUndo(doc),
|
|
387
|
-
repair: repairAttrs
|
|
388
|
-
}, options);
|
|
389
|
-
return um;
|
|
499
|
+
return new UndoManager(historyRules(Y, doc), options);
|
|
390
500
|
};
|
|
391
501
|
return { createUndoManager };
|
|
392
502
|
};
|