@blocknote/core 0.30.1 → 0.31.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/dist/blocknote.cjs +9 -9
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +2754 -2230
- package/dist/blocknote.js.map +1 -1
- package/dist/{en-D4taoCs4.cjs → en-BXVKCwYt.cjs} +2 -2
- package/dist/en-BXVKCwYt.cjs.map +1 -0
- package/dist/{en-B7ycW7c8.js → en-qGo6sk9V.js} +2 -3
- package/dist/en-qGo6sk9V.js.map +1 -0
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +20 -39
- package/dist/locales.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +4 -5
- package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +2 -3
- package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +1 -1
- package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +2816 -0
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.test.ts +158 -0
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +87 -17
- package/src/api/blockManipulation/selections/selection.ts +48 -1
- package/src/api/blockManipulation/selections/{textCursorPosition/textCursorPosition.ts → textCursorPosition.ts} +7 -7
- package/src/api/getBlockInfoFromPos.ts +1 -1
- package/src/api/nodeConversions/blockToNode.ts +5 -2
- package/src/api/nodeConversions/nodeToBlock.ts +203 -8
- package/src/api/pmUtil.ts +3 -3
- package/src/blocks/CodeBlockContent/CodeBlockContent.ts +6 -6
- package/src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts +1 -1
- package/src/blocks/TableBlockContent/TableBlockContent.ts +32 -2
- package/src/editor/Block.css +27 -1
- package/src/editor/BlockNoteEditor.test.ts +7 -0
- package/src/editor/BlockNoteEditor.ts +88 -37
- package/src/editor/BlockNoteExtension.ts +26 -0
- package/src/editor/BlockNoteExtensions.ts +28 -12
- package/src/editor/BlockNoteTipTapEditor.ts +23 -2
- package/src/extensions/Collaboration/CursorPlugin.ts +13 -7
- package/src/extensions/Collaboration/ForkYDocPlugin.test.ts +166 -0
- package/src/extensions/Collaboration/ForkYDocPlugin.ts +174 -0
- package/src/extensions/Collaboration/SyncPlugin.ts +7 -4
- package/src/extensions/Collaboration/UndoPlugin.ts +7 -4
- package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor-forked.json +30 -0
- package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor.json +30 -0
- package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-forked.html +1 -0
- package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap.html +1 -0
- package/src/extensions/Comments/CommentsPlugin.ts +75 -70
- package/src/extensions/FilePanel/FilePanelPlugin.ts +50 -49
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +56 -26
- package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +22 -21
- package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts +45 -42
- package/src/extensions/Placeholder/PlaceholderPlugin.ts +111 -108
- package/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts +179 -170
- package/src/extensions/ShowSelection/ShowSelectionPlugin.ts +22 -19
- package/src/extensions/SideMenu/SideMenuPlugin.ts +19 -18
- package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +168 -168
- package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +4 -4
- package/src/extensions/Suggestions/SuggestionMarks.ts +175 -0
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +153 -150
- package/src/i18n/locales/ar.ts +0 -1
- package/src/i18n/locales/de.ts +0 -1
- package/src/i18n/locales/en.ts +0 -1
- package/src/i18n/locales/es.ts +0 -1
- package/src/i18n/locales/fr.ts +0 -1
- package/src/i18n/locales/hr.ts +0 -1
- package/src/i18n/locales/is.ts +0 -1
- package/src/i18n/locales/it.ts +0 -1
- package/src/i18n/locales/ja.ts +0 -1
- package/src/i18n/locales/ko.ts +0 -1
- package/src/i18n/locales/nl.ts +0 -1
- package/src/i18n/locales/no.ts +0 -1
- package/src/i18n/locales/pl.ts +0 -1
- package/src/i18n/locales/pt.ts +0 -1
- package/src/i18n/locales/ru.ts +0 -1
- package/src/i18n/locales/sk.ts +0 -1
- package/src/i18n/locales/uk.ts +0 -1
- package/src/i18n/locales/vi.ts +0 -1
- package/src/i18n/locales/zh-tw.ts +0 -1
- package/src/i18n/locales/zh.ts +0 -1
- package/src/index.ts +18 -8
- package/src/pm-nodes/BlockContainer.ts +1 -1
- package/src/pm-nodes/BlockGroup.ts +1 -1
- package/src/pm-nodes/Doc.ts +1 -0
- package/types/src/api/blockManipulation/commands/insertBlocks/insertBlocks.d.ts +1 -1
- package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.d.ts +4 -0
- package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.test.d.ts +1 -0
- package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.d.ts +3 -1
- package/types/src/api/blockManipulation/selections/selection.d.ts +10 -0
- package/types/src/api/blockManipulation/selections/textCursorPosition.d.ts +5 -0
- package/types/src/api/blockManipulation/transactions.test.d.ts +0 -0
- package/types/src/api/clipboard/clipboardExternal.test.d.ts +1 -0
- package/types/src/api/clipboard/clipboardInternal.test.d.ts +1 -0
- package/types/src/api/clipboard/testUtil.d.ts +541 -0
- package/types/src/api/exporters/html/htmlConversion.test.d.ts +1 -0
- package/types/src/api/exporters/markdown/markdownExporter.test.d.ts +1 -0
- package/types/src/api/nodeConversions/nodeConversions.test.d.ts +1 -0
- package/types/src/api/nodeConversions/nodeToBlock.d.ts +39 -2
- package/types/src/api/parsers/html/parseHTML.test.d.ts +1 -0
- package/types/src/api/parsers/markdown/parseMarkdown.test.d.ts +1 -0
- package/types/src/api/pmUtil.d.ts +3 -3
- package/types/src/api/testUtil/cases/customBlocks.d.ts +670 -0
- package/types/src/api/testUtil/cases/customInlineContent.d.ts +558 -0
- package/types/src/api/testUtil/cases/customStyles.d.ts +552 -0
- package/types/src/api/testUtil/cases/defaultSchema.d.ts +4 -0
- package/types/src/api/testUtil/index.d.ts +14 -0
- package/types/src/api/testUtil/partialBlockTestUtil.d.ts +9 -0
- package/types/src/api/testUtil/paste.d.ts +2 -0
- package/types/src/blocks/CodeBlockContent/defaultSupportedLanguages.d.ts +6 -0
- package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +9 -1
- package/types/src/editor/BlockNoteEditor.d.ts +55 -9
- package/types/src/editor/BlockNoteExtension.d.ts +9 -0
- package/types/src/editor/BlockNoteExtensions.d.ts +2 -2
- package/types/src/editor/BlockNoteTipTapEditor.d.ts +2 -2
- package/types/src/extensions/Collaboration/CursorPlugin.d.ts +3 -3
- package/types/src/extensions/Collaboration/ForkYDocPlugin.d.ts +41 -0
- package/types/src/extensions/Collaboration/ForkYDocPlugin.test.d.ts +1 -0
- package/types/src/extensions/Collaboration/SyncPlugin.d.ts +3 -3
- package/types/src/extensions/Collaboration/UndoPlugin.d.ts +3 -3
- package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +17 -0
- package/types/src/extensions/Comments/CommentsPlugin.d.ts +2 -4
- package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +3 -4
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +5 -5
- package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +3 -4
- package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.d.ts +2 -3
- package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +2 -3
- package/types/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.d.ts +2 -3
- package/types/src/extensions/ShowSelection/ShowSelectionPlugin.d.ts +2 -3
- package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +3 -4
- package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +2 -4
- package/types/src/extensions/Suggestions/SuggestionMarks.d.ts +4 -0
- package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +5 -6
- package/types/src/i18n/locales/en.d.ts +0 -1
- package/types/src/i18n/locales/sk.d.ts +0 -1
- package/types/src/index.d.ts +15 -8
- package/dist/en-B7ycW7c8.js.map +0 -1
- package/dist/en-D4taoCs4.cjs.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/src/api/blockManipulation/selections/__snapshots__/selection.test.ts.snap +0 -844
- package/src/api/blockManipulation/selections/selection.test.ts +0 -72
- package/src/api/blockManipulation/selections/textCursorPosition/__snapshots__/textCursorPosition.test.ts.snap +0 -316
- package/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.ts +0 -74
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2
2
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
3
3
|
import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
|
|
4
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
4
5
|
|
|
5
6
|
const PLUGIN_KEY = new PluginKey(`blocknote-show-selection`);
|
|
6
7
|
|
|
@@ -9,29 +10,31 @@ const PLUGIN_KEY = new PluginKey(`blocknote-show-selection`);
|
|
|
9
10
|
* This can be used to highlight the current selection in the UI even when the
|
|
10
11
|
* text editor is not focused.
|
|
11
12
|
*/
|
|
12
|
-
export class ShowSelectionPlugin {
|
|
13
|
-
public readonly plugin: Plugin;
|
|
13
|
+
export class ShowSelectionPlugin extends BlockNoteExtension {
|
|
14
14
|
private enabled = false;
|
|
15
15
|
|
|
16
16
|
public constructor(private readonly editor: BlockNoteEditor<any, any, any>) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
super();
|
|
18
|
+
this.addProsemirrorPlugin(
|
|
19
|
+
new Plugin({
|
|
20
|
+
key: PLUGIN_KEY,
|
|
21
|
+
props: {
|
|
22
|
+
decorations: (state) => {
|
|
23
|
+
const { doc, selection } = state;
|
|
24
|
+
|
|
25
|
+
if (!this.enabled) {
|
|
26
|
+
return DecorationSet.empty;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const dec = Decoration.inline(selection.from, selection.to, {
|
|
30
|
+
"data-show-selection": "true",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return DecorationSet.create(doc, [dec]);
|
|
34
|
+
},
|
|
32
35
|
},
|
|
33
|
-
},
|
|
34
|
-
|
|
36
|
+
}),
|
|
37
|
+
);
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
public setEnabled(enabled: boolean) {
|
|
@@ -3,20 +3,20 @@ import {
|
|
|
3
3
|
EditorState,
|
|
4
4
|
Plugin,
|
|
5
5
|
PluginKey,
|
|
6
|
-
TextSelection,
|
|
7
6
|
PluginView,
|
|
7
|
+
TextSelection,
|
|
8
8
|
} from "@tiptap/pm/state";
|
|
9
9
|
import { EditorView } from "@tiptap/pm/view";
|
|
10
10
|
|
|
11
11
|
import { Block } from "../../blocks/defaultBlocks.js";
|
|
12
12
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
|
|
13
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
13
14
|
import { UiElementPosition } from "../../extensions-shared/UiElementPosition.js";
|
|
14
15
|
import {
|
|
15
16
|
BlockSchema,
|
|
16
17
|
InlineContentSchema,
|
|
17
18
|
StyleSchema,
|
|
18
19
|
} from "../../schema/index.js";
|
|
19
|
-
import { EventEmitter } from "../../util/EventEmitter.js";
|
|
20
20
|
import { initializeESMDependencies } from "../../util/esmDependencies.js";
|
|
21
21
|
import { getDraggableBlockFromElement } from "../getDraggableBlockFromElement.js";
|
|
22
22
|
import { dragStart, unsetDragImage } from "./dragging.js";
|
|
@@ -608,29 +608,30 @@ export class SideMenuProsemirrorPlugin<
|
|
|
608
608
|
BSchema extends BlockSchema,
|
|
609
609
|
I extends InlineContentSchema,
|
|
610
610
|
S extends StyleSchema,
|
|
611
|
-
> extends
|
|
611
|
+
> extends BlockNoteExtension {
|
|
612
612
|
public view: SideMenuView<BSchema, I, S> | undefined;
|
|
613
|
-
public readonly plugin: Plugin;
|
|
614
613
|
|
|
615
614
|
constructor(
|
|
616
615
|
private readonly editor: BlockNoteEditor<BSchema, I, S>,
|
|
617
616
|
sideMenuDetection: "viewport" | "editor",
|
|
618
617
|
) {
|
|
619
618
|
super();
|
|
620
|
-
this.
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
619
|
+
this.addProsemirrorPlugin(
|
|
620
|
+
new Plugin({
|
|
621
|
+
key: sideMenuPluginKey,
|
|
622
|
+
view: (editorView) => {
|
|
623
|
+
this.view = new SideMenuView(
|
|
624
|
+
editor,
|
|
625
|
+
sideMenuDetection,
|
|
626
|
+
editorView,
|
|
627
|
+
(state) => {
|
|
628
|
+
this.emit("update", state);
|
|
629
|
+
},
|
|
630
|
+
);
|
|
631
|
+
return this.view;
|
|
632
|
+
},
|
|
633
|
+
}),
|
|
634
|
+
);
|
|
634
635
|
}
|
|
635
636
|
|
|
636
637
|
public onUpdate(callback: (state: SideMenuState<BSchema, I, S>) => void) {
|
|
@@ -2,15 +2,15 @@ import { findParentNode } from "@tiptap/core";
|
|
|
2
2
|
import { EditorState, Plugin, PluginKey } from "prosemirror-state";
|
|
3
3
|
import { Decoration, DecorationSet, EditorView } from "prosemirror-view";
|
|
4
4
|
|
|
5
|
+
import { trackPosition } from "../../api/positionMapping.js";
|
|
5
6
|
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
|
|
7
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
6
8
|
import { UiElementPosition } from "../../extensions-shared/UiElementPosition.js";
|
|
7
9
|
import {
|
|
8
10
|
BlockSchema,
|
|
9
11
|
InlineContentSchema,
|
|
10
12
|
StyleSchema,
|
|
11
13
|
} from "../../schema/index.js";
|
|
12
|
-
import { EventEmitter } from "../../util/EventEmitter.js";
|
|
13
|
-
import { trackPosition } from "../../api/positionMapping.js";
|
|
14
14
|
|
|
15
15
|
const findBlock = findParentNode((node) => node.type.name === "blockContainer");
|
|
16
16
|
|
|
@@ -166,190 +166,190 @@ export class SuggestionMenuProseMirrorPlugin<
|
|
|
166
166
|
BSchema extends BlockSchema,
|
|
167
167
|
I extends InlineContentSchema,
|
|
168
168
|
S extends StyleSchema,
|
|
169
|
-
> extends
|
|
169
|
+
> extends BlockNoteExtension {
|
|
170
170
|
private view: SuggestionMenuView<BSchema, I, S> | undefined;
|
|
171
|
-
public readonly plugin: Plugin;
|
|
172
|
-
|
|
173
171
|
private triggerCharacters: string[] = [];
|
|
174
172
|
|
|
175
173
|
constructor(editor: BlockNoteEditor<BSchema, I, S>) {
|
|
176
174
|
super();
|
|
177
175
|
const triggerCharacters = this.triggerCharacters;
|
|
178
|
-
this.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
state: {
|
|
192
|
-
// Initialize the plugin's internal state.
|
|
193
|
-
init(): SuggestionPluginState {
|
|
194
|
-
return undefined;
|
|
176
|
+
this.addProsemirrorPlugin(
|
|
177
|
+
new Plugin({
|
|
178
|
+
key: suggestionMenuPluginKey,
|
|
179
|
+
|
|
180
|
+
view: () => {
|
|
181
|
+
this.view = new SuggestionMenuView<BSchema, I, S>(
|
|
182
|
+
editor,
|
|
183
|
+
(triggerCharacter, state) => {
|
|
184
|
+
this.emit(`update ${triggerCharacter}`, state);
|
|
185
|
+
},
|
|
186
|
+
);
|
|
187
|
+
return this.view;
|
|
195
188
|
},
|
|
196
189
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
prev,
|
|
201
|
-
_oldState,
|
|
202
|
-
newState,
|
|
203
|
-
): SuggestionPluginState => {
|
|
204
|
-
// TODO: More clearly define which transactions should be ignored.
|
|
205
|
-
if (transaction.getMeta("orderedListIndexing") !== undefined) {
|
|
206
|
-
return prev;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Ignore transactions in code blocks.
|
|
210
|
-
if (transaction.selection.$from.parent.type.spec.code) {
|
|
211
|
-
return prev;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Either contains the trigger character if the menu should be shown,
|
|
215
|
-
// or null if it should be hidden.
|
|
216
|
-
const suggestionPluginTransactionMeta: {
|
|
217
|
-
triggerCharacter: string;
|
|
218
|
-
deleteTriggerCharacter?: boolean;
|
|
219
|
-
ignoreQueryLength?: boolean;
|
|
220
|
-
} | null = transaction.getMeta(suggestionMenuPluginKey);
|
|
221
|
-
|
|
222
|
-
if (
|
|
223
|
-
typeof suggestionPluginTransactionMeta === "object" &&
|
|
224
|
-
suggestionPluginTransactionMeta !== null
|
|
225
|
-
) {
|
|
226
|
-
if (prev) {
|
|
227
|
-
// Close the previous menu if it exists
|
|
228
|
-
this.closeMenu();
|
|
229
|
-
}
|
|
230
|
-
const trackedPosition = trackPosition(
|
|
231
|
-
editor,
|
|
232
|
-
newState.selection.from -
|
|
233
|
-
// Need to account for the trigger char that was inserted, so we offset the position by the length of the trigger character.
|
|
234
|
-
suggestionPluginTransactionMeta.triggerCharacter.length,
|
|
235
|
-
);
|
|
236
|
-
return {
|
|
237
|
-
triggerCharacter:
|
|
238
|
-
suggestionPluginTransactionMeta.triggerCharacter,
|
|
239
|
-
deleteTriggerCharacter:
|
|
240
|
-
suggestionPluginTransactionMeta.deleteTriggerCharacter !==
|
|
241
|
-
false,
|
|
242
|
-
// When reading the queryStartPos, we offset the result by the length of the trigger character, to make it easy on the caller
|
|
243
|
-
queryStartPos: () =>
|
|
244
|
-
trackedPosition() +
|
|
245
|
-
suggestionPluginTransactionMeta.triggerCharacter.length,
|
|
246
|
-
query: "",
|
|
247
|
-
decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,
|
|
248
|
-
ignoreQueryLength:
|
|
249
|
-
suggestionPluginTransactionMeta?.ignoreQueryLength,
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Checks if the menu is hidden, in which case it doesn't need to be hidden or updated.
|
|
254
|
-
if (prev === undefined) {
|
|
255
|
-
return prev;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Checks if the menu should be hidden.
|
|
259
|
-
if (
|
|
260
|
-
// Highlighting text should hide the menu.
|
|
261
|
-
newState.selection.from !== newState.selection.to ||
|
|
262
|
-
// Transactions with plugin metadata should hide the menu.
|
|
263
|
-
suggestionPluginTransactionMeta === null ||
|
|
264
|
-
// Certain mouse events should hide the menu.
|
|
265
|
-
// TODO: Change to global mousedown listener.
|
|
266
|
-
transaction.getMeta("focus") ||
|
|
267
|
-
transaction.getMeta("blur") ||
|
|
268
|
-
transaction.getMeta("pointer") ||
|
|
269
|
-
// Moving the caret before the character which triggered the menu should hide it.
|
|
270
|
-
(prev.triggerCharacter !== undefined &&
|
|
271
|
-
newState.selection.from < prev.queryStartPos()) ||
|
|
272
|
-
// Moving the caret to a new block should hide the menu.
|
|
273
|
-
!newState.selection.$from.sameParent(
|
|
274
|
-
newState.doc.resolve(prev.queryStartPos()),
|
|
275
|
-
)
|
|
276
|
-
) {
|
|
190
|
+
state: {
|
|
191
|
+
// Initialize the plugin's internal state.
|
|
192
|
+
init(): SuggestionPluginState {
|
|
277
193
|
return undefined;
|
|
278
|
-
}
|
|
194
|
+
},
|
|
279
195
|
|
|
280
|
-
|
|
196
|
+
// Apply changes to the plugin state from an editor transaction.
|
|
197
|
+
apply: (
|
|
198
|
+
transaction,
|
|
199
|
+
prev,
|
|
200
|
+
_oldState,
|
|
201
|
+
newState,
|
|
202
|
+
): SuggestionPluginState => {
|
|
203
|
+
// TODO: More clearly define which transactions should be ignored.
|
|
204
|
+
if (transaction.getMeta("orderedListIndexing") !== undefined) {
|
|
205
|
+
return prev;
|
|
206
|
+
}
|
|
281
207
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
);
|
|
208
|
+
// Ignore transactions in code blocks.
|
|
209
|
+
if (transaction.selection.$from.parent.type.spec.code) {
|
|
210
|
+
return prev;
|
|
211
|
+
}
|
|
287
212
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
213
|
+
// Either contains the trigger character if the menu should be shown,
|
|
214
|
+
// or null if it should be hidden.
|
|
215
|
+
const suggestionPluginTransactionMeta: {
|
|
216
|
+
triggerCharacter: string;
|
|
217
|
+
deleteTriggerCharacter?: boolean;
|
|
218
|
+
ignoreQueryLength?: boolean;
|
|
219
|
+
} | null = transaction.getMeta(suggestionMenuPluginKey);
|
|
220
|
+
|
|
221
|
+
if (
|
|
222
|
+
typeof suggestionPluginTransactionMeta === "object" &&
|
|
223
|
+
suggestionPluginTransactionMeta !== null
|
|
224
|
+
) {
|
|
225
|
+
if (prev) {
|
|
226
|
+
// Close the previous menu if it exists
|
|
227
|
+
this.closeMenu();
|
|
228
|
+
}
|
|
229
|
+
const trackedPosition = trackPosition(
|
|
230
|
+
editor,
|
|
231
|
+
newState.selection.from -
|
|
232
|
+
// Need to account for the trigger char that was inserted, so we offset the position by the length of the trigger character.
|
|
233
|
+
suggestionPluginTransactionMeta.triggerCharacter.length,
|
|
234
|
+
);
|
|
235
|
+
return {
|
|
236
|
+
triggerCharacter:
|
|
237
|
+
suggestionPluginTransactionMeta.triggerCharacter,
|
|
238
|
+
deleteTriggerCharacter:
|
|
239
|
+
suggestionPluginTransactionMeta.deleteTriggerCharacter !==
|
|
240
|
+
false,
|
|
241
|
+
// When reading the queryStartPos, we offset the result by the length of the trigger character, to make it easy on the caller
|
|
242
|
+
queryStartPos: () =>
|
|
243
|
+
trackedPosition() +
|
|
244
|
+
suggestionPluginTransactionMeta.triggerCharacter.length,
|
|
245
|
+
query: "",
|
|
246
|
+
decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,
|
|
247
|
+
ignoreQueryLength:
|
|
248
|
+
suggestionPluginTransactionMeta?.ignoreQueryLength,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Checks if the menu is hidden, in which case it doesn't need to be hidden or updated.
|
|
253
|
+
if (prev === undefined) {
|
|
254
|
+
return prev;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Checks if the menu should be hidden.
|
|
258
|
+
if (
|
|
259
|
+
// Highlighting text should hide the menu.
|
|
260
|
+
newState.selection.from !== newState.selection.to ||
|
|
261
|
+
// Transactions with plugin metadata should hide the menu.
|
|
262
|
+
suggestionPluginTransactionMeta === null ||
|
|
263
|
+
// Certain mouse events should hide the menu.
|
|
264
|
+
// TODO: Change to global mousedown listener.
|
|
265
|
+
transaction.getMeta("focus") ||
|
|
266
|
+
transaction.getMeta("blur") ||
|
|
267
|
+
transaction.getMeta("pointer") ||
|
|
268
|
+
// Moving the caret before the character which triggered the menu should hide it.
|
|
269
|
+
(prev.triggerCharacter !== undefined &&
|
|
270
|
+
newState.selection.from < prev.queryStartPos()) ||
|
|
271
|
+
// Moving the caret to a new block should hide the menu.
|
|
272
|
+
!newState.selection.$from.sameParent(
|
|
273
|
+
newState.doc.resolve(prev.queryStartPos()),
|
|
274
|
+
)
|
|
275
|
+
) {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const next = { ...prev };
|
|
280
|
+
|
|
281
|
+
// Updates the current query.
|
|
282
|
+
next.query = newState.doc.textBetween(
|
|
283
|
+
prev.queryStartPos(),
|
|
284
|
+
newState.selection.from,
|
|
302
285
|
);
|
|
303
286
|
|
|
304
|
-
return
|
|
305
|
-
}
|
|
306
|
-
return false;
|
|
287
|
+
return next;
|
|
288
|
+
},
|
|
307
289
|
},
|
|
308
290
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
]);
|
|
291
|
+
props: {
|
|
292
|
+
handleTextInput(view, _from, _to, text) {
|
|
293
|
+
if (triggerCharacters.includes(text)) {
|
|
294
|
+
view.dispatch(view.state.tr.insertText(text));
|
|
295
|
+
view.dispatch(
|
|
296
|
+
view.state.tr
|
|
297
|
+
.setMeta(suggestionMenuPluginKey, {
|
|
298
|
+
triggerCharacter: text,
|
|
299
|
+
})
|
|
300
|
+
.scrollIntoView(),
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
return false;
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
// Setup decorator on the currently active suggestion.
|
|
309
|
+
decorations(state) {
|
|
310
|
+
const suggestionPluginState: SuggestionPluginState = (
|
|
311
|
+
this as Plugin
|
|
312
|
+
).getState(state);
|
|
313
|
+
|
|
314
|
+
if (suggestionPluginState === undefined) {
|
|
315
|
+
return null;
|
|
335
316
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
317
|
+
|
|
318
|
+
// If the menu was opened programmatically by another extension, it may not use a trigger character. In this
|
|
319
|
+
// case, the decoration is set on the whole block instead, as the decoration range would otherwise be empty.
|
|
320
|
+
if (!suggestionPluginState.deleteTriggerCharacter) {
|
|
321
|
+
const blockNode = findBlock(state.selection);
|
|
322
|
+
if (blockNode) {
|
|
323
|
+
return DecorationSet.create(state.doc, [
|
|
324
|
+
Decoration.node(
|
|
325
|
+
blockNode.pos,
|
|
326
|
+
blockNode.pos + blockNode.node.nodeSize,
|
|
327
|
+
{
|
|
328
|
+
nodeName: "span",
|
|
329
|
+
class: "bn-suggestion-decorator",
|
|
330
|
+
"data-decoration-id": suggestionPluginState.decorationId,
|
|
331
|
+
},
|
|
332
|
+
),
|
|
333
|
+
]);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
// Creates an inline decoration around the trigger character.
|
|
337
|
+
return DecorationSet.create(state.doc, [
|
|
338
|
+
Decoration.inline(
|
|
339
|
+
suggestionPluginState.queryStartPos() -
|
|
340
|
+
suggestionPluginState.triggerCharacter!.length,
|
|
341
|
+
suggestionPluginState.queryStartPos(),
|
|
342
|
+
{
|
|
343
|
+
nodeName: "span",
|
|
344
|
+
class: "bn-suggestion-decorator",
|
|
345
|
+
"data-decoration-id": suggestionPluginState.decorationId,
|
|
346
|
+
},
|
|
347
|
+
),
|
|
348
|
+
]);
|
|
349
|
+
},
|
|
350
350
|
},
|
|
351
|
-
},
|
|
352
|
-
|
|
351
|
+
}),
|
|
352
|
+
);
|
|
353
353
|
}
|
|
354
354
|
|
|
355
355
|
public onUpdate(
|
|
@@ -235,7 +235,7 @@ export function getDefaultSlashMenuItems<
|
|
|
235
235
|
|
|
236
236
|
// Immediately open the file toolbar
|
|
237
237
|
editor.transact((tr) =>
|
|
238
|
-
tr.setMeta(editor.filePanel!.
|
|
238
|
+
tr.setMeta(editor.filePanel!.plugins[0], {
|
|
239
239
|
block: insertedBlock,
|
|
240
240
|
}),
|
|
241
241
|
);
|
|
@@ -254,7 +254,7 @@ export function getDefaultSlashMenuItems<
|
|
|
254
254
|
|
|
255
255
|
// Immediately open the file toolbar
|
|
256
256
|
editor.transact((tr) =>
|
|
257
|
-
tr.setMeta(editor.filePanel!.
|
|
257
|
+
tr.setMeta(editor.filePanel!.plugins[0], {
|
|
258
258
|
block: insertedBlock,
|
|
259
259
|
}),
|
|
260
260
|
);
|
|
@@ -273,7 +273,7 @@ export function getDefaultSlashMenuItems<
|
|
|
273
273
|
|
|
274
274
|
// Immediately open the file toolbar
|
|
275
275
|
editor.transact((tr) =>
|
|
276
|
-
tr.setMeta(editor.filePanel!.
|
|
276
|
+
tr.setMeta(editor.filePanel!.plugins[0], {
|
|
277
277
|
block: insertedBlock,
|
|
278
278
|
}),
|
|
279
279
|
);
|
|
@@ -292,7 +292,7 @@ export function getDefaultSlashMenuItems<
|
|
|
292
292
|
|
|
293
293
|
// Immediately open the file toolbar
|
|
294
294
|
editor.transact((tr) =>
|
|
295
|
-
tr.setMeta(editor.filePanel!.
|
|
295
|
+
tr.setMeta(editor.filePanel!.plugins[0], {
|
|
296
296
|
block: insertedBlock,
|
|
297
297
|
}),
|
|
298
298
|
);
|