edytor 0.0.11 → 0.1.0-next.16
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 +77 -197
- package/dist/block/block.svelte.d.ts +156 -69
- package/dist/block/block.svelte.js +324 -355
- package/dist/block/block.utils.d.ts +191 -24
- package/dist/block/block.utils.js +327 -460
- package/dist/block/contentRange.d.ts +4 -0
- package/dist/block/contentRange.js +20 -0
- package/dist/block/inlineBlock.svelte.d.ts +26 -19
- package/dist/block/inlineBlock.svelte.js +91 -39
- package/dist/clipboard/clipboard.d.ts +4 -0
- package/dist/clipboard/clipboard.js +4 -0
- package/dist/clipboard/createClipboardFragment.d.ts +3 -0
- package/dist/clipboard/createClipboardFragment.js +103 -0
- package/dist/clipboard/fragmentData.d.ts +6 -0
- package/dist/clipboard/fragmentData.js +74 -0
- package/dist/clipboard/htmlFlow.d.ts +22 -0
- package/dist/clipboard/htmlFlow.js +167 -0
- package/dist/clipboard/insertClipboardFragment.d.ts +18 -0
- package/dist/clipboard/insertClipboardFragment.js +48 -0
- package/dist/clipboard/serializeClipboardFragment.d.ts +7 -0
- package/dist/clipboard/serializeClipboardFragment.js +53 -0
- package/dist/clipboard/textBlocks.d.ts +23 -0
- package/dist/clipboard/textBlocks.js +103 -0
- package/dist/clipboard/types.d.ts +20 -0
- package/dist/clipboard/types.js +2 -0
- package/dist/cloudflare/DocumentRoom.d.ts +586 -0
- package/dist/cloudflare/DocumentRoom.js +1706 -0
- package/dist/cloudflare/index.d.ts +8 -0
- package/dist/cloudflare/index.js +8 -0
- package/dist/cloudflare/routeDocumentSocket.d.ts +33 -0
- package/dist/cloudflare/routeDocumentSocket.js +51 -0
- package/dist/collaboration/RemoteSelections.svelte +94 -0
- package/dist/collaboration/RemoteSelections.svelte.d.ts +7 -0
- package/dist/collaboration/awarenessSelection.d.ts +127 -0
- package/dist/collaboration/awarenessSelection.js +199 -0
- package/dist/collaboration/documentSync.d.ts +20 -0
- package/dist/collaboration/documentSync.js +13 -0
- package/dist/collaboration/index.d.ts +3 -0
- package/dist/collaboration/index.js +3 -0
- package/dist/collaboration/providers.d.ts +13 -0
- package/dist/collaboration/providers.js +21 -0
- package/dist/collaboration/remoteSelection.d.ts +21 -0
- package/dist/collaboration/remoteSelection.js +159 -0
- package/dist/components/Block.svelte +223 -15
- package/dist/components/Block.svelte.d.ts +4 -2
- package/dist/components/Content.svelte +128 -32
- package/dist/components/Content.svelte.d.ts +6 -2
- package/dist/components/Edytor.svelte +308 -110
- package/dist/components/Edytor.svelte.d.ts +64 -20
- package/dist/components/InlineBlock.svelte +38 -7
- package/dist/components/InlineBlock.svelte.d.ts +5 -2
- package/dist/components/Mark.svelte +29 -13
- package/dist/components/Mark.svelte.d.ts +4 -4
- package/dist/components/Suggestion.svelte +48 -0
- package/dist/components/Suggestion.svelte.d.ts +7 -0
- package/dist/components/SuggestionRanges.svelte +58 -0
- package/dist/components/SuggestionRanges.svelte.d.ts +7 -0
- package/dist/components/Text.svelte +107 -14
- package/dist/components/Text.svelte.d.ts +8 -1
- package/dist/constants.d.ts +0 -2
- package/dist/constants.js +0 -2
- package/dist/crdt/admission.d.ts +141 -0
- package/dist/crdt/admission.js +147 -0
- package/dist/crdt/anchors.d.ts +47 -0
- package/dist/crdt/anchors.js +42 -0
- package/dist/crdt/attribution/attribution.d.ts +169 -0
- package/dist/crdt/attribution/attribution.js +136 -0
- package/dist/crdt/attribution/block.d.ts +200 -0
- package/dist/crdt/attribution/block.js +327 -0
- package/dist/crdt/attribution/index.d.ts +9 -0
- package/dist/crdt/attribution/index.js +9 -0
- package/dist/crdt/data.d.ts +81 -0
- package/dist/crdt/data.js +383 -0
- package/dist/crdt/document.d.ts +590 -0
- package/dist/crdt/document.js +1160 -0
- package/dist/crdt/edytor-doc.d.ts +752 -0
- package/dist/crdt/edytor-doc.js +2382 -0
- package/dist/crdt/engine-api.d.ts +153 -0
- package/dist/crdt/engine.d.ts +37 -0
- package/dist/crdt/engine.js +50 -0
- package/dist/crdt/flow.d.ts +104 -0
- package/dist/crdt/flow.js +229 -0
- package/dist/crdt/index.d.ts +630 -0
- package/dist/crdt/index.js +168 -0
- package/dist/crdt/migration/legacy-schema.d.ts +61 -0
- package/dist/crdt/migration/legacy-schema.js +149 -0
- package/dist/crdt/migration/migrate.d.ts +67 -0
- package/dist/crdt/migration/migrate.js +219 -0
- package/dist/crdt/nodes.d.ts +120 -0
- package/dist/crdt/nodes.js +56 -0
- package/dist/crdt/placement/model.d.ts +383 -0
- package/dist/crdt/placement/model.js +811 -0
- package/dist/crdt/placement/rank.d.ts +57 -0
- package/dist/crdt/placement/rank.js +209 -0
- package/dist/crdt/protocols/auth.d.ts +28 -0
- package/dist/crdt/protocols/auth.js +43 -0
- package/dist/crdt/protocols/awareness.d.ts +87 -0
- package/dist/crdt/protocols/awareness.js +271 -0
- package/dist/crdt/protocols/envelope.d.ts +75 -0
- package/dist/crdt/protocols/envelope.js +89 -0
- package/dist/crdt/protocols/observable.d.ts +19 -0
- package/dist/crdt/protocols/observable.js +26 -0
- package/dist/crdt/protocols/sync.d.ts +82 -0
- package/dist/crdt/protocols/sync.js +288 -0
- package/dist/crdt/providers/container.d.ts +23 -0
- package/dist/crdt/providers/container.js +64 -0
- package/dist/crdt/providers/index.d.ts +282 -0
- package/dist/crdt/providers/index.js +118 -0
- package/dist/crdt/providers/indexeddb.d.ts +196 -0
- package/dist/crdt/providers/indexeddb.js +332 -0
- package/dist/crdt/providers/room.d.ts +193 -0
- package/dist/crdt/providers/room.js +444 -0
- package/dist/crdt/providers/websocket.d.ts +223 -0
- package/dist/crdt/providers/websocket.js +601 -0
- package/dist/crdt/rand.d.ts +22 -0
- package/dist/crdt/rand.js +22 -0
- package/dist/crdt/rangeDelete.d.ts +85 -0
- package/dist/crdt/rangeDelete.js +126 -0
- package/dist/crdt/schema.d.ts +96 -0
- package/dist/crdt/schema.js +79 -0
- package/dist/crdt/semantics.d.ts +81 -0
- package/dist/crdt/semantics.js +57 -0
- package/dist/crdt/structs.d.ts +106 -0
- package/dist/crdt/structs.js +119 -0
- package/dist/crdt/text/deletes.d.ts +23 -0
- package/dist/crdt/text/deletes.js +608 -0
- package/dist/crdt/text/model.d.ts +280 -0
- package/dist/crdt/text/model.js +554 -0
- package/dist/crdt/text/runs.d.ts +212 -0
- package/dist/crdt/text/runs.js +1142 -0
- package/dist/crdt/vendor/yjs/API-NOTES.md +59 -0
- package/dist/crdt/vendor/yjs/LICENSE +23 -0
- package/dist/crdt/vendor/yjs/UPSTREAM.md +653 -0
- package/dist/crdt/vendor/yjs/dts/global.d.ts +52 -0
- package/dist/crdt/vendor/yjs/dts/index.d.ts +25 -0
- package/dist/crdt/vendor/yjs/dts/structs/AbstractStruct.d.ts +38 -0
- package/dist/crdt/vendor/yjs/dts/structs/GC.d.ts +25 -0
- package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +748 -0
- package/dist/crdt/vendor/yjs/dts/structs/Skip.d.ts +30 -0
- package/dist/crdt/vendor/yjs/dts/utils/BlockSet.d.ts +34 -0
- package/dist/crdt/vendor/yjs/dts/utils/Doc.d.ts +198 -0
- package/dist/crdt/vendor/yjs/dts/utils/EventHandler.d.ts +17 -0
- package/dist/crdt/vendor/yjs/dts/utils/ID.d.ts +20 -0
- package/dist/crdt/vendor/yjs/dts/utils/RangeCursor.d.ts +198 -0
- package/dist/crdt/vendor/yjs/dts/utils/RelativePosition.d.ts +80 -0
- package/dist/crdt/vendor/yjs/dts/utils/StructStore.d.ts +61 -0
- package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +129 -0
- package/dist/crdt/vendor/yjs/dts/utils/UndoManager.d.ts +205 -0
- package/dist/crdt/vendor/yjs/dts/utils/UpdateDecoder.d.ts +170 -0
- package/dist/crdt/vendor/yjs/dts/utils/UpdateEncoder.d.ts +164 -0
- package/dist/crdt/vendor/yjs/dts/utils/YEvent.d.ts +93 -0
- package/dist/crdt/vendor/yjs/dts/utils/content-helper.d.ts +1 -0
- package/dist/crdt/vendor/yjs/dts/utils/encoding-helpers.d.ts +5 -0
- package/dist/crdt/vendor/yjs/dts/utils/encoding.d.ts +26 -0
- package/dist/crdt/vendor/yjs/dts/utils/ids.d.ts +407 -0
- package/dist/crdt/vendor/yjs/dts/utils/isParentOf.d.ts +1 -0
- package/dist/crdt/vendor/yjs/dts/utils/meta.d.ts +25 -0
- package/dist/crdt/vendor/yjs/dts/utils/renderer-helpers.d.ts +98 -0
- package/dist/crdt/vendor/yjs/dts/utils/schemas.d.ts +2 -0
- package/dist/crdt/vendor/yjs/dts/utils/transaction-helpers.d.ts +15 -0
- package/dist/crdt/vendor/yjs/dts/utils/updates.d.ts +70 -0
- package/dist/crdt/vendor/yjs/dts/ynode.d.ts +655 -0
- package/dist/crdt/vendor/yjs/global.d.ts +52 -0
- package/dist/crdt/vendor/yjs/src/index.js +64 -0
- package/dist/crdt/vendor/yjs/src/structs/AbstractStruct.js +64 -0
- package/dist/crdt/vendor/yjs/src/structs/GC.js +75 -0
- package/dist/crdt/vendor/yjs/src/structs/Item.js +1538 -0
- package/dist/crdt/vendor/yjs/src/structs/Skip.js +72 -0
- package/dist/crdt/vendor/yjs/src/utils/BlockSet.js +291 -0
- package/dist/crdt/vendor/yjs/src/utils/Doc.js +255 -0
- package/dist/crdt/vendor/yjs/src/utils/EventHandler.js +75 -0
- package/dist/crdt/vendor/yjs/src/utils/ID.js +59 -0
- package/dist/crdt/vendor/yjs/src/utils/RangeCursor.js +407 -0
- package/dist/crdt/vendor/yjs/src/utils/RelativePosition.js +301 -0
- package/dist/crdt/vendor/yjs/src/utils/StructStore.js +134 -0
- package/dist/crdt/vendor/yjs/src/utils/Transaction.js +458 -0
- package/dist/crdt/vendor/yjs/src/utils/UndoManager.js +554 -0
- package/dist/crdt/vendor/yjs/src/utils/UpdateDecoder.js +284 -0
- package/dist/crdt/vendor/yjs/src/utils/UpdateEncoder.js +323 -0
- package/dist/crdt/vendor/yjs/src/utils/YEvent.js +158 -0
- package/dist/crdt/vendor/yjs/src/utils/content-helper.js +0 -0
- package/dist/crdt/vendor/yjs/src/utils/encoding-helpers.js +110 -0
- package/dist/crdt/vendor/yjs/src/utils/encoding.js +662 -0
- package/dist/crdt/vendor/yjs/src/utils/ids.js +1504 -0
- package/dist/crdt/vendor/yjs/src/utils/isParentOf.js +19 -0
- package/dist/crdt/vendor/yjs/src/utils/meta.js +74 -0
- package/dist/crdt/vendor/yjs/src/utils/renderer-helpers.js +186 -0
- package/dist/crdt/vendor/yjs/src/utils/schemas.js +3 -0
- package/dist/crdt/vendor/yjs/src/utils/transaction-helpers.js +391 -0
- package/dist/crdt/vendor/yjs/src/utils/updates.js +264 -0
- package/dist/crdt/vendor/yjs/src/ynode.js +2897 -0
- package/dist/dnd/pragmatic.d.ts +22 -0
- package/dist/dnd/pragmatic.js +26 -0
- package/dist/edytor.svelte.d.ts +323 -54
- package/dist/edytor.svelte.js +771 -197
- package/dist/edytor.utils.d.ts +49 -2
- package/dist/edytor.utils.js +65 -76
- package/dist/events/beforeInputCommands.d.ts +21 -0
- package/dist/events/beforeInputCommands.js +328 -0
- package/dist/events/beforeInputDeleteCommands.d.ts +3 -0
- package/dist/events/beforeInputDeleteCommands.js +245 -0
- package/dist/events/dataTransferPayload.d.ts +6 -0
- package/dist/events/dataTransferPayload.js +9 -0
- package/dist/events/domTextOffset.d.ts +12 -0
- package/dist/events/domTextOffset.js +52 -0
- package/dist/events/events.utils.d.ts +3 -0
- package/dist/events/events.utils.js +13 -0
- package/dist/events/nativeInteractiveControl.d.ts +31 -0
- package/dist/events/nativeInteractiveControl.js +98 -0
- package/dist/events/onBeforeInput.d.ts +10 -1
- package/dist/events/onBeforeInput.js +449 -330
- package/dist/events/onCopy.d.ts +7 -0
- package/dist/events/onCopy.js +30 -0
- package/dist/events/onCut.d.ts +8 -0
- package/dist/events/onCut.js +13 -0
- package/dist/events/onDrop.d.ts +16 -0
- package/dist/events/onDrop.js +158 -0
- package/dist/events/onFocus.d.ts +4 -0
- package/dist/events/onFocus.js +166 -0
- package/dist/events/onInput.d.ts +20 -0
- package/dist/events/onInput.js +249 -0
- package/dist/events/onKeyDown.js +191 -11
- package/dist/events/onPaste.d.ts +3 -0
- package/dist/events/onPaste.js +108 -0
- package/dist/events/wordBoundary.d.ts +2 -0
- package/dist/events/wordBoundary.js +58 -0
- package/dist/index.d.ts +38 -1
- package/dist/index.js +36 -1
- package/dist/kinds.d.ts +100 -0
- package/dist/kinds.js +198 -0
- package/dist/plugins/arrowMove/arrowMove.d.ts +1 -1
- package/dist/plugins/arrowMove/arrowMove.js +30 -65
- package/dist/plugins/blockHandles/BlockHandle.svelte +152 -0
- package/dist/plugins/blockHandles/BlockHandle.svelte.d.ts +12 -0
- package/dist/plugins/blockHandles/BlockHandleController.svelte.d.ts +208 -0
- package/dist/plugins/blockHandles/BlockHandleController.svelte.js +823 -0
- package/dist/plugins/blockHandles/BlockHandles.svelte +151 -0
- package/dist/plugins/blockHandles/BlockHandles.svelte.d.ts +20 -0
- package/dist/plugins/blockHandles/autoScroll.d.ts +8 -0
- package/dist/plugins/blockHandles/autoScroll.js +25 -0
- package/dist/plugins/blockHandles/blockHandlesPlugin.d.ts +37 -0
- package/dist/plugins/blockHandles/blockHandlesPlugin.js +100 -0
- package/dist/plugins/blockHandles/dragPreview.d.ts +33 -0
- package/dist/plugins/blockHandles/dragPreview.js +228 -0
- package/dist/plugins/blockMenu/BlockMenu.svelte +301 -0
- package/dist/plugins/blockMenu/BlockMenu.svelte.d.ts +9 -0
- package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +102 -0
- package/dist/plugins/blockMenu/BlockMenuController.svelte.js +245 -0
- package/dist/plugins/blockMenu/blockMenuPlugin.d.ts +11 -0
- package/dist/plugins/blockMenu/blockMenuPlugin.js +89 -0
- package/dist/plugins/code/CodePlugin.svelte +210 -163
- package/dist/plugins/code/CodePlugin.svelte.d.ts +1 -3
- package/dist/plugins/code/code.css +92 -0
- package/dist/plugins/icons.d.ts +2 -0
- package/dist/plugins/icons.js +31 -0
- package/dist/plugins/image/ImageEmpty.svelte +69 -0
- package/dist/plugins/image/ImageEmpty.svelte.d.ts +8 -0
- package/dist/plugins/image/ImagePlugin.svelte +74 -12
- package/dist/plugins/image/ImagePlugin.svelte.d.ts +15 -0
- package/dist/plugins/image/image.d.ts +2 -0
- package/dist/plugins/image/image.js +7 -0
- package/dist/plugins/index.d.ts +14 -1
- package/dist/plugins/index.js +10 -1
- package/dist/plugins/keepInView.d.ts +4 -0
- package/dist/plugins/keepInView.js +6 -0
- package/dist/plugins/markdownShortcuts.d.ts +3 -0
- package/dist/plugins/markdownShortcuts.js +104 -0
- package/dist/plugins/mention/MentionPlugin.svelte +28 -31
- package/dist/plugins/richtext/RichTextPlugin.svelte +411 -200
- package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +8 -7
- package/dist/plugins/richtext/richTextOperations.d.ts +53 -0
- package/dist/plugins/richtext/richTextOperations.js +200 -0
- package/dist/plugins/slashMenu/SlashMenu.svelte +297 -0
- package/dist/plugins/slashMenu/SlashMenu.svelte.d.ts +11 -0
- package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +56 -0
- package/dist/plugins/slashMenu/SlashMenuController.svelte.js +275 -0
- package/dist/plugins/slashMenu/slashMenuPlugin.d.ts +25 -0
- package/dist/plugins/slashMenu/slashMenuPlugin.js +105 -0
- package/dist/plugins/suggestions/SuggestionBars.svelte +142 -0
- package/dist/plugins/suggestions/SuggestionBars.svelte.d.ts +10 -0
- package/dist/plugins/suggestions/suggestionsPlugin.d.ts +28 -0
- package/dist/plugins/suggestions/suggestionsPlugin.js +53 -0
- package/dist/plugins/toolbar/Toolbar.svelte +341 -0
- package/dist/plugins/toolbar/Toolbar.svelte.d.ts +9 -0
- package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +85 -0
- package/dist/plugins/toolbar/ToolbarController.svelte.js +150 -0
- package/dist/plugins/toolbar/toolbarPlugin.d.ts +16 -0
- package/dist/plugins/toolbar/toolbarPlugin.js +40 -0
- package/dist/plugins.d.ts +249 -40
- package/dist/plugins.js +11 -5
- package/dist/selection/domSelection.d.ts +29 -0
- package/dist/selection/domSelection.js +230 -0
- package/dist/selection/replaceSelection.d.ts +143 -0
- package/dist/selection/replaceSelection.js +316 -0
- package/dist/selection/selection.svelte.d.ts +275 -37
- package/dist/selection/selection.svelte.js +1162 -331
- package/dist/selection/selection.utils.d.ts +35 -4
- package/dist/selection/selection.utils.js +309 -100
- package/dist/selection/visibility.d.ts +88 -0
- package/dist/selection/visibility.js +140 -0
- package/dist/session/attempt.d.ts +190 -0
- package/dist/session/attempt.js +188 -0
- package/dist/session/bindings.d.ts +16 -0
- package/dist/session/bindings.js +262 -0
- package/dist/session/commands.d.ts +158 -0
- package/dist/session/commands.js +601 -0
- package/dist/session/composition.svelte.d.ts +114 -0
- package/dist/session/composition.svelte.js +489 -0
- package/dist/session/editing/text.d.ts +33 -0
- package/dist/session/editing/text.js +36 -0
- package/dist/session/handles.d.ts +63 -0
- package/dist/session/handles.js +123 -0
- package/dist/session/history.d.ts +49 -0
- package/dist/session/history.js +131 -0
- package/dist/session/keymap.d.ts +42 -0
- package/dist/session/keymap.js +144 -0
- package/dist/session/moves.d.ts +32 -0
- package/dist/session/moves.js +116 -0
- package/dist/session/navigation.d.ts +51 -0
- package/dist/session/navigation.js +312 -0
- package/dist/session/props.d.ts +28 -0
- package/dist/session/props.js +162 -0
- package/dist/session/selection.d.ts +126 -0
- package/dist/session/selection.js +227 -0
- package/dist/session/suggestions.svelte.d.ts +125 -0
- package/dist/session/suggestions.svelte.js +329 -0
- package/dist/session/virtual.d.ts +33 -0
- package/dist/session/virtual.js +182 -0
- package/dist/surface/attributes.d.ts +36 -0
- package/dist/surface/attributes.js +143 -0
- package/dist/surface/cells.d.ts +103 -0
- package/dist/surface/cells.js +215 -0
- package/dist/surface/observer.svelte.d.ts +70 -0
- package/dist/surface/observer.svelte.js +969 -0
- package/dist/surface/overlay.d.ts +33 -0
- package/dist/surface/overlay.js +91 -0
- package/dist/surface/pin.svelte.d.ts +56 -0
- package/dist/surface/pin.svelte.js +108 -0
- package/dist/surface/projector.svelte.d.ts +69 -0
- package/dist/surface/projector.svelte.js +486 -0
- package/dist/text/deltas.d.ts +14 -3
- package/dist/text/deltas.js +27 -90
- package/dist/text/text.svelte.d.ts +43 -31
- package/dist/text/text.svelte.js +88 -69
- package/dist/text/text.utils.d.ts +7 -2
- package/dist/text/text.utils.js +121 -97
- package/dist/themes/notion.css +473 -0
- package/dist/utils/diffText.d.ts +15 -0
- package/dist/utils/diffText.js +26 -0
- package/dist/utils/json.d.ts +90 -3
- package/dist/utils/json.js +369 -2
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +2 -0
- package/package.json +112 -50
- package/dist/block/content.svelte.d.ts +0 -14
- package/dist/block/content.svelte.js +0 -40
- package/dist/components/ReadonlyEditor.svelte +0 -46
- package/dist/components/ReadonlyEditor.svelte.d.ts +0 -4
- package/dist/components/readonlyElements.svelte.d.ts +0 -82
- package/dist/components/readonlyElements.svelte.js +0 -144
- package/dist/dnd.svelte.d.ts +0 -17
- package/dist/dnd.svelte.js +0 -125
- package/dist/hotkeys.d.ts +0 -27
- package/dist/hotkeys.js +0 -282
- package/dist/localProvider.d.ts +0 -82
- package/dist/localProvider.js +0 -267
- package/dist/plugins/code/prism.css +0 -141
- package/dist/utils/jsx.d.ts +0 -25
- package/dist/utils/jsx.js +0 -66
- package/dist/utils/serialize.js +0 -1
- /package/dist/{utils/serialize.d.ts → crdt/engine-api.js} +0 -0
|
@@ -1,102 +1,146 @@
|
|
|
1
1
|
import { Text } from '../text/text.svelte.js';
|
|
2
2
|
import { Edytor } from '../edytor.svelte.js';
|
|
3
|
-
import {} from '
|
|
4
|
-
import
|
|
5
|
-
import { batch, removeInlineBlock, addChildBlock, insertBlockAfter, insertBlockBefore, pushContentIntoBlock, mergeBlockBackward, mergeBlockForward, nestBlock, removeBlock, setBlock, splitBlock, addChildBlocks, unNestBlock, moveBlock, normalizeContent, groupContent, addInlineBlock, acceptSuggestedText, suggestText, deleteContentAtRange } from './block.utils.js';
|
|
6
|
-
import { id } from '../utils.js';
|
|
7
|
-
import { climb } from '../selection/selection.utils.js';
|
|
3
|
+
import { batch, removeInlineBlock, addChildBlock, insertBlockAfter, insertBlockBefore, mergeBlockBackward, mergeBlockForward, nestBlock, removeBlock, setBlock, splitBlock, prepareSplit, duplicateBlock, prepareDuplicate, prepareSet, prepareMove, prepareMoves, prepareInsertAfter, prepareInsertBefore, prepareRemove, prepareMergeBackward, prepareMergeForward, prepareUnNest, prepareNest, prepareRemoveInline, preparePatch, patchData, prepareDeleteRange, addChildBlocks, pushContentIntoBlock, unNestBlock, moveBlock, moveBlocks, normalizeContent, addInlineBlock, textAfterAtom, blockOf, acceptSuggestedText, suggestText, deleteContentAtRange, normalizeChildren } from './block.utils.js';
|
|
4
|
+
import { jsonBlockToSpec, jsonContentToItems } from '../utils/json.js';
|
|
8
5
|
import { InlineBlock } from './inlineBlock.svelte.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
yText = new Y.Text();
|
|
23
|
-
yBlock.set('content', yText);
|
|
24
|
-
}
|
|
25
|
-
return yText;
|
|
6
|
+
import { revealed } from '../selection/replaceSelection.js';
|
|
7
|
+
import { propsProxy } from '../session/props.js';
|
|
8
|
+
/**
|
|
9
|
+
* An id-only block handle (§2.4 "Handles", R4): every getter reads the
|
|
10
|
+
* document index (transaction-aware), every mutator issues a command. The
|
|
11
|
+
* view keeps one per id (`edytor.idToBlock`); `node` is the element the core
|
|
12
|
+
* renders for it (O45).
|
|
13
|
+
*/
|
|
14
|
+
/** Mark an element inside a block's markup as non-editable chrome (`block.void`, a preview's too). */
|
|
15
|
+
export const voidChrome = (node) => {
|
|
16
|
+
node.setAttribute('data-edytor-void', `true`);
|
|
17
|
+
node.style.userSelect = 'none';
|
|
18
|
+
node.setAttribute('contenteditable', 'false');
|
|
26
19
|
};
|
|
27
20
|
export class Block {
|
|
28
21
|
readonly = false;
|
|
29
22
|
edytor;
|
|
30
|
-
|
|
31
|
-
parent;
|
|
32
|
-
yChildren;
|
|
33
|
-
yContent;
|
|
34
|
-
children = $state([]);
|
|
35
|
-
content = $state([]);
|
|
36
|
-
id = $state(id('b'));
|
|
37
|
-
data = $state({});
|
|
23
|
+
id;
|
|
38
24
|
node;
|
|
39
|
-
|
|
25
|
+
constructor(edytor, id) {
|
|
26
|
+
this.edytor = edytor;
|
|
27
|
+
this.id = id;
|
|
28
|
+
}
|
|
29
|
+
get isRoot() {
|
|
30
|
+
return this.id === 'root';
|
|
31
|
+
}
|
|
32
|
+
/** The typed document node — `null` for the root. */
|
|
33
|
+
get model() {
|
|
34
|
+
return this.isRoot ? null : this.edytor.facade.block(this.id);
|
|
35
|
+
}
|
|
36
|
+
/** The display parent (the root for a top-level block); none for the root or a dead block. */
|
|
37
|
+
get parent() {
|
|
38
|
+
const at = this.isRoot ? null : this.edytor.facade.positionOf(this.id);
|
|
39
|
+
return at ? this.edytor.idToBlock.block(at.parent ?? 'root') : undefined;
|
|
40
|
+
}
|
|
41
|
+
get children() {
|
|
42
|
+
const { facade, idToBlock } = this.edytor;
|
|
43
|
+
return facade.childrenIds(this.isRoot ? null : this.id).map(idToBlock.block);
|
|
44
|
+
}
|
|
45
|
+
/** Text segments and inline atoms, alternating, starting and ending with a text. */
|
|
46
|
+
get content() {
|
|
47
|
+
const handles = this.edytor.idToBlock;
|
|
48
|
+
let ordinal = 0;
|
|
49
|
+
return handles
|
|
50
|
+
.parts(this.id)
|
|
51
|
+
.map((part) => part.kind === 'text'
|
|
52
|
+
? handles.text(this.id, ordinal++)
|
|
53
|
+
: handles.atom(this.id, part.item.id));
|
|
54
|
+
}
|
|
55
|
+
get type() {
|
|
56
|
+
return this.isRoot ? 'root' : (this.edytor.facade.blockTypeOf(this.id) ?? '');
|
|
57
|
+
}
|
|
58
|
+
/** Retype the block — the `setBlock` command (readonly, hooks, `dispatcher.last`). */
|
|
59
|
+
set type(value) {
|
|
60
|
+
this.setBlock({ value: { type: value } });
|
|
61
|
+
}
|
|
62
|
+
#data;
|
|
63
|
+
#props;
|
|
64
|
+
/**
|
|
65
|
+
* The block's `data` as a live proxy (`session/props.ts`): reads follow the
|
|
66
|
+
* document (reactive through the block's cell), writes are `patchData`
|
|
67
|
+
* commands. The root's is the document's data (`edytor.data`).
|
|
68
|
+
*/
|
|
69
|
+
get data() {
|
|
70
|
+
return (this.#props ??= propsProxy(() => (this.isRoot ? this.edytor.docData() : this.#current()), (ops) => this.patchData({ ops }), (path) => this.edytor.facade.dataItemIds(this.isRoot ? null : this.id, path)));
|
|
71
|
+
}
|
|
72
|
+
#current() {
|
|
73
|
+
const { facade, cells } = this.edytor;
|
|
74
|
+
cells?.get(this.id);
|
|
75
|
+
const version = facade.version;
|
|
76
|
+
if (this.#data?.version !== version)
|
|
77
|
+
this.#data = { version, value: facade.blockDataOf(this.id) ?? {} };
|
|
78
|
+
return this.#data.value;
|
|
79
|
+
}
|
|
80
|
+
get definition() {
|
|
81
|
+
return this.edytor.definitionOf(this.type);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Replace the block's `data` — a `patchData` command of its root (readonly,
|
|
85
|
+
* hooks, `dispatcher.last`); `block.model.setData` is the raw document write.
|
|
86
|
+
*/
|
|
87
|
+
setData = (data) => {
|
|
88
|
+
// Non-JSON values are coerced at the document boundary (`sanitizeWireJson`).
|
|
89
|
+
this.patchData({ ops: [{ path: [], value: data }] });
|
|
90
|
+
};
|
|
40
91
|
get selected() {
|
|
41
|
-
this.
|
|
42
|
-
return this.edytor.selection.selectedBlocks.has(this) || this.edytor.selection.hasSelectedAll;
|
|
92
|
+
return this.edytor.selection.selectedBlocks.has(this);
|
|
43
93
|
}
|
|
44
94
|
get focused() {
|
|
45
95
|
return this.edytor.selection.focusedBlocks.has(this) && !this.selected;
|
|
46
96
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
97
|
+
/** May this block move at all — R5 `canPlace` without a destination (drag handles). */
|
|
98
|
+
get movable() {
|
|
99
|
+
return this.edytor.facade.canPlace([this.id]);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* May text-level structural commands (convert, markdown shortcut, slash
|
|
103
|
+
* menu) apply: the block is movable — or the virtual paragraph of an
|
|
104
|
+
* emptied document, which a conversion creates with its kind
|
|
105
|
+
* (SW10-lists-3) — has no role of its own and renders its own content —
|
|
106
|
+
* a container (a list) is never converted, its items are (ZW-02).
|
|
107
|
+
*/
|
|
108
|
+
get convertible() {
|
|
109
|
+
const { facade } = this.edytor;
|
|
110
|
+
const placeable = this.movable || facade.virtual() === this.id;
|
|
111
|
+
return placeable && this.rendersContent && !facade.isVoid(this.id) && !facade.isIsland(this.id);
|
|
56
112
|
}
|
|
57
113
|
get firstEditableText() {
|
|
58
|
-
|
|
59
|
-
|
|
114
|
+
// Only a RENDERED text part is editable — a container's phantom
|
|
115
|
+
// content slot holds a Text with no `node`. Scan ALL children: the
|
|
116
|
+
// first child can be noneditable (a void divider) while a later
|
|
117
|
+
// child owns the text the caret must land in.
|
|
118
|
+
const own = this.content.find((part) => part instanceof Text && part.node != null);
|
|
119
|
+
if (own)
|
|
120
|
+
return own;
|
|
121
|
+
for (const child of this.children) {
|
|
122
|
+
const text = child.firstEditableText;
|
|
123
|
+
if (text)
|
|
124
|
+
return text;
|
|
60
125
|
}
|
|
61
|
-
return
|
|
126
|
+
return undefined;
|
|
62
127
|
}
|
|
63
128
|
get lastEditableText() {
|
|
64
|
-
|
|
65
|
-
|
|
129
|
+
const own = this.content.findLast((part) => part instanceof Text && part.node != null);
|
|
130
|
+
if (own)
|
|
131
|
+
return own;
|
|
132
|
+
for (let i = this.children.length - 1; i >= 0; i--) {
|
|
133
|
+
const text = this.children[i].lastEditableText;
|
|
134
|
+
if (text)
|
|
135
|
+
return text;
|
|
66
136
|
}
|
|
67
|
-
return
|
|
137
|
+
return undefined;
|
|
68
138
|
}
|
|
69
|
-
#index = $state(null);
|
|
70
139
|
get index() {
|
|
71
|
-
|
|
72
|
-
return 0;
|
|
73
|
-
}
|
|
74
|
-
if (this.#index === null) {
|
|
75
|
-
return this.parent.children.indexOf(this);
|
|
76
|
-
}
|
|
77
|
-
return this.#index;
|
|
78
|
-
}
|
|
79
|
-
set index(value) {
|
|
80
|
-
this.#index = value;
|
|
81
|
-
}
|
|
82
|
-
#type = $state('paragraph');
|
|
83
|
-
get type() {
|
|
84
|
-
return this.#type;
|
|
85
|
-
}
|
|
86
|
-
set type(value) {
|
|
87
|
-
this.yBlock.set('type', value);
|
|
88
|
-
this.#type = value;
|
|
89
|
-
this.definition = this.edytor.getBlockDefinition('block', value);
|
|
140
|
+
return (!this.isRoot && this.edytor.facade.positionOf(this.id)?.index) || 0;
|
|
90
141
|
}
|
|
91
|
-
#depth = $state(null);
|
|
92
142
|
get depth() {
|
|
93
|
-
|
|
94
|
-
return 0;
|
|
95
|
-
}
|
|
96
|
-
if (this.#depth === null) {
|
|
97
|
-
return this.parent.depth + 1;
|
|
98
|
-
}
|
|
99
|
-
return this.#depth;
|
|
143
|
+
return this.parent ? this.parent.depth + 1 : 0;
|
|
100
144
|
}
|
|
101
145
|
get path() {
|
|
102
146
|
const start = [this.index];
|
|
@@ -107,324 +151,249 @@ export class Block {
|
|
|
107
151
|
}
|
|
108
152
|
return start.toReversed();
|
|
109
153
|
}
|
|
110
|
-
|
|
111
|
-
|
|
154
|
+
/** The block is visible in the document (a dead handle answers false). */
|
|
155
|
+
get isInTree() {
|
|
156
|
+
return this.isRoot || this.edytor.facade.isVisibleBlock(this.id);
|
|
112
157
|
}
|
|
113
|
-
|
|
158
|
+
/**
|
|
159
|
+
* @deprecated `edytor.suggestions` with `{ end: block.id }`. The content of
|
|
160
|
+
* this block's latest `end` suggestion, as parts (a text's runs, or an
|
|
161
|
+
* atom); setting it replaces this block's `end` suggestions, `null` drops them.
|
|
162
|
+
*/
|
|
114
163
|
get suggestions() {
|
|
115
|
-
|
|
164
|
+
const content = this.edytor.suggestions?.at(this.id).end.at(-1)?.content[0]?.content;
|
|
165
|
+
if (!content?.length)
|
|
116
166
|
return null;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if ('type' in
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
else {
|
|
127
|
-
return createReadonlyText({
|
|
128
|
-
value: suggestion,
|
|
129
|
-
parent: this,
|
|
130
|
-
edytor: this.edytor
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
});
|
|
167
|
+
const parts = [];
|
|
168
|
+
for (const part of content)
|
|
169
|
+
if ('type' in part)
|
|
170
|
+
parts.push(part);
|
|
171
|
+
else if (Array.isArray(parts.at(-1)))
|
|
172
|
+
parts.at(-1).push(part);
|
|
173
|
+
else
|
|
174
|
+
parts.push([part]);
|
|
175
|
+
return parts;
|
|
134
176
|
}
|
|
135
177
|
set suggestions(value) {
|
|
136
|
-
|
|
178
|
+
const { suggestions } = this.edytor;
|
|
179
|
+
for (const suggestion of suggestions.at(this.id).end)
|
|
180
|
+
suggestion.discard();
|
|
181
|
+
if (value)
|
|
182
|
+
suggestions.add({ end: this.id }, [{ type: this.type, content: value.flat() }]);
|
|
137
183
|
}
|
|
138
184
|
get nextBlock() {
|
|
139
|
-
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
return this.parent.children[this.index + 1];
|
|
185
|
+
return this.parent ? this.parent.children[this.index + 1] : null;
|
|
143
186
|
}
|
|
144
187
|
get previousBlock() {
|
|
145
|
-
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
return this.parent.children[this.index - 1];
|
|
188
|
+
return this.parent ? this.parent.children[this.index - 1] : null;
|
|
149
189
|
}
|
|
150
190
|
get closestPreviousBlock() {
|
|
151
|
-
|
|
152
|
-
if (this.index === 0) {
|
|
153
|
-
return this.parent instanceof Block ? this.parent : null;
|
|
154
|
-
}
|
|
155
|
-
else if (previousBlock) {
|
|
156
|
-
if (previousBlock?.children.length > 0) {
|
|
157
|
-
let closestPreviousBlock = previousBlock.children.at(-1) || null;
|
|
158
|
-
while (closestPreviousBlock && closestPreviousBlock?.children.length > 0) {
|
|
159
|
-
closestPreviousBlock = closestPreviousBlock.children.at(-1) || null;
|
|
160
|
-
}
|
|
161
|
-
return closestPreviousBlock || null;
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
return this.previousBlock;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return null;
|
|
191
|
+
return this.edytor.blockBefore(this);
|
|
168
192
|
}
|
|
169
193
|
get closestNextBlock() {
|
|
170
|
-
|
|
171
|
-
return this.children.at(0) || null;
|
|
172
|
-
}
|
|
173
|
-
if (this.nextBlock || this.definition.island || this.definition.void) {
|
|
174
|
-
return this.nextBlock;
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
if (this.parent instanceof Block) {
|
|
178
|
-
let parent = this.parent;
|
|
179
|
-
let nextBlock = parent.nextBlock;
|
|
180
|
-
while (!nextBlock && parent instanceof Block) {
|
|
181
|
-
if (parent.parent instanceof Block) {
|
|
182
|
-
parent = parent.parent;
|
|
183
|
-
nextBlock = parent.nextBlock;
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
return nextBlock;
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
get deepestChild() {
|
|
197
|
-
if (this.children.length) {
|
|
198
|
-
return this.children.at(-1).deepestChild;
|
|
199
|
-
}
|
|
200
|
-
return this;
|
|
194
|
+
return this.edytor.blockAfter(this);
|
|
201
195
|
}
|
|
202
196
|
get hasChildren() {
|
|
203
197
|
return this.children.length > 0;
|
|
204
198
|
}
|
|
199
|
+
/** It shows content: text or an inline atom (a block holding only a mention is not empty). */
|
|
205
200
|
get hasContent() {
|
|
206
|
-
return
|
|
201
|
+
return this.content.some((part) => !(part instanceof Text) || !part.isEmpty);
|
|
207
202
|
}
|
|
203
|
+
/** It holds nothing: no content and no children (the emptiness Turn into reads, `holdsNothing`). */
|
|
208
204
|
get isEmpty() {
|
|
209
205
|
return !this.hasContent && !this.hasChildren;
|
|
210
206
|
}
|
|
207
|
+
get isNested() {
|
|
208
|
+
return (this.parent && this.parent.type !== 'root') || false;
|
|
209
|
+
}
|
|
210
|
+
/** This block's JSON — the document's one serializer (`facade.blockJSON`, L14). */
|
|
211
211
|
get value() {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
212
|
+
if (!this.isRoot)
|
|
213
|
+
return this.edytor.facade.blockJSON(this.id);
|
|
214
|
+
const { data = {}, children } = this.edytor.facade.toJSON();
|
|
215
|
+
return { type: 'root', id: 'root', data, ...(children.length > 0 && { children }) };
|
|
216
|
+
}
|
|
217
|
+
isChildOf(block) {
|
|
218
|
+
for (let parent = this.parent; parent; parent = parent.parent)
|
|
219
|
+
if (parent === block)
|
|
220
|
+
return true;
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
/** Whether this kind renders its own content slot — the adopted capability (R5, O22). */
|
|
224
|
+
get rendersContent() {
|
|
225
|
+
return this.edytor.document.rendersContent(this.type);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* A container: it shows only its children (a list), neither void nor an
|
|
229
|
+
* island — the document's container rule (YW-02). Its items hold what it
|
|
230
|
+
* shows; it is never converted (`convertible`).
|
|
231
|
+
*/
|
|
232
|
+
get isContainer() {
|
|
233
|
+
const { facade } = this.edytor;
|
|
234
|
+
return !this.rendersContent && !facade.isVoid(this.id) && !facade.isIsland(this.id);
|
|
230
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* An item of a list: its parent is a container whose items are a kind of
|
|
238
|
+
* their own (a `list-item` in an `unordered-list`), not the document's
|
|
239
|
+
* default — a column of paragraphs is no list. Turned into another kind,
|
|
240
|
+
* an item leaves its list; <kbd>Enter</kbd> in an empty one ends it.
|
|
241
|
+
*/
|
|
242
|
+
get isListItem() {
|
|
243
|
+
const { parent, edytor } = this;
|
|
244
|
+
if (!parent?.isContainer)
|
|
245
|
+
return false;
|
|
246
|
+
const item = edytor.defaultChild(parent);
|
|
247
|
+
return this.type === item && item !== edytor.document.defaultChild(null);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* The list this block shows in: its container when it is an item
|
|
251
|
+
* (`isListItem`), or — an item outdented out of a nested list into the
|
|
252
|
+
* item holding it (SW8-roles-4) — the list of the items of its kind it
|
|
253
|
+
* sits under. <kbd>Enter</kbd> in an empty one outdents it; the menus
|
|
254
|
+
* name it by the list's `itemKind`.
|
|
255
|
+
*/
|
|
256
|
+
get list() {
|
|
257
|
+
if (this.isListItem)
|
|
258
|
+
return this.parent ?? undefined;
|
|
259
|
+
return this.parent?.type === this.type ? this.parent.list : undefined;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* The first text of this block's own content — none for a kind that
|
|
263
|
+
* does not render its content (a list container, a divider): its slot
|
|
264
|
+
* is never displayed, so no caret or endpoint may land there. A block
|
|
265
|
+
* without a content slot (the root) answers with its first child's.
|
|
266
|
+
*/
|
|
231
267
|
get firstText() {
|
|
232
|
-
if (this.content.length)
|
|
233
|
-
return this.
|
|
234
|
-
|
|
235
|
-
return this.children.at(0)?.firstText;
|
|
268
|
+
if (!this.content.length)
|
|
269
|
+
return this.children.at(0)?.firstText;
|
|
270
|
+
return this.rendersContent ? this.content.find((p) => p instanceof Text) : undefined;
|
|
236
271
|
}
|
|
272
|
+
/** The last text of this block's own content (see {@link firstText}). */
|
|
237
273
|
get lastText() {
|
|
238
|
-
if (this.content.length)
|
|
239
|
-
return this.
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const groupedContent = groupContent(block.content);
|
|
284
|
-
if (!groupedContent.length) {
|
|
285
|
-
groupedContent.push([{ text: '' }]);
|
|
274
|
+
if (!this.content.length)
|
|
275
|
+
return this.children.at(-1)?.lastText;
|
|
276
|
+
return this.rendersContent ? this.content.findLast((p) => p instanceof Text) : undefined;
|
|
277
|
+
}
|
|
278
|
+
addChildBlock = batch('addChildBlock', addChildBlock);
|
|
279
|
+
addChildBlocks = batch('addChildBlocks', addChildBlocks);
|
|
280
|
+
insertBlockAfter = batch('insertBlockAfter', insertBlockAfter, prepareInsertAfter, blockOf);
|
|
281
|
+
insertBlockBefore = batch('insertBlockBefore', insertBlockBefore, prepareInsertBefore, blockOf);
|
|
282
|
+
splitBlock = batch('splitBlock', splitBlock, prepareSplit, blockOf);
|
|
283
|
+
duplicateBlock = batch('duplicateBlock', duplicateBlock, prepareDuplicate, blockOf);
|
|
284
|
+
removeBlock = batch('removeBlock', removeBlock, prepareRemove);
|
|
285
|
+
unNestBlock = revealed(batch('unNestBlock', unNestBlock, prepareUnNest));
|
|
286
|
+
mergeBlockBackward = batch('mergeBlockBackward', mergeBlockBackward, prepareMergeBackward, blockOf);
|
|
287
|
+
mergeBlockForward = batch('mergeBlockForward', mergeBlockForward, prepareMergeForward, blockOf);
|
|
288
|
+
nestBlock = revealed(batch('nestBlock', nestBlock, prepareNest));
|
|
289
|
+
setBlock = batch('setBlock', setBlock, prepareSet);
|
|
290
|
+
moveBlock = revealed(batch('moveBlock', moveBlock, prepareMove));
|
|
291
|
+
moveBlocks = revealed(batch('moveBlocks', moveBlocks, prepareMoves));
|
|
292
|
+
pushContentIntoBlock = batch('pushContentIntoBlock', pushContentIntoBlock);
|
|
293
|
+
removeInlineBlock = batch('removeInlineBlock', removeInlineBlock, prepareRemoveInline);
|
|
294
|
+
patchData = batch('patchData', patchData, preparePatch);
|
|
295
|
+
addInlineBlock = batch('addInlineBlock', addInlineBlock, undefined, textAfterAtom);
|
|
296
|
+
normalizeContent = batch('normalizeContent', normalizeContent);
|
|
297
|
+
normalizeChildren = batch('normalizeChildren', normalizeChildren);
|
|
298
|
+
/** @deprecated `edytor.suggestions.add({ end: block.id }, …)`. */
|
|
299
|
+
suggestText = (payload) => suggestText.call(this, payload);
|
|
300
|
+
/** @deprecated `suggestion.accept()`. */
|
|
301
|
+
acceptSuggestedText = () => acceptSuggestedText.call(this);
|
|
302
|
+
deleteContentAtRange = batch('deleteContentAtRange', deleteContentAtRange, prepareDeleteRange);
|
|
303
|
+
/** Mark an element inside the block's markup as non-editable chrome (a header, a caption bar). */
|
|
304
|
+
void = voidChrome;
|
|
305
|
+
/**
|
|
306
|
+
* The text segment that displays block offset `offset`, and the offset in
|
|
307
|
+
* it — the one offset → segment mapper over the committed parts (a
|
|
308
|
+
* boundary before an atom reads the text before it; past the end, the
|
|
309
|
+
* last text's end).
|
|
310
|
+
*/
|
|
311
|
+
textAtOffset = (offset) => {
|
|
312
|
+
let at = 0;
|
|
313
|
+
let hit = null;
|
|
314
|
+
for (const part of this.content) {
|
|
315
|
+
if (!(part instanceof Text)) {
|
|
316
|
+
if (offset <= at)
|
|
317
|
+
return hit;
|
|
318
|
+
at += 1;
|
|
286
319
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (isInlineBlock) {
|
|
290
|
-
const block = new InlineBlock({ parent: this, block: part });
|
|
291
|
-
block.index = index;
|
|
292
|
-
return block;
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
const text = new Text({ parent: this, content: part });
|
|
296
|
-
text.index = index;
|
|
297
|
-
return text;
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
this.yChildren = Y.Array.from(this.children.map((child) => child.yBlock));
|
|
301
|
-
this.yContent = Y.Array.from(this.content.map((part) => (part instanceof Text ? part.yText : part.yBlock)));
|
|
302
|
-
// If the block is a root block we need to set the yBlock to the yRootBlock
|
|
303
|
-
if (block.type === 'root') {
|
|
304
|
-
this.yBlock = yBlock;
|
|
305
|
-
this.yBlock.set('id', this.id);
|
|
306
|
-
this.yBlock.set('type', block.type);
|
|
307
|
-
this.yBlock.set('data', this.data);
|
|
308
|
-
this.yBlock.set('children', this.yChildren);
|
|
309
|
-
this.yBlock.set('content', this.yContent);
|
|
320
|
+
else if (offset <= at + part.length) {
|
|
321
|
+
return { text: part, offset: Math.max(0, offset - at) };
|
|
310
322
|
}
|
|
311
323
|
else {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
id: this.id,
|
|
315
|
-
data: this.data,
|
|
316
|
-
children: this.yChildren,
|
|
317
|
-
content: this.yContent
|
|
318
|
-
}));
|
|
324
|
+
hit = { text: part, offset: part.length };
|
|
325
|
+
at += part.length;
|
|
319
326
|
}
|
|
320
327
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
328
|
+
return hit;
|
|
329
|
+
};
|
|
330
|
+
// ── JSON insertion (K5: specs are data; `new Block({block})` is gone) ──
|
|
331
|
+
/**
|
|
332
|
+
* Insert children at `index`: a JSON spec is created (its id kept, minted
|
|
333
|
+
* when missing); a block handle moves there with its identity.
|
|
334
|
+
*/
|
|
335
|
+
insertChildren = (index, blocks) => {
|
|
336
|
+
const { facade } = this.edytor;
|
|
337
|
+
const parent = this.isRoot ? null : this.id;
|
|
338
|
+
blocks.forEach((block, k) => {
|
|
339
|
+
if (block instanceof Block)
|
|
340
|
+
block.model?.moveTo({ parent: this.model, index: index + k });
|
|
341
|
+
else
|
|
342
|
+
facade.insertBlock({ parent, index: index + k }, jsonBlockToSpec(block));
|
|
343
|
+
});
|
|
344
|
+
};
|
|
345
|
+
/** Delete `length` visible children from `index`, each with its subtree (a document delete). */
|
|
346
|
+
deleteChildren = (index, length = 1) => {
|
|
347
|
+
const ids = this.edytor.facade.childrenIds(this.isRoot ? null : this.id);
|
|
348
|
+
for (const id of ids.slice(index, index + length).reverse())
|
|
349
|
+
this.edytor.facade.block(id).delete({ keepChildren: false });
|
|
350
|
+
};
|
|
351
|
+
/**
|
|
352
|
+
* Insert content before part `index` (a text segment or an inline atom):
|
|
353
|
+
* each entry is a text's runs or an atom, as JSON.
|
|
354
|
+
*/
|
|
355
|
+
insertParts = (index, parts) => {
|
|
356
|
+
const model = this.model;
|
|
357
|
+
if (!model)
|
|
358
|
+
return;
|
|
359
|
+
const all = this.edytor.idToBlock.parts(this.id);
|
|
360
|
+
let at = all[index]?.start ?? model.length;
|
|
361
|
+
for (const item of jsonContentToItems(parts.flat())) {
|
|
362
|
+
if (item.kind === 'inline')
|
|
363
|
+
model.insertInline(at++, item);
|
|
364
|
+
else if (item.text) {
|
|
365
|
+
model.insertText(at, item.text, item.marks);
|
|
366
|
+
at += item.text.length;
|
|
367
|
+
}
|
|
351
368
|
}
|
|
352
|
-
}
|
|
369
|
+
};
|
|
370
|
+
/** The declared view state (`open` on a `details`) the block's last element held. */
|
|
371
|
+
#viewState = [];
|
|
372
|
+
/**
|
|
373
|
+
* Register the element the core rendered for this block (O45) and run the
|
|
374
|
+
* attach hooks. A re-rendered block (moved, re-parented) keeps its declared
|
|
375
|
+
* view state (R11): an open toggle stays open.
|
|
376
|
+
*/
|
|
353
377
|
attach = (node) => {
|
|
378
|
+
const names = this.definition.viewState ?? [];
|
|
379
|
+
const read = (from) => names.flatMap((name) => (from.hasAttribute(name) ? [[name, from.getAttribute(name)]] : []));
|
|
380
|
+
for (const [name, value] of this.node ? read(this.node) : this.#viewState)
|
|
381
|
+
if (names.includes(name))
|
|
382
|
+
node.setAttribute(name, value);
|
|
354
383
|
this.node = node;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
node.setAttribute('data-edytor-type', `${this.#type}`);
|
|
358
|
-
const pluginDestroy = this.edytor.plugins.reduce((acc, plugin) => {
|
|
384
|
+
const release = this.edytor.surface.register(node, 'block', this.id);
|
|
385
|
+
const onDestroy = this.edytor.plugins.flatMap((plugin) => {
|
|
359
386
|
const action = plugin.onBlockAttached?.({ node, block: this });
|
|
360
|
-
action
|
|
361
|
-
|
|
362
|
-
}, []);
|
|
363
|
-
if (this.definition.void) {
|
|
364
|
-
this.void(node);
|
|
365
|
-
}
|
|
387
|
+
return typeof action === 'function' ? [action] : [];
|
|
388
|
+
});
|
|
366
389
|
return {
|
|
367
390
|
destroy: () => {
|
|
368
|
-
this
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
391
|
+
this.#viewState = read(node);
|
|
392
|
+
if (this.node === node)
|
|
393
|
+
this.node = undefined;
|
|
394
|
+
release();
|
|
395
|
+
onDestroy.forEach((destroy) => destroy());
|
|
372
396
|
}
|
|
373
397
|
};
|
|
374
398
|
};
|
|
375
399
|
}
|
|
376
|
-
export function observeChildren(event) {
|
|
377
|
-
let start = 0;
|
|
378
|
-
event.delta.forEach(({ retain, delete: _delete, insert }) => {
|
|
379
|
-
if (retain) {
|
|
380
|
-
start += retain;
|
|
381
|
-
}
|
|
382
|
-
if (_delete) {
|
|
383
|
-
this.children.splice(start, _delete);
|
|
384
|
-
}
|
|
385
|
-
if (Array.isArray(insert)) {
|
|
386
|
-
for (let i = 0; i < insert.length; i++) {
|
|
387
|
-
const yBlock = insert[i];
|
|
388
|
-
const block = this.edytor.idToBlock.get(yBlock.get('id')) ||
|
|
389
|
-
new Block({
|
|
390
|
-
parent: this,
|
|
391
|
-
edytor: this.edytor,
|
|
392
|
-
yBlock
|
|
393
|
-
});
|
|
394
|
-
this.children.splice(start, 0, block);
|
|
395
|
-
start += 1;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
this.children.forEach((child, index) => {
|
|
400
|
-
child.index = index;
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
export function observeContent(event) {
|
|
404
|
-
let start = 0;
|
|
405
|
-
event.delta.forEach(({ retain, delete: _delete, insert }) => {
|
|
406
|
-
if (retain) {
|
|
407
|
-
start += retain;
|
|
408
|
-
}
|
|
409
|
-
if (_delete) {
|
|
410
|
-
this.content.splice(start, _delete);
|
|
411
|
-
}
|
|
412
|
-
if (Array.isArray(insert)) {
|
|
413
|
-
for (let i = 0; i < insert.length; i++) {
|
|
414
|
-
const yElement = insert[i];
|
|
415
|
-
if (yElement instanceof Y.Text) {
|
|
416
|
-
const text = new Text({ parent: this, yText: yElement });
|
|
417
|
-
this.content.splice(start, 0, text);
|
|
418
|
-
}
|
|
419
|
-
else {
|
|
420
|
-
const inlineBlock = new InlineBlock({ parent: this, yBlock: yElement });
|
|
421
|
-
this.content.splice(start, 0, inlineBlock);
|
|
422
|
-
}
|
|
423
|
-
start += 1;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
});
|
|
427
|
-
this.content.forEach((part, index) => {
|
|
428
|
-
part.index = index;
|
|
429
|
-
});
|
|
430
|
-
}
|