@blocknote/core 0.38.0 → 0.39.1-capitol

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 (239) hide show
  1. package/dist/BlockNoteSchema-Bsa_tSAC.cjs +11 -0
  2. package/dist/BlockNoteSchema-Bsa_tSAC.cjs.map +1 -0
  3. package/dist/BlockNoteSchema-CZez1nQf.js +4244 -0
  4. package/dist/BlockNoteSchema-CZez1nQf.js.map +1 -0
  5. package/dist/blocknote.cjs +4 -12
  6. package/dist/blocknote.cjs.map +1 -1
  7. package/dist/blocknote.js +3401 -7305
  8. package/dist/blocknote.js.map +1 -1
  9. package/dist/blocks.cjs +2 -0
  10. package/dist/blocks.cjs.map +1 -0
  11. package/dist/blocks.js +71 -0
  12. package/dist/blocks.js.map +1 -0
  13. package/dist/style.css +1 -1
  14. package/dist/webpack-stats.json +1 -1
  15. package/package.json +19 -17
  16. package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +1 -1
  17. package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +2 -2
  18. package/src/api/blockManipulation/commands/splitBlock/splitBlock.ts +34 -25
  19. package/src/api/blockManipulation/setupTestEnv.ts +0 -1
  20. package/src/api/clipboard/fromClipboard/handleFileInsertion.ts +6 -10
  21. package/src/api/clipboard/fromClipboard/pasteExtension.ts +1 -1
  22. package/src/api/clipboard/toClipboard/copyExtension.ts +1 -1
  23. package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +128 -28
  24. package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +101 -41
  25. package/src/api/pmUtil.ts +1 -1
  26. package/src/api/positionMapping.test.ts +58 -15
  27. package/src/api/positionMapping.ts +2 -4
  28. package/src/blocks/Audio/block.ts +174 -0
  29. package/src/blocks/BlockNoteSchema.ts +59 -0
  30. package/src/blocks/Code/block.ts +299 -0
  31. package/src/blocks/File/block.ts +98 -0
  32. package/src/blocks/{FileBlockContent → File}/helpers/render/createAddFileButton.ts +5 -2
  33. package/src/blocks/{FileBlockContent → File}/helpers/render/createFileBlockWrapper.ts +15 -6
  34. package/src/blocks/{FileBlockContent → File}/helpers/render/createFileNameWithIcon.ts +15 -2
  35. package/src/blocks/{FileBlockContent → File}/helpers/render/createResizableFileBlockWrapper.ts +21 -2
  36. package/src/blocks/Heading/block.ts +138 -0
  37. package/src/blocks/Image/block.ts +190 -0
  38. package/src/blocks/ListItem/BulletListItem/block.ts +116 -0
  39. package/src/blocks/ListItem/CheckListItem/block.ts +175 -0
  40. package/src/blocks/ListItem/NumberedListItem/IndexingPlugin.ts +173 -0
  41. package/src/blocks/ListItem/NumberedListItem/block.ts +133 -0
  42. package/src/blocks/ListItem/ToggleListItem/block.ts +78 -0
  43. package/src/blocks/PageBreak/block.ts +72 -0
  44. package/src/blocks/{PageBreakBlockContent → PageBreak}/getPageBreakSlashMenuItems.ts +9 -7
  45. package/src/blocks/Paragraph/block.ts +80 -0
  46. package/src/blocks/Quote/block.ts +90 -0
  47. package/src/blocks/{TableBlockContent/TableBlockContent.ts → Table/block.ts} +169 -51
  48. package/src/blocks/ToggleWrapper/createToggleWrapper.ts +1 -1
  49. package/src/blocks/Video/block.ts +143 -0
  50. package/src/blocks/defaultBlockHelpers.ts +2 -2
  51. package/src/blocks/defaultBlockTypeGuards.ts +143 -174
  52. package/src/blocks/defaultBlocks.ts +107 -35
  53. package/src/blocks/defaultProps.ts +145 -4
  54. package/src/blocks/index.ts +26 -0
  55. package/src/blocks/utils/listItemEnterHandler.ts +42 -0
  56. package/src/editor/Block.css +54 -18
  57. package/src/editor/BlockNoteEditor.ts +256 -211
  58. package/src/editor/BlockNoteExtension.ts +92 -0
  59. package/src/editor/BlockNoteExtensions.ts +18 -17
  60. package/src/editor/defaultColors.ts +2 -2
  61. package/src/exporter/Exporter.ts +1 -1
  62. package/src/exporter/mapping.ts +1 -1
  63. package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +3 -20
  64. package/src/extensions/BackgroundColor/BackgroundColorMark.ts +6 -8
  65. package/src/extensions/BlockChange/BlockChangePlugin.ts +2 -1
  66. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor-forked.json +2 -2
  67. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor.json +2 -2
  68. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-forked.html +1 -1
  69. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap.html +1 -1
  70. package/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.ts +52 -0
  71. package/src/extensions/Collaboration/schemaMigration/migrationRules/index.ts +4 -0
  72. package/src/extensions/Collaboration/schemaMigration/migrationRules/migrationRule.ts +4 -0
  73. package/src/extensions/Collaboration/schemaMigration/migrationRules/moveColorAttributes.ts +78 -0
  74. package/src/extensions/Comments/CommentsPlugin.ts +1 -1
  75. package/src/extensions/FilePanel/FilePanelPlugin.ts +5 -10
  76. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +1 -1
  77. package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +4 -3
  78. package/src/extensions/Placeholder/PlaceholderPlugin.ts +6 -6
  79. package/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts +1 -23
  80. package/src/extensions/SideMenu/SideMenuPlugin.ts +1 -3
  81. package/src/extensions/SideMenu/dragging.ts +2 -2
  82. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +4 -7
  83. package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +6 -2
  84. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +24 -17
  85. package/src/extensions/TableHandles/TableHandlesPlugin.ts +8 -8
  86. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +5 -11
  87. package/src/extensions/TextColor/TextColorExtension.ts +3 -17
  88. package/src/extensions/TextColor/TextColorMark.ts +4 -9
  89. package/src/extensions/UniqueID/UniqueID.ts +6 -13
  90. package/src/index.ts +2 -28
  91. package/src/schema/blocks/createSpec.ts +342 -169
  92. package/src/schema/blocks/internal.ts +77 -138
  93. package/src/schema/blocks/types.ts +264 -94
  94. package/src/schema/index.ts +1 -0
  95. package/src/schema/inlineContent/createSpec.ts +99 -21
  96. package/src/schema/inlineContent/internal.ts +16 -7
  97. package/src/schema/inlineContent/types.ts +24 -2
  98. package/src/schema/propTypes.ts +15 -9
  99. package/src/schema/schema.ts +209 -0
  100. package/src/schema/styles/createSpec.ts +79 -31
  101. package/src/schema/styles/internal.ts +61 -2
  102. package/src/schema/styles/types.ts +17 -3
  103. package/src/util/topo-sort.test.ts +125 -0
  104. package/src/util/topo-sort.ts +160 -0
  105. package/types/src/api/blockManipulation/commands/splitBlock/splitBlock.d.ts +2 -1
  106. package/types/src/api/blockManipulation/selections/selection.d.ts +1 -1
  107. package/types/src/api/blockManipulation/setupTestEnv.d.ts +29 -543
  108. package/types/src/api/exporters/html/util/serializeBlocksExternalHTML.d.ts +1 -1
  109. package/types/src/api/exporters/html/util/serializeBlocksInternalHTML.d.ts +1 -1
  110. package/types/src/api/exporters/markdown/util/convertVideoToMarkdownRehypePlugin.d.ts +2 -0
  111. package/types/src/api/exporters/markdown/util/removeUnderlinesRehypePlugin.d.ts +6 -0
  112. package/types/src/api/pmUtil.d.ts +1 -1
  113. package/types/src/blocks/Audio/block.d.ts +58 -0
  114. package/types/src/blocks/BlockNoteSchema.d.ts +18 -0
  115. package/types/src/blocks/{CodeBlockContent/CodeBlockContent.d.ts → Code/block.d.ts} +25 -26
  116. package/types/src/blocks/Code/shiki.d.ts +4 -0
  117. package/types/src/blocks/Divider/block.d.ts +3 -0
  118. package/types/src/blocks/File/block.d.ts +37 -0
  119. package/types/src/blocks/File/helpers/render/createAddFileButton.d.ts +6 -0
  120. package/types/src/blocks/File/helpers/render/createFileBlockWrapper.d.ts +25 -0
  121. package/types/src/blocks/{FileBlockContent → File}/helpers/render/createFileNameWithIcon.d.ts +6 -2
  122. package/types/src/blocks/File/helpers/render/createResizableFileBlockWrapper.d.ts +31 -0
  123. package/types/src/blocks/Heading/block.d.ts +71 -0
  124. package/types/src/blocks/Image/block.d.ts +102 -0
  125. package/types/src/blocks/ListItem/BulletListItem/block.d.ts +25 -0
  126. package/types/src/blocks/ListItem/CheckListItem/block.d.ts +33 -0
  127. package/types/src/blocks/ListItem/NumberedListItem/IndexingPlugin.d.ts +8 -0
  128. package/types/src/blocks/ListItem/NumberedListItem/block.d.ts +33 -0
  129. package/types/src/blocks/ListItem/ToggleListItem/block.d.ts +25 -0
  130. package/types/src/blocks/PageBreak/block.d.ts +11 -0
  131. package/types/src/blocks/{PageBreakBlockContent → PageBreak}/getPageBreakSlashMenuItems.d.ts +4 -2
  132. package/types/src/blocks/Paragraph/block.d.ts +25 -0
  133. package/types/src/blocks/Quote/block.d.ts +17 -0
  134. package/types/src/blocks/Table/block.d.ts +21 -0
  135. package/types/src/blocks/Video/block.d.ts +67 -0
  136. package/types/src/blocks/defaultBlockHelpers.d.ts +1 -1
  137. package/types/src/blocks/defaultBlockTypeGuards.d.ts +15 -36
  138. package/types/src/blocks/defaultBlocks.d.ts +221 -1060
  139. package/types/src/blocks/defaultProps.d.ts +17 -1
  140. package/types/src/blocks/index.d.ts +24 -0
  141. package/types/src/blocks/utils/listItemEnterHandler.d.ts +2 -0
  142. package/types/src/editor/BlockNoteEditor.d.ts +36 -67
  143. package/types/src/editor/BlockNoteExtension.d.ts +67 -0
  144. package/types/src/editor/BlockNoteExtensions.d.ts +1 -1
  145. package/types/src/editor/defaultColors.d.ts +8 -76
  146. package/types/src/editor/managers/BlockManager.d.ts +114 -0
  147. package/types/src/editor/managers/CollaborationManager.d.ts +115 -0
  148. package/types/src/editor/managers/EventManager.d.ts +58 -0
  149. package/types/src/editor/managers/ExportManager.d.ts +64 -0
  150. package/types/src/editor/managers/ExtensionManager.d.ts +68 -0
  151. package/types/src/editor/managers/SelectionManager.d.ts +54 -0
  152. package/types/src/editor/managers/StateManager.d.ts +115 -0
  153. package/types/src/editor/managers/StyleManager.d.ts +48 -0
  154. package/types/src/editor/managers/index.d.ts +8 -0
  155. package/types/src/exporter/Exporter.d.ts +1 -1
  156. package/types/src/exporter/mapping.d.ts +1 -1
  157. package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +4 -1
  158. package/types/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.d.ts +7 -0
  159. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/index.d.ts +3 -0
  160. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/migrationRule.d.ts +3 -0
  161. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/moveColorAttributes.d.ts +2 -0
  162. package/types/src/extensions/Comments/CommentsPlugin.d.ts +1 -1
  163. package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +4 -4
  164. package/types/src/extensions/TextColor/TextColorMark.d.ts +4 -1
  165. package/types/src/index.d.ts +2 -25
  166. package/types/src/schema/blocks/createSpec.d.ts +16 -36
  167. package/types/src/schema/blocks/internal.d.ts +11 -33
  168. package/types/src/schema/blocks/types.d.ts +181 -57
  169. package/types/src/schema/index.d.ts +1 -0
  170. package/types/src/schema/inlineContent/createSpec.d.ts +36 -2
  171. package/types/src/schema/inlineContent/internal.d.ts +7 -15
  172. package/types/src/schema/inlineContent/types.d.ts +15 -1
  173. package/types/src/schema/propTypes.d.ts +4 -4
  174. package/types/src/schema/schema.d.ts +40 -0
  175. package/types/src/schema/styles/createSpec.d.ts +6 -4
  176. package/types/src/schema/styles/internal.d.ts +6 -3
  177. package/types/src/schema/styles/types.d.ts +11 -2
  178. package/types/src/util/topo-sort.d.ts +18 -0
  179. package/types/src/util/topo-sort.test.d.ts +1 -0
  180. package/dist/tsconfig.tsbuildinfo +0 -1
  181. package/src/blocks/AudioBlockContent/AudioBlockContent.ts +0 -144
  182. package/src/blocks/CodeBlockContent/CodeBlockContent.ts +0 -445
  183. package/src/blocks/FileBlockContent/FileBlockContent.ts +0 -100
  184. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +0 -159
  185. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +0 -159
  186. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +0 -134
  187. package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +0 -299
  188. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +0 -86
  189. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +0 -172
  190. package/src/blocks/ListItemBlockContent/ToggleListItemBlockContent/ToggleListItemBlockContent.ts +0 -104
  191. package/src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts +0 -49
  192. package/src/blocks/PageBreakBlockContent/schema.ts +0 -40
  193. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +0 -78
  194. package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +0 -121
  195. package/src/blocks/VideoBlockContent/VideoBlockContent.ts +0 -158
  196. package/src/editor/BlockNoteSchema.ts +0 -107
  197. package/src/editor/BlockNoteTipTapEditor.ts +0 -335
  198. package/types/src/blocks/AudioBlockContent/AudioBlockContent.d.ts +0 -99
  199. package/types/src/blocks/FileBlockContent/FileBlockContent.d.ts +0 -90
  200. package/types/src/blocks/FileBlockContent/helpers/render/createAddFileButton.d.ts +0 -6
  201. package/types/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.d.ts +0 -9
  202. package/types/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.d.ts +0 -9
  203. package/types/src/blocks/HeadingBlockContent/HeadingBlockContent.d.ts +0 -67
  204. package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +0 -131
  205. package/types/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +0 -46
  206. package/types/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.d.ts +0 -55
  207. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.d.ts +0 -2
  208. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +0 -58
  209. package/types/src/blocks/ListItemBlockContent/ToggleListItemBlockContent/ToggleListItemBlockContent.d.ts +0 -46
  210. package/types/src/blocks/PageBreakBlockContent/PageBreakBlockContent.d.ts +0 -31
  211. package/types/src/blocks/PageBreakBlockContent/schema.d.ts +0 -86
  212. package/types/src/blocks/ParagraphBlockContent/ParagraphBlockContent.d.ts +0 -52
  213. package/types/src/blocks/QuoteBlockContent/QuoteBlockContent.d.ts +0 -52
  214. package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +0 -39
  215. package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +0 -131
  216. package/types/src/editor/BlockNoteSchema.d.ts +0 -34
  217. package/types/src/editor/BlockNoteTipTapEditor.d.ts +0 -43
  218. /package/src/blocks/{AudioBlockContent → Audio}/parseAudioElement.ts +0 -0
  219. /package/src/blocks/{FileBlockContent → File}/helpers/parse/parseEmbedElement.ts +0 -0
  220. /package/src/blocks/{FileBlockContent → File}/helpers/parse/parseFigureElement.ts +0 -0
  221. /package/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createFigureWithCaption.ts +0 -0
  222. /package/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createLinkWithCaption.ts +0 -0
  223. /package/src/blocks/{FileBlockContent → File/helpers}/uploadToTmpFilesDotOrg_DEV_ONLY.ts +0 -0
  224. /package/src/blocks/{ImageBlockContent → Image}/parseImageElement.ts +0 -0
  225. /package/src/blocks/{ListItemBlockContent → ListItem}/ListItemKeyboardShortcuts.ts +0 -0
  226. /package/src/blocks/{ListItemBlockContent → ListItem}/getListItemContent.ts +0 -0
  227. /package/src/blocks/{TableBlockContent → Table}/TableExtension.ts +0 -0
  228. /package/src/blocks/{VideoBlockContent → Video}/parseVideoElement.ts +0 -0
  229. /package/types/src/blocks/{AudioBlockContent → Audio}/parseAudioElement.d.ts +0 -0
  230. /package/types/src/blocks/{FileBlockContent → File}/helpers/parse/parseEmbedElement.d.ts +0 -0
  231. /package/types/src/blocks/{FileBlockContent → File}/helpers/parse/parseFigureElement.d.ts +0 -0
  232. /package/types/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createFigureWithCaption.d.ts +0 -0
  233. /package/types/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createLinkWithCaption.d.ts +0 -0
  234. /package/types/src/blocks/{FileBlockContent → File/helpers}/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +0 -0
  235. /package/types/src/blocks/{ImageBlockContent → Image}/parseImageElement.d.ts +0 -0
  236. /package/types/src/blocks/{ListItemBlockContent → ListItem}/ListItemKeyboardShortcuts.d.ts +0 -0
  237. /package/types/src/blocks/{ListItemBlockContent → ListItem}/getListItemContent.d.ts +0 -0
  238. /package/types/src/blocks/{TableBlockContent → Table}/TableExtension.d.ts +0 -0
  239. /package/types/src/blocks/{VideoBlockContent → Video}/parseVideoElement.d.ts +0 -0
@@ -1,9 +1,28 @@
1
1
  import type { BlockNoteEditor } from "../../../../editor/BlockNoteEditor.js";
2
- import { BlockFromConfig, FileBlockConfig } from "../../../../schema/index.js";
2
+ import {
3
+ BlockConfig,
4
+ BlockFromConfigNoChildren,
5
+ } from "../../../../schema/index.js";
3
6
  import { createFileBlockWrapper } from "./createFileBlockWrapper.js";
4
7
 
5
8
  export const createResizableFileBlockWrapper = (
6
- block: BlockFromConfig<FileBlockConfig, any, any>,
9
+ block: BlockFromConfigNoChildren<
10
+ BlockConfig<
11
+ string,
12
+ {
13
+ backgroundColor: { default: "default" };
14
+ name: { default: "" };
15
+ url: { default: "" };
16
+ caption: { default: "" };
17
+ showPreview?: { default: true };
18
+ previewWidth?: { default: number };
19
+ textAlignment?: { default: "left" };
20
+ },
21
+ "none"
22
+ >,
23
+ any,
24
+ any
25
+ >,
7
26
  editor: BlockNoteEditor<any, any, any>,
8
27
  element: { dom: HTMLElement; destroy?: () => void },
9
28
  resizeHandlesContainerElement: HTMLElement,
@@ -0,0 +1,138 @@
1
+ import { createBlockConfig, createBlockSpec } from "../../schema/index.js";
2
+ import { createBlockNoteExtension } from "../../editor/BlockNoteExtension.js";
3
+ import {
4
+ addDefaultPropsExternalHTML,
5
+ defaultProps,
6
+ parseDefaultProps,
7
+ } from "../defaultProps.js";
8
+ import { createToggleWrapper } from "../ToggleWrapper/createToggleWrapper.js";
9
+
10
+ const HEADING_LEVELS = [1, 2, 3, 4, 5, 6] as const;
11
+
12
+ export interface HeadingOptions {
13
+ defaultLevel?: (typeof HEADING_LEVELS)[number];
14
+ levels?: readonly number[];
15
+ // TODO should probably use composition instead of this
16
+ allowToggleHeadings?: boolean;
17
+ }
18
+
19
+ export type HeadingBlockConfig = ReturnType<typeof createHeadingBlockConfig>;
20
+
21
+ export const createHeadingBlockConfig = createBlockConfig(
22
+ ({
23
+ defaultLevel = 1,
24
+ levels = HEADING_LEVELS,
25
+ allowToggleHeadings = true,
26
+ }: HeadingOptions = {}) =>
27
+ ({
28
+ type: "heading" as const,
29
+ propSchema: {
30
+ ...defaultProps,
31
+ level: { default: defaultLevel, values: levels },
32
+ ...(allowToggleHeadings
33
+ ? { isToggleable: { default: false, optional: true } as const }
34
+ : {}),
35
+ },
36
+ content: "inline",
37
+ }) as const,
38
+ );
39
+
40
+ export const createHeadingBlockSpec = createBlockSpec(
41
+ createHeadingBlockConfig,
42
+ ({ allowToggleHeadings = true }: HeadingOptions = {}) => ({
43
+ meta: {
44
+ isolating: false,
45
+ },
46
+ parse(e) {
47
+ let level: number;
48
+ switch (e.tagName) {
49
+ case "H1":
50
+ level = 1;
51
+ break;
52
+ case "H2":
53
+ level = 2;
54
+ break;
55
+ case "H3":
56
+ level = 3;
57
+ break;
58
+ case "H4":
59
+ level = 4;
60
+ break;
61
+ case "H5":
62
+ level = 5;
63
+ break;
64
+ case "H6":
65
+ level = 6;
66
+ break;
67
+ default:
68
+ return undefined;
69
+ }
70
+
71
+ return {
72
+ ...parseDefaultProps(e),
73
+ level,
74
+ };
75
+ },
76
+ render(block, editor) {
77
+ const dom = document.createElement(`h${block.props.level}`);
78
+
79
+ if (allowToggleHeadings) {
80
+ const toggleWrapper = createToggleWrapper(block, editor, dom);
81
+ return { ...toggleWrapper, contentDOM: dom };
82
+ }
83
+
84
+ return {
85
+ dom,
86
+ contentDOM: dom,
87
+ };
88
+ },
89
+ toExternalHTML(block) {
90
+ const dom = document.createElement(`h${block.props.level}`);
91
+ addDefaultPropsExternalHTML(block.props, dom);
92
+
93
+ return {
94
+ dom,
95
+ contentDOM: dom,
96
+ };
97
+ },
98
+ }),
99
+ ({ levels = HEADING_LEVELS }: HeadingOptions = {}) => [
100
+ createBlockNoteExtension({
101
+ key: "heading-shortcuts",
102
+ keyboardShortcuts: Object.fromEntries(
103
+ levels.map((level) => [
104
+ `Mod-Alt-${level}`,
105
+ ({ editor }) => {
106
+ const cursorPosition = editor.getTextCursorPosition();
107
+
108
+ if (
109
+ editor.schema.blockSchema[cursorPosition.block.type].content !==
110
+ "inline"
111
+ ) {
112
+ return false;
113
+ }
114
+
115
+ editor.updateBlock(cursorPosition.block, {
116
+ type: "heading",
117
+ props: {
118
+ level: level as any,
119
+ },
120
+ });
121
+ return true;
122
+ },
123
+ ]) ?? [],
124
+ ),
125
+ inputRules: levels.map((level) => ({
126
+ find: new RegExp(`^(#{${level}})\\s$`),
127
+ replace({ match }: { match: RegExpMatchArray }) {
128
+ return {
129
+ type: "heading",
130
+ props: {
131
+ level: match[1].length,
132
+ },
133
+ };
134
+ },
135
+ })),
136
+ }),
137
+ ],
138
+ );
@@ -0,0 +1,190 @@
1
+ import { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
2
+ import {
3
+ BlockFromConfig,
4
+ createBlockConfig,
5
+ createBlockSpec,
6
+ } from "../../schema/index.js";
7
+ import { defaultProps, parseDefaultProps } from "../defaultProps.js";
8
+ import { parseFigureElement } from "../File/helpers/parse/parseFigureElement.js";
9
+ import { createResizableFileBlockWrapper } from "../File/helpers/render/createResizableFileBlockWrapper.js";
10
+ import { createFigureWithCaption } from "../File/helpers/toExternalHTML/createFigureWithCaption.js";
11
+ import { createLinkWithCaption } from "../File/helpers/toExternalHTML/createLinkWithCaption.js";
12
+ import { parseImageElement } from "./parseImageElement.js";
13
+
14
+ export const FILE_IMAGE_ICON_SVG =
15
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M5 11.1005L7 9.1005L12.5 14.6005L16 11.1005L19 14.1005V5H5V11.1005ZM4 3H20C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3ZM15.5 10C14.6716 10 14 9.32843 14 8.5C14 7.67157 14.6716 7 15.5 7C16.3284 7 17 7.67157 17 8.5C17 9.32843 16.3284 10 15.5 10Z"></path></svg>';
16
+
17
+ export interface ImageOptions {
18
+ icon?: string;
19
+ }
20
+
21
+ export type ImageBlockConfig = ReturnType<typeof createImageBlockConfig>;
22
+
23
+ export const createImageBlockConfig = createBlockConfig(
24
+ (_ctx: ImageOptions = {}) =>
25
+ ({
26
+ type: "image" as const,
27
+ propSchema: {
28
+ textAlignment: defaultProps.textAlignment,
29
+ backgroundColor: defaultProps.backgroundColor,
30
+ // File name.
31
+ name: {
32
+ default: "" as const,
33
+ },
34
+ // File url.
35
+ url: {
36
+ default: "" as const,
37
+ },
38
+ // File caption.
39
+ caption: {
40
+ default: "" as const,
41
+ },
42
+
43
+ showPreview: {
44
+ default: true,
45
+ },
46
+ // File preview width in px.
47
+ previewWidth: {
48
+ default: undefined,
49
+ type: "number" as const,
50
+ },
51
+ },
52
+ content: "none" as const,
53
+ }) as const,
54
+ );
55
+
56
+ export const imageParse =
57
+ (_config: ImageOptions = {}) =>
58
+ (element: HTMLElement) => {
59
+ if (element.tagName === "IMG") {
60
+ // Ignore if parent figure has already been parsed.
61
+ if (element.closest("figure")) {
62
+ return undefined;
63
+ }
64
+
65
+ const { backgroundColor } = parseDefaultProps(element);
66
+
67
+ return {
68
+ ...parseImageElement(element as HTMLImageElement),
69
+ backgroundColor,
70
+ };
71
+ }
72
+
73
+ if (element.tagName === "FIGURE") {
74
+ const parsedFigure = parseFigureElement(element, "img");
75
+ if (!parsedFigure) {
76
+ return undefined;
77
+ }
78
+
79
+ const { targetElement, caption } = parsedFigure;
80
+
81
+ const { backgroundColor } = parseDefaultProps(element);
82
+
83
+ return {
84
+ ...parseImageElement(targetElement as HTMLImageElement),
85
+ backgroundColor,
86
+ caption,
87
+ };
88
+ }
89
+
90
+ return undefined;
91
+ };
92
+
93
+ export const imageRender =
94
+ (config: ImageOptions = {}) =>
95
+ (
96
+ block: BlockFromConfig<ReturnType<typeof createImageBlockConfig>, any, any>,
97
+ editor: BlockNoteEditor<
98
+ Record<"image", ReturnType<typeof createImageBlockConfig>>,
99
+ any,
100
+ any
101
+ >,
102
+ ) => {
103
+ const icon = document.createElement("div");
104
+ icon.innerHTML = config.icon ?? FILE_IMAGE_ICON_SVG;
105
+
106
+ const imageWrapper = document.createElement("div");
107
+ imageWrapper.className = "bn-visual-media-wrapper";
108
+
109
+ const image = document.createElement("img");
110
+ image.className = "bn-visual-media";
111
+ if (editor.resolveFileUrl) {
112
+ editor.resolveFileUrl(block.props.url).then((downloadUrl) => {
113
+ image.src = downloadUrl;
114
+ });
115
+ } else {
116
+ image.src = block.props.url;
117
+ }
118
+
119
+ image.alt = block.props.name || block.props.caption || "BlockNote image";
120
+ image.contentEditable = "false";
121
+ image.draggable = false;
122
+ imageWrapper.appendChild(image);
123
+
124
+ return createResizableFileBlockWrapper(
125
+ block,
126
+ editor,
127
+ { dom: imageWrapper },
128
+ imageWrapper,
129
+ icon.firstElementChild as HTMLElement,
130
+ );
131
+ };
132
+
133
+ export const imageToExternalHTML =
134
+ (_config: ImageOptions = {}) =>
135
+ (
136
+ block: BlockFromConfig<ReturnType<typeof createImageBlockConfig>, any, any>,
137
+ _editor: BlockNoteEditor<
138
+ Record<"image", ReturnType<typeof createImageBlockConfig>>,
139
+ any,
140
+ any
141
+ >,
142
+ ) => {
143
+ if (!block.props.url) {
144
+ const div = document.createElement("p");
145
+ div.textContent = "Add image";
146
+
147
+ return {
148
+ dom: div,
149
+ };
150
+ }
151
+
152
+ let image;
153
+ if (block.props.showPreview) {
154
+ image = document.createElement("img");
155
+ image.src = block.props.url;
156
+ image.alt = block.props.name || block.props.caption || "BlockNote image";
157
+ if (block.props.previewWidth) {
158
+ image.width = block.props.previewWidth;
159
+ }
160
+ } else {
161
+ image = document.createElement("a");
162
+ image.href = block.props.url;
163
+ image.textContent = block.props.name || block.props.url;
164
+ }
165
+
166
+ if (block.props.caption) {
167
+ if (block.props.showPreview) {
168
+ return createFigureWithCaption(image, block.props.caption);
169
+ } else {
170
+ return createLinkWithCaption(image, block.props.caption);
171
+ }
172
+ }
173
+
174
+ return {
175
+ dom: image,
176
+ };
177
+ };
178
+
179
+ export const createImageBlockSpec = createBlockSpec(
180
+ createImageBlockConfig,
181
+ (config) => ({
182
+ meta: {
183
+ fileBlockAccept: ["image/*"],
184
+ },
185
+ parse: imageParse(config),
186
+ render: imageRender(config),
187
+ toExternalHTML: imageToExternalHTML(config),
188
+ runsBefore: ["file"],
189
+ }),
190
+ );
@@ -0,0 +1,116 @@
1
+ import { createBlockNoteExtension } from "../../../editor/BlockNoteExtension.js";
2
+ import { createBlockConfig, createBlockSpec } from "../../../schema/index.js";
3
+ import {
4
+ addDefaultPropsExternalHTML,
5
+ defaultProps,
6
+ parseDefaultProps,
7
+ } from "../../defaultProps.js";
8
+ import { handleEnter } from "../../utils/listItemEnterHandler.js";
9
+ import { getListItemContent } from "../getListItemContent.js";
10
+
11
+ export type BulletListItemBlockConfig = ReturnType<
12
+ typeof createBulletListItemBlockConfig
13
+ >;
14
+
15
+ export const createBulletListItemBlockConfig = createBlockConfig(
16
+ () =>
17
+ ({
18
+ type: "bulletListItem" as const,
19
+ propSchema: {
20
+ ...defaultProps,
21
+ },
22
+ content: "inline",
23
+ }) as const,
24
+ );
25
+
26
+ export const createBulletListItemBlockSpec = createBlockSpec(
27
+ createBulletListItemBlockConfig,
28
+ {
29
+ meta: {
30
+ isolating: false,
31
+ },
32
+ parse(element) {
33
+ if (element.tagName !== "LI") {
34
+ return undefined;
35
+ }
36
+
37
+ const parent = element.parentElement;
38
+
39
+ if (parent === null) {
40
+ return undefined;
41
+ }
42
+
43
+ if (
44
+ parent.tagName === "UL" ||
45
+ (parent.tagName === "DIV" && parent.parentElement?.tagName === "UL")
46
+ ) {
47
+ return parseDefaultProps(element);
48
+ }
49
+
50
+ return undefined;
51
+ },
52
+ // As `li` elements can contain multiple paragraphs, we need to merge their contents
53
+ // into a single one so that ProseMirror can parse everything correctly.
54
+ parseContent: ({ el, schema }) =>
55
+ getListItemContent(el, schema, "bulletListItem"),
56
+ render() {
57
+ // We use a <p> tag, because for <li> tags we'd need a <ul> element to put
58
+ // them in to be semantically correct, which we can't have due to the
59
+ // schema.
60
+ const dom = document.createElement("p");
61
+
62
+ return {
63
+ dom,
64
+ contentDOM: dom,
65
+ };
66
+ },
67
+ toExternalHTML(block) {
68
+ const li = document.createElement("li");
69
+ const p = document.createElement("p");
70
+ addDefaultPropsExternalHTML(block.props, li);
71
+ li.appendChild(p);
72
+
73
+ return {
74
+ dom: li,
75
+ contentDOM: p,
76
+ };
77
+ },
78
+ },
79
+ [
80
+ createBlockNoteExtension({
81
+ key: "bullet-list-item-shortcuts",
82
+ keyboardShortcuts: {
83
+ Enter: ({ editor }) => {
84
+ return handleEnter(editor, "bulletListItem");
85
+ },
86
+ "Mod-Shift-8": ({ editor }) => {
87
+ const cursorPosition = editor.getTextCursorPosition();
88
+
89
+ if (
90
+ editor.schema.blockSchema[cursorPosition.block.type].content !==
91
+ "inline"
92
+ ) {
93
+ return false;
94
+ }
95
+
96
+ editor.updateBlock(cursorPosition.block, {
97
+ type: "bulletListItem",
98
+ props: {},
99
+ });
100
+ return true;
101
+ },
102
+ },
103
+ inputRules: [
104
+ {
105
+ find: new RegExp(`^[-+*]\\s$`),
106
+ replace() {
107
+ return {
108
+ type: "bulletListItem",
109
+ props: {},
110
+ };
111
+ },
112
+ },
113
+ ],
114
+ }),
115
+ ],
116
+ );
@@ -0,0 +1,175 @@
1
+ import { createBlockNoteExtension } from "../../../editor/BlockNoteExtension.js";
2
+ import { createBlockConfig, createBlockSpec } from "../../../schema/index.js";
3
+ import {
4
+ addDefaultPropsExternalHTML,
5
+ defaultProps,
6
+ parseDefaultProps,
7
+ } from "../../defaultProps.js";
8
+ import { handleEnter } from "../../utils/listItemEnterHandler.js";
9
+ import { getListItemContent } from "../getListItemContent.js";
10
+
11
+ export type CheckListItemBlockConfig = ReturnType<
12
+ typeof createCheckListItemConfig
13
+ >;
14
+
15
+ export const createCheckListItemConfig = createBlockConfig(
16
+ () =>
17
+ ({
18
+ type: "checkListItem" as const,
19
+ propSchema: {
20
+ ...defaultProps,
21
+ checked: { default: false, type: "boolean" },
22
+ },
23
+ content: "inline",
24
+ }) as const,
25
+ );
26
+
27
+ export const createCheckListItemBlockSpec = createBlockSpec(
28
+ createCheckListItemConfig,
29
+ {
30
+ meta: {
31
+ isolating: false,
32
+ },
33
+ parse(element) {
34
+ if (element.tagName === "input") {
35
+ // Ignore if we already parsed an ancestor list item to avoid double-parsing.
36
+ if (element.closest("[data-content-type]") || element.closest("li")) {
37
+ return undefined;
38
+ }
39
+
40
+ if ((element as HTMLInputElement).type === "checkbox") {
41
+ return { checked: (element as HTMLInputElement).checked };
42
+ }
43
+ return undefined;
44
+ }
45
+ if (element.tagName !== "LI") {
46
+ return undefined;
47
+ }
48
+
49
+ const parent = element.parentElement;
50
+
51
+ if (parent === null) {
52
+ return undefined;
53
+ }
54
+
55
+ if (
56
+ parent.tagName === "UL" ||
57
+ (parent.tagName === "DIV" && parent.parentElement?.tagName === "UL")
58
+ ) {
59
+ const checkbox =
60
+ (element.querySelector("input[type=checkbox]") as HTMLInputElement) ||
61
+ null;
62
+
63
+ if (checkbox === null) {
64
+ return undefined;
65
+ }
66
+
67
+ return { ...parseDefaultProps(element), checked: checkbox.checked };
68
+ }
69
+
70
+ return;
71
+ },
72
+ // As `li` elements can contain multiple paragraphs, we need to merge their contents
73
+ // into a single one so that ProseMirror can parse everything correctly.
74
+ parseContent: ({ el, schema }) =>
75
+ getListItemContent(el, schema, "checkListItem"),
76
+ render(block, editor) {
77
+ const dom = document.createDocumentFragment();
78
+ const checkbox = document.createElement("input");
79
+ checkbox.type = "checkbox";
80
+ checkbox.checked = block.props.checked;
81
+ if (block.props.checked) {
82
+ checkbox.setAttribute("checked", "");
83
+ }
84
+ checkbox.addEventListener("change", () => {
85
+ editor.updateBlock(block, { props: { checked: !block.props.checked } });
86
+ });
87
+ // We use a <p> tag, because for <li> tags we'd need a <ul> element to put
88
+ // them in to be semantically correct, which we can't have due to the
89
+ // schema.
90
+ const paragraph = document.createElement("p");
91
+
92
+ dom.appendChild(checkbox);
93
+ dom.appendChild(paragraph);
94
+
95
+ return {
96
+ dom,
97
+ contentDOM: paragraph,
98
+ };
99
+ },
100
+ toExternalHTML(block) {
101
+ const dom = document.createElement("li");
102
+ const checkbox = document.createElement("input");
103
+ checkbox.type = "checkbox";
104
+ checkbox.checked = block.props.checked;
105
+ if (block.props.checked) {
106
+ checkbox.setAttribute("checked", "");
107
+ }
108
+ // We use a <p> tag, because for <li> tags we'd need a <ul> element to put
109
+ // them in to be semantically correct, which we can't have due to the
110
+ // schema.
111
+ const paragraph = document.createElement("p");
112
+ addDefaultPropsExternalHTML(block.props, dom);
113
+
114
+ dom.appendChild(checkbox);
115
+ dom.appendChild(paragraph);
116
+
117
+ return {
118
+ dom,
119
+ contentDOM: paragraph,
120
+ };
121
+ },
122
+ runsBefore: ["bulletListItem"],
123
+ },
124
+ [
125
+ createBlockNoteExtension({
126
+ key: "check-list-item-shortcuts",
127
+ keyboardShortcuts: {
128
+ Enter: ({ editor }) => {
129
+ return handleEnter(editor, "checkListItem");
130
+ },
131
+ "Mod-Shift-9": ({ editor }) => {
132
+ const cursorPosition = editor.getTextCursorPosition();
133
+
134
+ if (
135
+ editor.schema.blockSchema[cursorPosition.block.type].content !==
136
+ "inline"
137
+ ) {
138
+ return false;
139
+ }
140
+
141
+ editor.updateBlock(cursorPosition.block, {
142
+ type: "checkListItem",
143
+ props: {},
144
+ });
145
+ return true;
146
+ },
147
+ },
148
+ inputRules: [
149
+ {
150
+ find: new RegExp(`\\[\\s*\\]\\s$`),
151
+ replace() {
152
+ return {
153
+ type: "checkListItem",
154
+ props: {
155
+ checked: false,
156
+ },
157
+ content: [],
158
+ };
159
+ },
160
+ },
161
+ {
162
+ find: new RegExp(`\\[[Xx]\\]\\s$`),
163
+ replace() {
164
+ return {
165
+ type: "checkListItem",
166
+ props: {
167
+ checked: true,
168
+ },
169
+ };
170
+ },
171
+ },
172
+ ],
173
+ }),
174
+ ],
175
+ );