@blocknote/core 0.38.0 → 0.39.1

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 (228) hide show
  1. package/dist/BlockNoteSchema-DmZ6UQfY.cjs +11 -0
  2. package/dist/BlockNoteSchema-DmZ6UQfY.cjs.map +1 -0
  3. package/dist/BlockNoteSchema-oR047ACf.js +4275 -0
  4. package/dist/BlockNoteSchema-oR047ACf.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/tsconfig.tsbuildinfo +1 -1
  15. package/dist/webpack-stats.json +1 -1
  16. package/package.json +19 -16
  17. package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +1 -1
  18. package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +2 -2
  19. package/src/api/blockManipulation/commands/splitBlock/splitBlock.ts +34 -25
  20. package/src/api/blockManipulation/setupTestEnv.ts +0 -1
  21. package/src/api/clipboard/fromClipboard/handleFileInsertion.ts +6 -10
  22. package/src/api/clipboard/fromClipboard/pasteExtension.ts +1 -1
  23. package/src/api/clipboard/toClipboard/copyExtension.ts +1 -1
  24. package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +128 -28
  25. package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +101 -41
  26. package/src/api/pmUtil.ts +1 -1
  27. package/src/api/positionMapping.test.ts +58 -15
  28. package/src/api/positionMapping.ts +2 -4
  29. package/src/blocks/Audio/block.ts +174 -0
  30. package/src/blocks/BlockNoteSchema.ts +59 -0
  31. package/src/blocks/Code/block.ts +303 -0
  32. package/src/blocks/Code/shiki.ts +73 -0
  33. package/src/blocks/File/block.ts +98 -0
  34. package/src/blocks/{FileBlockContent → File}/helpers/render/createAddFileButton.ts +5 -2
  35. package/src/blocks/{FileBlockContent → File}/helpers/render/createFileBlockWrapper.ts +15 -6
  36. package/src/blocks/{FileBlockContent → File}/helpers/render/createFileNameWithIcon.ts +15 -2
  37. package/src/blocks/{FileBlockContent → File}/helpers/render/createResizableFileBlockWrapper.ts +21 -2
  38. package/src/blocks/Heading/block.ts +138 -0
  39. package/src/blocks/Image/block.ts +190 -0
  40. package/src/blocks/ListItem/BulletListItem/block.ts +116 -0
  41. package/src/blocks/ListItem/CheckListItem/block.ts +175 -0
  42. package/src/blocks/ListItem/NumberedListItem/IndexingPlugin.ts +173 -0
  43. package/src/blocks/ListItem/NumberedListItem/block.ts +133 -0
  44. package/src/blocks/ListItem/ToggleListItem/block.ts +78 -0
  45. package/src/blocks/PageBreak/block.ts +72 -0
  46. package/src/blocks/{PageBreakBlockContent → PageBreak}/getPageBreakSlashMenuItems.ts +9 -7
  47. package/src/blocks/Paragraph/block.ts +80 -0
  48. package/src/blocks/Quote/block.ts +90 -0
  49. package/src/blocks/{TableBlockContent/TableBlockContent.ts → Table/block.ts} +169 -51
  50. package/src/blocks/ToggleWrapper/createToggleWrapper.ts +1 -1
  51. package/src/blocks/Video/block.ts +143 -0
  52. package/src/blocks/defaultBlockHelpers.ts +2 -2
  53. package/src/blocks/defaultBlockTypeGuards.ts +143 -174
  54. package/src/blocks/defaultBlocks.ts +107 -35
  55. package/src/blocks/defaultProps.ts +145 -4
  56. package/src/blocks/index.ts +26 -0
  57. package/src/blocks/utils/listItemEnterHandler.ts +42 -0
  58. package/src/editor/Block.css +54 -18
  59. package/src/editor/BlockNoteEditor.ts +256 -211
  60. package/src/editor/BlockNoteExtension.ts +92 -0
  61. package/src/editor/BlockNoteExtensions.ts +18 -17
  62. package/src/editor/defaultColors.ts +2 -2
  63. package/src/exporter/Exporter.ts +1 -1
  64. package/src/exporter/mapping.ts +1 -1
  65. package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +3 -20
  66. package/src/extensions/BackgroundColor/BackgroundColorMark.ts +6 -8
  67. package/src/extensions/BlockChange/BlockChangePlugin.ts +2 -1
  68. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor-forked.json +2 -2
  69. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor.json +2 -2
  70. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-forked.html +1 -1
  71. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap.html +1 -1
  72. package/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.ts +52 -0
  73. package/src/extensions/Collaboration/schemaMigration/migrationRules/index.ts +4 -0
  74. package/src/extensions/Collaboration/schemaMigration/migrationRules/migrationRule.ts +4 -0
  75. package/src/extensions/Collaboration/schemaMigration/migrationRules/moveColorAttributes.ts +78 -0
  76. package/src/extensions/Comments/CommentsPlugin.ts +1 -1
  77. package/src/extensions/FilePanel/FilePanelPlugin.ts +5 -10
  78. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +1 -1
  79. package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +4 -3
  80. package/src/extensions/Placeholder/PlaceholderPlugin.ts +6 -6
  81. package/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts +1 -23
  82. package/src/extensions/SideMenu/SideMenuPlugin.ts +1 -3
  83. package/src/extensions/SideMenu/dragging.ts +2 -2
  84. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +4 -7
  85. package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +6 -2
  86. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +24 -17
  87. package/src/extensions/TableHandles/TableHandlesPlugin.ts +8 -8
  88. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +5 -11
  89. package/src/extensions/TextColor/TextColorExtension.ts +3 -17
  90. package/src/extensions/TextColor/TextColorMark.ts +4 -9
  91. package/src/extensions/UniqueID/UniqueID.ts +6 -13
  92. package/src/index.ts +2 -28
  93. package/src/schema/blocks/createSpec.ts +342 -169
  94. package/src/schema/blocks/internal.ts +77 -138
  95. package/src/schema/blocks/types.ts +264 -94
  96. package/src/schema/index.ts +1 -0
  97. package/src/schema/inlineContent/createSpec.ts +99 -21
  98. package/src/schema/inlineContent/internal.ts +16 -7
  99. package/src/schema/inlineContent/types.ts +24 -2
  100. package/src/schema/propTypes.ts +15 -9
  101. package/src/schema/schema.ts +209 -0
  102. package/src/schema/styles/createSpec.ts +79 -31
  103. package/src/schema/styles/internal.ts +61 -2
  104. package/src/schema/styles/types.ts +17 -3
  105. package/src/util/topo-sort.test.ts +125 -0
  106. package/src/util/topo-sort.ts +160 -0
  107. package/types/src/api/blockManipulation/commands/splitBlock/splitBlock.d.ts +2 -1
  108. package/types/src/api/blockManipulation/selections/selection.d.ts +1 -1
  109. package/types/src/api/blockManipulation/setupTestEnv.d.ts +29 -543
  110. package/types/src/api/exporters/html/util/serializeBlocksExternalHTML.d.ts +1 -1
  111. package/types/src/api/exporters/html/util/serializeBlocksInternalHTML.d.ts +1 -1
  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/File/block.d.ts +37 -0
  118. package/types/src/blocks/File/helpers/render/createAddFileButton.d.ts +6 -0
  119. package/types/src/blocks/File/helpers/render/createFileBlockWrapper.d.ts +25 -0
  120. package/types/src/blocks/{FileBlockContent → File}/helpers/render/createFileNameWithIcon.d.ts +6 -2
  121. package/types/src/blocks/File/helpers/render/createResizableFileBlockWrapper.d.ts +31 -0
  122. package/types/src/blocks/Heading/block.d.ts +71 -0
  123. package/types/src/blocks/Image/block.d.ts +102 -0
  124. package/types/src/blocks/ListItem/BulletListItem/block.d.ts +25 -0
  125. package/types/src/blocks/ListItem/CheckListItem/block.d.ts +33 -0
  126. package/types/src/blocks/ListItem/NumberedListItem/IndexingPlugin.d.ts +8 -0
  127. package/types/src/blocks/ListItem/NumberedListItem/block.d.ts +33 -0
  128. package/types/src/blocks/ListItem/ToggleListItem/block.d.ts +25 -0
  129. package/types/src/blocks/PageBreak/block.d.ts +11 -0
  130. package/types/src/blocks/{PageBreakBlockContent → PageBreak}/getPageBreakSlashMenuItems.d.ts +4 -2
  131. package/types/src/blocks/Paragraph/block.d.ts +25 -0
  132. package/types/src/blocks/Quote/block.d.ts +17 -0
  133. package/types/src/blocks/Table/block.d.ts +21 -0
  134. package/types/src/blocks/Video/block.d.ts +67 -0
  135. package/types/src/blocks/defaultBlockHelpers.d.ts +1 -1
  136. package/types/src/blocks/defaultBlockTypeGuards.d.ts +15 -36
  137. package/types/src/blocks/defaultBlocks.d.ts +221 -1060
  138. package/types/src/blocks/defaultProps.d.ts +17 -1
  139. package/types/src/blocks/index.d.ts +24 -0
  140. package/types/src/blocks/utils/listItemEnterHandler.d.ts +2 -0
  141. package/types/src/editor/BlockNoteEditor.d.ts +36 -67
  142. package/types/src/editor/BlockNoteExtension.d.ts +67 -0
  143. package/types/src/editor/BlockNoteExtensions.d.ts +1 -1
  144. package/types/src/editor/defaultColors.d.ts +8 -76
  145. package/types/src/exporter/Exporter.d.ts +1 -1
  146. package/types/src/exporter/mapping.d.ts +1 -1
  147. package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +4 -1
  148. package/types/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.d.ts +7 -0
  149. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/index.d.ts +3 -0
  150. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/migrationRule.d.ts +3 -0
  151. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/moveColorAttributes.d.ts +2 -0
  152. package/types/src/extensions/Comments/CommentsPlugin.d.ts +1 -1
  153. package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +4 -4
  154. package/types/src/extensions/TextColor/TextColorMark.d.ts +4 -1
  155. package/types/src/index.d.ts +2 -25
  156. package/types/src/schema/blocks/createSpec.d.ts +16 -36
  157. package/types/src/schema/blocks/internal.d.ts +11 -33
  158. package/types/src/schema/blocks/types.d.ts +181 -57
  159. package/types/src/schema/index.d.ts +1 -0
  160. package/types/src/schema/inlineContent/createSpec.d.ts +36 -2
  161. package/types/src/schema/inlineContent/internal.d.ts +7 -15
  162. package/types/src/schema/inlineContent/types.d.ts +15 -1
  163. package/types/src/schema/propTypes.d.ts +4 -4
  164. package/types/src/schema/schema.d.ts +40 -0
  165. package/types/src/schema/styles/createSpec.d.ts +6 -4
  166. package/types/src/schema/styles/internal.d.ts +6 -3
  167. package/types/src/schema/styles/types.d.ts +11 -2
  168. package/types/src/util/topo-sort.d.ts +18 -0
  169. package/types/src/util/topo-sort.test.d.ts +1 -0
  170. package/src/blocks/AudioBlockContent/AudioBlockContent.ts +0 -144
  171. package/src/blocks/CodeBlockContent/CodeBlockContent.ts +0 -445
  172. package/src/blocks/FileBlockContent/FileBlockContent.ts +0 -100
  173. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +0 -159
  174. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +0 -159
  175. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +0 -134
  176. package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +0 -299
  177. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +0 -86
  178. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +0 -172
  179. package/src/blocks/ListItemBlockContent/ToggleListItemBlockContent/ToggleListItemBlockContent.ts +0 -104
  180. package/src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts +0 -49
  181. package/src/blocks/PageBreakBlockContent/schema.ts +0 -40
  182. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +0 -78
  183. package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +0 -121
  184. package/src/blocks/VideoBlockContent/VideoBlockContent.ts +0 -158
  185. package/src/editor/BlockNoteSchema.ts +0 -107
  186. package/src/editor/BlockNoteTipTapEditor.ts +0 -335
  187. package/types/src/blocks/AudioBlockContent/AudioBlockContent.d.ts +0 -99
  188. package/types/src/blocks/FileBlockContent/FileBlockContent.d.ts +0 -90
  189. package/types/src/blocks/FileBlockContent/helpers/render/createAddFileButton.d.ts +0 -6
  190. package/types/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.d.ts +0 -9
  191. package/types/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.d.ts +0 -9
  192. package/types/src/blocks/HeadingBlockContent/HeadingBlockContent.d.ts +0 -67
  193. package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +0 -131
  194. package/types/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +0 -46
  195. package/types/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.d.ts +0 -55
  196. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.d.ts +0 -2
  197. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +0 -58
  198. package/types/src/blocks/ListItemBlockContent/ToggleListItemBlockContent/ToggleListItemBlockContent.d.ts +0 -46
  199. package/types/src/blocks/PageBreakBlockContent/PageBreakBlockContent.d.ts +0 -31
  200. package/types/src/blocks/PageBreakBlockContent/schema.d.ts +0 -86
  201. package/types/src/blocks/ParagraphBlockContent/ParagraphBlockContent.d.ts +0 -52
  202. package/types/src/blocks/QuoteBlockContent/QuoteBlockContent.d.ts +0 -52
  203. package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +0 -39
  204. package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +0 -131
  205. package/types/src/editor/BlockNoteSchema.d.ts +0 -34
  206. package/types/src/editor/BlockNoteTipTapEditor.d.ts +0 -43
  207. /package/src/blocks/{AudioBlockContent → Audio}/parseAudioElement.ts +0 -0
  208. /package/src/blocks/{FileBlockContent → File}/helpers/parse/parseEmbedElement.ts +0 -0
  209. /package/src/blocks/{FileBlockContent → File}/helpers/parse/parseFigureElement.ts +0 -0
  210. /package/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createFigureWithCaption.ts +0 -0
  211. /package/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createLinkWithCaption.ts +0 -0
  212. /package/src/blocks/{FileBlockContent → File/helpers}/uploadToTmpFilesDotOrg_DEV_ONLY.ts +0 -0
  213. /package/src/blocks/{ImageBlockContent → Image}/parseImageElement.ts +0 -0
  214. /package/src/blocks/{ListItemBlockContent → ListItem}/ListItemKeyboardShortcuts.ts +0 -0
  215. /package/src/blocks/{ListItemBlockContent → ListItem}/getListItemContent.ts +0 -0
  216. /package/src/blocks/{TableBlockContent → Table}/TableExtension.ts +0 -0
  217. /package/src/blocks/{VideoBlockContent → Video}/parseVideoElement.ts +0 -0
  218. /package/types/src/blocks/{AudioBlockContent → Audio}/parseAudioElement.d.ts +0 -0
  219. /package/types/src/blocks/{FileBlockContent → File}/helpers/parse/parseEmbedElement.d.ts +0 -0
  220. /package/types/src/blocks/{FileBlockContent → File}/helpers/parse/parseFigureElement.d.ts +0 -0
  221. /package/types/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createFigureWithCaption.d.ts +0 -0
  222. /package/types/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createLinkWithCaption.d.ts +0 -0
  223. /package/types/src/blocks/{FileBlockContent → File/helpers}/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +0 -0
  224. /package/types/src/blocks/{ImageBlockContent → Image}/parseImageElement.d.ts +0 -0
  225. /package/types/src/blocks/{ListItemBlockContent → ListItem}/ListItemKeyboardShortcuts.d.ts +0 -0
  226. /package/types/src/blocks/{ListItemBlockContent → ListItem}/getListItemContent.d.ts +0 -0
  227. /package/types/src/blocks/{TableBlockContent → Table}/TableExtension.d.ts +0 -0
  228. /package/types/src/blocks/{VideoBlockContent → Video}/parseVideoElement.d.ts +0 -0
@@ -1,299 +0,0 @@
1
- import { InputRule } from "@tiptap/core";
2
- import { updateBlockCommand } from "../../../api/blockManipulation/commands/updateBlock/updateBlock.js";
3
- import {
4
- getBlockInfoFromSelection,
5
- getNearestBlockPos,
6
- } from "../../../api/getBlockInfoFromPos.js";
7
- import {
8
- PropSchema,
9
- createBlockSpecFromStronglyTypedTiptapNode,
10
- createStronglyTypedTiptapNode,
11
- propsToAttributes,
12
- } from "../../../schema/index.js";
13
- import { createDefaultBlockDOMOutputSpec } from "../../defaultBlockHelpers.js";
14
- import { defaultProps } from "../../defaultProps.js";
15
- import { getListItemContent } from "../getListItemContent.js";
16
- import { handleEnter } from "../ListItemKeyboardShortcuts.js";
17
-
18
- export const checkListItemPropSchema = {
19
- ...defaultProps,
20
- checked: {
21
- default: false,
22
- },
23
- } satisfies PropSchema;
24
-
25
- const checkListItemBlockContent = createStronglyTypedTiptapNode({
26
- name: "checkListItem",
27
- content: "inline*",
28
- group: "blockContent",
29
-
30
- addAttributes() {
31
- return propsToAttributes(checkListItemPropSchema);
32
- },
33
-
34
- addInputRules() {
35
- return [
36
- // Creates a checklist when starting with "[]" or "[X]".
37
- new InputRule({
38
- find: new RegExp(`\\[\\s*\\]\\s$`),
39
- handler: ({ state, chain, range }) => {
40
- const blockInfo = getBlockInfoFromSelection(state);
41
- if (
42
- !blockInfo.isBlockContainer ||
43
- blockInfo.blockContent.node.type.spec.content !== "inline*"
44
- ) {
45
- return;
46
- }
47
-
48
- chain()
49
- .command(
50
- updateBlockCommand(blockInfo.bnBlock.beforePos, {
51
- type: "checkListItem",
52
- props: {
53
- checked: false as any,
54
- },
55
- }),
56
- )
57
- // Removes the characters used to set the list.
58
- .deleteRange({ from: range.from, to: range.to });
59
- },
60
- }),
61
- new InputRule({
62
- find: new RegExp(`\\[[Xx]\\]\\s$`),
63
- handler: ({ state, chain, range }) => {
64
- const blockInfo = getBlockInfoFromSelection(state);
65
-
66
- if (
67
- !blockInfo.isBlockContainer ||
68
- blockInfo.blockContent.node.type.spec.content !== "inline*"
69
- ) {
70
- return;
71
- }
72
-
73
- chain()
74
- .command(
75
- updateBlockCommand(blockInfo.bnBlock.beforePos, {
76
- type: "checkListItem",
77
- props: {
78
- checked: true as any,
79
- },
80
- }),
81
- )
82
- // Removes the characters used to set the list.
83
- .deleteRange({ from: range.from, to: range.to });
84
- },
85
- }),
86
- ];
87
- },
88
-
89
- addKeyboardShortcuts() {
90
- return {
91
- Enter: () => handleEnter(this.options.editor),
92
- "Mod-Shift-9": () => {
93
- const blockInfo = getBlockInfoFromSelection(this.editor.state);
94
- if (
95
- !blockInfo.isBlockContainer ||
96
- blockInfo.blockContent.node.type.spec.content !== "inline*"
97
- ) {
98
- return true;
99
- }
100
-
101
- return this.editor.commands.command(
102
- updateBlockCommand(blockInfo.bnBlock.beforePos, {
103
- type: "checkListItem",
104
- props: {},
105
- }),
106
- );
107
- },
108
- };
109
- },
110
-
111
- parseHTML() {
112
- return [
113
- // Parse from internal HTML.
114
- {
115
- tag: "div[data-content-type=" + this.name + "]",
116
- contentElement: ".bn-inline-content",
117
- },
118
- // Parse from external HTML.
119
- {
120
- tag: "input",
121
- getAttrs: (element) => {
122
- if (typeof element === "string") {
123
- return false;
124
- }
125
-
126
- // Ignore if we already parsed an ancestor list item to avoid double-parsing.
127
- if (element.closest("[data-content-type]") || element.closest("li")) {
128
- return false;
129
- }
130
-
131
- if ((element as HTMLInputElement).type === "checkbox") {
132
- return { checked: (element as HTMLInputElement).checked };
133
- }
134
-
135
- return false;
136
- },
137
- node: "checkListItem",
138
- },
139
- {
140
- tag: "li",
141
- getAttrs: (element) => {
142
- if (typeof element === "string") {
143
- return false;
144
- }
145
-
146
- const parent = element.parentElement;
147
-
148
- if (parent === null) {
149
- return false;
150
- }
151
-
152
- if (
153
- parent.tagName === "UL" ||
154
- (parent.tagName === "DIV" && parent.parentElement?.tagName === "UL")
155
- ) {
156
- const checkbox =
157
- (element.querySelector(
158
- "input[type=checkbox]",
159
- ) as HTMLInputElement) || null;
160
-
161
- if (checkbox === null) {
162
- return false;
163
- }
164
-
165
- return { checked: checkbox.checked };
166
- }
167
-
168
- return false;
169
- },
170
- // As `li` elements can contain multiple paragraphs, we need to merge their contents
171
- // into a single one so that ProseMirror can parse everything correctly.
172
- getContent: (node, schema) =>
173
- getListItemContent(node, schema, this.name),
174
- node: "checkListItem",
175
- },
176
- ];
177
- },
178
-
179
- // Since there is no HTML checklist element, there isn't really any
180
- // standardization for what checklists should look like in the DOM. GDocs'
181
- // and Notion's aren't cross compatible, for example. This implementation
182
- // has a semantically correct DOM structure (though missing a label for the
183
- // checkbox) which is also converted correctly to Markdown by remark.
184
- renderHTML({ node, HTMLAttributes }) {
185
- const checkbox = document.createElement("input");
186
- checkbox.type = "checkbox";
187
- checkbox.checked = node.attrs.checked;
188
- if (node.attrs.checked) {
189
- checkbox.setAttribute("checked", "");
190
- }
191
-
192
- const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
193
- this.name,
194
- "p",
195
- {
196
- ...(this.options.domAttributes?.blockContent || {}),
197
- ...HTMLAttributes,
198
- },
199
- this.options.domAttributes?.inlineContent || {},
200
- );
201
-
202
- dom.insertBefore(checkbox, contentDOM);
203
-
204
- return { dom, contentDOM };
205
- },
206
-
207
- // Need to render node view since the checkbox needs to be able to update the
208
- // node. This is only possible with a node view as it exposes `getPos`.
209
- addNodeView() {
210
- return ({ node, getPos, editor, HTMLAttributes }) => {
211
- // Need to wrap certain elements in a div or keyboard navigation gets
212
- // confused.
213
- const wrapper = document.createElement("div");
214
- const checkboxWrapper = document.createElement("div");
215
- checkboxWrapper.contentEditable = "false";
216
-
217
- const checkbox = document.createElement("input");
218
- checkbox.type = "checkbox";
219
- checkbox.checked = node.attrs.checked;
220
- if (node.attrs.checked) {
221
- checkbox.setAttribute("checked", "");
222
- }
223
-
224
- const changeHandler = () => {
225
- if (!editor.isEditable) {
226
- // This seems like the most effective way of blocking the checkbox
227
- // from being toggled, as event.preventDefault() does not stop it for
228
- // "click" or "change" events.
229
- checkbox.checked = !checkbox.checked;
230
- return;
231
- }
232
-
233
- // TODO: test
234
- if (typeof getPos !== "boolean") {
235
- const beforeBlockContainerPos = getNearestBlockPos(
236
- editor.state.doc,
237
- getPos(),
238
- );
239
-
240
- if (beforeBlockContainerPos.node.type.name !== "blockContainer") {
241
- throw new Error(
242
- `Expected blockContainer node, got ${beforeBlockContainerPos.node.type.name}`,
243
- );
244
- }
245
-
246
- this.editor.commands.command(
247
- updateBlockCommand(beforeBlockContainerPos.posBeforeNode, {
248
- type: "checkListItem",
249
- props: {
250
- checked: checkbox.checked as any,
251
- },
252
- }),
253
- );
254
- }
255
- };
256
- checkbox.addEventListener("change", changeHandler);
257
-
258
- const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
259
- this.name,
260
- "p",
261
- {
262
- ...(this.options.domAttributes?.blockContent || {}),
263
- ...HTMLAttributes,
264
- },
265
- this.options.domAttributes?.inlineContent || {},
266
- );
267
-
268
- if (typeof getPos !== "boolean") {
269
- // Since `node` is a blockContent node, we have to get the block ID from
270
- // the parent blockContainer node. This means we can't add the label in
271
- // `renderHTML` as we can't use `getPos` and therefore can't get the
272
- // parent blockContainer node.
273
- const blockID = this.editor.state.doc.resolve(getPos()).node().attrs.id;
274
- const label = "label-" + blockID;
275
- checkbox.setAttribute("aria-labelledby", label);
276
- contentDOM.id = label;
277
- }
278
-
279
- dom.removeChild(contentDOM);
280
- dom.appendChild(wrapper);
281
- wrapper.appendChild(checkboxWrapper);
282
- wrapper.appendChild(contentDOM);
283
- checkboxWrapper.appendChild(checkbox);
284
-
285
- return {
286
- dom,
287
- contentDOM,
288
- destroy: () => {
289
- checkbox.removeEventListener("change", changeHandler);
290
- },
291
- };
292
- };
293
- },
294
- });
295
-
296
- export const CheckListItem = createBlockSpecFromStronglyTypedTiptapNode(
297
- checkListItemBlockContent,
298
- checkListItemPropSchema,
299
- );
@@ -1,86 +0,0 @@
1
- import { Plugin, PluginKey } from "prosemirror-state";
2
- import { getBlockInfo } from "../../../api/getBlockInfoFromPos.js";
3
-
4
- // ProseMirror Plugin which automatically assigns indices to ordered list items per nesting level.
5
- const PLUGIN_KEY = new PluginKey(`numbered-list-indexing`);
6
- export const NumberedListIndexingPlugin = () => {
7
- return new Plugin({
8
- key: PLUGIN_KEY,
9
- appendTransaction: (_transactions, _oldState, newState) => {
10
- const tr = newState.tr;
11
- tr.setMeta("numberedListIndexing", true);
12
-
13
- let modified = false;
14
-
15
- // Traverses each node the doc using DFS, so blocks which are on the same nesting level will be traversed in the
16
- // same order they appear. This means the index of each list item block can be calculated by incrementing the
17
- // index of the previous list item block.
18
- newState.doc.descendants((node, pos) => {
19
- if (
20
- node.type.name === "blockContainer" &&
21
- node.firstChild!.type.name === "numberedListItem"
22
- ) {
23
- let newIndex = `${node.firstChild!.attrs["start"] || 1}`;
24
-
25
- const blockInfo = getBlockInfo({
26
- posBeforeNode: pos,
27
- node,
28
- });
29
-
30
- if (!blockInfo.isBlockContainer) {
31
- throw new Error("impossible");
32
- }
33
-
34
- // Checks if this block is the start of a new ordered list, i.e. if it's the first block in the document, the
35
- // first block in its nesting level, or the previous block is not an ordered list item.
36
-
37
- const prevBlock = tr.doc.resolve(
38
- blockInfo.bnBlock.beforePos,
39
- ).nodeBefore;
40
-
41
- if (prevBlock) {
42
- const prevBlockInfo = getBlockInfo({
43
- posBeforeNode: blockInfo.bnBlock.beforePos - prevBlock.nodeSize,
44
- node: prevBlock,
45
- });
46
-
47
- const isPrevBlockOrderedListItem =
48
- prevBlockInfo.blockNoteType === "numberedListItem";
49
-
50
- if (isPrevBlockOrderedListItem) {
51
- if (!prevBlockInfo.isBlockContainer) {
52
- throw new Error("impossible");
53
- }
54
- const prevBlockIndex =
55
- prevBlockInfo.blockContent.node.attrs["index"];
56
-
57
- newIndex = (parseInt(prevBlockIndex) + 1).toString();
58
- }
59
- }
60
-
61
- const contentNode = blockInfo.blockContent.node;
62
- const index = contentNode.attrs["index"];
63
- const isFirst =
64
- prevBlock?.firstChild?.type.name !== "numberedListItem";
65
-
66
- if (index !== newIndex || (contentNode.attrs.start && !isFirst)) {
67
- modified = true;
68
-
69
- const { start, ...attrs } = contentNode.attrs;
70
-
71
- tr.setNodeMarkup(blockInfo.blockContent.beforePos, undefined, {
72
- ...attrs,
73
- index: newIndex,
74
- ...(typeof start === "number" &&
75
- isFirst && {
76
- start,
77
- }),
78
- });
79
- }
80
- }
81
- });
82
-
83
- return modified ? tr : null;
84
- },
85
- });
86
- };
@@ -1,172 +0,0 @@
1
- import { InputRule } from "@tiptap/core";
2
- import { updateBlockCommand } from "../../../api/blockManipulation/commands/updateBlock/updateBlock.js";
3
- import { getBlockInfoFromSelection } from "../../../api/getBlockInfoFromPos.js";
4
- import {
5
- PropSchema,
6
- createBlockSpecFromStronglyTypedTiptapNode,
7
- createStronglyTypedTiptapNode,
8
- propsToAttributes,
9
- } from "../../../schema/index.js";
10
- import { createDefaultBlockDOMOutputSpec } from "../../defaultBlockHelpers.js";
11
- import { defaultProps } from "../../defaultProps.js";
12
- import { getListItemContent } from "../getListItemContent.js";
13
- import { handleEnter } from "../ListItemKeyboardShortcuts.js";
14
- import { NumberedListIndexingPlugin } from "./NumberedListIndexingPlugin.js";
15
-
16
- export const numberedListItemPropSchema = {
17
- ...defaultProps,
18
- start: { default: undefined, type: "number" },
19
- } satisfies PropSchema;
20
-
21
- const NumberedListItemBlockContent = createStronglyTypedTiptapNode({
22
- name: "numberedListItem",
23
- content: "inline*",
24
- group: "blockContent",
25
- priority: 90,
26
- addAttributes() {
27
- return {
28
- ...propsToAttributes(numberedListItemPropSchema),
29
- // the index attribute is only used internally (it's not part of the blocknote schema)
30
- // that's why it's defined explicitly here, and not part of the prop schema
31
- index: {
32
- default: null,
33
- parseHTML: (element) => element.getAttribute("data-index"),
34
- renderHTML: (attributes) => {
35
- return {
36
- "data-index": attributes.index,
37
- };
38
- },
39
- },
40
- };
41
- },
42
-
43
- addInputRules() {
44
- return [
45
- // Creates an ordered list when starting with "1.".
46
- new InputRule({
47
- find: new RegExp(`^(\\d+)\\.\\s$`),
48
- handler: ({ state, chain, range, match }) => {
49
- const blockInfo = getBlockInfoFromSelection(state);
50
- if (
51
- !blockInfo.isBlockContainer ||
52
- blockInfo.blockContent.node.type.spec.content !== "inline*" ||
53
- blockInfo.blockNoteType === "numberedListItem" ||
54
- blockInfo.blockNoteType === "heading"
55
- ) {
56
- return;
57
- }
58
- const startIndex = parseInt(match[1]);
59
-
60
- chain()
61
- .command(
62
- updateBlockCommand(blockInfo.bnBlock.beforePos, {
63
- type: "numberedListItem",
64
- props:
65
- (startIndex === 1 && {}) ||
66
- ({
67
- start: startIndex,
68
- } as any),
69
- }),
70
- )
71
- // Removes the "1." characters used to set the list.
72
- .deleteRange({ from: range.from, to: range.to });
73
- },
74
- }),
75
- ];
76
- },
77
-
78
- addKeyboardShortcuts() {
79
- return {
80
- Enter: () => handleEnter(this.options.editor),
81
- "Mod-Shift-7": () => {
82
- const blockInfo = getBlockInfoFromSelection(this.editor.state);
83
- if (
84
- !blockInfo.isBlockContainer ||
85
- blockInfo.blockContent.node.type.spec.content !== "inline*"
86
- ) {
87
- return true;
88
- }
89
-
90
- return this.editor.commands.command(
91
- updateBlockCommand(blockInfo.bnBlock.beforePos, {
92
- type: "numberedListItem",
93
- props: {},
94
- }),
95
- );
96
- },
97
- };
98
- },
99
-
100
- addProseMirrorPlugins() {
101
- return [NumberedListIndexingPlugin()];
102
- },
103
-
104
- parseHTML() {
105
- return [
106
- // Parse from internal HTML.
107
- {
108
- tag: "div[data-content-type=" + this.name + "]",
109
- contentElement: ".bn-inline-content",
110
- },
111
- // Parse from external HTML.
112
- {
113
- tag: "li",
114
- getAttrs: (element) => {
115
- if (typeof element === "string") {
116
- return false;
117
- }
118
-
119
- const parent = element.parentElement;
120
-
121
- if (parent === null) {
122
- return false;
123
- }
124
-
125
- if (
126
- parent.tagName === "OL" ||
127
- (parent.tagName === "DIV" && parent.parentElement?.tagName === "OL")
128
- ) {
129
- const startIndex =
130
- parseInt(parent.getAttribute("start") || "1") || 1;
131
-
132
- if (element.previousSibling || startIndex === 1) {
133
- return {};
134
- }
135
-
136
- return {
137
- start: startIndex,
138
- };
139
- }
140
-
141
- return false;
142
- },
143
- // As `li` elements can contain multiple paragraphs, we need to merge their contents
144
- // into a single one so that ProseMirror can parse everything correctly.
145
- getContent: (node, schema) =>
146
- getListItemContent(node, schema, this.name),
147
- priority: 300,
148
- node: "numberedListItem",
149
- },
150
- ];
151
- },
152
-
153
- renderHTML({ HTMLAttributes }) {
154
- return createDefaultBlockDOMOutputSpec(
155
- this.name,
156
- // We use a <p> tag, because for <li> tags we'd need an <ol> element to
157
- // put them in to be semantically correct, which we can't have due to the
158
- // schema.
159
- "p",
160
- {
161
- ...(this.options.domAttributes?.blockContent || {}),
162
- ...HTMLAttributes,
163
- },
164
- this.options.domAttributes?.inlineContent || {},
165
- );
166
- },
167
- });
168
-
169
- export const NumberedListItem = createBlockSpecFromStronglyTypedTiptapNode(
170
- NumberedListItemBlockContent,
171
- numberedListItemPropSchema,
172
- );
@@ -1,104 +0,0 @@
1
- import { updateBlockCommand } from "../../../api/blockManipulation/commands/updateBlock/updateBlock.js";
2
- import { getBlockInfoFromSelection } from "../../../api/getBlockInfoFromPos.js";
3
- import {
4
- PropSchema,
5
- createBlockSpecFromStronglyTypedTiptapNode,
6
- createStronglyTypedTiptapNode,
7
- getBlockFromPos,
8
- } from "../../../schema/index.js";
9
- import { createDefaultBlockDOMOutputSpec } from "../../defaultBlockHelpers.js";
10
- import { defaultProps } from "../../defaultProps.js";
11
- import { createToggleWrapper } from "../../ToggleWrapper/createToggleWrapper.js";
12
- import { handleEnter } from "../ListItemKeyboardShortcuts.js";
13
-
14
- export const toggleListItemPropSchema = {
15
- ...defaultProps,
16
- } satisfies PropSchema;
17
-
18
- const ToggleListItemBlockContent = createStronglyTypedTiptapNode({
19
- name: "toggleListItem",
20
- content: "inline*",
21
- group: "blockContent",
22
- // This is to make sure that the list item Enter keyboard handler takes
23
- // priority over the default one.
24
- priority: 90,
25
- addKeyboardShortcuts() {
26
- return {
27
- Enter: () => handleEnter(this.options.editor),
28
- "Mod-Shift-6": () => {
29
- const blockInfo = getBlockInfoFromSelection(this.editor.state);
30
- if (
31
- !blockInfo.isBlockContainer ||
32
- blockInfo.blockContent.node.type.spec.content !== "inline*"
33
- ) {
34
- return true;
35
- }
36
-
37
- return this.editor.commands.command(
38
- updateBlockCommand(blockInfo.bnBlock.beforePos, {
39
- type: "toggleListItem",
40
- props: {},
41
- }),
42
- );
43
- },
44
- };
45
- },
46
-
47
- parseHTML() {
48
- return [
49
- // Parse from internal HTML.
50
- {
51
- tag: "div[data-content-type=" + this.name + "]",
52
- contentElement: ".bn-inline-content",
53
- },
54
- ];
55
- },
56
-
57
- renderHTML({ HTMLAttributes }) {
58
- return createDefaultBlockDOMOutputSpec(
59
- this.name,
60
- "p",
61
- {
62
- ...(this.options.domAttributes?.blockContent || {}),
63
- ...HTMLAttributes,
64
- },
65
- this.options.domAttributes?.inlineContent || {},
66
- );
67
- },
68
-
69
- addNodeView() {
70
- return ({ HTMLAttributes, getPos }) => {
71
- const { dom, contentDOM } = createDefaultBlockDOMOutputSpec(
72
- this.name,
73
- "p",
74
- {
75
- ...(this.options.domAttributes?.blockContent || {}),
76
- ...HTMLAttributes,
77
- },
78
- this.options.domAttributes?.inlineContent || {},
79
- );
80
-
81
- const editor = this.options.editor;
82
- const block = getBlockFromPos(getPos, editor, this.editor, this.name);
83
-
84
- const toggleWrapper = createToggleWrapper(
85
- block as any,
86
- editor,
87
- contentDOM,
88
- );
89
- dom.appendChild(toggleWrapper.dom);
90
-
91
- return {
92
- dom,
93
- contentDOM,
94
- ignoreMutation: toggleWrapper.ignoreMutation,
95
- destroy: toggleWrapper.destroy,
96
- };
97
- };
98
- },
99
- });
100
-
101
- export const ToggleListItem = createBlockSpecFromStronglyTypedTiptapNode(
102
- ToggleListItemBlockContent,
103
- toggleListItemPropSchema,
104
- );
@@ -1,49 +0,0 @@
1
- import {
2
- createBlockSpec,
3
- CustomBlockConfig,
4
- Props,
5
- } from "../../schema/index.js";
6
-
7
- export const pageBreakConfig = {
8
- type: "pageBreak" as const,
9
- propSchema: {},
10
- content: "none",
11
- isFileBlock: false,
12
- isSelectable: false,
13
- } satisfies CustomBlockConfig;
14
- export const pageBreakRender = () => {
15
- const pageBreak = document.createElement("div");
16
-
17
- pageBreak.className = "bn-page-break";
18
- pageBreak.setAttribute("data-page-break", "");
19
-
20
- return {
21
- dom: pageBreak,
22
- };
23
- };
24
- export const pageBreakParse = (
25
- element: HTMLElement,
26
- ): Partial<Props<typeof pageBreakConfig.propSchema>> | undefined => {
27
- if (element.tagName === "DIV" && element.hasAttribute("data-page-break")) {
28
- return {
29
- type: "pageBreak",
30
- };
31
- }
32
-
33
- return undefined;
34
- };
35
- export const pageBreakToExternalHTML = () => {
36
- const pageBreak = document.createElement("div");
37
-
38
- pageBreak.setAttribute("data-page-break", "");
39
-
40
- return {
41
- dom: pageBreak,
42
- };
43
- };
44
-
45
- export const PageBreak = createBlockSpec(pageBreakConfig, {
46
- render: pageBreakRender,
47
- parse: pageBreakParse,
48
- toExternalHTML: pageBreakToExternalHTML,
49
- });