@blocknote/core 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +13 -17
  2. package/dist/blocknote.js +1611 -1408
  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 +8 -4
  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/nodeConversions/nodeConversions.test.ts +14 -7
  18. package/src/api/nodeConversions/nodeConversions.ts +1 -2
  19. package/src/api/parsers/html/parseHTML.test.ts +5 -1
  20. package/src/api/parsers/html/parseHTML.ts +2 -6
  21. package/src/api/parsers/html/util/nestedLists.ts +11 -1
  22. package/src/api/parsers/markdown/parseMarkdown.test.ts +3 -0
  23. package/src/api/parsers/markdown/parseMarkdown.ts +2 -6
  24. package/src/api/testUtil/cases/customBlocks.ts +18 -16
  25. package/src/api/testUtil/cases/customInlineContent.ts +12 -13
  26. package/src/api/testUtil/cases/customStyles.ts +12 -10
  27. package/src/api/testUtil/index.ts +4 -2
  28. package/src/api/testUtil/partialBlockTestUtil.ts +2 -6
  29. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +1 -2
  30. package/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +8 -1
  31. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +13 -0
  32. package/src/blocks/defaultBlockHelpers.ts +3 -3
  33. package/src/blocks/defaultBlockTypeGuards.ts +84 -0
  34. package/src/blocks/defaultBlocks.ts +29 -3
  35. package/src/editor/Block.css +2 -31
  36. package/src/editor/BlockNoteEditor.ts +219 -263
  37. package/src/editor/BlockNoteExtensions.ts +5 -2
  38. package/src/editor/BlockNoteSchema.ts +98 -0
  39. package/src/editor/BlockNoteTipTapEditor.ts +162 -0
  40. package/src/editor/cursorPositionTypes.ts +2 -6
  41. package/src/editor/editor.css +0 -1
  42. package/src/editor/selectionTypes.ts +2 -6
  43. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +22 -29
  44. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +26 -27
  45. package/src/extensions/ImageToolbar/ImageToolbarPlugin.ts +45 -51
  46. package/src/extensions/Placeholder/PlaceholderExtension.ts +81 -88
  47. package/src/extensions/SideMenu/SideMenuPlugin.ts +55 -56
  48. package/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts +8 -0
  49. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +353 -0
  50. package/src/extensions/{SlashMenu/defaultSlashMenuItems.ts → SuggestionMenu/getDefaultSlashMenuItems.ts} +119 -89
  51. package/src/extensions/TableHandles/TableHandlesPlugin.ts +62 -45
  52. package/src/extensions-shared/UiElementPosition.ts +4 -0
  53. package/src/index.ts +6 -6
  54. package/src/pm-nodes/BlockContainer.ts +5 -9
  55. package/src/schema/blocks/types.ts +15 -15
  56. package/src/schema/inlineContent/createSpec.ts +2 -2
  57. package/src/schema/inlineContent/types.ts +1 -1
  58. package/src/util/browser.ts +6 -4
  59. package/src/util/typescript.ts +7 -4
  60. package/types/src/api/blockManipulation/blockManipulation.d.ts +6 -1
  61. package/types/src/api/exporters/html/externalHTMLExporter.d.ts +2 -1
  62. package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +2 -1
  63. package/types/src/api/exporters/markdown/markdownExporter.d.ts +2 -1
  64. package/types/src/api/nodeConversions/nodeConversions.d.ts +2 -1
  65. package/types/src/api/parsers/html/parseHTML.d.ts +2 -1
  66. package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -1
  67. package/types/src/api/testUtil/cases/customBlocks.d.ts +72 -13
  68. package/types/src/api/testUtil/cases/customInlineContent.d.ts +281 -6
  69. package/types/src/api/testUtil/cases/customStyles.d.ts +247 -13
  70. package/types/src/api/testUtil/index.d.ts +4 -2
  71. package/types/src/api/testUtil/partialBlockTestUtil.d.ts +2 -1
  72. package/types/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +6 -1
  73. package/types/src/blocks/defaultBlockHelpers.d.ts +2 -2
  74. package/types/src/blocks/defaultBlockTypeGuards.d.ts +24 -0
  75. package/types/src/blocks/defaultBlocks.d.ts +21 -15
  76. package/types/src/editor/BlockNoteEditor.d.ts +48 -53
  77. package/types/src/editor/BlockNoteExtensions.d.ts +1 -0
  78. package/types/src/editor/BlockNoteSchema.d.ts +34 -0
  79. package/types/src/editor/BlockNoteTipTapEditor.d.ts +28 -0
  80. package/types/src/editor/cursorPositionTypes.d.ts +2 -1
  81. package/types/src/editor/selectionTypes.d.ts +2 -1
  82. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +5 -6
  83. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +2 -2
  84. package/types/src/extensions/ImageToolbar/ImageToolbarPlugin.d.ts +15 -14
  85. package/types/src/extensions/Placeholder/PlaceholderExtension.d.ts +2 -15
  86. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +8 -7
  87. package/types/src/extensions/SuggestionMenu/DefaultSuggestionItem.d.ts +8 -0
  88. package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +31 -0
  89. package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +10 -0
  90. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +7 -7
  91. package/types/src/extensions-shared/UiElementPosition.d.ts +4 -0
  92. package/types/src/index.d.ts +6 -6
  93. package/types/src/pm-nodes/BlockContainer.d.ts +3 -2
  94. package/types/src/pm-nodes/BlockGroup.d.ts +1 -1
  95. package/types/src/schema/blocks/types.d.ts +15 -15
  96. package/types/src/schema/inlineContent/types.d.ts +1 -1
  97. package/types/src/util/browser.d.ts +1 -0
  98. package/types/src/util/typescript.d.ts +1 -0
  99. package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +0 -12
  100. package/src/extensions/SlashMenu/SlashMenuPlugin.ts +0 -53
  101. package/src/extensions-shared/BaseUiElementTypes.ts +0 -8
  102. package/src/extensions-shared/README.md +0 -3
  103. package/src/extensions-shared/suggestion/SuggestionItem.ts +0 -3
  104. package/src/extensions-shared/suggestion/SuggestionPlugin.ts +0 -448
  105. package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +0 -7
  106. package/types/src/extensions/SlashMenu/SlashMenuPlugin.d.ts +0 -13
  107. package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +0 -3
  108. package/types/src/extensions-shared/BaseUiElementTypes.d.ts +0 -7
  109. package/types/src/extensions-shared/suggestion/SuggestionItem.d.ts +0 -3
  110. package/types/src/extensions-shared/suggestion/SuggestionPlugin.d.ts +0 -36
  111. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-100.woff +0 -0
  112. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-100.woff2 +0 -0
  113. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-200.woff +0 -0
  114. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-200.woff2 +0 -0
  115. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-300.woff +0 -0
  116. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-300.woff2 +0 -0
  117. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-500.woff +0 -0
  118. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-500.woff2 +0 -0
  119. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-600.woff +0 -0
  120. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-600.woff2 +0 -0
  121. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-700.woff +0 -0
  122. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-700.woff2 +0 -0
  123. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-800.woff +0 -0
  124. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-800.woff2 +0 -0
  125. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-900.woff +0 -0
  126. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-900.woff2 +0 -0
  127. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-regular.woff +0 -0
  128. /package/src/{assets → fonts}/inter-v12-latin/inter-v12-latin-regular.woff2 +0 -0
  129. /package/src/{assets/fonts-inter.css → fonts/inter.css} +0 -0
@@ -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,
@@ -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.imageToolbar!.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
 
@@ -4,6 +4,7 @@ import {
4
4
  } from "../../schema";
5
5
  import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers";
6
6
  import { defaultProps } from "../defaultProps";
7
+ import { handleEnter } from "../ListItemBlockContent/ListItemKeyboardShortcuts";
7
8
 
8
9
  export const paragraphPropSchema = {
9
10
  ...defaultProps,
@@ -13,6 +14,18 @@ export const ParagraphBlockContent = createStronglyTypedTiptapNode({
13
14
  name: "paragraph",
14
15
  content: "inline*",
15
16
  group: "blockContent",
17
+
18
+ addKeyboardShortcuts() {
19
+ return {
20
+ Enter: () => handleEnter(this.editor),
21
+ "Mod-Alt-0": () =>
22
+ this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {
23
+ type: "paragraph",
24
+ props: {},
25
+ }),
26
+ };
27
+ },
28
+
16
29
  parseHTML() {
17
30
  return [
18
31
  { tag: "div[data-content-type=" + this.name + "]" },
@@ -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
+ }
@@ -6,8 +6,13 @@ import Underline from "@tiptap/extension-underline";
6
6
  import { BackgroundColor } from "../extensions/BackgroundColor/BackgroundColorMark";
7
7
  import { TextColor } from "../extensions/TextColor/TextColorMark";
8
8
  import {
9
+ BlockNoDefaults,
10
+ BlockSchema,
9
11
  BlockSpecs,
12
+ InlineContentSchema,
10
13
  InlineContentSpecs,
14
+ PartialBlockNoDefaults,
15
+ StyleSchema,
11
16
  StyleSpecs,
12
17
  createStyleSpecFromTipTapMark,
13
18
  getBlockSchemaFromSpecs,
@@ -32,7 +37,10 @@ export const defaultBlockSpecs = {
32
37
 
33
38
  export const defaultBlockSchema = getBlockSchemaFromSpecs(defaultBlockSpecs);
34
39
 
35
- export type DefaultBlockSchema = typeof defaultBlockSchema;
40
+ // underscore is used that in case a user overrides DefaultBlockSchema,
41
+ // they can still access the original default block schema
42
+ export type _DefaultBlockSchema = typeof defaultBlockSchema;
43
+ export type DefaultBlockSchema = _DefaultBlockSchema;
36
44
 
37
45
  export const defaultStyleSpecs = {
38
46
  bold: createStyleSpecFromTipTapMark(Bold, "boolean"),
@@ -46,7 +54,10 @@ export const defaultStyleSpecs = {
46
54
 
47
55
  export const defaultStyleSchema = getStyleSchemaFromSpecs(defaultStyleSpecs);
48
56
 
49
- export type DefaultStyleSchema = typeof defaultStyleSchema;
57
+ // underscore is used that in case a user overrides DefaultStyleSchema,
58
+ // they can still access the original default style schema
59
+ export type _DefaultStyleSchema = typeof defaultStyleSchema;
60
+ export type DefaultStyleSchema = _DefaultStyleSchema;
50
61
 
51
62
  export const defaultInlineContentSpecs = {
52
63
  text: { config: "text", implementation: {} as any },
@@ -57,4 +68,19 @@ export const defaultInlineContentSchema = getInlineContentSchemaFromSpecs(
57
68
  defaultInlineContentSpecs
58
69
  );
59
70
 
60
- export type DefaultInlineContentSchema = typeof defaultInlineContentSchema;
71
+ // underscore is used that in case a user overrides DefaultInlineContentSchema,
72
+ // they can still access the original default inline content schema
73
+ export type _DefaultInlineContentSchema = typeof defaultInlineContentSchema;
74
+ export type DefaultInlineContentSchema = _DefaultInlineContentSchema;
75
+
76
+ export type PartialBlock<
77
+ BSchema extends BlockSchema = DefaultBlockSchema,
78
+ I extends InlineContentSchema = DefaultInlineContentSchema,
79
+ S extends StyleSchema = DefaultStyleSchema
80
+ > = PartialBlockNoDefaults<BSchema, I, S>;
81
+
82
+ export type Block<
83
+ BSchema extends BlockSchema = DefaultBlockSchema,
84
+ I extends InlineContentSchema = DefaultInlineContentSchema,
85
+ S extends StyleSchema = DefaultStyleSchema
86
+ > = BlockNoDefaults<BSchema, I, S>;
@@ -305,11 +305,8 @@ NESTED BLOCKS
305
305
  }
306
306
 
307
307
  /* PLACEHOLDERS*/
308
-
309
- .bn-is-empty .bn-inline-content:before,
310
- .bn-is-filter .bn-inline-content:before {
308
+ .bn-inline-content:has(> .ProseMirror-trailingBreak):before {
311
309
  /*float: left; */
312
- content: "";
313
310
  pointer-events: none;
314
311
  height: 0;
315
312
  /* width: 0; */
@@ -317,33 +314,7 @@ NESTED BLOCKS
317
314
  font-style: italic;
318
315
  }
319
316
 
320
- /* TODO: would be nicer if defined from code */
321
-
322
- .bn-block-content.bn-is-empty.bn-has-anchor .bn-inline-content:before {
323
- content: "Enter text or type '/' for commands";
324
- }
325
-
326
- .bn-block-content.bn-is-filter.bn-has-anchor .bn-inline-content:before {
327
- content: "Type to filter";
328
- }
329
-
330
- .bn-block-content[data-content-type="heading"].bn-is-empty
331
- .bn-inline-content:before {
332
- content: "Heading";
333
- }
334
-
335
- .bn-block-content[data-content-type="bulletListItem"].bn-is-empty
336
- .bn-inline-content:before,
337
- .bn-block-content[data-content-type="numberedListItem"].bn-is-empty
338
- .bn-inline-content:before {
339
- content: "List";
340
- }
341
-
342
- .bn-is-empty
343
- .bn-block-content[data-content-type="captionedImage"]
344
- .bn-inline-content:before {
345
- content: "Caption";
346
- }
317
+ /* TODO: should this be here? */
347
318
 
348
319
  /* TEXT COLORS */
349
320
  [data-text-color="gray"] {