@blocknote/core 0.13.2 → 0.13.4

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 (163) hide show
  1. package/dist/blocknote.js +5730 -2891
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +7 -7
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/dist/webpack-stats.json +1 -1
  7. package/package.json +2 -2
  8. package/src/api/exporters/html/__snapshots__/file/basic/external.html +1 -0
  9. package/src/api/exporters/html/__snapshots__/file/basic/internal.html +1 -0
  10. package/src/api/exporters/html/__snapshots__/file/button/external.html +1 -0
  11. package/src/api/exporters/html/__snapshots__/file/button/internal.html +1 -0
  12. package/src/api/exporters/html/__snapshots__/file/nested/external.html +1 -0
  13. package/src/api/exporters/html/__snapshots__/file/nested/internal.html +1 -0
  14. package/src/api/exporters/html/__snapshots__/file/noCaption/external.html +1 -0
  15. package/src/api/exporters/html/__snapshots__/file/noCaption/internal.html +1 -0
  16. package/src/api/exporters/html/__snapshots__/file/noName/external.html +1 -0
  17. package/src/api/exporters/html/__snapshots__/file/noName/internal.html +1 -0
  18. package/src/api/exporters/html/__snapshots__/image/basic/external.html +1 -1
  19. package/src/api/exporters/html/__snapshots__/image/basic/internal.html +1 -1
  20. package/src/api/exporters/html/__snapshots__/image/button/external.html +1 -1
  21. package/src/api/exporters/html/__snapshots__/image/button/internal.html +1 -1
  22. package/src/api/exporters/html/__snapshots__/image/nested/external.html +1 -1
  23. package/src/api/exporters/html/__snapshots__/image/nested/internal.html +1 -1
  24. package/src/api/exporters/html/__snapshots__/image/noCaption/external.html +1 -0
  25. package/src/api/exporters/html/__snapshots__/image/noCaption/internal.html +1 -0
  26. package/src/api/exporters/html/__snapshots__/image/noName/external.html +1 -0
  27. package/src/api/exporters/html/__snapshots__/image/noName/internal.html +1 -0
  28. package/src/api/exporters/html/__snapshots__/image/noPreview/external.html +1 -0
  29. package/src/api/exporters/html/__snapshots__/image/noPreview/internal.html +1 -0
  30. package/src/api/exporters/html/__snapshots__/lists/basic/external.html +1 -0
  31. package/src/api/exporters/html/__snapshots__/lists/basic/internal.html +1 -0
  32. package/src/api/exporters/html/__snapshots__/lists/nested/external.html +1 -0
  33. package/src/api/exporters/html/__snapshots__/lists/nested/internal.html +1 -0
  34. package/src/api/exporters/html/__snapshots__/simpleFile/basic/external.html +1 -0
  35. package/src/api/exporters/html/__snapshots__/simpleFile/basic/internal.html +1 -0
  36. package/src/api/exporters/html/__snapshots__/simpleFile/button/external.html +1 -0
  37. package/src/api/exporters/html/__snapshots__/simpleFile/button/internal.html +1 -0
  38. package/src/api/exporters/html/__snapshots__/simpleFile/nested/external.html +1 -0
  39. package/src/api/exporters/html/__snapshots__/simpleFile/nested/internal.html +1 -0
  40. package/src/api/exporters/html/__snapshots__/simpleImage/basic/external.html +1 -1
  41. package/src/api/exporters/html/__snapshots__/simpleImage/basic/internal.html +1 -1
  42. package/src/api/exporters/html/__snapshots__/simpleImage/button/external.html +1 -1
  43. package/src/api/exporters/html/__snapshots__/simpleImage/button/internal.html +1 -1
  44. package/src/api/exporters/html/__snapshots__/simpleImage/nested/external.html +1 -1
  45. package/src/api/exporters/html/__snapshots__/simpleImage/nested/internal.html +1 -1
  46. package/src/api/exporters/html/__snapshots__/simpleImage/noCaption/external.html +1 -0
  47. package/src/api/exporters/html/__snapshots__/simpleImage/noCaption/internal.html +1 -0
  48. package/src/api/exporters/html/__snapshots__/simpleImage/noName/external.html +1 -0
  49. package/src/api/exporters/html/__snapshots__/simpleImage/noName/internal.html +1 -0
  50. package/src/api/exporters/html/__snapshots__/simpleImage/noPreview/external.html +1 -0
  51. package/src/api/exporters/html/__snapshots__/simpleImage/noPreview/internal.html +1 -0
  52. package/src/api/exporters/html/externalHTMLExporter.ts +4 -3
  53. package/src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts +1 -1
  54. package/src/api/exporters/markdown/__snapshots__/file/basic/markdown.md +3 -0
  55. package/src/api/exporters/markdown/__snapshots__/file/button/markdown.md +1 -0
  56. package/src/api/exporters/markdown/__snapshots__/file/nested/markdown.md +7 -0
  57. package/src/api/exporters/markdown/__snapshots__/file/noCaption/markdown.md +1 -0
  58. package/src/api/exporters/markdown/__snapshots__/file/noName/markdown.md +3 -0
  59. package/src/api/exporters/markdown/__snapshots__/image/basic/markdown.md +1 -1
  60. package/src/api/exporters/markdown/__snapshots__/image/button/markdown.md +1 -1
  61. package/src/api/exporters/markdown/__snapshots__/image/nested/markdown.md +2 -2
  62. package/src/api/exporters/markdown/__snapshots__/image/noCaption/markdown.md +1 -0
  63. package/src/api/exporters/markdown/__snapshots__/image/noName/markdown.md +3 -0
  64. package/src/api/exporters/markdown/__snapshots__/image/noPreview/markdown.md +3 -0
  65. package/src/api/exporters/markdown/__snapshots__/lists/basic/markdown.md +8 -0
  66. package/src/api/exporters/markdown/__snapshots__/lists/nested/markdown.md +10 -0
  67. package/src/api/exporters/markdown/__snapshots__/simpleFile/basic/markdown.md +3 -0
  68. package/src/api/exporters/markdown/__snapshots__/simpleFile/button/markdown.md +1 -0
  69. package/src/api/exporters/markdown/__snapshots__/simpleFile/nested/markdown.md +7 -0
  70. package/src/api/exporters/markdown/__snapshots__/simpleImage/basic/markdown.md +3 -1
  71. package/src/api/exporters/markdown/__snapshots__/simpleImage/button/markdown.md +1 -0
  72. package/src/api/exporters/markdown/__snapshots__/simpleImage/nested/markdown.md +6 -2
  73. package/src/api/exporters/markdown/__snapshots__/simpleImage/noCaption/markdown.md +1 -0
  74. package/src/api/exporters/markdown/__snapshots__/simpleImage/noName/markdown.md +3 -0
  75. package/src/api/exporters/markdown/__snapshots__/simpleImage/noPreview/markdown.md +3 -0
  76. package/src/api/exporters/markdown/markdownExporter.ts +2 -0
  77. package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +42 -0
  78. package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +262 -4
  79. package/src/api/parsers/html/__snapshots__/paste/list-test.json +74 -2
  80. package/src/api/parsers/html/__snapshots__/paste/parse-basic-block-types.json +3 -1
  81. package/src/api/parsers/html/__snapshots__/paste/parse-fake-image-caption.json +3 -1
  82. package/src/api/parsers/html/__snapshots__/paste/parse-mixed-nested-lists.json +135 -10
  83. package/src/api/parsers/html/__snapshots__/paste/parse-nested-lists-with-paragraphs.json +132 -7
  84. package/src/api/parsers/html/__snapshots__/paste/parse-nested-lists.json +111 -3
  85. package/src/api/parsers/html/parseHTML.test.ts +166 -95
  86. package/src/api/testUtil/cases/customBlocks.ts +82 -33
  87. package/src/api/testUtil/cases/customInlineContent.ts +1 -1
  88. package/src/api/testUtil/cases/customStyles.ts +1 -1
  89. package/src/api/testUtil/cases/defaultSchema.ts +185 -4
  90. package/src/blocks/AudioBlockContent/AudioBlockContent.ts +163 -0
  91. package/src/blocks/AudioBlockContent/audioBlockHelpers.ts +5 -0
  92. package/src/blocks/FileBlockContent/FileBlockContent.ts +120 -0
  93. package/src/blocks/FileBlockContent/fileBlockHelpers.ts +377 -0
  94. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +134 -354
  95. package/src/blocks/ImageBlockContent/imageBlockHelpers.ts +6 -0
  96. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +3 -0
  97. package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +266 -0
  98. package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +2 -1
  99. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +1 -0
  100. package/src/blocks/VideoBlockContent/VideoBlockContent.ts +181 -0
  101. package/src/blocks/VideoBlockContent/videoBlockHelpers.ts +6 -0
  102. package/src/blocks/defaultBlockTypeGuards.ts +53 -1
  103. package/src/blocks/defaultBlocks.ts +11 -2
  104. package/src/editor/Block.css +89 -27
  105. package/src/editor/BlockNoteEditor.ts +24 -10
  106. package/src/editor/BlockNoteSchema.ts +12 -3
  107. package/src/editor/transformPasted.ts +2 -1
  108. package/src/extensions/{ImagePanel/ImageToolbarPlugin.ts → FilePanel/FilePanelPlugin.ts} +22 -25
  109. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +14 -2
  110. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +72 -2
  111. package/src/extensions/TableHandles/TableHandlesPlugin.ts +27 -27
  112. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +7 -1
  113. package/src/i18n/locales/en.ts +117 -11
  114. package/src/i18n/locales/fr.ts +118 -11
  115. package/src/i18n/locales/index.ts +8 -2
  116. package/src/i18n/locales/is.ts +295 -0
  117. package/src/i18n/locales/ja.ts +323 -0
  118. package/src/i18n/locales/ko.ts +307 -0
  119. package/src/i18n/locales/nl.ts +108 -8
  120. package/src/i18n/locales/pl.ts +287 -0
  121. package/src/i18n/locales/pt.ts +295 -0
  122. package/src/i18n/locales/vi.ts +295 -0
  123. package/src/i18n/locales/zh.ts +123 -8
  124. package/src/index.ts +9 -2
  125. package/src/pm-nodes/BlockContainer.ts +18 -6
  126. package/src/schema/blocks/createSpec.ts +1 -0
  127. package/src/schema/blocks/internal.ts +10 -0
  128. package/src/schema/blocks/types.ts +40 -5
  129. package/src/util/string.ts +12 -0
  130. package/types/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.d.ts +7 -0
  131. package/types/src/api/testUtil/cases/customBlocks.d.ts +272 -54
  132. package/types/src/api/testUtil/cases/customInlineContent.d.ts +222 -16
  133. package/types/src/api/testUtil/cases/customStyles.d.ts +222 -16
  134. package/types/src/blocks/AudioBlockContent/AudioBlockContent.d.ts +101 -0
  135. package/types/src/blocks/AudioBlockContent/audioBlockHelpers.d.ts +3 -0
  136. package/types/src/blocks/FileBlockContent/FileBlockContent.d.ts +93 -0
  137. package/types/src/blocks/FileBlockContent/fileBlockHelpers.d.ts +30 -0
  138. package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +50 -14
  139. package/types/src/blocks/ImageBlockContent/imageBlockHelpers.d.ts +4 -0
  140. package/types/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.d.ts +55 -0
  141. package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +129 -0
  142. package/types/src/blocks/VideoBlockContent/videoBlockHelpers.d.ts +4 -0
  143. package/types/src/blocks/defaultBlockTypeGuards.d.ts +6 -1
  144. package/types/src/blocks/defaultBlocks.d.ts +444 -32
  145. package/types/src/editor/BlockNoteEditor.d.ts +12 -5
  146. package/types/src/extensions/{ImagePanel/ImageToolbarPlugin.d.ts → FilePanel/FilePanelPlugin.d.ts} +9 -12
  147. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +1 -1
  148. package/types/src/i18n/locales/en.d.ts +56 -7
  149. package/types/src/i18n/locales/fr.d.ts +2 -184
  150. package/types/src/i18n/locales/index.d.ts +7 -1
  151. package/types/src/i18n/locales/is.d.ts +2 -0
  152. package/types/src/i18n/locales/ja.d.ts +2 -0
  153. package/types/src/i18n/locales/ko.d.ts +2 -0
  154. package/types/src/i18n/locales/pl.d.ts +2 -0
  155. package/types/src/i18n/locales/pt.d.ts +2 -0
  156. package/types/src/i18n/locales/vi.d.ts +2 -0
  157. package/types/src/index.d.ts +8 -2
  158. package/types/src/pm-nodes/BlockContainer.d.ts +1 -1
  159. package/types/src/schema/blocks/internal.d.ts +1 -1
  160. package/types/src/schema/blocks/types.d.ts +25 -1
  161. package/types/src/util/string.d.ts +1 -0
  162. /package/src/blocks/{ImageBlockContent → FileBlockContent}/uploadToTmpFilesDotOrg_DEV_ONLY.ts +0 -0
  163. /package/types/src/blocks/{ImageBlockContent → FileBlockContent}/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +0 -0
@@ -1,10 +1,6 @@
1
1
  import { EditorTestCases } from "../index";
2
2
 
3
- import {
4
- imagePropSchema,
5
- renderImage,
6
- } from "../../../blocks/ImageBlockContent/ImageBlockContent";
7
- import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
3
+ import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
8
4
  import {
9
5
  DefaultInlineContentSchema,
10
6
  DefaultStyleSchema,
@@ -13,23 +9,29 @@ import {
13
9
  import { defaultProps } from "../../../blocks/defaultProps";
14
10
  import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
15
11
  import { BlockNoteSchema } from "../../../editor/BlockNoteSchema";
16
- import { createBlockSpec } from "../../../schema/blocks/createSpec";
12
+ import { createBlockSpec } from "../../../schema";
13
+ import {
14
+ imagePropSchema,
15
+ imageRender,
16
+ } from "../../../blocks/ImageBlockContent/ImageBlockContent";
17
17
 
18
18
  // This is a modified version of the default image block that does not implement
19
- // a `serialize` function. It's used to test if the custom serializer by default
20
- // serializes custom blocks using their `render` function.
19
+ // a `toExternalHTML` function. It's used to test if the custom serializer by
20
+ // default serializes custom blocks using their `render` function.
21
21
  const SimpleImage = createBlockSpec(
22
22
  {
23
- type: "simpleImage" as const,
23
+ type: "simpleImage",
24
24
  propSchema: imagePropSchema,
25
25
  content: "none",
26
26
  },
27
- { render: renderImage as any }
27
+ {
28
+ render: (block, editor) => imageRender(block as any, editor as any),
29
+ }
28
30
  );
29
31
 
30
32
  const CustomParagraph = createBlockSpec(
31
33
  {
32
- type: "customParagraph" as const,
34
+ type: "customParagraph",
33
35
  propSchema: defaultProps,
34
36
  content: "inline",
35
37
  },
@@ -57,7 +59,7 @@ const CustomParagraph = createBlockSpec(
57
59
 
58
60
  const SimpleCustomParagraph = createBlockSpec(
59
61
  {
60
- type: "simpleCustomParagraph" as const,
62
+ type: "simpleCustomParagraph",
61
63
  propSchema: defaultProps,
62
64
  content: "inline",
63
65
  },
@@ -96,6 +98,9 @@ export const customBlocksTestCases: EditorTestCases<
96
98
  });
97
99
  },
98
100
  documents: [
101
+ // Because images need to fetch the download URL async, their output HTML is
102
+ // initially rendered without a `src` attribute, which is reflected in the
103
+ // tests.
99
104
  {
100
105
  name: "simpleImage/button",
101
106
  blocks: [
@@ -108,12 +113,54 @@ export const customBlocksTestCases: EditorTestCases<
108
113
  name: "simpleImage/basic",
109
114
  blocks: [
110
115
  {
111
- type: "simpleImage" as const,
116
+ type: "simpleImage",
117
+ props: {
118
+ name: "example",
119
+ url: "exampleURL",
120
+ caption: "Caption",
121
+ previewWidth: 256,
122
+ },
123
+ },
124
+ ],
125
+ },
126
+ {
127
+ name: "simpleImage/noName",
128
+ blocks: [
129
+ {
130
+ type: "simpleImage",
131
+ props: {
132
+ url: "exampleURL",
133
+ caption: "Caption",
134
+ previewWidth: 256,
135
+ },
136
+ },
137
+ ],
138
+ },
139
+ {
140
+ name: "simpleImage/noCaption",
141
+ blocks: [
142
+ {
143
+ type: "simpleImage",
144
+ props: {
145
+ name: "example",
146
+ url: "exampleURL",
147
+ previewWidth: 256,
148
+ },
149
+ },
150
+ ],
151
+ },
152
+ {
153
+ name: "simpleImage/noPreview",
154
+ blocks: [
155
+ {
156
+ type: "simpleImage",
112
157
  props: {
158
+ name: "example",
113
159
  url: "exampleURL",
114
160
  caption: "Caption",
115
- width: 256,
116
- } as const,
161
+ showPreview: false,
162
+ previewWidth: 256,
163
+ },
117
164
  },
118
165
  ],
119
166
  },
@@ -121,20 +168,22 @@ export const customBlocksTestCases: EditorTestCases<
121
168
  name: "simpleImage/nested",
122
169
  blocks: [
123
170
  {
124
- type: "simpleImage" as const,
171
+ type: "simpleImage",
125
172
  props: {
173
+ name: "example",
126
174
  url: "exampleURL",
127
175
  caption: "Caption",
128
- width: 256,
129
- } as const,
176
+ previewWidth: 256,
177
+ },
130
178
  children: [
131
179
  {
132
- type: "simpleImage" as const,
180
+ type: "simpleImage",
133
181
  props: {
182
+ name: "example",
134
183
  url: "exampleURL",
135
184
  caption: "Caption",
136
- width: 256,
137
- } as const,
185
+ previewWidth: 256,
186
+ },
138
187
  },
139
188
  ],
140
189
  },
@@ -144,7 +193,7 @@ export const customBlocksTestCases: EditorTestCases<
144
193
  name: "customParagraph/basic",
145
194
  blocks: [
146
195
  {
147
- type: "customParagraph" as const,
196
+ type: "customParagraph",
148
197
  content: "Custom Paragraph",
149
198
  },
150
199
  ],
@@ -153,12 +202,12 @@ export const customBlocksTestCases: EditorTestCases<
153
202
  name: "customParagraph/styled",
154
203
  blocks: [
155
204
  {
156
- type: "customParagraph" as const,
205
+ type: "customParagraph",
157
206
  props: {
158
207
  textAlignment: "center",
159
208
  textColor: "orange",
160
209
  backgroundColor: "pink",
161
- } as const,
210
+ },
162
211
  content: [
163
212
  {
164
213
  type: "text",
@@ -195,15 +244,15 @@ export const customBlocksTestCases: EditorTestCases<
195
244
  name: "customParagraph/nested",
196
245
  blocks: [
197
246
  {
198
- type: "customParagraph" as const,
247
+ type: "customParagraph",
199
248
  content: "Custom Paragraph",
200
249
  children: [
201
250
  {
202
- type: "customParagraph" as const,
251
+ type: "customParagraph",
203
252
  content: "Nested Custom Paragraph 1",
204
253
  },
205
254
  {
206
- type: "customParagraph" as const,
255
+ type: "customParagraph",
207
256
  content: "Nested Custom Paragraph 2",
208
257
  },
209
258
  ],
@@ -214,7 +263,7 @@ export const customBlocksTestCases: EditorTestCases<
214
263
  name: "simpleCustomParagraph/basic",
215
264
  blocks: [
216
265
  {
217
- type: "simpleCustomParagraph" as const,
266
+ type: "simpleCustomParagraph",
218
267
  content: "Custom Paragraph",
219
268
  },
220
269
  ],
@@ -223,12 +272,12 @@ export const customBlocksTestCases: EditorTestCases<
223
272
  name: "simpleCustomParagraph/styled",
224
273
  blocks: [
225
274
  {
226
- type: "simpleCustomParagraph" as const,
275
+ type: "simpleCustomParagraph",
227
276
  props: {
228
277
  textAlignment: "center",
229
278
  textColor: "orange",
230
279
  backgroundColor: "pink",
231
- } as const,
280
+ },
232
281
  content: [
233
282
  {
234
283
  type: "text",
@@ -265,15 +314,15 @@ export const customBlocksTestCases: EditorTestCases<
265
314
  name: "simpleCustomParagraph/nested",
266
315
  blocks: [
267
316
  {
268
- type: "simpleCustomParagraph" as const,
317
+ type: "simpleCustomParagraph",
269
318
  content: "Custom Paragraph",
270
319
  children: [
271
320
  {
272
- type: "simpleCustomParagraph" as const,
321
+ type: "simpleCustomParagraph",
273
322
  content: "Nested Custom Paragraph 1",
274
323
  },
275
324
  {
276
- type: "simpleCustomParagraph" as const,
325
+ type: "simpleCustomParagraph",
277
326
  content: "Nested Custom Paragraph 2",
278
327
  },
279
328
  ],
@@ -1,6 +1,6 @@
1
1
  import { EditorTestCases } from "../index";
2
2
 
3
- import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
3
+ import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
4
4
  import {
5
5
  DefaultBlockSchema,
6
6
  DefaultStyleSchema,
@@ -1,6 +1,6 @@
1
1
  import { EditorTestCases } from "../index";
2
2
 
3
- import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
3
+ import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
4
4
  import {
5
5
  DefaultBlockSchema,
6
6
  DefaultInlineContentSchema,
@@ -6,7 +6,7 @@ import {
6
6
  DefaultInlineContentSchema,
7
7
  DefaultStyleSchema,
8
8
  } from "../../../blocks/defaultBlocks";
9
- import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
9
+ import { uploadToTmpFilesDotOrg_DEV_ONLY } from "../../../blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY";
10
10
 
11
11
  export const defaultSchemaTestCases: EditorTestCases<
12
12
  DefaultBlockSchema,
@@ -98,6 +98,145 @@ export const defaultSchemaTestCases: EditorTestCases<
98
98
  },
99
99
  ],
100
100
  },
101
+ {
102
+ name: "lists/basic",
103
+ blocks: [
104
+ {
105
+ type: "bulletListItem",
106
+ content: "Bullet List Item 1",
107
+ },
108
+ {
109
+ type: "bulletListItem",
110
+ content: "Bullet List Item 2",
111
+ },
112
+ {
113
+ type: "numberedListItem",
114
+ content: "Numbered List Item 1",
115
+ },
116
+ {
117
+ type: "numberedListItem",
118
+ content: "Numbered List Item 2",
119
+ },
120
+ {
121
+ type: "checkListItem",
122
+ content: "Check List Item 1",
123
+ },
124
+ {
125
+ type: "checkListItem",
126
+ props: {
127
+ checked: true,
128
+ },
129
+ content: "Check List Item 2",
130
+ },
131
+ ],
132
+ },
133
+ {
134
+ name: "lists/nested",
135
+ blocks: [
136
+ {
137
+ type: "bulletListItem",
138
+ content: "Bullet List Item 1",
139
+ },
140
+ {
141
+ type: "bulletListItem",
142
+ content: "Bullet List Item 2",
143
+ children: [
144
+ {
145
+ type: "numberedListItem",
146
+ content: "Numbered List Item 1",
147
+ },
148
+ {
149
+ type: "numberedListItem",
150
+ content: "Numbered List Item 2",
151
+ children: [
152
+ {
153
+ type: "checkListItem",
154
+ content: "Check List Item 1",
155
+ },
156
+ {
157
+ type: "checkListItem",
158
+ props: {
159
+ checked: true,
160
+ },
161
+ content: "Check List Item 2",
162
+ },
163
+ ],
164
+ },
165
+ ],
166
+ },
167
+ ],
168
+ },
169
+ {
170
+ name: "file/button",
171
+ blocks: [
172
+ {
173
+ type: "file",
174
+ },
175
+ ],
176
+ },
177
+ {
178
+ name: "file/basic",
179
+ blocks: [
180
+ {
181
+ type: "file",
182
+ props: {
183
+ name: "example",
184
+ url: "exampleURL",
185
+ caption: "Caption",
186
+ },
187
+ },
188
+ ],
189
+ },
190
+ {
191
+ name: "file/noName",
192
+ blocks: [
193
+ {
194
+ type: "file",
195
+ props: {
196
+ url: "exampleURL",
197
+ caption: "Caption",
198
+ },
199
+ },
200
+ ],
201
+ },
202
+ {
203
+ name: "file/noCaption",
204
+ blocks: [
205
+ {
206
+ type: "file",
207
+ props: {
208
+ name: "example",
209
+ url: "exampleURL",
210
+ },
211
+ },
212
+ ],
213
+ },
214
+ {
215
+ name: "file/nested",
216
+ blocks: [
217
+ {
218
+ type: "file",
219
+ props: {
220
+ name: "example",
221
+ url: "exampleURL",
222
+ caption: "Caption",
223
+ },
224
+ children: [
225
+ {
226
+ type: "file",
227
+ props: {
228
+ name: "example",
229
+ url: "exampleURL",
230
+ caption: "Caption",
231
+ },
232
+ },
233
+ ],
234
+ },
235
+ ],
236
+ },
237
+ // Because images need to fetch the download URL async, their internal HTML
238
+ // is initially rendered without a `src` attribute, which is reflected in
239
+ // the tests.
101
240
  {
102
241
  name: "image/button",
103
242
  blocks: [
@@ -112,9 +251,51 @@ export const defaultSchemaTestCases: EditorTestCases<
112
251
  {
113
252
  type: "image",
114
253
  props: {
254
+ name: "example",
255
+ url: "exampleURL",
256
+ caption: "Caption",
257
+ previewWidth: 256,
258
+ },
259
+ },
260
+ ],
261
+ },
262
+ {
263
+ name: "image/noName",
264
+ blocks: [
265
+ {
266
+ type: "image",
267
+ props: {
268
+ url: "exampleURL",
269
+ caption: "Caption",
270
+ previewWidth: 256,
271
+ },
272
+ },
273
+ ],
274
+ },
275
+ {
276
+ name: "image/noCaption",
277
+ blocks: [
278
+ {
279
+ type: "image",
280
+ props: {
281
+ name: "example",
282
+ url: "exampleURL",
283
+ previewWidth: 256,
284
+ },
285
+ },
286
+ ],
287
+ },
288
+ {
289
+ name: "image/noPreview",
290
+ blocks: [
291
+ {
292
+ type: "image",
293
+ props: {
294
+ name: "example",
115
295
  url: "exampleURL",
116
296
  caption: "Caption",
117
- width: 256,
297
+ showPreview: false,
298
+ previewWidth: 256,
118
299
  },
119
300
  },
120
301
  ],
@@ -127,7 +308,7 @@ export const defaultSchemaTestCases: EditorTestCases<
127
308
  props: {
128
309
  url: "exampleURL",
129
310
  caption: "Caption",
130
- width: 256,
311
+ previewWidth: 256,
131
312
  },
132
313
  children: [
133
314
  {
@@ -135,7 +316,7 @@ export const defaultSchemaTestCases: EditorTestCases<
135
316
  props: {
136
317
  url: "exampleURL",
137
318
  caption: "Caption",
138
- width: 256,
319
+ previewWidth: 256,
139
320
  },
140
321
  },
141
322
  ],
@@ -0,0 +1,163 @@
1
+ import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
2
+ import {
3
+ BlockFromConfig,
4
+ createBlockSpec,
5
+ FileBlockConfig,
6
+ Props,
7
+ PropSchema,
8
+ } from "../../schema";
9
+ import { defaultProps } from "../defaultProps";
10
+
11
+ import {
12
+ createAddFileButton,
13
+ createDefaultFilePreview,
14
+ createFigureWithCaption,
15
+ createFileAndCaptionWrapper,
16
+ createLinkWithCaption,
17
+ parseFigureElement,
18
+ } from "../FileBlockContent/fileBlockHelpers";
19
+ import { parseAudioElement } from "./audioBlockHelpers";
20
+
21
+ export const audioPropSchema = {
22
+ backgroundColor: defaultProps.backgroundColor,
23
+ // File name.
24
+ name: {
25
+ default: "" as const,
26
+ },
27
+ // File url.
28
+ url: {
29
+ default: "" as const,
30
+ },
31
+ // File caption.
32
+ caption: {
33
+ default: "" as const,
34
+ },
35
+
36
+ showPreview: {
37
+ default: true,
38
+ },
39
+ } satisfies PropSchema;
40
+
41
+ export const audioBlockConfig = {
42
+ type: "audio" as const,
43
+ propSchema: audioPropSchema,
44
+ content: "none",
45
+ isFileBlock: true,
46
+ fileBlockAcceptMimeTypes: ["audio/*"],
47
+ } satisfies FileBlockConfig;
48
+
49
+ export const audioRender = (
50
+ block: BlockFromConfig<typeof audioBlockConfig, any, any>,
51
+ editor: BlockNoteEditor<any, any, any>
52
+ ) => {
53
+ const wrapper = document.createElement("div");
54
+ wrapper.className = "bn-file-block-content-wrapper";
55
+
56
+ if (block.props.url === "") {
57
+ const fileBlockAudioIcon = document.createElement("div");
58
+ fileBlockAudioIcon.innerHTML =
59
+ '<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>';
60
+ const addAudioButton = createAddFileButton(
61
+ block,
62
+ editor,
63
+ editor.dictionary.file_blocks.audio.add_button_text,
64
+ fileBlockAudioIcon.firstElementChild as HTMLElement
65
+ );
66
+ wrapper.appendChild(addAudioButton.dom);
67
+
68
+ return {
69
+ dom: wrapper,
70
+ destroy: () => {
71
+ addAudioButton?.destroy?.();
72
+ },
73
+ };
74
+ } else if (!block.props.showPreview) {
75
+ const file = createDefaultFilePreview(block).dom;
76
+ const element = createFileAndCaptionWrapper(block, file);
77
+
78
+ return {
79
+ dom: element.dom,
80
+ };
81
+ } else {
82
+ const audio = document.createElement("audio");
83
+ audio.className = "bn-audio";
84
+ editor.resolveFileUrl(block.props.url).then((downloadUrl) => {
85
+ audio.src = downloadUrl;
86
+ });
87
+ audio.controls = true;
88
+ audio.contentEditable = "false";
89
+ audio.draggable = false;
90
+
91
+ const element = createFileAndCaptionWrapper(block, audio);
92
+ wrapper.appendChild(element.dom);
93
+
94
+ return {
95
+ dom: wrapper,
96
+ };
97
+ }
98
+ };
99
+
100
+ export const audioParse = (
101
+ element: HTMLElement
102
+ ): Partial<Props<typeof audioBlockConfig.propSchema>> | undefined => {
103
+ if (element.tagName === "AUDIO") {
104
+ return parseAudioElement(element as HTMLAudioElement);
105
+ }
106
+
107
+ if (element.tagName === "FIGURE") {
108
+ const parsedFigure = parseFigureElement(element, "audio");
109
+ if (!parsedFigure) {
110
+ return undefined;
111
+ }
112
+
113
+ const { targetElement, caption } = parsedFigure;
114
+
115
+ return {
116
+ ...parseAudioElement(targetElement as HTMLAudioElement),
117
+ caption,
118
+ };
119
+ }
120
+
121
+ return undefined;
122
+ };
123
+
124
+ export const audioToExternalHTML = (
125
+ block: BlockFromConfig<typeof audioBlockConfig, any, any>
126
+ ) => {
127
+ if (!block.props.url) {
128
+ const div = document.createElement("p");
129
+ div.textContent = "Add audio";
130
+
131
+ return {
132
+ dom: div,
133
+ };
134
+ }
135
+
136
+ let audio;
137
+ if (block.props.showPreview) {
138
+ audio = document.createElement("audio");
139
+ audio.src = block.props.url;
140
+ } else {
141
+ audio = document.createElement("a");
142
+ audio.href = block.props.url;
143
+ audio.textContent = block.props.name || block.props.url;
144
+ }
145
+
146
+ if (block.props.caption) {
147
+ if (block.props.showPreview) {
148
+ return createFigureWithCaption(audio, block.props.caption);
149
+ } else {
150
+ return createLinkWithCaption(audio, block.props.caption);
151
+ }
152
+ }
153
+
154
+ return {
155
+ dom: audio,
156
+ };
157
+ };
158
+
159
+ export const AudioBlock = createBlockSpec(audioBlockConfig, {
160
+ render: audioRender,
161
+ parse: audioParse,
162
+ toExternalHTML: audioToExternalHTML,
163
+ });
@@ -0,0 +1,5 @@
1
+ export const parseAudioElement = (audioElement: HTMLAudioElement) => {
2
+ const url = audioElement.src || undefined;
3
+
4
+ return { url };
5
+ };