@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,144 +0,0 @@
1
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
2
- import {
3
- BlockFromConfig,
4
- createBlockSpec,
5
- FileBlockConfig,
6
- Props,
7
- PropSchema,
8
- } from "../../schema/index.js";
9
- import { defaultProps } from "../defaultProps.js";
10
-
11
- import { parseFigureElement } from "../FileBlockContent/helpers/parse/parseFigureElement.js";
12
- import { createFileBlockWrapper } from "../FileBlockContent/helpers/render/createFileBlockWrapper.js";
13
- import { createFigureWithCaption } from "../FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.js";
14
- import { createLinkWithCaption } from "../FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.js";
15
- import { parseAudioElement } from "./parseAudioElement.js";
16
-
17
- export const FILE_AUDIO_ICON_SVG =
18
- '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M2 16.0001H5.88889L11.1834 20.3319C11.2727 20.405 11.3846 20.4449 11.5 20.4449C11.7761 20.4449 12 20.2211 12 19.9449V4.05519C12 3.93977 11.9601 3.8279 11.887 3.73857C11.7121 3.52485 11.3971 3.49335 11.1834 3.66821L5.88889 8.00007H2C1.44772 8.00007 1 8.44778 1 9.00007V15.0001C1 15.5524 1.44772 16.0001 2 16.0001ZM23 12C23 15.292 21.5539 18.2463 19.2622 20.2622L17.8445 18.8444C19.7758 17.1937 21 14.7398 21 12C21 9.26016 19.7758 6.80629 17.8445 5.15557L19.2622 3.73779C21.5539 5.75368 23 8.70795 23 12ZM18 12C18 10.0883 17.106 8.38548 15.7133 7.28673L14.2842 8.71584C15.3213 9.43855 16 10.64 16 12C16 13.36 15.3213 14.5614 14.2842 15.2841L15.7133 16.7132C17.106 15.6145 18 13.9116 18 12Z"></path></svg>';
19
-
20
- export const audioPropSchema = {
21
- backgroundColor: defaultProps.backgroundColor,
22
- // File name.
23
- name: {
24
- default: "" as const,
25
- },
26
- // File url.
27
- url: {
28
- default: "" as const,
29
- },
30
- // File caption.
31
- caption: {
32
- default: "" as const,
33
- },
34
-
35
- showPreview: {
36
- default: true,
37
- },
38
- } satisfies PropSchema;
39
-
40
- export const audioBlockConfig = {
41
- type: "audio" as const,
42
- propSchema: audioPropSchema,
43
- content: "none",
44
- isFileBlock: true,
45
- fileBlockAccept: ["audio/*"],
46
- } satisfies FileBlockConfig;
47
-
48
- export const audioRender = (
49
- block: BlockFromConfig<typeof audioBlockConfig, any, any>,
50
- editor: BlockNoteEditor<any, any, any>,
51
- ) => {
52
- const icon = document.createElement("div");
53
- icon.innerHTML = FILE_AUDIO_ICON_SVG;
54
-
55
- const audio = document.createElement("audio");
56
- audio.className = "bn-audio";
57
- if (editor.resolveFileUrl) {
58
- editor.resolveFileUrl(block.props.url).then((downloadUrl) => {
59
- audio.src = downloadUrl;
60
- });
61
- } else {
62
- audio.src = block.props.url;
63
- }
64
- audio.controls = true;
65
- audio.contentEditable = "false";
66
- audio.draggable = false;
67
-
68
- return createFileBlockWrapper(
69
- block,
70
- editor,
71
- { dom: audio },
72
- icon.firstElementChild as HTMLElement,
73
- );
74
- };
75
-
76
- export const audioParse = (
77
- element: HTMLElement,
78
- ): Partial<Props<typeof audioBlockConfig.propSchema>> | undefined => {
79
- if (element.tagName === "AUDIO") {
80
- // Ignore if parent figure has already been parsed.
81
- if (element.closest("figure")) {
82
- return undefined;
83
- }
84
-
85
- return parseAudioElement(element as HTMLAudioElement);
86
- }
87
-
88
- if (element.tagName === "FIGURE") {
89
- const parsedFigure = parseFigureElement(element, "audio");
90
- if (!parsedFigure) {
91
- return undefined;
92
- }
93
-
94
- const { targetElement, caption } = parsedFigure;
95
-
96
- return {
97
- ...parseAudioElement(targetElement as HTMLAudioElement),
98
- caption,
99
- };
100
- }
101
-
102
- return undefined;
103
- };
104
-
105
- export const audioToExternalHTML = (
106
- block: BlockFromConfig<typeof audioBlockConfig, any, any>,
107
- ) => {
108
- if (!block.props.url) {
109
- const div = document.createElement("p");
110
- div.textContent = "Add audio";
111
-
112
- return {
113
- dom: div,
114
- };
115
- }
116
-
117
- let audio;
118
- if (block.props.showPreview) {
119
- audio = document.createElement("audio");
120
- audio.src = block.props.url;
121
- } else {
122
- audio = document.createElement("a");
123
- audio.href = block.props.url;
124
- audio.textContent = block.props.name || block.props.url;
125
- }
126
-
127
- if (block.props.caption) {
128
- if (block.props.showPreview) {
129
- return createFigureWithCaption(audio, block.props.caption);
130
- } else {
131
- return createLinkWithCaption(audio, block.props.caption);
132
- }
133
- }
134
-
135
- return {
136
- dom: audio,
137
- };
138
- };
139
-
140
- export const AudioBlock = createBlockSpec(audioBlockConfig, {
141
- render: audioRender,
142
- parse: audioParse,
143
- toExternalHTML: audioToExternalHTML,
144
- });
@@ -1,445 +0,0 @@
1
- import type { HighlighterGeneric } from "@shikijs/types";
2
- import { InputRule, isTextSelection } from "@tiptap/core";
3
- import { TextSelection } from "@tiptap/pm/state";
4
- import { Parser, createHighlightPlugin } from "prosemirror-highlight";
5
- import { createParser } from "prosemirror-highlight/shiki";
6
- import { BlockNoteEditor } from "../../index.js";
7
- import {
8
- PropSchema,
9
- createBlockSpecFromStronglyTypedTiptapNode,
10
- createStronglyTypedTiptapNode,
11
- } from "../../schema/index.js";
12
- import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers.js";
13
-
14
- export type CodeBlockOptions = {
15
- /**
16
- * Whether to indent lines with a tab when the user presses `Tab` in a code block.
17
- *
18
- * @default true
19
- */
20
- indentLineWithTab?: boolean;
21
- /**
22
- * The default language to use for code blocks.
23
- *
24
- * @default "text"
25
- */
26
- defaultLanguage?: string;
27
- /**
28
- * The languages that are supported in the editor.
29
- *
30
- * @example
31
- * {
32
- * javascript: {
33
- * name: "JavaScript",
34
- * aliases: ["js"],
35
- * },
36
- * typescript: {
37
- * name: "TypeScript",
38
- * aliases: ["ts"],
39
- * },
40
- * }
41
- */
42
- supportedLanguages: Record<
43
- string,
44
- {
45
- /**
46
- * The display name of the language.
47
- */
48
- name: string;
49
- /**
50
- * Aliases for this language.
51
- */
52
- aliases?: string[];
53
- }
54
- >;
55
- /**
56
- * The highlighter to use for code blocks.
57
- */
58
- createHighlighter?: () => Promise<HighlighterGeneric<any, any>>;
59
- };
60
-
61
- type CodeBlockConfigOptions = {
62
- editor: BlockNoteEditor<any, any, any>;
63
- };
64
-
65
- export const shikiParserSymbol = Symbol.for("blocknote.shikiParser");
66
- export const shikiHighlighterPromiseSymbol = Symbol.for(
67
- "blocknote.shikiHighlighterPromise",
68
- );
69
- export const defaultCodeBlockPropSchema = {
70
- language: {
71
- default: "text",
72
- },
73
- } satisfies PropSchema;
74
-
75
- const CodeBlockContent = createStronglyTypedTiptapNode({
76
- name: "codeBlock",
77
- content: "inline*",
78
- group: "blockContent",
79
- marks: "insertion deletion modification",
80
- code: true,
81
- defining: true,
82
- addOptions() {
83
- return {
84
- defaultLanguage: "text",
85
- indentLineWithTab: true,
86
- supportedLanguages: {},
87
- };
88
- },
89
- addAttributes() {
90
- const options = this.options as CodeBlockConfigOptions;
91
-
92
- return {
93
- language: {
94
- default: options.editor.settings.codeBlock.defaultLanguage,
95
- parseHTML: (inputElement) => {
96
- let element = inputElement as HTMLElement | null;
97
- let language: string | null = null;
98
-
99
- if (
100
- element?.tagName === "DIV" &&
101
- element?.dataset.contentType === "codeBlock"
102
- ) {
103
- element = element.children[0] as HTMLElement | null;
104
- }
105
-
106
- if (element?.tagName === "PRE") {
107
- element = element?.children[0] as HTMLElement | null;
108
- }
109
-
110
- const dataLanguage = element?.getAttribute("data-language");
111
-
112
- if (dataLanguage) {
113
- language = dataLanguage.toLowerCase();
114
- } else {
115
- const classNames = [...(element?.className.split(" ") || [])];
116
- const languages = classNames
117
- .filter((className) => className.startsWith("language-"))
118
- .map((className) => className.replace("language-", ""));
119
-
120
- if (languages.length > 0) {
121
- language = languages[0].toLowerCase();
122
- }
123
- }
124
-
125
- if (!language) {
126
- return null;
127
- }
128
-
129
- return (
130
- getLanguageId(options.editor.settings.codeBlock, language) ??
131
- language
132
- );
133
- },
134
- renderHTML: (attributes) => {
135
- return attributes.language
136
- ? {
137
- class: `language-${attributes.language}`,
138
- "data-language": attributes.language,
139
- }
140
- : {};
141
- },
142
- },
143
- };
144
- },
145
- parseHTML() {
146
- return [
147
- // Parse from internal HTML.
148
- {
149
- tag: "div[data-content-type=" + this.name + "]",
150
- contentElement: ".bn-inline-content",
151
- },
152
- // Parse from external HTML.
153
- {
154
- tag: "pre",
155
- // contentElement: "code",
156
- preserveWhitespace: "full",
157
- },
158
- ];
159
- },
160
- renderHTML({ HTMLAttributes }) {
161
- const pre = document.createElement("pre");
162
- const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
163
- this.name,
164
- "code",
165
- this.options.domAttributes?.blockContent || {},
166
- {
167
- ...(this.options.domAttributes?.inlineContent || {}),
168
- ...HTMLAttributes,
169
- },
170
- );
171
-
172
- dom.removeChild(contentDOM);
173
- dom.appendChild(pre);
174
- pre.appendChild(contentDOM);
175
-
176
- return {
177
- dom,
178
- contentDOM,
179
- };
180
- },
181
- addNodeView() {
182
- const options = this.options as CodeBlockConfigOptions;
183
-
184
- return ({ editor, node, getPos, HTMLAttributes }) => {
185
- const pre = document.createElement("pre");
186
- const select = document.createElement("select");
187
- const selectWrapper = document.createElement("div");
188
- const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
189
- this.name,
190
- "code",
191
- {
192
- ...(this.options.domAttributes?.blockContent || {}),
193
- ...HTMLAttributes,
194
- },
195
- this.options.domAttributes?.inlineContent || {},
196
- );
197
- const handleLanguageChange = (event: Event) => {
198
- const language = (event.target as HTMLSelectElement).value;
199
-
200
- editor.commands.command(({ tr }) => {
201
- tr.setNodeAttribute(getPos(), "language", language);
202
-
203
- return true;
204
- });
205
- };
206
-
207
- Object.entries(
208
- options.editor.settings.codeBlock.supportedLanguages,
209
- ).forEach(([id, { name }]) => {
210
- const option = document.createElement("option");
211
-
212
- option.value = id;
213
- option.text = name;
214
- select.appendChild(option);
215
- });
216
-
217
- selectWrapper.contentEditable = "false";
218
- select.value =
219
- node.attrs.language ||
220
- options.editor.settings.codeBlock.defaultLanguage;
221
- dom.removeChild(contentDOM);
222
- dom.appendChild(selectWrapper);
223
- dom.appendChild(pre);
224
- pre.appendChild(contentDOM);
225
- selectWrapper.appendChild(select);
226
- select.addEventListener("change", handleLanguageChange);
227
-
228
- return {
229
- dom,
230
- contentDOM,
231
- update: (newNode) => {
232
- if (newNode.type !== this.type) {
233
- return false;
234
- }
235
-
236
- return true;
237
- },
238
- destroy: () => {
239
- select.removeEventListener("change", handleLanguageChange);
240
- },
241
- };
242
- };
243
- },
244
- addProseMirrorPlugins() {
245
- const options = this.options as CodeBlockConfigOptions;
246
- const globalThisForShiki = globalThis as {
247
- [shikiHighlighterPromiseSymbol]?: Promise<HighlighterGeneric<any, any>>;
248
- [shikiParserSymbol]?: Parser;
249
- };
250
-
251
- let highlighter: HighlighterGeneric<any, any> | undefined;
252
- let parser: Parser | undefined;
253
- let hasWarned = false;
254
- const lazyParser: Parser = (parserOptions) => {
255
- if (!options.editor.settings.codeBlock.createHighlighter) {
256
- if (process.env.NODE_ENV === "development" && !hasWarned) {
257
- // eslint-disable-next-line no-console
258
- console.log(
259
- "For syntax highlighting of code blocks, you must provide a `codeBlock.createHighlighter` function",
260
- );
261
- hasWarned = true;
262
- }
263
- return [];
264
- }
265
- if (!highlighter) {
266
- globalThisForShiki[shikiHighlighterPromiseSymbol] =
267
- globalThisForShiki[shikiHighlighterPromiseSymbol] ||
268
- options.editor.settings.codeBlock.createHighlighter();
269
-
270
- return globalThisForShiki[shikiHighlighterPromiseSymbol].then(
271
- (createdHighlighter) => {
272
- highlighter = createdHighlighter;
273
- },
274
- );
275
- }
276
- const language = getLanguageId(
277
- options.editor.settings.codeBlock,
278
- parserOptions.language!,
279
- );
280
-
281
- if (
282
- !language ||
283
- language === "text" ||
284
- language === "none" ||
285
- language === "plaintext" ||
286
- language === "txt"
287
- ) {
288
- return [];
289
- }
290
-
291
- if (!highlighter.getLoadedLanguages().includes(language)) {
292
- return highlighter.loadLanguage(language);
293
- }
294
-
295
- if (!parser) {
296
- parser =
297
- globalThisForShiki[shikiParserSymbol] ||
298
- createParser(highlighter as any);
299
- globalThisForShiki[shikiParserSymbol] = parser;
300
- }
301
-
302
- return parser(parserOptions);
303
- };
304
-
305
- const shikiLazyPlugin = createHighlightPlugin({
306
- parser: lazyParser,
307
- languageExtractor: (node) => node.attrs.language,
308
- nodeTypes: [this.name],
309
- });
310
-
311
- return [shikiLazyPlugin];
312
- },
313
- addInputRules() {
314
- const options = this.options as CodeBlockConfigOptions;
315
-
316
- return [
317
- new InputRule({
318
- find: /^```(.*?)\s$/,
319
- handler: ({ state, range, match }) => {
320
- const $start = state.doc.resolve(range.from);
321
- const languageName = match[1].trim();
322
- const attributes = {
323
- language:
324
- getLanguageId(options.editor.settings.codeBlock, languageName) ??
325
- languageName,
326
- };
327
-
328
- if (
329
- !$start
330
- .node(-1)
331
- .canReplaceWith(
332
- $start.index(-1),
333
- $start.indexAfter(-1),
334
- this.type,
335
- )
336
- ) {
337
- return null;
338
- }
339
-
340
- state.tr
341
- .delete(range.from, range.to)
342
- .setBlockType(range.from, range.from, this.type, attributes)
343
- .setSelection(TextSelection.create(state.tr.doc, range.from));
344
-
345
- return;
346
- },
347
- }),
348
- ];
349
- },
350
- addKeyboardShortcuts() {
351
- return {
352
- Delete: ({ editor }) => {
353
- const { selection } = editor.state;
354
- const { $from } = selection;
355
-
356
- // When inside empty codeblock, on `DELETE` key press, delete the codeblock
357
- if (
358
- editor.isActive(this.name) &&
359
- !$from.parent.textContent &&
360
- isTextSelection(selection)
361
- ) {
362
- // Get the start position of the codeblock for node selection
363
- const from = $from.pos - $from.parentOffset - 2;
364
-
365
- editor.chain().setNodeSelection(from).deleteSelection().run();
366
-
367
- return true;
368
- }
369
-
370
- return false;
371
- },
372
- Tab: ({ editor }) => {
373
- if (!this.options.indentLineWithTab) {
374
- return false;
375
- }
376
- if (editor.isActive(this.name)) {
377
- editor.commands.insertContent(" ");
378
- return true;
379
- }
380
-
381
- return false;
382
- },
383
- Enter: ({ editor }) => {
384
- const { $from } = editor.state.selection;
385
-
386
- if (!editor.isActive(this.name)) {
387
- return false;
388
- }
389
-
390
- const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2;
391
- const endsWithDoubleNewline = $from.parent.textContent.endsWith("\n\n");
392
-
393
- if (!isAtEnd || !endsWithDoubleNewline) {
394
- editor.commands.insertContent("\n");
395
- return true;
396
- }
397
-
398
- return editor
399
- .chain()
400
- .command(({ tr }) => {
401
- tr.delete($from.pos - 2, $from.pos);
402
-
403
- return true;
404
- })
405
- .exitCode()
406
- .run();
407
- },
408
- "Shift-Enter": ({ editor }) => {
409
- const { $from } = editor.state.selection;
410
-
411
- if (!editor.isActive(this.name)) {
412
- return false;
413
- }
414
-
415
- editor
416
- .chain()
417
- .insertContentAt(
418
- $from.pos - $from.parentOffset + $from.parent.nodeSize,
419
- {
420
- type: "paragraph",
421
- },
422
- )
423
- .run();
424
-
425
- return true;
426
- },
427
- };
428
- },
429
- });
430
-
431
- export const CodeBlock = createBlockSpecFromStronglyTypedTiptapNode(
432
- CodeBlockContent,
433
- defaultCodeBlockPropSchema,
434
- );
435
-
436
- function getLanguageId(
437
- options: CodeBlockOptions,
438
- languageName: string,
439
- ): string | undefined {
440
- return Object.entries(options.supportedLanguages).find(
441
- ([id, { aliases }]) => {
442
- return aliases?.includes(languageName) || id === languageName;
443
- },
444
- )?.[0];
445
- }
@@ -1,100 +0,0 @@
1
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor.js";
2
- import {
3
- BlockFromConfig,
4
- FileBlockConfig,
5
- PropSchema,
6
- createBlockSpec,
7
- } from "../../schema/index.js";
8
- import { defaultProps } from "../defaultProps.js";
9
- import { parseEmbedElement } from "./helpers/parse/parseEmbedElement.js";
10
- import { parseFigureElement } from "./helpers/parse/parseFigureElement.js";
11
- import { createFileBlockWrapper } from "./helpers/render/createFileBlockWrapper.js";
12
- import { createLinkWithCaption } from "./helpers/toExternalHTML/createLinkWithCaption.js";
13
-
14
- export const filePropSchema = {
15
- backgroundColor: defaultProps.backgroundColor,
16
- // File name.
17
- name: {
18
- default: "" as const,
19
- },
20
- // File url.
21
- url: {
22
- default: "" as const,
23
- },
24
- // File caption.
25
- caption: {
26
- default: "" as const,
27
- },
28
- } satisfies PropSchema;
29
-
30
- export const fileBlockConfig = {
31
- type: "file" as const,
32
- propSchema: filePropSchema,
33
- content: "none",
34
- isFileBlock: true,
35
- } satisfies FileBlockConfig;
36
-
37
- export const fileRender = (
38
- block: BlockFromConfig<typeof fileBlockConfig, any, any>,
39
- editor: BlockNoteEditor<any, any, any>,
40
- ) => {
41
- return createFileBlockWrapper(block, editor);
42
- };
43
-
44
- export const fileParse = (element: HTMLElement) => {
45
- if (element.tagName === "EMBED") {
46
- // Ignore if parent figure has already been parsed.
47
- if (element.closest("figure")) {
48
- return undefined;
49
- }
50
-
51
- return parseEmbedElement(element as HTMLEmbedElement);
52
- }
53
-
54
- if (element.tagName === "FIGURE") {
55
- const parsedFigure = parseFigureElement(element, "embed");
56
- if (!parsedFigure) {
57
- return undefined;
58
- }
59
-
60
- const { targetElement, caption } = parsedFigure;
61
-
62
- return {
63
- ...parseEmbedElement(targetElement as HTMLEmbedElement),
64
- caption,
65
- };
66
- }
67
-
68
- return undefined;
69
- };
70
-
71
- export const fileToExternalHTML = (
72
- block: BlockFromConfig<typeof fileBlockConfig, any, any>,
73
- ) => {
74
- if (!block.props.url) {
75
- const div = document.createElement("p");
76
- div.textContent = "Add file";
77
-
78
- return {
79
- dom: div,
80
- };
81
- }
82
-
83
- const fileSrcLink = document.createElement("a");
84
- fileSrcLink.href = block.props.url;
85
- fileSrcLink.textContent = block.props.name || block.props.url;
86
-
87
- if (block.props.caption) {
88
- return createLinkWithCaption(fileSrcLink, block.props.caption);
89
- }
90
-
91
- return {
92
- dom: fileSrcLink,
93
- };
94
- };
95
-
96
- export const FileBlock = createBlockSpec(fileBlockConfig, {
97
- render: fileRender,
98
- parse: fileParse,
99
- toExternalHTML: fileToExternalHTML,
100
- });