@blocknote/core 0.11.2 → 0.12.1

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 (138) hide show
  1. package/README.md +13 -17
  2. package/dist/blocknote.js +1662 -1447
  3. package/dist/blocknote.js.map +1 -1
  4. package/dist/blocknote.umd.cjs +6 -6
  5. package/dist/blocknote.umd.cjs.map +1 -1
  6. package/dist/style.css +1 -1
  7. package/dist/webpack-stats.json +1 -1
  8. package/package.json +7 -3
  9. package/src/api/blockManipulation/blockManipulation.test.ts +19 -15
  10. package/src/api/blockManipulation/blockManipulation.ts +107 -17
  11. package/src/api/exporters/html/externalHTMLExporter.ts +3 -7
  12. package/src/api/exporters/html/htmlConversion.test.ts +6 -3
  13. package/src/api/exporters/html/internalHTMLSerializer.ts +3 -7
  14. package/src/api/exporters/html/util/sharedHTMLConversion.ts +3 -3
  15. package/src/api/exporters/markdown/markdownExporter.test.ts +7 -3
  16. package/src/api/exporters/markdown/markdownExporter.ts +2 -6
  17. package/src/api/getCurrentBlockContentType.ts +14 -0
  18. package/src/api/nodeConversions/nodeConversions.test.ts +14 -7
  19. package/src/api/nodeConversions/nodeConversions.ts +1 -2
  20. package/src/api/parsers/html/parseHTML.test.ts +5 -1
  21. package/src/api/parsers/html/parseHTML.ts +2 -6
  22. package/src/api/parsers/html/util/nestedLists.ts +11 -1
  23. package/src/api/parsers/markdown/parseMarkdown.test.ts +3 -0
  24. package/src/api/parsers/markdown/parseMarkdown.ts +2 -6
  25. package/src/api/testUtil/cases/customBlocks.ts +18 -16
  26. package/src/api/testUtil/cases/customInlineContent.ts +12 -13
  27. package/src/api/testUtil/cases/customStyles.ts +12 -10
  28. package/src/api/testUtil/index.ts +4 -2
  29. package/src/api/testUtil/partialBlockTestUtil.ts +2 -6
  30. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +50 -21
  31. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +1 -2
  32. package/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +8 -1
  33. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +18 -5
  34. package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +7 -1
  35. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +18 -5
  36. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +14 -5
  37. package/src/blocks/defaultBlockHelpers.ts +3 -3
  38. package/src/blocks/defaultBlockTypeGuards.ts +84 -0
  39. package/src/blocks/defaultBlocks.ts +29 -3
  40. package/src/editor/Block.css +2 -31
  41. package/src/editor/BlockNoteEditor.ts +223 -267
  42. package/src/editor/BlockNoteExtensions.ts +5 -2
  43. package/src/editor/BlockNoteSchema.ts +98 -0
  44. package/src/editor/BlockNoteTipTapEditor.ts +162 -0
  45. package/src/editor/cursorPositionTypes.ts +2 -6
  46. package/src/editor/editor.css +0 -1
  47. package/src/editor/selectionTypes.ts +2 -6
  48. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +22 -29
  49. package/src/extensions/{ImageToolbar → ImagePanel}/ImageToolbarPlugin.ts +54 -60
  50. package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +330 -0
  51. package/src/extensions/Placeholder/PlaceholderExtension.ts +81 -88
  52. package/src/extensions/SideMenu/SideMenuPlugin.ts +55 -56
  53. package/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts +8 -0
  54. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +353 -0
  55. package/src/extensions/{SlashMenu/defaultSlashMenuItems.ts → SuggestionMenu/getDefaultSlashMenuItems.ts} +119 -89
  56. package/src/extensions/TableHandles/TableHandlesPlugin.ts +62 -45
  57. package/src/extensions-shared/UiElementPosition.ts +4 -0
  58. package/src/index.ts +8 -8
  59. package/src/pm-nodes/BlockContainer.ts +5 -5
  60. package/src/schema/blocks/types.ts +15 -15
  61. package/src/schema/inlineContent/createSpec.ts +2 -2
  62. package/src/schema/inlineContent/types.ts +1 -1
  63. package/src/util/browser.ts +6 -4
  64. package/src/util/typescript.ts +7 -4
  65. package/types/src/api/blockManipulation/blockManipulation.d.ts +6 -1
  66. package/types/src/api/exporters/html/externalHTMLExporter.d.ts +2 -1
  67. package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +2 -1
  68. package/types/src/api/exporters/markdown/markdownExporter.d.ts +2 -1
  69. package/types/src/api/getCurrentBlockContentType.d.ts +2 -0
  70. package/types/src/api/nodeConversions/nodeConversions.d.ts +2 -1
  71. package/types/src/api/parsers/html/parseHTML.d.ts +2 -1
  72. package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -1
  73. package/types/src/api/testUtil/cases/customBlocks.d.ts +72 -13
  74. package/types/src/api/testUtil/cases/customInlineContent.d.ts +281 -6
  75. package/types/src/api/testUtil/cases/customStyles.d.ts +247 -13
  76. package/types/src/api/testUtil/index.d.ts +4 -2
  77. package/types/src/api/testUtil/partialBlockTestUtil.d.ts +2 -1
  78. package/types/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +6 -1
  79. package/types/src/blocks/defaultBlockHelpers.d.ts +2 -2
  80. package/types/src/blocks/defaultBlockTypeGuards.d.ts +24 -0
  81. package/types/src/blocks/defaultBlocks.d.ts +21 -15
  82. package/types/src/editor/BlockNoteEditor.d.ts +51 -56
  83. package/types/src/editor/BlockNoteExtensions.d.ts +1 -0
  84. package/types/src/editor/BlockNoteSchema.d.ts +34 -0
  85. package/types/src/editor/BlockNoteTipTapEditor.d.ts +28 -0
  86. package/types/src/editor/cursorPositionTypes.d.ts +2 -1
  87. package/types/src/editor/selectionTypes.d.ts +2 -1
  88. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +5 -6
  89. package/types/src/extensions/ImagePanel/ImageToolbarPlugin.d.ts +32 -0
  90. package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +40 -0
  91. package/types/src/extensions/Placeholder/PlaceholderExtension.d.ts +2 -15
  92. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +8 -7
  93. package/types/src/extensions/SuggestionMenu/DefaultSuggestionItem.d.ts +8 -0
  94. package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +31 -0
  95. package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +10 -0
  96. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +7 -7
  97. package/types/src/extensions-shared/UiElementPosition.d.ts +4 -0
  98. package/types/src/index.d.ts +8 -8
  99. package/types/src/pm-nodes/BlockContainer.d.ts +3 -2
  100. package/types/src/pm-nodes/BlockGroup.d.ts +1 -1
  101. package/types/src/schema/blocks/types.d.ts +15 -15
  102. package/types/src/schema/inlineContent/types.d.ts +1 -1
  103. package/types/src/util/browser.d.ts +1 -0
  104. package/types/src/util/typescript.d.ts +1 -0
  105. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +0 -335
  106. package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +0 -12
  107. package/src/extensions/SlashMenu/SlashMenuPlugin.ts +0 -53
  108. package/src/extensions-shared/BaseUiElementTypes.ts +0 -8
  109. package/src/extensions-shared/README.md +0 -3
  110. package/src/extensions-shared/suggestion/SuggestionItem.ts +0 -3
  111. package/src/extensions-shared/suggestion/SuggestionPlugin.ts +0 -448
  112. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +0 -38
  113. package/types/src/extensions/ImageToolbar/ImageToolbarPlugin.d.ts +0 -31
  114. package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +0 -7
  115. package/types/src/extensions/SlashMenu/SlashMenuPlugin.d.ts +0 -13
  116. package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +0 -3
  117. package/types/src/extensions-shared/BaseUiElementTypes.d.ts +0 -7
  118. package/types/src/extensions-shared/suggestion/SuggestionItem.d.ts +0 -3
  119. package/types/src/extensions-shared/suggestion/SuggestionPlugin.d.ts +0 -36
  120. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-100.woff +0 -0
  121. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-100.woff2 +0 -0
  122. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-200.woff +0 -0
  123. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-200.woff2 +0 -0
  124. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-300.woff +0 -0
  125. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-300.woff2 +0 -0
  126. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-500.woff +0 -0
  127. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-500.woff2 +0 -0
  128. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-600.woff +0 -0
  129. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-600.woff2 +0 -0
  130. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-700.woff +0 -0
  131. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-700.woff2 +0 -0
  132. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-800.woff +0 -0
  133. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-800.woff2 +0 -0
  134. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-900.woff +0 -0
  135. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-900.woff2 +0 -0
  136. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-regular.woff +0 -0
  137. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-regular.woff2 +0 -0
  138. /package/src/{assets/fonts-inter.css → fonts/inter.css} +0 -0
@@ -1,11 +1,7 @@
1
1
  import { DOMParser, Schema } from "prosemirror-model";
2
- import {
3
- Block,
4
- BlockSchema,
5
- InlineContentSchema,
6
- StyleSchema,
7
- } from "../../../schema";
2
+ import { BlockSchema, InlineContentSchema, StyleSchema } from "../../../schema";
8
3
 
4
+ import { Block } from "../../../blocks/defaultBlocks";
9
5
  import { nodeToBlock } from "../../nodeConversions/nodeConversions";
10
6
  import { nestedListsToBlockNoteStructure } from "./util/nestedLists";
11
7
  export async function HTMLToBlocks<
@@ -99,11 +99,21 @@ function createGroups(element: HTMLElement) {
99
99
  });
100
100
  }
101
101
 
102
+ // prevent XSS, similar to https://github.com/ProseMirror/prosemirror-view/blob/1251b2b412656a2a06263e4187574beb43651273/src/clipboard.ts#L204
103
+ // https://github.com/TypeCellOS/BlockNote/issues/601
104
+ let _detachedDoc: Document | null = null;
105
+ function detachedDoc() {
106
+ return (
107
+ _detachedDoc ||
108
+ (_detachedDoc = document.implementation.createHTMLDocument("title"))
109
+ );
110
+ }
111
+
102
112
  export function nestedListsToBlockNoteStructure(
103
113
  elementOrHTML: HTMLElement | string
104
114
  ) {
105
115
  if (typeof elementOrHTML === "string") {
106
- const element = document.createElement("div");
116
+ const element = detachedDoc().createElement("div");
107
117
  element.innerHTML = elementOrHTML;
108
118
  elementOrHTML = element;
109
119
  }
@@ -6,12 +6,15 @@ async function parseMarkdownAndCompareSnapshots(
6
6
  snapshotName: string
7
7
  ) {
8
8
  const editor = BlockNoteEditor.create();
9
+ const div = document.createElement("div");
10
+ editor.mount(div);
9
11
  const blocks = await editor.tryParseMarkdownToBlocks(md);
10
12
 
11
13
  const snapshotPath = "./__snapshots__/" + snapshotName + ".json";
12
14
  expect(JSON.stringify(blocks, undefined, 2)).toMatchFileSnapshot(
13
15
  snapshotPath
14
16
  );
17
+ editor.mount(undefined);
15
18
  }
16
19
 
17
20
  describe("Parse Markdown", () => {
@@ -4,12 +4,8 @@ import remarkGfm from "remark-gfm";
4
4
  import remarkParse from "remark-parse";
5
5
  import remarkRehype, { defaultHandlers } from "remark-rehype";
6
6
  import { unified } from "unified";
7
- import {
8
- Block,
9
- BlockSchema,
10
- InlineContentSchema,
11
- StyleSchema,
12
- } from "../../../schema";
7
+ import { Block } from "../../../blocks/defaultBlocks";
8
+ import { BlockSchema, InlineContentSchema, StyleSchema } from "../../../schema";
13
9
  import { HTMLToBlocks } from "../html/parseHTML";
14
10
 
15
11
  // modified version of https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js
@@ -1,19 +1,19 @@
1
1
  import { EditorTestCases } from "../index";
2
2
 
3
- import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
3
+ import {
4
+ imagePropSchema,
5
+ renderImage,
6
+ } from "../../../blocks/ImageBlockContent/ImageBlockContent";
7
+ import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
4
8
  import {
5
9
  DefaultInlineContentSchema,
6
10
  DefaultStyleSchema,
7
11
  defaultBlockSpecs,
8
12
  } from "../../../blocks/defaultBlocks";
9
13
  import { defaultProps } from "../../../blocks/defaultProps";
10
- import {
11
- imagePropSchema,
12
- renderImage,
13
- } from "../../../blocks/ImageBlockContent/ImageBlockContent";
14
- import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
14
+ import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
15
+ import { BlockNoteSchema } from "../../../editor/BlockNoteSchema";
15
16
  import { createBlockSpec } from "../../../schema/blocks/createSpec";
16
- import { BlockSchemaFromSpecs, BlockSpecs } from "../../../schema/blocks/types";
17
17
 
18
18
  // This is a modified version of the default image block that does not implement
19
19
  // a `serialize` function. It's used to test if the custom serializer by default
@@ -74,22 +74,24 @@ const SimpleCustomParagraph = createBlockSpec(
74
74
  }
75
75
  );
76
76
 
77
- const customSpecs = {
78
- ...defaultBlockSpecs,
79
- simpleImage: SimpleImage,
80
- customParagraph: CustomParagraph,
81
- simpleCustomParagraph: SimpleCustomParagraph,
82
- } satisfies BlockSpecs;
77
+ const schema = BlockNoteSchema.create({
78
+ blockSpecs: {
79
+ ...defaultBlockSpecs,
80
+ simpleImage: SimpleImage,
81
+ customParagraph: CustomParagraph,
82
+ simpleCustomParagraph: SimpleCustomParagraph,
83
+ },
84
+ });
83
85
 
84
86
  export const customBlocksTestCases: EditorTestCases<
85
- BlockSchemaFromSpecs<typeof customSpecs>,
87
+ typeof schema.blockSchema,
86
88
  DefaultInlineContentSchema,
87
89
  DefaultStyleSchema
88
90
  > = {
89
91
  name: "custom blocks schema",
90
92
  createEditor: () => {
91
93
  return BlockNoteEditor.create({
92
- blockSpecs: customSpecs,
94
+ schema,
93
95
  uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
94
96
  });
95
97
  },
@@ -98,7 +100,7 @@ export const customBlocksTestCases: EditorTestCases<
98
100
  name: "simpleImage/button",
99
101
  blocks: [
100
102
  {
101
- type: "simpleImage" as const,
103
+ type: "simpleImage",
102
104
  },
103
105
  ],
104
106
  },
@@ -1,17 +1,14 @@
1
1
  import { EditorTestCases } from "../index";
2
2
 
3
- import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
3
+ import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
4
4
  import {
5
5
  DefaultBlockSchema,
6
6
  DefaultStyleSchema,
7
7
  defaultInlineContentSpecs,
8
8
  } from "../../../blocks/defaultBlocks";
9
- import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
9
+ import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
10
+ import { BlockNoteSchema } from "../../../editor/BlockNoteSchema";
10
11
  import { createInlineContentSpec } from "../../../schema/inlineContent/createSpec";
11
- import {
12
- InlineContentSchemaFromSpecs,
13
- InlineContentSpecs,
14
- } from "../../../schema/inlineContent/types";
15
12
 
16
13
  const mention = createInlineContentSpec(
17
14
  {
@@ -57,22 +54,24 @@ const tag = createInlineContentSpec(
57
54
  }
58
55
  );
59
56
 
60
- const customInlineContent = {
61
- ...defaultInlineContentSpecs,
62
- mention,
63
- tag,
64
- } satisfies InlineContentSpecs;
57
+ const schema = BlockNoteSchema.create({
58
+ inlineContentSpecs: {
59
+ ...defaultInlineContentSpecs,
60
+ mention,
61
+ tag,
62
+ },
63
+ });
65
64
 
66
65
  export const customInlineContentTestCases: EditorTestCases<
67
66
  DefaultBlockSchema,
68
- InlineContentSchemaFromSpecs<typeof customInlineContent>,
67
+ typeof schema.inlineContentSchema,
69
68
  DefaultStyleSchema
70
69
  > = {
71
70
  name: "custom inline content schema",
72
71
  createEditor: () => {
73
72
  return BlockNoteEditor.create({
74
73
  uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
75
- inlineContentSpecs: customInlineContent,
74
+ schema,
76
75
  });
77
76
  },
78
77
  documents: [
@@ -1,14 +1,14 @@
1
1
  import { EditorTestCases } from "../index";
2
2
 
3
- import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
3
+ import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
4
4
  import {
5
5
  DefaultBlockSchema,
6
6
  DefaultInlineContentSchema,
7
7
  defaultStyleSpecs,
8
8
  } from "../../../blocks/defaultBlocks";
9
- import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
9
+ import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
10
+ import { BlockNoteSchema } from "../../../editor/BlockNoteSchema";
10
11
  import { createStyleSpec } from "../../../schema/styles/createSpec";
11
- import { StyleSchemaFromSpecs, StyleSpecs } from "../../../schema/styles/types";
12
12
 
13
13
  const small = createStyleSpec(
14
14
  {
@@ -43,22 +43,24 @@ const fontSize = createStyleSpec(
43
43
  }
44
44
  );
45
45
 
46
- const customStyles = {
47
- ...defaultStyleSpecs,
48
- small,
49
- fontSize,
50
- } satisfies StyleSpecs;
46
+ const schema = BlockNoteSchema.create({
47
+ styleSpecs: {
48
+ ...defaultStyleSpecs,
49
+ small,
50
+ fontSize,
51
+ },
52
+ });
51
53
 
52
54
  export const customStylesTestCases: EditorTestCases<
53
55
  DefaultBlockSchema,
54
56
  DefaultInlineContentSchema,
55
- StyleSchemaFromSpecs<typeof customStyles>
57
+ typeof schema.styleSchema
56
58
  > = {
57
59
  name: "custom style schema",
58
60
  createEditor: () => {
59
61
  return BlockNoteEditor.create({
60
62
  uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
61
- styleSpecs: customStyles,
63
+ schema,
62
64
  });
63
65
  },
64
66
  documents: [
@@ -1,7 +1,9 @@
1
+ import { PartialBlock } from "../../blocks/defaultBlocks";
1
2
  import { BlockNoteEditor } from "../../editor/BlockNoteEditor";
2
- import { BlockSchema, PartialBlock } from "../../schema/blocks/types";
3
+ import { BlockSchema } from "../../schema/blocks/types";
3
4
  import { InlineContentSchema } from "../../schema/inlineContent/types";
4
5
  import { StyleSchema } from "../../schema/styles/types";
6
+ import { NoInfer } from "../../util/typescript";
5
7
 
6
8
  export type EditorTestCases<
7
9
  B extends BlockSchema,
@@ -12,6 +14,6 @@ export type EditorTestCases<
12
14
  createEditor: () => BlockNoteEditor<B, I, S>;
13
15
  documents: Array<{
14
16
  name: string;
15
- blocks: PartialBlock<B, I, S>[];
17
+ blocks: PartialBlock<NoInfer<B>, NoInfer<I>, NoInfer<S>>[];
16
18
  }>;
17
19
  };
@@ -1,10 +1,6 @@
1
+ import { Block, PartialBlock } from "../../blocks/defaultBlocks";
1
2
  import UniqueID from "../../extensions/UniqueID/UniqueID";
2
- import {
3
- Block,
4
- BlockSchema,
5
- PartialBlock,
6
- TableContent,
7
- } from "../../schema/blocks/types";
3
+ import { BlockSchema, TableContent } from "../../schema/blocks/types";
8
4
  import {
9
5
  InlineContent,
10
6
  InlineContentSchema,
@@ -6,6 +6,7 @@ import {
6
6
  } from "../../schema";
7
7
  import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers";
8
8
  import { defaultProps } from "../defaultProps";
9
+ import { getCurrentBlockContentType } from "../../api/getCurrentBlockContentType";
9
10
 
10
11
  export const headingPropSchema = {
11
12
  ...defaultProps,
@@ -45,6 +46,10 @@ const HeadingBlockContent = createStronglyTypedTiptapNode({
45
46
  return new InputRule({
46
47
  find: new RegExp(`^(#{${level}})\\s$`),
47
48
  handler: ({ state, chain, range }) => {
49
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
50
+ return;
51
+ }
52
+
48
53
  chain()
49
54
  .BNUpdateBlock(state.selection.from, {
50
55
  type: "heading",
@@ -62,27 +67,51 @@ const HeadingBlockContent = createStronglyTypedTiptapNode({
62
67
 
63
68
  addKeyboardShortcuts() {
64
69
  return {
65
- "Mod-Alt-1": () =>
66
- this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
67
- type: "heading",
68
- props: {
69
- level: 1 as any,
70
- },
71
- }),
72
- "Mod-Alt-2": () =>
73
- this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
74
- type: "heading",
75
- props: {
76
- level: 2 as any,
77
- },
78
- }),
79
- "Mod-Alt-3": () =>
80
- this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
81
- type: "heading",
82
- props: {
83
- level: 3 as any,
84
- },
85
- }),
70
+ "Mod-Alt-1": () => {
71
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
72
+ return true;
73
+ }
74
+
75
+ return this.editor.commands.BNUpdateBlock(
76
+ this.editor.state.selection.anchor,
77
+ {
78
+ type: "heading",
79
+ props: {
80
+ level: 1 as any,
81
+ },
82
+ }
83
+ );
84
+ },
85
+ "Mod-Alt-2": () => {
86
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
87
+ return true;
88
+ }
89
+
90
+ return this.editor.commands.BNUpdateBlock(
91
+ this.editor.state.selection.anchor,
92
+ {
93
+ type: "heading",
94
+ props: {
95
+ level: 2 as any,
96
+ },
97
+ }
98
+ );
99
+ },
100
+ "Mod-Alt-3": () => {
101
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
102
+ return true;
103
+ }
104
+
105
+ return this.editor.commands.BNUpdateBlock(
106
+ this.editor.state.selection.anchor,
107
+ {
108
+ type: "heading",
109
+ props: {
110
+ level: 3 as any,
111
+ },
112
+ }
113
+ );
114
+ },
86
115
  };
87
116
  },
88
117
  parseHTML() {
@@ -1,5 +1,4 @@
1
1
  import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
2
- import { imageToolbarPluginKey } from "../../extensions/ImageToolbar/ImageToolbarPlugin";
3
2
 
4
3
  import {
5
4
  BlockFromConfig,
@@ -235,7 +234,7 @@ export const renderImage = (
235
234
  // Opens the image toolbar.
236
235
  const addImageButtonClickHandler = () => {
237
236
  editor._tiptapEditor.view.dispatch(
238
- editor._tiptapEditor.state.tr.setMeta(imageToolbarPluginKey, {
237
+ editor._tiptapEditor.state.tr.setMeta(editor.imagePanel!.plugin, {
239
238
  block: block,
240
239
  })
241
240
  );
@@ -1,4 +1,11 @@
1
- export const uploadToTmpFilesDotOrg_DEV_ONLY = async (file: File) => {
1
+ /**
2
+ * Uploads a file to tmpfiles.org and returns the URL to the uploaded file.
3
+ *
4
+ * @warning This function should only be used for development purposes, replace with your own backend!
5
+ */
6
+ export const uploadToTmpFilesDotOrg_DEV_ONLY = async (
7
+ file: File
8
+ ): Promise<string> => {
2
9
  const body = new FormData();
3
10
  body.append("file", file);
4
11
 
@@ -7,6 +7,7 @@ import {
7
7
  import { createDefaultBlockDOMOutputSpec } from "../../defaultBlockHelpers";
8
8
  import { defaultProps } from "../../defaultProps";
9
9
  import { handleEnter } from "../ListItemKeyboardShortcuts";
10
+ import { getCurrentBlockContentType } from "../../../api/getCurrentBlockContentType";
10
11
 
11
12
  export const bulletListItemPropSchema = {
12
13
  ...defaultProps,
@@ -22,6 +23,10 @@ const BulletListItemBlockContent = createStronglyTypedTiptapNode({
22
23
  new InputRule({
23
24
  find: new RegExp(`^[-+*]\\s$`),
24
25
  handler: ({ state, chain, range }) => {
26
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
27
+ return;
28
+ }
29
+
25
30
  chain()
26
31
  .BNUpdateBlock(state.selection.from, {
27
32
  type: "bulletListItem",
@@ -37,11 +42,19 @@ const BulletListItemBlockContent = createStronglyTypedTiptapNode({
37
42
  addKeyboardShortcuts() {
38
43
  return {
39
44
  Enter: () => handleEnter(this.editor),
40
- "Mod-Shift-8": () =>
41
- this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
42
- type: "bulletListItem",
43
- props: {},
44
- }),
45
+ "Mod-Shift-8": () => {
46
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
47
+ return true;
48
+ }
49
+
50
+ return this.editor.commands.BNUpdateBlock(
51
+ this.editor.state.selection.anchor,
52
+ {
53
+ type: "bulletListItem",
54
+ props: {},
55
+ }
56
+ );
57
+ },
45
58
  };
46
59
  },
47
60
 
@@ -10,7 +10,13 @@ export const handleEnter = (editor: Editor) => {
10
10
  const selectionEmpty =
11
11
  editor.state.selection.anchor === editor.state.selection.head;
12
12
 
13
- if (!contentType.name.endsWith("ListItem") || !selectionEmpty) {
13
+ if (
14
+ !(
15
+ contentType.name === "bulletListItem" ||
16
+ contentType.name === "numberedListItem"
17
+ ) ||
18
+ !selectionEmpty
19
+ ) {
14
20
  return false;
15
21
  }
16
22
 
@@ -8,6 +8,7 @@ import { createDefaultBlockDOMOutputSpec } from "../../defaultBlockHelpers";
8
8
  import { defaultProps } from "../../defaultProps";
9
9
  import { handleEnter } from "../ListItemKeyboardShortcuts";
10
10
  import { NumberedListIndexingPlugin } from "./NumberedListIndexingPlugin";
11
+ import { getCurrentBlockContentType } from "../../../api/getCurrentBlockContentType";
11
12
 
12
13
  export const numberedListItemPropSchema = {
13
14
  ...defaultProps,
@@ -37,6 +38,10 @@ const NumberedListItemBlockContent = createStronglyTypedTiptapNode({
37
38
  new InputRule({
38
39
  find: new RegExp(`^1\\.\\s$`),
39
40
  handler: ({ state, chain, range }) => {
41
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
42
+ return;
43
+ }
44
+
40
45
  chain()
41
46
  .BNUpdateBlock(state.selection.from, {
42
47
  type: "numberedListItem",
@@ -52,11 +57,19 @@ const NumberedListItemBlockContent = createStronglyTypedTiptapNode({
52
57
  addKeyboardShortcuts() {
53
58
  return {
54
59
  Enter: () => handleEnter(this.editor),
55
- "Mod-Shift-7": () =>
56
- this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
57
- type: "numberedListItem",
58
- props: {},
59
- }),
60
+ "Mod-Shift-7": () => {
61
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
62
+ return true;
63
+ }
64
+
65
+ return this.editor.commands.BNUpdateBlock(
66
+ this.editor.state.selection.anchor,
67
+ {
68
+ type: "numberedListItem",
69
+ props: {},
70
+ }
71
+ );
72
+ },
60
73
  };
61
74
  },
62
75
 
@@ -5,6 +5,7 @@ import {
5
5
  import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers";
6
6
  import { defaultProps } from "../defaultProps";
7
7
  import { handleEnter } from "../ListItemBlockContent/ListItemKeyboardShortcuts";
8
+ import { getCurrentBlockContentType } from "../../api/getCurrentBlockContentType";
8
9
 
9
10
  export const paragraphPropSchema = {
10
11
  ...defaultProps,
@@ -18,11 +19,19 @@ export const ParagraphBlockContent = createStronglyTypedTiptapNode({
18
19
  addKeyboardShortcuts() {
19
20
  return {
20
21
  Enter: () => handleEnter(this.editor),
21
- "Mod-Alt-0": () =>
22
- this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
23
- type: "paragraph",
24
- props: {},
25
- }),
22
+ "Mod-Alt-0": () => {
23
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
24
+ return true;
25
+ }
26
+
27
+ return this.editor.commands.BNUpdateBlock(
28
+ this.editor.state.selection.anchor,
29
+ {
30
+ type: "paragraph",
31
+ props: {},
32
+ }
33
+ );
34
+ },
26
35
  };
27
36
  },
28
37
 
@@ -1,7 +1,7 @@
1
1
  import { blockToNode } from "../api/nodeConversions/nodeConversions";
2
2
  import type { BlockNoteEditor } from "../editor/BlockNoteEditor";
3
3
  import type {
4
- Block,
4
+ BlockNoDefaults,
5
5
  BlockSchema,
6
6
  InlineContentSchema,
7
7
  StyleSchema,
@@ -61,7 +61,7 @@ export const defaultBlockToHTML = <
61
61
  I extends InlineContentSchema,
62
62
  S extends StyleSchema
63
63
  >(
64
- block: Block<BSchema, I, S>,
64
+ block: BlockNoDefaults<BSchema, I, S>,
65
65
  editor: BlockNoteEditor<BSchema, I, S>
66
66
  ): {
67
67
  dom: HTMLElement;
@@ -70,7 +70,7 @@ export const defaultBlockToHTML = <
70
70
  const node = blockToNode(
71
71
  block,
72
72
  editor._tiptapEditor.schema,
73
- editor.styleSchema
73
+ editor.schema.styleSchema
74
74
  ).firstChild!;
75
75
  const toDOM = editor._tiptapEditor.schema.nodes[node.type.name].spec.toDOM;
76
76
 
@@ -0,0 +1,84 @@
1
+ import type { BlockNoteEditor } from "../editor/BlockNoteEditor";
2
+ import { BlockFromConfig, InlineContentSchema, StyleSchema } from "../schema";
3
+ import { Block, DefaultBlockSchema, defaultBlockSchema } from "./defaultBlocks";
4
+ import { defaultProps } from "./defaultProps";
5
+
6
+ export function checkDefaultBlockTypeInSchema<
7
+ BlockType extends keyof DefaultBlockSchema,
8
+ I extends InlineContentSchema,
9
+ S extends StyleSchema
10
+ >(
11
+ blockType: BlockType,
12
+ editor: BlockNoteEditor<any, I, S>
13
+ ): editor is BlockNoteEditor<{ Type: DefaultBlockSchema[BlockType] }, I, S> {
14
+ return (
15
+ blockType in editor.schema.blockSchema &&
16
+ editor.schema.blockSchema[blockType] === defaultBlockSchema[blockType]
17
+ );
18
+ }
19
+
20
+ export function checkBlockIsDefaultType<
21
+ BlockType extends keyof DefaultBlockSchema,
22
+ I extends InlineContentSchema,
23
+ S extends StyleSchema
24
+ >(
25
+ blockType: BlockType,
26
+ block: Block<any, I, S>,
27
+ editor: BlockNoteEditor<any, I, S>
28
+ ): block is BlockFromConfig<DefaultBlockSchema[BlockType], I, S> {
29
+ return (
30
+ block.type === blockType &&
31
+ block.type in editor.schema.blockSchema &&
32
+ checkDefaultBlockTypeInSchema(block.type, editor)
33
+ );
34
+ }
35
+
36
+ export function checkBlockTypeHasDefaultProp<
37
+ Prop extends keyof typeof defaultProps,
38
+ I extends InlineContentSchema,
39
+ S extends StyleSchema
40
+ >(
41
+ prop: Prop,
42
+ blockType: string,
43
+ editor: BlockNoteEditor<any, I, S>
44
+ ): editor is BlockNoteEditor<
45
+ {
46
+ [BT in string]: {
47
+ type: BT;
48
+ propSchema: {
49
+ [P in Prop]: (typeof defaultProps)[P];
50
+ };
51
+ content: "table" | "inline" | "none";
52
+ };
53
+ },
54
+ I,
55
+ S
56
+ > {
57
+ return (
58
+ blockType in editor.schema.blockSchema &&
59
+ prop in editor.schema.blockSchema[blockType].propSchema &&
60
+ editor.schema.blockSchema[blockType].propSchema[prop] === defaultProps[prop]
61
+ );
62
+ }
63
+
64
+ export function checkBlockHasDefaultProp<
65
+ Prop extends keyof typeof defaultProps,
66
+ I extends InlineContentSchema,
67
+ S extends StyleSchema
68
+ >(
69
+ prop: Prop,
70
+ block: Block<any, I, S>,
71
+ editor: BlockNoteEditor<any, I, S>
72
+ ): block is BlockFromConfig<
73
+ {
74
+ type: string;
75
+ propSchema: {
76
+ [P in Prop]: (typeof defaultProps)[P];
77
+ };
78
+ content: "table" | "inline" | "none";
79
+ },
80
+ I,
81
+ S
82
+ > {
83
+ return checkBlockTypeHasDefaultProp(prop, block.type, editor);
84
+ }