@blocknote/core 0.37.0 → 0.39.0

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 (271) 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 +3311 -7230
  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/{en-CvDoFvhc.js → en-Bq3Es3Np.js} +6 -12
  14. package/dist/en-Bq3Es3Np.js.map +1 -0
  15. package/dist/en-D3B48eJ7.cjs +2 -0
  16. package/dist/en-D3B48eJ7.cjs.map +1 -0
  17. package/dist/locales.cjs +1 -1
  18. package/dist/locales.cjs.map +1 -1
  19. package/dist/locales.js +109 -229
  20. package/dist/locales.js.map +1 -1
  21. package/dist/style.css +1 -1
  22. package/dist/tsconfig.tsbuildinfo +1 -0
  23. package/dist/webpack-stats.json +1 -1
  24. package/package.json +25 -22
  25. package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +1 -1
  26. package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +2 -2
  27. package/src/api/blockManipulation/commands/splitBlock/splitBlock.ts +34 -25
  28. package/src/api/blockManipulation/setupTestEnv.ts +0 -1
  29. package/src/api/clipboard/fromClipboard/handleFileInsertion.ts +4 -8
  30. package/src/api/clipboard/toClipboard/copyExtension.ts +1 -3
  31. package/src/api/exporters/html/externalHTMLExporter.ts +0 -1
  32. package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +128 -28
  33. package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +101 -41
  34. package/src/api/exporters/markdown/markdownExporter.ts +13 -22
  35. package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +2 -12
  36. package/src/api/parsers/html/parseHTML.ts +3 -2
  37. package/src/api/parsers/html/util/nestedLists.test.ts +8 -8
  38. package/src/api/parsers/markdown/parseMarkdown.ts +17 -14
  39. package/src/api/pmUtil.ts +1 -1
  40. package/src/api/positionMapping.test.ts +197 -33
  41. package/src/api/positionMapping.ts +4 -6
  42. package/src/blocks/Audio/block.ts +174 -0
  43. package/src/blocks/BlockNoteSchema.ts +59 -0
  44. package/src/blocks/Code/block.ts +303 -0
  45. package/src/blocks/Code/shiki.ts +73 -0
  46. package/src/blocks/File/block.ts +98 -0
  47. package/src/blocks/{FileBlockContent → File}/helpers/render/createAddFileButton.ts +8 -4
  48. package/src/blocks/{FileBlockContent → File}/helpers/render/createFileBlockWrapper.ts +16 -13
  49. package/src/blocks/{FileBlockContent → File}/helpers/render/createFileNameWithIcon.ts +15 -2
  50. package/src/blocks/{FileBlockContent → File}/helpers/render/createResizableFileBlockWrapper.ts +63 -19
  51. package/src/blocks/Heading/block.ts +138 -0
  52. package/src/blocks/Image/block.ts +190 -0
  53. package/src/blocks/ListItem/BulletListItem/block.ts +116 -0
  54. package/src/blocks/ListItem/CheckListItem/block.ts +175 -0
  55. package/src/blocks/ListItem/NumberedListItem/IndexingPlugin.ts +173 -0
  56. package/src/blocks/ListItem/NumberedListItem/block.ts +133 -0
  57. package/src/blocks/ListItem/ToggleListItem/block.ts +78 -0
  58. package/src/blocks/PageBreak/block.ts +72 -0
  59. package/src/blocks/{PageBreakBlockContent → PageBreak}/getPageBreakSlashMenuItems.ts +9 -7
  60. package/src/blocks/Paragraph/block.ts +80 -0
  61. package/src/blocks/Quote/block.ts +90 -0
  62. package/src/blocks/{TableBlockContent/TableBlockContent.ts → Table/block.ts} +169 -51
  63. package/src/blocks/ToggleWrapper/createToggleWrapper.ts +1 -1
  64. package/src/blocks/Video/block.ts +143 -0
  65. package/src/blocks/defaultBlockHelpers.ts +2 -2
  66. package/src/blocks/defaultBlockTypeGuards.ts +143 -174
  67. package/src/blocks/defaultBlocks.ts +107 -35
  68. package/src/blocks/defaultProps.ts +145 -4
  69. package/src/blocks/index.ts +26 -0
  70. package/src/blocks/utils/listItemEnterHandler.ts +42 -0
  71. package/src/editor/Block.css +54 -18
  72. package/src/editor/BlockNoteEditor.ts +265 -230
  73. package/src/editor/BlockNoteExtension.ts +92 -0
  74. package/src/editor/BlockNoteExtensions.ts +20 -16
  75. package/src/editor/defaultColors.ts +2 -2
  76. package/src/exporter/Exporter.ts +1 -1
  77. package/src/exporter/mapping.ts +1 -1
  78. package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +3 -20
  79. package/src/extensions/BackgroundColor/BackgroundColorMark.ts +6 -8
  80. package/src/extensions/BlockChange/BlockChangePlugin.ts +2 -1
  81. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor-forked.json +2 -2
  82. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor.json +2 -2
  83. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-forked.html +1 -1
  84. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap.html +1 -1
  85. package/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.ts +52 -0
  86. package/src/extensions/Collaboration/schemaMigration/migrationRules/index.ts +4 -0
  87. package/src/extensions/Collaboration/schemaMigration/migrationRules/migrationRule.ts +4 -0
  88. package/src/extensions/Collaboration/schemaMigration/migrationRules/moveColorAttributes.ts +78 -0
  89. package/src/extensions/Comments/CommentsPlugin.ts +2 -0
  90. package/src/extensions/FilePanel/FilePanelPlugin.ts +5 -10
  91. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +1 -1
  92. package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +4 -3
  93. package/src/extensions/Placeholder/PlaceholderPlugin.ts +2 -2
  94. package/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts +1 -23
  95. package/src/extensions/SideMenu/SideMenuPlugin.ts +0 -2
  96. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +0 -5
  97. package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +6 -2
  98. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +24 -17
  99. package/src/extensions/TableHandles/TableHandlesPlugin.ts +2 -2
  100. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +5 -11
  101. package/src/extensions/TextColor/TextColorExtension.ts +3 -17
  102. package/src/extensions/TextColor/TextColorMark.ts +4 -9
  103. package/src/extensions/UniqueID/UniqueID.ts +6 -13
  104. package/src/i18n/locales/ar.ts +6 -12
  105. package/src/i18n/locales/de.ts +6 -12
  106. package/src/i18n/locales/en.ts +6 -12
  107. package/src/i18n/locales/es.ts +6 -12
  108. package/src/i18n/locales/fr.ts +6 -12
  109. package/src/i18n/locales/he.ts +6 -12
  110. package/src/i18n/locales/hr.ts +6 -12
  111. package/src/i18n/locales/is.ts +6 -12
  112. package/src/i18n/locales/it.ts +6 -12
  113. package/src/i18n/locales/ja.ts +6 -12
  114. package/src/i18n/locales/ko.ts +6 -12
  115. package/src/i18n/locales/nl.ts +6 -12
  116. package/src/i18n/locales/no.ts +6 -12
  117. package/src/i18n/locales/pl.ts +6 -12
  118. package/src/i18n/locales/pt.ts +6 -12
  119. package/src/i18n/locales/ru.ts +6 -12
  120. package/src/i18n/locales/sk.ts +6 -12
  121. package/src/i18n/locales/uk.ts +6 -12
  122. package/src/i18n/locales/vi.ts +6 -12
  123. package/src/i18n/locales/zh-tw.ts +6 -12
  124. package/src/i18n/locales/zh.ts +6 -12
  125. package/src/index.ts +2 -29
  126. package/src/schema/blocks/createSpec.ts +342 -169
  127. package/src/schema/blocks/internal.ts +77 -138
  128. package/src/schema/blocks/types.ts +264 -94
  129. package/src/schema/index.ts +1 -0
  130. package/src/schema/inlineContent/createSpec.ts +99 -21
  131. package/src/schema/inlineContent/internal.ts +16 -7
  132. package/src/schema/inlineContent/types.ts +24 -2
  133. package/src/schema/propTypes.ts +15 -9
  134. package/src/schema/schema.ts +209 -0
  135. package/src/schema/styles/createSpec.ts +79 -31
  136. package/src/schema/styles/internal.ts +61 -2
  137. package/src/schema/styles/types.ts +17 -3
  138. package/src/util/topo-sort.test.ts +125 -0
  139. package/src/util/topo-sort.ts +160 -0
  140. package/types/src/api/blockManipulation/commands/splitBlock/splitBlock.d.ts +2 -1
  141. package/types/src/api/blockManipulation/selections/selection.d.ts +1 -1
  142. package/types/src/api/blockManipulation/setupTestEnv.d.ts +29 -543
  143. package/types/src/api/exporters/html/util/serializeBlocksExternalHTML.d.ts +1 -1
  144. package/types/src/api/exporters/html/util/serializeBlocksInternalHTML.d.ts +1 -1
  145. package/types/src/api/exporters/markdown/markdownExporter.d.ts +1 -1
  146. package/types/src/api/parsers/html/parseHTML.d.ts +1 -1
  147. package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -2
  148. package/types/src/api/pmUtil.d.ts +1 -1
  149. package/types/src/blocks/Audio/block.d.ts +58 -0
  150. package/types/src/blocks/BlockNoteSchema.d.ts +18 -0
  151. package/types/src/blocks/{CodeBlockContent/CodeBlockContent.d.ts → Code/block.d.ts} +25 -26
  152. package/types/src/blocks/Code/shiki.d.ts +4 -0
  153. package/types/src/blocks/File/block.d.ts +37 -0
  154. package/types/src/blocks/File/helpers/render/createAddFileButton.d.ts +6 -0
  155. package/types/src/blocks/File/helpers/render/createFileBlockWrapper.d.ts +25 -0
  156. package/types/src/blocks/{FileBlockContent → File}/helpers/render/createFileNameWithIcon.d.ts +6 -2
  157. package/types/src/blocks/File/helpers/render/createResizableFileBlockWrapper.d.ts +31 -0
  158. package/types/src/blocks/Heading/block.d.ts +71 -0
  159. package/types/src/blocks/Image/block.d.ts +102 -0
  160. package/types/src/blocks/ListItem/BulletListItem/block.d.ts +25 -0
  161. package/types/src/blocks/ListItem/CheckListItem/block.d.ts +33 -0
  162. package/types/src/blocks/ListItem/NumberedListItem/IndexingPlugin.d.ts +8 -0
  163. package/types/src/blocks/ListItem/NumberedListItem/block.d.ts +33 -0
  164. package/types/src/blocks/ListItem/ToggleListItem/block.d.ts +25 -0
  165. package/types/src/blocks/PageBreak/block.d.ts +11 -0
  166. package/types/src/blocks/{PageBreakBlockContent → PageBreak}/getPageBreakSlashMenuItems.d.ts +4 -2
  167. package/types/src/blocks/Paragraph/block.d.ts +25 -0
  168. package/types/src/blocks/Quote/block.d.ts +17 -0
  169. package/types/src/blocks/Table/block.d.ts +21 -0
  170. package/types/src/blocks/Video/block.d.ts +67 -0
  171. package/types/src/blocks/defaultBlockHelpers.d.ts +1 -1
  172. package/types/src/blocks/defaultBlockTypeGuards.d.ts +15 -36
  173. package/types/src/blocks/defaultBlocks.d.ts +221 -1060
  174. package/types/src/blocks/defaultProps.d.ts +17 -1
  175. package/types/src/blocks/index.d.ts +24 -0
  176. package/types/src/blocks/utils/listItemEnterHandler.d.ts +2 -0
  177. package/types/src/editor/BlockNoteEditor.d.ts +39 -75
  178. package/types/src/editor/BlockNoteExtension.d.ts +67 -0
  179. package/types/src/editor/BlockNoteExtensions.d.ts +2 -0
  180. package/types/src/editor/defaultColors.d.ts +8 -76
  181. package/types/src/exporter/Exporter.d.ts +1 -1
  182. package/types/src/exporter/mapping.d.ts +1 -1
  183. package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +4 -1
  184. package/types/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.d.ts +7 -0
  185. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/index.d.ts +3 -0
  186. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/migrationRule.d.ts +3 -0
  187. package/types/src/extensions/Collaboration/schemaMigration/migrationRules/moveColorAttributes.d.ts +2 -0
  188. package/types/src/extensions/Comments/CommentsPlugin.d.ts +3 -1
  189. package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +4 -4
  190. package/types/src/extensions/TextColor/TextColorMark.d.ts +4 -1
  191. package/types/src/i18n/locales/en.d.ts +1 -12
  192. package/types/src/i18n/locales/sk.d.ts +1 -12
  193. package/types/src/index.d.ts +2 -26
  194. package/types/src/schema/blocks/createSpec.d.ts +16 -36
  195. package/types/src/schema/blocks/internal.d.ts +11 -33
  196. package/types/src/schema/blocks/types.d.ts +181 -57
  197. package/types/src/schema/index.d.ts +1 -0
  198. package/types/src/schema/inlineContent/createSpec.d.ts +36 -2
  199. package/types/src/schema/inlineContent/internal.d.ts +7 -15
  200. package/types/src/schema/inlineContent/types.d.ts +15 -1
  201. package/types/src/schema/propTypes.d.ts +4 -4
  202. package/types/src/schema/schema.d.ts +40 -0
  203. package/types/src/schema/styles/createSpec.d.ts +6 -4
  204. package/types/src/schema/styles/internal.d.ts +6 -3
  205. package/types/src/schema/styles/types.d.ts +11 -2
  206. package/types/src/util/topo-sort.d.ts +18 -0
  207. package/types/src/util/topo-sort.test.d.ts +1 -0
  208. package/dist/en-CvDoFvhc.js.map +0 -1
  209. package/dist/en-ub2yVBX0.cjs +0 -2
  210. package/dist/en-ub2yVBX0.cjs.map +0 -1
  211. package/src/blocks/AudioBlockContent/AudioBlockContent.ts +0 -145
  212. package/src/blocks/CodeBlockContent/CodeBlockContent.ts +0 -445
  213. package/src/blocks/FileBlockContent/FileBlockContent.ts +0 -100
  214. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +0 -159
  215. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +0 -160
  216. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +0 -134
  217. package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +0 -299
  218. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +0 -86
  219. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +0 -172
  220. package/src/blocks/ListItemBlockContent/ToggleListItemBlockContent/ToggleListItemBlockContent.ts +0 -104
  221. package/src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts +0 -49
  222. package/src/blocks/PageBreakBlockContent/schema.ts +0 -40
  223. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +0 -78
  224. package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +0 -121
  225. package/src/blocks/VideoBlockContent/VideoBlockContent.ts +0 -159
  226. package/src/editor/BlockNoteSchema.ts +0 -107
  227. package/src/editor/BlockNoteTipTapEditor.ts +0 -335
  228. package/src/util/esmDependencies.ts +0 -51
  229. package/types/src/blocks/AudioBlockContent/AudioBlockContent.d.ts +0 -99
  230. package/types/src/blocks/FileBlockContent/FileBlockContent.d.ts +0 -90
  231. package/types/src/blocks/FileBlockContent/helpers/render/createAddFileButton.d.ts +0 -6
  232. package/types/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.d.ts +0 -9
  233. package/types/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.d.ts +0 -9
  234. package/types/src/blocks/HeadingBlockContent/HeadingBlockContent.d.ts +0 -67
  235. package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +0 -131
  236. package/types/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +0 -46
  237. package/types/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.d.ts +0 -55
  238. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.d.ts +0 -2
  239. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +0 -58
  240. package/types/src/blocks/ListItemBlockContent/ToggleListItemBlockContent/ToggleListItemBlockContent.d.ts +0 -46
  241. package/types/src/blocks/PageBreakBlockContent/PageBreakBlockContent.d.ts +0 -31
  242. package/types/src/blocks/PageBreakBlockContent/schema.d.ts +0 -86
  243. package/types/src/blocks/ParagraphBlockContent/ParagraphBlockContent.d.ts +0 -52
  244. package/types/src/blocks/QuoteBlockContent/QuoteBlockContent.d.ts +0 -52
  245. package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +0 -39
  246. package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +0 -131
  247. package/types/src/editor/BlockNoteSchema.d.ts +0 -34
  248. package/types/src/editor/BlockNoteTipTapEditor.d.ts +0 -43
  249. package/types/src/util/esmDependencies.d.ts +0 -24
  250. /package/src/blocks/{AudioBlockContent → Audio}/parseAudioElement.ts +0 -0
  251. /package/src/blocks/{FileBlockContent → File}/helpers/parse/parseEmbedElement.ts +0 -0
  252. /package/src/blocks/{FileBlockContent → File}/helpers/parse/parseFigureElement.ts +0 -0
  253. /package/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createFigureWithCaption.ts +0 -0
  254. /package/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createLinkWithCaption.ts +0 -0
  255. /package/src/blocks/{FileBlockContent → File/helpers}/uploadToTmpFilesDotOrg_DEV_ONLY.ts +0 -0
  256. /package/src/blocks/{ImageBlockContent → Image}/parseImageElement.ts +0 -0
  257. /package/src/blocks/{ListItemBlockContent → ListItem}/ListItemKeyboardShortcuts.ts +0 -0
  258. /package/src/blocks/{ListItemBlockContent → ListItem}/getListItemContent.ts +0 -0
  259. /package/src/blocks/{TableBlockContent → Table}/TableExtension.ts +0 -0
  260. /package/src/blocks/{VideoBlockContent → Video}/parseVideoElement.ts +0 -0
  261. /package/types/src/blocks/{AudioBlockContent → Audio}/parseAudioElement.d.ts +0 -0
  262. /package/types/src/blocks/{FileBlockContent → File}/helpers/parse/parseEmbedElement.d.ts +0 -0
  263. /package/types/src/blocks/{FileBlockContent → File}/helpers/parse/parseFigureElement.d.ts +0 -0
  264. /package/types/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createFigureWithCaption.d.ts +0 -0
  265. /package/types/src/blocks/{FileBlockContent → File}/helpers/toExternalHTML/createLinkWithCaption.d.ts +0 -0
  266. /package/types/src/blocks/{FileBlockContent → File/helpers}/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +0 -0
  267. /package/types/src/blocks/{ImageBlockContent → Image}/parseImageElement.d.ts +0 -0
  268. /package/types/src/blocks/{ListItemBlockContent → ListItem}/ListItemKeyboardShortcuts.d.ts +0 -0
  269. /package/types/src/blocks/{ListItemBlockContent → ListItem}/getListItemContent.d.ts +0 -0
  270. /package/types/src/blocks/{TableBlockContent → Table}/TableExtension.d.ts +0 -0
  271. /package/types/src/blocks/{VideoBlockContent → Video}/parseVideoElement.d.ts +0 -0
@@ -0,0 +1,175 @@
1
+ import { createBlockNoteExtension } from "../../../editor/BlockNoteExtension.js";
2
+ import { createBlockConfig, createBlockSpec } from "../../../schema/index.js";
3
+ import {
4
+ addDefaultPropsExternalHTML,
5
+ defaultProps,
6
+ parseDefaultProps,
7
+ } from "../../defaultProps.js";
8
+ import { handleEnter } from "../../utils/listItemEnterHandler.js";
9
+ import { getListItemContent } from "../getListItemContent.js";
10
+
11
+ export type CheckListItemBlockConfig = ReturnType<
12
+ typeof createCheckListItemConfig
13
+ >;
14
+
15
+ export const createCheckListItemConfig = createBlockConfig(
16
+ () =>
17
+ ({
18
+ type: "checkListItem" as const,
19
+ propSchema: {
20
+ ...defaultProps,
21
+ checked: { default: false, type: "boolean" },
22
+ },
23
+ content: "inline",
24
+ }) as const,
25
+ );
26
+
27
+ export const createCheckListItemBlockSpec = createBlockSpec(
28
+ createCheckListItemConfig,
29
+ {
30
+ meta: {
31
+ isolating: false,
32
+ },
33
+ parse(element) {
34
+ if (element.tagName === "input") {
35
+ // Ignore if we already parsed an ancestor list item to avoid double-parsing.
36
+ if (element.closest("[data-content-type]") || element.closest("li")) {
37
+ return undefined;
38
+ }
39
+
40
+ if ((element as HTMLInputElement).type === "checkbox") {
41
+ return { checked: (element as HTMLInputElement).checked };
42
+ }
43
+ return undefined;
44
+ }
45
+ if (element.tagName !== "LI") {
46
+ return undefined;
47
+ }
48
+
49
+ const parent = element.parentElement;
50
+
51
+ if (parent === null) {
52
+ return undefined;
53
+ }
54
+
55
+ if (
56
+ parent.tagName === "UL" ||
57
+ (parent.tagName === "DIV" && parent.parentElement?.tagName === "UL")
58
+ ) {
59
+ const checkbox =
60
+ (element.querySelector("input[type=checkbox]") as HTMLInputElement) ||
61
+ null;
62
+
63
+ if (checkbox === null) {
64
+ return undefined;
65
+ }
66
+
67
+ return { ...parseDefaultProps(element), checked: checkbox.checked };
68
+ }
69
+
70
+ return;
71
+ },
72
+ // As `li` elements can contain multiple paragraphs, we need to merge their contents
73
+ // into a single one so that ProseMirror can parse everything correctly.
74
+ parseContent: ({ el, schema }) =>
75
+ getListItemContent(el, schema, "checkListItem"),
76
+ render(block, editor) {
77
+ const dom = document.createDocumentFragment();
78
+ const checkbox = document.createElement("input");
79
+ checkbox.type = "checkbox";
80
+ checkbox.checked = block.props.checked;
81
+ if (block.props.checked) {
82
+ checkbox.setAttribute("checked", "");
83
+ }
84
+ checkbox.addEventListener("change", () => {
85
+ editor.updateBlock(block, { props: { checked: !block.props.checked } });
86
+ });
87
+ // We use a <p> tag, because for <li> tags we'd need a <ul> element to put
88
+ // them in to be semantically correct, which we can't have due to the
89
+ // schema.
90
+ const paragraph = document.createElement("p");
91
+
92
+ dom.appendChild(checkbox);
93
+ dom.appendChild(paragraph);
94
+
95
+ return {
96
+ dom,
97
+ contentDOM: paragraph,
98
+ };
99
+ },
100
+ toExternalHTML(block) {
101
+ const dom = document.createElement("li");
102
+ const checkbox = document.createElement("input");
103
+ checkbox.type = "checkbox";
104
+ checkbox.checked = block.props.checked;
105
+ if (block.props.checked) {
106
+ checkbox.setAttribute("checked", "");
107
+ }
108
+ // We use a <p> tag, because for <li> tags we'd need a <ul> element to put
109
+ // them in to be semantically correct, which we can't have due to the
110
+ // schema.
111
+ const paragraph = document.createElement("p");
112
+ addDefaultPropsExternalHTML(block.props, dom);
113
+
114
+ dom.appendChild(checkbox);
115
+ dom.appendChild(paragraph);
116
+
117
+ return {
118
+ dom,
119
+ contentDOM: paragraph,
120
+ };
121
+ },
122
+ runsBefore: ["bulletListItem"],
123
+ },
124
+ [
125
+ createBlockNoteExtension({
126
+ key: "check-list-item-shortcuts",
127
+ keyboardShortcuts: {
128
+ Enter: ({ editor }) => {
129
+ return handleEnter(editor, "checkListItem");
130
+ },
131
+ "Mod-Shift-9": ({ editor }) => {
132
+ const cursorPosition = editor.getTextCursorPosition();
133
+
134
+ if (
135
+ editor.schema.blockSchema[cursorPosition.block.type].content !==
136
+ "inline"
137
+ ) {
138
+ return false;
139
+ }
140
+
141
+ editor.updateBlock(cursorPosition.block, {
142
+ type: "checkListItem",
143
+ props: {},
144
+ });
145
+ return true;
146
+ },
147
+ },
148
+ inputRules: [
149
+ {
150
+ find: new RegExp(`\\[\\s*\\]\\s$`),
151
+ replace() {
152
+ return {
153
+ type: "checkListItem",
154
+ props: {
155
+ checked: false,
156
+ },
157
+ content: [],
158
+ };
159
+ },
160
+ },
161
+ {
162
+ find: new RegExp(`\\[[Xx]\\]\\s$`),
163
+ replace() {
164
+ return {
165
+ type: "checkListItem",
166
+ props: {
167
+ checked: true,
168
+ },
169
+ };
170
+ },
171
+ },
172
+ ],
173
+ }),
174
+ ],
175
+ );
@@ -0,0 +1,173 @@
1
+ import type { Node } from "@tiptap/pm/model";
2
+ import type { Transaction } from "@tiptap/pm/state";
3
+ import { Plugin, PluginKey } from "@tiptap/pm/state";
4
+ import { Decoration, DecorationSet } from "@tiptap/pm/view";
5
+
6
+ import { getBlockInfo } from "../../../api/getBlockInfoFromPos.js";
7
+
8
+ // Loosely based on https://github.com/ueberdosis/tiptap/blob/7ac01ef0b816a535e903b5ca92492bff110a71ae/packages/extension-mathematics/src/MathematicsPlugin.ts (MIT)
9
+
10
+ type DecoSpec = {
11
+ index: number;
12
+ isFirst: boolean;
13
+ hasStart: boolean;
14
+ side: number;
15
+ };
16
+
17
+ type Deco = Omit<Decoration, "spec"> & { spec: DecoSpec };
18
+
19
+ /**
20
+ * Calculate the index for a numbered list item based on its position and previous siblings
21
+ */
22
+ function calculateListItemIndex(
23
+ node: Node,
24
+ pos: number,
25
+ tr: Transaction,
26
+ map: Map<Node, number>,
27
+ ): { index: number; isFirst: boolean; hasStart: boolean } {
28
+ let index: number = node.firstChild!.attrs["start"] || 1;
29
+ let isFirst = true;
30
+ const hasStart = !!node.firstChild!.attrs["start"];
31
+
32
+ const blockInfo = getBlockInfo({
33
+ posBeforeNode: pos,
34
+ node,
35
+ });
36
+
37
+ if (!blockInfo.isBlockContainer) {
38
+ throw new Error("impossible");
39
+ }
40
+
41
+ // Check if this block is the start of a new ordered list
42
+ const prevBlock = tr.doc.resolve(blockInfo.bnBlock.beforePos).nodeBefore;
43
+ const prevBlockIndex = prevBlock ? map.get(prevBlock) : undefined;
44
+
45
+ if (prevBlockIndex !== undefined) {
46
+ index = prevBlockIndex + 1;
47
+ isFirst = false;
48
+ } else if (prevBlock) {
49
+ // Because we only check the affected ranges, we may need to walk backwards to find the previous block's index
50
+ // We can't just rely on the map, because the map is reset every `apply` call
51
+ const prevBlockInfo = getBlockInfo({
52
+ posBeforeNode: blockInfo.bnBlock.beforePos - prevBlock.nodeSize,
53
+ node: prevBlock,
54
+ });
55
+
56
+ const isPrevBlockOrderedListItem =
57
+ prevBlockInfo.blockNoteType === "numberedListItem";
58
+ if (isPrevBlockOrderedListItem) {
59
+ // recurse to get the index of the previous block
60
+ const itemIndex = calculateListItemIndex(
61
+ prevBlock,
62
+ blockInfo.bnBlock.beforePos - prevBlock.nodeSize,
63
+ tr,
64
+ map,
65
+ );
66
+ index = itemIndex.index + 1;
67
+ isFirst = false;
68
+ }
69
+ }
70
+ // Note: we set the map late, so that when we recurse, we can rely on the map to get the previous block's index in one lookup
71
+ map.set(node, index);
72
+
73
+ return { index, isFirst, hasStart };
74
+ }
75
+
76
+ /**
77
+ * Get the decorations for the current state based on the previous state,
78
+ * and the transaction that was applied to get to the current state
79
+ */
80
+ function getDecorations(
81
+ tr: Transaction,
82
+ previousPluginState: { decorations: DecorationSet },
83
+ ) {
84
+ const map = new Map<Node, number>();
85
+
86
+ const nextDecorationSet = previousPluginState.decorations.map(
87
+ tr.mapping,
88
+ tr.doc,
89
+ );
90
+ const decorationsToAdd = [] as Deco[];
91
+
92
+ tr.doc.nodesBetween(0, tr.doc.nodeSize - 2, (node, pos) => {
93
+ if (
94
+ node.type.name === "blockContainer" &&
95
+ node.firstChild!.type.name === "numberedListItem"
96
+ ) {
97
+ const { index, isFirst, hasStart } = calculateListItemIndex(
98
+ node,
99
+ pos,
100
+ tr,
101
+ map,
102
+ );
103
+
104
+ // Check if decoration already exists with the same properties (for perf reasons)
105
+ const existingDecorations = nextDecorationSet.find(
106
+ pos,
107
+ pos + node.nodeSize,
108
+ (deco: DecoSpec) =>
109
+ deco.index === index &&
110
+ deco.isFirst === isFirst &&
111
+ deco.hasStart === hasStart,
112
+ );
113
+
114
+ if (existingDecorations.length === 0) {
115
+ // Create a widget decoration to display the index
116
+ decorationsToAdd.push(
117
+ // move in by 1 to account for the block container
118
+ Decoration.node(pos + 1, pos + node.nodeSize - 1, {
119
+ "data-index": index.toString(),
120
+ }),
121
+ );
122
+ }
123
+ }
124
+ });
125
+
126
+ // Remove any decorations that exist at the same position, they will be replaced by the new decorations
127
+ const decorationsToRemove = decorationsToAdd.flatMap((deco) =>
128
+ nextDecorationSet.find(deco.from, deco.to),
129
+ );
130
+
131
+ return {
132
+ decorations: nextDecorationSet
133
+ // Remove existing decorations that are going to be replaced
134
+ .remove(decorationsToRemove)
135
+ // Add any new decorations
136
+ .add(tr.doc, decorationsToAdd),
137
+ };
138
+ }
139
+
140
+ /**
141
+ * This plugin adds decorations to numbered list items to display their index.
142
+ */
143
+ export const NumberedListIndexingDecorationPlugin = () => {
144
+ return new Plugin<{ decorations: DecorationSet }>({
145
+ key: new PluginKey("numbered-list-indexing-decorations"),
146
+
147
+ state: {
148
+ init(_config, state) {
149
+ // We create an empty transaction to get the decorations for the initial state based on the initial content
150
+ return getDecorations(state.tr, {
151
+ decorations: DecorationSet.empty,
152
+ });
153
+ },
154
+ apply(tr, previousPluginState) {
155
+ if (
156
+ !tr.docChanged &&
157
+ !tr.selectionSet &&
158
+ previousPluginState.decorations
159
+ ) {
160
+ // Just reuse the existing decorations, since nothing should have changed
161
+ return previousPluginState;
162
+ }
163
+ return getDecorations(tr, previousPluginState);
164
+ },
165
+ },
166
+
167
+ props: {
168
+ decorations(state) {
169
+ return this.getState(state)?.decorations ?? DecorationSet.empty;
170
+ },
171
+ },
172
+ });
173
+ };
@@ -0,0 +1,133 @@
1
+ import { createBlockNoteExtension } from "../../../editor/BlockNoteExtension.js";
2
+ import { createBlockConfig, createBlockSpec } from "../../../schema/index.js";
3
+ import {
4
+ addDefaultPropsExternalHTML,
5
+ defaultProps,
6
+ parseDefaultProps,
7
+ } from "../../defaultProps.js";
8
+ import { handleEnter } from "../../utils/listItemEnterHandler.js";
9
+ import { getListItemContent } from "../getListItemContent.js";
10
+ import { NumberedListIndexingDecorationPlugin } from "./IndexingPlugin.js";
11
+
12
+ export type NumberedListItemBlockConfig = ReturnType<
13
+ typeof createNumberedListItemBlockConfig
14
+ >;
15
+
16
+ export const createNumberedListItemBlockConfig = createBlockConfig(
17
+ () =>
18
+ ({
19
+ type: "numberedListItem" as const,
20
+ propSchema: {
21
+ ...defaultProps,
22
+ start: { default: undefined, type: "number" } as const,
23
+ },
24
+ content: "inline",
25
+ }) as const,
26
+ );
27
+
28
+ export const createNumberedListItemBlockSpec = createBlockSpec(
29
+ createNumberedListItemBlockConfig,
30
+ {
31
+ meta: {
32
+ isolating: false,
33
+ },
34
+ parse(element) {
35
+ if (element.tagName !== "LI") {
36
+ return undefined;
37
+ }
38
+
39
+ const parent = element.parentElement;
40
+
41
+ if (parent === null) {
42
+ return undefined;
43
+ }
44
+
45
+ if (
46
+ parent.tagName === "OL" ||
47
+ (parent.tagName === "DIV" && parent.parentElement?.tagName === "OL")
48
+ ) {
49
+ const startIndex = parseInt(parent.getAttribute("start") || "1");
50
+
51
+ const defaultProps = parseDefaultProps(element);
52
+
53
+ if (element.previousElementSibling || startIndex === 1) {
54
+ return defaultProps;
55
+ }
56
+
57
+ return {
58
+ ...defaultProps,
59
+ start: startIndex,
60
+ };
61
+ }
62
+
63
+ return undefined;
64
+ },
65
+ // As `li` elements can contain multiple paragraphs, we need to merge their contents
66
+ // into a single one so that ProseMirror can parse everything correctly.
67
+ parseContent: ({ el, schema }) =>
68
+ getListItemContent(el, schema, "numberedListItem"),
69
+ render() {
70
+ // We use a <p> tag, because for <li> tags we'd need a <ul> element to put
71
+ // them in to be semantically correct, which we can't have due to the
72
+ // schema.
73
+ const dom = document.createElement("p");
74
+
75
+ return {
76
+ dom,
77
+ contentDOM: dom,
78
+ };
79
+ },
80
+ toExternalHTML(block) {
81
+ const li = document.createElement("li");
82
+ const p = document.createElement("p");
83
+ addDefaultPropsExternalHTML(block.props, li);
84
+ li.appendChild(p);
85
+
86
+ return {
87
+ dom: li,
88
+ contentDOM: p,
89
+ };
90
+ },
91
+ },
92
+ [
93
+ createBlockNoteExtension({
94
+ key: "numbered-list-item-shortcuts",
95
+ inputRules: [
96
+ {
97
+ find: new RegExp(`^(\\d+)\\.\\s$`),
98
+ replace({ match }) {
99
+ const start = parseInt(match[1]);
100
+ return {
101
+ type: "numberedListItem",
102
+ props: {
103
+ start: start !== 1 ? start : undefined,
104
+ },
105
+ };
106
+ },
107
+ },
108
+ ],
109
+ keyboardShortcuts: {
110
+ Enter: ({ editor }) => {
111
+ return handleEnter(editor, "numberedListItem");
112
+ },
113
+ "Mod-Shift-7": ({ editor }) => {
114
+ const cursorPosition = editor.getTextCursorPosition();
115
+
116
+ if (
117
+ editor.schema.blockSchema[cursorPosition.block.type].content !==
118
+ "inline"
119
+ ) {
120
+ return false;
121
+ }
122
+
123
+ editor.updateBlock(cursorPosition.block, {
124
+ type: "numberedListItem",
125
+ props: {},
126
+ });
127
+ return true;
128
+ },
129
+ },
130
+ plugins: [NumberedListIndexingDecorationPlugin()],
131
+ }),
132
+ ],
133
+ );
@@ -0,0 +1,78 @@
1
+ import { createBlockNoteExtension } from "../../../editor/BlockNoteExtension.js";
2
+ import { createBlockConfig, createBlockSpec } from "../../../schema/index.js";
3
+ import {
4
+ addDefaultPropsExternalHTML,
5
+ defaultProps,
6
+ } from "../../defaultProps.js";
7
+ import { createToggleWrapper } from "../../ToggleWrapper/createToggleWrapper.js";
8
+ import { handleEnter } from "../../utils/listItemEnterHandler.js";
9
+
10
+ export type ToggleListItemBlockConfig = ReturnType<
11
+ typeof createToggleListItemBlockConfig
12
+ >;
13
+
14
+ export const createToggleListItemBlockConfig = createBlockConfig(
15
+ () =>
16
+ ({
17
+ type: "toggleListItem" as const,
18
+ propSchema: {
19
+ ...defaultProps,
20
+ },
21
+ content: "inline" as const,
22
+ }) as const,
23
+ );
24
+
25
+ export const createToggleListItemBlockSpec = createBlockSpec(
26
+ createToggleListItemBlockConfig,
27
+ {
28
+ meta: {
29
+ isolating: false,
30
+ },
31
+ render(block, editor) {
32
+ const paragraphEl = document.createElement("p");
33
+ const toggleWrapper = createToggleWrapper(
34
+ block as any,
35
+ editor,
36
+ paragraphEl,
37
+ );
38
+ return { ...toggleWrapper, contentDOM: paragraphEl };
39
+ },
40
+ toExternalHTML(block) {
41
+ const li = document.createElement("li");
42
+ const p = document.createElement("p");
43
+ addDefaultPropsExternalHTML(block.props, li);
44
+ li.appendChild(p);
45
+
46
+ return {
47
+ dom: li,
48
+ contentDOM: p,
49
+ };
50
+ },
51
+ },
52
+ [
53
+ createBlockNoteExtension({
54
+ key: "toggle-list-item-shortcuts",
55
+ keyboardShortcuts: {
56
+ Enter: ({ editor }) => {
57
+ return handleEnter(editor, "toggleListItem");
58
+ },
59
+ "Mod-Shift-6": ({ editor }) => {
60
+ const cursorPosition = editor.getTextCursorPosition();
61
+
62
+ if (
63
+ editor.schema.blockSchema[cursorPosition.block.type].content !==
64
+ "inline"
65
+ ) {
66
+ return false;
67
+ }
68
+
69
+ editor.updateBlock(cursorPosition.block, {
70
+ type: "toggleListItem",
71
+ props: {},
72
+ });
73
+ return true;
74
+ },
75
+ },
76
+ }),
77
+ ],
78
+ );
@@ -0,0 +1,72 @@
1
+ import {
2
+ BlockSchema,
3
+ createBlockConfig,
4
+ createBlockSpec,
5
+ InlineContentSchema,
6
+ StyleSchema,
7
+ } from "../../schema/index.js";
8
+ import { BlockNoteSchema } from "../BlockNoteSchema.js";
9
+
10
+ export type PageBreakBlockConfig = ReturnType<
11
+ typeof createPageBreakBlockConfig
12
+ >;
13
+
14
+ export const createPageBreakBlockConfig = createBlockConfig(
15
+ () =>
16
+ ({
17
+ type: "pageBreak" as const,
18
+ propSchema: {},
19
+ content: "none",
20
+ }) as const,
21
+ );
22
+
23
+ export const createPageBreakBlockSpec = createBlockSpec(
24
+ createPageBreakBlockConfig,
25
+ {
26
+ parse(element) {
27
+ if (
28
+ element.tagName === "DIV" &&
29
+ element.hasAttribute("data-page-break")
30
+ ) {
31
+ return {};
32
+ }
33
+
34
+ return undefined;
35
+ },
36
+ render() {
37
+ const pageBreak = document.createElement("div");
38
+
39
+ pageBreak.setAttribute("data-page-break", "");
40
+
41
+ return {
42
+ dom: pageBreak,
43
+ };
44
+ },
45
+ toExternalHTML() {
46
+ const pageBreak = document.createElement("div");
47
+
48
+ pageBreak.setAttribute("data-page-break", "");
49
+
50
+ return {
51
+ dom: pageBreak,
52
+ };
53
+ },
54
+ },
55
+ );
56
+
57
+ /**
58
+ * Adds page break support to the given schema.
59
+ */
60
+ export const withPageBreak = <
61
+ B extends BlockSchema,
62
+ I extends InlineContentSchema,
63
+ S extends StyleSchema,
64
+ >(
65
+ schema: BlockNoteSchema<B, I, S>,
66
+ ) => {
67
+ return schema.extend({
68
+ blockSpecs: {
69
+ pageBreak: createPageBreakBlockSpec(),
70
+ },
71
+ });
72
+ };
@@ -6,19 +6,21 @@ import {
6
6
  InlineContentSchema,
7
7
  StyleSchema,
8
8
  } from "../../schema/index.js";
9
- import { pageBreakSchema } from "./schema.js";
9
+ import { createPageBreakBlockConfig } from "./block.js";
10
10
 
11
11
  export function checkPageBreakBlocksInSchema<
12
12
  I extends InlineContentSchema,
13
13
  S extends StyleSchema,
14
14
  >(
15
15
  editor: BlockNoteEditor<any, I, S>,
16
- ): editor is BlockNoteEditor<typeof pageBreakSchema.blockSchema, I, S> {
17
- return (
18
- "pageBreak" in editor.schema.blockSchema &&
19
- editor.schema.blockSchema["pageBreak"] ===
20
- pageBreakSchema.blockSchema["pageBreak"]
21
- );
16
+ ): editor is BlockNoteEditor<
17
+ {
18
+ pageBreak: ReturnType<typeof createPageBreakBlockConfig>;
19
+ },
20
+ I,
21
+ S
22
+ > {
23
+ return "pageBreak" in editor.schema.blockSchema;
22
24
  }
23
25
 
24
26
  export function getPageBreakSlashMenuItems<