@blocknote/core 0.13.3 → 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 (84) hide show
  1. package/dist/blocknote.js +1038 -696
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +6 -6
  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__/image/basic/internal.html +1 -1
  9. package/src/api/exporters/html/__snapshots__/image/nested/internal.html +1 -1
  10. package/src/api/exporters/html/__snapshots__/image/noCaption/internal.html +1 -1
  11. package/src/api/exporters/html/__snapshots__/image/noName/internal.html +1 -1
  12. package/src/api/exporters/html/__snapshots__/lists/basic/external.html +1 -0
  13. package/src/api/exporters/html/__snapshots__/lists/basic/internal.html +1 -0
  14. package/src/api/exporters/html/__snapshots__/lists/nested/external.html +1 -0
  15. package/src/api/exporters/html/__snapshots__/lists/nested/internal.html +1 -0
  16. package/src/api/exporters/html/__snapshots__/simpleImage/basic/external.html +1 -1
  17. package/src/api/exporters/html/__snapshots__/simpleImage/basic/internal.html +1 -1
  18. package/src/api/exporters/html/__snapshots__/simpleImage/nested/external.html +1 -1
  19. package/src/api/exporters/html/__snapshots__/simpleImage/nested/internal.html +1 -1
  20. package/src/api/exporters/html/__snapshots__/simpleImage/noCaption/external.html +1 -1
  21. package/src/api/exporters/html/__snapshots__/simpleImage/noCaption/internal.html +1 -1
  22. package/src/api/exporters/html/__snapshots__/simpleImage/noName/external.html +1 -1
  23. package/src/api/exporters/html/__snapshots__/simpleImage/noName/internal.html +1 -1
  24. package/src/api/exporters/html/externalHTMLExporter.ts +4 -3
  25. package/src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts +1 -1
  26. package/src/api/exporters/markdown/__snapshots__/lists/basic/markdown.md +8 -0
  27. package/src/api/exporters/markdown/__snapshots__/lists/nested/markdown.md +10 -0
  28. package/src/api/exporters/markdown/__snapshots__/simpleImage/basic/markdown.md +1 -1
  29. package/src/api/exporters/markdown/__snapshots__/simpleImage/nested/markdown.md +2 -2
  30. package/src/api/exporters/markdown/__snapshots__/simpleImage/noCaption/markdown.md +1 -1
  31. package/src/api/exporters/markdown/__snapshots__/simpleImage/noName/markdown.md +1 -1
  32. package/src/api/exporters/markdown/markdownExporter.ts +2 -0
  33. package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +42 -0
  34. package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +50 -0
  35. package/src/api/parsers/html/__snapshots__/paste/list-test.json +74 -2
  36. package/src/api/parsers/html/__snapshots__/paste/parse-mixed-nested-lists.json +135 -10
  37. package/src/api/parsers/html/__snapshots__/paste/parse-nested-lists-with-paragraphs.json +132 -7
  38. package/src/api/parsers/html/__snapshots__/paste/parse-nested-lists.json +111 -3
  39. package/src/api/parsers/html/parseHTML.test.ts +166 -95
  40. package/src/api/testUtil/cases/customBlocks.ts +3 -0
  41. package/src/api/testUtil/cases/defaultSchema.ts +71 -0
  42. package/src/blocks/AudioBlockContent/AudioBlockContent.ts +3 -2
  43. package/src/blocks/FileBlockContent/FileBlockContent.ts +1 -2
  44. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +3 -2
  45. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +3 -0
  46. package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +266 -0
  47. package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +2 -1
  48. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +1 -0
  49. package/src/blocks/VideoBlockContent/VideoBlockContent.ts +0 -1
  50. package/src/blocks/defaultBlockTypeGuards.ts +1 -1
  51. package/src/blocks/defaultBlocks.ts +6 -3
  52. package/src/editor/Block.css +22 -0
  53. package/src/editor/BlockNoteEditor.ts +10 -0
  54. package/src/editor/transformPasted.ts +2 -1
  55. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +13 -0
  56. package/src/extensions/TableHandles/TableHandlesPlugin.ts +27 -27
  57. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +7 -1
  58. package/src/i18n/locales/en.ts +15 -0
  59. package/src/i18n/locales/fr.ts +14 -0
  60. package/src/i18n/locales/is.ts +7 -0
  61. package/src/i18n/locales/ja.ts +24 -1
  62. package/src/i18n/locales/ko.ts +15 -0
  63. package/src/i18n/locales/nl.ts +7 -0
  64. package/src/i18n/locales/pl.ts +7 -0
  65. package/src/i18n/locales/pt.ts +14 -0
  66. package/src/i18n/locales/vi.ts +16 -2
  67. package/src/i18n/locales/zh.ts +16 -0
  68. package/src/pm-nodes/BlockContainer.ts +16 -4
  69. package/src/schema/blocks/types.ts +0 -1
  70. package/types/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.d.ts +7 -0
  71. package/types/src/api/testUtil/cases/customBlocks.d.ts +74 -42
  72. package/types/src/api/testUtil/cases/customInlineContent.d.ts +74 -42
  73. package/types/src/api/testUtil/cases/customStyles.d.ts +74 -42
  74. package/types/src/blocks/AudioBlockContent/AudioBlockContent.d.ts +0 -3
  75. package/types/src/blocks/FileBlockContent/FileBlockContent.d.ts +0 -3
  76. package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +0 -3
  77. package/types/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.d.ts +55 -0
  78. package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +0 -3
  79. package/types/src/blocks/defaultBlocks.d.ts +141 -77
  80. package/types/src/editor/BlockNoteEditor.d.ts +7 -0
  81. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +1 -1
  82. package/types/src/i18n/locales/en.d.ts +7 -0
  83. package/types/src/pm-nodes/BlockContainer.d.ts +1 -1
  84. package/types/src/schema/blocks/types.d.ts +0 -1
@@ -0,0 +1,266 @@
1
+ import { InputRule } from "@tiptap/core";
2
+ import {
3
+ PropSchema,
4
+ createBlockSpecFromStronglyTypedTiptapNode,
5
+ createStronglyTypedTiptapNode,
6
+ } from "../../../schema";
7
+ import { createDefaultBlockDOMOutputSpec } from "../../defaultBlockHelpers";
8
+ import { defaultProps } from "../../defaultProps";
9
+ import { handleEnter } from "../ListItemKeyboardShortcuts";
10
+ import { getCurrentBlockContentType } from "../../../api/getCurrentBlockContentType";
11
+
12
+ export const checkListItemPropSchema = {
13
+ ...defaultProps,
14
+ checked: {
15
+ default: false,
16
+ },
17
+ } satisfies PropSchema;
18
+
19
+ const checkListItemBlockContent = createStronglyTypedTiptapNode({
20
+ name: "checkListItem",
21
+ content: "inline*",
22
+ group: "blockContent",
23
+ addAttributes() {
24
+ return {
25
+ checked: {
26
+ default: false,
27
+ // instead of "checked" attributes, use "data-checked"
28
+ parseHTML: (element) =>
29
+ element.getAttribute("data-checked") === "true" || undefined,
30
+ renderHTML: (attributes) => {
31
+ return attributes.checked
32
+ ? {
33
+ "data-checked": (attributes.checked as boolean).toString(),
34
+ }
35
+ : {};
36
+ },
37
+ },
38
+ };
39
+ },
40
+
41
+ addInputRules() {
42
+ return [
43
+ // Creates a checklist when starting with "[]" or "[X]".
44
+ new InputRule({
45
+ find: new RegExp(`\\[\\s*\\]\\s$`),
46
+ handler: ({ state, chain, range }) => {
47
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
48
+ return;
49
+ }
50
+
51
+ chain()
52
+ .BNUpdateBlock(state.selection.from, {
53
+ type: "checkListItem",
54
+ props: {
55
+ checked: false as any,
56
+ },
57
+ })
58
+ // Removes the characters used to set the list.
59
+ .deleteRange({ from: range.from, to: range.to });
60
+ },
61
+ }),
62
+ new InputRule({
63
+ find: new RegExp(`\\[[Xx]\\]\\s$`),
64
+ handler: ({ state, chain, range }) => {
65
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
66
+ return;
67
+ }
68
+
69
+ chain()
70
+ .BNUpdateBlock(state.selection.from, {
71
+ type: "checkListItem",
72
+ props: {
73
+ checked: true as any,
74
+ },
75
+ })
76
+ // Removes the characters used to set the list.
77
+ .deleteRange({ from: range.from, to: range.to });
78
+ },
79
+ }),
80
+ ];
81
+ },
82
+
83
+ addKeyboardShortcuts() {
84
+ return {
85
+ Enter: () => handleEnter(this.editor),
86
+ "Mod-Shift-9": () => {
87
+ if (getCurrentBlockContentType(this.editor) !== "inline*") {
88
+ return true;
89
+ }
90
+
91
+ return this.editor.commands.BNUpdateBlock(
92
+ this.editor.state.selection.anchor,
93
+ {
94
+ type: "checkListItem",
95
+ props: {},
96
+ }
97
+ );
98
+ },
99
+ };
100
+ },
101
+
102
+ parseHTML() {
103
+ return [
104
+ {
105
+ tag: "div[data-content-type=" + this.name + "]", // TODO: remove if we can't come up with test case that needs this
106
+ },
107
+ // Checkbox only.
108
+ {
109
+ tag: "input",
110
+ getAttrs: (element) => {
111
+ if (typeof element === "string") {
112
+ return false;
113
+ }
114
+
115
+ if ((element as HTMLInputElement).type === "checkbox") {
116
+ return { checked: (element as HTMLInputElement).checked };
117
+ }
118
+
119
+ return false;
120
+ },
121
+ node: "checkListItem",
122
+ },
123
+ // Container element for checkbox + label.
124
+ {
125
+ tag: "li",
126
+ getAttrs: (element) => {
127
+ if (typeof element === "string") {
128
+ return false;
129
+ }
130
+
131
+ const parent = element.parentElement;
132
+
133
+ if (parent === null) {
134
+ return false;
135
+ }
136
+
137
+ if (
138
+ parent.tagName === "UL" ||
139
+ (parent.tagName === "DIV" && parent.parentElement!.tagName === "UL")
140
+ ) {
141
+ const checkbox =
142
+ (element.querySelector(
143
+ "input[type=checkbox]"
144
+ ) as HTMLInputElement) || null;
145
+
146
+ if (checkbox === null) {
147
+ return false;
148
+ }
149
+
150
+ return { checked: checkbox.checked };
151
+ }
152
+
153
+ return false;
154
+ },
155
+ node: "checkListItem",
156
+ },
157
+ ];
158
+ },
159
+
160
+ // Since there is no HTML checklist element, there isn't really any
161
+ // standardization for what checklists should look like in the DOM. GDocs'
162
+ // and Notion's aren't cross compatible, for example. This implementation
163
+ // has a semantically correct DOM structure (though missing a label for the
164
+ // checkbox) which is also converted correctly to Markdown by remark.
165
+ renderHTML({ node, HTMLAttributes }) {
166
+ const checkbox = document.createElement("input");
167
+ checkbox.type = "checkbox";
168
+ checkbox.checked = node.attrs.checked;
169
+ if (node.attrs.checked) {
170
+ checkbox.setAttribute("checked", "");
171
+ }
172
+
173
+ const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
174
+ this.name,
175
+ "p",
176
+ {
177
+ ...(this.options.domAttributes?.blockContent || {}),
178
+ ...HTMLAttributes,
179
+ },
180
+ this.options.domAttributes?.inlineContent || {}
181
+ );
182
+
183
+ dom.insertBefore(checkbox, contentDOM);
184
+
185
+ return { dom, contentDOM };
186
+ },
187
+
188
+ // Need to render node view since the checkbox needs to be able to update the
189
+ // node. This is only possible with a node view as it exposes `getPos`.
190
+ addNodeView() {
191
+ return ({ node, getPos, editor, HTMLAttributes }) => {
192
+ // Need to wrap certain elements in a div or keyboard navigation gets
193
+ // confused.
194
+ const wrapper = document.createElement("div");
195
+ const checkboxWrapper = document.createElement("div");
196
+ checkboxWrapper.contentEditable = "false";
197
+
198
+ const checkbox = document.createElement("input");
199
+ checkbox.type = "checkbox";
200
+ checkbox.checked = node.attrs.checked;
201
+ if (node.attrs.checked) {
202
+ checkbox.setAttribute("checked", "");
203
+ }
204
+
205
+ const changeHandler = () => {
206
+ if (!editor.isEditable) {
207
+ // This seems like the most effective way of blocking the checkbox
208
+ // from being toggled, as event.preventDefault() does not stop it for
209
+ // "click" or "change" events.
210
+ checkbox.checked = !checkbox.checked;
211
+ return;
212
+ }
213
+
214
+ if (typeof getPos !== "boolean") {
215
+ this.editor.commands.BNUpdateBlock(getPos(), {
216
+ type: "checkListItem",
217
+ props: {
218
+ checked: checkbox.checked as any,
219
+ },
220
+ });
221
+ }
222
+ };
223
+ checkbox.addEventListener("change", changeHandler);
224
+
225
+ const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
226
+ this.name,
227
+ "p",
228
+ {
229
+ ...(this.options.domAttributes?.blockContent || {}),
230
+ ...HTMLAttributes,
231
+ },
232
+ this.options.domAttributes?.inlineContent || {}
233
+ );
234
+
235
+ if (typeof getPos !== "boolean") {
236
+ // Since `node` is a blockContent node, we have to get the block ID from
237
+ // the parent blockContainer node. This means we can't add the label in
238
+ // `renderHTML` as we can't use `getPos` and therefore can't get the
239
+ // parent blockContainer node.
240
+ const blockID = this.editor.state.doc.resolve(getPos()).node().attrs.id;
241
+ const label = "label-" + blockID;
242
+ checkbox.setAttribute("aria-labelledby", label);
243
+ contentDOM.id = label;
244
+ }
245
+
246
+ dom.removeChild(contentDOM);
247
+ dom.appendChild(wrapper);
248
+ wrapper.appendChild(checkboxWrapper);
249
+ wrapper.appendChild(contentDOM);
250
+ checkboxWrapper.appendChild(checkbox);
251
+
252
+ return {
253
+ dom,
254
+ contentDOM,
255
+ destroy: () => {
256
+ checkbox.removeEventListener("change", changeHandler);
257
+ },
258
+ };
259
+ };
260
+ },
261
+ });
262
+
263
+ export const CheckListItem = createBlockSpecFromStronglyTypedTiptapNode(
264
+ checkListItemBlockContent,
265
+ checkListItemPropSchema
266
+ );
@@ -13,7 +13,8 @@ export const handleEnter = (editor: Editor) => {
13
13
  if (
14
14
  !(
15
15
  contentType.name === "bulletListItem" ||
16
- contentType.name === "numberedListItem"
16
+ contentType.name === "numberedListItem" ||
17
+ contentType.name === "checkListItem"
17
18
  ) ||
18
19
  !selectionEmpty
19
20
  ) {
@@ -18,6 +18,7 @@ const NumberedListItemBlockContent = createStronglyTypedTiptapNode({
18
18
  name: "numberedListItem",
19
19
  content: "inline*",
20
20
  group: "blockContent",
21
+ priority: 90,
21
22
  addAttributes() {
22
23
  return {
23
24
  index: {
@@ -49,7 +49,6 @@ export const videoBlockConfig = {
49
49
  propSchema: videoPropSchema,
50
50
  content: "none",
51
51
  isFileBlock: true,
52
- isFileBlockPlaceholder: (block: any) => !block.props.url,
53
52
  fileBlockAcceptMimeTypes: ["video/*"],
54
53
  } satisfies FileBlockConfig;
55
54
 
@@ -82,7 +82,7 @@ export function checkBlockIsFileBlockWithPlaceholder<
82
82
  S extends StyleSchema
83
83
  >(block: Block<B, I, S>, editor: BlockNoteEditor<B, I, S>) {
84
84
  const config = editor.schema.blockSchema[block.type];
85
- return config.isFileBlock && config.isFileBlockPlaceholder(block);
85
+ return config.isFileBlock && !block.props.url;
86
86
  }
87
87
 
88
88
  export function checkBlockTypeHasDefaultProp<
@@ -19,13 +19,15 @@ import {
19
19
  getInlineContentSchemaFromSpecs,
20
20
  getStyleSchemaFromSpecs,
21
21
  } from "../schema";
22
- import { FileBlock } from "./FileBlockContent/FileBlockContent";
23
- import { ImageBlock } from "./ImageBlockContent/ImageBlockContent";
22
+
24
23
  import { Heading } from "./HeadingBlockContent/HeadingBlockContent";
25
24
  import { BulletListItem } from "./ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent";
26
25
  import { NumberedListItem } from "./ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent";
26
+ import { CheckListItem } from "./ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent";
27
27
  import { Paragraph } from "./ParagraphBlockContent/ParagraphBlockContent";
28
28
  import { Table } from "./TableBlockContent/TableBlockContent";
29
+ import { FileBlock } from "./FileBlockContent/FileBlockContent";
30
+ import { ImageBlock } from "./ImageBlockContent/ImageBlockContent";
29
31
  import { VideoBlock } from "./VideoBlockContent/VideoBlockContent";
30
32
  import { AudioBlock } from "./AudioBlockContent/AudioBlockContent";
31
33
 
@@ -34,11 +36,12 @@ export const defaultBlockSpecs = {
34
36
  heading: Heading,
35
37
  bulletListItem: BulletListItem,
36
38
  numberedListItem: NumberedListItem,
39
+ checkListItem: CheckListItem,
40
+ table: Table,
37
41
  file: FileBlock,
38
42
  image: ImageBlock,
39
43
  video: VideoBlock,
40
44
  audio: AudioBlock,
41
- table: Table,
42
45
  } satisfies BlockSpecs;
43
46
 
44
47
  export const defaultBlockSchema = getBlockSchemaFromSpecs(defaultBlockSpecs);
@@ -185,6 +185,28 @@ NESTED BLOCKS
185
185
  gap: 1.2em;
186
186
  }
187
187
 
188
+ /* Checked */
189
+ .bn-block-content[data-content-type="checkListItem"] > div {
190
+ display: flex;
191
+ }
192
+
193
+ .bn-block-content[data-content-type="checkListItem"] > div > div > input {
194
+ margin: 0 1.2em 0 0;
195
+ cursor: pointer;
196
+ }
197
+
198
+ .bn-block-content[data-content-type="checkListItem"][data-checked="true"] .bn-inline-content {
199
+ text-decoration: line-through;
200
+ }
201
+
202
+ .bn-block-content[data-text-alignment="center"] {
203
+ justify-content: center;
204
+ }
205
+
206
+ .bn-block-content[data-text-alignment="right"] {
207
+ justify-content: flex-end;
208
+ }
209
+
188
210
  /* No list nesting */
189
211
  .bn-block-outer[data-prev-type="bulletListItem"]
190
212
  > .bn-block
@@ -117,6 +117,13 @@ export type BlockNoteEditorOptions<
117
117
  */
118
118
  uploadFile: (file: File) => Promise<string | Record<string, any>>;
119
119
 
120
+ /**
121
+ * Resolve a URL of a file block to one that can be displayed or downloaded. This can be used for creating authenticated URL or
122
+ * implementing custom protocols / schemes
123
+ * @returns The URL that's
124
+ */
125
+ resolveFileUrl: (url: string) => Promise<string>;
126
+
120
127
  /**
121
128
  * When enabled, allows for collaboration between multiple users.
122
129
  */
@@ -201,6 +208,8 @@ export class BlockNoteEditor<
201
208
  | ((file: File) => Promise<string | Record<string, any>>)
202
209
  | undefined;
203
210
 
211
+ public readonly resolveFileUrl: (url: string) => Promise<string>;
212
+
204
213
  public static create<
205
214
  BSchema extends BlockSchema = DefaultBlockSchema,
206
215
  ISchema extends InlineContentSchema = DefaultInlineContentSchema,
@@ -295,6 +304,7 @@ export class BlockNoteEditor<
295
304
  extensions.push(blockNoteUIExtension);
296
305
 
297
306
  this.uploadFile = newOptions.uploadFile;
307
+ this.resolveFileUrl = newOptions.resolveFileUrl || (async (url) => url);
298
308
 
299
309
  if (newOptions.collaboration && newOptions.initialContent) {
300
310
  console.warn(
@@ -40,7 +40,8 @@ export function transformPasted(slice: Slice, view: EditorView) {
40
40
 
41
41
  if (
42
42
  nestedChild.type.name === "bulletListItem" ||
43
- nestedChild.type.name === "numberedListItem"
43
+ nestedChild.type.name === "numberedListItem" ||
44
+ nestedChild.type.name === "checkListItem"
44
45
  ) {
45
46
  content.push(f.child(i + 1));
46
47
  f = removeChild(f, i + 1);
@@ -144,6 +144,19 @@ export function getDefaultSlashMenuItems<
144
144
  });
145
145
  }
146
146
 
147
+ if (checkDefaultBlockTypeInSchema("checkListItem", editor)) {
148
+ items.push({
149
+ onItemClick: () => {
150
+ insertOrUpdateBlock(editor, {
151
+ type: "checkListItem",
152
+ });
153
+ },
154
+ badge: formatKeyboardShortcut("Mod-Shift-9"),
155
+ key: "check_list",
156
+ ...editor.dictionary.slash_menu.check_list,
157
+ });
158
+ }
159
+
147
160
  if (checkDefaultBlockTypeInSchema("paragraph", editor)) {
148
161
  items.push({
149
162
  onItemClick: () => {
@@ -7,9 +7,9 @@ import {
7
7
  BlockFromConfigNoChildren,
8
8
  BlockSchemaWithBlock,
9
9
  InlineContentSchema,
10
- SpecificBlock,
11
10
  StyleSchema,
12
11
  } from "../../schema";
12
+ import { checkBlockIsDefaultType } from "../../blocks/defaultBlockTypeGuards";
13
13
  import { EventEmitter } from "../../util/EventEmitter";
14
14
  import { getDraggableBlockFromCoords } from "../SideMenu/SideMenuPlugin";
15
15
 
@@ -83,7 +83,6 @@ function hideElementsWithClassNames(classNames: string[]) {
83
83
  }
84
84
 
85
85
  export class TableHandlesView<
86
- BSchema extends BlockSchemaWithBlock<"table", DefaultBlockSchema["table"]>,
87
86
  I extends InlineContentSchema,
88
87
  S extends StyleSchema
89
88
  > implements PluginView
@@ -146,28 +145,15 @@ export class TableHandlesView<
146
145
 
147
146
  const blockEl = getDraggableBlockFromCoords(cellRect, this.pmView);
148
147
  if (!blockEl) {
149
- throw new Error(
150
- "Found table cell element, but could not find surrounding blockContent element."
151
- );
152
- }
153
- this.tableId = blockEl.id;
154
-
155
- if (
156
- this.state !== undefined &&
157
- this.state.show &&
158
- this.tableId === blockEl.id &&
159
- this.state.rowIndex === rowIndex &&
160
- this.state.colIndex === colIndex
161
- ) {
162
148
  return;
163
149
  }
164
150
 
165
- let block: Block<any, any, any> | undefined = undefined;
151
+ let tableBlock: Block<any, any, any> | undefined = undefined;
166
152
 
167
153
  // Copied from `getBlock`. We don't use `getBlock` since we also need the PM
168
154
  // node for the table, so we would effectively be doing the same work twice.
169
155
  this.editor._tiptapEditor.state.doc.descendants((node, pos) => {
170
- if (typeof block !== "undefined") {
156
+ if (typeof tableBlock !== "undefined") {
171
157
  return false;
172
158
  }
173
159
 
@@ -175,24 +161,44 @@ export class TableHandlesView<
175
161
  return true;
176
162
  }
177
163
 
178
- block = nodeToBlock(
164
+ const block = nodeToBlock(
179
165
  node,
180
166
  this.editor.schema.blockSchema,
181
167
  this.editor.schema.inlineContentSchema,
182
168
  this.editor.schema.styleSchema,
183
169
  this.editor.blockCache
184
170
  );
185
- this.tablePos = pos + 1;
171
+
172
+ if (checkBlockIsDefaultType("table", block, this.editor)) {
173
+ this.tablePos = pos + 1;
174
+ tableBlock = block;
175
+ }
186
176
 
187
177
  return false;
188
178
  });
189
179
 
180
+ if (!tableBlock) {
181
+ return;
182
+ }
183
+
184
+ this.tableId = blockEl.id;
185
+
186
+ if (
187
+ this.state !== undefined &&
188
+ this.state.show &&
189
+ this.tableId === blockEl.id &&
190
+ this.state.rowIndex === rowIndex &&
191
+ this.state.colIndex === colIndex
192
+ ) {
193
+ return;
194
+ }
195
+
190
196
  this.state = {
191
197
  show: true,
192
198
  referencePosCell: cellRect,
193
199
  referencePosTable: tableRect,
194
200
 
195
- block: block! as SpecificBlock<BSchema, "table", I, S>,
201
+ block: tableBlock,
196
202
  colIndex: colIndex,
197
203
  rowIndex: rowIndex,
198
204
 
@@ -365,13 +371,7 @@ export class TableHandlesProsemirrorPlugin<
365
371
  I extends InlineContentSchema,
366
372
  S extends StyleSchema
367
373
  > extends EventEmitter<any> {
368
- private view:
369
- | TableHandlesView<
370
- BlockSchemaWithBlock<"table", DefaultBlockSchema["table"]>,
371
- I,
372
- S
373
- >
374
- | undefined;
374
+ private view: TableHandlesView<I, S> | undefined;
375
375
  public readonly plugin: Plugin;
376
376
 
377
377
  constructor(
@@ -8,7 +8,13 @@ export const TextAlignmentExtension = Extension.create({
8
8
  {
9
9
  // Attribute is applied to block content instead of container so that child blocks don't inherit the text
10
10
  // alignment styling.
11
- types: ["paragraph", "heading", "bulletListItem", "numberedListItem"],
11
+ types: [
12
+ "paragraph",
13
+ "heading",
14
+ "bulletListItem",
15
+ "numberedListItem",
16
+ "checkListItem",
17
+ ],
12
18
  attributes: {
13
19
  textAlignment: {
14
20
  default: "left",
@@ -30,6 +30,20 @@ export const en = {
30
30
  aliases: ["ul", "li", "list", "bulletlist", "bullet list"],
31
31
  group: "Basic blocks",
32
32
  },
33
+ check_list: {
34
+ title: "Check List",
35
+ subtext: "Used to display a list with checkboxes",
36
+ aliases: [
37
+ "ul",
38
+ "li",
39
+ "list",
40
+ "checklist",
41
+ "check list",
42
+ "checked list",
43
+ "checkbox",
44
+ ],
45
+ group: "Basic blocks",
46
+ },
33
47
  paragraph: {
34
48
  title: "Paragraph",
35
49
  subtext: "Used for the body of your document",
@@ -96,6 +110,7 @@ export const en = {
96
110
  heading: "Heading",
97
111
  bulletListItem: "List",
98
112
  numberedListItem: "List",
113
+ checkListItem: "List",
99
114
  },
100
115
  file_blocks: {
101
116
  image: {
@@ -32,6 +32,19 @@ export const fr: Dictionary = {
32
32
  aliases: ["ul", "li", "liste", "listeàpuces", "liste à puces"],
33
33
  group: "Blocs de base",
34
34
  },
35
+ check_list: {
36
+ title: "Liste de vérification",
37
+ subtext: "Utilisé pour afficher une liste avec des cases à cocher",
38
+ aliases: [
39
+ "ul",
40
+ "li",
41
+ "liste",
42
+ "liste de vérification",
43
+ "liste cochée",
44
+ "case à cocher",
45
+ ],
46
+ group: "Blocs de base",
47
+ },
35
48
  paragraph: {
36
49
  title: "Paragraphe",
37
50
  subtext: "Utilisé pour le corps de votre document",
@@ -98,6 +111,7 @@ export const fr: Dictionary = {
98
111
  heading: "Titre",
99
112
  bulletListItem: "Liste",
100
113
  numberedListItem: "Liste",
114
+ checkListItem: "Liste",
101
115
  },
102
116
  file_blocks: {
103
117
  image: {
@@ -32,6 +32,12 @@ export const is: Dictionary = {
32
32
  aliases: ["ul", "li", "listi", "punktalisti"],
33
33
  group: "Grunnblokkar",
34
34
  },
35
+ check_list: {
36
+ title: "Athugunarlisti",
37
+ subtext: "Notað til að sýna lista með gátreitum",
38
+ aliases: ["ul", "li", "listi", "athugunarlisti", "merktur listi"],
39
+ group: "Grunnblokkar",
40
+ },
35
41
  paragraph: {
36
42
  title: "Málsgrein",
37
43
  subtext: "Notað fyrir meginmál skjalsins",
@@ -98,6 +104,7 @@ export const is: Dictionary = {
98
104
  heading: "Fyrirsögn",
99
105
  bulletListItem: "Listi",
100
106
  numberedListItem: "Listi",
107
+ checkListItem: "Listi",
101
108
  },
102
109
  file_blocks: {
103
110
  image: {
@@ -37,7 +37,29 @@ export const ja: Dictionary = {
37
37
  bullet_list: {
38
38
  title: "箇条書き",
39
39
  subtext: "箇条書きを表示するために使用",
40
- aliases: ["ul", "li", "リスト", "箇条書きリスト"],
40
+ aliases: [
41
+ "ul",
42
+ "li",
43
+ "bulletlist",
44
+ "bullet list",
45
+ "リスト",
46
+ "箇条書きリスト",
47
+ ],
48
+ group: "基本ブロック",
49
+ },
50
+ check_list: {
51
+ title: "チェックリスト",
52
+ subtext: "チェックボックス付きリストを表示するために使用されます",
53
+ aliases: [
54
+ "ul",
55
+ "li",
56
+ "list",
57
+ "checklist",
58
+ "checked list",
59
+ "リスト",
60
+ "チェックリスト",
61
+ "チェックされたリスト",
62
+ ],
41
63
  group: "基本ブロック",
42
64
  },
43
65
  paragraph: {
@@ -109,6 +131,7 @@ export const ja: Dictionary = {
109
131
  heading: "見出し",
110
132
  bulletListItem: "リストを追加",
111
133
  numberedListItem: "リストを追加",
134
+ checkListItem: "リストを追加",
112
135
  },
113
136
  file_blocks: {
114
137
  image: {