@blocknote/core 0.9.0 → 0.9.2

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 (37) hide show
  1. package/dist/blocknote.js +337 -298
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +5 -4
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/package.json +2 -2
  6. package/src/BlockNoteEditor.ts +2 -2
  7. package/src/BlockNoteExtensions.ts +24 -22
  8. package/src/api/blockManipulation/blockManipulation.test.ts +2 -2
  9. package/src/api/blockManipulation/blockManipulation.ts +1 -1
  10. package/src/api/formatConversions/formatConversions.test.ts +2 -2
  11. package/src/api/formatConversions/formatConversions.ts +47 -3
  12. package/src/api/nodeConversions/nodeConversions.test.ts +6 -6
  13. package/src/api/nodeConversions/nodeConversions.ts +6 -6
  14. package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +2 -2
  15. package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +27 -5
  16. package/src/extensions/Blocks/nodes/BlockContainer.ts +5 -5
  17. package/src/extensions/SideMenu/MultipleNodeSelection.ts +3 -3
  18. package/src/extensions/SideMenu/SideMenuPlugin.ts +9 -9
  19. package/src/extensions/UniqueID/UniqueID.ts +10 -9
  20. package/src/shared/EventEmitter.ts +1 -0
  21. package/src/shared/plugins/suggestion/SuggestionPlugin.ts +6 -2
  22. package/types/src/extensions/Blocks/helpers/getBlockInfoFromPos.d.ts +9 -1
  23. package/types/src/extensions/Blocks/nodes/TableCell.d.ts +5 -0
  24. package/types/src/extensions/Blocks/nodes/TableRow.d.ts +5 -0
  25. package/types/src/extensions/SideMenu/MultipleNodeSelection.d.ts +1 -1
  26. package/types/src/EventEmitter.d.ts +0 -11
  27. package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +0 -0
  28. package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +0 -16
  29. package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +0 -55
  30. package/types/src/extensions/DraggableBlocks/MultipleNodeSelection.d.ts +0 -24
  31. package/types/src/extensions/FormattingToolbar/FormattingToolbarExtension.d.ts +0 -11
  32. package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +0 -10
  33. package/types/src/extensions/HyperlinkToolbar/HyperlinkMark.d.ts +0 -8
  34. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +0 -0
  35. package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +0 -13
  36. package/types/src/extensions/SlashMenu/index.d.ts +0 -3
  37. package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +0 -12
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "homepage": "https://github.com/TypeCellOS/BlockNote",
4
4
  "private": false,
5
5
  "license": "MPL-2.0",
6
- "version": "0.9.0",
6
+ "version": "0.9.2",
7
7
  "files": [
8
8
  "dist",
9
9
  "types",
@@ -109,5 +109,5 @@
109
109
  "access": "public",
110
110
  "registry": "https://registry.npmjs.org/"
111
111
  },
112
- "gitHead": "75d9591eef6f06f78bdd8dadc32d0ee66c57c4d2"
112
+ "gitHead": "4d18bc8a01e841954672b9e522f20ce12f4ada10"
113
113
  }
@@ -353,7 +353,7 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
353
353
  */
354
354
  public forEachBlock(
355
355
  callback: (block: Block<BSchema>) => boolean,
356
- reverse: boolean = false
356
+ reverse = false
357
357
  ): void {
358
358
  const blocks = this.topLevelBlocks.slice();
359
359
 
@@ -692,7 +692,7 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
692
692
  return;
693
693
  }
694
694
 
695
- let { from, to } = this._tiptapEditor.state.selection;
695
+ const { from, to } = this._tiptapEditor.state.selection;
696
696
 
697
697
  if (!text) {
698
698
  text = this._tiptapEditor.state.doc.textBetween(from, to);
@@ -118,32 +118,34 @@ export const getBlockNoteExtensions = <BSchema extends BlockSchema>(opts: {
118
118
  fragment: opts.collaboration.fragment,
119
119
  })
120
120
  );
121
- const defaultRender = (user: { color: string; name: string }) => {
122
- const cursor = document.createElement("span");
121
+ if (opts.collaboration.provider?.awareness) {
122
+ const defaultRender = (user: { color: string; name: string }) => {
123
+ const cursor = document.createElement("span");
123
124
 
124
- cursor.classList.add(styles["collaboration-cursor__caret"]);
125
- cursor.setAttribute("style", `border-color: ${user.color}`);
125
+ cursor.classList.add(styles["collaboration-cursor__caret"]);
126
+ cursor.setAttribute("style", `border-color: ${user.color}`);
126
127
 
127
- const label = document.createElement("span");
128
+ const label = document.createElement("span");
128
129
 
129
- label.classList.add(styles["collaboration-cursor__label"]);
130
- label.setAttribute("style", `background-color: ${user.color}`);
131
- label.insertBefore(document.createTextNode(user.name), null);
130
+ label.classList.add(styles["collaboration-cursor__label"]);
131
+ label.setAttribute("style", `background-color: ${user.color}`);
132
+ label.insertBefore(document.createTextNode(user.name), null);
132
133
 
133
- const nonbreakingSpace1 = document.createTextNode("\u2060");
134
- const nonbreakingSpace2 = document.createTextNode("\u2060");
135
- cursor.insertBefore(nonbreakingSpace1, null);
136
- cursor.insertBefore(label, null);
137
- cursor.insertBefore(nonbreakingSpace2, null);
138
- return cursor;
139
- };
140
- ret.push(
141
- CollaborationCursor.configure({
142
- user: opts.collaboration.user,
143
- render: opts.collaboration.renderCursor || defaultRender,
144
- provider: opts.collaboration.provider,
145
- })
146
- );
134
+ const nonbreakingSpace1 = document.createTextNode("\u2060");
135
+ const nonbreakingSpace2 = document.createTextNode("\u2060");
136
+ cursor.insertBefore(nonbreakingSpace1, null);
137
+ cursor.insertBefore(label, null);
138
+ cursor.insertBefore(nonbreakingSpace2, null);
139
+ return cursor;
140
+ };
141
+ ret.push(
142
+ CollaborationCursor.configure({
143
+ user: opts.collaboration.user,
144
+ render: opts.collaboration.renderCursor || defaultRender,
145
+ provider: opts.collaboration.provider,
146
+ })
147
+ );
148
+ }
147
149
  } else {
148
150
  // disable history extension when collaboration is enabled as Yjs takes care of undo / redo
149
151
  ret.push(History);
@@ -24,7 +24,7 @@ let insert: (
24
24
  ) => Block<DefaultBlockSchema>[];
25
25
 
26
26
  beforeEach(() => {
27
- (window as Window & { __TEST_OPTIONS?: {} }).__TEST_OPTIONS = {};
27
+ (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS = {};
28
28
 
29
29
  editor = new BlockNoteEditor();
30
30
 
@@ -80,7 +80,7 @@ afterEach(() => {
80
80
  editor._tiptapEditor.destroy();
81
81
  editor = undefined as any;
82
82
 
83
- delete (window as Window & { __TEST_OPTIONS?: {} }).__TEST_OPTIONS;
83
+ delete (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS;
84
84
  });
85
85
 
86
86
  describe("Inserting Blocks with Different Placements", () => {
@@ -107,7 +107,7 @@ export function removeBlocks(
107
107
  });
108
108
 
109
109
  if (idsOfBlocksToRemove.size > 0) {
110
- let notFoundIds = [...idsOfBlocksToRemove].join("\n");
110
+ const notFoundIds = [...idsOfBlocksToRemove].join("\n");
111
111
 
112
112
  throw Error(
113
113
  "Blocks with the following IDs could not be found in the editor: " +
@@ -579,7 +579,7 @@ function removeInlineContentClass(html: string) {
579
579
  }
580
580
 
581
581
  beforeEach(() => {
582
- (window as Window & { __TEST_OPTIONS?: {} }).__TEST_OPTIONS = {};
582
+ (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS = {};
583
583
 
584
584
  editor = new BlockNoteEditor();
585
585
  });
@@ -588,7 +588,7 @@ afterEach(() => {
588
588
  editor._tiptapEditor.destroy();
589
589
  editor = undefined as any;
590
590
 
591
- delete (window as Window & { __TEST_OPTIONS?: {} }).__TEST_OPTIONS;
591
+ delete (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS;
592
592
  });
593
593
 
594
594
  describe("Non-Nested Block/HTML/Markdown Conversions", () => {
@@ -4,7 +4,7 @@ import rehypeRemark from "rehype-remark";
4
4
  import rehypeStringify from "rehype-stringify";
5
5
  import remarkGfm from "remark-gfm";
6
6
  import remarkParse from "remark-parse";
7
- import remarkRehype from "remark-rehype";
7
+ import remarkRehype, { defaultHandlers } from "remark-rehype";
8
8
  import remarkStringify from "remark-stringify";
9
9
  import { unified } from "unified";
10
10
  import { Block, BlockSchema } from "../../extensions/Blocks/api/blockTypes";
@@ -47,7 +47,7 @@ export async function HTMLToBlocks<BSchema extends BlockSchema>(
47
47
  htmlNode.innerHTML = html.trim();
48
48
 
49
49
  const parser = DOMParser.fromSchema(schema);
50
- const parentNode = parser.parse(htmlNode);
50
+ const parentNode = parser.parse(htmlNode); //, { preserveWhitespace: "full" });
51
51
 
52
52
  const blocks: Block<BSchema>[] = [];
53
53
 
@@ -73,6 +73,45 @@ export async function blocksToMarkdown<BSchema extends BlockSchema>(
73
73
  return markdownString.value as string;
74
74
  }
75
75
 
76
+ // modefied version of https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js
77
+ // that outputs a data-language attribute instead of a CSS class (e.g.: language-typescript)
78
+ function code(state: any, node: any) {
79
+ const value = node.value ? node.value + "\n" : "";
80
+ /** @type {Properties} */
81
+ const properties: any = {};
82
+
83
+ if (node.lang) {
84
+ // changed line
85
+ properties["data-language"] = node.lang;
86
+ }
87
+
88
+ // Create `<code>`.
89
+ /** @type {Element} */
90
+ let result: any = {
91
+ type: "element",
92
+ tagName: "code",
93
+ properties,
94
+ children: [{ type: "text", value }],
95
+ };
96
+
97
+ if (node.meta) {
98
+ result.data = { meta: node.meta };
99
+ }
100
+
101
+ state.patch(node, result);
102
+ result = state.applyData(node, result);
103
+
104
+ // Create `<pre>`.
105
+ result = {
106
+ type: "element",
107
+ tagName: "pre",
108
+ properties: {},
109
+ children: [result],
110
+ };
111
+ state.patch(node, result);
112
+ return result;
113
+ }
114
+
76
115
  export async function markdownToBlocks<BSchema extends BlockSchema>(
77
116
  markdown: string,
78
117
  blockSchema: BSchema,
@@ -81,7 +120,12 @@ export async function markdownToBlocks<BSchema extends BlockSchema>(
81
120
  const htmlString = await unified()
82
121
  .use(remarkParse)
83
122
  .use(remarkGfm)
84
- .use(remarkRehype)
123
+ .use(remarkRehype, {
124
+ handlers: {
125
+ ...(defaultHandlers as any),
126
+ code,
127
+ },
128
+ })
85
129
  .use(rehypeStringify)
86
130
  .process(markdown);
87
131
 
@@ -1,19 +1,19 @@
1
1
  import { Editor } from "@tiptap/core";
2
2
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
3
3
  import { BlockNoteEditor, PartialBlock } from "../..";
4
- import UniqueID from "../../extensions/UniqueID/UniqueID";
5
- import { blockToNode, nodeToBlock } from "./nodeConversions";
6
- import { partialBlockToBlockForTesting } from "./testUtil";
7
4
  import {
8
- defaultBlockSchema,
9
5
  DefaultBlockSchema,
6
+ defaultBlockSchema,
10
7
  } from "../../extensions/Blocks/api/defaultBlocks";
8
+ import UniqueID from "../../extensions/UniqueID/UniqueID";
9
+ import { blockToNode, nodeToBlock } from "./nodeConversions";
10
+ import { partialBlockToBlockForTesting } from "./testUtil";
11
11
 
12
12
  let editor: BlockNoteEditor;
13
13
  let tt: Editor;
14
14
 
15
15
  beforeEach(() => {
16
- (window as Window & { __TEST_OPTIONS?: {} }).__TEST_OPTIONS = {};
16
+ (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS = {};
17
17
 
18
18
  editor = new BlockNoteEditor();
19
19
  tt = editor._tiptapEditor;
@@ -24,7 +24,7 @@ afterEach(() => {
24
24
  editor = undefined as any;
25
25
  tt = undefined as any;
26
26
 
27
- delete (window as Window & { __TEST_OPTIONS?: {} }).__TEST_OPTIONS;
27
+ delete (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS;
28
28
  });
29
29
 
30
30
  describe("Simple ProseMirror Node Conversions", () => {
@@ -16,9 +16,9 @@ import {
16
16
  Styles,
17
17
  ToggledStyle,
18
18
  } from "../../extensions/Blocks/api/inlineContentTypes";
19
- import { getBlockInfoFromPos } from "../../extensions/Blocks/helpers/getBlockInfoFromPos";
20
19
  import UniqueID from "../../extensions/UniqueID/UniqueID";
21
20
  import { UnreachableCaseError } from "../../shared/utils";
21
+ import { getBlockInfo } from "../../extensions/Blocks/helpers/getBlockInfoFromPos";
22
22
 
23
23
  const toggleStyles = new Set<ToggledStyle>([
24
24
  "bold",
@@ -91,7 +91,7 @@ function styledTextArrayToNodes(
91
91
  content: string | StyledText[],
92
92
  schema: Schema
93
93
  ): Node[] {
94
- let nodes: Node[] = [];
94
+ const nodes: Node[] = [];
95
95
 
96
96
  if (typeof content === "string") {
97
97
  nodes.push(
@@ -113,7 +113,7 @@ export function inlineContentToNodes(
113
113
  blockContent: PartialInlineContent[],
114
114
  schema: Schema
115
115
  ): Node[] {
116
- let nodes: Node[] = [];
116
+ const nodes: Node[] = [];
117
117
 
118
118
  for (const content of blockContent) {
119
119
  if (content.type === "link") {
@@ -369,7 +369,7 @@ export function nodeToBlock<BSchema extends BlockSchema>(
369
369
  return cachedBlock;
370
370
  }
371
371
 
372
- const blockInfo = getBlockInfoFromPos(node, 0)!;
372
+ const blockInfo = getBlockInfo(node);
373
373
 
374
374
  let id = blockInfo.id;
375
375
 
@@ -380,7 +380,7 @@ export function nodeToBlock<BSchema extends BlockSchema>(
380
380
 
381
381
  const props: any = {};
382
382
  for (const [attr, value] of Object.entries({
383
- ...blockInfo.node.attrs,
383
+ ...node.attrs,
384
384
  ...blockInfo.contentNode.attrs,
385
385
  })) {
386
386
  const blockSpec = blockSchema[blockInfo.contentType.name];
@@ -414,7 +414,7 @@ export function nodeToBlock<BSchema extends BlockSchema>(
414
414
  const children: Block<BSchema>[] = [];
415
415
  for (let i = 0; i < blockInfo.numChildBlocks; i++) {
416
416
  children.push(
417
- nodeToBlock(blockInfo.node.lastChild!.child(i), blockSchema, blockCache)
417
+ nodeToBlock(node.lastChild!.child(i), blockSchema, blockCache)
418
418
  );
419
419
  }
420
420
 
@@ -96,7 +96,7 @@ export const PreviousBlockTypePlugin = () => {
96
96
  const newNodes = findChildren(newState.doc, (node) => node.attrs.id);
97
97
 
98
98
  // Traverses all block containers in the new editor state.
99
- for (let node of newNodes) {
99
+ for (const node of newNodes) {
100
100
  const oldNode = oldNodesById.get(node.node.attrs.id);
101
101
 
102
102
  const oldContentNode = oldNode?.node.firstChild;
@@ -192,7 +192,7 @@ export const PreviousBlockTypePlugin = () => {
192
192
  pluginState.currentTransactionOldBlockAttrs[node.attrs.id];
193
193
  const decorationAttrs: any = {};
194
194
 
195
- for (let [nodeAttr, val] of Object.entries(prevAttrs)) {
195
+ for (const [nodeAttr, val] of Object.entries(prevAttrs)) {
196
196
  decorationAttrs["data-prev-" + nodeAttributes[nodeAttr]] =
197
197
  val || "none";
198
198
  }
@@ -1,16 +1,40 @@
1
1
  import { Node, NodeType } from "prosemirror-model";
2
2
 
3
- export type BlockInfo = {
3
+ export type BlockInfoWithoutPositions = {
4
4
  id: string;
5
5
  node: Node;
6
6
  contentNode: Node;
7
7
  contentType: NodeType;
8
8
  numChildBlocks: number;
9
+ };
10
+
11
+ export type BlockInfo = BlockInfoWithoutPositions & {
9
12
  startPos: number;
10
13
  endPos: number;
11
14
  depth: number;
12
15
  };
13
16
 
17
+ /**
18
+ * Helper function for `getBlockInfoFromPos`, returns information regarding
19
+ * provided blockContainer node.
20
+ * @param blockContainer The blockContainer node to retrieve info for.
21
+ */
22
+ export function getBlockInfo(blockContainer: Node): BlockInfoWithoutPositions {
23
+ const id = blockContainer.attrs["id"];
24
+ const contentNode = blockContainer.firstChild!;
25
+ const contentType = contentNode.type;
26
+ const numChildBlocks =
27
+ blockContainer.childCount === 2 ? blockContainer.lastChild!.childCount : 0;
28
+
29
+ return {
30
+ id,
31
+ node: blockContainer,
32
+ contentNode,
33
+ contentType,
34
+ numChildBlocks,
35
+ };
36
+ }
37
+
14
38
  /**
15
39
  * Retrieves information regarding the nearest blockContainer node in a
16
40
  * ProseMirror doc, relative to a position.
@@ -56,6 +80,7 @@ export function getBlockInfoFromPos(doc: Node, pos: number): BlockInfo {
56
80
  let node = $pos.node(maxDepth);
57
81
  let depth = maxDepth;
58
82
 
83
+ // eslint-disable-next-line no-constant-condition
59
84
  while (true) {
60
85
  if (depth < 0) {
61
86
  throw new Error(
@@ -71,10 +96,7 @@ export function getBlockInfoFromPos(doc: Node, pos: number): BlockInfo {
71
96
  node = $pos.node(depth);
72
97
  }
73
98
 
74
- const id = node.attrs["id"];
75
- const contentNode = node.firstChild!;
76
- const contentType = contentNode.type;
77
- const numChildBlocks = node.childCount === 2 ? node.lastChild!.childCount : 0;
99
+ const { id, contentNode, contentType, numChildBlocks } = getBlockInfo(node);
78
100
 
79
101
  const startPos = $pos.start(depth);
80
102
  const endPos = $pos.end(depth);
@@ -6,15 +6,15 @@ import {
6
6
  inlineContentToNodes,
7
7
  } from "../../../api/nodeConversions/nodeConversions";
8
8
 
9
- import { getBlockInfoFromPos } from "../helpers/getBlockInfoFromPos";
10
- import { PreviousBlockTypePlugin } from "../PreviousBlockTypePlugin";
11
- import styles from "./Block.module.css";
12
- import BlockAttributes from "./BlockAttributes";
13
9
  import {
14
10
  BlockNoteDOMAttributes,
15
11
  BlockSchema,
16
12
  PartialBlock,
17
13
  } from "../api/blockTypes";
14
+ import { getBlockInfoFromPos } from "../helpers/getBlockInfoFromPos";
15
+ import { PreviousBlockTypePlugin } from "../PreviousBlockTypePlugin";
16
+ import styles from "./Block.module.css";
17
+ import BlockAttributes from "./BlockAttributes";
18
18
  import { mergeCSSClasses } from "../../../shared/utils";
19
19
 
20
20
  declare module "@tiptap/core" {
@@ -60,7 +60,7 @@ export const BlockContainer = Node.create<{
60
60
  }
61
61
 
62
62
  const attrs: Record<string, string> = {};
63
- for (let [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {
63
+ for (const [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {
64
64
  if (element.getAttribute(HTMLAttr)) {
65
65
  attrs[nodeAttr] = element.getAttribute(HTMLAttr)!;
66
66
  }
@@ -1,5 +1,5 @@
1
- import { Selection } from "prosemirror-state";
2
1
  import { Fragment, Node, ResolvedPos, Slice } from "prosemirror-model";
2
+ import { Selection } from "prosemirror-state";
3
3
  import { Mappable } from "prosemirror-transform";
4
4
 
5
5
  /**
@@ -64,8 +64,8 @@ export class MultipleNodeSelection extends Selection {
64
64
  }
65
65
 
66
66
  map(doc: Node, mapping: Mappable): Selection {
67
- let fromResult = mapping.mapResult(this.from);
68
- let toResult = mapping.mapResult(this.to);
67
+ const fromResult = mapping.mapResult(this.from);
68
+ const toResult = mapping.mapResult(this.to);
69
69
 
70
70
  if (toResult.deleted) {
71
71
  return Selection.near(doc.resolve(fromResult.pos));
@@ -32,7 +32,7 @@ function getDraggableBlockFromCoords(
32
32
  return undefined;
33
33
  }
34
34
 
35
- let pos = view.posAtCoords(coords);
35
+ const pos = view.posAtCoords(coords);
36
36
  if (!pos) {
37
37
  return undefined;
38
38
  }
@@ -61,12 +61,12 @@ function blockPositionFromCoords(
61
61
  coords: { left: number; top: number },
62
62
  view: EditorView
63
63
  ) {
64
- let block = getDraggableBlockFromCoords(coords, view);
64
+ const block = getDraggableBlockFromCoords(coords, view);
65
65
 
66
66
  if (block && block.node.nodeType === 1) {
67
67
  // TODO: this uses undocumented PM APIs? do we need this / let's add docs?
68
68
  const docView = (view as any).docView;
69
- let desc = docView.nearestDesc(block.node, true);
69
+ const desc = docView.nearestDesc(block.node, true);
70
70
  if (!desc || desc === docView) {
71
71
  return null;
72
72
  }
@@ -186,12 +186,12 @@ function dragStart(
186
186
 
187
187
  const editorBoundingBox = view.dom.getBoundingClientRect();
188
188
 
189
- let coords = {
189
+ const coords = {
190
190
  left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor
191
191
  top: e.clientY,
192
192
  };
193
193
 
194
- let pos = blockPositionFromCoords(coords, view);
194
+ const pos = blockPositionFromCoords(coords, view);
195
195
  if (pos != null) {
196
196
  const selection = view.state.selection;
197
197
  const doc = view.state.doc;
@@ -215,8 +215,8 @@ function dragStart(
215
215
  setDragImage(view, pos);
216
216
  }
217
217
 
218
- let slice = view.state.selection.content();
219
- let { dom, text } = serializeForClipboard(view, slice);
218
+ const slice = view.state.selection.content();
219
+ const { dom, text } = serializeForClipboard(view, slice);
220
220
 
221
221
  e.dataTransfer.clearData();
222
222
  e.dataTransfer.setData("text/html", dom.innerHTML);
@@ -288,7 +288,7 @@ export class SideMenuView<BSchema extends BlockSchema> implements PluginView {
288
288
  return;
289
289
  }
290
290
 
291
- let pos = this.pmView.posAtCoords({
291
+ const pos = this.pmView.posAtCoords({
292
292
  left: event.clientX,
293
293
  top: event.clientY,
294
294
  });
@@ -319,7 +319,7 @@ export class SideMenuView<BSchema extends BlockSchema> implements PluginView {
319
319
  if ((event as any).synthetic || !this.isDragging) {
320
320
  return;
321
321
  }
322
- let pos = this.pmView.posAtCoords({
322
+ const pos = this.pmView.posAtCoords({
323
323
  left: event.clientX,
324
324
  top: event.clientY,
325
325
  });
@@ -52,14 +52,15 @@ const UniqueID = Extension.create({
52
52
  types: [],
53
53
  generateID: () => {
54
54
  // Use mock ID if tests are running.
55
- if ((window as any).__TEST_OPTIONS) {
56
- if ((window as any).__TEST_OPTIONS.mockID === undefined) {
57
- (window as any).__TEST_OPTIONS.mockID = 0;
55
+ if (typeof window !== "undefined" && (window as any).__TEST_OPTIONS) {
56
+ const testOptions = (window as any).__TEST_OPTIONS;
57
+ if (testOptions.mockID === undefined) {
58
+ testOptions.mockID = 0;
58
59
  } else {
59
- (window as any).__TEST_OPTIONS.mockID++;
60
+ testOptions.mockID++;
60
61
  }
61
62
 
62
- return (window as any).__TEST_OPTIONS.mockID.toString() as string;
63
+ return testOptions.mockID.toString() as string;
63
64
  }
64
65
 
65
66
  return v4();
@@ -129,7 +130,7 @@ const UniqueID = Extension.create({
129
130
  const filterTransactions =
130
131
  this.options.filterTransaction &&
131
132
  transactions.some((tr) => {
132
- var _a, _b;
133
+ let _a, _b;
133
134
  return !((_b = (_a = this.options).filterTransaction) === null ||
134
135
  _b === void 0
135
136
  ? void 0
@@ -161,7 +162,7 @@ const UniqueID = Extension.create({
161
162
  .filter((id) => id !== null);
162
163
  const duplicatedNewIds = findDuplicates(newIds);
163
164
  newNodes.forEach(({ node, pos }) => {
164
- var _a;
165
+ let _a;
165
166
  // instead of checking `node.attrs[attributeName]` directly
166
167
  // we look at the current state of the node within `tr.doc`.
167
168
  // this helps to prevent adding new ids to the same node
@@ -196,7 +197,7 @@ const UniqueID = Extension.create({
196
197
  // we register a global drag handler to track the current drag source element
197
198
  view(view) {
198
199
  const handleDragstart = (event: any) => {
199
- var _a;
200
+ let _a;
200
201
  dragSourceElement = (
201
202
  (_a = view.dom.parentElement) === null || _a === void 0
202
203
  ? void 0
@@ -219,7 +220,7 @@ const UniqueID = Extension.create({
219
220
  // only create new ids for dropped content while holding `alt`
220
221
  // or content is dragged from another editor
221
222
  drop: (view, event: any) => {
222
- var _a;
223
+ let _a;
223
224
  if (
224
225
  dragSourceElement !== view.dom.parentElement ||
225
226
  ((_a = event.dataTransfer) === null || _a === void 0
@@ -11,6 +11,7 @@ type CallbackFunction<
11
11
  > = (...props: CallbackType<T, EventName>) => any;
12
12
 
13
13
  export class EventEmitter<T extends Record<string, any>> {
14
+ // eslint-disable-next-line @typescript-eslint/ban-types
14
15
  private callbacks: { [key: string]: Function[] } = {};
15
16
 
16
17
  public on<EventName extends StringKeyOf<T>>(
@@ -28,7 +28,9 @@ class SuggestionsMenuView<
28
28
  private readonly pluginKey: PluginKey,
29
29
  updateSuggestionsMenu: (
30
30
  suggestionsMenuState: SuggestionsMenuState<T>
31
- ) => void = () => {}
31
+ ) => void = () => {
32
+ // noop
33
+ }
32
34
  ) {
33
35
  this.pluginState = getDefaultPluginState<T>();
34
36
 
@@ -158,7 +160,9 @@ export const setupSuggestionsMenu = <
158
160
  onSelectItem: (props: {
159
161
  item: T;
160
162
  editor: BlockNoteEditor<BSchema>;
161
- }) => void = () => {}
163
+ }) => void = () => {
164
+ // noop
165
+ }
162
166
  ) => {
163
167
  // Assertions
164
168
  if (defaultTriggerCharacter.length !== 1) {
@@ -1,14 +1,22 @@
1
1
  import { Node, NodeType } from "prosemirror-model";
2
- export type BlockInfo = {
2
+ export type BlockInfoWithoutPositions = {
3
3
  id: string;
4
4
  node: Node;
5
5
  contentNode: Node;
6
6
  contentType: NodeType;
7
7
  numChildBlocks: number;
8
+ };
9
+ export type BlockInfo = BlockInfoWithoutPositions & {
8
10
  startPos: number;
9
11
  endPos: number;
10
12
  depth: number;
11
13
  };
14
+ /**
15
+ * Helper function for `getBlockInfoFromPos`, returns information regarding
16
+ * provided blockContainer node.
17
+ * @param blockContainer The blockContainer node to retrieve info for.
18
+ */
19
+ export declare function getBlockInfo(blockContainer: Node): BlockInfoWithoutPositions;
12
20
  /**
13
21
  * Retrieves information regarding the nearest blockContainer node in a
14
22
  * ProseMirror doc, relative to a position.
@@ -0,0 +1,5 @@
1
+ import { Node } from "@tiptap/core";
2
+ export interface TableCellOptions {
3
+ HTMLAttributes: Record<string, any>;
4
+ }
5
+ export declare const TableCell: Node<TableCellOptions, any>;
@@ -0,0 +1,5 @@
1
+ import { Node } from "@tiptap/core";
2
+ export interface TableRowOptions {
3
+ HTMLAttributes: Record<string, any>;
4
+ }
5
+ export declare const TableRow: Node<TableRowOptions, any>;
@@ -1,5 +1,5 @@
1
- import { Selection } from "prosemirror-state";
2
1
  import { Node, ResolvedPos, Slice } from "prosemirror-model";
2
+ import { Selection } from "prosemirror-state";
3
3
  import { Mappable } from "prosemirror-transform";
4
4
  /**
5
5
  * This class represents an editor selection which spans multiple nodes/blocks. It's currently only used to allow users
@@ -1,11 +0,0 @@
1
- type StringKeyOf<T> = Extract<keyof T, string>;
2
- type CallbackType<T extends Record<string, any>, EventName extends StringKeyOf<T>> = T[EventName] extends any[] ? T[EventName] : [T[EventName]];
3
- type CallbackFunction<T extends Record<string, any>, EventName extends StringKeyOf<T>> = (...props: CallbackType<T, EventName>) => any;
4
- export declare class EventEmitter<T extends Record<string, any>> {
5
- private callbacks;
6
- on<EventName extends StringKeyOf<T>>(event: EventName, fn: CallbackFunction<T, EventName>): this;
7
- protected emit<EventName extends StringKeyOf<T>>(event: EventName, ...args: CallbackType<T, EventName>): this;
8
- off<EventName extends StringKeyOf<T>>(event: EventName, fn?: CallbackFunction<T, EventName>): this;
9
- protected removeAllListeners(): void;
10
- }
11
- export {};