edytor 1.0.0 → 3.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 +26 -69
- package/dist/block/block.svelte.d.ts +6 -4
- package/dist/block/block.svelte.js +12 -8
- package/dist/block/inlineBlock.svelte.d.ts +6 -2
- package/dist/block/inlineBlock.svelte.js +7 -2
- 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/room/admission.js +3 -3
- package/dist/cloudflare/room/context.d.ts +7 -1
- package/dist/cloudflare/routeDocumentSocket.d.ts +17 -0
- package/dist/cloudflare/routeDocumentSocket.js +53 -0
- package/dist/collaboration/awarenessSelection.d.ts +22 -1
- package/dist/collaboration/awarenessSelection.js +42 -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/Block.svelte +3 -1
- package/dist/components/Edytor.svelte +38 -20
- package/dist/components/Edytor.svelte.d.ts +9 -4
- package/dist/components/InlineBlock.svelte +1 -1
- package/dist/crdt/admission.d.ts +5 -10
- package/dist/crdt/admission.js +5 -11
- package/dist/crdt/data.d.ts +10 -0
- package/dist/crdt/data.js +20 -2
- package/dist/crdt/doc/funnel.d.ts +7 -6
- package/dist/crdt/doc/funnel.js +10 -9
- package/dist/crdt/doc/gate.d.ts +0 -17
- package/dist/crdt/doc/gate.js +2 -41
- package/dist/crdt/doc/history.js +2 -2
- package/dist/crdt/doc/reads.d.ts +7 -0
- package/dist/crdt/doc/reads.js +11 -1
- package/dist/crdt/document.d.ts +13 -14
- package/dist/crdt/document.js +17 -19
- package/dist/crdt/edytor-doc.d.ts +22 -4
- package/dist/crdt/edytor-doc.js +5 -8
- package/dist/crdt/index.d.ts +9 -3
- package/dist/crdt/index.js +2 -2
- package/dist/crdt/operations.d.ts +1 -1
- package/dist/crdt/operations.js +1 -0
- package/dist/crdt/props.d.ts +32 -0
- package/dist/crdt/props.js +172 -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 +10 -9
- package/dist/crdt/providers/room.js +13 -10
- package/dist/crdt/providers/websocket.d.ts +1 -1
- package/dist/crdt/providers/websocket.js +28 -29
- package/dist/crdt/semantics.js +3 -1
- package/dist/dnd/autoScroll.d.ts +15 -7
- package/dist/dnd/autoScroll.js +10 -15
- package/dist/{plugins/blockHandles → dnd}/dropIndicator.d.ts +2 -2
- package/dist/{plugins/blockHandles → dnd}/dropIndicator.js +2 -5
- package/dist/dnd/external.d.ts +6 -0
- package/dist/dnd/external.js +17 -0
- package/dist/{plugins/blockHandles → dnd}/geometry.d.ts +4 -2
- package/dist/{plugins/blockHandles → dnd}/geometry.js +3 -4
- package/dist/dnd/placement.d.ts +200 -0
- package/dist/dnd/placement.js +426 -0
- 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 +19 -9
- package/dist/edytor.svelte.js +28 -33
- package/dist/events/beforeInputCommands.d.ts +2 -2
- package/dist/events/beforeInputCommands.js +8 -4
- package/dist/events/onBeforeInput.js +1 -1
- package/dist/events/onDrop.js +25 -10
- package/dist/events/onInput.d.ts +0 -12
- package/dist/events/onInput.js +1 -67
- package/dist/events/onPaste.d.ts +2 -1
- package/dist/events/onPaste.js +8 -3
- 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 +4 -4
- package/dist/index.js +2 -2
- package/dist/kinds.js +1 -1
- package/dist/labels.d.ts +2 -0
- package/dist/labels.js +2 -1
- package/dist/plugins/anchored.svelte.d.ts +21 -25
- package/dist/plugins/anchored.svelte.js +23 -39
- package/dist/plugins/arrowMove/arrowMove.d.ts +1 -1
- package/dist/plugins/arrowMove/arrowMove.js +1 -1
- package/dist/plugins/blockHandles/BlockHandleController.svelte.d.ts +2 -122
- package/dist/plugins/blockHandles/BlockHandleController.svelte.js +48 -414
- package/dist/plugins/blockHandles/BlockHandles.svelte +14 -32
- package/dist/plugins/blockHandles/blockHandlesPlugin.js +2 -1
- 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/CodeHeader.svelte +5 -3
- package/dist/plugins/code/CodePlugin.svelte +15 -12
- 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/code/languages.d.ts +0 -3
- package/dist/plugins/code/languages.js +0 -2
- package/dist/plugins/columns/ColumnResize.svelte +3 -2
- package/dist/plugins/columns/ColumnsPlugin.svelte +8 -21
- package/dist/plugins/columns/gaps.d.ts +7 -5
- package/dist/plugins/columns/gaps.js +11 -6
- package/dist/plugins/columns/resize.svelte.d.ts +5 -6
- package/dist/plugins/columns/resize.svelte.js +12 -14
- 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 +13 -30
- package/dist/plugins/equation/EquationPlugin.svelte.d.ts +1 -0
- package/dist/plugins/equation/equation.css +7 -0
- 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 +43 -0
- package/dist/plugins/fileDrop.js +122 -0
- 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 +56 -84
- package/dist/plugins/image/ImagePlugin.svelte.d.ts +13 -1
- package/dist/plugins/image/controls.svelte.js +16 -2
- package/dist/plugins/image/image.css +17 -0
- 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 +4 -5
- package/dist/plugins/index.js +0 -1
- package/dist/plugins/list.svelte.d.ts +9 -0
- package/dist/plugins/list.svelte.js +18 -0
- package/dist/plugins/markdownShortcuts.js +5 -5
- package/dist/plugins/marquee/marqueePlugin.js +0 -4
- package/dist/plugins/media/AudioPlugin.svelte +13 -1
- package/dist/plugins/media/AudioPlugin.svelte.d.ts +11 -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 +12 -20
- package/dist/plugins/media/FilePlugin.svelte.d.ts +9 -0
- package/dist/plugins/media/MediaEmpty.svelte +2 -55
- package/dist/plugins/media/MediaEmpty.svelte.d.ts +18 -14
- package/dist/plugins/media/SourceBlock.svelte +178 -52
- package/dist/plugins/media/SourceBlock.svelte.d.ts +13 -6
- package/dist/plugins/media/UploadPreview.svelte +32 -0
- package/dist/plugins/media/UploadPreview.svelte.d.ts +11 -0
- package/dist/plugins/media/VideoPlugin.svelte +13 -1
- package/dist/plugins/media/VideoPlugin.svelte.d.ts +11 -1
- package/dist/plugins/media/empty.svelte.d.ts +13 -4
- package/dist/plugins/media/empty.svelte.js +32 -26
- package/dist/plugins/media/media.d.ts +9 -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/upload.css +23 -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 +50 -38
- package/dist/plugins/mention/MentionPlugin.svelte.d.ts +11 -2
- package/dist/plugins/mention/mention.css +6 -0
- package/dist/plugins/page/PagePlugin.svelte +2 -9
- package/dist/plugins/page/page.js +1 -1
- package/dist/plugins/pageLink/PageLinkPlugin.svelte +126 -28
- package/dist/plugins/pageLink/PageLinkPlugin.svelte.d.ts +13 -1
- package/dist/plugins/pageLink/pageLink.css +6 -0
- package/dist/plugins/richtext/RichTextPlugin.svelte +99 -204
- package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +1 -0
- 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/richtext/richtext.css +6 -0
- 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 +33 -56
- 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 +48 -32
- package/dist/plugins/uploads.svelte.js +119 -43
- package/dist/plugins.d.ts +66 -14
- 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/attempt.d.ts +16 -6
- package/dist/session/attempt.js +1 -0
- package/dist/session/bindings.js +35 -32
- package/dist/session/commands.d.ts +7 -11
- package/dist/session/commands.js +15 -19
- package/dist/session/history.js +1 -0
- package/dist/session/inputRules.d.ts +6 -3
- package/dist/session/inputRules.js +10 -6
- package/dist/session/moves.d.ts +33 -0
- package/dist/session/moves.js +71 -1
- package/dist/session/navigation.d.ts +7 -0
- package/dist/session/navigation.js +20 -11
- package/dist/session/props.d.ts +28 -0
- package/dist/session/props.js +65 -0
- package/dist/session/suggestions.svelte.d.ts +0 -11
- package/dist/session/suggestions.svelte.js +15 -3
- package/dist/session/uploads.d.ts +29 -0
- package/dist/session/uploads.js +10 -0
- package/dist/surface/lines.js +1 -3
- package/dist/surface/observer.svelte.d.ts +17 -1
- package/dist/surface/observer.svelte.js +72 -17
- package/dist/surface/overlay.d.ts +0 -14
- package/dist/surface/overlay.js +0 -25
- package/dist/surface/projector.svelte.js +1 -1
- package/dist/text/text.svelte.js +3 -13
- package/dist/themes/notion.css +9 -0
- 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 +18 -1
- 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/{plugins/columns → dnd}/stacking.d.ts +0 -0
- /package/dist/{plugins/columns → dnd}/stacking.js +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Properties: the deep proxy behind `block.data`, `atom.data`,
|
|
3
|
+
* `edytor.data` and `document.data` (SyncedStore's feel, one small module).
|
|
4
|
+
* It is sugar over the one write path: every mutation is a data patch
|
|
5
|
+
* handed to `write`, which is the `patchData` operation (dispatched on a
|
|
6
|
+
* view, raw on a bare document).
|
|
7
|
+
*
|
|
8
|
+
* A read goes to `read()` every time (the live source), so a reactive
|
|
9
|
+
* reader of `block.data.title` re-runs when anyone changes it, and a key a
|
|
10
|
+
* peer deletes is gone. Plain objects read as nested proxies, arrays as
|
|
11
|
+
* array proxies, everything else as the raw value; a proxy is cached per
|
|
12
|
+
* path, so its identity is stable. An object or array held in an array
|
|
13
|
+
* item is that item's (its path names the item by id, from `ids`): it
|
|
14
|
+
* stays on its item wherever peers move it, so `{#each list as item (item)}`
|
|
15
|
+
* keeps a row on its item; once the item is removed, its writes are
|
|
16
|
+
* refused. A key is a path segment as `keySegment` writes it.
|
|
17
|
+
*
|
|
18
|
+
* Writes, each the patch of only what it changes (per-leaf storage, so
|
|
19
|
+
* concurrent edits of other keys and items merge): `obj.key = v`,
|
|
20
|
+
* `arr[i] = v` and `delete obj.key` patch that path; `push`, `pop`,
|
|
21
|
+
* `shift`, `unshift`, `splice` and `length` are one `splice` (the items
|
|
22
|
+
* kept keep their ids), `sort` and `reverse` one `order` (the items move),
|
|
23
|
+
* `fill` and `copyWithin` writes of the items they change. Assigning a
|
|
24
|
+
* value equal to the one there writes nothing. `JSON.stringify` and
|
|
25
|
+
* `$state.snapshot` read plain JSON through it.
|
|
26
|
+
*/
|
|
27
|
+
import { isObject, keySegment, segmentKey } from './data.js';
|
|
28
|
+
import { jsonEquals } from '../utils/json.js';
|
|
29
|
+
/** A plain JSON copy (proxies included), or `undefined`. */
|
|
30
|
+
const plain = (v) => (v === undefined ? v : JSON.parse(JSON.stringify(v)));
|
|
31
|
+
/** The items of `now` that differ from `was`, as writes of those items. */
|
|
32
|
+
const changed = (_, __, was, now) => now.flatMap((value, i) => JSON.stringify(value) === JSON.stringify(was[i]) ? [] : [{ at: `${i}`, value }]);
|
|
33
|
+
/**
|
|
34
|
+
* Each array mutator as the patches of the array (or of its items `at`),
|
|
35
|
+
* from its length `n`, the call's `args`, the array `was` and the result `out`.
|
|
36
|
+
*/
|
|
37
|
+
const MUTATORS = {
|
|
38
|
+
push: (n, args) => ({ splice: [n, 0, ...args] }),
|
|
39
|
+
pop: (n) => ({ splice: [Math.max(n - 1, 0), n && 1] }),
|
|
40
|
+
shift: () => ({ splice: [0, 1] }),
|
|
41
|
+
unshift: (_, args) => ({ splice: [0, 0, ...args] }),
|
|
42
|
+
// The start and count `splice` resolved (negative, fractional, past the end).
|
|
43
|
+
splice: (n, [start, , ...items], _, out) => {
|
|
44
|
+
const s = Math.trunc(Number(start)) || 0;
|
|
45
|
+
return { splice: [s < 0 ? Math.max(n + s, 0) : Math.min(s, n), out.length, ...items] };
|
|
46
|
+
},
|
|
47
|
+
sort: (n, [compare], was) => ({ order: sorted(n, was, compare) }),
|
|
48
|
+
reverse: (n) => ({ order: Array.from({ length: n }, (_, i) => n - 1 - i) }),
|
|
49
|
+
fill: changed,
|
|
50
|
+
copyWithin: changed
|
|
51
|
+
};
|
|
52
|
+
/** The indexes `Array.prototype.sort` puts `values` in (stable, `undefined` compare: by string). */
|
|
53
|
+
const sorted = (n, values, compare) => {
|
|
54
|
+
const by = typeof compare === 'function'
|
|
55
|
+
? compare
|
|
56
|
+
: (a, b) => (`${a}` < `${b}` ? -1 : `${a}` > `${b}` ? 1 : 0);
|
|
57
|
+
return Array.from({ length: n }, (_, i) => i).sort((a, b) => by(values[a], values[b]));
|
|
58
|
+
};
|
|
59
|
+
export const propsProxy = (read, write,
|
|
60
|
+
/** The ids of the items of the array at a path (`facade.dataItemIds`). */
|
|
61
|
+
ids = () => []) => {
|
|
62
|
+
const cache = new Map();
|
|
63
|
+
// Item ids per array path, for the value `read()` last gave.
|
|
64
|
+
let seen;
|
|
65
|
+
const known = new Map();
|
|
66
|
+
const idsOf = (path) => {
|
|
67
|
+
const now = read();
|
|
68
|
+
if (now !== seen) {
|
|
69
|
+
seen = now;
|
|
70
|
+
known.clear();
|
|
71
|
+
}
|
|
72
|
+
const key = JSON.stringify(path);
|
|
73
|
+
return known.get(key) ?? known.set(key, ids(path)).get(key);
|
|
74
|
+
};
|
|
75
|
+
const at = (path) => path.reduce((v, k, n) => /^~[a-z]/.test(k)
|
|
76
|
+
? Array.isArray(v)
|
|
77
|
+
? v[idsOf(path.slice(0, n)).indexOf(k)]
|
|
78
|
+
: undefined // its array is gone
|
|
79
|
+
: v !== null && typeof v === 'object'
|
|
80
|
+
? v[segmentKey(k)]
|
|
81
|
+
: undefined, read());
|
|
82
|
+
const put = (path, value) => {
|
|
83
|
+
const next = plain(value);
|
|
84
|
+
if (jsonEquals(at(path), next))
|
|
85
|
+
return;
|
|
86
|
+
write([{ path, ...(next !== undefined && { value: next }) }]);
|
|
87
|
+
};
|
|
88
|
+
const wrap = (path, v) => Array.isArray(v) || isObject(v) ? proxy(path, Array.isArray(v)) : v;
|
|
89
|
+
const proxy = (path, array) => {
|
|
90
|
+
const key = `${array ? '[' : '{'}${JSON.stringify(path)}`;
|
|
91
|
+
const cached = cache.get(key);
|
|
92
|
+
if (cached)
|
|
93
|
+
return cached;
|
|
94
|
+
const current = () => {
|
|
95
|
+
const v = at(path);
|
|
96
|
+
return array ? (Array.isArray(v) ? v : []) : isObject(v) ? v : {};
|
|
97
|
+
};
|
|
98
|
+
/** The path of child `k`: an item by its id, a key as its segment. */
|
|
99
|
+
const child = (k) => [...path, (array && idsOf(path)[Number(k)]) || keySegment(k)];
|
|
100
|
+
const items = () => current().map((v, i) => wrap(child(`${i}`), v));
|
|
101
|
+
const own = (k) => Object.prototype.hasOwnProperty.call(current(), k);
|
|
102
|
+
const made = new Proxy(array ? [] : {}, {
|
|
103
|
+
get(target, k) {
|
|
104
|
+
if (typeof k === 'symbol')
|
|
105
|
+
return array && k === Symbol.iterator
|
|
106
|
+
? () => items()[Symbol.iterator]()
|
|
107
|
+
: Reflect.get(target, k);
|
|
108
|
+
if (array && k === 'length')
|
|
109
|
+
return current().length;
|
|
110
|
+
if (own(k))
|
|
111
|
+
return wrap(child(k), current()[k]);
|
|
112
|
+
if (array && Object.hasOwn(MUTATORS, k))
|
|
113
|
+
return (...args) => {
|
|
114
|
+
const was = plain(current());
|
|
115
|
+
const next = [...was];
|
|
116
|
+
const fn = Array.prototype[k];
|
|
117
|
+
args = args.map((a) => (a !== null && typeof a === 'object' ? plain(a) : a));
|
|
118
|
+
const out = fn.apply(next, args);
|
|
119
|
+
const ops = [MUTATORS[k](was.length, args, was, out)].flat();
|
|
120
|
+
if (!jsonEquals(was, next))
|
|
121
|
+
write(ops.map(({ at, ...op }) => ({ ...op, path: at ? [...path, at] : path })));
|
|
122
|
+
return out === next ? made : out;
|
|
123
|
+
};
|
|
124
|
+
const method = array ? Array.prototype[k] : undefined;
|
|
125
|
+
if (typeof method === 'function')
|
|
126
|
+
return (...args) => method.apply(items(), args);
|
|
127
|
+
return Reflect.get(target, k);
|
|
128
|
+
},
|
|
129
|
+
set(_, k, value) {
|
|
130
|
+
if (typeof k === 'symbol')
|
|
131
|
+
return false;
|
|
132
|
+
if (array && k === 'length') {
|
|
133
|
+
const n = current().length;
|
|
134
|
+
const nulls = Array.from({ length: Math.max(value - n, 0) }, () => null);
|
|
135
|
+
write([{ path, splice: [Math.min(value, n), Math.max(n - value, 0), ...nulls] }]);
|
|
136
|
+
}
|
|
137
|
+
else
|
|
138
|
+
put([...path, keySegment(k)], value);
|
|
139
|
+
return true;
|
|
140
|
+
},
|
|
141
|
+
deleteProperty(_, k) {
|
|
142
|
+
if (typeof k === 'symbol')
|
|
143
|
+
return false;
|
|
144
|
+
if (own(k))
|
|
145
|
+
put([...path, keySegment(k)], undefined);
|
|
146
|
+
return true;
|
|
147
|
+
},
|
|
148
|
+
has: (target, k) => (typeof k === 'string' && own(k)) || Reflect.has(target, k),
|
|
149
|
+
ownKeys: () => [...Object.keys(current()), ...(array ? ['length'] : [])],
|
|
150
|
+
getOwnPropertyDescriptor(target, k) {
|
|
151
|
+
if (array && k === 'length')
|
|
152
|
+
return (Reflect.getOwnPropertyDescriptor(target, k) && {
|
|
153
|
+
value: current().length,
|
|
154
|
+
writable: true,
|
|
155
|
+
enumerable: false,
|
|
156
|
+
configurable: false
|
|
157
|
+
});
|
|
158
|
+
if (typeof k !== 'string' || !own(k))
|
|
159
|
+
return undefined;
|
|
160
|
+
return {
|
|
161
|
+
value: wrap(child(k), current()[k]),
|
|
162
|
+
writable: true,
|
|
163
|
+
enumerable: true,
|
|
164
|
+
configurable: true
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
cache.set(key, made);
|
|
169
|
+
return made;
|
|
170
|
+
};
|
|
171
|
+
return proxy([], false);
|
|
172
|
+
};
|
package/dist/crdt/protocol.d.ts
CHANGED
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
export { bindCrdt, type Crdt, type EngineApi, type EngineDoc, type EngineNode, type EngineTransaction, type EngineItemRef, type YNode, type YItem, type YDoc, type YUndoManager, type YTransaction } from './index.js';
|
|
28
28
|
export { SCHEMA_VERSION, META_KEY } from './edytor-doc.js';
|
|
29
29
|
export { GENERATION, generationWord, frame, PROTOCOL_VERSION, GENERATION_RECORD, GenerationMismatchError, readProtocolVersion, type GenerationRecord } from './protocols/envelope.js';
|
|
30
|
-
export { messageSync, messageAwareness, messageAuth, messageQueryAwareness, messageSaved, messageChunk, messageComments, MAX_FRAME_BYTES, chunkFrame, createChunkReader,
|
|
30
|
+
export { messageSync, messageAwareness, messageAuth, messageQueryAwareness, messageSaved, messageChunk, messageComments, MAX_FRAME_BYTES, chunkFrame, createChunkReader, ChunkError, type ChunkReader, CLOSE } from './providers/room.js';
|
|
31
31
|
export { messageYjsSyncStep1, messageYjsSyncStep2, messageYjsUpdate, type SyncProtocol } from './protocols/sync.js';
|
|
32
32
|
export { messagePermissionDenied, messageReadOnly, writePermissionDenied, writeReadOnly } from './protocols/auth.js';
|
|
33
33
|
export { commentsSubscribe, commentsSnapshot, commentsChange, writeCommentsSubscribe, writeCommentsSnapshot, writeCommentsChange, readCommentsMessage, type CommentChange, type CommentMessage, type CommentSnapshot, type CommentThread, type ThreadComment } from './protocols/comments.js';
|
|
34
34
|
export { applyAwarenessUpdate, encodeAwarenessUpdate, readAwarenessEntries, writeAwarenessEntries, type AwarenessEntry } from './protocols/awareness.js';
|
|
35
35
|
export { createDecoder, readVarUint, readVarUint8Array, type Decoder } from 'lib0-v14/decoding';
|
|
36
36
|
export { writeVarUint8Array, type Encoder } from 'lib0-v14/encoding';
|
|
37
|
-
export { assertAdmission, assertSchema,
|
|
37
|
+
export { assertAdmission, assertSchema, checkSchema, inspectAdmission, isInitialized, registryEmpty, schemaVersion, SchemaMismatchError, UndecodableUpdateError, type AdmissionResult, type AdmissionVerdict, type SchemaProblem } from './admission.js';
|
|
38
38
|
import type { ProviderStack } from './providers/index.js';
|
|
39
39
|
export declare const IndexeddbPersistence: ProviderStack['IndexeddbPersistence'];
|
|
40
40
|
export declare const WebsocketProvider: ProviderStack['WebsocketProvider'];
|
package/dist/crdt/protocol.js
CHANGED
|
@@ -30,7 +30,7 @@ export { bindCrdt } from './index.js';
|
|
|
30
30
|
export { SCHEMA_VERSION, META_KEY } from './edytor-doc.js';
|
|
31
31
|
export { GENERATION, generationWord, frame, PROTOCOL_VERSION, GENERATION_RECORD, GenerationMismatchError, readProtocolVersion } from './protocols/envelope.js';
|
|
32
32
|
// ── Message types, acknowledgements and chunks ─────────────────────────
|
|
33
|
-
export { messageSync, messageAwareness, messageAuth, messageQueryAwareness, messageSaved, messageChunk, messageComments, MAX_FRAME_BYTES, chunkFrame, createChunkReader,
|
|
33
|
+
export { messageSync, messageAwareness, messageAuth, messageQueryAwareness, messageSaved, messageChunk, messageComments, MAX_FRAME_BYTES, chunkFrame, createChunkReader, ChunkError, CLOSE } from './providers/room.js';
|
|
34
34
|
export { messageYjsSyncStep1, messageYjsSyncStep2, messageYjsUpdate } from './protocols/sync.js';
|
|
35
35
|
export { messagePermissionDenied, messageReadOnly, writePermissionDenied, writeReadOnly } from './protocols/auth.js';
|
|
36
36
|
export { commentsSubscribe, commentsSnapshot, commentsChange, writeCommentsSubscribe, writeCommentsSnapshot, writeCommentsChange, readCommentsMessage } from './protocols/comments.js';
|
|
@@ -46,7 +46,7 @@ export { writeVarUint8Array } from 'lib0-v14/encoding';
|
|
|
46
46
|
// the matrix and the refusal-preserves-data contract). The errors they
|
|
47
47
|
// throw are also exported from `edytor` and `edytor/crdt/edytor`, where a
|
|
48
48
|
// `loadDocument` caller catches them.
|
|
49
|
-
export { assertAdmission, assertSchema,
|
|
49
|
+
export { assertAdmission, assertSchema, checkSchema, inspectAdmission, isInitialized, registryEmpty, schemaVersion, SchemaMismatchError, UndecodableUpdateError } from './admission.js';
|
|
50
50
|
// ── Raw providers ──────────────────────────────────────────────────────
|
|
51
51
|
//
|
|
52
52
|
// The classes `createIndexeddbSync`/`createWebsocketSync` construct, bound
|
|
@@ -280,7 +280,7 @@ export declare const bindProviders: (Y: EngineApi) => {
|
|
|
280
280
|
off<NAME extends "refused" | "status" | "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: WebsocketProviderEvents[NAME]): void;
|
|
281
281
|
};
|
|
282
282
|
};
|
|
283
|
-
watchComments: (server: string, roomName: string, listener: (message: import("../protocol.js").CommentMessage) => void) => (() => void);
|
|
283
|
+
watchComments: (server: string | null, roomName: string, listener: (message: import("../protocol.js").CommentMessage) => void) => (() => void);
|
|
284
284
|
storeState: (idbPersistence: {
|
|
285
285
|
db: IDBDatabase | null;
|
|
286
286
|
name: string;
|
|
@@ -69,14 +69,15 @@ export declare const MAX_FRAME_BYTES: number;
|
|
|
69
69
|
* receiver applies the reassembled frame only once `end` arrives.
|
|
70
70
|
*/
|
|
71
71
|
export declare const chunkFrame: (whole: Uint8Array, maxFrameBytes?: number) => Uint8Array[];
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
/**
|
|
73
|
+
* A chunk sequence its reader refuses ({@link createChunkReader}): one
|
|
74
|
+
* announcing a frame larger than the reader takes (`total` over `limit`),
|
|
75
|
+
* or a part or end with no sequence started (one lost, or never sent).
|
|
76
|
+
*/
|
|
77
|
+
export declare class ChunkError extends Error {
|
|
78
|
+
readonly total?: number | undefined;
|
|
79
|
+
readonly limit?: number | undefined;
|
|
80
|
+
constructor(total?: number | undefined, limit?: number | undefined);
|
|
80
81
|
}
|
|
81
82
|
/** A chunk reader ({@link createChunkReader}): feed it chunk bodies; `buffered` is what it holds. */
|
|
82
83
|
export type ChunkReader = {
|
|
@@ -89,7 +90,7 @@ export type ChunkReader = {
|
|
|
89
90
|
* each chunk frame's body (after the message type); it returns the whole
|
|
90
91
|
* frame on `end`, `null` before. An out-of-order or oversized sequence
|
|
91
92
|
* throws and resets; a sequence announcing more than `maxBytes` throws
|
|
92
|
-
* {@link
|
|
93
|
+
* {@link ChunkError} at its start, before anything is buffered. A
|
|
93
94
|
* sequence is assembled into ONE buffer of its announced size, allocated
|
|
94
95
|
* at its start (`buffered`), never into parts copied at its end.
|
|
95
96
|
* `admit(total)` is asked at each start, before that allocation: it may
|
|
@@ -92,26 +92,29 @@ export const chunkFrame = (whole, maxFrameBytes = MAX_FRAME_BYTES) => {
|
|
|
92
92
|
frames.push(frame(messageChunk, (e) => encoding.writeVarUint(e, chunkEnd)));
|
|
93
93
|
return frames;
|
|
94
94
|
};
|
|
95
|
-
/**
|
|
96
|
-
|
|
95
|
+
/**
|
|
96
|
+
* A chunk sequence its reader refuses ({@link createChunkReader}): one
|
|
97
|
+
* announcing a frame larger than the reader takes (`total` over `limit`),
|
|
98
|
+
* or a part or end with no sequence started (one lost, or never sent).
|
|
99
|
+
*/
|
|
100
|
+
export class ChunkError extends Error {
|
|
97
101
|
total;
|
|
98
102
|
limit;
|
|
99
103
|
constructor(total, limit) {
|
|
100
|
-
super(
|
|
104
|
+
super(limit === undefined
|
|
105
|
+
? 'chunk without a start'
|
|
106
|
+
: `chunked frame of ${total} bytes exceeds ${limit}`);
|
|
101
107
|
this.total = total;
|
|
102
108
|
this.limit = limit;
|
|
103
|
-
this.name = '
|
|
109
|
+
this.name = 'ChunkError';
|
|
104
110
|
}
|
|
105
111
|
}
|
|
106
|
-
/** A chunk part or end with no sequence started (one lost, or never sent). */
|
|
107
|
-
export class ChunkSequenceError extends Error {
|
|
108
|
-
}
|
|
109
112
|
/**
|
|
110
113
|
* The receiving half of {@link chunkFrame}, one per connection: feed it
|
|
111
114
|
* each chunk frame's body (after the message type); it returns the whole
|
|
112
115
|
* frame on `end`, `null` before. An out-of-order or oversized sequence
|
|
113
116
|
* throws and resets; a sequence announcing more than `maxBytes` throws
|
|
114
|
-
* {@link
|
|
117
|
+
* {@link ChunkError} at its start, before anything is buffered. A
|
|
115
118
|
* sequence is assembled into ONE buffer of its announced size, allocated
|
|
116
119
|
* at its start (`buffered`), never into parts copied at its end.
|
|
117
120
|
* `admit(total)` is asked at each start, before that allocation: it may
|
|
@@ -136,14 +139,14 @@ export const createChunkReader = (maxBytes = Infinity, admit = () => true) => {
|
|
|
136
139
|
reset();
|
|
137
140
|
const announced = decoding.readVarUint(decoder);
|
|
138
141
|
if (announced > maxBytes)
|
|
139
|
-
throw new
|
|
142
|
+
throw new ChunkError(announced, maxBytes);
|
|
140
143
|
whole = admit(announced) ? new Uint8Array(announced) : null;
|
|
141
144
|
total = announced;
|
|
142
145
|
open = true;
|
|
143
146
|
return null;
|
|
144
147
|
}
|
|
145
148
|
if (!open)
|
|
146
|
-
throw new
|
|
149
|
+
throw new ChunkError();
|
|
147
150
|
if (kind === chunkPart) {
|
|
148
151
|
const bytes = decoding.readVarUint8Array(decoder);
|
|
149
152
|
if (received + bytes.length > total)
|
|
@@ -228,5 +228,5 @@ export declare const bindWebsocketProvider: (Y: EngineApi) => {
|
|
|
228
228
|
off<NAME extends "refused" | "status" | "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: WebsocketProviderEvents[NAME]): void;
|
|
229
229
|
};
|
|
230
230
|
};
|
|
231
|
-
watchComments: (server: string, roomName: string, listener: (message: CommentMessage) => void) => (() => void);
|
|
231
|
+
watchComments: (server: string | null, roomName: string, listener: (message: CommentMessage) => void) => (() => void);
|
|
232
232
|
};
|
|
@@ -142,16 +142,16 @@ export const bindWebsocketProvider = (Y) => {
|
|
|
142
142
|
provider.synced = true;
|
|
143
143
|
}
|
|
144
144
|
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
// the room for them (a subscribe) at every open while a room has a
|
|
148
|
-
// listener, and hands each message the room sends to every listener.
|
|
149
|
-
const commentListeners = new Map();
|
|
150
|
-
const providersOf = new Map();
|
|
145
|
+
const watchers = new Set();
|
|
146
|
+
const providers = new Set();
|
|
151
147
|
const subscribeFrame = (on) => frame(messageComments, (e) => writeCommentsSubscribe(e, on));
|
|
148
|
+
const hears = (watcher, provider) => watcher.room === provider.roomname &&
|
|
149
|
+
(watcher.channel === null || watcher.channel === provider.bcChannel);
|
|
150
|
+
const listenersOf = (provider) => [...watchers].filter((watcher) => hears(watcher, provider)).map((watcher) => watcher.listener);
|
|
151
|
+
const providersFor = (watcher) => [...providers].filter((p) => hears(watcher, p));
|
|
152
152
|
room.messageHandlers[messageComments] = (_encoder, decoder, provider) => {
|
|
153
153
|
const message = readCommentsMessage(decoder);
|
|
154
|
-
for (const listener of
|
|
154
|
+
for (const listener of listenersOf(provider)) {
|
|
155
155
|
try {
|
|
156
156
|
listener(message);
|
|
157
157
|
}
|
|
@@ -162,26 +162,28 @@ export const bindWebsocketProvider = (Y) => {
|
|
|
162
162
|
};
|
|
163
163
|
/**
|
|
164
164
|
* Hear the comment threads of `room` on `server` (the URL a provider
|
|
165
|
-
* dials, `ws:`/`wss
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
165
|
+
* dials, `ws:`/`wss:`; `null`: every provider of that room on the page,
|
|
166
|
+
* whatever its server): every such provider subscribes now and at each
|
|
167
|
+
* (re)connect, which the room answers with every thread (a `snapshot`),
|
|
168
|
+
* then sends each `change`. Answers the unsubscribe; the last listener
|
|
169
|
+
* of a provider leaving tells its room to stop.
|
|
169
170
|
*/
|
|
170
171
|
const watchComments = (server, roomName, listener) => {
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
172
|
+
const watcher = {
|
|
173
|
+
room: roomName,
|
|
174
|
+
channel: server === null ? null : `${server.replace(/\/+$/, '')}/${roomName}`,
|
|
175
|
+
listener
|
|
176
|
+
};
|
|
177
|
+
const fresh = providersFor(watcher).filter((p) => listenersOf(p).length === 0);
|
|
178
|
+
watchers.add(watcher);
|
|
179
|
+
for (const provider of fresh)
|
|
180
|
+
send(provider, subscribeFrame(true));
|
|
179
181
|
return () => {
|
|
180
|
-
if (!
|
|
182
|
+
if (!watchers.delete(watcher))
|
|
181
183
|
return;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
184
|
+
for (const provider of providersFor(watcher))
|
|
185
|
+
if (listenersOf(provider).length === 0)
|
|
186
|
+
send(provider, subscribeFrame(false));
|
|
185
187
|
};
|
|
186
188
|
};
|
|
187
189
|
// The room's acknowledgement and its bounded catch-up (a frame too large
|
|
@@ -468,7 +470,7 @@ export const bindWebsocketProvider = (Y) => {
|
|
|
468
470
|
for (const buf of room.hello(provider))
|
|
469
471
|
sendOn(provider, websocket, buf);
|
|
470
472
|
// The room's comment threads, while someone listens (`watchComments`).
|
|
471
|
-
if (
|
|
473
|
+
if (listenersOf(provider).length > 0)
|
|
472
474
|
sendOn(provider, websocket, subscribeFrame(true));
|
|
473
475
|
};
|
|
474
476
|
provider.emit('status', [{ status: 'connecting' }]);
|
|
@@ -540,8 +542,7 @@ export const bindWebsocketProvider = (Y) => {
|
|
|
540
542
|
this._resync = setInterval(() => send(this, room.step1(this)), resyncInterval);
|
|
541
543
|
}
|
|
542
544
|
this._bcSubscriber = room.bcSubscriber(this);
|
|
543
|
-
|
|
544
|
-
providersOf.set(this.bcChannel, peers.add(this));
|
|
545
|
+
providers.add(this);
|
|
545
546
|
// Local doc updates go to the room; another tab's go to the server
|
|
546
547
|
// only (`broadcastUpdate` quarantines a read-only document). A
|
|
547
548
|
// socket the room made read-only gets this document's own edits
|
|
@@ -641,9 +642,7 @@ export const bindWebsocketProvider = (Y) => {
|
|
|
641
642
|
return;
|
|
642
643
|
clearInterval(this._resync);
|
|
643
644
|
clearInterval(this._checkInterval);
|
|
644
|
-
|
|
645
|
-
if (peers?.delete(this) && peers.size === 0)
|
|
646
|
-
providersOf.delete(this.bcChannel);
|
|
645
|
+
providers.delete(this);
|
|
647
646
|
this.disconnect();
|
|
648
647
|
this.awareness.off('update', this._awarenessUpdateHandler);
|
|
649
648
|
this.doc.off('update', this._updateHandler);
|
package/dist/crdt/semantics.js
CHANGED
|
@@ -40,6 +40,7 @@ export const normalizeRole = (role) => {
|
|
|
40
40
|
};
|
|
41
41
|
};
|
|
42
42
|
/** Freeze `value` and everything in it: the tables are shared by every document. */
|
|
43
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
43
44
|
const frozen = (value) => {
|
|
44
45
|
if (value && typeof value === 'object' && !Object.isFrozen(value)) {
|
|
45
46
|
Object.freeze(value);
|
|
@@ -294,7 +295,8 @@ export const equationSemantics = /* @__PURE__ */ semanticsOf(equationKinds);
|
|
|
294
295
|
* plugins are not default plugins of `<Edytor>`, but their roles are here so their
|
|
295
296
|
* blocks read the same on every replica.
|
|
296
297
|
*/
|
|
297
|
-
export const defaultSemantics = withMarks(semanticsOf(richTextKinds, codeKinds, imageKinds, mediaKinds, layoutKinds, pageKinds, tocKinds, tableKinds, equationKinds),
|
|
298
|
+
export const defaultSemantics = /* @__PURE__ */ withMarks(semanticsOf(richTextKinds, codeKinds, imageKinds, mediaKinds, layoutKinds, pageKinds, tocKinds, tableKinds, equationKinds),
|
|
299
|
+
/* @__PURE__ */ Object.assign({}, richTextMarks, commentMarks));
|
|
298
300
|
/**
|
|
299
301
|
* The facade configuration (`EdytorDocConfig`) a document with no view
|
|
300
302
|
* reads `semantics` with — the room's: roles, default children, content-less kinds
|
package/dist/dnd/autoScroll.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
/** One adapter's auto-scroll (Atlassian's auto-scroll package), its drags already chosen. */
|
|
2
|
+
export type Scrollers = {
|
|
3
|
+
/** The window scrolls as the pointer nears its edges. */
|
|
4
|
+
window(): () => void;
|
|
5
|
+
/** `element` scrolls as the pointer nears its edges. */
|
|
6
|
+
element(element: Element): () => void;
|
|
7
|
+
};
|
|
1
8
|
/**
|
|
2
|
-
* Auto-scroll for one drag (a block's, a table row's or column's
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* drag's start (the package allows it
|
|
9
|
+
* Auto-scroll for one drag (a block's, a table row's or column's, files
|
|
10
|
+
* dragged from outside): the window and every scrolling element from the
|
|
11
|
+
* editor up (the editor included) scroll as the pointer nears their edges,
|
|
12
|
+
* faster the closer and the longer it stays, innermost first. `scrollers`
|
|
13
|
+
* is the drag's adapter's (`elementScrollers`, `externalScrollers`), kept to
|
|
14
|
+
* this editor's drags. Registered at the drag's start (the package allows it
|
|
15
|
+
* mid-drag); the answer releases it.
|
|
8
16
|
*/
|
|
9
|
-
export declare const autoScrollFor: (root: HTMLElement,
|
|
17
|
+
export declare const autoScrollFor: (root: HTMLElement, scrollers: Scrollers) => (() => void);
|
package/dist/dnd/autoScroll.js
CHANGED
|
@@ -1,25 +1,20 @@
|
|
|
1
|
-
import { autoScroll, autoScrollWindow } from './pragmatic.js';
|
|
2
1
|
/**
|
|
3
|
-
* Auto-scroll for one drag (a block's, a table row's or column's
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* drag's start (the package allows it
|
|
2
|
+
* Auto-scroll for one drag (a block's, a table row's or column's, files
|
|
3
|
+
* dragged from outside): the window and every scrolling element from the
|
|
4
|
+
* editor up (the editor included) scroll as the pointer nears their edges,
|
|
5
|
+
* faster the closer and the longer it stays, innermost first. `scrollers`
|
|
6
|
+
* is the drag's adapter's (`elementScrollers`, `externalScrollers`), kept to
|
|
7
|
+
* this editor's drags. Registered at the drag's start (the package allows it
|
|
8
|
+
* mid-drag); the answer releases it.
|
|
9
9
|
*/
|
|
10
|
-
export const autoScrollFor = (root,
|
|
11
|
-
|
|
12
|
-
// so it is created only where that exists.
|
|
13
|
-
if (typeof root.ownerDocument.elementsFromPoint !== 'function')
|
|
14
|
-
return () => { };
|
|
15
|
-
const canScroll = ({ source }) => ours(source.data);
|
|
16
|
-
const releases = [autoScrollWindow({ canScroll })];
|
|
10
|
+
export const autoScrollFor = (root, scrollers) => {
|
|
11
|
+
const releases = [scrollers.window()];
|
|
17
12
|
const { body, documentElement, defaultView } = root.ownerDocument;
|
|
18
13
|
// The window is the document's scroller: stop below it.
|
|
19
14
|
for (let element = root; element && element !== body && element !== documentElement; element = element.parentElement) {
|
|
20
15
|
const { overflowX, overflowY } = defaultView.getComputedStyle(element);
|
|
21
16
|
if (/auto|scroll|overlay/.test(`${overflowX} ${overflowY}`))
|
|
22
|
-
releases.push(
|
|
17
|
+
releases.push(scrollers.element(element));
|
|
23
18
|
}
|
|
24
19
|
return () => releases.forEach((release) => release());
|
|
25
20
|
};
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* future parent's own row. Both live in the overlay layer, measured each
|
|
6
6
|
* frame. The controller decides the placement; this draws it.
|
|
7
7
|
*/
|
|
8
|
-
import type { Block } from '
|
|
9
|
-
import type { Edytor } from '
|
|
8
|
+
import type { Block } from '../block/block.svelte.js';
|
|
9
|
+
import type { Edytor } from '../edytor.svelte.js';
|
|
10
10
|
import { type DropPlacement } from './geometry.js';
|
|
11
11
|
/** What the indicator reads of the controller: the dragged blocks and the beside resolution. */
|
|
12
12
|
type IndicatorContext = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getOwnRowBottom, isBeside, nestIndent, ownRow, ownTextRow } from './geometry.js';
|
|
1
|
+
import { cssVar, getOwnRowBottom, isBeside, nestIndent, ownRow, ownTextRow } from './geometry.js';
|
|
2
2
|
/** Notion's drop bar: 4px (its height in `BlockHandles.svelte`, its look the app's). */
|
|
3
3
|
const BAR = 4;
|
|
4
4
|
/** Place `element` at `box`, relative to the layer (`origin`). */
|
|
@@ -14,10 +14,7 @@ const place = (element, box, origin) => Object.assign(element.style, {
|
|
|
14
14
|
* unset there without one.
|
|
15
15
|
*/
|
|
16
16
|
const themed = (from, name) => {
|
|
17
|
-
const value = from
|
|
18
|
-
?.getComputedStyle(from)
|
|
19
|
-
.getPropertyValue(name)
|
|
20
|
-
.trim();
|
|
17
|
+
const value = cssVar(from, name);
|
|
21
18
|
return (element) => value ? element.style.setProperty(name, value) : element.style.removeProperty(name);
|
|
22
19
|
};
|
|
23
20
|
/**
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Scrollers } from './autoScroll.js';
|
|
2
|
+
export { dropTargetForExternal } from './vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js';
|
|
3
|
+
export { containsFiles } from './vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js';
|
|
4
|
+
export { getFiles } from './vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js';
|
|
5
|
+
/** The external adapter's auto-scroll, while `ours()` (the drag is over this editor). */
|
|
6
|
+
export declare const externalScrollers: (ours: () => boolean) => Scrollers;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Pragmatic drag and drop's external adapter (vendored with the element
|
|
2
|
+
// adapter, on its core, `vendor/pragmatic/UPSTREAM.md`): drags that start
|
|
3
|
+
// outside the window (files from the desktop). Only the media plugins that
|
|
4
|
+
// take an upload import it (`plugins/fileDrop.ts`), so a view without them
|
|
5
|
+
// ships none of it.
|
|
6
|
+
import { autoScrollForExternal, autoScrollWindowForExternal } from './vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.js';
|
|
7
|
+
export { dropTargetForExternal } from './vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js';
|
|
8
|
+
export { containsFiles } from './vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js';
|
|
9
|
+
export { getFiles } from './vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js';
|
|
10
|
+
/** The external adapter's auto-scroll, while `ours()` (the drag is over this editor). */
|
|
11
|
+
export const externalScrollers = (ours) => {
|
|
12
|
+
const canScroll = () => ours();
|
|
13
|
+
return {
|
|
14
|
+
window: () => autoScrollWindowForExternal({ canScroll }),
|
|
15
|
+
element: (element) => autoScrollForExternal({ element, canScroll })
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* placement's shape, a block's own row, its first text line and one
|
|
5
5
|
* nesting step.
|
|
6
6
|
*/
|
|
7
|
-
import type { Block } from '
|
|
8
|
-
import type { BlockMovePosition } from '
|
|
7
|
+
import type { Block } from '../block/block.svelte.js';
|
|
8
|
+
import type { BlockMovePosition } from '../session/moves.js';
|
|
9
9
|
export type DropPlacement = {
|
|
10
10
|
target: Block;
|
|
11
11
|
node: HTMLElement;
|
|
@@ -27,6 +27,8 @@ export declare const ownTextRow: (node: HTMLElement) => DOMRect;
|
|
|
27
27
|
*/
|
|
28
28
|
export declare const NEST_INDENT = 24;
|
|
29
29
|
export declare const nestIndent: (node: HTMLElement) => number;
|
|
30
|
+
/** The theme variable `name` as `node` inherits it, read now (none outside a window). */
|
|
31
|
+
export declare const cssVar: (node: HTMLElement, name: string) => string | undefined;
|
|
30
32
|
/**
|
|
31
33
|
* Whether `y` is over the hint of `node`'s empty body (`body.hint`, a kind's
|
|
32
34
|
* `data-edytor-empty-body` element: an open toggle's, a callout's): a drop
|
|
@@ -31,12 +31,11 @@ export const ownTextRow = (node) => {
|
|
|
31
31
|
*/
|
|
32
32
|
export const NEST_INDENT = 24;
|
|
33
33
|
export const nestIndent = (node) => {
|
|
34
|
-
const value = node
|
|
35
|
-
?.getComputedStyle(node)
|
|
36
|
-
.getPropertyValue('--edytor-nest-indent')
|
|
37
|
-
.trim();
|
|
34
|
+
const value = cssVar(node, '--edytor-nest-indent');
|
|
38
35
|
return value?.endsWith('px') ? parseFloat(value) : NEST_INDENT;
|
|
39
36
|
};
|
|
37
|
+
/** The theme variable `name` as `node` inherits it, read now (none outside a window). */
|
|
38
|
+
export const cssVar = (node, name) => node.ownerDocument.defaultView?.getComputedStyle(node).getPropertyValue(name).trim();
|
|
40
39
|
/**
|
|
41
40
|
* Whether `y` is over the hint of `node`'s empty body (`body.hint`, a kind's
|
|
42
41
|
* `data-edytor-empty-body` element: an open toggle's, a callout's): a drop
|