@blocknote/core 0.30.0 → 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 +2771 -2245
- package/dist/blocknote.js.map +1 -1
- package/dist/comments.cjs.map +1 -1
- package/dist/comments.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 +8 -7
- package/src/api/README.md +1 -1
- package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.test.ts +19 -14
- package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +7 -8
- package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts +3 -3
- package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts +12 -12
- package/src/api/blockManipulation/commands/moveBlocks/moveBlocks.test.ts +14 -14
- package/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts +16 -16
- package/src/api/blockManipulation/commands/nestBlock/nestBlock.ts +8 -8
- package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.test.ts +12 -12
- package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +8 -8
- package/src/api/blockManipulation/commands/splitBlock/splitBlock.test.ts +10 -10
- package/src/api/blockManipulation/commands/splitBlock/splitBlock.ts +2 -2
- package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +2816 -0
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.test.ts +200 -42
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +104 -34
- package/src/api/blockManipulation/getBlock/getBlock.ts +9 -9
- package/src/api/blockManipulation/insertContentAt.ts +1 -1
- package/src/api/blockManipulation/selections/selection.ts +59 -12
- package/src/api/blockManipulation/selections/{textCursorPosition/textCursorPosition.ts → textCursorPosition.ts} +13 -13
- package/src/api/blockManipulation/tables/tables.test.ts +106 -106
- package/src/api/blockManipulation/tables/tables.ts +35 -35
- package/src/api/clipboard/fromClipboard/fileDropExtension.ts +2 -2
- package/src/api/clipboard/fromClipboard/handleFileInsertion.ts +9 -9
- package/src/api/clipboard/fromClipboard/handleVSCodePaste.ts +3 -3
- package/src/api/clipboard/fromClipboard/pasteExtension.ts +3 -3
- package/src/api/clipboard/toClipboard/copyExtension.ts +22 -22
- package/src/api/exporters/html/externalHTMLExporter.ts +6 -6
- package/src/api/exporters/html/internalHTMLSerializer.ts +3 -3
- package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +16 -16
- package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +14 -14
- package/src/api/exporters/markdown/markdownExporter.ts +3 -3
- package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +3 -3
- package/src/api/getBlockInfoFromPos.ts +6 -6
- package/src/api/nodeConversions/blockToNode.ts +31 -28
- package/src/api/nodeConversions/fragmentToBlocks.ts +1 -1
- package/src/api/nodeConversions/nodeToBlock.ts +240 -41
- package/src/api/nodeUtil.test.ts +16 -16
- package/src/api/nodeUtil.ts +10 -10
- package/src/api/parsers/html/parseHTML.ts +1 -1
- package/src/api/parsers/html/util/nestedLists.ts +2 -2
- package/src/api/parsers/markdown/parseMarkdown.ts +1 -1
- package/src/api/pmUtil.ts +7 -7
- package/src/api/positionMapping.test.ts +3 -3
- package/src/api/positionMapping.ts +5 -5
- package/src/blocks/AudioBlockContent/AudioBlockContent.ts +4 -4
- package/src/blocks/CodeBlockContent/CodeBlockContent.ts +18 -18
- package/src/blocks/FileBlockContent/FileBlockContent.ts +2 -2
- package/src/blocks/FileBlockContent/helpers/parse/parseFigureElement.ts +2 -2
- package/src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts +6 -6
- package/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.ts +2 -2
- package/src/blocks/FileBlockContent/helpers/render/createFileNameWithIcon.ts +1 -1
- package/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts +7 -7
- package/src/blocks/FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.ts +1 -1
- package/src/blocks/FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.ts +1 -1
- package/src/blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +2 -2
- package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +6 -6
- package/src/blocks/ImageBlockContent/ImageBlockContent.ts +4 -4
- package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +4 -4
- package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +10 -10
- package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +1 -1
- package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +1 -1
- package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +4 -4
- package/src/blocks/ListItemBlockContent/getListItemContent.ts +5 -5
- package/src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts +1 -1
- package/src/blocks/PageBreakBlockContent/getPageBreakSlashMenuItems.ts +3 -3
- package/src/blocks/PageBreakBlockContent/schema.ts +2 -2
- package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +3 -3
- package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +4 -4
- package/src/blocks/README.md +1 -1
- package/src/blocks/TableBlockContent/TableBlockContent.ts +37 -7
- package/src/blocks/TableBlockContent/TableExtension.ts +3 -3
- package/src/blocks/VideoBlockContent/VideoBlockContent.ts +4 -4
- package/src/blocks/defaultBlockHelpers.ts +8 -8
- package/src/blocks/defaultBlockTypeGuards.ts +16 -16
- package/src/blocks/defaultBlocks.ts +3 -3
- package/src/comments/threadstore/DefaultThreadStoreAuth.ts +3 -3
- package/src/comments/threadstore/ThreadStore.ts +1 -1
- package/src/comments/threadstore/TipTapThreadStore.ts +10 -10
- package/src/comments/threadstore/yjs/RESTYjsThreadStore.ts +4 -4
- package/src/comments/threadstore/yjs/YjsThreadStore.test.ts +2 -2
- package/src/comments/threadstore/yjs/YjsThreadStore.ts +14 -14
- package/src/comments/threadstore/yjs/YjsThreadStoreBase.ts +1 -1
- package/src/comments/threadstore/yjs/yjsHelpers.ts +6 -6
- package/src/editor/Block.css +35 -1
- package/src/editor/BlockNoteEditor.test.ts +10 -3
- package/src/editor/BlockNoteEditor.ts +95 -38
- package/src/editor/BlockNoteExtension.ts +26 -0
- package/src/editor/BlockNoteExtensions.ts +38 -22
- package/src/editor/BlockNoteSchema.ts +4 -4
- package/src/editor/BlockNoteTipTapEditor.ts +33 -12
- package/src/editor/README.md +1 -1
- package/src/editor/cursorPositionTypes.ts +1 -1
- package/src/editor/editor.css +15 -3
- package/src/editor/selectionTypes.ts +1 -1
- package/src/editor/transformPasted.ts +2 -2
- package/src/exporter/Exporter.ts +5 -5
- package/src/exporter/mapping.ts +7 -7
- package/src/extensions/BackgroundColor/BackgroundColorMark.ts +1 -1
- package/src/extensions/Collaboration/CursorPlugin.ts +15 -9
- 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 +80 -75
- package/src/extensions/Comments/userstore/UserStore.ts +2 -2
- package/src/extensions/FilePanel/FilePanelPlugin.ts +56 -55
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +60 -30
- package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +26 -26
- package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +33 -32
- package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts +45 -42
- package/src/extensions/Placeholder/PlaceholderPlugin.ts +113 -110
- package/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts +179 -170
- package/src/extensions/README.md +1 -1
- package/src/extensions/ShowSelection/ShowSelectionPlugin.ts +22 -19
- package/src/extensions/SideMenu/MultipleNodeSelection.ts +1 -1
- package/src/extensions/SideMenu/SideMenuPlugin.ts +49 -48
- package/src/extensions/SideMenu/dragging.ts +8 -8
- package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +176 -176
- package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +2 -2
- package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +16 -16
- package/src/extensions/Suggestions/SuggestionMarks.ts +175 -0
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +199 -195
- package/src/extensions/TrailingNode/TrailingNodeExtension.ts +1 -1
- package/src/extensions/UniqueID/UniqueID.ts +6 -6
- package/src/extensions/getDraggableBlockFromElement.ts +1 -1
- package/src/fonts/inter.css +18 -9
- 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/locales.ts +1 -1
- package/src/pm-nodes/BlockContainer.ts +1 -1
- package/src/pm-nodes/BlockGroup.ts +2 -2
- package/src/pm-nodes/Doc.ts +5 -4
- package/src/schema/README.md +1 -1
- package/src/schema/blocks/createSpec.ts +14 -14
- package/src/schema/blocks/internal.ts +17 -17
- package/src/schema/blocks/types.ts +25 -25
- package/src/schema/inlineContent/createSpec.ts +16 -20
- package/src/schema/inlineContent/internal.ts +9 -9
- package/src/schema/inlineContent/types.ts +26 -26
- package/src/schema/propTypes.ts +8 -8
- package/src/schema/styles/createSpec.ts +2 -2
- package/src/schema/styles/internal.ts +7 -7
- package/src/schema/styles/types.ts +2 -2
- package/src/util/EventEmitter.ts +4 -4
- package/src/util/README.md +1 -1
- package/src/util/combineByGroup.ts +1 -1
- package/src/util/table.ts +33 -30
- 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 +58 -10
- 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
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { expect, it } from "vitest";
|
|
2
|
+
import * as Y from "yjs";
|
|
3
|
+
import { Awareness } from "y-protocols/awareness";
|
|
4
|
+
import { BlockNoteEditor } from "../../index.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @vitest-environment jsdom
|
|
8
|
+
*/
|
|
9
|
+
it("can fork a document", async () => {
|
|
10
|
+
const doc = new Y.Doc();
|
|
11
|
+
const fragment = doc.getXmlFragment("doc");
|
|
12
|
+
const editor = BlockNoteEditor.create({
|
|
13
|
+
collaboration: {
|
|
14
|
+
fragment,
|
|
15
|
+
user: { name: "Hello", color: "#FFFFFF" },
|
|
16
|
+
provider: {
|
|
17
|
+
awareness: new Awareness(doc),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const div = document.createElement("div");
|
|
23
|
+
editor.mount(div);
|
|
24
|
+
|
|
25
|
+
editor.replaceBlocks(editor.document, [
|
|
26
|
+
{
|
|
27
|
+
type: "paragraph",
|
|
28
|
+
content: [{ text: "Hello", styles: {}, type: "text" }],
|
|
29
|
+
},
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
await expect(fragment.toJSON()).toMatchFileSnapshot(
|
|
33
|
+
"__snapshots__/fork-yjs-snap.html",
|
|
34
|
+
);
|
|
35
|
+
await expect(editor.document).toMatchFileSnapshot(
|
|
36
|
+
"__snapshots__/fork-yjs-snap-editor.json",
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
editor.forkYDocPlugin!.fork();
|
|
40
|
+
|
|
41
|
+
editor.replaceBlocks(editor.document, [
|
|
42
|
+
{
|
|
43
|
+
type: "paragraph",
|
|
44
|
+
content: [{ text: "Hello World", styles: {}, type: "text" }],
|
|
45
|
+
},
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
await expect(fragment.toJSON()).toMatchFileSnapshot(
|
|
49
|
+
"__snapshots__/fork-yjs-snap.html",
|
|
50
|
+
);
|
|
51
|
+
await expect(editor.document).toMatchFileSnapshot(
|
|
52
|
+
"__snapshots__/fork-yjs-snap-editor-forked.json",
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("can merge a document", async () => {
|
|
57
|
+
const doc = new Y.Doc();
|
|
58
|
+
const fragment = doc.getXmlFragment("doc");
|
|
59
|
+
const editor = BlockNoteEditor.create({
|
|
60
|
+
collaboration: {
|
|
61
|
+
fragment,
|
|
62
|
+
user: { name: "Hello", color: "#FFFFFF" },
|
|
63
|
+
provider: {
|
|
64
|
+
awareness: new Awareness(doc),
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const div = document.createElement("div");
|
|
70
|
+
editor.mount(div);
|
|
71
|
+
|
|
72
|
+
editor.replaceBlocks(editor.document, [
|
|
73
|
+
{
|
|
74
|
+
type: "paragraph",
|
|
75
|
+
content: [{ text: "Hello", styles: {}, type: "text" }],
|
|
76
|
+
},
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
await expect(fragment.toJSON()).toMatchFileSnapshot(
|
|
80
|
+
"__snapshots__/fork-yjs-snap.html",
|
|
81
|
+
);
|
|
82
|
+
await expect(editor.document).toMatchFileSnapshot(
|
|
83
|
+
"__snapshots__/fork-yjs-snap-editor.json",
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
editor.forkYDocPlugin!.fork();
|
|
87
|
+
|
|
88
|
+
editor.replaceBlocks(editor.document, [
|
|
89
|
+
{
|
|
90
|
+
type: "paragraph",
|
|
91
|
+
content: [{ text: "Hello World", styles: {}, type: "text" }],
|
|
92
|
+
},
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
await expect(fragment.toJSON()).toMatchFileSnapshot(
|
|
96
|
+
"__snapshots__/fork-yjs-snap.html",
|
|
97
|
+
);
|
|
98
|
+
await expect(editor.document).toMatchFileSnapshot(
|
|
99
|
+
"__snapshots__/fork-yjs-snap-editor-forked.json",
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
editor.forkYDocPlugin!.merge({ keepChanges: false });
|
|
103
|
+
|
|
104
|
+
await expect(fragment.toJSON()).toMatchFileSnapshot(
|
|
105
|
+
"__snapshots__/fork-yjs-snap.html",
|
|
106
|
+
);
|
|
107
|
+
await expect(editor.document).toMatchFileSnapshot(
|
|
108
|
+
"__snapshots__/fork-yjs-snap-editor.json",
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("can fork an keep the changes to the original document", async () => {
|
|
113
|
+
const doc = new Y.Doc();
|
|
114
|
+
const fragment = doc.getXmlFragment("doc");
|
|
115
|
+
const editor = BlockNoteEditor.create({
|
|
116
|
+
collaboration: {
|
|
117
|
+
fragment,
|
|
118
|
+
user: { name: "Hello", color: "#FFFFFF" },
|
|
119
|
+
provider: {
|
|
120
|
+
awareness: new Awareness(doc),
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const div = document.createElement("div");
|
|
126
|
+
editor.mount(div);
|
|
127
|
+
|
|
128
|
+
editor.replaceBlocks(editor.document, [
|
|
129
|
+
{
|
|
130
|
+
type: "paragraph",
|
|
131
|
+
content: [{ text: "Hello", styles: {}, type: "text" }],
|
|
132
|
+
},
|
|
133
|
+
]);
|
|
134
|
+
|
|
135
|
+
await expect(fragment.toJSON()).toMatchFileSnapshot(
|
|
136
|
+
"__snapshots__/fork-yjs-snap.html",
|
|
137
|
+
);
|
|
138
|
+
await expect(editor.document).toMatchFileSnapshot(
|
|
139
|
+
"__snapshots__/fork-yjs-snap-editor.json",
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
editor.forkYDocPlugin!.fork();
|
|
143
|
+
|
|
144
|
+
editor.replaceBlocks(editor.document, [
|
|
145
|
+
{
|
|
146
|
+
type: "paragraph",
|
|
147
|
+
content: [{ text: "Hello World", styles: {}, type: "text" }],
|
|
148
|
+
},
|
|
149
|
+
]);
|
|
150
|
+
|
|
151
|
+
await expect(fragment.toJSON()).toMatchFileSnapshot(
|
|
152
|
+
"__snapshots__/fork-yjs-snap.html",
|
|
153
|
+
);
|
|
154
|
+
await expect(editor.document).toMatchFileSnapshot(
|
|
155
|
+
"__snapshots__/fork-yjs-snap-editor-forked.json",
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
editor.forkYDocPlugin!.merge({ keepChanges: true });
|
|
159
|
+
|
|
160
|
+
await expect(fragment.toJSON()).toMatchFileSnapshot(
|
|
161
|
+
"__snapshots__/fork-yjs-snap-forked.html",
|
|
162
|
+
);
|
|
163
|
+
await expect(editor.document).toMatchFileSnapshot(
|
|
164
|
+
"__snapshots__/fork-yjs-snap-editor-forked.json",
|
|
165
|
+
);
|
|
166
|
+
});
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as Y from "yjs";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
yCursorPluginKey,
|
|
5
|
+
ySyncPluginKey,
|
|
6
|
+
yUndoPluginKey,
|
|
7
|
+
} from "y-prosemirror";
|
|
8
|
+
import { CursorPlugin } from "./CursorPlugin.js";
|
|
9
|
+
import { SyncPlugin } from "./SyncPlugin.js";
|
|
10
|
+
import { UndoPlugin } from "./UndoPlugin.js";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
BlockNoteEditor,
|
|
14
|
+
BlockNoteEditorOptions,
|
|
15
|
+
} from "../../editor/BlockNoteEditor.js";
|
|
16
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
17
|
+
|
|
18
|
+
export class ForkYDocPlugin extends BlockNoteExtension<{
|
|
19
|
+
forked: boolean;
|
|
20
|
+
}> {
|
|
21
|
+
public static name() {
|
|
22
|
+
return "ForkYDocPlugin";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private editor: BlockNoteEditor<any, any, any>;
|
|
26
|
+
private collaboration: BlockNoteEditorOptions<any, any, any>["collaboration"];
|
|
27
|
+
|
|
28
|
+
constructor({
|
|
29
|
+
editor,
|
|
30
|
+
collaboration,
|
|
31
|
+
}: {
|
|
32
|
+
editor: BlockNoteEditor<any, any, any>;
|
|
33
|
+
collaboration: BlockNoteEditorOptions<any, any, any>["collaboration"];
|
|
34
|
+
}) {
|
|
35
|
+
super(editor);
|
|
36
|
+
this.editor = editor;
|
|
37
|
+
this.collaboration = collaboration;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* To find a fragment in another ydoc, we need to search for it.
|
|
42
|
+
*/
|
|
43
|
+
private findTypeInOtherYdoc<T extends Y.AbstractType<any>>(
|
|
44
|
+
ytype: T,
|
|
45
|
+
otherYdoc: Y.Doc,
|
|
46
|
+
): T {
|
|
47
|
+
const ydoc = ytype.doc!;
|
|
48
|
+
if (ytype._item === null) {
|
|
49
|
+
/**
|
|
50
|
+
* If is a root type, we need to find the root key in the original ydoc
|
|
51
|
+
* and use it to get the type in the other ydoc.
|
|
52
|
+
*/
|
|
53
|
+
const rootKey = Array.from(ydoc.share.keys()).find(
|
|
54
|
+
(key) => ydoc.share.get(key) === ytype,
|
|
55
|
+
);
|
|
56
|
+
if (rootKey == null) {
|
|
57
|
+
throw new Error("type does not exist in other ydoc");
|
|
58
|
+
}
|
|
59
|
+
return otherYdoc.get(rootKey, ytype.constructor as new () => T) as T;
|
|
60
|
+
} else {
|
|
61
|
+
/**
|
|
62
|
+
* If it is a sub type, we use the item id to find the history type.
|
|
63
|
+
*/
|
|
64
|
+
const ytypeItem = ytype._item;
|
|
65
|
+
const otherStructs =
|
|
66
|
+
otherYdoc.store.clients.get(ytypeItem.id.client) ?? [];
|
|
67
|
+
const itemIndex = Y.findIndexSS(otherStructs, ytypeItem.id.clock);
|
|
68
|
+
const otherItem = otherStructs[itemIndex] as Y.Item;
|
|
69
|
+
const otherContent = otherItem.content as Y.ContentType;
|
|
70
|
+
return otherContent.type as T;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Whether the editor is editing a forked document,
|
|
76
|
+
* preserving a reference to the original document and the forked document.
|
|
77
|
+
*/
|
|
78
|
+
public get isForkedFromRemote() {
|
|
79
|
+
return this.forkedState !== undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Stores whether the editor is editing a forked document,
|
|
84
|
+
* preserving a reference to the original document and the forked document.
|
|
85
|
+
*/
|
|
86
|
+
private forkedState:
|
|
87
|
+
| {
|
|
88
|
+
originalFragment: Y.XmlFragment;
|
|
89
|
+
forkedFragment: Y.XmlFragment;
|
|
90
|
+
}
|
|
91
|
+
| undefined;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Fork the Y.js document from syncing to the remote,
|
|
95
|
+
* allowing modifications to the document without affecting the remote.
|
|
96
|
+
* These changes can later be rolled back or applied to the remote.
|
|
97
|
+
*/
|
|
98
|
+
public fork() {
|
|
99
|
+
if (this.isForkedFromRemote) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const originalFragment = this.collaboration.fragment;
|
|
104
|
+
|
|
105
|
+
if (!originalFragment) {
|
|
106
|
+
throw new Error("No fragment to fork from");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const doc = new Y.Doc();
|
|
110
|
+
// Copy the original document to a new Yjs document
|
|
111
|
+
Y.applyUpdate(doc, Y.encodeStateAsUpdate(originalFragment.doc!));
|
|
112
|
+
|
|
113
|
+
// Find the forked fragment in the new Yjs document
|
|
114
|
+
const forkedFragment = this.findTypeInOtherYdoc(originalFragment, doc);
|
|
115
|
+
|
|
116
|
+
this.forkedState = {
|
|
117
|
+
originalFragment,
|
|
118
|
+
forkedFragment,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Need to reset all the yjs plugins
|
|
122
|
+
this.editor._tiptapEditor.unregisterPlugin([
|
|
123
|
+
yCursorPluginKey,
|
|
124
|
+
yUndoPluginKey,
|
|
125
|
+
ySyncPluginKey,
|
|
126
|
+
]);
|
|
127
|
+
// Register them again, based on the new forked fragment
|
|
128
|
+
this.editor._tiptapEditor.registerPlugin(
|
|
129
|
+
new SyncPlugin(forkedFragment).plugins[0],
|
|
130
|
+
);
|
|
131
|
+
this.editor._tiptapEditor.registerPlugin(new UndoPlugin().plugins[0]);
|
|
132
|
+
// No need to register the cursor plugin again, it's a local fork
|
|
133
|
+
this.emit("forked", true);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Resume syncing the Y.js document to the remote
|
|
138
|
+
* If `keepChanges` is true, any changes that have been made to the forked document will be applied to the original document.
|
|
139
|
+
* Otherwise, the original document will be restored and the changes will be discarded.
|
|
140
|
+
*/
|
|
141
|
+
public merge({ keepChanges }: { keepChanges: boolean }) {
|
|
142
|
+
if (!this.forkedState) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
// Remove the forked fragment's plugins
|
|
146
|
+
this.editor._tiptapEditor.unregisterPlugin(ySyncPluginKey);
|
|
147
|
+
this.editor._tiptapEditor.unregisterPlugin(yUndoPluginKey);
|
|
148
|
+
|
|
149
|
+
const { originalFragment, forkedFragment } = this.forkedState;
|
|
150
|
+
if (keepChanges) {
|
|
151
|
+
// Apply any changes that have been made to the fork, onto the original doc
|
|
152
|
+
const update = Y.encodeStateAsUpdate(forkedFragment.doc!);
|
|
153
|
+
Y.applyUpdate(originalFragment.doc!, update);
|
|
154
|
+
}
|
|
155
|
+
this.editor.extensions["ySyncPlugin"] = new SyncPlugin(originalFragment);
|
|
156
|
+
this.editor.extensions["yCursorPlugin"] = new CursorPlugin(
|
|
157
|
+
this.collaboration!,
|
|
158
|
+
);
|
|
159
|
+
this.editor.extensions["yUndoPlugin"] = new UndoPlugin();
|
|
160
|
+
// Register the plugins again, based on the original fragment
|
|
161
|
+
this.editor._tiptapEditor.registerPlugin(
|
|
162
|
+
this.editor.extensions["ySyncPlugin"].plugins[0],
|
|
163
|
+
);
|
|
164
|
+
this.editor._tiptapEditor.registerPlugin(
|
|
165
|
+
this.editor.extensions["yCursorPlugin"].plugins[0],
|
|
166
|
+
);
|
|
167
|
+
this.editor._tiptapEditor.registerPlugin(
|
|
168
|
+
this.editor.extensions["yUndoPlugin"].plugins[0],
|
|
169
|
+
);
|
|
170
|
+
// Reset the forked state
|
|
171
|
+
this.forkedState = undefined;
|
|
172
|
+
this.emit("forked", false);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { Plugin } from "prosemirror-state";
|
|
2
1
|
import { ySyncPlugin } from "y-prosemirror";
|
|
3
2
|
import type * as Y from "yjs";
|
|
3
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
4
4
|
|
|
5
|
-
export class SyncPlugin {
|
|
6
|
-
public
|
|
5
|
+
export class SyncPlugin extends BlockNoteExtension {
|
|
6
|
+
public static name() {
|
|
7
|
+
return "ySyncPlugin";
|
|
8
|
+
}
|
|
7
9
|
|
|
8
10
|
constructor(fragment: Y.XmlFragment) {
|
|
9
|
-
|
|
11
|
+
super();
|
|
12
|
+
this.addProsemirrorPlugin(ySyncPlugin(fragment));
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
public get priority() {
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { Plugin } from "prosemirror-state";
|
|
2
1
|
import { yUndoPlugin } from "y-prosemirror";
|
|
2
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
3
3
|
|
|
4
|
-
export class UndoPlugin {
|
|
5
|
-
public
|
|
4
|
+
export class UndoPlugin extends BlockNoteExtension {
|
|
5
|
+
public static name() {
|
|
6
|
+
return "yUndoPlugin";
|
|
7
|
+
}
|
|
6
8
|
|
|
7
9
|
constructor() {
|
|
8
|
-
|
|
10
|
+
super();
|
|
11
|
+
this.addProsemirrorPlugin(yUndoPlugin());
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
public get priority() {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"children": [],
|
|
4
|
+
"content": [
|
|
5
|
+
{
|
|
6
|
+
"styles": {},
|
|
7
|
+
"text": "Hello World",
|
|
8
|
+
"type": "text",
|
|
9
|
+
},
|
|
10
|
+
],
|
|
11
|
+
"id": "2",
|
|
12
|
+
"props": {
|
|
13
|
+
"backgroundColor": "default",
|
|
14
|
+
"textAlignment": "left",
|
|
15
|
+
"textColor": "default",
|
|
16
|
+
},
|
|
17
|
+
"type": "paragraph",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"children": [],
|
|
21
|
+
"content": [],
|
|
22
|
+
"id": "3",
|
|
23
|
+
"props": {
|
|
24
|
+
"backgroundColor": "default",
|
|
25
|
+
"textAlignment": "left",
|
|
26
|
+
"textColor": "default",
|
|
27
|
+
},
|
|
28
|
+
"type": "paragraph",
|
|
29
|
+
},
|
|
30
|
+
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"children": [],
|
|
4
|
+
"content": [
|
|
5
|
+
{
|
|
6
|
+
"styles": {},
|
|
7
|
+
"text": "Hello",
|
|
8
|
+
"type": "text",
|
|
9
|
+
},
|
|
10
|
+
],
|
|
11
|
+
"id": "0",
|
|
12
|
+
"props": {
|
|
13
|
+
"backgroundColor": "default",
|
|
14
|
+
"textAlignment": "left",
|
|
15
|
+
"textColor": "default",
|
|
16
|
+
},
|
|
17
|
+
"type": "paragraph",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"children": [],
|
|
21
|
+
"content": [],
|
|
22
|
+
"id": "1",
|
|
23
|
+
"props": {
|
|
24
|
+
"backgroundColor": "default",
|
|
25
|
+
"textAlignment": "left",
|
|
26
|
+
"textColor": "default",
|
|
27
|
+
},
|
|
28
|
+
"type": "paragraph",
|
|
29
|
+
},
|
|
30
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<blockgroup><blockcontainer backgroundColor="default" id="2" textColor="default"><paragraph textAlignment="left">Hello World</paragraph></blockcontainer><blockcontainer backgroundColor="default" id="3" textColor="default"><paragraph textAlignment="left"></paragraph></blockcontainer></blockgroup>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<blockgroup><blockcontainer backgroundColor="default" id="0" textColor="default"><paragraph textAlignment="left">Hello</paragraph></blockcontainer><blockcontainer backgroundColor="default" id="1" textColor="default"><paragraph textAlignment="left"></paragraph></blockcontainer></blockgroup>
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
User,
|
|
10
10
|
} from "../../comments/index.js";
|
|
11
11
|
import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
|
|
12
|
-
import {
|
|
12
|
+
import { BlockNoteExtension } from "../../editor/BlockNoteExtension.js";
|
|
13
13
|
import { UserStore } from "./userstore/UserStore.js";
|
|
14
14
|
|
|
15
15
|
const PLUGIN_KEY = new PluginKey(`blocknote-comments`);
|
|
@@ -56,8 +56,7 @@ function getUpdatedThreadPositions(doc: Node, markType: string) {
|
|
|
56
56
|
return threadPositions;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
export class CommentsPlugin extends
|
|
60
|
-
public readonly plugin: Plugin;
|
|
59
|
+
export class CommentsPlugin extends BlockNoteExtension {
|
|
61
60
|
public readonly userStore: UserStore<User>;
|
|
62
61
|
|
|
63
62
|
/**
|
|
@@ -102,7 +101,8 @@ export class CommentsPlugin extends EventEmitter<any> {
|
|
|
102
101
|
const trimmedFrom = Math.max(pos, 0);
|
|
103
102
|
const trimmedTo = Math.min(
|
|
104
103
|
pos + node.nodeSize,
|
|
105
|
-
tr.doc.content.size - 1
|
|
104
|
+
tr.doc.content.size - 1,
|
|
105
|
+
tr.doc.content.size - 1,
|
|
106
106
|
);
|
|
107
107
|
tr.removeMark(trimmedFrom, trimmedTo, mark);
|
|
108
108
|
tr.addMark(
|
|
@@ -111,7 +111,7 @@ export class CommentsPlugin extends EventEmitter<any> {
|
|
|
111
111
|
markType.create({
|
|
112
112
|
...mark.attrs,
|
|
113
113
|
orphan: isOrphan,
|
|
114
|
-
})
|
|
114
|
+
}),
|
|
115
115
|
);
|
|
116
116
|
|
|
117
117
|
if (isOrphan && this.selectedThreadId === markThreadId) {
|
|
@@ -129,7 +129,7 @@ export class CommentsPlugin extends EventEmitter<any> {
|
|
|
129
129
|
constructor(
|
|
130
130
|
private readonly editor: BlockNoteEditor<any, any, any>,
|
|
131
131
|
public readonly threadStore: ThreadStore,
|
|
132
|
-
private readonly markType: string
|
|
132
|
+
private readonly markType: string,
|
|
133
133
|
) {
|
|
134
134
|
super();
|
|
135
135
|
|
|
@@ -156,86 +156,91 @@ export class CommentsPlugin extends EventEmitter<any> {
|
|
|
156
156
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
157
157
|
const self = this;
|
|
158
158
|
|
|
159
|
-
this.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
// only update threadPositions if the doc changed
|
|
175
|
-
const threadPositions = tr.docChanged
|
|
176
|
-
? getUpdatedThreadPositions(tr.doc, self.markType)
|
|
177
|
-
: self.threadPositions;
|
|
159
|
+
this.addProsemirrorPlugin(
|
|
160
|
+
new Plugin<CommentsPluginState>({
|
|
161
|
+
key: PLUGIN_KEY,
|
|
162
|
+
state: {
|
|
163
|
+
init() {
|
|
164
|
+
return {
|
|
165
|
+
decorations: DecorationSet.empty,
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
apply(tr, state) {
|
|
169
|
+
const action = tr.getMeta(PLUGIN_KEY);
|
|
170
|
+
|
|
171
|
+
if (!tr.docChanged && !action) {
|
|
172
|
+
return state;
|
|
173
|
+
}
|
|
178
174
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
175
|
+
// only update threadPositions if the doc changed
|
|
176
|
+
const threadPositions = tr.docChanged
|
|
177
|
+
? getUpdatedThreadPositions(tr.doc, self.markType)
|
|
178
|
+
: self.threadPositions;
|
|
184
179
|
|
|
185
|
-
|
|
186
|
-
|
|
180
|
+
if (threadPositions.size > 0 || self.threadPositions.size > 0) {
|
|
181
|
+
// small optimization; don't emit event if threadPositions before / after were both empty
|
|
182
|
+
self.threadPositions = threadPositions;
|
|
183
|
+
self.emitStateUpdate();
|
|
184
|
+
}
|
|
187
185
|
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
self.selectedThreadId
|
|
191
|
-
);
|
|
186
|
+
// update decorations if doc or selected thread changed
|
|
187
|
+
const decorations = [];
|
|
192
188
|
|
|
193
|
-
if (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
selectedThreadPosition.from,
|
|
197
|
-
selectedThreadPosition.to,
|
|
198
|
-
{
|
|
199
|
-
class: "bn-thread-mark-selected",
|
|
200
|
-
}
|
|
201
|
-
)
|
|
189
|
+
if (self.selectedThreadId) {
|
|
190
|
+
const selectedThreadPosition = threadPositions.get(
|
|
191
|
+
self.selectedThreadId,
|
|
202
192
|
);
|
|
193
|
+
|
|
194
|
+
if (selectedThreadPosition) {
|
|
195
|
+
decorations.push(
|
|
196
|
+
Decoration.inline(
|
|
197
|
+
selectedThreadPosition.from,
|
|
198
|
+
selectedThreadPosition.to,
|
|
199
|
+
{
|
|
200
|
+
class: "bn-thread-mark-selected",
|
|
201
|
+
},
|
|
202
|
+
),
|
|
203
|
+
);
|
|
204
|
+
}
|
|
203
205
|
}
|
|
204
|
-
}
|
|
205
206
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
},
|
|
211
|
-
props: {
|
|
212
|
-
decorations(state) {
|
|
213
|
-
return PLUGIN_KEY.getState(state)?.decorations ?? DecorationSet.empty;
|
|
207
|
+
return {
|
|
208
|
+
decorations: DecorationSet.create(tr.doc, decorations),
|
|
209
|
+
};
|
|
210
|
+
},
|
|
214
211
|
},
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
212
|
+
props: {
|
|
213
|
+
decorations(state) {
|
|
214
|
+
return (
|
|
215
|
+
PLUGIN_KEY.getState(state)?.decorations ?? DecorationSet.empty
|
|
216
|
+
);
|
|
217
|
+
},
|
|
218
|
+
/**
|
|
219
|
+
* Handle click on a thread mark and mark it as selected
|
|
220
|
+
*/
|
|
221
|
+
handleClick: (view, pos, event) => {
|
|
222
|
+
if (event.button !== 0) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
222
225
|
|
|
223
|
-
|
|
226
|
+
const node = view.state.doc.nodeAt(pos);
|
|
224
227
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
228
|
+
if (!node) {
|
|
229
|
+
self.selectThread(undefined);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
229
232
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
+
const commentMark = node.marks.find(
|
|
234
|
+
(mark) =>
|
|
235
|
+
mark.type.name === markType && mark.attrs.orphan !== true,
|
|
236
|
+
);
|
|
233
237
|
|
|
234
|
-
|
|
235
|
-
|
|
238
|
+
const threadId = commentMark?.attrs.threadId as string | undefined;
|
|
239
|
+
self.selectThread(threadId, false);
|
|
240
|
+
},
|
|
236
241
|
},
|
|
237
|
-
},
|
|
238
|
-
|
|
242
|
+
}),
|
|
243
|
+
);
|
|
239
244
|
}
|
|
240
245
|
|
|
241
246
|
/**
|
|
@@ -246,7 +251,7 @@ export class CommentsPlugin extends EventEmitter<any> {
|
|
|
246
251
|
pendingComment: boolean;
|
|
247
252
|
selectedThreadId: string | undefined;
|
|
248
253
|
threadPositions: Map<string, { from: number; to: number }>;
|
|
249
|
-
}) => void
|
|
254
|
+
}) => void,
|
|
250
255
|
) {
|
|
251
256
|
return this.on("update", callback);
|
|
252
257
|
}
|
|
@@ -263,7 +268,7 @@ export class CommentsPlugin extends EventEmitter<any> {
|
|
|
263
268
|
this.editor.transact((tr) =>
|
|
264
269
|
tr.setMeta(PLUGIN_KEY, {
|
|
265
270
|
name: SET_SELECTED_THREAD_ID,
|
|
266
|
-
})
|
|
271
|
+
}),
|
|
267
272
|
);
|
|
268
273
|
|
|
269
274
|
if (threadId && scrollToThread) {
|
|
@@ -14,7 +14,7 @@ export class UserStore<U extends User> extends EventEmitter<any> {
|
|
|
14
14
|
private loadingUsers = new Set<string>();
|
|
15
15
|
|
|
16
16
|
public constructor(
|
|
17
|
-
private readonly resolveUsers: (userIds: string[]) => Promise<U[]
|
|
17
|
+
private readonly resolveUsers: (userIds: string[]) => Promise<U[]>,
|
|
18
18
|
) {
|
|
19
19
|
super();
|
|
20
20
|
}
|
|
@@ -24,7 +24,7 @@ export class UserStore<U extends User> extends EventEmitter<any> {
|
|
|
24
24
|
*/
|
|
25
25
|
public async loadUsers(userIds: string[]) {
|
|
26
26
|
const missingUsers = userIds.filter(
|
|
27
|
-
(id) => !this.userCache.has(id) && !this.loadingUsers.has(id)
|
|
27
|
+
(id) => !this.userCache.has(id) && !this.loadingUsers.has(id),
|
|
28
28
|
);
|
|
29
29
|
|
|
30
30
|
if (missingUsers.length === 0) {
|