@blocknote/core 0.1.0-alpha.3
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 +99 -0
- package/dist/blocknote.js +4485 -0
- package/dist/blocknote.js.map +1 -0
- package/dist/blocknote.umd.cjs +90 -0
- package/dist/blocknote.umd.cjs.map +1 -0
- package/dist/style.css +1 -0
- package/package.json +109 -0
- package/src/BlockNoteExtensions.ts +90 -0
- package/src/EditorContent.tsx +1 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-100.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-100.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-200.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-200.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-300.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-300.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-500.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-500.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-600.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-600.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-700.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-700.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-800.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-800.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-900.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-900.woff2 +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-regular.woff +0 -0
- package/src/assets/inter-v12-latin/inter-v12-latin-regular.woff2 +0 -0
- package/src/editor.module.css +3 -0
- package/src/extensions/Blocks/OrderedListPlugin.ts +46 -0
- package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +146 -0
- package/src/extensions/Blocks/commands/joinBackward.ts +274 -0
- package/src/extensions/Blocks/helpers/findBlock.ts +3 -0
- package/src/extensions/Blocks/helpers/setBlockHeading.ts +30 -0
- package/src/extensions/Blocks/index.ts +15 -0
- package/src/extensions/Blocks/nodes/Block.module.css +226 -0
- package/src/extensions/Blocks/nodes/Block.ts +390 -0
- package/src/extensions/Blocks/nodes/BlockGroup.ts +28 -0
- package/src/extensions/Blocks/nodes/Content.ts +50 -0
- package/src/extensions/Blocks/nodes/README.md +26 -0
- package/src/extensions/Blocks/rule.ts +48 -0
- package/src/extensions/BubbleMenu/BubbleMenuExtension.tsx +28 -0
- package/src/extensions/BubbleMenu/BubbleMenuPlugin.ts +245 -0
- package/src/extensions/BubbleMenu/component/BubbleMenu.tsx +216 -0
- package/src/extensions/BubbleMenu/component/DropdownBlockItem.module.css +13 -0
- package/src/extensions/BubbleMenu/component/DropdownBlockItem.tsx +25 -0
- package/src/extensions/BubbleMenu/component/LinkToolbarButton.tsx +67 -0
- package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +15 -0
- package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.tsx +266 -0
- package/src/extensions/DraggableBlocks/components/DragHandle.module.css +33 -0
- package/src/extensions/DraggableBlocks/components/DragHandle.tsx +108 -0
- package/src/extensions/DraggableBlocks/components/DragHandleMenu.module.css +10 -0
- package/src/extensions/DraggableBlocks/components/DragHandleMenu.tsx +18 -0
- package/src/extensions/Hyperlinks/HyperlinkMark.tsx +16 -0
- package/src/extensions/Hyperlinks/HyperlinkMenuPlugin.tsx +200 -0
- package/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.tsx +59 -0
- package/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.tsx +72 -0
- package/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.tsx +173 -0
- package/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.ts +36 -0
- package/src/extensions/Hyperlinks/menus/atlaskit/README.md +1 -0
- package/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.tsx +61 -0
- package/src/extensions/Paragraph/FixedParagraph.ts +12 -0
- package/src/extensions/Placeholder/PlaceholderExtension.ts +127 -0
- package/src/extensions/SlashMenu/SlashMenuExtension.ts +43 -0
- package/src/extensions/SlashMenu/SlashMenuItem.ts +56 -0
- package/src/extensions/SlashMenu/defaultCommands.tsx +229 -0
- package/src/extensions/SlashMenu/index.ts +11 -0
- package/src/extensions/TrailingNode/TrailingNodeExtension.ts +70 -0
- package/src/extensions/UniqueID/UniqueID.ts +281 -0
- package/src/extensions/helpers/formatKeyboardShortcut.ts +9 -0
- package/src/fonts-inter.css +94 -0
- package/src/globals.css +28 -0
- package/src/index.ts +5 -0
- package/src/lib/atlaskit/browser.ts +47 -0
- package/src/root.module.css +19 -0
- package/src/shared/components/toolbar/SimpleToolbarButton.module.css +13 -0
- package/src/shared/components/toolbar/SimpleToolbarButton.tsx +56 -0
- package/src/shared/components/toolbar/Toolbar.module.css +10 -0
- package/src/shared/components/toolbar/Toolbar.tsx +5 -0
- package/src/shared/components/toolbar/ToolbarSeparator.module.css +13 -0
- package/src/shared/components/toolbar/ToolbarSeparator.tsx +7 -0
- package/src/shared/components/tooltip/TooltipContent.module.css +15 -0
- package/src/shared/components/tooltip/TooltipContent.tsx +23 -0
- package/src/shared/hooks/useEditorForceUpdate.tsx +30 -0
- package/src/shared/plugins/suggestion/SuggestionItem.ts +31 -0
- package/src/shared/plugins/suggestion/SuggestionListReactRenderer.ts +227 -0
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +365 -0
- package/src/shared/plugins/suggestion/components/SuggestionGroup.module.css +45 -0
- package/src/shared/plugins/suggestion/components/SuggestionGroup.tsx +134 -0
- package/src/shared/plugins/suggestion/components/SuggestionList.module.css +10 -0
- package/src/shared/plugins/suggestion/components/SuggestionList.tsx +91 -0
- package/src/style.css +7 -0
- package/src/useEditor.ts +47 -0
- package/src/vite-env.d.ts +1 -0
- package/types/src/BlockNoteExtensions.d.ts +4 -0
- package/types/src/EditorContent.d.ts +1 -0
- package/types/src/extensions/Blocks/OrderedListPlugin.d.ts +2 -0
- package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +13 -0
- package/types/src/extensions/Blocks/commands/joinBackward.d.ts +14 -0
- package/types/src/extensions/Blocks/helpers/findBlock.d.ts +6 -0
- package/types/src/extensions/Blocks/helpers/setBlockHeading.d.ts +5 -0
- package/types/src/extensions/Blocks/index.d.ts +1 -0
- package/types/src/extensions/Blocks/nodes/Block.d.ts +32 -0
- package/types/src/extensions/Blocks/nodes/BlockGroup.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/Content.d.ts +5 -0
- package/types/src/extensions/Blocks/rule.d.ts +16 -0
- package/types/src/extensions/BubbleMenu/BubbleMenuExtension.d.ts +5 -0
- package/types/src/extensions/BubbleMenu/BubbleMenuPlugin.d.ts +46 -0
- package/types/src/extensions/BubbleMenu/component/BubbleMenu.d.ts +5 -0
- package/types/src/extensions/BubbleMenu/component/DropdownBlockItem.d.ts +10 -0
- package/types/src/extensions/BubbleMenu/component/LinkToolbarButton.d.ts +11 -0
- package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +7 -0
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +18 -0
- package/types/src/extensions/DraggableBlocks/components/DragHandle.d.ts +12 -0
- package/types/src/extensions/DraggableBlocks/components/DragHandleMenu.d.ts +6 -0
- package/types/src/extensions/Hyperlinks/HyperlinkMark.d.ts +7 -0
- package/types/src/extensions/Hyperlinks/HyperlinkMenuPlugin.d.ts +2 -0
- package/types/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.d.ts +12 -0
- package/types/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.d.ts +10 -0
- package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.d.ts +39 -0
- package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.d.ts +1 -0
- package/types/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.d.ts +11 -0
- package/types/src/extensions/Paragraph/FixedParagraph.d.ts +1 -0
- package/types/src/extensions/Placeholder/PlaceholderExtension.d.ts +25 -0
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +10 -0
- package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +43 -0
- package/types/src/extensions/SlashMenu/defaultCommands.d.ts +8 -0
- package/types/src/extensions/SlashMenu/index.d.ts +5 -0
- package/types/src/extensions/TrailingNode/TrailingNodeExtension.d.ts +10 -0
- package/types/src/extensions/UniqueID/UniqueID.d.ts +3 -0
- package/types/src/extensions/helpers/formatKeyboardShortcut.d.ts +1 -0
- package/types/src/index.d.ts +4 -0
- package/types/src/lib/atlaskit/browser.d.ts +12 -0
- package/types/src/shared/components/toolbar/SimpleToolbarButton.d.ts +16 -0
- package/types/src/shared/components/toolbar/Toolbar.d.ts +4 -0
- package/types/src/shared/components/toolbar/ToolbarSeparator.d.ts +2 -0
- package/types/src/shared/components/tooltip/TooltipContent.d.ts +15 -0
- package/types/src/shared/hooks/useEditorForceUpdate.d.ts +2 -0
- package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +29 -0
- package/types/src/shared/plugins/suggestion/SuggestionListReactRenderer.d.ts +71 -0
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +74 -0
- package/types/src/shared/plugins/suggestion/components/SuggestionGroup.d.ts +23 -0
- package/types/src/shared/plugins/suggestion/components/SuggestionList.d.ts +26 -0
- package/types/src/useEditor.d.ts +8 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RiH1,
|
|
3
|
+
RiH2,
|
|
4
|
+
RiH3,
|
|
5
|
+
RiListOrdered,
|
|
6
|
+
RiListUnordered,
|
|
7
|
+
RiText,
|
|
8
|
+
} from "react-icons/ri";
|
|
9
|
+
import formatKeyboardShortcut from "../helpers/formatKeyboardShortcut";
|
|
10
|
+
import { SlashMenuGroups, SlashMenuItem } from "./SlashMenuItem";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* An array containing commands for creating all default blocks.
|
|
14
|
+
*/
|
|
15
|
+
const defaultCommands: { [key: string]: SlashMenuItem } = {
|
|
16
|
+
// Command for creating a level 1 heading
|
|
17
|
+
heading: new SlashMenuItem(
|
|
18
|
+
"Heading",
|
|
19
|
+
SlashMenuGroups.HEADINGS,
|
|
20
|
+
(editor, range) => {
|
|
21
|
+
return editor
|
|
22
|
+
.chain()
|
|
23
|
+
.focus()
|
|
24
|
+
.deleteRange(range)
|
|
25
|
+
.addNewBlockAsSibling({ headingType: 1 })
|
|
26
|
+
.run();
|
|
27
|
+
},
|
|
28
|
+
["h", "heading1", "h1"],
|
|
29
|
+
RiH1,
|
|
30
|
+
"Used for a top-level heading",
|
|
31
|
+
formatKeyboardShortcut("Mod-Alt-1")
|
|
32
|
+
),
|
|
33
|
+
|
|
34
|
+
// Command for creating a level 2 heading
|
|
35
|
+
heading2: new SlashMenuItem(
|
|
36
|
+
"Heading 2",
|
|
37
|
+
SlashMenuGroups.HEADINGS,
|
|
38
|
+
(editor, range) => {
|
|
39
|
+
return editor
|
|
40
|
+
.chain()
|
|
41
|
+
.focus()
|
|
42
|
+
.deleteRange(range)
|
|
43
|
+
.addNewBlockAsSibling({ headingType: 2 })
|
|
44
|
+
.run();
|
|
45
|
+
},
|
|
46
|
+
["h2", "heading2", "subheading"],
|
|
47
|
+
RiH2,
|
|
48
|
+
"Used for key sections",
|
|
49
|
+
formatKeyboardShortcut("Mod-Alt-2")
|
|
50
|
+
),
|
|
51
|
+
|
|
52
|
+
// Command for creating a level 3 heading
|
|
53
|
+
heading3: new SlashMenuItem(
|
|
54
|
+
"Heading 3",
|
|
55
|
+
SlashMenuGroups.HEADINGS,
|
|
56
|
+
(editor, range) => {
|
|
57
|
+
return editor
|
|
58
|
+
.chain()
|
|
59
|
+
.focus()
|
|
60
|
+
.deleteRange(range)
|
|
61
|
+
.addNewBlockAsSibling({ headingType: 3 })
|
|
62
|
+
.run();
|
|
63
|
+
},
|
|
64
|
+
["h3", "heading3", "subheading"],
|
|
65
|
+
RiH3,
|
|
66
|
+
"Used for subsections and group headings",
|
|
67
|
+
formatKeyboardShortcut("Mod-Alt-3")
|
|
68
|
+
),
|
|
69
|
+
|
|
70
|
+
// Command for creating an ordered list
|
|
71
|
+
numberedList: new SlashMenuItem(
|
|
72
|
+
"Numbered List",
|
|
73
|
+
SlashMenuGroups.BASIC_BLOCKS,
|
|
74
|
+
(editor, range) => {
|
|
75
|
+
return editor
|
|
76
|
+
.chain()
|
|
77
|
+
.focus()
|
|
78
|
+
.deleteRange(range)
|
|
79
|
+
.addNewBlockAsSibling({ listType: "oli" })
|
|
80
|
+
.run();
|
|
81
|
+
},
|
|
82
|
+
["li", "list", "numberedlist", "numbered list"],
|
|
83
|
+
RiListOrdered,
|
|
84
|
+
"Used to display a numbered list",
|
|
85
|
+
formatKeyboardShortcut("Mod-Shift-7")
|
|
86
|
+
),
|
|
87
|
+
|
|
88
|
+
// Command for creating a bullet list
|
|
89
|
+
bulletlist: new SlashMenuItem(
|
|
90
|
+
"Bullet List",
|
|
91
|
+
SlashMenuGroups.BASIC_BLOCKS,
|
|
92
|
+
(editor, range) => {
|
|
93
|
+
return editor
|
|
94
|
+
.chain()
|
|
95
|
+
.focus()
|
|
96
|
+
.deleteRange(range)
|
|
97
|
+
.addNewBlockAsSibling({ listType: "li" })
|
|
98
|
+
.run();
|
|
99
|
+
},
|
|
100
|
+
["ul", "list", "bulletlist", "bullet list"],
|
|
101
|
+
RiListUnordered,
|
|
102
|
+
"Used to display an unordered list",
|
|
103
|
+
formatKeyboardShortcut("Mod-Shift-8")
|
|
104
|
+
),
|
|
105
|
+
|
|
106
|
+
// Command for creating a paragraph (pretty useless)
|
|
107
|
+
paragraph: new SlashMenuItem(
|
|
108
|
+
"Paragraph",
|
|
109
|
+
SlashMenuGroups.BASIC_BLOCKS,
|
|
110
|
+
(editor, range) => {
|
|
111
|
+
return editor
|
|
112
|
+
.chain()
|
|
113
|
+
.focus()
|
|
114
|
+
.deleteRange(range)
|
|
115
|
+
.addNewBlockAsSibling()
|
|
116
|
+
.run();
|
|
117
|
+
},
|
|
118
|
+
["p"],
|
|
119
|
+
RiText,
|
|
120
|
+
"Used for the body of your document",
|
|
121
|
+
formatKeyboardShortcut("Mod-Alt-0")
|
|
122
|
+
),
|
|
123
|
+
|
|
124
|
+
// replaceRangeWithNode(editor, range, node);
|
|
125
|
+
|
|
126
|
+
// return true;
|
|
127
|
+
// },
|
|
128
|
+
// ["ol", "orderedlist"],
|
|
129
|
+
// OrderedListIcon,
|
|
130
|
+
// "Used to display an ordered (enumerated) list item"
|
|
131
|
+
// ),
|
|
132
|
+
|
|
133
|
+
// Command for creating a blockquote
|
|
134
|
+
// blockquote: new SlashCommand(
|
|
135
|
+
// "Block Quote",
|
|
136
|
+
// CommandGroup.BASIC_BLOCKS,
|
|
137
|
+
// (editor, range) => {
|
|
138
|
+
// const paragraph = editor.schema.node("paragraph");
|
|
139
|
+
// const node = editor.schema.node(
|
|
140
|
+
// "blockquote",
|
|
141
|
+
// { "block-id": uniqueId.generate() },
|
|
142
|
+
// paragraph
|
|
143
|
+
// );
|
|
144
|
+
|
|
145
|
+
// replaceRangeWithNode(editor, range, node);
|
|
146
|
+
|
|
147
|
+
// return true;
|
|
148
|
+
// },
|
|
149
|
+
// ["quote", "blockquote"],
|
|
150
|
+
// QuoteIcon,
|
|
151
|
+
// "Used to make a quote stand out",
|
|
152
|
+
// "Ctrl+Shift+B"
|
|
153
|
+
// ),
|
|
154
|
+
|
|
155
|
+
// Command for creating a horizontal rule
|
|
156
|
+
// horizontalRule: new SlashCommand(
|
|
157
|
+
// "Horizontal Rule",
|
|
158
|
+
// CommandGroup.BASIC_BLOCKS,
|
|
159
|
+
// (editor, range) => {
|
|
160
|
+
// const node = editor.schema.node("horizontalRule", {
|
|
161
|
+
// "block-id": uniqueId.generate(),
|
|
162
|
+
// });
|
|
163
|
+
|
|
164
|
+
// // insert horizontal rule, create a new block after the horizontal rule if applicable
|
|
165
|
+
// // and put the cursor in the block after the horizontal rule.
|
|
166
|
+
// editor
|
|
167
|
+
// .chain()
|
|
168
|
+
// .focus()
|
|
169
|
+
// .replaceRangeAndUpdateSelection(range, node)
|
|
170
|
+
// .command(({ tr, dispatch }) => {
|
|
171
|
+
// if (dispatch) {
|
|
172
|
+
// // the node immediately after the cursor
|
|
173
|
+
// const nodeAfter = tr.selection.$to.nodeAfter;
|
|
174
|
+
|
|
175
|
+
// // the position of the cursor
|
|
176
|
+
// const cursorPos = tr.selection.$to.pos;
|
|
177
|
+
|
|
178
|
+
// // check if there is no node after the cursor (end of document)
|
|
179
|
+
// if (!nodeAfter) {
|
|
180
|
+
// // create a new block of the default type (probably paragraph) after the cursor
|
|
181
|
+
// const { parent } = tr.selection.$to;
|
|
182
|
+
// const node = parent.type.contentMatch.defaultType?.create();
|
|
183
|
+
|
|
184
|
+
// if (node) {
|
|
185
|
+
// tr.insert(cursorPos, node);
|
|
186
|
+
// }
|
|
187
|
+
// }
|
|
188
|
+
|
|
189
|
+
// // try to put the cursor at the start of the node directly after the inserted horizontal rule
|
|
190
|
+
// tr.doc.nodesBetween(cursorPos, cursorPos + 1, (node, pos) => {
|
|
191
|
+
// if (node.type.name !== "horizontalRule") {
|
|
192
|
+
// tr.setSelection(TextSelection.create(tr.doc, pos));
|
|
193
|
+
// }
|
|
194
|
+
// });
|
|
195
|
+
// }
|
|
196
|
+
|
|
197
|
+
// return true;
|
|
198
|
+
// })
|
|
199
|
+
// .scrollIntoView()
|
|
200
|
+
// .run();
|
|
201
|
+
// return true;
|
|
202
|
+
// },
|
|
203
|
+
// ["hr", "horizontalrule"],
|
|
204
|
+
// SeparatorIcon,
|
|
205
|
+
// "Used to separate sections with a horizontal line"
|
|
206
|
+
// ),
|
|
207
|
+
|
|
208
|
+
// Command for creating a table
|
|
209
|
+
// table: new SlashCommand(
|
|
210
|
+
// "Table",
|
|
211
|
+
// CommandGroup.BASIC_BLOCKS,
|
|
212
|
+
// (editor, range) => {
|
|
213
|
+
// editor.chain().focus().deleteRange(range).run();
|
|
214
|
+
// // TODO: add blockid, pending https://github.com/ueberdosis/tiptap/pull/1469
|
|
215
|
+
// editor
|
|
216
|
+
// .chain()
|
|
217
|
+
// .focus()
|
|
218
|
+
// .insertTable({ rows: 1, cols: 2, withHeaderRow: false })
|
|
219
|
+
// .scrollIntoView()
|
|
220
|
+
// .run();
|
|
221
|
+
// return true;
|
|
222
|
+
// },
|
|
223
|
+
// ["table", "database"],
|
|
224
|
+
// TableIcon,
|
|
225
|
+
// "Used to create a simple table"
|
|
226
|
+
// ),
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export default defaultCommands;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SlashMenuExtension } from "./SlashMenuExtension";
|
|
2
|
+
import defaultCommands from "./defaultCommands";
|
|
3
|
+
import { SlashMenuGroups, SlashMenuItem } from "./SlashMenuItem";
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
defaultCommands,
|
|
7
|
+
SlashMenuItem as SlashCommand,
|
|
8
|
+
SlashMenuGroups as CommandGroup,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default SlashMenuExtension;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Extension } from "@tiptap/core";
|
|
2
|
+
import { Plugin, PluginKey } from "prosemirror-state";
|
|
3
|
+
|
|
4
|
+
// based on https://github.com/ueberdosis/tiptap/blob/40a9404c94c7fef7900610c195536384781ae101/demos/src/Experiments/TrailingNode/Vue/trailing-node.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extension based on:
|
|
8
|
+
* - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js
|
|
9
|
+
* - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export interface TrailingNodeOptions {
|
|
13
|
+
node: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const TrailingNode = Extension.create<TrailingNodeOptions>({
|
|
17
|
+
name: "trailingNode",
|
|
18
|
+
|
|
19
|
+
addProseMirrorPlugins() {
|
|
20
|
+
const plugin = new PluginKey(this.name);
|
|
21
|
+
// const disabledNodes = Object.entries(this.editor.schema.nodes)
|
|
22
|
+
// .map(([, value]) => value)
|
|
23
|
+
// .filter((node) => this.options.notAfter.includes(node.name));
|
|
24
|
+
|
|
25
|
+
return [
|
|
26
|
+
new Plugin({
|
|
27
|
+
key: plugin,
|
|
28
|
+
appendTransaction: (_, __, state) => {
|
|
29
|
+
const { doc, tr, schema } = state;
|
|
30
|
+
const shouldInsertNodeAtEnd = plugin.getState(state);
|
|
31
|
+
const endPosition = doc.content.size - 2;
|
|
32
|
+
const type = schema.nodes["tcblock"];
|
|
33
|
+
const contenttype = schema.nodes["tccontent"];
|
|
34
|
+
if (!shouldInsertNodeAtEnd) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return tr.insert(
|
|
39
|
+
endPosition,
|
|
40
|
+
type.create(undefined, contenttype.create())
|
|
41
|
+
);
|
|
42
|
+
},
|
|
43
|
+
state: {
|
|
44
|
+
init: (_, _state) => {
|
|
45
|
+
// (maybe fix): use same logic as apply() here
|
|
46
|
+
// so it works when initializing
|
|
47
|
+
},
|
|
48
|
+
apply: (tr, value) => {
|
|
49
|
+
if (!tr.docChanged) {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let lastNode = tr.doc.lastChild;
|
|
54
|
+
|
|
55
|
+
if (!lastNode || lastNode.type.name !== "blockgroup") {
|
|
56
|
+
throw new Error("Expected blockgroup");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
lastNode = lastNode.lastChild;
|
|
60
|
+
|
|
61
|
+
if (!lastNode || lastNode.type.name !== "tcblock") {
|
|
62
|
+
throw new Error("Expected tcblock");
|
|
63
|
+
}
|
|
64
|
+
return lastNode.nodeSize > 4; // empty <tcblock><tccontent/></tcblock> is length 4
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
}),
|
|
68
|
+
];
|
|
69
|
+
},
|
|
70
|
+
});
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import {
|
|
2
|
+
combineTransactionSteps,
|
|
3
|
+
Extension,
|
|
4
|
+
findChildren,
|
|
5
|
+
findChildrenInRange,
|
|
6
|
+
getChangedRanges,
|
|
7
|
+
} from "@tiptap/core";
|
|
8
|
+
import { Fragment, Slice } from "prosemirror-model";
|
|
9
|
+
import { Plugin, PluginKey } from "prosemirror-state";
|
|
10
|
+
import { v4 } from "uuid";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Code from Tiptap UniqueID extension (https://tiptap.dev/api/extensions/unique-id)
|
|
14
|
+
* This extension is licensed under MIT (even though it's part of Tiptap pro).
|
|
15
|
+
*
|
|
16
|
+
* If you're a user of BlockNote, we still recommend to support their awesome work and become a sponsor!
|
|
17
|
+
* https://tiptap.dev/pro
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Removes duplicated values within an array.
|
|
22
|
+
* Supports numbers, strings and objects.
|
|
23
|
+
*/
|
|
24
|
+
function removeDuplicates(array: any, by = JSON.stringify) {
|
|
25
|
+
const seen: any = {};
|
|
26
|
+
return array.filter((item: any) => {
|
|
27
|
+
const key = by(item);
|
|
28
|
+
return Object.prototype.hasOwnProperty.call(seen, key)
|
|
29
|
+
? false
|
|
30
|
+
: (seen[key] = true);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns a list of duplicated items within an array.
|
|
36
|
+
*/
|
|
37
|
+
function findDuplicates(items: any) {
|
|
38
|
+
const filtered = items.filter(
|
|
39
|
+
(el: any, index: number) => items.indexOf(el) !== index
|
|
40
|
+
);
|
|
41
|
+
const duplicates = removeDuplicates(filtered);
|
|
42
|
+
return duplicates;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const UniqueID = Extension.create({
|
|
46
|
+
name: "uniqueID",
|
|
47
|
+
// we’ll set a very high priority to make sure this runs first
|
|
48
|
+
// and is compatible with `appendTransaction` hooks of other extensions
|
|
49
|
+
priority: 10000,
|
|
50
|
+
addOptions() {
|
|
51
|
+
return {
|
|
52
|
+
attributeName: "id",
|
|
53
|
+
types: [],
|
|
54
|
+
generateID: () => v4(),
|
|
55
|
+
filterTransaction: null,
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
addGlobalAttributes() {
|
|
59
|
+
return [
|
|
60
|
+
{
|
|
61
|
+
types: this.options.types,
|
|
62
|
+
attributes: {
|
|
63
|
+
[this.options.attributeName]: {
|
|
64
|
+
default: null,
|
|
65
|
+
parseHTML: (element) =>
|
|
66
|
+
element.getAttribute(`data-${this.options.attributeName}`),
|
|
67
|
+
renderHTML: (attributes) => {
|
|
68
|
+
if (!attributes[this.options.attributeName]) {
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
[`data-${this.options.attributeName}`]:
|
|
73
|
+
attributes[this.options.attributeName],
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
},
|
|
81
|
+
// check initial content for missing ids
|
|
82
|
+
onCreate() {
|
|
83
|
+
// Don’t do this when the collaboration extension is active
|
|
84
|
+
// because this may update the content, so Y.js tries to merge these changes.
|
|
85
|
+
// This leads to empty block nodes.
|
|
86
|
+
// See: https://github.com/ueberdosis/tiptap/issues/2400
|
|
87
|
+
if (
|
|
88
|
+
this.editor.extensionManager.extensions.find(
|
|
89
|
+
(extension) => extension.name === "collaboration"
|
|
90
|
+
)
|
|
91
|
+
) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const { view, state } = this.editor;
|
|
95
|
+
const { tr, doc } = state;
|
|
96
|
+
const { types, attributeName, generateID } = this.options;
|
|
97
|
+
const nodesWithoutId = findChildren(doc, (node) => {
|
|
98
|
+
return (
|
|
99
|
+
types.includes(node.type.name) && node.attrs[attributeName] === null
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
nodesWithoutId.forEach(({ node, pos }) => {
|
|
103
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
104
|
+
...node.attrs,
|
|
105
|
+
[attributeName]: generateID(),
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
tr.setMeta("addToHistory", false);
|
|
109
|
+
view.dispatch(tr);
|
|
110
|
+
},
|
|
111
|
+
addProseMirrorPlugins() {
|
|
112
|
+
let dragSourceElement: any = null;
|
|
113
|
+
let transformPasted = false;
|
|
114
|
+
return [
|
|
115
|
+
new Plugin({
|
|
116
|
+
key: new PluginKey("uniqueID"),
|
|
117
|
+
appendTransaction: (transactions, oldState, newState) => {
|
|
118
|
+
console.log("appendTransaction");
|
|
119
|
+
const docChanges =
|
|
120
|
+
transactions.some((transaction) => transaction.docChanged) &&
|
|
121
|
+
!oldState.doc.eq(newState.doc);
|
|
122
|
+
const filterTransactions =
|
|
123
|
+
this.options.filterTransaction &&
|
|
124
|
+
transactions.some((tr) => {
|
|
125
|
+
var _a, _b;
|
|
126
|
+
return !((_b = (_a = this.options).filterTransaction) === null ||
|
|
127
|
+
_b === void 0
|
|
128
|
+
? void 0
|
|
129
|
+
: _b.call(_a, tr));
|
|
130
|
+
});
|
|
131
|
+
if (!docChanges || filterTransactions) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const { tr } = newState;
|
|
135
|
+
const { types, attributeName, generateID } = this.options;
|
|
136
|
+
const transform = combineTransactionSteps(
|
|
137
|
+
oldState.doc,
|
|
138
|
+
transactions as any
|
|
139
|
+
);
|
|
140
|
+
const { mapping } = transform;
|
|
141
|
+
// get changed ranges based on the old state
|
|
142
|
+
const changes = getChangedRanges(transform);
|
|
143
|
+
|
|
144
|
+
changes.forEach(({ newRange }) => {
|
|
145
|
+
const newNodes = findChildrenInRange(
|
|
146
|
+
newState.doc,
|
|
147
|
+
newRange,
|
|
148
|
+
(node) => {
|
|
149
|
+
return types.includes(node.type.name);
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
const newIds = newNodes
|
|
153
|
+
.map(({ node }) => node.attrs[attributeName])
|
|
154
|
+
.filter((id) => id !== null);
|
|
155
|
+
const duplicatedNewIds = findDuplicates(newIds);
|
|
156
|
+
newNodes.forEach(({ node, pos }) => {
|
|
157
|
+
var _a;
|
|
158
|
+
// instead of checking `node.attrs[attributeName]` directly
|
|
159
|
+
// we look at the current state of the node within `tr.doc`.
|
|
160
|
+
// this helps to prevent adding new ids to the same node
|
|
161
|
+
// if the node changed multiple times within one transaction
|
|
162
|
+
const id =
|
|
163
|
+
(_a = tr.doc.nodeAt(pos)) === null || _a === void 0
|
|
164
|
+
? void 0
|
|
165
|
+
: _a.attrs[attributeName];
|
|
166
|
+
if (id === null) {
|
|
167
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
168
|
+
...node.attrs,
|
|
169
|
+
[attributeName]: generateID(),
|
|
170
|
+
});
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
// check if the node doesn’t exist in the old state
|
|
174
|
+
const { deleted } = mapping.invert().mapResult(pos);
|
|
175
|
+
const newNode = deleted && duplicatedNewIds.includes(id);
|
|
176
|
+
if (newNode) {
|
|
177
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
178
|
+
...node.attrs,
|
|
179
|
+
[attributeName]: generateID(),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
if (!tr.steps.length) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
return tr;
|
|
188
|
+
},
|
|
189
|
+
// we register a global drag handler to track the current drag source element
|
|
190
|
+
view(view) {
|
|
191
|
+
const handleDragstart = (event: any) => {
|
|
192
|
+
var _a;
|
|
193
|
+
dragSourceElement = (
|
|
194
|
+
(_a = view.dom.parentElement) === null || _a === void 0
|
|
195
|
+
? void 0
|
|
196
|
+
: _a.contains(event.target)
|
|
197
|
+
)
|
|
198
|
+
? view.dom.parentElement
|
|
199
|
+
: null;
|
|
200
|
+
};
|
|
201
|
+
window.addEventListener("dragstart", handleDragstart);
|
|
202
|
+
return {
|
|
203
|
+
destroy() {
|
|
204
|
+
window.removeEventListener("dragstart", handleDragstart);
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
},
|
|
208
|
+
props: {
|
|
209
|
+
// `handleDOMEvents` is called before `transformPasted`
|
|
210
|
+
// so we can do some checks before
|
|
211
|
+
handleDOMEvents: {
|
|
212
|
+
// only create new ids for dropped content while holding `alt`
|
|
213
|
+
// or content is dragged from another editor
|
|
214
|
+
drop: (view, event: any) => {
|
|
215
|
+
var _a;
|
|
216
|
+
if (
|
|
217
|
+
dragSourceElement !== view.dom.parentElement ||
|
|
218
|
+
((_a = event.dataTransfer) === null || _a === void 0
|
|
219
|
+
? void 0
|
|
220
|
+
: _a.effectAllowed) === "copy"
|
|
221
|
+
) {
|
|
222
|
+
dragSourceElement = null;
|
|
223
|
+
transformPasted = true;
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
},
|
|
227
|
+
// always create new ids on pasted content
|
|
228
|
+
paste: () => {
|
|
229
|
+
transformPasted = true;
|
|
230
|
+
return false;
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
// we’ll remove ids for every pasted node
|
|
234
|
+
// so we can create a new one within `appendTransaction`
|
|
235
|
+
transformPasted: (slice) => {
|
|
236
|
+
if (!transformPasted) {
|
|
237
|
+
return slice;
|
|
238
|
+
}
|
|
239
|
+
const { types, attributeName } = this.options;
|
|
240
|
+
const removeId = (fragment: any) => {
|
|
241
|
+
const list: any[] = [];
|
|
242
|
+
fragment.forEach((node: any) => {
|
|
243
|
+
// don’t touch text nodes
|
|
244
|
+
if (node.isText) {
|
|
245
|
+
list.push(node);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
// check for any other child nodes
|
|
249
|
+
if (!types.includes(node.type.name)) {
|
|
250
|
+
list.push(node.copy(removeId(node.content)));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
// remove id
|
|
254
|
+
const nodeWithoutId = node.type.create(
|
|
255
|
+
{
|
|
256
|
+
...node.attrs,
|
|
257
|
+
[attributeName]: null,
|
|
258
|
+
},
|
|
259
|
+
removeId(node.content),
|
|
260
|
+
node.marks
|
|
261
|
+
);
|
|
262
|
+
list.push(nodeWithoutId);
|
|
263
|
+
});
|
|
264
|
+
return Fragment.from(list);
|
|
265
|
+
};
|
|
266
|
+
// reset check
|
|
267
|
+
transformPasted = false;
|
|
268
|
+
return new Slice(
|
|
269
|
+
removeId(slice.content),
|
|
270
|
+
slice.openStart,
|
|
271
|
+
slice.openEnd
|
|
272
|
+
);
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
}),
|
|
276
|
+
];
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
export { UniqueID, UniqueID as default };
|
|
281
|
+
//# sourceMappingURL=tiptap-extension-unique-id.esm.js.map
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* Generated using https://google-webfonts-helper.herokuapp.com/fonts/inter?subsets=latin */
|
|
2
|
+
|
|
3
|
+
/* inter-100 - latin */
|
|
4
|
+
@font-face {
|
|
5
|
+
font-family: "Inter";
|
|
6
|
+
font-style: normal;
|
|
7
|
+
font-weight: 100;
|
|
8
|
+
src: local(""),
|
|
9
|
+
url("./assets/inter-v12-latin/inter-v12-latin-100.woff2") format("woff2"),
|
|
10
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
11
|
+
url("./assets/inter-v12-latin/inter-v12-latin-100.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
12
|
+
}
|
|
13
|
+
/* inter-200 - latin */
|
|
14
|
+
@font-face {
|
|
15
|
+
font-family: "Inter";
|
|
16
|
+
font-style: normal;
|
|
17
|
+
font-weight: 200;
|
|
18
|
+
src: local(""),
|
|
19
|
+
url("./assets/inter-v12-latin/inter-v12-latin-200.woff2") format("woff2"),
|
|
20
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
21
|
+
url("./assets/inter-v12-latin/inter-v12-latin-200.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
22
|
+
}
|
|
23
|
+
/* inter-300 - latin */
|
|
24
|
+
@font-face {
|
|
25
|
+
font-family: "Inter";
|
|
26
|
+
font-style: normal;
|
|
27
|
+
font-weight: 300;
|
|
28
|
+
src: local(""),
|
|
29
|
+
url("./assets/inter-v12-latin/inter-v12-latin-300.woff2") format("woff2"),
|
|
30
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
31
|
+
url("./assets/inter-v12-latin/inter-v12-latin-300.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
32
|
+
}
|
|
33
|
+
/* inter-regular - latin */
|
|
34
|
+
@font-face {
|
|
35
|
+
font-family: "Inter";
|
|
36
|
+
font-style: normal;
|
|
37
|
+
font-weight: 400;
|
|
38
|
+
src: local(""),
|
|
39
|
+
url("./assets/inter-v12-latin/inter-v12-latin-regular.woff2")
|
|
40
|
+
format("woff2"),
|
|
41
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
42
|
+
url("./assets/inter-v12-latin/inter-v12-latin-regular.woff")
|
|
43
|
+
format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
44
|
+
}
|
|
45
|
+
/* inter-500 - latin */
|
|
46
|
+
@font-face {
|
|
47
|
+
font-family: "Inter";
|
|
48
|
+
font-style: normal;
|
|
49
|
+
font-weight: 500;
|
|
50
|
+
src: local(""),
|
|
51
|
+
url("./assets/inter-v12-latin/inter-v12-latin-500.woff2") format("woff2"),
|
|
52
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
53
|
+
url("./assets/inter-v12-latin/inter-v12-latin-500.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
54
|
+
}
|
|
55
|
+
/* inter-600 - latin */
|
|
56
|
+
@font-face {
|
|
57
|
+
font-family: "Inter";
|
|
58
|
+
font-style: normal;
|
|
59
|
+
font-weight: 600;
|
|
60
|
+
src: local(""),
|
|
61
|
+
url("./assets/inter-v12-latin/inter-v12-latin-600.woff2") format("woff2"),
|
|
62
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
63
|
+
url("./assets/inter-v12-latin/inter-v12-latin-600.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
64
|
+
}
|
|
65
|
+
/* inter-700 - latin */
|
|
66
|
+
@font-face {
|
|
67
|
+
font-family: "Inter";
|
|
68
|
+
font-style: normal;
|
|
69
|
+
font-weight: 700;
|
|
70
|
+
src: local(""),
|
|
71
|
+
url("./assets/inter-v12-latin/inter-v12-latin-700.woff2") format("woff2"),
|
|
72
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
73
|
+
url("./assets/inter-v12-latin/inter-v12-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
74
|
+
}
|
|
75
|
+
/* inter-800 - latin */
|
|
76
|
+
@font-face {
|
|
77
|
+
font-family: "Inter";
|
|
78
|
+
font-style: normal;
|
|
79
|
+
font-weight: 800;
|
|
80
|
+
src: local(""),
|
|
81
|
+
url("./assets/inter-v12-latin/inter-v12-latin-800.woff2") format("woff2"),
|
|
82
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
83
|
+
url("./assets/inter-v12-latin/inter-v12-latin-800.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
84
|
+
}
|
|
85
|
+
/* inter-900 - latin */
|
|
86
|
+
@font-face {
|
|
87
|
+
font-family: "Inter";
|
|
88
|
+
font-style: normal;
|
|
89
|
+
font-weight: 900;
|
|
90
|
+
src: local(""),
|
|
91
|
+
url("./assets/inter-v12-latin/inter-v12-latin-900.woff2") format("woff2"),
|
|
92
|
+
/* Chrome 26+, Opera 23+, Firefox 39+ */
|
|
93
|
+
url("./assets/inter-v12-latin/inter-v12-latin-900.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
|
94
|
+
}
|