@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.
Files changed (143) hide show
  1. package/README.md +99 -0
  2. package/dist/blocknote.js +4485 -0
  3. package/dist/blocknote.js.map +1 -0
  4. package/dist/blocknote.umd.cjs +90 -0
  5. package/dist/blocknote.umd.cjs.map +1 -0
  6. package/dist/style.css +1 -0
  7. package/package.json +109 -0
  8. package/src/BlockNoteExtensions.ts +90 -0
  9. package/src/EditorContent.tsx +1 -0
  10. package/src/assets/inter-v12-latin/inter-v12-latin-100.woff +0 -0
  11. package/src/assets/inter-v12-latin/inter-v12-latin-100.woff2 +0 -0
  12. package/src/assets/inter-v12-latin/inter-v12-latin-200.woff +0 -0
  13. package/src/assets/inter-v12-latin/inter-v12-latin-200.woff2 +0 -0
  14. package/src/assets/inter-v12-latin/inter-v12-latin-300.woff +0 -0
  15. package/src/assets/inter-v12-latin/inter-v12-latin-300.woff2 +0 -0
  16. package/src/assets/inter-v12-latin/inter-v12-latin-500.woff +0 -0
  17. package/src/assets/inter-v12-latin/inter-v12-latin-500.woff2 +0 -0
  18. package/src/assets/inter-v12-latin/inter-v12-latin-600.woff +0 -0
  19. package/src/assets/inter-v12-latin/inter-v12-latin-600.woff2 +0 -0
  20. package/src/assets/inter-v12-latin/inter-v12-latin-700.woff +0 -0
  21. package/src/assets/inter-v12-latin/inter-v12-latin-700.woff2 +0 -0
  22. package/src/assets/inter-v12-latin/inter-v12-latin-800.woff +0 -0
  23. package/src/assets/inter-v12-latin/inter-v12-latin-800.woff2 +0 -0
  24. package/src/assets/inter-v12-latin/inter-v12-latin-900.woff +0 -0
  25. package/src/assets/inter-v12-latin/inter-v12-latin-900.woff2 +0 -0
  26. package/src/assets/inter-v12-latin/inter-v12-latin-regular.woff +0 -0
  27. package/src/assets/inter-v12-latin/inter-v12-latin-regular.woff2 +0 -0
  28. package/src/editor.module.css +3 -0
  29. package/src/extensions/Blocks/OrderedListPlugin.ts +46 -0
  30. package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +146 -0
  31. package/src/extensions/Blocks/commands/joinBackward.ts +274 -0
  32. package/src/extensions/Blocks/helpers/findBlock.ts +3 -0
  33. package/src/extensions/Blocks/helpers/setBlockHeading.ts +30 -0
  34. package/src/extensions/Blocks/index.ts +15 -0
  35. package/src/extensions/Blocks/nodes/Block.module.css +226 -0
  36. package/src/extensions/Blocks/nodes/Block.ts +390 -0
  37. package/src/extensions/Blocks/nodes/BlockGroup.ts +28 -0
  38. package/src/extensions/Blocks/nodes/Content.ts +50 -0
  39. package/src/extensions/Blocks/nodes/README.md +26 -0
  40. package/src/extensions/Blocks/rule.ts +48 -0
  41. package/src/extensions/BubbleMenu/BubbleMenuExtension.tsx +28 -0
  42. package/src/extensions/BubbleMenu/BubbleMenuPlugin.ts +245 -0
  43. package/src/extensions/BubbleMenu/component/BubbleMenu.tsx +216 -0
  44. package/src/extensions/BubbleMenu/component/DropdownBlockItem.module.css +13 -0
  45. package/src/extensions/BubbleMenu/component/DropdownBlockItem.tsx +25 -0
  46. package/src/extensions/BubbleMenu/component/LinkToolbarButton.tsx +67 -0
  47. package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +15 -0
  48. package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.tsx +266 -0
  49. package/src/extensions/DraggableBlocks/components/DragHandle.module.css +33 -0
  50. package/src/extensions/DraggableBlocks/components/DragHandle.tsx +108 -0
  51. package/src/extensions/DraggableBlocks/components/DragHandleMenu.module.css +10 -0
  52. package/src/extensions/DraggableBlocks/components/DragHandleMenu.tsx +18 -0
  53. package/src/extensions/Hyperlinks/HyperlinkMark.tsx +16 -0
  54. package/src/extensions/Hyperlinks/HyperlinkMenuPlugin.tsx +200 -0
  55. package/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.tsx +59 -0
  56. package/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.tsx +72 -0
  57. package/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.tsx +173 -0
  58. package/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.ts +36 -0
  59. package/src/extensions/Hyperlinks/menus/atlaskit/README.md +1 -0
  60. package/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.tsx +61 -0
  61. package/src/extensions/Paragraph/FixedParagraph.ts +12 -0
  62. package/src/extensions/Placeholder/PlaceholderExtension.ts +127 -0
  63. package/src/extensions/SlashMenu/SlashMenuExtension.ts +43 -0
  64. package/src/extensions/SlashMenu/SlashMenuItem.ts +56 -0
  65. package/src/extensions/SlashMenu/defaultCommands.tsx +229 -0
  66. package/src/extensions/SlashMenu/index.ts +11 -0
  67. package/src/extensions/TrailingNode/TrailingNodeExtension.ts +70 -0
  68. package/src/extensions/UniqueID/UniqueID.ts +281 -0
  69. package/src/extensions/helpers/formatKeyboardShortcut.ts +9 -0
  70. package/src/fonts-inter.css +94 -0
  71. package/src/globals.css +28 -0
  72. package/src/index.ts +5 -0
  73. package/src/lib/atlaskit/browser.ts +47 -0
  74. package/src/root.module.css +19 -0
  75. package/src/shared/components/toolbar/SimpleToolbarButton.module.css +13 -0
  76. package/src/shared/components/toolbar/SimpleToolbarButton.tsx +56 -0
  77. package/src/shared/components/toolbar/Toolbar.module.css +10 -0
  78. package/src/shared/components/toolbar/Toolbar.tsx +5 -0
  79. package/src/shared/components/toolbar/ToolbarSeparator.module.css +13 -0
  80. package/src/shared/components/toolbar/ToolbarSeparator.tsx +7 -0
  81. package/src/shared/components/tooltip/TooltipContent.module.css +15 -0
  82. package/src/shared/components/tooltip/TooltipContent.tsx +23 -0
  83. package/src/shared/hooks/useEditorForceUpdate.tsx +30 -0
  84. package/src/shared/plugins/suggestion/SuggestionItem.ts +31 -0
  85. package/src/shared/plugins/suggestion/SuggestionListReactRenderer.ts +227 -0
  86. package/src/shared/plugins/suggestion/SuggestionPlugin.ts +365 -0
  87. package/src/shared/plugins/suggestion/components/SuggestionGroup.module.css +45 -0
  88. package/src/shared/plugins/suggestion/components/SuggestionGroup.tsx +134 -0
  89. package/src/shared/plugins/suggestion/components/SuggestionList.module.css +10 -0
  90. package/src/shared/plugins/suggestion/components/SuggestionList.tsx +91 -0
  91. package/src/style.css +7 -0
  92. package/src/useEditor.ts +47 -0
  93. package/src/vite-env.d.ts +1 -0
  94. package/types/src/BlockNoteExtensions.d.ts +4 -0
  95. package/types/src/EditorContent.d.ts +1 -0
  96. package/types/src/extensions/Blocks/OrderedListPlugin.d.ts +2 -0
  97. package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +13 -0
  98. package/types/src/extensions/Blocks/commands/joinBackward.d.ts +14 -0
  99. package/types/src/extensions/Blocks/helpers/findBlock.d.ts +6 -0
  100. package/types/src/extensions/Blocks/helpers/setBlockHeading.d.ts +5 -0
  101. package/types/src/extensions/Blocks/index.d.ts +1 -0
  102. package/types/src/extensions/Blocks/nodes/Block.d.ts +32 -0
  103. package/types/src/extensions/Blocks/nodes/BlockGroup.d.ts +2 -0
  104. package/types/src/extensions/Blocks/nodes/Content.d.ts +5 -0
  105. package/types/src/extensions/Blocks/rule.d.ts +16 -0
  106. package/types/src/extensions/BubbleMenu/BubbleMenuExtension.d.ts +5 -0
  107. package/types/src/extensions/BubbleMenu/BubbleMenuPlugin.d.ts +46 -0
  108. package/types/src/extensions/BubbleMenu/component/BubbleMenu.d.ts +5 -0
  109. package/types/src/extensions/BubbleMenu/component/DropdownBlockItem.d.ts +10 -0
  110. package/types/src/extensions/BubbleMenu/component/LinkToolbarButton.d.ts +11 -0
  111. package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +7 -0
  112. package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +18 -0
  113. package/types/src/extensions/DraggableBlocks/components/DragHandle.d.ts +12 -0
  114. package/types/src/extensions/DraggableBlocks/components/DragHandleMenu.d.ts +6 -0
  115. package/types/src/extensions/Hyperlinks/HyperlinkMark.d.ts +7 -0
  116. package/types/src/extensions/Hyperlinks/HyperlinkMenuPlugin.d.ts +2 -0
  117. package/types/src/extensions/Hyperlinks/menus/HyperlinkBasicMenu.d.ts +12 -0
  118. package/types/src/extensions/Hyperlinks/menus/HyperlinkEditMenu.d.ts +10 -0
  119. package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInput.d.ts +39 -0
  120. package/types/src/extensions/Hyperlinks/menus/atlaskit/PanelTextInputStyles.d.ts +1 -0
  121. package/types/src/extensions/Hyperlinks/menus/atlaskit/ToolbarComponent.d.ts +11 -0
  122. package/types/src/extensions/Paragraph/FixedParagraph.d.ts +1 -0
  123. package/types/src/extensions/Placeholder/PlaceholderExtension.d.ts +25 -0
  124. package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +10 -0
  125. package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +43 -0
  126. package/types/src/extensions/SlashMenu/defaultCommands.d.ts +8 -0
  127. package/types/src/extensions/SlashMenu/index.d.ts +5 -0
  128. package/types/src/extensions/TrailingNode/TrailingNodeExtension.d.ts +10 -0
  129. package/types/src/extensions/UniqueID/UniqueID.d.ts +3 -0
  130. package/types/src/extensions/helpers/formatKeyboardShortcut.d.ts +1 -0
  131. package/types/src/index.d.ts +4 -0
  132. package/types/src/lib/atlaskit/browser.d.ts +12 -0
  133. package/types/src/shared/components/toolbar/SimpleToolbarButton.d.ts +16 -0
  134. package/types/src/shared/components/toolbar/Toolbar.d.ts +4 -0
  135. package/types/src/shared/components/toolbar/ToolbarSeparator.d.ts +2 -0
  136. package/types/src/shared/components/tooltip/TooltipContent.d.ts +15 -0
  137. package/types/src/shared/hooks/useEditorForceUpdate.d.ts +2 -0
  138. package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +29 -0
  139. package/types/src/shared/plugins/suggestion/SuggestionListReactRenderer.d.ts +71 -0
  140. package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +74 -0
  141. package/types/src/shared/plugins/suggestion/components/SuggestionGroup.d.ts +23 -0
  142. package/types/src/shared/plugins/suggestion/components/SuggestionList.d.ts +26 -0
  143. 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,9 @@
1
+ import browser from "../../lib/atlaskit/browser";
2
+
3
+ export default function formatKeyboardShortcut(shortcut: string) {
4
+ if (browser.ios || browser.mac) {
5
+ return shortcut.replace("Mod", "⌘");
6
+ } else {
7
+ return shortcut.replace("Mod", "Ctrl");
8
+ }
9
+ }
@@ -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
+ }