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
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { placeNear } from '../../surface/overlay.js';
|
|
2
|
-
import { onPress } from '../../events/onFocus.js';
|
|
3
1
|
import { convertToKind, holdsNothing } from '../../kinds.js';
|
|
4
2
|
import { pastedLink } from '../richtext/richTextOperations.js';
|
|
5
3
|
import { safeWebUrl } from './media.js';
|
|
6
|
-
import { mountChrome } from '../chrome.js';
|
|
4
|
+
import { mountChrome, onPressOutside, virtualAnchor } from '../chrome.js';
|
|
7
5
|
import { ChromeList, inPage, listHotkeys } from '../list.svelte.js';
|
|
8
6
|
/**
|
|
9
7
|
* Pasting a bare URL on an empty line (Notion): the URL lands as a link at
|
|
@@ -27,9 +25,6 @@ export class UrlPasteController extends ChromeList {
|
|
|
27
25
|
get count() {
|
|
28
26
|
return this.open?.options.length ?? 0;
|
|
29
27
|
}
|
|
30
|
-
get readonly() {
|
|
31
|
-
return this.edytor.readonly;
|
|
32
|
-
}
|
|
33
28
|
/** A custom menu (a media plugin's `menu`): the first one a plugin making an offer passed. */
|
|
34
29
|
#menu;
|
|
35
30
|
/** Take `menu` as the view's menu, unless a plugin listed before passed one. @internal */
|
|
@@ -70,7 +65,7 @@ export class UrlPasteController extends ChromeList {
|
|
|
70
65
|
: {};
|
|
71
66
|
edytor.dispatcher.run('insertFromPaste', () => {
|
|
72
67
|
edytor.insertText(block.id, text.segStart, url, marks);
|
|
73
|
-
edytor.dispatcher.
|
|
68
|
+
edytor.dispatcher.caretIn(edytor.idToBlock.get(block.id)?.firstText, url.length);
|
|
74
69
|
});
|
|
75
70
|
if (edytor.dispatcher.last?.status !== 'applied')
|
|
76
71
|
return;
|
|
@@ -122,12 +117,7 @@ export class UrlPasteController extends ChromeList {
|
|
|
122
117
|
this.close();
|
|
123
118
|
},
|
|
124
119
|
onEdytorAttached: ({ node }) => {
|
|
125
|
-
const
|
|
126
|
-
const target = event.target;
|
|
127
|
-
if (!target?.closest?.('[data-edytor-url-paste-host]'))
|
|
128
|
-
this.close();
|
|
129
|
-
};
|
|
130
|
-
const offPress = onPress(this.edytor, node.ownerDocument, outside, true);
|
|
120
|
+
const offPress = onPressOutside(this.edytor, node.ownerDocument, '[data-edytor-url-paste-host]', this.close);
|
|
131
121
|
const unmount = mountChrome(this.edytor, this.#menu, this, () => this.open, { name: 'edytor-url-paste-host', zIndex: 50, measure: this.measure }, this.close);
|
|
132
122
|
return () => {
|
|
133
123
|
offPress();
|
|
@@ -136,16 +126,17 @@ export class UrlPasteController extends ChromeList {
|
|
|
136
126
|
};
|
|
137
127
|
}
|
|
138
128
|
});
|
|
139
|
-
/**
|
|
140
|
-
measure = (
|
|
129
|
+
/** A gone line closes the menu (measured in the overlay's frame). @internal */
|
|
130
|
+
measure = () => {
|
|
141
131
|
const { open, edytor } = this;
|
|
142
|
-
if (!open)
|
|
143
|
-
return;
|
|
144
|
-
const block = edytor.idToBlock.get(open.block);
|
|
145
|
-
if (!block?.isInTree)
|
|
132
|
+
if (open && !edytor.idToBlock.get(open.block)?.isInTree)
|
|
146
133
|
return () => this.close();
|
|
147
|
-
|
|
148
|
-
|
|
134
|
+
};
|
|
135
|
+
/** Where the menu stands (`ChromeAnchor`): the pasted line, which your `menu` places itself under. */
|
|
136
|
+
anchor = virtualAnchor(() => this.#line()?.getBoundingClientRect(), () => this.#line());
|
|
137
|
+
#line = () => {
|
|
138
|
+
const block = this.open && this.edytor.idToBlock.get(this.open.block);
|
|
139
|
+
return block ? (block.firstText?.node ?? block.node) : undefined;
|
|
149
140
|
};
|
|
150
141
|
}
|
|
151
142
|
const controllers = new WeakMap();
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
<svelte:options runes />
|
|
2
2
|
|
|
3
3
|
<script module lang="ts">
|
|
4
|
+
import { mentionForms } from '../../export/forms.js';
|
|
5
|
+
import './mention.css';
|
|
4
6
|
import type { Snippet } from 'svelte';
|
|
5
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
InlineBlockDefinition,
|
|
9
|
+
InlineBlockSnippetPayload,
|
|
10
|
+
InlineBlockView,
|
|
11
|
+
Plugin,
|
|
12
|
+
TriggerContext
|
|
13
|
+
} from '../../plugins.js';
|
|
6
14
|
import type { TriggerMenuController } from '../triggers/TriggerController.svelte.js';
|
|
7
|
-
import { withRulesAndTriggers } from '../triggers/triggers.js';
|
|
15
|
+
import { placeAtom, withRulesAndTriggers } from '../triggers/triggers.js';
|
|
8
16
|
|
|
9
17
|
/** A person the mention menu offers: what your app's directory answers. */
|
|
10
18
|
export type MentionItem = {
|
|
@@ -18,7 +26,7 @@
|
|
|
18
26
|
avatar?: string;
|
|
19
27
|
};
|
|
20
28
|
|
|
21
|
-
/** What a
|
|
29
|
+
/** What a mention atom stores (whatever its kind). */
|
|
22
30
|
export type MentionData = { id: string; label: string };
|
|
23
31
|
|
|
24
32
|
export type MentionPluginOptions = {
|
|
@@ -27,8 +35,15 @@
|
|
|
27
35
|
query: string,
|
|
28
36
|
ctx: TriggerContext
|
|
29
37
|
) => readonly MentionItem[] | Promise<readonly MentionItem[]>;
|
|
30
|
-
/** The character that opens the menu (default `@`). */
|
|
38
|
+
/** The character that opens the menu, and that the atom shows before its label (default `@`). */
|
|
31
39
|
char?: string;
|
|
40
|
+
/**
|
|
41
|
+
* The inline kind the atoms are (default `mention`), and the name of the
|
|
42
|
+
* trigger menu (`controller.trigger.name`). List the plugin once per kind
|
|
43
|
+
* to mention several things (`@` people, `$` tickers as `ticker`); two
|
|
44
|
+
* instances of one kind: the first listed defines it.
|
|
45
|
+
*/
|
|
46
|
+
kind?: string;
|
|
32
47
|
/**
|
|
33
48
|
* The menu's markup and its words; it renders while `controller.isOpen`,
|
|
34
49
|
* at the caret (without it, nothing shows). Keep its ARIA with `{@attach
|
|
@@ -38,61 +53,58 @@
|
|
|
38
53
|
menu?: Snippet<[TriggerMenuController<MentionItem>]>;
|
|
39
54
|
};
|
|
40
55
|
|
|
56
|
+
/** A mention kind's record: its `char` read by the atom's markup. */
|
|
57
|
+
type MentionKind = InlineBlockDefinition & { char: string };
|
|
58
|
+
|
|
59
|
+
/** The char of the atom's kind (the first listed instance's); `@` with no view (a suggestion). */
|
|
60
|
+
const charOf = (atom: InlineBlockView) =>
|
|
61
|
+
(atom.handle?.edytor.inlineBlocks.get(atom.type) as Partial<MentionKind> | undefined)?.char ??
|
|
62
|
+
'@';
|
|
63
|
+
|
|
41
64
|
/**
|
|
42
65
|
* People mentions, as in Notion: `@` opens a menu of the people your app's
|
|
43
66
|
* `items(query)` answers; picking one replaces `@query` with a `mention`
|
|
44
67
|
* atom (`{ id, label }`) and puts the caret after it, in one undo step.
|
|
68
|
+
* `char` and `kind` make another one (`$` tickers as `ticker` atoms).
|
|
45
69
|
*/
|
|
46
|
-
export const createMentionPlugin =
|
|
47
|
-
|
|
48
|
-
|
|
70
|
+
export const createMentionPlugin = (options: MentionPluginOptions): Plugin => {
|
|
71
|
+
const char = options.char ?? '@';
|
|
72
|
+
const kind = options.kind ?? 'mention';
|
|
73
|
+
const atom: MentionKind = {
|
|
74
|
+
snippet: mention,
|
|
75
|
+
char,
|
|
76
|
+
...mentionForms(kind, char)
|
|
77
|
+
};
|
|
78
|
+
return (edytor) =>
|
|
49
79
|
withRulesAndTriggers(
|
|
50
80
|
edytor,
|
|
51
|
-
{
|
|
52
|
-
inlineBlocks: {
|
|
53
|
-
mention: {
|
|
54
|
-
snippet: mention,
|
|
55
|
-
plain: (data) => {
|
|
56
|
-
const label = (data as Partial<MentionData> | undefined)?.label;
|
|
57
|
-
return typeof label === 'string' && label ? `@${label}` : '@';
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
},
|
|
81
|
+
{ inlineBlocks: { [kind]: atom } },
|
|
62
82
|
{
|
|
63
83
|
triggers: [
|
|
64
84
|
{
|
|
65
|
-
char
|
|
85
|
+
char,
|
|
86
|
+
name: kind,
|
|
66
87
|
items: (query, ctx) => options.items(query, ctx),
|
|
67
|
-
label: (
|
|
68
|
-
key: (
|
|
88
|
+
label: (item: MentionItem) => item.label,
|
|
89
|
+
key: (item: MentionItem) => item.id,
|
|
69
90
|
menu: options.menu,
|
|
70
|
-
onPick: (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (written) caret(from + 1);
|
|
76
|
-
return written;
|
|
77
|
-
}
|
|
91
|
+
onPick: (item: MentionItem, ctx) =>
|
|
92
|
+
placeAtom(ctx, {
|
|
93
|
+
type: kind,
|
|
94
|
+
data: { id: item.id, label: item.label } satisfies MentionData
|
|
95
|
+
})
|
|
78
96
|
}
|
|
79
97
|
]
|
|
80
98
|
}
|
|
81
99
|
);
|
|
100
|
+
};
|
|
82
101
|
</script>
|
|
83
102
|
|
|
84
103
|
{#snippet mention({ block }: InlineBlockSnippetPayload<Partial<MentionData>>)}
|
|
85
104
|
<span
|
|
86
105
|
class="edytor-mention"
|
|
87
106
|
data-selected={block.selected ? 'true' : undefined}
|
|
88
|
-
data-edytor-mention
|
|
89
|
-
data-mention-id={block.data.id}
|
|
107
|
+
data-edytor-mention={block.type}
|
|
108
|
+
data-mention-id={block.data.id}>{charOf(block)}{block.data.label ?? ''}</span
|
|
90
109
|
>
|
|
91
110
|
{/snippet}
|
|
92
|
-
|
|
93
|
-
<style>
|
|
94
|
-
/* One unit, on one line; its look is a theme's. */
|
|
95
|
-
.edytor-mention {
|
|
96
|
-
white-space: nowrap;
|
|
97
|
-
}
|
|
98
|
-
</style>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import './mention.css';
|
|
1
2
|
import type { Snippet } from 'svelte';
|
|
2
3
|
import type { Plugin, TriggerContext } from '../../plugins.js';
|
|
3
4
|
import type { TriggerMenuController } from '../triggers/TriggerController.svelte.js';
|
|
@@ -12,7 +13,7 @@ export type MentionItem = {
|
|
|
12
13
|
/** An avatar image URL (http, https or data). */
|
|
13
14
|
avatar?: string;
|
|
14
15
|
};
|
|
15
|
-
/** What a
|
|
16
|
+
/** What a mention atom stores (whatever its kind). */
|
|
16
17
|
export type MentionData = {
|
|
17
18
|
id: string;
|
|
18
19
|
label: string;
|
|
@@ -20,8 +21,15 @@ export type MentionData = {
|
|
|
20
21
|
export type MentionPluginOptions = {
|
|
21
22
|
/** The people matching `query` (the text typed after `@`), at once or as a promise. */
|
|
22
23
|
items: (query: string, ctx: TriggerContext) => readonly MentionItem[] | Promise<readonly MentionItem[]>;
|
|
23
|
-
/** The character that opens the menu (default `@`). */
|
|
24
|
+
/** The character that opens the menu, and that the atom shows before its label (default `@`). */
|
|
24
25
|
char?: string;
|
|
26
|
+
/**
|
|
27
|
+
* The inline kind the atoms are (default `mention`), and the name of the
|
|
28
|
+
* trigger menu (`controller.trigger.name`). List the plugin once per kind
|
|
29
|
+
* to mention several things (`@` people, `$` tickers as `ticker`); two
|
|
30
|
+
* instances of one kind: the first listed defines it.
|
|
31
|
+
*/
|
|
32
|
+
kind?: string;
|
|
25
33
|
/**
|
|
26
34
|
* The menu's markup and its words; it renders while `controller.isOpen`,
|
|
27
35
|
* at the caret (without it, nothing shows). Keep its ARIA with `{@attach
|
|
@@ -34,6 +42,7 @@ export type MentionPluginOptions = {
|
|
|
34
42
|
* People mentions, as in Notion: `@` opens a menu of the people your app's
|
|
35
43
|
* `items(query)` answers; picking one replaces `@query` with a `mention`
|
|
36
44
|
* atom (`{ id, label }`) and puts the caret after it, in one undo step.
|
|
45
|
+
* `char` and `kind` make another one (`$` tickers as `ticker` atoms).
|
|
37
46
|
*/
|
|
38
47
|
export declare const createMentionPlugin: (options: MentionPluginOptions) => Plugin;
|
|
39
48
|
declare const MentionPlugin: import("svelte").Component<Record<string, never>, {}, "">;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
|
+
import { pageForms } from '../../export/forms.js';
|
|
2
3
|
import type { Plugin, BlockSnippetPayload } from '../../plugins.js';
|
|
3
4
|
import { pageKinds } from '../../crdt/semantics.js';
|
|
4
5
|
import { convertToKind, type KindRow } from '../../kinds.js';
|
|
@@ -6,7 +7,6 @@
|
|
|
6
7
|
import { getSelectedBlocksInDocumentOrder } from '../../selection/replaceSelection.js';
|
|
7
8
|
import PageLink from './PageLink.svelte';
|
|
8
9
|
import {
|
|
9
|
-
pageHtml,
|
|
10
10
|
pageIdOf,
|
|
11
11
|
pageTitleOf,
|
|
12
12
|
pageOptions as optionsOf,
|
|
@@ -63,15 +63,8 @@
|
|
|
63
63
|
...pageKinds.page,
|
|
64
64
|
snippet: page,
|
|
65
65
|
empty: { content: [], children: [] },
|
|
66
|
-
html: (block) => pageHtml(block.data, own, labels.untitled),
|
|
67
|
-
plain: (block) => pageTitleOf(block.data?.title) ?? labels.untitled,
|
|
68
66
|
// Its own export: a `p[data-edytor-page]` naming the page.
|
|
69
|
-
|
|
70
|
-
const pageId = pageIdOf(el.getAttribute('data-edytor-page'));
|
|
71
|
-
if (el.localName !== 'p' || !pageId) return;
|
|
72
|
-
const title = pageTitleOf(el.textContent);
|
|
73
|
-
return { pageId, ...(title && { title }) };
|
|
74
|
-
}
|
|
67
|
+
...pageForms(own, labels.untitled).page
|
|
75
68
|
}
|
|
76
69
|
},
|
|
77
70
|
commands: create
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sanitizeLinkHref } from '
|
|
1
|
+
import { sanitizeLinkHref } from '../../utils/sanitize.js';
|
|
2
2
|
import { escapeHtml } from '../../clipboard/serializeClipboardFragment.js';
|
|
3
3
|
/** Each view's page options (the first page plugin listed sets them). */
|
|
4
4
|
export const pageOptions = new WeakMap();
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
<svelte:options runes />
|
|
2
2
|
|
|
3
3
|
<script module lang="ts">
|
|
4
|
+
import { pageLinkForms } from '../../export/forms.js';
|
|
5
|
+
import './pageLink.css';
|
|
4
6
|
import type { Snippet } from 'svelte';
|
|
5
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
InlineBlockSnippetPayload,
|
|
9
|
+
Plugin,
|
|
10
|
+
PluginOperations,
|
|
11
|
+
TriggerContext
|
|
12
|
+
} from '../../plugins.js';
|
|
13
|
+
import type { Edytor } from '../../edytor.svelte.js';
|
|
14
|
+
import type { TextAnchor } from '../../selection/selection.svelte.js';
|
|
6
15
|
import type { TriggerMenuController } from '../triggers/TriggerController.svelte.js';
|
|
7
|
-
import { withRulesAndTriggers } from '../triggers/triggers.js';
|
|
16
|
+
import { placeAtom, withRulesAndTriggers } from '../triggers/triggers.js';
|
|
8
17
|
import { pageLinkEnglish, labelsOf } from '../../labels.js';
|
|
9
18
|
import { sanitizeLinkHref } from '../richtext/richTextOperations.js';
|
|
10
19
|
|
|
@@ -31,6 +40,18 @@
|
|
|
31
40
|
) => readonly PageLinkItem[] | Promise<readonly PageLinkItem[]>;
|
|
32
41
|
/** A page's URL when the search answers none (`/pages/<id>`, say). */
|
|
33
42
|
href?: (page: PageLinkItem) => string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* The page a pasted text names (your app's URL for it, `page:roadmap`…),
|
|
45
|
+
* at once or as a promise; `null` when it names none. Asked for a plain
|
|
46
|
+
* text paste at a caret that is one item (trimmed, one line): a page
|
|
47
|
+
* turns the pasted text into a `pageLink` atom, an undo step of its own
|
|
48
|
+
* after the paste, so undo gives the text back. A promise lets the paste
|
|
49
|
+
* land as it would without this option and swaps it when it answers, if
|
|
50
|
+
* the text is still there.
|
|
51
|
+
*/
|
|
52
|
+
fromPaste?: (
|
|
53
|
+
text: string
|
|
54
|
+
) => PageLinkItem | null | undefined | Promise<PageLinkItem | null | undefined>;
|
|
34
55
|
/** The text that opens the menu (default `[[`). */
|
|
35
56
|
char?: string;
|
|
36
57
|
/**
|
|
@@ -42,11 +63,107 @@
|
|
|
42
63
|
menu?: Snippet<[TriggerMenuController<PageLinkItem>]>;
|
|
43
64
|
};
|
|
44
65
|
|
|
66
|
+
/** The atom for `page`, its href sanitized. */
|
|
67
|
+
const atomOf = (page: PageLinkItem, options: PageLinkPluginOptions) => {
|
|
68
|
+
const href = sanitizeLinkHref(page.href ?? options.href?.(page)) ?? undefined;
|
|
69
|
+
const data: PageLinkData = {
|
|
70
|
+
id: page.id,
|
|
71
|
+
title: page.title,
|
|
72
|
+
...(href ? { href } : {}),
|
|
73
|
+
...(page.icon ? { icon: page.icon } : {})
|
|
74
|
+
};
|
|
75
|
+
return { type: 'pageLink', data };
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const isPromise = <T,>(value: unknown): value is Promise<T> =>
|
|
79
|
+
typeof (value as Promise<T> | null)?.then === 'function';
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Swap the pasted `item`, where the paste put it (right after `start`,
|
|
83
|
+
* past leading spaces), for `page`'s atom: one `autolink` step, so undo
|
|
84
|
+
* gives the text back. Nothing when the view is readonly or the text is
|
|
85
|
+
* no longer there; the caret follows the atom when it was at the text's end.
|
|
86
|
+
*/
|
|
87
|
+
const swapPasted = (
|
|
88
|
+
edytor: Edytor,
|
|
89
|
+
start: TextAnchor,
|
|
90
|
+
item: string,
|
|
91
|
+
page: PageLinkItem,
|
|
92
|
+
options: PageLinkPluginOptions
|
|
93
|
+
) => {
|
|
94
|
+
if (edytor.readonly) return;
|
|
95
|
+
const at = edytor.selection.resolveTextAnchor(start);
|
|
96
|
+
if (!at) return;
|
|
97
|
+
const { text } = at;
|
|
98
|
+
const content = text.stringContent;
|
|
99
|
+
let from = at.offset;
|
|
100
|
+
while (from < content.length && /\s/.test(content[from])) from++;
|
|
101
|
+
if (content.slice(from, from + item.length) !== item) return;
|
|
102
|
+
const block = text.parent;
|
|
103
|
+
const offset = text.segStart + from;
|
|
104
|
+
const caret = edytor.selection.caret;
|
|
105
|
+
const follows = caret?.block === block && caret.offset === offset + item.length;
|
|
106
|
+
edytor.dispatcher.run('autolink', () => {
|
|
107
|
+
if (edytor.deleteText(block.id, offset, item.length).status !== 'applied') return;
|
|
108
|
+
edytor.insertInline(block.id, offset, atomOf(page, options));
|
|
109
|
+
if (follows) edytor.dispatcher.caret({ block, offset: offset + 1 });
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The paste hook of `fromPaste` (it runs before the other plugins'
|
|
115
|
+
* `onPaste`, `pasteFirst`): a plain text paste at a caret in a text,
|
|
116
|
+
* outside islands and voids, that is one item. A page answered at once
|
|
117
|
+
* claims the paste (the text, then the swap); a promise claims nothing
|
|
118
|
+
* (the rich text link, the URL menu or the plain paste take it) and swaps
|
|
119
|
+
* what landed when it answers a page.
|
|
120
|
+
*/
|
|
121
|
+
const pasteHook = (edytor: Edytor, options: PageLinkPluginOptions): PluginOperations['onPaste'] =>
|
|
122
|
+
options.fromPaste &&
|
|
123
|
+
(({ e, prevent, at }) => {
|
|
124
|
+
const { fromPaste } = options;
|
|
125
|
+
if (!fromPaste || at || edytor.readonly) return;
|
|
126
|
+
const plain = e.clipboardData?.getData('text/plain') ?? '';
|
|
127
|
+
const item = plain.trim();
|
|
128
|
+
if (!item || /[\r\n]/.test(item)) return;
|
|
129
|
+
const { value, projection } = edytor.selection;
|
|
130
|
+
if (value.kind !== 'text' || !projection.isCollapsed) return;
|
|
131
|
+
if (projection.islandRoot !== null || projection.voidRoot !== null) return;
|
|
132
|
+
const { startText: text, yStart } = edytor.selection.textRange();
|
|
133
|
+
if (!text) return;
|
|
134
|
+
const start = edytor.selection.createTextAnchor(text, yStart, 'left');
|
|
135
|
+
if (!start) return;
|
|
136
|
+
let answer: ReturnType<typeof fromPaste>;
|
|
137
|
+
try {
|
|
138
|
+
answer = fromPaste(item);
|
|
139
|
+
} catch {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (isPromise<PageLinkItem | null | undefined>(answer)) {
|
|
143
|
+
answer.then(
|
|
144
|
+
(page) => page && swapPasted(edytor, start, item, page, options),
|
|
145
|
+
() => {}
|
|
146
|
+
);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const page = answer;
|
|
150
|
+
if (!page) return;
|
|
151
|
+
prevent(() => {
|
|
152
|
+
edytor.dispatcher.run('insertFromPaste', () => {
|
|
153
|
+
edytor.insertText(text.parent.id, text.segStart + yStart, item);
|
|
154
|
+
edytor.dispatcher.caretIn(text, yStart + item.length);
|
|
155
|
+
});
|
|
156
|
+
if (edytor.dispatcher.last?.status === 'applied')
|
|
157
|
+
swapPasted(edytor, start, item, page, options);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
45
161
|
/**
|
|
46
162
|
* Links to your app's pages, as Notion's `[[`: it opens a menu of the pages
|
|
47
163
|
* your app's `search(query)` answers; picking one replaces `[[query` with
|
|
48
164
|
* a `pageLink` atom (`{ id, title, href, icon }`), an `<a>` to the page,
|
|
49
|
-
* and puts the caret after it, in one undo step.
|
|
165
|
+
* and puts the caret after it, in one undo step. With `fromPaste`, a
|
|
166
|
+
* pasted text your app recognizes becomes a page link too.
|
|
50
167
|
*/
|
|
51
168
|
export const createPageLinkPlugin =
|
|
52
169
|
(options: PageLinkPluginOptions): Plugin =>
|
|
@@ -54,13 +171,13 @@
|
|
|
54
171
|
withRulesAndTriggers(
|
|
55
172
|
edytor,
|
|
56
173
|
{
|
|
174
|
+
...(edytor && options.fromPaste
|
|
175
|
+
? { onPaste: pasteHook(edytor, options), pasteFirst: true }
|
|
176
|
+
: {}),
|
|
57
177
|
inlineBlocks: {
|
|
58
178
|
pageLink: {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const title = (data as Partial<PageLinkData> | undefined)?.title;
|
|
62
|
-
return typeof title === 'string' ? title : '';
|
|
63
|
-
}
|
|
179
|
+
...pageLinkForms(),
|
|
180
|
+
snippet: pageLink
|
|
64
181
|
}
|
|
65
182
|
}
|
|
66
183
|
},
|
|
@@ -72,19 +189,7 @@
|
|
|
72
189
|
label: (page: PageLinkItem) => page.title,
|
|
73
190
|
key: (page: PageLinkItem) => page.id,
|
|
74
191
|
menu: options.menu,
|
|
75
|
-
onPick: (page: PageLinkItem,
|
|
76
|
-
const href = sanitizeLinkHref(page.href ?? options.href?.(page)) ?? undefined;
|
|
77
|
-
const data: PageLinkData = {
|
|
78
|
-
id: page.id,
|
|
79
|
-
title: page.title,
|
|
80
|
-
...(href ? { href } : {}),
|
|
81
|
-
...(page.icon ? { icon: page.icon } : {})
|
|
82
|
-
};
|
|
83
|
-
const atom = { type: 'pageLink', data };
|
|
84
|
-
const written = edytor.insertInline(block.id, from, atom).status === 'applied';
|
|
85
|
-
if (written) caret(from + 1);
|
|
86
|
-
return written;
|
|
87
|
-
}
|
|
192
|
+
onPick: (page: PageLinkItem, ctx) => placeAtom(ctx, atomOf(page, options))
|
|
88
193
|
}
|
|
89
194
|
]
|
|
90
195
|
}
|
|
@@ -104,10 +209,3 @@
|
|
|
104
209
|
></a
|
|
105
210
|
>
|
|
106
211
|
{/snippet}
|
|
107
|
-
|
|
108
|
-
<style>
|
|
109
|
-
/* One unit, on one line; its look is a theme's. */
|
|
110
|
-
.edytor-page-link {
|
|
111
|
-
white-space: nowrap;
|
|
112
|
-
}
|
|
113
|
-
</style>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import './pageLink.css';
|
|
1
2
|
import type { Snippet } from 'svelte';
|
|
2
3
|
import type { Plugin, TriggerContext } from '../../plugins.js';
|
|
3
4
|
import type { TriggerMenuController } from '../triggers/TriggerController.svelte.js';
|
|
@@ -24,6 +25,16 @@ export type PageLinkPluginOptions = {
|
|
|
24
25
|
search: (query: string, ctx: TriggerContext) => readonly PageLinkItem[] | Promise<readonly PageLinkItem[]>;
|
|
25
26
|
/** A page's URL when the search answers none (`/pages/<id>`, say). */
|
|
26
27
|
href?: (page: PageLinkItem) => string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* The page a pasted text names (your app's URL for it, `page:roadmap`…),
|
|
30
|
+
* at once or as a promise; `null` when it names none. Asked for a plain
|
|
31
|
+
* text paste at a caret that is one item (trimmed, one line): a page
|
|
32
|
+
* turns the pasted text into a `pageLink` atom, an undo step of its own
|
|
33
|
+
* after the paste, so undo gives the text back. A promise lets the paste
|
|
34
|
+
* land as it would without this option and swaps it when it answers, if
|
|
35
|
+
* the text is still there.
|
|
36
|
+
*/
|
|
37
|
+
fromPaste?: (text: string) => PageLinkItem | null | undefined | Promise<PageLinkItem | null | undefined>;
|
|
27
38
|
/** The text that opens the menu (default `[[`). */
|
|
28
39
|
char?: string;
|
|
29
40
|
/**
|
|
@@ -38,7 +49,8 @@ export type PageLinkPluginOptions = {
|
|
|
38
49
|
* Links to your app's pages, as Notion's `[[`: it opens a menu of the pages
|
|
39
50
|
* your app's `search(query)` answers; picking one replaces `[[query` with
|
|
40
51
|
* a `pageLink` atom (`{ id, title, href, icon }`), an `<a>` to the page,
|
|
41
|
-
* and puts the caret after it, in one undo step.
|
|
52
|
+
* and puts the caret after it, in one undo step. With `fromPaste`, a
|
|
53
|
+
* pasted text your app recognizes becomes a page link too.
|
|
42
54
|
*/
|
|
43
55
|
export declare const createPageLinkPlugin: (options: PageLinkPluginOptions) => Plugin;
|
|
44
56
|
declare const PageLinkPlugin: import("svelte").Component<Record<string, never>, {}, "">;
|