@blocknote/core 0.8.2 → 0.8.3
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/README.md +4 -0
- package/dist/blocknote.js +1777 -1849
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +4 -4
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/BlockNoteEditor.ts +89 -39
- package/src/BlockNoteExtensions.ts +1 -58
- package/src/api/formatConversions/__snapshots__/formatConversions.test.ts.snap +10 -10
- package/src/api/formatConversions/formatConversions.test.ts +587 -605
- package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +15 -15
- package/src/api/nodeConversions/nodeConversions.test.ts +90 -94
- package/src/extensions/Blocks/api/blockTypes.ts +3 -2
- package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +6 -0
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +101 -114
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +184 -149
- package/src/extensions/Placeholder/PlaceholderExtension.ts +2 -2
- package/src/extensions/{DraggableBlocks/DraggableBlocksPlugin.ts → SideMenu/SideMenuPlugin.ts} +181 -164
- package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +7 -30
- package/src/extensions/SlashMenu/SlashMenuPlugin.ts +51 -0
- package/src/extensions/SlashMenu/defaultSlashMenuItems.ts +109 -0
- package/src/extensions/UniqueID/UniqueID.ts +29 -30
- package/src/index.ts +9 -8
- package/src/node_modules/.vitest/results.json +1 -0
- package/src/shared/BaseUiElementTypes.ts +8 -0
- package/src/shared/EditorElement.ts +0 -16
- package/src/shared/EventEmitter.ts +58 -0
- package/src/shared/plugins/suggestion/SuggestionItem.ts +3 -6
- package/src/shared/plugins/suggestion/SuggestionPlugin.ts +341 -403
- package/types/src/BlockNoteEditor.d.ts +18 -11
- package/types/src/BlockNoteExtensions.d.ts +0 -19
- package/types/src/EventEmitter.d.ts +11 -0
- package/types/src/extensions/Blocks/api/blockTypes.d.ts +3 -2
- package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +0 -17
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +26 -20
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +18 -24
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +0 -12
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +37 -10
- package/types/src/extensions/SideMenu/MultipleNodeSelection.d.ts +24 -0
- package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +79 -0
- package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +5 -18
- package/types/src/extensions/SlashMenu/SlashMenuPlugin.d.ts +13 -0
- package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +1 -69
- package/types/src/extensions/SlashMenu/index.d.ts +2 -3
- package/types/src/index.d.ts +9 -8
- package/types/src/shared/BaseUiElementTypes.d.ts +7 -0
- package/types/src/shared/EditorElement.d.ts +0 -10
- package/types/src/shared/EventEmitter.d.ts +11 -0
- package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +2 -7
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +12 -43
- package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +0 -29
- package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +0 -37
- package/src/extensions/FormattingToolbar/FormattingToolbarExtension.ts +0 -37
- package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +0 -18
- package/src/extensions/HyperlinkToolbar/HyperlinkMark.ts +0 -28
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.ts +0 -19
- package/src/extensions/SlashMenu/SlashMenuExtension.ts +0 -53
- package/src/extensions/SlashMenu/defaultSlashMenuItems.tsx +0 -195
- package/src/extensions/SlashMenu/index.ts +0 -5
- package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +0 -21
- package/types/src/CustomBlock.d.ts +0 -15
- package/types/src/extensions/Blocks/nodes/BlockContent/TableContent/TableCol.d.ts +0 -2
- package/types/src/extensions/Blocks/nodes/BlockContent/TableContent/TableContent.d.ts +0 -2
- package/types/src/extensions/Blocks/nodes/BlockContent/TableContent/TableRow.d.ts +0 -2
- package/types/src/extensions/Placeholder/localisation/index.d.ts +0 -2
- package/types/src/extensions/Placeholder/localisation/translation.d.ts +0 -51
- /package/src/extensions/{DraggableBlocks → SideMenu}/MultipleNodeSelection.ts +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { BlockNoteEditor } from "../../BlockNoteEditor";
|
|
2
|
+
import { BlockSchema, PartialBlock } from "../Blocks/api/blockTypes";
|
|
3
|
+
import { BaseSlashMenuItem } from "./BaseSlashMenuItem";
|
|
4
|
+
import { defaultBlockSchema } from "../Blocks/api/defaultBlocks";
|
|
5
|
+
|
|
6
|
+
function insertOrUpdateBlock<BSchema extends BlockSchema>(
|
|
7
|
+
editor: BlockNoteEditor<BSchema>,
|
|
8
|
+
block: PartialBlock<BSchema>
|
|
9
|
+
) {
|
|
10
|
+
const currentBlock = editor.getTextCursorPosition().block;
|
|
11
|
+
|
|
12
|
+
if (
|
|
13
|
+
(currentBlock.content.length === 1 &&
|
|
14
|
+
currentBlock.content[0].type === "text" &&
|
|
15
|
+
currentBlock.content[0].text === "/") ||
|
|
16
|
+
currentBlock.content.length === 0
|
|
17
|
+
) {
|
|
18
|
+
editor.updateBlock(currentBlock, block);
|
|
19
|
+
} else {
|
|
20
|
+
editor.insertBlocks([block], currentBlock, "after");
|
|
21
|
+
editor.setTextCursorPosition(editor.getTextCursorPosition().nextBlock!);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const getDefaultSlashMenuItems = <BSchema extends BlockSchema>(
|
|
26
|
+
// This type casting is weird, but it's the best way of doing it, as it allows
|
|
27
|
+
// the schema type to be automatically inferred if it is defined, or be
|
|
28
|
+
// inferred as any if it is not defined. I don't think it's possible to make it
|
|
29
|
+
// infer to DefaultBlockSchema if it is not defined.
|
|
30
|
+
schema: BSchema = defaultBlockSchema as unknown as BSchema
|
|
31
|
+
) => {
|
|
32
|
+
const slashMenuItems: BaseSlashMenuItem<BSchema>[] = [];
|
|
33
|
+
|
|
34
|
+
if ("heading" in schema && "level" in schema.heading.propSchema) {
|
|
35
|
+
// Command for creating a level 1 heading
|
|
36
|
+
if (schema.heading.propSchema.level.values?.includes("1")) {
|
|
37
|
+
slashMenuItems.push({
|
|
38
|
+
name: "Heading",
|
|
39
|
+
aliases: ["h", "heading1", "h1"],
|
|
40
|
+
execute: (editor) =>
|
|
41
|
+
insertOrUpdateBlock(editor, {
|
|
42
|
+
type: "heading",
|
|
43
|
+
props: { level: "1" },
|
|
44
|
+
} as PartialBlock<BSchema>),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Command for creating a level 2 heading
|
|
49
|
+
if (schema.heading.propSchema.level.values?.includes("2")) {
|
|
50
|
+
slashMenuItems.push({
|
|
51
|
+
name: "Heading 2",
|
|
52
|
+
aliases: ["h2", "heading2", "subheading"],
|
|
53
|
+
execute: (editor) =>
|
|
54
|
+
insertOrUpdateBlock(editor, {
|
|
55
|
+
type: "heading",
|
|
56
|
+
props: { level: "2" },
|
|
57
|
+
} as PartialBlock<BSchema>),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Command for creating a level 3 heading
|
|
62
|
+
if (schema.heading.propSchema.level.values?.includes("3")) {
|
|
63
|
+
slashMenuItems.push({
|
|
64
|
+
name: "Heading 3",
|
|
65
|
+
aliases: ["h3", "heading3", "subheading"],
|
|
66
|
+
execute: (editor) =>
|
|
67
|
+
insertOrUpdateBlock(editor, {
|
|
68
|
+
type: "heading",
|
|
69
|
+
props: { level: "3" },
|
|
70
|
+
} as PartialBlock<BSchema>),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if ("bulletListItem" in schema) {
|
|
76
|
+
slashMenuItems.push({
|
|
77
|
+
name: "Bullet List",
|
|
78
|
+
aliases: ["ul", "list", "bulletlist", "bullet list"],
|
|
79
|
+
execute: (editor) =>
|
|
80
|
+
insertOrUpdateBlock(editor, {
|
|
81
|
+
type: "bulletListItem",
|
|
82
|
+
} as PartialBlock<BSchema>),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if ("numberedListItem" in schema) {
|
|
87
|
+
slashMenuItems.push({
|
|
88
|
+
name: "Numbered List",
|
|
89
|
+
aliases: ["li", "list", "numberedlist", "numbered list"],
|
|
90
|
+
execute: (editor) =>
|
|
91
|
+
insertOrUpdateBlock(editor, {
|
|
92
|
+
type: "numberedListItem",
|
|
93
|
+
} as PartialBlock<BSchema>),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if ("paragraph" in schema) {
|
|
98
|
+
slashMenuItems.push({
|
|
99
|
+
name: "Paragraph",
|
|
100
|
+
aliases: ["p"],
|
|
101
|
+
execute: (editor) =>
|
|
102
|
+
insertOrUpdateBlock(editor, {
|
|
103
|
+
type: "paragraph",
|
|
104
|
+
} as PartialBlock<BSchema>),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return slashMenuItems;
|
|
109
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
combineTransactionSteps,
|
|
3
3
|
Extension,
|
|
4
|
-
findChildren,
|
|
5
4
|
findChildrenInRange,
|
|
6
5
|
getChangedRanges,
|
|
7
6
|
} from "@tiptap/core";
|
|
@@ -87,35 +86,35 @@ const UniqueID = Extension.create({
|
|
|
87
86
|
];
|
|
88
87
|
},
|
|
89
88
|
// check initial content for missing ids
|
|
90
|
-
onCreate() {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
},
|
|
89
|
+
// onCreate() {
|
|
90
|
+
// // Don’t do this when the collaboration extension is active
|
|
91
|
+
// // because this may update the content, so Y.js tries to merge these changes.
|
|
92
|
+
// // This leads to empty block nodes.
|
|
93
|
+
// // See: https://github.com/ueberdosis/tiptap/issues/2400
|
|
94
|
+
// if (
|
|
95
|
+
// this.editor.extensionManager.extensions.find(
|
|
96
|
+
// (extension) => extension.name === "collaboration"
|
|
97
|
+
// )
|
|
98
|
+
// ) {
|
|
99
|
+
// return;
|
|
100
|
+
// }
|
|
101
|
+
// const { view, state } = this.editor;
|
|
102
|
+
// const { tr, doc } = state;
|
|
103
|
+
// const { types, attributeName, generateID } = this.options;
|
|
104
|
+
// const nodesWithoutId = findChildren(doc, (node) => {
|
|
105
|
+
// return (
|
|
106
|
+
// types.includes(node.type.name) && node.attrs[attributeName] === null
|
|
107
|
+
// );
|
|
108
|
+
// });
|
|
109
|
+
// nodesWithoutId.forEach(({ node, pos }) => {
|
|
110
|
+
// tr.setNodeMarkup(pos, undefined, {
|
|
111
|
+
// ...node.attrs,
|
|
112
|
+
// [attributeName]: generateID(),
|
|
113
|
+
// });
|
|
114
|
+
// });
|
|
115
|
+
// tr.setMeta("addToHistory", false);
|
|
116
|
+
// view.dispatch(tr);
|
|
117
|
+
// },
|
|
119
118
|
addProseMirrorPlugins() {
|
|
120
119
|
let dragSourceElement: any = null;
|
|
121
120
|
let transformPasted = false;
|
package/src/index.ts
CHANGED
|
@@ -3,14 +3,15 @@ export * from "./BlockNoteExtensions";
|
|
|
3
3
|
export * from "./extensions/Blocks/api/block";
|
|
4
4
|
export * from "./extensions/Blocks/api/blockTypes";
|
|
5
5
|
export * from "./extensions/Blocks/api/defaultBlocks";
|
|
6
|
-
export * from "./extensions/DraggableBlocks/BlockSideMenuFactoryTypes";
|
|
7
|
-
export * from "./extensions/FormattingToolbar/FormattingToolbarFactoryTypes";
|
|
8
|
-
export * from "./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes";
|
|
9
|
-
export { defaultSlashMenuItems } from "./extensions/SlashMenu/defaultSlashMenuItems";
|
|
10
|
-
export * from "./extensions/SlashMenu/BaseSlashMenuItem";
|
|
11
|
-
export * from "./shared/EditorElement";
|
|
12
|
-
export type { SuggestionItem } from "./shared/plugins/suggestion/SuggestionItem";
|
|
13
|
-
export * from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
|
|
14
6
|
export * from "./extensions/Blocks/api/inlineContentTypes";
|
|
15
7
|
export * from "./extensions/Blocks/api/serialization";
|
|
16
8
|
export * as blockStyles from "./extensions/Blocks/nodes/Block.module.css";
|
|
9
|
+
export * from "./extensions/FormattingToolbar/FormattingToolbarPlugin";
|
|
10
|
+
export * from "./extensions/HyperlinkToolbar/HyperlinkToolbarPlugin";
|
|
11
|
+
export * from "./extensions/SideMenu/SideMenuPlugin";
|
|
12
|
+
export * from "./extensions/SlashMenu/BaseSlashMenuItem";
|
|
13
|
+
export * from "./extensions/SlashMenu/SlashMenuPlugin";
|
|
14
|
+
export { getDefaultSlashMenuItems } from "./extensions/SlashMenu/defaultSlashMenuItems";
|
|
15
|
+
export * from "./shared/BaseUiElementTypes";
|
|
16
|
+
export type { SuggestionItem } from "./shared/plugins/suggestion/SuggestionItem";
|
|
17
|
+
export * from "./shared/plugins/suggestion/SuggestionPlugin";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":"0.28.5","results":[["/api/formatConversions/formatConversions.test.ts",{"duration":109,"failed":false}],["/api/nodeConversions/nodeConversions.test.ts",{"duration":32,"failed":false}],["/api/blockManipulation/blockManipulation.test.ts",{"duration":38,"failed":false}],["/BlockNoteEditor.test.ts",{"duration":4,"failed":false}]]}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export type RequiredStaticParams = Record<string, any> & {
|
|
2
|
-
getReferenceRect: () => DOMRect;
|
|
3
|
-
};
|
|
4
|
-
export type RequiredDynamicParams = Record<string, any> & {};
|
|
5
|
-
|
|
6
|
-
export type EditorElement<ElementDynamicParams extends RequiredDynamicParams> =
|
|
7
|
-
{
|
|
8
|
-
element: HTMLElement | undefined;
|
|
9
|
-
render: (params: ElementDynamicParams, isHidden: boolean) => void;
|
|
10
|
-
hide: () => void;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export type ElementFactory<
|
|
14
|
-
ElementStaticParams extends RequiredStaticParams,
|
|
15
|
-
ElementDynamicParams extends RequiredDynamicParams
|
|
16
|
-
> = (staticParams: ElementStaticParams) => EditorElement<ElementDynamicParams>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// from https://raw.githubusercontent.com/ueberdosis/tiptap/develop/packages/core/src/EventEmitter.ts (MIT)
|
|
2
|
+
|
|
3
|
+
type StringKeyOf<T> = Extract<keyof T, string>;
|
|
4
|
+
type CallbackType<
|
|
5
|
+
T extends Record<string, any>,
|
|
6
|
+
EventName extends StringKeyOf<T>
|
|
7
|
+
> = T[EventName] extends any[] ? T[EventName] : [T[EventName]];
|
|
8
|
+
type CallbackFunction<
|
|
9
|
+
T extends Record<string, any>,
|
|
10
|
+
EventName extends StringKeyOf<T>
|
|
11
|
+
> = (...props: CallbackType<T, EventName>) => any;
|
|
12
|
+
|
|
13
|
+
export class EventEmitter<T extends Record<string, any>> {
|
|
14
|
+
private callbacks: { [key: string]: Function[] } = {};
|
|
15
|
+
|
|
16
|
+
public on<EventName extends StringKeyOf<T>>(
|
|
17
|
+
event: EventName,
|
|
18
|
+
fn: CallbackFunction<T, EventName>
|
|
19
|
+
) {
|
|
20
|
+
if (!this.callbacks[event]) {
|
|
21
|
+
this.callbacks[event] = [];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
this.callbacks[event].push(fn);
|
|
25
|
+
|
|
26
|
+
return () => this.off(event, fn);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
protected emit<EventName extends StringKeyOf<T>>(
|
|
30
|
+
event: EventName,
|
|
31
|
+
...args: CallbackType<T, EventName>
|
|
32
|
+
) {
|
|
33
|
+
const callbacks = this.callbacks[event];
|
|
34
|
+
|
|
35
|
+
if (callbacks) {
|
|
36
|
+
callbacks.forEach((callback) => callback.apply(this, args));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public off<EventName extends StringKeyOf<T>>(
|
|
41
|
+
event: EventName,
|
|
42
|
+
fn?: CallbackFunction<T, EventName>
|
|
43
|
+
) {
|
|
44
|
+
const callbacks = this.callbacks[event];
|
|
45
|
+
|
|
46
|
+
if (callbacks) {
|
|
47
|
+
if (fn) {
|
|
48
|
+
this.callbacks[event] = callbacks.filter((callback) => callback !== fn);
|
|
49
|
+
} else {
|
|
50
|
+
delete this.callbacks[event];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
protected removeAllListeners(): void {
|
|
56
|
+
this.callbacks = {};
|
|
57
|
+
}
|
|
58
|
+
}
|