@blocknote/core 0.26.0 → 0.27.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.
- package/dist/blocknote.cjs +11 -10
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +3685 -9960
- package/dist/blocknote.js.map +1 -1
- package/dist/comments.cjs.map +1 -1
- package/dist/comments.js.map +1 -1
- package/dist/en-B7ycW7c8.js +360 -0
- package/dist/en-B7ycW7c8.js.map +1 -0
- package/dist/en-D4taoCs4.cjs +2 -0
- package/dist/en-D4taoCs4.cjs.map +1 -0
- package/dist/locales.cjs +2 -0
- package/dist/locales.cjs.map +1 -0
- package/dist/locales.js +6129 -0
- package/dist/locales.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +36 -27
- package/src/api/clipboard/__snapshots__/internal/basicBlocks.html +1 -1
- package/src/api/clipboard/__snapshots__/internal/basicBlocksWithProps.html +1 -1
- package/src/api/clipboard/clipboardExternal.test.ts +1 -1
- package/src/api/clipboard/clipboardInternal.test.ts +1 -1
- package/src/api/clipboard/fromClipboard/acceptedMIMETypes.ts +1 -0
- package/src/api/clipboard/fromClipboard/pasteExtension.ts +96 -42
- package/src/api/exporters/html/__snapshots__/codeBlock/contains-newlines/external.html +1 -1
- package/src/api/exporters/html/__snapshots__/codeBlock/contains-newlines/internal.html +1 -1
- package/src/api/exporters/html/__snapshots__/codeBlock/defaultLanguage/external.html +1 -1
- package/src/api/exporters/html/__snapshots__/codeBlock/defaultLanguage/internal.html +1 -1
- package/src/api/exporters/html/__snapshots__/codeBlock/empty/external.html +1 -1
- package/src/api/exporters/html/__snapshots__/codeBlock/empty/internal.html +1 -1
- package/src/api/exporters/html/__snapshots__/codeBlock/python/external.html +1 -1
- package/src/api/exporters/html/__snapshots__/codeBlock/python/internal.html +1 -1
- package/src/api/exporters/html/htmlConversion.test.ts +2 -2
- package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +4 -4
- package/src/api/exporters/markdown/__snapshots__/codeBlock/defaultLanguage/markdown.md +1 -1
- package/src/api/exporters/markdown/__snapshots__/codeBlock/empty/markdown.md +1 -1
- package/src/api/exporters/markdown/__snapshots__/complex/misc/markdown.md +1 -1
- package/src/api/exporters/markdown/__snapshots__/lists/basic/markdown.md +8 -6
- package/src/api/exporters/markdown/__snapshots__/lists/nested/markdown.md +6 -6
- package/src/api/exporters/markdown/markdownExporter.test.ts +2 -2
- package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +2 -2
- package/src/api/parsers/html/__snapshots__/parse-codeblocks.json +1 -1
- package/src/api/parsers/html/parseHTML.test.ts +1 -1
- package/src/api/parsers/markdown/__snapshots__/pasted/whitespace bold.json +42 -0
- package/src/api/parsers/markdown/__snapshots__/whitespace bold.json +19 -0
- package/src/api/parsers/markdown/detectMarkdown.ts +60 -0
- package/src/api/parsers/markdown/parseMarkdown.test.ts +7 -2
- package/src/api/parsers/markdown/parseMarkdown.ts +19 -18
- package/src/api/testUtil/cases/defaultSchema.ts +13 -0
- package/src/blocks/CodeBlockContent/CodeBlockContent.ts +100 -69
- package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +98 -0
- package/src/blocks/TableBlockContent/TableExtension.ts +1 -1
- package/src/blocks/defaultBlocks.ts +2 -2
- package/src/editor/Block.css +13 -0
- package/src/editor/BlockNoteEditor.ts +102 -10
- package/src/editor/BlockNoteExtensions.ts +18 -4
- package/src/extensions/Comments/CommentsPlugin.ts +1 -1
- package/src/extensions/HardBreak/HardBreak.ts +35 -0
- package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +100 -3
- package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +3 -1
- package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +12 -0
- package/src/i18n/index.ts +2 -0
- package/src/i18n/locales/ar.ts +6 -0
- package/src/i18n/locales/de.ts +6 -0
- package/src/i18n/locales/en.ts +6 -0
- package/src/i18n/locales/es.ts +6 -0
- package/src/i18n/locales/fr.ts +6 -0
- package/src/i18n/locales/hr.ts +6 -0
- package/src/i18n/locales/is.ts +6 -0
- package/src/i18n/locales/it.ts +6 -0
- package/src/i18n/locales/ja.ts +6 -0
- package/src/i18n/locales/ko.ts +6 -0
- package/src/i18n/locales/nl.ts +6 -0
- package/src/i18n/locales/no.ts +6 -0
- package/src/i18n/locales/pl.ts +6 -0
- package/src/i18n/locales/pt.ts +6 -0
- package/src/i18n/locales/ru.ts +6 -0
- package/src/i18n/locales/uk.ts +6 -0
- package/src/i18n/locales/vi.ts +6 -0
- package/src/i18n/locales/zh.ts +6 -0
- package/src/index.ts +2 -3
- package/src/locales.ts +1 -0
- package/src/schema/blocks/types.ts +1 -0
- package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.d.ts +1 -1
- package/types/src/api/blockManipulation/setupTestEnv.d.ts +34 -2
- package/types/src/api/clipboard/fromClipboard/acceptedMIMETypes.d.ts +1 -1
- package/types/src/api/clipboard/fromClipboard/fileDropExtension.d.ts +2 -2
- package/types/src/api/clipboard/fromClipboard/pasteExtension.d.ts +3 -3
- package/types/src/api/clipboard/testUtil.d.ts +66 -34
- package/types/src/api/clipboard/toClipboard/copyExtension.d.ts +1 -1
- package/types/src/api/exporters/html/externalHTMLExporter.d.ts +2 -2
- package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +2 -2
- package/types/src/api/exporters/html/util/serializeBlocksExternalHTML.d.ts +1 -1
- package/types/src/api/exporters/html/util/serializeBlocksInternalHTML.d.ts +1 -1
- package/types/src/api/parsers/markdown/detectMarkdown.d.ts +6 -0
- package/types/src/api/parsers/markdown/parseMarkdown.d.ts +1 -0
- package/types/src/api/testUtil/cases/customBlocks.d.ts +72 -40
- package/types/src/api/testUtil/cases/customInlineContent.d.ts +34 -2
- package/types/src/api/testUtil/cases/customStyles.d.ts +34 -2
- package/types/src/blocks/AudioBlockContent/AudioBlockContent.d.ts +3 -3
- package/types/src/blocks/CodeBlockContent/CodeBlockContent.d.ts +46 -34
- package/types/src/blocks/FileBlockContent/FileBlockContent.d.ts +3 -3
- package/types/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.d.ts +1 -1
- package/types/src/blocks/HeadingBlockContent/HeadingBlockContent.d.ts +2 -2
- package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +2 -2
- package/types/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +2 -2
- package/types/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.d.ts +2 -2
- package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +2 -2
- package/types/src/blocks/PageBreakBlockContent/PageBreakBlockContent.d.ts +2 -2
- package/types/src/blocks/PageBreakBlockContent/schema.d.ts +13 -13
- package/types/src/blocks/ParagraphBlockContent/ParagraphBlockContent.d.ts +2 -2
- package/types/src/blocks/QuoteBlockContent/QuoteBlockContent.d.ts +52 -0
- package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +2 -2
- package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +2 -2
- package/types/src/blocks/defaultBlockHelpers.d.ts +2 -2
- package/types/src/blocks/defaultBlocks.d.ts +107 -44
- package/types/src/comments/threadstore/yjs/YjsThreadStore.d.ts +3 -3
- package/types/src/editor/BlockNoteEditor.d.ts +58 -0
- package/types/src/editor/BlockNoteExtensions.d.ts +3 -2
- package/types/src/exporter/mapping.d.ts +2 -2
- package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +1 -1
- package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +1 -1
- package/types/src/extensions/HardBreak/HardBreak.d.ts +2 -0
- package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +4 -4
- package/types/src/extensions/TextColor/TextColorMark.d.ts +1 -1
- package/types/src/i18n/index.d.ts +2 -0
- package/types/src/i18n/locales/en.d.ts +7 -1
- package/types/src/index.d.ts +1 -2
- package/types/src/locales.d.ts +1 -0
- package/types/src/pm-nodes/BlockContainer.d.ts +2 -7
- package/types/src/pm-nodes/BlockGroup.d.ts +2 -7
- package/types/src/schema/blocks/types.d.ts +1 -0
- package/types/src/schema/inlineContent/internal.d.ts +1 -1
- package/README.md +0 -125
- package/src/blocks/CodeBlockContent/defaultSupportedLanguages.ts +0 -116
- package/types/src/extensions/Comments/threadstore/DefaultThreadStoreAuth.d.ts +0 -47
- package/types/src/extensions/Comments/threadstore/ThreadStore.d.ts +0 -121
- package/types/src/extensions/Comments/threadstore/ThreadStoreAuth.d.ts +0 -12
- package/types/src/extensions/Comments/threadstore/TipTapThreadStore.d.ts +0 -97
- package/types/src/extensions/Comments/threadstore/yjs/RESTYjsThreadStore.d.ts +0 -83
- package/types/src/extensions/Comments/threadstore/yjs/YjsThreadStore.d.ts +0 -79
- package/types/src/extensions/Comments/threadstore/yjs/YjsThreadStore.test.d.ts +0 -1
- package/types/src/extensions/Comments/threadstore/yjs/YjsThreadStoreBase.d.ts +0 -15
- package/types/src/extensions/Comments/threadstore/yjs/yjsHelpers.d.ts +0 -13
- package/types/src/extensions/Comments/types.d.ts +0 -109
- package/types/src/models/User.d.ts +0 -5
package/src/editor/Block.css
CHANGED
|
@@ -37,6 +37,10 @@ BASIC STYLES
|
|
|
37
37
|
outline: 4px solid rgb(100, 160, 255);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
.bn-inline-content {
|
|
41
|
+
width: 100%;
|
|
42
|
+
}
|
|
43
|
+
|
|
40
44
|
/*
|
|
41
45
|
NESTED BLOCKS
|
|
42
46
|
*/
|
|
@@ -146,6 +150,14 @@ NESTED BLOCKS
|
|
|
146
150
|
font-weight: bold;
|
|
147
151
|
}
|
|
148
152
|
|
|
153
|
+
/* QUOTES */
|
|
154
|
+
[data-content-type="quote"] blockquote {
|
|
155
|
+
border-left: 2px solid rgb(125, 121, 122);
|
|
156
|
+
color: rgb(125, 121, 122);
|
|
157
|
+
margin: 0;
|
|
158
|
+
padding-left: 1em;
|
|
159
|
+
}
|
|
160
|
+
|
|
149
161
|
/* LISTS */
|
|
150
162
|
|
|
151
163
|
.bn-block-content::before {
|
|
@@ -188,6 +200,7 @@ NESTED BLOCKS
|
|
|
188
200
|
/* Checked */
|
|
189
201
|
.bn-block-content[data-content-type="checkListItem"] > div {
|
|
190
202
|
display: flex;
|
|
203
|
+
width: 100%;
|
|
191
204
|
}
|
|
192
205
|
|
|
193
206
|
.bn-block-content[data-content-type="checkListItem"] > div > div > input {
|
|
@@ -43,7 +43,10 @@ import {
|
|
|
43
43
|
import { createExternalHTMLExporter } from "../api/exporters/html/externalHTMLExporter.js";
|
|
44
44
|
import { blocksToMarkdown } from "../api/exporters/markdown/markdownExporter.js";
|
|
45
45
|
import { HTMLToBlocks } from "../api/parsers/html/parseHTML.js";
|
|
46
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
markdownToBlocks,
|
|
48
|
+
markdownToHTML,
|
|
49
|
+
} from "../api/parsers/markdown/parseMarkdown.js";
|
|
47
50
|
import {
|
|
48
51
|
Block,
|
|
49
52
|
DefaultBlockSchema,
|
|
@@ -91,7 +94,7 @@ import {
|
|
|
91
94
|
import { Dictionary } from "../i18n/dictionary.js";
|
|
92
95
|
import { en } from "../i18n/locales/index.js";
|
|
93
96
|
|
|
94
|
-
import { Plugin, Transaction } from "@tiptap/pm/state";
|
|
97
|
+
import { Plugin, TextSelection, Transaction } from "@tiptap/pm/state";
|
|
95
98
|
import { dropCursor } from "prosemirror-dropcursor";
|
|
96
99
|
import { EditorView } from "prosemirror-view";
|
|
97
100
|
import { ySyncPluginKey } from "y-prosemirror";
|
|
@@ -101,6 +104,8 @@ import { nodeToBlock } from "../api/nodeConversions/nodeToBlock.js";
|
|
|
101
104
|
import type { ThreadStore, User } from "../comments/index.js";
|
|
102
105
|
import "../style.css";
|
|
103
106
|
import { EventEmitter } from "../util/EventEmitter.js";
|
|
107
|
+
import { CodeBlockOptions } from "../blocks/CodeBlockContent/CodeBlockContent.js";
|
|
108
|
+
import { nestedListsToBlockNoteStructure } from "../api/parsers/html/util/nestedLists.js";
|
|
104
109
|
|
|
105
110
|
export type BlockNoteExtensionFactory = (
|
|
106
111
|
editor: BlockNoteEditor<any, any, any>
|
|
@@ -156,6 +161,11 @@ export type BlockNoteEditorOptions<
|
|
|
156
161
|
showCursorLabels?: "always" | "activity";
|
|
157
162
|
};
|
|
158
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Options for code blocks.
|
|
166
|
+
*/
|
|
167
|
+
codeBlock?: CodeBlockOptions;
|
|
168
|
+
|
|
159
169
|
comments: {
|
|
160
170
|
threadStore: ThreadStore;
|
|
161
171
|
};
|
|
@@ -212,6 +222,39 @@ export type BlockNoteEditorOptions<
|
|
|
212
222
|
string | undefined
|
|
213
223
|
>;
|
|
214
224
|
|
|
225
|
+
/**
|
|
226
|
+
* Custom paste handler that can be used to override the default paste behavior.
|
|
227
|
+
* @returns The function should return `true` if the paste event was handled, otherwise it should return `false` if it should be canceled or `undefined` if it should be handled by another handler.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```ts
|
|
231
|
+
* pasteHandler: ({ defaultPasteHandler }) => {
|
|
232
|
+
* return defaultPasteHandler({ pasteBehavior: "prefer-html" });
|
|
233
|
+
* }
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
pasteHandler?: (context: {
|
|
237
|
+
event: ClipboardEvent;
|
|
238
|
+
editor: BlockNoteEditor<BSchema, ISchema, SSchema>;
|
|
239
|
+
/**
|
|
240
|
+
* The default paste handler
|
|
241
|
+
* @param context The context object
|
|
242
|
+
* @returns Whether the paste event was handled or not
|
|
243
|
+
*/
|
|
244
|
+
defaultPasteHandler: (context?: {
|
|
245
|
+
/**
|
|
246
|
+
* Whether to prioritize Markdown content in `text/plain` over `text/html` when pasting from the clipboard.
|
|
247
|
+
* @default true
|
|
248
|
+
*/
|
|
249
|
+
prioritizeMarkdownOverHTML?: boolean;
|
|
250
|
+
/**
|
|
251
|
+
* Whether to parse `text/plain` content from the clipboard as Markdown content.
|
|
252
|
+
* @default true
|
|
253
|
+
*/
|
|
254
|
+
plainTextAsMarkdown?: boolean;
|
|
255
|
+
}) => boolean | undefined;
|
|
256
|
+
}) => boolean | undefined;
|
|
257
|
+
|
|
215
258
|
/**
|
|
216
259
|
* Resolve a URL of a file block to one that can be displayed or downloaded. This can be used for creating authenticated URL or
|
|
217
260
|
* implementing custom protocols / schemes
|
|
@@ -442,6 +485,7 @@ export class BlockNoteEditor<
|
|
|
442
485
|
cellTextColor: boolean;
|
|
443
486
|
headers: boolean;
|
|
444
487
|
};
|
|
488
|
+
codeBlock: CodeBlockOptions;
|
|
445
489
|
};
|
|
446
490
|
|
|
447
491
|
public static create<
|
|
@@ -489,6 +533,12 @@ export class BlockNoteEditor<
|
|
|
489
533
|
cellTextColor: options?.tables?.cellTextColor ?? false,
|
|
490
534
|
headers: options?.tables?.headers ?? false,
|
|
491
535
|
},
|
|
536
|
+
codeBlock: {
|
|
537
|
+
indentLineWithTab: options?.codeBlock?.indentLineWithTab ?? true,
|
|
538
|
+
defaultLanguage: options?.codeBlock?.defaultLanguage ?? "text",
|
|
539
|
+
supportedLanguages: options?.codeBlock?.supportedLanguages ?? {},
|
|
540
|
+
createHighlighter: options?.codeBlock?.createHighlighter ?? undefined,
|
|
541
|
+
},
|
|
492
542
|
};
|
|
493
543
|
|
|
494
544
|
// apply defaults
|
|
@@ -532,6 +582,7 @@ export class BlockNoteEditor<
|
|
|
532
582
|
tabBehavior: newOptions.tabBehavior,
|
|
533
583
|
sideMenuDetection: newOptions.sideMenuDetection || "viewport",
|
|
534
584
|
comments: newOptions.comments,
|
|
585
|
+
pasteHandler: newOptions.pasteHandler,
|
|
535
586
|
});
|
|
536
587
|
|
|
537
588
|
// add extensions from _tiptapOptions
|
|
@@ -1136,17 +1187,18 @@ export class BlockNoteEditor<
|
|
|
1136
1187
|
}
|
|
1137
1188
|
|
|
1138
1189
|
const { from, to } = this._tiptapEditor.state.selection;
|
|
1139
|
-
|
|
1140
|
-
if (!text) {
|
|
1141
|
-
text = this._tiptapEditor.state.doc.textBetween(from, to);
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
1190
|
const mark = this.pmSchema.mark("link", { href: url });
|
|
1145
1191
|
|
|
1146
1192
|
this.dispatch(
|
|
1147
|
-
|
|
1148
|
-
.
|
|
1149
|
-
|
|
1193
|
+
text
|
|
1194
|
+
? this._tiptapEditor.state.tr
|
|
1195
|
+
.insertText(text, from, to)
|
|
1196
|
+
.addMark(from, from + text.length, mark)
|
|
1197
|
+
: this._tiptapEditor.state.tr
|
|
1198
|
+
.setSelection(
|
|
1199
|
+
TextSelection.create(this._tiptapEditor.state.tr.doc, to)
|
|
1200
|
+
)
|
|
1201
|
+
.addMark(from, to, mark)
|
|
1150
1202
|
);
|
|
1151
1203
|
}
|
|
1152
1204
|
|
|
@@ -1431,4 +1483,44 @@ export class BlockNoteEditor<
|
|
|
1431
1483
|
public setForceSelectionVisible(forceSelectionVisible: boolean) {
|
|
1432
1484
|
this.showSelectionPlugin.setEnabled(forceSelectionVisible);
|
|
1433
1485
|
}
|
|
1486
|
+
|
|
1487
|
+
/**
|
|
1488
|
+
* This will convert HTML into a format that is compatible with BlockNote.
|
|
1489
|
+
*/
|
|
1490
|
+
private convertHtmlToBlockNoteHtml(html: string) {
|
|
1491
|
+
const htmlNode = nestedListsToBlockNoteStructure(html.trim());
|
|
1492
|
+
return htmlNode.innerHTML;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
/**
|
|
1496
|
+
* Paste HTML into the editor. Defaults to converting HTML to BlockNote HTML.
|
|
1497
|
+
* @param html The HTML to paste.
|
|
1498
|
+
* @param raw Whether to paste the HTML as is, or to convert it to BlockNote HTML.
|
|
1499
|
+
*/
|
|
1500
|
+
public pasteHTML(html: string, raw = false) {
|
|
1501
|
+
let htmlToPaste = html;
|
|
1502
|
+
if (!raw) {
|
|
1503
|
+
htmlToPaste = this.convertHtmlToBlockNoteHtml(html);
|
|
1504
|
+
}
|
|
1505
|
+
if (!htmlToPaste) {
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
this.prosemirrorView?.pasteHTML(htmlToPaste);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
/**
|
|
1512
|
+
* Paste text into the editor. Defaults to interpreting text as markdown.
|
|
1513
|
+
* @param text The text to paste.
|
|
1514
|
+
*/
|
|
1515
|
+
public pasteText(text: string) {
|
|
1516
|
+
return this.prosemirrorView?.pasteText(text);
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
/**
|
|
1520
|
+
* Paste markdown into the editor.
|
|
1521
|
+
* @param markdown The markdown to paste.
|
|
1522
|
+
*/
|
|
1523
|
+
public async pasteMarkdown(markdown: string) {
|
|
1524
|
+
return this.pasteHTML(await markdownToHTML(markdown));
|
|
1525
|
+
}
|
|
1434
1526
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { AnyExtension, Extension, extensions } from "@tiptap/core";
|
|
2
2
|
import { Gapcursor } from "@tiptap/extension-gapcursor";
|
|
3
|
-
import { HardBreak } from "@tiptap/extension-hard-break";
|
|
4
3
|
import { History } from "@tiptap/extension-history";
|
|
5
4
|
import { Link } from "@tiptap/extension-link";
|
|
6
5
|
import { Text } from "@tiptap/extension-text";
|
|
@@ -17,6 +16,7 @@ import { CommentsPlugin } from "../extensions/Comments/CommentsPlugin.js";
|
|
|
17
16
|
import type { ThreadStore } from "../comments/index.js";
|
|
18
17
|
import { FilePanelProsemirrorPlugin } from "../extensions/FilePanel/FilePanelPlugin.js";
|
|
19
18
|
import { FormattingToolbarProsemirrorPlugin } from "../extensions/FormattingToolbar/FormattingToolbarPlugin.js";
|
|
19
|
+
import { HardBreak } from "../extensions/HardBreak/HardBreak.js";
|
|
20
20
|
import { KeyboardShortcutsExtension } from "../extensions/KeyboardShortcuts/KeyboardShortcutsExtension.js";
|
|
21
21
|
import { LinkToolbarProsemirrorPlugin } from "../extensions/LinkToolbar/LinkToolbarPlugin.js";
|
|
22
22
|
import {
|
|
@@ -44,7 +44,11 @@ import {
|
|
|
44
44
|
StyleSchema,
|
|
45
45
|
StyleSpecs,
|
|
46
46
|
} from "../schema/index.js";
|
|
47
|
-
import type {
|
|
47
|
+
import type {
|
|
48
|
+
BlockNoteEditor,
|
|
49
|
+
BlockNoteEditorOptions,
|
|
50
|
+
BlockNoteExtension,
|
|
51
|
+
} from "./BlockNoteEditor.js";
|
|
48
52
|
|
|
49
53
|
type ExtensionOptions<
|
|
50
54
|
BSchema extends BlockSchema,
|
|
@@ -82,6 +86,7 @@ type ExtensionOptions<
|
|
|
82
86
|
comments?: {
|
|
83
87
|
threadStore: ThreadStore;
|
|
84
88
|
};
|
|
89
|
+
pasteHandler: BlockNoteEditorOptions<any, any, any>["pasteHandler"];
|
|
85
90
|
};
|
|
86
91
|
|
|
87
92
|
/**
|
|
@@ -179,7 +184,7 @@ const getTipTapExtensions = <
|
|
|
179
184
|
types: ["blockContainer", "columnList", "column"],
|
|
180
185
|
setIdAttribute: opts.setIdAttribute,
|
|
181
186
|
}),
|
|
182
|
-
HardBreak
|
|
187
|
+
HardBreak,
|
|
183
188
|
// Comments,
|
|
184
189
|
|
|
185
190
|
// basics:
|
|
@@ -258,7 +263,16 @@ const getTipTapExtensions = <
|
|
|
258
263
|
];
|
|
259
264
|
}),
|
|
260
265
|
createCopyToClipboardExtension(opts.editor),
|
|
261
|
-
createPasteFromClipboardExtension(
|
|
266
|
+
createPasteFromClipboardExtension(
|
|
267
|
+
opts.editor,
|
|
268
|
+
opts.pasteHandler ||
|
|
269
|
+
((context: {
|
|
270
|
+
defaultPasteHandler: (context?: {
|
|
271
|
+
prioritizeMarkdownOverHTML?: boolean;
|
|
272
|
+
plainTextAsMarkdown?: boolean;
|
|
273
|
+
}) => boolean | undefined;
|
|
274
|
+
}) => context.defaultPasteHandler())
|
|
275
|
+
),
|
|
262
276
|
createDropFileExtension(opts.editor),
|
|
263
277
|
|
|
264
278
|
// This needs to be at the bottom of this list, because Key events (such as enter, when selecting a /command),
|
|
@@ -106,7 +106,7 @@ export class CommentsPlugin extends EventEmitter<any> {
|
|
|
106
106
|
pos + node.nodeSize,
|
|
107
107
|
ttEditor.state.doc.content.size - 1
|
|
108
108
|
);
|
|
109
|
-
tr.removeMark(trimmedFrom, trimmedTo,
|
|
109
|
+
tr.removeMark(trimmedFrom, trimmedTo, mark);
|
|
110
110
|
tr.addMark(
|
|
111
111
|
trimmedFrom,
|
|
112
112
|
trimmedTo,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Stripped down version of the TipTap HardBreak extension:
|
|
2
|
+
// https://github.com/ueberdosis/tiptap/blob/f3258d9ee5fb7979102fe63434f6ea4120507311/packages/extension-hard-break/src/hard-break.ts#L80
|
|
3
|
+
// Changes:
|
|
4
|
+
// - Removed options
|
|
5
|
+
// - Removed keyboard shortcuts & moved them to the `KeyboardShortcutsExtension`
|
|
6
|
+
// - Removed `setHardBreak` command (added a simpler version in the Shift+Enter
|
|
7
|
+
// handler in `KeyboardShortcutsExtension`).
|
|
8
|
+
// - Added priority
|
|
9
|
+
import { mergeAttributes, Node } from "@tiptap/core";
|
|
10
|
+
|
|
11
|
+
export const HardBreak = Node.create({
|
|
12
|
+
name: "hardBreak",
|
|
13
|
+
|
|
14
|
+
inline: true,
|
|
15
|
+
|
|
16
|
+
group: "inline",
|
|
17
|
+
|
|
18
|
+
selectable: false,
|
|
19
|
+
|
|
20
|
+
linebreakReplacement: true,
|
|
21
|
+
|
|
22
|
+
priority: 10,
|
|
23
|
+
|
|
24
|
+
parseHTML() {
|
|
25
|
+
return [{ tag: "br" }];
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
renderHTML({ HTMLAttributes }) {
|
|
29
|
+
return ["br", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
renderText() {
|
|
33
|
+
return "\n";
|
|
34
|
+
},
|
|
35
|
+
});
|
|
@@ -260,6 +260,73 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
260
260
|
|
|
261
261
|
return true;
|
|
262
262
|
}),
|
|
263
|
+
// Deletes the current block if it's an empty block with inline content,
|
|
264
|
+
// and moves the selection to the previous block.
|
|
265
|
+
() =>
|
|
266
|
+
commands.command(({ state }) => {
|
|
267
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
268
|
+
if (!blockInfo.isBlockContainer) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const blockEmpty =
|
|
273
|
+
blockInfo.blockContent.node.childCount === 0 &&
|
|
274
|
+
blockInfo.blockContent.node.type.spec.content === "inline*";
|
|
275
|
+
|
|
276
|
+
if (blockEmpty) {
|
|
277
|
+
const prevBlockInfo = getPrevBlockInfo(
|
|
278
|
+
state.doc,
|
|
279
|
+
blockInfo.bnBlock.beforePos
|
|
280
|
+
);
|
|
281
|
+
if (!prevBlockInfo || !prevBlockInfo.isBlockContainer) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
let chainedCommands = chain();
|
|
286
|
+
|
|
287
|
+
if (
|
|
288
|
+
prevBlockInfo.blockContent.node.type.spec.content ===
|
|
289
|
+
"tableRow+"
|
|
290
|
+
) {
|
|
291
|
+
const tableBlockEndPos = blockInfo.bnBlock.beforePos - 1;
|
|
292
|
+
const tableBlockContentEndPos = tableBlockEndPos - 1;
|
|
293
|
+
const lastRowEndPos = tableBlockContentEndPos - 1;
|
|
294
|
+
const lastCellEndPos = lastRowEndPos - 1;
|
|
295
|
+
const lastCellParagraphEndPos = lastCellEndPos - 1;
|
|
296
|
+
|
|
297
|
+
chainedCommands = chainedCommands.setTextSelection(
|
|
298
|
+
lastCellParagraphEndPos
|
|
299
|
+
);
|
|
300
|
+
} else if (
|
|
301
|
+
prevBlockInfo.blockContent.node.type.spec.content === ""
|
|
302
|
+
) {
|
|
303
|
+
const nonEditableBlockContentStartPos =
|
|
304
|
+
prevBlockInfo.blockContent.afterPos -
|
|
305
|
+
prevBlockInfo.blockContent.node.nodeSize;
|
|
306
|
+
|
|
307
|
+
chainedCommands = chainedCommands.setNodeSelection(
|
|
308
|
+
nonEditableBlockContentStartPos
|
|
309
|
+
);
|
|
310
|
+
} else {
|
|
311
|
+
const blockContentStartPos =
|
|
312
|
+
prevBlockInfo.blockContent.afterPos -
|
|
313
|
+
prevBlockInfo.blockContent.node.nodeSize;
|
|
314
|
+
|
|
315
|
+
chainedCommands =
|
|
316
|
+
chainedCommands.setTextSelection(blockContentStartPos);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return chainedCommands
|
|
320
|
+
.deleteRange({
|
|
321
|
+
from: blockInfo.bnBlock.beforePos,
|
|
322
|
+
to: blockInfo.bnBlock.afterPos,
|
|
323
|
+
})
|
|
324
|
+
.scrollIntoView()
|
|
325
|
+
.run();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return false;
|
|
329
|
+
}),
|
|
263
330
|
// Deletes previous block if it contains no content and isn't a table,
|
|
264
331
|
// when the selection is empty and at the start of the block. Moves the
|
|
265
332
|
// current block into the deleted block's place.
|
|
@@ -370,8 +437,8 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
370
437
|
}),
|
|
371
438
|
]);
|
|
372
439
|
|
|
373
|
-
const handleEnter = () =>
|
|
374
|
-
this.editor.commands.first(({ commands }) => [
|
|
440
|
+
const handleEnter = (withShift = false) => {
|
|
441
|
+
return this.editor.commands.first(({ commands }) => [
|
|
375
442
|
// Removes a level of nesting if the block is empty & indented, while the selection is also empty & at the start
|
|
376
443
|
// of the block.
|
|
377
444
|
() =>
|
|
@@ -400,6 +467,34 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
400
467
|
return commands.liftListItem("blockContainer");
|
|
401
468
|
}
|
|
402
469
|
|
|
470
|
+
return false;
|
|
471
|
+
}),
|
|
472
|
+
// Creates a hard break if block is configured to do so.
|
|
473
|
+
() =>
|
|
474
|
+
commands.command(({ state }) => {
|
|
475
|
+
const blockInfo = getBlockInfoFromSelection(state);
|
|
476
|
+
|
|
477
|
+
const blockHardBreakShortcut: "shift+enter" | "enter" | "none" =
|
|
478
|
+
this.options.editor.schema.blockSchema[blockInfo.blockNoteType]
|
|
479
|
+
.hardBreakShortcut ?? "shift+enter";
|
|
480
|
+
|
|
481
|
+
if (blockHardBreakShortcut === "none") {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (
|
|
486
|
+
// If shortcut is not configured, or is configured as "shift+enter",
|
|
487
|
+
// create a hard break for shift+enter, but not for enter.
|
|
488
|
+
(blockHardBreakShortcut === "shift+enter" && withShift) ||
|
|
489
|
+
// If shortcut is configured as "enter", create a hard break for
|
|
490
|
+
// both enter and shift+enter.
|
|
491
|
+
blockHardBreakShortcut === "enter"
|
|
492
|
+
) {
|
|
493
|
+
return commands.insertContent({
|
|
494
|
+
type: "hardBreak",
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
403
498
|
return false;
|
|
404
499
|
}),
|
|
405
500
|
// Creates a new block and moves the selection to it if the current one is empty, while the selection is also
|
|
@@ -471,11 +566,13 @@ export const KeyboardShortcutsExtension = Extension.create<{
|
|
|
471
566
|
return false;
|
|
472
567
|
}),
|
|
473
568
|
]);
|
|
569
|
+
};
|
|
474
570
|
|
|
475
571
|
return {
|
|
476
572
|
Backspace: handleBackspace,
|
|
477
573
|
Delete: handleDelete,
|
|
478
|
-
Enter: handleEnter,
|
|
574
|
+
Enter: () => handleEnter(),
|
|
575
|
+
"Shift-Enter": () => handleEnter(true),
|
|
479
576
|
// Always returning true for tab key presses ensures they're not captured by the browser. Otherwise, they blur the
|
|
480
577
|
// editor since the browser will try to use tab for keyboard navigation.
|
|
481
578
|
Tab: () => {
|
|
@@ -86,7 +86,9 @@ class SuggestionMenuView<
|
|
|
86
86
|
this.pluginState = stopped ? prev : next;
|
|
87
87
|
|
|
88
88
|
if (stopped || !this.editor.isEditable) {
|
|
89
|
-
this.state
|
|
89
|
+
if (this.state) {
|
|
90
|
+
this.state.show = false;
|
|
91
|
+
}
|
|
90
92
|
this.emitUpdate(this.pluginState!.triggerCharacter);
|
|
91
93
|
|
|
92
94
|
return;
|
|
@@ -125,6 +125,18 @@ export function getDefaultSlashMenuItems<
|
|
|
125
125
|
);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
if (checkDefaultBlockTypeInSchema("quote", editor)) {
|
|
129
|
+
items.push({
|
|
130
|
+
onItemClick: () => {
|
|
131
|
+
insertOrUpdateBlock(editor, {
|
|
132
|
+
type: "quote",
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
key: "quote",
|
|
136
|
+
...editor.dictionary.slash_menu.quote,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
128
140
|
if (checkDefaultBlockTypeInSchema("numberedListItem", editor)) {
|
|
129
141
|
items.push({
|
|
130
142
|
onItemClick: () => {
|
package/src/i18n/locales/ar.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const ar: Dictionary = {
|
|
|
20
20
|
aliases: ["ع3", "عنوان3", "عنوان فرعي"],
|
|
21
21
|
group: "العناوين",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "اقتباس",
|
|
25
|
+
subtext: "اقتباس أو مقتطف",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "الكتل الأساسية",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "قائمة مرقمة",
|
|
25
31
|
subtext: "تستخدم لعرض قائمة مرقمة",
|
package/src/i18n/locales/de.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const de: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "überschrift3", "unterüberschrift"],
|
|
21
21
|
group: "Überschriften",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "Zitat",
|
|
25
|
+
subtext: "Zitat oder Auszug",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "Grundlegende blöcke",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "Nummerierte Liste",
|
|
25
31
|
subtext: "Liste mit nummerierten Elementen",
|
package/src/i18n/locales/en.ts
CHANGED
|
@@ -18,6 +18,12 @@ export const en = {
|
|
|
18
18
|
aliases: ["h3", "heading3", "subheading"],
|
|
19
19
|
group: "Headings",
|
|
20
20
|
},
|
|
21
|
+
quote: {
|
|
22
|
+
title: "Quote",
|
|
23
|
+
subtext: "Quote or excerpt",
|
|
24
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
25
|
+
group: "Basic blocks",
|
|
26
|
+
},
|
|
21
27
|
numbered_list: {
|
|
22
28
|
title: "Numbered List",
|
|
23
29
|
subtext: "List with ordered items",
|
package/src/i18n/locales/es.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const es: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "encabezado3", "subencabezado"],
|
|
21
21
|
group: "Encabezados",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "Cita",
|
|
25
|
+
subtext: "Cita o extracto",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "Bloques básicos",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "Lista Numerada",
|
|
25
31
|
subtext: "Lista con elementos ordenados",
|
package/src/i18n/locales/fr.ts
CHANGED
|
@@ -21,6 +21,12 @@ export const fr: Dictionary = {
|
|
|
21
21
|
aliases: ["h3", "titre3", "sous-titre"],
|
|
22
22
|
group: "Titres",
|
|
23
23
|
},
|
|
24
|
+
quote: {
|
|
25
|
+
title: "Citation",
|
|
26
|
+
subtext: "Citation ou extrait",
|
|
27
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
28
|
+
group: "Blocs de base",
|
|
29
|
+
},
|
|
24
30
|
numbered_list: {
|
|
25
31
|
title: "Liste Numérotée",
|
|
26
32
|
subtext: "Utilisé pour afficher une liste numérotée",
|
package/src/i18n/locales/hr.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const hr: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "naslov3", "podnaslov"],
|
|
21
21
|
group: "Naslovi",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "Citat",
|
|
25
|
+
subtext: "Citat ili izvadak",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "Osnovni blokovi",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "Numerirani popis",
|
|
25
31
|
subtext: "Popis s numeriranim stavkama",
|
package/src/i18n/locales/is.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const is: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "fyrirsogn3", "undirfyrirsogn"],
|
|
21
21
|
group: "Fyrirsagnir",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "Tilvitnun",
|
|
25
|
+
subtext: "Tilvitnun eða útdráttur",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "Grunnblokkar",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "Númeruð listi",
|
|
25
31
|
subtext: "Notað til að birta númeraðan lista",
|
package/src/i18n/locales/it.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const it: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "intestazione3", "sottotitolo"],
|
|
21
21
|
group: "Intestazioni",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "Citazione",
|
|
25
|
+
subtext: "Citazione o estratto",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "Blocchi Base",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "Elenco Numerato",
|
|
25
31
|
subtext: "Elenco con elementi ordinati",
|
package/src/i18n/locales/ja.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const ja: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "見出し3", "subheading", "小見出し"],
|
|
21
21
|
group: "見出し",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "引用",
|
|
25
|
+
subtext: "引用または抜粋",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "基本ブロック",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "番号付リスト",
|
|
25
31
|
subtext: "番号付リストを表示するために使用",
|
package/src/i18n/locales/ko.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const ko: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "제목3", "subheading"],
|
|
21
21
|
group: "제목",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "인용",
|
|
25
|
+
subtext: "인용문 또는 발췌",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "기본 블록",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "번호 매기기 목록",
|
|
25
31
|
subtext: "번호가 매겨진 목록을 추가합니다.",
|
package/src/i18n/locales/nl.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const nl: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "kop3", "subkop"],
|
|
21
21
|
group: "Koppen",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "Citaat",
|
|
25
|
+
subtext: "Citaat of uittreksel",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "Basisblokken",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "Genummerde Lijst",
|
|
25
31
|
subtext: "Gebruikt om een genummerde lijst weer te geven",
|
package/src/i18n/locales/no.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const no: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "overskrift3", "underoverskrift"],
|
|
21
21
|
group: "Overskrifter",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "Sitat",
|
|
25
|
+
subtext: "Sitat eller utdrag",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "Grunnleggende blokker",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "Nummerert liste",
|
|
25
31
|
subtext: "Liste med ordnede elementer",
|
package/src/i18n/locales/pl.ts
CHANGED
|
@@ -20,6 +20,12 @@ export const pl: Dictionary = {
|
|
|
20
20
|
aliases: ["h3", "naglowek3", "podnaglowek"],
|
|
21
21
|
group: "Nagłówki",
|
|
22
22
|
},
|
|
23
|
+
quote: {
|
|
24
|
+
title: "Cytat",
|
|
25
|
+
subtext: "Cytat lub fragment",
|
|
26
|
+
aliases: ["quotation", "blockquote", "bq"],
|
|
27
|
+
group: "Podstawowe bloki",
|
|
28
|
+
},
|
|
23
29
|
numbered_list: {
|
|
24
30
|
title: "Lista numerowana",
|
|
25
31
|
subtext: "Używana do wyświetlania listy numerowanej",
|