@blocknote/core 0.14.5 → 0.15.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 (60) hide show
  1. package/dist/blocknote.js +1219 -1005
  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/webpack-stats.json +1 -1
  6. package/package.json +26 -23
  7. package/src/api/blockManipulation/blockManipulation.ts +21 -21
  8. package/src/api/exporters/copyExtension.ts +14 -10
  9. package/src/api/exporters/html/externalHTMLExporter.ts +26 -8
  10. package/src/api/exporters/html/htmlConversion.test.ts +27 -25
  11. package/src/api/exporters/html/internalHTMLSerializer.ts +22 -7
  12. package/src/api/exporters/html/util/sharedHTMLConversion.ts +3 -2
  13. package/src/api/exporters/markdown/markdownExporter.ts +5 -4
  14. package/src/api/nodeConversions/nodeConversions.test.ts +9 -6
  15. package/src/api/parsers/html/parseHTML.test.ts +3 -4
  16. package/src/blocks/FileBlockContent/fileBlockHelpers.ts +1 -1
  17. package/src/blocks/defaultBlockHelpers.ts +3 -6
  18. package/src/blocks/defaultBlockTypeGuards.ts +26 -1
  19. package/src/editor/BlockNoteEditor.test.ts +48 -1
  20. package/src/editor/BlockNoteEditor.ts +153 -36
  21. package/src/editor/BlockNoteExtensions.ts +0 -1
  22. package/src/editor/BlockNoteTipTapEditor.ts +14 -5
  23. package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +10 -4
  24. package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +2 -2
  25. package/src/extensions/SideMenu/SideMenuPlugin.ts +7 -12
  26. package/src/extensions/SuggestionMenu/DefaultGridSuggestionItem.ts +4 -0
  27. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +2 -2
  28. package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +38 -0
  29. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +13 -6
  30. package/src/extensions/TableHandles/TableHandlesPlugin.ts +5 -5
  31. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +7 -3
  32. package/src/extensions/TextColor/TextColorExtension.ts +7 -3
  33. package/src/i18n/locales/ar.ts +6 -0
  34. package/src/i18n/locales/en.ts +18 -12
  35. package/src/i18n/locales/fr.ts +6 -0
  36. package/src/i18n/locales/is.ts +6 -0
  37. package/src/i18n/locales/ja.ts +6 -0
  38. package/src/i18n/locales/ko.ts +15 -0
  39. package/src/i18n/locales/nl.ts +11 -0
  40. package/src/i18n/locales/pl.ts +6 -0
  41. package/src/i18n/locales/pt.ts +6 -0
  42. package/src/i18n/locales/ru.ts +322 -309
  43. package/src/i18n/locales/vi.ts +13 -0
  44. package/src/i18n/locales/zh.ts +14 -0
  45. package/src/index.ts +14 -5
  46. package/src/style.css +2 -7
  47. package/types/src/api/exporters/html/externalHTMLExporter.d.ts +6 -2
  48. package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +6 -2
  49. package/types/src/api/exporters/html/util/sharedHTMLConversion.d.ts +3 -1
  50. package/types/src/api/exporters/markdown/markdownExporter.d.ts +4 -2
  51. package/types/src/blocks/defaultBlockTypeGuards.d.ts +4 -1
  52. package/types/src/editor/BlockNoteEditor.d.ts +71 -11
  53. package/types/src/editor/BlockNoteExtensions.d.ts +0 -1
  54. package/types/src/editor/BlockNoteTipTapEditor.d.ts +2 -2
  55. package/types/src/extensions/SuggestionMenu/DefaultGridSuggestionItem.d.ts +4 -0
  56. package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +1 -2
  57. package/types/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.d.ts +4 -0
  58. package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +1 -1
  59. package/types/src/i18n/locales/en.d.ts +6 -0
  60. package/types/src/index.d.ts +11 -5
@@ -0,0 +1,38 @@
1
+ import data, { Emoji, EmojiMartData } from "@emoji-mart/data";
2
+ import { init, SearchIndex } from "emoji-mart";
3
+
4
+ import { BlockSchema, InlineContentSchema, StyleSchema } from "../../schema";
5
+ import { BlockNoteEditor } from "../../editor/BlockNoteEditor";
6
+ import { checkDefaultInlineContentTypeInSchema } from "../../blocks/defaultBlockTypeGuards";
7
+ import { DefaultGridSuggestionItem } from "./DefaultGridSuggestionItem";
8
+
9
+ let dataInitialized = false;
10
+ const emojiMartData = data as EmojiMartData;
11
+
12
+ export async function getDefaultEmojiPickerItems<
13
+ BSchema extends BlockSchema,
14
+ I extends InlineContentSchema,
15
+ S extends StyleSchema
16
+ >(
17
+ editor: BlockNoteEditor<BSchema, I, S>,
18
+ query: string
19
+ ): Promise<DefaultGridSuggestionItem[]> {
20
+ if (!checkDefaultInlineContentTypeInSchema("text", editor)) {
21
+ return [];
22
+ }
23
+
24
+ if (!dataInitialized) {
25
+ dataInitialized = true;
26
+ await init({ emojiMartData });
27
+ }
28
+
29
+ const emojisToShow =
30
+ query.trim() === ""
31
+ ? Object.values(emojiMartData.emojis)
32
+ : ((await SearchIndex.search(query)) as Emoji[]);
33
+
34
+ return emojisToShow.map((emoji: Emoji) => ({
35
+ id: emoji.skins[0].native,
36
+ onItemClick: () => editor.insertInlineContent(emoji.skins[0].native + " "),
37
+ }));
38
+ }
@@ -1,11 +1,12 @@
1
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
2
1
  import { Block, PartialBlock } from "../../blocks/defaultBlocks";
2
+ import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
3
+
3
4
  import { checkDefaultBlockTypeInSchema } from "../../blocks/defaultBlockTypeGuards";
4
5
  import {
5
6
  BlockSchema,
6
7
  InlineContentSchema,
7
- isStyledTextInlineContent,
8
8
  StyleSchema,
9
+ isStyledTextInlineContent,
9
10
  } from "../../schema";
10
11
  import { formatKeyboardShortcut } from "../../util/browser";
11
12
  import { DefaultSuggestionItem } from "./DefaultSuggestionItem";
@@ -202,7 +203,7 @@ export function getDefaultSlashMenuItems<
202
203
  });
203
204
 
204
205
  // Immediately open the file toolbar
205
- editor.prosemirrorView.dispatch(
206
+ editor.dispatch(
206
207
  editor._tiptapEditor.state.tr.setMeta(editor.filePanel!.plugin, {
207
208
  block: insertedBlock,
208
209
  })
@@ -221,7 +222,7 @@ export function getDefaultSlashMenuItems<
221
222
  });
222
223
 
223
224
  // Immediately open the file toolbar
224
- editor.prosemirrorView.dispatch(
225
+ editor.dispatch(
225
226
  editor._tiptapEditor.state.tr.setMeta(editor.filePanel!.plugin, {
226
227
  block: insertedBlock,
227
228
  })
@@ -240,7 +241,7 @@ export function getDefaultSlashMenuItems<
240
241
  });
241
242
 
242
243
  // Immediately open the file toolbar
243
- editor.prosemirrorView.dispatch(
244
+ editor.dispatch(
244
245
  editor._tiptapEditor.state.tr.setMeta(editor.filePanel!.plugin, {
245
246
  block: insertedBlock,
246
247
  })
@@ -259,7 +260,7 @@ export function getDefaultSlashMenuItems<
259
260
  });
260
261
 
261
262
  // Immediately open the file toolbar
262
- editor.prosemirrorView.dispatch(
263
+ editor.dispatch(
263
264
  editor._tiptapEditor.state.tr.setMeta(editor.filePanel!.plugin, {
264
265
  block: insertedBlock,
265
266
  })
@@ -270,6 +271,12 @@ export function getDefaultSlashMenuItems<
270
271
  });
271
272
  }
272
273
 
274
+ items.push({
275
+ onItemClick: () => editor.openSelectionMenu(":"),
276
+ key: "emoji",
277
+ ...editor.dictionary.slash_menu.emoji,
278
+ });
279
+
273
280
  return items;
274
281
  }
275
282
 
@@ -1,6 +1,7 @@
1
1
  import { Plugin, PluginKey, PluginView } from "prosemirror-state";
2
2
  import { Decoration, DecorationSet, EditorView } from "prosemirror-view";
3
3
  import { nodeToBlock } from "../../api/nodeConversions/nodeConversions";
4
+ import { checkBlockIsDefaultType } from "../../blocks/defaultBlockTypeGuards";
4
5
  import { Block, DefaultBlockSchema } from "../../blocks/defaultBlocks";
5
6
  import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
6
7
  import {
@@ -9,7 +10,6 @@ import {
9
10
  InlineContentSchema,
10
11
  StyleSchema,
11
12
  } from "../../schema";
12
- import { checkBlockIsDefaultType } from "../../blocks/defaultBlockTypeGuards";
13
13
  import { EventEmitter } from "../../util/EventEmitter";
14
14
  import { getDraggableBlockFromElement } from "../SideMenu/SideMenuPlugin";
15
15
 
@@ -321,7 +321,7 @@ export class TableHandlesView<
321
321
  // Dispatches a dummy transaction to force a decorations update if
322
322
  // necessary.
323
323
  if (dispatchDecorationsTransaction) {
324
- this.pmView.dispatch(
324
+ this.editor.dispatch(
325
325
  this.pmView.state.tr.setMeta(tableHandlesPluginKey, true)
326
326
  );
327
327
  }
@@ -571,7 +571,7 @@ export class TableHandlesProsemirrorPlugin<
571
571
  };
572
572
  this.view!.emitUpdate();
573
573
 
574
- this.editor._tiptapEditor.view.dispatch(
574
+ this.editor.dispatch(
575
575
  this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, {
576
576
  draggedCellOrientation:
577
577
  this.view!.state.draggingState.draggedCellOrientation,
@@ -607,7 +607,7 @@ export class TableHandlesProsemirrorPlugin<
607
607
  };
608
608
  this.view!.emitUpdate();
609
609
 
610
- this.editor._tiptapEditor.view.dispatch(
610
+ this.editor.dispatch(
611
611
  this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, {
612
612
  draggedCellOrientation:
613
613
  this.view!.state.draggingState.draggedCellOrientation,
@@ -636,7 +636,7 @@ export class TableHandlesProsemirrorPlugin<
636
636
  this.view!.state.draggingState = undefined;
637
637
  this.view!.emitUpdate();
638
638
 
639
- this.editor._tiptapEditor.view.dispatch(
639
+ this.editor.dispatch(
640
640
  this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, null)
641
641
  );
642
642
 
@@ -21,10 +21,14 @@ export const TextAlignmentExtension = Extension.create({
21
21
  parseHTML: (element) => {
22
22
  return element.getAttribute("data-text-alignment");
23
23
  },
24
- renderHTML: (attributes) =>
25
- attributes.textAlignment !== "left" && {
24
+ renderHTML: (attributes) => {
25
+ if (attributes.textAlignment === "left") {
26
+ return {};
27
+ }
28
+ return {
26
29
  "data-text-alignment": attributes.textAlignment,
27
- },
30
+ };
31
+ },
28
32
  },
29
33
  },
30
34
  },
@@ -15,10 +15,14 @@ export const TextColorExtension = Extension.create({
15
15
  element.hasAttribute("data-text-color")
16
16
  ? element.getAttribute("data-text-color")
17
17
  : defaultProps.textColor.default,
18
- renderHTML: (attributes) =>
19
- attributes.textColor !== defaultProps.textColor.default && {
18
+ renderHTML: (attributes) => {
19
+ if (attributes.textColor === defaultProps.textColor.default) {
20
+ return {};
21
+ }
22
+ return {
20
23
  "data-text-color": attributes.textColor,
21
- },
24
+ };
25
+ },
22
26
  },
23
27
  },
24
28
  },
@@ -90,6 +90,12 @@ export const ar: Dictionary = {
90
90
  aliases: ["ملف", "تحميل", "تضمين", "وسائط", "رابط"],
91
91
  group: "وسائط",
92
92
  },
93
+ emoji: {
94
+ title: "الرموز التعبيرية",
95
+ subtext: "تُستخدم لإدراج رمز تعبيري",
96
+ aliases: ["رمز تعبيري", "إيموجي", "إيموت", "عاطفة", "وجه"],
97
+ group: "آخرون",
98
+ },
93
99
  },
94
100
  placeholders: {
95
101
  default: "أدخل نصًا أو اكتب '/' للأوامر",
@@ -2,37 +2,37 @@ export const en = {
2
2
  slash_menu: {
3
3
  heading: {
4
4
  title: "Heading 1",
5
- subtext: "Used for a top-level heading",
5
+ subtext: "Top-level heading",
6
6
  aliases: ["h", "heading1", "h1"],
7
7
  group: "Headings",
8
8
  },
9
9
  heading_2: {
10
10
  title: "Heading 2",
11
- subtext: "Used for key sections",
11
+ subtext: "Key section heading",
12
12
  aliases: ["h2", "heading2", "subheading"],
13
13
  group: "Headings",
14
14
  },
15
15
  heading_3: {
16
16
  title: "Heading 3",
17
- subtext: "Used for subsections and group headings",
17
+ subtext: "Subsection and group heading",
18
18
  aliases: ["h3", "heading3", "subheading"],
19
19
  group: "Headings",
20
20
  },
21
21
  numbered_list: {
22
22
  title: "Numbered List",
23
- subtext: "Used to display a numbered list",
23
+ subtext: "List with ordered items",
24
24
  aliases: ["ol", "li", "list", "numberedlist", "numbered list"],
25
25
  group: "Basic blocks",
26
26
  },
27
27
  bullet_list: {
28
28
  title: "Bullet List",
29
- subtext: "Used to display an unordered list",
29
+ subtext: "List with unordered items",
30
30
  aliases: ["ul", "li", "list", "bulletlist", "bullet list"],
31
31
  group: "Basic blocks",
32
32
  },
33
33
  check_list: {
34
34
  title: "Check List",
35
- subtext: "Used to display a list with checkboxes",
35
+ subtext: "List with checkboxes",
36
36
  aliases: [
37
37
  "ul",
38
38
  "li",
@@ -46,19 +46,19 @@ export const en = {
46
46
  },
47
47
  paragraph: {
48
48
  title: "Paragraph",
49
- subtext: "Used for the body of your document",
49
+ subtext: "The body of your document",
50
50
  aliases: ["p", "paragraph"],
51
51
  group: "Basic blocks",
52
52
  },
53
53
  table: {
54
54
  title: "Table",
55
- subtext: "Used for tables",
55
+ subtext: "Table with editable cells",
56
56
  aliases: ["table"],
57
57
  group: "Advanced",
58
58
  },
59
59
  image: {
60
60
  title: "Image",
61
- subtext: "Insert an image",
61
+ subtext: "Resizable image with caption",
62
62
  aliases: [
63
63
  "image",
64
64
  "imageUpload",
@@ -72,7 +72,7 @@ export const en = {
72
72
  },
73
73
  video: {
74
74
  title: "Video",
75
- subtext: "Insert a video",
75
+ subtext: "Resizable video with caption",
76
76
  aliases: [
77
77
  "video",
78
78
  "videoUpload",
@@ -86,7 +86,7 @@ export const en = {
86
86
  },
87
87
  audio: {
88
88
  title: "Audio",
89
- subtext: "Insert audio",
89
+ subtext: "Embedded audio with caption",
90
90
  aliases: [
91
91
  "audio",
92
92
  "audioUpload",
@@ -100,10 +100,16 @@ export const en = {
100
100
  },
101
101
  file: {
102
102
  title: "File",
103
- subtext: "Insert a file",
103
+ subtext: "Embedded file",
104
104
  aliases: ["file", "upload", "embed", "media", "url"],
105
105
  group: "Media",
106
106
  },
107
+ emoji: {
108
+ title: "Emoji",
109
+ subtext: "Search for and insert an emoji",
110
+ aliases: ["emoji", "emote", "emotion", "face"],
111
+ group: "Others",
112
+ },
107
113
  },
108
114
  placeholders: {
109
115
  default: "Enter text or type '/' for commands",
@@ -105,6 +105,12 @@ export const fr: Dictionary = {
105
105
  aliases: ["fichier", "téléverser", "intégrer", "média", "url"],
106
106
  group: "Média",
107
107
  },
108
+ emoji: {
109
+ title: "Emoji",
110
+ subtext: "Utilisé pour insérer un emoji",
111
+ aliases: ["emoji", "émoticône", "émotion", "visage"],
112
+ group: "Autres",
113
+ },
108
114
  },
109
115
  placeholders: {
110
116
  default: "Entrez du texte ou tapez '/' pour les commandes",
@@ -98,6 +98,12 @@ export const is: Dictionary = {
98
98
  aliases: ["skrá", "hlaða upp", "fella inn", "miðill", "url"],
99
99
  group: "Miðlar",
100
100
  },
101
+ emoji: {
102
+ title: "Emoji",
103
+ subtext: "Notað til að setja inn smámynd",
104
+ aliases: ["emoji", "andlitsávísun", "tilfinningar", "andlit"],
105
+ group: "Annað",
106
+ },
101
107
  },
102
108
  placeholders: {
103
109
  default: "Sláðu inn texta eða skrifaðu '/' fyrir skipanir",
@@ -125,6 +125,12 @@ export const ja: Dictionary = {
125
125
  aliases: ["file", "upload", "embed", "media", "url", "ファイル"],
126
126
  group: "メディア",
127
127
  },
128
+ emoji: {
129
+ title: "絵文字",
130
+ subtext: "絵文字を挿入するために使用します",
131
+ aliases: ["絵文字", "顔文字", "感情表現", "顔"],
132
+ group: "その他",
133
+ },
128
134
  },
129
135
  placeholders: {
130
136
  default: "テキストを入力するか'/' を入力してコマンド選択",
@@ -109,6 +109,21 @@ export const ko: Dictionary = {
109
109
  aliases: ["file", "upload", "embed", "media", "파일", "url"],
110
110
  group: "미디어",
111
111
  },
112
+ emoji: {
113
+ title: "이모지",
114
+ subtext: "이모지 삽입용으로 사용됩니다",
115
+ aliases: [
116
+ "이모지",
117
+ "emoji",
118
+ "감정 표현",
119
+ "emotion expression",
120
+ "표정",
121
+ "face expression",
122
+ "얼굴",
123
+ "face",
124
+ ],
125
+ group: "기타",
126
+ },
112
127
  },
113
128
  placeholders: {
114
129
  default: "텍스트를 입력하거나 /를 입력하여 명령을 입력하세요.",
@@ -100,6 +100,17 @@ export const nl: Dictionary = {
100
100
  aliases: ["bestand", "upload", "insluiten", "media", "url"],
101
101
  group: "Media",
102
102
  },
103
+ emoji: {
104
+ title: "Emoji",
105
+ subtext: "Gebruikt voor het invoegen van een emoji",
106
+ aliases: [
107
+ "emoji",
108
+ "emotie-uitdrukking",
109
+ "gezichtsuitdrukking",
110
+ "gezicht",
111
+ ],
112
+ group: "Overig",
113
+ },
103
114
  },
104
115
  placeholders: {
105
116
  default: "Voer tekst in of type '/' voor commando's",
@@ -90,6 +90,12 @@ export const pl: Dictionary = {
90
90
  aliases: ["plik", "wrzuć", "wstaw", "media", "url"],
91
91
  group: "Media",
92
92
  },
93
+ emoji: {
94
+ title: "Emoji",
95
+ subtext: "Używane do wstawiania emoji",
96
+ aliases: ["emoji", "emotka", "wyrażenie emocji", "twarz"],
97
+ group: "Inne",
98
+ },
93
99
  },
94
100
  placeholders: {
95
101
  default: "Wprowadź tekst lub wpisz '/' aby użyć poleceń",
@@ -97,6 +97,12 @@ export const pt: Dictionary = {
97
97
  aliases: ["arquivo", "upload", "incorporar", "mídia", "url"],
98
98
  group: "Mídia",
99
99
  },
100
+ emoji: {
101
+ title: "Emoji",
102
+ subtext: "Usado para inserir um emoji",
103
+ aliases: ["emoji", "emoticon", "expressão emocional", "rosto"],
104
+ group: "Outros",
105
+ },
100
106
  },
101
107
  placeholders: {
102
108
  default: "Digite texto ou use '/' para comandos",